diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..5bde4d8609745bf3ac27fef6dd17c1bdcd392660 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,3 +33,34 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text +mne-python/source/doc/_static/blender_import_obj/blender_import_obj1.jpg filter=lfs diff=lfs merge=lfs -text +mne-python/source/doc/_static/blender_import_obj/blender_import_obj4.jpg filter=lfs diff=lfs merge=lfs -text +mne-python/source/doc/_static/funding/nsf.png filter=lfs diff=lfs merge=lfs -text +mne-python/source/doc/_static/mne_installer_macOS.png filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/data/fsaverage/fsaverage-inner_skull-bem.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/brainvision/tests/data/test_bin_raw.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/brainvision/tests/data/test.eeg filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/bti/tests/data/exported4D_linux_raw.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/bti/tests/data/exported4D_solaris_raw.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/bti/tests/data/test_config_linux filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/bti/tests/data/test_config_solaris filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/bti/tests/data/test_hs_solaris filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/bti/tests/data/test_pdf_linux filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/bti/tests/data/test_pdf_solaris filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/edf/tests/data/test_bdf_eeglab.mat filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/edf/tests/data/test_edf_eeglab.mat filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/edf/tests/data/test_eeglab.mat filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/kit/tests/data/test_bin_raw.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/kit/tests/data/test_Ykgw.mat filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/kit/tests/data/test-epoch.raw filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/kit/tests/data/test.sqd filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test_chpi_raw_sss.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test_ctf_comp_raw.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test_ctf_raw.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test_erm-cov.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test_raw.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test_withbads_raw.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test-ave.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test-cov.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test-km-cov.fif filter=lfs diff=lfs merge=lfs -text +mne-python/source/mne/io/tests/data/test-nf-ave.fif filter=lfs diff=lfs merge=lfs -text diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..ff093f1e22fb71dfb37206e0906a24e8b1b7ae74 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM python:3.10 + +RUN useradd -m -u 1000 user && python -m pip install --upgrade pip +USER user +ENV PATH="/home/user/.local/bin:$PATH" + +WORKDIR /app + +COPY --chown=user ./requirements.txt requirements.txt +RUN pip install --no-cache-dir --upgrade -r requirements.txt + +COPY --chown=user . /app +ENV MCP_TRANSPORT=http +ENV MCP_PORT=7860 + +EXPOSE 7860 + +CMD ["python", "mne-python/mcp_output/start_mcp.py"] diff --git a/app.py b/app.py new file mode 100644 index 0000000000000000000000000000000000000000..c78e6b0ca75d3259d2be35f1da8fdc1ba0ab4bb0 --- /dev/null +++ b/app.py @@ -0,0 +1,45 @@ +from fastapi import FastAPI +import os +import sys + +mcp_plugin_path = os.path.join(os.path.dirname(__file__), "mne-python", "mcp_output", "mcp_plugin") +sys.path.insert(0, mcp_plugin_path) + +app = FastAPI( + title="Mne-Python MCP Service", + description="Auto-generated MCP service for mne-python", + version="1.0.0" +) + +@app.get("/") +def root(): + return { + "service": "Mne-Python MCP Service", + "version": "1.0.0", + "status": "running", + "transport": os.environ.get("MCP_TRANSPORT", "http") + } + +@app.get("/health") +def health_check(): + return {"status": "healthy", "service": "mne-python MCP"} + +@app.get("/tools") +def list_tools(): + try: + from mcp_service import create_app + mcp_app = create_app() + tools = [] + for tool_name, tool_func in mcp_app.tools.items(): + tools.append({ + "name": tool_name, + "description": tool_func.__doc__ or "No description available" + }) + return {"tools": tools} + except Exception as e: + return {"error": f"Failed to load tools: {str(e)}"} + +if __name__ == "__main__": + import uvicorn + port = int(os.environ.get("PORT", 7860)) + uvicorn.run(app, host="0.0.0.0", port=port) diff --git a/mne-python/.DS_Store b/mne-python/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..2badcffef759730c9d999689be91ad196b50bd32 Binary files /dev/null and b/mne-python/.DS_Store differ diff --git a/mne-python/mcp_output/.DS_Store b/mne-python/mcp_output/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..70c6fe88b00a3fe4e579709c2bd7a6c036805b11 Binary files /dev/null and b/mne-python/mcp_output/.DS_Store differ diff --git a/mne-python/mcp_output/README_MCP.md b/mne-python/mcp_output/README_MCP.md new file mode 100644 index 0000000000000000000000000000000000000000..73cc0a715d69d3957c3ec31041266421853df4a1 --- /dev/null +++ b/mne-python/mcp_output/README_MCP.md @@ -0,0 +1,129 @@ +# MNE-Python MCP (Model Context Protocol) Service README + +## 1) Project Introduction + +This service wraps core **MNE-Python** capabilities for EEG/MEG workflows in an MCP (Model Context Protocol)-friendly interface. + +Primary goals: +- Load raw neurophysiology data (FIF, EDF, BDF, BrainVision). +- Perform event handling and channel picking. +- Run common preprocessing (EOG/ECG detection, ICA-related preparation). +- Compute PSD and time-frequency features. +- Optionally render diagnostic visualizations (when GUI/backends are available). + +Recommended integration path: +- **Primary:** in-process Python imports from `mne` modules. +- **Fallback:** call the `mne` CLI for heavier or isolated execution contexts. + +--- + +## 2) Installation Method + +### Requirements +Core dependencies: +- `numpy` +- `scipy` +- `matplotlib` +- `packaging` +- `pooch` +- `tqdm` + +Common optional dependencies (feature-dependent): +- `scikit-learn`, `pandas`, `h5py`, `nibabel` +- `pyvista`, `vtk`, `mne-qt-browser` +- `numba` + +### Install +- Install MNE-Python and common scientific stack via pip: + - `pip install mne` +- For broader functionality: + - `pip install mne[full]` (if supported by your environment/version) +- If your service uses project-local dependency files, prefer: + - `pyproject.toml` / `environment.yml` in your deployment workflow. + +--- + +## 3) Quick Start + +### Minimal service flow (Python-side) +1. Read raw data: + - `mne.io.read_raw_fif(...)` / `read_raw_edf(...)` / `read_raw_bdf(...)` / `read_raw_brainvision(...)` +2. Extract events: + - `mne.find_events(raw)` or `mne.read_events(path)` +3. Pick channels: + - `mne.pick_types(raw.info, meg=True, eeg=True, eog=True, exclude="bads")` +4. Preprocess (optional): + - `mne.preprocessing.find_eog_events(raw)`, `find_ecg_events(raw)`, ICA workflows +5. Spectral analysis: + - `mne.time_frequency.psd_array_welch(...)` or `psd_array_multitaper(...)` +6. Return structured results from your MCP (Model Context Protocol) service endpoint. + +### CLI fallback +- Use `mne` command wrapper when import-time overhead or environment isolation is needed. + +--- + +## 4) Available Tools and Endpoints List + +Suggested MCP (Model Context Protocol) service endpoints: + +- `load_raw` + - Load raw recordings from FIF/EDF/BDF/BrainVision. + - Maps to `mne.io.read_raw_*`. + +- `read_info` + - Read metadata/header info without full processing. + - Maps to `mne.io.read_info`. + +- `events_detect` + - Detect or load event markers. + - Maps to `mne.find_events`, `mne.read_events`, `mne.merge_events`. + +- `channels_pick` + - Build channel selections by modality/type. + - Maps to `mne.pick_types`. + +- `preprocess_eog_ecg` + - EOG/ECG event detection and projection helpers. + - Maps to `mne.preprocessing.find_eog_events`, `find_ecg_events`, `compute_proj_eog`, `compute_proj_ecg`. + +- `ica_workflow` + - Artifact decomposition/removal pipeline. + - Maps to `mne.preprocessing.ICA`, `EOGRegression`. + +- `psd_compute` + - Power spectral density calculations. + - Maps to `mne.time_frequency.psd_array_welch`, `psd_array_multitaper`. + +- `tfr_compute` + - Time-frequency decomposition. + - Maps to `tfr_morlet`, `tfr_multitaper`, `csd_multitaper`. + +- `viz_diagnostics` (optional/headless-sensitive) + - Event/covariance/alignment diagnostic plotting. + - Maps to `mne.viz.plot_events`, `plot_cov`, `plot_bem`, `plot_alignment`. + +- `cli_exec` (fallback) + - Run `mne` subcommands for isolated or heavyweight tasks. + +--- + +## 5) Common Issues and Notes + +- **Complexity:** MNE-Python is feature-rich; keep endpoint contracts narrow and typed. +- **Import overhead:** First import can be non-trivial; consider lazy-loading per endpoint. +- **GUI dependencies:** Visualization endpoints may fail in headless servers unless backend is configured. +- **Optional packages:** Some analyses silently require extras (`sklearn`, `h5py`, `nibabel`, etc.). +- **Performance:** Large FIF files and TFR/ICA jobs are memory/CPU intensive; set resource limits. +- **Reproducibility:** Pin MNE + NumPy/SciPy versions in deployment. +- **Risk profile:** Import feasibility is moderate (~0.72); keep CLI fallback available. +- **Data handling:** Validate paths, file formats, and channel metadata before heavy processing. + +--- + +## 6) Reference Links / Documentation + +- MNE-Python repository: https://github.com/mne-tools/mne-python +- MNE official docs: https://mne.tools/stable/index.html +- MNE API reference: https://mne.tools/stable/python_reference.html +- MNE command-line tools: https://mne.tools/stable/overview/command_line.html \ No newline at end of file diff --git a/mne-python/mcp_output/analysis.json b/mne-python/mcp_output/analysis.json new file mode 100644 index 0000000000000000000000000000000000000000..811a0e9a94e2ddbb1d7928900e1812b8c8a27fa7 --- /dev/null +++ b/mne-python/mcp_output/analysis.json @@ -0,0 +1,199 @@ +{ + "summary": { + "repository_url": "https://github.com/mne-tools/mne-python", + "summary": "Unable to preprocess repository: https://github.com/mne-tools/mne-python", + "file_tree": {}, + "content": {}, + "processed_by": "fallback", + "success": false, + "error": "zip download failed: IncompleteRead(4160073 bytes read)" + }, + "structure": { + "packages": [ + "deployment.mne-python.source", + "mcp_output.mcp_plugin", + "source.mne", + "source.mne._fiff", + "source.mne.beamformer", + "source.mne.channels", + "source.mne.commands", + "source.mne.data", + "source.mne.datasets", + "source.mne.decoding", + "source.mne.export", + "source.mne.forward", + "source.mne.gui", + "source.mne.html_templates", + "source.mne.inverse_sparse", + "source.mne.io", + "source.mne.minimum_norm", + "source.mne.preprocessing", + "source.mne.report", + "source.mne.simulation", + "source.mne.source_space", + "source.mne.stats", + "source.mne.tests", + "source.mne.time_frequency", + "source.mne.utils", + "source.mne.viz" + ] + }, + "dependencies": { + "has_environment_yml": true, + "has_requirements_txt": false, + "pyproject": true, + "setup_cfg": false, + "setup_py": false + }, + "entry_points": { + "imports": [], + "cli": [], + "modules": [] + }, + "llm_analysis": { + "core_modules": [ + { + "package": "source.mne", + "module": "source.mne", + "functions": [ + "create_info", + "set_log_level", + "read_events", + "pick_types", + "find_events", + "merge_events", + "concatenate_raws" + ], + "classes": [ + "Info", + "Covariance", + "Epochs", + "Evoked", + "Annotations" + ], + "description": "Top-level API surface for core EEG/MEG data structures and common preprocessing/event utilities; safest primary integration point for MCP tooling." + }, + { + "package": "source.mne.io", + "module": "source.mne.io", + "functions": [ + "read_raw_fif", + "read_raw_edf", + "read_raw_bdf", + "read_raw_brainvision", + "read_info" + ], + "classes": [ + "Raw", + "RawArray" + ], + "description": "Input/output layer for loading raw recordings from major formats and constructing in-memory raw objects." + }, + { + "package": "source.mne.preprocessing", + "module": "source.mne.preprocessing", + "functions": [ + "compute_proj_ecg", + "compute_proj_eog", + "find_eog_events", + "find_ecg_events", + "create_eog_epochs" + ], + "classes": [ + "ICA", + "EOGRegression" + ], + "description": "Artifact detection/removal workflows (ICA/projections/regression), useful for preprocessing-oriented MCP commands." + }, + { + "package": "source.mne.time_frequency", + "module": "source.mne.time_frequency", + "functions": [ + "psd_array_welch", + "psd_array_multitaper", + "tfr_morlet", + "tfr_multitaper", + "csd_multitaper" + ], + "classes": [ + "AverageTFR", + "EpochsTFR" + ], + "description": "Frequency-domain and time-frequency analysis APIs commonly needed for downstream analytics plugins." + }, + { + "package": "source.mne.viz", + "module": "source.mne.viz", + "functions": [ + "plot_events", + "plot_cov", + "plot_bem", + "plot_alignment" + ], + "classes": [], + "description": "Visualization endpoints; useful but generally optional in headless MCP execution." + }, + { + "package": "source.mne.commands", + "module": "source.mne.commands", + "functions": [], + "classes": [], + "description": "CLI command package; preferred fallback execution boundary when direct in-process imports are too heavy." + } + ], + "cli_commands": [ + { + "name": "mne", + "module": "source.mne.commands", + "description": "Primary MNE command-line entry wrapper (subcommand-based tooling for data handling, preprocessing, and project utilities)." + } + ], + "import_strategy": { + "primary": "import", + "fallback": "cli", + "confidence": 0.7 + }, + "dependencies": { + "required": [ + "numpy", + "scipy", + "matplotlib", + "packaging", + "pooch", + "tqdm" + ], + "optional": [ + "sklearn", + "pandas", + "h5py", + "nibabel", + "pyvista", + "vtk", + "mne-qt-browser", + "numba" + ] + }, + "risk_assessment": { + "import_feasibility": 0.72, + "intrusiveness_risk": "medium", + "complexity": "complex" + } + }, + "deepwiki_analysis": { + "repo_url": "https://github.com/mne-tools/mne-python", + "repo_name": "mne-python", + "error": "DeepWiki analysis failed", + "model": "gpt-5.3-codex", + "source": "llm_direct_analysis", + "success": false + }, + "deepwiki_options": { + "enabled": true, + "model": "gpt-5.3-codex" + }, + "risk": { + "import_feasibility": 0.72, + "intrusiveness_risk": "medium", + "complexity": "complex" + } +} \ No newline at end of file diff --git a/mne-python/mcp_output/diff_report.md b/mne-python/mcp_output/diff_report.md new file mode 100644 index 0000000000000000000000000000000000000000..e7a43bafb21f597cb38a0b6deb5163a732a5fefc --- /dev/null +++ b/mne-python/mcp_output/diff_report.md @@ -0,0 +1,161 @@ +# Difference Report — **mne-python** + +**Generated:** 2026-03-14 12:25:49 +**Repository:** `mne-python` +**Project Type:** Python library +**Scope / Main Features:** Basic functionality +**Change Intrusiveness:** None +**Workflow Status:** ✅ Success +**Test Status:** ❌ Failed +**Files Changed:** 8 new, 0 modified + +--- + +## 1) Project Overview + +This update introduces **8 new files** to the `mne-python` codebase without modifying existing files. +Given the “Basic functionality” scope and “None” intrusiveness, the change appears additive and low-risk at the integration layer. However, the **failed test status** indicates unresolved quality or environment issues that block confidence in release readiness. + +--- + +## 2) Change Summary + +| Metric | Value | +|---|---:| +| New files | 8 | +| Modified files | 0 | +| Deleted files | 0 (not reported) | +| Intrusiveness | None | +| CI workflow | Success | +| Test result | Failed | + +### High-level interpretation +- **Additive-only change set** (no direct regressions from edits to existing files expected). +- **Pipeline orchestration passed**, suggesting jobs ran correctly. +- **Test execution failed**, indicating either: + - new functionality is incomplete/incorrect, + - tests are outdated or misconfigured, + - dependency/version/environment mismatch. + +--- + +## 3) Difference Analysis + +Because only aggregate metadata is provided (no file paths or patch hunks), analysis is structural: + +1. **No legacy code edits** + - Existing APIs likely unchanged directly. + - Backward compatibility risk is lower than in refactor/edit-heavy updates. + +2. **New surface area introduced** + - 8 files likely include one or more of: + - implementation modules, + - tests, + - docs/examples, + - configuration helpers. + - Any newly introduced module still affects packaging/import graph and CI. + +3. **Quality gate mismatch** + - CI workflow success + tests failed implies workflow did not enforce test pass as a hard gate, or failures occurred in a non-blocking stage. + +--- + +## 4) Technical Analysis + +## 4.1 Risk Assessment + +| Area | Risk | Rationale | +|---|---|---| +| API stability | Low–Medium | No modified files, but new public modules may expose new API surface. | +| Runtime behavior | Medium | New files can alter import side effects, plugin discovery, or optional paths. | +| Test reliability | High | Failed tests directly reduce confidence in correctness. | +| Release readiness | High risk (not ready) | Test suite failing is a release blocker for scientific Python libs. | + +## 4.2 Likely Failure Categories (to triage first) + +- **Unit test expectation mismatch** for newly added behavior. +- **Missing optional dependencies** in CI test matrix. +- **Numerical tolerance/precision drift** (common in scientific stacks). +- **Platform-specific failures** (Linux/macOS/Windows differences). +- **Import/package registration issues** (new files not wired into package init or config). +- **Style/type/linters treated as tests** if test stage aggregates tooling checks. + +## 4.3 Validation Gaps + +- No file-level diff context available. +- No failing test names/tracebacks included. +- Cannot confirm whether failures are deterministic or flaky. + +--- + +## 5) Recommendations & Improvements + +## 5.1 Immediate (Blocker Resolution) + +1. **Collect failure artifacts** + - Extract failing test IDs, stack traces, and environment metadata (Python, NumPy/SciPy, OS). +2. **Classify failures** + - New-code defects vs. test harness/config issues. +3. **Re-run targeted tests locally and in CI** + - Isolate minimal reproducer; verify determinism. +4. **Enforce hard gate** + - Ensure release/protected branch requires test success. + +## 5.2 Short-term Quality Hardening + +- Add/adjust tests for each new file’s intended behavior. +- If numeric algorithms were added, pin tolerances and seed randomness. +- Validate packaging exposure (`__init__`, entry points, module discovery). +- Run matrix smoke tests across supported Python versions. + +## 5.3 Process Improvements + +- Introduce a **change manifest** in PRs: purpose of each new file + expected impact. +- Add CI stage separation: + - lint/type/doc checks, + - unit/integration tests, + - optional slow tests. +- Track flaky tests and quarantine with explicit issue links. + +--- + +## 6) Deployment Information + +## 6.1 Current Deployment Readiness + +**Status: Not recommended for deployment** due to failed tests. + +## 6.2 Suggested Release Criteria + +Deploy only after all conditions are met: + +- ✅ All required tests pass on supported matrix. +- ✅ No critical/new warnings in CI logs. +- ✅ Documentation/changelog entries for new files. +- ✅ Versioning decision made (likely patch/minor based on new functionality exposure). + +## 6.3 Rollout Strategy (once green) + +- Use staged rollout (internal validation → broader user release). +- Monitor error reports/import issues post-release. +- Prepare rapid rollback/hotfix path. + +--- + +## 7) Future Planning + +1. **Improve observability in CI** + - Publish structured test reports and failure clustering. +2. **Strengthen compatibility guarantees** + - Add contract tests for public APIs. +3. **Automate regression prevention** + - Pre-merge required checks + nightly full-matrix runs. +4. **Documentation alignment** + - Ensure examples/tutorials reference new functionality where relevant. + +--- + +## 8) Executive Conclusion + +This change set is structurally low-intrusive (**8 new files, no modifications**), but **test failures are a hard release blocker**. +Primary priority is failure triage and stabilization. Once tests are green and packaging/API exposure is validated, the update should be safe to proceed through normal release gates. \ No newline at end of file diff --git a/mne-python/mcp_output/mcp_plugin/__init__.py b/mne-python/mcp_output/mcp_plugin/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/mne-python/mcp_output/mcp_plugin/adapter.py b/mne-python/mcp_output/mcp_plugin/adapter.py new file mode 100644 index 0000000000000000000000000000000000000000..f22d9108d5f9fc03e7b7e420708e7c01199e2279 --- /dev/null +++ b/mne-python/mcp_output/mcp_plugin/adapter.py @@ -0,0 +1,358 @@ +import os +import sys +import importlib +import traceback +from typing import Any, Dict, List, Optional + +source_path = os.path.join( + os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), + "source", +) +sys.path.insert(0, source_path) + + +class Adapter: + """ + Import-mode adapter for the mne-python MCP plugin integration. + + This adapter prioritizes Python imports and provides a graceful CLI fallback + pathway when import-based execution is unavailable. + """ + + # ------------------------------------------------------------------------- + # Lifecycle / Initialization + # ------------------------------------------------------------------------- + def __init__(self) -> None: + """ + Initialize adapter state, import registry, and module availability. + + Attributes: + mode: Adapter execution mode, fixed to "import". + package_root: Root import path for repository package. + modules: Loaded module cache keyed by logical name. + available: Boolean import readiness state. + warnings: List of non-fatal issues detected during initialization. + """ + self.mode = "import" + self.package_root = "mne" + self.modules: Dict[str, Any] = {} + self.available = False + self.warnings: List[str] = [] + self._initialize_imports() + + def _initialize_imports(self) -> None: + """ + Attempt to import core and command modules identified by analysis. + + This method captures and stores import exceptions so the adapter can + continue operating in graceful fallback mode. + """ + targets = { + "mne": "mne", + "commands": "mne.commands", + } + + loaded = 0 + for key, mod_path in targets.items(): + try: + self.modules[key] = importlib.import_module(mod_path) + loaded += 1 + except Exception as exc: + self.modules[key] = None + self.warnings.append( + f"Failed to import '{mod_path}'. Verify local source checkout and dependencies. Detail: {exc}" + ) + self.available = loaded > 0 + + # ------------------------------------------------------------------------- + # Unified response helpers + # ------------------------------------------------------------------------- + def _ok(self, message: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: + return {"status": "success", "message": message, "data": data or {}} + + def _fail( + self, + message: str, + error: Optional[str] = None, + guidance: Optional[str] = None, + data: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + payload = {"status": "error", "message": message, "data": data or {}} + if error: + payload["error"] = error + if guidance: + payload["guidance"] = guidance + return payload + + def _fallback( + self, + action: str, + reason: str, + extra: Optional[Dict[str, Any]] = None, + ) -> Dict[str, Any]: + return { + "status": "fallback", + "message": f"Import mode unavailable for '{action}'.", + "reason": reason, + "guidance": ( + "Ensure repository source is present under the configured 'source' directory and " + "install required dependencies (numpy, scipy, matplotlib, packaging, pooch, tqdm). " + "If import still fails, use the CLI fallback via the 'mne' command." + ), + "data": extra or {}, + } + + # ------------------------------------------------------------------------- + # Health / Introspection + # ------------------------------------------------------------------------- + def health_check(self) -> Dict[str, Any]: + """ + Report adapter readiness and import diagnostics. + + Returns: + Dict with status, mode, import availability, and warning details. + """ + return self._ok( + "Adapter health check completed.", + { + "mode": self.mode, + "available": self.available, + "loaded_modules": {k: bool(v) for k, v in self.modules.items()}, + "warnings": self.warnings, + }, + ) + + def list_known_packages(self) -> Dict[str, Any]: + """ + Return package namespaces discovered during analysis. + + Returns: + Dict containing analyzed package names for discovery/debugging. + """ + packages = [ + "deployment.mne-python.source", + "mcp_output.mcp_plugin", + "source.mne", + "source.mne._fiff", + "source.mne.beamformer", + "source.mne.channels", + "source.mne.commands", + "source.mne.data", + "source.mne.datasets", + "source.mne.decoding", + "source.mne.export", + "source.mne.forward", + "source.mne.gui", + "source.mne.html_templates", + "source.mne.inverse_sparse", + "source.mne.io", + "source.mne.minimum_norm", + "source.mne.preprocessing", + "source.mne.report", + "source.mne.simulation", + "source.mne.source_space", + "source.mne.stats", + "source.mne.tests", + "source.mne.time_frequency", + "source.mne.utils", + "source.mne.viz", + ] + return self._ok("Known package list prepared.", {"packages": packages}) + + # ------------------------------------------------------------------------- + # Module management + # ------------------------------------------------------------------------- + def import_module(self, module_path: str) -> Dict[str, Any]: + """ + Dynamically import an MNE module using full package path. + + Args: + module_path: Absolute module path (e.g., 'mne.io', 'mne.preprocessing'). + + Returns: + Unified status dictionary with module import result. + """ + try: + mod = importlib.import_module(module_path) + self.modules[module_path] = mod + return self._ok("Module imported successfully.", {"module_path": module_path}) + except Exception as exc: + return self._fail( + "Module import failed.", + error=str(exc), + guidance="Confirm module path and dependency installation.", + data={"module_path": module_path}, + ) + + def get_module_attributes(self, module_path: str, limit: int = 200) -> Dict[str, Any]: + """ + Enumerate public attributes for a module to support function discovery. + + Args: + module_path: Full module path. + limit: Maximum number of attributes to return. + + Returns: + Unified status dictionary containing exported attribute names. + """ + try: + mod = self.modules.get(module_path) or importlib.import_module(module_path) + attrs = [a for a in dir(mod) if not a.startswith("_")] + return self._ok( + "Module attributes fetched.", + {"module_path": module_path, "attributes": attrs[: max(1, limit)]}, + ) + except Exception as exc: + return self._fail( + "Could not inspect module attributes.", + error=str(exc), + guidance="Import the module first and verify it is available in local source.", + data={"module_path": module_path}, + ) + + # ------------------------------------------------------------------------- + # Core MNE call surface + # ------------------------------------------------------------------------- + def call_mne_function(self, function_name: str, *args: Any, **kwargs: Any) -> Dict[str, Any]: + """ + Call a function from the top-level mne module by name. + + Args: + function_name: Name of the function in module 'mne'. + *args: Positional arguments forwarded to the target function. + **kwargs: Keyword arguments forwarded to the target function. + + Returns: + Unified status dictionary with execution result or actionable failure. + """ + if not self.modules.get("mne"): + return self._fallback("call_mne_function", "Top-level module 'mne' is not importable.") + + try: + target = getattr(self.modules["mne"], function_name, None) + if target is None or not callable(target): + return self._fail( + "Requested MNE function was not found.", + guidance="Use get_module_attributes('mne') to discover available callables.", + data={"function_name": function_name}, + ) + result = target(*args, **kwargs) + return self._ok( + "MNE function executed successfully.", + {"function_name": function_name, "result": result}, + ) + except Exception as exc: + return self._fail( + "MNE function execution failed.", + error=str(exc), + guidance="Validate function arguments and data formats expected by MNE.", + data={"function_name": function_name, "traceback": traceback.format_exc()}, + ) + + # ------------------------------------------------------------------------- + # CLI wrapper (fallback-friendly) + # ------------------------------------------------------------------------- + def call_mne_cli(self, argv: Optional[List[str]] = None) -> Dict[str, Any]: + """ + Execute the primary MNE command-line wrapper from imported command module. + + Args: + argv: Optional list of CLI-like arguments. If omitted, attempts default call. + + Returns: + Unified status dictionary with invocation status and hints. + """ + commands_mod = self.modules.get("commands") + if not commands_mod: + return self._fallback("call_mne_cli", "Module 'mne.commands' is not importable.") + + try: + entry_candidates = ["main", "run", "command_main"] + entry = None + for name in entry_candidates: + fn = getattr(commands_mod, name, None) + if callable(fn): + entry = fn + break + + if entry is None: + return self._fail( + "No callable CLI entry point found in mne.commands.", + guidance="Inspect mne.commands module attributes and map the correct callable.", + data={"checked_candidates": entry_candidates}, + ) + + if argv is None: + out = entry() + else: + out = entry(argv) + + return self._ok( + "MNE CLI wrapper executed.", + {"argv": argv or [], "result": out, "entry_point": entry.__name__}, + ) + except TypeError: + try: + out = entry() # type: ignore[misc] + return self._ok( + "MNE CLI wrapper executed with default signature.", + {"argv": argv or [], "result": out, "entry_point": entry.__name__}, # type: ignore[union-attr] + ) + except Exception as exc: + return self._fail( + "MNE CLI invocation failed.", + error=str(exc), + guidance="Pass valid subcommands/arguments or verify command module compatibility.", + data={"traceback": traceback.format_exc()}, + ) + except Exception as exc: + return self._fail( + "MNE CLI invocation failed.", + error=str(exc), + guidance="Check installed optional dependencies and command arguments.", + data={"traceback": traceback.format_exc()}, + ) + + # ------------------------------------------------------------------------- + # Class instantiation helper (generic, analysis-driven) + # ------------------------------------------------------------------------- + def create_instance( + self, + module_path: str, + class_name: str, + *args: Any, + **kwargs: Any, + ) -> Dict[str, Any]: + """ + Instantiate a class from a target module path. + + Args: + module_path: Full module path containing the class. + class_name: Class name to instantiate. + *args: Positional constructor arguments. + **kwargs: Keyword constructor arguments. + + Returns: + Unified status dictionary with instantiated object handle. + """ + try: + mod = self.modules.get(module_path) or importlib.import_module(module_path) + cls = getattr(mod, class_name, None) + if cls is None: + return self._fail( + "Class not found in module.", + guidance="Use get_module_attributes(module_path) to verify class exports.", + data={"module_path": module_path, "class_name": class_name}, + ) + instance = cls(*args, **kwargs) + return self._ok( + "Class instantiated successfully.", + {"module_path": module_path, "class_name": class_name, "instance": instance}, + ) + except Exception as exc: + return self._fail( + "Class instantiation failed.", + error=str(exc), + guidance="Verify constructor arguments and required dependencies for this class.", + data={"module_path": module_path, "class_name": class_name, "traceback": traceback.format_exc()}, + ) \ No newline at end of file diff --git a/mne-python/mcp_output/mcp_plugin/main.py b/mne-python/mcp_output/mcp_plugin/main.py new file mode 100644 index 0000000000000000000000000000000000000000..fca6ec384e22f703b287550e94cc00baaaa4c4a7 --- /dev/null +++ b/mne-python/mcp_output/mcp_plugin/main.py @@ -0,0 +1,13 @@ +""" +MCP Service Auto-Wrapper - Auto-generated +""" +from mcp_service import create_app + +def main(): + """Main entry point""" + app = create_app() + return app + +if __name__ == "__main__": + app = main() + app.run() \ No newline at end of file diff --git a/mne-python/mcp_output/mcp_plugin/mcp_service.py b/mne-python/mcp_output/mcp_plugin/mcp_service.py new file mode 100644 index 0000000000000000000000000000000000000000..dae0b61153d91cd2a7b101d56edf508d1efe6da1 --- /dev/null +++ b/mne-python/mcp_output/mcp_plugin/mcp_service.py @@ -0,0 +1,215 @@ +import os +import sys +from typing import Optional, Dict, Any, List + +source_path = os.path.join( + os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), + "source", +) +if source_path not in sys.path: + sys.path.insert(0, source_path) + +from fastmcp import FastMCP + +mcp = FastMCP("mne_python_service") + + +def _safe_import_mne(): + try: + import mne # type: ignore + return True, mne, None + except Exception as exc: + return False, None, str(exc) + + +@mcp.tool(name="mne_get_version", description="Get installed MNE version information.") +def mne_get_version() -> Dict[str, Any]: + """ + Return MNE package version. + + Returns: + Dict with: + - success: bool indicating operation status + - result: version string when successful + - error: error string when failed + """ + ok, mne_mod, err = _safe_import_mne() + if not ok: + return {"success": False, "result": None, "error": err} + try: + version = getattr(mne_mod, "__version__", "unknown") + return {"success": True, "result": version, "error": None} + except Exception as exc: + return {"success": False, "result": None, "error": str(exc)} + + +@mcp.tool(name="mne_get_config", description="Read MNE configuration value by key.") +def mne_get_config(key: str, default: Optional[str] = None) -> Dict[str, Any]: + """ + Read a single MNE config key. + + Parameters: + key: Configuration key to lookup. + default: Optional fallback if key is not found. + + Returns: + Dict with: + - success: bool + - result: config value + - error: error message when failed + """ + ok, mne_mod, err = _safe_import_mne() + if not ok: + return {"success": False, "result": None, "error": err} + try: + value = mne_mod.get_config(key=key, default=default) + return {"success": True, "result": value, "error": None} + except Exception as exc: + return {"success": False, "result": None, "error": str(exc)} + + +@mcp.tool(name="mne_set_config", description="Set an MNE configuration key to a value.") +def mne_set_config(key: str, value: str, set_env: bool = False) -> Dict[str, Any]: + """ + Set a single MNE config key. + + Parameters: + key: Configuration key. + value: Configuration value. + set_env: If True, also set environment variable for current process. + + Returns: + Dict with: + - success: bool + - result: True when set successfully + - error: error message when failed + """ + ok, mne_mod, err = _safe_import_mne() + if not ok: + return {"success": False, "result": None, "error": err} + try: + mne_mod.set_config(key=key, value=value, set_env=set_env) + return {"success": True, "result": True, "error": None} + except Exception as exc: + return {"success": False, "result": None, "error": str(exc)} + + +@mcp.tool(name="mne_create_info", description="Create an MNE Info object from channels and sampling frequency.") +def mne_create_info(ch_names: List[str], sfreq: float, ch_types: Optional[List[str]] = None) -> Dict[str, Any]: + """ + Create a lightweight channel metadata structure. + + Parameters: + ch_names: List of channel names. + sfreq: Sampling frequency in Hz. + ch_types: Optional list of channel types aligned with ch_names. + + Returns: + Dict with: + - success: bool + - result: serializable summary of created Info + - error: error message when failed + """ + ok, mne_mod, err = _safe_import_mne() + if not ok: + return {"success": False, "result": None, "error": err} + try: + info = mne_mod.create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types) + result = { + "nchan": int(info["nchan"]), + "sfreq": float(info["sfreq"]), + "ch_names": list(info["ch_names"]), + "highpass": float(info.get("highpass", 0.0) or 0.0), + "lowpass": float(info.get("lowpass", 0.0) or 0.0), + } + return {"success": True, "result": result, "error": None} + except Exception as exc: + return {"success": False, "result": None, "error": str(exc)} + + +@mcp.tool(name="mne_compute_events", description="Detect events from a stim channel in a raw FIF file.") +def mne_compute_events( + raw_fif_path: str, + stim_channel: Optional[str] = None, + shortest_event: int = 1, + min_duration: float = 0.0, +) -> Dict[str, Any]: + """ + Load raw FIF and compute events from stimulation channel. + + Parameters: + raw_fif_path: Path to a readable raw FIF file. + stim_channel: Optional stim channel name. If None, MNE default detection is used. + shortest_event: Minimum number of samples for an event. + min_duration: Minimum event duration in seconds. + + Returns: + Dict with: + - success: bool + - result: event count and preview rows + - error: error message when failed + """ + ok, mne_mod, err = _safe_import_mne() + if not ok: + return {"success": False, "result": None, "error": err} + try: + raw = mne_mod.io.read_raw_fif(raw_fif_path, preload=False, verbose=False) + events = mne_mod.find_events( + raw, + stim_channel=stim_channel, + shortest_event=shortest_event, + min_duration=min_duration, + verbose=False, + ) + preview = events[:20].tolist() if len(events) > 0 else [] + return { + "success": True, + "result": {"count": int(len(events)), "preview": preview}, + "error": None, + } + except Exception as exc: + return {"success": False, "result": None, "error": str(exc)} + + +@mcp.tool(name="mne_estimate_rank", description="Estimate data rank from an epochs or raw FIF file.") +def mne_estimate_rank(fif_path: str, tol: Optional[float] = None) -> Dict[str, Any]: + """ + Estimate numerical rank from MNE data object loaded from FIF. + + Parameters: + fif_path: Path to raw or epochs FIF file. + tol: Optional tolerance passed to rank estimator. + + Returns: + Dict with: + - success: bool + - result: estimated rank dictionary or scalar + - error: error message when failed + """ + ok, mne_mod, err = _safe_import_mne() + if not ok: + return {"success": False, "result": None, "error": err} + try: + result_obj: Any + try: + raw = mne_mod.io.read_raw_fif(fif_path, preload=False, verbose=False) + result_obj = mne_mod.compute_rank(raw, tol=tol, verbose=False) + except Exception: + epochs = mne_mod.read_epochs(fif_path, preload=False, verbose=False) + result_obj = mne_mod.compute_rank(epochs, tol=tol, verbose=False) + + if isinstance(result_obj, dict): + serializable = {str(k): int(v) for k, v in result_obj.items()} + else: + serializable = int(result_obj) + return {"success": True, "result": serializable, "error": None} + except Exception as exc: + return {"success": False, "result": None, "error": str(exc)} + + +def create_app() -> FastMCP: + return mcp + + +if __name__ == "__main__": + mcp.run() \ No newline at end of file diff --git a/mne-python/mcp_output/requirements.txt b/mne-python/mcp_output/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..86e8cf82cb08c4b712e5cde69473cc8c2fc700da --- /dev/null +++ b/mne-python/mcp_output/requirements.txt @@ -0,0 +1,16 @@ +fastmcp +fastapi +uvicorn[standard] +pydantic>=2.0.0 +decorator >= 5.1 +jinja2 >= 3.1 +lazy_loader >= 0.3 +matplotlib >= 3.8 +numpy >= 1.26, < 3 +packaging +pooch >= 1.5 +scipy >= 1.12 +tqdm >= 4.66 +nest-asyncio2 +pymef +pyobjc-framework-Cocoa >=5.2.0;platform_system=='Darwin' diff --git a/mne-python/mcp_output/start_mcp.py b/mne-python/mcp_output/start_mcp.py new file mode 100644 index 0000000000000000000000000000000000000000..fc7fcbd9646ad53f089fc94af8129043a703325a --- /dev/null +++ b/mne-python/mcp_output/start_mcp.py @@ -0,0 +1,30 @@ + +""" +MCP Service Startup Entry +""" +import sys +import os + +project_root = os.path.dirname(os.path.abspath(__file__)) +mcp_plugin_dir = os.path.join(project_root, "mcp_plugin") +if mcp_plugin_dir not in sys.path: + sys.path.insert(0, mcp_plugin_dir) + +from mcp_service import create_app + +def main(): + """Start FastMCP service""" + app = create_app() + # Use environment variable to configure port, default 8000 + port = int(os.environ.get("MCP_PORT", "8000")) + + # Choose transport mode based on environment variable + transport = os.environ.get("MCP_TRANSPORT", "stdio") + if transport == "http": + app.run(transport="http", host="0.0.0.0", port=port) + else: + # Default to STDIO mode + app.run() + +if __name__ == "__main__": + main() diff --git a/mne-python/mcp_output/workflow_summary.json b/mne-python/mcp_output/workflow_summary.json new file mode 100644 index 0000000000000000000000000000000000000000..7b3b985ab6b1dee7970b2a461ea243efb400749b --- /dev/null +++ b/mne-python/mcp_output/workflow_summary.json @@ -0,0 +1,253 @@ +{ + "repository": { + "name": "mne-python", + "url": "https://github.com/mne-tools/mne-python", + "local_path": "/Users/ghh/Documents/Code/Code2MCP-private/workspace/mne-python", + "description": "Python library", + "features": "Basic functionality", + "tech_stack": "Python", + "stars": 0, + "forks": 0, + "language": "Python", + "last_updated": "", + "complexity": "complex", + "intrusiveness_risk": "medium" + }, + "execution": { + "start_time": 1773461253.309027, + "end_time": 1773462216.903234, + "duration": 963.5942070484161, + "status": "success", + "workflow_status": "success", + "nodes_executed": [ + "download", + "analysis", + "env", + "generate", + "run", + "review", + "finalize" + ], + "total_files_processed": 26, + "environment_type": "unknown", + "llm_calls": 0, + "deepwiki_calls": 0 + }, + "tests": { + "original_project": { + "passed": false, + "details": {}, + "test_coverage": "100%", + "execution_time": 0, + "test_files": [] + }, + "mcp_plugin": { + "passed": true, + "details": {}, + "service_health": "healthy", + "startup_time": 0, + "transport_mode": "stdio", + "fastmcp_version": "unknown", + "mcp_version": "unknown" + } + }, + "analysis": { + "structure": { + "packages": [ + "deployment.mne-python.source", + "mcp_output.mcp_plugin", + "source.mne", + "source.mne._fiff", + "source.mne.beamformer", + "source.mne.channels", + "source.mne.commands", + "source.mne.data", + "source.mne.datasets", + "source.mne.decoding", + "source.mne.export", + "source.mne.forward", + "source.mne.gui", + "source.mne.html_templates", + "source.mne.inverse_sparse", + "source.mne.io", + "source.mne.minimum_norm", + "source.mne.preprocessing", + "source.mne.report", + "source.mne.simulation", + "source.mne.source_space", + "source.mne.stats", + "source.mne.tests", + "source.mne.time_frequency", + "source.mne.utils", + "source.mne.viz" + ] + }, + "dependencies": { + "has_environment_yml": true, + "has_requirements_txt": false, + "pyproject": true, + "setup_cfg": false, + "setup_py": false + }, + "entry_points": { + "imports": [], + "cli": [], + "modules": [] + }, + "risk_assessment": { + "import_feasibility": 0.72, + "intrusiveness_risk": "medium", + "complexity": "complex" + }, + "deepwiki_analysis": { + "repo_url": "https://github.com/mne-tools/mne-python", + "repo_name": "mne-python", + "error": "DeepWiki analysis failed", + "model": "gpt-5.3-codex", + "source": "llm_direct_analysis", + "success": false + }, + "code_complexity": { + "cyclomatic_complexity": "medium", + "cognitive_complexity": "medium", + "maintainability_index": 75 + }, + "security_analysis": { + "vulnerabilities_found": 0, + "security_score": 85, + "recommendations": [] + } + }, + "plugin_generation": { + "files_created": [ + "mcp_output/start_mcp.py", + "mcp_output/mcp_plugin/__init__.py", + "mcp_output/mcp_plugin/mcp_service.py", + "mcp_output/mcp_plugin/adapter.py", + "mcp_output/mcp_plugin/main.py", + "mcp_output/requirements.txt", + "mcp_output/README_MCP.md" + ], + "main_entry": "start_mcp.py", + "requirements": [ + "fastmcp>=0.1.0", + "pydantic>=2.0.0" + ], + "readme_path": "/Users/ghh/Documents/Code/Code2MCP-private/workspace/mne-python/mcp_output/README_MCP.md", + "adapter_mode": "import", + "total_lines_of_code": 0, + "generated_files_size": 0, + "tool_endpoints": 0, + "supported_features": [ + "Basic functionality" + ], + "generated_tools": [ + "Basic tools", + "Health check tools", + "Version info tools" + ] + }, + "code_review": {}, + "errors": [], + "warnings": [], + "recommendations": [ + "Harden repository ingestion with retry/resume and fallback to shallow git clone when zip download fails", + "Add a preflight dependency checker that validates required/optional MNE extras and reports actionable install commands", + "Implement lazy imports and per-endpoint module loading to reduce startup cost and import-side failures", + "Add a CLI fallback execution path for heavy/fragile endpoints (especially viz and large IO) when import mode errors", + "Introduce endpoint-level health checks/smoke tests using small synthetic MNE objects (RawArray/Epochs) to validate MCP bindings", + "Expand automated tests in `tests_mcp` for argument validation", + "error mapping", + "and serialization of core classes", + "Add structured error taxonomy (DependencyMissing", + "FileFormatUnsupported", + "RuntimeImportError", + "HeadlessVizError) with user-friendly remediation hints", + "Gate visualization endpoints behind headless-safe checks (matplotlib backend/PyVista availability) and return clear non-GUI alternatives", + "Improve README_MCP with concrete examples for common workflows (load raw", + "find events", + "ICA", + "PSD) and expected input/output schemas", + "Add version pinning/compatibility matrix for `mne`", + "`numpy`", + "`scipy`", + "and `pydantic` to prevent runtime drift", + "Generate JSON Schemas for each endpoint and enforce strict Pydantic models for stable MCP contracts", + "Add timeout/cancellation controls and memory guards for long-running transforms (TFR/ICA/CSD)", + "Implement lightweight caching for repeated file reads and computed intermediates (with invalidation by file hash)", + "Add observability: structured logs", + "per-endpoint latency/error metrics", + "and import-failure counters", + "Create a minimal “safe default” endpoint set (non-viz", + "low-memory) and mark advanced endpoints as optional capability flags", + "Add integration tests for representative file formats (FIF/EDF/BDF/BrainVision) with tiny fixtures", + "Validate and normalize path handling across OSes (spaces", + "unicode", + "relative paths) before IO calls", + "Add graceful degradation when optional packages are missing (e.g.", + "skip vtk/pyvista features instead of failing server start)", + "Include a reproducible dev environment (`environment.yml`/lockfile) for MCP plugin CI", + "Add CI workflow to run lint/type-check/tests for `mcp_output` and publish test report artifacts" + ], + "performance_metrics": { + "memory_usage_mb": 0, + "cpu_usage_percent": 0, + "response_time_ms": 0, + "throughput_requests_per_second": 0 + }, + "deployment_info": { + "supported_platforms": [ + "Linux", + "Windows", + "macOS" + ], + "python_versions": [ + "3.8", + "3.9", + "3.10", + "3.11", + "3.12" + ], + "deployment_methods": [ + "Docker", + "pip", + "conda" + ], + "monitoring_support": true, + "logging_configuration": "structured" + }, + "execution_analysis": { + "success_factors": [ + "Workflow reached terminal success state with all planned nodes executed (download, analysis, env, generate, run, review, finalize)", + "MCP plugin runtime test passed with healthy service status over stdio transport", + "Import-based adapter strategy aligned with detected MNE API surface and produced broad endpoint coverage", + "No runtime errors or warnings were recorded during orchestration" + ], + "failure_reasons": [ + "Repository preprocessing partially failed due to zip download IncompleteRead, reducing analysis fidelity", + "DeepWiki analysis failed, so architecture/context enrichment depended on fallback LLM direct analysis", + "Original project test status is failed/unknown despite reported 100% coverage metadata, indicating unreliable baseline validation", + "Generated artifact metrics are inconsistent (tool_endpoints=0 vs populated endpoint list; total_lines_of_code=0), suggesting reporting/telemetry defects" + ], + "overall_assessment": "good", + "node_performance": { + "download_time": "Download node completed but experienced non-fatal zip transfer instability (IncompleteRead). This is the primary execution fragility.", + "analysis_time": "Analysis completed via fallback path; quality adequate for generation but lower confidence than full repository preprocessing + DeepWiki.", + "generation_time": "Generation completed successfully with required files and entrypoint created; endpoint exposure is broad and useful.", + "test_time": "Service-level test passed quickly (startup_time reported 0), but original-project validation is not trustworthy; test depth appears shallow." + }, + "resource_usage": { + "memory_efficiency": "Undetermined from metrics (reported 0 MB). Likely acceptable for scaffold generation, but runtime memory for heavy MNE ops remains unmeasured.", + "cpu_efficiency": "Undetermined from metrics (reported 0%). End-to-end duration (~964s) indicates non-trivial processing overhead and potential I/O/network wait.", + "disk_usage": "Generated output footprint appears underreported (0 size), indicating instrumentation gaps rather than true zero disk impact." + } + }, + "technical_quality": { + "code_quality_score": 74, + "architecture_score": 78, + "performance_score": 62, + "maintainability_score": 76, + "security_score": 85, + "scalability_score": 68 + } +} \ No newline at end of file diff --git a/mne-python/source/.DS_Store b/mne-python/source/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4bb0ca3005031372decaa212f94953924f42d368 Binary files /dev/null and b/mne-python/source/.DS_Store differ diff --git a/mne-python/source/.circleci/config.yml b/mne-python/source/.circleci/config.yml new file mode 100644 index 0000000000000000000000000000000000000000..c0780cd047f923d64b2b4dd0e2ec0dccca27204f --- /dev/null +++ b/mne-python/source/.circleci/config.yml @@ -0,0 +1,570 @@ +# By default, for PRs CircleCI will build only examples that have changed. +# For main commits, builds are skipped entirely, as we only do full builds +# scheduled for one time daily. +# +# Tagging a commit with the following overrides these behaviors: +# - [circle front] will run the front page examples and perform test-doc +# - [circle full] will run all examples and perform test-doc +# - [circle linkcheck] will run our linkcheck job +# - [circle deploy] on a main or maint/* commit will try to immediately build +# and deploy docs rather than waiting for the nightly build + +version: 2.1 + +_check_skip: &check_skip + name: Check-skip + command: | + set -e + export COMMIT_MESSAGE=$(git log --format=oneline -n 1); + if [[ "$CIRCLE_PULL_REQUEST" != "" ]] && ([[ "$COMMIT_MESSAGE" == *"[skip circle]"* ]] || [[ "$COMMIT_MESSAGE" == *"[circle skip]"* ]]); then + echo "Skip detected, exiting job ${CIRCLE_JOB} for PR ${CIRCLE_PULL_REQUEST}." + circleci-agent step halt; + fi + +jobs: + build_docs: + parameters: + scheduled: + type: string + default: "false" + machine: + image: ubuntu-2404:current + # large 4 vCPUs 15GB mem + # https://discuss.circleci.com/t/changes-to-remote-docker-reporting-pricing/47759 + resource_class: large + steps: + - restore_cache: + keys: + - source-cache + - checkout: + method: full + - run: + name: Complete checkout + command: | + set -e + if ! git remote -v | grep upstream; then + git remote add upstream https://github.com/mne-tools/mne-python.git + fi + git remote set-url upstream https://github.com/mne-tools/mne-python.git + git fetch upstream + - save_cache: + key: source-cache + paths: + - ".git" + - run: + <<: *check_skip + - run: + name: Merge with upstream and triage run + command: | + set -e + echo $(git log -1 --pretty=%B) | tee gitlog.txt + echo ${CI_PULL_REQUEST//*pull\//} | tee merge.txt + if [[ $(cat merge.txt) != "" ]]; then + echo "Merging $(cat merge.txt)"; + git pull --ff-only upstream "refs/pull/$(cat merge.txt)/merge"; + else + if [[ "$CIRCLE_BRANCH" == "main" ]]; then + KIND=dev + else + KIND=stable + fi + export COMMIT_MESSAGE=$(git log --format=oneline -n 1); + if [[ "<< parameters.scheduled >>" == "true" ]]; then + echo "Scheduled full build detected, checking if it's required." + wget https://mne.tools/${KIND}/_version.txt; + REMOTE_VERSION=$(cat _version.txt) + THIS_VERSION=$(git rev-parse HEAD) + echo "Current ${KIND} SHA: ${REMOTE_VERSION}" + echo "This ${KIND} SHA: ${THIS_VERSION}" + if [[ "${THIS_VERSION}" != "${REMOTE_VERSION}" ]]; then + echo "Rebuild required." + else + echo "Rebuild skipped." + circleci-agent step halt; + fi + elif [[ "$COMMIT_MESSAGE" == *"[circle deploy]"* ]]; then + echo "Forced deployed build detected, building and deploying docs"; + else + echo "Waiting until scheduled run to build ${KIND} docs, exiting job ${CIRCLE_JOB}." + circleci-agent step halt; + fi + fi + + - run: + name: Set BASH_ENV + command: ./tools/circleci_bash_env.sh + + - run: + name: Install fonts needed for diagrams + command: | + mkdir -p $HOME/.fonts + echo "Source Code Pro" + curl https://codeload.github.com/adobe-fonts/source-code-pro/tar.gz/2.038R-ro/1.058R-it/1.018R-VAR | tar xz -C $HOME/.fonts + echo "Source Sans Pro" + curl https://codeload.github.com/adobe-fonts/source-sans/tar.gz/3.028R | tar xz -C $HOME/.fonts + fc-cache -f + + # Load pip cache + - restore_cache: + keys: + - pip-cache-0 + - restore_cache: + keys: + - user-install-bin-cache-310 + + # Hack in uninstalls of libraries as necessary if pip doesn't do the right thing in upgrading for us... + - run: + name: Get Python running + command: | + ./tools/circleci_dependencies.sh + + - save_cache: + key: pip-cache-0 + paths: + - ~/.cache/pip + - save_cache: + key: user-install-bin-cache-310 + paths: + - ~/.local/lib/python3.10/site-packages + - ~/.local/bin + + - run: + name: Check Qt + command: | + ./tools/check_qt_import.sh PyQt6 + # Load tiny cache so that ~/.mne does not need to be created below + - restore_cache: + keys: + - data-cache-tiny-0 + + # Look at what we have and fail early if there is some library conflict + - run: + name: Check installation + command: | + which python + QT_DEBUG_PLUGINS=1 mne sys_info -pd + python -c "import numpy; numpy.show_config()" + python -c "import dipy.align.metrics" + LIBGL_DEBUG=verbose python -c "import pyvistaqt; pyvistaqt.BackgroundPlotter(show=True)" + python -c "import mne; mne.set_config('MNE_USE_CUDA', 'false')" # this is needed for the config tutorial + python -c "import mne; mne.set_config('MNE_LOGGING_LEVEL', 'info')" + python -c "import mne; level = mne.get_config('MNE_LOGGING_LEVEL'); assert level.lower() == 'info', repr(level)" + - run: + name: List packages + command: python -m pip list + + # Figure out if we should run a full build or specify a pattern + - restore_cache: + keys: + - data-cache-tiny-1 + - restore_cache: + keys: + - data-cache-multimodal + - restore_cache: + keys: + - data-cache-limo + - restore_cache: + keys: + - data-cache-fsaverage + - restore_cache: + keys: + - data-cache-bst-raw + - restore_cache: + keys: + - data-cache-bst-phantom-ctf + - restore_cache: + keys: + - data-cache-bst-phantom-elekta + - restore_cache: + keys: + - data-cache-bst-phantom-kernel + - restore_cache: + keys: + - data-cache-bst-auditory + - restore_cache: + keys: + - data-cache-bst-resting + - restore_cache: + keys: + - data-cache-fieldtrip + - restore_cache: + keys: + - data-cache-somato + - restore_cache: + keys: + - data-cache-hf-sef + - restore_cache: + keys: + - data-cache-opm + - restore_cache: + keys: + - data-cache-sample + - restore_cache: + keys: + - data-cache-spm-face + - restore_cache: + keys: + - data-cache-testing + - restore_cache: + keys: + - data-cache-visual + - restore_cache: + keys: + - data-cache-ucl-opm-auditory + - restore_cache: + keys: + - data-cache-phantom-kit + - restore_cache: + keys: + - data-cache-ds004388 + - run: + name: Get data + # This limit could be increased, but this is helpful for finding slow ones + # (even ~2GB datasets should be downloadable in this time from good + # providers) + no_output_timeout: 10m + command: | + ./tools/circleci_download.sh + - run: + name: Verify build type + command: | + echo "PATTERN=$(cat pattern.txt)" + echo "BUILD=$(cat build.txt)" + ls -al ~/mne_data; + + # Run doctest (if it's full or front) before building the docs + - run: + name: make test-doc + command: | + if [[ $(cat gitlog.txt) == *"[circle front]"* ]] || [[ $(cat build.txt) == "html-memory" ]] ; then + make test-doc; + mkdir -p doc/_build/test-results/test-doc; + cp junit-results.xml doc/_build/test-results/test-doc/junit.xml; + cp coverage.xml doc/_build/test-results/test-doc/coverage.xml; + fi; + # Build docs + - run: + name: make html + command: | # we have -o pipefail in #BASH_ENV so we should be okay + set -x + PATTERN=$(cat pattern.txt) make -C doc $(cat build.txt) 2>&1 | tee sphinx_log.txt + - run: + name: Check sphinx log for warnings (which are treated as errors) + when: always + command: | + ! grep "^.*\(WARNING\|ERROR\): " sphinx_log.txt + - run: + name: Show profiling output + when: always + command: | + if compgen -G "doc/*.dat" > /dev/null; then + mkdir -p doc/generated + mprof plot doc/*.dat --output doc/generated/memory.png + else + echo "No profile data found in doc/" + fi + - run: + name: Sanity check system state + command: | + python -c "import mne; level = mne.get_config('MNE_LOGGING_LEVEL'); assert level.lower() == 'info', repr(level)" + + # Reduce upload time of artifacts we will (almost) never look at + - run: + name: Reduce artifact upload time + command: | + if grep -q html-pattern-memory build.txt; then + zip -rm doc/_build/html/_downloads.zip doc/_build/html/_downloads + fi + for NAME in generated auto_tutorials auto_examples; do + zip -rm doc/${NAME}.zip doc/${NAME} + done + + # Save the JUnit file + - store_test_results: + path: doc/_build/test-results + - store_artifacts: + path: doc/_build/test-results + destination: test-results + # Upload test results to Codecov + - run: + name: Upload test results to Codecov + environment: + CODECOV_TOKEN: fb4c4a94-72d7-4743-bb08-af25b623a29a + command: | + if [[ -f doc/_build/test-results/test-doc/coverage.xml ]]; then + bash <(curl -s https://codecov.io/bash) -f doc/_build/test-results/test-doc/coverage.xml || true + fi + # Save the SG RST + - store_artifacts: + path: doc/auto_examples.zip + - store_artifacts: + path: doc/auto_tutorials.zip + - store_artifacts: + path: doc/generated.zip + # Save the HTML + - store_artifacts: + path: doc/_build/html/ + destination: html + - persist_to_workspace: + root: doc/_build + paths: + - html + + # Keep these separate, maybe better in terms of size limitations (?) + - save_cache: + key: data-cache-tiny-0 # < 100 M, might as well combine + paths: + - ~/.mne + - ~/mne_data/MNE-kiloword-data # (28 M) + - ~/mne_data/MNE-eegbci-data # (35 M) + - ~/mne_data/MNE-misc-data # (39 M) + - ~/mne_data/mTRF_1.5 # (56 M) + - ~/mne_data/MNE-phantom-4DBTi # (77 M) + - save_cache: + key: data-cache-tiny-1 # more to combine + paths: + - ~/mne_data/MNE-fNIRS-motor-data # (71 M) + - ~/mne_data/MNE-refmeg-noise-data # (93 M) + - ~/mne_data/physionet-sleep-data # (95 M) + - save_cache: + key: data-cache-multimodal + paths: + - ~/mne_data/MNE-multimodal-data # (240 M) + - save_cache: + key: data-cache-limo + paths: + - ~/mne_data/MNE-limo-data # (244 M) + - save_cache: + key: data-cache-fsaverage + paths: + - ~/mne_data/MNE-fsaverage-data # (762 M) + - save_cache: + key: data-cache-bst-raw + paths: + - ~/mne_data/MNE-brainstorm-data/bst_raw # (830 M) + - save_cache: + key: data-cache-bst-phantom-ctf + paths: + - ~/mne_data/MNE-brainstorm-data/bst_phantom_ctf # (177 M) + - save_cache: + key: data-cache-bst-phantom-elekta + paths: + - ~/mne_data/MNE-brainstorm-data/bst_phantom_elekta # (1.4 G) + - save_cache: + key: data-cache-bst-phantom-kernel + paths: + - ~/mne_data/MNE-phantom-kernel-data # (362 M) + - save_cache: + key: data-cache-bst-auditory + paths: + - ~/mne_data/MNE-brainstorm-data/bst_auditory # (2.9 G) + - save_cache: + key: data-cache-bst-resting + paths: + - ~/mne_data/MNE-brainstorm-data/bst_resting # (4.5 G) + - save_cache: + key: data-cache-fieldtrip + paths: + - ~/mne_data/MNE-fieldtrip_cmc-data # (699 M) + - save_cache: + key: data-cache-somato + paths: + - ~/mne_data/MNE-somato-data # (750 M) + - save_cache: + key: data-cache-hf-sef + paths: + - ~/mne_data/HF_SEF # (1.3 G) + - save_cache: + key: data-cache-opm + paths: + - ~/mne_data/MNE-OPM-data # (1.9 G) + - save_cache: + key: data-cache-sample + paths: + - ~/mne_data/MNE-sample-data # (3.2 G) + - save_cache: + key: data-cache-spm-face + paths: + - ~/mne_data/MNE-spm-face # (1.5 G) + - save_cache: + key: data-cache-testing + paths: + - ~/mne_data/MNE-testing-data # (2.5 G) + - save_cache: + key: data-cache-visual + paths: + - ~/mne_data/MNE-visual_92_categories-data # (6 G) + - save_cache: + key: data-cache-ucl-opm-auditory + paths: + - ~/mne_data/auditory_OPM_stationary # (4 G) + - save_cache: + key: data-cache-phantom-kit + paths: + - ~/mne_data/MNE-phantom-KIT-data # (1 G) + - save_cache: + key: data-cache-ds004388 + paths: + - ~/mne_data/ds004388 # (1.8 G) + + + linkcheck: + # there are a few files excluded from this for expediency, see Makefile + parameters: + scheduled: + type: string + default: "false" + machine: + image: ubuntu-2404:current + resource_class: large + steps: + - restore_cache: + keys: + - source-cache + - checkout + - run: + name: Check-skip + command: | + export COMMIT_MESSAGE=$(git log --format=oneline -n 1); + if [[ "$COMMIT_MESSAGE" != *"[circle linkcheck]"* ]] && [ "<< parameters.scheduled >>" != "true" ]; then + echo "Skip detected, exiting job ${CIRCLE_JOB}." + circleci-agent step halt; + fi + - run: + name: Set BASH_ENV + command: ./tools/circleci_bash_env.sh + - restore_cache: + keys: + - pip-cache-0 + - run: + name: Get Python running + command: | + ./tools/circleci_dependencies.sh + - run: + name: Check installation + command: | + mne sys_info -pd + - run: + name: make linkcheck + no_output_timeout: 40m + command: | + make -C doc linkcheck + - store_artifacts: + path: doc/_build/linkcheck + destination: linkcheck + + + deploy: + machine: + image: ubuntu-2404:current + steps: + - attach_workspace: + at: /tmp/build + - restore_cache: + keys: + - website-cache-1 + - add_ssh_keys: + fingerprints: + # SHA256:N4qvp6MSbXcTz/27xz96VPsNuTDRT92zoRP8EW0I/8I + - "19:fe:1d:c3:c7:af:7e:16:94:4c:e1:e7:0a:56:13:bd" + - run: + name: Set BASH_ENV + command: | + set -e + echo "set -e" >> $BASH_ENV + # Don't try to deploy if nothing is there or not on the right branch + - run: + name: Check docs + command: | + if [ ! -f /tmp/build/html/index.html ] ; then + echo "No files found to upload (build: ${CIRCLE_BRANCH})."; + circleci-agent step halt; + fi; + - run: + name: Fetch docs + command: | + mkdir -p ~/.ssh + echo -e "Host *\nStrictHostKeyChecking no" > ~/.ssh/config + chmod og= ~/.ssh/config + if [ ! -d ~/mne-tools.github.io ]; then + git clone git@github.com:/mne-tools/mne-tools.github.io.git ~/mne-tools.github.io --depth=1 + fi + - run: + name: Deploy docs + command: | + git config --global user.email "circle@mne.tools"; + git config --global user.name "Circle CI"; + ssh-add -D && ssh-add ~/.ssh/id_rsa_19fe1dc3c7af7e16944ce1e70a5613bd + cd ~/mne-tools.github.io; + git checkout main + git remote -v + git fetch origin + git reset --hard origin/main + git clean -xdf + if [ "${CIRCLE_BRANCH}" == "main" ]; then + echo "Deploying dev docs for ${CIRCLE_BRANCH}."; + rm -Rf dev; + cp -a /tmp/build/html dev; + git add -A; + git commit -m "CircleCI update of dev docs (${CIRCLE_BUILD_NUM})."; + else + echo "Deploying stable docs for ${CIRCLE_BRANCH}."; + rm -Rf stable; + cp -a /tmp/build/html stable; + git add -A; + git commit -m "CircleCI update of stable docs (${CIRCLE_BUILD_NUM})."; + fi; + git push origin main; + - save_cache: + key: website-cache-1 + paths: + - ~/mne-tools.github.io + +workflows: + default: + jobs: + - build_docs: + name: build_docs + - linkcheck: + name: linkcheck + - deploy: + name: deploy + requires: + - build_docs + filters: + branches: + only: + - main + - /maint\/.*/ + + main: + jobs: + - build_docs: + scheduled: "true" + name: build_docs_main + - deploy: + name: deploy_main + requires: + - build_docs_main + triggers: + - schedule: + # "At 6:00 AM GMT every day" + cron: "0 6 * * *" + filters: + branches: + only: + - main + + monthly: + jobs: + - linkcheck: + name: linkcheck_monthly + scheduled: "true" + triggers: + - schedule: + # "At 6:00 AM GMT on the first day of each month" + cron: "0 6 1 * *" + filters: + branches: + only: + - main diff --git a/mne-python/source/.coveragerc b/mne-python/source/.coveragerc new file mode 100644 index 0000000000000000000000000000000000000000..33ba1c26b45ccecc2b8c165ff60c56d4543cd21b --- /dev/null +++ b/mne-python/source/.coveragerc @@ -0,0 +1,16 @@ +[run] +branch = True +source = mne +omit = + */bin/* + */setup.py + */mne/fixes* + */mne/utils/linalg.py + */mne/conftest.py + +[report] +exclude_lines = + pragma: no cover + if __name__ == .__main__.: + @abstractmethod + @abstractclassmethod diff --git a/mne-python/source/.mailmap b/mne-python/source/.mailmap new file mode 100644 index 0000000000000000000000000000000000000000..7e9fe67c4b25e37dca6b0ccf85cec6aa3fb37f97 --- /dev/null +++ b/mne-python/source/.mailmap @@ -0,0 +1,379 @@ +Adam Li Adam Li +Adam Li Adam Li +Alan Leggitt leggitta +Alessandro Tonin Lychfindel <58313635+Lychfindel@users.noreply.github.com> +Alex Lepauvre Alex lepauvre +Alex Rockhill Alex +Alex Rockhill Alex +Alex Rockhill Alex Rockhill +Alex Rockhill Alex Rockhill +Alexander Rudiuk Alexander Rudiuk +Alexandre Barachant alexandre barachant +Alexandre Gramfort Alexandre Gramfort +Alexandre Gramfort Alexandre Gramfort +Alexandre Gramfort Alexandre Gramfort +Alexandre Gramfort Alexandre Gramfort +Alexandre Gramfort Alexandre Gramfort +Ana Radanovic anaradanovic <79697247+anaradanovic@users.noreply.github.com> +Andres Rodriguez +Andrew Dykstra +Andrew Quinn AJQuinn +Andy Gilbert <7andy121@gmail.com> Andrew Gilbert +Andy Gilbert <7andy121@gmail.com> Andrew Gilbert +Aniket Singh Yadav <148300120+Aniketsy@users.noreply.github.com> Aniket <148300120+Aniketsy@users.noreply.github.com> +Anna Padee apadee <44297909+apadee@users.noreply.github.com> +Anne-Sophie Dubarry annesodub +Archit Singhal <43236121+architsinghal-mriirs@users.noreply.github.com> archit singhal +Arne Pelzer aplzr <7202498+aplzr@users.noreply.github.com> +Arne Pelzer pzr +Ashley Drew ashdrew <33734402+ashdrew@users.noreply.github.com> +Asish Panda kaichogami +Basile Pinsard +Brad Buran Brad Buran +Britta Westner britta-wstnr +Bruno Aristimunha +btkcodedev +buildqa +Burkhard Maess Burkhard Maess +Carina Forster Carina +Carlos de la Torre carlos +Catalina María Galván <79813952+catalinamagalvan@users.noreply.github.com> Catalina Magalvan <79813952+catalinamagalvan@users.noreply.github.com> +Catalina María Galván <79813952+catalinamagalvan@users.noreply.github.com> catalinamagalvan <79813952+catalinamagalvan@users.noreply.github.com> +Cathy Nangini CN +Chetan Gohil <53237863+cgohil8@users.noreply.github.com> cgohil8 <53237863+cgohil8@users.noreply.github.com> +Chris Holdgraf Chris Holdgraf +Chris Holdgraf Christopher Holdgraf +Christian Brodbeck Christian Brodbeck +Christian Brodbeck christianmbrodbeck +Christian Mista cmista <79416030+cmista@users.noreply.github.com> +Christina Zhao ChristinaZhao +Christoph Dinh Christoph Dinh +Christopher J. Bailey Chris Bailey +Claire Braboszcz claire-braboszcz +Clemens Brunner +Clément Moutard +Cora Kim kimcoco <41998428+kimcoco@users.noreply.github.com> +Cristóbal Moënne-Loccoz Cristóbal +Dan G. Wakeman Daniel G. Wakeman +Dan G. Wakeman Daniel Wakeman +Dan G. Wakeman dgwakeman +Dan G. Wakeman dgwakeman +Daniel C Schad Daniel C Schad +Daniel C Schad Daniel Carlström Schad +Daniel McCloy Daniel McCloy +Daniel McCloy Daniel McCloy +Daniel McCloy drammock +Daniel Strohmeier Daniel Strohmeier +Daniel Strohmeier joewalter +David Julien David JULIEN +David Sabbagh DavidSabbagh <33925146+DavidSabbagh@users.noreply.github.com> +Demetres Kostas <40433000+kostasde@users.noreply.github.com> kostasde <40433000+kostasde@users.noreply.github.com> +Denis A. Engemann dengemann +Denis A. Engemann dengemann +Denis A. Engemann denis +Denis A. Engemann Denis A. Engemann +Denis A. Engemann Denis A. Engemann +Denis A. Engemann Denis A. Engemann +Denis A. Engemann Denis Engemann +Denis A. Engemann Denis Engemann +Dmitrii Altukhov dmalt +Dominik Krzemiński dokato +Dominik Welke dominikwelke <33089761+dominikwelke@users.noreply.github.com> +Dominik Welke dominikwelke +Dominik Wetzel Dominik Wetzel +Eberhard Eich ebeich +Eduard Ort Eduard Ort +Eduard Ort eort +Eduard Ort examplename +Ellen Lau ellenlau +Emily Stephen Emily P. Stephen +Emily Stephen emilyps14 +Emma Bailey <93327939+emma-bailey@users.noreply.github.com> emma-bailey <93327939+emma-bailey@users.noreply.github.com> +Emma Zhang <150376834+zhijingz@users.noreply.github.com> Emma <150376834+zhijingz@users.noreply.github.com> +Enrico Varano enricovara <69973551+enricovara@users.noreply.github.com> +Enzo Altamiranda enzo +Eric Larson Eric Larson +Eric Larson Eric Larson +Eric Larson Eric Larson +Eric Larson Eric89GXL +Eric Larson Eric89GXL +Erica Peterson nordme <38704848+nordme@users.noreply.github.com> +Erica Peterson nordme +Erik Hornberger er06645810 +Erik Hornberger Erik Hornberger +Erkka Heinila Teekuningas +Erkka Heinila Teekuningas +Etienne de Montalivet +Evgenii Kalenkovich kalenkovich +Evgeny Goldstein <84768107+evgenygoldstein@users.noreply.github.com> evgenygoldstein <84768107+evgenygoldstein@users.noreply.github.com> +Ezequiel Mikulan ezemikulan <39155887+ezemikulan@users.noreply.github.com> +Fahimeh Mamashli <33672431+fmamashli@users.noreply.github.com> fmamashli <33672431+fmamashli@users.noreply.github.com> +Fede Raimondo Fede +Fede Raimondo Fede Raimondo +Fede Raimondo Fede Raimondo +Fede Raimondo Fede Raimondo +Fede Raimondo Federico Raimondo +Fede Raimondo Federico Raimondo +Federico Zamberlan <44038765+fzamberlan@users.noreply.github.com> +Felix Klotzsche eioe +Felix Klotzsche eioe +Frederik D. Weber Frederik-D-Weber +Fu-Te Wong foucault +Fu-Te Wong zuxfoucault +Félix Raimundo Felix Raimundo +Gansheng Tan <49130176+GanshengT@users.noreply.github.com> Gansheng TAN <49130176+GanshengT@users.noreply.github.com> +Gennadiy Belonosov <7503709+Genuster@users.noreply.github.com> Gennadiy <7503709+Genuster@users.noreply.github.com> +Gennadiy Belonosov <7503709+Genuster@users.noreply.github.com> Genuster <7503709+Genuster@users.noreply.github.com> +Giorgio Marinato neurogima <76406896+neurogima@users.noreply.github.com> +Giulio Gabrieli +Guillaume Dumas deep-introspection +Guillaume Dumas Guillaume Dumas +Hakimeh Aslsardroud +Hamid Maymandi <46011104+HamidMandi@users.noreply.github.com> Hamid <46011104+HamidMandi@users.noreply.github.com> +Hasrat Ali Arzoo hasrat17 <56307533+hasrat17@users.noreply.github.com> +Hongjiang Ye YE Hongjiang +Hongjiang Ye YE Hongjiang +Hubert Banville hubertjb +Hyonyoung Shin <55095699+mcvain@users.noreply.github.com> mcvain <55095699+mcvain@users.noreply.github.com> +Hüseyin Orkun Elmas Hüseyin +Ingoo Lee dlsrnsi +Ivo de Jong ivopascal +Jaakko Leppakangas Jaakko Leppakangas +Jaakko Leppakangas jaeilepp +Jaakko Leppakangas jaeilepp +Jacob Phelan +Jair Montoya jmontoyam +Jan Ebert janEbert +Jan Sedivy +Jan Sosulski jsosulski +Jean-Baptiste Schiratti Jean-Baptiste SCHIRATTI +Jean-Rémi King Jean-Rémi KING +Jean-Rémi King kingjr +Jean-Rémi King kingjr +Jean-Rémi King kingjr +Jean-Rémi King UMR9752 +Jean-Rémi King UMR9752 +Jeff Stout jstout211 +Jennifer Behnke +Jesper Duemose Nielsen jdue +Jevri Hanna Jeff Hanna +Jevri Hanna Jevri Hanna +Joan Massich Joan Massich +Joan Massich massich +Johannes Kasper jeythekey <44215387+jeythekey@users.noreply.github.com> +John Samuelsson johnsam7 +John Veillette +Jon Houck Jon Houck +Jona Sassenhagen jona +Jona Sassenhagen Jona Sassenhagen +Jona Sassenhagen jona-sassenhagen +Jona Sassenhagen jona-sassenhagen +Jona Sassenhagen jona-sassenhagen@ +Jona Sassenhagen jona.sassenhagen@gmail.com +Jona Sassenhagen sassenha +Jonathan Kuziek +Jordan Drew <39603454+jadrew43@users.noreply.github.com> jadrew43 <39603454+jadrew43@users.noreply.github.com> +Joris Van den Bossche Joris Van den Bossche +Joshua Calder-Travis <38797399+jCalderTravis@users.noreply.github.com> jCalderTravis <38797399+jCalderTravis@users.noreply.github.com> +Joshua J Bear +Joshua Teves Joshua Teves +José C. García Alanis Jose Alanis +José C. García Alanis Jose C. G. Alanis <12409129+JoseAlanis@users.noreply.github.com> +José C. García Alanis José C. G. Alanis <12409129+JoseAlanis@users.noreply.github.com> +José C. García Alanis José C. García Alanis <12409129+JoseAlanis@users.noreply.github.com> +Julius Welzel <52565341+JuliusWelzel@users.noreply.github.com> jwelzel <52565341+JuliusWelzel@users.noreply.github.com> +Justus Schwabedal +Kaisu Lankinen <41806798+klankinen@users.noreply.github.com> klankinen <41806798+klankinen@users.noreply.github.com> +Kambiz Tabavi Kambiz Tavabi +Kambiz Tabavi kambysese +Katarina Slama katarinaslama +Katia Al-Amir <129207373+katia-sentry@users.noreply.github.com> Katia <129207373+katia-sentry@users.noreply.github.com> +Kostiantyn Maksymenko kostiantyn maksymenko +Kostiantyn Maksymenko Maksymenko Kostiantyn +Kostiantyn Maksymenko Maksymenko Kostiantyn +Laetitia Grabot LaetitiaG +Larry Eisenman lneisenman +Laurent Lementec +Lenny Varghese lennyvarghese +Liberty Hamilton +Lorenz Esch Lorenz Esch +Lorenzo Alfine lorrandal +Louis Thibault = +Louis Thibault Louis Thibault +Lukas Gemein gemeinl +Lukáš Hejtmánek hejtmy +Mads Jensen mads jensen +Mainak Jas Mainak +Mainak Jas Mainak Jas +Mainak Jas Mainak Jas +Mainak Jas Mainak Jas +Mainak Jas mainakjas +Manoj Kumar MechCoder +Manu Sutela MJAS1 +Marian Dovgialo Marian Dovgialo +Marian Dovgialo Marian Dovgialo +Marian Dovgialo mdovgialo +Marijn van Vliet Marijn van Vliet +Mark Henney Mark +Mark Henney Mark Alexander Henney +Mark Henney Mark Henney <120719655+henneysq@users.noreply.github.com> +Mark Wronkiewicz wronk +Marmaduke Woodman maedoc +Martin BaBer +Martin Billinger kazemakase +Martin Billinger kazemakase +Martin Billinger Martin Billinger +Martin Billinger mbillingr +Martin Luessi martin +Martin Luessi martin +Martin Luessi mluessi@nmr.mgh.harvard.edu +Martin Perez-Guevara +Martin Schulz Martin Schulz <46245704+marsipu@users.noreply.github.com> +Martin Schulz Martin Schulz +Martin van Harmelen <1544429+MPvHarmelen@users.noreply.github.com> Martin <1544429+MPvHarmelen@users.noreply.github.com> +Mathieu Scheltienne Mathieu Scheltienne <73893616+mscheltienne@users.noreply.github.com> +Mathieu Scheltienne Mathieu Scheltienne +Mathurin Massias mathurinm +Mathurin Massias mathurinm +Mats van Es Mats +Matt Sanderson monkeyman192 +Matteo Anelli Matteo Anelli +Matteo Visconti di Oleggio Castello Matteo Visconti dOC +Matthias Dold matthiasdold <62005770+matthiasdold@users.noreply.github.com> +Matthias Eberlein <41163089+MatthiasEb@users.noreply.github.com> MatthiasEb <41163089+MatthiasEb@users.noreply.github.com> +Matti Hämäläinen Matti Hamalainen +Matti Hämäläinen Matti Hamalainen +Matti Hämäläinen Matti Hämäläinen +Matti Hämäläinen mshamalainen +Matti Toivonen <105695400+mattitoi@users.noreply.github.com> mattitoi <105695400+mattitoi@users.noreply.github.com> +Maureen Shader <55732126+mshader@users.noreply.github.com> mshader <55732126+mshader@users.noreply.github.com> +Melih Yayli +Michiru Kaneda rcmdnk +Mikołaj Magnuski Mikolaj Magnuski +Mikołaj Magnuski mmagnuski +Mohamed Sherif mohdsherif +Mohammad Daneshzand <55800429+mdaneshzand@users.noreply.github.com> mdaneshzand <55800429+mdaneshzand@users.noreply.github.com> +Mojackhak <23111220065@m.fudan.edu.cn> Ankang Hu <23111220065@m.fudan.edu.cn> +Motofumi Fushimi <30593537+motofumi-fushimi@users.noreply.github.com> motofumi-fushimi <30593537+motofumi-fushimi@users.noreply.github.com> +Natalie Klein natalieklein +Nathalie Gayraud Nathalie +Nathalie Gayraud Nathalie +Natneal B +Naveen Srinivasan <172697+naveensrinivasan@users.noreply.github.com> Naveen <172697+naveensrinivasan@users.noreply.github.com> +Nicolas Barascud nbara +Nicolas Barascud Nicolas Barascud <10333715+nbara@users.noreply.github.com> +Nicolas Fourcaud-Trocmé Fourcaud-Trocmé +Nicolas Gensollen Gensollen +Nicolas Legrand Legrand Nicolas +Nicolas Legrand LegrandNico +Nicolas Legrand Nicolas Legrand +Niels Focke nmri-nfocke <114056301+nmri-nfocke@users.noreply.github.com> +Niklas Wilming Niklas Wilming +Nikolai Chapochnikov <23103092+chapochn@users.noreply.github.com> chapochn <23103092+chapochn@users.noreply.github.com> +Nikolai Chapochnikov <23103092+chapochn@users.noreply.github.com> Nikolai M Chapochnikov <23103092+chapochn@users.noreply.github.com> +Nikolas Chalas Nichalas +Noah Markowitz <34498671+nmarkowitz@users.noreply.github.com> NoahMarkowitz <34498671+nmarkowitz@users.noreply.github.com> +Olaf Hauk Olaf Hauk +Olaf Hauk olafhauk +Omer Shubi Omer S +Pablo Arias +Paul Pasler ppasler +Paul Roujansky Paul ROUJANSKY +Paul Roujansky paulroujansky +Pavel Navratil +Pedro Silva pbnsilva +Phillip Alday Phillip Alday +Phillip Alday Phillip Alday +Pierre Ablin pierreablin +Pierre-Antoine Bannier PAB +Pierre-Antoine Bannier Pierre-Antoine Bannier +Pierre-Antoine Bannier Pierre-Antoine Bannier +Pierre-Antoine Bannier Pierre-Antoine Bannier +Pierre-Antoine Bannier Pierre-Antoine Bannier +Ping-Keng Jao nafraw +Pragnya Khandelwal Pragnya +Pragnya Khandelwal PragnyaKhandelwal +Praveen Sripad prav +Praveen Sripad prav +Proloy Das pdas6 +Ram Pari Ram +Ramonapariciog Apariciogarcia ramonapariciog +Rasmus Aagaard roraa +Reza Nasri Reza +Reza Nasri RezaNasri +Riessarius Stargardsky +Roan LaPlante aestrivex +Robert Luke Robert Luke <748691+rob-luke@users.noreply.github.com> +Robert Luke Robert Luke +Robert Seymour +Robin Tibor Schirrmeister robintibor +Roeland Hancock +Romain Derollepot +Romain Trachel Romain Trachel +Romain Trachel Romain Trachel +Romain Trachel trachelr +Roman Goj +Rongfei Jin <131315c@gmail.com> GreasyCat <131315c@gmail.com> +Ross Maddox rkmaddox +Ross Maddox Ross Maddox +Ross Maddox unknown +Rotem Falach Falach +Roy Eric Wieske <139973278+Randomidous@users.noreply.github.com> Roy Eric <139973278+Randomidous@users.noreply.github.com> +Ryan Law Ryan Law +Ryan Law Ryan M.C. Law +Sammi Chekroud +Samuel Deslauriers-Gauthier Samuel Deslauriers-Gauthier +Santeri Ruuskanen Santeri Ruuskanen <66060772+ruuskas@users.noreply.github.com> +Santi Martínez szz-dvl +Sara Sommariva sarasommariva +Sebastien Treguer DataFox +Sena Er <2799280+sena-neuro@users.noreply.github.com> Sena <2799280+sena-neuro@users.noreply.github.com> +Senwen Deng <36327760+snwnde@users.noreply.github.com> Senwen DENG <36327760+snwnde@users.noreply.github.com> +Shristi Baral shristi +Silvia Cotroneo <78911192+sfc-neuro@users.noreply.github.com> sfc-neuro <78911192+sfc-neuro@users.noreply.github.com> +Simon Kern Simon Kern <14980558+skjerns@users.noreply.github.com> +Simon Kern skjerns <14980558+skjerns@users.noreply.github.com> +Simon Kern skjerns +Sondre Foslien sondrfos +Sophie Herbst +Steinn Hauser Magnússon Steinn Magnusson +Steve Matindi stevemats +Steven Bierer Steven Bierer <40672003+NeuroLaunch@users.noreply.github.com> +Steven M. Gutstein S. M. Gutstein +Steven M. Gutstein smgutstein +sviter +T. Wang twang5 <81429617+twang5@users.noreply.github.com> +Tanay Gahlot Tanay +Teon L Brooks +Teon L Brooks +Teon L Brooks Teon +Teon L Brooks Teon Brooks +Thomas Donoghue Tom +Thomas Radman +Timon Merk +Timon Merk Timon Merk <38216460+timonmerk@users.noreply.github.com> +Timon Merk timonmerk <38216460+timonmerk@users.noreply.github.com> +Timothy Gates Tim Gates +Timur Sokhin +Tod Flak <45362686+todflak@users.noreply.github.com> todflak <45362686+todflak@users.noreply.github.com> +Tom Ma myd7349 +Tom Stone Stone +Tom Stone tomdstone <77251489+tomdstone@users.noreply.github.com> +Tristan Stenner Tristan Stenner +Tziona NessAiver TzionaN +user27182 <89109579+user27182@users.noreply.github.com> +Valerii Chirkov Valerii <42982039+vagechirkov@users.noreply.github.com> +Valerii Chirkov Valerii +varshaa-1616 +Velu Prabhakar Kumaravel Velu Prabhakar Kumaravel +Victoria Peterson vpeterson +Wei Xu Wei +Will Turner Will Turner +Yiping Zuo Frostime +Yousra Bekhti Yoursa BEKHTI +Yousra Bekhti Yoursa BEKHTI +Yousra Bekhti Yousra BEKHTI +Yousra Bekhti yousrabk +Zhi Zhang <850734033@qq.com> ZHANG Zhi <850734033@qq.com> +Zhi Zhang <850734033@qq.com> ZHANG Zhi +Ziyi ZENG ZIYI ZENG diff --git a/mne-python/source/.pre-commit-config.yaml b/mne-python/source/.pre-commit-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..13bd7afdad93c5723895533341351c5796b3dfeb --- /dev/null +++ b/mne-python/source/.pre-commit-config.yaml @@ -0,0 +1,106 @@ +repos: + # Ruff mne + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.15.5 + hooks: + - id: ruff-check + name: ruff lint mne + args: ["--fix"] + files: ^mne/|^tools/ + exclude: vulture_allowlist.py + - id: ruff-check + name: ruff lint mne preview + args: ["--fix", "--preview", "--select=NPY201"] + files: ^mne/|^tools/ + - id: ruff-check + name: ruff lint doc, tutorials, and examples + # D103: missing docstring in public function + # D400: docstring first line must end with period + args: ["--ignore=D103,D400", "--fix"] + files: ^doc/|^tutorials/|^examples/ + - id: ruff-format + files: ^mne/|^doc/|^tutorials/|^examples/|^tools/ + + # Codespell + - repo: https://github.com/codespell-project/codespell + rev: v2.4.2 + hooks: + - id: codespell + additional_dependencies: + - tomli + files: ^mne/|^doc/|^examples/|^tutorials/|^tools/ + types_or: [python, bib, rst, inc] + + # yamllint + - repo: https://github.com/adrienverge/yamllint.git + rev: v1.38.0 + hooks: + - id: yamllint + args: [--strict, -c, .yamllint.yml] + + # rstcheck + - repo: https://github.com/rstcheck/rstcheck.git + rev: v6.2.5 + hooks: + - id: rstcheck + additional_dependencies: + - tomli + files: ^doc/.*\.(rst|inc)$ + # Credit is problematic because we generate an include on the fly + exclude: ^doc/credit.rst$ + + # sorting + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: file-contents-sorter + files: ^doc/changes/names.inc|^.mailmap|^doc/sphinxext/related_software.txt + args: ["--ignore-case"] + + - repo: https://github.com/pappasam/toml-sort + rev: v0.24.3 + hooks: + - id: toml-sort-fix + files: pyproject.toml + + # dependencies + - repo: local + hooks: + - id: update-env-file + name: Copy dependency changes from pyproject.toml to environment.yml + language: python + entry: ./tools/hooks/update_environment_file.py + files: '^(pyproject.toml|tools/hooks/update_environment_file.py)$' + - repo: local + hooks: + - id: dependency-sync + name: Copy core dependencies from pyproject.toml to README.rst + language: python + entry: ./tools/hooks/sync_dependencies.py + files: '^(pyproject.toml|tools/hooks/sync_dependencies.py)$' + additional_dependencies: ["mne==1.11.0"] + + # zizmor + - repo: https://github.com/woodruffw/zizmor-pre-commit + rev: v1.23.1 + hooks: + - id: zizmor + args: [--fix] + # We correctly use pull_request_trigger, and need Zizmor 2.0+ to configure the ignore + exclude: ^.github/workflows/automerge.yml + +# these should *not* be run on CIs: +ci: + skip: [dependency-sync] # needs MNE to work, which exceeds the free tier space alloc. + +# The following are too slow to run on local commits, so let's only run on CIs: +# +# - repo: https://github.com/pre-commit/mirrors-mypy +# rev: v1.9.0 +# hooks: +# - id: mypy +# +# - repo: https://github.com/jendrikseipp/vulture +# rev: 'v2.11' # or any later Vulture version +# hooks: +# - id: vulture diff --git a/mne-python/source/.yamllint.yml b/mne-python/source/.yamllint.yml new file mode 100644 index 0000000000000000000000000000000000000000..3b8f96c0e530bfe9c656d9940c163ad901b9e147 --- /dev/null +++ b/mne-python/source/.yamllint.yml @@ -0,0 +1,10 @@ +extends: default + +ignore: | + .github/workflows/codeql-analysis.yml + +rules: + line-length: disable + document-start: disable + new-lines: + type: platform diff --git a/mne-python/source/CITATION.cff b/mne-python/source/CITATION.cff new file mode 100644 index 0000000000000000000000000000000000000000..754d97877f63fb9f99b73fac2cf49ff0a24fce24 --- /dev/null +++ b/mne-python/source/CITATION.cff @@ -0,0 +1,877 @@ +cff-version: 1.2.0 +title: "MNE-Python" +message: "If you use this software, please cite both the software itself, and the paper listed in the preferred-citation field." +version: 1.11.0 +date-released: "2025-11-21" +commit: 07328a6a7fa974b24455e1ac333d7607b154f87c +doi: 10.5281/zenodo.592483 +keywords: + - MEG + - magnetoencephalography + - EEG + - electroencephalography + - fNIRS + - "functional near-infrared spectroscopy" + - iEEG + - "intracranial EEG" + - eCoG + - electrocorticography + - DBS + - "deep brain stimulation" +authors: + - family-names: Larson + given-names: Eric + - family-names: Gramfort + given-names: Alexandre + - family-names: Engemann + given-names: Denis A + - family-names: Leppakangas + given-names: Jaakko + - family-names: Brodbeck + given-names: Christian + - family-names: Jas + given-names: Mainak + - family-names: Brooks + given-names: Teon L + - family-names: Sassenhagen + given-names: Jona + - family-names: McCloy + given-names: Daniel + - family-names: Luessi + given-names: Martin + - family-names: King + given-names: Jean-Rémi + - family-names: Höchenberger + given-names: Richard + - family-names: Brunner + given-names: Clemens + - family-names: Goj + given-names: Roman + - family-names: Favelier + given-names: Guillaume + - family-names: van Vliet + given-names: Marijn + - family-names: Wronkiewicz + given-names: Mark + - family-names: Appelhoff + given-names: Stefan + - family-names: Rockhill + given-names: Alex + - family-names: Holdgraf + given-names: Chris + - family-names: Scheltienne + given-names: Mathieu + - family-names: Massich + given-names: Joan + - family-names: Bekhti + given-names: Yousra + - family-names: Leggitt + given-names: Alan + - family-names: Dykstra + given-names: Andrew + - family-names: Trachel + given-names: Romain + - family-names: Luke + given-names: Robert + - family-names: De Santis + given-names: Lorenzo + - family-names: Panda + given-names: Asish + - family-names: Magnuski + given-names: Mikołaj + - family-names: Westner + given-names: Britta + - family-names: Wakeman + given-names: Dan G + - family-names: Strohmeier + given-names: Daniel + - family-names: Bharadwaj + given-names: Hari + - family-names: Linzen + given-names: Tal + - family-names: Barachant + given-names: Alexandre + - family-names: Ruzich + given-names: Emily + - family-names: Huberty + given-names: Scott + - family-names: Bailey + given-names: Christopher J + - family-names: Li + given-names: Adam + - family-names: Moutard + given-names: Clément + - family-names: Bloy + given-names: Luke + - family-names: Raimondo + given-names: Fede + - family-names: Nurminen + given-names: Jussi + - family-names: Billinger + given-names: Martin + - family-names: Montoya + given-names: Jair + - family-names: Woodman + given-names: Marmaduke + - family-names: Lee + given-names: Ingoo + - family-names: Schulz + given-names: Martin + - family-names: Foti + given-names: Nick + - family-names: Nangini + given-names: Cathy + - family-names: García Alanis + given-names: José C + - family-names: Binns + given-names: Thomas S + - family-names: Orfanos + given-names: Dimitri Papadopoulos + - family-names: Hauk + given-names: Olaf + - family-names: Maddox + given-names: Ross + - family-names: LaPlante + given-names: Roan + - family-names: Drew + given-names: Ashley + - family-names: Dinh + given-names: Christoph + - family-names: Dumas + given-names: Guillaume + - name: Martin + - family-names: Benerradi + given-names: Johann + - family-names: Hartmann + given-names: Thomas + - family-names: Ort + given-names: Eduard + - family-names: Billinger + given-names: Martin + - family-names: Pasler + given-names: Paul + - family-names: Repplinger + given-names: Stefan + - family-names: Rudiuk + given-names: Alexander + - family-names: Radanovic + given-names: Ana + - family-names: Buran + given-names: Brad + - family-names: Woessner + given-names: Jacob + - family-names: Massias + given-names: Mathurin + - family-names: Hämäläinen + given-names: Matti + - family-names: Sripad + given-names: Praveen + - family-names: Chirkov + given-names: Valerii + - family-names: Mullins + given-names: Christopher + - family-names: Raimundo + given-names: Félix + - family-names: Belonosov + given-names: Gennadiy + - family-names: Kaneda + given-names: Michiru + - family-names: Alday + given-names: Phillip + - family-names: Pari + given-names: Ram + - family-names: Kornblith + given-names: Simon + - family-names: Halchenko + given-names: Yaroslav + - family-names: Luo + given-names: Yu-Han + - family-names: Gramfort + given-names: Alexandre + - family-names: Kasper + given-names: Johannes + - family-names: Doelling + given-names: Keith + - family-names: Jensen + given-names: Mads + - family-names: Ruuskanen + given-names: Santeri + - family-names: Kern + given-names: Simon + - family-names: Gahlot + given-names: Tanay + - family-names: Nunes + given-names: Adonay + - family-names: Gütlin + given-names: Dirk + - family-names: Heinila + given-names: Erkka + - family-names: Armeni + given-names: Kristijan + - name: kjs + - family-names: Weinstein + given-names: Alejandro + - family-names: Lamus + given-names: Camilo + - family-names: Galván + given-names: Catalina María + - family-names: Moënne-Loccoz + given-names: Cristóbal + - family-names: Altukhov + given-names: Dmitrii + - family-names: Peterson + given-names: Erica + - family-names: Hanna + given-names: Jevri + - family-names: Houck + given-names: Jon + - family-names: Klein + given-names: Natalie + - family-names: Roujansky + given-names: Paul + - family-names: Luke + given-names: Rob + - family-names: Rantala + given-names: Antti + - family-names: Maess + given-names: Burkhard + - family-names: Forster + given-names: Carina + - family-names: O'Reilly + given-names: Christian + - family-names: Welke + given-names: Dominik + - family-names: Welke + given-names: Dominik + - family-names: Kolkhorst + given-names: Henrich + - family-names: Banville + given-names: Hubert + - family-names: Zhang + given-names: Jack + - family-names: Maksymenko + given-names: Kostiantyn + - family-names: Clarke + given-names: Maggie + - family-names: Anelli + given-names: Matteo + - family-names: Straube + given-names: Michael + - family-names: Chapochnikov + given-names: Nikolai + - family-names: Bannier + given-names: Pierre-Antoine + - family-names: Choudhary + given-names: Saket + - family-names: Férat + given-names: Victor + - family-names: Kim + given-names: Cora + - family-names: Klotzsche + given-names: Felix + - family-names: Wong + given-names: Fu-Te + - family-names: Kojcic + given-names: Ivana + - family-names: Nielsen + given-names: Jesper Duemose + - family-names: Lankinen + given-names: Kaisu + - family-names: Tabavi + given-names: Kambiz + - family-names: Thibault + given-names: Louis + - family-names: Gerster + given-names: Moritz + - family-names: Alibou + given-names: Nabil + - family-names: Gayraud + given-names: Nathalie + - family-names: Ward + given-names: Nick + - family-names: Chu + given-names: Qian + - family-names: Herbst + given-names: Sophie + - family-names: Ma + given-names: Tom + - family-names: Radanovic + given-names: Ana + - family-names: Quinn + given-names: Andrew + - family-names: Gauthier + given-names: Antoine + - family-names: Pinsard + given-names: Basile + - family-names: Stephen + given-names: Emily + - family-names: Hornberger + given-names: Erik + - family-names: Hathaway + given-names: Evan + - family-names: Kalenkovich + given-names: Evgenii + - family-names: Mamashli + given-names: Fahimeh + - family-names: O'Neill + given-names: George + - family-names: Marinato + given-names: Giorgio + - family-names: Anevar + given-names: Hafeza + - family-names: Abdelhedi + given-names: Hamza + - family-names: Sosulski + given-names: Jan + - family-names: Stout + given-names: Jeff + - family-names: Calder-Travis + given-names: Joshua + - family-names: Zhu + given-names: Judy D + - family-names: Eisenman + given-names: Larry + - family-names: Esch + given-names: Lorenz + - family-names: Dovgialo + given-names: Marian + - family-names: Barascud + given-names: Nicolas + - family-names: Legrand + given-names: Nicolas + - family-names: Kapralov + given-names: Nikolai + - family-names: Molfese + given-names: Peter J + - family-names: Falach + given-names: Rotem + - family-names: Deslauriers-Gauthier + given-names: Samuel + - family-names: Cotroneo + given-names: Silvia + - family-names: Matindi + given-names: Steve + - family-names: Bierer + given-names: Steven + - family-names: Papadopoulo + given-names: Theodore + - family-names: Binns + given-names: Thomas Samuel + - family-names: Stenner + given-names: Tristan + - family-names: Peterson + given-names: Victoria + - family-names: Baratz + given-names: Zvi + - family-names: Tonin + given-names: Alessandro + - family-names: Kovrig + given-names: Alexander + - family-names: Pascarella + given-names: Annalisa + - family-names: Karekal + given-names: Apoorva + - family-names: Aristimunha + given-names: Bruno + - family-names: de la Torre + given-names: Carlos + - family-names: Gohil + given-names: Chetan + - family-names: Zhao + given-names: Christina + - family-names: Krzemiński + given-names: Dominik + - family-names: Makowski + given-names: Dominique + - family-names: Mikulan + given-names: Ezequiel + - family-names: Hofer + given-names: Florian + - family-names: Ritz + given-names: Harrison + - family-names: Schiratti + given-names: Jean-Baptiste + - family-names: Evans + given-names: Jen + - family-names: Herforth + given-names: Johannes + - family-names: Veillette + given-names: John + - family-names: Drew + given-names: Jordan + - family-names: Teves + given-names: Joshua + - family-names: Mathewson + given-names: Kyle + - family-names: Gwilliams + given-names: Laura + - family-names: Lementec + given-names: Laurent + - family-names: Varghese + given-names: Lenny + - family-names: Hamilton + given-names: Liberty + - family-names: Gemein + given-names: Lukas + - family-names: Hecker + given-names: Lukas + - name: Lx37 + - family-names: van Es + given-names: Mats + - family-names: Boggess + given-names: Matt + - family-names: Eberlein + given-names: Matthias + - family-names: Žák + given-names: Michal + - family-names: Sherif + given-names: Mohamed + - family-names: Kozhemiako + given-names: Nataliia + - family-names: Srinivasan + given-names: Naveen + - family-names: Wilming + given-names: Niklas + - family-names: Kozynets + given-names: Oleh + - family-names: Ablin + given-names: Pierre + - family-names: Das + given-names: Proloy + - family-names: Bertrand + given-names: Quentin + - family-names: Shoorangiz + given-names: Reza + - family-names: Scholz + given-names: Richard + - family-names: Hübner + given-names: Rodrigo + - family-names: Sommariva + given-names: Sara + - family-names: Er + given-names: Sena + - family-names: Khan + given-names: Sheraz + - family-names: Datta + given-names: Sumalyo + - family-names: Donoghue + given-names: Thomas + - family-names: Jochmann + given-names: Thomas + - family-names: Merk + given-names: Timon + - family-names: Flak + given-names: Tod + - family-names: Dupré la Tour + given-names: Tom + - family-names: NessAiver + given-names: Tziona + - name: akshay0724 + - name: sviter + - family-names: Earle-Richardson + given-names: Aaron + - family-names: Hindle + given-names: Abram + - family-names: Koutsou + given-names: Achilleas + - family-names: Fecker + given-names: Adeline + - family-names: Wagner + given-names: Adina + - family-names: Ciok + given-names: Alex + - family-names: Lepauvre + given-names: Alex + - family-names: Kiefer + given-names: Alexander + - family-names: Gilbert + given-names: Andy + - family-names: Pradhan + given-names: Aniket + - family-names: Padee + given-names: Anna + - family-names: Dubarry + given-names: Anne-Sophie + - family-names: Collas + given-names: Antoine + - family-names: Waniek + given-names: Anton Nikolas + - family-names: Singhal + given-names: Archit + - family-names: Rokem + given-names: Ariel + - family-names: Pelzer + given-names: Arne + - family-names: Hurst + given-names: Austin + - family-names: Jin + given-names: Beige Jerry + - family-names: Beasley + given-names: Ben + - family-names: Nicenboim + given-names: Bruno + - family-names: de la Torre + given-names: Carlos + - family-names: Clauss + given-names: Christian + - family-names: Mista + given-names: Christian + - family-names: Kechris + given-names: Christodoulos + - family-names: Li + given-names: Chun-Hui + - family-names: Braboszcz + given-names: Claire + - family-names: Schad + given-names: Daniel C + - family-names: Hasegan + given-names: Daniel + - family-names: Tse + given-names: Daniel + - family-names: Sleiter + given-names: Darin Erat + - family-names: Haslacher + given-names: David + - family-names: Sabbagh + given-names: David + - family-names: Kostas + given-names: Demetres + - family-names: Petkova + given-names: Desislava + - family-names: Issagaliyeva + given-names: Dinara + - family-names: Das + given-names: Diptyajit + - family-names: Wetzel + given-names: Dominik + - family-names: Eich + given-names: Eberhard + - family-names: DuPre + given-names: Elizabeth + - family-names: Lau + given-names: Ellen + - family-names: Olivetti + given-names: Emanuele + - family-names: Zhang + given-names: Emma + - family-names: Ferdman + given-names: Emmanuel + - family-names: Çelik + given-names: Emrecan + - family-names: Varano + given-names: Enrico + - family-names: Altamiranda + given-names: Enzo + - family-names: Brayet + given-names: Eric + - family-names: de Montalivet + given-names: Etienne + - family-names: Goldstein + given-names: Evgeny + - family-names: Mamashli + given-names: Fahimeh + - family-names: Negahbani + given-names: Farzin + - family-names: Zamberlan + given-names: Federico + - family-names: Pop + given-names: Florin + - family-names: Weber + given-names: Frederik D + - family-names: Tan + given-names: Gansheng + - family-names: Brookshire + given-names: Geoff + - family-names: O'Neill + given-names: George + - name: Giulio + - family-names: Reina + given-names: Gonzalo + - family-names: Maymandi + given-names: Hamid + - family-names: Arzoo + given-names: Hasrat Ali + - family-names: Sonntag + given-names: Hermann + - family-names: Ye + given-names: Hongjiang + - family-names: Shin + given-names: Hyonyoung + - family-names: Elmas + given-names: Hüseyin Orkun + - family-names: AZZ + given-names: Ilian + - family-names: Machairas + given-names: Ilias + - family-names: Zubarev + given-names: Ivan + - family-names: de Jong + given-names: Ivo + - family-names: Phelan + given-names: Jacob + - family-names: Kaczmarzyk + given-names: Jakub + - family-names: Zerfowski + given-names: Jan + - family-names: van den Bosch + given-names: Jasper J F + - family-names: Van Der Donckt + given-names: Jeroen + - family-names: van der Meer + given-names: Johan + - family-names: Niediek + given-names: Johannes + - family-names: Koen + given-names: Josh + - family-names: Bear + given-names: Joshua J + - family-names: Dammers + given-names: Juergen + - family-names: Galán + given-names: Julia Guiomar Niso + - family-names: Welzel + given-names: Julius + - family-names: Slama + given-names: Katarina + - family-names: Al-Amir + given-names: Katia + - family-names: Leinweber + given-names: Katrin + - family-names: Grabot + given-names: Laetitia + - family-names: Andersen + given-names: Lau Møller + - family-names: Almeida + given-names: Leonardo Rochael + - family-names: Barbosa + given-names: Leonardo S + - family-names: Alfine + given-names: Lorenzo + - family-names: Hejtmánek + given-names: Lukáš + - family-names: Balatsko + given-names: Maksym + - family-names: Kitzbichler + given-names: Manfred + - family-names: Kumar + given-names: Manoj + - family-names: Kadwani + given-names: Manorama + - family-names: Sutela + given-names: Manu + - family-names: Koculak + given-names: Marcin + - family-names: Henney + given-names: Mark + - family-names: BaBer + given-names: Martin + - family-names: Oberg + given-names: Martin + - family-names: van Harmelen + given-names: Martin + - family-names: Scheltienne + given-names: Mathieu + - family-names: Courtemanche + given-names: Matt + - family-names: Tucker + given-names: Matt + - family-names: Visconti di Oleggio Castello + given-names: Matteo + - family-names: Dold + given-names: Matthias + - family-names: Toivonen + given-names: Matti + - family-names: Shader + given-names: Maureen + - family-names: Cespedes + given-names: Mauricio + - family-names: Krause + given-names: Michael + - family-names: Rybář + given-names: Milan + - family-names: He + given-names: Mingjian + - family-names: Daneshzand + given-names: Mohammad + - name: Mojackhak + - family-names: Fourcaud-Trocmé + given-names: Nicolas + - family-names: Gensollen + given-names: Nicolas + - family-names: Proulx + given-names: Nicole + - family-names: Focke + given-names: Niels + - family-names: Chalas + given-names: Nikolas + - family-names: Markowitz + given-names: Noah + - family-names: Shubi + given-names: Omer + - family-names: Mainar + given-names: Pablo + - family-names: Sundaram + given-names: Padma + - family-names: Anders + given-names: Paul + - family-names: Silva + given-names: Pedro + - family-names: Guetschel + given-names: Pierre + - family-names: Li + given-names: Quanliang + - family-names: Barthélemy + given-names: Quentin + - family-names: Nadkarni + given-names: Rahul + - family-names: Gatti + given-names: Ramiro + - family-names: Apariciogarcia + given-names: Ramonapariciog + - family-names: Aagaard + given-names: Rasmus + - family-names: Nasri + given-names: Reza + - family-names: Koehler + given-names: Richard + - family-names: Stargardsky + given-names: Riessarius + - family-names: Oostenveld + given-names: Robert + - family-names: Seymour + given-names: Robert + - family-names: Schirrmeister + given-names: Robin Tibor + - family-names: Jin + given-names: Rongfei + - family-names: Wieske + given-names: Roy Eric + - family-names: Law + given-names: Ryan + - family-names: Pai + given-names: Sagun + - family-names: Perry + given-names: Sam + - family-names: Louviot + given-names: Samuel + - family-names: Martínez + given-names: Santi + - family-names: Saha + given-names: Sawradip + - family-names: Mathot + given-names: Sebastiaan + - family-names: Jentschke + given-names: Sebastian + - family-names: Major + given-names: Sebastian + - family-names: Treguer + given-names: Sebastien + - family-names: Castaño + given-names: Sebastián + - family-names: Deng + given-names: Senwen + - family-names: Antopolskiy + given-names: Sergey + - family-names: Shirazi + given-names: Seyed (Yahya) + - family-names: Keshari + given-names: Shresth + - family-names: Baral + given-names: Shristi + - family-names: Baral + given-names: Shristi + - family-names: Wong + given-names: Simeon + - family-names: Wong + given-names: Simeon + - family-names: Hofmann + given-names: Simon M + - family-names: Poil + given-names: Simon-Shlomo + - family-names: Foslien + given-names: Sondre + - family-names: Singh + given-names: Sourav + - family-names: Chambon + given-names: Stanislas + - family-names: Magnússon + given-names: Steinn Hauser + - family-names: Bethard + given-names: Steven + - family-names: Gutstein + given-names: Steven M + - family-names: Meyer + given-names: Svea Marie + - family-names: Wang + given-names: T + - family-names: Jayawardana + given-names: Tharupahan + - family-names: Moreau + given-names: Thomas + - family-names: Radman + given-names: Thomas + - family-names: Gates + given-names: Timothy + - family-names: Stone + given-names: Tom + - family-names: Clausner + given-names: Tommy + - family-names: Anijärv + given-names: Toomas Erik + - family-names: Kumaravel + given-names: Velu Prabhakar + - family-names: Xu + given-names: Wei + - family-names: Turner + given-names: Will + - family-names: Zuazo + given-names: Xabier de + - family-names: Xia + given-names: Xiaokai + - family-names: Zuo + given-names: Yiping + - family-names: Shen + given-names: Yixiao + - family-names: Truong + given-names: Young + - family-names: Zhang + given-names: Zhi + - family-names: ZENG + given-names: Ziyi + - name: btkcodedev + - name: buildqa + - name: luzpaz + - name: user27182 +preferred-citation: + title: "MEG and EEG Data Analysis with MNE-Python" + journal: "Frontiers in Neuroscience" + type: article + year: 2013 + volume: 7 + issue: 267 + start: 1 + end: 13 + doi: 10.3389/fnins.2013.00267 + authors: + - family-names: Gramfort + given-names: Alexandre + - family-names: Luessi + given-names: Martin + - family-names: Larson + given-names: Eric + - family-names: Engemann + given-names: Denis A. + - family-names: Strohmeier + given-names: Daniel + - family-names: Brodbeck + given-names: Christian + - family-names: Goj + given-names: Roman + - family-names: Jas + given-names: Mainak + - family-names: Brooks + given-names: Teon + - family-names: Parkkonen + given-names: Lauri + - family-names: Hämäläinen + given-names: Matti S. diff --git a/mne-python/source/CONTRIBUTING.md b/mne-python/source/CONTRIBUTING.md new file mode 100644 index 0000000000000000000000000000000000000000..e653797b3ada29f8fd1fb075bb3d2bcccfa89b22 --- /dev/null +++ b/mne-python/source/CONTRIBUTING.md @@ -0,0 +1,9 @@ +Contributing to MNE-Python +========================== + +MNE-Python is maintained by a community of scientists and research labs. The project accepts contributions in the form of bug reports, fixes, feature additions, and documentation improvements (including typo corrections). The best way to start contributing is by [opening an issue](https://github.com/mne-tools/mne-python/issues/new/choose) on our GitHub page to discuss ideas for changes or enhancements, or to tell us about behavior that you think might be a bug. For *general troubleshooting* or *usage questions*, please consider posting your questions on our [MNE Forum](https://mne.discourse.group). + +Users and contributors to MNE-Python are expected to follow our [code of conduct](https://github.com/mne-tools/.github/blob/main/CODE_OF_CONDUCT.md). + +The [contributing guide](https://mne.tools/dev/development/contributing.html) has details on the preferred contribution workflow +and the recommended system configuration for a smooth contribution/development experience. diff --git a/mne-python/source/LICENSE.txt b/mne-python/source/LICENSE.txt new file mode 100644 index 0000000000000000000000000000000000000000..8e4a81bec1eb1d1c38bef305216fae3323a3ffbf --- /dev/null +++ b/mne-python/source/LICENSE.txt @@ -0,0 +1,11 @@ +Copyright 2011-2025 MNE-Python authors + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/mne-python/source/Makefile b/mne-python/source/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3ce4eda956d496fa9a4a5ffd451f503d7ab84129 --- /dev/null +++ b/mne-python/source/Makefile @@ -0,0 +1,62 @@ +# simple makefile to simplify repetitive build env management tasks under posix + +PYTHON ?= python +PYTESTS ?= py.test +CODESPELL_SKIPS ?= "doc/_build,doc/auto_*,*.fif,*.eve,*.gz,*.tgz,*.zip,*.mat,*.stc,*.label,*.w,*.bz2,*.annot,*.sulc,*.log,*.local-copy,*.orig_avg,*.inflated_avg,*.gii,*.pyc,*.doctree,*.pickle,*.inv,*.png,*.edf,*.touch,*.thickness,*.nofix,*.volume,*.defect_borders,*.mgh,lh.*,rh.*,COR-*,FreeSurferColorLUT.txt,*.examples,.xdebug_mris_calc,bad.segments,BadChannels,*.hist,empty_file,*.orig,*.js,*.map,*.ipynb,searchindex.dat,install_mne_c.rst,plot_*.rst,*.rst.txt,c_EULA.rst*,*.html,gdf_encodes.txt,*.svg,references.bib,*.css,*.edf,*.bdf,*.vhdr" +CODESPELL_DIRS ?= mne/ doc/ tutorials/ examples/ +all: clean test-doc + +clean-pyc: + find . -name "*.pyc" | xargs rm -f + +clean-so: + find . -name "*.so" | xargs rm -f + find . -name "*.pyd" | xargs rm -f + +clean-build: + rm -rf build dist + +clean-ctags: + rm -f tags + +clean-cache: + find . -name "__pycache__" | xargs rm -rf + +clean: clean-build clean-pyc clean-so clean-ctags clean-cache + +wheel: + $(PYTHON) -m build -w + +sample_data: + @python -c "import mne; mne.datasets.sample.data_path(verbose=True);" + +testing_data: + @python -c "import mne; mne.datasets.testing.data_path(verbose=True);" + +test-no-network: in + sudo unshare -n -- sh -c 'MNE_SKIP_NETWORK_TESTS=1 py.test mne' + +test-no-testing-data: in + @MNE_SKIP_TESTING_DATASET_TESTS=true \ + $(PYTESTS) mne + +test-doc: sample_data testing_data + $(PYTESTS) --tb=short --cov=mne --cov-report=xml --cov-branch --doctest-modules --doctest-ignore-import-errors --doctest-glob='*.rst' ./doc/ --ignore=./doc/auto_examples --ignore=./doc/auto_tutorials --ignore=./doc/_build --ignore=./doc/conf.py --ignore=doc/sphinxext --fulltrace + +pre-commit: + @pre-commit run -a --show-diff-on-failure + +# Aliases for stuff we used to support or users might think of +ruff: pre-commit +flake: pre-commit +pep: pre-commit + +codespell: # running manually + @codespell --builtin clear,rare,informal,names,usage -w -i 3 -q 3 -S $(CODESPELL_SKIPS) --ignore-words=ignore_words.txt --uri-ignore-words-list=bu $(CODESPELL_DIRS) + +check-readme: clean wheel + twine check dist/* + +nesting: + @echo "Running import nesting tests" + @$(PYTESTS) mne/tests/test_import_nesting.py diff --git a/mne-python/source/README.rst b/mne-python/source/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..962887a4e62ebf22abd5aa166b5f7cb565544bc8 --- /dev/null +++ b/mne-python/source/README.rst @@ -0,0 +1,144 @@ +.. -*- mode: rst -*- + +|MNE| + +MNE-Python +========== + +MNE-Python is an open-source Python package for exploring, +visualizing, and analyzing human neurophysiological data such as MEG, EEG, sEEG, +ECoG, and more. It includes modules for data input/output, preprocessing, +visualization, source estimation, time-frequency analysis, connectivity analysis, +machine learning, statistics, and more. + + +Documentation +^^^^^^^^^^^^^ + +`Documentation`_ for MNE-Python encompasses installation instructions, tutorials, +and examples for a wide variety of topics, contributing guidelines, and an API +reference. + + +Forum +^^^^^^ + +The `user forum`_ is the best place to ask questions about MNE-Python usage or +the contribution process. The forum also features job opportunities and other +announcements. + +If you find a bug or have an idea for a new feature that should be added to +MNE-Python, please use the +`issue tracker `__ of +our GitHub repository. + + +Installation +^^^^^^^^^^^^ + +To install the latest stable version of MNE-Python with minimal dependencies +only, use pip_ in a terminal: + +.. code-block:: console + + $ pip install --upgrade mne + +For more complete instructions, including our standalone installers and more +advanced installation methods, please refer to the `installation guide`_. + + +Get the development version +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To install the latest development version of MNE-Python using pip_, open a +terminal and type: + +.. code-block:: console + + $ pip install --upgrade https://github.com/mne-tools/mne-python/archive/refs/heads/main.zip + +To clone the repository with `git `__, open a terminal +and type: + +.. code-block:: console + + $ git clone https://github.com/mne-tools/mne-python.git + + +Dependencies +^^^^^^^^^^^^ + +The minimum required dependencies to run MNE-Python are: + +.. ↓↓↓ BEGIN CORE DEPS LIST. DO NOT EDIT! HANDLED BY PRE-COMMIT HOOK ↓↓↓ + +- `Python `__ ≥ 3.10 +- `NumPy `__ ≥ 1.26 +- `SciPy `__ ≥ 1.11 +- `Matplotlib `__ ≥ 3.8 +- `Pooch `__ ≥ 1.5 +- `tqdm `__ +- `Jinja2 `__ +- `decorator `__ +- `lazy-loader `__ ≥ 0.3 +- `packaging `__ + +.. ↑↑↑ END CORE DEPS LIST. DO NOT EDIT! HANDLED BY PRE-COMMIT HOOK ↑↑↑ + +Contributing +^^^^^^^^^^^^ + +Please see the `contributing guidelines `__ on our documentation website. + + +About +^^^^^ + ++---------+------------+----------------+ +| CI | |Codecov| | |Bandit| | ++---------+------------+----------------+ +| Package | |PyPI| | |conda-forge| | ++---------+------------+----------------+ +| Docs | |Docs| | |Discourse| | ++---------+------------+----------------+ +| Meta | |Zenodo| | |OpenSSF| | ++---------+------------+----------------+ + + +License +^^^^^^^ + +MNE-Python is licensed under the BSD-3-Clause license. + + +.. _Documentation: https://mne.tools/dev/ +.. _user forum: https://mne.discourse.group +.. _installation guide: https://mne.tools/dev/install/index.html +.. _pip: https://pip.pypa.io/en/stable/ + +.. |PyPI| image:: https://img.shields.io/pypi/dm/mne.svg?label=PyPI + :target: https://pypi.org/project/mne/ + +.. |conda-forge| image:: https://img.shields.io/conda/dn/conda-forge/mne.svg?label=Conda + :target: https://anaconda.org/conda-forge/mne + +.. |Docs| image:: https://img.shields.io/badge/Docs-online-green?label=Documentation + :target: https://mne.tools/dev/ + +.. |Zenodo| image:: https://zenodo.org/badge/DOI/10.5281/zenodo.592483.svg + :target: https://doi.org/10.5281/zenodo.592483 + +.. |Discourse| image:: https://img.shields.io/discourse/status?label=Forum&server=https%3A%2F%2Fmne.discourse.group%2F + :target: https://mne.discourse.group/ + +.. |Codecov| image:: https://img.shields.io/codecov/c/github/mne-tools/mne-python?label=Coverage + :target: https://codecov.io/gh/mne-tools/mne-python + +.. |Bandit| image:: https://img.shields.io/badge/Security-Bandit-yellow.svg + :target: https://github.com/PyCQA/bandit + +.. |OpenSSF| image:: https://www.bestpractices.dev/projects/7783/badge + :target: https://www.bestpractices.dev/projects/7783 + +.. |MNE| image:: https://mne.tools/dev/_static/mne_logo_gray.svg + :target: https://mne.tools/dev/ diff --git a/mne-python/source/SECURITY.md b/mne-python/source/SECURITY.md new file mode 100644 index 0000000000000000000000000000000000000000..9d85763fbce26edd36f75ef7d4311640f4f95c2b --- /dev/null +++ b/mne-python/source/SECURITY.md @@ -0,0 +1,30 @@ +# Security Policy + +## Supported Versions + +New minor versions of MNE-Python are typically released twice per year. +Only the most current stable release is officially supported. +The unreleased, unstable "dev version" is also supported, though users +should beware that the API of the dev version is subject to change +without a proper 6-month deprecation cycle. + +| Version | Supported | +| ------- | ------------------------ | +| 1.12.x | :heavy_check_mark: (dev) | +| 1.11.x | :heavy_check_mark: | +| < 1.11 | :x: | + +## Reporting a Vulnerability + +MNE-Python is software for analysis and visualization of brain activity +recorded with a variety of devices/modalities (EEG, MEG, ECoG, fNIRS, etc). +It is not expected that using MNE-Python will lead to security +vulnerabilities under normal use cases (i.e., running without administrator +privileges). However, if you think you have found a security vulnerability +in MNE-Python, **please do not report it as a GitHub issue**, in order to +keep the vulnerability confidential. Instead, please report it to +mne-core-dev-team@groups.io and include a description and proof-of-concept +that is [short and self-contained](http://www.sscce.org/). + +Generally you will receive a response within one week. MNE-Python does not +award bounties for security vulnerabilities. diff --git a/mne-python/source/__init__.py b/mne-python/source/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..dceb0b266bf44075ee409b03fb53678a1b447db9 --- /dev/null +++ b/mne-python/source/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +""" +mne-python Project Package Initialization File +""" diff --git a/mne-python/source/azure-pipelines.yml b/mne-python/source/azure-pipelines.yml new file mode 100644 index 0000000000000000000000000000000000000000..d56cdf062fc7dc549a9bd6d1661020dc232dbfd3 --- /dev/null +++ b/mne-python/source/azure-pipelines.yml @@ -0,0 +1,303 @@ +trigger: + # start a new build for every push + batch: false + branches: + include: + - 'main' + - 'maint/*' +pr: + branches: + include: + - '*' # must quote since "*" is a YAML reserved character; we want a string + + +stages: + + - stage: Check + jobs: + - job: Skip + pool: + vmImage: 'ubuntu-latest' + variables: + DECODE_PERCENTS: 'false' + RET: 'true' + BUILD_REASON: $(Build.Reason) + steps: + - bash: | + git_log=`git log --format=oneline -n 1 --skip=1` + echo "##vso[task.setvariable variable=log]$git_log" + - bash: echo "##vso[task.setvariable variable=RET]false" + condition: and(eq(variables.BUILD_REASON, 'PullRequest'), or(contains(variables.log, '[skip azp]'), contains(variables.log, '[azp skip]'), contains(variables.log, '[skip ci]'), contains(variables.log, '[ci skip]'))) + - bash: echo "##vso[task.setvariable variable=start_main;isOutput=true]$RET" + name: result + + - stage: Style + variables: + AZURE_CI: 'true' + jobs: + - job: All + pool: + vmImage: 'ubuntu-latest' + variables: + PYTHON_VERSION: '3.11' + PYTHON_ARCH: 'x64' + steps: + - bash: echo $(COMMIT_MSG) + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PYTHON_VERSION) + architecture: $(PYTHON_ARCH) + addToPath: true + displayName: 'Get Python' + - bash: | + set -eo pipefail + python -m pip install --progress-bar off --upgrade pip build + python -m pip install --progress-bar off -ve .[hdf5] --group=test + python -m pip uninstall -yq pytest-qt # don't want to set up display, etc. for this + pre-commit install --install-hooks + displayName: Install dependencies + - bash: | + make pre-commit + displayName: make pre-commit + condition: always() + - bash: | + make nesting + displayName: make nesting + condition: always() + - bash: | + make check-readme + displayName: make check-readme + condition: always() + - bash: mypy + displayName: mypy + condition: always() + - bash: vulture + displayName: vulture + condition: always() + + + - stage: Test + condition: and(succeeded(), eq(dependencies.Check.outputs['Skip.result.start_main'], 'true')) + dependsOn: ['Style', 'Check'] + variables: + AZURE_CI: 'true' + jobs: + - job: Ultraslow_PG + pool: + vmImage: 'ubuntu-22.04' + variables: + DISPLAY: ':99' + OPENBLAS_NUM_THREADS: '1' + OMP_NUM_THREADS: '1' + MNE_TEST_ALLOW_SKIP: '^.*(PySide6 causes segfaults).*$' + MNE_BROWSER_PRECOMPUTE: 'false' + steps: + - bash: | + set -e + ./tools/setup_xvfb.sh + sudo apt install -yq tcsh + displayName: 'Install Ubuntu dependencies' + - bash: | + source tools/get_minimal_commands.sh + displayName: 'Install minimal commands' + - bash: | + echo $PATH + mne_surf2bem --version + fsl_rigid_register --version + displayName: 'Test minimal commands' + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.12' + architecture: 'x64' + addToPath: true + displayName: 'Get Python' + - bash: | + set -e + python -m pip install --progress-bar off --upgrade pip + python -m pip install --progress-bar off "mne-qt-browser[opengl] @ git+https://github.com/mne-tools/mne-qt-browser.git" pyvista scikit-learn python-picard qtpy nibabel sphinx-gallery "PySide6!=6.8.0,!=6.8.0.1,!=6.8.1.1,!=6.9.1" pandas neo pymatreader antio defusedxml curryreader pymef + python -m pip uninstall -yq mne + python -m pip install --progress-bar off --upgrade -e . --group=test + displayName: 'Install dependencies with pip' + - bash: | + set -e + mne sys_info -pd + mne sys_info -pd | grep "qtpy .*(PySide6=.*)$" + displayName: Print config + - bash: | + set -e + LD_DEBUG=libs python -c "from PySide6.QtWidgets import QApplication, QWidget; app = QApplication([]); import matplotlib; matplotlib.use('QtAgg'); import matplotlib.pyplot as plt; plt.figure()" + - bash: source tools/get_testing_version.sh + displayName: 'Get testing version' + - task: Cache@2 + inputs: + key: $(testing_version) + path: /home/vsts/mne_data + displayName: 'Cache testing data' + - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)" + displayName: 'Get test data' + - script: pytest -m "ultraslowtest or pgtest" --tb=short --cov=mne --cov-report=xml -vv mne + displayName: 'slow and mne-qt-browser tests' + # Coverage + - bash: bash <(curl -s https://codecov.io/bash) + displayName: 'Codecov' + condition: succeededOrFailed() + - task: PublishTestResults@2 + inputs: + testResultsFiles: '**/junit-*.xml' + testRunTitle: 'Publish test results for $(Agent.JobName)' + failTaskOnFailedTests: true + condition: succeededOrFailed() + - task: PublishCodeCoverageResults@2 + inputs: + summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' + + - job: Qt + pool: + vmImage: 'ubuntu-22.04' + variables: + DISPLAY: ':99' + OPENBLAS_NUM_THREADS: '1' + TEST_OPTIONS: "--tb=short --cov=mne --cov-report=xml --cov-append -vv mne/viz/_brain mne/viz/backends mne/viz/tests/test_evoked.py mne/gui mne/report" + MNE_TEST_ALLOW_SKIP: '^.*(PySide6 causes segfaults).*$' + steps: + - bash: ./tools/setup_xvfb.sh + displayName: 'Install Ubuntu dependencies' + - task: UsePythonVersion@0 + inputs: + versionSpec: '3.10' + architecture: 'x64' + addToPath: true + displayName: 'Get Python' + - bash: | + set -e + python -m pip install --progress-bar off --upgrade pip + python -m pip install --progress-bar off --upgrade --pre --only-binary=\"numpy,scipy,matplotlib,vtk\" numpy scipy matplotlib vtk + python -c "import vtk" + python -m pip install --progress-bar off --upgrade -ve .[full] --group=test_extra + displayName: 'Install dependencies with pip' + - bash: | + set -e + which mne + mne sys_info -pd + python ./tools/check_mne_location.py + displayName: Print config + - bash: source tools/get_testing_version.sh + displayName: 'Get testing version' + - task: Cache@2 + inputs: + key: $(testing_version) + path: /home/vsts/mne_data + displayName: 'Cache testing data' + - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)" + displayName: 'Get test data' + - bash: | + set -eo pipefail + python -m pip install PyQt6 + LD_DEBUG=libs python -c "from PyQt6.QtWidgets import QApplication, QWidget; app = QApplication([]); import matplotlib; matplotlib.use('QtAgg'); import matplotlib.pyplot as plt; plt.figure()" + displayName: 'Check Qt import' + - bash: | + set -eo pipefail + mne sys_info -pd + mne sys_info -pd | grep "qtpy .* (PyQt6=.*)$" + PYTEST_QT_API=PyQt6 pytest -m "not ultraslowtest" ${TEST_OPTIONS} + python -m pip uninstall -yq PyQt6 PyQt6-sip PyQt6-Qt6 + displayName: 'PyQt6' + - bash: | + set -eo pipefail + python -m pip install "PySide6!=6.8.0,!=6.8.0.1,!=6.9.1" + mne sys_info -pd + mne sys_info -pd | grep "qtpy .* (PySide6=.*)$" + PYTEST_QT_API=PySide6 pytest -m "not ultraslowtest" ${TEST_OPTIONS} + python -m pip uninstall -yq PySide6 + displayName: 'PySide6' + # PyQt5 leaves cruft behind, so run it last + - bash: | + set -eo pipefail + python -m pip install PyQt5 + mne sys_info -pd + mne sys_info -pd | grep "qtpy .* (PyQt5=.*)$" + PYTEST_QT_API=PyQt5 pytest -m "not ultraslowtest" ${TEST_OPTIONS} + python -m pip uninstall -yq PyQt5 PyQt5-sip PyQt5-Qt5 + displayName: 'PyQt5' + # Coverage + - bash: bash <(curl -s https://codecov.io/bash) + displayName: 'Codecov' + condition: succeededOrFailed() + - task: PublishTestResults@2 + inputs: + testResultsFiles: '**/junit-*.xml' + testRunTitle: 'Publish test results for $(Agent.JobName)' + failTaskOnFailedTests: true + condition: succeededOrFailed() + - task: PublishCodeCoverageResults@2 + inputs: + summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' + + - job: Windows + pool: + vmImage: 'windows-latest' + variables: + MNE_LOGGING_LEVEL: 'warning' + MNE_FORCE_SERIAL: 'true' + OPENBLAS_NUM_THREADS: '2' + OMP_DYNAMIC: 'false' + PYTHONUNBUFFERED: 1 + PYTHONIOENCODING: 'utf-8' + AZURE_CI_WINDOWS: 'true' + PYTHON_ARCH: 'x64' + MNE_CI_KIND: $(TEST_MODE) + timeoutInMinutes: 95 + strategy: + maxParallel: 4 + matrix: + 3.10 pip: + TEST_MODE: 'pip' + PYTHON_VERSION: '3.10' + 3.13 pip pre: + TEST_MODE: 'pip-pre' + PYTHON_VERSION: '3.13' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PYTHON_VERSION) + architecture: $(PYTHON_ARCH) + addToPath: true + displayName: 'Get Python' + - bash: | + set -eo pipefail + git clone --depth 1 https://github.com/pyvista/setup-headless-display-action.git + MESA3D_VERSION=24.3.0 bash setup-headless-display-action/windows/install_opengl.sh + displayName: Install OpenGL + - bash: ./tools/azure_dependencies.sh + displayName: Install dependencies with pip + - script: pip install -e . + displayName: 'Install MNE-Python dev' + - script: mne sys_info -pd + displayName: 'Print config' + - script: python -c "import numpy; numpy.show_config()" + displayName: Print NumPy config + - script: python -c "import numpy; import scipy.linalg; import sklearn.neighbors; from threadpoolctl import threadpool_info; from pprint import pprint; pprint(threadpool_info())" + displayName: Print threadpoolctl info + - bash: source tools/get_testing_version.sh + displayName: 'Get testing version' + - task: Cache@2 + inputs: + key: $(testing_version) + path: C:\Users\VssAdministrator\mne_data + displayName: 'Cache testing data' + - script: python -c "import mne; mne.datasets.testing.data_path(verbose=True)" + displayName: 'Get test data' + - script: pytest -m "not (slowtest or pgtest)" --tb=short --cov=mne --cov-report=xml -vv mne + displayName: 'Run tests' + - bash: bash <(curl -s https://codecov.io/bash) + displayName: 'Codecov' + condition: succeededOrFailed() + - task: PublishTestResults@2 + inputs: + testResultsFiles: '**/junit-*.xml' + testRunTitle: 'Publish test results for $(Agent.JobName) $(TEST_MODE) $(PYTHON_VERSION)' + failTaskOnFailedTests: true + condition: succeededOrFailed() + - task: PublishCodeCoverageResults@2 + inputs: + summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/coverage.xml' diff --git a/mne-python/source/codecov.yml b/mne-python/source/codecov.yml new file mode 100644 index 0000000000000000000000000000000000000000..408f379cd31b55b4717ea896e0c8eb5bf1f2496d --- /dev/null +++ b/mne-python/source/codecov.yml @@ -0,0 +1,25 @@ +comment: false +github_checks: # too noisy, even though "a" interactively disables them + annotations: false + +codecov: + notify: + require_ci_to_pass: false + +coverage: + status: + patch: + default: + informational: true + target: 95% + if_no_uploads: error + if_not_found: success + if_ci_failed: failure + project: + default: false + library: + informational: true + target: 90% + if_no_uploads: error + if_not_found: success + if_ci_failed: failure diff --git a/mne-python/source/codemeta.json b/mne-python/source/codemeta.json new file mode 100644 index 0000000000000000000000000000000000000000..ddcef37bc38988e4b0d76253bf96eea73ae2cfd8 --- /dev/null +++ b/mne-python/source/codemeta.json @@ -0,0 +1,2555 @@ +{ + "@context": "https://doi.org/10.5063/schema/codemeta-2.0", + "@type": "SoftwareSourceCode", + "license": "https://spdx.org/licenses/BSD-3-Clause", + "codeRepository": "git+https://github.com/mne-tools/mne-python.git", + "dateCreated": "2010-12-26", + "datePublished": "2014-08-04", + "dateModified": "2025-11-21", + "downloadUrl": "https://github.com/mne-tools/mne-python/archive/v1.11.0.zip", + "issueTracker": "https://github.com/mne-tools/mne-python/issues", + "name": "MNE-Python", + "version": "1.11.0", + "description": "MNE-Python is an open-source Python package for exploring, visualizing, and analyzing human neurophysiological data. It provides methods for data input/output, preprocessing, visualization, source estimation, time-frequency analysis, connectivity analysis, machine learning, and statistics.", + "applicationCategory": "Neuroscience", + "developmentStatus": "active", + "referencePublication": "https://doi.org/10.3389/fnins.2013.00267", + "keywords": [ + "MEG", + "magnetoencephalography", + "EEG", + "electroencephalography", + "fNIRS", + "functional near-infrared spectroscopy", + "iEEG", + "intracranial EEG", + "eCoG", + "electrocorticography", + "DBS", + "deep brain stimulation" + ], + "programmingLanguage": [ + "Python" + ], + "operatingSystem": [ + "Linux", + "Windows", + "macOS" + ], + "softwareRequirements": [ + "python>= 3.10", + "decorator", + "jinja2", + "lazy_loader >= 0.3", + "matplotlib >= 3.8", + "numpy >= 1.26, < 3", + "packaging", + "pooch >= 1.5", + "scipy >= 1.11", + "tqdm" + ], + "author": [ + { + "@type":"Person", + "email":"larson.eric.d@gmail.com", + "givenName":"Eric", + "familyName": "Larson" + }, + { + "@type":"Person", + "email":"alexandre.gramfort@inria.fr", + "givenName":"Alexandre", + "familyName": "Gramfort" + }, + { + "@type":"Person", + "email":"denis.engemann@gmail.com", + "givenName":"Denis A", + "familyName": "Engemann" + }, + { + "@type":"Person", + "email":"jaeilepp@gmail.com", + "givenName":"Jaakko", + "familyName": "Leppakangas" + }, + { + "@type":"Person", + "email":"christianmbrodbeck@gmail.com", + "givenName":"Christian", + "familyName": "Brodbeck" + }, + { + "@type":"Person", + "email":"mainakjas@gmail.com", + "givenName":"Mainak", + "familyName": "Jas" + }, + { + "@type":"Person", + "email":"teon.brooks@gmail.com", + "givenName":"Teon L", + "familyName": "Brooks" + }, + { + "@type":"Person", + "email":"jona.sassenhagen@gmail.com", + "givenName":"Jona", + "familyName": "Sassenhagen" + }, + { + "@type":"Person", + "email":"dan@mccloy.info", + "givenName":"Daniel", + "familyName": "McCloy" + }, + { + "@type":"Person", + "email":"mluessi@nmr.mgh.harvard.edu", + "givenName":"Martin", + "familyName": "Luessi" + }, + { + "@type":"Person", + "email":"jeanremi.king+github@gmail.com", + "givenName":"Jean-Rémi", + "familyName": "King" + }, + { + "@type":"Person", + "email":"richard.hoechenberger@gmail.com", + "givenName":"Richard", + "familyName": "Höchenberger" + }, + { + "@type":"Person", + "email":"clemens.brunner@gmail.com", + "givenName":"Clemens", + "familyName": "Brunner" + }, + { + "@type":"Person", + "email":"roman.goj@gmail.com", + "givenName":"Roman", + "familyName": "Goj" + }, + { + "@type":"Person", + "email":"guillaume.favelier@gmail.com", + "givenName":"Guillaume", + "familyName": "Favelier" + }, + { + "@type":"Person", + "email":"w.m.vanvliet@gmail.com", + "givenName":"Marijn", + "familyName": "van Vliet" + }, + { + "@type":"Person", + "email":"wronk.mark@gmail.com", + "givenName":"Mark", + "familyName": "Wronkiewicz" + }, + { + "@type":"Person", + "email":"stefan.appelhoff@mailbox.org", + "givenName":"Stefan", + "familyName": "Appelhoff" + }, + { + "@type":"Person", + "email":"aprockhill206@gmail.com", + "givenName":"Alex", + "familyName": "Rockhill" + }, + { + "@type":"Person", + "email":"choldgraf@gmail.com", + "givenName":"Chris", + "familyName": "Holdgraf" + }, + { + "@type":"Person", + "email":"mathieu.scheltienne@gmail.com", + "givenName":"Mathieu", + "familyName": "Scheltienne" + }, + { + "@type":"Person", + "email":"mailsik@gmail.com", + "givenName":"Joan", + "familyName": "Massich" + }, + { + "@type":"Person", + "email":"yousra.bekhti@gmail.com", + "givenName":"Yousra", + "familyName": "Bekhti" + }, + { + "@type":"Person", + "email":"leggitta3@gmail.com", + "givenName":"Alan", + "familyName": "Leggitt" + }, + { + "@type":"Person", + "email":"andrew.r.dykstra@gmail.com", + "givenName":"Andrew", + "familyName": "Dykstra" + }, + { + "@type":"Person", + "email":"romain.trachel@inria.fr", + "givenName":"Romain", + "familyName": "Trachel" + }, + { + "@type":"Person", + "email":"code@robertluke.net", + "givenName":"Robert", + "familyName": "Luke" + }, + { + "@type":"Person", + "email":"desantis.lnz@gmail.com", + "givenName":"Lorenzo", + "familyName": "De Santis" + }, + { + "@type":"Person", + "email":"asishrocks95@gmail.com", + "givenName":"Asish", + "familyName": "Panda" + }, + { + "@type":"Person", + "email":"mmagnuski@swps.edu.pl", + "givenName":"Mikołaj", + "familyName": "Magnuski" + }, + { + "@type":"Person", + "email":"britta.wstnr@gmail.com", + "givenName":"Britta", + "familyName": "Westner" + }, + { + "@type":"Person", + "email":"dgwakeman@gmail.com", + "givenName":"Dan G", + "familyName": "Wakeman" + }, + { + "@type":"Person", + "email":"daniel.strohmeier@googlemail.com", + "givenName":"Daniel", + "familyName": "Strohmeier" + }, + { + "@type":"Person", + "email":"hari@nmr.mgh.harvard.edu", + "givenName":"Hari", + "familyName": "Bharadwaj" + }, + { + "@type":"Person", + "email":"tal.linzen@gmail.com", + "givenName":"Tal", + "familyName": "Linzen" + }, + { + "@type":"Person", + "email":"alexandre.barachant@gmail.com", + "givenName":"Alexandre", + "familyName": "Barachant" + }, + { + "@type":"Person", + "email":"emilyr@nmr.mgh.harvard.edu", + "givenName":"Emily", + "familyName": "Ruzich" + }, + { + "@type":"Person", + "email":"", + "givenName":"Scott", + "familyName": "Huberty" + }, + { + "@type":"Person", + "email":"bailey.cj@gmail.com", + "givenName":"Christopher J", + "familyName": "Bailey" + }, + { + "@type":"Person", + "email":"adam2392@gmail.com", + "givenName":"Adam", + "familyName": "Li" + }, + { + "@type":"Person", + "email":"clement.moutard@gmail.com", + "givenName":"Clément", + "familyName": "Moutard" + }, + { + "@type":"Person", + "email":"luke.bloy@gmail.com", + "givenName":"Luke", + "familyName": "Bloy" + }, + { + "@type":"Person", + "email":"federaimondo@gmail.com", + "givenName":"Fede", + "familyName": "Raimondo" + }, + { + "@type":"Person", + "email":"jnu@iki.fi", + "givenName":"Jussi", + "familyName": "Nurminen" + }, + { + "@type":"Person", + "email":"flKazemakase@gmail.com", + "givenName":"Martin", + "familyName": "Billinger" + }, + { + "@type":"Person", + "email":"montoya.jair.m@gmail.com", + "givenName":"Jair", + "familyName": "Montoya" + }, + { + "@type":"Person", + "email":"mmwoodman@gmail.com", + "givenName":"Marmaduke", + "familyName": "Woodman" + }, + { + "@type":"Person", + "email":"dlsrnsladlek@naver.com", + "givenName":"Ingoo", + "familyName": "Lee" + }, + { + "@type":"Person", + "email":"dev@mgschulz.de", + "givenName":"Martin", + "familyName": "Schulz" + }, + { + "@type":"Person", + "email":"nfoti01@gmail.com", + "givenName":"Nick", + "familyName": "Foti" + }, + { + "@type":"Person", + "email":"cnangini@gmail.com", + "givenName":"Cathy", + "familyName": "Nangini" + }, + { + "@type":"Person", + "email":"joialanisson@gmail.com", + "givenName":"José C", + "familyName": "García Alanis" + }, + { + "@type":"Person", + "email":"t.s.binns@outlook.com", + "givenName":"Thomas S", + "familyName": "Binns" + }, + { + "@type":"Person", + "email":"", + "givenName":"Dimitri Papadopoulos", + "familyName": "Orfanos" + }, + { + "@type":"Person", + "email":"olaf.hauk@mrc-cbu.cam.ac.uk", + "givenName":"Olaf", + "familyName": "Hauk" + }, + { + "@type":"Person", + "email":"ross.maddox@rochester.edu", + "givenName":"Ross", + "familyName": "Maddox" + }, + { + "@type":"Person", + "email":"aestrivex@gmail.com", + "givenName":"Roan", + "familyName": "LaPlante" + }, + { + "@type":"Person", + "email":"ashdrew@uw.edu", + "givenName":"Ashley", + "familyName": "Drew" + }, + { + "@type":"Person", + "email":"chdinh@nmr.mgh.harvard.edu", + "givenName":"Christoph", + "familyName": "Dinh" + }, + { + "@type":"Person", + "email":"deep@introspection.eu", + "givenName":"Guillaume", + "familyName": "Dumas" + }, + { + "@type":"Person", + "email":"martin.billinger@tugraz.at", + "givenName":"", + "familyName": "Martin" + }, + { + "@type":"Person", + "email":"johann.benerradi@gmail.com", + "givenName":"Johann", + "familyName": "Benerradi" + }, + { + "@type":"Person", + "email":"thomas.hartmann@th-ht.de", + "givenName":"Thomas", + "familyName": "Hartmann" + }, + { + "@type":"Person", + "email":"eduardxort@gmail.com", + "givenName":"Eduard", + "familyName": "Ort" + }, + { + "@type":"Person", + "email":"flkazemakase@gmail.com", + "givenName":"Martin", + "familyName": "Billinger" + }, + { + "@type":"Person", + "email":"paul@ppasler.de", + "givenName":"Paul", + "familyName": "Pasler" + }, + { + "@type":"Person", + "email":"stefan.repplinger@posteo.net", + "givenName":"Stefan", + "familyName": "Repplinger" + }, + { + "@type":"Person", + "email":"alxanderr@gmail.com", + "givenName":"Alexander", + "familyName": "Rudiuk" + }, + { + "@type":"Person", + "email":"anaradanovica@gmail.com", + "givenName":"Ana", + "familyName": "Radanovic" + }, + { + "@type":"Person", + "email":"bburan@galenea.com", + "givenName":"Brad", + "familyName": "Buran" + }, + { + "@type":"Person", + "email":"Woessner.jacob@gmail.com", + "givenName":"Jacob", + "familyName": "Woessner" + }, + { + "@type":"Person", + "email":"mathurin.massias@gmail.com", + "givenName":"Mathurin", + "familyName": "Massias" + }, + { + "@type":"Person", + "email":"msh@nmr.mgh.harvard.edu", + "givenName":"Matti", + "familyName": "Hämäläinen" + }, + { + "@type":"Person", + "email":"pravsripad@gmail.com", + "givenName":"Praveen", + "familyName": "Sripad" + }, + { + "@type":"Person", + "email":"vagechirkov@gmail.com", + "givenName":"Valerii", + "familyName": "Chirkov" + }, + { + "@type":"Person", + "email":"christopherrmullins@gmail.com", + "givenName":"Christopher", + "familyName": "Mullins" + }, + { + "@type":"Person", + "email":"gamaz3ps@gmail.com", + "givenName":"Félix", + "familyName": "Raimundo" + }, + { + "@type":"Person", + "email":"", + "givenName":"Gennadiy", + "familyName": "Belonosov" + }, + { + "@type":"Person", + "email":"rcmdnk@gmail.com", + "givenName":"Michiru", + "familyName": "Kaneda" + }, + { + "@type":"Person", + "email":"phillip.alday@mpi.nl", + "givenName":"Phillip", + "familyName": "Alday" + }, + { + "@type":"Person", + "email":"ramsbam@gmail.com", + "givenName":"Ram", + "familyName": "Pari" + }, + { + "@type":"Person", + "email":"simon@simonster.com", + "givenName":"Simon", + "familyName": "Kornblith" + }, + { + "@type":"Person", + "email":"debian@onerussian.com", + "givenName":"Yaroslav", + "familyName": "Halchenko" + }, + { + "@type":"Person", + "email":"yuhanluo1994@gmail.com", + "givenName":"Yu-Han", + "familyName": "Luo" + }, + { + "@type":"Person", + "email":"agramfort@fb.com", + "givenName":"Alexandre", + "familyName": "Gramfort" + }, + { + "@type":"Person", + "email":"jeythekey@tutanota.com", + "givenName":"Johannes", + "familyName": "Kasper" + }, + { + "@type":"Person", + "email":"kd889@nyu.edu", + "givenName":"Keith", + "familyName": "Doelling" + }, + { + "@type":"Person", + "email":"mje.mads@gmail.com", + "givenName":"Mads", + "familyName": "Jensen" + }, + { + "@type":"Person", + "email":"santeri.ruuskanen@aalto.fi", + "givenName":"Santeri", + "familyName": "Ruuskanen" + }, + { + "@type":"Person", + "email":"simon.kern@online.de", + "givenName":"Simon", + "familyName": "Kern" + }, + { + "@type":"Person", + "email":"tanaygahlot@gmail.com", + "givenName":"Tanay", + "familyName": "Gahlot" + }, + { + "@type":"Person", + "email":"adonay.s.nunes@gmail.com", + "givenName":"Adonay", + "familyName": "Nunes" + }, + { + "@type":"Person", + "email":"", + "givenName":"Dirk", + "familyName": "Gütlin" + }, + { + "@type":"Person", + "email":"erkkahe@gmail.com", + "givenName":"Erkka", + "familyName": "Heinila" + }, + { + "@type":"Person", + "email":"kristijan.armeni@gmail.com", + "givenName":"Kristijan", + "familyName": "Armeni" + }, + { + "@type":"Person", + "email":"kjs@llama", + "givenName":"", + "familyName": "kjs" + }, + { + "@type":"Person", + "email":"alejandro.weinstein@gmail.com", + "givenName":"Alejandro", + "familyName": "Weinstein" + }, + { + "@type":"Person", + "email":"camilo@neurostat.mit.edu", + "givenName":"Camilo", + "familyName": "Lamus" + }, + { + "@type":"Person", + "email":"", + "givenName":"Catalina María", + "familyName": "Galván" + }, + { + "@type":"Person", + "email":"cmmoenne@gmail.com", + "givenName":"Cristóbal", + "familyName": "Moënne-Loccoz" + }, + { + "@type":"Person", + "email":"dm.altukhov@ya.ru", + "givenName":"Dmitrii", + "familyName": "Altukhov" + }, + { + "@type":"Person", + "email":"nordme@uw.edu", + "givenName":"Erica", + "familyName": "Peterson" + }, + { + "@type":"Person", + "email":"jevri.hanna@gmail.com", + "givenName":"Jevri", + "familyName": "Hanna" + }, + { + "@type":"Person", + "email":"jon.houck@gmail.com", + "givenName":"Jon", + "familyName": "Houck" + }, + { + "@type":"Person", + "email":"neklein@andrew.cmu.edu", + "givenName":"Natalie", + "familyName": "Klein" + }, + { + "@type":"Person", + "email":"paul@roujansky.eu", + "givenName":"Paul", + "familyName": "Roujansky" + }, + { + "@type":"Person", + "email":"code@robertluke.net", + "givenName":"Rob", + "familyName": "Luke" + }, + { + "@type":"Person", + "email":"antti.rantala90@gmail.com", + "givenName":"Antti", + "familyName": "Rantala" + }, + { + "@type":"Person", + "email":"burkhard.maess@arcor.de", + "givenName":"Burkhard", + "familyName": "Maess" + }, + { + "@type":"Person", + "email":"carinaforster0611@gmail.com", + "givenName":"Carina", + "familyName": "Forster" + }, + { + "@type":"Person", + "email":"christian.oreilly@gmail.com", + "givenName":"Christian", + "familyName": "O'Reilly" + }, + { + "@type":"Person", + "email":"dominik.welke@ae.mpg.de", + "givenName":"Dominik", + "familyName": "Welke" + }, + { + "@type":"Person", + "email":"dominik.welke@web.de", + "givenName":"Dominik", + "familyName": "Welke" + }, + { + "@type":"Person", + "email":"", + "givenName":"Henrich", + "familyName": "Kolkhorst" + }, + { + "@type":"Person", + "email":"hubert.jbanville@gmail.com", + "givenName":"Hubert", + "familyName": "Banville" + }, + { + "@type":"Person", + "email":"zhangmengyu10@gmail.com", + "givenName":"Jack", + "familyName": "Zhang" + }, + { + "@type":"Person", + "email":"makkostya@ukr.net", + "givenName":"Kostiantyn", + "familyName": "Maksymenko" + }, + { + "@type":"Person", + "email":"mdclarke@uw.edu", + "givenName":"Maggie", + "familyName": "Clarke" + }, + { + "@type":"Person", + "email":"matteo.anelli@aalto.fi", + "givenName":"Matteo", + "familyName": "Anelli" + }, + { + "@type":"Person", + "email":"michael.straube.d@gmail.com", + "givenName":"Michael", + "familyName": "Straube" + }, + { + "@type":"Person", + "email":"", + "givenName":"Nikolai", + "familyName": "Chapochnikov" + }, + { + "@type":"Person", + "email":"pierreantoine.bannier@gmail.com", + "givenName":"Pierre-Antoine", + "familyName": "Bannier" + }, + { + "@type":"Person", + "email":"saketkc@gmail.com", + "givenName":"Saket", + "familyName": "Choudhary" + }, + { + "@type":"Person", + "email":"victor.ferat@live.Fr", + "givenName":"Victor", + "familyName": "Férat" + }, + { + "@type":"Person", + "email":"kimjico@gmail.com", + "givenName":"Cora", + "familyName": "Kim" + }, + { + "@type":"Person", + "email":"klotzsche@cbs.mpg.de", + "givenName":"Felix", + "familyName": "Klotzsche" + }, + { + "@type":"Person", + "email":"zuxfoucault@gmail.com", + "givenName":"Fu-Te", + "familyName": "Wong" + }, + { + "@type":"Person", + "email":"", + "givenName":"Ivana", + "familyName": "Kojcic" + }, + { + "@type":"Person", + "email":"jdue@dtu.dk", + "givenName":"Jesper Duemose", + "familyName": "Nielsen" + }, + { + "@type":"Person", + "email":"", + "givenName":"Kaisu", + "familyName": "Lankinen" + }, + { + "@type":"Person", + "email":"ktavabi@gmail.com", + "givenName":"Kambiz", + "familyName": "Tabavi" + }, + { + "@type":"Person", + "email":"louist87@gmail.com", + "givenName":"Louis", + "familyName": "Thibault" + }, + { + "@type":"Person", + "email":"", + "givenName":"Moritz", + "familyName": "Gerster" + }, + { + "@type":"Person", + "email":"", + "givenName":"Nabil", + "familyName": "Alibou" + }, + { + "@type":"Person", + "email":"nathalie.gayraud@inria.fr", + "givenName":"Nathalie", + "familyName": "Gayraud" + }, + { + "@type":"Person", + "email":"ward.nickjames@gmail.com", + "givenName":"Nick", + "familyName": "Ward" + }, + { + "@type":"Person", + "email":"", + "givenName":"Qian", + "familyName": "Chu" + }, + { + "@type":"Person", + "email":"ksherbst@gmail.com", + "givenName":"Sophie", + "familyName": "Herbst" + }, + { + "@type":"Person", + "email":"myd7349@gmail.com", + "givenName":"Tom", + "familyName": "Ma" + }, + { + "@type":"Person", + "email":"", + "givenName":"Ana", + "familyName": "Radanovic" + }, + { + "@type":"Person", + "email":"", + "givenName":"Andrew", + "familyName": "Quinn" + }, + { + "@type":"Person", + "email":"antoine.gauthier@ensta.fr", + "givenName":"Antoine", + "familyName": "Gauthier" + }, + { + "@type":"Person", + "email":"basile.pinsard@umontreal.ca", + "givenName":"Basile", + "familyName": "Pinsard" + }, + { + "@type":"Person", + "email":"emilyps14@gmail.com", + "givenName":"Emily", + "familyName": "Stephen" + }, + { + "@type":"Person", + "email":"erik.hornberger@shi-g.com", + "givenName":"Erik", + "familyName": "Hornberger" + }, + { + "@type":"Person", + "email":"", + "givenName":"Evan", + "familyName": "Hathaway" + }, + { + "@type":"Person", + "email":"e.kalenkovich@gmail.com", + "givenName":"Evgenii", + "familyName": "Kalenkovich" + }, + { + "@type":"Person", + "email":"", + "givenName":"Fahimeh", + "familyName": "Mamashli" + }, + { + "@type":"Person", + "email":"g.o'neill@ucl.ac.uk", + "givenName":"George", + "familyName": "O'Neill" + }, + { + "@type":"Person", + "email":"giorgio.marinato@unitn.it", + "givenName":"Giorgio", + "familyName": "Marinato" + }, + { + "@type":"Person", + "email":"hafiza.taj@gmail.com", + "givenName":"Hafeza", + "familyName": "Anevar" + }, + { + "@type":"Person", + "email":"hamza.abdelhedii@gmail.com", + "givenName":"Hamza", + "familyName": "Abdelhedi" + }, + { + "@type":"Person", + "email":"mail@jan-sosulski.de", + "givenName":"Jan", + "familyName": "Sosulski" + }, + { + "@type":"Person", + "email":"stoutjd@nih.gov", + "givenName":"Jeff", + "familyName": "Stout" + }, + { + "@type":"Person", + "email":"", + "givenName":"Joshua", + "familyName": "Calder-Travis" + }, + { + "@type":"Person", + "email":"", + "givenName":"Judy D", + "familyName": "Zhu" + }, + { + "@type":"Person", + "email":"leisenman@wustl.edu", + "givenName":"Larry", + "familyName": "Eisenman" + }, + { + "@type":"Person", + "email":"Lorenz.Esch@tu-ilmenau.de", + "givenName":"Lorenz", + "familyName": "Esch" + }, + { + "@type":"Person", + "email":"marian.dowgialo@gmail.com", + "givenName":"Marian", + "familyName": "Dovgialo" + }, + { + "@type":"Person", + "email":"", + "givenName":"Nicolas", + "familyName": "Barascud" + }, + { + "@type":"Person", + "email":"legrand@cyceron.fr", + "givenName":"Nicolas", + "familyName": "Legrand" + }, + { + "@type":"Person", + "email":"4dvlup@gmail.com", + "givenName":"Nikolai", + "familyName": "Kapralov" + }, + { + "@type":"Person", + "email":"pmolfese@gmail.com", + "givenName":"Peter J", + "familyName": "Molfese" + }, + { + "@type":"Person", + "email":"falachrotem@gmail.com", + "givenName":"Rotem", + "familyName": "Falach" + }, + { + "@type":"Person", + "email":"sam.deslauriers@gmail.com", + "givenName":"Samuel", + "familyName": "Deslauriers-Gauthier" + }, + { + "@type":"Person", + "email":"", + "givenName":"Silvia", + "familyName": "Cotroneo" + }, + { + "@type":"Person", + "email":"stevematindi@gmail.com", + "givenName":"Steve", + "familyName": "Matindi" + }, + { + "@type":"Person", + "email":"neurolaunch@gmail.copm", + "givenName":"Steven", + "familyName": "Bierer" + }, + { + "@type":"Person", + "email":"Theodore.Papadopoulo@inria.fr", + "givenName":"Theodore", + "familyName": "Papadopoulo" + }, + { + "@type":"Person", + "email":"t.s.binns@outlook.com", + "givenName":"Thomas Samuel", + "familyName": "Binns" + }, + { + "@type":"Person", + "email":"ttstenner@gmail.com", + "givenName":"Tristan", + "familyName": "Stenner" + }, + { + "@type":"Person", + "email":"victoriapeterson09@gmail.com", + "givenName":"Victoria", + "familyName": "Peterson" + }, + { + "@type":"Person", + "email":"z.baratz@gmail.com", + "givenName":"Zvi", + "familyName": "Baratz" + }, + { + "@type":"Person", + "email":"alessandro.tonin@wysscenter.ch", + "givenName":"Alessandro", + "familyName": "Tonin" + }, + { + "@type":"Person", + "email":"alexander.kovrig@gmail.com", + "givenName":"Alexander", + "familyName": "Kovrig" + }, + { + "@type":"Person", + "email":"a.pascarella@iac.cnr.it", + "givenName":"Annalisa", + "familyName": "Pascarella" + }, + { + "@type":"Person", + "email":"", + "givenName":"Apoorva", + "familyName": "Karekal" + }, + { + "@type":"Person", + "email":"b.aristimunha@gmail.com", + "givenName":"Bruno", + "familyName": "Aristimunha" + }, + { + "@type":"Person", + "email":"", + "givenName":"Carlos", + "familyName": "de la Torre" + }, + { + "@type":"Person", + "email":"", + "givenName":"Chetan", + "familyName": "Gohil" + }, + { + "@type":"Person", + "email":"zhaotc@uw.edu", + "givenName":"Christina", + "familyName": "Zhao" + }, + { + "@type":"Person", + "email":"raymon92@gmail.com", + "givenName":"Dominik", + "familyName": "Krzemiński" + }, + { + "@type":"Person", + "email":"dom.mak19@gmail.com", + "givenName":"Dominique", + "familyName": "Makowski" + }, + { + "@type":"Person", + "email":"e.mikulan@gmail.com", + "givenName":"Ezequiel", + "familyName": "Mikulan" + }, + { + "@type":"Person", + "email":"hofaflo@gmail.com", + "givenName":"Florian", + "familyName": "Hofer" + }, + { + "@type":"Person", + "email":"harrison.ritz@gmail.com", + "givenName":"Harrison", + "familyName": "Ritz" + }, + { + "@type":"Person", + "email":"jean.baptiste.schiratti@gmail.com", + "givenName":"Jean-Baptiste", + "familyName": "Schiratti" + }, + { + "@type":"Person", + "email":"", + "givenName":"Jen", + "familyName": "Evans" + }, + { + "@type":"Person", + "email":"johannes@herforth.net", + "givenName":"Johannes", + "familyName": "Herforth" + }, + { + "@type":"Person", + "email":"johnv@uchicago.edu", + "givenName":"John", + "familyName": "Veillette" + }, + { + "@type":"Person", + "email":"", + "givenName":"Jordan", + "familyName": "Drew" + }, + { + "@type":"Person", + "email":"jbtevespro@gmail.com", + "givenName":"Joshua", + "familyName": "Teves" + }, + { + "@type":"Person", + "email":"kylemath@gmail.com", + "givenName":"Kyle", + "familyName": "Mathewson" + }, + { + "@type":"Person", + "email":"lgwilliams90@gmail.com", + "givenName":"Laura", + "familyName": "Gwilliams" + }, + { + "@type":"Person", + "email":"laurent.lementec@gmail.com", + "givenName":"Laurent", + "familyName": "Lementec" + }, + { + "@type":"Person", + "email":"", + "givenName":"Lenny", + "familyName": "Varghese" + }, + { + "@type":"Person", + "email":"", + "givenName":"Liberty", + "familyName": "Hamilton" + }, + { + "@type":"Person", + "email":"lukas.gemein@gmx.de", + "givenName":"Lukas", + "familyName": "Gemein" + }, + { + "@type":"Person", + "email":"", + "givenName":"Lukas", + "familyName": "Hecker" + }, + { + "@type":"Person", + "email":"capmanip@DESKTOP-TLIFEG1.localdomain", + "givenName":"", + "familyName": "Lx37" + }, + { + "@type":"Person", + "email":"mats.vanes@psych.ox.ac.uk", + "givenName":"Mats", + "familyName": "van Es" + }, + { + "@type":"Person", + "email":"", + "givenName":"Matt", + "familyName": "Boggess" + }, + { + "@type":"Person", + "email":"", + "givenName":"Matthias", + "familyName": "Eberlein" + }, + { + "@type":"Person", + "email":"", + "givenName":"Michal", + "familyName": "Žák" + }, + { + "@type":"Person", + "email":"molpsychistb@gmail.com", + "givenName":"Mohamed", + "familyName": "Sherif" + }, + { + "@type":"Person", + "email":"natakozh22@gmail.com", + "givenName":"Nataliia", + "familyName": "Kozhemiako" + }, + { + "@type":"Person", + "email":"", + "givenName":"Naveen", + "familyName": "Srinivasan" + }, + { + "@type":"Person", + "email":"niklas.wilming@gmail.com", + "givenName":"Niklas", + "familyName": "Wilming" + }, + { + "@type":"Person", + "email":"", + "givenName":"Oleh", + "familyName": "Kozynets" + }, + { + "@type":"Person", + "email":"pierreablin@gmail.com", + "givenName":"Pierre", + "familyName": "Ablin" + }, + { + "@type":"Person", + "email":"proloy@umd.edu", + "givenName":"Proloy", + "familyName": "Das" + }, + { + "@type":"Person", + "email":"quentinbertrand54@gmail.com", + "givenName":"Quentin", + "familyName": "Bertrand" + }, + { + "@type":"Person", + "email":"r.shoorangiz@live.com", + "givenName":"Reza", + "familyName": "Shoorangiz" + }, + { + "@type":"Person", + "email":"", + "givenName":"Richard", + "familyName": "Scholz" + }, + { + "@type":"Person", + "email":"rhubner@gmail.com", + "givenName":"Rodrigo", + "familyName": "Hübner" + }, + { + "@type":"Person", + "email":"sommariva@dima.unige.it", + "givenName":"Sara", + "familyName": "Sommariva" + }, + { + "@type":"Person", + "email":"", + "givenName":"Sena", + "familyName": "Er" + }, + { + "@type":"Person", + "email":"sheraz@nmr.mgh.harvard.edu", + "givenName":"Sheraz", + "familyName": "Khan" + }, + { + "@type":"Person", + "email":"", + "givenName":"Sumalyo", + "familyName": "Datta" + }, + { + "@type":"Person", + "email":"tdonoghue.research@gmail.com", + "givenName":"Thomas", + "familyName": "Donoghue" + }, + { + "@type":"Person", + "email":"", + "givenName":"Thomas", + "familyName": "Jochmann" + }, + { + "@type":"Person", + "email":"timon.merk@charite.de", + "givenName":"Timon", + "familyName": "Merk" + }, + { + "@type":"Person", + "email":"", + "givenName":"Tod", + "familyName": "Flak" + }, + { + "@type":"Person", + "email":"tom.dupre-la-tour@m4x.org", + "givenName":"Tom", + "familyName": "Dupré la Tour" + }, + { + "@type":"Person", + "email":"tzionan@mail.tau.ac.il", + "givenName":"Tziona", + "familyName": "NessAiver" + }, + { + "@type":"Person", + "email":"akshay0724@gmail.com", + "givenName":"", + "familyName": "akshay0724" + }, + { + "@type":"Person", + "email":"sviter33@gmail.com", + "givenName":"", + "familyName": "sviter" + }, + { + "@type":"Person", + "email":"Jakdaxter31@gmail.com", + "givenName":"Aaron", + "familyName": "Earle-Richardson" + }, + { + "@type":"Person", + "email":"abram.hindle@softwareprocess.es", + "givenName":"Abram", + "familyName": "Hindle" + }, + { + "@type":"Person", + "email":"achilleas.k@gmail.com", + "givenName":"Achilleas", + "familyName": "Koutsou" + }, + { + "@type":"Person", + "email":"", + "givenName":"Adeline", + "familyName": "Fecker" + }, + { + "@type":"Person", + "email":"adina.wagner@t-online.de", + "givenName":"Adina", + "familyName": "Wagner" + }, + { + "@type":"Person", + "email":"", + "givenName":"Alex", + "familyName": "Ciok" + }, + { + "@type":"Person", + "email":"alex.lepauvre@ae.mpg.de", + "givenName":"Alex", + "familyName": "Lepauvre" + }, + { + "@type":"Person", + "email":"", + "givenName":"Alexander", + "familyName": "Kiefer" + }, + { + "@type":"Person", + "email":"7andy121@gmail.com", + "givenName":"Andy", + "familyName": "Gilbert" + }, + { + "@type":"Person", + "email":"aniket17133@iiitd.ac.in", + "givenName":"Aniket", + "familyName": "Pradhan" + }, + { + "@type":"Person", + "email":"anna.padee@gmail.com", + "givenName":"Anna", + "familyName": "Padee" + }, + { + "@type":"Person", + "email":"as_dub@hotmail.com", + "givenName":"Anne-Sophie", + "familyName": "Dubarry" + }, + { + "@type":"Person", + "email":"contact@antoinecollas.fr", + "givenName":"Antoine", + "familyName": "Collas" + }, + { + "@type":"Person", + "email":"", + "givenName":"Anton Nikolas", + "familyName": "Waniek" + }, + { + "@type":"Person", + "email":"", + "givenName":"Archit", + "familyName": "Singhal" + }, + { + "@type":"Person", + "email":"arokem@gmail.com", + "givenName":"Ariel", + "familyName": "Rokem" + }, + { + "@type":"Person", + "email":"arne.pelzer@idmt.fraunhofer.de", + "givenName":"Arne", + "familyName": "Pelzer" + }, + { + "@type":"Person", + "email":"mynameisaustinhurst@gmail.com", + "givenName":"Austin", + "familyName": "Hurst" + }, + { + "@type":"Person", + "email":"", + "givenName":"Beige Jerry", + "familyName": "Jin" + }, + { + "@type":"Person", + "email":"code@musicinmybrain.net", + "givenName":"Ben", + "familyName": "Beasley" + }, + { + "@type":"Person", + "email":"bruno.nicenboim@gmail.com", + "givenName":"Bruno", + "familyName": "Nicenboim" + }, + { + "@type":"Person", + "email":"ctorre@mailbox.org", + "givenName":"Carlos", + "familyName": "de la Torre" + }, + { + "@type":"Person", + "email":"cclauss@me.com", + "givenName":"Christian", + "familyName": "Clauss" + }, + { + "@type":"Person", + "email":"cmista@ingenieria.uner.edu.ar", + "givenName":"Christian", + "familyName": "Mista" + }, + { + "@type":"Person", + "email":"kechrisc@gmail.com", + "givenName":"Christodoulos", + "familyName": "Kechris" + }, + { + "@type":"Person", + "email":"", + "givenName":"Chun-Hui", + "familyName": "Li" + }, + { + "@type":"Person", + "email":"claire@guakamole.org", + "givenName":"Claire", + "familyName": "Braboszcz" + }, + { + "@type":"Person", + "email":"daniel.c.schad@protonmail.com", + "givenName":"Daniel C", + "familyName": "Schad" + }, + { + "@type":"Person", + "email":"danielhasegan@gmail.com", + "givenName":"Daniel", + "familyName": "Hasegan" + }, + { + "@type":"Person", + "email":"xiezhibin.0.0.superman@gmail.com", + "givenName":"Daniel", + "familyName": "Tse" + }, + { + "@type":"Person", + "email":"darin.sleiter@gmail.com", + "givenName":"Darin Erat", + "familyName": "Sleiter" + }, + { + "@type":"Person", + "email":"haslacherdavid@gmail.com", + "givenName":"David", + "familyName": "Haslacher" + }, + { + "@type":"Person", + "email":"dav.sabbagh@gmail.com", + "givenName":"David", + "familyName": "Sabbagh" + }, + { + "@type":"Person", + "email":"", + "givenName":"Demetres", + "familyName": "Kostas" + }, + { + "@type":"Person", + "email":"desislavka@gmail.com", + "givenName":"Desislava", + "familyName": "Petkova" + }, + { + "@type":"Person", + "email":"", + "givenName":"Dinara", + "familyName": "Issagaliyeva" + }, + { + "@type":"Person", + "email":"", + "givenName":"Diptyajit", + "familyName": "Das" + }, + { + "@type":"Person", + "email":"dimonok@web.de", + "givenName":"Dominik", + "familyName": "Wetzel" + }, + { + "@type":"Person", + "email":"e.eich@fz-juelich.de", + "givenName":"Eberhard", + "familyName": "Eich" + }, + { + "@type":"Person", + "email":"emd222@cornell.edu", + "givenName":"Elizabeth", + "familyName": "DuPre" + }, + { + "@type":"Person", + "email":"ellenlau@umd.edu", + "givenName":"Ellen", + "familyName": "Lau" + }, + { + "@type":"Person", + "email":"emanuele@relativita.com", + "givenName":"Emanuele", + "familyName": "Olivetti" + }, + { + "@type":"Person", + "email":"", + "givenName":"Emma", + "familyName": "Zhang" + }, + { + "@type":"Person", + "email":"emmanuelferdman@gmail.com", + "givenName":"Emmanuel", + "familyName": "Ferdman" + }, + { + "@type":"Person", + "email":"emrecncelik@gmail.com", + "givenName":"Emrecan", + "familyName": "Çelik" + }, + { + "@type":"Person", + "email":"enricovarano@gmail.com", + "givenName":"Enrico", + "familyName": "Varano" + }, + { + "@type":"Person", + "email":"enzo.alt@gmail.com", + "givenName":"Enzo", + "familyName": "Altamiranda" + }, + { + "@type":"Person", + "email":"eric.brayet@mybraintech.com", + "givenName":"Eric", + "familyName": "Brayet" + }, + { + "@type":"Person", + "email":"", + "givenName":"Etienne", + "familyName": "de Montalivet" + }, + { + "@type":"Person", + "email":"", + "givenName":"Evgeny", + "familyName": "Goldstein" + }, + { + "@type":"Person", + "email":"fmamashli@gmail.com", + "givenName":"Fahimeh", + "familyName": "Mamashli" + }, + { + "@type":"Person", + "email":"farzin.negahbani@gmail.com", + "givenName":"Farzin", + "familyName": "Negahbani" + }, + { + "@type":"Person", + "email":"", + "givenName":"Federico", + "familyName": "Zamberlan" + }, + { + "@type":"Person", + "email":"florinpop@me.com", + "givenName":"Florin", + "familyName": "Pop" + }, + { + "@type":"Person", + "email":"", + "givenName":"Frederik D", + "familyName": "Weber" + }, + { + "@type":"Person", + "email":"", + "givenName":"Gansheng", + "familyName": "Tan" + }, + { + "@type":"Person", + "email":"Geoff.Brookshire@gmail.com", + "givenName":"Geoff", + "familyName": "Brookshire" + }, + { + "@type":"Person", + "email":"george.oneill.90@gmail.com", + "givenName":"George", + "familyName": "O'Neill" + }, + { + "@type":"Person", + "email":"gack94@gmail.com", + "givenName":"", + "familyName": "Giulio" + }, + { + "@type":"Person", + "email":"", + "givenName":"Gonzalo", + "familyName": "Reina" + }, + { + "@type":"Person", + "email":"", + "givenName":"Hamid", + "familyName": "Maymandi" + }, + { + "@type":"Person", + "email":"hasrat407@gmail.com", + "givenName":"Hasrat Ali", + "familyName": "Arzoo" + }, + { + "@type":"Person", + "email":"hermann.sonntag@gmail.com", + "givenName":"Hermann", + "familyName": "Sonntag" + }, + { + "@type":"Person", + "email":"rubyyhj@gmail.com", + "givenName":"Hongjiang", + "familyName": "Ye" + }, + { + "@type":"Person", + "email":"", + "givenName":"Hyonyoung", + "familyName": "Shin" + }, + { + "@type":"Person", + "email":"huseyinorkunelmas@gmail.com", + "givenName":"Hüseyin Orkun", + "familyName": "Elmas" + }, + { + "@type":"Person", + "email":"", + "givenName":"Ilian", + "familyName": "AZZ" + }, + { + "@type":"Person", + "email":"", + "givenName":"Ilias", + "familyName": "Machairas" + }, + { + "@type":"Person", + "email":"ivan.zubarev@aalto.fi", + "givenName":"Ivan", + "familyName": "Zubarev" + }, + { + "@type":"Person", + "email":"ivopascal@gmail.com", + "givenName":"Ivo", + "familyName": "de Jong" + }, + { + "@type":"Person", + "email":"jacob.phelan.jp@gmail.com", + "givenName":"Jacob", + "familyName": "Phelan" + }, + { + "@type":"Person", + "email":"", + "givenName":"Jakub", + "familyName": "Kaczmarzyk" + }, + { + "@type":"Person", + "email":"", + "givenName":"Jan", + "familyName": "Zerfowski" + }, + { + "@type":"Person", + "email":"japsai@gmail.com", + "givenName":"Jasper J F", + "familyName": "van den Bosch" + }, + { + "@type":"Person", + "email":"", + "givenName":"Jeroen", + "familyName": "Van Der Donckt" + }, + { + "@type":"Person", + "email":"johanvandermeer@gmail.com", + "givenName":"Johan", + "familyName": "van der Meer" + }, + { + "@type":"Person", + "email":"", + "givenName":"Johannes", + "familyName": "Niediek" + }, + { + "@type":"Person", + "email":"koen.joshua@gmail.com", + "givenName":"Josh", + "familyName": "Koen" + }, + { + "@type":"Person", + "email":"", + "givenName":"Joshua J", + "familyName": "Bear" + }, + { + "@type":"Person", + "email":"j.dammers@fz-juelich.de", + "givenName":"Juergen", + "familyName": "Dammers" + }, + { + "@type":"Person", + "email":"guiomar.niso@ctb.upm.es", + "givenName":"Julia Guiomar Niso", + "familyName": "Galán" + }, + { + "@type":"Person", + "email":"", + "givenName":"Julius", + "familyName": "Welzel" + }, + { + "@type":"Person", + "email":"slama@berkeley.edu", + "givenName":"Katarina", + "familyName": "Slama" + }, + { + "@type":"Person", + "email":"", + "givenName":"Katia", + "familyName": "Al-Amir" + }, + { + "@type":"Person", + "email":"", + "givenName":"Katrin", + "familyName": "Leinweber" + }, + { + "@type":"Person", + "email":"laetitia.grabot@gmail.com", + "givenName":"Laetitia", + "familyName": "Grabot" + }, + { + "@type":"Person", + "email":"ualsbombe@protonmail.com", + "givenName":"Lau Møller", + "familyName": "Andersen" + }, + { + "@type":"Person", + "email":"leorochael@gmail.com", + "givenName":"Leonardo Rochael", + "familyName": "Almeida" + }, + { + "@type":"Person", + "email":"lsbarbosa@gmail.com", + "givenName":"Leonardo S", + "familyName": "Barbosa" + }, + { + "@type":"Person", + "email":"lorenzo.alfine@gmail.com", + "givenName":"Lorenzo", + "familyName": "Alfine" + }, + { + "@type":"Person", + "email":"hejtmy@gmail.com", + "givenName":"Lukáš", + "familyName": "Hejtmánek" + }, + { + "@type":"Person", + "email":"mbalatsko@gmail.com", + "givenName":"Maksym", + "familyName": "Balatsko" + }, + { + "@type":"Person", + "email":"manfredg@nmr.mgh.harvard.edu", + "givenName":"Manfred", + "familyName": "Kitzbichler" + }, + { + "@type":"Person", + "email":"manojkumarsivaraj334@gmail.com", + "givenName":"Manoj", + "familyName": "Kumar" + }, + { + "@type":"Person", + "email":"", + "givenName":"Manorama", + "familyName": "Kadwani" + }, + { + "@type":"Person", + "email":"manu.sutela@gmail.com", + "givenName":"Manu", + "familyName": "Sutela" + }, + { + "@type":"Person", + "email":"koculak.marcin@gmail.com", + "givenName":"Marcin", + "familyName": "Koculak" + }, + { + "@type":"Person", + "email":"mah@optoceutics.com", + "givenName":"Mark", + "familyName": "Henney" + }, + { + "@type":"Person", + "email":"Martinb.nmb@gmail.com", + "givenName":"Martin", + "familyName": "BaBer" + }, + { + "@type":"Person", + "email":"", + "givenName":"Martin", + "familyName": "Oberg" + }, + { + "@type":"Person", + "email":"", + "givenName":"Martin", + "familyName": "van Harmelen" + }, + { + "@type":"Person", + "email":"mathieu.scheltienne@dandelion.science", + "givenName":"Mathieu", + "familyName": "Scheltienne" + }, + { + "@type":"Person", + "email":"", + "givenName":"Matt", + "familyName": "Courtemanche" + }, + { + "@type":"Person", + "email":"matt.tucker@nyu.edu", + "givenName":"Matt", + "familyName": "Tucker" + }, + { + "@type":"Person", + "email":"matteo.visconti.gr@dartmouth.edu", + "givenName":"Matteo", + "familyName": "Visconti di Oleggio Castello" + }, + { + "@type":"Person", + "email":"matthias.dold@gmx.net", + "givenName":"Matthias", + "familyName": "Dold" + }, + { + "@type":"Person", + "email":"", + "givenName":"Matti", + "familyName": "Toivonen" + }, + { + "@type":"Person", + "email":"", + "givenName":"Maureen", + "familyName": "Shader" + }, + { + "@type":"Person", + "email":"", + "givenName":"Mauricio", + "familyName": "Cespedes" + }, + { + "@type":"Person", + "email":"krause@mpib-berlin.mpg.de", + "givenName":"Michael", + "familyName": "Krause" + }, + { + "@type":"Person", + "email":"kontakt@milanrybar.cz", + "givenName":"Milan", + "familyName": "Rybář" + }, + { + "@type":"Person", + "email":"", + "givenName":"Mingjian", + "familyName": "He" + }, + { + "@type":"Person", + "email":"", + "givenName":"Mohammad", + "familyName": "Daneshzand" + }, + { + "@type":"Person", + "email":"23111220065@m.fudan.edu.cn", + "givenName":"", + "familyName": "Mojackhak" + }, + { + "@type":"Person", + "email":"celicolimmo@free.fr", + "givenName":"Nicolas", + "familyName": "Fourcaud-Trocmé" + }, + { + "@type":"Person", + "email":"nicolas.gensollen@gmail.com", + "givenName":"Nicolas", + "familyName": "Gensollen" + }, + { + "@type":"Person", + "email":"nh.proulx@gmail.com", + "givenName":"Nicole", + "familyName": "Proulx" + }, + { + "@type":"Person", + "email":"nfocke@uni-goettingen.de", + "givenName":"Niels", + "familyName": "Focke" + }, + { + "@type":"Person", + "email":"nikos.ch01@gmail.com", + "givenName":"Nikolas", + "familyName": "Chalas" + }, + { + "@type":"Person", + "email":"", + "givenName":"Noah", + "familyName": "Markowitz" + }, + { + "@type":"Person", + "email":"omer.shubi@gmail.com", + "givenName":"Omer", + "familyName": "Shubi" + }, + { + "@type":"Person", + "email":"pablomainar.pm@gmail.com", + "givenName":"Pablo", + "familyName": "Mainar" + }, + { + "@type":"Person", + "email":"tottochan@gmail.com", + "givenName":"Padma", + "familyName": "Sundaram" + }, + { + "@type":"Person", + "email":"", + "givenName":"Paul", + "familyName": "Anders" + }, + { + "@type":"Person", + "email":"pedrobnsilva@gmail.com", + "givenName":"Pedro", + "familyName": "Silva" + }, + { + "@type":"Person", + "email":"", + "givenName":"Pierre", + "familyName": "Guetschel" + }, + { + "@type":"Person", + "email":"glia@dtu.dk", + "givenName":"Quanliang", + "familyName": "Li" + }, + { + "@type":"Person", + "email":"q.barthelemy@gmail.com", + "givenName":"Quentin", + "familyName": "Barthélemy" + }, + { + "@type":"Person", + "email":"rahuln@cs.washington.edu", + "givenName":"Rahul", + "familyName": "Nadkarni" + }, + { + "@type":"Person", + "email":"rmrgatti@gmail.com", + "givenName":"Ramiro", + "familyName": "Gatti" + }, + { + "@type":"Person", + "email":"moncho_apa@hotmail.com", + "givenName":"Ramonapariciog", + "familyName": "Apariciogarcia" + }, + { + "@type":"Person", + "email":"raagaard97@gmail.com", + "givenName":"Rasmus", + "familyName": "Aagaard" + }, + { + "@type":"Person", + "email":"reza@ddpo.ir", + "givenName":"Reza", + "familyName": "Nasri" + }, + { + "@type":"Person", + "email":"richard.koehler@outlook.de", + "givenName":"Richard", + "familyName": "Koehler" + }, + { + "@type":"Person", + "email":"rie.acad@gmail.com", + "givenName":"Riessarius", + "familyName": "Stargardsky" + }, + { + "@type":"Person", + "email":"r.oostenveld@gmail.com", + "givenName":"Robert", + "familyName": "Oostenveld" + }, + { + "@type":"Person", + "email":"robbyseymour@gmail.com", + "givenName":"Robert", + "familyName": "Seymour" + }, + { + "@type":"Person", + "email":"robintibor@gmail.com", + "givenName":"Robin Tibor", + "familyName": "Schirrmeister" + }, + { + "@type":"Person", + "email":"131315c@gmail.com", + "givenName":"Rongfei", + "familyName": "Jin" + }, + { + "@type":"Person", + "email":"", + "givenName":"Roy Eric", + "familyName": "Wieske" + }, + { + "@type":"Person", + "email":"ryan.law@mpi.nl", + "givenName":"Ryan", + "familyName": "Law" + }, + { + "@type":"Person", + "email":"sagung.pai@gmail.com", + "givenName":"Sagun", + "familyName": "Pai" + }, + { + "@type":"Person", + "email":"u1265119@unimail.hud.ac.uk", + "givenName":"Sam", + "familyName": "Perry" + }, + { + "@type":"Person", + "email":"", + "givenName":"Samuel", + "familyName": "Louviot" + }, + { + "@type":"Person", + "email":"santiaguzz@gmail.com", + "givenName":"Santi", + "familyName": "Martínez" + }, + { + "@type":"Person", + "email":"", + "givenName":"Sawradip", + "familyName": "Saha" + }, + { + "@type":"Person", + "email":"s.mathot@cogsci.nl", + "givenName":"Sebastiaan", + "familyName": "Mathot" + }, + { + "@type":"Person", + "email":"", + "givenName":"Sebastian", + "familyName": "Jentschke" + }, + { + "@type":"Person", + "email":"", + "givenName":"Sebastian", + "familyName": "Major" + }, + { + "@type":"Person", + "email":"sfox@riseup.net", + "givenName":"Sebastien", + "familyName": "Treguer" + }, + { + "@type":"Person", + "email":"sebastian.castano@blbt.uni-freiburg.de", + "givenName":"Sebastián", + "familyName": "Castaño" + }, + { + "@type":"Person", + "email":"", + "givenName":"Senwen", + "familyName": "Deng" + }, + { + "@type":"Person", + "email":"s.antopolsky@gmail.com", + "givenName":"Sergey", + "familyName": "Antopolskiy" + }, + { + "@type":"Person", + "email":"shirazi@ieee.org", + "givenName":"Seyed (Yahya)", + "familyName": "Shirazi" + }, + { + "@type":"Person", + "email":"kesharishresth5@gmail.com", + "givenName":"Shresth", + "familyName": "Keshari" + }, + { + "@type":"Person", + "email":"baral.shristi@gmail.com", + "givenName":"Shristi", + "familyName": "Baral" + }, + { + "@type":"Person", + "email":"baralshristi@gmail.com", + "givenName":"Shristi", + "familyName": "Baral" + }, + { + "@type":"Person", + "email":"", + "givenName":"Simeon", + "familyName": "Wong" + }, + { + "@type":"Person", + "email":"", + "givenName":"Simeon", + "familyName": "Wong" + }, + { + "@type":"Person", + "email":"", + "givenName":"Simon M", + "familyName": "Hofmann" + }, + { + "@type":"Person", + "email":"", + "givenName":"Simon-Shlomo", + "familyName": "Poil" + }, + { + "@type":"Person", + "email":"sondre.foslien@gmail.com", + "givenName":"Sondre", + "familyName": "Foslien" + }, + { + "@type":"Person", + "email":"", + "givenName":"Sourav", + "familyName": "Singh" + }, + { + "@type":"Person", + "email":"stan.chambon@gmail.com", + "givenName":"Stanislas", + "familyName": "Chambon" + }, + { + "@type":"Person", + "email":"", + "givenName":"Steinn Hauser", + "familyName": "Magnússon" + }, + { + "@type":"Person", + "email":"bethard@email.arizona.edu", + "givenName":"Steven", + "familyName": "Bethard" + }, + { + "@type":"Person", + "email":"s.m.gutstein@gmail.com", + "givenName":"Steven M", + "familyName": "Gutstein" + }, + { + "@type":"Person", + "email":"", + "givenName":"Svea Marie", + "familyName": "Meyer" + }, + { + "@type":"Person", + "email":"twang5@swarthmore.edu", + "givenName":"T", + "familyName": "Wang" + }, + { + "@type":"Person", + "email":"tharupahanjayawardana@gmail.com", + "givenName":"Tharupahan", + "familyName": "Jayawardana" + }, + { + "@type":"Person", + "email":"thomas.moreau.2010@gmail.com", + "givenName":"Thomas", + "familyName": "Moreau" + }, + { + "@type":"Person", + "email":"radman.thomas@gmail.com", + "givenName":"Thomas", + "familyName": "Radman" + }, + { + "@type":"Person", + "email":"tim.gates@iress.com", + "givenName":"Timothy", + "familyName": "Gates" + }, + { + "@type":"Person", + "email":"TASTONE@mgh.harvard.edu", + "givenName":"Tom", + "familyName": "Stone" + }, + { + "@type":"Person", + "email":"", + "givenName":"Tommy", + "familyName": "Clausner" + }, + { + "@type":"Person", + "email":"toomaserikanijarv@gmail.com", + "givenName":"Toomas Erik", + "familyName": "Anijärv" + }, + { + "@type":"Person", + "email":"", + "givenName":"Velu Prabhakar", + "familyName": "Kumaravel" + }, + { + "@type":"Person", + "email":"weixu@mail.bnu.edu.cn", + "givenName":"Wei", + "familyName": "Xu" + }, + { + "@type":"Person", + "email":"williamfrancisturner@gmail.com", + "givenName":"Will", + "familyName": "Turner" + }, + { + "@type":"Person", + "email":"xabier@zuazo.org", + "givenName":"Xabier de", + "familyName": "Zuazo" + }, + { + "@type":"Person", + "email":"xia@xiaokai.me", + "givenName":"Xiaokai", + "familyName": "Xia" + }, + { + "@type":"Person", + "email":"frostime@foxmail.com", + "givenName":"Yiping", + "familyName": "Zuo" + }, + { + "@type":"Person", + "email":"", + "givenName":"Yixiao", + "familyName": "Shen" + }, + { + "@type":"Person", + "email":"", + "givenName":"Young", + "familyName": "Truong" + }, + { + "@type":"Person", + "email":"850734033@qq.com", + "givenName":"Zhi", + "familyName": "Zhang" + }, + { + "@type":"Person", + "email":"ziyizeng@link.cuhk.edu.cn", + "givenName":"Ziyi", + "familyName": "ZENG" + }, + { + "@type":"Person", + "email":"btk.codedev@gmail.com", + "givenName":"", + "familyName": "btkcodedev" + }, + { + "@type":"Person", + "email":"", + "givenName":"", + "familyName": "buildqa" + }, + { + "@type":"Person", + "email":"", + "givenName":"", + "familyName": "luzpaz" + }, + { + "@type":"Person", + "email":"", + "givenName":"", + "familyName": "user27182" + } + ] +} diff --git a/mne-python/source/doc/Makefile b/mne-python/source/doc/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..4eb4ee4dd0676751c945aa79007c13f225c4db80 --- /dev/null +++ b/mne-python/source/doc/Makefile @@ -0,0 +1,81 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -nWT --keep-going +SPHINXBUILD = sphinx-build +MPROF = SG_STAMP_STARTS=true mprof run -E --python sphinx + +# Internal variables. +ALLSPHINXOPTS = -d _build/doctrees $(SPHINXOPTS) . + +.PHONY: help clean html html-noplot html-pattern linkcheck linkcheck-grep doctest + +# make with no arguments will build the first target by default, i.e., build standalone HTML files +first_target: html-noplot + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " html-memory to make standalone HTML files while monitoring memory usage" + @echo " html-pattern to make standalone HTML files for a specific filename pattern" + @echo " html-front to make standalone HTML files with only the frontpage examples" + @echo " html-noplot to make standalone HTML files without plotting" + @echo " clean to clean HTML files" + @echo " linkcheck to check all external links for integrity" + @echo " linkcheck-grep to grep the linkcheck result" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " view to view the built HTML" + +clean: + -rm -rf _build sg_execution_times.rst auto_examples auto_tutorials generated *.stc *.fif *.nii.gz + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html + @echo + @echo "Build finished. The HTML pages are in _build/html." + +html-memory: + $(MPROF) -b html $(ALLSPHINXOPTS) _build/html + @echo + @echo "Build finished. The HTML pages are in _build/html." + +html-pattern: + $(SPHINXBUILD) -D sphinx_gallery_conf.filename_pattern=$(PATTERN) -D sphinx_gallery_conf.run_stale_examples=True -b html $(ALLSPHINXOPTS) _build/html + @echo + @echo "Build finished. The HTML pages are in _build/html" + +html-pattern-memory: + $(MPROF) -D sphinx_gallery_conf.filename_pattern=$(PATTERN) -D sphinx_gallery_conf.run_stale_examples=True -b html $(ALLSPHINXOPTS) _build/html + @echo + @echo "Build finished. The HTML pages are in _build/html" + +html-noplot: + $(SPHINXBUILD) -D plot_gallery=0 -b html $(ALLSPHINXOPTS) _build/html + @echo + @echo "Build finished. The HTML pages are in _build/html." + +html-front: + @PATTERN="\(30_mne_dspm_loreta.py\|50_decoding.py\|30_strf.py\|20_cluster_1samp_spatiotemporal.py\|20_visualize_evoked.py\)" make html-pattern + +# Aliases for old methods +html_dev-pattern-memory: html-pattern-memory +html_dev-pattern: html-pattern +html_dev-noplot: html-noplot +html_dev-front: html-front + +linkcheck: + @$(SPHINXBUILD) -b linkcheck -D nitpicky=0 -q -D plot_gallery=0 -D exclude_patterns="cited.rst,whats_new.rst,configure_git.rst,_includes,changes/dev" -d _build/doctrees . _build/linkcheck + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in _build/doctest/output.txt." + +view: + @python -c "import webbrowser; webbrowser.open_new_tab('file://$(PWD)/_build/html/sg_execution_times.html')" + +show: view + +serve: + python -m http.server -d _build/html diff --git a/mne-python/source/doc/_includes/bem_model.rst b/mne-python/source/doc/_includes/bem_model.rst new file mode 100644 index 0000000000000000000000000000000000000000..cb9c849c1bb4acd1731e52362c82f51df5f5853b --- /dev/null +++ b/mne-python/source/doc/_includes/bem_model.rst @@ -0,0 +1,162 @@ +:orphan: + +Creating the BEM meshes +======================= + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`bem-model` to link to that section of the implementation.rst page. + The next line is a target for :start-after: so we can omit the title from + the include: + bem-begin-content + +.. _bem_watershed_algorithm: + +Using the watershed algorithm +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The watershed algorithm [Segonne *et al.*, +2004] is part of the FreeSurfer software. +The name of the program is mri_watershed_. +Its use in the MNE environment is facilitated by the script +:ref:`mne watershed_bem`. + +After ``mne watershed_bem`` has completed, the following files appear in the +subject's :file:`bem/watershed` directory: + +- :file:`{}_brain_surface` contains the brain surface triangulation. + +- :file:`{}_inner_skull_surface` contains the inner skull + triangulation. + +- :file:`{}_outer_skull_surface` contains the outer skull + triangulation. + +- :file:`{}_outer_skin_surface` contains the scalp triangulation. + +All of these surfaces are in the FreeSurfer format. In addition, there will be +a file called :file:`bem/watershed/ws.mgz` which contains the brain MRI +volume. Furthermore, ``mne watershed_bem`` script converts the scalp surface to +fif format and saves the result to :file:`bem/{}-head.fif`. + +.. _bem_flash_algorithm: + +Using FLASH images +~~~~~~~~~~~~~~~~~~ + +This method depends on the availablily of MRI data acquired with a multi-echo +FLASH sequence at two flip angles (5 and 30 degrees). These data can be +acquired separately from the MPRAGE data employed in FreeSurfer cortical +reconstructions but it is strongly recommended that they are collected at the +same time with the MPRAGEs or at least with the same scanner. For easy +co-registration, the images should have FOV, matrix, slice thickness, gap, and +slice orientation as the MPRAGE data. For information on suitable pulse +sequences, see :footcite:t:`FischlEtAl2004`. + +Creation of the BEM meshes using this method involves the following steps: + +- Creating a synthetic 5-degree flip angle FLASH volume, register + it with the MPRAGE data, and run the segmentation and meshing program. + This step is accomplished by running the script :ref:`mne flash_bem`. + +- Inspecting the meshes with tkmedit, see :ref:`inspecting-meshes`. + +.. note:: Different methods can be employed for the creation of the + individual surfaces. For example, it may turn out that the + watershed algorithm produces are better quality skin surface than + the segmentation approach based on the FLASH images. If this is + the case, ``outer_skin.surf`` can set to point to the corresponding + watershed output file while the other surfaces can be picked from + the FLASH segmentation data. + + +Organizing MRI data into directories +------------------------------------ + +Since all images comprising the multi-echo FLASH data are contained in a single +series, it is necessary to organize the images according to the echoes before +proceeding to the BEM surface reconstruction. This can be accomplished by using +`dcm2niix `__ +or the MNE-C tool ``mne_organize_dicom`` if necessary, then use +:func:`mne.bem.convert_flash_mris`. + +Creating the surface tessellations +---------------------------------- + +The BEM surface segmentation and tessellation is automated with the script +:ref:`mne flash_bem`. It assumes that a FreeSurfer reconstruction for this +subject is already in place. + +Before running :ref:`mne flash_bem` do the following: + +- Create symbolic links from the directories containing the 5-degree and + 30-degree flip angle FLASH series to ``flash05`` and ``flash30``, + respectively: + + - :samp:`ln -s {} flash05` + + - :samp:`ln -s {} flash30` + +- Some partition formats (e.g. FAT32) do not support symbolic links. In this + case, copy the file to the appropriate series: + + - :samp:`cp {} flash05` + + - :samp:`cp {} flash30` + +- Set the ``SUBJECTS_DIR`` and ``SUBJECT`` environment variables or pass + the ``--subjects-dir`` and ``--subject`` options to ``mne flash_bem`` + +.. note:: If ``mne flash_bem`` is run with the ``--noflash30`` option, the + :file:`flash30` directory is not needed, *i.e.*, only the 5-degree flip + angle flash data are employed. + +It may take a while for ``mne flash_bem`` to complete. It uses the FreeSurfer +directory structure under ``$SUBJECTS_DIR/$SUBJECT``. The script encapsulates +the following processing steps: + +- It creates an mgz file corresponding to each of the eight echoes in each of + the FLASH directories in ``mri/flash``. The files will be called + :file:`mef {}_{}.mgz`. + +- If the ``unwarp=True`` option is specified, run grad_unwarp and produce + files :file:`mef {}_{}u.mgz`. These files will be + then used in the following steps. + +- It creates parameter maps in :file:`mri/flash/parameter_maps` using + ``mri_ms_fitparms``. + +- It creates a synthetic 5-degree flip angle volume in + :file:`mri/flash/parameter_maps/flash5.mgz` using ``mri_synthesize``. + +- Using ``fsl_rigid_register``, it creates a registered 5-degree flip angle + volume ``mri/flash/parameter_maps/flash5_reg.mgz`` by registering + :file:`mri/flash/parameter_maps/flash5.mgz` to the *T1* volume under ``mri``. + +- Using ``mri_convert``, it converts the flash5_reg volume to COR format under + ``mri/flash5``. If necessary, the T1 and brain volumes are also converted + into the COR format. + +- It runs ``mri_make_bem_surfaces`` to create the BEM surface tessellations. + +- It creates the directory :file:`bem/flash`, moves the tri-format + tringulations there and creates the corresponding FreeSurfer surface files + in the same directory. + +- The COR format volumes created by ``mne flash_bem`` are removed. + +If the ``--noflash30`` option is specified to ``mne flash_bem``, +steps 3 and 4 in the above are replaced by averaging over the different +echo times in 5-degree flip angle data. + +.. _inspecting-meshes: + +Inspecting the meshes +--------------------- + +It is advisable to check the validity of the BEM meshes before +using them. This can be done with: + +- the ``--view`` option of :ref:`mne flash_bem` +- calling :func:`mne.viz.plot_bem` directly +- Using FreeSurfer tools ``tkmedit`` or ``freeview`` diff --git a/mne-python/source/doc/_includes/channel_interpolation.rst b/mne-python/source/doc/_includes/channel_interpolation.rst new file mode 100644 index 0000000000000000000000000000000000000000..e90a763d214d81f0a9db3163b9448cc6473438d9 --- /dev/null +++ b/mne-python/source/doc/_includes/channel_interpolation.rst @@ -0,0 +1,70 @@ +:orphan: + +Bad channel repair via interpolation +==================================== + +Spherical spline interpolation (EEG) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`channel-interpolation` to link to that section of the + implementation.rst page. The next line is a target for :start-after: so we + can omit the title from the include: + channel-interpolation-begin-content + +In short, data repair using spherical spline interpolation :footcite:`PerrinEtAl1989` consists of the following steps: + +* Project the good and bad electrodes onto a unit sphere +* Compute a mapping matrix that maps :math:`N` good channels to :math:`M` bad channels +* Use this mapping matrix to compute interpolated data in the bad channels + +Spherical splines assume that the potential :math:`V(\boldsymbol{r_i})` at any point :math:`\boldsymbol{r_i}` on the surface of the sphere can be represented by: + +.. math:: V(\boldsymbol{r_i}) = c_0 + \sum_{j=1}^{N}c_{i}g_{m}(cos(\boldsymbol{r_i}, \boldsymbol{r_{j}})) + :name: model + +where the :math:`C = (c_{1}, ..., c_{N})^{T}` are constants which must be estimated. The function :math:`g_{m}(\cdot)` of order :math:`m` is given by: + +.. math:: g_{m}(x) = \frac{1}{4 \pi}\sum_{n=1}^{\infty} \frac{2n + 1}{(n(n + 1))^m}P_{n}(x) + +where :math:`P_{n}(x)` are `Legendre polynomials`_ of order :math:`n`. + +.. _Legendre polynomials: https://en.wikipedia.org/wiki/Legendre_polynomials + +To estimate the constants :math:`C`, we must solve the following two equations simultaneously: + +.. math:: G_{ss}C + T_{s}c_0 = X + :name: matrix_form + +.. math:: {T_s}^{T}C = 0 + :name: constraint + +where :math:`G_{ss} \in R^{N \times N}` is a matrix whose entries are :math:`G_{ss}[i, j] = g_{m}(cos(\boldsymbol{r_i}, \boldsymbol{r_j}))` and :math:`X \in R^{N \times 1}` are the potentials :math:`V(\boldsymbol{r_i})` measured at the good channels. :math:`T_{s} = (1, 1, ..., 1)^\top` is a column vector of dimension :math:`N`. Equation :eq:`matrix_form` is the matrix formulation of Equation :eq:`model` and equation :eq:`constraint` is like applying an average reference to the data. From equation :eq:`matrix_form` and :eq:`constraint`, we get: + +.. math:: \begin{bmatrix} c_0 \\ C \end{bmatrix} = {\begin{bmatrix} {T_s}^{T} && 0 \\ T_s && G_{ss} \end{bmatrix}}^{-1} \begin{bmatrix} 0 \\ X \end{bmatrix} = C_{i}X + :name: estimate_constant + +:math:`C_{i}` is the same as matrix :math:`{\begin{bmatrix} {T_s}^{T} && 0 \\ T_s && G_{ss} \end{bmatrix}}^{-1}` but with its first column deleted, therefore giving a matrix of dimension :math:`(N + 1) \times N`. + +Now, to estimate the potentials :math:`\hat{X} \in R^{M \times 1}` at the bad channels, we have to do: + +.. math:: \hat{X} = G_{ds}C + T_{d}c_0 + :name: estimate_data + +where :math:`G_{ds} \in R^{M \times N}` computes :math:`g_{m}(\boldsymbol{r_i}, \boldsymbol{r_j})` between the bad and good channels. :math:`T_{d} = (1, 1, ..., 1)^\top` is a column vector of dimension :math:`M`. Plugging in equation :eq:`estimate_constant` in :eq:`estimate_data`, we get + +.. math:: \hat{X} = \begin{bmatrix} T_d && G_{ds} \end{bmatrix} \begin{bmatrix} c_0 \\ C \end{bmatrix} = \underbrace{\begin{bmatrix} T_d && G_{ds} \end{bmatrix} C_{i}}_\text{mapping matrix}X + + +To interpolate bad channels, one can simply do: + + >>> evoked.interpolate_bads(reset_bads=False) # doctest: +SKIP + +and the bad channel will be fixed. + +.. target for :end-before: channel-interpolation-end-content + +.. topic:: Examples: + + * :ref:`ex-interpolate-bad-channels` diff --git a/mne-python/source/doc/_includes/channel_types.rst b/mne-python/source/doc/_includes/channel_types.rst new file mode 100644 index 0000000000000000000000000000000000000000..0a2ea0ab007e626b6e3804f1f1680d22f1065ed6 --- /dev/null +++ b/mne-python/source/doc/_includes/channel_types.rst @@ -0,0 +1,104 @@ +:orphan: + +Supported channel types +======================= + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`channel-types` to link to that section of the implementation.rst + page. The next line is a target for :start-after: so we can omit the title + from the include: + channel-types-begin-content + +.. NOTE: In the future, this table should be automatically synchronized with + the sensor types listed in the glossary. Perhaps a table showing data type + channels as well as non-data type channels should be added to the glossary + and displayed here too. + +Channel types are represented in MNE-Python with shortened or abbreviated +names. This page lists all supported channel types, their abbreviated names, +and the measurement unit used to represent data of that type. Where channel +types occur in two or more sub-types, the sub-type abbreviations are given in +parentheses. More information about measurement units is given in the +:ref:`units` section. + +.. NOTE: To include only the table, here's a different target for :start-after: + channel-types-begin-table + +.. cssclass:: table-bordered +.. rst-class:: midvalign + +================= ========================================= ================= +Channel type Description Measurement unit +================= ========================================= ================= +eeg scalp electroencephalography (EEG) Volts + +meg (mag) Magnetoencephalography (magnetometers) Teslas + +meg (grad) Magnetoencephalography (gradiometers) Teslas/meter + +ecg Electrocardiography (ECG) Volts + +seeg Stereotactic EEG channels Volts + +dbs Deep brain stimulation (DBS) Volts + +ecog Electrocorticography (ECoG) Volts + +fnirs (hbo) Functional near-infrared spectroscopy Moles/liter + (oxyhemoglobin) + +fnirs (hbr) Functional near-infrared spectroscopy Moles/liter + (deoxyhemoglobin) + +emg Electromyography (EMG) Volts + +eog Electrooculography (EOG) Volts + +bio Miscellaneous biological channels (e.g., Arbitrary units + skin conductance) + +stim stimulus (a.k.a. trigger) channels Arbitrary units + +resp respiration monitoring channel Volts + +chpi continuous head position indicator Teslas + (HPI) coil channels + +exci Flux excitation channel + +ias Internal Active Shielding data + (Triux systems only?) + +syst System status channel information + (Triux systems only) + +temperature Temperature Degrees Celsius + +gsr Galvanic skin response Siemens + +ref_meg Reference Magnetometers Teslas + +dipole Dipole amplitude Amperes + +gof Goodness of fit (GOF) Goodness-of-fit + +cw-nirs (amp) Continuous-wave functional near-infrared Volts + spectroscopy (CW-fNIRS) (CW amplitude) + +fd-nirs (ac amp) Frequency-domain near-infrared Volts + spectroscopy (FD-NIRS AC amplitude) + +fd-nirs (phase) Frequency-domain near-infrared Radians + spectroscopy (FD-NIRS phase) + +fnirs (od) Functional near-infrared spectroscopy Volts + (optical density) + +csd Current source density Volts per square + meter + +eyegaze Eye-tracking (gaze position) Arbitrary units + +pupil Eye-tracking (pupil size) Arbitrary units +================= ========================================= ================= \ No newline at end of file diff --git a/mne-python/source/doc/_includes/data_formats.rst b/mne-python/source/doc/_includes/data_formats.rst new file mode 100644 index 0000000000000000000000000000000000000000..2326f75a781cb9c8ad0cd617642fb65636de6ce9 --- /dev/null +++ b/mne-python/source/doc/_includes/data_formats.rst @@ -0,0 +1,86 @@ +:orphan: + +Supported data formats +====================== + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, + link to :ref:`data-formats`. The next line is + a target for :start-after: so we can omit the title above: + data-formats-begin-content + +When MNE-Python loads sensor data, the data are stored in a Python object of +type :class:`mne.io.Raw`. Specialized loading functions are provided for the +raw data file formats from a variety of equipment manufacturers. All raw data +input/output functions in MNE-Python are found in :mod:`mne.io` and start +with :samp:`read_raw_{*}`; see the documentation for each reader function for +more info on reading specific file types. + +As seen in the table below, there are also a few formats defined by other +neuroimaging analysis software packages that are supported (EEGLAB, +FieldTrip). Like the equipment-specific loading functions, these will also +return an object of class :class:`~mne.io.Raw`; additional functions are +available for reading data that has already been epoched or averaged (see +table). + +.. NOTE: To include only the table, here's a different target for :start-after: + data-formats-begin-table + +.. cssclass:: table-bordered +.. rst-class:: midvalign + +============ ============================================ ========= =================================== +Data type File format Extension MNE-Python function +============ ============================================ ========= =================================== +MEG :ref:`Artemis123 ` .bin :func:`mne.io.read_raw_artemis123` + +MEG :ref:`4-D Neuroimaging / BTi ` :func:`mne.io.read_raw_bti` + +MEG :ref:`CTF ` :func:`mne.io.read_raw_ctf` + +MEG and EEG :ref:`Elekta Neuromag ` .fif :func:`mne.io.read_raw_fif` + +MEG :ref:`FIL OPM MEG ` .bin :func:`mne.io.read_raw_fil` + +MEG :ref:`KIT ` .sqd :func:`mne.io.read_raw_kit`, + :func:`mne.read_epochs_kit` + +MEG and EEG :ref:`FieldTrip ` .mat :func:`mne.io.read_raw_fieldtrip`, + :func:`mne.read_epochs_fieldtrip`, + :func:`mne.read_evoked_fieldtrip` + +EEG :ref:`Brainvision ` .vhdr :func:`mne.io.read_raw_brainvision` + +EEG :ref:`Biosemi data format ` .bdf :func:`mne.io.read_raw_bdf` + +EEG :ref:`Neuroscan CNT ` .cnt :func:`mne.io.read_raw_cnt` + +EEG :ref:`European data format ` .edf :func:`mne.io.read_raw_edf` + +EEG :ref:`EEGLAB ` .set :func:`mne.io.read_raw_eeglab`, + :func:`mne.read_epochs_eeglab` + +EEG :ref:`EGI simple binary ` .egi :func:`mne.io.read_raw_egi` + +EEG :ref:`EGI MFF format ` .mff :func:`mne.io.read_raw_egi` + +EEG :ref:`eXimia ` .nxe :func:`mne.io.read_raw_eximia` + +EEG :ref:`General data format ` .gdf :func:`mne.io.read_raw_gdf` + +EEG :ref:`Nicolet ` .data :func:`mne.io.read_raw_nicolet` + +EEG :ref:`Persyst ` .lay :func:`mne.io.read_raw_persyst` + +NIRS :ref:`NIRx ` directory :func:`mne.io.read_raw_nirx` + +NIRS :ref:`BOXY ` directory :func:`mne.io.read_raw_boxy` + +EYETRACK SR eyelink ASCII files .asc :func:`mne.io.read_raw_eyelink` + +iEEG MEF3 .mefd :func:`mne.io.read_raw_mef` + +============ ============================================ ========= =================================== + +More details are provided in the tutorials in the :ref:`tut-data-formats` +section. diff --git a/mne-python/source/doc/_includes/dig_formats.rst b/mne-python/source/doc/_includes/dig_formats.rst new file mode 100644 index 0000000000000000000000000000000000000000..47d99a889bc8076a8db025733f2eaf2a04198c2b --- /dev/null +++ b/mne-python/source/doc/_includes/dig_formats.rst @@ -0,0 +1,47 @@ +:orphan: + +.. _dig-formats: + +Supported formats for digitized 3D locations +============================================ + +.. NOTE: If you want to link to this content, link to :ref:`dig-formats` + for the implementation page. The next line is + a target for :start-after: so we can omit the title above: + dig-formats-begin-content + +MNE-Python can load 3D point locations obtained by digitization systems. +Such files allow to obtain a :class:`montage ` +that can then be added to :class:`~mne.io.Raw` objects with the +:meth:`~mne.io.Raw.set_montage`. See the documentation for each reader +function for more info on reading specific file types. + +.. NOTE: To include only the table, here's a different target for :start-after: + dig-formats-begin-table + +.. cssclass:: table-bordered +.. rst-class:: midvalign + +===================== ================ ============================================== +Vendor Extension(s) MNE-Python function +===================== ================ ============================================== +Neuromag .fif :func:`mne.channels.read_dig_fif` + +Polhemus ISOTRAK .hsp, .elp, .eeg :func:`mne.channels.read_dig_polhemus_isotrak` + +EGI .xml :func:`mne.channels.read_dig_egi` + +MNE-C .hpts :func:`mne.channels.read_dig_hpts` + +Brain Products .bvct :func:`mne.channels.read_dig_captrak` + +Compumedics .dat, .cdt :func:`mne.channels.read_dig_curry` + +Compumedics (legacy) .dat :func:`mne.channels.read_dig_dat` +===================== ================ ============================================== + +To load Polhemus FastSCAN files you can use +:func:`montage `. + +It is also possible to make a :class:`montage ` +from arrays with :func:`mne.channels.make_dig_montage`. diff --git a/mne-python/source/doc/_includes/forward.rst b/mne-python/source/doc/_includes/forward.rst new file mode 100644 index 0000000000000000000000000000000000000000..40706fb292c8776ed7e99020ec26dd49cdc785c2 --- /dev/null +++ b/mne-python/source/doc/_includes/forward.rst @@ -0,0 +1,726 @@ +:orphan: + +The forward solution +==================== + +This page covers the definitions of different coordinate systems employed in +MNE software and FreeSurfer, the details of the computation of the forward +solutions, and the associated low-level utilities. + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`ch_forward` to link to that section of the implementation.rst page. + The next line is a target for :start-after: so we can omit the title from + the include: + forward-begin-content + + +.. _coordinate_systems: + +MEG/EEG and MRI coordinate systems +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: Coordinate systems in MNE-Python + :class: sidebar + + In some MNE-Python objects (e.g., :class:`~mne.Forward`, + :class:`~mne.SourceSpaces`, etc), information about the coordinate frame is + encoded as a constant integer value. The meaning of those integers is + determined `in the source code + `__. + +The coordinate systems used in MNE software (and FreeSurfer) and their +relationships are depicted in :ref:`coordinate_system_figure`. Except for the +*sensor coordinates*, all of the coordinate systems are Cartesian and have the +"RAS" (Right-Anterior-Superior) orientation, *i.e.*, the :math:`x` axis points +to the right, the :math:`y` axis to the front, and the :math:`z` axis up. + +.. _coordinate_system_figure: + +.. figure:: ../_static/CoordinateSystems.png + :alt: MEG/EEG and MRI coordinate systems + + MEG/EEG and MRI coordinate systems + + The coordinate transforms present in the fif files in MNE and the + FreeSurfer files as well as those set to fixed values are indicated with + :math:`T_x`, where :math:`x` identifies the transformation. + +The coordinate systems related to MEG/EEG data are: + +**Head coordinates** + + This is a coordinate system defined with help of the fiducial landmarks + (nasion and the two auricular points). In fif files, EEG electrode + locations are given in this coordinate system. In addition, the head + digitization data acquired in the beginning of an MEG, MEG/EEG, or EEG + acquisition are expressed in head coordinates. For details, see + :ref:`coordinate_systems`. + +**Device coordinates** + + This is a coordinate system tied to the MEG device. The relationship of the + Device and Head coordinates is determined during an MEG measurement by + feeding current to three to five head-position indicator (HPI) coils and by + determining their locations with respect to the MEG sensor array from the + magnetic fields they generate. + +**Sensor coordinates** + + Each MEG sensor has a local coordinate system defining the orientation and + location of the sensor. With help of this coordinate system, the numerical + integration data needed for the computation of the magnetic field can be + expressed conveniently as discussed in :ref:`coil_geometry_information`. + The channel information data in the fif files contain the information to + specify the coordinate transformation between the coordinates of each + sensor and the MEG device coordinates. + +The coordinate systems related to MRI data are: + +**Surface RAS coordinates** + + The FreeSurfer surface data are expressed in this coordinate system. The + origin of this coordinate system is at the center of the conformed + FreeSurfer MRI volumes (usually 256 x 256 x 256 isotropic 1-mm3 voxels) + and the axes are oriented along the axes of this volume. The BEM surface + and the locations of the sources in the source space are usually expressed + in this coordinate system in the fif files. In this manual, the *Surface + RAS coordinates* are usually referred to as *MRI coordinates* unless there + is need to specifically discuss the different MRI-related coordinate + systems. + +**RAS coordinates** + + This coordinate system has axes identical to the Surface RAS coordinates + but the location of the origin is different and defined by the original MRI + data, i.e. , the origin is in a scanner-dependent location. There is hardly + any need to refer to this coordinate system explicitly in the analysis with + the MNE software. However, since the Talairach coordinates, discussed + below, are defined with respect to *RAS coordinates* rather than the + *Surface RAS coordinates*, the RAS coordinate system is implicitly involved + in the transformation between Surface RAS coordinates and the two + *Talairach* coordinate systems. + +**MNI Talairach coordinates** + + The definition of this coordinate system is discussed, e.g., in + https://imaging.mrc-cbu.cam.ac.uk/imaging/MniTalairach. This transformation + is determined during the FreeSurfer reconstruction process. These + coordinates are in MNI305 space. + +**FreeSurfer Talairach coordinates** + + The problem with the MNI Talairach coordinates is that the linear MNI + Talairach transform does not match the brains completely to the Talairach + brain. This is probably because the Talairach atlas brain is a rather odd + shape, and as a result, it is difficult to match a standard brain to the + atlas brain using an affine transform. As a result, the MNI brains are + slightly larger (in particular higher, deeper and longer) than the + Talairach brain. The differences are larger as you get further from the + middle of the brain, towards the outside. The FreeSurfer Talairach + coordinates mitigate this problem by additing a an additional + transformation, defined separately for negative and positive MNI Talairach + :math:`z` coordinates. These two transformations, denoted by :math:`T_-` + and :math:`T_+` in :ref:`coordinate_system_figure`, are fixed as discussed in + https://imaging.mrc-cbu.cam.ac.uk/imaging/MniTalairach (*Approach 2*). + +The different coordinate systems are related by coordinate transformations +depicted in :ref:`coordinate_system_figure`. The arrows and coordinate +transformation symbols (:math:`T_x`) indicate the transformations actually +present in the FreeSurfer files. Generally, + +.. math:: \begin{bmatrix} + x_2 \\ + y_2 \\ + z_2 \\ + 1 + \end{bmatrix} = T_{12} \begin{bmatrix} + x_1 \\ + y_1 \\ + z_1 \\ + 1 + \end{bmatrix} = \begin{bmatrix} + R_{11} & R_{12} & R_{13} & x_0 \\ + R_{21} & R_{22} & R_{23} & y_0 \\ + R_{31} & R_{32} & R_{33} & z_0 \\ + 0 & 0 & 0 & 1 + \end{bmatrix} \begin{bmatrix} + x_1 \\ + y_1 \\ + z_1 \\ + 1 + \end{bmatrix}\ , + +where :math:`x_k`, :math:`y_k`,and :math:`z_k` are the location coordinates in +two coordinate systems, :math:`T_{12}` is the coordinate transformation from +coordinate system "1" to "2", :math:`x_0`, :math:`y_0`, and :math:`z_0` is the +location of the origin of coordinate system "1" in coordinate system "2", and +:math:`R_{jk}` are the elements of the rotation matrix relating the two +coordinate systems. The coordinate transformations are present in different +files produced by FreeSurfer and MNE. +The fixed transformations :math:`T_-` and :math:`T_+` are: + +.. math:: T_{-} = \begin{bmatrix} + 0.99 & 0 & 0 & 0 \\ + 0 & 0.9688 & 0.042 & 0 \\ + 0 & -0.0485 & 0.839 & 0 \\ + 0 & 0 & 0 & 1 + \end{bmatrix} + +and + +.. math:: T_{+} = \begin{bmatrix} + 0.99 & 0 & 0 & 0 \\ + 0 & 0.9688 & 0.046 & 0 \\ + 0 & -0.0485 & 0.9189 & 0 \\ + 0 & 0 & 0 & 1 + \end{bmatrix} + +.. note:: + This section does not discuss the transformation between the MRI voxel + indices and the different MRI coordinates. However, it is important to note + that in FreeSurfer, MNE, as well as in Neuromag software an integer voxel + coordinate corresponds to the location of the center of a voxel. Detailed + information on the FreeSurfer MRI systems can be found at + https://surfer.nmr.mgh.harvard.edu/fswiki/CoordinateSystems. + The symbols :math:`T_x` are defined in :ref:`coordinate_system_figure`. + +.. tabularcolumns:: |p{0.2\linewidth}|p{0.3\linewidth}|p{0.5\linewidth}| +.. table:: Coordinate transformations in FreeSurfer and MNE software packages + + +------------------------------+-------------------------------+-------------------------------------------------+ + | Transformation | FreeSurfer | MNE | + +------------------------------+-------------------------------+-------------------------------------------------+ + | :math:`T_1` | Not present | | Measurement data files | + | | | | Forward solution files (``*fwd.fif``) | + | | | | Inverse operator files (``*inv.fif``) | + +------------------------------+-------------------------------+-------------------------------------------------+ + | :math:`T_{s_1}\dots T_{s_n}` | Not present | Channel information in files | + | | | containing :math:`T_1`. | + +------------------------------+-------------------------------+-------------------------------------------------+ + | :math:`T_2` | Not present | | MRI description filesSeparate | + | | | | Separate ``-trans.fif`` files | + | | | | from :ref:`mne coreg` | + | | | | Forward solution files | + | | | | Inverse operator files | + +------------------------------+-------------------------------+-------------------------------------------------+ + | :math:`T_3` | ``mri/*mgz`` files | :class:`nibabel.freesurfer.mghformat.MGHImage` | + +------------------------------+-------------------------------+-------------------------------------------------+ + | :math:`T_4` | mri/transforms/talairach.xfm | Internal reading | + +------------------------------+-------------------------------+-------------------------------------------------+ + | :math:`T_-` | Hardcoded in software | Hardcoded in software. | + +------------------------------+-------------------------------+-------------------------------------------------+ + | :math:`T_+` | Hardcoded in software | Hardcoded in software. | + +------------------------------+-------------------------------+-------------------------------------------------+ + +.. _head_device_coords: + +The head and device coordinate systems +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. figure:: ../_static/HeadCS.png + :alt: Head coordinate system + + The head coordinate system + +The MEG/EEG head coordinate system employed in the MNE software is a +right-handed Cartesian coordinate system. The direction of :math:`x` axis is +from left to right, that of :math:`y` axis to the front, and the :math:`z` axis +thus points up. + +The :math:`x` axis of the head coordinate system passes through the two +periauricular or preauricular points digitized before acquiring the data with +positive direction to the right. The :math:`y` axis passes through the nasion +and is normal to the :math:`x` axis. The :math:`z` axis points up according to +the right-hand rule and is normal to the :math:`xy` plane. + +The origin of the MEG device coordinate system is device dependent. Its origin +is located approximately at the center of a sphere which fits the occipital +section of the MEG helmet best with :math:`x` axis axis going from left to +right and :math:`y` axis pointing front. The :math:`z` axis is, again, normal +to the :math:`xy` plane with positive direction up. + +.. note:: + The above definition is identical to that of the Neuromag MEG/EEG (head) + coordinate system. However, in 4-D Neuroimaging and CTF MEG systems the head + coordinate frame definition is different. The origin of the coordinate + system is at the midpoint of the left and right auricular points. The + :math:`x` axis passes through the nasion and the origin with positive + direction to the front. The :math:`y` axis is perpendicular to the :math:`x` + axis on the and lies in the plane defined by the three fiducial landmarks, + positive direction from right to left. The :math:`z` axis is normal to the + plane of the landmarks, pointing up. Note that in this convention the + auricular points are not necessarily located on :math:`y` coordinate axis. + The file conversion utilities take care of these idiosyncrasies and convert + all coordinate information to the MNE software head coordinate frame. + +Creating a surface-based source space +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The fif format source space files containing the dipole locations and +orientations are created with :func:`mne.setup_source_space`. + +Creating a volumetric or discrete source space +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In addition to source spaces confined to a surface, the MNE software provides +some support for three-dimensional source spaces bounded by a surface as well +as source spaces comprised of discrete, arbitrarily located source points. The +:func:`mne.setup_volume_source_space` utility assists in generating such source +spaces. + +Creating the BEM meshes +~~~~~~~~~~~~~~~~~~~~~~~ + +See :ref:`bem-model`. + +Topology checks +--------------- + +The following topology checks are performed during the creation of BEM models: + +- The completeness of each surface is confirmed by calculating the total solid + angle subtended by all triangles from a point inside the triangulation. The + result should be very close to :math:`4 \pi`. If the result is :math:`-4 \pi` + instead, it is conceivable that the ordering of the triangle vertices is + incorrect and the ``--swap`` option should be specified. + +- The correct ordering of the surfaces is verified by checking that the + surfaces are inside each other as expected. This is accomplished by checking + that the sum solid angles subtended by triangles of a surface :math:`S_k` at + all vertices of another surface :math:`S_p` which is supposed to be inside it + equals :math:`4 \pi`. Naturally, this check is applied only if the model has + more than one surface. Since the surface relations are transitive, it is + enough to check that the outer skull surface is inside the skin surface and + that the inner skull surface is inside the outer skull one. + +- The extent of each of the triangulated volumes is checked. If the extent is + smaller than 50mm, an error is reported. This may indicate that the vertex + coordinates have been specified in meters instead of millimeters. + + +Computing the BEM geometry data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The utility :func:`mne.make_bem_solution` computes the geometry information for +BEM. + +.. _coil_geometry_information: + +Coil geometry information +~~~~~~~~~~~~~~~~~~~~~~~~~ + +This Section explains the presentation of MEG detection coil geometry +information the approximations used for different detection coils in MNE +software. Two pieces of information are needed to characterize the detectors: + +- The location and orientation a local coordinate system for each detector. + +- A unique identifier, which has an one-to-one correspondence to the + geometrical description of the coil. + +.. note:: MNE ships with several coil geometry configurations. They can be + found in ``mne/data``. See :ref:`ex-plot-meg-sensors` for a + comparison between different coil geometries, and + :ref:`implemented_coil_geometries` for detailed information regarding + the files describing Neuromag coil geometries. + + +The sensor coordinate system +---------------------------- + +The sensor coordinate system is completely characterized by the location of its +origin and the direction cosines of three orthogonal unit vectors pointing to +the directions of the x, y, and z axis. In fact, the unit vectors contain +redundant information because the orientation can be uniquely defined with +three angles. The measurement fif files list these data in MEG device +coordinates. Transformation to the MEG head coordinate frame can be easily +accomplished by applying the device-to-head coordinate transformation matrix +available in the data files provided that the head-position indicator was used. +Optionally, the MNE software forward calculation applies another coordinate +transformation to the head-coordinate data to bring the coil locations and +orientations to the MRI coordinate system. + +If :math:`r_0` is a row vector for the origin of the local sensor coordinate +system and :math:`e_x`, :math:`e_y`, and :math:`e_z` are the row vectors for +the three orthogonal unit vectors, all given in device coordinates, a location +of a point :math:`r_C` in sensor coordinates is transformed to device +coordinates (:math:`r_D`) by + +.. math:: [r_D 1] = [r_C 1] T_{CD}\ , + +where + +.. math:: T = \begin{bmatrix} + e_x & 0 \\ + e_y & 0 \\ + e_z & 0 \\ + r_{0D} & 1 + \end{bmatrix}\ . + +Calculation of the magnetic field +--------------------------------- + +The forward calculation in the MNE software computes the signals detected by +each MEG sensor for three orthogonal dipoles at each source space location. +This requires specification of the conductor model, the location and +orientation of the dipoles, and the location and orientation of each MEG sensor +as well as its coil geometry. + +The output of each SQUID sensor is a weighted sum of the magnetic fluxes +threading the loops comprising the detection coil. Since the flux threading a +coil loop is an integral of the magnetic field component normal to the coil +plane, the output of the k :sup:`th` MEG channel, :math:`b_k` can be +approximated by: + +.. math:: b_k = \sum_{p = 1}^{N_k} {w_{kp} B(r_{kp}) \cdot n_{kp}} + +where :math:`r_{kp}` are a set of :math:`N_k` integration points covering the +pickup coil loops of the sensor, :math:`B(r_{kp})` is the magnetic field due to +the current sources calculated at :math:`r_{kp}`, :math:`n_{kp}` are the coil +normal directions at these points, and :math:`w_{kp}` are the weights +associated to the integration points. This formula essentially presents +numerical integration of the magnetic field over the pickup loops of sensor +:math:`k`. + +There are three accuracy levels for the numerical integration expressed above. +The *simple* accuracy means the simplest description of the coil. This accuracy +is not used in the MNE forward calculations. The *normal* or *recommended* +accuracy typically uses two integration points for planar gradiometers, one in +each half of the pickup coil and four evenly distributed integration points for +magnetometers. This is the default accuracy used by MNE. If the ``--accurate`` +option is specified, the forward calculation typically employs a total of eight +integration points for planar gradiometers and sixteen for magnetometers. +Detailed information about the integration points is given in the next section. + + +.. _implemented_coil_geometries: + +Implemented coil geometries +--------------------------- + +This section describes the coil geometries currently implemented +in MNE. The coil types fall in two general categories: + +- Axial gradiometers and planar gradiometers + and + +- Planar magnetometers. + +For axial sensors, the *z* axis of the local coordinate system is parallel to +the field component detected, *i.e.*, normal to the coil plane.For circular +coils, the orientation of the *x* and *y* axes on the plane normal to the z +axis is irrelevant. In the square coils employed in the Vectorview (TM) system +the *x* axis is chosen to be parallel to one of the sides of the magnetometer +coil. For planar sensors, the *z* axis is likewise normal to the coil plane and +the x axis passes through the centerpoints of the two coil loops so that the +detector gives a positive signal when the normal field component increases +along the *x* axis. + +:ref:`normal_coil_descriptions` lists the parameters of the *normal* coil +geometry descriptions :ref:`accurate_coil_descriptions` lists the *accurate* +descriptions. For simple accuracy, please consult the coil definition file, see +:ref:`coil_definition_file`. The columns of the tables contain the following +data: + +- The number identifying the coil id. + This number is used in the coil descriptions found in the FIF files. + +- Description of the coil. + +- Number of integration points used + +- The locations of the integration points in sensor coordinates. + +- Weights assigned to the field values at the integration points. + Some formulas are listed instead of the numerical values to demonstrate + the principle of the calculation. For example, in the normal coil + descriptions of the planar gradiometers the weights are inverses + of the baseline of the gradiometer to show that the output is in + T/m. + +.. note:: The coil geometry information is stored in the file + :file:`mne/data/coil_def.dat`, which is + automatically created by the MNE-C utility ``mne_list_coil_def``. + +.. tabularcolumns:: |p{0.1\linewidth}|p{0.3\linewidth}|p{0.1\linewidth}|p{0.25\linewidth}|p{0.2\linewidth}| +.. table:: Normal coil descriptions + :name: normal_coil_descriptions + + +------+-------------------------+----+----------------------------------+----------------------+ + | Id | Description | n | r/mm | w | + +======+=========================+====+==================================+======================+ + | 2 | Neuromag-122 | 2 | (+/-8.1, 0, 0) mm | +/-1 ⁄ 16.2mm | + | | planar gradiometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 2000 | A point magnetometer | 1 | (0, 0, 0)mm | 1 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3012 | Vectorview type 1 | 2 | (+/-8.4, 0, 0.3) mm | +/-1 ⁄ 16.8mm | + | | planar gradiometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3013 | Vectorview type 2 | 2 | (+/-8.4, 0, 0.3) mm | +/-1 ⁄ 16.8mm | + | | planar gradiometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3022 | Vectorview type 1 | 4 | (+/-6.45, +/-6.45, 0.3)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3023 | Vectorview type 2 | 4 | (+/-6.45, +/-6.45, 0.3)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3024 | Vectorview type 3 | 4 | (+/-5.25, +/-5.25, 0.3)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 2000 | An ideal point | 1 | (0.0, 0.0, 0.0)mm | 1 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 4001 | Magnes WH | 4 | (+/-5.75, +/-5.75, 0.0)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 4002 | Magnes WH 3600 | 8 | (+/-4.5, +/-4.5, 0.0)mm | 1/4 | + | | axial gradiometer | | (+/-4.5, +/-4.5, 50.0)mm | -1/4 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 4003 | Magnes reference | 4 | (+/-7.5, +/-7.5, 0.0)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 4004 | Magnes reference | 8 | (+/-20, +/-20, 0.0)mm | 1/4 | + | | gradiometer measuring | | (+/-20, +/-20, 135)mm | -1/4 | + | | diagonal gradients | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 4005 | Magnes reference | 8 | (87.5, +/-20, 0.0)mm | 1/4 | + | | gradiometer measuring | | (47.5, +/-20, 0.0)mm | -1/4 | + | | off-diagonal gradients | | (-87.5, +/-20, 0.0)mm | 1/4 | + | | | | (-47.5, +/-20, 0.0)mm | -1/4 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 5001 | CTF 275 axial | 8 | (+/-4.5, +/-4.5, 0.0)mm | 1/4 | + | | gradiometer | | (+/-4.5, +/-4.5, 50.0)mm | -1/4 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 5002 | CTF reference | 4 | (+/-4, +/-4, 0.0)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 5003 | CTF reference | 8 | (+/-8.6, +/-8.6, 0.0)mm | 1/4 | + | | gradiometer measuring | | (+/-8.6, +/-8.6, 78.6)mm | -1/4 | + | | diagonal gradients | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + +.. note:: If a plus-minus sign occurs in several coordinates, all possible + combinations have to be included. + +.. tabularcolumns:: |p{0.1\linewidth}|p{0.3\linewidth}|p{0.05\linewidth}|p{0.25\linewidth}|p{0.15\linewidth}| +.. table:: Accurate coil descriptions + :name: accurate_coil_descriptions + + +------+-------------------------+----+----------------------------------+----------------------+ + | Id | Description | n | r/mm | w | + +======+=========================+====+==================================+======================+ + | 2 | Neuromag-122 planar | 8 | +/-(8.1, 0, 0) mm | +/-1 ⁄ 16.2mm | + | | gradiometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 2000 | A point magnetometer | 1 | (0, 0, 0) mm | 1 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3012 | Vectorview type 1 | 2 | (+/-8.4, 0, 0.3) mm | +/-1 ⁄ 16.8mm | + | | planar gradiometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3013 | Vectorview type 2 | 2 | (+/-8.4, 0, 0.3) mm | +/-1 ⁄ 16.8mm | + | | planar gradiometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3022 | Vectorview type 1 | 4 | (+/-6.45, +/-6.45, 0.3)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3023 | Vectorview type 2 | 4 | (+/-6.45, +/-6.45, 0.3)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 3024 | Vectorview type 3 | 4 | (+/-5.25, +/-5.25, 0.3)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 4001 | Magnes WH magnetometer | 4 | (+/-5.75, +/-5.75, 0.0)mm | 1/4 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 4002 | Magnes WH 3600 | 4 | (+/-4.5, +/-4.5, 0.0)mm | 1/4 | + | | axial gradiometer | | (+/-4.5, +/-4.5, 0.0)mm | -1/4 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 4004 | Magnes reference | 8 | (+/-20, +/-20, 0.0)mm | 1/4 | + | | gradiometer measuring | | (+/-20, +/-20, 135)mm | -1/4 | + | | diagonal gradients | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 4005 | Magnes reference | 8 | (87.5, +/-20, 0.0)mm | 1/4 | + | | gradiometer measuring | | (47.5, +/-20, 0.0)mm | -1/4 | + | | off-diagonal gradients | | (-87.5, +/-20, 0.0)mm | 1/4 | + | | | | (-47.5, +/-20, 0.0)mm | -1/4 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 5001 | CTF 275 axial | 8 | (+/-4.5, +/-4.5, 0.0)mm | 1/4 | + | | gradiometer | | (+/-4.5, +/-4.5, 50.0)mm | -1/4 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 5002 | CTF reference | 4 | (+/-4, +/-4, 0.0)mm | 1/4 | + | | magnetometer | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 5003 | CTF 275 reference | 8 | (+/-8.6, +/-8.6, 0.0)mm | 1/4 | + | | gradiometer measuring | | (+/-8.6, +/-8.6, 78.6)mm | -1/4 | + | | diagonal gradients | | | | + +------+-------------------------+----+----------------------------------+----------------------+ + | 5004 | CTF 275 reference | 8 | (47.8, +/-8.5, 0.0)mm | 1/4 | + | | gradiometer measuring | | (30.8, +/-8.5, 0.0)mm | -1/4 | + | | off-diagonal gradients | | (-47.8, +/-8.5, 0.0)mm | 1/4 | + | | | | (-30.8, +/-8.5, 0.0)mm | -1/4 | + +------+-------------------------+----+----------------------------------+----------------------+ + | 6001 | MIT KIT system axial | 8 | (+/-3.875, +/-3.875, 0.0)mm | 1/4 | + | | gradiometer | | (+/-3.875, +/-3.875, 0.0)mm | -1/4 | + +------+-------------------------+----+----------------------------------+----------------------+ + + +.. _coil_definition_file: + +The coil definition file +------------------------ + +The coil geometry information is stored in the text file +:file:`{$MNE_ROOT}/share/mne/coil_def.dat`. In this file, any lines starting +with the pound sign (#) are comments. A coil definition starts with a +description line containing the following fields: + +- :samp:`{}`: A number indicating class of this coil. + +- :samp:`{}`: Coil ID value. This value is listed in the first column of + Tables :ref:`normal_coil_descriptions` and :ref:`accurate_coil_descriptions`. + +- :samp:`{}`: The coil representation accuracy. Possible values and + their meanings are listed in :ref:`coil_accuracies`. + +- :samp:`{}`: Number of integration points in this representation. + +- :samp:`{}`: The size of the coil. For circular coils this is the + diameter of the coil and for square ones the side length of the square. This + information is mainly included to facilitate drawing of the coil geometry. It + should not be employed to infer a coil approximation for the forward + calculations. + +- :samp:`{}`: The baseline of a this kind of a coil. This will be + zero for magnetometer coils. This information is mainly included to + facilitate drawing of the coil geometry. It should not be employed to infer + a coil approximation for the forward calculations. + +- :samp:`{}`: Short description of this kind of a coil. If the + description contains several words, it is enclosed in quotes. + + +.. tabularcolumns:: |p{0.1\linewidth}|p{0.5\linewidth}| +.. table:: Coil representation accuracies + :name: coil_accuracies + + ======= ==================================================================================== + Value Meaning + ======= ==================================================================================== + 1 The simplest representation available + 2 The standard or *normal* representation (see :ref:`normal_coil_descriptions`) + 3 The most *accurate* representation available (see :ref:`accurate_coil_descriptions`) + ======= ==================================================================================== + +Each coil description line is followed by one or more integration point lines, +consisting of seven numbers: + +- :samp:`{}`: Gives the weight for this integration point (last column + in Tables :ref:`normal_coil_descriptions` and + :ref:`accurate_coil_descriptions`). + +- :samp:`{} {} {}`: Indicates the location of the integration + point (fourth column in Tables :ref:`normal_coil_descriptions` and + :ref:`accurate_coil_descriptions`). + +- :samp:`{} {} {}`: Components of a unit vector indicating the + field component to be selected. Note that listing a separate unit vector for + each integration points allows the implementation of curved coils and coils + with the gradiometer loops tilted with respect to each other. + + +Computing the forward solution +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Purpose +------- + +Examples on how to compute the forward solution in MNE-Python using +:func:`mne.make_forward_solution` can be found +:ref:`plot_forward_compute_forward_solution` and +:ref:`computing_the_forward_solution`. + +Implementation of software gradient compensation +------------------------------------------------ + +Accounting for noise cancellation in MNE-Python is accomplished in +:meth:`mne.io.Raw.apply_gradient_compensation`. See +:ref:`plot_brainstorm_phantom_ctf` for an example. + +CTF and 4D Neuroimaging data may have been subjected to noise cancellation +employing the data from the reference sensor array. Even though these sensor +are rather far away from the brain sources, :func:`mne.make_forward_solution` +takes them into account in the computations. If the data file has software +gradient compensation activated, it computes the field of at the reference +sensors in addition to the main MEG sensor array and computes a compensated +forward solution. + +The EEG sphere model definition file +------------------------------------ + +In MNE-Python, different sphere models can be specified through +:func:`mne.make_sphere_model`. The default model has the following structure: + +.. tabularcolumns:: |p{0.1\linewidth}|p{0.25\linewidth}|p{0.2\linewidth}| +.. table:: Structure of the default EEG model + + ======== ======================= ======================= + Layer Relative outer radius :math:`\sigma` (S/m) + ======== ======================= ======================= + Head 1.0 0.33 + Skull 0.97 0.04 + CSF 0.92 1.0 + Brain 0.90 0.33 + ======== ======================= ======================= + +Although it is not BEM model per se the ``sphere`` structure describes the head +geometry so it can be passed as ``bem`` parameter in MNE-Python functions such +as :func:`mne.fit_dipole`, :func:`mne.viz.plot_alignment` or +:func:`mne.make_forward_solution`. + +.. _eeg_sphere_model: + +EEG forward solution in the sphere model +---------------------------------------- + +.. note:: Sphere-model examples in MNE-Python + :class: sidebar + + For examples of using the sphere model when computing the forward model + (using :func:`mne.make_forward_solution`), see :ref:`Brainstorm CTF phantom + dataset tutorial `, + :ref:`Brainstorm Elekta phantom dataset tutorial + `, and + :ref:`tut-source-alignment-without-mri`. + +When the sphere model is employed, the computation of the EEG solution can be +substantially accelerated by using approximation methods described by Mosher +:footcite:`MosherEtAl1999`, Zhang :footcite:`Zhang1995`, and Berg +:footcite:`BergScherg1994`. +:func:`mne.make_forward_solution` approximates the solution with three dipoles +in a homogeneous sphere whose locations and amplitudes are determined by +minimizing the cost function: + +.. math:: + S(r_1,\dotsc,r_m\ ,\ \mu_1,\dotsc,\mu_m) = \int_{scalp} {(V_{true} - V_{approx})}\,dS + +where :math:`r_1,\dotsc,r_m` and :math:`\mu_1,\dotsc,\mu_m` are the locations +and amplitudes of the approximating dipoles and :math:`V_{true}` and +:math:`V_{approx}` are the potential distributions given by the true and +approximative formulas, respectively. It can be shown that this integral can be +expressed in closed form using an expansion of the potentials in spherical +harmonics. The formula is evaluated for the most superficial dipoles, *i.e.*, +those lying just inside the inner skull surface. + +Averaging forward solutions +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +One possibility to make a grand average over several runs of a experiment is to +average the data across runs and average the forward solutions accordingly. For +this purpose, :func:`mne.average_forward_solutions` computes a weighted average +of several forward solutions. The function averages both MEG and EEG forward +solutions. Usually the EEG forward solution is identical across runs because +the electrode locations do not change. + +.. target for :end-before: forward-end-content diff --git a/mne-python/source/doc/_includes/ged.rst b/mne-python/source/doc/_includes/ged.rst new file mode 100644 index 0000000000000000000000000000000000000000..5146fef5ffa747a6efa5c0e8944f4c51c0bb8e00 --- /dev/null +++ b/mne-python/source/doc/_includes/ged.rst @@ -0,0 +1,107 @@ +:orphan: + +Generalized eigendecomposition in decoding +========================================== + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`ged` to link to that section of the implementation.rst page. + The next line is a target for :start-after: so we can omit the title from + the include: + ged-begin-content + +This section describes the mathematical formulation and application of +Generalized Eigendecomposition (GED), often used in spatial filtering +and source separation algorithms, such as :class:`mne.decoding.CSP`, +:class:`mne.decoding.SPoC`, :class:`mne.decoding.SSD` and +:class:`mne.decoding.XdawnTransformer`. + +The core principle of GED is to find a set of channel weights (spatial filter) +that maximizes the ratio of signal power between two data features. +These features are defined by the researcher and are represented by two covariance matrices: +a "signal" matrix :math:`S` and a "reference" matrix :math:`R`. +For example, :math:`S` could be the covariance of data from a task time interval, +and :math:`S` could be the covariance from a baseline time interval. For more details see :footcite:`Cohen2022`. + +Algebraic formulation of GED +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A few definitions first: +Let :math:`n \in \mathbb{N}^+` be a number of channels. +Let :math:`\text{Symm}_n(\mathbb{R}) \subset M_n(\mathbb{R})` be a vector space of real symmetric matrices. +Let :math:`S^n_+, S^n_{++} \subset \text{Symm}_n(\mathbb{R})` be sets of real positive semidefinite and positive definite matrices, respectively. +Let :math:`S, R \in S^n_+` be covariance matrices estimated from electrophysiological data :math:`X_S \in M_{n \times t_S}(\mathbb{R})` and :math:`X_R \in M_{n \times t_R}(\mathbb{R})`. + +GED (or simultaneous diagonalization by congruence) of :math:`S` and :math:`R` +is possible when :math:`R` is full rank (and thus :math:`R \in S^n_{++}`): + +.. math:: + + SW = RWD, + +where :math:`W \in M_n(\mathbb{R})` is an invertible matrix of eigenvectors +of :math:`(S, R)` and :math:`D` is a diagonal matrix of eigenvalues :math:`\lambda_i`. + +Each eigenvector :math:`\mathbf{w} \in W` is a spatial filter that solves +an optimization problem of the form: + +.. math:: + + \operatorname{argmax}_{\mathbf{w}} \frac{\mathbf{w}^t S \mathbf{w}}{\mathbf{w}^t R \mathbf{w}} + +That is, using spatial filters :math:`W` on time-series :math:`X \in M_{n \times t}(\mathbb{R})`: + +.. math:: + + \mathbf{A} = W^t X, + +results in "activation" time-series :math:`A` of the estimated "sources", +such that the ratio of their variances, +:math:`\frac{\text{Var}(\mathbf{w}^T X_S)}{\text{Var}(\mathbf{w}^T X_R)} = \frac{\mathbf{w}^T S \mathbf{w}}{\mathbf{w}^T R \mathbf{w}}`, +is sequentially maximized spatial filters :math:`\mathbf{w}_i`, sorted according to :math:`\lambda_i`. + +GED in the principal subspace +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Unfortunately, :math:`R` might not be full rank depending on the data :math:`X_R` (for example due to average reference, removed PCA/ICA components, etc.). +In such cases, GED can be performed on :math:`S` and :math:`R` in the principal subspace :math:`Q = \operatorname{Im}(C_{ref}) \subset \mathbb{R}^n` of some reference +covariance :math:`C_{ref}` (in Common Spatial Pattern (CSP) algorithm, for example, :math:`C_{ref}=\frac{1}{2}(S+R)` and GED is performed on S and R'=S+R). + +More formally: +Let :math:`r \leq n` be a rank of :math:`C \in S^n_+`. +Let :math:`Q=\operatorname{Im}(C_{ref})` be a principal subspace of :math:`C_{ref}`. +Let :math:`P \in M_{n \times r}(\mathbb{R})` be an isometry formed by orthonormal basis of :math:`Q`. +Let :math:`f:S^n_+ \to S^r_+`, :math:`A \mapsto P^t A P` be a "restricting" map, that restricts quadratic form +:math:`q_A:\mathbb{R}^n \to \mathbb{R}` to :math:`q_{A|_Q}:\mathbb{R}^n \to \mathbb{R}` (in practical terms, :math:`q_A` maps +spatial filters to variance of the spatially filtered data :math:`X_A`). + +Then, the GED of :math:`S` and :math:`R` in the principal subspace :math:`Q` of :math:`C_{ref}` is performed as follows: + +1. :math:`S` and :math:`R` are transformed to :math:`S_Q = f(S) = P^t S P` and :math:`R_Q = f(R) = P^t R P`, + such that :math:`S_Q` and :math:`R_Q` are matrix representations of restricted :math:`q_{S|_Q}` and :math:`q_{R|_Q}`. +2. GED is performed on :math:`S_Q` and :math:`R_Q`: :math:`S_Q W_Q = R_Q W_Q D`. +3. Eigenvectors :math:`W_Q` of :math:`(S_Q, R_Q)` are transformed back to :math:`\mathbb{R}^n` + by :math:`W = P W_Q \in \mathbb{R}^{n \times r}` to obtain :math:`r` spatial filters. + +Note that the solution to the original optimization problem is preserved: + +.. math:: + + \frac{\mathbf{w_Q}^t S_Q \mathbf{w_Q}}{\mathbf{w_Q}^t R_Q \mathbf{w_Q}}= \frac{\mathbf{w_Q}^t (P^t S P) \mathbf{w_Q}}{\mathbf{w_Q}^t (P^t R P) + \mathbf{w_Q}} = \frac{\mathbf{w}^t S \mathbf{w}}{\mathbf{w}^t R \mathbf{w}} = \lambda + + +In addition to restriction, :math:`q_S` and :math:`q_R` can be rescaled based on the whitened :math:`C_{ref}`. +In this case the whitening map :math:`f_{wh}:S^n_+ \to S^r_+`, +:math:`A \mapsto P_{wh}^t A P_{wh}` transforms :math:`A` into matrix representation of :math:`q_{A|Q}` rescaled according to :math:`\Lambda^{-1/2}`, +where :math:`\Lambda` is a diagonal matrix of eigenvalues of :math:`C_{ref}` and so :math:`P_{wh} = P \Lambda^{-1/2}`. + +In MNE-Python, the matrix :math:`P` of the restricting map can be obtained using +:: + + _, ref_evecs, mask = mne.cov._smart_eigh(C_ref, ..., proj_subspace=True, ...) + restr_mat = ref_evecs[mask] + +while :math:`P_{wh}` using: +:: + + restr_mat = compute_whitener(C_ref, ..., pca=True, ...) \ No newline at end of file diff --git a/mne-python/source/doc/_includes/institutional-partners.rst b/mne-python/source/doc/_includes/institutional-partners.rst new file mode 100644 index 0000000000000000000000000000000000000000..3316670b7b6f12bed5311ed650b06f4a47e75ff8 --- /dev/null +++ b/mne-python/source/doc/_includes/institutional-partners.rst @@ -0,0 +1,44 @@ +:orphan: + +Institutional partners +---------------------- + +.. NOTE: this file is included in doc/funding.rst and doc/overview/people.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`supporting-institutions` to link to that section of the funding.rst + page. The next line is a target for :start-after: so we can omit the title + from the include: + institutional-partners-begin-content + +Current partners +~~~~~~~~~~~~~~~~ + +- `Aalto-yliopiston perustieteiden korkeakoulu `_ +- `Donders Institute for Brain, Cognition and Behaviour at Radboud University `_ +- `Karl-Franzens-Universität Graz `_ +- `University of Washington `_ + +Former partners +~~~~~~~~~~~~~~~ + +- `Aarhus Universitet `_ +- `AE Studio `_ +- `Athinoula A. Martinos Center for Biomedical Imaging `_ +- `Berkeley Institute for Data Science `_ +- `Boston University `_ +- `Children’s Hospital of Philadelphia Research Institute `_ +- `Commissariat à l’énergie atomique et aux énergies alternatives `_ +- `Fondation Campus Biotech Geneva `_ +- `Forschungszentrum Jülich `_ +- `Harvard Medical School `_ +- `Institut du Cerveau et de la Moelle épinière `_ +- `Institut national de la santé et de la recherche médicale `_ +- `Institut national de recherche en informatique et en automatique `_ +- `Massachusetts General Hospital `_ +- `Massachusetts Institute of Technology `_ +- `Max-Planck-Institut für Bildungsforschung `_ +- `Macquarie University `_ +- `New York University `_ +- `SWPS Uniwersytet Humanistycznospołeczny `_ +- `Technische Universität Ilmenau `_ +- `Télécom ParisTech `_ diff --git a/mne-python/source/doc/_includes/inverse.rst b/mne-python/source/doc/_includes/inverse.rst new file mode 100644 index 0000000000000000000000000000000000000000..6d0d77ed8bba3c23f263ca89cd152c905eb17aa0 --- /dev/null +++ b/mne-python/source/doc/_includes/inverse.rst @@ -0,0 +1,607 @@ +.. _ch_mne: + +The minimum-norm current estimates +================================== + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`ch_mne` to link to that section of the implementation.rst page. + The next line is a target for :start-after: so we can omit the title from + the include: + inverse-begin-content + + +This section describes the mathematical details of the calculation of +minimum-norm estimates. In Bayesian sense, the ensuing current distribution is +the maximum a posteriori (MAP) estimate under the following assumptions: + +- The viable locations of the currents are constrained to the cortex. + Optionally, the current orientations can be fixed to be normal to the + cortical mantle. + +- The amplitudes of the currents have a Gaussian prior distribution with a + known source covariance matrix. + +- The measured data contain additive noise with a Gaussian distribution with a + known covariance matrix. The noise is not correlated over time. + +Computing the inverse operator is accomplished using +:func:`mne.minimum_norm.make_inverse_operator` and +:func:`mne.minimum_norm.apply_inverse`. The use of these functions is presented +in the tutorial :ref:`tut-inverse-methods`. + +The linear inverse operator +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The measured data in the source estimation procedure consists of MEG and EEG +data, recorded on a total of N channels. The task is to estimate a total of +:math:`Q` +strengths of sources located on the cortical mantle. If the number of source +locations is :math:`P`, :math:`Q = P` for fixed-orientation sources and +:math:`Q = 3P` if the source +orientations are unconstrained. The regularized linear inverse operator +following from regularized maximal likelihood of the above probabilistic model +is given by the :math:`Q \times N` matrix + +.. math:: M = R' G^\top (G R' G^\top + C)^{-1}\ , + +where :math:`G` is the gain matrix relating the source strengths to the measured +MEG/EEG data, :math:`C` is the data noise-covariance matrix and :math:`R'` is +the source covariance matrix. The dimensions of these matrices are :math:`N +\times Q`, :math:`N \times N`, and :math:`Q \times Q`, respectively. The +:math:`Q \times 1` source-strength vector is obtained by multiplying the +:math:`Q \times 1` data vector by :math:`Q`. + +The expected value of the current amplitudes at time *t* is then given by +:math:`\hat{j}(t) = Mx(t)`, where :math:`x(t)` is a vector containing the +measured MEG and EEG data values at time *t*. + +For computational convenience, the linear inverse operator is +not computed explicitly. See :ref:`mne_solution` for mathematical +details, and :ref:`CIHCFJEI` for a detailed example. + +.. _mne_regularization: + +Regularization +~~~~~~~~~~~~~~ + +The a priori variance of the currents is, in practice, unknown. We can express +this by writing :math:`R' = R/ \lambda^2 = R \lambda^{-2}`, which yields the +inverse operator + +.. math:: + :name: inv_m + + M &= R' G^\top (G R' G^\top + C)^{-1} \\ + &= R \lambda^{-2} G^\top (G R \lambda^{-2} G^\top + C)^{-1} \\ + &= R \lambda^{-2} G^\top \lambda^2 (G R G^\top + \lambda^2 C)^{-1} \\ + &= R G^\top (G R G^\top + \lambda^2 C)^{-1}\ , + +where the unknown current amplitude is now interpreted in terms of the +regularization parameter :math:`\lambda^2`. Larger :math:`\lambda^2` values +correspond to spatially smoother and weaker current amplitudes, whereas smaller +:math:`\lambda^2` values lead to the opposite. + +We can arrive at the regularized linear inverse operator also by minimizing a +cost function :math:`S` with respect to the estimated current :math:`\hat{j}` +(given the measurement vector :math:`x` at any given time :math:`t`) as + +.. math:: + + \min_\hat{j} \Bigl\{ S \Bigr\} &= \min_\hat{j} \Bigl\{ \tilde{e}^\top \tilde{e} + \lambda^2 \hat{j}^\top R^{-1} \hat{j} \Bigr\} \\ + &= \min_\hat{j} \Bigl\{ (x - G\hat{j})^\top C^{-1} (x - G\hat{j}) + \lambda^2 \hat{j}^\top R^{-1} \hat{j} \Bigr\} \, + +where the first term consists of the difference between the whitened measured +data (see :ref:`whitening_and_scaling`) and those predicted by the model while the +second term is a weighted-norm of the current estimate. It is seen that, with +increasing :math:`\lambda^2`, the source term receive more weight and larger +discrepancy between the measured and predicted data is tolerable. + +.. _whitening_and_scaling: + +Whitening and scaling +~~~~~~~~~~~~~~~~~~~~~ + +The MNE software employs data whitening so that a 'whitened' inverse operator +assumes the form + +.. math:: \tilde{M} = M C^{^1/_2} = R \tilde{G}^\top (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1}\ , + :name: inv_m_tilde + +where + +.. math:: \tilde{G} = C^{-^1/_2}G + :name: inv_g_tilde + +is the spatially whitened gain matrix. We arrive at the whitened inverse +operator equation :eq:`inv_m_tilde` by making the substitution for +:math:`G` from :eq:`inv_g_tilde` in :eq:`inv_m` as + +.. math:: + + \tilde{M} = M C^{^1/_2} &= R G^\top (G R G^\top + \lambda^2 C)^{-1} C^{^1/_2} \\ + &= R \tilde{G}^\top C^{^1/_2} (C^{^1/_2} \tilde{G} R \tilde{G}^\top C^{^1/_2} + \lambda^2 C)^{-1} C^{^1/_2} \\ + &= R \tilde{G}^\top C^{^1/_2} (C^{^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I) C^{^1/_2})^{-1} C^{^1/_2} \\ + &= R \tilde{G}^\top C^{^1/_2} C^{-^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1} C^{-^1/_2} C^{^1/_2} \\ + &= R \tilde{G}^\top (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1}\ . + +The expected current values are + +.. math:: + :name: inv_j_hat_t + + \hat{j}(t) &= Mx(t) \\ + &= M C^{^1/_2} C^{-^1/_2} x(t) \\ + &= \tilde{M} \tilde{x}(t) + +knowing :eq:`inv_m_tilde` and taking + +.. math:: + :name: inv_tilde_x_t + + \tilde{x}(t) = C^{-^1/_2}x(t) + +as the whitened measurement vector at time *t*. The spatial +whitening operator :math:`C^{-^1/_2}` is obtained with the help of the +eigenvalue decomposition +:math:`C = U_C \Lambda_C^2 U_C^\top` as :math:`C^{-^1/_2} = \Lambda_C^{-1} U_C^\top`. +In the MNE software the noise-covariance matrix is stored as the one applying +to raw data. To reflect the decrease of noise due to averaging, this matrix, +:math:`C_0`, is scaled by the number of averages, :math:`L`, *i.e.*, :math:`C = +C_0 / L`. + +.. note:: + When EEG data are included, the gain matrix :math:`G` needs to be average referenced when computing the linear inverse operator :math:`M`. This is incorporated during creating the spatial whitening operator :math:`C^{-^1/_2}`, which includes any projectors on the data. EEG data average reference (using a projector) is mandatory for source modeling and is checked when calculating the inverse operator. + +As shown above, regularization of the inverse solution is equivalent to a +change in the variance of the current amplitudes in the Bayesian *a priori* +distribution. + +A convenient choice for the source-covariance matrix :math:`R` is such that +:math:`\text{trace}(\tilde{G} R \tilde{G}^\top) / \text{trace}(I) = 1`. With this +choice we can approximate :math:`\lambda^2 \sim 1/\rm{SNR}^2`, where SNR is the +(amplitude) signal-to-noise ratio of the whitened data. + +.. note:: + The definition of the signal to noise-ratio/ :math:`\lambda^2` relationship + given above works nicely for the whitened forward solution. In the + un-whitened case scaling with the trace ratio :math:`\text{trace}(GRG^\top) / + \text{trace}(C)` does not make sense, since the diagonal elements summed + have, in general, different units of measure. For example, the MEG data are + expressed in T or T/m whereas the unit of EEG is Volts. + +See :ref:`tut-compute-covariance` for example of noise covariance computation +and whitening. + +.. _cov_regularization_math: + +Regularization of the noise-covariance matrix +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since finite amount of data is usually available to compute an estimate of the +noise-covariance matrix :math:`C`, the smallest eigenvalues of its estimate are +usually inaccurate and smaller than the true eigenvalues. Depending on the +seriousness of this problem, the following quantities can be affected: + +- The model data predicted by the current estimate, + +- Estimates of signal-to-noise ratios, which lead to estimates of the required + regularization, see :ref:`mne_regularization`, + +- The estimated current values, and + +- The noise-normalized estimates, see :ref:`noise_normalization`. + +Fortunately, the latter two are least likely to be affected due to +regularization of the estimates. However, in some cases especially the EEG part +of the noise-covariance matrix estimate can be deficient, *i.e.*, it may +possess very small eigenvalues and thus regularization of the noise-covariance +matrix is advisable. + +Historically, the MNE software accomplishes the regularization by replacing a +noise-covariance matrix estimate :math:`C` with + +.. math:: C' = C + \sum_k {\varepsilon_k \bar{\sigma_k}^2 I^{(k)}}\ , + +where the index :math:`k` goes across the different channel groups (MEG planar +gradiometers, MEG axial gradiometers and magnetometers, and EEG), +:math:`\varepsilon_k` are the corresponding regularization factors, +:math:`\bar{\sigma_k}` are the average variances across the channel groups, and +:math:`I^{(k)}` are diagonal matrices containing ones at the positions +corresponding to the channels contained in each channel group. + +See :ref:`plot_compute_covariance_howto` for details on computing and +regularizing the channel covariance matrix. + +.. _mne_solution: + +Computation of the solution +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The most straightforward approach to calculate the MNE is to employ the +expression of the original or whitened inverse operator directly. However, for +computational convenience we prefer to take another route, which employs the +singular-value decomposition (SVD) of the matrix + +.. math:: + :name: inv_a + + A &= \tilde{G} R^{^1/_2} \\ + &= U \Lambda V^\top + +where the superscript :math:`^1/_2` indicates a square root of :math:`R`. For a +diagonal matrix, one simply takes the square root of :math:`R` while in the +more general case one can use the Cholesky factorization :math:`R = R_C R_C^\top` +and thus :math:`R^{^1/_2} = R_C`. + +Combining the SVD from :eq:`inv_a` with the inverse equation :eq:`inv_m` it is +easy to show that + +.. math:: + :name: inv_m_tilde_svd + + \tilde{M} &= R \tilde{G}^\top (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1} \\ + &= R^{^1/_2} A^\top (A A^\top + \lambda^2 I)^{-1} \\ + &= R^{^1/_2} V \Lambda U^\top (U \Lambda V^\top V \Lambda U^\top + \lambda^2 I)^{-1} \\ + &= R^{^1/_2} V \Lambda U^\top (U (\Lambda^2 + \lambda^2 I) U^\top)^{-1} \\ + &= R^{^1/_2} V \Lambda U^\top U (\Lambda^2 + \lambda^2 I)^{-1} U^\top \\ + &= R^{^1/_2} V \Lambda (\Lambda^2 + \lambda^2 I)^{-1} U^\top \\ + &= R^{^1/_2} V \Gamma U^\top + +where the elements of the diagonal matrix :math:`\Gamma` are simply + +.. `reginv` in our code: + +.. math:: + :name: inv_gamma_k + + \gamma_k = \frac{\lambda_k}{\lambda_k^2 + \lambda^2}\ . + +From our expected current equation :eq:`inv_j_hat_t` and our whitened +measurement equation :eq:`inv_tilde_x_t`, if we take + +.. math:: + :name: inv_w_t + + w(t) &= U^\top \tilde{x}(t) \\ + &= U^\top C^{-^1/_2} x(t)\ , + +we can see that the expression for the expected current is just + +.. math:: + :name: inv_j_hat_t_svd + + \hat{j}(t) &= R^{^1/_2} V \Gamma w(t) \\ + &= \sum_k {\bar{v_k} \gamma_k w_k(t)}\ , + +where :math:`\bar{v_k} = R^{^1/_2} v_k`, with :math:`v_k` being the +:math:`k` th column of :math:`V`. It is thus seen that the current estimate is +a weighted sum of the "weighted" eigenleads :math:`v_k`. + +It is easy to see that :math:`w(t) \propto \sqrt{L}`. To maintain the relation +:math:`(\tilde{G} R \tilde{G}^\top) / \text{trace}(I) = 1` when :math:`L` changes +we must have :math:`R \propto 1/L`. With this approach, :math:`\lambda_k` is +independent of :math:`L` and, for fixed :math:`\lambda`, we see directly that +:math:`j(t)` is independent of :math:`L`. + +The minimum-norm estimate is computed using this procedure in +:func:`mne.minimum_norm.make_inverse_operator`, and its usage is illustrated +in :ref:`CIHCFJEI`. + + +.. _noise_normalization: + +Noise normalization +~~~~~~~~~~~~~~~~~~~ + +Noise normalization serves three purposes: + +- It converts the expected current value into a dimensionless statistical test + variable. Thus the resulting time and location dependent values are often + referred to as dynamic statistical parameter maps (dSPM). + +- It reduces the location bias of the estimates. In particular, the tendency of + the MNE to prefer superficial currents is eliminated. + +- The width of the point-spread function becomes less dependent on the source + location on the cortical mantle. The point-spread is defined as the MNE + resulting from the signals coming from a point current source (a current + dipole) located at a certain point on the cortex. + +In practice, noise normalization is implemented as a division by the square +root of the estimated variance of each voxel. In computing these noise +normalization factors, it's convenient to reuse our "weighted eigenleads" +definition from equation :eq:`inv_j_hat_t` in matrix form as + +.. math:: + :name: inv_eigenleads_weighted + + \bar{V} = R^{^1/_2} V\ . + +dSPM +---- + +Noise-normalized linear estimates introduced by Dale et al. +:footcite:`DaleEtAl1999` require division of the expected current amplitude by +its variance. In practice, this requires the computation of the diagonal +elements of the following matrix, using SVD equation :eq:`inv_m_tilde` and +:eq:`inv_eigenleads_weighted`: + +.. math:: + + M C M^\top &= M C^{^1/_2} C^{^1/_2} M^\top \\ + &= \tilde{M} \tilde{M}^\top \\ + &= R^{^1/_2} V \Gamma U^\top U \Gamma V^\top R^{^1/_2} \\ + &= \bar{V} \Gamma^2 \bar{V}^\top\ . + +Because we only care about the diagonal entries here, we can find the +variances for each source as + +.. math:: + + \sigma_k^2 = \gamma_k^2 + +Under the conditions expressed at the end of :ref:`mne_solution`, it +follows that the *t*-statistic values associated with fixed-orientation +sources) are thus proportional to :math:`\sqrt{L}` while the *F*-statistic +employed with free-orientation sources is proportional to :math:`L`, +correspondingly. + +.. note:: + The MNE software usually computes the *square roots* of the F-statistic to + be displayed on the inflated cortical surfaces. These are also proportional + to :math:`\sqrt{L}`. + +sLORETA +------- +sLORETA :footcite:`Pascual-Marqui2002` estimates the current variances as the +diagonal entries of the +resolution matrix, which is the product of the inverse and forward operators. +In other words, the diagonal entries of (using :eq:`inv_m_tilde_svd`, +:eq:`inv_g_tilde`, and :eq:`inv_a`) + +.. math:: + + M G &= M C^{^1/_2} C^{-^1/_2} G \\ + &= \tilde{M} \tilde{G} \\ + &= R^{^1/_2} V \Gamma U^\top \tilde{G} R^{^1/_2} R^{-^1/_2} \\ + &= R^{^1/_2} V \Gamma U^\top U \Lambda V^\top R^{-^1/_2} \\ + &= R^{^1/_2} V \Gamma U^\top U \Lambda V^\top R^{^1/_2} R^{-1} \\ + &= \bar{V} \Gamma U^\top U \Lambda \bar{V}^\top R^{-1} \\ + &= \bar{V} \Gamma \Lambda \bar{V}^\top R^{-1}\ . + +Because :math:`R` is diagonal and we only care about the diagonal entries, +we can find our variance estimates as + +.. math:: + + \sigma_k^2 &= \gamma_k \lambda_k R_{k,k}^{-1} \\ + &= \left(\frac{\lambda_k}{(\lambda_k^2 + \lambda^2)}\right) \left(\frac{\lambda_k}{1}\right) \left(\frac{1}{\lambda^2}\right) \\ + &= \frac{\lambda_k^2}{(\lambda_k^2 + \lambda^2) \lambda^2} \\ + &= \left(\frac{\lambda_k^2}{(\lambda_k^2 + \lambda^2)^2}\right) \left(\frac{\lambda^2 + \lambda_k^2}{\lambda^2}\right) \\ + &= \left(\frac{\lambda_k}{\lambda_k^2 + \lambda^2}\right)^2 \left(1 + \frac{\lambda_k^2}{\lambda^2}\right) \\ + &= \gamma_k^2 \left(1 + \frac{\lambda_k^2}{\lambda^2}\right)\ . + +eLORETA +~~~~~~~ +While dSPM and sLORETA solve for noise normalization weights +:math:`\sigma^2_k` that are applied to standard minimum-norm estimates +:math:`\hat{j}(t)`, eLORETA :footcite:`Pascual-Marqui2011` instead solves for +a source covariance +matrix :math:`R` that achieves zero localization bias. For fixed-orientation +solutions the resulting matrix :math:`R` will be a diagonal matrix, and for +free-orientation solutions it will be a block-diagonal matrix with +:math:`3 \times 3` blocks. + +.. In https://royalsocietypublishing.org/doi/full/10.1098/rsta.2011.0081 +.. eq. 2.10 (classical min norm), their values map onto our values as: +.. +.. - α=λ² +.. - W=R⁻¹ (pos semidef weight matrix) +.. - K=G +.. - ϕ=x +.. - C=H +.. + +In :footcite:`Pascual-Marqui2011` eq. 2.13 states that the following system +of equations can be used to find the weights, :math:`\forall i \in {1, ..., P}` +(note that here we represent the equations from that paper using our notation): + +.. math:: r_i = \left[ G_i^\top \left( GRG^\top + \lambda^2C \right)^{-1} G_i \right] ^{-^1/_2} + +And an iterative algorithm can be used to find the values for the weights +:math:`r_i` that satisfy these equations as: + +1. Initialize identity weights. +2. Compute :math:`N= \left( GRG^\top + \lambda^2C \right)^{-1}`. +3. Holding :math:`N` fixed, compute new weights :math:`r_i = \left[ G_i^\top N G_i \right]^{-^1/_2}`. +4. Using new weights, go to step (2) until convergence. + +In particular, for step (2) we can use our substitution from :eq:`inv_g_tilde` +as: + +.. math:: + + N &= (G R G^\top + \lambda^2 C)^{-1} \\ + &= (C^{^1/_2} \tilde{G} R \tilde{G}^\top C^{^1/_2} + \lambda^2 C)^{-1} \\ + &= (C^{^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I) C^{^1/_2})^{-1} \\ + &= C^{-^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1} C^{-^1/_2} \\ + &= C^{-^1/_2} (\tilde{G} R \tilde{G}^\top + \lambda^2 I)^{-1} C^{-^1/_2}\ . + +Then defining :math:`\tilde{N}` as the whitened version of :math:`N`, i.e., +the regularized pseudoinverse of :math:`\tilde{G}R\tilde{G}^\top`, we can +compute :math:`N` as: + +.. math:: + + N &= C^{-^1/_2} (U_{\tilde{G}R\tilde{G}^\top} \Lambda_{\tilde{G}R\tilde{G}^\top} V_{\tilde{G}R\tilde{G}^\top}^\top + \lambda^2 I)^{-1} C^{-^1/_2} \\ + &= C^{-^1/_2} (U_{\tilde{G}R\tilde{G}^\top} (\Lambda_{\tilde{G}R\tilde{G}^\top} + \lambda^2 I) V_{\tilde{G}R\tilde{G}^\top}^\top)^{-1} C^{-^1/_2} \\ + &= C^{-^1/_2} V_{\tilde{G}R\tilde{G}^\top} (\Lambda_{\tilde{G}R\tilde{G}^\top} + \lambda^2 I)^{-1} U_{\tilde{G}R\tilde{G}^\top}^\top C^{-^1/_2} \\ + &= C^{-^1/_2} \tilde{N} C^{-^1/_2}\ . + +In step (3) we left and right multiply with subsets of :math:`G`, but making +the substitution :eq:`inv_g_tilde` we see that we equivalently compute: + +.. math:: + + r_i &= \left[ G_i^\top N G_i \right]^{-^1/_2} \\ + &= \left[ (C^{^1/_2} \tilde{G}_i)^\top N C^{^1/_2} \tilde{G}_i \right]^{-^1/_2} \\ + &= \left[ \tilde{G}_i^\top C^{^1/_2} N C^{^1/_2} \tilde{G}_i \right]^{-^1/_2} \\ + &= \left[ \tilde{G}_i^\top C^{^1/_2} C^{-^1/_2} \tilde{N} C^{-^1/_2} C^{^1/_2} \tilde{G}_i \right]^{-^1/_2} \\ + &= \left[ \tilde{G}_i^\top \tilde{N} \tilde{G}_i \right]^{-^1/_2}\ . + +For convenience, we thus never need to compute :math:`N` itself but can instead +compute the whitened version :math:`\tilde{N}`. + +Predicted data +~~~~~~~~~~~~~~ + +Under noiseless conditions the SNR is infinite and thus leads to +:math:`\lambda^2 = 0` and the minimum-norm estimate explains the measured data +perfectly. Under realistic conditions, however, :math:`\lambda^2 > 0` and there +is a misfit between measured data and those predicted by the MNE. Comparison of +the predicted data, here denoted by :math:`x(t)`, and measured one can give +valuable insight on the correctness of the regularization applied. + +In the SVD approach we easily find + +.. math:: \hat{x}(t) = G \hat{j}(t) = C^{^1/_2} U \Pi w(t)\ , + +where the diagonal matrix :math:`\Pi` has elements :math:`\pi_k = \lambda_k +\gamma_k` The predicted data is thus expressed as the weighted sum of the +'recolored eigenfields' in :math:`C^{^1/_2} U`. + +Cortical patch statistics +~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the ``add_dists=True`` option was used in source space creation, +the source space file will contain +Cortical Patch Statistics (CPS) for each vertex of the cortical surface. The +CPS provide information about the source space point closest to it as well as +the distance from the vertex to this source space point. The vertices for which +a given source space point is the nearest one define the cortical patch +associated with with the source space point. Once these data are available, it +is straightforward to compute the following cortical patch statistics for each +source location :math:`d`: + +- The average over the normals of at the vertices in a patch, + :math:`\bar{n_d}`, + +- The areas of the patches, :math:`A_d`, and + +- The average deviation of the vertex normals in a patch from their average, + :math:`\sigma_d`, given in degrees. + +``use_cps`` parameter in :func:`mne.convert_forward_solution`, and +:func:`mne.minimum_norm.make_inverse_operator` controls whether to use +cortical patch statistics (CPS) to define normal orientations or not (see +:ref:`CHDBBCEJ`). + +.. _inverse_orientation_constraints: + +Orientation constraints +~~~~~~~~~~~~~~~~~~~~~~~ + +The principal sources of MEG and EEG signals are generally believed to be +postsynaptic currents in the cortical pyramidal neurons. Since the net primary +current associated with these microscopic events is oriented normal to the +cortical mantle, it is reasonable to use the cortical normal orientation as a +constraint in source estimation. In addition to allowing completely free source +orientations, the MNE software implements three orientation constraints based +of the surface normal data: + +- Source orientation can be rigidly fixed to the surface normal direction by + specifying ``fixed=True`` in :func:`mne.minimum_norm.make_inverse_operator`. + If cortical patch statistics are available the average + normal over each patch, :math:`\bar{n_d}`, are used to define the source + orientation. Otherwise, the vertex normal at the source space location is + employed. + +- A *location independent or fixed loose orientation constraint* (fLOC) can be + employed by specifying ``fixed=False`` and ``loose=1.0`` when + calling :func:`mne.minimum_norm.make_inverse_operator` (see + :ref:`plot_dipole_orientations_fLOC_orientations`). + In this approach, a source coordinate + system based on the local surface orientation at the source location is + employed. By default, the three columns of the gain matrix G, associated with + a given source location, are the fields of unit dipoles pointing to the + directions of the :math:`x`, :math:`y`, and :math:`z` axis of the coordinate + system employed in the forward calculation (usually the :ref:`MEG head + coordinate frame `). For LOC the orientation is changed so + that the first two source components lie in the plane normal to the surface + normal at the source location and the third component is aligned with it. + Thereafter, the variance of the source components tangential to the cortical + surface are reduced by a factor defined by the ``--loose`` option. + +- A *variable loose orientation constraint* (vLOC) can be employed by + specifying ``fixed=False`` and ``loose`` parameters when calling + :func:`mne.minimum_norm.make_inverse_operator` (see + :ref:`plot_dipole_orientations_vLOC_orientations`). This + is similar to *fLOC* except that the value given with the ``loose`` + parameter will be multiplied by :math:`\sigma_d`, defined above. + +Depth weighting +~~~~~~~~~~~~~~~ + +The minimum-norm estimates have a bias towards superficial currents. This +tendency can be alleviated by adjusting the source covariance matrix :math:`R` +to favor deeper source locations. In the depth weighting scheme employed in MNE +analyze, the elements of :math:`R` corresponding to the :math:`p` th source +location are be scaled by a factor + +.. math:: f_p = (g_{1p}^\top g_{1p} + g_{2p}^\top g_{2p} + g_{3p}^\top g_{3p})^{-\gamma}\ , + +where :math:`g_{1p}`, :math:`g_{2p}`, and :math:`g_{3p}` are the three columns +of :math:`G` corresponding to source location :math:`p` and :math:`\gamma` is +the order of the depth weighting, which is specified via the ``depth`` option +in :func:`mne.minimum_norm.make_inverse_operator`. + +Effective number of averages +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It is often the case that the epoch to be analyzed is a linear combination over +conditions rather than one of the original averages computed. As stated above, +the noise-covariance matrix computed is originally one corresponding to raw +data. Therefore, it has to be scaled correctly to correspond to the actual or +effective number of epochs in the condition to be analyzed. In general, we have + +.. math:: C = C_0 / L_{eff} + +where :math:`L_{eff}` is the effective number of averages. To calculate +:math:`L_{eff}` for an arbitrary linear combination of conditions + +.. math:: y(t) = \sum_{i = 1}^n {w_i x_i(t)} + +we make use of the the fact that the noise-covariance matrix + +.. math:: C_y = \sum_{i = 1}^n {w_i^2 C_{x_i}} = C_0 \sum_{i = 1}^n {w_i^2 / L_i} + +which leads to + +.. math:: 1 / L_{eff} = \sum_{i = 1}^n {w_i^2 / L_i} + +An important special case of the above is a weighted average, where + +.. math:: w_i = L_i / \sum_{i = 1}^n {L_i} + +and, therefore + +.. math:: L_{eff} = \sum_{i = 1}^n {L_i} + +Instead of a weighted average, one often computes a weighted sum, a simplest +case being a difference or sum of two categories. For a difference :math:`w_1 = +1` and :math:`w_2 = -1` and thus + +.. math:: 1 / L_{eff} = 1 / L_1 + 1 / L_2 + +or + +.. math:: L_{eff} = \frac{L_1 L_2}{L_1 + L_2} + +Interestingly, the same holds for a sum, where :math:`w_1 = w_2 = 1`. +Generalizing, for any combination of sums and differences, where :math:`w_i = +1` or :math:`w_i = -1`, :math:`i = 1 \dotso n`, we have + +.. math:: 1 / L_{eff} = \sum_{i = 1}^n {1/{L_i}} + +.. target for :end-before: inverse-end-content diff --git a/mne-python/source/doc/_includes/memory.rst b/mne-python/source/doc/_includes/memory.rst new file mode 100644 index 0000000000000000000000000000000000000000..0e668b54525830a7608ba2371b8599d2c9767149 --- /dev/null +++ b/mne-python/source/doc/_includes/memory.rst @@ -0,0 +1,68 @@ +:orphan: + +Memory-efficient I/O +==================== + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`memory` to link to that section of the implementation.rst + page. The next line is a target for :start-after: so we can omit the title + from the include: + memory-begin-content + + +Preloading continuous (raw) data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +MNE-Python can read data on-demand using the ``preload`` option provided in +raw reading functions. For example:: + + from mne import io + from mne.datasets import sample + data_path = sample.data_path() + raw_fname = data_path / 'MEG' / 'sample' / 'sample_audvis_filt-0-40_raw.fif' + raw = io.read_raw_fif(raw_fname, preload=False) + +.. note:: Filtering, resampling and dropping or selecting channels does not + work with ``preload=False``. + + +Preloading epoched data +~~~~~~~~~~~~~~~~~~~~~~~ + +Similarly, epochs can also be be read from disk on-demand. For example:: + + import mne + events = mne.find_events(raw) + event_id, tmin, tmax = 1, -0.2, 0.5 + picks = mne.pick_types(raw.info, meg=True, eeg=True, stim=False, eog=True) + epochs = mne.Epochs(raw, events, event_id, tmin, tmax, picks=picks, + baseline=(None, 0), reject=dict(eeg=80e-6, eog=150e-6), + preload=False) + +When ``preload=False``, the epochs data is loaded from the disk on-demand. Note +that ``preload=False`` for epochs will work even if the ``raw`` object has been +loaded with ``preload=True``. Preloading is also supported for +:func:`mne.read_epochs`. + +.. warning:: This comes with a caveat. When ``preload=False``, data rejection + based on peak-to-peak thresholds is executed when the data is + loaded from disk, *not* when the ``Epochs`` object is created. + +To explicitly reject artifacts with ``preload=False``, use the function :func:`mne.Epochs.drop_bad`. + + +Loading data explicitly +~~~~~~~~~~~~~~~~~~~~~~~ + +To load the data if ``preload=False`` was initially selected, use the functions :func:`mne.io.Raw.load_data` and :func:`mne.Epochs.load_data`. + + +Accessing data as NumPy arrays +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you just want your raw data as a :class:`Numpy array ` to +work with it in a different framework you can use slicing syntax:: + + first_channel_data, times = raw[0, :] + channels_3_and_4, times = raw[3:5, :] diff --git a/mne-python/source/doc/_includes/morph.rst b/mne-python/source/doc/_includes/morph.rst new file mode 100644 index 0000000000000000000000000000000000000000..1fd7c1898c330e07dd14f29083a2d0f5de6b5eda --- /dev/null +++ b/mne-python/source/doc/_includes/morph.rst @@ -0,0 +1,123 @@ +:orphan: + +Morphing and averaging source estimates +======================================= + +The spherical morphing of BEM surfaces accomplished by FreeSurfer can be +employed to bring data from different subjects into a common anatomical frame. +This page describes utilities which make use of the spherical :term:`morphing` +procedure. :func:`mne.morph_labels` morphs label files between subjects +allowing the definition of labels in a one brain and transforming them to +anatomically analogous labels in another. :meth:`mne.SourceMorph.apply` offers +the capability to transform all subject data to the same space and, +e.g., compute averages of data across subjects. + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`ch_morph` to link to that section of the implementation.rst page. + The next line is a target for :start-after: so we can omit the title from + the include: + morph-begin-content + + +Why morphing? +~~~~~~~~~~~~~ + +.. note:: Morphing examples in MNE-Python + :class: sidebar + + Examples of morphing in MNE-Python include :ref:`this tutorial + ` on surface source estimation or these examples on + :ref:`surface ` and :ref:`volumetric ` + source estimation. + +Modern neuroimaging techniques, such as source reconstruction or fMRI analyses, +make use of advanced mathematical models and hardware to map brain activity +patterns into a subject-specific anatomical brain space. This enables the study +of spatio-temporal brain activity. The representation of spatio-temporal brain +data is often mapped onto the anatomical brain structure to relate functional +and anatomical maps. Thereby activity patterns are overlaid with anatomical +locations that supposedly produced the activity. Anatomical MR images are often +used as such or are transformed into an inflated surface representations to +serve as "canvas" for the visualization. + +In order to compute group-level statistics, data representations across +subjects must be morphed to a common frame, such that anatomically and +functional similar structures are represented at the same spatial location for +*all subjects equally*. Since brains vary, :term:`morphing` comes into play to +tell us how the data produced by subject A would be represented on the brain of +subject B (and vice-versa). + + +The morphing maps +~~~~~~~~~~~~~~~~~ + +The MNE software accomplishes morphing with help of morphing maps. +The morphing is performed with help of the registered +spherical surfaces (``lh.sphere.reg`` and ``rh.sphere.reg`` ) which must be +produced in FreeSurfer. A morphing map is a linear mapping from cortical +surface values in subject A (:math:`x^{(A)}`) to those in another subject B +(:math:`x^{(B)}`) + +.. math:: x^{(B)} = M^{(AB)} x^{(A)}\ , + +where :math:`M^{(AB)}` is a sparse matrix with at most three nonzero elements +on each row. These elements are determined as follows. First, using the aligned +spherical surfaces, for each vertex :math:`x_j^{(B)}`, find the triangle +:math:`T_j^{(A)}` on the spherical surface of subject A which contains the +location :math:`x_j^{(B)}`. Next, find the numbers of the vertices of this +triangle and set the corresponding elements on the *j* th row of +:math:`M^{(AB)}` so that :math:`x_j^{(B)}` will be a linear interpolation +between the triangle vertex values reflecting the location :math:`x_j^{(B)}` +within the triangle :math:`T_j^{(A)}`. + +It follows from the above definition that in general + +.. math:: M^{(AB)} \neq (M^{(BA)})^{-1}\ , + +*i.e.*, + +.. math:: x_{(A)} \neq M^{(BA)} M^{(AB)} x^{(A)}\ , + +even if + +.. math:: x^{(A)} \approx M^{(BA)} M^{(AB)} x^{(A)}\ , + +*i.e.*, the mapping is *almost* a bijection. + + +About smoothing +~~~~~~~~~~~~~~~ + +The current estimates are normally defined only in a decimated grid which is a +sparse subset of the vertices in the triangular tessellation of the cortical +surface. Therefore, any sparse set of values is distributed to neighboring +vertices to make the visualized results easily understandable. This procedure +has been traditionally called smoothing but a more appropriate name might be +smudging or blurring in accordance with similar operations in image processing +programs. + +In MNE software terms, smoothing of the vertex data is an iterative procedure, +which produces a blurred image :math:`x^{(N)}` from the original sparse image +:math:`x^{(0)}` by applying in each iteration step a sparse blurring matrix: + +.. math:: x^{(p)} = S^{(p)} x^{(p - 1)}\ . + +On each row :math:`j` of the matrix :math:`S^{(p)}` there are :math:`N_j^{(p - +1)}` nonzero entries whose values equal :math:`1/N_j^{(p - 1)}`. Here +:math:`N_j^{(p - 1)}` is the number of immediate neighbors of vertex :math:`j` +which had non-zero values at iteration step :math:`p - 1`. Matrix +:math:`S^{(p)}` thus assigns the average of the non-zero neighbors as the new +value for vertex :math:`j`. One important feature of this procedure is that it +tends to preserve the amplitudes while blurring the surface image. + +Once the indices non-zero vertices in :math:`x^{(0)}` and the topology of the +triangulation are fixed the matrices :math:`S^{(p)}` are fixed and independent +of the data. Therefore, it would be in principle possible to construct a +composite blurring matrix + +.. math:: S^{(N)} = \prod_{p = 1}^N {S^{(p)}}\ . + +However, it turns out to be computationally more effective to do blurring with +an iteration. The above formula for :math:`S^{(N)}` also shows that the +smudging (smoothing) operation is linear. diff --git a/mne-python/source/doc/_includes/precision.rst b/mne-python/source/doc/_includes/precision.rst new file mode 100644 index 0000000000000000000000000000000000000000..0956bc954e92bf9307d865bf28fd615480d2b9ab --- /dev/null +++ b/mne-python/source/doc/_includes/precision.rst @@ -0,0 +1,28 @@ +:orphan: + +Floating-point precision +======================== + +.. NOTE: part of this file is included in doc/manual/io.rst and + doc/overview/implementation.rst. Changes here are reflected there. If you + want to link to this content, link to :ref:`manual-precision` for the manual + or :ref:`precision` for the implementation page. The next line is a target + for :start-after: so we can omit the title above: + precision-begin-content + +MNE-Python performs all computation in memory using the double-precision 64-bit +floating point format. This means that the data is typecast into float64 format +as soon as it is read into memory. The reason for this is that operations such +as filtering and preprocessing are more accurate when using the 64-bit format. +However, for backward compatibility, MNE-Python writes :file:`.fif` files in a +32-bit format by default. This reduces file size when saving data to disk, but +beware that *saving intermediate results to disk and re-loading them from disk +later may lead to loss in precision*. If you would like to ensure 64-bit +precision, there are two possibilities: + +- Chain the operations in memory and avoid saving intermediate results. + +- Save intermediate results but change the :class:`~numpy.dtype` used for + saving, by using the ``fmt`` parameter of :meth:`mne.io.Raw.save` (or + :meth:`mne.Epochs.save`, etc). However, note that this may render the + :file:`.fif` files unreadable in software packages other than MNE-Python. diff --git a/mne-python/source/doc/_includes/ssp.rst b/mne-python/source/doc/_includes/ssp.rst new file mode 100644 index 0000000000000000000000000000000000000000..40b25a237db9830d257a06954c1b2d74c1bcab1f --- /dev/null +++ b/mne-python/source/doc/_includes/ssp.rst @@ -0,0 +1,119 @@ +:orphan: + +The Signal-Space Projection (SSP) method +======================================== + +.. NOTE: part of this file is included in doc/overview/implementation.rst. + Changes here are reflected there. If you want to link to this content, link + to :ref:`ssp-method` to link to that section of the implementation.rst + page. The next line is a target for :start-after: so we can omit the title + from the include: + ssp-begin-content + +The Signal-Space Projection (SSP) is one approach to rejection of external +disturbances in software. The section presents some relevant details of this +method. For practical examples of how to use SSP for artifact rejection, see +:ref:`tut-artifact-ssp`. + +General concepts +~~~~~~~~~~~~~~~~ + +Unlike many other noise-cancellation approaches, SSP does not require +additional reference sensors to record the disturbance fields. Instead, SSP +relies on the fact that the magnetic field distributions generated by the +sources in the brain have spatial distributions sufficiently different from +those generated by external noise sources. Furthermore, it is implicitly +assumed that the linear space spanned by the significant external noise patterns +has a low dimension. + +Without loss of generality we can always decompose any :math:`n`-channel +measurement :math:`b(t)` into its signal and noise components as + +.. math:: b(t) = b_s(t) + b_n(t) + :name: additive_model + +Further, if we know that :math:`b_n(t)` is well characterized by a few field +patterns :math:`b_1 \dotso b_m`, we can express the disturbance as + +.. math:: b_n(t) = Uc_n(t) + e(t)\ , + :name: pca + +where the columns of :math:`U` constitute an orthonormal basis for :math:`b_1 +\dotso b_m`, :math:`c_n(t)` is an :math:`m`-component column vector, and the +error term :math:`e(t)` is small and does not exhibit any consistent spatial +distributions over time, *i.e.*, :math:`C_e = E \{e e^\top\} = I`. Subsequently, +we will call the column space of :math:`U` the noise subspace. The basic idea +of SSP is that we can actually find a small basis set :math:`b_1 \dotso b_m` +such that the conditions described above are satisfied. We can now construct +the orthogonal complement operator + +.. math:: P_{\perp} = I - UU^\top + :name: projector + +and apply it to :math:`b(t)` in Equation :eq:`additive_model` yielding + +.. math:: b_{s}(t) \approx P_{\perp}b(t)\ , + :name: result + +since :math:`P_{\perp}b_n(t) = P_{\perp}(Uc_n(t) + e(t)) \approx 0` and +:math:`P_{\perp}b_{s}(t) \approx b_{s}(t)`. The projection operator +:math:`P_{\perp}` is called the **signal-space projection operator** and +generally provides considerable rejection of noise, suppressing external +disturbances by a factor of 10 or more. The effectiveness of SSP depends on two +factors: + +- The basis set :math:`b_1 \dotso b_m` should be able to characterize the + disturbance field patterns completely and + +- The angles between the noise subspace space spanned by :math:`b_1 \dotso b_m` + and the signal vectors :math:`b_s(t)` should be as close to :math:`\pi / 2` + as possible. + +If the first requirement is not satisfied, some noise will leak through because +:math:`P_{\perp}b_n(t) \neq 0`. If the any of the brain signal vectors +:math:`b_s(t)` is close to the noise subspace not only the noise but also the +signal will be attenuated by the application of :math:`P_{\perp}` and, +consequently, there might by little gain in signal-to-noise ratio. + +Since the signal-space projection modifies the signal vectors originating in +the brain, it is necessary to apply the projection to the forward solution in +the course of inverse computations. + +For more information on SSP, please consult the references listed in +:footcite:t:`TescheEtAl1995,UusitaloIlmoniemi1997`. + +Estimation of the noise subspace +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As described above, application of SSP requires the estimation of the signal +vectors :math:`b_1 \dotso b_m` constituting the noise subspace. The most common +approach, also implemented in :func:`mne.compute_proj_raw` +is to compute a covariance matrix +of empty room data, compute its eigenvalue decomposition, and employ the +eigenvectors corresponding to the highest eigenvalues as basis for the noise +subspace. It is also customary to use a separate set of vectors for +magnetometers and gradiometers in the Vectorview system. + +EEG average electrode reference +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The EEG average reference is the mean signal over all the sensors. It is +typical in EEG analysis to subtract the average reference from all the sensor +signals :math:`b^{1}(t), ..., b^{n}(t)`. That is: + +.. math:: {b}^{j}_{s}(t) = b^{j}(t) - \frac{1}{n}\sum_{k}{b^k(t)} + :name: eeg_proj + +where the noise term :math:`b_{n}^{j}(t)` is given by + +.. math:: b_{n}^{j}(t) = \frac{1}{n}\sum_{k}{b^k(t)} + :name: noise_term + +Thus, the projector vector :math:`P_{\perp}` will be given by +:math:`P_{\perp}=\frac{1}{n}[1, 1, ..., 1]` + +.. warning:: + When applying SSP, the signal of interest can also be sometimes removed. + Therefore, it's always a good idea to check how much the effect of interest + is reduced by applying SSP. SSP might remove *both* the artifact and signal + of interest. diff --git a/mne-python/source/doc/_includes/units.rst b/mne-python/source/doc/_includes/units.rst new file mode 100644 index 0000000000000000000000000000000000000000..f37f03ebaf4a99d15d7a2f3c60299cde56489fc3 --- /dev/null +++ b/mne-python/source/doc/_includes/units.rst @@ -0,0 +1,36 @@ +:orphan: + +Internal representation (units) +=============================== + +.. NOTE: part of this file is included in doc/manual/io.rst and + doc/overview/implementation.rst. Changes here are reflected there. If you + want to link to this content, link to :ref:`manual-units` for the manual or + :ref:`units` for the implementation page. The next line is a target for + :start-after: so we can omit what's above: + units-begin-content + +Irrespective of the units used in your manufacturer's format, when importing +data, MNE-Python will always convert measurements to the same standard units. +Thus the in-memory representation of data are always in: + +- Volts (eeg, eog, seeg, emg, ecg, bio, ecog, dbs) +- Teslas (magnetometers) +- Teslas/meter (gradiometers) +- Amperes*meter (dipole fits, minimum-norm estimates, etc.) +- Moles/liter ("molar"; fNIRS data: oxyhemoglobin (hbo), deoxyhemoglobin (hbr)) +- Arbitrary units (various derived unitless quantities) + +.. NOTE: this is a target for :end-before: units-end-of-list + +Note, however, that most MNE-Python plotting functions will scale the data when +plotted to yield nice-looking axis annotations in a sensible range; for +example, :meth:`mne.io.Raw.plot_psd` will convert teslas to femtoteslas (fT) +and volts to microvolts (µV) when plotting MEG and EEG data. + +The units used in internal data representation are particularly important to +remember when extracting data from MNE-Python objects and manipulating it +outside MNE-Python (e.g., when using methods like :meth:`~mne.io.Raw.get_data` +or :meth:`~mne.Epochs.to_data_frame` to convert data to :class:`NumPy arrays +` or :class:`Pandas DataFrames ` for analysis +or plotting with other Python modules). diff --git a/mne-python/source/doc/_static/CoordinateSystems.png b/mne-python/source/doc/_static/CoordinateSystems.png new file mode 100644 index 0000000000000000000000000000000000000000..f71441a46c46629c09fbd3e3f45b1ffd5754af91 Binary files /dev/null and b/mne-python/source/doc/_static/CoordinateSystems.png differ diff --git a/mne-python/source/doc/_static/HeadCS.png b/mne-python/source/doc/_static/HeadCS.png new file mode 100644 index 0000000000000000000000000000000000000000..a55c2b3a94493b8375088bb3d3db461922321f3c Binary files /dev/null and b/mne-python/source/doc/_static/HeadCS.png differ diff --git a/mne-python/source/doc/_static/blender_import_obj/blender_import_obj1.jpg b/mne-python/source/doc/_static/blender_import_obj/blender_import_obj1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1a2a9b1e0496eda905cbef26084d7a7bc618505d --- /dev/null +++ b/mne-python/source/doc/_static/blender_import_obj/blender_import_obj1.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:043b90cd6267ebffe84933b1995fda4caa44a5d3f0e55df8dd1f676d1ba92e2e +size 103607 diff --git a/mne-python/source/doc/_static/blender_import_obj/blender_import_obj2.jpg b/mne-python/source/doc/_static/blender_import_obj/blender_import_obj2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..928c7480aeed23a1d844ec5aa9b1ad382ee40ff1 Binary files /dev/null and b/mne-python/source/doc/_static/blender_import_obj/blender_import_obj2.jpg differ diff --git a/mne-python/source/doc/_static/blender_import_obj/blender_import_obj3.jpg b/mne-python/source/doc/_static/blender_import_obj/blender_import_obj3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4f486a87da92f169c7fb92dd4f79d49c453b0a74 Binary files /dev/null and b/mne-python/source/doc/_static/blender_import_obj/blender_import_obj3.jpg differ diff --git a/mne-python/source/doc/_static/blender_import_obj/blender_import_obj4.jpg b/mne-python/source/doc/_static/blender_import_obj/blender_import_obj4.jpg new file mode 100644 index 0000000000000000000000000000000000000000..eaa93f2e9cf7a8d4d4732817c01014fcbc082bbe --- /dev/null +++ b/mne-python/source/doc/_static/blender_import_obj/blender_import_obj4.jpg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e83661d4a71c4fa81b497e7a4c8bdae58968436df60af0a2303c571d317df350 +size 495857 diff --git a/mne-python/source/doc/_static/default_linux_dock_icon.png b/mne-python/source/doc/_static/default_linux_dock_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..63156ae58654c3cf15eee6b2edb8627b34972c81 Binary files /dev/null and b/mne-python/source/doc/_static/default_linux_dock_icon.png differ diff --git a/mne-python/source/doc/_static/diagrams/git_setup.dot b/mne-python/source/doc/_static/diagrams/git_setup.dot new file mode 100644 index 0000000000000000000000000000000000000000..63a86460d27338e184174378e66efef726ff4ba2 --- /dev/null +++ b/mne-python/source/doc/_static/diagrams/git_setup.dot @@ -0,0 +1,64 @@ +digraph gitstructure { + /* LAYOUT CONTROL */ + rankdir=UD + newrank=true + ranksep=0.75 + clusterrank=local + labelloc=t + pad=0.1 + + /* GLOBAL TITLE */ + label="Schematic of recommended setup" + + /* GLOBAL STYLES */ + splines=true + fontsize=20 + fontname="Source Sans Pro" + + node [shape=box + style=filled + fontsize=12 + fontname="Source Sans Pro" + fillcolor="#bbbbbb" + margin="0.35,0.1"] + + edge [arrowsize=1.2 + penwidth=2.5 + fontsize=16 + fontname="Source Code Pro"] + + /* REMOTES */ + subgraph cluster_0 { + label=<REMOTES
> + color="#33bbee" + fontcolor="#33bbee" + fontsize=18 + style=dashed + penwidth=1.5 + + upstream [label=<Official version (“upstream”)
https://github.com/mne-tools/mne-python>] + + yourfork [label=<Your fork (“origin”)
https://github.com/your_github_username/mne-python>] + + } + + /* LOCAL */ + yourclone [label=<Your local clone
/somewhere/on/your/computer/mne-python/>] + + /* edges */ + upstream -> yourfork [label="1. “fork” button on \l upstream's GitHub page" + color="#ee7733" + fontcolor="#ee7733" + fontname="Source Sans Pro"] + + yourfork -> yourclone [label="2. git clone ... \l" + color="#00998855" + fontcolor="#009988"] + + yourclone -> upstream [label="3. git remote add ... \r" + color="#ee337755" + fontcolor="#ee3377"] + + /* align "remote" boxes */ + { rank="same" upstream yourfork } +} diff --git a/mne-python/source/doc/_static/diagrams/ica.dot b/mne-python/source/doc/_static/diagrams/ica.dot new file mode 100644 index 0000000000000000000000000000000000000000..87c3cb05bbb7d31d4a0be8fcf4002d54bed9df4b --- /dev/null +++ b/mne-python/source/doc/_static/diagrams/ica.dot @@ -0,0 +1,77 @@ +digraph ICAdiagram { + /* LAYOUT CONTROL */ + rankdir=LR + newrank=true + ranksep=0.75 + clusterrank=local + + /* GLOBAL STYLES */ + splines=true + fontsize=20 + fontname="Source Code Pro" + + node [style="filled" + fontsize=18 + fontname="Source Sans Pro"] + + edge [arrowsize=1.2 + penwidth=2.5 + color="gray50" + fontsize=12 + fontname="Source Code Pro"] + + /* starting nodes */ + sensor [label="Sensor data" shape="box" fillcolor="#bbbbbb"] + cov [label="Noise cov" shape="box" fillcolor="#bbbbbb"] + + /* ICA.FIT() */ + subgraph cluster_0 { + label="ICA.fit()" + color="#009988" + fontcolor="#009988" + penwidth=1.5 + + + /* PRE-WHITENING */ + subgraph cluster_1 { + label="Whitening" + style="dashed" + fontname="Source Sans Pro" + color="gray50" + fontcolor="gray50" + /* nodes & edges */ + pre [label="Pre-\nwhiten" fontsize=11 shape="circle" fillcolor="#ee7733"] + pre -> pca + pca [label="PCA" shape="circle" fillcolor="#ee7733"] + pcs [label="Principal\ncomponents" shape="box" fillcolor="#33bbee"] + pca -> pcs + } + + /* nodes & edges */ + ica [label="ICA" shape="circle" fillcolor="#ee7733"] + ics [label="Independent\ncomponents" shape="box" fillcolor="#33bbee"] + ica -> ics [label="n_components\r"] + } + + /* ICA.APPLY() */ + subgraph cluster_2 { + label="ICA.apply()" + color="#ee3377" + fontcolor="#ee3377" + penwidth=1.5 + /* ending node */ + recon [label="Reconstructed\nsensor data" shape="box" fillcolor="#bbbbbb"] + } + + /* subgraph-crossing edges */ + sensor -> pre [label="all sensor channels\r" fontsize=14 fontname="Source Sans Pro"] + cov -> pre [label="covariance or std. dev.\r" fontsize=14 fontname="Source Sans Pro"] + pcs -> ica [label="n_components\l"] + ics -> recon [constraint=false color="#ee3377" + xlabel="Retained ICs:\ln_components -\llen(ICA.exclude)\l"] + pcs -> recon [constraint=false color="#ee3377" + xlabel="PCA residual:\ln_pca_components\l- n_components\l"] + + /* position recon box where we want it */ + { rank="same" recon ica } +} diff --git a/mne-python/source/doc/_static/favicon.ico b/mne-python/source/doc/_static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..b0a1b57a5574966eb13a3c8bfaf36f0337ed5367 Binary files /dev/null and b/mne-python/source/doc/_static/favicon.ico differ diff --git a/mne-python/source/doc/_static/flow_diagram.svg b/mne-python/source/doc/_static/flow_diagram.svg new file mode 100644 index 0000000000000000000000000000000000000000..783f5e422f40e2a387d95343f39dd15e27a43cd8 --- /dev/null +++ b/mne-python/source/doc/_static/flow_diagram.svg @@ -0,0 +1,204 @@ + + + + + + +%3 + +cluster0 + +Structural information + + +src + +Source space +mne.SourceSpaces + + +fwd + + + + + + + +Forward solution +mne.forward.Forward + + +src->fwd + + + + +bem + +BEM + + +bem->fwd + + + + +recon + +Freesurfer surfaces + + +recon->src + + +setup_source_space + + +recon->bem + + + + +T1 + +T1 + + +T1->recon + + + + +flashes + +Flash5/30 + + +flashes->bem + + + + +inv + + + + + + + +Inverse operator +mne.minimum_norm.Inverse + + +fwd->inv + + + + +stc + +Source estimate +mne.SourceEstimate + + +inv->stc + + + + +pre + +Preprocessed data +mne.io.Raw + + +epo + +Epoched data +mne.Epochs + + +pre->epo + + +Epochs + + +epo->stc + + +apply_inverse_epochs + + +evo + +Averaged data +mne.Evoked + + +epo->evo + + +epochs.average + + +cov + +Noise covariance +mne.Covariance + + +epo->cov + + +compute_covariance + + +evo->stc + + +apply_inverse + + +cov->inv + + +make_inverse_operator + + +raw + +Raw data +mne.io.Raw + + +raw->pre + + +raw.filter +etc. + + +trans + + + + + + + +Head-MRI trans + + +trans->fwd + + +make_forward_solution + + + diff --git a/mne-python/source/doc/_static/funding/amazon.svg b/mne-python/source/doc/_static/funding/amazon.svg new file mode 100644 index 0000000000000000000000000000000000000000..0bed89ab2cee119dd8b9297eefacbaa4310eb989 --- /dev/null +++ b/mne-python/source/doc/_static/funding/amazon.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/funding/anr.svg b/mne-python/source/doc/_static/funding/anr.svg new file mode 100644 index 0000000000000000000000000000000000000000..1db7259a79f1f77fe9e9d20b9a57950dcac02d31 --- /dev/null +++ b/mne-python/source/doc/_static/funding/anr.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/funding/cds-dark.svg b/mne-python/source/doc/_static/funding/cds-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..940d66b5680fee45f9d755c38e9c726d5e5f80a1 --- /dev/null +++ b/mne-python/source/doc/_static/funding/cds-dark.svg @@ -0,0 +1,26 @@ + +image/svg+xml \ No newline at end of file diff --git a/mne-python/source/doc/_static/funding/cds.svg b/mne-python/source/doc/_static/funding/cds.svg new file mode 100644 index 0000000000000000000000000000000000000000..07b2482727d4ec31c560db26acef3a90ac0fdd4e --- /dev/null +++ b/mne-python/source/doc/_static/funding/cds.svg @@ -0,0 +1,27 @@ + +image/svg+xml diff --git a/mne-python/source/doc/_static/funding/czi.svg b/mne-python/source/doc/_static/funding/czi.svg new file mode 100644 index 0000000000000000000000000000000000000000..a85d737782d5cf7e3e44fad06943d2add2783dee --- /dev/null +++ b/mne-python/source/doc/_static/funding/czi.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/funding/doe.svg b/mne-python/source/doc/_static/funding/doe.svg new file mode 100644 index 0000000000000000000000000000000000000000..9debe055e24d019a5925de5c32f39f9de9c5d965 --- /dev/null +++ b/mne-python/source/doc/_static/funding/doe.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/funding/erc-dark.svg b/mne-python/source/doc/_static/funding/erc-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..7252d4dd47d4b225959d6a06d01035b07852fc19 --- /dev/null +++ b/mne-python/source/doc/_static/funding/erc-dark.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/funding/erc.svg b/mne-python/source/doc/_static/funding/erc.svg new file mode 100644 index 0000000000000000000000000000000000000000..0eac35304c66c7d019a2cb1eed2645ab448276f8 --- /dev/null +++ b/mne-python/source/doc/_static/funding/erc.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/funding/google.svg b/mne-python/source/doc/_static/funding/google.svg new file mode 100644 index 0000000000000000000000000000000000000000..8fe3bade85a9cd293c46cfbd71475b7f23dd7900 --- /dev/null +++ b/mne-python/source/doc/_static/funding/google.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/mne-python/source/doc/_static/funding/nih.svg b/mne-python/source/doc/_static/funding/nih.svg new file mode 100644 index 0000000000000000000000000000000000000000..c9e0881d6f72b8b23e14ac160a103779b1cc466b --- /dev/null +++ b/mne-python/source/doc/_static/funding/nih.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/mne-python/source/doc/_static/funding/nsf.png b/mne-python/source/doc/_static/funding/nsf.png new file mode 100644 index 0000000000000000000000000000000000000000..aefe59419626536cf04e65d715c5c7f3135a6c95 --- /dev/null +++ b/mne-python/source/doc/_static/funding/nsf.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60fba3c20bca5a77f47fcd48e457c3b40c48ccedd2378531781e6a9c2753a322 +size 322889 diff --git a/mne-python/source/doc/_static/institution_logos/AE-Studio-dark.svg b/mne-python/source/doc/_static/institution_logos/AE-Studio-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..d3519ed2513d891d5bc5ec9fac8df3e332bbddf4 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/AE-Studio-dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/AE-Studio-light.svg b/mne-python/source/doc/_static/institution_logos/AE-Studio-light.svg new file mode 100644 index 0000000000000000000000000000000000000000..d5c849f1718abe3ca5d293a059fce5748009c3bb --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/AE-Studio-light.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Aalto-dark.svg b/mne-python/source/doc/_static/institution_logos/Aalto-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..62b821a86f72ea0446111f0d63cba0754632f53e --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Aalto-dark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Aalto.svg b/mne-python/source/doc/_static/institution_logos/Aalto.svg new file mode 100644 index 0000000000000000000000000000000000000000..d9b3fdf14181603a2809290e864c8cf5f0f351ca --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Aalto.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Aarhus-dark.svg b/mne-python/source/doc/_static/institution_logos/Aarhus-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..9d533611e83d5ab9b308ef8497de14d4845aec8e --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Aarhus-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/mne-python/source/doc/_static/institution_logos/Aarhus.svg b/mne-python/source/doc/_static/institution_logos/Aarhus.svg new file mode 100644 index 0000000000000000000000000000000000000000..382cb72cd9693bae60928eaea54c29d22cdc162a --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Aarhus.svg @@ -0,0 +1,3 @@ + + + diff --git a/mne-python/source/doc/_static/institution_logos/BIDS-dark.svg b/mne-python/source/doc/_static/institution_logos/BIDS-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..8e04470462b8431f5967089d0ebb0685a5319114 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/BIDS-dark.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/BIDS.svg b/mne-python/source/doc/_static/institution_logos/BIDS.svg new file mode 100644 index 0000000000000000000000000000000000000000..21e7c56ba32d2fc4d6df55e51c6a5bc2c97f79f7 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/BIDS.svg @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/BU.svg b/mne-python/source/doc/_static/institution_logos/BU.svg new file mode 100644 index 0000000000000000000000000000000000000000..5f20405b9176a3c86486a746fd4c360399fbaf40 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/BU.svg @@ -0,0 +1,4 @@ + + + + diff --git a/mne-python/source/doc/_static/institution_logos/CEA.png b/mne-python/source/doc/_static/institution_logos/CEA.png new file mode 100644 index 0000000000000000000000000000000000000000..ea3f6b2e6d0f5f60378d00a4e59750bf1f1caddc Binary files /dev/null and b/mne-python/source/doc/_static/institution_logos/CEA.png differ diff --git a/mne-python/source/doc/_static/institution_logos/CHOP-dark.svg b/mne-python/source/doc/_static/institution_logos/CHOP-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..42f449879c1543a6eaeda5359cab7ff85d74ee89 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/CHOP-dark.svg @@ -0,0 +1,10 @@ + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/CHOP.svg b/mne-python/source/doc/_static/institution_logos/CHOP.svg new file mode 100644 index 0000000000000000000000000000000000000000..22b5eda7e56562c5183bf87034daa60f915a008d --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/CHOP.svg @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Donders.png b/mne-python/source/doc/_static/institution_logos/Donders.png new file mode 100644 index 0000000000000000000000000000000000000000..89f6e5fe5618dd2342f6ed6c5d190956f065a6c0 Binary files /dev/null and b/mne-python/source/doc/_static/institution_logos/Donders.png differ diff --git a/mne-python/source/doc/_static/institution_logos/FCBG.svg b/mne-python/source/doc/_static/institution_logos/FCBG.svg new file mode 100644 index 0000000000000000000000000000000000000000..c2c930fe5af40c5ae38ce57ac5a26ad0b0207580 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/FCBG.svg @@ -0,0 +1,82 @@ + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Graz.svg b/mne-python/source/doc/_static/institution_logos/Graz.svg new file mode 100644 index 0000000000000000000000000000000000000000..ac8aa6dca6add25ed97957eefb3646645913b191 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Graz.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/doc/_static/institution_logos/Harvard.png b/mne-python/source/doc/_static/institution_logos/Harvard.png new file mode 100644 index 0000000000000000000000000000000000000000..51a038400cdd1ce92db82da2fccae61db22c0a3a Binary files /dev/null and b/mne-python/source/doc/_static/institution_logos/Harvard.png differ diff --git a/mne-python/source/doc/_static/institution_logos/ICM.jpg b/mne-python/source/doc/_static/institution_logos/ICM.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8385f115049230b899b35688a1b480305fb92bc9 Binary files /dev/null and b/mne-python/source/doc/_static/institution_logos/ICM.jpg differ diff --git a/mne-python/source/doc/_static/institution_logos/Ilmenau-dark.svg b/mne-python/source/doc/_static/institution_logos/Ilmenau-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..01fcf5aff4ac6da95884cfe6031cd01eab22fbd8 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Ilmenau-dark.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Ilmenau.svg b/mne-python/source/doc/_static/institution_logos/Ilmenau.svg new file mode 100644 index 0000000000000000000000000000000000000000..fc8c6bcb52e113a2bfcaa6d08dcd56fe0fdb20d0 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Ilmenau.svg @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Inserm-dark.svg b/mne-python/source/doc/_static/institution_logos/Inserm-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..d869f5d9c1de20bb0ba02f82dcc18b971d0c5847 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Inserm-dark.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Inserm.svg b/mne-python/source/doc/_static/institution_logos/Inserm.svg new file mode 100644 index 0000000000000000000000000000000000000000..31341f8b67020a88e387cdb229dfdcd5c1aa19f4 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Inserm.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Julich-dark.svg b/mne-python/source/doc/_static/institution_logos/Julich-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..287e950640f1a1925624e002a69fe8f141d5eedd --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Julich-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/mne-python/source/doc/_static/institution_logos/Julich.svg b/mne-python/source/doc/_static/institution_logos/Julich.svg new file mode 100644 index 0000000000000000000000000000000000000000..c8be98451104dbf9a10056c79d902b7e268c45a0 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Julich.svg @@ -0,0 +1,3 @@ + + + diff --git a/mne-python/source/doc/_static/institution_logos/MGH.svg b/mne-python/source/doc/_static/institution_logos/MGH.svg new file mode 100644 index 0000000000000000000000000000000000000000..8c438f329fe7659114eca95bdbfd08ca74661f9c --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/MGH.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/MIT.svg b/mne-python/source/doc/_static/institution_logos/MIT.svg new file mode 100644 index 0000000000000000000000000000000000000000..3113bbe76bd244f8dcbd8156d71f61cb0d46d646 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/MIT.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/MPIB-dark.svg b/mne-python/source/doc/_static/institution_logos/MPIB-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..9b0c0232fe74194d5294d871036feb112f2dd6e1 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/MPIB-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/doc/_static/institution_logos/MPIB.svg b/mne-python/source/doc/_static/institution_logos/MPIB.svg new file mode 100644 index 0000000000000000000000000000000000000000..d9f236de03ff70af8dee59fcd49c965d766495a3 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/MPIB.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Macquarie-dark.svg b/mne-python/source/doc/_static/institution_logos/Macquarie-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..e1f48bae2dda50615389f64f243bed6c8252cca8 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Macquarie-dark.svg @@ -0,0 +1,165 @@ + +image/svg+xml \ No newline at end of file diff --git a/mne-python/source/doc/_static/institution_logos/Macquarie.svg b/mne-python/source/doc/_static/institution_logos/Macquarie.svg new file mode 100644 index 0000000000000000000000000000000000000000..64ae7b2c8c1d9853b4f71d7d3642c9a6f651f1c3 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Macquarie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/doc/_static/institution_logos/Martinos.png b/mne-python/source/doc/_static/institution_logos/Martinos.png new file mode 100644 index 0000000000000000000000000000000000000000..786da577e2640c9fb7bd552d788e9ea98dcdd8d5 Binary files /dev/null and b/mne-python/source/doc/_static/institution_logos/Martinos.png differ diff --git a/mne-python/source/doc/_static/institution_logos/NYU-dark.svg b/mne-python/source/doc/_static/institution_logos/NYU-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..6bc6c93b7251687f3b225ae5c893570413a6c514 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/NYU-dark.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/NYU.svg b/mne-python/source/doc/_static/institution_logos/NYU.svg new file mode 100644 index 0000000000000000000000000000000000000000..11c7facec97702b0acba7db937b00b245a674ece --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/NYU.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/SWPS-dark.svg b/mne-python/source/doc/_static/institution_logos/SWPS-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..8ad62d8abaaf5e7074a9ad45f49296e6f38ee192 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/SWPS-dark.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/SWPS.svg b/mne-python/source/doc/_static/institution_logos/SWPS.svg new file mode 100644 index 0000000000000000000000000000000000000000..b8683a23e5f3c8ae28c9f8b6776bee0623e0ca38 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/SWPS.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Telecom_Paris_Tech.svg b/mne-python/source/doc/_static/institution_logos/Telecom_Paris_Tech.svg new file mode 100644 index 0000000000000000000000000000000000000000..f38eed771ff9f7bee7da266a98138951a2abd371 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Telecom_Paris_Tech.svg @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/mne-python/source/doc/_static/institution_logos/Washington-dark.svg b/mne-python/source/doc/_static/institution_logos/Washington-dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..8d6f9af51a1e9dea36761d5d78cb4127c393d91b --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Washington-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/mne-python/source/doc/_static/institution_logos/Washington.svg b/mne-python/source/doc/_static/institution_logos/Washington.svg new file mode 100644 index 0000000000000000000000000000000000000000..0c79d4319509a7a96550b8c8b04ce36135d82e63 --- /dev/null +++ b/mne-python/source/doc/_static/institution_logos/Washington.svg @@ -0,0 +1,3 @@ + + + diff --git a/mne-python/source/doc/_static/institution_logos/inria.png b/mne-python/source/doc/_static/institution_logos/inria.png new file mode 100644 index 0000000000000000000000000000000000000000..9d6397e366b90982779c85a689769bb7392b5497 Binary files /dev/null and b/mne-python/source/doc/_static/institution_logos/inria.png differ diff --git a/mne-python/source/doc/_static/js/contrib-avatars.js b/mne-python/source/doc/_static/js/contrib-avatars.js new file mode 100644 index 0000000000000000000000000000000000000000..ee1434537403915ce9ece6f35a1267149657a6a2 --- /dev/null +++ b/mne-python/source/doc/_static/js/contrib-avatars.js @@ -0,0 +1,53 @@ +async function getContribs(url) { + result = await fetch(url); + data = await result.json(); + return data; +} + +function addCards(data, container) { + data.forEach((entry) => { + if (!entry.login.endsWith("[bot]") && entry.login != "mne-bot") { + let card = document.createElement("div"); + let anchor = document.createElement("a"); + let image = document.createElement("img"); + card.setAttribute("class", "card my-1 mx-2"); + anchor.setAttribute("href", entry.html_url); + image.setAttribute("class", "card-img contributor-avatar"); + image.setAttribute("src", entry.avatar_url); + image.setAttribute("title", entry.login); + image.setAttribute("alt", `Contributor avatar for ${entry.login}`); + anchor.append(image); + card.append(anchor); + container.append(card); + } + }); +} + +async function putAvatarsInPage() { + // container + let outer = document.createElement("div"); + let title = document.createElement("p"); + let inner = document.createElement("div"); + outer.setAttribute("id", "contributor-avatars"); + outer.setAttribute("class", "container my-4"); + title.setAttribute("class", "h4 text-center font-weight-light"); + title.innerText = "Contributors"; + inner.setAttribute("class", "d-flex flex-wrap flex-row justify-content-center align-items-center"); + // GitHub API returns batches of 100 so we have to loop + var page = 1; + while (true) { + data = await getContribs( + `https://api.github.com/repos/mne-tools/mne-python/contributors?per_page=100&page=${page}` + ); + if (!data.length) { + break; + } + addCards(data, container=inner); + page++; + } + // finish + outer.append(title, inner); + document.body.append(outer); +} + +putAvatarsInPage(); diff --git a/mne-python/source/doc/_static/js/custom-icons.js b/mne-python/source/doc/_static/js/custom-icons.js new file mode 100644 index 0000000000000000000000000000000000000000..60b3c3b9276c08afdce399ad3e0afb99d5d2a207 --- /dev/null +++ b/mne-python/source/doc/_static/js/custom-icons.js @@ -0,0 +1,19 @@ +FontAwesome.library.add( + /** + * Custom icon definitions + * + * see https://pydata-sphinx-theme.readthedocs.io/en/latest/user_guide/header-links.html#svg-image-icons + */ + { + prefix: "fa-custom", + iconName: "opencollective", + icon: [ + 24, + 24, + [], + "e001", + // https://simpleicons.org/icons/opencollective.svg + "M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12c2.54 0 4.894-.79 6.834-2.135l-3.107-3.109a7.715 7.715 0 1 1 0-13.512l3.107-3.109A11.943 11.943 0 0 0 12 0zm9.865 5.166l-3.109 3.107A7.67 7.67 0 0 1 19.715 12a7.682 7.682 0 0 1-.959 3.727l3.109 3.107A11.943 11.943 0 0 0 24 12c0-2.54-.79-4.894-2.135-6.834z", + ], + }, +); diff --git a/mne-python/source/doc/_static/js/set_installer_tab.js b/mne-python/source/doc/_static/js/set_installer_tab.js new file mode 100644 index 0000000000000000000000000000000000000000..ea019d51852514bfa0525254bcec62911f4f800c --- /dev/null +++ b/mne-python/source/doc/_static/js/set_installer_tab.js @@ -0,0 +1,55 @@ +/* inspired by https://tobiasahlin.com/blog/move-from-jquery-to-vanilla-javascript/ */ + +function documentReady(callback) { + if (document.readyState != "loading") callback(); + else document.addEventListener("DOMContentLoaded", callback); +} + +function setTabs() { + var platform = "linux"; + if (navigator.userAgent.indexOf("Win") !== -1) { + platform = "windows"; + } + if (navigator.userAgent.indexOf("Mac") !== -1) { + // there's no good way to distinguish intel vs M1 in javascript so we + // just default to showing the most modern macOS installer + platform = "macos-apple"; + } + var platform_short = platform.split("-")[0]; + + let tab_label_nodes = [...document.querySelectorAll('.sd-tab-label')]; + + let install_tab_nodes = document.querySelectorAll( + '.install-selector-tabset')[0].children; + let install_input_nodes = [...install_tab_nodes].filter( + child => child.nodeName === "INPUT"); + let install_label = tab_label_nodes.filter( + // label.id is drawn from :name: property in the rST, which must + // be unique across the whole site (*sigh*) + label => label.id.startsWith(`install-${platform}`))[0]; + let install_id = install_label.getAttribute('for'); + let install_input = install_input_nodes.filter(node => node.id === install_id)[0]; + install_input.checked = true; + + let uninstall_tab_nodes = document.querySelectorAll( + '.uninstall-selector-tabset')[0].children; + let uninstall_input_nodes = [...uninstall_tab_nodes].filter( + child => child.nodeName === "INPUT"); + let uninstall_label = tab_label_nodes.filter( + label => label.id.startsWith(`uninstall-${platform_short}`))[0]; + let uninstall_id = uninstall_label.getAttribute('for'); + let uninstall_input = uninstall_input_nodes.filter(node => node.id === uninstall_id)[0]; + uninstall_input.checked = true; +} + +function setAlert() { + for (let button of document.querySelectorAll('.install-download-button')) { + button.addEventListener('click', function() { + alert = document.querySelectorAll('.install-download-alert')[0]; + alert.style.display = 'block'; + }); + } +} + +documentReady(setTabs); +documentReady(setAlert); diff --git a/mne-python/source/doc/_static/js/update_installer_version.js b/mne-python/source/doc/_static/js/update_installer_version.js new file mode 100644 index 0000000000000000000000000000000000000000..ad18890caf78edd39bd33b2a11cdad8cc7c93d90 --- /dev/null +++ b/mne-python/source/doc/_static/js/update_installer_version.js @@ -0,0 +1,61 @@ +/* inspired by https://tobiasahlin.com/blog/move-from-jquery-to-vanilla-javascript/ */ + +function documentReady(callback) { + if (document.readyState != "loading") callback(); + else document.addEventListener("DOMContentLoaded", callback); +} + +async function getRelease() { + result = await fetch("https://api.github.com/repos/mne-tools/mne-installers/releases/latest"); + data = await result.json(); + return data; +} +async function warnVersion() { + data = await getRelease(); + // Take v1.5.1 for example and change to 1.5 + ids = ["linux-installers", "macos-intel-installers", "macos-apple-installers", "windows-installers"]; + warn = false; + ids.forEach((id) => { + label_id = document.getElementById(id); + // tab is immediately after label + children = [].slice.call(label_id.parentNode.children); + div = children[children.indexOf(label_id) + 1]; + a = div.children[0].children[0]; // div->p->a + ending = a.href.split("-").slice(-1)[0]; // Should be one of: ["macOS_Intel.pkg", "macOS_M1.pkg", "Linux.sh", "Windows.exe"] + data["assets"].every((asset) => { + // find the matching asset + if (!asset["browser_download_url"].endsWith(ending)) { + return true; // continue + } + old_stem = a.href.split("/").slice(-1)[0]; + new_stem = asset["browser_download_url"].split("/").slice(-1)[0]; + a.href = asset["browser_download_url"]; + // also replace the command on Linux + if (ending === "Linux.sh") { + code = document.getElementById("codecell0"); + } + if (!warn) { + // MNE-Python-1.5.1_0-Linux.sh to 1.5 for example + old_ver = old_stem.split("-").slice(2)[0].split("_")[0].split(".").slice(0, 2).join("."); + new_ver = new_stem.split("-").slice(2)[0].split("_")[0].split(".").slice(0, 2).join("."); + if (old_ver !== new_ver) { + warn = `The installers below are for version ${new_ver} as ${old_ver} is no longer supported`; + } + } + return false; // do not continue + }); + }); + if (warn) { + let outer = document.createElement("div"); + let title = document.createElement("p"); + let inner = document.createElement("p"); + outer.setAttribute("class", "admonition warning"); + title.setAttribute("class", "admonition-title"); + title.innerText = "Warning"; + inner.innerText = warn; + outer.append(title, inner); + document.querySelectorAll('.install-selector-tabset')[0].before(outer); + } +} + +documentReady(warnVersion); diff --git a/mne-python/source/doc/_static/mne_helmet.png b/mne-python/source/doc/_static/mne_helmet.png new file mode 100644 index 0000000000000000000000000000000000000000..bb2124669ea5e251bf5370321e7e4e312a8ff28f Binary files /dev/null and b/mne-python/source/doc/_static/mne_helmet.png differ diff --git a/mne-python/source/doc/_static/mne_installer_console.png b/mne-python/source/doc/_static/mne_installer_console.png new file mode 100644 index 0000000000000000000000000000000000000000..7a9ddaebbd0a22c4015376e460cb715101619a42 Binary files /dev/null and b/mne-python/source/doc/_static/mne_installer_console.png differ diff --git a/mne-python/source/doc/_static/mne_installer_macOS.png b/mne-python/source/doc/_static/mne_installer_macOS.png new file mode 100644 index 0000000000000000000000000000000000000000..b32e023e571b4e984e377b95f89ea71d7b1e1fdb --- /dev/null +++ b/mne-python/source/doc/_static/mne_installer_macOS.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:afef70fee4f4635651beebeed2e85a1eae893316486888f40ebe4e57870ead55 +size 301254 diff --git a/mne-python/source/doc/_static/mne_logo.svg b/mne-python/source/doc/_static/mne_logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..dc9ff39d029883fd1cd436277db0dfe294d91cec --- /dev/null +++ b/mne-python/source/doc/_static/mne_logo.svg @@ -0,0 +1,783 @@ + + + + + + + + 2023-11-07T13:26:54.126105 + image/svg+xml + + + Matplotlib v3.8.0.dev1998+gc5707d9c79, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/mne_logo_dark.svg b/mne-python/source/doc/_static/mne_logo_dark.svg new file mode 100644 index 0000000000000000000000000000000000000000..1afbae82f9a2b2fd31dd56910db16f0880c78cb9 --- /dev/null +++ b/mne-python/source/doc/_static/mne_logo_dark.svg @@ -0,0 +1,783 @@ + + + + + + + + 2023-11-07T13:26:53.926101 + image/svg+xml + + + Matplotlib v3.8.0.dev1998+gc5707d9c79, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/mne_logo_gray.svg b/mne-python/source/doc/_static/mne_logo_gray.svg new file mode 100644 index 0000000000000000000000000000000000000000..1cabd8f5932b89d464a8cbf785343fdc391ad366 --- /dev/null +++ b/mne-python/source/doc/_static/mne_logo_gray.svg @@ -0,0 +1,783 @@ + + + + + + + + 2023-11-07T13:26:54.034781 + image/svg+xml + + + Matplotlib v3.8.0.dev1998+gc5707d9c79, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/mne_logo_small.svg b/mne-python/source/doc/_static/mne_logo_small.svg new file mode 100644 index 0000000000000000000000000000000000000000..0f62fdf3ce538718bc6471ad3cfa42cb5999a244 --- /dev/null +++ b/mne-python/source/doc/_static/mne_logo_small.svg @@ -0,0 +1,84 @@ + + + + + + + + 2023-11-07T13:26:54.345596 + image/svg+xml + + + Matplotlib v3.8.0.dev1998+gc5707d9c79, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mne-python/source/doc/_static/mne_python_dock_icon.png b/mne-python/source/doc/_static/mne_python_dock_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..abd77ff9d82f2da398a7b6e4ba7e53f3a6b987e0 Binary files /dev/null and b/mne-python/source/doc/_static/mne_python_dock_icon.png differ diff --git a/mne-python/source/doc/_static/style.css b/mne-python/source/doc/_static/style.css new file mode 100644 index 0000000000000000000000000000000000000000..ec57511c1c0c80a158845f98e9d4a8b457b8d48e --- /dev/null +++ b/mne-python/source/doc/_static/style.css @@ -0,0 +1,431 @@ +:root { + + --pst-font-size-base: 16px; + --pst-font-size-milli: 13px; + --pst-font-family-base: 'Source Sans Pro', var(--pst-font-family-base-system); + --pst-font-family-heading: var(--pst-font-family-base); + --pst-font-family-monospace: 'Source Code Pro', var(--pst-font-family-monospace-system); + /* colors that aren't responsive to light/dark mode */ + --mne-color-discord: #5865F2; + /* font weight */ + --mne-font-weight-semibold: 600; +} + + +html[data-theme="light"] { + /* pydata-sphinx-theme overrides */ + /* ↓↓↓ use default "info" colors for "primary" */ + --pst-color-primary: #276be9; + --pst-color-primary-bg: #dce7fc; + /* ↓↓↓ use default "primary" colors for "info" */ + --pst-color-info: var(--pst-teal-500); + --pst-color-info-bg: var(--pst-teal-200); + /* ↓↓↓ use "warning" colors for "secondary" */ + --pst-color-secondary: var(--pst-color-warning); + --pst-color-secondary-bg: var(--pst-color-warning-bg); + /* ↓↓↓ make sure new primary (link) color propogates to links on code */ + --pst-color-inline-code-links: var(--pst-color-link); + /* ↓↓↓ make sure new secondary (hover) color propogates to hovering on table rows */ + --pst-color-table-row-hover-bg: var(--pst-color-secondary-bg); + /* topbar logo links */ + --mne-color-github: #000; + --mne-color-discourse: #d0232b; + --mne-color-mastodon: #2F0C7A; + --mne-color-sponsor: #BF3989; /* from GH sponsor heart, via browser devtools */ + --mne-color-opencollective: #1F87FF; /* scraped from logo SVG */ + /* code block copy button */ + --copybtn-opacity: 0.75; + /* card header bg color */ + --mne-color-card-header: rgba(0, 0, 0, 0.05); + /* sphinx-gallery overrides */ + --sg-download-a-background-color: var(--pst-color-primary); + --sg-download-a-background-image: unset; + --sg-download-a-border-color: var(--pst-color-border); + --sg-download-a-color: var(--sd-color-primary-text); + --sg-download-a-hover-background-color: var(--pst-color-primary-highlight); + --sg-download-a-hover-box-shadow-1: none; + --sg-download-a-hover-box-shadow-2: none; +} +html[data-theme="dark"] { + /* pydata-sphinx-theme overrides */ + /* ↓↓↓ use default "info" colors for "primary" */ + --pst-color-primary: #79a3f2; + --pst-color-primary-bg: #06245d; + /* ↓↓↓ use default "primary" colors for "info" */ + --pst-color-info: var(--pst-teal-400); + --pst-color-info-bg: var(--pst-teal-800); + /* ↓↓↓ use "warning" colors for "secondary" */ + --pst-color-secondary: var(--pst-color-warning); + --pst-color-secondary-bg: var(--pst-color-warning-bg); + /* ↓↓↓ make sure new primary (link) color propogates to links on code */ + --pst-color-inline-code-links: var(--pst-color-link); + /* ↓↓↓ make sure new secondary (hover) color propogates to hovering on table rows */ + --pst-color-table-row-hover-bg: var(--pst-color-secondary-bg); + /* topbar logo links */ + --mne-color-github: rgb(240, 246, 252); /* from their logo SVG */ + --mne-color-discourse: #FFF9AE; /* from their logo SVG */ + --mne-color-mastodon: #858AFA; /* www.joinmastodon.org/en/branding */ + --mne-color-sponsor: #DB61A2; /* from GH sponsor heart, via browser devtools */ + --mne-color-opencollective: #99CFFF; /* scraped from logo SVG */ + /* code block copy button */ + --copybtn-opacity: 0.25; + /* card header bg color */ + --mne-color-card-header: rgba(255, 255, 255, 0.2); + /* sphinx-gallery overrides */ + --sg-download-a-background-color: var(--pst-color-primary); + --sg-download-a-background-image: unset; + --sg-download-a-border-color: var(--pst-color-border); + --sg-download-a-color: var(--sd-color-primary-text); + --sg-download-a-hover-background-color: var(--pst-color-primary-highlight); + --sg-download-a-hover-box-shadow-1: none; + --sg-download-a-hover-box-shadow-2: none; +} + +/* ************************************************************ Sphinx fixes */ + +/* API docs parameter lists */ +dl.field-list { + grid-template-columns: auto 1fr; +} + +/* make HTML'd pandas dataframes scrollable */ +table.dataframe { + display: block; + overflow: auto; +} + +/* Long API titles need to wrap for mobile */ +div[id^="mne-"] h1, +div[id^="examples-using-"] h2 { + word-break: break-word; +} + +/* *********************************************** pydata-sphinx-theme fixes */ + +/* this is most critical for the homepage logos, but affects all images */ +html[data-theme="dark"] img { + filter: none; +} + +/* make versionadded smaller and inline with param name */ +/* don't do for deprecated / versionchanged; they have extra info (too long to fit) */ +div.versionadded > p { + margin-top: 0; + margin-bottom: 0; +} +div.versionadded { + margin: 0; + margin-left: 0.5rem; + display: inline-block; +} +/* when FF supports :has(), change to → dd > p:has(+div.versionadded) */ +dd>p { + display: inline; +} + +/* **************************************************** sphinx-gallery fixes */ + +/* backreference links: restore hover decoration that SG removes */ +a.sphx-glr-backref-instance:hover { + text-decoration: underline; +} +/* backreference links: make non-MNE func/meth calls resemble regular code */ +a[class^="sphx-glr-backref-module"] { + color: var(--pst-color-text-base); +} +/* backreference links: make MNE calls bold and colorful */ +a[class^="sphx-glr-backref-module-mne"] { + color: var(--pst-color-link); + font-weight: var(--mne-font-weight-semibold); +} +/* suppress redundant note at top of every tutorial and signature at the end */ +div.sphx-glr-download-link-note, +p.sphx-glr-signature { + visibility: hidden; + height: 0; + margin: 0; + padding: 0; +} +/* this fixes the "Examples using " quirk */ +p.rubric { + flex-direction: row; + gap: 4px; +} + +/* script/notebook download buttons */ +.sphx-glr-download a.download { + border-radius: 0.5rem; + /* ↓↓↓↓↓↓↓ these two rules copied from sphinx-design */ + box-shadow: 0 .125rem .25rem var(--sd-color-shadow) !important; + text-decoration: none; + transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; +} +.sphx-glr-download a.download code { + color: var(--sg-download-a-color); +} +.sphx-glr-download a.download::before { + color: var(--sg-download-a-color); +} +/* Report embedding */ +iframe.sg_report { + width: 95%; + height: 70vh; + margin: 20px auto; + display: block; + border-style: solid; +} +/* Disable thumbnail tooltips on hover */ +.sphx-glr-thumbcontainer[tooltip]:hover::before, +.sphx-glr-thumbcontainer[tooltip]:hover::after { + display: none; +} + +/* Make our external thumbnails (e.g., mne-gui-addons) act like standard SG ones */ +.sphx-glr-thumbcontainer a.external { + bottom: 0; + display: block; + left: 0; + box-sizing: border-box; + padding: 150px 10px 0; + position: absolute; + right: 0; + top: 0; +} + +/* ******************************************************** HTML repr tables */ + +/* make table responsive to pydata-sphinx-theme's light/dark mode */ +.table > :not(caption) > * > * { + color: var(--pst-color-text-base); +} +.mne-repr-table tbody tr:hover { + background-color: var(--pst-color-table-row-hover-bg); +} +.mne-repr-section-toggle > button > svg > path { + fill: var(--pst-color-text-base); +} +/* make the expand/collapse button look nicer */ +.mne-repr-section-toggle > button { + padding: 20%; +} +/* make section header rows more distinct (and harmonize with pydata-sphinx-theme table +style in the process). Color copied from pydata-sphinx-theme; 2px copied from bootstrap. +*/ +.mne-repr-table th { + border-bottom: 2px solid var(--pst-color-primary); +} +/* harmonize the channel names buttons with the rest of the table */ +.mne-ch-names-btn { + font-size: inherit; + padding: 0.25rem; + min-width: 1.5rem; + font-weight: bold; +} +/* +.mne-ch-names-btn:hover { + background-color: var(--pst-color-); + text-decoration: underline; +} +.mne-ch-names-btn:focus-visible { + outline: 0.1875rem solid var(--pst-color-accent); + outline-offset: 0.1875rem; +} +*/ +/* ***************************************************** sphinx-design fixes */ +p.btn a { + color: unset; +} +/* sphinx-design tabs */ +html .bd-content .sd-tab-set > label:hover, +.bd-content .sd-tab-set > input:not(:checked) + label:hover { + opacity: unset; + color: var(--pst-color-secondary); + border-color: var(--pst-color-secondary); +} + +/* ************************************************************* copy button */ +button.copybtn { + /* always show; https://sphinx-copybutton.readthedocs.io/en/latest/use.html#modify-the-copy-button-s-css */ + opacity: var(--copybtn-opacity); + } + +/* *************************************************** bib reference spacing */ +aside.footnote { + margin-bottom: 0.5rem; +} +aside.footnote:last-child { + margin-bottom: 1rem; +} + +/* ******************************************************** version dropdown */ +.dropdown-toggle { + font-weight: var(--mne-font-weight-semibold); +} + +/* ******************************************************* navbar icon links */ +.navbar-icon-links svg.fa-github { + color: var(--mne-color-github); +} +.navbar-icon-links svg.fa-discourse { + color: var(--mne-color-discourse); +} +.navbar-icon-links svg.fa-discord { + color: var(--mne-color-discord); +} +.navbar-icon-links svg.fa-mastodon { + color: var(--mne-color-mastodon); +} +.navbar-icon-links svg.fa-heart { + color: var(--mne-color-sponsor); +} +.navbar-icon-links svg.fa-opencollective { + color: var(--mne-color-opencollective); +} + +/* ************************************************************ nav elements */ +/* topbar nav inactive */ +.bd-header.navbar-light#navbar-main .navbar-nav li a.nav-link { + color: var(--pst-color-text-muted); +} +/* topbar nav active */ +.bd-header.navbar-light#navbar-main .navbar-nav > li.active > .nav-link { + font-weight: var(--mne-font-weight-semibold); +} +/* topbar nav hover */ +.bd-header.navbar-light#navbar-main .navbar-nav li a.nav-link:focus, +.bd-header.navbar-light#navbar-main .navbar-nav li a.nav-link:hover { + color: var(--pst-color-secondary); +} + +/* *********************************************************** homepage logo */ +img.logo { + max-width: 360px; + width: 100%; +} + +/* **************************************************** homepage quick links */ +ul.quicklinks a { + font-weight: var(--mne-font-weight-semibold); + color: var(--pst-color-text-base); + text-decoration: none; +} +ul.quicklinks a svg { + color: var(--pst-color-text-muted); +} +ul.quicklinks a:hover { + text-decoration: none; +} +h5.card-header { + margin-top: 0px; + margin-bottom: 0px; + color: var(--pst-color-text-base); +} +h5.card-header::before { + height: 0px; + margin-top: 0px; +} +/* ******************************************************* homepage carousel */ +div.frontpage-gallery { + overflow: hidden; + height: 180px; + justify-content: center; +} +div.frontpage-gallery a { + text-decoration: none; + color: var(--pst-color-text-base); +} +div.frontpage-gallery img.card-img { + transform: scale(1.8); + transform-origin: 40% 20%; + opacity: 0.2; + transition: 400ms ease-out; +} +div.frontpage-gallery:hover img.card-img { + transform: scale(1.2); + opacity: 1.0; + transition: 400ms ease-out; +} +div.frontpage-gallery .fadeout { + opacity: 1.0; + transition: 200ms linear; +} +div.frontpage-gallery:hover .fadeout { + opacity: 0.0; + transition: 200ms linear; +} +/* affects the homepage gallery tiles and the homepage sidebar quicklinks card; + needed for dark mode. */ +div.card { + border: 1px solid var(--pst-color-border); + background-color: var(--pst-color-background); +} +.card-header { + border-bottom-color: var(--pst-color-border); + background-color: var(--mne-color-card-header); +} + +/* *************************************** homepage funder/institution logos */ +div#funder-logos div.card, +div#funder-logos div.card img, +div#institution-logos div.card, +div#institution-logos div.card img, +div#contributor-avatars div.card, +div#contributor-avatars div.card img { + background-color: unset; + border: none; + border-radius: unset; +} +div#contributor-avatars div.card img { + width: 2.5em; +} +.contributor-avatar { + clip-path: circle(closest-side); +} + +/* ************************************************************ funders page */ +ul.funders li { + margin-left: 36px; + text-indent: -36px; + padding-bottom: 9px; +} +ul.funders li img { + width: 30px; + max-height: 24px; + object-fit: contain; + background-color: unset !important; +} + +/* *********************************************************** contrib guide */ +ul.icon-bullets { + list-style-type: none; + padding-left: 2em; + text-indent: -1.5em; +} +.small-stack { + font-size: 0.5em; +} + +/* *********************************************************** miscellaneous */ +.hidden { + display: none; +} +img.hidden { + visibility: hidden; +} +td.justify { + text-align-last: justify; +} + +/* Matplotlib HTML5 video embedding */ +div.sphx-glr-animation video { + max-width: 100%; + height: auto; +} + +/* fix sidebar scrollbars */ +.sidebar-primary-items__end { + margin-bottom: 0 !important; + margin-top: 0 !important; + margin-left: 0 !important; + margin-right: 0 !important; +} diff --git a/mne-python/source/doc/_static/versions.json b/mne-python/source/doc/_static/versions.json new file mode 100644 index 0000000000000000000000000000000000000000..1592342851bbe03191bfda94f503a37ce343d136 --- /dev/null +++ b/mne-python/source/doc/_static/versions.json @@ -0,0 +1,86 @@ +[ + { + "name": "1.12 (dev)", + "version": "dev", + "url": "https://mne.tools/dev/" + }, + { + "name": "1.11 (stable)", + "version": "stable", + "url": "https://mne.tools/stable/" + }, + { + "name": "1.10", + "version": "1.10", + "url": "https://mne.tools/1.10/" + }, + { + "name": "1.9", + "version": "1.9", + "url": "https://mne.tools/1.9/" + }, + { + "name": "1.8", + "version": "1.8", + "url": "https://mne.tools/1.8/" + }, + { + "name": "1.7", + "version": "1.7", + "url": "https://mne.tools/1.7/" + }, + { + "name": "1.6", + "version": "1.6", + "url": "https://mne.tools/1.6/" + }, + { + "name": "1.5", + "version": "1.5", + "url": "https://mne.tools/1.5/" + }, + { + "name": "1.4", + "version": "1.4", + "url": "https://mne.tools/1.4/" + }, + { + "name": "1.3", + "version": "1.3", + "url": "https://mne.tools/1.3/" + }, + { + "name": "1.2", + "version": "1.2", + "url": "https://mne.tools/1.2/" + }, + { + "version": "1.1", + "url": "https://mne.tools/1.1/" + }, + { + "version": "1.0", + "url": "https://mne.tools/1.0/" + }, + { + "version": "0.24", + "url": "https://mne.tools/0.24/" + }, + { + "version": "0.23", + "url": "https://mne.tools/0.23/" + }, + { + "version": "0.22", + "url": "https://mne.tools/0.22/" + }, + { + "version": "0.21", + "url": "https://mne.tools/0.21/" + }, + { + "name": "≤ 0.20 ...", + "version": "0.20", + "url": "https://mne.tools/dev/old_versions/" + } +] diff --git a/mne-python/source/doc/_templates/autosummary/class.rst b/mne-python/source/doc/_templates/autosummary/class.rst new file mode 100644 index 0000000000000000000000000000000000000000..fe4744011c02cb0a85197447c981233e9d6cbd0b --- /dev/null +++ b/mne-python/source/doc/_templates/autosummary/class.rst @@ -0,0 +1,12 @@ +{{ fullname | escape | underline }} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :special-members: __contains__,__getitem__,__iter__,__len__,__add__,__sub__,__mul__,__div__,__neg__ + :members: + +.. _sphx_glr_backreferences_{{ fullname }}: + +.. minigallery:: {{ fullname }} + :add-heading: diff --git a/mne-python/source/doc/_templates/autosummary/class_no_inherited_members.rst b/mne-python/source/doc/_templates/autosummary/class_no_inherited_members.rst new file mode 100644 index 0000000000000000000000000000000000000000..279bc0344d9edd4fb94fab6697b2fe9103836a5c --- /dev/null +++ b/mne-python/source/doc/_templates/autosummary/class_no_inherited_members.rst @@ -0,0 +1,13 @@ +{{ fullname | escape | underline }} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :special-members: __contains__,__getitem__,__iter__,__len__,__add__,__sub__,__mul__,__div__,__neg__ + :members: + :no-inherited-members: + +.. _sphx_glr_backreferences_{{ fullname }}: + +.. minigallery:: {{ fullname }} + :add-heading: diff --git a/mne-python/source/doc/_templates/autosummary/class_no_members.rst b/mne-python/source/doc/_templates/autosummary/class_no_members.rst new file mode 100644 index 0000000000000000000000000000000000000000..afe62bc489372e2155b61c983426bbeb57d06f41 --- /dev/null +++ b/mne-python/source/doc/_templates/autosummary/class_no_members.rst @@ -0,0 +1,8 @@ +{{ fullname | escape | underline }} + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + :no-special-members: + :no-members: + :no-inherited-members: diff --git a/mne-python/source/doc/_templates/autosummary/function.rst b/mne-python/source/doc/_templates/autosummary/function.rst new file mode 100644 index 0000000000000000000000000000000000000000..bd78b8e8e3aa72d04dc29b1acf87953dc3e45c6f --- /dev/null +++ b/mne-python/source/doc/_templates/autosummary/function.rst @@ -0,0 +1,10 @@ +{{ fullname | escape | underline }} + +.. currentmodule:: {{ module }} + +.. autofunction:: {{ objname }} + +.. _sphx_glr_backreferences_{{ fullname }}: + +.. minigallery:: {{ fullname }} + :add-heading: diff --git a/mne-python/source/doc/_templates/copyright.html b/mne-python/source/doc/_templates/copyright.html new file mode 100644 index 0000000000000000000000000000000000000000..742b8b7e09c60257f5b221852e649f2a9ec461f8 --- /dev/null +++ b/mne-python/source/doc/_templates/copyright.html @@ -0,0 +1 @@ +

© Copyright {{ copyright }}

diff --git a/mne-python/source/doc/_templates/homepage.html b/mne-python/source/doc/_templates/homepage.html new file mode 100644 index 0000000000000000000000000000000000000000..023e92e4dbc58ed2f8a08d95e9d637cb2f4b7a1c --- /dev/null +++ b/mne-python/source/doc/_templates/homepage.html @@ -0,0 +1,46 @@ + +
+
+ {% for item in carousel %} + + {% endfor %} +
+
+ +
+

Funders

+
+ {% for item in funders -%} +
+ + {{ item.title }} + +
+ {% endfor %} +
+
+ +
+

Supporting institutions

+
+ {% for inst in institutions -%} +
+ + {{ inst.name }} + +
+ {% endfor %} +
+ +{% include 'avatars.html' %} +
diff --git a/mne-python/source/doc/_templates/layout.html b/mne-python/source/doc/_templates/layout.html new file mode 100644 index 0000000000000000000000000000000000000000..87bf1bde9ac3f9751491bc30ba5340722a3e1abb --- /dev/null +++ b/mne-python/source/doc/_templates/layout.html @@ -0,0 +1,20 @@ +{%- extends 'pydata_sphinx_theme/layout.html' %} + +{% block extrahead %} + + {{ super() }} +{% endblock %} + +{% block docs_body %} +
+ {% block body %} {% endblock %} + {% if pagename == 'index' %} + {%- include 'homepage.html' -%} + {% endif %} +
+{% endblock %} + +{%- block scripts_end %} + {{ super() }} + +{%- endblock %} diff --git a/mne-python/source/doc/_templates/sidebar-quicklinks.html b/mne-python/source/doc/_templates/sidebar-quicklinks.html new file mode 100644 index 0000000000000000000000000000000000000000..7a27cd532c16d6916efc6962d50da64e9ec61996 --- /dev/null +++ b/mne-python/source/doc/_templates/sidebar-quicklinks.html @@ -0,0 +1,13 @@ +
+
Version {{ release }}
+ +
diff --git a/mne-python/source/doc/api/connectivity.rst b/mne-python/source/doc/api/connectivity.rst new file mode 100644 index 0000000000000000000000000000000000000000..acd492c9da72259bf6ab2a160ca9239f6111e087 --- /dev/null +++ b/mne-python/source/doc/api/connectivity.rst @@ -0,0 +1,6 @@ + +Connectivity Estimation +======================= + +As of 0.24, connectivity functionality has been moved to the separate package +:mod:`mne-connectivity:mne_connectivity`. diff --git a/mne-python/source/doc/api/covariance.rst b/mne-python/source/doc/api/covariance.rst new file mode 100644 index 0000000000000000000000000000000000000000..b5449186b27e3c34d14da7629fee22f522caaccc --- /dev/null +++ b/mne-python/source/doc/api/covariance.rst @@ -0,0 +1,19 @@ + +Covariance computation +====================== + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + Covariance + compute_covariance + compute_raw_covariance + cov.compute_whitener + cov.prepare_noise_cov + cov.regularize + compute_rank + make_ad_hoc_cov + read_cov + write_cov diff --git a/mne-python/source/doc/api/creating_from_arrays.rst b/mne-python/source/doc/api/creating_from_arrays.rst new file mode 100644 index 0000000000000000000000000000000000000000..f5771f15ef80791adeb0b127c30dff19ffa7523e --- /dev/null +++ b/mne-python/source/doc/api/creating_from_arrays.rst @@ -0,0 +1,13 @@ + +Creating data objects from arrays +================================= + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + EvokedArray + EpochsArray + io.RawArray + create_info diff --git a/mne-python/source/doc/api/datasets.rst b/mne-python/source/doc/api/datasets.rst new file mode 100644 index 0000000000000000000000000000000000000000..87730fbd717b39c16effaa0c72a066121c9a2517 --- /dev/null +++ b/mne-python/source/doc/api/datasets.rst @@ -0,0 +1,51 @@ + +Datasets +======== + +.. currentmodule:: mne.datasets + +:py:mod:`mne.datasets`: + +.. automodule:: mne.datasets + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + fetch_dataset + has_dataset + brainstorm.bst_auditory.data_path + brainstorm.bst_resting.data_path + brainstorm.bst_raw.data_path + default_path + eegbci.load_data + eegbci.standardize + fetch_aparc_sub_parcellation + fetch_fsaverage + fetch_hcp_mmp_parcellation + fetch_infant_template + fetch_phantom + fnirs_motor.data_path + hf_sef.data_path + kiloword.data_path + limo.load_data + misc.data_path + mtrf.data_path + multimodal.data_path + opm.data_path + sleep_physionet.age.fetch_data + sleep_physionet.temazepam.fetch_data + sample.data_path + somato.data_path + spm_face.data_path + ucl_opm_auditory.data_path + visual_92_categories.data_path + phantom_kit.data_path + phantom_4dbti.data_path + phantom_kernel.data_path + refmeg_noise.data_path + ssvep.data_path + erp_core.data_path + epilepsy_ecog.data_path + eyelink.data_path diff --git a/mne-python/source/doc/api/decoding.rst b/mne-python/source/doc/api/decoding.rst new file mode 100644 index 0000000000000000000000000000000000000000..f8f2257825ffa37e4aecc311bd3d912f496582df --- /dev/null +++ b/mne-python/source/doc/api/decoding.rst @@ -0,0 +1,43 @@ + +.. _api_decoding: + +Decoding +======== + +:py:mod:`mne.decoding`: + +.. automodule:: mne.decoding + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + CSP + EMS + FilterEstimator + LinearModel + PSDEstimator + Scaler + TemporalFilter + TimeFrequency + UnsupervisedSpatialFilter + Vectorizer + ReceptiveField + TimeDelayingRidge + SlidingEstimator + GeneralizingEstimator + SPoC + SSD + XdawnTransformer + SpatialFilter + +Functions that assist with decoding and model fitting: + +.. autosummary:: + :toctree: ../generated/ + + compute_ems + cross_val_multiscore + get_coef + get_spatial_filter_from_estimator diff --git a/mne-python/source/doc/api/events.rst b/mne-python/source/doc/api/events.rst new file mode 100644 index 0000000000000000000000000000000000000000..88479eb8f3e9ca59e8a83a460d38ee63637c7acf --- /dev/null +++ b/mne-python/source/doc/api/events.rst @@ -0,0 +1,59 @@ + +Events +====== + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + Annotations + AcqParserFIF + HEDAnnotations + concatenate_events + count_events + find_events + find_stim_steps + make_fixed_length_events + make_fixed_length_epochs + merge_events + parse_config + pick_events + read_annotations + read_events + write_events + concatenate_epochs + events_from_annotations + annotations_from_events + count_annotations + +:py:mod:`mne.event`: + +.. automodule:: mne.event + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.event + +.. autosummary:: + :toctree: ../generated/ + + define_target_events + match_event_names + shift_time_events + +:py:mod:`mne.epochs`: + +.. automodule:: mne.epochs + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.epochs + +.. autosummary:: + :toctree: ../generated/ + + average_movements + combine_event_ids + equalize_epoch_counts + make_metadata diff --git a/mne-python/source/doc/api/export.rst b/mne-python/source/doc/api/export.rst new file mode 100644 index 0000000000000000000000000000000000000000..7c3bfc3f868dd555bbc59b4b7ae2978b1de327f1 --- /dev/null +++ b/mne-python/source/doc/api/export.rst @@ -0,0 +1,19 @@ + +Exporting +================ + +:py:mod:`mne.export`: + +.. automodule:: mne.export + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.export + +.. autosummary:: + :toctree: ../generated/ + + export_epochs + export_evokeds + export_evokeds_mff + export_raw diff --git a/mne-python/source/doc/api/file_io.rst b/mne-python/source/doc/api/file_io.rst new file mode 100644 index 0000000000000000000000000000000000000000..2da9059deb3dc65d12988bb9fd2ad6dd76ae643d --- /dev/null +++ b/mne-python/source/doc/api/file_io.rst @@ -0,0 +1,66 @@ +File I/O +======== + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + channel_type + channel_indices_by_type + get_head_surf + get_meg_helmet_surf + get_volume_labels_from_aseg + get_volume_labels_from_src + parse_config + read_labels_from_annot + read_bem_solution + read_bem_surfaces + read_cov + read_dipole + read_epochs + read_epochs_kit + read_epochs_eeglab + read_epochs_fieldtrip + read_events + read_evokeds + read_evoked_besa + read_evoked_fieldtrip + read_evokeds_mff + read_freesurfer_lut + read_forward_solution + read_label + read_morph_map + read_proj + read_reject_parameters + read_source_estimate + read_source_spaces + read_surface + read_trans + read_tri + write_labels_to_annot + write_bem_solution + write_bem_surfaces + write_head_bem + write_cov + write_events + write_evokeds + write_forward_solution + write_label + write_proj + write_source_spaces + write_surface + write_trans + what + io.read_info + io.write_info + io.show_fiff + io.get_channel_type_constants + +Base class: + +.. autosummary:: + :toctree: ../generated/ + :template: autosummary/class_no_members.rst + + BaseEpochs diff --git a/mne-python/source/doc/api/forward.rst b/mne-python/source/doc/api/forward.rst new file mode 100644 index 0000000000000000000000000000000000000000..5abcd5178fcd376e1095be3bcc762974e84de955 --- /dev/null +++ b/mne-python/source/doc/api/forward.rst @@ -0,0 +1,67 @@ + +Forward Modeling +================ + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + :template: autosummary/class_no_inherited_members.rst + + Forward + SourceSpaces + +.. autosummary:: + :toctree: ../generated/ + + add_source_space_distances + apply_forward + apply_forward_raw + average_forward_solutions + convert_forward_solution + decimate_surface + dig_mri_distances + forward.compute_depth_prior + forward.compute_orient_prior + forward.restrict_forward_to_label + forward.restrict_forward_to_stc + make_bem_model + make_bem_solution + make_forward_dipole + make_forward_solution + make_field_map + make_sphere_model + morph_source_spaces + read_bem_surfaces + read_forward_solution + read_trans + read_source_spaces + read_surface + sensitivity_map + setup_source_space + setup_volume_source_space + surface.complete_surface_info + surface.read_curvature + use_coil_def + write_bem_surfaces + write_trans + +:py:mod:`mne.bem`: + +.. automodule:: mne.bem + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.bem + +.. autosummary:: + :toctree: ../generated/ + + ConductorModel + fit_sphere_to_headshape + get_fitting_dig + make_watershed_bem + make_flash_bem + make_scalp_surfaces + convert_flash_mris + distance_to_bem diff --git a/mne-python/source/doc/api/inverse.rst b/mne-python/source/doc/api/inverse.rst new file mode 100644 index 0000000000000000000000000000000000000000..754244c17fe0e461d180e163b5aecdde02901c6e --- /dev/null +++ b/mne-python/source/doc/api/inverse.rst @@ -0,0 +1,100 @@ + +Inverse Solutions +================= + +:py:mod:`mne.minimum_norm`: + +.. automodule:: mne.minimum_norm + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.minimum_norm + +.. autosummary:: + :toctree: ../generated/ + + InverseOperator + apply_inverse + apply_inverse_cov + apply_inverse_epochs + apply_inverse_raw + apply_inverse_tfr_epochs + compute_source_psd + compute_source_psd_epochs + compute_rank_inverse + estimate_snr + make_inverse_operator + prepare_inverse_operator + read_inverse_operator + source_band_induced_power + source_induced_power + write_inverse_operator + make_inverse_resolution_matrix + resolution_metrics + get_cross_talk + get_point_spread + +:py:mod:`mne.inverse_sparse`: + +.. automodule:: mne.inverse_sparse + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.inverse_sparse + +.. autosummary:: + :toctree: ../generated/ + + mixed_norm + tf_mixed_norm + gamma_map + make_stc_from_dipoles + +:py:mod:`mne.beamformer`: + +.. automodule:: mne.beamformer + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.beamformer + +.. autosummary:: + :toctree: ../generated/ + + Beamformer + read_beamformer + make_lcmv + apply_lcmv + apply_lcmv_epochs + apply_lcmv_raw + apply_lcmv_cov + make_dics + apply_dics + apply_dics_csd + apply_dics_epochs + apply_dics_tfr_epochs + rap_music + trap_music + make_lcmv_resolution_matrix + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + Dipole + DipoleFixed + fit_dipole + +:py:mod:`mne.dipole`: + +.. automodule:: mne.dipole + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.dipole + +.. autosummary:: + :toctree: ../generated/ + + get_phantom_dipoles diff --git a/mne-python/source/doc/api/logging.rst b/mne-python/source/doc/api/logging.rst new file mode 100644 index 0000000000000000000000000000000000000000..64cc21759a79400ee7f01999266934b14fca665d --- /dev/null +++ b/mne-python/source/doc/api/logging.rst @@ -0,0 +1,49 @@ + +Logging and Configuration +========================= + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + get_config_path + get_config + open_docs + set_log_level + set_log_file + set_config + set_cache_dir + set_memmap_min_size + sys_info + use_log_level + verbose + +:py:mod:`mne.utils`: + +.. currentmodule:: mne.utils + +.. automodule:: mne.utils + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + deprecated + warn + +:py:mod:`mne.cuda`: + +.. currentmodule:: mne.cuda + +.. automodule:: mne.cuda + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + get_cuda_memory + init_cuda + set_cuda_device diff --git a/mne-python/source/doc/api/most_used_classes.rst b/mne-python/source/doc/api/most_used_classes.rst new file mode 100644 index 0000000000000000000000000000000000000000..705b4e845b3758c900c111c209dc587fd8dd8536 --- /dev/null +++ b/mne-python/source/doc/api/most_used_classes.rst @@ -0,0 +1,12 @@ +Most-used classes +================= + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + io.Raw + Epochs + Evoked + Info diff --git a/mne-python/source/doc/api/mri.rst b/mne-python/source/doc/api/mri.rst new file mode 100644 index 0000000000000000000000000000000000000000..6cd38cbbeb42f144d8c4075b2731e209a7b2ce19 --- /dev/null +++ b/mne-python/source/doc/api/mri.rst @@ -0,0 +1,41 @@ + +MRI Processing +============== + +.. currentmodule:: mne + +Step by step instructions for using :func:`gui.coregistration`: + + - `Coregistration for subjects with structural MRI + `_ + - `Scaling a template MRI for subjects for which no MRI is available + `_ + +See also: + +- :func:`mne-gui-addons:mne_gui_addons.locate_ieeg`. + +.. autosummary:: + :toctree: ../generated/ + + coreg.get_mni_fiducials + coreg.estimate_head_mri_t + io.read_fiducials + io.write_fiducials + get_montage_volume_labels + gui.coregistration + create_default_subject + head_to_mni + head_to_mri + read_freesurfer_lut + read_lta + read_talxfm + scale_mri + scale_bem + scale_labels + scale_source_space + transforms.apply_volume_registration + transforms.apply_volume_registration_points + transforms.compute_volume_registration + vertex_to_mni + coreg.Coregistration diff --git a/mne-python/source/doc/api/preprocessing.rst b/mne-python/source/doc/api/preprocessing.rst new file mode 100644 index 0000000000000000000000000000000000000000..f1d60cfdc3b15a07baca4b73e432a0ad0aa74d8d --- /dev/null +++ b/mne-python/source/doc/api/preprocessing.rst @@ -0,0 +1,243 @@ + +Preprocessing +============= + +Projections: + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + :template: autosummary/class_no_inherited_members.rst + + Projection + +.. autosummary:: + :toctree: ../generated/ + + compute_proj_epochs + compute_proj_evoked + compute_proj_raw + read_proj + write_proj + +:py:mod:`mne.channels`: + +.. currentmodule:: mne.channels + +.. automodule:: mne.channels + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + Layout + DigMontage + compute_native_head_t + fix_mag_coil_types + read_polhemus_fastscan + get_builtin_montages + make_dig_montage + read_dig_polhemus_isotrak + read_dig_captrak + read_dig_dat + read_dig_curry + read_dig_egi + read_dig_fif + read_dig_hpts + read_dig_localite + make_standard_montage + read_custom_montage + read_meg_canonical_info + transform_to_head + compute_dev_head_t + read_layout + find_layout + make_eeg_layout + make_grid_layout + find_ch_adjacency + get_builtin_ch_adjacencies + read_ch_adjacency + equalize_channels + unify_bad_channels + rename_channels + generate_2d_layout + make_1020_channel_selections + combine_channels + +:py:mod:`mne.preprocessing`: + +.. currentmodule:: mne.preprocessing + +.. automodule:: mne.preprocessing + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + ICA + Xdawn + EOGRegression + annotate_amplitude + annotate_break + annotate_movement + annotate_muscle_zscore + annotate_nan + compute_average_dev_head_t + compute_current_source_density + compute_bridged_electrodes + compute_fine_calibration + compute_maxwell_basis + compute_proj_ecg + compute_proj_eog + compute_proj_hfc + cortical_signal_suppression + create_ecg_epochs + create_eog_epochs + find_bad_channels_lof + find_bad_channels_maxwell + find_ecg_events + find_eog_events + fix_stim_artifact + ica_find_ecg_events + ica_find_eog_events + infomax + interpolate_bridged_electrodes + equalize_bads + maxwell_filter + maxwell_filter_prepare_emptyroom + oversampled_temporal_projection + peak_finder + read_ica + read_eog_regression + realign_raw + regress_artifact + corrmap + read_ica_eeglab + read_fine_calibration + write_fine_calibration + apply_pca_obs + +:py:mod:`mne.preprocessing.nirs`: + +.. currentmodule:: mne.preprocessing.nirs + +.. automodule:: mne.preprocessing.nirs + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + optical_density + beer_lambert_law + source_detector_distances + short_channels + scalp_coupling_index + temporal_derivative_distribution_repair + +:py:mod:`mne.preprocessing.ieeg`: + +.. currentmodule:: mne.preprocessing.ieeg + +.. automodule:: mne.preprocessing.ieeg + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + project_sensors_onto_brain + make_montage_volume + warp_montage + +:py:mod:`mne.preprocessing.eyetracking`: + +.. currentmodule:: mne.preprocessing.eyetracking + +.. automodule:: mne.preprocessing.eyetracking + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + Calibration + read_eyelink_calibration + set_channel_types_eyetrack + convert_units + get_screen_visual_angle + interpolate_blinks + +EEG referencing: + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + add_reference_channels + set_bipolar_reference + set_eeg_reference + +:py:mod:`mne.filter`: + +.. currentmodule:: mne.filter + +.. automodule:: mne.filter + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + construct_iir_filter + create_filter + estimate_ringing_samples + filter_data + notch_filter + resample + +:py:mod:`mne.chpi` + +.. currentmodule:: mne.chpi + +.. automodule:: mne.chpi + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + compute_chpi_amplitudes + compute_chpi_snr + compute_chpi_locs + compute_head_pos + extract_chpi_locs_ctf + extract_chpi_locs_kit + filter_chpi + get_active_chpi + get_chpi_info + head_pos_to_trans_rot_t + read_head_pos + refit_hpi + write_head_pos + +:py:mod:`mne.transforms` + +.. currentmodule:: mne.transforms + +.. automodule:: mne.transforms + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + Transform + angle_distance_between_rigid + quat_to_rot + rot_to_quat + read_ras_mni_t diff --git a/mne-python/source/doc/api/python_reference.rst b/mne-python/source/doc/api/python_reference.rst new file mode 100644 index 0000000000000000000000000000000000000000..76c306d4210c184107c6a69c2a94b1f7a853102c --- /dev/null +++ b/mne-python/source/doc/api/python_reference.rst @@ -0,0 +1,48 @@ +.. _api_reference: + +==================== +Python API Reference +==================== + +This is the reference for classes (``CamelCase`` names) and functions +(``underscore_case`` names) of MNE-Python, grouped thematically by analysis +stage. Functions and classes that are not +below a module heading are found in the ``mne`` namespace. + +MNE-Python also provides multiple command-line scripts that can be called +directly from a terminal, see :ref:`python_commands`. + +.. container:: d-none + + :py:mod:`mne`: + + .. automodule:: mne + :no-members: + :no-inherited-members: + +.. toctree:: + :maxdepth: 2 + + most_used_classes + reading_raw_data + file_io + creating_from_arrays + export + datasets + visualization + preprocessing + events + sensor_space + covariance + mri + forward + inverse + source_space + time_frequency + connectivity + statistics + simulation + decoding + realtime + report + logging diff --git a/mne-python/source/doc/api/reading_raw_data.rst b/mne-python/source/doc/api/reading_raw_data.rst new file mode 100644 index 0000000000000000000000000000000000000000..1dcf926792feb5994ecf03246869ced29e2121bc --- /dev/null +++ b/mne-python/source/doc/api/reading_raw_data.rst @@ -0,0 +1,66 @@ +Reading raw data +================ + +:py:mod:`mne.io`: + +.. currentmodule:: mne.io + +.. automodule:: mne.io + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + anonymize_info + read_raw + read_raw_ant + read_raw_artemis123 + read_raw_bdf + read_raw_boxy + read_raw_brainvision + read_raw_bti + read_raw_cnt + read_raw_ctf + read_raw_curry + read_raw_edf + read_raw_eeglab + read_raw_egi + read_raw_eximia + read_raw_eyelink + read_raw_fieldtrip + read_raw_fif + read_raw_fil + read_raw_gdf + read_raw_hitachi + read_raw_kit + read_raw_mef + read_raw_nedf + read_raw_nicolet + read_raw_nihon + read_raw_nirx + read_raw_nsx + read_raw_neuralynx + read_raw_persyst + read_raw_snirf + +Base class: + +.. autosummary:: + :toctree: ../generated/ + :template: autosummary/class_no_members.rst + + BaseRaw + +:py:mod:`mne.io.kit`: + +.. currentmodule:: mne.io.kit + +.. automodule:: mne.io.kit + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + read_mrk diff --git a/mne-python/source/doc/api/realtime.rst b/mne-python/source/doc/api/realtime.rst new file mode 100644 index 0000000000000000000000000000000000000000..0df65ad0d56f5952635188bf87687739b2ea4ee5 --- /dev/null +++ b/mne-python/source/doc/api/realtime.rst @@ -0,0 +1,6 @@ +.. include:: ../links.inc + +Realtime +======== + +Realtime functionality has moved to the standalone module `MNE-LSL`_. diff --git a/mne-python/source/doc/api/report.rst b/mne-python/source/doc/api/report.rst new file mode 100644 index 0000000000000000000000000000000000000000..eab37eae5424d2e79bbcbbf9b247c7ded22edf4c --- /dev/null +++ b/mne-python/source/doc/api/report.rst @@ -0,0 +1,13 @@ + +MNE-Report +========== + +:py:mod:`mne`: + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + Report + open_report diff --git a/mne-python/source/doc/api/sensor_space.rst b/mne-python/source/doc/api/sensor_space.rst new file mode 100644 index 0000000000000000000000000000000000000000..8121f63f3d57c5989a82094a7c9332077ca28439 --- /dev/null +++ b/mne-python/source/doc/api/sensor_space.rst @@ -0,0 +1,38 @@ + +Sensor Space Data +================= + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + combine_evoked + concatenate_raws + equalize_channels + grand_average + match_channel_orders + pick_channels + pick_channels_cov + pick_channels_forward + pick_channels_regexp + pick_types + pick_types_forward + pick_info + read_epochs + read_reject_parameters + read_vectorview_selection + rename_channels + +:py:mod:`mne.baseline`: + +.. automodule:: mne.baseline + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.baseline + +.. autosummary:: + :toctree: ../generated/ + + rescale diff --git a/mne-python/source/doc/api/simulation.rst b/mne-python/source/doc/api/simulation.rst new file mode 100644 index 0000000000000000000000000000000000000000..3416e05ed724b3a909d33faa92e50b138641092e --- /dev/null +++ b/mne-python/source/doc/api/simulation.rst @@ -0,0 +1,45 @@ + +Simulation +========== + +:py:mod:`mne.simulation`: + +.. automodule:: mne.simulation + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.simulation + +.. autosummary:: + :toctree: ../generated/ + + add_chpi + add_ecg + add_eog + add_noise + simulate_evoked + simulate_raw + simulate_stc + simulate_sparse_stc + select_source_in_label + SourceSimulator + +:py:mod:`mne.simulation.metrics`: + +.. automodule:: mne.simulation.metrics + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.simulation.metrics + +.. autosummary:: + :toctree: ../generated/ + + cosine_score + region_localization_error + f1_score + precision_score + recall_score + roc_auc_score + spatial_deviation_error + peak_position_error diff --git a/mne-python/source/doc/api/source_space.rst b/mne-python/source/doc/api/source_space.rst new file mode 100644 index 0000000000000000000000000000000000000000..cb4aee084f22c483189621dbf3f882116e127239 --- /dev/null +++ b/mne-python/source/doc/api/source_space.rst @@ -0,0 +1,41 @@ + +Source Space Data +================= + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + BiHemiLabel + Label + MixedSourceEstimate + MixedVectorSourceEstimate + SourceEstimate + VectorSourceEstimate + VolSourceEstimate + VolVectorSourceEstimate + SourceMorph + compute_source_morph + extract_label_time_course + grade_to_tris + grade_to_vertices + label.select_sources + grow_labels + label_sign_flip + labels_to_stc + morph_labels + random_parcellation + read_labels_from_annot + read_dipole + read_label + read_source_estimate + read_source_morph + split_label + stc_to_label + stc_near_sensors + transform_surface_to + write_labels_to_annot + write_label + source_space.compute_distance_to_sensors + source_space.get_decimated_surfaces diff --git a/mne-python/source/doc/api/statistics.rst b/mne-python/source/doc/api/statistics.rst new file mode 100644 index 0000000000000000000000000000000000000000..f098b7206db22e54f05e30dc6203d9b8ff7e0ef2 --- /dev/null +++ b/mne-python/source/doc/api/statistics.rst @@ -0,0 +1,73 @@ + +.. _api_reference_statistics: + +Statistics +========== + +:py:mod:`mne.stats`: + +.. automodule:: mne.stats + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.stats + +Parametric statistics (see :mod:`scipy.stats` and :mod:`statsmodels` for more +options): + +.. autosummary:: + :toctree: ../generated/ + + ttest_1samp_no_p + ttest_ind_no_p + f_oneway + f_mway_rm + f_threshold_mway_rm + linear_regression + linear_regression_raw + +Mass-univariate multiple comparison correction: + +.. autosummary:: + :toctree: ../generated/ + + bonferroni_correction + fdr_correction + +Non-parametric (clustering) resampling methods: + +.. autosummary:: + :toctree: ../generated/ + + combine_adjacency + permutation_cluster_test + permutation_cluster_1samp_test + permutation_t_test + spatio_temporal_cluster_test + spatio_temporal_cluster_1samp_test + summarize_clusters_stc + bootstrap_confidence_interval + +ERP-related statistics: + +.. autosummary:: + :toctree: ../generated/ + + erp.compute_sme + +Compute ``adjacency`` matrices for cluster-level statistics: + +.. currentmodule:: mne + +.. autosummary:: + :toctree: ../generated/ + + channels.find_ch_adjacency + channels.read_ch_adjacency + spatial_dist_adjacency + spatial_src_adjacency + spatial_tris_adjacency + spatial_inter_hemi_adjacency + spatio_temporal_src_adjacency + spatio_temporal_tris_adjacency + spatio_temporal_dist_adjacency diff --git a/mne-python/source/doc/api/time_frequency.rst b/mne-python/source/doc/api/time_frequency.rst new file mode 100644 index 0000000000000000000000000000000000000000..a9ab2c3426822f140b432a1d090b1ec1fa7efc63 --- /dev/null +++ b/mne-python/source/doc/api/time_frequency.rst @@ -0,0 +1,83 @@ + +Time-Frequency +============== + +:py:mod:`mne.time_frequency`: + +.. automodule:: mne.time_frequency + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.time_frequency + +.. autosummary:: + :toctree: ../generated/ + + AverageTFR + AverageTFRArray + BaseTFR + EpochsTFR + EpochsTFRArray + RawTFR + RawTFRArray + CrossSpectralDensity + Spectrum + SpectrumArray + EpochsSpectrum + EpochsSpectrumArray + +Functions that operate on mne-python objects: + +.. autosummary:: + :toctree: ../generated/ + + combine_spectrum + combine_tfr + csd_tfr + csd_fourier + csd_multitaper + csd_morlet + pick_channels_csd + read_csd + fit_iir_model_raw + tfr_morlet + tfr_multitaper + tfr_stockwell + read_tfrs + write_tfrs + read_spectrum + +Functions that operate on ``np.ndarray`` objects: + +.. autosummary:: + :toctree: ../generated/ + + csd_array_fourier + csd_array_multitaper + csd_array_morlet + dpss_windows + fwhm + morlet + stft + istft + stftfreq + psd_array_multitaper + psd_array_welch + tfr_array_morlet + tfr_array_multitaper + tfr_array_stockwell + + +:py:mod:`mne.time_frequency.tfr`: + +.. automodule:: mne.time_frequency.tfr + :no-members: + :no-inherited-members: + +.. currentmodule:: mne.time_frequency.tfr + +.. autosummary:: + :toctree: ../generated/ + + cwt + morlet diff --git a/mne-python/source/doc/api/visualization.rst b/mne-python/source/doc/api/visualization.rst new file mode 100644 index 0000000000000000000000000000000000000000..280ed51f5902ec57e14ec3c1975957063885c449 --- /dev/null +++ b/mne-python/source/doc/api/visualization.rst @@ -0,0 +1,132 @@ + +Visualization +============= + +.. currentmodule:: mne.viz + +:py:mod:`mne.viz`: + +.. automodule:: mne.viz + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + Brain + ClickableImage + EvokedField + Figure3D + add_background_image + centers_to_edges + compare_fiff + circular_layout + iter_topography + mne_analyze_colormap + plot_bem + plot_brain_colorbar + plot_bridged_electrodes + plot_chpi_snr + plot_cov + plot_channel_labels_circle + plot_ch_adjacency + plot_csd + plot_dipole_amplitudes + plot_dipole_locations + plot_drop_log + plot_epochs + plot_epochs_psd_topomap + plot_events + plot_evoked + plot_evoked_image + plot_evoked_topo + plot_evoked_topomap + plot_evoked_joint + plot_evoked_field + plot_evoked_white + plot_filter + plot_head_positions + plot_ideal_filter + plot_compare_evokeds + plot_ica_sources + plot_ica_components + plot_ica_properties + plot_ica_scores + plot_ica_overlay + plot_epochs_image + plot_layout + plot_montage + plot_projs_topomap + plot_projs_joint + plot_raw + plot_raw_psd + plot_regression_weights + plot_sensors + plot_snr_estimate + plot_source_estimates + link_brains + plot_volume_source_estimates + plot_vector_source_estimates + plot_sparse_source_estimates + plot_tfr_topomap + plot_topo_image_epochs + plot_topomap + plot_alignment + snapshot_brain_montage + plot_arrowmap + set_3d_backend + get_3d_backend + use_3d_backend + set_3d_options + set_3d_view + set_3d_title + create_3d_figure + close_3d_figure + close_all_3d_figures + get_brain_class + set_browser_backend + get_browser_backend + use_browser_backend + +Eyetracking +----------- + +.. currentmodule:: mne.viz.eyetracking + +:py:mod:`mne.viz.eyetracking`: + +.. automodule:: mne.viz.eyetracking + :no-members: + :no-inherited-members: +.. autosummary:: + :toctree: ../generated/ + + plot_gaze + +UI Events +--------- + +.. currentmodule:: mne.viz.ui_events + +:py:mod:`mne.viz.ui_events`: + +.. automodule:: mne.viz.ui_events + :no-members: + :no-inherited-members: + +.. autosummary:: + :toctree: ../generated/ + + subscribe + unsubscribe + publish + link + unlink + disable_ui_events + UIEvent + ColormapRange + Contours + FigureClosing + PlaybackSpeed + TimeChange + VertexSelect diff --git a/mne-python/source/doc/bibliography.rst b/mne-python/source/doc/bibliography.rst new file mode 100644 index 0000000000000000000000000000000000000000..4a310352d8d9de513c6e3f968f889cc366169de4 --- /dev/null +++ b/mne-python/source/doc/bibliography.rst @@ -0,0 +1,12 @@ +:orphan: + +.. _general_bibliography: + +General bibliography +==================== + +The references below are arranged alphabetically by first author. + +.. bibliography:: ./references.bib + :all: + :list: enumerated diff --git a/mne-python/source/doc/changes/dev.rst b/mne-python/source/doc/changes/dev.rst new file mode 100644 index 0000000000000000000000000000000000000000..0e80d522b51a33dd6f89d0fec0d63f66ab706928 --- /dev/null +++ b/mne-python/source/doc/changes/dev.rst @@ -0,0 +1,5 @@ +.. See doc/development/contributing.rst for description of how to add entries. + +.. _current: + +.. towncrier-draft-entries:: Version |release| (development) diff --git a/mne-python/source/doc/changes/dev.rst.template b/mne-python/source/doc/changes/dev.rst.template new file mode 100644 index 0000000000000000000000000000000000000000..0e80d522b51a33dd6f89d0fec0d63f66ab706928 --- /dev/null +++ b/mne-python/source/doc/changes/dev.rst.template @@ -0,0 +1,5 @@ +.. See doc/development/contributing.rst for description of how to add entries. + +.. _current: + +.. towncrier-draft-entries:: Version |release| (development) diff --git a/mne-python/source/doc/changes/dev/13024.bugfix.rst b/mne-python/source/doc/changes/dev/13024.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..b751d61507dc22a00bbdd42a82d09a30b7e425ad --- /dev/null +++ b/mne-python/source/doc/changes/dev/13024.bugfix.rst @@ -0,0 +1 @@ +Fix bug where outdated ``seghead.mgz`` files were reused in :func:`mne.bem.make_scalp_surfaces`. Add a new parameter ``reuse_seghead`` to control whether to reuse existing ``seghead.mgz`` files, by `Victor Ferat`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13059.newfeature.rst b/mne-python/source/doc/changes/dev/13059.newfeature.rst new file mode 100644 index 0000000000000000000000000000000000000000..68352f7284f3ad535368853c89f4c863e942fcc5 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13059.newfeature.rst @@ -0,0 +1 @@ +Add :class:`mne.HEDAnnotations` for attaching `HED (Hierarchical Event Descriptors) `__ tags to annotations, by :newcontrib:`Kay Robbins`, `Bruno Aristimunha`_, and `Daniel McCloy`_. diff --git a/mne-python/source/doc/changes/dev/13196.newfeature.rst b/mne-python/source/doc/changes/dev/13196.newfeature.rst new file mode 100644 index 0000000000000000000000000000000000000000..225a026ec33917361389eedc4dee9f9b709da168 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13196.newfeature.rst @@ -0,0 +1 @@ +Add support for :meth:`mne.io.Raw.interpolate_to` and related methods (and :func:`mne.channels.read_meg_canonical_info`) for interpolating MEG data across systems, by :newcontrib:`Konstantinos Tsilimparis`. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13408.newfeature.rst b/mne-python/source/doc/changes/dev/13408.newfeature.rst new file mode 100644 index 0000000000000000000000000000000000000000..c43ebb1144f49012c94e36878009766a11062639 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13408.newfeature.rst @@ -0,0 +1 @@ +Add support for multi-wavelength NIRS processing to :func:`mne.preprocessing.nirs.beer_lambert_law`, :func:`mne.preprocessing.nirs.scalp_coupling_index`, and SNIRF reader :func:`mne.io.read_raw_snirf`, by :newcontrib:`Tamas Fehervari`. diff --git a/mne-python/source/doc/changes/dev/13518.bugfix.rst b/mne-python/source/doc/changes/dev/13518.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..7b74ebb4453adbbddbea8285ea11dbd48bac680b --- /dev/null +++ b/mne-python/source/doc/changes/dev/13518.bugfix.rst @@ -0,0 +1 @@ +Make :meth:`~mne.io.Raw.interpolate_bads` method flexible (ignore, warn, raise) about how to handle interpolation of channels with invalid positions, by `Himanshu Mahor`_. diff --git a/mne-python/source/doc/changes/dev/13520.bugfix.rst b/mne-python/source/doc/changes/dev/13520.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..8540469462b64d6f83cd4339f64905aec3e92de7 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13520.bugfix.rst @@ -0,0 +1 @@ +Preserve ``kit_system_id`` in forward-solution ``Info``, by :newcontrib:`Melih Yayli`. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13521.bugfix.rst b/mne-python/source/doc/changes/dev/13521.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..bba18190331a4e02b3989b8329072a7528670119 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13521.bugfix.rst @@ -0,0 +1 @@ +Fix bug preventing :func:`mne.time_frequency.read_spectrum` from reading saved :class:`mne.time_frequency.Spectrum` objects created from :meth:`mne.time_frequency.EpochsSpectrum.average`, by `Thomas Binns`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13525.bugfix.rst b/mne-python/source/doc/changes/dev/13525.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..8477178380a46e4246ef65d0d0032454b6e0eee1 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13525.bugfix.rst @@ -0,0 +1 @@ +Fix bug where :func:`mne.chpi.refit_hpi` did not take ``gof_limit`` into account when fitting HPI order, by `Eric Larson`_ diff --git a/mne-python/source/doc/changes/dev/13526.bugfix.rst b/mne-python/source/doc/changes/dev/13526.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..09827e7a5811abdc0930a43f4bedf011ebd685b7 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13526.bugfix.rst @@ -0,0 +1 @@ +Fix bug preventing reading of :class:`mne.time_frequency.Spectrum` and :class:`mne.time_frequency.BaseTFR` objects created in MNE<1.8 using the deprecated subject info birthday tuple format, by `Thomas Binns`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13528.bugfix.rst b/mne-python/source/doc/changes/dev/13528.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..ef24b8c6e2409993b3fc468d80ea27c3f7aaa27a --- /dev/null +++ b/mne-python/source/doc/changes/dev/13528.bugfix.rst @@ -0,0 +1 @@ +Fix bug where invalid date formats passed to :meth:`mne.Info.set_meas_date` were not caught, by `Thomas Binns`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13532.other.rst b/mne-python/source/doc/changes/dev/13532.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..4e6bca707a47d8a2974ab39103ea0a4bf6c6fef9 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13532.other.rst @@ -0,0 +1 @@ +Created a quality control report tutorial :ref:`tut-qc-report`, by :newcontrib:`varshaa-1616`. diff --git a/mne-python/source/doc/changes/dev/13539.bugfix.rst b/mne-python/source/doc/changes/dev/13539.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..ddf6f4caffdbdbe9d111a6c38b868ccebe7bf961 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13539.bugfix.rst @@ -0,0 +1,2 @@ +Fix bug with :ref:`mne coreg` where interactively altered MRI fiducials were not used when +scaling a surrogate subject, by `Eric Larson`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13541.other.rst b/mne-python/source/doc/changes/dev/13541.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..fe613ba4729392e688382cb3a02acf5e81978741 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13541.other.rst @@ -0,0 +1 @@ +Improved docs for :func:`mne.io.read_raw_nirx`, by :newcontrib:`Natneal B`. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13549.bugfix.rst b/mne-python/source/doc/changes/dev/13549.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..5c0d111f40c39efa7a955dda8288203618852c81 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13549.bugfix.rst @@ -0,0 +1 @@ +Fix bug with :func:`mne.viz.plot_evoked` where channels were plotted above axis spines, by `Michael Straube`_. diff --git a/mne-python/source/doc/changes/dev/13551.other.rst b/mne-python/source/doc/changes/dev/13551.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..252200605ef37ac39954839a13dff07d79569b2a --- /dev/null +++ b/mne-python/source/doc/changes/dev/13551.other.rst @@ -0,0 +1 @@ +Refactor f-strings in ``mne/tests/test_import_nesting.py``, by :newcontrib:`Shruti Bhale`. diff --git a/mne-python/source/doc/changes/dev/13558.bugfix.rst b/mne-python/source/doc/changes/dev/13558.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..2d62eb8b0cecb8fdd3e0935a6f93c7502c032beb --- /dev/null +++ b/mne-python/source/doc/changes/dev/13558.bugfix.rst @@ -0,0 +1 @@ +Fix axis limits in :meth:`mne.preprocessing.eyetracking.Calibration.plot` to use screen resolution if available, by :newcontrib:`Gnaneswar Lopinti`. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13566.other.rst b/mne-python/source/doc/changes/dev/13566.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..20f2066726a4eb4fc2c6dce9fd8229111601afe0 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13566.other.rst @@ -0,0 +1 @@ +Remove legacy Python-version compatibility checks in ``mne.utils.misc._empty_hash`` now that ``usedforsecurity=False`` is always supported, by :newcontrib:`Varun Kasyap Pentamaraju` (:gh:`13566`). diff --git a/mne-python/source/doc/changes/dev/13570.newfeature.rst b/mne-python/source/doc/changes/dev/13570.newfeature.rst new file mode 100644 index 0000000000000000000000000000000000000000..284614e1b9ec7dc6bfc38b7b1a6aab2326145136 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13570.newfeature.rst @@ -0,0 +1,3 @@ +Add an optional ``show_channel_names`` parameter to +:meth:`mne.viz.plot_alignment` to overlay channel labels at sensor +locations in the 3D alignment view, by :newcontrib:`Aman Srivastava`. diff --git a/mne-python/source/doc/changes/dev/13579.bugfix.rst b/mne-python/source/doc/changes/dev/13579.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..29b9ab063725c95ab59c615bc017759ec4e1e90c --- /dev/null +++ b/mne-python/source/doc/changes/dev/13579.bugfix.rst @@ -0,0 +1 @@ +Fix bug with montage test error message checking, by `Eric Larson`_. diff --git a/mne-python/source/doc/changes/dev/13585.other.rst b/mne-python/source/doc/changes/dev/13585.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..bb62007ee71d89b8461a193f844f4141777cf921 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13585.other.rst @@ -0,0 +1 @@ +Fix deprecation of setting a shape on an array directly in ``numpy`` 2.5+, by `Mathieu Scheltienne`_. diff --git a/mne-python/source/doc/changes/dev/13591.other.rst b/mne-python/source/doc/changes/dev/13591.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..20831356a0a27e4b77b15f56d07bcf83e4398bf9 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13591.other.rst @@ -0,0 +1 @@ +Documentation improvement for eSSS in docstring :func:`mne.preprocessing.maxwell_filter` and in the MaxFilter example by `Simon Kern`_. diff --git a/mne-python/source/doc/changes/dev/13593.other.rst b/mne-python/source/doc/changes/dev/13593.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..fe9694f2c92bfae3f67b93e0fe89bf2cd8dddb28 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13593.other.rst @@ -0,0 +1 @@ +make :func:`mne.sys_info` work on Windows systems with Powershell version 7+, by `Marijn van Vliet`_ diff --git a/mne-python/source/doc/changes/dev/13595.bugfix.rst b/mne-python/source/doc/changes/dev/13595.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..1eda0af925cddbdd28b48e5495db520b6f43ba82 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13595.bugfix.rst @@ -0,0 +1 @@ +Fix bug where :func:`mne.viz.plot_evoked_white` did not accept a single "meg" rank value like those returned from :func:`mne.compute_rank`, by `Eric Larson`_. diff --git a/mne-python/source/doc/changes/dev/13596.other.rst b/mne-python/source/doc/changes/dev/13596.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..d06ea383a5a4ad198309bf35b415b007c0c24bc7 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13596.other.rst @@ -0,0 +1,2 @@ +Examples Using section quirk fix in documentation, by :newcontrib:`Himanshu Mahor`. + diff --git a/mne-python/source/doc/changes/dev/13602.other.rst b/mne-python/source/doc/changes/dev/13602.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..caf00bc1211025a6b4116bd45175401f9dc1e97c --- /dev/null +++ b/mne-python/source/doc/changes/dev/13602.other.rst @@ -0,0 +1 @@ +Code refactor in :func:`mne.preprocessing.eyetracking.set_channel_types_eyetrack`, by `Himanshu Mahor`_. diff --git a/mne-python/source/doc/changes/dev/13606.bugfix.rst b/mne-python/source/doc/changes/dev/13606.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..0f5424797497679d1d8f6990a4aa91aaf81dd261 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13606.bugfix.rst @@ -0,0 +1 @@ +Fix bug where :func:`mne.viz.plot_raw` would access incorrect matplotlib attributes, by :newcontrib:`Thomas Caswell`. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13610.newfeature.rst b/mne-python/source/doc/changes/dev/13610.newfeature.rst new file mode 100644 index 0000000000000000000000000000000000000000..21bfd463198a9d6a4c6d6c519d1eedcb99017a22 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13610.newfeature.rst @@ -0,0 +1 @@ +Add :func:`mne.io.read_raw_mef` for reading MEF3 files, supporting BIDS iEEG data formats, by `Bruno Aristimunha`_. diff --git a/mne-python/source/doc/changes/dev/13611.dependency.rst b/mne-python/source/doc/changes/dev/13611.dependency.rst new file mode 100644 index 0000000000000000000000000000000000000000..8b6e029dbe04bd189a53faf9ba98bbbfd1fd97da --- /dev/null +++ b/mne-python/source/doc/changes/dev/13611.dependency.rst @@ -0,0 +1,7 @@ +Updated minimum for: + +- Core dependency ``scipy >= 1.12`` +- Optional dependency ``pandas >= 2.2`` +- Optional dependency ``scikit-learn >= 1.4`` + +Changed implemented via CI action created by `Thomas Binns`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13628.bugfix.rst b/mne-python/source/doc/changes/dev/13628.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..883ac03c2da6841e2c1efc235309d96d81bcbe6c --- /dev/null +++ b/mne-python/source/doc/changes/dev/13628.bugfix.rst @@ -0,0 +1 @@ +Fix :func:`mne.io.read_raw_snirf` raising ``TypeError`` when ``landmarkLabels`` is empty or scalar, by `Bruno Aristimunha`_. diff --git a/mne-python/source/doc/changes/dev/13630.bugfix.rst b/mne-python/source/doc/changes/dev/13630.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..f865dffa9daf388b063f5bbfbb7db1a5173a21dc --- /dev/null +++ b/mne-python/source/doc/changes/dev/13630.bugfix.rst @@ -0,0 +1 @@ +Fix bug with :func:`mne.datasets.somato.data_path` where the archive couldn't be extracted due to an absolute path issue, by `Eric Larson`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13647.newfeature.rst b/mne-python/source/doc/changes/dev/13647.newfeature.rst new file mode 100644 index 0000000000000000000000000000000000000000..3b4ecc7ed53a639d34a4099a602b28e2838d4782 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13647.newfeature.rst @@ -0,0 +1 @@ +Add finer-grained control to :func:`mne.io.anonymize_info` and the related methods :meth:`mne.io.Raw.anonymize`, :meth:`mne.Epochs.anonymize`, and :meth:`mne.Evoked.anonymize` by allowing ``keep_his`` to accept one or more strings; ``keep_his=True`` remains unchanged (retaining ``"his_id"``, ``"sex"``, and ``"hand"`` from anonymization), but individual fields can now also be retained (the default ``keep_his=False`` also remains unchanged and still anonymizes all fields), by `Clemens Brunner`_. diff --git a/mne-python/source/doc/changes/dev/13654.bugfix.rst b/mne-python/source/doc/changes/dev/13654.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..e380a14f1f85bea34aa63d01944edff474185118 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13654.bugfix.rst @@ -0,0 +1 @@ +Fix bug in :meth:`mne.Epochs.plot` where clicking on the scrollbar would not scroll to the last epoch, by `Clemens Brunner`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13669.bugfix.rst b/mne-python/source/doc/changes/dev/13669.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..b6a35b96828b7fe9867c2c096230854b3c527106 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13669.bugfix.rst @@ -0,0 +1 @@ +Expose :mod:`mne.bem` namespace, which was inadverdently removed in MNE version 1.5. As an example, users can once again use the ``mne.bem.make_watershed_bem`` API entrypoint, by `Scott Huberty`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13672.bugfix.rst b/mne-python/source/doc/changes/dev/13672.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..3cf463e11d759b5e63b998808fbf9ed83e4f1479 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13672.bugfix.rst @@ -0,0 +1 @@ +Allow reading alternative nasion label ("Nz") in SNIRF files when parsing landmarkPos3D, by :newcontrib:`Aniket Singh Yadav`. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13674.other.rst b/mne-python/source/doc/changes/dev/13674.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..576f70dcf574ea34298f09a12cf5ec15a1b73c5d --- /dev/null +++ b/mne-python/source/doc/changes/dev/13674.other.rst @@ -0,0 +1 @@ +Improve documentation of return values to clarify that methods typically return the original instance type for chaining purposes, by `Aniket Singh Yadav`_. diff --git a/mne-python/source/doc/changes/dev/13675.other.rst b/mne-python/source/doc/changes/dev/13675.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..6700691a9a1490a7b73022132ce76710e0f5c03f --- /dev/null +++ b/mne-python/source/doc/changes/dev/13675.other.rst @@ -0,0 +1 @@ +Add :meth:`mne.Epochs.reset_index`, which replaces the legacy :meth:`mne.Epochs.reset_drop_log_selection` (the new name better reflects the method's purpose), by `Clemens Brunner`_. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13685.other.rst b/mne-python/source/doc/changes/dev/13685.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..8a6db6411a14f23a78acef62200f5d40c1e3d0c6 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13685.other.rst @@ -0,0 +1 @@ +Document the behavior of :term:`first_samp` after :meth:`~mne.io.Raw.crop` and add ``reset_first_samp`` parameter to reset it to 0 after cropping, by :newcontrib:`Famous077`. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13688.other.rst b/mne-python/source/doc/changes/dev/13688.other.rst new file mode 100644 index 0000000000000000000000000000000000000000..c061900d78a3d6501c92cd51a8ca6eddc19307f8 --- /dev/null +++ b/mne-python/source/doc/changes/dev/13688.other.rst @@ -0,0 +1 @@ +Add a note to :meth:`mne.Epochs.drop` describing a potential mismatch between the indices expected by :meth:`~mne.Epochs.drop` and those found in the ``selection`` attribute when epochs have been automatically dropped, by :newcontrib:`Famous Raj Bhat`. \ No newline at end of file diff --git a/mne-python/source/doc/changes/dev/13706.newfeature.rst b/mne-python/source/doc/changes/dev/13706.newfeature.rst new file mode 100644 index 0000000000000000000000000000000000000000..4624f5b2be812a15e15d3e42b8a4a07fa2a7e6ac --- /dev/null +++ b/mne-python/source/doc/changes/dev/13706.newfeature.rst @@ -0,0 +1 @@ +Add support for scalar or per-vertex ``alpha`` (shape ``(n_vertices,)``) in distributed overlays, including validation/errors for invalid shapes, tests, and a visualization example in ``examples/visualization/brain.py`` using :meth:`mne.viz.Brain.add_data`, by :newcontrib:`Pragnya Khandelwal`. (:gh:`13706`) diff --git a/mne-python/source/doc/changes/dev/13714.bugfix.rst b/mne-python/source/doc/changes/dev/13714.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..e5eb842da21c09ae19d89c1f045b107a2ed4bb1d --- /dev/null +++ b/mne-python/source/doc/changes/dev/13714.bugfix.rst @@ -0,0 +1 @@ +Fix bug in 3D overlay compositing that could produce NaN RGBA values when the resulting alpha is zero, by `Pragnya Khandelwal`_. diff --git a/mne-python/source/doc/changes/dev/13723.bugfix.rst b/mne-python/source/doc/changes/dev/13723.bugfix.rst new file mode 100644 index 0000000000000000000000000000000000000000..f5e6b619cdad19166c2019bf76daa017243c0d0e --- /dev/null +++ b/mne-python/source/doc/changes/dev/13723.bugfix.rst @@ -0,0 +1 @@ +Change default-pick 'data' for "eyegaze" to false, following existing documentation. by :newcontrib:`Benedikt Ehinger`. diff --git a/mne-python/source/doc/changes/names.inc b/mne-python/source/doc/changes/names.inc new file mode 100644 index 0000000000000000000000000000000000000000..ac53955a57f2ac2c96f373edbdad87d3fbc2e482 --- /dev/null +++ b/mne-python/source/doc/changes/names.inc @@ -0,0 +1,370 @@ +.. _Aaron Earle-Richardson: https://github.com/Aaronearlerichardson +.. _Abram Hindle: https://softwareprocess.es +.. _Adam Li: https://github.com/adam2392 +.. _Adeline Fecker: https://github.com/adelinefecker +.. _Adina Wagner: https://github.com/adswa +.. _Adonay Nunes: https://github.com/AdoNunes +.. _Alan Leggitt: https://github.com/leggitta +.. _Alejandro Weinstein: http://ocam.cl +.. _Alessandro Tonin: https://www.linkedin.com/in/alessandro-tonin-7892b046 +.. _Alex Ciok: https://github.com/alexCiok +.. _Alex Gramfort: https://alexandre.gramfort.net +.. _Alex Kiefer: https://home.alexk101.dev +.. _Alex Lepauvre: https://github.com/AlexLepauvre +.. _Alex Rockhill: https://github.com/alexrockhill/ +.. _Alexander Rudiuk: https://github.com/ARudiuk +.. _Alexandre Barachant: https://alexandre.barachant.org +.. _Aman Srivastava: https://github.com/aman-coder03 +.. _Andrea Brovelli: https://brovelli.github.io/ +.. _Andreas Hojlund: https://github.com/ahoejlund +.. _Andres Rodriguez: https://github.com/infinitejest/ +.. _Andrew Dykstra: https://github.com/adykstra +.. _Andrew Gilbert: https://github.com/adgilbert +.. _Andrew Quinn: https://github.com/ajquinn +.. _Aniket Pradhan: https://github.com/Aniket-Pradhan +.. _Aniket Singh Yadav: https://github.com/Aniketsy +.. _Anna Padee: https://github.com/apadee/ +.. _Annalisa Pascarella: https://github.com/annapasca +.. _Anne-Sophie Dubarry: https://github.com/annesodub +.. _Antoine Collas: https://www.antoinecollas.fr +.. _Antoine Gauthier: https://github.com/Okamille +.. _Antti Rantala: https://github.com/Odingod +.. _Apoorva Karekal: https://github.com/apoorva6262 +.. _Archit Singhal: https://github.com/architsinghal-mriirs +.. _Arne Pelzer: https://github.com/aplzr +.. _Ashley Drew: https://github.com/ashdrew +.. _Asish Panda: https://github.com/kaichogami +.. _Austin Hurst: https://github.com/a-hurst +.. _Beige Jin: https://github.com/BeiGeJin +.. _Ben Beasley: https://github.com/musicinmybrain +.. _Benedikt Ehinger: https://www.benediktehinger.de +.. _Bradley Voytek: https://github.com/voytek +.. _Britta Westner: https://britta-wstnr.github.io +.. _Bruno Aristimunha: https://bruaristimunha.github.io +.. _Bruno Nicenboim: https://bnicenboim.github.io +.. _btkcodedev: https://github.com/btkcodedev +.. _buildqa: https://github.com/buildqa +.. _Carina Forster: https://github.com/CarinaFo +.. _Carlos de la Torre-Ortiz: https://ctorre.me +.. _Cathy Nangini: https://github.com/KatiRG +.. _Chetan Gohil: https://github.com/cgohil8 +.. _Chris Bailey: https://github.com/cjayb +.. _Chris Holdgraf: https://chrisholdgraf.com +.. _Chris Mullins: https://crmullins.com +.. _Christian Brodbeck: https://github.com/christianbrodbeck +.. _Christian O'Reilly: https://github.com/christian-oreilly +.. _Christopher Dinh: https://github.com/chdinh +.. _Chun-Hui Li: https://github.com/iamsc +.. _Clemens Brunner: https://github.com/cbrnr +.. _Cora Kim: https://github.com/kimcoco +.. _Cristóbal Moënne-Loccoz: https://github.com/cmmoenne +.. _Dan Wakeman: https://github.com/dgwakeman +.. _Daniel Carlström Schad: https://github.com/DanielCSchad +.. _Daniel Hasegan: https://daniel.hasegan.com +.. _Daniel McCloy: https://dan.mccloy.info +.. _Daniel Strohmeier: https://github.com/joewalter +.. _Daniel Tse: https://github.com/Xiezhibin +.. _Darin Erat Sleiter: https://github.com/dsleiter +.. _David Haslacher: https://github.com/davidhaslacher +.. _David Julien: https://github.com/Swy7ch +.. _David Sabbagh: https://github.com/DavidSabbagh +.. _Demetres Kostas: https://github.com/kostasde +.. _Denis Engemann: https://denis-engemann.de +.. _Dev Parikh: https://github.com/devparikh0506 +.. _Dinara Issagaliyeva: https://github.com/dissagaliyeva +.. _Diptyajit Das: https://github.com/dasdiptyajit +.. _Dirk Gütlin: https://github.com/DiGyt +.. _Dmitrii Altukhov: https://github.com/dmalt +.. _Dominik Welke: https://github.com/dominikwelke/ +.. _Dominik Wetzel: https://github.com/schmetzler +.. _Dominique Makowski: https://dominiquemakowski.github.io/ +.. _Eberhard Eich: https://github.com/ebeich +.. _Eduard Ort: https://github.com/eort +.. _Emily Stephen: https://github.com/emilyps14 +.. _Emma Bailey: https://www.cbs.mpg.de/employees/bailey +.. _Emma Zhang: https://portfolio-production-ed03.up.railway.app/ +.. _Emmanuel Ferdman: https://github.com/emmanuel-ferdman +.. _Emrecan Çelik: https://github.com/emrecncelik +.. _Enrico Varano: https://github.com/enricovara/ +.. _Enzo Altamiranda: https://www.linkedin.com/in/enzoalt +.. _Eric Larson: https://larsoner.com +.. _Erica Peterson: https://github.com/nordme +.. _Erkka Heinila: https://github.com/Teekuningas +.. _Etienne de Montalivet: https://github.com/etiennedemontalivet +.. _Evan Hathaway: https://github.com/ephathaway +.. _Evgenii Kalenkovich: https://github.com/kalenkovich +.. _Evgeny Goldstein: https://github.com/evgenygoldstein +.. _Ezequiel Mikulan: https://github.com/ezemikulan +.. _Ezequiel Mikulan: https://github.com/ezemikulan +.. _Fahimeh Mamashli: https://github.com/fmamashli +.. _Famous077: https://github.com/Famous077 +.. _Farzin Negahbani: https://github.com/Farzin-Negahbani +.. _Federico Raimondo: https://github.com/fraimondo +.. _Federico Zamberlan: https://github.com/fzamberlan +.. _Felix Klotzsche: https://github.com/eioe +.. _Felix Raimundo: https://github.com/gamazeps +.. _Florian Hofer: https://github.com/hofaflo +.. _Florin Pop: https://github.com/florin-pop +.. _Frederik Weber: https://github.com/Frederik-D-Weber +.. _Fu-Te Wong: https://github.com/zuxfoucault +.. _Gennadiy Belonosov: https://github.com/Genuster +.. _Geoff Brookshire: https://github.com/gbrookshire +.. _George O'Neill: https://georgeoneill.github.io +.. _Gnaneswar Lopinti: https://github.com/flying-spagetti +.. _Gonzalo Reina: https://orcid.org/0000-0003-4219-2306 +.. _Guillaume Dumas: https://mila.quebec/en/person/guillaume-dumas +.. _Guillaume Favelier: https://github.com/GuillaumeFavelier +.. _Hakimeh Aslsardroud: https://www.researchgate.net/profile/Hakimeh-Pourakbari +.. _Hakimeh Pourakbari: https://github.com/Hpakbari +.. _Hamid Maymandi: https://github.com/HamidMandi +.. _Hamza Abdelhedi: https://github.com/BabaSanfour +.. _Hari Bharadwaj: https://github.com/haribharadwaj +.. _Harrison Ritz: https://github.com/harrisonritz +.. _Hasrat Ali Arzoo: https://github.com/hasrat17 +.. _Henrich Kolkhorst: https://github.com/hekolk +.. _Himanshu Mahor: https://github.com/1himan +.. _Hongjiang Ye: https://github.com/ye-hongjiang +.. _Hubert Banville: https://github.com/hubertjb +.. _Hyonyoung Shin: https://github.com/mcvain +.. _Hüseyin Orkun Elmas: https://github.com/HuseyinOrkun +.. _Ilian Azz: https://github.com/ilianAZZ +.. _Ilias Machairas: https://github.com/JungleHippo +.. _Ivan Skelin: https://github.com/ivan-skelin +.. _Ivan Zubarev: https://github.com/zubara +.. _Ivana Kojcic: https://github.com/ikojcic +.. _Ivo de Jong: https://github.com/ivopascal +.. _Jaakko Leppakangas: https://github.com/jaeilepp +.. _Jack Zhang: https://github.com/jackz314 +.. _Jacob Phelan: https://github.com/JacPhe +.. _Jacob Woessner: https://github.com/withmywoessner +.. _Jair Montoya Martinez: https://github.com/jmontoyam +.. _Jan Ebert: https://www.jan-ebert.com/ +.. _Jan Sedivy: https://github.com/honzaseda +.. _Jan Sosulski: https://jan-sosulski.de +.. _Jan Zerfowski: https://github.com/jzerfowski +.. _Jan-Mathijs Schoeffelen: https://github.com/schoffelen +.. _Jasper van den Bosch: https://github.com/ilogue +.. _Jean-Baptiste Schiratti: https://github.com/jbschiratti +.. _Jean-Rémi King: https://github.com/kingjr +.. _Jeff Stout: https://megcore.nih.gov/index.php/Staff +.. _Jennifer Behnke: https://github.com/JKBehnke +.. _Jeroen Van Der Donckt: https://github.com/jvdd +.. _Jesper Duemose Nielsen: https://github.com/jdue +.. _Jevri Hanna: https://github.com/jshanna100 +.. _jeythekey: https://github.com/jeythekey +.. _Joan Massich: https://github.com/massich +.. _Johann Benerradi: https://github.com/HanBnrd +.. _Johannes Herforth: https://herforth.net +.. _Johannes Niediek: https://github.com/jniediek +.. _John Samuelsson: https://github.com/johnsam7 +.. _John Veillette: https://psychology.uchicago.edu/directory/john-veillette +.. _Jon Houck: https://www.mrn.org/people/jon-m.-houck/principal-investigators +.. _Jona Sassenhagen: https://github.com/jona-sassenhagen +.. _Jonathan Kuziek: https://github.com/kuziekj +.. _Jordan Drew: https://github.com/jadrew43 +.. _Jose Alanis: https://github.com/JoseAlanis +.. _Joshua Bear: https://github.com/joshbear +.. _Joshua Calder-Travis: https://github.com/jCalderTravis +.. _Joshua Teves: https://github.com/jbteves +.. _Judy D Zhu: https://github.com/JD-Zhu +.. _Juergen Dammers: https://github.com/jdammers +.. _Jukka Nenonen: https://www.linkedin.com/pub/jukka-nenonen/28/b5a/684 +.. _Jussi Nurminen: https://github.com/jjnurminen +.. _Kaisu Lankinen: http://bishoplab.berkeley.edu/Kaisu.html +.. _Katarina Slama: https://github.com/katarinaslama +.. _Katia Al-Amir: https://github.com/katia-sentry +.. _Kay Robbins: https://github.com/VisLab +.. _Keith Doelling: https://github.com/kdoelling1919 +.. _Konstantinos Tsilimparis: https://contsili.github.io/ +.. _Kostiantyn Maksymenko: https://github.com/makkostya +.. _Kristijan Armeni: https://github.com/kristijanarmeni +.. _Kyle Mathewson: https://github.com/kylemath +.. _Larry Eisenman: https://github.com/lneisenman +.. _Lau Møller Andersen: https://github.com/ualsbombe +.. _Laura Gwilliams: https://lauragwilliams.github.io +.. _Laurent Le Mentec: https://github.com/LaurentLM +.. _Leonardo Barbosa: https://github.com/noreun +.. _Leonardo Rochael Almeida: https://github.com/leorochael +.. _Liberty Hamilton: https://github.com/libertyh +.. _Lorenzo Desantis: https://github.com/lorenzo-desantis/ +.. _Lukas Breuer: https://www.researchgate.net/profile/Lukas-Breuer-2 +.. _Lukas Gemein: https://github.com/gemeinl +.. _Luke Bloy: https://www.research.chop.edu/imaging/team +.. _Lukáš Hejtmánek: https://github.com/hejtmy +.. _Lx37: https://github.com/Lx37 +.. _Mads Jensen: https://github.com/MadsJensen +.. _Maggie Clarke: https://github.com/mdclarke +.. _Mainak Jas: https://jasmainak.github.io +.. _Maksym Balatsko: https://github.com/mbalatsko +.. _Marcin Koculak: https://github.com/mkoculak +.. _Marian Dovgialo: https://github.com/mdovgialo +.. _Marijn van Vliet: https://github.com/wmvanvliet +.. _Mark Alexander Henney: https://github.com/henneysq +.. _Mark Wronkiewicz: https://github.com/wronk +.. _Marmaduke Woodman: https://github.com/maedoc +.. _Martin Billinger: https://github.com/mbillingr +.. _Martin Luessi: https://github.com/mluessi +.. _Martin Oberg: https://github.com/obergmartin +.. _Martin Schulz: https://github.com/marsipu +.. _Mathieu Scheltienne: https://github.com/mscheltienne +.. _Mathurin Massias: https://mathurinm.github.io/ +.. _Mats van Es: https://github.com/matsvanes +.. _Matt Boggess: https://github.com/mattboggess +.. _Matt Courtemanche: https://github.com/mjcourte +.. _Matt Sanderson: https://github.com/monkeyman192 +.. _Matteo Anelli: https://github.com/matteoanelli +.. _Matthias Dold: https://matthiasdold.de +.. _Matthias Eberlein: https://github.com/MatthiasEb +.. _Matti Hämäläinen: https://research.aalto.fi/en/persons/matti-h%C3%A4m%C3%A4l%C3%A4inen/ +.. _Matti Toivonen: https://github.com/mattitoi +.. _Mauricio Cespedes Tenorio: https://github.com/mcespedes99 +.. _Melih Yayli: https://github.com/yaylim +.. _Michael Straube: https://github.com/mistraube +.. _Michal Žák: https://github.com/michalrzak +.. _Michiru Kaneda: https://github.com/rcmdnk +.. _Mikołaj Magnuski: https://github.com/mmagnuski +.. _Milan Rybář: https://milanrybar.cz +.. _Mingjian He: https://github.com/mh105 +.. _Mohammad Daneshzand: https://github.com/mdaneshzand +.. _Mojackhak: https://github.com/Mojackhak +.. _Moritz Gerster: https://github.com/moritz-gerster +.. _Motofumi Fushimi: https://github.com/motofumi-fushimi/motofumi-fushimi.github.io +.. _Nabil Alibou: https://github.com/nabilalibou +.. _Natalie Klein: https://github.com/natalieklein +.. _Nathalie Gayraud: https://github.com/ngayraud +.. _Natneal B: https://github.com/natinew77-creator +.. _Naveen Srinivasan: https://github.com/naveensrinivasan +.. _Nick Foti: https://nfoti.github.io +.. _Nick Ward: https://profiles.ucl.ac.uk/10827-nick-ward +.. _Nicolas Barascud: https://github.com/nbara +.. _Nicolas Fourcaud-Trocmé: https://www.crnl.fr/fr/user/316 +.. _Niels Focke: https://neurologie.umg.eu/forschung/arbeitsgruppen/epilepsie-und-bildgebungsforschung +.. _Niklas Wilming: https://github.com/nwilming +.. _Nikolai Chapochnikov: https://github.com/chapochn +.. _Nikolai Kapralov: https://github.com/ctrltz +.. _Nikolas Chalas: https://github.com/Nichalas +.. _Noah Markowitz: https://github.com/nmarkowitz +.. _Okba Bekhelifi: https://github.com/okbalefthanded +.. _Olaf Hauk: https://neuroscience.cam.ac.uk/member/olafhauk +.. _Ole Jensen: https://www.psy.ox.ac.uk/people/ole-jensen +.. _Oleh Kozynets: https://github.com/OlehKSS +.. _Pablo Mainar: https://github.com/pablomainar +.. _Pablo-Arias: https://github.com/Pablo-Arias +.. _Padma Sundaram: https://www.nmr.mgh.harvard.edu/user/8071 +.. _Paul Anders: https://github.com/Mettphysik +.. _Paul Pasler: https://github.com/ppasler +.. _Paul Roujansky: https://github.com/paulroujansky +.. _Pavel Navratil: https://github.com/navrpa13 +.. _Peter Molfese: https://github.com/pmolfese +.. _Phillip Alday: https://palday.bitbucket.io +.. _Pierre Ablin: https://pierreablin.com +.. _Pierre Guetschel: https://github.com/PierreGtch +.. _Pierre-Antoine Bannier: https://github.com/PABannier +.. _Ping-Keng Jao: https://github.com/nafraw +.. _Pragnya Khandelwal: https://github.com/PragnyaKhandelwal +.. _Proloy Das: https://github.com/proloyd +.. _Qian Chu: https://github.com/qian-chu +.. _Qianliang Li: https://www.dtu.dk/english/service/phonebook/person?id=126774 +.. _Quentin Barthélemy: https://github.com/qbarthelemy +.. _Quentin Bertrand: https://github.com/QB3 +.. _Qunxi Dong: https://github.com/dongqunxi +.. _Rahul Nadkarni: https://github.com/rahuln +.. _Ram Pari: https://github.com/ramkpari +.. _Ramiro Gatti: https://github.com/ragatti +.. _ramonapariciog: https://github.com/ramonapariciog +.. _Rasmus Aagaard: https://github.com/rasgaard +.. _Rasmus Zetter: https://github.com/rzetter +.. _Reza Nasri: https://github.com/rznas +.. _Reza Shoorangiz: https://github.com/rezashr +.. _Richard Höchenberger: https://github.com/hoechenberger +.. _Richard Koehler: https://github.com/richardkoehler +.. _Richard Scholz: https://github.com/scholzri +.. _Riessarius Stargardsky: https://github.com/Riessarius +.. _Roan LaPlante: https://github.com/aestrivex +.. _Robert Luke: https://github.com/rob-luke +.. _Robert Seymour: https://neurofractal.github.io +.. _Romain Derollepot: https://github.com/rderollepot +.. _Romain Trachel: https://fr.linkedin.com/in/trachelr +.. _Roman Goj: https://romanmne.blogspot.co.uk +.. _Rongfei Jin: https://github.com/greasycat +.. _Ross Maddox: https://medicine.umich.edu/dept/khri/ross-maddox-phd +.. _Rotem Falach: https://github.com/Falach +.. _Roy Eric Wieske: https://github.com/Randomidous +.. _Sammi Chekroud: https://github.com/schekroud +.. _Samu Taulu: https://phys.washington.edu/people/samu-taulu +.. _Samuel Deslauriers-Gauthier: https://github.com/sdeslauriers +.. _Samuel Louviot: https://github.com/Sam54000 +.. _Samuel Powell: https://github.com/samuelpowell +.. _Santeri Ruuskanen: https://github.com/ruuskas +.. _Santi Martínez: https://github.com/szz-dvl +.. _Sara Sommariva: https://github.com/sarasommariva +.. _Sawradip Saha: https://sawradip.github.io/ +.. _Scott Huberty: https://orcid.org/0000-0003-2637-031X +.. _Sebastiaan Mathot: https://www.cogsci.nl/smathot +.. _Sebastian Castano: https://github.com/jscastanoc +.. _Sebastian Jentschke: https://github.com/sjentsch +.. _Sebastian Major: https://github.com/major-s +.. _Sena Er: https://github.com/sena-neuro +.. _Senwen Deng: https://snwn.de +.. _Seyed Yahya Shirazi: https://neuromechanist.github.io +.. _Sheraz Khan: https://github.com/SherazKhan +.. _Shresth Keshari: https://github.com/shresth-keshari +.. _Shristi Baral: https://github.com/shristibaral +.. _Shruti Bhale: https://github.com/shruti423 +.. _Silvia Cotroneo: https://github.com/sfc-neuro +.. _Simeon Wong: https://github.com/dtxe +.. _Simon Kern: https://skjerns.de +.. _Simon Kornblith: https://simonster.com +.. _Simon M. Hofmann: https://github.com/SHEscher +.. _Sondre Foslien: https://github.com/sondrfos +.. _Sophie Herbst: https://github.com/SophieHerbst +.. _Stanislas Chambon: https://github.com/Slasnista +.. _Stefan Appelhoff: https://stefanappelhoff.com +.. _Stefan Repplinger: https://github.com/stfnrpplngr +.. _Steinn Hauser Magnusson: https://github.com/steinnhauser +.. _Steven Bethard: https://github.com/bethard +.. _Steven Bierer: https://github.com/neurolaunch +.. _Steven Gutstein: https://github.com/smgutstein +.. _Sumalyo Datta: https://github.com/Sumalyo +.. _Susanna Aro: https://www.linkedin.com/in/susanna-aro +.. _Svea Marie Meyer: https://github.com/SveaMeyer13 +.. _Sébastien Marti: https://www.researchgate.net/profile/Sebastien-Marti +.. _T. Wang: https://github.com/twang5 +.. _Tal Linzen: https://tallinzen.net/ +.. _Tamas Fehervari: https://github.com/zEdS15B3GCwq +.. _Teon Brooks: https://github.com/teonbrooks +.. _Tharupahan Jayawardana: https://github.com/tharu-jwd +.. _Thomas Binns: https://github.com/tsbinns +.. _Thomas Caswell: https://tacaswell.github.io +.. _Thomas Hartmann: https://github.com/thht +.. _Thomas Radman: https://github.com/tradman +.. _Théodore Papadopoulo: https://github.com/papadop +.. _Timothy Gates: https://au.linkedin.com/in/tim-gates-0528a4199 +.. _Timur Sokhin: https://github.com/Qwinpin +.. _Tod Flak: https://github.com/todflak +.. _Tom Ma: https://github.com/myd7349 +.. _Tom Stone: https://github.com/tomdstone +.. _Tommy Clausner: https://github.com/TommyClausner +.. _Toomas Erik Anijärv: https://github.com/teanijarv +.. _Tristan Stenner: https://github.com/tstenner/ +.. _Tziona NessAiver: https://github.com/TzionaN +.. _user27182: https://github.com/user27182 +.. _Valerii Chirkov: https://github.com/vagechirkov +.. _varshaa-1616: https://github.com/varshaa-1616 +.. _Varun Kasyap Pentamaraju: https://github.com/varunkasyap +.. _Velu Prabhakar Kumaravel: https://github.com/vpKumaravel +.. _Victor Ferat: https://github.com/vferat +.. _Victoria Peterson: https://github.com/vpeterson +.. _Wei Xu: https://github.com/psyxw +.. _Will Turner: https://bootstrapbill.github.io +.. _Wouter Kroot: https://github.com/WouterKroot +.. _Xabier de Zuazo: https://github.com/zuazo +.. _Xiaokai Xia: https://github.com/dddd1007 +.. _Yaroslav Halchenko: http://haxbylab.dartmouth.edu/ppl/yarik.html +.. _Yiping Zuo: https://github.com/frostime +.. _Yixiao Shen: https://github.com/SYXiao2002 +.. _Yousra Bekhti: https://www.linkedin.com/pub/yousra-bekhti/56/886/421 +.. _Yu-Han Luo: https://github.com/yh-luo +.. _Zhi Zhang: https://github.com/tczhangzhi/ +.. _Ziyi ZENG: https://github.com/ZiyiTsang +.. _Zvi Baratz: https://github.com/ZviBaratz diff --git a/mne-python/source/doc/changes/v0.1.rst b/mne-python/source/doc/changes/v0.1.rst new file mode 100644 index 0000000000000000000000000000000000000000..3d60006d49746bef6c21717c2bee4dcd27399a3f --- /dev/null +++ b/mne-python/source/doc/changes/v0.1.rst @@ -0,0 +1,18 @@ +.. _changes_0_1: + +Version 0.1 (2011-09-23) +------------------------ + +- Initial release (initial commit: 2010-12-26). + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number +of commits): + +* 315 Alexandre Gramfort +* 1 Ellen Lau +* 41 Emily Ruzich +* 2 Martin Luessi +* 9 Matti Hämäläinen diff --git a/mne-python/source/doc/changes/v0.10.rst b/mne-python/source/doc/changes/v0.10.rst new file mode 100644 index 0000000000000000000000000000000000000000..d237da49930ece199328683ea0d658b7a73c33da --- /dev/null +++ b/mne-python/source/doc/changes/v0.10.rst @@ -0,0 +1,148 @@ +.. _changes_0_10: + +Version 0.10 (2015-10-26) +------------------------- + +Changelog +~~~~~~~~~ + +- Add support for generalized M-way repeated measures ANOVA for fully balanced designs with :func:`mne.stats.f_mway_rm` by `Denis Engemann`_ + +- Add epochs browser to interactively view and manipulate epochs with :func:`mne.viz.plot_epochs` by `Jaakko Leppakangas`_ + +- Speed up TF-MxNE inverse solver with block coordinate descent by `Daniel Strohmeier`_ and `Yousra Bekhti`_ + +- Speed up zero-phase overlap-add (default) filtering by a factor of up to 2 using linearity by `Ross Maddox`_ and `Eric Larson`_ + +- Add support for scaling and adjusting the number of channels/time per view by `Jaakko Leppakangas`_ + +- Add support to toggle the show/hide state of all sections with a single keypress ('t') in :class:`mne.Report` by `Mainak Jas`_ + +- Add support for BEM model creation :func:`mne.make_bem_model` by `Eric Larson`_ + +- Add support for BEM solution computation :func:`mne.make_bem_solution` by `Eric Larson`_ + +- Add ICA plotters for raw and epoch components by `Jaakko Leppakangas`_ + +- Add new object ``mne.decoding.TimeDecoding`` for decoding sensors' evoked response across time by `Jean-Rémi King`_ + +- Add command ``mne freeview_bem_surfaces`` to quickly check BEM surfaces with Freeview by `Alex Gramfort`_. + +- Add support for splitting epochs into multiple files in :func:`mne.Epochs.save` by `Mainak Jas`_ and `Alex Gramfort`_ + +- Add support for jointly resampling a raw object and event matrix to avoid issues with resampling status channels by `Marijn van Vliet`_ + +- Add new method :class:`mne.preprocessing.Xdawn` for denoising and decoding of ERP/ERF by `Alexandre Barachant`_ + +- Add support for plotting patterns/filters in :class:`mne.decoding.CSP` and :class:`mne.decoding.LinearModel` by `Romain Trachel`_ + +- Add new object :class:`mne.decoding.LinearModel` for decoding M/EEG data and interpreting coefficients of linear models with patterns attribute by `Romain Trachel`_ and `Alex Gramfort`_ + +- Add support to append new channels to an object from a list of other objects by `Chris Holdgraf`_ + +- Add interactive plotting of topomap from time-frequency representation by `Jaakko Leppakangas`_ + +- Add ``plot_topo`` method to ``Evoked`` object by `Jaakko Leppakangas`_ + +- Add fetcher :mod:`mne.datasets.brainstorm ` for datasets used by Brainstorm in their tutorials by `Mainak Jas`_ + +- Add interactive plotting of single trials by right clicking on channel name in epochs browser by `Jaakko Leppakangas`_ + +- New logos and logo generation script by `Daniel McCloy`_ + +- Add ability to plot topomap with a "skirt" (channels outside of the head circle) by `Marijn van Vliet`_ + +- Add multiple options to ICA infomax and extended infomax algorithms (number of subgaussian components, computation of bias, iteration status printing), enabling equivalent computations to those performed by EEGLAB by `Jair Montoya Martinez`_ + +- Add :func:`mne.Epochs.apply_baseline` method to ``Epochs`` objects by `Teon Brooks`_ + +- Add ``preload`` argument to :func:`mne.read_epochs` to enable on-demand reads from disk by `Eric Larson`_ + +- Big rewrite of simulation module by `Yousra Bekhti`_, `Mark Wronkiewicz`_, `Eric Larson`_ and `Alex Gramfort`_. Allows to simulate raw with artifacts (ECG, EOG) and evoked data, exploiting the forward solution. See :func:`mne.simulation.simulate_raw`, :func:`mne.simulation.simulate_evoked` and :func:`mne.simulation.simulate_sparse_stc` + +- Add :func:`mne.Epochs.load_data` method to :class:`mne.Epochs` by `Teon Brooks`_ + +- Add support for drawing topomaps by selecting an area in :func:`mne.Evoked.plot` by `Jaakko Leppakangas`_ + +- Add support for finding peaks in evoked data in :func:`mne.Evoked.plot_topomap` by `Jona Sassenhagen`_ and `Jaakko Leppakangas`_ + +- Add source space morphing in :func:`morph_source_spaces` and :func:`SourceEstimate.to_original_src` by `Eric Larson`_ and `Denis Engemann`_ + +- Adapt ``corrmap`` function (Viola et al. 2009) to semi-automatically detect similar ICs across data sets by `Jona Sassenhagen`_ and `Denis Engemann`_ and `Eric Larson`_ + +- Clarify docstring for :class:`mne.preprocessing.ICA` by `jeythekey`_ + +- New ``mne flash_bem`` command to compute BEM surfaces from Flash MRI images by `Lorenzo Desantis`_, `Alex Gramfort`_ and `Eric Larson`_. See :func:`mne.bem.make_flash_bem`. + +- New gfp parameter in :func:`mne.Evoked.plot` method to display Global Field Power (GFP) by `Eric Larson`_. + +- Add ``mne.Report.add_slider_to_section`` methods to :class:`mne.Report` by `Teon Brooks`_ + +BUG +~~~ + +- Fix ``mne.io.add_reference_channels`` not setting ``info[nchan]`` correctly by `Federico Raimondo`_ + +- Fix ``mne.stats.bonferroni_correction`` reject mask output to use corrected p-values by `Denis Engemann`_ + +- Fix FFT filter artifacts when using short windows in overlap-add by `Eric Larson`_ + +- Fix picking channels from forward operator could return a channel ordering different from ``info['chs']`` by `Chris Bailey`_ + +- Fix dropping of events after downsampling stim channels by `Marijn van Vliet`_ + +- Fix scaling in ``mne.viz.utils._setup_vmin_vmax`` by `Jaakko Leppakangas`_ + +- Fix order of component selection in :class:`mne.decoding.CSP` by `Clemens Brunner`_ + +API +~~~ + +- Rename and deprecate ``mne.viz.plot_topo`` for ``mne.viz.plot_evoked_topo`` by `Jaakko Leppakangas`_ + +- Deprecated ``mne.decoding.transformer.ConcatenateChannels`` and replaced by ``mne.decoding.EpochsVectorizer`` by `Romain Trachel`_ + +- Deprecated ``lws`` and renamed ``ledoit_wolf`` for the ``reg`` argument in :class:`mne.decoding.CSP` by `Romain Trachel`_ + +- Redesigned and rewrote :meth:`mne.Epochs.plot` (no backwards compatibility) during the GSOC 2015 by `Jaakko Leppakangas`_, `Mainak Jas`_, `Federico Raimondo`_ and `Denis Engemann`_ + +- Deprecated and renamed ``mne.viz.plot_image_epochs`` for ``mne.plot.plot_epochs_image`` by `Teon Brooks`_ + +- ``picks`` argument has been added to :func:`mne.time_frequency.tfr_morlet`, :func:`mne.time_frequency.tfr_multitaper` by `Teon Brooks`_ + +- ``mne.io.Raw.preload_data`` has been deprecated for :func:`mne.io.Raw.load_data` by `Teon Brooks`_ + +- ``RawBrainVision`` objects now always have event channel ``'STI 014'``, and recordings with no events will have this channel set to zero by `Eric Larson`_ + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number of commits): + +* 273 Eric Larson +* 270 Jaakko Leppakangas +* 194 Alexandre Gramfort +* 128 Denis A. Engemann +* 114 Jona Sassenhagen +* 107 Mark Wronkiewicz +* 97 Teon Brooks +* 81 Lorenzo De Santis +* 55 Yousra Bekhti +* 54 Jean-Rémi King +* 48 Romain Trachel +* 45 Mainak Jas +* 40 Alexandre Barachant +* 32 Marijn van Vliet +* 26 Jair Montoya +* 22 Chris Holdgraf +* 16 Christopher J. Bailey +* 7 Christian Brodbeck +* 5 Natalie Klein +* 5 Fede Raimondo +* 5 Alan Leggitt +* 5 Roan LaPlante +* 5 Ross Maddox +* 4 Dan G. Wakeman +* 3 Daniel McCloy +* 3 Daniel Strohmeier +* 1 Jussi Nurminen diff --git a/mne-python/source/doc/changes/v0.11.rst b/mne-python/source/doc/changes/v0.11.rst new file mode 100644 index 0000000000000000000000000000000000000000..218508e86fbef1fa9eb990101933360d208fa190 --- /dev/null +++ b/mne-python/source/doc/changes/v0.11.rst @@ -0,0 +1,92 @@ +.. _changes_0_11: + +Version 0.11 (2015-12-24) +------------------------- + +Changelog +~~~~~~~~~ + +- Maxwell filtering (SSS) implemented in :func:`mne.preprocessing.maxwell_filter` by `Mark Wronkiewicz`_ as part of Google Summer of Code, with help from `Samu Taulu`_, `Jukka Nenonen`_, and `Jussi Nurminen`_. Our implementation includes support for: + + - Fine calibration + + - Cross-talk correction + + - Temporal SSS (tSSS) + + - Head position translation + + - Internal component regularization + +- Compensation for movements using Maxwell filtering on epoched data in :func:`mne.epochs.average_movements` by `Eric Larson`_ and `Samu Taulu`_ + +- Add reader for Nicolet files in :func:`mne.io.read_raw_nicolet` by `Jaakko Leppakangas`_ + +- Add FIFF persistence for ICA labels by `Denis Engemann`_ + +- Display ICA labels in :func:`mne.viz.plot_ica_scores` and :func:`mne.viz.plot_ica_sources` (for evoked objects) by `Denis Engemann`_ + +- Plot spatially color coded lines in :func:`mne.Evoked.plot` by `Jona Sassenhagen`_ and `Jaakko Leppakangas`_ + +- Add reader for CTF data in :func:`mne.io.read_raw_ctf` by `Eric Larson`_ + +- Add support for Brainvision v2 in :func:`mne.io.read_raw_brainvision` by `Teon Brooks`_ + +- Improve speed of generalization across time ``mne.decoding.GeneralizationAcrossTime`` decoding up to a factor of seven by `Jean-Rémi King`_ and `Federico Raimondo`_ and `Denis Engemann`_. + +- Add the explained variance for each principal component, ``explained_var``, key to the :class:`mne.Projection` by `Teon Brooks`_ + +- Added methods ``mne.Epochs.add_eeg_average_proj``, ``mne.io.Raw.add_eeg_average_proj``, and ``mne.Evoked.add_eeg_average_proj`` to add an average EEG reference. + +- Add reader for EEGLAB data in :func:`mne.io.read_raw_eeglab` and :func:`mne.read_epochs_eeglab` by `Mainak Jas`_ + +BUG +~~~ + +- Fix bug that prevented homogeneous bem surfaces to be displayed in HTML reports by `Denis Engemann`_ + +- Added safeguards against ``None`` and negative values in reject and flat parameters in :class:`mne.Epochs` by `Eric Larson`_ + +- Fix train and test time window-length in ``mne.decoding.GeneralizationAcrossTime`` by `Jean-Rémi King`_ + +- Added lower bound in :func:`mne.stats.linear_regression` on p-values ``p_val`` (and resulting ``mlog10_p_val``) using double floating point arithmetic limits by `Eric Larson`_ + +- Fix channel name pick in :func:`mne.Evoked.get_peak` method by `Alex Gramfort`_ + +- Fix drop percentages to take into account ``ignore`` option in :func:`mne.viz.plot_drop_log` and :func:`mne.Epochs.plot_drop_log` by `Eric Larson`_. + +- :class:`mne.EpochsArray` no longer has an average EEG reference silently added (but not applied to the data) by default. Use ``mne.EpochsArray.add_eeg_ref`` to properly add one. + +- Fix :func:`mne.io.read_raw_ctf` to read ``n_samp_tot`` instead of ``n_samp`` by `Jaakko Leppakangas`_ + +API +~~~ + +- :func:`mne.io.read_raw_brainvision` now has ``event_id`` argument to assign non-standard trigger events to a trigger value by `Teon Brooks`_ + +- :func:`mne.read_epochs` now has ``add_eeg_ref=False`` by default, since average EEG reference can be added before writing or after reading using the method ``mne.Epochs.add_eeg_ref``. + +- :class:`mne.EpochsArray` no longer has an average EEG reference silently added (but not applied to the data) by default. Use ``mne.EpochsArray.add_eeg_average_proj`` to properly add one. + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number of commits): + +* 171 Eric Larson +* 117 Jaakko Leppakangas +* 58 Jona Sassenhagen +* 52 Mainak Jas +* 46 Alexandre Gramfort +* 33 Denis A. Engemann +* 28 Teon Brooks +* 24 Clemens Brunner +* 23 Christian Brodbeck +* 15 Mark Wronkiewicz +* 10 Jean-Rémi King +* 5 Marijn van Vliet +* 3 Fede Raimondo +* 2 Alexander Rudiuk +* 2 emilyps14 +* 2 lennyvarghese +* 1 Marian Dovgialo diff --git a/mne-python/source/doc/changes/v0.12.rst b/mne-python/source/doc/changes/v0.12.rst new file mode 100644 index 0000000000000000000000000000000000000000..b48b80bf2d043e88cbebc4f357c023134b5958f8 --- /dev/null +++ b/mne-python/source/doc/changes/v0.12.rst @@ -0,0 +1,211 @@ +.. _changes_0_12: + +Version 0.12 (2016-05-10) +------------------------- + +Changelog +~~~~~~~~~ + +- Add ``overlay_times`` parameter to :func:`mne.viz.plot_epochs_image` to be able to display for example reaction times on top of the images, by `Alex Gramfort`_ + +- Animation for evoked topomap in :func:`mne.Evoked.animate_topomap` by `Jaakko Leppakangas`_ + +- Make :func:`mne.channels.find_layout` more robust for KIT systems in the presence of bad or missing channels by `Jaakko Leppakangas`_ + +- Add raw movement compensation to :func:`mne.preprocessing.maxwell_filter` by `Eric Larson`_ + +- Add :class:`mne.Annotations` for for annotating segments of raw data by `Jaakko Leppakangas`_ + +- Add reading of .fif file montages by `Eric Larson`_ + +- Add system config utility :func:`mne.sys_info` by `Eric Larson`_ + +- Automatic cross-validation and scoring metrics in ``mne.decoding.GeneralizationAcrossTime``, by `Jean-Rémi King`_ + +- ``mne.decoding.GeneralizationAcrossTime`` accepts non-deterministic cross-validations, by `Jean-Rémi King`_ + +- Add plotting RMS of gradiometer pairs in :func:`mne.viz.plot_evoked_topo` by `Jaakko Leppakangas`_ + +- Add regularization methods to :func:`mne.compute_raw_covariance` by `Eric Larson`_. + +- Add command ``mne show_info`` to quickly show the measurement info from a .fif file from the terminal by `Alex Gramfort`_. + +- Add creating forward operator for dipole object :func:`mne.make_forward_dipole` by `Chris Bailey`_ + +- Add reading and estimation of fixed-position dipole time courses (similar to Elekta ``xfit``) using :func:`mne.read_dipole` and :func:`mne.fit_dipole` by `Eric Larson`_. + +- Accept ``mne.decoding.GeneralizationAcrossTime``'s ``scorer`` parameter to be a string that refers to a scikit-learn_ metric scorer by `Asish Panda`_. + +- Add method :func:`mne.Epochs.plot_image` calling :func:`mne.viz.plot_epochs_image` for better usability by `Asish Panda`_. + +- Add :func:`mne.io.read_raw_cnt` for reading Neuroscan CNT files by `Jaakko Leppakangas`_ + +- Add ``decim`` parameter to ``mne.time_frequency.cwt_morlet``, by `Jean-Rémi King`_ + +- Add method :func:`mne.Epochs.plot_topo_image` by `Jaakko Leppakangas`_ + +- Add the ability to read events when importing raw EEGLAB files, by `Jona Sassenhagen`_. + +- Add function :func:`mne.viz.plot_sensors` and methods :func:`mne.Epochs.plot_sensors`, :func:`mne.io.Raw.plot_sensors` and :func:`mne.Evoked.plot_sensors` for plotting sensor positions and :func:`mne.viz.plot_layout` and :func:`mne.channels.Layout.plot` for plotting layouts by `Jaakko Leppakangas`_ + +- Add epoch rejection based on annotated segments by `Jaakko Leppakangas`_ + +- Add option to use new-style MEG channel names in ``mne.read_selection`` by `Eric Larson`_ + +- Add option for ``proj`` in :class:`mne.EpochsArray` by `Eric Larson`_ + +- Enable the usage of :func:`mne.viz.plot_topomap` with an :class:`mne.Info` instance for location information, by `Jona Sassenhagen`_. + +- Add support for electrocorticography (ECoG) channel type by `Eric Larson`_ + +- Add option for ``first_samp`` in :func:`mne.make_fixed_length_events` by `Jon Houck`_ + +- Add ability to auto-scale channel types for :func:`mne.viz.plot_raw` and :func:`mne.viz.plot_epochs` and corresponding object plotting methods by `Chris Holdgraf`_ + +BUG +~~~ + +- ``mne.time_frequency.compute_raw_psd``, ``mne.time_frequency.compute_epochs_psd``, ``mne.time_frequency.psd_multitaper``, and ``mne.time_frequency.psd_welch`` no longer remove rows/columns of the SSP matrix before applying SSP projectors when picks are provided by `Chris Holdgraf`_. + +- :func:`mne.Epochs.plot_psd` no longer calls a Welch PSD, and instead uses a Multitaper method which is more appropriate for epochs. Flags for this function are passed to ``mne.time_frequency.psd_multitaper`` by `Chris Holdgraf`_ + +- Time-cropping functions (e.g., :func:`mne.Epochs.crop`, :func:`mne.Evoked.crop`, :func:`mne.io.Raw.crop`, :func:`mne.SourceEstimate.crop`) made consistent with behavior of ``tmin`` and ``tmax`` of :class:`mne.Epochs`, where nearest sample is kept. For example, for MGH data acquired with ``sfreq=600.614990234``, constructing ``Epochs(..., tmin=-1, tmax=1)`` has bounds ``+/-1.00064103``, and now ``epochs.crop(-1, 1)`` will also have these bounds (previously they would have been ``+/-0.99897607``). Time cropping functions also no longer use relative tolerances when determining the boundaries. These changes have minor effects on functions that use cropping under the hood, such as :func:`mne.compute_covariance` and ``mne.connectivity.spectral_connectivity``. Changes by `Jaakko Leppakangas`_ and `Eric Larson`_ + +- Fix EEG spherical spline interpolation code to account for average reference by `Mainak Jas`_ + +- MEG projectors are removed after Maxwell filtering by `Eric Larson`_ + +- Fix ``mne.decoding.TimeDecoding`` to allow specifying ``clf`` by `Jean-Rémi King`_ + +- Fix bug with units (uV) in 'Brain Vision Data Exchange Header File Version 1.0' by `Federico Raimondo`_ + +- Fix bug where :func:`mne.preprocessing.maxwell_filter` ``destination`` parameter did not properly set device-to-head transform by `Eric Larson`_ + +- Fix bug in rank calculation of ``mne.utils.estimate_rank``, ``mne.io.Raw.estimate_rank``, and covariance functions where the tolerance was set to slightly too small a value, new 'auto' mode uses values from ``scipy.linalg.orth`` by `Eric Larson`_. + +- Fix bug when specifying irregular ``train_times['slices']`` in ``mne.decoding.GeneralizationAcrossTime``, by `Jean-Rémi King`_ + +- Fix colorbar range on norm data by `Jaakko Leppakangas`_ + +- Fix bug in ``mne.preprocessing.run_ica``, which used the ``ecg_criterion`` parameter for the EOG criterion instead of ``eog_criterion`` by `Christian Brodbeck`_ + +- Fix normals in CTF data reader by `Eric Larson`_ + +- Fix bug in :func:`mne.io.read_raw_ctf`, when omitting samples at the end by `Jaakko Leppakangas`_ + +- Fix ``info['lowpass']`` value for downsampled raw data by `Eric Larson`_ + +- Remove measurement date from :class:`mne.Info` in :func:`mne.io.Raw.anonymize` by `Eric Larson`_ + +- Fix bug that caused synthetic ecg channel creation even if channel was specified for ECG peak detection in :func:`mne.preprocessing.create_ecg_epochs` by `Jaakko Leppakangas`_ + +- Fix bug with vmin and vmax when None is passed in :func:`mne.viz.plot_topo_image_epochs` by `Jaakko Leppakangas`_ + +- Fix bug with :func:`mne.label_sign_flip` (and :func:`mne.extract_label_time_course`) by `Natalie Klein`_ and `Eric Larson`_ + +- Add copy parameter in :func:`mne.Epochs.apply_baseline` and :func:`mne.io.Raw.filter` methods by `Jona Sassenhagen`_ and `Alex Gramfort`_ + +- Fix bug in :func:`mne.merge_events` when using ``replace_events=False`` by `Alex Gramfort`_ + +- Fix bug in :class:`mne.Evoked` type setting in :func:`mne.stats.linear_regression_raw` by `Eric Larson`_ + +- Fix bug in ``mne.io.edf.RawEDF`` highpass filter setting to take max highpass to match warning message by `Teon Brooks`_ + +- Fix bugs with coordinane frame adjustments in ``mne.viz.plot_trans`` by `Eric Larson`_ + +- Fix bug in colormap selection in :func:`mne.Evoked.plot_projs_topomap` by `Jaakko Leppakangas`_ + +- Fix bug in source normal adjustment that occurred when 1) patch information is available (e.g., when distances have been calculated) and 2) points are excluded from the source space (by inner skull distance) by `Eric Larson`_ + +- Fix bug when merging info that has a field with list of dicts by `Jaakko Leppakangas`_ + +- The BTi/4D reader now considers user defined channel labels instead of the hard-ware names, however only for channels other than MEG. By `Denis Engemann`_ and `Alex Gramfort`_. + +- The BTi reader :func:`mne.io.read_raw_bti` can now read 2500 system data, by `Eric Larson`_ + +- Fix bug in :func:`mne.compute_raw_covariance` where rejection by non-data channels (e.g. EOG) was not done properly by `Eric Larson`_. + +- Change default scoring method of ``mne.decoding.GeneralizationAcrossTime`` and ``mne.decoding.TimeDecoding`` to estimate the scores within the cross-validation as in scikit-learn_ as opposed to across all cross-validated ``y_pred``. The method can be changed with the ``score_mode`` parameter by `Jean-Rémi King`_ + +- Fix bug in :func:`mne.io.Raw.save` where, in rare cases, automatically split files could end up writing an extra empty file that wouldn't be read properly by `Eric Larson`_ + +- Fix ``mne.realtime.StimServer`` by removing superfluous argument ``ip`` used while initializing the object by `Mainak Jas`_. + +- Fix removal of projectors in :func:`mne.preprocessing.maxwell_filter` in ``st_only=True`` mode by `Eric Larson`_ + +API +~~~ + +- The default ``picks=None`` in :func:`mne.viz.plot_epochs_image` now only plots the first 5 channels, not all channels, by `Jona Sassenhagen`_ + +- The ``mesh_color`` parameter in :func:`mne.viz.plot_dipole_locations` has been removed (use ``brain_color`` instead), by `Marijn van Vliet`_ + +- Deprecated functions ``mne.time_frequency.compute_raw_psd`` and ``mne.time_frequency.compute_epochs_psd``, replaced by ``mne.time_frequency.psd_welch`` by `Chris Holdgraf`_ + +- Deprecated function ``mne.time_frequency.multitaper_psd`` and replaced by ``mne.time_frequency.psd_multitaper`` by `Chris Holdgraf`_ + +- The ``y_pred`` attribute in ``mne.decoding.GeneralizationAcrossTime`` and ``mne.decoding.TimeDecoding`` is now a numpy array, by `Jean-Rémi King`_ + +- The :func:`mne.bem.fit_sphere_to_headshape` function now default to ``dig_kinds='auto'`` which will use extra digitization points, falling back to extra plus eeg digitization points if there not enough extra points are available. + +- The :func:`mne.bem.fit_sphere_to_headshape` now has a ``units`` argument that should be set explicitly. This will default to ``units='mm'`` in 0.12 for backward compatibility but change to ``units='m'`` in 0.13. + +- Added default parameters in Epochs class namely ``event_id=None``, ``tmin=-0.2`` and ``tmax=0.5``. + +- To unify and extend the behavior of :func:`mne.compute_raw_covariance` relative to :func:`mne.compute_covariance`, the default parameter ``tstep=0.2`` now discards any epochs at the end of the :class:`mne.io.Raw` instance that are not the full ``tstep`` duration. This will slightly change the computation of :func:`mne.compute_raw_covariance`, but should only potentially have a big impact if the :class:`mne.io.Raw` instance is short relative to ``tstep`` and the last, too short (now discarded) epoch contained data inconsistent with the epochs that preceded it. + +- The default ``picks=None`` in :func:`mne.io.Raw.filter` now picks eeg, meg, seeg, and ecog channels, by `Jean-Rémi King`_ and `Eric Larson`_ + +- EOG, ECG and EMG channels are now plotted by default (if present in data) when using :func:`mne.viz.plot_evoked` by `Marijn van Vliet`_ + +- Replace pseudoinverse-based solver with much faster Cholesky solver in :func:`mne.stats.linear_regression_raw`, by `Jona Sassenhagen`_. + +- CTF data reader now reads EEG locations from .pos file as HPI points by `Jaakko Leppakangas`_ + +- Subselecting channels can now emit a warning if many channels have been subselected from projection vectors. We recommend only computing projection vertors for and applying projectors to channels that will be used in the final analysis. However, after picking a subset of channels, projection vectors can be renormalized with :func:`mne.Info.normalize_proj` if necessary to avoid warnings about subselection. Changes by `Eric Larson`_ and `Alex Gramfort`_. + +- Rename and deprecate ``mne.Epochs.drop_bad_epochs`` to :func:`mne.Epochs.drop_bad`, and ``mne.Epochs.drop_epochs`` to :func:`mne.Epochs.drop` by `Alex Gramfort`_. + +- The C wrapper ``mne.do_forward_solution`` has been deprecated in favor of the native Python version :func:`mne.make_forward_solution` by `Eric Larson`_ + +- The ``events`` parameter of :func:`mne.EpochsArray` is set by default to chronological time-samples and event values to 1, by `Jean-Rémi King`_ + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number of commits): + +* 348 Eric Larson +* 347 Jaakko Leppakangas +* 157 Alexandre Gramfort +* 139 Jona Sassenhagen +* 67 Jean-Rémi King +* 32 Chris Holdgraf +* 31 Denis A. Engemann +* 30 Mainak Jas +* 16 Christopher J. Bailey +* 13 Marijn van Vliet +* 10 Mark Wronkiewicz +* 9 Teon Brooks +* 9 kaichogami +* 8 Clément Moutard +* 5 Camilo Lamus +* 5 mmagnuski +* 4 Christian Brodbeck +* 4 Daniel McCloy +* 4 Yousra Bekhti +* 3 Fede Raimondo +* 1 Jussi Nurminen +* 1 MartinBaBer +* 1 Mikolaj Magnuski +* 1 Natalie Klein +* 1 Niklas Wilming +* 1 Richard Höchenberger +* 1 Sagun Pai +* 1 Sourav Singh +* 1 Tom Dupré la Tour +* 1 jona-sassenhagen@ +* 1 kambysese +* 1 pbnsilva +* 1 sviter +* 1 zuxfoucault diff --git a/mne-python/source/doc/changes/v0.13.rst b/mne-python/source/doc/changes/v0.13.rst new file mode 100644 index 0000000000000000000000000000000000000000..50fcde79702cde27d4bcb8c186bd84bc4a643ce0 --- /dev/null +++ b/mne-python/source/doc/changes/v0.13.rst @@ -0,0 +1,248 @@ +.. _changes_0_13: + +Version 0.13 (2016-09-27) +------------------------- + +Changelog +~~~~~~~~~ + +- Add new class :class:`AcqParserFIF` to parse Elekta/Neuromag MEG acquisition info, allowing e.g. collecting epochs according to acquisition-defined averaging categories by `Jussi Nurminen`_ + +- Adds automatic determination of FIR filter parameters ``filter_length``, ``l_trans_bandwidth``, and ``h_trans_bandwidth`` and adds ``phase`` argument in e.g. in :meth:`mne.io.Raw.filter` by `Eric Larson`_ + +- Adds faster ``n_fft='auto'`` option to :meth:`mne.io.Raw.apply_hilbert` by `Eric Larson`_ + +- Adds new function ``mne.time_frequency.csd_array`` to compute the cross-spectral density of multivariate signals stored in an array, by `Nick Foti`_ + +- Add order params 'selection' and 'position' for :func:`mne.viz.plot_raw` to allow plotting of specific brain regions by `Jaakko Leppakangas`_ + +- Added the ability to decimate :class:`mne.Evoked` objects with :func:`mne.Evoked.decimate` by `Eric Larson`_ + +- Add generic array-filtering function :func:`mne.filter.filter_data` by `Eric Larson`_ + +- ``mne.viz.plot_trans`` now also shows head position indicators by `Christian Brodbeck`_ + +- Add label center of mass function :func:`mne.Label.center_of_mass` by `Eric Larson`_ + +- Added :func:`mne.viz.plot_ica_properties` that allows plotting of independent component properties similar to ``pop_prop`` in EEGLAB. Also :class:`mne.preprocessing.ICA` has :func:`mne.preprocessing.ICA.plot_properties` method now. Added by `Mikołaj Magnuski`_ + +- Add second-order sections (instead of ``(b, a)`` form) IIR filtering for reduced numerical error by `Eric Larson`_ + +- Add interactive colormap option to image plotting functions by `Jaakko Leppakangas`_ + +- Add support for the University of Maryland KIT system by `Christian Brodbeck`_ + +- Add support for \*.elp and \*.hsp files to the KIT2FIFF converter and ``mne.channels.read_dig_montage`` by `Teon Brooks`_ and `Christian Brodbeck`_ + +- Add option to preview events in the KIT2FIFF GUI by `Christian Brodbeck`_ + +- Add approximation of size of :class:`io.Raw`, :class:`Epochs`, and :class:`Evoked` in :func:`repr` by `Eric Larson`_ + +- Add possibility to select a subset of sensors by lasso selector to :func:`mne.viz.plot_sensors` and :func:`mne.viz.plot_raw` when using order='selection' or order='position' by `Jaakko Leppakangas`_ + +- Add the option to plot brain surfaces and source spaces to :func:`viz.plot_bem` by `Christian Brodbeck`_ + +- Add the ``--filterchpi`` option to :ref:`mne browse_raw`, by `Felix Raimundo`_ + +- Add the ``--no-decimate`` option to :ref:`mne make_scalp_surfaces` to skip the high-resolution surface decimation step, by `Eric Larson`_ + +- Add new class :class:`mne.decoding.EMS` to transform epochs with the event-matched spatial filters and add 'cv' parameter to :func:`mne.decoding.compute_ems`, by `Jean-Rémi King`_ + +- Added :class:`mne.time_frequency.EpochsTFR` and average parameter in :func:`mne.time_frequency.tfr_morlet` and :func:`mne.time_frequency.tfr_multitaper` to compute time-frequency transforms on single trial epochs without averaging, by `Jean-Rémi King`_ and `Alex Gramfort`_ + +- Added :class:`mne.decoding.TimeFrequency` to transform signals in scikit-learn pipelines, by `Jean-Rémi King`_ + +- Added :class:`mne.decoding.UnsupervisedSpatialFilter` providing interface for scikit-learn decomposition algorithms to be used with MNE data, by `Jean-Rémi King`_ and `Asish Panda`_ + +- Added support for multiclass decoding in :class:`mne.decoding.CSP`, by `Jean-Rémi King`_ and `Alexandre Barachant`_ + +- Components obtained from :class:`mne.preprocessing.ICA` are now sorted by explained variance, by `Mikołaj Magnuski`_ + +- Adding an EEG reference channel using :func:`mne.add_reference_channels` will now use its digitized location from the FIFF file, if present, by `Chris Bailey`_ + +- Added interactivity to :func:`mne.preprocessing.ICA.plot_components` - passing an instance of :class:`io.Raw` or :class:`Epochs` in ``inst`` argument allows to open component properties by clicking on component topomaps, by `Mikołaj Magnuski`_ + +- Adds new function :func:`mne.viz.plot_compare_evokeds` to show multiple evoked time courses at a single location, or the mean over a ROI, or the GFP, automatically averaging and calculating a CI if multiple subjects are given, by `Jona Sassenhagen`_ + +- Added ``transform_into`` parameter into :class:`mne.decoding.CSP` to retrieve the average power of each source or the time course of each source, by `Jean-Rémi King`_ + +- Added support for reading MaxShield (IAS) evoked data (e.g., from the acquisition machine) in :func:`mne.read_evokeds` by `Eric Larson`_ + +- Added support for functional near-infrared spectroscopy (fNIRS) channels by `Jaakko Leppakangas`_ + +- Added :attr:`mne.io.Raw.acqparser` convenience attribute for :class:`mne.AcqParserFIF` by `Eric Larson`_ + +- Added example of Representational Similarity Analysis, by `Jean-Rémi King`_ + +BUG +~~~ + +- Fixed a bug where selecting epochs using hierarchical event IDs (HIDs) was *and*-like instead of *or*-like. When doing e.g. ``epochs[('Auditory', 'Left')]``, previously all trials that contain ``'Auditory'`` *and* ``'Left'`` (like ``'Auditory/Left'``) would be selected, but now any conditions matching ``'Auditory'`` *or* ``'Left'`` will be selected (like ``'Auditory/Left'``, ``'Auditory/Right'``, and ``'Visual/Left'``). This is now consistent with how epoch selection was done without HID tags, e.g. ``epochs[['a', 'b']]`` would select all epochs of type ``'a'`` and type ``'b'``. By `Eric Larson`_ + +- Fixed Infomax/Extended Infomax when the user provides an initial weights matrix by `Jair Montoya Martinez`_ + +- Fixed the default raw FIF writing buffer size to be 1 second instead of 10 seconds by `Eric Larson`_ + +- Fixed channel selection order when MEG channels do not come first in :func:`mne.preprocessing.maxwell_filter` by `Eric Larson`_ + +- Fixed color ranges to correspond to the colorbar when plotting several time instances with :func:`mne.viz.plot_evoked_topomap` by `Jaakko Leppakangas`_ + +- Added units to :func:`mne.io.read_raw_brainvision` for reading non-data channels and enable default behavior of inferring channel type by unit by `Jaakko Leppakangas`_ and `Pablo-Arias`_ + +- Fixed minor bugs with :func:`mne.Epochs.resample` and :func:`mne.Epochs.decimate` by `Eric Larson`_ + +- Fixed a bug where duplicate vertices were not strictly checked by :func:`mne.simulation.simulate_stc` by `Eric Larson`_ + +- Fixed a bug where some FIF files could not be read with :func:`mne.io.show_fiff` by `Christian Brodbeck`_ and `Eric Larson`_ + +- Fixed a bug where ``merge_grads=True`` causes :func:`mne.viz.plot_evoked_topo` to fail when plotting a list of evokeds by `Jaakko Leppakangas`_ + +- Fixed a bug when setting multiple bipolar references with :func:`set_bipolar_reference` by `Marijn van Vliet`_. + +- Fixed image scaling in :func:`mne.viz.plot_epochs_image` when plotting more than one channel by `Jaakko Leppakangas`_ + +- Fixed :class:`mne.preprocessing.Xdawn` to fit shuffled epochs by `Jean-Rémi King`_ + +- Fixed a bug with channel order determination that could lead to an ``AssertionError`` when using :class:`mne.Covariance` matrices by `Eric Larson`_ + +- Fixed the check for CTF gradient compensation in :func:`mne.preprocessing.maxwell_filter` by `Eric Larson`_ + +- Fixed the import of EDF files with encoding characters in :func:`mne.io.read_raw_edf` by `Guillaume Dumas`_ + +- Fixed :class:`mne.Epochs` to ensure that detrend parameter is not a boolean by `Jean-Rémi King`_ + +- Fixed bug with ``mne.realtime.FieldTripClient.get_data_as_epoch`` when ``picks=None`` which crashed the function by `Mainak Jas`_ + +- Fixed reading of units in ``.elc`` montage files (from ``UnitsPosition`` field) so that ``mne.channels.Montage`` objects are now returned with the ``pos`` attribute correctly in meters, by `Chris Mullins`_ + +- Fixed reading of BrainVision files by `Phillip Alday`_: + +- Greater support for BVA files, especially older ones: alternate text coding schemes with fallback to Latin-1 as well as units in column headers + +- Use online software filter information when present + +- Fix comparisons of filter settings for determining "strictest"/"weakest" filter + +- Weakest filter is now used for heterogeneous channel filter settings, leading to more consistent behavior with filtering methods applied to a subset of channels (e.g. ``Raw.filter`` with ``picks != None``). + +- Fixed plotting and timing of :class:`Annotations` and restricted addition of annotations outside data range to prevent problems with cropping and concatenating data by `Jaakko Leppakangas`_ + +- Fixed ICA plotting functions to refer to IC index instead of component number by `Andreas Hojlund`_ and `Jaakko Leppakangas`_ + +- Fixed bug with ``picks`` when interpolating MEG channels by `Mainak Jas`_. + +- Fixed bug in padding of Stockwell transform for signal of length a power of 2 by `Johannes Niediek`_ + +API +~~~ + +- The ``add_eeg_ref`` argument in core functions like :func:`mne.io.read_raw_fif` and :class:`mne.Epochs` has been deprecated in favor of using :func:`mne.set_eeg_reference` and equivalent instance methods like :meth:`raw.set_eeg_reference() `. In functions like :func:`mne.io.read_raw_fif` where the default in 0.13 and older versions is ``add_eeg_ref=True``, the default will change to ``add_eeg_ref=False`` in 0.14, and the argument will be removed in 0.15. + +- Multiple aspects of FIR filtering in MNE-Python has been refactored: + + 1. New recommended defaults for ``l_trans_bandwidth='auto'``, ``h_trans_bandwidth='auto'``, and ``filter_length='auto'``. This should generally reduce filter artifacts at the expense of slight decrease in effective filter stop-band attenuation. For details see :ref:`tut-filtering-in-python`. The default values of ``l_trans_bandwidth=h_trans_bandwidth=0.5`` and ``filter_length='10s'`` will change to ``'auto'`` in 0.14. + + 2. The ``filter_length=None`` option (i.e. use ``len(x)``) has been deprecated. + + 3. An improved ``phase='zero'`` zero-phase FIR filtering has been added. Instead of running the designed filter forward and backward, the filter is applied once and we compensate for the linear phase of the filter. The previous ``phase='zero-double'`` default will change to ``phase='zero'`` in 0.14. + + 4. A warning is provided when the filter is longer than the signal of interest, as this is unlikely to produce desired results. + + 5. Previously, if the filter was as long or longer than the signal of interest, direct FFT-based computations were used. Now a single code path (overlap-add filtering) is used for all FIR filters. This could cause minor changes in how short signals are filtered. + +- Support for Python 2.6 has been dropped, and the minimum supported dependencies are NumPy_ 1.8, SciPy_ 0.12, and Matplotlib_ 1.3 by `Eric Larson`_ + +- When CTF gradient compensation is applied to raw data, it is no longer reverted on save of :meth:`mne.io.Raw.save` by `Eric Larson`_ + +- Adds ``mne.time_frequency.csd_epochs`` to replace ``mne.time_frequency.csd_compute_epochs`` for naming consistency. ``mne.time_frequency.csd_compute_epochs`` is now deprecated and will be removed in mne 0.14, by `Nick Foti`_ + +- Weighted addition and subtraction of :class:`Evoked` as ``ev1 + ev2`` and ``ev1 - ev2`` have been deprecated, use explicit :func:`mne.combine_evoked(..., weights='nave') ` instead by `Eric Larson`_ + +- Deprecated support for passing a list of filenames to :class:`mne.io.Raw` constructor, use :func:`mne.io.read_raw_fif` and :func:`mne.concatenate_raws` instead by `Eric Larson`_ + +- Added options for setting data and date formats manually in :func:`mne.io.read_raw_cnt` by `Jaakko Leppakangas`_ + +- Now channels with units of 'C', 'µS', 'uS', 'ARU' and 'S' will be turned to misc by default in :func:`mne.io.read_raw_brainvision` by `Jaakko Leppakangas`_ + +- Add :func:`mne.io.anonymize_info` function to anonymize measurements and add methods to :class:`mne.io.Raw`, :class:`mne.Epochs` and :class:`mne.Evoked`, by `Jean-Rémi King`_ + +- Now it is possible to plot only a subselection of channels in :func:`mne.viz.plot_raw` by using an array for order parameter by `Jaakko Leppakangas`_ + +- EOG channels can now be included when calling :func:`mne.preprocessing.ICA.fit` and a proper error is raised when trying to include unsupported channels by `Alexander Rudiuk`_ + +- :func:`mne.concatenate_epochs` and :func:`mne.compute_covariance` now check to see if all :class:`Epochs` instances have the same MEG-to-Head transformation, and errors by default if they do not by `Eric Larson`_ + +- Added option to pass a list of axes to :func:`mne.viz.plot_epochs_image` by `Mikołaj Magnuski`_ + +- Constructing IIR filters in :func:`mne.filter.construct_iir_filter` defaults to ``output='ba'`` in 0.13 but this will be changed to ``output='sos'`` by `Eric Larson`_ + +- Add ``zorder`` parameter to :func:`mne.Evoked.plot` and derived functions to sort allow sorting channels by e.g. standard deviation, by `Jona Sassenhagen`_ + +- The ``baseline`` parameter of :func:`mne.Epochs.apply_baseline` is set by default (None, 0), by `Felix Raimundo`_ + +- Adds :func:`mne.Evoked.apply_baseline` to be consistent with :func:`mne.Epochs.apply_baseline`, by `Felix Raimundo`_ + +- Deprecated the ``baseline`` parameter in :class:`mne.Evoked`, by `Felix Raimundo`_ + +- The API of :meth:`mne.SourceEstimate.plot` and :func:`mne.viz.plot_source_estimates` has been updated to reflect current PySurfer 0.6 API. The ``config_opts`` parameter is now deprecated and will be removed in mne 0.14, and the default representation for time will change from ``ms`` to ``s`` in mne 0.14. By `Christian Brodbeck`_ + +- The default dataset location has been changed from ``examples/`` in the MNE-Python root directory to ``~/mne_data`` in the user's home directory, by `Eric Larson`_ + +- A new option ``set_env`` has been added to :func:`mne.set_config` that defaults to ``False`` in 0.13 but will change to ``True`` in 0.14, by `Eric Larson`_ + +- The ``compensation`` parameter in :func:`mne.io.read_raw_fif` has been deprecated in favor of the method :meth:`mne.io.Raw.apply_gradient_compensation` by `Eric Larson`_ + +- ``mne.decoding.EpochsVectorizer`` has been deprecated in favor of :class:`mne.decoding.Vectorizer` by `Asish Panda`_ + +- The ``epochs_data`` parameter has been deprecated in :class:`mne.decoding.CSP`, in favour of the ``X`` parameter to comply to scikit-learn API, by `Jean-Rémi King`_ + +- Deprecated ``mne.time_frequency.cwt_morlet`` and ``mne.time_frequency.single_trial_power`` in favour of :func:`mne.time_frequency.tfr_morlet` with parameter average=False, by `Jean-Rémi King`_ and `Alex Gramfort`_ + +- Add argument ``mask_type`` to :func:`mne.read_events` and :func:`mne.find_events` to support MNE-C style of trigger masking by `Teon Brooks`_ and `Eric Larson`_ + +- Extended Infomax is now the new default in :func:`mne.preprocessing.infomax` (``extended=True``), by `Clemens Brunner`_ + +- :func:`mne.io.read_raw_eeglab` and :func:`mne.read_epochs_eeglab` now take additional argument ``uint16_codec`` that allows to define the encoding of character arrays in set file. This helps in rare cases when reading a set file fails with ``TypeError: buffer is too small for requested array``. By `Mikołaj Magnuski`_ + +- Added :class:`mne.decoding.TemporalFilter` to filter data in scikit-learn pipelines, by `Asish Panda`_ + +- :func:`mne.preprocessing.create_ecg_epochs` now includes all the channels when ``picks=None`` by `Jaakko Leppakangas`_ + +- :func:`mne.set_eeg_reference` now allows moving from a custom to an average EEG reference by `Marijn van Vliet`_ + +Authors +~~~~~~~ + +The committer list for this release is the following (sorted by alphabetical order): + +* Alexander Rudiuk +* Alexandre Barachant +* Alexandre Gramfort +* Asish Panda +* Camilo Lamus +* Chris Holdgraf +* Christian Brodbeck +* Christopher J. Bailey +* Christopher Mullins +* Clemens Brunner +* Denis A. Engemann +* Eric Larson +* Federico Raimondo +* Félix Raimundo +* Guillaume Dumas +* Jaakko Leppakangas +* Jair Montoya +* Jean-Rémi King +* Johannes Niediek +* Jona Sassenhagen +* Jussi Nurminen +* Keith Doelling +* Mainak Jas +* Marijn van Vliet +* Michael Krause +* Mikolaj Magnuski +* Nick Foti +* Phillip Alday +* Simon-Shlomo Poil +* Teon Brooks +* Yaroslav Halchenko diff --git a/mne-python/source/doc/changes/v0.14.rst b/mne-python/source/doc/changes/v0.14.rst new file mode 100644 index 0000000000000000000000000000000000000000..bfb9498a0c1d6e424193769ba21652b14bf4d5c2 --- /dev/null +++ b/mne-python/source/doc/changes/v0.14.rst @@ -0,0 +1,250 @@ +.. _changes_0_14: + +Version 0.14 (2017-03-24) +------------------------- + +Changelog +~~~~~~~~~ + +- Add example of time-frequency decoding with CSP by `Laura Gwilliams`_ + +- Automatically create a legend in :func:`mne.viz.plot_evoked_topo` by `Jussi Nurminen`_ + +- Add I/O support for Artemis123 infant/toddler MEG data by `Luke Bloy`_ + +- Add filter plotting functions :func:`mne.viz.plot_filter` and :func:`mne.viz.plot_ideal_filter` as well as filter creation function :func:`mne.filter.create_filter` by `Eric Larson`_ + +- Add HCP-MMP1.0 parcellation dataset downloader by `Eric Larson`_ + +- Add option to project EEG electrodes onto the scalp in ``mne.viz.plot_trans`` by `Eric Larson`_ + +- Add option to plot individual sensors in :meth:`mne.io.Raw.plot_psd` by `Alex Gramfort`_ and `Eric Larson`_ + +- Add option to plot ECoG electrodes in ``mne.viz.plot_trans`` by `Eric Larson`_ + +- Add convenient default values to :meth:`mne.io.Raw.apply_hilbert` and :meth:`mne.io.Raw.apply_function` by `Denis Engemann`_ + +- Remove MNE-C requirement for :ref:`mne make_scalp_surfaces` by `Eric Larson`_ + +- Add support for FastTrack Polhemus ``.mat`` file outputs in ``hsp`` argument of ``mne.channels.read_dig_montage`` by `Eric Larson`_ + +- Add option to convert 3d electrode plots to a snapshot with 2d electrode positions with :func:`mne.viz.snapshot_brain_montage` by `Chris Holdgraf`_ + +- Add skull surface plotting option to ``mne.viz.plot_trans`` by `Jaakko Leppakangas`_ + +- Add minimum-phase filtering option in :meth:`mne.io.Raw.filter` by `Eric Larson`_ + +- Add support for reading ASCII BrainVision files in :func:`mne.io.read_raw_brainvision` by `Eric Larson`_ + +- Add method of ICA objects for retrieving the component maps :meth:`mne.preprocessing.ICA.get_components` by `Jona Sassenhagen`_ + +- Add option to plot events in :func:`mne.viz.plot_epochs` by `Jaakko Leppakangas`_ + +- Add dipole definitions for older phantom at Otaniemi in :func:`mne.dipole.get_phantom_dipoles` by `Eric Larson`_ + +- Add spatial colors option for :func:`mne.viz.plot_raw_psd` by `Jaakko Leppakangas`_ + +- Add functions like :func:`get_volume_labels_from_src` to handle mixed source spaces by `Annalisa Pascarella`_ + +- Add convenience function for opening MNE documentation :func:`open_docs` by `Eric Larson`_ + +- Add option in :meth:`mne.io.Raw.plot` to display the time axis relative to ``raw.first_samp`` by `Mainak Jas`_ + +- Add new :mod:`mne.datasets.visual_92_categories ` dataset by `Jaakko Leppakangas`_ + +- Add option in :func:`mne.io.read_raw_edf` to allow channel exclusion by `Jaakko Leppakangas`_ + +- Allow integer event codes in :func:`mne.read_epochs_eeglab` by `Jaakko Leppakangas`_ + +- Add ability to match channel names in a case insensitive manner when applying a ``mne.channels.Montage`` by `Marijn van Vliet`_ + +- Add ``yscale`` keyword argument to :meth:`mne.time_frequency.AverageTFR.plot` that allows specifying whether to present the frequency axis in linear (``'linear'``) or log (``'log'``) scale. The default value is ``'auto'`` which detects whether frequencies are log-spaced and sets yscale to log. Added by `Mikołaj Magnuski`_ + +- Add :ref:`Representational Similarity Analysis (RSA) ` example on :mod:`mne.datasets.visual_92_categories.data_path` dataset by `Jaakko Leppakangas`_, `Jean-Rémi King`_ and `Alex Gramfort`_ + +- Add support for NeuroScan files with event type 3 in :func:`mne.io.read_raw_cnt` by `Marijn van Vliet`_ + +- Add interactive annotation mode to :meth:`mne.io.Raw.plot` (accessed by pressing 'a') by `Jaakko Leppakangas`_ + +- Add support for deleting all projectors or a list of indices in :meth:`mne.io.Raw.del_proj` by `Eric Larson`_ + +- Add source space plotting with :meth:`mne.SourceSpaces.plot` using ``mne.viz.plot_trans`` by `Eric Larson`_ + +- Add :func:`mne.decoding.get_coef` to retrieve and inverse the coefficients of a linear model - typically a spatial filter or pattern, by `Jean-Rémi King`_ + +- Add support for reading in EGI MFF digitization coordinate files in ``mne.channels.read_dig_montage`` by `Matt Boggess`_ + +- Add ``n_per_seg`` keyword argument to ``mne.time_frequency.psd_welch`` and :func:`mne.time_frequency.psd_array_welch` that allows to control segment length independently of ``n_fft`` and use zero-padding when ``n_fft > n_per_seg`` by `Mikołaj Magnuski`_ + +- Add annotation aware data getter :meth:`mne.io.Raw.get_data` by `Jaakko Leppakangas`_ + +- Add support of dipole location visualization with MRI slice overlay with matplotlib to :func:`mne.viz.plot_dipole_locations` via mode='orthoview' parameter by `Jaakko Leppakangas`_ and `Alex Gramfort`_ + +- Add plotting of head positions as a function of time in :func:`mne.viz.plot_head_positions` by `Eric Larson`_ + +- Add ``real_filter`` option to ``mne.beamformer.dics``, ``mne.beamformer.dics_source_power``, ``mne.beamformer.tf_dics`` and ``mne.beamformer.dics_epochs`` by `Eric Larson`_, `Alex Gramfort`_ and `Andrea Brovelli`_. + +- Add a demo script showing how to use a custom inverse solver with MNE by `Alex Gramfort`_ + +- Functions :func:`mne.preprocessing.create_ecg_epochs`, :func:`mne.preprocessing.create_eog_epochs`, :func:`mne.compute_raw_covariance` and ICA methods :meth:`mne.preprocessing.ICA.score_sources`, :meth:`mne.preprocessing.ICA.find_bads_ecg`, :meth:`mne.preprocessing.ICA.find_bads_eog` are now annotation aware by `Jaakko Leppakangas`_ + +- Allow using ``spatial_colors`` for non-standard layouts by creating custom layouts from channel locations and add ``to_sphere`` keyword to :func:`mne.viz.plot_sensors` to allow plotting sensors that are not on the head surface by `Jaakko Leppakangas`_ + +- Concatenating raws with :func:`mne.concatenate_raws` now creates boundary annotations automatically by `Jaakko Leppakangas`_ + +- :func:`mne.viz.plot_projs_topomap` now supports plotting EEG topomaps by passing in :class:`mne.Info` by `Eric Larson`_ + +BUG +~~~ + +- Fix bug with DICS and LCMV (e.g., ``mne.beamformer.lcmv``, ``mne.beamformer.dics``) where regularization was done improperly. The default ``reg=0.01`` has been changed to ``reg=0.05``, by `Andrea Brovelli`_, `Alex Gramfort`_, and `Eric Larson`_ + +- Fix callback function call in ``mne.viz.topo._plot_topo_onpick`` by `Erkka Heinila`_ + +- Fix reading multi-file CTF recordings in :func:`mne.io.read_raw_ctf` by `Niklas Wilming`_ + +- Fix computation of AR coefficients across channels in :func:`mne.time_frequency.fit_iir_model_raw` by `Eric Larson`_ + +- Fix maxfilter channel names extra space bug in :func:`mne.preprocessing.maxwell_filter` by `Sheraz Khan`_ + +- :func:`mne.channels.find_layout` now leaves out the excluded channels by `Jaakko Leppakangas`_ + +- Array data constructors :class:`mne.io.RawArray` and :class:`EvokedArray` now make a copy of the info structure by `Jaakko Leppakangas`_ + +- Fix bug with finding layouts in :func:`mne.viz.plot_projs_topomap` by `Eric Larson`_ + +- Fix bug :func:`mne.io.anonymize_info` when Info does not contain 'file_id' or 'meas_id' fields by `Jean-Rémi King`_ + +- Fix colormap selection in :func:`mne.viz.plot_evoked_topomap` when using positive vmin with negative data by `Jaakko Leppakangas`_ + +- Fix channel name comparison in ``mne.channels.read_montage`` so that if ``ch_names`` is provided, the returned montage will have channel names in the same letter case by `Jaakko Leppakangas`_ + +- Fix :meth:`inst.set_montage(montage) ` to only set ``inst.info['dev_head_t']`` if ``dev_head_t=True`` in ``mne.channels.read_dig_montage`` by `Eric Larson`_ + +- Fix handling of events in ``mne.realtime.RtEpochs`` when the triggers were split between two buffers resulting in missing and/or duplicate epochs by `Mainak Jas`_ and `Antti Rantala`_ + +- Fix bug with automatic decimation in :func:`mne.io.read_raw_kit` by `Keith Doelling`_ + +- Fix bug with :func:`setup_volume_source_space` where arguments ``subject`` and ``subjects_dir`` were ignored by `Jaakko Leppakangas`_ + +- Fix sanity check for incompatible ``threshold`` and ``tail`` values in clustering functions like :func:`mne.stats.spatio_temporal_cluster_1samp_test` by `Eric Larson`_ + +- Fix ``_bad_dropped`` not being set when loading eeglab epoched files via :func:`mne.read_epochs_eeglab` which resulted in :func:`len` not working by `Mikołaj Magnuski`_ + +- Fix a bug in :meth:`mne.time_frequency.AverageTFR.plot` when plotting without a colorbar by `Jaakko Leppakangas`_ + +- Fix ``_filenames`` attribute in creation of :class:`mne.io.RawArray` with :meth:`mne.preprocessing.ICA.get_sources` by `Paul Pasler`_ + +- Fix contour levels in :func:`mne.viz.plot_evoked_topomap` to be uniform across topomaps by `Jaakko Leppakangas`_ + +- Fix bug in :func:`mne.preprocessing.maxwell_filter` where fine calibration indices were mismatched leading to an ``AssertionError`` by `Eric Larson`_ + +- Fix bug in :func:`mne.preprocessing.fix_stim_artifact` where non-data channels were interpolated by `Eric Larson`_ + +- :class:`mne.decoding.Scaler` now scales each channel independently using data from all time points (epochs and times) instead of scaling all channels for each time point. It also now accepts parameter ``scalings`` to determine the data scaling method (default is ``None`` to use static channel-type-based scaling), by `Asish Panda`_, `Jean-Rémi King`_, and `Eric Larson`_ + +- Raise error if the cv parameter of ``mne.decoding.GeneralizationAcrossTime`` and ``mne.decoding.TimeDecoding`` is not a partition and the predict_mode is "cross-validation" by `Jean-Rémi King`_ + +- Fix bug in :func:`mne.io.read_raw_edf` when ``preload=False`` and channels have different sampling rates by `Jaakko Leppakangas`_ + +- Fix :func:`mne.read_labels_from_annot` to set ``label.values[:]=1`` rather than 0 for consistency with the :class:`Label` class by `Jon Houck`_ + +- Fix plotting non-uniform freqs (for example log-spaced) in :meth:`mne.time_frequency.AverageTFR.plot` by `Mikołaj Magnuski`_ + +- Fix :func:`mne.minimum_norm.compute_source_psd` when used with ``pick_ori=None`` by `Annalisa Pascarella`_ and `Alex Gramfort`_ + +- Fix bug in :class:`mne.Annotations` where concatenating two raws where ``orig_time`` of the second run is ``None`` by `Jaakko Leppakangas`_ + +- Fix reading channel location from eeglab ``.set`` files when some of the channels do not provide this information. Previously all channel locations were ignored in such case, now they are read - unless a montage is provided by the user in which case only channel names are read from set file. By `Mikołaj Magnuski`_ + +- Fix reading eeglab ``.set`` files when ``.chanlocs`` structure does not contain ``X``, ``Y`` or ``Z`` fields by `Mikołaj Magnuski`_ + +- Fix bug with :func:`mne.simulation.simulate_raw` when ``interp != 'zero'`` by `Eric Larson`_ + +- Fix :func:`mne.fit_dipole` to handle sphere model rank deficiency properly by `Alex Gramfort`_ + +- Raise error in :func:`mne.concatenate_epochs` when concatenated epochs have conflicting event_id by `Mikołaj Magnuski`_ + +- Fix handling of ``n_components=None`` in :class:`mne.preprocessing.ICA` by `Richard Höchenberger`_ + +- Fix reading of fiducials correctly from CTF data in :func:`mne.io.read_raw_ctf` by `Jaakko Leppakangas`_ + +- Fix :func:`mne.beamformer.rap_music` to return dipoles with amplitudes in Am instead of nAm by `Jaakko Leppakangas`_ + +- Fix computation of duality gap in ``mne.inverse_sparse.mxne_optim.dgap_l21`` by `Mathurin Massias`_ + +API +~~~ + +- The filtering functions ``band_pass_filter``, ``band_stop_filter``, ``low_pass_filter``, and ``high_pass_filter`` have been deprecated in favor of :func:`mne.filter.filter_data` by `Eric Larson`_ + +- :class:`EvokedArray` now has default value ``tmin=0.`` by `Jaakko Leppakangas`_ + +- The ``ch_type`` argument for ``mne.viz.plot_trans`` has been deprecated, use ``eeg_sensors`` and ``meg_sensors`` instead, by `Eric Larson`_ + +- The default ``tmax=60.`` in :meth:`mne.io.Raw.plot_psd` will change to ``tmax=np.inf`` in 0.15, by `Eric Larson`_ + +- Base classes :class:`mne.io.BaseRaw` and :class:`mne.BaseEpochs` are now public to allow easier typechecking, by `Daniel McCloy`_ + +- :func:`mne.io.read_raw_edf` now combines triggers from multiple tal channels to 'STI 014' by `Jaakko Leppakangas`_ + +- The measurement info :class:`Info` no longer contains a potentially misleading ``info['filename']`` entry. Use class properties like :attr:`mne.io.Raw.filenames` or :attr:`mne.Epochs.filename` instead by `Eric Larson`_ + +- Default fiducial name change from 'nz' to 'nasion' in ``mne.channels.read_montage``, so that it is the same for both ``mne.channels.Montage`` and :class: `mne.channels.DigMontage` by `Leonardo Barbosa`_ + +- MNE's additional files for the ``fsaverage`` head/brain model are now included in MNE-Python, and the now superfluous ``mne_root`` parameter to :func:`create_default_subject` has been deprecated by `Christian Brodbeck`_ + +- An ``overwrite=False`` default parameter has been added to :func:`write_source_spaces` to protect against accidental overwrites, by `Eric Larson`_ + +- The :class:`mne.decoding.LinearModel` class will no longer support ``plot_filters`` and ``plot_patterns``, use :class:`mne.EvokedArray` with :func:`mne.decoding.get_coef` instead, by `Jean-Rémi King`_ + +- Made functions :func:`mne.time_frequency.tfr_array_multitaper`, :func:`mne.time_frequency.tfr_array_morlet`, :func:`mne.time_frequency.tfr_array_stockwell`, :func:`mne.time_frequency.psd_array_multitaper` and :func:`mne.time_frequency.psd_array_welch` public to allow computing TFRs and PSDs on numpy arrays by `Jaakko Leppakangas`_ + +- :meth:`mne.preprocessing.ICA.fit` now rejects data annotated bad by default. Turn off with ``reject_by_annotation=False``, by `Jaakko Leppakangas`_ + +- :func:`mne.io.read_raw_egi` now names channels with pattern 'E'. This behavior can be changed with parameter ``channel_naming`` by `Jaakko Leppakangas`_ + +- the ``name`` parameter in :class:`mne.Epochs` is deprecated, by `Jaakko Leppakangas`_ + +Authors +~~~~~~~ + +People who contributed to this release (in alphabetical order): + +* Alexander Rudiuk +* Alexandre Gramfort +* Annalisa Pascarella +* Antti Rantala +* Asish Panda +* Burkhard Maess +* Chris Holdgraf +* Christian Brodbeck +* Cristóbal Moënne-Loccoz +* Daniel McCloy +* Denis A. Engemann +* Eric Larson +* Erkka Heinila +* Hermann Sonntag +* Jaakko Leppakangas +* Jakub Kaczmarzyk +* Jean-Rémi King +* Jon Houck +* Jona Sassenhagen +* Jussi Nurminen +* Keith Doelling +* Leonardo S. Barbosa +* Lorenz Esch +* Lorenzo Alfine +* Luke Bloy +* Mainak Jas +* Marijn van Vliet +* Matt Boggess +* Matteo Visconti +* Mikolaj Magnuski +* Niklas Wilming +* Paul Pasler +* Richard Höchenberger +* Sheraz Khan +* Stefan Repplinger +* Teon Brooks +* Yaroslav Halchenko diff --git a/mne-python/source/doc/changes/v0.15.rst b/mne-python/source/doc/changes/v0.15.rst new file mode 100644 index 0000000000000000000000000000000000000000..94470ba531634d8693f4971e8119b86be4b6c3ba --- /dev/null +++ b/mne-python/source/doc/changes/v0.15.rst @@ -0,0 +1,329 @@ +.. _changes_0_15: + +Version 0.15 (2017-10-20) +------------------------- + +Changelog +~~~~~~~~~ + +- :meth:`mne.channels.Layout.plot` and :func:`mne.viz.plot_layout` now allows plotting a subset of channels with ``picks`` argument by `Jaakko Leppakangas`_ + +- Add .bvef extension (BrainVision Electrodes File) to ``mne.channels.read_montage`` by `Jean-Baptiste Schiratti`_ + +- Add :func:`mne.decoding.cross_val_multiscore` to allow scoring of multiple tasks, typically used with :class:`mne.decoding.SlidingEstimator`, by `Jean-Rémi King`_ + +- Add :class:`mne.decoding.ReceptiveField` module for modeling electrode response to input features by `Chris Holdgraf`_ + +- Add :class:`mne.decoding.TimeDelayingRidge` class, used by default by :class:`mne.decoding.ReceptiveField`, to speed up auto- and cross-correlation computations and enable Laplacian regularization by `Ross Maddox`_ and `Eric Larson`_ + +- Add new :mod:`mne.datasets.mtrf ` dataset by `Chris Holdgraf`_ + +- Add example of time-frequency decoding with CSP by `Laura Gwilliams`_ + +- Add :class:`mne.decoding.SPoC` to fit and apply spatial filters based on continuous target variables, by `Jean-Rémi King`_ and `Alexandre Barachant`_ + +- Add Fieldtrip's electromyogram dataset, by `Alexandre Barachant`_ + +- Add ``reject_by_annotation`` option to :func:`mne.preprocessing.find_eog_events` (which is also utilised by :func:`mne.preprocessing.create_eog_epochs`) to omit data that is annotated as bad by `Jaakko Leppakangas`_ + +- Add example for fast screening of event-related dynamics in frequency bands by `Denis Engemann`_ + +- Add :meth:`mne.time_frequency.EpochsTFR.save` by `Jaakko Leppakangas`_ + +- Add butterfly mode (toggled with 'b' key) to :meth:`mne.io.Raw.plot` by `Jaakko Leppakangas`_ + +- Add ``axes`` parameter to plot_topo functions by `Jaakko Leppakangas`_ + +- Add options to change time windowing in :func:`mne.chpi.filter_chpi` by `Eric Larson`_ + +- ``mne.channels.Montage.plot``, :meth:`mne.channels.DigMontage.plot`, and :func:`mne.viz.plot_montage` now allow plotting channel locations as a topomap by `Clemens Brunner`_ + +- Add ``background_color`` parameter to :meth:`mne.Evoked.plot_topo` and :func:`mne.viz.plot_evoked_topo` and improve axes rendering as done in :func:`mne.viz.plot_compare_evokeds` by `Alex Gramfort`_ + +- Add support for GDF files in :func:`mne.io.read_raw_edf` by `Nicolas Barascud`_ + +- Add ``mne.io.find_edf_events`` for getting the events as they are in the EDF/GDF header by `Jaakko Leppakangas`_ + +- Speed up :meth:`mne.io.Raw.plot` and :meth:`mne.Epochs.plot` using (automatic) decimation based on low-passing with ``decim='auto'`` parameter by `Eric Larson`_ and `Jaakko Leppakangas`_ + +- Add ``mne.inverse_sparse.mxne_optim.dgap_l21l1`` for computing the duality gap for TF-MxNE as the new stopping criterion by `Daniel Strohmeier`_ + +- Add option to return a list of :class:`Dipole` objects in sparse source imaging methods by `Daniel Strohmeier`_ + +- Add :func:`mne.inverse_sparse.make_stc_from_dipoles` to generate stc objects from lists of dipoles by `Daniel Strohmeier`_ + +- Add ``mne.channels.find_ch_connectivity`` that tries to infer the correct connectivity template using channel info. If no template is found, it computes the connectivity matrix using :class:`Delaunay ` triangulation of the 2d projected channel positions by `Jaakko Leppakangas`_ + +- Add IO support for EGI MFF format by `Jaakko Leppakangas`_ and `ramonapariciog`_ + +- Add option to use matplotlib backend when plotting with :func:`mne.viz.plot_source_estimates` by `Jaakko Leppakangas`_ + +- Add ``mne.channels.Montage.get_pos2d`` to get the 2D positions of channels in a montage by `Clemens Brunner`_ + +- Add MGH 60- and 70-channel standard montages to ``mne.channels.read_montage`` by `Eric Larson`_ + +- Add option for embedding SVG instead of PNG in HTML for :class:`mne.Report` by `Eric Larson`_ + +- Add confidence intervals, number of free parameters, and χ² to :func:`mne.fit_dipole` and :func:`mne.read_dipole` by `Eric Larson`_ + +- :attr:`mne.SourceEstimate.data` is now writable, writing to it will also update :attr:`mne.SourceEstimate.times` by `Marijn van Vliet`_ + +- :meth:`mne.io.Raw.plot` and :meth:`mne.Epochs.plot` now use anti-aliasing to draw signals by `Clemens Brunner`_ + +- Allow using saved ``DigMontage`` to import digitization to :func:`mne.gui.coregistration` by `Jaakko Leppakangas`_ + +- Add function :func:`mne.channels.get_builtin_montages` to list all built-in montages by `Clemens Brunner`_ + +- :class:`mne.decoding.SlidingEstimator` and :class:`mne.decoding.GeneralizingEstimator` now accept ``**fit_params`` at fitting by `Jean-Rémi King`_ + +- Add :class:`mne.VectorSourceEstimate` class which enables working with both source power and dipole orientations by `Marijn van Vliet`_ + +- Add option ``pick_ori='vector'`` to :func:`mne.minimum_norm.apply_inverse` to produce :class:`mne.VectorSourceEstimate` by `Marijn van Vliet`_ + +- Add support for :class:`numpy.random.RandomState` argument to ``seed`` in :mod:`statistical clustering functions ` and better documentation of exact 1-sample tests by `Eric Larson`_ + +- Extend :func:`mne.viz.plot_epochs_image`/:meth:`mne.Epochs.plot_image` with regards to grouping by or aggregating over channels. See the new example at ``examples/visualization/plot_roi_erpimage_by_rt.py`` by `Jona Sassenhagen`_ + +- Add bootstrapped confidence intervals to :func:`mne.viz.plot_compare_evokeds` by `Jona Sassenhagen`_ and `Denis Engemann`_ + +- Add example on how to plot ERDS maps (also known as ERSP) by `Clemens Brunner`_ + +- Add support for volume source spaces to ``spatial_src_connectivity`` and ``spatio_temporal_src_connectivity`` by `Alex Gramfort`_ + +- Plotting raw data (:func:`mne.viz.plot_raw` or :meth:`mne.io.Raw.plot`) with events now includes event numbers (if there are not more than 50 events on a page) by `Clemens Brunner`_ + +- Add filtering functions :meth:`mne.Epochs.filter` and :meth:`mne.Evoked.filter`, as well as ``pad`` argument to :meth:`mne.io.Raw.filter` by `Eric Larson`_ + +- Add high frequency somatosensory MEG dataset by `Jussi Nurminen`_ + +- Add reduced set of labels for HCPMMP-1.0 parcellation in :func:`mne.datasets.fetch_hcp_mmp_parcellation` by `Eric Larson`_ + +- Enable morphing between hemispheres with ``mne.compute_morph_matrix`` by `Christian Brodbeck`_ + +- Add ``return_residual`` to :func:`mne.minimum_norm.apply_inverse` by `Eric Larson`_ + +- Add ``return_drop_log`` to :func:`mne.preprocessing.compute_proj_eog` and :func:`mne.preprocessing.compute_proj_ecg` by `Eric Larson`_ + +- Add time cursor and category/amplitude status message into the single-channel evoked plot by `Jussi Nurminen`_ + +BUG +~~~ +- Fixed a bug when creating spherical volumetric grid source spaces in :func:`setup_volume_source_space` by improving the minimum-distance computations, which in general will decrease the number of used source space points by `Eric Larson`_ + +- Fix bug in :meth:`mne.io.read_raw_brainvision` read .vhdr files with ANSI codepage by `Okba Bekhelifi`_ and `Alex Gramfort`_ + +- Fix unit scaling when reading in EGI digitization files using ``mne.channels.read_dig_montage`` by `Matt Boggess`_ + +- Fix ``picks`` default in :meth:`mne.io.Raw.filter` to include ``ref_meg`` channels by default by `Eric Larson`_ + +- Fix :class:`mne.decoding.CSP` order of spatial filter in ``patterns_`` by `Alexandre Barachant`_ + +- :meth:`mne.concatenate_epochs` now maintains the relative position of events during concatenation by `Alexandre Barachant`_ + +- Fix bug in script ``mne make_scalp_surfaces`` by `Denis Engemann`_ (this bug prevented creation of high-resolution meshes when they were absent in the first place.) + +- Fix writing of raw files with empty set of annotations by `Jaakko Leppakangas`_ + +- Fix bug in :meth:`mne.preprocessing.ICA.plot_properties` where merging gradiometers would fail by `Jaakko Leppakangas`_ + +- Fix :func:`mne.viz.plot_sensors` to maintain proper aspect ratio by `Eric Larson`_ + +- Fix :func:`mne.viz.plot_topomap` to allow 0 contours by `Jaakko Leppakangas`_ + +- Fix :class:`mne.preprocessing.ICA` source-picking to increase threshold for rank estimation to 1e-14 by `Jesper Duemose Nielsen`_ + +- Fix :func:`mne.set_bipolar_reference` to support duplicates in anodes by `Jean-Baptiste Schiratti`_ and `Alex Gramfort`_ + +- Fix visuals of :func:`mne.viz.plot_evoked` and a bug where ylim changes when using interactive topomap plotting by `Jaakko Leppakangas`_ + +- Fix :meth:`mne.Evoked.plot_topomap` when using the ``mask`` argument with paired gradiometers by `Eric Larson`_ + +- Fix bug in :meth:`mne.Label.fill` where an empty label raised an error, by `Eric Larson`_ + +- Fix :func:`mne.io.read_raw_ctf` to also include the samples in the last block by `Jaakko Leppakangas`_ + +- Fix :meth:`mne.preprocessing.ICA.save` to close file before attempting to delete it when write fails by `Jesper Duemose Nielsen`_ + +- Fix :func:`mne.simulation.simulate_evoked` to use nave parameter instead of snr, by `Yousra Bekhti`_ + +- Fix :func:`mne.read_bem_surfaces` for BEM files missing normals by `Christian Brodbeck`_ + +- Fix :func:`mne.transform_surface_to` to actually copy when ``copy=True`` by `Eric Larson`_ + +- Fix :func:`mne.io.read_raw_brainvision` to read vectorized data correctly by `Jaakko Leppakangas`_ and `Phillip Alday`_ + +- Fix ``mne.connectivity.spectral_connectivity`` so that if ``n_jobs > 1`` it does not ignore last ``n_epochs % n_jobs`` epochs by `Mikołaj Magnuski`_ + +- Fix :func:`mne.io.read_raw_edf` to infer sampling rate correctly when reading EDF+ files where tal-channel has a higher sampling frequency by `Jaakko Leppakangas`_ + +- Fix default value of ``kind='topomap'`` in ``mne.channels.Montage.plot`` to be consistent with :func:`mne.viz.plot_montage` by `Clemens Brunner`_ + +- Fix bug in :meth:`to_data_frame ` where non-consecutive picks would make the function crash by `Jaakko Leppakangas`_ + +- Fix channel picking and drop in :class:`mne.time_frequency.EpochsTFR` by `Lukáš Hejtmánek`_ + +- Fix :func:`mne.SourceEstimate.transform` to properly update :attr:`mne.SourceEstimate.times` by `Marijn van Vliet`_ + +- Fix :func:`mne.viz.plot_evoked_joint` to allow custom titles without appending information about the channels by `Jaakko Leppakangas`_ + +- Fix writing a forward solution after being processed by :func:`mne.forward.restrict_forward_to_label` or :func:`mne.forward.restrict_forward_to_stc` by `Marijn van Vliet`_ + +- Fix bug in :func:`mne.viz.plot_compare_evokeds` where ``truncate_yaxis`` was ignored (default is now ``False``), by `Jona Sassenhagen`_ + +- Fix bug in :func:`mne.viz.plot_evoked` where all xlabels were removed when using ``spatial_colors=True``, by `Jesper Duemose Nielsen`_ + +- Fix field mapping :func:`mne.make_field_map` and MEG bad channel interpolation functions (e.g., :meth:`mne.Evoked.interpolate_bads`) to choose a better number of components during pseudoinversion when few channels are available, by `Eric Larson`_ + +- Fix bug in :func:`mne.io.read_raw_brainvision`, changed default to read coordinate information if available and added test, by `Jesper Duemose Nielsen`_ + +- Fix bug in :meth:`mne.SourceEstimate.to_original_src` where morphing failed if two vertices map to the same target vertex, by `Marijn van Vliet`_ + +- Fix :class:`mne.preprocessing.Xdawn` to give verbose error messages about rank deficiency and handle transforming :class:`mne.Evoked`, by `Eric Larson`_ + +- Fix bug in DC and Nyquist frequency multitaper PSD computations, e.g. in ``mne.time_frequency.psd_multitaper``, by `Eric Larson`_ + +- Fix default padding type for :meth:`mne.Epochs.resample` and :meth:`mne.Evoked.resample` to be ``'edge'`` by default, by `Eric Larson`_ + +- Fix :func:`mne.inverse_sparse.mixed_norm`, :func:`mne.inverse_sparse.tf_mixed_norm` and :func:`mne.inverse_sparse.gamma_map` to work with volume source space and sphere head models in MEG by `Alex Gramfort`_ and `Yousra Bekhti`_ + +- Fix :meth:`mne.Evoked.as_type` channel renaming to append ``'_v'`` instead of ``'_virtual'`` to channel names to comply with shorter naming (15 char) requirements, by `Eric Larson`_ + +- Fix treatment of CTF HPI coils as fiducial points in :func:`mne.gui.coregistration` by `Eric Larson`_ + +- Fix resampling of events along with raw in :func:`mne.io.Raw` to now take into consideration the value of ``first_samp`` by `Chris Bailey`_ + +- Fix labels of PSD plots in :func:`mne.viz.plot_raw_psd` by `Alejandro Weinstein`_ + +- Fix depth weighting of sparse solvers (:func:`mne.inverse_sparse.mixed_norm`, :func:`mne.inverse_sparse.tf_mixed_norm` and :func:`mne.inverse_sparse.gamma_map`) with free orientation source spaces to improve orientation estimation by `Alex Gramfort`_ and `Yousra Bekhti`_ + +- Fix the threshold in :func:`mne.beamformer.rap_music` to properly estimate the rank by `Yousra Bekhti`_ + +- Fix treatment of vector inverse in :func:`mne.minimum_norm.apply_inverse_epochs` by `Emily Stephen`_ + +- Fix :func:`mne.find_events` when passing a list as stim_channel parameter by `Alex Gramfort`_ + +- Fix parallel processing when computing covariance with shrinkage estimators by `Denis Engemann`_ + +API +~~~ +- Removed the ``mne.datasets.megsim`` dataset because it was taken down by its host (MRN). Use the :mod:`mne.simulation` functions instead, by `Eric Larson`_ + +- Add ``skip_by_annotation`` to :meth:`mne.io.Raw.filter` to process data concatenated with e.g. :func:`mne.concatenate_raws` separately. This parameter will default to the old behavior (treating all data as a single block) in 0.15 but will change to ``skip_by_annotation='edge'``, which will separately filter the concatenated chunks separately, in 0.16. This should help prevent potential problems with filter-induced ringing in concatenated files, by `Eric Larson`_ + +- ICA channel names have now been reformatted to start from zero, e.g. ``"ICA000"``, to match indexing schemes in :class:`mne.preprocessing.ICA` and related functions, by `Stefan Repplinger`_ and `Eric Larson`_ + +- Add :func:`mne.beamformer.make_lcmv` and :func:`mne.beamformer.apply_lcmv`, :func:`mne.beamformer.apply_lcmv_epochs`, and :func:`mne.beamformer.apply_lcmv_raw` to enable the separate computation and application of LCMV beamformer weights by `Britta Westner`_, `Alex Gramfort`_, and `Denis Engemann`_. + +- Add ``weight_norm`` parameter to enable both unit-noise-gain beamformer and neural activity index (weight normalization) and make whitening optional by allowing ``noise_cov=None`` in ``mne.beamformer.lcmv``, ``mne.beamformer.lcmv_epochs``, and ``mne.beamformer.lcmv_raw``, by `Britta Westner`_, `Alex Gramfort`_, and `Denis Engemann`_. + +- Add new filtering mode ``fir_design='firwin'`` (default in the next 0.16 release) that gets improved attenuation using fewer samples compared to ``fir_design='firwin2'`` (default in the current 0.15 release) by `Eric Larson`_ + +- Make the goodness of fit (GOF) of the dipoles returned by :func:`mne.beamformer.rap_music` consistent with the GOF of dipoles returned by :func:`mne.fit_dipole` by `Alex Gramfort`_. + +- :class:`mne.decoding.SlidingEstimator` will now replace ``mne.decoding.TimeDecoding`` to make it generic and fully compatible with scikit-learn, by `Jean-Rémi King`_ and `Alex Gramfort`_ + +- :class:`mne.decoding.GeneralizingEstimator` will now replace ``mne.decoding.GeneralizationAcrossTime`` to make it generic and fully compatible with scikit-learn, by `Jean-Rémi King`_ and `Alex Gramfort`_ + +- ``mne.viz.decoding.plot_gat_times``, ``mne.viz.decoding.plot_gat_matrix`` are now deprecated. Use matplotlib instead as shown in the examples, by `Jean-Rémi King`_ and `Alex Gramfort`_ + +- Add ``norm_trace`` parameter to control single-epoch covariance normalization in :class:`mne.decoding.CSP`, by `Jean-Rémi King`_ + +- Allow passing a list of channel names as ``show_names`` in function :func:`mne.viz.plot_sensors` and methods :meth:`mne.Evoked.plot_sensors`, :meth:`mne.Epochs.plot_sensors` and :meth:`mne.io.Raw.plot_sensors` to show only a subset of channel names by `Jaakko Leppakangas`_ + +- Make function ``mne.io.eeglab.read_events_eeglab`` public to allow loading overlapping events from EEGLAB files, by `Jona Sassenhagen`_. + +- :func:`mne.find_events` ``mask_type`` parameter will change from ``'not_and'`` to ``'and'`` in 0.16. + +- Instead of raising an error, duplicate channel names in the data file are now appended with a running number by `Jaakko Leppakangas`_ + +- :func:`mne.io.read_raw_edf` has now ``'auto'`` option for ``stim_channel`` (default in version 0.16) that automatically detects if EDF annotations or GDF events exist in the header and constructs the stim channel based on these events by `Jaakko Leppakangas`_ + +- :meth:`mne.io.Raw.plot_psd` now rejects data annotated bad by default. Turn off with ``reject_by_annotation=False``, by `Eric Larson`_ + +- :func:`mne.set_eeg_reference` and the related methods (e.g., :meth:`mne.io.Raw.set_eeg_reference`) have a new argument ``projection``, which if set to False directly applies an average reference instead of adding an SSP projector, by `Clemens Brunner`_ + +- Deprecate ``plot_trans`` in favor of :func:`mne.viz.plot_alignment` and add ``bem`` parameter for plotting conductor model by `Jaakko Leppakangas`_ + +- ``mne.beamformer.tf_lcmv`` now has a ``raw`` parameter to accommodate epochs objects that already have data loaded with ``preload=True``, with :meth:`mne.Epochs.load_data`, or that are read from disk, by `Eric Larson`_ + +- ``mne.time_frequency.psd_welch`` and :func:`mne.time_frequency.psd_array_welch` now use a Hamming window (instead of a Hann window) by `Clemens Brunner`_ + +- ``picks`` parameter in ``mne.beamformer.lcmv``, ``mne.beamformer.lcmv_epochs``, ``mne.beamformer.lcmv_raw``, ``mne.beamformer.tf_lcmv`` and :func:`mne.beamformer.rap_music` is now deprecated and will be removed in 0.16, by `Britta Westner`_, `Alex Gramfort`_, and `Denis Engemann`_. + +- The keyword argument ``frequencies`` has been deprecated in favor of ``freqs`` in various time-frequency functions, e.g. :func:`mne.time_frequency.tfr_array_morlet`, by `Eric Larson`_ + +- Add ``patterns=False`` parameter in :class:`mne.decoding.ReceptiveField`. Turn on to compute inverse model coefficients, by `Nicolas Barascud`_ + +- The ``scale``, ``scale_time``, and ``unit`` parameters have been deprecated in favor of ``scalings``, ``scalings_time``, and ``units`` in :func:`mne.viz.plot_evoked_topomap` and related functions, by `Eric Larson`_ + +- ``loose`` parameter in inverse solvers has now a default value ``'auto'`` depending if the source space is a surface, volume, or discrete type by `Alex Gramfort`_ and `Yousra Bekhti`_ + +- The behavior of ``'mean_flip'`` label-flipping in :meth:`mne.extract_label_time_course` and related functions has been changed such that the flip, instead of having arbitrary sign, maximally aligns in the positive direction of the normals of the label, by `Eric Larson`_ + +- Deprecate force_fixed and surf_ori in :func:`mne.read_forward_solution` by `Daniel Strohmeier`_ + +- :func:`mne.convert_forward_solution` has a new argument ``use_cps``, which controls whether information on cortical patch statistics is applied while generating surface-oriented forward solutions with free and fixed orientation by `Daniel Strohmeier`_ + +- :func:`mne.write_forward_solution` writes a forward solution as a forward solution with free orientation in X/Y/Z RAS coordinates if it is derived from a forward solution with free orientation and as a forward solution with fixed orientation in surface-based local coordinates otherwise by `Daniel Strohmeier`_ + +- ``loose=None`` in inverse solvers is deprecated, use explicitly ``loose=0`` for fixed constraint and ``loose=1.0`` for free orientations by `Eric Larson`_ + +- Zero-channel-value in PSD calculation in :func:`mne.viz.plot_raw_psd` has been relaxed from error to warning by `Alejandro Weinstein`_ + +- Expose "rank" parameter in :func:`mne.viz.plot_evoked_white` to correct rank estimates on the spot during visualization by `Denis Engemann`_, `Eric Larson`_, `Alex Gramfort`_. + +- Show channel name under mouse cursor on topography plots by `Jussi Nurminen`_ + +- Return maximum response amplitude from :meth:`mne.Evoked.get_peak` + +Authors +~~~~~~~ + +People who contributed to this release (in alphabetical order): + +* akshay0724 +* Alejandro Weinstein +* Alexander Rudiuk +* Alexandre Barachant +* Alexandre Gramfort +* Andrew Dykstra +* Britta Westner +* Chris Bailey +* Chris Holdgraf +* Christian Brodbeck +* Christopher Holdgraf +* Clemens Brunner +* Cristóbal Moënne-Loccoz +* Daniel McCloy +* Daniel Strohmeier +* Denis A. Engemann +* Emily P. Stephen +* Eric Larson +* Fede Raimondo +* Jaakko Leppakangas +* Jean-Baptiste Schiratti +* Jean-Rémi King +* Jesper Duemose Nielsen +* Joan Massich +* Jon Houck +* Jona Sassenhagen +* Jussi Nurminen +* Laetitia Grabot +* Laura Gwilliams +* Luke Bloy +* Lukáš Hejtmánek +* Mainak Jas +* Marijn van Vliet +* Mathurin Massias +* Matt Boggess +* Mikolaj Magnuski +* Nicolas Barascud +* Nicole Proulx +* Phillip Alday +* Ramonapariciog Apariciogarcia +* Robin Tibor Schirrmeister +* Rodrigo Hübner +* S. M. Gutstein +* Simon Kern +* Teon Brooks +* Yousra Bekhti diff --git a/mne-python/source/doc/changes/v0.16.rst b/mne-python/source/doc/changes/v0.16.rst new file mode 100644 index 0000000000000000000000000000000000000000..cdf6dbf0495c33c14294fbc8c7276978e275b7dc --- /dev/null +++ b/mne-python/source/doc/changes/v0.16.rst @@ -0,0 +1,258 @@ +.. _changes_0_16: + +Version 0.16 (2018-05-01) +------------------------- + +Changelog +~~~~~~~~~ + +- Add possibility to pass dict of floats as argument to :func:`mne.make_ad_hoc_cov` by `Nathalie Gayraud`_ + +- Add support for metadata in :class:`mne.Epochs` by `Chris Holdgraf`_, `Alex Gramfort`_, `Jona Sassenhagen`_, and `Eric Larson`_ + +- Add support for plotting a dense head in :func:`mne.viz.plot_alignment` by `Eric Larson`_ + +- Allow plotting in user-created mayavi Scene in :func:`mne.viz.plot_alignment` by `Daniel McCloy`_ + +- Reduce memory consumption and do not require data to be loaded in :meth:`mne.Epochs.apply_baseline` by `Eric Larson`_ + +- Add option ``render_bem`` to :meth:`mne.Report.parse_folder` by `Eric Larson`_ + +- Add to :func:`mne.viz.plot_alignment` plotting of coordinate frame axes via ``show_axes`` and terrain-style interaction via ``interaction``, by `Eric Larson`_ + +- Add option ``initial_event`` to :func:`mne.find_events` by `Clemens Brunner`_ + +- Left and right arrow keys now scroll by 25% of the visible data, whereas Shift+left/right scroll by a whole page in :meth:`mne.io.Raw.plot` by `Clemens Brunner`_ + +- Add support for gantry tilt angle determination from Elekta FIF file header by `Chris Bailey`_ + +- Add possibility to concatenate :class:`mne.Annotations` objects with ``+`` or ``+=`` operators by `Clemens Brunner`_ + +- Add support for MaxShield raw files in :class:`mne.Report` by `Eric Larson`_ + +- Add ability to plot whitened data in :meth:`mne.io.Raw.plot`, :meth:`mne.Epochs.plot`, :meth:`mne.Evoked.plot`, and :meth:`mne.Evoked.plot_topo` by `Eric Larson`_ + +- Workaround for reading EGI MFF files with physiological signals that also present a bug from the EGI system in :func:`mne.io.read_raw_egi` by `Federico Raimondo`_ + +- Add support for reading subject height and weight in ``info['subject_info']`` by `Eric Larson`_ + +- Improve online filtering of raw data when plotting with :meth:`mne.io.Raw.plot` to filter in segments in accordance with the default ``skip_by_annotation=('edge', 'bad_acq_skip')`` of :meth:`mne.io.Raw.filter` to avoid edge ringing by `Eric Larson`_ + +- Add support for multiple head position files, plotting of sensors, and control of plotting color and axes in :func:`mne.viz.plot_head_positions` by `Eric Larson`_ + +- Add ability to read and write :class:`Annotations` separate from :class:`mne.io.Raw` instances via :meth:`Annotations.save` and :func:`read_annotations` by `Eric Larson`_ + +- Add option to unset a montage by passing `None` to :meth:`mne.io.Raw.set_montage` by `Clemens Brunner`_ + +- Add sensor denoising via :func:`mne.preprocessing.oversampled_temporal_projection` by `Eric Larson`_ + +- Add ``mne.io.pick.get_channel_types`` which returns all available channel types in MNE by `Clemens Brunner`_ + +- Use standard PCA instead of randomized PCA whitening prior to ICA to increase reproducibility by `Clemens Brunner`_ + +- Plot sEEG electrodes in :func:`mne.viz.plot_alignment` by `Alex Gramfort`_ + +- Add support for any data type like sEEG or ECoG in covariance related functions (estimation, whitening and plotting) by `Alex Gramfort`_ and `Eric Larson`_ + +- Add function ``mne.io.read_annotations_eeglab`` to allow loading annotations from EEGLAB files, by `Alex Gramfort`_ + +- :meth:`mne.io.Raw.set_montage` now accepts a string as its ``montage`` argument; this will set a builtin montage, by `Clemens Brunner`_ + +- Add 4D BTi phantom dataset :func:`mne.datasets.phantom_4dbti.data_path`, by `Alex Gramfort`_ + +- Changed the background color to grey in :func:`mne.viz.plot_alignment` to make helmet more visible, by `Alex Gramfort`_ + +- Add :meth:`mne.io.Raw.reorder_channels`, :meth:`mne.Evoked.reorder_channels`, etc. to reorder channels, by `Eric Larson`_ + +- Add to ``mne coreg`` and :func:`mne.gui.coregistration` by `Eric Larson`_: + + - Improved visibility of points inside the head + - Projection of EEG electrodes + - Orientation of extra points toward the surface + - Scaling points by distance to the head surface + - Display of HPI points + - ICP fitting with convergence criteria + - Faster display updates + - Scaling of ``mri/*.mgz`` files + - Scaling of ``mri/trainsforms/talairach.xfm`` files for conversion to MNI space + +- Add ability to exclude components interactively by clicking on their labels in :meth:`mne.preprocessing.ICA.plot_components` by `Mikołaj Magnuski`_ + +- Add reader for manual annotations of raw data produced by Brainstorm by `Anne-Sophie Dubarry`_ + +- Add eLORETA noise normalization for minimum-norm solvers by `Eric Larson`_ + +- Tighter duality gap computation in ``mne.inverse_sparse.tf_mxne_optim`` and new parametrization with ``alpha`` and ``l1_ratio`` instead of ``alpha_space`` and ``alpha_time`` by `Mathurin Massias`_ and `Daniel Strohmeier`_ + +- Add ``dgap_freq`` parameter in ``mne.inverse_sparse.mxne_optim`` solvers to control the frequency of duality gap computation by `Mathurin Massias`_ and `Daniel Strohmeier`_ + +- Add support for reading Eximia files by `Eric Larson`_ and `Federico Raimondo`_ + +- Add the Picard algorithm to perform ICA for :class:`mne.preprocessing.ICA`, by `Pierre Ablin`_ and `Alex Gramfort`_ + +- Add ability to supply a mask to the plot in :func:`mne.viz.plot_evoked_image` by `Jona Sassenhagen`_ + +- Add ``connectivity=False`` to cluster-based statistical functions to perform non-clustering stats by `Eric Larson`_ + +- Add :func:`mne.time_frequency.csd_morlet` and :func:`mne.time_frequency.csd_array_morlet` to estimate cross-spectral density using Morlet wavelets, by `Marijn van Vliet`_ + +- Add multidictionary time-frequency support to :func:`mne.inverse_sparse.tf_mixed_norm` by `Mathurin Massias`_ and `Daniel Strohmeier`_ + +- Add new DICS implementation as :func:`mne.beamformer.make_dics`, :func:`mne.beamformer.apply_dics`, :func:`mne.beamformer.apply_dics_csd` and :func:`mne.beamformer.apply_dics_epochs`, by `Marijn van Vliet`_ and `Susanna Aro`_ + +Bug +~~~ + +- Fix bug in EEG interpolation code to do nothing if there is no channel to interpolate by `Mainak Jas`_ + +- Fix bug in ``mne.preprocessing.peak_finder`` to output datatype consistently and added input check for empty vectors by `Tommy Clausner`_ + +- Fix bug in :func:`mne.io.read_raw_brainvision` to use the correct conversion for filters from time constant to frequency by `Stefan Appelhoff`_ + +- Fix bug with events when saving split files using :meth:`mne.Epochs.save` by `Eric Larson`_ + +- Fix bug in :class:`mne.decoding.SlidingEstimator` and :class:`mne.decoding.GeneralizingEstimator` to allow :func:`mne.decoding.cross_val_multiscore` to automatically detect whether the ``base_estimator`` is a classifier and use a ``StratifiedKFold`` instead of a ``KFold`` when ``cv`` is not specified, by `Jean-Rémi King`_ + +- Fix bug in :func:`mne.set_eeg_reference` to remove an average reference projector when setting the reference to ``[]`` (i.e. do not change the existing reference) by `Clemens Brunner`_ + +- Fix bug in threshold-free cluster enhancement parameter validation (:func:`mne.stats.permutation_cluster_1samp_test` and :func:`mne.stats.permutation_cluster_test`) by `Clemens Brunner`_ + +- Fix bug in :meth:`mne.io.Raw.plot` to correctly display event types when annotations are present by `Clemens Brunner`_ + +- Fix bug in :func:`mne.stats.spatio_temporal_cluster_test` default value for ``threshold`` is now calculated based on the array sizes in ``X``, by `Eric Larson`_ + +- Fix bug in :func:`mne.simulation.simulate_raw` with ``use_cps=True`` where CPS was not actually used by `Eric Larson`_ + +- Fix bug in :func:`mne.simulation.simulate_raw` where 1- and 3-layer BEMs were not properly transformed using ``trans`` by `Eric Larson`_ + +- Fix bug in :func:`mne.viz.plot_alignment` where the head surface file ``-head.fif`` was not used even though present by `Chris Bailey`_ + +- Fix bug when writing compressed sparse column matrices (e.g., Maxwell filtering cross-talk matrices) by `Marijn van Vliet`_ and `Eric Larson`_ + +- Fix bug in :meth:`mne.io.Raw.plot_psd` to correctly deal with ``reject_by_annotation=False`` by `Clemens Brunner`_ + +- Fix bug in :func:`mne.make_fixed_length_events` when hitting corner case problems rounding to sample numbers by `Eric Larson`_ + +- Fix bug in :class:`mne.Epochs` when passing events as list with ``event_id=None`` by `Alex Gramfort`_ + +- Fix bug in ``mne.Report.add_figs_to_section`` when passing :class:`numpy.ndarray` by `Eric Larson`_ + +- Fix bug in CSS class setting in `mne.Report` BEM section by `Eric Larson`_ + +- Fix bug in :class:`Annotations` where annotations that extend to the end of a recording were not extended properly by `Eric Larson`_ + +- Fix bug in :meth:`mne.io.Raw.filter` to properly raw data with acquisition skips in separate segments by `Eric Larson`_ + +- Fix bug in :func:`mne.preprocessing.maxwell_filter` where homogeneous fields were not removed for CTF systems by `Eric Larson`_ + +- Fix computation of average quaternions in :func:`mne.preprocessing.maxwell_filter` by `Eric Larson`_ + +- Fix bug in writing ``raw.annotations`` where empty annotations could not be written to disk, by `Eric Larson`_ + +- Fix support for writing FIF files with acquisition skips by using empty buffers rather than writing zeros by `Eric Larson`_ + +- Fix bug in the ``mne make_scalp_surfaces`` command where ``--force`` (to bypass topology check failures) was ignored by `Eric Larson`_ + +- Fix bug in :func:`mne.preprocessing.maxwell_filter` when providing ``origin`` in ``'meg'`` coordinate frame for recordings with a MEG to head transform (i.e., non empty-room recordings) by `Eric Larson`_ + +- Fix bug in :func:`mne.viz.plot_cov` that ignored ``colorbar`` argument by `Nathalie Gayraud`_ + +- Fix bug when picking CTF channels that could cause data saved to disk to be unreadable by `Eric Larson`_ + +- Fix bug when reading event latencies (in samples) from eeglab files didn't translate indices to 0-based python indexing by `Mikołaj Magnuski`_ + +- Fix consistency between :class:`mne.Epochs` and :func:`mne.stats.linear_regression_raw` in converting between samples and times (:func:`mne.stats.linear_regression_raw` now rounds, instead of truncating) by `Phillip Alday`_ + +- Fix bug in ``mne coreg`` where sphere surfaces were scaled by `Eric Larson`_ + +- Fix bug in :meth:`mne.Evoked.plot_topomap` when using ``proj='interactive'`` mode by `Eric Larson`_ + +- Fix bug when passing ``show_sensors=1`` to :func:`mne.viz.plot_compare_evokeds` resulted in sensors legend placed in lower right of the figure (position 4 in matplotlib), not upper right by `Mikołaj Magnuski`_ + +- Fix handling of annotations when cropping and concatenating raw data by `Alex Gramfort`_ and `Eric Larson`_ + +- Fix bug in :func:`mne.preprocessing.create_ecg_epochs` where ``keep_ecg=False`` was ignored by `Eric Larson`_ + +- Fix bug in :meth:`mne.io.Raw.plot_psd` when ``picks is not None`` and ``picks`` spans more than one channel type by `Eric Larson`_ + +- Fix bug in :class:`mne.make_forward_solution` when passing data with compensation channels (e.g. CTF) that contain bad channels by `Alex Gramfort`_ + +- Fix bug in :meth:`mne.SourceEstimate.get_peak` and :meth:`mne.VolSourceEstimate.get_peak` when there is only a single time point by `Marijn van Vliet`_ + +- Fix bug in :func:`mne.io.read_raw_edf` when reading BDF files stimulus channels are now not scaled anymore by `Clemens Brunner`_ + +API +~~~ + +- Channels with unknown locations are now assigned position ``[np.nan, np.nan, np.nan]`` instead of ``[0., 0., 0.]``, by `Eric Larson`_ + +- Removed unused ``image_mask`` argument from :func:`mne.viz.plot_topomap` by `Eric Larson`_ + +- Unknown measurement dates are now stored as ``info['meas_date'] = None`` rather than using the current date. ``None`` is also now used when anonymizing data and when determining the machine ID for writing files, by `Mainak Jas`_ and `Eric Larson`_ + +- :meth:`mne.Evoked.plot` will now append the number of epochs averaged for the evoked data in the first plot title, by `Eric Larson`_ + +- Changed the line width in :func:`mne.viz.plot_bem` from 2.0 to 1.0 for better visibility of underlying structures, by `Eric Larson`_ + +- Changed the behavior of :meth:`mne.io.Raw.pick_channels` and similar methods to be consistent with :func:`mne.pick_channels` to treat channel list as a set (ignoring order) -- if reordering is necessary use ``inst.reorder_channels``, by `Eric Larson`_ + +- Changed the labeling of some plotting functions to use more standard capitalization and units, e.g. "Time (s)" instead of "time [sec]" by `Eric Larson`_ + +- ``mne.time_frequency.csd_epochs`` has been refactored into :func:`mne.time_frequency.csd_fourier` and :func:`mne.time_frequency.csd_multitaper`, by `Marijn van Vliet`_ + +- ``mne.time_frequency.csd_array`` has been refactored into :func:`mne.time_frequency.csd_array_fourier` and :func:`mne.time_frequency.csd_array_multitaper`, by `Marijn van Vliet`_ + +- Added ``clean_names=False`` parameter to :func:`mne.io.read_raw_ctf` for control over cleaning of main channel names and compensation channel names from CTF suffixes by `Oleh Kozynets`_ + +- The functions ``lcmv``, ``lcmv_epochs``, and ``lcmv_raw`` are now deprecated in favor of :func:`mne.beamformer.make_lcmv` and :func:`mne.beamformer.apply_lcmv`, :func:`mne.beamformer.apply_lcmv_epochs`, and :func:`mne.beamformer.apply_lcmv_raw`, by `Britta Westner`_ + +- The functions ``mne.beamformer.dics``, ``mne.beamformer.dics_epochs`` and ``mne.beamformer.dics_source_power`` are now deprecated in favor of :func:`mne.beamformer.make_dics`, :func:`mne.beamformer.apply_dics`, and :func:`mne.beamformer.apply_dics_csd`, by `Marijn van Vliet`_ + + +Authors +~~~~~~~ + +People who contributed to this release (in alphabetical order): + +* Alejandro Weinstein +* Alexandre Gramfort +* Annalisa Pascarella +* Anne-Sophie Dubarry +* Britta Westner +* Chris Bailey +* Chris Holdgraf +* Christian Brodbeck +* Claire Braboszcz +* Clemens Brunner +* Daniel McCloy +* Denis A. Engemann +* Desislava Petkova +* Dominik Krzemiński +* Eric Larson +* Erik Hornberger +* Fede Raimondo +* Henrich Kolkhorst +* Jean-Rémi King +* Jen Evans +* Joan Massich +* Jon Houck +* Jona Sassenhagen +* Juergen Dammers +* Jussi Nurminen +* Kambiz Tavabi +* Katrin Leinweber +* Kostiantyn Maksymenko +* Larry Eisenman +* Luke Bloy +* Mainak Jas +* Marijn van Vliet +* Mathurin Massias +* Mikolaj Magnuski +* Nathalie Gayraud +* Oleh Kozynets +* Phillip Alday +* Pierre Ablin +* Stefan Appelhoff +* Stefan Repplinger +* Tommy Clausner +* Yaroslav Halchenko diff --git a/mne-python/source/doc/changes/v0.17.rst b/mne-python/source/doc/changes/v0.17.rst new file mode 100644 index 0000000000000000000000000000000000000000..49e722c584d51f2c86bfd22fe7315ca5cd7bdf40 --- /dev/null +++ b/mne-python/source/doc/changes/v0.17.rst @@ -0,0 +1,317 @@ +.. _changes_0_17: + +Version 0.17 (2018-11-19) +------------------------- + +Changelog +~~~~~~~~~ + +- Add new tutorial for :class:`mne.Annotations` and ``events`` by `Joan Massich`_ and `Alex Gramfort`_ + +- Add support for saving :class:`mne.Annotations` as CSV and TXT files by `Joan Massich`_ and `Alex Gramfort`_ + +- Add :meth:`mne.Epochs.shift_time` that shifts the time axis of :class:`mne.Epochs` by `Thomas Hartmann`_ + +- Add :func:`mne.viz.plot_arrowmap` computes arrowmaps using Hosaka-Cohen transformation from magnetometer or gradiometer data, these arrows represents an estimation of the current flow underneath the MEG sensors by `Sheraz Khan`_ + +- Add :func:`mne.io.read_raw_fieldtrip`, :func:`mne.read_epochs_fieldtrip` and :func:`mne.read_evoked_fieldtrip` to import FieldTrip data. By `Thomas Hartmann`_ and `Dirk Gütlin`_. + +- Add ``rank`` parameter to :func:`mne.compute_covariance`, :func:`mne.cov.regularize` and related functions to preserve data rank and speed up computation using low-rank computations during regularization by `Eric Larson`_ and `Denis Engemann`_ + +- Add new function :func:`mne.read_annotations` that can read annotations in EEGLAB, BrainVision, EDF and Brainstorm formats by `Joan Massich`_ and `Alex Gramfort`_. + +- Add capability to read and save Epochs containing complex data (e.g. after Hilbert-transform) using :meth:`mne.Epochs.save` and :func:`mne.read_epochs`, by `Stefan Repplinger`_, `Eric Larson`_ and `Alex Gramfort`_ + +- Add optically pumped magnetometer dataset and example by `Rasmus Zetter`_ and `Eric Larson`_ + +- Add ``origin`` parameter to :meth:`mne.io.Raw.time_as_index` to allow ``times`` to be relative to this ``origin`` by `Joan Massich`_ + +- Add ``title`` argument to :meth:`mne.SourceEstimate.plot` by `Eric Larson`_ + +- :func:`mne.io.Raw.set_annotations` now changes ``orig_time`` to match ``meas_date`` and shift ``self.annotations.onset`` accordingly. Previous behavior is deprecated and would be removed in 0.18. Work by `Joan Massich`_ + +- Add :func:`mne.compute_source_morph` which creates a :class:`mne.SourceMorph` object to unify morphing any type of source estimates (surface or volume) from one subject to another for group studies. It is now possible to do group studies when working on the volume with MNE. Work by `Tommy Clausner`_ during GSOC 2018 with the help of `Alex Gramfort`_ and `Eric Larson`_. + +- Add ability to pass threshold for EOG to :func:`mne.preprocessing.find_eog_events` and :func:`mne.preprocessing.create_eog_epochs` by `Peter Molfese`_ + +- Add possibility to save :class:`mne.VolSourceEstimate` and :class:`mne.MixedSourceEstimate` to HDF5 format (file extension .h5) with :meth:`mne.VolSourceEstimate.save` and :meth:`mne.MixedSourceEstimate.save` by `Alex Gramfort`_ + +- Add ``replace`` parameter to :meth:`mne.io.Raw.add_events` to allow adding events while removing the old ones on the stim channel by `Alex Gramfort`_ + +- Add ability to pass ``axes`` to ``ts_args`` and ``topomap_args`` of :meth:`mne.viz.plot_evoked_joint` by `Jona Sassenhagen`_ + +- Add ability to pass a precomputed forward solution to :func:`mne.simulation.simulate_raw` by `Eric Larson`_ + +- Add ability to read and write beamformers with :func:`mne.beamformer.read_beamformer` and :class:`mne.beamformer.Beamformer.save` by `Eric Larson`_ + +- Add resting-state source power spectral estimation example ``sphx_glr_auto_examples_datasets_plot_opm_rest_data.py`` by `Eric Larson`_, `Denis Engemann`_, and `Luke Bloy`_ + +- Add :func:`mne.channels.make_1020_channel_selections` to group 10/20-named EEG channels by location, by `Jona Sassenhagen`_ + +- Add helmet for Artemis123 for :func:`mne.viz.plot_alignment` by `Eric Larson`_ + +- Add support for reading MATLAB ``v7.3+`` files in :func:`mne.io.read_raw_eeglab` and :func:`mne.read_epochs_eeglab` via `pymatreader`_ by `Steven Gutstein`_, `Eric Larson`_, and `Thomas Hartmann`_ + +- Add support for raw PSD plots in :meth:`mne.Report.parse_folder` via ``raw_psd`` argument of :class:`mne.Report` by `Eric Larson`_ + +- Add ``trig_shift_by_type`` parameter in :func:`mne.io.read_raw_brainvision` to allow to specify offsets for arbitrary marker types by `Henrich Kolkhorst`_ + +- Add progress bar support to :class:`mne.decoding.SlidingEstimator` and :class:`mne.decoding.GeneralizingEstimator` by `Eric Larson`_ + +- Add interactive visualization of volume source estimates using :func:`mne.viz.plot_volume_source_estimates` by `Mainak Jas`_ + +- Add :func:`mne.head_to_mri` to convert positions from head coordinates to MRI RAS coordinates, by `Joan Massich`_ and `Alex Gramfort`_ + +- Add improved CTF helmet for :func:`mne.viz.plot_alignment` by `Eric Larson`_ + +- Add handling in :func:`mne.combine_evoked` and :func:`mne.grand_average` for input with the same channels in different orders, if required, by `Jona Sassenhagen`_ + +- Add ``split_naming`` parameter to the `mne.io.Raw.save` method to allow for BIDS-compatible raw file name construction by `Teon Brooks`_ + +- Add ``origin`` parameter to :meth:`mne.Evoked.interpolate_bads` and related methods by `Eric Larson`_ + +- Add automated MEG helmet shape approximation to :func:`mne.viz.plot_alignment` by `Eric Larson`_ + +- Add capability to save a :class:`mne.Report` to an HDF5 file to :meth:`mne.Report.save` by `Marijn van Vliet`_ + +- Add :func:`mne.open_report` to read back a :class:`mne.Report` object that was saved to an HDF5 file by `Marijn van Vliet`_ + +- Add multi-taper estimation to :func:`mne.minimum_norm.compute_source_psd` by `Eric Larson`_ + +- Add support for custom, e.g. robust, averaging methods in :meth:`mne.Epochs.average` by `Jona Sassenhagen`_ + +- Add support for Neuromag 122 system by `Alex Gramfort`_ + +- Add function ``mne.io.read_annotations_brainvision`` for reading directly Brainvision marker files by `Alex Gramfort`_ + +- Add :meth:`mne.Report.remove` method to remove existing figures from a report, by `Marijn van Vliet`_ + +- Add sign to output of max-power orientation for :func:`mne.beamformer.make_dics` by `Eric Larson`_ + +- Add support for ``pick_ori='max-power'`` when ``weight_norm=None`` in :func:`mne.beamformer.make_lcmv` by `Marijn van Vliet`_ + +- Add support for ``weight_norm='nai'`` for all ``pick_ori`` options in :func:`mne.beamformer.make_lcmv` by `Marijn van Vliet`_ + +- Add support for ``weight_norm='nai'`` to :func:`mne.beamformer.make_dics` by `Marijn van Vliet`_ + +- Add parameter ``rank=None`` to :func:`mne.beamformer.make_dics` by `Marijn van Vliet`_ + +- Add parameter ``rank='full'`` to :func:`mne.beamformer.make_lcmv`, which can be set to ``None`` to auto-compute the rank of the covariance matrix before regularization by `Marijn van Vliet`_ + +- Handle different time vectors in topography plots using :func:`mne.viz.plot_evoked_topo` by `Jussi Nurminen`_ + +- Speed up :func:`mne.inverse_sparse.mixed_norm` if the ``solver`` parameter is set to ``bcd`` using :func:`scipy.linalg.get_blas_funcs` by `Quentin Bertrand`_ + +Bug +~~~ + +- Fix bug with scaling of data in ``mne.cov._compute_covariance_auto`` that was affecting the :class:`mne.decoding.SPoC` estimator by `David Sabbagh`_ + +- Fix :func:`mne.io.Raw.plot_projs_topomap` by `Joan Massich`_ + +- Fix bug in :func:`mne.minimum_norm.compute_source_psd` where the ``stc.times`` output was scaled by 1000, by `Eric Larson`_ + +- Fix default values for ``'diagonal_fixed'`` estimation method of :func:`mne.compute_covariance` to be ``0.1`` for all channel types, as in :func:`mne.cov.regularize` by `Eric Larson`_ + +- Fix reading edf file annotations by `Joan Massich`_ + +- Fix bug with reading events from BrainVision files by `Stefan Appelhoff`_ + +- Fix bug where :func:`mne.io.read_raw_eeglab` would warn when the stim channel is populated with an array of zeros by `Joan Massich`_ + +- Fix 2nd column of events in BrainVision to no longer store duration but rather be contained by ``raw.annotations`` by `Alex Gramfort`_ + +- Fix checking of the correctness of the ``prepared=True`` argument in :func:`mne.minimum_norm.apply_inverse` and related functions by `Eric Larson`_ + +- Fix bug of not showing ERD's in baseline rescaled tfr topomaps if grads are combined by `Erkka Heinila`_ + +- Fix bug with FIF I/O where strings were written in UTF-8 format instead of Latin-1 by `Eric Larson`_ + +- Fix bug with reading measurement dates from BrainVision files by `Stefan Appelhoff`_ + +- Fix bug with `mne.fit_dipole` where the residual was returned as ``ndarray`` instead of :class:`mne.Evoked` instance, by `Eric Larson`_ + +- Fix bug with ``mne flash_bem`` when ``flash30`` is not used by `Eric Larson`_ + +- Fix bug with :func:`mne.stats.permutation_cluster_test` and :func:`mne.stats.spatio_temporal_cluster_test` where ``threshold=None`` was not calculated properly for a f-oneway test by `Daniel McCloy`_ and `Eric Larson`_ + +- Fix bug with channel names in ``mgh70`` montage in ``mne.channels.read_montage`` by `Eric Larson`_ + +- Fix duplication of ``info['hpi_meas']`` and ``info['hpi_results']`` by `Sara Sommariva`_ + +- Fix bug in :func:`mne.io.read_raw_edf` when reading large files on Windows by `Marcin Koculak`_ + +- Fix check in :func:`mne.viz.plot_sensors` for invalid channel locations by `Eric Larson`_ + +- Fix bug in :func:`mne.io.read_raw_edf` where GDF files had ``info['highpass']`` and ``info['lowpass']`` set to NaN and ``info['meas_date']`` set incorrectly, by `Eric Larson`_ + +- Fix bug in :func:`mne.preprocessing.ICA.apply` to handle arrays as ``exclude`` property by `Joan Massich`_ + +- Fix bug in ``method='eLORETA'`` for :func:`mne.minimum_norm.apply_inverse` when using a sphere model and saved ``inv`` by `Eric Larson`_ + +- Fix bug in :class:`mne.io.Raw` where warnings were emitted when objects were deleted by `Eric Larson`_ + +- Fix vector data support for :class:`mne.VolSourceEstimate` by `Christian Brodbeck`_ + +- Fix bug with IIR filtering axis in :func:`mne.filter.filter_data` by `Eric Larson`_ + +- Fix bug with non-boxcar windows in :meth:`mne.io.Raw.resample` and :func:`mne.filter.resample` by `Eric Larson`_ + +- Fix bug in :func:`mne.minimum_norm.apply_inverse` where applying an MEG-only inverse would raise an error about needing an average EEG reference by `Eric Larson`_ + +- Fix bug in ``inst.apply_proj()`` where an average EEG reference was always added by `Eric Larson`_ + +- Fix bug in :func:`mne.time_frequency.tfr_morlet`, :func:`mne.time_frequency.tfr_multitaper`, and :func:`mne.time_frequency.tfr_stockwell` where not all data channels were picked by `Eric Larson`_ + +- Fix bug in :meth:`mne.preprocessing.ICA.plot_overlay` and :func:`mne.make_field_map` for CTF data with compensation by `Eric Larson`_ + +- Fix bug in :func:`mne.create_info` passing ``int`` as ``ch_names`` on Windows by `Eric Larson`_ + +- Fix bug in ``mne.realtime.RtEpochs`` where events during the buildup of the buffer were not correctly processed when incoming data buffers are smaller than the epochs by `Henrich Kolkhorst`_ + +- Fix bug in :func:`mne.io.read_raw_brainvision` where 1-indexed BrainVision events were not being converted into 0-indexed mne events by `Steven Bethard`_ + +- Fix bug in :func:`mne.viz.plot_snr_estimate` and :func:`mne.minimum_norm.estimate_snr` where the inverse rank was not properly utilized (especially affecting SSS'ed MEG data) by `Eric Larson`_ + +- Fix error when saving stc as nifti image when using volume source space formed by more than one label by `Alex Gramfort`_ + +- Fix error when interpolating MEG channels with compensation using reference channels (like for CTF data) by `Alex Gramfort`_ + +- Fix bug in :func:`mne.make_sphere_model` where EEG sphere model coefficients were not optimized properly by `Eric Larson`_ + +- Fix bug in :func:`mne.io.read_raw_ctf` to read bad channels and segments from CTF ds files by `Luke Bloy`_ + +- Fix problem with :meth:`mne.io.Raw.add_channels` where ``raw.info['bads']`` was replicated by `Eric Larson`_ + +- Fix bug with :class:`mne.Epochs` where an error was thrown when resizing data (e.g., during :meth:`mne.Epochs.drop_bad`) by `Eric Larson`_ + +- Fix naming of ``raw.info['buffer_size_sec']`` to be ``raw.buffer_size_sec`` as it is a writing parameter rather than a measurement parameter by `Eric Larson`_ + +- Fix EGI-MFF parser not to require ``dateutil`` package by `Eric Larson`_ + +- Fix error when running LCMV on MEG channels with compensation using reference channels (like for CTF data) by `Alex Gramfort`_ + +- Fix the use of :func:`sklearn.model_selection.cross_val_predict` with :class:`mne.decoding.SlidingEstimator` by `Alex Gramfort`_ + +- Fix event sample number increase when combining many Epochs objects with :func:`mne.concatenate_epochs` with by `Jasper van den Bosch`_ + +- Fix title of custom slider images to :class:`mne.Report` by `Marijn van Vliet`_ + +- Fix missing initialization of ``self._current`` in :class:`mne.Epochs` by `Henrich Kolkhorst`_ + +- Fix processing of data with bad segments and acquisition skips with new ``skip_by_annotation`` parameter in :func:`mne.preprocessing.maxwell_filter` by `Eric Larson`_ + +- Fix symlinking to use relative paths in ``mne flash_bem`` and ``mne watershed_bem`` by `Eric Larson`_ + +- Fix error in mne coreg when saving with scaled MRI if fiducials haven't been saved by `Ezequiel Mikulan`_ + +- Fix normalization error in :func:`mne.beamformer.make_lcmv` when ``pick_ori='normal', weight_norm='unit_noise_gain'`` by `Marijn van Vliet`_ + +- Fix MNE-C installation instructions by `buildqa`_ + +- Fix computation of max-power orientation in :func:`mne.beamformer.make_dics` when ``pick_ori='max-power', weight_norm='unit_noise_gain'`` by `Marijn van Vliet`_ + +API +~~~ + +- Deprecated separate reading of annotations and synthesis of STI014 channels in readers by `Joan Massich`_: + + - Deprecated ``mne.io.read_annotations_eeglab`` + - Deprecated ``annot`` and ``annotmap`` parameters in :meth:`~mne.io.read_raw_edf` + - Deprecated ``stim_channel`` parameters in :func:`~mne.io.read_raw_edf`, :func:`~mne.io.read_raw_brainvision`, and :func:`~mne.io.read_raw_eeglab` + + Annotations are now added to ``raw`` instances directly upon reading as :attr:`raw.annotations `. + They can also be read separately with :func:`mne.read_annotations` for EEGLAB, BrainVision, EDF, and Brainstorm formats. + Use :func:`mne.events_from_annotations(raw.annotations) ` + to convert these to events instead of the old way (using STI014 channel synthesis followed by :func:`mne.find_events(raw) `). + + In 0.17 (this release) + Use ``read_raw_...(stim_channel=False)`` to disable warnings (and stim channel synthesis), but other arguments for ``stim_channel`` will still be supported. + + In 0.18 + The only supported option will be ``read_raw_...(stim_channel=False)``, and all stim-channel-synthesis arguments will be removed. At this point, ``stim_channel`` should be removed from scripts for future compatibility, but ``stim_channel=False`` will still be acceptable for backward compatibility. + + In 0.19 + The ``stim_channel`` keyword arguments will be removed from ``read_raw_...`` functions. + +- Calling ``mne.io.pick.pick_info`` removing channels that are needed by compensation matrices (``info['comps']``) no longer raises ``RuntimeException`` but instead logs an info level message. By `Luke Bloy`_ + +- :meth:`mne.Epochs.save` now has the parameter ``fmt`` to specify the desired format (precision) saving epoched data, by `Stefan Repplinger`_, `Eric Larson`_ and `Alex Gramfort`_ + +- Deprecated ``mne.SourceEstimate.morph_precomputed``, ``mne.SourceEstimate.morph``, ``mne.compute_morph_matrix``, ``mne.morph_data_precomputed`` and ``mne.morph_data`` in favor of :func:`mne.compute_source_morph`, by `Tommy Clausner`_ + +- Prepare transition to Python 3. This release will be the last release compatible with Python 2. The next version will be Python 3 only. + +- CUDA support now relies on CuPy_ instead of ``PyCUDA`` and ``scikits-cuda``. It can be installed using ``conda install cupy``. By `Eric Larson`_ + +- Functions requiring a color cycle will now default to Matplotlib rcParams colors, by `Stefan Appelhoff`_ + +- :meth:`mne.Evoked.plot_image` has gained the ability to ``show_names``, and if a selection is provided to ``group_by``, ``axes`` can now receive a `dict`, by `Jona Sassenhagen`_ + +- Calling :meth:`mne.Epochs.decimate` with ``decim=1`` no longer copies the data by `Henrich Kolkhorst`_ + +- Removed blocking (waiting for new epochs) in ``mne.realtime.RtEpochs.get_data()`` by `Henrich Kolkhorst`_ + +- Warning messages are now only emitted as :func:`warnings.warn_explicit` rather than also being emitted as ``logging`` messages (unless a logging file is being used) to avoid duplicate warning messages, by `Eric Larson`_ + +- Deprecated save_stc_as_volume function in favor of :meth:`mne.VolSourceEstimate.as_volume` and :meth:`mne.VolSourceEstimate.save_as_volume` by `Alex Gramfort`_ + +- ``src.kind`` now equals to ``'mixed'`` (and not ``'combined'``) for a mixed source space (made of surfaces and volume grids) by `Alex Gramfort`_ + +- Deprecation of :attr:`mne.io.Raw.annotations` property in favor of :meth:`mne.io.Raw.set_annotations` by `Joan Massich`_ + +- The default value of ``stop_receive_thread`` in ``mne.realtime.RtEpochs.stop`` has been changed to ``True`` by `Henrich Kolkhorst`_ + +- Using the :meth:`mne.io.Raw.add_channels` on an instance with memmapped data will now resize the memmap file to append the new channels on Windows and Linux, by `Eric Larson`_ + +- :attr:`mne.io.Raw.annotations` when missing is set to an empty :class:`mne.Annotations` rather than ``None`` by `Joan Massich`_ and `Alex Gramfort`_ + +- Mismatches in CTF compensation grade are now checked in inverse computation by `Eric Larson`_ + + +Authors +~~~~~~~ + +People who contributed to this release (in alphabetical order): + +* Alexandre Gramfort +* Antoine Gauthier +* Britta Westner +* Christian Brodbeck +* Clemens Brunner +* Daniel McCloy +* David Sabbagh +* Denis A. Engemann +* Eric Larson +* Ezequiel Mikulan +* Henrich Kolkhorst +* Hubert Banville +* Jasper J.F. van den Bosch +* Jen Evans +* Joan Massich +* Johan van der Meer +* Jona Sassenhagen +* Kambiz Tavabi +* Lorenz Esch +* Luke Bloy +* Mainak Jas +* Manu Sutela +* Marcin Koculak +* Marijn van Vliet +* Mikolaj Magnuski +* Peter J. Molfese +* Sam Perry +* Sara Sommariva +* Sergey Antopolskiy +* Sheraz Khan +* Stefan Appelhoff +* Stefan Repplinger +* Steven Bethard +* Teekuningas +* Teon Brooks +* Thomas Hartmann +* Thomas Jochmann +* Tom Dupré la Tour +* Tristan Stenner +* buildqa +* jeythekey diff --git a/mne-python/source/doc/changes/v0.18.rst b/mne-python/source/doc/changes/v0.18.rst new file mode 100644 index 0000000000000000000000000000000000000000..aa9c4b378261556c969caa1f7c2f0669a0589dd5 --- /dev/null +++ b/mne-python/source/doc/changes/v0.18.rst @@ -0,0 +1,268 @@ +.. _changes_0_18: + +Version 0.18 (2019-05-19) +------------------------- + +Changelog +~~~~~~~~~ + +- Add ``event_id='auto'`` in :func:`mne.events_from_annotations` to accommodate Brainvision markers by `Jona Sassenhagen`_, `Joan Massich`_ and `Eric Larson`_ + +- Add example on how to simulate raw data using subject anatomy, by `Ivana Kojcic`_, `Eric Larson`_, `Samuel Deslauriers-Gauthier`_ and `Kostiantyn Maksymenko`_ + +- :func:`mne.beamformer.apply_lcmv_cov` returns static source power after supplying a data covariance matrix to the beamformer filter by `Britta Westner`_ and `Marijn van Vliet`_ + +- Add ``butterfly`` and ``order`` arguments to :func:`mne.viz.plot_epochs` and offer separated traces for non-meg data (seeg, eeg, ecog) in butterfly view by `Stefan Repplinger`_ and `Eric Larson`_ + +- :meth:`mne.Epochs.get_data` now takes a ``picks`` parameter by `Jona Sassenhagen`_ + +- :func:`~mne.viz.plot_compare_evokeds` will generate topo plots if ``axes='topo'`` by `Jona Sassenhagen`_ + +- ``mne.viz.iter_topography`` can yield an additional axis, e.g., for plotting legends by `Jona Sassenhagen`_ and `Daniel McCloy`_ + +- Default plot title reflects channel type when ``picks`` is a channel type in :func:`~mne.viz.plot_compare_evokeds` by `Daniel McCloy`_ + +- Color scale limits in :func:`~mne.viz.plot_topo_image_epochs` are now computed separately per channel type in combined mag/grad plots, by `Daniel McCloy`_ + +- :func:`mne.simulation.simulate_stc` now allows for label overlaps by `Nathalie Gayraud`_, and `Ivana Kojcic`_ + +- Add ``long_format`` option to the pandas dataframe exporters, e.g :meth:`mne.Epochs.to_data_frame` by `Denis Engemann`_ + +- Add example on how to load standard montage :ref:`plot_montage` by `Joan Massich`_ + +- Add new tutorial on :ref:`tut-eeg-fsaverage-source-modeling` by `Alex Gramfort`_, and `Joan Massich`_ + +- Add :meth:`mne.Epochs.apply_hilbert` and :meth:`mne.Evoked.apply_hilbert` by `Eric Larson`_ + +- Add convenience ``fsaverage`` subject dataset fetcher / updater :func:`mne.datasets.fetch_fsaverage` by `Eric Larson`_ + +- Add ``fmin`` and ``fmax`` argument to :meth:`mne.time_frequency.AverageTFR.crop` and to :meth:`mne.time_frequency.EpochsTFR.crop` to crop TFR objects along frequency axis by `Dirk Gütlin`_ + +- Add support to :func:`mne.read_annotations` to read CNT formats by `Joan Massich`_ + +- Add ``reject`` parameter to :meth:`mne.preprocessing.ICA.plot_properties` to visualize rejected epochs by `Antoine Gauthier`_ + +- Add support for picking channels using channel name and type strings to functions with ``picks`` arguments, along with a convenience :meth:`mne.io.Raw.pick`, :meth:`mne.Epochs.pick`, and :meth:`mne.Evoked.pick` method, by `Eric Larson`_ + +- Add new tutorial on :ref:`tut-sleep-stage-classif` by `Alex Gramfort`_, `Stanislas Chambon`_ and `Joan Massich`_ + +- Add data fetchers for polysomnography (PSG) recordings from Physionet (:func:`mne.datasets.sleep_physionet.age.fetch_data` and :func:`mne.datasets.sleep_physionet.temazepam.fetch_data`) by `Alex Gramfort`_ and `Joan Massich`_ + +- Add envelope correlation code in ``mne.connectivity.envelope_correlation`` by `Denis Engemann`_, `Sheraz Khan`_, and `Eric Larson`_ + +- Add option to toggle all projectors in :meth:`mne.io.Raw.plot` and related functions by `Eric Larson`_ + +- Add support for indexing, slicing, and iterating :class:`mne.Annotations` by `Joan Massich`_ + +- :meth:`mne.io.Raw.plot` now uses the lesser of ``n_channels`` and ``raw.ch_names``, by `Joan Massich`_ + +- Add support for FIR filtering in :meth:`mne.io.Raw.plot` and :ref:`mne browse_raw` by passing ``filtorder=0`` or ``--filtorder 0``, respectively, by `Eric Larson`_ + +- Add ``chunk_duration`` parameter to :func:`mne.events_from_annotations` to allow multiple events from a single annotation by `Joan Massich`_ + +- Add :class:`mne.simulation.SourceSimulator` class to simplify simulating SourceEstimates, by `Samuel Deslauriers-Gauthier`_, `Kostiantyn Maksymenko`_, `Nathalie Gayraud`_, `Ivana Kojcic`_, `Alex Gramfort`_, and `Eric Larson`_ + +- :func:`mne.io.read_raw_edf` now detects analog stim channels labeled ``'STATUS'`` and sets them as stim channel. :func:`mne.io.read_raw_edf` no longer synthesize TAL annotations into stim channel but stores them in ``raw.annotations`` when reading by `Joan Massich`_ + +- Add `mne.simulation.add_noise` for ad-hoc noise addition to `io.Raw`, `Epochs`, and `Evoked` instances, by `Eric Larson`_ + +- Add ``drop_refs=True`` parameter to :func:`set_bipolar_reference` to drop/keep anode and cathode channels after applying the reference by `Cristóbal Moënne-Loccoz`_. + +- Add processing of reference MEG channels to :class:`mne.preprocessing.ICA` by `Jevri Hanna`_ + +- Add use of :func:`scipy.signal.windows.dpss` for faster multitaper window computations in PSD functions by `Eric Larson`_ + +- Add :func:`mne.morph_labels` to facilitate morphing label sets obtained from parcellations, by `Eric Larson`_ + +- Add :func:`mne.labels_to_stc` to facilitate working with label data, by `Eric Larson`_ + +- Add :func:`mne.label.select_sources` to simplify the selection of sources within a label, by `Samuel Deslauriers-Gauthier`_ + +- Add support for using :class:`mne.Info` in :func:`mne.simulation.simulate_raw` instead of :class:`mne.io.Raw` by `Eric Larson`_ + +- Add support for passing an iterable and stim channel values using ``stc`` parameter of :func:`mne.simulation.simulate_raw` by `Eric Larson`_ + +- Add ``overlap`` argument to :func:`mne.make_fixed_length_events` by `Eric Larson`_ + +- Add approximate distance-based ``spacing`` source space decimation algorithm to :func:`mne.setup_source_space` by `Eric Larson`_ + +- Add 448-labels subdivided aparc cortical parcellation by `Denis Engemann`_ and `Sheraz Khan`_ + +- Add option to improve rendering in :ref:`mne coreg` for modern graphics cards by `Eric Larson`_ + +- Add ``mne.preprocessing.mark_flat`` to automate marking of flat channels and segments of raw data by `Eric Larson`_ + +- Add support for CUDA-based correlation computations and progress bars in :class:`mne.decoding.ReceptiveField` by `Eric Larson`_ + +- Add support for file-like objects in :func:`mne.io.read_raw_fif` as long as preloading is used by `Eric Larson`_ + +- Add keyboard shortcuts to nativate volume source estimates in time using (shift+)left/right arrow keys by `Mainak Jas`_ + +- Add option to SSP preprocessing functions (e.g., :func:`mne.preprocessing.compute_proj_eog` and :func:`mne.compute_proj_epochs`) to process MEG channels jointly with ``meg='combined'`` by `Eric Larson`_ + +- Add Epoch selection and metadata functionality to :class:`mne.time_frequency.EpochsTFR` using new mixin class by `Keith Doelling`_ + +- Add ``reject_by_annotation`` argument to :func:`mne.preprocessing.find_ecg_events` by `Eric Larson`_ + +- Add ``pca`` argument to return the rank-reduced whitener in :func:`mne.cov.compute_whitener` by `Eric Larson`_ + +- Add ``extrapolate`` argument to :func:`mne.viz.plot_topomap` for better control of extrapolation points placement by `Mikołaj Magnuski`_ + +- Add ``channel_wise`` argument to :func:`mne.io.Raw.apply_function` to allow applying a function on multiple channels at once by `Hubert Banville`_ + +- Add option ``copy='auto'`` to control data copying in :class:`mne.io.RawArray` by `Eric Larson`_ + +- The ``mri`` parameter in :func:`mne.setup_volume_source_space` is now automatically set to ``T1.mgz`` if ``subject`` is provided. This allows to get a :class:`mne.SourceSpaces` of kind ``volume`` more automatically. By `Alex Gramfort`_ + +- Add better ``__repr__`` for constants, and :class:`info['dig'] ` entries via ``DigPoint`` by `Eric Larson`_ + +- Allow string argument in :meth:`mne.io.Raw.drop_channels` to remove a single channel by `Clemens Brunner`_ + +- Add additional depth weighting options for inverse solvers (e.g., :func:`mne.inverse_sparse.gamma_map` and :func:`mne.inverse_sparse.mixed_norm`) by `Eric Larson`_ + +- Add depth weighting to LCMV beamformers via ``depth`` argument in :func:`mne.beamformer.make_lcmv` by `Eric Larson`_ + +- Allow toggling of DC removal in :meth:`mne.io.Raw.plot` by pressing the 'd' key by `Clemens Brunner`_ + +- Improved clicking in :meth:`mne.io.Raw.plot` (left click on trace toggles bad, left click on background sets green line, right click anywhere removes green line) by `Clemens Brunner`_ + +- Add ``mne.realtime.LSLClient`` for realtime data acquisition with LSL streams of data by `Teon Brooks`_ and `Mainak Jas`_ + +- Add partial support for PyVista as a 3D backend using :func:`mne.viz.use_3d_backend` by `Guillaume Favelier`_ + +- Add option ``ids = None`` in :func:`mne.event.shift_time_events` for considering all events by `Nikolas Chalas`_ and `Joan Massich`_ + +- Add ``mne.realtime.MockLSLStream`` to simulate an LSL stream for testing and examples by `Teon Brooks`_ + +- Add support for file-like objects in :func:`mne.read_epochs` as long as preloading is used by `Paul Roujansky`_ + +Bug +~~~ + +- Fix annotations in split fif files :func:`mne.io.read_raw_fif` by `Joan Massich`_ + +- Fix :meth:`mne.Epochs.plot` with ``scalings='auto'`` to properly compute channel-wise scalings by `Stefan Repplinger`_ + +- Fix :func:`mne.gui.coregistration` and :ref:`mne coreg` crashing with segmentation fault when switching subjects by `Eric Larson`_ + +- Fix :func:`mne.io.read_raw_brainvision` to accommodate vmrk files which do not have any annotations by Alexander Kovrig + +- Fix :meth:`mne.io.Raw.plot` and :meth:`mne.Epochs.plot` to auto-scale ``misc`` channel types by default by `Eric Larson`_ + +- Fix filtering functions (e.g., :meth:`mne.io.Raw.filter`) to properly take into account the two elements in ``n_pad`` parameter by `Bruno Nicenboim`_ + +- Fix ``feature_names`` parameter change after fitting in :class:`mne.decoding.ReceptiveField` by `Jean-Rémi King`_ + +- Fix index error in :func:`mne.io.read_raw_cnt` when creating stim_channel manually by `Joan Massich`_ + +- Fix bug with ``weight_norm='unit-gain'`` in :func:`mne.beamformer.make_lcmv` and :func:`mne.beamformer.make_dics` by `Britta Westner`_ + +- Fix 32bits annotations in :func:`mne.io.read_raw_cnt` by `Joan Massich`_ + +- Fix :func:`mne.events_from_annotations` to ignore ``'BAD_'`` and ``'EDGE_'`` annotations by default using a new default ``regexp`` by `Eric Larson`_ + +- Fix bug in ``mne.preprocessing.mark_flat`` where ``raw.first_samp`` was not taken into account by `Evgenii Kalenkovich`_ + +- Fix date parsing in :func:`mne.io.read_raw_cnt` by `Joan Massich`_ + +- Fix topological checks and error messages for BEM surfaces in :func:`mne.make_bem_model` by `Eric Larson`_ + +- Fix default HTML language of :class:`mne.Report` to be ``"en-us"`` instead of ``"fr"`` and allow setting via ``report.lang`` property by `Eric Larson`_ + +- Fix bug where loading epochs with ``preload=True`` and subsequently using :meth:`mne.Epochs.drop_bad` with new ``reject`` or ``flat`` entries leads to improper data (and ``epochs.selection``) since v0.16.0 by `Eric Larson`_. + If your code uses ``Epochs(..., preload=True).drop_bad(reject=..., flat=...)``, we recommend regenerating these data. + +- Fix :ref:`mne flash_bem` to properly utilize ``flash30`` images when conversion from DICOM images is used, and to properly deal with non-standard acquisition affines by `Eric Larson`_ + +- Fix :meth:`mne.io.Raw.set_annotations` with ``annotations=None`` to create an empty annotations object with ``orig_time`` that matches the :class:`mne.io.Raw` instance by `Eric Larson`_ + +- Fix :func:`mne.io.read_raw_edf` returning all the annotations with the same name in GDF files by `Joan Massich`_ + +- Fix boundaries during plotting of raw data with :func:`mne.io.Raw.plot` and :ref:`mne browse_raw` on scaled displays (e.g., macOS with HiDPI/Retina screens) by `Clemens Brunner`_ + +- Fix bug where filtering was not performed with ``lowpass`` or ``highpass`` in :meth:`mne.io.Raw.plot` and :ref:`mne browse_raw` by `Eric Larson`_ + +- Fix :func:`mne.simulation.simulate_evoked` that was failing to simulate the noise with heterogeneous sensor types due to poor conditioning of the noise covariance and make sure the projections from the noise covariance are taken into account `Alex Gramfort`_ + +- Fix checking of ``data`` dimensionality in :class:`mne.SourceEstimate` and related constructors by `Eric Larson`_ + +- Fix :meth:`mne.io.Raw.append` annotations miss-alignment by `Joan Massich`_ + +- Fix hash bug in the ``mne.io.edf`` module when installing on Windows by `Eric Larson`_ + +- Fix :func:`mne.io.read_raw_edf` reading duplicate channel names by `Larry Eisenman`_ + +- Fix :func:`set_bipolar_reference` in the case of generating all bipolar combinations and also in the case of repeated channels in both lists (anode and cathode) by `Cristóbal Moënne-Loccoz`_ + +- Fix missing code for computing the median when ``method='median'`` in :meth:`mne.Epochs.average` by `Cristóbal Moënne-Loccoz`_ + +- Fix CTF helmet plotting in :func:`mne.viz.plot_evoked_field` by `Eric Larson`_ + +- Fix saving of rejection parameters in :meth:`mne.Epochs.save` by `Eric Larson`_ + +- Fix orientations returned by :func:`mne.dipole.get_phantom_dipoles` (half were flipped 180 degrees) by `Eric Larson`_ + +- Fix bug in :func:`mne.viz.plot_compare_evokeds` when ``evoked.times[0] >= 0`` would cause a problem with ``vlines='auto'`` mode by `Eric Larson`_ + +- Fix path bugs in :func:`mne.bem.make_flash_bem` and :ref:`mne flash_bem` by `Eric Larson`_ + +- Fix :meth:`mne.time_frequency.AverageTFR.plot_joint` mishandling bad channels, by `David Haslacher`_ and `Jona Sassenhagen`_ + +- Fix :func:`mne.beamformer.make_lcmv` failing when full rank data is used (i.e., when no projection is done) with ``reg=0.``, by `Eric Larson`_ + +- Fix issue with bad channels ignored in :func:`mne.beamformer.make_lcmv` and :func:`mne.beamformer.make_dics` by `Alex Gramfort`_ + +- Fix :func:`mne.compute_proj_raw` when ``duration != None`` not to apply existing proj and to avoid using duplicate raw data samples by `Eric Larson`_ + +- Fix ``reject_by_annotation`` not being passed internally by :func:`mne.preprocessing.create_ecg_epochs` and :ref:`mne clean_eog_ecg` to :func:`mne.preprocessing.find_ecg_events` by `Eric Larson`_ + +- Fix :func:`mne.io.read_raw_edf` failing when EDF header fields (such as patient name) contained special characters, by `Clemens Brunner`_ + +- Fix :func:`mne.io.read_raw_eeglab` incorrectly parsing event durations by `Clemens Brunner`_ + +- Fix :func:`mne.io.read_raw_egi` when cropping non-preloaded EGI MFF data by `Alex Gramfort`_ + +- Fix :meth:`mne.io.Raw.interpolate_bads` for interpolating CTF MEG channels when reference sensors are present by `jeythekey`_ + +- Fix a bug in :meth:`mne.io.Raw.resample`, where resampling events could result in indices > n_times-1, by `jeythekey`_ + +- Fix :meth:`mne.preprocessing.ICA.score_sources` to use the ``sfreq`` of the raw data to filter rather than the ``sfreq`` when the ICA was fit, by `jeythekey`_ + +- Fix a bug in :class:`mne.preprocessing.ICA`, where manually setting the attribute ``ICA.exclude`` to an np.array resulted in the removal of random components when later also providing the ``exclude`` argument to any ``apply...``-method, by `jeythekey`_ + +- Ascending changed to descending sorting of scores for integer ``..._criterion`` arguments in ``mne.preprocessing.ICA.detect_artifacts`` and ``mne.preprocessing.run_ica``, as it used to be documented; the docstring in these functions was corrected for float ``..._criterion`` arguments, by `jeythekey`_ + +API +~~~ + +- Deprecate ``cov, iir_params, blink, ecg, chpi, random_state`` and support for :class:`mne.io.Raw` instance inputs in :func:`mne.simulation.simulate_raw`; use :func:`mne.simulation.add_noise`, :func:`mne.simulation.add_ecg`, :func:`mne.simulation.add_eog`, and :func:`mne.simulation.add_chpi` by `Eric Larson`_ + +- Add ``overwrite`` parameter in :func:`mne.Epochs.save` by `Katarina Slama`_ + +- Add ``stim_channel`` parameter in :func:`mne.io.read_raw_cnt` to toggle stim channel synthesis by `Joan Massich`_ + +- Python 2 is no longer supported; MNE-Python now requires Python 3.5+, by `Eric Larson`_ + +- A new class :class:`mne.VolVectorSourceEstimate` is returned by :func:`mne.minimum_norm.apply_inverse` (and related functions) when a volume source space and ``pick_ori='vector'`` is used, by `Eric Larson`_ + +- Converting a forward solution with a volume source space to fixed orientation using :func:`mne.convert_forward_solution` now raises an error, by `Eric Larson`_ + +- ``raw.estimate_rank`` has been deprecated and will be removed in 0.19 in favor of :func:`mne.compute_rank` by `Eric Larson`_ + +- :class:`Annotations` are now kept sorted (by onset time) during instantiation and :meth:`~Annotations.append` operations, by `Eric Larson`_ + +- Deprecate ``mne.io.find_edf_events`` by `Joan Massich`_ + +- Deprecate ``limit_depth_chs`` in :func:`mne.minimum_norm.make_inverse_operator` in favor of ``depth=dict(limit_depth_chs=...)`` by `Eric Larson`_ + +- Reading BDF and GDF files with :func:`mne.io.read_raw_edf` is deprecated and replaced by :func:`mne.io.read_raw_bdf` and :func:`mne.io.read_raw_gdf`, by `Clemens Brunner`_ + +- :func:`mne.forward.compute_depth_prior` has been reworked to operate directly on :class:`Forward` instance as ``forward`` rather than a representation scattered across the parameters ``G, is_fixed_ori, patch_info``, by `Eric Larson`_ + +- Deprecate ``method='extended-infomax'`` in :class:`mne.preprocessing.ICA`; Extended Infomax can now be computed with ``method='infomax'`` and ``fit_params=dict(extended=True)`` by `Clemens Brunner`_ + +- Fix support for supplying ``extrapolate`` via :meth:`ica.plot_properties(..., topomap_args=dict(extrapolate=...)) ` by `Sebastian Castano`_ + +- The peak finder that was formerly accessible via ``from mne.preprocessing.peak_finder import peak_finder`` should now be imported directly from the enclosing namespace as ``from mne.preprocessing import peak_finder`` by `Eric Larson`_ + +- Deprecate ``mne.realtime`` module to make a standalone module ``mne-realtime`` that will live outside of this package by `Teon Brooks`_ diff --git a/mne-python/source/doc/changes/v0.19.rst b/mne-python/source/doc/changes/v0.19.rst new file mode 100644 index 0000000000000000000000000000000000000000..5e34210868a8c066c274d1a262ce742bc6b542b7 --- /dev/null +++ b/mne-python/source/doc/changes/v0.19.rst @@ -0,0 +1,232 @@ +.. _changes_0_19: + +Version 0.19 (2019-09-24) +------------------------- + +Changelog +~~~~~~~~~ + +- Add :func:`mne.cuda.set_cuda_device` and config variable ``MNE_CUDA_DEVICE`` to select among multiple GPUs (by numeric device ID) by `Daniel McCloy`_. + +- Add :func:`mne.channels.make_standard_montage` to create :class:`mne.channels.DigMontage` from templates by `Joan Massich`_ and `Alex Gramfort`_. + +- Add :func:`mne.channels.compute_dev_head_t` to compute Device-to-Head transformation from a montage by `Joan Massich`_ and `Alex Gramfort`_. + +- Add :func:`mne.channels.read_dig_fif` to read digitization coordinates from ``.fif`` files by `Joan Massich`_ and `Alex Gramfort`_. + +- Add :func:`mne.channels.read_dig_egi` to read digitization coordinates from EGI ``.xml`` files by `Joan Massich`_ and `Alex Gramfort`_. + +- Add :func:`mne.channels.read_dig_polhemus_isotrak` and :func:`mne.channels.read_polhemus_fastscan` to read Polhemus data by `Joan Massich`_ + +- Add ``mne.channels.read_dig_captrack`` to read BrainVision CapTrak (BVCT) digitization coordinate files by `Stefan Appelhoff`_ and `Joan Massich`_ + +- Add :func:`mne.channels.make_dig_montage` to create :class:`mne.channels.DigMontage` objects out of np.arrays by `Joan Massich`_ + +- Add :func:`mne.channels.read_custom_montage` to read various EEG electrode locations files by `Joan Massich`_ and `Alex Gramfort`_. + +- Add support for making epochs with duplicated events, by allowing three policies: "error" (default), "drop", or "merge" in :class:`mne.Epochs` by `Stefan Appelhoff`_ + +- Allow :meth:`mne.Annotations.crop` to support negative ``tmin`` and ``tmax`` by `Joan Massich`_ + +- Unknown events code in GDF are now visible in the ``event_id`` by `Théodore Papadopoulo`_ + +- Now :func:`mne.io.read_raw_ctf` populates ``raw.annotations`` with the markers in ``MarkerFile.mrk`` if any by `Joan Massich`_ + +- Add options for controlling the use of the ``-T1`` flag and the location of the brainmask output in :ref:`mne watershed_bem` by `Eric Larson`_ + +- Add support to :func:`mne.read_annotations` to read CTF marker files by `Joan Massich`_ + +- Do not convert effective number of averages (``nave`` attribute of :class:`mne.Evoked`) to integer except when saving to FIFF file by `Daniel McCloy`_. + +- Add automatic fiducial position estimation in :ref:`mne coreg` using MNI Talairach fiducial locations in :func:`mne.coreg.get_mni_fiducials` by `Jon Houck`_ and `Eric Larson`_ + +- Add support for :ref:`mne coreg` scaling surrogate subjects without surface reconstructions, such as those created for volumetric analyses only (e.g., with ``recon-all -autorecon1``) by `Eric Larson`_ + +- Add reader for Curry data in :func:`mne.io.read_raw_curry` by `Dirk Gütlin`_ + +- Butterfly channel plots now possible for :meth:`mne.Epochs.plot_psd` with ``average=False``. Infrastructure for this function now shared with analogous Raw function, found in ``mne.viz.utils`` by `Jevri Hanna`_ + +- Add option not to orthogonalize power envelopes with ``orthogonalize=False`` in ``mne.connectivity.envelope_correlation`` by `Denis Engemann`_ + +- Accept filenames of raw .fif files that end in ``_meg.fif`` to enable complicance with the Brain Imaging Data Structure by `Stefan Appelhoff`_ + +- Add function to check the type of a FIF file using :func:`mne.what` and :ref:`mne what` by `Eric Larson`_ + +- Add support for specifying the initial time and/or position and providing a :class:`mne.SourceMorph` instead of :class:`mne.SourceSpaces` in :func:`mne.viz.plot_volume_source_estimates` by `Eric Larson`_ + +- Speed up morph map generation in :func:`mne.read_morph_map` by ~5-10x by using :func:`numba.jit` by `Eric Larson`_ + +- Speed up :func:`mne.setup_volume_source_space`, especially when ``volume_label is not None`` by `Eric Larson`_ + +- Speed up :ref:`mne coreg` interactive and automated (ICP) alignment by using nearest-neighbor calculations in the MRI coordinate frame, by `Eric Larson`_ + +- Add :func:`mne.dig_mri_distances` to compute the distances between digitized head points and the MRI head surface by `Alex Gramfort`_ and `Eric Larson`_ + +- Add scale bars for data channels in :func:`mne.io.Raw.plot` by `Eric Larson`_ + +- Add :func:`mne.viz.plot_brain_colorbar` to plot a colorbar appropriately matched to a :func:`mne.viz.plot_source_estimates` plot by `Eric Larson`_ + +- Add support for showing head surface (to visualize digitization fit) while showing a single-layer BEM to :func:`mne.viz.plot_alignment` by `Eric Larson`_ + +- Add option ``include_tmax=True`` to cropping methods :meth:`mne.io.Raw.crop`, :meth:`mne.Epochs.crop`, :meth:`mne.Evoked.crop`, :meth:`mne.SourceEstimate.crop`, :meth:`mne.Dipole.crop`, and :meth:`mne.time_frequency.AverageTFR.crop` by `Eric Larson`_ + +- Change the behavior of :meth:`mne.io.Raw.plot` for ``scalings='auto'`` and ``remove_dc=True`` to compute the scalings on the data with DC removed by `Clemens Brunner`_ + +- Allow creating annotations within existing annotations in :func:`mne.io.Raw.plot` by default (the old snapping behavior can be toggled by pressing 'p') by `Clemens Brunner`_ + +- Add plotting of rank estimates in :func:`mne.viz.plot_cov` by `Eric Larson`_ + +- Add a new ``mne.viz.plot_sensors_connectivity`` function to visualize the sensor connectivity in 3D by `Guillaume Favelier`_ and `Alex Gramfort`_ + +- Add support for ``info['utc_offset']``, ``info['device_info']``, and ``info['helium_info']`` components of :class:`mne.Info` by `Eric Larson`_ + +- Add control over dipole colors in :func:`mne.viz.plot_dipole_locations` when using orthoview mode by `Eric Larson`_ + +- Use second-order-sections filtering in :meth:`mne.io.Raw.plot` and :ref:`mne browse_raw` by `Eric Larson`_ + +- Add re-referencing functionality for ecog and seeg channel types in :func:`mne.set_eeg_reference` by `Keith Doelling`_ + +- Add support for median averaging and for returning unaggregated segments in ``mne.time_frequency.psd_welch`` by `Richard Höchenberger`_ + +- :func:`io.read_raw_kit`: add support for NYU New York 2019 system update, by `Christian Brodbeck`_ + + +Bug +~~~ + +- Fix setting montage eeg ref position for captrak by `Joan Massich`_ + +- Fix saving raw read from BDF file using ``tmin`` and ``tmax`` using ``preload=False`` by `Alex Gramfort`_ + +- Fix :func:`mne.grand_average` to use equal sum-to-one weights (like it used to, before changes to underlying :func:`mne.combine_evoked`) by `Daniel McCloy`_ + +- Fix :meth:`mne.io.Raw.filter` to deal with instances with no data channels properly by `Eric Larson`_ + +- Fix one-sample baseline issue in :class:`mne.BaseEpochs` when using ``tmin=0`` by `Milan Rybář`_ + +- Fix bug in :func:`mne.viz.plot_volume_source_estimates` where ``'glass_brain'`` MRIs were not transformed to MNI space, by `Eric Larson`_ + +- Fix bug in :func:`mne.viz.plot_volume_source_estimates` where MRIs with voxels not in RAS orientation could not be browsed properly, by `Eric Larson`_ + +- Fix bug in :meth:`mne.SourceMorph.apply` where output STCs had ``stc.vertices`` defined improperly, by `Eric Larson`_ + +- Fix bug in :meth:`mne.SourceMorph.apply` where the default was errantly ``mri_space=False`` instead of ``mri_space=None`` (as documented), by `Eric Larson`_ + +- Fix ``mne.VolVectorSourceEstimate.normal`` and :func:`mne.minimum_norm.apply_inverse` to only allow normal extraction/orientation for surface and discrete source spaces by `Eric Larson`_ + +- Fix :meth:`mne.io.Raw.set_annotations` for ``meas_date`` previous to 1970 by `Joan Massich`_ + +- Fix horizontal spacing issues in :meth:`mne.io.Raw.plot_psd` by `Jevri Hanna`_ + +- Fix reading of dates in BrainVision files if no "New Segment" marker is specified, no date is given, or data is missing, by `Stefan Appelhoff`_ + +- Fix bug with reading one-channel GDF files by `Abram Hindle`_ + +- Fix bug with y-axis labeling in :meth:`mne.io.Raw.plot_psd` by `Eric Larson`_ + +- Fix side-effect where :func:`mne.viz.plot_ica_sources` and :meth:`mne.preprocessing.ICA.plot_sources` changed the ``ICA.exclude`` attribute even when users didn't interact with the plot by `Daniel McCloy`_. + +- Fix scaling of sources in :meth:`ica.plot_sources(epochs) ` by `Eric Larson`_ + +- Fix wrong assumptions about units in BrainVision montages and add test asserting units in "mm" or "auto", by `Stefan Appelhoff`_ + +- Fix scaling issue with signals in mV in EDF files read with :func:`mne.io.read_raw_edf` by `Alex Gramfort`_ + +- Fix :func:`mne.extract_label_time_course` behavior when using STCs generated with ``apply_inverse(..., label=label)`` or ``stc.in_label`` by `Eric Larson`_ + +- Fix bug in :func:`mne.io.read_raw_brainvision` so that recording date timestamps are also recognized if channel reference data is negative, by `Stefan Appelhoff`_ + +- Fix order of ``info['dig']`` that was alphabetical based on channel names and not following the channel order when using :meth:`mne.io.Raw.set_montage` and a ``mne.channels.Montage`` object by `Joan Massich`_ and `Alex Gramfort`_. + +- Fix reading CNT files larger than 2Gb by `Joan Massich`_ + +- Fix reading of 4D/BTi data with different channel names and onsets in :func:`mne.io.read_raw_bti` by `Joshua Bear`_ and `Eberhard Eich`_ + +- Fix formula for effective number of averages in :func:`mne.combine_evoked` when ``weights='equal'`` by `Daniel McCloy`_. + +- Fix bug in :func:`mne.simulation.simulate_stc` to avoid empty stc if label vertices and source space do not intersect, by `Kostiantyn Maksymenko`_ + +- Fix ``event_id='auto'`` in :func:`mne.events_from_annotations` to recover Brainvision markers after saving it in ``.fif`` by `Joan Massich`_ + +- Fix :func:`mne.read_epochs_eeglab` when epochs are stored as float. By `Thomas Radman`_ + +- Fix :func:`mne.Evoked.resample` and :func:`mne.Epochs.resample` not setting ``inst.info['lowpass']`` properly by `Eric Larson`_ + +- Fix checks when constructing volumetric and surface source spaces with :func:`mne.setup_volume_source_space` and :func:`mne.setup_source_space`, respectively, by `Eric Larson`_ + +- Fix bug in handling of :class:`mne.Evoked` types that were not produced by MNE-Python (e.g., alternating average) by `Eric Larson`_ + +- Fix bug in :func:`mne.read_source_estimate` where vector volumetric source estimates could not be read by `Eric Larson`_ + +- Fix bug in :func:`mne.inverse_sparse.mixed_norm` and :func:`mne.inverse_sparse.tf_mixed_norm` where ``weights`` was supplied but ``weights_min`` was not, by `Eric Larson`_ + +- Fix bug in :func:`mne.set_eeg_reference` where non-EEG channels could be re-referenced by default if there were no EEG channels present, by `Eric Larson`_ + +- Fix bug in :func:`mne.io.Raw.plot` when using HiDPI displays and the MacOSX backend of matplotlib by `Eric Larson`_ + +- Fix bug in :func:`mne.viz.plot_compare_evokeds` when using Neuromag 122 system by `Eric Larson`_ + +- Fix bug in :func:`mne.Epochs.plot_psd` when some channels had zero/infinite ``psd`` values causing erroneous error messages by `Luke Bloy`_ + +- Fix :func:`mne.Evoked.decimate` not setting ``inst.first`` and ``inst.last`` properly by `Marijn van Vliet`_ + +- Fix :func:`mne.io.read_raw_brainvision` not handling ``Event`` markers created by PyCorder correctly by `Richard Höchenberger`_ + +- Fix support for string-like objects (such as :class:`python:pathlib.Path`) by `Eric Larson`_ + +- Fix :class:`mne.Report` silently suppressing exceptions when used as a context manager by `Marijn van Vliet`_ + +API +~~~ + +- Deprecate ``mne.channels.Montage`` class, ``mne.channels.read_montage`` and ``mne.channels.read_dig_montage`` function by `Joan Massich`_. + +- Deprecate passing ``Montage``, ``str`` as montage parameter in :meth:`mne.io.Raw.set_montage` by `Joan Massich`_. + +- Deprecate ``set_dig`` parameter in :meth:`mne.io.Raw.set_montage` and ``update_ch_names`` in ``mne.io.RawEEGLAB.set_montage`` when using :class:`mne.channels.DigMontage` as by `Joan Massich`_. + +- Now :meth:`mne.io.Raw.set_montage` raises an error when :class:`mne.channels.DigMontage` contains only a subset of the channels in ``raw.info``. It also adds ``raise_if_subset`` parameter to ensure backward compatibility (defaults to False in 0.19, to True in 0.20, and will be removed in 0.21) by `Joan Massich`_. + +- Minimum dependency versions for the following libraries have been bumped up (by `Eric Larson`_): + + - NumPy: 1.12.1 + - SciPy: 0.18.1 + - matplotlib: 2.0.2 + - scikit-learn: 0.18.2 + - pandas 0.19.2 + +- New boolean parameter ``show_scrollbars`` for :meth:`mne.io.Raw.plot`, :meth:`mne.Epochs.plot`, and :meth:`mne.preprocessing.ICA.plot_sources` (and associated functions) that allows hiding the scrollbars and buttons for a "zen mode" data browsing experience. When the plot window has focus, zen mode can be toggled by pressing :kbd:`z`, by `Daniel McCloy`_. + +- Deprecate ``mne.evoked.grand_average`` in favor of :func:`mne.grand_average` (which works on both :class:`~mne.Evoked` and :class:`~mne.time_frequency.AverageTFR`) by `Daniel McCloy`_ + +- Deprecate ``exclude`` parameter in :func:`mne.viz.plot_ica_sources` and :meth:`mne.preprocessing.ICA.plot_sources`, instead always use the ``exclude`` attribute of the ICA object by `Daniel McCloy`_. + +- Deprecate ``montage`` parameter in favor of the ``set_montage`` method in all EEG data readers :func:`mne.io.read_raw_cnt`, :func:`mne.io.read_raw_egi`, :func:`mne.io.read_raw_edf`, :func:`mne.io.read_raw_gdf`, :func:`mne.io.read_raw_nicolet`, :func:`mne.io.read_raw_eeglab` and :func:`mne.read_epochs_eeglab` by `Alex Gramfort`_ + +- New parameter ``clear`` in :func:`mne.viz.plot_epochs_image` for clearing pre-existing axes before plotting into them by `Daniel McCloy`_ + +- :func:`mne.viz.plot_epochs_image` no longer supports ``group_by='type'`` — combining by channel type is now the default when ``picks`` is a channel type string; to get individual plots for each channel, pass ``picks`` as a list of channel names or indices by `Daniel McCloy`_ + +- New parameter ``combine`` in :func:`mne.viz.plot_compare_evokeds` for specifying method to combine information across channels by `Daniel McCloy`_ + +- FIFF constants related to SmartShield (``*_SMSH_*`` and ``*_SMARTSHIELD``) have been renamed to ``IAS`` for consistency with MEGIN, by `Eric Larson`_ + +- The ``gfp`` parameter of :func:`mne.viz.plot_compare_evokeds` is deprecated; use ``combine='gfp'`` instead by `Daniel McCloy`_ + +- The ``truncate_yaxis='max_ticks'`` parameter of :func:`mne.viz.plot_compare_evokeds` is deprecated; use ``truncate_yaxis='auto'`` instead by `Daniel McCloy`_ + +- The ``truncate_xaxis`` and ``truncate_yaxis`` parameters of :func:`mne.viz.plot_compare_evokeds` now perform one-sided truncation unless both are ``True`` by `Daniel McCloy`_ + +- The ``show_legend`` parameter of :func:`mne.viz.plot_compare_evokeds` is renamed to ``legend`` by `Daniel McCloy`_ + +- :func:`mne.viz.plot_compare_evokeds` always returns a list of figures even when a single figure is generated by `Daniel McCloy`_ + +- Deprecate ``average=True`` and ``spatial_colors=False`` for :func:`mne.Epochs.plot_psd` by `Jevri Hanna`_ + +- :func:`mne.io.read_raw_brainvision` no longer raises an error when there are inconsistencies between ``info['chs']`` and ``montage`` but warns instead by `Joan Massich`_ + +- Add ``update_ch_names`` parameter to ``mne.io.RawEEGLAB.set_montage`` to allow updating the channel names based on the montage by `Joan Massich`_ + +- Reading annotations contained in GDF files with :func:`mne.io.read_raw_gdf` now returns numeric event codes as descriptions (instead of textual descriptions) due to restrictive licensing of the GDF event code table from BioSig by `Clemens Brunner`_ + +- ``channels.find_ch_connectivity`` now returns pre-built neighbor maps for KIT systems when available, by `Christian Brodbeck`_ diff --git a/mne-python/source/doc/changes/v0.2.rst b/mne-python/source/doc/changes/v0.2.rst new file mode 100644 index 0000000000000000000000000000000000000000..528e2a64f883d0bdd9c6139c219e8ed3008e85af --- /dev/null +++ b/mne-python/source/doc/changes/v0.2.rst @@ -0,0 +1,40 @@ +.. _changes_0_2: + +Version 0.2 (2011-11-08) +------------------------ + +Changelog +~~~~~~~~~ + +- New stats functions for FDR correction and Bonferroni by `Alex Gramfort`_. + +- Faster time-frequency using downsampling trick by `Alex Gramfort`_. + +- Support for volume source spaces by `Alex Gramfort`_ (requires next MNE release or nightly). + +- Improved Epochs handling by `Martin Luessi`_ (slicing, drop_bad_epochs). + +- Bug fix in Epochs + ECG detection by Manfred Kitzbichler. + +- New pick_types_evoked function by `Alex Gramfort`_. + +- SourceEstimate now supports algebra by `Alex Gramfort`_. + +API changes summary +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Here are the code migration instructions when upgrading from mne-python +version 0.1: + +- New return values for the function find_ecg_events + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number +of commits): + +* 33 Alexandre Gramfort +* 12 Martin Luessi +* 2 Yaroslav Halchenko +* 1 Manfred Kitzbichler diff --git a/mne-python/source/doc/changes/v0.20.rst b/mne-python/source/doc/changes/v0.20.rst new file mode 100644 index 0000000000000000000000000000000000000000..eb191834ea2eb9ceffc3f65521bb77fc1f8dba3b --- /dev/null +++ b/mne-python/source/doc/changes/v0.20.rst @@ -0,0 +1,407 @@ +.. _changes_0_20: + +Version 0.20 (2020-03-27) +------------------------- + +Changelog +~~~~~~~~~ + +- Improved :func:`mne.viz.plot_epochs` to label epoch counts starting from 0, by `Sophie Herbst`_ + +- Add :func:`minimum_norm.apply_inverse_cov` to compute static power by applying inverse solutions to a data covariance matrix by `Denis Engemann`_, `Luke Bloy`_, and `Eric Larson`_ + +- Add :func:`mne.minimum_norm.resolution_metrics` to compute various resolution metrics for inverse solutions, by `Olaf Hauk`_ + +- Add current source density :func:`mne.preprocessing.compute_current_source_density` to compute the surface Laplacian in order to reduce volume conduction in data by `Alex Rockhill`_ + +- Add :func:`mne.chpi.extract_chpi_locs_ctf` to extract cHPI coil locations from CTF data by `Luke Bloy`_ + +- Add :func:`mne.chpi.compute_chpi_amplitudes`, :func:`mne.chpi.compute_chpi_locs`, and :func:`mne.chpi.compute_head_pos` to compute head positions from cHPI coil locations by `Eric Larson`_ and `Luke Bloy`_ + +- Add ``allow_line_only`` option to :func:`mne.chpi.filter_chpi` to allow filtering line frequencies only in files that do not have cHPI information by `Eric Larson`_ + +- Add :func:`mne.io.Raw.set_meas_date` by `Eric Larson`_ + +- Add :meth:`mne.Epochs.as_type` to allow remapping data in MEG channels to virtual magnetometer or gradiometer channels by `Sophie Herbst`_ and `Alex Gramfort`_ + +- Add ``copy`` parameter to :meth:`mne.Epochs.iter_evoked` by `Alex Gramfort`_ + +- Add command :ref:`mne setup_source_space` to quickly set up bilateral hemisphere surface-based source space with subsampling by `Victor Ferat`_. + +- Add command :ref:`mne sys_info` to print system information by `Eric Larson`_ + +- Add function :func:`mne.make_fixed_length_epochs` to segment raw into fixed length epochs by `Mohammad Daneshzand`_ + +- Add support for computing patch information only in surface source space creation with ``add_dist='patch'`` in :func:`mne.setup_source_space` and ``dist_limit=0`` in :func:`mne.add_source_space_distances` by `Eric Larson`_ + +- Add :class:`mne.Label.restrict` to restrict a label to vertices within a source space by `Eric Larson`_ + +- Add support for passing a destination source space ``src_to`` in :func:`mne.compute_source_morph` to ensure morphing for multiple subjects results in consistent STCs, by `Eric Larson`_ + +- Add support for ``smooth='nearest'`` for surfaces in :func:`mne.compute_source_morph` by `Eric Larson`_ + +- Add support for plotting fNIRS channels in :func:`mne.viz.plot_alignment`, :func:`mne.viz.plot_evoked_topo` and :func:`mne.Evoked.animate_topomap` by `Eric Larson`_ and `Robert Luke`_ + +- Add command line tool :ref:`mne anonymize` for anonymizing raw fiff files by `Luke Bloy`_ + +- Add :func:`mne.preprocessing.find_bad_channels_maxwell` for automatic bad channel detection via Maxwell filtering by `Eric Larson`_ + +- Add support to :func:`mne.io.anonymize_info` to allow time offset to be applied to dates by `Luke Bloy`_ + +- Add support for computing resolution matrix to get point spread functions (PSF) and cross-talk functions (CTF) in :func:`mne.minimum_norm.make_inverse_resolution_matrix`, :func:`mne.beamformer.make_lcmv_resolution_matrix`, :func:`mne.minimum_norm.get_cross_talk`, :func:`mne.minimum_norm.get_point_spread` by `Olaf Hauk`_ + +- Add :func:`mne.preprocessing.read_ica_eeglab` to read EEGLAB ICA decompositions by `Christian O'Reilly`_ + +- Add keyboard functionality to interactive colorbar plotting TFRs by `Stefan Repplinger`_ + +- Add the ability to ``return_event_id`` in :func:`mne.read_events` for use with MNE-C produced ``-annot.fif`` files, by `Eric Larson`_ + +- Add option to ``mne.connectivity.spectral_connectivity`` to compute corrected imaginary PLV by `Adonay Nunes`_ + +- Add :func:`mne.SourceEstimate.estimate_snr` to estimate source-space SNR, by `Kaisu Lankinen`_ and `Padma Sundaram`_ + +- Add option to specify the coordinate frame in :func:`mne.channels.read_custom_montage` by `Eric Larson`_ + +- Add option to use ``match_case=False`` to :meth:`mne.io.Raw.set_montage` and related functions by `Eric Larson`_ + +- Add reader for NIRx data in :func:`mne.io.read_raw_nirx` by `Robert Luke`_ + +- Add function to convert NIRS data to optical density :func:`mne.preprocessing.nirs.optical_density` by `Robert Luke`_ + +- Add function to convert NIRS data to haemoglobin concentration :func:`mne.preprocessing.nirs.beer_lambert_law` by `Robert Luke`_ + +- Add ``fig`` argument to :func:`mne.viz.plot_evoked_field` by `Eric Larson`_ + +- Add functions to calculate spatial information of NIRS channels :func:`mne.preprocessing.nirs.source_detector_distances` and :func:`mne.preprocessing.nirs.short_channels` by `Robert Luke`_ + +- Add reader for ``*.dat`` electrode position files :func:`mne.channels.read_dig_dat` by `Christian Brodbeck`_ + +- Improved :func:`mne.viz.plot_events` to always show event counts by `Eric Larson`_ + +- Improved :ref:`limo-dataset` usage and :ref:`example ` for usage of :func:`mne.stats.linear_regression` by `Jose Alanis`_ + +- Add support for ``reduce_rank=True`` for vector beamformers by `Eric Larson`_ + +- Add ``method='sphere'`` support for using Freesurfer spherical inflation in :func:`mne.decimate_surface` to facilitate mesh downsampling for use with :func:`mne.make_bem_model` by `Eric Larson`_ + +- Speed up :func:`mne.beamformer.make_lcmv` and :func:`mne.beamformer.make_dics` calculations by vectorizing linear algebra calls by `Dmitrii Altukhov`_ and `Eric Larson`_ + +- Speed up :func:`mne.make_forward_solution` using Numba, by `Eric Larson`_ + +- Speed up :func:`mne.io.read_raw_fif` data reading when the recording is long and there are many data tags repeatedly accessed, by `Eric Larson`_ + +- For KIT systems without built-in layout, :func:`mne.channels.find_layout` now falls back on an automatically generated layout, by `Christian Brodbeck`_ + +- :meth:`mne.Epochs.plot` now takes a ``epochs_colors`` parameter to color specific epoch segments by `Mainak Jas`_ + +- Add command :ref:`mne setup_forward_model` to quickly create a BEM model for a subject by `Victor Ferat`_. + +- Add command :ref:`mne prepare_bem_model` to quickly create a BEM solution using the linear collocation approach by `Victor Ferat`_. + +- Add support for reading ``.bdip`` Xfit binary dipole fit files in :func:`mne.read_dipole` by `Eric Larson`_ + +- Allow returning vector source estimates from sparse inverse solvers through ``pick_ori='vector'`` by `Christian Brodbeck`_ + +- Add NIRS support to :func:`mne.viz.plot_topomap` and :func:`mne.viz.plot_ica_components` by `Robert Luke`_ + +- Add the ability to :func:`mne.channels.equalize_channels` to also re-order the channels and also operate on instances of :class:`mne.Info`, :class:`mne.Forward`, :class:`mne.Covariance` and :class:`mne.time_frequency.CrossSpectralDensity` by `Marijn van Vliet`_ + +- Allow `mne.channels.read_custom_montage` to handle fiducial points for BESA spherical (``.elp``) files by `Richard Höchenberger`_ + +- Add ``rank`` argument to :func:`mne.fit_dipole` by `Eric Larson`_ + +- Add function to convert events to annotations :func:`mne.annotations_from_events` by `Nicolas Barascud`_ + +- Add function to calculate scalp coupling index for fNIRS data :func:`mne.preprocessing.nirs.scalp_coupling_index` by `Robert Luke`_ + +- Add ``item`` argument to :meth:`mne.Epochs.get_data` for faster access to NumPy data arrays compared to :meth:`mne.Epochs.__getitem__` for frequent access on large :class:`mne.Epochs` objects, by `Eric Larson`_ + +- More accurate coordinate system for Easycap montages in :func:`mne.channels.make_standard_montage` by `Christian Brodbeck`_ + +- Add ``border`` argument to :func:`mne.viz.plot_topomap`. ``border`` controls the value of the edge points to which topomap values are extrapolated. ``border='mean'`` sets these points value to the average of their neighbours. By `Mikołaj Magnuski`_ + +- Add function :func:`mne.viz.link_brains` to link time properties of multiple brain objects interactively by `Guillaume Favelier`_ + +- Add function :func:`mne.preprocessing.annotate_movement` to annotate periods with head motion and :func:`mne.preprocessing.compute_average_dev_head_t` to re-estimate the device to head transform with average head position during segments with acceptable head movement. by `Adonay Nunes`_ + +- Make selected channels more distinguishable in :meth:`mne.Epochs.plot_sensors` when using ``kind='select'`` by `Mikołaj Magnuski`_ + +- Allow retrieval of the number of Infomax ICA iterations via the new ``return_n_iter`` keyword argument of :func:`mne.preprocessing.infomax` by `Richard Höchenberger`_ + +- Expose the number of ICA iterations during the fitting procedure via the ``n_iter_`` attribute of :class:`mne.preprocessing.ICA` by `Richard Höchenberger`_ + +- :func:`mne.grand_average` now produces a warning when only a single dataset was passed, instead of raising an error by `Richard Höchenberger`_ + +- Add ``nrows`` and ``ncols`` parameters to :func:`mne.viz.plot_evoked_topomap`, which allows to create multiline topomap plots for Evoked. By `Federico Raimondo`_ + +- Improve repr of :class:`mne.Info` (empty items are not shown anymore) by `Clemens Brunner`_ + +Bug +~~~ + +- Fix the ``reduce_rank`` parameter in :func:`mne.beamformer.make_lcmv` and :func:`mne.beamformer.make_dics` to reduce the rank of the leadfield first before then reducing the rank of the denominator of the beamformer formula for the inversion by `Britta Westner`_ and `Eric Larson`_. + +- Fix bug with :func:`mne.beamformer.make_lcmv` with data where rank was incorrectly checked by `Eric Larson`_. + +- Allow :func:`mne.channels.read_dig_hpts` to accept point categories (eg. EEG) to be specified in upper case by `Alex Gramfort`_. + +- Fix a bug in ``mne.MixedSourceEstimate.plot_surface`` that prevented plotting in latest PySurfer by `Christian O'Reilly`_. + +- Fix ``method='eLORETA'`` in :func:`mne.minimum_norm.apply_inverse`, by `Eric Larson`_: + + 1. regularization, which was off by roughly a factor of a square root + 2. units, which are now nAm instead of being arbitrary + 3. explained variance and residuals, which were previously unavailable + 4. ``force_equal`` in the case of loose orientations, which previously + defaulted to ``True`` now defaults to ``False``. + Reapplying orientation priors at each iteration of the algorithm + sufficiently preserves a smooth transition between loose=0. to loose=1. + without compromising localization accuracy in testing. + +- Fix bug in ``method='eLORETA'`` for :func:`mne.minimum_norm.apply_inverse` (and variants) to allow restricting source estimation to a label by `Luke Bloy`_ + +- Fix bug in :func:`mne.compute_covariance` and :func:`mne.compute_raw_covariance` where biased normalization (based on degrees of freedom) was used and ``cov.nfree`` was not set properly by `Eric Larson`_ + +- Fix ``mne.VectorSourceEstimate.normal`` to account for cortical patch statistics using ``use_cps=True`` by `Eric Larson`_ + +- Fix ``pick_ori='normal'`` for :func:`mne.minimum_norm.apply_inverse` when the inverse was computed with ``loose=1.`` and the forward solution was not in surface orientation, by `Eric Larson`_ + +- Fix missing xlabel for :func:`mne.io.Raw.plot_psd` and similar functions when passing a subset of axes from a figure by `Alex Gramfort`_ + +- Fix wrong DataFrame index when ``index=None`` in methods :meth:`mne.io.Raw.to_data_frame`, :meth:`mne.Epochs.to_data_frame`, :meth:`mne.Evoked.to_data_frame`, and :meth:`mne.SourceEstimate.to_data_frame`, by `Daniel McCloy`_. + +- Fix incorrect scaling of cluster temporal extent in :func:`mne.stats.summarize_clusters_stc` by `Daniel McCloy`_. + +- Fix :func:`mne.time_frequency.read_tfrs` to properly read :class:`~mne.Info` transforms by `Eric Larson`_ + +- Fix :func:`mne.viz.plot_sensors` to always plot in head coordinate frame by `Daniel McCloy`_. + +- Fix :func:`mne.io.read_raw_cnt` for version 1 of format in the presence of annotations by `Alex Gramfort`_. + +- Fix :class:`mne.decoding.GeneralizingEstimator` and related classes to support multi-class sklearn scorers such as ``'roc_auc_ovo'`` and ``'roc_auc_ovo_weighted'`` by `Eric Larson`_ + +- Fix :meth:`mne.io.read_raw_ctf` to set measurement date from CTF ds files by `Luke Bloy`_. + +- Fix :meth:`mne.read_epochs_eeglab` that ignored channel locations by `Alex Gramfort`_. + +- Fix :func:`mne.io.read_raw_brainvision` when channel names have spaces by `Sebastian Major`_. + +- Fix :func:`mne.io.read_raw_brainvision` when ``"Core"`` is in the data header by `Eric Larson`_ + +- Fix :meth:`mne.io.Raw.anonymize` to correctly reset ``raw.annotations.orig_time`` by `Luke Bloy`_. + +- Fix :meth:`mne.io.Raw.anonymize` to correctly avoid shifting ``raw.annotations.onset`` relative to ``raw.first_samp`` by `Eric Larson`_ + +- Fix :meth:`mne.io.Raw.set_channel_types` and :meth:`mne.io.Raw.rename_channels` and related methods to return the instance instead of ``None`` by `Eric Larson`_ + +- :meth:`mne.Epochs.iter_evoked` now does not return a copy of info when ``copy=False`` (default parameter) by `Alex Gramfort`_ + +- The attribute :class:`mne.Annotations.orig_time ` is now read-only, and is a :class:`~python:datetime.datetime` object (or None) rather than float, by `Eric Larson`_ + +- Fix bug where MRI distances were not properly initialized in :ref:`mne coreg` by `Eric Larson`_ + +- Fix ``xscale='log'`` in :meth:`mne.io.Raw.plot_psd` and related functions by `Alex Gramfort`_ + +- Unify behavior of ``raw.annotations.append(...)`` when ``raw.info['meas_date']`` is None to make onsets absolute relative to ``first_samp`` as they are when ``raw.info['meas_date']`` is not None; i.e., you might need to do ``raw.annotations.append(old_time + raw.first_time)``, by `Eric Larson`_ + +- The :class:`info['meas_date'] ` entry is now a :class:`~python:datetime.datetime` object (or None) rather than float, by `Eric Larson`_ + +- Fix :meth:`mne.time_frequency.AverageTFR.save` and related functions to deal with :class:`~python:datetime.datetime` objects properly by `Eric Larson`_ + +- Fix date reading before Unix time zero (1970 Jan 1) on Windows by `Alex Rockhill`_. + +- Fix bug running subprocesses (e.g., in :func:`mne.bem.make_watershed_bem`) in Jupyter notebooks, by `Eric Larson`_ + +- Fix :meth:`mne.io.read_raw_artemis123` to add HPI locations to digitization points, by `Luke Bloy`_ + +- Fix :meth:`mne.Epochs.shift_time` and :meth:`mne.Evoked.shift_time` to return the modified :class:`~mne.Epochs` or :class:`~mne.Evoked` instance (instead of ``None``) by `Daniel McCloy`_. + +- Fix :func:`mne.read_annotations` for text files with zero or one annotations, by `Adonay Nunes`_ + +- Fix bug in :class:`~mne.preprocessing.ICA` where requesting extended infomax via ``fit_params={'extended': True}`` was overridden, by `Daniel McCloy`_. + +- Fix bug in :meth:`mne.Epochs.interpolate_bads` where the ``origin`` was not used during MEG or EEG data interpolation by `Eric Larson`_. Old behavior can be achieved using ``origin=(0., 0., 0.)`` for EEG and ``origin=(0., 0., 0.04)`` for MEG, and the new default is ``origin='auto'``, which uses a head-digitization-based fit. + +- Fix bug in :func:`mne.write_evokeds` where ``evoked.nave`` was not saved properly when multiple :class:`~mne.Evoked` instances were written to a single file, by `Eric Larson`_ + +- Fix bug in ``mne.preprocessing.mark_flat`` where acquisition skips were not handled properly, by `Eric Larson`_ + +- Fix bug in :func:`mne.viz.plot_bem` where some sources were not plotted by `Jean-Rémi King`_ and `Eric Larson`_ + +- Fix TAL channel parsing (annotations) for EDF-D files by `Clemens Brunner`_ + +- Fix bug with :func:`mne.viz.plot_dipole_locations` when plotting in head coordinates by `Eric Larson`_ + +- Fix handling in cases where no components are found in :func:`mne.preprocessing.corrmap` by `Eric Larson`_ + +- Fix handling of repeated events in :class:`mne.Epochs` by `Fahimeh Mamashli`_ and `Alex Gramfort`_ + +- Fix many bugs with plotting sensors overlaid on a head outline. All plotting is now done in head coordinates and scaled by ``head_radius``, which defaults to 0.095, by `Eric Larson`_ + +- Fix :func:`mne.io.anonymize_info` to allow shifting dates of service and to match anticipated changes in mne-cpp by `Luke Bloy`_ + +- Fix reading of cardinals in .htps files (identifier are int not strings) by `Alex Gramfort`_ + +- Fix IO of TFRs when event_id contain a / in one of the keys by `Alex Gramfort`_ + +- Fix plotting of TFRs with linear y-scale (misaligned frequency bins), by `Stefan Repplinger`_ and `Eric Larson`_ + +- Fix ``info['sfreq']`` when decimating in :func:`mne.time_frequency.tfr_multitaper` and :func:`mne.time_frequency.tfr_morlet` and make sure an error is raised when exceed Nyquist frequency by `Adonay Nunes`_ + +- Fix bug in EDF(+) loading, filter values ignored by insufficient regex, by `Demetres Kostas`_ + +- Fix missing scaling of tolerance parameter in :func:`mne.inverse_sparse.tf_mixed_norm` and :func:`mne.inverse_sparse.mixed_norm`, by `Mathurin Massias`_ + +- Fix the automatic scaling of the glyphs in :func:`mne.viz.plot_vector_source_estimates` by using 10% of the brain width, by `Guillaume Favelier`_ + +- Fix handling of missing values (NaNs) in ``mne.time_frequency.psd_welch`` by `Clemens Brunner`_ + +- Fix :class:`mne.decoding.LinearModel` to support the refitted estimator of ``GridSearchCV`` in ``sklearn`` by `Chun-Hui Li`_ + +- Fix :func:`mne.viz.plot_topomap` when there are bad channels in the provided :class:`mne.Info` instance by `Eric Larson`_ + +- Fix check for subject definition existing in source space in :func:`mne.compute_source_morph` and related functions by `Eric Larson`_ + +- Fix creation of new figures in :meth:`mne.Epochs.plot_image` and :func:`mne.viz.plot_epochs_image` by `Eric Larson`_ + +- Fix bug in :class:`~mne.preprocessing.Xdawn` where filters where selected along the incorrect axis, by `Henrich Kolkhorst`_ + +- Fix bug in :func:`mne.bem.make_watershed_bem` where some surfaces were saved incorrectly in the working directory by `Yu-Han Luo`_ + +- Fix support for multiple TAL (annotations) channels in BDF reader by `Clemens Brunner`_ + +- Fix missing ``brainmask`` file type in :func:`mne.bem.make_watershed_bem` by changing its default value to ``ws.mgz`` by `Fu-Te Wong`_ + +- Fix bug in :func:`mne.channels.make_standard_montage` which would return ``easycap-M1`` even when requesting ``easycap-M10`` by `Christian Brodbeck`_ + +- Fix the way planar gradiometers are combined in :func:`mne.viz.plot_tfr_topomap` and :meth:`mne.Epochs.plot_psd_topomap` by `Geoff Brookshire`_ + +- Improve error message when trying to load FieldTrip data from a cell array by `Thomas Hartmann`_ + +- Fix bug in :func:`mne.read_evoked_fieldtrip` causing it to crash when channels were present in the provided Info object but were not present in the data by `Thomas Hartmann`_ + +- Fix placement of extrapolation points in :meth:`mne.Evoked.plot_topomap` and related functions when exactly three channels were used by `Mikołaj Magnuski`_. + +- Fix bug in reading annotations in :func:`read_annotations`, which would not accept ";" character by `Adam Li`_ + +- Fix bug in :func:`mne.Report.parse_folder`, which would not recognize ``*meg.fif`` files by `Dmitrii Altukhov`_. + +- Include ``fit_params`` when saving an :class:`~mne.preprocessing.ICA` instance to disk by `Richard Höchenberger`_ + +- Update old url link in :func:`mne.datasets.eegbci.load_data` to ``EEGMI_URL = 'https://physionet.org/files/eegmmidb/1.0.0/'`` by `Ramiro Gatti`_ + +- Ensure corrected p-values calculated by :func:`mne.stats.bonferroni_correction` never exceed the value of 1.0 by `Richard Höchenberger`_ + +API +~~~ + +- ``mne.io.pick.get_channel_types`` is now called ``mne.io.pick.get_channel_type_constants`` to better reflect its return values, by `Daniel McCloy`_. + +- :meth:`mne.Evoked.as_type` now returns an instance of :class:`mne.EvokedArray` by `Sophie Herbst`_ and `Alex Gramfort`_ + +- Bumped minimum requirements to fall 2017 versions by `Eric Larson`_: + + - NumPy 1.13.3 + - SciPy 1.0.0 + - matplotlib 2.1 + - scikit-learn 0.19.1 (optional requirement) + - pandas 0.21 (optional requirement) + +- :meth:`mne.Epochs.plot` now accepts an ``event_id`` parameter (useful in tandem with ``event_colors`` for specifying event colors by name) by `Daniel McCloy`_. + +- Passing ``ch_types=None`` has been deprecated in favor of explicitly passing ``ch_types='misc'`` in :func:`mne.create_info` by `Eric Larson`_ + +- New time conversion options for methods :meth:`mne.io.Raw.to_data_frame`, :meth:`mne.Epochs.to_data_frame`, :meth:`mne.Evoked.to_data_frame`, and :meth:`mne.SourceEstimate.to_data_frame`, by `Daniel McCloy`_. + +- :meth:`mne.Epochs.shift_time` and :meth:`mne.Evoked.shift_time` now allow shifting times by arbitrary amounts (previously only by integer multiples of the sampling period), by `Daniel McCloy`_ and `Eric Larson`_. + +- The ``head_pos`` argument of :func:`mne.Evoked.plot_topomap` and related functions has been deprecated in favor of ``head_radius``, by `Eric Larson`_. + +- The ``layout`` argument to topomap-related functions such as :meth:`mne.Evoked.plot_topomap` and :func:`mne.viz.plot_tfr_topomap` has been deprecated in favor of channel-position based flattening based on the ``info`` and ``sphere`` argument, by `Eric Larson`_. + +- The APIs of :meth:`mne.io.Raw.plot_projs_topomap`, :meth:`mne.Epochs.plot_projs_topomap` and :meth:`mne.Evoked.plot_projs_topomap` are now more similar to :func:`mne.viz.plot_projs_topomap` by `Daniel McCloy`_. + +- The function :func:`mne.setup_volume_source_space` has a ``sphere_units`` argument that defaults to ``'mm'`` in 0.20 but will change to ``'m'`` in 0.21, set it to avoid a warning by `Eric Larson`_. + +- :func:`mne.viz.plot_projs_topomap` and the related methods :meth:`mne.io.Raw.plot_projs_topomap`, :meth:`mne.Epochs.plot_projs_topomap` and :meth:`mne.Evoked.plot_projs_topomap` now accept parameter ``vlim`` to control the colormap, with keyword ``'joint'`` computing the colormap jointly across all projectors of a given channel type, by `Daniel McCloy`_. + +- New methods :meth:`mne.io.Raw.get_channel_types`, :meth:`mne.Epochs.get_channel_types`, :meth:`mne.Evoked.get_channel_types` by `Daniel McCloy`_. + +- Deprecate ``mne.minimum_norm.point_spread_function`` and ``mne.minimum_norm.cross_talk_function`` by `Alex Gramfort`_ + +- Deprecate ``montage`` parameter of :func:`mne.create_info` in favor of :meth:`mne.io.Raw.set_montage`, :meth:`mne.Info.set_montage`, and related functions by `Eric Larson`_ + +- :func:`mne.channels.equalize_channels` no longer operates in-place by default, but instead makes copies of the objects when necessary (see ``copy`` parameter) by `Marijn van Vliet`_ + +- :func:`mne.channels.equalize_channels` now uses the first object in the list as a template for channel ordering by `Marijn van Vliet`_ + +- :func:`mne.channels.equalize_channels` now also re-orders the channels to match, in addition to dropping channels that are not shared by all objects by `Marijn van Vliet`_ + +- :meth:`mne.io.Raw.pick_channels`, :meth:`mne.Epochs.pick_channels` and :meth:`mne.Evoked.pick_channels` now have an ``ordered`` parameter to enforce the ordering of the picked channels by `Marijn van Vliet`_ + +- New methods :meth:`mne.Forward.pick_channels`, :meth:`mne.Covariance.pick_channels`, ``mne.Info.pick_channels``, :meth:`mne.time_frequency.CrossSpectralDensity.pick_channels` by `Marijn van Vliet`_ + +- New attributes ``mne.Forward.ch_names`` and ``mne.Info.ch_names`` by `Marijn van Vliet`_ + +- In :class:`~mne.preprocessing.Xdawn`, the components are stored in the rows of attributes ``filters_`` and ``patterns_`` to be consistent with :class:`~mne.decoding.CSP` and :class:`~mne.preprocessing.ICA` by `Henrich Kolkhorst`_ + +- Drop ``unit`` keyword argument from :func:`mne.channels.read_custom_montage`, as it was unused by `Richard Höchenberger`_ + +- Deprecate ``mne.preprocessing.run_ica``, use ``mne.preprocessing.ICA.detect_artifacts`` instead by `Richard Höchenberger`_ + +Authors +~~~~~~~ + +People who contributed to this release (in alphabetical order): + +* Adam Li +* Adonay Nunes +* Alex Rockhill +* Alexandre Gramfort +* Ariel Rokem +* Britta Westner +* Carlos de la Torre +* Christian Brodbeck +* Christian O'Reilly +* Chun-Hui Li +* Clemens Brunner +* Daniel McCloy +* Demetres Kostas +* Denis A. Engemann +* Dmitrii Altukhov +* Dominik Welke +* Eric Larson +* Ezequiel Mikulan +* Fahimeh Mamashli +* Fede Raimondo +* Fu-Te Wong +* Geoff Brookshire +* Guillaume Favelier +* Henrich Kolkhorst +* Joan Massich +* José C. García Alanis +* Jussi Nurminen +* Kaisu Lankinen +* Luke Bloy +* Mainak Jas +* Marijn van Vliet +* Mathurin Massias +* Mikolaj Magnuski +* Mohamed Sherif +* Mohammad Daneshzand +* Nataliia Kozhemiako +* Nicolas Barascud +* Nicolas Legrand +* Olaf Hauk +* Padma Sundaram +* Ramiro Gatti +* Richard Höchenberger +* Robert Luke +* Robert Oostenveld +* Sebastian Major +* Sophie Herbst +* Stefan Appelhoff +* Stefan Repplinger +* Thomas Hartmann +* Victor Férat +* Yu-Han Luo diff --git a/mne-python/source/doc/changes/v0.21.rst b/mne-python/source/doc/changes/v0.21.rst new file mode 100644 index 0000000000000000000000000000000000000000..2f2fa201a3c1911b493d07f45e6e041cf6670c2b --- /dev/null +++ b/mne-python/source/doc/changes/v0.21.rst @@ -0,0 +1,486 @@ +.. _changes_0_21: + +Version 0.21 (2020-09-21) +------------------------- + +.. |Rahul Nadkarni| replace:: **Rahul Nadkarni** +.. |Lau Møller Andersen| replace:: **Lau Møller Andersen** +.. |Kyle Mathewson| replace:: **Kyle Mathewson** +.. |Jan Sedivy| replace:: **Jan Sedivy** +.. |Johann Benerradi| replace:: **Johann Benerradi** +.. |Martin Schulz| replace:: **Martin Schulz** +.. |Jeroen Van Der Donckt| replace:: **Jeroen Van Der Donckt** +.. |Simeon Wong| replace:: **Simeon Wong** +.. |Svea Marie Meyer| replace:: **Svea Marie Meyer** +.. |Lx37| replace:: **Lx37** +.. |Liberty Hamilton| replace:: **Liberty Hamilton** +.. |Steven Bierer| replace:: **Steven Bierer** + +Enhancements +~~~~~~~~~~~~ + +- Modified :meth:`mne.Epochs.pick_types` to remove dropped channel types from ``reject`` and ``flat`` dictionaries **by new contributor** |Rahul Nadkarni|_ + +- Add function :func:`mne.preprocessing.regress_artifact` to remove artifacts using linear regression **by new contributor** |Kyle Mathewson|_ and `Eric Larson`_ + +- Add ``sources`` and ``detectors`` options for fNIRS use of :meth:`mne.viz.plot_alignment` allowing plotting of optode locations in addition to channel midpoint ``channels`` and ``path`` between fNIRS optodes **by new contributor** |Kyle Mathewson|_ + +- BrainVision data format files are now parsed for EEG impedance values in :func:`mne.io.read_raw_brainvision` and provided as a ``.impedances`` attribute of ``raw`` **by new contributor** |Jan Sedivy|_ and `Stefan Appelhoff`_ + +- Add function :func:`mne.channels.combine_channels` to combine channels from Raw, Epochs, or Evoked according to ROIs (combinations including mean, median, or standard deviation; can also use a callable) **by new contributor** |Johann Benerradi|_ + +- Improved documentation building instructions and execution on Windows **by new contributor** |Martin Schulz|_, `Evgenii Kalenkovich`_, and `Eric Larson`_ + +- Speed up reading of annotations in EDF+ files **by new contributor** |Jeroen Van Der Donckt|_ + +- Add head to mri and mri to voxel space transform details to :ref:`tut-source-alignment` tutorial, by `Alex Rockhill`_ + +- Improve memory efficiency of :func:`mne.concatenate_epochs` by `Eric Larson`_ + +- Allow picking channels in raw instances (e.g., :meth:`mne.io.Raw.pick_types`) without preloading data, by `Eric Larson`_ + +- :meth:`mne.preprocessing.ICA.plot_sources` now plots annotation markers similar to :meth:`mne.io.Raw.plot` by `Luke Bloy`_ + +- Add support for scalar multiplication and division of :class:`mne.time_frequency.AverageTFR` instances by `Luke Bloy`_ + +- Add support for signals in mV for :func:`mne.io.read_raw_brainvision` by `Clemens Brunner`_ + +- :meth:`mne.Epochs.plot_psd_topomap` and :func:`mne.viz.plot_epochs_psd_topomap` now allow joint colorbar limits across subplots, by `Daniel McCloy`_. + +- Add support for using loose-orientation surface priors with free-orientation volume priors in mixed source space inverses by `Eric Larson`_ + +- Add :class:`mne.MixedVectorSourceEstimate` for vector source estimates for mixed source spaces, by `Eric Larson`_ + +- Add mixed and volumetric source estimate plotting using volumetric ray-casting to :meth:`mne.MixedSourceEstimate.plot` and :meth:`mne.VolSourceEstimate.plot_3d` by `Eric Larson`_ + +- Add :meth:`mne.MixedSourceEstimate.surface` and :meth:`mne.MixedSourceEstimate.volume` methods to allow surface and volume extraction by `Eric Larson`_ + +- Add :meth:`mne.VectorSourceEstimate.project` to project vector source estimates onto the direction of maximum source power by `Eric Larson`_ + +- Add support to :func:`mne.extract_label_time_course` for vector-valued and volumetric source estimates by `Eric Larson`_ + +- Add method :meth:`mne.VolSourceEstimate.in_label` by `Eric Larson`_ + +- Add support for mixed source spaces to :func:`mne.compute_source_morph` by `Eric Larson`_ + +- Add support for volume and mixed source spaces to :func:`mne.stats.summarize_clusters_stc` by `Eric Larson`_ + +- Add support for omitting the SDR step in volumetric morphing by passing ``n_iter_sdr=()`` to `mne.compute_source_morph` by `Eric Larson`_ + +- Add ``single_volume`` argument to :func:`mne.setup_volume_source_space` to facilitate creating source spaces with many volumes (e.g., all subvolumes of ``aseg.mgz``) by `Eric Larson`_ + +- Add support for passing a string argument to ``bg_img`` in `mne.viz.plot_volume_source_estimates` by `Eric Larson`_ + +- Add support for providing the destination surface source space in the ``src_to`` argument of :func:`mne.compute_source_morph` by `Eric Larson`_ + +- Add explained variance logging to :func:`mne.inverse_sparse.mixed_norm`, :func:`mne.inverse_sparse.gamma_map`, and :func:`mne.beamformer.rap_music` by `Eric Larson`_ + +- Add ``tol_kind`` option to :func:`mne.compute_rank` by `Eric Larson`_ + +- Allow resampling raw data with :func:`mne.io.Raw.resample` without preloading data, by `Eric Larson`_ + +- Allow using ``pick_ori='vector'`` with a fixed-orientation inverse to facilitate visualization with :func:`mne.viz.plot_vector_source_estimates` by `Eric Larson`_ + +- :func:`mne.viz.plot_dipole_locations` and :meth:`mne.Dipole.plot_locations` gained a ``title`` argument to specify a custom figure title in ``orthoview`` mode by `Richard Höchenberger`_ + +- Add orientations projected onto the MRI slices in :func:`mne.viz.plot_dipole_locations` in ``'orthoview'`` mode by `Eric Larson`_ + +- Add temporal derivative distribution repair (TDDR) :func:`mne.preprocessing.nirs.temporal_derivative_distribution_repair` with shortened alias ``mne.preprocessing.nirs.tddr`` by `Robert Luke`_ + +- Add :func:`mne.read_freesurfer_lut` to make it easier to work with volume atlases by `Eric Larson`_ + +- Add support for overlap-add processing when ``method='spectrum_fit'`` in :func:`mne.io.Raw.notch_filter` by `Eric Larson`_ + +- Add functionality to interpolate bad NIRS channels by `Robert Luke`_ + +- Add ability to interpolate EEG channels using minimum-norm projection in :meth:`mne.io.Raw.interpolate_bads` and related functions with ``method=dict(eeg='MNE')`` by `Eric Larson`_ + +- Added ability of :func:`mne.io.read_raw_nirx` to open data by passing path to header file `Robert Luke`_ + +- Add :meth:`mne.channels.DigMontage.rename_channels` to allow renaming montage channels by `Eric Larson`_ + +- Document :meth:`mne.channels.compute_native_head_t` to allow computing the native-to-head transformation that will be applied when doing :meth:`raw.set_montage ` and related functions by `Eric Larson`_ + +- Add support to in :meth:`mne.io.Raw.plot` for passing ``clipping`` as a float to clip to a proportion of the dedicated channel range by `Eric Larson`_ + +- Add function :func:`mne.preprocessing.annotate_muscle_zscore` to annotate periods with muscle artifacts. by `Adonay Nunes`_ + +- Add :func:`mne.stats.ttest_ind_no_p` to mirror :func:`mne.stats.ttest_1samp_no_p` with hat correction by `Eric Larson`_ + +- Add `mne.stats.combine_adjacency` to combine adjacency matrices for independent data dimensions to enable things like spatio-temporal-time-frequency clustering in `mne.stats.permutation_cluster_test` by `Eric Larson`_ + +- Speed up raw data reading without preload in :func:`mne.io.read_raw_nirx` by `Eric Larson`_ + +- Speed up :meth:`mne.Epochs.copy` and :meth:`mne.Epochs.__getitem__` by avoiding copying immutable attributes by `Eric Larson`_ + +- Speed up and reduce memory usage of :meth:`mne.SourceEstimate.plot` and related functions/methods when ``show_traces=True`` by `Eric Larson`_ + +- Reduce memory usage of `~mne.io.Raw.plot_psd`, ``mne.time_frequency.psd_welch``, and `~mne.time_frequency.psd_array_welch` for long segments of data by `Eric Larson`_ + +- Support for saving movies of source time courses (STCs) with ``brain.save_movie`` method and from graphical user interface by `Guillaume Favelier`_ + +- Add ``mri`` and ``show_orientation`` arguments to :func:`mne.viz.plot_bem` by `Eric Larson`_ + +- Add :func:`mne.viz.centers_to_edges` to help when using :meth:`matplotlib.axes.Axes.pcolormesh` with flat shading by `Eric Larson`_ + +- Add ``on_missing='raise'`` to :meth:`mne.io.Raw.set_montage` and related functions to allow ignoring of missing electrode coordinates by `Adam Li`_ + +- Add ``on_missing='raise'`` to :func:`mne.viz.plot_events` to allow ignoring missing events when passing ``event_id`` by `Eric Larson`_ + +- Add REST EEG infinity reference scheme to :meth:`mne.io.Raw.set_eeg_reference` and related functions by `Eric Larson`_ + +- Add better sanity checking of ``max_pca_components`` and ``n_components`` to provide more informative error messages for :class:`mne.preprocessing.ICA` by `Eric Larson`_ + +- Add ``plot`` option to :meth:`mne.viz.plot_filter` allowing selection of which filter properties are plotted and added option for user to supply ``axes`` by `Robert Luke`_ + +- Add estimation method legend to :func:`mne.viz.plot_snr_estimate` by `Eric Larson`_ + +- Add support to `mne.SourceSpaces.export_volume` for ``mri_resolution='sparse'`` to color only the nearest-neighbor voxels instead of entire regions by `Eric Larson`_ + +- Add ``axes`` argument to :func:`mne.viz.plot_evoked_white`, :meth:`mne.Evoked.plot_white`, and :func:`mne.viz.plot_snr_estimate` by `Eric Larson`_ + +- Change default to ``surfaces='auto'`` from ``surfaces='head'`` to allow :func:`mne.viz.plot_alignment` to work when just passing a :class:`mne.Info` as ``plot_alignment(info)`` by `Eric Larson`_ + +- Add ECoG misc EDF dataset to the :ref:`tut-working-with-ecog` tutorial to show snapshots of time-frequency activity by `Adam Li`_ + +- Add :func:`mne.viz.set_3d_options` and ``MNE_3D_OPTION_ANTIALIAS`` environment variable to control full-scene antialiasing (FXAA) in 3D functions like :ref:`mne coreg`, :func:`mne.viz.plot_alignment`, and :func:`mne.viz.plot_source_estimates`; this can be useful on systems where FXAA does not work well, such as some with MESA software rendering, by `Eric Larson`_ + +- Add config variable ``MNE_TQDM`` to support explicitly setting the TQDM backend to use, for example ``tqdm`` or ``tqdm.auto`` (default) by `Eric Larson`_ + +- Add better support for reading corrupted FIF files in :func:`mne.io.read_raw_fif` by `Eric Larson`_ + +- BIDS conformity: When saving FIF files to disk and the files are split into parts, the ``split_naming='bids'`` parameter now uses a "_split-%d" naming instead of the previous "_part-%d", by `Stefan Appelhoff`_ + +- Add support for whitening and multiple channel types in :func:`mne.beamformer.make_dics` by `Marijn van Vliet`_ + +- Add better error message when trying to save incompatible `~mne.Evoked` objects to the same file by `Eric Larson`_ + +- Add support for loading complex numbers from mat files by `Thomas Hartmann`_ + +- Add generic reader function :func:`mne.io.read_raw` that loads files based on their extensions (it wraps the underlying specific ``read_raw_xxx`` functions) by `Clemens Brunner`_ + +- Add automatic T3 magnetometer detection and application of :meth:`mne.io.Raw.fix_mag_coil_types` to :func:`mne.preprocessing.maxwell_filter` by `Eric Larson`_ + +- Add extended SSS (eSSS) support to :func:`mne.preprocessing.maxwell_filter` by `Eric Larson`_ + +- Add ``'auto'`` option to :meth:`mne.preprocessing.ICA.find_bads_ecg` to automatically determine the threshold for CTPS method by `Yu-Han Luo`_ + +- Add a ``notebook`` 3d backend for visualization in jupyter notebook with :func:`mne.viz.set_3d_backend` by `Guillaume Favelier`_ + +- Add support for reading and writing surfaces in Wavefront .obj format to the :func:`mne.read_surface` and :func:`mne.write_surface` by `Marijn van Vliet`_ + +- Add tutorial on how to manually fix BEM meshes in Blender by `Marijn van Vliet`_ and `Ezequiel Mikulan`_ + +- :func:`mne.write_evokeds` will now accept :class:`mne.Evoked` objects with differing channel orders in ``info['bads']``, which would previously raise an exception by `Richard Höchenberger`_ + +- Add support for reading channel names (e.g., for Ricoh data) to :func:`mne.io.read_raw_kit` by `Alex Gramfort`_ and `Eric Larson`_ + +- The ``reject_tmin`` and ``reject_tmax`` parameters of :class:`mne.Epochs` are now taken into account when using the ``reject_by_annotation`` parameter by `Stefan Appelhoff`_ + +- :func:`mne.preprocessing.find_bad_channels_maxwell` now automatically applies a low-pass filter before running bad channel detection. This can be disabled, restoring previous behavior by `Richard Höchenberger`_ + +- Add ``proj='reconstruct'`` to :meth:`mne.Evoked.plot` and related functions to apply projectors and then undo the signal bias using field mapping by `Eric Larson`_ + +- Add writing BEM surfaces and solutions in H5 format in :func:`mne.write_bem_surfaces` and :func:`mne.write_bem_solution` by `Eric Larson`_ + +- When picking a subset of channels, or when dropping channels from `~mne.io.Raw`, `~mne.Epochs`, or `~mne.Evoked`, projectors that can only be applied to the removed channels will now be dropped automatically by `Richard Höchenberger`_ + +- :class:`mne.Report` now can add topomaps of SSP projectors to the generated report. This behavior can be toggled via the new ``projs`` argument by `Richard Höchenberger`_ + +- When passing a list of `~mne.Evoked` objects to `~mne.viz.plot_compare_evokeds`, each evoked's ``.comment`` attribute will be used to label the trace. If ``.comment`` is empty, a 1-based index is assigned as the label by `Richard Höchenberger`_ + +- Speed up :func:`mne.stats.summarize_clusters_stc` using Numba by `Yu-Han Luo`_ + +- Add ``reject_by_annotation=True`` to :func:`mne.make_fixed_length_epochs` and :meth:`mne.preprocessing.ICA.plot_properties` to reject bad data segments based on annotation by `Yu-Han Luo`_ + +- `~mne.Report.parse_folder` now accepts a path-like folder name (it used to work with strings only) by `Alex Gramfort`_ + +- Add ``component_order`` parameter to :class:`mne.decoding.CSP` which allows switching between ``mutual_info`` (default) and ``alternate`` (a simpler and frequently used option) by `Martin Billinger`_ and `Clemens Brunner`_ + +- Add memory size information to the ``repr`` of :class:`mne.SourceSpaces` and :class:`mne.SourceEstimate` and related classes by `Eric Larson`_ + +- Add reader for Persyst (.lay + .dat format) data in :func:`mne.io.read_raw_persyst` by `Adam Li`_ + +- Use PyVista as the default backend for 3D visualization instead of Mayavi by `Guillaume Favelier`_ + +- Add reader for SNIRF NIRS data in :func:`mne.io.read_raw_snirf` by `Robert Luke`_ + +- `~mne.Evoked` has gained ``tmin`` and ``tmax`` attributes for more consistency with `~mne.Epochs` by `Richard Höchenberger`_ + +Bugs +~~~~ + +- Fix bug for writing and reading complex evoked data modifying :func:`mne.write_evokeds` and :func:`mne.read_evokeds` **by new contributor** |Lau Møller Andersen|_ + +- Fix bug by adding error message when trying to save complex stc data in a non.-h5 format :meth:`mne.VolSourceEstimate.save` **by new contributor** |Lau Møller Andersen|_ + +- Fix bug with logging in :meth:`mne.io.Raw.set_eeg_reference` and related functions **by new contributor** |Simeon Wong|_ + +- Fix bug with :func:`mne.io.read_raw_gdf` where birthdays were not parsed properly, leading to an error **by new contributor** |Svea Marie Meyer|_ + +- Fix bug with :func:`mne.io.read_raw_edf` where recording ID was not read properly for non-ASCII characters **by new contributor** |Lx37|_ + +- Fix bug in :func:`mne.set_eeg_reference` and related functions to set ``info['custom_ref_applied']`` to ``True`` for 'ecog' and 'seeg' channels in addition to 'eeg' **by new contributor** |Liberty Hamilton|_ + +- Fix bug with :func:`mne.chpi.compute_chpi_amplitudes` and :func:`mne.chpi.filter_chpi` to optimize time window length **by new contributor** |Steven Bierer|_ + +- Fix bug with :func:`mne.preprocessing.ICA.find_bads_eog` when more than one EOG components are present by `Christian O'Reilly`_ + +- Fix bug with non-preloaded data when using ``raw.apply_proj().load_data().get_data()`` where projectors were not applied by `Eric Larson`_ + +- Fix bug to permit :meth:`stc.project('nn', src) ` to be applied after ``stc`` was restricted to an :class:`mne.Label` by `Luke Bloy`_ + +- Fix bug with :func:`mne.io.Raw.set_meas_date` to support setting ``meas_date`` to ``None``, by `Luke Bloy`_ + +- Fix bug with :func:`mne.setup_volume_source_space` when ``volume_label`` was supplied where voxels slightly (in a worst case, about 37% times ``pos`` in distance) outside the voxel-grid-based bounds of regions were errantly included, by `Eric Larson`_ + +- Fix bug with :ref:`mne coreg` where reverse scalings were applied to ``src[0]['src_mri_t']`` for volume source spaces, so morphing and plotting did not work correctly by `Eric Larson`_ + +- Fix bug with :func:`mne.io.read_raw_ctf` when reference magnetometers have the compensation grade marked by `Eric Larson`_ + +- Fix bug with `mne.SourceSpaces.export_volume` with ``use_lut=False`` where no values were written by `Eric Larson`_ + +- Fix bug with :func:`mne.preprocessing.annotate_movement` where bad data segments, specified in ``raw.annotations``, would be handled incorrectly by `Luke Bloy`_ + +- Fix bug with :func:`mne.compute_source_morph` when more than one volume source space was present (e.g., when using labels) where only the first label would be interpolated when ``mri_resolution=True`` by `Eric Larson`_ + +- Fix bug with :func:`mne.compute_source_morph` when morphing to a volume source space when ``src_to`` is used and the destination subject is not ``fsaverage`` by `Eric Larson`_ + +- Fix bug with :func:`mne.compute_source_morph` where outermost voxels in the destination source space could be errantly omitted by `Eric Larson`_ + +- Fix bug with :func:`mne.compute_source_morph` where complex data was cast to real when doing a volumetric morph by `Eric Larson`_ + +- Fix bug with :func:`mne.minimum_norm.compute_source_psd_epochs` and :func:`mne.minimum_norm.source_band_induced_power` raised errors when ``method='eLORETA'`` by `Eric Larson`_ + +- Fix bug with :func:`mne.minimum_norm.apply_inverse` where the explained variance did not work for complex data by `Eric Larson`_ + +- Fix bug with :func:`mne.preprocessing.compute_current_source_density` where values were not properly computed; maps should now be more focal, by `Alex Rockhill`_ and `Eric Larson`_ + +- Fix bug with :func:`mne.combine_evoked` where equal-weighted averages were wrongly computed as equal-weighted sums, by `Daniel McCloy`_ + +- Fix bug with :meth:`mne.channels.DigMontage.plot` when reference channels with no defined position are present, by `Eric Larson`_ + +- Fix bug with :func:`mne.channels.read_custom_montage` where ``"headshape"`` points in SFP format were not read properly, by `Eric Larson`_ + +- Fix bug with setting HTML classes when using ``mne.Report.add_bem_to_section`` by `Eric Larson`_ + +- Fix bug with convex-hull based MEG helmet creation where the face area could be covered up, by `Eric Larson`_ + +- Fix bug with :func:`mne.inverse_sparse.mixed_norm` and :func:`mne.inverse_sparse.gamma_map` with ``return_as_dipoles=True`` and :func:`mne.beamformer.rap_music` where ``dip.gof`` was the same for all dipoles. GOF values / explained variance across all dipoles now gets split among the dipoles using SVD of the lead fields. To get the total GOF, ``sum(dip.gof for dip in dipoles)`` can be used, by `Eric Larson`_ + +- Fix bug with :func:`mne.inverse_sparse.gamma_map` where output data was not assigned properly when using a free-orientation forward and ``xyz_same_gamma=False`` by `Eric Larson`_ + +- Fix to enable interactive plotting with no colorbar with :func:`mne.viz.plot_evoked_topomap` by `Daniel McCloy`_ + +- Fix plotting with :func:`mne.viz.plot_evoked_topomap` to pre-existing axes by `Daniel McCloy`_ + +- Fix bug with :func:`mne.viz.plot_vector_source_estimates` using the PyVista backend with ``time_viewer=True`` when updating the arrow colormaps by `Eric Larson`_ + +- Fix bug with :func:`mne.viz.plot_vector_source_estimates` where ``clim='auto'`` and ``clim=dict(..., kind='percent')`` did not take into account the magnitude of the activation, by `Eric Larson`_ + +- The default plotting mode for :func:`mne.io.Raw.plot` and :ref:`mne browse_raw` has been changed to ``clipping=3.`` to facilitate data analysis with large deflections, by `Eric Larson`_ + +- PSD plots will now show non-data channels (e.g., ``misc``) if those channels are explicitly passed to ``picks``, by `Daniel McCloy`_. + +- Fix bug with :func:`mne.time_frequency.read_tfrs` where ``info['meas_date']`` was not parsed correctly, by `Eric Larson`_ + +- Fix bug with :func:`mne.time_frequency.tfr_array_stockwell` where inputs were not properly validated by `Eric Larson`_ + +- Fix handling of NaN when using TFCE in clustering functions such as :func:`mne.stats.spatio_temporal_cluster_1samp_test` by `Eric Larson`_ + +- Fix handling of signs when using TFCE by `Eric Larson`_ + +- The :class:`mne.MixedSourceEstimate` class has been clarified to contain two cortical surface source spaces, plus at least one other source space. Creating source estimates in other orderings is not supported, by `Eric Larson`_ + +- Fix bug where :class:`VolSourceEstimate.vertices ` was an instance of :class:`~numpy.ndarray` instead of :class:`python:list` of one :class:`~numpy.ndarray`, by `Eric Larson`_ + +- Fix default to be ``foreground=None`` in :func:`mne.viz.plot_source_estimates` to use white or black text based on the background color by `Eric Larson`_ + +- Fix bug with writing EGI and CTF `mne.Info` to H5 format, e.g., with `mne.time_frequency.AverageTFR.save` by `Eric Larson`_ + +- Fix bug with topomap outlines in :meth:`mne.time_frequency.AverageTFR.plot_joint` and :meth:`mne.time_frequency.AverageTFR.plot_topo` by `Eric Larson`_ + +- Fix bug with :func:`mne.io.Raw.plot` where toggling all projectors did not actually take effect by `Eric Larson`_ + +- Fix bug with :func:`mne.write_proj` where the number of columns was incorrectly written by `Eric Larson`_ + +- Fix bug with :func:`mne.read_epochs` when loading data in complex format with ``preload=False`` by `Eric Larson`_ + +- Fix bug with :meth:`mne.Epochs.save` where the file splitting calculations did not account for the sizes of non-data writes by `Eric Larson`_ + +- Fix bug with :class:`mne.Epochs` when metadata was not subselected properly when ``event_repeated='drop'`` by `Eric Larson`_ + +- Fix bug with :class:`mne.Epochs` where ``epochs.drop_log`` was a list of list of str rather than an immutable tuple of tuple of str (not meant to be changed by the user) by `Eric Larson`_ + +- Fix bug with :class:`mne.Report` where the BEM section could not be toggled by `Eric Larson`_ + +- Fix bug when using :meth:`mne.Epochs.crop` to exclude the baseline period would break :func:`mne.Epochs.save` / :func:`mne.read_epochs` round-trip by `Eric Larson`_ + +- Fix bug with `mne.Epochs.subtract_evoked` where using decimated epochs would lead to an error by `Eric Larson`_ + +- Fix bug with :func:`mne.viz.plot_bem` and :class:`mne.Report` when plotting BEM contours when MRIs are not in standard FreeSurfer orientation by `Eric Larson`_ + +- Fix bug with :func:`mne.minimum_norm.make_inverse_operator` where it would warn even when an explicit ``rank`` was used by `Eric Larson`_ + +- Fix bugs with :func:`mne.beamformer.make_lcmv` and :func:`mne.beamformer.make_dics` where: + + - Noise normalization factors ``weight_norm='unit-noise-gain'`` and ``weight_norm='nai'`` were computed incorrectly + - ``pick_ori='max-power'`` computed the max-power orientation incorrectly + - ``pick_ori='normal'`` did not compute power or noise normalization factors correctly + - :func:`mne.beamformer.apply_lcmv_cov` did not apply whitening and projections properly + +- Fix :ref:`mne setup_forward_model` to have it actually compute the BEM solution in addition to creating the BEM model by `Eric Larson`_ + +- Fix bug with :func:`mne.io.read_raw_edf` where null bytes were not properly handled, causing an error when opening a file by `Eric Larson`_ + +- Fix bug with :func:`mne.Report` where unicode characters were not rendered properly (encoding for HTML was not set) by `Eric Larson`_ + +- Fix bug with :func:`mne.preprocessing.nirs.scalp_coupling_index` where filter transition was incorrectly assigned by `Robert Luke`_ + +- Fix bug with :func:`mne.make_forward_dipole` where :func:`mne.write_forward_solution` could not be used by `Eric Larson`_ + +- Fix bug with :meth:`mne.io.Raw.plot` when ``scalings='auto'`` where bad data would prevent channel plotting by `Eric Larson`_ + +- Default ``border`` and ``extrapolate`` arguments for :func:`mne.Evoked.plot_topomap` and related functions were changed from ``0.`` to ``'mean'`` and ``'box'`` to ``'auto'``, respectively, to help more accurately reflect sensor geometries and boundary conditions. ``extrapolate='auto'`` uses ``extrapolate='local'`` for MEG data and ``extrapolate='head'`` otherwise, by `Eric Larson`_ + +- Fix bug that prevents ``n_jobs`` from being a NumPy integer type, by `Daniel McCloy`_. + +- Fix bug with :func:`mne.epochs.average_movements` where epoch weights were computed using all basis vectors instead of the internal basis only by `Eric Larson`_ + +- Fix bug with :func:`mne.get_volume_labels_from_aseg` where the returned labels were alphabetical instead of reflecting their volumetric ID-based order by `Eric Larson`_ + +- Fix bug with :func:`mne.preprocessing.find_bad_channels_maxwell` where good data of exactly ``step`` duration would lead to an error by `Eric Larson`_ + +- Fix bug with :func:`mne.preprocessing.find_bad_channels_maxwell` where indices were not handled properly when MEG channels were not first in the raw instance, and logging messages incorrectly reported the interval used by `Eric Larson`_ + +- Make :func:`mne.set_config` accept path-like input values by `Richard Höchenberger`_ + +- Fix bug with :func:`mne.write_labels_to_annot` and :func:`mne.datasets.fetch_hcp_mmp_parcellation` where label name strings were not properly terminated, leading to problems loading in FreeSurfer by `Eric Larson`_ + +- Fix bug with :func:`mne.beamformer.make_dics` where complex conjugates were not applied properly by `Britta Westner`_ and `Eric Larson`_ + +- Fix bug with :func:`mne.bem.make_watershed_bem` where the RAS coordinates of watershed bem surfaces were not updated correctly from the volume file by `Yu-Han Luo`_ + +- Fix bug with :meth:`mne.io.Raw.get_channel_types` and related methods where the ordering of ``picks`` was not preserved, by `Eric Larson`_ + +- Fix bug with :meth:`mne.io.Raw.plot_psd` with ``average=False`` and multiple channel types where channel locations were not shown properly by `Eric Larson`_ + +- Fix bug with :func:`mne.viz.plot_sparse_source_estimates` when using ``'sphere'`` mode by `Eric Larson`_ and `Guillaume Favelier`_ + +- Fix bug in FieldTrip reader functions when channels are missing in the ``info`` object by `Thomas Hartmann`_ + +- Throw proper error when trying to import FieldTrip Epochs data with non-uniform time for trials by `Thomas Hartmann`_ + +- Throw proper error when trying to import FieldTrip data saved by an old, incompatible version by `Thomas Hartmann`_ + +- Fix bug in :func:`mne.read_epochs_fieldtrip` when importing data without a ``trialinfo`` field by `Thomas Hartmann`_ + +- Fix bug in :meth:`mne.preprocessing.ICA.plot_properties` where time series plot doesn't start at the proper tmin by `Teon Brooks`_ + +- Fix bug with :meth:`mne.preprocessing.ICA.plot_properties` where a :class:`mne.io.Raw` object with annotations would lead to an error by `Yu-Han Luo`_ + +- Fix bug with :func:`mne.events_from_annotations(raw.annotations) ` when ``orig_time`` of annotations is None and ``raw.first_time > 0``, by `Alex Gramfort`_ + +API changes +~~~~~~~~~~~ + +- Python 3.5 is no longer supported, Python 3.6+ is required, by `Eric Larson`_ + +- ``adjacency`` has replaced ``connectivity`` in the names of: + + 1. Arguments to clustering functions, such as `mne.stats.permutation_cluster_test`, and + 2. Function names for defining adjacency, such as `mne.spatio_temporal_src_adjacency` replacing ``mne.spatio_temporal_src_connectivity``. + + The complete list of changed function names is: + + - ``mne.channels.find_ch_connectivity`` → `~mne.channels.find_ch_adjacency` + - ``mne.channels.read_ch_connectivity`` → `~mne.channels.read_ch_adjacency` + - ``mne.spatial_dist_connectivity`` → `~mne.spatial_dist_adjacency` + - ``mne.spatial_inter_hemi_connectivity`` → `~mne.spatial_inter_hemi_adjacency` + - ``mne.spatial_src_connectivity`` → `~mne.spatial_src_adjacency` + - ``mne.spatial_tris_connectivity`` → `~mne.spatial_tris_adjacency` + - ``mne.spatio_temporal_dist_connectivity`` → `~mne.spatio_temporal_dist_adjacency` + - ``mne.spatio_temporal_src_connectivity`` → `~mne.spatio_temporal_src_adjacency` + - ``mne.spatio_temporal_tris_connectivity`` → `~mne.spatio_temporal_tris_adjacency` + + "connectivity" is now reserved for discussions of functional and effective connectivity of the brain, and "adjacency" for source or sensor neighbor definitions for cluster-based analyses, by `Eric Larson`_. + +- The default for the ``standardize_names`` argument of :func:`mne.io.read_raw_kit` will change from ``True`` to ``False`` in 0.22, by `Eric Larson`_ + +- The ``normalize_fwd`` argument of :func:`mne.beamformer.make_dics` has been deprecated in favor of ``depth``, by `Eric Larson`_ + +- The ``overwrite`` parameter of :func:`mne.write_bem_surfaces` and :func:`mne.write_bem_solution` defaults to ``True`` in 0.21 but will change to ``False`` in 0.22, by `Eric Larson`_ + +- Add ``n_cols`` parameter to :meth:`mne.preprocessing.ICA.plot_scores` to allow plotting scores in multiple columns, by `Luke Bloy`_ + +- In :func:`mne.stats.permutation_cluster_test` and :func:`mne.stats.permutation_cluster_1samp_test` the default parameter value ``out_type='mask'`` has changed to ``None``, which in 0.21 means ``'mask'`` but will change to mean ``'indices'`` in the next version, by `Daniel McCloy`_ + +- The default window size set by ``filter_length`` when ``method='spectrum_fit'`` in :meth:`mne.io.Raw.notch_filter` will change from ``None`` (use whole file) to ``'10s'`` in 0.22, by `Eric Larson`_ + +- ``vmin`` and ``vmax`` parameters are deprecated in :meth:`mne.Epochs.plot_psd_topomap` and :func:`mne.viz.plot_epochs_psd_topomap`; use new ``vlim`` parameter instead, by `Daniel McCloy`_. + +- The method ``stc_mixed.plot_surface`` for a :class:`mne.MixedSourceEstimate` has been deprecated in favor of :meth:`stc.surface().plot(...) ` by `Eric Larson`_ + +- The method ``stc.normal`` for :class:`mne.VectorSourceEstimate` has been deprecated in favor of :meth:`stc.project('nn', src) ` by `Eric Larson`_ + +- Add ``use_dev_head_trans`` parameter to :func:`mne.preprocessing.annotate_movement` to allow choosing the device to head transform is used to define the fixed cHPI coordinates by `Luke Bloy`_ + +- The function ``mne.channels.read_dig_captrack`` will be deprecated in version 0.22 in favor of :func:`mne.channels.read_dig_captrak` to correct the spelling error: "captraCK" -> "captraK", by `Stefan Appelhoff`_ + +- The ``threshold`` argument in :meth:`mne.preprocessing.ICA.find_bads_ecg` defaults to ``None`` in version 0.21 but will change to ``'auto'`` in 0.22 by `Yu-Han Luo`_ + +- The function ``mne.preprocessing.mark_flat`` has been deprecated in favor of ``mne.preprocessing.annotate_flat`` by `Eric Larson`_ + +- The default argument ``meg=True`` in :func:`mne.pick_types` will change to ``meg=False`` in version 0.22 by `Clemens Brunner`_ + +- Added :meth:`mne.io.Raw.get_montage`, which obtains the montage that an instance has, by `Adam Li`_ + + +Authors +~~~~~~~ + +People who contributed to this release in alphabetical order +(people with a + are first time contributors): + +* Adam Li +* Adonay Nunes +* Alejandro Weinstein +* Alex Rockhill +* Alexandre Gramfort +* Anton Nikolas Waniek +* Britta Westner +* Christian O'Reilly +* Clemens Brunner +* Daniel McCloy +* Eric Larson +* Evgenii Kalenkovich +* Fede Raimondo +* Guillaume Favelier +* Hubert Banville +* Jeroen Van Der Donckt + +* Johann Benerradi + +* Kyle Mathewson + +* Lau Møller Andersen + +* Liberty Hamilton + +* Luke Bloy +* Lx37 + +* Mainak Jas +* Marijn van Vliet +* Martin Billinger +* Martin Schulz + +* Martin van Harmelen +* Mikolaj Magnuski +* Olaf Hauk +* Rahul Nadkarni + +* Richard Höchenberger +* Robert Luke +* Sara Sommariva +* Simeon Wong + +* Stefan Appelhoff +* Steven Bierer + +* Svea Marie Meyer + +* Teon Brooks +* Thomas Hartmann +* Yu-Han Luo +* chapochn +* mshader diff --git a/mne-python/source/doc/changes/v0.22.rst b/mne-python/source/doc/changes/v0.22.rst new file mode 100644 index 0000000000000000000000000000000000000000..52d7cec71e549e775eadfdc4070b8512e9db27b3 --- /dev/null +++ b/mne-python/source/doc/changes/v0.22.rst @@ -0,0 +1,263 @@ +.. _changes_0_22: + +Version 0.22.0 (2020-12-17) +--------------------------- + +.. |Austin Hurst| replace:: **Austin Hurst** + +.. |Aniket Pradhan| replace:: **Aniket Pradhan** + +.. |Eduard Ort| replace:: **Eduard Ort** + +.. |Evan Hathaway| replace:: **Evan Hathaway** + +.. |Hongjiang Ye| replace:: **Hongjiang Ye** + +.. |Jeff Stout| replace:: **Jeff Stout** + +.. |Jonathan Kuziek| replace:: **Jonathan Kuziek** + +.. |Qianliang Li| replace:: **Qianliang Li** + +.. |Tod Flak| replace:: **Tod Flak** + +.. |Victoria Peterson| replace:: **Victoria Peterson** + + +Enhancements +~~~~~~~~~~~~ +- Add :func:`mne.read_evokeds_mff` to read averaged MFFs (requires mffpy >= 0.5.7) **by new contributor** |Evan Hathaway|_ (:gh:`8354`) + +- Add :class:`mne.decoding.SSD` for spatial filtering with spatio-spectral-decomposition (:gh:`7070` **by new contributor** |Victoria Peterson|_ and `Denis Engemann`_) + +- Add reader for optical imaging data recorded using ISS Imgagent I/II hardware and BOXY recording software in :func:`mne.io.read_raw_boxy` (:gh:`7717` **by new contributor** |Jonathan Kuziek|_ and `Kyle Mathewson`_) + +- Add options to use labels in :func:`mne.minimum_norm.get_point_spread` and :func:`mne.minimum_norm.get_cross_talk` (:gh:`8275` by `Olaf Hauk`_) + +- Update ``surfaces`` argument in :func:`mne.viz.plot_alignment` to allow dict for transparency values, and set default for sEEG data to have transparency (:gh:`8445` by `Keith Doelling`_) + +- Add support for ``mri_fiducials='estimated'`` in :func:`mne.viz.plot_alignment` to allow estimating MRI fiducial locations using :func:`mne.coreg.get_mni_fiducials` (:gh:`8553` by `Eric Larson`_) + +- Update default values in :ref:`mne coreg` and :func:`mne.viz.plot_alignment` for clearer representation of MRI and digitized fiducial points (:gh:`8553` by `Alex Gramfort`_ and `Eric Larson`_) + +- Add ``n_pca_components`` argument to :func:`mne.viz.plot_ica_overlay` (:gh:`8351` by `Eric Larson`_) + +- Add :func:`mne.stc_near_sensors` to facilitate plotting ECoG data (:gh:`8190` by `Eric Larson`_) + +- Add ``proj`` argument to :func:`mne.make_fixed_length_epochs` (:gh:`8351` by `Eric Larson`_) + +- Add :func:`mne.preprocessing.realign_raw` to realign simultaneous raw recordings in the presence of clock drift (:gh:`8539` by `Eric Larson`_) + +- Reduce memory usage of volume source spaces (:gh:`8379` by `Eric Larson`_) + +- Speed up heavy use of :meth:`mne.SourceMorph.apply` for volumetric source spaces by use of the method :meth:`mne.SourceMorph.compute_vol_morph_mat` (:gh:`8366` by `Eric Larson`_) + +- Add support for non-uniform ``zooms`` (e.g., when using a surrogate MRI via :func:`mne.scale_mri`) in volumetric morphing (:gh:`8642` by `Eric Larson`_) + +- In :func:`mne.compute_source_morph` ``zooms`` are no longer required to match the spacing of ``src_to``, which is useful to ensure the morphing is accurate when the ``src_to`` spacing is large (e.g., 1 cm) (:gh:`8642` by `Eric Larson`_) + +- Add volumetric source space support to :func:`mne.labels_to_stc` (:gh:`8447` by `Eric Larson`_) + +- Speed up :class:`mne.decoding.TimeDelayingRidge` with edge correction using Numba (:gh:`8323` by `Eric Larson`_) + +- Add :meth:`mne.Epochs.reset_drop_log_selection` to facilitate writing epochs with many ignored entries in their drop log (:gh:`8449` by `Eric Larson`_) + +- Add sEEG source visualization using :func:`mne.stc_near_sensors` and sEEG working tutorial (:gh:`8402` by `Eric Larson`_ and `Adam Li`_) + +- Add :meth:`mne.channels.DigMontage.get_positions`, which will return a dictionary of channel positions, coordinate frame and fiducial locations (:gh:`8460` by `Adam Li`_) + +- Add support for writing digitization points in a coordinate frame other than head in :meth:`mne.channels.DigMontage.save` (:gh:`8532` by `Eric Larson`_) + +- Add ``picks`` parameter to :func:`mne.preprocessing.fix_stim_artifact` to specify which channel needs to be fixed (:gh:`8482` by `Alex Gramfort`_) + +- Add progress bar support to :func:`mne.time_frequency.csd_morlet` (:gh:`8608` by `Eric Larson`_) + +- Further improved documentation building instructions and execution on Windows (:gh:`8502` by `Evgenii Kalenkovich`_ and `Eric Larson`_) + +- Add option to disable TQDM entirely with ``MNE_TQDM='off'`` (:gh:`8515` by `Eric Larson`_) + +- Add option ``on_header_missing`` to :func:`mne.channels.read_polhemus_fastscan` (:gh:`8622` by `Eric Larson`_) + +- Add option ``window`` to ``mne.time_frequency.psd_welch`` and related functions (:gh:`8862` by `Eric Larson`_) + +- `mne.preprocessing.ICA.plot_sources` now displays an `mne.preprocessing.ICA.plot_properties` window when right-clicking on component names on the y-axis (:gh:`8381` by `Daniel McCloy`_) + +- :func:`mne.io.read_raw_edf`, :func:`mne.io.read_raw_bdf`, and :func:`mne.io.read_raw_gdf` now detect and handle invalid highpass/lowpass filter settings (:gh:`8584` by `Clemens Brunner`_) + +- If a ``baseline`` tuple containing one or two ``None`` values – e.g. ``(None, 0)``, ``(0, None)``, or ``(None, None)`` – is passed to `~mne.Epochs` or `~mne.Epochs.apply_baseline`, the ``None`` value(s) will be replaced with the actual time (i.e., :attr:`~mne.Epochs.tmin` and :attr:`~mne.Epochs.tmax`, respectively) when populating ``Epochs.baseline`` (:gh:`8442` by `Richard Höchenberger`_) + +- `~mne.Epochs` will now retain the information about an applied baseline correction, even if the baseline period is partially or completely removed through cropping later on (:gh:`8442` by `Richard Höchenberger`_) + +- Add :func:`mne.source_space.compute_distance_to_sensors` to compute distances between vertices and sensors (:gh:`8534` by `Olaf Hauk`_ and `Marijn van Vliet`_) + +- Annotations can now be shown/hidden interactively in raw plots (:gh:`8624` by `Daniel McCloy`_) + +- Added argument ``colors`` to `mne.grow_labels` (:gh:`8519` by `Olaf Hauk`_) + +- Added `mne.SourceEstimate.apply_baseline` method for baseline-correction of source estimates (:gh:`8452` by `Olaf Hauk`_) + +- New `mne.viz.Brain.set_time` method to set the displayed time in seconds (:gh:`8415` by `Daniel McCloy`_) + +- Update the ``backend`` parameter of :func:`mne.viz.plot_source_estimates` to integrate ``pyvista`` (:gh:`8395` by `Guillaume Favelier`_) + +- Add ``group_by`` parameter to `mne.viz.plot_epochs` and `mne.Epochs.plot` to allow displaying channel data by sensor position (:gh:`8381` by `Daniel McCloy`_) + +Bugs +~~~~ +- Fix orthogonalization of power envelopes in ``mne.connectivity.envelope_correlation`` (:gh:`8658` **by new contributor** |Qianliang Li|_ and `Eric Larson`_) + +- Fix data overwrite of cascading simulation operations :`mne.simulation.simulate_raw` (:gh:`8633` **by new contributor** |Jeff Stout|_) + +- Fix a transpose issue of :func:`mne.decoding.CSP.plot_filters` (:gh:`8580` **by new contributor** |Hongjiang Ye|_) + +- Fix :func:`mne.io.read_raw_curry` to deal with Curry datasets that have channels that are listed in the labels file, but which are absent from the saved data file (e.g. 'Ref' channel). Also now populates info['meas_date'] if possible (:gh:`8400` **by new contributor** |Tod Flak|_) + +- Fix bug with mne.io.egi.tests/test_egi.py where it mandatorily downloaded testing data when it was not necessary (:gh:`8474` **by new contributor** |Aniket Pradhan|_) + +- Fix bug with reading split files that have dashes in the filename (:gh:`8339` **by new contributor** |Eduard Ort|_) + +- Fix bug with parsing EDF dates and date integers (:gh:`8558` **by new contributor** |Austin Hurst|_ and `Eric Larson`_) + +- Fix bug with reading EDF and KIT files on big endian architectures such as s390x (:gh:`8618` by `Eric Larson`_) + +- Fix bug with :func:`mne.beamformer.make_dics` where the ``rank`` parameter was not properly handled (:gh:`8594` by `Marijn van Vliet`_ and `Eric Larson`_) + +- Fix bug with :func:`mne.beamformer.apply_dics` where the whitener was not properly applied (:gh:`8610` by `Eric Larson`_) + +- Fix bug with `~mne.viz.plot_epochs_image` when ``order`` is supplied and multiple conditions are plotted (:gh:`8377` by `Daniel McCloy`_ ) + +- Fix bug with :func:`mne.viz.plot_source_estimates` when using the PyVista backend where singleton time points were not handled properly (:gh:`8285` by `Eric Larson`_) + +- Fix bug when passing ``axes`` to plotting functions, :func:`matplotlib.pyplot.tight_layout` will not be called when the figure was created using a constrained layout (:gh:`8344` by `Eric Larson`_) + +- Fix bug with compensated CTF data when picking channels without preload (:gh:`8318` by `Eric Larson`_) + +- Fix bug with plotting MEG topographies where the wrong extrapolation made was used in ICA (:gh:`8637` by `Eric Larson`_) + +- Fix bug when merging fNIRS channels in :func:`mne.viz.plot_evoked_topomap` and related functions (:gh:`8306` by `Robert Luke`_) + +- Fix bug where events could overflow when writing to FIF (:gh:`8448` by `Eric Larson`_) + +- :func:`mne.io.read_raw_edf` now supports EDF files with invalid recording dates (:gh:`8283` by `Clemens Brunner`_) + +- Fix bug with :func:`mne.io.Raw.save` when using ``split_naming='bids'`` where non-split files would still be named ``name_split-01_meg.fif`` instead of the requested ``name_meg.fif`` (:gh:`8464` by `Alex Gramfort`_ and `Eric Larson`_) + +- Fix bug with :class:`mne.preprocessing.ICA` where ``n_pca_components`` as a :class:`python:float` would give the number of components that explained less than or equal to the given variance. It now gives greater than the given number for better usability and consistency with :class:`sklearn.decomposition.PCA`. Generally this will mean that one more component will be included (:gh:`8326` by `Eric Larson`_) + +- Fix bug with :class:`mne.preprocessing.ICA` where projections were not tracked properly (:gh:`8343` by `Eric Larson`_) + +- Fix bug where extrapolation points created artifacts in :func:`mne.viz.plot_evoked_topomap` and related functions (:gh:`8425` by `Mikołaj Magnuski`_) + +- Fix bug with :func:`mne.preprocessing.read_ica_eeglab` where full-rank data were not handled properly (:gh:`8326` by `Eric Larson`_) + +- Fix bug with :ref:`somato-dataset` where the BEM was not included (:gh:`8317` by `Eric Larson`_) + +- Fix bug with coordinate frames when performing volumetric morphs via :func:`mne.compute_source_morph` and :meth:`mne.SourceMorph.apply` that could lead to ~5 mm bias (:gh:`8642` by `Eric Larson`_) + +- Fix bug with volumetric rendering alpha in :meth:`mne.VolSourceEstimate.plot_3d` and related functions (:gh:`8663` by `Eric Larson`_) + +- Fix missing documentation of :func:`mne.io.read_raw_nihon` in :ref:`tut-imorting-eeg-data` (:gh:`8320` by `Adam Li`_) + +- Fix bug with :func:`mne.add_reference_channels` when :func:`mne.io.Raw.reorder_channels` or related methods are used afterward (:gh:`8303`, :gh:`#8484` by `Eric Larson`_) + +- Fix bug where the ``verbose`` arguments to :meth:`mne.Evoked.apply_baseline` and :meth:`mne.Epochs.apply_baseline` were not keyword-only (:gh:`8349` by `Eric Larson`_) + +- ``ICA.max_pca_components`` will not be altered by calling `~mne.preprocessing.ICA.fit` anymore. Instead, the new attribute ``ICA.max_pca_components_`` will be set (:gh:`8321` by `Richard Höchenberger`_) + +- Fix bug that `~mne.viz.plot_ica_overlay` would sometimes not create red traces (:gh:`8341` by `Richard Höchenberger`_) + +- Fix bug with :class:`~mne.preprocessing.ICA` where ``n_components=None, n_pca_components=None`` could lead to unstable unmixing matrix inversion by making ``n_components=None`` also use the lesser of ``n_components=0.999999`` and ``n_components=n_pca_components`` (:gh:`8351` by `Eric Larson`_) + +- The ``ica.n_pca_components`` property is no longer be updated during :meth:`mne.preprocessing.ICA.fit`, instead ``ica.n_components_`` will be added to the instance (:gh:`8351` by `Eric Larson`_) + +- Pass ``rank`` everyhwere in forward preparation for source imaging. This bug affected sparse solvers when using maxfilter data (:gh:`8368` by `Alex Gramfort`_) + +- Fix bug in :func:`mne.viz.plot_alignment` where ECoG and sEEG channels were not plotted and fNIRS channels were always plotted in the head coordinate frame (:gh:`8393` by `Eric Larson`_) + +- Fix bug in :func:`mne.set_bipolar_reference` where ``ch_info`` could contain invalid channel information keys (:gh:`8416` by `Eric Larson`_) + +- When reading BrainVision raw data, the channel units and types were sometimes not inferred correctly (:gh:`8434` by `Richard Höchenberger`_) + +- Attempting to remove baseline correction from preloaded `~mne.Epochs` will now raise an exception (:gh:`8435` by `Richard Höchenberger`_) + +- :meth:`mne.Report.parse_folder` will now correctly handle split FIFF files (:gh:`8486`, :gh:`8491` by `Richard Höchenberger`_) + +- Fix bug where BrainVision channel names, event types, and event descriptions containing commas were incorrectly parsed (:gh:`8492` by `Stefan Appelhoff`_) + +- Fix bug in :func:`mne.preprocessing.compute_fine_calibration` where the magnetometer calibration coefficients were computed incorrectly (:gh:`8522` by `Eric Larson`_) + +- Fix bug in :func:`mne.io.read_raw_eeglab` where empty event durations led to an error (:gh:`8384` by `Mikołaj Magnuski`_) + +- Fix inset sensor plots to always use equal aspect (:gh:`8545` by `Daniel McCloy`_) + +- Fix bug in `mne.viz.plot_compare_evokeds` where evokeds with identical ``comment`` attributes would not plot properly if passed as a list (:gh:`8590` by `Daniel McCloy`_) + +- Fix bug in ``mne.time_frequency.psd_welch`` and related functions where the window default errantly changed from ``'hamming'`` to ``('tukey', 0.25)`` (:gh:`8862` by `Eric Larson`_) + +- Fix bug in :func:`mne.io.read_raw_kit` where scale factors for EEG channels could be set to zero (:gh:`8542` by `Eric Larson`_) + +- Fix reading GDF files with excluded channels in :func:`mne.io.read_raw_gdf` (:gh:`8520` by `Clemens Brunner`_) + +- Fix automatic selection of extrapolation mask type from channel type when plotting field maps (:gh:`8589` by `Daniel McCloy`_) + +- Fix bug in :func:`mne.viz.set_3d_title` where 3D plot could have multiple titles that overlap (:gh:`8564` by `Guillaume Favelier`_) + +- Fix bug in :func:`mne.viz.set_3d_view` where plotter is not updated properly causing camera issues in the doc (:gh:`8564` by `Guillaume Favelier`_) + +- :func:`mne.preprocessing.find_ecg_events` didn't take the ``tstart`` parameter value into account when calculating the average heart rate (:gh:`8605` by `Richard Höchenberger`_) + +API changes +~~~~~~~~~~~ + +- Minimum required versions were increased for core dependencies NumPy (1.15.4), SciPy (1.1.0), and Matplotlib (3.0) and for the optional dependencies scikit-learn (0.20.2) and pandas (0.23.4) (:gh:`8374` by `Eric Larson`_) + +- The parameter ``on_split_missing`` has been added to :func:`mne.io.read_raw_fif` and its default will change from ``'warn'`` to ``'raise'`` in 0.23, by (:gh:`8357` `Eric Larson`_) + +- The ``max_pca_components`` argument of :class:`~mne.preprocessing.ICA` has been deprecated, use ``n_components`` during initialization and ``n_pca_components`` in :meth:`~mne.preprocessing.ICA.apply` instead (:gh:`8351` by `Eric Larson`_) + +- The ``n_pca_components`` argument of :class:`~mne.preprocessing.ICA` has been deprecated, use ``n_pca_components`` in :meth:`~mne.preprocessing.ICA.apply` (:gh:`8356` by `Eric Larson`_) + +- The ``trans`` argument of :func:`mne.extract_label_time_course` is deprecated and will be removed in 0.23 as it is no longer necessary (:gh:`8389` by `Eric Larson`_) + +- Parameter ``event_colors`` in `mne.viz.plot_epochs` and `mne.Epochs.plot` is deprecated, replaced by ``event_color`` which is consistent with `mne.viz.plot_raw` and provides greater flexibility (:gh:`8381` by `Daniel McCloy`_) + +Authors +~~~~~~~ + +People who contributed to this release in alphabetical order +(people with a + are first time contributors): + +* Adam Li +* Alexandre Gramfort +* Aniket Pradhan + +* Austin Hurst + +* Christian Brodbeck +* Clemens Brunner +* Daniel McCloy +* Denis A. Engemann +* Eduard Ort + +* Eric Larson +* Evan Hathaway + +* Evgenii Kalenkovich +* Fede Raimondo +* Guillaume Favelier +* Hongjiang Ye + +* Jean-Rémi King +* Jeff Stout + +* Jonathan Kuziek + +* Jussi Nurminen +* Justus Schwabedal +* Keith Doelling +* Kyle Mathewson +* Mads Jensen +* Mainak Jas +* Marijn van Vliet +* Mikolaj Magnuski +* Olaf Hauk +* Qianliang Li + +* Richard Höchenberger +* Robert Luke +* Stefan Appelhoff +* Thomas Hartmann +* Tod Flak + +* Victoria Peterson + diff --git a/mne-python/source/doc/changes/v0.23.rst b/mne-python/source/doc/changes/v0.23.rst new file mode 100644 index 0000000000000000000000000000000000000000..a005feab4ec612645f16178e19a8c03ac4142e63 --- /dev/null +++ b/mne-python/source/doc/changes/v0.23.rst @@ -0,0 +1,388 @@ +.. _changes_0_23_0: + +Version 0.23.0 (2021-04-27) +--------------------------- + +.. |Jack Zhang| replace:: **Jack Zhang** + +.. |Sumalyo Datta| replace:: **Sumalyo Datta** + +.. |Anna Padee| replace:: **Anna Padee** + +.. |Richard Koehler| replace:: **Richard Koehler** + +.. |Zhi Zhang| replace:: **Zhi Zhang** + +.. |Rotem Falach| replace:: **Rotem Falach** + +.. |Andres Rodriguez| replace:: **Andres Rodriguez** + +.. |Matt Sanderson| replace:: **Matt Sanderson** + +.. |Enrico Varano| replace:: **Enrico Varano** + +.. |Dominik Welke| replace:: **Dominik Welke** + +.. |Judy D Zhu| replace:: **Judy D Zhu** + +.. |Valerii Chirkov| replace:: **Valerii Chirkov** + +.. |Matteo Anelli| replace:: **Matteo Anelli** + +.. |Apoorva Karekal| replace:: **Apoorva Karekal** + +.. |Cora Kim| replace:: **Cora Kim** + +.. |Silvia Cotroneo| replace:: **Silvia Cotroneo** + +.. |Ram Pari| replace:: **Ram Pari** + +.. |Erica Peterson| replace:: **Erica Peterson** + +.. |Maggie Clarke| replace:: **Maggie Clarke** + +.. |Felix Klotzsche| replace:: **Felix Klotzsche** + +Enhancements +~~~~~~~~~~~~ +- Add support for exporting to EEGLAB's set format with :mod:`eeglabio` with new methods :meth:`mne.io.Raw.export` and :meth:`mne.Epochs.export`. (:gh:`9192` **by new contributor** |Jack Zhang|_) + +- :func:`mne.viz.plot_evoked_topo` now uses a Minimum/Maximum of peaks for each channel type to calculate ylim when input param is None (:gh:`9285` **by new contributor** |Ram Pari|_) + +- Add exclude parameter to :func:`mne.viz.plot_evoked_topo` (:gh:`9278` **by new contributor** |Ram Pari|_) + +- Add :meth:`mne.time_frequency.EpochsTFR.to_data_frame` and :meth:`mne.time_frequency.AverageTFR.to_data_frame` methods (:gh:`9124` **by new contributor** |Felix Klotzsche|_) + +- Add ``selection`` and ``drop_log`` to :class:`mne.time_frequency.EpochsTFR` (:gh:`9124` **by new contributor** |Felix Klotzsche|_) + +- Add CSV, TSV, and XYZ support to :func:`mne.channels.read_custom_montage` (:gh:`9203` **by new contributor** |Jack Zhang|_) + +- Add HTML representation for `~mne.Epochs` in Jupyter Notebooks (:gh:`9174` **by new contributor** |Valerii Chirkov|_) + +- Speed up :func:`mne.viz.plot_ica_properties` by refactoring (:gh:`9174` **by new contributor** |Valerii Chirkov|_) + +- Add ``apply_function`` method to epochs and evoked objects (:gh:`9088` **by new contributor** |Erica Peterson|_ and `Victoria Peterson`_) + +- New tutorial for function :func:`mne.make_fixed_length_epochs` (:gh:`9156` **by new contributor** |Erica Peterson|_) + +- Add different colors for each volume source space in :func:`mne.viz.plot_alignment` (:gh:`9043` **by new contributor** |Valerii Chirkov|_) + +- Add ``overlap`` parameter to :func:`mne.make_fixed_length_epochs` to allow creating overlapping fixed length epochs (:gh:`9096` **by new contributor** |Silvia Cotroneo|_) + +- Add :meth:`mne.Dipole.to_mni` for more convenient dipole.pos to MNI conversion (:gh:`9043` **by new contributor** |Valerii Chirkov|_) + +- Update citations in maxwell.py (:gh:`9043` **by new contributor** |Valerii Chirkov|_) + +- New Tutorial for analyzing frequency-tagging data (:gh:`8867` **by new contributor** |Dominik Welke|_ and `Evgenii Kalenkovich`_) + +- Add dbs as new channel type for deep brain stimulation (DBS) recordings (:gh:`8739` **by new contributor** |Richard Koehler|_) + +- Add some preprocessing functions to the EEGLAB migration guide (:gh:`9169` **by new contributor** |Apoorva Karekal|_) + +- Add :func:`mne.chpi.extract_chpi_locs_kit` to read cHPI coil locations from KIT/Yokogawa data (:gh:`8813` **by new contributor** |Matt Sanderson|_, `Robert Seymour`_, and `Eric Larson`_) + +- Add ``match_alias`` parameter to :meth:`mne.io.Raw.set_montage` and related functions to match unrecognized channel location names to known aliases (:gh:`8799` **by new contributor** |Zhi Zhang|_) + +- Update the ``notebook`` 3d backend to use ``ipyvtk_simple`` for a better integration within ``Jupyter`` (:gh:`8503` by `Guillaume Favelier`_) + +- Remove the 15-character limitation for channel names when writing to FIF format. If you need the old 15-character names, you can use something like ``raw.rename_channels({n: n[:13] for n in raw.ch_names}, allow_duplicates=True)``, by `Eric Larson`_ (:gh:`8346`) + +- Add channel-specific annotation support to :class:`mne.Annotations` via ``ch_names`` parameter (:gh:`8896` by `Eric Larson`_) + +- Add toggle-all button to :class:`mne.Report` HTML and ``width`` argument to ``mne.Report.add_bem_to_section`` (:gh:`8723` by `Eric Larson`_) + +- Add infant template MRI dataset downloader :func:`mne.datasets.fetch_infant_template` (:gh:`8738` by `Eric Larson`_ and `Christian O'Reilly`_) + +- Add digitizer information to :func:`mne.io.read_raw_egi` (:gh:`8789` by `Christian Brodbeck`_) + +- Add support for reading some incomplete raw FIF files in :func:`mne.io.read_raw_fif` (:gh:`9268` by `Eric Larson`_) + +- Allow reading digitization from files other than ``*.fif`` in the coregistration GUI (:gh:`8790` by `Christian Brodbeck`_) + +- Speed up :func:`mne.inverse_sparse.tf_mixed_norm` using STFT/ISTFT linearity (:gh:`8697` by `Eric Larson`_) + +- Reduce memory consumption of `mne.io.Raw` and speed up epoching when thousands of events are present for `mne.Epochs` (:gh:`8801` by `Eric Larson`_) + +- Speed up ``import mne`` by reducing function creation overhead (:gh:`8829` by `Eric Larson`_) + +- `mne.Report.parse_folder` now processes supported non-FIFF files by default, too (:gh:`8744` by `Richard Höchenberger`_) + +- `mne.Report` has gained the new methods `~mne.Report.add_custom_js` and `~mne.Report.add_custom_css` for adding user-defined JavaScript and styles (:gh:`8762`, :gh:`9037` by `Richard Höchenberger`_) + +- Add option to control appearance of opaque inside surface of the head to :ref:`mne coreg` (:gh:`8793` by `Eric Larson`_) + +- Add option to disable projection using ``--projoff`` in :ref:`mne browse_raw` (:gh:`9262` by `Eric Larson`_) + +- Add keypress to toggle projection using ``shift+j`` in :meth:`mne.io.Raw.plot` and :ref:`mne browse_raw` (:gh:`9262` by `Eric Larson`_) + +- Add support for non-FIF files in :ref:`mne browse_raw` using :func:`mne.io.read_raw` (:gh:`8806` by `Eric Larson`_) + +- Add :func:`mne.io.read_raw_nedf` for reading StarStim / enobio NEDF files (:gh:`8734` by `Tristan Stenner`_) + +- Add :meth:`raw.describe() ` to display (or return) descriptive statistics for each channel (:gh:`8760` by `Clemens Brunner`_) + +- Add :meth:`annotations.to_data_frame() ` to return annotations as a pandas dataframe (:gh:`8783` by `Robert Luke`_) + +- Add :func:`mne.preprocessing.compute_maxwell_basis` to compute the SSS basis function (:gh:`8822` by `Eric Larson`_) + +- Add the ``silhouette`` parameter to :class:`mne.viz.Brain` to display sharp edges and improve perception (:gh:`8771` by `Guillaume Favelier`_) + +- Add warning to :func:`mne.cov.compute_whitener` when an explicit ``rank`` parameter leads to a large increase in condition number (:gh:`8805` by `Eric Larson`_) + +- Add parameter ``align=True`` to `mne.viz.Brain.show_view` to make views relative to the closest canonical (MNI) axes rather than the native MRI surface RAS coordinates (:gh:`8794` by `Eric Larson`_) + +- Add ``auto_close`` to ``mne.Report.add_figs_to_section`` and ``mne.Report.add_slider_to_section`` to manage closing figures (:gh:`8730` by `Guillaume Favelier`_) + +- Add :func:`mne.write_head_bem` to support writing head surface files (:gh:`8841` by `Yu-Han Luo`_) + +- The signal of ``resp`` (respiratory) channels is now assumed to be in the unit Volt (:gh:`8858` by `Richard Höchenberger`_) + +- Static type checkers like Pylance (comes with VS Code) now display the parameters of many more functions correctly, largely improving overall usability for VS Code users (:gh:`8862` by `Richard Höchenberger`_) + +- Support new EEGLAB file format (:gh:`8874` by `Clemens Brunner`_) + +- Reading and writing FIFF files whose filenames end with ``_meg.fif.gz``, ``_eeg.fif(.gz)``, and ``_ieeg.fif(.gz)`` doesn't emit a warning anymore; this improves interobaility with BIDS-formatted datasets (:gh:`8868` by `Richard Höchenberger`_) + +- On macOS, we now set the environment variable ``QT_MAC_WANTS_LAYER`` to ``"1"`` if it hasn't been set explicitly by the user, in order to ensure that `~mne.SourceEstimate` plots work on macOS 11 with older versions of Qt and PyQt (:gh:`8959` by `Richard Höchenberger`_) + +- :func:`mne.time_frequency.EpochsTFR.average` now allows different ways of averaging, such as "median", or callable functions (:gh:`8879` by `Adam Li`_) + +- `~mne.Epochs` metadata can now be generated automatically from events using `mne.epochs.make_metadata` (:gh:`8834` by `Richard Höchenberger`_) + +- Interactions with sliders in `mne.Report` will now continuously update the linked content (it was updated only on mouse button release before) (:gh:`9023` by `Richard Höchenberger`_) + +- `mne.viz.plot_drop_log` and :meth:`mne.Epochs.plot_drop_log` now omit displaying the subject name in the title if ``subject=None`` is passed (:gh:`9015` by `Richard Höchenberger`_) + +- Plot ECoG tutorial now uses a real epilepsy seizure dataset and visualizes the seizure onset (:gh:`9087` by `Eric Larson`_, `Adam Li`_, `Alex Rockhill`_ and `Liberty Hamilton`_) + +- Improve documentation of Report-Class (:gh:`9113` by `Martin Schulz`_) + +- Add :func:`mne.channels.DigMontage.add_estimated_fiducials` which will add LPA, RPA and Nasion fiducial points to the ``DigMontage`` object in ``mri`` coordinate frame (:gh:`9118` by `Adam Li`_) + +- :func:`mne.io.anonymize_info` now anonymizes also sex and hand fields when ``keep_his`` is ``False`` (:gh:`9103`, :gh:`9175` **by new contributor** |Rotem Falach|_ and `Richard Höchenberger`_) + +- Add parameter ``theme`` to :class:`mne.viz.Brain` for optional Dark-Mode (:gh:`9149` by `Martin Schulz`_, `Guillaume Favelier`_) + +- Add first_samp support for raw simulations with `mne.simulation.simulate_raw` and `mne.simulation.SourceSimulator` (:gh:`9166` by `Steven Bierer`_) + +- `~mne.Evoked` gained a ``baseline`` attribute that is automatically assembled based on the baseline of the averaged `~mne.Epochs` (:gh:`9210` by `Richard Höchenberger`_) + +- Add ``units`` parameter to :meth:`mne.io.Raw.get_data` to return data in the desired unit (:gh:`9136` by `Johann Benerradi`_ and `Stefan Appelhoff`_) + +- Add :func:`mne.preprocessing.equalize_bads` to interpolate bad channels in a list of `~mne.Evoked`, `~mne.Epochs` or `~mne.io.Raw` having different sets of bad channels (:gh:`9241` by `Alex Gramfort`_) + +- :meth:`mne.Epochs.equalize_event_counts` can now be called without providing a list of event names, and will equalize the counts of **all** event types present in the `~mne.Epochs` (:gh:`9261` by `Richard Höchenberger`_) + +- :func:`mne.preprocessing.find_eog_events` and :func:`mne.preprocessing.create_eog_epochs` now accept a list of channel names, allowing you to specify multiple EOG channels at once (:gh:`9269` by `Richard Höchenberger`_) + +- Improve performance of :func:`mne.set_bipolar_reference` (:gh:`9270` by `Martin Schulz`_) + +- Add support for setting montages on fNIRS data, with built in standard montages for Artinis OctaMon and Artinis Brite23 devices (:gh:`9141` by `Johann Benerradi`_, `Robert Luke`_ and `Eric Larson`_) + +- Enable support for reading SNIRF files with 2D optode positions (:gh:`9347` `Robert Luke`_) + + +Bugs +~~~~ +- Fix bug with :func:`mne.time_frequency.tfr` where plot misbehaved. Plot now always returns a list of figures instead of a single figure handle (:gh:`8013` **by new contributor** `Eduard Ort`_) + +- Fix bug with :func:`mne.viz.plot_evoked_topo` where set ylim parameters gets swapped across channel types. (:gh:`9207` **by new contributor** |Ram Pari|_) + +- Fix bug with :func:`mne.io.read_raw_edf` where µV was not correctly recognized (:gh:`9187` **by new contributor** |Sumalyo Datta|_) + +- Fix bug with :func:`mne.viz.plot_compare_evokeds` did not check type of combine. (:gh:`9151` **by new contributor** |Matteo Anelli|_) + +- Fix bug with :func:`mne.viz.plot_evoked_topo` where ``ylim`` was only being applied to the first channel in the dataset (:gh:`9162` **by new contributor** |Ram Pari|_ ) + +- Fix bug with :func:`mne.Epochs.plot_image` allowing interactive zoom to work properly (:gh:`9152` by **by new contributor** |Maggie Clarke|_ and `Daniel McCloy`_) + +- Fix bug with :func:`mne.Epochs.plot_image` where the ``x_label`` was different depending on the evoked parameter (:gh:`9115` **by new contributor** |Matteo Anelli|_) + +- Fix bug with restricting :func:`mne.io.Raw.save` saving options to .fif and .fif.gz extensions (:gh:`9062` **by new contributor** |Valerii Chirkov|_) + +- Fix bug with :func:`mne.io.read_raw_kit` where missing marker coils were not handled (:gh:`8989` **by new contributor** |Judy D Zhu|_) + +- Fix bug with ``mne.connectivity.spectral_connectivity`` where time axis in Epochs data object was dropped. (:gh:`8839` **by new contributor** |Anna Padee|_) + +- Fix bug with `mne.io.Raw.resample` to allow passing ``stim_picks='misc'`` (:gh:`8844` **by new contributor** |Enrico Varano|_ and `Eric Larson`_) + +- Fix bugs with `mne.io.read_raw_persyst` where multiple ``Comments`` with the same name are allowed, and ``Comments`` with a "," character are now allowed (:gh:`8311` and :gh:`8806` **by new contributor** |Andres Rodriguez|_ and `Adam Li`_) + +- Fix zen mode and scalebar toggling for :meth:`raw.plot() ` when using the ``macosx`` matplotlib backend (:gh:`8688` by `Daniel McCloy`_) + +- Fix bug with :func:`mne.viz.snapshot_brain_montage` where the positions were incorrect (:gh:`8983` by `Eric Larson`_) + +- Fix bug with :func:`mne.preprocessing.maxwell_filter` where the eSSS basis had to exactly match the good channels instead of being a superset (:gh:`8675` by `Eric Larson`_) + +- Fix bug with ``mne.Report.add_bem_to_section`` where ``n_jobs != 1`` would cause ``n_jobs`` subsets of MRI images in some orientations to be flipped (:gh:`8713` by `Eric Larson`_) + +- Fix bug with :meth:`raw.plot() ` where annotations didn't immediately appear when changing window duration (:gh:`8689` by `Daniel McCloy`_) + +- Fix bug with :meth:`raw.plot() ` where ``scalings='auto'`` did not compute scalings using the full range of data (:gh:`8806` by `Eric Larson`_) + +- Fix bug with :meth:`raw.plot() ` where setting a ``lowpass`` could lead to non-data-channels not plotting (:gh:`8954` by `Eric Larson`_) + +- Fix bug with :meth:`mne.io.Raw.load_data` and :meth:`mne.Epochs.drop_bad` where ``verbose`` logging was not handled properly (:gh:`8884` by `Eric Larson`_) + +- Fix bug with :func:`mne.io.read_raw_nicolet` where header type values such as num_sample and duration_in_sec where not parsed properly (:gh:`8712` by `Alex Gramfort`_) + +- Fix bug with :func:`mne.preprocessing.read_ica_eeglab` when reading decompositions using PCA dimensionality reduction (:gh:`8780` by `Alex Gramfort`_ and `Eric Larson`_) + +- Fix bug with :func:`mne.minimum_norm.make_inverse_operator` where ``depth`` was errantly restricted to be less than or equal to 1. (:gh:`8804` by `Eric Larson`_) + +- Fix bug with :func:`mne.stats.permutation_cluster_1samp_test` and related clustering functions when ``adjacency=None`` and ``out_type='indices'`` (:gh:`#8842` by `Eric Larson`_) + +- Fix bug with :func:`mne.viz.plot_alignment` where plotting a sphere model could ignore the ``brain`` argument (:gh:`8857` by `Eric Larson`_) + +- Fix bug with :func:`mne.SourceEstimate.plot` where flatmaps were not positioned properly when using ``hemi='both'`` (:gh:`9315` by `Eric Larson`_) + +- Fix bug with :meth:`mne.Annotations.save` where files could be overwritten accidentally, it can now be controlled via the ``overwrite`` argument (:gh:`8896` by `Eric Larson`_) + +- Fix bug with ``replace`` argument of ``mne.Report.add_bem_to_section`` and ``mne.Report.add_slider_to_section`` (:gh:`8723` by `Eric Larson`_) + +- Fix bug with :func:`mne.chpi.compute_chpi_locs` where all cHPI coils being off would lead to an empty array of the wrong dimensionality (:gh:`8956` by `Eric Larson`_) + +- Fix bug with :func:`mne.extract_label_time_course` where labels, STCs, and the source space were not checked for compatible ``subject`` attributes (:gh:`9284` by `Eric Larson`_) + +- Fix bug with :func:`mne.grow_labels` where ``overlap=False`` could run forever or raise an error (:gh:`9317` by `Eric Larson`_) + +- Fix compatibility bugs with ``mne_realtime`` (:gh:`8845` by `Eric Larson`_) + +- Fix bug with `mne.viz.Brain` where non-inflated surfaces had an X-offset imposed by default (:gh:`8794` by `Eric Larson`_) + +- Fix bug with :ref:`mne coreg` where nasion values were not updated when clicking (:gh:`8793` by `Eric Larson`_) + +- Fix bug with matplotlib-based 3D plotting where ``Axes3D`` were not properly initialized in :func:`mne.viz.plot_source_estimates` (:gh:`8811` by `Chris Bailey`_) + +- Allow sEEG channel types in :meth:`mne.Evoked.plot_joint` (:gh:`8736` by `Daniel McCloy`_) + +- Fix bug where hidden annotations could be deleted interactively in :meth:`mne.io.Raw.plot` windows (:gh:`8831` by `Daniel McCloy`_) + +- Function :func:`mne.set_bipolar_reference` was not working when passing ``Epochs`` constructed with some ``picks`` (:gh:`8728` by `Alex Gramfort`_) + +- Fix anonymization issue of FIF files after IO round trip (:gh:`8731` by `Alex Gramfort`_) + +- Fix bug in `mne.preprocessing.ICA.plot_sources` where right-clicking component names could yield `~mne.preprocessing.ICA.plot_properties` windows for the wrong component if ``picks`` had been specified (:gh:`8996` by `Daniel McCloy`_) + +- Fix title not shown in :func:`mne.viz.plot_montage` (:gh:`8752` by `Clemens Brunner`_) + +- `mne.io.read_raw_egi` now correctly handles `pathlib.Path` filenames (:gh:`8759` by `Richard Höchenberger`_) + +- `mne.viz.plot_evoked` and `mne.Evoked.plot` now correctly plot global field power (GFP) for EEG data when ``gfp=True`` or ``gfp='only'`` is passed (used to plot RMS). For MEG data, we continue to plot the RMS, but now label it correctly as such (:gh:`8775` by `Richard Höchenberger`_) + +- Fix bug with :ref:`mne make_scalp_surfaces` where ``--overwrite`` was not functional (:gh:`8800` by `Yu-Han Luo`_) + +- Fix bug with :func:`mne.viz.plot_topomap` when plotting gradiometers with a missing channel in a pair (:gh:`8817` by `Alex Gramfort`_) + +- :meth:`epochs.crop() ` now also adjusts the ``reject_tmin`` and ``reject_tmax`` attributes if necessary (:gh:`8821` by `Richard Höchenberger`_) + +- When creating `~mne.Epochs`, we now ensure that ``reject_tmin`` and ``reject_tmax`` cannot fall outside of the epochs' time interval anymore (:gh:`8821` by `Richard Höchenberger`_) + +- `~mne.io.read_raw_bti` erroneously treated response channels as respiratory channels (:gh:`8856` by `Richard Höchenberger`_) + +- The RMS trace shown in the time viewer of `~mne.SourceEstimate` plots is now correctly labeled as ``RMS`` (was ``GFP`` before) (:gh:`8965` by `Richard Höchenberger`_) + +- Fix bug with :meth:`mne.SourceEstimate.plot` and related functions where the scalars were not interactively updated properly (:gh:`8985` by `Eric Larson`_) + +- Fix bug with mne.channels.find_ch_adjacency() returning wrong adjacency for Neuromag122-Data (:gh:`8891` by `Martin Schulz`_) + +- Fix :func:`mne.read_dipole` yielding :class:`mne.Dipole` objects that could not be indexed (:gh:`8963` by `Marijn van Vliet`_) + +- Fix bug when setting n_jobs > 1 in :meth:`mne.Report.parse_folder` (:gh:`9109` by `Martin Schulz`_) + +- Fix bug with :meth:`mne.Evoked.plot_image` where an incorrect clim parameter did not raise any error (:gh:`9115` **by new contributor** |Matteo Anelli|_) + +- Fix bug with ``mne.io.Raw.pick`` where incorrect fnirs types were returned (:gh:`9178` by `Robert Luke`_) + +- Fix bug when passing both axes and picks to `mne.viz.plot_compare_evokeds` (:gh:`9252` by `Daniel McCloy`_) + +- Improved string representation of `~mne.Epochs` containing multiple event types; improved (and more mathematically correct) ``evoked.comment`` in the `mne.combine_evoked` output; and better (and often more concise) legend labels in the figures created via `~mne.viz.plot_compare_evokeds` (:gh:`9027` by `Richard Höchenberger`_) + +- :func:`mne.preprocessing.find_ecg_events` now correctly handles situation where no ECG activity could be detected, and correctly returns an empty array of ECG events (:gh:`9236` by `Richard Höchenberger`_) + +- Fix bug with ``picks`` attribute for `~mne.Epochs` after calling :meth:`mne.Epochs.add_channels` (:gh:`9246` by `Alex Gramfort`_) + +- Fix bug where ``backend='notebook'`` could not be used in :meth:`mne.SourceEstimate.plot` (:gh:`9305` by `Jean-Rémi King`_) + +- `mne.preprocessing.compute_proj_eog` and `mne.preprocessing.compute_proj_ecg` now return empty lists if no EOG or ECG events, respectively, could be found. Previously, we'd return ``None`` in these situations, which does not match the documented behavior of returning a list of projectors (:gh:`9277` by `Richard Höchenberger`_) + +API changes +~~~~~~~~~~~ +- Introduced new ``'auto'`` settings for ``ICA.max_iter``. The old default ``max_iter=200`` will be removed in MNE-Python 0.24 (:gh:`9099` **by new contributor** |Cora Kim|_) + +- ``mne.viz.plot_sensors_connectivity`` now allows setting the colorbar label via the ``cbar_label`` parameter (:gh:`9248` by `Daniel McCloy`_) + +- ``mne.read_selection`` has been deprecated in favor of `mne.read_vectorview_selection`. ``mne.read_selection`` will be removed in MNE-Python 0.24 (:gh:`8870` by `Richard Höchenberger`_) + +- ``mne.beamformer.tf_dics`` has been deprecated and will be removed in MNE-Python 0.24 (:gh:`9122` by `Britta Westner`_) + +- Fitting `~mne.preprocessing.ICA` on baseline-corrected `~mne.Epochs`, and / or applying it on baseline-corrected `~mne.Epochs` or `~mne.Evoked` data will now display a warning. Users are advised to only baseline correct their data after cleaning is completed (:gh:`9033` by `Richard Höchenberger`_) + +- Supplying multiple channel names to `mne.preprocessing.find_eog_events` or `mne.preprocessing.compute_proj_eog` as a string of comma-separated channel names has been deprecated; please pass a list of channel names instead. Support for comma-separated strings will be removed in MNE-Python 0.24 (:gh:`9269` by `Richard Höchenberger`_) + +- The default in :func:`mne.beamformer.make_dics` of ``real_filter=False`` will change to ``real_filter=True`` in 0.24 (:gh:`9340` by `Britta Westner`_) + +Authors +~~~~~~~ + +People who contributed to this release in alphabetical order +(people with a + are first time contributors): + +* Adam Li +* Alex Rockhill +* Alexandre Gramfort +* Ana Radanovic +* Andres Rodriguez+ +* Anna Padee+ +* Apoorva Karekal+ +* Britta Westner +* Catalina Magalvan +* Christian Brodbeck +* Christian Mista +* Christian O'Reilly +* Christina Zhao +* Christopher J. Bailey +* Clemens Brunner +* Cora Kim+ +* Daniel McCloy +* Denis A. Engemann +* Dominik Welke+ +* Eduard Ort +* Enrico Varano+ +* Eric Larson +* Erica Peterson+ +* Evgenii Kalenkovich +* Felix Klotzsche+ +* Giorgio Marinato +* Guillaume Favelier +* Jack Zhang+ +* Jean-Rémi King +* Johann Benerradi +* Joris Van den Bossche +* Judy D Zhu+ +* Liberty Hamilton +* Luke Bloy +* Maggie Clarke+ +* Mainak Jas +* Manorama Kadwani +* Marijn van Vliet +* Martin Schulz +* Matt Sanderson+ +* Matteo Anelli+ +* Nicolas Gensollen +* Ram Pari+ +* Richard Höchenberger +* Richard Koehler+ +* Robert Luke +* Rotem Falach+ +* Sebastien Treguer +* Silvia Cotroneo+ +* Stefan Appelhoff +* Steven Bierer +* Sumalyo Datta+ +* Timon Merk +* Tristan Stenner +* Valerii Chirkov+ +* Victoria Peterson +* Yu-Han Luo +* Zhi Zhang+ diff --git a/mne-python/source/doc/changes/v0.24.rst b/mne-python/source/doc/changes/v0.24.rst new file mode 100644 index 0000000000000000000000000000000000000000..f36191d8af1ef48920271e1aaab2f8efce9e3c50 --- /dev/null +++ b/mne-python/source/doc/changes/v0.24.rst @@ -0,0 +1,411 @@ +.. _changes_0_24_0: + +Version 0.24.0 (2021-11-03) +--------------------------- + +.. |David Julien| replace:: **David Julien** + +.. |Dominique Makowski| replace:: **Dominique Makowski** + +.. |Romain Derollepot| replace:: **Romain Derollepot** + +.. |Jan Sosulski| replace:: **Jan Sosulski** + +.. |Xiaokai Xia| replace:: **Xiaokai Xia** + +.. |Marian Dovgialo| replace:: **Marian Dovgialo** + +.. |Pierre-Antoine Bannier| replace:: **Pierre-Antoine Bannier** + +.. |Darin Erat Sleiter| replace:: **Darin Erat Sleiter** + +.. |Mathieu Scheltienne| replace:: **Mathieu Scheltienne** + +.. |Timothy Gates| replace:: **Timothy Gates** + +.. |Reza Shoorangiz| replace:: **Reza Shoorangiz** + +.. |Evgeny Goldstein| replace:: **Evgeny Goldstein** + +.. |Joshua Teves| replace:: **Joshua Teves** + +.. |Riessarius Stargardsky| replace:: **Riessarius Stargardsky** + +.. |John Samuelsson| replace:: **John Samuelsson** + +Enhancements +~~~~~~~~~~~~ +.. - Add something cool (:gh:`9192` **by new contributor** |New Contributor|_) + +- Add ``pooch`` to system information reports (:gh:`9801` **by new contributor** |Joshua Teves|_) + +- Get annotation descriptions from the name field of SNIRF stimulus groups when reading SNIRF files via `mne.io.read_raw_snirf` (:gh:`9575` **by new contributor** |Darin Erat Sleiter|_) + +- Add support for NIRSport and NIRSport2 devices to `mne.io.read_raw_nirx` (:gh:`9348` and :gh:`9401` **by new contributor** |David Julien|_, **new contributor** |Romain Derollepot|_, `Robert Luke`_, and `Eric Larson`_) + +- New function :func:`mne.Dipole.to_volume_labels` to get atlas label for MRI coordinates. (:gh:`9376` by **new contributor** |Marian Dovgialo|_) + +- Add support for SURE parameter selection in :func:`mne.inverse_sparse.mixed_norm` and make ``alpha`` parameter now default to ``'sure'`` (:gh:`9430` by **new contributor** |Pierre-Antoine Bannier|_ and `Alex Gramfort`_) + +- Speed up BCD solver in :func:`mne.inverse_sparse.mixed_norm` by adding Anderson acceleration (:gh:`9481` by **new contributor** |Pierre-Antoine Bannier|_ and `Alex Gramfort`_) + +- Add support for list of channel types for EEG/sEEG/ECoG/DBS referencing (:gh:`9637` **by new contributor** |Mathieu Scheltienne|_) + +- Add the ability to set point size and line width in :func:`mne.viz.plot_sensors` and related functions (:gH:`9872` **by new contributor** |Dominique Makowski|_) + +- Add support for changing the default event id used by :func:`mne.make_fixed_length_epochs` (:gh:`9782` **by new contributor** |Mathieu Scheltienne|_) + +- Improve documentation for arguments ``threshold``, ``method`` and ``measure`` of ICA methods `~mne.preprocessing.ICA.find_bads_ecg`, `~mne.preprocessing.ICA.find_bads_ref` and `~mne.preprocessing.ICA.find_bads_eog` (:gh:`9858` **by new contributor** |Mathieu Scheltienne|_) + +- Add support for more than 3 source estimates in :func:`mne.viz.plot_sparse_source_estimates` (:gh:`9640` **by new contributor** |Pierre-Antoine Bannier|_ and `Alex Gramfort`_) + +- Add cortical signal suppression (CSS) :func:`mne.preprocessing.cortical_signal_suppression` (:gh:`6888`, :gh:`9892` **by new contributor** |John Samuelsson|_ and `Eric Larson`_) + +- Show all good channel types and counts when printing a :class:`mne.Info` in the notebook (:gh:`9725` by `Valerii Chirkov`_ and `Eric Larson`_) + +- Speed up point decimation in :func:`mne.io.read_raw_kit` by vectorization and use of :class:`scipy.spatial.cKDTree` (:gh:`9568` by `Jean-Rémi King`_ and `Eric Larson`_) + +- Add ability to export EDF+ files using :func:`mne.export.export_raw` (:gh:`9643` by `Adam Li`_) + +- New function :func:`mne.chpi.get_chpi_info` to retrieve basic information about the cHPI system used when recording MEG data (:gh:`9369` by `Richard Höchenberger`_) + +- New namespace `mne.export` created to contain functions (such as `mne.export.export_raw` and `mne.export.export_epochs`) for exporting data to non-FIF formats (:gh:`9427` by `Eric Larson`_) + +- Add support for Hitachi fNIRS devices in `mne.io.read_raw_hitachi` (:gh:`9391` by `Eric Larson`_) + +- Add support for ``picks`` in :func:`mne.stc_near_sensors` (:gh:`9396` by `Eric Larson`_) + +- Add label methods `mne.Label.compute_area` and `mne.Label.distances_to_outside` (:gh:`9424` by `Eric Larson`_) + +- Add projections when printing a :class:`mne.Info` in the notebook (:gh:`9403` by `Alex Gramfort`_) + +- Add new function :func:`mne.bem.make_scalp_surfaces` to compute scalp surfaces for coregistration (:gh:`9463` by `Alex Gramfort`_) + +- Add support for interpolating oxy and deoxyhaemoglobin data types (:gh:`9431` by `Robert Luke`_) + +- Add support for SNIRF files in :class:`mne.Report` (:gh:`9443` by `Robert Luke`_) + +- Add support for exporting MFF evoked files using `mne.export.export_evokeds` and `mne.export.export_evokeds_mff` (:gh:`9406` by `Evan Hathaway`_) + +- :func:`mne.concatenate_raws`, :func:`mne.concatenate_epochs`, and :func:`mne.write_evokeds` gained a new parameter ``on_mismatch``, which controls behavior in case not all of the supplied instances share the same device-to-head transformation (:gh:`9438` by `Richard Höchenberger`_) + +- Add support for multiple datablocks (acquisitions with pauses) in :func:`mne.io.read_raw_nihon` (:gh:`9437` by `Federico Raimondo`_) + +- Add new function :func:`mne.preprocessing.annotate_break` to automatically detect and mark "break" periods without any marked experimental events in the continuous data (:gh:`9445` by `Richard Höchenberger`_) + +- Add "time_format" to :meth:`mne.io.Raw.plot` and :meth:`mne.preprocessing.ICA.plot_sources` to display acquisition time on x-axis (:gh:`9419` by `Martin Schulz`_) + +- Speed up :meth:`mne.decoding.TimeDelayingRidge.predict` by switching to FFT-based convolution (:gh:`9458` by `Ross Maddox`_) + +- Show multiple colors and linestyles for excluded components with :class:`mne.Evoked` in :meth:`mne.preprocessing.ICA.plot_sources` (:gh:`9444` by `Martin Schulz`_) + +- Add functions for aligning MRI and CT data `mne.transforms.compute_volume_registration` and `mne.transforms.apply_volume_registration` (:gh:`9503` by `Alex Rockhill`_ and `Eric Larson`_) + +- Add tutorial for how to processes image (CT and MR) files in order to localize electrode contacts for intracranial recordings :ref:`tut-ieeg-localize` (:gh:`9484` by `Alex Rockhill`_) + +- Add vertex number in source space for :meth:`mne.VolSourceEstimate.plot` and :func:`mne.viz.plot_volume_source_estimates` (:gh:`9697` by `Eric Larson`_) + +- Add support for colormap normalization in :func:`mne.viz.plot_topomap` (:gh:`9468` by `Clemens Brunner`_) + +- Update :func:`mne.preprocessing.realign_raw` with Numpy-recommended polynomial fitting method (:gh:`9514` by `Erica Peterson`_) + +- Add a warning to `mne.preprocessing.nirs.beer_lambert_law` when source-detector distances are zero (:gh:`9541` by `Eric Larson`_) + +- Add ``exclude`` parameter to :meth:`mne.io.Raw.plot_psd` and :meth:`mne.Epochs.plot_psd` (:gh:`9519` by `Clemens Brunner`_) + +- Add `mne.Annotations.rename` to rename annotation descriptions (:gh:`9525` by `Robert Luke`_) + +- Add `mne.Annotations.set_durations` to set annotation durations (:gh:`9529` by `Robert Luke`_) + +- The ``exclude`` parameter in `mne.io.read_raw_edf`, `mne.io.read_raw_bdf`, and `mne.io.read_raw_gdf` now also accepts a regular expression (:gh:`9558` by `Clemens Brunner`_) + +- Add :meth:`mne.Evoked.get_data` method to :class:`mne.Evoked` (:gh:`9555` by `Stefan Appelhoff`_) + +- The :meth:`mne.Epochs.get_data` method now has a ``units`` parameter (:gh:`9553` by `Stefan Appelhoff`_) + +- Add ``mne.warp_montage_volume`` to use an anatomical volume with channel locations at high or low insensities to apply a symmetric diffeomorphic registration to a template (e.g. fsaverage) space (:gh:`9544` by `Alex Rockhill`_) + +- :meth:`mne.io.Raw.get_data`, :meth:`mne.Epochs.get_data`, and :meth:`mne.Evoked.get_data` methods now have ``tmin`` and ``tmax`` parameters to specify data window in seconds to get (:gh:`9556` by `Stefan Appelhoff`_) + +- The :meth:`mne.Evoked.get_data` method now has a ``units`` parameter (:gh:`9578` by `Stefan Appelhoff`_) + +- Add `mne.chpi.compute_chpi_snr` and `mne.viz.plot_chpi_snr` for computing and plotting the time-varying SNR of continuously-active HPI coils (:gh:`9570` by `Daniel McCloy`_ and `Jussi Nurminen`_) + +- Add :func:`mne.get_montage_volume_labels` to find the regions of interest in a Freesurfer atlas anatomical segmentation for an intracranial electrode montage and :func:`mne.viz.plot_channel_labels_circle` to plot them (:gh:`9545` by `Alex Rockhill`_) + +- Add :func:`mne.viz.Brain.add_volume_labels` to plot subcortical surfaces and other regions of interest (:gh:`9540` by `Alex Rockhill`_ and `Eric Larson`_) + +- Add custom cortex curvature colors in :class:`mne.viz.Brain` via the ``cortex`` argument (:gh:`9750` by `Eric Larson`_) + +- Add :meth:`mne.channels.DigMontage.apply_trans` to apply a transform directly to a montage (:gh:`9601` by `Alex Rockhill`_) + +- :meth:`mne.preprocessing.ICA.fit` now emits a warning if any of the ``start``, ``stop``, ``reject``, and ``flat`` parameters are passed when performing ICA on `~mne.Epochs`. These parameters only have an effect on `~mne.io.Raw` data and were previously silently ignored in the case of `~mne.Epochs` (:gh:`9605` by `Richard Höchenberger`_) + +- :func:`mne.viz.plot_alignment` now emits a warning (instead of aborting with an exception) if the surfaces contain topological defects (:gh:`9614` by `Richard Höchenberger`_) + +- The coregistration GUI can now display the head surface even if there are topological defects. Previously, a low-resolution standard head unsuitable for individualized coregistration was displayed (:gh:`9614` by `Richard Höchenberger`_) + +- New :class:`mne.coreg.Coregistration` object to allow coregistration scripting without a dependency on mayavi (:gh:`9516` by `Guillaume Favelier`_). + +- Add :meth:`mne.viz.Brain.add_head` to plot the head surface (:gh:`9618` by `Alex Rockhill`_) + +- Add :func:`mne.channels.read_dig_localite` to read Localite electrode location files (:gh:`9658` by `Clemens Brunner`_) + +- Add :meth:`mne.viz.Brain.add_sensors` to plot sensor locations (:gh:`9585` by `Alex Rockhill`_) + +- Add :func:`mne.coreg.estimate_head_mri_t` to estimate the head->mri transform from fsaverage fiducials (:gh:`9585` by `Alex Rockhill`_) + +- Add :meth:`mne.channels.DigMontage.add_mni_fiducials` to add fiducials to a montage in MNI coordinates (:gh:`9682` by `Alex Rockhill`_) + +- Add :meth:`mne.channels.DigMontage.remove_fiducials` to remove fiducials under rare circumstances when the coordinate frame should not be set to "head" (:gh:`9684` by `Alex Rockhill`_) + +- Add remove methods for mesh objects in :class:`mne.viz.Brain` (:gh:`9688` by `Alex Rockhill`_) + +- Add ``--show-paths`` and ``--developer`` options to :ref:`mne sys_info` (:gh:`9789` by `Eric Larson`_) + +- Add ability to export EDF+ files using :func:`mne.export.export_raw` (:gh:`9643` by `Adam Li`_) + +- Reading EDF files via :func:`mne.io.read_raw_edf` now can infer channel type from the signal label in the EDF header (:gh:`9694` by `Adam Li`_) + +- Add ``mne.gui.locate_ieeg`` to locate intracranial electrode contacts from a CT, an MRI (with Freesurfer ``recon-all``) and the channel names from an :class:`mne.Info` object (:gh:`9586` by `Alex Rockhill`_) + +- All data fetching code now relies on ``pooch``, which is an added optional requirement for dataset fetchers (:gh:`9742` by `Adam Li`_ and `Daniel McCloy`_) + +- Add phantom FreeSurfer subject fetcher :func:`mne.datasets.fetch_phantom` to allow fetching the Otaniemi phantom (:gh:`9796` by `Eric Larson`_) + +- Add :func:`mne.datasets.fetch_dataset` to allow packages to fetch datasets in a similar fashion to MNE (:gh:`9763` by `Adam Li`_) + +- Add full ECoG dataset to MNE-misc-data and demonstrate its use in :ref:`ex-electrode-pos-2d` and :ref:`tut-ieeg-localize` (:gh:`9784` by `Alex Rockhill`_) + +- Add options ``tol`` and ``accuracy`` to :func:`mne.fit_dipole` to control optimization (:gh:`9810` by `Eric Larson`_) + +- Completely revamp the `~mne.Report` experience: new HTML layout, many new methods, more flexibility; the functionality is demonstrated in :ref:`tut-report` (:gh:`9754`, :gh:`9828`, :gh:`9847`, :gh:`9860`, :gh:`9861`, :gh:`9862`, :gh:`9863`, :gh:`9871`, :gh:`9881`, :gh:`9891`, :gh:`9901` by `Richard Höchenberger`_, `Eric Larson`_, and `Alex Gramfort`_) + +- Add basic HTML representations of `~mne.Forward` and `~mne.minimum_norm.InverseOperator` instances for a nicer Jupyter experience (:gh:`9754` by `Richard Höchenberger`_) + +- `mne.io.read_raw_brainvision` now handles ASCII data with comma-separated values, as may be exported from BrainVision Analyzer (:gh:`9795` by `Richard Höchenberger`_) + +- Add :func:`mne.preprocessing.ieeg.project_sensors_onto_brain` to project ECoG sensors onto the pial surface to compensate for brain shift (:gh:`9800` by `Alex Rockhill`_) + +- Add support for data acquired with NIRx devices using Aurora software version 2021.9 (:gh:`9800` by `Robert Luke`_, and `Eric Larson`_) + +- All functions for reading and writing files should now automatically handle ``~`` (the tilde character) and expand it to the user's home directory. Should you come across any function that doesn't do it, please do let us know! (:gh:`9613`, :gh:`9845` by `Richard Höchenberger`_) + +- All functions accepting a FreeSurfer subjects directory via a ``subjects_dir`` parameter can now consume :class:`pathlib.Path` objects too (used to be only strings) (:gh:`9613` by `Richard Höchenberger`_) + +- Add support for colormap normalization in :meth:`mne.time_frequency.AverageTFR.plot` (:gh:`9851` by `Clemens Brunner`_) + +- Add support for BIDS-compatible filenames when splitting big epochs files via the new ``split_naming`` parameter in :meth:`mne.Epochs.save` (:gh:`9869` by `Denis Engemann`_) + +- Add ``by_event_type`` parameter to :meth:`mne.Epochs.average` to create a list containing an :class:`mne.Evoked` object for each event type (:gh:`9859` by `Marijn van Vliet`_) + +- Add pyqtgraph as a new backend for :meth:`mne.io.Raw.plot` (:gh:`9687` by `Martin Schulz`_) + +- Add :func:`mne.viz.set_browser_backend`, :func:`mne.viz.use_browser_backend` and :func:`mne.viz.get_browser_backend` to set matplotlib or pyqtgraph as backend for :meth:`mne.io.Raw.plot` (:gh:`9687` by `Martin Schulz`_) + +Bugs +~~~~ +- Fix bug in :meth:`mne.io.Raw.pick` and related functions when parameter list contains channels which are not in info instance (:gh:`9708` **by new contributor** |Evgeny Goldstein|_) + +- Fix a few typos (:gh:`9706` **by new contributor** |Timothy Gates|_) + +- Fix bug with :meth:`mne.Epochs.crop` and :meth:`mne.Evoked.crop` when ``include_tmax=False``, where the last sample was always cut off, even when ``tmax > epo.times[-1]`` (:gh:`9378` **by new contributor** |Jan Sosulski|_) + +- Fix bug with `mne.io.read_raw_curry` to allow reading Curry 7 and 8 event files with '.ceo' and '.cdt.ceo' extensions (:gh:`9381`, :gh:`9712` by **new contributor** |Xiaokai Xia|_, `Daniel McCloy`_, and **by new contributor** |Reza Shoorangiz|_) + +- Fix bug with `mne.compute_rank`, `mne.cov.compute_whitener` and `mne.preprocessing.ICA.fit` when explicit picks including bad channels are provided (:gh:`9719` **by new contributor** |Mathieu Scheltienne|_) + +- Fix bug with :func:`mne.concatenate_epochs` where the concatenated events could end up in non-chronological order. (:gh:`9765` **by new contributor** |Jan Sosulski|_) + +- Fix bug where :func:`mne.time_frequency.psd_array_welch` and :func:`mne.time_frequency.psd_array_multitaper` failed to handle negative integer for ``n_jobs`` argument (:gh:`9849` **by new contributor** |Riessarius Stargardsky|_) + +- Fix bug where resampling returns empty instances (:gh:`9897` **by new contributor** |Mathieu Scheltienne|_ and `Eric Larson`_) + +- Fix bug with `mne.io.Raw.get_montage` now returning both good and bad channels in the montage. (:gh:`9920` **by new contributor** |Mathieu Scheltienne|_) + +- Fix bug with :func:`mne.io.read_raw_nihon` where latin-1 annotations could not be read (:gh:`9384` by `Alex Gramfort`_) + +- Fix bug when printing a :class:`mne.io.RawArray` in the notebook (:gh:`9404` by `Alex Gramfort`_) + +- Fix bug when computing rank from info for SSS data with only gradiometers or magnetometers (:gh:`9435` by `Alex Gramfort`_) + +- Fix bug with `mne.preprocessing.find_bad_channels_maxwell` where all-flat segments could lead to an error (:gh:`9531` by `Eric Larson`_) + +- Fix bug with `mne.io.Raw.set_montage` and related functions where the channel coordinate frame was not properly set to head (:gh:`9447` by `Eric Larson`_) + +- Fix bug with `mne.io.read_raw_fieldtrip` and `mne.read_epochs_fieldtrip` where channel positions were not set properly (:gh:`9447` by `Eric Larson`_) + +- Fix bug with :func:`mne.io.read_raw_kit` where omitting HPI coils could lead to an :exc:`python:AssertionError` on reading (:gh:`9612` by `Eric Larson`_) + +- Fix bug with :func:`mne.io.read_raw_edf` where reading only stimulus channels would lead to an error (:gh:`9831` by `Eric Larson`_) + +- Fix bug with `mne.preprocessing.nirs.optical_density` where protection against zero values was not guaranteed (:gh:`9522` by `Eric Larson`_) + +- :func:`mne.concatenate_raws` now raises an exception if ``raw.info['dev_head_t']`` differs between files. This behavior can be controlled using the new ``on_mismatch`` parameter (:gh:`9438` by `Richard Höchenberger`_) + +- Fixed bug in :meth:`mne.Epochs.drop_bad` where subsequent rejections failed if they only specified thresholds for a subset of the channel types used in a previous rejection (:gh:`9485` by `Richard Höchenberger`_). + +- Fix bug with `mne.simulation.simulate_evoked`, `mne.apply_forward`, and `mne.apply_forward_raw` where systems with EEG channels that come before MEG channels would have them mixed up in the output evoked or raw object (:gh:`#9513` by `Eric Larson`_) + +- In :func:`mne.viz.plot_ica_scores` and :meth:`mne.preprocessing.ICA.plot_scores`, the figure and axis titles no longer overlap when plotting only a single EOG or ECG channel (:gh:`9489` by `Richard Höchenberger`_). + +- Ensure `mne.io.Raw.get_montage` works with SNIRF data (:gh:`9524` by `Robert Luke`_) + +- Fix bug in :func:`mne.setup_volume_source_space` where non-finite positions could be used in a discrete source space (:gh:`9603` by `Eric Larson`_) + +- Fix bug in :func:`mne.viz.plot_topomap` (and related methods like :meth:`mne.Evoked.plot_topomap`) where large distances between electrodes (higher than head radius) would lead to an error (:gh:`9528` by `Mikołaj Magnuski`_). + +- Fix bug in `mne.viz.plot_topomap` (and related methods) where passing ``axes`` that are part of a matplotlib figure that uses a constrained layout would emit warnings (:gh:`9558` by `Eric Larson`_) + +- Fix bug in :func:`mne.make_forward_solution` where impossible sensor-BEM geometries were not checked (:gh:`9893` by `Eric Larson`_) + +- Fix bug in :func:`mne.concatenate_epochs` when concatenating :class:`mne.Epochs` objects with 0 events (:gh:`9535` by `Marijn van Vliet`_) + +- Fix bug in :func:`mne.viz.Brain.screenshot` where the RGBA mode was not supported (:gh:`9564` by `Guillaume Favelier`_). + +- Fix bug in :func:`mne.io.read_raw_egi` where reading data from a data segment that is part of an acquisition skip would lead to an error (:gh:`9565` by `Eric Larson`_) + +- Prevent :meth:`mne.io.Raw.plot` windows from spawning at sizes too small to properly render (:gh:`9629` by `Daniel McCloy`_) + +- Fix bug where :meth:`mne.io.Raw.plot` raised an error when plotting raw dipole data (:gh:`9771` by `Eric Larson`_) + +- Fix bug in ::meth:`mne.preprocessing.ICA.find_bads_ecg` where passing ``start`` and ``stop`` lead to erroneous data windows depending on the combination of Raw, Epochs, Evoked, and the type (int, float, None) of ``start`` and ``stop`` (:gh:`9556` by `Stefan Appelhoff`_) + +- Fix bug in :func:`mne.viz.set_3d_backend` and :func:`mne.viz.get_3d_backend` where the PyVistaQt-based backend was ambiguously named ``'pyvista'`` instead of ``'pyvistaqt'``; use ``set_3d_backend('pyvistaqt')`` and expect ``'pyvistaqt'`` as the output of :func:`mne.viz.get_3d_backend` instead of ``'pyvista'``, and consider using ``get_3d_backend().startswith('pyvista')`` for example for backward-compatible conditionals (:gh:`9607` by `Guillaume Favelier`_) + +- Fix bug in :func:`mne.viz.plot_compare_evokeds` where confidence bands were not drawn if only one condition was plotted (:gh:`9663` by `Daniel McCloy`_) + +- Fix bug where setting of a montage with fNIRS data got set to "unknown" coordinate frame when it should have been in "head" (:gh:`9630` by `Alex Rockhill`_) + +- Fix bug where "seeg", "ecog", "dbs" and "fnirs" data had coordinate frame unknown upon loading from a file when it should have been in "head" (:gh:`9580` by `Alex Rockhill`_) + +- Raise error when no ``trans`` is provided to :func:`mne.viz.plot_alignment` when required instead of assuming identity head->mri transform (:gh:`9585` by `Alex Rockhill`_) + +- Fix bug where :meth:`mne.Epochs.equalize_event_counts` failed when only one good epoch existed for one of the event types (:gh:`9758` by `Daniel McCloy`_) + +- Fix bug where channels with a dollar sign ($) were not being labeled "misc" in :func:`mne.io.read_raw_nihon` (:gh:`9695` by `Adam Li`_) + +- Fix bug where :func:`mne.io.read_raw_persyst` was lower-casing events it found in the ``.lay`` file (:gh:`9746` by `Adam Li`_) + +- Fix bug with Qhull when plotting OPM sensors in :func:`mne.viz.plot_alignment` (:gh:`9799` and :gh:`9804` by `Eric Larson`_) + +- Fix bug where :func:`mne.io.read_raw_snirf` was including the landmark index as a spatial coordinate (:gh:`9777` by `Robert luke`_) + +- Fix bug where `mne.Annotations` were not appending channel names when being added together (:gh:`9780` by `Adam Li`_) + +- `mne.viz.plot_evoked_joint` now correctly handles a ``times='peaks'`` parameter value (:gh:`9754` by `Richard Höchenberger`_) + +- In `mne.viz.plot_compare_evokeds`, slightly adjust the x-axis limit calculation to avoid drawing an axis that is too short (:gh:`9754` by `Richard Höchenberger`_) + +- Fix a bug with :func:`mne.viz.snapshot_brain_montage` with the Mayavi backend where electrodes were shown in the wrong positions, and with the PyVista backend where the snapshot always contained the electrodes but could be missing a hemisphere (:gh:`9933` by `Eric Larson`_) + +- In :meth:`mne.io.Raw.plot_psd` and :meth:`mne.Epochs.plot_psd`, avoid overlap between subplot titles and x-axis tick labels (:gh:`9864` by `Richard Höchenberger`_) + +- In :meth:`mne.Epochs.plot_psd_topomap`, the data is now scaled to match the output of :meth:`mne.Epochs.plot_psd` (:gh:`9873` by `Richard Höchenberger`_) + +- Fix channel locations with ``NaN`` values causing all channel locations not to be plotted in :func:`mne.viz.Brain.add_sensors` (:gh:`9911` by `Alex Rockhill`_) + +- Fix infinite loop bug in :func:`mne.get_montage_volume_labels` (:gh:`9940` by `Alex Rockhill`_) + +API changes +~~~~~~~~~~~ +- The :class:`mne.Info` class is now more strictly checked when attributes are set. Setting most attributes directly will lead to an error in the next release. See the docstring of :class:`mne.Info` for more information (:gh:`9867` **by new contributor** |Mathieu Scheltienne|_) + +- The Mayavi 3D backend has been deprecated (:gh:`9904` by `Eric Larson`_): + + - In 3D plotting functions, use PyVista-based backends (``'pyvistaqt'`` and ``'notebook'``) as PySurfer/Mayavi will be removed in the next version + + - To use the :ref:`mne kit2fiff` command-line GUI for fiducial markers, install the separate ``mne-kit-gui`` module, which can still be launched via ``$ mne kit2fiff`` + + - The ``mne.gui.fiducials`` GUI has been deprecated, use :ref:`mne coreg` or ``mne_kit_gui.fiducials()`` to set MRI fiducials instead + +- In `mne.compute_source_morph`, the ``niter_affine`` and ``niter_sdr`` parameters have been replaced by ``niter`` and ``pipeline`` parameters for more consistent and finer-grained control of registration/warping steps and iteration (:gh:`9505` by `Alex Rockhill`_ and `Eric Larson`_) + +- Split :func:`mne.viz.Brain.show_view` argument ``view`` into ``azimuth``, ``elevation`` and ``focalpoint`` for clearer view setting and make the default for ``row`` and ``col`` apply to all rows and columns (:gh:`9596` by `Alex Rockhill`_) + +- Deprecate ``solver='prox'`` in :func:`mne.inverse_sparse.mixed_norm` in favor of ``solver='cd'`` and ``solver='bcd'`` as coordinate descent solvers consistently outperform proximal gradient descent (:gh:`9608` by `Pierre-Antoine Bannier`_) + +- All ``mne.connectivity`` functions have moved to the ``mne-connectivity`` package; they are deprecated in MNE-Python and will be removed in version 0.25 (:gh:`9493` by `Adam Li`_). + +- :func:`mne.inverse_sparse.mixed_norm` now simply warns when source estimates contain no dipole, e.g. if data are too noisy and alpha is based on SURE (:gh:`9685` by `Alex Gramfort`_) + +- Deprecate functions :samp:`mne.datasets.{DATASET_NAME}.has_{DATASET_NAME}_data()` for these datasets: ``epilepsy_ecog``, ``fnirs_motor``, ``multimodal``, ``opm``, ``phantom_4dbti``, ``refmeg_noise``, ``sample``, ``somato``, and ``ssvep``. Use the generic :func:`mne.datasets.has_dataset` instead (:gh:`9781` by `Daniel McCloy`_ and `Adam Li`_) + +- :class:`mne.Report` modernization has led to multiple deprecations (:gh:`9754` by `Richard Höchenberger`_): + + - ``mne.Report.add_figs_to_section`` and ``mne.Report.add_slider_to_section`` have been deprecated in favor of :meth:`mne.Report.add_figure` + + - ``mne.Report.add_images_to_section`` has been deprecated in favor of :meth:`mne.Report.add_image` + + - ``mne.Report.add_bem_to_section`` has been deprecated in favor of :meth:`mne.Report.add_bem` + + - ``mne.Report.add_htmls_to_section`` has been deprecated in favor of :meth:`mne.Report.add_html` + + - In :meth:`mne.Report.parse_folder`, the ``sort_sections`` parameter has been deprecated in favor of ``sort_content`` + + - In :meth:`mne.Report.remove`, the ``caption`` and ``section`` parameters have been deprecated in favor of ``title`` and ``tags``, respectively + + - The ``mne.Report.sections`` attribute has been deprecated in favor of ``mne.Report.tags`` + + - The ``mne.Report.fnames`` attribute has been deprecated without replacement + +- :meth:`mne.Epochs.plot` and :func:`mne.viz.plot_epochs` gained parameter ``show_scalebars`` analogous to :meth:`mne.viz.plot_raw` (:gh:`9815` by `Daniel McCloy`_) + +- The output folder name for HF_SEF datasets is now ``hf_sef`` instead of ``HF_SEF`` (:gh:`9763` by `Adam Li`_) + +- Deprecate ``mne.viz.utils.center_cmap`` (:gh:`9851` by `Clemens Brunner`_) + +- The default partial pathlength factor of :func:`mne.preprocessing.nirs.beer_lambert_law` will change from 0.1 in 0.24 to 6.0 in the next release (:gh:`9843` by `Robert Luke`_) + +- ``mne.preprocessing.ICA.detect_artifacts`` has been deprecated. Please use `~mne.preprocessing.ICA.find_bads_eog` and `~mne.preprocessing.ICA.find_bads_ecg` instead (:gh:`9909` by `Richard Höchenberger`_) + +Authors +~~~~~~~ +People who contributed to this release in alphabetical order +(people with a + are first time contributors): + +* Adam Li +* Alex Rockhill +* Alexandre Gramfort +* Britta Westner +* Clemens Brunner +* Daniel McCloy +* Darin Erat Sleiter+ +* David Julien+ +* Denis A. Engemann +* Dominique Makowski+ +* Eric Larson +* Erica Peterson +* Evan Hathaway +* Evgeny Goldstein+ +* Fede Raimondo +* Gansheng Tan+ +* Guillaume Favelier +* Hubert Banville +* Jan Sosulski+ +* Jean-Rémi King +* Jeff Stout +* Johann Benerradi +* John Samuelsson+ +* Josh Koen+ +* Joshua Teves+ +* Lukas Hecker+ +* Luke Bloy +* Marian Dovgialo+ +* Marijn van Vliet +* Martin Schulz +* Mathieu Scheltienne+ +* Mikołaj Magnuski +* Pierre-Antoine Bannier+ +* Reza Shoorangiz+ +* Richard Höchenberger +* Riessarius Stargardsky+ +* Robert Luke +* Romain Derollepot+ +* Ross Maddox +* Ryan Law+ +* Stefan Appelhoff +* Steve Matindi+ +* Timothy Gates+ +* Valerii Chirkov +* Xiaokai Xia+ diff --git a/mne-python/source/doc/changes/v0.3.rst b/mne-python/source/doc/changes/v0.3.rst new file mode 100644 index 0000000000000000000000000000000000000000..9c61d8c482b91f3877eb39e9ca574f2889467e22 --- /dev/null +++ b/mne-python/source/doc/changes/v0.3.rst @@ -0,0 +1,40 @@ +.. _changes_0_3: + +Version 0.3 (2012-03-23) +------------------------ + +Changelog +~~~~~~~~~ + +- Sign flip computation for robust label average of signed values by `Alex Gramfort`_. + +- Reading and writing of .w files by `Martin Luessi`_. + +- Support for modifying Raw object and allow raw data preloading with memory mapping by `Martin Luessi`_ and `Alex Gramfort`_. + +- Support of arithmetic of Evoked data (useful to concatenate between runs and compute contrasts) by `Alex Gramfort`_. + +- Support for computing sensor space data from a source estimate using an MNE forward solution by `Martin Luessi`_. + +- Support of arithmetic of Covariance by `Alex Gramfort`_. + +- Write BEM surfaces in Python by `Alex Gramfort`_. + +- Filtering operations and apply_function interface for Raw object by `Martin Luessi`_. + +- Support for complex valued raw fiff files and computation of analytic signal for Raw object by `Martin Luessi`_. + +- Write inverse operators (surface and volume) by `Alex Gramfort`_. + +- Covariance matrix computation with multiple event types by `Martin Luessi`_. + +- New tutorial in the documentation and new classes and functions reference page by `Alex Gramfort`_. + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number +of commits): + +* 80 Alexandre Gramfort +* 51 Martin Luessi diff --git a/mne-python/source/doc/changes/v0.4.rst b/mne-python/source/doc/changes/v0.4.rst new file mode 100644 index 0000000000000000000000000000000000000000..680e5fe8123ef2dde2e31a42f263e75dd76cffcc --- /dev/null +++ b/mne-python/source/doc/changes/v0.4.rst @@ -0,0 +1,52 @@ +.. _changes_0_4: + +Version 0.4 (2012-08-24) +------------------------ + +Changelog +~~~~~~~~~ + +- Add function to compute source PSD using minimum norm by `Alex Gramfort`_ + +- L21 Mixed Norm Estimates (MxNE) by `Alex Gramfort`_ and `Daniel Strohmeier`_ + +- Generation of simulated evoked responses by `Alex Gramfort`_, `Daniel Strohmeier`_, and `Martin Luessi`_ + +- Fit AR models to raw data for temporal whitening by `Alex Gramfort`_. + +- speedup + reduce memory of mne.morph_data by `Alex Gramfort`_. + +- Backporting scipy.signal.firwin2 so filtering works with old scipy by `Alex Gramfort`_. + +- LCMV Beamformer for evoked data, single trials, and raw data by `Alex Gramfort`_ and `Martin Luessi`_. + +- Add support for reading named channel selections by `Martin Luessi`_. + +- Add Raw.filter method to more easily band pass data by `Alex Gramfort`_. + +- Add tmin + tmax parameters in mne.compute_covariance to estimate noise covariance in epochs baseline without creating new epochs by `Alex Gramfort`_. + +- Add support for sLORETA in apply_inverse, apply_inverse_raw, apply_inverse_epochs (API Change) by `Alex Gramfort`_. + +- Add method to regularize a noise covariance by `Alex Gramfort`_. + +- Read and write measurement info in forward and inverse operators for interactive visualization in mne_analyze by `Alex Gramfort`_. + +- New mne_compute_proj_ecg.py and mne_compute_proj_eog.py scripts to estimate ECG/EOG PCA/SSP vectors by `Alex Gramfort`_ and `Martin Luessi`_. + +- Wrapper function and script (mne_maxfilter.py) for Elekta Neuromag MaxFilter(TM) by `Martin Luessi`_ + +- Add method to eliminate stimulation artifacts from raw data by linear interpolation or windowing by `Daniel Strohmeier`_. + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number +of commits): + +* 118 Alexandre Gramfort +* 81 Martin Luessi +* 15 Daniel Strohmeier +* 4 Christian Brodbeck +* 4 Louis Thibault +* 2 Brad Buran diff --git a/mne-python/source/doc/changes/v0.5.rst b/mne-python/source/doc/changes/v0.5.rst new file mode 100644 index 0000000000000000000000000000000000000000..9d6a8b3b8562c2298115b9bb169053d1b9213882 --- /dev/null +++ b/mne-python/source/doc/changes/v0.5.rst @@ -0,0 +1,125 @@ +.. _changes_0_5: + +Version 0.5 (2012-12-27) +------------------------ + +Changelog +~~~~~~~~~ + +- Multi-taper PSD estimation for single epochs in source space using minimum norm by `Martin Luessi`_ + +- Read and visualize .dip files obtained with xfit or mne_dipole_fit by `Alex Gramfort`_ + +- Make EEG layout by `Eric Larson`_ + +- Ability to specify SSP projectors when computing covariance from raw by `Eric Larson`_ + +- Read and write txt based event files (.eve or .txt) by `Eric Larson`_ + +- Pass qrs threshold to preprocessing functions by `Eric Larson`_ + +- Compute SSP projections from continuous raw data by `Eric Larson`_ + +- Support for applied SSP projections when loading Raw by `Eric Larson`_ and `Alex Gramfort`_ + +- Support for loading Raw stored in different fif files by `Eric Larson`_ + +- IO of many Evoked in a single fif file + compute Epochs.standard_error by `Eric Larson`_ and `Alex Gramfort`_ + +- ICA computation on Raw and Epochs with automatic component selection by `Denis Engemann`_ and `Alex Gramfort`_ + +- Saving ICA sources to fif files and creating ICA topography layouts by `Denis Engemann`_ + +- Save and restore ICA session to and from fif by `Denis Engemann`_ + +- Export raw, epochs and evoked data as data frame to the pandas library by `Denis Engemann`_ + +- Export raw, epochs and evoked data to the nitime library by `Denis Engemann`_ + +- Copy methods for raw and epochs objects by `Denis Engemann`_, `Martin Luessi`_ and `Alex Gramfort`_ + +- New raw objects method to get the time at certain indices by `Denis Engemann`_ and `Alex Gramfort`_ + +- Plot method for evoked objects by `Denis Engemann`_ + +- Enhancement of cluster-level stats (speed and memory efficiency) by `Eric Larson`_ and `Martin Luessi`_ + +- Reading of source space distances by `Eric Larson`_ + +- Support for filling / smoothing labels and speedup of morphing by `Eric Larson`_ + +- Adding options for morphing by `Eric Larson`_ + +- Plotting functions for time frequency and epochs image topographies by `Denis Engemann`_ and `Alex Gramfort`_ + +- Plotting ERP/ERF images by `Alex Gramfort`_ + +- See detailed subplot when cliking on a channel inside a topography plot by `Martin Luessi`_, `Eric Larson`_ and `Denis Engemann`_ + +- Misc channel type support plotting functions by `Denis Engemann`_ + +- Improved logging support by `Eric Larson`_ + +- Whitening of evoked data for plotting and quality checking by `Alex Gramfort`_ + +- Transparent I/O of gzipped fif files (as .fif.gz) by `Eric Larson`_ + +- Spectral connectivity estimation in sensor and source space by `Martin Luessi`_ + +- Read and write Epochs in FIF files by `Alex Gramfort`_ + +- Resampling of Raw, Epochs, and Evoked by `Eric Larson`_ + +- Creating epochs objects for different conditions and accessing conditions via user-defined name by `Denis Engemann`_ , `Eric Larson`_, `Alex Gramfort`_ and `Christian Brodbeck`_ + +- Visualizing evoked responses from different conditions in one topography plot by `Denis Engemann`_ and `Alex Gramfort`_ + +- Support for L21 MxNE solver using coordinate descent using scikit-learn by `Alex Gramfort`_ and `Daniel Strohmeier`_ + +- Support IIR filters (butterworth, chebyshev, bessel, etc.) by `Eric Larson`_ + +- Read labels from FreeSurfer parcellation by `Martin Luessi`_ + +- Combining labels in source space by `Christian Brodbeck`_ + +- Read and write source spaces, surfaces and coordinate transforms to and from files by `Christian Brodbeck`_ + +- Downsample epochs by `Christian Brodbeck`_ and `Eric Larson`_ + +- New labels class for handling source estimates by `Christian Brodbeck`_, `Martin Luessi`_ and `Alex Gramfort`_ + +- New plotting routines to easily display SourceEstimates using PySurfer by `Alex Gramfort`_ + +- Function to extract label time courses from SourceEstimate(s) by `Martin Luessi`_ + +- Function to visualize connectivity as circular graph by `Martin Luessi`_ and `Alex Gramfort`_ + +- Time-frequency Mixed Norm Estimates (TF-MxNE) by `Alex Gramfort`_ and `Daniel Strohmeier`_ + + +API +~~~ +- Added nave parameter to source_induced_power() and source_band_induced_power(), use nave=1 by default (wrong nave was used before). + +- Use mne.layout.read_layout instead of mne.layout.Layout to read a layout file (.lout) + +- Use raw.time_as_index instead of time_to_index (still works but is deprecated). + +- The artifacts module (mne.artifacts) is now merged into mne.preprocessing + +- Epochs objects now also take dicts as values for the event_id argument. They now can represent multiple conditions. + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number +of commits): + +* 313 Eric Larson +* 226 Alexandre Gramfort +* 219 Denis A. Engemann +* 104 Christian Brodbeck +* 85 Martin Luessi +* 6 Daniel Strohmeier +* 4 Teon Brooks +* 1 Dan G. Wakeman diff --git a/mne-python/source/doc/changes/v0.6.rst b/mne-python/source/doc/changes/v0.6.rst new file mode 100644 index 0000000000000000000000000000000000000000..eeb2ef87c8bbf8ec7fd3c0033696b25545519337 --- /dev/null +++ b/mne-python/source/doc/changes/v0.6.rst @@ -0,0 +1,156 @@ +.. _changes_0_6: + +Version 0.6 (2013-06-15) +------------------------ + +Changelog +~~~~~~~~~ + +- Linear (and zeroth-order) detrending for Epochs and Evoked by `Eric Larson`_ + +- Label morphing between subjects by `Eric Larson`_ + +- Define events based on time lag between reference and target event by `Denis Engemann`_ + +- ICA convenience function implementing an automated artifact removal workflow by `Denis Engemann`_ + +- Bad channels no longer included in epochs by default by `Eric Larson`_ + +- Support for diagonal noise covariances in inverse methods and rank computation by `Eric Larson`_ + +- Support for using CUDA in FFT-based FIR filtering (method='fft') and resampling by `Eric Larson`_ + +- Optimized FFT length selection for faster overlap-add filtering by `Martin Luessi`_ + +- Ability to exclude bad channels from evoked plots or shown them in red by `Martin Luessi`_ + +- Option to show both hemispheres when plotting SourceEstimate with PySurfer by `Martin Luessi`_ + +- Optimized Raw reading and epoching routines to limit memory copies by `Eric Larson`_ + +- Advanced options to save raw files in short or double precision by `Eric Larson`_ + +- Option to detect decreasing events using find_events by `Simon Kornblith`_ + +- Option to change default stim_channel used for finding events by `Eric Larson`_ + +- Use average patch normal from surface-oriented forward solution in inverse calculation when possible by `Eric Larson`_ + +- Function to plot drop_log from Epochs instance by `Eric Larson`_ + +- Estimate rank of Raw data by `Eric Larson`_ + +- Support reading of BTi/4D data by `Denis Engemann`_ + +- Wrapper for generating forward solutions by `Eric Larson`_ + +- Averaging forward solutions by `Eric Larson`_ + +- Events now contain the pre-event stim channel value in the middle column, by `Christian Brodbeck`_ + +- New function ``mne.find_stim_steps`` for finding all steps in a stim channel by `Christian Brodbeck`_ + +- Get information about FIFF files using mne.fiff.show_fiff() by `Eric Larson`_ + +- Compute forward fields sensitivity maps by `Alex Gramfort`_ and `Eric Larson`_ + +- Support reading of KIT data by `Teon Brooks`_ and `Christian Brodbeck`_ + +- Raw data visualization by `Eric Larson`_ + +- Smarter SourceEstimate object that contains linear inverse kernel and sensor space data for fast time-frequency transforms in source space by `Martin Luessi`_ + +- Add example of decoding/MVPA on MEG sensor data by `Alex Gramfort`_ + +- Add support for non-paired tests in spatiotemporal cluster stats by `Alex Gramfort`_ + +- Add unified SSP-projector API for Raw, Epochs and Evoked objects by `Denis Engemann`_, `Alex Gramfort`_ `Eric Larson`_ and `Martin Luessi`_ + +- Add support for delayed SSP application at evoked stage `Denis Engemann`_, `Alex Gramfort`_, `Eric Larson`_ and `Martin Luessi`_ + +- Support selective parameter updating in functions taking dicts as arguments by `Denis Engemann`_ + +- New ICA method ``sources_as_epochs`` to create Epochs in ICA space by `Denis Engemann`_ + +- New method in Evoked and Epoch classes to shift time scale by `Mainak Jas`_ + +- Added option to specify EOG channel(s) when computing PCA/SSP projections for EOG artifacts by `Mainak Jas`_ + +- Improved connectivity interface to allow combinations of signals, e.g., seed time series and source estimates, by `Martin Luessi`_ + +- Effective connectivity estimation using Phase Slope Index (PSI) by `Martin Luessi`_ + +- Support for threshold-free cluster enhancement (TFCE) by `Eric Larson`_ + +- Support for "hat" variance regularization by `Eric Larson`_ + +- Access source estimates as Pandas DataFrame by `Denis Engemann`_. + +- Add example of decoding/MVPA on MEG source space data by `Denis Engemann`_ + +- Add support for --tstart option in mne_compute_proj_eog.py by `Alex Gramfort`_ + +- Add two-way repeated measures ANOVA for mass-univariate statistics by `Denis Engemann`_, `Eric Larson`_ and `Alex Gramfort`_ + +- Add function for summarizing clusters from spatio-temporal-cluster permutation tests by `Denis Engemann`_ and `Eric Larson`_ + +- Add generator support for ``lcmv_epochs`` by `Denis Engemann`_ + +- Gamma-MAP sparse source localization method by `Martin Luessi`_ and `Alex Gramfort`_ + +- Add regular expression and substring support for selecting parcellation labels by `Denis Engemann`_ + +- New plot_evoked option for interactive and reversible selection of SSP projection vectors by `Denis Engemann`_ + +- Plot 2D flat topographies with interpolation for evoked and SSPs by `Christian Brodbeck`_ and `Alex Gramfort`_ + +- Support delayed SSP applicationon for 2D flat topographies by `Denis Engemann`_ and `Christian Brodbeck`_ and `Alex Gramfort`_ + +- Allow picking maximum power source, a.k.a. "optimal", orientation in LCMV beamformers by `Roman Goj`_, `Alex Gramfort`_, `Denis Engemann`_ and `Martin Luessi`_ + +- Add sensor type scaling parameter to plot_topo by `Andrew Dykstra`_, `Denis Engemann`_ and `Eric Larson`_ + +- Support delayed SSP application in plot_topo by `Denis Engemann`_ + +API +~~~ + +- Deprecated use of fiff.pick_types without specifying exclude -- use either [] (none), ``bads`` (bad channels), or a list of string (channel names). + +- Depth bias correction in dSPM/MNE/sLORETA make_inverse_operator is now done like in the C code using only gradiometers if present, else magnetometers, and EEG if no MEG channels are present. + +- Fixed-orientation inverse solutions need to be made using ``fixed=True`` option (using non-surface-oriented forward solutions if no depth weighting is used) to maintain compatibility with MNE C code. + +- Raw.save() will only overwrite the destination file, if it exists, if option overwrite=True is set. + +- mne.utils.set_config(), get_config(), get_config_path() moved to mne namespace. + +- Raw constructor argument proj_active deprecated -- use proj argument instead. + +- Functions from the mne.mixed_norm module have been moved to the mne.inverse_sparse module. + +- Deprecate CTF compensation (keep_comp and dest_comp) in Epochs and move it to Raw with a single compensation parameter. + +- Remove artifacts module. Artifacts- and preprocessing related functions can now be found in mne.preprocessing. + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number +of commits): + +* 340 Eric Larson +* 330 Denis A. Engemann +* 204 Alexandre Gramfort +* 72 Christian Brodbeck +* 66 Roman Goj +* 65 Martin Luessi +* 37 Teon Brooks +* 18 Mainak Jas +* 9 Simon Kornblith +* 7 Daniel Strohmeier +* 6 Romain Trachel +* 5 Yousra BEKHTI +* 5 Brad Buran +* 1 Andrew Dykstra +* 1 Christoph Dinh diff --git a/mne-python/source/doc/changes/v0.7.rst b/mne-python/source/doc/changes/v0.7.rst new file mode 100644 index 0000000000000000000000000000000000000000..7fde706f2cd1d0e2b9f358fa0e33283fb14046b1 --- /dev/null +++ b/mne-python/source/doc/changes/v0.7.rst @@ -0,0 +1,136 @@ +.. _changes_0_7: + +Version 0.7 (2013-11-26) +------------------------ + +Changelog +~~~~~~~~~ + +- Add capability for real-time feedback via trigger codes using StimServer and StimClient classes by `Mainak Jas`_ + +- New decoding module for MEG analysis containing sklearn compatible transformers by `Mainak Jas`_ and `Alex Gramfort`_ + +- New realtime module containing RtEpochs, RtClient and MockRtClient class by `Martin Luessi`_, `Christopher Dinh`_, `Alex Gramfort`_, `Denis Engemann`_ and `Mainak Jas`_ + +- Allow picking normal orientation in LCMV beamformers by `Roman Goj`_, `Alex Gramfort`_, `Denis Engemann`_ and `Martin Luessi`_ + +- Add printing summary to terminal for measurement info by `Denis Engemann`_ + +- Add read and write info attribute ICA objects by `Denis Engemann`_ + +- Decoding with Common Spatial Patterns (CSP) by `Romain Trachel`_ and `Alex Gramfort`_ + +- Add ICA ``plot_topomap`` function and method for displaying the spatial sensitivity of ICA sources by `Denis Engemann`_ + +- Plotting multiple brain views at once by `Eric Larson`_ + +- Reading head positions from raw FIFF files by `Eric Larson`_ + +- Add decimation parameter to ICA.decompose* methods by `Denis Engemann`_ and `Alex Gramfort`_ + +- Add rejection buffer to ICA.decompose* methods by `Denis Engemann`_ and `Alex Gramfort`_ + +- Improve ICA computation speed and memory usage by `Denis Engemann`_ and `Alex Gramfort`_ + +- Add polygonal surface decimation function to preprocess head surfaces for coregistration by `Denis Engemann`_ and `Alex Gramfort`_ + +- DICS time-frequency beamforming for epochs, evoked and for estimating source power by `Roman Goj`_, `Alex Gramfort`_ and `Denis Engemann`_ + +- Add method for computing cross-spectral density (CSD) from epochs and class for storing CSD data by `Roman Goj`_, `Alex Gramfort`_ and `Denis Engemann`_ + +- Add trellis plot function and method for visualizing single epochs by `Denis Engemann`_ + +- Add fiducials read/write support by `Christian Brodbeck`_ and `Alex Gramfort`_ + +- Add select / drop bad channels in ``plot_raw`` on click by `Denis Engemann`_ + +- Add ``ico`` and ``oct`` source space creation in native Python by `Eric Larson`_ + +- Add interactive rejection of bad trials in ``plot_epochs`` by `Denis Engemann`_ + +- Add morph map calculation by `Eric Larson`_ and `Martin Luessi`_ + +- Add volume and discrete source space creation and I/O support by `Eric Larson`_ + +- Time-frequency beamforming to obtain spectrograms in source space using LCMV and DICS by `Roman Goj`_, `Alex Gramfort`_ and `Denis Engemann`_ + +- Compute epochs power spectral density function by `Denis Engemann`_ + +- Plot raw power spectral density by `Eric Larson`_ + +- Computing of distances along the cortical surface by `Eric Larson`_ + +- Add reading BEM solutions by `Eric Larson`_ + +- Add forward solution calculation in native Python by `Eric Larson`_ + +- Add (Neuro)debian license compatibility by `Eric Larson`_ + +- Automatic QRS threshold selection for ECG events by `Eric Larson`_ + +- Add Travis continuous integration service by `Denis Engemann`_ + +- Add SPM face data set by `Denis Engemann`_ `Martin Luessi`_ and `Alex Gramfort`_ + +- Support reading of EDF+,BDF data by `Teon Brooks`_ + +- Tools for scaling MRIs (mne.scale_mri) by `Christian Brodbeck`_ + +- GUI for head-MRI coregistration (mne.gui.coregistration) by `Christian Brodbeck`_ + +- GUI for ki2fiff conversion (mne.gui.kit2fiff) by `Christian Brodbeck`_ + +- Support reading of EEG BrainVision data by `Teon Brooks`_ + +- Improve CTF compensation handling by `Martin Luessi`_ and `Eric Larson`_ + +- Improve and extend automated layout guessing by `Denis Engemann`_ + +- Add Continuum Analytics Anaconda support by `Denis Engemann`_ + +- Add ``subtract evoked`` option to beamformers by `Andrew Dykstra`_ + +- Add new ``transform`` method to SourceEstimate(s) by `Andrew Dykstra`_ + +API +~~~ + +- The pick_normal parameter for minimum norm solvers has been renamed as ``pick_ori`` and normal orientation picking is now achieved by passing the value "normal" for the ``pick_ori`` parameter. + +- ICA objects now expose the measurement info of the object fitted. + +- Average EEG reference is now added by default to Raw instances. + +- Removed deprecated read/write_stc/w, use SourceEstimate methods instead + +- The ``chs`` argument in ``mne.layouts.find_layout`` is deprecated and will be removed in MNE-Python 0.9. Use ``info`` instead. + +- ``plot_evoked`` and ``Epochs.plot`` now open a new figure by default. To plot on an existing figure please specify the ``axes`` parameter. + + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number +of commits): + +* 336 Denis A. Engemann +* 202 Eric Larson +* 193 Roman Goj +* 138 Alexandre Gramfort +* 99 Mainak Jas +* 75 Christian Brodbeck +* 60 Martin Luessi +* 40 Teon Brooks +* 29 Romain Trachel +* 28 Andrew Dykstra +* 12 Mark Wronkiewicz +* 10 Christoph Dinh +* 8 Alan Leggitt +* 3 Yaroslav Halchenko +* 3 Daniel Strohmeier +* 2 Mads Jensen +* 2 Praveen Sripad +* 1 Luke Bloy +* 1 Emanuele Olivetti +* 1 Yousra BEKHTI diff --git a/mne-python/source/doc/changes/v0.8.rst b/mne-python/source/doc/changes/v0.8.rst new file mode 100644 index 0000000000000000000000000000000000000000..324bb0161239d4b86911bfadb189b10188572cf4 --- /dev/null +++ b/mne-python/source/doc/changes/v0.8.rst @@ -0,0 +1,194 @@ +.. _changes_0_8: + +Version 0.8 (2014-06-25) +------------------------ + +Changelog +~~~~~~~~~ + +- Add Python3 support by `Nick Ward`_, `Alex Gramfort`_, `Denis Engemann`_, and `Eric Larson`_ + +- Add ``get_peak`` method for evoked and stc objects by `Denis Engemann`_ + +- Add ``iter_topography`` function for radically simplified custom sensor topography plotting by `Denis Engemann`_ + +- Add field line interpolation by `Eric Larson`_ + +- Add full provenance tacking for epochs and improve ``drop_log`` by `Tal Linzen`_, `Alex Gramfort`_ and `Denis Engemann`_ + +- Add systematic contains method to ``Raw``, ``Epochs`` and ``Evoked`` for channel type membership testing by `Denis Engemann`_ + +- Add fiff unicode writing and reading support by `Denis Engemann`_ + +- Add 3D MEG/EEG field plotting function and evoked method by `Denis Engemann`_ and `Alex Gramfort`_ + +- Add consistent channel-dropping methods to ``Raw``, ``Epochs`` and ``Evoked`` by `Denis Engemann`_ and `Alex Gramfort`_ + +- Add ``equalize_channnels`` function to set common channels for a list of ``Raw``, ``Epochs``, or ``Evoked`` objects by `Denis Engemann`_ + +- Add ``plot_events`` function to visually display paradigm by `Alex Gramfort`_ + +- Improved connectivity circle plot by `Martin Luessi`_ + +- Add ability to anonymize measurement info by `Eric Larson`_ + +- Add callback to connectivity circle plot to isolate connections to clicked nodes `Roan LaPlante`_ + +- Add ability to add patch information to source spaces by `Eric Larson`_ + +- Add ``split_label`` function to divide labels into multiple parts by `Christian Brodbeck`_ + +- Add ``color`` attribute to ``Label`` objects by `Christian Brodbeck`_ + +- Add ``max`` mode for ``extract_label_time_course`` by `Mads Jensen`_ + +- Add ``rename_channels`` function to change channel names and types in info object by `Dan Wakeman`_ and `Denis Engemann`_ + +- Add ``compute_ems`` function to extract the time course of experimental effects by `Denis Engemann`_, `Sébastien Marti`_ and `Alex Gramfort`_ + +- Add option to expand Labels defined in a source space to the original surface (``Label.fill()``) by `Christian Brodbeck`_ + +- GUIs can be invoked form the command line using ``$ mne coreg`` and ``$ mne kit2fiff`` by `Christian Brodbeck`_ + +- Add ``add_channels_epochs`` function to combine different recordings at the Epochs level by `Christian Brodbeck`_ and `Denis Engemann`_ + +- Add support for EGI Netstation simple binary files by `Denis Engemann`_ + +- Add support for treating arbitrary data (numpy ndarray) as a Raw instance by `Eric Larson`_ + +- Support for parsing the EDF+ annotation channel by `Martin Billinger`_ + +- Add EpochsArray constructor for creating epochs from numpy arrays by `Denis Engemann`_ and `Federico Raimondo`_ + +- Add connector to FieldTrip realtime client by `Mainak Jas`_ + +- Add color and event_id with legend options in plot_events in viz.py by `Cathy Nangini`_ + +- Add ``events_list`` parameter to ``mne.concatenate_raws`` to concatenate events corresponding to runs by `Denis Engemann`_ + +- Add ``read_ch_connectivity`` function to read FieldTrip neighbor template .mat files and obtain sensor adjacency matrices by `Denis Engemann`_ + +- Add display of head in helmet from -trans.fif file to check coregistration quality by `Mainak Jas`_ + +- Add ``raw.add_events`` to allow adding events to a raw file by `Eric Larson`_ + +- Add ``plot_image`` method to Evoked object to display data as images by `Jean-Rémi King`_ and `Alex Gramfort`_ and `Denis Engemann`_ + +- Add BCI demo with CSP on motor imagery by `Martin Billinger`_ + +- New ICA API with unified methods for processing ``Raw``, ``Epochs`` and ``Evoked`` objects by `Denis Engemann`_ + +- Apply ICA at the evoked stage by `Denis Engemann`_ + +- New ICA methods for visualizing unmixing quality, artifact detection and rejection by `Denis Engemann`_ + +- Add ``pick_channels`` and ``drop_channels`` mixin class to pick and drop channels from ``Raw``, ``Epochs``, and ``Evoked`` objects by `Andrew Dykstra`_ and `Denis Engemann`_ + +- Add ``EvokedArray`` class to create an Evoked object from an array by `Andrew Dykstra`_ + +- Add ``plot_bem`` method to visualize BEM contours on MRI anatomical images by `Mainak Jas`_ and `Alex Gramfort`_ + +- Add automated ECG detection using cross-trial phase statistics by `Denis Engemann`_ and `Juergen Dammers`_ + +- Add Forward class to succinctly display gain matrix info by `Andrew Dykstra`_ + +- Add reading and writing of split raw files by `Martin Luessi`_ + +- Add OLS regression function by `Tal Linzen`_, `Teon Brooks`_ and `Denis Engemann`_ + +- Add computation of point spread and cross-talk functions for MNE type solutions by `Alex Gramfort`_ and `Olaf Hauk`_ + +- Add mask parameter to ``plot_evoked_topomap`` and ``evoked.plot_topomap`` by `Denis Engemann`_ and `Alex Gramfort`_ + +- Add infomax and extended infomax ICA by `Denis Engemann`_, `Juergen Dammers`_ and `Lukas Breuer`_ and `Federico Raimondo`_ + +- Aesthetically redesign interpolated topography plots by `Denis Engemann`_ and `Alex Gramfort`_ + +- Simplify sensor space time-frequency analysis API with ``tfr_morlet`` function by `Alex Gramfort`_ and `Denis Engemann`_ + +- Add new somatosensory MEG dataset with nice time-frequency content by `Alex Gramfort`_ + +- Add HDF5 write/read support for SourceEstimates by `Eric Larson`_ + +- Add InverseOperator class to display inverse operator info by `Mainak Jas`_ + +- Add ``$ mne report`` command to generate html reports of MEG/EEG data analysis pipelines by `Mainak Jas`_, `Alex Gramfort`_ and `Denis Engemann`_ + +- Improve ICA verbosity with regard to rank reduction by `Denis Engemann`_ + +BUG +~~~ + +- Fix incorrect ``times`` attribute when stc was computed using ``apply_inverse`` after decimation at epochs stage for certain, arbitrary sample frequencies by `Denis Engemann`_ + +- Fix corner case error for step-down-in-jumps permutation test (when step-down threshold was high enough to include all clusters) by `Eric Larson`_ + +- Fix selection of total number of components via float when picking ICA sources by `Denis Engemann`_ and `Qunxi Dong`_ + +- Fix writing and reading transforms after modification in measurement info by `Denis Engemann`_ and `Martin Luessi`_ and `Eric Larson`_ + +- Fix pre-whitening / rescaling when estimating ICA on multiple channels without covariance by `Denis Engemann`_ + +- Fix ICA pre-whitening, avoid recomputation when applying ICA to new data by `Denis Engemann`_ + +API +~~~ + +- The minimum numpy version has been increased to 1.6 from 1.4. + +- Epochs object now has a selection attribute to track provenance of selected Epochs. The length of the drop_log attribute is now the same as the length of the original events passed to Epochs. In earlier versions it had the length of the events filtered by event_id. Epochs has also now a plot_drop_log method. + +- Deprecate Epochs.drop_picks in favor of a new method called drop_channels + +- Deprecate ``labels_from_parc`` and ``parc_from_labels`` in favor of ``read_labels_from_annot`` and ``write_labels_to_annot`` + +- The default of the new add_dist option of ``setup_source_space`` to add patch information will change from False to True in MNE-Python 0.9 + +- Deprecate ``read_evoked`` and ``write_evoked`` in favor of ``read_evokeds`` and ``write_evokeds``. read_evokeds will return all `Evoked` instances in a file by default. + +- Deprecate ``setno`` in favor of ``condition`` in the initialization of an Evoked instance. This affects ``mne.fiff.Evoked`` and ``read_evokeds``, but not ``read_evoked``. + +- Deprecate ``mne.fiff`` module, use ``mne.io`` instead e.g. ``mne.io.Raw`` instead of ``mne.fiff.Raw``. + +- Pick functions (e.g., ``pick_types``) are now in the mne namespace (e.g. use ``mne.pick_types``). + +- Deprecated ICA methods specific to one container type. Use ICA.fit, ICA.get_sources ICA.apply and ``ICA.plot_*`` for processing Raw, Epochs and Evoked objects. + +- The default smoothing method for ``mne.stc_to_label`` will change in v0.9, and the old method is deprecated. + +- As default, for ICA the maximum number of PCA components equals the number of channels passed. The number of PCA components used to reconstruct the sensor space signals now defaults to the maximum number of PCA components estimated. + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number of commits): + +* 418 Denis A. Engemann +* 284 Alexandre Gramfort +* 242 Eric Larson +* 155 Christian Brodbeck +* 144 Mainak Jas +* 49 Martin Billinger +* 49 Andrew Dykstra +* 44 Tal Linzen +* 37 Dan G. Wakeman +* 36 Martin Luessi +* 26 Teon Brooks +* 20 Cathy Nangini +* 15 Hari Bharadwaj +* 15 Roman Goj +* 10 Ross Maddox +* 9 Marmaduke Woodman +* 8 Praveen Sripad +* 8 Tanay +* 8 Roan LaPlante +* 5 Saket Choudhary +* 4 Nick Ward +* 4 Mads Jensen +* 3 Olaf Hauk +* 3 Brad Buran +* 2 Daniel Strohmeier +* 2 Federico Raimondo +* 2 Alan Leggitt +* 1 Jean-Rémi King +* 1 Matti Hämäläinen diff --git a/mne-python/source/doc/changes/v0.9.rst b/mne-python/source/doc/changes/v0.9.rst new file mode 100644 index 0000000000000000000000000000000000000000..5ab19f3a07ff68a68acfc968bf47da6813ab2e65 --- /dev/null +++ b/mne-python/source/doc/changes/v0.9.rst @@ -0,0 +1,239 @@ +.. _changes_0_9: + +Version 0.9 (2015-05-22) +------------------------ + +Changelog +~~~~~~~~~ + +- Add support for mayavi figures in ``add_section`` method in Report by `Mainak Jas`_ + +- Add extract volumes of interest from freesurfer segmentation and setup as volume source space by `Alan Leggitt`_ + +- Add support to combine source spaces of different types by `Alan Leggitt`_ + +- Add support for source estimate for mixed source spaces by `Alan Leggitt`_ + +- Add ``SourceSpaces.save_as_volume`` method by `Alan Leggitt`_ + +- Automatically compute proper box sizes when generating layouts on the fly by `Marijn van Vliet`_ + +- Average evoked topographies across time points by `Denis Engemann`_ + +- Add option to Report class to save images as vector graphics (SVG) by `Denis Engemann`_ + +- Add events count to ``mne.viz.plot_events`` by `Denis Engemann`_ + +- Add support for stereotactic EEG (sEEG) channel type by `Marmaduke Woodman`_ + +- Add support for montage files by `Denis Engemann`_, `Marijn van Vliet`_, `Jona Sassenhagen`_, `Alex Gramfort`_ and `Teon Brooks`_ + +- Add support for spatiotemporal permutation clustering on sensors by `Denis Engemann`_ + +- Add support for multitaper time-frequency analysis by `Hari Bharadwaj`_ + +- Add Stockwell (S) transform for time-frequency representations by `Denis Engemann`_ and `Alex Gramfort`_ + +- Add reading and writing support for time frequency data (AverageTFR objects) by `Denis Engemann`_ + +- Add reading and writing support for digitizer data, and function for adding dig points to info by `Teon Brooks`_ + +- Add ``plot_projs_topomap`` method to ``Raw``, ``Epochs`` and ``Evoked`` objects by `Teon Brooks`_ + +- Add EEG (based on spherical splines) and MEG (based on field interpolation) bad channel interpolation method to ``Raw``, ``Epochs`` and ``Evoked`` objects by `Denis Engemann`_ and `Mainak Jas`_ + +- Add parameter to ``whiten_evoked``, ``compute_whitener`` and ``prepare_noise_cov`` to set the exact rank by `Martin Luessi`_ and `Denis Engemann`_ + +- Add fiff I/O for processing history and MaxFilter info by `Denis Engemann`_ and `Eric Larson`_ + +- Add automated regularization with support for multiple sensor types to ``compute_covariance`` by `Denis Engemann`_ and `Alex Gramfort`_ + +- Add ``Evoked.plot_white`` method to diagnose the quality of the estimated noise covariance and its impact on spatial whitening by `Denis Engemann`_ and `Alex Gramfort`_ + +- Add ``mne.evoked.grand_average`` function to compute grand average of Evoked data while interpolating bad EEG channels if necessary by `Mads Jensen`_ and `Alex Gramfort`_ + +- Improve EEG referencing support and add support for bipolar referencing by `Marijn van Vliet`_ and `Alex Gramfort`_ + +- Enable TFR calculation on Evoked objects by `Eric Larson`_ + +- Add support for combining Evoked datasets with arbitrary weights (e.g., for oddball paradigms) by `Eric Larson`_ and `Alex Gramfort`_ + +- Add support for concatenating a list of Epochs objects by `Denis Engemann`_ + +- Labels support subtraction (``label_1 - label_2``) by `Christian Brodbeck`_ + +- Add GeneralizationAcrossTime object with support for cross-condition generalization by `Jean-Rémi King`_ and `Denis Engemann`_ + +- Add support for single dipole fitting by `Eric Larson`_ + +- Add support for spherical models in forward calculations by `Eric Larson`_ + +- Add support for SNR estimation by `Eric Larson`_ + +- Add support for Savitsky-Golay filtering of Evoked and Epochs by `Eric Larson`_ + +- Add support for adding an empty reference channel to data by `Teon Brooks`_ + +- Add reader function ``mne.io.read_raw_fif`` for Raw FIF files by `Teon Brooks`_ + +- Add example of creating MNE objects from arbitrary data and NEO files by `Jaakko Leppakangas`_ + +- Add ``plot_psd`` and ``plot_psd_topomap`` methods to epochs by `Yousra Bekhti`_, `Eric Larson`_ and `Denis Engemann`_ + +- ``evoked.pick_types``, ``epochs.pick_types``, and ``tfr.pick_types`` added by `Eric Larson`_ + +- ``rename_channels`` and ``set_channel_types`` added as methods to ``Raw``, ``Epochs`` and ``Evoked`` objects by `Teon Brooks`_ + +- Add RAP-MUSIC inverse method by `Yousra Bekhti`_ and `Alex Gramfort`_ + +- Add ``evoked.as_type`` to allow remapping data in MEG channels to virtual magnetometer or gradiometer channels by `Mainak Jas`_ + +- Add ``mne.Report.add_bem_to_section``, ``mne.Report.add_htmls_to_section`` methods to :class:`mne.Report` by `Teon Brooks`_ + +- Add support for KIT epochs files with ``read_epochs_kit`` by `Teon Brooks`_ + +- Add whitening plots for evokeds to ``mne.Report`` by `Mainak Jas`_ + +- Add ``DigMontage`` class and reader to interface with digitization info by `Teon Brooks`_ and `Christian Brodbeck`_ + +- Add ``set_montage`` method to the ``Raw``, ``Epochs``, and ``Evoked`` objects by `Teon Brooks`_ and `Denis Engemann`_ + +- Add support for capturing sensor positions when clicking on an image by `Chris Holdgraf`_ + +- Add support for custom sensor positions when creating Layout objects by `Chris Holdgraf`_ + +BUG +~~~ + +- Fix energy conservation for STFT with tight frames by `Daniel Strohmeier`_ + +- Fix incorrect data matrix when tfr was plotted with parameters ``tmin``, ``tmax``, ``fmin`` and ``fmax`` by `Mainak Jas`_ + +- Fix channel names in topomaps by `Alex Gramfort`_ + +- Fix mapping of ``l_trans_bandwidth`` (to low frequency) and ``h_trans_bandwidth`` (to high frequency) in ``_BaseRaw.filter`` by `Denis Engemann`_ + +- Fix scaling source spaces when distances have to be recomputed by `Christian Brodbeck`_ + +- Fix repeated samples in client to FieldTrip buffer by `Mainak Jas`_ and `Federico Raimondo`_ + +- Fix highpass and lowpass units read from Brainvision vhdr files by `Alex Gramfort`_ + +- Add missing attributes for BrainVision and KIT systems needed for resample by `Teon Brooks`_ + +- Fix file extensions of SSP projection files written by mne commands (from _proj.fif to -prof.fif) by `Alex Gramfort`_ + +- Generating EEG layouts no longer requires digitization points by `Marijn van Vliet`_ + +- Add missing attributes to BTI, KIT, and BrainVision by `Eric Larson`_ + +- The API change to the edf, brainvision, and egi break backwards compatibility for when importing eeg data by `Teon Brooks`_ + +- Fix bug in ``mne.viz.plot_topo`` if ylim was passed for single sensor layouts by `Denis Engemann`_ + +- Average reference projections will no longer by automatically added after applying a custom EEG reference by `Marijn van Vliet`_ + +- Fix picks argument to filter in n dimensions (affects FilterEstimator), and highpass filter in FilterEstimator by `Mainak Jas`_ + +- Fix beamformer code LCMV/DICS for CTF data with reference channels by `Denis Engemann`_ and `Alex Gramfort`_ + +- Fix scalings for bad EEG channels in ``mne.viz.plot_topo`` by `Marijn van Vliet`_ + +- Fix EGI reading when no events are present by `Federico Raimondo`_ + +- Add functionality to determine plot limits automatically or by data percentiles by `Mark Wronkiewicz`_ + +- Fix bug in mne.io.edf where the channel offsets were omitted in the voltage calculations by `Teon Brooks`_ + +- Decouple section ordering in command-line from python interface for mne-report by `Mainak Jas`_ + +- Fix bug with ICA resetting by `Denis Engemann`_ + +API +~~~ + +- apply_inverse functions have a new boolean parameter ``prepared`` which saves computation time by calling ``prepare_inverse_operator`` only if it is False + +- find_events and read_events functions have a new parameter ``mask`` to set some bits to a don't care state by `Teon Brooks`_ + +- New channels module including layouts, electrode montages, and neighbor definitions of sensors which deprecates ``mne.layouts`` by `Denis Engemann`_ + +- ``read_raw_brainvision``, ``read_raw_edf``, ``read_raw_egi`` all use a standard montage import by `Teon Brooks`_ + +- Fix missing calibration factors for ``mne.io.egi.read_raw_egi`` by `Denis Engemann`_ and `Federico Raimondo`_ + +- Allow multiple filename patterns as a list (e.g., \*raw.fif and \*-eve.fif) to be parsed by mne report in ``Report.parse_folder()`` by `Mainak Jas`_ + +- ``read_hsp``, ``read_elp``, and ``write_hsp``, ``write_mrk`` were removed and made private by `Teon Brooks`_ + +- When computing the noise covariance or MNE inverse solutions, the rank is estimated empirically using more sensitive thresholds, which stabilizes results by `Denis Engemann`_ and `Eric Larson`_ and `Alex Gramfort`_ + +- Raw FIFF files can be preloaded after class instantiation using ``raw.preload_data()`` + +- Add ``label`` parameter to ``apply_inverse`` by `Teon Brooks`_ + +- Deprecated ``label_time_courses`` for ``in_label`` method in `SourceEstimate` by `Teon Brooks`_ + +- Deprecated ``as_data_frame`` for ``to_data_frame`` by `Chris Holdgraf`_ + +- Add ``transform``, ``unit`` parameters to ``read_montage`` by `Teon Brooks`_ + +- Deprecated ``fmin, fmid, fmax`` in stc.plot and added ``clim`` by `Mark Wronkiewicz`_ + +- Use ``scipy.signal.welch`` instead of matplotlib.psd inside ``compute_raw_psd`` and ``compute_epochs_psd`` by `Yousra Bekhti`_ `Eric Larson`_ and `Denis Engemann`_. As a consequence, ``Raw.plot_raw_psds`` has been deprecated. + +- ``Raw`` instances returned by ``mne.forward.apply_forward_raw`` now always have times starting from + zero to be consistent with all other ``Raw`` instances. To get the former ``start`` and ``stop`` times, + use ``raw.first_samp / raw.info['sfreq']`` and ``raw.last_samp / raw.info['sfreq']``. + +- ``pick_types_evoked`` has been deprecated in favor of ``evoked.pick_types``. + +- Deprecated changing the sensor type of channels in ``rename_channels`` by `Teon Brooks`_ + +- CUDA is no longer initialized at module import, but only when first used. + +- ``add_figs_to_section`` and ``add_images_to_section`` now have a ``textbox`` parameter to add comments to the image by `Teon Brooks`_ + +- Deprecated ``iir_filter_raw`` for ``fit_iir_model_raw``. + +- Add ``montage`` parameter to the ``create_info`` function to create the info using montages by `Teon Brooks`_ + +Authors +~~~~~~~ + +The committer list for this release is the following (preceded by number of commits): + +* 515 Eric Larson +* 343 Denis A. Engemann +* 304 Alexandre Gramfort +* 300 Teon Brooks +* 142 Mainak Jas +* 119 Jean-Rémi King +* 77 Alan Leggitt +* 75 Marijn van Vliet +* 63 Chris Holdgraf +* 57 Yousra Bekhti +* 49 Mark Wronkiewicz +* 44 Christian Brodbeck +* 30 Jona Sassenhagen +* 29 Hari Bharadwaj +* 27 Clément Moutard +* 24 Ingoo Lee +* 18 Marmaduke Woodman +* 16 Martin Luessi +* 10 Jaakko Leppakangas +* 9 Andrew Dykstra +* 9 Daniel Strohmeier +* 7 kjs +* 6 Dan G. Wakeman +* 5 Federico Raimondo +* 3 Basile Pinsard +* 3 Christoph Dinh +* 3 Hafeza Anevar +* 2 Martin Billinger +* 2 Roan LaPlante +* 1 Manoj Kumar +* 1 Matt Tucker +* 1 Romain Trachel +* 1 mads jensen +* 1 sviter diff --git a/mne-python/source/doc/changes/v1.0.rst b/mne-python/source/doc/changes/v1.0.rst new file mode 100644 index 0000000000000000000000000000000000000000..dd5e7b501ed79a9767f32f64bc79a72a93b827f1 --- /dev/null +++ b/mne-python/source/doc/changes/v1.0.rst @@ -0,0 +1,307 @@ +.. _changes_1_0_0: + +Version 1.0.0 (2022-03-21) +-------------------------- + +Enhancements +~~~~~~~~~~~~ + +- Add ``use_orig_time`` option to :meth:`mne.Annotations.crop`. (:gh:`10396` by :newcontrib:`Michiru Kaneda`) + +- Speed up :func:`mne.preprocessing.annotate_muscle_zscore`, :func:`mne.preprocessing.annotate_movement`, and :func:`mne.preprocessing.annotate_nan` through better annotation creation (:gh:`10089` by :newcontrib:`Senwen Deng`) + +- Fix some unused variables in time_frequency_erds.py example (:gh:`10076` by :newcontrib:`Jan Zerfowski`) + +- Document ``BAD_ACQ_SKIP`` annotation behavior (:gh:`10054` by :newcontrib:`Etienne de Montalivet`) + +- Add link to related ``MNE-ARI`` package (:gh:`10174` by :newcontrib:`John Veillette`) + +- :func:`mne.time_frequency.psd_array_multitaper` can now return complex results per-taper when specifying ``output='complex'`` (:gh:`10307` by `Mikołaj Magnuski`_) + +- :func:`mne.time_frequency.tfr_array_multitaper` can now return results for ``output='phase'`` instead of an error (:gh:`10281` by `Mikołaj Magnuski`_) + +- Add show local maxima toggling button to ``mne.gui.locate_ieeg`` (:gh:`9952` by `Alex Rockhill`_) + +- Show boundaries in ``mne.gui.locate_ieeg`` (:gh:`10379` by `Eric Larson`_) + +- Add argument ``cval`` to :func:`mne.transforms.apply_volume_registration` to set interpolation values outside the image domain (:gh:`10379` by `Eric Larson`_) + +- Improve docstring of :class:`mne.Info` and add attributes that were not covered (:gh:`9922` by `Mathieu Scheltienne`_) + +- Add an alternate, manual procedure for aligning a CT to an MR procedure to :ref:`tut-ieeg-localize` (:gh:`9978` by `Alex Rockhill`_) + +- Improve docstring of export functions :func:`mne.export.export_raw`, :func:`mne.export.export_epochs`, :func:`mne.export.export_evokeds`, :func:`mne.export.export_evokeds_mff` and issue a warning when there are unapplied projectors (:gh:`9994` by `Mathieu Scheltienne`_) + +- Add support for reading haemoglobin fNIRS data to :func:`mne.io.read_raw_snirf` (:gh:`9929` by `Robert Luke`_) + +- Add ``fill_hole_size`` keyword argument to :func:`mne.viz.Brain.add_volume_labels` to close holes in the mesh (:gh:`10024` by `Alex Rockhill`_) + +- Changed :class:`mne.Epochs` and :class:`mne.Evoked` to have a more concise ``__repr__`` to improve interactive MNE usage in Python Interactive Console, IDEs, and debuggers when many events are handled. (:gh:`10042` by `Jan Sosulski`_) + +- Improve docstring of ``events`` arguments and cross-referencing to :term:`events` (:gh:`10056` by `Mathieu Scheltienne`_) + +- Speed up repeated surface-smoothing operation (e.g., in repeated calls to :meth:`stc.plot() `) (:gh:`10077` by `Eric Larson`_) + +- Add ``verbose`` parameter to :func:`mne.io.Raw.load_bad_channels` and log information on how bad channels are updated (:gh:`10102` by `Stefan Appelhoff`_) + +- Add ``infer_type`` argument to :func:`mne.io.read_raw_edf` and :func:`mne.io.read_raw_bdf` to automatically infer channel types from channel labels (:gh:`10058` by `Clemens Brunner`_) + +- Reduce the time it takes to generate a :class:`mne.io.Raw`, :class:`~mne.Epochs`, or :class:`~mne.preprocessing.ICA` figure if a ``scalings`` parameter is provided (:gh:`10109` by `Richard Höchenberger`_ and `Eric Larson`_) + +- :meth:`mne.Report.add_raw` gained a new ``scalings`` parameter to provide custom data scalings for the butterfly plots (:gh:`10109` by `Richard Höchenberger`_) + +- The ``butterfly`` parameter of :meth:`mne.Report.add_raw` now also accepts numbers to specify how many segments to plot (:gh:`10115` by `Richard Höchenberger`_) + +- The ``psd`` parameter of :meth:`mne.Report.add_epochs` now also accepts numbers to specify the signal duration used for PSD calculation (:gh:`10119` by `Richard Höchenberger`_) + +- Drastically speed up butterfly plot generation in :meth:`mne.Report.add_raw`. We now don't plot annotations anymore; however, we feel that the speed improvements justify this change, also considering the annotations were of limited use in the displayed one-second time slices anyway (:gh:`10114`, :gh:`10116` by `Richard Höchenberger`_) + +- In :class:`mne.Report`, limit the width of automatically generated figures to a maximum of 850 pixels (450 pixels for :class:`mne.SourceEstimate` plots), and the resolution to 100 DPI to reduce file size, memory consumption, and – in some cases like :meth:`mne.Report.add_stc` – processing time (:gh:`10126`, :gh:`10129`, :gh:`10135`, :gh:`10142` by `Richard Höchenberger`_) + +- :class:`~mne.Epochs` metadata tables are now included in :class:`mne.Report` (:gh:`10166` by `Richard Höchenberger`_) + +- :func:`mne.get_head_surf` and :func:`mne.dig_mri_distances` gained a new parameter, ``on_defects``, controlling how to handle surfaces with topological defects (:gh:`10175` by `Richard Höchenberger`_) + +- :meth:`mne.Report.add_epochs` gained a new parameter, ``drop_log_ignore``, to control which drop reasons to omit when creating the drop log plot (:gh:`10182` by `Richard Höchenberger`_) + +- :meth:`mne.Epochs.plot_drop_log` now also includes the absolute number of epochs dropped in the title (:gh:`10186` by `Richard Höchenberger`_) + +- Add a button to show the maximum intensity projection in ``mne.gui.locate_ieeg`` (:gh:`10185` by `Alex Rockhill`_) + +- Annotations from a :class:`~mne.io.Raw` object are now preserved by the :class:`~mne.Epochs` constructor and are supported when saving Epochs (:gh:`9969` and :gh:`10019` by `Adam Li`_) + +- Add a checkbox to show and hide the MEG helmet in the coregistration GUI (:gh:`10200` by `Guillaume Favelier`_) + +- The coregistration GUI (instantiated via :func:`mne.gui.coregistration`) gained a new attribute, ``coreg``, to access the :class:`mne.coreg.Coregistration` instance used by the GUI (:gh:`10255` by `Richard Höchenberger`_) + +- Add marching cubes display of head if :func:`mne.bem.make_scalp_surfaces` has not computed or the recon-all hasn't finished (:gh:`10202` by `Alex Rockhill`_) + +- The default interaction style of :func:`mne.gui.coregistration` and :func:`mne.viz.plot_alignment` has been changed to ``'terrain'``, which keeps one axis fixed and should make interactions with the 3D scene more predictable (:gh:`9972`, :gh:`10206` by `Richard Höchenberger`_) + +- :func:`mne.gui.coregistration` now uses the proper widget style for push buttons, making for a more native feel of the application (:gh:`10220` by `Richard Höchenberger`_ and `Guillaume Favelier`_) + +- :class:`mne.coreg.Coregistration`, :func:`mne.scale_bem`, and :func:`mne.scale_mri` gained a new parameter, ``on_defects``, controlling how to handle topological defects (:gh:`10230`, :gh:`10249` by `Richard Höchenberger`_) + +- :class:`mne.coreg.Coregistration` gained a new attribute, ``fiducials``, allowing for convenient retrieval of the MRI fiducial points (:gh:`10243`, by `Richard Höchenberger`_) + +- Added plotting points to represent contacts on the max intensity projection plot for ``mne.gui.locate_ieeg`` (:gh:`10212` by `Alex Rockhill`_) + +- Add lines in 3D and on the maximum intensity projection when more than two electrode contacts are selected to aid in identifying that contact for ``mne.gui.locate_ieeg`` (:gh:`10212` by `Alex Rockhill`_) + +- Add a ``block`` parameter to :class:`mne.viz.Brain` and the UI of :class:`mne.coreg.Coregistration` to prevent the windows from closing immediately when running in a non-interactive Python session (:gh:`10222` by `Guillaume Favelier`_) + +- All methods of :class:`mne.Report` with a ``tags`` parameter now also accept a single tag passed as a string (previously, you needed to pass a tuple of strings, even for a single tag) (:gh:`10183`, by `Richard Höchenberger`_) + +- :meth:`mne.Report.add_trans` has gained a new parameter, ``alpha``, to control the level of opacity of the rendered head (:gh:`10247`, by `Richard Höchenberger`_) + +- The new convenience function :func:`mne.event.match_event_names` allows for straightforward checking if a specific event name or a group of events is present in a collection of event names (:gh:`10233` by `Richard Höchenberger`_) + +- :meth:`Epochs.plot` is now supported by the pyqtgraph-backend (:gh:`10297` by `Martin Schulz`_) + +- The ``map_surface`` parameter of :meth:`mne.viz.Brain.add_foci` now works and allows you to add foci to a rendering of a brain that are positioned at the vertex of the mesh closest to the given coordinates (:gh:`10299` by `Marijn van Vliet`_) + +- :meth:`mne.preprocessing.ICA.plot_sources()` is now also supported by the ``qt`` backend (:gh:`10330` by `Martin Schulz`_) + +- Added :meth:`mne.viz.Brain.add_dipole` and :meth:`mne.viz.Brain.add_forward` to plot dipoles on a brain as well as :meth:`mne.viz.Brain.remove_dipole` and :meth:`mne.viz.Brain.remove_forward` (:gh:`10373` by `Alex Rockhill`_) + +- Made anterior/posterior slice scrolling in ``mne.gui.locate_ieeg`` possible for users without page up and page down buttons by allowing angle bracket buttons to be used (:gh:`10384` by `Alex Rockhill`_) + +- Add support for ``theme='auto'`` for automatic dark-mode support in :meth:`raw.plot() ` and related functions and methods when using the ``'qt'`` backend (:gh:`10417` by `Eric Larson`_) + +- Add support for ``MNE_3D_OPTION_THEME`` and ``MNE_BROWSER_THEME`` to use ``['light', 'dark', 'auto']`` or a custom theme path in :class:`mne.viz.Brain` and :meth:`raw.plot() ` (and related functions and methods when using the ``'qt'`` backend(), respectively (:gh:`10418` by `Eric Larson`_) + +- Add support for passing time-frequency data to :func:`mne.stats.spatio_temporal_cluster_test` and :func:`mne.stats.spatio_temporal_cluster_1samp_test` and added an example to :ref:`tut-cluster-spatiotemporal-sensor` (:gh:`10384` by `Alex Rockhill`_) + +- Add support for reading optical density fNIRS data to :func:`mne.io.read_raw_snirf` (:gh:`10408` by `Robert Luke`_) + +- Added :func:`mne.source_space.get_decimated_surfaces` to extract subsurfaces from a SourceSpaces instance or a .fif file (:gh:`10421` by `Joshua Teves`_) + +Bugs +~~~~ +- Fix bug with :func:`mne.io.read_raw_nihon` where latin-1 channels could not be read (:gh:`10429` by :newcontrib:`Matthias Eberlein`) + +- Fix bug with :func:`mne.io.read_raw_nihon` so that it handles duplicates in channel names (:gh:`10431` by :newcontrib:`Matthias Eberlein`) + +- Fix bug in :func:`mne.io.read_raw_egi` where the ``meas_date`` in a ``rawMFF`` object was incorrectly assigned. The function now converts the ``meas_date`` to UTC and provides a UTC offset key, i.e. ``raw.info['utc_offset']``. (:gh:`10304` by :newcontrib:`Scott Huberty`) + +- Fix datetime conversion for tmin/tmax=None cases in :meth:`mne.Annotations.crop`. Allow the use of float and None simultaneously for :meth:`mne.Annotations.crop`. (:gh:`10361` by :newcontrib:`Michiru Kaneda`) + +- Add Shift_JIST mu in :func:`mne.io.read_raw_edf` (:gh:`10356` by :newcontrib:`Michiru Kaneda`) + +- Teach :func:`mne.io.read_raw_bti` to use its ``eog_ch`` parameter (:gh:`10093` by :newcontrib:`Adina Wagner`) + +- Fix use of arguments in :func:`numpy.loadtxt` (:gh:`10189` by :newcontrib:`Federico Zamberlan`) + +- Fix documentation of options in :func:`mne.stc_near_sensors` (:gh:`10007` by :newcontrib:`Nikolai Chapochnikov`) + +- :func:`mne.time_frequency.tfr_array_multitaper` now returns results per taper when ``output='complex'`` (:gh:`10281` by `Mikołaj Magnuski`_) + +- Fix default of :func:`mne.io.Raw.plot` to be ``use_opengl=None``, which will act like False unless ``MNE_BROWSER_USE_OPENGL=true`` is set in the user configuration (:gh:`9957` by `Eric Larson`_) + +- Fix bug with :class:`mne.Report` where figures were saved with ``bbox_inches='tight'``, which led to inconsistent sizes in sliders (:gh:`9966` by `Eric Larson`_) + +- When opening a saved report and saving it to a different filename again, don't change ``Report.fname`` to avoid a regression when using :func:`~mne.open_report` as a context manager (:gh:`9998` by `Marijn van Vliet`_) + +- Fix bug in :func:`mne.make_forward_solution` where sensor-sphere geometry check was incorrect (:gh:`9968` by `Eric Larson`_) + +- Use single char alphanumeric suffix when renaming long channel names (over 15-characters) when writing to FIF format. (:gh:`10002` by `Luke Bloy`_) + +- Add argument ``overwrite`` to :func:`mne.export.export_raw`, :func:`mne.export.export_epochs`, :func:`mne.export.export_evokeds` and :func:`mne.export.export_evokeds_mff` (:gh:`9975` by `Mathieu Scheltienne`_) + +- :func:`mne.gui.coregistration` and the ``mne coreg`` command didn't respect the ``interaction`` parameter (:gh:`9972` by `Richard Höchenberger`_) + +- Fix incorrect projection of source space onto white matter surface instead of pial in :ref:`tut-working-with-ecog` (:gh:`9980` by `Alex Rockhill`_) + +- Fix channel type support when reading from EEGLAB ``.set`` format with :func:`mne.io.read_raw_eeglab` and :func:`mne.read_epochs_eeglab` (:gh:`9990` by `Mathieu Scheltienne`_) + +- Fix suboptimal alignment using :func:`mne.transforms.compute_volume_registration` (:gh:`9991` by `Alex Rockhill`_) + +- Only warn if header is missing in BrainVision files instead of raising an error (:gh:`10001` by `Clemens Brunner`_) + +- Add argument ``overwrite`` to `mne.preprocessing.ICA.save` to check for existing file (:gh:`10004` by `Mathieu Scheltienne`_) + +- :class:`mne.Report` now raises an exception if invalid tags were passed (:gh:`9970` by `Richard Höchenberger`_) + +- Fix bug in :func:`mne.get_montage_volume_labels` that set the maximum number of voxels to be included too low causing unwanted capping of the included voxel labels (:gh:`10021` by `Alex Rockhill`_) + +- Fix annotation cropping and I/O roundtrip when there is no measurement date available (:gh:`10040` by `Mathieu Scheltienne`_ and `Alex Gramfort`_). + +- Fix bug where :meth:`raw.crop() ` from the beginning of the instance could break annotations and ``raw.first_samp`` (:gh:`10358` by `Eric Larson`_) + +- :func:`~mne.sys_info` output now contains the installed version of ``pooch``, too; this output had been accidentally removed previously (:gh:`10047` by `Richard Höchenberger`_) + +- Fix VTK version extraction in :func:`mne.sys_info` (:gh:`10399` by `Eric Larson`_) + +- Fix automatic channel type detection from channel labels in :func:`mne.io.read_raw_edf` and :func:`mne.io.read_raw_bdf` (and disable this functionality from :func:`mne.io.read_raw_gdf`) (:gh:`10058` by `Clemens Brunner`_) + +- Fix :func:`~mne.stats.permutation_cluster_1samp_test` to properly handle 2-dimensional data in combination with TFCE (:gh:`10073` by `Richard Höchenberger`_) + +- Fix channel grouping error when using "butterfly mode" with :meth:`mne.io.Raw.plot` (:gh:`10087` by `Daniel McCloy`_) + +- Fix inconsistent behavior of ``mne.preprocessing.annotate_*`` functions by making them all return :class:`mne.Annotations` objects with the ``orig_time`` attribute set to ``raw.info["meas_time"]`` (:gh:`10067` and :gh:`10118` by `Stefan Appelhoff`_, `Eric Larson`_, and `Alex Gramfort`_) + +- Fix bug that appears during automatic calculation of the colormap of `mne.viz.Brain` when data values of ``fmin`` and ``fmax`` are too close (:gh:`10074` by `Guillaume Favelier`_) + +- We now display a scrollbar in the tags dropdown of a `~mne.Report` if many tags have been added, granting access to all tags instead of "hiding" them below the bottom of the page (:gh:`10082` by `Richard Höchenberger`_) + +- Creating :class:`mne.Epochs` now provides clearer logging (less ambiguous, no duplicates) when the ``preload`` and/or ``metadata`` parameters are set (:gh:`10112` by `Stefan Appelhoff`_) + +- Fix bug with :class:`mne.Epochs` where save-load round-trip with FIF would cause :meth:`mne.Epochs.apply_baseline` to no longer work (:gh:`10177` by `Eric Larson`_) + +- Fix functions by adding missing ``overwrite`` parameters: :func:`mne.write_events`, :func:`mne.write_cov`, :func:`mne.write_evokeds`, :meth:`mne.SourceEstimate.save`, :func:`mne.minimum_norm.write_inverse_operator`, :func:`mne.write_proj`, and related methods (:gh:`10127` by `Eric Larson`_) + +- Fix bug with :func:`mne.transforms.compute_volume_registration` and :func:`mne.compute_source_morph` (volumetric) where the smoothing factors were not scaled based on ``zooms`` (:gh:`10132` by `Eric Larson`_) + +- Remove repeated logging output when overwriting an existing `~mne.io.Raw` file (:gh:`10095` by `Richard Höchenberger`_ and `Stefan Appelhoff`_) + +- In the plots generated by :meth:`mne.Report.add_stc`, we now only add 5 labels to the color bar to reduce the chance of overlap, which could previously cause the labels to become unreadable (:gh:`10135` by `Richard Höchenberger`_) + +- :meth:`mne.Report.add_trans` now allows you to add sensor alignment plots for head surfaces that have topological defects (:gh:`10175` by `Richard Höchenberger`_) + +- :meth:`mne.Report.add_trans` now also works if no digitization points are present in the data (:gh:`10176` by `Jeff Stout`_) + +- Argument ``verbose`` is now respected by dataset fetching (:gh:`10210` by `Mathieu Scheltienne`_) + +- Fix bug with :func:`mne.io.read_raw_hitachi` where empty ``Comment`` descriptions were not handled properly (:gh:`10235` by `Eric Larson`_) + +- Fix bug with input validation of low-level filtering functions (:gh:`10267` by `Eric Larson`_) + +- :func:`mne.gui.coregistration` now works with surfaces containing topological defects (:gh:`10230`, by `Richard Höchenberger`_) + +- Fix bug with :func:`mne.io.read_raw_nirx` being unable to read measurement dates recorded on systems with German (de_DE), French (fr_FR), and Italian (it_IT) locales (:gh:`10277` by `Eric Larson`_) + +- Fix bug with projector normalization checks that were too sensitive, and improve warning (:gh:`10292` by `Eric Larson`_) + +- Fix bug with :func:`mne.viz.plot_alignment` where head-coordinate source spaces (e.g., from a forward solution) were not properly plotted (:gh:`10309` by `Eric Larson`_) + +- :func:`mne.read_trans` and :func:`mne.io.read_fiducials` now correctly expand ``~`` in the provided path (i.e., to the user's home directory) (:gh:`10265`, :gh:`10415`, by `Richard Höchenberger`_) + +- :func:`mne.find_events` now uses ``first_samp`` and not ``0`` for initial event when using ``initial_value`` (:gh:`10289`, by `Alex Gramfort`_) + +- Fix bug with :func:`mne.channels.make_standard_montage` for ``'standard*'``, ``'mgh*'``, and ``'artinis*'`` montages where the points were incorrectly scaled and fiducials incorrectly set away from the correct values for use with the ``fsaverage`` subject (:gh:`10324` by `Eric Larson`_) + +- Fix bug with :meth:`mne.Report.add_figure` where figures generated externally were closed and possibly resized during render (:gh:`10342` by `Eric Larson`_) + +- Fix bug with :func:`mne.viz.plot_sparse_source_estimates` where the return value was incorrect (:gh:`10347` by `Eric Larson`_) + +- Fix plotting bug in :ref:`ex-electrode-pos-2d` and make view look more natural in :ref:`ex-movement-detect` (:gh:`10313`, by `Alex Rockhill`_) + +- Fix bug with blank 3D rendering with MESA software rendering (:gh:`10400` by `Eric Larson`_) + +- Fix a bug in ``mne.gui.locate_ieeg`` where 2D lines on slice plots failed to update and were shown when not in maximum projection mode (:gh:`10335`, by `Alex Rockhill`_) + +- Fix misleading color scale in :ref:`tut-cluster-tfr` for the plotting of cluster F-statistics (:gh:`10393` by `Alex Rockhill`_) + +- Fix baseline removal using ``remove_dc=True`` in :meth:`raw.plot() ` for data containing ``np.nan`` (:gh:`10392` by `Clemens Brunner`_) + +- Fix misleading color scale in :ref:`tut-timefreq-twoway-anova` for plotting F-stats (:gh:`10401` by `Alex Rockhill`_) + +- Fix misleading ``T_obs`` return name for :func:`mne.stats.spatio_temporal_cluster_test` when the default returns an F-statistic (:gh:`10401` by `Alex Rockhill`_) + +API changes +~~~~~~~~~~~ +- The default browser for :meth:`raw.plot() `, :meth:`epochs.plot() `, and :meth:`ica.plot_sources() ` has been changed to the ``'qt'`` backend on systems where `mne_qt_browser `__ is installed. To change back to matplotlib within a session, you can use :func:`mne.viz.set_browser_backend('matplotlib') `. To set it permanently on your system, you can use :func:`mne.set_config('MNE_BROWSER_BACKEND', 'matplotlib') ` (:gh:`9960` by `Martin Schulz`_ and `Eric Larson`_) + +- ``mne.Info.pick_channels`` has been deprecated. Use ``inst.pick_channels`` to pick channels from :class:`~mne.io.Raw`, :class:`~mne.Epochs`, and :class:`~mne.Evoked`. Use :func:`mne.pick_info` to pick channels from :class:`mne.Info` (:gh:`10039` by `Mathieu Scheltienne`_) + +- All :func:`data_path ` functions now return :class:`python:pathlib.Path` objects rather than strings. Support for string concatenation with plus (``+``) is thus deprecated and will be removed in 1.2, use the forward-slash ``/`` operator instead (:gh:`10348` by `Eric Larson`_) + +- Argument ``event_list`` has been deprecated in favor of ``events`` in :func:`mne.write_events` (:gh:`10056` by `Mathieu Scheltienne`_) + +- ``mne.preprocessing.annotate_flat`` has been deprecated in favor of :func:`mne.preprocessing.annotate_amplitude`, that covers both minimum and maximum peak-to-peak variation. (:gh:`10143` by `Mathieu Scheltienne`_) + +- The ``max_ori_out`` parameter of :func:`mne.beamformer.apply_lcmv` and related functions is being removed as only signed estimates are supported. ``abs(stc)`` can be used to obtain unsigned estimates (:gh:`10366` by `Eric Larson`_) + +- The ``verbose`` attribute of classes (e.g., :class:`mne.io.Raw`, `mne.Epochs`, etc.) has been deprecated. Explicitly pass ``verbose`` to methods as necessary instead. (:gh:`10267` by `Eric Larson`_) + +- In :func:`mne.viz.set_browser_backend`, the `mne-qt-browser `__-based backend is now called ``'qt'`` rather than ``'pyqtgraph'`` for simplicity (:gh:`10323` by `Eric Larson`_) + +Dependencies +~~~~~~~~~~~~ +Numerous external dependencies that used to be bundled with MNE-Python are now +not shipped with the package anymore and will instead be retrieved +automatically from their official sources when you install MNE-Python. This +simplifies MNE-Python maintenance and keeps the package smaller. The following +new dependencies have been added: + +- `Jinja2`_ (replaces ``Tempita``, which is not maintained anymore; :gh:`10211` by `Richard Höchenberger`_) + + +.. _Jinja2: https://jinja.palletsprojects.com/ + +Authors +~~~~~~~ + +* Adam Li +* Adina Wagner+ +* Alex Rockhill +* Alexandre Gramfort +* Britta Westner +* Clemens Brunner +* Daniel McCloy +* Eduard Ort +* Eric Larson +* Etienne de Montalivet+ +* Federico Zamberlan+ +* Guillaume Favelier +* Jan Sosulski +* Jan Zerfowski+ +* Jeff Stout +* John Veillette+ +* Joshua Teves +* Julia Guiomar Niso Galán +* Luke Bloy +* Marijn van Vliet +* Martin Schulz +* Mathieu Scheltienne +* Matthias Eberlein+ +* Michiru Kaneda+ +* Mikołaj Magnuski +* Nikolai Chapochnikov+ +* Richard Höchenberger +* Robert Luke +* Scott Huberty+ +* Senwen Deng+ +* Stefan Appelhoff +* Steve Matindi +* Thomas Hartmann diff --git a/mne-python/source/doc/changes/v1.1.rst b/mne-python/source/doc/changes/v1.1.rst new file mode 100644 index 0000000000000000000000000000000000000000..03b03dc3f1860e2bf716d8d9701242da85c1875b --- /dev/null +++ b/mne-python/source/doc/changes/v1.1.rst @@ -0,0 +1,271 @@ +.. _changes_1_1_0: + +Version 1.1.0 (2022-08-03) +-------------------------- + +Enhancements +~~~~~~~~~~~~ +- Added new built-in montage R-Net 128 Ch (Brain Products) (:gh:`10974` by :newcontrib:`Ilias Machairas`) + +- :class:`~mne.channels.DigMontage` objects can now be checked for equality via ``==`` (:gh:`10942` by :newcontrib:`Tziona NessAiver`) + +- Add a note to clarify the inclusion of average referencing gain matrix during whitening (:gh:`10922` by :newcontrib:`Mingjian He`) + +- Add time axis scale bar for :meth:`mne.Epochs.plot` using matplotlib backend (:gh:`10736` by :newcontrib:`Jordan Drew`) + +- Add :func:`mne.bem.distance_to_bem` to find depth of source positions (:gh:`10632` by :newcontrib:`Matt Courtemanche`) + +- Add support for ahdr files in :func:`mne.io.read_raw_brainvision` (:gh:`10515` by :newcontrib:`Alessandro Tonin`) + +- Add support for reading data from Gowerlabs devices to :func:`mne.io.read_raw_snirf` (:gh:`10555` by :newcontrib:`Samuel Powell` and `Robert Luke`_) + +- Add built-in sensor layout files for Geodesic Head Web 130 and 280 devices (:gh:`10627` by `Evan Hathaway`_) + +- Add ``mne-icalabel`` to :func:`mne.sys_info` (:gh:`10615` by `Adam Li`_) + +- Add support for ``overview_mode`` in :meth:`raw.plot() ` and related functions/methods (:gh:`10501` by `Eric Larson`_) + +- Add :meth:`mne.io.Raw.crop_by_annotations` method to get chunks of Raw data based on :class:`mne.Annotations`. (:gh:`10460` by `Alex Gramfort`_) + +- The ``pick_channels`` method gained a ``verbose`` parameter, allowing e.g. to suppress messages about removed projectors (:gh:`10544` by `Richard Höchenberger`_) + +- Add :func:`mne.viz.plot_projs_joint` for joint plotting of projectors and Evoked (:gh:`10720` by `Eric Larson`_) + +- The :func:`mne.make_forward_dipole` function can now take a list of dipoles to make a multi-dipole forward models (:gh:`10464` by `Marijn van Vliet`_) + +- Add ``mode='outlines'`` support to :meth:`mne.Dipole.plot_locations` and :func:`mne.viz.plot_dipole_locations` (:gh:`10699` by `Eric Larson`_) + +- Add :meth:`mne.preprocessing.ICA.find_bads_muscle` to find muscle-related ICA components with an example, :ref:`ex-muscle-ica` (:gh:`10534` by `Alex Rockhill`_) + +- Add example of Xfit-style ECD modeling using multiple dipoles (:gh:`10464` by `Marijn van Vliet`_) + +- Add ``head_source`` argument to :func:`mne.make_field_map` to allow selecting which head source to use (:gh:`10568` by `Eric Larson`_) + +- Add support for ``n_jobs=None`` to support ``joblib:joblib.parallel_backend`` for more precise control over parallelization (:gh:`10567` by `Eric Larson`_) + +- It is now possible to compute inverse solutions with restricted source orientations using discrete forward models (:gh:`10464` by `Marijn van Vliet`_) + +- The new function :func:`mne.preprocessing.maxwell_filter_prepare_emptyroom` simplifies the preconditioning of an empty-room recording for our Maxwell filtering operations (:gh:`10533` by `Richard Höchenberger`_ and `Eric Larson`_) + +- Add keyboard shortcuts to toggle :meth:`mne.preprocessing.ICA.plot_properties` topomap channel types ('t') and power spectral density log-scale ('l') (:gh:`10557` by `Alex Rockhill`_) + +- Add ``--mri``, and ``--threshold`` options to :ref:`mne make_scalp_surfaces` to improve head surface mesh extraction (:gh:`10591` by `Eric Larson`_) + +- Add :func:`mne.preprocessing.compute_bridged_electrodes` to detect EEG electrodes with shared spatial sources due to a conductive medium connecting two or more electrodes, add :ref:`ex-eeg-bridging` for an example and :func:`mne.viz.plot_bridged_electrodes` to help visualize (:gh:`10571` by `Alex Rockhill`_) + +- Add ``'nearest'`` as an option for the ``image_interp`` argument in :func:`mne.viz.plot_topomap` to plot a topomap without interpolation using a Voronoi parcelation (:gh:`10571` by `Alex Rockhill`_) + +- Add :func:`mne.preprocessing.interpolate_bridged_electrodes` to use the spatially smeared signal to get a better interpolation rather than dropping those channels (:gh:`10587` by `Alex Rockhill`_) + +- Add support for hemoglobin type fNIRS data to temporal derivative distribution repair (TDDR) :func:`mne.preprocessing.nirs.temporal_derivative_distribution_repair` (:gh:`10125` by `Johann Benerradi`_) + +- :func:`mne.viz.plot_evoked_topomap` and :meth:`mne.Evoked.plot_topomap` now display the time range the map was averaged over if ``average`` was passed (:gh:`10606` by `Richard Höchenberger`_) + +- :func:`mne.viz.plot_evoked_topomap` and :meth:`mne.Evoked.plot_topomap` can now average the topographic maps across different time periods for each time point. To do this, pass a list of periods via the ``average`` parameter (:gh:`10610` by `Richard Höchenberger`_) + +- :func:`mne.viz.plot_evoked` and :meth:`mne.Evoked.plot` gained a new parameter, ``highlight``, to visually highlight time periods of interest (:gh:`10614` by `Richard Höchenberger`_) + +- Added fNIRS support to :func:`mne.Info.get_montage` (:gh:`10611` by `Robert Luke`_) + +- Add :func:`mne.viz.plot_ch_adjacency` to visualize and manually edit the channel adjacency matrix (:gh:`10633` by `Mikołaj Magnuski`_) + +- Add :meth:`mne.viz.Brain.get_view` to get the current camera parameters such that they can be passed to :meth:`mne.viz.Brain.show_view` (:gh:`10661` by `Alex Rockhill`_) + +- Added support for Aurora version 2021.9.0.6 to :func:`mne.io.read_raw_nirx` (:gh:`10668` by `Robert Luke`_) + +- Added BrainVision format (``.vhdr``, ``.vmrk``, ``.eeg``) to :func:`mne.export.export_raw` (:gh:`10681` by `Stefan Appelhoff`_) + +- Added ``export`` method to :class:`mne.Evoked` (:gh:`10681` by `Stefan Appelhoff`_) + +- Add timeformat ``YYYY/MM/DD`` to ``mne.io.ctf.info._convert_time`` (:gh:`10674` by `Simon Kern`_) + +- :meth:`mne.Report.add_figure` and :meth:`mne.Report.add_image` gained a new parameter, ``section``, allowing to put multiple figures or images into the same "content block". Previously, the only way to group figures and images was by means of a slider, which sometimes made content hard to discover. The slider remains available as an alternative (:gh:`10694` by `Richard Höchenberger`_) + +- All functions and methods that plot topographic maps for EEG (2D projections of the EEG sensor locations) now accept the parameter value ``sphere='eeglab'`` to lay out the sensors with respect to the head circle in a similar way to how EEGLAB does, i.e., T7/T8 and Fpz/Oz are placed directly on the circle for template montages (:gh:`10572` by `Richard Höchenberger`_) + +- :func:`mne.channels.get_builtin_montages` gained a new parameter, ``descriptions``, which allows to retrieve the descriptions of the montages in addition to their names (:gh:`10373` by `Richard Höchenberger`_) + +- Add ``include`` option to :meth:`mne.io.read_raw_edf`, :meth:`mne.io.read_raw_bdf` and :meth:`mne.io.read_raw_gdf`. (:gh:`10734` by `Michiru Kaneda`_) + +- :func:`mne.gui.coregistration` gained a new parameter, ``fullscreen``, to start the GUI in fullscreen mode (:gh:`10284` by `Richard Höchenberger`_) + +- The built-in FieldTrip channel adjacency matrices, which can be read via :func:`~mne.channels.read_ch_adjacency`, have been synchronized with FieldTrip again. This means that numerous new adjacencies have been added, most notably those for standard 10-05 and 10-20 montages (:gh:`10749` by `Richard Höchenberger`_) + +- :meth:`mne.Evoked.plot_field` gained a new parameter, ``interaction``, to control the rotation axes when interacting with the head (:gh:`10788` by `Richard Höchenberger`_) + +- Add :func:`mne.read_evoked_besa` for reading evokeds from BESA ``.avr`` and ``.mul`` files. (:gh:`10892` by `Marijn van Vliet`_) + +- Add :meth:`mne.time_frequency.EpochsTFR.decimate` to reduce size of time-frequency epochs objects (:gh:`10940` by `Alex Rockhill`_) + +- Add an alias that maps EGI reference channel names (``VREF`` or ``Vertex Reference``) to the electrode name in the standard EGI montages (``Cz``). Now setting standard EGI montages with :meth:`~mne.io.Raw.set_montage` with ``match_alias=True`` will avoid raising an error (:gh:`10823` by `Scott Huberty`_) + +- Add provenance in :func:`mne.time_frequency.EpochsTFR.apply_baseline` (:gh:`10979` by `Alex Rockhill`_) + +Bugs +~~~~ +- Fix bug in ``mne.surface._project_onto_surface`` for the condition ``method != 'accurate' and return_nn`` (:gh:`10930` by `Christian O'Reilly`_) + +- Fix bug in :func:`mne.export.export_raw` to ignore None value in filenames attribute of :class:`mne.io.RawArray` (:gh:`10927` by :newcontrib:`Reza Nasri`) + +- Fix bug in :func:`mne.io.read_raw_edf` to allow reading in all Hypnodyne ZMax EDFs to be read in without issues (:gh:`10754` by :newcontrib:`Frederik Weber`) + +- Fix bug in :func:`mne.Epochs.drop_bad` where data was loaded although no rejection had to be performed (:gh:`10718` by :newcontrib:`Lukas Gemein`) + +- Pick also bad channels when selecting T1T2 magnetometers in :func:`mne.preprocessing.maxwell_filter` (:gh:`10639` by :newcontrib:`Matti Toivonen`) + +- Make ``color`` parameter check in in :func:`mne.viz.plot_evoked_topo` consistent (:gh:`10217` by :newcontrib:`T. Wang` and `Stefan Appelhoff`_) + +- Fix bug in :func:`mne.io.read_raw_brainvision` when BrainVision data are acquired with the Brain Products "V-Amp" amplifier and disabled lowpass filter is marked with value ``0`` (:gh:`10517` by :newcontrib:`Alessandro Tonin`) + +- Fix bug in :func:`mne.pick_types` and related methods where ``csd=True`` was not passed handled properly (:gh:`10470` by :newcontrib:`Matthias Dold`) + +- Fix bug where plots produced using the ``'qt'`` / ``mne_qt_browser`` backend could not be added using :meth:`mne.Report.add_figure` (:gh:`10485` by `Eric Larson`_) + +- Fix bug where ``theme`` was not handled properly in :meth:`mne.io.Raw.plot` (:gh:`10487`, :gh:`10500` by `Mathieu Scheltienne`_ and `Eric Larson`_) + +- Fix bug in :meth:`raw.crop(start, stop) ` that would cause annotations to be erroneously shifted when ``start != 0`` and no measurement date was set. (:gh:`10491` by `Eric Larson`_) + +- Fix bug in :func:`mne.io.read_raw_bti` where unknown electrode locations were not handled properly (:gh:`10662` by `Eric Larson`_) + +- Fix bug in :func:`mne.io.read_raw_ctf` on Windows where large files could not be read (:gh:`10866` by `Eric Larson`_) + +- Fix bug in :func:`mne.io.read_raw_ctf` where invalid measurement dates were not handled properly (:gh:`10957` by `Jean-Rémi King`_ and `Eric Larson`_) + +- Rendering issues with recent MESA releases can be avoided by setting the new environment variable ``MNE_3D_OPTION_MULTI_SAMPLES=1`` or using :func:`mne.viz.set_3d_options` (:gh:`10513` by `Eric Larson`_) + +- Fix behavior for the ``pyvista`` 3D renderer's ``quiver3D`` function so that default arguments plot a glyph in ``arrow`` mode (:gh:`10493` by `Alex Rockhill`_) + +- Retain epochs metadata when using :func:`mne.channels.combine_channels` (:gh:`10504` by `Clemens Brunner`_) + +- Fix epochs indexing with metadata containing boolean type and missing values (:gh:`10705` by `Clemens Brunner`_ and `Alex Gramfort`_) + +- Fix reading of fiducial locations in :func:`mne.io.read_raw_eeglab` (:gh:`10521` by `Alex Gramfort`_) + +- Prevent creation of montage with invalid ``[x, y, z]`` coordinates with :func:`mne.channels.make_dig_montage` (:gh:`10547` by `Mathieu Scheltienne`_) + +- Fix bug in coregistration GUI that prevented it from starting up if only a high-resolution head model was available (:gh:`10543` by `Richard Höchenberger`_) + +- Fix bug with :class:`mne.Epochs.add_reference_channels` where attributes were not updated properly so subsequent `~mne.Epochs.pick_types` calls were broken (:gh:`10912` by `Eric Larson`_) +- +- Fix bug in the :class:`mne.viz.Brain` tool bar that prevented the buttons to call the corresponding feature (:gh:`10560` by `Guillaume Favelier`_) + +- Fix issue with saving epochs once :func:`~mne.preprocessing.compute_current_source_density` has been used if a rejection threshold was used first (:gh:`10619` by `Alex Rockhill`_ and `Richard Höchenberger`_) + +- Fix bug in :func:`mne.viz.plot_evoked_image` that would cause incorrect sub-titles when using ``group_by`` (:gh:`10618` by `Reza Shoorangiz`_) + +- Reduce memory usage when loading an EDF file with ``preload=False`` (:gh:`10638` by `Clemens Brunner`_) + +- Fix bug in :meth:`mne.io.Raw.get_channel_types` and related methods where ``unique=True`` would return a :class:`python:set` with arbitrary order rather than a :class:`python:list` that preserves the same order as ``inst.ch_names`` (:gh:`10720` by `Eric Larson`_) + +- In :func:`mne.preprocessing.find_bad_channels_maxwell`, do not re-filter the data if a low-pass filter with the requested frequency has already been applied (:gh:`10664` by `Richard Höchenberger`_) + +- Fix a problem in :meth:`mne.Evoked.get_peak`, where under certain circumstances the ``mode`` parameters ``'pos'`` and ``'neg'`` were not honored when ``tmin`` and/or ``tmax`` were passed as well (:gh:`10686` by `Richard Höchenberger`_) + +- :func:`mne.read_evokeds`, :func:`mne.channels.read_custom_montage`, :func:`mne.channels.read_dig_hpts`, :func:`mne.channels.read_dig_polhemus_isotrak`, and :func:`mne.channels.read_polhemus_fastscan` now correctly expand ``~`` in the provided path to the user's home directory (:gh:`10685`, :gh:`10688` by `Richard Höchenberger`_) + +- Fix bug in :func:`mne.io.read_raw_eeglab` and :func:`mne.read_epochs_eeglab`, where the presence of channels without position in the ``.set`` file caused positions incorrectly assigned to all further channels (:gh:`8754` by `Mikołaj Magnuski`_) + +- Combining channels of :class:`mne.Epochs` or :class:`mne.Evoked` objects now properly retains baseline information (:gh:`10703` by `Clemens Brunner`_) + +- In :class:`mne.Report`, some figures would have an undesired border added to the edges; this has now been resolved (:gh:`10730` by `Richard Höchenberger`_) + +- Fix selection of EEG channels and selected sphere when plotting bridged electrodes with :func:`mne.viz.plot_bridged_electrodes` (:gh:`10753` by `Mathieu Scheltienne`_) + +- Fix broken links in :ref:`tut-fix-meshes` (:gh:`10765` by `Alex Rockhill`_) + +- The built-in FieldTrip channel adjacency matrix for ``easycapM1`` had a bug, where the channel ``PO8`` was incorrectly labeled as ``PO6`` This has been resolved by updating the adjacency matrix to the latest version provided by FieldTrip (:gh:`10749` by `Richard Höchenberger`_) + +- Add a YouTube video tutorial for editing Freesurfer surfaces in Blender to :ref:`tut-fix-meshes` (:gh:`10778` by `Alex Rockhill`_) + +- The default interaction style of :meth:`mne.Evoked.plot_field` has been changed such that if behaves like :func:`~mne.viz.plot_alignment` when trying to rotate the head (:gh:`10788` by `Richard Höchenberger`_) + +- Add a video on how to operate the intracranial electrode contact location GUI in :ref:`tut-ieeg-localize` (:gh:`10800` by `Alex Rockhill`_) + +- Add a video on how to operate the coregistration GUI in :ref:`tut-source-alignment` (:gh:`10802` by `Alex Rockhill`_) + +- Add ``show`` and ``block`` arguments to :func:`mne.gui.coregistration` and ``mne.gui.locate_ieeg`` to pop up the GUIs and halt execution of subsequent code respectively (:gh:`10802` by `Alex Rockhill`_) + +- Correctly report the number of available projections when printing measurement info in a Jupyter notebook (:gh:`10471` by `Clemens Brunner`_) + +- Fix value set in ``raw.orig_format`` for readers of BrainVision (ASCII format), EGI and Artemis123 files (:gh:`10851` by `Mathieu Scheltienne`_) + +- When reading EGI MFF files, channel names are no longer ignored and reference channel information is properly incorporated (:gh:`10898` by `Scott Huberty`_ and `Daniel McCloy`_) + +- Fix bug in :func:`mne.time_frequency.psd_array_welch` and related functions/methods where the bias was not accounted for when ``average='median'`` (:gh:`10990` by `Eric Larson`_) + +- Fix bug in :class:`mne.decoding.TemporalFilter` where filter parameters were not handled properly (:gh:`10968` by `Eric Larson`_) + +- Fix documentation bug in ``ica.plot_sources`` to specify that ``picks`` keyword argument is for picking ICA components to plot (:gh:`10936` by `Adam Li`_) + +- Annotations contained in EDF files are correctly read as UTF-8 according to the EDF specification (:gh:`10963` by `Clemens Brunner`_) + +- Fix bug where complex-valued topoplots caused an error, convert to amplitude instead (:gh:`10978` by `Alex Rockhill`_) + +API and behavior changes +~~~~~~~~~~~~~~~~~~~~~~~~ +- When creating BEM surfaces via :func:`mne.bem.make_watershed_bem` and :func:`mne.bem.make_flash_bem`, the ``copy`` parameter now defaults to ``True``. This means that instead of creating symbolic links inside the FreeSurfer subject's ``bem`` folder, we now create "actual" files. This should avoid troubles when sharing files across different operating systems and file systems (:gh:`10531` by `Richard Höchenberger`_) + +- The ordering of channels returned by :func:`mne.io.read_raw_nirx` is now ordered by channel name, rather than the order provided by the manufacturer. This enables consistent ordering of channels across different file types (:gh:`10555` by `Robert Luke`_) + +- For :func:`mne.viz.plot_topomap`, :func:`mne.viz.plot_evoked_topomap`, :func:`mne.viz.plot_arrowmap`, :func:`mne.viz.plot_ica_components`, :meth:`mne.Covariance.plot_topomap`, :meth:`mne.Evoked.plot_topomap`, :meth:`mne.Evoked.animate_topomap`, :meth:`mne.decoding.CSP.plot_patterns`, :meth:`mne.Projection.plot_topomap` and :meth:`mne.preprocessing.ICA.plot_components` the topomap image interpolation was previously a cubic interpolation but now can be ``'linear'`` and ``'nearest'`` as well. Unless ``image_interp='nearest'`` is passed mne uses a subsequent matplotlib bilinear interpolation to make the interpolated image smoother. Previously, ``'image_interp'`` controlled this second interpolation step and, for the first interpolation, the only option was cubic. To simplify, ``image_interp`` is now responsible for the main interpolation and the subsequent matplotlib image interpolation is bilinear but can be changed afterward using ``im.set_interpolation`` (:gh:`10617` by `Alex Rockhill`_) + +- The FLASH BEM surface generation via :func:`mne.bem.make_flash_bem` or the :ref:`mne flash_bem` command has now been clarified in terms of expected inputs. In :func:`mne.bem.convert_flash_mris` the ``convert`` parameter is now deprecated and the ``flash5`` and ``flash30`` now accept list of file names or nibabel images. One breaking change is that now the flash files are looked for as mef05_*.mgz and mef30_*.mgz in mri/flash folder (:gh:`10715` by `Alex Gramfort`_) + +- :func:`~mne.viz.plot_compare_evokeds` gets a new parameter ``time_unit`` which can be ``"s"`` or ``"ms"`` (:gh:`10950` by `Daniel McCloy`_) + +- The ``to_data_frame`` methods for :meth:`Raw `, :meth:`Epochs `, :meth:`Evoked `, :meth:`SourceEstimate `, :meth:`EpochsTFR `, and :meth:`AverageTFR ` all now have default ``time_format=None`` (keep time in seconds) instead of ``time_format='ms'`` (convert time to milliseconds) (:gh:`10925` by `Daniel McCloy`_) + +- :func:`mne.Evoked.decimate` now aligns to the sample at time=0 (so that the exact sample when the event occurred is preserved) to be consistent with :func:`mne.Epochs.decimate` (:gh:`10945` by `Alex Rockhill`_) + +Authors +~~~~~~~ + +* Adam Li +* Adeline Fecker+ +* Alessandro Tonin+ +* Alex Ciok+ +* Alex Rockhill +* Alexandre Gramfort +* Archit Singhal+ +* Ashley Drew+ +* Ben Beasley+ +* Carina Forster+ +* Christian O'Reilly +* Clemens Brunner +* Cora Kim +* Daniel McCloy +* Dominik Welke +* Dominique Makowski +* Eric Larson +* Evan Hathaway +* Frederik D. Weber+ +* Guillaume Favelier +* Hamid Maymandi+ +* Ilias Machairas+ +* Jean-Rémi King +* Johann Benerradi +* Jon Houck +* Jona Sassenhagen +* Jordan Drew+ +* Lukas Gemein+ +* Marijn van Vliet +* Martin Schulz +* Mathieu Scheltienne +* Matt Courtemanche+ +* Matthias Dold+ +* Matti Toivonen+ +* Michiru Kaneda+ +* Mikołaj Magnuski +* Mingjian He+ +* Naveen Srinivasan+ +* Phillip Alday +* Reza Nasri+ +* Reza Shoorangiz +* Richard Höchenberger +* Rob Luke +* Scott Huberty+ +* Simon Kern +* Sondre Foslien+ +* Stefan Appelhoff +* T. Wang+ +* Tziona NessAiver+ diff --git a/mne-python/source/doc/changes/v1.10.rst b/mne-python/source/doc/changes/v1.10.rst new file mode 100644 index 0000000000000000000000000000000000000000..7c6baae19a54ddb9bf39baf6ab7ac7b7183d8db6 --- /dev/null +++ b/mne-python/source/doc/changes/v1.10.rst @@ -0,0 +1,130 @@ +.. _changes_1_10_0: + +Version 1.10.0 (2025-07-14) +=========================== + +Bugfixes +-------- + +- Fixed behavior of :func:`mne.viz.plot_source_estimates` where the ``title`` was not displayed properly, by :newcontrib:`Shristi Baral`. (`#12828 `__) +- Return events when requested even when current matches the desired sfreq in :meth:`mne.io.Raw.resample` by :newcontrib:`Roy Eric Wieske`. (`#13070 `__) +- Fix bug in :func:`mne.io.read_raw_gdf`, by :newcontrib:`Rongfei Jin`. (`#13113 `__) +- Fixed CTF cHPI coil location detection in :func:`mne.chpi.extract_chpi_locs_ctf` by :newcontrib:`Shresth Keshari`. (`#13123 `__) +- Fix bug with sampling frequency estimation in snirf files, by `Daniel McCloy`_ and :newcontrib:`Yixiao Shen`. (`#13184 `__) +- Fix bug where :func:`mne.gui.coregistration` would emit an error for some CTF datasets, by :newcontrib:`Wei Xu`. (`#13218 `__) +- Improved the configuration json to handle with parallel access with file lock configuration by :newcontrib:`Bruno Aristimunha`. (`#13241 `__) +- Update :func:`mne.viz.plot_alignment` and related functions to support PyVista deprecation of positional arguments by :newcontrib:`user27182`. (`#13277 `__) +- Fixed bug where :func:`mne.preprocessing.maxwell_filter_prepare_emptyroom` would not reliably identify meg channel types for matching bads across emptyroom and task, by :newcontrib:`Harrison Ritz`. (`#13280 `__) +- Fixed bug where saving FIFF files failed when ``info["subject_info"]["birthday"]`` was a :class:`pandas.Timestamp` instead of :class:`datetime.date`, by :newcontrib:`Laurent Le Mentec`. (`#13284 `__) +- Fixed almost-white (barely visible) channel traces when using ``spatial_colors=True`` in :meth:`mne.io.Raw.plot_psd`, :meth:`mne.Epochs.plot_psd`, and related PSD-plot helpers, by :newcontrib:`Mojackhak`. (`#13286 `__) +- Fix bug where :func:`mne.export.export_raw` does not correct for recording start time (:attr:`raw.first_time `) when exporting Raw instances to EDF or EEGLAB formats, by `Qian Chu`_. (`#12656 `__) +- Fix epoch indexing in :class:`mne.time_frequency.EpochsTFRArray` when initialising the class with the default ``drop_log`` parameter, by `Thomas Binns`_. (`#13028 `__) +- Fix loading and saving of :class:`~mne.time_frequency.EpochsSpectrum` objects that contain slash-separators in their condition names, by `Daniel McCloy`_. (`#13042 `__) +- Fix input boxes for the max value not showing when plotting fieldlines with :func:`~mne.viz.plot_evoked_field` when ``show_density=False``, by `Marijn van Vliet`_. (`#13048 `__) +- Fix bug with saving of anonymized data when helium info is present in measurement info, by `Eric Larson`_. (`#13056 `__) +- Fix computation of time intervals in :func:`mne.preprocessing.compute_fine_calibration` by `Eric Larson`_. (`#13062 `__) +- Fix bug in the colorbars created by :func:`mne.viz.plot_evoked_topomap` by `Santeri Ruuskanen`_. (`#13063 `__) +- Improved sklearn class compatibility and compliance, which resulted in some parameters of classes having an underscore appended to their name during ``fit``, such as: + + - :class:`mne.decoding.FilterEstimator` parameter ``picks`` passed to the initializer is set as ``est.picks_`` + - :class:`mne.decoding.UnsupervisedSpatialFilter` parameter ``estimator`` passed to the initializer is set as ``est.estimator_`` + + Unused ``verbose`` class parameters (that had no effect) were removed from :class:`~mne.decoding.PSDEstimator`, :class:`~mne.decoding.TemporalFilter`, and :class:`~mne.decoding.FilterEstimator` as well. + Changes by `Eric Larson`_. (`#13065 `__) +- Fix bug where taper weights were not correctly applied when computing multitaper power with :meth:`mne.Epochs.compute_tfr` and :func:`mne.time_frequency.tfr_array_multitaper`, by `Thomas Binns`_. (`#13067 `__) +- Fix bug cause by unnecessary assertion when loading mixed frequency EDFs without preloading :func:`mne.io.read_raw_edf` by `Simon Kern`_. (`#13069 `__) +- Fix bug with automated Mesa 3D detection for proper 3D option setting on systems with software rendering, by `Eric Larson`_. (`#13082 `__) +- Fix bug with reading digitization points from digitization strings with newer MEGIN systems, by `Eric Larson`_. (`#13083 `__) +- Fix bug when loading certain EEGLAB files that do not contain a ``nodatchans`` field, by `Clemens Brunner`_. (`#13097 `__) +- Do not convert the first "New Segment" marker in a BrainVision file to an annotation, as it only contains the recording date (which is already available in ``info["meas_date"]``), by `Clemens Brunner`_. (`#13100 `__) +- Take units (m or mm) into account when drawing :func:`~mne.viz.plot_evoked_field` on top of :class:`~mne.viz.Brain`, by `Marijn van Vliet`_. (`#13101 `__) +- Improved the handling of problematic MFF files in `mne.io.read_raw_egi` by `Scott Huberty`_. (`#13145 `__) +- Fix bug in :func:`mne.bem.make_watershed_bem` where function would fail if ``talairach_with_skull.lta`` did not exist due to changes in Freesurfer by `Peter Molfese`_. (`#13172 `__) +- Fix bug where :func:`mne.export.export_raw` might allocate huge intermediate arrays unnecessarily, when padding data blocks during export to EDF format, by `Daniel McCloy`_. (`#13174 `__) +- Fix bug with least-squares fitting of head origin using digitization points in :func:`mne.preprocessing.maxwell_filter`, by `Eric Larson`_. (`#13178 `__) +- Fix bug with :func:`mne.viz.plot_alignment` where ``eeg="projected"`` was not plotted, by `Eric Larson`_. (`#13179 `__) +- Fixed bug with filter padding type in :func:`mne.io.Raw.plot` and related functions to reduce edge ringing during data display, by `Eric Larson`_. (`#13183 `__) +- Handle channels with potential electrode location in :func:`~mne.preprocessing.maxwell_filter_prepare_emptyroom`, by `Mathieu Scheltienne`_. (`#13208 `__) +- Fixed bug where the file_id is not set when the file contains a directory at the end of the file, by `Théodore Papadopoulo`_. (`#13268 `__) +- Fix bug with :func:`mne.simulation.simulate_raw` and :class:`mne.simulation.SourceSimulator` where using different head positions with ``head_pos`` and a BEM would raise an error, by `Eric Larson`_. (`#13276 `__) +- Fix y-axis label in PSD plot when ``dB=True`` to show a more conventional label (i.e., dB/Hz or dB/√Hz), by `Clemens Brunner`_. (`#13298 `__) +- Fix bug in :func:`mne.sys_info` where calling it in Windows could lead to a an error while trying to get the amount of available memory, by `Eric Larson`_. (`#13310 `__) +- Change default pupil unit scalings from micrometrs to millimeters by `Scott Huberty`_ (`#13314 `__) +- Fix :meth:`mne.channels.DigMontage.rename_channels` so that the changed montage is returned instead of ``None``, by `Stefan Appelhoff`_. (`#13320 `__) + + +API changes by deprecation +-------------------------- + +- The backward-compatible defaults in :func:`mne.preprocessing.maxwell_filter` of ``st_overlap=False`` and ```mc_interp=None`` will change to their smooth variants ``True`` and ``"hann"``, respectively, in 1.11, by `Eric Larson`_. (`#13080 `__) + + +New features +------------ + +- Add PCA-OBS preprocessing for the removal of heart-artefacts from EEG or ESG datasets via :func:`mne.preprocessing.apply_pca_obs`, by :newcontrib:`Emma Bailey` and :newcontrib:`Steinn Hauser Magnusson`. (`#13037 `__) +- Add :meth:`mne.Evoked.interpolate_to` to allow interpolating EEG data to other montages, by :newcontrib:`Antoine Collas`. (`#13044 `__) +- Allow for ``topomap`` plotting of optically pumped MEG (OPM) sensors with overlapping channel locations. When channel locations overlap, plot the most radially oriented channel. By :newcontrib:`Harrison Ritz`. (`#13144 `__) +- Improved error message in :meth:`mne.io.Raw.save` when attempting to overwrite a file, by :newcontrib:`Sebastian Jentschke` (`#13233 `__) +- Add new ``select`` parameter to :func:`mne.viz.plot_evoked_topo` and :meth:`mne.Evoked.plot_topo` to toggle lasso selection of sensors, by `Marijn van Vliet`_. (`#12071 `__) +- Add source space(s) visualization(s) in :func:`mne.Report.add_forward`, by `Victor Ferat`_. (`#12848 `__) +- Added the option to return taper weights from :func:`mne.time_frequency.tfr_array_multitaper`, and taper weights are now stored in the :class:`mne.time_frequency.BaseTFR` objects, by `Thomas Binns`_. (`#12910 `__) +- Add ``fig.mne`` container for :class:`Colorbar ` in :func:`plot_connectivity_circle ` to allow users to access it directly, by `Santeri Ruuskanen`_. (`#13019 `__) +- Added :func:`mne.time_frequency.combine_tfr` to allow combining TFRs across tapers, by `Thomas Binns`_. (`#13054 `__) +- Add the function :func:`mne.time_frequency.combine_spectrum` for combining data across :class:`mne.time_frequency.Spectrum` objects, and allow :func:`mne.grand_average` to operate on :class:`mne.time_frequency.Spectrum` objects, by `Thomas Binns`_. (`#13058 `__) +- Add smooth processing of tSSS windows (using overlap-add) and movement compensation (using smooth interpolation of head positions) in :func:`mne.preprocessing.maxwell_filter` via ``st_overlap`` and ```mc_interp`` options, respectively, by `Eric Larson`_. (`#13080 `__) +- The :meth:`mne.Info.save` method now has an ``overwrite`` and a ``verbose`` parameter, by `Stefan Appelhoff`_. (`#13107 `__) +- Add ``upsampling`` option to :func:`mne.make_field_map` to allow upsampling MEG helmet surfaces for plotting, by `Eric Larson`_. (`#13179 `__) +- New argument ``sfreq`` to :func:`mne.io.read_raw_snirf`, to allow overriding the sampling frequency estimated from (possibly jittered) sampling periods in the file, by `Daniel McCloy`_. (`#13184 `__) +- Add an ``extras`` attribute to :class:`mne.Annotations` for storing arbitrary metadata, by `Pierre Guetschel`_. (`#13228 `__) +- :meth:`mne.Report.add_trans` now accepts ``"auto"`` and ``"fsaverage"`` as arguments for the ``trans`` parameter, by `Stefan Appelhoff`_. (`#13232 `__) +- Add a new parameter ``plot_kwargs`` to :meth:`mne.Report.add_trans`, to control low level properties of the visualization, by `Stefan Appelhoff`_. (`#13234 `__) +- :func:`~mne.channel_indices_by_type` now has an ``exclude`` parameter, by `Stefan Appelhoff`_. (`#13293 `__) + + +Other changes +------------- + +- Add test analytics functionality to track and analyze test performance, by :newcontrib:`Katia Al-Amir`. (`#13225 `__) + + +Authors +------- + +* Alexandre Gramfort +* Antoine Collas+ +* Britta Westner +* Bruno Aristimunha+ +* Clemens Brunner +* Daniel McCloy +* Dominik Welke +* Emma Bailey+ +* Eric Larson +* Harrison Ritz+ +* Jona Sassenhagen +* Katia Al-Amir+ +* Laurent Lementec+ +* Marijn van Vliet +* Mathieu Scheltienne +* Mojackhak+ +* Peter J. Molfese +* Pierre Guetschel +* Qian Chu +* Richard Höchenberger +* Rongfei Jin+ +* Roy Eric Wieske +* Santeri Ruuskanen +* Scott Huberty +* Sebastian Jentschke+ +* Shresth Keshari+ +* Shristi Baral+ +* Simon Kern +* Stefan Appelhoff +* Steinn Hauser Magnússon+ +* Teon L Brooks +* Theodore Papadopoulo +* Thomas S. Binns +* Victor Férat +* Wei Xu+ +* Yixiao Shen+ +* user27182+ diff --git a/mne-python/source/doc/changes/v1.11.rst b/mne-python/source/doc/changes/v1.11.rst new file mode 100644 index 0000000000000000000000000000000000000000..f4f5cd2c68484d4722d0a92958e470d12412cd75 --- /dev/null +++ b/mne-python/source/doc/changes/v1.11.rst @@ -0,0 +1,122 @@ +Version 1.11.0 (2025-11-21) +=========================== + +Dependencies +------------ + +- New reader for Neuroscan Curry files, using the curry-python-reader module, by `Dominik Welke`_. (`#13176 `__) + + +Bugfixes +-------- + +- Handle scenario where an Eyelink recording switched from binocular to monocular mode during a trial by `Scott Huberty`_ (`#12847 `__) +- Fixed ICA getting sources for concatenated raw instances, by :newcontrib:`Beige Jin`. (`#13068 `__) +- Fix reading annotations with :func:`mne.read_annotations` from .csv files containing nanoseconds in times, and drop nanoseconds from times returned from :meth:`mne.Annotations.to_data_frame` and saved in .csv files by :meth:`mne.Annotations.save`, by `Thomas Binns`_. (`#13109 `__) +- Fix bug with :func:`mne.io.read_raw_egi` where ``info["dev_head_t"]`` was an identity matrix instead of ``None``, by `Eric Larson`_. (`#13112 `__) +- Read Nihon Kohden annotation file accurately (using sublog parsing), by `Tom Ma`_. (`#13251 `__) +- Fix bug with :func:`mne.open_report` not working with old saved files, by `Eric Larson`_. (`#13341 `__) +- Restore ``clipping=3`` in :meth:`~mne.io.Raw.plot` (which was mistakenly changed to ``1.5``) to reduce excessive clipping of raw data, by `Clemens Brunner`_. (`#13354 `__) +- Make :func:`~mne.io.read_raw_eyelink` work with ASCII files collected with Eye Event Mode set to "HREF" by `Scott Huberty`_. (`#13357 `__) +- ``model`` parameter of :class:`mne.decoding.LinearModel` + will not be modified, use ``model_`` attribute to access the fitted model. + To be compatible with all MNE-Python versions you can use + ``getattr(clf, "model_", getattr(clf, "model"))`` + The provided ``model`` is expected to be a supervised predictor, + i.e. classifier or regressor (or :class:`sklearn.multiclass.OneVsRestClassifier`), + otherwise an error will be raised. + by `Gennadiy Belonosov`_. (`#13361 `__) +- Fix the check in :func:`mne.make_forward_solution` that all MEG sensors are outside a spherical BEM model, by `Marijn van Vliet`_ (`#13371 `__) +- Fix bug with :func:`mne.grand_average` not working with :class:`mne.time_frequency.Spectrum` objects, by `Thomas Binns`_. (`#13375 `__) +- Ensure auto-computed plot scalings are always non-zero, by `Daniel McCloy`_. (`#13376 `__) +- Fix :func:`~mne.viz.plot_evoked_joint` docstring to correctly document ``exclude`` parameter default as ``'bads'`` instead of ``None``, by :newcontrib:`Tharupahan Jayawardana`. (`#13391 `__) +- Make decoding classes sklearn-compliant, by `Gennadiy Belonosov`_. (`#13393 `__) +- Fix loading problems caused by attempting to iterate floats in :func:`~mne.read_epochs_eeglab` for specific EEGLab data, by :newcontrib:`Emrecan Çelik`. (`#13395 `__) +- Fix bug with :func:`mne.make_forward_solution` where sources were not checked to make sure they're inside the inner skull for spherical BEMs, by `Eric Larson`_. (`#13407 `__) +- Preserve event-to-epoch mapping when exporting EEGLAB .set files by `Scott Huberty`_ (`#13428 `__) +- Fix and update osf.io links to new format, by :newcontrib:`Johannes Herforth`. (`#13440 `__) +- Fix bug with :func:`mne.add_reference_channels` not working correctly when passing more than one channel name, by `Michael Straube`_. (`#13466 `__) +- Correctly set the calibration factor in Nihon Kohden reader (which affects channel amplitudes), by `Tom Ma`_. (`#13468 `__) +- Make :func:`mne.preprocessing.eyetracking.read_eyelink_calibration` robust to files with blank lines, by `Scott Huberty`_. (`#13469 `__) +- Fix bug with :func:`mne.viz.plot_topomap` that caused unexpected channel name plotting when using a mask, by `Michael Straube`_. (`#13470 `__) +- Fix bug with :func:`mne.preprocessing.ICA.apply` not working when the ICA instance was fitted including marked bad channels, by `Michael Straube`_. (`#13478 `__) +- Fix bug with :func:`mne.viz.plot_evoked` when using ``gfp="only"`` or ``gfp=True``, by `Michael Straube`_. (`#13481 `__) +- Improved error message when non-finite values (NaN/Inf) are detected in calls to + :meth:`inst.compute_psd(method="welch") ` or + :meth:`ICA.fit() `, by :newcontrib:`Emma Zhang`. (`#13486 `__) +- Fix bug where :meth:`mne.channels.DigMontage.plot` would error when ``axes`` was passed by `Christian O'Reilly`_. (`#13494 `__) +- Fixed a bug where ``mne.io.read_raw_gdf`` failed with NumPy ≥1.24 due to the removal of ``np.fromstring`` binary mode. Replaced with ``np.frombuffer`` for compatibility, by :newcontrib:`Dev Parikh`. (`#13497 `__) + + +API changes by deprecation +-------------------------- + +- Add ``on_few_samples`` parameter to :func:`mne.compute_covariance` and :func:`mne.compute_raw_covariance` for controlling behavior when there are fewer samples than channels, which can lead to inaccurate covariance estimates, by :newcontrib:`Emmanuel Ferdman`. (`#13350 `__) +- The default for :func:`mne.make_field_map` will change to ``"auto"`` in MNE-Python 1.12 (from ``(0., 0., 0.04)``), changes by :newcontrib:`Paul Anders`. (`#13398 `__) +- Add ``encoding`` parameter to :func:`mne.io.read_raw_nihon` for better handling of annotation decoding, by `Tom Ma`_. (`#13458 `__) + + +New features +------------ + +- Support for preloading=False when reading .set files, by `Bruno Aristimunha`_. (`#13096 `__) +- Added support for file like objects in :func:`read_raw_bdf `, :func:`read_raw_edf ` and :func:`read_raw_gdf `, by :newcontrib:`Santi Martínez`. (`#13156 `__) +- Read impedances and montage from Neuroscan Curry files, by `Dominik Welke`_. (`#13176 `__) +- Implement GEDTransformer superclass that generalizes + :class:`mne.decoding.CSP`, :class:`mne.decoding.SPoC`, :class:`mne.decoding.XdawnTransformer`, + :class:`mne.decoding.SSD` and fix related bugs and inconsistencies, by `Gennadiy Belonosov`_. (`#13259 `__) +- Added ``on_inside="raise"`` parameter to :func:`mne.make_forward_solution` and :func:`mne.make_forward_dipole` to control behavior when MEG sensors are inside the outer skin surface. This is useful for forward solutions that are computed with sensors just inside the outer skin surface (e.g., with some OPM coregistrations), by `Eric Larson`_. (`#13307 `__) +- Implement :class:`mne.decoding.SpatialFilter` class returned by :func:`mne.decoding.get_spatial_filter_from_estimator` for + visualisation of filters and patterns for :class:`mne.decoding.LinearModel` + and additionally eigenvalues for GED-based transformers such as + :class:`mne.decoding.XdawnTransformer`, :class:`mne.decoding.CSP`, by `Gennadiy Belonosov`_. (`#13332 `__) +- Add more options for the ``sphere`` parameter of :func:`mne.viz.plot_sensors`, by `Marijn van Vliet`_ (`#13400 `__) +- Add support for BDF export in :func:`mne.export.export_raw`, by `Clemens Brunner`_ (`#13435 `__) +- Improve precision of fiducial clicking in ``mne coreg``, by `Eric Larson`_. (`#13445 `__) +- Add support for Nihon Kohden EEG-1200A V01.00, by `Eric Larson`_. (`#13448 `__) +- The ``rename_channels`` method now has an ``on_missing`` parameter to control behavior on channel mismatch, by `Stefan Appelhoff`_. (`#13456 `__) +- Added the ``annotation_regex`` parameter to :func:`mne.viz.plot_raw` and :func:`mne.viz.plot_ica_sources`, allowing automatic hiding of annotations that do not match the specified regular expression. The same functionality is available via :meth:`mne.io.Raw.plot` and :meth:`mne.preprocessing.ICA.plot_sources`. Contributed by `Johannes Herforth`_. (`#13460 `__) +- The ``combine_channels`` method now has an ``on_missing`` parameter to control behavior on missing event ids, by :newcontrib:`Michael Straube`. (`#13463 `__) +- Add ability to refit HPI order and device-to-head transform via :func:`mne.chpi.refit_hpi` and compute distances between transforms with :func:`mne.transforms.angle_distance_between_rigid` by `Eric Larson`_. (`#13484 `__) +- Added :meth:`mne.Info.to_json_dict` and :meth:`mne.Info.from_json_dict` methods to enable JSON serialization and deserialization of :class:`mne.Info` objects, preserving all data types including numpy arrays, datetime objects, and special MNE types, by `Bruno Aristimunha`_. (`#13489 `__) +- Added support for parsing Eyelink ``BUTTON`` events (i.e. external controller button presses) to :func:`~mne.io.read_raw_eyelink` by :newcontrib:`Wouter Kroot` (`#13499 `__) + + +Other changes +------------- + +- Changed "enhancement" to "new feature" in the contributing guide as enhancement is not a recognized change type, by `Shristi Baral`_ (`#13373 `__) +- Add a SPEC0-like policy in which minimum-supported versions for select dependencies are set to the latest minor release that was available 2 years prior, by `Thomas Binns`_ (`#13451 `__) +- Removed development dependencies from user-visible "extras"; they're now dependency + groups only visible to developers (and can be installed for example via + ``pip install --group dev`` with pip version 25.1 or later), by `Richard Höchenberger`_ (`#13452 `__) + +Authors +------- +* Beige Jerry Jin+ +* Bruno Aristimunha +* Christian O'Reilly +* Christodoulos Kechris +* Clemens Brunner +* Daniel McCloy +* Dev Parikh+ +* Dominik Welke +* Emma Zhang+ +* Emmanuel Ferdman+ +* Emrecan Çelik+ +* Eric Larson +* Gennadiy Belonosov +* Johannes Herforth+ +* Marijn van Vliet +* Michael Straube+ +* Paul Anders+ +* Richard Höchenberger +* Santi Martínez+ +* Scott Huberty +* Shristi Baral +* Stefan Appelhoff +* Tharupahan Jayawardana* +* Thomas S. Binns +* Tom Ma +* Wouter Kroot+ +* Young Truong diff --git a/mne-python/source/doc/changes/v1.2.rst b/mne-python/source/doc/changes/v1.2.rst new file mode 100644 index 0000000000000000000000000000000000000000..e292b472b0383e947f4c0687b9bf530ac153deb3 --- /dev/null +++ b/mne-python/source/doc/changes/v1.2.rst @@ -0,0 +1,116 @@ +.. _changes_1_2_0: + +Version 1.2.0 (2022-10-11) +-------------------------- + +Enhancements +~~~~~~~~~~~~ +- Add ``vmin`` and ``vmax`` parameters to :meth:`mne.Evoked.animate_topomap` (:gh:`11073` by :newcontrib:`Mats van Es`) +- Enable common average reference projection for ECoG, sEEG, and DBS data (optionally jointly with ``joint=True``) in :meth:`~mne.io.Raw.set_eeg_reference` and related functions/methods (:gh:`10656` by :newcontrib:`Moritz Gerster` and `Eric Larson`_) +- The ``trans`` parameter in :func:`mne.make_field_map` now accepts a :class:`~pathlib.Path` object, and uses standardised loading logic (:gh:`10784` by :newcontrib:`Andrew Quinn`) +- Add support for computing forward solutions using OpenMEEG_ (:gh:`11011` by `Alex Gramfort`_ and `Eric Larson`_) +- EEGLAB files (saved as MAT versions less than v7.3) can now be imported with :func:`mne.io.read_raw_eeglab` without the optional dependency ``pymatreader`` (:gh:`11006` by `Clemens Brunner`_) +- Add eight source estimate comparison metrics to new submodule :mod:`mne.simulation.metrics` (:gh:`6233` by `Kostiantyn Maksymenko`_ and `Alex Gramfort`_) +- Add :func:`mne.time_frequency.csd_tfr` to compute cross-spectral density from :class:`mne.time_frequency.EpochsTFR` (:gh:`10986` by `Alex Rockhill`_) +- Improve ``repr()`` for :class:`mne.minimum_norm.InverseOperator` when loose orientation is used (:gh:`11048` by `Eric Larson`_) +- Add support for vector and volume source estimates in :func:`mne.minimum_norm.get_point_spread` and :func:`mne.minimum_norm.get_cross_talk` (:gh:`8639`, :gh:`11083` by `Olaf Hauk`_, `Marijn van Vliet`_, `Alex Gramfort`_, and `Eric Larson`_) +- :meth:`mne.Epochs.plot_psd_topomap` now suppresses redundant colorbars when ``vlim='joint'`` (:gh:`11051` by `Daniel McCloy`_) +- Add ``starting_affine`` keyword argument to :func:`mne.transforms.compute_volume_registration` to initialize an alignment with an affine (:gh:`11020` by `Alex Rockhill`_) +- Add HTML representation for `~mne.Evoked` in Jupyter Notebooks (:gh:`11075` by `Valerii Chirkov`_ and `Andrew Quinn`_) +- Add support for ``temperature`` and ``gsr`` (galvanic skin response, i.e., electrodermal activity) channel types (:gh:`11090`, :gh:`11108` by `Eric Larson`_ and `Richard Höchenberger`_) +- Allow :func:`mne.beamformer.make_dics` to take ``pick_ori='vector'`` to compute vector source estimates (:gh:`10980` by `Alex Rockhill`_) +- Add ``units`` parameter to :func:`mne.io.read_raw_edf` in case units are missing from the file (:gh:`11099` by `Alex Gramfort`_) +- Add ``on_missing`` functionality to all of our classes that have a ``drop_channels`` method, to control what happens when channel names are not in the object (:gh:`11077` by `Andrew Quinn`_) +- Improve interpolation of bridged electrodes with `~mne.preprocessing.interpolate_bridged_electrodes` (:gh:`11094` by `Mathieu Scheltienne`_) +- Add :func:`mne.minimum_norm.apply_inverse_tfr_epochs` to apply inverse methods to time-frequency resolved epochs (:gh:`11095` by `Alex Rockhill`_) +- Add support for multiple probes via multiple CSV files passed to :func:`mne.io.read_raw_hitachi` (:gh:`11186` by `Eric Larson`_) +- Add :func:`mne.chpi.get_active_chpi` to retrieve the number of active hpi coils for each time point (:gh:`11122` by `Eduard Ort`_) +- Add example of how to obtain time-frequency decomposition using narrow bandpass Hilbert transforms to :ref:`ex-tfr-comparison` (:gh:`11116` by `Alex Rockhill`_) +- Add ``==`` and ``!=`` comparison between `mne.Projection` objects (:gh:`11147` by `Mathieu Scheltienne`_) +- Parse automatically temperature channel with :func:`mne.io.read_raw_edf` (:gh:`11150` by `Eric Larson`_ and `Alex Gramfort`_) +- Add ``unscale`` option to :func:`mne.head_to_mri` to facilitate working with surrogate MRI data (:gh:`11185` by `Eric Larson`_) +- Add ``encoding`` parameter to :func:`mne.io.read_raw_edf` and :func:`mne.io.read_raw_bdf` to support custom (non-UTF8) annotation channel encodings (:gh:`11154` by `Clemens Brunner`_) +- :class:`mne.preprocessing.ICA` gained a new method, :meth:`~mne.preprocessing.ICA.get_explained_variance_ratio`, that allows the retrieval of the proportion of variance explained by ICA components (:gh:`11141` by `Richard Höchenberger`_) +- Add ``on_baseline`` to :meth:`mne.preprocessing.ICA.apply`, :meth:`mne.preprocessing.ICA.plot_overlay`, and :func:`mne.viz.plot_ica_overlay` to allow reapplying baseline correction after applying ICA (:gh:`11232` by `Eric Larson`_) +- Add config option ``MNE_REPR_HTML`` to disable HTML repr in notebook environments (:gh:`11159` by `Clemens Brunner`_) + +Bugs +~~~~ +- Fix bug in :meth:`mne.io.Raw.crop` where argument ``include_tmax`` was not considered in checking ``tmax`` in bounds (:gh:`11196` by `Lukas Gemein`_) +- Fix bug in :func:`mne.io.read_raw_eeglab` where unlabeled fiducials caused reading errors (:gh:`11074` by :newcontrib:`Sebastiaan Mathot`) +- Fix bug in :func:`mne.time_frequency.read_csd` that returned ``projs`` as a list of dict instead of :class:`mne.Projection` (:gh:`11072` by :newcontrib:`Chetan Gohil`) +- Fix bug in :func:`mne.decoding.TimeFrequency` that prevented cloning if constructor arguments were modified (:gh:`11004` by :newcontrib:`Daniel Carlström Schad`) +- Fix bug in ``repr`` of decoding estimator classes (e.g., :class:`mne.decoding.SlidingEstimator`) where the parameters where not stored in the result string but instead just printed to ``sys.stdout`` (:gh:`11190` by :newcontrib:`Dominik Wetzel`) +- Document ``height`` and ``weight`` keys of ``subject_info`` entry in :class:`mne.Info` (:gh:`11019` by :newcontrib:`Sena Er`) +- Fix bug in :class:`mne.viz.Brain` constructor where the first argument was named ``subject_id`` instead of ``subject`` (:gh:`11049` by `Eric Larson`_) +- Fix bug in :ref:`mne coreg` where the MEG helmet position was not updated during ICP fitting (:gh:`11084` by `Eric Larson`_) +- Fix bug in :func:`~mne.io.read_raw_curry`, and :func:`~mne.io.read_raw_cnt` where digitization points were not read properly (:gh:`11145` by `Eric Larson`_) +- Fix bug in :func:`mne.minimum_norm.apply_inverse_epochs` where the average EEG projector was not checked properly (:gh:`11182` by `Eric Larson`_) +- Fix bug in :func:`mne.viz.plot_filter` when plotting filters created using ``output='ba'`` mode with ``compensation`` turned on. (:gh:`11040` by `Marian Dovgialo`_) +- Fix bugs in documentation of surface :class:`~mne.SourceSpaces` (:gh:`11171` by `Eric Larson`_) +- Fix bug in :func:`mne.viz.plot_compare_evokeds` where automatic legend labels could be excessively long; they are now abbreviated with ``...`` when necessary (:gh:`11181` by `Eric Larson`_) +- Fix bugs with ``verbose='error'`` not being used properly and allowing warnings through (:gh:`11193` by `Eric Larson`_) +- Fix bug in :func:`mne.io.read_raw_bti` where EEG, EMG, and H/VEOG channels were not detected properly, and many non-ECG channels were called ECG. The logic has been improved, and any channels of unknown type are now labeled as ``misc`` (:gh:`11102` by `Eric Larson`_) +- Fix bug in :func:`mne.viz.plot_topomap` when providing ``sphere="eeglab"`` (:gh:`11081` by `Mathieu Scheltienne`_) +- Fix bug in :meth:`mne.Dipole.to_mri` where MRI RAS rather than MRI surface RAS was returned (:gh:`11185` by `Eric Larson`_) +- Fix bug in :meth:`epochs.save ` where the ``verbose`` parameter defaulted to ``True`` instead of ``None`` (:gh:`11191` by `Eric Larson`_) +- The string and HTML representation of :class:`mne.preprocessing.ICA` reported incorrect values for the explained variance. This information has been removed from the representations, and should instead be retrieved via the new :meth:`~mne.preprocessing.ICA.get_explained_variance_ratio` method (:gh:`11141` by `Richard Höchenberger`_) +- Fix bug in :meth:`mne.Evoked.plot` and related methods where a ``np.nan`` location value in any channel causes spatial colours to fail (:gh:`6870` by `Simeon Wong`_) +- Fix bug in :meth:`mne.preprocessing.ICA.find_bads_muscle` where epochs caused an error when passed as the ``inst`` (:gh:`11197` by `Alex Rockhill`_) +- Fix bug in readers where EEG coordinates were assumed to be in head coordinates but no fiducial points were present. Estimated fiducial locations will now be added automatically to reflect the assumption of locations being in the head coordinate frame (:gh:`11212` by `Stefan Appelhoff`_ and `Eric Larson`_) +- The duration of raw data sometimes wasn't displayed correctly in Jupyter notebooks by omitting fractions of a second. We now always round up to the next full second so a duration of less than 1 second will not be displayed as a duration of zero anymore (:gh:`11203` by `Richard Höchenberger`_) +- Fix bug in :meth:`mne.Report.add_ica` and where baselines were not reapplied to the data when ``inst`` is Epochs or Evoked (:gh:`11232` by `Eric Larson`_) + +API changes +~~~~~~~~~~~ +- In :meth:`mne.Evoked.plot`, the default value of the ``spatial_colors`` parameter has been changed to ``'auto'``, which will use spatial colors if channel locations are available (:gh:`11201` by :newcontrib:`Hüseyin Orkun Elmas` and `Daniel McCloy`_) +- Starting with this release we now follow the Python convention of using ``FutureWarning`` instead of ``DeprecationWarning`` to signal user-facing changes to our API (:gh:`11120` by `Daniel McCloy`_) +- The ``names`` parameter of :func:`mne.viz.plot_arrowmap` and :func:`mne.viz.plot_regression_weights` has been deprecated; sensor names will be automatically drawn from the ``info_from`` or ``model`` parameter (respectively), and can be hidden, shown, or altered via the ``show_names`` parameter (:gh:`11123` by `Daniel McCloy`_) +- The ``bands`` parameter of :meth:`mne.Epochs.plot_psd_topomap` now accepts :class:`dict` input; legacy :class:`tuple` input is supported, but discouraged for new code (:gh:`11050` by `Daniel McCloy`_) +- The :func:`mne.head_to_mri` new function parameter ``kind`` default will change from ``'ras'`` to ``'mri'`` (:gh:`11185` by `Eric Larson`_) +- The ``show_toolbar`` argument to :class:`mne.viz.Brain` is being removed by deprecation (:gh:`11049` by `Eric Larson`_) +- New classes :class:`~mne.time_frequency.Spectrum` and :class:`~mne.time_frequency.EpochsSpectrum`, created via new methods :meth:`Raw.compute_psd()`, :meth:`Epochs.compute_psd()`, and :meth:`Evoked.compute_psd()` (:gh:`10184` by `Daniel McCloy`_) +- Functions/methods for plotting topomaps now have more consistent signatures; most have gained parameters for finer control of the topomap image and/or colorbar. See docstrings for details (:gh:`11123` by `Daniel McCloy`_) +- In :func:`mne.viz.plot_topomap`, passing ``axes=None`` will now create a new :class:`~matplotlib.figure.Figure` instead of plotting into the current axes (:gh:`11123` by `Daniel McCloy`_) +- In :func:`mne.viz.plot_topomap`, the parameter ``show_names`` has been deprecated, use the ``names`` parameter instead (:gh:`11123` by `Daniel McCloy`_) +- In :func:`mne.viz.plot_topomap`, :func:`~mne.viz.plot_tfr_topomap`, :func:`~mne.viz.plot_evoked_topomap`, and related class methods :meth:`mne.Covariance.plot_topomap`, :meth:`mne.Evoked.plot_topomap`, and :meth:`mne.time_frequency.AverageTFR.plot_topomap`: the parameters ``vmin`` and ``vmax`` are deprecated in favor of ``vlim``, for consistency with other ``plot_topomap`` functions and methods (:gh:`11123` by `Daniel McCloy`_) +- In :func:`mne.viz.plot_tfr_topomap`, :func:`~mne.viz.plot_evoked_topomap`, and related class methods :meth:`mne.Covariance.plot_topomap`, :meth:`mne.Evoked.plot_topomap`, and :meth:`mne.time_frequency.AverageTFR.plot_topomap`: the ``title`` parameter has been deprecated; use matplotlib's :meth:`fig.suptitle()` instead (:gh:`11123` by `Daniel McCloy`_) +- In functions/methods for plotting topomaps, the ``outlines='skirt'`` option is deprecated; use ``sphere='eeglab'`` for similar functionality (:gh:`11123` by `Daniel McCloy`_) +- The ``mne.epochs.add_channels_epochs`` function has been deprecated in favor of :meth:`epochs.add_channels ` (:gh:`11180` by `Eric Larson`_) +- The PSD functions that operate on Raw/Epochs/Evoked instances (``mne.time_frequency.psd_welch`` and ``mne.time_frequency.psd_multitaper``) are deprecated; for equivalent functionality create :class:`~mne.time_frequency.Spectrum` or :class:`~mne.time_frequency.EpochsSpectrum` objects instead and then run ``spectrum.get_data(return_freqs=True)`` (:gh:`10184` by `Daniel McCloy`_) +- Added new class :class:`mne.preprocessing.EOGRegression` to allow more flexibility when using regression to reduce EOG artifacts (:gh:`11046` by `Marijn van Vliet`_) +- New parameter ``exclude`` added to :func:`mne.preprocessing.regress_artifact` to prevent regression from being applied to certain channels (:gh:`11046` by `Marijn van Vliet`_) + +Authors +~~~~~~~ + +* Alex Rockhill +* Alexandre Gramfort +* Andrew Quinn+ +* Chetan Gohil+ +* Christian Brodbeck +* Clemens Brunner +* Daniel Carlström Schad+ +* Daniel McCloy +* Dominik Wetzel+ +* Eduard Ort +* Eric Larson +* Hüseyin Orkun Elmas+ +* Jack Zhang +* Joan Massich +* Julius Welzel+ +* Kostiantyn Maksymenko +* Lukas Gemein +* Marian Dovgialo +* Marijn van Vliet +* Mathieu Scheltienne +* Mats van Es+ +* Moritz Gerster+ +* Olaf Hauk +* Richard Höchenberger +* Sebastiaan Mathot+ +* Sena Er+ +* Simeon Wong +* Stefan Appelhoff +* Valerii Chirkov +* luzpaz+ diff --git a/mne-python/source/doc/changes/v1.3.rst b/mne-python/source/doc/changes/v1.3.rst new file mode 100644 index 0000000000000000000000000000000000000000..d5923e12aa9acdc4188684d9baf6bec9b5b6106e --- /dev/null +++ b/mne-python/source/doc/changes/v1.3.rst @@ -0,0 +1,89 @@ +.. _changes_1_3_0: + +Version 1.3.0 (2022-12-21) +-------------------------- + +Enhancements +~~~~~~~~~~~~ +- Improve default line width used in :func:`mne.viz.plot_filter` (:gh:`11333` by :newcontrib:`Toomas Erik Anijärv`) +- Add the argument ``max_iter`` to :func:`~mne.time_frequency.psd_array_multitaper` and to :func:`~mne.time_frequency.csd_array_multitaper` to increase the maximum number of iterations to reach convergence when using ``adaptive=True`` (:gh:`11237` by `Mathieu Scheltienne`_) +- Add a warning to the docstring of :func:`mne.channels.find_ch_adjacency` to encourage users to validate their outputs (:gh:`11236` by `Felix Klotzsche`_ and `Eric Larson`_) +- Mixed, cortical + discrete source spaces with fixed orientations are now allowed. (:gh:`11241` by `Jevri Hanna`_) +- Add size information to the ``repr`` of :class:`mne.Report` (:gh:`11357` by `Eric Larson`_) +- Add support for ``image_format='webp'`` to :class:`mne.Report` when using Matplotlib 3.6+, which can reduce file sizes by up to 50% compared to ``'png'``. The new default ``image_format='auto'`` will automatically use this format if it's available on the system (:gh:`11359` by `Eric Larson`_) +- Add :func:`mne.beamformer.apply_dics_tfr_epochs` to apply a DICS beamformer to time-frequency resolved epochs (:gh:`11096` by `Alex Rockhill`_) +- Add :func:`mne.time_frequency.fwhm` to determine the full-width half maximum for :func:`mne.time_frequency.morlet` (:gh:`11353` by `Britta Westner`_, `Daniel McCloy`_, and `Eric Larson`_) +- Check whether head radius (estimated from channel positions) is correct when reading EEGLAB data with :func:`~mne.io.read_raw_eeglab` and :func:`~mne.read_epochs_eeglab`. If head radius is not within likely values, warn informing about possible units mismatch and the new ``montage_units`` argument (:gh:`11283` by `Mikołaj Magnuski`_). +- Add support for a callable passed in ``combine`` for `mne.time_frequency.AverageTFR.plot` and `mne.time_frequency.AverageTFR.plot_joint` (:gh:`11329` by `Mathieu Scheltienne`_) + +Bugs +~~~~ +- Fix bug in :func:`mne.export.export_raw` when exporting raw to EDF with EDFLib when subject ``sex`` is missing (:gh:`11375` by :newcontrib:`Mark Alexander Henney`) +- Fix bugs in documentation of :func:`mne.time_frequency.tfr_array_multitaper` and related functions/methods (:gh:`11310` by :newcontrib:`Santeri Ruuskanen`) +- Fix bug to be able to customize legends when using :meth:`mne.viz.Brain.add_volume_labels` (:gh:`11289` by :newcontrib:`Mauricio Cespedes Tenorio`) +- Fix bug in documentation of :func:`mne.channels.make_dig_montage` (:gh:`11235` by :newcontrib:`Daniel Hasegan`) +- Add support for bad channel handling in :func:`mne.set_bipolar_reference` (:gh:`11245` by `Moritz Gerster`_, :newcontrib:`Dinara Issagaliyeva`, :newcontrib:`Jennifer Behnke`, :newcontrib:`Hakimeh Aslsardroud`, and :newcontrib:`Pavel Navratil`) +- Fix X coordinates of ear_left and ear_right in head outlines dict (:gh:`11255` by :newcontrib:`Tom Ma`) +- Add type checking for ``tmin`` and ``tmax`` arguments for ``crop`` (:gh:`11263` by :newcontrib:`Carlos de la Torre-Ortiz`). +- Fix bug where trying to setup projection without an EEG average reference projector would fail (:gh:`11351` by :newcontrib:`Enzo Altamiranda`) +- Fix bug where ``ica.reject_`` was not saved to disk, and the ``ica.reject_`` property was not inherited from ``Epochs`` when doing ``ICA.fit(epochs)`` (:gh:`11244` by `Eric Larson`_) +- Fix bug in automatic MESA detection for disabling advanced 3D options (:gh:`11271` by `Eric Larson`_) +- Fix bug in :func:`mne.head_to_mri` when ``unscale=True`` (:gh:`11303` by `Eric Larson`_) +- Fix bug in :meth:`set_montage('mgh60') ` and related functions where the ``'mgh60'`` sensor positions were incorrectly ordered (:gh:`11290` by `Eric Larson`_) +- Fix bug in the ``.compute_psd()`` methods where the number of unaggregated Welch segments was wrongly computed for some inputs, leading to an assertion error when computing the PSD (:gh:`11248` by `Daniel McCloy`_) +- Fix bug in the :func:`~mne.viz.plot_evoked_topo` and :meth:`~mne.Evoked.plot_topo`, where legend colors where shown incorrectly on newer matplotlib versions (:gh:`11258` by `Erkka Heinila`_) +- Fix bug where EEGLAB channel positions were read as meters, while they are commonly in millimeters, leading to head outlies of the size of one channel when plotting topomaps. Now ``montage_units`` argument has been added to :func:`~mne.io.read_raw_eeglab` and :func:`~mne.read_epochs_eeglab` to control in what units EEGLAB channel positions are read. The default is millimeters, ``'mm'`` (:gh:`11283` by `Mikołaj Magnuski`_) +- Fix bug where computing PSD with welch's method with more jobs than channels would fail (:gh:`11298` by `Mathieu Scheltienne`_) +- Fix bug where the default FFT length changed for spectrum plots (:gh:`11345` by `Daniel McCloy`_) +- Fix bug with :func:`mne.decoding.cross_val_multiscore` where progress bars were not displayed correctly (:gh:`11311` by `Eric Larson`_) +- Fix channel selection edge-cases in `~mne.preprocessing.ICA.find_bads_muscle` (:gh:`11300` by `Mathieu Scheltienne`_) +- Fix bug with :func:`mne.io.read_raw_curry` where a dot in the parent folders prevented files from being read (:gh:`11340` by `Eric Larson`_) +- Fix bug with :class:`mne.Report` with ``replace=True`` where the wrong content was replaced and ``section`` was not respected (:gh:`11318`, :gh:`11346` by `Eric Larson`_) +- Fix bug with unit conversion when setting reference MEG as the channel type in :meth:`mne.io.Raw.set_channel_types` and related methods (:gh:`11344` by `Eric Larson`_) +- Fix bug where reference MEG channels could not be plotted using :func:`mne.viz.plot_epochs_image` (:gh:`11344` by `Eric Larson`_) +- Fix bug where ``image_format='gif'`` was errantly documented as being supported by :class:`mne.Report`, it is now only supported in :meth:`mne.Report.add_image` (:gh:`11347` by `Eric Larson`_) +- Multitaper spectral estimation now uses periodic (rather than symmetric) taper windows. This also necessitated changing the default ``max_iter`` of our cross-spectral density functions from 150 to 250. (:gh:`11293` by `Daniel McCloy`_) +- Fix :meth:`mne.Epochs.plot_image` and :func:`mne.viz.plot_epochs_image` when using EMG signals (:gh:`11322` by `Alex Gramfort`_) +- Fix selection of ICA components in :func:`mne.viz.plot_ica_components` and :meth:`mne.preprocessing.ICA.plot_components` (:gh:`11369` by `Mathieu Scheltienne`_) +- Fix bug where a Freesurfer reconstruction run with both a T1 and a T2 caused :class:`mne.viz.Brain` not to initialize pial surfaces properly (:gh:`11361` by `Alex Rockhill`_) + +API changes +~~~~~~~~~~~ +- In :func:`mne.time_frequency.dpss_windows`, interpolating is deprecated (nowadays SciPy's computations are fast enough for large ``N`` without interpolation). This affects parameters ``interp_from`` and ``interp_kind``. Two new parameters of the underlying SciPy :func:`~scipy.signal.windows.dpss` function are also exposed: ``sym`` (for choosing symmetric vs. periodic windows) and ``norm`` (window normalization method). (:gh:`11293` by `Daniel McCloy`_) +- In :meth:`mne.decoding.CSP.plot_patterns`, :meth:`mne.decoding.CSP.plot_filters`, :meth:`mne.preprocessing.ICA.plot_components`, and :func:`mne.viz.plot_ica_components`, the parameters ``vmin`` and ``vmax`` are deprecated in favor of ``vlim``, for consistency with other topomap-plotting functions and methods (:gh:`11371` by `Daniel McCloy`_) +- In :meth:`mne.decoding.CSP.plot_patterns` and :meth:`mne.decoding.CSP.plot_filters` the ``title`` parameter is deprecated and will be removed in version 1.4 (:gh:`11371` by `Daniel McCloy`_) +- The APIs of :meth:`mne.preprocessing.ICA.plot_components` and :func:`mne.viz.plot_ica_components` gained new parameters ``show_names``, ``extrapolate``, ``border``, ``size``, ``cnorm``, ``cbar_fmt``, ``axes``, ``nrows``, ``ncols``, for consistency with other topomap-plotting functions and methods (:gh:`11371` by `Daniel McCloy`_) +- The APIs of :meth:`mne.decoding.CSP.plot_patterns` and :meth:`mne.decoding.CSP.plot_filters` gained new parameters ``extrapolate``, ``border``, ``cnorm``, ``axes``, ``nrows``, ``ncols``, for consistency with other topomap-plotting functions and methods (:gh:`11371` by `Daniel McCloy`_) + +Authors +~~~~~~~ + +* Alex Rockhill +* Alexandre Gramfort +* Britta Westner +* Carlos de la Torre+ +* Daniel Hasegan+ +* Daniel McCloy +* Dinara Issagaliyeva+ +* Enzo Altamiranda+ +* Eric Brayet+ +* Eric Larson +* Erkka Heinila +* Felix Klotzsche +* Hakimeh Aslsardroud+ +* Jennifer Behnke+ +* Jevri Hanna +* Lukas Hecker +* Mark Alexander Henney+ +* Mathieu Scheltienne +* Mauricio Cespedes+ +* Mikołaj Magnuski +* Moritz Gerster +* Omer Shubi+ +* Pavel Navratil+ +* Richard Höchenberger +* Santeri Ruuskanen+ +* Stefan Appelhoff +* Timon Merk +* Tom Ma+ +* Toomas Erik Anijärv+ diff --git a/mne-python/source/doc/changes/v1.4.rst b/mne-python/source/doc/changes/v1.4.rst new file mode 100644 index 0000000000000000000000000000000000000000..2fa9ec2a0d1f36e88a91416ad6252e1dce5cf4ab --- /dev/null +++ b/mne-python/source/doc/changes/v1.4.rst @@ -0,0 +1,133 @@ +.. _changes_1_4_0: + +Version 1.4.0 (2023-05-10) +-------------------------- + +Enhancements +~~~~~~~~~~~~ +- Add functionality for reading CNT spans/annotations marked bad to :func:`mne.io.read_raw_cnt` (:gh:`11631` by :newcontrib:`Jacob Woessner`) +- Add ``:unit:`` Sphinx directive to enable use of uniform non-breaking spaces throughout the documentation (:gh:`11469` by :newcontrib:`Sawradip Saha`) +- Adjusted the algorithm used in :class:`mne.decoding.SSD` to support non-full rank data (:gh:`11458` by :newcontrib:`Thomas Binns`) +- Changed suggested type for ``ch_groups`` in `mne.viz.plot_sensors` from array to list of list(s) (arrays are still supported). (:gh:`11465` by `Hyonyoung Shin`_) +- Add support for UCL/FIL OPM data using :func:`mne.io.read_raw_fil` (:gh:`11366` by :newcontrib:`George O'Neill` and `Robert Seymour`_) +- Add harmonic field correction (HFC) for OPM sensors in :func:`mne.preprocessing.compute_proj_hfc` (:gh:`11536` by :newcontrib:`George O'Neill` and `Eric Larson`_) +- Forward argument ``axes`` from `mne.viz.plot_sensors` to `mne.channels.DigMontage.plot` (:gh:`11470` by :newcontrib:`Jan Ebert` and `Mathieu Scheltienne`_) +- Add forward IIR filtering, using parameters ``method='iir', phase='forward'`` (:gh:`11078` by :newcontrib:`Quentin Barthélemy`) +- Added ability to read stimulus durations from SNIRF files when using :func:`mne.io.read_raw_snirf` (:gh:`11397` by `Robert Luke`_) +- Add :meth:`mne.Info.save` to save an :class:`mne.Info` object to a fif file (:gh:`11401` by `Alex Rockhill`_) +- Improved error message when downloads are corrupted for :func:`mne.datasets.sample.data_path` and related functions (:gh:`11407` by `Eric Larson`_) +- Improved :func:`mne.get_config("") ` behavior to return a dict of key-value pairs (config key and its description) rather than just a tuple of config keys (:gh:`11166` by `Clemens Brunner`_, `Daniel McCloy`_, and `Eric Larson`_) +- Add support for ``skip_by_annotation`` in :func:`mne.io.Raw.notch_filter` (:gh:`11388` by `Mainak Jas`_) +- Add support for ``output='complex'`` to :func:`mne.time_frequency.psd_array_welch` and when using ``method='welch'`` with :meth:`mne.Epochs.compute_psd` (:gh:`11556` by `Eric Larson`_) +- Slightly adjusted the window title for :func:`mne.Epochs.plot` (:gh:`11419` by `Richard Höchenberger`_ and `Daniel McCloy`_) +- Add :func:`mne.count_events` to count unique event types in a given event array (:gh:`11430` by `Clemens Brunner`_) +- Add a video to :ref:`tut-freesurfer-mne` of a brain inflating from the pial surface to aid in understanding the inflated brain (:gh:`11440` by `Alex Rockhill`_) +- Add automatic projection of sEEG contact onto the inflated surface for :meth:`mne.viz.Brain.add_sensors` (:gh:`11436` by `Alex Rockhill`_) +- Allow an image with intracranial electrode contacts (e.g. computed tomography) to be used without the freesurfer recon-all surfaces to locate contacts so that it doesn't have to be downsampled to freesurfer dimensions (for microelectrodes) and show an example :ref:`ex-ieeg-micro` with :func:`mne.transforms.apply_volume_registration_points` added to aid this transform (:gh:`11567` by `Alex Rockhill`_) +- Use new :meth:`dipy.align.imwarp.DiffeomorphicMap.transform_points` to transform a montage of intracranial contacts more efficiently (:gh:`11572` by `Alex Rockhill`_) +- Improve performance of raw data browsing with many annotations (:gh:`11614` by `Eric Larson`_) +- Add support for :func:`mne.preprocessing.maxwell_filter` with gradient-compensated CTF data, e.g., for tSSS-only mode (:gh:`10554` by `Eric Larson`_) +- Add support for eyetracking data using :func:`mne.io.read_raw_eyelink` (:gh:`11152` by `Dominik Welke`_ and `Scott Huberty`_) +- :func:`mne.channels.make_1020_channel_selections` gained a new parameter, ``return_ch_names``, to allow for easy retrieval of EEG channel names corresponding to the left, right, and midline portions of the montage (:gh:`11632` by `Richard Höchenberger`_) +- Methods for setting the sensor types of channels (e.g., for raw data, :meth:`mne.io.Raw.set_channel_types`) gained a new parameter, ``on_unit_change``, to control behavior (raise an exception, emit a warning, or do nothing) in case the measurement unit is adjusted automatically (:gh:`11668` by `Richard Höchenberger`_) +- :func:`mne.beamformer.trap_music` implements the TRAP-MUSIC localisation algorithm with the same signature as :func:`mne.beamformer.rap_music` (:gh:`11679` by `Théodore Papadopoulo`_) + +Bugs +~~~~ +- Improving compatibility with Qt6 by removing the use of deprecated ``AA_UseHighDpiPixmaps`` attribute for this Qt version (:gh:`11662` by :newcontrib:`Florin Pop`) +- Fix :func:`mne.time_frequency.psd_array_multitaper` docstring where argument ``bandwidth`` incorrectly reported argument as half-bandwidth and gave wrong explanation of default value (:gh:`11479` by :newcontrib:`Tom Stone`) +- Fix bug where installation of a package depending on ``mne`` will error when done in an environment where ``setuptools`` is not present (:gh:`11454` by :newcontrib:`Arne Pelzer`) +- Fix bug in :meth:`mne.Annotations.rename` where replacements were not done correctly (:gh:`11666` by :newcontrib:`Timur Sokhin` and `Eric Larson`_) +- Fix :meth:`mne.time_frequency.Spectrum.to_data_frame`'s docstring to reflect the correct name for the appended frequencies column (:gh:`11457` by :newcontrib:`Zvi Baratz`) +- Fix bug with :func:`mne.io.read_raw_egi` where events outside the recording window could break data reading (:gh:`11505` by :newcontrib:`Niels Focke`) +- Fix bug where :func:`mne.preprocessing.regress_artifact` and :class:`mne.preprocessing.EOGRegression` incorrectly tracked ``picks`` (:gh:`11366` by `Eric Larson`_) +- Fix bug where channel names were not properly sanitized in :func:`mne.write_evokeds` and related functions (:gh:`11399` by `Eric Larson`_) +- Fix bug where splash screen would not always disappear (:gh:`11398` by `Eric Larson`_) +- Fix bug where having a different combination of volumes loaded into ``freeview`` caused different affines to be returned by :func:`mne.read_lta` for the same Linear Transform Array (LTA) (:gh:`11402` by `Alex Rockhill`_) +- Fix how :class:`mne.channels.DigMontage` is set when using ``mne.gui.locate_ieeg`` so that :func:`mne.Info.get_montage` works and does not return ``None`` (:gh:`11421` by `Alex Rockhill`_) +- Fix :func:`mne.io.read_raw_edf` when reading EDF data with different sampling rates and a mix of data channels when using ``infer_types=True`` (:gh:`11427` by `Alex Gramfort`_) +- Fix how :class:`mne.channels.DigMontage` is set when using :func:`mne.preprocessing.ieeg.project_sensors_onto_brain` so that :func:`mne.Info.get_montage` works and does not return ``None`` (:gh:`11436` by `Alex Rockhill`_) +- Fix configuration folder discovery on Windows, which would fail in certain edge cases; and produce a helpful error message if discovery still fails (:gh:`11441` by `Richard Höchenberger`_) +- Make :class:`~mne.decoding.SlidingEstimator` and :class:`~mne.decoding.GeneralizingEstimator` respect the ``verbose`` argument. Now with ``verbose=False``, the progress bar is not shown during fitting, scoring, etc. (:gh:`11450` by `Mikołaj Magnuski`_) +- Fix bug with ``mne.gui.locate_ieeg`` where Freesurfer ``?h.pial.T1`` was not recognized and suppress excess logging (:gh:`11489` by `Alex Rockhill`_) +- All functions accepting paths can now correctly handle :class:`~pathlib.Path` as input. Historically, we expected strings (instead of "proper" path objects), and only added :class:`~pathlib.Path` support in a few select places, leading to inconsistent behavior. (:gh:`11473` and :gh:`11499` by `Mathieu Scheltienne`_) +- Fix visualization dialog compatibility with matplotlib 3.7 (:gh:`11409` by `Daniel McCloy`_ and `Eric Larson`_) +- Expand tilde (user directory) in config keys (:gh:`11537` by `Clemens Brunner`_) +- Fix bug in :func:`mne.preprocessing.compute_maxwell_basis` where using ``int_order=0`` would raise an error (:gh:`11562` by `Eric Larson`_) +- In the legacy function :func:`mne.viz.plot_epochs_psd_topomap`, the parameter ``names`` now works again (:gh:`11563` by `Daniel McCloy`_) +- Fix :func:`mne.io.read_raw` for file names containing multiple dots (:gh:`11521` by `Clemens Brunner`_) +- Fix bug in :func:`mne.export.export_raw` when exporting to EDF with a physical range set smaller than the data range (:gh:`11569` by `Mathieu Scheltienne`_) +- Fix bug in :func:`mne.concatenate_raws` where two raws could not be merged if the order of the bad channel lists did not match (:gh:`11502` by `Moritz Gerster`_) +- Fix bug where :meth:`mne.Evoked.plot_topomap` opened an extra figure (:gh:`11607` by `Alex Rockhill`_) +- Fix bug where :func:`mne.transforms.apply_volume_registration_points` modified info in place (:gh:`11612` by `Alex Rockhill`_) +- Fix bug where Maxwell-filtered data rank was not handled properly in :func:`mne.beamformer.make_lcmv` (:gh:`11664` by `Eric Larson`_) +- In :class:`~mne.Report`, custom figures now show up correctly when ``image_format='svg'`` is requested (:gh:`11623` by `Richard Höchenberger`_) +- Fix bug where providing ``axes`` in `mne.preprocessing.ICA.plot_components` would fail (:gh:`11654` by `Mathieu Scheltienne`_) +- Fix deprecation of ``title``, ``vmin`` and ``vmax`` in `~mne.viz.plot_tfr_topomap` called from interactive `mne.time_frequency.AverageTFR.plot_topo` (:gh:`11683` by `Mathieu Scheltienne`_) + +API changes +~~~~~~~~~~~ +- Deprecate ``mne.gui.locate_ieeg`` in favor of :func:`mne-gui-addons:mne_gui_addons.locate_ieeg` (:gh:`11616` by `Alex Rockhill`_) +- Deprecate arguments ``kind`` and ``path`` from :func:`mne.channels.read_layout` in favor of a common argument ``fname`` (:gh:`11500` by `Mathieu Scheltienne`_) +- Change ``aligned_ct`` positional argument in ``mne.gui.locate_ieeg`` to ``base_image`` to reflect that this can now be used with unaligned images (:gh:`11567` by `Alex Rockhill`_) +- ``mne.warp_montage_volume`` was deprecated in favor of :func:`mne.preprocessing.ieeg.warp_montage` (acts directly on points instead of using an intermediate volume) and :func:`mne.preprocessing.ieeg.make_montage_volume` (which makes a volume of ieeg contact locations which can still be useful) (:gh:`11572` by `Alex Rockhill`_) +- Deprecate ``mne.pick_channels_evoked`` in favor of ``evoked.copy().pick(...)`` (:gh:`11665` by `Eric Larson`_) +- Set instance methods ``inst.pick_types`` and ``inst.pick_channels`` as legacy in favor of ``inst.pick(...)`` (:gh:`11665` by `Eric Larson`_) +- The default of ``inst.pick_channels(..., ordered=False)`` will change to ``ordered=True`` in 1.5 to avoid silent bugs (:gh:`11665` by `Eric Larson`_) + +Authors +~~~~~~~ + +* Alex Rockhill +* Alexandre Gramfort +* Arne Pelzer+ +* Britta Westner +* Carlos de la Torre +* Clemens Brunner +* Daniel Hasegan +* Daniel McCloy +* Denis A. Engemann +* Dimitri Papadopoulos Orfanos +* Dinara Issagaliyeva +* Dominik Welke +* Enzo Altamiranda +* Eric Brayet +* Eric Larson +* Erkka Heinila +* Felix Klotzsche +* Florin Pop+ +* George O'Neill+ +* Giulio +* Hakimeh Aslsardroud +* Hyonyoung Shin+ +* Jacob Woessner+ +* Jan Ebert+ +* Jennifer Behnke +* Jevri Hanna +* Lukas Hecker +* Mainak Jas +* Mark Alexander Henney +* Mathieu Scheltienne +* Mauricio Cespedes +* Michiru Kaneda +* Mikołaj Magnuski +* Moritz Gerster +* Niels Focke+ +* Omer Shubi +* Pavel Navratil +* Quentin Barthélemy+ +* Richard Höchenberger +* Rob Luke +* Robert Seymour+ +* Santeri Ruuskanen +* Sawradip Saha+ +* Scott Huberty +* Stefan Appelhoff +* Theodore Papadopoulo +* Thomas Samuel Binns+ +* Timon Merk +* Timur Sokhin+ +* Tom Ma +* Tom Stone+ +* Toomas Erik Anijärv +* Zvi Baratz+ diff --git a/mne-python/source/doc/changes/v1.5.rst b/mne-python/source/doc/changes/v1.5.rst new file mode 100644 index 0000000000000000000000000000000000000000..c607aefe26db153cd5e049d578c804c503693eb8 --- /dev/null +++ b/mne-python/source/doc/changes/v1.5.rst @@ -0,0 +1,107 @@ +.. NOTE: we use cross-references to highlight new functions and classes. + Please follow the examples below like :func:`mne.stats.f_mway_rm`, so the + whats_new page will have a link to the function/class documentation. + +.. NOTE: there are 3 separate sections for changes, based on type: + - "Enhancements" for new features + - "Bugs" for bug fixes + - "API changes" for backward-incompatible changes + +.. NOTE: changes from first-time contributors should be added to the TOP of + the relevant section (Enhancements / Bugs / API changes), and should look + like this (where xxxx is the pull request number): + + - description of enhancement/bugfix/API change (:gh:`xxxx` by + :newcontrib:`Firstname Lastname`) + + Also add a corresponding entry for yourself in doc/changes/names.inc + +.. _changes_1_5_0: + +Version 1.5.0 (2023-08-14) +-------------------------- + +Enhancements +~~~~~~~~~~~~ +- Add reader for NSx files (Blackrock Microsystems Data Acquisition Systems) (:gh:`11432` by :newcontrib:`Proloy Das`) +- Add ``cmap`` argument for the :func:`mne.viz.plot_sensors` (:gh:`11720` by :newcontrib:`Gennadiy Belonosov`) +- Return unmodified instance if new sampling frequency is identical to the original in :meth:`mne.io.Raw.resample`, :meth:`mne.Epochs.resample`, :meth:`mne.Evoked.resample` and :meth:`mne.SourceEstimate.resample` (:gh:`11736` by :newcontrib:`Gennadiy Belonosov`) +- When failing to locate a file, we now print the full path in quotation marks to help spot accidentally added trailing spaces (:gh:`11718` by `Richard Höchenberger`_) +- Add standard montage lookup table for ``easycap-M43`` (:gh:`11744` by :newcontrib:`Diptyajit Das`) +- Added :class:`mne.preprocessing.eyetracking.Calibration` to store eye-tracking calibration info, and :func:`mne.preprocessing.eyetracking.read_eyelink_calibration` to read calibration data from EyeLink systems (:gh:`11719` by `Scott Huberty`_) +- Ocular :class:`mne.Annotations` read in by :func:`mne.io.read_raw_eyelink` are now channel aware. This means if the left eye blinked, the associated annotation will store this in the ``'ch_names'`` key. (:gh:`11746` by `Scott Huberty`_) +- Added :func:`mne.preprocessing.eyetracking.interpolate_blinks` to linear interpolate eyetrack signals during blink periods. (:gh:`11740` by `Scott Huberty`_) +- Added a section for combining eye-tracking and EEG data to the preprocessing tutorial "working with eye tracker data in MNE-Python" (:gh:`11770` by `Scott Huberty`_) +- Added a ``show_bytes`` option to :ref:`mne show_fiff` to show byte offsets (:gh:`11800` by `Eric Larson`_) +- Add :meth:`mne.Annotations.count` and :func:`mne.count_annotations` to count unique annotations (:gh:`11796` by `Clemens Brunner`_) +- Split the display of :meth:`mne.preprocessing.ICA.plot_overlay` between sensor types and display the RMS for MEG sensors and the :term:`GFP` for EEG sensors in the second panel instead of the channel average (:gh:`11830` by `Mathieu Scheltienne`_) +- Add :meth:`mne.Info.set_channel_types`, :meth:`mne.Info.rename_channels`, :meth:`mne.Info.plot_sensors`, :meth:`mne.Info.anonymize`, :meth:`mne.Info.set_meas_date` (:gh:`11839` by `Alex Rockhill`_) +- Curry and NEDF raw files can now also be read with the generic :func:`mne.io.read_raw` function (:gh:`11841` by `Richard Höchenberger`_) + +Bugs +~~~~ +- Fix bug in :func:`mne.bem.convert_flash_mris` to handle missing "flash5_reg.mgz" when processing "flash30" data. (:gh:`11842` by :newcontrib:`Hamza Abdelhedi`) +- Fix bug where epochs ``event_id`` was not kept by :func:`mne.channels.combine_channels` (:gh:`11786` by :newcontrib:`Samuel Louviot`) +- Fix bug where user-provided codec was not used to read annotations when loading EEGLAB ``.set`` files (:gh:`11773` by :newcontrib:`Yiping Zuo`) +- Fix bug that required curv.*h files to create Brain object (:gh:`11704` by :newcontrib:`Aaron Earle-Richardson`) +- Extended test to highlight bug in :func:`mne.stats.permutation_t_test` (:gh:`11575` by :newcontrib:`Joshua Calder-Travis`) +- Fix bug that used wrong indices for line/label styles (sometimes causing an ``IndexError``) in :meth:`mne.preprocessing.ICA.plot_sources` under certain conditions (:gh:`11808` by :newcontrib:`Joshua Calder-Travis`) +- Fix bug with :func:`~mne.io.read_raw_snirf` to handle files with measurement time containing milliseconds (:gh:`11804` by :newcontrib:`Daniel Tse`) +- Fix loading of EDF with mixed sampling frequencies with :func:`mne.io.read_raw_edf`: Upsampling is now applied to the entire signal and no longer block based, significantly reducing edge artifacts (:gh:`11549` by `Simon Kern`_) +- Fix bug where :func:`mne.io.read_raw_cnt` imports unnecessary durations (:gh:`11828` by `Jacob Woessner`_) +- Fix bug where :meth:`mne.viz.Brain.add_volume_labels` used an incorrect orientation (:gh:`11730` by `Alex Rockhill`_) +- Fix bug with :func:`mne.forward.restrict_forward_to_label` where cortical patch information was not adjusted (:gh:`11694` by `Eric Larson`_) +- Fix bug with PySide6 compatibility (:gh:`11721` by `Eric Larson`_) +- Fix bug with :class:`mne.io.Raw`, :class:`mne.SourceEstimate`, and related classes where the ``decimate`` and ``shift_time`` methods were errantly added (:gh:`11853` by `Eric Larson`_) +- Fix hanging interpreter with matplotlib figures using ``mne/viz/_mpl_figure.py`` in spyder console and jupyter notebooks (:gh:`11696` by `Mathieu Scheltienne`_) +- Fix bug with overlapping text for :meth:`mne.Evoked.plot` (:gh:`11698` by `Alex Rockhill`_) +- Fix bug with :func:`mne.preprocessing.corrmap` where the template iteration had non-standard map averaging (:gh:`11857` by `Eric Larson`_) +- For :func:`mne.io.read_raw_eyelink`, the default value of the ``gap_description`` parameter is now ``'BAD_ACQ_SKIP'``, following MNE convention (:gh:`11719` by `Scott Huberty`_) +- Fix bug with :func:`mne.io.read_raw_fil` where datasets without sensor positions would not import (:gh:`11733` by `George O'Neill`_) +- Fix bug with :func:`mne.chpi.compute_chpi_snr` where cHPI being off for part of the recording or bad channels being defined led to an error or incorrect behavior (:gh:`11754`, :gh:`11755` by `Eric Larson`_) +- Allow int-like for the argument ``id`` of `~mne.make_fixed_length_events` (:gh:`11748` by `Mathieu Scheltienne`_) +- Fix bugs with :mod:`mne.decoding` classes (:gh:`11846` by `Eric Larson`_): + - :class:`mne.decoding.ReceptiveField` now sets ``rf.fit_intercept_`` during ``fit()`` rather than overwriting ``rf.fit_intercept`` + - :class:`mne.decoding.SlidingEstimator` now returns the same ``dtype`` as ``X`` (usually ``float64``) in ``sl.transform(X)`` rather than always returning ``int`` +- Fix bug with :func:`mne.beamformer.make_lcmv` where the source space was not checked properly when the ``label`` argument was provided (:gh:`11852` by `Eric Larson`_) +- Fix bug where :func:`mne.io.read_raw_egi` did not properly set the EEG reference location for the reference channel itself (:gh:`11822` by `Eric Larson`_) +- Fix bug with legacy :meth:`~mne.io.Raw.plot_psd` method where passed axes were not used (:gh:`11778` by `Daniel McCloy`_) +- blink :class:`mne.Annotations` read in by :func:`mne.io.read_raw_eyelink` now begin with ``'BAD_'``, i.e. ``'BAD_blink'``, because ocular data are missing during blinks. (:gh:`11746` by `Scott Huberty`_) +- Fix bug where :ref:`mne show_fiff` could fail with an ambiguous error if the file is corrupt (:gh:`11800` by `Eric Larson`_) +- Fix bug where annotation FIF files lacked an end block tag (:gh:`11800` by `Eric Larson`_) +- Fix display of :class:`~mne.Annotations` in `mne.preprocessing.ICA.plot_sources` when the ``raw`` has ``raw.first_samp != 0`` and doesn't have a measurement date (:gh:`11766` by `Mathieu Scheltienne`_) +- Fix bug in read_raw_eyelink, where STATUS information of samples was always assumed to be in the file. Performance and memory improvements were also made. (:gh:`11823` by `Scott Huberty`_) +- Fix closing of a topographic map created from an interactive drag on an Evoked or PSD plot (:gh:`11862` by `Mathieu Scheltienne`_) + +API changes +~~~~~~~~~~~ +- The ``baseline`` argument can now be array-like (e.g. ``list``, ``tuple``, ``np.ndarray``, ...) instead of only a ``tuple`` (:gh:`11713` by `Clemens Brunner`_) +- The ``events`` and ``event_id`` parameters of :meth:`Epochs.plot() ` now accept boolean values; see docstring for details (:gh:`11445` by `Daniel McCloy`_ and `Clemens Brunner`_) +- Deprecated ``gap_description`` keyword argument of :func:`mne.io.read_raw_eyelink`, which will be removed in mne version 1.6, in favor of using :meth:`mne.Annotations.rename` (:gh:`11719` by `Scott Huberty`_) + +Authors +~~~~~~~ +* Aaron Earle-Richardson+ +* Alex Rockhill +* Alexandre Gramfort +* Britta Westner +* Clemens Brunner +* Daniel McCloy +* Daniel Tse+ +* Diptyajit Das+ +* Eric Larson +* Gennadiy Belonosov+ +* George O'Neill +* Hamza Abdelhedi+ +* Jacob Woessner +* Joshua Calder-Travis+ +* Mathieu Scheltienne +* Proloy Das +* Richard Höchenberger +* Rob Luke +* Samuel Louviot+ +* Scott Huberty +* Simon Kern +* Stefan Appelhoff +* Thomas Moreau +* Yiping Zuo+ diff --git a/mne-python/source/doc/changes/v1.6.rst b/mne-python/source/doc/changes/v1.6.rst new file mode 100644 index 0000000000000000000000000000000000000000..f770b5046d2dacafd90b9d6eaab714a9435cee5c --- /dev/null +++ b/mne-python/source/doc/changes/v1.6.rst @@ -0,0 +1,132 @@ +.. _changes_1_6_0: + +Version 1.6.0 (2023-11-20) +-------------------------- + +Enhancements +~~~~~~~~~~~~ +- Add support for Neuralynx data files with :func:`mne.io.read_raw_neuralynx` (:gh:`11969` by :newcontrib:`Kristijan Armeni` and :newcontrib:`Ivan Skelin`) +- Improve tests for saving splits with :class:`mne.Epochs` (:gh:`11884` by `Dmitrii Altukhov`_) +- Added functionality for linking interactive figures together, such that changing one figure will affect another, see :ref:`tut-ui-events` and :mod:`mne.viz.ui_events`. Current figures implementing UI events are :func:`mne.viz.plot_topomap` and :func:`mne.viz.plot_source_estimates` (:gh:`11685` :gh:`11891` by `Marijn van Vliet`_) +- HTML anchors for :class:`mne.Report` now reflect the ``section-title`` of the report items rather than using a global incrementor ``global-N`` (:gh:`11890` by `Eric Larson`_) +- Added public :func:`mne.io.write_info` to complement :func:`mne.io.read_info` (:gh:`11918` by `Eric Larson`_) +- Added option ``remove_dc`` to to :meth:`Raw.compute_psd() `, :meth:`Epochs.compute_psd() `, and :meth:`Evoked.compute_psd() `, to allow skipping DC removal when computing Welch or multitaper spectra (:gh:`11769` by `Nikolai Chapochnikov`_) +- Add the possibility to provide a float between 0 and 1 as ``n_grad``, ``n_mag`` and ``n_eeg`` in `~mne.compute_proj_raw`, `~mne.compute_proj_epochs` and `~mne.compute_proj_evoked` to select the number of vectors based on the cumulative explained variance (:gh:`11919` by `Mathieu Scheltienne`_) +- Add extracting all time courses in a label using :func:`mne.extract_label_time_course` without applying an aggregation function (like ``mean``) (:gh:`12001` by `Hamza Abdelhedi`_) +- Added support for Artinis fNIRS data files to :func:`mne.io.read_raw_snirf` (:gh:`11926` by `Robert Luke`_) +- Add helpful error messages when using methods on empty :class:`mne.Epochs`-objects (:gh:`11306` by `Martin Schulz`_) +- Add support for passing a :class:`python:dict` as ``sensor_color`` to specify per-channel-type colors in :func:`mne.viz.plot_alignment` (:gh:`12067` by `Eric Larson`_) +- Add inferring EEGLAB files' montage unit automatically based on estimated head radius using :func:`read_raw_eeglab(..., montage_units="auto") ` (:gh:`11925` by `Jack Zhang`_, :gh:`11951` by `Eric Larson`_) +- Add :class:`~mne.time_frequency.EpochsSpectrumArray` and :class:`~mne.time_frequency.SpectrumArray` to support creating power spectra from :class:`NumPy array ` data (:gh:`11803` by `Alex Rockhill`_) +- Add support for writing forward solutions to HDF5 and convenience function :meth:`mne.Forward.save` (:gh:`12036` by `Eric Larson`_) +- Refactored internals of :func:`mne.read_annotations` (:gh:`11964` by `Paul Roujansky`_) +- Add support for drawing MEG sensors in :ref:`mne coreg` (:gh:`12098` by `Eric Larson`_) +- Improve string representation of :class:`mne.Covariance` (:gh:`12181` by `Eric Larson`_) +- Add ``check_version=True`` to :ref:`mne sys_info` to check for a new release on GitHub (:gh:`12146` by `Eric Larson`_) +- Bad channels are now colored gray in addition to being dashed when spatial colors are used in :func:`mne.viz.plot_evoked` and related functions (:gh:`12142` by `Eric Larson`_) +- By default MNE-Python creates matplotlib figures with ``layout='constrained'`` rather than the default ``layout='tight'`` (:gh:`12050`, :gh:`12103` by `Mathieu Scheltienne`_ and `Eric Larson`_) +- Enhance :func:`~mne.viz.plot_evoked_field` with a GUI that has controls for time, colormap, and contour lines (:gh:`11942` by `Marijn van Vliet`_) +- Add :class:`mne.viz.ui_events.UIEvent` linking for interactive colorbars, allowing users to link figures and change the colormap and limits interactively. This supports :func:`~mne.viz.plot_evoked_topomap`, :func:`~mne.viz.plot_ica_components`, :func:`~mne.viz.plot_tfr_topomap`, :func:`~mne.viz.plot_projs_topomap`, :meth:`~mne.Evoked.plot_image`, and :meth:`~mne.Epochs.plot_image` (:gh:`12057` by `Santeri Ruuskanen`_) +- Add example KIT phantom dataset in :func:`mne.datasets.phantom_kit.data_path` and :ref:`tut-phantom-kit` (:gh:`12105` by `Judy D Zhu`_ and `Eric Larson`_) +- :func:`~mne.epochs.make_metadata` now accepts ``tmin=None`` and ``tmax=None``, which will bound the time window used for metadata generation by event names (instead of a fixed time). That way, you can now for example generate metadata spanning from one cue or fixation cross to the next, even if trial durations vary throughout the recording (:gh:`12118` by `Richard Höchenberger`_) +- Add support for passing multiple labels to :func:`mne.minimum_norm.source_induced_power` (:gh:`12026` by `Erica Peterson`_, `Eric Larson`_, and `Daniel McCloy`_ ) +- Added documentation to :meth:`mne.io.Raw.set_montage` and :func:`mne.add_reference_channels` to specify that montages should be set after adding reference channels (:gh:`12160` by `Jacob Woessner`_) +- Add argument ``splash`` to the function using the ``qt`` browser backend to allow enabling/disabling the splash screen (:gh:`12185` by `Mathieu Scheltienne`_) +- :class:`~mne.preprocessing.ICA`'s HTML representation (displayed in Jupyter notebooks and :class:`mne.Report`) now includes all optional fit parameters (e.g., max. number of iterations) (:gh:`12194`, by `Richard Höchenberger`_) + +Bugs +~~~~ +- Fix bug where :func:`mne.io.read_raw_gdf` would fail due to improper usage of ``np.clip`` (:gh:`12168` by :newcontrib:`Rasmus Aagaard`) +- Fix bugs with :func:`mne.preprocessing.realign_raw` where the start of ``other`` was incorrectly cropped; and onsets and durations in ``other.annotations`` were left unsynced with the resampled data (:gh:`11950` by :newcontrib:`Qian Chu`) +- Fix bug where ``encoding`` argument was ignored when reading annotations from an EDF file (:gh:`11958` by :newcontrib:`Andrew Gilbert`) +- Mark tests ``test_adjacency_matches_ft`` and ``test_fetch_uncompressed_file`` as network tests (:gh:`12041` by :newcontrib:`Maksym Balatsko`) +- Fix bug with :func:`mne.channels.read_ch_adjacency` (:gh:`11608` by :newcontrib:`Ivan Zubarev`) +- Fix bug where ``epochs.get_data(..., scalings=...)`` would errantly modify the preloaded data (:gh:`12121` by :newcontrib:`Pablo Mainar` and `Eric Larson`_) +- Fix bugs with saving splits for :class:`~mne.Epochs` (:gh:`11876` by `Dmitrii Altukhov`_) +- Fix bug with multi-plot 3D rendering where only one plot was updated (:gh:`11896` by `Eric Larson`_) +- Fix bug where ``verbose`` level was not respected inside parallel jobs (:gh:`12154` by `Eric Larson`_) +- Fix bug where subject birthdays were not correctly read by :func:`mne.io.read_raw_snirf` (:gh:`11912` by `Eric Larson`_) +- Fix bug where warnings were emitted when computing spectra for channels marked as bad (:gh:`12186` by `Eric Larson`_) +- Fix bug with :func:`mne.chpi.compute_head_pos` for CTF data where digitization points were modified in-place, producing an incorrect result during a save-load round-trip (:gh:`11934` by `Eric Larson`_) +- Fix bug where non-compliant stimulus data streams were not ignored by :func:`mne.io.read_raw_snirf` (:gh:`11915` by `Johann Benerradi`_) +- Fix bug with ``pca=False`` in :func:`mne.minimum_norm.compute_source_psd` (:gh:`11927` by `Alex Gramfort`_) +- Fix bug with notebooks when using PyVista 0.42 by implementing ``trame`` backend support (:gh:`11956` by `Eric Larson`_) +- Removed preload parameter from :func:`mne.io.read_raw_eyelink`, because data are always preloaded no matter what preload is set to (:gh:`11910` by `Scott Huberty`_) +- Fix bug with :meth:`mne.viz.Brain.get_view` where calling :meth:`~mne.viz.Brain.show_view` with returned parameters would change the view (:gh:`12000` by `Eric Larson`_) +- Fix bug with :meth:`mne.viz.Brain.show_view` where ``distance=None`` would change the view distance (:gh:`12000` by `Eric Larson`_) +- Fix bug with :meth:`~mne.viz.Brain.add_annotation` when reading an annotation from a file with both hemispheres shown (:gh:`11946` by `Marijn van Vliet`_) +- Fix bug with reported component number and errant reporting of PCA explained variance as ICA explained variance in :meth:`mne.Report.add_ica` (:gh:`12155`, :gh:`12167` by `Eric Larson`_ and `Richard Höchenberger`_) +- Fix bug with axis clip box boundaries in :func:`mne.viz.plot_evoked_topo` and related functions (:gh:`11999` by `Eric Larson`_) +- Fix bug with ``subject_info`` when loading data from and exporting to EDF file (:gh:`11952` by `Paul Roujansky`_) +- Fix bug where :class:`mne.Info` HTML representations listed all channel counts instead of good channel counts under the heading "Good channels" (:gh:`12145` by `Eric Larson`_) +- Fix rendering glitches when plotting Neuromag/TRIUX sensors in :func:`mne.viz.plot_alignment` and related functions (:gh:`12098` by `Eric Larson`_) +- Fix bug with delayed checking of :class:`info["bads"] ` (:gh:`12038` by `Eric Larson`_) +- Fix bug with :ref:`mne coreg` where points inside the head surface were not shown (:gh:`12147`, :gh:`12164` by `Eric Larson`_) +- Fix bug with :func:`mne.viz.plot_alignment` where ``sensor_colors`` were not handled properly on a per-channel-type basis (:gh:`12067` by `Eric Larson`_) +- Fix handling of channel information in annotations when loading data from and exporting to EDF file (:gh:`11960` :gh:`12017` :gh:`12044` by `Paul Roujansky`_) +- Add missing ``overwrite`` and ``verbose`` parameters to :meth:`Transform.save() ` (:gh:`12004` by `Marijn van Vliet`_) +- Fix parsing of eye-link :class:`~mne.Annotations` when ``apply_offsets=False`` is provided to :func:`~mne.io.read_raw_eyelink` (:gh:`12003` by `Mathieu Scheltienne`_) +- Correctly prune channel-specific :class:`~mne.Annotations` when creating :class:`~mne.Epochs` without the channel(s) included in the channel specific annotations (:gh:`12010` by `Mathieu Scheltienne`_) +- Fix :func:`~mne.viz.plot_volume_source_estimates` with :class:`~mne.VolSourceEstimate` which include a list of vertices (:gh:`12025` by `Mathieu Scheltienne`_) +- Add support for non-ASCII characters in Annotations, Evoked comments, etc when saving to FIFF format (:gh:`12080` by `Daniel McCloy`_) +- Correctly handle passing ``"eyegaze"`` or ``"pupil"`` to :meth:`mne.io.Raw.pick` (:gh:`12019` by `Scott Huberty`_) +- Fix bug with :func:`mne.time_frequency.Spectrum.plot` and related functions where bad channels were not marked (:gh:`12142` by `Eric Larson`_) +- Fix bug with :func:`~mne.viz.plot_raw` where changing ``MNE_BROWSER_BACKEND`` via :func:`~mne.set_config` would have no effect within a Python session (:gh:`12078` by `Santeri Ruuskanen`_) +- Improve handling of ``method`` argument in the channel interpolation function to support :class:`str` and raise helpful error messages (:gh:`12113` by `Mathieu Scheltienne`_) +- Fix combination of ``DIN`` event channels into a single synthetic trigger channel ``STI 014`` by the MFF reader of :func:`mne.io.read_raw_egi` (:gh:`12122` by `Mathieu Scheltienne`_) +- Fix bug with :func:`mne.io.read_raw_eeglab` and :func:`mne.read_epochs_eeglab` where automatic fiducial detection would fail for certain files (:gh:`12165` by `Clemens Brunner`_) +- Fix concatenation of ``raws`` with ``np.nan`` in the device to head transformation (:gh:`12198` by `Mathieu Scheltienne`_) +- Fix bug with :func:`mne.viz.plot_compare_evokeds` where the title was not displayed when ``axes='topo'`` (:gh:`12192` by `Jacob Woessner`_) +- Fix bug with :func:`mne.io.read_raw_cnt` where the bad channels were not properly read (:gh:`12189` by `Jacob Woessner`_) +- Fix bug where iterating over :class:`~mne.io.Raw` would result in an error (:gh:`12205` by `Clemens Brunner`_) + + +API changes +~~~~~~~~~~~ +- The default for :meth:`mne.Epochs.get_data` of ``copy=False`` will change to ``copy=True`` in 1.7. Set it explicitly to avoid a warning (:gh:`12121` by :newcontrib:`Pablo Mainar` and `Eric Larson`_) +- ``mne.preprocessing.apply_maxfilter`` and ``mne maxfilter`` have been deprecated and will be removed in 1.7. Use :func:`mne.preprocessing.maxwell_filter` (see :ref:`this tutorial `) in Python or the command-line utility from MEGIN ``maxfilter`` and :func:`mne.bem.fit_sphere_to_headshape` instead (:gh:`11938` by `Eric Larson`_) +- :func:`mne.io.kit.read_mrk` reading pickled files is deprecated using something like ``np.savetxt(fid, pts, delimiter="\t", newline="\n")`` to save your points instead (:gh:`11937` by `Eric Larson`_) +- Replace legacy ``inst.pick_channels`` and ``inst.pick_types`` with ``inst.pick`` (where ``inst`` is an instance of :class:`~mne.io.Raw`, :class:`~mne.Epochs`, or :class:`~mne.Evoked`) wherever possible (:gh:`11907` by `Clemens Brunner`_) +- The ``reset_camera`` parameter has been removed in favor of ``distance="auto"`` in :func:`mne.viz.set_3d_view`, :meth:`mne.viz.Brain.show_view`, and related functions (:gh:`12000` by `Eric Larson`_) +- Several unused parameters from :func:`mne.gui.coregistration` are now deprecated: tabbed, split, scrollable, head_inside, guess_mri_subject, scale, and ``advanced_rendering``. All arguments are also now keyword-only. (:gh:`12147` by `Eric Larson`_) + +Authors +~~~~~~~ +* Adam Li +* Alex Rockhill +* Alexandre Gramfort +* Ana Radanovic +* Andy Gilbert+ +* Clemens Brunner +* Daniel McCloy +* Denis A. Engemann +* Dimitri Papadopoulos Orfanos +* Dmitrii Altukhov +* Dominik Welke +* Eric Larson +* Erica Peterson +* Gonzalo Reina +* Hamza Abdelhedi +* Ivan Skelin+ +* Ivan Zubarev+ +* Jack Zhang +* Jacob Woessner +* Johann Benerradi +* John Veillette +* Judy D Zhu +* Kristijan Armeni+ +* Mainak Jas +* Maksym Balatsko+ +* Marijn van Vliet +* Martin Schulz +* Mathieu Scheltienne +* Nikolai Chapochnikov +* Pablo Mainar+ +* Paul Roujansky +* Qian Chu+ +* Rasmus Aagaard+ +* Richard Höchenberger +* Rob Luke +* Santeri Ruuskanen +* Scott Huberty +* Stefan Appelhoff diff --git a/mne-python/source/doc/changes/v1.7.rst b/mne-python/source/doc/changes/v1.7.rst new file mode 100644 index 0000000000000000000000000000000000000000..6b11861254140fbfb1b5665a1962ef81d501a485 --- /dev/null +++ b/mne-python/source/doc/changes/v1.7.rst @@ -0,0 +1,197 @@ +.. _changes_1_7_1: + +Version 1.7.1 (2024-06-14) +========================== + +Bugfixes +-------- + +- Fix bug where :func:`mne.time_frequency.csd_multitaper`, :func:`mne.time_frequency.csd_fourier`, :func:`mne.time_frequency.csd_array_multitaper`, and :func:`mne.time_frequency.csd_array_fourier` would return cross-spectral densities with the ``fmin`` and ``fmax`` frequencies missing, by `Thomas Binns`_ (`#12633 `__) +- Fix incorrect RuntimeWarning (different channel filter settings) in EDF/BDF import, by `Clemens Brunner`_. (`#12661 `__) + +Authors +------- + +* Clemens Brunner +* Thomas Binns + +.. _changes_1_7_0: + +Version 1.7.0 (2024-04-19) +========================== + +Notable changes +--------------- + +- In this version, we started adding type hints (also known as "type annotations") to select parts of the codebase. + This meta information will be used by development environments (IDEs) like VS Code and PyCharm automatically to provide + better assistance such as tab completion or error detection even before running your code. + + So far, we've only added return type hints to :func:`mne.io.read_raw`, :func:`mne.read_epochs`, :func:`mne.read_evokeds` and + all format-specific ``read_raw_*()`` and ``read_epochs_*()`` functions. Now your editors will know: + these functions return evoked and raw data, respectively. We are planning add type hints to more functions after careful + evaluation in the future. + + You don't need to do anything to benefit from these changes – your editor will pick them up automatically and provide the + enhanced experience if it supports it! (`#12250 `__) + + +Dependencies +------------ + +- ``defusedxml`` is now an optional (rather than required) dependency and needed when reading EGI-MFF data, NEDF data, and BrainVision montages, by `Eric Larson`_. (`#12264 `__) +- For developers, ``pytest>=8.0`` is now required for running unit tests, by `Eric Larson`_. (`#12376 `__) +- ``pytest-harvest`` is no longer used as a test dependency, by `Eric Larson`_. (`#12451 `__) +- The minimum supported version of Qt bindings is 5.15, by `Eric Larson`_. (`#12491 `__) + + +Bugfixes +-------- + +- Fix bug where section parameter in :meth:`mne.Report.add_html` was not being utilized resulting in improper formatting, by :newcontrib:`Martin Oberg`. (`#12319 `__) +- Fix bug in :func:`mne.preprocessing.maxwell_filter` where calibration was incorrectly applied during virtual sensor reconstruction, by `Eric Larson`_ and :newcontrib:`Motofumi Fushimi`. (`#12348 `__) +- Reformats channel and detector lookup in :func:`mne.io.read_raw_snirf` from array based to dictionary based. Removes incorrect assertions that every detector and source must have data associated with every registered optode position, by :newcontrib:`Alex Kiefer`. (`#12430 `__) +- Remove FDT file format check for strings in EEGLAB's EEG.data in :func:`mne.io.read_raw_eeglab` and related functions by :newcontrib:`Seyed Yahya Shirazi` (`#12523 `__) +- Fixes to interactivity in time-frequency objects: the rectangle selector now works on TFR image plots of gradiometer data; and in ``TFR.plot_joint()`` plots, the colormap limits of interactively-generated topomaps match the colormap limits of the main plot. By `Daniel McCloy`_. (`#11282 `__) +- Allow :func:`mne.viz.plot_compare_evokeds` to plot eyetracking channels, and improve error handling, y `Scott Huberty`_. (`#12190 `__) +- Fix bug in :meth:`mne.Epochs.apply_function` where data was handed down incorrectly in parallel processing, by `Dominik Welke`_. (`#12206 `__) +- Remove incorrect type hints in :func:`mne.io.read_raw_neuralynx`, by `Richard Höchenberger`_. (`#12236 `__) +- Fix bug with accessing the last data sample using ``raw[:, -1]`` where an empty array was returned, by `Eric Larson`_. (`#12248 `__) +- Correctly handle temporal gaps in Neuralynx .ncs files via :func:`mne.io.read_raw_neuralynx`, by `Kristijan Armeni`_ and `Eric Larson`_. (`#12279 `__) +- Fix bug where parent directory existence was not checked properly in :meth:`mne.io.Raw.save`, by `Eric Larson`_. (`#12282 `__) +- Add ``tol`` parameter to :meth:`mne.events_from_annotations` so that the user can specify the tolerance to ignore rounding errors of event onsets when using ``chunk_duration`` is not None (default is 1e-8), by `Michiru Kaneda`_ (`#12324 `__) +- Allow :meth:`mne.io.Raw.interpolate_bads` and :meth:`mne.Epochs.interpolate_bads` to work on ``ecog`` and ``seeg`` data; for ``seeg`` data a spline is fit to neighboring electrode contacts on the same shaft, by `Alex Rockhill`_ (`#12336 `__) +- Fix clicking on an axis of :func:`mne.viz.plot_evoked_topo` when multiple vertical lines ``vlines`` are used, by `Mathieu Scheltienne`_. (`#12345 `__) +- Fix bug in :meth:`mne.viz.EvokedField.set_vmax` that prevented setting the color limits of the MEG magnetic field density, by `Marijn van Vliet`_ (`#12354 `__) +- Fix faulty indexing in :func:`mne.io.read_raw_neuralynx` when picking a single channel, by `Kristijan Armeni`_. (`#12357 `__) +- Fix bug where :func:`mne.preprocessing.compute_proj_ecg` and :func:`mne.preprocessing.compute_proj_eog` could modify the default ``reject`` and ``flat`` arguments on multiple calls based on channel types present, by `Eric Larson`_. (`#12380 `__) +- Fix bad channels not handled properly in :func:`mne.stc_near_sensors` by `Alex Rockhill`_. (`#12382 `__) +- Fix bug where :func:`mne.preprocessing.regress_artifact` projection check was not specific to the channels being processed, by `Eric Larson`_. (`#12389 `__) +- Change how samples are read when using ``data_format='auto'`` in :func:`mne.io.read_raw_cnt`, by `Jacob Woessner`_. (`#12393 `__) +- Fix bugs with :class:`mne.Report` CSS where TOC items could disappear at the bottom of the page, by `Eric Larson`_. (`#12399 `__) +- In :func:`~mne.viz.plot_compare_evokeds`, actually plot GFP (not RMS amplitude) for EEG channels when global field power is requested by `Daniel McCloy`_. (`#12410 `__) +- Fix :ref:`tut-working-with-seeg` use of :func:`mne.stc_near_sensors` to use the :class:`mne.VolSourceEstimate` positions and not the pial surface, by `Alex Rockhill`_ (`#12436 `__) +- Fix prefiltering information management for EDF/BDF, by `Michiru Kaneda`_ (`#12441 `__) +- Fix validation of ``ch_type`` in :func:`mne.preprocessing.annotate_muscle_zscore`, by `Mathieu Scheltienne`_. (`#12444 `__) +- Fix errant redundant use of ``BIDSPath.split`` when writing split raw and epochs data, by `Eric Larson`_. (`#12451 `__) +- Disable config parser interpolation when reading BrainVision files, which allows using the percent sign as a regular character in channel units, by `Clemens Brunner`_. (`#12456 `__) +- Fix the default color of :meth:`mne.viz.Brain.add_text` to properly contrast with the figure background color, by `Marijn van Vliet`_. (`#12470 `__) +- Changed default ECoG and sEEG electrode sizes in brain plots to better reflect real world sizes, by `Liberty Hamilton`_ (`#12474 `__) +- Fixed bugs with handling of rank in :class:`mne.decoding.CSP`, by `Eric Larson`_. (`#12476 `__) +- Fix reading segmented recordings with :func:`mne.io.read_raw_eyelink` by `Dominik Welke`_. (`#12481 `__) +- Improve compatibility with other Qt-based GUIs by handling theme icons better, by `Eric Larson`_. (`#12483 `__) +- Fix problem caused by onsets with NaN values using :func:`mne.io.read_raw_eeglab` by `Jacob Woessner`_ (`#12484 `__) +- Fix cleaning of channel names for non vectorview or CTF dataset including whitespaces or dash in their channel names, by `Mathieu Scheltienne`_. (`#12489 `__) +- Fix bug with :meth:`mne.preprocessing.ICA.plot_sources` for ``evoked`` data where the + legend contained too many entries, by `Eric Larson`_. (`#12498 `__) +- Fix bug where using ``phase="minimum"`` in filtering functions like + :meth:`mne.io.Raw.filter` constructed a filter half the desired length with + compromised attenuation. Now ``phase="minimum"`` has the same length and comparable + suppression as ``phase="zero"``, and the old (incorrect) behavior can be achieved + with ``phase="minimum-half"``, by `Eric Larson`_. (`#12507 `__) +- Correct reading of ``info["subject_info"]["his_id"]`` in :func:`mne.io.read_raw_snirf`, by `Eric Larson`_. (`#12526 `__) +- Calling :meth:`~mne.io.Raw.compute_psd` with ``method="multitaper"`` is now expressly disallowed when ``reject_by_annotation=True`` and ``bad_*`` annotations are present (previously this was nominally allowed but resulted in ``nan`` values in the PSD). By `Daniel McCloy`_. (`#12535 `__) +- :meth:`~mne.io.Raw.compute_psd` and :func:`~mne.time_frequency.psd_array_welch` will now use FFT windows aligned to the onsets of good data spans when ``bad_*`` annotations are present. By `Daniel McCloy`_. (`#12536 `__) +- Fix bug in loading of complex/phase TFRs. By `Daniel McCloy`_. (`#12537 `__) +- Fix bug with :func:`mne.SourceSpaces.export_volume` where the ``img.affine`` was not set properly, by `Eric Larson`_. (`#12544 `__) + + +API changes by deprecation +-------------------------- + +- The default value of the ``zero_mean`` parameter of :func:`mne.time_frequency.tfr_array_morlet` will change from ``False`` to ``True`` in version 1.8, for consistency with related functions. By `Daniel McCloy`_. (`#11282 `__) +- The parameter for providing data to :func:`mne.time_frequency.tfr_array_morlet` and :func:`mne.time_frequency.tfr_array_multitaper` has been switched from ``epoch_data`` to ``data``. Only use the ``data`` parameter to avoid a warning. Changes by `Thomas Binns`_. (`#12308 `__) +- Change :func:`mne.stc_near_sensors` ``surface`` default from the ``'pial'`` surface to the surface in ``src`` if ``src`` is not ``None`` in version 1.8, by `Alex Rockhill`_. (`#12382 `__) + + +New features +------------ + +- Detecting Bad EEG/MEG channels using the local outlier factor (LOF) algorithm in :func:`mne.preprocessing.find_bad_channels_lof`, by :newcontrib:`Velu Prabhakar Kumaravel`. (`#11234 `__) +- Inform the user about channel discrepancy between provided info, forward operator, and/or covariance matrices in :func:`mne.beamformer.make_lcmv`, by :newcontrib:`Nikolai Kapralov`. (`#12238 `__) +- Support partial pathlength factors for each wavelength in :func:`mne.preprocessing.nirs.beer_lambert_law`, by :newcontrib:`Richard Scholz`. (`#12446 `__) +- Add ``picks`` parameter to :meth:`mne.io.Raw.plot`, allowing users to select which channels to plot. This makes makes the raw data plotting API consistent with :meth:`mne.Epochs.plot` and :meth:`mne.Evoked.plot`, by :newcontrib:`Ivo de Jong`. (`#12467 `__) +- New class :class:`mne.time_frequency.RawTFR` and new methods :meth:`mne.io.Raw.compute_tfr`, :meth:`mne.Epochs.compute_tfr`, and :meth:`mne.Evoked.compute_tfr`. These new methods supersede functions :func:`mne.time_frequency.tfr_morlet`, and :func:`mne.time_frequency.tfr_multitaper`, and :func:`mne.time_frequency.tfr_stockwell`, which are now considered "legacy" functions. By `Daniel McCloy`_. (`#11282 `__) +- Add ability reject :class:`mne.Epochs` using callables, by `Jacob Woessner`_. (`#12195 `__) +- Custom functions applied via :meth:`mne.io.Raw.apply_function`, :meth:`mne.Epochs.apply_function` or :meth:`mne.Evoked.apply_function` can now use ``ch_idx`` or ``ch_name`` to get access to the currently processed channel during channel wise processing. +- :meth:`mne.Evoked.apply_function` can now also work on full data array instead of just channel wise, analogous to :meth:`mne.io.Raw.apply_function` and :meth:`mne.Epochs.apply_function`, by `Dominik Welke`_. (`#12206 `__) +- Allow :class:`mne.time_frequency.EpochsTFR` as input to :func:`mne.epochs.equalize_epoch_counts`, by `Carina Forster`_. (`#12207 `__) +- Speed up export to .edf in :func:`mne.export.export_raw` by using ``edfio`` instead of ``EDFlib-Python``. (`#12218 `__) +- Added a helper function :func:`mne.preprocessing.eyetracking.convert_units` to convert eyegaze data from pixel-on-screen values to radians of visual angle. Also added a helper function :func:`mne.preprocessing.eyetracking.get_screen_visual_angle` to get the visual angle that the participant screen subtends, by `Scott Huberty`_. (`#12237 `__) +- We added type hints for the return values of :func:`mne.read_evokeds` and :func:`mne.io.read_raw`. Development environments like VS Code or PyCharm will now provide more help when using these functions in your code. By `Richard Höchenberger`_ and `Eric Larson`_. (:gh:`12297`) (`#12250 `__) +- Add ``method="polyphase"`` to :meth:`mne.io.Raw.resample` and related functions to allow resampling using :func:`scipy.signal.upfirdn`, by `Eric Larson`_. (`#12268 `__) +- The package build backend was switched from ``setuptools`` to ``hatchling``. This will only affect users who build and install MNE-Python from source. By `Richard Höchenberger`_. (:gh:`12281`) (`#12269 `__) +- :meth:`mne.Annotations.to_data_frame` can now output different formats for the ``onset`` column: seconds, milliseconds, datetime objects, and timedelta objects. By `Daniel McCloy`_. (`#12289 `__) +- Add method :meth:`mne.SourceEstimate.save_as_surface` to allow saving GIFTI files from surface source estimates, by `Peter Molfese`_. (`#12309 `__) +- :class:`mne.Epochs` can now be constructed using :class:`mne.Annotations` stored in the ``raw`` object, by specifying ``events=None``. By `Alex Rockhill`_. (`#12311 `__) +- Add :meth:`~mne.SourceEstimate.savgol_filter`, :meth:`~mne.SourceEstimate.filter`, :meth:`~mne.SourceEstimate.apply_hilbert`, and :meth:`~mne.SourceEstimate.apply_function` methods to :class:`mne.SourceEstimate` and related classes, by `Hamza Abdelhedi`_. (`#12323 `__) +- Add ability to export STIM channels to EDF in :meth:`mne.io.Raw.export`, by `Clemens Brunner`_. (`#12332 `__) +- Speed up raw FIF reading when using small buffer sizes by `Eric Larson`_. (`#12343 `__) +- Speed up :func:`mne.io.read_raw_neuralynx` on large datasets with many gaps, by `Kristijan Armeni`_. (`#12371 `__) +- Add ability to detect minima peaks found in :class:`mne.Evoked` if data is all positive and maxima if data is all negative. (`#12383 `__) +- Add ability to remove bad marker coils in :func:`mne.io.read_raw_kit`, by `Judy D Zhu`_. (`#12394 `__) +- Add option to pass ``image_kwargs`` to :class:`mne.Report.add_epochs` to allow adjusting e.g. ``vmin`` and ``vmax`` of the epochs image in the report, by `Sophie Herbst`_. (`#12443 `__) +- Add support for multiple raw instances in :func:`mne.preprocessing.compute_average_dev_head_t` by `Eric Larson`_. (`#12445 `__) +- Completing PR 12453. Add option to pass ``image_kwargs`` per channel type to :class:`mne.Report.add_epochs`. (`#12454 `__) +- :func:`mne.epochs.make_metadata` now accepts strings as ``tmin`` and ``tmax`` parameter values, simplifying metadata creation based on time-varying events such as responses to a stimulus, by `Richard Höchenberger`_. (`#12462 `__) +- Include date of acquisition and filter parameters in ``raw.info`` for :func:`mne.io.read_raw_neuralynx` by `Kristijan Armeni`_. (`#12463 `__) +- Add ``physical_range="channelwise"`` to :meth:`mne.io.Raw.export` for exporting to EDF, which can improve amplitude resolution if individual channels vary greatly in their offsets, by `Clemens Brunner`_. (`#12510 `__) +- Added the ability to reorder report contents via :meth:`mne.Report.reorder` (with + helper to get contents with :meth:`mne.Report.get_contents`), by `Eric Larson`_. (`#12513 `__) +- Add ``exclude_after_unique`` option to :meth:`mne.io.read_raw_edf` and :meth:`mne.io.read_raw_edf` to search for exclude channels after making channels names unique, by `Michiru Kaneda`_ (`#12518 `__) + + +Other changes +------------- + +- Updated the text in the preprocessing tutorial to use :meth:`mne.io.Raw.pick` instead of the legacy :meth:`mne.io.Raw.pick_types`, by :newcontrib:`btkcodedev`. (`#12326 `__) +- Clarify in the :ref:`EEG referencing tutorial ` that an average reference projector ready is required for inverse modeling, by :newcontrib:`Nabil Alibou` (`#12420 `__) +- Fix dead links in ``README.rst`` documentation by :newcontrib:`Will Turner`. (`#12461 `__) +- Replacing percent format with f-strings format specifiers , by :newcontrib:`Hasrat Ali Arzoo`. (`#12464 `__) +- Adopted towncrier_ for changelog entries, by `Eric Larson`_. (`#12299 `__) +- Automate adding of PR number to towncrier stubs, by `Eric Larson`_. (`#12318 `__) +- Refresh code base to use Python 3.9 syntax using Ruff UP rules (pyupgrade), by `Clemens Brunner`_. (`#12358 `__) +- Move private data preparation functions for BrainVision export from ``pybv`` to ``mne``, by `Clemens Brunner`_. (`#12450 `__) +- Update the list of sensor types in docstrings, tutorials and the glossary by `Nabil Alibou`_. (`#12509 `__) + + +Authors +------- +* Alex Rockhill +* Alexander Kiefer+ +* Alexandre Gramfort +* Britta Westner +* Carina Forster +* Clemens Brunner +* Daniel McCloy +* Dominik Welke +* Eric Larson +* Erkka Heinila +* Florian Hofer +* Hamza Abdelhedi +* Hasrat Ali Arzoo+ +* Ivo de Jong+ +* Jacob Woessner +* Judy D Zhu +* Kristijan Armeni +* Liberty Hamilton +* Marijn van Vliet +* Martin Oberg+ +* Mathieu Scheltienne +* Michiru Kaneda +* Motofumi Fushimi+ +* Nabil Alibou+ +* Nikolai Kapralov+ +* Peter J. Molfese +* Richard Höchenberger +* Richard Scholz+ +* Scott Huberty +* Seyed (Yahya) Shirazi+ +* Sophie Herbst +* Stefan Appelhoff +* Thomas Donoghue +* Thomas Samuel Binns +* Tristan Stenner +* Velu Prabhakar Kumaravel+ +* Will Turner+ +* btkcodedev+ diff --git a/mne-python/source/doc/changes/v1.8.rst b/mne-python/source/doc/changes/v1.8.rst new file mode 100644 index 0000000000000000000000000000000000000000..f6abcc65e5293bbb2e43aa22593e17b8d05f2295 --- /dev/null +++ b/mne-python/source/doc/changes/v1.8.rst @@ -0,0 +1,173 @@ +.. _changes_1_8_0: + +Version 1.8.0 (2024-08-18) +========================== + +Dependencies +------------ + +- Minimum versions for dependencies were bumped to those ~2 years old at the time of release (by `Eric Larson`_), including: + + - NumPy ≥ 1.23 + - SciPy ≥ 1.9 + - Matplotlib ≥ 3.6 + - scikit-learn ≥ 1.1 (`#12554 `__) +- Official support for PySide2 has been dropped in this release (though it might continue + to work), by `Eric Larson`_. (`#12742 `__) + + +Bugfixes +-------- + +- Fix bug where an event that occurred only once was excluded in :func:`mne.io.read_raw_egi`, by :newcontrib:`Ping-Keng Jao`. (`#12300 `__) +- Fix bug where :func:`mne.stats.permutation_cluster_test` (and related functions) uses excessive amount of memory for large 2D data when TFCE method is selected, by :newcontrib:`Nicolas Fourcaud-Trocmé`. (`#12609 `__) +- Assure that blink times are handled correctly :func:`mne.preprocessing.eyetracking.interpolate_blinks`, even when the raw object is cropped by `Scott Huberty`_ and :newcontrib:`Sammi Chekroud`. (`#12759 `__) +- Fix check for dropping all channels in :meth:`mne.io.Raw.drop_channels` and related methods, by :newcontrib:`Farzin Negahbani`. (`#12763 `__) +- Fix scrolling behavior in :class:`~mne.Report` when clicking on a TOC entry multiple times, by `Richard Höchenberger`_. (`#12561 `__) +- Fix bug where :func:`mne.decoding.get_coef` did not work properly with :class:`mne.decoding.CSP`, by `Eric Larson`_. (`#12562 `__) +- The color scaling of Evoked topomaps added to reports via :meth:`mne.Report.add_evokeds` + was sometimes sub-optimal if bad channels were present in the data. This has now been fixed + and should be more consistent with the topomaps shown in the joint plots, by `Richard Höchenberger`_. (`#12578 `__) +- Fix error causing :meth:`mne.Epochs.interpolate_bads` not to work for ``seeg`` channels and fix a single contact on neighboring shafts sometimes being included in interpolation, by `Alex Rockhill`_ (`#12593 `__) +- Fix bug where :func:`mne.io.read_raw_fil` could not assign bad channels on import, by `George O'Neill`_. (`#12597 `__) +- Fixed a bug where :meth:`mne.Evoked.animate_topomap` did not work with :func:`mne.preprocessing.compute_current_source_density` - modified data, by `Michal Žák`_. (`#12605 `__) +- Fix overflow when plotting source estimates where data is all zero (or close to zero), and fix the range of allowed values for the colorbar sliders, by `Marijn van Vliet`_. (`#12612 `__) +- Fix adding channels to :class:`~mne.time_frequency.EpochsTFR` objects, by `Clemens Brunner`_. (`#12616 `__) +- Fix for new sklearn metadata routing protocol in decoding search_light, by `Alex Gramfort`_ (`#12620 `__) +- Fix bug where :func:`mne.time_frequency.csd_multitaper`, :func:`mne.time_frequency.csd_fourier`, :func:`mne.time_frequency.csd_array_multitaper`, and :func:`mne.time_frequency.csd_array_fourier` would return cross-spectral densities with the ``fmin`` and ``fmax`` frequencies missing, by `Thomas Binns`_ (`#12633 `__) +- Output types of sparse arrays were changed from ``matrix`` to ``array`` in + :func:`~mne.channels.read_ch_adjacency`, :func:`~mne.channels.find_ch_adjacency`, + :func:`~mne.stats.combine_adjacency`, :func:`~mne.spatio_temporal_src_adjacency`, + and related functions to comply with the pending deprecation of ``np.matrix``. + The returned objects now behave like standard :class:`~numpy.ndarray` objects, and + in particular ``*`` now operates element-wise instead of performing matrix + multiplication. You can use ``@`` as a backward compatible matrix multiplication + for both ``np.matrix`` and ``np.ndarray`` objects, and if a matrix is desired + the outputs can be cast directly, for example as ``scipy.sparse.csr_matrix(out)``. + Changed by `Eric Larson`_. (`#12646 `__) +- Fix incorrect RuntimeWarning (different channel filter settings) in EDF/BDF import, by `Clemens Brunner`_. (`#12661 `__) +- In :func:`mne.export.export_raw` (``fmt='edf'``), when padding data to create equal-length data blocks, + edge-padding is favored over zero-padding in order to avoid accidentally enlarging physical range, by `Qian Chu`_. (`#12676 `__) +- In :func:`mne.io.read_raw_eyelink`, gracefully handle missing datetime in file by `Scott Huberty`_. (`#12687 `__) +- Fix regression with :class:`mne.decoding.CSP` where using ``rank="full"`` errantly + raised an error, by `Eric Larson`_. (`#12694 `__) +- Fix in-memory anonymization of data read with :func:`mne.io.read_raw_edf` by `Eric Larson`_. (`#12720 `__) +- Fix bug with overplotting of butterfly labels in :func:`mne.viz.plot_raw` and related + functions and methods, by `Eric Larson`_. (`#12721 `__) +- Fix a bug where the ``ylim`` parameter would sometimes apply to the wrong channel types in :func:`mne.viz.plot_evoked_topo`, by `Marijn van Vliet`_. (`#12724 `__) +- Fix bug where ad-hoc regularization of a covariance with + :func:`mne.cov.regularize` did not properly account for bad channels + in rank calculations, by `Eric Larson`_. (`#12727 `__) +- Fix bug when reading NIRX files saved in a non-western encoding, by `Daniel McCloy`_. (`#12730 `__) +- :func:`~mne.set_log_file` and :func:`~mne.set_log_level` can now be correctly detected by + static analysis tools like Pylance, by `Richard Höchenberger`_. (`#12735 `__) +- Safeguard loading of ``meas_date`` in :func:`mne.io.read_raw_edf`, by `Mathieu Scheltienne`_. (`#12754 `__) +- Fix bug in :func:`~mne.preprocessing.maxwell_filter_prepare_emptyroom` where a difference in sampling frequencies between data and emptyroom files was ignored, by `Daniel McCloy`_. (`#12760 `__) + + +API changes by deprecation +-------------------------- + +- A new argument ``events_as_annotations`` has been added to :func:`mne.io.read_raw_egi` + with a default value of ``False`` that will change to ``True`` in version 1.9, by + `Scott Huberty`_ and `Eric Larson`_. (`#12300 `__) +- ``mne.Info.ch_names`` will now return an empty list instead of raising a ``KeyError`` if no channels + are present, by `Richard Höchenberger`_. (`#12583 `__) +- Documented that :func:`~mne.match_channel_orders` can also work on Epochs, and Evoked objects. Reflecting this, deprecated the ``raws`` parameter in favor of an ``insts`` parameter, by `Stefan Appelhoff`_. (`#12699 `__) +- The ``block`` argument to :class:`mne.viz.Brain` is deprecated and will be removed in + 1.9, use :func:`matplotlib.pyplot.show` with ``block=True`` instead, by `Eric Larson`_. (`#12719 `__) +- :func:`mne.datasets.fetch_fsaverage` now returns a :class:`python:pathlib.Path` object + rather than a string. Support for string concatenation with plus (``+``) is thus + deprecated and will be removed in 1.9, use the forward-slash ``/`` operator instead, + by `Eric Larson`_. (`#12771 `__) + + +New features +------------ + +- Added internals to allow modifying single-channel annotations in the Qt + raw browser, by :newcontrib:`Noah Markowitz`. (`#12669 `__) +- Adding :meth:`mne.channels.Layout.copy` and :meth:`mne.channels.Layout.pick` to copy and select channels from a :class:`mne.channels.Layout` object. Plotting 2D topographies of evoked responses with :func:`mne.viz.plot_evoked_topo` with both arguments ``layout`` and ``exclude`` now ignores excluded channels from the :class:`mne.channels.Layout`. By `Mathieu Scheltienne`_. (`#12338 `__) +- In :class:`~mne.Report` you can now easily navigate through images and figures connected to a slider with the left and right arrow keys. Clicking on the slider or respective image will focus the slider, enabling keyboard navigation, by `Richard Höchenberger`_ (`#12556 `__) +- When plotting EOG and ECG artifact scores for ICA in :meth:`mne.Report.add_ica`, + the channel names used for artifact detection are now displayed in the titles of + each respective subplot, by `Richard Höchenberger`_. (`#12573 `__) +- Use ``aseg='auto'`` for :meth:`mne.viz.Brain.add_volume_labels` and :func:`mne.get_montage_volume_labels` to use ``aparc+aseg`` by default or if not present use ``wmparc`` because freesurfer uses ``wmparc`` in the latest version, by `Alex Rockhill`_. (`#12576 `__) +- The HTML representations of :class:`~mne.io.Raw`, :class:`~mne.Epochs`, + and :class:`~mne.Evoked` (which you will see e.g. when working with Jupyter Notebooks or + :class:`~mne.Report`) have been updated to be more consistent and contain + slightly more information, by `Richard Höchenberger`_. (:gh:`12624`) (`#12583 `__) +- When adding :class:`~mne.Evoked` data to a :class:`~mne.Report` via + :meth:`~mne.Report.add_evokeds`, we now also include an "Info" section + with some basic summary info, as has already been the case for raw and + epochs data, by `Richard Höchenberger`_. (`#12584 `__) +- We added new installation variants for a full installation with the PySide6 Qt binding + (``"mne[full-pyside6]"``), with the PyQt6 binding (``"mne[full-pyqt6]"``, equivalent to + ``"mne[full]"``), and without any Qt binding (``"mne[full-no-qt]"``), which may be useful + in certain situations by `Richard Höchenberger`_. (`#12628 `__) +- Adding argument ``'random'`` to :func:`~mne.epochs.equalize_epoch_counts` and to :meth:`~mne.Epochs.equalize_event_counts` to randomly select epochs or events. By `Mathieu Scheltienne`_. (`#12649 `__) +- Add new parameter ``ignore_marker_types`` to :func:`~mne.io.read_raw_brainvision` to ignore marker types (and only use marker descriptions) when reading BrainVision files, by `Clemens Brunner`_. (`#12652 `__) +- Added support for passing ``axes`` to :func:`mne.viz.plot_head_positions` when + ``mode='field'``, by `Eric Larson`_. (`#12655 `__) +- The HTML representation of :class:`~mne.Epochs` (visible e.g. in Jupyter or in :class:`~mne.Report`) now + indicates whether metadata is attached to the epochs, by `Richard Höchenberger`_. (`#12686 `__) +- Montage plots created with :meth:`~mne.channels.DigMontage.plot` now scale both the channel dots *and* channel names with the new ``scale`` parameter. The default is ``scale=1`` (factors less than 1 will scale down, whereas factors greater than 1 will scale up). The previous ``scale_factor`` parameter only affected marker size, and this parameter is now deprecated. By `Clemens Brunner`_. (`#12703 `__) +- Add :func:`~mne.stats.erp.compute_sme` to compute the analytical standardized measurement error (SME) as a data quality measure for ERP studies, by `Clemens Brunner`_. (`#12707 `__) +- Use :class:`python:datetime.date` for ``info["subject_info"]["birthday"]`` rather than + a tuple of ``(year, month, day)`` by `Eric Larson`_. (`#12720 `__) +- Add default ``spatial_colors="auto"`` to :func:`mne.viz.plot_evoked_white` and + :meth:`mne.Evoked.plot_white` to enable spatial colors by default, by `Eric Larson`_. (`#12725 `__) +- :func:`mne.minimum_norm.make_inverse_operator` and related functions now more robustly + warn if the whitener computed from the noise covariance has an incorrect rank, + by `Eric Larson`_. (`#12727 `__) +- When indexing :class:`~mne.Epochs` (e.g. by doing ``epochs[0]``), static code analysis tools like Pylance + should now be able to infer that the returned object is an epoch, too, and provide editor support + like automated code completions, by `Richard Höchenberger`_. (`#12733 `__) +- When using the ``data_path()`` in any dataset included in :py:mod:`mne.datasets`, + static analysis tools like Pylance will now correctly infer that a `pathlib.Path` will + be returned and provide editor support like automated code completions, by `Richard Höchenberger`_. (`#12734 `__) +- Add support for storing Fourier coefficients in :class:`mne.time_frequency.Spectrum`, + :class:`mne.time_frequency.EpochsSpectrum`, :class:`mne.time_frequency.SpectrumArray`, + and :class:`mne.time_frequency.EpochsSpectrumArray` objects, by `Thomas Binns`_. (`#12747 `__) + + +Other changes +------------- + +- Fixed issue template links by :newcontrib:`Michal Žák` (`#12600 `__) +- Enhance documentation on decimation filtering to prevent aliasing, by :newcontrib:`Xabier de Zuazo`. (`#12650 `__) +- Added `vulture `__ as a pre-commit hook and removed related dead code, by `Eric Larson`_. (`#12569 `__) +- Add link to BEst-Python in the list of related software. by `Ilian Azz`_. (`#12659 `__) +- Improved clarity of parameter documentation for `mne.decoding.SSD.fit`, by `Thomas Binns`_. (`#12664 `__) +- Disable the "Back to top" button in the documentation, by `Richard Höchenberger`_. (`#12688 `__) +- Improve argument ``ylim`` documentation through :class:`~mne.Evoked` plotting function and validate type to :class:`dict` or ``None`` to prevent misuage, by `Mathieu Scheltienne`_. (`#12697 `__) +- Code contributions are now measured using PRs and reported on the :ref:`contributors` + page, by `Eric Larson`_. (`#12774 `__) +- Authorship headers in MNE-Python code have been standardized, by `Eric Larson`_. (`#12781 `__) + +Authors +------- + +* Alex Rockhill +* Alexandre Gramfort +* Clemens Brunner +* Daniel McCloy +* Dimitri Papadopoulos Orfanos +* Eric Larson +* Farzin Negahbani+ +* George O'Neill +* Ilian AZZ +* Marijn van Vliet +* Mathieu Scheltienne +* Michal Žák+ +* Nabil Alibou +* Nicolas Fourcaud-Trocmé+ +* Noah Markowitz+ +* Ping-Keng Jao+ +* Qian Chu +* Richard Höchenberger +* Sammi Chekroud+ +* Scott Huberty +* Stefan Appelhoff +* Thomas S. Binns +* Xabier de Zuazo+ diff --git a/mne-python/source/doc/changes/v1.9.rst b/mne-python/source/doc/changes/v1.9.rst new file mode 100644 index 0000000000000000000000000000000000000000..0c6f7c1fddca7c07cb6bb354cadb901e8e5008a1 --- /dev/null +++ b/mne-python/source/doc/changes/v1.9.rst @@ -0,0 +1,128 @@ +.. _changes_1_9_0: + +Version 1.9.0 (2024-12-18) +========================== + +Dependencies +------------ + +- Minimum supported dependencies were updated in accordance with SPEC0_, most notably Python 3.10+ is now required. (`#12798 `__) +- Importing from ``mne.decoding`` now explicitly requires ``scikit-learn`` to be installed, + by `Eric Larson`_. (`#12834 `__) +- Compatibility improved for Python 3.13, by `Eric Larson`_. (`#13021 `__) + + +Bugfixes +-------- + +- Fix typos in the Spatio-Spectral Decomposition example, by :newcontrib:`Simon M. Hofmann`. (`#12924 `__) +- Fix duration calculation for the textual (``__repr__``) and html (``_repr_html_``, used by e.g. Jupyter) display of :class:`mne.io.Raw` instances. For example a duration of 1h is now displayed as ``00:01:00`` rather than ``00:59:60``. By :newcontrib:`Leonardo Rochael Almeida`. (`#12955 `__) +- Fix IndexError when loading CNT file does not have annotations, by :newcontrib:`Ziyi ZENG`. (`#12986 `__) +- Fix handling of MRI file-path in :class:`mne.SourceSpaces` and safeguard saving of :class:`pathlib.Path` with ``h5io`` by casting to :class:`str`, by `Mathieu Scheltienne`_. (`#12803 `__) +- Cast ``fwd["info"]`` to :class:`~mne.Info` and ``fwd["src"]`` to :class:`~mne.SourceSpaces` when loading a forward solution from an HDF5 file, by `Mathieu Scheltienne`_. (`#12804 `__) +- Fix bug where :meth:`mne.Epochs.compute_tfr` could not be used with the multitaper method and complex or phase outputs, by `Thomas Binns`_. (`#12842 `__) +- Fixed a bug where split FIF files that were read and then appended to other + :class:`mne.io.Raw` instances had their ``BAD boundary`` annotations incorrectly offset + in samples by the number of split files, by `Eric Larson`_. (`#12843 `__) +- Enforce SI units for Eyetracking data (eyegaze data should be radians of visual angle, not pixels. Pupil size data should be meters). + Updated tutorials so demonstrate how to convert data to SI units before analyses, by `Scott Huberty`_. (`#12846 `__) +- Prevent the ``colorbar`` parameter being ignored in topomap plots such as :meth:`mne.time_frequency.Spectrum.plot_topomap`, by `Thomas Binns`_. (`#12853 `__) +- Fix bug where invalid data types (e.g., ``np.ndarray``s) could be used in some + :class:`mne.io.Info` fields like ``info["subject_info"]["weight"]``, by `Eric Larson`_. (`#12875 `__) +- When creating a :class:`~mne.time_frequency.SpectrumArray`, the array shape check now + compares against the total of both 'good' and 'bad' channels in the provided + :class:`~mne.Info` (previously only good channels were checked), by + `Mathieu Scheltienne`_. (`#12877 `__) +- Fix bug where :ref:`mne coreg` would always show MEG channels even if the "MEG Sensors" checkbox was disabled, by `Eric Larson`_. (`#12884 `__) +- :class:`mne.Report` HDF5 files are now written in ``mode='a'`` (append) to allow users to store other data in the HDF5 files, by `Eric Larson`_. (`#12901 `__) +- Fix bug in :func:`mne.io.read_raw_gdf` when NumPy >= 2 is used, by `Clemens Brunner`_. (`#12909 `__) +- Allow exporting edf where a channel contains only constant values, by `Florian Hofer`_. (`#12911 `__) +- Fix a bug in :func:`mne.epochs.make_metadata`, where missing values in the columns + generated for ``keep_first`` and ``keep_last`` events were represented by empty strings, + while it should have been ``NA`` values, by `Richard Höchenberger`_. (`#12931 `__) +- Fix decimal places of :class:`float` ``mne.Evoked.nave`` in :meth:`mne.Evoked.plot` and :meth:`mne.Evoked.plot_image`, by `Gennadiy Belonosov`_. (`#12936 `__) +- Fix displayed units in representations of classes such as :class:`mne.io.Raw` to correctly use KiB, MiB, GiB, and so on, by `Clemens Brunner`_. (`#12962 `__) +- Gracefully handle invalid patient info when reading EDF files by `Scott Huberty`_. (`#12968 `__) +- Correct :func:`mne.io.read_raw_cnt` to read responses and fix exceptions by `Jacob Woessner`_. (`#13007 `__) +- Fix errant detection of software-rendered vs hardware-rendered MESA GL contexts in 3D rendering on Linux, by `Eric Larson`_. (`#13012 `__) +- Fix plot scaling for :meth:`Spectrum.plot(dB=True, amplitude=True) `, by `Daniel McCloy`_. (`#13036 `__) + + +API changes by deprecation +-------------------------- + +- Deprecate ``average`` parameter in ``plot_filters`` and ``plot_patterns`` methods of the :class:`mne.decoding.CSP` and :class:`mne.decoding.SPoC` classes, by `Thomas Binns`_. (`#12829 `__) +- Deprecate ``subject`` parameter in favor of ``subjects`` in :func:`mne.datasets.eegbci.load_data`, by `Stefan Appelhoff`_. (`#12918 `__) + + +New features +------------ + +- Added support for ``sensor_scales`` to :meth:`mne.viz.Brain.add_sensors` and :func:`mne.viz.plot_alignment`, by :newcontrib:`Alex Lepauvre`. (`#12805 `__) +- Add convenience :attr:`mne.io.Raw.duration` property to centralize duration calculation for the textual (``__repr__``) and html (``_repr_html_``, used by e.g. Jupyter) display of :class:`mne.io.Raw` instances, by :newcontrib:`Leonardo Rochael Almeida`. (`#12955 `__) +- Add option to :func:`mne.preprocessing.fix_stim_artifact` to use baseline average to flatten TMS pulse artifact by `Fahimeh Mamashli`_ and `Padma Sundaram`_ and `Mohammad Daneshzand`_. (`#6915 `__) +- Add support for `dict` type argument ``ref_channels`` to :func:`mne.set_eeg_reference`, to allow flexible re-referencing (e.g. ``raw.set_eeg_reference(ref_channels={'A1': ['A2', 'A3']})`` will set the new A1 data to be ``A1 - mean(A2, A3)``), by `Alex Lepauvre`_ and `Qian Chu`_ and `Daniel McCloy`_. (`#12366 `__) +- Add reader for ANT Neuro files in the ``*.cnt`` format with :func:`~mne.io.read_raw_ant`, by `Mathieu Scheltienne`_, `Eric Larson`_ and `Proloy Das`_. (`#12792 `__) +- Add support for a :class:`mne.transforms.Transform` in the argument ``trans`` of the coregistration GUI called with :func:`mne.gui.coregistration`, by `Mathieu Scheltienne`_. (`#12801 `__) +- :meth:`~mne.io.Raw` and :meth:`~mne.Epochs.save` now return the path to the saved file(s), by `Victor Ferat`_. (`#12811 `__) +- :func:`mne.channels.read_custom_montage` may now read a newer version of the ``.elc`` ASA Electrode file format, by `Stefan Appelhoff`_. (`#12830 `__) +- Added the ``title`` argument to :func:`mne.viz.create_3d_figure`, and + ``color`` and ``position`` arguments to :func:`mne.viz.set_3d_title`, by `Eric Larson`_. (`#12871 `__) +- Improved reporting and plotting options: + + - :meth:`mne.Report.add_projs` can now plot with :func:`mne.viz.plot_projs_joint` rather than :func:`mne.viz.plot_projs_topomap` + - :class:`mne.Report` now has attributes ``img_max_width`` and ``img_max_res`` that can be used to control image scaling. + - :class:`mne.Report` now has an attribute ``collapse`` that allows collapsing sections and/or subsections by default. + - :func:`mne.viz.plot_head_positions` now has a ``totals=True`` option to show the total distance and angle of the head. + + Changes by `Eric Larson`_. (`#12901 `__) +- Added the ``psd_args`` argument to :func:`mne.viz.plot_ica_sources` and :meth:`mne.preprocessing.ICA.plot_sources`, by `Richard Scholz`_. (`#12912 `__) +- Add ability to use :func:`mne.preprocessing.compute_fine_calibration` with non-Neuromag-style systems, as well as options to control the bad-angle and error tolerances, by `Eric Larson`_. (`#12966 `__) +- Add support for ``uint16_codec`` argument in :func:`mne.io.read_raw_eeglab` when ``pymatreader`` (which already supported this argument previously) is not installed, by `Clemens Brunner`_. (`#12971 `__) +- Added support for saving and loading channel names from FIF in :meth:`mne.channels.DigMontage.save` and :meth:`mne.channels.read_dig_fif` and added the convention that they should be saved as ``-dig.fif``, by `Eric Larson`_. (`#13003 `__) +- Add new :meth:`Raw.rescale ` method to rescale the data in place, by `Clemens Brunner`_. (`#13018 `__) + + +Other changes +------------- + +- Fix a mistake in :ref:`tut-artifact-regression` where the wrong regression coefficients were applied, by :newcontrib:`Jacob Phelan`. (`#12978 `__) +- Use custom code in :func:`mne.sys_info` to get the amount of physical memory and a more informative CPU name instead of using the ``psutil`` package, by `Clemens Brunner`_. (`#12787 `__) +- Improve documentation clarity of ``fit_transform`` methods for :class:`mne.decoding.SSD`, :class:`mne.decoding.CSP`, and :class:`mne.decoding.SPoC` classes, by `Thomas Binns`_. (`#12827 `__) +- Improve handling of filenames in ``raw.filenames`` by using :class:`~pathlib.Path` instead of :class:`str`, by `Mathieu Scheltienne`_. (`#12843 `__) +- Improve automatic figure scaling of :func:`mne.viz.plot_events`, and event_id and count overview legend when a high amount of unique events is supplied, by `Stefan Appelhoff`_. (`#12844 `__) +- :meth:`mne.preprocessing.ICA.find_bads_muscle` can now be run when passing an ``inst`` without sensor positions. However, it will just use the first of three criteria (slope) to find muscle-related ICA components, by `Stefan Appelhoff`_. (`#12862 `__) +- Update governance model, by `Daniel McCloy`_. (`#12896 `__) +- Improve the :ref:`tut-autogenerate-metadata`, by `Clemens Brunner`_ and `Richard Höchenberger`_. (`#12931 `__) +- Mention some gotchas that arise from the fact that by default, we pool across dipole orientations when performing source estimation, by `Marijn van Vliet`_ (`#12960 `__) +- Repository CI security is now audited using `zizmor `__, by `Eric Larson`_. (`#13011 `__) + +Authors +------- + +* Alex Lepauvre+ +* Britta Westner +* Clemens Brunner +* Daniel McCloy +* Eric Larson +* Fahimeh Mamashli +* Florian Hofer +* Gennadiy Belonosov +* Jacob Phelan +* Jacob Woessner +* Leonardo Rochael Almeida+ +* Mainak Jas +* Marijn van Vliet +* Mathieu Scheltienne +* Proloy Das +* Qian Chu +* Richard Höchenberger +* Richard Scholz +* Santeri Ruuskanen +* Scott Huberty +* Simon M. Hofmann+ +* Stefan Appelhoff +* Thomas Grainger +* Thomas S. Binns +* Victor Férat +* Ziyi ZENG+ diff --git a/mne-python/source/doc/conf.py b/mne-python/source/doc/conf.py new file mode 100644 index 0000000000000000000000000000000000000000..0d9fe79346e5d3ce2f34498ec20f0f7c146be33f --- /dev/null +++ b/mne-python/source/doc/conf.py @@ -0,0 +1,1761 @@ +"""Configuration file for the Sphinx documentation builder. + +This file only contains a selection of the most common options. For a full +list see the documentation: +https://www.sphinx-doc.org/en/master/usage/configuration.html +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import faulthandler +import os +import subprocess +import sys +from datetime import datetime, timezone +from importlib.metadata import metadata +from pathlib import Path + +import matplotlib +import sphinx +from intersphinx_registry import get_intersphinx_mapping +from numpydoc import docscrape +from sphinx.config import is_serializable +from sphinx.domains.changeset import versionlabels +from sphinx_gallery.sorting import ExplicitOrder + +import mne +import mne.html_templates._templates +from mne.tests.test_docstring_parameters import error_ignores +from mne.utils import ( + linkcode_resolve, + run_subprocess, +) + +assert linkcode_resolve is not None # avoid flake warnings, used by numpydoc +matplotlib.use("agg") +faulthandler.enable() +os.environ["_MNE_BROWSER_NO_BLOCK"] = "true" +os.environ["MNE_BROWSER_OVERVIEW_MODE"] = "hidden" +os.environ["MNE_BROWSER_THEME"] = "light" +os.environ["MNE_3D_OPTION_THEME"] = "light" +# https://numba.readthedocs.io/en/latest/reference/deprecation.html#deprecation-of-old-style-numba-captured-errors # noqa: E501 +os.environ["NUMBA_CAPTURED_ERRORS"] = "new_style" +mne.html_templates._templates._COLLAPSED = True # collapse info _repr_html_ + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +curpath = Path(__file__).parent.resolve(strict=True) +sys.path.append(str(curpath / "sphinxext")) + +from credit_tools import generate_credit_rst # noqa: E402 +from mne_doc_utils import report_scraper, reset_warnings, sphinx_logger # noqa: E402 + +# -- Project information ----------------------------------------------------- + +project = "MNE" +td = datetime.now(tz=timezone.utc) + +# We need to triage which date type we use so that incremental builds work +# (Sphinx looks at variable changes and rewrites all files if some change) +project_copyright = ( + f'2012–{td.year}, MNE Developers. Last updated .\n' # noqa: E501 + """""" +) +if os.getenv("MNE_FULL_DATE", "false").lower() != "true": + project_copyright = f"2012–{td.year}, MNE Developers. Last updated locally." + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The full version, including alpha/beta/rc tags. +release = mne.__version__ +sphinx_logger.info(f"Building documentation for MNE {release} ({mne.__file__})") +# The short X.Y version. +version = ".".join(release.split(".")[:2]) + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = "6.0" + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + # builtin + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.coverage", + "sphinx.ext.doctest", + "sphinx.ext.graphviz", + "sphinx.ext.intersphinx", + "sphinx.ext.linkcode", + "sphinx.ext.mathjax", + "sphinx.ext.todo", + # contrib + "matplotlib.sphinxext.plot_directive", + "numpydoc", + "sphinx_copybutton", + "sphinx_design", + "sphinx_gallery.gen_gallery", + "sphinxcontrib.bibtex", + "sphinxcontrib.youtube", + "sphinxcontrib.towncrier.ext", + # homegrown + "contrib_avatars", + "gen_commands", + "gen_names", + "gh_substitutions", + "mne_substitutions", + "newcontrib_substitutions", + "unit_role", + "related_software", + "directive_formatting", +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ["_templates"] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. + +# NB: changes here should also be made to the linkcheck target in the Makefile +exclude_patterns = ["_includes", "changes/dev"] + +# The suffix of source filenames. +source_suffix = ".rst" + +# The main toctree document. +master_doc = "index" + +# List of documents that shouldn't be included in the build. +unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ["_build"] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +default_role = "py:obj" + +# A list of ignored prefixes for module index sorting. +modindex_common_prefix = ["mne."] + +# -- Sphinx-Copybutton configuration ----------------------------------------- +copybutton_prompt_text = r">>> |\.\.\. |\$ " +copybutton_prompt_is_regexp = True + +# -- sphinxcontrib-towncrier configuration ----------------------------------- + +towncrier_draft_working_directory = str(curpath.parent) + +# -- Intersphinx configuration ----------------------------------------------- + +intersphinx_mapping = { + # More niche so didn't upstream to intersphinx_registry + "nitime": ("https://nipy.org/nitime/", None), + "mne_bids": ("https://mne.tools/mne-bids/stable", None), + "mne-connectivity": ("https://mne.tools/mne-connectivity/stable", None), + "mne-gui-addons": ("https://mne.tools/mne-gui-addons", None), + "picard": ("https://mind-inria.github.io/picard/", None), + "eeglabio": ("https://eeglabio.readthedocs.io/en/latest", None), + "pybv": ("https://pybv.readthedocs.io/en/latest", None), +} +intersphinx_mapping.update( + get_intersphinx_mapping( + packages=set( + """ +imageio matplotlib numpy pandas python scipy statsmodels sklearn numba joblib nibabel +seaborn patsy pyvista dipy nilearn pyqtgraph +""".strip().split() + ), + ) +) + + +# NumPyDoc configuration ----------------------------------------------------- + +# Define what extra methods numpydoc will document +docscrape.ClassDoc.extra_public_methods = mne.utils._doc_special_members +numpydoc_class_members_toctree = False +numpydoc_show_inherited_class_members = { + "mne.Forward": False, + "mne.Projection": False, + "mne.SourceSpaces": False, +} +numpydoc_attributes_as_param_list = True +numpydoc_xref_param_type = True +numpydoc_xref_aliases = { + # Python + "file-like": ":term:`file-like `", + "iterator": ":term:`iterator `", + "path-like": ":term:`path-like`", + "array-like": ":term:`array_like `", + "Path": ":class:`python:pathlib.Path`", + "bool": ":ref:`bool `", + # Matplotlib + "colormap": ":ref:`colormap `", + "color": ":doc:`color `", + "Axes": "matplotlib.axes.Axes", + "Figure": "matplotlib.figure.Figure", + "Axes3D": "mpl_toolkits.mplot3d.axes3d.Axes3D", + "ColorbarBase": "matplotlib.colorbar.ColorbarBase", + # sklearn + "LeaveOneOut": "sklearn.model_selection.LeaveOneOut", + "MetadataRequest": "sklearn.utils.metadata_routing.MetadataRequest", + "estimator": "sklearn.base.BaseEstimator", + # joblib + "joblib.Parallel": "joblib.Parallel", + # nibabel + "Nifti1Image": "nibabel.nifti1.Nifti1Image", + "Nifti2Image": "nibabel.nifti2.Nifti2Image", + "SpatialImage": "nibabel.spatialimages.SpatialImage", + # MNE + "Label": "mne.Label", + "Forward": "mne.Forward", + "Evoked": "mne.Evoked", + "Info": "mne.Info", + "SourceSpaces": "mne.SourceSpaces", + "Epochs": "mne.Epochs", + "Layout": "mne.channels.Layout", + "EvokedArray": "mne.EvokedArray", + "BiHemiLabel": "mne.BiHemiLabel", + "AverageTFR": "mne.time_frequency.AverageTFR", + "AverageTFRArray": "mne.time_frequency.AverageTFRArray", + "EpochsTFR": "mne.time_frequency.EpochsTFR", + "EpochsTFRArray": "mne.time_frequency.EpochsTFRArray", + "RawTFR": "mne.time_frequency.RawTFR", + "RawTFRArray": "mne.time_frequency.RawTFRArray", + "Raw": "mne.io.Raw", + "ICA": "mne.preprocessing.ICA", + "Covariance": "mne.Covariance", + "Annotations": "mne.Annotations", + "DigMontage": "mne.channels.DigMontage", + "VectorSourceEstimate": "mne.VectorSourceEstimate", + "VolSourceEstimate": "mne.VolSourceEstimate", + "VolVectorSourceEstimate": "mne.VolVectorSourceEstimate", + "MixedSourceEstimate": "mne.MixedSourceEstimate", + "MixedVectorSourceEstimate": "mne.MixedVectorSourceEstimate", + "SourceEstimate": "mne.SourceEstimate", + "Projection": "mne.Projection", + "ConductorModel": "mne.bem.ConductorModel", + "Dipole": "mne.Dipole", + "DipoleFixed": "mne.DipoleFixed", + "InverseOperator": "mne.minimum_norm.InverseOperator", + "CrossSpectralDensity": "mne.time_frequency.CrossSpectralDensity", + "SourceMorph": "mne.SourceMorph", + "Xdawn": "mne.preprocessing.Xdawn", + "Report": "mne.Report", + "TimeDelayingRidge": "mne.decoding.TimeDelayingRidge", + "Vectorizer": "mne.decoding.Vectorizer", + "UnsupervisedSpatialFilter": "mne.decoding.UnsupervisedSpatialFilter", + "TemporalFilter": "mne.decoding.TemporalFilter", + "SSD": "mne.decoding.SSD", + "Scaler": "mne.decoding.Scaler", + "SPoC": "mne.decoding.SPoC", + "PSDEstimator": "mne.decoding.PSDEstimator", + "LinearModel": "mne.decoding.LinearModel", + "FilterEstimator": "mne.decoding.FilterEstimator", + "EMS": "mne.decoding.EMS", + "CSP": "mne.decoding.CSP", + "Beamformer": "mne.beamformer.Beamformer", + "Transform": "mne.transforms.Transform", + "Coregistration": "mne.coreg.Coregistration", + "Figure3D": "mne.viz.Figure3D", + "EOGRegression": "mne.preprocessing.EOGRegression", + "Spectrum": "mne.time_frequency.Spectrum", + "EpochsSpectrum": "mne.time_frequency.EpochsSpectrum", + "EpochsFIF": "mne.Epochs", + "EpochsEEGLAB": "mne.Epochs", + "EpochsKIT": "mne.Epochs", + "RawANT": "mne.io.Raw", + "RawBOXY": "mne.io.Raw", + "RawBrainVision": "mne.io.Raw", + "RawBTi": "mne.io.Raw", + "RawCTF": "mne.io.Raw", + "RawCurry": "mne.io.Raw", + "RawEDF": "mne.io.Raw", + "RawEEGLAB": "mne.io.Raw", + "RawEGI": "mne.io.Raw", + "RawEximia": "mne.io.Raw", + "RawEyelink": "mne.io.Raw", + "RawFIL": "mne.io.Raw", + "RawGDF": "mne.io.Raw", + "RawHitachi": "mne.io.Raw", + "RawKIT": "mne.io.Raw", + "RawNedf": "mne.io.Raw", + "RawNeuralynx": "mne.io.Raw", + "RawNihon": "mne.io.Raw", + "RawMEF": "mne.io.Raw", + "RawNIRX": "mne.io.Raw", + "RawPersyst": "mne.io.Raw", + "RawSNIRF": "mne.io.Raw", + "Calibration": "mne.preprocessing.eyetracking.Calibration", + # dipy + "dipy.align.AffineMap": "dipy.align.imaffine.AffineMap", + "dipy.align.DiffeomorphicMap": "dipy.align.imwarp.DiffeomorphicMap", +} +numpydoc_xref_ignore = { + # words + "and", + "as", + "between", + "data", + "instance", + "instances", + "input", + "of", + "default", + "same", + "shape", + "or", + "the", + "with", + "length", + "pair", + "matplotlib", + "optional", + "kwargs", + "in", + "dtype", + "object", + # shapes + "n_vertices", + "n_faces", + "n_channels", + "m", + "n", + "n_events", + "n_colors", + "n_times", + "obj", + "n_chan", + "n_epochs", + "n_picks", + "n_ch_groups", + "n_dipoles", + "n_ica_components", + "n_pos", + "n_node_names", + "n_tapers", + "n_signals", + "n_step", + "n_freqs", + "wsize", + "Tx", + "M", + "N", + "p", + "q", + "r", + "n_observations", + "n_regressors", + "n_cols", + "n_frequencies", + "n_tests", + "n_samples", + "n_peaks", + "n_permutations", + "nchan", + "n_points", + "n_features", + "n_parts", + "n_features_new", + "n_components", + "n_labels", + "n_events_in", + "n_splits", + "n_scores", + "n_outputs", + "n_trials", + "n_estimators", + "n_tasks", + "nd_features", + "n_classes", + "n_targets", + "n_slices", + "n_hpi", + "n_fids", + "n_elp", + "n_pts", + "n_tris", + "n_nodes", + "n_nonzero", + "n_events_out", + "n_segments", + "n_orient_inv", + "n_orient_fwd", + "n_orient", + "n_dipoles_lcmv", + "n_dipoles_fwd", + "n_picks_ref", + "n_coords", + "n_meg", + "n_good_meg", + "n_moments", + "n_patterns", + "n_new_events", + # sklearn subclasses + "mapping", + "to", + "any", + "pandas", + "polars", + "default", + # unlinkable + "CoregistrationUI", + "mne_qt_browser.figure.MNEQtBrowser", + # pooch, since its website is unreliable and users will rarely need the links + "pooch.Unzip", + "pooch.Untar", + "pooch.HTTPDownloader", +} +numpydoc_validate = True +numpydoc_validation_checks = {"all"} | set(error_ignores) +numpydoc_validation_exclude = { # set of regex + # dict subclasses + r"\.clear", + r"\.get$", + r"\.copy$", + r"\.fromkeys", + r"\.items", + r"\.keys", + r"\.move_to_end", + r"\.pop", + r"\.popitem", + r"\.setdefault", + r"\.update", + r"\.values", + # list subclasses + r"\.append", + r"\.count", + r"\.extend", + r"\.index", + r"\.insert", + r"\.remove", + r"\.sort", + # we currently don't document these properly (probably okay) + r"\.__getitem__", + r"\.__contains__", + r"\.__hash__", + r"\.__mul__", + r"\.__sub__", + r"\.__add__", + r"\.__iter__", + r"\.__div__", + r"\.__neg__", + # copied from sklearn + r"mne\.utils\.deprecated", +} + + +# -- Sphinx-gallery configuration -------------------------------------------- + +examples_dirs = ["../tutorials", "../examples"] +gallery_dirs = ["auto_tutorials", "auto_examples"] +os.environ["_MNE_BUILDING_DOC"] = "true" + +scrapers = ( + "matplotlib", + "mne_doc_utils.gui_scraper", + "mne_doc_utils.brain_scraper", + "pyvista", + "mne_doc_utils.report_scraper", + "mne_doc_utils.mne_qt_browser_scraper", +) + +compress_images = ("images", "thumbnails") +# let's make things easier on Windows users +# (on Linux and macOS it's easy enough to require this) +if sys.platform.startswith("win"): + try: + subprocess.check_call(["optipng", "--version"]) + except Exception: + compress_images = () + +sphinx_gallery_parallel = int(os.getenv("MNE_DOC_BUILD_N_JOBS", "1")) +sphinx_gallery_conf = { + "doc_module": ("mne",), + "reference_url": dict(mne=None), + "examples_dirs": examples_dirs, + "subsection_order": ExplicitOrder( + [ + "../examples/io/", + "../examples/simulation/", + "../examples/preprocessing/", + "../examples/visualization/", + "../examples/time_frequency/", + "../examples/stats/", + "../examples/decoding/", + "../examples/connectivity/", + "../examples/forward/", + "../examples/inverse/", + "../examples/realtime/", + "../examples/datasets/", + "../tutorials/intro/", + "../tutorials/io/", + "../tutorials/raw/", + "../tutorials/preprocessing/", + "../tutorials/epochs/", + "../tutorials/evoked/", + "../tutorials/time-freq/", + "../tutorials/forward/", + "../tutorials/inverse/", + "../tutorials/stats-sensor-space/", + "../tutorials/stats-source-space/", + "../tutorials/machine-learning/", + "../tutorials/clinical/", + "../tutorials/simulation/", + "../tutorials/sample-datasets/", + "../tutorials/visualization/", + "../tutorials/misc/", + ] + ), + "gallery_dirs": gallery_dirs, + "default_thumb_file": os.path.join("_static", "mne_helmet.png"), + "backreferences_dir": "generated", + "plot_gallery": "True", # Avoid annoying Unicode/bool default warning + "thumbnail_size": (160, 112), + "remove_config_comments": True, + "min_reported_time": 1.0, + "abort_on_example_error": False, + "reset_modules": ( + "matplotlib", + "mne_doc_utils.reset_modules", + ), # called w/each script + "reset_modules_order": "both", + "image_scrapers": scrapers, + "show_memory": sys.platform == "linux" and sphinx_gallery_parallel == 1, + "line_numbers": False, # messes with style + "within_subsection_order": "FileNameSortKey", + "capture_repr": ("_repr_html_",), + "junit": os.path.join("..", "test-results", "sphinx-gallery", "junit.xml"), + "matplotlib_animations": True, + "compress_images": compress_images, + "filename_pattern": "^((?!sgskip).)*$", + "exclude_implicit_doc": { + r"mne\.io\.read_raw_fif", + r"mne\.io\.Raw", + r"mne\.Epochs", + r"mne.datasets.*", + }, + "show_api_usage": "unused", + "api_usage_ignore": ( + "(" + ".*__.*__|" # built-ins + ".*Base.*|.*Array.*|mne.Vector.*|mne.Mixed.*|mne.Vol.*|" # inherited + "mne.coreg.Coregistration.*|" # GUI + # common + ".*utils.*|.*verbose()|.*copy()|.*update()|.*save()|" + ".*get_data()|" + # mixins + ".*add_channels()|.*add_reference_channels()|" + ".*anonymize()|.*apply_baseline()|.*apply_function()|" + ".*apply_hilbert()|.*as_type()|.*decimate()|" + ".*drop()|.*drop_channels()|.*drop_log_stats()|" + ".*export()|.*get_channel_types()|" + ".*get_montage()|.*interpolate_bads()|.*next()|" + ".*pick()|.*pick_channels()|.*pick_types()|" + ".*plot_sensors()|.*rename_channels()|" + ".*reorder_channels()|.*savgol_filter()|" + ".*set_eeg_reference()|.*set_channel_types()|" + ".*set_meas_date()|.*set_montage()|.*shift_time()|" + ".*time_as_index()|.*to_data_frame()|" + # dictionary inherited + ".*clear()|.*fromkeys()|.*get()|.*items()|" + ".*keys()|.*pop()|.*popitem()|.*setdefault()|" + ".*values()|" + # sklearn inherited + ".*apply()|.*decision_function()|.*fit()|" + ".*fit_transform()|.*get_params()|.*predict()|" + ".*predict_proba()|.*set_params()|.*transform()|" + # I/O, also related to mixins + ".*.remove.*|.*.write.*)" + ), + "copyfile_regex": r".*index\.rst", # allow custom index.rst files + "parallel": sphinx_gallery_parallel, +} +assert is_serializable(sphinx_gallery_conf) +# Files were renamed from plot_* with: +# find . -type f -name 'plot_*.py' -exec sh -c 'x="{}"; xn=`basename "${x}"`; git mv "$x" `dirname "${x}"`/${xn:5}' \; # noqa + + +def append_attr_meth_examples(app, what, name, obj, options, lines): + """Append SG examples backreferences to method and attr docstrings.""" + # NumpyDoc nicely embeds method and attribute docstrings for us, but it + # does not respect the autodoc templates that would otherwise insert + # the .. include:: lines, so we need to do it. + # Eventually this could perhaps live in SG. + if what in ("attribute", "method"): + size = os.path.getsize( + os.path.join( + os.path.dirname(__file__), + "generated", + f"{name}.examples", + ) + ) + if size > 0: + lines += """ +.. _sphx_glr_backreferences_{1}: + +.. rubric:: Examples using ``{0}``: + +.. minigallery:: {1} + +""".format(name.split(".")[-1], name).split("\n") + + +def fix_sklearn_inherited_docstrings(app, what, name, obj, options, lines): + """Fix sklearn docstrings because they use autolink and we do not.""" + if ( + name.startswith("mne.decoding.") or name.startswith("mne.preprocessing.Xdawn") + ) and name.endswith( + ( + ".get_metadata_routing", + ".fit", + ".fit_transform", + ".set_output", + ".transform", + ) + ): + if ":Parameters:" in lines: + loc = lines.index(":Parameters:") + else: + loc = lines.index(":Returns:") + lines.insert(loc, "") + lines.insert(loc, ".. default-role:: autolink") + lines.insert(loc, "") + + +# -- Other extension configuration ------------------------------------------- + +# Consider using http://magjac.com/graphviz-visual-editor for this +graphviz_dot_args = [ + "-Gsep=-0.5", + "-Gpad=0.5", + "-Nshape=box", + "-Nfontsize=20", + "-Nfontname=Open Sans,Arial", +] +graphviz_output_format = "svg" # for API usage diagrams +user_agent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Mobile Safari/537.36" # noqa: E501 +# Can eventually add linkcheck_request_headers if needed +linkcheck_ignore = [ # will be compiled to regex + # 403 Client Error: Forbidden + "https://doi.org/10.1002/", # onlinelibrary.wiley.com/doi/10.1002/hbm + "https://doi.org/10.1017/", # cambridge.org + "https://doi.org/10.1016/", # neuroimage + "https://doi.org/10.1021/", # pubs.acs.org/doi/abs + "https://doi.org/10.1063/", # pubs.aip.org/aip/jap + "https://doi.org/10.1073/", # pnas.org + "https://doi.org/10.1080/", # www.tandfonline.com + "https://doi.org/10.1088/", # www.tandfonline.com + "https://doi.org/10.1090/", # ams.org + "https://doi.org/10.1093/", # academic.oup.com/sleep/ + "https://doi.org/10.1098/", # royalsocietypublishing.org + "https://doi.org/10.1101/", # www.biorxiv.org + "https://doi.org/10.1103/", # journals.aps.org/rmp + "https://doi.org/10.1111/", # onlinelibrary.wiley.com/doi/10.1111/psyp + "https://doi.org/10.1126/", # www.science.org + "https://doi.org/10.1137/", # epubs.siam.org + "https://doi.org/10.1145/", # dl.acm.org + "https://doi.org/10.1155/", # www.hindawi.com/journals/cin + "https://doi.org/10.1161/", # www.ahajournals.org + "https://doi.org/10.1162/", # direct.mit.edu/neco/article/ + "https://doi.org/10.1167/", # jov.arvojournals.org + "https://doi.org/10.1177/", # journals.sagepub.com + "https://doi.org/10.1523/", # jneurosci.org + "https://doi.org/10.3109/", # www.tandfonline.com + "https://doi.org/10.3390/", # mdpi.com + "https://hms.harvard.edu/", # doc/funding.rst + "https://stackoverflow.com/questions/21752259/python-why-pickle", # doc/help/faq + "https://blender.org", + "https://home.alexk101.dev", + "https://www.mq.edu.au/", + "https://www.biorxiv.org/content/10.1101/", # biorxiv.org + "https://www.researchgate.net/profile/", + "https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html", + r"https://scholar.google.com/scholar\?cites=12188330066413208874&as_ylo=2014", + r"https://scholar.google.com/scholar\?cites=1521584321377182930&as_ylo=2013", + "https://www.research.chop.edu/imaging", + "http://prdownloads.sourceforge.net/optipng", + "https://sourceforge.net/projects/aespa/files/", + "https://sourceforge.net/projects/ezwinports/files/", + r"https://.*\.sourceforge\.net/", + "https://www.cogsci.nl/smathot", + "https://www.mathworks.com/products/compiler/matlab-runtime.html", + "https://medicine.umich.edu/dept/khri/ross-maddox-phd", + "http://blog.kaggle.com/2015/08/12/july-2015-scripts-of-the-week", + # 500 server error + "https://openwetware.org/wiki/Beauchamp:FreeSurfer", + # 503 Server error + "https://hal.archives-ouvertes.fr/hal-01848442", + # Read timed out + "http://www.cs.ucl.ac.uk/staff/d.barber/brml", + "https://www.cea.fr", + "http://www.humanconnectome.org/data", + "https://www.mail-archive.com/freesurfer@nmr.mgh.harvard.edu", + "https://surfer.nmr.mgh.harvard.edu/fswiki/mri_normalize", + "https://launchpad.net", + # Max retries exceeded + "https://doi.org/10.7488/ds/1556", + "https://datashare.is.ed.ac.uk/handle/10283", + "https://imaging.mrc-cbu.cam.ac.uk/imaging/MniTalairach", + "https://www.nyu.edu/", + # Too slow + "https://speakerdeck.com/dengemann/", + "https://www.dtu.dk/english/service/phonebook/person", + "https://www.gnu.org/software/make/", + "https://www.macports.org/", + "https://hastie.su.domains/CASI", + # SSL problems sometimes + "http://ilabs.washington.edu", + "https://psychophysiology.cpmc.columbia.edu", + "https://erc.easme-web.eu", + "https://www.crnl.fr", + # Not rendered by linkcheck builder + r"ides\.html", +] +linkcheck_anchors = False # saves a bit of time +linkcheck_timeout = 15 # some can be quite slow +linkcheck_retries = 3 +linkcheck_report_timeouts_as_broken = False + +# autodoc / autosummary +autosummary_generate = True +autodoc_default_options = {"inherited-members": None} + +# sphinxcontrib-bibtex +bibtex_bibfiles = ["./references.bib"] +bibtex_style = "unsrt" +bibtex_footbibliography_header = "" + + +# -- Nitpicky ---------------------------------------------------------------- + +nitpicky = True +show_warning_types = True +nitpick_ignore = [ + ("py:class", "None. Remove all items from D."), + ( + "py:class", + "v, remove specified key and return the corresponding value.", + ), # noqa: E501 + ("py:class", "an object providing a view on D's values"), + ("py:class", "a shallow copy of D"), + ("py:class", "(k, v), remove and return some (key, value) pair as a"), + ("py:class", "_FuncT"), # type hint used in @verbose decorator + ("py:class", "mne.utils._logging._FuncT"), + ("py:class", "None. Remove all items from od."), +] +nitpick_ignore_regex = [ + ("py:class", "a set-like object providing a view on D's (items|keys)"), + ("py:class", r"None\. Update D from (dict|mapping)/iterable E and F\."), + # Classes whose methods we purposefully do not document + ("py:.*", r"mne\.io\.BaseRaw.*"), # use mne.io.Raw + ("py:.*", r"mne\.BaseEpochs.*"), # use mne.Epochs + # Type hints for undocumented types + ("py:.*", r"mne\.io\..*\.Raw.*"), # RawEDF etc. + ("py:.*", r"mne\.epochs\.EpochsFIF.*"), + ("py:.*", r"mne\.io\..*\.Epochs.*"), # EpochsKIT etc. + ( # BaseRaw attributes are documented in Raw + "py:obj", + "(filename|metadata|proj|times|tmax|tmin|annotations|ch_names" + "|compensation_grade|duration|filenames|first_samp|first_time" + "|last_samp|n_times|proj|times|tmax|tmin)", + ), +] +suppress_warnings = [ + "image.nonlocal_uri", # we intentionally link outside +] + + +# -- Sphinx hacks / overrides ------------------------------------------------ + +versionlabels["versionadded"] = sphinx.locale._("New in v%s") + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "pydata_sphinx_theme" + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +switcher_version_match = "dev" if ".dev" in release else version +html_theme_options = { + "icon_links": [ + dict( + name="Discord (office hours)", + url="https://discord.gg/rKfvxTuATa", + icon="fa-brands fa-discord fa-fw", + ), + dict( + name="Mastodon", + url="https://fosstodon.org/@mne", + icon="fa-brands fa-mastodon fa-fw", + attributes=dict(rel="me"), + ), + dict( + name="Q&A Forum", + url="https://mne.discourse.group/", + icon="fa-brands fa-discourse fa-fw", + ), + dict( + name="Code Repository", + url="https://github.com/mne-tools/mne-python", + icon="fa-brands fa-github fa-fw", + ), + dict( + name="Sponsor us on GitHub", + url="https://github.com/sponsors/mne-tools", + icon="fa-regular fa-heart fa-fw", + ), + dict( + name="Donate via OpenCollective", + url="https://opencollective.com/mne-python", + icon="fa-custom fa-opencollective fa-fw", + ), + ], + "icon_links_label": "External Links", # for screen reader + "use_edit_page_button": False, + "navigation_with_keys": False, + "show_toc_level": 1, + "article_header_start": [], # disable breadcrumbs + "navbar_end": [ + "theme-switcher", + "version-switcher", + "navbar-icon-links", + ], + "navbar_align": "left", + "navbar_persistent": ["search-button"], + "footer_start": ["copyright"], + "secondary_sidebar_items": ["page-toc", "edit-this-page"], + "analytics": dict(google_analytics_id="G-5TBCPCRB6X"), + "switcher": { + "json_url": "https://mne.tools/dev/_static/versions.json", + "version_match": switcher_version_match, + }, + "back_to_top_button": False, +} + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +html_logo = "_static/mne_logo_small.svg" + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +html_favicon = "_static/favicon.ico" + + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ["_static"] +html_css_files = [ + "style.css", +] +html_js_files = [ + ("js/custom-icons.js", {"defer": "defer"}), +] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +html_extra_path = [ + "contributing.html", + "documentation.html", + "getting_started.html", + "install_mne_python.html", +] + +# Custom sidebar templates, maps document names to template names. +html_sidebars = { + "index": ["sidebar-quicklinks.html"], +} + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = False +html_copy_source = False + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +html_show_sphinx = False + +# accommodate different logo shapes (width values in rem) +xs = "2" +sm = "2.5" +md = "3" +lg = "4.5" +xl = "5" +xxl = "6" +# variables to pass to HTML templating engine +html_context = { + "default_mode": "auto", + # next 3 are for the "edit this page" button + "github_user": "mne-tools", + "github_repo": "mne-python", + "github_version": "main", + "doc_path": "doc", + "funders": [ + dict(img="nih.svg", size="3", title="National Institutes of Health"), + dict(img="nsf.png", size="3.5", title="US National Science Foundation"), + dict( + img="erc.svg", + size="3.5", + title="European Research Council", + klass="only-light", + ), + dict( + img="erc-dark.svg", + size="3.5", + title="European Research Council", + klass="only-dark", + ), + dict(img="doe.svg", size="3", title="US Department of Energy"), + dict(img="anr.svg", size="3.5", title="Agence Nationale de la Recherche"), + dict( + img="cds.svg", + size="1.75", + title="Paris-Saclay Center for Data Science", + klass="only-light", + ), + dict( + img="cds-dark.svg", + size="1.75", + title="Paris-Saclay Center for Data Science", + klass="only-dark", + ), + dict(img="google.svg", size="2.25", title="Google"), + dict(img="amazon.svg", size="2.5", title="Amazon"), + dict(img="czi.svg", size="2.5", title="Chan Zuckerberg Initiative"), + ], + "institutions": [ + dict( + name="Massachusetts General Hospital", + img="MGH.svg", + url="https://www.massgeneral.org/", + size=sm, + ), + dict( + name="Athinoula A. Martinos Center for Biomedical Imaging", + img="Martinos.png", + url="https://martinos.org/", + size=md, + ), + dict( + name="Harvard Medical School", + img="Harvard.png", + url="https://hms.harvard.edu/", + size=sm, + ), + dict( + name="Massachusetts Institute of Technology", + img="MIT.svg", + url="https://web.mit.edu/", + size=md, + ), + dict( + name="New York University", + img="NYU.svg", + url="https://www.nyu.edu/", + size=xs, + klass="only-light", + ), + dict( + name="New York University", + img="NYU-dark.svg", + url="https://www.nyu.edu/", + size=xs, + klass="only-dark", + ), + dict( + name="Commissariat à l´énergie atomique et aux énergies alternatives", + img="CEA.png", + url="http://www.cea.fr/", + size=md, + ), + dict( + name="Aalto-yliopiston perustieteiden korkeakoulu", + img="Aalto.svg", + url="https://sci.aalto.fi/", + size=md, + klass="only-light", + ), + dict( + name="Aalto-yliopiston perustieteiden korkeakoulu", + img="Aalto-dark.svg", + url="https://sci.aalto.fi/", + size=md, + klass="only-dark", + ), + dict( + name="Télécom ParisTech", + img="Telecom_Paris_Tech.svg", + url="https://www.telecom-paris.fr/", + size=md, + ), + dict( + name="University of Washington", + img="Washington.svg", + url="https://www.washington.edu/", + size=md, + klass="only-light", + ), + dict( + name="University of Washington", + img="Washington-dark.svg", + url="https://www.washington.edu/", + size=md, + klass="only-dark", + ), + dict( + name="Institut du Cerveau et de la Moelle épinière", + img="ICM.jpg", + url="https://icm-institute.org/", + size=md, + ), + dict( + name="Boston University", img="BU.svg", url="https://www.bu.edu/", size=lg + ), + dict( + name="Institut national de la santé et de la recherche médicale", + img="Inserm.svg", + url="https://www.inserm.fr/", + size=xl, + klass="only-light", + ), + dict( + name="Institut national de la santé et de la recherche médicale", + img="Inserm-dark.svg", + url="https://www.inserm.fr/", + size=xl, + klass="only-dark", + ), + dict( + name="Forschungszentrum Jülich", + img="Julich.svg", + url="https://www.fz-juelich.de/", + size=xl, + klass="only-light", + ), + dict( + name="Forschungszentrum Jülich", + img="Julich-dark.svg", + url="https://www.fz-juelich.de/", + size=xl, + klass="only-dark", + ), + dict( + name="Technische Universität Ilmenau", + img="Ilmenau.svg", + url="https://www.tu-ilmenau.de/", + size=xxl, + klass="only-light", + ), + dict( + name="Technische Universität Ilmenau", + img="Ilmenau-dark.svg", + url="https://www.tu-ilmenau.de/", + size=xxl, + klass="only-dark", + ), + dict( + name="Berkeley Institute for Data Science", + img="BIDS.svg", + url="https://bids.berkeley.edu/", + size=lg, + klass="only-light", + ), + dict( + name="Berkeley Institute for Data Science", + img="BIDS-dark.svg", + url="https://bids.berkeley.edu/", + size=lg, + klass="only-dark", + ), + dict( + name="Institut national de recherche en informatique et en automatique", + img="inria.png", + url="https://www.inria.fr/", + size=xl, + ), + dict( + name="Aarhus Universitet", + img="Aarhus.svg", + url="https://www.au.dk/", + size=xl, + klass="only-light", + ), + dict( + name="Aarhus Universitet", + img="Aarhus-dark.svg", + url="https://www.au.dk/", + size=xl, + klass="only-dark", + ), + dict( + name="Karl-Franzens-Universität Graz", + img="Graz.svg", + url="https://www.uni-graz.at/", + size=md, + ), + dict( + name="SWPS Uniwersytet Humanistycznospołeczny", + img="SWPS.svg", + url="https://www.swps.pl/", + size=xl, + klass="only-light", + ), + dict( + name="SWPS Uniwersytet Humanistycznospołeczny", + img="SWPS-dark.svg", + url="https://www.swps.pl/", + size=xl, + klass="only-dark", + ), + dict( + name="Max-Planck-Institut für Bildungsforschung", + img="MPIB.svg", + url="https://www.mpib-berlin.mpg.de/", + size=xxl, + klass="only-light", + ), + dict( + name="Max-Planck-Institut für Bildungsforschung", + img="MPIB-dark.svg", + url="https://www.mpib-berlin.mpg.de/", + size=xxl, + klass="only-dark", + ), + dict( + name="Macquarie University", + img="Macquarie.svg", + url="https://www.mq.edu.au/", + size=lg, + klass="only-light", + ), + dict( + name="Macquarie University", + img="Macquarie-dark.svg", + url="https://www.mq.edu.au/", + size=lg, + klass="only-dark", + ), + dict( + name="AE Studio", + img="AE-Studio-light.svg", + url="https://ae.studio/", + size=xxl, + klass="only-light", + ), + dict( + name="AE Studio", + img="AE-Studio-dark.svg", + url="https://ae.studio/", + size=xxl, + klass="only-dark", + ), + dict( + name="Children’s Hospital of Philadelphia Research Institute", + img="CHOP.svg", + url="https://www.research.chop.edu/imaging", + size=xxl, + klass="only-light", + ), + dict( + name="Children’s Hospital of Philadelphia Research Institute", + img="CHOP-dark.svg", + url="https://www.research.chop.edu/imaging", + size=xxl, + klass="only-dark", + ), + dict( + name="Donders Institute for Brain, Cognition and Behaviour at Radboud University", # noqa E501 + img="Donders.png", + url="https://www.ru.nl/donders/", + size=xl, + ), + dict( + name="Fondation Campus Biotech Geneva", + img="FCBG.svg", + url="https://fcbg.ch/", + size=sm, + ), + ], + # \u00AD is an optional hyphen (not rendered unless needed) + # If these are changed, the Makefile should be updated, too + "carousel": [ + dict( + title="Source Estimation", + text="Distributed, sparse, mixed-norm, beam\u00adformers, dipole fitting, and more.", # noqa E501 + url="auto_tutorials/inverse/index.html", + img="sphx_glr_30_mne_dspm_loreta_008.gif", + alt="dSPM", + ), + dict( + title="Machine Learning", + text="Advanced decoding models including time general\u00adiza\u00adtion.", + url="auto_tutorials/machine-learning/50_decoding.html", + img="sphx_glr_50_decoding_006.png", + alt="Decoding", + ), + dict( + title="Encoding Models", + text="Receptive field estima\u00adtion with optional smooth\u00adness priors.", # noqa E501 + url="auto_tutorials/machine-learning/30_strf.html", + img="sphx_glr_30_strf_001.png", + alt="STRF", + ), + dict( + title="Statistics", + text="Parametric and non-parametric, permutation tests and clustering.", + url="auto_tutorials/stats-source-space/index.html", + img="sphx_glr_20_cluster_1samp_spatiotemporal_001.png", + alt="Clusters", + ), + dict( + title="Connectivity", + text="All-to-all spectral and effective connec\u00adtivity measures.", + url="https://mne.tools/mne-connectivity/stable/auto_examples/mne_inverse_label_connectivity.html", # noqa E501 + img="https://mne.tools/mne-connectivity/stable/_images/sphx_glr_mne_inverse_label_connectivity_001.png", # noqa E501 + alt="Connectivity", + ), + dict( + title="Data Visualization", + text="Explore your data from multiple perspectives.", + url="auto_tutorials/evoked/20_visualize_evoked.html", + img="sphx_glr_20_visualize_evoked_010.png", + alt="Visualization", + ), + ], +} + +# Output file base name for HTML help builder. +htmlhelp_basename = "mne-doc" + + +# -- Options for plot_directive ---------------------------------------------- + +# Adapted from SciPy +plot_include_source = True +plot_formats = [("png", 96)] +plot_html_show_formats = False +plot_html_show_source_link = False +font_size = 13 * 72 / 96.0 # 13 px +plot_rcparams = { + "font.size": font_size, + "axes.titlesize": font_size, + "axes.labelsize": font_size, + "xtick.labelsize": font_size, + "ytick.labelsize": font_size, + "legend.fontsize": font_size, + "figure.figsize": (6, 5), + "figure.subplot.bottom": 0.2, + "figure.subplot.left": 0.2, + "figure.subplot.right": 0.9, + "figure.subplot.top": 0.85, + "figure.subplot.wspace": 0.4, + "text.usetex": False, +} + + +# -- Options for LaTeX output ------------------------------------------------ + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass +# [howto/manual]). +latex_documents = [] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +latex_logo = "_static/logo.png" + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +latex_toplevel_sectioning = "part" + +# -- Warnings management ----------------------------------------------------- +reset_warnings(None, None) + +# -- Fontawesome support ----------------------------------------------------- +brand_icons = ("apple", "linux", "windows", "discourse", "python") +fixed_width_icons = ( + # homepage: + "book", + "code-branch", + "newspaper", + "circle-question", + "quote-left", + # contrib guide: + "bug-slash", + "comment", + "computer-mouse", + "hand-sparkles", + "pencil", + "text-slash", + "universal-access", + "wand-magic-sparkles", + "discourse", + "python", +) +other_icons = ( + "hand-paper", + "question", + "rocket", + "server", + "code", + "desktop", + "terminal", + "cloud-arrow-down", + "wrench", + "hourglass-half", +) +icon_class = dict() +for icon in brand_icons + fixed_width_icons + other_icons: + icon_class[icon] = ("fa-brands",) if icon in brand_icons else ("fa-solid",) + icon_class[icon] += ("fa-fw",) if icon in fixed_width_icons else () + +rst_prolog = "" +for icon, classes in icon_class.items(): + rst_prolog += f""" +.. |{icon}| raw:: html + + +""" + +rst_prolog += """ +.. |ensp| unicode:: U+2002 .. EN SPACE + +.. include:: /links.inc +.. include:: /changes/names.inc + +.. currentmodule:: mne +""" + +# -- Dependency info ---------------------------------------------------------- + +min_py = metadata("mne")["Requires-Python"].lstrip(" =<>") +rst_prolog += f"\n.. |min_python_version| replace:: {min_py}\n" + +# -- website redirects -------------------------------------------------------- + +# Static list created 2021/04/13 based on what we needed to redirect, +# since we don't need to add redirects for examples added after this date. +needed_plot_redirects = { + # tutorials + "10_epochs_overview.py", + "10_evoked_overview.py", + "10_overview.py", + "10_preprocessing_overview.py", + "10_raw_overview.py", + "10_reading_meg_data.py", + "15_handling_bad_channels.py", + "20_event_arrays.py", + "20_events_from_raw.py", + "20_reading_eeg_data.py", + "20_rejecting_bad_data.py", + "20_visualize_epochs.py", + "20_visualize_evoked.py", + "30_annotate_raw.py", + "30_epochs_metadata.py", + "30_filtering_resampling.py", + "30_info.py", + "30_reading_fnirs_data.py", + "35_artifact_correction_regression.py", + "40_artifact_correction_ica.py", + "40_autogenerate_metadata.py", + "40_sensor_locations.py", + "40_visualize_raw.py", + "45_projectors_background.py", + "50_artifact_correction_ssp.py", + "50_configure_mne.py", + "50_epochs_to_data_frame.py", + "55_setting_eeg_reference.py", + "59_head_positions.py", + "60_make_fixed_length_epochs.py", + "60_maxwell_filtering_sss.py", + "70_fnirs_processing.py", + # examples + "3d_to_2d.py", + "brainstorm_data.py", + "channel_epochs_image.py", + "cluster_stats_evoked.py", + "compute_csd.py", + "compute_mne_inverse_epochs_in_label.py", + "compute_mne_inverse_raw_in_label.py", + "compute_mne_inverse_volume.py", + "compute_source_psd_epochs.py", + "covariance_whitening_dspm.py", + "custom_inverse_solver.py", + "decoding_csp_eeg.py", + "decoding_csp_timefreq.py", + "decoding_spatio_temporal_source.py", + "decoding_spoc_CMC.py", + "decoding_time_generalization_conditions.py", + "decoding_unsupervised_spatial_filter.py", + "decoding_xdawn_eeg.py", + "define_target_events.py", + "dics_source_power.py", + "eeg_csd.py", + "eeg_on_scalp.py", + "eeglab_head_sphere.py", + "elekta_epochs.py", + "ems_filtering.py", + "eog_artifact_histogram.py", + "evoked_arrowmap.py", + "evoked_ers_source_power.py", + "evoked_topomap.py", + "evoked_whitening.py", + "fdr_stats_evoked.py", + "find_ref_artifacts.py", + "fnirs_artifact_removal.py", + "forward_sensitivity_maps.py", + "gamma_map_inverse.py", + "hf_sef_data.py", + "ica_comparison.py", + "interpolate_bad_channels.py", + "label_activation_from_stc.py", + "label_from_stc.py", + "label_source_activations.py", + "left_cerebellum_volume_source.py", + "limo_data.py", + "linear_model_patterns.py", + "linear_regression_raw.py", + "meg_sensors.py", + "mixed_norm_inverse.py", + "mixed_source_space_inverse.py", + "mne_cov_power.py", + "mne_helmet.py", + "mne_inverse_coherence_epochs.py", + "mne_inverse_envelope_correlation.py", + "mne_inverse_envelope_correlation_volume.py", + "mne_inverse_psi_visual.py", + "morph_surface_stc.py", + "morph_volume_stc.py", + "movement_compensation.py", + "movement_detection.py", + "multidict_reweighted_tfmxne.py", + "muscle_detection.py", + "opm_data.py", + "otp.py", + "parcellation.py", + "psf_ctf_label_leakage.py", + "psf_ctf_vertices.py", + "psf_ctf_vertices_lcmv.py", + "publication_figure.py", + "rap_music.py", + "trap_music.py", + "read_inverse.py", + "read_neo_format.py", + "read_noise_covariance_matrix.py", + "read_stc.py", + "receptive_field_mtrf.py", + "resolution_metrics.py", + "resolution_metrics_eegmeg.py", + "roi_erpimage_by_rt.py", + "sensor_noise_level.py", + "sensor_permutation_test.py", + "sensor_regression.py", + "shift_evoked.py", + "simulate_evoked_data.py", + "simulate_raw_data.py", + "simulated_raw_data_using_subject_anatomy.py", + "snr_estimate.py", + "source_label_time_frequency.py", + "source_power_spectrum.py", + "source_power_spectrum_opm.py", + "source_simulator.py", + "source_space_morphing.py", + "source_space_snr.py", + "source_space_time_frequency.py", + "ssd_spatial_filters.py", + "ssp_projs_sensitivity_map.py", + "temporal_whitening.py", + "time_frequency_erds.py", + "time_frequency_global_field_power.py", + "time_frequency_mixed_norm_inverse.py", + "time_frequency_simulated.py", + "topo_compare_conditions.py", + "topo_customized.py", + "vector_mne_solution.py", + "virtual_evoked.py", + "xdawn_denoising.py", + "xhemi.py", +} +api_redirects = { + "connectivity", + "covariance", + "creating_from_arrays", + "datasets", + "decoding", + "events", + "export", + "file_io", + "forward", + "inverse", + "logging", + "most_used_classes", + "mri", + "preprocessing", + "python_reference", + "reading_raw_data", + "realtime", + "report", + "sensor_space", + "simulation", + "source_space", + "statistics", + "time_frequency", + "visualization", +} +ex = "auto_examples" +co = "connectivity" +mne_conn = "https://mne.tools/mne-connectivity/stable" +tu = "auto_tutorials" +pr = "preprocessing" +di = "discussions" +sm = "source-modeling" +fw = "forward" +nv = "inverse" +sn = "stats-sensor-space" +sr = "stats-source-space" +sd = "sample-datasets" +ml = "machine-learning" +tf = "time-freq" +si = "simulation" +vi = "visualization" +custom_redirects = { + # Custom redirects (one HTML path to another, relative to outdir) + # can be added here as fr->to key->value mappings + "install/contributing": "development/contributing", + "overview/cite": "documentation/cite", + "overview/get_help": "help/index", + "overview/roadmap": "development/roadmap", + "whats_new": "development/whats_new", + f"{tu}/evoked/plot_eeg_erp": f"{tu}/evoked/30_eeg_erp", + f"{tu}/evoked/plot_whitened": f"{tu}/evoked/40_whitened", + f"{tu}/misc/plot_modifying_data_inplace": f"{tu}/intro/15_inplace", + f"{tu}/misc/plot_report": f"{tu}/intro/70_report", + f"{tu}/misc/plot_seeg": f"{tu}/clinical/20_seeg", + f"{tu}/misc/plot_ecog": f"{tu}/clinical/30_ecog", + f"{tu}/{ml}/plot_receptive_field": f"{tu}/{ml}/30_strf", + f"{tu}/{ml}/plot_sensors_decoding": f"{tu}/{ml}/50_decoding", + f"{tu}/{sm}/plot_background_freesurfer": f"{tu}/{fw}/10_background_freesurfer", + f"{tu}/{sm}/plot_source_alignment": f"{tu}/{fw}/20_source_alignment", + f"{tu}/{sm}/plot_forward": f"{tu}/{fw}/30_forward", + f"{tu}/{sm}/plot_eeg_no_mri": f"{tu}/{fw}/35_eeg_no_mri", + f"{tu}/{sm}/plot_background_freesurfer_mne": f"{tu}/{fw}/50_background_freesurfer_mne", # noqa E501 + f"{tu}/{sm}/plot_fix_bem_in_blender": f"{tu}/{fw}/80_fix_bem_in_blender", + f"{tu}/{sm}/plot_compute_covariance": f"{tu}/{fw}/90_compute_covariance", + f"{tu}/{sm}/plot_object_source_estimate": f"{tu}/{nv}/10_stc_class", + f"{tu}/{sm}/plot_dipole_fit": f"{tu}/{nv}/20_dipole_fit", + f"{tu}/{sm}/plot_mne_dspm_source_localization": f"{tu}/{nv}/30_mne_dspm_loreta", + f"{tu}/{sm}/plot_dipole_orientations": f"{tu}/{nv}/35_dipole_orientations", + f"{tu}/{sm}/plot_mne_solutions": f"{tu}/{nv}/40_mne_fixed_free", + f"{tu}/{sm}/plot_beamformer_lcmv": f"{tu}/{nv}/50_beamformer_lcmv", + f"{tu}/{sm}/plot_visualize_stc": f"{tu}/{nv}/60_visualize_stc", + f"{tu}/{sm}/plot_eeg_mri_coords": f"{tu}/{nv}/70_eeg_mri_coords", + f"{tu}/{sd}/plot_brainstorm_phantom_elekta": f"{tu}/{nv}/80_brainstorm_phantom_elekta", # noqa E501 + f"{tu}/{sd}/plot_brainstorm_phantom_ctf": f"{tu}/{nv}/85_brainstorm_phantom_ctf", + f"{tu}/{sd}/plot_phantom_4DBTi": f"{tu}/{nv}/90_phantom_4DBTi", + f"{tu}/{sd}/plot_brainstorm_auditory": f"{tu}/io/60_ctf_bst_auditory", + f"{tu}/{sd}/plot_sleep": f"{tu}/clinical/60_sleep", + f"{tu}/{di}/plot_background_filtering": f"{tu}/{pr}/25_background_filtering", + f"{tu}/{di}/plot_background_statistics": f"{tu}/{sn}/10_background_stats", + f"{tu}/{sn}/plot_stats_cluster_erp": f"{tu}/{sn}/20_erp_stats", + f"{tu}/{sn}/plot_stats_cluster_1samp_test_time_frequency": f"{tu}/{sn}/40_cluster_1samp_time_freq", # noqa E501 + f"{tu}/{sn}/plot_stats_cluster_time_frequency": f"{tu}/{sn}/50_cluster_between_time_freq", # noqa E501 + f"{tu}/{sn}/plot_stats_spatio_temporal_cluster_sensors": f"{tu}/{sn}/75_cluster_ftest_spatiotemporal", # noqa E501 + f"{tu}/{sr}/plot_stats_cluster_spatio_temporal": f"{tu}/{sr}/20_cluster_1samp_spatiotemporal", # noqa E501 + f"{tu}/{sr}/plot_stats_cluster_spatio_temporal_2samp": f"{tu}/{sr}/30_cluster_ftest_spatiotemporal", # noqa E501 + f"{tu}/{sr}/plot_stats_cluster_spatio_temporal_repeated_measures_anova": f"{tu}/{sr}/60_cluster_rmANOVA_spatiotemporal", # noqa E501 + f"{tu}/{sr}/plot_stats_cluster_time_frequency_repeated_measures_anova": f"{tu}/{sn}/70_cluster_rmANOVA_time_freq", # noqa E501 + f"{tu}/{tf}/plot_sensors_time_frequency": f"{tu}/{tf}/20_sensors_time_frequency", + f"{tu}/{tf}/plot_ssvep": f"{tu}/{tf}/50_ssvep", + f"{tu}/{si}/plot_creating_data_structures": f"{tu}/{si}/10_array_objs", + f"{tu}/{si}/plot_point_spread": f"{tu}/{si}/70_point_spread", + f"{tu}/{si}/plot_dics": f"{tu}/{si}/80_dics", + f"{tu}/{tf}/plot_eyetracking": f"{tu}/{pr}/90_eyetracking_data", + f"{ex}/{co}/mne_inverse_label_connectivity": f"{mne_conn}/{ex}/mne_inverse_label_connectivity", # noqa E501 + f"{ex}/{co}/cwt_sensor_connectivity": f"{mne_conn}/{ex}/cwt_sensor_connectivity", + f"{ex}/{co}/mixed_source_space_connectivity": f"{mne_conn}/{ex}/mixed_source_space_connectivity", # noqa E501 + f"{ex}/{co}/mne_inverse_coherence_epochs": f"{mne_conn}/{ex}/mne_inverse_coherence_epochs", # noqa E501 + f"{ex}/{co}/mne_inverse_connectivity_spectrum": f"{mne_conn}/{ex}/mne_inverse_connectivity_spectrum", # noqa E501 + f"{ex}/{co}/mne_inverse_envelope_correlation_volume": f"{mne_conn}/{ex}/mne_inverse_envelope_correlation_volume", # noqa E501 + f"{ex}/{co}/mne_inverse_envelope_correlation": f"{mne_conn}/{ex}/mne_inverse_envelope_correlation", # noqa E501 + f"{ex}/{co}/mne_inverse_psi_visual": f"{mne_conn}/{ex}/mne_inverse_psi_visual", + f"{ex}/{co}/sensor_connectivity": f"{mne_conn}/{ex}/sensor_connectivity", + f"{ex}/{vi}/publication_figure": f"{tu}/{vi}/10_publication_figure", + f"{ex}/{vi}/sensor_noise_level": f"{tu}/{pr}/50_artifact_correction_ssp", +} + +# Adapted from sphinxcontrib/redirects (BSD-2-Clause) +REDIRECT_TEMPLATE = """\ + + + + + + + Page Redirection + + + If you are not redirected automatically, follow this link. + +""" + + +def check_existing_redirect(path): + """Make sure existing HTML files are redirects, before overwriting.""" + if path.is_file(): + with open(path) as fid: + for _ in range(8): + next(fid) + line = fid.readline() + if "Page Redirection" not in line: + raise RuntimeError( + "Attempted overwrite of HTML file with a redirect, where the " + "original file was not already a redirect." + ) + + +def _check_valid_builder(app, exception): + valid_builder = isinstance(app.builder, sphinx.builders.html.StandaloneHTMLBuilder) + return valid_builder and exception is None + + +def make_gallery_redirects(app, exception): + """Make HTML redirects for our sphinx gallery pages.""" + if not _check_valid_builder(app, exception): + return + sg_conf = app.config["sphinx_gallery_conf"] + for src_dir, out_dir in zip(sg_conf["examples_dirs"], sg_conf["gallery_dirs"]): + root = (Path(app.srcdir) / src_dir).resolve() + fnames = [ + pyfile.relative_to(root) + for pyfile in root.rglob(r"**/*.py") + if pyfile.name in needed_plot_redirects + ] + # plot_ redirects + for fname in fnames: + dirname = Path(app.outdir) / out_dir / fname.parent + to_fname = fname.with_suffix(".html").name + fr_fname = f"plot_{to_fname}" + to_path = dirname / to_fname + fr_path = dirname / fr_fname + assert to_path.is_file(), (fname, to_path) + with open(fr_path, "w") as fid: + fid.write(REDIRECT_TEMPLATE.format(to=to_fname)) + sphinx_logger.info( + f"Added {len(fnames):3d} HTML plot_* redirects for {out_dir}" + ) + + +def make_api_redirects(app, exception): + """Make HTML redirects for our API pages.""" + if not _check_valid_builder(app, exception): + return + + for page in api_redirects: + fname = f"{page}.html" + fr_path = Path(app.outdir) / fname + to_path = Path(app.outdir) / "api" / fname + # allow overwrite if existing file is just a redirect + check_existing_redirect(fr_path) + with open(fr_path, "w") as fid: + fid.write(REDIRECT_TEMPLATE.format(to=to_path)) + sphinx_logger.info(f"Added {len(api_redirects):3d} HTML API redirects") + + +def make_custom_redirects(app, exception): + """Make HTML redirects for miscellaneous pages.""" + if not _check_valid_builder(app, exception): + return + + for _fr, _to in custom_redirects.items(): + fr = f"{_fr}.html" + to = f"{_to}.html" + fr_path = Path(app.outdir) / fr + check_existing_redirect(fr_path) + if to.startswith("http"): + to_path = to + else: + to_path = Path(app.outdir) / to + assert to_path.is_file(), to_path + # recreate folders that no longer exist + defunct_gallery_folders = ( + "misc", + "discussions", + "source-modeling", + "sample-datasets", + "connectivity", + ) + parts = fr_path.relative_to(Path(app.outdir)).parts + if ( + len(parts) > 1 # whats_new violates this + and parts[1] in defunct_gallery_folders + and not fr_path.parent.exists() + ): + os.makedirs(fr_path.parent, exist_ok=True) + # write the redirect + with open(fr_path, "w") as fid: + fid.write(REDIRECT_TEMPLATE.format(to=to_path)) + sphinx_logger.info(f"Added {len(custom_redirects):3d} HTML custom redirects") + + +def make_version(app, exception): + """Make a text file with the git version.""" + if not ( + isinstance(app.builder, sphinx.builders.html.StandaloneHTMLBuilder) + and exception is None + ): + return + try: + stdout, _ = run_subprocess(["git", "rev-parse", "HEAD"], verbose=False) + except Exception as exc: + sphinx_logger.warning(f"Failed to write _version.txt: {exc}") + return + with open(os.path.join(app.outdir, "_version.txt"), "w") as fid: + fid.write(stdout) + sphinx_logger.info(f'Added "{stdout.rstrip()}" > _version.txt') + + +# -- Connect our handlers to the main Sphinx app --------------------------- + + +def setup(app): + """Set up the Sphinx app.""" + app.connect("autodoc-process-docstring", append_attr_meth_examples) + app.connect("autodoc-process-docstring", fix_sklearn_inherited_docstrings) + # High prio, will happen before SG + app.connect("builder-inited", generate_credit_rst, priority=10) + app.connect("builder-inited", report_scraper.set_dirs, priority=20) + app.connect("build-finished", make_gallery_redirects) + app.connect("build-finished", make_api_redirects) + app.connect("build-finished", make_custom_redirects) + app.connect("build-finished", make_version) diff --git a/mne-python/source/doc/conftest.py b/mne-python/source/doc/conftest.py new file mode 100644 index 0000000000000000000000000000000000000000..1e791fbb9235e43792fbdb881d539e02ad277ca9 --- /dev/null +++ b/mne-python/source/doc/conftest.py @@ -0,0 +1,5 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from mne.conftest import * # noqa diff --git a/mne-python/source/doc/contributing.html b/mne-python/source/doc/contributing.html new file mode 100644 index 0000000000000000000000000000000000000000..0b77fd0aaacca6e3446b2824231b82edc6fce371 --- /dev/null +++ b/mne-python/source/doc/contributing.html @@ -0,0 +1,9 @@ + + + + + + +

Please follow this link.

+ + diff --git a/mne-python/source/doc/credit.rst b/mne-python/source/doc/credit.rst new file mode 100644 index 0000000000000000000000000000000000000000..4d9a995760492ab658c19edecfebc74f2026587b --- /dev/null +++ b/mne-python/source/doc/credit.rst @@ -0,0 +1,12 @@ +:orphan: + +.. _contributors: + +============ +Contributors +============ + +There are many different ways to contribute to MNE-Python! So far we only list +code contributions below, but plan to add other metrics in the future. + +.. include:: ./code_credit.inc diff --git a/mne-python/source/doc/development/contributing.rst b/mne-python/source/doc/development/contributing.rst new file mode 100644 index 0000000000000000000000000000000000000000..beed58f65589e79378703bae3d61c3189b18f568 --- /dev/null +++ b/mne-python/source/doc/development/contributing.rst @@ -0,0 +1,1119 @@ +.. _contributing: + +Contributing guide +================== + +.. highlight:: console + +Thanks for taking the time to contribute! MNE-Python is an open-source project +sustained mostly by volunteer effort. We welcome contributions from anyone as +long as they abide by our `Code of Conduct`_. + +There are lots of ways to contribute, such as: + +.. rst-class:: icon-bullets + +- |computer-mouse| Use the software, and when you find bugs, tell us about them! We can + only fix the bugs we know about. +- |discourse| Answer questions on `our user forum`_. +- |comment| Tell us about parts of the documentation that you find confusing or + unclear. +- |hand-sparkles| Tell us about things you wish MNE-Python could do, or things + it can do but you wish they were easier. +- |universal-access| Improve the accessibility of our website. +- |bug-slash| Fix bugs. +- |text-slash| Fix mistakes in our function documentation strings. +- |wand-magic-sparkles| Implement new features. +- |pencil| Improve existing tutorials or write new ones. +- |python| Contribute to one of the many Python packages that MNE-Python + depends on. + +To *report* bugs, *request* new features, or *ask about* confusing +documentation, it's usually best to open a new issue on `our user forum`_ +first; you'll probably get help fastest that way, and it helps keep our GitHub +issue tracker focused on things that we *know* will require changes to our +software (as opposed to problems that can be fixed in the user's code). We may +ultimately ask you to open an issue on GitHub too, but starting on the forum +helps us keep things organized. For fastest results, be sure to include +information about your operating system and MNE-Python version, and (if +applicable) include a reproducible code sample that is as short as possible and +ideally uses one of :ref:`our example datasets `. + +If you want to *fix* bugs, *add* new features, or *improve* our +docstrings/tutorials/website, those kinds of contributions are made through +`our GitHub repository `_. The rest of this page explains +how to set up your workflow to make contributing via GitHub as easy as +possible. + + +.. dropdown:: Want an example to work through? + :color: success + :icon: rocket + + Feel free to just read through the rest of the page, but if you find it + easier to "learn by doing", take a look at our + `GitHub issues marked "easy"`_, pick one that looks interesting, and work + through it while reading this guide! + + +Overview of contribution process +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. note:: Reminder: all contributors are expected to follow our + `code of conduct`_. + +Changes to MNE-Python are typically made by `forking`_ the MNE-Python +repository, making changes to your fork (usually by `cloning`_ it to your +personal computer, making the changes locally, and then `pushing`_ the local +changes up to your fork on GitHub), and finally creating a `pull request`_ to incorporate +your changes back into the shared "upstream" version of the codebase. + +In general you'll be working with three different copies of the MNE-Python +codebase: the official remote copy at https://github.com/mne-tools/mne-python +(usually called ``upstream``), your remote `fork`_ of the upstream repository +(similar URL, but with your username in place of ``mne-tools``, and usually +called ``origin``), and the local copy of the codebase on your computer. The +typical contribution process is to: + +1. synchronize your local copy with ``upstream`` + +2. make changes to your local copy + +3. `push`_ your changes to ``origin`` (your remote fork of the upstream) + +4. submit a `pull request`_ from your fork into ``upstream`` + +The sections :ref:`basic-git` and :ref:`github-workflow` (below) describe this +process in more detail. + + +Setting up your local development environment +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Configuring git +~~~~~~~~~~~~~~~ + +.. admonition:: Git GUI alternative + :class: sidebar note + + `GitHub desktop`_ is a GUI alternative to command line git that some users + appreciate; it is available for |windows| Windows and |apple| MacOS. + +To get set up for contributing, make sure you have git installed on your local +computer: + +- On Linux, the command ``sudo apt install git`` is usually sufficient; see the + `official Linux instructions`_ for more options. + +- On MacOS, download `the .dmg installer`_; Atlassian also provides `more + detailed instructions and alternatives`_ such as using MacPorts or Homebrew. + +- On Windows, download and install `git for Windows`_. With Git BASH it provides its own shell that + includes many Linux-equivalent command line programs that are useful for development. + + *Windows 10 also offers the* `Windows subsystem for Linux`_ *that offers similar + functionality to git BASH, but has not been widely tested by MNE-Python + developers yet and may still pose problems with graphical output (e.g. building the documentation)* + + +Once git is installed, the only absolutely necessary configuration step is +identifying yourself and your contact info:: + + $ git config --global user.name "Your Name" + $ git config --global user.email you@yourdomain.example.com + +Make sure that the same email address is associated with your GitHub account +and with your local git configuration. It is possible to associate multiple +emails with a GitHub account, so if you initially set them up with different +emails, you can add the local email to the GitHub account. + +Sooner or later, git is going to ask you what text editor you want it to use +when writing commit messages, so you might as well configure that now too:: + + $ git config --global core.editor emacs # or vim, or nano, or subl, or... + +There are many other ways to customize git's behavior; see `configuring git`_ +for more information. + + +GNU Make +~~~~~~~~ + +We use `GNU Make`_ to organize commands or short scripts that are often needed +in development. These are stored in files with the name :file:`Makefile`. +MNE-Python has two Makefiles, one in the package's root directory (containing +mainly testing commands) and one in :file:`doc/` (containing recipes for +building our documentation pages in different ways). + +To check if make is already installed type :: + + $ make + +into a terminal and you should see :: + + make: *** No targets specified and no makefile found. Stop. + +If you don't see this or something similar, you may not have ``make`` installed. + +.. tab-set:: + + .. tab-item:: Linux + :class-content: text-center + + .. button-link:: https://www.gnu.org/software/make/ + :ref-type: ref + :color: primary + :shadow: + :class: font-weight-bold mt-3 + + |cloud-arrow-down| |ensp| Get make for Linux + + .. tab-item:: macOS + :class-content: text-center + + .. button-link:: https://www.gnu.org/software/make/ + :ref-type: ref + :color: primary + :shadow: + :class: font-weight-bold mt-3 + + |cloud-arrow-down| |ensp| Get make for macOS + + .. tab-item:: Windows + + If you see: :: + + bash: make: command not found + + Install ``make`` for git BASH (which comes with `git for Windows`_): + + 1. Download :file:`make-{newest.version}-without-guile-w32-bin.zip` from `ezwinports`_ + 2. Extract zip-folder + 3. Copy the contents into :file:`{path_to_git}\\mingw64\\` (e.g. by merging the + folders with the equivalent ones already inside) + 4. For the first time using git BASH, you need to run once (to be able to + activate your ``mnedev`` environment): :: + + $ conda init bash + + If instead you see an error like: :: + + bash: conda: command not found + + at the top of your git BASH window, you need to add + + - :file:`{path_to_Anaconda}` + - :file:`{path_to_Anaconda}\\Scripts` + + to Windows-PATH first. + + +Forking the MNE-Python repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once you have git installed and configured, and before creating your local copy +of the codebase, go to the `MNE-Python GitHub`_ page and create a `fork`_ into +your GitHub user account. + +This will create a copy of the MNE-Python codebase inside your GitHub user +account (this is called "your fork"). Changes you make to MNE-Python will +eventually get "pushed" to your fork, and will be incorporated into the +official version of MNE-Python (often called the "upstream version") through a +"pull request". This process will be described in detail below; a summary +of how that structure is set up is given here: + +.. graphviz:: ../_static/diagrams/git_setup.dot + :alt: Diagram of recommended git setup + :align: left + + +Creating the virtual environment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. admonition:: Supported Python environments + :class: sidebar note + + We strongly recommend the `Anaconda`_ or `Miniconda`_ environment managers + for Python. Other setups are possible but are not officially supported by + the MNE-Python development team; see discussion :ref:`here + `. These instructions use ``conda`` where possible; + experts may replace those lines with some combination of ``git`` and + ``pip``. + +These instructions will set up a Python environment that is separated from your +system-level Python and any other managed Python environments on your computer. +This lets you switch between different versions of Python and also switch between +the stable and development +versions of MNE-Python (so you can, for example, use the same computer to +analyze your data with the stable release, and also work with the latest +development version to fix bugs or add new features). Even if you've already +followed the :ref:`installation instructions ` for the stable +version of MNE-Python, you should now repeat that process to create a new, +separate environment for MNE-Python development (here we'll give it the name +``mnedev``):: + + $ curl --remote-name https://raw.githubusercontent.com/mne-tools/mne-python/main/environment.yml + $ conda env create --file environment.yml --name mnedev + $ conda activate mnedev + +Now you'll have *two* MNE-Python environments: ``mne`` (or whatever custom +name you used when installing the stable version of MNE-Python) and ``mnedev`` +that we just created. At this point ``mnedev`` also has the stable version of +MNE-Python (that's what the :file:`environment.yml` file installs), but we're +about to remove the stable version from ``mnedev`` and replace it with the +development version. To do that, we'll `clone`_ the MNE-Python repository from +your remote fork, and also connect the local copy to the ``upstream`` version +of the codebase, so you can stay up-to-date with changes from other +contributors. First, edit these two variables for your situation:: + + $ GITHUB_USERNAME="insert_your_actual_GitHub_username_here" + $ # pick where to put your local copy of MNE-Python development version: + $ INSTALL_LOCATION="/opt" + +.. note:: + On Windows, add ``set`` before the variable names (``set GITHUB_USERNAME=...``, etc.). + +Then make a local clone of your remote fork (``origin``):: + + $ cd $INSTALL_LOCATION + $ git clone https://github.com/$GITHUB_USERNAME/mne-python.git + +Finally, set up a link between your local clone and the official repository +(``upstream``) and set up ``git diff`` to work properly:: + + $ cd mne-python + $ git remote add upstream https://github.com/mne-tools/mne-python.git + $ git fetch --all + $ git config --local blame.ignoreRevsFile .git-blame-ignore-revs + +Now we'll remove the *stable* version of MNE-Python and replace it with the +*development* version (the clone we just created with git). Make sure you're in +the correct environment first (``conda activate mnedev``), and then do:: + + $ cd $INSTALL_LOCATION/mne-python # make sure we're in the right folder + $ conda remove --force mne-base # the --force avoids dependency checking + $ pip install -e . + +The command ``pip install -e .`` installs a python module into the current +environment by creating a link to the source code directory (instead of copying +the code to pip's :file:`site_packages` directory, which is what normally +happens). This means that any edits you make to the MNE-Python source code will +be reflected the next time you open a Python interpreter and ``import mne`` +(the ``-e`` flag of ``pip`` stands for an "editable" installation). + +Finally, we'll add a few dependencies that are not needed for running +MNE-Python, but are needed for locally running our test suite:: + + $ pip install --group=test + +And for building our documentation:: + + $ pip install --group=doc + $ conda install graphviz + +.. note:: + On Windows, if you installed graphviz using the conda command above but still get an error like this:: + + WARNING: dot command 'dot' cannot be run (needed for graphviz output), check the graphviz_dot setting + + try adding the graphviz folder to path:: + + $ PATH=$CONDA_PREFIX\\Library\\bin\\graphviz:$PATH + +To build documentation, you will also require `optipng`_: + +- On Linux, use the command ``sudo apt install optipng``. + +- On MacOS, optipng can be installed using Homebrew. + +- On Windows, unzip :file:`optipng.exe` from the `optipng for Windows`_ archive + into the :file:`doc/` folder. This step is optional for Windows users. + +There are additional optional dependencies needed to run various tests, such as +scikit-learn for decoding tests, or nibabel for MRI tests. If you want to run all the +tests, consider using our MNE installers (which provide these dependencies) or pay +attention to the skips that ``pytest`` reports and install the relevant libraries. +For example, this traceback:: + + SKIPPED [2] mne/io/eyelink/tests/test_eyelink.py:14: could not import 'pandas': No module named 'pandas' + +indicates that ``pandas`` needs to be installed in order to run the Eyelink tests. + + +.. _basic-git: + +Basic git commands +~~~~~~~~~~~~~~~~~~ + +Learning to work with git can take a long time, because it is a complex and +powerful tool for managing versions of files across multiple users, each of +whom have multiple copies of the codebase. We've already seen in the setup +commands above a few of the basic git commands useful to an MNE-Python +developer: + +- :samp:`git clone {}` (make a local copy of a repository) + +- :samp:`git remote add {} {}` (connect + a local copy to an additional remote) + +- ``git fetch --all`` (get the current state of connected remote repos) + +Other commands that you will undoubtedly need relate to `branches`_. Branches +represent multiple copies of the codebase *within a local clone or remote +repo*. Branches are typically used to experiment with new features while still +keeping a clean, working copy of the original codebase that you can switch back +to at any time. The default branch of any repo is called ``main``, and +it is recommended that you reserve the ``main`` branch to be that clean copy +of the working ``upstream`` codebase. Therefore, if you want to add a new +feature, you should first synchronize your local ``main`` branch with the +``upstream`` repository, then create a new branch based off of ``main`` and +`check it out`_ so that any changes you make will exist on that new branch +(instead of on ``main``):: + + $ git checkout main # switch to local main branch + $ git fetch upstream # get the current state of the remote upstream repo + $ git merge upstream/main # synchronize local main branch with remote upstream main branch + $ git checkout -b new-feature-x # create local branch "new-feature-x" and check it out + +.. tip:: + :class: sidebar + + You can save some typing by using ``git pull upstream/main`` to replace + the ``fetch`` and ``merge`` lines above. + +Now that you're on a new branch, you can fix a bug or add a new feature, add a +test, update the documentation, etc. When you're done, it's time to organize +your changes into a series of `commits`_. Commits are like snapshots of the +repository — actually, more like a description of what has to change to get +from the most recent snapshot to the current snapshot. + +Git knows that people often work on multiple changes in multiple files all at +once, but that ultimately they should separate those changes into sets of +related changes that are grouped together based on common goals (so that it's +easier for their colleagues to understand and review the changes). For example, +you might want to group all the code changes together in one commit, put new +unit tests in another commit, and changes to the documentation in a third +commit. Git makes this possible with something called the `stage`_ (or +*staging area*). After you've made some changes to the codebase, you'll have +what git calls "unstaged changes", which will show up with the `status`_ +command:: + + $ git status # see what state the local copy of the codebase is in + +Those unstaged changes can be `added`_ to the stage one by one, by either +adding a whole file's worth of changes, or by adding only certain lines +interactively:: + + $ git add mne/some_file.py # add all the changes you made to this file + $ git add mne/some_new_file.py # add a completely new file in its entirety + $ # enter interactive staging mode, to add only portions of a file: + $ git add -p mne/viz/some_other_file.py + +Once you've collected all the related changes together on the stage, the ``git +status`` command will now refer to them as "changes staged for commit". You can +commit them to the current branch with the `commit`_ command. If you just type +``git commit`` by itself, git will open the text editor you configured it to +use so that you can write a *commit message* — a short description of the +changes you've grouped together in this commit. You can bypass the text editor +by passing a commit message on the command line with the ``-m`` flag. For +example, if your first commit adds a new feature, your commit message might be:: + + $ git commit -m 'ENH: adds feature X to the Epochs class' + +Once you've made the commit, the stage is now empty, and you can repeat the +cycle, adding the unit tests and documentation changes:: + + $ git add mne/tests/some_testing_file.py + $ git commit -m 'add test of new feature X of the Epochs class' + $ git add -p mne/some_file.py mne/viz/some_other_file.py + $ git commit -m 'DOC: update Epochs and BaseEpochs docstrings' + $ git add tutorials/new_tutorial_file.py + $ git commit -m 'DOC: adds new tutorial about feature X' + +When you're done, it's time to run the test suite to make sure your changes +haven't broken any existing functionality, and to make sure your new test +covers the lines of code you've added (see :ref:`run-tests` and +:ref:`build-docs`, below). Once everything looks good, it's time to push your +changes to your fork:: + + $ # push local changes to remote branch origin/new-feature-x + $ # (this will create the remote branch if it doesn't already exist) + $ git push origin new-feature-x + +Finally, go to the `MNE-Python GitHub`_ page, click on the pull requests tab, +click the "new pull request" button, and choose "compare across forks" to +select your new branch (``new-feature-x``) as the "head repository". See the +GitHub help page on `creating a PR from a fork`_ for more information about +opening pull requests. + +If any of the tests failed before you pushed your changes, try to fix them, +then add and commit the changes that fixed the tests, and push to your fork. If +you're stuck and can't figure out how to fix the tests, go ahead and push your +commits to your fork anyway and open a pull request (as described above), then +in the pull request you should describe how the tests are failing and ask for +advice about how to fix them. + +To learn more about git, check out the `GitHub help`_ website, the `GitHub +skills`_ tutorial series, and the `pro git book`_. + + +.. _github-ssh: + +Connecting to GitHub with SSH (optional) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +One easy way to speed up development is to reduce the number of times you have +to type your password. SSH (secure shell) allows authentication with pre-shared +key pairs. The private half of your key pair is kept secret on your computer, +while the public half of your key pair is added to your GitHub account; when +you connect to GitHub from your computer, the local git client checks the +remote (public) key against your local (private) key, and grants access your +account only if the keys fit. GitHub has `several help pages`_ that guide you +through the process. + +Once you have set up GitHub to use SSH authentication, you should change the +addresses of your MNE-Python GitHub remotes, from ``https://`` addresses to +``git@`` addresses, so that git knows to connect via SSH instead of HTTPS. For +example:: + + $ git remote -v # show existing remote addresses + $ git remote set-url origin git@github.com:$GITHUB_USERNAME/mne-python.git + $ git remote set-url upstream git@github.com:mne-tools/mne-python.git + + +MNE-Python coding conventions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +General requirements +~~~~~~~~~~~~~~~~~~~~ + +All new functionality must have test coverage +--------------------------------------------- + +For example, a new `mne.Evoked` method in :file:`mne/evoked.py` should +have a corresponding test in :file:`mne/tests/test_evoked.py`. + + +All new functionality must be documented +---------------------------------------- + +This includes thorough docstring descriptions for all public API changes, as +well as how-to examples or longer tutorials for major contributions. Docstrings +for private functions may be more sparse, but should usually not be omitted. + + +Avoid API changes when possible +------------------------------- + +Changes to the public API (e.g., class/function/method names and signatures) +should not be made lightly, as they can break existing user scripts. Changes to +the API require a deprecation cycle (with warnings) so that users have time to +adapt their code before API changes become default behavior. See :ref:`the +deprecation section ` and `mne.utils.deprecated` for +instructions. Bug fixes (when something isn't doing what it says it will do) do +not require a deprecation cycle. + +Note that any new API elements should be added to the main reference; +classes, functions, methods, and attributes cannot be cross-referenced unless +they are included in the :ref:`api_reference` +(:file:`doc/python_reference.rst`). + + +.. _deprecating: + +Deprecate with a decorator or a warning +--------------------------------------- + +MNE-Python has a :func:`~mne.utils.deprecated` decorator for classes and +functions that will be removed in a future version: + +.. code-block:: python + + from mne.utils import deprecated + + @deprecated('my_function is deprecated and will be removed in 0.XX; please ' + 'use my_new_function instead.') + def my_function(): + return 'foo' + +If you need to deprecate a parameter, use :func:`mne.utils.warn`. For example, +to rename a parameter from ``old_param`` to ``new_param`` you can do something +like this: + +.. code-block:: python + + from mne.utils import warn + + def my_other_function(new_param=None, old_param=None): + if old_param is not None: + depr_message = ('old_param is deprecated and will be replaced by ' + 'new_param in 0.XX.') + if new_param is None: + new_param = old_param + warn(depr_message, FutureWarning) + else: + warn(depr_message + ' Since you passed values for both ' + 'old_param and new_param, old_param will be ignored.', + FutureWarning) + # Do whatever you have to do with new_param + return 'foo' + +When deprecating, you should also add corresponding test(s) to the relevant +test file(s), to make sure that the warning(s) are being issued in the +conditions you expect: + +.. code-block:: python + + # test deprecation warning for function + with pytest.warns(FutureWarning, match='my_function is deprecated'): + my_function() + + # test deprecation warning for parameter + with pytest.warns(FutureWarning, match='values for both old_param'): + my_other_function(new_param=1, old_param=2) + with pytest.warns(FutureWarning, match='old_param is deprecated and'): + my_other_function(old_param=2) + +You should also search the codebase for any cases where the deprecated function +or parameter are being used internally, and update them immediately (don't wait +to the *end* of the deprecation cycle to do this). Later, at the end of the +deprecation period when the stated release is being prepared: + +- delete the deprecated functions +- remove the deprecated parameters (along with the conditional branches of + ``my_other_function`` that handle the presence of ``old_param``) +- remove the deprecation tests +- double-check for any other tests that relied on the deprecated test or + parameter, and (if found) update them to use the new function / parameter. + + +Describe your changes in the changelog +-------------------------------------- + +Include in your changeset a brief description of the change in the +:ref:`changelog ` using towncrier_ format, which aggregates small, +properly-named ``.rst`` files to create a changelog. This can be +skipped for very minor changes like correcting typos in the documentation. + +There are six separate sections for changes, based on change type. +To add a changelog entry to a given section, name it as +:file:`doc/changes/dev/..rst`. The types are: + +notable + For overarching changes, e.g., adding type hints package-wide. These are rare. +dependency + For changes to dependencies, e.g., adding a new dependency or changing + the minimum version of an existing dependency. +bugfix + For bug fixes. Can change code behavior with no deprecation period. +apichange + Code behavior changes that require a deprecation period. +newfeature + For new features. +other + For changes that don't fit into any of the above categories, e.g., + internal refactorings. + +For example, for a new feature PR with number 12345, the changelog entry should be +added as a new file :file:`doc/changes/dev/12345.newfeature.rst`. The file should +contain: + +1. A brief description of the change, typically in a single line of one or two + sentences. +2. reST links to **public** API endpoints like functions (``:func:``), + classes (``:class:``), and methods (``:meth:``). If changes are only internal + to private functions/attributes, mention internal refactoring rather than name + the private attributes changed. +3. Author credit. If you are a new contributor (we're very happy to have you here! 🤗), + you should using the ``:newcontrib:`` reST role, whereas previous contributors should + use a standard reST link to their name. For example, a new contributor could write: + + .. code-block:: rst + + Short description of the changes, by :newcontrib:`Firstname Lastname`. + + And an previous contributor could write: + + .. code-block:: rst + + Short description of the changes, by `Firstname Lastname`_. + +Make sure that your name is included in the list of authors in +:file:`doc/changes/names.inc`, otherwise the documentation build will fail. +To add an author name, append a line with the following pattern (note +how the syntax is different from that used in the changelog): + +.. code-block:: rst + + .. _Your Name: https://www.your-website.com/ + +Many contributors opt to link to their GitHub profile that way. Have a look +at the existing entries in the file to get some inspiration. + +Sometimes, changes that shall appear as a single changelog entry are spread out +across multiple PRs. In this case, edit the existing towncrier file for the relevant +change, and append additional PR numbers in parentheticals with the ``:gh:`` role like: + +.. code-block:: rst + + Short description of the changes, by `Firstname Lastname`_. (:gh:`12346`) + +Test locally before opening pull requests (PRs) +----------------------------------------------- + +MNE-Python uses `continuous integration`_ (CI) to ensure code quality and +test across multiple installation targets. However, the CIs are often slower +than testing locally, especially when other contributors also have open PRs +(which is basically always the case). Therefore, do not rely on the CIs to +catch bugs and style errors for you; :ref:`run the tests locally ` +instead before opening a new PR and before each time you push additional +changes to an already-open PR. + + +Make tests fast and thorough +---------------------------- + +Whenever possible, use the testing dataset rather than one of the sample +datasets when writing tests; it includes small versions of most MNE-Python +objects (e.g., `~mne.io.Raw` objects with short durations and few +channels). You can also check which lines are missed by the tests, then modify +existing tests (or write new ones) to target the missed lines. Here's an +example that reports which lines within ``mne.viz`` are missed when running +:file:`test_evoked.py` and :file:`test_topo.py`:: + + $ pytest --cov=mne.viz --cov-report=term-missing mne/viz/tests/test_evoked.py mne/viz/tests/test_topo.py + +You can also use ``pytest --durations=5`` to ensure new or modified tests will +not slow down the test suite too much. + + +Code style +~~~~~~~~~~ + +Adhere to standard Python style guidelines +------------------------------------------ + +All contributions to MNE-Python are checked against style guidelines described +in `PEP 8`_. We also check for common coding errors (such as variables that are +defined but never used). We allow very few exceptions to these guidelines, and +use tools such as ruff_ to check code style +automatically. From the :file:`mne-python` root directory, you can check for +style violations by first installing our pre-commit hook:: + + $ pip install pre-commit + $ pre-commit install --install-hooks + +Then running:: + + $ make ruff # alias for `pre-commit run -a` + +in the shell. Several text editors or IDEs also have Python style checking, +which can highlight style errors while you code (and train you to make those +errors less frequently). This functionality is built-in to the Spyder_ IDE, but +most editors have plug-ins that provide similar functionality. Search for +:samp:`python linter ` to learn more. + + +Use consistent variable naming +------------------------------ + +Classes should be named using ``CamelCase``. Functions and instances/variables +should use ``snake_case`` (``n_samples`` rather than ``nsamples``). Avoid +single-character variable names, unless inside a :term:`comprehension ` or :ref:`generator `. + + +We (mostly) follow NumPy style for docstrings +--------------------------------------------- + +In most cases you can look at existing MNE-Python docstrings to figure out how +yours should be formatted. If you can't find a relevant example, consult the +`Numpy docstring style guidelines`_ for examples of more complicated formatting +such as embedding example code, citing references, or including rendered +mathematics. Note that we diverge from the NumPy docstring standard in a few +ways: + +1. We use a module called ``sphinxcontrib-bibtex`` to render citations. Search + our source code (``git grep footcite`` and ``git grep footbibliography``) to + see examples of how to add in-text citations and formatted references to + your docstrings, examples, or tutorials. The structured bibliographic data + lives in :file:`doc/references.bib`; please follow the existing key scheme + when adding new references (e.g., ``Singleauthor2019``, + ``AuthoroneAuthortwo2020``, ``FirstauthorEtAl2021a``, + ``FirstauthorEtAl2021b``). +2. We don't explicitly say "optional" for optional keyword parameters (because + it's clear from the function or method signature which parameters have + default values). +3. For parameters that may take multiple types, we use pipe characters instead + of the word "or", like this: ``param_name : str | None``. +4. We don't include a ``Raises`` or ``Warns`` section describing + errors/warnings that might occur. + + +Private function/method docstrings may be brief for simple functions/methods, +but complete docstrings are appropriate when private functions/methods are +relatively complex. To run some basic tests on documentation, you can use:: + + $ pytest mne/tests/test_docstring_parameters.py + $ make ruff + + +Cross-reference everywhere +-------------------------- + +Both the docstrings and dedicated documentation pages (tutorials, how-to +examples, discussions, and glossary) should include cross-references to any +mentioned module, class, function, method, attribute, or documentation page. +There are sphinx roles for all of these (``:mod:``, ``:class:``, +``:func:``, ``:meth:``, ``:attr:``, ``:doc:``) as well as a generic +cross-reference directive (``:ref:``) for linking to specific sections of a +documentation page. + +.. warning:: + + Some API elements have multiple exposure points (for example, + ``mne.set_config`` and ``mne.utils.set_config``). For cross-references to + work, they must match an entry in :file:`doc/python_reference.rst` (thus + ``:func:`mne.set_config``` will work but ``:func:`mne.utils.set_config``` + will not). + +MNE-Python also uses Intersphinx_, so you can (and should) +cross-reference to Python built-in classes and functions as well as API +elements in :mod:`NumPy `, :mod:`SciPy `, etc. See the Sphinx +configuration file (:file:`doc/conf.py`) for the list of Intersphinx projects +we link to. Their inventories can be examined using a tool like `sphobjinv`_ or +dumped to file with commands like:: + + $ python -m sphinx.ext.intersphinx https://docs.python.org/3/objects.inv > python.txt + +Note that anything surrounded by single backticks that is *not* preceded by one +of the API roles (``:class:``, ``:func:``, etc) will be assumed to be +in the MNE-Python namespace. This can save some typing especially in +tutorials; instead of ``see :func:`mne.io.Raw.plot_psd` for details`` you can +instead type ``see `mne.io.Raw.plot_psd` for details``. + + +Other style guidance +-------------------- + +- Use single quotes whenever possible. + +- Prefer :ref:`generators ` or + :term:`comprehensions ` over :func:`filter`, :func:`map` + and other functional idioms. + +- Use explicit functional constructors for builtin containers to improve + readability (e.g., :ref:`list() `, :ref:`dict() `, + :ref:`set() `). + +- Avoid nested functions or class methods if possible — use private functions + instead. + +- Avoid ``*args`` and ``**kwargs`` in function/method signatures. + + +Code organization +~~~~~~~~~~~~~~~~~ + +Importing +--------- + +Import modules in this order, preferably alphabetized within each subsection: + +1. Python built-in (``copy``, ``functools``, ``os``, etc.) +2. NumPy (``numpy as np``) and, in test files, pytest (``pytest``) +3. MNE-Python imports (e.g., ``from .pick import pick_types``) + +When importing from other parts of MNE-Python, use relative imports in the main +codebase and absolute imports in tests, tutorials, and how-to examples. Imports +for ``matplotlib``, ``scipy``, and optional modules (``sklearn``, ``pandas``, +etc.) should be nested (i.e., within a function or method, not at the top of a +file). This helps reduce import time and limit hard requirements for using MNE. + + +Return types +------------ + +Methods should modify inplace and return ``self``, functions should return +copies (where applicable). Docstrings should always give an informative name +for the return value, even if the function or method's return value is never +stored under that name in the code. + + +Visualization +------------- + +Visualization capabilities should be made available in both function and method +forms. Add public visualization functions to the :mod:`mne.viz` submodule, and +call those functions from the corresponding object methods. For example, the +method :meth:`mne.Epochs.plot` internally calls the function +:func:`mne.viz.plot_epochs`. + +All visualization functions must accept a boolean ``show`` parameter and +typically return a :class:`matplotlib.figure.Figure` (or a list of +:class:`~matplotlib.figure.Figure` objects). 3D visualization functions return +a :class:`mne.viz.Figure3D`, :class:`mne.viz.Brain`, or other return type +as appropriate. + +Visualization functions should default to the colormap ``RdBu_r`` for signed +data with a meaningful middle (zero-point) and ``Reds`` otherwise. This applies +to both visualization functions and tutorials/examples. + + +.. _run-tests: + +Running the test suite +~~~~~~~~~~~~~~~~~~~~~~ + +.. admonition:: pytest flags + :class: sidebar tip + + The ``-x`` flag exits the pytest run when any test fails; this can speed + up debugging when running all tests in a file or module. + + The ``--pdb`` flag will automatically start the python debugger upon test + failure. + +The full test suite can be run by calling ``pytest -m "not ultraslowtest" mne`` from the +``mne-python`` root folder. Testing the entire module can be quite +slow, however, so to run individual tests while working on a new feature, you +can run the following line:: + + $ pytest mne/tests/test_evoked.py::test_io_evoked --verbose + +Or alternatively:: + + $ pytest mne/tests/test_evoked.py -k test_io_evoked --verbose + +Make sure you have the testing dataset, which you can get by running this in +a Python interpreter: + +.. code-block:: python + + >>> mne.datasets.testing.data_path(verbose=True) # doctest: +SKIP + + +.. _build-docs: + +Building the documentation +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Our documentation (including docstrings in code files) is in +reStructuredText_ format and is built using Sphinx_ and `Sphinx-Gallery`_. +The easiest way to ensure that your contributions to the documentation are +properly formatted is to follow the style guidelines on this page, imitate +existing documentation examples, refer to the Sphinx and Sphinx-Gallery +reference materials when unsure how to format your contributions, and build the +docs locally to confirm that everything looks correct before submitting the +changes in a pull request. + +You can build the documentation locally using `GNU Make`_ with +:file:`doc/Makefile`. From within the :file:`doc` directory, you can test +formatting and linking by running:: + + $ make html-noplot + +This will build the documentation *except* it will format (but not execute) the +tutorial and example files. If you have created or modified an example or +tutorial, you should instead run +:samp:`make html-pattern PATTERN={}` to render +all the documentation and additionally execute just your example or tutorial +(so you can make sure it runs successfully and generates the output / figures +you expect). + +After either of these commands completes, ``make show`` will open the +locally-rendered documentation site in your browser. If you see many warnings +that seem unrelated to your contributions, it might be that your output folder +for the documentation build contains old, now irrelevant, files. Running +``make clean`` will clean those up. Additional ``make`` recipes are available; +run ``make help`` from the :file:`doc` directory or consult the +`Sphinx-Gallery`_ documentation for additional details. + + +Modifying command-line tools +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +MNE-Python provides support for a limited set of :ref:`python_commands`. +These are typically used with a call like:: + + $ mne browse_raw ~/mne_data/MNE-sample-data/MEG/sample/sample_audvis_raw.fif + +These are generally available for convenience, and can be useful for quick +debugging (in this case, for `mne.io.Raw.plot`). + +If a given command-line function fails, they can also be executed as part of +the ``mne`` module with ``python -m``. For example:: + + $ python -i -m mne browse_raw ... + +Because this was launched with ``python -i``, once the script completes +it will drop to a Python terminal. This is useful when there are errors, +because then you can drop into a :func:`post-mortem debugger `: + +.. code-block:: python + + >>> import pdb; pdb.pm() # doctest:+SKIP + + +.. _`github-workflow`: + +GitHub workflow +~~~~~~~~~~~~~~~ + +Nearly everyone in the community of MNE-Python contributors and maintainers is +a working scientist, engineer, or student who contributes to MNE-Python in +their spare time. For that reason, a set of best practices have been adopted to +streamline the collaboration and review process. Most of these practices are +common to many open-source software projects, so learning to follow them while +working on MNE-Python will bear fruit when you contribute to other projects +down the road. Here are the guidelines: + +- Search the `GitHub issues page`_ (both open and closed issues) in case + someone else has already started work on the same bugfix or feature. If you + don't find anything, `open a new issue`_ to discuss changes with maintainers + before starting work on your proposed changes. + +- Implement only one new feature or bugfix per pull request (PR). Occasionally + it may make sense to fix a few related bugs at once, but this makes PRs + harder to review and test, so check with MNE-Python maintainers first before + doing this. Avoid purely cosmetic changes to the code; they make PRs harder + to review. + +- It is usually better to make PRs *from* branches other than your main + branch, so that you can use your main branch to easily get back to a + working state of the code if needed (e.g., if you're working on multiple + changes at once, or need to pull in recent changes from someone else to get + your new feature to work properly). + +- In most cases you should make PRs *into* the upstream's main branch, unless + you are specifically asked by a maintainer to PR into another branch (e.g., + for backports or maintenance bugfixes to the current stable version). + +- Don't forget to include in your PR a brief description of the change in the + :ref:`changelog ` (:file:`doc/whats_new.rst`). + +- Our community uses the following commit tags and conventions: + + - Work-in-progress PRs should be created as `draft PRs`_ and the PR title + should begin with ``WIP``. + + - When you believe a PR is ready to be reviewed and merged, `convert it + from a draft PR to a normal PR`_, change its title to begin with ``MRG``, + and add a comment to the PR asking for reviews (changing the title does not + automatically notify maintainers). + + - PRs that only affect documentation should additionally be labelled + ``DOC``, bugfixes should be labelled ``FIX``, and new features should be + labelled ``ENH`` (for "enhancement"). ``STY`` is used for style changes + (i.e., improving docstring consistency or formatting without changing its + content). + + - the following commit tags are used to interact with our + `continuous integration`_ (CI) providers. Use them judiciously; *do not + skip tests simply because they are failing*: + + - ``[skip circle]`` Skip `CircleCI`_, which tests successful building of + our documentation. + + - ``[skip actions]`` Skip our `GitHub Actions`_, which test installation + and execution on Linux and macOS systems. + + - ``[skip azp]`` Skip `azure`_ which tests installation and execution on + Windows systems. + + - ``[ci skip]`` is an alias for ``[skip actions][skip azp][skip circle]``. + Notice that ``[skip ci]`` is not a valid tag. + + - ``[circle full]`` triggers a "full" documentation build, i.e., all code + in tutorials and how-to examples will be *executed* (instead of just + nicely formatted) and the resulting output and figures will be rendered + as part of the tutorial/example. + +- Examples and tutorials should execute as quickly and with as low memory usage as + possible while still conveying necessary information. To see current execution + times and memory usage, visit the `sg_execution_times page`_. To see unused API + entries, see the `sg_api_usage page`_. + +`This sample pull request`_ exemplifies many of the conventions listed above: +it addresses only one problem; it started with an issue to discuss the problem +and some possible solutions; it is a PR from the user's non-main branch into +the upstream main branch; it separates different kinds of changes into +separate commits and uses labels like ``DOC``, ``FIX``, and ``STY`` to make it +easier for maintainers to review the changeset; etc. If you are new to GitHub +it can serve as a useful example of what to expect from the PR review process. + + +.. MNE + +.. _`GitHub issues marked "easy"`: https://github.com/mne-tools/mne-python/issues?q=is%3Aissue+is%3Aopen+label%3AEASY +.. _open a new issue: https://github.com/mne-tools/mne-python/issues/new/choose +.. _This sample pull request: https://github.com/mne-tools/mne-python/pull/6230 +.. _our user forum: https://mne.discourse.group +.. _sg_execution_times page: https://mne.tools/dev/sg_execution_times.html +.. _sg_api_usage page: https://mne.tools/dev/sg_api_usage.html + +.. git installation + +.. _the .dmg installer: https://git-scm.com/download/mac +.. _official Linux instructions: https://git-scm.com/download/linux +.. _more detailed instructions and alternatives: https://www.atlassian.com/git/tutorials/install-git +.. _Windows subsystem for Linux: https://docs.microsoft.com/en-us/windows/wsl/about +.. _GitHub desktop: https://desktop.github.com/ +.. _GNU Make: https://www.gnu.org/software/make/ +.. _ezwinports: https://sourceforge.net/projects/ezwinports/files/ + +.. github help pages + +.. _fork: https://help.github.com/en/articles/fork-a-repo +.. _clone: https://help.github.com/en/articles/cloning-a-repository +.. _push: https://help.github.com/en/articles/pushing-to-a-remote +.. _forking: https://help.github.com/en/articles/fork-a-repo +.. _cloning: https://help.github.com/en/articles/cloning-a-repository +.. _pushing: https://help.github.com/en/articles/pushing-to-a-remote +.. _branches: https://help.github.com/en/articles/about-branches +.. _several help pages: https://help.github.com/en/articles/connecting-to-github-with-ssh +.. _draft PRs: https://help.github.com/en/articles/about-pull-requests#draft-pull-requests +.. _convert it from a draft PR to a normal PR: https://help.github.com/en/articles/changing-the-stage-of-a-pull-request +.. _pull request: https://help.github.com/en/articles/creating-a-pull-request-from-a-fork +.. _creating a PR from a fork: https://help.github.com/en/articles/creating-a-pull-request-from-a-fork + +.. git docs + +.. _check it out: https://git-scm.com/docs/git-checkout +.. _added: https://git-scm.com/docs/git-add +.. _commits: https://git-scm.com/docs/git-commit +.. _commit: https://git-scm.com/docs/git-commit +.. _status: https://git-scm.com/docs/git-status + +.. git book + +.. _stage: https://git-scm.com/book/en/v2/Git-Tools-Interactive-Staging +.. _configuring git: https://www.git-scm.com/book/en/v2/Customizing-Git-Git-Configuration + +.. sphinx + +.. _reStructuredText: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html +.. _intersphinx: https://www.sphinx-doc.org/en/master/usage/extensions/intersphinx.html +.. _sphobjinv: https://sphobjinv.readthedocs.io/en/latest/ + +.. linting + +.. _PEP 8: https://www.python.org/dev/peps/pep-0008/ +.. _ruff: https://beta.ruff.rs/docs + +.. misc + +.. _miniconda: https://conda.io/en/latest/miniconda.html +.. _Spyder: https://www.spyder-ide.org/ +.. _continuous integration: https://en.wikipedia.org/wiki/Continuous_integration +.. _matplotlib: https://matplotlib.org/ +.. _github actions: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions +.. _azure: https://dev.azure.com/mne-tools/mne-python/_build/latest?definitionId=1&branchName=main +.. _CircleCI: https://circleci.com/gh/mne-tools/mne-python + +.. optipng + +.. _optipng: https://optipng.sourceforge.net/ +.. _optipng for Windows: http://prdownloads.sourceforge.net/optipng/optipng-0.7.8-win64.zip?download + +.. include:: ../links.inc diff --git a/mne-python/source/doc/development/governance.rst b/mne-python/source/doc/development/governance.rst new file mode 100644 index 0000000000000000000000000000000000000000..a0c8c2c89a295ffddb7f538d53b41e7a52170d20 --- /dev/null +++ b/mne-python/source/doc/development/governance.rst @@ -0,0 +1,380 @@ +.. _governance: + +================== +Project Governance +================== + +The purpose of this document is to formalize the governance process +used by the MNE-Python project in both ordinary and extraordinary +situations, and to clarify how decisions are made and how the various +elements of our community interact, including the relationship between +open source collaborative development and work that may be funded by +for-profit or non-profit entities. + +The Project +=========== + +The MNE-Python Project (The Project) is an open source software project. The +goal of The Project is to develop open source software for analysis of +neuroscience data in Python. The Project is released under the BSD (or similar) +open source license, developed openly and is hosted publicly under the +``mne-tools`` GitHub organization. + +The Project is developed by a team of distributed developers, called +Contributors. Contributors are individuals who have contributed code, +documentation, designs, or other work to the Project. Anyone can be a +Contributor. Contributors can be affiliated with any legal entity or +none. Contributors participate in the project by submitting, reviewing, +and discussing GitHub Pull Requests and Issues and participating in open +and public Project discussions on GitHub, Discourse, and other +channels. The foundation of Project participation is openness and +transparency. + +The Project Community consists of all Contributors and Users of the +Project. Contributors work on behalf of and are responsible to the +larger Project Community and we strive to keep the barrier between +Contributors and Users as low as possible. + +The Project is not a legal entity, nor does it currently have any formal +relationships with legal entities. + +Governance Model +================ + +.. _leadership-roles: + +Leadership Roles +^^^^^^^^^^^^^^^^ + +The MNE-Python leadership structure shall consist of the following groups. +A list of the current members of the respective groups is maintained at the +page :ref:`governance-people`. + +Maintainer Team +--------------- + +The Maintainer Team (:ref:`members `) is responsible for +implementing changes to the software and supporting the user community. Duties: + +- Infrastructure/large-scale software decisions, in partnership with the Steering + Council +- Reviewing and merging pull requests +- Responding to issues on GitHub +- Monitoring CI failures and addressing them +- Community maintenance: answering forum posts, holding office hours +- Community information: social media announcements (releases, new features, etc) +- Training new members of the Maintainer Team + +*Note:* different permissions may be given to each maintainer based on the work they do +(e.g., GitHub repository triage/merge/admin permissions, social media account access, +Discord admin roles, forum admin rights). The role of maintainer does not confer these +automatically. + +Steering Council +---------------- + +The Steering Council (:ref:`members `) is responsible for +guiding and shepherding the project on a day-to-day basis. Duties: + +- Obtaining funding (either by writing grants specifically for MNE development, or + convincing others to include funds for MNE development in their research grants) +- Translating high-level roadmap guidance from the Advisory Board (e.g. “better support + for OPMs”) into actionable roadmap items (e.g., “Add support for OPM manufacturers + besides QuSpin, and add standard preprocessing routines for coreg and OPM-specific + artifacts”) +- Coordination with the larger Scientific Python ecosystem +- Large-scale changes to the software (e.g., type hints, docdict, things that affect + multiple submodules), in partnership with the Maintainer Team +- Infrastructure decisions (e.g., dependency version policy, release cadence, CI + management, etc), in partnership with the Maintainer Team +- Any other governance task not mentioned elsewhere, and that falls outside of the + responsibilities of other teams +- Attendance at Steering Council meetings (approx. every 2 weeks; time to be decided + among SC members) +- Attendance at Advisory Board meetings (approx. every 1-2 years) +- Write funding proposals +- Communicate/coordinate with Maintainer Team + +Members of the Steering Council shall additionally be considered as members of the +Maintainer Team, *ex officio*, and thus shall have the necessary rights and privileges +afforded to maintainers (passwords, merge rights, etc). + +Chair of the Steering Council +----------------------------- + +The Chair (:ref:`member `) of the Steering Council is +responsible for liaising between the Steering Council and the community. Duties: + +- Convening the Steering Council meetings +- Calling for votes when consensus fails +- Communicating important decisions (and the context for why those decisions were + taken) to the community + +External Advisory Board +----------------------- + +The External Advisory Board (:ref:`members `) is responsible for +high-level roadmap and funding guidance. Duties: + +- Attendance at Advisory Board meetings (approx. every 1-2 years) +- Periodically communicating with Steering Council to impart guidance + +Meetings +^^^^^^^^ + +Maintainer Meetings +------------------- + +The Maintainer Team can decide if there should be maintainer meetings or not. These +could be either discussion meetings or social meetings to keep in touch with each other +(or something completely different!). Frequency and time could vary. + +Steering Council Meetings +------------------------- + +The Steering Council will have mandatory meetings every two weeks to discuss project +management and funding. The Steering Council may decide to change meeting time or +frequency at their discretion. + +All-hands Meetings +------------------ + +At least once a year, all maintainers and Steering Council members should come together +in a (possibly virtual) meeting. Meeting time will be determined via poll. During this +meeting, any governance changes proposed since the prior meeting shall be discussed and +may be adopted by vote. + +Population of Leadership Roles +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Maintainer Team +--------------- + +Appointment +~~~~~~~~~~~ + +- Once per year, before the annual all-hands meeting, the Maintainer Team shall assess + their anticipated needs for the coming year. During the meeting, they shall decide how + many new maintainers they want to add to their team. New maintainers are selected from + applications by a vote of the currently-serving maintainers and the Steering Council. +- Ad-hoc additions are possible by initiative of the Steering Council for exceptional + circumstances, e.g., hiring someone with grant funds to specifically do MNE + maintenance. These ad-hoc additions do not necessarily require a vote from the + Maintainer Team, as the job application procedures of the hiring institution are + assumed to be sufficiently rigorous to avoid bias, nepotism, etc. + +Duration of service +~~~~~~~~~~~~~~~~~~~ + +Appointment to the Maintainer Team is for an indefinite term. + +Termination +~~~~~~~~~~~ + +Loss of maintainer status (and revocation of associated rights and +privileges, e.g., passwords, merge rights, etc) can occur under the following +circumstances: + +- *Voluntary resignation*, at any time, for any reason. +- *Inactivity*. Once per year, before the annual all-hands meeting, the Steering Council + shall assess maintainer activity for the preceding year. Any maintainers seeming to be + inactive shall be contacted and given opportunity to dispute their inactivity (e.g., + by highlighting ways they have been working in the MNE community that may not be + visible from simple metrics like GitHub or forum activity reports). Maintainers who do + not dispute their inactivity (or fail to respond within 14 days, or longer at the + discretion of the Steering Council) shall be removed from the Maintainer Team. In + cases where the Steering Council and the maintainer still disagree about the alleged + inactivity, removal may still occur by a two-thirds majority vote of the rest of the + Maintainer Team. +- *Conduct*. At any time, a maintainer may be removed by unanimous vote of the + code-of-conduct committee, for violations of our community guidelines (in accordance + with the enforcement guidelines outlined therein). + +*Reinstatement*. Maintainers who voluntarily resigned may be re-appointed on an ad-hoc +basis by a vote of the current Maintainer Team. Maintainers removed for inactivity may +re-apply to an annual call for new maintainers. Maintainers removed for reasons of +conduct may be reinstated only if their eligibility is allowed/restored by the +code-of-conduct committee in accordance with the enforcement section of our Community +Guidelines. In such cases the re-eligible former maintainer may re-apply through the +annual appointment process. + +Steering Council +---------------- + +Appointment +~~~~~~~~~~~ +A term on the Steering Council shall last approximately 2 years. Terms shall be +staggered such that no more than half of the seats shall be open for election in any +given year. Upon first constitution, the Steering Council decides which 50% of the +members shall be granted an initial three year term to initiate the staggering. + +The Maintainer Team and current Steering Council will vote to fill the open seats on the +Steering Council. Candidates can be (self-)nominated from the current Maintainer Team +and Steering Council. + +At any time, the Steering Council may increase the number of seats on the Council to +adapt to the Council’s workload and needs. New seats shall be filled in the same manner +as normal (re-)elections, i.e., by vote open to all members of the Maintainer Team and +Steering Council. Term length shall be set so as to maintain the 50/50 balance of +staggered re-election cycles as nearly as possible, and in cases where perfect balance +already exists, the term shall err towards being *longer*. + +In the case of vacancies due to termination (see below), the Steering Council may call a +special election (following the same procedures as in a normal (re-)election), or may +choose to wait to fill the seat until the next scheduled election. For filled vacancies, +the term shall be the balance of the unserved term of the person vacating the seat, +unless the remaining time after the vacancy-filling election is 6 months or shorter, in +which case the term shall be for 2 years plus the remaining time on the vacant seat. + +Termination +~~~~~~~~~~~ + +Loss of Steering Council status (and revocation of associated rights and privileges, +e.g., passwords, merge rights, etc) can occur under the following circumstances: + +- *Voluntary resignation*, at any time, for any reason. +- *Conduct*. At any time, a member of the Steering Council may be removed by unanimous + vote of the code-of-conduct committee, for violations of our community guidelines (in + accordance with the enforcement guidelines outlined therein). + +External Advisory Board +----------------------- + +The External Advisory Board shall be populated by invitation from the Steering Council. +Anyone may propose individuals for potential invitation. Appointment and removal from +the External Advisory Board is determined by the Steering Council. + +Decision Making Process +^^^^^^^^^^^^^^^^^^^^^^^ + +Announcement of Elections +------------------------- + +All votes shall be open for at least ten days and shall be announced 14 days in advance +to all eligible voters by email. The voting deadline shall also be added to the core +team’s shared Google calendar. At least one reminder shall be sent out half-way through +the voting period. + +Voting Mechanism +---------------- + +All elections shall be held as anonymous online votes using ElectionBuddy or a similar +service. Unless otherwise specified the mechanism shall be +`ranked choice voting `__ +with a threshold of 50% + 1 vote. That means, everyone ranks those candidates (in order +of preference) that they could see filling the role in question. Note that it is +possible for a voter to reject all candidates by submitting a blank ballot, so that if a +single person is running for a seat it is still possible for them to fail to be elected +if enough voters cast blank ballots. + +Voting for the Steering Council +------------------------------- + +Votes for Steering Council membership shall be scheduled as-needed to address Steering +Council workload, and advertised to eligible candidates (i.e., the Maintainer Team) for +a minimum of 14 days, after which a vote of current maintainers and Steering Council +members shall be scheduled. + +Voting for the Maintainer Team +------------------------------ + +Votes for additions to the Maintainer Team shall be scheduled promptly following the +annual all-hands meeting. The Maintainer Team shall advertise the open seats via online +MNE-Python channels. Applications (consisting of a short candidate statement) must be +open for a minimum of 14 days, after which a vote of the current maintainers and +Steering Council shall be scheduled. The Maintainer Team shall set up a confidential +submission system for applications (consisting of short candidate statements), such as a +dedicated email address, Google form, or similar confidential submission mechanism. + +Institutional Partners and Funding +================================== + +The leadership roles for the project are :ref:`defined above `. No +outside institution, individual, or legal entity has the ability to own, +control, usurp, or influence the project other than by participating in +the Project in one of those roles. However, because +institutions can be an important funding mechanism for the project, it +is important to formally acknowledge institutional participation in the +project. These are Institutional Partners. + +An Institutional Contributor is any individual Project Contributor who +contributes to the project as part of their official duties at an +Institutional Partner. Likewise, an Institutional Project Leader is anyone +in a Project leadership role who contributes to the project as part +of their official duties at an Institutional Partner. + +With these definitions, an Institutional Partner is any recognized legal +entity in any country that employs at least 1 Institutional Contributor or +Institutional Project Leader. Institutional Partners can be for-profit or +non-profit entities. + +Institutions become eligible to become an Institutional Partner by +employing individuals who actively contribute to The Project as part of +their official duties. To state this another way, the only way for a +Partner to influence the project is by actively contributing to the open +development of the project, in equal terms to any other member of the +community of Contributors and Leaders. Merely using Project +Software in institutional context does not allow an entity to become an +Institutional Partner. Financial gifts do not enable an entity to become +an Institutional Partner. Once an institution becomes eligible for +Institutional Partnership, the Steering Council must nominate and +approve the Partnership. + +If, at some point, an existing Institutional Partner stops having any +contributing employees, then a one year grace period commences. If, at +the end of this one-year period, they continue not to have any +contributing employees, then their Institutional Partnership will +lapse, and resuming it will require going through the normal process +for new Partnerships. + +An Institutional Partner is free to pursue funding for their work on The +Project through any legal means. This could involve a non-profit +organization raising money from private foundations and donors or a +for-profit company building proprietary products and services that +leverage Project Software and Services. Funding acquired by +Institutional Partners to work on The Project is called Institutional +Funding. However, no funding obtained by an Institutional Partner can +override Project Leadership. If a Partner has funding to do MNE-Python work +and the Project Leadership decides to not pursue that work as a project, the +Partner is free to pursue it on their own. However, in this situation, +that part of the Partner’s work will not be under the MNE-Python umbrella and +cannot use the Project trademarks in any way that suggests a formal +relationship. + +Institutional Partner benefits are: + +- optional acknowledgement on the MNE-Python website and in talks +- ability to acknowledge their own funding sources on the MNE-Python + website and in talks +- ability to influence the project through the participation of their + Institutional Contributors and Institutional Project Leaders. +- invitation of the Council Members to MNE-Python Developer Meetings + +A list of current Institutional Partners is maintained at the page +:ref:`supporting-institutions`. + +Document History +================ + +https://github.com/mne-tools/mne-python/commits/main/doc/overview/governance.rst + + +Acknowledgements +================ + +Substantial portions of this document were adapted from the +`SciPy project's governance document +`_, +which in turn was adapted from +`Jupyter/IPython project's governance document +`_ and +`NumPy's governance document +`_. + +License +======= + +To the extent possible under law, the authors have waived all +copyright and related or neighboring rights to the MNE-Python project +governance document, as per the `CC-0 public domain dedication / license +`_. diff --git a/mne-python/source/doc/development/index.rst b/mne-python/source/doc/development/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..98fc28f8e7fcec176de03a53ad01eda2999fe18e --- /dev/null +++ b/mne-python/source/doc/development/index.rst @@ -0,0 +1,35 @@ +MNE-Python Development +====================== + +.. NOTE: this first section (up until "overview of contribution process") is + basically a copy/paste of CONTRIBUTING.md from the repository root, with one + sentence deleted to avoid self-referential linking. Changes made here should + be mirrored there, and vice-versa. + +MNE-Python is maintained by a community of scientists and research labs. The +project accepts contributions in the form of bug reports, fixes, feature +additions, and documentation improvements (including typo corrections). The +best way to start contributing is by `opening an issue`_ on our GitHub page to +discuss ideas for changes or enhancements, or to tell us about behavior that +you think might be a bug. For *general troubleshooting* or *usage questions*, +please consider posting your questions on our `MNE Forum`_. + +Users and contributors to MNE-Python are expected to follow our +`code of conduct`_. + +The `contributing guide`_ has details on the preferred contribution workflow +and the recommended system configuration for a smooth contribution/development +experience. + +.. _`opening an issue`: https://github.com/mne-tools/mne-python/issues/new/choose +.. _`MNE Forum`: https://mne.discourse.group +.. _`code of conduct`: https://github.com/mne-tools/.github/blob/main/CODE_OF_CONDUCT.md +.. _`contributing guide`: https://mne.tools/dev/development/contributing.html + +.. toctree:: + :hidden: + + contributing + whats_new + roadmap + governance diff --git a/mne-python/source/doc/development/roadmap.rst b/mne-python/source/doc/development/roadmap.rst new file mode 100644 index 0000000000000000000000000000000000000000..bab992d89d409faffc680c00d6b6e29333576276 --- /dev/null +++ b/mne-python/source/doc/development/roadmap.rst @@ -0,0 +1,308 @@ +Roadmap +======= + +This page describes some of the major medium- to long-term goals for +MNE-Python. These are goals that require substantial effort and/or +API design considerations. Some of these may be suitable for Google Summer of +Code projects, while others require more extensive work. + + +Open +---- + +Type Annotations +^^^^^^^^^^^^^^^^ + +We would like to have type annotations for as much of our codebase as is practicable. +The main motivation for this is to improve the end-user experience when writing analysis +code that uses MNE-Python (i.e., code-completion suggestions, which rely on static +analysis / type hints). The main discussion of how to go about this is in :gh:`12243`. +Some piecemeal progress has been made (e.g., :gh:`12250`) but there isn't currently +anyone actively chipping away at this, hence its status as "open" rather than "in +progress". + +Docstring De-duplication +^^^^^^^^^^^^^^^^^^^^^^^^ + +For many years, MNE-Python has used a technique borrowed from SciPy (called +`doccer `__) +for improving the consistency of parameter names and descriptions that recur across our +API. For example, parameters for number of parallel jobs to use, for specifying random +seeds, or for controlling the appearance of a colorbar on a plot --- all of these appear +in multiple functions/methods in MNE-Python. The approach works by re-defining a +function's ``__doc__`` attribute at import time, filling in placeholders in the +docstring's parameter list with fully spelled-out equivalents (which are stored in a big +dictionary called the ``docdict``). There are two major downsides: + +1. Many docstrings can't be read (at least not in full) while browsing the source code. +2. Static code analyzers don't have access to the completed docstrings, so things like + hover-tooltips in IDEs are less useful than they would be if the docstrings were + complete in-place. + +A possible route forward: + +- Convert all docstrings to be fully spelled out in the source code. +- Instead of maintaining the ``docdict``, maintain a registry of sets of + function+parameter combinations that ought to be identical. +- Add a test that the entries in the registry are indeed identical, so that + inconsistencies cannot be introduced in existing code. +- Add a test that parses docstrings in any *newly added* functions and looks for + parameter names that maybe should be added to the registry of identical docstrings. +- To allow for parameter descriptions that should be *nearly* identical (e.g., the same + except one refers to :class:`~mne.io.Raw` objects and the other refers to + :class:`~mne.Epochs` objects), consider using regular expressions to check the + "identity" of the parameter descriptions. + +The main discussion is in :gh:`8218`; a wider discussion among maintainers of other +packages in the Scientific Python Ecosystem is +`here `__. + +Containerization +^^^^^^^^^^^^^^^^ + +Users sometimes encounter difficulty getting a working MNE-Python environment on shared +resources (such as compute clusters), due to various problems (old versions of package +managers or graphics libraries, lack of sufficient permissions, etc). Providing a +robust and up-to-date containerized distribution of MNE-Python would alleviate some of +these issues. Initial efforts can be seen in the +`MNE-Docker repository `__; these efforts +should be revived, brought up-to-date as necessary, and integrated into our normal +release process so that the images do not become stale. + +Education +^^^^^^^^^ + +Live workshops/tutorials/trainings on MNE-Python have historically been organized +*ad-hoc* rather than centrally. Instructors for these workshops are often approached +directly by the organization or group desiring to host the training, and there is often +no way for users outside that group to attend (or even learn about the opportunity). At +a minimum, we would like to have a process for keeping track of educational events that +feature MNE-Python or other tools in the MNE suite. Ideally, we would go further and +initiate a recurring series of tutorials that could be advertised widely. Such events +might even provide a small revenue stream for MNE-Python, to support things like +continuous integration costs. + +Documentation interactivity +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +With jupyterlite support landing `in sphinx-gallery `__, +we should work on allowing users to run examples interactively on our website. +See :gh:`13616` for more details and discussion. + + +In progress +----------- + +Diversity, Equity, and Inclusion (DEI) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +MNE-Python is committed to recruiting and retaining a diverse pool of +contributors, see :gh:`8221`. + +First-class OPM support +^^^^^^^^^^^^^^^^^^^^^^^ +MNE-Python has support for reading some OPM data formats such as FIF and FIL/QuSpin. +Support should be added for other manufacturers, and standard preprocessing routines +should be added to deal with coregistration adjustment and OPM-specific artifacts. +See for example :gh:`11275`, :gh:`11276`, :gh:`11579`, :gh:`12179`. + +Deep source modeling +^^^^^^^^^^^^^^^^^^^^ +Existing source modeling and inverse routines are not explicitly designed to +deal with deep sources. Advanced algorithms exist from MGH for enhancing +deep source localization, and these should be implemented and vetted in +MNE-Python. See :gh:`6784`. + +Time-frequency classes +^^^^^^^^^^^^^^^^^^^^^^ +Historically our codebase had classes related to :term:`TFRs ` that +were incomplete. New classes are being built from the ground up: + +- new classes :class:`~mne.time_frequency.Spectrum` and + :class:`~mne.time_frequency.EpochsSpectrum` (implemented in :gh:`10184`, with + follow-up tweaks and bugfixes in :gh:`11178`, :gh:`11259`, :gh:`11280`, :gh:`11345`, + :gh:`11418`, :gh:`11563`, :gh:`11680`, :gh:`11682`, :gh:`11778`, :gh:`11921`, + :gh:`11978`, :gh:`12747`), and corresponding array-based constructors + :class:`~mne.time_frequency.SpectrumArray` and + :class:`~mne.time_frequency.EpochsSpectrumArray` (:gh:`11803`). + +- new class :class:`~mne.time_frequency.RawTFR` and updated classes + :class:`~mne.time_frequency.EpochsTFR` and :class:`~mne.time_frequency.AverageTFR`, + and corresponding array-based constructors :class:`~mne.time_frequency.RawTFRArray`, + :class:`~mne.time_frequency.EpochsTFRArray` and + :class:`~mne.time_frequency.AverageTFRArray` (implemented in :gh:`11282`, with + follow-ups in :gh:`12514`, :gh:`12842`). + +- new/updated classes for source-space frequency and time-frequency data are not yet + implemented. + +Other related issues: :gh:`6290`, :gh:`7671`, :gh:`8026`, :gh:`8724`, :gh:`9045`, +and PRs: :gh:`6609`, :gh:`6629`, :gh:`6672`, :gh:`6673`, :gh:`8397`, :gh:`8892`. + +Modernization of realtime processing +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +LSL has become the de facto standard for streaming data from EEG/MEG systems. +We should deprecate `MNE-Realtime`_ in favor of the newly minted `MNE-LSL`_. +We should then fully support MNE-LSL using modern coding best practices such as CI +integration. + +Core components of commonly used real-time processing pipelines should be implemented in +MNE-LSL, including but not limited to realtime IIR filtering, artifact rejection, +montage and reference setting, and online averaging. Integration with standard +MNE-Python plotting routines (evoked joint plots, topomaps, etc.) should be +supported with continuous updating. + +Clustering statistics API +^^^^^^^^^^^^^^^^^^^^^^^^^ +The current clustering statistics code has limited functionality. It should be +re-worked to create a new ``cluster_based_statistic`` or similar function. + +The new API will likely be along the lines of:: + + cluster_stat(obs, design, *, alpha=0.05, cluster_alpha=0.05, ...) + +with: + +``obs`` : :class:`pandas.DataFrame` + Has columns like "subject", "condition", and "data". + The "data" column holds things like :class:`mne.Evoked`, + :class:`mne.SourceEstimate`, :class:`mne.time_frequency.Spectrum`, etc. +``design`` : `str` + Likely Wilkinson notation to mirror :func:`patsy.dmatrices` (e.g., this is + is used by :class:`statsmodels.regression.linear_model.OLS`). Getting from the + string to the design matrix could be done via Patsy or more likely + `Formulaic `__. + +This generic API will support mixed within- and between-subjects designs, +different statistical functions/tests, etc. This should be achievable without +introducing any significant speed penalty (e.g., < 10% slower) compared to the existing +more specialized/limited functions, since most computation cost is in clustering rather +than statistical testing. + +The clustering function will return a user-friendly ``ClusterStat`` object or similar +that retains information about dimensionality, significance, etc. and facilitates +plotting and interpretation of results. + +Clear tutorials will be needed to: + +1. Show how different contrasts can be done (toy data). +2. Show some common analyses on real data (time-freq, sensor space, source space, etc.) + +Regression tests will be written to ensure equivalent outputs when compared to FieldTrip +for cases that FieldTrip also supports. + +More details are in :gh:`4859`; progress in :gh:`12663`. + + +.. _documentation-updates: + +Documentation updates +^^^^^^^^^^^^^^^^^^^^^ +Our documentation has many minor issues, which can be found under the tag +:gh:`labels/DOC`. + + +Completed +--------- + +3D visualization +^^^^^^^^^^^^^^^^ +Historically we used Mayavi for 3D visualization, but faced limitations and challenges +with it. We switched to PyVista to get major improvements, such as: + +1. *Proper notebook support (through ``ipyvtklink``)* (complete; updated to use ``trame``) +2. *Better interactivity with surface plots* (complete) +3. Time-frequency plotting (complementary to volume-based + :ref:`time-frequency-viz`) +4. Integration of multiple functions as done in ``mne_analyze``, e.g., + simultaneous source estimate viewing, field map + viewing, head surface display, etc. These were all available in + separate functions, but can now be combined in a single plot. + +The meta-issue tracking to-do lists for surface plotting was :gh:`7162`. + +Improved sEEG/ECoG/DBS support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +iEEG-specific pipeline steps such as electrode localization and visualizations +are now available in `MNE-gui-addons`_. + +Access to open EEG/MEG databases +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Open EEG/MEG databases are now more easily accessible via standardized tools such as +`openneuro-py`_. + +Eye-tracking support +^^^^^^^^^^^^^^^^^^^^ +We had a GSoC student funded to improve support for eye-tracking data, see +`the GSoC proposal `__ +for details. An EyeLink data reader and analysis/plotting functions are now available. + +Pediatric and clinical MEG pipelines +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +MNE-Python provides automated analysis of BIDS-compliant datasets via +`MNE-BIDS-Pipeline`_. Functionality from the +`mnefun `__ pipeline, +which has been used extensively for pediatric data analysis at `I-LABS`_, +now provides better support for pediatric and clinical data processing. +Multiple processing steps (e.g., eSSS), sanity checks (e.g., cHPI quality), +and reporting (e.g., SSP joint plots, SNR plots) have been added. + +Integrate OpenMEEG via improved Python bindings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`OpenMEEG`_ is a state-of-the art solver for +forward modeling in the field of brain imaging with MEG/EEG. It solves +numerically partial differential equations (PDE). It is written in C++ with +Python bindings written in SWIG. +The ambition of the project is to integrate OpenMEEG into MNE offering to MNE +the ability to solve more forward problems (cortical mapping, intracranial +recordings, etc.). Tasks that have been completed: + +- Cleanup Python bindings (remove useless functions, check memory managements, + etc.) +- Understand how MNE encodes info about sensors (location, orientation, + integration points etc.) and allow OpenMEEG to be used. +- Modernize CI systems (e.g., using ``cibuildwheel``). +- Automated deployment on PyPI and conda-forge. + +.. _time-frequency-viz: + +Time-frequency visualization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +We implemented a viewer for interactive visualization of volumetric +source-time-frequency (5-D) maps on MRI slices (orthogonal 2D viewer). +`NutmegTrip `__ +(written by Sarang Dalal) provides similar functionality in MATLAB in +conjunction with FieldTrip. Example of NutmegTrip's source-time-frequency mode +in action (click for link to YouTube): + +.. image:: https://i.ytimg.com/vi/xKdjZZphdNc/maxresdefault.jpg + :target: https://www.youtube.com/watch?v=xKdjZZphdNc + :width: 50% + +See :func:`mne-gui-addons:mne_gui_addons.view_vol_stc`. + +Distributed computing support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`MNE-BIDS-Pipeline`_ has been enhanced with support for cloud computing +via `Dask`_ and :doc:`joblib `. +After configuring Dask to use local or remote distributed computing resources, +MNE-BIDS-Pipeline can readily make use of remote workers to parallelize +processing across subjects. + +2D visualization +^^^^^^^^^^^^^^^^ +`This goal `__ +was completed under CZI `EOSS2`_. Some additional enhancements that could also +be implemented are listed in :gh:`7751`. + +Tutorial / example overhaul +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +`This goal `__ +was completed under CZI `EOSS2`_. Ongoing documentation needs are listed in +:ref:`documentation-updates`. + +Cluster computing images +^^^^^^^^^^^^^^^^^^^^^^^^ +As part of `this goal `__, +we created docker images suitable for cloud computing via `MNE-Docker`_. + +.. _I-LABS: http://ilabs.washington.edu/ diff --git a/mne-python/source/doc/development/whats_new.rst b/mne-python/source/doc/development/whats_new.rst new file mode 100644 index 0000000000000000000000000000000000000000..79bf102a2b3fa447812ee258b89aab4713f98932 --- /dev/null +++ b/mne-python/source/doc/development/whats_new.rst @@ -0,0 +1,48 @@ +.. _whats_new: + +What's new +========== + +Changes for each version of MNE-Python are listed below. + +.. toctree:: + :maxdepth: 1 + + ../changes/dev.rst + ../changes/v1.11.rst + ../changes/v1.10.rst + ../changes/v1.9.rst + ../changes/v1.8.rst + ../changes/v1.7.rst + ../changes/v1.6.rst + ../changes/v1.5.rst + ../changes/v1.4.rst + ../changes/v1.3.rst + ../changes/v1.2.rst + ../changes/v1.1.rst + ../changes/v1.0.rst + ../changes/v0.24.rst + ../changes/v0.23.rst + ../changes/v0.22.rst + ../changes/v0.21.rst + ../changes/v0.20.rst + ../changes/v0.19.rst + ../changes/v0.18.rst + ../changes/v0.17.rst + ../changes/v0.16.rst + ../changes/v0.15.rst + ../changes/v0.14.rst + ../changes/v0.13.rst + ../changes/v0.12.rst + ../changes/v0.11.rst + ../changes/v0.10.rst + ../changes/v0.9.rst + ../changes/v0.8.rst + ../changes/v0.7.rst + ../changes/v0.6.rst + ../changes/v0.5.rst + ../changes/v0.4.rst + ../changes/v0.3.rst + ../changes/v0.2.rst + ../changes/v0.1.rst + ../old_versions/index.rst diff --git a/mne-python/source/doc/documentation.html b/mne-python/source/doc/documentation.html new file mode 100644 index 0000000000000000000000000000000000000000..6395cf555781eb8032ee456fe5fcb10a70fc1784 --- /dev/null +++ b/mne-python/source/doc/documentation.html @@ -0,0 +1,9 @@ + + + + + + +

Please follow this link.

+ + diff --git a/mne-python/source/doc/documentation/cite.rst b/mne-python/source/doc/documentation/cite.rst new file mode 100644 index 0000000000000000000000000000000000000000..5d67fec3ea3f02f29054c999377313ea3fca5315 --- /dev/null +++ b/mne-python/source/doc/documentation/cite.rst @@ -0,0 +1,54 @@ +.. _cite: + +How to cite MNE-Python +====================== + +Citing the software +------------------- + +To cite specific version numbers of the software, you can use the DOIs provided +by `Zenodo `_; look for the "versions" +list in the sidebar to find the correct DOI for the version you used in your +work (or to cite the project in a general way, use +https://doi.org/10.5281/zenodo.592483). Additionally, we ask that when citing +MNE-Python you also cite the canonical journal article reference +:footcite:`GramfortEtAl2013a`: + +.. footbibliography:: + +.. dropdown:: BibTeX for MNE-Python + :color: info + :icon: typography + + .. include:: ../references.bib + :code: bibtex + :start-after: % MNE-Python reference + :end-before: % everything else + + +Citing the inverse imaging algorithms +------------------------------------- + +To cite MNE-C or the inverse imaging implementations provided by the MNE +software, please use :footcite:`GramfortEtAl2014`: + +.. footbibliography:: + + +.. dropdown:: BibTeX for inverse algorithms / MNE-C + :color: info + :icon: typography + + .. include:: ../references.bib + :code: bibtex + :start-after: % MNE-C reference + :end-before: % MNE-Python reference + + +Citing other algorithms +----------------------- + +Depending on your research topic, it may also be appropriate to cite related +method papers, some of which are listed in the documentation strings of the +relevant functions or methods. All references cited in the MNE-Python codebase +and documentation are collected in the :ref:`general_bibliography`. diff --git a/mne-python/source/doc/documentation/cited.rst b/mne-python/source/doc/documentation/cited.rst new file mode 100644 index 0000000000000000000000000000000000000000..b7f9821b8d3d76aee94f15d83fdebfb971aa74db --- /dev/null +++ b/mne-python/source/doc/documentation/cited.rst @@ -0,0 +1,9 @@ +.. _cited: + +Papers citing MNE-Python +======================== + +Estimates provided by Google Scholar as of 16 December 2024: + +- `MNE (2,190) `_ +- `MNE-Python (4,360) `_ diff --git a/mne-python/source/doc/documentation/cookbook.rst b/mne-python/source/doc/documentation/cookbook.rst new file mode 100644 index 0000000000000000000000000000000000000000..d5eb149002bd6b76b0c5a67030314f610727bba5 --- /dev/null +++ b/mne-python/source/doc/documentation/cookbook.rst @@ -0,0 +1,426 @@ +.. _cookbook: + +========================== +The typical M/EEG workflow +========================== + +Overview +======== + +This section describes a typical MEG/EEG workflow, eventually up to source +reconstruction. The workflow is summarized in :ref:`flow_diagram`. +References below refer to Python functions and objects. + +.. _flow_diagram: + +.. figure:: ../_static/flow_diagram.svg + :alt: MNE Workflow Flowchart + :align: center + + **Workflow of the MNE software** + + +Preprocessing +============= +The following MEG and EEG data preprocessing steps are recommended: + +- Bad channels in the MEG and EEG data must be identified, see :ref:`marking_bad_channels`. + +- The data has to be filtered to the desired passband. + +- Artifacts should be suppressed (e.g., using ICA or SSP). + +.. _marking_bad_channels: + +Marking bad channels +-------------------- + +Sometimes some MEG or EEG channels are not functioning properly +for various reasons. These channels should be excluded from +analysis by marking them bad as:: + + >>> raw.info['bads'] = ['MEG2443'] # doctest: +SKIP + +Especially if a channel does not show +a signal at all (flat) it is important to exclude it from the +analysis, since its noise estimate will be unrealistically low and +thus the current estimate calculations will give a strong weight +to the zero signal on the flat channels and will essentially vanish. +It is also important to exclude noisy channels because they can +possibly affect others when signal-space projections or EEG average electrode +reference is employed. Noisy bad channels can also adversely affect +averaging and noise-covariance matrix estimation by causing +unnecessary rejections of epochs. + +Recommended ways to identify bad channels are: + +- Observe the quality of data during data + acquisition and make notes of observed malfunctioning channels to + your measurement protocol sheet. + +- View the on-line averages and check the condition of the channels. + +- Compute preliminary off-line averages with artifact rejection, + SSP/ICA, and EEG average electrode reference computation + off and check the condition of the channels. + +- View raw data with :func:`mne.io.Raw.plot` without SSP/ICA + enabled and identify bad channels. + +.. note:: It is strongly recommended that bad channels are identified and + marked in the original raw data files. If present in the raw data + files, the bad channel selections will be automatically transferred + to averaged files, noise-covariance matrices, forward solution + files, and inverse operator decompositions. + +Artifact suppression +-------------------- + +SSP +### + +The Signal-Space Projection (SSP) is one approach to rejection +of external disturbances in software. Unlike many other +noise-cancellation approaches, SSP does +not require additional reference sensors to record the disturbance +fields. Instead, SSP relies on the fact that the magnetic field +distributions generated by the sources in the brain have spatial +distributions sufficiently different from those generated by external +noise sources. Furthermore, it is implicitly assumed that the linear +space spanned by the significant external noise patterns has a low +dimension. + +SSP-based rejection is often done using the +:func:`mne.preprocessing.compute_proj_ecg` and +:func:`mne.preprocessing.compute_proj_eog` methods, see +:ref:`tut-projectors-background` and :ref:`tut-artifact-ssp` for more +information. + +ICA +### + +Many M/EEG signals including biological artifacts reflect non-Gaussian +processes. Therefore PCA-based artifact rejection will likely perform worse at +separating the signal from noise sources. + +ICA-based artifact rejection is done using the :class:`mne.preprocessing.ICA` +class, see the :ref:`ica` section for more information. + + +Epoching and evoked data +======================== + +Epoching of raw data is done using events, which define a ``t=0`` for your +data chunks. Event times stamped to the acquisition software can be extracted +using :func:`mne.find_events`:: + + >>> events = mne.find_events(raw) # doctest: +SKIP + +The ``events`` array can then be modified, extended, or changed if necessary. +If the original trigger codes and trigger times are correct for the analysis +of interest, :class:`mne.Epochs` for the first event type (``1``) can be +constructed using:: + + >>> reject = dict(grad=4000e-13, mag=4e-12, eog=150e-6) # doctest: +SKIP + >>> epochs = mne.Epochs(raw, events, event_id=1, tmin=-0.2, tmax=0.5, # doctest: +SKIP + >>> proj=True, picks=picks, baseline=(None, 0), # doctest: +SKIP + >>> preload=True, reject=reject) # doctest: +SKIP + +.. note:: The rejection thresholds (set with argument ``reject``) are defined + in T / m for gradiometers, T for magnetometers and V for EEG and EOG + channels. + + +Rejection using annotations +--------------------------- + +The reject keyword of :class:`mne.Epochs` is used for rejecting bad epochs +based on peak-to-peak thresholds. Bad segments of data can also be rejected +by marking segments of raw data with annotations. See +:ref:`tut-reject-data-spans` and :class:`mne.Annotations` for more . + +Once the :class:`mne.Epochs` are constructed, they can be averaged to obtain +:class:`mne.Evoked` data as:: + + >>> evoked = epochs.average() # doctest: +SKIP + + +Source localization +=================== + +MNE makes extensive use of the FreeSurfer file structure for analysis. +Before starting data analysis, we recommend setting up the environment +variable ``SUBJECTS_DIR`` (or set it permanently using :func:`mne.set_config`) +to select the directory under which the anatomical MRI data are stored. +This makes it so that the ``subjects_dir`` argument does not need to +be passed to many functions. + +Anatomical information +---------------------- + +.. _CHDBBCEJ: + +Cortical surface reconstruction with FreeSurfer +############################################### + +The first processing stage is the creation of various surface +reconstructions with FreeSurfer. The recommended FreeSurfer workflow +is summarized on the `FreeSurfer wiki pages `_. See +also this information :ref:`tut-freesurfer-reconstruction`. + +.. _setting_up_source_space: + +Setting up the source space +########################### + +This stage consists of the following: + +- Creating a suitable decimated dipole grid on the white matter surface. + +- Creating the source space file in fif format. + +This is accomplished with using :func:`mne.setup_source_space` and +:func:`mne.write_source_spaces`. These assume that the anatomical MRI processing +has been completed as described in :ref:`CHDBBCEJ`. + +.. _BABGCDHA: + +.. table:: Recommended subdivisions of an icosahedron and an octahedron for the creation of source spaces. The approximate source spacing and corresponding surface area have been calculated assuming a 1000-cm2 surface area per hemisphere. + + =========== ====================== =================== ============================= + ``spacing`` Sources per hemisphere Source spacing / mm Surface area per source / mm2 + =========== ====================== =================== ============================= + ``'oct5'`` 1026 9.9 97 + ``'ico4'`` 2562 6.2 39 + ``'oct6'`` 4098 4.9 24 + ``'ico5'`` 10242 3.1 9.8 + =========== ====================== =================== ============================= + +For example, to create the reconstruction geometry for ``subject='sample'`` +with a ~5-mm spacing between the grid points, say:: + + >>> src = setup_source_space('sample', spacing='oct6') # doctest: +SKIP + >>> write_source_spaces('sample-oct6-src.fif', src) # doctest: +SKIP + +This creates the source spaces and writes them to disk. + +:ref:`plot_forward_source_space` illustrates how the source space is used to +compute the forward model. + +.. _CHDBJCIA: + +Creating the BEM model meshes +############################# + +Calculation of the forward solution using the boundary-element +model (BEM) requires that the surfaces separating regions of different +electrical conductivities are tessellated with suitable surface +elements. Our BEM software employs triangular tessellations. Therefore, +prerequisites for BEM calculations are the segmentation of the MRI +data and the triangulation of the relevant surfaces. + +For MEG computations, a reasonably accurate solution can +be obtained by using a single-compartment BEM assuming the shape +of the intracranial volume. For EEG, the standard model contains +the intracranial space, the skull, and the scalp. + +At present, no bulletproof method exists for creating the +triangulations. Feasible approaches are described in :ref:`bem-model`. + +.. _BABDBBFC: + +Setting up the head surface triangulation files +############################################### + +The segmentation algorithms described in :ref:`bem-model` produce +either FreeSurfer surfaces or triangulation +data in text. Before proceeding to the creation of the boundary +element model, standard files for FreeSurfer surfaces must be present: + +1. **inner_skull.surf** contains the inner skull triangulation. + +2. **outer_skull.surf** contains the outer skull triangulation. + +3. **outer_skin.surf** contains the head surface triangulation. + +.. _CIHDBFEG: + +Setting up the boundary-element model +##################################### + +This stage sets up the subject-dependent data for computing +the forward solutions:" + + >>> model = make_bem_model('sample') # doctest: +SKIP + >>> write_bem_surfaces('sample-5120-5120-5120-bem.fif', model) # doctest: +SKIP + +Where ``surfaces`` is a list of BEM surfaces that have each been read using +:func:`mne.read_surface`. This step also checks that the input surfaces +are complete and that they are topologically correct, *i.e.*, +that the surfaces do not intersect and that the surfaces are correctly +ordered (outer skull surface inside the scalp and inner skull surface +inside the outer skull). + +This step assigns the conductivity values to the BEM compartments. +For the scalp and the brain compartments, the default is 0.3 S/m. +The default skull conductivity is 50 times smaller, *i.e.*, +0.006 S/m. Recent publications report a range of skull conductivity ratios +ranging from 1:15 :footcite:`OostendorpEtAl2000` to 1:25 - 1:50 +:footcite:`GoncalvesEtAl2003,LewEtAl2009`. The MNE default ratio 1:50 is based +on the typical values reported in :footcite:`GoncalvesEtAl2003`, since their +approach is based on comparison of SEF/SEP measurements in a BEM model. +The variability across publications may depend on individual variations +but, more importantly, on the precision of the skull compartment +segmentation. + +.. note:: To produce single layer BEM models (--homog flag in the C command + line tools) pass a list with one single conductivity value, + e.g. ``conductivities=[0.3]``. + +Using this model, the BEM solution can be computed using +:func:`mne.make_bem_solution` as:: + + >>> bem_sol = make_bem_solution(model) # doctest: +SKIP + >>> write_bem_solution('sample-5120-5120-5120-bem-sol.fif', bem_sol) # doctest: +SKIP + +After the BEM is set up it is advisable to check that the +BEM model meshes are correctly positioned using *e.g.* +:func:`mne.viz.plot_alignment` or :class:`mne.Report`. + +.. note:: Up to this point all processing stages depend on the + anatomical (geometrical) information only and thus remain + identical across different MEG studies. + +.. note:: If you use custom head models you might need to set the ``ico=None`` + parameter to ``None`` and skip subsampling of the surface. + + +.. _CHDBEHDC: + +Aligning coordinate frames +-------------------------- + +The calculation of the forward solution requires knowledge +of the relative location and orientation of the MEG/EEG and MRI +coordinate systems (see :ref:`head_device_coords`). The head coordinate +frame is defined by identifying the fiducial landmark locations, +making the origin and orientation of the head coordinate system +slightly user dependent. As a result, it is safest to reestablish +the definition of the coordinate transformation computation +for each experimental session, *i.e.*, each time when new head +digitization data are employed. + +The corregistration is stored in ``-trans.fif`` file. If is present, +you can follow :ref:`tut-source-alignment` to validate its correctness. +If the ``-trans.fif`` is not present or the alignment is not correct +you need to use :func:`mne.gui.coregistration` (or its convenient command line +equivalent :ref:`mne coreg`) to generate it. + +.. XXX: It would be good to link to the ``-trans.fif`` file description + +.. warning:: This step is important. If the alignment of the + coordinate frames is inaccurate all subsequent processing + steps suffer from the error. Therefore, this step should be + performed by the person in charge of the study or by a trained + technician. Written or photographic documentation of the alignment + points employed during the MEG/EEG acquisition can also be + helpful. + +.. _computing_the_forward_solution: + +Computing the forward solution +------------------------------ + +After the MRI-MEG/EEG alignment has been set, the forward +solution, *i.e.*, the magnetic fields and electric +potentials at the measurement sensors and electrodes due to dipole +sources located on the cortex, can be calculated with help of +:func:`mne.make_forward_solution` as:: + + >>> fwd = make_forward_solution(raw.info, fname_trans, src, bem_sol) # doctest: +SKIP + +Computing the noise-covariance matrix +------------------------------------- + +The MNE software employs an estimate of the noise-covariance +matrix to weight the channels correctly in the calculations. The +noise-covariance matrix provides information about field and potential +patterns representing uninteresting noise sources of either human +or environmental origin. + +The noise covariance matrix can be calculated in several +ways: + +- Employ the individual epochs during + off-line averaging to calculate the full noise covariance matrix. + This is the recommended approach for evoked responses, *e.g.* using + :func:`mne.compute_covariance`:: + + >>> cov = mne.compute_covariance(epochs, method='auto') # doctest: +SKIP + +- Employ empty room data (collected without the subject) to + calculate the full noise covariance matrix. This is recommended + for analyzing ongoing spontaneous activity. This can be done using + :func:`mne.compute_raw_covariance` as:: + + >>> cov = mne.compute_raw_covariance(raw_erm) # doctest: +SKIP + +- Employ a section of continuous raw data collected in the presence + of the subject to calculate the full noise covariance matrix. This + is the recommended approach for analyzing epileptic activity. The + data used for this purpose should be free of technical artifacts + and epileptic activity of interest. The length of the data segment + employed should be at least 20 seconds. One can also use a long + (``*> 200 s``) segment of data with epileptic spikes present provided + that the spikes occur infrequently and that the segment is apparently + stationary with respect to background brain activity. This can also + use :func:`mne.compute_raw_covariance`. + +.. _CIHCFJEI: + +Calculating the inverse operator +-------------------------------- + +The MNE software doesn't calculate the inverse operator +explicitly but rather computes an SVD of a matrix composed of the +noise-covariance matrix, the result of the forward calculation, +and the source covariance matrix. This approach has the benefit +that the regularization parameter ('SNR') can +be adjusted easily when the final source estimates or dSPMs are +computed. For mathematical details of this approach, +please consult :ref:`minimum_norm_estimates`. + +This computation stage can be done by using +:func:`mne.minimum_norm.make_inverse_operator` as:: + + >>> inv = mne.minimum_norm.make_inverse_operator(raw.info, fwd, cov, loose=0.2) # doctest: +SKIP + +Creating source estimates +------------------------- + +Once all the preprocessing steps described above have been +completed, the inverse operator computed can be applied to the MEG +and EEG data as:: + + >>> stc = mne.minimum_norm.apply_inverse(evoked, inv, lambda2=1. / 9.) # doctest: +SKIP + +And the results can be viewed as:: + + >>> stc.plot() # doctest: +SKIP + +Group analyses +-------------- + +Group analysis is facilitated by morphing source estimates, which can be +done *e.g.*, to ``subject='fsaverage'`` as:: + + >>> morph = mne.compute_source_morph(stc, subject_from='sample', subject_to='fsaverage') # doctest: +SKIP + >>> stc_fsaverage = morph.apply(stc) # doctest: +SKIP + +See :ref:`ch_morph` for more information. + + +References +========== + +.. footbibliography:: diff --git a/mne-python/source/doc/documentation/datasets.rst b/mne-python/source/doc/documentation/datasets.rst new file mode 100644 index 0000000000000000000000000000000000000000..2ec98664e7470ef9bd28fda17f1bf5a887099030 --- /dev/null +++ b/mne-python/source/doc/documentation/datasets.rst @@ -0,0 +1,556 @@ +.. _datasets: + +Datasets Overview +################# + +.. note:: Contributing datasets to MNE-Python + :class: sidebar + + Do not hesitate to contact MNE-Python developers on the + `MNE Forum `_ to discuss the possibility of + adding more publicly available datasets. + +All the dataset fetchers are available in :mod:`mne.datasets`. To download any of the datasets, +use the ``data_path`` (fetches full dataset) or the ``load_data`` (fetches dataset partially) functions. + +All fetchers will check the default download location first to see if the dataset +is already on your computer, and only download it if necessary. The default +download location is also configurable; see the documentation of any of the +``data_path`` functions for more information. + +.. _sample-dataset: + +Sample +====== +:func:`mne.datasets.sample.data_path` + +These data were acquired with the Neuromag +Vectorview system at MGH/HMS/MIT Athinoula A. Martinos Center Biomedical +Imaging. EEG data from a 60-channel electrode cap was acquired simultaneously with +the MEG. The original MRI data set was acquired with a Siemens 1.5 T +Sonata scanner using an MPRAGE sequence. + +.. note:: These data are provided solely for the purpose of getting familiar + with the MNE software. The data should not be used to evaluate the + performance of the MEG or MRI system employed. + +In this experiment, checkerboard patterns were presented to the subject +into the left and right visual field, interspersed by tones to the +left or right ear. The interval between the stimuli was 750 ms. Occasionally +a smiley face was presented at the center of the visual field. +The subject was asked to press a key with the right index finger +as soon as possible after the appearance of the face. + +.. table:: Trigger codes for the sample data set. + + ========= ===== ========================================== + Name Contents + ========= ===== ========================================== + LA 1 Response to left-ear auditory stimulus + RA 2 Response to right-ear auditory stimulus + LV 3 Response to left visual field stimulus + RV 4 Response to right visual field stimulus + smiley 5 Response to the smiley face + button 32 Response triggered by the button press + ========= ===== ========================================== + +Contents of the data set +^^^^^^^^^^^^^^^^^^^^^^^^ + +The sample data set contains two main directories: ``MEG/sample`` (the MEG/EEG +data) and ``subjects/sample`` (the MRI reconstructions). +In addition to subject ``sample``, the MRI surface reconstructions from another +subject, morph, are provided to demonstrate morphing capabilities. + +.. table:: Contents of the MEG/sample directory. + + ======================== ===================================================================== + File Contents + ======================== ===================================================================== + sample/audvis_raw.fif The raw MEG/EEG data + audvis.ave A template script for off-line averaging + auvis.cov A template script for the computation of a noise-covariance matrix + ======================== ===================================================================== + +.. table:: Overview of the contents of the subjects/sample directory. + + ======================= ====================================================================== + File / directory Contents + ======================= ====================================================================== + bem Directory for the forward modelling data + bem/watershed BEM surface segmentation data computed with the watershed algorithm + bem/inner_skull.surf Inner skull surface for BEM + bem/outer_skull.surf Outer skull surface for BEM + bem/outer_skin.surf Skin surface for BEM + sample-head.fif Skin surface in fif format for mne_analyze visualizations + surf Surface reconstructions + mri/T1 The T1-weighted MRI data employed in visualizations + ======================= ====================================================================== + +The following preprocessing steps have been already accomplished +in the sample data set: + +- The MRI surface reconstructions have + been computed using the FreeSurfer software. + +- The BEM surfaces have been created with the watershed algorithm, + see :ref:`bem_watershed_algorithm`. + +The **sample** dataset is distributed with :ref:`fsaverage` for convenience. + +.. _ucl-opm-auditory-dataset: + +UCL OPM Auditory +================ +:func:`mne.datasets.ucl_opm_auditory.data_path`. + +A basic auditory evoked field experiment using an OPM setup from FIL at UCL. +See :footcite:`SeymourEtAl2022` for details. + +.. topic:: Examples + + * :ref:`tut-opm-processing` + +Brainstorm +========== +Dataset fetchers for three Brainstorm tutorials are available. Users must agree to the +license terms of these datasets before downloading them. These files are recorded in a CTF 275 system +and are provided in native CTF format (.ds files). + +Auditory +^^^^^^^^ +:func:`mne.datasets.brainstorm.bst_raw.data_path`. + +Details about the data can be found at the Brainstorm `auditory dataset tutorial`_. + +.. topic:: Examples + + * :ref:`tut-brainstorm-auditory`: Partially replicates the original Brainstorm tutorial. + +Resting state +^^^^^^^^^^^^^ +:func:`mne.datasets.brainstorm.bst_resting.data_path` + +Details can be found at the Brainstorm `resting state dataset tutorial`_. + +.. topic:: Examples + + * :ref:`mne-connectivity:ex-envelope-correlation` + +Median nerve +^^^^^^^^^^^^ +:func:`mne.datasets.brainstorm.bst_raw.data_path` + +Details can be found at the Brainstorm `median nerve dataset tutorial`_. + +.. topic:: Examples + + * :ref:`ex-brainstorm-raw` + +SPM faces +========= +:func:`mne.datasets.spm_face.data_path` + +The `SPM faces dataset`_ contains EEG, MEG and fMRI recordings on face perception. + +.. topic:: Examples + + * :ref:`ex-spm-faces` Full pipeline including artifact removal, epochs averaging, forward model computation and source reconstruction using dSPM on the contrast: "faces - scrambled". + +EEGBCI motor imagery +==================== +:func:`mne.datasets.eegbci.load_data` + +The EEGBCI dataset is documented in :footcite:`SchalkEtAl2004` and on the +`PhysioNet documentation page `_. +The data set is available at PhysioNet :footcite:`GoldbergerEtAl2000`. +It contains 64-channel EEG recordings from 109 subjects and 14 runs on each +subject in EDF+ format. The recordings were made using the BCI2000 system. +To load a subject, do:: + + from mne.io import concatenate_raws, read_raw_edf + from mne.datasets import eegbci + subjects = [1] # may vary + runs = [4, 8, 12] # may vary + raw_fnames = eegbci.load_data(subjects, runs) + raws = [read_raw_edf(f, preload=True) for f in raw_fnames] + # concatenate runs from subject + raw = concatenate_raws(raws) + # make channel names follow standard conventions + eegbci.standardize(raw) + +.. topic:: Examples + + * :ref:`ex-decoding-csp-eeg` + +.. _somato-dataset: + +Somatosensory +============= +:func:`mne.datasets.somato.data_path` + +This dataset contains somatosensory data with event-related synchronizations +(ERS) and desynchronizations (ERD). + +.. topic:: Examples + + * :ref:`tut-sensors-time-freq` + * :ref:`ex-inverse-source-power` + * :ref:`ex-time-freq-global-field-power` + +Multimodal +========== +:func:`mne.datasets.multimodal.data_path` + +This dataset contains a single subject recorded at Otaniemi (Aalto University) +with auditory, visual, and somatosensory stimuli. + +.. topic:: Examples + + * :ref:`ex-io-ave-fiff` + +.. _fnirs-motor-dataset: + +fNIRS motor +=========== +:func:`mne.datasets.fnirs_motor.data_path` + +This dataset contains a single subject recorded at Macquarie University. +It has optodes placed over the motor cortex. There are three conditions: + +- tapping the left thumb to fingers +- tapping the right thumb to fingers +- a control where nothing happens + +The tapping lasts 5 seconds, and there are 30 trials of each condition. + +.. topic:: Examples + + * :ref:`tut-fnirs-processing` + +High frequency SEF +================== +:func:`mne.datasets.hf_sef.data_path()` + +This dataset contains somatosensory evoked fields (median nerve stimulation) +with thousands of epochs. It was recorded with an Elekta TRIUX MEG device at +a sampling frequency of 3 kHz. The dataset is suitable for investigating +high-frequency somatosensory responses. Data from two subjects are included +with MRI images in DICOM format and FreeSurfer reconstructions. + +.. topic:: Examples + + * :ref:`high-frequency SEF responses `. + +Visual 92 object categories +=========================== +:func:`mne.datasets.visual_92_categories.data_path`. + +This dataset is recorded using a 306-channel Neuromag vectorview system. + +Experiment consisted in the visual presentation of 92 images of human, animal +and inanimate objects either natural or artificial :footcite:`CichyEtAl2014`. +Given the high number of conditions this dataset is well adapted to an approach +based on Representational Similarity Analysis (RSA). + +.. topic:: Examples + + * :ref:`Representational Similarity Analysis (RSA) `: Partially replicates the results from :footcite:`CichyEtAl2014`. + + +mTRF Dataset +============ +:func:`mne.datasets.mtrf.data_path`. + +This dataset contains 128 channel EEG as well as natural speech stimulus features, +which is also available `here `_. + +The experiment consisted of subjects listening to natural speech. +The dataset contains several feature representations of the speech stimulus, +suitable for using to fit continuous regression models of neural activity. +More details and a description of the package can be found in +:footcite:`CrosseEtAl2016`. + +.. topic:: Examples + + * :ref:`Receptive Field Estimation and Prediction `: Partially replicates the results from :footcite:`CrosseEtAl2016`. + + +.. _kiloword-dataset: + +Kiloword dataset +================ +:func:`mne.datasets.kiloword.data_path`. + +This dataset consists of averaged EEG data from 75 subjects performing a +lexical decision task on 960 English words :footcite:`DufauEtAl2015`. The words +are richly annotated, and can be used for e.g. multiple regression estimation +of EEG correlates of printed word processing. + + +KIT phantom dataset +============================= +:func:`mne.datasets.phantom_kit.data_path`. + +This dataset was obtained with a phantom on a KIT system at +Macquarie University in Sydney, Australia. + +.. topic:: Examples + + * :ref:`tut-phantom-KIT` + + +4D Neuroimaging / BTi dataset +============================= +:func:`mne.datasets.phantom_4dbti.data_path`. + +This dataset was obtained with a phantom on a 4D Neuroimaging / BTi system at +the MEG center in La Timone hospital in Marseille. + +.. topic:: Examples + + * :ref:`tut-phantom-4Dbti` + +Kernel OPM phantom dataset +========================== +:func:`mne.datasets.phantom_kernel.data_path`. + +This dataset was obtained with a Neuromag phantom in a Kernel Flux (720-sensor) +system at ILABS at the University of Washington. Only 7 out of 42 possible modules +were active for testing purposes, yielding 121 channels of data with limited coverage +(mostly occipital and parietal). + +.. topic:: Examples + + * :ref:`ex-kernel-opm-phantom` + +OPM +=== +:func:`mne.datasets.opm.data_path` + +OPM data acquired using an Elekta DACQ, simply piping the data into Elekta +magnetometer channels. The FIF files thus appear to come from a TRIUX system +that is only acquiring a small number of magnetometer channels instead of the +whole array. + +The OPM ``coil_type`` is custom, requiring a custom ``coil_def.dat``. +The new ``coil_type`` is 9999. + +OPM co-registration differs a bit from the typical SQUID-MEG workflow. +No ``-trans.fif`` file is needed for the OPMs, the FIF files include proper +sensor locations in MRI coordinates and no digitization of RPA/LPA/Nasion. +Thus the MEG<->Head coordinate transform is taken to be an identity matrix +(i.e., everything is in MRI coordinates), even though this mis-identifies +the head coordinate frame (which is defined by the relationship of the +LPA, RPA, and Nasion). + +Triggers include: + +* Median nerve stimulation: trigger value 257. +* Magnetic trigger (in OPM measurement only): trigger value 260. + 1 second before the median nerve stimulation, a magnetic trigger is piped into the MSR. + This was to be able to check the synchronization between OPMs retrospectively, as each + sensor runs on an independent clock. Synchronization turned out to be satisfactory. + +.. topic:: Examples + + * :ref:`ex-opm-somatosensory` + * :ref:`ex-opm-resting-state` + +The Sleep PolySomnoGraphic Database +=================================== +:func:`mne.datasets.sleep_physionet.age.fetch_data` +:func:`mne.datasets.sleep_physionet.temazepam.fetch_data` + +The sleep PhysioNet database contains 197 whole-night PolySomnoGraphic sleep +recordings, containing EEG, EOG, chin EMG, and event markers. Some records also +contain respiration and body temperature. Corresponding hypnograms (sleep +patterns) were manually scored by well-trained technicians according to the +Rechtschaffen and Kales manual, and are also available. If you use these +data please cite :footcite:`KempEtAl2000` and :footcite:`GoldbergerEtAl2000`. + +.. topic:: Examples + + * :ref:`tut-sleep-stage-classif` + +Reference channel noise MEG data set +==================================== +:func:`mne.datasets.refmeg_noise.data_path`. + +This dataset was obtained with a 4D Neuroimaging / BTi system at +the University Clinic - Erlangen, Germany. There are powerful bursts of +external magnetic noise throughout the recording, which make it a good +example for automatic noise removal techniques. + +.. topic:: Examples + + * :ref:`ex-megnoise_processing` + +Miscellaneous Datasets +====================== +These datasets are used for specific purposes in the documentation and in +general are not useful for separate analyses. + +.. _fsaverage: + +fsaverage +^^^^^^^^^ +:func:`mne.datasets.fetch_fsaverage` + +For convenience, we provide a function to separately download and extract the +(or update an existing) fsaverage subject. See also the +:ref:`background information on fsaverage `. + +.. topic:: Examples + + :ref:`tut-eeg-fsaverage-source-modeling` + +Infant template MRIs +^^^^^^^^^^^^^^^^^^^^ +:func:`mne.datasets.fetch_infant_template` + +This function will download an infant template MRI from +:footcite:`OReillyEtAl2021` along with MNE-specific files. + +ECoG Dataset +^^^^^^^^^^^^ +:func:`mne.datasets.misc.data_path`. Data exists at ``/ecog/``. + +This dataset contains a sample electrocorticography (ECoG) dataset. It includes +two grids of electrodes and ten shaft electrodes with simulated motor data (actual data +pending availability). + +.. topic:: Examples + + * :ref:`ex-electrode-pos-2d`: Demonstrates how to project a 3D electrode location onto a 2D image, a common procedure in ECoG analyses. + * :ref:`tut-ieeg-localize`: Demonstrates how to use a graphical user interface to locate electrode contacts as well as warp them to a common atlas. + +sEEG Dataset +^^^^^^^^^^^^ +:func:`mne.datasets.misc.data_path`. Data exists at ``/seeg/``. + +This dataset contains a sample stereoelectroencephalography (sEEG) dataset. +It includes 21 shaft electrodes during a two-choice movement task on a keyboard. + +.. topic:: Examples + + * :ref:`tut-ieeg-localize`: Demonstrates how to use a graphical user interface to locate electrode contacts as well as warp them to a common atlas. + * :ref:`tut-working-with-seeg`: Demonstrates ways to plot sEEG anatomy and results. + +.. _limo-dataset: + +LIMO Dataset +^^^^^^^^^^^^ +:func:`mne.datasets.limo.load_data`. + +In the original LIMO experiment (see :footcite:`RousseletEtAl2010`), participants +performed a +two-alternative forced choice task, discriminating between two face stimuli. +Subjects discriminated the same two faces during the whole experiment. +The critical manipulation consisted of the level of noise added to the +face-stimuli during the task, making the faces more or less discernible to the +observer. + +The presented faces varied across a noise-signal (or phase-coherence) continuum +spanning from 0 to 100% in increasing steps of 10%. In other words, faces with +high phase-coherence (e.g., 90%) were easy to identify, while faces with low +phase-coherence (e.g., 10%) were hard to identify and by extension hard to +discriminate. + +.. topic:: Examples + + * :ref:`Single trial linear regression analysis with the LIMO dataset + `: Explores data from a single subject of the LIMO dataset + and demonstrates how to fit a single trial linear regression using the + information contained in the metadata of the individual datasets. + +.. _erp-core-dataset: + +ERP CORE Dataset +^^^^^^^^^^^^^^^^ +:func:`mne.datasets.erp_core.data_path` + +The original `ERP CORE dataset`_ :footcite:`Kappenman2021` contains data from +40 participants who completed 6 EEG experiments, carefully crafted to evoke +7 well-known event-related potential (ERP) components. + +Currently, the MNE-Python ERP CORE dataset only provides data from one +participant (subject ``001``) of the Flankers paradigm, which elicits the +lateralized readiness potential (LRP) and error-related negativity (ERN). The +data provided is **not** the original data from the ERP CORE dataset, but +rather a slightly modified version, designed to demonstrate the Epochs metadata +functionality. For example, we already set the references and montage +correctly, and stored events as Annotations. Data is provided in ``FIFF`` +format. + +.. topic:: Examples + + * :ref:`tut-autogenerate-metadata`: Learn how to auto-generate + `~mne.Epochs` metadata, and visualize the error-related negativity (ERN) + ERP component. + +.. _ssvep-dataset: + +SSVEP +===== +:func:`mne.datasets.ssvep.data_path` + +This is a simple example dataset with frequency tagged visual stimulation: +N=2 participants observed checkerboards patterns inverting with a constant +frequency of either 12.0 Hz of 15.0 Hz. 10 trials of 20.0 s length each. +32 channels wet EEG was recorded. + +Data format: BrainVision .eeg/.vhdr/.vmrk files organized according to BIDS +standard. + +.. topic:: Examples + + * :ref:`tut-ssvep` + +.. _eyelink-dataset: + +EYELINK +======= +:func:`mne.datasets.eyelink.data_path` + +Two small example datasets of eye-tracking data from SR Research EyeLink. + +EEG-Eyetracking +^^^^^^^^^^^^^^^ +:func:`mne.datasets.eyelink.data_path`. Data exists at ``/eeg-et/``. + +Contains both EEG (EGI) and eye-tracking (ASCII format) data recorded from a +pupillary light reflex experiment, stored in separate files. 1 participant fixated +on the screen while short light flashes appeared. Event onsets were recorded by a +photodiode attached to the screen and were sent to both the EEG and eye-tracking +systems. + +.. topic:: Examples + + * :ref:`tut-eyetrack` + +Freeviewing +^^^^^^^^^^^ +:func:`mne.datasets.eyelink.data_path`. Data exists at ``/freeviewing/``. + +Contains eye-tracking data (ASCII format) from 1 participant who was free-viewing a +video of a natural scene. In some videos, the natural scene was pixelated such that +the people in the scene were unrecognizable. + +.. topic:: Examples + + * :ref:`tut-eyetrack-heatmap` + +References +========== + +.. footbibliography:: + + +.. LINKS + +.. _auditory dataset tutorial: https://neuroimage.usc.edu/brainstorm/DatasetAuditory +.. _resting state dataset tutorial: https://neuroimage.usc.edu/brainstorm/DatasetResting +.. _median nerve dataset tutorial: https://neuroimage.usc.edu/brainstorm/DatasetMedianNerveCtf +.. _SPM faces dataset: https://www.fil.ion.ucl.ac.uk/spm/data/mmfaces/ +.. _ERP-CORE dataset: https://erpinfo.org/erp-core diff --git a/mne-python/source/doc/documentation/design_philosophy.rst b/mne-python/source/doc/documentation/design_philosophy.rst new file mode 100644 index 0000000000000000000000000000000000000000..5bdec09b4fa58396f714c1a89cb1eff694406272 --- /dev/null +++ b/mne-python/source/doc/documentation/design_philosophy.rst @@ -0,0 +1,98 @@ +.. _design_philosophy: + +Design philosophy +================= + +Interactive versus scripted analysis +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +MNE-Python has some great interactive plotting abilities that can help you +explore your data, and there are a few GUI-like interactive plotting commands +(like browsing through the raw data and clicking to mark bad channels, or +click-and-dragging to annotate bad temporal spans). But in general it is not +possible to use MNE-Python to mouse-click your way to a finished, publishable +analysis. MNE-Python works best when you assemble your analysis pipeline into +one or more Python scripts. On the plus side, your scripts act as a record of +everything you did in your analysis, making it easy to tweak your analysis +later and/or share it with others (including your future self). + + +Integration with the scientific python stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +MNE-Python also integrates well with other standard scientific Python +libraries. For example, MNE-Python objects underlyingly store their data in +NumPy arrays, making it easy to apply custom algorithms or pass your data into +one of `scikit-learn's `_ machine learning pipelines. +MNE-Python's 2-D plotting functions also return `matplotlib`_ +:class:`~matplotlib.figure.Figure` objects, and the 3D plotting functions +return :class:`mne.viz.Figure3D` classes with a ``.plotter`` attribute +pointing to :class:`pyvista.Plotter` instances, +so you can customize your MNE-Python plots using any +of matplotlib or PyVista's plotting commands. The intent is that MNE-Python +will get most neuroscientists 90% of the way to their desired analysis goal, +and other packages can get them over the finish line. + + +Submodule-based organization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A useful-to-know organizing principle is that MNE-Python objects and functions +are separated into submodules. This can help you discover related functions if +you're using an editor that supports tab-completion. For example, you can type +:samp:`mne.preprocessing.{}` to see all the functions in the preprocessing +submodule; similarly for visualization functions (:mod:`mne.viz`), functions +for reading and writing data (:mod:`mne.io`), statistics (:mod:`mne.stats`), +etc. This also helps save keystrokes — instead of:: + + import mne + mne.preprocessing.eog.peak_finder(...) + mne.preprocessing.eog.find_eog_events(...) + mne.preprocessing.eog.create_eog_epochs(...) + +you can import submodules directly, and use just the submodule name to access +its functions:: + + from mne.preprocessing import eog + eog.peak_finder(...) + eog.find_eog_events(...) + eog.create_eog_epochs(...) + + +(Mostly) unified API +^^^^^^^^^^^^^^^^^^^^ + +Whenever possible, we've tried to provide a unified API for the different data +classes. For example, the :class:`~mne.io.Raw`, :class:`~mne.Epochs`, +:class:`~mne.Evoked`, and :class:`~mne.SourceEstimate` classes all have a +``plot()`` method that can typically be called with no parameters specified and +still yield an informative plot of the data. Similarly, they all have the +methods ``copy()``, ``crop()``, ``resample()`` and ``save()`` with similar or +identical method signatures. The sensor-level classes also all have an ``info`` +attribute containing an :class:`~mne.Info` object, which keeps track of channel +names and types, applied filters, projectors, etc. See :ref:`tut-info-class` +for more info. + + +.. _sect-meth-chain: + +In-place operation +^^^^^^^^^^^^^^^^^^ + +Because neuroimaging datasets can be quite large, MNE-Python tries very hard to +avoid making unnecessary copies of your data behind-the-scenes. To further +improve memory efficiency, many object methods operate in-place (and silently +return their object to allow `method chaining`_). In-place operation may lead +you to frequent use of the ``copy()`` method during interactive, exploratory +analysis — so you can try out different preprocessing approaches or parameter +settings without having to re-load the data each time — but it can also be a +big memory-saver when applying a finished script to dozens of subjects' worth +of data. + + + +.. LINKS + +.. _`method chaining`: https://en.wikipedia.org/wiki/Method_chaining + +.. include:: ../links.inc diff --git a/mne-python/source/doc/documentation/glossary.rst b/mne-python/source/doc/documentation/glossary.rst new file mode 100644 index 0000000000000000000000000000000000000000..89a5c477a75ea754d3025dc56d54f2e5eb4af3a7 --- /dev/null +++ b/mne-python/source/doc/documentation/glossary.rst @@ -0,0 +1,438 @@ +Glossary +======== + +The Glossary provides short definitions of vocabulary specific to MNE-Python and +general neuroimaging concepts. If you think a term is missing, please consider +`creating a new issue`_ or `opening a pull request`_ to add it. + +.. glossary:: + :sorted: + + + annotations + An annotation is defined by an onset, a duration, and a textual + description. It can contain information about the experiment, but + also details on signals marked by a human such as bad data segments, + sleep stages, sleep events (spindles, K-complex), and so on. + An :class:`Annotations` object is a container for multiple annotations, + which is available as the ``annotations`` attribute of :class:`~io.Raw` + objects. See :class:`Annotations` for the class definition and + :ref:`tut-events-vs-annotations` for a short tutorial. + See also :term:`events`. + + beamformer + A beamformer is a popular source estimation approach that uses a set of + spatial filters (beamformer weights) to compute time courses of sources + at predefined locations. See :class:`beamformer.Beamformer` for the class + definition. See also :term:`LCMV`. + + BEM + boundary element model + boundary element method + BEM is the acronym for boundary element method or boundary element + model. Both are related to the definion of the conductor model in the + forward model computation. The boundary element model consists of surfaces + such as the inner skull, outer skull, and outer skin (scalp) that define + compartments of tissues of the head. You can compute the BEM surfaces with + :func:`bem.make_watershed_bem` or :func:`bem.make_flash_bem`. + See :ref:`tut-forward` for a usage demo. + + channels + Channels refer to MEG sensors, EEG electrodes or other sensors such as + EOG, ECG, sEEG, ECoG, etc. Channels usually have + a type (such as gradiometer), and a unit (such as T/m) used e.g. for + plotting. See also :term:`data channels` and :term:`non-data channels`. + + data channels + Many functions in MNE-Python operate on "data channels" by default. These + are channels that contain electrophysiological data from the brain, + as opposed to other channel types such as EOG, ECG, stimulus/trigger, + or acquisition system status data (see :term:`non-data channels`). + The set of channels considered "data channels" in MNE contains the + following types (together with scale factors for plotting): + + .. mne:: data channels list + + DC + direct current + The part of a signal that stays constant over time. The "DC offset" + of electrophysiological signals is often dealt with by high-pass + filtering or by subtracting some suitable baseline. + + DICS + dynamic imaging of coherent sources + Dynamic Imaging of Coherent Sources is a method for computing source + power in different frequency bands. See :ref:`ex-inverse-source-power` + and :func:`beamformer.make_dics` for more details. + + digitization + Digitization is a procedure of recording the head shape and locations of + fiducial coils (or :term:`HPI`) and/or EEG electrodes on the head. They + are represented as a set of points in 3D space. + See :ref:`reading-dig-montages` and :ref:`dig-formats`. + + dipole + ECD + equivalent current dipole + An equivalent current dipole (ECD) is an approximate representation of + post-synaptic activity in a small cortical region. The intracellular + currents that give rise to measurable EEG/MEG signals are thought to + originate in populations of cortical pyramidal neurons aligned + perpendicularly to the cortical surface. Because the length of such + current sources is very small relative to the distance between the + cortex and the EEG/MEG sensors, the fields measured by these techniques + are well approximated by (i.e., equivalent to) fields generated by + idealized point sources (dipoles) located on the cortical surface. + + dSPM + dynamic statistical parametric mapping + Dynamic statistical parametric mapping (dSPM) gives a noise-normalized + minimum-norm estimate at a given source location. It is calculated by + dividing the activity estimate at each source location by the baseline + standard deviation of the noise. + + eLORETA + sLORETA + eLORETA and sLORETA (exact and standardized low resolution brain + electromagnetic tomography) are linear source estimation techniques + like :term:`dSPM` and :term:`MNE`. sLORETA outputs + standardized values (like dSPM), while eLORETA generates normalized + current estimates. See :func:`minimum_norm.apply_inverse`, + :ref:`tut-inverse-methods`, and :ref:`example-sLORETA`. + + epochs + Epochs (sometimes called "trials" in other software packages) are + equal-length segments of data extracted from continuous data. Usually, + epochs are extracted around stimulus events or responses, + though sometimes sequential or overlapping epochs are used (e.g., + for analysis of resting-state activity). See :class:`Epochs` for the + class definition and :ref:`tut-epochs-class` for a narrative overview. + + events + Events correspond to specific time points in raw data, such as triggers, + experimental condition events, etc. MNE-Python represents events with + integers stored in NumPy arrays of shape ``(n_events, 3)``. The first + column contains the event onset (in samples) with :term:`first_samp` + included. The last column contains the event code. The second + column contains the signal value of the immediately preceding sample, + and reflects the fact that event arrays sometimes originate from + analog voltage channels ("trigger channels" or "stim channels"). In + most cases, the second column is all zeros and can be ignored. + Event arrays can be created with :func:`mne.make_fixed_length_events`, + :func:`mne.read_events`, and :func:`mne.find_events`. + See :ref:`tut-events-vs-annotations` for a short tutorial. + See also :term:`annotations`. + + evoked + Evoked data are obtained by averaging epochs. Typically, an evoked object + is constructed for each subject and each condition, but it can also be + obtained by averaging a list of evoked objects over different subjects. + See :class:`EvokedArray` for the class definition and + :ref:`tut-evoked-class` for a narrative overview. + + fiducial + fiducial point + anatomical landmark + Fiducials are objects placed in the field of view of an imaging system + to act as known spatial references that are easy to localize. + In neuroimaging, fiducials are often placed on anatomical landmarks + such as the nasion (NAS) or left/right preauricular points (LPA and + RPA). + + These known reference locations are used to define a coordinate system + for localizing sensors (hence NAS, LPA and RPA are often + called "cardinal points" because they define the cardinal directions of + the head coordinate system). The cardinal points are also useful when + co-registering measurements in different coordinate systems (such as + aligning EEG sensor locations to an MRI of the head). + + Due to the common neuroimaging practice of placing fiducial objects on + anatomical landmarks, the terms "fiducial", "anatomical landmark", and + "cardinal point" are often (erroneously) used interchangeably. + + first_samp + The :attr:`~io.Raw.first_samp` attribute of :class:`~io.Raw` + objects is an integer representing the number of time samples that + passed between the onset of the hardware acquisition system and the + time when data recording started. This approach to sample + numbering is a peculiarity of VectorView MEG systems, but for + consistency it is present in all :class:`~io.Raw` objects + regardless of the source of the data. In other words, + :attr:`~io.Raw.first_samp` will be ``0`` in :class:`~io.Raw` + objects loaded from non-VectorView data files. See also + :term:`last_samp`. + + forward + forward solution + The forward solution is a linear operator capturing the + relationship between each dipole location in the :term:`source space` + and the corresponding field distribution measured by the sensors + (the "lead field matrix"). Calculating a forward solution requires a + conductivity model of the head, which encapsulates the geometries and + electrical conductivities of the different tissue compartments (see + :term:`boundary element model` and :class:`bem.ConductorModel`). + For information about the Forward object and the data it stores, see + :class:`mne.Forward`. + + GFP + global field power + Global Field Power (GFP) is a measure of the (non-)uniformity + of the electromagnetic field at the sensors. It is typically calculated + as the standard deviation of the sensor values at each time point. Thus, + it is a one-dimensional time series capturing the spatial variability + of the signal across sensor locations. + + HED + hierarchical event descriptors + Hierarchical event descriptors (HED) are tags that use + keywords separated by slashes (/) to describe different types of + experimental events (for example, ``stimulus/circle/red/left`` and + ``stimulus/circle/blue/left``). These tags can be used to group + experimental events and select event types for analysis. + + HPI + cHPI + head position indicator + Head position indicators (HPI, sometimes cHPI for + *continuous* head position indicators) are small coils attached to a + subject's head during MEG acquisition. Each coil emits a sinusoidal + signal of a different frequency, which is picked up by the MEG sensors + and can be used to infer the head position. With cHPI, the sinusoidal + signals are typically set at frequencies above any neural signal of + interest, and thus can be removed after head position correction via + low-pass filtering. See :ref:`tut-head-pos`. + + info + measurement info + A "measurement info" (or short "info") object is a collection of metadata + related to :class:`~io.Raw`, :class:`Epochs`, or :class:`Evoked` + objects. It contains channel locations and types, sampling frequency, + preprocessing history such as filters, etc. + See :ref:`tut-info-class` for a narrative overview. + + inverse + inverse operator + The inverse operator is an :math:`M \times N` matrix (:math:`M` source + locations by :math:`N` sensors) that, when applied to the sensor + signals, yields estimates of the brain activity that gave rise to the + observed sensor signals. Inverse operators are available for the linear + inverse methods :term:`MNE`, :term:`dSPM`, :term:`sLORETA`, and + :term:`eLORETA`. See :func:`minimum_norm.apply_inverse`. + + label + A :class:`Label` refers to a defined region in the cortex, often called + a region of interest (ROI) in the literature. Labels can be defined + anatomically (based on the physical structure of the cortex) or functionally + (based on cortical responses to specific stimuli). See also :term:`ROI`. + + last_samp + The :attr:`~io.Raw.last_samp` attribute of :class:`~io.Raw` + objects is an integer representing the number of time samples that + passed between the start and end of data recording. This approach to sample + numbering is a peculiarity of VectorView MEG systems, but for + consistency it is present in all :class:`~io.Raw` objects + regardless of the source of the data. See also :term:`first_samp`. + + layout + A :class:`~channels.Layout` gives sensor positions in two + dimensions (defined by ``x``, ``y``, ``width``, and ``height`` values for + each sensor). It is primarily used for illustrative purposes (i.e., making + diagrams of approximate sensor positions in cartoons of the head, + so-called topographies or topomaps). See also :term:`montage`. + + LCMV + LCMV beamformer + Linearly constrained minimum variance beamformer attempt to + estimate activity for a given source while suppressing cross-talk from + other regions (:func:`beamformer.make_lcmv`). See also + :term:`beamformer`. + + FreeSurfer LUT + LUT + A FreeSurfer lookup table (LUT) provides a mapping between a given + volumetric atlas or surface label name, its integer value + (e.g., in ``aparc+aseg.mgz``), and its standard color (see the + `FreeSurfer wiki `__ + for more information). Custom LUTs can be also be created from different + surface parcellations, see for example `this comment about HCPMMP + `__. + + maximum intensity projection + A method to display pixel-wise activity within some volume by + finding the maximum value along a vector from the viewer to the pixel + (i.e., along the vector pependicular to the view plane). + + MNE + minimum-norm estimate + minimum-norm estimation + Minimum-norm estimation (MNE) can be used to generate a distributed + map of activation on a :term:`source space` (usually on a cortical surface). + MNE uses a linear :term:`inverse operator` to project sensor measurements + into the source space. The :term:`inverse operator` is computed from the + :term:`forward solution` for a subject and an estimate of the + :term:`noise covariance` of sensor measurements. + + montage + EEG channel names and relative positions of sensors on the scalp. + While layouts are 2D locations, montages are 3D locations. A montage + can also contain locations for HPI points, fiducial points, or + extra head shape points. + See :class:`~channels.DigMontage` for the class definition. See also + :term:`layout`. + + morphing + Morphing refers to the operation of transferring source estimates from + one anatomy to another. It is known as realignment in the fMRI + literature. This operation is necessary for group studies to get the + data into a common space for statistical analysis. + See :ref:`ch_morph` for more details. + + non-data channels + All types of channels other than :term:`data channels`. + The set of channels considered "non-data channels" in MNE contains the + following types (together with scale factors for plotting): + + .. mne:: non-data channels list + + OPM + optically pumped magnetometer + An optically pumped magnetometer (OPM) is a type of magnetometer + that uses a laser passing through a gas (e.g., rubidium) to sense + magnetic fluctuations. OPMs can operate near room temperature. + + noise covariance + The noise covariance is a matrix that contains the covariance between data + channels. It is a square matrix with shape ``n_channels`` :math:`\times` + ``n_channels``. It is especially useful when working with multiple sensor + types (e.g. EEG and MEG). In practice, the matrix is estimated from baseline + periods or empty room measurements, and it also provides a noise model + that can be used for subsequent analysis (like source imaging). + + path-like + Something that acts like a path in a file system. This can be a `str` + or a `pathlib.Path`. + + pick + An integer that is the index of a channel in the :term:`measurement info`. + It allows to obtain the information on a channel in the list of channels + available in ``info['chs']``. + + projector + SSP + A projector, also referred to as Signal Space + Projection (SSP), defines a linear operation applied spatially to EEG + or MEG data. A matrix multiplication of an SSP projector with the data + will reduce the rank of the data by projecting it to a + lower-dimensional subspace. Such projections are typically applied to + both the data and the forward operator when performing + source localization. Note that EEG average referencing can be done + using such a projection operator. Projectors are stored alongside data + in the :term:`measurement info` in the field ``info['projs']``. + + raw + `~io.Raw` objects hold continuous data (preprocessed or not), typically + obtained from reading recordings stored in a file. + See :class:`~io.RawArray` for the class definition and :ref:`tut-raw-class` + for a narrative overview. + + RAS + Right-Anterior-Superior, denoting the standard way to define coordinate + frames in MNE-Python: + + R + +X is right, -X is left + A + +Y is anterior (front), -Y is posterior (rear) + S + +Z is superior (top), -Z is inferior (bottom) + + ROI + region of interest + A spatial region where an experimental effect is expected to manifest. + This can be a collection of sensors or, when performing inverse imaging, + a set of vertices on the cortical surface or within the cortical volume. + See also :term:`label`. + + selection + A selection is a set of picked channels (for example, all sensors + falling within a :term:`region of interest`). + + sensor types + All the sensors handled by MNE-Python can be divided into two categories: + :term:`data channels` and :term:`non-data channels`. + + STC + source estimate + source time course + Source estimates, commonly referred to as STC (Source Time Courses), + are obtained from source localization methods such as :term:`dSPM`, + :term:`sLORETA`, :term:`LCMV`, or MxNE. + STCs contain the amplitudes of the neural sources over time. + In MNE-Python, :class:`SourceEstimate` objects only store the + amplitudes of activation but not the locations of the sources. The + locations are stored separately in the :class:`SourceSpaces` object + that was used to compute the forward operator. + See :class:`SourceEstimate`, :class:`VolSourceEstimate`, + :class:`VectorSourceEstimate`, and :class:`MixedSourceEstimate`. + + source space + A source space specifies where in the brain source amplitudes are + estimated. It corresponds to locations of a set of + candidate :term:`equivalent current dipoles`. MNE-Python mostly + works with source spaces defined on the cortical surfaces estimated + by FreeSurfer from a T1-weighted MRI image. See :ref:`tut-forward` + to read about how to compute a forward operator in a source space. + See :class:`SourceSpaces` for the class definition and information + about the data it contains. + + SQUID + superconducting quantum interference device + A superconducting quantum interference device (SQUID) is a type of + magnetometer that uses superconducting materials to sense magnetic + fluctuations. Standard low-temperature SQUID sensors typically found + in MEG systems operate at temperatures within a few degrees of + absolute zero (e.g., below 4 K). + + stim channel + trigger channel + A stim channel or trigger channel is a channel that encodes + events during the recording. It is typically a channel that is always + zero and takes positive values when something happens (such as the + onset of a stimulus or a subject response). Stim channels are often + prefixed with ``STI`` to distinguish them from other channel types. See + :ref:`stim-channel-defined` for more details. + + template montage + An idealized EEG :term:`montage`, often provided by the manufacturer + of the EEG system or cap. The electrode positions were not actually + measured on the participants' heads, but rather were calculated + assuming optimal theoretical placement on a sphere. + + tfr + A time-frequency representation (TFR) is often a spectrogram (STFT) or + scaleogram (wavelet) showing the frequency content as a function of + time. + + trans + A coordinate frame affine transformation, usually between the Neuromag head + coordinate frame and the MRI Surface RAS coordinate frame used by Freesurfer. + + whitening + A linear operation that transforms data with a known covariance + structure into "whitened data", which has a covariance structure equal to + the identity matrix. In other words, whitening creates virtual channels that + are uncorrelated and have unit variance. This is also known as a + sphering transformation. + + The term "whitening" comes from the fact that light with a flat + frequency spectrum in the visible range is white, whereas + non-uniform frequency spectra lead to perception of different colors + (e.g., "pink noise" has a ``1/f`` characteristic, which for visible + light would appear pink). + +.. LINKS + +.. _`creating a new issue`: + https://github.com/mne-tools/mne-python/issues/new?template=glossary.md +.. _`opening a pull request`: + https://github.com/mne-tools/mne-python/pull/new/main diff --git a/mne-python/source/doc/documentation/implementation.rst b/mne-python/source/doc/documentation/implementation.rst new file mode 100644 index 0000000000000000000000000000000000000000..49fe31bac9c6be10e6d02071869d85b0240d0663 --- /dev/null +++ b/mne-python/source/doc/documentation/implementation.rst @@ -0,0 +1,137 @@ +.. _implementation: + +Algorithms and other implementation details +=========================================== + +This page describes some of the technical details of MNE-Python implementation. + +.. _units: + +Internal representation (units) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/units.rst + :start-after: units-begin-content + + +.. _precision: + +Floating-point precision +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/precision.rst + :start-after: precision-begin-content + + +.. _channel-types: + +Supported channel types +^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/channel_types.rst + :start-after: channel-types-begin-content + + +.. _data-formats: + +Supported data formats +^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/data_formats.rst + :start-after: data-formats-begin-content + + +.. _dig-formats: + +Supported formats for digitized 3D locations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/dig_formats.rst + :start-after: dig-formats-begin-content + + +.. _memory: + +Memory-efficient I/O +^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/memory.rst + :start-after: memory-begin-content + + +.. _channel-interpolation: + +Bad channel repair via interpolation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/channel_interpolation.rst + :start-after: channel-interpolation-begin-content + :end-before: channel-interpolation-end-content + + +.. _maxwell: + +Maxwell filtering +^^^^^^^^^^^^^^^^^ + +MNE-Python's implementation of Maxwell filtering is described in the +:ref:`tut-artifact-sss` tutorial. + + +.. _ssp-method: + +Signal-Space Projection (SSP) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/ssp.rst + :start-after: ssp-begin-content + + +.. _bem-model: + +The Boundary Element Model (BEM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/bem_model.rst + :start-after: bem-begin-content + + +.. _ch_forward: + +The forward solution +^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/forward.rst + :start-after: forward-begin-content + :end-before: forward-end-content + +.. _minimum_norm_estimates: + +The minimum-norm current estimates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/inverse.rst + :start-after: inverse-begin-content + :end-before: inverse-end-content + + +.. _ch_morph: + +Morphing and averaging source estimates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/morph.rst + :start-after: morph-begin-content + + +.. _ged: + +Generalized eigendecomposition in decoding +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. include:: ../_includes/ged.rst + :start-after: ged-begin-content + +References +^^^^^^^^^^ +.. footbibliography:: diff --git a/mne-python/source/doc/documentation/index.rst b/mne-python/source/doc/documentation/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..764fcd08188708abf521476487071308679478d4 --- /dev/null +++ b/mne-python/source/doc/documentation/index.rst @@ -0,0 +1,63 @@ +.. _documentation_overview: + +Documentation overview +====================== + +.. note:: + + If you haven't already installed MNE-Python, please take a look + at our :ref:`installation guides`. Please also kindly find some + resources for :doc:`../help/learn_python` if you need to. + + +The documentation for MNE-Python is divided into four main sections: + +1. The :doc:`../auto_tutorials/index` provide narrative explanations, sample + code, and expected output for the most common MNE-Python analysis tasks. The + emphasis is on thorough explanations that get new users up to speed quickly, + at the expense of covering only a limited number of topics. + +2. The :doc:`How-to Examples <../auto_examples/index>` provides working code + samples demonstrating various analysis and visualization techniques. These + examples often lack the narrative explanations seen in the tutorials, but + can be a useful way to discover new analysis or plotting ideas, or to see + how a particular technique you've read about can be applied using + MNE-Python. + +3. The :doc:`glossary` provides short definitions of MNE-Python-specific + vocabulary and general neuroimaging concepts. The glossary is often a good + place to look if you don't understand a term or acronym used somewhere else + in the documentation. + +4. The :doc:`API reference <../api/python_reference>` provides documentation for + the classes, functions and methods in the MNE-Python codebase. This is the + same information that is rendered when running + :samp:`help(mne.{})` in an interactive Python session, or + when typing :samp:`mne.{}?` in an IPython session or Jupyter + notebook. + +The rest of the MNE-Python documentation pages (parts outside of the four +categories above) are shown in the navigation menu, including the +:ref:`list of example datasets`, +:ref:`implementation details`, and more. +Documentation for the related C and MATLAB tools are available here: + +- `MNE-MATLAB`_ (repository) +- `MNE-C `_ (PDF) + +.. toctree:: + :hidden: + + Tutorials<../auto_tutorials/index> + Examples<../auto_examples/index> + glossary + Implementation details + design_philosophy + Example datasets + Command-line tools<../generated/commands> + ../help/migrating + cookbook + cite + cited + +.. include:: ../links.inc diff --git a/mne-python/source/doc/funding.rst b/mne-python/source/doc/funding.rst new file mode 100644 index 0000000000000000000000000000000000000000..bbf25a7165c1a1b3e30b1e988ba6388021b55f86 --- /dev/null +++ b/mne-python/source/doc/funding.rst @@ -0,0 +1,70 @@ +:orphan: + +.. _funding: + +Funding and other support +========================= + +Development of MNE-Python has been supported by: + +.. rst-class:: list-unstyled funders + +- |nih| **National Institutes of Health:** + `R01-EB009048 `_, + `R01-EB006385 `_, + `R01-HD040712 `_, + `R01-NS044319 `_, + `R01-NS037462 `_, + `R01-NS104585 `_, + `P41-EB015896 `_, + `P41-RR014075 `_ +- |nsf| **US National Science Foundation:** + `0958669 `_, + `1042134 `_ +- |erc| |ercdk| **European Research Council:** + `YStG-263584 `_, + `YStG-676943 `_ +- |doe| **US Department of Energy:** DE-FG02-99ER62764 (MIND) +- |anr| **Agence Nationale de la Recherche:** + `14-NEUC-0002-01 `_, + **IDEX** Paris-Saclay + `11-IDEX-0003-02 `_ +- |cds| |cdsdk| **Paris-Saclay Center for Data Science:** + `PARIS-SACLAY `_ +- |goo| **Google:** + Summer of code (×7 years) +- |ama| **Amazon:** + AWS Research Grants +- |czi| **Chan Zuckerberg Initiative:** + `EOSS2`_, + `EOSS4`_ + + +.. _supporting-institutions: + +Institutional partners +---------------------- + +Additionally, many universities or research institutions have supported their +employees’ contributions to MNE-Python as part of normal work duties. These +institutions include: + +.. include:: _includes/institutional-partners.rst + :start-after: institutional-partners-begin-content + + +.. |nih| image:: _static/funding/nih.svg +.. |nsf| image:: _static/funding/nsf.png +.. |erc| image:: _static/funding/erc.svg + :class: only-light +.. |ercdk| image:: _static/funding/erc-dark.svg + :class: only-dark +.. |doe| image:: _static/funding/doe.svg +.. |anr| image:: _static/funding/anr.svg +.. |cds| image:: _static/funding/cds.svg + :class: only-light +.. |cdsdk| image:: _static/funding/cds-dark.svg + :class: only-dark +.. |goo| image:: _static/funding/google.svg +.. |ama| image:: _static/funding/amazon.svg +.. |czi| image:: _static/funding/czi.svg diff --git a/mne-python/source/doc/getting_started.html b/mne-python/source/doc/getting_started.html new file mode 100644 index 0000000000000000000000000000000000000000..6f4c5703867de8aeea69d9eefce1fca375e2f868 --- /dev/null +++ b/mne-python/source/doc/getting_started.html @@ -0,0 +1,9 @@ + + + + + + +

Please follow this link.

+ + diff --git a/mne-python/source/doc/help/faq.rst b/mne-python/source/doc/help/faq.rst new file mode 100644 index 0000000000000000000000000000000000000000..7720885d6437bb2cf30cb652e5eb03a6fec70c2a --- /dev/null +++ b/mne-python/source/doc/help/faq.rst @@ -0,0 +1,422 @@ +.. _faq: + +================================ +Frequently Asked Questions (FAQ) +================================ + +.. highlight:: python + +General MNE-Python issues +========================= + + +Help! I can't get Python and MNE-Python working! +------------------------------------------------ + +Check out our :ref:`installation instructions `. + + +I still can't get it to work! +----------------------------- + +See :ref:`help`. + + +I can't get PyVista/3D plotting to work under Windows +----------------------------------------------------- + +If PyVista plotting in Jupyter Notebooks doesn't work well, using the IPython +magic ``%gui qt`` should `help +`_. + +.. code-block:: ipython + + %gui qt + +Python runs on macOS extremely slow even on simple commands! +------------------------------------------------------------ + +Python uses some backends that interfere with the macOS energy saver when +using an IDE such as Spyder or PyCharm. To test it, import ``time`` and run:: + + start = time.time(); time.sleep(0.0005); print(time.time() - start) + +If it takes several seconds you can either: + +- Install the module ``appnope`` and run in your script:: + + import appnope + appnope.nope() + +- Change the configuration defaults by running in your terminal: + + .. code-block:: console + + $ defaults write org.python.python NSAppSleepDisabled -bool YES + + +How do I cite MNE? +------------------ + +See :ref:`cite`. + + +I'm not sure how to do *X* analysis step with my *Y* data... +------------------------------------------------------------ + +Knowing "the right thing" to do with EEG and MEG data is challenging. We use +the `MNE Forum`_ to discuss analysis strategies for different kinds of +data. It's worth searching the archives to see if there have been relevant +discussions in the past, but don't hesitate to ask a new question if the answer +isn't out there already. + + +I think I found a bug, what do I do? +------------------------------------ + +When you encounter an error message or unexpected results, it can be hard to +tell whether it happened because of a bug in MNE-Python, a mistake in user +code, a corrupted data file, or irregularities in the data itself. Your first +step when asking for help should be the `MNE Forum`_, not GitHub. This bears +repeating: *the GitHub issue tracker is not for usage help* — it is for +software bugs, feature requests, and improvements to documentation. If you +open an issue that contains only a usage question, we will close the issue and +direct you to the forum. If you're pretty sure the problem you've encountered +is a software bug (not bad data or user error): + +- Make sure you're using `the most current version`_. You can check it locally + at a shell prompt with: + + .. code-block:: console + + $ mne sys_info + + which will also give you version info about important MNE-Python + dependencies. + +- If you're already on the most current version, if possible try using + :ref:`the latest development version `, as the bug may + have been fixed already since the latest release. If you can't try the latest + development version, search the GitHub issues page to see if the problem has + already been reported and/or fixed. + +- Try to replicate the problem with one of the :ref:`MNE sample datasets + `. If you can't replicate it with a built-in dataset, provide a + link to a small, anonymized portion of your data that does yield the error. + +If the problem persists, `open a new issue +`__ +and include the *smallest possible* code sample that replicates the error +you're seeing. Paste the code sample into the issue, with a line containing +three backticks (\`\`\`) above and below the lines of code. This +`minimal working example`_ should be self-contained, which means that +MNE-Python contributors should be able to copy and paste the provided snippet +and replicate the bug on their own computers. + +Why is it dangerous to "pickle" my MNE-Python objects and data for later use? +----------------------------------------------------------------------------- + +`Pickling `_ data and MNE-Python +objects for later use can be tempting due to its simplicity and generality, but +it is usually not the best option. Pickling is not designed for stable +persistence, and it is likely that you will not be able to read your data in +the not-too-distant future. For details, see: + +- http://www.benfrederickson.com/dont-pickle-your-data/ +- https://stackoverflow.com/questions/21752259/python-why-pickle + +MNE-Python is designed to provide its own file saving formats (often based on +the FIF standard) for its objects usually via a ``save`` method or ``write_*`` +method, e.g. :func:`mne.io.Raw.save`, :func:`mne.Epochs.save`, +:func:`mne.write_evokeds`, :func:`mne.SourceEstimate.save`. If you have some +data that you want to save but can't figure out how, post to the `MNE Forum`_ +or to the `GitHub issues page`_. + +If you want to write your own data to disk (e.g., subject behavioral scores), +we strongly recommend using h5io_, which is based on the `HDF5 format +`_ and h5py_, to save +data in a fast, future-compatible, standard format. + + +I downloaded a dataset once, but MNE-Python is asking to download it again. Why? +-------------------------------------------------------------------------------- + +The default location for the MNE-sample data is ``~/mne_data``. If you +downloaded data and an example asks you whether to download it again, make sure +the data reside in the examples directory and that you run the script from its +current directory: + +.. code-block:: console + + $ cd examples/preprocessing + +Then in Python you can do:: + + In [1]: %run plot_find_ecg_artifacts.py + +See :ref:`datasets` for a list of all available datasets and some advanced +configuration options, e.g. to specify a custom location for storing the +datasets. + + +.. _faq_cpu: + +A function uses multiple CPU cores even though I didn't tell it to. Why? +------------------------------------------------------------------------ + +Ordinarily in MNE-python the ``parallel`` module is used to deploy multiple +cores via the ``n_jobs`` variable. However, functions like +:func:`mne.preprocessing.maxwell_filter` that use :mod:`scipy.linalg` do not +have an ``n_jobs`` flag but may still use multiple cores. This is because +:mod:`scipy.linalg` is built with linear algebra libraries that natively +support multithreading: + +- `OpenBLAS `_ +- `Intel Math Kernel Library (MKL) `_, + which uses `OpenMP `_ + +To control how many cores are used for linear-algebra-heavy functions like +:func:`mne.preprocessing.maxwell_filter`, you can set the ``OMP_NUM_THREADS`` +or ``OPENBLAS_NUM_THREADS`` environment variable to the desired number of cores +for MKL or OpenBLAS, respectively. This can be done before running Python, or +inside Python you can achieve the same effect by, e.g.:: + + >>> import os + >>> num_cpu = '4' # Set as a string + >>> os.environ['OMP_NUM_THREADS'] = num_cpu + +This must be done *before* running linear algebra functions; subsequent +changes in the same Python session will have no effect. + + +I have a mystery FIF file, how do I read it? +-------------------------------------------- + +The :func:`mne.what` function can be called on any :file:`.fif` file to +identify the kind of data contained in the file. This will help you determine +whether to use :func:`mne.read_cov`, :func:`mne.read_epochs`, +:func:`mne.read_evokeds`, etc. There is also a corresponding command line tool +:ref:`mne what`: + +.. code-block:: console + + $ mne what sample_audvis_eog-eve.fif + events + + +.. _resampling-and-decimating: + +Resampling and decimating data +============================== + +What are all these options for resampling, decimating, and binning data? +------------------------------------------------------------------------ + +There are many functions in MNE-Python for changing the effective sampling rate +of data. We'll discuss some major ones here, with some of their implications: + +- :func:`mne.io.Raw.resample` is used to resample (typically downsample) raw + data. Resampling is the two-step process of applying a low-pass FIR filter + and subselecting samples from the data. + + Using this function to resample data before forming :class:`mne.Epochs` + for final analysis is generally discouraged because doing so effectively + loses precision of (and jitters) the event timings, see + `this gist `_ as + a demonstration. However, resampling raw data can be useful for + (at least): + + - Computing projectors in low- or band-passed data + - Exploring data + +- :func:`mne.preprocessing.ICA.fit` decimates data without low-passing, + but is only used for fitting a statistical model to the data. + +- :func:`mne.Epochs.decimate`, which does the same thing as the + ``decim`` parameter in the :class:`mne.Epochs` constructor, sub-selects every + :math:`N^{th}` sample before and after each event. To avoid aliasing + artifacts, the raw data should be sufficiently low-passed before decimation. + It is recommended to use :func:`mne.io.Raw.filter` with ``h_freq`` set to + half the new sampling rate (fs/2N) or lower, as per the Nyquist criterion, to + ensure effective attenuation of frequency content above this threshold. + +- :func:`mne.Epochs.resample`, :func:`mne.Evoked.resample`, and + :func:`mne.SourceEstimate.resample` all resample data. + This process avoids potential aliasing artifacts because the + resampling process applies a low-pass filter. However, this filtering + introduces edge artifacts. Edge artifacts also exist when using + :func:`mne.io.Raw.resample`, but there the edge artifacts are constrained + to two times: the start and end of the recording. With these three methods, + edge artifacts are introduced to the start and end of every epoch + of data (or the start and end of the :class:`mne.Evoked` or + :class:`mne.SourceEstimate` data), which often has a more pronounced + effect on the data. + +- :func:`mne.SourceEstimate.bin` can be used to decimate, with or without + "binning" (averaging across data points). This is equivalent to applying + a moving-average (boxcar) filter to the data and decimating. A boxcar in + time is a `sinc `_ in + frequency, so this acts as a simplistic, non-ideal low-pass filter; + this will reduce but not eliminate aliasing if data were not sufficiently + low-passed. In the case where the "filter" or bin-width is a single sample + (i.e., an impulse) this operation simplifies to decimation without filtering. + + +Resampling raw data is taking forever! What do I do? +---------------------------------------------------- + +:func:`mne.io.Raw.resample` has a parameter ``npad=='auto'``. This is the +default, but if you've changed it you could try changing it back to ``'auto'``, +it might help. + +If you have an NVIDIA GPU you could also try using :ref:`CUDA`, which can +sometimes speed up filtering and resampling operations by an order of +magnitude. + + +Forward and Inverse Solution +============================ + +.. _faq_how_should_i_regularize: + +How should I regularize the covariance matrix? +---------------------------------------------- + +The estimated covariance can be numerically unstable and tends to induce +correlations between estimated source amplitudes and the number of samples +available. It is thus suggested to regularize the noise covariance +matrix (see :ref:`cov_regularization_math`), especially if only few samples +are available. Unfortunately it is not easy to tell the effective number of +samples, hence, to choose the appropriate regularization. In MNE-Python, +regularization is done using advanced regularization methods described in +:footcite:`EngemannGramfort2015`. For this the 'auto' option can be used. With +this option cross-validation will be used to learn the optimal regularization:: + + >>> import mne + >>> epochs = mne.read_epochs(epochs_path) # doctest: +SKIP + >>> cov = mne.compute_covariance(epochs, tmax=0., method='auto') # doctest: +SKIP + +This procedure evaluates the noise covariance quantitatively by how well it +whitens the data using the negative log-likelihood of unseen data. The final +result can also be visually inspected. Under the assumption that the baseline +does not contain a systematic signal (time-locked to the event of interest), +the whitened baseline signal should be follow a multivariate Gaussian +distribution, i.e., whitened baseline signals should be between -1.96 and 1.96 +at a given time sample. Based on the same reasoning, the expected value for the +:term:`global field power` (GFP) is 1 (calculation of the :term:`GFP` +should take into account the true degrees of freedom, e.g. ``ddof=3`` with 2 +active SSP vectors):: + + >>> evoked = epochs.average() # doctest: +SKIP + >>> evoked.plot_white(cov) # doctest: +SKIP + +This plot displays both, the whitened evoked signals for each channels and the +whitened :term:`GFP`. The numbers in the :term:`GFP` panel represent the +estimated rank of the data, which amounts to the effective degrees of freedom +by which the squared sum across sensors is divided when computing the whitened +:term:`GFP`. The whitened :term:`GFP` also helps detecting spurious late evoked +components which can be the consequence of over- or under-regularization. + +Note that if data have been processed using signal space separation (SSS) +:footcite:`TauluEtAl2005`, gradiometers and magnetometers will be displayed +jointly because both are reconstructed from the same SSS basis vectors with the +same numerical rank. This also implies that both sensor types are not any +longer linearly independent. + +These methods for evaluation can be used to assess model violations. Additional +introductory materials can be found `here +`_. + +For expert use cases or debugging the alternative estimators can also be +compared:: + + >>> covs = mne.compute_covariance(epochs, tmax=0., method='auto', return_estimators=True) # doctest: +SKIP + >>> evoked = epochs.average() # doctest: +SKIP + >>> evoked.plot_white(covs) # doctest: +SKIP + +This will plot the whitened evoked for the optimal estimator and display the +:term:`GFP` for all estimators as separate lines in the related panel. + + +.. _faq_watershed_bem_meshes: + +My watershed BEM meshes look incorrect +-------------------------------------- + +After using :ref:`mne watershed_bem` or :func:`mne.bem.make_watershed_bem` +you might find that the BEM meshes for the brain, inner skull, outer skull, +and/or scalp surfaces do not look correct in :func:`mne.viz.plot_alignment` +and :func:`mne.viz.plot_bem`. + +MNE relies on FreeSurfer's mri_watershed_ to compute the BEM meshes. +Freesurfer's watershed bem strategy is to: + +1. Compute the outer skin (scalp) surface +2. Shrink outer skin inward make the "outer skull" +3. Compute brain surface +4. Expand brain surface outward to make the "inner skull" + +A common problem is to see: + + the surface inner skull is not completely inside surface outer skull + +When looking at the meshes, the inner skull surface (expanded brain surface) +will have defects, and these defects will protrude into the outer skull surface +(shrunken scalp surface). In these cases, you can try (in rough ascending +order of difficulty): + +.. highlight:: console + +1. Changing the ``--preflood`` / ``-p`` parameter in + :ref:`mne watershed_bem`. +2. Changing the ``--atlas`` and ``--gcaatlas`` options of + :ref:`mne watershed_bem`. +3. Manually editing the meshes (see :ref:`this tutorial `). +4. Manually running mri_watershed_ with various FreeSurfer flags (e.g., + ``-less`` to fix the output). +5. Going farther back in your Freesurfer pipeline to fix the problem. + In particular, ``mri/brainmask.mgz`` could be incorrectly generated by the + autorecon1_ step and contain some dura and/or skull within the brain mask. + You can check by using freeview_ or some other MRI-viewing tool. + + - Consult the Freesurfer docs on `fixing errors + `__. + - Try tweaking the mri_normalize_ parameters `via xopts + `__, + e.g.:: + + $ mri_normalize -mprage -b 20 -n 5 + + - Try `manually setting the control points and/or using -gentle + `__. + - Examine the talairach transformation to see if it's not quite right, + and if it's not, `adjust it manually + `__. + - Search the `FreeSurfer listserv`_ for other ideas + + It can be helpful to run ``recon_all -autorecon1 -xopts xopts.txt`` in a + clean directory first to see if this fixes everything, and, if not, then + resorting to manual control point setting and/or talairach adjustment. + Once everything looks good at the end of ``-autorecon1``, you can then run + :ref:`mne watershed_bem` to see if the output is good. Once it is + (and once brainmask.mgz is correct), you can then proceed with + ``recon_all -autorecon2`` and ``recon_all -autorecon3`` to effectively + complete all ``recon_all`` steps. + +.. highlight:: python + + +References +---------- + +.. footbibliography:: + +.. LINKS + +.. _`the most current version`: https://github.com/mne-tools/mne-python/releases/latest +.. _`minimal working example`: https://en.wikipedia.org/wiki/Minimal_Working_Example +.. _mri_watershed: https://surfer.nmr.mgh.harvard.edu/fswiki/mri_watershed +.. _mri_normalize: https://surfer.nmr.mgh.harvard.edu/fswiki/mri_normalize +.. _freeview: https://surfer.nmr.mgh.harvard.edu/fswiki/FreeviewGuide/FreeviewIntroduction +.. _`FreeSurfer listserv`: https://www.mail-archive.com/freesurfer@nmr.mgh.harvard.edu/ +.. _autorecon1: https://surfer.nmr.mgh.harvard.edu/fswiki/ReconAllDevTable diff --git a/mne-python/source/doc/help/index.rst b/mne-python/source/doc/help/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..ceaf7a10c2566275ed500443e458df483566afd3 --- /dev/null +++ b/mne-python/source/doc/help/index.rst @@ -0,0 +1,27 @@ +.. _help: + +Getting help +^^^^^^^^^^^^ + +There are several places to obtain help with MNE software tools. + +- The `MNE Forum`_ is a good placed to go for both troubleshooting and general + questions. +- The :ref:`faq` page has some troubleshooting tips, and is a good source of + general information. There are also some troubleshooting tips built into + the :ref:`Python ` and + :ref:`MNE-Python ` installation pages (look for the + |hand-paper| symbols), and some tips related to 3D plotting problems on + :ref:`the advanced setup page `. +- If you want to request new features or if you're confident that you have + found a bug, please create a new issue on the `GitHub issues page`_. + When reporting bugs, please try to replicate the bug with the MNE-Python + :ref:`sample data `, and make every effort to simplify your + example script to only the elements necessary to replicate the bug. + + +.. toctree:: + :hidden: + + learn_python + faq diff --git a/mne-python/source/doc/help/learn_python.rst b/mne-python/source/doc/help/learn_python.rst new file mode 100644 index 0000000000000000000000000000000000000000..25d42b3847f7f1a177b3064b5f31654f966b425f --- /dev/null +++ b/mne-python/source/doc/help/learn_python.rst @@ -0,0 +1,25 @@ +.. _learn-python: + +Getting started with Python +=========================== + +`Python`_ is a modern general-purpose object-oriented high-level programming +language. There are many general introductions to Python online; here are a +few: + +- The official `Python tutorial `__ +- W3Schools `Python tutorial `__ +- Software Carpentry's `Python lesson `_ + +Additionally, here are a couple tutorials focused on scientific programming in +Python: + +- the `SciPy Lecture Notes `_ +- `NumPy for MATLAB users `_ + +There are also many video tutorials online, including `videos from the annual +SciPy conferences +`_. +One of those is a `Python introduction for complete beginners +`_, but there are many more +lectures on advanced topics available as well. diff --git a/mne-python/source/doc/help/migrating.rst b/mne-python/source/doc/help/migrating.rst new file mode 100644 index 0000000000000000000000000000000000000000..9aeb945c4185a993846a50b7270640b3debaf33c --- /dev/null +++ b/mne-python/source/doc/help/migrating.rst @@ -0,0 +1,91 @@ +.. _migrating: + +Migrating from other analysis software +====================================== + +Here we offer some tips on how to migrate from other analysis software. + +EEGLAB +^^^^^^ + +To read in data exported from EEGLAB, MNE-Python includes an :file:`.edf` +reader :func:`mne.io.read_raw_edf` and a ``set`` file reader. To read in +``set`` files containing ``raw`` data, use :func:`mne.io.read_raw_eeglab` and +to read in ``set`` files containing ``epochs`` data, use +:func:`mne.read_epochs_eeglab`. + +This table summarizes the equivalent EEGLAB and MNE-Python code for some of the +most common analysis tasks. For the sake of clarity, the table below assumes +the following variables exist: the file name ``fname``, time interval of the +epochs ``tmin`` and ``tmax``, and the experimental conditions ``cond1`` and +``cond2``. The variables ``l_freq`` and ``h_freq`` are the frequencies (in Hz) +below which and above which to filter out data. + +.. cssclass:: table-bordered +.. rst-class:: midvalign + ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Processing step | EEGLAB function | MNE-Python | ++=====================+==========================================================+==================================================================================================+ +| Get started | | ``addpath(...);`` | | :mod:`import mne ` | +| | | ``eeglab;`` | | :mod:`from mne import io, ` :class:`~mne.Epochs` | +| | | | | :mod:`from mne.preprocessing ` :class:`import ICA ` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Import data | | ``EEG = pop_fileio(fname);`` | | :func:`raw = io.read_raw_fif(fname) ` | +| | | | | :func:`raw = io.read_raw_edf(fname) ` | +| | | | | :func:`raw = io.read_raw_eeglab(fname) ` ``(set file)`` | +| | | | | | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Filter data | | ``EEG = pop_eegfiltnew(EEG, l_freq, h_freq);`` | | :func:`raw.filter(l_freq, h_freq) ` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Common Average | | ``EEG= pop_averef;`` | | :func:`raw.set_eeg_reference("average") ` | +| referencing | | | | | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Remove channels | | ``pop_select.m`` | | :func:`raw.drop_channels() ` | +| | | | | | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Run ICA | | ``EEG = pop_runica(EEG, 'pca', n);`` | | :func:`ica.fit(raw) ` | +| | | | | | +| | | ``EEG = pop_binica(EEG, 'pca', n);`` | | :func:`mne.preprocessing.infomax` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Plot ICA properties | | ``pop_compprop( EEG, comp_num, winhandle);`` | | :func:`ica.plot_properties(raw, picks) ` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Plot ICA components | | ``compheads()`` | | :func:`ica.plot_components(raw, picks) ` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Exclude components | | ``pop_selectcomps()`` | | ``ica.exclude = list_of_components_to_exclude`` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Epoch data | | ``event_id = {'cond1', 'cond2'};`` | | :func:`events = mne.find_events(raw) ` | +| | | ``Epochs = pop_epochs(EEG, event_id, [tmin, tmax]);`` | | :class:`event_id = dict(cond1=32, cond2=64) ` | +| | | | | :class:`epochs = Epochs(raw, events, event_id, tmin, tmax) ` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Selecting epochs | | ``Epochs = pop_epochs(EEG_epochs, {cond2});`` | | :class:`epochs[cond2] ` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| ERP butterfly plot | | ``pop_timtopo(EEG_epochs, ...);`` | | :meth:`evoked = epochs[cond2].average() ` | +| | | | | :func:`evoked.plot() ` | +| | | | | :func:`evoked.plot_joint() ` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Contrast ERPs | | ``pop_compareerps(EEG_epochs1, EEG_epochs2);`` | | :func:`mne.combine_evoked([evoked1, -evoked2], weights='equal').plot() ` | +| | | | | :func:`mne.viz.plot_compare_evokeds([evoked1, evoked2]) ` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ +| Save data | | ``EEG = pop_saveset(EEG, fname);`` | | :func:`raw.save(fname) ` | +| | | | | :func:`epochs.save(fname) ` | +| | | | | :func:`evoked.save(fname) ` | ++---------------------+----------------------------------------------------------+--------------------------------------------------------------------------------------------------+ + +Potential pitfalls +~~~~~~~~~~~~~~~~~~ + +- Many of the MNE-Python objects have methods that operate in-place to save + memory (i.e., the data in the :class:`~mne.io.Raw` object is changed when you + call :meth:`raw.filter(lfreq, hfreq) `). If you do not + want this, it is always possible to first call the object's + :meth:`~mne.io.Raw.copy` method (e.g., ``filtered_raw = + raw.copy().filter(lfreq, hfreq)``). In addition, some MNE-Python functions + have a boolean ``copy`` parameter that achieves the same purpose. + +- The concept of channel types is critical in MNE because it supports analysis + of multimodal data (e.g., EEG, MEG, EOG, Stim channel, etc) whereas most + EEGLAB functions assume all channels are of the same type (EEG). To restrict + channels to a single type, see :func:`mne.pick_types`, + :meth:`raw.pick() `, :meth:`epochs.pick() ` + and :meth:`evoked.pick() `. diff --git a/mne-python/source/doc/index.rst b/mne-python/source/doc/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..7629f3d037b2e0492df2aaebcda516900f6f324e --- /dev/null +++ b/mne-python/source/doc/index.rst @@ -0,0 +1,41 @@ +:html_theme.sidebar_secondary.remove: + +.. title:: MNE + +.. The page title must be in rST for it to show in next/prev page buttons. + Therefore we add a special style rule to only this page that hides h1 tags + +.. raw:: html + + + +MNE-Python Homepage +=================== + +.. LOGO + +.. image:: _static/mne_logo.svg + :alt: MNE-Python + :class: logo, mainlogo, only-light + :align: center + +.. image:: _static/mne_logo_dark.svg + :alt: MNE-Python + :class: logo, mainlogo, only-dark + :align: center + +.. rst-class:: h4 text-center font-weight-light my-4 + + Open-source Python package for exploring, visualizing, and analyzing + human neurophysiological data: MEG, EEG, sEEG, ECoG, NIRS, and more. + +.. frontpage gallery is added by a conditional in _templates/layout.html + +.. toctree:: + :hidden: + + Install + Documentation + API Reference + Get Help + Development diff --git a/mne-python/source/doc/install/advanced.rst b/mne-python/source/doc/install/advanced.rst new file mode 100644 index 0000000000000000000000000000000000000000..f1e217403aa83cbec44f86284cd70852fb5c6df7 --- /dev/null +++ b/mne-python/source/doc/install/advanced.rst @@ -0,0 +1,303 @@ +.. _advanced_setup: + +Advanced setup +============== + +Working with Jupyter Notebooks and JupyterLab +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you like using Jupyter notebooks, you should also update the "base" +conda environment to include the ``nb_conda_kernels`` package; this will +make it easier to use MNE-Python in Jupyter Notebooks launched from the +Anaconda GUI: + +.. code-block:: console + + $ conda install --name=base nb_conda_kernels + +When using MNE-Python within IPython or a Jupyter notebook, we strongly +recommend using the Qt matplotlib backend for fast and correct rendering. On +Linux, for example, Qt is the only matplotlib backend for which 3D rendering +will work correctly. On macOS, certain matplotlib functions might not work as +expected on backends other than Qt. Enabling Qt can be accomplished when +starting IPython from a terminal: + +.. code-block:: console + + $ ipython --matplotlib=qt + +or in a Jupyter Notebook, you can use the "magic" command: + +.. code-block:: ipython + + In [1]: %matplotlib qt + +This will create separate pop-up windows for each figure, and has the advantage +that the 3D plots will retain rich interactivity (so, for example, you can +click-and-drag to rotate cortical surface activation maps). + +If you are creating a static notebook or simply prefer Jupyter's inline plot +display, MNE-Python will work with the standard "inline" magic: + +.. code-block:: ipython + + In [1]: %matplotlib inline + +but some functionality will be lost. For example, PyVista scenes will still +pop-up a separate window, but only one window at a time is possible, and +interactivity within the scene is limited in non-blocking plot calls. + +.. admonition:: |windows| Windows + :class: note + + If you are using MNE-Python on Windows through IPython or Jupyter, you might + also have to use the IPython magic command ``%gui qt`` (see `here + `_). For example: + + .. code-block:: ipython + + In [2]: %gui qt + +If you installed the ``nb_conda_kernels`` package into your ``base`` +environment (as recommended), you should be able to launch ``mne``-capable +notebooks from within the Anaconda Navigator GUI without having to explicitly +switch to the ``mne`` environment first; look for ``Python [conda env:mne]`` +when choosing which notebook kernel to use. Otherwise, be sure to activate the +``mne`` environment before launching the notebook. + +If you use another Python setup and you encounter some difficulties please +report them on the `MNE Forum`_ or on the `GitHub issues page`_ to get +assistance. + +It is also possible to interact with the 3D plots without installing Qt by using +the notebook 3d backend: + +.. code-block:: ipython + + In [1]: import mne + In [2]: mne.viz.set_3d_backend("notebook") + + +The notebook 3d backend requires PyVista to be installed along with other packages, +please follow :ref:`standard-instructions`. + +Installing to a headless Linux server +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +First, follow the standard installation instructions. Next, you can choose +to install the ``osmesa`` (off-screen MESA) VTK variant, which avoids the need +to use Xvfb to start a virtual display (and have a sufficiently updated +MESA to render properly): + +.. code-block:: console + + $ conda install -c conda-forge "vtk>=9.2=*osmesa*" "mesalib=21.2.5" + +Using the development version +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +See :ref:`installing_main` for how to do a one-time update to the latest +development version of MNE-Python. If you plan to contribute to MNE-Python, or +just prefer to use git rather than pip to make frequent updates, there are +instructions for installing from a ``git clone`` in the :ref:`contributing`. + +Choosing the Qt framework +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The ``conda-forge`` version of MNE-Python ships with PyQt5. If you would like to +use a different binding, you can instead install MNE-Python via ``pip``: + +.. code-block:: console + + $ pip install "mne[full]" # uses PyQt6 + $ pip install "mne[full-pyqt6]" # same as above + $ pip install "mne[full-pyside6]" # use PySide6 + $ pip install "mne[full-no-qt]" # don't install any Qt binding + +.. _CUDA: + +Fixing dock icons on Linux +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +On newer versions of Ubuntu (e.g., 24.04), applications must supply a ``.desktop`` +file associated with them, otherwise a generic icon will be used like: + +.. image:: ../_static/default_linux_dock_icon.png + :alt: Default Linux dock icon + +To fix this, you can create a ``.desktop`` file for MNE-Python. Here is an example +file that you can save as ``~/.local/share/applications/mne-python.desktop`` after +fixing the path to the MNE-Python icon, which you can download +`here `__ +if needed: + +.. code-block:: ini + + [Desktop Entry] + Type=Application + Version=1.5 + Name=MNE-Python + StartupWMClass=MNE-Python + Icon=/path/to/mne-python/mne/icons/mne_default_icon.png + SingleMainWindow=true + NoDisplay=true + +It should make the icon appear correctly in the dock: + +.. image:: ../_static/mne_python_dock_icon.png + :alt: MNE-Python dock icon + +GPU acceleration with CUDA +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +MNE-Python can utilize `NVIDIA CUDA GPU processing`_ to speed up some +operations (e.g. FIR filtering) by roughly an order of magnitude. To use CUDA, +first ensure that you are running the `NVIDIA proprietary drivers`_ on your +operating system, and then do: + +.. code-block:: console + + $ conda install cupy + $ MNE_USE_CUDA=true python -c "import mne; mne.cuda.init_cuda(verbose=True)" + Enabling CUDA with 1.55 GB available memory + +If you receive a message reporting the GPU's available memory, CuPy_ +is working properly. To permanently enable CUDA in MNE, you can do:: + + >>> mne.utils.set_config('MNE_USE_CUDA', 'true') # doctest: +SKIP + +You can then test MNE CUDA support by running the associated test: + +.. code-block:: console + + $ pytest mne/tests/test_filter.py -k cuda + +If the tests pass, then CUDA should work in MNE. You can use CUDA in methods +that state that they allow passing ``n_jobs='cuda'``, such as +:meth:`mne.io.Raw.filter` and :meth:`mne.io.Raw.resample`, +and they should run faster than the CPU-based multithreading such as +``n_jobs=8``. + +Off-screen rendering with MESA +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +On remote Linux systems, it might be possible to use MESA software rendering +(such as ``llvmpipe`` or ``swr``) for 3D visualization (with some tweaks). +For example, on CentOS 7.5 you might be able to use an environment variable +to force MESA to use modern OpenGL by using this before executing +``spyder`` or ``python``: + +.. code-block:: console + + $ export MESA_GL_VERSION_OVERRIDE=3.3 + +Also, it's possible that different software rending backends might perform +better than others, such as using the ``llvmpipe`` backend rather than ``swr``. +In newer MESA (21+), rendering can be incorrect when using MSAA, so consider +setting: + +.. code-block:: console + + $ export MNE_3D_OPTION_MULTI_SAMPLES=1 + +MESA also can have trouble with full-screen antialiasing, which you can +disable with: + +.. code-block:: console + + $ export MNE_3D_OPTION_ANTIALIAS=false + +or by doing +:func:`mne.viz.set_3d_options(antialias=False) ` within +a given Python session. + +Some hardware-accelerated graphics on linux (e.g., some Intel graphics cards) +provide an insufficient implementation of OpenGL, and in those cases it can help to +force software rendering instead with something like: + +.. code-block:: console + + $ export LIBGL_ALWAYS_SOFTWARE=true + +Another issue that may come up is that the MESA software itself may be out of date +in certain operating systems, for example CentOS. This may lead to incomplete +rendering of some 3D plots. A solution is described in this `Github comment `_. +It boils down to building a newer version (e.g., 18.3.6) +locally following a variant of `these instructions `_. +If you have CentOS 7 or newer, you can also try some `prebuilt binaries `_ we made. +After downloading the files, untar them and add them to the appropriate library paths +using the following commands: + +.. code-block:: console + + $ tar xzvf mesa_18.3.6_centos_lib.tgz + $ export LIBGL_DRIVERS_PATH="${PWD}/lib" + $ export LD_LIBRARY_PATH="${PWD}/lib" + +To check that everything went well, type the following: + +.. code-block:: console + + $ glxinfo | grep "OpenGL core profile version" + +which should give:: + + OpenGL core profile version string: 3.3 (Core Profile) Mesa 18.3.6 + +Another way to check is to type: + +.. code-block:: console + + $ mne sys_info + +and it should show the right version of MESA:: + + ... + pyvista: 0.27.4 {pyvistaqt=0.2.0, OpenGL 3.3 (Core Profile) Mesa 18.3.6 via llvmpipe (LLVM 3.4, 256 bits)} + ... + +.. _troubleshoot_3d: + +Troubleshooting 3D plots +^^^^^^^^^^^^^^^^^^^^^^^^ + +3D plotting trouble after upgrade on macOS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When upgrading MNE-Python from version 0.19 or lower, some macOS users may end +up with +conflicting versions of some of the 3D plotting dependencies. If you plot using +the pyvista 3D backend and find that you can click-drag to rotate the brain, +but cannot adjust any of the settings sliders, it is likely that your versions +of VTK and/or QT are incompatible. This series of commands should fix it: + +.. code-block:: console + + $ conda uninstall vtk + $ pip uninstall -y pyvista + $ conda install vtk + $ pip install --no-cache pyvista + +If you installed VTK using ``pip`` rather than ``conda``, substitute the first +line for ``pip uninstall -y vtk``. + +3D plotting trouble on Linux +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are having trouble with 3D plotting on Linux, one possibility is that you +are using Wayland for graphics. To check, you can do: + +.. code-block:: console + + $ echo $XDG_SESSION_TYPE + wayland + +If so, you will need to tell Qt to use X11 instead of Wayland. You can do this +by setting ``export QT_QPA_PLATFORM=xcb`` in your terminal session. To make it +permanent for your logins, you can set it for example in ``~/.profile``. + +.. LINKS + +.. _`pyvista`: https://docs.pyvista.org/ +.. _`X server`: https://en.wikipedia.org/wiki/X_Window_System +.. _`xvfb`: https://en.wikipedia.org/wiki/Xvfb diff --git a/mne-python/source/doc/install/check_installation.rst b/mne-python/source/doc/install/check_installation.rst new file mode 100644 index 0000000000000000000000000000000000000000..4a7592a66e828ce1c84b81fec01a10c070a420a9 --- /dev/null +++ b/mne-python/source/doc/install/check_installation.rst @@ -0,0 +1,89 @@ +.. _testing-installation: + + +Testing your installation +========================= + +To make sure MNE-Python was installed correctly, type the following command in +a terminal:: + + python -c "import mne; mne.sys_info()" + +.. hint:: + If you installed MNE-Python using one of our installers, enter the above + command in the **Prompt**. + +This should display some system information along with the versions of +MNE-Python and its dependencies. Typical output looks like this:: + + Platform Windows-10-10.0.20348-SP0 + Python 3.10.12 | packaged by conda-forge | (main, Jun 23 2023, 22:34:57) [MSC v.1936 64 bit (AMD64)] + Executable C:\Miniconda3\envs\mne\python.exe + CPU Intel64 Family 6 Model 85 Stepping 7, GenuineIntel (2 cores) + Memory 7.0 GB + + Core + ├☑ mne 1.6.0.dev67+gb12384562 + ├☑ numpy 1.25.2 (OpenBLAS 0.3.23.dev with 1 thread) + ├☑ scipy 1.11.2 + ├☑ matplotlib 3.7.2 (backend=QtAgg) + ├☑ pooch 1.7.0 + └☑ jinja2 3.1.2 + + Numerical (optional) + ├☑ sklearn 1.3.0 + ├☑ nibabel 5.1.0 + ├☑ nilearn 0.10.1 + ├☑ dipy 1.7.0 + ├☑ openmeeg 2.5.6 + ├☑ pandas 2.1.0 + └☐ unavailable numba, cupy + + Visualization (optional) + ├☑ pyvista 0.41.1 (OpenGL 3.3 (Core Profile) Mesa 10.2.4 (git-d92815a) via Gallium 0.4 on llvmpipe (LLVM 3.4, 256 bits)) + ├☑ pyvistaqt 0.0.0 + ├☑ ipyvtklink 0.2.2 + ├☑ vtk 9.2.6 + ├☑ qtpy 2.4.0 (PyQt5=5.15.8) + ├☑ ipympl 0.9.3 + ├☑ pyqtgraph 0.13.3 + └☑ mne-qt-browser 0.5.2 + + Ecosystem (optional) + └☐ unavailable mne-bids, mne-nirs, mne-features, mne-connectivity, mne-icalabel, mne-bids-pipeline + + +.. dropdown:: If you get an error... + :color: danger + :icon: alert-fill + + .. rubric:: If you see an error like: + + :: + + Traceback (most recent call last): + File "", line 1, in + ModuleNotFoundError: No module named 'mne' + + This suggests that your environment containing MNE-Python is not active. + If you followed the setup for 3D plotting/source analysis (i.e., you + installed to a new ``mne`` environment instead of the ``base`` environment) + try running ``conda activate mne`` first, and try again. If this works, + you might want to set your terminal to automatically activate the + ``mne`` environment each time you open a terminal:: + + echo conda activate mne >> ~/.bashrc # for bash shells + echo conda activate mne >> ~/.zprofile # for zsh shells + +If something else went wrong during installation and you can't figure it out, +check out the :ref:`advanced_setup` instructions to see if your problem is +discussed there. If not, the `MNE Forum`_ is a good resources for +troubleshooting installation problems. + +.. highlight:: python + +.. LINKS + +.. _`pyvista`: https://docs.pyvista.org/ +.. _`X server`: https://en.wikipedia.org/wiki/X_Window_System +.. _`xvfb`: https://en.wikipedia.org/wiki/Xvfb diff --git a/mne-python/source/doc/install/freesurfer.rst b/mne-python/source/doc/install/freesurfer.rst new file mode 100644 index 0000000000000000000000000000000000000000..1de6fc82c556f43381296cb244fe4b98ff506580 --- /dev/null +++ b/mne-python/source/doc/install/freesurfer.rst @@ -0,0 +1,25 @@ +Installing FreeSurfer +===================== + +`FreeSurfer `_ is software for analysis and visualization of MRI data. +In the MNE ecosystem, freesurfer is used to convert structural MRI scans into +models of the scalp, inner/outer skull, and cortical surfaces, which are used +to + +1. model how changes in the electrical and magnetic field caused by neural + activity propagate to the sensor locations (part of computing the "forward + solution"), and + +2. constrain the estimates of where brain activity may have occurred (in the + "inverse imaging" step of source localization). + +System requirements, setup instructions, and test scripts are provided on the +`FreeSurfer download page`_. Note that if you don't already have it, you will +need to install ``tcsh`` for FreeSurfer to work; ``tcsh`` is usually +pre-installed with macOS, and is available in the package repositories for +Linux-based systems (e.g., ``sudo apt install tcsh`` on Ubuntu-like systems). + +.. LINKS + +.. _fs-wiki: https://surfer.nmr.mgh.harvard.edu/fswiki/ +.. _`FreeSurfer download page`: https://surfer.nmr.mgh.harvard.edu/fswiki/DownloadAndInstall diff --git a/mne-python/source/doc/install/ides.rst b/mne-python/source/doc/install/ides.rst new file mode 100644 index 0000000000000000000000000000000000000000..ff5d28ff3816e725772d4b0d6944b7848736684e --- /dev/null +++ b/mne-python/source/doc/install/ides.rst @@ -0,0 +1,55 @@ +.. _ide_setup: + +IDE integration (VSCode, Spyder, etc.) +====================================== + +Most users find it convenient to write and run their code in an `Integrated +Development Environment`_ (IDE). Some popular choices for scientific +Python development are: + +- `Visual Studio Code`_ (often shortened to "VS Code" or "vscode") is a + development-focused text editor that supports many programming languages in + addition to Python, includes an integrated terminal console, and has a rich + extension ecosystem. Installing + `Microsoft's Python Extension + `__ is + enough to get most Python users up and running. VS Code is free and + open-source. + +- `Spyder`_ is a free and open-source IDE developed by and for scientists who + use Python. It can be installed via a + `standalone Spyder installer `__. + To avoid dependency conflicts with Spyder, you should install ``mne`` in a + separate environment, as explained in previous sections or using our dedicated + installer. Then, instruct + Spyder to use the MNE-Python interpreter by opening + Spyder and `navigating to `__ + :samp:`Tools > Preferences > Python Interpreter > Use the following interpreter`. + +- `PyCharm`_ is an IDE specifically for Python development that provides an + all-in-one solution (no extension packages needed). PyCharm comes in a + free and open-source Community edition as well as a paid Professional edition. + +For these IDEs, you'll need to provide the path to the Python interpreter you want it +to use. If you're using the MNE-Python installers, on Linux and macOS opening the +**Prompt** will display several lines of information, including a line that will read +something like: + +.. code-block:: output + + Using Python: /some/directory/mne-python_1.10.0_0/bin/python + +Altertatively (or on Windows), you can find that path by opening the Python interpreter +you want to use (e.g., the one from the MNE-Python installer, or a ``conda`` environment +that you have activated) and running:: + + >>> import sys + >>> print(sys.executable) # doctest:+SKIP + +This should print something like +``C:\Program Files\MNE-Python\1.10.0_0\bin\python.exe`` (Windows) or +``/Users/user/Applications/MNE-Python/1.10.0_0/.mne-python/bin/python`` (macOS). + +For Spyder, if the console cannot start because ``spyder-kernels`` is missing, +install the required version in the conda environment. For example, with the +environment you want to use activated, run ``conda install spyder-kernels``. diff --git a/mne-python/source/doc/install/index.rst b/mne-python/source/doc/install/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..1adbee4df92f6e734c0e57e04753278df2ea3213 --- /dev/null +++ b/mne-python/source/doc/install/index.rst @@ -0,0 +1,83 @@ +:html_theme.sidebar_secondary.remove: + +.. _install: +.. _quick-start: + +Installing MNE-Python +====================== + + +.. when https://github.com/executablebooks/sphinx-design/issues/66 is fixed, + prepend |cloud-arrow-down| |ensp| to the "Download installers" button text + and |wrench| |ensp| to the "Setup instructions" button text + +.. grid:: 2 + + .. grid-item-card:: + :text-align: center + + .. rst-class:: font-weight-bold mb-0 + + Standalone installers + + .. rst-class:: card-subtitle text-muted mt-0 + + For Beginners + + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. image:: ../_static/mne_installer_macOS.png + :alt: MNE-Python Installer + + **New to Python?** Use our standalone installers that include + everything to get you started! + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + + .. button-ref:: installers + :ref-type: ref + :color: primary + :shadow: + :class: font-weight-bold + + Download Installers + + + .. grid-item-card:: + :text-align: center + + .. rst-class:: font-weight-bold mb-0 + + Install via ``pip`` or ``conda`` + + .. rst-class:: card-subtitle text-muted mt-0 + + For Advanced Users + + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. image:: ../_static/mne_installer_console.png + :alt: Terminal Window + + **Already familiar with Python?** + Follow our advanced setup instructions for ``pip`` and ``conda``! + +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + .. button-ref:: manual-install + :ref-type: ref + :color: primary + :shadow: + :class: font-weight-bold + + Setup Instructions + + +.. toctree:: + :hidden: + + installers + ides + manual_install + advanced + check_installation + updating + freesurfer + mne_tools_suite diff --git a/mne-python/source/doc/install/installers.rst b/mne-python/source/doc/install/installers.rst new file mode 100644 index 0000000000000000000000000000000000000000..6a1329797323cac9c98c8aedeb96e781c709637d --- /dev/null +++ b/mne-python/source/doc/install/installers.rst @@ -0,0 +1,180 @@ +.. _installers: + +MNE-Python installers +===================== + +MNE-Python installers are the easiest way to install MNE-Python and +all dependencies. They also provide many additional +Python packages and tools. Got any questions? Let us know on the `MNE Forum`_! + +Platform-specific installers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. tab-set:: + :class: install-selector-tabset + + .. tab-item:: Linux + :class-content: text-center + :name: install-linux + + .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.11.0/MNE-Python-1.11.0_0-Linux.sh + :ref-type: ref + :color: primary + :shadow: + :class: font-weight-bold mt-3 install-download-button + + |cloud-arrow-down| |ensp| Download for Linux + + **Supported platforms:** Ubuntu 18.04 (Bionic Beaver) and newer + + Run the installer in a terminal via: + + .. code-block:: console + + $ sh ./MNE-Python-1.11.0_0-Linux.sh + + + .. tab-item:: macOS (Intel) + :class-content: text-center + :name: install-macos-intel + + .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.11.0/MNE-Python-1.11.0_0-macOS_Intel.pkg + :ref-type: ref + :color: primary + :shadow: + :class: font-weight-bold mt-3 install-download-button + + |cloud-arrow-down| |ensp| Download for macOS (Intel) + + **Supported platforms:** + macOS 10.15 (Catalina) and newer + + + .. tab-item:: macOS (Apple Silicon) + :class-content: text-center + :name: install-macos-apple + + .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.11.0/MNE-Python-1.11.0_0-macOS_M1.pkg + :ref-type: ref + :color: primary + :shadow: + :class: font-weight-bold mt-3 install-download-button + + |cloud-arrow-down| |ensp| Download for macOS (Apple Silicon) + + + **Supported platforms:** + macOS 10.15 (Catalina) and newer + + .. tab-item:: Windows + :class-content: text-center + :name: install-windows + + .. button-link:: https://github.com/mne-tools/mne-installers/releases/download/v1.11.0/MNE-Python-1.11.0_0-Windows.exe + :ref-type: ref + :color: primary + :shadow: + :class: font-weight-bold mt-3 install-download-button + + |cloud-arrow-down| |ensp| Download for Windows + + **Supported platforms:** Windows 10 and newer + +.. card:: + :class-body: text-center + :class-card: install-download-alert hidden + + .. We have to use a button-link here because button-ref doesn't properly nested parse the inline code + + .. button-link:: ides.html + :ref-type: ref + :color: success + :shadow: + :class: font-weight-bold mt-3 + :click-parent: + + |rocket| Go to IDE Setup + + Once installation completes, **set up your IDE**! + +.. raw:: html + + + + +First steps +^^^^^^^^^^^ + +The installer adds menu entries on Linux and Windows, and several application +bundles to the ``Applications`` folder on macOS. + +.. rst-class:: list-unstyled +.. rst-class:: mx-5 +.. rst-class:: mt-4 +.. rst-class:: mb-5 + +- |code| |ensp| Set up **Visual Studio Code** or another IDE (:ref:`instructions here `) to start writing your own analysis scripts right away, or to run one of our examples from this website. + + .. rst-class:: mt-3 +- |desktop| |ensp| With **System Info**, list the versions of all installed MNE-Python-related packages. + + .. rst-class:: mt-3 +- |terminal| |ensp| The **Prompt** drops you into a command line interface with a properly activated MNE-Python environment. + + +.. note:: + |hourglass-half| |ensp| Depending on your system, it may take a little while for these + applications to start, especially on the very first run – which may take + particularly long on Apple Silicon-based computers. Subsequent runs should + usually be much faster. + +Uninstallation +^^^^^^^^^^^^^^ + +To remove the MNE-Python distribution provided by our installers above: + +1. Remove relevant lines from your shell initialization scripts if you + added them at installation time. To do this, you can run from the MNE Prompt: + + .. code-block:: bash + + $ conda init --reverse + + Or you can manually edit shell initialization scripts, e.g., ``~/.bashrc`` or + ``~/.bash_profile``. + +2. Follow the instructions below to remove the MNE-Python conda installation for your platform: + + .. tab-set:: + :class: uninstall-selector-tabset + + .. tab-item:: Linux + :name: uninstall-linux + + In a BASH terminal you can do: + + .. code-block:: bash + + $ which python + /home/username/mne-python/1.11.0_0/bin/python + $ rm -Rf /home/$USER/mne-python + $ rm /home/$USER/.local/share/applications/mne-python-*.desktop + + .. tab-item:: macOS + :name: uninstall-macos + + You can simply `drag the MNE-Python folder to the trash in the Finder `__. + + Alternatively, you can do something like: + + .. code-block:: bash + + $ which python + /Users/username/Applications/MNE-Python/1.11.0_0/.mne-python/bin/python + $ rm -Rf /Users/$USER/Applications/MNE-Python # if user-specific + $ rm -Rf /Applications/MNE-Python # if system-wide + + .. tab-item:: Windows + :name: uninstall-windows + + To uninstall MNE-Python, you can remove the application using the `Windows Control Panel `__. diff --git a/mne-python/source/doc/install/manual_install.rst b/mne-python/source/doc/install/manual_install.rst new file mode 100644 index 0000000000000000000000000000000000000000..5a67a3aea68ba0b09fcc44fa370d6f28e7dfb736 --- /dev/null +++ b/mne-python/source/doc/install/manual_install.rst @@ -0,0 +1,95 @@ +.. _manual-install: +.. _standard-instructions: + +Install via :code:`pip` or :code:`conda` +======================================== + +.. hint:: + If you're unfamiliar with Python, we recommend using our :ref:`installers` + instead. + +MNE-Python requires Python version |min_python_version| or higher. If you +need help installing Python, please refer to our :ref:`install-python` guide. + +Installing MNE-Python with all dependencies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If you use Anaconda, we suggest installing MNE-Python into its own ``conda`` environment. + +First, please ensure you're using a recent version of ``conda``. Run in your terminal: + +.. code-block:: console + + $ conda update --name=base conda # update conda + $ conda --version + +The installed ``conda`` version should be ``23.10.0`` or newer. + +Now, you can install MNE-Python: + +.. code-block:: console + + $ conda create --channel=conda-forge --strict-channel-priority --name=mne mne + +This will create a new ``conda`` environment called ``mne`` (you can adjust +this by passing a different name via ``--name``) and install all +dependencies into it. + +If you need to convert structural MRI scans into models +of the scalp, inner/outer skull, and cortical surfaces, you will also need +to install :doc:`FreeSurfer `. + +Installing MNE-Python with core dependencies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If you only need MNE-Python's core functionality, which includes 2D plotting +(but does not support 3D visualization), install via :code:`pip`: + +.. code-block:: console + + $ pip install mne + +or via :code:`conda`: + +.. code-block:: console + + $ conda create --channel=conda-forge --strict-channel-priority --name=mne mne-base + +This will create a new ``conda`` environment called ``mne`` (you can adjust +this by passing a different name via ``--name``). + +This minimal installation requires only a few dependencies. If you need additional +functionality later on, you can install individual packages as needed. + +Installing MNE-Python with HDF5 support +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +If you plan to use MNE-Python's functions that require +`HDF5 `__ I/O (this +includes :func:`mne.io.read_raw_eeglab`, :meth:`mne.SourceMorph.save`, and +others), you should run via :code:`pip`: + +.. code-block:: console + + $ pip install "mne[hdf5]" + +or via :code:`conda`: + +.. code-block:: console + + $ conda create --override-channels --channel=conda-forge --name=mne mne-base h5io h5py pymatreader + +This will create a new ``conda`` environment called ``mne`` (you can adjust +this by passing a different name via ``--name``). + +If you have already installed MNE-Python with core dependencies (e.g. via ``pip install mne``), +you can install these two packages to unlock HDF5 support: + +.. code-block:: console + + $ pip install h5io pymatreader + +Installing MNE-Python for other scenarios +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The :ref:`advanced_setup` page has additional +tips and tricks for special situations (servers, notebooks, CUDA, installing +the development version, etc). The :ref:`contributing` has additional +installation instructions for (future) contributors to MNE-Python (e.g, extra +dependencies for running our tests and building our documentation). diff --git a/mne-python/source/doc/install/manual_install_python.rst b/mne-python/source/doc/install/manual_install_python.rst new file mode 100644 index 0000000000000000000000000000000000000000..623b27d2a12b10addb571bcbf26b16f773a8e2c5 --- /dev/null +++ b/mne-python/source/doc/install/manual_install_python.rst @@ -0,0 +1,34 @@ +:orphan: + +.. _install-python: + +Installing Python +================= + +MNE-Python requires Python and several Python packages. MNE-Python +version |version| requires Python version |min_python_version| or higher. + +We recommend using a ``conda``-based Python installation, such as +`Anaconda`_, `Miniconda`_, or `Miniforge`_. For new users we recommend +our pre-built :ref:`installers`, which use ``conda`` environments under the hood. + +.. warning:: + Anaconda Inc., the company that develops the Anaconda and Miniconda Python + distributions, + `changed their terms of service `__ + in March of 2024. If you're unsure about whether your usage situation requires a paid + license, we recommend using Miniforge or our pre-built installer instead. These + options, by default, install packages only from the community-maintained `conda-forge`_ + distribution channel, and avoid the distribution channels covered by Anaconda's terms + of service. + +.. _other-py-distros: + +Other Python distributions +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +While conda-based CPython distributions provide many conveniences, other types of +installation (``pip`` / ``poetry``, ``venv`` / system-level) and/or other Python +distributions (PyPy) *should* also work with MNE-Python. Generally speaking, if you can +install SciPy, getting MNE-Python to work should be unproblematic. Note however that we +do not offer installation support for anything other than conda-based installations. diff --git a/mne-python/source/doc/install/mne_c.rst b/mne-python/source/doc/install/mne_c.rst new file mode 100644 index 0000000000000000000000000000000000000000..10985a0c3929c540651163a89ce83de3ad7dd54c --- /dev/null +++ b/mne-python/source/doc/install/mne_c.rst @@ -0,0 +1,191 @@ +:orphan: + +.. _install_mne_c: + +Installing MNE-C +================ + +System requirements +^^^^^^^^^^^^^^^^^^^ + +MNE-C runs on macOS (version 10.5 "Leopard" or later) and Linux (kernel 2.6.9 +or later). Both 32- and 64-bit operating systems are supported; a PowerPC +version for macOS can be provided upon request. At least 2 GB of memory is +required, 4 GB or more is recommended. The software requires at least 80 MB of +disk space. MATLAB is an optional dependency; the free `MATLAB runtime`_ is +sufficient. If MATLAB is not present, the utilities ``mne_convert_mne_data``, +``mne_epochs2mat``, ``mne_raw2mat``, and ``mne_simu`` will not work. + +For boundary-element model (BEM) mesh generation, and for accessing the ``tkmedit`` +program from ``mne_analyze``, MNE-C needs access to a +working installation of :doc:`FreeSurfer `, including the +environment variables ``FREESURFER_HOME``, ``SUBJECTS_DIR``, and ``SUBJECT``. + +.. admonition:: |apple| macOS + :class: note + + For installation on macOS, you also need: + + - the `XCode developer tools`_. + - an X Window System such as XQuartz_. Version 2.7.9 of XQuartz should work + out of the box; the most current version (2.7.11, as of May 2019) may + require these additional steps to work: + + .. code-block:: console + + $ cd /opt/X11/lib + $ sudo cp libXt.6.dylib libXt.6.dylib.bak + $ cd flat_namespace/ + $ sudo cp libXt.6.dylib ../. + + - the netpbm_ library. The recommended way to get netpbm is to install + Homebrew_, and run ``brew install netpbm`` in the Terminal app. + Alternatively, if you prefer to use MacPorts_, you can run + ``sudo port install netpbm`` in the Terminal app. + + +Downloading and Installing MNE-C +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +MNE-C is distributed as either a compressed tar archive (.tar.gz) or a macOS +disk image (.dmg). The `MNE-C download page`_ requires registration with a +valid email address. The current stable version is 2.7.3; "nightly" builds of +the development version are also available on the download page. + +To install from the compressed tar archive, change directory to the desired +install location, and unpack the software using ``tar``: + +.. code-block:: console + + $ cd + $ tar zxvf + +To install from the macOS disk image, double-click the downloaded .dmg file. In +the window that opens, double-click the installer package file (.pkg) to launch +the installer, and follow its instructions. In newer versions of macOS, if you +see an error that the app is from an untrusted developer, you can override this +warning by opening it anyway from the Security & Privacy pane within the +computer's System Preferences. + +.. _user_environment: + +Configuring MNE-C +^^^^^^^^^^^^^^^^^ + +MNE-C requires two environment variables to be defined manually: + +- ``MNE_ROOT`` should give the path to the folder where MNE-C is installed +- ``MATLAB_ROOT`` should give the path to your MATLAB binary (e.g., + ``/opt/MATLAB/R2018b`` or similar). If you do not have MATLAB or the MATLAB + runtime, leave ``MATLAB_ROOT`` undefined. + +Other environment variables are defined by setup scripts provided with MNE-C. +You may either run the setup script each time you use MNE-C, or (recommended) +configure your shell to run it automatically each time you open a terminal. For +bash compatible shells, e.g., sh/bash/zsh, the script to source is +``$MNE_ROOT/bin/mne_setup_sh``. For C shells, e.g., csh/tcsh, the script to +source is ``$MNE_ROOT/bin/mne_setup``. If you don't know what shell you are +using, you can run the following command to find out: + +.. code-block:: console + + $ echo $SHELL + +To configure MNE-C automatically for ``bash`` or ``sh`` shells, add this to +your ``.bashrc``: + +.. code-block:: sh + + export MNE_ROOT= + export MATLAB_ROOT= + source $MNE_ROOT/bin/mne_setup_sh + +where ```` and ```` are replaced by the absolute +paths to MNE-C and MATLAB, respectively. If you don't have MATLAB, you should +still include the ``export MATLAB_ROOT=`` statement, but leave +```` blank. + +To configure MNE-C automatically for ``zsh``, use the built-in ``emulate`` +command in your ``.zshrc`` file: + +.. code-block:: sh + + export MNE_ROOT= + export MATLAB_ROOT= + emulate sh -c 'source $MNE_ROOT/bin/mne_setup_sh' + +To configure MNE-C automatically for ``csh`` or ``tcsh`` shells, the +corresponding commands in the ``.cshrc`` / ``.tcshrc`` file are: + +.. code-block:: tcsh + + setenv MNE_ROOT + setenv MATLAB_ROOT + source $MNE_ROOT/bin/mne_setup + +If you have done this correctly, the command ``ls $MNE_ROOT/bin/mne_setup_sh`` +should succeed when run in a new terminal. + +Testing MNE-C installation +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +An easy way to verify whether your installation of MNE-C is working is to test +the OpenGL graphics performance: + +.. code-block:: console + + $ $MNE_ROOT/bin/mne_opengl_test + +This will render an inflated brain surface repeatedly, rotating it by 5 degrees +around the z-axis between redraws. The time spent for each full revolution is +printed to the terminal window where ``mne_opengl_test`` was invoked. Switch +focus to that terminal window and use the interrupt key (usually control-c) to +halt the test. + +The best graphics performance occurs when MNE-C renders to a local display on a +computer with hardware acceleration enabled. The ``mne_analyze`` GUI has a menu +item "On GLX..." in the Help menu; if the GLX dialog says "Direct rendering +context" then hardware acceleration is in use. If you are rendering to a local +display and see "Nondirect rendering context", it is recommended that you +enable hardware acceleration (consult a search engine or your local IT support +staff for assistance). If you are rendering to a remote display or using a VNC +connection, "Nondirect rendering context" is normal. + +On the fastest graphics cards, the time per revolution in the +``mne_opengl_test`` is well below 1 second. If your time per revolution is +longer than 10 seconds, either the graphics hardware acceleration is not in +effect or you need a faster graphics adapter. + +Troubleshooting MNE-C installation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If MNE-C can't find ``libxp.so.6``, you will need to get the package from the original +author (https://launchpad.net/%7Ezeehio/+archive/ubuntu/libxp) to install it: + +.. code-block:: console + + $ sudo add-apt-repository ppa:zeehio/libxp + $ sudo apt install libxp6 + +If MNE-C can't find ``libgfortran.so.1``, you can probably safely link that +filename to the current version of libfortran that came with your system. On +a typical 64-bit Ubuntu-like system this would be accomplished by: + +.. code-block:: console + + $ cd /usr/lib/x86_64-linux-gnu + $ sudo ln -s libgfortran.so.1 $(find . -maxdepth 1 -type f -name libgfortran.so*) + +If you encounter other errors installing MNE-C, please post a message to the +`MNE Forum`_. + +.. links + +.. _MNE-C download page: http://www.nmr.mgh.harvard.edu/martinos/userInfo/data/MNE_register/index.php +.. _MATLAB runtime: https://www.mathworks.com/products/compiler/matlab-runtime.html +.. _netpbm: https://netpbm.sourceforge.net/ +.. _MacPorts: https://www.macports.org/ +.. _Homebrew: https://brew.sh/ +.. _XCode developer tools: https://developer.apple.com/xcode/ +.. _xquartz: https://www.xquartz.org/ +.. _debian: https://packages.debian.org/jessie/amd64/libxp6/download diff --git a/mne-python/source/doc/install/mne_tools_suite.rst b/mne-python/source/doc/install/mne_tools_suite.rst new file mode 100644 index 0000000000000000000000000000000000000000..0a37f666634e00a0a2651e9defcfa7a7d787f8e3 --- /dev/null +++ b/mne-python/source/doc/install/mne_tools_suite.rst @@ -0,0 +1,70 @@ +Overview of the MNE tools suite +=============================== + +MNE-Python is an open-source Python module for processing, analysis, and +visualization of functional neuroimaging data (EEG, MEG, sEEG, ECoG, and +fNIRS). There are several related or interoperable software packages that you +may also want to install, depending on your analysis needs. + +Related software +^^^^^^^^^^^^^^^^ + +- MNE-C was the initial stage of this project, + providing a set of interrelated command-line and GUI programs focused on + computing cortically constrained Minimum Norm Estimates from MEG and EEG + data. These tools were written in C by Matti Hämäläinen, and are + documented `here `_. See :ref:`install_mne_c` for installation + instructions. + +- MNE-Python reimplements the functionality of MNE-C, extends considerably the + analysis and visualization capabilities, and adds support for additional data + types like functional near-infrared spectroscopy (fNIRS). MNE-Python is + collaboratively developed and has more than 200 contributors. + +- `MNE-MATLAB`_ provides a MATLAB interface to the .fif + file format and other MNE data structures, and provides example MATLAB + implementations of some of the core analysis functionality of MNE-C. It is + distributed alongside MNE-C, and can also be downloaded from the `MNE-MATLAB`_ GitHub repository. + +- :ref:`MNE-CPP ` provides core MNE functionality implemented in + C++ and is primarily intended for embedded and real-time applications. + +There is also a growing ecosystem of other Python packages that work alongside +MNE-Python, including: + +.. note:: Something missing? + :class: sidebar + + If you know of a package that is related but not listed here, feel free to + to add it to this list by :ref:`making a pull request ` to update + `doc/sphinxext/related_software.py `__. + +.. related-software:: + +What should I install? +^^^^^^^^^^^^^^^^^^^^^^ + +If you intend only to perform ERP, ERF, or other sensor-level analyses, +:ref:`MNE-Python ` is all you need. If you prefer to +work with +shell scripts and the Unix command line, or prefer MATLAB over Python, probably +all you need is :doc:`MNE-C ` — the MNE MATLAB toolbox is distributed +with it — although note that the C tools and the MATLAB toolbox are less +actively developed than the MNE-Python module, and hence are considerably less +feature-complete. + +If you want to transform sensor recordings into estimates of localized brain +activity, you will need MNE-Python, plus :doc:`FreeSurfer ` to +convert structural MRI scans into models of the scalp, inner/outer skull, and +cortical surfaces (specifically, for command-line functions +:ref:`mne flash_bem`, :ref:`mne watershed_bem`, and +:ref:`mne make_scalp_surfaces`). + + +Getting help +^^^^^^^^^^^^ + +Help with installation is available through the `MNE Forum`_. See the +:ref:`help` page for more information. + +.. include:: ../links.inc diff --git a/mne-python/source/doc/install/updating.rst b/mne-python/source/doc/install/updating.rst new file mode 100644 index 0000000000000000000000000000000000000000..c946d5e496e21418c6c115e96c525853d78d492c --- /dev/null +++ b/mne-python/source/doc/install/updating.rst @@ -0,0 +1,85 @@ +Updating MNE-Python +=================== + +If you want to update MNE-Python to a newer version, there are a few different +options, depending on how you originally installed it. + +.. hint:: + To update via the :ref:`MNE-Python installers `, simply + download and run the latest installer for your platform. MNE-Python will be + installed in parallel to your existing installation, which you may uninstall + or delete if you don't need it anymore. + +If you're not using the MNE-Python installers, keep reading. + + +Upgrading MNE-Python only +^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you wish to update MNE-Python only and leave other packages in their current +state, you can usually safely do this with ``pip``, even if you originally +installed via conda. With the ``mne`` environment active +(``conda activate name_of_environment``), do: + +.. code-block:: console + + $ pip install -U mne + + +Upgrading all packages +^^^^^^^^^^^^^^^^^^^^^^ + +Generally speaking, if you want to upgrade *your whole software stack* +including all the dependencies, the best approach is to re-create it as a new +virtual environment, because neither conda nor pip are fool-proof at making +sure all packages remain compatible with one another during upgrades. + +Here we'll demonstrate renaming the old environment first, as a safety measure. +We'll assume that the existing environment is called ``mne`` and you want to +rename the old one so that the new, upgraded environment can be called ``mne`` +instead. + +.. warning:: + + Before running the below command, ensure that your existing MNE conda + environment is **not** activated. Run ``conda deactivate`` if in doubt. + +.. code-block:: console + + $ conda rename --name=mne old_mne # rename existing "mne" env to "old_mne" + +Then, just follow our regular installation instructions, :ref:`manual-install`. + +.. note:: + + If you installed extra packages into your old ``mne`` environment, + you'll need to repeat that process after re-creating the updated + environment. Comparing the output of ``conda list --name old_mne`` versus + ``conda list --name mne`` will show you what is missing from the new + environment. On Linux, you can automate that comparison like this: + + .. code-block:: console + + $ diff <(conda list -n mne | cut -d " " -f 1 | sort) <(conda list -n old_mne | cut -d " " -f 1 | sort) | grep "^>" | cut -d " " -f 2 + + +.. _installing_main: + +Upgrading to the development version +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. warning:: + :class: sidebar + + In between releases, function and class APIs can change without + warning. + +Sometimes, new features or bugfixes become available that are important to your +research and you just can't wait for the next official release of MNE-Python to +start taking advantage of them. In such cases, you can use ``pip`` to install +the *development version* of MNE-Python. Ensure to activate the MNE conda +environment first by running ``conda activate mne``. + +.. code-block:: console + + $ pip install -U --no-deps https://github.com/mne-tools/mne-python/archive/refs/heads/main.zip diff --git a/mne-python/source/doc/install_mne_python.html b/mne-python/source/doc/install_mne_python.html new file mode 100644 index 0000000000000000000000000000000000000000..6f4c5703867de8aeea69d9eefce1fca375e2f868 --- /dev/null +++ b/mne-python/source/doc/install_mne_python.html @@ -0,0 +1,9 @@ + + + + + + +

Please follow this link.

+ + diff --git a/mne-python/source/doc/links.inc b/mne-python/source/doc/links.inc new file mode 100644 index 0000000000000000000000000000000000000000..8538f4050c032c2438b25e4f63809dd3c1369ed4 --- /dev/null +++ b/mne-python/source/doc/links.inc @@ -0,0 +1,128 @@ +.. This (-*- rst -*-) format file contains commonly used link targets + and name substitutions. It may be included in many files, + therefore it should only contain link targets and name + substitutions. Try grepping for "^\.\. _" to find plausible + candidates for this list. + +.. NOTE: reST targets are + __not_case_sensitive__, so only one target definition is needed for + nipy, NIPY, Nipy, etc... + + +.. mne + +.. _`MNE-Python GitHub`: https://github.com/mne-tools/mne-python +.. _`MNE-C manual`: https://mne.tools/mne-c-manual/MNE-manual-2.7.3.pdf +.. _`GitHub issues page`: https://github.com/mne-tools/mne-python/issues/ +.. _`MNE Forum`: https://mne.discourse.group +.. _`MNE-BIDS`: https://mne.tools/mne-bids +.. _`MNE-BIDS-Pipeline`: https://mne.tools/mne-bids-pipeline +.. _`MNE-HCP`: http://mne.tools/mne-hcp +.. _`MNE-Realtime`: https://mne.tools/mne-realtime +.. _`MNE-LSL`: https://mne.tools/mne-lsl +.. _`MNE-gui-addons`: https://mne.tools/mne-gui-addons +.. _`MNE-MATLAB`: https://github.com/mne-tools/mne-matlab +.. _`MNE-Docker`: https://github.com/mne-tools/mne-docker +.. _`MNE-ICAlabel`: https://github.com/mne-tools/mne-icalabel +.. _`MNE-Connectivity`: https://github.com/mne-tools/mne-connectivity +.. _`MNE-NIRS`: https://github.com/mne-tools/mne-nirs +.. _PICARD: https://mind-inria.github.io/picard/ +.. _OpenMEEG: https://openmeeg.github.io +.. _openneuro-py: https://pypi.org/project/openneuro-py +.. _EOSS2: https://chanzuckerberg.com/eoss/proposals/improving-usability-of-core-neuroscience-analysis-tools-with-mne-python +.. _EOSS4: https://chanzuckerberg.com/eoss/proposals/building-pediatric-and-clinical-data-pipelines-for-mne-python/ +.. _`code of conduct`: https://github.com/mne-tools/.github/blob/main/CODE_OF_CONDUCT.md + + +.. TUTORIAL LINKS + +.. _errors: https://en.wikipedia.org/w/index.php?title=Type_I_and_type_II_errors#Table_of_error_types +.. _fwer: https://en.wikipedia.org/wiki/Family-wise_error_rate +.. _fdr: https://en.wikipedia.org/wiki/False_discovery_rate +.. _ft_cluster: http://www.fieldtriptoolbox.org/faq/how_not_to_interpret_results_from_a_cluster-based_permutation_test +.. _ft_cluster_effect_size: https://mailman.science.ru.nl/pipermail/fieldtrip/2017-September/011773.html +.. _ft_exch: https://mailman.science.ru.nl/pipermail/fieldtrip/2008-October/001794.html + + +.. git stuff + +.. _git: https://git-scm.com/ +.. _github: https://github.com +.. _GitHub Help: https://help.github.com +.. _GitHub skills: https://skills.github.com/ +.. _pro git book: https://git-scm.com/book/ +.. _git bash: https://gitforwindows.org/ +.. _git for Windows: https://gitforwindows.org/ +.. _git clone: http://schacon.github.com/git/git-clone.html +.. _git checkout: https://schacon.github.io/git/git-checkout.html +.. _git commit: https://schacon.github.io/git/git-commit.html +.. _git push: https://schacon.github.io/git/git-push.html +.. _git pull: https://schacon.github.io/git/git-pull.html +.. _git add: https://schacon.github.io/git/git-add.html +.. _git status: https://schacon.github.io/git/git-status.html +.. _git diff: https://schacon.github.io/git/git-diff.html +.. _git log: https://schacon.github.io/git/git-log.html +.. _git branch: https://schacon.github.io/git/git-branch.html +.. _git remote: https://schacon.github.io/git/git-remote.html +.. _git rebase: https://schacon.github.io/git/git-rebase.html +.. _git config: https://schacon.github.io/git/git-config.html + +.. other stuff + +.. _python: http://www.python.org +.. _Brain Imaging Data Structure: https://bids.neuroimaging.io/ +.. _SPEC0: https://scientific-python.org/specs/spec-0000 +.. _mri_watershed: https://surfer.nmr.mgh.harvard.edu/fswiki/mri_watershed +.. _recon-all: https://surfer.nmr.mgh.harvard.edu/fswiki/recon-all + +.. python packages + +.. _numpy: http://www.numpy.org +.. _scipy: http://www.scipy.org +.. _freesurfer: https://surfer.nmr.mgh.harvard.edu/ +.. _nipy: http://nipy.org/nipy +.. _h5py: http://www.h5py.org +.. _pymatreader: https://gitlab.com/obob/pymatreader +.. _h5io: https://github.com/h5io/h5io +.. _CuPy: https://cupy.chainer.org/ +.. _Dask: https://dask.org/ +.. _pep8: https://pypi.org/project/pep8/ +.. _pyflakes: https://pypi.org/project/pyflakes +.. _coverage: https://pypi.python.org/pypi/coverage +.. _mayavi: https://docs.enthought.com/mayavi/mayavi/ +.. _nitime: http://nipy.org/nitime/ +.. _joblib: https://pypi.python.org/pypi/joblib +.. _scikit-learn: https://scikit-learn.org/stable/ +.. _matplotlib: https://matplotlib.org/ +.. _sphinx: https://www.sphinx-doc.org/ +.. _pandas: https://pandas.pydata.org/ +.. _PIL: https://pypi.python.org/pypi/PIL +.. _tqdm: https://tqdm.github.io/ +.. _pooch: https://www.fatiando.org/pooch/latest/ +.. _towncrier: https://towncrier.readthedocs.io/ + +.. python editors + +.. _Spyder: https://www.spyder-ide.org/ +.. _`integrated development environment`: https://en.wikipedia.org/wiki/Integrated_development_environment +.. _`spyder`: https://www.spyder-ide.org/ +.. _`visual studio code`: https://code.visualstudio.com/ +.. _`pycharm`: https://www.jetbrains.com/pycharm/ + +.. _anaconda: https://www.anaconda.com/products/individual +.. _miniconda: https://conda.io/en/latest/miniconda.html +.. _miniforge: https://github.com/conda-forge/miniforge +.. _installation instructions for Anaconda: http://docs.continuum.io/anaconda/install +.. _installation instructions for Miniconda: https://conda.io/projects/conda/en/latest/user-guide/install/index.html +.. _Anaconda troubleshooting guide: http://conda.pydata.org/docs/troubleshooting.html +.. _conda-forge: https://conda-forge.org + +.. installation links + +.. _NVIDIA CUDA GPU processing: https://developer.nvidia.com/cuda-zone +.. _NVIDIA proprietary drivers: https://www.geforce.com/drivers + +.. _Sphinx documentation: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html +.. _sphinx-gallery: https://sphinx-gallery.github.io +.. _NumPy docstring style guidelines: https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard +.. _Stack Overflow: https://stackoverflow.com/ diff --git a/mne-python/source/doc/mne_cpp.rst b/mne-python/source/doc/mne_cpp.rst new file mode 100644 index 0000000000000000000000000000000000000000..6d586b9b33c896ea0e8b4a8255abce73a79d9f7f --- /dev/null +++ b/mne-python/source/doc/mne_cpp.rst @@ -0,0 +1,35 @@ +:orphan: + +.. _mne_cpp: + +====================== +MNE with CPP +====================== + +MNE-CPP is a cross-platform application and algorithm C++ framework +for MEG/EEG data acquisition, analysis and visualization. It +provides a modular structure with sub-libraries. The MNE-CPP API +can be integrated into other stand-alone projects to, e.g. provide +full I/O support for the FIF-file format or files generated by the +MNE and Freesurfer suite. MNE-CPP’s 3D visualization library is based +on the Qt3D module, which provides tools for online data displaying +with OpenGL. + +MNE-CPP ships with built-in stand-alone applications, some of which +are closely connected to well-known MNE-C applications. MNE Browse can +be used to inspect and process pre-recorded data. Among others, dipole +fitting and the computation of forward solutions have been ported from +the MNE-C library, including the same command line interfaces. With MNE +Scan the MNE-CPP project provides an application for acquiring and +processing MEG/EEG data in real-time. Supported MEG devices include +the Elekta Neuromag VectorView and BabyMEG system. Several EEG amplifiers +(TMSI Refa, BrainAmp, ANT eegosports, gUSBamp) are supported as well. + +For further information please visit the MNE-CPP project pages: + + * `Project Page `_ + * `GitHub Sources `_ + +.. raw:: html + +
diff --git a/mne-python/source/doc/old_versions/index.rst b/mne-python/source/doc/old_versions/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..abac30dad821aafe09951d306efff0a684f74eb3 --- /dev/null +++ b/mne-python/source/doc/old_versions/index.rst @@ -0,0 +1,18 @@ +Archived documentation for old versions +======================================= + +.. compressed with: zip -r -s 100m 0.20.zip 0.20/ + +Zip archives of old documentation versions are available below. Some have +multiple parts because GitHub has a 100 MB file size limit. + +- `v0.20 part 1 `__ and `part 2 `__ +- `v0.19 part 1 `__ and `part 2 `__ +- `v0.18 `__ +- `v0.17 `__ +- `v0.16 `__ +- `v0.15 `__ +- `v0.14 `__ +- `v0.13 `__ +- `v0.12 `__ +- `v0.11 `__ diff --git a/mne-python/source/doc/overview/people.rst b/mne-python/source/doc/overview/people.rst new file mode 100644 index 0000000000000000000000000000000000000000..d3d5899ffb6674a6f4c6a12ca9dda27b3087294f --- /dev/null +++ b/mne-python/source/doc/overview/people.rst @@ -0,0 +1,92 @@ +:orphan: + +.. _governance-people: + +Current Project Leadership and Institutional Partners +===================================================== + +.. _maintainer-team-people: + +Maintainer Team +--------------- + +* `Alex Gramfort`_ +* `Britta Westner`_ +* `Carina Forster`_ +* `Clemens Brunner`_ +* `Daniel McCloy`_ +* `Eric Larson`_ +* `Erica Peterson`_ +* `Marijn van Vliet`_ +* `Mathieu Scheltienne`_ +* `Richard Höchenberger`_ +* `Scott Huberty`_ +* `Stefan Appelhoff`_ +* `Thomas Binns`_ + +Past Maintainers +---------------- + +* `Adam Li`_ +* `Alex Rockhill`_ +* `Denis Engemann`_ +* `Chris Holdgraf`_ +* `Christian Brodbeck`_ +* `Guillaume Favelier`_ +* `Jaakko Leppakangas`_ +* `Jean-Rémi King`_ +* `Joan Massich`_ +* `Jona Sassenhagen`_ +* `Luke Bloy`_ +* `Mainak Jas`_ +* `Martin Luessi`_ +* `Mikołaj Magnuski`_ +* `Robert Luke`_ +* `Roman Goj`_ +* `Teon Brooks`_ + +.. _steering-council-people: + +Steering Council +---------------- + +* `Britta Westner`_ +* `Daniel McCloy`_ (chair) +* `Eric Larson`_ + +.. _advisory-board-people: + +Advisory Board +-------------- + +* `Alex Gramfort`_ +* `Bradley Voytek`_ +* `Jan-Mathijs Schoeffelen`_ +* `Liberty Hamilton`_ +* `Matti Hämäläinen`_ +* `Ole Jensen`_ + + +.. _governance-cpgrl: + +Community Participation Guidelines Response Leads +------------------------------------------------- + +See our `Community Participation Guidelines `__ +for explanation. Current Response Leads are: + +* `Daniel McCloy`_ +* `Eric Larson`_ + + +Institutional Partners +---------------------- + +.. include:: ../_includes/institutional-partners.rst + :start-after: institutional-partners-begin-content + + +Document history +---------------- + +https://github.com/mne-tools/mne-python/commits/main/doc/overview/people.rst diff --git a/mne-python/source/doc/references.bib b/mne-python/source/doc/references.bib new file mode 100644 index 0000000000000000000000000000000000000000..12d63458bd187a0ee3ca5b46a17c7addf8ba8435 --- /dev/null +++ b/mne-python/source/doc/references.bib @@ -0,0 +1,2547 @@ +% Encoding: UTF-8 +% +% If available, include a DOI (preferred) *or* a URL for a given reference, but +# not both, as the DOI turns into a link which is redundant with the URL. + +% MNE-C reference +@article{GramfortEtAl2014, + title = {{{MNE}} Software for Processing {{MEG}} and {{EEG}} Data}, + author = {Gramfort, Alexandre and Luessi, Martin and Larson, Eric and Engemann, Denis A. and Strohmeier, Daniel and Brodbeck, Christian and Parkkonen, Lauri and H{\"a}m{\"a}l{\"a}inen, Matti S.}, + year = {2014}, + volume = {86}, + pages = {446--460}, + doi = {10.1016/j.neuroimage.2013.10.027}, + journal = {NeuroImage}, +} +% MNE-Python reference +@article{GramfortEtAl2013a, + title = {{{MEG}} and {{EEG}} Data Analysis with {{MNE}}-{{Python}}}, + author = {Gramfort, Alexandre and Luessi, Martin and Larson, Eric and Engemann, Denis A. and Strohmeier, Daniel and Brodbeck, Christian and Goj, Roman and Jas, Mainak and Brooks, Teon and Parkkonen, Lauri and H{\"a}m{\"a}l{\"a}inen, Matti S.}, + year = {2013}, + volume = {7}, + pages = {1--13}, + doi = {10.3389/fnins.2013.00267}, + journal = {Frontiers in Neuroscience}, + number = {267} +} +% everything else +@article{AblinEtAl2018, + author = {Ablin, Pierre and Cardoso, Jean-Francois and Gramfort, Alexandre}, + doi = {10.1109/TSP.2018.2844203}, + journal = {IEEE Transactions on Signal Processing}, + number = {15}, + pages = {4040-4049}, + title = {Faster {{Independent Component Analysis}} by Preconditioning with Hessian Approximations}, + volume = {66}, + year = {2018} +} + +@article{AcunzoEtAl2012, + author = {Acunzo, David J. and MacKenzie, Graham and {van Rossum}, Mark C.W.}, + doi = {10.1016/j.jneumeth.2012.06.011}, + journal = {Journal of Neuroscience Methods}, + number = {1}, + pages = {212-218}, + title = {Systematic Biases in Early {{ERP}} and {{ERF}} Components as a Result of High-Pass Filtering}, + volume = {209}, + year = {2012} +} + +@article{Alday2019, + title = {How much baseline correction do we need in {ERP} research? Extended {GLM} model can replace baseline correction while lifting its limits}, + author = {Alday, Phillip M.}, + year = {2019}, + volume = {56}, + doi = {10.1111/psyp.13451}, + journal = {Psychophysiology}, + number = {12} +} + +@article{ArtoniEtAl2018, + author = {Artoni, Fiorenzo and Delorme, Arnaud and Makeig, Scott}, + doi = {10.1016/j.neuroimage.2018.03.016}, + journal = {NeuroImage}, + pages = {176-187}, + title = {Applying Dimension Reduction to {{EEG}} Data by {{Principal Component Analysis}} Reduces the Quality of Its Subsequent {{Independent Component}} Decomposition}, + volume = {175}, + year = {2018} +} + +@article{AvantsEtAl2008, + author = {Avants, Brian B. and Epstein, Charles L. and Grossman, Murray C. and Gee, James C.}, + doi = {10.1016/j.media.2007.06.004}, + journal = {Medical Image Analysis}, + number = {1}, + pages = {26-41}, + shorttitle = {Symmetric Diffeomorphic Image Registration with Cross-Correlation}, + title = {Symmetric Diffeomorphic Image Registration with Cross-Correlation: Evaluating Automated Labeling of Elderly and Neurodegenerative Brain}, + volume = {12}, + year = {2008} +} + +@article{BailletEtAl2001, + author = {Baillet, Sylvain and Mosher, John C. and Leahy, Richard M.}, + doi = {10.1109/79.962275}, + journal = {IEEE Signal Processing Magazine}, + number = {6}, + pages = {14-30}, + title = {Electromagnetic Brain Mapping}, + volume = {18}, + year = {2001} +} + +@inproceedings{BarachantEtAl2010, + author = {Barachant, Alexandre and Bonnet, Stephane and Congedo, Marco and Jutten, Christian}, + booktitle = {2010 IEEE International Workshop on Multimedia Signal Processing}, + title = {Common Spatial Pattern revisited by {Riemannian} geometry}, + year = {2010}, + pages={472-476}, + doi = {10.1109/MMSP.2010.5662067} +} + +@book{Barber2012, + address = {{Cambridge}}, + author = {Barber, David}, + isbn = {978-0-521-51814-7}, + publisher = {{Cambridge University Press}}, + title = {Bayesian Reasoning and Machine Learning}, + url = {http://www.cs.ucl.ac.uk/staff/d.barber/brml/}, + year = {2012} +} + +@inproceedings{BekhtiEtAl2016, + address = {{Trento}}, + author = {Bekhti, Yousra and Strohmeier, Daniel and Jas, Mainak and Badeau, Roland and Gramfort, Alexandre}, + booktitle = {Proceedings of {{PRNI}}-2016}, + doi = {10.1109/PRNI.2016.7552337}, + isbn = {978-1-4673-6530-7}, + pages = {1-4}, + publisher = {{IEEE}}, + title = {M/{{EEG}} Source Localization with Multi-Scale Time-Frequency Dictionaries}, + year = {2016} +} + +@article{BellSejnowski1995, + author = {Bell, Anthony J. and Sejnowski, Terrence J.}, + doi = {10.1162/neco.1995.7.6.1129}, + journal = {Neural Computation}, + number = {6}, + pages = {1129-1159}, + title = {An Information-Maximization Approach to Blind Separation and Blind Deconvolution}, + volume = {7}, + year = {1995} +} + +@article{BentivoglioEtAl1997, + author = {Bentivoglio, Anna Rita and Bressman, Susan B. and Cassetta, Emanuele and Carretta, Donatella and Tonali, Pietro and Albanese, Alberto}, + doi = {10.1002/mds.870120629}, + journal = {Movement Disorders}, + number = {6}, + pages = {1028-1034}, + title = {Analysis of Blink Rate Patterns in Normal Subjects}, + volume = {12}, + year = {1997} +} + +@article{BergScherg1994, + author = {Berg, Patrick and Scherg, Michael}, + doi = {10.1016/0013-4694(94)90113-9}, + journal = {Electroencephalography and Clinical Neurophysiology}, + number = {1}, + pages = {58-64}, + title = {A Fast Method for Forward Computation of Multiple-Shell Spherical Head Models}, + volume = {90}, + year = {1994} +} + +@inproceedings{BigdelyShamloEtAl2013, + author = {Bigdely-Shamlo, Nima and Kreutz-Delgado, Kenneth and Robbins, Kay and Miyakoshi, Makoto and Westerfield, Marissa and Bel-Bahar, Tarik and Kothe, Christian and Hsi, Jessica and Makeig, Scott}, + doi = {10.1109/GlobalSIP.2013.6736796}, + booktitle = {2013 IEEE Global Conference on Signal and Information Processing}, + pages = {1--4}, + title = {Hierarchical event descriptor {(HED)} tags for analysis of event-related {EEG} studies}, + organization = {IEEE}, + year = {2013}, +} + +@article{BlankertzEtAl2008, + author = {Blankertz, Benjamin and Tomioka, Ryota and Lemm, Steven and Kawanabe, Motoaki and Müller, Klaus-Robert}, + doi = {10.1109/MSP.2008.4408441}, + journal = {IEEE Signal Processing Magazine}, + number = {1}, + pages = {41-56}, + title = {Optimizing Spatial Filters for Robust {{EEG}} Single-Trial Analysis}, + volume = {25}, + year = {2008} +} + +@article{Bookstein1989, + author = {Bookstein, Fred L.}, + doi = {10.1109/34.24792}, + journal = {IEEE Transactions on Pattern Analysis and Machine Intelligence}, + number = {6}, + pages = {567-585}, + shorttitle = {Principal Warps}, + title = {Principal Warps: Thin-Plate Splines and the Decomposition of Deformations}, + volume = {11}, + year = {1989} +} + +@article{BrookesEtAl2008, + author = {Brookes, Matthew J. and Vrba, Jiri and Robinson, Stephen E. and Stevenson, Claire M. and Peters, Andrew M. and Barnes, Gareth R. and Hillebrand, Arjan and Morris, Peter G.}, + doi = {10.1016/j.neuroimage.2007.09.050}, + journal = {NeuroImage}, + number = {4}, + pages = {1788-1802}, + title = {Optimising Experimental Design for {{MEG}} Beamformer Imaging}, + volume = {39}, + year = {2008} +} + +@article{BrunaEtAl2018, + doi = {10.1088/1741-2552/aacfe4}, + year = {2018}, + publisher = {{IOP} Publishing}, + volume = {15}, + number = {5}, + pages = {056011}, + author = {Ricardo Bru{\~{n}}a, Fernando Maest{\'{u}}, Ernesto Pereda}, + title = {Phase locking value revisited: teaching new tricks to an old dog}, + journal = {Journal of Neural Engineering}, +} + +@techreport{BurdakovMerkulov2001, + title={On a new norm for data fitting and optimization problems}, + author={Burdakov, Oleg and Merkulov, Boris}, + number={LiTH-MAT-R-2001-29}, + address={Link{\"o}ping}, + institution={Link{\"o}ping University}, + type = {Technical {{Report}}}, + year={2001} +} + +@article{CamposViolaEtAl2009, + author = {Campos Viola, Filipa and Thorne, Jeremy and Edmonds, Barrie and Schneider, Till and Eichele, Tom and Debener, Stefan}, + doi = {10.1016/j.clinph.2009.01.015}, + journal = {Clinical Neurophysiology}, + number = {5}, + pages = {868-877}, + title = {Semi-Automatic Identification of Independent Components Representing {{EEG}} Artifact}, + volume = {120}, + year = {2009} +} + +@article{ChambonEtAl2018, + author = {Chambon, Stanislas and Galtier, Mathieu N. and Arnal, Pierrick J. and Wainrib, Gilles and Gramfort, Alexandre}, + doi = {10.1109/TNSRE.2018.2813138}, + journal = {IEEE Transactions on Neural Systems and Rehabilitation Engineering}, + number = {4}, + pages = {758-769}, + title = {A Deep Learning Architecture for Temporal Sleep Stage Classification Using Multivariate and Multimodal Time Series}, + volume = {26}, + year = {2018} +} + +@article{ChenEtAl2010, + author = {Chen, Yilun and Wiesel, Ami and Eldar, Yonina C. and Hero, Alfred O.}, + doi = {10.1109/TSP.2010.2053029}, + journal = {IEEE Transactions on Signal Processing}, + number = {10}, + pages = {5016-5029}, + title = {Shrinkage Algorithms for {{MMSE}} Covariance Estimation}, + volume = {58}, + year = {2010} +} + +@article{CichyEtAl2014, + author = {Cichy, Radoslaw Martin and Pantazis, Dimitrios and Oliva, Aude}, + doi = {10.1038/nn.3635}, + journal = {Nature Neuroscience}, + number = {3}, + pages = {455-462}, + title = {Resolving Human Object Recognition in Space and Time}, + volume = {17}, + year = {2014} +} + +@book{Cohen2014, + place={Cambridge, MA}, + title={Analyzing Neural Time Series Data: Theory and Practice}, + publisher={MIT Press}, + author={Cohen, Mike X.}, + year={2014} +} + +@article{Cohen2019, + author={Cohen, Michael X}, + doi = {10.1016/j.neuroimage.2019.05.048}, + journal = {NeuroImage}, + pages = {81-86}, + title = {A better way to define and describe {Morlet} wavelets for time-frequency analysis}, + volume = {199}, + year = {2019} +} + +@article{Cohen2022, +author = {Cohen, Michael X}, +doi = {10.1016/j.neuroimage.2021.118809}, +journal = {NeuroImage}, +pages = {118809}, +title = {A tutorial on generalized eigendecomposition for denoising, contrast enhancement, and dimension reduction in multichannel electrophysiology}, +volume = {247}, +year = {2022}, +issn = {1053-8119}, + +} + +@article{CohenHosaka1976, + author = {Cohen, David and Hosaka, Hidehiro}, + doi = {10.1016/S0022-0736(76)80041-6}, + journal = {Journal of Electrocardiology}, + number = {4}, + pages = {409-417}, + title = {Part {{II}} Magnetic Field Produced by a Current Dipole}, + volume = {9}, + year = {1976} +} + +@article{CrosseEtAl2016, + author = {Crosse, Michael J. and Di Liberto, Giovanni M. and Bednar, Adam and Lalor, Edmund C.}, + doi = {10.3389/fnhum.2016.00604}, + journal = {Frontiers in Human Neuroscience}, + shorttitle = {The Multivariate Temporal Response Function ({{mTRF}}) Toolbox}, + title = {The Multivariate Temporal Response Function ({{mTRF}}) Toolbox: A {{MATLAB}} Toolbox for Relating Neural Signals to Continuous Stimuli}, + volume = {10}, + year = {2016} +} + +@article{DahneEtAl2014, + author = {Dähne, Sven and Meinecke, Frank C. and Haufe, Stefan and Höhne, Johannes and Tangermann, Michael and Müller, Klaus-Robert and Nikulin, Vadim V.}, + doi = {10.1016/j.neuroimage.2013.07.079}, + journal = {NeuroImage}, + pages = {111-122}, + shorttitle = {{{SPoC}}}, + title = {{{SPoC}}: A Novel Framework for Relating the Amplitude of Neuronal Oscillations to Behaviorally Relevant Parameters}, + volume = {86}, + year = {2014} +} + +@article{DalalEtAl2008, + author = {Dalal, Sarang S. and Guggisberg, Adrian G. and Edwards, Erik and Sekihara, Kensuke and Findlay, Anne M. and Canolty, Ryan T. and Berger, Mitchel S. and Knight, Robert T. and Barbaro, Nicholas M. and Kirsch, Heidi E. and Nagarajan, Srikantan S.}, + doi = {10.1016/j.neuroimage.2008.01.023}, + journal = {NeuroImage}, + number = {4}, + pages = {1686-1700}, + shorttitle = {Five-Dimensional Neuroimaging}, + title = {Five-Dimensional Neuroimaging: Localization of the Time–Frequency Dynamics of Cortical Activity}, + volume = {40}, + year = {2008} +} + +@article{DaleEtAl1999, + author = {Dale, Anders M. and Fischl, Bruce and Sereno, Martin I.}, + doi = {10.1006/nimg.1998.0395}, + journal = {NeuroImage}, + number = {2}, + pages = {179-194}, + title = {Cortical Surface-Based Analysis: {{I}}. Segmentation and Surface Reconstruction}, + volume = {9}, + year = {1999} +} + +@article{DaleEtAl2000, + author = {Dale, Anders M. and Liu, Arthur K. and Fischl, Bruce R. and Buckner, Randy L. and Belliveau, John W. and Lewine, Jeffrey D. and Halgren, Eric}, + doi = {10.1016/S0896-6273(00)81138-1}, + journal = {Neuron}, + number = {1}, + pages = {55-67}, + title = {Dynamic Statistical Parametric Mapping: Combining {{fMRI}} and {{MEG}} for High-Resolution Imaging of Cortical Activity}, + volume = {26}, + year = {2000} +} + +@article{DaleSereno1993, + author = {Dale, Anders M. and Sereno, Martin I.}, + doi = {10.1162/jocn.1993.5.2.162}, + journal = {Journal of Cognitive Neuroscience}, + number = {2}, + pages = {162-176}, + shorttitle = {Improved Localization of Cortical Activity by Combining {{EEG}} and {{MEG}} with {{MRI}} Cortical Surface Reconstruction}, + title = {Improved Localization of Cortical Activity by Combining {{EEG}} and {{MEG}} with {{MRI}} Cortical Surface Reconstruction: A Linear Approach}, + volume = {5}, + year = {1993} +} + +@article{DammersEtAl2008, + author = {Dammers, Jürgen and Schiek, Michael and Boers, Frank and Silex, Carmen and Zvyagintsev, Mikhail and Pietrzyk, Uwe and Mathiak, Klaus}, + doi = {10.1109/TBME.2008.926677}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {10}, + pages = {2353-2362}, + title = {Integration of Amplitude and Phase Statistics for Complete Artifact Removal in Independent Components of Neuromagnetic Recordings}, + volume = {55}, + year = {2008} +} + +@article{DarvasEtAl2006, + author = {Darvas, Felix and Ermer, John J. and Mosher, John C. and Leahy, Richard M.}, + doi = {10.1002/hbm.20171}, + journal = {Human Brain Mapping}, + number = {2}, + pages = {129-143}, + title = {Generic Head Models for Atlas-Based {{EEG}} Source Analysis}, + volume = {27}, + year = {2006} +} + +@article{DelormeMakeig2004, + title = {{EEGLAB}: an open source toolbox for analysis of single-trial {EEG} dynamics including independent component analysis}, + volume = {134}, + issn = {0165-0270}, + shorttitle = {{EEGLAB}}, + doi = {10.1016/j.jneumeth.2003.10.009}, + language = {eng}, + number = {1}, + journal = {Journal of Neuroscience Methods}, + author = {Delorme, Arnaud and Makeig, Scott}, + month = mar, + year = {2004}, + pmid = {15102499}, + keywords = {Computer Simulation, Electroencephalography, Evoked Potentials, Software}, + pages = {9--21} +} + +@article{DestrieuxEtAl2010, + author = {Destrieux, Christophe and Fischl, Bruce and Dale, Anders and Halgren, Eric}, + doi = {10.1016/j.neuroimage.2010.06.010}, + journal = {NeuroImage}, + number = {1}, + pages = {1-15}, + title = {Automatic Parcellation of Human Cortical Gyri and Sulci Using Standard Anatomical Nomenclature}, + volume = {53}, + year = {2010} +} + +@inproceedings{DharmapraniEtAl2016, + address = {Orlando, FL, USA}, + title = {A comparison of independent component analysis algorithms and measures to discriminate between {EEG} and artifact components}, + isbn = {978-1-4577-0220-4}, + doi = {10.1109/EMBC.2016.7590828}, + booktitle = {2016 38th {Annual} {International} {Conference} of the {IEEE} {Engineering} in {Medicine} and {Biology} {Society} ({EMBC})}, + publisher = {IEEE}, + author = {Dharmaprani, Dhani and Nguyen, Hoang K. and Lewis, Trent W. and DeLosAngeles, Dylan and Willoughby, John O. and Pope, Kenneth J.}, + year = {2016}, + pages = {825--828}, +} + + +@article{DufauEtAl2015, + author = {Dufau, Stéphane and Grainger, Jonathan and Midgley, Katherine J. and Holcomb, Phillip J.}, + doi = {10.1177/0956797615603934}, + journal = {Psychological Science}, + number = {12}, + pages = {1887-1897}, + shorttitle = {A Thousand Words Are Worth a Picture}, + title = {A Thousand Words Are Worth a Picture: Snapshots of Printed-Word Processing in an Event-Related Potential Megastudy}, + volume = {26}, + year = {2015} +} + +@book{EfronHastie2016, + address = {{New York}}, + author = {Efron, Bradley and Hastie, Trevor}, + isbn = {978-1-107-14989-2}, + number = {5}, + publisher = {{Cambridge University Press}}, + series = {Institute of {{Mathematical Statistics}} Monographs}, + shorttitle = {Computer Age Statistical Inference}, + title = {Computer Age Statistical Inference: Algorithms, Evidence, and Data Science}, + url = {https://hastie.su.domains/CASI/}, + year = {2016} +} + +@article{EngemannGramfort2015, + author = {Engemann, Denis A. and Gramfort, Alexandre}, + doi = {10.1016/j.neuroimage.2014.12.040}, + journal = {NeuroImage}, + pages = {328-342}, + title = {Automated Model Selection in Covariance Estimation and Spatial Whitening of {{MEG}} and {{EEG}} Signals}, + volume = {108}, + year = {2015} +} + +@article{FischlEtAl1999, + author = {Fischl, Bruce and Sereno, Martin I. and Dale, Anders M.}, + doi = {10.1006/nimg.1998.0396}, + journal = {NeuroImage}, + number = {2}, + pages = {195-207}, + title = {Cortical Surface-Based Analysis: {{II}}. Inflation, Flattening, and a Surface-Based Coordinate System}, + volume = {9}, + year = {1999} +} + +@article{FischlEtAl1999a, + author = {Fischl, Bruce and Sereno, Martin I. and Tootell, Roger B.H. and Dale, Anders M.}, + doi = {10.1002/(SICI)1097-0193(1999)8:4<272::AID-HBM10>3.0.CO;2-4}, + journal = {Human Brain Mapping}, + number = {4}, + pages = {272-284}, + title = {High-Resolution Intersubject Averaging and a Coordinate System for the Cortical Surface}, + volume = {8}, + year = {1999} +} + +@article{FischlEtAl2004, + author = {Fischl, Bruce and Salat, David H. and {van der Kouwe}, André J.W. and Makris, Nikos and Ségonne, Florent and Quinn, Brian T. and Dale, Anders M.}, + doi = {10.1016/j.neuroimage.2004.07.016}, + journal = {NeuroImage}, + pages = {S69-S84}, + title = {Sequence-Independent Segmentation of Magnetic Resonance Images}, + volume = {23}, + year = {2004} +} + +@article{FishburnEtAl2019, + title={Temporal derivative distribution repair (TDDR): a motion correction method for {fNIRS}}, + doi = {10.1016/j.neuroimage.2018.09.025}, + author={Fishburn, Frank A and Ludlum, Ruth S and Vaidya, Chandan J and Medvedev, Andrei V}, + journal={NeuroImage}, + volume={184}, + pages={171--179}, + year={2019}, + publisher={Elsevier} +} + +@article{GlasserEtAl2016, + author = {Glasser, Matthew F. and Coalson, Timothy S. and Robinson, Emma C. and Hacker, Carl D. and Harwell, John and Yacoub, Essa and Ugurbil, Kamil and Andersson, Jesper and Beckmann, Christian F. and Jenkinson, Mark and Smith, Stephen M. and Van Essen, David C.}, + doi = {10.1038/nature18933}, + journal = {Nature}, + number = {7615}, + pages = {171-178}, + title = {A multi-modal parcellation of human cerebral cortex}, + volume = {536}, + year = {2016} +} + +@article{GlasserEtAl2016supp, + author = {Glasser, Matthew F. and Coalson, Timothy S. and Robinson, Emma C. and Hacker, Carl D. and Harwell, John and Yacoub, Essa and Ugurbil, Kamil and Andersson, Jesper and Beckmann, Christian F. and Jenkinson, Mark and Smith, Stephen M. and Van Essen, David C.}, + url = {https://static-content.springer.com/esm/art%3A10.1038%2Fnature18933/MediaObjects/41586_2016_BFnature18933_MOESM330_ESM.pdf#page=2}, + journal = {Nature}, + number = {7615}, + title = {Supplementary neuroanatomical results for “{A} multi-modal parcellation of human cerebral cortex”}, + volume = {536}, + year = {2016} +} + +@article{GoldbergerEtAl2000, + author = {Goldberger, Ary L. and Amaral, Luis A. N. and Glass, Leon and Hausdorff, Jeffrey M. and Ivanov, Plamen Ch. and Mark, Roger G. and Mietus, Joseph E. and Moody, George B. and Peng, Chung-Kang and Stanley, H. Eugene}, + doi = {10.1161/01.CIR.101.23.e215}, + journal = {Circulation}, + number = {23}, + shorttitle = {{{PhysioBank}}, {{PhysioToolkit}}, and {{PhysioNet}}}, + title = {{{PhysioBank}}, {{PhysioToolkit}}, and {{PhysioNet}}: {{Components}} of a New Research Resource for Complex Physiologic Signals}, + volume = {101}, + year = {2000} +} + +@article{GoldenholzEtAl2009, + author = {Goldenholz, Daniel M. and Ahlfors, Seppo P. and Hämäläinen, Matti S. and Sharon, Dahlia and Ishitobi, Mamiko and Vaina, Lucia M. and Stufflebeam, Steven M.}, + doi = {10.1002/hbm.20571}, + journal = {Human Brain Mapping}, + number = {4}, + pages = {1077-1086}, + title = {Mapping the Signal-to-Noise-Ratios of Cortical Sources in Magnetoencephalography and Electroencephalography}, + volume = {30}, + year = {2009} +} + +@article{GoncalvesEtAl2003, + author = {Gonçalves, Sónia I. and {de Munck}, Jan Casper and Verbunt, Jeroen P. A. and Bijma, Fetsje and Heethaar, Rob M. and {Lopes da Silva}, Fernando}, + doi = {10.1109/TBME.2003.812164}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {6}, + pages = {754-767}, + title = {In Vivo Measurement of the Brain and Skull Resistivities Using an {{EIT}}-Based Method and Realistic Models for the Head}, + volume = {50}, + year = {2003} +} + +@article{GraimannEtAl2002, + author = {Graimann, Bernhard and Huggins, Jane E. and Levine, Simon P. and Pfurtscheller, Gert}, + doi = {10.1016/S1388-2457(01)00697-6}, + journal = {Clinical Neurophysiology}, + number = {1}, + pages = {43-47}, + title = {Visualization of Significant {{ERD}}/{{ERS}} Patterns in Multichannel {{EEG}} and {{ECoG}} Data}, + volume = {113}, + year = {2002} +} + +@article{GramfortEtAl2010, + author = {Alexandre Gramfort and Renaud Keriven and Maureen Clerc}, + title = {Graph-Based Variability Estimation in Single-Trial Event-Related Neural Responses}, + journal = {{IEEE} Transactions on Biomedical Engineering}, + doi = {10.1109/tbme.2009.2037139}, + year = {2010}, + publisher = {Institute of Electrical and Electronics Engineers ({IEEE})}, + volume = {57}, + number = {5}, + pages = {1051--1061}, +} + +@incollection{GramfortEtAl2011, + address = {{Berlin; Heidelberg}}, + author = {Gramfort, Alexandre and Strohmeier, Daniel and Haueisen, Jens and Hämäläinen, Matti S. and Kowalski, Matthieu}, + booktitle = {Information {{Processing}} in {{Medical Imaging}}}, + doi = {10.1007/978-3-642-22092-0_49}, + editor = {Székely, Gábor and Hahn, Horst K.}, + isbn = {978-3-642-22091-3 978-3-642-22092-0}, + pages = {600-611}, + publisher = {Springer}, + title = {Functional Brain Imaging with {M/EEG} Using Structured Sparsity in Time-Frequency Dictionaries}, + volume = {6801}, + year = {2011} +} + +@article{GramfortEtAl2012, + author = {Gramfort, Alexandre and Kowalski, Matthieu and Hämäläinen, Matti S.}, + doi = {10.1088/0031-9155/57/7/1937}, + journal = {Physics in Medicine and Biology}, + number = {7}, + pages = {1937-1961}, + title = {Mixed-Norm Estimates for the {M/EEG} Inverse Problem Using Accelerated Gradient Methods}, + volume = {57}, + year = {2012} +} + +@article{GramfortEtAl2013b, + author = {Gramfort, Alexandre and Strohmeier, Daniel T. and Haueisen, Jens and Hämäläinen, Matti S. and Kowalski, Matthieu}, + doi = {10.1016/j.neuroimage.2012.12.051}, + journal = {NeuroImage}, + pages = {410-422}, + shorttitle = {Time-Frequency Mixed-Norm Estimates}, + title = {Time-Frequency Mixed-Norm Estimates: Sparse {M/EEG} Imaging with Non-Stationary Source Activations}, + volume = {70}, + year = {2013} +} + +@article{GreischarEtAl2004, + title = {Effects of electrode density and electrolyte spreading in dense array electroencephalographic recording}, + volume = {115}, + issn = {13882457}, + doi = {10.1016/j.clinph.2003.10.028}, + language = {en}, + number = {3}, + journal = {Clinical Neurophysiology}, + author = {Greischar, Lawrence L. and Burghy, Cory A. and van Reekum, Carien M. and Jackson, Daren C. and Pizzagalli, Diego A. and Mueller, Corrina and Davidson, Richard J.}, + month = mar, + year = {2004}, + pages = {710--720} +} + +@article{GreveEtAl2013, + author = {Greve, Douglas N. and {Van der Haegen}, Lise and Cai, Qing and Stufflebeam, Steven and Sabuncu, Mert R. and Fischl, Bruce and Brysbaert, Marc}, + doi = {10.1162/jocn_a_00405}, + journal = {Journal of Cognitive Neuroscience}, + number = {9}, + pages = {1477-1492}, + title = {A Surface-Based Analysis of Language Lateralization and Cortical Asymmetry}, + volume = {25}, + year = {2013} +} + +@article{Grosse-WentrupBuss2008, + author = {{Grosse-Wentrup}, Moritz and Buss, Martin}, + doi = {10.1109/TBME.2008.921154}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {8}, + pages = {1991-2000}, + title = {Multiclass Common Spatial Patterns and Information Theoretic Feature Extraction}, + volume = {55}, + year = {2008} +} + +@article{GrossEtAl2001, + author = {Groß, Joachim and Kujala, Jan and Hämäläinen, Matti S. and Timmermann, Lars and Schnitzler, Alfons and Salmelin, Riitta}, + doi = {10.1073/pnas.98.2.694}, + journal = {Proceedings of the National Academy of Sciences}, + number = {2}, + pages = {694-699}, + shorttitle = {Dynamic Imaging of Coherent Sources}, + title = {Dynamic Imaging of Coherent Sources: Studying Neural Interactions in the Human Brain}, + volume = {98}, + year = {2001} +} + +@article{HamalainenEtAl1993, + author = {Hämäläinen, Matti S. and Hari, Riitta and Ilmoniemi, Risto J. and Knuutila, Jukka and Lounasmaa, Olli V.}, + doi = {10.1103/RevModPhys.65.413}, + journal = {Reviews of Modern Physics}, + number = {2}, + pages = {413-497}, + title = {Magnetoencephalography—Theory, Instrumentation, and Applications to Noninvasive Studies of the Working Human Brain}, + volume = {65}, + year = {1993} +} + +@incollection{HamalainenHari2002, + address = {{San Diego}}, + author = {Hämäläinen, Matti S. and Hari, Riitta}, + booktitle = {Brain Mapping: The Methods}, + doi = {10.1016/B978-012693019-1/50012-5}, + edition = {2}, + editor = {Toga, Arthur W. and Mazziotta, John C.}, + isbn = {978-0-12-693019-1}, + pages = {227 - 253}, + publisher = {{Academic Press}}, + title = {Magnetoencephalographic Characterization of Dynamic Brain Activation: Basic Principles and Methods of Data Collection and Source Analysis}, + year = {2002} +} + +@techreport{HamalainenIlmoniemi1984, + address = {{Helsinki}}, + author = {Hämäläinen, Matti S. and Ilmoniemi, Risto J.}, + number = {TKK-F-A559}, + title = {Interpreting Measured Magnetic Fields of the Brain: Estimates of Current Distributions}, + type = {Technical {{Report}}}, + institution = {Helsinki University of Technology}, + year = {1984} +} + +@article{HamalainenIlmoniemi1994, + author = {Hämäläinen, Matti S. and Ilmoniemi, Risto J., Ilmoniemi}, + doi = {10.1007/BF02512476}, + journal = {Medical \& Biological Engineering \& Computing}, + number = {1}, + pages = {35-42}, + shorttitle = {Interpreting Magnetic Fields of the Brain}, + title = {Interpreting Magnetic Fields of the Brain: Minimum Norm Estimates}, + volume = {32}, + year = {1994} +} + +@article{HamalainenSarvas1989, + author = {Hämäläinen, Matti S. and Sarvas, Jukka}, + doi = {10.1109/10.16463}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {2}, + pages = {165-171}, + title = {Realistic Conductivity Geometry Model of the Human Head for Interpretation of Neuromagnetic Data}, + volume = {36}, + year = {1989} +} + +@article{HamiltonEtAl2017, + author = {Hamilton, Liberty S. and Chang, David L. and Lee, Morgan B. and Chang, Edward F.}, + doi = {10.3389/fninf.2017.00062}, + journal = {Frontiers in Neuroinformatics}, + title = {Semi-automated Anatomical Labeling and Inter-subject Warping of High-Density Intracranial Recording Electrodes in Electrocorticography}, + volume = {11}, + issn = {1662-5196}, + month = oct, + year = {2017}, +} + +@article{HannaEtAl2020, + author = {Hanna, Jeff and Kim, Cora and Müller-Voggel, Nadia}, + doi = {10.1016/j.jneumeth.2020.108592}, + journal = {Journal of Neuroscience Methods}, + title = {External noise removed from magnetoencephalographic signal using Independent Component Analysis of reference channels}, + year = {2020} +} + +@article{HariSalmelin1997, + author = {Hari, Riitta and Salmelin, Riitta}, + doi = {10.1016/S0166-2236(96)10065-5}, + journal = {Trends in Neurosciences}, + number = {1}, + pages = {44-49}, + shorttitle = {Human Cortical Oscillations}, + title = {Human Cortical Oscillations: A Neuromagnetic View through the Skull}, + volume = {20}, + year = {1997} +} + +@article{HaufeEtAl2014, + author = {Haufe, Stefan and Meinecke, Frank and Görgen, Kai and Dähne, Sven and Haynes, John-Dylan and Blankertz, Benjamin and Bießmann, Felix}, + doi = {10.1016/j.neuroimage.2013.10.067}, + journal = {NeuroImage}, + pages = {96-110}, + title = {On the Interpretation of Weight Vectors of Linear Models in Multivariate Neuroimaging}, + volume = {87}, + year = {2014} +} + +@article{HaufeEtAl2014b, + author = {Haufe, Stefan and D{\"a}hne, Sven and Nikulin, Vadim V}, + doi = {https://doi.org/10.1016/j.neuroimage.2014.06.073}, + journal = {NeuroImage}, + pages = {583-597}, + title = {Dimensionality reduction for the analysis of brain oscillations}, + volume = {101}, + year = {2014} +} + +@article{HaukEtAl2006, + author = {Hauk, Olaf and Davis, Matt H. and Ford, Michael A. and Pulvermüller, Friedmann and {Marslen-Wilson}, William D.}, + doi = {10.1016/j.neuroimage.2005.11.048}, + journal = {NeuroImage}, + number = {4}, + pages = {1383-1400}, + title = {The Time Course of Visual Word Recognition as Revealed by Linear Regression Analysis of {{ERP}} Data}, + volume = {30}, + year = {2006} +} + +@article {HaukEtAl2019, + author = {Hauk, Olaf and Stenroos, Matti and Treder, Matthias}, + title = {Towards an Objective Evaluation of {EEG/MEG} Source Estimation Methods: The Linear Tool Kit}, + year = {2019}, + doi = {10.1101/672956}, + publisher = {Cold Spring Harbor Laboratory}, + journal = {bioRxiv} +} + +@book{Heiman2002, + address = {{Boston}}, + author = {Heiman, Gary W.}, + edition = {3}, + isbn = {978-0-618-17028-9}, + publisher = {{Houghton Mifflin Company}}, + title = {Research Methods in Psychology}, + year = {2002} +} + +@ARTICLE{HelleEtAl2021, + author={Helle, Liisa and Nenonen, Jukka and Larson, Eric and Simola, Juha and Parkkonen, Lauri and Taulu, Samu}, + journal={IEEE Transactions on Biomedical Engineering}, + title={Extended Signal-Space Separation Method for Improved Interference Suppression in MEG}, + year={2021}, + volume={68}, + number={7}, + pages={2211-2221}, + doi={10.1109/TBME.2020.3040373} +} + +@article{HippEtAl2011, + author = {Hipp, Joerg F. and Engel, Andreas K. and Siegel, Markus}, + doi = {10.1016/j.neuron.2010.12.027}, + journal = {Neuron}, + number = {2}, + pages = {387-396}, + title = {Oscillatory Synchronization in Large-Scale Cortical Networks Predicts Perception}, + volume = {69}, + year = {2011} +} + +@article{HippEtAl2012, + author = {Hipp, Joerg F and Hawellek, David J and Corbetta, Maurizio and Siegel, Markus and Engel, Andreas K}, + doi = {10.1038/nn.3101}, + journal = {Nature Neuroscience}, + number = {6}, + pages = {884-890}, + title = {Large-Scale Cortical Correlation Structure of Spontaneous Oscillatory Activity}, + volume = {15}, + year = {2012} +} + +@article{HoldgrafEtAl2016, + author = {Holdgraf, Christopher R. and {de Heer}, Wendy and Pasley, Brian and Rieger, Jochem and Crone, Nathan and Lin, Jack J. and Knight, Robert T. and Theunissen, Frédéric E.}, + doi = {10.1038/ncomms13654}, + journal = {Nature Communications}, + number = {1}, + title = {Rapid Tuning Shifts in Human Auditory Cortex Enhance Speech Intelligibility}, + volume = {7}, + year = {2016} +} + +@article{HouckClaus2020, + author = {Houck, Jon M. and Claus, Eric D.}, + doi = {10.1371/journal.pone.0232100}, + journal = {PLOS ONE}, + pages = {e0232100}, + title = {A comparison of automated and manual co-registration for magnetoencephalography}, + volume = {15}, + year = {2020} +} + +@article{Hyvarinen1999, + author = {Hyvärinen, Aapo}, + doi = {10.1109/72.761722}, + journal = {IEEE Transactions on Neural Networks}, + number = {3}, + pages = {626-634}, + title = {Fast and Robust Fixed-Point Algorithms for Independent Component Analysis}, + volume = {10}, + year = {1999} +} + +@book{IfeachorJervis2002, + author = {Ifeachor, Emmanuel C. and Jervis, Barrie W.}, + edition = {2}, + publisher = {{Pearson}}, + shorttitle = {Digital Signal Processing}, + title = {Digital Signal Processing: A Practical Approach}, + year = {2002} +} + +@article{JonesEtAl2006, + author = {Jones, Kevin A. and Porjesz, Bernice and Chorlian, David and Rangaswamy, Madhavi and Kamarajan, Chella and Padmanabhapillai, Ajayan and Stimus, Arthur and Begleiter, Henri}, + doi = {10.1016/j.clinph.2006.02.028}, + journal = {Clinical Neurophysiology}, + number = {10}, + pages = {2128-2143}, + title = {S-Transform Time-Frequency Analysis of {{P300}} Reveals Deficits in Individuals Diagnosed with Alcoholism}, + volume = {117}, + year = {2006} +} + +@article{JovicichEtAl2006, + author = {Jovicich, Jorge and Czanner, Silvester and Greve, Douglas and Haley, Elizabeth and {van der Kouwe}, Andre and Gollub, Randy and Kennedy, David and Schmitt, Franz and Brown, Gregory and MacFall, James and Fischl, Bruce and Dale, Anders}, + doi = {10.1016/j.neuroimage.2005.09.046}, + journal = {NeuroImage}, + number = {2}, + pages = {436-443}, + shorttitle = {Reliability in Multi-Site Structural {{MRI}} Studies}, + title = {Reliability in Multi-Site Structural {{MRI}} Studies: Effects of Gradient Non-Linearity Correction on Phantom and Human Data}, + volume = {30}, + year = {2006} +} + +@article{KappenmanLuck2010, + author = {Kappenman, Emily S. and Luck, Steven J.}, + doi = {10.1111/j.1469-8986.2010.01009.x}, + journal = {Psychophysiology}, + title = {The Effects of Electrode Impedance on Data Quality and Statistical Significance in {{ERP}} Recordings}, + year = {2010} +} + +@article{KempEtAl2000, + author = {Kemp, B. and Zwinderman, A. H. and Tuk, B. and Kamphuisen, H. A. C. and Oberyé, J. J. L.}, + doi = {10.1109/10.867928}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {9}, + pages = {1185-1194}, + shorttitle = {Analysis of a Sleep-Dependent Neuronal Feedback Loop}, + title = {Analysis of a Sleep-Dependent Neuronal Feedback Loop: The Slow-Wave Microcontinuity of the {{EEG}}}, + volume = {47}, + year = {2000} +} + +@article{KhanCohen2013, + author = {Khan, Sheraz and Cohen, David}, + doi = {10.1063/1.4802845}, + journal = {Review of Scientific Instruments}, + number = {5}, + pages = {056101}, + shorttitle = {Magnetic Noise from the Inner Wall of a Magnetically Shielded Room}, + title = {Note: Magnetic Noise from the Inner Wall of a Magnetically Shielded Room}, + volume = {84}, + year = {2013} +} + +@article{KhanEtAl2018, + author = {Khan, Sheraz and Hashmi, Javeria A. and Mamashli, Fahimeh and Michmizos, Konstantinos and Kitzbichler, Manfred G. and Bharadwaj, Hari and Bekhti, Yousra and Ganesan, Santosh and Garel, Keri-Lee A. and {Whitfield-Gabrieli}, Susan and Gollub, Randy L. and Kong, Jian and Vaina, Lucia M. and Rana, Kunjan D. and Stufflebeam, Steven M. and Hämäläinen, Matti S. and Kenet, Tal}, + doi = {10.1016/j.neuroimage.2018.02.018}, + journal = {NeuroImage}, + pages = {57-68}, + title = {Maturation Trajectories of Cortical Resting-State Networks Depend on the Mediating Frequency Band}, + volume = {174}, + year = {2018} +} + +@article{KingDehaene2014, + author = {King, Jean-Rémi and Dehaene, Stanislas}, + doi = {10.1016/j.tics.2014.01.002}, + journal = {Trends in Cognitive Sciences}, + number = {4}, + pages = {203-210}, + shorttitle = {Characterizing the Dynamics of Mental Representations}, + title = {Characterizing the Dynamics of Mental Representations: The Temporal Generalization Method}, + volume = {18}, + year = {2014} +} + +@article{KingEtAl2014, + author = {King, Jean-Rémi and Gramfort, Alexandre and Schurger, Aaron and Naccache, Lionel and Dehaene, Stanislas}, + doi = {10.1371/journal.pone.0085791}, + editor = {Kiebel, Stefan}, + journal = {PLoS ONE}, + number = {1}, + pages = {e85791}, + title = {Two Distinct Dynamic Modes Subtend the Detection of Unexpected Sounds}, + volume = {9}, + year = {2014} +} + +@unpublished{KingEtAl2018, + author = {King, Jean-Rémi and Gwilliams, Laura and Holdgraf, Chris and Sassenhagen, Jona and Barachant, Alexandre and Engemann, Denis and Larson, Eric and Gramfort, Alexandre}, + title = {Encoding and Decoding Neuronal Dynamics: Methodological Framework to Uncover the Algorithms of Cognition}, + url = {https://hal.archives-ouvertes.fr/hal-01848442}, + year = {2018}, + note = {hal-01848442} +} + +@article{KnuutilaEtAl1993, + author = {Knuutila, Jukka E. T. and Ahonen, Antti I. and Hämäläinen, Matti S. and Kajola, Matti J. and Laine, P. P. and Lounasmaa, Olli V. and Parkkonen, Lauri T. and Simola, Juha T. A. and Tesche, Claudia D.}, + doi = {10.1109/20.281163}, + journal = {IEEE Transactions on Magnetics}, + number = {6}, + pages = {3315-3320}, + title = {A 122-Channel Whole-Cortex {{SQUID}} System for Measuring the Brain's Magnetic Fields}, + volume = {29}, + year = {1993} +} + +@article{Koles1991, + author = {Koles, Zoltan J.}, + doi = {10.1016/0013-4694(91)90163-X}, + journal = {Electroencephalography and Clinical Neurophysiology}, + number = {6}, + pages = {440-447}, + title = {The Quantitative Extraction and Topographic Mapping of the Abnormal Components in the Clinical {{EEG}}}, + volume = {79}, + year = {1991} +} + +@article{KolesEtAl1990, + author = {Koles, Zoltan J. and Lazar, Michael S. and Zhou, Steven Z.}, + doi = {10.1007/BF01129656}, + journal = {Brain Topography}, + number = {4}, + pages = {275-284}, + title = {Spatial Patterns Underlying Population Differences in the Background {{EEG}}}, + volume = {2}, + year = {1990} +} + +@article{KriegeskorteEtAl2008, + author = {Kriegeskorte, Nikolaus and Mur, Marieke and Bandettini, Peter}, + doi = {10.3389/neuro.06.004.2008}, + journal = {Frontiers in Systems Neuroscience}, + pages = {4}, + pmcid = {PMC2605405}, + pmid = {19104670}, + title = {Representational Similarity Analysis – Connecting the Branches of Systems Neuroscience}, + volume = {2}, + year = {2008} +} + +@article{LaaksoCottrell2000, + author = {Laakso, Aarre and Cottrell, Garrison}, + doi = {10.1080/09515080050002726}, + journal = {Philosophical Psychology}, + number = {1}, + pages = {47-76}, + shorttitle = {Content and Cluster Analysis}, + title = {Content and Cluster Analysis: Assessing Representational Similarity in Neural Systems}, + volume = {13}, + year = {2000} +} + +@article{LachauxEtAl1999, + author = {Lachaux, Jean-Philippe and Rodriguez, Eugenio and Martinerie, Jacques and Varela, Francisco J.}, + doi = {10.1002/(SICI)1097-0193(1999)8:4<194::AID-HBM4>3.0.CO;2-C}, + journal = {Human Brain Mapping}, + number = {4}, + pages = {194-208}, + title = {Measuring Phase Synchrony in Brain Signals}, + volume = {8}, + year = {1999} +} + +@article{LarsonLee2013, + author = {Larson, Eric and Lee, Adrian K.C.}, + doi = {10.1016/j.neuroimage.2012.09.006}, + journal = {NeuroImage}, + pages = {365-370}, + title = {The Cortical Dynamics Underlying Effective Switching of Auditory Spatial Attention}, + volume = {64}, + year = {2013} +} + +@article{LarsonTaulu2017, + author = {Larson, Eric and Taulu, Samu}, + doi = {10.1007/s10548-016-0523-1}, + journal = {Brain Topography}, + number = {2}, + pages = {172-181}, + title = {The Importance of Properly Compensating for Head Movements during {{MEG}} Acquisition across Different Age Groups}, + volume = {30}, + year = {2017} +} + +@article{LarsonTaulu2018, + author = {Larson, Eric and Taulu, Samu}, + doi = {10.1109/TBME.2017.2734641}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {5}, + pages = {1002-1013}, + title = {Reducing Sensor Noise in {{MEG}} and {{EEG}} Recordings Using Oversampled Temporal Projection}, + volume = {65}, + year = {2018} +} + +@article{LedoitWolf2004, + author = {Ledoit, Olivier and Wolf, Michael}, + doi = {10.1016/S0047-259X(03)00096-4}, + journal = {Journal of Multivariate Analysis}, + number = {2}, + pages = {365-411}, + title = {A Well-Conditioned Estimator for Large-Dimensional Covariance Matrices}, + volume = {88}, + year = {2004} +} + +@article{LeeEtAl1999, + author = {Lee, Te-Won and Girolami, Mark and Sejnowski, Terrence J.}, + doi = {10.1162/089976699300016719}, + journal = {Neural Computation}, + number = {2}, + pages = {417-441}, + title = {Independent Component Analysis Using an Extended Infomax Algorithm for Mixed Subgaussian and Supergaussian Sources}, + volume = {11}, + year = {1999} +} + +@article{LewEtAl2009, + author = {Lew, Seok and Wolters, Carsten H. and Anwander, Alfred and Makeig, Scott and MacLeod, Rob S.}, + doi = {10.1002/hbm.20714}, + journal = {Human Brain Mapping}, + number = {9}, + pages = {2862-2878}, + title = {Improved {{EEG}} Source Analysis Using Low-Resolution Conductivity Estimation in a Four-Compartment Finite Element Head Model}, + volume = {30}, + year = {2009} +} + +@article{LinEtAl2004, + author = {Lin, Fa-Hsuan and Witzel, Thomas and Hämäläinen, Matti S. and Dale, Anders M. and Belliveau, John W. and Stufflebeam, Steven M.}, + doi = {10.1016/j.neuroimage.2004.04.027}, + journal = {NeuroImage}, + number = {2}, + pages = {582-595}, + title = {Spectral Spatiotemporal Imaging of Cortical Oscillations and Interactions in the Human Brain}, + volume = {23}, + year = {2004} +} + +@article{LinEtAl2006, + author = {Lin, Fa-Hsuan and Belliveau, John W. and Dale, Anders M. and Hämäläinen, Matti S.}, + doi = {10.1002/hbm.20155}, + journal = {Human Brain Mapping}, + number = {1}, + pages = {1-13}, + title = {Distributed Current Estimates Using Cortical Orientation Constraints}, + volume = {27}, + year = {2006} +} + +@article{LinEtAl2006a, + title = {Assessing and improving the spatial accuracy in {MEG} source localization by depth-weighted minimum-norm estimates}, + volume = {31}, + issn = {1053-8119}, + doi = {10.1016/j.neuroimage.2005.11.054}, + number = {1}, + journal = {NeuroImage}, + author = {Lin, Fa-Hsuan and Witzel, Thomas and Ahlfors, Seppo P. and Stufflebeam, Steven M. and Belliveau, John W. and Hämäläinen, Matti S.}, + year = {2006}, + pages = {160--171} +} + +@article{LiuEtAl1998, + author = {Liu, Arthur K. and Belliveau, John W. and Dale, Anders M.}, + doi = {10.1073/pnas.95.15.8945}, + journal = {Proceedings of the National Academy of Sciences}, + number = {15}, + pages = {8945-8950}, + shorttitle = {Spatiotemporal Imaging of Human Brain Activity Using Functional {{MRI}} Constrained Magnetoencephalography Data}, + title = {Spatiotemporal Imaging of Human Brain Activity Using Functional {{MRI}} Constrained Magnetoencephalography Data: {{Monte Carlo}} Simulations}, + volume = {95}, + year = {1998} +} + +@article{LiuEtAl2002, + author = {Liu, Arthur K. and Dale, Anders M. and Belliveau, John W.}, + doi = {10.1002/hbm.10024}, + journal = {Human Brain Mapping}, + number = {1}, + pages = {47-62}, + title = {Monte {{Carlo}} Simulation Studies of {{EEG}} and {{MEG}} Localization Accuracy}, + volume = {16}, + year = {2002} +} + +@misc{Lowry2014, + author = {Lowry, Richard}, + journal = {Concepts and applications of inferential statistics}, + title = {One-Way Analysis of Variance for Independent Samples}, + url = {http://vassarstats.net/textbook/}, + year = {2014} +} + +@article{LuckEtAl2021, + author = {Luck, Steven J. and Stewart, Andrew X. and Simmons, Aaron M. and Rhemtulla, Mijke}, + journal = {Psychophysiology}, + title = {Standardized Measurement Error: A Universal Metric of Data Quality for Averaged Event-Related Potentials}, + volume = {58}, + number = {6}, + pages = {e13793}, + year = {2021}, + doi = {10.1111/psyp.13793} +} + +@article{MaessEtAl2016, + author = {Maess, Burkhard and Schröger, Erich and Widmann, Andreas}, + doi = {10.1016/j.jneumeth.2015.12.003}, + journal = {Journal of Neuroscience Methods}, + pages = {164-165}, + shorttitle = {High-Pass Filters and Baseline Correction in {{M}}/{{EEG}} Analysis}, + title = {High-Pass Filters and Baseline Correction in {{M}}/{{EEG}} Analysis. {{Commentary}} on: “{{How}} Inappropriate High-Pass Filters Can Produce Artefacts and Incorrect Conclusions in {{ERP}} Studies of Language and Cognition”}, + volume = {266}, + year = {2016} +} + +@article{MaessEtAl2016a, + author = {Maess, Burkhard and Schröger, Erich and Widmann, Andreas}, + doi = {10.1016/j.jneumeth.2016.01.016}, + journal = {Journal of Neuroscience Methods}, + pages = {171-172}, + title = {High-Pass Filters and Baseline Correction in {{M}}/{{EEG}} Analysis-Continued Discussion}, + volume = {266}, + year = {2016} +} + +@article{Makeig1993, + author = {Makeig, Scott}, + doi = {10.1016/0013-4694(93)90110-H}, + journal = {Electroencephalography and Clinical Neurophysiology}, + number = {4}, + pages = {283-293}, + title = {Auditory Event-Related Dynamics of the {{EEG}} Spectrum and Effects of Exposure to Tones}, + volume = {86}, + year = {1993} +} + +@article{Makela2018, + author = {Mäkelä, Niko and Stenroos, Matti and Sarvas, Jukka and Ilmoniemi, Risto J.}, + doi = {10.1016/j.neuroimage.2017.11.013}, + journal = {Neuroimage}, + number = {}, + pages = {73-83}, + title = {Truncated RAP-MUSIC (TRAP-MUSIC) for MEG and EEG source localization}, + volume = {167}, + year = {2018} +} + +@article{MarisOostenveld2007, + author = {Maris, Eric and Oostenveld, Robert}, + doi = {10.1016/j.jneumeth.2007.03.024}, + journal = {Journal of Neuroscience Methods}, + number = {1}, + pages = {177-190}, + title = {Nonparametric Statistical Testing of {{EEG}}- and {{MEG}}-Data}, + volume = {164}, + year = {2007} +} + +@misc{Mills2016, + author = {Mills, Kathryn}, + doi = {10.6084/m9.figshare.3498446.v2}, + publisher = {{Figshare}}, + title = {{{HCP-MMP1.0}} Projected on {{fsaverage}}}, + year = {2016} +} + +@article{MolinsEtAl2008, + author = {Molins A, and Stufflebeam S. M., and Brown E. N., and Hämäläinen M. S.}, + doi = {10.1016/j.neuroimage.2008.05.064}, + journal = {Neuroimage}, + number = {3}, + pages = {1069-1077}, + title = {Quantification of the benefit from integrating {MEG} and {EEG} data in + minimum l2-norm estimation}, + volume = {42}, + year = {2008} +} + +@incollection{Montoya-MartinezEtAl2017, + address = {{Cham}}, + author = {{Montoya-Martínez}, Jair and Cardoso, Jean-François and Gramfort, Alexandre}, + booktitle = {Latent Variable Analysis and Signal Separation}, + doi = {10.1007/978-3-319-53547-0_27}, + editor = {Tichavský, Petr and {Babaie-Zadeh}, Massoud and Michel, Olivier J.J. and {Thirion-Moreau}, Nadège}, + isbn = {978-3-319-53546-3 978-3-319-53547-0}, + number = {10169}, + pages = {279-289}, + publisher = {{Springer International Publishing}}, + series = {Lecture {{Notes}} in {{Computer Science}}}, + title = {Caveats with Stochastic Gradient and Maximum Likelihood Based {{ICA}} for {{EEG}}}, + year = {2017} +} + +@article{MosherEtAl1999, + author = {Mosher, John C. and Leahy, Richard M. and Lewis, Paul S.}, + doi = {10.1109/10.748978}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {3}, + pages = {245-259}, + shorttitle = {{{EEG}} and {{MEG}}}, + title = {{{EEG}} and {{MEG}}: Forward Solutions for Inverse Methods}, + volume = {46}, + year = {1999} +} + +@article{MosherLeahy1999, + author = {Mosher, John C. and Leahy, Richard M.}, + doi = {10.1109/78.740118}, + journal = {IEEE Transactions on Signal Processing}, + number = {2}, + pages = {332-340}, + title = {Source Localization Using Recursively Applied and Projected ({{RAP}}) {{MUSIC}}}, + volume = {47}, + year = {1999} +} + +@inproceedings{MosherLeahy1996, + title = {{EEG} and {MEG} source localization using recursively applied ({RAP}) {MUSIC}}, + doi = {10.1109/ACSSC.1996.599135}, + booktitle = {Conference {Record} of {The} {Thirtieth} {Asilomar} {Conference} on {Signals}, {Systems} and {Computers}}, + author = {Mosher, J.C. and Leahy, R.M.}, + month = nov, + year = {1996}, + note = {ISSN: 1058-6393}, + pages = {1201--1207 vol.2} +} + +@inproceedings{MoukademEtAl2014, + address = {{Lisbon}}, + author = {Moukadem, Ali and Bouguila, Zied and Abdeslam, Djaffar Ould and Dieterlen, Alain}, + booktitle = {Proceedings of {{EUSIPCO}}-2014}, + pages = {2015-2019}, + publisher = {{IEEE}}, + title = {Stockwell Transform Optimization Applied on the Detection of Split in Heart Sounds}, + url = {https://ieeexplore.ieee.org/document/6952743}, + year = {2014} +} + +@article{MourtazaevEtAl1995, + author = {Mourtazaev, M. S. and Kemp, B. and Zwinderman, A. H. and Kamphuisen, H. A. C.}, + doi = {10.1093/sleep/18.7.557}, + journal = {Sleep}, + number = {7}, + pages = {557-564}, + title = {Age and Gender Affect Different Characteristics of Slow Waves in the Sleep {{EEG}}}, + volume = {18}, + year = {1995} +} + +@article{Muthukumaraswamy2013, + author = {Muthukumaraswamy, Suresh}, + doi = {10.3389/fnhum.2013.00138}, + journal = {Frontiers in Human Neuroscience}, + pages = {138}, + title = {High-frequency brain activity and muscle artifacts in {{MEG}}/{{EEG}}: A review and recommendations}, + volume = {7}, + year = {2013} +} + +@inproceedings{NdiayeEtAl2016, + author = {Ndiaye, Eugene and Fercoq, Olivier and Gramfort, Alexandre and Salmon, Joseph}, + booktitle = {Advances in Neural Information Processing Systems 29}, + editor = {Lee, D. D. and Sugiyama, M. and Luxburg, U. V. and Guyon, I. and Garnett, R.}, + pages = {388-396}, + publisher = {{Curran Associates, Inc.}}, + title = {{{GAP}} Safe Screening Rules for Sparse-Group Lasso}, + url = {http://papers.nips.cc/paper/6405-gap-safe-screening-rules-for-sparse-group-lasso.pdf}, + year = {2016} +} + +@article{NiazyEtAl2005, + author = {Niazy, R. K. and Beckmann, C.F. and Iannetti, G.D. and Brady, J. M. and Smith, S. M.}, + title = {Removal of FMRI environment artifacts from EEG data using optimal basis sets}, + journal = {NeuroImage}, + year = {2005}, + volume = {28}, + pages = {720-737}, + doi = {10.1016/j.neuroimage.2005.06.067.} +} + +@article{NicholsHolmes2002, + author = {Nichols, Thomas E. and Holmes, Andrew P.}, + doi = {10.1002/hbm.1058}, + journal = {Human Brain Mapping}, + number = {1}, + pages = {1-25}, + shorttitle = {Nonparametric Permutation Tests for Functional Neuroimaging}, + title = {Nonparametric Permutation Tests for Functional Neuroimaging: A Primer with Examples}, + volume = {15}, + year = {2002} +} + +@article{NikulinEtAl2011, + author = {Nikulin, Vadim V and Nolte, Guido and Curio, Gabriel}, + doi = {10.1016/j.neuroimage.2011.01.057}, + journal={NeuroImage}, + title = {A novel method for reliable and fast extraction of neuronal {EEG/MEG} oscillations on the basis of spatio-spectral decomposition}, + pages={1528-1535}, + volume={55}, + number={4}, + year={2011} +} + +@article{NolteEtAl2004, + author = {Nolte, Guido and Bai, Ou and Wheaton, Lewis and Mari, Zoltan and Vorbach, Sherry and Hallett, Mark}, + doi = {10.1016/j.clinph.2004.04.029}, + journal = {Clinical Neurophysiology}, + number = {10}, + pages = {2292-2307}, + title = {Identifying True Brain Interaction from {{EEG}} Data Using the Imaginary Part of Coherency}, + volume = {115}, + year = {2004} +} + +@article{NolteEtAl2008, + author = {Nolte, Guido and Ziehe, Andreas and Nikulin, Vadim V. and Schlögl, Alois and Krämer, Nicole and Brismar, Tom and Müller, Klaus-Robert}, + doi = {10.1103/PhysRevLett.100.234101}, + journal = {Physical Review Letters}, + number = {23}, + title = {Robustly Estimating the Flow Direction of Information in Complex Physical Systems}, + volume = {100}, + year = {2008} +} + +@misc{NurminenEtAl2017, + author = {Nurminen, Jussi and Paananen, Hilla and Mäkelä, Jyrki}, + doi = {10.5281/zenodo.889234}, + publisher = {{Zenodo}}, + shorttitle = {High Frequency Somatosensory {{MEG}}}, + title = {High Frequency Somatosensory {{MEG}}: Evoked Responses, Freesurfer Reconstruction}, + year = {2017} +} + +@article{OostendorpEtAl2000, + author = {Oostendorp, Thom F. and Delbeke, Jean and Stegeman, Dick F.}, + doi = {10.1109/TBME.2000.880100}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {11}, + pages = {1487-1492}, + shorttitle = {The Conductivity of the Human Skull}, + title = {The Conductivity of the Human Skull: Results of in Vivo and in Vitro Measurements}, + volume = {47}, + year = {2000} +} + +@book{ParksBurrus1987, + address = {{New York}}, + author = {Parks, Thomas W. and Burrus, C. Sidney S.}, + isbn = {978-0-471-82896-9}, + publisher = {{Wiley}}, + series = {Topics in Digital Signal Processing}, + title = {Digital Filter Design}, + year = {1987} +} + +@article{Pascual-Marqui2002, + author = {{Pascual-Marqui}, Roberto D.}, + journal = {Methods and Findings in Experimental and Clinical Pharmacology}, + number = {D}, + pages = {5-12}, + pmid = {12575463}, + shorttitle = {Standardized Low-Resolution Brain Electromagnetic Tomography ({{sLORETA}})}, + title = {Standardized Low-Resolution Brain Electromagnetic Tomography ({{sLORETA}}): Technical Details}, + volume = {24}, + year = {2002}, + url = {https://pubmed.ncbi.nlm.nih.gov/12575463/} +} + +@article{Pascual-Marqui2011, + title = {Assessing interactions in the brain with exact low-resolution electromagnetic tomography}, + volume = {369}, + doi = {10.1098/rsta.2011.0081}, + number = {1952}, + journal = {Philosophical Transactions of the Royal Society A: Mathematical, Physical and Engineering Sciences}, + author = {Pascual-Marqui, Roberto D. and Lehmann, Dietrich and Koukkou, Martha and Kochi, Kieko and Anderer, Peter and Saletu, Bernd and Tanaka, Hideaki and Hirata, Koichi and John, E. Roy and Prichep, Leslie and Biscay-Lirio, Rolando and Kinoshita, Toshihiko}, + year = {2011}, + pages = {3768--3784} +} + +@book{PercivalWalden1993, + address = {{Cambridge; New York}}, + author = {Percival, Donald B. and Walden, Andrew T.}, + isbn = {978-0-521-35532-2}, + publisher = {{Cambridge University Press}}, + shorttitle = {Spectral Analysis for Physical Applications}, + title = {Spectral Analysis for Physical Applications: Multitaper and Conventional Univariate Techniques}, + doi = {10.1017/CBO9780511622762}, + year = {1993} +} + +@article{PerrinEtAl1987, + title = {Scalp {Current} {Density} {Mapping}: {Value} and {Estimation} from {Potential} {Data}}, + volume = {BME-34}, + issn = {1558-2531}, + shorttitle = {Scalp {Current} {Density} {Mapping}}, + doi = {10.1109/TBME.1987.326089}, + number = {4}, + journal = {IEEE Transactions on Biomedical Engineering}, + author = {Perrin, F. and Bertrand, O. and Pernier, J.}, + year = {1987}, + pages = {283--288} +} + +@article{PerrinEtAl1989, + author = {Perrin, François M. and Pernier, Jacques and Bertrand, Olivier M. and Echallier, Jean Franćois}, + doi = {10.1016/0013-4694(89)90180-6}, + journal = {Electroencephalography and Clinical Neurophysiology}, + number = {2}, + pages = {184-187}, + title = {Spherical Splines for Scalp Potential and Current Density Mapping}, + volume = {72}, + year = {1989} +} + +@article{PfurtschellerLopesdaSilva1999, + author = {Pfurtscheller, Gert and {Lopes da Silva}, Fernando H.}, + doi = {10.1016/S1388-2457(99)00141-8}, + journal = {Clinical Neurophysiology}, + number = {11}, + pages = {1842-1857}, + shorttitle = {Event-Related {{EEG}}/{{MEG}} Synchronization and Desynchronization}, + title = {Event-Related {{EEG}}/{{MEG}} Synchronization and Desynchronization: Basic Principles}, + volume = {110}, + year = {1999} +} + +@article{Pham2001, + author = {Pham, Dinh Tuan}, + doi = {10.1137/S089547980035689X}, + journal = {SIAM Journal on Matrix Analysis and Applications}, + number = {4}, + pages = {1136-1152}, + title = {Joint Approximate Diagonalization of Positive Definite Hermitian Matrices}, + volume = {22}, + year = {2001} +} + +@article{pollonini2014auditory, + title={Auditory cortex activation to natural speech and simulated cochlear implant speech measured with functional near-infrared spectroscopy}, + author={Pollonini, Luca and Olds, Cristen and Abaya, Homer and Bortfeld, Heather and Beauchamp, Michael S and Oghalai, John S}, + journal={Hearing Research}, + volume={309}, + pages={84--93}, + year={2014}, + publisher={Elsevier}, + pmid={24342740}, + doi={10.1016/j.heares.2013.11.007} +} + +@article{RidgwayEtAl2012, + author = {Ridgway, Gerard R. and Litvak, Vladimir and Flandin, Guillaume and Friston, Karl J. and Penny, Will D.}, + doi = {10.1016/j.neuroimage.2011.10.027}, + journal = {NeuroImage}, + number = {3}, + pages = {2131-2141}, + title = {The Problem of Low Variance Voxels in Statistical Parametric Mapping; a New Hat Avoids a ‘Haircut’}, + volume = {59}, + year = {2012} +} + +@article{RivetEtAl2009, + author = {Rivet, Bertrand and Souloumiac, Antoine and Attina, Virginie and Gibert, Guillaume}, + doi = {10.1109/TBME.2009.2012869}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {8}, + pages = {2035-2043}, + shorttitle = {{{xDAWN}} Algorithm to Enhance Evoked Potentials}, + title = {{{xDAWN}} Algorithm to Enhance Evoked Potentials: Application to Brain–Computer Interface}, + volume = {56}, + year = {2009} +} + +@inproceedings{RivetEtAl2011, + address = {{Barcelona}}, + author = {Rivet, Bertrand and Cecotti, Hubert and Souloumiac, Antoine and Maby, Emmanuel and Mattout, Jérémie}, + booktitle = {Proceedings of {{EUSIPCO}}-2011}, + pages = {1382-1386}, + publisher = {{IEEE}}, + title = {Theoretical Analysis of {{xDAWN}} Algorithm: Application to an Efficient Sensor Selection in a {{P300}} {{BCI}}}, + url = {https://ieeexplore.ieee.org/document/7073970}, + year = {2011} +} + +@article{RockhillEtAl2022, + doi = {10.21105/joss.03897}, + year = {2022}, + publisher = {The Open Journal}, + volume = {7}, + number = {70}, + pages = {3897}, + author = {Alexander P. Rockhill and Eric Larson and Brittany Stedelin and Alessandra Mantovani and Ahmed M. Raslan and Alexandre Gramfort and Nicole C. Swann}, + title = {Intracranial Electrode Location and Analysis in MNE-Python}, + journal = {Journal of Open Source Software} +} + +@article{Rousselet2012, + author = {Rousselet, Guillaume A.}, + doi = {10.3389/fpsyg.2012.00131}, + journal = {Frontiers in Psychology}, + title = {Does Filtering Preclude Us from Studying {{ERP}} Time-Courses?}, + volume = {3}, + year = {2012} +} + +@misc{Rousselet2016, + author = {Rousselet, Guillaume A.}, + doi = {10.7488/ds/1556}, + publisher = {{University of Edinburgh, Centre for Clinical Brain Sciences}}, + title = {{{LIMO EEG}} Dataset}, + year = {2016} +} + +@article{RousseletEtAl2010, + author = {Rousselet, Guillaume A. and Gaspar, Carl M. and Pernet, Cyril R. and Husk, Jesse S. and Bennett, Patrick J. and Sekuler, Allison B.}, + doi = {10.3389/fpsyg.2010.00019}, + journal = {Frontiers in Psychology}, + number = {19}, + pages = {1-14}, + title = {Healthy Aging Delays Scalp {{EEG}} Sensitivity to Noise in a Face Discrimination Task}, + volume = {1}, + year = {2010} +} + +@article{RousseletEtAl2008, + title = {Parametric Study of {{EEG}} Sensitivity to Phase Noise during Face Processing}, + author = {Rousselet, Guillaume A. and Pernet, Cyril R. and Bennett, Patrick J. and Sekuler, Allison B.}, + year = {2008}, + volume = {9}, + pages = {98}, + doi = {10.1186/1471-2202-9-98}, + journal = {BMC Neuroscience}, + number = {1} +} + +@article{Sabbagh2020, + author = {Sabbagh, David and Ablin, Pierre and Varoquaux, Gaël and Gramfort, Alexandre and Engemann, Denis A.}, + title = {Predictive regression modeling with MEG/EEG: from source power to signals and cognitive states}, + journal = {NeuroImage}, + year = {2020}, + doi = {10.1016/j.neuroimage.2020.116893} +} + +@article{Samuelsson2019, + author = {Samuelsson, John and Khan, Sheraz and Sundaram, Padma and Peled, Noam and Hämäläinen, Matti}, + title = {Cortical Signal Suppression (CSS) for detection of subcortical activity using MEG and EEG}, + journal = {Brain Topography}, + year = {2019}, + volume = {32}, + pages = {215-228}, + doi = {10.1007/s10548-018-00694-5} +} + +@article{Sarvas1987, + author = {Sarvas, Jukka}, + doi = {10.1088/0031-9155/32/1/004}, + journal = {Physics in Medicine and Biology}, + number = {1}, + pages = {11-22}, + publisher = {{IOP Publishing}}, + title = {Basic Mathematical and Electromagnetic Concepts of the Biomagnetic Inverse Problem}, + volume = {32}, + year = {1987} +} + +@article{Sassenhagen2019, +author = {Sassenhagen, Jona and Draschkow, Dejan}, +doi = {10.1111/psyp.13335}, +journal = {Psychophysiology}, +volume = {56}, +number = {6}, +pages = {e13335}, +keywords = {cluster-based permutation test, EEG, MEG, statistics}, +title = {Cluster-based permutation tests of MEG/EEG data do not establish significance of effect latency or location}, +year = {2019} +} + +@article{SavitzkyGolay1964, + author = {Savitzky, Abraham and Golay, Marcel J. E.}, + doi = {10.1021/ac60214a047}, + journal = {Analytical Chemistry}, + number = {8}, + pages = {1627-1639}, + title = {Smoothing and Differentiation of Data by Simplified Least Squares Procedures}, + volume = {36}, + year = {1964} +} + +@article{SchalkEtAl2004, + author = {Schalk, Gerwin and McFarland, Dennis J. and Hinterberger, Thilo and Birbaumer, Niels and Wolpaw, Jonathan R.}, + doi = {10.1109/TBME.2004.827072}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {6}, + pages = {1034-1043}, + shorttitle = {{{BCI2000}}}, + title = {{{BCI2000}}: A General-Purpose Brain-Computer Interface ({{BCI}}) System}, + volume = {51}, + year = {2004} +} + +@article{SchurgerEtAl2013, + author = {Schurger, Aaron and Marti, Sebastien and Dehaene, Stanislas}, + doi = {10.1186/1471-2202-14-122}, + journal = {BMC Neuroscience}, + number = {1}, + title = {Reducing Multi-Sensor Data to a Single Time Course That Reveals Experimental Effects}, + volume = {14}, + year = {2013} +} + +@article{SegonneEtAl2004, + author = {Ségonne, Florent and Dale, Anders M. and Busa, Evelina and Glessner, Maureen and Salat, David and Hahn, Horst Karl and Fischl, Bruce R.}, + doi = {10.1016/j.neuroimage.2004.03.032}, + journal = {NeuroImage}, + number = {3}, + pages = {1060-1075}, + title = {A Hybrid Approach to the Skull Stripping Problem in {{MRI}}}, + volume = {22}, + year = {2004} +} + +@book{SekiharaNagarajan2008, + address = {{Berlin; Heidelberg}}, + author = {Sekihara, Kensuke and Nagarajan, Srikantan S.}, + doi = {10.1007/978-3-540-79370-0}, + editor = {Nagel, Joachim H.}, + isbn = {978-3-540-79369-4 978-3-540-79370-0}, + publisher = {Springer}, + series = {Series in {{Biomedical Engineering}}}, + title = {Adaptive Spatial Filters for Electromagnetic Brain Imaging}, + year = {2008} +} + +@article{Shepard1980, + author = {Shepard, Roger N.}, + doi = {10.1126/science.210.4468.390}, + journal = {Science}, + number = {4468}, + pages = {390-398}, + title = {Multidimensional Scaling, Tree-Fitting, and Clustering}, + volume = {210}, + year = {1980} +} + +@article{Slepian1978, + author = {Slepian, David S.}, + doi = {10.1002/j.1538-7305.1978.tb02104.x}, + journal = {Bell System Technical Journal}, + number = {5}, + pages = {1371-1430}, + shorttitle = {Prolate Spheroidal Wave Functions, Fourier Analysis, and Uncertainty-{{V}}}, + title = {Prolate Spheroidal Wave Functions, Fourier Analysis, and Uncertainty-{{V}}: The Discrete Case}, + volume = {57}, + year = {1978} +} + +@article{SmithKutas2015, + author = {Smith, Nathaniel J. and Kutas, Marta}, + doi = {10.1111/psyp.12320}, + journal = {Psychophysiology}, + number = {2}, + pages = {169-181}, + shorttitle = {Regression-Based Estimation of {{ERP}} Waveforms}, + title = {Regression-Based Estimation of {{ERP}} Waveforms: {{II}}. {{Nonlinear}} Effects, Overlap Correction, and Practical Considerations: {{rERPS II}}}, + volume = {52}, + year = {2015} +} + +@article{SmithNichols2009, + author = {Smith, Stephen M. and Nichols, Thomas E.}, + doi = {10.1016/j.neuroimage.2008.03.061}, + journal = {NeuroImage}, + number = {1}, + pages = {83-98}, + shorttitle = {Threshold-Free Cluster Enhancement}, + title = {Threshold-Free Cluster Enhancement: Addressing Problems of Smoothing, Threshold Dependence and Localisation in Cluster Inference}, + volume = {44}, + year = {2009} +} + +@article{StamEtAl2007, + author = {Stam, Cornelis J. and Nolte, Guido and Daffertshofer, Andreas}, + doi = {10.1002/hbm.20346}, + journal = {Human Brain Mapping}, + number = {11}, + pages = {1178-1193}, + shorttitle = {Phase Lag Index}, + title = {Phase Lag Index: Assessment of Functional Connectivity from Multi Channel {{EEG}} and {{MEG}} with Diminished Bias from Common Sources}, + volume = {28}, + year = {2007} +} + +@incollection{Stockwell2007, + address = {{Providence, RI}}, + author = {Stockwell, R. G.}, + booktitle = {Pseudo-{{Differential Operators}}: {{Partial Differential Equations}} and {{Time}}-{{Frequency Analysis}}}, + doi = {10.1090/fic/052}, + editor = {Rodino, Luigi and Schulze, Bert-Wolfgang and Wong, M. W.}, + isbn = {978-0-8218-4276-8 978-1-4704-3086-3}, + number = {52}, + pages = {279-309}, + publisher = {{American Mathematical Society}}, + series = {Fields {{Institute Communications}}}, + title = {Why Use the {{S}}-Transform?}, + year = {2007} +} + +@inproceedings{StrohmeierEtAl2014, + address = {{Tübingen}}, + author = {Strohmeier, Daniel and Haueisen, Jens and Gramfort, Alexandre}, + booktitle = {Proceedings of {{PRNI}}-2014}, + doi = {10.1109/PRNI.2014.6858545}, + isbn = {978-1-4799-4149-0 978-1-4799-4150-6}, + pages = {1-4}, + publisher = {{IEEE}}, + title = {Improved {{MEG}}/{{EEG}} Source Localization with Reweighted Mixed-Norms}, + year = {2014} +} + +@article{StrohmeierEtAl2016, + author = {Strohmeier, Daniel and Bekhti, Yousra and Haueisen, Jens and Gramfort, Alexandre}, + doi = {10.1109/TMI.2016.2553445}, + journal = {IEEE Transactions on Medical Imaging}, + number = {10}, + pages = {2218-2228}, + title = {The Iterative Reweighted Mixed-Norm Estimate for Spatio-Temporal {{MEG}}/{{EEG}} Source Reconstruction}, + volume = {35}, + year = {2016} +} + +@article{TadelEtAl2011, + author = {Tadel, François and Baillet, Sylvain and Mosher, John C. and Pantazis, Dimitrios and Leahy, Richard M.}, + doi = {10.1155/2011/879716}, + journal = {Computational Intelligence and Neuroscience}, + pages = {1-13}, + shorttitle = {Brainstorm}, + title = {Brainstorm: A User-Friendly Application for {{MEG}}/{{EEG}} Analysis}, + volume = {2011}, + year = {2011} +} + +@article{Tallon-BaudryEtAl1997, + author = {Tallon-Baudry, Catherine and Bertrand, Olivier and Delpuech, Claude and Pernier, Jacques}, + doi = {10.1523/JNEUROSCI.17-02-00722.1997}, + journal = {Journal of Neuroscience}, + pages = {722-734}, + title = {Oscillatory {Gamma}-{Band} (30–70 {Hz}) {Activity} {Induced} by a {Visual} {Search} {Task} in {Humans}}, + year = {1997}, +} + +@article{TannerEtAl2015, + author = {Tanner, Darren and {Morgan-Short}, Kara and Luck, Steven J.}, + doi = {10.1111/psyp.12437}, + journal = {Psychophysiology}, + number = {8}, + pages = {997-1009}, + shorttitle = {How Inappropriate High-Pass Filters Can Produce Artifactual Effects and Incorrect Conclusions in {{ERP}} Studies of Language and Cognition}, + title = {How Inappropriate High-Pass Filters Can Produce Artifactual Effects and Incorrect Conclusions in {{ERP}} Studies of Language and Cognition: High-Pass Filtering and Artifactual {{ERP}} Effects}, + volume = {52}, + year = {2015} +} + +@article{TannerEtAl2016, + author = {Tanner, Darren and Norton, James J.S. and {Morgan-Short}, Kara and Luck, Steven J.}, + doi = {10.1016/j.jneumeth.2016.01.002}, + journal = {Journal of Neuroscience Methods}, + pages = {166-170}, + title = {On High-Pass Filter Artifacts (They’re Real) and Baseline Correction (It's a Good Idea) in {{ERP}}/{{ERMF}} Analysis}, + volume = {266}, + year = {2016} +} + +@article{TauluEtAl2005, + author = {Taulu, Samu and Simola, Juha and Kajola, Matti J.}, + doi = {10.1109/TSP.2005.853302}, + journal = {IEEE Transactions on Signal Processing}, + number = {9}, + pages = {3359-3372}, + title = {Applications of the Signal Space Separation Method}, + volume = {53}, + year = {2005} +} + +@article{TauluKajola2005, + author = {Taulu, Samu and Kajola, Matti}, + doi = {10.1063/1.1935742}, + journal = {Journal of Applied Physics}, + number = {12}, + pages = {124905}, + shorttitle = {Presentation of Electromagnetic Multichannel Data}, + title = {Presentation of Electromagnetic Multichannel Data: The Signal Space Separation Method}, + volume = {97}, + year = {2005} +} + +@article{TauluSimola2006, + author = {Taulu, Samu and Simola, Juha}, + doi = {10.1088/0031-9155/51/7/008}, + journal = {Physics in Medicine and Biology}, + number = {7}, + pages = {1759-1768}, + title = {Spatiotemporal Signal Space Separation Method for Rejecting Nearby Interference in {{MEG}} Measurements}, + volume = {51}, + year = {2006} +} + +@article{TenkeKayser2001, + title = {A convenient method for detecting electrolyte bridges in multichannel electroencephalogram and event-related potential recordings}, + volume = {112}, + issn = {1388-2457}, + doi = {10.1016/s1388-2457(00)00553-8}, + language = {eng}, + number = {3}, + journal = {Clinical Neurophysiology: Official Journal of the International Federation of Clinical Neurophysiology}, + author = {Tenke, C. E. and Kayser, J.}, + month = mar, + year = {2001}, + pmid = {11222978}, + keywords = {Algorithms, Artifacts, Brain, Electrodes, Electroencephalography, Electrolytes, Evoked Potentials, Humans, Scalp}, + pages = {545--550} +} + +@article{TescheEtAl1995, + author = {Tesche, Claudia D. and Uusitalo, Mikko A. and Ilmoniemi, Risto J. and Huotilainen, Minna and Kajola, Matti J. and Salonen, Oili L. M.}, + doi = {10.1016/0013-4694(95)00064-6}, + journal = {Electroencephalography and Clinical Neurophysiology}, + number = {3}, + pages = {189-200}, + title = {Signal-Space Projections of {{MEG}} Data Characterize Both Distributed and Well-Localized Neuronal Sources}, + volume = {95}, + year = {1995} +} + +@article{TheunissenEtAl2001, + author = {Theunissen, Frédéric E. and David, Stephen V. and Singh, Nandini C. and Hsu, Ann and Vinje, William E. and Gallant, Jack L.}, + doi = {10.1080/net.12.3.289.316}, + journal = {Network: Computation in Neural Systems}, + number = {3}, + pages = {289-316}, + title = {Estimating Spatio-Temporal Receptive Fields of Auditory and Visual Neurons from Their Responses to Natural Stimuli}, + volume = {12}, + year = {2001} +} + +@article{TippingBishop1999, + author = {Tipping, Michael E. and Bishop, Christopher M.}, + doi = {10.1111/1467-9868.00196}, + journal = {Journal of the Royal Statistical Society: Series B (Statistical Methodology)}, + number = {3}, + pages = {611-622}, + title = {Probabilistic Principal Component Analysis}, + volume = {61}, + year = {1999} +} + +@article{UusitaloIlmoniemi1997, + author = {Uusitalo, Mikko A. and Ilmoniemi, Risto J.}, + doi = {10.1007/BF02534144}, + journal = {Medical \& Biological Engineering \& Computing}, + number = {2}, + pages = {135-140}, + title = {Signal-Space Projection Method for Separating {{MEG}} or {{EEG}} into Components}, + volume = {35}, + year = {1997} +} + +@article{VanRullen2011, + author = {VanRullen, Rufin}, + doi = {10.3389/fpsyg.2011.00365}, + journal = {Frontiers in Psychology}, + title = {Four Common Conceptual Fallacies in Mapping the Time Course of Recognition}, + volume = {2}, + year = {2011} +} + +@article{VanVeenEtAl1997, + author = {Van Veen, Barry D. and {van Drongelen}, Wim and Yuchtman, Moshe and Suzuki, Akifumi}, + doi = {10.1109/10.623056}, + journal = {IEEE Transactions on Biomedical Engineering}, + number = {9}, + pages = {867-880}, + title = {Localization of Brain Electrical Activity via Linearly Constrained Minimum Variance Spatial Filtering}, + volume = {44}, + year = {1997} +} + +@article{vanVlietEtAl2018, + author = {{van Vliet}, Marijn and Liljeström, Mia and Aro, Susanna and Salmelin, Riitta and Kujala, Jan}, + doi = {10.1101/245530}, + journal = {bioRxiv}, + shorttitle = {Analysis of Functional Connectivity and Oscillatory Power Using {{DICS}}}, + title = {Analysis of Functional Connectivity and Oscillatory Power Using {{DICS}}: From Raw {{MEG}} Data to Group-Level Statistics in {{Python}}}, + year = {2018} +} + +@article{VinckEtAl2010, + author = {Vinck, Martin and {van Wingerden}, Marijn and Womelsdorf, Thilo and Fries, Pascal and Pennartz, Cyriel M.A.}, + doi = {10.1016/j.neuroimage.2010.01.073}, + journal = {NeuroImage}, + number = {1}, + pages = {112-122}, + shorttitle = {The Pairwise Phase Consistency}, + title = {The Pairwise Phase Consistency: A Bias-Free Measure of Rhythmic Neuronal Synchronization}, + volume = {51}, + year = {2010} +} + +@article{VinckEtAl2011, + author = {Vinck, Martin and Oostenveld, Robert and {van Wingerden}, Marijn and Battaglia, Franscesco and Pennartz, Cyriel M.A.}, + doi = {10.1016/j.neuroimage.2011.01.055}, + journal = {NeuroImage}, + number = {4}, + pages = {1548-1565}, + title = {An Improved Index of Phase-Synchronization for Electrophysiological Data in the Presence of Volume-Conduction, Noise and Sample-Size Bias}, + volume = {55}, + year = {2011} +} + +@article{WehnerEtAl2008, + author = {Wehner, Daniel T. and Hämäläinen, Matti S. and Mody, Maria and Ahlfors, Seppo P.}, + doi = {10.1016/j.neuroimage.2007.12.026}, + journal = {NeuroImage}, + number = {2}, + pages = {541-550}, + shorttitle = {Head Movements of Children in {{MEG}}}, + title = {Head Movements of Children in {{MEG}}: Quantification, Effects on Source Estimation, and Compensation}, + volume = {40}, + year = {2008} +} + +@article{WestnerEtAl2022, + author = {Westner, Britta U. and Dalal, Sarang S. and Gramfort, Alexandre and Litvak, Vladimir and Mosher, John C. and Oostenveld, Robert and Schoffelen, Jan-Mathijs}, + doi = {10.1016/j.neuroimage.2021.118789}, + journal = {NeuroImage}, + pages = {118789}, + title = {A unified view on beamformers for {M}/{EEG} source reconstruction}, + volume = {246}, + year = {2022}, +} + +@article{WheatEtAl2010, + author = {Wheat, Katherine L. and Cornelissen, Piers L. and Frost, Stephen J. and Hansen, Peter C.}, + doi = {10.1523/JNEUROSCI.4448-09.2010}, + journal = {Journal of Neuroscience}, + number = {15}, + pages = {5229-5233}, + shorttitle = {During Visual Word Recognition, Phonology Is Accessed within {{100 ms}} and May Be Mediated by a Speech Production Code}, + title = {During Visual Word Recognition, Phonology Is Accessed within {{100 ms}} and May Be Mediated by a Speech Production Code: Evidence from Magnetoencephalography}, + volume = {30}, + year = {2010} +} + +@article{WhithamEtAl2007, + title = {Scalp electrical recording during paralysis: quantitative evidence that {EEG} frequencies above 20 {Hz} are contaminated by {EMG}}, + volume = {118}, + issn = {1388-2457}, + doi = {10.1016/j.clinph.2007.04.027}, + number = {8}, + journal = {Clinical Neurophysiology: Official Journal of the International Federation of Clinical Neurophysiology}, + author = {Whitham, Emma M. and Pope, Kenneth J. and Fitzgibbon, Sean P. and Lewis, Trent and Clark, C. Richard and Loveless, Stephen and Broberg, Marita and Wallace, Angus and DeLosAngeles, Dylan and Lillie, Peter and Hardy, Andrew and Fronsko, Rik and Pulbrook, Alyson and Willoughby, John O.}, + year = {2007}, + pmid = {17574912}, + pages = {1877--1888}, +} + +@article{WidmannEtAl2015, + author = {Widmann, Andreas and Schröger, Erich and Maess, Burkhard}, + doi = {10.1016/j.jneumeth.2014.08.002}, + journal = {Journal of Neuroscience Methods}, + pages = {34-46}, + title = {Digital Filter Design for Electrophysiological Data – a Practical Approach}, + volume = {250}, + year = {2015} +} + +@article{WidmannSchroger2012, + author = {Widmann, Andreas and Schröger, Erich}, + doi = {10.3389/fpsyg.2012.00233}, + journal = {Frontiers in Psychology}, + title = {Filter Effects and Filter Artifacts in the Analysis of Electrophysiological Data}, + volume = {3}, + year = {2012} +} + +@article{WillmoreSmyth2003, + author = {Willmore, Ben and Smyth, Darragh}, + doi = {10.1088/0954-898X_14_3_309}, + journal = {Network: Computation in Neural Systems}, + number = {3}, + pages = {553-577}, + shorttitle = {Methods for First-Order Kernel Estimation}, + title = {Methods for First-Order Kernel Estimation: Simple-Cell Receptive Fields from Responses to Natural Scenes}, + volume = {14}, + year = {2003} +} + +@inproceedings{WinklerEtAl2015, + address = {{Milan}}, + author = {Winkler, Irene and Debener, Stefan and Müller, Klaus-Robert and Tangermann, Michael}, + booktitle = {Proceedings of {{EMBC}}-2015}, + doi = {10.1109/EMBC.2015.7319296}, + isbn = {978-1-4244-9271-8}, + pages = {4101-4105}, + publisher = {{IEEE}}, + title = {On the Influence of High-Pass Filtering on {{ICA}}-Based Artifact Reduction in {{EEG}}-{{ERP}}}, + year = {2015} +} + +@inproceedings{WipfEtAl2007, + author = {Wipf, David P. and Ramírez, Rey and Palmer, Jason and Makeig, Scott and Rao, Bhaskar D.}, + booktitle = {Advances in Neural Information Processing Systems 19}, + editor = {Schölkopf, Bernhard and Platt, John C. and Hoffman, T.}, + pages = {1505-1512}, + publisher = {{MIT Press}}, + title = {Analysis of Empirical Bayesian Methods for Neuroelectromagnetic Source Localization}, + url = {http://papers.nips.cc/paper/3089-analysis-of-empirical-bayesian-methods-for-neuroelectromagnetic-source-localization.pdf}, + year = {2007} +} + +@article{WipfNagarajan2009, + author = {Wipf, David and Nagarajan, Srikantan}, + doi = {10.1016/j.neuroimage.2008.02.059}, + journal = {NeuroImage}, + number = {3}, + pages = {947-966}, + title = {A Unified {{Bayesian}} Framework for {{MEG}}/{{EEG}} Source Imaging}, + volume = {44}, + year = {2009} +} + +@article{Zhang1995, + author = {Zhang, Zhi}, + doi = {10.1088/0031-9155/40/3/001}, + journal = {Physics in Medicine and Biology}, + number = {3}, + pages = {335-349}, + title = {A Fast Method to Compute Surface Potentials Generated by Dipoles within Multilayer Anisotropic Spheres}, + volume = {40}, + year = {1995} +} + +@article{KayserTenke2015, + title = {On the benefits of using surface {Laplacian} ({Current} {Source} {Density}) methodology in electrophysiology}, + volume = {97}, + issn = {0167-8760}, + doi = {10.1016/j.ijpsycho.2015.06.001}, + number = {3}, + journal = {International journal of psychophysiology : official journal of the International Organization of Psychophysiology}, + author = {Kayser, Jürgen and Tenke, Craig E.}, + year = {2015}, + pmid = {26071227}, + pmcid = {PMC4610715}, + pages = {171--173} +} + +@article{GrattonEtAl1983, + title = {A new method for off-line removal of ocular artifact}, + volume = {55}, + issn = {0013-4694}, + doi = {10.1016/0013-4694(83)90135-9}, + number = {4}, + urldate = {2020-08-03}, + journal = {Electroencephalography and Clinical Neurophysiology}, + author = {Gratton, Gabriele and Coles, Michael G. H and Donchin, Emanuel}, + year = {1983}, + pages = {468--484} +} + +@book{OppenheimEtAl1999, + address = {Upper Saddle River, NJ}, + edition = {2 edition}, + title = {Discrete-{Time} {Signal} {Processing}}, + isbn = {978-0-13-754920-7}, + publisher = {Prentice Hall}, + author = {Oppenheim, Alan V. and Schafer, Ronald W. and Buck, John R.}, + year = {1999} +} + +@book{CrochiereRabiner1983, + address = {Englewood Cliffs, NJ}, + edition = {1 edition}, + title = {Multirate {Digital} {Signal} {Processing}}, + isbn = {978-0-13-605162-6}, + publisher = {Pearson}, + author = {Crochiere, Ronald E. and Rabiner, Lawrence R.}, + year = {1983} +} + +@article{Yao2001, + title = {A method to standardize a reference of scalp {EEG} recordings to a point at infinity}, + volume = {22}, + issn = {0967-3334}, + doi = {10.1088/0967-3334/22/4/305}, + number = {4}, + journal = {Physiological Measurement}, + author = {Yao, D.}, + year = {2001}, + pmid = {11761077}, + pages = {693--711} +} + +@inproceedings{StrohmeierEtAl2015, + title = {{MEG}/{EEG} {Source} {Imaging} with a {Non}-{Convex} {Penalty} in the {Time}-{Frequency} {Domain}}, + doi = {10.1109/PRNI.2015.14}, + booktitle = {2015 {International} {Workshop} on {Pattern} {Recognition} in {NeuroImaging}}, + author = {Strohmeier, Daniel and Gramfort, Alexandre and Haueisen, Jens}, + year = {2015}, + pages = {21--24} +} + +@misc{WikipediaSI, + author = "{Wikipedia contributors}", + title = "International System of Units — {Wikipedia}{,} The Free Encyclopedia", + year = "2020", + url = "https://en.wikipedia.org/w/index.php?title=International_System_of_Units&oldid=982683558", + urldate = "12-October-2020" +} + +@misc{BIDSdocs, + author = "{BIDS} contributors", + title = {Brain Imaging Data Structure — Specification}, + url = {https://bids-specification.readthedocs.io/en/stable/}, + urldate = "12-October-2020" +} + +@article{OReillyEtAl2021, + title = {Structural templates for imaging {EEG} cortical sources in infants}, + volume = {227}, + issn = {1053-8119}, + doi = {10.1016/j.neuroimage.2020.117682}, + journal = {NeuroImage}, + author = {O'Reilly, Christian and Larson, Eric and Richards, John E. and Elsabbagh, Mayada}, + year = {2021}, + pages = {117682} +} + +@article{RichardsEtAl2016, + series = {Sharing the wealth: {Brain} {Imaging} {Repositories} in 2015}, + title = {A database of age-appropriate average {MRI} templates}, + volume = {124}, + issn = {1053-8119}, + doi = {10.1016/j.neuroimage.2015.04.055}, + journal = {NeuroImage}, + author = {Richards, John E. and Sanchez, Carmen and Phillips-Meek, Michelle and Xie, Wanze}, + year = {2016}, + pages = {1254--1259} +} + +@Article{Lehmann1980, + author = {Dietrich Lehmann and Wolfgang Skrandies}, + journal = {Electroencephalography and Clinical Neurophysiology}, + title = {Reference-free identification of components of checkerboard-evoked multichannel potential fields}, + year = {1980}, + issn = {0013-4694}, + number = {6}, + pages = {609--621}, + volume = {48}, + doi = {10.1016/0013-4694(80)90419-8}, + publisher = {Elsevier {BV}}, +} + +@Article{Lehmann1984, + author = {Dietrich Lehmann and Wolfgang Skrandies}, + journal = {Progress in Neurobiology}, + title = {Spatial analysis of evoked potentials in man—a review}, + year = {1984}, + issn = {0301-0082}, + number = {3}, + pages = {227--250}, + volume = {23}, + doi = {10.1016/0301-0082(84)90003-0}, + publisher = {Elsevier {BV}}, +} + +@Article{Murray2008, + author = {Micah M. Murray and Denis Brunet and Christoph M. Michel}, + journal = {Brain Topography}, + title = {Topographic {ERP} Analyses: {A} Step-by-Step Tutorial Review}, + year = {2008}, + issn = {0896-0267}, + number = {4}, + pages = {249--264}, + volume = {20}, + doi = {10.1007/s10548-008-0054-5}, + publisher = {Springer Science and Business Media {LLC}}, +} + +@Article{Kappenman2021, + author = {Emily S. Kappenman and Jaclyn L. Farrens and Wendy Zhang and Andrew X. Stewart and Steven J. Luck}, + journal = {{NeuroImage}}, + title = {{ERP} {CORE}: An open resource for human event-related potential research}, + year = {2021}, + issn = {1053-8119}, + pages = {117465}, + volume = {225}, + doi = {10.1016/j.neuroimage.2020.117465}, + publisher = {Elsevier {BV}}, +} + +@article{GenoveseEtAl2002, + title = {Thresholding of Statistical Maps in Functional Neuroimaging Using the False Discovery Rate}, + journal = {NeuroImage}, + volume = {15}, + number = {4}, + pages = {870-878}, + year = {2002}, + issn = {1053-8119}, + doi = {https://doi.org/10.1006/nimg.2001.1037}, + author = {Christopher R. Genovese and Nicole A. Lazar and Thomas Nichols}, +} + +@article{YaoEtAl2019, + title={Which reference should we use for {EEG} and {ERP} practice?}, + author={Yao, Dezhong and Qin, Yun and Hu, Shiang and Dong, Li and Vega, Maria L Bringas and Sosa, Pedro A Vald{\'e}s}, + journal={Brain topography}, + volume={32}, + number={4}, + pages={530--549}, + year={2019}, + doi = {10.1007/s10548-019-00707-x}, + publisher={Springer} +} + +@article{PolonenkoMaddox2019, + title = {The {Parallel} {Auditory} {Brainstem} {Response}}, + volume = {23}, + issn = {2331-2165}, + doi = {10.1177/2331216519871395}, + language = {en}, + journal = {Trends in Hearing}, + author = {Polonenko, Melissa J. and Maddox, Ross K.}, + year = {2019}, + pages = {2331216519871395} +} + +@article{DeledalleEtAl2014, + author = {Deledalle, Charles-Alban and Vaiter, Samuel and Fadili, Jalal and Peyré, Gabriel}, + title = {Stein Unbiased GrAdient estimator of the Risk (SUGAR) for Multiple Parameter Selection}, + journal = {SIAM Journal on Imaging Sciences}, + volume = {7}, + number = {4}, + pages = {2448-2487}, + year = {2014}, + doi = {10.1137/140968045}, +} + +@InProceedings{BertrandEtAl2020, + title = { Anderson acceleration of coordinate descent }, + author = {Bertrand, Quentin and Massias, Mathurin}, + booktitle = {Proceedings of The 24th International Conference on Artificial Intelligence and Statistics}, + pages = {1288--1296}, + year = {2021}, + editor = {Banerjee, Arindam and Fukumizu, Kenji}, + volume = {130}, + series = {Proceedings of Machine Learning Research}, + month = {13--15 Apr}, + publisher = {PMLR}, + url = {http://proceedings.mlr.press/v130/bertrand21a.html} +} + +@book{Luck2014, + title = {An Introduction to the Event-Related Potential Technique}, + author = {Luck, Steven J}, + year = {2014}, + edition = {2nd}, + publisher = {The MIT Press}, + address = {Cambridge, MA}, + url = {https://mitpress.mit.edu/books/introduction-event-related-potential-technique-second-edition}, + isbn = {978-0-262-52585-5} +} + +@article{Lopez-CalderonLuck2014, + title = {ERPLAB: An Open-Source Toolbox for the Analysis of Event-Related Potentials}, + author = {Lopez-Calderon, Javier and Luck, Steven J.}, + year = {2014}, + journal = {Frontiers in Human Neuroscience}, + volume = {8}, + issn = {1662-5161}, + doi = {10.3389/fnhum.2014.00213} +} + +@article{LuckGaspelin2017, + title = {How to Get Statistically Significant Effects in Any {{ERP}} Experiment (and Why You Shouldn't)}, + author = {Luck, Steven J. and Gaspelin, Nicholas}, + year = {2017}, + journal = {Psychophysiology}, + volume = {54}, + number = {1}, + pages = {146--157}, + issn = {1469-8986}, + doi = {10.1111/psyp.12639}, +} + +@article{Welch1967, + title = {The Use of Fast {{Fourier}} Transform for the Estimation of Power Spectra: {{A}} Method Based on Time Averaging over Short, Modified Periodograms}, + author = {Welch, Peter D.}, + year = {1967}, + journal = {IEEE Transactions on Audio and Electroacoustics}, + volume = {15}, + number = {2}, + pages = {70--73}, + doi = {10.1109/TAU.1967.1161901}, +} + +@article{MaksymenkoEtAl2017, + title = {Strategies for statistical thresholding of source localization maps in magnetoencephalography and estimating source extent}, + volume = {290}, + issn = {0165-0270}, + doi = {10.1016/j.jneumeth.2017.07.015}, + language = {en}, + journal = {Journal of Neuroscience Methods}, + author = {Maksymenko, Kostiantyn and Giusiano, Bernard and Roehri, Nicolas and Bénar, Christian-G. and Badier, Jean-Michel}, + month = oct, + year = {2017}, + pages = {95--104} +} + +@article{BeckerEtAl2017, + title = {{SISSY}: {An} efficient and automatic algorithm for the analysis of {EEG} sources based on structured sparsity}, + volume = {157}, + issn = {1053-8119}, + shorttitle = {{SISSY}}, + doi = {10.1016/j.neuroimage.2017.05.046}, + language = {en}, + journal = {NeuroImage}, + author = {Becker, H. and Albera, L. and Comon, P. and Nunes, J. -C. and Gribonval, R. and Fleureau, J. and Guillotel, P. and Merlet, I.}, + month = aug, + year = {2017}, + pages = {157--172} +} + +@article{YaoEtAl2005, + title = {Evaluation of different cortical source localization methods using simulated and experimental {EEG} data}, + volume = {25}, + issn = {1053-8119}, + doi = {10.1016/j.neuroimage.2004.11.036}, + language = {en}, + number = {2}, + journal = {NeuroImage}, + author = {Yao, Jun and Dewald, Julius P. A.}, + month = apr, + year = {2005}, + pages = {369--382} +} + +@article{StenroosHauk2013, + title = {Minimum-norm cortical source estimation in layered head models is robust against skull conductivity error}, + volume = {81}, + issn = {1053-8119}, + doi = {10.1016/j.neuroimage.2013.04.086}, + abstract = {The conductivity profile of the head has a major effect on EEG signals, but unfortunately the conductivity for the most important compartment, skull, is only poorly known. In dipole modeling studies, errors in modeled skull conductivity have been considered to have a detrimental effect on EEG source estimation. However, as dipole models are very restrictive, those results cannot be generalized to other source estimation methods. In this work, we studied the sensitivity of EEG and combined MEG+EEG source estimation to errors in skull conductivity using a distributed source model and minimum-norm (MN) estimation. We used a MEG/EEG modeling set-up that reflected state-of-the-art practices of experimental research. Cortical surfaces were segmented and realistically-shaped three-layer anatomical head models were constructed, and forward models were built with Galerkin boundary element method while varying the skull conductivity. Lead-field topographies and MN spatial filter vectors were compared across conductivities, and the localization and spatial spread of the MN estimators were assessed using intuitive resolution metrics. The results showed that the MN estimator is robust against errors in skull conductivity: the conductivity had a moderate effect on amplitudes of lead fields and spatial filter vectors, but the effect on corresponding morphologies was small. The localization performance of the EEG or combined MEG+EEG MN estimator was only minimally affected by the conductivity error, while the spread of the estimate varied slightly. Thus, the uncertainty with respect to skull conductivity should not prevent researchers from applying minimum norm estimation to EEG or combined MEG+EEG data. Comparing our results to those obtained earlier with dipole models shows that general judgment on the performance of an imaging modality should not be based on analysis with one source estimation method only.}, + language = {en}, + journal = {NeuroImage}, + author = {Stenroos, Matti and Hauk, Olaf}, + month = nov, + year = {2013}, + keywords = {Electroencephalography, Inverse problem, Magnetoencephalography, Minimum-norm estimation, Skull conductivity}, + pages = {265--272} +} + +@article{CroftBarry2000, + title = {Removal of ocular artifact from the {EEG}: a review}, + author = {Croft, R. J. and Barry, R. J.}, + year = {2000}, + journal = {Clinical Neurophysiology}, + volume = {30}, + number = {1}, + pages = {5--19}, + doi = {10.1016/S0987-7053(00)00055-1} +} + + +@article{SeymourEtAl2022, + title = {Interference suppression techniques for {OPM}-based {MEG}: {Opportunities} and challenges}, + volume = {247}, + issn = {1053-8119}, + shorttitle = {Interference suppression techniques for {OPM}-based {MEG}}, + doi = {10.1016/j.neuroimage.2021.118834}, + language = {en}, + journal = {NeuroImage}, + author = {Seymour, Robert A. and Alexander, Nicholas and Mellor, Stephanie and O'Neill, George C. and Tierney, Tim M. and Barnes, Gareth R. and Maguire, Eleanor A.}, + month = feb, + year = {2022}, + pages = {118834} +} + +@article{TierneyEtAl2021, + title = {Modelling optically pumped magnetometer interference in MEG as a spatially homogeneous magnetic field}, + volume = {244}, + issn = {1053-8119}, + doi = {10.1016/j.neuroimage.2021.118484}, + language = {en}, + journal = {NeuroImage}, + author = {Tierney, Tim M. and Alexander, Nicholas and Mellor, Stephanie and Holmes, Niall and Seymour, Robert and O'Neill, George C. and Maguire, Eleanor A. and Barnes, Gareth R.}, + year = {2021}, +} + +@article{TierneyEtAl2022, + title = {Spherical harmonic based noise rejection and neuronal sampling with multi-axis OPMs}, + journal = {NeuroImage}, + volume = {258}, + year = {2022}, + issn = {1053-8119}, + doi = {10.1016/j.neuroimage.2022.119338}, + author = {Tierney, Tim M. and Mellor, Stephanie nd O'Neill, George C. and Timms, Ryan C. and Barnes, Gareth R.}, +} + +@article{KumaravelEtAl2022, + doi = {10.3390/s22197314}, + url = {https://doi.org/10.3390/s22197314}, + year = {2022}, + month = sep, + publisher = {{MDPI} {AG}}, + volume = {22}, + number = {19}, + pages = {7314}, + author = {Velu Prabhakar Kumaravel and Marco Buiatti and Eugenio Parise and Elisabetta Farella}, + title = {Adaptable and Robust {EEG} Bad Channel Detection Using Local Outlier Factor ({LOF})}, + journal = {Sensors} +} + +@article{BreunigEtAl2000, + author = {Breunig, Markus M. and Kriegel, Hans-Peter and Ng, Raymond T. and Sander, J\"{o}rg}, + title = {LOF: Identifying Density-Based Local Outliers}, + year = {2000}, + issue_date = {June 2000}, + publisher = {Association for Computing Machinery}, + address = {New York, NY, USA}, + volume = {29}, + number = {2}, + url = {https://doi.org/10.1145/335191.335388}, + doi = {10.1145/335191.335388}, + journal = {SIGMOD Rec.}, + month = {may}, + pages = {93–104}, + numpages = {12}, + keywords = {outlier detection, database mining} +} + +@article{OyamaEtAl2015, + title = {Dry phantom for magnetoencephalography —{Configuration}, calibration, and contribution}, + volume = {251}, + issn = {0165-0270}, + doi = {10.1016/j.jneumeth.2015.05.004}, + journal = {Journal of Neuroscience Methods}, + author = {Oyama, Daisuke and Adachi, Yoshiaki and Yumoto, Masato and Hashimoto, Isao and Uehara, Gen}, + month = aug, + year = {2015}, + pages = {24--36}, +} + +@inproceedings{MellotEtAl2024, + title = {Physics-informed and Unsupervised Riemannian Domain Adaptation for Machine Learning on Heterogeneous EEG Datasets}, + author = {Mellot, Apolline and Collas, Antoine and Chevallier, Sylvain and Engemann, Denis and Gramfort, Alexandre}, + booktitle = {Proceedings of the 32nd European Signal Processing Conference (EUSIPCO)}, + year = {2024}, + address = {Lyon, France} +} diff --git a/mne-python/source/doc/sphinxext/_avatar_template.html b/mne-python/source/doc/sphinxext/_avatar_template.html new file mode 100644 index 0000000000000000000000000000000000000000..a0e086ee85e636440b0449ecc343263dfef1b936 --- /dev/null +++ b/mne-python/source/doc/sphinxext/_avatar_template.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/mne-python/source/doc/sphinxext/contrib_avatars.py b/mne-python/source/doc/sphinxext/contrib_avatars.py new file mode 100644 index 0000000000000000000000000000000000000000..9741a9eb095947c76a0e34347a00d7e559c22386 --- /dev/null +++ b/mne-python/source/doc/sphinxext/contrib_avatars.py @@ -0,0 +1,50 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +from pathlib import Path + +from mne.utils import _replace_md5 + + +def generate_contrib_avatars(app, config): + """Render a template webpage with avatars generated by JS and a GitHub API call.""" + root = Path(app.srcdir) + infile = root / "sphinxext" / "_avatar_template.html" + outfile = root / "_templates" / "avatars.html.new" + if os.getenv("MNE_ADD_CONTRIBUTOR_IMAGE", "false").lower() != "true": + body = """\ +

Contributor avators will appear here in full doc builds. Set \ +MNE_ADD_CONTRIBUTOR_IMAGE=true in your environment to generate it.

""" + else: + from selenium import webdriver + from selenium.common.exceptions import WebDriverException + from selenium.webdriver.common.by import By + from selenium.webdriver.support.ui import WebDriverWait + + try: + options = webdriver.ChromeOptions() + options.add_argument("--headless=new") + driver = webdriver.Chrome(options=options) + except WebDriverException: + options = webdriver.FirefoxOptions() + options.add_argument("-headless") + driver = webdriver.Firefox(options=options) + driver.get(f"file://{infile}") + wait = WebDriverWait(driver, 20) + wait.until(lambda d: d.find_element(by=By.ID, value="contributor-avatars")) + body = driver.find_element(by=By.TAG_NAME, value="body").get_property( + "innerHTML" + ) + assert isinstance(body, str), type(body) + driver.quit() + with open(outfile, "w") as fid: + fid.write(body) + _replace_md5(str(outfile)) + + +def setup(app): + """Set up the Sphinx app.""" + app.connect("config-inited", generate_contrib_avatars) + return diff --git a/mne-python/source/doc/sphinxext/credit_tools.py b/mne-python/source/doc/sphinxext/credit_tools.py new file mode 100644 index 0000000000000000000000000000000000000000..4526a85838f78f06089cd7949fe26e00088c7a43 --- /dev/null +++ b/mne-python/source/doc/sphinxext/credit_tools.py @@ -0,0 +1,527 @@ +"""Create code credit RST file. + +Run ./tools/dev/update_credit_json.py first to get the latest PR JSON files. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import glob +import json +import pathlib +import re +from collections import defaultdict +from pathlib import Path + +import numpy as np +import sphinx.util.logging + +import mne +from mne.utils import logger, verbose + +sphinx_logger = sphinx.util.logging.getLogger("mne") + +repo_root = Path(__file__).parents[2] +doc_root = repo_root / "doc" +data_dir = doc_root / "sphinxext" + +# TODO: For contributor names there are three sources of potential truth: +# +# 1. names.inc +# 2. GitHub profile names (that we pull dynamically here) +# 3. commit history / .mailmap. +# +# All three names can mismatch. Currently we try to defer to names.inc since this +# is assumed to have been chosen the most consciously/intentionally by contributors. +# Though it is possible that people can change their preferred names as well, so +# preferring GitHub profile info (when complete!) is probably preferable. + +# Allowed singletons +single_names = """ +btkcodedev buildqa sviter Akshay user27182 Mojackhak mne[bot] varshaa-1616 +""".strip().split() +# Surnames where we have more than one distinct contributor: +name_counts = dict( + Bailey=2, + Das=2, + Drew=2, + Jin=2, + Li=2, + Peterson=2, + Wong=2, + Zhang=3, +) +# Exceptions, e.g., abbrevitaions in first/last name or all-caps +exceptions = [ + "Natneal B", + "T. Wang", + "Ziyi ZENG", +] +# Manual renames +manual_renames = { + "akshay0724": "Akshay", # 4046, TODO: Check singleton + "alexandra.corneyllie": "Alexandra Corneyllie", # 7600 + "alexandra": "Alexandra Corneyllie", # 7600 + "Aniket": "Aniket Singh Yadav", # 13672 + "AnneSo": "Anne-Sophie Dubarry", # 4910 + "Basile": "Basile Pinsard", # 1791 + "Bru": "Bruno Aristimunha", # 13489 + "ChristinaZhao": "Christina Zhao", # 9075 + "Drew, J.": "Jordan Drew", # 10861 + "enzo": "Enzo Altamiranda", # 11351 + "Emma": "Emma Zhang", # 13486 + "Frostime": "Yiping Zuo", # 11773 + "FT": "Tamas Fehervari", # 13408 + "Gennadiy": "Gennadiy Belonosov", # 11720 + "Genuster": "Gennadiy Belonosov", # 12936 + "GreasyCat": "Rongfei Jin", # 13113 + "Hamid": "Hamid Maymandi", # 10849 + "jwelzel": "Julius Welzel", # 11118 + "Katia": "Katia Al-Amir", # 13225 + "Martin": "Martin Billinger", # 8099, TODO: Check + "Mats": "Mats van Es", # 11068 + "Michael": "Michael Krause", # 3304 + "Naveen": "Naveen Srinivasan", # 10787 + "NoahMarkowitz": "Noah Markowitz", # 12669 + "PAB": "Pierre-Antoine Bannier", # 9430 + "Rob Luke": "Robert Luke", + "Sena": "Sena Er", # 11029 + "TzionaN": "Tziona NessAiver", # 10953 + "Valerii": "Valerii Chirkov", # 9043 + "Wei": "Wei Xu", # 13218 + "Zhenya": "Evgenii Kalenkovich", # 6310, TODO: Check +} + + +def _good_name(name): + if name is None: + return False + assert isinstance(name, str), type(name) + if name == "mne[bot]": + return True + if not name.strip(): + return False + if " " not in name and name not in single_names: # at least two parts + return False + if name not in exceptions and "." in name.split()[0] or "." in name.split()[-1]: + return False + if " " in name and name not in exceptions: + first = name.split()[0] + last = name.split()[-1] + if first == first.upper() or last == last.upper(): # e.g., KING instead of King + return False + return True + + +@verbose +def generate_credit_rst(app=None, *, verbose=False): + """Get the credit RST.""" + sphinx_logger.info("Creating code credit RST inclusion file") + ignores = [ + int(ignore.split("#", maxsplit=1)[1].strip().split()[0][:-1]) + for ignore in (repo_root / ".git-blame-ignore-revs") + .read_text("utf-8") + .splitlines() + if not ignore.strip().startswith("#") and ignore.strip() + ] + ignores = {str(ig): [] for ig in ignores} + + # Use mailmap to help translate emails to names + mailmap = dict() + # mapping from email to name + name_map: dict[str, str] = dict() + for line in (repo_root / ".mailmap").read_text("utf-8").splitlines(): + name = re.match("^([^<]+) <([^<>]+)>", line.strip()).group(1) + assert _good_name(name), repr(name) + emails = list(re.findall("<([^<>]+)>", line.strip())) + assert len(emails) > 0 + new = emails[0] + if new in name_map: + assert name_map[new] == name + else: + name_map[new] = name + if len(emails) == 1: + continue + for old in emails[1:]: + if old in mailmap: + assert new == mailmap[old] # can be different names + else: + mailmap[old] = new + if old in name_map: + assert name_map[old] == name + else: + name_map[old] = name + + unknown_emails: set[str] = set() + + # dict with (name, commit) keys, values are int change counts + # ("commits" is really "PRs" for Python mode) + commits: dict[tuple[str], int] = defaultdict(lambda: 0) + + # dict with filename keys, values are dicts with name keys and +/- ndarrays + stats: dict[str, dict[str, np.ndarray]] = defaultdict( + lambda: defaultdict( + lambda: np.zeros(2, int), + ), + ) + + bad_commits = set() + expected_bad_names = dict() + + for fname in sorted(glob.glob(str(data_dir / "prs" / "*.json"))): + commit = Path(fname).stem # PR number is in the filename + data = json.loads(Path(fname).read_text("utf-8")) + del fname + assert data != {} + authors = data["authors"] + for author in authors: + if ( + author["e"] is not None + and author["e"] not in name_map + and _good_name(author["n"]) + ): + name_map[author["e"]] = author["n"] + for file, counts in data["changes"].items(): + if commit in ignores: + ignores[commit].append([file, commit]) + continue + p, m = counts["a"], counts["d"] + used_authors = set() + for author in authors: + if author["e"] is not None: + if author["e"] not in name_map: + unknown_emails.add( + f"{author['e'].ljust(29)} " + "https://github.com/mne-tools/mne-python/pull/" + f"{commit}/files" + ) + continue + name = name_map[author["e"]] + else: + name = author["n"] + if name in manual_renames: + assert _good_name(manual_renames[name]), ( + f"Bad manual rename: {name}" + ) + name = manual_renames[name] + if " " in name: + first, last = name.rsplit(" ", maxsplit=1) + if last == last.upper() and len(last) > 1: + last = last.capitalize() + if first == first.upper() and len(first) > 1: + first = first.capitalize() + name = f"{first} {last}" + assert not first.upper() == first, f"Bad {name=} from {commit}" + assert _good_name(name), f"Bad {name=} from {commit}" + if "King" in name: + assert name == "Jean-Rémi King", name + + if name is None: + bad_commits.add(commit) + continue + if name in used_authors: + continue + if not _good_name(name) and name not in expected_bad_names: + expected_bad_names[name] = f"{name} from #{commit}" + if author["e"]: + expected_bad_names[name] += f" email {author['e']}" + assert name.strip(), repr(name) + used_authors.add(name) + # treat moves and permission changes like a single-line change + if p == m == 0: + p = 1 + commits[(name, commit)] += p + m + stats[file][name] += [p, m] + if bad_commits: + raise RuntimeError( + "Run:\nrm " + + " ".join(f"{bad}.json" for bad in sorted(bad_commits, key=int)) + ) + + # Check for duplicate names based on last name, and also singleton names. + last_map = defaultdict(lambda: set()) + bad_names = set() + for these_stats in stats.values(): + for name in these_stats: + assert name == name.strip(), f"Un-stripped name: {repr(name)}" + last = name.split()[-1] + first = name.split()[0] + last_map[last].add(name) + name_where = expected_bad_names.get(name, name) + if last == name and name not in single_names: + bad_names.add(f"Singleton: {name_where}") + if "." in last or "." in first and name not in exceptions: + bad_names.add(f"Abbreviation: {name_where}") + bad_names = sorted(bad_names) + for last, names in last_map.items(): + if len(names) > name_counts.get(last, 1): + bad_names.append(f"Duplicates: {sorted(names)}") + if bad_names: + what = ( + "Unexpected possible duplicates or bad names found, " + f"consider modifying {'/'.join(Path(__file__).parts[-3:])}:\n" + ) + raise RuntimeError(what + "\n".join(bad_names)) + + unknown_emails = set( + email + for email in unknown_emails + if "autofix-ci[bot]" not in email + and "pre-commit-ci[bot]" not in email + and "dependabot[bot]" not in email + and "github-actions[bot]" not in email + and "50266005+mne-bot" not in email + ) + what = "Unknown emails, consider adding to .mailmap:\n" + assert len(unknown_emails) == 0, what + "\n".join(sorted(unknown_emails)) + + logger.info("Biggest included commits/PRs:") + commits = dict( + (k, commits[k]) + for k in sorted(commits, key=lambda k_: commits[k_], reverse=True) + ) + for ni, name in enumerate(commits, 1): + if ni > 10: + break + logger.info(f"{str(name[1]).ljust(5)} @ {commits[name]:5d} by {name[0]}") + + logger.info("\nIgnored commits:") + # Report the ignores + for commit in ignores: # should have found one of each + logger.info(f"ignored {len(ignores[commit]):3d} files for {commit}") + assert len(ignores[commit]) >= 1, (ignores[commit], commit) + globs = dict() + + # This is the mapping from changed filename globs to module names on the website. + # We need to include aliases for old stuff. Anything we want to exclude we put in + # "null" with a higher priority (i.e., in dict first): + link_overrides = dict() # overrides for links + for key in """ + *.qrc *.png *.svg *.ico *.elc *.sfp *.lout *.lay *.csd *.txt + mne/_version.py mne/externals/* */__init__.py* */resources.py paper.bib + mne/html/*.css mne/html/*.js mne/io/bti/tests/data/* */SHA1SUMS *__init__py + AUTHORS.rst CITATION.cff CONTRIBUTING.rst codemeta.json mne/tests/*.* jr-tools + */whats_new.rst */latest.inc */dev.rst */changelog.rst */manual/* doc/*.json + logo/LICENSE doc/credit.rst + """.strip().split(): + globs[key] = "null" + # Now onto the actual module organization + root_path = pathlib.Path(mne.__file__).parent + mod_file_map = dict() + for file in root_path.iterdir(): + rel = file.relative_to(root_path).with_suffix("") + mod = f"mne.{rel}" + if file.is_dir(): + globs[f"mne/{rel}/*.*"] = mod + globs[f"mne/{rel}.*"] = mod + elif file.is_file() and file.suffix == ".py": + key = f"mne/{rel}.py" + if file.stem == "conftest": + globs[key] = "maintenance" + globs["conftest.py"] = "maintenance" + else: + globs[key] = mod + mod_file_map[mod] = key + globs["mne/artifacts/*.py"] = "mne.preprocessing" + for key in """ + pick.py constants.py info.py fiff/*.* _fiff/*.* raw.py testing.py _hdf5.py + compensator.py + """.strip().split(): + globs[f"mne/{key}"] = "mne.io" + for key in ("mne/transforms/*.py", "mne/_freesurfer.py"): + globs[key] = "mne.transforms" + globs["mne/mixed_norm/*.py"] = "mne.inverse_sparse" + globs["mne/__main__.py"] = "mne.commands" + globs["bin/*"] = "mne.commands" + globs["mne/morph_map.py"] = "mne.surface" + globs["mne/baseline.py"] = "mne.epochs" + for key in """ + parallel.py rank.py misc.py data/*.* defaults.py fixes.py icons/*.* icons.* + """.strip().split(): + globs[f"mne/{key}"] = "mne.utils" + for key in ("mne/_ola.py", "mne/cuda.py"): + globs[key] = "mne.filter" + for key in """ + *digitization/*.py layouts/*.py montages/*.py selection.py + """.strip().split(): + globs[f"mne/{key}"] = "mne.channels" + globs["mne/sparse_learning/*.py"] = "mne.inverse_sparse" + globs["mne/csp.py"] = "mne.preprocessing" + globs["mne/bem_surfaces.py"] = "mne.bem" + globs["mne/coreg/*.py"] = "mne.coreg" + globs["mne/inverse.py"] = "mne.minimum_norm" + globs["mne/stc.py"] = "mne.source_estimate" + globs["mne/surfer.py"] = "mne.viz" + globs["mne/tfr.py"] = "mne.time_frequency" + globs["mne/connectivity/*.py"] = "mne-connectivity (moved)" + link_overrides["mne-connectivity (moved)"] = "mne-tools/mne-connectivity" + globs["mne/realtime/*.py"] = "mne-realtime (moved)" + link_overrides["mne-realtime (moved)"] = "mne-tools/mne-realtime" + globs["mne/html_templates/*.*"] = "mne.report" + globs[".circleci/*"] = "maintenance" + link_overrides["maintenance"] = "mne-tools/mne-python" + globs["tools/*"] = "maintenance" + globs["doc/*"] = "doc" + for key in ("*.py", "*.rst"): + for mod in ("examples", "tutorials", "doc"): + globs[f"{mod}/{key}"] = mod + for key in """ + *.yml *.md setup.* MANIFEST.in Makefile README.rst flow_diagram.py *.toml + debian/* logo/*.py *.git* .pre-commit-config.yaml .mailmap .coveragerc make/* + """.strip().split(): + globs[key] = "maintenance" + + mod_stats = defaultdict(lambda: defaultdict(lambda: np.zeros(2, int))) + other_files = set() + total_lines = np.zeros(2, int) + for fname, counts in stats.items(): + for pattern, mod in globs.items(): + if glob.fnmatch.fnmatch(fname, pattern): + break + else: + other_files.add(fname) + mod = "other" + for e, pm in counts.items(): + if mod == "mne._fiff": + raise RuntimeError + # sanity check a bit + if mod != "null" and (".png" in fname or "/manual/" in fname): + raise RuntimeError(f"Unexpected {mod} {fname}") + mod_stats[mod][e] += pm + mod_stats["mne"][e] += pm + total_lines += pm + mod_stats.pop("null") # stuff we shouldn't give credit for + mod_stats = dict( + (k, mod_stats[k]) + for k in sorted( + mod_stats, + key=lambda x: ( + not x.startswith("mne"), + x == "maintenance", + x.replace("-", "."), + ), + ) + ) # sort modules alphabetically + other_files = sorted(other_files) + if len(other_files): + raise RuntimeError( + f"{len(other_files)} misc file(s) found:\n" + "\n".join(other_files) + ) + logger.info(f"\nTotal line change count: {list(map(int, total_lines))}") + + # sphinx-design badges that we use for contributors + BADGE_KINDS = ["bdg-info-line", "bdg"] + content = f"""\ +.. THIS FILE IS AUTO-GENERATED BY {Path(__file__).stem} AND WILL BE OVERWRITTEN + +.. raw:: html + + + +.. _code_credit: + +Code credit +=========== + +Below are lists of code contributors to MNE-Python. The numbers in parentheses are the +number of lines changed in our code history. + +- :{BADGE_KINDS[0]}:`This badge` is used for the top 10% of contributors. +- :{BADGE_KINDS[1]}:`This badge` is used for the remaining 90% of contributors. + +Entire codebase +--------------- + +""" + for mi, (mod, counts) in enumerate(mod_stats.items()): + if mi == 0: + assert mod == "mne", mod + indent = " " * 3 + elif mi == 1: + indent = " " * 6 + content += """ + +By submodule +------------ + +Contributors often have domain-specific expertise, so we've broken down the +contributions by submodule as well below. + +.. grid:: 1 2 3 3 + :gutter: 1 + +""" + # if there are 10 this is 100, if there are 100 this is 100 + these_stats = dict((k, v.sum()) for k, v in counts.items()) + these_stats = dict( + (k, these_stats[k]) + for k in sorted(these_stats, key=lambda x: these_stats[x], reverse=True) + ) + if mod in link_overrides: + link = f"https://github.com/{link_overrides[mod]}" + else: + kind = "blame" if mod in mod_file_map else "tree" + link_mod = mod_file_map.get(mod, mod.replace(".", "/")) + link = f"https://github.com/mne-tools/mne-python/{kind}/main/{link_mod}" + assert "moved" not in link, (mod, link) + # Use badges because they flow nicely, inside a grid to make it more compact + stat_lines = [] + for ki, (k, v) in enumerate(these_stats.items()): + # Round to two digits, e.g. 12340 -> 12000, 12560 -> 13000 + v_round = int(float(f"{v:.2g}")) + assert v_round > 0, f"Got zero lines changed for {k} in {mod}: {v_round}" + # And then write as a max-3-char human-readable abbreviation like + # 123, 1.2k, 123k, 12m, etc. + for prefix in ("", "k", "m", "g"): + if v_round >= 1000: + v_round = v_round / 1000 + else: + if v_round >= 10 or prefix == "": # keep single digit as 1 not 1.0 + v_round = f"{int(round(v_round))}" + else: + v_round = f"{v_round:.1f}" + v_round += prefix + break + else: + raise RuntimeError(f"Too many digits in {v}") + idx = 0 if ki < (len(these_stats) - 1) // 10 + 1 else 1 + if any(b in k for b in ("[bot]", "Lumberbot", "Deleted user")): + continue + assert _good_name(k) + stat_lines.append(f":{BADGE_KINDS[idx]}:`{k} ({v_round})`") + stat_lines = f"\n{indent}".join(stat_lines) + if mi == 0: + content += f""" + +.. card:: {mod} + :class-card: overflow-auto + :link: https://github.com/mne-tools/mne-python/graphs/contributors + +{indent}{stat_lines} + +""" + else: + content += f""" + + .. grid-item-card:: {mod} + :class-card: overflow-auto + :link: {link} + +{indent}{stat_lines} + +""" + (doc_root / "code_credit.inc").write_text(content, encoding="utf-8") + + +if __name__ == "__main__": + generate_credit_rst(verbose=True) diff --git a/mne-python/source/doc/sphinxext/directive_formatting.py b/mne-python/source/doc/sphinxext/directive_formatting.py new file mode 100644 index 0000000000000000000000000000000000000000..4c65f653d4a5b04b581fee51c79e430a6f6b0140 --- /dev/null +++ b/mne-python/source/doc/sphinxext/directive_formatting.py @@ -0,0 +1,88 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import re + +from mne_doc_utils import sphinx_logger + + +def setup(app): + app.connect("source-read", check_directive_formatting) + app.connect("autodoc-process-docstring", check_directive_formatting) + + +def setup_module(): + # HACK: Stop nosetests running setup() above + pass + + +def check_directive_formatting(*args): + """Check that directives are not missing a space. + + For args, see Sphinx events 'source-read' and 'autodoc-process-docstring'. + """ + # Extract relevant info from args + if len(args) == 3: # from source-read + source_type = "File" + name = args[1] + source = args[2][0] + source_concat = source # content already a single string + elif len(args) == 6: # from autodoc-process-docstring + source_type = "Docstring" + name = args[2] + source = args[5] + source_concat = "\n".join(source) # combine lines into single string + else: + raise RuntimeError("Unexpected number of arguments from Sphinx event") + + # Check if any directives are present + if re.search(r"\.\.\s*[a-zA-Z]+::", source_concat) is None: + return + + # Separate content into lines (docstrings already are) + if source_type == "File": + source = source.split("\n") + + # Check for bad formatting + for idx, line in enumerate(source): + # Check for missing space after '..' + missing = re.search(r"\.\.[a-zA-Z]+::", line) + if missing is not None: + sphinx_logger.warning( + f"{source_type} '{name}' is missing a space after '..' in the " + f"directive '{missing.group()}'" + ) + # Extra spaces after '..' don't affect formatting + + # Check for missing preceding blank line + # (exceptions are for directives at the start of files, after a header, or after + # another directive/another directive's content) + if idx == 0: + continue + dir_pattern = r"^\s*\.\. \w+::" # line might start with whitespace + head_pattern = r"^[-|=|\^]+$" + directive = re.search(dir_pattern, line) + if directive is not None: + line_prev = source[idx - 1].strip() + if ( # If previous line is... + line_prev != "" # not empty + and not re.search(head_pattern, line_prev) # not a header + and not re.search(dir_pattern, line_prev) # not a directive + ): + # Check if previous line is part of another directive + bad = True + for line_prev in reversed(source[: idx - 1]): + line_prev = line_prev.strip() + if line_prev == "" or re.search(head_pattern, line_prev): + # is a blank line or header, so not part of another directive + break # must be bad formatting + if re.search(dir_pattern, line_prev): + bad = False # is part of another directive, is good formatting + break + # or keep going until we reach the first line (so must be bad) + if bad: + sphinx_logger.warning( + f"{source_type} '{name}' is missing a blank line before the " + f"directive '{directive.group()}' on line {idx + 1}" + ) diff --git a/mne-python/source/doc/sphinxext/flow_diagram.py b/mne-python/source/doc/sphinxext/flow_diagram.py new file mode 100644 index 0000000000000000000000000000000000000000..3b6007c6595ad3a601cfd1c425ab7b04a26027f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/flow_diagram.py @@ -0,0 +1,180 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +from os import path as op + +title = "mne-python flow diagram" + +font_face = "Arial" +node_size = 12 +node_small_size = 9 +edge_size = 9 +sensor_color = "#7bbeca" +source_color = "#ff6347" + +legend = f""" +< + + + +
+Sensor (M/EEG) space
+Source (brain) space
>""" +legend = "".join(legend.split("\n")) + +nodes = dict( + T1="T1", + flashes="Flash5/30", + trans="Head-MRI trans", + recon="Freesurfer surfaces", + bem="BEM", + src="Source space\nmne.SourceSpaces", + cov="Noise covariance\nmne.Covariance", + fwd="Forward solution\nmne.forward.Forward", + inv="Inverse operator\nmne.minimum_norm.InverseOperator", + stc="Source estimate\nmne.SourceEstimate", + raw="Raw data\nmne.io.Raw", + epo="Epoched data\nmne.Epochs", + evo="Averaged data\nmne.Evoked", + pre="Preprocessed data\nmne.io.Raw", + legend=legend, +) + +sensor_space = ("raw", "pre", "epo", "evo", "cov") +source_space = ("src", "stc", "bem", "flashes", "recon", "T1") + +edges = ( + ("T1", "recon"), + ("flashes", "bem"), + ("recon", "bem"), + ("recon", "src", "mne.setup_source_space"), + ("src", "fwd"), + ("bem", "fwd"), + ("trans", "fwd", "mne.make_forward_solution"), + ("fwd", "inv"), + ("cov", "inv", "mne.make_inverse_operator"), + ("inv", "stc"), + ("evo", "stc", "mne.minimum_norm.apply_inverse"), + ( + "raw", + "pre", + "raw.filter\n" + "mne.preprocessing.ICA\n" + "mne.preprocessing.compute_proj_eog\n" + "mne.preprocessing.compute_proj_ecg\n" + "...", + ), + ("pre", "epo", "mne.Epochs"), + ("epo", "evo", "epochs.average"), + ("epo", "cov", "mne.compute_covariance"), +) + +subgraphs = ( + [ + ("T1", "flashes", "recon", "bem", "src"), + ( + f'' + "Freesurfer / MNE-C>" + ), + ], +) + + +def setup(app): + app.connect("builder-inited", generate_flow_diagram) + app.add_config_value("make_flow_diagram", True, "html") + + +def setup_module(): + # HACK: Stop nosetests running setup() above + pass + + +def generate_flow_diagram(app): + out_dir = op.join(app.builder.outdir, "_static") + if not op.isdir(out_dir): + os.makedirs(out_dir) + out_fname = op.join(out_dir, "mne-python_flow.svg") + make_flow_diagram = app is None or bool(app.builder.config.make_flow_diagram) + if not make_flow_diagram: + print("Skipping flow diagram, webpage will have a missing image") + return + + import pygraphviz as pgv + + g = pgv.AGraph(name=title, directed=True) + + for key, label in nodes.items(): + label = label.split("\n") + if len(label) > 1: + label[0] = f'<' + label[0] + "" + for li in range(1, len(label)): + label[li] = ( + f'' + + label[li] + + "" + ) + label[-1] = label[-1] + ">" + label = "
".join(label) + else: + label = label[0] + g.add_node(key, shape="plaintext", label=label) + + # Create and customize nodes and edges + for edge in edges: + g.add_edge(*edge[:2]) + e = g.get_edge(*edge[:2]) + if len(edge) > 2: + e.attr["label"] = ( + "<" + + '
'.join(edge[2].split("\n")) + + '
>' + ) + e.attr["fontsize"] = edge_size + + # Change colors + for these_nodes, color in zip( + (sensor_space, source_space), (sensor_color, source_color) + ): + for node in these_nodes: + g.get_node(node).attr["fillcolor"] = color + g.get_node(node).attr["style"] = "filled" + + # Create subgraphs + for si, subgraph in enumerate(subgraphs): + g.add_subgraph(subgraph[0], f"cluster{si}", label=subgraph[1], color="black") + + # Format (sub)graphs + for gr in g.subgraphs() + [g]: + for x in [gr.node_attr, gr.edge_attr]: + x["fontname"] = font_face + g.node_attr["shape"] = "box" + + # A couple of special ones + for ni, node in enumerate(("fwd", "inv", "trans")): + node = g.get_node(node) + node.attr["gradientangle"] = 270 + colors = (source_color, sensor_color) + colors = colors if ni == 0 else colors[::-1] + node.attr["fillcolor"] = ":".join(colors) + node.attr["style"] = "filled" + del node + g.get_node("legend").attr.update(shape="plaintext", margin=0, rank="sink") + # put legend in same rank/level as inverse + leg = g.add_subgraph(["legend", "inv"], name="legendy") + leg.graph_attr["rank"] = "same" + + g.layout("dot") + g.draw(out_fname, format="svg") + return g + + +# This is useful for testing/iterating to see what the result looks like +if __name__ == "__main__": + from mne.io.constants import Bunch + + out_dir = op.abspath(op.join(op.dirname(__file__), "..", "_build", "html")) + app = Bunch(builder=Bunch(outdir=out_dir, config=Bunch(make_flow_diagram=True))) + g = generate_flow_diagram(app) diff --git a/mne-python/source/doc/sphinxext/gen_commands.py b/mne-python/source/doc/sphinxext/gen_commands.py new file mode 100644 index 0000000000000000000000000000000000000000..9e9d04eca08358ec8c49f801695d6bb9da84fb6c --- /dev/null +++ b/mne-python/source/doc/sphinxext/gen_commands.py @@ -0,0 +1,113 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import glob +from importlib import import_module +from pathlib import Path + +from mne.utils import ArgvSetter, _replace_md5 + + +def setup(app): + app.connect("builder-inited", generate_commands_rst) + + +def setup_module(): + # HACK: Stop nosetests running setup() above + pass + + +# Header markings go: +# 1. =/= : Page title +# 2. = : Command name +# 3. -/- : Command description +# 4. - : Command sections (Examples, Notes) + +header = """\ +:orphan: + +.. _python_commands: + +=============================== +Command line tools using Python +=============================== + +""" + +command_rst = """ + +.. _{0}: + +{0} +{1} + +.. rst-class:: callout + +{2} + +""" + + +def generate_commands_rst(app=None): + try: + from sphinx.util.display import status_iterator + except Exception: + from sphinx.util import status_iterator + root = Path(__file__).parents[2] + out_dir = root / "doc" / "generated" + out_dir.mkdir(exist_ok=True) + out_fname = out_dir / "commands.rst.new" + + command_path = root / "mne" / "commands" + fnames = sorted( + Path(fname).name for fname in glob.glob(str(command_path / "mne_*.py")) + ) + assert len(fnames) + iterator = status_iterator( + fnames, "generating MNE command help ... ", length=len(fnames) + ) + with open(out_fname, "w", encoding="utf8") as f: + f.write(header) + for fname in iterator: + cmd_name = fname[:-3] + module = import_module("." + cmd_name, "mne.commands") + with ArgvSetter(("mne", cmd_name, "--help")) as out: + try: + module.run() + except SystemExit: # this is how these terminate + pass + output = out.stdout.getvalue().splitlines() + + # Swap usage and title lines + output[0], output[2] = output[2], output[0] + + # Add header marking + for idx in (1, 0): + output.insert(idx, "-" * len(output[0])) + + # Add code styling for the "Usage: " line + for li, line in enumerate(output): + if line.startswith("Usage: mne "): + output[li] = f"Usage: ``{line[7:]}``" + break + + # Turn "Options:" into field list + if "Options:" in output: + ii = output.index("Options:") + output[ii] = "Options" + output.insert(ii + 1, "-------") + output.insert(ii + 2, "") + output.insert(ii + 3, ".. rst-class:: field-list cmd-list") + output.insert(ii + 4, "") + output = "\n".join(output) + cmd_name_space = cmd_name.replace("mne_", "mne ") + f.write( + command_rst.format(cmd_name_space, "=" * len(cmd_name_space), output) + ) + _replace_md5(str(out_fname)) + + +# This is useful for testing/iterating to see what the result looks like +if __name__ == "__main__": + generate_commands_rst() diff --git a/mne-python/source/doc/sphinxext/gen_names.py b/mne-python/source/doc/sphinxext/gen_names.py new file mode 100644 index 0000000000000000000000000000000000000000..24212dd7a9bfbef61874392c6c5745880490f02d --- /dev/null +++ b/mne-python/source/doc/sphinxext/gen_names.py @@ -0,0 +1,33 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +from os import path as op + + +def setup(app): + app.connect("builder-inited", generate_name_links_rst) + + +def setup_module(): + # HACK: Stop nosetests running setup() above + pass + + +def generate_name_links_rst(app=None): + if "linkcheck" not in str(app.builder).lower(): + return + out_dir = op.abspath(op.join(op.dirname(__file__), "..", "generated")) + if not op.isdir(out_dir): + os.mkdir(out_dir) + out_fname = op.join(out_dir, "_names.rst") + names_path = op.abspath( + op.join(os.path.dirname(__file__), "..", "changes", "names.inc") + ) + with open(out_fname, "w", encoding="utf8") as fout: + fout.write(":orphan:\n\n") + with open(names_path) as fin: + for line in fin: + if line.startswith(".. _"): + fout.write(f"- {line[4:]}") diff --git a/mne-python/source/doc/sphinxext/gh_substitutions.py b/mne-python/source/doc/sphinxext/gh_substitutions.py new file mode 100644 index 0000000000000000000000000000000000000000..9f9fc2eeff693935c16b0e51d66ae3dcbbc14486 --- /dev/null +++ b/mne-python/source/doc/sphinxext/gh_substitutions.py @@ -0,0 +1,48 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import docutils +from docutils.nodes import reference + +# Adapted from sphinx +if docutils.__version_info__[:2] < (0, 22): + from docutils.parsers.rst import roles + + def _normalize_options(options): + if options is None: + return {} + n_options = options.copy() + roles.set_classes(n_options) + return n_options + +else: + from docutils.parsers.rst.roles import ( + normalize_options as _normalize_options, + ) + + +def gh_role(name, rawtext, text, lineno, inliner, options={}, content=[]): # noqa: B006 + """Link to a GitHub issue. + + adapted from + https://doughellmann.com/blog/2010/05/09/defining-custom-roles-in-sphinx/ + """ + try: + # issue/PR mode (issues/PR-num will redirect to pull/PR-num) + int(text) + except ValueError: + # direct link mode + slug = text + else: + slug = "issues/" + text + text = "#" + text + ref = "https://github.com/mne-tools/mne-python/" + slug + options = _normalize_options(options) + node = reference(rawtext, text, refuri=ref, **options) + return [node], [] + + +def setup(app): + app.add_role("gh", gh_role) + return diff --git a/mne-python/source/doc/sphinxext/mne_doc_utils.py b/mne-python/source/doc/sphinxext/mne_doc_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..0c2a4d5f8e9b463f9c96ca4632e9052b6096662d --- /dev/null +++ b/mne-python/source/doc/sphinxext/mne_doc_utils.py @@ -0,0 +1,245 @@ +"""Doc building utils.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import gc +import os +import time +import warnings +from pathlib import Path + +import numpy as np +import pyvista +import sphinx.util.logging +from sphinx.errors import ExtensionError + +import mne +from mne.utils import ( + _assert_no_instances as _assert_no_instances_mne, +) +from mne.utils import ( + _get_extra_data_path, + sizeof_fmt, +) +from mne.viz import Brain + +sphinx_logger = sphinx.util.logging.getLogger("mne") +_np_print_defaults = np.get_printoptions() + + +def reset_warnings(gallery_conf, fname): + """Ensure we are future compatible and ignore silly warnings.""" + # In principle, our examples should produce no warnings. + # Here we cause warnings to become errors, with a few exceptions. + # This list should be considered alongside + # setup.cfg -> [tool:pytest] -> filterwarnings + + # remove tweaks from other module imports or example runs + warnings.resetwarnings() + # restrict + warnings.filterwarnings("error") + # allow these, but show them + warnings.filterwarnings("always", '.*non-standard config type: "foo".*') + warnings.filterwarnings("always", '.*config type: "MNEE_USE_CUUDAA".*') + warnings.filterwarnings("always", ".*cannot make axes width small.*") + warnings.filterwarnings("always", ".*Axes that are not compatible.*") + warnings.filterwarnings("always", ".*FastICA did not converge.*") + # ECoG BIDS spec violations: + warnings.filterwarnings("always", ".*Fiducial point nasion not found.*") + warnings.filterwarnings("always", ".*DigMontage is only a subset of.*") + warnings.filterwarnings( # xhemi morph (should probably update sample) + "always", ".*does not exist, creating it and saving it.*" + ) + # internal warnings + warnings.filterwarnings("default", module="sphinx") + # don't error on joblib warning during parallel doc build otherwise we get a + # cryptic deadlock instead of a nice traceback + warnings.filterwarnings( + "always", + "A worker stopped while some jobs were given to the executor.*", + category=UserWarning, + ) + # ignore (DeprecationWarning) + for key in ( + # nibabel + "__array__ implementation doesn't accept.*", + # pybtex (from sphinxcontrib-bibtex) + "pkg_resources is deprecated as an API.*", + "\nImplementing implicit namespace packages", + # latexcodec + r"open_text is deprecated\. Use files", + # dipy etc. + "The `disp` and `iprint` options of the L-BFGS-B solver", + # statsmodels<->pandas + "Substitution is deprecated and will be removed", + ): + warnings.filterwarnings( # deal with other modules having bad imports + "ignore", message=f".*{key}.*", category=DeprecationWarning + ) + # ignore (PendingDeprecationWarning) + for key in ( + # sphinx + "The mapping interface for autodoc options", + # sphinxcontrib-bibtex + "sphinx.environment.BuildEnvironment.app' is deprecated", + ): + warnings.filterwarnings( # deal with other modules having bad imports + "ignore", message=f".*{key}.*", category=PendingDeprecationWarning + ) + # ignore (UserWarning) + for message in ( + # Matplotlib + ".*is non-interactive, and thus cannot.*", + # nilearn + r"You are using the.*matplotlib backend that[.\n]*", + # pybtex + ".*pkg_resources is deprecated as an API.*", + # dipy <-> NumPy + "'where' used without 'out', expect.*", + ): + warnings.filterwarnings( + "ignore", + message=message, + category=UserWarning, + ) + # ignore (RuntimeWarning) + for message in ( + # mne-python config file "corruption" due to doc build parallelization + ".*The MNE-Python config file.*valid JSON.*", + ): + warnings.filterwarnings( + "ignore", + message=message, + category=RuntimeWarning, + ) + + # In case we use np.set_printoptions in any tutorials, we only + # want it to affect those: + np.set_printoptions(**_np_print_defaults) + + +t0 = time.time() + + +def _assert_no_instances(cls, when): + """Wrap our internal one but make the traceback nicer when it fails.""" + try: + _assert_no_instances_mne(cls, when) + except Exception as exc: + raise ExtensionError(str(exc)) from None + + +def reset_modules(gallery_conf, fname, when): + """Do the reset.""" + import matplotlib.pyplot as plt + + mne.viz.set_3d_backend("pyvistaqt") + pyvista.OFF_SCREEN = False + pyvista.BUILDING_GALLERY = True + + from pyvista import Plotter # noqa + + try: + from pyvistaqt import BackgroundPlotter # noqa + except ImportError: + BackgroundPlotter = None # noqa + try: + from vtkmodules.vtkCommonDataModel import vtkPolyData # noqa + except ImportError: + vtkPolyData = None # noqa + try: + from mne_qt_browser._pg_figure import MNEQtBrowser + except ImportError: + MNEQtBrowser = None + from mne.viz.backends.renderer import backend + + _Renderer = backend._Renderer if backend is not None else None + reset_warnings(gallery_conf, fname) + # in case users have interactive mode turned on in matplotlibrc, + # turn it off here (otherwise the build can be very slow) + plt.ioff() + plt.rcParams["animation.embed_limit"] = 40.0 + plt.rcParams["figure.raise_window"] = False + # https://github.com/sphinx-gallery/sphinx-gallery/pull/1243#issue-2043332860 + plt.rcParams["animation.html"] = "html5" + # neo holds on to an exception, which in turn holds a stack frame, + # which will keep alive the global vars during SG execution + try: + import neo + + neo.io.stimfitio.STFIO_ERR = None + except Exception: + pass + gc.collect() + + # Agg does not call close_event so let's clean up on our own :( + # https://github.com/matplotlib/matplotlib/issues/18609 + mne.viz.ui_events._cleanup_agg() + assert len(mne.viz.ui_events._event_channels) == 0, list( + mne.viz.ui_events._event_channels + ) + + orig_when = when + when = f"mne/conf.py:Resetter.__call__:{when}:{fname}" + # Support stuff like + # MNE_SKIP_INSTANCE_ASSERTIONS="Brain,Plotter,BackgroundPlotter,vtkPolyData,_Renderer" make html-memory # noqa: E501 + # to just test MNEQtBrowser + skips = os.getenv("MNE_SKIP_INSTANCE_ASSERTIONS", "").lower() + prefix = "" + if skips not in ("true", "1", "all"): + prefix = "Clean " + skips = skips.split(",") + if "brain" not in skips: + _assert_no_instances(Brain, when) # calls gc.collect() + if Plotter is not None and "plotter" not in skips: + _assert_no_instances(Plotter, when) + if BackgroundPlotter is not None and "backgroundplotter" not in skips: + _assert_no_instances(BackgroundPlotter, when) + if vtkPolyData is not None and "vtkpolydata" not in skips: + _assert_no_instances(vtkPolyData, when) + if "_renderer" not in skips: + _assert_no_instances(_Renderer, when) + if MNEQtBrowser is not None and "mneqtbrowser" not in skips: + # Ensure any manual fig.close() events get properly handled + from mne_qt_browser._pg_figure import QApplication + + inst = QApplication.instance() + if inst is not None: + for _ in range(2): + inst.processEvents() + _assert_no_instances(MNEQtBrowser, when) + # This will overwrite some Sphinx printing but it's useful + # for memory timestamps + if os.getenv("SG_STAMP_STARTS", "").lower() == "true": + import psutil + + process = psutil.Process(os.getpid()) + mem = sizeof_fmt(process.memory_info().rss) + print(f"{prefix}{time.time() - t0:6.1f} s : {mem}".ljust(22)) + + if fname == "50_configure_mne.py": + # This messes with the config, so let's do so in a temp dir + if orig_when == "before": + fake_home = Path(_get_extra_data_path()) / "temp" + fake_home.mkdir(exist_ok=True, parents=True) + os.environ["_MNE_FAKE_HOME_DIR"] = str(fake_home) + else: + assert orig_when == "after" + to_del = Path(os.environ["_MNE_FAKE_HOME_DIR"]) + try: + (to_del / "mne-python.json").unlink() + except Exception: + pass + try: + to_del.rmdir() + except Exception: + pass + del os.environ["_MNE_FAKE_HOME_DIR"] + + +report_scraper = mne.report._ReportScraper() +mne_qt_browser_scraper = mne.viz._scraper._MNEQtBrowserScraper() +brain_scraper = mne.viz._brain._BrainScraper() +gui_scraper = mne.gui._GUIScraper() diff --git a/mne-python/source/doc/sphinxext/mne_substitutions.py b/mne-python/source/doc/sphinxext/mne_substitutions.py new file mode 100644 index 0000000000000000000000000000000000000000..df23dbc910397a6d1908cd9e1b2fa6fc6d9404d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/mne_substitutions.py @@ -0,0 +1,81 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from docutils import nodes +from docutils.parsers.rst import Directive +from docutils.statemachine import StringList + +from mne._fiff.pick import ( + _DATA_CH_TYPES_ORDER_DEFAULT, + _DATA_CH_TYPES_SPLIT, + _EYETRACK_CH_TYPES_SPLIT, + _PICK_TYPES_DATA_DICT, +) +from mne.defaults import DEFAULTS + + +class MNESubstitution(Directive): # noqa: D101 + has_content = False + required_arguments = 1 + final_argument_whitespace = True + + def run(self, **kwargs): # noqa: D102 + env = self.state.document.settings.env + if self.arguments[0] == "data channels list": + keys = list() + for key in _DATA_CH_TYPES_ORDER_DEFAULT: + if key in _DATA_CH_TYPES_SPLIT: + keys.append(key) + elif key not in ("meg", "fnirs") and _PICK_TYPES_DATA_DICT.get( + key, False + ): + keys.append(key) + rst = "- " + "\n- ".join( + f"``{repr(key)}``: **{DEFAULTS['titles'][key]}** " + f"(scaled by {DEFAULTS['scalings'][key]:g} to " + f"plot in *{DEFAULTS['units'][key]}*)" + for key in keys + ) + elif self.arguments[0] == "non-data channels list": + keys = list() + rst = "" + for key in _DATA_CH_TYPES_ORDER_DEFAULT: + if ( + not _PICK_TYPES_DATA_DICT.get(key, True) + or key in _EYETRACK_CH_TYPES_SPLIT + or key in ("ref_meg", "whitened") + ): + keys.append(key) + for key in keys: + if DEFAULTS["scalings"].get(key, False) and DEFAULTS["units"].get( + key, False + ): + rst += ( + f"- ``{repr(key)}``: **{DEFAULTS['titles'][key]}** " + f"(scaled by {DEFAULTS['scalings'][key]:g} to " + f"plot in *{DEFAULTS['units'][key]}*)\n" + ) + else: + rst += f"- ``{repr(key)}``: **{DEFAULTS['titles'][key]}**\n" + else: + raise self.error( + "MNE directive unknown in %s: %r" # noqa: UP031 + % ( + env.doc2path(env.docname, base=None), + self.arguments[0], + ) + ) + node = nodes.compound(rst) # General(Body), Element + content = StringList( + rst.split("\n"), + parent=self.content.parent, + parent_offset=self.content.parent_offset, + ) + self.state.nested_parse(content, self.content_offset, node) + return [node] + + +def setup(app): # noqa: D103 + app.add_directive("mne", MNESubstitution) + return {"version": "0.1", "parallel_read_safe": True, "parallel_write_safe": True} diff --git a/mne-python/source/doc/sphinxext/newcontrib_substitutions.py b/mne-python/source/doc/sphinxext/newcontrib_substitutions.py new file mode 100644 index 0000000000000000000000000000000000000000..85feae1ad89abcf762bdfc90a44059fff91e4f7e --- /dev/null +++ b/mne-python/source/doc/sphinxext/newcontrib_substitutions.py @@ -0,0 +1,27 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from docutils.nodes import reference, strong, target + + +def newcontrib_role(name, rawtext, text, lineno, inliner, options={}, content=[]): # noqa: B006 + """Create a role to highlight new contributors in changelog entries.""" + newcontrib = f"new contributor {text}" + alias_text = f" <{text}_>" + rawtext = f"`{newcontrib}{alias_text}`_" + refname = text.lower() + strong_node = strong(rawtext, newcontrib) + target_node = target(alias_text, refname=refname, names=[newcontrib]) + target_node.indirect_reference_name = text + options.update(refname=refname, name=newcontrib) + ref_node = reference("", "", strong_node, **options) + ref_node[0].rawsource = rawtext + inliner.document.note_indirect_target(target_node) + inliner.document.note_refname(ref_node) + return [ref_node, target_node], [] + + +def setup(app): + app.add_role("newcontrib", newcontrib_role) + return diff --git a/mne-python/source/doc/sphinxext/prs/1.json b/mne-python/source/doc/sphinxext/prs/1.json new file mode 100644 index 0000000000000000000000000000000000000000..faf866354a4c938af91122a1d7e66e83cc3364f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cc832c4711fd29382be9ca0fe892b0d9f1301c97", + "authors": [ + { + "n": "ellenlau", + "e": "ellenlau@umd.edu" + } + ], + "changes": { + "examples/inverse/plot_label_source_activations.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10.json b/mne-python/source/doc/sphinxext/prs/10.json new file mode 100644 index 0000000000000000000000000000000000000000..26ebc5cba10943558e74af08040b9ebeae2c55bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3b705d9973cd6e824f74226d1223387f4572453d", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/filter.py": { + "a": 199, + "d": 82 + }, + "mne/tests/test_filter.py": { + "a": 21, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1000.json b/mne-python/source/doc/sphinxext/prs/1000.json new file mode 100644 index 0000000000000000000000000000000000000000..d735617144edf105aeb02469927a170e5e0ea931 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1000.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "399d323ecc7360ec210775a3f2ba9769747bf140", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/edf/tests/test_edf.py": { + "a": 17, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10001.json b/mne-python/source/doc/sphinxext/prs/10001.json new file mode 100644 index 0000000000000000000000000000000000000000..d0ad9087382e3380669bb3a409162406bab08b84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10001.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "923e6dd6f7a83af91e9bfdfc42b21805a411a978", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 10, + "d": 8 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 21, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10002.json b/mne-python/source/doc/sphinxext/prs/10002.json new file mode 100644 index 0000000000000000000000000000000000000000..8ade4063cf0915fcda6506992ec8028eb5fc7d9e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10002.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9a305c1a8820d155b38bcacea0b773808ccebb30", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10003.json b/mne-python/source/doc/sphinxext/prs/10003.json new file mode 100644 index 0000000000000000000000000000000000000000..1728f8b0151ba0620b84b692034fdbbe20e53af2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10003.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "444075aefe9d4f907f1ab652e2841953d98334db", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/glossary.rst": { + "a": 11, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 4, + "d": 4 + }, + "mne/surface.py": { + "a": 3, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10004.json b/mne-python/source/doc/sphinxext/prs/10004.json new file mode 100644 index 0000000000000000000000000000000000000000..07e8f8288dbf96b29a1603db7bd1335a798e3ab4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10004.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "33aa10ec7604b1aabe1c6ef51b11f3638aa0a0f5", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10005.json b/mne-python/source/doc/sphinxext/prs/10005.json new file mode 100644 index 0000000000000000000000000000000000000000..addf33c2390cc9e5370725b10a382dcaa33a2533 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10005.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1df8a5f8863e12abbe05da2aa6b93edbcbcc1144", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/externals/pymatreader/pymatreader.py": { + "a": 2, + "d": 2 + }, + "mne/externals/pymatreader/utils.py": { + "a": 3, + "d": 5 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10007.json b/mne-python/source/doc/sphinxext/prs/10007.json new file mode 100644 index 0000000000000000000000000000000000000000..291abdad328d728ddb52c26b61890c61d15af6ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10007.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f71b98a3a082a79a89e0e5948813fbd7a27fdb66", + "authors": [ + { + "n": "Nikolai M Chapochnikov", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10008.json b/mne-python/source/doc/sphinxext/prs/10008.json new file mode 100644 index 0000000000000000000000000000000000000000..cd6408c333a54ea94a6b9163b49b245811db4b77 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10008.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8e2ca2aa8c3b667bdbb92fa2b74df7c7b39e524a", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report/js_and_css/report.js": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10009.json b/mne-python/source/doc/sphinxext/prs/10009.json new file mode 100644 index 0000000000000000000000000000000000000000..ffaa379869d9b09454ac1e808b8ac02a5517e158 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10009.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "47e15a8d78ac4315187322e7b2f8c99f5d5b4239", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 4, + "d": 6 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 3 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10013.json b/mne-python/source/doc/sphinxext/prs/10013.json new file mode 100644 index 0000000000000000000000000000000000000000..9700be860435d74573289b7e4c1336cde9b9f586 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10013.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5672f78b1e2bb3dd51fea1d30aa8f7a879d2ee38", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "mne/externals/pymatreader/pymatreader.py": { + "a": 6, + "d": 2 + }, + "mne/externals/pymatreader/utils.py": { + "a": 6, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10015.json b/mne-python/source/doc/sphinxext/prs/10015.json new file mode 100644 index 0000000000000000000000000000000000000000..578d26db57702b874e98a3e8bc5ee80e3b89b287 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10015.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "0ad069bbff3a1b6f380ce77b191c766eddc0a991", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 16 + }, + "mne/conftest.py": { + "a": 2, + "d": 11 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 9, + "d": 10 + }, + "mne/gui/_coreg.py": { + "a": 181, + "d": 84 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 8, + "d": 6 + }, + "mne/utils/check.py": { + "a": 18, + "d": 8 + }, + "mne/viz/_3d.py": { + "a": 39, + "d": 20 + }, + "mne/viz/backends/_abstract.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 5, + "d": 8 + }, + "mne/viz/backends/_pyvista.py": { + "a": 15, + "d": 17 + }, + "mne/viz/backends/_qt.py": { + "a": 3, + "d": 0 + }, + "mne/viz/backends/_utils.py": { + "a": 16, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "server_environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10017.json b/mne-python/source/doc/sphinxext/prs/10017.json new file mode 100644 index 0000000000000000000000000000000000000000..b45e5e035a46cc991a30406dea6b7d80fd680346 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10017.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e6db45db994313be3bc9d686d7bc830b33a186d1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10018.json b/mne-python/source/doc/sphinxext/prs/10018.json new file mode 100644 index 0000000000000000000000000000000000000000..d7d31472315b274e3060f87e24b10ebf15724085 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10018.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "54638887057a2cc771e108e44dd4a61b75de4933", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10019.json b/mne-python/source/doc/sphinxext/prs/10019.json new file mode 100644 index 0000000000000000000000000000000000000000..80ce048a3ce6e046d8f78e8b95780e729be12438 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10019.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "2791ba472a7a3cec6135b70441288384842bf6ff", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 3 + }, + "mne/annotations.py": { + "a": 205, + "d": 0 + }, + "mne/epochs.py": { + "a": 79, + "d": 208 + }, + "mne/io/constants.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 199, + "d": 68 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10020.json b/mne-python/source/doc/sphinxext/prs/10020.json new file mode 100644 index 0000000000000000000000000000000000000000..be72c500c0037f20d94bcd250f484fe8444d8a74 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10020.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "955f9149a56de39b4f51b94780e910a871e2efd3", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 9, + "d": 1 + }, + "doc/conf.py": { + "a": 27, + "d": 20 + }, + "doc/install/contributing.rst": { + "a": 56, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10021.json b/mne-python/source/doc/sphinxext/prs/10021.json new file mode 100644 index 0000000000000000000000000000000000000000..571e9808d18a8c3d71e3ad15ecf0a9330f6aed74 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10021.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4cab7e96262c44101b9d87c3d91a56010054cc83", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/surface.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10024.json b/mne-python/source/doc/sphinxext/prs/10024.json new file mode 100644 index 0000000000000000000000000000000000000000..da749aeb864025c9f459c8fe31f2de0b39ba680e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10024.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "57b9de61c1ba0386654cec0d95145ea35f40ca31", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/surface.py": { + "a": 22, + "d": 7 + }, + "mne/tests/test_surface.py": { + "a": 6, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10025.json b/mne-python/source/doc/sphinxext/prs/10025.json new file mode 100644 index 0000000000000000000000000000000000000000..d2070ac0cd029411bea4ccef9c2ea3f0b750b99b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10025.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ce29d3e402cc390e51c16a97f9d2ff27a205147b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 7, + "d": 3 + }, + "tools/circleci_dependencies.sh": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10026.json b/mne-python/source/doc/sphinxext/prs/10026.json new file mode 100644 index 0000000000000000000000000000000000000000..df420a4bccac30568ff1bb1c1211127f9f813e95 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10026.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3722dd8772941fd1502ea57ec8390fb875156e31", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10027.json b/mne-python/source/doc/sphinxext/prs/10027.json new file mode 100644 index 0000000000000000000000000000000000000000..7f742c3dc85c71b3e974643190d43eb4ff426068 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10027.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3e87a691b07ef14dd3705054ecc789a1fa6f18b6", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10030.json b/mne-python/source/doc/sphinxext/prs/10030.json new file mode 100644 index 0000000000000000000000000000000000000000..ff4c3b38564f3731ac4b331a31099d2332799ecb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10030.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ead37bb15e89eff45d0813183867a1807f44aa7f", + "authors": [ + { + "n": "Julia Guiomar Niso Galán", + "e": null + } + ], + "changes": { + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10031.json b/mne-python/source/doc/sphinxext/prs/10031.json new file mode 100644 index 0000000000000000000000000000000000000000..a3ed7256fe7de176314827e1fd0a69b9be6fe3aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10031.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "98b01534297e38ec6e876d3753f04bc7e82473e0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10036.json b/mne-python/source/doc/sphinxext/prs/10036.json new file mode 100644 index 0000000000000000000000000000000000000000..da105b1b376d7c117c11d0c5a6604d2ff346d2b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10036.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b5f48116920871e50aa9f6e21d5046eafc63100e", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10038.json b/mne-python/source/doc/sphinxext/prs/10038.json new file mode 100644 index 0000000000000000000000000000000000000000..7fde83cfbbcb4ec40b2b4a6fbf40461a5771ea97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10038.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0789b7dade297a7e5cae10a343a870ed260ab9a0", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/datasets/__init__.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10039.json b/mne-python/source/doc/sphinxext/prs/10039.json new file mode 100644 index 0000000000000000000000000000000000000000..b61cbd71b6558cdb7e3754b090ead9577386ef34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10039.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "602958dc4bb7094a770671d78777c2d90cc266bb", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 6, + "d": 6 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1004.json b/mne-python/source/doc/sphinxext/prs/1004.json new file mode 100644 index 0000000000000000000000000000000000000000..25060b67cc7f78cf8a5f6ad5fecf687088c4454b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1004.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1af793825ae60e68c2845c853c5c9a1bffc3628b", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/epochs.py": { + "a": 13, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10040.json b/mne-python/source/doc/sphinxext/prs/10040.json new file mode 100644 index 0000000000000000000000000000000000000000..458de624038e73c7f63603b34fe2436b3026dd82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10040.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a3d20ad4a003bbb873bec1237d4941c9498fe1ab", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 5, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10041.json b/mne-python/source/doc/sphinxext/prs/10041.json new file mode 100644 index 0000000000000000000000000000000000000000..93f088a4b45c88354ff249357f16419624bd8542 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10041.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "34ca144db4adab33d576bb60db1d7e8661b1082f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 0, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10044.json b/mne-python/source/doc/sphinxext/prs/10044.json new file mode 100644 index 0000000000000000000000000000000000000000..d0c2a02d8b166ad3de19420046f73a111267adff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10044.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f58eb9d55c21f20ba56016a2e06a05d2997b5faa", + "authors": [ + { + "n": "Jan Sosulski", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 5, + "d": 1 + }, + "mne/evoked.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10045.json b/mne-python/source/doc/sphinxext/prs/10045.json new file mode 100644 index 0000000000000000000000000000000000000000..5d235361685101cd6139d041e2d520e473330811 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10045.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b22031065418396b131676e7ef472acfcb123002", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 6, + "d": 3 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10047.json b/mne-python/source/doc/sphinxext/prs/10047.json new file mode 100644 index 0000000000000000000000000000000000000000..f83191c4697afd2eb0f41f7817e86146757aee57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10047.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6da538f2ac9f4d922a499ff407885dae08f1b6f2", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/config.py": { + "a": 4, + "d": 4 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10048.json b/mne-python/source/doc/sphinxext/prs/10048.json new file mode 100644 index 0000000000000000000000000000000000000000..3ff42a6491c757b8d1713d9fe8809d7eab0135a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10048.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "327777cd77b7ff41d26ebcc334161bbb07bc5db3", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 10, + "d": 9 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 11 + }, + "mne/viz/backends/_utils.py": { + "a": 57, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 4 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10050.json b/mne-python/source/doc/sphinxext/prs/10050.json new file mode 100644 index 0000000000000000000000000000000000000000..9bd20f416be077d82bde7dd1f1d0765beb14ffbe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10050.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "07ef4d698ff60c1e1f04b3d0566bec6250fa0e90", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10051.json b/mne-python/source/doc/sphinxext/prs/10051.json new file mode 100644 index 0000000000000000000000000000000000000000..8e7d4b5d8dfbb2b97bfa5366b49b6bc65ceb8e78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10051.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0a63648b6596ece5afe1448bacd32658b27a7fdc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 28 + }, + "mne/utils/docs.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10052.json b/mne-python/source/doc/sphinxext/prs/10052.json new file mode 100644 index 0000000000000000000000000000000000000000..cd5673a4b090502f2892e60d3628bf2a9f9dddb0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10052.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d9862fdfa76dcace92d8749df5277b6388981fb0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10054.json b/mne-python/source/doc/sphinxext/prs/10054.json new file mode 100644 index 0000000000000000000000000000000000000000..70491326c918fc5d9cde12dcda54fb417fd34ddd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10054.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c45920796deabdd95f0a8ec40e5184605de85cc7", + "authors": [ + { + "n": "Etienne de Montalivet", + "e": "etienne.demontalivet@protonmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 6, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10056.json b/mne-python/source/doc/sphinxext/prs/10056.json new file mode 100644 index 0000000000000000000000000000000000000000..2d617764e3c700a4a3d928888a8bca48909acdc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10056.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "10b537c26573d999597500a854c602d7fa81688c", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/glossary.rst": { + "a": 22, + "d": 10 + }, + "mne/annotations.py": { + "a": 3, + "d": 4 + }, + "mne/epochs.py": { + "a": 4, + "d": 2 + }, + "mne/event.py": { + "a": 32, + "d": 30 + }, + "mne/io/base.py": { + "a": 6, + "d": 5 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 12 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 23, + "d": 20 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10058.json b/mne-python/source/doc/sphinxext/prs/10058.json new file mode 100644 index 0000000000000000000000000000000000000000..6e3fd7e7c8d770649549d8cfe1957b9d6b7138cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10058.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "eff12c448bea2d9acb1c9483f05ec32ba24ffae1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/export/tests/test_export.py": { + "a": 12, + "d": 17 + }, + "mne/io/edf/edf.py": { + "a": 81, + "d": 51 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 37, + "d": 14 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10061.json b/mne-python/source/doc/sphinxext/prs/10061.json new file mode 100644 index 0000000000000000000000000000000000000000..b30dfb02dd864548fd9de49a9fdeb09b5a0af32a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10061.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1514d0c72e4f0c45b00af9138925512f52640ea9", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10064.json b/mne-python/source/doc/sphinxext/prs/10064.json new file mode 100644 index 0000000000000000000000000000000000000000..1d0b8cb1a2f4bf18e695be78218fd97963a49538 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10064.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ffdac14db914c7c810e93cf256c020e6e55b487f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 6, + "d": 3 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10065.json b/mne-python/source/doc/sphinxext/prs/10065.json new file mode 100644 index 0000000000000000000000000000000000000000..ca3c59f48a75d3eb3fd533df6b2a9007dc85d3e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10065.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "113dafb58f77879229ba7debe0bcb2295178b25c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10066.json b/mne-python/source/doc/sphinxext/prs/10066.json new file mode 100644 index 0000000000000000000000000000000000000000..fd3eb626a2b0e4f40b6901f9fcaa08e2e1c5eac1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10066.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7b5c61cd951e5071170995fa885151711e8f48c0", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/0.24.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10067.json b/mne-python/source/doc/sphinxext/prs/10067.json new file mode 100644 index 0000000000000000000000000000000000000000..c554c537b0ae760a5ef75cb8d6ee28956c98a679 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10067.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "151b8a6cf92524d7e97ea63592b6d3707c38e2b4", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/annotate_nan.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 16, + "d": 9 + }, + "mne/preprocessing/flat.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 33, + "d": 13 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10068.json b/mne-python/source/doc/sphinxext/prs/10068.json new file mode 100644 index 0000000000000000000000000000000000000000..d04ea0d8f4999954f1720136442b2940d1b13653 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10068.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "00f27916b1eb865d33c6dcb757ef5412c7a6bcbb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10069.json b/mne-python/source/doc/sphinxext/prs/10069.json new file mode 100644 index 0000000000000000000000000000000000000000..4553555339bf46956d687c74bc0afe0b9060281e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10069.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "05f0358927404671a600e2fc8e35b30b0cd93f19", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 57, + "d": 64 + }, + "doc/conf.py": { + "a": 19, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 12 + }, + "tutorials/clinical/20_seeg.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1007.json b/mne-python/source/doc/sphinxext/prs/1007.json new file mode 100644 index 0000000000000000000000000000000000000000..fdcc15a4fa31f38be081add86dfff27ebb509af0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1007.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e0cac66a4840087cc624c081312f05ae4f37a244", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/layouts/layout.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10071.json b/mne-python/source/doc/sphinxext/prs/10071.json new file mode 100644 index 0000000000000000000000000000000000000000..bde1bf15b5cf7a13f7148f7f5057e3feab2c942d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10071.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "3aad5b1aa7f74ea0f8d927664d8b844afbc40cea", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 0, + "d": 1 + }, + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 4, + "d": 4 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 7, + "d": 7 + }, + "examples/inverse/covariance_whitening_dspm.py": { + "a": 0, + "d": 188 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 5, + "d": 1 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/mne_cov_power.py": { + "a": 10, + "d": 12 + }, + "examples/inverse/vector_mne_solution.py": { + "a": 7, + "d": 4 + }, + "examples/preprocessing/ica_comparison.py": { + "a": 2, + "d": 3 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 8, + "d": 37 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 6, + "d": 8 + }, + "mne/transforms.py": { + "a": 2, + "d": 0 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 6, + "d": 6 + }, + "tutorials/clinical/20_seeg.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 6, + "d": 9 + }, + "tutorials/forward/30_forward.py": { + "a": 16, + "d": 12 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 5, + "d": 5 + }, + "tutorials/intro/70_report.py": { + "a": 30, + "d": 25 + }, + "tutorials/inverse/40_mne_fixed_free.py": { + "a": 4, + "d": 3 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 7, + "d": 5 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 7, + "d": 6 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 13, + "d": 9 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 6, + "d": 6 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 10, + "d": 8 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 13, + "d": 13 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 4, + "d": 1 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 9, + "d": 6 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 9, + "d": 9 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10072.json b/mne-python/source/doc/sphinxext/prs/10072.json new file mode 100644 index 0000000000000000000000000000000000000000..0f3097494cf0a6c6124720a86b6ff775c761e6cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10072.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "963eea23740f0e697ac03dc1fd671ee91e15c162", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10073.json b/mne-python/source/doc/sphinxext/prs/10073.json new file mode 100644 index 0000000000000000000000000000000000000000..f4da66e3bfcb9d28345b31ffebe8b016978bae07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10073.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8eba56032b93e2f51030c4ddcd28c9ae3addafb1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10074.json b/mne-python/source/doc/sphinxext/prs/10074.json new file mode 100644 index 0000000000000000000000000000000000000000..1cb7df6d30be541c8d045a20cce20a1e8bf1eebf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10074.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "59ca238896e275e0f97f2c81fc9bdd18f31066b1", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/colormap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10075.json b/mne-python/source/doc/sphinxext/prs/10075.json new file mode 100644 index 0000000000000000000000000000000000000000..b3b964d185dbcf87ba22122d5e8ed53b74622478 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10075.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4128974b2428826b89c4b25c2f49bfac8132b941", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/annotations.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10076.json b/mne-python/source/doc/sphinxext/prs/10076.json new file mode 100644 index 0000000000000000000000000000000000000000..e94bc1f2d7188349e3455b71bed138b8bc12e7f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10076.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "01da5a32ac1a80cf0cc42684f154597595608ea0", + "authors": [ + { + "n": "Jan Zerfowski", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 1 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10077.json b/mne-python/source/doc/sphinxext/prs/10077.json new file mode 100644 index 0000000000000000000000000000000000000000..ee42b5f064ac2f51292e7660d55950646533a2ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10077.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3fd23c67578a8424e59df17b9026bddb0409b538", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/morph.py": { + "a": 17, + "d": 8 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 34, + "d": 0 + }, + "mne/utils/tests/test_numerics.py": { + "a": 50, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10078.json b/mne-python/source/doc/sphinxext/prs/10078.json new file mode 100644 index 0000000000000000000000000000000000000000..e47acf688a2e5ced88c8d01da484e523e57ffaa8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10078.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f2ae58f6bfdbabf0aaa06a6f650124f9b2788581", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 24, + "d": 13 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 2, + "d": 2 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 2, + "d": 2 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1008.json b/mne-python/source/doc/sphinxext/prs/1008.json new file mode 100644 index 0000000000000000000000000000000000000000..d98851a0f639846c2603152ff502d4eb5f4adefb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1008.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a1ac7575dc528d27243b5ed6dab354569df98a02", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/layouts/KIT-157.lout": { + "a": 158, + "d": 0 + }, + "mne/layouts/layout.py": { + "a": 4, + "d": 0 + }, + "mne/layouts/tests/test_layout.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10080.json b/mne-python/source/doc/sphinxext/prs/10080.json new file mode 100644 index 0000000000000000000000000000000000000000..7622cce359d36b287055090ca813825d5001ea49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10080.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8954c3711b57dc1b90a8079c278384ba684ed17f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10082.json b/mne-python/source/doc/sphinxext/prs/10082.json new file mode 100644 index 0000000000000000000000000000000000000000..d825a31cf33316511b07dffd0d0f84a61fe034b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10082.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f3c90675295e411d0c4242f2eeeb2a75b64dead6", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/templates/header.html": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10084.json b/mne-python/source/doc/sphinxext/prs/10084.json new file mode 100644 index 0000000000000000000000000000000000000000..efdf182d21d8aa57fa05ac2613a36f55c5fc91db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10084.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c1cbc784f7c44abfa33d728528c319f4a468dc0c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 5, + "d": 1 + }, + "mne/decoding/mixin.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10085.json b/mne-python/source/doc/sphinxext/prs/10085.json new file mode 100644 index 0000000000000000000000000000000000000000..34d8a3411bd3d900f7d27523a0cf54cab738aac7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10085.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "269527169e08f953caf4675c7960eae93f5bc307", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 61, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 67, + "d": 12 + }, + "mne/viz/backends/_abstract.py": { + "a": 0, + "d": 4 + }, + "mne/viz/backends/_notebook.py": { + "a": 0, + "d": 3 + }, + "mne/viz/backends/_qt.py": { + "a": 0, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10086.json b/mne-python/source/doc/sphinxext/prs/10086.json new file mode 100644 index 0000000000000000000000000000000000000000..3a249a0e704019de9ef5c9543e6250dacd3f69df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10086.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d7202b4866c88c6989a548e268b87113ac69e212", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10087.json b/mne-python/source/doc/sphinxext/prs/10087.json new file mode 100644 index 0000000000000000000000000000000000000000..940d0c2154d2d69c8216fb86884b84fdf4f6c6d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10087.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9dff61616bfc9ca411df578a4f3b963de8ac023c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10089.json b/mne-python/source/doc/sphinxext/prs/10089.json new file mode 100644 index 0000000000000000000000000000000000000000..e19cdfd95a0e0c8115eddb78f7ba23a50bf27618 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10089.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d7c8fe391ac6c0b01b66d7e328689f3dbe9a51dd", + "authors": [ + { + "n": "Sen-wen DENG", + "e": null + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 29, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10091.json b/mne-python/source/doc/sphinxext/prs/10091.json new file mode 100644 index 0000000000000000000000000000000000000000..09b12d89452d7981fabc956657b88f5e6d50379d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10091.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "8db9aac060fe736438933efd0a421a866853727b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 4, + "d": 5 + }, + "mne/cov.py": { + "a": 2, + "d": 3 + }, + "mne/datasets/_fetch.py": { + "a": 3, + "d": 3 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 4, + "d": 5 + }, + "mne/externals/tqdm/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 2, + "d": 3 + }, + "mne/utils/_testing.py": { + "a": 5, + "d": 6 + }, + "mne/utils/tests/test_linalg.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_scraper.py": { + "a": 5, + "d": 4 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 7 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10093.json b/mne-python/source/doc/sphinxext/prs/10093.json new file mode 100644 index 0000000000000000000000000000000000000000..e6997b069b32d3b969df8c7397b5606b29fc3e97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10093.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "59af71a7e37e8b6af80de28fd3d1ec344fc38a7b", + "authors": [ + { + "n": "Adina Wagner", + "e": "adina.wagner@t-online.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10095.json b/mne-python/source/doc/sphinxext/prs/10095.json new file mode 100644 index 0000000000000000000000000000000000000000..ea0bbad427d988cc8514e58e2ed2eaf45104a285 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10095.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fa0e8d951e7fff82b7a4402dd858d18016f69a64", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + }, + "mne/utils/check.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10096.json b/mne-python/source/doc/sphinxext/prs/10096.json new file mode 100644 index 0000000000000000000000000000000000000000..4a1ae1bd60b22981f774a0479fe28c0b823bab08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10096.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "ae0ca34a4a53d0a307381833bc75c4b536d5ea54", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 0, + "d": 6 + }, + "mne/cov.py": { + "a": 2, + "d": 10 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 3, + "d": 11 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 0, + "d": 7 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 0, + "d": 4 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 1, + "d": 3 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 8 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 6 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10097.json b/mne-python/source/doc/sphinxext/prs/10097.json new file mode 100644 index 0000000000000000000000000000000000000000..d873fa958f857868cc719777f025d6153191abb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10097.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "12833cebf689840f4e339f78e27466d256e36c37", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10098.json b/mne-python/source/doc/sphinxext/prs/10098.json new file mode 100644 index 0000000000000000000000000000000000000000..e20d80ef0cc7acb47b4dde10b821a6cbc8ceaebf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10098.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a3066f6eb3730d13d2dce632ff6cb5d4870fbe7f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_mpl_figure.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 8, + "d": 0 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1010.json b/mne-python/source/doc/sphinxext/prs/1010.json new file mode 100644 index 0000000000000000000000000000000000000000..6f15b761ad2bf49ca486c77c13632e4ca5cd1a27 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1010.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "948d9135925f6769f151151ea870592a41af6ada", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/layouts/layout.py": { + "a": 3, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10100.json b/mne-python/source/doc/sphinxext/prs/10100.json new file mode 100644 index 0000000000000000000000000000000000000000..98297a44d31a280c7c9f3e0731e26b16b9a66840 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10100.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e8f71755fc88b4d6a368b0b3e12c1d4ac1c1f3bc", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/backends/renderer.py": { + "a": 6, + "d": 1 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 3 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10102.json b/mne-python/source/doc/sphinxext/prs/10102.json new file mode 100644 index 0000000000000000000000000000000000000000..4ac2327131da33b20166f642d1cb4c128cd2bcc1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10102.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e79924cdf226782763acc46c75f7aede06456b32", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 21, + "d": 15 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10108.json b/mne-python/source/doc/sphinxext/prs/10108.json new file mode 100644 index 0000000000000000000000000000000000000000..b8ae56b6f40a4cc16557073c04a0a63c71833e4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10108.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f0abc4c332b265355f39ec230539e037d23cd752", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "server_environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10109.json b/mne-python/source/doc/sphinxext/prs/10109.json new file mode 100644 index 0000000000000000000000000000000000000000..b4800fad6b4c72378faded71f69df342181ded1e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10109.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6a265839876a2c4205a557ec387edda10cc237b4", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 0 + }, + "mne/report/report.py": { + "a": 19, + "d": 8 + }, + "mne/utils/docs.py": { + "a": 23, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 11 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 17 + }, + "mne/viz/utils.py": { + "a": 20, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10110.json b/mne-python/source/doc/sphinxext/prs/10110.json new file mode 100644 index 0000000000000000000000000000000000000000..477104ca02a43852bddf4b605d56514bc0f8cb42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10110.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8333d703dc2c9feb8b81e2585294c77deeca4ae4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/morph.py": { + "a": 8, + "d": 7 + }, + "mne/tests/test_morph.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10111.json b/mne-python/source/doc/sphinxext/prs/10111.json new file mode 100644 index 0000000000000000000000000000000000000000..3fdd74cec704cde6f1ed1da14bf44dc8fea88c1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10111.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b7daa3603d75062f713c84707da3a940c7de7266", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + "doc/overview/people.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10112.json b/mne-python/source/doc/sphinxext/prs/10112.json new file mode 100644 index 0000000000000000000000000000000000000000..219e0d7f8ea2d97b885af012fa6157614cb4fc93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10112.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f19fe3cd0089101f209b968f1fe66a2a8eae6c1f", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 17, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 32, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10113.json b/mne-python/source/doc/sphinxext/prs/10113.json new file mode 100644 index 0000000000000000000000000000000000000000..933836381946a2107856fe042d93c6ddf3ac23ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10113.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "82d32b5d90e156b915084251a0be29bd34419c01", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/overview/people.rst": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10114.json b/mne-python/source/doc/sphinxext/prs/10114.json new file mode 100644 index 0000000000000000000000000000000000000000..898e8ba49c9349479942a176ce04bd3695375c55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10114.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4faf87f4ac2deb133a40554df02f0596046611a7", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "mne/report/report.py": { + "a": 26, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10115.json b/mne-python/source/doc/sphinxext/prs/10115.json new file mode 100644 index 0000000000000000000000000000000000000000..3f8451a6a1e6c0a6b7781435bcab3facc35bab18 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10115.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9917316f4e376d3c6f3d7cff4dafd237dba64bbf", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 21, + "d": 12 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10116.json b/mne-python/source/doc/sphinxext/prs/10116.json new file mode 100644 index 0000000000000000000000000000000000000000..d302ace4f28f4bd498aefcd503058235eb5d21ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10116.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9b3676d991220edfad86edc9cbd97cea032c5191", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 45, + "d": 32 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10117.json b/mne-python/source/doc/sphinxext/prs/10117.json new file mode 100644 index 0000000000000000000000000000000000000000..ed53506500d0d4177c85beab4fbea95eba4742d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10117.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a885741c16abc21b5fccba85a3650a03f87e5e8f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 294, + "d": 100 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 20, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10118.json b/mne-python/source/doc/sphinxext/prs/10118.json new file mode 100644 index 0000000000000000000000000000000000000000..d3c8db91209b0dddc6c2ef203b182b31d1767645 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10118.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "a9b63658006855ad67512eb6dfde8bbaf095acd8", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 8, + "d": 0 + }, + "mne/io/base.py": { + "a": 4, + "d": 1 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 6, + "d": 1 + }, + "mne/preprocessing/annotate_nan.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 16, + "d": 17 + }, + "mne/preprocessing/flat.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/tests/test_annotate_nan.py": { + "a": 53, + "d": 0 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 54, + "d": 4 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 15, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10119.json b/mne-python/source/doc/sphinxext/prs/10119.json new file mode 100644 index 0000000000000000000000000000000000000000..ba396378ea99e8c0cd8253ee1dd77d770588002c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10119.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "16498afc8b6a92a6f0e5754c71c6d64ed62c1ad2", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 88, + "d": 28 + }, + "mne/report/tests/test_report.py": { + "a": 12, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 4, + "d": 2 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1012.json b/mne-python/source/doc/sphinxext/prs/1012.json new file mode 100644 index 0000000000000000000000000000000000000000..e0a449c1ae4c592e02bccf181bbee7290c25929e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1012.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "673ee9af04d3e347b7d3c63fcbfd14680e0c49c9", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/fiff/evoked.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10120.json b/mne-python/source/doc/sphinxext/prs/10120.json new file mode 100644 index 0000000000000000000000000000000000000000..b8c6a08bdebb3433d93c608ad2c8de749010d8d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10120.json @@ -0,0 +1,195 @@ +{ + "merge_commit_sha": "a8dbd5f4158f3bfaeb0e1b46576de18514f34219", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 6 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 3, + "d": 2 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/commands/tests/test_commands.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 11, + "d": 9 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 13, + "d": 13 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 4, + "d": 2 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 4, + "d": 4 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 22, + "d": 16 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_reference.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_what.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 18, + "d": 19 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 6, + "d": 4 + }, + "mne/tests/test_annotations.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 6, + "d": 5 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 5, + "d": 6 + }, + "mne/tests/test_label.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_line_endings.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_morph.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_morph_map.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 7, + "d": 6 + }, + "mne/tests/test_source_space.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_surface.py": { + "a": 4, + "d": 3 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 2, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 9, + "d": 22 + }, + "mne/utils/tests/test_linalg.py": { + "a": 3, + "d": 2 + }, + "mne/utils/tests/test_testing.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 5, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 5 + }, + "mne/viz/tests/test_topo.py": { + "a": 3, + "d": 2 + }, + "tools/azure_dependencies.sh": { + "a": 3, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 13, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10122.json b/mne-python/source/doc/sphinxext/prs/10122.json new file mode 100644 index 0000000000000000000000000000000000000000..557b4f0f903c81e1cd5f2c8c7ee2b993c7d25f20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10122.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e0aa5feb7b2dcb6704242fd9ad4b5fd1e7b97b0d", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 9, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10123.json b/mne-python/source/doc/sphinxext/prs/10123.json new file mode 100644 index 0000000000000000000000000000000000000000..930bc1903bc76f7de089718d7d6888d3a9d3146a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10123.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c49ddf168c74db8a6211489ac8de9be6dbe6708e", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "tutorials/io/30_reading_fnirs_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10125.json b/mne-python/source/doc/sphinxext/prs/10125.json new file mode 100644 index 0000000000000000000000000000000000000000..489c7e272269889234963d0ba1dbe734debff284 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10125.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "575193c1b189733071a0623bf436c08daeab671c", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 13, + "d": 10 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 28, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10126.json b/mne-python/source/doc/sphinxext/prs/10126.json new file mode 100644 index 0000000000000000000000000000000000000000..bc3d4e9229a2ca145118e39b5111a8171053d0fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10126.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7133478275cb3737d56e6381995246a5abdfa3fc", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 52, + "d": 10 + }, + "tutorials/intro/70_report.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10127.json b/mne-python/source/doc/sphinxext/prs/10127.json new file mode 100644 index 0000000000000000000000000000000000000000..66c26c2aa347dff7248853fe97f2f43d351605c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10127.json @@ -0,0 +1,143 @@ +{ + "merge_commit_sha": "fd4f692f142ed8107cc816c3f60cfb3b4509e477", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 12, + "d": 8 + }, + "mne/bem.py": { + "a": 4, + "d": 7 + }, + "mne/channels/montage.py": { + "a": 5, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 16, + "d": 16 + }, + "mne/epochs.py": { + "a": 2, + "d": 3 + }, + "mne/event.py": { + "a": 14, + "d": 16 + }, + "mne/evoked.py": { + "a": 16, + "d": 12 + }, + "mne/forward/forward.py": { + "a": 6, + "d": 3 + }, + "mne/io/_digitization.py": { + "a": 12, + "d": 5 + }, + "mne/io/base.py": { + "a": 16, + "d": 17 + }, + "mne/io/meas_info.py": { + "a": 9, + "d": 25 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/write.py": { + "a": 9, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 13, + "d": 9 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 3, + "d": 3 + }, + "mne/morph_map.py": { + "a": 6, + "d": 5 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 11 + }, + "mne/proj.py": { + "a": 12, + "d": 7 + }, + "mne/source_estimate.py": { + "a": 55, + "d": 50 + }, + "mne/source_space.py": { + "a": 11, + "d": 7 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_event.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 18, + "d": 16 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 12, + "d": 6 + }, + "mne/time_frequency/csd.py": { + "a": 12, + "d": 4 + }, + "mne/transforms.py": { + "a": 8, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10129.json b/mne-python/source/doc/sphinxext/prs/10129.json new file mode 100644 index 0000000000000000000000000000000000000000..4375241c5ff98236d55756b0d9b2603ad4d175c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10129.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "74c3965088eb3f74e650d6191b834be0601cae1f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 67, + "d": 24 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10130.json b/mne-python/source/doc/sphinxext/prs/10130.json new file mode 100644 index 0000000000000000000000000000000000000000..2b31597befa831c9928c17f460e2c193ea2f30b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10130.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c3245352f4ccf8cf278baa1b911b4853c06b3dcf", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10132.json b/mne-python/source/doc/sphinxext/prs/10132.json new file mode 100644 index 0000000000000000000000000000000000000000..e455c3a67b209fd0712b5ed289828a64d27630a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10132.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0126591383729475326714e3edc0360cdbbe92e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/surface.py": { + "a": 8, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_surface.py": { + "a": 6, + "d": 7 + }, + "mne/transforms.py": { + "a": 14, + "d": 6 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10133.json b/mne-python/source/doc/sphinxext/prs/10133.json new file mode 100644 index 0000000000000000000000000000000000000000..d79a26cabc3492eac64fbf3bcaf3dd5d66b7897a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10133.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3ccb227367560803f91d3f19251a1531e3dde6e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/linux_pip.yml": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10134.json b/mne-python/source/doc/sphinxext/prs/10134.json new file mode 100644 index 0000000000000000000000000000000000000000..c954bb82b373946394faefb737ebfd2c0a1c30e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10134.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "61c5c51cacd998cde4bb0ba350738619a4bcee72", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 9, + "d": 13 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/gh_substitutions.py": { + "a": 5, + "d": 5 + }, + "doc/sphinxext/newcontrib_substitutions.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10135.json b/mne-python/source/doc/sphinxext/prs/10135.json new file mode 100644 index 0000000000000000000000000000000000000000..352f5ed15a892500eb315766eee9726e50469dc6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10135.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ad5ab0ab44981694409abe6d06da44b599f079ee", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/defaults.py": { + "a": 7, + "d": 1 + }, + "mne/report/report.py": { + "a": 16, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10136.json b/mne-python/source/doc/sphinxext/prs/10136.json new file mode 100644 index 0000000000000000000000000000000000000000..c2de34ea5295bf0f750966f970c6059af3294e23 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10136.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "410ebf1856fee8f433da865f0ca7e4ef62e30260", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1014.json b/mne-python/source/doc/sphinxext/prs/1014.json new file mode 100644 index 0000000000000000000000000000000000000000..f044a18934167b4b8d0b816a95821cc0920c29e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1014.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "99a492bca5cfb65177e7167e09822d373e6429bf", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 13, + "d": 1 + }, + "examples/plot_field_lines.py": { + "a": 0, + "d": 88 + }, + "examples/plot_meg_eeg_fields_3d.py": { + "a": 36, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/channels.py": { + "a": 9, + "d": 4 + }, + "mne/fiff/evoked.py": { + "a": 25, + "d": 0 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 178, + "d": 69 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 39, + "d": 18 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_viz.py": { + "a": 35, + "d": 11 + }, + "mne/viz.py": { + "a": 113, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10140.json b/mne-python/source/doc/sphinxext/prs/10140.json new file mode 100644 index 0000000000000000000000000000000000000000..e5eb0eefb9e6b1a42a47247b80825ce646967dde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10140.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3d4a4f66232448de542ac076df7b57115644978a", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/io/base.py": { + "a": 4, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 2 + }, + "mne/utils/dataframe.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10141.json b/mne-python/source/doc/sphinxext/prs/10141.json new file mode 100644 index 0000000000000000000000000000000000000000..4ad5e86b73ae599249c0596b95bd1c9cd5fb9426 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10141.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ea5e19e62382b48d0779907e626e4671d920149e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 1, + "d": 2 + }, + "mne/gui/_coreg.py": { + "a": 33, + "d": 4 + }, + "mne/viz/backends/_abstract.py": { + "a": 8, + "d": 6 + }, + "mne/viz/backends/_notebook.py": { + "a": 13, + "d": 7 + }, + "mne/viz/backends/_qt.py": { + "a": 18, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10142.json b/mne-python/source/doc/sphinxext/prs/10142.json new file mode 100644 index 0000000000000000000000000000000000000000..d9b90d1408f6440bdba188cc4f9a1b919cfa2b02 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10142.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b65a428c6cd28505735601b2c607a52ea1d98f21", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 3 + }, + "tutorials/intro/70_report.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10143.json b/mne-python/source/doc/sphinxext/prs/10143.json new file mode 100644 index 0000000000000000000000000000000000000000..75da123cf7fdf5b9586165e949a6179cda25d5a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10143.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "a2e3080c2b64f7a5242c1ecb9675aaef1874db4b", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/0.21.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/annotate_amplitude.py": { + "a": 254, + "d": 0 + }, + "mne/preprocessing/flat.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/tests/test_annotate_amplitude.py": { + "a": 394, + "d": 0 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 12, + "d": 5 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 2 + }, + "tools/setup_xvfb.sh": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10144.json b/mne-python/source/doc/sphinxext/prs/10144.json new file mode 100644 index 0000000000000000000000000000000000000000..8c80bdb212ae7eb63bf007387a4b55a84a9d3bff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10144.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "077d311204efb0f947a8fbe57419ced0fc1769ff", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 24, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1015.json b/mne-python/source/doc/sphinxext/prs/1015.json new file mode 100644 index 0000000000000000000000000000000000000000..d19b51cfc8b814cf3eefd853fd63aafa9a0cee50 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1015.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e5f41bfca6881ab6f0bec8ba2c148ee2793c9c0e", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 9, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10151.json b/mne-python/source/doc/sphinxext/prs/10151.json new file mode 100644 index 0000000000000000000000000000000000000000..7dabca9ed09e2c4cd68ec602fadd5e5712f9f4c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10151.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fecf5411d28f47dcb4ff379976a1b4813edc45a9", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 21, + "d": 0 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10152.json b/mne-python/source/doc/sphinxext/prs/10152.json new file mode 100644 index 0000000000000000000000000000000000000000..66fd69bfdffa3360a27e5fe5d761fc07f3ad57e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10152.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e3fec3ff414017a93b4d7ae7d6698c06b22ed3b4", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/epochs.py": { + "a": 8, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10153.json b/mne-python/source/doc/sphinxext/prs/10153.json new file mode 100644 index 0000000000000000000000000000000000000000..a1fb91ac0d0c039c724e185c33307bccf26e4639 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10153.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "433a4e19bb15b061c17a3fee3e9f8e8f6d8ea229", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 3, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10154.json b/mne-python/source/doc/sphinxext/prs/10154.json new file mode 100644 index 0000000000000000000000000000000000000000..f8f2d99aa4995b81fa806c272045a64480057e2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10154.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f37ef8e4ae07cd1c10118cb6e64e904333920924", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "figures/Figure_6.png": { + "a": 0, + "d": 0 + }, + "figures/circle.png": { + "a": 0, + "d": 0 + }, + "figures/ecog.png": { + "a": 0, + "d": 0 + }, + "figures/electrode.png": { + "a": 0, + "d": 0 + }, + "paper.bib": { + "a": 58, + "d": 0 + }, + "paper.md": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10155.json b/mne-python/source/doc/sphinxext/prs/10155.json new file mode 100644 index 0000000000000000000000000000000000000000..00079f3c56c105aa5dc260e778aa48f5ea2fc3fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10155.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "dfe7f7e950109f9ee7346fe8bd77d7de18c8c726", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/install/index.rst": { + "a": 2, + "d": 0 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 5, + "d": 4 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 41, + "d": 25 + }, + "tutorials/clinical/20_seeg.py": { + "a": 3, + "d": 0 + }, + "tutorials/clinical/30_ecog.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10157.json b/mne-python/source/doc/sphinxext/prs/10157.json new file mode 100644 index 0000000000000000000000000000000000000000..a127959b46b41fe3d23cdfc39131fa4386aa4baf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10157.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d7932956b5ae2516f6880cfdb2642f619108e3f2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10159.json b/mne-python/source/doc/sphinxext/prs/10159.json new file mode 100644 index 0000000000000000000000000000000000000000..4a5b6e3effc79d3264aa69e460e7b656c4ee7136 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10159.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "523576f6bd805dfbf3e882933d779c5a2fd6d740", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10166.json b/mne-python/source/doc/sphinxext/prs/10166.json new file mode 100644 index 0000000000000000000000000000000000000000..e2e103cb0f06580e543b11027b6ee37954fc16a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10166.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "79a431910d88d8174f754e4868b29a1aa42a7351", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 1 + }, + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/report/js_and_css/bootstrap-icons/bootstrap-icons.mne.min.css": { + "a": 1, + "d": 0 + }, + "mne/report/js_and_css/bootstrap-icons/gen_css_for_mne.py": { + "a": 60, + "d": 0 + }, + "mne/report/js_and_css/bootstrap-table/bootstrap-table-copy-rows.min.js": { + "a": 10, + "d": 0 + }, + "mne/report/js_and_css/bootstrap-table/bootstrap-table-export.min.js": { + "a": 10, + "d": 0 + }, + "mne/report/js_and_css/bootstrap-table/bootstrap-table.min.css": { + "a": 10, + "d": 0 + }, + "mne/report/js_and_css/bootstrap-table/bootstrap-table.min.js": { + "a": 10, + "d": 0 + }, + "mne/report/js_and_css/bootstrap-table/tableExport.min.js": { + "a": 13, + "d": 0 + }, + "mne/report/js_and_css/report.js": { + "a": 31, + "d": 13 + }, + "mne/report/report.py": { + "a": 101, + "d": 8 + }, + "mne/report/templates/epochs.html": { + "a": 1, + "d": 0 + }, + "mne/report/tests/test_report.py": { + "a": 40, + "d": 10 + }, + "setup.cfg": { + "a": 2, + "d": 2 + }, + "tutorials/intro/70_report.py": { + "a": 18, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10168.json b/mne-python/source/doc/sphinxext/prs/10168.json new file mode 100644 index 0000000000000000000000000000000000000000..7d40881d2e7fe30bcd078d7213c2f96342430bf4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10168.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fd0387089d88575773e20eb84de08929598ba45d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10170.json b/mne-python/source/doc/sphinxext/prs/10170.json new file mode 100644 index 0000000000000000000000000000000000000000..9b73d165ab9d15dfbab3e86fbda396f32709936d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10170.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3ab96f07e8396ec0fe11b532f9e6d42f4637b3a3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10171.json b/mne-python/source/doc/sphinxext/prs/10171.json new file mode 100644 index 0000000000000000000000000000000000000000..8ee4af53709fc65898f2d415172fbddaa0d1b8d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10171.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "faf8b2d96e601db405bc4cc1eb1d0bd6e71541dc", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10172.json b/mne-python/source/doc/sphinxext/prs/10172.json new file mode 100644 index 0000000000000000000000000000000000000000..3a0bc197013cbf8fc945934dd22da684ba0870c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10172.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "215fe39f6a8a565f932c74d57d9f677ec587d672", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/inverse.rst": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10174.json b/mne-python/source/doc/sphinxext/prs/10174.json new file mode 100644 index 0000000000000000000000000000000000000000..d1ea315a71aeaa3109f9742f8978840c19d37664 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10174.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cda07d5d8f3e551799c0677b5dcce89d9f0dbdc7", + "authors": [ + { + "n": "John Veillette", + "e": "johnv@uchicago.edu" + } + ], + "changes": { + "doc/install/pre_install.rst": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10175.json b/mne-python/source/doc/sphinxext/prs/10175.json new file mode 100644 index 0000000000000000000000000000000000000000..9087411b3434c350a67a9fdf98e9c3a06a658e64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10175.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e6282d27dbe2f54e6c9135a5c883170f7beeb3dd", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 1 + }, + "mne/report/report.py": { + "a": 2, + "d": 1 + }, + "mne/surface.py": { + "a": 14, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10176.json b/mne-python/source/doc/sphinxext/prs/10176.json new file mode 100644 index 0000000000000000000000000000000000000000..1cbc720bd79225f79fabfdc43b6736143f0df0f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10176.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a8889009536218960e5546d941453c0f1ae86c61", + "authors": [ + { + "n": "Jeff Stout", + "e": null + } + ], + "changes": { + "mne/report/report.py": { + "a": 15, + "d": 9 + }, + "mne/report/tests/test_report.py": { + "a": 15, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10177.json b/mne-python/source/doc/sphinxext/prs/10177.json new file mode 100644 index 0000000000000000000000000000000000000000..87d3658084559199dd3db7227450e4818447eebd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10177.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "337bee137414d3effb246258e3fd3ff7297392a5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10178.json b/mne-python/source/doc/sphinxext/prs/10178.json new file mode 100644 index 0000000000000000000000000000000000000000..f615398cd3b62538c2f0cd30aeea451ddef88512 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10178.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "161497b28df1b8db77ab4e6061ea9b32a74d17ca", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10179.json b/mne-python/source/doc/sphinxext/prs/10179.json new file mode 100644 index 0000000000000000000000000000000000000000..ae458c8926e9b5065c9aa4b2b65a246663c1bcf2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10179.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "38d63e33bc1b0e51394ce800123b42853e3a0c20", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/install/advanced.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1018.json b/mne-python/source/doc/sphinxext/prs/1018.json new file mode 100644 index 0000000000000000000000000000000000000000..a1327f5a6a0139fba15d86d298622c009a36e9f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1018.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "010b0800f53dbd0506c93276d47a2b80143989f4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/channels.py": { + "a": 40, + "d": 0 + }, + "mne/fiff/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10181.json b/mne-python/source/doc/sphinxext/prs/10181.json new file mode 100644 index 0000000000000000000000000000000000000000..bf4c1f8a9023bbf71131dadfd900b7b691698bdc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10181.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fe6a30c67b6d08a10331e6eff4372e161d7e4109", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/pre_install.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10182.json b/mne-python/source/doc/sphinxext/prs/10182.json new file mode 100644 index 0000000000000000000000000000000000000000..35555cdd4d21b908303f2e8d709b9f5adac8ce75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10182.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bafc6ef4857806bf28fa7952865ba9a71f514274", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 17, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10183.json b/mne-python/source/doc/sphinxext/prs/10183.json new file mode 100644 index 0000000000000000000000000000000000000000..ec964a9423d6cf6a83e04ada6059e488b19a80f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10183.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ebaaed43a0ff8010de1deb0861b3642d1308fff8", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 10, + "d": 5 + }, + "mne/report/tests/test_report.py": { + "a": 15, + "d": 16 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10184.json b/mne-python/source/doc/sphinxext/prs/10184.json new file mode 100644 index 0000000000000000000000000000000000000000..baab593101280b8dade959cf60d7f6a61a284d99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10184.json @@ -0,0 +1,195 @@ +{ + "merge_commit_sha": "93485e025d576470c21cc936becb3992c01a9c5e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 3, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 11, + "d": 0 + }, + "doc/time_frequency.rst": { + "a": 3, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 3 + }, + "mne/cov.py": { + "a": 2, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 96, + "d": 40 + }, + "mne/evoked.py": { + "a": 93, + "d": 1 + }, + "mne/filter.py": { + "a": 2, + "d": 1 + }, + "mne/html_templates/repr/spectrum.html.jinja": { + "a": 50, + "d": 0 + }, + "mne/io/base.py": { + "a": 41, + "d": 38 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 3 + }, + "mne/simulation/tests/test_raw.py": { + "a": 4, + "d": 3 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 3, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 34, + "d": 69 + }, + "mne/time_frequency/spectrum.py": { + "a": 1146, + "d": 0 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 30, + "d": 27 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 116, + "d": 243 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 184, + "d": 0 + }, + "mne/utils/check.py": { + "a": 2, + "d": 1 + }, + "mne/utils/dataframe.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 151, + "d": 41 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 8, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 18, + "d": 25 + }, + "mne/viz/ica.py": { + "a": 7, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 36, + "d": 87 + }, + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 57, + "d": 57 + }, + "mne/viz/utils.py": { + "a": 12, + "d": 13 + }, + "setup.cfg": { + "a": 4, + "d": 1 + }, + "tutorials/clinical/60_sleep.py": { + "a": 6, + "d": 7 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 36, + "d": 19 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 42, + "d": 14 + }, + "tutorials/time-freq/10_spectrum_class.py": { + "a": 172, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10185.json b/mne-python/source/doc/sphinxext/prs/10185.json new file mode 100644 index 0000000000000000000000000000000000000000..62e8ceccb9d0b5d35c57244721aa5fb46999ad33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10185.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dfe32b078b4c6deb16101db36ca452074d2d11e9", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 25, + "d": 1 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10186.json b/mne-python/source/doc/sphinxext/prs/10186.json new file mode 100644 index 0000000000000000000000000000000000000000..195f6c364986f66df99b2d40315f851203baf8af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10186.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2d5d1686e9b06a1e7bc29794bd2084b0336f0ded", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10188.json b/mne-python/source/doc/sphinxext/prs/10188.json new file mode 100644 index 0000000000000000000000000000000000000000..750d1e3a989d4ea8580444a55a2dc373d5f0cc3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10188.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1dc380aabb8d4d8869aea0192c3beabeb9fc141c", + "authors": [ + { + "n": "Eduard Ort", + "e": "eduardxort@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/annotations.py": { + "a": 9, + "d": 1 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10189.json b/mne-python/source/doc/sphinxext/prs/10189.json new file mode 100644 index 0000000000000000000000000000000000000000..8db0b8ea453eb355661bec38ff46551564576a4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10189.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "15f478791aa37e260a4d77b95a1a67166da95ccb", + "authors": [ + { + "n": "fzamberlan", + "e": "44038765+fzamberlan@users.noreply.github.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/channels/_standard_montage_utils.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10191.json b/mne-python/source/doc/sphinxext/prs/10191.json new file mode 100644 index 0000000000000000000000000000000000000000..5e1bcba0c29919e344f50bea24a6dcd87f165f2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10191.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3b84f95f792b71bbd7a1f223910d676590d5bf7f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/io/read_neo_format.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10192.json b/mne-python/source/doc/sphinxext/prs/10192.json new file mode 100644 index 0000000000000000000000000000000000000000..247d54bf951fd3c9d7f1bf6d6fc5b91fff10fcc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10192.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b7e8c7791b000258b2ba158ddd89eecbbb35af30", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 0, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10196.json b/mne-python/source/doc/sphinxext/prs/10196.json new file mode 100644 index 0000000000000000000000000000000000000000..c5d61167284b14aec502f59301951685bff4e563 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10196.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "67f3fb8f838893f7210b805aa51b7ffeeac292b5", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 7, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10199.json b/mne-python/source/doc/sphinxext/prs/10199.json new file mode 100644 index 0000000000000000000000000000000000000000..ef700631c7da9f976ffe211ae66107cc46f259ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10199.json @@ -0,0 +1,423 @@ +{ + "merge_commit_sha": "6e312e1254105b9f2546c3b91108b1f96b7f05c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".coveragerc": { + "a": 0, + "d": 1 + }, + ".lgtm.yml": { + "a": 0, + "d": 5 + }, + "MANIFEST.in": { + "a": 2, + "d": 1 + }, + "README.rst": { + "a": 8, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 0, + "d": 3 + }, + "doc/install/index.rst": { + "a": 6, + "d": 13 + }, + "doc/links.inc": { + "a": 5, + "d": 0 + }, + "doc/overview/faq.rst": { + "a": 1, + "d": 2 + }, + "environment.yml": { + "a": 6, + "d": 2 + }, + "mne/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 5, + "d": 3 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_external.py": { + "a": 4, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 5, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/conftest.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/testing/_testing.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 4 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 2, + "d": 0 + }, + "mne/externals/FieldTrip.py": { + "a": 0, + "d": 508 + }, + "mne/externals/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/externals/decorator.py": { + "a": 0, + "d": 454 + }, + "mne/externals/doccer.py": { + "a": 0, + "d": 149 + }, + "mne/externals/h5io/__init__.py": { + "a": 0, + "d": 6 + }, + "mne/externals/h5io/_h5io.py": { + "a": 0, + "d": 746 + }, + "mne/externals/pymatreader/__init__.py": { + "a": 0, + "d": 32 + }, + "mne/externals/pymatreader/pymatreader.py": { + "a": 0, + "d": 103 + }, + "mne/externals/pymatreader/utils.py": { + "a": 0, + "d": 263 + }, + "mne/externals/tqdm/__init__.py": { + "a": 0, + "d": 12 + }, + "mne/externals/tqdm/_tqdm/__init__.py": { + "a": 0, + "d": 40 + }, + "mne/externals/tqdm/_tqdm/__main__.py": { + "a": 0, + "d": 2 + }, + "mne/externals/tqdm/_tqdm/_main.py": { + "a": 0, + "d": 7 + }, + "mne/externals/tqdm/_tqdm/_monitor.py": { + "a": 0, + "d": 99 + }, + "mne/externals/tqdm/_tqdm/_tqdm.py": { + "a": 0, + "d": 7 + }, + "mne/externals/tqdm/_tqdm/_tqdm_gui.py": { + "a": 0, + "d": 7 + }, + "mne/externals/tqdm/_tqdm/_tqdm_notebook.py": { + "a": 0, + "d": 7 + }, + "mne/externals/tqdm/_tqdm/_tqdm_pandas.py": { + "a": 0, + "d": 46 + }, + "mne/externals/tqdm/_tqdm/_utils.py": { + "a": 0, + "d": 6 + }, + "mne/externals/tqdm/_tqdm/_version.py": { + "a": 0, + "d": 59 + }, + "mne/externals/tqdm/_tqdm/auto.py": { + "a": 0, + "d": 6 + }, + "mne/externals/tqdm/_tqdm/autonotebook.py": { + "a": 0, + "d": 18 + }, + "mne/externals/tqdm/_tqdm/cli.py": { + "a": 0, + "d": 228 + }, + "mne/externals/tqdm/_tqdm/contrib/__init__.py": { + "a": 0, + "d": 10 + }, + "mne/externals/tqdm/_tqdm/gui.py": { + "a": 0, + "d": 321 + }, + "mne/externals/tqdm/_tqdm/notebook.py": { + "a": 0, + "d": 261 + }, + "mne/externals/tqdm/_tqdm/std.py": { + "a": 0, + "d": 1464 + }, + "mne/externals/tqdm/_tqdm/tqdm.1": { + "a": 0, + "d": 255 + }, + "mne/externals/tqdm/_tqdm/utils.py": { + "a": 0, + "d": 345 + }, + "mne/fixes.py": { + "a": 3, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 6, + "d": 7 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 4, + "d": 4 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 1, + "d": 9 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 10, + "d": 32 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 7, + "d": 6 + }, + "mne/io/snirf/_snirf.py": { + "a": 2, + "d": 4 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 2, + "d": 13 + }, + "mne/io/tests/test_raw.py": { + "a": 4, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 6, + "d": 3 + }, + "mne/parallel.py": { + "a": 2, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 7, + "d": 2 + }, + "mne/report/report.py": { + "a": 17, + "d": 3 + }, + "mne/report/tests/test_report.py": { + "a": 8, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 9, + "d": 4 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 4 + }, + "mne/tests/test_import_nesting.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_source_estimate.py": { + "a": 7, + "d": 7 + }, + "mne/time_frequency/csd.py": { + "a": 4, + "d": 2 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 5, + "d": 2 + }, + "mne/utils/check.py": { + "a": 20, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 74, + "d": 4 + }, + "mne/utils/progressbar.py": { + "a": 7, + "d": 1 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 5, + "d": 4 + }, + "mne/viz/conftest.py": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 6, + "d": 2 + }, + "requirements_base.txt": { + "a": 9, + "d": 0 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "requirements_hdf5.txt": { + "a": 3, + "d": 0 + }, + "setup.cfg": { + "a": 4, + "d": 4 + }, + "setup.py": { + "a": 8, + "d": 12 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 7, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1020.json b/mne-python/source/doc/sphinxext/prs/1020.json new file mode 100644 index 0000000000000000000000000000000000000000..c6ae1eff66bcce88be04643a5f59cc4aa9b13eed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1020.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5b20fc2208e41f712f017f67ba6e1df43c563462", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/time_frequency/tests/test_ar.py": { + "a": 2, + "d": 2 + }, + "mne/utils.py": { + "a": 48, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10200.json b/mne-python/source/doc/sphinxext/prs/10200.json new file mode 100644 index 0000000000000000000000000000000000000000..fd3e51fe1601a9a29b92c1a280e776ded5eb26fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10200.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f95c84760aae461179e8fab55034fa3dc0b5463d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 30, + "d": 2 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 3, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 16, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10202.json b/mne-python/source/doc/sphinxext/prs/10202.json new file mode 100644 index 0000000000000000000000000000000000000000..e1c1096209e54699b20ccd4436d5ee2dfbe94160 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10202.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e923880fdfa021b9d1b487206db0826e4b88b800", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 23, + "d": 8 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10203.json b/mne-python/source/doc/sphinxext/prs/10203.json new file mode 100644 index 0000000000000000000000000000000000000000..b5db59ed8f52f8e4eeba4fbdff4d7a4f36b0a50c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10203.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f90b303ce66a8415e64edd4605b09ac0179c1ebf", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10205.json b/mne-python/source/doc/sphinxext/prs/10205.json new file mode 100644 index 0000000000000000000000000000000000000000..7ec7b9c82f49f7f922bd6e70207c57a48acee2cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10205.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e48ec6cb0689f747f2ec53a162fe13496c03a200", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10206.json b/mne-python/source/doc/sphinxext/prs/10206.json new file mode 100644 index 0000000000000000000000000000000000000000..36add585fb208e87016ab0289896016a71fa2571 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10206.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9b44cb9af43c0fde8b61c37abdd7dfa5d0d531f2", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 14, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1021.json b/mne-python/source/doc/sphinxext/prs/1021.json new file mode 100644 index 0000000000000000000000000000000000000000..531d3d6ac36777a3712034e86863bec0fd2b5a1d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1021.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4d81e9b6e300f671d3de19a06ee69300ae6cf1b1", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "examples/plot_evoked_topomap.py": { + "a": 39, + "d": 34 + }, + "mne/fiff/evoked.py": { + "a": 11, + "d": 5 + }, + "mne/tests/test_viz.py": { + "a": 10, + "d": 0 + }, + "mne/viz.py": { + "a": 32, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10210.json b/mne-python/source/doc/sphinxext/prs/10210.json new file mode 100644 index 0000000000000000000000000000000000000000..cdedb1b2b3f2cdd5f06ba2e024d7e28615f4c7e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10210.json @@ -0,0 +1,171 @@ +{ + "merge_commit_sha": "2b2b0cff2fa82d07919a6947563a0b0ddba95499", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/datasets/_fake/_fake.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/_fetch.py": { + "a": 4, + "d": 4 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/_infant/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 3, + "d": 4 + }, + "mne/datasets/epilepsy_ecog/_data.py": { + "a": 2, + "d": 3 + }, + "mne/datasets/erp_core/erp_core.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/fnirs_motor/fnirs_motor.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/limo/limo.py": { + "a": 2, + "d": 3 + }, + "mne/datasets/misc/_misc.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/mtrf/mtrf.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/opm/opm.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/phantom_4dbti/phantom_4dbti.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/refmeg_noise/refmeg_noise.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/sample/sample.py": { + "a": 2, + "d": 3 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 4, + "d": 9 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 1, + "d": 5 + }, + "mne/datasets/somato/somato.py": { + "a": 2, + "d": 3 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 2, + "d": 3 + }, + "mne/datasets/ssvep/ssvep.py": { + "a": 2, + "d": 4 + }, + "mne/datasets/testing/_testing.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 5 + }, + "mne/datasets/utils.py": { + "a": 4, + "d": 8 + }, + "mne/datasets/visual_92_categories/visual_92_categories.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10211.json b/mne-python/source/doc/sphinxext/prs/10211.json new file mode 100644 index 0000000000000000000000000000000000000000..74e776cd3a77680f3fc78b4a1bfabd468935db15 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10211.json @@ -0,0 +1,199 @@ +{ + "merge_commit_sha": "e6336f0ee5dcb13023bee516787150dfb25a4bcf", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 2, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 13, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/data/html_templates.py": { + "a": 0, + "d": 180 + }, + "mne/epochs.py": { + "a": 11, + "d": 9 + }, + "mne/externals/tempita/__init__.py": { + "a": 0, + "d": 1309 + }, + "mne/externals/tempita/_looper.py": { + "a": 0, + "d": 163 + }, + "mne/externals/tempita/compat3.py": { + "a": 0, + "d": 45 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 2 + }, + "mne/html_templates/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/html_templates/_templates.py": { + "a": 25, + "d": 0 + }, + "mne/html_templates/report/code.html.jinja": { + "a": 24, + "d": 0 + }, + "mne/html_templates/report/cov.html.jinja": { + "a": 23, + "d": 0 + }, + "mne/html_templates/report/epochs.html.jinja": { + "a": 27, + "d": 0 + }, + "mne/html_templates/report/evoked.html.jinja": { + "a": 26, + "d": 0 + }, + "mne/html_templates/report/footer.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/report/forward.html.jinja": { + "a": 23, + "d": 0 + }, + "mne/html_templates/report/header.html.jinja": { + "a": 10, + "d": 10 + }, + "mne/html_templates/report/html.html.jinja": { + "a": 23, + "d": 0 + }, + "mne/html_templates/report/ica.html.jinja": { + "a": 29, + "d": 0 + }, + "mne/html_templates/report/image.html.jinja": { + "a": 36, + "d": 0 + }, + "mne/html_templates/report/inverse.html.jinja": { + "a": 23, + "d": 0 + }, + "mne/html_templates/report/raw.html.jinja": { + "a": 25, + "d": 0 + }, + "mne/html_templates/report/slider.html.jinja": { + "a": 22, + "d": 22 + }, + "mne/html_templates/report/toc.html.jinja": { + "a": 4, + "d": 4 + }, + "mne/html_templates/repr/epochs.html.jinja": { + "a": 22, + "d": 0 + }, + "mne/html_templates/repr/forward.html.jinja": { + "a": 18, + "d": 0 + }, + "mne/html_templates/repr/ica.html.jinja": { + "a": 32, + "d": 0 + }, + "mne/html_templates/repr/info.html.jinja": { + "a": 74, + "d": 0 + }, + "mne/html_templates/repr/inverse_operator.html.jinja": { + "a": 14, + "d": 0 + }, + "mne/html_templates/repr/raw.html.jinja": { + "a": 12, + "d": 0 + }, + "mne/io/base.py": { + "a": 5, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 57, + "d": 13 + }, + "mne/minimum_norm/inverse.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 2 + }, + "mne/report/report.py": { + "a": 74, + "d": 106 + }, + "mne/report/templates/code.html": { + "a": 0, + "d": 24 + }, + "mne/report/templates/cov.html": { + "a": 0, + "d": 23 + }, + "mne/report/templates/epochs.html": { + "a": 0, + "d": 27 + }, + "mne/report/templates/evoked.html": { + "a": 0, + "d": 26 + }, + "mne/report/templates/forward.html": { + "a": 0, + "d": 23 + }, + "mne/report/templates/html.html": { + "a": 0, + "d": 23 + }, + "mne/report/templates/ica.html": { + "a": 0, + "d": 29 + }, + "mne/report/templates/image.html": { + "a": 0, + "d": 36 + }, + "mne/report/templates/inverse.html": { + "a": 0, + "d": 23 + }, + "mne/report/templates/raw.html": { + "a": 0, + "d": 25 + }, + "requirements.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10212.json b/mne-python/source/doc/sphinxext/prs/10212.json new file mode 100644 index 0000000000000000000000000000000000000000..31cee773400a7c29a0f03b8886de08581585a742 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10212.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "43e7ab99ccc7d7e006af81804147b57abf882b7e", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 106, + "d": 38 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 17, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10214.json b/mne-python/source/doc/sphinxext/prs/10214.json new file mode 100644 index 0000000000000000000000000000000000000000..f3f7d36e890af114eb0a5be59584836910fdd3cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10214.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7ecd46fe444a9c7e9d2b0c7f63ef05af09d41082", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10215.json b/mne-python/source/doc/sphinxext/prs/10215.json new file mode 100644 index 0000000000000000000000000000000000000000..5c0ba13809886375b867357796ee691675e1055c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10215.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c9fff0c24c80f17282a72251470b207f878a36f7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/overview/governance.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10217.json b/mne-python/source/doc/sphinxext/prs/10217.json new file mode 100644 index 0000000000000000000000000000000000000000..dfb306a1052593df5f60ba893773191e8eaa80d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10217.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "ceb381a4cdb05e0c0b237ec4180106e970dc08a4", + "authors": [ + { + "n": "twang5", + "e": "twang5@swarthmore.edu" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + ".gitignore": { + "a": 2, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 14, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 7, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1022.json b/mne-python/source/doc/sphinxext/prs/1022.json new file mode 100644 index 0000000000000000000000000000000000000000..f37de36724cddd57939340fcd35189e280d71295 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1022.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "10211c039a8c37f98f4172ae1af196b0041a3c6d", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/fiff/evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10220.json b/mne-python/source/doc/sphinxext/prs/10220.json new file mode 100644 index 0000000000000000000000000000000000000000..56889bad1a068d3e5a8bdbb6e59f2d3c169449fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10220.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f0611b5e93af11b59f48b540f4ec3a5d56c0bff5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 14, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 23, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10222.json b/mne-python/source/doc/sphinxext/prs/10222.json new file mode 100644 index 0000000000000000000000000000000000000000..ae5baf88754fb4ab348a0d94cfd52ee69969a885 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10222.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "e05151abb5d752cf6bd91fec0dc395ca7aa286fc", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_coreg.py": { + "a": 14, + "d": 3 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 5, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10223.json b/mne-python/source/doc/sphinxext/prs/10223.json new file mode 100644 index 0000000000000000000000000000000000000000..2cbec7bd720de9d2098fd9be181491437b520c36 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10223.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "89e163f60be122be2150ee93a9d3fcea5641b8b7", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/fixes.py": { + "a": 1, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10226.json b/mne-python/source/doc/sphinxext/prs/10226.json new file mode 100644 index 0000000000000000000000000000000000000000..90d562dc1b3be368514ed89e709a82ea71146de9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10226.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "037ebe20a4aa300eb3cb7b9d7828bdae9c1fa954", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/gui/_ieeg_locate_gui.py": { + "a": 7, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 12 + }, + "mne/viz/utils.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10229.json b/mne-python/source/doc/sphinxext/prs/10229.json new file mode 100644 index 0000000000000000000000000000000000000000..e963bf1118d72542d08f8ae47a777182ae18a91b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10229.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "47051833f21bb372d60afc3adbf4305648ac7f69", + "authors": [ + { + "n": "Steve Matindi", + "e": null + } + ], + "changes": { + "LICENSE.txt": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10230.json b/mne-python/source/doc/sphinxext/prs/10230.json new file mode 100644 index 0000000000000000000000000000000000000000..814d0e69cd784f08f9b21a2a36a3268cbe609a7e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10230.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "8cfadafadb3ddd7c91a1b03934f0eb1d2fc54a3c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/coreg.py": { + "a": 29, + "d": 10 + }, + "mne/gui/_coreg.py": { + "a": 11, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10233.json b/mne-python/source/doc/sphinxext/prs/10233.json new file mode 100644 index 0000000000000000000000000000000000000000..23cc8de48acfad305d7bffc0390925ba0dfaa2ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10233.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "e305764e54300bb174d37c2c69cbb03e089a4e4b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/events.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 6, + "d": 4 + }, + "mne/event.py": { + "a": 87, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 48, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 4 + }, + "mne/utils/mixin.py": { + "a": 3, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10234.json b/mne-python/source/doc/sphinxext/prs/10234.json new file mode 100644 index 0000000000000000000000000000000000000000..6f11ead60f7fac094123fe98f1493ad5eb189515 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10234.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "edcdaf38efdb436c13860ebdf4b190d4719f8051", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10235.json b/mne-python/source/doc/sphinxext/prs/10235.json new file mode 100644 index 0000000000000000000000000000000000000000..e49ed3ffc7d4a242be253e3b00a564d4d45ee4c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10235.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a1cd8003bf7a359ebd76e4044afb7e8c0a1bfba9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/hitachi/hitachi.py": { + "a": 2, + "d": 0 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10239.json b/mne-python/source/doc/sphinxext/prs/10239.json new file mode 100644 index 0000000000000000000000000000000000000000..05acdbf48e89646c75ba00eda9349552b29073fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10239.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "c8751aad782b6f39cbe9516799f2d3dab9df0204", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/mri.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 8, + "d": 7 + }, + "mne/coreg.py": { + "a": 1, + "d": 11 + }, + "mne/gui/_coreg.py": { + "a": 1, + "d": 11 + }, + "mne/io/_digitization.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 12, + "d": 8 + }, + "mne/utils/docs.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10240.json b/mne-python/source/doc/sphinxext/prs/10240.json new file mode 100644 index 0000000000000000000000000000000000000000..39005aaa2eb4418edab95d783305e56b2db9961c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10240.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "24f63b1d8ccc665308c0e2637b9782c504250f1e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 7, + "d": 5 + }, + "mne/viz/backends/_notebook.py": { + "a": 7, + "d": 5 + }, + "mne/viz/backends/_qt.py": { + "a": 28, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10241.json b/mne-python/source/doc/sphinxext/prs/10241.json new file mode 100644 index 0000000000000000000000000000000000000000..0316b3ac5cc099cb3e9b7b8aa3457b6c626d0d30 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10241.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "92908de66e7a6da60300929b3d0859c40e25eaa6", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 18, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10242.json b/mne-python/source/doc/sphinxext/prs/10242.json new file mode 100644 index 0000000000000000000000000000000000000000..7aa898f7bc8d3ebea60d89f0c5ce84e37d9d03de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10242.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "89650ca14913a6f32badec6b07c12d160d125934", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 3, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 124, + "d": 38 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10243.json b/mne-python/source/doc/sphinxext/prs/10243.json new file mode 100644 index 0000000000000000000000000000000000000000..70ae6c5cdebe5e31c38fb954498760a4bd4bdcfa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10243.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "49bdb5e0e0eb85dbfa37d3dfda03e7591dc7ed4d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 51, + "d": 12 + }, + "mne/gui/_coreg.py": { + "a": 14, + "d": 13 + }, + "mne/tests/test_coreg.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10244.json b/mne-python/source/doc/sphinxext/prs/10244.json new file mode 100644 index 0000000000000000000000000000000000000000..cfc2bb27c8e45b41dc806a87ba1de016e1f2a786 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10244.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "53878ce44237bb7abc5cc00721e19fa22e6f25fd", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10245.json b/mne-python/source/doc/sphinxext/prs/10245.json new file mode 100644 index 0000000000000000000000000000000000000000..293f261907441742a8c600030a14b987fa93ef93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10245.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9396ca77ba61f78714bb14449d4f78ecbec1caf0", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 18, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10246.json b/mne-python/source/doc/sphinxext/prs/10246.json new file mode 100644 index 0000000000000000000000000000000000000000..19c374781effec55ae37aeddf96d8fa7b8052124 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10246.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "585e444a709efb1aa5236182c3ba8052d1658cbb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/html_templates/report/epochs.html.jinja": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10247.json b/mne-python/source/doc/sphinxext/prs/10247.json new file mode 100644 index 0000000000000000000000000000000000000000..5d1dcd671da895897132e90dfe2e062c057efc20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10247.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "89f3d40d41e56130d91a555180a6a357ba00ed29", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 14, + "d": 7 + }, + "tutorials/intro/70_report.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10249.json b/mne-python/source/doc/sphinxext/prs/10249.json new file mode 100644 index 0000000000000000000000000000000000000000..cb09b59ba666701dfc882b6e777d40472f0a3d5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10249.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4bedd849b868f3fe35a98ebf1c9dbd1acfa758f5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10250.json b/mne-python/source/doc/sphinxext/prs/10250.json new file mode 100644 index 0000000000000000000000000000000000000000..2b33e7d4619e44bc7ae5466eb4f684ef8dca713f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10250.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b3bd234a412405e4fe5222382aa817e830928e10", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 5, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 6, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 5, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10251.json b/mne-python/source/doc/sphinxext/prs/10251.json new file mode 100644 index 0000000000000000000000000000000000000000..f7a630d58d8cd09f948ae721c3efa8b7d22f7f19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10251.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e1aec0ec39bee4ff437ab4f0fb80d4cc673a7751", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 45, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10252.json b/mne-python/source/doc/sphinxext/prs/10252.json new file mode 100644 index 0000000000000000000000000000000000000000..ae5f065e03d9dee099fa4ce08125b70f55ca84bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10252.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0accf8ceb7dbdcfe64f74f43260cb66583159cab", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/__init__.py": { + "a": 6, + "d": 7 + }, + "mne/gui/_coreg.py": { + "a": 39, + "d": 18 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10253.json b/mne-python/source/doc/sphinxext/prs/10253.json new file mode 100644 index 0000000000000000000000000000000000000000..5a98840622a19b8604ddae5e88d876cce8764899 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10253.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b5688906f971ad0b4026d9812e021dbfd015bf70", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 142, + "d": 16 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10255.json b/mne-python/source/doc/sphinxext/prs/10255.json new file mode 100644 index 0000000000000000000000000000000000000000..6a563fd2b516d27103ef3227f8473eb2efb8f422 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10255.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "abf530f78ea39e5dfeaf3d33b0f994c706eb9e9e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 62, + "d": 57 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10257.json b/mne-python/source/doc/sphinxext/prs/10257.json new file mode 100644 index 0000000000000000000000000000000000000000..64226a402080d60104541ce888a061792ea9e0b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10257.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f2d152916e8cd32c411c9b429317b455a7e699f5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10259.json b/mne-python/source/doc/sphinxext/prs/10259.json new file mode 100644 index 0000000000000000000000000000000000000000..b924af6716d0f763c1e82b9a22d0363e0fbec522 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10259.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8992bd050194b31ec03b8b6ef70021b307d2a541", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 36, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 24, + "d": 15 + }, + "mne/viz/backends/_notebook.py": { + "a": 55, + "d": 22 + }, + "mne/viz/backends/_qt.py": { + "a": 32, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10260.json b/mne-python/source/doc/sphinxext/prs/10260.json new file mode 100644 index 0000000000000000000000000000000000000000..65f48f5c3c128ad2974a795f8c9d8c08bcfd176a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10260.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2142d19a47a26cf5b94926c321daec50a94eff86", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 56, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10261.json b/mne-python/source/doc/sphinxext/prs/10261.json new file mode 100644 index 0000000000000000000000000000000000000000..7b0e2f64d2170ee1010cbb48c99c1c625dd607fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10261.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "addab681a95d8a1054cfd0e0de1842f3ee4b467f", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/utils/config.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10262.json b/mne-python/source/doc/sphinxext/prs/10262.json new file mode 100644 index 0000000000000000000000000000000000000000..f64c9f70ab3abbbf264f8d5ecad2fc8401bd9107 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10262.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cfa92b5119c9acb2293c654585f3b730dce1f19c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 39, + "d": 18 + }, + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10265.json b/mne-python/source/doc/sphinxext/prs/10265.json new file mode 100644 index 0000000000000000000000000000000000000000..0fba315fdf44fe1b2e3e106a68c9b38009ffceb2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10265.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "79cbc029fb45bfb1bd441f7544c53d76521be7d9", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/transforms.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10266.json b/mne-python/source/doc/sphinxext/prs/10266.json new file mode 100644 index 0000000000000000000000000000000000000000..49aff51f8dd3ec083a60a84da19a12a3079d80b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10266.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4595f8c7c849181ee225b994b2eacdfd143feb82", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 23, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10267.json b/mne-python/source/doc/sphinxext/prs/10267.json new file mode 100644 index 0000000000000000000000000000000000000000..2be0d6e9f292913d10353fee5913dcc786198676 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10267.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "69e2ce6016f49c915ac37f4adf57db347d4d14f2", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "examples/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/README.txt": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10268.json b/mne-python/source/doc/sphinxext/prs/10268.json new file mode 100644 index 0000000000000000000000000000000000000000..7921abc185d5a225046f1c6b4101aedead5baba4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10268.json @@ -0,0 +1,159 @@ +{ + "merge_commit_sha": "93a3be5d21028331a88c42ef9dfa10566bcd6d1f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "doc/logging.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/_ola.py": { + "a": 4, + "d": 5 + }, + "mne/annotations.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 0, + "d": 13 + }, + "mne/channels/channels.py": { + "a": 9, + "d": 11 + }, + "mne/cov.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/receptive_field.py": { + "a": 2, + "d": 4 + }, + "mne/decoding/search_light.py": { + "a": 4, + "d": 8 + }, + "mne/decoding/time_frequency.py": { + "a": 5, + "d": 7 + }, + "mne/decoding/transformer.py": { + "a": 10, + "d": 10 + }, + "mne/dipole.py": { + "a": 9, + "d": 10 + }, + "mne/epochs.py": { + "a": 17, + "d": 26 + }, + "mne/evoked.py": { + "a": 10, + "d": 13 + }, + "mne/filter.py": { + "a": 4, + "d": 4 + }, + "mne/io/base.py": { + "a": 13, + "d": 13 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 3, + "d": 3 + }, + "mne/io/fiff/raw.py": { + "a": 0, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 4, + "d": 4 + }, + "mne/label.py": { + "a": 12, + "d": 17 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 8, + "d": 8 + }, + "mne/preprocessing/ica.py": { + "a": 9, + "d": 10 + }, + "mne/report/report.py": { + "a": 10, + "d": 9 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 16, + "d": 18 + }, + "mne/source_space.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 61, + "d": 37 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 1 + }, + "mne/utils/tests/test_logging.py": { + "a": 9, + "d": 18 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1027.json b/mne-python/source/doc/sphinxext/prs/1027.json new file mode 100644 index 0000000000000000000000000000000000000000..326eb38fda604506f220e17ce56a41f5286893cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1027.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "969ac4ba6167ddf255aac6fd8042f1d5e142232a", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + ".travis.yml": { + "a": 21, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10270.json b/mne-python/source/doc/sphinxext/prs/10270.json new file mode 100644 index 0000000000000000000000000000000000000000..76333387553da8e439d1327121f0a3645b941dd2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10270.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5b788d6cfb6d6c84c7d630ba41d9696f2c37e31b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 12, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 8, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 8, + "d": 0 + }, + "mne/viz/backends/_qt.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10271.json b/mne-python/source/doc/sphinxext/prs/10271.json new file mode 100644 index 0000000000000000000000000000000000000000..33c28211bbd8f1a14a2d4b17234bb088bcee63d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10271.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "139a6347e481477650022b9fc069bea84be344eb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10272.json b/mne-python/source/doc/sphinxext/prs/10272.json new file mode 100644 index 0000000000000000000000000000000000000000..ad940935e4e3619a386175bf8e8cabcbc5f4c244 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10272.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0fcac00dd9095771f36642864bfb302e8c3e138b", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 68, + "d": 81 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10273.json b/mne-python/source/doc/sphinxext/prs/10273.json new file mode 100644 index 0000000000000000000000000000000000000000..0268a11558e439ee90dd9bdcff46bbcb4853e463 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10273.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4e8ae75d51d8fb4b9a20744c65f4f0eaa4eb7a82", + "authors": [ + { + "n": "Eduard Ort", + "e": "eduardxort@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10275.json b/mne-python/source/doc/sphinxext/prs/10275.json new file mode 100644 index 0000000000000000000000000000000000000000..e5a817df298237471017a2c403d4a6d53ce35ac8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10275.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "30f182d94ebaa226c8f7777c939c8ab80738ca07", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10276.json b/mne-python/source/doc/sphinxext/prs/10276.json new file mode 100644 index 0000000000000000000000000000000000000000..b4b868cc22616aad85875be1d848dd39a94a0914 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10276.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "623645a3d3f5e71ddaf448ccd6ca1be74748219a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 5 + }, + "mne/gui/__init__.py": { + "a": 14, + "d": 13 + }, + "mne/gui/_coreg.py": { + "a": 15, + "d": 32 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 27, + "d": 11 + }, + "mne/utils/config.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10277.json b/mne-python/source/doc/sphinxext/prs/10277.json new file mode 100644 index 0000000000000000000000000000000000000000..c464b46c0c855019bff1ba86a0cdf4a796143683 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10277.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d53c5bb9d9c69c055b6bca680ee750ac235bbe58", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/_localized_abbr.py": { + "a": 60, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 33, + "d": 10 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 44, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10278.json b/mne-python/source/doc/sphinxext/prs/10278.json new file mode 100644 index 0000000000000000000000000000000000000000..a0bb8406114e5e07314d3a1eda73322874247f49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10278.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e11f1fcd09f1ec14e48bc70bddc27b9ce3beff45", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 14, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10279.json b/mne-python/source/doc/sphinxext/prs/10279.json new file mode 100644 index 0000000000000000000000000000000000000000..c28356572eb460b7e6c5bbcaa89dc656fa5fcbf1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10279.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e59df7c3128f1b5299f949a9bfe26adc98ff1440", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 19, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10280.json b/mne-python/source/doc/sphinxext/prs/10280.json new file mode 100644 index 0000000000000000000000000000000000000000..2e022da6e85de803a8069e3c56e9fb7e045b1f08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10280.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a315288bfc483aab7e79f42e1d78c4b2bf3e5d15", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 0, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10281.json b/mne-python/source/doc/sphinxext/prs/10281.json new file mode 100644 index 0000000000000000000000000000000000000000..67626b339cb12264a5bfd8ca76224b6f4faba19f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10281.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6422d6c033c3a9d6221c2848dbb4b0cd6d8848f7", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 9, + "d": 7 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 29, + "d": 14 + }, + "mne/time_frequency/tfr.py": { + "a": 29, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10282.json b/mne-python/source/doc/sphinxext/prs/10282.json new file mode 100644 index 0000000000000000000000000000000000000000..b7a8f56208629b1f5b3318ac7aaf322388b7467e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10282.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2ade8dab149f9b45d2321208a16131f8c89f0d10", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/links.inc": { + "a": 3, + "d": 0 + }, + "doc/overview/roadmap.rst": { + "a": 54, + "d": 63 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10283.json b/mne-python/source/doc/sphinxext/prs/10283.json new file mode 100644 index 0000000000000000000000000000000000000000..154f8d2742f5a73b82264852336d9635caea73bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10283.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d694c74c3f90e3128a321bbef2fbc5de77fae1e8", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 21, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10284.json b/mne-python/source/doc/sphinxext/prs/10284.json new file mode 100644 index 0000000000000000000000000000000000000000..ccddf99e14fc8b898552bd4aef56754426accce5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10284.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "5920d6930da19ed393949acf3c9bb7d7859c3b9d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 11, + "d": 2 + }, + "mne/gui/_coreg.py": { + "a": 13, + "d": 4 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 5, + "d": 0 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 5, + "d": 2 + }, + "mne/viz/backends/_qt.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10289.json b/mne-python/source/doc/sphinxext/prs/10289.json new file mode 100644 index 0000000000000000000000000000000000000000..b379624b185b04ba5b45c28c0cd839b648341079 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10289.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "258b462f06a3a5ef4c6d8ded6ca03f519b498831", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/event.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10290.json b/mne-python/source/doc/sphinxext/prs/10290.json new file mode 100644 index 0000000000000000000000000000000000000000..9af3b02a6e9b41942c1ddec6d24bdfb86fb80043 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10290.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "193802765043f9b03b29cd9da08e2c690c22ef72", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_notebook.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10291.json b/mne-python/source/doc/sphinxext/prs/10291.json new file mode 100644 index 0000000000000000000000000000000000000000..da7e8cde992a46537bb13707811cff8501e476e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10291.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7a8964a6c8277ae1e84e0a606604f1c7eadd2569", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10292.json b/mne-python/source/doc/sphinxext/prs/10292.json new file mode 100644 index 0000000000000000000000000000000000000000..2fd2ba3d259dc350c972fdd2fd2d250b33fad7fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10292.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "8babd8ce675be5fa17a9288b0ed49b2cd88b8f75", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 1 + }, + "mne/io/proj.py": { + "a": 46, + "d": 14 + }, + "mne/io/tests/test_raw.py": { + "a": 5, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/proj.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10293.json b/mne-python/source/doc/sphinxext/prs/10293.json new file mode 100644 index 0000000000000000000000000000000000000000..061e7fce4e95a625b560b61020c352b8cf781274 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10293.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "00ea4fa75906149cfa20232d6a72a8abc73f1430", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 137, + "d": 141 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10294.json b/mne-python/source/doc/sphinxext/prs/10294.json new file mode 100644 index 0000000000000000000000000000000000000000..0410ffd510f5a21c1f77fe5d1cd9ec237a5c8ce1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10294.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b28c9af5920db2c94967f4cc3d8789fc18b5a5af", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10296.json b/mne-python/source/doc/sphinxext/prs/10296.json new file mode 100644 index 0000000000000000000000000000000000000000..d7bd5ec538520842dc0d7622b0c355e67a570f72 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10296.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fa643e8dcde1024d21d695e4c788f1a1a8a0e41f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_notebook.py": { + "a": 19, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10297.json b/mne-python/source/doc/sphinxext/prs/10297.json new file mode 100644 index 0000000000000000000000000000000000000000..595f824f87f3941dd49d1a483f6ab610ef4d3d7d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10297.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "3677baf21a6d8a82d64eb9683b980c9d16907ad0", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 14, + "d": 4 + }, + "mne/epochs.py": { + "a": 4, + "d": 2 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 22, + "d": 24 + }, + "mne/viz/_mpl_figure.py": { + "a": 12, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 12, + "d": 7 + }, + "mne/viz/tests/test_epochs.py": { + "a": 35, + "d": 38 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10298.json b/mne-python/source/doc/sphinxext/prs/10298.json new file mode 100644 index 0000000000000000000000000000000000000000..97999da861fb9e769536ed77ff22b72b137f8212 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10298.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c3e812ba3840a336f4da6c26236e1b4487f6c02e", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/mri.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 22, + "d": 0 + }, + "mne/tests/test_freesurfer.py": { + "a": 39, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 39, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10299.json b/mne-python/source/doc/sphinxext/prs/10299.json new file mode 100644 index 0000000000000000000000000000000000000000..e241700a52a93f21a403b6e0b92659fa7b867f45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10299.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "00e0889d0a5b7cf953cc3fdc6065b0564f220a75", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 22, + "d": 5 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 13, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1030.json b/mne-python/source/doc/sphinxext/prs/1030.json new file mode 100644 index 0000000000000000000000000000000000000000..37f09f5ac70ba67b69c8d5eafbc8f547eee7beb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1030.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "37ef1ca556317ccef68311aaedd0612f8a95ff64", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/fiff/tag.py": { + "a": 8, + "d": 5 + }, + "mne/fiff/tests/test_raw.py": { + "a": 13, + "d": 0 + }, + "mne/fiff/write.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10300.json b/mne-python/source/doc/sphinxext/prs/10300.json new file mode 100644 index 0000000000000000000000000000000000000000..48e14d77fd6db548e7c592935825267847020c77 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10300.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "47c53f9cf57bd81de4427f903cde839df5aba664", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/install/mne_python.rst": { + "a": 20, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10301.json b/mne-python/source/doc/sphinxext/prs/10301.json new file mode 100644 index 0000000000000000000000000000000000000000..ce060d67e82147172a087f4fea93c9bd02e0beab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10301.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "40eaa0e1114d0bb64e8363d70527833f48189c25", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10302.json b/mne-python/source/doc/sphinxext/prs/10302.json new file mode 100644 index 0000000000000000000000000000000000000000..6cbfa4d785ddeec17eaa56e6d80eadae7fac3cc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10302.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f1c118cefb45a4a9aafce1725120f67997860ed2", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 32, + "d": 12 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 22, + "d": 7 + }, + "mne/viz/backends/_qt.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10304.json b/mne-python/source/doc/sphinxext/prs/10304.json new file mode 100644 index 0000000000000000000000000000000000000000..c5265847d4b0d9907e5415d7a4baed19433a48d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10304.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "bdd8a3f963963f7ccf54bd3a286748bf3dcb88ff", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/egi/egimff.py": { + "a": 24, + "d": 22 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10305.json b/mne-python/source/doc/sphinxext/prs/10305.json new file mode 100644 index 0000000000000000000000000000000000000000..0349c5bdbd79915bcffba6f8ca992c66d5118139 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10305.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "639d7362b2c1a4599b583f247a431a3492c24190", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 85, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 11, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 23, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10306.json b/mne-python/source/doc/sphinxext/prs/10306.json new file mode 100644 index 0000000000000000000000000000000000000000..afe8acb4a576ee9ae51af7ca8e6c9e913a3734af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10306.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6dcfda8edf51ba4cbc61ccc6b06aca1b804731d4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/glossary.rst": { + "a": 11, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 119, + "d": 86 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10307.json b/mne-python/source/doc/sphinxext/prs/10307.json new file mode 100644 index 0000000000000000000000000000000000000000..9c8e95fae9a874e1ce9becbd9e8210ba38644694 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10307.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e6b53672ba66af749a075559aa2e94fe06802f3c", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 38, + "d": 16 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10309.json b/mne-python/source/doc/sphinxext/prs/10309.json new file mode 100644 index 0000000000000000000000000000000000000000..ee65649cd6ad89bd4b42366356dc3d559c51c207 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10309.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "6107c3a6377eb07c2ba1c5a93cea54122fe74d64", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/datasets/opm_data.py": { + "a": 2, + "d": 2 + }, + "examples/forward/left_cerebellum_volume_source.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/read_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/movement_detection.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 2, + "d": 3 + }, + "examples/visualization/3d_to_2d.py": { + "a": 5, + "d": 6 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 27, + "d": 21 + }, + "mne/viz/tests/test_3d.py": { + "a": 8, + "d": 5 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 2, + "d": 2 + }, + "tutorials/clinical/30_ecog.py": { + "a": 3, + "d": 3 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 2, + "d": 3 + }, + "tutorials/forward/25_automated_coreg.py": { + "a": 10, + "d": 4 + }, + "tutorials/forward/30_forward.py": { + "a": 2, + "d": 2 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 6, + "d": 9 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 1, + "d": 0 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 2, + "d": 2 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10313.json b/mne-python/source/doc/sphinxext/prs/10313.json new file mode 100644 index 0000000000000000000000000000000000000000..1efcb85ef8891b8b6056d7a695937e293c38a445 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10313.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "58e17f29b4daf65d013fcf90f6746b565160a016", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/movement_compensation.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/movement_detection.py": { + "a": 5, + "d": 2 + }, + "examples/visualization/3d_to_2d.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10316.json b/mne-python/source/doc/sphinxext/prs/10316.json new file mode 100644 index 0000000000000000000000000000000000000000..3ea52973a499d0c31a1e7df31ed31f3254d34ea4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10316.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ff7ca979b70e92d265678ab00b832ac175adc40d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10317.json b/mne-python/source/doc/sphinxext/prs/10317.json new file mode 100644 index 0000000000000000000000000000000000000000..c4b026d5be3250bf11fca125b206c9ae91869fd8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10317.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "356dde91de47d8d1d113b65400ece5c777d833c2", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/viz/_mpl_figure.py": { + "a": 3, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10318.json b/mne-python/source/doc/sphinxext/prs/10318.json new file mode 100644 index 0000000000000000000000000000000000000000..a57d71caf1b0723395d9c726393968cd59ed3511 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10318.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "92393e880316d5ba07f67cd62571fbe80d37cc36", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/icons/README.rst": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10319.json b/mne-python/source/doc/sphinxext/prs/10319.json new file mode 100644 index 0000000000000000000000000000000000000000..fbb970cc3c5c9acf033b18545e0315d63ae9c49b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10319.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "a5f8d0bf0cb68f91696d442bdb81f3b2d152e8e2", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 0, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 29, + "d": 18 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 5 + }, + "mne/viz/backends/_abstract.py": { + "a": 0, + "d": 5 + }, + "mne/viz/backends/_pyvista.py": { + "a": 12, + "d": 5 + }, + "tutorials/clinical/20_seeg.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 0, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10322.json b/mne-python/source/doc/sphinxext/prs/10322.json new file mode 100644 index 0000000000000000000000000000000000000000..42fb585e357bcb29becca907f763dee9969566b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10322.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aa0db284840730b91baf2a56e73bdf672c4b5e15", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "paper.md": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10323.json b/mne-python/source/doc/sphinxext/prs/10323.json new file mode 100644 index 0000000000000000000000000000000000000000..f95748dab9b20d0a487997aec168620328d501dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10323.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "3ccb6c0d6810f95b0ee22568e0bbefb24b3cd9d7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 3, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_figure.py": { + "a": 33, + "d": 29 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 7, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10324.json b/mne-python/source/doc/sphinxext/prs/10324.json new file mode 100644 index 0000000000000000000000000000000000000000..f253424fe63b14d959f491888486e3ca5de39561 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10324.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0c3c52fa96365cfc8a6fc8b4b9e97d038ffaf385", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 25, + "d": 10 + }, + "mne/channels/montage.py": { + "a": 14, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 20, + "d": 4 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 14, + "d": 14 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10325.json b/mne-python/source/doc/sphinxext/prs/10325.json new file mode 100644 index 0000000000000000000000000000000000000000..965fc4bddb6610946009d9861b4adced585629a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10325.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2075f84592a77a40213706ec54f4965aca60afd2", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 21, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10326.json b/mne-python/source/doc/sphinxext/prs/10326.json new file mode 100644 index 0000000000000000000000000000000000000000..694b28104068fe4835c71809e13d13c34e5ac731 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10326.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d20ead8b9c1bbb2fab9b0af93f1cca913e3dddfd", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "figures/Figure_2.png": { + "a": 0, + "d": 0 + }, + "figures/Figure_3.png": { + "a": 0, + "d": 0 + }, + "paper.md": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10328.json b/mne-python/source/doc/sphinxext/prs/10328.json new file mode 100644 index 0000000000000000000000000000000000000000..95df6fe256df246f1eda824ddad402b68b548bfb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10328.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bdb7921aeeffbd8858113ca2101a4d46031393b4", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "paper.md": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1033.json b/mne-python/source/doc/sphinxext/prs/1033.json new file mode 100644 index 0000000000000000000000000000000000000000..72ea6555d6abdf738d3dfdc0325cd63e56eb31fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1033.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "91415917083fa64cb9c386f7f26d8553d88b266e", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/brainvision/brainvision.py": { + "a": 63, + "d": 27 + }, + "mne/fiff/brainvision/tests/test_brainvision.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10330.json b/mne-python/source/doc/sphinxext/prs/10330.json new file mode 100644 index 0000000000000000000000000000000000000000..6fa06f10c12b05732e9674316501832233f8c240 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10330.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "9315ed6e77157b9536452bafc738ac97065f9ca1", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 17, + "d": 8 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 5, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 18, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 0, + "d": 12 + }, + "mne/viz/ica.py": { + "a": 13, + "d": 19 + }, + "mne/viz/raw.py": { + "a": 0, + "d": 14 + }, + "mne/viz/tests/test_ica.py": { + "a": 18, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10331.json b/mne-python/source/doc/sphinxext/prs/10331.json new file mode 100644 index 0000000000000000000000000000000000000000..dbf45d52f3c9c8f1051f86e69fff52e7e81c9512 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10331.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "20078a124a135e5fce7b55f00f1659be2df137fe", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10332.json b/mne-python/source/doc/sphinxext/prs/10332.json new file mode 100644 index 0000000000000000000000000000000000000000..35af0dc55e4db79a75d58a3034fe591584a5fb2d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10332.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1713cc294f8c545bd7940e6d0dc52ec719f3495b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "paper.md": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10334.json b/mne-python/source/doc/sphinxext/prs/10334.json new file mode 100644 index 0000000000000000000000000000000000000000..fa4a327a594c59ef19173a65eb3c7ef3b175184d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10334.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "919489a2da08ddb3d70e4056de1ab7c7305c5e6f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/tests/test_commands.py": { + "a": 15, + "d": 14 + }, + "mne/conftest.py": { + "a": 21, + "d": 5 + }, + "mne/tests/test_coreg.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_source_space.py": { + "a": 9, + "d": 8 + }, + "mne/utils/_logging.py": { + "a": 9, + "d": 0 + }, + "mne/utils/_testing.py": { + "a": 3, + "d": 0 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 16, + "d": 10 + }, + "mne/utils/tests/test_testing.py": { + "a": 25, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10335.json b/mne-python/source/doc/sphinxext/prs/10335.json new file mode 100644 index 0000000000000000000000000000000000000000..b4c6307823464b8524b7642e0d2d3bc1af8a1101 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10335.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "32084513d547657029ce4a77b8db79d2a2a24b70", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 17, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10336.json b/mne-python/source/doc/sphinxext/prs/10336.json new file mode 100644 index 0000000000000000000000000000000000000000..779a0e730332736f7b0b26cb2f1e66e7a58d4398 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10336.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "397eda40c41b0e9a9587b443b53faa07a05cdcca", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/io/base.py": { + "a": 7, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10338.json b/mne-python/source/doc/sphinxext/prs/10338.json new file mode 100644 index 0000000000000000000000000000000000000000..0e08bf8a72a448febeb5ee8ada6d1e46ad51736c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10338.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ad54e0ffae82d86fc96f8cfef312637ae96a3da5", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "paper.md": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10339.json b/mne-python/source/doc/sphinxext/prs/10339.json new file mode 100644 index 0000000000000000000000000000000000000000..dadf60aaed25d62c9bef63a2a88f0d9977b8ad3f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10339.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "62a9de90c88a6a9dfcc1094e5ca4643434991dda", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10340.json b/mne-python/source/doc/sphinxext/prs/10340.json new file mode 100644 index 0000000000000000000000000000000000000000..353dc3d7874f59f5eb612fcd987b5872175fbd35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10340.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7d6943aa455d572e09ddec60879a84863f4b8ef2", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "paper.md": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10341.json b/mne-python/source/doc/sphinxext/prs/10341.json new file mode 100644 index 0000000000000000000000000000000000000000..cc9d22b89d436eb207d307843b8740a528368cae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10341.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "926385a7fc9af342801642b1731662b785c8fcd8", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "paper.md": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10342.json b/mne-python/source/doc/sphinxext/prs/10342.json new file mode 100644 index 0000000000000000000000000000000000000000..c38faefff1c4ed14428d851c0938d3452d49d0ff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10342.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "65fb5a63f959203654d88a3614bd880da86ad735", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 23, + "d": 15 + }, + "mne/report/tests/test_report.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10345.json b/mne-python/source/doc/sphinxext/prs/10345.json new file mode 100644 index 0000000000000000000000000000000000000000..90f74a64f286673ee1cd4c64540bfd5447d6f002 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10345.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c92316d96ec373fe4e3d923b5b0a6ca7119299ad", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10346.json b/mne-python/source/doc/sphinxext/prs/10346.json new file mode 100644 index 0000000000000000000000000000000000000000..14f54d39f1b854ca17d42c282efdfb7e5d1dd9f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10346.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0c500107be1a85e42c9b63411829c5dbaedf62d4", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 34, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 7, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 8, + "d": 2 + }, + "mne/viz/backends/_qt.py": { + "a": 53, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10347.json b/mne-python/source/doc/sphinxext/prs/10347.json new file mode 100644 index 0000000000000000000000000000000000000000..403866383c9bdf834dd1156b367a059797586c74 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10347.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "9e546ac41629ff18548328dfe79fe47d232b1229", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/ssp.rst": { + "a": 1, + "d": 1 + }, + "doc/_templates/autosummary/class.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 3, + "d": 20 + }, + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + }, + "doc/overview/cookbook.rst": { + "a": 1, + "d": 1 + }, + "doc/overview/design_philosophy.rst": { + "a": 2, + "d": 1 + }, + "doc/overview/matlab.rst": { + "a": 1, + "d": 1 + }, + "doc/visualization.rst": { + "a": 1, + "d": 0 + }, + "ignore_words.txt": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 4, + "d": 0 + }, + "mne/dipole.py": { + "a": 3, + "d": 3 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 5, + "d": 3 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 17, + "d": 18 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 30, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 28, + "d": 24 + }, + "mne/viz/backends/_qt.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 6, + "d": 6 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 15, + "d": 9 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10348.json b/mne-python/source/doc/sphinxext/prs/10348.json new file mode 100644 index 0000000000000000000000000000000000000000..9037f19d5cb50ec64a46c7b44dbe5f908195f479 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10348.json @@ -0,0 +1,463 @@ +{ + "merge_commit_sha": "5fd9ca6c6323fc5307f46c86b7c6bfae522525e7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/memory.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "examples/datasets/brainstorm_data.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 6, + "d": 6 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 8, + "d": 7 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 3, + "d": 2 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 3, + "d": 2 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 3, + "d": 2 + }, + "examples/decoding/ems_filtering.py": { + "a": 3, + "d": 2 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 3, + "d": 3 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 1, + "d": 1 + }, + "examples/forward/forward_sensitivity_maps.py": { + "a": 3, + "d": 4 + }, + "examples/inverse/compute_mne_inverse_epochs_in_label.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/compute_mne_inverse_raw_in_label.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/custom_inverse_solver.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/gamma_map_inverse.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/label_activation_from_stc.py": { + "a": 9, + "d": 11 + }, + "examples/inverse/label_from_stc.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/label_source_activations.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 7, + "d": 5 + }, + "examples/inverse/mne_cov_power.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/psf_ctf_vertices.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/psf_ctf_vertices_lcmv.py": { + "a": 6, + "d": 5 + }, + "examples/inverse/rap_music.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/read_inverse.py": { + "a": 4, + "d": 6 + }, + "examples/inverse/read_stc.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/resolution_metrics.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/resolution_metrics_eegmeg.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/source_space_snr.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/vector_mne_solution.py": { + "a": 5, + "d": 4 + }, + "examples/preprocessing/css.py": { + "a": 9, + "d": 8 + }, + "examples/preprocessing/define_target_events.py": { + "a": 3, + "d": 2 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/ica_comparison.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/interpolate_bad_channels.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/shift_evoked.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/virtual_evoked.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/xdawn_denoising.py": { + "a": 3, + "d": 2 + }, + "examples/simulation/simulate_evoked_data.py": { + "a": 7, + "d": 7 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 3, + "d": 2 + }, + "examples/stats/cluster_stats_evoked.py": { + "a": 3, + "d": 2 + }, + "examples/stats/fdr_stats_evoked.py": { + "a": 3, + "d": 2 + }, + "examples/stats/linear_regression_raw.py": { + "a": 2, + "d": 1 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 3, + "d": 2 + }, + "examples/stats/sensor_regression.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/compute_csd.py": { + "a": 3, + "d": 2 + }, + "examples/time_frequency/compute_source_psd_epochs.py": { + "a": 6, + "d": 5 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 4, + "d": 3 + }, + "examples/time_frequency/source_power_spectrum.py": { + "a": 4, + "d": 3 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 5, + "d": 5 + }, + "examples/time_frequency/source_space_time_frequency.py": { + "a": 3, + "d": 2 + }, + "examples/time_frequency/temporal_whitening.py": { + "a": 3, + "d": 3 + }, + "examples/visualization/channel_epochs_image.py": { + "a": 3, + "d": 2 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 4, + "d": 3 + }, + "examples/visualization/evoked_arrowmap.py": { + "a": 3, + "d": 3 + }, + "examples/visualization/evoked_topomap.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/evoked_whitening.py": { + "a": 3, + "d": 2 + }, + "examples/visualization/meg_sensors.py": { + "a": 7, + "d": 6 + }, + "examples/visualization/parcellation.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/roi_erpimage_by_rt.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/ssp_projs_sensitivity_map.py": { + "a": 4, + "d": 3 + }, + "examples/visualization/topo_compare_conditions.py": { + "a": 3, + "d": 2 + }, + "examples/visualization/topo_customized.py": { + "a": 2, + "d": 1 + }, + "examples/visualization/xhemi.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 9, + "d": 0 + }, + "mne/datasets/_fetch.py": { + "a": 12, + "d": 6 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 23, + "d": 5 + }, + "mne/datasets/utils.py": { + "a": 40, + "d": 9 + }, + "mne/datasets/visual_92_categories/visual_92_categories.py": { + "a": 2, + "d": 3 + }, + "mne/dipole.py": { + "a": 2, + "d": 4 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 4 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 3, + "d": 2 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 6, + "d": 6 + }, + "mne/preprocessing/tests/test_css.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 5 + }, + "mne/stats/tests/test_regression.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 2 + }, + "mne/utils/tests/test_testing.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 3, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 6 + }, + "tools/circleci_download.sh": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/40_whitened.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/25_automated_coreg.py": { + "a": 2, + "d": 3 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 3, + "d": 6 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 7, + "d": 6 + }, + "tutorials/inverse/40_mne_fixed_free.py": { + "a": 5, + "d": 4 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 5, + "d": 4 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 8, + "d": 8 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 4, + "d": 3 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 2, + "d": 1 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 3, + "d": 2 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 3, + "d": 2 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 7, + "d": 8 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 5, + "d": 6 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 6, + "d": 5 + }, + "tutorials/stats-source-space/70_cluster_rmANOVA_time_freq.py": { + "a": 3, + "d": 2 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10349.json b/mne-python/source/doc/sphinxext/prs/10349.json new file mode 100644 index 0000000000000000000000000000000000000000..20e6afe7539513e3f292c980d3dfa28b65a8b7d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10349.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7c0e36d3f8764137219d1681193081ace91774cd", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 20, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 6, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10350.json b/mne-python/source/doc/sphinxext/prs/10350.json new file mode 100644 index 0000000000000000000000000000000000000000..6cd948cce79ed5d5b1e57c81a4bd1bd3ab206efd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10350.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d2d6ec1eb5fb51289978e8ec34fb19d5c5c02b57", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "examples/time_frequency/time_frequency_erds.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10356.json b/mne-python/source/doc/sphinxext/prs/10356.json new file mode 100644 index 0000000000000000000000000000000000000000..6519f8782894a25c6919aecbb0695958e7380663 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10356.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ffb4ef3d623b9e7202e5078cd3301c8cfc40d5a5", + "authors": [ + { + "n": "rcmdnk", + "e": "rcmdnk@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + }, + "mne/io/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10357.json b/mne-python/source/doc/sphinxext/prs/10357.json new file mode 100644 index 0000000000000000000000000000000000000000..fd399d735432b3136faf38e6d16dab6a939970ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10357.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2520a6d66123c5acb7f6301d49943283adc4a7a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10358.json b/mne-python/source/doc/sphinxext/prs/10358.json new file mode 100644 index 0000000000000000000000000000000000000000..a15f3cb788908265282cbe759ea9546c7473f00b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10358.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "ffbd0957764c838f71815cbce980b6d3ea2c73e8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 14, + "d": 6 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 5 + }, + "mne/io/base.py": { + "a": 21, + "d": 8 + }, + "mne/io/tests/test_raw.py": { + "a": 53, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 17, + "d": 7 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 147, + "d": 11 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10359.json b/mne-python/source/doc/sphinxext/prs/10359.json new file mode 100644 index 0000000000000000000000000000000000000000..f7615d30ff4d83e14f5bd92cf3259a6d3a420ba2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10359.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "01b4bf2f3a4a7f259c4d3377c83aa6e07b62eb09", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 38, + "d": 10 + }, + "mne/viz/_scraper.py": { + "a": 1, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 2, + "d": 2 + }, + "tutorials/intro/10_overview.py": { + "a": 0, + "d": 1 + }, + "tutorials/intro/15_inplace.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1036.json b/mne-python/source/doc/sphinxext/prs/1036.json new file mode 100644 index 0000000000000000000000000000000000000000..e75385df1f82b7cc96eb8966587a0b6aba47fd78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1036.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c079e0a117a27f87916f451f5a3776eaa6cd8408", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 28, + "d": 42 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10361.json b/mne-python/source/doc/sphinxext/prs/10361.json new file mode 100644 index 0000000000000000000000000000000000000000..56a5e7e4a3b3266f951508cba2c8535c7649cd2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10361.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "776b203fb323d7d935a4b76d9e20b13541491e59", + "authors": [ + { + "n": "rcmdnk", + "e": "rcmdnk@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 8, + "d": 6 + }, + "mne/tests/test_annotations.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10362.json b/mne-python/source/doc/sphinxext/prs/10362.json new file mode 100644 index 0000000000000000000000000000000000000000..1f7b63f556b7d8c3bd9a52ef8eef04cbcc21b45c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10362.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c87494462b7935e592efc0dcdc9553de1d0ccc5e", + "authors": [ + { + "n": "rcmdnk", + "e": "rcmdnk@gmail.com" + } + ], + "changes": { + "tutorials/clinical/60_sleep.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10363.json b/mne-python/source/doc/sphinxext/prs/10363.json new file mode 100644 index 0000000000000000000000000000000000000000..3de2bd6f5dd1ded4c61d8efe1d71b60f4bb25a0f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10363.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "732bb1f994e64e41a8e95dcc10dc98c22cac95c0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10364.json b/mne-python/source/doc/sphinxext/prs/10364.json new file mode 100644 index 0000000000000000000000000000000000000000..cabd69e076eaa3802ed6ea35b991db3fd686b5ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10364.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4396a3f7f073ba735d7e578f449496676fdc2bd7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 0, + "d": 5 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 2, + "d": 2 + }, + "tutorials/intro/70_report.py": { + "a": 8, + "d": 7 + }, + "tutorials/inverse/10_stc_class.py": { + "a": 4, + "d": 4 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10365.json b/mne-python/source/doc/sphinxext/prs/10365.json new file mode 100644 index 0000000000000000000000000000000000000000..dbb41976e9df6c0d709773ba05aa7ff6943278c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10365.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "79ea57a4318d8d045f5966c26360b079f40a4865", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10366.json b/mne-python/source/doc/sphinxext/prs/10366.json new file mode 100644 index 0000000000000000000000000000000000000000..f569acced04ae4da80b4d451a9e2508343a5cac9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10366.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e2150ede1cfbdb44ad64268623a3d55ed87a1702", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 21, + "d": 22 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 2, + "d": 4 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 15, + "d": 15 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10368.json b/mne-python/source/doc/sphinxext/prs/10368.json new file mode 100644 index 0000000000000000000000000000000000000000..10e851a06938dfa462524ce6bb905e2e28e32c51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10368.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "54884b563d312270d6442fbd709350a4d72afb8c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 5, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/_qt.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10369.json b/mne-python/source/doc/sphinxext/prs/10369.json new file mode 100644 index 0000000000000000000000000000000000000000..33ca7a7d50fe148be0cd898a9b3f69a40164f684 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10369.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4cf71bf9db388c4d2e6b1eefdd688e1675a13524", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/_static/branch_dropdown.png": { + "a": 0, + "d": 0 + }, + "doc/_static/forking_button.png": { + "a": 0, + "d": 0 + }, + "doc/_static/pull_button.png": { + "a": 0, + "d": 0 + }, + "logo/LICENSE": { + "a": 397, + "d": 0 + }, + "logo/README.md": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10370.json b/mne-python/source/doc/sphinxext/prs/10370.json new file mode 100644 index 0000000000000000000000000000000000000000..b4da9788a246556b079d28d9add1c0aeb09d3c08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10370.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4bbc11e09844dca7211994a217b30dcbf889146f", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/dipole.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10371.json b/mne-python/source/doc/sphinxext/prs/10371.json new file mode 100644 index 0000000000000000000000000000000000000000..9c3aea9f71880f5d9a4b157778923624ceef31b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10371.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "082c8ad100343fda87bde4246c03d559832e2d26", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 10, + "d": 17 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 17, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10373.json b/mne-python/source/doc/sphinxext/prs/10373.json new file mode 100644 index 0000000000000000000000000000000000000000..bed3d4f6fb4f26cb22f8eca7f02b2847c0a3623d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10373.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "4a24000b81373badd378b78b9e930c32ac2c2acf", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/visualization/brain.py": { + "a": 23, + "d": 6 + }, + "mne/dipole.py": { + "a": 1, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 21, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 16, + "d": 21 + }, + "mne/viz/_brain/_brain.py": { + "a": 125, + "d": 23 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 25, + "d": 1 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10375.json b/mne-python/source/doc/sphinxext/prs/10375.json new file mode 100644 index 0000000000000000000000000000000000000000..21f757d274083f97d5cc5c8abf439f433ee7a8c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10375.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4cca31d0c84391531fb60b87d33d98a3af0022e7", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 25, + "d": 57 + }, + "mne/utils/docs.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10376.json b/mne-python/source/doc/sphinxext/prs/10376.json new file mode 100644 index 0000000000000000000000000000000000000000..f1ffc744dbea7a238ad89113a6cc8a2473e39d70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10376.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "761b03c0e1f385fc9d6cebce9ad01f9818e47f42", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 3, + "d": 3 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10377.json b/mne-python/source/doc/sphinxext/prs/10377.json new file mode 100644 index 0000000000000000000000000000000000000000..c573556ee7f71a0816904aa8a3db9b6d4adc00a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10377.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "e7f8ccc24f1a1f85ac929f967f290b49f1b908e9", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 4, + "d": 4 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 7, + "d": 3 + }, + "mne/gui/_coreg.py": { + "a": 61, + "d": 28 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 45, + "d": 9 + }, + "mne/surface.py": { + "a": 99, + "d": 18 + }, + "mne/viz/_3d.py": { + "a": 25, + "d": 14 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10378.json b/mne-python/source/doc/sphinxext/prs/10378.json new file mode 100644 index 0000000000000000000000000000000000000000..6489c42ddaf4007fd6c4442156b6cd5b7f1c1626 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10378.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "f6432882738d000c79778906bcbaace7a3ff940e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 58, + "d": 41 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/_qt.py": { + "a": 33, + "d": 9 + }, + "server_environment.yml": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10379.json b/mne-python/source/doc/sphinxext/prs/10379.json new file mode 100644 index 0000000000000000000000000000000000000000..1003ac2bad46b2ca4fdc708ff461f1465f949019 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10379.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "6d0aa2572221c9a710c5965fab96042f3cf9ad3c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alex", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 168, + "d": 114 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 19, + "d": 15 + }, + "mne/tests/test_transforms.py": { + "a": 5, + "d": 2 + }, + "mne/transforms.py": { + "a": 19, + "d": 2 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1038.json b/mne-python/source/doc/sphinxext/prs/1038.json new file mode 100644 index 0000000000000000000000000000000000000000..5420933643117c67ecc1f073850aa32a64010500 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1038.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8850d07c13de05cd270abea6843d5b54f3737d7d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/cite.rst": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10381.json b/mne-python/source/doc/sphinxext/prs/10381.json new file mode 100644 index 0000000000000000000000000000000000000000..236e7caeb714038c62579583fd24f019964cc97a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10381.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3c3c87670976714a05265d806b0e1834ea875585", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10384.json b/mne-python/source/doc/sphinxext/prs/10384.json new file mode 100644 index 0000000000000000000000000000000000000000..9a1b4f58ab03edb46af4e31607965bbb848dff5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10384.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f1c7fc696ea3b8fa48bdee8f89d949766975907e", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10385.json b/mne-python/source/doc/sphinxext/prs/10385.json new file mode 100644 index 0000000000000000000000000000000000000000..209ffd1f688f03de004d0bee403b765ec6909254 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10385.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3a79a2319fafe53dd1155de235d07959b48d8b23", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 23, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10386.json b/mne-python/source/doc/sphinxext/prs/10386.json new file mode 100644 index 0000000000000000000000000000000000000000..8a46a0c6a01f7cdc766b7866b400e17235bb878a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10386.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0799d4c68e68ed0f226cbc33c03936ccc0a5a313", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "tutorials/io/30_reading_fnirs_data.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10388.json b/mne-python/source/doc/sphinxext/prs/10388.json new file mode 100644 index 0000000000000000000000000000000000000000..1f379f8e62ddba1e4f09eb59dc86ee221f0004d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10388.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "61f10d539fcb3e95943eb1462771a3538d53a772", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 3, + "d": 2 + }, + "mne/gui/_coreg.py": { + "a": 4, + "d": 9 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 2, + "d": 1 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 8, + "d": 0 + }, + "mne/utils/misc.py": { + "a": 11, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 5, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 4, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 20, + "d": 4 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1039.json b/mne-python/source/doc/sphinxext/prs/1039.json new file mode 100644 index 0000000000000000000000000000000000000000..d732f2f854836278184c79cfe5d0a1b33c2922b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1039.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b0892d20b8e4408714946ea16e68932ff5a0d1ab", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 11, + "d": 10 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10392.json b/mne-python/source/doc/sphinxext/prs/10392.json new file mode 100644 index 0000000000000000000000000000000000000000..3ad079dd552fe9bd55281ee2b6a03a448de96d49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10392.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5e101bc0ff80b8ee022f24de00e1c4c9ebaae00b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10393.json b/mne-python/source/doc/sphinxext/prs/10393.json new file mode 100644 index 0000000000000000000000000000000000000000..f396886c453a4e45973af7906f05d98cb4fd891a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10393.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "373f63591de506c6f173e8598fb1c20dbbe85539", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 31, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10395.json b/mne-python/source/doc/sphinxext/prs/10395.json new file mode 100644 index 0000000000000000000000000000000000000000..1e0a75e380cf8da42cf685280c43bf14badcbc45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10395.json @@ -0,0 +1,687 @@ +{ + "merge_commit_sha": "6608b720b214529732542cb2aac11b401770eddf", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "examples/datasets/brainstorm_data.py": { + "a": 1, + "d": 0 + }, + "examples/datasets/hf_sef_data.py": { + "a": 1, + "d": 0 + }, + "examples/datasets/limo_data.py": { + "a": 1, + "d": 0 + }, + "examples/datasets/opm_data.py": { + "a": 1, + "d": 0 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 1, + "d": 0 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 1, + "d": 0 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 1, + "d": 0 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 2, + "d": 1 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 1, + "d": 0 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 3, + "d": 0 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 3, + "d": 0 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 1, + "d": 0 + }, + "examples/decoding/ems_filtering.py": { + "a": 1, + "d": 0 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 1, + "d": 0 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 3, + "d": 0 + }, + "examples/forward/forward_sensitivity_maps.py": { + "a": 1, + "d": 0 + }, + "examples/forward/left_cerebellum_volume_source.py": { + "a": 3, + "d": 0 + }, + "examples/forward/source_space_morphing.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/compute_mne_inverse_epochs_in_label.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/custom_inverse_solver.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/dics_source_power.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/gamma_map_inverse.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/label_activation_from_stc.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/label_from_stc.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/label_source_activations.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/mne_cov_power.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/morph_surface_stc.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/multidict_reweighted_tfmxne.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/psf_ctf_vertices.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/psf_ctf_vertices_lcmv.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/rap_music.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/read_inverse.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/read_stc.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/resolution_metrics.py": { + "a": 5, + "d": 2 + }, + "examples/inverse/resolution_metrics_eegmeg.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/snr_estimate.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/source_space_snr.py": { + "a": 4, + "d": 2 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/vector_mne_solution.py": { + "a": 1, + "d": 1 + }, + "examples/io/elekta_epochs.py": { + "a": 1, + "d": 0 + }, + "examples/io/read_neo_format.py": { + "a": 3, + "d": 1 + }, + "examples/io/read_noise_covariance_matrix.py": { + "a": 3, + "d": 0 + }, + "examples/io/read_xdf.py": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/css.py": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/define_target_events.py": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/fnirs_artifact_removal.py": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/ica_comparison.py": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/interpolate_bad_channels.py": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/movement_compensation.py": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/movement_detection.py": { + "a": 3, + "d": 2 + }, + "examples/preprocessing/muscle_detection.py": { + "a": 5, + "d": 2 + }, + "examples/preprocessing/otp.py": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/shift_evoked.py": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/virtual_evoked.py": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/xdawn_denoising.py": { + "a": 1, + "d": 0 + }, + "examples/simulation/simulate_evoked_data.py": { + "a": 3, + "d": 0 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 3, + "d": 0 + }, + "examples/simulation/simulated_raw_data_using_subject_anatomy.py": { + "a": 3, + "d": 0 + }, + "examples/simulation/source_simulator.py": { + "a": 3, + "d": 0 + }, + "examples/stats/cluster_stats_evoked.py": { + "a": 16, + "d": 14 + }, + "examples/stats/fdr_stats_evoked.py": { + "a": 3, + "d": 0 + }, + "examples/stats/linear_regression_raw.py": { + "a": 3, + "d": 0 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 3, + "d": 0 + }, + "examples/stats/sensor_regression.py": { + "a": 5, + "d": 2 + }, + "examples/time_frequency/compute_csd.py": { + "a": 5, + "d": 2 + }, + "examples/time_frequency/compute_source_psd_epochs.py": { + "a": 3, + "d": 0 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 3, + "d": 0 + }, + "examples/time_frequency/source_power_spectrum.py": { + "a": 3, + "d": 0 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 1, + "d": 0 + }, + "examples/time_frequency/source_space_time_frequency.py": { + "a": 3, + "d": 0 + }, + "examples/time_frequency/temporal_whitening.py": { + "a": 3, + "d": 0 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 3, + "d": 0 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 1, + "d": 0 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 3, + "d": 0 + }, + "examples/visualization/3d_to_2d.py": { + "a": 1, + "d": 0 + }, + "examples/visualization/brain.py": { + "a": 1, + "d": 0 + }, + "examples/visualization/channel_epochs_image.py": { + "a": 3, + "d": 0 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 1, + "d": 0 + }, + "examples/visualization/eeglab_head_sphere.py": { + "a": 1, + "d": 0 + }, + "examples/visualization/evoked_arrowmap.py": { + "a": 3, + "d": 0 + }, + "examples/visualization/evoked_whitening.py": { + "a": 1, + "d": 0 + }, + "examples/visualization/meg_sensors.py": { + "a": 1, + "d": 0 + }, + "examples/visualization/mne_helmet.py": { + "a": 4, + "d": 0 + }, + "examples/visualization/parcellation.py": { + "a": 2, + "d": 0 + }, + "examples/visualization/publication_figure.py": { + "a": 1, + "d": 0 + }, + "examples/visualization/roi_erpimage_by_rt.py": { + "a": 3, + "d": 0 + }, + "examples/visualization/sensor_noise_level.py": { + "a": 2, + "d": 0 + }, + "examples/visualization/ssp_projs_sensitivity_map.py": { + "a": 3, + "d": 0 + }, + "examples/visualization/topo_compare_conditions.py": { + "a": 3, + "d": 0 + }, + "examples/visualization/topo_customized.py": { + "a": 3, + "d": 0 + }, + "examples/visualization/xhemi.py": { + "a": 2, + "d": 0 + }, + "tutorials/clinical/20_seeg.py": { + "a": 1, + "d": 0 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 0 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 1, + "d": 0 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/40_whitened.py": { + "a": 4, + "d": 0 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 1, + "d": 0 + }, + "tutorials/forward/25_automated_coreg.py": { + "a": 3, + "d": 0 + }, + "tutorials/forward/30_forward.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 1, + "d": 0 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 0 + }, + "tutorials/intro/15_inplace.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 1, + "d": 0 + }, + "tutorials/intro/30_info.py": { + "a": 1, + "d": 0 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 1, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/10_stc_class.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 1, + "d": 0 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 4, + "d": 0 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 1, + "d": 0 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 0 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 0 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 1, + "d": 0 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 2, + "d": 0 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 4, + "d": 1 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 2, + "d": 0 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 1, + "d": 0 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 1, + "d": 0 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 1, + "d": 0 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 1, + "d": 0 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 2, + "d": 0 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 4, + "d": 0 + }, + "tutorials/simulation/80_dics.py": { + "a": 3, + "d": 0 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 5, + "d": 2 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 3, + "d": 0 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 1, + "d": 2 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 3, + "d": 0 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 3, + "d": 0 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 3, + "d": 0 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 3, + "d": 0 + }, + "tutorials/stats-source-space/70_cluster_rmANOVA_time_freq.py": { + "a": 1, + "d": 0 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 1, + "d": 0 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10396.json b/mne-python/source/doc/sphinxext/prs/10396.json new file mode 100644 index 0000000000000000000000000000000000000000..b0e7d3a878ec7172161a88dedbb954f0ae51b0ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10396.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bbcd975b1288a1a5a34088fed57caa67988d5922", + "authors": [ + { + "n": "rcmdnk", + "e": "rcmdnk@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/annotations.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10397.json b/mne-python/source/doc/sphinxext/prs/10397.json new file mode 100644 index 0000000000000000000000000000000000000000..173a3fe2cb1f9e736dbf678f169754c7bd958b65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10397.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "195df2ac9f88c03913f6292c99a7addfb3a99ecb", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 12, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10399.json b/mne-python/source/doc/sphinxext/prs/10399.json new file mode 100644 index 0000000000000000000000000000000000000000..aada5448cd31d008b5822ff087f9b7a95b0268bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10399.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7214707dad2df89df646e523426a5df33bf4bf0a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/config.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1040.json b/mne-python/source/doc/sphinxext/prs/1040.json new file mode 100644 index 0000000000000000000000000000000000000000..611d86cb8b8727561214bc3a7c36f0aa5c982de1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1040.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cf7b40bd97def4396662406a3d3941e846683a93", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 74, + "d": 54 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10400.json b/mne-python/source/doc/sphinxext/prs/10400.json new file mode 100644 index 0000000000000000000000000000000000000000..bcda1f124eb66e3b4ec8cb122ffabee95fa4595d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10400.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d25c87d65238e4a0b1f583be1dde2defcff0a5c6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 0, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10401.json b/mne-python/source/doc/sphinxext/prs/10401.json new file mode 100644 index 0000000000000000000000000000000000000000..c672202aa39fa016e6b972ddc7f33640321d62f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10401.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "7a1e900ad1db8a271142c32a8d7e5dd8d0e38ca7", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 7, + "d": 1 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 1, + "d": 2 + }, + "mne/stats/cluster_level.py": { + "a": 19, + "d": 16 + }, + "mne/stats/parametric.py": { + "a": 6, + "d": 3 + }, + "mne/stats/tests/test_parametric.py": { + "a": 6, + "d": 0 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 9, + "d": 9 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 149, + "d": 8 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/70_cluster_rmANOVA_time_freq.py": { + "a": 54, + "d": 50 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10406.json b/mne-python/source/doc/sphinxext/prs/10406.json new file mode 100644 index 0000000000000000000000000000000000000000..9d7a5f0f887e5a1fe2da11316f090b138ce036a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10406.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6fa13b73caacccdf1487035fbc9190395a00a981", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/check.py": { + "a": 40, + "d": 5 + }, + "mne/utils/tests/test_check.py": { + "a": 53, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10407.json b/mne-python/source/doc/sphinxext/prs/10407.json new file mode 100644 index 0000000000000000000000000000000000000000..0897a9e4b936fac7ca67c754d3a8b74a56bedc92 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10407.json @@ -0,0 +1,211 @@ +{ + "merge_commit_sha": "31a83063557fbd54d898f00f9527ffc547888395", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 2, + "d": 2 + }, + "mne/baseline.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 9, + "d": 8 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 13, + "d": 13 + }, + "mne/cov.py": { + "a": 28, + "d": 28 + }, + "mne/decoding/csp.py": { + "a": 7, + "d": 7 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 34, + "d": 34 + }, + "mne/evoked.py": { + "a": 12, + "d": 12 + }, + "mne/export/_egimff.py": { + "a": 1, + "d": 1 + }, + "mne/export/_export.py": { + "a": 7, + "d": 7 + }, + "mne/filter.py": { + "a": 14, + "d": 14 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 23, + "d": 23 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/proj.py": { + "a": 5, + "d": 5 + }, + "mne/io/reference.py": { + "a": 4, + "d": 4 + }, + "mne/label.py": { + "a": 11, + "d": 11 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 21, + "d": 21 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/ecg.py": { + "a": 10, + "d": 10 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 38, + "d": 38 + }, + "mne/rank.py": { + "a": 5, + "d": 5 + }, + "mne/report/report.py": { + "a": 40, + "d": 40 + }, + "mne/source_estimate.py": { + "a": 21, + "d": 21 + }, + "mne/stats/cluster_level.py": { + "a": 44, + "d": 44 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 26, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 7 + }, + "mne/utils/docs.py": { + "a": 2845, + "d": 2463 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 4, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 12, + "d": 12 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 6 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 13, + "d": 13 + }, + "mne/viz/topomap.py": { + "a": 66, + "d": 66 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10408.json b/mne-python/source/doc/sphinxext/prs/10408.json new file mode 100644 index 0000000000000000000000000000000000000000..7d4bb617583bda79bedd2a9c31f8bee0a751e9b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10408.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "67eccfbcb3e7e3f9634f12fdf6c3f4f16f91feca", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/snirf/_snirf.py": { + "a": 20, + "d": 5 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 21, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10409.json b/mne-python/source/doc/sphinxext/prs/10409.json new file mode 100644 index 0000000000000000000000000000000000000000..e017149f624816e8cda3611a679c609332221734 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10409.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b2e3005f1a2ec31d57027eef0ef434c70c2633d1", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1041.json b/mne-python/source/doc/sphinxext/prs/1041.json new file mode 100644 index 0000000000000000000000000000000000000000..e312e248c321190ada0a345b49d92d93b2d50fe7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1041.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cd1bc42cbc0b9e7e46029302f674b357b6ba4027", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/proj.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10411.json b/mne-python/source/doc/sphinxext/prs/10411.json new file mode 100644 index 0000000000000000000000000000000000000000..1465d55fb690fbf1e41fb0e95c03fa368c4babf5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10411.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "84ec00016f7ae354ef4bbbe7aeb4c5e91cfd9b64", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".github/workflows/linux_conda.yml": { + "a": 44, + "d": 3 + }, + "azure-pipelines.yml": { + "a": 0, + "d": 46 + }, + "server_environment.yml": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10412.json b/mne-python/source/doc/sphinxext/prs/10412.json new file mode 100644 index 0000000000000000000000000000000000000000..207e43cd7a14daba8a30fb2822eac94b1eae8f3d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10412.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "a93c198d3d6fd9bad27c3f6d4fb879db980330ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "logo/generate_mne_logos.py": { + "a": 22, + "d": 7 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 1 + }, + "mne/icons/mne-splash.png": { + "a": 0, + "d": 0 + }, + "mne/icons/mne.qrc": { + "a": 1, + "d": 0 + }, + "mne/icons/resources.py": { + "a": 2950, + "d": 1127 + }, + "mne/viz/_figure.py": { + "a": 3, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 4, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 15, + "d": 5 + }, + "mne/viz/backends/_qt.py": { + "a": 11, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 36, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10414.json b/mne-python/source/doc/sphinxext/prs/10414.json new file mode 100644 index 0000000000000000000000000000000000000000..7909ee40dced8ba930a1a9b0be5eb29f3f8ff127 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10414.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6e2c52c592be02de3c798c98b21cfdc1d6e264ad", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_qt.py": { + "a": 4, + "d": 28 + }, + "mne/viz/backends/_utils.py": { + "a": 29, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10415.json b/mne-python/source/doc/sphinxext/prs/10415.json new file mode 100644 index 0000000000000000000000000000000000000000..fdcf535fc80d9de16a76e66c5bd37ee7c76633fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10415.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fec2972c6257b358d0bfbd0d35a59e7e83630158", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10416.json b/mne-python/source/doc/sphinxext/prs/10416.json new file mode 100644 index 0000000000000000000000000000000000000000..a51bea3a7d416dd37976dfd2a6314d52524603a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10416.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c7df0d91cae4b87958f21f0bbfc944ab62ba8763", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 31, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10417.json b/mne-python/source/doc/sphinxext/prs/10417.json new file mode 100644 index 0000000000000000000000000000000000000000..539cffa2d1f888c32fbbc660a51e4dd0ae60e14e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10417.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "8f46d3ea80dabdf7f6499acfc7d114ef8a32302b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 13, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 5 + }, + "mne/viz/_figure.py": { + "a": 1, + "d": 3 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 5, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 6, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10418.json b/mne-python/source/doc/sphinxext/prs/10418.json new file mode 100644 index 0000000000000000000000000000000000000000..9037dfd9616d795565ecea9364cfd93c2dd8341a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10418.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "20366bb72785fe7f5cf08cdf4783503e3a312edf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 14, + "d": 2 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 3, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 12, + "d": 5 + }, + "mne/viz/_brain/_brain.py": { + "a": 9, + "d": 6 + }, + "mne/viz/_figure.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 3, + "d": 6 + }, + "mne/viz/backends/_utils.py": { + "a": 39, + "d": 22 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10421.json b/mne-python/source/doc/sphinxext/prs/10421.json new file mode 100644 index 0000000000000000000000000000000000000000..f3abd99a7aa182de99bfef1188afa0203bc076aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10421.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5704330f7d9cb549427a9861b2489d29eebe2f45", + "authors": [ + { + "n": "Joshua Teves", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/source_space.rst": { + "a": 1, + "d": 0 + }, + "mne/source_space.py": { + "a": 37, + "d": 0 + }, + "mne/tests/test_source_space.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10423.json b/mne-python/source/doc/sphinxext/prs/10423.json new file mode 100644 index 0000000000000000000000000000000000000000..9cdea5440340e9c099e75e6579554daf2db91fe5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10423.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0ac9eba4c359ea8aaaa8b05d2c83114286d4da2d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_ieeg_locate_gui.py": { + "a": 4, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10424.json b/mne-python/source/doc/sphinxext/prs/10424.json new file mode 100644 index 0000000000000000000000000000000000000000..7568f7f106abc7bef09f40a9352cb5b6c03c643f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10424.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "40e7e2ab9afc007e58cb03269c7738e9ee010532", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/linux_conda.yml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10425.json b/mne-python/source/doc/sphinxext/prs/10425.json new file mode 100644 index 0000000000000000000000000000000000000000..2455f4b6fd3e38d20241c094ec77e74cdd98a420 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10425.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1b14d458cbcd391a6907032b809ec37410b60592", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/utils/_testing.py": { + "a": 5, + "d": 2 + }, + "tools/azure_dependencies.sh": { + "a": 3, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10429.json b/mne-python/source/doc/sphinxext/prs/10429.json new file mode 100644 index 0000000000000000000000000000000000000000..34be30811365ee950b2d1cea6304415460ed19ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10429.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8507b1c3f7ff7457f9cd429be914dcca0f6dc9c5", + "authors": [ + { + "n": "Matthias Eberlein", + "e": "matthias.eberlein@tu-dresden.de" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 29, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1043.json b/mne-python/source/doc/sphinxext/prs/1043.json new file mode 100644 index 0000000000000000000000000000000000000000..4ef3a7013e942ec29b7e5bfb6a8e2dbe10577665 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1043.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f2b834b0f1da448ad448f95dc920b9c3f7205ee3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".coveragerc": { + "a": 8, + "d": 0 + }, + ".travis.yml": { + "a": 26, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10430.json b/mne-python/source/doc/sphinxext/prs/10430.json new file mode 100644 index 0000000000000000000000000000000000000000..2d4468fb39dd5911ed3ad33fe8f59824219c9518 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10430.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "af685332c76332e6ab50aeb401276a89c9e3cce1", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 40, + "d": 44 + }, + "doc/install/check_installation.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 9, + "d": 9 + }, + "mne/gui/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 17, + "d": 17 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 13, + "d": 11 + }, + "mne/utils/config.py": { + "a": 13, + "d": 5 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_qt.py": { + "a": 24, + "d": 19 + }, + "mne/viz/backends/_utils.py": { + "a": 6, + "d": 7 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 9, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10431.json b/mne-python/source/doc/sphinxext/prs/10431.json new file mode 100644 index 0000000000000000000000000000000000000000..905c854a085c88a1eb983cff0166f611d9512358 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10431.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "eb1ed981fcab62c0892c02cae9fa087bc08bc522", + "authors": [ + { + "n": "Matthias Eberlein", + "e": "matthias.eberlein@tu-dresden.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 4, + "d": 5 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10432.json b/mne-python/source/doc/sphinxext/prs/10432.json new file mode 100644 index 0000000000000000000000000000000000000000..d4b17c01c9d5eb9799367e17db275d3c81aba111 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10432.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "400de94d556e9ec6c6f6308024a6e3417e54ba9a", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 1, + "d": 100 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 15 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 3, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 106, + "d": 6 + }, + "mne/io/tests/test_meas_info.py": { + "a": 22, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10433.json b/mne-python/source/doc/sphinxext/prs/10433.json new file mode 100644 index 0000000000000000000000000000000000000000..e9579508c5effba734b1fe7226c52c11e348e038 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10433.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2427d3b2f1a75a92664e919bb5a7071df8ea92fd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10434.json b/mne-python/source/doc/sphinxext/prs/10434.json new file mode 100644 index 0000000000000000000000000000000000000000..3b2ccacc8da95db4ce43d73b8432c548ae7f0f92 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10434.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2e0753da5c0fee1768bda1a77a72f9b67e9ae863", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10436.json b/mne-python/source/doc/sphinxext/prs/10436.json new file mode 100644 index 0000000000000000000000000000000000000000..81c28924d75eb8d7b98440fc916089790f6202f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10436.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "38caebe4dfd9b96a9fa0619675b8df9b7bb46808", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/_static/mne_installer_console.png": { + "a": 0, + "d": 0 + }, + "doc/_static/mne_installer_macOS.png": { + "a": 0, + "d": 0 + }, + "doc/conf.py": { + "a": 4, + "d": 1 + }, + "doc/index.rst": { + "a": 5, + "d": 5 + }, + "doc/install/advanced.rst": { + "a": 48, + "d": 19 + }, + "doc/install/check_installation.rst": { + "a": 77, + "d": 0 + }, + "doc/install/index.rst": { + "a": 10, + "d": 53 + }, + "doc/install/install_type_selector.html": { + "a": 40, + "d": 0 + }, + "doc/install/installers.rst": { + "a": 62, + "d": 0 + }, + "doc/install/installers_platform_selector.html": { + "a": 79, + "d": 0 + }, + "doc/install/manual_install.rst": { + "a": 115, + "d": 0 + }, + "doc/install/manual_install_python.rst": { + "a": 3, + "d": 1 + }, + "doc/install/mne_python.rst": { + "a": 0, + "d": 257 + }, + "doc/install/mne_tools_suite.rst": { + "a": 2, + "d": 1 + }, + "doc/install/updating.rst": { + "a": 8, + "d": 0 + }, + "doc/links.inc": { + "a": 5, + "d": 2 + }, + "doc/overview/faq.rst": { + "a": 1, + "d": 2 + }, + "doc/overview/get_help.rst": { + "a": 1, + "d": 1 + }, + "doc/overview/index.rst": { + "a": 3, + "d": 4 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10438.json b/mne-python/source/doc/sphinxext/prs/10438.json new file mode 100644 index 0000000000000000000000000000000000000000..ee4e5f5155d480eb9e8c5399e2d0e5cdf51aee5e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10438.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "306adb67fcaadf88fc88011d74b18359a0ecd1ff", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 96, + "d": 50 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 0, + "d": 4 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 3 + }, + "mne/viz/backends/_notebook.py": { + "a": 154, + "d": 17 + }, + "mne/viz/backends/_qt.py": { + "a": 3, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10439.json b/mne-python/source/doc/sphinxext/prs/10439.json new file mode 100644 index 0000000000000000000000000000000000000000..b5aed117f7bea748d00cf8690e4f166bd9455e17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10439.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a6d407da0b263ee098357c15daf0040c463bab98", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/viz/circle.py": { + "a": 37, + "d": 33 + }, + "tutorials/clinical/20_seeg.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1044.json b/mne-python/source/doc/sphinxext/prs/1044.json new file mode 100644 index 0000000000000000000000000000000000000000..cdad5102117523eb487134df3f3e16de551eee39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1044.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a4979c891b51adfa740efa46e05f253688cceeb9", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/epochs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10441.json b/mne-python/source/doc/sphinxext/prs/10441.json new file mode 100644 index 0000000000000000000000000000000000000000..1f8a6502a6568d747bfdeb96e4edaa6edf22c676 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10441.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f3fc6e4093cefb70488e705e9b3cb41d0cdf8e59", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/viz/circle.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10442.json b/mne-python/source/doc/sphinxext/prs/10442.json new file mode 100644 index 0000000000000000000000000000000000000000..d0f95c5d874aa0ae547f4fa9acc17c6d7ce8b132 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10442.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "634544ba9a003fb6635ae1bdd89b7a15aac4c22e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_coreg.py": { + "a": 11, + "d": 8 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10443.json b/mne-python/source/doc/sphinxext/prs/10443.json new file mode 100644 index 0000000000000000000000000000000000000000..3d09dde3234bf60e2aa6b5dbd97b3812c4e69ed8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10443.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6faab5f33e66d9fc68b1990ccc4c45cc676dd84a", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/viz/circle.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10444.json b/mne-python/source/doc/sphinxext/prs/10444.json new file mode 100644 index 0000000000000000000000000000000000000000..9c23017e6207b6949f40747b7b533c5abc6d2270 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10444.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "45f6c2f60312aab09d5c7c88b17114b0eabab116", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10448.json b/mne-python/source/doc/sphinxext/prs/10448.json new file mode 100644 index 0000000000000000000000000000000000000000..a997febc525681b45573c7078307ac5c038150bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10448.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c20d4c7e78e1cd9ad2a70c6160133129b3d20596", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/check_installation.rst": { + "a": 1, + "d": 1 + }, + "doc/install/installers.rst": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10450.json b/mne-python/source/doc/sphinxext/prs/10450.json new file mode 100644 index 0000000000000000000000000000000000000000..37fefdaa147fbb55164a77474d3ae93c53120b8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10450.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "38ffd9b1edff7ecf1ed507dfc9c9a4cf3730451c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/compat_minimal.yml": { + "a": 1, + "d": 2 + }, + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 2 + }, + ".github/workflows/linux_conda.yml": { + "a": 1, + "d": 2 + }, + ".github/workflows/linux_pip.yml": { + "a": 1, + "d": 2 + }, + ".github/workflows/macos_conda.yml": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10452.json b/mne-python/source/doc/sphinxext/prs/10452.json new file mode 100644 index 0000000000000000000000000000000000000000..b7645f3b8b0533459ae548d87a8137549fafc244 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10452.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cd5a5608d2183efdab2625627584913cdeddbba6", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10455.json b/mne-python/source/doc/sphinxext/prs/10455.json new file mode 100644 index 0000000000000000000000000000000000000000..8481a436cc6da3fab27f82f6385afdd24ac8ad88 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10455.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8fde21e3da598dd53c01cd23e1b5bb24d6ecf6df", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/_notebook.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10456.json b/mne-python/source/doc/sphinxext/prs/10456.json new file mode 100644 index 0000000000000000000000000000000000000000..f0fe6cf5fc4706242dd7b12df65c5ab22aceb1e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10456.json @@ -0,0 +1,199 @@ +{ + "merge_commit_sha": "4301092691d279314d3a46ee58de66a6f3a6152a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 0, + "d": 3 + }, + "mne/icons/README.rst": { + "a": 0, + "d": 12 + }, + "mne/icons/clear-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/icons/dark/actions/clear.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/help.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/movie.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/pause.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/play.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/reset.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/restore.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/scale.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/screenshot.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/visibility_off.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/actions/visibility_on.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/dark/index.theme": { + "a": 11, + "d": 0 + }, + "mne/icons/help-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/icons/light/actions/clear.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/help.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/movie.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/pause.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/play.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/reset.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/restore.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/scale.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/screenshot.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/visibility_off.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/visibility_on.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/index.theme": { + "a": 11, + "d": 0 + }, + "mne/icons/mne.qrc": { + "a": 0, + "d": 18 + }, + "mne/icons/mne_bigsur_icon.png": { + "a": 0, + "d": 0 + }, + "mne/icons/mne_default_icon.png": { + "a": 0, + "d": 0 + }, + "mne/icons/mne_splash.png": { + "a": 0, + "d": 0 + }, + "mne/icons/movie-black-18dp.svg": { + "a": 0, + "d": 72 + }, + "mne/icons/pause-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/icons/play-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/icons/reset-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/icons/resources.py": { + "a": 0, + "d": 6075 + }, + "mne/icons/restore-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/icons/scale-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/icons/screenshot-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/icons/visibility_off-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/icons/visibility_on-black-18dp.svg": { + "a": 0, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 7 + }, + "mne/viz/backends/_abstract.py": { + "a": 0, + "d": 4 + }, + "mne/viz/backends/_notebook.py": { + "a": 0, + "d": 3 + }, + "mne/viz/backends/_qt.py": { + "a": 26, + "d": 25 + }, + "mne/viz/backends/_utils.py": { + "a": 30, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10457.json b/mne-python/source/doc/sphinxext/prs/10457.json new file mode 100644 index 0000000000000000000000000000000000000000..39491ec67558781df230016655f12707e952a8e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10457.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cf8543c8d609d717cd39d69d49431d3da73a7fdb", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 9, + "d": 3 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 113, + "d": 103 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10458.json b/mne-python/source/doc/sphinxext/prs/10458.json new file mode 100644 index 0000000000000000000000000000000000000000..fbeae927ed270c0aaa5a84c91745951ddd985d60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10458.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "4359456cfc9debb581d290acf4b677f4c31bed92", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 2, + "d": 0 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 0, + "d": 1 + }, + "mne/icons/dark/actions/folder.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/light/actions/folder.svg": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 0, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 8, + "d": 6 + }, + "mne/viz/backends/_notebook.py": { + "a": 37, + "d": 21 + }, + "mne/viz/backends/_qt.py": { + "a": 27, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10459.json b/mne-python/source/doc/sphinxext/prs/10459.json new file mode 100644 index 0000000000000000000000000000000000000000..078d02faf59da472c4ad7f38f0bfef2b309c5b79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10459.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "933e35c19b917989fe6fe8917118d9bddc2e7ae7", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 9, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 29, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10460.json b/mne-python/source/doc/sphinxext/prs/10460.json new file mode 100644 index 0000000000000000000000000000000000000000..1638f76a6aed39fa4461b80deafd407875b981a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10460.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6bb14380fcb2108b336a0436a6f17d929735a0db", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 31, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 35, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10461.json b/mne-python/source/doc/sphinxext/prs/10461.json new file mode 100644 index 0000000000000000000000000000000000000000..c164a8f336ad1a860038d749690107bbf408c47f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10461.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cdbd0459b71be3e094d8c85badc69a33a5b68d2c", + "authors": [ + { + "n": "Simon Kern", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/montage.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10462.json b/mne-python/source/doc/sphinxext/prs/10462.json new file mode 100644 index 0000000000000000000000000000000000000000..3db4eca717e63a70b1de87fca027ebdb2fd1150e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10462.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "091da8f01aeeecd7d583ba596cf5a85cd649f192", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "tutorials/preprocessing/25_background_filtering.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10463.json b/mne-python/source/doc/sphinxext/prs/10463.json new file mode 100644 index 0000000000000000000000000000000000000000..81a9df7e8c39f3f0f492f04a9e808a3f268f2043 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10463.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "60eebfdff97028061647d96b2cfebbbf3a7eef16", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/install/advanced.rst": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10464.json b/mne-python/source/doc/sphinxext/prs/10464.json new file mode 100644 index 0000000000000000000000000000000000000000..3475f9bcd7cfd949aeeb098ec114246db829e520 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10464.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "8233041319f97195db35db2461bf155cefe50f36", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/multi_dipole_model.py": { + "a": 166, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 6, + "d": 0 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 4, + "d": 6 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 6, + "d": 6 + }, + "mne/minimum_norm/inverse.py": { + "a": 26, + "d": 6 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 19, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10473.json b/mne-python/source/doc/sphinxext/prs/10473.json new file mode 100644 index 0000000000000000000000000000000000000000..a3362e3efb34b48642555e42f61f1ef5c87f4cd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10473.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1a58d7c5def8ee46d939f461811ff8fbf1283538", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/evoked/30_eeg_erp.py": { + "a": 191, + "d": 180 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10478.json b/mne-python/source/doc/sphinxext/prs/10478.json new file mode 100644 index 0000000000000000000000000000000000000000..65fc50ec326d0068ec7cbf62d70d83d9f3c50bb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10478.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2c3e97f4f8d5b6f8bc55679e8d26135064481105", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/install/installers.rst": { + "a": 1, + "d": 1 + }, + "doc/install/installers_platform_selector.html": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10479.json b/mne-python/source/doc/sphinxext/prs/10479.json new file mode 100644 index 0000000000000000000000000000000000000000..42e6788ad2821c8b50cd95070ed181e6e2a99144 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10479.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d203c226bf9a6b74708ee9ebcea2bcc17eea7fb5", + "authors": [ + { + "n": "Sondre Foslien", + "e": null + } + ], + "changes": { + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1048.json b/mne-python/source/doc/sphinxext/prs/1048.json new file mode 100644 index 0000000000000000000000000000000000000000..7e7ea4072cd9ea6c4a73891ce7e6b2038227bd8f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1048.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2bd975aa3f048249bda8bba606a81f3dd1633b88", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_evoked_topomap.py": { + "a": 4, + "d": 4 + }, + "mne/fiff/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 12, + "d": 0 + }, + "mne/viz.py": { + "a": 15, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10484.json b/mne-python/source/doc/sphinxext/prs/10484.json new file mode 100644 index 0000000000000000000000000000000000000000..c3177c9fa6ef0c21a19bde71254eb40f7b60287b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10484.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b226f7048243f620a66f34108aa865bbea3a1a8e", + "authors": [ + { + "n": "matthiasdold", + "e": "matthias.dold@gmx.net" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_pick.py": { + "a": 19, + "d": 0 + }, + "mne/preprocessing/_csd.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10485.json b/mne-python/source/doc/sphinxext/prs/10485.json new file mode 100644 index 0000000000000000000000000000000000000000..3d2a88bb09c198163daafca042ba84244ac7b4d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10485.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "c992168eb556526b06cbba494b6a938dbb3729f6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 7, + "d": 2 + }, + "mne/report/report.py": { + "a": 24, + "d": 11 + }, + "mne/report/tests/test_report.py": { + "a": 20, + "d": 2 + }, + "mne/utils/_bunch.py": { + "a": 4, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 1 + }, + "mne/viz/_scraper.py": { + "a": 41, + "d": 10 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 3 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 2 + }, + "tutorials/intro/70_report.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10487.json b/mne-python/source/doc/sphinxext/prs/10487.json new file mode 100644 index 0000000000000000000000000000000000000000..e46dc45bce3a25bcd66edab3cc7b92ffa26698c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10487.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a191018c2a7732e8637f827dbf04d6e8fee3b405", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10488.json b/mne-python/source/doc/sphinxext/prs/10488.json new file mode 100644 index 0000000000000000000000000000000000000000..1bbca3a762e5f9d7555d13f75551abb88f535556 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10488.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2fb83987ef0999788b7aede3091753583491b57d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "mne/datasets/config.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10489.json b/mne-python/source/doc/sphinxext/prs/10489.json new file mode 100644 index 0000000000000000000000000000000000000000..c26c840592c97d4755951e7626600b243a2eb642 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10489.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2052b15cf1194bfa19c1b168b8b530c82d67f839", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/datasets/_fsaverage/base.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/_phantom/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/config.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1049.json b/mne-python/source/doc/sphinxext/prs/1049.json new file mode 100644 index 0000000000000000000000000000000000000000..d3a446daba17609b38a21ba1c80e469b487905d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1049.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bc16701b5078bab2753ee896801256ac57d30ca5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10491.json b/mne-python/source/doc/sphinxext/prs/10491.json new file mode 100644 index 0000000000000000000000000000000000000000..6d7935b61b5eea476367096b07ce3a18e59f9cc9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10491.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "2f53da713804847cc4e122b3ce1f784470258280", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 10, + "d": 2 + }, + "mne/io/base.py": { + "a": 8, + "d": 2 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 61, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10492.json b/mne-python/source/doc/sphinxext/prs/10492.json new file mode 100644 index 0000000000000000000000000000000000000000..d3d4539d926ac3ef29357e2e787ec3365cd0bf90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10492.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7796a9316c825ae007be3476f64eae4e0e1dde49", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10493.json b/mne-python/source/doc/sphinxext/prs/10493.json new file mode 100644 index 0000000000000000000000000000000000000000..e53147312d065200c8c428a64cbd281839c59f78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10493.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "93dc7dc9022ed861ddb2afda73143efbbaf6bf4a", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/visualization/brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 14 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10495.json b/mne-python/source/doc/sphinxext/prs/10495.json new file mode 100644 index 0000000000000000000000000000000000000000..6d80aaea2bc83aa7aab83262a78c5c4f869726b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10495.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7a8d41e7175db1b6744d20f5670f90190329a1c9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 97, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_scraper.py": { + "a": 4, + "d": 1 + }, + "requirements_testing.txt": { + "a": 0, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10497.json b/mne-python/source/doc/sphinxext/prs/10497.json new file mode 100644 index 0000000000000000000000000000000000000000..860c02e8d0aeb2d41fbda3db591503d9ebd61297 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10497.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "eea8ea65892163cfbbb10f51aa74d4dd09dfd222", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "tutorials/evoked/10_evoked_overview.py": { + "a": 64, + "d": 64 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10498.json b/mne-python/source/doc/sphinxext/prs/10498.json new file mode 100644 index 0000000000000000000000000000000000000000..306270740ab50ff42aa45972b86ba1716a8fec2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10498.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5a6b5fc08bfa95642fdeb22d6e2a477845528dfb", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "tutorials/evoked/20_visualize_evoked.py": { + "a": 62, + "d": 65 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10500.json b/mne-python/source/doc/sphinxext/prs/10500.json new file mode 100644 index 0000000000000000000000000000000000000000..66c439827551720344952e3f0d758bf41231726d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10500.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "c276f61c8ed23473834eea88af6e13966e0b834e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/icons/toolbar_move_horizontal@2x.png": { + "a": 0, + "d": 0 + }, + "mne/icons/toolbar_move_vertical@2x.png": { + "a": 0, + "d": 0 + }, + "mne/icons/toolbar_separator_horizontal.png": { + "a": 0, + "d": 0 + }, + "mne/icons/toolbar_separator_horizontal@2x.png": { + "a": 0, + "d": 0 + }, + "mne/icons/toolbar_separator_vertical@2x.png": { + "a": 0, + "d": 0 + }, + "mne/viz/_scraper.py": { + "a": 2, + "d": 9 + }, + "mne/viz/backends/_utils.py": { + "a": 67, + "d": 6 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 40, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10501.json b/mne-python/source/doc/sphinxext/prs/10501.json new file mode 100644 index 0000000000000000000000000000000000000000..129965429f38694b9b617c421ce6bb93ac1c781c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10501.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "d0fc8a2acca1ee7c601e9c040185eddabe6f231c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 2 + }, + "mne/io/base.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 3, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 7, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 11, + "d": 4 + }, + "mne/viz/raw.py": { + "a": 8, + "d": 2 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10502.json b/mne-python/source/doc/sphinxext/prs/10502.json new file mode 100644 index 0000000000000000000000000000000000000000..387e62b65cf554b9dffeda2845be29ea6751e437 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10502.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "321cafcb8bfae073c66cbe4dfb29a1002f0e0f53", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 3, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 8, + "d": 9 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 4, + "d": 4 + }, + "mne/commands/tests/test_commands.py": { + "a": 6, + "d": 6 + }, + "mne/conftest.py": { + "a": 12, + "d": 3 + }, + "mne/datasets/misc/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/misc/_misc.py": { + "a": 7, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 4, + "d": 2 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 3, + "d": 3 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 7, + "d": 7 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 4, + "d": 2 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 5, + "d": 8 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 4, + "d": 7 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 9, + "d": 8 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 5, + "d": 4 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 0, + "d": 3 + }, + "mne/tests/test_coreg.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 4, + "d": 2 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 0, + "d": 2 + }, + "mne/viz/conftest.py": { + "a": 5, + "d": 3 + }, + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 4 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 20, + "d": 2 + }, + "tools/github_actions_download.sh": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10503.json b/mne-python/source/doc/sphinxext/prs/10503.json new file mode 100644 index 0000000000000000000000000000000000000000..98c28bd1290aa4b3c270acc4d70ecfdd7bdb6738 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10503.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0252176cb87d1163f8b19e808ccc6d2c299aea66", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_utils.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10504.json b/mne-python/source/doc/sphinxext/prs/10504.json new file mode 100644 index 0000000000000000000000000000000000000000..1cb8e5d87589ff714f1fe636772a55430eb01d6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10504.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "493418e6e30c9ef85c57aabc6702c1724dd8d82b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 18, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10506.json b/mne-python/source/doc/sphinxext/prs/10506.json new file mode 100644 index 0000000000000000000000000000000000000000..5415ee354a6e14f165ff76354b369b77dd13dda7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10506.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "41d38b7a55afeb2a6a840d07a155dae837326ef0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/utils/misc.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10509.json b/mne-python/source/doc/sphinxext/prs/10509.json new file mode 100644 index 0000000000000000000000000000000000000000..0067bf4b6ea7ee45bc467159d717bc4cb97c6daa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10509.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "e63da5125bc789c79ef9c05dc6e54592821b710d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 18, + "d": 12 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 15, + "d": 3 + }, + "mne/utils/check.py": { + "a": 12, + "d": 11 + }, + "mne/utils/config.py": { + "a": 7, + "d": 12 + }, + "mne/viz/backends/_utils.py": { + "a": 32, + "d": 21 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 0, + "d": 11 + }, + "mne/viz/tests/test_ica.py": { + "a": 10, + "d": 1 + }, + "requirements.txt": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10511.json b/mne-python/source/doc/sphinxext/prs/10511.json new file mode 100644 index 0000000000000000000000000000000000000000..88b78f5fa57d748bf2e3a63022093c31160ce838 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10511.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9b25b5d8b6d4c6753ff226443f44b381c8c98d4a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/installers_platform_selector.html": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10513.json b/mne-python/source/doc/sphinxext/prs/10513.json new file mode 100644 index 0000000000000000000000000000000000000000..a887449c47fda46eabeae43c7e4fe3b02440d8ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10513.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "25e9451ccacd0523343807a54255f8d06d202755", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 7, + "d": 21 + }, + "azure-pipelines.yml": { + "a": 19, + "d": 19 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 11, + "d": 7 + }, + "doc/install/advanced.rst": { + "a": 6, + "d": 0 + }, + "doc/install/check_installation.rst": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 2 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/utils/misc.py": { + "a": 6, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 24, + "d": 11 + }, + "mne/viz/_brain/_brain.py": { + "a": 31, + "d": 14 + }, + "mne/viz/_brain/callback.py": { + "a": 11, + "d": 5 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 29, + "d": 0 + }, + "mne/viz/_scraper.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 20, + "d": 11 + }, + "mne/viz/backends/_qt.py": { + "a": 8, + "d": 2 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 15, + "d": 1 + }, + "mne/viz/tests/test_scraper.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_utils.py": { + "a": 18, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 4 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 13 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tools/setup_xvfb.sh": { + "a": 2, + "d": 1 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10515.json b/mne-python/source/doc/sphinxext/prs/10515.json new file mode 100644 index 0000000000000000000000000000000000000000..a7cc57bb114edfa7df9ba82e68a7fb99b769bad8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10515.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "c4c100cdd030d5de41b5b558e50f497a3f6900e4", + "authors": [ + { + "n": "Alessandro Tonin", + "e": null + }, + { + "n": "Alessandro Tonin", + "e": "alessandro.tonin@wysscenter.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 11, + "d": 10 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/_read_raw.py": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 74, + "d": 47 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10517.json b/mne-python/source/doc/sphinxext/prs/10517.json new file mode 100644 index 0000000000000000000000000000000000000000..f5cf705dee97096958213c0e61be55f3cdc1098c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10517.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "394ee2c810ea06ee472e65005893ce939d879fa2", + "authors": [ + { + "n": "Alessandro Tonin", + "e": null + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Alessandro Tonin", + "e": "alessandro.tonin@wysscenter.ch" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1052.json b/mne-python/source/doc/sphinxext/prs/1052.json new file mode 100644 index 0000000000000000000000000000000000000000..827f92fe2b585b27fadb10be9e72f38864b9313d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1052.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "758a48b467391d114397dc9c616c0627da2222f0", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/fiff/evoked.py": { + "a": 16, + "d": 12 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz.py": { + "a": 42, + "d": 35 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10521.json b/mne-python/source/doc/sphinxext/prs/10521.json new file mode 100644 index 0000000000000000000000000000000000000000..45cb4a95ebbaf2f585ec1b8de37fdb3a5bc211e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10521.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5e60e475ef8019af73cc81e184a10bde524c681f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 16, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10523.json b/mne-python/source/doc/sphinxext/prs/10523.json new file mode 100644 index 0000000000000000000000000000000000000000..7dbda44ce17d50dd1df9f435ea4e720399ab1e2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10523.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "f222ef5b8caa622e56279f5e33cefbe3771fe186", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/mne_logo.svg": { + "a": 864, + "d": 174 + }, + "doc/_static/mne_logo_dark.svg": { + "a": 866, + "d": 0 + }, + "doc/_static/mne_logo_small.svg": { + "a": 82, + "d": 80 + }, + "doc/_static/style.css": { + "a": 26, + "d": 2 + }, + "doc/_templates/homepage.html": { + "a": 3, + "d": 3 + }, + "doc/conf.py": { + "a": 4, + "d": 1 + }, + "doc/index.rst": { + "a": 12, + "d": 2 + }, + "doc/install/install_type_selector.html": { + "a": 2, + "d": 2 + }, + "logo/generate_mne_logos.py": { + "a": 26, + "d": 15 + }, + "mne/icons/mne_bigsur_icon.png": { + "a": 0, + "d": 0 + }, + "mne/icons/mne_default_icon.png": { + "a": 0, + "d": 0 + }, + "mne/icons/mne_icon.png": { + "a": 0, + "d": 0 + }, + "mne/icons/mne_splash.png": { + "a": 0, + "d": 0 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "tools/circleci_download.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10525.json b/mne-python/source/doc/sphinxext/prs/10525.json new file mode 100644 index 0000000000000000000000000000000000000000..46ea82d2b81220ef1d50407996f6ff235e8df8ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10525.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "706dd3a36096e88a12b3bfb207e348c26fe8625c", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "examples/preprocessing/muscle_detection.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10527.json b/mne-python/source/doc/sphinxext/prs/10527.json new file mode 100644 index 0000000000000000000000000000000000000000..689a5451b0aeef341bba7e18940ae8dcfccce278 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10527.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "30ca67b25c7e558affd3fe17db18bab035b1add4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 0 + }, + "mne/io/_digitization.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10528.json b/mne-python/source/doc/sphinxext/prs/10528.json new file mode 100644 index 0000000000000000000000000000000000000000..88be22ae0c744265f498dd92e418bf49876b8468 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10528.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a264cdb6dfae0e86db93f8de1d43350deb5849f4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/installers_platform_selector.html": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10531.json b/mne-python/source/doc/sphinxext/prs/10531.json new file mode 100644 index 0000000000000000000000000000000000000000..cd6636f563b90c3ea1b283d0fe7ad76de2dfed86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10531.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "df2a581041949d8bd3a106f127101d7a034f6595", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 3 + }, + "mne/bem.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10534.json b/mne-python/source/doc/sphinxext/prs/10534.json new file mode 100644 index 0000000000000000000000000000000000000000..9ccc37b449e9f37e1062253b72f0b9628b424db7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10534.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5adb55223e564575ac384dbc853d0daaa4e75d8e", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 28, + "d": 0 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 0, + "d": 3 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 117, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 104, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 7, + "d": 1 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10535.json b/mne-python/source/doc/sphinxext/prs/10535.json new file mode 100644 index 0000000000000000000000000000000000000000..9b7b93e608b0ed8c74224a814617b18f27458497 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10535.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ab0888e8e092f4dec102aab0a377177a73387ca8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/installers_platform_selector.html": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10536.json b/mne-python/source/doc/sphinxext/prs/10536.json new file mode 100644 index 0000000000000000000000000000000000000000..29e7d5b39b79b1d0123b2952f829de0bd3cae8da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10536.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a0d1125166029844923d896a76519b6e13a5a8b9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/installers_platform_selector.html": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10537.json b/mne-python/source/doc/sphinxext/prs/10537.json new file mode 100644 index 0000000000000000000000000000000000000000..01513214ffd3e3090140db7fa15eada7add45241 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10537.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b6ce4f850d7c2dd562001fe2d76777276c6a9543", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 138, + "d": 0 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 112, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1054.json b/mne-python/source/doc/sphinxext/prs/1054.json new file mode 100644 index 0000000000000000000000000000000000000000..24420bbdd7215d8edbebb4ee700cc2440c42eb56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1054.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "080b67ae223704841b618cdd1451080fb5660268", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainak@neuro.hut.fi" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/realtime/ftclient_rt_average.py": { + "a": 78, + "d": 0 + }, + "mne/externals/FieldTrip.py": { + "a": 508, + "d": 0 + }, + "mne/realtime/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 257, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10540.json b/mne-python/source/doc/sphinxext/prs/10540.json new file mode 100644 index 0000000000000000000000000000000000000000..894598047cb237ced51a67b304a10a1a0a8d82e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10540.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dc88b7a18297818e7ab796d8e43755e499f324cc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "logo/generate_mne_logos.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10541.json b/mne-python/source/doc/sphinxext/prs/10541.json new file mode 100644 index 0000000000000000000000000000000000000000..ed248cfe98cd3beb7cacd4883fc928f562add5a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10541.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "47d7a8eb302ca59de109972b0c87b32b70b52713", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10543.json b/mne-python/source/doc/sphinxext/prs/10543.json new file mode 100644 index 0000000000000000000000000000000000000000..1b93102f7c564f8c49db653ede33407dc55a10c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10543.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c6bfb20172f4c37bbcb2960efa01c40c17aa4101", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 19, + "d": 0 + }, + "mne/coreg.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 30, + "d": 7 + }, + "mne/tests/test_coreg.py": { + "a": 4, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10544.json b/mne-python/source/doc/sphinxext/prs/10544.json new file mode 100644 index 0000000000000000000000000000000000000000..b3bfcacea1414ac52412dc7eb37c40f4e37e16ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10544.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "419ecdbf4ee0ac7cdfd2d71d3d001f77ec5d9840", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10545.json b/mne-python/source/doc/sphinxext/prs/10545.json new file mode 100644 index 0000000000000000000000000000000000000000..92e58b0892c1e28e8f7164c440fa188577aefc4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10545.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4216e50db1af4f8c78c9b90cbd4de865808cb464", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10546.json b/mne-python/source/doc/sphinxext/prs/10546.json new file mode 100644 index 0000000000000000000000000000000000000000..42c19a80de0e0dee87609ea7462878c952a41c0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10546.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a48c9b99ff2af47dcc86a8d76427457f0a74626a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 6, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 8, + "d": 7 + }, + "mne/viz/backends/_qt.py": { + "a": 13, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10547.json b/mne-python/source/doc/sphinxext/prs/10547.json new file mode 100644 index 0000000000000000000000000000000000000000..06782486929001cb584907a3efc1484de52eafbf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10547.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4e601bcab824e49d9f96eba9c402b75868fe4604", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 9, + "d": 0 + }, + "mne/io/_digitization.py": { + "a": 15, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10548.json b/mne-python/source/doc/sphinxext/prs/10548.json new file mode 100644 index 0000000000000000000000000000000000000000..aa0fbeb08fab00cd3ea670ba8b392f0fda4f9429 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10548.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2424a49b8af33b557367cf63b584155bd6000394", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10549.json b/mne-python/source/doc/sphinxext/prs/10549.json new file mode 100644 index 0000000000000000000000000000000000000000..7488578f6d225534ffccad604e2a45bb7428957d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10549.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ac45cbe05687c9b7a09151b73a577c3f51b37f08", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_coreg.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10552.json b/mne-python/source/doc/sphinxext/prs/10552.json new file mode 100644 index 0000000000000000000000000000000000000000..db50639a288d784db82b2e7ea56dd791377b57aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10552.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0908c79aca54211d4bef084cd54d772e7bf0ff20", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 4, + "d": 1 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 5, + "d": 3 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 17, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10554.json b/mne-python/source/doc/sphinxext/prs/10554.json new file mode 100644 index 0000000000000000000000000000000000000000..7a4f828e305d562a6ad55d8f3427b9997c7469de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10554.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fc981bd93b7a485480d0d074fe29fbfb23443609", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 8, + "d": 3 + }, + "mne/io/base.py": { + "a": 15, + "d": 22 + }, + "mne/preprocessing/maxwell.py": { + "a": 38, + "d": 13 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 35, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10555.json b/mne-python/source/doc/sphinxext/prs/10555.json new file mode 100644 index 0000000000000000000000000000000000000000..8f0a15bd4c54d1d8155aba4ccf1963cdb7fca2fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10555.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "7fcace5d8ebe6f56a05fcaf269e26512d034de1f", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 3, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 68, + "d": 62 + }, + "mne/io/snirf/_snirf.py": { + "a": 73, + "d": 33 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 41, + "d": 24 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 13, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10556.json b/mne-python/source/doc/sphinxext/prs/10556.json new file mode 100644 index 0000000000000000000000000000000000000000..7ce8fe3367842d004a2dec270578ccc897dceaee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10556.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f523f24af64921cf3e49fee01f665ef36867e05a", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "examples/inverse/multi_dipole_model.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10557.json b/mne-python/source/doc/sphinxext/prs/10557.json new file mode 100644 index 0000000000000000000000000000000000000000..07155bf9295f3d7ef9d011f9892d5d8fac6bf753 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10557.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "419b9e2d0825d4660b39200391ed1ad9b8e1b892", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 58, + "d": 16 + }, + "mne/viz/tests/test_ica.py": { + "a": 26, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10558.json b/mne-python/source/doc/sphinxext/prs/10558.json new file mode 100644 index 0000000000000000000000000000000000000000..8d06fab96c59e44939e1523d707ace7a9860d2fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10558.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aa4118655e70b57d99262aad70d4fe38ea6ecd63", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 6, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10559.json b/mne-python/source/doc/sphinxext/prs/10559.json new file mode 100644 index 0000000000000000000000000000000000000000..84a4d09a55ab8b50a4cfb2ffa4700128e6580470 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10559.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "04e5f687c3241503b63010ca3943bb5e173efb4d", + "authors": [ + { + "n": "Simeon Wong", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10560.json b/mne-python/source/doc/sphinxext/prs/10560.json new file mode 100644 index 0000000000000000000000000000000000000000..17f1d2320149f5bf69968a9ddd8fc6952bc6f753 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10560.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "9bd26a39996ddafe31830ce31add97a8fd84a970", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 6, + "d": 4 + }, + "mne/viz/backends/_abstract.py": { + "a": 8, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 14, + "d": 5 + }, + "mne/viz/backends/_qt.py": { + "a": 11, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10563.json b/mne-python/source/doc/sphinxext/prs/10563.json new file mode 100644 index 0000000000000000000000000000000000000000..5119208468c8a21130f686dbe1c69eeb46c36e36 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10563.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bd210961c5d899af2ecd7d7e2bb53b80ec4807e3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10567.json b/mne-python/source/doc/sphinxext/prs/10567.json new file mode 100644 index 0000000000000000000000000000000000000000..87406800e8d84e8c034e7565c886003d3847eb4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10567.json @@ -0,0 +1,371 @@ +{ + "merge_commit_sha": "62143cbeb12a822e08833941c4e0f1d450d35240", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/datasets/opm_data.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 6, + "d": 8 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "examples/stats/cluster_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/source_space_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/evoked_whitening.py": { + "a": 3, + "d": 3 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 7, + "d": 6 + }, + "mne/cuda.py": { + "a": 9, + "d": 7 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ems.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 11, + "d": 17 + }, + "mne/decoding/tests/test_base.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 5, + "d": 6 + }, + "mne/decoding/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 5, + "d": 5 + }, + "mne/dipole.py": { + "a": 4, + "d": 4 + }, + "mne/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/evoked.py": { + "a": 4, + "d": 3 + }, + "mne/filter.py": { + "a": 22, + "d": 26 + }, + "mne/forward/_compute_forward.py": { + "a": 7, + "d": 5 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 5 + }, + "mne/forward/_lead_dots.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 4 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 11, + "d": 9 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 5, + "d": 6 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 8, + "d": 9 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/parallel.py": { + "a": 55, + "d": 76 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 4, + "d": 4 + }, + "mne/report/report.py": { + "a": 20, + "d": 25 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 8, + "d": 8 + }, + "mne/stats/cluster_level.py": { + "a": 6, + "d": 7 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 6, + "d": 6 + }, + "mne/surface.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 11, + "d": 8 + }, + "mne/tests/test_parallel.py": { + "a": 40, + "d": 0 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 5, + "d": 0 + }, + "mne/time_frequency/_stockwell.py": { + "a": 4, + "d": 5 + }, + "mne/time_frequency/csd.py": { + "a": 11, + "d": 9 + }, + "mne/time_frequency/multitaper.py": { + "a": 6, + "d": 7 + }, + "mne/time_frequency/psd.py": { + "a": 7, + "d": 8 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 5, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/30_forward.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 9, + "d": 7 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 4, + "d": 4 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/70_cluster_rmANOVA_time_freq.py": { + "a": 3, + "d": 2 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10568.json b/mne-python/source/doc/sphinxext/prs/10568.json new file mode 100644 index 0000000000000000000000000000000000000000..69f4e29ab7bdd7963e433e634998c924d69b9c3f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10568.json @@ -0,0 +1,151 @@ +{ + "merge_commit_sha": "858d1b25aafe98c54786e4344d2e5a11ac65da4b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/0.20.inc": { + "a": 1, + "d": 1 + }, + "mne/_ola.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 5, + "d": 18 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 0, + "d": 3 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/receptive_field.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/transformer.py": { + "a": 3, + "d": 4 + }, + "mne/dipole.py": { + "a": 3, + "d": 4 + }, + "mne/epochs.py": { + "a": 2, + "d": 3 + }, + "mne/event.py": { + "a": 1, + "d": 10 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 12 + }, + "mne/gui/_coreg.py": { + "a": 2, + "d": 28 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 0, + "d": 26 + }, + "mne/io/base.py": { + "a": 2, + "d": 3 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 29 + }, + "mne/io/tests/test_meas_info.py": { + "a": 0, + "d": 7 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/morph.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/flat.py": { + "a": 0, + "d": 108 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 0, + "d": 96 + }, + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 3 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 0, + "d": 17 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 6 + }, + "mne/utils/tests/test_logging.py": { + "a": 2, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10569.json b/mne-python/source/doc/sphinxext/prs/10569.json new file mode 100644 index 0000000000000000000000000000000000000000..d09c6cd0635f3b9bed1fd58a24466f669ed280aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10569.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fc1112d8708e7ca8a8f7af6062c2927e538b55b2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/forward/_field_interpolation.py": { + "a": 9, + "d": 2 + }, + "mne/io/open.py": { + "a": 5, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 3 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10571.json b/mne-python/source/doc/sphinxext/prs/10571.json new file mode 100644 index 0000000000000000000000000000000000000000..a958d57815849214d595569693ab630546cee2ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10571.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "a6a67de8ca8a57c5aefaa13fd233e0958c81c26f", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 49, + "d": 0 + }, + "doc/visualization.rst": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 262, + "d": 0 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 5, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/_csd.py": { + "a": 123, + "d": 2 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 29, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 26, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 115, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10572.json b/mne-python/source/doc/sphinxext/prs/10572.json new file mode 100644 index 0000000000000000000000000000000000000000..d441193e18b9c8312f017455551773bc51ee19dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10572.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "65a53882e7ba2d7909a9e14de48218dfeb00f664", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "doc/glossary.rst": { + "a": 6, + "d": 0 + }, + "examples/visualization/eeglab_head_sphere.py": { + "a": 0, + "d": 130 + }, + "mne/utils/check.py": { + "a": 79, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 36, + "d": 21 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 3 + }, + "mne/viz/tests/test_montage.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 33, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 14, + "d": 4 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 160, + "d": 132 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10573.json b/mne-python/source/doc/sphinxext/prs/10573.json new file mode 100644 index 0000000000000000000000000000000000000000..fddbc84c71208117dda091044b19a26689daa8de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10573.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "42102b58a24d1b864a4a668ba687fe8097e52a00", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 3, + "d": 3 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 3, + "d": 2 + }, + "mne/viz/backends/_abstract.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_qt.py": { + "a": 18, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10574.json b/mne-python/source/doc/sphinxext/prs/10574.json new file mode 100644 index 0000000000000000000000000000000000000000..2fa4d7fa0eb9d921d79b8248ce8feb05471caafb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10574.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d5544e700600cde978e8a5d6ea73aedad6843a28", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10575.json b/mne-python/source/doc/sphinxext/prs/10575.json new file mode 100644 index 0000000000000000000000000000000000000000..f144182f82799bc389843f7dd4743ec16d3dbab5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10575.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4cab7a555b2430e1de11799a22b949607987603e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10578.json b/mne-python/source/doc/sphinxext/prs/10578.json new file mode 100644 index 0000000000000000000000000000000000000000..333b4e3c63fc87fa2cba7c3211bcbae88da06bc9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10578.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f059f8f1edaee3f9b6954e7987dd1e6d482bba27", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1058.json b/mne-python/source/doc/sphinxext/prs/1058.json new file mode 100644 index 0000000000000000000000000000000000000000..f5102cb6d54d7c36547cd2dc516af91cb21c86ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1058.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "856353d24e852bbb078245b60a40f9e72d72a964", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 28, + "d": 8 + }, + "mne/fiff/pick.py": { + "a": 9, + "d": 7 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10580.json b/mne-python/source/doc/sphinxext/prs/10580.json new file mode 100644 index 0000000000000000000000000000000000000000..442ce4eb278623666054f738a8889ad93d91cf78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10580.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "820e3ccc63a13fbe0142f3333c7739ecaa42612d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/install/advanced.rst": { + "a": 15, + "d": 13 + }, + "doc/install/manual_install.rst": { + "a": 69, + "d": 43 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10581.json b/mne-python/source/doc/sphinxext/prs/10581.json new file mode 100644 index 0000000000000000000000000000000000000000..d236da5f825b417e23292da228ffe81cd3c42541 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10581.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "770aa7c8e3183f54140632f86796c808641ecd26", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/install/advanced.rst": { + "a": 14, + "d": 12 + }, + "doc/install/manual_install.rst": { + "a": 69, + "d": 43 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10582.json b/mne-python/source/doc/sphinxext/prs/10582.json new file mode 100644 index 0000000000000000000000000000000000000000..ae1e619e08bb59c4d3c03eb7aa7b430243620d54 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10582.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "00e96d940ac666f66c5a268f17564c470e141236", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/decoding/search_light.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10583.json b/mne-python/source/doc/sphinxext/prs/10583.json new file mode 100644 index 0000000000000000000000000000000000000000..bbba6ca600603d7e03d7b046352bf9dc2ece7bf1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10583.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "cf820dfe28bfa2a01f4b431de33ff571287d1320", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 6, + "d": 6 + }, + "doc/_static/style.css": { + "a": 8, + "d": 0 + }, + "doc/install/advanced.rst": { + "a": 34, + "d": 34 + }, + "doc/install/installers_platform_selector.html": { + "a": 1, + "d": 1 + }, + "doc/install/manual_install.rst": { + "a": 17, + "d": 19 + }, + "doc/install/manual_install_platform_selector.html": { + "a": 56, + "d": 0 + }, + "doc/install/manual_install_python.rst": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10586.json b/mne-python/source/doc/sphinxext/prs/10586.json new file mode 100644 index 0000000000000000000000000000000000000000..cf075fa0eed20dd8209081d67ec9c41921d0c2f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10586.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a5d91041d787fcd2ba58330a4ccde360cf543b7f", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "examples/preprocessing/eeg_bridging.py": { + "a": 16, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10587.json b/mne-python/source/doc/sphinxext/prs/10587.json new file mode 100644 index 0000000000000000000000000000000000000000..cd9df77c7750638d7bdcbb5476a275cbc03e57bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10587.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4349f6d9805c43e1034b09742668a952fdff40ec", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 92, + "d": 7 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/interpolate.py": { + "a": 85, + "d": 1 + }, + "mne/preprocessing/tests/test_interpolate.py": { + "a": 23, + "d": 1 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10588.json b/mne-python/source/doc/sphinxext/prs/10588.json new file mode 100644 index 0000000000000000000000000000000000000000..c253085cecaa3b0b51c2749ba43c4e6cc5faeed3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10588.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cc44af23232542e5a14d86922e10f6d0ea22bc1e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/preprocessing/eeg_bridging.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10589.json b/mne-python/source/doc/sphinxext/prs/10589.json new file mode 100644 index 0000000000000000000000000000000000000000..c8358ae09ff5992e079e3dc342b36f83e3b680e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10589.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "438eefc036405cae3b25a4a3d91bedb690a2d36d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 6, + "d": 6 + }, + "doc/_static/style.css": { + "a": 6, + "d": 0 + }, + "doc/install/advanced.rst": { + "a": 32, + "d": 32 + }, + "doc/install/installers_platform_selector.html": { + "a": 1, + "d": 1 + }, + "doc/install/manual_install.rst": { + "a": 17, + "d": 19 + }, + "doc/install/manual_install_platform_selector.html": { + "a": 56, + "d": 0 + }, + "doc/install/manual_install_python.rst": { + "a": 1, + "d": 1 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10592.json b/mne-python/source/doc/sphinxext/prs/10592.json new file mode 100644 index 0000000000000000000000000000000000000000..6dac477267a7612134ccda9a8c1f631117fceefa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10592.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "754ea8e1d4f4204b172653eda34d30a74438b9fe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 4, + "d": 2 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 6, + "d": 3 + }, + "mne/bem.py": { + "a": 54, + "d": 23 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 6, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 7, + "d": 4 + }, + "mne/coreg.py": { + "a": 2, + "d": 0 + }, + "mne/surface.py": { + "a": 73, + "d": 50 + }, + "mne/tests/test_bem.py": { + "a": 53, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 3, + "d": 3 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 2 + }, + "mne/utils/misc.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 69, + "d": 48 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 129, + "d": 75 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10593.json b/mne-python/source/doc/sphinxext/prs/10593.json new file mode 100644 index 0000000000000000000000000000000000000000..bc7310209f760edd1c789a57d1eb988ad3336214 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10593.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "50c1adf5d7b4cbf000010a6a9aedbc90f495c921", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/colormap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10597.json b/mne-python/source/doc/sphinxext/prs/10597.json new file mode 100644 index 0000000000000000000000000000000000000000..204b600f44889b42dbb3d9a99e4dcd4e6dfee3c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10597.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fae9ada64b49afd9f6bb8161111a2aee9070c38c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/install/manual_install.rst": { + "a": 2, + "d": 3 + }, + "doc/install/manual_install_platform_selector.html": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10599.json b/mne-python/source/doc/sphinxext/prs/10599.json new file mode 100644 index 0000000000000000000000000000000000000000..64a660ee53ae08541ac13d142f4f0daf8e674589 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10599.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cc86f163126ad1aa950f1909062abe5e9b1888c5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 0, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10600.json b/mne-python/source/doc/sphinxext/prs/10600.json new file mode 100644 index 0000000000000000000000000000000000000000..77d06387ac400a93da28d65a0942818ff84fd53f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10600.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8f37e20a3551ba36a10c6ea541b64dd87da53a21", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/install/manual_install.rst": { + "a": 2, + "d": 3 + }, + "doc/install/manual_install_platform_selector.html": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10603.json b/mne-python/source/doc/sphinxext/prs/10603.json new file mode 100644 index 0000000000000000000000000000000000000000..c0026d25c81dac1b75c4215599cf43ff0e8999a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10603.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "90172f41531b15f35b0cf2c87c6b39044f54469e", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "tutorials/intro/70_report.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10605.json b/mne-python/source/doc/sphinxext/prs/10605.json new file mode 100644 index 0000000000000000000000000000000000000000..001c5599fdbe4eaffbb7194dbbaaf310ac47d116 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10605.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b00dcb1cb0376f0965054145b4222c6a7bfaf7ee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/versions.json": { + "a": 32, + "d": 16 + }, + "doc/conf.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10606.json b/mne-python/source/doc/sphinxext/prs/10606.json new file mode 100644 index 0000000000000000000000000000000000000000..31c1c73b5330c4317a4a1b3ae8a0d1aad0e6a8d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10606.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "add9e1620958b61f5509bea172ce8343975aee10", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 14, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10607.json b/mne-python/source/doc/sphinxext/prs/10607.json new file mode 100644 index 0000000000000000000000000000000000000000..2212c242ba4b9fcb7aba439fd3da53d38577d60d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10607.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9b7fdd11f60debe810e7445c0699d9e6f487e0b1", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10610.json b/mne-python/source/doc/sphinxext/prs/10610.json new file mode 100644 index 0000000000000000000000000000000000000000..9c2d971eb021c7560098f90004d547e32060521c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10610.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "20a721328b430b850e5e4654e93a592cdab87271", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 9 + }, + "mne/viz/tests/test_topomap.py": { + "a": 23, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 66, + "d": 21 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10611.json b/mne-python/source/doc/sphinxext/prs/10611.json new file mode 100644 index 0000000000000000000000000000000000000000..f2659d606431a165d3ef551571955746a2da11a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10611.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "d24d0766c8c16733d1fdcf4e908c722505e9d507", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 30, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 27, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 37, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 30, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10613.json b/mne-python/source/doc/sphinxext/prs/10613.json new file mode 100644 index 0000000000000000000000000000000000000000..2249ff0e505eb060c53a6cb571114d4a60e5fa41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10613.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "343afe9d34d8cce35344819bdfa0e733aae1159f", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/snirf/_snirf.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10614.json b/mne-python/source/doc/sphinxext/prs/10614.json new file mode 100644 index 0000000000000000000000000000000000000000..151a6bc1db815340f4626ff39ecbc746375fb052 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10614.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9f833658527a2c06ba833bffee33c9ba3a4a528a", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 43, + "d": 6 + }, + "mne/viz/tests/test_evoked.py": { + "a": 14, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10615.json b/mne-python/source/doc/sphinxext/prs/10615.json new file mode 100644 index 0000000000000000000000000000000000000000..7988011e88851f3cd6c57064c6d3a7d8ac8d1f25 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10615.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "439e598ccb30019e81ebe8fc7885c8b5e57dff02", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10616.json b/mne-python/source/doc/sphinxext/prs/10616.json new file mode 100644 index 0000000000000000000000000000000000000000..b0fca5b257d6eab9169d32149c57b98bb38386ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10616.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "65547f9712f3cf029e9aa7eeb9372596edbf7fe9", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/references.bib": { + "a": 13, + "d": 0 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10617.json b/mne-python/source/doc/sphinxext/prs/10617.json new file mode 100644 index 0000000000000000000000000000000000000000..d61b0e1344c28969b8ca17e63b603a5fc91285c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10617.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "be56457160097ba8826e2a0c8e66c5b4073bea05", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/evoked_topomap.py": { + "a": 29, + "d": 0 + }, + "mne/cov.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/csp.py": { + "a": 5, + "d": 8 + }, + "mne/defaults.py": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 12, + "d": 8 + }, + "mne/io/proj.py": { + "a": 11, + "d": 7 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 5 + }, + "mne/viz/tests/test_ica.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 7, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 64, + "d": 41 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10618.json b/mne-python/source/doc/sphinxext/prs/10618.json new file mode 100644 index 0000000000000000000000000000000000000000..43ec1c1738322864c158006f09a0c13688f4c79c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10618.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "97bce190e1a9831395ed0c1ebf5365b248e023d3", + "authors": [ + { + "n": "Reza Shoorangiz", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10619.json b/mne-python/source/doc/sphinxext/prs/10619.json new file mode 100644 index 0000000000000000000000000000000000000000..54b36f28d55a50346a064423c9f3c17450adebde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10619.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "820bd7a90f7babe7104efdc722c840d0137919a7", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alex", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/_csd.py": { + "a": 8, + "d": 0 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1062.json b/mne-python/source/doc/sphinxext/prs/1062.json new file mode 100644 index 0000000000000000000000000000000000000000..f3e436b780b568fedd7a1284d004d15124f07c88 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1062.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "6f822578746945abd595a4772cfaa85ec6478d54", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 22 + }, + "mne/fiff/channels.py": { + "a": 76, + "d": 1 + }, + "mne/fiff/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 25, + "d": 1 + }, + "mne/fiff/tests/test_raw.py": { + "a": 27, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 29, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10620.json b/mne-python/source/doc/sphinxext/prs/10620.json new file mode 100644 index 0000000000000000000000000000000000000000..9e9cc35b3c82645a542ece2b13f44a0e77353fd8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10620.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7b34565088f0120e9795fba1acb16a74936105f2", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/_csd.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10621.json b/mne-python/source/doc/sphinxext/prs/10621.json new file mode 100644 index 0000000000000000000000000000000000000000..94b9974e0da7af6d46b0e09c6b6fa1f26639a4e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10621.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "e711615915c3c5c99b605d4b064f668684fec08b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alex", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Alex", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/1.0.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/_csd.py": { + "a": 8, + "d": 0 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 15, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 18 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10622.json b/mne-python/source/doc/sphinxext/prs/10622.json new file mode 100644 index 0000000000000000000000000000000000000000..6b5b879dfdba275800730a7608913aecad9e6d4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10622.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "04d799d3fae689db4f3af7317e8e93c1ba7b8328", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/installers_platform_selector.html": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10624.json b/mne-python/source/doc/sphinxext/prs/10624.json new file mode 100644 index 0000000000000000000000000000000000000000..bae6cabc83683736258a9d244fc40416e9f30f83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10624.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ae0b1bdda4567cc3ac30d1168270c396c8c93409", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10626.json b/mne-python/source/doc/sphinxext/prs/10626.json new file mode 100644 index 0000000000000000000000000000000000000000..2e69f6a92940499081580b351326af193c203526 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10626.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3f7388a888eb473d79b3729ae75b5d2e403c7778", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/gui/_ieeg_locate_gui.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10627.json b/mne-python/source/doc/sphinxext/prs/10627.json new file mode 100644 index 0000000000000000000000000000000000000000..3afb3db78b8f24ccaf269fc4db122ddc5b4a33df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10627.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "7655632d8e85164a36b8f322ed52e9262a7e2ebb", + "authors": [ + { + "n": "Evan Hathaway", + "e": null + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/data/layouts/GeodesicHeadWeb-130.lout": { + "a": 132, + "d": 0 + }, + "mne/channels/data/layouts/GeodesicHeadWeb-280.lout": { + "a": 282, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 54, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10628.json b/mne-python/source/doc/sphinxext/prs/10628.json new file mode 100644 index 0000000000000000000000000000000000000000..3467b1587e1e955c7994c7fa2fe13c5dd94d5cab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10628.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "549de120926465a514ac5d7b0b8950f49ec2ade5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/linux_conda.yml": { + "a": 7, + "d": 3 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "tools/setup_xvfb.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1063.json b/mne-python/source/doc/sphinxext/prs/1063.json new file mode 100644 index 0000000000000000000000000000000000000000..1a3efcdb3be81ce8e73809cf54798b3d857e3111 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1063.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f5fed2a8c88217c7154ce47df4b8eaf35ed9d1ee", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/edf/edf.py": { + "a": 10, + "d": 4 + }, + "mne/fiff/edf/tests/test_edf.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10630.json b/mne-python/source/doc/sphinxext/prs/10630.json new file mode 100644 index 0000000000000000000000000000000000000000..4dec95bd7d2b0a5824a4b436117eaadfa5279475 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10630.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "fd3112ef5b8bf4f23f4dda320ef91b1b22e7f7cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/overview/faq.rst": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 20, + "d": 3 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 64, + "d": 42 + }, + "mne/io/snirf/_snirf.py": { + "a": 2, + "d": 3 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 27, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 4, + "d": 13 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10632.json b/mne-python/source/doc/sphinxext/prs/10632.json new file mode 100644 index 0000000000000000000000000000000000000000..74a7ffeef17ca47e97de1b873907fc3fb1170307 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10632.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "18ccda607e9139563270011ecb3391c4c35011ce", + "authors": [ + { + "n": "Matt Courtemanche", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/forward.rst": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 62, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 47, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10633.json b/mne-python/source/doc/sphinxext/prs/10633.json new file mode 100644 index 0000000000000000000000000000000000000000..0c3103a6cf7f48e1afacce2bc9e7bb5213ef597b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10633.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "c3d67179a80b9d9e8c23684c8cad4c01e1c44093", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/visualization.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 9, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 97, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 210, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 38, + "d": 1 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10636.json b/mne-python/source/doc/sphinxext/prs/10636.json new file mode 100644 index 0000000000000000000000000000000000000000..5d6c992443c07add9142762a8c774a66c9884632 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10636.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7f5b0f1c0d06e8b06eb51363b876c497fab9934f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 3, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10637.json b/mne-python/source/doc/sphinxext/prs/10637.json new file mode 100644 index 0000000000000000000000000000000000000000..ea74d14fb691017f9b302a9bc9c52cc8f5639ea1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10637.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0d3232195d3d531b53c095eda7a9907cbfbc4c30", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10638.json b/mne-python/source/doc/sphinxext/prs/10638.json new file mode 100644 index 0000000000000000000000000000000000000000..a234b3ca1b0d2272926ebe3a894c7c7df4f99cf0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10638.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9d972e45a10c3cecace5eace7c5eac35d53db7e7", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10639.json b/mne-python/source/doc/sphinxext/prs/10639.json new file mode 100644 index 0000000000000000000000000000000000000000..054bce79e6910e3ac7036baa9530ab9a84438639 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10639.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "db2c8fd8671a20857c8c56b71b116a6560b6638f", + "authors": [ + { + "n": "Matti Toivonen", + "e": "matti.toivonen@megin.fi" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10642.json b/mne-python/source/doc/sphinxext/prs/10642.json new file mode 100644 index 0000000000000000000000000000000000000000..0648f7fb2b42eb1350316ee7dc824eb439315e0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10642.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "f43584635b386a845c13953cc113305cc4e70721", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larsoner@monolith.local" + } + ], + "changes": { + "mne/channels/interpolation.py": { + "a": 3, + "d": 3 + }, + "mne/conftest.py": { + "a": 24, + "d": 1 + }, + "mne/fixes.py": { + "a": 8, + "d": 5 + }, + "mne/io/nirx/nirx.py": { + "a": 0, + "d": 20 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 6, + "d": 21 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 5 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 22, + "d": 24 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 1 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 10, + "d": 10 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 5, + "d": 9 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 4, + "d": 8 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 141, + "d": 90 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 8, + "d": 7 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 91, + "d": 25 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 2, + "d": 0 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 0, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10643.json b/mne-python/source/doc/sphinxext/prs/10643.json new file mode 100644 index 0000000000000000000000000000000000000000..510fb890bfa5d44216eb80f81a4569fdb4887ccc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10643.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6a8dd1434c6bbea527385838aa1fa0cc07c5201f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/1.0.inc": { + "a": 6, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10645.json b/mne-python/source/doc/sphinxext/prs/10645.json new file mode 100644 index 0000000000000000000000000000000000000000..60a3f579c27ae31372f5bfbe92b18e5d7ad426e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10645.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "965521831b5ca8675becc0cc9716db0cfc8ad946", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 9, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 14, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 15, + "d": 2 + }, + "mne/viz/backends/_qt.py": { + "a": 52, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10646.json b/mne-python/source/doc/sphinxext/prs/10646.json new file mode 100644 index 0000000000000000000000000000000000000000..f99302987b9726899e39391a8a286c5b6104f26f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10646.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1e806f358c7eee7e29192615a6394464d6c5abec", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_gui_api.py": { + "a": 11, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 11, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 18, + "d": 3 + }, + "mne/viz/backends/_qt.py": { + "a": 31, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10649.json b/mne-python/source/doc/sphinxext/prs/10649.json new file mode 100644 index 0000000000000000000000000000000000000000..cc3c710dc2fe0426f9a5331288af7efe00ef7d43 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10649.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1349ad88bdfe72d9214fe7496f74b1629985673d", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1065.json b/mne-python/source/doc/sphinxext/prs/1065.json new file mode 100644 index 0000000000000000000000000000000000000000..796ec1477e5abae69d1c8b058f56022809e24089 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1065.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "7795da0e6678797db127ebef967a1ca8d785d5b3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 0 + }, + "mne/fiff/brainvision/brainvision.py": { + "a": 17, + "d": 7 + }, + "mne/fiff/tag.py": { + "a": 6, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_file_traits.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 9, + "d": 10 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 8, + "d": 8 + }, + "mne/utils.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10651.json b/mne-python/source/doc/sphinxext/prs/10651.json new file mode 100644 index 0000000000000000000000000000000000000000..48f2ff988ae56487b65de3cc22ad2921a641e766 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10651.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3a9867adc80459317504468ab7829ed7379169e7", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 18, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10654.json b/mne-python/source/doc/sphinxext/prs/10654.json new file mode 100644 index 0000000000000000000000000000000000000000..34d7bce1cc37d9f7bdcecfe5df4c1966bc05752b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10654.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4061f38ceec3727e08dccc5c9e8b2d8a408bf314", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 18, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10656.json b/mne-python/source/doc/sphinxext/prs/10656.json new file mode 100644 index 0000000000000000000000000000000000000000..83c3e59ff5614c4e369691466425874b2f9cf30c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10656.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "fefa7dba887089a46cf5e0f8836ff6fb07be2552", + "authors": [ + { + "n": "Moritz Gerster", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 2 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 3 + }, + "mne/io/proj.py": { + "a": 94, + "d": 34 + }, + "mne/io/reference.py": { + "a": 19, + "d": 6 + }, + "mne/io/tests/test_reference.py": { + "a": 40, + "d": 33 + }, + "mne/proj.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_proj.py": { + "a": 98, + "d": 11 + }, + "mne/tests/test_rank.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 14, + "d": 0 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10658.json b/mne-python/source/doc/sphinxext/prs/10658.json new file mode 100644 index 0000000000000000000000000000000000000000..82c0a8c1fd0d3dbe0c2bed08e406bb429eb41490 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10658.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "a2f6fe7cb6b1ef38fea697ee82cb97eb65c79217", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "Makefile": { + "a": 0, + "d": 2 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/install/contributing.rst": { + "a": 6, + "d": 8 + }, + "doc/references.bib": { + "a": 12, + "d": 0 + }, + "examples/decoding/ems_filtering.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 92, + "d": 18 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/stats/_adjacency.py": { + "a": 15, + "d": 4 + }, + "mne/stats/cluster_level.py": { + "a": 44, + "d": 31 + }, + "mne/stats/parametric.py": { + "a": 2, + "d": 10 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 56, + "d": 14 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 30, + "d": 13 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 103, + "d": 18 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 90, + "d": 43 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 74, + "d": 30 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-source-space/70_cluster_rmANOVA_time_freq.py": { + "a": 3, + "d": 3 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1066.json b/mne-python/source/doc/sphinxext/prs/1066.json new file mode 100644 index 0000000000000000000000000000000000000000..67b37827baaaf2743b74c64c44e0f1bee2c5a707 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1066.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "9ed41d984dc894baacfb49c6d92cdf3d90b1d318", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/brainvision/brainvision.py": { + "a": 20, + "d": 9 + }, + "mne/fiff/tag.py": { + "a": 6, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_file_traits.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 40, + "d": 41 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 8, + "d": 8 + }, + "mne/utils.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10661.json b/mne-python/source/doc/sphinxext/prs/10661.json new file mode 100644 index 0000000000000000000000000000000000000000..be7f8fd6ca9d65dc692fbb1935f629d7cc2bf390 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10661.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2dbebc005f7498a06d5b1d7b64de5b3cb07b1430", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 29, + "d": 6 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 14, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10662.json b/mne-python/source/doc/sphinxext/prs/10662.json new file mode 100644 index 0000000000000000000000000000000000000000..4fece100d2d77cbcee119bc8e41767ca26cf701b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10662.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f5df9272193a5e84c6bceddb5b9b6582578a155c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 21, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10664.json b/mne-python/source/doc/sphinxext/prs/10664.json new file mode 100644 index 0000000000000000000000000000000000000000..5de31ea0be4479afee290ed0e34990c16feff6ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10664.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5bddef897c97bdcfb8d879901137c599e776df56", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10666.json b/mne-python/source/doc/sphinxext/prs/10666.json new file mode 100644 index 0000000000000000000000000000000000000000..73c1c5f3ddea9c8a6db629a1856611a480a79882 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10666.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "cba0f9b9d40ee19345f576a72017316174121851", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "Makefile": { + "a": 0, + "d": 2 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/install/contributing.rst": { + "a": 6, + "d": 8 + }, + "doc/references.bib": { + "a": 12, + "d": 0 + }, + "examples/decoding/ems_filtering.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 90, + "d": 16 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/stats/_adjacency.py": { + "a": 15, + "d": 4 + }, + "mne/stats/cluster_level.py": { + "a": 44, + "d": 31 + }, + "mne/stats/parametric.py": { + "a": 2, + "d": 10 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 56, + "d": 14 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 30, + "d": 13 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 102, + "d": 17 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 90, + "d": 43 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 74, + "d": 30 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-source-space/70_cluster_rmANOVA_time_freq.py": { + "a": 3, + "d": 3 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10667.json b/mne-python/source/doc/sphinxext/prs/10667.json new file mode 100644 index 0000000000000000000000000000000000000000..2dc94b7d418a0937c0d5021cae20377c04c92908 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10667.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a62f9a4d6fffa7c7c84817d4fde988f7930eace1", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/gui/_ieeg_locate_gui.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10668.json b/mne-python/source/doc/sphinxext/prs/10668.json new file mode 100644 index 0000000000000000000000000000000000000000..b0aa8f36ff64f4ed90cfd5764c5816d33ffb350f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10668.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3e2b87fa02b00b3fc0cab4fd7483973ad53d0bbe", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 22, + "d": 3 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10669.json b/mne-python/source/doc/sphinxext/prs/10669.json new file mode 100644 index 0000000000000000000000000000000000000000..73c462a55f403d919d365553d94306cda063884f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10669.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6b2cc8554f1503831b8fb807de57d6c5b26ade37", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 25, + "d": 6 + }, + "mne/viz/_3d_overlay.py": { + "a": 191, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 180 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1067.json b/mne-python/source/doc/sphinxext/prs/1067.json new file mode 100644 index 0000000000000000000000000000000000000000..3a2809f43959a02d41f300738d490385135b0f16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1067.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4fa583a1796c8d4838d7e31b656e8d14068abfdd", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/brainvision/brainvision.py": { + "a": 41, + "d": 20 + }, + "mne/fiff/brainvision/tests/test_brainvision.py": { + "a": 17, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10671.json b/mne-python/source/doc/sphinxext/prs/10671.json new file mode 100644 index 0000000000000000000000000000000000000000..b64465ebbbc5609e35d43ad5160a1bce9a87403f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10671.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "fc53916dcc98184fde17d2d41973c156e24c02f9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 16, + "d": 1 + }, + "doc/conf.py": { + "a": 7, + "d": 3 + }, + "doc/index.rst": { + "a": 6, + "d": 12 + }, + "doc/install/check_installation.rst": { + "a": 2, + "d": 2 + }, + "doc/install/contributing.rst": { + "a": 7, + "d": 6 + }, + "doc/install/index.rst": { + "a": 63, + "d": 2 + }, + "doc/install/install_type_selector.html": { + "a": 0, + "d": 40 + }, + "doc/install/installers.rst": { + "a": 74, + "d": 3 + }, + "doc/install/installers_platform_selector.html": { + "a": 0, + "d": 79 + }, + "doc/install/manual_install.rst": { + "a": 2, + "d": 2 + }, + "doc/install/manual_install_python.rst": { + "a": 59, + "d": 44 + }, + "doc/overview/cite.rst": { + "a": 4, + "d": 4 + }, + "doc/sphinxext/sphinx_bootstrap_divs/__init__.py": { + "a": 0, + "d": 196 + }, + "doc/sphinxext/sphinx_bootstrap_divs/bootstrap_divs.css": { + "a": 0, + "d": 9 + }, + "doc/sphinxext/sphinx_bootstrap_divs/bootstrap_divs.js": { + "a": 0, + "d": 6 + }, + "requirements_doc.txt": { + "a": 2, + "d": 1 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10672.json b/mne-python/source/doc/sphinxext/prs/10672.json new file mode 100644 index 0000000000000000000000000000000000000000..3f805c8761bf68ac90c9acfb14596534e879417e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10672.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "56436a4f49239c96f74b0cbc6a8369195232cdb5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10674.json b/mne-python/source/doc/sphinxext/prs/10674.json new file mode 100644 index 0000000000000000000000000000000000000000..1e5b5d97c98d989628b4fcc5fab259a47a670b57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10674.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "85bca4ccc4b957b6597799a7eb92b972a78a7fe1", + "authors": [ + { + "n": "Simon Kern", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10676.json b/mne-python/source/doc/sphinxext/prs/10676.json new file mode 100644 index 0000000000000000000000000000000000000000..0872ae6739e92a45fc276750531635a4137f485c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10676.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "368c7fcee60a55d76d26c6d77bfec08b4cad658b", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "mne/utils/check.py": { + "a": 23, + "d": 2 + }, + "mne/viz/backends/renderer.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10677.json b/mne-python/source/doc/sphinxext/prs/10677.json new file mode 100644 index 0000000000000000000000000000000000000000..1888aa4dea85535e68ae9240d64e633320168377 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10677.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ee1f4ce8caccc2e8e77a7a520d34a216f2a8fccb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10681.json b/mne-python/source/doc/sphinxext/prs/10681.json new file mode 100644 index 0000000000000000000000000000000000000000..515e267294117faa7be283d34850db90da6c8dae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10681.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "aafad953b07b0891cf179a00608293171a3226e4", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 4, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 24, + "d": 0 + }, + "mne/export/_brainvision.py": { + "a": 19, + "d": 0 + }, + "mne/export/_export.py": { + "a": 10, + "d": 30 + }, + "mne/export/tests/test_export.py": { + "a": 59, + "d": 14 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 5, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 36, + "d": 7 + }, + "requirements_testing_extra.txt": { + "a": 1, + "d": 0 + }, + "tutorials/io/20_reading_eeg_data.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10683.json b/mne-python/source/doc/sphinxext/prs/10683.json new file mode 100644 index 0000000000000000000000000000000000000000..e57dc54c8328c7242d1bbe46afb72ec6861b6bf5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10683.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b74d00449e796f0af163c5cfb86386a7b8a98d6e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/install/manual_install.rst": { + "a": 5, + "d": 3 + }, + "doc/install/manual_install_platform_selector.html": { + "a": 0, + "d": 55 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10685.json b/mne-python/source/doc/sphinxext/prs/10685.json new file mode 100644 index 0000000000000000000000000000000000000000..b3e5b1ee1a326b84ebcdf9d44c09907796564ec4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10685.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bd452f34c2a25f2f65e66ec4ee1ee9f0b0a05062", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10686.json b/mne-python/source/doc/sphinxext/prs/10686.json new file mode 100644 index 0000000000000000000000000000000000000000..2248fbe4a3528da1e9556031f09f21c5ff372e51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10686.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1cd46a6b846541d9627ec2d9e55a07165fa5e228", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/evoked.py": { + "a": 27, + "d": 20 + }, + "mne/export/tests/test_export.py": { + "a": 3, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 56, + "d": 11 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10688.json b/mne-python/source/doc/sphinxext/prs/10688.json new file mode 100644 index 0000000000000000000000000000000000000000..acb4d5360e9270e5b70236987022fa1f8cd6d8b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10688.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a877fada44f4241e740dad3dee8ffeb1a50422e3", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 10, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10689.json b/mne-python/source/doc/sphinxext/prs/10689.json new file mode 100644 index 0000000000000000000000000000000000000000..022e55add211de1a16ddf7c6f9013e9c73d3cbd3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10689.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6df80b5f2e9823dd299f9887e6fbf5b6f8380bbc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 2, + "d": 2 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 2, + "d": 7 + }, + "doc/install/mne_tools_suite.rst": { + "a": 1, + "d": 1 + }, + "doc/links.inc": { + "a": 4, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10692.json b/mne-python/source/doc/sphinxext/prs/10692.json new file mode 100644 index 0000000000000000000000000000000000000000..ff50fcbd7aa194e73a6cbb5b01dfee6310d54da1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10692.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6c15f996b53996534ebbcc0ef8d5fc8ec27d825e", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 13, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 7, + "d": 44 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10694.json b/mne-python/source/doc/sphinxext/prs/10694.json new file mode 100644 index 0000000000000000000000000000000000000000..250c47cca34aa0b75d6abc018ce51ce6e4843588 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10694.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "a9b139d00d6ce966dfebc078597ad335ebb425f9", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/html_templates/report/bem.html.jinja": { + "a": 8, + "d": 0 + }, + "mne/html_templates/report/code.html.jinja": { + "a": 6, + "d": 24 + }, + "mne/html_templates/report/epochs.html.jinja": { + "a": 0, + "d": 27 + }, + "mne/html_templates/report/evoked.html.jinja": { + "a": 0, + "d": 26 + }, + "mne/html_templates/report/forward.html.jinja": { + "a": 5, + "d": 23 + }, + "mne/html_templates/report/ica.html.jinja": { + "a": 0, + "d": 29 + }, + "mne/html_templates/report/image.html.jinja": { + "a": 15, + "d": 34 + }, + "mne/html_templates/report/inverse.html.jinja": { + "a": 5, + "d": 23 + }, + "mne/html_templates/report/raw.html.jinja": { + "a": 0, + "d": 25 + }, + "mne/html_templates/report/section.html.jinja": { + "a": 9, + "d": 5 + }, + "mne/html_templates/report/toc.html.jinja": { + "a": 3, + "d": 3 + }, + "mne/report/report.py": { + "a": 793, + "d": 724 + }, + "mne/report/tests/test_report.py": { + "a": 18, + "d": 14 + }, + "mne/utils/docs.py": { + "a": 12, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 29, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10699.json b/mne-python/source/doc/sphinxext/prs/10699.json new file mode 100644 index 0000000000000000000000000000000000000000..430d2134eb42d348223c4022b8c344ac6a4a2b2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10699.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "6b905281bf86ff336f2208297dc0f6794d25c746", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/datasets/opm_data.py": { + "a": 0, + "d": 2 + }, + "mne/_freesurfer.py": { + "a": 14, + "d": 1 + }, + "mne/coreg.py": { + "a": 1, + "d": 15 + }, + "mne/dipole.py": { + "a": 10, + "d": 80 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_freesurfer.py": { + "a": 17, + "d": 2 + }, + "mne/transforms.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 13, + "d": 7 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 77, + "d": 48 + }, + "mne/viz/_brain/_brain.py": { + "a": 9, + "d": 14 + }, + "mne/viz/_dipole.py": { + "a": 166, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 25, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_utils.py": { + "a": 4, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 18, + "d": 21 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 10, + "d": 0 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10703.json b/mne-python/source/doc/sphinxext/prs/10703.json new file mode 100644 index 0000000000000000000000000000000000000000..bce15de9c84436f4fc05408604d9cf36dea29e52 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10703.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "618eb5480d648a9bd1f4741af4fd08856c1a69fa", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10705.json b/mne-python/source/doc/sphinxext/prs/10705.json new file mode 100644 index 0000000000000000000000000000000000000000..ce96e79bcfd9a1270a7af248a7364e4ffdf81613 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10705.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b2652a68fd503a087ecba38a208603567db214da", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 18, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10710.json b/mne-python/source/doc/sphinxext/prs/10710.json new file mode 100644 index 0000000000000000000000000000000000000000..0124ae15c3c95ddf2f120a8b4949f1eecfc78998 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10710.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ae52496f77ddee08dcaea8daaf4ccbfa11e791b1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/config.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10711.json b/mne-python/source/doc/sphinxext/prs/10711.json new file mode 100644 index 0000000000000000000000000000000000000000..452026c1da834142d349f9095e10d2119d74ed37 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10711.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "36ec7f4299f0085120c61bee628e747c83ada742", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".mailmap": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10714.json b/mne-python/source/doc/sphinxext/prs/10714.json new file mode 100644 index 0000000000000000000000000000000000000000..eaf70acc0416a7d702ef3278e47d16cf6f978b55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10714.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "83c716268344f79d2621f2fc7498b0c9e8975b2e", + "authors": [ + { + "n": "Dominique Makowski", + "e": "D.Makowski@sussex.ac.uk" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/_csd.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10715.json b/mne-python/source/doc/sphinxext/prs/10715.json new file mode 100644 index 0000000000000000000000000000000000000000..dc4a883b4601b776928e753389bffc075e5f093d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10715.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "24e5fe2ec67c5c23bce53a2158cc8cc78907eae6", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 184, + "d": 99 + }, + "mne/commands/mne_flash_bem.py": { + "a": 55, + "d": 35 + }, + "mne/commands/tests/test_commands.py": { + "a": 39, + "d": 12 + }, + "tools/get_minimal_commands.sh": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10716.json b/mne-python/source/doc/sphinxext/prs/10716.json new file mode 100644 index 0000000000000000000000000000000000000000..3db5aa41e34a1da61adfe1d73be2b8aff5f2ff22 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10716.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f176d91f0c2f6adeb7f7d6d196ff5271d636735d", + "authors": [ + { + "n": "Jon Houck", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "tutorials/forward/25_automated_coreg.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10718.json b/mne-python/source/doc/sphinxext/prs/10718.json new file mode 100644 index 0000000000000000000000000000000000000000..99ae74d917f56ce4b7ebe154507a2e601896ebd8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10718.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "eec5fe96ead56b5d162f667bdca1c1c3ea39832c", + "authors": [ + { + "n": "gemeinl", + "e": "lukas.gemein@gmx.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10719.json b/mne-python/source/doc/sphinxext/prs/10719.json new file mode 100644 index 0000000000000000000000000000000000000000..fb9b7a04e3580bbbe24c09494d60b1160abfabcf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10719.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f645075a801596753c1ae3625095ee93bc8af8d6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1072.json b/mne-python/source/doc/sphinxext/prs/1072.json new file mode 100644 index 0000000000000000000000000000000000000000..8956b2a569a8d4588e2713334954215cce570aa0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1072.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a1efe9cdbeba29f1a34ea96219e3fab14786f74f", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 6, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10720.json b/mne-python/source/doc/sphinxext/prs/10720.json new file mode 100644 index 0000000000000000000000000000000000000000..a90cc57952ca18febcd2b26cfa9de17ad7a3d6f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10720.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "237fdfeb5efe4632b4bfeff1adacf87757a6e2ba", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tools/generate_codemeta.py": { + "a": 108, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10722.json b/mne-python/source/doc/sphinxext/prs/10722.json new file mode 100644 index 0000000000000000000000000000000000000000..1a76d23804f0d0fa1b27e4cdf2facd995b68e936 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10722.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "948f0dc2745ba44d5add4faabc4090075bf1a770", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/visualization.rst": { + "a": 1, + "d": 0 + }, + "mne/io/pick.py": { + "a": 4, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 23, + "d": 12 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_proj.py": { + "a": 224, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 14, + "d": 9 + }, + "mne/viz/tests/test_proj.py": { + "a": 56, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 21, + "d": 11 + }, + "mne/viz/utils.py": { + "a": 11, + "d": 2 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 51, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10723.json b/mne-python/source/doc/sphinxext/prs/10723.json new file mode 100644 index 0000000000000000000000000000000000000000..2b2962442a48c4caeee392f1edb9b43f99e15067 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10723.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1df52a04d7d11ef9d64d6e8c78cf0b187d4378e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10727.json b/mne-python/source/doc/sphinxext/prs/10727.json new file mode 100644 index 0000000000000000000000000000000000000000..30bd1c890e41e6ab3cf9bf9f8798a7fae845bba1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10727.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "255cc03e4e0532cbc9bad12b1f65d2b201ca668f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10729.json b/mne-python/source/doc/sphinxext/prs/10729.json new file mode 100644 index 0000000000000000000000000000000000000000..72066807a1694c8de718f69cb1d706bbdda1c153 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10729.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4e329679a8d07e88ddcc231837ddc6d6785eca24", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 13, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10730.json b/mne-python/source/doc/sphinxext/prs/10730.json new file mode 100644 index 0000000000000000000000000000000000000000..f7d5b808e639a4229835d98dc4ddc0795820cbc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10730.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2ca8b24d7b54a018dc5942235e6bc02dfbbee597", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "tutorials/intro/70_report.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10733.json b/mne-python/source/doc/sphinxext/prs/10733.json new file mode 100644 index 0000000000000000000000000000000000000000..8a476db768c7c86f01c374c41563c36722db9268 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10733.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5387316b1e8fc0d31bc52993885f2ae77f774463", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 21, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10734.json b/mne-python/source/doc/sphinxext/prs/10734.json new file mode 100644 index 0000000000000000000000000000000000000000..588fbd650288032947239b15848aaacc0559dbb4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10734.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "152b5113d135ebbba196b878e4c6a08a1a937d8c", + "authors": [ + { + "n": "rcmdnk", + "e": "rcmdnk@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 82, + "d": 23 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 14, + "d": 0 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10735.json b/mne-python/source/doc/sphinxext/prs/10735.json new file mode 100644 index 0000000000000000000000000000000000000000..2f5a771fe38c74a72183735defcf5dac2259d672 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10735.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a9bdf81d21626c22dc879154367648515bcea3cd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10736.json b/mne-python/source/doc/sphinxext/prs/10736.json new file mode 100644 index 0000000000000000000000000000000000000000..54da38c3d0002291db13374237906ef11f1fde79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10736.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1310269f27bdf4347dfc465a834c1e04d25563d8", + "authors": [ + { + "n": "Drew, J.", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/viz/_mpl_figure.py": { + "a": 20, + "d": 8 + }, + "mne/viz/tests/test_epochs.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10737.json b/mne-python/source/doc/sphinxext/prs/10737.json new file mode 100644 index 0000000000000000000000000000000000000000..c5605451b0a6450611bd48c689960829bac0a272 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10737.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5ff33fa5ae8c1b0004ef894d5fe009140203ed48", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 163, + "d": 73 + }, + "mne/channels/tests/test_montage.py": { + "a": 21, + "d": 25 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 5 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 5, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10739.json b/mne-python/source/doc/sphinxext/prs/10739.json new file mode 100644 index 0000000000000000000000000000000000000000..6d7c26ab2d9572dfb496703600f408e2b97993fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10739.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5af527d399571e1ac0c84af29fdfd2b4fd676cbd", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/visualization/montage_sgskip.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1074.json b/mne-python/source/doc/sphinxext/prs/1074.json new file mode 100644 index 0000000000000000000000000000000000000000..f8286bb56b3a4d70a0d9b8f7a6bae0094ea09133 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1074.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e1f8f96c25b8dc2f278ce7a0d82ef9345ca6173c", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/source_space.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10740.json b/mne-python/source/doc/sphinxext/prs/10740.json new file mode 100644 index 0000000000000000000000000000000000000000..c700827f6ba1a2b0144d2443d00a3f3f8cd9a95c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10740.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0fefef9cfc063280b13a9d7bc00e8e489f9e3134", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10748.json b/mne-python/source/doc/sphinxext/prs/10748.json new file mode 100644 index 0000000000000000000000000000000000000000..c1af87c31938e57ced44025742ef02bfe6bd404b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10748.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5944b870f3d2d1803c0563e73792855f004d8932", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/utils/check.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10749.json b/mne-python/source/doc/sphinxext/prs/10749.json new file mode 100644 index 0000000000000000000000000000000000000000..abe31ddb0463a41c4d9f83a8d49aeca093aa3833 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10749.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "01dce0d268b3b3243d363b1d7f14ac2894030cbe", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 335, + "d": 86 + }, + "mne/channels/data/neighbors/easycapM1_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/ecog256_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/ecog256bipolar_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/eeg1010_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/elec1005_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/elec1010_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/elec1020_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/itab153_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/itab28_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/language29ch-avg_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/mpi_59_channels_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/neuromag122cmb_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/neuromag306cmb_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/yokogawa160_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/yokogawa440_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 88, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10753.json b/mne-python/source/doc/sphinxext/prs/10753.json new file mode 100644 index 0000000000000000000000000000000000000000..6aec3c31af9339086297170927f9b2716dbea636 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10753.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0d8f46934d524253b2bcb154460ac9ef17556ac5", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 9, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 17, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10754.json b/mne-python/source/doc/sphinxext/prs/10754.json new file mode 100644 index 0000000000000000000000000000000000000000..e46e208a468913bddcdb9842676cd3a72a600dbf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10754.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "aafa189db6096040088f4d2ffbdae0e4732aed10", + "authors": [ + { + "n": "Frederik-D-Weber", + "e": "Frederik-D-Weber@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10755.json b/mne-python/source/doc/sphinxext/prs/10755.json new file mode 100644 index 0000000000000000000000000000000000000000..e605d1f9fd882d5c564cb94f142cb1368d91d8c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10755.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "74edf166440b278fb16ffc9fe64cebd272e35ccb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1076.json b/mne-python/source/doc/sphinxext/prs/1076.json new file mode 100644 index 0000000000000000000000000000000000000000..ff687aa5bd91165ccb1268a38ae02e48363b6e3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1076.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5a3fa6dcddce37802c71be3477abcc8f975eed57", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/sphinxext/gen_rst.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10760.json b/mne-python/source/doc/sphinxext/prs/10760.json new file mode 100644 index 0000000000000000000000000000000000000000..560e670e9b682fb1624b7caae6c253402538bcc6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10760.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "04b5ed9afb7722e72e43dd2082bdfc5e4c1c9d52", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 8, + "d": 4 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10762.json b/mne-python/source/doc/sphinxext/prs/10762.json new file mode 100644 index 0000000000000000000000000000000000000000..12f797817839533a3fc9b8afaab38a8ae2a511a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10762.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "12dd9c950eeb59fb908afd0293a3a8fdc6e020a9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 26, + "d": 10 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10763.json b/mne-python/source/doc/sphinxext/prs/10763.json new file mode 100644 index 0000000000000000000000000000000000000000..21f49ad40deb1ff8025d0c5f810f66e4fa00429a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10763.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "dabcabf551b5de684fc77d387b865824860f670c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 9, + "d": 9 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 3, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 25, + "d": 26 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 9, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 4, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 4 + }, + "mne/viz/backends/_qt.py": { + "a": 13, + "d": 2 + }, + "mne/viz/backends/renderer.py": { + "a": 0, + "d": 6 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 10, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10764.json b/mne-python/source/doc/sphinxext/prs/10764.json new file mode 100644 index 0000000000000000000000000000000000000000..a56635e80c4aaf0826a7b060f7ad07c841164062 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10764.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ba2754fe3d9f49e486773403e673b04df8bb66e7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_includes/forward.rst": { + "a": 14, + "d": 12 + }, + "doc/_includes/morph.rst": { + "a": 5, + "d": 4 + }, + "doc/_static/style.css": { + "a": 25, + "d": 16 + }, + "doc/install/contributing.rst": { + "a": 10, + "d": 5 + }, + "doc/install/mne_tools_suite.rst": { + "a": 1, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10765.json b/mne-python/source/doc/sphinxext/prs/10765.json new file mode 100644 index 0000000000000000000000000000000000000000..11012529a8f49ae1e6cc3498f1fd7f400e377492 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10765.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5fb84d6b9ffd7d9d29714795da89cb8be23828b7", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10770.json b/mne-python/source/doc/sphinxext/prs/10770.json new file mode 100644 index 0000000000000000000000000000000000000000..5cba0db55747683d30db08bee4dcc6ccebf63c00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10770.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "faa543feffe057638a7c823479a5b5ad6ab3b3a2", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/preprocessing/interpolate.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10776.json b/mne-python/source/doc/sphinxext/prs/10776.json new file mode 100644 index 0000000000000000000000000000000000000000..6033cd88be4a2c39551bb0406a9a0f0ee33a21fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10776.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "37a9e5587443109515a85cdc4396af4e014ecf82", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/fixes.py": { + "a": 7, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 4, + "d": 2 + }, + "mne/viz/_mpl_figure.py": { + "a": 56, + "d": 47 + }, + "mne/viz/tests/test_raw.py": { + "a": 56, + "d": 35 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10777.json b/mne-python/source/doc/sphinxext/prs/10777.json new file mode 100644 index 0000000000000000000000000000000000000000..a15fd9d1f8acfe17276da78a04ce23ca71aed915 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10777.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "da02a256423404a81929d6de278bc63d3192a280", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/gui/_core.py": { + "a": 483, + "d": 0 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 79, + "d": 456 + }, + "mne/gui/tests/test_core_gui.py": { + "a": 82, + "d": 0 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 3, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10778.json b/mne-python/source/doc/sphinxext/prs/10778.json new file mode 100644 index 0000000000000000000000000000000000000000..c064b6c3378992a5fc631e40a5655e3fdcdff5b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10778.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "428fc90675442acee259a485d818d5b1d671359d", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10781.json b/mne-python/source/doc/sphinxext/prs/10781.json new file mode 100644 index 0000000000000000000000000000000000000000..f79c6842bc7e5d0a477c3a0d293f0590cefd7577 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10781.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9151f6f33e99f980812344e1f015c6007f837e42", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/ctf/ctf.py": { + "a": 12, + "d": 2 + }, + "mne/io/ctf/eeg.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/hc.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/res4.py": { + "a": 4, + "d": 4 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10787.json b/mne-python/source/doc/sphinxext/prs/10787.json new file mode 100644 index 0000000000000000000000000000000000000000..83f2c5bd45cd53a7bd596c01ab638e451ec31157 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10787.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "632e89a2eaafd742058a30a1494b8f06f6ab5f6c", + "authors": [ + { + "n": "Naveen", + "e": null + } + ], + "changes": { + ".github/workflows/linux_pip.yml": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10788.json b/mne-python/source/doc/sphinxext/prs/10788.json new file mode 100644 index 0000000000000000000000000000000000000000..703a7e4fe105086823b619764d52592b025d8f99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10788.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0dbdcb68aca0fc282b390f13fd464d3598dee5e2", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1079.json b/mne-python/source/doc/sphinxext/prs/1079.json new file mode 100644 index 0000000000000000000000000000000000000000..370934afb973d3068837e8595e8dd7288f42888f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1079.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "93afc83bd996b43b8ed3b4a02a6774b3fbab875b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 5, + "d": 5 + }, + "mne/utils.py": { + "a": 39, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10792.json b/mne-python/source/doc/sphinxext/prs/10792.json new file mode 100644 index 0000000000000000000000000000000000000000..83fc2ab28d45cd15fc01b50cdba7a7cdb73b1c9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10792.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6021d4a49dd5f6064b2af58e6309b08c72e02606", + "authors": [ + { + "n": "Naveen", + "e": null + } + ], + "changes": { + ".github/dependabot.yml": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10793.json b/mne-python/source/doc/sphinxext/prs/10793.json new file mode 100644 index 0000000000000000000000000000000000000000..ca42156877ddc2e91b679e4b335f96c8f11682c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10793.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9423ce676734d74e0551132ab4d6698d9bab3807", + "authors": [ + { + "n": "Alex Ciok", + "e": null + } + ], + "changes": { + "tutorials/README.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10794.json b/mne-python/source/doc/sphinxext/prs/10794.json new file mode 100644 index 0000000000000000000000000000000000000000..c63595897a39e01a6bba513b0478847f1271471d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10794.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "bd1b4cc7029a90e2124795596b7396f6f9026909", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/compat_minimal.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/linux_conda.yml": { + "a": 2, + "d": 2 + }, + ".github/workflows/linux_pip.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/macos_conda.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10795.json b/mne-python/source/doc/sphinxext/prs/10795.json new file mode 100644 index 0000000000000000000000000000000000000000..2dab2f0a0e15bbb76da37ce22a35931bdf931be6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10795.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7218ac1f609211875e1a02a25a0c8d112ab799c2", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/linux_pip.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10796.json b/mne-python/source/doc/sphinxext/prs/10796.json new file mode 100644 index 0000000000000000000000000000000000000000..412bcd50b0d413b8989fdfcd1dfa716a68b1701b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10796.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "562f4730dd3d462abb4ec134270c7cf0a9d53b0e", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/linux_conda.yml": { + "a": 2, + "d": 2 + }, + ".github/workflows/linux_pip.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/macos_conda.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10797.json b/mne-python/source/doc/sphinxext/prs/10797.json new file mode 100644 index 0000000000000000000000000000000000000000..643e019f9706aff88e994d739f461dc94ae36bc8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10797.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "af66aa0dc8a056797f591cf6fa7216d56e386bf9", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/linux_conda.yml": { + "a": 2, + "d": 2 + }, + ".github/workflows/linux_pip.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/macos_conda.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10800.json b/mne-python/source/doc/sphinxext/prs/10800.json new file mode 100644 index 0000000000000000000000000000000000000000..145d35dcd5c842219a8c516bf27af251c2009dbd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10800.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5e7e35ad0c50fb0de42872e2743c4fae2e511d90", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10802.json b/mne-python/source/doc/sphinxext/prs/10802.json new file mode 100644 index 0000000000000000000000000000000000000000..6a6e8dd198873da65b22ba5f56db364bb4800698 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10802.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "db6c8221efeb4d7de881c937012dca8ff9fcf2f8", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 53, + "d": 35 + }, + "mne/gui/_coreg.py": { + "a": 6, + "d": 1 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 4, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 20, + "d": 0 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 10, + "d": 9 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 18, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10804.json b/mne-python/source/doc/sphinxext/prs/10804.json new file mode 100644 index 0000000000000000000000000000000000000000..1e93688b2ea1869a3c20f49ac5a955cdf69fb200 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10804.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0dc113d4abda83aa3e3dcf865ce43bdad3a568b2", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 19, + "d": 38 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10820.json b/mne-python/source/doc/sphinxext/prs/10820.json new file mode 100644 index 0000000000000000000000000000000000000000..68396882723c268a7524af2d7c399f904b28839f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10820.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c75dfffcf03c2c061a37db6ba83171e68a91faba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/macos_conda.yml": { + "a": 9, + "d": 4 + }, + "tools/get_minimal_commands.sh": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10824.json b/mne-python/source/doc/sphinxext/prs/10824.json new file mode 100644 index 0000000000000000000000000000000000000000..4b409c05f4830958f8dc3d2ec79c81a63d44d63d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10824.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "89b6357edb0dfed9a56f83e43815a42700e6cd3c", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10825.json b/mne-python/source/doc/sphinxext/prs/10825.json new file mode 100644 index 0000000000000000000000000000000000000000..589e9edae1d513eb550fc57f233bd4dc672d475e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10825.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3ff8e9aced24d0e62e4a17348aa940b749500e9d", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10829.json b/mne-python/source/doc/sphinxext/prs/10829.json new file mode 100644 index 0000000000000000000000000000000000000000..f2e5b8b3c25cf41313cd0ec30b6f58b287ab9ba8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10829.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "23a8da684a4debe87b8de99dda6fba399ac22063", + "authors": [ + { + "n": "Carina", + "e": "carinaforster0611@gmail.com" + } + ], + "changes": { + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1083.json b/mne-python/source/doc/sphinxext/prs/1083.json new file mode 100644 index 0000000000000000000000000000000000000000..bff5ef0386df86ddf41414c2eabb7a510a076ea7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1083.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "99da520ca4eb85624d49e91e79c7a39a279bd27c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 7, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10830.json b/mne-python/source/doc/sphinxext/prs/10830.json new file mode 100644 index 0000000000000000000000000000000000000000..19ba7f6e2bdd29557cf1112fed7f8044889ac3d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10830.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c5e14281bfef445c245bd54633c48456427ef0b7", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + } + ], + "changes": { + "examples/forward/source_space_morphing.py": { + "a": 8, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10832.json b/mne-python/source/doc/sphinxext/prs/10832.json new file mode 100644 index 0000000000000000000000000000000000000000..d32b3a401e7f7bdec14ea6da75bf4eb6e506858e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10832.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ff40ce33418a786b23b534a6cfcb44cca5f6b105", + "authors": [ + { + "n": "kimcoco", + "e": "kimjico@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/inverse/evoked_ers_source_power.py": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10838.json b/mne-python/source/doc/sphinxext/prs/10838.json new file mode 100644 index 0000000000000000000000000000000000000000..52d3acabb78293d7e29c4298ab4331a37ac20b82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10838.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6eaca414e4b3dc89f64a2e5287ff9d6d8eb1ceb0", + "authors": [ + { + "n": "Carina", + "e": "carinaforster0611@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/io/read_noise_covariance_matrix.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10839.json b/mne-python/source/doc/sphinxext/prs/10839.json new file mode 100644 index 0000000000000000000000000000000000000000..0e638a183ec8edd07dd5bfe8a527129503e9b5d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10839.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "486519911d25ad2cc34c9bf6ad7c0a38e7f8aabd", + "authors": [ + { + "n": "Carina", + "e": "carinaforster0611@gmail.com" + } + ], + "changes": { + "mne/preprocessing/infomax_.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1084.json b/mne-python/source/doc/sphinxext/prs/1084.json new file mode 100644 index 0000000000000000000000000000000000000000..e35f5bbe04a4e52da746f81ae8af6556c13c3927 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1084.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6cca18958f4e297ed3ec239e1ecacf9a0deb1367", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 4, + "d": 0 + }, + "examples/plot_extract_events_from_raw.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_viz.py": { + "a": 7, + "d": 1 + }, + "mne/viz.py": { + "a": 36, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10841.json b/mne-python/source/doc/sphinxext/prs/10841.json new file mode 100644 index 0000000000000000000000000000000000000000..facf2c123a811d807978b80038db294e44954498 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10841.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "8f6305a0db273e91de8d965f1fe84a550febb876", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 0 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 3, + "d": 3 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 16, + "d": 63 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 3, + "d": 9 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 4 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10843.json b/mne-python/source/doc/sphinxext/prs/10843.json new file mode 100644 index 0000000000000000000000000000000000000000..9120292f5be51b5c7523feb656c36ff0dbc6853e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10843.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e8b76b94dee4176ceb48e72bd284b5fb3db5c837", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "examples/inverse/dics_source_power.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10844.json b/mne-python/source/doc/sphinxext/prs/10844.json new file mode 100644 index 0000000000000000000000000000000000000000..1e643f3263d5f068c2a316433cbb8045839a9f14 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10844.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c72cdaf002b5ecae75cc5f525e224bcac153acba", + "authors": [ + { + "n": "Adeline Fecker", + "e": null + } + ], + "changes": { + "examples/forward/left_cerebellum_volume_source.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10845.json b/mne-python/source/doc/sphinxext/prs/10845.json new file mode 100644 index 0000000000000000000000000000000000000000..7a23ab0beea6c0201a3ddc82fda1733d5aa3d6fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10845.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "380efbf63e5604c65c733567e744d36a224959cd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 14, + "d": 67 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10846.json b/mne-python/source/doc/sphinxext/prs/10846.json new file mode 100644 index 0000000000000000000000000000000000000000..6e8daf60241d2ad4c49c12fb6e5f58a829255b7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10846.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "6c43b2d398780e2e69ea2f5b2e3db6b59135825c", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "jadrew43", + "e": "39603454+jadrew43@users.noreply.github.com" + }, + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + } + ], + "changes": { + "examples/inverse/mixed_source_space_inverse.py": { + "a": 13, + "d": 14 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 6, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10849.json b/mne-python/source/doc/sphinxext/prs/10849.json new file mode 100644 index 0000000000000000000000000000000000000000..0d00d33bbef2daa7515859a35ed1c4e279e2a354 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10849.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5b582a19bf79164bd86f297e467e3b1117a2a4eb", + "authors": [ + { + "n": "Hamid", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/inverse/mne_cov_power.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1085.json b/mne-python/source/doc/sphinxext/prs/1085.json new file mode 100644 index 0000000000000000000000000000000000000000..38892a4043e4b4d912c4761605467547d4fd6d41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1085.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2d96346a43f37fe8fa1a9bccd348cfd618043c1c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 183, + "d": 5 + }, + "mne/tests/test_label.py": { + "a": 46, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10851.json b/mne-python/source/doc/sphinxext/prs/10851.json new file mode 100644 index 0000000000000000000000000000000000000000..42061e918896265a4bc4a9770c4be9d6c996472d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10851.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "7e71888056a2f922fdc4e9e42454294197b0cffc", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 4, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 3, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10856.json b/mne-python/source/doc/sphinxext/prs/10856.json new file mode 100644 index 0000000000000000000000000000000000000000..4e50615f5341d9dc0a515cc5433c39e6badd0f90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10856.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "82b65ab7451bbdd9ae49c363c7018bfde554be12", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 4, + "d": 1 + }, + "mne/source_space.py": { + "a": 13, + "d": 4 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10858.json b/mne-python/source/doc/sphinxext/prs/10858.json new file mode 100644 index 0000000000000000000000000000000000000000..b71d45c6e6c8b1ab53d29e4e1cf453771c574a79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10858.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7f11a236a54e2175c6e871a88d69803e3281b99a", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "examples/inverse/snr_estimate.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10859.json b/mne-python/source/doc/sphinxext/prs/10859.json new file mode 100644 index 0000000000000000000000000000000000000000..8afdac97c573120e9269242b37b43052cf18ea51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10859.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7cb4523eacd6bdc054721570de70ecfcfa38a42d", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/inverse/multidict_reweighted_tfmxne.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10861.json b/mne-python/source/doc/sphinxext/prs/10861.json new file mode 100644 index 0000000000000000000000000000000000000000..2781b876c293acdeeade3c2127e9a25f5f7aa417 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10861.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e49525c470b01b04c7270dc054bbfa7600021262", + "authors": [ + { + "n": "Drew, J.", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10862.json b/mne-python/source/doc/sphinxext/prs/10862.json new file mode 100644 index 0000000000000000000000000000000000000000..03eb940192abdeb8aa1f16d0a43f99fb353e8884 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10862.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2ac8b164dc5dd7ddfdd5b82a7c013eba4672cb61", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "examples/io/read_xdf.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10863.json b/mne-python/source/doc/sphinxext/prs/10863.json new file mode 100644 index 0000000000000000000000000000000000000000..d41273d85126160c2621b1cdec4861cebba143e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10863.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1ae1c28c42496c4465494b46aa69eec2313eb3f5", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "examples/preprocessing/movement_compensation.py": { + "a": 4, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10864.json b/mne-python/source/doc/sphinxext/prs/10864.json new file mode 100644 index 0000000000000000000000000000000000000000..8af3101adbace4a99323f3b4f1ed3e5b065180a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10864.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c5e683eac98803c6ba7bdbb8af439a2766f86a94", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + } + ], + "changes": { + "examples/preprocessing/movement_detection.py": { + "a": 5, + "d": 8 + }, + "examples/preprocessing/muscle_detection.py": { + "a": 1, + "d": 2 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10865.json b/mne-python/source/doc/sphinxext/prs/10865.json new file mode 100644 index 0000000000000000000000000000000000000000..e2976d5dae8e2a592d7a56a61ccaffe9f06f7624 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10865.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b58d6a52353d753353e0c7822ce9d1276d045e84", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 9, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10866.json b/mne-python/source/doc/sphinxext/prs/10866.json new file mode 100644 index 0000000000000000000000000000000000000000..593f2db970f713059b7292d863ea2e8c05e7adf5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10866.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0452d69396ade5186bfad166aa7c7f608b288867", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/ctf/ctf.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10868.json b/mne-python/source/doc/sphinxext/prs/10868.json new file mode 100644 index 0000000000000000000000000000000000000000..3d1ef5fe85ab192c16b6b7bfeea04655f9925cae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10868.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4b612d2e6411e64e27d6d9522c651e0d90bf1b8d", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "examples/inverse/morph_surface_stc.py": { + "a": 7, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10870.json b/mne-python/source/doc/sphinxext/prs/10870.json new file mode 100644 index 0000000000000000000000000000000000000000..ea440a75a7c4448f500a181b1ba2fa1f9a6cff7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10870.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3426356b3ec34787c2ac478dff1302cabfe7df99", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "examples/datasets/opm_data.py": { + "a": 6, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10873.json b/mne-python/source/doc/sphinxext/prs/10873.json new file mode 100644 index 0000000000000000000000000000000000000000..07b6d8e1c8b8cdd849c7c31d06a04bc520862984 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10873.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f0948f862c82159781ce822b2bd7614298f924be", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/install/installers.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10874.json b/mne-python/source/doc/sphinxext/prs/10874.json new file mode 100644 index 0000000000000000000000000000000000000000..e3e2f730100458b50f81593ecc73d421eaae2be0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10874.json @@ -0,0 +1,191 @@ +{ + "merge_commit_sha": "fdffb6eb95edb3858dd5884b5930b20c8d411448", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_includes/forward.rst": { + "a": 4, + "d": 4 + }, + "doc/_includes/morph.rst": { + "a": 2, + "d": 2 + }, + "doc/_static/funding/anr.svg": { + "a": 73, + "d": 6 + }, + "doc/_static/funding/erc-dark.svg": { + "a": 662, + "d": 0 + }, + "doc/_static/funding/erc.svg": { + "a": 2, + "d": 2 + }, + "doc/_static/funding/nih.png": { + "a": 0, + "d": 0 + }, + "doc/_static/funding/nih.svg": { + "a": 83, + "d": 0 + }, + "doc/_static/institution_logos/Aalto-dark.svg": { + "a": 2466, + "d": 0 + }, + "doc/_static/institution_logos/Aarhus-dark.svg": { + "a": 65, + "d": 0 + }, + "doc/_static/institution_logos/Aarhus.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Aarhus.svg": { + "a": 65, + "d": 0 + }, + "doc/_static/institution_logos/BIDS-dark.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/CHOP-dark.svg": { + "a": 1, + "d": 0 + }, + "doc/_static/institution_logos/Graz.jpg": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Graz.svg": { + "a": 1, + "d": 0 + }, + "doc/_static/institution_logos/Ilmenau-dark.svg": { + "a": 91, + "d": 0 + }, + "doc/_static/institution_logos/Ilmenau.gif": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Ilmenau.svg": { + "a": 91, + "d": 0 + }, + "doc/_static/institution_logos/Inserm-dark.svg": { + "a": 46, + "d": 0 + }, + "doc/_static/institution_logos/Inserm.svg": { + "a": 6, + "d": 6 + }, + "doc/_static/institution_logos/Julich-dark.svg": { + "a": 55, + "d": 0 + }, + "doc/_static/institution_logos/Julich.svg": { + "a": 33, + "d": 19 + }, + "doc/_static/institution_logos/MPIB-dark.svg": { + "a": 3, + "d": 0 + }, + "doc/_static/institution_logos/Macquarie-dark.svg": { + "a": 165, + "d": 0 + }, + "doc/_static/institution_logos/Macquarie.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Macquarie.svg": { + "a": 222, + "d": 0 + }, + "doc/_static/institution_logos/NYU-dark.svg": { + "a": 66, + "d": 0 + }, + "doc/_static/institution_logos/NYU.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/NYU.svg": { + "a": 66, + "d": 0 + }, + "doc/_static/institution_logos/SWPS-dark.svg": { + "a": 151, + "d": 0 + }, + "doc/_static/institution_logos/Washington-dark.svg": { + "a": 34, + "d": 0 + }, + "doc/_static/institution_logos/Washington.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Washington.svg": { + "a": 34, + "d": 0 + }, + "doc/_static/style.css": { + "a": 115, + "d": 69 + }, + "doc/_templates/homepage.html": { + "a": 4, + "d": 4 + }, + "doc/conf.py": { + "a": 103, + "d": 30 + }, + "doc/funding.rst": { + "a": 5, + "d": 2 + }, + "doc/install/check_installation.rst": { + "a": 1, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 54, + "d": 25 + }, + "doc/install/manual_install_python.rst": { + "a": 1, + "d": 0 + }, + "doc/install/mne_tools_suite.rst": { + "a": 2, + "d": 2 + }, + "doc/install/updating.rst": { + "a": 4, + "d": 1 + }, + "doc/overview/cite.rst": { + "a": 2, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 2, + "d": 2 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10875.json b/mne-python/source/doc/sphinxext/prs/10875.json new file mode 100644 index 0000000000000000000000000000000000000000..5463b3c28096dab3048ce39a892b9471d71f45d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10875.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b0a415d83d90e365e8a60483a0885b3b7ad3609b", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "tutorials/clinical/10_ieeg_localize.py": { + "a": 18, + "d": 21 + }, + "tutorials/clinical/20_seeg.py": { + "a": 6, + "d": 8 + }, + "tutorials/clinical/30_ecog.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10876.json b/mne-python/source/doc/sphinxext/prs/10876.json new file mode 100644 index 0000000000000000000000000000000000000000..64fa3dc2e737568b93b75443b7cdd312311d83af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10876.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5c5c7bad9eee72758567ec65306b5793d0640be8", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "tutorials/epochs/10_epochs_overview.py": { + "a": 2, + "d": 3 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 4, + "d": 5 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 1, + "d": 3 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 4, + "d": 5 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10879.json b/mne-python/source/doc/sphinxext/prs/10879.json new file mode 100644 index 0000000000000000000000000000000000000000..76a0809fecdc1ca9f3de948897771f87431a01cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10879.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3180e0b2061b008886873de518686debce2fe47d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10880.json b/mne-python/source/doc/sphinxext/prs/10880.json new file mode 100644 index 0000000000000000000000000000000000000000..fb45282d9e9555f11cccb25d6d33a1d646773b82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10880.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fe9f5a503377bc30683f22a16a4490e54111eb46", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 4, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10884.json b/mne-python/source/doc/sphinxext/prs/10884.json new file mode 100644 index 0000000000000000000000000000000000000000..f8268db75b95bdd32e6314431842d3cd0277d7e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10884.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "386d4cf56551a248637c5291d5b1568dbcd26d1e", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + } + ], + "changes": { + "doc/_includes/forward.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10886.json b/mne-python/source/doc/sphinxext/prs/10886.json new file mode 100644 index 0000000000000000000000000000000000000000..09079728b4888223d6c57ff2e8d0b59c703302f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10886.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e579fdb81d7d0ca30e7821cd61ea52ec6189e388", + "authors": [ + { + "n": "Carina", + "e": "carinaforster0611@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Phillip Alday", + "e": "palday@users.noreply.github.com" + }, + { + "n": "Phillip Alday", + "e": "palday@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Phillip Alday", + "e": "palday@users.noreply.github.com" + } + ], + "changes": { + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "tutorials/epochs/15_baseline_regression.py": { + "a": 285, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10887.json b/mne-python/source/doc/sphinxext/prs/10887.json new file mode 100644 index 0000000000000000000000000000000000000000..2229b688314873eb204f368c74ecd8ec2f6f2707 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10887.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3513c9472a56495415a2c8827d5083c650095050", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/inverse/mixed_source_space_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 7, + "d": 6 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 5, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10889.json b/mne-python/source/doc/sphinxext/prs/10889.json new file mode 100644 index 0000000000000000000000000000000000000000..de4eda4715f5900a9938fe878eb16ca3a58f4770 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10889.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "37bbe2757f062875049ff66e6bb2cdc8d1dcc412", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/decoding/tests/test_search_light.py": { + "a": 5, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10891.json b/mne-python/source/doc/sphinxext/prs/10891.json new file mode 100644 index 0000000000000000000000000000000000000000..c4723026466f384c3c4b0caed80cfbbf1538a1fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10891.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4d388dea2a305dc7ca97a1b556c81a4437e8732d", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "tutorials/forward/10_background_freesurfer.py": { + "a": 1, + "d": 2 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 9, + "d": 10 + }, + "tutorials/forward/30_forward.py": { + "a": 5, + "d": 6 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 13, + "d": 16 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10892.json b/mne-python/source/doc/sphinxext/prs/10892.json new file mode 100644 index 0000000000000000000000000000000000000000..83085b59945de0cdec824f018eefb5153e12f87b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10892.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "6921ed20975ae0b37be447bb5d2a185262f08ae7", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/file_io.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/besa/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/besa/besa.py": { + "a": 243, + "d": 0 + }, + "mne/io/besa/tests/data/simulation.avr": { + "a": 35, + "d": 0 + }, + "mne/io/besa/tests/data/simulation.elp": { + "a": 33, + "d": 0 + }, + "mne/io/besa/tests/data/simulation.mul": { + "a": 202, + "d": 0 + }, + "mne/io/besa/tests/data/simulation_oldstyle.avr": { + "a": 34, + "d": 0 + }, + "mne/io/besa/tests/data/simulation_oldstyle.elp": { + "a": 33, + "d": 0 + }, + "mne/io/besa/tests/test_besa.py": { + "a": 74, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10893.json b/mne-python/source/doc/sphinxext/prs/10893.json new file mode 100644 index 0000000000000000000000000000000000000000..89c668677d88976afe8a1722debb78a9250c3c2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10893.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "fdcfac7cf2b2620a8b16af595a31ada1bc0b0592", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "tutorials/intro/10_overview.py": { + "a": 5, + "d": 6 + }, + "tutorials/intro/15_inplace.py": { + "a": 2, + "d": 3 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 3, + "d": 4 + }, + "tutorials/intro/30_info.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10894.json b/mne-python/source/doc/sphinxext/prs/10894.json new file mode 100644 index 0000000000000000000000000000000000000000..5857c35947cad877dde75d6948ff7b3c5c70d360 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10894.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8a7658b615a67845a54302c357cd66d86f56cc99", + "authors": [ + { + "n": "Archit Singhal", + "e": null + }, + { + "n": "archit singhal", + "e": "zyphergiest@pop-os.localdomain" + } + ], + "changes": { + "examples/preprocessing/otp.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10895.json b/mne-python/source/doc/sphinxext/prs/10895.json new file mode 100644 index 0000000000000000000000000000000000000000..7e4afa84efe5d4b76da2360b0cc5a6c65dc1f7b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10895.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b3983fce7d06314275dc964c1d737fb904d8c9f2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 8, + "d": 7 + }, + "doc/links.inc": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10896.json b/mne-python/source/doc/sphinxext/prs/10896.json new file mode 100644 index 0000000000000000000000000000000000000000..6b94c3cb8d7e969ff90f2c3bcb1a3a306d050eef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10896.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3c23f13c0262118d075de0719248409bdc838982", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "tutorials/inverse/10_stc_class.py": { + "a": 3, + "d": 5 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 6, + "d": 7 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 7, + "d": 9 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 2 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10897.json b/mne-python/source/doc/sphinxext/prs/10897.json new file mode 100644 index 0000000000000000000000000000000000000000..d797ba6755d6f29cd8a95fc3cd25ee780d94af02 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10897.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3b2e6c914dbb820fec74cd1f4aca6e29e7e5c558", + "authors": [ + { + "n": "ashdrew", + "e": "ashdrew@uw.edu" + } + ], + "changes": { + "tutorials/io/30_reading_fnirs_data.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10898.json b/mne-python/source/doc/sphinxext/prs/10898.json new file mode 100644 index 0000000000000000000000000000000000000000..03a84eaa81e03f03582a5fc3736f4e0524566e17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10898.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "21c61576c2dce056a40946af0820d56e2259ec5f", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 39, + "d": 19 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 31, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/109.json b/mne-python/source/doc/sphinxext/prs/109.json new file mode 100644 index 0000000000000000000000000000000000000000..f9103da0eb28177bbff1f51b7080947b6eceb13b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/109.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "971aabad689f18951f810605125bd865c88315a0", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 8, + "d": 30 + }, + "mne/fiff/proj.py": { + "a": 54, + "d": 0 + }, + "mne/fiff/raw.py": { + "a": 121, + "d": 83 + }, + "mne/fiff/tests/test_raw.py": { + "a": 30, + "d": 0 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 20, + "d": 3 + }, + "mne/utils.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1090.json b/mne-python/source/doc/sphinxext/prs/1090.json new file mode 100644 index 0000000000000000000000000000000000000000..72ffb41fddd3818b4973541a80b76bcae8d208aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1090.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "44c41d463ca82924096c47605bf9afcdf940a745", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 21, + "d": 7 + }, + "mne/tests/test_viz.py": { + "a": 11, + "d": 2 + }, + "mne/viz.py": { + "a": 81, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10900.json b/mne-python/source/doc/sphinxext/prs/10900.json new file mode 100644 index 0000000000000000000000000000000000000000..1e2237b5d89405084c68e590bbbb49d24ace84a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10900.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a424fba542b7df53a5dcec12c518c7f6af64a740", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/institutional-partners.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10906.json b/mne-python/source/doc/sphinxext/prs/10906.json new file mode 100644 index 0000000000000000000000000000000000000000..4adce52a70b4a11c3d8d8bc07482f15b85912ab2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10906.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4351e611364be97c9bd156535ba73735bf6ea78d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/glossary.rst": { + "a": 6, + "d": 3 + }, + "mne/datasets/_fetch.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 67, + "d": 2 + }, + "mne/source_space.py": { + "a": 130, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10907.json b/mne-python/source/doc/sphinxext/prs/10907.json new file mode 100644 index 0000000000000000000000000000000000000000..b29a141e06e3ea188d1185ac1f045d9541029fce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10907.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8a837ec2c6544589747bfd7aec39115cda3ecff5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1091.json b/mne-python/source/doc/sphinxext/prs/1091.json new file mode 100644 index 0000000000000000000000000000000000000000..818055842d22ab38c9dd2c4672b0ffe2fb8e039c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1091.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "05c8f5202322ba4c41827e5b9d459eedb3216138", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 93, + "d": 0 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/ems.py": { + "a": 117, + "d": 0 + }, + "mne/decoding/tests/test_ems.py": { + "a": 61, + "d": 0 + }, + "mne/fiff/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 28, + "d": 19 + }, + "mne/utils.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10911.json b/mne-python/source/doc/sphinxext/prs/10911.json new file mode 100644 index 0000000000000000000000000000000000000000..e5626f47a732f4157b924a0e160a9517a730a3b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10911.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "86d3c2a9559d1e7cd59ae806fcdc25051becc9de", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/autosummary/class_no_inherited_members.rst": { + "a": 13, + "d": 0 + }, + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "doc/forward.rst": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10912.json b/mne-python/source/doc/sphinxext/prs/10912.json new file mode 100644 index 0000000000000000000000000000000000000000..9e4c5199b00e72fbc42de8a51d93b86af0573278 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10912.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "73247a9a5afb5cebc72f1c63b08efc015a1a8955", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/reference.py": { + "a": 5, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10913.json b/mne-python/source/doc/sphinxext/prs/10913.json new file mode 100644 index 0000000000000000000000000000000000000000..e830fb6f44ce15ae36491085e477c287795fc6b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10913.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "4c219c20a2ce07cde7dc26875200eeb6d7abeffb", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 5, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 423, + "d": 31 + }, + "mne/viz/backends/_notebook.py": { + "a": 729, + "d": 11 + }, + "mne/viz/backends/_qt.py": { + "a": 734, + "d": 26 + }, + "mne/viz/backends/renderer.py": { + "a": 5, + "d": 0 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 109, + "d": 0 + }, + "mne/viz/backends/tests/test_abstract_notebook.py": { + "a": 30, + "d": 0 + }, + "requirements.txt": { + "a": 2, + "d": 0 + }, + "server_environment.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10917.json b/mne-python/source/doc/sphinxext/prs/10917.json new file mode 100644 index 0000000000000000000000000000000000000000..fb573afb286dd92248e77d86f473fad6a4d38436 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10917.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c6d26627a3b0a8ceae33a2f1e59f81207e4d4456", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/70_cluster_rmANOVA_time_freq.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1092.json b/mne-python/source/doc/sphinxext/prs/1092.json new file mode 100644 index 0000000000000000000000000000000000000000..dec79c60099f3e0e402b2669ca715e0761b1c0a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1092.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "690bc1dd7e000c0ae55dd99a274cbb374e956462", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/meas_info.py": { + "a": 24, + "d": 1 + }, + "mne/fiff/tests/test_meas_info.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10920.json b/mne-python/source/doc/sphinxext/prs/10920.json new file mode 100644 index 0000000000000000000000000000000000000000..73217277729ba8fc730c90f76b2bb9d687b6a79c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10920.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "2d1babfeef86f6294d5f7a981026f13489dd3e0b", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/mri.rst": { + "a": 1, + "d": 0 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 95, + "d": 32 + }, + "mne/gui/__init__.py": { + "a": 96, + "d": 1 + }, + "mne/gui/_core.py": { + "a": 33, + "d": 33 + }, + "mne/gui/_vol_stc.py": { + "a": 896, + "d": 0 + }, + "mne/gui/tests/test_core.py": { + "a": 2, + "d": 2 + }, + "mne/gui/tests/test_vol_stc.py": { + "a": 202, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 31, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10922.json b/mne-python/source/doc/sphinxext/prs/10922.json new file mode 100644 index 0000000000000000000000000000000000000000..78c8224561369dc5301564d4bad457fc8edbc1fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10922.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "73e1d858e1aad07f12c649ef1b84707d98dd59a7", + "authors": [ + { + "n": "Mingjian He", + "e": null + } + ], + "changes": { + "doc/_includes/inverse.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10923.json b/mne-python/source/doc/sphinxext/prs/10923.json new file mode 100644 index 0000000000000000000000000000000000000000..734e165ba3e4840350fa2509fb71283749402d2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10923.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "94433a355fe164dca8154e6a27e0442cb6844801", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/linux_pip.yml": { + "a": 3, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 4, + "d": 0 + }, + "tools/setup_xvfb.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10925.json b/mne-python/source/doc/sphinxext/prs/10925.json new file mode 100644 index 0000000000000000000000000000000000000000..859f14132ebbb9eea0bd1d967c89cc4328f2baa4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10925.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "febd79800e325aad32eda57b63ad8bd95ae6ea9d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 15, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 3, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10926.json b/mne-python/source/doc/sphinxext/prs/10926.json new file mode 100644 index 0000000000000000000000000000000000000000..ca2a42f702af51f9cf0ed7c90d5d09f884faec28 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10926.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e09482b016d1a1a4284edd837cf3c130730386d3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10927.json b/mne-python/source/doc/sphinxext/prs/10927.json new file mode 100644 index 0000000000000000000000000000000000000000..5ee1d621b68504d24cb7680aebb98afac1e8ff49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10927.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b733f72c4f2fdffcaf1248491368c7240e30c7f8", + "authors": [ + { + "n": "Reza", + "e": "rezanasri@outlook.com" + }, + { + "n": "RezaNasri", + "e": "rezanasri@outlook.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/export/_eeglab.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1093.json b/mne-python/source/doc/sphinxext/prs/1093.json new file mode 100644 index 0000000000000000000000000000000000000000..65aa7eef216d3ce9531da84814cbc46354398682 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1093.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cdc5e465a353f8b018786989b6b28e0f7c7e4939", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/surface.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10930.json b/mne-python/source/doc/sphinxext/prs/10930.json new file mode 100644 index 0000000000000000000000000000000000000000..dacd42670d7a332e04f0eef049d6c29494747247 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10930.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "171371169a519062296fc370d3050ba6a7146de5", + "authors": [ + { + "n": "Christian O'Reilly", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/surface.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 46, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10933.json b/mne-python/source/doc/sphinxext/prs/10933.json new file mode 100644 index 0000000000000000000000000000000000000000..ac17ddf17ea2dd447e00eb52dcbb74c92878c413 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10933.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6955f977ac12612f38ab30277dcfff94315a0463", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fixes.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10936.json b/mne-python/source/doc/sphinxext/prs/10936.json new file mode 100644 index 0000000000000000000000000000000000000000..f5ae1f5117beaef1477addccb67176c76d91af15 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10936.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e8ded9719de7425c8d6752d2942a6ecba20fd0fc", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10938.json b/mne-python/source/doc/sphinxext/prs/10938.json new file mode 100644 index 0000000000000000000000000000000000000000..4c5565c98e851c90313ff8f0bdf2c11a2f8ca5cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10938.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c6a86f15b8ace3758443f392ba8bfe5a9a0c2878", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1094.json b/mne-python/source/doc/sphinxext/prs/1094.json new file mode 100644 index 0000000000000000000000000000000000000000..ea9ec16c26761998ac0648534067f7a236716c2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1094.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "034cc9d43d7bbfde25ea0bf02bf2428806a214bf", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10940.json b/mne-python/source/doc/sphinxext/prs/10940.json new file mode 100644 index 0000000000000000000000000000000000000000..449806b307e06d9cea7ed2cceb2eb98e5c343796 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10940.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "80c3596228287c5577be6b921f25c426edef2aec", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 79 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 15, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 12, + "d": 10 + }, + "mne/utils/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/utils/mixin.py": { + "a": 81, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10942.json b/mne-python/source/doc/sphinxext/prs/10942.json new file mode 100644 index 0000000000000000000000000000000000000000..4e9068d5066dda9032f9a61e5e8d6a3e579a29c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10942.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "a8e9495685531fc0fd2f52fc4bec32b769ec936f", + "authors": [ + { + "n": "TzionaN", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 9, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 14, + "d": 0 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10944.json b/mne-python/source/doc/sphinxext/prs/10944.json new file mode 100644 index 0000000000000000000000000000000000000000..7d10e54fda43b6d72a0f6b81d9520be8ad3e21d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10944.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6c2b485d128643a5e96ee45fbe496ecea9438f28", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/utils/check.py": { + "a": 19, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10945.json b/mne-python/source/doc/sphinxext/prs/10945.json new file mode 100644 index 0000000000000000000000000000000000000000..42cb3144e5115fd314490421b452c3c792bff237 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10945.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "23f37cdaf1b5e2b2b8d0e7c38de2b0483b38673d", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 11, + "d": 10 + }, + "mne/epochs.py": { + "a": 8, + "d": 28 + }, + "mne/evoked.py": { + "a": 14, + "d": 132 + }, + "mne/filter.py": { + "a": 3, + "d": 6 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 66 + }, + "mne/report/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 11, + "d": 9 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 10, + "d": 17 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/utils/mixin.py": { + "a": 182, + "d": 54 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10949.json b/mne-python/source/doc/sphinxext/prs/10949.json new file mode 100644 index 0000000000000000000000000000000000000000..2c6d4301e6201c5b63044071ccf9a3685ebe1dbf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10949.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "82be959161b4911faba40aca7604236c4ee0f3ec", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "server_environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1095.json b/mne-python/source/doc/sphinxext/prs/1095.json new file mode 100644 index 0000000000000000000000000000000000000000..39c5a0a8c212ce5b2d1af1634eac1dc1afc6d131 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1095.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "034ffce93c6e2bab7aedfce5ae0ed0ecbc887e4b", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/sphinxext/gen_rst.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10950.json b/mne-python/source/doc/sphinxext/prs/10950.json new file mode 100644 index 0000000000000000000000000000000000000000..d8005bb05f9f3cda830375281d501a59df168814 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10950.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b9287882beb8e04ad362b333ad5f14047a8c07ff", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 14, + "d": 9 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10951.json b/mne-python/source/doc/sphinxext/prs/10951.json new file mode 100644 index 0000000000000000000000000000000000000000..bf1176d40e89102619d2da7df4597ebb6042d5c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10951.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6a0b02dc06290d0f7f89c6c35310b9e7216ee58c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10953.json b/mne-python/source/doc/sphinxext/prs/10953.json new file mode 100644 index 0000000000000000000000000000000000000000..b27707c924070bd4335437ed819f256d1071a888 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10953.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4e5ca1bf86429d976d86223480bd091d4b3888e2", + "authors": [ + { + "n": "TzionaN", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10956.json b/mne-python/source/doc/sphinxext/prs/10956.json new file mode 100644 index 0000000000000000000000000000000000000000..d8bbcd361ade8b486868bca8c39561c2df58ca61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10956.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bf7fd4755a95ad43aa7c2dd07b1ed12656f85292", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/backends/_utils.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10957.json b/mne-python/source/doc/sphinxext/prs/10957.json new file mode 100644 index 0000000000000000000000000000000000000000..0971b20f377cd6888d76aed9f92df5135cc0b9cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10957.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c12a02000776adb9df18da55ea60c50cbf83827d", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/ctf/info.py": { + "a": 6, + "d": 0 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10958.json b/mne-python/source/doc/sphinxext/prs/10958.json new file mode 100644 index 0000000000000000000000000000000000000000..fb422cc3086f02029b9fbcc487ea92cd7796df82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10958.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "622dc0cf358bd20523219d01f93d2f87b28c1c86", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10962.json b/mne-python/source/doc/sphinxext/prs/10962.json new file mode 100644 index 0000000000000000000000000000000000000000..c4c70b36977a8d81e3b8aeab36bdb2333c754092 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10962.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b4c44312da300c79578f9bfb953ee5a0b597d6c4", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/constants.py": { + "a": 5, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10963.json b/mne-python/source/doc/sphinxext/prs/10963.json new file mode 100644 index 0000000000000000000000000000000000000000..b19c2a60c08fd0f35d49e762d56df4b4d7e6d33d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10963.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1d1868d2c94e3cf7ff27f3256d20aae0840664ea", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 4 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10967.json b/mne-python/source/doc/sphinxext/prs/10967.json new file mode 100644 index 0000000000000000000000000000000000000000..5f8c1992dfb7f4aca65f8ff27ca4be31b1b9582d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10967.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f3f26c61aa9cd8480493f86df4b7bcef13e598e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/surface.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 25, + "d": 34 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10968.json b/mne-python/source/doc/sphinxext/prs/10968.json new file mode 100644 index 0000000000000000000000000000000000000000..3fcf363ada94679189f45be2b3fd7d5d293bada6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10968.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "48eb3f3e218d2297af0ef3310c1e86b70012e7a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 11, + "d": 2 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10969.json b/mne-python/source/doc/sphinxext/prs/10969.json new file mode 100644 index 0000000000000000000000000000000000000000..ca35a701e2b72871424a57f1ea7c6c5f80498b35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10969.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "04747bbfbc6f1714ffc943dfe9b86a689446580a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/simulation/simulated_raw_data_using_subject_anatomy.py": { + "a": 13, + "d": 8 + }, + "examples/simulation/source_simulator.py": { + "a": 12, + "d": 6 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 6, + "d": 11 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 4, + "d": 6 + }, + "examples/visualization/3d_to_2d.py": { + "a": 9, + "d": 7 + }, + "examples/visualization/brain.py": { + "a": 10, + "d": 10 + }, + "examples/visualization/meg_sensors.py": { + "a": 11, + "d": 9 + }, + "examples/visualization/mne_helmet.py": { + "a": 5, + "d": 7 + }, + "mne/forward/_field_interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10972.json b/mne-python/source/doc/sphinxext/prs/10972.json new file mode 100644 index 0000000000000000000000000000000000000000..5e01cd416b28adea1486de00e7bb38385c445170 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10972.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f2ea6807c86d265c3828c94fb9c052324dbca49c", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/gui/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_ieeg_locate.py": { + "a": 0, + "d": 0 + }, + "mne/gui/tests/test_core.py": { + "a": 0, + "d": 0 + }, + "mne/gui/tests/test_coreg.py": { + "a": 0, + "d": 0 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10973.json b/mne-python/source/doc/sphinxext/prs/10973.json new file mode 100644 index 0000000000000000000000000000000000000000..55ce98f111ede850cd09a56b9ef28e06fd0dd0c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10973.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "2a25dd1c090bbcf2e3a3a148eac41e88d6d369dc", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/institution_logos/BIDS-dark.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/BIDS-dark.svg": { + "a": 318, + "d": 0 + }, + "doc/_static/institution_logos/BIDS.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/BIDS.svg": { + "a": 318, + "d": 0 + }, + "doc/_static/style.css": { + "a": 120, + "d": 98 + }, + "doc/_templates/layout.html": { + "a": 69, + "d": 9 + }, + "doc/conf.py": { + "a": 3, + "d": 4 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 0, + "d": 1 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 2, + "d": 1 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 2, + "d": 1 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 2, + "d": 1 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 2, + "d": 1 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 10, + "d": 8 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 2, + "d": 1 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 7, + "d": 5 + }, + "tutorials/io/10_reading_meg_data.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 12, + "d": 8 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 2, + "d": 1 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 10, + "d": 5 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 2, + "d": 1 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 9, + "d": 6 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10974.json b/mne-python/source/doc/sphinxext/prs/10974.json new file mode 100644 index 0000000000000000000000000000000000000000..b9c0c2f4aecb29e4d750ca04e40985160a490bff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10974.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "f4e6f971c43327ec5cc4100b7e026b33303de860", + "authors": [ + { + "n": "Ilias Machairas", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 2, + "d": 0 + }, + "mne/channels/data/montages/brainproducts-RNP-BA-128.txt": { + "a": 131, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10978.json b/mne-python/source/doc/sphinxext/prs/10978.json new file mode 100644 index 0000000000000000000000000000000000000000..d36cce4242d93616cd5640892c042e6db533f7bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10978.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "d3fb79553783d4dd4637f946e721a006547c07d4", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 3, + "d": 0 + }, + "mne/viz/tests/test_misc.py": { + "a": 4, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 6, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 7, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10979.json b/mne-python/source/doc/sphinxext/prs/10979.json new file mode 100644 index 0000000000000000000000000000000000000000..6bc67b3a5fdb9dd740cecf5845eb22a3327400c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10979.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "64dff6189215cbead61db81d6e6de811a05633e3", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1098.json b/mne-python/source/doc/sphinxext/prs/1098.json new file mode 100644 index 0000000000000000000000000000000000000000..0a028564bc3e53002edada27eb8722ff1d04f033 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1098.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e0ef5d084014dbe2628d15b33132ba834560698e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10980.json b/mne-python/source/doc/sphinxext/prs/10980.json new file mode 100644 index 0000000000000000000000000000000000000000..567af6948b33783377891be09fcab31b7da37fa3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10980.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "11696d018595e934bf98080f08d1ddeb704e1c4d", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 19, + "d": 8 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10982.json b/mne-python/source/doc/sphinxext/prs/10982.json new file mode 100644 index 0000000000000000000000000000000000000000..f5cc76bcc4f028979bf33b61c92aa1a8d753cf46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10982.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "93c144e562c81489766eeb4cb98766534a8576af", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 0, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 2 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 3, + "d": 3 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/hc.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/markers.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 3, + "d": 3 + }, + "mne/transforms.py": { + "a": 3, + "d": 3 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10986.json b/mne-python/source/doc/sphinxext/prs/10986.json new file mode 100644 index 0000000000000000000000000000000000000000..f63f8c36baf0f9a8a1d3b30a79f2c61ebd38a105 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10986.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "530988c7475f9a60cfa137972b8523180aaa3c0f", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/time_frequency.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 49, + "d": 3 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 21, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10989.json b/mne-python/source/doc/sphinxext/prs/10989.json new file mode 100644 index 0000000000000000000000000000000000000000..225fab0efbe733d442c76f2e6abef0eaba7f1e17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10989.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f97faf7ae1e88dd0976c6b2dbbf23155c1c83065", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 3 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10990.json b/mne-python/source/doc/sphinxext/prs/10990.json new file mode 100644 index 0000000000000000000000000000000000000000..4e9d05b3d68a54c1e3f0d482094353e9738ab447 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10990.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "245844206d4b6d806fac2ec2ba60b77f83b31841", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 8, + "d": 1 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10993.json b/mne-python/source/doc/sphinxext/prs/10993.json new file mode 100644 index 0000000000000000000000000000000000000000..6c2f215021895a2189880db7b73d7fa58e175abd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10993.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "078149bf980943e84c8b7fd9950e7dc89f3b7745", + "authors": [ + { + "n": "Ben Beasley", + "e": "code@musicinmybrain.net" + } + ], + "changes": { + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10994.json b/mne-python/source/doc/sphinxext/prs/10994.json new file mode 100644 index 0000000000000000000000000000000000000000..c0545b1672e2821fc7b0cea3ea140dba407a5da8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10994.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "d57a3d649050aa4cdcdea86e7f5b8039df8d2307", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".mailmap": { + "a": 249, + "d": 231 + }, + "CITATION.cff": { + "a": 655, + "d": 0 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "SECURITY.md": { + "a": 3, + "d": 3 + }, + "codemeta.json": { + "a": 262, + "d": 154 + }, + "doc/_static/versions.json": { + "a": 6, + "d": 2 + }, + "doc/changes/1.1.inc": { + "a": 56, + "d": 3 + }, + "doc/changes/names.inc": { + "a": 248, + "d": 230 + }, + "doc/cited.rst": { + "a": 3, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/_version.py": { + "a": 1, + "d": 1 + }, + "tools/circleci_download.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10997.json b/mne-python/source/doc/sphinxext/prs/10997.json new file mode 100644 index 0000000000000000000000000000000000000000..5d5ac98d7526abd412eb7ca757eeb490392138c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10997.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "60087ebe36943f760cafcc10a0e99bc5b3b685bf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 33, + "d": 5 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 32, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/10999.json b/mne-python/source/doc/sphinxext/prs/10999.json new file mode 100644 index 0000000000000000000000000000000000000000..0437849096267da2756c6779779cb77b9c9f37e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/10999.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2d183aade4f482ca39516edb6569b9ca450b8665", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 31, + "d": 0 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1100.json b/mne-python/source/doc/sphinxext/prs/1100.json new file mode 100644 index 0000000000000000000000000000000000000000..f4a5ef6c14903a08c0cf034005d488ecad53e6e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1100.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4ef4ff748a3f83a2761ecf25093ae162821e84bb", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/datasets/sample/sample.py": { + "a": 11, + "d": 4 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 8, + "d": 4 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11000.json b/mne-python/source/doc/sphinxext/prs/11000.json new file mode 100644 index 0000000000000000000000000000000000000000..eaf269fbc69c95de16c013a3cb18fc2e2234dabe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11000.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f27df270539bda9994ec791232d87a82b262d721", + "authors": [ + { + "n": "Jack Zhang", + "e": "me@jackzhang.me" + } + ], + "changes": { + "mne/export/_eeglab.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11001.json b/mne-python/source/doc/sphinxext/prs/11001.json new file mode 100644 index 0000000000000000000000000000000000000000..c5b75af4618c2749237c093cea75738e7899cf8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11001.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cee9e96e99abc98ce4fd0ae5e0a9ffcb0c3919f3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/time_frequency/time_frequency_erds.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11003.json b/mne-python/source/doc/sphinxext/prs/11003.json new file mode 100644 index 0000000000000000000000000000000000000000..837fa2d4fa8193a0bd6ec62b0f4e7d384bf318c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11003.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ef8b971340ddee0f7fe4a2a51c51ccc37d205b3e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "tools/check_mne_location.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11004.json b/mne-python/source/doc/sphinxext/prs/11004.json new file mode 100644 index 0000000000000000000000000000000000000000..0bb7694555acde663a615893e18de0ef726756fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11004.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ec8a360911172e8c245b676c0e2af38c023b266f", + "authors": [ + { + "n": "Daniel C Schad", + "e": null + }, + { + "n": "Daniel Carlström Schad", + "e": "daniel.c.schad@protonmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 5, + "d": 0 + }, + "mne/decoding/time_frequency.py": { + "a": 11, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11006.json b/mne-python/source/doc/sphinxext/prs/11006.json new file mode 100644 index 0000000000000000000000000000000000000000..ea6979bdf8f725765a1ffe9adff179808a774951 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11006.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a511bfbc820293f08a9a42aa19e9f21cbf63c4a0", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/_eeglab.py": { + "a": 82, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 4 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 23, + "d": 8 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11007.json b/mne-python/source/doc/sphinxext/prs/11007.json new file mode 100644 index 0000000000000000000000000000000000000000..e34bd2653e46ff69275ca3e5ec021d27ce3dc0ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11007.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "d44fc4e19ee44ec7f70870842507c282f33b54e5", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 6, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 19, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 5 + }, + "requirements_doc.txt": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11008.json b/mne-python/source/doc/sphinxext/prs/11008.json new file mode 100644 index 0000000000000000000000000000000000000000..c4e46cc8eeca7f7c4d56489e685e43b05228e8d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11008.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "2ba483ab91828be18a480e689d95f61c422ed6eb", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/bem.py": { + "a": 11, + "d": 79 + }, + "mne/commands/mne_flash_bem.py": { + "a": 3, + "d": 6 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 3 + }, + "mne/datasets/_fetch.py": { + "a": 4, + "d": 3 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 13 + }, + "mne/datasets/utils.py": { + "a": 4, + "d": 34 + }, + "mne/gui/tests/test_coreg.py": { + "a": 3, + "d": 1 + }, + "mne/parallel.py": { + "a": 1, + "d": 31 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/utils/_testing.py": { + "a": 0, + "d": 31 + }, + "mne/utils/tests/test_testing.py": { + "a": 1, + "d": 20 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11009.json b/mne-python/source/doc/sphinxext/prs/11009.json new file mode 100644 index 0000000000000000000000000000000000000000..9d735d43e53f4c121443a9daf46a0cc0ac68c4b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11009.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "440ce1a9bed96526526cc256dfa282335571ed21", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/tests/test_docstring_parameters.py": { + "a": 8, + "d": 12 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11011.json b/mne-python/source/doc/sphinxext/prs/11011.json new file mode 100644 index 0000000000000000000000000000000000000000..be22df63b5d83587feb1589d469ac40a4743ca61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11011.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "44f499f13c5100cc86058c65ba81dbd50412ec7e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 0, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/links.inc": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 203, + "d": 37 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 69, + "d": 10 + }, + "mne/forward/_make_forward.py": { + "a": 14, + "d": 9 + }, + "mne/forward/forward.py": { + "a": 47, + "d": 33 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 144, + "d": 28 + }, + "mne/io/constants.py": { + "a": 0, + "d": 4 + }, + "mne/simulation/raw.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 37, + "d": 12 + }, + "mne/utils/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/utils/_testing.py": { + "a": 13, + "d": 0 + }, + "mne/utils/config.py": { + "a": 2, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 4, + "d": 3 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11012.json b/mne-python/source/doc/sphinxext/prs/11012.json new file mode 100644 index 0000000000000000000000000000000000000000..2acffd7eecc1289fcf9f7675d152a2911622fcab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11012.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b5fb30aac5ead825727d7d83db51378101941868", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/gen_commands.py": { + "a": 2, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 15, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11016.json b/mne-python/source/doc/sphinxext/prs/11016.json new file mode 100644 index 0000000000000000000000000000000000000000..502009072405562b13c2681701b9628e9bc75429 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11016.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8baaa7675ea34d3b98dd2875ad8b5efaf6d44d16", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 10 + }, + "mne/viz/backends/_qt.py": { + "a": 1, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11017.json b/mne-python/source/doc/sphinxext/prs/11017.json new file mode 100644 index 0000000000000000000000000000000000000000..962217fee44662bc127c4f77245f59d8f3a93c60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11017.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "879829e3d4da228f0c022d8f1ca4abf6e4599c81", + "authors": [ + { + "n": "Hüseyin", + "e": "huseyinorkunelmas@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_proj.py": { + "a": 2, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 20, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 25, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11018.json b/mne-python/source/doc/sphinxext/prs/11018.json new file mode 100644 index 0000000000000000000000000000000000000000..0cf65c7b00eb038d929c3ca12046fc9fd0111f32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11018.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9adf3f1cad3264b93e32c0ca51e3fc003a297a11", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/report/report.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11019.json b/mne-python/source/doc/sphinxext/prs/11019.json new file mode 100644 index 0000000000000000000000000000000000000000..33c7a6ca8fd785a74f83775a7389b5e30de9ddc1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11019.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7044b8202f9549c18f486d263f167153138d9925", + "authors": [ + { + "n": "Sena", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1102.json b/mne-python/source/doc/sphinxext/prs/1102.json new file mode 100644 index 0000000000000000000000000000000000000000..88b376c2758b49d8ffb50495067e3b3ed7919abb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1102.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "004d3aaaaaa693ea7b5a490a49ef268c117ae2a7", + "authors": [ + { + "n": "Daniel G. Wakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 15, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11020.json b/mne-python/source/doc/sphinxext/prs/11020.json new file mode 100644 index 0000000000000000000000000000000000000000..935de373f6d33f127c90bed56e65f415a28e6416 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11020.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "711da1d40783c8f37cea85e0b338c5e08e5dad93", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/transforms.py": { + "a": 11, + "d": 4 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 7, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11022.json b/mne-python/source/doc/sphinxext/prs/11022.json new file mode 100644 index 0000000000000000000000000000000000000000..ac0634d67383ff694760219229be60bd04ebe6c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11022.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c8d8c5f72e6714ae147994effcee8efe04c648f4", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 1, + "d": 58 + }, + "mne/io/pick.py": { + "a": 1, + "d": 57 + }, + "mne/utils/docs.py": { + "a": 61, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11024.json b/mne-python/source/doc/sphinxext/prs/11024.json new file mode 100644 index 0000000000000000000000000000000000000000..17c635a68383364a1268cc38be6108bce3eab305 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11024.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6d27c4260adcbad9c171688427453eaf99545cd1", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/references.bib": { + "a": 0, + "d": 10 + }, + "mne/preprocessing/_csd.py": { + "a": 10, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11029.json b/mne-python/source/doc/sphinxext/prs/11029.json new file mode 100644 index 0000000000000000000000000000000000000000..434804a80aa4430a4723e8c87ef23e44c42055ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11029.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c1f65be9f79cdb29f629f5335d79d2fedd32f73b", + "authors": [ + { + "n": "Sena", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/time_frequency/compute_csd.py": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11033.json b/mne-python/source/doc/sphinxext/prs/11033.json new file mode 100644 index 0000000000000000000000000000000000000000..5388fc2e49ae6fd0b11cdfdeb2032fb956b57a76 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11033.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f55c5eab72c6848ee808413eee473fbf21036a56", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 9, + "d": 69 + }, + "doc/conf.py": { + "a": 5, + "d": 2 + }, + "doc/install/installers.rst": { + "a": 12, + "d": 4 + }, + "doc/install/manual_install_python.rst": { + "a": 8, + "d": 3 + }, + "requirements_doc.txt": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11034.json b/mne-python/source/doc/sphinxext/prs/11034.json new file mode 100644 index 0000000000000000000000000000000000000000..aa60a2054efb75ec40684528fe9004c03e73df32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11034.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ae3e0b885685c07915fe06031d70b3c637b2aa90", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11035.json b/mne-python/source/doc/sphinxext/prs/11035.json new file mode 100644 index 0000000000000000000000000000000000000000..d039067a3c2509d2751e5d8ba45af705ff2da5bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11035.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7511bf717665005dcc0445efab30e16cbe84ba99", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/_includes/channel_types.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/0.23.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11037.json b/mne-python/source/doc/sphinxext/prs/11037.json new file mode 100644 index 0000000000000000000000000000000000000000..76a6dd19ec03e927d17d9d93daf26deac3876acd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11037.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "93a1856445f1f838b0faf4b4cdf61397661c7c0a", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11038.json b/mne-python/source/doc/sphinxext/prs/11038.json new file mode 100644 index 0000000000000000000000000000000000000000..422d64b73a539e995fa8246041e99b21c9b34e4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11038.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7d80664de0ebefcee5532864565bb49cfae27cc2", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/time_frequency/csd.py": { + "a": 26, + "d": 6 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1104.json b/mne-python/source/doc/sphinxext/prs/1104.json new file mode 100644 index 0000000000000000000000000000000000000000..8cab051489c82a2dc6bf3b797f5d4f5517ae1abb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1104.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "a3dbd6751c4455c436ced5bd6d96019285b0cfb3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/externals/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/externals/jdcal.py": { + "a": 116, + "d": 0 + }, + "mne/fiff/brainvision/brainvision.py": { + "a": 2, + "d": 0 + }, + "mne/fiff/constants.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/edf/edf.py": { + "a": 2, + "d": 0 + }, + "mne/fiff/meas_info.py": { + "a": 67, + "d": 3 + }, + "mne/fiff/open.py": { + "a": 2, + "d": 0 + }, + "mne/fiff/raw.py": { + "a": 6, + "d": 0 + }, + "mne/fiff/tag.py": { + "a": 4, + "d": 1 + }, + "mne/fiff/tests/test_raw.py": { + "a": 28, + "d": 2 + }, + "mne/fiff/write.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11040.json b/mne-python/source/doc/sphinxext/prs/11040.json new file mode 100644 index 0000000000000000000000000000000000000000..72ac38084af8005087eeca66b1550f3282e32eef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11040.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "776c91f7a92402f02174c1f79124e236e1e38e89", + "authors": [ + { + "n": "mdovgialo", + "e": "mdovgialo@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_misc.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11041.json b/mne-python/source/doc/sphinxext/prs/11041.json new file mode 100644 index 0000000000000000000000000000000000000000..fb85df74ebe5278f223698ecba331ac581d6cc30 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11041.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3df770ce87915b5ef221d9b65ace481868a871b6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/export/tests/test_export.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11046.json b/mne-python/source/doc/sphinxext/prs/11046.json new file mode 100644 index 0000000000000000000000000000000000000000..17e54485542fe30f5f2d1e4ed697edceec0d316a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11046.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "12cf8749adfee03caaaa1424b0440a2eaa9886cb", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 11, + "d": 0 + }, + "doc/visualization.rst": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/eog_regression.py": { + "a": 78, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_regress.py": { + "a": 269, + "d": 32 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 105, + "d": 5 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 83, + "d": 0 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 165, + "d": 105 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11047.json b/mne-python/source/doc/sphinxext/prs/11047.json new file mode 100644 index 0000000000000000000000000000000000000000..16765704dac2592fa808e41bcc4ffbbfd7f5e185 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11047.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "fa11149b9d246c115ea0794ce9c819c36ec34f72", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 0 + }, + "Makefile": { + "a": 3, + "d": 3 + }, + "ignore_words.txt": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ssd.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/curry/curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/nihon/nihon.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 1, + "d": 1 + }, + "mne/utils/dataframe.py": { + "a": 15, + "d": 4 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11048.json b/mne-python/source/doc/sphinxext/prs/11048.json new file mode 100644 index 0000000000000000000000000000000000000000..74ab45cdf723eb9ea481f57aea7d29a7926c0ba2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11048.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f855987927f1ad94670288067a8598e14b7fd509", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 6, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11049.json b/mne-python/source/doc/sphinxext/prs/11049.json new file mode 100644 index 0000000000000000000000000000000000000000..4b2cdba0280c73145a5abb00e9e8f92469f088bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11049.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d4564c25bd156f85a63904414f76bccae55db67e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 39, + "d": 20 + }, + "mne/viz/_brain/surface.py": { + "a": 5, + "d": 5 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 14, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11050.json b/mne-python/source/doc/sphinxext/prs/11050.json new file mode 100644 index 0000000000000000000000000000000000000000..2c00946c6466533189c8517ce3306786d1f1f2e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11050.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9acfa0642c0681a5d208a8ce551b2985338ace0a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 20, + "d": 12 + }, + "mne/viz/topomap.py": { + "a": 19, + "d": 11 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11051.json b/mne-python/source/doc/sphinxext/prs/11051.json new file mode 100644 index 0000000000000000000000000000000000000000..d80ac04735a022f3e081e78725830b6713966c82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11051.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7720b4d6b4b637bb0819a9a44e750ee82675b25f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 4 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11052.json b/mne-python/source/doc/sphinxext/prs/11052.json new file mode 100644 index 0000000000000000000000000000000000000000..f8599470ba6dbaade819f35a256cab18f377cd9e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11052.json @@ -0,0 +1,143 @@ +{ + "merge_commit_sha": "0cd79a3608ab3817ee180c0f0c4d9307bf653d3a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/funding/amazon.svg": { + "a": 16, + "d": 17 + }, + "doc/_static/funding/anr.svg": { + "a": 14, + "d": 68 + }, + "doc/_static/funding/czi.svg": { + "a": 12, + "d": 19 + }, + "doc/_static/funding/doe.svg": { + "a": 72, + "d": 1658 + }, + "doc/_static/funding/erc-dark.svg": { + "a": 13, + "d": 658 + }, + "doc/_static/funding/erc.svg": { + "a": 13, + "d": 658 + }, + "doc/_static/funding/google.svg": { + "a": 9, + "d": 1 + }, + "doc/_static/funding/nih.svg": { + "a": 6, + "d": 81 + }, + "doc/_static/institution_logos/Aalto-dark.svg": { + "a": 11, + "d": 2466 + }, + "doc/_static/institution_logos/Aalto.svg": { + "a": 11, + "d": 2466 + }, + "doc/_static/institution_logos/Aarhus-dark.svg": { + "a": 2, + "d": 64 + }, + "doc/_static/institution_logos/Aarhus.svg": { + "a": 2, + "d": 64 + }, + "doc/_static/institution_logos/BIDS-dark.svg": { + "a": 52, + "d": 318 + }, + "doc/_static/institution_logos/BIDS.svg": { + "a": 52, + "d": 318 + }, + "doc/_static/institution_logos/BU.svg": { + "a": 4, + "d": 1 + }, + "doc/_static/institution_logos/CHOP-dark.svg": { + "a": 10, + "d": 1 + }, + "doc/_static/institution_logos/CHOP.svg": { + "a": 12, + "d": 1 + }, + "doc/_static/institution_logos/Inserm-dark.svg": { + "a": 12, + "d": 46 + }, + "doc/_static/institution_logos/Inserm.svg": { + "a": 12, + "d": 46 + }, + "doc/_static/institution_logos/Julich-dark.svg": { + "a": 2, + "d": 54 + }, + "doc/_static/institution_logos/Julich.svg": { + "a": 2, + "d": 54 + }, + "doc/_static/institution_logos/MGH.svg": { + "a": 7, + "d": 18 + }, + "doc/_static/institution_logos/MIT.svg": { + "a": 6, + "d": 8 + }, + "doc/_static/institution_logos/MPIB-dark.svg": { + "a": 1, + "d": 3 + }, + "doc/_static/institution_logos/MPIB.svg": { + "a": 21, + "d": 3 + }, + "doc/_static/institution_logos/Macquarie.svg": { + "a": 1, + "d": 222 + }, + "doc/_static/institution_logos/NYU-dark.svg": { + "a": 11, + "d": 66 + }, + "doc/_static/institution_logos/NYU.svg": { + "a": 11, + "d": 66 + }, + "doc/_static/institution_logos/SWPS-dark.svg": { + "a": 25, + "d": 151 + }, + "doc/_static/institution_logos/SWPS.svg": { + "a": 25, + "d": 151 + }, + "doc/_static/institution_logos/Telecom_Paris_Tech.svg": { + "a": 11, + "d": 1 + }, + "doc/_static/institution_logos/Washington-dark.svg": { + "a": 2, + "d": 33 + }, + "doc/_static/institution_logos/Washington.svg": { + "a": 2, + "d": 33 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11053.json b/mne-python/source/doc/sphinxext/prs/11053.json new file mode 100644 index 0000000000000000000000000000000000000000..2fe3bd45a40ac0f044bfb0c83760af5d061f4c0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11053.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dd3d0f4d616f619993b3b4ef6b1afec66737704d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11056.json b/mne-python/source/doc/sphinxext/prs/11056.json new file mode 100644 index 0000000000000000000000000000000000000000..27c674ddd25a07395fe554dfde14609246aeb1f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11056.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e0df20d1dd9bdab5d44b76aeadc93c6e9731e4c1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11057.json b/mne-python/source/doc/sphinxext/prs/11057.json new file mode 100644 index 0000000000000000000000000000000000000000..c4df7b87fe957577c0775eff8c5eba8b4817f528 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11057.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "56543eda8f8739cc9e36de0b6eb95f93d756a39b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11059.json b/mne-python/source/doc/sphinxext/prs/11059.json new file mode 100644 index 0000000000000000000000000000000000000000..ebea3393b58a0de7ec5c3c401fb56f7e33dfc3c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11059.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "46262a369ea40ea658df7a5435ee9b7776517064", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 18, + "d": 22 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11060.json b/mne-python/source/doc/sphinxext/prs/11060.json new file mode 100644 index 0000000000000000000000000000000000000000..dfb6d07c66e4b00abd4603c7f227a697b979d578 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11060.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "eeefc2ed0aa39c10eab3bd1ef883c9cacb6f7b86", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/codeql-analysis.yml": { + "a": 72, + "d": 0 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 3 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11065.json b/mne-python/source/doc/sphinxext/prs/11065.json new file mode 100644 index 0000000000000000000000000000000000000000..6ca49585e2b84b2ba8d36706e12d516f69b59989 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11065.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e59fcf5002ce7839dcd608ffd2f0bee6857e11b1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11066.json b/mne-python/source/doc/sphinxext/prs/11066.json new file mode 100644 index 0000000000000000000000000000000000000000..c04d5bf6c405338e5798f1cb09d28e00a2926d1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11066.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c58e87556af8173aa72a4bb59dcc64b7a2b51e89", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/conf.py": { + "a": 8, + "d": 0 + }, + "mne/conftest.py": { + "a": 5, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11067.json b/mne-python/source/doc/sphinxext/prs/11067.json new file mode 100644 index 0000000000000000000000000000000000000000..531b51a93720182055897b817fce75f9e1ea3f62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11067.json @@ -0,0 +1,123 @@ +{ + "merge_commit_sha": "82a341076416bfbf3e62ae97e330ecfe9bedc1eb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 6 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/brain.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 4 + }, + "mne/fixes.py": { + "a": 11, + "d": 1 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 14, + "d": 14 + }, + "mne/utils/check.py": { + "a": 3, + "d": 11 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 14 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 7, + "d": 4 + }, + "mne/viz/_mpl_figure.py": { + "a": 5, + "d": 5 + }, + "mne/viz/backends/_utils.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/tests/test_abstract_notebook.py": { + "a": 4, + "d": 2 + }, + "mne/viz/circle.py": { + "a": 2, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 8, + "d": 16 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 9, + "d": 9 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 5, + "d": 5 + }, + "mne/viz/tests/test_raw.py": { + "a": 13, + "d": 7 + }, + "mne/viz/tests/test_topomap.py": { + "a": 7, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 74, + "d": 11 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 2 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11068.json b/mne-python/source/doc/sphinxext/prs/11068.json new file mode 100644 index 0000000000000000000000000000000000000000..8bf73b1fb862bf2164184908f317eaa23a422cea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11068.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "61b90ee2d555d10a6cb52dd5a6454d7d910a9166", + "authors": [ + { + "n": "Mats", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11069.json b/mne-python/source/doc/sphinxext/prs/11069.json new file mode 100644 index 0000000000000000000000000000000000000000..799c676045ea7faa93d2528fdd8fea7997bbd45b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11069.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "af925f4fd7f0274fe6bc642561af2abeb954289d", + "authors": [ + { + "n": "Chetan Gohil", + "e": "chetan.gohil@psych.ox.ac.uk" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11070.json b/mne-python/source/doc/sphinxext/prs/11070.json new file mode 100644 index 0000000000000000000000000000000000000000..a5f93e659e8715c7eef2eb655eed0633d65f58f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11070.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7ab69ab8ad6e90817d41b945e2b1e5daac26b8ff", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 43, + "d": 27 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 9, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11071.json b/mne-python/source/doc/sphinxext/prs/11071.json new file mode 100644 index 0000000000000000000000000000000000000000..4b17567d7ee9041801ad621d4124b07918dd2292 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11071.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "bb93462a5853dc1a6bd6f4ebfb3a9d8b9431e731", + "authors": [ + { + "n": "Andrew Quinn", + "e": "aquinn501@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 3, + "d": 0 + }, + "mne/dipole.py": { + "a": 3, + "d": 0 + }, + "mne/forward/_field_interpolation.py": { + "a": 10, + "d": 15 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 0 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 3, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11072.json b/mne-python/source/doc/sphinxext/prs/11072.json new file mode 100644 index 0000000000000000000000000000000000000000..80f9bccd0d85cc964502b8432adaf6a6537c3db9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11072.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ec85fe81b0f679f6ffad0611935e5fbfb98ad378", + "authors": [ + { + "n": "Chetan Gohil", + "e": "chetan.gohil@psych.ox.ac.uk" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/csd.py": { + "a": 6, + "d": 0 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 16, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11073.json b/mne-python/source/doc/sphinxext/prs/11073.json new file mode 100644 index 0000000000000000000000000000000000000000..c77b523794111442ba276ae87b4ffc7d96088ee4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11073.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6ff1ea387822a66759dc9a2b801661bb5347d3a0", + "authors": [ + { + "n": "Mats", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 6, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11074.json b/mne-python/source/doc/sphinxext/prs/11074.json new file mode 100644 index 0000000000000000000000000000000000000000..ae1572e7050f13cb36ef03b614daec19e7ea0829 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11074.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "86f38376a75fbe3d3e894eb4348b653e4340a6b3", + "authors": [ + { + "n": "Sebastiaan Mathot", + "e": "s.mathot@cogsci.nl" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 5, + "d": 7 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 18, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11075.json b/mne-python/source/doc/sphinxext/prs/11075.json new file mode 100644 index 0000000000000000000000000000000000000000..1ec467f9677ae22973486df542a3a81bbdaf11f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11075.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "1f19f5ba77c8b794f39701aeffcfdd88c1d1b070", + "authors": [ + { + "n": "Valerii", + "e": "vagechirkov@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 12, + "d": 0 + }, + "mne/html_templates/repr/evoked.html.jinja": { + "a": 29, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 0 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11076.json b/mne-python/source/doc/sphinxext/prs/11076.json new file mode 100644 index 0000000000000000000000000000000000000000..ef42e36b185806041254a453ca7309102c9b5ac6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11076.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4302ad01495a151e215bd5a0d6e221e2d79c0911", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/simulation/plot_stc_metrics.py": { + "a": 3, + "d": 6 + }, + "mne/simulation/metrics/metrics.py": { + "a": 38, + "d": 42 + }, + "mne/simulation/metrics/tests/test_metrics.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11077.json b/mne-python/source/doc/sphinxext/prs/11077.json new file mode 100644 index 0000000000000000000000000000000000000000..d4675ed4550301160ef329765f1861fa55975187 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11077.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5ee892f2ef79f451b7bdba251f4dec18e266001e", + "authors": [ + { + "n": "Andrew Quinn", + "e": "aquinn501@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11078.json b/mne-python/source/doc/sphinxext/prs/11078.json new file mode 100644 index 0000000000000000000000000000000000000000..96ea78c97de8ce3d90f6683e39fcbcb3ac08b5fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11078.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "f319107095d0ca09cc453ddc57815d9f7fd0ccfe", + "authors": [ + { + "n": "Quentin Barthélemy", + "e": "q.barthelemy@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 2 + }, + "mne/filter.py": { + "a": 55, + "d": 25 + }, + "mne/tests/test_filter.py": { + "a": 42, + "d": 11 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 5 + }, + "mne/viz/_figure.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11080.json b/mne-python/source/doc/sphinxext/prs/11080.json new file mode 100644 index 0000000000000000000000000000000000000000..42ca1596da62dd6b40000356f8138820c217cfac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11080.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bdc435d8a7643a934365a221ab9d52ec8b33bc33", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 8, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 11, + "d": 0 + }, + "mne/io/_digitization.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11081.json b/mne-python/source/doc/sphinxext/prs/11081.json new file mode 100644 index 0000000000000000000000000000000000000000..ab68ec918eff02f4fe73e2afef981f7b0dca888c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11081.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b53ed6ecc76b695a79850c9786e547b06fcc6c36", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 6, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11083.json b/mne-python/source/doc/sphinxext/prs/11083.json new file mode 100644 index 0000000000000000000000000000000000000000..10e4cfaf067bf3b4fc0900c9835fbf87b3588dc1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11083.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "08c8cad249e6e180096b0c8c3e9075ca6ae31bd6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "examples/inverse/psf_ctf_vertices.py": { + "a": 48, + "d": 5 + }, + "mne/conftest.py": { + "a": 11, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 16, + "d": 7 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 45, + "d": 56 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 3, + "d": 1 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 88, + "d": 60 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11084.json b/mne-python/source/doc/sphinxext/prs/11084.json new file mode 100644 index 0000000000000000000000000000000000000000..d39e9bc406df2d57cd128a75639611ff941cd7dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11084.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a0ca70901cd7105da03607e7155ae606e18ed195", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 2 + }, + "mne/gui/tests/test_coreg.py": { + "a": 11, + "d": 0 + }, + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11085.json b/mne-python/source/doc/sphinxext/prs/11085.json new file mode 100644 index 0000000000000000000000000000000000000000..599bec00bafaa4a9965bb4db3e2d049dcacb43cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11085.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "89fbad30af8065fbdbf8a0289f741fa5454330b6", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + } + ], + "changes": { + "examples/inverse/psf_ctf_vertices.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11086.json b/mne-python/source/doc/sphinxext/prs/11086.json new file mode 100644 index 0000000000000000000000000000000000000000..291a97442d6ca9bda18787b3ee12f0fefb7e57e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11086.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "bea8767a164bc43d02134bb7c9f063b1209a253c", + "authors": [ + { + "n": "luz paz", + "e": "luzpaz@pm.me" + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/documentation.md": { + "a": 1, + "d": 1 + }, + "Makefile": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 2, + "d": 2 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/data/FreeSurferColorLUT.txt": { + "a": 3, + "d": 3 + }, + "mne/filter.py": { + "a": 3, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 2, + "d": 2 + }, + "mne/report/js_and_css/report.js": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11090.json b/mne-python/source/doc/sphinxext/prs/11090.json new file mode 100644 index 0000000000000000000000000000000000000000..c43789fc687297f89eedcac3595e643a8b50c07e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11090.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "7aa3a27631b16fc9c16852c720e7243d876fe104", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/_includes/channel_types.rst": { + "a": 4, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 5 + }, + "mne/defaults.py": { + "a": 10, + "d": 6 + }, + "mne/io/constants.py": { + "a": 6, + "d": 2 + }, + "mne/io/pick.py": { + "a": 20, + "d": 9 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11094.json b/mne-python/source/doc/sphinxext/prs/11094.json new file mode 100644 index 0000000000000000000000000000000000000000..ec7f2dd09845bd711fb83b291033f3d64b1484b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11094.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4787bac9147902afefd608c235e8d983199b5bf3", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/interpolate.py": { + "a": 104, + "d": 22 + }, + "mne/preprocessing/tests/test_interpolate.py": { + "a": 104, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11095.json b/mne-python/source/doc/sphinxext/prs/11095.json new file mode 100644 index 0000000000000000000000000000000000000000..cc33803033b83ebdead7fc0da901740f7e9c556c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11095.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0faabfb093ebf4e03d8b6cbdb0b9418eeb090ff1", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/inverse.rst": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/__init__.py": { + "a": 4, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 89, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 48, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11096.json b/mne-python/source/doc/sphinxext/prs/11096.json new file mode 100644 index 0000000000000000000000000000000000000000..758bb77f2a1c04c66c753da74e9f691e8b26801b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11096.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "45d87fb0e5c34156c9568e04cd6ceef81140bed4", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/inverse.rst": { + "a": 1, + "d": 0 + }, + "examples/inverse/dics_epochs.py": { + "a": 119, + "d": 0 + }, + "mne/beamformer/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 73, + "d": 6 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 72, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11097.json b/mne-python/source/doc/sphinxext/prs/11097.json new file mode 100644 index 0000000000000000000000000000000000000000..dbedc29c857a849c900a4bfbb4a824ac4c25f674 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11097.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "02fce0bb67c9b00494ec3397bd18b5a81699ef7f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 87, + "d": 50 + }, + "mne/utils/tests/test_docs.py": { + "a": 48, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11099.json b/mne-python/source/doc/sphinxext/prs/11099.json new file mode 100644 index 0000000000000000000000000000000000000000..0912e47d3da363f829a5039fac7e64172b51d042 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11099.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6cebb1332a5e33c9a4e4d6999625a4cc585803e1", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 25, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11101.json b/mne-python/source/doc/sphinxext/prs/11101.json new file mode 100644 index 0000000000000000000000000000000000000000..47d321657622c99b418fc83b58c8868e15374761 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11101.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "a5acbec2c9c5a93a6ac2a06127068927858e6302", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/bug_report.md": { + "a": 0, + "d": 52 + }, + ".github/ISSUE_TEMPLATE/bug_report.yml": { + "a": 65, + "d": 0 + }, + ".github/ISSUE_TEMPLATE/config.yml": { + "a": 3, + "d": 3 + }, + ".github/ISSUE_TEMPLATE/documentation.md": { + "a": 0, + "d": 15 + }, + ".github/ISSUE_TEMPLATE/documentation.yml": { + "a": 26, + "d": 0 + }, + ".github/ISSUE_TEMPLATE/feature_request.md": { + "a": 0, + "d": 27 + }, + ".github/ISSUE_TEMPLATE/feature_request.yml": { + "a": 51, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11102.json b/mne-python/source/doc/sphinxext/prs/11102.json new file mode 100644 index 0000000000000000000000000000000000000000..4401b2968fa5bb7161a1f5597bfd8b21e92faf8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11102.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a02fa0a386a1feb770caaeaa91678b753ab8e48e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 29, + "d": 8 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 63, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11103.json b/mne-python/source/doc/sphinxext/prs/11103.json new file mode 100644 index 0000000000000000000000000000000000000000..7cf388f181d98e456d7a25f5097716577674a667 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11103.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "9555588cb1e0456ab91b016a69740e4db3bff5a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/dipole.py": { + "a": 58, + "d": 43 + }, + "mne/forward/_compute_forward.py": { + "a": 52, + "d": 159 + }, + "mne/forward/_make_forward.py": { + "a": 81, + "d": 120 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 5 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 62, + "d": 51 + }, + "mne/preprocessing/maxwell.py": { + "a": 3, + "d": 14 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 24, + "d": 18 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11104.json b/mne-python/source/doc/sphinxext/prs/11104.json new file mode 100644 index 0000000000000000000000000000000000000000..5ffcebab85e025ba853d310c553e9db49eb9511d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11104.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bc30e0e8c687cd91f75432df97e4f348ee8d73eb", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 0, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 0, + "d": 8 + }, + "mne/channels/tests/test_montage.py": { + "a": 0, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11105.json b/mne-python/source/doc/sphinxext/prs/11105.json new file mode 100644 index 0000000000000000000000000000000000000000..5e0d3b702323711f7e39dd6dcb142fdb59def365 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11105.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "532cfc5cee360dff6bad9cac7710c805aee9a347", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11108.json b/mne-python/source/doc/sphinxext/prs/11108.json new file mode 100644 index 0000000000000000000000000000000000000000..4a1c10f256703f08ed3b632b6d71ddcb32944001 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11108.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9385b96ad12c26e8f7d3b913b330eade4ee1365a", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 1 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1111.json b/mne-python/source/doc/sphinxext/prs/1111.json new file mode 100644 index 0000000000000000000000000000000000000000..b731e3878e477aaefb249acd894b0cab883b8d47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1111.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "78794f60f896cf2780902007b43ac191a4314a0c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 224, + "d": 68 + }, + "mne/tests/test_label.py": { + "a": 43, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11115.json b/mne-python/source/doc/sphinxext/prs/11115.json new file mode 100644 index 0000000000000000000000000000000000000000..50faf33416f612995dbe62a689f5c099066a591f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11115.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d587b89154cc398cacabc6e0d9b630c0aaf6e37a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/topo_customized.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/psd.py": { + "a": 8, + "d": 7 + }, + "tools/azure_dependencies.sh": { + "a": 3, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 1 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 13, + "d": 12 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11116.json b/mne-python/source/doc/sphinxext/prs/11116.json new file mode 100644 index 0000000000000000000000000000000000000000..290a76bb5623ebe59a70dde1890f787e8c56d250 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11116.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4310c92b85fa7dcc77ffe322501037e5ad82372d", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 77, + "d": 52 + }, + "mne/time_frequency/_stockwell.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11118.json b/mne-python/source/doc/sphinxext/prs/11118.json new file mode 100644 index 0000000000000000000000000000000000000000..914d423a8206afc3015dbfb3bcefbd79c4ea96f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11118.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2aceb47bb16698beebcff2118bdbf89abcaed3cc", + "authors": [ + { + "n": "jwelzel", + "e": null + } + ], + "changes": { + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11120.json b/mne-python/source/doc/sphinxext/prs/11120.json new file mode 100644 index 0000000000000000000000000000000000000000..09f91050573fbd176f593d5bdb988b5f0628823f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11120.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "db22d67b65b07dec07f3f65cbc52d8d146c8265b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 5, + "d": 5 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 4, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 13 + }, + "mne/utils/tests/test_docs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11121.json b/mne-python/source/doc/sphinxext/prs/11121.json new file mode 100644 index 0000000000000000000000000000000000000000..17b5f17b72428207911115e386cc2c8231e3c7e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11121.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "963453660fc3805a67b924646f4b88f57badcdaa", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/spectrum.py": { + "a": 4, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11122.json b/mne-python/source/doc/sphinxext/prs/11122.json new file mode 100644 index 0000000000000000000000000000000000000000..d828ffd54942db6fc03ff53662618d54507ce39c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11122.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2c356d6a4cb4fa33e6d1350fc9ec76446cc9162e", + "authors": [ + { + "n": "Eduard Ort", + "e": "eduardxort@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 37, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 31, + "d": 1 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 16, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11123.json b/mne-python/source/doc/sphinxext/prs/11123.json new file mode 100644 index 0000000000000000000000000000000000000000..fe84594524da76d3558ed709cb0a546bf6bf95eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11123.json @@ -0,0 +1,163 @@ +{ + "merge_commit_sha": "45720ccbae51927b4c7ceace3b89c7c294d21bab", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 7, + "d": 0 + }, + "examples/decoding/ems_filtering.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 4, + "d": 2 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/mne_cov_power.py": { + "a": 7, + "d": 4 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 4, + "d": 3 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/movement_compensation.py": { + "a": 9, + "d": 8 + }, + "examples/preprocessing/virtual_evoked.py": { + "a": 8, + "d": 7 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 10, + "d": 1 + }, + "examples/visualization/evoked_topomap.py": { + "a": 17, + "d": 21 + }, + "mne/cov.py": { + "a": 46, + "d": 27 + }, + "mne/evoked.py": { + "a": 13, + "d": 14 + }, + "mne/io/proj.py": { + "a": 103, + "d": 35 + }, + "mne/preprocessing/_regress.py": { + "a": 15, + "d": 8 + }, + "mne/preprocessing/ica.py": { + "a": 40, + "d": 35 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 76, + "d": 95 + }, + "mne/time_frequency/tfr.py": { + "a": 79, + "d": 104 + }, + "mne/utils/docs.py": { + "a": 133, + "d": 123 + }, + "mne/viz/_proj.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 5 + }, + "mne/viz/tests/test_topomap.py": { + "a": 126, + "d": 130 + }, + "mne/viz/topomap.py": { + "a": 554, + "d": 471 + }, + "mne/viz/utils.py": { + "a": 37, + "d": 0 + }, + "tutorials/epochs/15_baseline_regression.py": { + "a": 5, + "d": 3 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 2, + "d": 3 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 3, + "d": 3 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 1, + "d": 2 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 4, + "d": 2 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 3, + "d": 3 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 8, + "d": 13 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 3, + "d": 3 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 4, + "d": 2 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11124.json b/mne-python/source/doc/sphinxext/prs/11124.json new file mode 100644 index 0000000000000000000000000000000000000000..5f95cfbaa2d6f07cb06127f1d6fb942574a31db9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11124.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c58069137f800306ef8469b677530dbe14984429", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "tutorials/io/20_reading_eeg_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11125.json b/mne-python/source/doc/sphinxext/prs/11125.json new file mode 100644 index 0000000000000000000000000000000000000000..f9b3e1be9dfefe519c7a512fc3eadcdb0c0e45e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11125.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6b378e92f11a709e0cee12ac07d76d4bf8c55c5b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11126.json b/mne-python/source/doc/sphinxext/prs/11126.json new file mode 100644 index 0000000000000000000000000000000000000000..931e21e907490163222e2393f50844261bc4e1d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11126.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4fda0d849ec8bc10e3c6db18d9e4ba8dfdd1bb7e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/psf_ctf_vertices.py": { + "a": 5, + "d": 48 + }, + "examples/inverse/psf_volume.py": { + "a": 93, + "d": 0 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11127.json b/mne-python/source/doc/sphinxext/prs/11127.json new file mode 100644 index 0000000000000000000000000000000000000000..a159c0d30f5bbefc25d3282e05223f5f90a989c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11127.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "75ce3a0033f649deb8bc06e89a89ad031ee18092", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/backends/tests/test_abstract_notebook.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11129.json b/mne-python/source/doc/sphinxext/prs/11129.json new file mode 100644 index 0000000000000000000000000000000000000000..fd61723ea04a0b8c1728528c48d475459222305b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11129.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2a44a666cd5b3907fc816219697e17de83ef476e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11132.json b/mne-python/source/doc/sphinxext/prs/11132.json new file mode 100644 index 0000000000000000000000000000000000000000..9b2e5e25a738bec408f4d9841a1c68ae3cfa7033 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11132.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7db211bf5e906dfac7333315a49b1a2eb3b75067", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 4 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11134.json b/mne-python/source/doc/sphinxext/prs/11134.json new file mode 100644 index 0000000000000000000000000000000000000000..76cc2f65f4d47e7f8651aa0fc150cafee15a51e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11134.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aef49669fe1bdf19221e03e85cf961671508e0bb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11136.json b/mne-python/source/doc/sphinxext/prs/11136.json new file mode 100644 index 0000000000000000000000000000000000000000..477ed0dc1d47d8dd2a8f5b2d3d863a737abccced --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11136.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9e67f7ce9100bbac452b990541e8f36a072f098a", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/preprocessing/annotate_amplitude.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11139.json b/mne-python/source/doc/sphinxext/prs/11139.json new file mode 100644 index 0000000000000000000000000000000000000000..514decda381f1d261e7a92c7385ecd3f94f93105 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11139.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b8ba02fb74f63fef08f5386ea27a0f660342c99b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11140.json b/mne-python/source/doc/sphinxext/prs/11140.json new file mode 100644 index 0000000000000000000000000000000000000000..50a184db92d04ac7438a1c8f5aa74338cc8f6f48 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11140.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "cf235d539eb932013ea1fa5b78bc2dbf259e1c96", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 3, + "d": 3 + }, + "mne/io/kit/coreg.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11141.json b/mne-python/source/doc/sphinxext/prs/11141.json new file mode 100644 index 0000000000000000000000000000000000000000..db590df223e132c9de58eadf59ef64051851b849 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11141.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "333fd053af346e94d61732e10dca7356be5f3c51", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/html_templates/repr/ica.html.jinja": { + "a": 0, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 139, + "d": 10 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 89, + "d": 2 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 37, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11143.json b/mne-python/source/doc/sphinxext/prs/11143.json new file mode 100644 index 0000000000000000000000000000000000000000..ab0a48db17da294c7801efb03f5bd60f39871492 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11143.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "89e979b16add6944becba3ac750390a56518778b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 13, + "d": 9 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11144.json b/mne-python/source/doc/sphinxext/prs/11144.json new file mode 100644 index 0000000000000000000000000000000000000000..373bcd3f5e1ce5987fc6d1b7cb6879ba4e225dc8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11144.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "202a0d3b914de5816473970b381d2458a05866f2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/psf_volume.py": { + "a": 2, + "d": 1 + }, + "requirements_testing.txt": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11145.json b/mne-python/source/doc/sphinxext/prs/11145.json new file mode 100644 index 0000000000000000000000000000000000000000..3c7bf2f09dfb5936810010ec1cebfa71f681dc5b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11145.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e7326d63d224cd954966b4ee2c6322c0ff239305", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 22, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11146.json b/mne-python/source/doc/sphinxext/prs/11146.json new file mode 100644 index 0000000000000000000000000000000000000000..ffde1b6d831d9028c58035b431e8549ee5395283 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11146.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "8c3e6fb5ab0fdae3ce692d9ae9051f1c71bce37e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 3, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 3, + "d": 1 + }, + "mne/io/curry/curry.py": { + "a": 11, + "d": 12 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 13, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 1 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 3, + "d": 15 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 11, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 13, + "d": 1 + }, + "mne/io/utils.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11147.json b/mne-python/source/doc/sphinxext/prs/11147.json new file mode 100644 index 0000000000000000000000000000000000000000..2c3fad2af61021ad6d312880e11791cdf254996f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11147.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6df57c3d5995d281b21d84a31ab44c595a0dd74f", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 10, + "d": 1 + }, + "mne/io/tests/test_proj.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11148.json b/mne-python/source/doc/sphinxext/prs/11148.json new file mode 100644 index 0000000000000000000000000000000000000000..5cd0fedb0e82c7abf15bb840ff2b02e65fab5dd6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11148.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c87ed30fa8126a9ca8f47066cdd98cacbfb38e32", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 6, + "d": 11 + }, + "tools/github_actions_dependencies.sh": { + "a": 6, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1115.json b/mne-python/source/doc/sphinxext/prs/1115.json new file mode 100644 index 0000000000000000000000000000000000000000..467cb22abfae046c12aeb983b458768e5e28f267 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1115.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cbfa2c9ed2ebd972f5bd3eb0726105410546354e", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11150.json b/mne-python/source/doc/sphinxext/prs/11150.json new file mode 100644 index 0000000000000000000000000000000000000000..6d1ece44e98c70a5139e99dab0feaabb21433ca5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11150.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bc74d7d071f6aadc6ff42092ac64614649b2bd1f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11151.json b/mne-python/source/doc/sphinxext/prs/11151.json new file mode 100644 index 0000000000000000000000000000000000000000..97828812e00274232b19175060c3827a9b153d3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11151.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "880e883c06184160c30d50da06803e67977ac366", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 0, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 0, + "d": 2 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_proj.py": { + "a": 1, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 20 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 19, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11152.json b/mne-python/source/doc/sphinxext/prs/11152.json new file mode 100644 index 0000000000000000000000000000000000000000..f0aa3211584b4673658f2c304579ce4d5a03efec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11152.json @@ -0,0 +1,151 @@ +{ + "merge_commit_sha": "62af4ac642b21bc0b996c8c86fdeab417806f6d7", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "dominikwelke", + "e": "dominik.welke@web.de" + } + ], + "changes": { + "doc/_includes/data_formats.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/datasets.rst": { + "a": 2, + "d": 1 + }, + "doc/overview/datasets_index.rst": { + "a": 13, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 13, + "d": 0 + }, + "doc/reading_raw_data.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 12, + "d": 6 + }, + "mne/datasets/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/config.py": { + "a": 12, + "d": 3 + }, + "mne/datasets/eyelink/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/eyelink/eyelink.py": { + "a": 26, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 1 + }, + "mne/defaults.py": { + "a": 13, + "d": 6 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/constants.py": { + "a": 14, + "d": 1 + }, + "mne/io/eyelink/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/eyelink/eyelink.py": { + "a": 882, + "d": 0 + }, + "mne/io/eyelink/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 147, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/pick.py": { + "a": 50, + "d": 14 + }, + "mne/io/tests/test_constants.py": { + "a": 5, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/eyetracking/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 146, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 6, + "d": 4 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 4, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "tools/circleci_download.sh": { + "a": 3, + "d": 0 + }, + "tutorials/io/70_reading_eyetracking_data.py": { + "a": 172, + "d": 0 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 107, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11154.json b/mne-python/source/doc/sphinxext/prs/11154.json new file mode 100644 index 0000000000000000000000000000000000000000..b804f87ba5fa202087268c1e101b62fcf0522a3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11154.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b5b97f9a4ee3fe497efe0822fd190855e9a3359c", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 25, + "d": 16 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 47, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11155.json b/mne-python/source/doc/sphinxext/prs/11155.json new file mode 100644 index 0000000000000000000000000000000000000000..de54fc6030ab43b99020283ddac75c0deafb1955 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11155.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5059cc13cde5a5dd55640762602c54cd25ee4400", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11156.json b/mne-python/source/doc/sphinxext/prs/11156.json new file mode 100644 index 0000000000000000000000000000000000000000..9789cfd032d234f47f79943c49121d3ddcd809e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11156.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5cfb78063d52a5806eae88ffb14708af19552208", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11157.json b/mne-python/source/doc/sphinxext/prs/11157.json new file mode 100644 index 0000000000000000000000000000000000000000..223b79ca67744275a44ebbadd3728c71c2a02819 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11157.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "be6135a7f441581ae71cbe0403ee0b36774b8f69", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11159.json b/mne-python/source/doc/sphinxext/prs/11159.json new file mode 100644 index 0000000000000000000000000000000000000000..162f02c98ec839e1691e95c89b21d2961eb8d56c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11159.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "63b430e7f18ab4b49ae35b5ecc8564993647be62", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 2, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/utils/misc.py": { + "a": 29, + "d": 0 + }, + "mne/utils/tests/test_misc.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1116.json b/mne-python/source/doc/sphinxext/prs/1116.json new file mode 100644 index 0000000000000000000000000000000000000000..11c2847e225073d95c1a087ab959e5e856d99cb9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1116.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "23eaf5587881f57339b68dcd53fee38906ad7f3a", + "authors": [ + { + "n": "aestrivex", + "e": "aestrivex@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/viz.py": { + "a": 40, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11160.json b/mne-python/source/doc/sphinxext/prs/11160.json new file mode 100644 index 0000000000000000000000000000000000000000..2e01ceb5b1acdbf65437cffdd9b9d235470e0e0f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11160.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d74c0fa3922710a0ae58eb1d82b2b212a28889d5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 8, + "d": 5 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 14, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11163.json b/mne-python/source/doc/sphinxext/prs/11163.json new file mode 100644 index 0000000000000000000000000000000000000000..6667b3a20a3df9b3095099d10100814bc7bb2af6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11163.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "58a4b337697168020f8d72bdde3265897d4af61b", + "authors": [ + { + "n": "Eduard Ort", + "e": "eduardxort@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11166.json b/mne-python/source/doc/sphinxext/prs/11166.json new file mode 100644 index 0000000000000000000000000000000000000000..36967d56d654d869e6100b2e7bba82ac5e3d7318 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11166.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "da3823f906f871bda7b133778a99c800496e7963", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/logging.rst": { + "a": 1, + "d": 0 + }, + "mne/parallel.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 140, + "d": 84 + }, + "mne/utils/tests/test_config.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11169.json b/mne-python/source/doc/sphinxext/prs/11169.json new file mode 100644 index 0000000000000000000000000000000000000000..c6172ff2cff2942511d53e5630a936fe1a2ff780 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11169.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "72ba75d7d65db6c23b73ffdd4b38eee113d668c9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "requirements_doc.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11171.json b/mne-python/source/doc/sphinxext/prs/11171.json new file mode 100644 index 0000000000000000000000000000000000000000..511c6e6521ec6af001c30c1df43aa3b2a1e343bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11171.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7e229ed7f709d5345481548b186f832572536caa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/source_space.py": { + "a": 50, + "d": 7 + }, + "mne/tests/test_source_space.py": { + "a": 33, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11175.json b/mne-python/source/doc/sphinxext/prs/11175.json new file mode 100644 index 0000000000000000000000000000000000000000..129f71bfd88df85cfaa79e9fbf98cf20ea473915 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11175.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1f19c0fcf89d2cfa6b2702c9d9f5a485797d4ec6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/inverse/label_activation_from_stc.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 9, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11176.json b/mne-python/source/doc/sphinxext/prs/11176.json new file mode 100644 index 0000000000000000000000000000000000000000..b420e9fe780378bb6d8de905c05ddab49dd566c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11176.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8ea5400fe42cb6c91ab3755ccd909f146f679294", + "authors": [ + { + "n": "Eduard Ort", + "e": "eduardxort@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_chpi.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11178.json b/mne-python/source/doc/sphinxext/prs/11178.json new file mode 100644 index 0000000000000000000000000000000000000000..7f587797abad62dc253a569d11119bc3c76532e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11178.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ea08b8a73a4f03f6bf0e99c0c2ee33bb279aff81", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/spectrum.py": { + "a": 16, + "d": 11 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 24, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11179.json b/mne-python/source/doc/sphinxext/prs/11179.json new file mode 100644 index 0000000000000000000000000000000000000000..bdfc21228cc0a89108dfebd678e8aebf8bfcfcae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11179.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a4cd082024dab16d277ff116959b16b7a5e73dc8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/simulation/70_point_spread.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1118.json b/mne-python/source/doc/sphinxext/prs/1118.json new file mode 100644 index 0000000000000000000000000000000000000000..855a96e9ff7d49d97fb5fa9f283ec32b4f2db960 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1118.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8ac2a2389a3cee9d2632eb7ab7a095c0d6e720b7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/fiff/tests/data/small-src.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/source_space.py": { + "a": 44, + "d": 5 + }, + "mne/surface.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_source_space.py": { + "a": 85, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11180.json b/mne-python/source/doc/sphinxext/prs/11180.json new file mode 100644 index 0000000000000000000000000000000000000000..30b15cf987b004b25bea116286dc88b9d3c5f932 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11180.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "d5645aa0907faf06f7ef1d64699e9d91a74ad97d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/events.rst": { + "a": 0, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 3 + }, + "mne/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 59 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_docs.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11181.json b/mne-python/source/doc/sphinxext/prs/11181.json new file mode 100644 index 0000000000000000000000000000000000000000..ff1c3e371c7e0b4338376d008c9652e744ca955a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11181.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "706aea1eb723801c43ae5fc5f68bbb7b53184c29", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 11, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11182.json b/mne-python/source/doc/sphinxext/prs/11182.json new file mode 100644 index 0000000000000000000000000000000000000000..4f0ef7795f8f958b82acee35dca7bfcbc72a9c22 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11182.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "38dd35fded0e09bc1488534cbd35f81f5fa6688d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 22, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11183.json b/mne-python/source/doc/sphinxext/prs/11183.json new file mode 100644 index 0000000000000000000000000000000000000000..4514cc6c268ffbdc7160eb0f5f92119b1860061d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11183.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "53b8667bdb142e1055a18375bd4d79e23d9f2733", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 8, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11185.json b/mne-python/source/doc/sphinxext/prs/11185.json new file mode 100644 index 0000000000000000000000000000000000000000..11564863f99828b809d41625820f37800015afd6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11185.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0fcbae2d4bc556e44bce02b3169e5bd73371806c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/_freesurfer.py": { + "a": 36, + "d": 9 + }, + "mne/coreg.py": { + "a": 2, + "d": 6 + }, + "mne/dipole.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11186.json b/mne-python/source/doc/sphinxext/prs/11186.json new file mode 100644 index 0000000000000000000000000000000000000000..0392fcb968adcaa44dfd1edfba2ded8897891b45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11186.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "f76d8c14181f77363fb7e04c5e0291b68cab79a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/hitachi/hitachi.py": { + "a": 65, + "d": 22 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 40, + "d": 12 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11187.json b/mne-python/source/doc/sphinxext/prs/11187.json new file mode 100644 index 0000000000000000000000000000000000000000..6f9c324ebfef477584c09ae9ee9e4573c1ee1b8f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11187.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5aa12b6555993b3cdc958bcf594d74dae6bfdf04", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1119.json b/mne-python/source/doc/sphinxext/prs/1119.json new file mode 100644 index 0000000000000000000000000000000000000000..ba0dc96362efaa20a54d3246e64704c88690bbe4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1119.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "830e82e7f3fe05f98c0cbef6be48ee98b758c6cf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11190.json b/mne-python/source/doc/sphinxext/prs/11190.json new file mode 100644 index 0000000000000000000000000000000000000000..e22a060a2cce368c7855340ffb8c098133381ee3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11190.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "240df830bda18dc630f9bffea386ded3bd247ace", + "authors": [ + { + "n": "Dominik Wetzel", + "e": null + }, + { + "n": "Dominik Wetzel", + "e": "dominik.wetzel@fh-zwickau.de" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 2 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/fixes.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11191.json b/mne-python/source/doc/sphinxext/prs/11191.json new file mode 100644 index 0000000000000000000000000000000000000000..48a109e187ec914874a2bf5065b12c774bdb015b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11191.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "3032f48bec92a2ec12f9b36682070e99a72428bb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + ".github/workflows/linux_pip.yml": { + "a": 4, + "d": 3 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 29, + "d": 10 + }, + "mne/time_frequency/spectrum.py": { + "a": 4, + "d": 3 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 4, + "d": 1 + }, + "tools/check_qt_import.sh": { + "a": 8, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11192.json b/mne-python/source/doc/sphinxext/prs/11192.json new file mode 100644 index 0000000000000000000000000000000000000000..816de2bf9c2171773c201dfce206869cfa546df9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11192.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7730df72dc51f663fe557e997b6f5486111f3e43", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 2, + "d": 2 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11193.json b/mne-python/source/doc/sphinxext/prs/11193.json new file mode 100644 index 0000000000000000000000000000000000000000..6f5b9465c775afe6122f034bde556c3029192081 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11193.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "3a28322b3f8301b1486e080e024f115feeadfeca", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 7, + "d": 5 + }, + "mne/chpi.py": { + "a": 10, + "d": 8 + }, + "mne/cov.py": { + "a": 7, + "d": 5 + }, + "mne/dipole.py": { + "a": 5, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 5 + }, + "mne/report/report.py": { + "a": 19, + "d": 17 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 13, + "d": 6 + }, + "mne/utils/check.py": { + "a": 4, + "d": 2 + }, + "mne/utils/tests/test_check.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11197.json b/mne-python/source/doc/sphinxext/prs/11197.json new file mode 100644 index 0000000000000000000000000000000000000000..5df658c3ab0178e66a217ecb80beeb3a082d854d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11197.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a40ce20e12c7fb84315172bd6a9e44915a9f811b", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11198.json b/mne-python/source/doc/sphinxext/prs/11198.json new file mode 100644 index 0000000000000000000000000000000000000000..3da0d55f1d7a5188ce19ef014cb1dcbbc4d8fee9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11198.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dcb6230cc4066ea993479caaf56944d59b90b770", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/spectrum.py": { + "a": 43, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 9, + "d": 0 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 23, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11199.json b/mne-python/source/doc/sphinxext/prs/11199.json new file mode 100644 index 0000000000000000000000000000000000000000..f2d0b319fff17e012d5b4eb6db4878a91b5e6c8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11199.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1b3e7d5013dcce1abd6b884a2b39f756ac7b7694", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/datasets/brainstorm_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11200.json b/mne-python/source/doc/sphinxext/prs/11200.json new file mode 100644 index 0000000000000000000000000000000000000000..fbedba32272f995d114c3394fde3cda2686fa770 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11200.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b6e4f5ca04fd432fce6241f091947d37e890346a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/macos_conda.yml": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 8, + "d": 6 + }, + "mne/viz/backends/renderer.py": { + "a": 8, + "d": 3 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 29, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11201.json b/mne-python/source/doc/sphinxext/prs/11201.json new file mode 100644 index 0000000000000000000000000000000000000000..aac13c7dd06891051ea47bb1b5d406a460ac211d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11201.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "4a445507e6108bcd0477190d7c277d0a904dcb34", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Hüseyin", + "e": "huseyinorkunelmas@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_proj.py": { + "a": 2, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 30, + "d": 11 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 10, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11203.json b/mne-python/source/doc/sphinxext/prs/11203.json new file mode 100644 index 0000000000000000000000000000000000000000..aa57053e0d8dfc5969ea91fb758217ba840d3dc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11203.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4427adfb3bfe9d876ccbbed7fcffb625e6b3bce3", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11204.json b/mne-python/source/doc/sphinxext/prs/11204.json new file mode 100644 index 0000000000000000000000000000000000000000..8f50472431a654ec92dafc4a614404624ce55e63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11204.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "de546e2188761de69eede103b7c5a6cc09542a4d", + "authors": [ + { + "n": "gemeinl", + "e": "lukas.gemein@gmx.de" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11205.json b/mne-python/source/doc/sphinxext/prs/11205.json new file mode 100644 index 0000000000000000000000000000000000000000..1f0a1ab52e776e549a08791927534ae85cdc7a11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11205.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "35e466f3fbb71cc7b976ae1a88b97409adabf694", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "doc/references.bib": { + "a": 1, + "d": 2 + }, + "mne/conftest.py": { + "a": 5, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_lead_dots.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/res4.py": { + "a": 1, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 13, + "d": 1 + }, + "mne/viz/tests/test_scraper.py": { + "a": 2, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 0 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 2, + "d": 2 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 2, + "d": 2 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 0, + "d": 5 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11206.json b/mne-python/source/doc/sphinxext/prs/11206.json new file mode 100644 index 0000000000000000000000000000000000000000..dc79b275fe42466ed7676d701e3b4de6179cc20a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11206.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a8980714127579192e3b4b2ebcc2c51be824d053", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 7, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11207.json b/mne-python/source/doc/sphinxext/prs/11207.json new file mode 100644 index 0000000000000000000000000000000000000000..a0fb66242378b57babc9e11bff8ef95cbbc5d3e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11207.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e10b1dae11867cb15e63c783318995d0099979cd", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/glossary.rst": { + "a": 0, + "d": 7 + }, + "mne/time_frequency/multitaper.py": { + "a": 8, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 6, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 10, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11209.json b/mne-python/source/doc/sphinxext/prs/11209.json new file mode 100644 index 0000000000000000000000000000000000000000..d925307bb34f00d4367bb3ff23ee2eac69ce0d2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11209.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "2b3f339aed81f7990caeb1313e0c6341a15546ec", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".cirrus.yml": { + "a": 41, + "d": 0 + }, + "README.rst": { + "a": 4, + "d": 1 + }, + "mne/conftest.py": { + "a": 3, + "d": 0 + }, + "mne/gui/tests/test_core.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tools/cirrus_dependencies.sh": { + "a": 5, + "d": 0 + }, + "tools/cirrus_install_python.sh": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1121.json b/mne-python/source/doc/sphinxext/prs/1121.json new file mode 100644 index 0000000000000000000000000000000000000000..73e35d58e1d6738d755191cb8981680b104d5d66 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1121.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d318be39e562e85c83ed071b443f9c1f3ef982df", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/inverse/plot_dics_source_power.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11211.json b/mne-python/source/doc/sphinxext/prs/11211.json new file mode 100644 index 0000000000000000000000000000000000000000..960663aa8b4f4c00f7ce40ba2d45ab60a797709c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11211.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b486ef18f74d22b7bdcd0cf6f0e1a8fb988d5e35", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".cirrus.yml": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11212.json b/mne-python/source/doc/sphinxext/prs/11212.json new file mode 100644 index 0000000000000000000000000000000000000000..4de233c5cf5a86b9124ce402d1bbc1fe81a3c272 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11212.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "ac7cab31cd028df88bc925fe6ef68fea4403756b", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "mne/bem.py": { + "a": 10, + "d": 4 + }, + "mne/channels/montage.py": { + "a": 43, + "d": 12 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/io/_digitization.py": { + "a": 44, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 3, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 4, + "d": 1 + }, + "mne/io/curry/curry.py": { + "a": 2, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 4, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 6, + "d": 5 + }, + "mne/io/fieldtrip/utils.py": { + "a": 3, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 8, + "d": 1 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 0 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 10, + "d": 0 + }, + "mne/io/proj.py": { + "a": 3, + "d": 5 + }, + "mne/io/reference.py": { + "a": 4, + "d": 3 + }, + "mne/io/snirf/_snirf.py": { + "a": 6, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 29, + "d": 8 + }, + "mne/io/tests/test_reference.py": { + "a": 4, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 6, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + }, + "mne/viz/backends/_utils.py": { + "a": 10, + "d": 7 + }, + "setup.cfg": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11213.json b/mne-python/source/doc/sphinxext/prs/11213.json new file mode 100644 index 0000000000000000000000000000000000000000..ed9c1dbb188b9c2654f7eff1341469c7a020e71c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11213.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bfc2525b60b6dee59628a8d80c56d394586dc02d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/datasets/tests/test_datasets.py": { + "a": 5, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 49, + "d": 0 + }, + "mne/utils/config.py": { + "a": 4, + "d": 1 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11215.json b/mne-python/source/doc/sphinxext/prs/11215.json new file mode 100644 index 0000000000000000000000000000000000000000..3a2c1ba447dae708e1dea7ce1edaa9d7ecb7cab8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11215.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "880ec67a02ed59273d4b442ea46a118387a8dc03", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 3, + "d": 2 + }, + "mne/fixes.py": { + "a": 0, + "d": 20 + }, + "mne/io/what.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 11, + "d": 9 + }, + "mne/tests/test_cov.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_morph.py": { + "a": 2, + "d": 2 + }, + "mne/utils/dataframe.py": { + "a": 3, + "d": 2 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11216.json b/mne-python/source/doc/sphinxext/prs/11216.json new file mode 100644 index 0000000000000000000000000000000000000000..c5af628d7058148cac4de6f9902d93f19c4112bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11216.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "71271588e7d7fd3e165ad158571f40085eaa05e0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/overview/people.rst": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11219.json b/mne-python/source/doc/sphinxext/prs/11219.json new file mode 100644 index 0000000000000000000000000000000000000000..58451e4839488f951645babec9c6d7e705991ef1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11219.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "db0d02b72fc5246f3b5e8bd6a8d713b2801aa31b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/utils/misc.py": { + "a": 30, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1122.json b/mne-python/source/doc/sphinxext/prs/1122.json new file mode 100644 index 0000000000000000000000000000000000000000..73e963dcb0a05dab77720f22582907ffab70923b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1122.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "64823209bdf74668bb7a318d1aa549791c6f630f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/_field_interpolation.py": { + "a": 4, + "d": 5 + }, + "mne/viz.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11222.json b/mne-python/source/doc/sphinxext/prs/11222.json new file mode 100644 index 0000000000000000000000000000000000000000..d14b71b4e7316a2b4eb04a47f5012b74e043db2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11222.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6a5c031a01a4aadabd4d178a376952390bf4a3df", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11223.json b/mne-python/source/doc/sphinxext/prs/11223.json new file mode 100644 index 0000000000000000000000000000000000000000..13ff5510b8bc2f6198da16dc7249ce72436cc9c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11223.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4aed3f7257d04e51b4cd84ddf56e5ef755acdd84", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 34, + "d": 9 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11228.json b/mne-python/source/doc/sphinxext/prs/11228.json new file mode 100644 index 0000000000000000000000000000000000000000..5350dd78ba08afed16b4e604cfb9dc64754a3d41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11228.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "8a73a59beef4f896ef7f3c6ce4baede80f3ba7a6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/README.txt": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 4, + "d": 3 + }, + "mne/dipole.py": { + "a": 8, + "d": 4 + }, + "mne/epochs.py": { + "a": 10, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 15, + "d": 13 + }, + "mne/morph.py": { + "a": 9, + "d": 2 + }, + "mne/viz/backends/_abstract.py": { + "a": 7, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11229.json b/mne-python/source/doc/sphinxext/prs/11229.json new file mode 100644 index 0000000000000000000000000000000000000000..575252225cec5008eb752452149ba13efd72cac0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11229.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "20ebcaa85d01b1887aff54d2fe69ab8803151a7d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11230.json b/mne-python/source/doc/sphinxext/prs/11230.json new file mode 100644 index 0000000000000000000000000000000000000000..4e19fd0ead3b9d3975a9d74808e2a5bde315a82f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11230.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8bd94067676bb2f5bb158e6f2f2c3d24f7e66040", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/misc.py": { + "a": 14, + "d": 12 + }, + "mne/utils/tests/test_misc.py": { + "a": 34, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11231.json b/mne-python/source/doc/sphinxext/prs/11231.json new file mode 100644 index 0000000000000000000000000000000000000000..4e15b4d8fca308d5c121d5df8f639dcaba1e5156 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11231.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a373946084376800a95ce333fa984a8311a6bca", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11232.json b/mne-python/source/doc/sphinxext/prs/11232.json new file mode 100644 index 0000000000000000000000000000000000000000..20c3e3aa007445142b381d30a26cbc747a33a8e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11232.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0a0e00f6d9c3ebadd72451f4b7df68eeafb7fcd6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 24, + "d": 9 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 8, + "d": 1 + }, + "mne/utils/check.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11234.json b/mne-python/source/doc/sphinxext/prs/11234.json new file mode 100644 index 0000000000000000000000000000000000000000..fdd34b1bf9eb728973e0eb8e8ab5e5dfb1dd9e81 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11234.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "ff1cfdd8e3ac3c05bfd5987a3e821f13cf7928f9", + "authors": [ + { + "n": "Velu Prabhakar Kumaravel", + "e": null + }, + { + "n": "Velu Prabhakar Kumaravel", + "e": "veluprabhakarkumaravel@Velus-MBP.lan" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/api/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/11234.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 31, + "d": 0 + }, + "mne/preprocessing/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/_lof.py": { + "a": 100, + "d": 0 + }, + "mne/preprocessing/tests/test_lof.py": { + "a": 39, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11235.json b/mne-python/source/doc/sphinxext/prs/11235.json new file mode 100644 index 0000000000000000000000000000000000000000..f99cf206013d782ff2c699fc610cc8fda883f644 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11235.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1dd1fa1296480317be3d75fb84c915e5eaacef9e", + "authors": [ + { + "n": "Daniel Hasegan", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11236.json b/mne-python/source/doc/sphinxext/prs/11236.json new file mode 100644 index 0000000000000000000000000000000000000000..c45398745451855f66904994572154689b1cc6d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11236.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "b9628c09599eca74feb13b9ef75aba2eee1801bb", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".mailmap": { + "a": 8, + "d": 0 + }, + "CITATION.cff": { + "a": 42, + "d": 19 + }, + "SECURITY.md": { + "a": 3, + "d": 3 + }, + "codemeta.json": { + "a": 120, + "d": 48 + }, + "doc/_static/versions.json": { + "a": 6, + "d": 2 + }, + "doc/changes/1.2.inc": { + "a": 37, + "d": 3 + }, + "doc/cited.rst": { + "a": 3, + "d": 3 + }, + "doc/conf.py": { + "a": 9, + "d": 12 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/_version.py": { + "a": 1, + "d": 1 + }, + "requirements_doc.txt": { + "a": 2, + "d": 2 + }, + "tools/circleci_download.sh": { + "a": 1, + "d": 1 + }, + "tools/generate_codemeta.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11237.json b/mne-python/source/doc/sphinxext/prs/11237.json new file mode 100644 index 0000000000000000000000000000000000000000..3785f329fe5abd245c473b2a98e1072375ee11b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11237.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2482b52f26a2d36d98b42c8accc91e3608276bb6", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/csd.py": { + "a": 6, + "d": 29 + }, + "mne/time_frequency/multitaper.py": { + "a": 11, + "d": 7 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 12, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11238.json b/mne-python/source/doc/sphinxext/prs/11238.json new file mode 100644 index 0000000000000000000000000000000000000000..9216d0622f942d1464e31eba6cfcc37096b86dac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11238.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1a7d120ae41d22bb73b32c0b65a0598e1ebd03b3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1124.json b/mne-python/source/doc/sphinxext/prs/1124.json new file mode 100644 index 0000000000000000000000000000000000000000..16b3e21e8cbe5cb43554e362bf45159ad0fe7c04 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1124.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "eb6cb0d2ecc05091b139db27718998f51741f190", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/channels.py": { + "a": 63, + "d": 0 + }, + "mne/fiff/tests/test_channels.py": { + "a": 66, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11241.json b/mne-python/source/doc/sphinxext/prs/11241.json new file mode 100644 index 0000000000000000000000000000000000000000..a7f8f5e0916bf78882f5f6671ecd93f9eeec5a86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11241.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "62e88db6d04df32a248073e5d204a88bab6cb2cf", + "authors": [ + { + "n": "Jevri Hanna", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 5, + "d": 10 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11244.json b/mne-python/source/doc/sphinxext/prs/11244.json new file mode 100644 index 0000000000000000000000000000000000000000..0b1d4503c97207df0db01a87497391dd49e7a55c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11244.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3c73d042288c564ac1ed3499a5724a349e91e207", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 14, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 16, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11245.json b/mne-python/source/doc/sphinxext/prs/11245.json new file mode 100644 index 0000000000000000000000000000000000000000..ada4fdc051a9f1f52f9b879be16c30326a4a8d7d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11245.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "27df81a1c95c402403fc11ca7e391c8eb388ef16", + "authors": [ + { + "n": "Moritz Gerster", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 10, + "d": 0 + }, + "mne/io/reference.py": { + "a": 21, + "d": 2 + }, + "mne/io/tests/test_reference.py": { + "a": 28, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11246.json b/mne-python/source/doc/sphinxext/prs/11246.json new file mode 100644 index 0000000000000000000000000000000000000000..42599de28f4ed3238ff1095ade760fe5852a1ab1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11246.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9eedef0abc44ab4dfe7e6d23580170ca705e9240", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11248.json b/mne-python/source/doc/sphinxext/prs/11248.json new file mode 100644 index 0000000000000000000000000000000000000000..f6f9749cbf17f544d928b7a8527a00634f09a2d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11248.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "98a0dfcc74983f94ff5c59dcfdee40443ee0386b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/spectrum.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11249.json b/mne-python/source/doc/sphinxext/prs/11249.json new file mode 100644 index 0000000000000000000000000000000000000000..0322ba9154c132a3de72d86e3b7aa7516c50ef5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11249.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "689f88ba3a395a424b62973ed063c6ea95aceafa", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/references.bib": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1125.json b/mne-python/source/doc/sphinxext/prs/1125.json new file mode 100644 index 0000000000000000000000000000000000000000..ca04753c9aa40774b127e2d83c4c9426ca5d933f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1125.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "406a8cf31f73e266494b924b845aaeb102892089", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11250.json b/mne-python/source/doc/sphinxext/prs/11250.json new file mode 100644 index 0000000000000000000000000000000000000000..9356f0d9fa0296c51b85c1e745acd58e04fda7b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11250.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3d13746dc3d08b1eff073dab5c119812de4d42ee", + "authors": [ + { + "n": "Omer Shubi", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11251.json b/mne-python/source/doc/sphinxext/prs/11251.json new file mode 100644 index 0000000000000000000000000000000000000000..acce54fce33e351b58425b791d8e842a623588ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11251.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fcfb565bdf253ca2a20e1c43d622752160def656", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 2, + "d": 1 + }, + "Makefile": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11253.json b/mne-python/source/doc/sphinxext/prs/11253.json new file mode 100644 index 0000000000000000000000000000000000000000..0c52dc5f0c96342928e3d162735e1e78b7157498 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11253.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4957469534ed5f8a4434df8a31d7033ce0560a36", + "authors": [ + { + "n": "Dinara Issagaliyeva", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11255.json b/mne-python/source/doc/sphinxext/prs/11255.json new file mode 100644 index 0000000000000000000000000000000000000000..1c7563e2af79116a5a16660b8cef035574e04e3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11255.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "83db99f7ae2bde0e96412e7e33cffdb6b23b6152", + "authors": [ + { + "n": null, + "e": "myd7349@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11256.json b/mne-python/source/doc/sphinxext/prs/11256.json new file mode 100644 index 0000000000000000000000000000000000000000..faa7898537306bbd7be059f850bc7142d69c5432 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11256.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "792b398ef25564192db22cfa8dd4ca9f9b139e0d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "tools/circleci_download.sh": { + "a": 3, + "d": 1 + }, + "tools/get_minimal_commands.sh": { + "a": 3, + "d": 1 + }, + "tools/get_testing_version.sh": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11259.json b/mne-python/source/doc/sphinxext/prs/11259.json new file mode 100644 index 0000000000000000000000000000000000000000..d5cbb2dbae794a552a60ed8e634208bba5357efa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11259.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3b29980d22becbf8bfa1c535f6e5680ad4bc749a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 0 + }, + "mne/evoked.py": { + "a": 4, + "d": 0 + }, + "mne/io/base.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1126.json b/mne-python/source/doc/sphinxext/prs/1126.json new file mode 100644 index 0000000000000000000000000000000000000000..a6fb8fba551daf221972a46ac53621d673c45c7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1126.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "390a9483e98678e60f0ff8fc63b0f620e2b3c856", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 4, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 4, + "d": 5 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 7, + "d": 2 + }, + "mne/label.py": { + "a": 209, + "d": 72 + }, + "mne/tests/test_label.py": { + "a": 71, + "d": 56 + }, + "mne/tests/test_source_estimate.py": { + "a": 8, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11260.json b/mne-python/source/doc/sphinxext/prs/11260.json new file mode 100644 index 0000000000000000000000000000000000000000..c0459b1a80d1e9995a64f3c075f2599e80c289ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11260.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "85dfacbab79e9b802a7d91ce981bbb57b673ae49", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".mailmap": { + "a": 2, + "d": 0 + }, + "doc/changes/0.18.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.19.inc": { + "a": 3, + "d": 3 + }, + "doc/changes/names.inc": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11261.json b/mne-python/source/doc/sphinxext/prs/11261.json new file mode 100644 index 0000000000000000000000000000000000000000..d6d20f8b6802cc015f077eff2edf39773e4e8fdd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11261.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "907e8dbb18a67d6961cffbe63ff94dbe8dbc6ab2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11263.json b/mne-python/source/doc/sphinxext/prs/11263.json new file mode 100644 index 0000000000000000000000000000000000000000..3ea067e270391f375cd53f3f62b72d02494f2eed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11263.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a49995ed5b1e84ab74a6dd1882f115d8dfd10406", + "authors": [ + { + "n": "Carlos de la Torre", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/mixin.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11265.json b/mne-python/source/doc/sphinxext/prs/11265.json new file mode 100644 index 0000000000000000000000000000000000000000..ee2778c14f8173dc93287a1a2feae8563e595bd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11265.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bcf13b13e5388dea3b6885ac2c6e1f3f7437a463", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/time_frequency/multitaper.py": { + "a": 40, + "d": 47 + }, + "mne/time_frequency/psd.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 46, + "d": 73 + }, + "mne/utils/docs.py": { + "a": 104, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11266.json b/mne-python/source/doc/sphinxext/prs/11266.json new file mode 100644 index 0000000000000000000000000000000000000000..e4688e36428a87bd7b8f747df0784eeec792f5b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11266.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "80f93b302611033537bdd266c27fd7f99e63df83", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/utils/misc.py": { + "a": 23, + "d": 16 + }, + "mne/utils/tests/test_misc.py": { + "a": 83, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11270.json b/mne-python/source/doc/sphinxext/prs/11270.json new file mode 100644 index 0000000000000000000000000000000000000000..8e3293292ab5601dfcb1e4ee98c13160b5953ecd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11270.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f82c74ab5ee4bf6c32a39c282ab70a474340ca74", + "authors": [ + { + "n": "Carlos de la Torre", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11271.json b/mne-python/source/doc/sphinxext/prs/11271.json new file mode 100644 index 0000000000000000000000000000000000000000..6f31e576a6e2d9d7358b117012f3412f87bf0ec6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11271.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a46755782fa351bf9002be35b4c669ee01a019ff", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 15, + "d": 2 + }, + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 17, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11272.json b/mne-python/source/doc/sphinxext/prs/11272.json new file mode 100644 index 0000000000000000000000000000000000000000..0ac5088da47af25d084373cc1959950d3eac36c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11272.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7efe0b14d82be746799a99de4bb7b64c7ba1b644", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/installers.rst": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11273.json b/mne-python/source/doc/sphinxext/prs/11273.json new file mode 100644 index 0000000000000000000000000000000000000000..bfd23473f8df2fd1ff62732f710b84c4854d6191 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11273.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b1d62431845a897d113dd7c077207d5ec41d1e0c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/autosummary/class.rst": { + "a": 1, + "d": 1 + }, + "doc/_templates/autosummary/class_no_inherited_members.rst": { + "a": 1, + "d": 1 + }, + "doc/_templates/autosummary/class_no_members.rst": { + "a": 8, + "d": 0 + }, + "doc/_templates/autosummary/function.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "doc/file_io.rst": { + "a": 1, + "d": 0 + }, + "doc/reading_raw_data.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11277.json b/mne-python/source/doc/sphinxext/prs/11277.json new file mode 100644 index 0000000000000000000000000000000000000000..67a3d4cca8622c3ee39ecebfcced6eb449af90c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11277.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fcf2770e98532c1bae7d3193087b82999a64a8e4", + "authors": [ + { + "n": null, + "e": "erkkahe@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 8, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11279.json b/mne-python/source/doc/sphinxext/prs/11279.json new file mode 100644 index 0000000000000000000000000000000000000000..960214e5f69bc1c2ca98a7c405002870e63e93be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11279.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5b71e261d1a85c06265a78dd5084de4b3ef86962", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 14, + "d": 7 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1128.json b/mne-python/source/doc/sphinxext/prs/1128.json new file mode 100644 index 0000000000000000000000000000000000000000..214ab1d2db5cd5bdf01c6594c4f347ec682eb4e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1128.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2a0814f7ce4f6f50b2410e170a49a30d1214b0b8", + "authors": [ + { + "n": "Mads Jensen", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 25, + "d": 12 + }, + "mne/tests/test_source_estimate.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11280.json b/mne-python/source/doc/sphinxext/prs/11280.json new file mode 100644 index 0000000000000000000000000000000000000000..90997ca82700d74c5a8e6c3beeb73dd64b8b299b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11280.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cee4e7d11116bd4e0e219fe611c0121cafd2394d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/tests/test_spectrum.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11281.json b/mne-python/source/doc/sphinxext/prs/11281.json new file mode 100644 index 0000000000000000000000000000000000000000..714c1a6652edb8fa6eb29e56fb7d09f5ed94912d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11281.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ad4c99cdca4b71026568e474118f6b18054addc6", + "authors": [ + { + "n": null, + "e": "timon.merk@charite.de" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 55, + "d": 15 + }, + "tutorials/clinical/30_ecog.py": { + "a": 27, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11282.json b/mne-python/source/doc/sphinxext/prs/11282.json new file mode 100644 index 0000000000000000000000000000000000000000..ccf47195d92356feaac10f2b8d8b4606d3ad279e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11282.json @@ -0,0 +1,195 @@ +{ + "merge_commit_sha": "925f522829f74ded48935f39b51ef270adc70923", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/api/time_frequency.rst": { + "a": 5, + "d": 0 + }, + "doc/changes/devel/11282.apichange.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/11282.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/11282.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 10, + "d": 8 + }, + "examples/inverse/dics_epochs.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 2, + "d": 3 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 38, + "d": 42 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 7 + }, + "mne/conftest.py": { + "a": 46, + "d": 9 + }, + "mne/decoding/time_frequency.py": { + "a": 11, + "d": 11 + }, + "mne/epochs.py": { + "a": 142, + "d": 7 + }, + "mne/evoked.py": { + "a": 61, + "d": 0 + }, + "mne/html_templates/repr/tfr.html.jinja": { + "a": 60, + "d": 0 + }, + "mne/io/base.py": { + "a": 64, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/__init__.pyi": { + "a": 10, + "d": 2 + }, + "mne/time_frequency/_stockwell.py": { + "a": 47, + "d": 32 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 39, + "d": 48 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 8, + "d": 4 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 683, + "d": 511 + }, + "mne/time_frequency/tfr.py": { + "a": 2578, + "d": 1484 + }, + "mne/utils/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/utils/_testing.py": { + "a": 10, + "d": 0 + }, + "mne/utils/check.py": { + "a": 20, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 588, + "d": 138 + }, + "mne/utils/mixin.py": { + "a": 10, + "d": 9 + }, + "mne/utils/numerics.py": { + "a": 14, + "d": 3 + }, + "mne/utils/spectrum.py": { + "a": 22, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 23, + "d": 12 + }, + "mne/viz/tests/test_topomap.py": { + "a": 11, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 18, + "d": 5 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tutorials/intro/10_overview.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 2, + "d": 3 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 5, + "d": 13 + }, + "tutorials/stats-sensor-space/70_cluster_rmANOVA_time_freq.py": { + "a": 2, + "d": 3 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 3, + "d": 4 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 5, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11283.json b/mne-python/source/doc/sphinxext/prs/11283.json new file mode 100644 index 0000000000000000000000000000000000000000..48abfc2d53f6384042f7ea554b99de63475d71d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11283.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "062b5e0a34d9dfc8c701fa0d86f2a017262207f2", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 3, + "d": 7 + }, + "mne/defaults.py": { + "a": 2, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 4, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 59, + "d": 44 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 34, + "d": 19 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 41, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11284.json b/mne-python/source/doc/sphinxext/prs/11284.json new file mode 100644 index 0000000000000000000000000000000000000000..1c25b077eb71e5cf7e51c8569e3478fb3d601c45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11284.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6e5ca18793c5a0d6db9c97b932bb89756c9dd17e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 1 + }, + "mne/utils/tests/test_misc.py": { + "a": 7, + "d": 14 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11289.json b/mne-python/source/doc/sphinxext/prs/11289.json new file mode 100644 index 0000000000000000000000000000000000000000..db3803348df8226d44fd398e2b9733fb625f96e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11289.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6c3a159824c41ffac40e289da601fb57de3649ba", + "authors": [ + { + "n": "Mauricio Cespedes", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11290.json b/mne-python/source/doc/sphinxext/prs/11290.json new file mode 100644 index 0000000000000000000000000000000000000000..ec55397ded8f2730d745f38a1a66941d28b173f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11290.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9e5989097dcf60634c1daf111457ca8e202d29e6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/channels/data/montages/mgh60.elc": { + "a": 42, + "d": 42 + }, + "mne/channels/tests/test_montage.py": { + "a": 75, + "d": 13 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11291.json b/mne-python/source/doc/sphinxext/prs/11291.json new file mode 100644 index 0000000000000000000000000000000000000000..4d6863e797ad1e41ee69fae1b152facc0f8d9e33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11291.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "52f34d33013aadd92150d43f52234969ea9a621a", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "examples/visualization/publication_figure.py": { + "a": 4, + "d": 6 + }, + "examples/visualization/sensor_noise_level.py": { + "a": 3, + "d": 3 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 1, + "d": 2 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 4, + "d": 5 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 12, + "d": 13 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 2, + "d": 3 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 10, + "d": 11 + }, + "tutorials/simulation/80_dics.py": { + "a": 5, + "d": 6 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11293.json b/mne-python/source/doc/sphinxext/prs/11293.json new file mode 100644 index 0000000000000000000000000000000000000000..38c3ce2426647e78ccb57e0cdd216f69fa60cb5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11293.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "649357dfce54d5ea76b80c9cc03d642e02ed1535", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "mne/filter.py": { + "a": 1, + "d": 9 + }, + "mne/time_frequency/csd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/multitaper.py": { + "a": 42, + "d": 63 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 7, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11298.json b/mne-python/source/doc/sphinxext/prs/11298.json new file mode 100644 index 0000000000000000000000000000000000000000..3010f0a2de14b4a80a4015289d7ce399f345d7bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11298.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "15d20b88fef9ccdc16ecd2435bafe516a6b0ce67", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1130.json b/mne-python/source/doc/sphinxext/prs/1130.json new file mode 100644 index 0000000000000000000000000000000000000000..3188b64f13fe262984d0b41a44ccf2eeaf29a8ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1130.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8270ec8847afbe784fe970a033d60896eb3d2bf0", + "authors": [ + { + "n": "Saket Choudhary", + "e": "saketkc@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11300.json b/mne-python/source/doc/sphinxext/prs/11300.json new file mode 100644 index 0000000000000000000000000000000000000000..7e12f000b9980b27ae73a6b64c0e117e17a69159 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11300.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bb328cbeb253165f09b7dc9122d44c432c483138", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11301.json b/mne-python/source/doc/sphinxext/prs/11301.json new file mode 100644 index 0000000000000000000000000000000000000000..ebb948fb1e658ceecfa24507878a867172ca7dd7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11301.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "57bd4a5e75008db9141f3458204b03551da57b8b", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/_includes/institutional-partners.rst": { + "a": 2, + "d": 1 + }, + "doc/_static/institution_logos/Donders.png": { + "a": 0, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11302.json b/mne-python/source/doc/sphinxext/prs/11302.json new file mode 100644 index 0000000000000000000000000000000000000000..52da95780b1698e118b66f914e7cd5e9cb7d74c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11302.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4ef3a88c7c1ea29b4925cece2072ad5c5d826b82", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 9, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11303.json b/mne-python/source/doc/sphinxext/prs/11303.json new file mode 100644 index 0000000000000000000000000000000000000000..bd9731c65b565364751daf78be203f8d1503097c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11303.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "867505ddb9f02c2629a6b364e190589d47ffbbf5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/_freesurfer.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11304.json b/mne-python/source/doc/sphinxext/prs/11304.json new file mode 100644 index 0000000000000000000000000000000000000000..f635ee09f64a656fb1dd14b13375887dedc4cfd8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11304.json @@ -0,0 +1,175 @@ +{ + "merge_commit_sha": "0ec28e9ad8e234ea51266644ae1ac35a2bc11f46", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/0.12.inc": { + "a": 4, + "d": 4 + }, + "doc/changes/0.14.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.15.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.19.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.20.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.21.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.22.inc": { + "a": 2, + "d": 2 + }, + "doc/time_frequency.rst": { + "a": 0, + "d": 2 + }, + "mne/_freesurfer.py": { + "a": 5, + "d": 9 + }, + "mne/cov.py": { + "a": 4, + "d": 19 + }, + "mne/decoding/csp.py": { + "a": 13, + "d": 7 + }, + "mne/decoding/transformer.py": { + "a": 4, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 55 + }, + "mne/evoked.py": { + "a": 11, + "d": 14 + }, + "mne/fixes.py": { + "a": 0, + "d": 20 + }, + "mne/preprocessing/_regress.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/simulation/_metrics.py": { + "a": 0, + "d": 49 + }, + "mne/simulation/metrics/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 12, + "d": 15 + }, + "mne/tests/test_coreg.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 5 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 152 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 10, + "d": 30 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 68 + }, + "mne/viz/_brain/_brain.py": { + "a": 8, + "d": 26 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 4 + }, + "mne/viz/_mpl_figure.py": { + "a": 3, + "d": 73 + }, + "mne/viz/backends/_pyvista.py": { + "a": 11, + "d": 11 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_figure.py": { + "a": 0, + "d": 7 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 13 + }, + "mne/viz/topomap.py": { + "a": 24, + "d": 147 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 14 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 1, + "d": 2 + }, + "tutorials/time-freq/10_spectrum_class.py": { + "a": 2, + "d": 2 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11306.json b/mne-python/source/doc/sphinxext/prs/11306.json new file mode 100644 index 0000000000000000000000000000000000000000..a2f6c7e93de4710f0e478b27050012232e0adeee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11306.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "fe9358f161af6743adb61160824d93f5e7b77aa7", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 10, + "d": 0 + }, + "mne/epochs.py": { + "a": 55, + "d": 12 + }, + "mne/event.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 61, + "d": 13 + }, + "mne/time_frequency/spectrum.py": { + "a": 3, + "d": 1 + }, + "mne/utils/check.py": { + "a": 2, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11307.json b/mne-python/source/doc/sphinxext/prs/11307.json new file mode 100644 index 0000000000000000000000000000000000000000..f30ae5ac420b0ef7700af400945802d0d02c58ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11307.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8585dd5a2867a1666d19178026b87bd6e98378b3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/spectrum.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11308.json b/mne-python/source/doc/sphinxext/prs/11308.json new file mode 100644 index 0000000000000000000000000000000000000000..7e10cdf5e740a9b9a76548167fa517be7f0a63d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11308.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6fb51a10abb6d37a9c120ea7ebb7188fcddf6443", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_chpi.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11309.json b/mne-python/source/doc/sphinxext/prs/11309.json new file mode 100644 index 0000000000000000000000000000000000000000..e4357007d576032b61a6c40a5d8d13dc682b1309 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11309.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f26528d78764c83f754873c40f17e40d5eb08d2d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 40, + "d": 38 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1131.json b/mne-python/source/doc/sphinxext/prs/1131.json new file mode 100644 index 0000000000000000000000000000000000000000..775ca544544ee09433a3117ba514d1671dcc2ee2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1131.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6f699dd7ce87e5ed7bbc1739afa3e53eea3a87c0", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fixes.py": { + "a": 11, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11310.json b/mne-python/source/doc/sphinxext/prs/11310.json new file mode 100644 index 0000000000000000000000000000000000000000..2b6d234a5a66791a1b894f5833cf73359b351ca3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11310.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "80a558ef008dc0add4f151eb0fc6051071a0d404", + "authors": [ + { + "n": "Santeri Ruuskanen", + "e": null + }, + { + "n": "Santeri Ruuskanen", + "e": "santeri.ruuskanen@aalto.fi" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 11, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11311.json b/mne-python/source/doc/sphinxext/prs/11311.json new file mode 100644 index 0000000000000000000000000000000000000000..20404afdad0dc8b5462ca77d61db6e48185fdb77 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11311.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "815bee6b38c160e6f83d86bf929e79040536c83d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 9, + "d": 3 + }, + "mne/decoding/search_light.py": { + "a": 10, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11313.json b/mne-python/source/doc/sphinxext/prs/11313.json new file mode 100644 index 0000000000000000000000000000000000000000..ca0fa44b7fc835ea5b86cdb24359f6303c587256 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11313.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aeeb111f8555b49460583a34c573437358c1cb9f", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11315.json b/mne-python/source/doc/sphinxext/prs/11315.json new file mode 100644 index 0000000000000000000000000000000000000000..d5c76baee53d5ed55e71ce1f0ec2a5bc8c4bf0f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11315.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4d12df23916601003aef45d9e72c1e240191cd53", + "authors": [ + { + "n": "Eric Brayet", + "e": null + } + ], + "changes": { + "doc/changes/1.2.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11317.json b/mne-python/source/doc/sphinxext/prs/11317.json new file mode 100644 index 0000000000000000000000000000000000000000..055f14d34102672c286d9c7c904fe5441ef5cf71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11317.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1c1cc3f203e2d7f4edb97df312fdabaca51b9da9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11318.json b/mne-python/source/doc/sphinxext/prs/11318.json new file mode 100644 index 0000000000000000000000000000000000000000..20a3822a2e8a3a00a43a869f4b2e88cdae6f5c0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11318.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4f3ad29ec65a9e888cb237b24c834a9e161ba3f5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 5, + "d": 8 + }, + "mne/report/tests/test_report.py": { + "a": 15, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1132.json b/mne-python/source/doc/sphinxext/prs/1132.json new file mode 100644 index 0000000000000000000000000000000000000000..3365aca7bf4fc880d2f73f033575839c72b35382 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1132.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b5d50fe1b81486d03f022e0451c71f495f828403", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fiff/edf/edf.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11322.json b/mne-python/source/doc/sphinxext/prs/11322.json new file mode 100644 index 0000000000000000000000000000000000000000..a101f58f98e9f5bbf0c90e0ccc19dbf4302affc1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11322.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e65e5e5b49a7cdc21fb42d4a92bca5bd7a4e4329", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11325.json b/mne-python/source/doc/sphinxext/prs/11325.json new file mode 100644 index 0000000000000000000000000000000000000000..97e64822f167c321b0df41356426134720e39042 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11325.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "be6bee79833ad48aaf34b7afabf08df8fc154475", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11328.json b/mne-python/source/doc/sphinxext/prs/11328.json new file mode 100644 index 0000000000000000000000000000000000000000..385ee6b9f1ddcb7bd7ade0de2ba80f746c46fe2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11328.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0fbd8fcae6e6c3a69c47069da9af8127bd113e8a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_templates/sidebar-quicklinks.html": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 10, + "d": 18 + }, + "doc/install/contributing.rst": { + "a": 7, + "d": 7 + }, + "doc/install/index.rst": { + "a": 1, + "d": 1 + }, + "doc/install/installers.rst": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11329.json b/mne-python/source/doc/sphinxext/prs/11329.json new file mode 100644 index 0000000000000000000000000000000000000000..5a7a41f9f66647082377635991550b57a1d48f38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11329.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "063a3e87c521fc0bff0307a456cb8d363ecffa9e", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 24, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 45, + "d": 12 + }, + "mne/viz/utils.py": { + "a": 9, + "d": 9 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11333.json b/mne-python/source/doc/sphinxext/prs/11333.json new file mode 100644 index 0000000000000000000000000000000000000000..ab75c6cdf1baf788a1aeb9e6f5811cfe7a3317d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11333.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bbdf98b7d09b0c70db41ebfc203b3531e91c8e67", + "authors": [ + { + "n": "Toomas Erik Anijärv", + "e": "toomaserikanijarv@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 11, + "d": 5 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11334.json b/mne-python/source/doc/sphinxext/prs/11334.json new file mode 100644 index 0000000000000000000000000000000000000000..dd28c00762559049ce93c5b8cdeffeae3b6872ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11334.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e56581776c5b5442ae2f4fa7de5ab43a0600322d", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 5, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11335.json b/mne-python/source/doc/sphinxext/prs/11335.json new file mode 100644 index 0000000000000000000000000000000000000000..4aa601d6e94ea368b18c918ba0da3bd4e6aebcaa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11335.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8f01c9002a8ec6d89824e0cc1c6415be73ab1987", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/evoked.py": { + "a": 1, + "d": 0 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11338.json b/mne-python/source/doc/sphinxext/prs/11338.json new file mode 100644 index 0000000000000000000000000000000000000000..df9152cbefcfe3beba7c2b5f546c26c8c3fe18bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11338.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "049295e9fd84c821db4537c9ea50efc20625b43d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 3, + "d": 0 + }, + "mne/io/ctf/markers.py": { + "a": 5, + "d": 4 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 4 + }, + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1134.json b/mne-python/source/doc/sphinxext/prs/1134.json new file mode 100644 index 0000000000000000000000000000000000000000..83e977e046ad4280399b3599184ecfdf81d13529 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1134.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f0d0211ef87171566439caf042b57401fa58a114", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11340.json b/mne-python/source/doc/sphinxext/prs/11340.json new file mode 100644 index 0000000000000000000000000000000000000000..a8c43636b8e1b221e1412e1cb47cf449b179be58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11340.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c4e624962a1908c71a2fe912a531b6783adc7987", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/curry/curry.py": { + "a": 14, + "d": 6 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11344.json b/mne-python/source/doc/sphinxext/prs/11344.json new file mode 100644 index 0000000000000000000000000000000000000000..7582d818aa91175f590d3cba6ddf0add10aaa5df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11344.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "275a9879a058cc5b9eb48a39c46c6ec1d18b6248", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Felix Klotzsche", + "e": "klotzsche@cbs.mpg.de" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 6, + "d": 3 + }, + "mne/io/pick.py": { + "a": 6, + "d": 6 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11345.json b/mne-python/source/doc/sphinxext/prs/11345.json new file mode 100644 index 0000000000000000000000000000000000000000..4468401248fbc7cec8529c10e1fd42e521ecfc1d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11345.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f5d9a9eddefaffeedac46a79dfd149e6923fe048", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 11, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11346.json b/mne-python/source/doc/sphinxext/prs/11346.json new file mode 100644 index 0000000000000000000000000000000000000000..1180ddfce43abe74be7f2c6053215b17eac35c9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11346.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3812114eeea9a9ffc8449fb23b21353e878e6f25", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 36, + "d": 33 + }, + "mne/report/tests/test_report.py": { + "a": 37, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11347.json b/mne-python/source/doc/sphinxext/prs/11347.json new file mode 100644 index 0000000000000000000000000000000000000000..87f4fa0d6ced038acf3116f6c33ddb4bc1a8bcfe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11347.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "452d51d7ae5d058b04ead9f6d5995e4303e3e241", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 7, + "d": 2 + }, + "doc/conf.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11348.json b/mne-python/source/doc/sphinxext/prs/11348.json new file mode 100644 index 0000000000000000000000000000000000000000..67703c61ea9869f5a2e672c2d729f40f31b794e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11348.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ad8b91d752c9eb577dfbb96b4158ca0cb0ab2267", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/clinical/30_ecog.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1135.json b/mne-python/source/doc/sphinxext/prs/1135.json new file mode 100644 index 0000000000000000000000000000000000000000..d19f50d8c3ca2f18b124da154dd56b1053f4417d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1135.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "770af5643eb5130c727337af195089897b14cb19", + "authors": [ + { + "n": "Saket Choudhary", + "e": "saketkc@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 5, + "d": 0 + }, + "mne/utils.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11350.json b/mne-python/source/doc/sphinxext/prs/11350.json new file mode 100644 index 0000000000000000000000000000000000000000..aec70a55389d2d975fd849745aebf96aaaaa6245 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11350.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "d7bcdd526fd64680107dc98e5871fe128ec33079", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 0, + "d": 1 + }, + "doc/conf.py": { + "a": 0, + "d": 1 + }, + "doc/mri.rst": { + "a": 0, + "d": 1 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 32, + "d": 95 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 96 + }, + "mne/gui/_core.py": { + "a": 33, + "d": 33 + }, + "mne/gui/_vol_stc.py": { + "a": 0, + "d": 896 + }, + "mne/gui/tests/test_core.py": { + "a": 2, + "d": 2 + }, + "mne/gui/tests/test_vol_stc.py": { + "a": 0, + "d": 202 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 0, + "d": 31 + }, + "mne/utils/tests/test_check.py": { + "a": 1, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11351.json b/mne-python/source/doc/sphinxext/prs/11351.json new file mode 100644 index 0000000000000000000000000000000000000000..028daa3ed4abacb7ff5c78c581c21264acd95f74 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11351.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ec28281c54a9b4c7ce74c0a58a09ced1a5e580f8", + "authors": [ + { + "n": "enzo", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_proj.py": { + "a": 0, + "d": 24 + }, + "mne/tests/test_proj.py": { + "a": 27, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11353.json b/mne-python/source/doc/sphinxext/prs/11353.json new file mode 100644 index 0000000000000000000000000000000000000000..b15396fc21f722d1081ef24de70f9793884d7e20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11353.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "73047d3df0565195a977f690773153ec8710a2f4", + "authors": [ + { + "n": "Britta Westner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 28, + "d": 0 + }, + "doc/references.bib": { + "a": 19, + "d": 0 + }, + "doc/time_frequency.rst": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 31, + "d": 7 + }, + "mne/time_frequency/tfr.py": { + "a": 129, + "d": 15 + }, + "mne/utils/docs.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11354.json b/mne-python/source/doc/sphinxext/prs/11354.json new file mode 100644 index 0000000000000000000000000000000000000000..47742e2738c4043674553d32f385ee0183d4d4b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11354.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ee64a44c569024d653f0cd4fa8ed8c6a4e0a6b76", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/gui/__init__.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11356.json b/mne-python/source/doc/sphinxext/prs/11356.json new file mode 100644 index 0000000000000000000000000000000000000000..4d5e57f62a6ad743f6cc350ebcb641307496564a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11356.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "306b311a0a3b4ea9c353589d7647523ea0882253", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/linux_conda.yml": { + "a": 6, + "d": 2 + }, + "doc/install/advanced.rst": { + "a": 7, + "d": 8 + }, + "doc/install/check_installation.rst": { + "a": 0, + "d": 1 + }, + "environment.yml": { + "a": 5, + "d": 1 + }, + "mne/conftest.py": { + "a": 5, + "d": 2 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 1, + "d": 0 + }, + "mne/utils/check.py": { + "a": 8, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 7, + "d": 0 + }, + "mne/viz/backends/_utils.py": { + "a": 54, + "d": 0 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 33, + "d": 3 + }, + "mne/viz/backends/tests/test_abstract_notebook.py": { + "a": 0, + "d": 31 + }, + "server_environment.yml": { + "a": 0, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11357.json b/mne-python/source/doc/sphinxext/prs/11357.json new file mode 100644 index 0000000000000000000000000000000000000000..fb55804b651ed0a88c6e1e9e4e9b43aed799abca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11357.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1be103defc5e8a10773a3fe1a0ec56515920f08f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 26, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11359.json b/mne-python/source/doc/sphinxext/prs/11359.json new file mode 100644 index 0000000000000000000000000000000000000000..dfe6b608e9d9104da94dda8ec7545a4318d8a72c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11359.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8f6af8068fa2281d9b6bc207bd46ae705a31eb2d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 61, + "d": 19 + }, + "mne/report/tests/test_report.py": { + "a": 42, + "d": 3 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1136.json b/mne-python/source/doc/sphinxext/prs/1136.json new file mode 100644 index 0000000000000000000000000000000000000000..695b76c1266942d54c114aecaa5ce541c06c042e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1136.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f1f8c2c773c028ebda4d42431e0a1bbf7bc873c1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/event.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11361.json b/mne-python/source/doc/sphinxext/prs/11361.json new file mode 100644 index 0000000000000000000000000000000000000000..227463ab6e315c0c59556c5da3c6e619bcebe6d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11361.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5346534f838ef62a5bbb1fc5388d19854e284f91", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/surface.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11363.json b/mne-python/source/doc/sphinxext/prs/11363.json new file mode 100644 index 0000000000000000000000000000000000000000..83ae940025bb180b3cd01bd3b3ced0cc7017302c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11363.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "52590f330c3515b7871ee29063e991a5f2d79054", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11364.json b/mne-python/source/doc/sphinxext/prs/11364.json new file mode 100644 index 0000000000000000000000000000000000000000..c4cee1482962982ad7feb72b98baec4322e84532 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11364.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4e759bd5811a7f8d46b81a26c10869e496a9f878", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11365.json b/mne-python/source/doc/sphinxext/prs/11365.json new file mode 100644 index 0000000000000000000000000000000000000000..6491ffb6d692c439d19642aae6d3fc4a4b6224d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11365.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6b2d5f04b4e52e43ec0e34b29f48034b7b931d36", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11366.json b/mne-python/source/doc/sphinxext/prs/11366.json new file mode 100644 index 0000000000000000000000000000000000000000..ceacefbe783d434d70b85f112b3c2ec0e61e7749 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11366.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "d7570264afaa24da658bbd996ed50c2a37b0ffcf", + "authors": [ + { + "n": "George O'Neill", + "e": null + }, + { + "n": "Robert Seymour", + "e": "robbyseymour@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 7, + "d": 0 + }, + "doc/_includes/data_formats.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/datasets.rst": { + "a": 1, + "d": 0 + }, + "doc/glossary.rst": { + "a": 20, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 13, + "d": 0 + }, + "doc/reading_raw_data.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 15, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 10, + "d": 2 + }, + "mne/datasets/ucl_opm_auditory/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/ucl_opm_auditory/ucl_opm_auditory.py": { + "a": 32, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 48, + "d": 27 + }, + "mne/io/fil/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/io/fil/fil.py": { + "a": 298, + "d": 0 + }, + "mne/io/fil/sensors.py": { + "a": 145, + "d": 0 + }, + "mne/io/fil/tests/test_fil.py": { + "a": 146, + "d": 0 + }, + "mne/io/tests/test_read_raw.py": { + "a": 25, + "d": 3 + }, + "mne/preprocessing/_regress.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 32, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "tools/circleci_download.sh": { + "a": 4, + "d": 1 + }, + "tutorials/io/10_reading_meg_data.py": { + "a": 8, + "d": 1 + }, + "tutorials/preprocessing/80_opm_processing.py": { + "a": 181, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11369.json b/mne-python/source/doc/sphinxext/prs/11369.json new file mode 100644 index 0000000000000000000000000000000000000000..27576d63d3292eddecda8d441402e50ffe95816a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11369.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6c403d34d9542174203a6764197664e21bea8279", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/pick.py": { + "a": 19, + "d": 8 + }, + "mne/io/tests/test_pick.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 12, + "d": 8 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11371.json b/mne-python/source/doc/sphinxext/prs/11371.json new file mode 100644 index 0000000000000000000000000000000000000000..e82c07aec7a640ff1cb7aa0f67641481c88bd5d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11371.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "715e9790836c1e25ac20a82feed0b68d0e227d1b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 146, + "d": 174 + }, + "mne/preprocessing/ica.py": { + "a": 20, + "d": 19 + }, + "mne/utils/docs.py": { + "a": 35, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 24, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 139, + "d": 92 + }, + "mne/viz/utils.py": { + "a": 14, + "d": 0 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11374.json b/mne-python/source/doc/sphinxext/prs/11374.json new file mode 100644 index 0000000000000000000000000000000000000000..bb37a23575b24e1bc41610212a3f557a9f9a68ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11374.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "66fdc9f4af9f6eb71db8a3952ef9bb5e8cf7578d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11375.json b/mne-python/source/doc/sphinxext/prs/11375.json new file mode 100644 index 0000000000000000000000000000000000000000..6025e428e90f99257a375d830ed4ff84e9e8de51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11375.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d133a304d68b8e1aac5ebef49441e6ffa78a399b", + "authors": [ + { + "n": "Mark Henney", + "e": null + }, + { + "n": "Mark", + "e": "mah@optoceutics.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 5, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11377.json b/mne-python/source/doc/sphinxext/prs/11377.json new file mode 100644 index 0000000000000000000000000000000000000000..80936e9ec3b399991aa2003578cff4d7e263dc2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11377.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "83f56953569853304c4f4d974090b7f54df799a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 11, + "d": 13 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11378.json b/mne-python/source/doc/sphinxext/prs/11378.json new file mode 100644 index 0000000000000000000000000000000000000000..d2bb9c0aa758817e96d4730dffa2389a0a38d2fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11378.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "71467604d0e47a98a12364fe59e215c59a331e7a", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 12, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11379.json b/mne-python/source/doc/sphinxext/prs/11379.json new file mode 100644 index 0000000000000000000000000000000000000000..ec3ed21b2cd42df48906c478f72f61b18776d623 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11379.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a1fec00207a0c9b1281cb2ad1e761bd6b866a66", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11381.json b/mne-python/source/doc/sphinxext/prs/11381.json new file mode 100644 index 0000000000000000000000000000000000000000..5fad315347ac20156d4e7d6a654bfc539256399a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11381.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "654248a3ea9d5b106eaba51b9a74b93a531b3746", + "authors": [ + { + "n": "Lukas Hecker", + "e": null + } + ], + "changes": { + "doc/install/mne_tools_suite.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11384.json b/mne-python/source/doc/sphinxext/prs/11384.json new file mode 100644 index 0000000000000000000000000000000000000000..3815a6913dbf8b74cbae72a2c7d63e13073ad416 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11384.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "1c4c2504ee553e0cdb8def2bb0499b02bc93bbe3", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Jennifer Behnke", + "e": "jennifer.behnke@localhost" + }, + { + "n": "Hakimeh Aslsardroud", + "e": "hakimeh.aslsardroud@localhost" + }, + { + "n": "Pavel Navratil", + "e": "pavel.navratil@localhost" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".mailmap": { + "a": 6, + "d": 0 + }, + "CITATION.cff": { + "a": 43, + "d": 17 + }, + "SECURITY.md": { + "a": 3, + "d": 3 + }, + "codemeta.json": { + "a": 117, + "d": 39 + }, + "doc/_static/versions.json": { + "a": 7, + "d": 2 + }, + "doc/changes/1.3.inc": { + "a": 36, + "d": 3 + }, + "doc/cited.rst": { + "a": 3, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/_version.py": { + "a": 1, + "d": 1 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "tools/circleci_download.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11387.json b/mne-python/source/doc/sphinxext/prs/11387.json new file mode 100644 index 0000000000000000000000000000000000000000..ee401dca2fe22dc5332c03bb07f81b716338fbd0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11387.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "546cbafc4524a17653a57e960cbfa03088d0bdbf", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/installers.rst": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11388.json b/mne-python/source/doc/sphinxext/prs/11388.json new file mode 100644 index 0000000000000000000000000000000000000000..5e5adac43329cdba7e4ec0f3046356abde781c9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11388.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b298e6d2710a9d55e531a0958d48e88b9b92f539", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/filter.py": { + "a": 1, + "d": 9 + }, + "mne/io/base.py": { + "a": 19, + "d": 9 + }, + "mne/tests/test_annotations.py": { + "a": 10, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11389.json b/mne-python/source/doc/sphinxext/prs/11389.json new file mode 100644 index 0000000000000000000000000000000000000000..95fe56dcb9c0b810a567ca5801ec7937c3e4239d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11389.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a23c62b8e405f05a628c0fa05929b5c1fb01abc5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11390.json b/mne-python/source/doc/sphinxext/prs/11390.json new file mode 100644 index 0000000000000000000000000000000000000000..bf8249ad0b6e74a9a88efd7170e1f434c9fc5038 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11390.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "96a4bc2e928043a16ab23682fc818cf0a3e78aef", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11391.json b/mne-python/source/doc/sphinxext/prs/11391.json new file mode 100644 index 0000000000000000000000000000000000000000..783e5fc459c4860cf2d4a1070eeb879c003d8536 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11391.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e5086fcb20e891ef1c4ddc2ce2ae16047b496c5f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 7, + "d": 48 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 8 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 30 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 0, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 0, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 19, + "d": 41 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11397.json b/mne-python/source/doc/sphinxext/prs/11397.json new file mode 100644 index 0000000000000000000000000000000000000000..ab8cec0cd37051894e8cfa3c551a67d9773d32bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11397.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "9b1e7dd50846882efd62c6f02946e249585a1d8d", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + }, + "doc/links.inc": { + "a": 1, + "d": 1 + }, + "doc/overview/roadmap.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 5, + "d": 1 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 27, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11398.json b/mne-python/source/doc/sphinxext/prs/11398.json new file mode 100644 index 0000000000000000000000000000000000000000..14304261963b8169d5ab154a8ac5a4b035e72925 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11398.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "147d099c4ac17e3558a758cf672bb448affeae04", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 44, + "d": 14 + }, + "mne/gui/_core.py": { + "a": 2, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 1 + }, + "mne/gui/tests/test_core.py": { + "a": 12, + "d": 30 + }, + "mne/gui/tests/test_coreg.py": { + "a": 35, + "d": 5 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 17, + "d": 12 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 18, + "d": 28 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 9 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 5, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 11, + "d": 22 + }, + "mne/viz/backends/_qt.py": { + "a": 18, + "d": 15 + }, + "mne/viz/backends/_utils.py": { + "a": 41, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 0, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tools/cirrus_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11399.json b/mne-python/source/doc/sphinxext/prs/11399.json new file mode 100644 index 0000000000000000000000000000000000000000..4f90907d46936b00e3376dee94508b356089d196 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11399.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "b9e0d966e564f18220b57af3835adb42ddfc3d16", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 15, + "d": 27 + }, + "mne/cov.py": { + "a": 8, + "d": 9 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 7 + }, + "mne/io/meas_info.py": { + "a": 16, + "d": 9 + }, + "mne/io/proc_history.py": { + "a": 6, + "d": 4 + }, + "mne/io/proj.py": { + "a": 6, + "d": 4 + }, + "mne/io/write.py": { + "a": 21, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1140.json b/mne-python/source/doc/sphinxext/prs/1140.json new file mode 100644 index 0000000000000000000000000000000000000000..65e322961d5790f6740f00cc0bf830eeeca7bcef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1140.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "22fb909b06f5f69867d241b426a9e8978f31cd9e", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "doc/source/getting_started.rst": { + "a": 113, + "d": 82 + }, + "doc/source/python_tutorial.rst": { + "a": 7, + "d": 37 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11401.json b/mne-python/source/doc/sphinxext/prs/11401.json new file mode 100644 index 0000000000000000000000000000000000000000..5f52d299b3868179caa3854c7be51998ce164337 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11401.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ea88c55b183b5ed5aec793737caf30d750ac999e", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11402.json b/mne-python/source/doc/sphinxext/prs/11402.json new file mode 100644 index 0000000000000000000000000000000000000000..b5548ac741d210797c080ccde86a9976d017b722 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11402.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4c5f722585b6637b9180b50345a7ee0bbb6942be", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/_freesurfer.py": { + "a": 33, + "d": 1 + }, + "mne/tests/test_freesurfer.py": { + "a": 37, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11405.json b/mne-python/source/doc/sphinxext/prs/11405.json new file mode 100644 index 0000000000000000000000000000000000000000..c8e4d72eb3691d09b306d1c5f62d5aa93ec0f0f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11405.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "cc377dabd5a4e449d2bc706470a2ed16ea2339fe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 13, + "d": 6 + }, + "doc/api/datasets.rst": { + "a": 1, + "d": 0 + }, + "doc/documentation/datasets.rst": { + "a": 13, + "d": 0 + }, + "examples/datasets/kernel_phantom.py": { + "a": 103, + "d": 0 + }, + "mne/_fiff/_digitization.py": { + "a": 3, + "d": 0 + }, + "mne/bem.py": { + "a": 4, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 0 + }, + "mne/coreg.py": { + "a": 6, + "d": 4 + }, + "mne/data/helmets/Kernel_Flux.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/data/helmets/Kernel_Flux_ch_pos.txt": { + "a": 202, + "d": 0 + }, + "mne/datasets/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 8, + "d": 0 + }, + "mne/datasets/phantom_kernel/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/phantom_kernel/phantom_kernel.py": { + "a": 32, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 28, + "d": 31 + }, + "mne/surface.py": { + "a": 77, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 17, + "d": 0 + }, + "mne/transforms.py": { + "a": 52, + "d": 0 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 19, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 72, + "d": 21 + }, + "mne/viz/_brain/_brain.py": { + "a": 14, + "d": 13 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "tools/circleci_download.sh": { + "a": 3, + "d": 0 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 2, + "d": 2 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 2, + "d": 2 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11407.json b/mne-python/source/doc/sphinxext/prs/11407.json new file mode 100644 index 0000000000000000000000000000000000000000..a85cef113d24d5dc384834007e4fbaeb3bc0626f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11407.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6feb7091cf7ce7fb88325e5e9c1535370fa9c004", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/datasets/_fetch.py": { + "a": 12, + "d": 3 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11409.json b/mne-python/source/doc/sphinxext/prs/11409.json new file mode 100644 index 0000000000000000000000000000000000000000..549a54588f507817d27157c7ce92616e50300689 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11409.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "a5fa4ab637b0b59d2943d706dedce60822d01ad0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "mne/conftest.py": { + "a": 0, + "d": 5 + }, + "mne/viz/_mpl_figure.py": { + "a": 175, + "d": 87 + }, + "mne/viz/tests/test_epochs.py": { + "a": 0, + "d": 6 + }, + "mne/viz/tests/test_raw.py": { + "a": 31, + "d": 30 + }, + "mne/viz/tests/test_topomap.py": { + "a": 7, + "d": 14 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 21, + "d": 13 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 2, + "d": 2 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 1, + "d": 0 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11412.json b/mne-python/source/doc/sphinxext/prs/11412.json new file mode 100644 index 0000000000000000000000000000000000000000..9776f5f246e95489dc10191f360452894cbf0693 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11412.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f6da05d18810f1a64572d341392299228220a460", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 5, + "d": 4 + }, + "mne/channels/interpolation.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11416.json b/mne-python/source/doc/sphinxext/prs/11416.json new file mode 100644 index 0000000000000000000000000000000000000000..36986a885cef37d75f9243b9b254f88d29cfee0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11416.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8b868a09a224781932cbfa6a19fd52280b417de8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11417.json b/mne-python/source/doc/sphinxext/prs/11417.json new file mode 100644 index 0000000000000000000000000000000000000000..d94ca911c2bd403684e078cef77c4a962837290d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11417.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "0e607f3f0eb7c9cbc1e3c6274a214bbd454fb352", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 3, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 4, + "d": 2 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 9, + "d": 11 + }, + "mne/viz/tests/test_epochs.py": { + "a": 6, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 17, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 5, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11418.json b/mne-python/source/doc/sphinxext/prs/11418.json new file mode 100644 index 0000000000000000000000000000000000000000..7e844d4c41d7440369a45c3d485f0400eaf30cc3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11418.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b573951de1a84194aff18e9a99eae9f01a3b7aa0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 5, + "d": 1 + }, + "mne/evoked.py": { + "a": 4, + "d": 1 + }, + "mne/io/base.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/tests/test_raw.py": { + "a": 11, + "d": 13 + }, + "mne/time_frequency/spectrum.py": { + "a": 0, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11419.json b/mne-python/source/doc/sphinxext/prs/11419.json new file mode 100644 index 0000000000000000000000000000000000000000..4b5ed0b9d068199c23efad49945adb692287dbe6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11419.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "36af824f9d16a6d411318bb79e736d7641f1ec14", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 37, + "d": 5 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1142.json b/mne-python/source/doc/sphinxext/prs/1142.json new file mode 100644 index 0000000000000000000000000000000000000000..214c98c27aeb5b4959af88486253c2c62ccecaa7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1142.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2ee58a685d3176c852ed4b7e6167c376a1065a66", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 16, + "d": 21 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 33, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11420.json b/mne-python/source/doc/sphinxext/prs/11420.json new file mode 100644 index 0000000000000000000000000000000000000000..c2e92bb82123e36d5358b7318e3d5383019cd189 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11420.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e50d9bc7979830d4d0f5416c2f78720741dbe582", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 12, + "d": 15 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "requirements_doc.txt": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11421.json b/mne-python/source/doc/sphinxext/prs/11421.json new file mode 100644 index 0000000000000000000000000000000000000000..9ecc166a3e1ab398e7b81f49f86da45587e3c396 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11421.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6306265af0002e3b4a9e718c5fc3c4026fe80967", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/gui/_ieeg_locate.py": { + "a": 16, + "d": 6 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 20, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11422.json b/mne-python/source/doc/sphinxext/prs/11422.json new file mode 100644 index 0000000000000000000000000000000000000000..80a047b69ce914a3509db0591620c75988394b90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11422.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4afeceb9322a53b463d30177fe0ca3b58ffbb3b0", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11423.json b/mne-python/source/doc/sphinxext/prs/11423.json new file mode 100644 index 0000000000000000000000000000000000000000..fcfa70af68efa55d3dc6ed148c30a78cd08bb9bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11423.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "61f83a95f6ec256c4053b0e0e50ead7c0d9f5340", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11424.json b/mne-python/source/doc/sphinxext/prs/11424.json new file mode 100644 index 0000000000000000000000000000000000000000..a79c17c6850035554e65a0c12337b6ab8393fd1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11424.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "59125c9182804153729dfb355608457f09cb5bbd", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/tests/test_annotations.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11425.json b/mne-python/source/doc/sphinxext/prs/11425.json new file mode 100644 index 0000000000000000000000000000000000000000..488fe274b02d3c3704d2e5df4d6bf6daa2b55745 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11425.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "28ef1348cebb4ab55f2a22f64bc9c6da6e40569a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 3, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11427.json b/mne-python/source/doc/sphinxext/prs/11427.json new file mode 100644 index 0000000000000000000000000000000000000000..b3c423058cd1843b598ff47b52e64cb40728d4ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11427.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4f487feddddd9f3844aaee47e3993a2c137a7bf8", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1143.json b/mne-python/source/doc/sphinxext/prs/1143.json new file mode 100644 index 0000000000000000000000000000000000000000..1e9c7e2874cf6a118adbc7044942afb66ee48a99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1143.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "65b7401f2bc78eaa1a73131b6e8070c12e3c3020", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/_compute_forward.py": { + "a": 12, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11430.json b/mne-python/source/doc/sphinxext/prs/11430.json new file mode 100644 index 0000000000000000000000000000000000000000..9f400964f6e1999006506517eb26b444f9a6e39c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11430.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8dfb23be27536d654838377622a898b08f86cd31", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/events.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 34, + "d": 0 + }, + "mne/tests/test_event.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11432.json b/mne-python/source/doc/sphinxext/prs/11432.json new file mode 100644 index 0000000000000000000000000000000000000000..0226e9a887c9d292727bb397d809ca0968bcbc67 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11432.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "1704513f46f2596f7dccbb520e30804324999409", + "authors": [ + { + "n": "Proloy Das", + "e": "proloy@umd.edu" + }, + { + "n": "pdas6", + "e": "pdas6@mgh.harvard.edu" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/reading_raw_data.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/nsx/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/nsx/nsx.py": { + "a": 535, + "d": 0 + }, + "mne/io/nsx/tests/test_nsx.py": { + "a": 282, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11435.json b/mne-python/source/doc/sphinxext/prs/11435.json new file mode 100644 index 0000000000000000000000000000000000000000..863c0ecc9206d85400a719294fbe4e65f8563e9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11435.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "32b686c0416ca5d5751cf2e07befdfcecb6c0bcb", + "authors": [ + { + "n": "Giulio", + "e": "giulio.gabrieli@iit.it" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "agramfort@fb.com" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/export/_eeglab.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11436.json b/mne-python/source/doc/sphinxext/prs/11436.json new file mode 100644 index 0000000000000000000000000000000000000000..70f93f22fd33e415254cd5bb29553a6227ae227f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11436.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7262ad94b1c1e80d2cd63662a2f99aed49e74beb", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 7, + "d": 1 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11437.json b/mne-python/source/doc/sphinxext/prs/11437.json new file mode 100644 index 0000000000000000000000000000000000000000..cd8bfe229293da5a08321110433bd0b05032b3ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11437.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "11bc09911a2dbb6b73a86b31d8140ccd8a93b1c3", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 91, + "d": 1 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 102, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 14, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 31, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 25, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11438.json b/mne-python/source/doc/sphinxext/prs/11438.json new file mode 100644 index 0000000000000000000000000000000000000000..e654c7ad693c6a2be1c94d660cbca74405a70f2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11438.json @@ -0,0 +1,239 @@ +{ + "merge_commit_sha": "32feb72477e496663ae9dd0baccb85aab704c4f8", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "examples/inverse/dics_source_power.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/source_space_snr.py": { + "a": 1, + "d": 1 + }, + "examples/io/elekta_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 2, + "d": 2 + }, + "mne/_ola.py": { + "a": 3, + "d": 3 + }, + "mne/baseline.py": { + "a": 2, + "d": 2 + }, + "mne/chpi.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_maxfilter.py": { + "a": 2, + "d": 2 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 2 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 6, + "d": 6 + }, + "mne/evoked.py": { + "a": 4, + "d": 4 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/epochs.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/annotate_amplitude.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/maxfilter.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/realign.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/proj.py": { + "a": 3, + "d": 3 + }, + "mne/report/report.py": { + "a": 4, + "d": 4 + }, + "mne/report/tests/test_report.py": { + "a": 4, + "d": 4 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_rank.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_proj.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 4, + "d": 4 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11440.json b/mne-python/source/doc/sphinxext/prs/11440.json new file mode 100644 index 0000000000000000000000000000000000000000..f602ef5fe3ca52d7869d0a6bf8ad4688166dedcf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11440.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "51b2b75424a239116384b3268029b3ea60e18953", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11441.json b/mne-python/source/doc/sphinxext/prs/11441.json new file mode 100644 index 0000000000000000000000000000000000000000..dfa7d745b1da075ec92e218a3699d95744ae6153 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11441.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6f26d34593c937796c4edf9a68afb4f4b5e5361c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/utils/config.py": { + "a": 15, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11445.json b/mne-python/source/doc/sphinxext/prs/11445.json new file mode 100644 index 0000000000000000000000000000000000000000..a604f39fc5da3f13343c9aa0c59441802ec09fa6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11445.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1388d8440cd8347f8c86bdf2f3e91fae195d0359", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 35, + "d": 14 + }, + "mne/viz/tests/test_epochs.py": { + "a": 66, + "d": 32 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1145.json b/mne-python/source/doc/sphinxext/prs/1145.json new file mode 100644 index 0000000000000000000000000000000000000000..9fceb6e8bfdbe5859c60c3a57fd71eacc08f7dab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1145.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "89fa95be4de530f38a19b2c9addbaec50336d8dc", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_kit2fiff_gui.py": { + "a": 1, + "d": 2 + }, + "mne/gui/_marker_gui.py": { + "a": 8, + "d": 1 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 26, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11450.json b/mne-python/source/doc/sphinxext/prs/11450.json new file mode 100644 index 0000000000000000000000000000000000000000..08e7b9e380785ca3dc99a561deddb5d3aa8a9463 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11450.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d9964f568a02c8f9d900c84ebb8e857dfcad9844", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/decoding/search_light.py": { + "a": 68, + "d": 25 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 27, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 19, + "d": 11 + }, + "mne/utils/progressbar.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11452.json b/mne-python/source/doc/sphinxext/prs/11452.json new file mode 100644 index 0000000000000000000000000000000000000000..1debfe8d711608cae20ac0d1183fefc7ac78ca91 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11452.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9ca938ea6a6d1765e5e617b0efb064f1d0ea21f9", + "authors": [ + { + "n": "rcmdnk", + "e": "rcmdnk@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "agramfort@fb.com" + } + ], + "changes": { + "tutorials/clinical/60_sleep.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11453.json b/mne-python/source/doc/sphinxext/prs/11453.json new file mode 100644 index 0000000000000000000000000000000000000000..4d4e8ddab1a50681a2438d74a7a55a763f56f041 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11453.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c1c45249e9af81296313dcbd682e3c00cf25df92", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11454.json b/mne-python/source/doc/sphinxext/prs/11454.json new file mode 100644 index 0000000000000000000000000000000000000000..6d67a255e4e55a545f6662884d1737fb381a73b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11454.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e12ba0a139fa1356933b45c07faea8cf4eaaf5af", + "authors": [ + { + "n": "pzr", + "e": "arne.pelzer@idmt.fraunhofer.de" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 9, + "d": 5 + }, + "mne/utils/misc.py": { + "a": 7, + "d": 6 + }, + "requirements_base.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11455.json b/mne-python/source/doc/sphinxext/prs/11455.json new file mode 100644 index 0000000000000000000000000000000000000000..90c0716ea32020a9fd059d0d844ea5149891c2c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11455.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d021b91fbaa3abf3c3aafca5d826e30166421f9e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11457.json b/mne-python/source/doc/sphinxext/prs/11457.json new file mode 100644 index 0000000000000000000000000000000000000000..54e008270261d40db5cf20f0391492692cf52313 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11457.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5024b32782f7bf8e4dd944e57a3269c1b92d07d5", + "authors": [ + { + "n": "Zvi Baratz", + "e": "z.baratz@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11458.json b/mne-python/source/doc/sphinxext/prs/11458.json new file mode 100644 index 0000000000000000000000000000000000000000..de1f1a71365027555281180a85515407f9bd2649 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11458.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ae7ecf89f6d531e6b52ae69ea445be4a449de5e5", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "Alexandre Gramfort", + "e": "agramfort@fb.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/ssd.py": { + "a": 54, + "d": 9 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11459.json b/mne-python/source/doc/sphinxext/prs/11459.json new file mode 100644 index 0000000000000000000000000000000000000000..a6377ff13b59bcb2b75636b403cd28392e77901d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11459.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b8df1bd8c03ccf5c6f86a1173ba82f81874ae1b6", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/preprocessing/ieeg/_projection.py": { + "a": 6, + "d": 14 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11465.json b/mne-python/source/doc/sphinxext/prs/11465.json new file mode 100644 index 0000000000000000000000000000000000000000..9cf019d37873ede00775be480e9fc47eee0f96dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11465.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3e69d028d242fa4f5504c9b6c2750dc8e37120bb", + "authors": [ + { + "n": "HY Shin", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 10, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11467.json b/mne-python/source/doc/sphinxext/prs/11467.json new file mode 100644 index 0000000000000000000000000000000000000000..c1506d7cc13a62bf6be9df14b92a67f6e264cbd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11467.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "99bed94f837963bec5bafbca2a1b6a937a2126d3", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11469.json b/mne-python/source/doc/sphinxext/prs/11469.json new file mode 100644 index 0000000000000000000000000000000000000000..f01c7a062cbbec7f7fa611ce79ff012cdce58db7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11469.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "70119b6430afe22d480ba0f0ec39a6ee560a0c67", + "authors": [ + { + "n": "Sawradip Saha", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "agramfort@fb.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/sphinxext/unit_role.py": { + "a": 29, + "d": 0 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11470.json b/mne-python/source/doc/sphinxext/prs/11470.json new file mode 100644 index 0000000000000000000000000000000000000000..433af89f1dce2caaf184fa467142cbc4fd93acde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11470.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d740e47c8bbce81e6c0beda304748e606f20fc6c", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "janEbert", + "e": "janpublicebert@posteo.net" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 14, + "d": 12 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 11, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 0 + }, + "mne/viz/montage.py": { + "a": 5, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 34, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11471.json b/mne-python/source/doc/sphinxext/prs/11471.json new file mode 100644 index 0000000000000000000000000000000000000000..3afe2c712e713b52b3fc4d33c79ca0cd22b6f6c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11471.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c93c848f36219040de5fb9a8b8014472724e4143", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 3, + "d": 1 + }, + ".github/workflows/compat_old.yml": { + "a": 3, + "d": 1 + }, + ".github/workflows/linux_conda.yml": { + "a": 4, + "d": 2 + }, + ".github/workflows/macos_conda.yml": { + "a": 3, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11472.json b/mne-python/source/doc/sphinxext/prs/11472.json new file mode 100644 index 0000000000000000000000000000000000000000..31649b4e86f3e30a855b109cf684cac70bc27a32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11472.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "449ad99c4cdee96772afc843f7abda7ca27bfeee", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 10, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11473.json b/mne-python/source/doc/sphinxext/prs/11473.json new file mode 100644 index 0000000000000000000000000000000000000000..abb2cd73974fdade3708f4fe6e218c455aff12bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11473.json @@ -0,0 +1,811 @@ +{ + "merge_commit_sha": "5a97c2f0aa8afb53e63df1441fcda3508612364e", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/_freesurfer.py": { + "a": 50, + "d": 38 + }, + "mne/annotations.py": { + "a": 22, + "d": 16 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 10, + "d": 11 + }, + "mne/beamformer/tests/test_external.py": { + "a": 18, + "d": 18 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 12, + "d": 12 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 5, + "d": 6 + }, + "mne/beamformer/tests/test_resolution_matrix.py": { + "a": 13, + "d": 10 + }, + "mne/bem.py": { + "a": 36, + "d": 41 + }, + "mne/channels/channels.py": { + "a": 15, + "d": 11 + }, + "mne/channels/layout.py": { + "a": 34, + "d": 32 + }, + "mne/channels/montage.py": { + "a": 21, + "d": 20 + }, + "mne/channels/tests/test_channels.py": { + "a": 14, + "d": 18 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 9, + "d": 10 + }, + "mne/channels/tests/test_layout.py": { + "a": 22, + "d": 24 + }, + "mne/channels/tests/test_montage.py": { + "a": 49, + "d": 61 + }, + "mne/chpi.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 7, + "d": 5 + }, + "mne/commands/mne_setup_forward_model.py": { + "a": 2, + "d": 2 + }, + "mne/coreg.py": { + "a": 40, + "d": 39 + }, + "mne/cov.py": { + "a": 4, + "d": 4 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 3, + "d": 1 + }, + "mne/datasets/_infant/base.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/_phantom/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 11, + "d": 12 + }, + "mne/decoding/tests/test_csp.py": { + "a": 4, + "d": 5 + }, + "mne/decoding/tests/test_ems.py": { + "a": 5, + "d": 7 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 5, + "d": 5 + }, + "mne/dipole.py": { + "a": 9, + "d": 9 + }, + "mne/epochs.py": { + "a": 5, + "d": 4 + }, + "mne/event.py": { + "a": 15, + "d": 17 + }, + "mne/evoked.py": { + "a": 7, + "d": 5 + }, + "mne/export/_egimff.py": { + "a": 1, + "d": 1 + }, + "mne/export/_export.py": { + "a": 3, + "d": 3 + }, + "mne/export/tests/test_export.py": { + "a": 8, + "d": 9 + }, + "mne/forward/_field_interpolation.py": { + "a": 17, + "d": 7 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 4 + }, + "mne/forward/forward.py": { + "a": 53, + "d": 43 + }, + "mne/forward/tests/test_forward.py": { + "a": 23, + "d": 14 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 32, + "d": 29 + }, + "mne/gui/_core.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 20, + "d": 8 + }, + "mne/gui/tests/test_core.py": { + "a": 2, + "d": 3 + }, + "mne/gui/tests/test_coreg.py": { + "a": 46, + "d": 30 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 14, + "d": 15 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 6, + "d": 7 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 20, + "d": 13 + }, + "mne/io/array/tests/test_array.py": { + "a": 3, + "d": 3 + }, + "mne/io/artemis123/artemis123.py": { + "a": 4, + "d": 2 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 11, + "d": 14 + }, + "mne/io/base.py": { + "a": 6, + "d": 5 + }, + "mne/io/boxy/boxy.py": { + "a": 2, + "d": 2 + }, + "mne/io/boxy/tests/test_boxy.py": { + "a": 32, + "d": 17 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 43, + "d": 42 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 14, + "d": 15 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 1, + "d": 3 + }, + "mne/io/ctf/ctf.py": { + "a": 6, + "d": 5 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 58, + "d": 57 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 35, + "d": 37 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 37, + "d": 17 + }, + "mne/io/eeglab/eeglab.py": { + "a": 20, + "d": 15 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 42, + "d": 43 + }, + "mne/io/egi/egi.py": { + "a": 8, + "d": 6 + }, + "mne/io/egi/egimff.py": { + "a": 15, + "d": 5 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 18, + "d": 19 + }, + "mne/io/eximia/eximia.py": { + "a": 2, + "d": 2 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 2, + "d": 3 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 3, + "d": 3 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 19, + "d": 24 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 43, + "d": 40 + }, + "mne/io/fil/tests/test_fil.py": { + "a": 4, + "d": 7 + }, + "mne/io/hitachi/hitachi.py": { + "a": 3, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 31, + "d": 23 + }, + "mne/io/kit/kit.py": { + "a": 63, + "d": 136 + }, + "mne/io/kit/tests/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 4, + "d": 10 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 36, + "d": 36 + }, + "mne/io/nedf/nedf.py": { + "a": 1, + "d": 1 + }, + "mne/io/nedf/tests/test_nedf.py": { + "a": 1, + "d": 3 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 4, + "d": 6 + }, + "mne/io/nihon/nihon.py": { + "a": 3, + "d": 4 + }, + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 32, + "d": 27 + }, + "mne/io/persyst/persyst.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 21, + "d": 23 + }, + "mne/io/snirf/_snirf.py": { + "a": 2, + "d": 2 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 55, + "d": 25 + }, + "mne/io/tests/test_compensator.py": { + "a": 8, + "d": 7 + }, + "mne/io/tests/test_constants.py": { + "a": 8, + "d": 11 + }, + "mne/io/tests/test_meas_info.py": { + "a": 23, + "d": 21 + }, + "mne/io/tests/test_pick.py": { + "a": 26, + "d": 27 + }, + "mne/io/tests/test_proc_history.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_reference.py": { + "a": 8, + "d": 9 + }, + "mne/io/tests/test_show_fiff.py": { + "a": 5, + "d": 5 + }, + "mne/io/tests/test_what.py": { + "a": 7, + "d": 7 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 31, + "d": 28 + }, + "mne/minimum_norm/inverse.py": { + "a": 6, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 47, + "d": 53 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 7, + "d": 8 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 12, + "d": 9 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 8, + "d": 7 + }, + "mne/morph.py": { + "a": 14, + "d": 10 + }, + "mne/morph_map.py": { + "a": 11, + "d": 12 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/_regress.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 5, + "d": 7 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 51, + "d": 35 + }, + "mne/preprocessing/maxwell.py": { + "a": 5, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 12, + "d": 12 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 12, + "d": 9 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 6, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 12, + "d": 9 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/tests/test_annotate_nan.py": { + "a": 8, + "d": 3 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 6, + "d": 5 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 6, + "d": 9 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 28, + "d": 29 + }, + "mne/preprocessing/tests/test_interpolate.py": { + "a": 5, + "d": 6 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 112, + "d": 98 + }, + "mne/preprocessing/tests/test_otp.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 4, + "d": 6 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 5, + "d": 4 + }, + "mne/proj.py": { + "a": 2, + "d": 2 + }, + "mne/report/report.py": { + "a": 15, + "d": 8 + }, + "mne/report/tests/test_report.py": { + "a": 172, + "d": 146 + }, + "mne/simulation/raw.py": { + "a": 3, + "d": 1 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 25, + "d": 9 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 1, + "d": 5 + }, + "mne/simulation/tests/test_raw.py": { + "a": 30, + "d": 21 + }, + "mne/simulation/tests/test_source.py": { + "a": 9, + "d": 9 + }, + "mne/source_estimate.py": { + "a": 47, + "d": 44 + }, + "mne/source_space.py": { + "a": 31, + "d": 15 + }, + "mne/stats/tests/test_regression.py": { + "a": 3, + "d": 6 + }, + "mne/surface.py": { + "a": 10, + "d": 11 + }, + "mne/tests/test_annotations.py": { + "a": 14, + "d": 17 + }, + "mne/tests/test_bem.py": { + "a": 21, + "d": 21 + }, + "mne/tests/test_chpi.py": { + "a": 35, + "d": 30 + }, + "mne/tests/test_coreg.py": { + "a": 130, + "d": 74 + }, + "mne/tests/test_cov.py": { + "a": 10, + "d": 13 + }, + "mne/tests/test_dipole.py": { + "a": 31, + "d": 30 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 5, + "d": 7 + }, + "mne/tests/test_epochs.py": { + "a": 65, + "d": 70 + }, + "mne/tests/test_event.py": { + "a": 15, + "d": 15 + }, + "mne/tests/test_evoked.py": { + "a": 12, + "d": 16 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 5 + }, + "mne/tests/test_freesurfer.py": { + "a": 14, + "d": 13 + }, + "mne/tests/test_label.py": { + "a": 75, + "d": 80 + }, + "mne/tests/test_misc.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_morph.py": { + "a": 35, + "d": 33 + }, + "mne/tests/test_morph_map.py": { + "a": 9, + "d": 10 + }, + "mne/tests/test_proj.py": { + "a": 32, + "d": 31 + }, + "mne/tests/test_rank.py": { + "a": 13, + "d": 13 + }, + "mne/tests/test_read_vectorview_selection.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 92, + "d": 74 + }, + "mne/tests/test_source_space.py": { + "a": 40, + "d": 31 + }, + "mne/tests/test_surface.py": { + "a": 33, + "d": 41 + }, + "mne/tests/test_transforms.py": { + "a": 30, + "d": 27 + }, + "mne/time_frequency/csd.py": { + "a": 6, + "d": 6 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 8, + "d": 3 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 5, + "d": 5 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 10, + "d": 10 + }, + "mne/transforms.py": { + "a": 26, + "d": 16 + }, + "mne/utils/check.py": { + "a": 29, + "d": 22 + }, + "mne/utils/config.py": { + "a": 16, + "d": 15 + }, + "mne/utils/docs.py": { + "a": 57, + "d": 7 + }, + "mne/utils/tests/test_check.py": { + "a": 9, + "d": 9 + }, + "mne/utils/tests/test_config.py": { + "a": 3, + "d": 3 + }, + "mne/utils/tests/test_logging.py": { + "a": 8, + "d": 9 + }, + "mne/utils/tests/test_numerics.py": { + "a": 8, + "d": 9 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 5, + "d": 5 + }, + "mne/utils/tests/test_testing.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 46, + "d": 35 + }, + "mne/viz/_brain/_brain.py": { + "a": 14, + "d": 3 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 46, + "d": 39 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 13, + "d": 11 + }, + "mne/viz/_dipole.py": { + "a": 2, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 24, + "d": 18 + }, + "mne/viz/tests/test_3d.py": { + "a": 40, + "d": 36 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_evoked.py": { + "a": 8, + "d": 9 + }, + "mne/viz/tests/test_ica.py": { + "a": 7, + "d": 7 + }, + "mne/viz/tests/test_misc.py": { + "a": 19, + "d": 14 + }, + "mne/viz/tests/test_montage.py": { + "a": 10, + "d": 8 + }, + "mne/viz/tests/test_topo.py": { + "a": 7, + "d": 7 + }, + "mne/viz/tests/test_topomap.py": { + "a": 12, + "d": 12 + }, + "mne/viz/tests/test_utils.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11475.json b/mne-python/source/doc/sphinxext/prs/11475.json new file mode 100644 index 0000000000000000000000000000000000000000..ff1e809f3fc8b1679994e6cf856333149dfa40c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11475.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0dea13c2b3e6e9e90dbb5677be442eaf1203a180", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/ssd.py": { + "a": 40, + "d": 33 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11478.json b/mne-python/source/doc/sphinxext/prs/11478.json new file mode 100644 index 0000000000000000000000000000000000000000..6ba66b32fc2256111a16d21d314f922bfea073b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11478.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "62c5e42a4f5980576fe6a6ceca49c3e0aadd35a0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 0 + }, + "mne/conftest.py": { + "a": 3, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11479.json b/mne-python/source/doc/sphinxext/prs/11479.json new file mode 100644 index 0000000000000000000000000000000000000000..b67fdde10838229246bee65e026d700dd7afdde0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11479.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "dfdc5a61333495a575deedf8e773113e1e42a6cf", + "authors": [ + { + "n": "tomdstone", + "e": "77251489+tomdstone@users.noreply.github.com" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "Stone", + "e": "TASTONE@mgh.harvard.edu" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11485.json b/mne-python/source/doc/sphinxext/prs/11485.json new file mode 100644 index 0000000000000000000000000000000000000000..7d65ba43586b93f9032576d47951c037ec72dbc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11485.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4ee23004264b63ba2861ca70a4c777aee141de97", + "authors": [ + { + "n": "Zvi Baratz", + "e": "z.baratz@gmail.com" + } + ], + "changes": { + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11488.json b/mne-python/source/doc/sphinxext/prs/11488.json new file mode 100644 index 0000000000000000000000000000000000000000..73055986cab174ae0e02156fb8e5be2c81a30c0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11488.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ff48beee8f9da3493fc99c41c81e9baeb053f516", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11489.json b/mne-python/source/doc/sphinxext/prs/11489.json new file mode 100644 index 0000000000000000000000000000000000000000..68612ab1402251b2454d702afbfc4e6215c3ab34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11489.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "80dc73463d13a68cb0f7b6d13b993b03e07a57ac", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/gui/_core.py": { + "a": 14, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11491.json b/mne-python/source/doc/sphinxext/prs/11491.json new file mode 100644 index 0000000000000000000000000000000000000000..8f00839ea3c538344412df9cbc04c3a2cb5c715c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11491.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "18474b1d9227778ae875692a56f7e0927e856a54", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11493.json b/mne-python/source/doc/sphinxext/prs/11493.json new file mode 100644 index 0000000000000000000000000000000000000000..9a8930ddb0840c47e1f0040bddd3c8d797fbb266 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11493.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0cafb670d2285ce6a96627429c040b2ad9e4a60e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "tutorials/simulation/10_array_objs.py": { + "a": 47, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11496.json b/mne-python/source/doc/sphinxext/prs/11496.json new file mode 100644 index 0000000000000000000000000000000000000000..5d2a462ac800dd78e1eab3d912f3d47f7a117874 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11496.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "824259f5633b49c136bffd42dea1e1a2cc119882", + "authors": [ + { + "n": "Zvi Baratz", + "e": "z.baratz@gmail.com" + } + ], + "changes": { + "examples/simulation/simulate_evoked_data.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11497.json b/mne-python/source/doc/sphinxext/prs/11497.json new file mode 100644 index 0000000000000000000000000000000000000000..f188f3b5e148023bb4b5847595f8692b0d966ddf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11497.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2cf07038124f210d8b3f969d7657f52643fcc1f9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11498.json b/mne-python/source/doc/sphinxext/prs/11498.json new file mode 100644 index 0000000000000000000000000000000000000000..7bcaa5bc775af212eda1b532d3b081f28f2ba3b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11498.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "03961e4f5f82fd9529d84ef71c9ee3c74132f977", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11499.json b/mne-python/source/doc/sphinxext/prs/11499.json new file mode 100644 index 0000000000000000000000000000000000000000..eba572f549198cb9b46edbb8a7cb532ffa94afb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11499.json @@ -0,0 +1,299 @@ +{ + "merge_commit_sha": "603a96da58ddba3c2c05d3a01639abd669cc9543", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 4, + "d": 4 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 2 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_anonymize.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 4, + "d": 3 + }, + "mne/cuda.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 6, + "d": 5 + }, + "mne/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/filter.py": { + "a": 5, + "d": 5 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/_digitization.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/besa/besa.py": { + "a": 5, + "d": 5 + }, + "mne/io/boxy/boxy.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 6, + "d": 6 + }, + "mne/io/bti/bti.py": { + "a": 6, + "d": 6 + }, + "mne/io/cnt/cnt.py": { + "a": 23, + "d": 23 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/curry.py": { + "a": 8, + "d": 8 + }, + "mne/io/edf/edf.py": { + "a": 27, + "d": 26 + }, + "mne/io/eeglab/eeglab.py": { + "a": 6, + "d": 6 + }, + "mne/io/egi/egimff.py": { + "a": 3, + "d": 3 + }, + "mne/io/egi/events.py": { + "a": 2, + "d": 2 + }, + "mne/io/eximia/eximia.py": { + "a": 2, + "d": 2 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 4, + "d": 4 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/fil/fil.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 7, + "d": 7 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 5 + }, + "mne/io/nedf/nedf.py": { + "a": 2, + "d": 2 + }, + "mne/io/nicolet/nicolet.py": { + "a": 16, + "d": 16 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/open.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/persyst.py": { + "a": 2, + "d": 2 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/io/what.py": { + "a": 2, + "d": 2 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/misc.py": { + "a": 2, + "d": 2 + }, + "mne/morph.py": { + "a": 9, + "d": 8 + }, + "mne/parallel.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/maxfilter.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 2 + }, + "mne/proj.py": { + "a": 10, + "d": 10 + }, + "mne/rank.py": { + "a": 4, + "d": 4 + }, + "mne/simulation/metrics/metrics.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/source.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 13, + "d": 15 + }, + "mne/source_space.py": { + "a": 15, + "d": 14 + }, + "mne/surface.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/csd.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 6 + }, + "mne/transforms.py": { + "a": 3, + "d": 3 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1150.json b/mne-python/source/doc/sphinxext/prs/1150.json new file mode 100644 index 0000000000000000000000000000000000000000..a1ed3bef24f0bb3f88d4317e61d534fed0fabd93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1150.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "05af70db83b9e9f78dfc7b0ce9af0e471e138a2b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11500.json b/mne-python/source/doc/sphinxext/prs/11500.json new file mode 100644 index 0000000000000000000000000000000000000000..58865e51b07a2ecfaa077e5c676afcc6f0c7660d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11500.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0efe50b0e9ad44f863bd1e1aac145924f4c0bbfb", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 66, + "d": 21 + }, + "mne/channels/tests/test_layout.py": { + "a": 32, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11502.json b/mne-python/source/doc/sphinxext/prs/11502.json new file mode 100644 index 0000000000000000000000000000000000000000..5cce1fc7f25b6eab4c9239a0f36d77fd5a5ac970 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11502.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0e305ee75fed512e8af6eba33bf5570652fa5069", + "authors": [ + { + "n": "Moritz Gerster", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 10, + "d": 5 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 49, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11505.json b/mne-python/source/doc/sphinxext/prs/11505.json new file mode 100644 index 0000000000000000000000000000000000000000..11d2817e6dba305bf9fa000d6bbec190be297264 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11505.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6d3e41f888a72f99b436336e3dbf9dd39d1996a4", + "authors": [ + { + "n": "nmri-nfocke", + "e": "114056301+nmri-nfocke@users.noreply.github.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/egi/events.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11506.json b/mne-python/source/doc/sphinxext/prs/11506.json new file mode 100644 index 0000000000000000000000000000000000000000..a187a43d836d077d31f6b9fb8fd9b8880d5c6550 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11506.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ae0b34c08d68b7641a82428285e094267a6ac01c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/1.3.inc": { + "a": 9, + "d": 0 + }, + "doc/install/installers.rst": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1151.json b/mne-python/source/doc/sphinxext/prs/1151.json new file mode 100644 index 0000000000000000000000000000000000000000..ec4854c0966b9bbad100a564ebb24b5b98848e3d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1151.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "470ce0a4bf5e35c8699725917288306bdd9ad06d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11512.json b/mne-python/source/doc/sphinxext/prs/11512.json new file mode 100644 index 0000000000000000000000000000000000000000..edc9d2c03625b801bdb1d4fe7acddd5f4920a66f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11512.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e7d5226ae2599685112631e8ca5f203cf031d2c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/3d_to_2d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11517.json b/mne-python/source/doc/sphinxext/prs/11517.json new file mode 100644 index 0000000000000000000000000000000000000000..07b0549675f835dcb1d5aff297c0a6055839590d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11517.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3bf04edf744da89b1bb4f84cde5537758ed00865", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "Makefile": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 8, + "d": 1 + }, + "mne/_version.py": { + "a": 0, + "d": 6 + }, + "requirements_base.txt": { + "a": 2, + "d": 1 + }, + "setup.py": { + "a": 5, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11518.json b/mne-python/source/doc/sphinxext/prs/11518.json new file mode 100644 index 0000000000000000000000000000000000000000..cf8f8d3e1d7cecdff884ad846421cadeab7d569e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11518.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "866761249fa2b7fab7e6ce198d5226ebbeaacc9d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/linux_conda.yml": { + "a": 3, + "d": 1 + }, + "doc/install/advanced.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1152.json b/mne-python/source/doc/sphinxext/prs/1152.json new file mode 100644 index 0000000000000000000000000000000000000000..a4561d3ab0877a645ab23025c732ac9330e574c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1152.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e6b948dbd4afb4fd4f129e822f16f5d60a13bc92", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/index.rst": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11521.json b/mne-python/source/doc/sphinxext/prs/11521.json new file mode 100644 index 0000000000000000000000000000000000000000..6417c34296e9caafa56c6a9d0a321487d2de3ca1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11521.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "eb54bde2cc53f94b9cd253987937e3510a81f89f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 15, + "d": 3 + }, + "mne/io/tests/test_read_raw.py": { + "a": 25, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1153.json b/mne-python/source/doc/sphinxext/prs/1153.json new file mode 100644 index 0000000000000000000000000000000000000000..181fbef653a3e101e08996573946ce222044b968 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1153.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f8f7137f88eb8ba6e62ed0f03fda46b87b6afb0c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/index.rst": { + "a": 10, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11536.json b/mne-python/source/doc/sphinxext/prs/11536.json new file mode 100644 index 0000000000000000000000000000000000000000..9bfd58d69cc865101c7aba20f5eea079386b6562 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11536.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "295b7c7ee90ea341dab2cc497f7ec6d5eceb2770", + "authors": [ + { + "n": "George O'Neill", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 23, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 1 + }, + "mne/io/pick.py": { + "a": 5, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 16, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/hfc.py": { + "a": 100, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 4 + }, + "mne/preprocessing/tests/test_hfc.py": { + "a": 149, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + }, + "tutorials/preprocessing/80_opm_processing.py": { + "a": 64, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11537.json b/mne-python/source/doc/sphinxext/prs/11537.json new file mode 100644 index 0000000000000000000000000000000000000000..ce65a8949b0854b8dade190f57321ff16224ff64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11537.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fa618df07286e6be8177001bd23a91d76995e085", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11538.json b/mne-python/source/doc/sphinxext/prs/11538.json new file mode 100644 index 0000000000000000000000000000000000000000..5dcb3e6490530d158f9eb75334f0b016d88ec153 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11538.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "43979006d6236d3c9da27fdbe233f9b6fa450f04", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1154.json b/mne-python/source/doc/sphinxext/prs/1154.json new file mode 100644 index 0000000000000000000000000000000000000000..5e74a0a85002a7f51c2622a4943f545985e60fbd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1154.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c23486285c2daa9f831c25a64444b5383449435e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/index.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11541.json b/mne-python/source/doc/sphinxext/prs/11541.json new file mode 100644 index 0000000000000000000000000000000000000000..9e8bf952f2923a92c1d5b2edc23e82965e01ea82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11541.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "8325f8082afd1d0d836585e77e01fcf600fd348c", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 0, + "d": 45 + }, + ".github/workflows/precommit.yml": { + "a": 14, + "d": 0 + }, + ".gitignore": { + "a": 1, + "d": 1 + }, + ".pre-commit-config.yaml": { + "a": 36, + "d": 0 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "Makefile": { + "a": 6, + "d": 89 + }, + "azure-pipelines.yml": { + "a": 5, + "d": 14 + }, + "doc/install/contributing.rst": { + "a": 10, + "d": 6 + }, + "examples/simulation/simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/simulated_raw_data_using_subject_anatomy.py": { + "a": 1, + "d": 2 + }, + "examples/visualization/topo_customized.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/tests/test_resolution_matrix.py": { + "a": 2, + "d": 2 + }, + "mne/chpi.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 4, + "d": 1 + }, + "mne/utils/check.py": { + "a": 1, + "d": 0 + }, + "pyproject.toml": { + "a": 50, + "d": 0 + }, + "requirements_testing.txt": { + "a": 2, + "d": 3 + }, + "setup.cfg": { + "a": 0, + "d": 42 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11547.json b/mne-python/source/doc/sphinxext/prs/11547.json new file mode 100644 index 0000000000000000000000000000000000000000..95b7ea41d56d555583300da31435b2bff6ad2529 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11547.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bf2502166eb15626c1205accc2d2d467535b8d93", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/0.24.inc": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11549.json b/mne-python/source/doc/sphinxext/prs/11549.json new file mode 100644 index 0000000000000000000000000000000000000000..ea33954d5a0f1c73d01aebdc2d503d49ea0a6ee0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11549.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "21efb09059c03c6bd964d5e01a5833c05a8865c7", + "authors": [ + { + "n": "Simon Kern", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 64, + "d": 17 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 46, + "d": 1 + }, + "mne/io/utils.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11550.json b/mne-python/source/doc/sphinxext/prs/11550.json new file mode 100644 index 0000000000000000000000000000000000000000..a9554fc32edff12eb9cc8f0328e65cb042514c2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11550.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "132d1da7a3bebbb265fc5b23c440abacbfd33de2", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 2, + "d": 2 + }, + ".github/workflows/compat_old.yml": { + "a": 3, + "d": 3 + }, + "README.rst": { + "a": 3, + "d": 2 + }, + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + }, + "doc/install/manual_install_python.rst": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 8, + "d": 7 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "requirements_base.txt": { + "a": 1, + "d": 2 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11555.json b/mne-python/source/doc/sphinxext/prs/11555.json new file mode 100644 index 0000000000000000000000000000000000000000..d9667aad75a40d3fed24d184ce3a566c1854b6d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11555.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ecae0576c838f18d3ceae00e2268412356580135", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 28, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11556.json b/mne-python/source/doc/sphinxext/prs/11556.json new file mode 100644 index 0000000000000000000000000000000000000000..c92769b3f3c3fa3125e612cd7b3b307fbaa36670 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11556.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c461bad33dc953048f895ecc3aaea69208181024", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 15, + "d": 4 + }, + "mne/time_frequency/spectrum.py": { + "a": 11, + "d": 4 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 69, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11557.json b/mne-python/source/doc/sphinxext/prs/11557.json new file mode 100644 index 0000000000000000000000000000000000000000..99ff93eb7a303a9b562201baf84d4b59f8b00da6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11557.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "29e99c85da5e192a402528ffc5500b17d0281334", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 19, + "d": 11 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_base.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 13, + "d": 153 + }, + "mne/surface.py": { + "a": 13, + "d": 33 + }, + "mne/tests/test_annotations.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 0 + }, + "mne/utils/check.py": { + "a": 0, + "d": 6 + }, + "mne/utils/numerics.py": { + "a": 2, + "d": 3 + }, + "mne/utils/tests/test_linalg.py": { + "a": 2, + "d": 8 + }, + "mne/utils/tests/test_numerics.py": { + "a": 1, + "d": 3 + }, + "mne/viz/_brain/_scraper.py": { + "a": 1, + "d": 6 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 3, + "d": 2 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11558.json b/mne-python/source/doc/sphinxext/prs/11558.json new file mode 100644 index 0000000000000000000000000000000000000000..d78fde710b7a2d831608197352f26b5cc993b97d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11558.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f628e191912066ca375f920e5a92a9674d85d804", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 10, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1156.json b/mne-python/source/doc/sphinxext/prs/1156.json new file mode 100644 index 0000000000000000000000000000000000000000..004d811dd6204e55b7b11f40d29e35c6f6fe102c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1156.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3adb1b81108156fc78d299a1707af7215c95498e", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/epochs.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11562.json b/mne-python/source/doc/sphinxext/prs/11562.json new file mode 100644 index 0000000000000000000000000000000000000000..a88e83c5fb6b046413ce959c2d555c6fb5fcaf9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11562.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7fb3ef2338b9e4684b03d7f171ef62ad2ffc9c53", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 18, + "d": 12 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 7, + "d": 5 + }, + "mne/tests/test_import_nesting.py": { + "a": 10, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11563.json b/mne-python/source/doc/sphinxext/prs/11563.json new file mode 100644 index 0000000000000000000000000000000000000000..5ccb497fd3170947d515b33cded9da6046a4070b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11563.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "2bd0c3ee25606fc1e755fe589b0cc6bf409d3f84", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "examples/datasets/brainstorm_data.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/sensor_noise_level.py": { + "a": 2, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 5, + "d": 4 + }, + "mne/report/report.py": { + "a": 13, + "d": 4 + }, + "mne/report/tests/test_report.py": { + "a": 3, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 9, + "d": 46 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 15, + "d": 0 + }, + "mne/utils/spectrum.py": { + "a": 63, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 11 + }, + "mne/viz/raw.py": { + "a": 6, + "d": 14 + }, + "mne/viz/tests/test_epochs.py": { + "a": 18, + "d": 16 + }, + "mne/viz/tests/test_raw.py": { + "a": 25, + "d": 31 + }, + "mne/viz/topomap.py": { + "a": 12, + "d": 10 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 6, + "d": 4 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/15_inplace.py": { + "a": 3, + "d": 3 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 3, + "d": 5 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 9, + "d": 6 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 6, + "d": 8 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11566.json b/mne-python/source/doc/sphinxext/prs/11566.json new file mode 100644 index 0000000000000000000000000000000000000000..13634b7ead3d96bd5929ddc5b2543898c5bc3605 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11566.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6384a8901182272c48f3e72a10142ea75184f47f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 2, + "d": 1 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11567.json b/mne-python/source/doc/sphinxext/prs/11567.json new file mode 100644 index 0000000000000000000000000000000000000000..db9861782b76b970bb0b9d9864d25b1936389e41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11567.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "5ca0141f6bd9db9be98e94e7362e2103471487d2", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/mri.rst": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/locate_ieeg_micro.py": { + "a": 94, + "d": 0 + }, + "mne/conftest.py": { + "a": 9, + "d": 8 + }, + "mne/gui/__init__.py": { + "a": 7, + "d": 5 + }, + "mne/gui/_core.py": { + "a": 152, + "d": 101 + }, + "mne/gui/_ieeg_locate.py": { + "a": 37, + "d": 17 + }, + "mne/gui/tests/test_core.py": { + "a": 6, + "d": 3 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 15, + "d": 10 + }, + "mne/surface.py": { + "a": 10, + "d": 5 + }, + "mne/tests/test_transforms.py": { + "a": 12, + "d": 0 + }, + "mne/transforms.py": { + "a": 83, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 4, + "d": 3 + }, + "mne/viz/backends/_utils.py": { + "a": 4, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11568.json b/mne-python/source/doc/sphinxext/prs/11568.json new file mode 100644 index 0000000000000000000000000000000000000000..3cbdb7e1fdf802b792924a0e0405bff4743794ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11568.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "417a9c4e17e28f613e45e6ce45c24cafb7152b25", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 5, + "d": 5 + }, + "mne/commands/mne_sys_info.py": { + "a": 8, + "d": 1 + }, + "mne/utils/config.py": { + "a": 76, + "d": 67 + }, + "requirements_base.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11569.json b/mne-python/source/doc/sphinxext/prs/11569.json new file mode 100644 index 0000000000000000000000000000000000000000..2699d163c419abb6a786c7320efcb3ff7bb6c812 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11569.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5238cf7ccba5b5c14caaa76904dfacc22919cdcb", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 8, + "d": 4 + }, + "mne/export/tests/test_export.py": { + "a": 18, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11572.json b/mne-python/source/doc/sphinxext/prs/11572.json new file mode 100644 index 0000000000000000000000000000000000000000..354272a1468418abcee88bcd2af8865cc52ee61e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11572.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "df2cf84d8f4ed22aa897b78df9182984c499d8cb", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/0.24.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/mri.rst": { + "a": 0, + "d": 1 + }, + "doc/preprocessing.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ieeg/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ieeg/_volume.py": { + "a": 219, + "d": 0 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/ieeg/tests/test_volume.py": { + "a": 105, + "d": 0 + }, + "mne/surface.py": { + "a": 7, + "d": 14 + }, + "mne/tests/test_surface.py": { + "a": 20, + "d": 21 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 13, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11574.json b/mne-python/source/doc/sphinxext/prs/11574.json new file mode 100644 index 0000000000000000000000000000000000000000..e210264216052e98ed88c836fd425594ee4d9681 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11574.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e6b025309b0dfc5c6881dceaf398b4be37125a57", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_spectrum.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11575.json b/mne-python/source/doc/sphinxext/prs/11575.json new file mode 100644 index 0000000000000000000000000000000000000000..07eacba20601e88caf222c484ba81e3c2f744849 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11575.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "52a42e2d5993232ce268155a8c002428ff046cae", + "authors": [ + { + "n": "Joshua Calder-Travis", + "e": null + } + ], + "changes": { + "mne/stats/tests/test_permutations.py": { + "a": 19, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11577.json b/mne-python/source/doc/sphinxext/prs/11577.json new file mode 100644 index 0000000000000000000000000000000000000000..e09cee6153a69b8eff8fe5149493682a403cd16d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11577.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "367ed0ad708681c787b2088a4050352e46837c8d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 5, + "d": 5 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 0 + }, + "mne/utils/config.py": { + "a": 13, + "d": 12 + }, + "mne/utils/tests/test_config.py": { + "a": 14, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11578.json b/mne-python/source/doc/sphinxext/prs/11578.json new file mode 100644 index 0000000000000000000000000000000000000000..d4bbd457704a63984649ef71a9ab401feea7ac42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11578.json @@ -0,0 +1,187 @@ +{ + "merge_commit_sha": "6ccd1123ed10cdda2a34d0d4104fbad8f9bae23f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 1, + "d": 2 + }, + "mne/_freesurfer.py": { + "a": 7, + "d": 22 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 6, + "d": 6 + }, + "mne/commands/tests/test_commands.py": { + "a": 4, + "d": 3 + }, + "mne/coreg.py": { + "a": 2, + "d": 6 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 5, + "d": 4 + }, + "mne/gui/_core.py": { + "a": 2, + "d": 2 + }, + "mne/gui/tests/test_core.py": { + "a": 3, + "d": 3 + }, + "mne/gui/tests/test_coreg.py": { + "a": 3, + "d": 0 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 2, + "d": 1 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 3, + "d": 5 + }, + "mne/morph.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 2, + "d": 3 + }, + "mne/report/tests/test_report.py": { + "a": 7, + "d": 6 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/simulation/tests/test_source.py": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 5 + }, + "mne/source_space.py": { + "a": 2, + "d": 6 + }, + "mne/surface.py": { + "a": 2, + "d": 5 + }, + "mne/tests/test_bem.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_coreg.py": { + "a": 15, + "d": 14 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_freesurfer.py": { + "a": 5, + "d": 6 + }, + "mne/tests/test_label.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_morph.py": { + "a": 15, + "d": 15 + }, + "mne/tests/test_morph_map.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 9, + "d": 9 + }, + "mne/tests/test_source_space.py": { + "a": 11, + "d": 8 + }, + "mne/tests/test_surface.py": { + "a": 4, + "d": 6 + }, + "mne/tests/test_transforms.py": { + "a": 2, + "d": 4 + }, + "mne/transforms.py": { + "a": 4, + "d": 4 + }, + "mne/utils/__init__.py": { + "a": 4, + "d": 4 + }, + "mne/utils/_testing.py": { + "a": 0, + "d": 45 + }, + "mne/utils/check.py": { + "a": 9, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 2, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 3 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 11, + "d": 4 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 7, + "d": 8 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 5, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11582.json b/mne-python/source/doc/sphinxext/prs/11582.json new file mode 100644 index 0000000000000000000000000000000000000000..92b52d00f04f783228878cfa3a6edc333629d1d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11582.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "b921c8904ac752061a4698132d4da0d3164278c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 4 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 5, + "d": 0 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 2, + "d": 9 + }, + "mne/label.py": { + "a": 2, + "d": 10 + }, + "mne/morph.py": { + "a": 0, + "d": 4 + }, + "mne/report/report.py": { + "a": 1, + "d": 6 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 2, + "d": 5 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 7 + }, + "mne/simulation/tests/test_source.py": { + "a": 0, + "d": 7 + }, + "mne/source_space.py": { + "a": 2, + "d": 8 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 2, + "d": 6 + }, + "mne/stats/tests/test_permutations.py": { + "a": 0, + "d": 5 + }, + "mne/tests/test_coreg.py": { + "a": 13, + "d": 14 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 10 + }, + "mne/tests/test_label.py": { + "a": 3, + "d": 14 + }, + "mne/tests/test_source_space.py": { + "a": 7, + "d": 18 + }, + "mne/utils/check.py": { + "a": 6, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11583.json b/mne-python/source/doc/sphinxext/prs/11583.json new file mode 100644 index 0000000000000000000000000000000000000000..bb0b8ae74f1546e9aebd848a76a3a89ffc20f048 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11583.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1033764b80ef6154d8905b7b01113079991d78c8", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 0, + "d": 7 + }, + "mne/simulation/metrics/metrics.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11584.json b/mne-python/source/doc/sphinxext/prs/11584.json new file mode 100644 index 0000000000000000000000000000000000000000..3bde787a515b0d9603701cc9c32ac8082894cafa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11584.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9475b278dedcaef42ba129058cd9bc7a6f18c4ac", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11585.json b/mne-python/source/doc/sphinxext/prs/11585.json new file mode 100644 index 0000000000000000000000000000000000000000..8f7cf94bf28c92bbbbf5cdf4c100bf0db94cc2fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11585.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "51e0b2553a2757a822d0f10f42c236ab4e6faf23", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11586.json b/mne-python/source/doc/sphinxext/prs/11586.json new file mode 100644 index 0000000000000000000000000000000000000000..dc06a04a8236f7da472dd146381bcb608210a637 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11586.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a9a5866ba6aa35c877d7188af625a880980fc0b", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "doc/_static/institution_logos/CEA.png": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11587.json b/mne-python/source/doc/sphinxext/prs/11587.json new file mode 100644 index 0000000000000000000000000000000000000000..afaa6da6b9bde875ec2b6b6d10e49371a04d6d5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11587.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7d389814213b1f2c9e67c5af4049ee1b07654744", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1159.json b/mne-python/source/doc/sphinxext/prs/1159.json new file mode 100644 index 0000000000000000000000000000000000000000..2d6f1ef6f06a9b82473df6e283390ab139357b4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1159.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9dbda572f0184f83eeb06ae276fd256337c420de", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 5, + "d": 6 + }, + "mne/gui/_file_traits.py": { + "a": 147, + "d": 59 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 0, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11591.json b/mne-python/source/doc/sphinxext/prs/11591.json new file mode 100644 index 0000000000000000000000000000000000000000..1a80a359fa45e6720b8f45920691af6cfe2f6522 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11591.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "17f0dab46d0bd213965cdd222150eba973d32de0", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/boxy/boxy.py": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/curry/curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 4, + "d": 4 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/eximia/eximia.py": { + "a": 2, + "d": 2 + }, + "mne/io/fil/fil.py": { + "a": 2, + "d": 2 + }, + "mne/io/hitachi/hitachi.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 3 + }, + "mne/io/nedf/nedf.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 2, + "d": 2 + }, + "mne/io/nihon/nihon.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/persyst.py": { + "a": 2, + "d": 2 + }, + "mne/io/snirf/_snirf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11592.json b/mne-python/source/doc/sphinxext/prs/11592.json new file mode 100644 index 0000000000000000000000000000000000000000..29bcd847eca3988f2829925f087af31a0156aa93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11592.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "1a339ee065afab491cc950fea45ff39552985c58", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/boxy/boxy.py": { + "a": 2, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 2, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 1 + }, + "mne/io/curry/curry.py": { + "a": 5, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 7, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 2, + "d": 1 + }, + "mne/io/eximia/eximia.py": { + "a": 2, + "d": 1 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 5, + "d": 0 + }, + "mne/io/fil/fil.py": { + "a": 4, + "d": 2 + }, + "mne/io/hitachi/hitachi.py": { + "a": 2, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 1 + }, + "mne/io/nedf/nedf.py": { + "a": 2, + "d": 1 + }, + "mne/io/nihon/nihon.py": { + "a": 2, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 1 + }, + "mne/io/persyst/persyst.py": { + "a": 2, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11594.json b/mne-python/source/doc/sphinxext/prs/11594.json new file mode 100644 index 0000000000000000000000000000000000000000..47de7e418ada671c8bf29bf511367a9933a92942 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11594.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3d9af0fe6ecc0444932338ab083f06b194a5d9f3", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + ".github/config.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11595.json b/mne-python/source/doc/sphinxext/prs/11595.json new file mode 100644 index 0000000000000000000000000000000000000000..ba991d3b5de0464a9eb7a661985d85cba1c12334 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11595.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c4c9347e3ec6ee5b52f3470120fee68867277222", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11596.json b/mne-python/source/doc/sphinxext/prs/11596.json new file mode 100644 index 0000000000000000000000000000000000000000..54c717987dfdccfcf8144cfeb293f1e411b0055b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11596.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4b419e03e36bae756af00f90c2c1a3cd6d7c20e1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/preprocessing/contralateral_referencing.py": { + "a": 71, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11599.json b/mne-python/source/doc/sphinxext/prs/11599.json new file mode 100644 index 0000000000000000000000000000000000000000..97db8f50c25575c739aa6ba1d8081cf5c329317f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11599.json @@ -0,0 +1,1315 @@ +{ + "merge_commit_sha": "623895d0fd8894196ca638ad10ddccc98d488b4c", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 0, + "d": 2 + }, + "doc/sphinxext/flow_diagram.py": { + "a": 0, + "d": 2 + }, + "doc/sphinxext/gen_commands.py": { + "a": 0, + "d": 2 + }, + "doc/sphinxext/gen_names.py": { + "a": 0, + "d": 2 + }, + "doc/sphinxext/gh_substitutions.py": { + "a": 0, + "d": 2 + }, + "doc/sphinxext/newcontrib_substitutions.py": { + "a": 0, + "d": 2 + }, + "examples/datasets/brainstorm_data.py": { + "a": 0, + "d": 1 + }, + "examples/datasets/hf_sef_data.py": { + "a": 0, + "d": 1 + }, + "examples/datasets/limo_data.py": { + "a": 0, + "d": 1 + }, + "examples/datasets/opm_data.py": { + "a": 0, + "d": 1 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/ems_filtering.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 0, + "d": 1 + }, + "examples/forward/forward_sensitivity_maps.py": { + "a": 0, + "d": 1 + }, + "examples/forward/left_cerebellum_volume_source.py": { + "a": 0, + "d": 1 + }, + "examples/forward/source_space_morphing.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/compute_mne_inverse_epochs_in_label.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/compute_mne_inverse_raw_in_label.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/custom_inverse_solver.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/dics_epochs.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/dics_source_power.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/gamma_map_inverse.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/label_activation_from_stc.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/label_from_stc.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/label_source_activations.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/mne_cov_power.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/morph_surface_stc.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/multi_dipole_model.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/multidict_reweighted_tfmxne.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/psf_ctf_vertices.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/psf_ctf_vertices_lcmv.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/psf_volume.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/rap_music.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/read_inverse.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/read_stc.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/resolution_metrics.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/resolution_metrics_eegmeg.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/snr_estimate.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/source_space_snr.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/vector_mne_solution.py": { + "a": 0, + "d": 1 + }, + "examples/io/elekta_epochs.py": { + "a": 0, + "d": 1 + }, + "examples/io/read_neo_format.py": { + "a": 0, + "d": 1 + }, + "examples/io/read_noise_covariance_matrix.py": { + "a": 0, + "d": 1 + }, + "examples/io/read_xdf.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/css.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/define_target_events.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/eog_regression.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/fnirs_artifact_removal.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/ica_comparison.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/interpolate_bad_channels.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/locate_ieeg_micro.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/movement_compensation.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/movement_detection.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/muscle_detection.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/otp.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/shift_evoked.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/virtual_evoked.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/xdawn_denoising.py": { + "a": 0, + "d": 1 + }, + "examples/simulation/simulate_evoked_data.py": { + "a": 0, + "d": 1 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 0, + "d": 1 + }, + "examples/simulation/simulated_raw_data_using_subject_anatomy.py": { + "a": 0, + "d": 1 + }, + "examples/simulation/source_simulator.py": { + "a": 0, + "d": 1 + }, + "examples/stats/cluster_stats_evoked.py": { + "a": 0, + "d": 1 + }, + "examples/stats/fdr_stats_evoked.py": { + "a": 0, + "d": 1 + }, + "examples/stats/linear_regression_raw.py": { + "a": 0, + "d": 1 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 0, + "d": 1 + }, + "examples/stats/sensor_regression.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/compute_csd.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/compute_source_psd_epochs.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/source_power_spectrum.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/source_space_time_frequency.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/temporal_whitening.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/3d_to_2d.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/brain.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/channel_epochs_image.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/evoked_arrowmap.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/evoked_topomap.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/evoked_whitening.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/meg_sensors.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/mne_helmet.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/montage_sgskip.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/parcellation.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/publication_figure.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/roi_erpimage_by_rt.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/sensor_noise_level.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/ssp_projs_sensitivity_map.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/topo_compare_conditions.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/topo_customized.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/xhemi.py": { + "a": 0, + "d": 1 + }, + "logo/generate_mne_logos.py": { + "a": 0, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 0, + "d": 1 + }, + "mne/_ola.py": { + "a": 0, + "d": 1 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 0, + "d": 1 + }, + "mne/beamformer/tests/test_resolution_matrix.py": { + "a": 0, + "d": 1 + }, + "mne/chpi.py": { + "a": 0, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 0, + "d": 1 + }, + "mne/conftest.py": { + "a": 0, + "d": 1 + }, + "mne/coreg.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/_infant/base.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/_phantom/base.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/mixin.py": { + "a": 0, + "d": 2 + }, + "mne/decoding/receptive_field.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 0, + "d": 1 + }, + "mne/dipole.py": { + "a": 0, + "d": 1 + }, + "mne/epochs.py": { + "a": 0, + "d": 2 + }, + "mne/evoked.py": { + "a": 0, + "d": 1 + }, + "mne/export/_brainvision.py": { + "a": 0, + "d": 1 + }, + "mne/export/_edf.py": { + "a": 0, + "d": 1 + }, + "mne/export/_eeglab.py": { + "a": 0, + "d": 1 + }, + "mne/export/_egimff.py": { + "a": 0, + "d": 1 + }, + "mne/export/_export.py": { + "a": 0, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 0, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 0, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 0, + "d": 1 + }, + "mne/gui/_core.py": { + "a": 0, + "d": 1 + }, + "mne/gui/_ieeg_locate.py": { + "a": 0, + "d": 1 + }, + "mne/gui/tests/test_core.py": { + "a": 0, + "d": 1 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 0, + "d": 1 + }, + "mne/io/_digitization.py": { + "a": 0, + "d": 1 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 0, + "d": 1 + }, + "mne/io/base.py": { + "a": 0, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 0, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 0, + "d": 1 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 0, + "d": 1 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 0, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/events.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/general.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 0, + "d": 1 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 0, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 0, + "d": 1 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 0, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 0, + "d": 1 + }, + "mne/io/nedf/nedf.py": { + "a": 0, + "d": 1 + }, + "mne/io/nedf/tests/test_nedf.py": { + "a": 0, + "d": 1 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 0, + "d": 1 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 0, + "d": 1 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 0, + "d": 1 + }, + "mne/io/open.py": { + "a": 0, + "d": 1 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 0, + "d": 1 + }, + "mne/io/pick.py": { + "a": 0, + "d": 1 + }, + "mne/io/proc_history.py": { + "a": 0, + "d": 1 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 0, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 0, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 0, + "d": 1 + }, + "mne/io/tests/test_show_fiff.py": { + "a": 0, + "d": 1 + }, + "mne/io/tests/test_utils.py": { + "a": 0, + "d": 1 + }, + "mne/io/tests/test_write.py": { + "a": 0, + "d": 1 + }, + "mne/io/utils.py": { + "a": 0, + "d": 1 + }, + "mne/io/what.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/ieeg/tests/test_volume.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/otp.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/realign.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 0, + "d": 1 + }, + "mne/rank.py": { + "a": 0, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 0, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 0, + "d": 1 + }, + "mne/stats/_adjacency.py": { + "a": 0, + "d": 2 + }, + "mne/stats/cluster_level.py": { + "a": 0, + "d": 1 + }, + "mne/stats/tests/test_adjacency.py": { + "a": 0, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_parallel.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 0, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 0, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 0, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 0, + "d": 1 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 0, + "d": 1 + }, + "mne/transforms.py": { + "a": 0, + "d": 1 + }, + "mne/utils/_bunch.py": { + "a": 0, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 0, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 0, + "d": 1 + }, + "mne/utils/check.py": { + "a": 0, + "d": 1 + }, + "mne/utils/config.py": { + "a": 0, + "d": 1 + }, + "mne/utils/dataframe.py": { + "a": 0, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 1 + }, + "mne/utils/fetching.py": { + "a": 0, + "d": 1 + }, + "mne/utils/linalg.py": { + "a": 0, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 0, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 0, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 0, + "d": 1 + }, + "mne/utils/progressbar.py": { + "a": 0, + "d": 1 + }, + "mne/utils/tests/test_bunch.py": { + "a": 0, + "d": 1 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 0, + "d": 1 + }, + "mne/utils/tests/test_testing.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_3d_overlay.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_dipole.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 0, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 0, + "d": 1 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 0, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 0, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 0, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 0, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 0, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 0, + "d": 1 + }, + "tutorials/clinical/60_sleep.py": { + "a": 0, + "d": 1 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 0, + "d": 1 + }, + "tutorials/epochs/15_baseline_regression.py": { + "a": 0, + "d": 1 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 0, + "d": 1 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 0, + "d": 1 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 0, + "d": 1 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 0, + "d": 1 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 0, + "d": 1 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 0, + "d": 1 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 0, + "d": 1 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 0, + "d": 1 + }, + "tutorials/evoked/40_whitened.py": { + "a": 0, + "d": 1 + }, + "tutorials/forward/10_background_freesurfer.py": { + "a": 0, + "d": 1 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 0, + "d": 1 + }, + "tutorials/forward/25_automated_coreg.py": { + "a": 0, + "d": 1 + }, + "tutorials/forward/30_forward.py": { + "a": 0, + "d": 1 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 0, + "d": 1 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 0, + "d": 1 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 0, + "d": 1 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 0, + "d": 1 + }, + "tutorials/intro/10_overview.py": { + "a": 0, + "d": 1 + }, + "tutorials/intro/15_inplace.py": { + "a": 0, + "d": 1 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 0, + "d": 1 + }, + "tutorials/intro/30_info.py": { + "a": 0, + "d": 1 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 0, + "d": 1 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 0, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/10_stc_class.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/40_mne_fixed_free.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 0, + "d": 1 + }, + "tutorials/io/10_reading_meg_data.py": { + "a": 0, + "d": 1 + }, + "tutorials/io/20_reading_eeg_data.py": { + "a": 0, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 0, + "d": 1 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 0, + "d": 1 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 0, + "d": 1 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/80_opm_processing.py": { + "a": 0, + "d": 1 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 0, + "d": 1 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 0, + "d": 1 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 0, + "d": 1 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 0, + "d": 1 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 0, + "d": 1 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 0, + "d": 1 + }, + "tutorials/simulation/80_dics.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-sensor-space/70_cluster_rmANOVA_time_freq.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 0, + "d": 1 + }, + "tutorials/time-freq/10_spectrum_class.py": { + "a": 0, + "d": 1 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 0, + "d": 1 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/116.json b/mne-python/source/doc/sphinxext/prs/116.json new file mode 100644 index 0000000000000000000000000000000000000000..074f054da4530d7387716ee53cbd276fb6c412ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/116.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e0e1f9cff35c025f7cdc261a71bf0cc4f1b196da", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 6, + "d": 4 + }, + "mne/fiff/tests/data/test-eve-1.eve": { + "a": 1, + "d": 0 + }, + "mne/fiff/tests/data/test-eve-1.fif": { + "a": 0, + "d": 0 + }, + "mne/fiff/tests/data/test-eve-old-style.eve": { + "a": 0, + "d": 1 + }, + "mne/fiff/tests/data/test-eve.eve": { + "a": 0, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 21, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11600.json b/mne-python/source/doc/sphinxext/prs/11600.json new file mode 100644 index 0000000000000000000000000000000000000000..678e5090779a21ea8b87a7174e220b4e13b4f479 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11600.json @@ -0,0 +1,195 @@ +{ + "merge_commit_sha": "84259a673caafc3dfb37e07e9d73a3593c5c6acf", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "mne/_freesurfer.py": { + "a": 4, + "d": 4 + }, + "mne/annotations.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 10, + "d": 10 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/res4.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 3, + "d": 3 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 5, + "d": 5 + }, + "mne/source_space.py": { + "a": 3, + "d": 3 + }, + "mne/surface.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_morph.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 3, + "d": 3 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_check.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11601.json b/mne-python/source/doc/sphinxext/prs/11601.json new file mode 100644 index 0000000000000000000000000000000000000000..1d9f8f834f8ef9bd523409a06a63e6dddd03e335 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11601.json @@ -0,0 +1,187 @@ +{ + "merge_commit_sha": "bde717c01d9d4eaa21233685b9ea4017b54a5a0c", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "mne/_ola.py": { + "a": 2, + "d": 2 + }, + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/mixin.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/open.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + }, + "mne/utils/_bunch.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 2, + "d": 2 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 2, + "d": 2 + }, + "mne/utils/mixin.py": { + "a": 4, + "d": 4 + }, + "mne/utils/numerics.py": { + "a": 2, + "d": 2 + }, + "mne/utils/progressbar.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d_overlay.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_scraper.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/callback.py": { + "a": 5, + "d": 5 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11604.json b/mne-python/source/doc/sphinxext/prs/11604.json new file mode 100644 index 0000000000000000000000000000000000000000..74faabea5f16c35d3a63d2abf484b27e7373fbb0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11604.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "267967920ac384cd8698f65670bfb9c2e8720a49", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/io/open.py": { + "a": 1, + "d": 1 + }, + "mne/io/proc_history.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 6, + "d": 6 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/colormap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 3, + "d": 3 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11606.json b/mne-python/source/doc/sphinxext/prs/11606.json new file mode 100644 index 0000000000000000000000000000000000000000..c4125d82bbaf469571153a5f2c80e7dffb09bb86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11606.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6de2197a8c59f5b132c4769ff66706f1720c9d56", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11607.json b/mne-python/source/doc/sphinxext/prs/11607.json new file mode 100644 index 0000000000000000000000000000000000000000..b3fec26317294e01528d307c2263bdcc92f9d8e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11607.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3b4930abd32c00dc71da6c4a3e56a850a34ba185", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 31, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 11, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11612.json b/mne-python/source/doc/sphinxext/prs/11612.json new file mode 100644 index 0000000000000000000000000000000000000000..5f258d20643c312be22383a815d6a9c37e28c430 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11612.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "686857c55288ed91cc13cdc43bf100ab1f6c475d", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/transforms.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11614.json b/mne-python/source/doc/sphinxext/prs/11614.json new file mode 100644 index 0000000000000000000000000000000000000000..0c413fcb0e57b71553c3ca67b85c96f62658be44 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11614.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "bfc8a3c471d271e3d31b7696fc0f9465a262223d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 7, + "d": 3 + }, + "mne/time_frequency/spectrum.py": { + "a": 3, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 3 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 12, + "d": 2 + }, + "mne/viz/backends/_utils.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11616.json b/mne-python/source/doc/sphinxext/prs/11616.json new file mode 100644 index 0000000000000000000000000000000000000000..44a617000fcbd28c28def1660f656798e0eb3316 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11616.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "d0cf4db4ba1f79cf31009b0c060ed64cc6b6de57", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 3, + "d": 3 + }, + "doc/changes/1.0.inc": { + "a": 7, + "d": 7 + }, + "doc/changes/1.1.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 4, + "d": 3 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 6, + "d": 1 + }, + "mne/conftest.py": { + "a": 17, + "d": 14 + }, + "mne/gui/__init__.py": { + "a": 34, + "d": 16 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 5, + "d": 4 + }, + "mne/utils/check.py": { + "a": 1, + "d": 0 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11620.json b/mne-python/source/doc/sphinxext/prs/11620.json new file mode 100644 index 0000000000000000000000000000000000000000..89b6ad91f5b7335dff38bf4e734fca9f61a873a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11620.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "a458622f4b1b7daa7685ad1d79fe132b22082ed9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 11, + "d": 5 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 3, + "d": 3 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 4, + "d": 4 + }, + "tools/setup_xvfb.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11621.json b/mne-python/source/doc/sphinxext/prs/11621.json new file mode 100644 index 0000000000000000000000000000000000000000..2ef68599a8fb045a9e31b68bb97ea1d695798652 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11621.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b25f2505727eb7a79cd4955f044f7b027c57ab43", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11622.json b/mne-python/source/doc/sphinxext/prs/11622.json new file mode 100644 index 0000000000000000000000000000000000000000..448a96ed353c0e4b9248765fdd6efa048daafd01 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11622.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5d1aa110fa0d889a98171131609e59747fc52d65", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11623.json b/mne-python/source/doc/sphinxext/prs/11623.json new file mode 100644 index 0000000000000000000000000000000000000000..61aa0983841926826316a4ec689939b3b6cd6d86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11623.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4a467838cdd3b013547a813c1772f3a481546714", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/html_templates/report/image.html.jinja": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11625.json b/mne-python/source/doc/sphinxext/prs/11625.json new file mode 100644 index 0000000000000000000000000000000000000000..3422fd916269048e9cc64f77b0c08b86fb029986 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11625.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a605992c9001af6e2c19d9d82558eef8150833b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/tests/test_spectrum.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11629.json b/mne-python/source/doc/sphinxext/prs/11629.json new file mode 100644 index 0000000000000000000000000000000000000000..56e03d686c659fc0a5d9950acfde8d65cfa50555 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11629.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "1c301417dd3f80ea77289f2fd60a4fe585b9db8b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/preprocessing/locate_ieeg_micro.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 12, + "d": 6 + }, + "requirements.txt": { + "a": 0, + "d": 1 + }, + "requirements_doc.txt": { + "a": 5, + "d": 4 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1163.json b/mne-python/source/doc/sphinxext/prs/1163.json new file mode 100644 index 0000000000000000000000000000000000000000..756a0277c49d6c6140f689d33aaedf2e33c3d3fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1163.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0f80d89c9a46d3195fd75accc265e01cc2b1247c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/evoked.py": { + "a": 15, + "d": 16 + }, + "mne/filter.py": { + "a": 63, + "d": 46 + }, + "mne/tests/test_filter.py": { + "a": 19, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11631.json b/mne-python/source/doc/sphinxext/prs/11631.json new file mode 100644 index 0000000000000000000000000000000000000000..9777733482195182f8578eea11f2cc40451f7604 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11631.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "263114e32d4fe4951f8f622f7ca74c30bfba37ae", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 60, + "d": 2 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11632.json b/mne-python/source/doc/sphinxext/prs/11632.json new file mode 100644 index 0000000000000000000000000000000000000000..ae3df7e3950c33255c18bf2188e664baedbb9c73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11632.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f88f22d52b3b5e2cba3f790965ac14d2fe4a13e0", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/contralateral_referencing.py": { + "a": 3, + "d": 6 + }, + "mne/channels/channels.py": { + "a": 29, + "d": 16 + }, + "mne/channels/tests/test_channels.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11634.json b/mne-python/source/doc/sphinxext/prs/11634.json new file mode 100644 index 0000000000000000000000000000000000000000..351a49c68177cd18e103d109784fe0fcc77e9bbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11634.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "57f5ce300f8e67ffcc0d9a19ab724693105b74b6", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 46, + "d": 0 + }, + "mne/io/_digitization.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11635.json b/mne-python/source/doc/sphinxext/prs/11635.json new file mode 100644 index 0000000000000000000000000000000000000000..5a53ed5eb35079937be9524655e4b26ef0740e03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11635.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "8fc3d07c8ab32101cba41723f3f8d825a08166df", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 4, + "d": 0 + }, + "mne/datasets/_fetch.py": { + "a": 12, + "d": 9 + }, + "mne/datasets/config.py": { + "a": 4, + "d": 2 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 20, + "d": 7 + }, + "mne/datasets/limo/limo.py": { + "a": 21, + "d": 8 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 22, + "d": 15 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 20, + "d": 7 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 20, + "d": 7 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 21, + "d": 27 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 71, + "d": 35 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "tools/circleci_download.sh": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11639.json b/mne-python/source/doc/sphinxext/prs/11639.json new file mode 100644 index 0000000000000000000000000000000000000000..41f5037fdd5de8c207b3ce7f18ef7d25e0b2da5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11639.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4eb9ef04c50710dba840ceaac6dc4f69ffefdd31", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 41, + "d": 0 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/eegbci/tests/test_eegbci.py": { + "a": 14, + "d": 0 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 4, + "d": 29 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11640.json b/mne-python/source/doc/sphinxext/prs/11640.json new file mode 100644 index 0000000000000000000000000000000000000000..f09c46bc60e50a9914dfa57b0ca7be780a3aa486 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11640.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "52506f4bed1af37e42644ed261735ef0a27b7556", + "authors": [ + { + "n": "Moritz Gerster", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/sensor_space.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 22, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 41, + "d": 7 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11643.json b/mne-python/source/doc/sphinxext/prs/11643.json new file mode 100644 index 0000000000000000000000000000000000000000..714c2eb929171c8bc276ec5af40c5eb54982a316 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11643.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4adddf7c871fb345afc8426902dab987d589c7b3", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/install/installers.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11644.json b/mne-python/source/doc/sphinxext/prs/11644.json new file mode 100644 index 0000000000000000000000000000000000000000..84d0a088bc35be4abdfa908f4d12735a9a80d402 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11644.json @@ -0,0 +1,235 @@ +{ + "merge_commit_sha": "d5556313874d1d68e50dcab685d80fb6f73a7913", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 0, + "d": 77 + }, + ".github/workflows/compat_old.yml": { + "a": 0, + "d": 68 + }, + ".github/workflows/linux_conda.yml": { + "a": 0, + "d": 125 + }, + ".github/workflows/linux_pip.yml": { + "a": 0, + "d": 76 + }, + ".github/workflows/macos_conda.yml": { + "a": 0, + "d": 76 + }, + ".github/workflows/precommit.yml": { + "a": 0, + "d": 14 + }, + ".github/workflows/tests.yml": { + "a": 117, + "d": 0 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 3, + "d": 2 + }, + "mne/bem.py": { + "a": 10, + "d": 97 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 3, + "d": 3 + }, + "mne/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/evoked.py": { + "a": 11, + "d": 11 + }, + "mne/filter.py": { + "a": 43, + "d": 15 + }, + "mne/fixes.py": { + "a": 12, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 5, + "d": 5 + }, + "mne/io/_digitization.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 54, + "d": 65 + }, + "mne/io/cnt/cnt.py": { + "a": 15, + "d": 14 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/res4.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf_comp.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/general.py": { + "a": 4, + "d": 4 + }, + "mne/io/fiff/raw.py": { + "a": 3, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 36, + "d": 36 + }, + "mne/io/open.py": { + "a": 3, + "d": 3 + }, + "mne/io/proc_history.py": { + "a": 5, + "d": 5 + }, + "mne/io/proj.py": { + "a": 6, + "d": 6 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 28, + "d": 20 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 2 + }, + "mne/io/tree.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 4 + }, + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 10 + }, + "mne/source_space.py": { + "a": 10, + "d": 10 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/regression.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 9, + "d": 7 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 14, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tools/get_minimal_commands.sh": { + "a": 21, + "d": 11 + }, + "tools/github_actions_dependencies.sh": { + "a": 11, + "d": 15 + }, + "tools/github_actions_env_vars.sh": { + "a": 30, + "d": 0 + }, + "tools/github_actions_install.sh": { + "a": 4, + "d": 3 + }, + "tools/github_actions_locale.sh": { + "a": 0, + "d": 5 + }, + "tools/github_actions_test.sh": { + "a": 11, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11646.json b/mne-python/source/doc/sphinxext/prs/11646.json new file mode 100644 index 0000000000000000000000000000000000000000..ae02ed3ac326a534d7410f9af5c11ac132e4d78f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11646.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "8c7f0c61f37a150712251cc32200152b6b4bd37a", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 7, + "d": 1 + }, + "doc/_static/style.css": { + "a": 12, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/README.txt": { + "a": 23, + "d": 0 + }, + "examples/preprocessing/locate_ieeg_micro.py": { + "a": 0, + "d": 94 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 0, + "d": 544 + }, + "tutorials/clinical/README.txt": { + "a": 34, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11648.json b/mne-python/source/doc/sphinxext/prs/11648.json new file mode 100644 index 0000000000000000000000000000000000000000..347d4e4bb574ac4f2c79d5e2930b174bc53289f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11648.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cc4006845d3c5367f16705557d652d9bbb82e87e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 3 + }, + "requirements_testing.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11649.json b/mne-python/source/doc/sphinxext/prs/11649.json new file mode 100644 index 0000000000000000000000000000000000000000..1a0ac87f630f313de74a7f4337055b7b62f3696f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11649.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e4dd2286e397d3c40a92fefddaddc6273e683e1d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1165.json b/mne-python/source/doc/sphinxext/prs/1165.json new file mode 100644 index 0000000000000000000000000000000000000000..2285299537f98b4660b92019989db80b22a9a4e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1165.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7ef8390275c9ebf79bab67e3fe8bdd8016229ed9", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 137, + "d": 30 + }, + "mne/tests/test_label.py": { + "a": 34, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11654.json b/mne-python/source/doc/sphinxext/prs/11654.json new file mode 100644 index 0000000000000000000000000000000000000000..29bf279ea4cccdde556fd84e9bba259c8754f1bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11654.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "909e45821bd004b6072a6426e4e8ea88e51b72ad", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 18, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 20, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11657.json b/mne-python/source/doc/sphinxext/prs/11657.json new file mode 100644 index 0000000000000000000000000000000000000000..a6fbc0354d5e8701c19591e166c9007bea126f87 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11657.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "cecbf0fb1dc919254bb6095db491b2d7c5f68003", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 5, + "d": 9 + }, + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 0, + "d": 34 + }, + "doc/Makefile": { + "a": 27, + "d": 93 + }, + "doc/conf.py": { + "a": 30, + "d": 45 + }, + "doc/install/contributing.rst": { + "a": 2, + "d": 14 + }, + "doc/sphinxext/gen_commands.py": { + "a": 16, + "d": 13 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "requirements_testing_extra.txt": { + "a": 2, + "d": 1 + }, + "tools/circleci_download.sh": { + "a": 5, + "d": 9 + }, + "tools/github_actions_dependencies.sh": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11658.json b/mne-python/source/doc/sphinxext/prs/11658.json new file mode 100644 index 0000000000000000000000000000000000000000..94125208c961e669f7f475f688c28c308cd0a56b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11658.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "42b29db564564155a77352bae4303068f7d78935", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 28, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11662.json b/mne-python/source/doc/sphinxext/prs/11662.json new file mode 100644 index 0000000000000000000000000000000000000000..f06d87c8cbeae0036b5799f3b2079776d8c4004d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11662.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "32000d4983ba904a5660ec7c31818d881e1cfa61", + "authors": [ + { + "n": "Florin Pop", + "e": "florin@ae.studio" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/check.py": { + "a": 6, + "d": 5 + }, + "mne/viz/backends/_utils.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11663.json b/mne-python/source/doc/sphinxext/prs/11663.json new file mode 100644 index 0000000000000000000000000000000000000000..b35f1f7d3d67f2b0fca49ed7d0b98219b55c6c25 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11663.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "18b80903da84483325584d8dffe7c9f847f12b81", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 3 + }, + "doc/_static/style.css": { + "a": 15, + "d": 4 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11664.json b/mne-python/source/doc/sphinxext/prs/11664.json new file mode 100644 index 0000000000000000000000000000000000000000..237f12e31cc9e5e2bd7be259a16b4572a866f634 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11664.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "fe1d6edf38d203a4b5cbdedef207847f70b2ebab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 22, + "d": 5 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 8 + }, + "mne/utils/config.py": { + "a": 4, + "d": 3 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 8 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11665.json b/mne-python/source/doc/sphinxext/prs/11665.json new file mode 100644 index 0000000000000000000000000000000000000000..e449b8b108b33107b4dc2de01f616f355172674d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11665.json @@ -0,0 +1,175 @@ +{ + "merge_commit_sha": "daec3da7c7ecfc8a2db53f438d0c64f4703d78d0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 6, + "d": 31 + }, + "doc/changes/latest.inc": { + "a": 7, + "d": 4 + }, + "doc/conf.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/multi_dipole_model.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_rap_music.py": { + "a": 2, + "d": 6 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 5, + "d": 4 + }, + "mne/channels/channels.py": { + "a": 5, + "d": 7 + }, + "mne/channels/tests/test_channels.py": { + "a": 3, + "d": 3 + }, + "mne/chpi.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 10, + "d": 7 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/event.py": { + "a": 2, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 6, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 3 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 58, + "d": 50 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 35, + "d": 24 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 5, + "d": 7 + }, + "mne/rank.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 5, + "d": 6 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 5, + "d": 6 + }, + "mne/viz/tests/test_topo.py": { + "a": 2, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 5, + "d": 3 + }, + "tools/azure_dependencies.sh": { + "a": 4, + "d": 3 + }, + "tools/circleci_bash_env.sh": { + "a": 27, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 16 + }, + "tutorials/simulation/80_dics.py": { + "a": 5, + "d": 2 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11666.json b/mne-python/source/doc/sphinxext/prs/11666.json new file mode 100644 index 0000000000000000000000000000000000000000..dc2730b4384c65e36400bb93a571fd2c3954f14e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11666.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e9fd6e78283f4c0655dfe80e1e86053181543f8f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Timur Sokhin", + "e": "qwinpin@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 2, + "d": 5 + }, + "mne/tests/test_annotations.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11667.json b/mne-python/source/doc/sphinxext/prs/11667.json new file mode 100644 index 0000000000000000000000000000000000000000..f7c7ce817e9c5a02590ed7d999879ca03f543939 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11667.json @@ -0,0 +1,2879 @@ +{ + "merge_commit_sha": "16fe5b5dbb1622ddfb7269fab889bab44ef43212", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".git-blame-ignore-revs": { + "a": 1, + "d": 0 + }, + ".github/workflows/tests.yml": { + "a": 1, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 5, + "d": 5 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1158, + "d": 800 + }, + "doc/install/contributing.rst": { + "a": 2, + "d": 1 + }, + "doc/sphinxext/flow_diagram.py": { + "a": 100, + "d": 84 + }, + "doc/sphinxext/gen_commands.py": { + "a": 27, + "d": 25 + }, + "doc/sphinxext/gen_names.py": { + "a": 11, + "d": 10 + }, + "doc/sphinxext/gh_substitutions.py": { + "a": 4, + "d": 4 + }, + "doc/sphinxext/mne_substitutions.py": { + "a": 31, + "d": 20 + }, + "doc/sphinxext/newcontrib_substitutions.py": { + "a": 6, + "d": 7 + }, + "doc/sphinxext/unit_role.py": { + "a": 6, + "d": 4 + }, + "examples/datasets/brainstorm_data.py": { + "a": 21, + "d": 13 + }, + "examples/datasets/hf_sef_data.py": { + "a": 3, + "d": 4 + }, + "examples/datasets/limo_data.py": { + "a": 47, + "d": 48 + }, + "examples/datasets/opm_data.py": { + "a": 59, + "d": 36 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 41, + "d": 26 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 33, + "d": 24 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 64, + "d": 39 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 46, + "d": 30 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 60, + "d": 35 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 13, + "d": 14 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 47, + "d": 25 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 33, + "d": 20 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 43, + "d": 25 + }, + "examples/decoding/ems_filtering.py": { + "a": 35, + "d": 22 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 17, + "d": 16 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 82, + "d": 48 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 52, + "d": 38 + }, + "examples/forward/forward_sensitivity_maps.py": { + "a": 37, + "d": 33 + }, + "examples/forward/left_cerebellum_volume_source.py": { + "a": 21, + "d": 11 + }, + "examples/forward/source_space_morphing.py": { + "a": 22, + "d": 20 + }, + "examples/inverse/compute_mne_inverse_epochs_in_label.py": { + "a": 49, + "d": 34 + }, + "examples/inverse/compute_mne_inverse_raw_in_label.py": { + "a": 12, + "d": 12 + }, + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 13, + "d": 10 + }, + "examples/inverse/custom_inverse_solver.py": { + "a": 32, + "d": 19 + }, + "examples/inverse/dics_epochs.py": { + "a": 43, + "d": 24 + }, + "examples/inverse/dics_source_power.py": { + "a": 24, + "d": 12 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 78, + "d": 38 + }, + "examples/inverse/gamma_map_inverse.py": { + "a": 49, + "d": 26 + }, + "examples/inverse/label_activation_from_stc.py": { + "a": 22, + "d": 20 + }, + "examples/inverse/label_from_stc.py": { + "a": 35, + "d": 30 + }, + "examples/inverse/label_source_activations.py": { + "a": 46, + "d": 30 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 77, + "d": 41 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 83, + "d": 60 + }, + "examples/inverse/mne_cov_power.py": { + "a": 62, + "d": 33 + }, + "examples/inverse/morph_surface_stc.py": { + "a": 30, + "d": 25 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 19, + "d": 16 + }, + "examples/inverse/multi_dipole_model.py": { + "a": 42, + "d": 39 + }, + "examples/inverse/multidict_reweighted_tfmxne.py": { + "a": 39, + "d": 23 + }, + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 50, + "d": 35 + }, + "examples/inverse/psf_ctf_vertices.py": { + "a": 38, + "d": 31 + }, + "examples/inverse/psf_ctf_vertices_lcmv.py": { + "a": 93, + "d": 54 + }, + "examples/inverse/psf_volume.py": { + "a": 35, + "d": 27 + }, + "examples/inverse/rap_music.py": { + "a": 14, + "d": 16 + }, + "examples/inverse/read_inverse.py": { + "a": 21, + "d": 16 + }, + "examples/inverse/read_stc.py": { + "a": 7, + "d": 6 + }, + "examples/inverse/resolution_metrics.py": { + "a": 81, + "d": 46 + }, + "examples/inverse/resolution_metrics_eegmeg.py": { + "a": 86, + "d": 51 + }, + "examples/inverse/snr_estimate.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/source_space_snr.py": { + "a": 21, + "d": 17 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 81, + "d": 39 + }, + "examples/inverse/vector_mne_solution.py": { + "a": 37, + "d": 23 + }, + "examples/io/elekta_epochs.py": { + "a": 17, + "d": 17 + }, + "examples/io/read_neo_format.py": { + "a": 5, + "d": 5 + }, + "examples/io/read_noise_covariance_matrix.py": { + "a": 3, + "d": 3 + }, + "examples/io/read_xdf.py": { + "a": 2, + "d": 4 + }, + "examples/preprocessing/contralateral_referencing.py": { + "a": 20, + "d": 26 + }, + "examples/preprocessing/css.py": { + "a": 36, + "d": 31 + }, + "examples/preprocessing/define_target_events.py": { + "a": 32, + "d": 17 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 127, + "d": 64 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 23, + "d": 16 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 7, + "d": 8 + }, + "examples/preprocessing/eog_regression.py": { + "a": 16, + "d": 15 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 14, + "d": 10 + }, + "examples/preprocessing/fnirs_artifact_removal.py": { + "a": 12, + "d": 9 + }, + "examples/preprocessing/ica_comparison.py": { + "a": 16, + "d": 11 + }, + "examples/preprocessing/interpolate_bad_channels.py": { + "a": 8, + "d": 8 + }, + "examples/preprocessing/movement_compensation.py": { + "a": 14, + "d": 12 + }, + "examples/preprocessing/movement_detection.py": { + "a": 29, + "d": 19 + }, + "examples/preprocessing/muscle_detection.py": { + "a": 9, + "d": 5 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 19, + "d": 12 + }, + "examples/preprocessing/otp.py": { + "a": 27, + "d": 16 + }, + "examples/preprocessing/shift_evoked.py": { + "a": 26, + "d": 12 + }, + "examples/preprocessing/virtual_evoked.py": { + "a": 13, + "d": 13 + }, + "examples/preprocessing/xdawn_denoising.py": { + "a": 21, + "d": 13 + }, + "examples/simulation/plot_stc_metrics.py": { + "a": 95, + "d": 70 + }, + "examples/simulation/simulate_evoked_data.py": { + "a": 34, + "d": 24 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 26, + "d": 18 + }, + "examples/simulation/simulated_raw_data_using_subject_anatomy.py": { + "a": 54, + "d": 50 + }, + "examples/simulation/source_simulator.py": { + "a": 13, + "d": 12 + }, + "examples/stats/cluster_stats_evoked.py": { + "a": 29, + "d": 23 + }, + "examples/stats/fdr_stats_evoked.py": { + "a": 38, + "d": 17 + }, + "examples/stats/linear_regression_raw.py": { + "a": 24, + "d": 14 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 31, + "d": 14 + }, + "examples/stats/sensor_regression.py": { + "a": 8, + "d": 6 + }, + "examples/time_frequency/compute_csd.py": { + "a": 21, + "d": 11 + }, + "examples/time_frequency/compute_source_psd_epochs.py": { + "a": 48, + "d": 28 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 59, + "d": 32 + }, + "examples/time_frequency/source_power_spectrum.py": { + "a": 27, + "d": 16 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 99, + "d": 63 + }, + "examples/time_frequency/source_space_time_frequency.py": { + "a": 29, + "d": 18 + }, + "examples/time_frequency/temporal_whitening.py": { + "a": 13, + "d": 13 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 68, + "d": 39 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 41, + "d": 32 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 115, + "d": 55 + }, + "examples/visualization/3d_to_2d.py": { + "a": 16, + "d": 11 + }, + "examples/visualization/brain.py": { + "a": 26, + "d": 21 + }, + "examples/visualization/channel_epochs_image.py": { + "a": 36, + "d": 17 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 14, + "d": 7 + }, + "examples/visualization/evoked_arrowmap.py": { + "a": 18, + "d": 11 + }, + "examples/visualization/evoked_topomap.py": { + "a": 37, + "d": 30 + }, + "examples/visualization/evoked_whitening.py": { + "a": 32, + "d": 15 + }, + "examples/visualization/meg_sensors.py": { + "a": 33, + "d": 24 + }, + "examples/visualization/mne_helmet.py": { + "a": 35, + "d": 14 + }, + "examples/visualization/montage_sgskip.py": { + "a": 18, + "d": 11 + }, + "examples/visualization/parcellation.py": { + "a": 38, + "d": 17 + }, + "examples/visualization/publication_figure.py": { + "a": 81, + "d": 49 + }, + "examples/visualization/roi_erpimage_by_rt.py": { + "a": 55, + "d": 21 + }, + "examples/visualization/sensor_noise_level.py": { + "a": 4, + "d": 3 + }, + "examples/visualization/ssp_projs_sensitivity_map.py": { + "a": 12, + "d": 8 + }, + "examples/visualization/topo_compare_conditions.py": { + "a": 11, + "d": 11 + }, + "examples/visualization/topo_customized.py": { + "a": 16, + "d": 15 + }, + "examples/visualization/xhemi.py": { + "a": 17, + "d": 12 + }, + "ignore_words.txt": { + "a": 2, + "d": 0 + }, + "logo/generate_mne_logos.py": { + "a": 103, + "d": 70 + }, + "mne/__init__.py": { + "a": 190, + "d": 71 + }, + "mne/__main__.py": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 215, + "d": 160 + }, + "mne/_ola.py": { + "a": 166, + "d": 120 + }, + "mne/annotations.py": { + "a": 367, + "d": 256 + }, + "mne/baseline.py": { + "a": 57, + "d": 32 + }, + "mne/beamformer/__init__.py": { + "a": 14, + "d": 4 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 220, + "d": 132 + }, + "mne/beamformer/_dics.py": { + "a": 173, + "d": 95 + }, + "mne/beamformer/_lcmv.py": { + "a": 139, + "d": 69 + }, + "mne/beamformer/_rap_music.py": { + "a": 31, + "d": 28 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 7, + "d": 8 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 473, + "d": 292 + }, + "mne/beamformer/tests/test_external.py": { + "a": 41, + "d": 31 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 641, + "d": 336 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 83, + "d": 70 + }, + "mne/beamformer/tests/test_resolution_matrix.py": { + "a": 21, + "d": 22 + }, + "mne/bem.py": { + "a": 900, + "d": 686 + }, + "mne/channels/__init__.py": { + "a": 70, + "d": 30 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 37, + "d": 29 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 115, + "d": 112 + }, + "mne/channels/channels.py": { + "a": 822, + "d": 551 + }, + "mne/channels/interpolation.py": { + "a": 62, + "d": 43 + }, + "mne/channels/layout.py": { + "a": 262, + "d": 176 + }, + "mne/channels/montage.py": { + "a": 432, + "d": 332 + }, + "mne/channels/tests/test_channels.py": { + "a": 240, + "d": 201 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 116, + "d": 95 + }, + "mne/channels/tests/test_layout.py": { + "a": 136, + "d": 97 + }, + "mne/channels/tests/test_montage.py": { + "a": 1024, + "d": 769 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 165, + "d": 101 + }, + "mne/chpi.py": { + "a": 586, + "d": 396 + }, + "mne/commands/mne_anonymize.py": { + "a": 47, + "d": 20 + }, + "mne/commands/mne_browse_raw.py": { + "a": 128, + "d": 61 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 65, + "d": 32 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 137, + "d": 46 + }, + "mne/commands/mne_compare_fiff.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 224, + "d": 107 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_coreg.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_flash_bem.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_maxfilter.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_prepare_bem_model.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_report.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_setup_forward_model.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_show_fiff.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_show_info.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_surf2bem.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_sys_info.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_what.py": { + "a": 0, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 0, + "d": 0 + }, + "mne/commands/utils.py": { + "a": 0, + "d": 0 + }, + "mne/conftest.py": { + "a": 0, + "d": 0 + }, + "mne/coreg.py": { + "a": 0, + "d": 0 + }, + "mne/cov.py": { + "a": 0, + "d": 0 + }, + "mne/cuda.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/_fake/_fake.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/_fetch.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/_infant/base.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/_phantom/base.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/brainstorm/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 180, + "d": 175 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 35, + "d": 27 + }, + "mne/datasets/eegbci/tests/test_eegbci.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/epilepsy_ecog/_data.py": { + "a": 15, + "d": 10 + }, + "mne/datasets/erp_core/erp_core.py": { + "a": 16, + "d": 11 + }, + "mne/datasets/eyelink/eyelink.py": { + "a": 16, + "d": 11 + }, + "mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py": { + "a": 15, + "d": 10 + }, + "mne/datasets/fnirs_motor/fnirs_motor.py": { + "a": 16, + "d": 11 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 27, + "d": 21 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 13, + "d": 8 + }, + "mne/datasets/limo/limo.py": { + "a": 180, + "d": 107 + }, + "mne/datasets/misc/_misc.py": { + "a": 14, + "d": 8 + }, + "mne/datasets/mtrf/mtrf.py": { + "a": 13, + "d": 10 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 16, + "d": 11 + }, + "mne/datasets/opm/opm.py": { + "a": 14, + "d": 11 + }, + "mne/datasets/phantom_4dbti/phantom_4dbti.py": { + "a": 15, + "d": 10 + }, + "mne/datasets/refmeg_noise/refmeg_noise.py": { + "a": 15, + "d": 10 + }, + "mne/datasets/sample/sample.py": { + "a": 16, + "d": 11 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 99, + "d": 69 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 44, + "d": 27 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 31, + "d": 20 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 118, + "d": 78 + }, + "mne/datasets/somato/somato.py": { + "a": 16, + "d": 11 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 24, + "d": 16 + }, + "mne/datasets/ssvep/ssvep.py": { + "a": 14, + "d": 11 + }, + "mne/datasets/testing/__init__.py": { + "a": 7, + "d": 2 + }, + "mne/datasets/testing/_testing.py": { + "a": 31, + "d": 21 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 143, + "d": 112 + }, + "mne/datasets/ucl_opm_auditory/ucl_opm_auditory.py": { + "a": 14, + "d": 10 + }, + "mne/datasets/utils.py": { + "a": 417, + "d": 206 + }, + "mne/datasets/visual_92_categories/visual_92_categories.py": { + "a": 15, + "d": 10 + }, + "mne/decoding/__init__.py": { + "a": 8, + "d": 3 + }, + "mne/decoding/base.py": { + "a": 105, + "d": 64 + }, + "mne/decoding/csp.py": { + "a": 234, + "d": 115 + }, + "mne/decoding/ems.py": { + "a": 28, + "d": 21 + }, + "mne/decoding/mixin.py": { + "a": 12, + "d": 9 + }, + "mne/decoding/receptive_field.py": { + "a": 104, + "d": 64 + }, + "mne/decoding/search_light.py": { + "a": 71, + "d": 60 + }, + "mne/decoding/ssd.py": { + "a": 122, + "d": 66 + }, + "mne/decoding/tests/test_base.py": { + "a": 100, + "d": 75 + }, + "mne/decoding/tests/test_csp.py": { + "a": 123, + "d": 86 + }, + "mne/decoding/tests/test_ems.py": { + "a": 25, + "d": 14 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 226, + "d": 173 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 54, + "d": 53 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 232, + "d": 103 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 120, + "d": 64 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 80, + "d": 56 + }, + "mne/decoding/time_frequency.py": { + "a": 28, + "d": 9 + }, + "mne/decoding/transformer.py": { + "a": 167, + "d": 94 + }, + "mne/defaults.py": { + "a": 279, + "d": 115 + }, + "mne/dipole.py": { + "a": 666, + "d": 356 + }, + "mne/epochs.py": { + "a": 1405, + "d": 753 + }, + "mne/event.py": { + "a": 393, + "d": 239 + }, + "mne/evoked.py": { + "a": 759, + "d": 344 + }, + "mne/export/_brainvision.py": { + "a": 1, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 109, + "d": 83 + }, + "mne/export/_eeglab.py": { + "a": 36, + "d": 19 + }, + "mne/export/_egimff.py": { + "a": 53, + "d": 46 + }, + "mne/export/_export.py": { + "a": 56, + "d": 33 + }, + "mne/export/tests/test_export.py": { + "a": 204, + "d": 172 + }, + "mne/filter.py": { + "a": 1154, + "d": 561 + }, + "mne/fixes.py": { + "a": 167, + "d": 115 + }, + "mne/forward/__init__.py": { + "a": 45, + "d": 19 + }, + "mne/forward/_compute_forward.py": { + "a": 160, + "d": 133 + }, + "mne/forward/_field_interpolation.py": { + "a": 0, + "d": 0 + }, + "mne/forward/_lead_dots.py": { + "a": 0, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 0, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 0, + "d": 0 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 0, + "d": 0 + }, + "mne/forward/tests/test_forward.py": { + "a": 0, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 0, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/gui/_core.py": { + "a": 0, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 0, + "d": 0 + }, + "mne/gui/_ieeg_locate.py": { + "a": 0, + "d": 0 + }, + "mne/gui/tests/test_core.py": { + "a": 0, + "d": 0 + }, + "mne/gui/tests/test_coreg.py": { + "a": 0, + "d": 0 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 0, + "d": 0 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 0, + "d": 0 + }, + "mne/html_templates/_templates.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 0, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/_digitization.py": { + "a": 0, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 0, + "d": 0 + }, + "mne/io/array/array.py": { + "a": 0, + "d": 0 + }, + "mne/io/array/tests/test_array.py": { + "a": 0, + "d": 0 + }, + "mne/io/artemis123/artemis123.py": { + "a": 0, + "d": 0 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 0, + "d": 0 + }, + "mne/io/artemis123/utils.py": { + "a": 0, + "d": 0 + }, + "mne/io/base.py": { + "a": 0, + "d": 0 + }, + "mne/io/besa/besa.py": { + "a": 0, + "d": 0 + }, + "mne/io/besa/tests/test_besa.py": { + "a": 0, + "d": 0 + }, + "mne/io/boxy/boxy.py": { + "a": 101, + "d": 81 + }, + "mne/io/boxy/tests/test_boxy.py": { + "a": 76, + "d": 62 + }, + "mne/io/brainvision/brainvision.py": { + "a": 348, + "d": 271 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 435, + "d": 309 + }, + "mne/io/bti/bti.py": { + "a": 821, + "d": 645 + }, + "mne/io/bti/constants.py": { + "a": 67, + "d": 67 + }, + "mne/io/bti/read.py": { + "a": 17, + "d": 22 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 237, + "d": 174 + }, + "mne/io/cnt/_utils.py": { + "a": 39, + "d": 31 + }, + "mne/io/cnt/cnt.py": { + "a": 203, + "d": 154 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 14, + "d": 15 + }, + "mne/io/compensator.py": { + "a": 36, + "d": 33 + }, + "mne/io/constants.py": { + "a": 882, + "d": 746 + }, + "mne/io/ctf/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 123, + "d": 85 + }, + "mne/io/ctf/eeg.py": { + "a": 43, + "d": 30 + }, + "mne/io/ctf/hc.py": { + "a": 32, + "d": 26 + }, + "mne/io/ctf/info.py": { + "a": 298, + "d": 220 + }, + "mne/io/ctf/markers.py": { + "a": 36, + "d": 31 + }, + "mne/io/ctf/res4.py": { + "a": 124, + "d": 107 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 473, + "d": 194 + }, + "mne/io/ctf/trans.py": { + "a": 63, + "d": 45 + }, + "mne/io/ctf_comp.py": { + "a": 49, + "d": 43 + }, + "mne/io/curry/curry.py": { + "a": 233, + "d": 154 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 263, + "d": 158 + }, + "mne/io/diff.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 678, + "d": 461 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 428, + "d": 227 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 53, + "d": 38 + }, + "mne/io/eeglab/_eeglab.py": { + "a": 4, + "d": 4 + }, + "mne/io/eeglab/eeglab.py": { + "a": 248, + "d": 150 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 366, + "d": 234 + }, + "mne/io/egi/egi.py": { + "a": 167, + "d": 112 + }, + "mne/io/egi/egimff.py": { + "a": 388, + "d": 309 + }, + "mne/io/egi/events.py": { + "a": 30, + "d": 27 + }, + "mne/io/egi/general.py": { + "a": 65, + "d": 61 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 236, + "d": 193 + }, + "mne/io/eximia/eximia.py": { + "a": 34, + "d": 23 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 22, + "d": 16 + }, + "mne/io/eyelink/eyelink.py": { + "a": 0, + "d": 0 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 0, + "d": 0 + }, + "mne/io/fieldtrip/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 0, + "d": 0 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 0, + "d": 0 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 0, + "d": 0 + }, + "mne/io/fieldtrip/utils.py": { + "a": 0, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 0, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 0, + "d": 0 + }, + "mne/io/fil/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/fil/fil.py": { + "a": 0, + "d": 0 + }, + "mne/io/fil/sensors.py": { + "a": 0, + "d": 0 + }, + "mne/io/fil/tests/test_fil.py": { + "a": 0, + "d": 0 + }, + "mne/io/hitachi/hitachi.py": { + "a": 0, + "d": 0 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 0, + "d": 0 + }, + "mne/io/kit/constants.py": { + "a": 0, + "d": 0 + }, + "mne/io/kit/coreg.py": { + "a": 0, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 0, + "d": 0 + }, + "mne/io/matrix.py": { + "a": 0, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 0, + "d": 0 + }, + "mne/io/nedf/nedf.py": { + "a": 0, + "d": 0 + }, + "mne/io/nedf/tests/test_nedf.py": { + "a": 0, + "d": 0 + }, + "mne/io/nicolet/nicolet.py": { + "a": 0, + "d": 0 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 0, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 0, + "d": 0 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 0, + "d": 0 + }, + "mne/io/nirx/_localized_abbr.py": { + "a": 0, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 0, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 0, + "d": 0 + }, + "mne/io/open.py": { + "a": 0, + "d": 0 + }, + "mne/io/persyst/persyst.py": { + "a": 0, + "d": 0 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 0, + "d": 0 + }, + "mne/io/pick.py": { + "a": 0, + "d": 0 + }, + "mne/io/proc_history.py": { + "a": 0, + "d": 0 + }, + "mne/io/proj.py": { + "a": 0, + "d": 0 + }, + "mne/io/reference.py": { + "a": 0, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 0, + "d": 0 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 0, + "d": 0 + }, + "mne/io/tag.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_apply_function.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_compensator.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_constants.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_pick.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_proc_history.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_read_raw.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_show_fiff.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_utils.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_what.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_write.py": { + "a": 0, + "d": 0 + }, + "mne/io/tree.py": { + "a": 0, + "d": 0 + }, + "mne/io/utils.py": { + "a": 0, + "d": 0 + }, + "mne/io/what.py": { + "a": 0, + "d": 0 + }, + "mne/io/write.py": { + "a": 0, + "d": 0 + }, + "mne/label.py": { + "a": 0, + "d": 0 + }, + "mne/minimum_norm/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 59, + "d": 47 + }, + "mne/minimum_norm/inverse.py": { + "a": 896, + "d": 560 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 140, + "d": 73 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 63, + "d": 56 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 838, + "d": 567 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 128, + "d": 79 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 71, + "d": 64 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 17, + "d": 7 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 191, + "d": 86 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 403, + "d": 155 + }, + "mne/misc.py": { + "a": 15, + "d": 18 + }, + "mne/morph.py": { + "a": 509, + "d": 336 + }, + "mne/morph_map.py": { + "a": 57, + "d": 39 + }, + "mne/parallel.py": { + "a": 37, + "d": 27 + }, + "mne/preprocessing/__init__.py": { + "a": 26, + "d": 8 + }, + "mne/preprocessing/_csd.py": { + "a": 86, + "d": 65 + }, + "mne/preprocessing/_css.py": { + "a": 8, + "d": 10 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 179, + "d": 117 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 10, + "d": 11 + }, + "mne/preprocessing/_regress.py": { + "a": 126, + "d": 66 + }, + "mne/preprocessing/annotate_amplitude.py": { + "a": 65, + "d": 39 + }, + "mne/preprocessing/annotate_nan.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 161, + "d": 113 + }, + "mne/preprocessing/bads.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ctps_.py": { + "a": 10, + "d": 8 + }, + "mne/preprocessing/ecg.py": { + "a": 206, + "d": 89 + }, + "mne/preprocessing/eog.py": { + "a": 151, + "d": 63 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 67, + "d": 48 + }, + "mne/preprocessing/hfc.py": { + "a": 18, + "d": 12 + }, + "mne/preprocessing/ica.py": { + "a": 1140, + "d": 667 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 74, + "d": 53 + }, + "mne/preprocessing/ieeg/_volume.py": { + "a": 91, + "d": 70 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 83, + "d": 64 + }, + "mne/preprocessing/ieeg/tests/test_volume.py": { + "a": 64, + "d": 40 + }, + "mne/preprocessing/infomax_.py": { + "a": 55, + "d": 37 + }, + "mne/preprocessing/interpolate.py": { + "a": 33, + "d": 37 + }, + "mne/preprocessing/maxfilter.py": { + "a": 75, + "d": 49 + }, + "mne/preprocessing/maxwell.py": { + "a": 1092, + "d": 689 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 12, + "d": 5 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 36, + "d": 28 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 17, + "d": 9 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 7, + "d": 6 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 104, + "d": 78 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 38, + "d": 37 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 213, + "d": 128 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 11, + "d": 14 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 17, + "d": 16 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 9, + "d": 9 + }, + "mne/preprocessing/otp.py": { + "a": 19, + "d": 15 + }, + "mne/preprocessing/realign.py": { + "a": 27, + "d": 22 + }, + "mne/preprocessing/ssp.py": { + "a": 335, + "d": 96 + }, + "mne/preprocessing/stim.py": { + "a": 33, + "d": 23 + }, + "mne/preprocessing/tests/test_annotate_amplitude.py": { + "a": 146, + "d": 142 + }, + "mne/preprocessing/tests/test_annotate_nan.py": { + "a": 5, + "d": 9 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 74, + "d": 64 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 69, + "d": 62 + }, + "mne/preprocessing/tests/test_css.py": { + "a": 18, + "d": 13 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 29, + "d": 25 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 46, + "d": 32 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 40, + "d": 27 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 37, + "d": 34 + }, + "mne/preprocessing/tests/test_hfc.py": { + "a": 40, + "d": 38 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 587, + "d": 497 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 9, + "d": 8 + }, + "mne/preprocessing/tests/test_interpolate.py": { + "a": 60, + "d": 43 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_otp.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_peak_finder.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_realign.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/xdawn.py": { + "a": 0, + "d": 0 + }, + "mne/proj.py": { + "a": 0, + "d": 0 + }, + "mne/rank.py": { + "a": 0, + "d": 0 + }, + "mne/report/js_and_css/bootstrap-icons/gen_css_for_mne.py": { + "a": 0, + "d": 0 + }, + "mne/report/report.py": { + "a": 0, + "d": 0 + }, + "mne/report/tests/test_report.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/_metrics.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/evoked.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/metrics/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/metrics/metrics.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/metrics/tests/test_metrics.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/tests/test_raw.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/tests/test_source.py": { + "a": 0, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 0, + "d": 0 + }, + "mne/source_space.py": { + "a": 0, + "d": 0 + }, + "mne/stats/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/stats/_adjacency.py": { + "a": 0, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 0, + "d": 0 + }, + "mne/stats/multi_comp.py": { + "a": 0, + "d": 0 + }, + "mne/stats/parametric.py": { + "a": 0, + "d": 0 + }, + "mne/stats/permutations.py": { + "a": 0, + "d": 0 + }, + "mne/stats/regression.py": { + "a": 113, + "d": 70 + }, + "mne/stats/tests/test_adjacency.py": { + "a": 16, + "d": 12 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 395, + "d": 250 + }, + "mne/stats/tests/test_multi_comp.py": { + "a": 4, + "d": 5 + }, + "mne/stats/tests/test_parametric.py": { + "a": 76, + "d": 68 + }, + "mne/stats/tests/test_permutations.py": { + "a": 20, + "d": 20 + }, + "mne/stats/tests/test_regression.py": { + "a": 42, + "d": 40 + }, + "mne/surface.py": { + "a": 656, + "d": 455 + }, + "mne/tests/test_annotations.py": { + "a": 620, + "d": 511 + }, + "mne/tests/test_bem.py": { + "a": 316, + "d": 250 + }, + "mne/tests/test_chpi.py": { + "a": 319, + "d": 254 + }, + "mne/tests/test_coreg.py": { + "a": 216, + "d": 162 + }, + "mne/tests/test_cov.py": { + "a": 429, + "d": 320 + }, + "mne/tests/test_defaults.py": { + "a": 16, + "d": 17 + }, + "mne/tests/test_dipole.py": { + "a": 213, + "d": 148 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 155, + "d": 111 + }, + "mne/tests/test_epochs.py": { + "a": 1885, + "d": 1216 + }, + "mne/tests/test_event.py": { + "a": 271, + "d": 266 + }, + "mne/tests/test_evoked.py": { + "a": 216, + "d": 205 + }, + "mne/tests/test_filter.py": { + "a": 553, + "d": 341 + }, + "mne/tests/test_freesurfer.py": { + "a": 115, + "d": 71 + }, + "mne/tests/test_import_nesting.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 539, + "d": 345 + }, + "mne/tests/test_line_endings.py": { + "a": 50, + "d": 27 + }, + "mne/tests/test_morph.py": { + "a": 512, + "d": 343 + }, + "mne/tests/test_morph_map.py": { + "a": 14, + "d": 13 + }, + "mne/tests/test_ola.py": { + "a": 35, + "d": 28 + }, + "mne/tests/test_parallel.py": { + "a": 14, + "d": 6 + }, + "mne/tests/test_proj.py": { + "a": 179, + "d": 152 + }, + "mne/tests/test_rank.py": { + "a": 121, + "d": 116 + }, + "mne/tests/test_read_vectorview_selection.py": { + "a": 30, + "d": 13 + }, + "mne/tests/test_source_estimate.py": { + "a": 0, + "d": 0 + }, + "mne/tests/test_source_space.py": { + "a": 0, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 0, + "d": 0 + }, + "mne/tests/test_transforms.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/_stft.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/_stockwell.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/ar.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/csd.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 0, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 0, + "d": 0 + }, + "mne/transforms.py": { + "a": 0, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/utils/_bunch.py": { + "a": 0, + "d": 0 + }, + "mne/utils/_logging.py": { + "a": 0, + "d": 0 + }, + "mne/utils/_testing.py": { + "a": 0, + "d": 0 + }, + "mne/utils/check.py": { + "a": 0, + "d": 0 + }, + "mne/utils/config.py": { + "a": 0, + "d": 0 + }, + "mne/utils/dataframe.py": { + "a": 0, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 0 + }, + "mne/utils/fetching.py": { + "a": 0, + "d": 0 + }, + "mne/utils/linalg.py": { + "a": 0, + "d": 0 + }, + "mne/utils/misc.py": { + "a": 0, + "d": 0 + }, + "mne/utils/mixin.py": { + "a": 0, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 0, + "d": 0 + }, + "mne/utils/progressbar.py": { + "a": 0, + "d": 0 + }, + "mne/utils/spectrum.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_bunch.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_config.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_docs.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_linalg.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_logging.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_misc.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_numerics.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_testing.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_3d_overlay.py": { + "a": 0, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/_scraper.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/callback.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/colormap.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/surface.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/view.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_dipole.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_proj.py": { + "a": 0, + "d": 0 + }, + "mne/viz/_scraper.py": { + "a": 0, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 0, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 0, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 0, + "d": 0 + }, + "mne/viz/backends/_qt.py": { + "a": 0, + "d": 0 + }, + "mne/viz/backends/_utils.py": { + "a": 94, + "d": 72 + }, + "mne/viz/backends/renderer.py": { + "a": 56, + "d": 32 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 35, + "d": 33 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 79, + "d": 66 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 31, + "d": 28 + }, + "mne/viz/circle.py": { + "a": 121, + "d": 74 + }, + "mne/viz/conftest.py": { + "a": 11, + "d": 9 + }, + "mne/viz/epochs.py": { + "a": 422, + "d": 262 + }, + "mne/viz/evoked.py": { + "a": 1315, + "d": 660 + }, + "mne/viz/ica.py": { + "a": 548, + "d": 337 + }, + "mne/viz/misc.py": { + "a": 522, + "d": 344 + }, + "mne/viz/montage.py": { + "a": 25, + "d": 10 + }, + "mne/viz/raw.py": { + "a": 236, + "d": 128 + }, + "mne/viz/tests/test_3d.py": { + "a": 666, + "d": 392 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 78, + "d": 53 + }, + "mne/viz/tests/test_circle.py": { + "a": 15, + "d": 10 + }, + "mne/viz/tests/test_epochs.py": { + "a": 183, + "d": 125 + }, + "mne/viz/tests/test_evoked.py": { + "a": 291, + "d": 216 + }, + "mne/viz/tests/test_figure.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 163, + "d": 132 + }, + "mne/viz/tests/test_misc.py": { + "a": 176, + "d": 119 + }, + "mne/viz/tests/test_montage.py": { + "a": 35, + "d": 28 + }, + "mne/viz/tests/test_proj.py": { + "a": 26, + "d": 18 + }, + "mne/viz/tests/test_raw.py": { + "a": 337, + "d": 293 + }, + "mne/viz/tests/test_scraper.py": { + "a": 8, + "d": 9 + }, + "mne/viz/tests/test_topo.py": { + "a": 186, + "d": 125 + }, + "mne/viz/tests/test_topomap.py": { + "a": 337, + "d": 264 + }, + "mne/viz/tests/test_utils.py": { + "a": 49, + "d": 44 + }, + "mne/viz/topo.py": { + "a": 597, + "d": 246 + }, + "mne/viz/topomap.py": { + "a": 1727, + "d": 836 + }, + "mne/viz/utils.py": { + "a": 888, + "d": 560 + }, + "pyproject.toml": { + "a": 3, + "d": 1 + }, + "requirements_testing.txt": { + "a": 1, + "d": 0 + }, + "setup.py": { + "a": 105, + "d": 95 + }, + "tools/check_mne_location.py": { + "a": 3, + "d": 2 + }, + "tools/generate_codemeta.py": { + "a": 72, + "d": 64 + }, + "tools/get_testing_version.sh": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 79, + "d": 47 + }, + "tutorials/clinical/30_ecog.py": { + "a": 77, + "d": 37 + }, + "tutorials/clinical/60_sleep.py": { + "a": 81, + "d": 51 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 48, + "d": 38 + }, + "tutorials/epochs/15_baseline_regression.py": { + "a": 67, + "d": 45 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 46, + "d": 34 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 17, + "d": 18 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 143, + "d": 89 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 56, + "d": 35 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 7, + "d": 8 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 30, + "d": 25 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 54, + "d": 43 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 80, + "d": 70 + }, + "tutorials/evoked/40_whitened.py": { + "a": 19, + "d": 12 + }, + "tutorials/forward/10_background_freesurfer.py": { + "a": 5, + "d": 4 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 109, + "d": 64 + }, + "tutorials/forward/25_automated_coreg.py": { + "a": 17, + "d": 12 + }, + "tutorials/forward/30_forward.py": { + "a": 67, + "d": 34 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 39, + "d": 26 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 161, + "d": 107 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 18, + "d": 20 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 27, + "d": 23 + }, + "tutorials/intro/10_overview.py": { + "a": 80, + "d": 40 + }, + "tutorials/intro/15_inplace.py": { + "a": 8, + "d": 8 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 23, + "d": 17 + }, + "tutorials/intro/30_info.py": { + "a": 11, + "d": 11 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 25, + "d": 27 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 28, + "d": 22 + }, + "tutorials/intro/70_report.py": { + "a": 134, + "d": 155 + }, + "tutorials/inverse/10_stc_class.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/40_mne_fixed_free.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 0, + "d": 0 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 0, + "d": 0 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 0, + "d": 0 + }, + "tutorials/io/70_reading_eyetracking_data.py": { + "a": 0, + "d": 0 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 0, + "d": 0 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/80_opm_processing.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 0, + "d": 0 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 0, + "d": 0 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 0, + "d": 0 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 28, + "d": 23 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 6, + "d": 5 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 54, + "d": 35 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 42, + "d": 42 + }, + "tutorials/simulation/80_dics.py": { + "a": 99, + "d": 47 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 107, + "d": 49 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 33, + "d": 22 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 83, + "d": 41 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 88, + "d": 41 + }, + "tutorials/stats-sensor-space/70_cluster_rmANOVA_time_freq.py": { + "a": 100, + "d": 46 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 111, + "d": 56 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 65, + "d": 36 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 40, + "d": 26 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 85, + "d": 52 + }, + "tutorials/time-freq/10_spectrum_class.py": { + "a": 18, + "d": 15 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 81, + "d": 41 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 226, + "d": 157 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11668.json b/mne-python/source/doc/sphinxext/prs/11668.json new file mode 100644 index 0000000000000000000000000000000000000000..3ce44cc368895a429de845014fe06121e792f534 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11668.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "ccdbbdcc501042045c30f44454ed1d704c817550", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 15, + "d": 4 + }, + "mne/channels/tests/test_channels.py": { + "a": 11, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1167.json b/mne-python/source/doc/sphinxext/prs/1167.json new file mode 100644 index 0000000000000000000000000000000000000000..bdd14d60c3a824351756dddebe8bc37da4090961 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1167.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "90c94ef284f232ec619c6fcad7b1671f16f81ffe", + "authors": [ + { + "n": "Brad Buran", + "e": null + } + ], + "changes": { + "mne/forward/_lead_dots.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11670.json b/mne-python/source/doc/sphinxext/prs/11670.json new file mode 100644 index 0000000000000000000000000000000000000000..0ff50c991b2f292e8aa635071c50802de14350d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11670.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "295a1bbcb8eec67773506464b56230e4ef7c8e41", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/institutional-partners.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 23, + "d": 23 + }, + "doc/conf.py": { + "a": 33, + "d": 28 + }, + "doc/references.bib": { + "a": 2, + "d": 4 + }, + "mne/channels/montage.py": { + "a": 3, + "d": 4 + }, + "mne/io/cnt/cnt.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11673.json b/mne-python/source/doc/sphinxext/prs/11673.json new file mode 100644 index 0000000000000000000000000000000000000000..98f94f9460dbc2317e9aab21d43ccf4dc9deb0d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11673.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "24dff77255706e5498d8cc80ebe35b757725c4e9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "README.rst": { + "a": 10, + "d": 11 + }, + "setup.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11675.json b/mne-python/source/doc/sphinxext/prs/11675.json new file mode 100644 index 0000000000000000000000000000000000000000..535ea2f42b29ce6b094bbb77dc3976e687d82bd7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11675.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "dba7df1914f020f8905c7be4ae5a0ce823e4e2eb", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 0, + "d": 4 + }, + "doc/_templates/homepage.html": { + "a": 2, + "d": 2 + }, + "doc/_templates/layout.html": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 18, + "d": 14 + }, + "doc/index.rst": { + "a": 2, + "d": 0 + }, + "doc/install/index.rst": { + "a": 2, + "d": 0 + }, + "doc/overview/cite.rst": { + "a": 6, + "d": 3 + }, + "doc/overview/migrating.rst": { + "a": 3, + "d": 3 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11679.json b/mne-python/source/doc/sphinxext/prs/11679.json new file mode 100644 index 0000000000000000000000000000000000000000..ac39687cfa275548336ec15cdf5fb930690ba2c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11679.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "425e3b34439bfcff68f4f926b886aaba9a02478c", + "authors": [ + { + "n": "Theodore Papadopoulo", + "e": "Theodore.Papadopoulo@inria.fr" + } + ], + "changes": { + "doc/changes/0.19.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/inverse.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 23, + "d": 1 + }, + "examples/inverse/trap_music.py": { + "a": 61, + "d": 0 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_rap_music.py": { + "a": 100, + "d": 69 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11680.json b/mne-python/source/doc/sphinxext/prs/11680.json new file mode 100644 index 0000000000000000000000000000000000000000..cde518da0f987358c4627d1be9e9fc98de9a7fdb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11680.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "fdd56d5c6e5c8ac3bfa649abfa84b225d1629e9f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 6, + "d": 0 + }, + "mne/io/array/tests/test_array.py": { + "a": 10, + "d": 2 + }, + "mne/report/tests/test_report.py": { + "a": 19, + "d": 13 + }, + "mne/time_frequency/spectrum.py": { + "a": 21, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + }, + "mne/utils/spectrum.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 6, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 15, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11682.json b/mne-python/source/doc/sphinxext/prs/11682.json new file mode 100644 index 0000000000000000000000000000000000000000..0e02aac276c33f30ddd928e85e71fea826971df1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11682.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "60b29bef68144144445ddd1d3ca3126e369a2a7d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/datasets/brainstorm_data.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 5, + "d": 1 + }, + "examples/visualization/sensor_noise_level.py": { + "a": 6, + "d": 1 + }, + "mne/report/report.py": { + "a": 7, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 13, + "d": 19 + }, + "tutorials/clinical/60_sleep.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 3, + "d": 1 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 4, + "d": 4 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 2, + "d": 2 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 1, + "d": 1 + }, + "tutorials/time-freq/10_spectrum_class.py": { + "a": 1, + "d": 1 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11683.json b/mne-python/source/doc/sphinxext/prs/11683.json new file mode 100644 index 0000000000000000000000000000000000000000..bb66fc59578cd4e4b433a313bc619efddb3b2e61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11683.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d2600ee084bc884c3cc461cd94bfe25ae9932d4c", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11685.json b/mne-python/source/doc/sphinxext/prs/11685.json new file mode 100644 index 0000000000000000000000000000000000000000..0164ba1afb5a85e3bfebea748528a3e302abdc73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11685.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "0e68aba7e52f7d5241c58509ffd00f6ffc23d7a6", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 3, + "d": 0 + }, + "doc/visualization.rst": { + "a": 24, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_ui_events.py": { + "a": 261, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 52, + "d": 18 + }, + "mne/viz/ui_events.py": { + "a": 305, + "d": 0 + }, + "tutorials/visualization/10_publication_figure.py": { + "a": 1, + "d": 1 + }, + "tutorials/visualization/20_ui_events.py": { + "a": 100, + "d": 0 + }, + "tutorials/visualization/README.txt": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11686.json b/mne-python/source/doc/sphinxext/prs/11686.json new file mode 100644 index 0000000000000000000000000000000000000000..1c76c0cee65e82c4ccf6caab0a9918a99d19e26a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11686.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "7661516c7cc73055e8cdf85970d8b481ea9e45aa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".mailmap": { + "a": 8, + "d": 0 + }, + "CITATION.cff": { + "a": 44, + "d": 19 + }, + "SECURITY.md": { + "a": 3, + "d": 3 + }, + "codemeta.json": { + "a": 131, + "d": 53 + }, + "doc/_static/versions.json": { + "a": 7, + "d": 2 + }, + "doc/changes/0.19.inc": { + "a": 0, + "d": 9 + }, + "doc/changes/0.20.inc": { + "a": 0, + "d": 9 + }, + "doc/changes/0.21.inc": { + "a": 0, + "d": 9 + }, + "doc/changes/0.22.inc": { + "a": 0, + "d": 9 + }, + "doc/changes/0.23.inc": { + "a": 0, + "d": 14 + }, + "doc/changes/0.24.inc": { + "a": 0, + "d": 14 + }, + "doc/changes/1.0.inc": { + "a": 0, + "d": 18 + }, + "doc/changes/1.1.inc": { + "a": 0, + "d": 18 + }, + "doc/changes/1.2.inc": { + "a": 0, + "d": 18 + }, + "doc/changes/1.3.inc": { + "a": 0, + "d": 18 + }, + "doc/changes/1.4.inc": { + "a": 61, + "d": 21 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/cited.rst": { + "a": 3, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 2 + }, + "tools/generate_codemeta.py": { + "a": 13, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11687.json b/mne-python/source/doc/sphinxext/prs/11687.json new file mode 100644 index 0000000000000000000000000000000000000000..329db407fb380643008c52a5a9786d2a1433a32e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11687.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "75dea8183599eb8ea8091216a32b41b34458f797", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/0.24.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 34, + "d": 0 + }, + "doc/install/installers.rst": { + "a": 6, + "d": 6 + }, + "doc/mri.rst": { + "a": 4, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 0, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 14, + "d": 57 + }, + "mne/channels/tests/test_layout.py": { + "a": 0, + "d": 16 + }, + "mne/gui/__init__.py": { + "a": 2, + "d": 93 + }, + "mne/gui/_core.py": { + "a": 0, + "d": 639 + }, + "mne/gui/_ieeg_locate.py": { + "a": 0, + "d": 883 + }, + "mne/gui/tests/test_core.py": { + "a": 0, + "d": 71 + }, + "mne/gui/tests/test_ieeg_locate.py": { + "a": 0, + "d": 242 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 10 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 7 + }, + "mne/io/pick.py": { + "a": 0, + "d": 46 + }, + "mne/report/report.py": { + "a": 1, + "d": 7 + }, + "mne/surface.py": { + "a": 0, + "d": 198 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 153 + }, + "mne/time_frequency/spectrum.py": { + "a": 4, + "d": 12 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/spectrum.py": { + "a": 0, + "d": 5 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11692.json b/mne-python/source/doc/sphinxext/prs/11692.json new file mode 100644 index 0000000000000000000000000000000000000000..81004d104e7b715e4f31404809253f061eb95686 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11692.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "68e4f89763135637110859ee0e05e594955815f1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/updating.rst": { + "a": 14, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11694.json b/mne-python/source/doc/sphinxext/prs/11694.json new file mode 100644 index 0000000000000000000000000000000000000000..49d78ffef91aa90804b0385fdab39c7b5cfbfadf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11694.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1e6aa7d99530f4cd11505665307b5667fe126b8a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 7, + "d": 76 + }, + "mne/forward/tests/test_forward.py": { + "a": 43, + "d": 2 + }, + "mne/proj.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11695.json b/mne-python/source/doc/sphinxext/prs/11695.json new file mode 100644 index 0000000000000000000000000000000000000000..9594517a73ce89d6171ef6fa501ece1221f672a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11695.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "25094d7a0abe4ae17bff5f0e1f59c429770cfd19", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/_includes/institutional-partners.rst": { + "a": 2, + "d": 1 + }, + "doc/_static/institution_logos/AE-Studio-dark.svg": { + "a": 5, + "d": 0 + }, + "doc/_static/institution_logos/AE-Studio-light.svg": { + "a": 5, + "d": 0 + }, + "doc/conf.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11696.json b/mne-python/source/doc/sphinxext/prs/11696.json new file mode 100644 index 0000000000000000000000000000000000000000..3153216390b853e57d4f80cb0ad09072639df616 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11696.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "97db26cb8d867480fb4ac37f61a76090250555e6", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 4, + "d": 6 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 135, + "d": 169 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "requirements_base.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11697.json b/mne-python/source/doc/sphinxext/prs/11697.json new file mode 100644 index 0000000000000000000000000000000000000000..4fbfeb5cab74747530f03daa30353746ba529d51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11697.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a7fec8c0b1c31425f807ccb4cffa8b76f5d2f94", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11698.json b/mne-python/source/doc/sphinxext/prs/11698.json new file mode 100644 index 0000000000000000000000000000000000000000..c72ef0e784b94e4b3c54e63b51f444a456dd9254 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11698.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4ce984f4458652551e2997da3749c2cbdb92a64e", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1170.json b/mne-python/source/doc/sphinxext/prs/1170.json new file mode 100644 index 0000000000000000000000000000000000000000..8d1b5110060276f196c6b82640b1b9d434ee4421 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1170.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2daa7f621f6e1ec50fd8042a1bc19905368c6f2d", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 4, + "d": 7 + }, + "mne/tests/test_transforms.py": { + "a": 12, + "d": 11 + }, + "mne/transforms.py": { + "a": 20, + "d": 48 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11701.json b/mne-python/source/doc/sphinxext/prs/11701.json new file mode 100644 index 0000000000000000000000000000000000000000..eb4f7fc6cfc4eac583eb9292f790b214bfbbcdc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11701.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cdcad6e14adf8e931dfec3d7da8329493e7a9c4b", + "authors": [ + { + "n": "Thomas Moreau", + "e": "thomas.moreau.2010@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_event.py": { + "a": 6, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/utils/check.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11702.json b/mne-python/source/doc/sphinxext/prs/11702.json new file mode 100644 index 0000000000000000000000000000000000000000..37377e2884a9e1a71d475b7b51018e8390cfda78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11702.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c69f6327ecebc5bb8e70eeb39856677a640ea731", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11704.json b/mne-python/source/doc/sphinxext/prs/11704.json new file mode 100644 index 0000000000000000000000000000000000000000..47b780388e2ce37930cc63e22013bc10f61e6400 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11704.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "bb1d54798e56b2854cba76d0f3b12a383b8bb96f", + "authors": [ + { + "n": "Aaron Earle-Richardson", + "e": "ae166@duke.edu" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 1 + }, + "mne/viz/_brain/surface.py": { + "a": 8, + "d": 3 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 12, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11707.json b/mne-python/source/doc/sphinxext/prs/11707.json new file mode 100644 index 0000000000000000000000000000000000000000..2086736f7ff2e60496e6056bbe5c9339016d9ade --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11707.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "52fde5b8e4d9af5e10411911dd16e5cc11d80435", + "authors": [ + { + "n": "Joshua Calder-Travis", + "e": null + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11709.json b/mne-python/source/doc/sphinxext/prs/11709.json new file mode 100644 index 0000000000000000000000000000000000000000..c55d34c7f268995949c015c23a8bddaf6db75744 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11709.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a9126b19950e8803c87c022aee2e04d6d2515f9", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/install/installers.rst": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11713.json b/mne-python/source/doc/sphinxext/prs/11713.json new file mode 100644 index 0000000000000000000000000000000000000000..47450aadcd39c24ccc3c9433b709554312acf607 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11713.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "917b000f6f707e23499225c0e621b13b48e0f52a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/baseline.py": { + "a": 15, + "d": 15 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11714.json b/mne-python/source/doc/sphinxext/prs/11714.json new file mode 100644 index 0000000000000000000000000000000000000000..ebbb1a5dfdf5a422830b97e58be5bd8341398d58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11714.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d466e180715c95a2a86713b3df85c2203682bc23", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11715.json b/mne-python/source/doc/sphinxext/prs/11715.json new file mode 100644 index 0000000000000000000000000000000000000000..cf4f0abc6cfae85bd06b6b509286fde564432ff6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11715.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4914d2355c9b90f1b80862a78e548a649b36ad7c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11718.json b/mne-python/source/doc/sphinxext/prs/11718.json new file mode 100644 index 0000000000000000000000000000000000000000..9aae9058aa4b0f5fbd2af4911341722139437198 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11718.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "dd9a4073eff6cf9320af1500b8a614a60a38fb95", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_regression.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11719.json b/mne-python/source/doc/sphinxext/prs/11719.json new file mode 100644 index 0000000000000000000000000000000000000000..8e4fd3e52fe8314dacf42aa79f4731366f8d7cea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11719.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "35d37979ceb6f7f2ea021face10dc679b929d03e", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/file_io.rst": { + "a": 1, + "d": 1 + }, + "doc/preprocessing.rst": { + "a": 2, + "d": 0 + }, + "mne/io/eyelink/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/io/eyelink/_utils.py": { + "a": 113, + "d": 0 + }, + "mne/io/eyelink/eyelink.py": { + "a": 53, + "d": 40 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/eyetracking/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/eyetracking/calibration.py": { + "a": 229, + "d": 0 + }, + "mne/preprocessing/eyetracking/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/eyetracking/tests/test_calibration.py": { + "a": 247, + "d": 0 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 49, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1172.json b/mne-python/source/doc/sphinxext/prs/1172.json new file mode 100644 index 0000000000000000000000000000000000000000..328707f2dfc70399707e6d3806c62494c8118a72 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1172.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "030e087384a94c031ee45f348cbfbe3e95fe0a50", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "mne/fiff/open.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11720.json b/mne-python/source/doc/sphinxext/prs/11720.json new file mode 100644 index 0000000000000000000000000000000000000000..25e3f03974614b6000aba7ff9d80f917874550a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11720.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a8ec5d067ab8cc2ec8004d8dc291eebe893287d8", + "authors": [ + { + "n": "Gennadiy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11721.json b/mne-python/source/doc/sphinxext/prs/11721.json new file mode 100644 index 0000000000000000000000000000000000000000..4270829eba1f791e9a43d7a22ead3077540fb372 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11721.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "13dd05a48aeeb952deb183bede8ed588ae55f7a6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 5, + "d": 3 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 30, + "d": 9 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11723.json b/mne-python/source/doc/sphinxext/prs/11723.json new file mode 100644 index 0000000000000000000000000000000000000000..a8ee8df3f354ce8e4b17d2c7204f51c5619f41b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11723.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c19bce34d636285e9ddd14f5c183c81795caaf99", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11724.json b/mne-python/source/doc/sphinxext/prs/11724.json new file mode 100644 index 0000000000000000000000000000000000000000..073e49c265768a295490b50590c4e76adcba4cc8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11724.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d158117a716512fbe96d8ff6c4d735f1e9601d09", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/overview/roadmap.rst": { + "a": 41, + "d": 36 + }, + "mne/report/tests/test_report.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11727.json b/mne-python/source/doc/sphinxext/prs/11727.json new file mode 100644 index 0000000000000000000000000000000000000000..46012c0a3b31867a6dbea41ac19e4e76e1594094 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11727.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c98749b529a41473cfccbc18485a9d1924546545", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11729.json b/mne-python/source/doc/sphinxext/prs/11729.json new file mode 100644 index 0000000000000000000000000000000000000000..62c7c4fa44e58248e8d174581ef79061af82eeba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11729.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "959d2b64dd1f53b36eefb0e025110d01b92006ee", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/install/installers.rst": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1173.json b/mne-python/source/doc/sphinxext/prs/1173.json new file mode 100644 index 0000000000000000000000000000000000000000..35d6c6448d0931fe3021880e3034c97f04d4c933 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1173.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dcd3979155fb10bb3e4f5582d1345cdc98c916d2", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "mne/fiff/meas_info.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11730.json b/mne-python/source/doc/sphinxext/prs/11730.json new file mode 100644 index 0000000000000000000000000000000000000000..b5b6f5e7218b9aa2b00b250890ea330def2a84db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11730.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6fd91f6c61cf86b201b57b5df43ce6898518cc50", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/surface.py": { + "a": 11, + "d": 8 + }, + "mne/tests/test_surface.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11733.json b/mne-python/source/doc/sphinxext/prs/11733.json new file mode 100644 index 0000000000000000000000000000000000000000..cde1578db49f2deff205a536ec945aa22ed63f0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11733.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ffa3fb50f3fcf4029d874d490a53c7d142c034ab", + "authors": [ + { + "n": "George O'Neill", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/fil/fil.py": { + "a": 17, + "d": 10 + }, + "mne/io/fil/tests/test_fil.py": { + "a": 23, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11736.json b/mne-python/source/doc/sphinxext/prs/11736.json new file mode 100644 index 0000000000000000000000000000000000000000..d83d0768fcb941583fae0e88a726dc62d43e00fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11736.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "ee767ddffbcde5869e4740548120c9055c8e41ed", + "authors": [ + { + "n": "Gennadiy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/filter.py": { + "a": 16, + "d": 2 + }, + "mne/io/base.py": { + "a": 7, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 8, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 6, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 8, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11740.json b/mne-python/source/doc/sphinxext/prs/11740.json new file mode 100644 index 0000000000000000000000000000000000000000..98450af058ac2b4028f896b6564bcc16cb3cb635 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11740.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "f48398a141ac4ed0ec4ec1f2cef766afd8605696", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/eyetracking/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/eyetracking/_pupillometry.py": { + "a": 108, + "d": 0 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/eyetracking/tests/test_pupillometry.py": { + "a": 69, + "d": 0 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 69, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11741.json b/mne-python/source/doc/sphinxext/prs/11741.json new file mode 100644 index 0000000000000000000000000000000000000000..f2de28519cbbce6a743aa45440fa1d6b652c200c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11741.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "95297672f1a6c33cc7f64f887282bcfdaa795900", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/_includes/institutional-partners.rst": { + "a": 1, + "d": 0 + }, + "doc/_static/institution_logos/FCBG.svg": { + "a": 82, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 6, + "d": 0 + }, + "doc/overview/people.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11744.json b/mne-python/source/doc/sphinxext/prs/11744.json new file mode 100644 index 0000000000000000000000000000000000000000..28bbda6e457ed645e4ce0451e2c087bbc93a5ebd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11744.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c4464741467547a4e93f2f807af57313cdfa2331", + "authors": [ + { + "n": "Diptyajit Das", + "e": "bmedasdiptyajit@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 1, + "d": 0 + }, + "mne/channels/data/montages/easycap-M43.txt": { + "a": 65, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11745.json b/mne-python/source/doc/sphinxext/prs/11745.json new file mode 100644 index 0000000000000000000000000000000000000000..7e6dff7ac4320182926bfb3e1d085aa560574a1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11745.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b0f8ce69c7258319624aebdd6de63b23e1c78ad5", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/overview/people.rst": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 7 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11746.json b/mne-python/source/doc/sphinxext/prs/11746.json new file mode 100644 index 0000000000000000000000000000000000000000..c5c68990b986fd6e9912a127501177f9347615dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11746.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "bad786df12c4c14512cb1a27276a688912131a16", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 237, + "d": 0 + }, + "mne/io/eyelink/eyelink.py": { + "a": 34, + "d": 272 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 47, + "d": 18 + }, + "tutorials/io/70_reading_eyetracking_data.py": { + "a": 3, + "d": 3 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 22, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11748.json b/mne-python/source/doc/sphinxext/prs/11748.json new file mode 100644 index 0000000000000000000000000000000000000000..07df830ee4ac38475eed172e03e0f146f03ee551 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11748.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1d776cb0f83fe55784f06e004bad672878e34a8a", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "mne/event.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1175.json b/mne-python/source/doc/sphinxext/prs/1175.json new file mode 100644 index 0000000000000000000000000000000000000000..0c781919c99c517ba7957ebf4d5df982f0567f52 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1175.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "487500658b65c2cef24f45b3e92354c325633b21", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "mne/tests/test_transforms.py": { + "a": 9, + "d": 0 + }, + "mne/transforms.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11750.json b/mne-python/source/doc/sphinxext/prs/11750.json new file mode 100644 index 0000000000000000000000000000000000000000..2c6eb48589b75ea06918bcb54f43e8659bd965a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11750.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c8f478ba33b2d0eed9e326b543476403e54dcd03", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 3, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11752.json b/mne-python/source/doc/sphinxext/prs/11752.json new file mode 100644 index 0000000000000000000000000000000000000000..bd0e16b5c87371e3c488ea0098e316f915086695 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11752.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "52d1e3e016e5caadb040eb3fa30790a8895d8732", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 14, + "d": 5 + }, + "mne/viz/tests/test_epochs.py": { + "a": 6, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 2, + "d": 3 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/40_whitened.py": { + "a": 2, + "d": 2 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 1, + "d": 1 + }, + "tutorials/simulation/80_dics.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11753.json b/mne-python/source/doc/sphinxext/prs/11753.json new file mode 100644 index 0000000000000000000000000000000000000000..ab3d0e95a879b4afcaddcdd3749b4183f8b8071f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11753.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "be5f51aa8f5fdaec2b915be0346e163ab7363103", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11754.json b/mne-python/source/doc/sphinxext/prs/11754.json new file mode 100644 index 0000000000000000000000000000000000000000..8c636a96e497af233034e98dffd230b77eae2d0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11754.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "38ed57443a45131f9dee5e7a21ca39c2c1fcd78b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 14, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11755.json b/mne-python/source/doc/sphinxext/prs/11755.json new file mode 100644 index 0000000000000000000000000000000000000000..281d8b7e933d875f39fc615a60e8b63851b63ef3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11755.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4b0923f8cf491e13da9f602af91c42cd3722261d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 8, + "d": 6 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11756.json b/mne-python/source/doc/sphinxext/prs/11756.json new file mode 100644 index 0000000000000000000000000000000000000000..88061526680b5fa42b35833e1e0de45b7356b45e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11756.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dca0a2267c02ba10778913bdafebd352d630962e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/1.1.inc": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11757.json b/mne-python/source/doc/sphinxext/prs/11757.json new file mode 100644 index 0000000000000000000000000000000000000000..b500b1e45659018848686198a845987b15840db8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11757.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7def8369d7ca691d807fe916663168c2ee4c10e0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/preprocessing/eog.py": { + "a": 6, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11760.json b/mne-python/source/doc/sphinxext/prs/11760.json new file mode 100644 index 0000000000000000000000000000000000000000..0e740e338b831db28bdb94b3e629c96440e64da0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11760.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1763fa6af209b2eef34e2b41fe95f7e4f6d5dac1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 8, + "d": 7 + }, + "mne/viz/_mpl_figure.py": { + "a": 32, + "d": 8 + }, + "mne/viz/tests/test_raw.py": { + "a": 61, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11764.json b/mne-python/source/doc/sphinxext/prs/11764.json new file mode 100644 index 0000000000000000000000000000000000000000..7ea1214f24fe08cf4dcd718a1e110bf3839f18f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11764.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3c4a6f6bbc258dcb68f5d80ba5dd9b0d9f258057", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/install/manual_install.rst": { + "a": 28, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11765.json b/mne-python/source/doc/sphinxext/prs/11765.json new file mode 100644 index 0000000000000000000000000000000000000000..7108578d96de42bfc7265627bade1df576b0f375 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11765.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b92c88d70468a0f8174ab527b3e24d7f07af966b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/parallel.py": { + "a": 5, + "d": 1 + }, + "mne/tests/test_parallel.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11766.json b/mne-python/source/doc/sphinxext/prs/11766.json new file mode 100644 index 0000000000000000000000000000000000000000..17c6b236e10fc2406417f88548d9809d309871ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11766.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2eb608a0f111faee842e017993273f950b083012", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 18, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11769.json b/mne-python/source/doc/sphinxext/prs/11769.json new file mode 100644 index 0000000000000000000000000000000000000000..1699b45056017457e3f9d2722eb2b5e71d50f3b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11769.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c874a7d764061e34098f84da49b6d598fed4bfba", + "authors": [ + { + "n": "Nikolai M Chapochnikov", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 7, + "d": 3 + }, + "mne/time_frequency/psd.py": { + "a": 5, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 10, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11770.json b/mne-python/source/doc/sphinxext/prs/11770.json new file mode 100644 index 0000000000000000000000000000000000000000..c6bb38629974b739f9c57d2e8fa1ac1f6480718f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11770.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "79647ec0f24de1c2c4d7d637726ef61cdc72a4da", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 7, + "d": 4 + }, + "mne/datasets/config.py": { + "a": 3, + "d": 3 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 131, + "d": 144 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11771.json b/mne-python/source/doc/sphinxext/prs/11771.json new file mode 100644 index 0000000000000000000000000000000000000000..736e933b1282bf1bad74f69cc769f2c81c4a0552 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11771.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d78d0f5b0a6dedb4faf49950b07d72bdcc53557f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11773.json b/mne-python/source/doc/sphinxext/prs/11773.json new file mode 100644 index 0000000000000000000000000000000000000000..9e9c3b3594781ababb0bff04602a5d42ffa75a4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11773.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "06d396d40a6a925473dcf1451758272d68f64185", + "authors": [ + { + "n": "Frostime", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11774.json b/mne-python/source/doc/sphinxext/prs/11774.json new file mode 100644 index 0000000000000000000000000000000000000000..1a8b477c2626accba0abe53aa4eca23c1a240f6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11774.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b4eecda8d66ac083554db8ee1c925b98fdc2a402", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11777.json b/mne-python/source/doc/sphinxext/prs/11777.json new file mode 100644 index 0000000000000000000000000000000000000000..f202ab761c029088adb8c1ababfc808d1ccf2ca4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11777.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5d452c6a091f05d83055c9eef202008b34db2158", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11778.json b/mne-python/source/doc/sphinxext/prs/11778.json new file mode 100644 index 0000000000000000000000000000000000000000..de69ce8303699949c20d0394f219a026d8ec6177 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11778.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a3e98cea745b75665b7692161629937f6dc65921", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 13, + "d": 0 + }, + "mne/utils/spectrum.py": { + "a": 16, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11779.json b/mne-python/source/doc/sphinxext/prs/11779.json new file mode 100644 index 0000000000000000000000000000000000000000..aadd709ba13b63e432951d0b2a9cf1929d0824db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11779.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "30800ad71edcd1ae569c39083cd8d7dcc01c92ee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/artifact_detection.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11781.json b/mne-python/source/doc/sphinxext/prs/11781.json new file mode 100644 index 0000000000000000000000000000000000000000..9aff0d033d1e378cbd0656a6739488a911e9e42c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11781.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "2a0b111349380429dcd5cab8abf1a211fd5eb408", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 7, + "d": 1 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 0, + "d": 1 + }, + "mne/conftest.py": { + "a": 4, + "d": 0 + }, + "mne/io/tag.py": { + "a": 22, + "d": 22 + }, + "mne/viz/tests/test_topomap.py": { + "a": 10, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 36, + "d": 21 + }, + "tools/azure_dependencies.sh": { + "a": 8, + "d": 10 + }, + "tools/github_actions_dependencies.sh": { + "a": 5, + "d": 9 + }, + "tools/github_actions_test.sh": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11783.json b/mne-python/source/doc/sphinxext/prs/11783.json new file mode 100644 index 0000000000000000000000000000000000000000..ad2eb3416f00a66c89f47cafdcf4a80c8c0fd2ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11783.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4cf0d1d5ca692cf8426933ef5e683b648b04203d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/datasets/eegbci/eegbci.py": { + "a": 38, + "d": 41 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11786.json b/mne-python/source/doc/sphinxext/prs/11786.json new file mode 100644 index 0000000000000000000000000000000000000000..5219a9ce677b83532d7c933875a0f80ad4dce37e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11786.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "413e4a38601ce36e47018e9e4144d62a9d1c7a8e", + "authors": [ + { + "n": "Samuel Louviot", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11787.json b/mne-python/source/doc/sphinxext/prs/11787.json new file mode 100644 index 0000000000000000000000000000000000000000..410b726fd7a59c589feac46d77e4cb630484d65f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11787.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5608da261cc18f4813c1165baa8a6d5f64a1ea8c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11789.json b/mne-python/source/doc/sphinxext/prs/11789.json new file mode 100644 index 0000000000000000000000000000000000000000..779d7285ec2ba7afd7adcbe0cb378ac81e8661d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11789.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e28943603444353511bea8f22f5646153b7ec903", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 0, + "d": 2 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11792.json b/mne-python/source/doc/sphinxext/prs/11792.json new file mode 100644 index 0000000000000000000000000000000000000000..913852fc2f0d7877c9639da5c58b0bcd11f85317 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11792.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8051f6ddf68a797ec0c9e1801aea3c73808bba03", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 15, + "d": 11 + }, + "mne/viz/topomap.py": { + "a": 31, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11796.json b/mne-python/source/doc/sphinxext/prs/11796.json new file mode 100644 index 0000000000000000000000000000000000000000..c2e37392877e6f6816372bde4656e2b406413a4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11796.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "926bec285c34c0fbdcad7b09ac4f550af8288e8a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/events.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 35, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11798.json b/mne-python/source/doc/sphinxext/prs/11798.json new file mode 100644 index 0000000000000000000000000000000000000000..dcd30084b72a4b352b75b8fee8a15ff71afb50ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11798.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "c9d20060d74b8f384aedfeb02c122ca7c31986fa", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + } + ], + "changes": { + "doc/api/visualization.rst": { + "a": 15, + "d": 0 + }, + "doc/documentation/datasets.rst": { + "a": 23, + "d": 5 + }, + "examples/visualization/eyetracking_plot_heatmap.py": { + "a": 89, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 4, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + }, + "mne/viz/eyetracking/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/viz/eyetracking/heatmap.py": { + "a": 155, + "d": 0 + }, + "mne/viz/eyetracking/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/viz/eyetracking/tests/test_heatmap.py": { + "a": 35, + "d": 0 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 23, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11801.json b/mne-python/source/doc/sphinxext/prs/11801.json new file mode 100644 index 0000000000000000000000000000000000000000..45a1ebaecfe4d1a0598b11257c770d1fc05c7e06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11801.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "fc819143b28298c50c8d9de9555a02474fbe3bc9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/annotations.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_show_fiff.py": { + "a": 10, + "d": 1 + }, + "mne/io/constants.py": { + "a": 4, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 2 + }, + "mne/io/open.py": { + "a": 45, + "d": 21 + }, + "mne/io/tag.py": { + "a": 41, + "d": 40 + }, + "mne/io/tests/test_constants.py": { + "a": 7, + "d": 0 + }, + "mne/io/tree.py": { + "a": 6, + "d": 12 + }, + "mne/io/write.py": { + "a": 26, + "d": 89 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11803.json b/mne-python/source/doc/sphinxext/prs/11803.json new file mode 100644 index 0000000000000000000000000000000000000000..014e1eb74fad8a9e00cc86dc744a219aa7d56483 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11803.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "db07d55c6ed0b09c6e3f31568b096070f5886a98", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/time_frequency.rst": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 12, + "d": 0 + }, + "mne/epochs.py": { + "a": 7, + "d": 30 + }, + "mne/time_frequency/__init__.py": { + "a": 7, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 143, + "d": 4 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 79, + "d": 24 + }, + "mne/utils/docs.py": { + "a": 17, + "d": 0 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 9, + "d": 39 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11804.json b/mne-python/source/doc/sphinxext/prs/11804.json new file mode 100644 index 0000000000000000000000000000000000000000..2d4b13384875e31b37489a0c3cf24db17c8080cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11804.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9b3a4d38a252e8e26980135229f68ca90d0fe359", + "authors": [ + { + "n": "Daniel Tse", + "e": "xiezhibin.0.0.superman@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11806.json b/mne-python/source/doc/sphinxext/prs/11806.json new file mode 100644 index 0000000000000000000000000000000000000000..42391a43021565efce444839044e1a9621bd8075 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11806.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9a2758d708f23e4e67a1d0205fe645a6d9f77aea", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11808.json b/mne-python/source/doc/sphinxext/prs/11808.json new file mode 100644 index 0000000000000000000000000000000000000000..3f03c9bbd3e486e1b43b7bd65bb302d0673364fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11808.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1b4f6ff4e169c93c6abd2fe858e4985d95e48626", + "authors": [ + { + "n": "Joshua Calder-Travis", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11814.json b/mne-python/source/doc/sphinxext/prs/11814.json new file mode 100644 index 0000000000000000000000000000000000000000..122ef51d17845fcf63372d0f8269f9db22d6897b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11814.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6e5d6e87ab83dd62c8e1cd95b9f8691b43fb9774", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/45_projectors_background.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11815.json b/mne-python/source/doc/sphinxext/prs/11815.json new file mode 100644 index 0000000000000000000000000000000000000000..3b8555497fd198e38872457afdd69b917154910a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11815.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "57146eedf8779c50745677bed832f8481a9c5a86", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 4, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 3, + "d": 37 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 11, + "d": 4 + }, + "tools/github_actions_env_vars.sh": { + "a": 0, + "d": 4 + }, + "tools/github_actions_test.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11819.json b/mne-python/source/doc/sphinxext/prs/11819.json new file mode 100644 index 0000000000000000000000000000000000000000..778d49a2b83551a1a11789edd2ba25111b81f34f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11819.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7b2304840405f1d7956494c735c91d8bff094e7e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/_static/js/contrib-avatars.js": { + "a": 51, + "d": 0 + }, + "doc/_static/style.css": { + "a": 11, + "d": 2 + }, + "doc/_templates/layout.html": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1182.json b/mne-python/source/doc/sphinxext/prs/1182.json new file mode 100644 index 0000000000000000000000000000000000000000..f94f71fa0695cf8324880127965e613960722adb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1182.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f408543ac09f99039417c65d8f6dece33d4675ed", + "authors": [ + { + "n": "Ross Maddox", + "e": "rkmaddox@uw.edu" + } + ], + "changes": { + "mne/epochs.py": { + "a": 19, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11821.json b/mne-python/source/doc/sphinxext/prs/11821.json new file mode 100644 index 0000000000000000000000000000000000000000..6a9dff169cdf724e60d049775a5abf60574116c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11821.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "66c40caea1fd343fbe49a34815542065ceecdf3d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 16, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 1 + }, + "mne/cov.py": { + "a": 8, + "d": 0 + }, + "mne/io/eyelink/eyelink.py": { + "a": 7, + "d": 3 + }, + "mne/io/proj.py": { + "a": 10, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 12, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 8 + }, + "mne/viz/epochs.py": { + "a": 5, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 62, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11822.json b/mne-python/source/doc/sphinxext/prs/11822.json new file mode 100644 index 0000000000000000000000000000000000000000..76f948cd4933d4110371e08d3477e5eaa144fdea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11822.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "68e7272563fa88c2f0bd6d3e551eac9c51c2d07d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 9, + "d": 12 + }, + "mne/io/egi/egimff.py": { + "a": 2, + "d": 13 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 21, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11823.json b/mne-python/source/doc/sphinxext/prs/11823.json new file mode 100644 index 0000000000000000000000000000000000000000..c0b18074426b0781985e1474ce15190a1e05cd06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11823.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cc1d1825c41144c8c4c3dd1cbb44f8af7bf78e9b", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 9, + "d": 65 + }, + "mne/io/eyelink/eyelink.py": { + "a": 180, + "d": 182 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 100, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11826.json b/mne-python/source/doc/sphinxext/prs/11826.json new file mode 100644 index 0000000000000000000000000000000000000000..edd7538a2788ff06ba6f4806994d746519b3b384 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11826.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "fc88fe51565210144b4df4784352922f99799bab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 4, + "d": 2 + }, + "mne/io/ctf/ctf.py": { + "a": 8, + "d": 10 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 0 + }, + "mne/io/egi/egimff.py": { + "a": 2, + "d": 0 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 9, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 6, + "d": 0 + }, + "mne/io/hitachi/hitachi.py": { + "a": 181, + "d": 186 + }, + "mne/io/kit/kit.py": { + "a": 71, + "d": 70 + }, + "mne/io/nihon/nihon.py": { + "a": 1, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 31, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11828.json b/mne-python/source/doc/sphinxext/prs/11828.json new file mode 100644 index 0000000000000000000000000000000000000000..4afafa54e89bbe47520cc7b0e9ce14815f92c270 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11828.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "74f3f18c82d3548e12833712ac6fd6074f1a3005", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11829.json b/mne-python/source/doc/sphinxext/prs/11829.json new file mode 100644 index 0000000000000000000000000000000000000000..0f8d723c9f6fbc704638ccc3ad3430e014922840 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11829.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1a49303d74abba32ac216f88d040e66789a0d02b", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/install/mne_tools_suite.rst": { + "a": 5, + "d": 4 + }, + "doc/links.inc": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11830.json b/mne-python/source/doc/sphinxext/prs/11830.json new file mode 100644 index 0000000000000000000000000000000000000000..dacbd7eed3fb2502e80a674b62204eccabace028 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11830.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bc94f08ab08c572cf0597db96003ee9f152f10a6", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 85, + "d": 55 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11836.json b/mne-python/source/doc/sphinxext/prs/11836.json new file mode 100644 index 0000000000000000000000000000000000000000..0551234ff3f405a22154a414cdf4106ccbddaff7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11836.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0fd4ded6b773a34cdeee7b17a8c39a6ac93940ba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11837.json b/mne-python/source/doc/sphinxext/prs/11837.json new file mode 100644 index 0000000000000000000000000000000000000000..163e351089712568d790248340e2c2e019fc002c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11837.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "a560999215de1d58af57660cce08f813fac738a9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 0, + "d": 4 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 8, + "d": 9 + }, + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "tools/github_actions_test.sh": { + "a": 2, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11838.json b/mne-python/source/doc/sphinxext/prs/11838.json new file mode 100644 index 0000000000000000000000000000000000000000..abda64316666089add7b3a49fc065a79d5d41aa4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11838.json @@ -0,0 +1,579 @@ +{ + "merge_commit_sha": "dea8f8728eef1832ba6dc750e447fc0799f46f88", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 269, + "d": 222 + }, + "mne/_fiff/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/meas_info.py": { + "a": 2, + "d": 3 + }, + "mne/_fiff/open.py": { + "a": 2, + "d": 3 + }, + "mne/_fiff/pick.py": { + "a": 2, + "d": 0 + }, + "mne/_fiff/tag.py": { + "a": 3, + "d": 5 + }, + "mne/_fiff/write.py": { + "a": 4, + "d": 5 + }, + "mne/_freesurfer.py": { + "a": 2, + "d": 1 + }, + "mne/_ola.py": { + "a": 1, + "d": 3 + }, + "mne/annotations.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/__init__.py": { + "a": 32, + "d": 17 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 2 + }, + "mne/bem.py": { + "a": 1, + "d": 5 + }, + "mne/channels/__init__.py": { + "a": 47, + "d": 78 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 11 + }, + "mne/channels/interpolation.py": { + "a": 3, + "d": 4 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 3 + }, + "mne/channels/montage.py": { + "a": 7, + "d": 3 + }, + "mne/channels/tests/test_layout.py": { + "a": 3, + "d": 2 + }, + "mne/chpi.py": { + "a": 5, + "d": 8 + }, + "mne/commands/__init__.py": { + "a": 7, + "d": 1 + }, + "mne/coreg.py": { + "a": 2, + "d": 4 + }, + "mne/cov.py": { + "a": 4, + "d": 4 + }, + "mne/cuda.py": { + "a": 1, + "d": 5 + }, + "mne/datasets/__init__.py": { + "a": 42, + "d": 69 + }, + "mne/datasets/limo/limo.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/__init__.py": { + "a": 23, + "d": 16 + }, + "mne/decoding/csp.py": { + "a": 4, + "d": 7 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/receptive_field.py": { + "a": 3, + "d": 5 + }, + "mne/decoding/ssd.py": { + "a": 5, + "d": 7 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 3, + "d": 7 + }, + "mne/decoding/transformer.py": { + "a": 7, + "d": 2 + }, + "mne/dipole.py": { + "a": 3, + "d": 5 + }, + "mne/epochs.py": { + "a": 15, + "d": 8 + }, + "mne/evoked.py": { + "a": 7, + "d": 4 + }, + "mne/export/__init__.py": { + "a": 12, + "d": 2 + }, + "mne/filter.py": { + "a": 29, + "d": 49 + }, + "mne/fixes.py": { + "a": 26, + "d": 74 + }, + "mne/forward/__init__.py": { + "a": 52, + "d": 45 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 7 + }, + "mne/gui/__init__.py": { + "a": 6, + "d": 283 + }, + "mne/gui/_coreg.py": { + "a": 6, + "d": 5 + }, + "mne/gui/_gui.py": { + "a": 284, + "d": 0 + }, + "mne/html_templates/__init__.py": { + "a": 7, + "d": 1 + }, + "mne/html_templates/_templates.py": { + "a": 20, + "d": 15 + }, + "mne/inverse_sparse/__init__.py": { + "a": 10, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 64, + "d": 84 + }, + "mne/io/_fiff_wrap.py": { + "a": 14, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 69, + "d": 63 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 7, + "d": 9 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 3 + }, + "mne/io/eeglab/_eeglab.py": { + "a": 7, + "d": 12 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 1 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 4, + "d": 2 + }, + "mne/io/fiff/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_read_raw.py": { + "a": 2, + "d": 2 + }, + "mne/label.py": { + "a": 2, + "d": 7 + }, + "mne/minimum_norm/__init__.py": { + "a": 34, + "d": 26 + }, + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 7 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 3, + "d": 2 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 3, + "d": 1 + }, + "mne/morph.py": { + "a": 2, + "d": 12 + }, + "mne/morph_map.py": { + "a": 2, + "d": 3 + }, + "mne/parallel.py": { + "a": 9, + "d": 2 + }, + "mne/preprocessing/__init__.py": { + "a": 50, + "d": 45 + }, + "mne/preprocessing/_annotate_amplitude.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/_csd.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/_regress.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 4, + "d": 7 + }, + "mne/preprocessing/bads.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/ctps_.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 15 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/infomax_.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/interpolate.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 8 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/realign.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/stim.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/xdawn.py": { + "a": 2, + "d": 5 + }, + "mne/rank.py": { + "a": 1, + "d": 2 + }, + "mne/report/__init__.py": { + "a": 11, + "d": 1 + }, + "mne/report/report.py": { + "a": 12, + "d": 20 + }, + "mne/simulation/__init__.py": { + "a": 16, + "d": 5 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 2 + }, + "mne/simulation/metrics/metrics.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 15 + }, + "mne/source_space.py": { + "a": 10, + "d": 17 + }, + "mne/stats/__init__.py": { + "a": 31, + "d": 19 + }, + "mne/stats/_adjacency.py": { + "a": 1, + "d": 2 + }, + "mne/stats/cluster_level.py": { + "a": 6, + "d": 18 + }, + "mne/stats/parametric.py": { + "a": 7, + "d": 11 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 6 + }, + "mne/surface.py": { + "a": 6, + "d": 14 + }, + "mne/tests/test_import_nesting.py": { + "a": 12, + "d": 10 + }, + "mne/time_frequency/__init__.py": { + "a": 48, + "d": 29 + }, + "mne/time_frequency/_stft.py": { + "a": 2, + "d": 6 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 6 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/multitaper.py": { + "a": 4, + "d": 8 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/spectrum.py": { + "a": 4, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 6 + }, + "mne/transforms.py": { + "a": 4, + "d": 11 + }, + "mne/utils/__init__.py": { + "a": 204, + "d": 211 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 17, + "d": 0 + }, + "mne/utils/linalg.py": { + "a": 3, + "d": 13 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 6 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 7 + }, + "mne/viz/__init__.py": { + "a": 102, + "d": 87 + }, + "mne/viz/_brain/_brain.py": { + "a": 4, + "d": 7 + }, + "mne/viz/_dipole.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 6, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 4, + "d": 2 + }, + "mne/viz/montage.py": { + "a": 5, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 5, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 38, + "d": 21 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 4 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "requirements_base.txt": { + "a": 1, + "d": 0 + }, + "tools/github_actions_env_vars.sh": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11839.json b/mne-python/source/doc/sphinxext/prs/11839.json new file mode 100644 index 0000000000000000000000000000000000000000..e385589d4067a80d4ba35660efdd13f48d49d474 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11839.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0d4550b77f2e546f37e69ba4c709cb71132b1848", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + ".git-blame-ignore-revs": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 413 + }, + "mne/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/evoked.py": { + "a": 3, + "d": 1 + }, + "mne/io/base.py": { + "a": 9, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 424, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1184.json b/mne-python/source/doc/sphinxext/prs/1184.json new file mode 100644 index 0000000000000000000000000000000000000000..c1bf6d1e9e89d5ea25cd3e84e98ff6dde7dcb2f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1184.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "50fe6bb67d9a85d1d0c4579060b67c50a31c3ef7", + "authors": [ + { + "n": "Tanay Gahlot", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11841.json b/mne-python/source/doc/sphinxext/prs/11841.json new file mode 100644 index 0000000000000000000000000000000000000000..88142ad8cff177947b00f42126927020c73a3b2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11841.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "269d06d57d2adb24449539e6d99e569464ea5d9b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11842.json b/mne-python/source/doc/sphinxext/prs/11842.json new file mode 100644 index 0000000000000000000000000000000000000000..cc7403489a679cb6f09ed850a462f14961c857c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11842.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4f8295490c731d75b6763d710242c789e09c3ce2", + "authors": [ + { + "n": "Hamza Abdelhedi", + "e": "hamzaabdelhedi18@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11844.json b/mne-python/source/doc/sphinxext/prs/11844.json new file mode 100644 index 0000000000000000000000000000000000000000..4c90a0fdd23a53e4d046a8c8759307dded058dd2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11844.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1bd2cbcce26c5dbbdc5eb5ab0c8c0f018ba4a893", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 5, + "d": 4 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 4, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 0 + }, + "requirements_testing.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11846.json b/mne-python/source/doc/sphinxext/prs/11846.json new file mode 100644 index 0000000000000000000000000000000000000000..ffc1e507ec354235a57487c5ec2d9231064acd86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11846.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "64f384608b63ab6962d1e80c8c9ff1c2453d41b4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/overview/faq.rst": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 28, + "d": 104 + }, + "mne/decoding/receptive_field.py": { + "a": 16, + "d": 6 + }, + "mne/decoding/search_light.py": { + "a": 36, + "d": 10 + }, + "mne/decoding/tests/test_base.py": { + "a": 24, + "d": 2 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 39, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 25, + "d": 0 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 15, + "d": 3 + }, + "mne/fixes.py": { + "a": 1, + "d": 32 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11847.json b/mne-python/source/doc/sphinxext/prs/11847.json new file mode 100644 index 0000000000000000000000000000000000000000..5a7e024f4e33ffb485a605a1988976f6be8a11a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11847.json @@ -0,0 +1,219 @@ +{ + "merge_commit_sha": "b5a9a25d3fac7e4058b91efcadf6561b85aa45a3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_external.py": { + "a": 2, + "d": 4 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 5 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 4, + "d": 8 + }, + "mne/decoding/tests/test_base.py": { + "a": 4, + "d": 8 + }, + "mne/decoding/tests/test_csp.py": { + "a": 2, + "d": 3 + }, + "mne/decoding/tests/test_ems.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 6, + "d": 7 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 3, + "d": 5 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 2, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 6, + "d": 19 + }, + "mne/gui/tests/test_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 2 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 3, + "d": 3 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 2, + "d": 11 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 8, + "d": 13 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_what.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/eyetracking/tests/test_pupillometry.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 29 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 2, + "d": 4 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 3, + "d": 4 + }, + "mne/report/tests/test_report.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/metrics/tests/test_metrics.py": { + "a": 5, + "d": 6 + }, + "mne/stats/tests/test_adjacency.py": { + "a": 2, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 4, + "d": 4 + }, + "mne/stats/tests/test_regression.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 5 + }, + "mne/tests/test_cov.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 3, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 13, + "d": 18 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 6 + }, + "mne/tests/test_label.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_morph.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 14, + "d": 16 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 3, + "d": 4 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 3, + "d": 5 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 10, + "d": 14 + }, + "mne/utils/_testing.py": { + "a": 47, + "d": 32 + }, + "mne/utils/tests/test_config.py": { + "a": 1, + "d": 2 + }, + "mne/utils/tests/test_numerics.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 3, + "d": 7 + }, + "mne/viz/tests/test_scraper.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11849.json b/mne-python/source/doc/sphinxext/prs/11849.json new file mode 100644 index 0000000000000000000000000000000000000000..e6cd30975d84061e38be3b2ec0d39c6372996e86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11849.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "6e9ab0782890c5a3a6aac39159ccdb55a8e61223", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 6, + "d": 6 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 3, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 0 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11851.json b/mne-python/source/doc/sphinxext/prs/11851.json new file mode 100644 index 0000000000000000000000000000000000000000..c01546cc7309ffee00932e43f1a943e21b18dc5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11851.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2a39a3aa20eb52fa50fe40e99797f7dac3d99bf7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 16, + "d": 7 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 243, + "d": 249 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11852.json b/mne-python/source/doc/sphinxext/prs/11852.json new file mode 100644 index 0000000000000000000000000000000000000000..50266e31f5a7905ed1331fa085ff34a3b7d0b640 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11852.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "23542f5f1c6ebcc52c50471a0dbede85cd04a7b2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 9, + "d": 0 + }, + "mne/source_space.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11853.json b/mne-python/source/doc/sphinxext/prs/11853.json new file mode 100644 index 0000000000000000000000000000000000000000..6b9a953e43f1207f86a3ca2a6c0cbb02501ddc31 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11853.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "a6c07cb5cdf916ee345409ccc33c56db0043dfaf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/dipole.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 18, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/utils/mixin.py": { + "a": 85, + "d": 73 + }, + "mne/utils/tests/test_mixin.py": { + "a": 42, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11855.json b/mne-python/source/doc/sphinxext/prs/11855.json new file mode 100644 index 0000000000000000000000000000000000000000..ce7ec8d3678104a3fde6442b5e5e71ac93157e4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11855.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6f9b03c3811a81f81853f6bef88d13f985fd40c6", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 9, + "d": 10 + }, + "mne/viz/_mpl_figure.py": { + "a": 14, + "d": 24 + }, + "mne/viz/tests/test_raw.py": { + "a": 83, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11857.json b/mne-python/source/doc/sphinxext/prs/11857.json new file mode 100644 index 0000000000000000000000000000000000000000..12e7668bf5029a21c50b01cd3ebebbaeb81c33dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11857.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "69fbf81a4594acc5b42c024e9c9ead954c9ab443", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 4, + "d": 4 + }, + "mne/viz/_scraper.py": { + "a": 4, + "d": 2 + }, + "tutorials/clinical/60_sleep.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11858.json b/mne-python/source/doc/sphinxext/prs/11858.json new file mode 100644 index 0000000000000000000000000000000000000000..55bcc4f27925329c8784f3e827342e42f79f723a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11858.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bb6d542fdaa8efc85aa87255c886168bface24a9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 38, + "d": 19 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 1 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11859.json b/mne-python/source/doc/sphinxext/prs/11859.json new file mode 100644 index 0000000000000000000000000000000000000000..fb572f1234fafb62ab6a992d7ee8a4c8bf094d14 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11859.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "193e41093e8f9c888c1d56abbc86267200c15e53", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 65, + "d": 9 + }, + ".cirrus.yml": { + "a": 0, + "d": 44 + }, + "azure-pipelines.yml": { + "a": 11, + "d": 10 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tools/cirrus_dependencies.sh": { + "a": 0, + "d": 5 + }, + "tools/cirrus_install_python.sh": { + "a": 0, + "d": 6 + }, + "tools/get_testing_version.sh": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11862.json b/mne-python/source/doc/sphinxext/prs/11862.json new file mode 100644 index 0000000000000000000000000000000000000000..d74d53ec730baf45038658e7152e641aa320d346 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11862.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "34413d21ed2eae9bc6f411f44eb76ffd98e1b16f", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11863.json b/mne-python/source/doc/sphinxext/prs/11863.json new file mode 100644 index 0000000000000000000000000000000000000000..e4d8d3f4402a7fcf2af7532df44b74f796fb2121 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11863.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7ce2b2c9a7bf7d3fb4b98633fc89f3b5653d66d3", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "examples/visualization/sensor_noise_level.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11864.json b/mne-python/source/doc/sphinxext/prs/11864.json new file mode 100644 index 0000000000000000000000000000000000000000..b0fdfadb994d79c157b5d29a5fbf982219a3ff28 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11864.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "176b78c517e20c0b6b9ae98382395a91e78aa322", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/js/contrib-avatars.js": { + "a": 5, + "d": 3 + }, + "tools/generate_codemeta.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11865.json b/mne-python/source/doc/sphinxext/prs/11865.json new file mode 100644 index 0000000000000000000000000000000000000000..797c7c46de2477eed03048111b66ac22176aea41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11865.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "86dd11d988521abdae531a82a482c243eee28cca", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 2 + }, + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + }, + ".pre-commit-config.yaml": { + "a": 7, + "d": 0 + }, + ".yamllint.yml": { + "a": 16, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "codecov.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11867.json b/mne-python/source/doc/sphinxext/prs/11867.json new file mode 100644 index 0000000000000000000000000000000000000000..2b9eba4859dc25b6c70d177828c18a06a1e10bcf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11867.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7c4e27c65c05e2252005e827b9c13e5ad91077c3", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 3, + "d": 2 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11868.json b/mne-python/source/doc/sphinxext/prs/11868.json new file mode 100644 index 0000000000000000000000000000000000000000..8394f9103e3471a1e87f5f8869cda12b63303a6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11868.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "12395f9d9cf6ea3c72b225b62e052dd0d17d9889", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 490, + "d": 490 + }, + ".github/workflows/tests.yml": { + "a": 27, + "d": 27 + }, + ".pre-commit-config.yaml": { + "a": 37, + "d": 37 + }, + ".yamllint.yml": { + "a": 0, + "d": 8 + }, + "azure-pipelines.yml": { + "a": 286, + "d": 286 + }, + "environment.yml": { + "a": 56, + "d": 56 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11869.json b/mne-python/source/doc/sphinxext/prs/11869.json new file mode 100644 index 0000000000000000000000000000000000000000..e960d7a5bfacded8e5d262d2bbbc4d194690b585 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11869.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6e0f206595954c7815b2823a6dafb20c940586c9", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11872.json b/mne-python/source/doc/sphinxext/prs/11872.json new file mode 100644 index 0000000000000000000000000000000000000000..23c8b59c33452d9639a9d0d4c4578a0883171fe1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11872.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "baf1ad576c54918c95182a047e0a23183e64374d", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "mne/io/eyelink/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eyetracking/calibration.py": { + "a": 2, + "d": 7 + }, + "mne/preprocessing/eyetracking/tests/test_calibration.py": { + "a": 11, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11875.json b/mne-python/source/doc/sphinxext/prs/11875.json new file mode 100644 index 0000000000000000000000000000000000000000..d72d5ada6023fd81d55e4325b841a3794fcee648 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11875.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "2188c25a1534535643f3083e0c01beca2bd13630", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/_rap_music.py": { + "a": 4, + "d": 7 + }, + "mne/bem.py": { + "a": 2, + "d": 4 + }, + "mne/cov.py": { + "a": 2, + "d": 3 + }, + "mne/dipole.py": { + "a": 3, + "d": 7 + }, + "mne/forward/_field_interpolation.py": { + "a": 2, + "d": 3 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 3 + }, + "mne/io/proj.py": { + "a": 2, + "d": 3 + }, + "mne/label.py": { + "a": 2, + "d": 3 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 3, + "d": 2 + }, + "mne/proj.py": { + "a": 6, + "d": 9 + }, + "mne/tests/test_cov.py": { + "a": 5, + "d": 7 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11876.json b/mne-python/source/doc/sphinxext/prs/11876.json new file mode 100644 index 0000000000000000000000000000000000000000..9e416aed8a6214dc22343eea98eb0e6903fda339 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11876.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "9e85b2ec8887d3c918c82654daf56cac67076c6b", + "authors": [ + { + "n": "Dmitrii Altukhov", + "e": "dm.altukhov@ya.ru" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 11, + "d": 24 + }, + "mne/io/utils.py": { + "a": 15, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 40, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11877.json b/mne-python/source/doc/sphinxext/prs/11877.json new file mode 100644 index 0000000000000000000000000000000000000000..d7f848b44253e7643fc1301a44893b78bf4cf9d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11877.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2e357a6f9131208a0e5f69f6ca161f76dbf20f54", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "mne/io/eyelink/eyelink.py": { + "a": 6, + "d": 6 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11878.json b/mne-python/source/doc/sphinxext/prs/11878.json new file mode 100644 index 0000000000000000000000000000000000000000..212c53961b1f28f84de9dc7eebef084b593e93f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11878.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "522cf44e5327979ac734b99fb87792000aba3a04", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "mne/conftest.py": { + "a": 6, + "d": 2 + }, + "mne/viz/_mpl_figure.py": { + "a": 3, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11880.json b/mne-python/source/doc/sphinxext/prs/11880.json new file mode 100644 index 0000000000000000000000000000000000000000..9dfa5cc2755f4afbfda968d0a66a3975f7dd3874 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11880.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "039122abe7a8e744ac1e35a8a311a347351da47d", + "authors": [ + { + "n": "Dmitrii Altukhov", + "e": "dm.altukhov@ya.ru" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_epochs.py": { + "a": 111, + "d": 64 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11883.json b/mne-python/source/doc/sphinxext/prs/11883.json new file mode 100644 index 0000000000000000000000000000000000000000..8d64efdda3ee8757cdbc2d9d1ae4ca793631f794 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11883.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7c5ab0a9fb4c2e5f2fd3cfa05cef9d3ec05b94f8", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11884.json b/mne-python/source/doc/sphinxext/prs/11884.json new file mode 100644 index 0000000000000000000000000000000000000000..ca84ee2b2730ee5e4a5fb284e631e1f54e556f99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11884.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "75c83c3fa8be3a6f3a950dcd35ba222d460eb5b4", + "authors": [ + { + "n": "Dmitrii Altukhov", + "e": "dm.altukhov@ya.ru" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 100, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11886.json b/mne-python/source/doc/sphinxext/prs/11886.json new file mode 100644 index 0000000000000000000000000000000000000000..9b85394e708f8341eb31fa4f13ebf5c2f576c426 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11886.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "4dd4db9647338dab31c1ca8847331502efcea3b7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 4, + "d": 0 + }, + "CITATION.cff": { + "a": 39, + "d": 20 + }, + "SECURITY.md": { + "a": 3, + "d": 3 + }, + "codemeta.json": { + "a": 102, + "d": 48 + }, + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "doc/_static/versions.json": { + "a": 7, + "d": 2 + }, + "doc/changes/0.17.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.8.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/1.5.inc": { + "a": 30, + "d": 3 + }, + "doc/cited.rst": { + "a": 3, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11887.json b/mne-python/source/doc/sphinxext/prs/11887.json new file mode 100644 index 0000000000000000000000000000000000000000..f497890aa740367426abf935741c710160de2ade --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11887.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "84da5551c77a05596dc35362f004f98375f1a8de", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 6, + "d": 6 + }, + "doc/changes/latest.inc": { + "a": 34, + "d": 0 + }, + "doc/changes/latest.inc.template": { + "a": 1, + "d": 1 + }, + "doc/install/installers.rst": { + "a": 6, + "d": 6 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/io/eyelink/eyelink.py": { + "a": 12, + "d": 42 + }, + "mne/utils/__init__.py": { + "a": 0, + "d": 10 + }, + "mne/utils/_testing.py": { + "a": 0, + "d": 45 + }, + "mne/utils/check.py": { + "a": 0, + "d": 7 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 9 + }, + "mne/viz/tests/test_epochs.py": { + "a": 22, + "d": 25 + }, + "requirements_base.txt": { + "a": 3, + "d": 3 + }, + "tools/github_actions_env_vars.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11888.json b/mne-python/source/doc/sphinxext/prs/11888.json new file mode 100644 index 0000000000000000000000000000000000000000..37994e784947e534718c6080655da62c254d987a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11888.json @@ -0,0 +1,243 @@ +{ + "merge_commit_sha": "921e02701b3c6fede08ba77cef321ee3a064de96", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/_static/versions.json": { + "a": 2, + "d": 37 + }, + "doc/changes/devel.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/devel.rst.template": { + "a": 2, + "d": 2 + }, + "doc/changes/v0.1.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.10.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.11.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.12.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.13.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.14.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.15.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.16.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.17.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.18.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.19.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.2.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.20.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.21.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.22.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.23.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v0.24.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.3.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.4.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.5.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.6.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.7.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.8.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v0.9.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v1.0.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v1.1.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v1.2.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v1.3.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v1.4.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/v1.5.rst": { + "a": 0, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "doc/funding.rst": { + "a": 0, + "d": 2 + }, + "doc/glossary.rst": { + "a": 0, + "d": 2 + }, + "doc/install/advanced.rst": { + "a": 0, + "d": 2 + }, + "doc/install/check_installation.rst": { + "a": 0, + "d": 2 + }, + "doc/install/contributing.rst": { + "a": 0, + "d": 1 + }, + "doc/install/installers.rst": { + "a": 0, + "d": 2 + }, + "doc/install/manual_install.rst": { + "a": 0, + "d": 2 + }, + "doc/install/manual_install_python.rst": { + "a": 0, + "d": 2 + }, + "doc/install/mne_c.rst": { + "a": 0, + "d": 2 + }, + "doc/install/mne_tools_suite.rst": { + "a": 0, + "d": 2 + }, + "doc/links.inc": { + "a": 9, + "d": 94 + }, + "doc/old_versions/index.rst": { + "a": 18, + "d": 0 + }, + "doc/overview/design_philosophy.rst": { + "a": 0, + "d": 2 + }, + "doc/overview/faq.rst": { + "a": 0, + "d": 2 + }, + "doc/overview/get_help.rst": { + "a": 0, + "d": 2 + }, + "doc/overview/index.rst": { + "a": 0, + "d": 2 + }, + "doc/overview/learn_python.rst": { + "a": 0, + "d": 2 + }, + "doc/overview/matlab.rst": { + "a": 0, + "d": 2 + }, + "doc/overview/people.rst": { + "a": 0, + "d": 2 + }, + "doc/overview/roadmap.rst": { + "a": 0, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 36, + "d": 36 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 2 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11889.json b/mne-python/source/doc/sphinxext/prs/11889.json new file mode 100644 index 0000000000000000000000000000000000000000..0864757f9c22f4d36ac90bb9ba6a24d1de75be31 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11889.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f48b4899b35940d0dc2ece525ca264e0a92658b4", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11890.json b/mne-python/source/doc/sphinxext/prs/11890.json new file mode 100644 index 0000000000000000000000000000000000000000..744406fcfd31c7963b17a0e5d93ff4a69a2ae3fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11890.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "6fe2e1322afb6ae5f6816f05d8f85dd78678e1aa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/devel.rst.template": { + "a": 1, + "d": 1 + }, + "doc/changes/v1.3.rst": { + "a": 0, + "d": 9 + }, + "mne/html_templates/report/html.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/report/section.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/report/slider.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/report/js_and_css/report.js": { + "a": 13, + "d": 2 + }, + "mne/report/report.py": { + "a": 156, + "d": 150 + }, + "mne/report/tests/test_report.py": { + "a": 70, + "d": 6 + }, + "tutorials/intro/70_report.py": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11891.json b/mne-python/source/doc/sphinxext/prs/11891.json new file mode 100644 index 0000000000000000000000000000000000000000..1f2a5ff482980cc8f1189beac1e8750ee5f6e913 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11891.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "f3fac153135d6f2aa2ab53e08a7f443511550711", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 8, + "d": 0 + }, + "doc/visualization.rst": { + "a": 3, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 12, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 238, + "d": 137 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 13, + "d": 69 + }, + "mne/viz/_brain/callback.py": { + "a": 0, + "d": 118 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 60, + "d": 28 + }, + "mne/viz/backends/_abstract.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_ui_events.py": { + "a": 25, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ui_events.py": { + "a": 166, + "d": 42 + }, + "tutorials/visualization/20_ui_events.py": { + "a": 55, + "d": 43 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11896.json b/mne-python/source/doc/sphinxext/prs/11896.json new file mode 100644 index 0000000000000000000000000000000000000000..de588eab4bad94fdf9104b18d357c8c982e1a40d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11896.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9e0d1512beb9d51011e2c5a0dd1e0dba2ec292b6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 5 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11903.json b/mne-python/source/doc/sphinxext/prs/11903.json new file mode 100644 index 0000000000000000000000000000000000000000..fe116224f8be54ec95358cc4f78982b5448bc930 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11903.json @@ -0,0 +1,923 @@ +{ + "merge_commit_sha": "1e3206b28b4cc3cd9db05a022b7ea82cde4024e4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 9, + "d": 0 + }, + "doc/file_io.rst": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/mne_substitutions.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 5, + "d": 5 + }, + "mne/_fiff/__init__.py": { + "a": 25, + "d": 0 + }, + "mne/_fiff/_digitization.py": { + "a": 18, + "d": 47 + }, + "mne/_fiff/compensator.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/constants.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/ctf_comp.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/matrix.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 3, + "d": 4 + }, + "mne/_fiff/open.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/pick.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/proc_history.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/proj.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/reference.py": { + "a": 10, + "d": 5 + }, + "mne/_fiff/tag.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/tests/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/_fiff/tests/test_compensator.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tests/test_constants.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 14, + "d": 36 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 15, + "d": 9 + }, + "mne/_fiff/tests/test_proc_history.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 5, + "d": 4 + }, + "mne/_fiff/tests/test_show_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_what.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/tests/test_write.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tree.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/utils.py": { + "a": 0, + "d": 0 + }, + "mne/_fiff/what.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/write.py": { + "a": 0, + "d": 0 + }, + "mne/_freesurfer.py": { + "a": 8, + "d": 3 + }, + "mne/annotations.py": { + "a": 7, + "d": 7 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 6, + "d": 6 + }, + "mne/channels/channels.py": { + "a": 11, + "d": 14 + }, + "mne/channels/interpolation.py": { + "a": 3, + "d": 3 + }, + "mne/channels/layout.py": { + "a": 5, + "d": 5 + }, + "mne/channels/montage.py": { + "a": 5, + "d": 5 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_layout.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 2, + "d": 2 + }, + "mne/chpi.py": { + "a": 9, + "d": 8 + }, + "mne/conftest.py": { + "a": 3, + "d": 1 + }, + "mne/coreg.py": { + "a": 4, + "d": 4 + }, + "mne/cov.py": { + "a": 28, + "d": 24 + }, + "mne/datasets/limo/limo.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ssd.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 4, + "d": 4 + }, + "mne/epochs.py": { + "a": 12, + "d": 12 + }, + "mne/event.py": { + "a": 7, + "d": 7 + }, + "mne/evoked.py": { + "a": 8, + "d": 8 + }, + "mne/export/_egimff.py": { + "a": 1, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 8, + "d": 2 + }, + "mne/filter.py": { + "a": 5, + "d": 6 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 4, + "d": 4 + }, + "mne/forward/_make_forward.py": { + "a": 5, + "d": 4 + }, + "mne/forward/forward.py": { + "a": 14, + "d": 10 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 6, + "d": 6 + }, + "mne/gui/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 74, + "d": 24 + }, + "mne/io/_constants.py": { + "a": 16, + "d": 0 + }, + "mne/io/_meas_info.py": { + "a": 10, + "d": 0 + }, + "mne/io/_pick.py": { + "a": 27, + "d": 0 + }, + "mne/io/_proj.py": { + "a": 10, + "d": 0 + }, + "mne/io/_reference.py": { + "a": 10, + "d": 0 + }, + "mne/io/_tag.py": { + "a": 10, + "d": 0 + }, + "mne/io/_utils.py": { + "a": 10, + "d": 0 + }, + "mne/io/_write.py": { + "a": 10, + "d": 0 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 5, + "d": 5 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 23, + "d": 9 + }, + "mne/io/besa/besa.py": { + "a": 1, + "d": 1 + }, + "mne/io/boxy/boxy.py": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 4 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 6, + "d": 4 + }, + "mne/io/bti/read.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 3, + "d": 4 + }, + "mne/io/cnt/cnt.py": { + "a": 5, + "d": 5 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/eeg.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/hc.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 4, + "d": 5 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/trans.py": { + "a": 2, + "d": 2 + }, + "mne/io/curry/curry.py": { + "a": 5, + "d": 5 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 2, + "d": 2 + }, + "mne/io/diff.py": { + "a": 0, + "d": 40 + }, + "mne/io/edf/edf.py": { + "a": 4, + "d": 4 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 5, + "d": 5 + }, + "mne/io/egi/egi.py": { + "a": 3, + "d": 3 + }, + "mne/io/egi/egimff.py": { + "a": 4, + "d": 4 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/eximia/eximia.py": { + "a": 2, + "d": 2 + }, + "mne/io/eyelink/eyelink.py": { + "a": 2, + "d": 2 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 2, + "d": 2 + }, + "mne/io/fieldtrip/utils.py": { + "a": 4, + "d": 4 + }, + "mne/io/fiff/raw.py": { + "a": 13, + "d": 14 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 3 + }, + "mne/io/fil/fil.py": { + "a": 5, + "d": 5 + }, + "mne/io/fil/tests/test_fil.py": { + "a": 1, + "d": 1 + }, + "mne/io/hitachi/hitachi.py": { + "a": 3, + "d": 3 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 4, + "d": 4 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 5, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/nedf/nedf.py": { + "a": 2, + "d": 2 + }, + "mne/io/nedf/tests/test_nedf.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 4, + "d": 4 + }, + "mne/io/nihon/nihon.py": { + "a": 3, + "d": 3 + }, + "mne/io/nirx/nirx.py": { + "a": 3, + "d": 3 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/nsx/nsx.py": { + "a": 3, + "d": 3 + }, + "mne/io/nsx/tests/test_nsx.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/persyst.py": { + "a": 3, + "d": 3 + }, + "mne/io/snirf/_snirf.py": { + "a": 5, + "d": 5 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_deprecation.py": { + "a": 39, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 7, + "d": 8 + }, + "mne/minimum_norm/inverse.py": { + "a": 13, + "d": 9 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/morph_map.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_css.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/_regress.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/annotate_amplitude.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/eyetracking/_pupillometry.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/hfc.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 13, + "d": 13 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/interpolate.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 9, + "d": 7 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/stim.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_hfc.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 5, + "d": 5 + }, + "mne/rank.py": { + "a": 5, + "d": 7 + }, + "mne/report/report.py": { + "a": 3, + "d": 2 + }, + "mne/report/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 3 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 4 + }, + "mne/source_space.py": { + "a": 31, + "d": 20 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 20, + "d": 16 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_rank.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + }, + "mne/transforms.py": { + "a": 4, + "d": 4 + }, + "mne/utils/_testing.py": { + "a": 4, + "d": 4 + }, + "mne/utils/check.py": { + "a": 6, + "d": 6 + }, + "mne/utils/config.py": { + "a": 2, + "d": 2 + }, + "mne/utils/mixin.py": { + "a": 2, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 3 + }, + "mne/utils/tests/test_check.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_numerics.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 4 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_proj.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 7, + "d": 8 + }, + "mne/viz/misc.py": { + "a": 9, + "d": 4 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 5, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11904.json b/mne-python/source/doc/sphinxext/prs/11904.json new file mode 100644 index 0000000000000000000000000000000000000000..3b11c6efa4ac48e33af4766e7930031e27312431 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11904.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0306101af9f1c9317d1a4cdca574aa6e8f3374d7", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "examples/time_frequency/time_frequency_erds.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11905.json b/mne-python/source/doc/sphinxext/prs/11905.json new file mode 100644 index 0000000000000000000000000000000000000000..1c7770b6a7a03a6a326c2f23065525dbc5595ef0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11905.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1ee327014b9389962b70331f41b7de979e01140b", + "authors": [ + { + "n": "Dmitrii Altukhov", + "e": "dm.altukhov@ya.ru" + } + ], + "changes": { + "mne/io/base.py": { + "a": 5, + "d": 4 + }, + "mne/io/utils.py": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11907.json b/mne-python/source/doc/sphinxext/prs/11907.json new file mode 100644 index 0000000000000000000000000000000000000000..ee4188ee8e93c335e602b34611159fa187193af1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11907.json @@ -0,0 +1,471 @@ +{ + "merge_commit_sha": "1bed9ddbb8dd20af8c0072735c1f22062330ee8e", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 1 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/ems_filtering.py": { + "a": 2, + "d": 6 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 3, + "d": 3 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/custom_inverse_solver.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/gamma_map_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/multi_dipole_model.py": { + "a": 7, + "d": 6 + }, + "examples/inverse/multidict_reweighted_tfmxne.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/rap_music.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/source_space_snr.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/trap_music.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 3, + "d": 3 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 1, + "d": 3 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 1, + "d": 2 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/shift_evoked.py": { + "a": 1, + "d": 2 + }, + "examples/simulation/plot_stc_metrics.py": { + "a": 2, + "d": 2 + }, + "examples/stats/linear_regression_raw.py": { + "a": 6, + "d": 6 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/3d_to_2d.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/evoked_arrowmap.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/_fiff/reference.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 5, + "d": 5 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 5, + "d": 5 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 10, + "d": 15 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 8, + "d": 8 + }, + "mne/beamformer/tests/test_external.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 10, + "d": 10 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 3, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 19, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 1, + "d": 2 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 13, + "d": 13 + }, + "mne/forward/tests/test_forward.py": { + "a": 4, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 3, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 13, + "d": 13 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 8, + "d": 8 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 23, + "d": 15 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 18, + "d": 18 + }, + "mne/preprocessing/tests/test_otp.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 2, + "d": 2 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/tests/test_raw.py": { + "a": 9, + "d": 13 + }, + "mne/stats/tests/test_regression.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 8, + "d": 8 + }, + "mne/tests/test_dipole.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 13, + "d": 13 + }, + "mne/tests/test_event.py": { + "a": 7, + "d": 8 + }, + "mne/tests/test_evoked.py": { + "a": 9, + "d": 9 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_rank.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 6, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_check.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_numerics.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_proj.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 3 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_topo.py": { + "a": 8, + "d": 8 + }, + "mne/viz/tests/test_topomap.py": { + "a": 8, + "d": 8 + }, + "mne/viz/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/15_baseline_regression.py": { + "a": 2, + "d": 2 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/70_reading_eyetracking_data.py": { + "a": 2, + "d": 2 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 1, + "d": 0 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 7, + "d": 8 + }, + "tutorials/simulation/80_dics.py": { + "a": 3, + "d": 6 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 6, + "d": 11 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 3, + "d": 2 + }, + "tutorials/stats-sensor-space/70_cluster_rmANOVA_time_freq.py": { + "a": 1, + "d": 1 + }, + "tutorials/visualization/10_publication_figure.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11909.json b/mne-python/source/doc/sphinxext/prs/11909.json new file mode 100644 index 0000000000000000000000000000000000000000..438dbae142f714f4601c72bdac2295a33d2963d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11909.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d64981c5f26cbc85affe0edf3ad66b13521d51e5", + "authors": [ + { + "n": "John Veillette", + "e": "johnv@uchicago.edu" + } + ], + "changes": { + "doc/install/mne_tools_suite.rst": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1191.json b/mne-python/source/doc/sphinxext/prs/1191.json new file mode 100644 index 0000000000000000000000000000000000000000..ea811dd6990a36df806791b896703fce4e836eda --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1191.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2ee88da94eab2add694775971ae11b742c5fe6fc", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/fiff/brainvision/brainvision.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11910.json b/mne-python/source/doc/sphinxext/prs/11910.json new file mode 100644 index 0000000000000000000000000000000000000000..37df619ca031c0f5117681f1df52a736093a78ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11910.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4b9a778e8eb922d0b2437b818a6d039f2fe0a465", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 534, + "d": 5 + }, + "mne/io/eyelink/eyelink.py": { + "a": 18, + "d": 543 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 2, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/eyetracking/tests/test_pupillometry.py": { + "a": 1, + "d": 3 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 2, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11911.json b/mne-python/source/doc/sphinxext/prs/11911.json new file mode 100644 index 0000000000000000000000000000000000000000..859e5aadb9f52d3feeac0bccb7b9a6740da8e293 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11911.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3e32781376427a053ea04a4b92052e53241b96ab", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11912.json b/mne-python/source/doc/sphinxext/prs/11912.json new file mode 100644 index 0000000000000000000000000000000000000000..3ef5c54b7d314d35857eed2b554b02737cee7f53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11912.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "18aa019be069445a2bdb413a57089ea670b8446f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 4, + "d": 4 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 36, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 1, + "d": 1 + }, + "requirements_testing_extra.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11914.json b/mne-python/source/doc/sphinxext/prs/11914.json new file mode 100644 index 0000000000000000000000000000000000000000..87ddb4285774385f568594d3c35725d196a9711f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11914.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "74ab43a0bc61b9dbdc7fbf821d0b5ea176077313", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/__init__.py": { + "a": 5, + "d": 13 + }, + "mne/io/constants.py": { + "a": 0, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 0, + "d": 0 + }, + "mne/io/pick.py": { + "a": 0, + "d": 0 + }, + "mne/io/proj.py": { + "a": 0, + "d": 0 + }, + "mne/io/reference.py": { + "a": 0, + "d": 0 + }, + "mne/io/tag.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_deprecation.py": { + "a": 1, + "d": 1 + }, + "mne/io/utils.py": { + "a": 0, + "d": 0 + }, + "mne/io/write.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11915.json b/mne-python/source/doc/sphinxext/prs/11915.json new file mode 100644 index 0000000000000000000000000000000000000000..9223f7573acc41c90babd34905d1badbef6518af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11915.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e8e672b63b3d3e5e84d8881a4f5aac5f4bd214e1", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11916.json b/mne-python/source/doc/sphinxext/prs/11916.json new file mode 100644 index 0000000000000000000000000000000000000000..cd8e4c40ec2b2601097a36f3f8cc25801cc7478f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11916.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3960fe8e28771f9d84cb5fcf2898be10ede089cd", + "authors": [ + { + "n": "Nikolai M Chapochnikov", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11917.json b/mne-python/source/doc/sphinxext/prs/11917.json new file mode 100644 index 0000000000000000000000000000000000000000..c91376c3c1347e9ed6c625f3e7e717e7bf2d1d65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11917.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ca83201eed98c1b6716542a9aa9e29684538f613", + "authors": [ + { + "n": "Nikolai M Chapochnikov", + "e": null + } + ], + "changes": { + "mne/filter.py": { + "a": 6, + "d": 4 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11918.json b/mne-python/source/doc/sphinxext/prs/11918.json new file mode 100644 index 0000000000000000000000000000000000000000..a6e3f1a982e00a68410f6356f20257aec43c74d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11918.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "28d461420084dc714aec67ab370865ac5aa28d3e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/file_io.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 12, + "d": 4 + }, + "mne/_fiff/pick.py": { + "a": 0, + "d": 30 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/ssd.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/_fiff_wrap.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_annotate_amplitude.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_rank.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 8, + "d": 6 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 7 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11919.json b/mne-python/source/doc/sphinxext/prs/11919.json new file mode 100644 index 0000000000000000000000000000000000000000..aa5f3046b0a203e5ceaadf7e185046f619ce059a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11919.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "22ffe6f7a5560cc6a196c69e196007b8bcb13bfe", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 3, + "d": 2 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "mne/proj.py": { + "a": 65, + "d": 80 + }, + "mne/tests/test_proj.py": { + "a": 17, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1192.json b/mne-python/source/doc/sphinxext/prs/1192.json new file mode 100644 index 0000000000000000000000000000000000000000..d1f2daffab459923a16e4c960f5c28227c95c498 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1192.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "440b544a7e7178838bfb2c62521b9a28d9c57aaf", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 7, + "d": 1 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 110, + "d": 20 + }, + "mne/source_space.py": { + "a": 18, + "d": 3 + }, + "mne/tests/test_label.py": { + "a": 53, + "d": 12 + }, + "mne/tests/test_source_space.py": { + "a": 23, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11920.json b/mne-python/source/doc/sphinxext/prs/11920.json new file mode 100644 index 0000000000000000000000000000000000000000..aa836243c28772c3699f5ff0c95e0d1ae5310279 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11920.json @@ -0,0 +1,327 @@ +{ + "merge_commit_sha": "b33f3a83898823149e306901d94fd8de643ee4e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/__init__.py": { + "a": 4, + "d": 1 + }, + "mne/_fiff/__init__.py": { + "a": 5, + "d": 3 + }, + "mne/_fiff/meas_info.py": { + "a": 10, + "d": 9 + }, + "mne/_freesurfer.py": { + "a": 1, + "d": 4 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 1, + "d": 4 + }, + "mne/channels/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 43 + }, + "mne/channels/interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 5 + }, + "mne/channels/tests/test_montage.py": { + "a": 7, + "d": 2 + }, + "mne/chpi.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 4 + }, + "mne/dipole.py": { + "a": 2, + "d": 4 + }, + "mne/epochs.py": { + "a": 1, + "d": 6 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 14, + "d": 15 + }, + "mne/io/base.py": { + "a": 2, + "d": 5 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 2 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 2 + }, + "mne/io/eyelink/eyelink.py": { + "a": 1, + "d": 2 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 3, + "d": 5 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 4 + }, + "mne/io/kit/coreg.py": { + "a": 6, + "d": 7 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 2 + }, + "mne/label.py": { + "a": 5, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 3 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 2 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eyetracking/calibration.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 0, + "d": 2 + }, + "mne/report/report.py": { + "a": 8, + "d": 8 + }, + "mne/simulation/evoked.py": { + "a": 4, + "d": 6 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/source_space/__init__.py": { + "a": 54, + "d": 0 + }, + "mne/source_space/_source_space.py": { + "a": 28, + "d": 50 + }, + "mne/source_space/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 10, + "d": 4 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 12, + "d": 3 + }, + "mne/tests/test_import_nesting.py": { + "a": 218, + "d": 2 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 18, + "d": 10 + }, + "mne/time_frequency/tfr.py": { + "a": 12, + "d": 85 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 3, + "d": 6 + }, + "mne/utils/mixin.py": { + "a": 4, + "d": 23 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 10 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 5, + "d": 8 + }, + "mne/viz/_mpl_figure.py": { + "a": 9, + "d": 5 + }, + "mne/viz/backends/_utils.py": { + "a": 4, + "d": 8 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 12, + "d": 4 + }, + "mne/viz/misc.py": { + "a": 4, + "d": 3 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 17, + "d": 20 + }, + "mne/viz/utils.py": { + "a": 20, + "d": 3 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11921.json b/mne-python/source/doc/sphinxext/prs/11921.json new file mode 100644 index 0000000000000000000000000000000000000000..c1bc04d5ee5055fe2c36840f7827370d15643491 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11921.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "beb52bdeac0a9c637099739f5c1f126a384c4564", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/simulation/10_array_objs.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11923.json b/mne-python/source/doc/sphinxext/prs/11923.json new file mode 100644 index 0000000000000000000000000000000000000000..2939a9aeb06124be7408231494f73f5f83c69efc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11923.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "6a701d39b24c337c59295b38d88fd7e5ebaa25ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 0, + "d": 8 + }, + "mne/viz/backends/_pyvista.py": { + "a": 24, + "d": 34 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 2, + "d": 0 + }, + "tools/circleci_bash_env.sh": { + "a": 0, + "d": 1 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 1, + "d": 0 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 1, + "d": 1 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11925.json b/mne-python/source/doc/sphinxext/prs/11925.json new file mode 100644 index 0000000000000000000000000000000000000000..08a0b51fe8efa34eb85bad193074156a3e5ef511 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11925.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2d01672f77f7e5b124ddfbeecb3f745f99921609", + "authors": [ + { + "n": "Jack Zhang", + "e": "me@jackzhang.me" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 38, + "d": 14 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 69, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11926.json b/mne-python/source/doc/sphinxext/prs/11926.json new file mode 100644 index 0000000000000000000000000000000000000000..a5f9a8e359b4bdb1660353a9ef01c28e0140dfdb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11926.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "e8baea60027e10423e86f0cf0ec9eaa50238fa47", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 26, + "d": 7 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 43, + "d": 1 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "requirements_testing_extra.txt": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11927.json b/mne-python/source/doc/sphinxext/prs/11927.json new file mode 100644 index 0000000000000000000000000000000000000000..a9ddaa0df75ccb2dc2d96a82b5ed53a71eaeba16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11927.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4af14f493e28b0f28611ba62d971c1319577fa72", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 3, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11928.json b/mne-python/source/doc/sphinxext/prs/11928.json new file mode 100644 index 0000000000000000000000000000000000000000..652f175b7e4779a73bde38ea211573de0e3dfac3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11928.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f44636f00666b8eb869417960926d01690ff4f42", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/preprocessing.rst": { + "a": 5, + "d": 0 + }, + "mne/_fiff/proj.py": { + "a": 4, + "d": 3 + }, + "mne/proj.py": { + "a": 5, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 14, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11929.json b/mne-python/source/doc/sphinxext/prs/11929.json new file mode 100644 index 0000000000000000000000000000000000000000..f124ea131c4017c461cf95197e702ac1ec7bc993 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11929.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d31ff7a7c3f4374bae3a1f31fea35f05be0673e2", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1193.json b/mne-python/source/doc/sphinxext/prs/1193.json new file mode 100644 index 0000000000000000000000000000000000000000..8aff3930ab2f7acd3dfcc36f25049d19be0e8d9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1193.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "330a39178cb21c24931701c84a0fd9fffa95cd4e", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 25, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11930.json b/mne-python/source/doc/sphinxext/prs/11930.json new file mode 100644 index 0000000000000000000000000000000000000000..be445aea069b320692b787a02a35560b51a080c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11930.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9627f43bb2c03233827046bc06acdab0968d6610", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/cov.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11932.json b/mne-python/source/doc/sphinxext/prs/11932.json new file mode 100644 index 0000000000000000000000000000000000000000..704d0d8227561bbe9206d216b382b59e236ef407 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11932.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e94f255675c9287e8f69ca08db20a1eb6ada8a69", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "mne/utils/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 46, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 9, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11934.json b/mne-python/source/doc/sphinxext/prs/11934.json new file mode 100644 index 0000000000000000000000000000000000000000..62b512cec7844487583c9a439c569fdc41061d3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11934.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a969c28702e2c4041335632b784493fc5cf8d8a3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 6, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 22, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11935.json b/mne-python/source/doc/sphinxext/prs/11935.json new file mode 100644 index 0000000000000000000000000000000000000000..ad3724d9899ddd8e69b58a48f7f347b1c48a9ee1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11935.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "82b2e82e42c5167f30df371f3ca7e18b86a2313a", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11937.json b/mne-python/source/doc/sphinxext/prs/11937.json new file mode 100644 index 0000000000000000000000000000000000000000..5e5215fe8736f4c6823025c57f2a2406b38210ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11937.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "4afa3f44ef389ef4d50fba4f17f3359e2733c5cc", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 11, + "d": 0 + }, + "README.rst": { + "a": 7, + "d": 1 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 2, + "d": 1 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 4, + "d": 5 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 1, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/_fetch.py": { + "a": 5, + "d": 6 + }, + "mne/html_templates/_templates.py": { + "a": 1, + "d": 2 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/events.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/general.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 12, + "d": 7 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 12, + "d": 4 + }, + "mne/io/nedf/nedf.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 2, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 1, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/utils/_testing.py": { + "a": 26, + "d": 42 + }, + "mne/utils/misc.py": { + "a": 10, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 6 + }, + "mne/utils/tests/test_bunch.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_scraper.py": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 3, + "d": 0 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "requirements_base.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11939.json b/mne-python/source/doc/sphinxext/prs/11939.json new file mode 100644 index 0000000000000000000000000000000000000000..7c259b73cfd96801245ebde9e2c53f76358c23ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11939.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "94aa16910d26264367d69472b52fb26cb08b29eb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 6, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11940.json b/mne-python/source/doc/sphinxext/prs/11940.json new file mode 100644 index 0000000000000000000000000000000000000000..c114c45c510659073d82e490252165a14ed1fd19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11940.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "99acd07823dc7018a09ccc8f1fa58a9e7ab884c2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 10, + "d": 5 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 4, + "d": 1 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11942.json b/mne-python/source/doc/sphinxext/prs/11942.json new file mode 100644 index 0000000000000000000000000000000000000000..73b52ac5f4eb46bc85a4588ffd5c417ba7104bf1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11942.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "d2883d577a151f57723d7380f9149abb4247165e", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/visualization.rst": { + "a": 4, + "d": 2 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 3, + "d": 3 + }, + "examples/visualization/mne_helmet.py": { + "a": 3, + "d": 1 + }, + "mne/evoked.py": { + "a": 8, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 58, + "d": 126 + }, + "mne/viz/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 16, + "d": 120 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 0, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 10, + "d": 3 + }, + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 185, + "d": 0 + }, + "mne/viz/evoked_field.py": { + "a": 575, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 59, + "d": 0 + }, + "mne/viz/tests/test_ui_events.py": { + "a": 0, + "d": 2 + }, + "mne/viz/ui_events.py": { + "a": 34, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 2 + }, + "tutorials/visualization/20_ui_events.py": { + "a": 30, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11944.json b/mne-python/source/doc/sphinxext/prs/11944.json new file mode 100644 index 0000000000000000000000000000000000000000..f5e9b4264d9a4ac17977d12a9475e7d8127c159b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11944.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7aec681b4e98e5245a25dd68ec95339239d22b15", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/manual_install.rst": { + "a": 10, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11946.json b/mne-python/source/doc/sphinxext/prs/11946.json new file mode 100644 index 0000000000000000000000000000000000000000..6fad3e1f6ea3f9c8d69fa31582bb2c5fa8dc99e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11946.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d5e125fb6367377262c94c0bbab593b67a2bf5cd", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 9, + "d": 10 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11948.json b/mne-python/source/doc/sphinxext/prs/11948.json new file mode 100644 index 0000000000000000000000000000000000000000..f1a5cd4ff331ad3a368176756e40c55dfc17da1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11948.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c83f0eccf42ebd513b05e1b31a50023680759b3d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/v1.2.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11950.json b/mne-python/source/doc/sphinxext/prs/11950.json new file mode 100644 index 0000000000000000000000000000000000000000..f6fdc8f8837b2d38a4102d421de11d5adb63c0b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11950.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0363feed5ac8f1d68c9c90878e5ca370761acd5f", + "authors": [ + { + "n": "Qian Chu", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/realign.py": { + "a": 27, + "d": 9 + }, + "mne/preprocessing/tests/test_realign.py": { + "a": 102, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11951.json b/mne-python/source/doc/sphinxext/prs/11951.json new file mode 100644 index 0000000000000000000000000000000000000000..8f8d4dbfdc3e612550042b298e5b3278c4af782b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11951.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "7503c4e7dc5cbff23175be37d135308bf73448cc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "examples/visualization/roi_erpimage_by_rt.py": { + "a": 1, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 34, + "d": 44 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 12, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 2 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11952.json b/mne-python/source/doc/sphinxext/prs/11952.json new file mode 100644 index 0000000000000000000000000000000000000000..47d8e70bb2a3b72635019bb4ad4582d0b31c544f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11952.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9fd1869f64aefa6386cc1384821f7c524ef771c0", + "authors": [ + { + "n": "Paul ROUJANSKY", + "e": "paul.roujansky@bioserenity.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 18, + "d": 11 + }, + "mne/export/tests/test_export.py": { + "a": 13, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 54, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 39, + "d": 4 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11953.json b/mne-python/source/doc/sphinxext/prs/11953.json new file mode 100644 index 0000000000000000000000000000000000000000..fea8af97bb514c47d95ab740d5c1bae0eded739c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11953.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3dd8899aaa8345d434f31cf0f0248d9c4eabfc5d", + "authors": [ + { + "n": "Dmitrii Altukhov", + "e": "dm.altukhov@ya.ru" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 140, + "d": 197 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 31, + "d": 6 + }, + "mne/io/nsx/tests/test_nsx.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11954.json b/mne-python/source/doc/sphinxext/prs/11954.json new file mode 100644 index 0000000000000000000000000000000000000000..8bc9bed959ff136f9f4515f66f9ef59cb29a4bd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11954.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "68ff5de17e4ca3cfe5a9ef9c8cf2c2473ec1d880", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11955.json b/mne-python/source/doc/sphinxext/prs/11955.json new file mode 100644 index 0000000000000000000000000000000000000000..3d92bbf92deef1920b4ee50c42f0bc0a48d1b627 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11955.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "53636038c463cfb13c2fc9c7b072f14fc30930e6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 12 + }, + "doc/install/check_installation.rst": { + "a": 35, + "d": 20 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 1, + "d": 2 + }, + "mne/coreg.py": { + "a": 2, + "d": 2 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/morph_map.py": { + "a": 1, + "d": 1 + }, + "mne/source_space/_source_space.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 7, + "d": 14 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 5 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 28 + }, + "requirements.txt": { + "a": 2, + "d": 2 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 0, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11956.json b/mne-python/source/doc/sphinxext/prs/11956.json new file mode 100644 index 0000000000000000000000000000000000000000..bf06ee6ae47fd8210eb9c6f615ab337daf39c57e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11956.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "db090a3157efc2b26778cdc314ab7ee41442cfe0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/overview/roadmap.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 3, + "d": 1 + }, + "mne/conftest.py": { + "a": 15, + "d": 3 + }, + "mne/utils/config.py": { + "a": 6, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 23, + "d": 8 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 7, + "d": 8 + }, + "mne/viz/backends/_notebook.py": { + "a": 49, + "d": 20 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + }, + "requirements.txt": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11957.json b/mne-python/source/doc/sphinxext/prs/11957.json new file mode 100644 index 0000000000000000000000000000000000000000..07c6d1e2a4401c6151ab3079a8b33cff96b8cf13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11957.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "98a1f20ce45bc3475212b47746e1642e02bde73d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/mne_c.rst": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11958.json b/mne-python/source/doc/sphinxext/prs/11958.json new file mode 100644 index 0000000000000000000000000000000000000000..470aec4459d68dbc11296e649776d09c27fd2719 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11958.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c6779a83864d67835329aad0cba6e67d4d9d520f", + "authors": [ + { + "n": "Andy Gilbert", + "e": "adgilbert21@icloud.com" + }, + { + "n": "Andrew Gilbert", + "e": "andrew.gilbert@irhythmtech.com" + }, + { + "n": "paulroujansky", + "e": "paul@roujansky.eu" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11960.json b/mne-python/source/doc/sphinxext/prs/11960.json new file mode 100644 index 0000000000000000000000000000000000000000..5e28432865b1a43ac8dd64d1d10dc20620038fac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11960.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "80524afe333ece39f27f4639a32d186b1eb485b0", + "authors": [ + { + "n": "Paul ROUJANSKY", + "e": "paul.roujansky@bioserenity.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 6, + "d": 2 + }, + "mne/export/_edf.py": { + "a": 21, + "d": 10 + }, + "mne/export/tests/test_export.py": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 27, + "d": 6 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 14, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11962.json b/mne-python/source/doc/sphinxext/prs/11962.json new file mode 100644 index 0000000000000000000000000000000000000000..54dc4e168a32cd941c5716d4465893d5e54720db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11962.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "33d5db7296c3df407d013a44b1684bf448b432cd", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_notebook.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11964.json b/mne-python/source/doc/sphinxext/prs/11964.json new file mode 100644 index 0000000000000000000000000000000000000000..e96338f4e39dd93ae4276c79efb05d65f2939a96 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11964.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5a135edb0323628ac38468f000a96cc4d75e24db", + "authors": [ + { + "n": "Paul ROUJANSKY", + "e": "paul.roujansky@bioserenity.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 1 + }, + "mne/annotations.py": { + "a": 18, + "d": 21 + }, + "mne/io/edf/edf.py": { + "a": 18, + "d": 13 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 20, + "d": 36 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11965.json b/mne-python/source/doc/sphinxext/prs/11965.json new file mode 100644 index 0000000000000000000000000000000000000000..f6d4526a14e0a02b6957553a90938ae2ec21c1b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11965.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1d7b2187516cb5f17f7c194e66e8546708d546c2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 0, + "d": 4 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 0, + "d": 7 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 1, + "d": 15 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11969.json b/mne-python/source/doc/sphinxext/prs/11969.json new file mode 100644 index 0000000000000000000000000000000000000000..ae10e280c348027e7eefc7b346c09acb55ed0ffa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11969.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "e2b3c03bf1b55863d5653ff091f3784e9ab34121", + "authors": [ + { + "n": "Kristijan Armeni", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 4, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/io/neuralynx/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 199, + "d": 0 + }, + "mne/io/neuralynx/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/neuralynx/tests/test_neuralynx.py": { + "a": 138, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11970.json b/mne-python/source/doc/sphinxext/prs/11970.json new file mode 100644 index 0000000000000000000000000000000000000000..607a766d562b2840650b22263d934a8fc577fff8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11970.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0d063a7c80c9e87dbf7d5ae537bc3c93b5c2229d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 34, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11971.json b/mne-python/source/doc/sphinxext/prs/11971.json new file mode 100644 index 0000000000000000000000000000000000000000..d5d54d34af23cc0a01bbbdad6aaa420370d7b816 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11971.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d1c26aa338b8f988263ba84e1552d5ae9cc9774c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".mailmap": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11972.json b/mne-python/source/doc/sphinxext/prs/11972.json new file mode 100644 index 0000000000000000000000000000000000000000..8c94784793f59427ff4caee083616c325c796ba1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11972.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "14ac07df6f5cb8f070a019a758e9283798fa0554", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11974.json b/mne-python/source/doc/sphinxext/prs/11974.json new file mode 100644 index 0000000000000000000000000000000000000000..515cf9ae35da01f0f8615f6a61d19641cf2df9ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11974.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "82c8b85f8c13e8a5db4a075f7b027b2f455c3994", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11975.json b/mne-python/source/doc/sphinxext/prs/11975.json new file mode 100644 index 0000000000000000000000000000000000000000..3abb9e0f75a165829cb1ffe61cf8ff179eae3c2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11975.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6bb318d43ae3d556f2bc637168bf2f97bdb93f75", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/check_steering_committee.py": { + "a": 58, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11976.json b/mne-python/source/doc/sphinxext/prs/11976.json new file mode 100644 index 0000000000000000000000000000000000000000..2192b4f559531ac1abd16b12eb2ce6fa9eca9365 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11976.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "48c6d7617694364cfa0882e706afe66cfefe7609", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 37, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11978.json b/mne-python/source/doc/sphinxext/prs/11978.json new file mode 100644 index 0000000000000000000000000000000000000000..d572ec449ed0cf76c995d5238a62016a0b7633b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11978.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "89d10ffa8519fd60fcfae460258113b5a14b425e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/spectrum.py": { + "a": 10, + "d": 2 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11979.json b/mne-python/source/doc/sphinxext/prs/11979.json new file mode 100644 index 0000000000000000000000000000000000000000..07d2613cdbd782b9ff6740e26d9fda4820cbd311 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11979.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5935f407f24556ae2c30fd407b4296d6b146b926", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 17, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11980.json b/mne-python/source/doc/sphinxext/prs/11980.json new file mode 100644 index 0000000000000000000000000000000000000000..604962ee4efda0cec48c81a1966a61b14eb7c150 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11980.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cc74f7329d576bddaa5ec5f767efab5985c819a8", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/codeql-analysis.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11981.json b/mne-python/source/doc/sphinxext/prs/11981.json new file mode 100644 index 0000000000000000000000000000000000000000..6aec5b6e841a8c499985cc86c595f8c6bcf60179 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11981.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dbc3aaa8e4d672518953eaf26cae16f374b83eef", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11982.json b/mne-python/source/doc/sphinxext/prs/11982.json new file mode 100644 index 0000000000000000000000000000000000000000..5a52097251996648647e9720bc9e065e8d62e5a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11982.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "201f1efa945243727a826f7b15f30d57a80038e6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11983.json b/mne-python/source/doc/sphinxext/prs/11983.json new file mode 100644 index 0000000000000000000000000000000000000000..98dc144adbcd461be6c00a57b71936e599178a0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11983.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2e3f8058cd3e609d36949ba005b15b8c597cd5b1", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11987.json b/mne-python/source/doc/sphinxext/prs/11987.json new file mode 100644 index 0000000000000000000000000000000000000000..a1d20e10c9cb6d0a38aad357e87cc7f18ac8ef69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11987.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "db3a7924beea9ab075b4aacbd2db4ce36588f446", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 25, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11988.json b/mne-python/source/doc/sphinxext/prs/11988.json new file mode 100644 index 0000000000000000000000000000000000000000..d53cf9831375b052e67887f481f3c578a253b533 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11988.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1dfcac7ff7d528a8e4b78ef82b8693a454fce679", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11989.json b/mne-python/source/doc/sphinxext/prs/11989.json new file mode 100644 index 0000000000000000000000000000000000000000..98949308aed573a1b533cb9d11235cdac15a7c60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11989.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cef0d3cb77dcb38aee2076fea97bdadb48267150", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 10, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1199.json b/mne-python/source/doc/sphinxext/prs/1199.json new file mode 100644 index 0000000000000000000000000000000000000000..c5a6daf7df47b01a63d03ca5f852f188faea3419 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1199.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "efd5b45a84e4d3147debc77cc8762a5ed3234369", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/fiff/meas_info.py": { + "a": 6, + "d": 5 + }, + "mne/fiff/tests/test_meas_info.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11993.json b/mne-python/source/doc/sphinxext/prs/11993.json new file mode 100644 index 0000000000000000000000000000000000000000..70364910930f428ee7548921b5b197102ef52641 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11993.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aae0122fcea3acaba1cd7b11ce3b838a366cda28", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 16, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11994.json b/mne-python/source/doc/sphinxext/prs/11994.json new file mode 100644 index 0000000000000000000000000000000000000000..4963c59cdc3f340483cd5118706d546ed6836b7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11994.json @@ -0,0 +1,227 @@ +{ + "merge_commit_sha": "ba127f705a0046cd30d9fb4bfcc610cf1d66bbfd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/evoked_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 3 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 9, + "d": 9 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 4 + }, + "mne/source_space/_source_space.py": { + "a": 3, + "d": 3 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_adjacency.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 9, + "d": 9 + }, + "mne/tests/test_morph.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_source_estimate.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 5, + "d": 5 + }, + "mne/utils/check.py": { + "a": 14, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_figure.py": { + "a": 6, + "d": 6 + }, + "mne/viz/_mpl_figure.py": { + "a": 7, + "d": 7 + }, + "mne/viz/_proj.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 10, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11996.json b/mne-python/source/doc/sphinxext/prs/11996.json new file mode 100644 index 0000000000000000000000000000000000000000..b0dbdab70d4d8562d0080c07a9932e2fa172e68e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11996.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5bc2190dfb07baaca2c688737191d2ef447b557f", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/check.py": { + "a": 13, + "d": 12 + }, + "tools/azure_dependencies.sh": { + "a": 15, + "d": 11 + }, + "tools/github_actions_dependencies.sh": { + "a": 19, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11997.json b/mne-python/source/doc/sphinxext/prs/11997.json new file mode 100644 index 0000000000000000000000000000000000000000..5706f5215e3b7bf1f725c66218a0701df96036a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11997.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e6afe5fb64c46df50256635b74cf583d5cc92727", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tools/dev_reports/Makefile": { + "a": 16, + "d": 0 + }, + "tools/dev_reports/check_steering_committee.py": { + "a": 0, + "d": 0 + }, + "tools/dev_reports/unacknowledged-bug-reports.jq": { + "a": 32, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/11999.json b/mne-python/source/doc/sphinxext/prs/11999.json new file mode 100644 index 0000000000000000000000000000000000000000..45ce3de4d2892faadcbeed2e6e02b7d3fc071201 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/11999.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "966bdcca9a6109fc771b69e08515ee4d39ff38cc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "examples/io/elekta_epochs.py": { + "a": 2, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 13, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 0, + "d": 1 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12.json b/mne-python/source/doc/sphinxext/prs/12.json new file mode 100644 index 0000000000000000000000000000000000000000..996e71426b8e601c2f69b3c8561d46e039e74606 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4073148134e4941d13fae7a8ac992bd09f27091d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/artifacts/ecg.py": { + "a": 30, + "d": 13 + }, + "mne/artifacts/tests/test_ecg.py": { + "a": 3, + "d": 3 + }, + "mne/epochs.py": { + "a": 22, + "d": 11 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12000.json b/mne-python/source/doc/sphinxext/prs/12000.json new file mode 100644 index 0000000000000000000000000000000000000000..b8c0dc74994dbf18d4d487a893a9cda374e711a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12000.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "77ba263489b86ee7ad8c8bf02c8e6cb10e0c74d8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 3, + "d": 0 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 65, + "d": 50 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 87, + "d": 22 + }, + "mne/viz/_brain/view.py": { + "a": 33, + "d": 24 + }, + "mne/viz/backends/_abstract.py": { + "a": 9, + "d": 9 + }, + "mne/viz/backends/_pyvista.py": { + "a": 62, + "d": 65 + }, + "mne/viz/backends/renderer.py": { + "a": 3, + "d": 2 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12001.json b/mne-python/source/doc/sphinxext/prs/12001.json new file mode 100644 index 0000000000000000000000000000000000000000..e5683ef29e3d75d7635b593ad94f3800557799f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12001.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "37ae7e37354fddc5eced35aa96973e3f944c9780", + "authors": [ + { + "n": "Hamza Abdelhedi", + "e": "hamzaabdelhedi18@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 15, + "d": 11 + }, + "mne/tests/test_source_estimate.py": { + "a": 38, + "d": 8 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12002.json b/mne-python/source/doc/sphinxext/prs/12002.json new file mode 100644 index 0000000000000000000000000000000000000000..80f6d64523381187094c314b9704684716784584 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12002.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "59b31604e7e106e74455e7b6fbc4282b74fbe933", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12003.json b/mne-python/source/doc/sphinxext/prs/12003.json new file mode 100644 index 0000000000000000000000000000000000000000..58d40c79acaa6f1c84a834f82313bfda05ddaa0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12003.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "9f19bd694ce131b95535dd706c4d856333caaf66", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 20, + "d": 13 + }, + "mne/io/eyelink/eyelink.py": { + "a": 12, + "d": 49 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 29, + "d": 1 + }, + "mne/preprocessing/realign.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 50, + "d": 0 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12004.json b/mne-python/source/doc/sphinxext/prs/12004.json new file mode 100644 index 0000000000000000000000000000000000000000..4d4e0502bdb902238b3bd061d4b3aaf99c28cae8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12004.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9de0ef64d8964ab97d40addc33d6965249df262a", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/transforms.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12005.json b/mne-python/source/doc/sphinxext/prs/12005.json new file mode 100644 index 0000000000000000000000000000000000000000..196fe89cd32536a9f3c4cf82b664aa2b46073a8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12005.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "034e9dce29a5754c7134aa4753ca81149ff3f55c", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/evoked_field.py": { + "a": 2, + "d": 1 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12006.json b/mne-python/source/doc/sphinxext/prs/12006.json new file mode 100644 index 0000000000000000000000000000000000000000..92efcac59be8686b420d25d3576b11e74044892f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12006.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "d79606beef83e0b77512668ceb4945364113efbc", + "authors": [ + { + "n": "Gonzalo Reina", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 3, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 12, + "d": 1 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 11, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12008.json b/mne-python/source/doc/sphinxext/prs/12008.json new file mode 100644 index 0000000000000000000000000000000000000000..c87587da84acfa9ecfaf119a014175784d7070a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12008.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8ee60d0db3001b855dd827738baff09aab10c627", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 1 + }, + ".gitignore": { + "a": 1, + "d": 0 + }, + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "tools/circleci_download.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12009.json b/mne-python/source/doc/sphinxext/prs/12009.json new file mode 100644 index 0000000000000000000000000000000000000000..d43b99b81acd00e91e7d0e87ebd6a76f4b12d929 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12009.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "7a91c470be872698dd21b5c76ab26c1bc3f4f10c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 4, + "d": 0 + }, + "mne/fixes.py": { + "a": 0, + "d": 20 + }, + "mne/transforms.py": { + "a": 7, + "d": 11 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 0 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 0, + "d": 3 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 2, + "d": 3 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12010.json b/mne-python/source/doc/sphinxext/prs/12010.json new file mode 100644 index 0000000000000000000000000000000000000000..48f3904061698fc699a01e8386f290603f74a52c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12010.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b9e907667531ecee36b1e7fa79d2c546a14eaf28", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12013.json b/mne-python/source/doc/sphinxext/prs/12013.json new file mode 100644 index 0000000000000000000000000000000000000000..cf24043297f445bb3e8e9ddcc40e921fc8746cd9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12013.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "079c868240a898204bf82b2f1bf0e04cdee75da1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 10, + "d": 1 + }, + "doc/install/contributing.rst": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12014.json b/mne-python/source/doc/sphinxext/prs/12014.json new file mode 100644 index 0000000000000000000000000000000000000000..4fc7272ec32660f5c77254ac66c99aed0c1cf369 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12014.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "9ed326f4124058bd6a61790964b4f84456a49e52", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "nordme", + "e": "nordme@uw.edu" + }, + { + "n": "nordme", + "e": "38704848+nordme@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 79, + "d": 0 + }, + "mne/channels/tests/test_unify_bads.py": { + "a": 53, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12016.json b/mne-python/source/doc/sphinxext/prs/12016.json new file mode 100644 index 0000000000000000000000000000000000000000..7e099f263e3a182946395814a62e16c632cdcadc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12016.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5c4166f43c9358fd7aa3d960686d78c1bbcd7513", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12017.json b/mne-python/source/doc/sphinxext/prs/12017.json new file mode 100644 index 0000000000000000000000000000000000000000..b3d13221fffa6de777a1777f7d511391d7a2d263 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12017.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "de86932602782c75166e0d3ff4270a824ce4d655", + "authors": [ + { + "n": "Paul ROUJANSKY", + "e": "paul.roujansky@bioserenity.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12019.json b/mne-python/source/doc/sphinxext/prs/12019.json new file mode 100644 index 0000000000000000000000000000000000000000..3b75d9e5625c8e44ab2594dbdd8b952a94b4256f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12019.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e5a9db2933b2a309b466097c6988ab8117cb6e19", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/pick.py": { + "a": 10, + "d": 7 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12020.json b/mne-python/source/doc/sphinxext/prs/12020.json new file mode 100644 index 0000000000000000000000000000000000000000..90e308fe4a1e6339964f1f0c2fab9bc71ddadb5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12020.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "e99ea74de08bd19559bdcad754175b8d4b1f831a", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/bem_model.rst": { + "a": 3, + "d": 2 + }, + "doc/_includes/forward.rst": { + "a": 1, + "d": 1 + }, + "doc/_includes/ssp.rst": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 30, + "d": 19 + }, + "mne/cov.py": { + "a": 5, + "d": 7 + }, + "mne/forward/_make_forward.py": { + "a": 6, + "d": 4 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 5 + }, + "mne/source_space/_source_space.py": { + "a": 25, + "d": 17 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 8 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 7, + "d": 10 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 11, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12021.json b/mne-python/source/doc/sphinxext/prs/12021.json new file mode 100644 index 0000000000000000000000000000000000000000..90851cad829f01022219909a564f0988a63bc863 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12021.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2138c173cee05651cab808526233037eaa4d8b94", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12023.json b/mne-python/source/doc/sphinxext/prs/12023.json new file mode 100644 index 0000000000000000000000000000000000000000..84bf5fb35c77d627c18830ac03bcdeeedeff4451 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12023.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "927f88daad73559d090f2016c3827f62ab7170a8", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 17, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12025.json b/mne-python/source/doc/sphinxext/prs/12025.json new file mode 100644 index 0000000000000000000000000000000000000000..7d1b2498618570aec1fe02828914e9e98b31ba10 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12025.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "578f2a9c56f41329be375669d0c79600cc57b6ad", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 10, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 14, + "d": 15 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 65, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12026.json b/mne-python/source/doc/sphinxext/prs/12026.json new file mode 100644 index 0000000000000000000000000000000000000000..11fbfdcd202f1429b7d090a13d610cf2371032be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12026.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "e4a6eba5d0a4c5f92b904207c33252f1979043db", + "authors": [ + { + "n": "nordme", + "e": "nordme@uw.edu" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/devel.rst": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 45, + "d": 3 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 140, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 203, + "d": 18 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12027.json b/mne-python/source/doc/sphinxext/prs/12027.json new file mode 100644 index 0000000000000000000000000000000000000000..53f0a34dc8d0c4b6a43bb56dd420d4237a266e5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12027.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9f31cf35945a3bb8924208a816072d541443a9eb", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 44, + "d": 9 + }, + "mne/channels/interpolation.py": { + "a": 17, + "d": 3 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 25, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12029.json b/mne-python/source/doc/sphinxext/prs/12029.json new file mode 100644 index 0000000000000000000000000000000000000000..a10644cb5456587164145b213cd935cdb3e99efa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12029.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "04e05d4d323b26af483dde38664cb817f7df8e8a", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12032.json b/mne-python/source/doc/sphinxext/prs/12032.json new file mode 100644 index 0000000000000000000000000000000000000000..3aaf6b8a2d4add3e1443c3514fc545b94200a761 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12032.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3eaf3c1c7f98b75c7f8ea52cc707faf18ce2c01c", + "authors": [ + { + "n": "Kristijan Armeni", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12033.json b/mne-python/source/doc/sphinxext/prs/12033.json new file mode 100644 index 0000000000000000000000000000000000000000..64d3fc7309a75dfacaadc516119ec10862bbde0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12033.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1def4bf8a84b09d465ffd613984ee2badd364a3c", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + } + ], + "changes": { + "tutorials/forward/20_source_alignment.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/30_forward.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12035.json b/mne-python/source/doc/sphinxext/prs/12035.json new file mode 100644 index 0000000000000000000000000000000000000000..2ea2612a9943b88eea18fef248b97a7eb412c58e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12035.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d52a0d3cfc26c43cb5e1c960b5441bd887ef4a54", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/time_frequency/time_frequency_erds.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12036.json b/mne-python/source/doc/sphinxext/prs/12036.json new file mode 100644 index 0000000000000000000000000000000000000000..67822ccb14f6930e317461df704c11a7a31965d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12036.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "bd4d1d6df252e499f52598733da15d0757bce173", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 3, + "d": 0 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 8, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 39, + "d": 8 + }, + "mne/forward/tests/test_forward.py": { + "a": 9, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12037.json b/mne-python/source/doc/sphinxext/prs/12037.json new file mode 100644 index 0000000000000000000000000000000000000000..824ffcf5512956a2b9f93f2d260725517eb68817 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12037.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9f22adbcb2dd478a8d618b8479e5765eaad49c9e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/release.yml": { + "a": 51, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12038.json b/mne-python/source/doc/sphinxext/prs/12038.json new file mode 100644 index 0000000000000000000000000000000000000000..2a550f672f8359763757819768d392b950990d9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12038.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3c3ec57feebbdddb826535fe16768db787519bae", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 10, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12039.json b/mne-python/source/doc/sphinxext/prs/12039.json new file mode 100644 index 0000000000000000000000000000000000000000..88be4474f009dd5b8c4e4d73cb291580ab7b6829 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12039.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "ff6bad289da40e08b82e4db010815c607a09d2a7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 51, + "d": 23 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 29, + "d": 7 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 4 + }, + "mne/io/artemis123/artemis123.py": { + "a": 7, + "d": 7 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_annotate_nan.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1204.json b/mne-python/source/doc/sphinxext/prs/1204.json new file mode 100644 index 0000000000000000000000000000000000000000..a0ccf08588ae3adb071bf00dfb1d2d6e4972cb91 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1204.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d8343a4f40db1adcfcee4fb53970797b5dc68b74", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/commands/mne_coreg.py": { + "a": 24, + "d": 0 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12040.json b/mne-python/source/doc/sphinxext/prs/12040.json new file mode 100644 index 0000000000000000000000000000000000000000..48d651ccd82c166b603999e3fd328073c2b22c44 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12040.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "110947f35abc93fd88f4e6b72f9e573dc25b355f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/dics_epochs.py": { + "a": 2, + "d": 7 + }, + "tutorials/intro/70_report.py": { + "a": 14, + "d": 33 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12041.json b/mne-python/source/doc/sphinxext/prs/12041.json new file mode 100644 index 0000000000000000000000000000000000000000..c1e8020ba62ec9dc133cf7ae920fc4b150ebfdec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12041.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "56587f33e2cd3fd253a29784cbe1781235aa0447", + "authors": [ + { + "n": "Maksym Balatsko", + "e": "mbalatsko@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12042.json b/mne-python/source/doc/sphinxext/prs/12042.json new file mode 100644 index 0000000000000000000000000000000000000000..95336a8a9e64d73a23989b7c4dbafda508ccd380 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12042.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e4afb0aa211ca2990ead7f4bd93adbf99ad007ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 0, + "d": 2 + }, + "doc/install/advanced.rst": { + "a": 8, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12043.json b/mne-python/source/doc/sphinxext/prs/12043.json new file mode 100644 index 0000000000000000000000000000000000000000..993e6015d2cdece484a4af4741480c7d973c62d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12043.json @@ -0,0 +1,219 @@ +{ + "merge_commit_sha": "c6863e5470a4ea312f0d7762d1ba4e9139d63785", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/flow_diagram.svg": { + "a": 0, + "d": 0 + }, + "doc/api/connectivity.rst": { + "a": 0, + "d": 0 + }, + "doc/api/covariance.rst": { + "a": 0, + "d": 0 + }, + "doc/api/creating_from_arrays.rst": { + "a": 0, + "d": 0 + }, + "doc/api/datasets.rst": { + "a": 0, + "d": 0 + }, + "doc/api/decoding.rst": { + "a": 0, + "d": 0 + }, + "doc/api/events.rst": { + "a": 0, + "d": 0 + }, + "doc/api/export.rst": { + "a": 0, + "d": 0 + }, + "doc/api/file_io.rst": { + "a": 0, + "d": 0 + }, + "doc/api/forward.rst": { + "a": 0, + "d": 0 + }, + "doc/api/inverse.rst": { + "a": 0, + "d": 0 + }, + "doc/api/logging.rst": { + "a": 0, + "d": 0 + }, + "doc/api/most_used_classes.rst": { + "a": 0, + "d": 0 + }, + "doc/api/mri.rst": { + "a": 0, + "d": 0 + }, + "doc/api/preprocessing.rst": { + "a": 0, + "d": 0 + }, + "doc/api/python_reference.rst": { + "a": 0, + "d": 0 + }, + "doc/api/reading_raw_data.rst": { + "a": 0, + "d": 0 + }, + "doc/api/realtime.rst": { + "a": 0, + "d": 0 + }, + "doc/api/report.rst": { + "a": 0, + "d": 0 + }, + "doc/api/sensor_space.rst": { + "a": 0, + "d": 0 + }, + "doc/api/simulation.rst": { + "a": 0, + "d": 0 + }, + "doc/api/source_space.rst": { + "a": 0, + "d": 0 + }, + "doc/api/statistics.rst": { + "a": 0, + "d": 0 + }, + "doc/api/time_frequency.rst": { + "a": 0, + "d": 0 + }, + "doc/api/visualization.rst": { + "a": 0, + "d": 0 + }, + "doc/conf.py": { + "a": 64, + "d": 22 + }, + "doc/development/contributing.rst": { + "a": 0, + "d": 0 + }, + "doc/development/governance.rst": { + "a": 0, + "d": 0 + }, + "doc/development/index.rst": { + "a": 2, + "d": 2 + }, + "doc/development/roadmap.rst": { + "a": 0, + "d": 0 + }, + "doc/development/whats_new.rst": { + "a": 42, + "d": 0 + }, + "doc/documentation/cite.rst": { + "a": 0, + "d": 0 + }, + "doc/documentation/cited.rst": { + "a": 0, + "d": 0 + }, + "doc/documentation/cookbook.rst": { + "a": 1, + "d": 1 + }, + "doc/documentation/datasets.rst": { + "a": 0, + "d": 0 + }, + "doc/documentation/design_philosophy.rst": { + "a": 0, + "d": 0 + }, + "doc/documentation/glossary.rst": { + "a": 0, + "d": 0 + }, + "doc/documentation/implementation.rst": { + "a": 0, + "d": 0 + }, + "doc/documentation/index.rst": { + "a": 8, + "d": 8 + }, + "doc/help/faq.rst": { + "a": 0, + "d": 0 + }, + "doc/help/index.rst": { + "a": 0, + "d": 0 + }, + "doc/help/learn_python.rst": { + "a": 0, + "d": 0 + }, + "doc/help/migrating.rst": { + "a": 0, + "d": 0 + }, + "doc/index.rst": { + "a": 4, + "d": 4 + }, + "doc/install/advanced.rst": { + "a": 0, + "d": 41 + }, + "doc/install/manual_install_python.rst": { + "a": 13, + "d": 141 + }, + "doc/install/mne_tools_suite.rst": { + "a": 3, + "d": 4 + }, + "doc/links.inc": { + "a": 2, + "d": 1 + }, + "doc/overview/images/Digitizer-example.png": { + "a": 0, + "d": 0 + }, + "doc/overview/matlab.rst": { + "a": 0, + "d": 1218 + }, + "doc/whats_new.rst": { + "a": 0, + "d": 42 + }, + "tutorials/io/70_reading_eyetracking_data.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12044.json b/mne-python/source/doc/sphinxext/prs/12044.json new file mode 100644 index 0000000000000000000000000000000000000000..c52829e79fe6a2f451d9ad51cab9262b9fca8c0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12044.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fd08b5273ed2e2c02cde409252e10b3b580f5f37", + "authors": [ + { + "n": "Paul ROUJANSKY", + "e": "paul.roujansky@bioserenity.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 16, + "d": 17 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 76, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12046.json b/mne-python/source/doc/sphinxext/prs/12046.json new file mode 100644 index 0000000000000000000000000000000000000000..9a34b658b2b0821f7c61ebc1323ee7561e2ecc8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12046.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d585ff4ad2672fce92b629da681b2b5057a85888", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/release.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12050.json b/mne-python/source/doc/sphinxext/prs/12050.json new file mode 100644 index 0000000000000000000000000000000000000000..28a61b2c0c35ebe1ba6720b0fff2c4db9392fb57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12050.json @@ -0,0 +1,303 @@ +{ + "merge_commit_sha": "fdaeb86206d334242bcbcfd09460c970b33e4dcd", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 2, + "d": 4 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 1, + "d": 2 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 5, + "d": 4 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 5, + "d": 11 + }, + "examples/inverse/label_source_activations.py": { + "a": 2, + "d": 4 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/source_space_snr.py": { + "a": 1, + "d": 2 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 2, + "d": 5 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 1, + "d": 2 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 1, + "d": 2 + }, + "examples/preprocessing/eog_regression.py": { + "a": 3, + "d": 4 + }, + "examples/preprocessing/shift_evoked.py": { + "a": 0, + "d": 3 + }, + "examples/simulation/plot_stc_metrics.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 8, + "d": 17 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 0, + "d": 1 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 5, + "d": 12 + }, + "examples/visualization/3d_to_2d.py": { + "a": 1, + "d": 2 + }, + "examples/visualization/evoked_topomap.py": { + "a": 1, + "d": 3 + }, + "mne/conftest.py": { + "a": 25, + "d": 13 + }, + "mne/preprocessing/eyetracking/calibration.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 0, + "d": 1 + }, + "mne/report/report.py": { + "a": 6, + "d": 24 + }, + "mne/time_frequency/spectrum.py": { + "a": 0, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 20, + "d": 18 + }, + "mne/viz/_3d.py": { + "a": 14, + "d": 12 + }, + "mne/viz/__init__.pyi": { + "a": 0, + "d": 2 + }, + "mne/viz/_dipole.py": { + "a": 1, + "d": 3 + }, + "mne/viz/_figure.py": { + "a": 1, + "d": 11 + }, + "mne/viz/_mpl_figure.py": { + "a": 23, + "d": 6 + }, + "mne/viz/_proj.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 2, + "d": 13 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 3, + "d": 0 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 11 + }, + "mne/viz/evoked.py": { + "a": 36, + "d": 39 + }, + "mne/viz/ica.py": { + "a": 8, + "d": 16 + }, + "mne/viz/misc.py": { + "a": 24, + "d": 27 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 8 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 3, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 4, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 38, + "d": 68 + }, + "mne/viz/utils.py": { + "a": 16, + "d": 143 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "requirements_base.txt": { + "a": 1, + "d": 1 + }, + "tools/github_actions_env_vars.sh": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 2, + "d": 5 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 1, + "d": 2 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 1, + "d": 2 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 20, + "d": 20 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 3, + "d": 7 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 0, + "d": 3 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 3, + "d": 2 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 1, + "d": 4 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 8, + "d": 7 + }, + "tutorials/preprocessing/80_opm_processing.py": { + "a": 6, + "d": 6 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 0, + "d": 1 + }, + "tutorials/simulation/80_dics.py": { + "a": 1, + "d": 2 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 6, + "d": 11 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 6, + "d": 11 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 1, + "d": 2 + }, + "tutorials/stats-sensor-space/70_cluster_rmANOVA_time_freq.py": { + "a": 3, + "d": 7 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 4, + "d": 9 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12052.json b/mne-python/source/doc/sphinxext/prs/12052.json new file mode 100644 index 0000000000000000000000000000000000000000..0d4a7bfaf3259fca202b477490ed96359475a521 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12052.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "40da6d9123debed6eaf8879c96c604b80c2f9f6e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/evoked_field.py": { + "a": 1, + "d": 1 + }, + "tutorials/visualization/20_ui_events.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12053.json b/mne-python/source/doc/sphinxext/prs/12053.json new file mode 100644 index 0000000000000000000000000000000000000000..351fbab88eda48485cad0a5068e9835f5cf142b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12053.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "de3b5a00e3883c010863642c57818d8cb862ca45", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12056.json b/mne-python/source/doc/sphinxext/prs/12056.json new file mode 100644 index 0000000000000000000000000000000000000000..014bd1bd6c08a8be6119e0d41d24bf0a11a166f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12056.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7c1429403e4beaa0dadb369512e2d5b1b1ed79fc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/js/set_installer_tab.js": { + "a": 32, + "d": 0 + }, + "doc/_static/js/update_installer_version.js": { + "a": 61, + "d": 0 + }, + "doc/install/installers.rst": { + "a": 4, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12057.json b/mne-python/source/doc/sphinxext/prs/12057.json new file mode 100644 index 0000000000000000000000000000000000000000..1e657584766a24b7a1d0931831bb38ad26fd1b09 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12057.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "cedefa0751adbf6d2be4531239019ef50302a8af", + "authors": [ + { + "n": "Santeri Ruuskanen", + "e": null + }, + { + "n": "Santeri Ruuskanen", + "e": "santeri.ruuskanen@aalto.fi" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_utils.py": { + "a": 73, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 62, + "d": 8 + }, + "mne/viz/ui_events.py": { + "a": 15, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 32, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12060.json b/mne-python/source/doc/sphinxext/prs/12060.json new file mode 100644 index 0000000000000000000000000000000000000000..16248e5803662288e06aba460dc44036074cdb73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12060.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "b069d4abd7bd7b39973c9fcbf0d9ada02b5e4b19", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_ola.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 3, + "d": 3 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/transformer.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 2 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 90, + "d": 3 + }, + "setup.py": { + "a": 0, + "d": 88 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 3, + "d": 3 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 4, + "d": 4 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12061.json b/mne-python/source/doc/sphinxext/prs/12061.json new file mode 100644 index 0000000000000000000000000000000000000000..084ca233666f0bbfc1e470d1f220628de0f292f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12061.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a8b4638cf415838425fba34d2773c1007ac99ee1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12063.json b/mne-python/source/doc/sphinxext/prs/12063.json new file mode 100644 index 0000000000000000000000000000000000000000..3b93f29d5a524ac3fbcdb92c71341dc50606808e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12063.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c65345ad5cdadb466a8351e5e173aeb9a577f2a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 8, + "d": 1 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12064.json b/mne-python/source/doc/sphinxext/prs/12064.json new file mode 100644 index 0000000000000000000000000000000000000000..d0c7aa2d582021aa347534190754864f8e217d63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12064.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "63ce95d4f0928e2ad035cb67c70ea06db44bd19f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 8, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/info.html.jinja": { + "a": 80, + "d": 10 + }, + "mne/html_templates/repr/raw.html.jinja": { + "a": 1, + "d": 12 + }, + "mne/io/base.py": { + "a": 5, + "d": 3 + }, + "mne/utils/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/30_info.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12065.json b/mne-python/source/doc/sphinxext/prs/12065.json new file mode 100644 index 0000000000000000000000000000000000000000..9119c5cdaaea49277799f6d378924d8c5f03d1d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12065.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9d20815494aca4ccf134bcc8758aadad3a9954ae", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 15, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12066.json b/mne-python/source/doc/sphinxext/prs/12066.json new file mode 100644 index 0000000000000000000000000000000000000000..cb78cc7a02cf908dbf4fed8d6eccf6120ec1805a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12066.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "27d1c59777061a4a94c6a5fc03e6e08fc6c0cf9a", + "authors": [ + { + "n": "Ivan Zubarev", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 9 + }, + "mne/channels/tests/test_channels.py": { + "a": 20, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 15, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12067.json b/mne-python/source/doc/sphinxext/prs/12067.json new file mode 100644 index 0000000000000000000000000000000000000000..f3b1bc08cd4e7fa247d53f649bd5118d81cd1698 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12067.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "905c12c6eac0b6bd67dc88707c32f1f804ae56fd", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/io/__init__.py": { + "a": 1, + "d": 44 + }, + "mne/io/tests/test_deprecation.py": { + "a": 0, + "d": 10 + }, + "mne/source_space/__init__.py": { + "a": 1, + "d": 33 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 0, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12068.json b/mne-python/source/doc/sphinxext/prs/12068.json new file mode 100644 index 0000000000000000000000000000000000000000..9e610fff87c7e485994c219f205d187d6f969a84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12068.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "05f1fa69fdddc2725bd3099280cd189e96a940f3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "mne/defaults.py": { + "a": 3, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 16, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 100, + "d": 106 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 11, + "d": 12 + }, + "mne/viz/tests/test_3d.py": { + "a": 6, + "d": 0 + }, + "tutorials/clinical/30_ecog.py": { + "a": 5, + "d": 4 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 0, + "d": 1 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12071.json b/mne-python/source/doc/sphinxext/prs/12071.json new file mode 100644 index 0000000000000000000000000000000000000000..09e7ab310dd311cdb9e567ce9edbdc1dfc84d672 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12071.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "aca49655b10fc17679142e07c5d46659be1099da", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12071.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 12, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 14, + "d": 25 + }, + "mne/viz/tests/test_topo.py": { + "a": 35, + "d": 1 + }, + "mne/viz/tests/test_utils.py": { + "a": 69, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 81, + "d": 15 + }, + "mne/viz/ui_events.py": { + "a": 20, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 108, + "d": 63 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12072.json b/mne-python/source/doc/sphinxext/prs/12072.json new file mode 100644 index 0000000000000000000000000000000000000000..325971112fbce75f1982516979dc36c0f26267cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12072.json @@ -0,0 +1,203 @@ +{ + "merge_commit_sha": "81b7ddfe3fc33f83ba7d472a6a67e714850d7c73", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 274 + }, + "mne/__init__.pyi": { + "a": 426, + "d": 0 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 32 + }, + "mne/beamformer/__init__.pyi": { + "a": 34, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 1, + "d": 47 + }, + "mne/channels/__init__.pyi": { + "a": 76, + "d": 0 + }, + "mne/commands/__init__.py": { + "a": 1, + "d": 6 + }, + "mne/commands/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 42 + }, + "mne/datasets/__init__.pyi": { + "a": 72, + "d": 0 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 23 + }, + "mne/decoding/__init__.pyi": { + "a": 40, + "d": 0 + }, + "mne/export/__init__.py": { + "a": 1, + "d": 9 + }, + "mne/export/__init__.pyi": { + "a": 3, + "d": 0 + }, + "mne/forward/__init__.py": { + "a": 2, + "d": 53 + }, + "mne/forward/__init__.pyi": { + "a": 86, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 6 + }, + "mne/gui/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/html_templates/__init__.py": { + "a": 1, + "d": 6 + }, + "mne/html_templates/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/inverse_sparse/__init__.py": { + "a": 1, + "d": 10 + }, + "mne/inverse_sparse/__init__.pyi": { + "a": 3, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 52 + }, + "mne/io/__init__.pyi": { + "a": 87, + "d": 0 + }, + "mne/minimum_norm/__init__.py": { + "a": 1, + "d": 34 + }, + "mne/minimum_norm/__init__.pyi": { + "a": 50, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 51 + }, + "mne/preprocessing/__init__.pyi": { + "a": 91, + "d": 0 + }, + "mne/report/__init__.py": { + "a": 1, + "d": 8 + }, + "mne/report/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/simulation/__init__.py": { + "a": 1, + "d": 15 + }, + "mne/simulation/__init__.pyi": { + "a": 22, + "d": 0 + }, + "mne/source_space/__init__.py": { + "a": 1, + "d": 19 + }, + "mne/source_space/__init__.pyi": { + "a": 22, + "d": 0 + }, + "mne/stats/__init__.py": { + "a": 1, + "d": 31 + }, + "mne/stats/__init__.pyi": { + "a": 42, + "d": 0 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 54 + }, + "mne/time_frequency/__init__.pyi": { + "a": 73, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 206 + }, + "mne/utils/__init__.pyi": { + "a": 384, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 106 + }, + "mne/viz/__init__.pyi": { + "a": 178, + "d": 0 + }, + "tools/dev/Makefile": { + "a": 0, + "d": 0 + }, + "tools/dev/check_steering_committee.py": { + "a": 0, + "d": 0 + }, + "tools/dev/generate_pyi_files.py": { + "a": 76, + "d": 0 + }, + "tools/dev/unacknowledged-bug-reports.jq": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12073.json b/mne-python/source/doc/sphinxext/prs/12073.json new file mode 100644 index 0000000000000000000000000000000000000000..b60f593532e2a411f890a5e6998db3a2a871a686 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12073.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5f7c9b90fdf89bf7b33ee75b74f79fdb1128d42a", + "authors": [ + { + "n": "Santeri Ruuskanen", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 10, + "d": 8 + }, + "mne/utils/docs.py": { + "a": 37, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12074.json b/mne-python/source/doc/sphinxext/prs/12074.json new file mode 100644 index 0000000000000000000000000000000000000000..052ba9728091373c5192543ae3ad4548c1aeb24e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12074.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5a83eaea91c48c8ac87a443b102b4509f88e8f50", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 4, + "d": 2 + }, + "examples/visualization/sensor_noise_level.py": { + "a": 0, + "d": 39 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 0, + "d": 1 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12076.json b/mne-python/source/doc/sphinxext/prs/12076.json new file mode 100644 index 0000000000000000000000000000000000000000..278a1c5bb171189d92832dd133241a36c4d01ac9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12076.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "643580122691d58e855f5f25124e78615fbcd933", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12077.json b/mne-python/source/doc/sphinxext/prs/12077.json new file mode 100644 index 0000000000000000000000000000000000000000..8e751ed4a0f9daf5c769c4538ebcdaa6cb23fb89 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12077.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "812b02ef0808bff97b32be54473de9bb986366db", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/js/contrib-avatars.js": { + "a": 1, + "d": 1 + }, + "doc/_templates/homepage.html": { + "a": 2, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 0, + "d": 3 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/_avatar_template.html": { + "a": 7, + "d": 0 + }, + "doc/sphinxext/contrib_avatars.py": { + "a": 34, + "d": 0 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + }, + "tools/circleci_bash_env.sh": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12078.json b/mne-python/source/doc/sphinxext/prs/12078.json new file mode 100644 index 0000000000000000000000000000000000000000..d68239ba266336475a8b2215c2a0a2466fd9e382 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12078.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "92f5dd8520a74a273872536365a144972a656e3c", + "authors": [ + { + "n": "Santeri Ruuskanen", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/utils/config.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1208.json b/mne-python/source/doc/sphinxext/prs/1208.json new file mode 100644 index 0000000000000000000000000000000000000000..281e05847a8e03ef327d7bdcea5d081b86259d69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1208.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cc92acc223956f9ca73d884bc4d73b51bfa2a389", + "authors": [ + { + "n": "aestrivex", + "e": "aestrivex@gmail.com" + } + ], + "changes": { + "mne/viz.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12080.json b/mne-python/source/doc/sphinxext/prs/12080.json new file mode 100644 index 0000000000000000000000000000000000000000..f66096107a83b7b6643340d20bbc0b869f19d98e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12080.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "23fa43c3df27428734aa23f7bca3911c52b29048", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/tag.py": { + "a": 6, + "d": 1 + }, + "mne/_fiff/write.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12081.json b/mne-python/source/doc/sphinxext/prs/12081.json new file mode 100644 index 0000000000000000000000000000000000000000..84ea50bc90eb67baf4a32e0b2a795270b3977c33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12081.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6aca4ece3080e49b936f4a94096b4b074f0713d2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12086.json b/mne-python/source/doc/sphinxext/prs/12086.json new file mode 100644 index 0000000000000000000000000000000000000000..6af5e4c4ddec6a8b6e4528199c693556a9c9b468 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12086.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "566fa0701f5c44324b330c8b21d8c8a434898e3e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 4, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 11, + "d": 4 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 3, + "d": 4 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12089.json b/mne-python/source/doc/sphinxext/prs/12089.json new file mode 100644 index 0000000000000000000000000000000000000000..383f8b4101e4531f1be9796ad4b06fe55d51ee77 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12089.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "647fdd309a6f4e386a246f522817f0ba3f616b6f", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1209.json b/mne-python/source/doc/sphinxext/prs/1209.json new file mode 100644 index 0000000000000000000000000000000000000000..7f7ac143746e430cd7143fe3a4ce02cd5b694a01 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1209.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0683f1290b801945acfe6d0b7c99cfc245e17a3b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 13, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12095.json b/mne-python/source/doc/sphinxext/prs/12095.json new file mode 100644 index 0000000000000000000000000000000000000000..01f138255a3e9f204b7750f975469e26a37fd52b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12095.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3b6a33954c1aeb2ee02db3e9840b1df00d8c3be3", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/_fiff/write.py": { + "a": 1, + "d": 2 + }, + "mne/chpi.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12097.json b/mne-python/source/doc/sphinxext/prs/12097.json new file mode 100644 index 0000000000000000000000000000000000000000..89a7cd6b905ba1a9889a528bb60a3d0c2780932f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12097.json @@ -0,0 +1,2431 @@ +{ + "merge_commit_sha": "d6d2f8c6a2ed4a0b27357da9ddf8e0cd14931b59", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "examples/datasets/hf_sef_data.py": { + "a": 2, + "d": 1 + }, + "examples/datasets/limo_data.py": { + "a": 3, + "d": 4 + }, + "examples/datasets/opm_data.py": { + "a": 1, + "d": 0 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 4, + "d": 5 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 6, + "d": 7 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 5, + "d": 7 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 4, + "d": 5 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 4, + "d": 5 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 1, + "d": 2 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 2, + "d": 3 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 5, + "d": 7 + }, + "examples/decoding/ems_filtering.py": { + "a": 3, + "d": 3 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 6, + "d": 7 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 5, + "d": 5 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 1, + "d": 0 + }, + "examples/forward/forward_sensitivity_maps.py": { + "a": 3, + "d": 2 + }, + "examples/inverse/compute_mne_inverse_epochs_in_label.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/custom_inverse_solver.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/dics_epochs.py": { + "a": 3, + "d": 2 + }, + "examples/inverse/dics_source_power.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 3, + "d": 2 + }, + "examples/inverse/gamma_map_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/label_activation_from_stc.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/label_from_stc.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/label_source_activations.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/mne_cov_power.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 3, + "d": 2 + }, + "examples/inverse/multi_dipole_model.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/multidict_reweighted_tfmxne.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 4, + "d": 6 + }, + "examples/inverse/psf_ctf_vertices.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/psf_ctf_vertices_lcmv.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/psf_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/rap_music.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/resolution_metrics.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/snr_estimate.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/source_space_snr.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/trap_music.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/vector_mne_solution.py": { + "a": 2, + "d": 1 + }, + "examples/io/elekta_epochs.py": { + "a": 2, + "d": 1 + }, + "examples/io/read_neo_format.py": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/css.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/define_target_events.py": { + "a": 3, + "d": 2 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/eog_regression.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/fnirs_artifact_removal.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/ica_comparison.py": { + "a": 1, + "d": 2 + }, + "examples/preprocessing/muscle_detection.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/shift_evoked.py": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/xdawn_denoising.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/plot_stc_metrics.py": { + "a": 7, + "d": 6 + }, + "examples/simulation/simulate_evoked_data.py": { + "a": 2, + "d": 2 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 6, + "d": 6 + }, + "examples/stats/cluster_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/fdr_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "examples/stats/sensor_regression.py": { + "a": 3, + "d": 2 + }, + "examples/time_frequency/compute_csd.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/compute_source_psd_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/source_power_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/temporal_whitening.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 4, + "d": 3 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 4, + "d": 4 + }, + "examples/visualization/3d_to_2d.py": { + "a": 6, + "d": 2 + }, + "examples/visualization/channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/evoked_arrowmap.py": { + "a": 2, + "d": 1 + }, + "examples/visualization/evoked_topomap.py": { + "a": 2, + "d": 2 + }, + "examples/visualization/evoked_whitening.py": { + "a": 1, + "d": 2 + }, + "examples/visualization/montage_sgskip.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/roi_erpimage_by_rt.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/ssp_projs_sensitivity_map.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/topo_compare_conditions.py": { + "a": 2, + "d": 2 + }, + "examples/visualization/topo_customized.py": { + "a": 2, + "d": 2 + }, + "mne/__init__.pyi": { + "a": 25, + "d": 25 + }, + "mne/_fiff/_digitization.py": { + "a": 3, + "d": 4 + }, + "mne/_fiff/compensator.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/ctf_comp.py": { + "a": 3, + "d": 4 + }, + "mne/_fiff/matrix.py": { + "a": 3, + "d": 3 + }, + "mne/_fiff/meas_info.py": { + "a": 68, + "d": 68 + }, + "mne/_fiff/open.py": { + "a": 4, + "d": 4 + }, + "mne/_fiff/pick.py": { + "a": 6, + "d": 6 + }, + "mne/_fiff/proc_history.py": { + "a": 10, + "d": 10 + }, + "mne/_fiff/proj.py": { + "a": 20, + "d": 20 + }, + "mne/_fiff/reference.py": { + "a": 17, + "d": 18 + }, + "mne/_fiff/tag.py": { + "a": 8, + "d": 8 + }, + "mne/_fiff/tests/test_compensator.py": { + "a": 3, + "d": 3 + }, + "mne/_fiff/tests/test_constants.py": { + "a": 4, + "d": 5 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 41, + "d": 41 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 23, + "d": 23 + }, + "mne/_fiff/tests/test_proc_history.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 13, + "d": 13 + }, + "mne/_fiff/tests/test_what.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tree.py": { + "a": 3, + "d": 4 + }, + "mne/_fiff/utils.py": { + "a": 2, + "d": 1 + }, + "mne/_fiff/what.py": { + "a": 6, + "d": 6 + }, + "mne/_fiff/write.py": { + "a": 4, + "d": 4 + }, + "mne/_freesurfer.py": { + "a": 11, + "d": 10 + }, + "mne/_ola.py": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 43, + "d": 42 + }, + "mne/baseline.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/__init__.pyi": { + "a": 10, + "d": 10 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 9, + "d": 9 + }, + "mne/beamformer/_dics.py": { + "a": 14, + "d": 14 + }, + "mne/beamformer/_lcmv.py": { + "a": 10, + "d": 10 + }, + "mne/beamformer/_rap_music.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 10, + "d": 10 + }, + "mne/beamformer/tests/test_external.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 18, + "d": 19 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 2, + "d": 3 + }, + "mne/beamformer/tests/test_resolution_matrix.py": { + "a": 2, + "d": 1 + }, + "mne/bem.py": { + "a": 32, + "d": 32 + }, + "mne/channels/__init__.pyi": { + "a": 17, + "d": 17 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 2, + "d": 4 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 5, + "d": 6 + }, + "mne/channels/channels.py": { + "a": 35, + "d": 35 + }, + "mne/channels/interpolation.py": { + "a": 3, + "d": 4 + }, + "mne/channels/layout.py": { + "a": 6, + "d": 6 + }, + "mne/channels/montage.py": { + "a": 36, + "d": 38 + }, + "mne/channels/tests/test_channels.py": { + "a": 25, + "d": 25 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 6, + "d": 7 + }, + "mne/channels/tests/test_layout.py": { + "a": 9, + "d": 9 + }, + "mne/channels/tests/test_montage.py": { + "a": 38, + "d": 41 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 6, + "d": 8 + }, + "mne/channels/tests/test_unify_bads.py": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 26, + "d": 26 + }, + "mne/commands/mne_anonymize.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_browse_raw.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_compare_fiff.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_maxfilter.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_prepare_bem_model.py": { + "a": 3, + "d": 2 + }, + "mne/commands/mne_report.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_setup_forward_model.py": { + "a": 3, + "d": 2 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_show_fiff.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_show_info.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_sys_info.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 1, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 17, + "d": 17 + }, + "mne/commands/utils.py": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 17, + "d": 17 + }, + "mne/coreg.py": { + "a": 26, + "d": 27 + }, + "mne/cov.py": { + "a": 52, + "d": 50 + }, + "mne/cuda.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/__init__.pyi": { + "a": 15, + "d": 15 + }, + "mne/datasets/_fetch.py": { + "a": 7, + "d": 8 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/_infant/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/_phantom/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 3, + "d": 3 + }, + "mne/datasets/epilepsy_ecog/_data.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/erp_core/erp_core.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/eyelink/eyelink.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/fnirs_motor/fnirs_motor.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 4, + "d": 3 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/limo/limo.py": { + "a": 4, + "d": 4 + }, + "mne/datasets/misc/_misc.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/mtrf/mtrf.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/opm/opm.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/phantom_4dbti/phantom_4dbti.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/refmeg_noise/refmeg_noise.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sample/sample.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 7, + "d": 2 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 8, + "d": 6 + }, + "mne/datasets/somato/somato.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 3, + "d": 4 + }, + "mne/datasets/ssvep/ssvep.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/testing/_testing.py": { + "a": 3, + "d": 3 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 6, + "d": 8 + }, + "mne/datasets/ucl_opm_auditory/ucl_opm_auditory.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 15, + "d": 15 + }, + "mne/datasets/visual_92_categories/visual_92_categories.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 7, + "d": 5 + }, + "mne/decoding/csp.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/ems.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/receptive_field.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/search_light.py": { + "a": 4, + "d": 3 + }, + "mne/decoding/ssd.py": { + "a": 6, + "d": 6 + }, + "mne/decoding/tests/test_base.py": { + "a": 16, + "d": 17 + }, + "mne/decoding/tests/test_csp.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/tests/test_ems.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 6, + "d": 7 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 9, + "d": 9 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 6, + "d": 7 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/time_frequency.py": { + "a": 4, + "d": 3 + }, + "mne/decoding/transformer.py": { + "a": 7, + "d": 8 + }, + "mne/dipole.py": { + "a": 28, + "d": 31 + }, + "mne/epochs.py": { + "a": 72, + "d": 73 + }, + "mne/event.py": { + "a": 14, + "d": 14 + }, + "mne/evoked.py": { + "a": 49, + "d": 50 + }, + "mne/export/__init__.pyi": { + "a": 1, + "d": 1 + }, + "mne/export/_edf.py": { + "a": 1, + "d": 0 + }, + "mne/export/_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/export/_egimff.py": { + "a": 4, + "d": 4 + }, + "mne/export/_export.py": { + "a": 1, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 11, + "d": 11 + }, + "mne/filter.py": { + "a": 11, + "d": 12 + }, + "mne/fixes.py": { + "a": 6, + "d": 5 + }, + "mne/forward/__init__.pyi": { + "a": 30, + "d": 30 + }, + "mne/forward/_compute_forward.py": { + "a": 6, + "d": 6 + }, + "mne/forward/_field_interpolation.py": { + "a": 10, + "d": 10 + }, + "mne/forward/_lead_dots.py": { + "a": 1, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 22, + "d": 24 + }, + "mne/forward/forward.py": { + "a": 37, + "d": 38 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 7, + "d": 9 + }, + "mne/forward/tests/test_forward.py": { + "a": 17, + "d": 17 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 29, + "d": 31 + }, + "mne/gui/__init__.pyi": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 34, + "d": 35 + }, + "mne/gui/_gui.py": { + "a": 3, + "d": 3 + }, + "mne/gui/tests/test_coreg.py": { + "a": 6, + "d": 6 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 3, + "d": 2 + }, + "mne/inverse_sparse/__init__.pyi": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 15, + "d": 16 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 6, + "d": 6 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 8, + "d": 8 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 14, + "d": 12 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 10, + "d": 10 + }, + "mne/io/__init__.pyi": { + "a": 25, + "d": 25 + }, + "mne/io/_fiff_wrap.py": { + "a": 6, + "d": 4 + }, + "mne/io/_read_raw.py": { + "a": 14, + "d": 14 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 6, + "d": 6 + }, + "mne/io/artemis123/artemis123.py": { + "a": 11, + "d": 11 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 6, + "d": 6 + }, + "mne/io/artemis123/utils.py": { + "a": 4, + "d": 2 + }, + "mne/io/base.py": { + "a": 55, + "d": 55 + }, + "mne/io/besa/besa.py": { + "a": 2, + "d": 1 + }, + "mne/io/besa/tests/test_besa.py": { + "a": 3, + "d": 3 + }, + "mne/io/boxy/boxy.py": { + "a": 2, + "d": 2 + }, + "mne/io/boxy/tests/test_boxy.py": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 3 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 7, + "d": 7 + }, + "mne/io/bti/bti.py": { + "a": 14, + "d": 14 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 15, + "d": 15 + }, + "mne/io/cnt/_utils.py": { + "a": 3, + "d": 3 + }, + "mne/io/cnt/cnt.py": { + "a": 8, + "d": 10 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 3, + "d": 3 + }, + "mne/io/ctf/ctf.py": { + "a": 11, + "d": 13 + }, + "mne/io/ctf/eeg.py": { + "a": 5, + "d": 5 + }, + "mne/io/ctf/hc.py": { + "a": 2, + "d": 3 + }, + "mne/io/ctf/info.py": { + "a": 10, + "d": 12 + }, + "mne/io/ctf/markers.py": { + "a": 3, + "d": 2 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 10, + "d": 10 + }, + "mne/io/ctf/trans.py": { + "a": 5, + "d": 5 + }, + "mne/io/curry/curry.py": { + "a": 11, + "d": 11 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 9, + "d": 10 + }, + "mne/io/edf/edf.py": { + "a": 6, + "d": 7 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 8, + "d": 9 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 4, + "d": 4 + }, + "mne/io/eeglab/eeglab.py": { + "a": 12, + "d": 11 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 7, + "d": 7 + }, + "mne/io/egi/egi.py": { + "a": 5, + "d": 5 + }, + "mne/io/egi/egimff.py": { + "a": 14, + "d": 14 + }, + "mne/io/egi/events.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/general.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 5, + "d": 5 + }, + "mne/io/eximia/eximia.py": { + "a": 3, + "d": 3 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 1, + "d": 1 + }, + "mne/io/eyelink/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/eyelink/eyelink.py": { + "a": 2, + "d": 2 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 4, + "d": 5 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 6, + "d": 6 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 1, + "d": 2 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 6, + "d": 6 + }, + "mne/io/fieldtrip/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 15, + "d": 17 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 21, + "d": 21 + }, + "mne/io/fil/fil.py": { + "a": 8, + "d": 9 + }, + "mne/io/fil/sensors.py": { + "a": 1, + "d": 0 + }, + "mne/io/fil/tests/test_fil.py": { + "a": 4, + "d": 7 + }, + "mne/io/hitachi/hitachi.py": { + "a": 4, + "d": 4 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 4, + "d": 5 + }, + "mne/io/kit/coreg.py": { + "a": 8, + "d": 9 + }, + "mne/io/kit/kit.py": { + "a": 15, + "d": 15 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 10, + "d": 10 + }, + "mne/io/nedf/nedf.py": { + "a": 3, + "d": 3 + }, + "mne/io/nedf/tests/test_nedf.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 8, + "d": 7 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 2, + "d": 2 + }, + "mne/io/nihon/nihon.py": { + "a": 3, + "d": 3 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 4, + "d": 4 + }, + "mne/io/nirx/nirx.py": { + "a": 15, + "d": 15 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 7, + "d": 7 + }, + "mne/io/nsx/nsx.py": { + "a": 3, + "d": 5 + }, + "mne/io/nsx/tests/test_nsx.py": { + "a": 5, + "d": 6 + }, + "mne/io/persyst/persyst.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 9, + "d": 8 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 8, + "d": 8 + }, + "mne/io/tests/test_apply_function.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 16, + "d": 16 + }, + "mne/io/tests/test_read_raw.py": { + "a": 1, + "d": 2 + }, + "mne/label.py": { + "a": 12, + "d": 12 + }, + "mne/minimum_norm/__init__.pyi": { + "a": 15, + "d": 15 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 31, + "d": 33 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 6, + "d": 6 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 31, + "d": 32 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 4, + "d": 3 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 7, + "d": 9 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 12, + "d": 12 + }, + "mne/morph.py": { + "a": 22, + "d": 17 + }, + "mne/morph_map.py": { + "a": 7, + "d": 7 + }, + "mne/parallel.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/__init__.pyi": { + "a": 29, + "d": 29 + }, + "mne/preprocessing/_annotate_amplitude.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/_csd.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/_css.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 11, + "d": 12 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_regress.py": { + "a": 8, + "d": 8 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 9, + "d": 9 + }, + "mne/preprocessing/ecg.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/eog.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/eyetracking/_pupillometry.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/eyetracking/tests/test_calibration.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/eyetracking/tests/test_pupillometry.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/hfc.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 61, + "d": 64 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 6, + "d": 5 + }, + "mne/preprocessing/ieeg/_volume.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/ieeg/tests/test_volume.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/interpolate.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 27, + "d": 28 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 13, + "d": 14 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/realign.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/stim.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/tests/test_annotate_amplitude.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_annotate_nan.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 6, + "d": 8 + }, + "mne/preprocessing/tests/test_css.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 6, + "d": 6 + }, + "mne/preprocessing/tests/test_hfc.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 21, + "d": 19 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 2, + "d": 5 + }, + "mne/preprocessing/tests/test_interpolate.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 19, + "d": 20 + }, + "mne/preprocessing/tests/test_otp.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/tests/test_peak_finder.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_realign.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 6, + "d": 7 + }, + "mne/preprocessing/xdawn.py": { + "a": 4, + "d": 4 + }, + "mne/proj.py": { + "a": 15, + "d": 15 + }, + "mne/rank.py": { + "a": 14, + "d": 14 + }, + "mne/report/__init__.pyi": { + "a": 1, + "d": 1 + }, + "mne/report/js_and_css/bootstrap-icons/gen_css_for_mne.py": { + "a": 2, + "d": 2 + }, + "mne/report/report.py": { + "a": 48, + "d": 49 + }, + "mne/report/tests/test_report.py": { + "a": 10, + "d": 11 + }, + "mne/simulation/__init__.pyi": { + "a": 4, + "d": 4 + }, + "mne/simulation/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/metrics/metrics.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/metrics/tests/test_metrics.py": { + "a": 5, + "d": 6 + }, + "mne/simulation/raw.py": { + "a": 19, + "d": 19 + }, + "mne/simulation/source.py": { + "a": 7, + "d": 7 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 10, + "d": 10 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 25, + "d": 25 + }, + "mne/simulation/tests/test_source.py": { + "a": 6, + "d": 7 + }, + "mne/source_estimate.py": { + "a": 30, + "d": 30 + }, + "mne/source_space/__init__.pyi": { + "a": 3, + "d": 3 + }, + "mne/source_space/_source_space.py": { + "a": 53, + "d": 54 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 20, + "d": 19 + }, + "mne/stats/__init__.pyi": { + "a": 13, + "d": 13 + }, + "mne/stats/_adjacency.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 12, + "d": 12 + }, + "mne/stats/parametric.py": { + "a": 1, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 2, + "d": 1 + }, + "mne/stats/regression.py": { + "a": 4, + "d": 4 + }, + "mne/stats/tests/test_adjacency.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 12, + "d": 13 + }, + "mne/stats/tests/test_multi_comp.py": { + "a": 3, + "d": 3 + }, + "mne/stats/tests/test_parametric.py": { + "a": 3, + "d": 3 + }, + "mne/stats/tests/test_permutations.py": { + "a": 3, + "d": 3 + }, + "mne/stats/tests/test_regression.py": { + "a": 2, + "d": 3 + }, + "mne/surface.py": { + "a": 23, + "d": 24 + }, + "mne/tests/test_annotations.py": { + "a": 22, + "d": 22 + }, + "mne/tests/test_bem.py": { + "a": 17, + "d": 17 + }, + "mne/tests/test_chpi.py": { + "a": 22, + "d": 22 + }, + "mne/tests/test_coreg.py": { + "a": 22, + "d": 22 + }, + "mne/tests/test_cov.py": { + "a": 24, + "d": 25 + }, + "mne/tests/test_defaults.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 26, + "d": 28 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 30, + "d": 30 + }, + "mne/tests/test_event.py": { + "a": 15, + "d": 15 + }, + "mne/tests/test_evoked.py": { + "a": 11, + "d": 11 + }, + "mne/tests/test_filter.py": { + "a": 17, + "d": 17 + }, + "mne/tests/test_freesurfer.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_import_nesting.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_label.py": { + "a": 19, + "d": 21 + }, + "mne/tests/test_line_endings.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_morph.py": { + "a": 17, + "d": 16 + }, + "mne/tests/test_morph_map.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_ola.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_parallel.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 15, + "d": 15 + }, + "mne/tests/test_rank.py": { + "a": 7, + "d": 9 + }, + "mne/tests/test_source_estimate.py": { + "a": 37, + "d": 38 + }, + "mne/tests/test_surface.py": { + "a": 14, + "d": 14 + }, + "mne/tests/test_transforms.py": { + "a": 31, + "d": 29 + }, + "mne/time_frequency/__init__.pyi": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/csd.py": { + "a": 13, + "d": 13 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 5, + "d": 5 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 14, + "d": 13 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 4, + "d": 5 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 8, + "d": 10 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 16, + "d": 16 + }, + "mne/time_frequency/tfr.py": { + "a": 37, + "d": 38 + }, + "mne/transforms.py": { + "a": 18, + "d": 19 + }, + "mne/utils/__init__.pyi": { + "a": 148, + "d": 148 + }, + "mne/utils/_bunch.py": { + "a": 0, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 6, + "d": 6 + }, + "mne/utils/_testing.py": { + "a": 7, + "d": 7 + }, + "mne/utils/check.py": { + "a": 14, + "d": 13 + }, + "mne/utils/config.py": { + "a": 2, + "d": 3 + }, + "mne/utils/dataframe.py": { + "a": 2, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 7, + "d": 7 + }, + "mne/utils/mixin.py": { + "a": 8, + "d": 9 + }, + "mne/utils/numerics.py": { + "a": 9, + "d": 9 + }, + "mne/utils/progressbar.py": { + "a": 4, + "d": 4 + }, + "mne/utils/spectrum.py": { + "a": 1, + "d": 0 + }, + "mne/utils/tests/test_bunch.py": { + "a": 2, + "d": 1 + }, + "mne/utils/tests/test_check.py": { + "a": 14, + "d": 14 + }, + "mne/utils/tests/test_config.py": { + "a": 6, + "d": 5 + }, + "mne/utils/tests/test_docs.py": { + "a": 6, + "d": 5 + }, + "mne/utils/tests/test_linalg.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_logging.py": { + "a": 9, + "d": 9 + }, + "mne/utils/tests/test_misc.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_mixin.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_numerics.py": { + "a": 22, + "d": 23 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 58, + "d": 55 + }, + "mne/viz/_3d_overlay.py": { + "a": 2, + "d": 1 + }, + "mne/viz/__init__.pyi": { + "a": 51, + "d": 51 + }, + "mne/viz/_brain/_brain.py": { + "a": 55, + "d": 56 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_scraper.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/surface.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 17, + "d": 18 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 10, + "d": 5 + }, + "mne/viz/_dipole.py": { + "a": 5, + "d": 5 + }, + "mne/viz/_figure.py": { + "a": 16, + "d": 8 + }, + "mne/viz/_mpl_figure.py": { + "a": 6, + "d": 5 + }, + "mne/viz/_proj.py": { + "a": 5, + "d": 4 + }, + "mne/viz/backends/_abstract.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 47, + "d": 49 + }, + "mne/viz/backends/_pyvista.py": { + "a": 22, + "d": 23 + }, + "mne/viz/backends/_qt.py": { + "a": 71, + "d": 71 + }, + "mne/viz/backends/_utils.py": { + "a": 6, + "d": 6 + }, + "mne/viz/backends/renderer.py": { + "a": 15, + "d": 15 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 5, + "d": 5 + }, + "mne/viz/circle.py": { + "a": 4, + "d": 4 + }, + "mne/viz/conftest.py": { + "a": 6, + "d": 6 + }, + "mne/viz/epochs.py": { + "a": 16, + "d": 16 + }, + "mne/viz/evoked.py": { + "a": 50, + "d": 46 + }, + "mne/viz/evoked_field.py": { + "a": 15, + "d": 19 + }, + "mne/viz/ica.py": { + "a": 24, + "d": 24 + }, + "mne/viz/misc.py": { + "a": 22, + "d": 20 + }, + "mne/viz/montage.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 9, + "d": 9 + }, + "mne/viz/tests/test_3d.py": { + "a": 30, + "d": 30 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 8, + "d": 8 + }, + "mne/viz/tests/test_figure.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 6, + "d": 6 + }, + "mne/viz/tests/test_misc.py": { + "a": 12, + "d": 12 + }, + "mne/viz/tests/test_montage.py": { + "a": 2, + "d": 3 + }, + "mne/viz/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_scraper.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 5, + "d": 7 + }, + "mne/viz/tests/test_topomap.py": { + "a": 21, + "d": 24 + }, + "mne/viz/tests/test_utils.py": { + "a": 12, + "d": 12 + }, + "mne/viz/topo.py": { + "a": 11, + "d": 8 + }, + "mne/viz/topomap.py": { + "a": 53, + "d": 39 + }, + "mne/viz/ui_events.py": { + "a": 6, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 37, + "d": 33 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/60_sleep.py": { + "a": 5, + "d": 8 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 1, + "d": 0 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 3, + "d": 2 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 2, + "d": 1 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 2, + "d": 2 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 4, + "d": 4 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 1, + "d": 0 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 0 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 1, + "d": 0 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 1, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 4, + "d": 2 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 4, + "d": 5 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 2, + "d": 2 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 3, + "d": 2 + }, + "tutorials/inverse/40_mne_fixed_free.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 3, + "d": 2 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 3, + "d": 3 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 3, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 1, + "d": 0 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 2, + "d": 2 + }, + "tutorials/io/70_reading_eyetracking_data.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 4, + "d": 5 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 6, + "d": 7 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 2, + "d": 3 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 3, + "d": 1 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 3, + "d": 1 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 5, + "d": 3 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 4, + "d": 2 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 3, + "d": 3 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 3, + "d": 1 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 2, + "d": 0 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 1, + "d": 0 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 2, + "d": 3 + }, + "tutorials/simulation/80_dics.py": { + "a": 4, + "d": 4 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 4, + "d": 4 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 3, + "d": 3 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 3, + "d": 3 + }, + "tutorials/stats-sensor-space/70_cluster_rmANOVA_time_freq.py": { + "a": 3, + "d": 3 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 5, + "d": 5 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 5, + "d": 6 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 2, + "d": 1 + }, + "tutorials/visualization/10_publication_figure.py": { + "a": 2, + "d": 2 + }, + "tutorials/visualization/20_ui_events.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12098.json b/mne-python/source/doc/sphinxext/prs/12098.json new file mode 100644 index 0000000000000000000000000000000000000000..f638ba02758e3fe8b878ab5bb0e6d658788b0b33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12098.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c7c8a2919734963726cd2d04fa9e01002b7f843c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 98, + "d": 40 + }, + "mne/gui/tests/test_coreg.py": { + "a": 6, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12099.json b/mne-python/source/doc/sphinxext/prs/12099.json new file mode 100644 index 0000000000000000000000000000000000000000..05076da29d9e3bb128d6b74b9d7f326b71a99a9e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12099.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e1545e6214f09ffe0a84fed0bef9a17bc1a6386f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_templates/sidebar-quicklinks.html": { + "a": 4, + "d": 4 + }, + "doc/conf.py": { + "a": 143, + "d": 119 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12102.json b/mne-python/source/doc/sphinxext/prs/12102.json new file mode 100644 index 0000000000000000000000000000000000000000..e9518ba5dd88ed905e4268b95de60147bb393141 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12102.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a5ce1cbf7b29fdfd964bd9eb36b10319d2b3025b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".git-blame-ignore-revs": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12103.json b/mne-python/source/doc/sphinxext/prs/12103.json new file mode 100644 index 0000000000000000000000000000000000000000..f5a39e071ca15bb0358b671919b8336e313af9a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12103.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a5eb54846d0d5efb6f2519490d23569516c17d6d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 10, + "d": 33 + }, + "mne/viz/epochs.py": { + "a": 13, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 6 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 0, + "d": 1 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 1, + "d": 0 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12105.json b/mne-python/source/doc/sphinxext/prs/12105.json new file mode 100644 index 0000000000000000000000000000000000000000..f07da264b096674cca9551ebb7e8e228485ef701 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12105.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "16f4411162b9d4a90fcecb2559c45d1191b09fb5", + "authors": [ + { + "n": "Judy D Zhu", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 7, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "doc/api/datasets.rst": { + "a": 2, + "d": 1 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/documentation/datasets.rst": { + "a": 12, + "d": 0 + }, + "doc/references.bib": { + "a": 13, + "d": 0 + }, + "mne/datasets/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 8, + "d": 0 + }, + "mne/datasets/phantom_kit/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/phantom_kit/phantom_kit.py": { + "a": 28, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 67, + "d": 2 + }, + "mne/event.py": { + "a": 13, + "d": 9 + }, + "mne/tests/test_dipole.py": { + "a": 18, + "d": 7 + }, + "mne/transforms.py": { + "a": 2, + "d": 25 + }, + "mne/utils/config.py": { + "a": 4, + "d": 4 + }, + "tools/circleci_download.sh": { + "a": 3, + "d": 0 + }, + "tutorials/inverse/95_phantom_KIT.py": { + "a": 186, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12110.json b/mne-python/source/doc/sphinxext/prs/12110.json new file mode 100644 index 0000000000000000000000000000000000000000..a3280398cf9b8d265c0a09b59a5405aef61f5a68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12110.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "875df8285e25ca4964566f2b900b808be65845d7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "Scott Huberty", + "e": "52462026+scott-huberty@users.noreply.github.com" + } + ], + "changes": { + "doc/api/covariance.rst": { + "a": 1, + "d": 1 + }, + "doc/api/creating_from_arrays.rst": { + "a": 1, + "d": 1 + }, + "doc/api/datasets.rst": { + "a": 1, + "d": 1 + }, + "doc/api/decoding.rst": { + "a": 2, + "d": 2 + }, + "doc/api/events.rst": { + "a": 3, + "d": 3 + }, + "doc/api/export.rst": { + "a": 1, + "d": 1 + }, + "doc/api/file_io.rst": { + "a": 2, + "d": 2 + }, + "doc/api/forward.rst": { + "a": 3, + "d": 3 + }, + "doc/api/inverse.rst": { + "a": 5, + "d": 5 + }, + "doc/api/logging.rst": { + "a": 3, + "d": 3 + }, + "doc/api/most_used_classes.rst": { + "a": 1, + "d": 1 + }, + "doc/api/mri.rst": { + "a": 1, + "d": 1 + }, + "doc/api/preprocessing.rst": { + "a": 11, + "d": 11 + }, + "doc/api/reading_raw_data.rst": { + "a": 3, + "d": 3 + }, + "doc/api/report.rst": { + "a": 1, + "d": 1 + }, + "doc/api/sensor_space.rst": { + "a": 2, + "d": 2 + }, + "doc/api/simulation.rst": { + "a": 2, + "d": 2 + }, + "doc/api/source_space.rst": { + "a": 1, + "d": 1 + }, + "doc/api/statistics.rst": { + "a": 4, + "d": 4 + }, + "doc/api/time_frequency.rst": { + "a": 4, + "d": 4 + }, + "doc/api/visualization.rst": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12113.json b/mne-python/source/doc/sphinxext/prs/12113.json new file mode 100644 index 0000000000000000000000000000000000000000..1da3a47bb0e70553cf0f27aa7875ef993b9151e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12113.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b45837b5e1e4606e25701b85e525caf2f87dd523", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 54, + "d": 50 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 24, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12115.json b/mne-python/source/doc/sphinxext/prs/12115.json new file mode 100644 index 0000000000000000000000000000000000000000..0ed212cd688840c7db3d8bb89500ff2a13239642 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12115.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4beb8dde7588c3153ee0a240b5e363dc987c95f1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12118.json b/mne-python/source/doc/sphinxext/prs/12118.json new file mode 100644 index 0000000000000000000000000000000000000000..c940c1f82d6577a63def4d33c81579d304c39c06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12118.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "60db738c20fbfc84cb5468252742610522974aac", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 72, + "d": 20 + }, + "mne/tests/test_epochs.py": { + "a": 86, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12119.json b/mne-python/source/doc/sphinxext/prs/12119.json new file mode 100644 index 0000000000000000000000000000000000000000..4fa23ce1421f94d3359291bebde767b1fec2604a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12119.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f555d5f7c7389a6a3960e83253828b60fc816ce1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1212.json b/mne-python/source/doc/sphinxext/prs/1212.json new file mode 100644 index 0000000000000000000000000000000000000000..a3f35d50e6f5eead086d2a09200c488070d3b702 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1212.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bf9cf919730414f911ddfc3e71cd361d145617b6", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12121.json b/mne-python/source/doc/sphinxext/prs/12121.json new file mode 100644 index 0000000000000000000000000000000000000000..d59b2944760f4f57b1150d7d0fb59a4b3e50ec57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12121.json @@ -0,0 +1,255 @@ +{ + "merge_commit_sha": "7b3e3c931914ee655486e7b8d5a5a30668ce136f", + "authors": [ + { + "n": "Pablo Mainar", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "examples/datasets/kernel_phantom.py": { + "a": 1, + "d": 0 + }, + "examples/datasets/limo_data.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/ems_filtering.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/otp.py": { + "a": 1, + "d": 2 + }, + "examples/stats/sensor_regression.py": { + "a": 8, + "d": 7 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 5, + "d": 9 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_csp.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 5, + "d": 5 + }, + "mne/epochs.py": { + "a": 107, + "d": 24 + }, + "mne/forward/_field_interpolation.py": { + "a": 5, + "d": 1 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 9, + "d": 9 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/xdawn.py": { + "a": 3, + "d": 3 + }, + "mne/rank.py": { + "a": 1, + "d": 2 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_regression.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 28, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_rank.py": { + "a": 21, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_mixin.py": { + "a": 5, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 4, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 3, + "d": 1 + }, + "tutorials/epochs/15_baseline_regression.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12122.json b/mne-python/source/doc/sphinxext/prs/12122.json new file mode 100644 index 0000000000000000000000000000000000000000..2c5c707ab7aaf74440f2bc2b653620dd1f0371a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12122.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c54d229913c5fe1bdb7a76b70930f66a89601c95", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/egimff.py": { + "a": 11, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12124.json b/mne-python/source/doc/sphinxext/prs/12124.json new file mode 100644 index 0000000000000000000000000000000000000000..91de2550750a2172b1f4c7bbeafafcda54227162 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12124.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8c003e843717e316ba85008eff2298917489bbd1", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12128.json b/mne-python/source/doc/sphinxext/prs/12128.json new file mode 100644 index 0000000000000000000000000000000000000000..df95be01bde7730edcbba73be6840cca24750c65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12128.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "89b5a533867012a122fc43dfe57a18ad530c5906", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/utils/check.py": { + "a": 1, + "d": 2 + }, + "mne/utils/tests/test_check.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12129.json b/mne-python/source/doc/sphinxext/prs/12129.json new file mode 100644 index 0000000000000000000000000000000000000000..9f2283e1f512c01b3860d3d1d032bd47d9382bc2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12129.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a320b631a7c5b06201505f7f86b1d163074d8420", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1213.json b/mne-python/source/doc/sphinxext/prs/1213.json new file mode 100644 index 0000000000000000000000000000000000000000..97b205e5b13661b158a60a121b6a5b964bc3dbce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1213.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "78a29b5b50797da0c80754ab4cd36380c743b769", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 101, + "d": 1 + }, + "mne/fiff/meas_info.py": { + "a": 140, + "d": 2 + }, + "mne/fiff/proj.py": { + "a": 22, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 107, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12133.json b/mne-python/source/doc/sphinxext/prs/12133.json new file mode 100644 index 0000000000000000000000000000000000000000..be89431f29dec1fca2c3c1b3c5dbdafb5d4ed44b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12133.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4518a1a918051542ab7360ff63c529121a499417", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/development/governance.rst": { + "a": 1, + "d": 1 + }, + "doc/overview/people.rst": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12135.json b/mne-python/source/doc/sphinxext/prs/12135.json new file mode 100644 index 0000000000000000000000000000000000000000..bbbac60bf7020c333896f4dcb4bf20e5e4932781 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12135.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "debc275b795ea4cf4da72a74ee586c82b2e154fc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/io/bti/read.py": { + "a": 9, + "d": 3 + }, + "mne/io/ctf/res4.py": { + "a": 16, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/egi/egi.py": { + "a": 3, + "d": 3 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/nihon/nihon.py": { + "a": 4, + "d": 4 + }, + "mne/io/nsx/nsx.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/realign.py": { + "a": 7, + "d": 6 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 0 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12139.json b/mne-python/source/doc/sphinxext/prs/12139.json new file mode 100644 index 0000000000000000000000000000000000000000..5a01db2f469e4a1e8e44ea95d45043f51824b6fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12139.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c733e7b4d471eb72231b6492aa3031efc28d426d", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + ".lgtm.yml": { + "a": 0, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12140.json b/mne-python/source/doc/sphinxext/prs/12140.json new file mode 100644 index 0000000000000000000000000000000000000000..83e14c8be02d6bc560e86f5362befffa9875c32b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12140.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b9983df4673dbcb36155509c3b3c4b4352798402", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "examples/preprocessing/eeg_bridging.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12142.json b/mne-python/source/doc/sphinxext/prs/12142.json new file mode 100644 index 0000000000000000000000000000000000000000..7d39a4dd78032f65f44d0f9ad0cae05989b3e6dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12142.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "cdad29dac30041ee79d4e719cb53ad63ffdf21a9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 11, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 3 + }, + "mne/viz/tests/test_evoked.py": { + "a": 7, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12143.json b/mne-python/source/doc/sphinxext/prs/12143.json new file mode 100644 index 0000000000000000000000000000000000000000..feb0f47f0305576c42f81f5470e7ff495afaeec6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12143.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "58e8c7e779e741fe4168b4b0dd723aba7552a665", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12145.json b/mne-python/source/doc/sphinxext/prs/12145.json new file mode 100644 index 0000000000000000000000000000000000000000..9e764964db707feed3aa12757999f6b5c4fdf542 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12145.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "b9cab3ceb4e68c979e8496dd9799ab242b951bdc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 15, + "d": 30 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/html_templates/_templates.py": { + "a": 17, + "d": 1 + }, + "mne/html_templates/repr/evoked.html.jinja": { + "a": 1, + "d": 0 + }, + "mne/html_templates/repr/info.html.jinja": { + "a": 98, + "d": 141 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_misc.py": { + "a": 2, + "d": 2 + }, + "tutorials/intro/30_info.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12146.json b/mne-python/source/doc/sphinxext/prs/12146.json new file mode 100644 index 0000000000000000000000000000000000000000..aaf37d5aa32ed756657127baba834dad72614526 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12146.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "72225b57014ea05cd26327e57c6852b969cbc570", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 0 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_sys_info.py": { + "a": 8, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 74, + "d": 3 + }, + "mne/utils/tests/test_config.py": { + "a": 72, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12148.json b/mne-python/source/doc/sphinxext/prs/12148.json new file mode 100644 index 0000000000000000000000000000000000000000..2d0b2232179ce468bb379cfcf6a31329856ab7bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12148.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7ff8c586e4521d0d45833d715fd3055056aec505", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_coreg.py": { + "a": 4, + "d": 3 + }, + "mne/gui/_gui.py": { + "a": 24, + "d": 29 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12150.json b/mne-python/source/doc/sphinxext/prs/12150.json new file mode 100644 index 0000000000000000000000000000000000000000..1f670bd9440a6ca954d2fe19db8ea25eada1f0d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12150.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3add8f87fd729af9d740ebe5ea3e6f46e95bb782", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12154.json b/mne-python/source/doc/sphinxext/prs/12154.json new file mode 100644 index 0000000000000000000000000000000000000000..a8d11c4270c537274b3b818fba9aa3f4e95f54c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12154.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8d86df6780dd39dfcd55544ee358424a69d4b9be", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/parallel.py": { + "a": 7, + "d": 1 + }, + "mne/utils/tests/test_logging.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12155.json b/mne-python/source/doc/sphinxext/prs/12155.json new file mode 100644 index 0000000000000000000000000000000000000000..f0dc4f3fbfd6c1c9d1a9b2031b6a5f590c02c316 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12155.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3e0e543089b4ad3a4b6b064f45749c86ebbaa081", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12156.json b/mne-python/source/doc/sphinxext/prs/12156.json new file mode 100644 index 0000000000000000000000000000000000000000..ba31ba1331891c8b05fd40673ad0f57b58288f57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12156.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "70a915b08a8a7b1a02fcbfde3e5d4eee4c057717", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 2, + "d": 17 + }, + "mne/report/tests/test_report.py": { + "a": 4, + "d": 3 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12160.json b/mne-python/source/doc/sphinxext/prs/12160.json new file mode 100644 index 0000000000000000000000000000000000000000..503eee0cb09934ed3a6eac62a1ddd25202fa089b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12160.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fcb59266b7616dd99908c6dac0e2295722b0c567", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/_fiff/meas_info.py": { + "a": 6, + "d": 0 + }, + "mne/_fiff/reference.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12161.json b/mne-python/source/doc/sphinxext/prs/12161.json new file mode 100644 index 0000000000000000000000000000000000000000..1eeddd2bbad49188c86a9c3974ccdb5f4991a5c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12161.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fbc666d98f76d02a1917317c3733b1fe94ea95dd", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/v0.17.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v0.18.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/v1.0.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v1.1.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v1.4.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v1.5.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12162.json b/mne-python/source/doc/sphinxext/prs/12162.json new file mode 100644 index 0000000000000000000000000000000000000000..4daee56a9bfcc4ebb34ef14bf9f8ee9ed5103d84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12162.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a4d4c10c6546bd53fa01f7b81ca87c6d2c0f155a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 6, + "d": 0 + }, + "doc/development/contributing.rst": { + "a": 0, + "d": 2 + }, + "doc/help/faq.rst": { + "a": 1, + "d": 0 + }, + "mne/cov.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12163.json b/mne-python/source/doc/sphinxext/prs/12163.json new file mode 100644 index 0000000000000000000000000000000000000000..feeeb870a87abb7d407a6e7de13a718c7f0c9a2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12163.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "89ec1d156595ca8289b3fc81b9a0ef1119d3655b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 10, + "d": 0 + }, + "doc/_includes/dig_formats.rst": { + "a": 1, + "d": 0 + }, + "doc/development/contributing.rst": { + "a": 2, + "d": 0 + }, + "doc/documentation/design_philosophy.rst": { + "a": 2, + "d": 0 + }, + "doc/documentation/index.rst": { + "a": 2, + "d": 0 + }, + "doc/install/mne_tools_suite.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 5, + "d": 1 + }, + "pyproject.toml": { + "a": 14, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12164.json b/mne-python/source/doc/sphinxext/prs/12164.json new file mode 100644 index 0000000000000000000000000000000000000000..a3d908f05e875529e1e899dbd8445d288aea247f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12164.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ec87fd8976a82ef7541c3114cd7955083eb278d6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12165.json b/mne-python/source/doc/sphinxext/prs/12165.json new file mode 100644 index 0000000000000000000000000000000000000000..9c503305ae545415fb35fab04ccf2de3a2dfbace --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12165.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3bc18ffec21c2d0293d6af6452948d6f56f73b5d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 16, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12166.json b/mne-python/source/doc/sphinxext/prs/12166.json new file mode 100644 index 0000000000000000000000000000000000000000..b9b23686093e7057edddd951585423c8769f6320 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12166.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7b6b79583b5e738de08828670222e690c65085f1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 108, + "d": 88 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12167.json b/mne-python/source/doc/sphinxext/prs/12167.json new file mode 100644 index 0000000000000000000000000000000000000000..fad605d3fc0766bff79d6ddaef92ec8070157635 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12167.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "87d6be9047bbd5b234e22eafd79ab7695814fb41", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 5, + "d": 3 + }, + "mne/report/tests/test_report.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12168.json b/mne-python/source/doc/sphinxext/prs/12168.json new file mode 100644 index 0000000000000000000000000000000000000000..b5dd4669fb2a6a638b10662fd3f168546aaa5930 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12168.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f02e5576df7cfcee3fa435cafe66602e65ff76ec", + "authors": [ + { + "n": "Rasmus Aagaard", + "e": null + }, + { + "n": "roraa", + "e": "roraa@dtu.dk" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1217.json b/mne-python/source/doc/sphinxext/prs/1217.json new file mode 100644 index 0000000000000000000000000000000000000000..6663adda40c969988a860eb13250db69fa0469fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1217.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "43ad3b252ea3561ba182b7a47955bac252f6763f", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/channels.py": { + "a": 73, + "d": 23 + }, + "mne/fiff/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 25, + "d": 1 + }, + "mne/fiff/tests/test_raw.py": { + "a": 24, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 25, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12171.json b/mne-python/source/doc/sphinxext/prs/12171.json new file mode 100644 index 0000000000000000000000000000000000000000..f66eb860a0a1f83fd930c08fd04e51c255c1a76e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12171.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "58afb0fb73e55296f21f6c68a643f2ea98f77483", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/clinical/60_sleep.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12172.json b/mne-python/source/doc/sphinxext/prs/12172.json new file mode 100644 index 0000000000000000000000000000000000000000..309656dfccc67f765f41c103c349d6158829bd2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12172.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b988e67d9916ed651c381b867e8bf10c3a470905", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "mne/io/eyelink/_utils.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12174.json b/mne-python/source/doc/sphinxext/prs/12174.json new file mode 100644 index 0000000000000000000000000000000000000000..1427f66bde34628edeb176238acf65dca756ed67 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12174.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8ea98e2dd542735e2ae950e5daf2bdcc363f90bd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12175.json b/mne-python/source/doc/sphinxext/prs/12175.json new file mode 100644 index 0000000000000000000000000000000000000000..9bea78971268f2d70fe2901b1542991aef0d53ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12175.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "55b0184b94ec1c3d6b2559eeed383e760220f516", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tools/dev/Makefile": { + "a": 13, + "d": 2 + }, + "tools/dev/unacknowledged-issues.jq": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12176.json b/mne-python/source/doc/sphinxext/prs/12176.json new file mode 100644 index 0000000000000000000000000000000000000000..56e3a618bc214f4557e91bb68972a0b0bce8af55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12176.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "ffbce015ed8e6c069e00d68114079251781f7fb8", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/mne_logo.svg": { + "a": 744, + "d": 827 + }, + "doc/_static/mne_logo_dark.svg": { + "a": 744, + "d": 827 + }, + "doc/_static/mne_logo_gray.svg": { + "a": 783, + "d": 0 + }, + "doc/_static/mne_logo_small.svg": { + "a": 6, + "d": 6 + }, + "doc/sphinxext/gen_commands.py": { + "a": 2, + "d": 2 + }, + "logo/generate_mne_logos.py": { + "a": 72, + "d": 40 + }, + "mne/icons/mne_default_icon.png": { + "a": 0, + "d": 0 + }, + "mne/icons/mne_splash.png": { + "a": 0, + "d": 0 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 1 + }, + "tools/check_mne_location.py": { + "a": 1, + "d": 1 + }, + "tools/generate_codemeta.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12177.json b/mne-python/source/doc/sphinxext/prs/12177.json new file mode 100644 index 0000000000000000000000000000000000000000..777d4bf8cc837db1a8f6557700841e798d5237ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12177.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8af12aae0ec3f1e73a19ce9be5739922712be299", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12178.json b/mne-python/source/doc/sphinxext/prs/12178.json new file mode 100644 index 0000000000000000000000000000000000000000..0f744d623bb33120334d5001628a3aaf77ab794a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12178.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "22a6dc6b22a6397b75b6caa2271079ed14931986", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + ".github/workflows/tests.yml": { + "a": 1, + "d": 11 + }, + "MANIFEST.in": { + "a": 0, + "d": 6 + }, + "Makefile": { + "a": 3, + "d": 3 + }, + "azure-pipelines.yml": { + "a": 6, + "d": 7 + }, + "doc/changes/v0.24.rst": { + "a": 1, + "d": 1 + }, + "doc/development/contributing.rst": { + "a": 10, + "d": 4 + }, + "doc/links.inc": { + "a": 0, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 13, + "d": 7 + }, + "pyproject.toml": { + "a": 165, + "d": 9 + }, + "requirements.txt": { + "a": 0, + "d": 47 + }, + "requirements_base.txt": { + "a": 0, + "d": 12 + }, + "requirements_doc.txt": { + "a": 0, + "d": 22 + }, + "requirements_hdf5.txt": { + "a": 0, + "d": 3 + }, + "requirements_testing.txt": { + "a": 0, + "d": 15 + }, + "requirements_testing_extra.txt": { + "a": 0, + "d": 10 + }, + "setup.py": { + "a": 0, + "d": 57 + }, + "tools/azure_dependencies.sh": { + "a": 4, + "d": 5 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tools/generate_codemeta.py": { + "a": 11, + "d": 16 + }, + "tools/github_actions_dependencies.sh": { + "a": 8, + "d": 17 + }, + "tools/github_actions_env_vars.sh": { + "a": 2, + "d": 4 + }, + "tutorials/io/20_reading_eeg_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1218.json b/mne-python/source/doc/sphinxext/prs/1218.json new file mode 100644 index 0000000000000000000000000000000000000000..775fed91a8992bd3c0ebda8acb0be525f9da8cb2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1218.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "5a1feece8cccc5bb36c2ab91675d19377d0cfdf9", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 0 + }, + "doc/source/python_reference.rst": { + "a": 10, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 1 + }, + "mne/fiff/egi/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/fiff/egi/egi.py": { + "a": 273, + "d": 0 + }, + "mne/fiff/egi/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/fiff/egi/tests/data/test_egi.raw": { + "a": 0, + "d": 0 + }, + "mne/fiff/egi/tests/test_egi.py": { + "a": 60, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12181.json b/mne-python/source/doc/sphinxext/prs/12181.json new file mode 100644 index 0000000000000000000000000000000000000000..705d8ead20f783bb29ef21be1eae0fe84c65908f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12181.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b55df6397459245d280ffed9fce27ed3e808187c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/cov.py": { + "a": 5, + "d": 7 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 0 + }, + "mne/utils/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12184.json b/mne-python/source/doc/sphinxext/prs/12184.json new file mode 100644 index 0000000000000000000000000000000000000000..90a9089141f99551751bb35144737bd6c10f72f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12184.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bb93c0a20cc936f7cdfbadc8aa5ee40a974a6e80", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12185.json b/mne-python/source/doc/sphinxext/prs/12185.json new file mode 100644 index 0000000000000000000000000000000000000000..0333660f3f2e55e458f80c92807346ff45510ce5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12185.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "14f4f865e6fa28231962b8c7582cac5f41798f9f", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 4, + "d": 3 + }, + "mne/epochs.py": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 5, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 7, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12186.json b/mne-python/source/doc/sphinxext/prs/12186.json new file mode 100644 index 0000000000000000000000000000000000000000..4ea5b9b00dbb62053ac3c1a1da323c80281bc085 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12186.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6874483f6033743510a1ab0766c56ea007db1c20", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 7, + "d": 5 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 8, + "d": 5 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12187.json b/mne-python/source/doc/sphinxext/prs/12187.json new file mode 100644 index 0000000000000000000000000000000000000000..405ae70fbd3cfa40d7092bd75d65284cbee2f1b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12187.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2bc47d078999203a23a6c78ac55952c9e699c861", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12188.json b/mne-python/source/doc/sphinxext/prs/12188.json new file mode 100644 index 0000000000000000000000000000000000000000..52fcc0780b7f486afbf0fc314e9759613a476306 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12188.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fd53fc44915ee3bea2f18c468eece4ed84476e1d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12189.json b/mne-python/source/doc/sphinxext/prs/12189.json new file mode 100644 index 0000000000000000000000000000000000000000..6335ea879faa32213d96cd7049cd1172333ec786 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12189.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9b57c51686ca5536edc2a5e74444428a9a138ef6", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 33, + "d": 6 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 34, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12190.json b/mne-python/source/doc/sphinxext/prs/12190.json new file mode 100644 index 0000000000000000000000000000000000000000..142c275098ba3cbb07eb767c8fd71df77980d965 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12190.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0a9c61bbbd0b70193e9bb88ddaeea3a69c6805f4", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 9, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12192.json b/mne-python/source/doc/sphinxext/prs/12192.json new file mode 100644 index 0000000000000000000000000000000000000000..3d8871a21d6ab56d70a264eb1baf2a48ca2dbd8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12192.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a91f582874a29b32b558d8a55d60c2b5e22b0812", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12194.json b/mne-python/source/doc/sphinxext/prs/12194.json new file mode 100644 index 0000000000000000000000000000000000000000..76ab301f7ab2a8c4252b658ad299dbea31f05a99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12194.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9cbdc7b3eb0ff1e96e79c5cabd3fc7d8a8c27a92", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/html_templates/repr/ica.html.jinja": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12195.json b/mne-python/source/doc/sphinxext/prs/12195.json new file mode 100644 index 0000000000000000000000000000000000000000..2ea9c69f428a189f9b63c739e66dfac8720bc70d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12195.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "3a42bb913fcbfdfed7ae9e23b5649c51b372eb9c", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12195.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 78, + "d": 24 + }, + "mne/tests/test_epochs.py": { + "a": 161, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 43, + "d": 5 + }, + "mne/utils/mixin.py": { + "a": 10, + "d": 3 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 106, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12198.json b/mne-python/source/doc/sphinxext/prs/12198.json new file mode 100644 index 0000000000000000000000000000000000000000..6d1fef2819ebdabee3161e48b7324f759f7983d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12198.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a9a94d92b2040f1455d36403bd10822cf6770c8f", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 5, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12202.json b/mne-python/source/doc/sphinxext/prs/12202.json new file mode 100644 index 0000000000000000000000000000000000000000..9541a5f8762a711317399b134c187052d4b7d28b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12202.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "fa0e8cfc42e8a80f6018df02372bb9f709bd993f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 0, + "d": 3 + }, + "doc/_includes/channel_interpolation.rst": { + "a": 5, + "d": 6 + }, + "doc/_includes/inverse.rst": { + "a": 12, + "d": 12 + }, + "doc/_includes/ssp.rst": { + "a": 6, + "d": 6 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/development/roadmap.rst": { + "a": 81, + "d": 79 + }, + "doc/links.inc": { + "a": 4, + "d": 1 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 5, + "d": 5 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12203.json b/mne-python/source/doc/sphinxext/prs/12203.json new file mode 100644 index 0000000000000000000000000000000000000000..03b6bdf0094c7ec6b0b3d125741721c658bebc70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12203.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "26a0cdcfc0448ce7617f6ada8e0c324b2ceada0e", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12205.json b/mne-python/source/doc/sphinxext/prs/12205.json new file mode 100644 index 0000000000000000000000000000000000000000..8f8f8bb4171b107b5ff19e3b62599708d6a3afaf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12205.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f58776c4d1a0101c1442ae0432e2395ce4a38809", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/pick.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12206.json b/mne-python/source/doc/sphinxext/prs/12206.json new file mode 100644 index 0000000000000000000000000000000000000000..375853a90e37c07b2faf6f2c5ad9b8c485e5fc2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12206.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "87df00d63991a51835992e054d690aa67ccca7da", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12206.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12206.newfeature.rst": { + "a": 3, + "d": 0 + }, + "mne/epochs.py": { + "a": 38, + "d": 7 + }, + "mne/evoked.py": { + "a": 58, + "d": 12 + }, + "mne/io/base.py": { + "a": 37, + "d": 5 + }, + "mne/io/tests/test_apply_function.py": { + "a": 29, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 33, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 30, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12207.json b/mne-python/source/doc/sphinxext/prs/12207.json new file mode 100644 index 0000000000000000000000000000000000000000..e4a4ec3cde864fc1f31fd8a5f1e8ec6a7c8775a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12207.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "73ca06b4056bcb63d55bbcbc68c816c5c8b8f6f2", + "authors": [ + { + "n": "Carina", + "e": "carinaforster0611@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12207.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 19, + "d": 19 + }, + "mne/tests/test_epochs.py": { + "a": 38, + "d": 5 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 31, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 37, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12209.json b/mne-python/source/doc/sphinxext/prs/12209.json new file mode 100644 index 0000000000000000000000000000000000000000..57dd4a57f818ffdb24b975a8e728b7316834c9f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12209.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3fd2c912f25d7c6344edb44e77bd19f036db1c5c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "pyproject.toml": { + "a": 4, + "d": 4 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1221.json b/mne-python/source/doc/sphinxext/prs/1221.json new file mode 100644 index 0000000000000000000000000000000000000000..da0390ed53ecff3a13c6f399662374cd9ced4b16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1221.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "28cc5269865f3ae68822f3f63805e7db395e0c1a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/realtime/tests/test_stim_client_server.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12211.json b/mne-python/source/doc/sphinxext/prs/12211.json new file mode 100644 index 0000000000000000000000000000000000000000..30e81e8827d38687aa572b936a82d990e02ee0a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12211.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "137664c00475d6714ae655eee4fd09ff87bd74c4", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12212.json b/mne-python/source/doc/sphinxext/prs/12212.json new file mode 100644 index 0000000000000000000000000000000000000000..5e9f74a16eaef225cbe8d9916bfd5051c6306447 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12212.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3e73a0ea8ac886622d8f167bcb1b44d496be8a28", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12215.json b/mne-python/source/doc/sphinxext/prs/12215.json new file mode 100644 index 0000000000000000000000000000000000000000..7cf25b8bc1b10ddc1329102657c63ed1e3d3c72e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12215.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "239e574ee2f16f1c87dc3062df1876b6f5a5b1b5", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12218.json b/mne-python/source/doc/sphinxext/prs/12218.json new file mode 100644 index 0000000000000000000000000000000000000000..c5f4d3e430be75c7e0f0ae32699c544a4db043ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12218.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "6c6e6ec6dfea7feebc488fa7d39d3f295f4e105b", + "authors": [ + { + "n": "Florian Hofer", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 2, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/export/_edf.py": { + "a": 121, + "d": 218 + }, + "mne/export/tests/test_export.py": { + "a": 122, + "d": 151 + }, + "mne/utils/__init__.pyi": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 2, + "d": 17 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1222.json b/mne-python/source/doc/sphinxext/prs/1222.json new file mode 100644 index 0000000000000000000000000000000000000000..e4d70ef03b828f46bb6fe7277e94e61fc9e37570 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1222.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f663a08133ac5b0b36a980d5459235c813907d40", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 18, + "d": 16 + }, + "mne/tests/test_label.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12220.json b/mne-python/source/doc/sphinxext/prs/12220.json new file mode 100644 index 0000000000000000000000000000000000000000..d5500d768ae7793b91af3e98f8fb5e327c37b0a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12220.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "61777eb2679fbbc08f9752ae93ebcae547977fed", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 0, + "d": 1 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12222.json b/mne-python/source/doc/sphinxext/prs/12222.json new file mode 100644 index 0000000000000000000000000000000000000000..e767c277c6a9965846e835d3bb18abbf9e7d7759 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12222.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2efb77d7cbe085be548fdda9dfb3e1ad047ab812", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/links.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12223.json b/mne-python/source/doc/sphinxext/prs/12223.json new file mode 100644 index 0000000000000000000000000000000000000000..c5b906fca4d362b3d7d3361ed4ab23b01eb40788 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12223.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d8448e3940790eb3f03d3fbed0286ae75956f0c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 7, + "d": 1 + }, + "mne/_fiff/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_browse_raw.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12224.json b/mne-python/source/doc/sphinxext/prs/12224.json new file mode 100644 index 0000000000000000000000000000000000000000..17e02f3e9ae39d7f70cccec8363576f4e35734e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12224.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "e4838892bf8dcd220e623be66edfcef683f0e638", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 2, + "d": 0 + }, + "CITATION.cff": { + "a": 57, + "d": 35 + }, + "SECURITY.md": { + "a": 4, + "d": 4 + }, + "codemeta.json": { + "a": 169, + "d": 94 + }, + "doc/_static/style.css": { + "a": 1, + "d": 0 + }, + "doc/_static/versions.json": { + "a": 7, + "d": 2 + }, + "doc/changes/v1.6.rst": { + "a": 44, + "d": 21 + }, + "doc/development/whats_new.rst": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 5, + "d": 3 + }, + "tools/github_actions_dependencies.sh": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12225.json b/mne-python/source/doc/sphinxext/prs/12225.json new file mode 100644 index 0000000000000000000000000000000000000000..bc1aa6fb8eafa8ffa4a15a94bbf710b45a3e55d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12225.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d030961250650d0636de71d81b00fa69f90d30d8", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12226.json b/mne-python/source/doc/sphinxext/prs/12226.json new file mode 100644 index 0000000000000000000000000000000000000000..afb8c898b06aedc07b9162d20564eca4674f9f89 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12226.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d7612a115d7a3ff86b4bb55a19dfd4a62dab5b56", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 34, + "d": 0 + }, + "doc/development/whats_new.rst": { + "a": 1, + "d": 0 + }, + "doc/install/installers.rst": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12227.json b/mne-python/source/doc/sphinxext/prs/12227.json new file mode 100644 index 0000000000000000000000000000000000000000..574caa15e1f387e2d5183cfdd5ec14a18335c757 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12227.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1c86d86206610567091ba3fd2dcb63f919c768dc", + "authors": [ + { + "n": "Tristan Stenner", + "e": null + } + ], + "changes": { + "doc/changes/v1.6.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12228.json b/mne-python/source/doc/sphinxext/prs/12228.json new file mode 100644 index 0000000000000000000000000000000000000000..46b55ecf8fe67a7482b794557c137fab310b41a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12228.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bf2d368b65ff8adf92bde35f9ae2d6fdd3a03104", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 7, + "d": 40 + }, + "doc/development/contributing.rst": { + "a": 7, + "d": 7 + }, + "doc/development/roadmap.rst": { + "a": 0, + "d": 2 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12229.json b/mne-python/source/doc/sphinxext/prs/12229.json new file mode 100644 index 0000000000000000000000000000000000000000..aef6e4ebd3d1bfbbe808206b6b80cc0eedc08fc8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12229.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "44c787fd4cffa3453ffbc7b6735a5d09f47eed44", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 3, + "d": 3 + }, + ".pre-commit-config.yaml": { + "a": 3, + "d": 0 + }, + "README.rst": { + "a": 2, + "d": 2 + }, + "doc/development/contributing.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 0, + "d": 11 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1223.json b/mne-python/source/doc/sphinxext/prs/1223.json new file mode 100644 index 0000000000000000000000000000000000000000..450f8193ee570b5919b7e8f6829f96003ca43b10 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1223.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "61ab9e37a0c937229edc08489bbc28d028cacf08", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + ".travis.yml": { + "a": 1, + "d": 6 + }, + "doc/source/python_reference.rst": { + "a": 4, + "d": 0 + }, + "examples/plot_megsim_data.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 4, + "d": 5 + }, + "mne/fiff/__init__.py": { + "a": 10, + "d": 5 + }, + "mne/fiff/base.py": { + "a": 20, + "d": 472 + }, + "mne/fiff/brainvision/brainvision.py": { + "a": 2, + "d": 3 + }, + "mne/fiff/bti/raw.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/channels.py": { + "a": 6, + "d": 4 + }, + "mne/fiff/edf/edf.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/egi/egi.py": { + "a": 4, + "d": 4 + }, + "mne/fiff/egi/tests/test_egi.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/fiff/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/fiff/raw.py": { + "a": 535, + "d": 0 + }, + "mne/fiff/fiff/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/kit/kit.py": { + "a": 3, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 6, + "d": 6 + }, + "setup.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12231.json b/mne-python/source/doc/sphinxext/prs/12231.json new file mode 100644 index 0000000000000000000000000000000000000000..26e12d6700f8bd5067461e3be55dbc6dfb79f7a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12231.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a7d479568b3f427f65d87452e5400235e6a73dc9", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12235.json b/mne-python/source/doc/sphinxext/prs/12235.json new file mode 100644 index 0000000000000000000000000000000000000000..bfa00f9d6ec9590ec4b52ca2b0ab468457e41aac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12235.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1334bfcdbdd2c3fa70d4e0cff8d24cdb64ce9ff7", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "pyproject.toml": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12236.json b/mne-python/source/doc/sphinxext/prs/12236.json new file mode 100644 index 0000000000000000000000000000000000000000..de037becce52f2c7af13a60a9d4fb15cb3e99fb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12236.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "133d589bace71074e9cfddc57b641796235aaaeb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/api/reading_raw_data.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/v1.6.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12237.json b/mne-python/source/doc/sphinxext/prs/12237.json new file mode 100644 index 0000000000000000000000000000000000000000..8127dcac4a7f577057fc64cfd3b1b10c9257fc27 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12237.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "acab264e3d844cce5dfa9fadb49cc55352a261bc", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 7 + }, + "doc/api/preprocessing.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/devel/12237.newfeature.rst": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 9, + "d": 5 + }, + "doc/sphinxext/contrib_avatars.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/gen_commands.py": { + "a": 1, + "d": 2 + }, + "doc/sphinxext/gen_names.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/gh_substitutions.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/mne_substitutions.py": { + "a": 3, + "d": 3 + }, + "doc/sphinxext/newcontrib_substitutions.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/unit_role.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/eyetracking_plot_heatmap.py": { + "a": 25, + "d": 4 + }, + "mne/conftest.py": { + "a": 51, + "d": 0 + }, + "mne/preprocessing/eyetracking/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/eyetracking/_pupillometry.py": { + "a": 8, + "d": 0 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 165, + "d": 0 + }, + "mne/preprocessing/eyetracking/tests/test_eyetracking.py": { + "a": 78, + "d": 0 + }, + "mne/preprocessing/eyetracking/utils.py": { + "a": 41, + "d": 0 + }, + "mne/viz/__init__.pyi": { + "a": 2, + "d": 1 + }, + "mne/viz/eyetracking/heatmap.py": { + "a": 69, + "d": 15 + }, + "mne/viz/eyetracking/tests/test_heatmap.py": { + "a": 43, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12238.json b/mne-python/source/doc/sphinxext/prs/12238.json new file mode 100644 index 0000000000000000000000000000000000000000..b0b6a994515553bddea3168aa41c777bc4c4fd67 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12238.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "06c90a7982eee3b4747bbf6e6afca71014c3e5bf", + "authors": [ + { + "n": "Nikolai Kapralov", + "e": null + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/check.py": { + "a": 22, + "d": 2 + }, + "mne/utils/tests/test_check.py": { + "a": 13, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12239.json b/mne-python/source/doc/sphinxext/prs/12239.json new file mode 100644 index 0000000000000000000000000000000000000000..0af04768aa8ac28b97b0f5d552189aa197cd49ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12239.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a8422368e91d678c297429f19e496666a2a5e19f", + "authors": [ + { + "n": "Nikolai Kapralov", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1224.json b/mne-python/source/doc/sphinxext/prs/1224.json new file mode 100644 index 0000000000000000000000000000000000000000..db67077a2eba3530aaed8894e494e69b631a8a7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1224.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7d3ececcbb37133769d5262d05df7e3f9ebc7ec1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/stats/parametric.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12240.json b/mne-python/source/doc/sphinxext/prs/12240.json new file mode 100644 index 0000000000000000000000000000000000000000..426edc944eeb07c923346eff0c1a7f44c92a20ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12240.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ac0d42c997f3698922736721ba272ab5e9a4b791", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "pyproject.toml": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12242.json b/mne-python/source/doc/sphinxext/prs/12242.json new file mode 100644 index 0000000000000000000000000000000000000000..a34467a07b6f776857c8b5c878b3e513f86cecfe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12242.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "476e50dd0b67474d98b96b06bf3752c0ec0e46cb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_abstract.py": { + "a": 17, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12244.json b/mne-python/source/doc/sphinxext/prs/12244.json new file mode 100644 index 0000000000000000000000000000000000000000..7b5a723d32faa144f6fae98673e1617da2c09b9e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12244.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5ae31b6ca7275a03332eef0c23b5d2cee68c3c42", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg.py": { + "a": 3, + "d": 0 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 11, + "d": 10 + }, + "tools/github_actions_dependencies.sh": { + "a": 16, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12245.json b/mne-python/source/doc/sphinxext/prs/12245.json new file mode 100644 index 0000000000000000000000000000000000000000..57621858c33b1ec1b0559dd351986c3ccc08c520 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12245.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "88fb4a612ed7f109c3bac1910c38e32ccea49ebb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + ".git_archival.txt": { + "a": 4, + "d": 0 + }, + ".gitattributes": { + "a": 1, + "d": 0 + }, + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/development/contributing.rst": { + "a": 2, + "d": 2 + }, + "doc/install/manual_install.rst": { + "a": 1, + "d": 1 + }, + "doc/install/updating.rst": { + "a": 2, + "d": 2 + }, + "mne/__init__.py": { + "a": 3, + "d": 4 + }, + "pyproject.toml": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12246.json b/mne-python/source/doc/sphinxext/prs/12246.json new file mode 100644 index 0000000000000000000000000000000000000000..304ac4196eb90e980ac30a3c13b846c0e2794169 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12246.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2a1f7e4929b03c243375551755f5e99618acb5ca", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/datasets/eegbci/eegbci.py": { + "a": 1, + "d": 7 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 6 + }, + "pyproject.toml": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12248.json b/mne-python/source/doc/sphinxext/prs/12248.json new file mode 100644 index 0000000000000000000000000000000000000000..67d616ef42f62de7c4eb5b193a746bb05feaa487 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12248.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b107d92ecc0526bd8cd90b0a06c13caa9a9ec87c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12250.json b/mne-python/source/doc/sphinxext/prs/12250.json new file mode 100644 index 0000000000000000000000000000000000000000..d7e546650deda4b2202c039e7d5cef65f96f6f84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12250.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "7bf1b4ab70404a9f0b3cf00783a06e1ce9e0c272", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".git-blame-ignore-revs": { + "a": 1, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 9, + "d": 0 + }, + "doc/changes/devel.rst": { + "a": 13, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/io/_read_raw.py": { + "a": 2, + "d": 1 + }, + "pyproject.toml": { + "a": 31, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12251.json b/mne-python/source/doc/sphinxext/prs/12251.json new file mode 100644 index 0000000000000000000000000000000000000000..a809d7a2168bc110e85eb2fba7c4a6da4dd72b66 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12251.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "20174f448e5f70623c3c8eda048ae43cb0b39a05", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 7, + "d": 8 + }, + "pyproject.toml": { + "a": 1, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12252.json b/mne-python/source/doc/sphinxext/prs/12252.json new file mode 100644 index 0000000000000000000000000000000000000000..b320f88b55517e482e02cbde18fd663100acb46c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12252.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "45eba5a688b555d3d31ea89d9d2e0aa2fae33ff8", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/surface.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12254.json b/mne-python/source/doc/sphinxext/prs/12254.json new file mode 100644 index 0000000000000000000000000000000000000000..50005c4a88771fc0b2ffde9dba0399b9a3882889 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12254.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "080a2a12554415f0a4d6b6d89b63cb80534fa2aa", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 3, + "d": 3 + }, + "doc/links.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12257.json b/mne-python/source/doc/sphinxext/prs/12257.json new file mode 100644 index 0000000000000000000000000000000000000000..0e3ffaf20a271b0588f9f7b5d0cfc5d8bd6665fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12257.json @@ -0,0 +1,259 @@ +{ + "merge_commit_sha": "ac55693e1fa1d0da65791fb547ad4dd6fcd90dc5", + "authors": [ + { + "n": "Nikolai Kapralov", + "e": null + } + ], + "changes": { + "mne/_fiff/tests/test_compensator.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_proc_history.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_show_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_forward.py": { + "a": 1, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 4 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_read_raw.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_annotate_nan.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_hfc.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_interpolate.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 3, + "d": 7 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 3, + "d": 9 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 3 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_rank.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_read_vectorview_selection.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 1, + "d": 3 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_logging.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_numerics.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12260.json b/mne-python/source/doc/sphinxext/prs/12260.json new file mode 100644 index 0000000000000000000000000000000000000000..11794304aa0993c7267c661b1b363c28c6411996 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12260.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "82d195dd10c3b0756b5615b6e28dbc481040825f", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + }, + ".gitignore": { + "a": 2, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/api/realtime.rst": { + "a": 2, + "d": 1 + }, + "doc/changes/v0.23.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v0.24.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 4, + "d": 4 + }, + "doc/install/mne_tools_suite.rst": { + "a": 0, + "d": 1 + }, + "doc/links.inc": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/_fetch.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/transformer.py": { + "a": 3, + "d": 4 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12261.json b/mne-python/source/doc/sphinxext/prs/12261.json new file mode 100644 index 0000000000000000000000000000000000000000..fb32bc19e0038832d6b0d96e8ea30bb4b0ab8744 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12261.json @@ -0,0 +1,303 @@ +{ + "merge_commit_sha": "e7dd1588013179013a50d3f6b8e8f9ae0a185783", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 0, + "d": 1 + }, + ".pre-commit-config.yaml": { + "a": 8, + "d": 8 + }, + "mne/_fiff/tag.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_constants.py": { + "a": 6, + "d": 6 + }, + "mne/annotations.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 1, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 19, + "d": 54 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 4 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 1, + "d": 2 + }, + "mne/coreg.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 5, + "d": 7 + }, + "mne/dipole.py": { + "a": 6, + "d": 6 + }, + "mne/epochs.py": { + "a": 5, + "d": 7 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 2 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 8, + "d": 2 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 5, + "d": 5 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 3 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 5, + "d": 7 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 3 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 3 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/fil/fil.py": { + "a": 2, + "d": 2 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 2, + "d": 6 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 3 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/nihon/nihon.py": { + "a": 1, + "d": 2 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/interpolate.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_annotate_amplitude.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 5, + "d": 7 + }, + "mne/source_space/_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 5, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 3 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 2 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_bunch.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 384, + "d": 1148 + }, + "mne/utils/progressbar.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 2 + }, + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 5 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 2 + }, + "pyproject.toml": { + "a": 0, + "d": 4 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 3, + "d": 1 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 1, + "d": 2 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12263.json b/mne-python/source/doc/sphinxext/prs/12263.json new file mode 100644 index 0000000000000000000000000000000000000000..9a99d7eac3b9f650c18fc61d83edd53f0208d9f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12263.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "092cf9002c0510de7d66255a8b11e3a591036f92", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/sphinxext/contrib_avatars.py": { + "a": 26, + "d": 18 + }, + "tools/circleci_bash_env.sh": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12264.json b/mne-python/source/doc/sphinxext/prs/12264.json new file mode 100644 index 0000000000000000000000000000000000000000..31c9fdc5fdac57d6c44b710ceccc623c20ea675b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12264.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "3d3633cadf17631ffe2a984b13af5e21c5bbbde0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 5, + "d": 6 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 3, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 5, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 2, + "d": 0 + }, + "mne/io/egi/egimff.py": { + "a": 7, + "d": 2 + }, + "mne/io/egi/events.py": { + "a": 3, + "d": 3 + }, + "mne/io/egi/general.py": { + "a": 13, + "d": 2 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 11, + "d": 0 + }, + "mne/io/nedf/nedf.py": { + "a": 3, + "d": 3 + }, + "mne/io/nedf/tests/test_nedf.py": { + "a": 2, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12265.json b/mne-python/source/doc/sphinxext/prs/12265.json new file mode 100644 index 0000000000000000000000000000000000000000..d434952852aa48866bdd29c348be188cc7d64820 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12265.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "6187c836cdb4bbab4f222d7918df6f006a3beaa5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/_fiff/__init__.py": { + "a": 0, + "d": 19 + }, + "mne/commands/tests/test_commands.py": { + "a": 0, + "d": 27 + }, + "mne/gui/_gui.py": { + "a": 6, + "d": 61 + }, + "mne/io/constants.py": { + "a": 0, + "d": 9 + }, + "mne/io/meas_info.py": { + "a": 0, + "d": 11 + }, + "mne/io/pick.py": { + "a": 0, + "d": 9 + }, + "mne/io/proj.py": { + "a": 0, + "d": 11 + }, + "mne/io/reference.py": { + "a": 0, + "d": 11 + }, + "mne/io/tag.py": { + "a": 0, + "d": 11 + }, + "mne/io/tests/test_deprecation.py": { + "a": 0, + "d": 30 + }, + "mne/io/utils.py": { + "a": 0, + "d": 11 + }, + "mne/io/write.py": { + "a": 0, + "d": 11 + }, + "mne/preprocessing/__init__.pyi": { + "a": 0, + "d": 2 + }, + "mne/preprocessing/maxfilter.py": { + "a": 0, + "d": 230 + }, + "mne/source_space/_source_space.py": { + "a": 0, + "d": 3 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 9, + "d": 39 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 3, + "d": 134 + }, + "mne/viz/_brain/_brain.py": { + "a": 0, + "d": 10 + }, + "mne/viz/backends/_abstract.py": { + "a": 0, + "d": 9 + }, + "mne/viz/backends/_pyvista.py": { + "a": 0, + "d": 21 + }, + "mne/viz/backends/renderer.py": { + "a": 0, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12268.json b/mne-python/source/doc/sphinxext/prs/12268.json new file mode 100644 index 0000000000000000000000000000000000000000..732600f9b6fea4ef67fe8baed6711a069bd4321f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12268.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "432249ee6304b07a8ecece2b310a65c594c59ae9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "examples/datasets/spm_faces_dataset.py": { + "a": 28, + "d": 79 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 5, + "d": 6 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 4, + "d": 4 + }, + "mne/cuda.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 109, + "d": 57 + }, + "mne/io/base.py": { + "a": 16, + "d": 6 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 36, + "d": 30 + }, + "mne/source_estimate.py": { + "a": 23, + "d": 4 + }, + "mne/tests/test_filter.py": { + "a": 28, + "d": 11 + }, + "mne/tests/test_source_estimate.py": { + "a": 64, + "d": 52 + }, + "mne/utils/docs.py": { + "a": 45, + "d": 13 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 48, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12269.json b/mne-python/source/doc/sphinxext/prs/12269.json new file mode 100644 index 0000000000000000000000000000000000000000..7ba16b572ae364ee8e73b7f74a9f06a4e739c1aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12269.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d00cbb12b9b6070a713ac67fcba19e7443c71ef7", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 0, + "d": 86 + }, + "Makefile": { + "a": 1, + "d": 4 + }, + "azure-pipelines.yml": { + "a": 0, + "d": 4 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "pyproject.toml": { + "a": 26, + "d": 45 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12270.json b/mne-python/source/doc/sphinxext/prs/12270.json new file mode 100644 index 0000000000000000000000000000000000000000..34089cb449f9ade75db49efbb2ddb0e08643689c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12270.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "bf03a03c91bc64b8a9cf72d75a399cfcb89c0662", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/datasets/brainstorm_data.py": { + "a": 3, + "d": 1 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 3, + "d": 3 + }, + "mne/io/array/tests/test_array.py": { + "a": 4, + "d": 2 + }, + "mne/report/report.py": { + "a": 4, + "d": 2 + }, + "mne/time_frequency/spectrum.py": { + "a": 36, + "d": 27 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 17, + "d": 14 + }, + "mne/viz/utils.py": { + "a": 9, + "d": 24 + }, + "tutorials/clinical/60_sleep.py": { + "a": 1, + "d": 0 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/10_overview.py": { + "a": 7, + "d": 7 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 3, + "d": 1 + }, + "tutorials/inverse/95_phantom_KIT.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 6, + "d": 2 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 12, + "d": 6 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 8, + "d": 1 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 3, + "d": 1 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 7, + "d": 7 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 1, + "d": 1 + }, + "tutorials/time-freq/10_spectrum_class.py": { + "a": 4, + "d": 4 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12275.json b/mne-python/source/doc/sphinxext/prs/12275.json new file mode 100644 index 0000000000000000000000000000000000000000..e492727809eec95a4cfa9eee92aae767bea2af35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12275.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "854c0eb018beafa2841663bcbbdec3af1b35e73a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 3, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 4, + "d": 4 + }, + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12278.json b/mne-python/source/doc/sphinxext/prs/12278.json new file mode 100644 index 0000000000000000000000000000000000000000..598ecdd724bb6a44ac85d721d255ddc4228519ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12278.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "59e50247c8fc4d6d5c968b9d9b6207b7ff5d6b24", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "LICENSE.txt": { + "a": 9, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12279.json b/mne-python/source/doc/sphinxext/prs/12279.json new file mode 100644 index 0000000000000000000000000000000000000000..3f8322fbec7c8a3a46e2e2f543aefad04776cb29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12279.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "97512a15a74c6a610132c83e8e420dd4a7caf4f5", + "authors": [ + { + "n": "Kristijan Armeni", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 187, + "d": 27 + }, + "mne/io/neuralynx/tests/test_neuralynx.py": { + "a": 95, + "d": 13 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "pyproject.toml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12281.json b/mne-python/source/doc/sphinxext/prs/12281.json new file mode 100644 index 0000000000000000000000000000000000000000..56b900104f30d9739f8c7a3f85a8cfcbfa27df62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12281.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "8af33df490f94c3dd628cfc23beafed1a6cc6361", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 0, + "d": 1 + }, + ".gitignore": { + "a": 0, + "d": 1 + }, + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "examples/visualization/3d_to_2d.py": { + "a": 3, + "d": 6 + }, + "mne/conftest.py": { + "a": 5, + "d": 0 + }, + "mne/data/image/custom_layout.lout": { + "a": 0, + "d": 257 + }, + "mne/data/image/mni_brain.gif": { + "a": 0, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "pyproject.toml": { + "a": 8, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 5, + "d": 1 + }, + "tools/github_actions_install.sh": { + "a": 0, + "d": 5 + }, + "tools/github_actions_test.sh": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12282.json b/mne-python/source/doc/sphinxext/prs/12282.json new file mode 100644 index 0000000000000000000000000000000000000000..8e6ce095bbffbf87f0db71497160fbf1d06ce75a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12282.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fd5008a48a1819034f8cf94dfc0e31f7f1a74ba5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 7, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12284.json b/mne-python/source/doc/sphinxext/prs/12284.json new file mode 100644 index 0000000000000000000000000000000000000000..8a2fcb07d8abae49516660d87bdd5157a2a12773 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12284.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8e500a3f4c8e37136c72e13e060f819b711198f1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 34 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12287.json b/mne-python/source/doc/sphinxext/prs/12287.json new file mode 100644 index 0000000000000000000000000000000000000000..2ed1db492f7bc5f55e2b5076d1904cee0e356334 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12287.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "742065d5dd6c69223cc15bb7aca212e5d1a99988", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/release.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12288.json b/mne-python/source/doc/sphinxext/prs/12288.json new file mode 100644 index 0000000000000000000000000000000000000000..fa107fe0e42c2b78b73e0621793607afe499a1dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12288.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5df4cd6506ca2fb244070865a92bdbba8dabc1c4", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12289.json b/mne-python/source/doc/sphinxext/prs/12289.json new file mode 100644 index 0000000000000000000000000000000000000000..32108ecac0b538f30bfc2367ec16457864565476 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12289.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "4e2a60073c5c42030f825b7495032a91e5d7e722", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 14, + "d": 3 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 8, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils/dataframe.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12291.json b/mne-python/source/doc/sphinxext/prs/12291.json new file mode 100644 index 0000000000000000000000000000000000000000..0a50532e48f02c93929dba7e8210ab04de7d1409 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12291.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7ce9aa1789f9ebe928aaa315d993182ad416464e", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 7, + "d": 2 + }, + "pyproject.toml": { + "a": 0, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12294.json b/mne-python/source/doc/sphinxext/prs/12294.json new file mode 100644 index 0000000000000000000000000000000000000000..6d9ce7969d5a022939fc0c55651f11df73b5c679 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12294.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1034bffde6fe4a360da3fe155b3c16bdc6380b8d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/mne_coreg.py": { + "a": 0, + "d": 38 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12296.json b/mne-python/source/doc/sphinxext/prs/12296.json new file mode 100644 index 0000000000000000000000000000000000000000..59ec81712acced96e2b407c28d00b0a606d125fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12296.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "35f0ef65d02af33acf55ba01fa5aa62d8697e117", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 27, + "d": 24 + }, + "mne/annotations.py": { + "a": 4, + "d": 2 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/boxy/boxy.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 6 + }, + "mne/io/curry/curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/eximia/eximia.py": { + "a": 1, + "d": 1 + }, + "mne/io/eyelink/eyelink.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/fil/fil.py": { + "a": 3, + "d": 1 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/nedf/nedf.py": { + "a": 1, + "d": 1 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/nihon/nihon.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 3, + "d": 1 + }, + "mne/io/nsx/nsx.py": { + "a": 1, + "d": 1 + }, + "mne/io/persyst/persyst.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 3, + "d": 1 + }, + "pyproject.toml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12297.json b/mne-python/source/doc/sphinxext/prs/12297.json new file mode 100644 index 0000000000000000000000000000000000000000..a4884069193d93ec38b65a91045a6eb608a212c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12297.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "40256aef4dd5b417be91ce544fa8031cc2abd9bf", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 3, + "d": 2 + }, + "doc/conf.py": { + "a": 12, + "d": 13 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 3, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/nedf/nedf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12298.json b/mne-python/source/doc/sphinxext/prs/12298.json new file mode 100644 index 0000000000000000000000000000000000000000..6861e787093dc3270b4b5f259c767e6598eccf42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12298.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b1329c3ae59d0da3646b0c667441e12ee0f7bd8d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 6, + "d": 0 + }, + "doc/conf.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12299.json b/mne-python/source/doc/sphinxext/prs/12299.json new file mode 100644 index 0000000000000000000000000000000000000000..c01cab3e45ae499a3f0c365acccc242935c9c569 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12299.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "00882bc2d24b07594c080af1a768f970476bdd4c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/check_changelog.yml": { + "a": 15, + "d": 0 + }, + "doc/changes/devel.rst": { + "a": 2, + "d": 53 + }, + "doc/changes/devel.rst.template": { + "a": 0, + "d": 34 + }, + "doc/changes/devel/.gitignore": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12190.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12218.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12236.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12238.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12248.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12250.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12250.notable.rst": { + "a": 11, + "d": 0 + }, + "doc/changes/devel/12264.dependency.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12268.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12269.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12279.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12282.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12289.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12299.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12308.apichange.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 9, + "d": 5 + }, + "doc/development/contributing.rst": { + "a": 51, + "d": 53 + }, + "doc/links.inc": { + "a": 1, + "d": 0 + }, + "pyproject.toml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1230.json b/mne-python/source/doc/sphinxext/prs/1230.json new file mode 100644 index 0000000000000000000000000000000000000000..4d06f91870d3038dc6c0c8dfc94334f9bf1c9ae1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1230.json @@ -0,0 +1,155 @@ +{ + "merge_commit_sha": "ce903fe24a451a12a0b6634de63a7db79b70fa77", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/connectivity/effective.py": { + "a": 2, + "d": 2 + }, + "mne/coreg.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/base.py": { + "a": 12, + "d": 29 + }, + "mne/fiff/brainvision/brainvision.py": { + "a": 9, + "d": 7 + }, + "mne/fiff/bti/raw.py": { + "a": 389, + "d": 392 + }, + "mne/fiff/bti/tests/test_bti.py": { + "a": 0, + "d": 1 + }, + "mne/fiff/edf/edf.py": { + "a": 7, + "d": 6 + }, + "mne/fiff/egi/egi.py": { + "a": 2, + "d": 3 + }, + "mne/fiff/fiff/raw.py": { + "a": 114, + "d": 115 + }, + "mne/fiff/fiff/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/fiff/fiff/tests/test_raw.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/kit/kit.py": { + "a": 1, + "d": 2 + }, + "mne/fiff/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/open.py": { + "a": 17, + "d": 12 + }, + "mne/fiff/write.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 21, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 3, + "d": 3 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 2, + "d": 2 + }, + "mne/label.py": { + "a": 10, + "d": 11 + }, + "mne/minimum_norm/inverse.py": { + "a": 6, + "d": 6 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 2 + }, + "mne/proj.py": { + "a": 3, + "d": 2 + }, + "mne/realtime/stim_server_client.py": { + "a": 3, + "d": 0 + }, + "mne/realtime/tests/test_stim_client_server.py": { + "a": 1, + "d": 0 + }, + "mne/source_space.py": { + "a": 16, + "d": 17 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 5, + "d": 3 + }, + "mne/time_frequency/stft.py": { + "a": 5, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 4, + "d": 3 + }, + "mne/viz.py": { + "a": 8, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12300.json b/mne-python/source/doc/sphinxext/prs/12300.json new file mode 100644 index 0000000000000000000000000000000000000000..e4961193c94a9b91eaeaf9968ef4ecb1332cf31e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12300.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "fce9c5ed032cc7e7af0d7ea33f35e50d46510d64", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "nafraw", + "e": "ping-keng.jao@alumni.epfl.ch" + } + ], + "changes": { + "doc/changes/devel/12300.apichange.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/devel/12300.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 5, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 77, + "d": 74 + }, + "mne/io/egi/egimff.py": { + "a": 41, + "d": 114 + }, + "mne/io/egi/events.py": { + "a": 38, + "d": 2 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 45, + "d": 15 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12301.json b/mne-python/source/doc/sphinxext/prs/12301.json new file mode 100644 index 0000000000000000000000000000000000000000..af62fb32225304403587797c4f1a50a89b6e1691 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12301.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0a0cad8802e832669bb954a3bdd8e08bfaecf784", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12302.json b/mne-python/source/doc/sphinxext/prs/12302.json new file mode 100644 index 0000000000000000000000000000000000000000..7449ea3a49cca9d370ea05227c8a1fb2d652b055 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12302.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7242c291fdd572c58143281a64688968463b928a", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/release.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12303.json b/mne-python/source/doc/sphinxext/prs/12303.json new file mode 100644 index 0000000000000000000000000000000000000000..450205bf46f5a91b1205b0ab702b2124c01d434d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12303.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "60e46f0b6c184e1bfb9c399124fa7b619a96622b", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/codeql-analysis.yml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12304.json b/mne-python/source/doc/sphinxext/prs/12304.json new file mode 100644 index 0000000000000000000000000000000000000000..ebd5eb0a98594b3ab76c55bc4f3b97ef2fd4467d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12304.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cf2ca7ea723bc92ec1fdb77abc9eafe165160420", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/release.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12307.json b/mne-python/source/doc/sphinxext/prs/12307.json new file mode 100644 index 0000000000000000000000000000000000000000..1f23b8faf5498bf64fd88eca169f0bb5c06a325f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12307.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f1a8120d29a162ec42c85e9d64136e3c2405da2c", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12308.json b/mne-python/source/doc/sphinxext/prs/12308.json new file mode 100644 index 0000000000000000000000000000000000000000..eee77bbd783da714f7210dc9f5920ae814b140fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12308.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4742914ff898d22a3c3012aeefaf2a8301f2c2f8", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/devel.rst": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 16, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 16, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12309.json b/mne-python/source/doc/sphinxext/prs/12309.json new file mode 100644 index 0000000000000000000000000000000000000000..9a2e299c8adc5a784e4d36f69fefdb4f3ba96f8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12309.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a03a40d50f871b3d51da923ac156d50443162ea8", + "authors": [ + { + "n": "Peter J. Molfese", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12309.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 72, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 28, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1231.json b/mne-python/source/doc/sphinxext/prs/1231.json new file mode 100644 index 0000000000000000000000000000000000000000..a4f6c17df80c25d80b28598c17ce7d72d3d9136f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1231.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6803bc7024b04f49ec6207b3852a7fb660dc3049", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/egi/egi.py": { + "a": 55, + "d": 17 + }, + "mne/fiff/egi/tests/test_egi.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12311.json b/mne-python/source/doc/sphinxext/prs/12311.json new file mode 100644 index 0000000000000000000000000000000000000000..aa439ff4349b4b710b025787d11c0158c6df47f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12311.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "c73b8afcf3cb6304bb67c390d667cd1ac526473d", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12311.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 5, + "d": 8 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 8, + "d": 11 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 5, + "d": 6 + }, + "examples/visualization/eyetracking_plot_heatmap.py": { + "a": 1, + "d": 5 + }, + "mne/epochs.py": { + "a": 54, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 20, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 3 + }, + "tools/setup_xvfb.sh": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 1, + "d": 2 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 5 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 6, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12316.json b/mne-python/source/doc/sphinxext/prs/12316.json new file mode 100644 index 0000000000000000000000000000000000000000..c1fdcecfd12c4f59853859e35e0b7350a2a06a3d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12316.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c52208bedfb36e9157678d091f4b4e03ec96c96d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "CONTRIBUTING.md": { + "a": 1, + "d": 1 + }, + "doc/development/index.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12317.json b/mne-python/source/doc/sphinxext/prs/12317.json new file mode 100644 index 0000000000000000000000000000000000000000..1a147b6829a2e89020ebe8bda382b32e406a7e28 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12317.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0f59894a2491797c996272c23c39412a62369f5b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12318.json b/mne-python/source/doc/sphinxext/prs/12318.json new file mode 100644 index 0000000000000000000000000000000000000000..7ee964ecdda0ae39a7d3f961f6ceba6403d8b463 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12318.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6733cae2a0765da9ec1b67a98937839d4cd9aadf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/actions/rename_towncrier/rename_towncrier.py": { + "a": 56, + "d": 0 + }, + ".github/workflows/autofix.yml": { + "a": 21, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/12318.other.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12319.json b/mne-python/source/doc/sphinxext/prs/12319.json new file mode 100644 index 0000000000000000000000000000000000000000..58f1817d048995aefad1ee6ed0c9b02e5c41e9dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12319.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ca7fe266c0a6d4426a62798f37d6a3428d08de6b", + "authors": [ + { + "n": "Martin Oberg", + "e": null + } + ], + "changes": { + "doc/changes/devel/12319.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12320.json b/mne-python/source/doc/sphinxext/prs/12320.json new file mode 100644 index 0000000000000000000000000000000000000000..7948782ad5577f6a9c33a035e0eb2c92779186e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12320.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7ccd100310892617dc3c4290465c1eefe1d47282", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12323.json b/mne-python/source/doc/sphinxext/prs/12323.json new file mode 100644 index 0000000000000000000000000000000000000000..41c87204836f741b990fe918aee6a4c8a5fcfa48 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12323.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "70455902ba834bec75ae1fd0f7f5b2fc48455cf8", + "authors": [ + { + "n": "Hamza Abdelhedi", + "e": "hamzaabdelhedi18@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12323.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/filter.py": { + "a": 40, + "d": 16 + }, + "mne/source_estimate.py": { + "a": 56, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 11, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 29, + "d": 1 + }, + "mne/utils/check.py": { + "a": 2, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12324.json b/mne-python/source/doc/sphinxext/prs/12324.json new file mode 100644 index 0000000000000000000000000000000000000000..16c85e9e06493f8f36521bf0e5aab68cd4c891ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12324.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6857f10bd6470495635ffea190e673e91dc81ac6", + "authors": [ + { + "n": "rcmdnk", + "e": "rcmdnk@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12324.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 7, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 43, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12325.json b/mne-python/source/doc/sphinxext/prs/12325.json new file mode 100644 index 0000000000000000000000000000000000000000..01f7000d420f0c6e99e6a58bbbfa634786cd2544 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12325.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6790426221b83ee16375ec19e974808d7b9aad4c", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12326.json b/mne-python/source/doc/sphinxext/prs/12326.json new file mode 100644 index 0000000000000000000000000000000000000000..2fb3ff1d666cf89ca1a321b1913c36d89213603b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12326.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f060e6b470704823dad6120cd685ad7390c1eae6", + "authors": [ + { + "n": "btkcodedev", + "e": "btk.codedev@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12326.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1233.json b/mne-python/source/doc/sphinxext/prs/1233.json new file mode 100644 index 0000000000000000000000000000000000000000..261bf3b75b380b872733f518e60f0341445bb038 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1233.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d67973b73db6665770b272cfebf95136aa7d468b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 2 + }, + "examples/time_frequency/plot_stockwell.py": { + "a": 48, + "d": 0 + }, + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 20, + "d": 2 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/_stockwell.py": { + "a": 249, + "d": 0 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 93, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12330.json b/mne-python/source/doc/sphinxext/prs/12330.json new file mode 100644 index 0000000000000000000000000000000000000000..504cce4ca8d04494019c6dbb361a1d7d3f9ae38d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12330.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ff03c6ca17f7d12f72ee1f488264acec6a8db06e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 6, + "d": 6 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 3 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12332.json b/mne-python/source/doc/sphinxext/prs/12332.json new file mode 100644 index 0000000000000000000000000000000000000000..698dbee5f35d3f58347e8077ba145ca6859eb9e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12332.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6eb4c3f4f94177d9c6e7c40cf941f5a4be9d4c98", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12332.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 33, + "d": 66 + }, + "mne/export/tests/test_export.py": { + "a": 5, + "d": 8 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12335.json b/mne-python/source/doc/sphinxext/prs/12335.json new file mode 100644 index 0000000000000000000000000000000000000000..fa21ad13caffbc74b5fc4d22dbbd48c98a8101d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12335.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "596122d1f39a962e8299c63020885e207f127c87", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/development/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12336.json b/mne-python/source/doc/sphinxext/prs/12336.json new file mode 100644 index 0000000000000000000000000000000000000000..a24159ef202a7f36af5fc6871e6058f8484fcf81 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12336.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f70378a922a46b5432a761281ae857ec747b984b", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12336.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 27, + "d": 11 + }, + "mne/channels/interpolation.py": { + "a": 116, + "d": 26 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 50, + "d": 0 + }, + "mne/defaults.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12338.json b/mne-python/source/doc/sphinxext/prs/12338.json new file mode 100644 index 0000000000000000000000000000000000000000..457af66a8b1f73b3aa8eb6092d590d98f0903554 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12338.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d6a58cb6ef9a8d69143c4629c3991ccbf250af42", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12338.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/development/contributing.rst": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 136, + "d": 4 + }, + "mne/channels/tests/test_layout.py": { + "a": 116, + "d": 12 + }, + "mne/utils/docs.py": { + "a": 14, + "d": 10 + }, + "mne/viz/topo.py": { + "a": 11, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1234.json b/mne-python/source/doc/sphinxext/prs/1234.json new file mode 100644 index 0000000000000000000000000000000000000000..5361d7a06a0a5dc25de0298d6da03382eaf15125 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1234.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f127281d34540597e81dab029edbb67ed9a29be2", + "authors": [ + { + "n": null, + "e": "flKazemakase@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 5, + "d": 0 + }, + "mne/fiff/edf/edf.py": { + "a": 122, + "d": 7 + }, + "mne/fiff/edf/tests/data/test.edf": { + "a": 7, + "d": 7 + }, + "mne/fiff/edf/tests/test_edf.py": { + "a": 87, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12340.json b/mne-python/source/doc/sphinxext/prs/12340.json new file mode 100644 index 0000000000000000000000000000000000000000..7d22423d136f7b9db826b35316b5286f40ea185d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12340.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4750f0dd5dc81c15704230c785541ab09fa5373b", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12343.json b/mne-python/source/doc/sphinxext/prs/12343.json new file mode 100644 index 0000000000000000000000000000000000000000..75ce446d5b893a7007ee0b982b51f8eec415711d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12343.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "16c17b4dba8381615d57267c01f1f2f310fc522c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12343.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/open.py": { + "a": 17, + "d": 12 + }, + "mne/_fiff/tag.py": { + "a": 38, + "d": 59 + }, + "mne/_fiff/tree.py": { + "a": 1, + "d": 46 + }, + "mne/commands/tests/test_commands.py": { + "a": 11, + "d": 2 + }, + "mne/epochs.py": { + "a": 2, + "d": 3 + }, + "mne/io/fiff/raw.py": { + "a": 65, + "d": 71 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 5, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12345.json b/mne-python/source/doc/sphinxext/prs/12345.json new file mode 100644 index 0000000000000000000000000000000000000000..0d780407167ba76fb9c378b3350ad7c94f6c036a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12345.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4f1557d7c122d3bad83a5f43c648c0cd3cfc802a", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12345.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12347.json b/mne-python/source/doc/sphinxext/prs/12347.json new file mode 100644 index 0000000000000000000000000000000000000000..eadd62a7baf45f8f43f8a7eb486c29016cc18a83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12347.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d2c806c198ccedb5b66c8eb0da31519ad0e970e9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12348.json b/mne-python/source/doc/sphinxext/prs/12348.json new file mode 100644 index 0000000000000000000000000000000000000000..59937e7eaf5adc29e4b6fc9c636f9a0de23bbe1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12348.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "8eb10e36ebfdac990ed86da919f2729177090dd2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "motofumi-fushimi", + "e": "30593537+motofumi-fushimi@users.noreply.github.com" + } + ], + "changes": { + ".mailmap": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12348.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 6, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 18, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12353.json b/mne-python/source/doc/sphinxext/prs/12353.json new file mode 100644 index 0000000000000000000000000000000000000000..0cf114c11ebf97c0e6d7e6d03126d49da916990f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12353.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "eefd179b767fea456fd1eab3700c5299310b5b8e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 4, + "d": 5 + }, + "mne/_fiff/open.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 8, + "d": 8 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_annotate_amplitude.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/interpolate.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_realign.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 2, + "d": 2 + }, + "mne/source_space/_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 3, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked_field.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12354.json b/mne-python/source/doc/sphinxext/prs/12354.json new file mode 100644 index 0000000000000000000000000000000000000000..dc85305fd860ed416ef103f5d06a7633c282e75b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12354.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6af181afff86c679e1ac6c94b65a7843e07ae923", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12354.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked_field.py": { + "a": 16, + "d": 18 + }, + "mne/viz/tests/test_3d.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12357.json b/mne-python/source/doc/sphinxext/prs/12357.json new file mode 100644 index 0000000000000000000000000000000000000000..e5a46e50f04acbc3cdb90e12d692043d91d89cc2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12357.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "85838854a333575ecb9d74b8f767f8bcbd515d56", + "authors": [ + { + "n": "Kristijan Armeni", + "e": null + } + ], + "changes": { + "doc/changes/devel/12357.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 12, + "d": 6 + }, + "mne/io/neuralynx/tests/test_neuralynx.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12358.json b/mne-python/source/doc/sphinxext/prs/12358.json new file mode 100644 index 0000000000000000000000000000000000000000..599338803414eb2e970e2e29d5c61823e58494af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12358.json @@ -0,0 +1,775 @@ +{ + "merge_commit_sha": "2040898ac14e79353b7a23a07e177d1633298c0f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12358.other.rst": { + "a": 1, + "d": 0 + }, + "examples/datasets/limo_data.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/opm_data.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 1, + "d": 3 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 7, + "d": 7 + }, + "examples/inverse/compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 2, + "d": 10 + }, + "examples/inverse/label_source_activations.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/read_stc.py": { + "a": 1, + "d": 3 + }, + "examples/preprocessing/define_target_events.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 1, + "d": 10 + }, + "examples/preprocessing/ica_comparison.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/otp.py": { + "a": 2, + "d": 8 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/evoked_topomap.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/evoked_whitening.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/_digitization.py": { + "a": 13, + "d": 17 + }, + "mne/_fiff/meas_info.py": { + "a": 29, + "d": 45 + }, + "mne/_fiff/open.py": { + "a": 4, + "d": 4 + }, + "mne/_fiff/pick.py": { + "a": 14, + "d": 18 + }, + "mne/_fiff/proj.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/reference.py": { + "a": 5, + "d": 5 + }, + "mne/_fiff/tests/test_constants.py": { + "a": 4, + "d": 4 + }, + "mne/_fiff/utils.py": { + "a": 3, + "d": 4 + }, + "mne/_fiff/what.py": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 2, + "d": 2 + }, + "mne/_ola.py": { + "a": 22, + "d": 30 + }, + "mne/annotations.py": { + "a": 15, + "d": 19 + }, + "mne/baseline.py": { + "a": 10, + "d": 12 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 11, + "d": 12 + }, + "mne/beamformer/_dics.py": { + "a": 2, + "d": 3 + }, + "mne/beamformer/_lcmv.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/_rap_music.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 41, + "d": 49 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 1, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 7, + "d": 7 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 6 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 4, + "d": 4 + }, + "mne/channels/montage.py": { + "a": 10, + "d": 12 + }, + "mne/channels/tests/test_montage.py": { + "a": 18, + "d": 25 + }, + "mne/chpi.py": { + "a": 42, + "d": 52 + }, + "mne/commands/mne_anonymize.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 5, + "d": 7 + }, + "mne/commands/utils.py": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 16, + "d": 20 + }, + "mne/cov.py": { + "a": 31, + "d": 35 + }, + "mne/cuda.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 2, + "d": 6 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 8, + "d": 9 + }, + "mne/decoding/base.py": { + "a": 9, + "d": 14 + }, + "mne/decoding/csp.py": { + "a": 4, + "d": 6 + }, + "mne/decoding/mixin.py": { + "a": 5, + "d": 7 + }, + "mne/decoding/receptive_field.py": { + "a": 25, + "d": 31 + }, + "mne/decoding/search_light.py": { + "a": 4, + "d": 5 + }, + "mne/decoding/ssd.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 3, + "d": 5 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 34, + "d": 29 + }, + "mne/epochs.py": { + "a": 32, + "d": 40 + }, + "mne/event.py": { + "a": 2, + "d": 4 + }, + "mne/evoked.py": { + "a": 22, + "d": 29 + }, + "mne/filter.py": { + "a": 50, + "d": 77 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 11, + "d": 10 + }, + "mne/io/artemis123/artemis123.py": { + "a": 3, + "d": 3 + }, + "mne/io/artemis123/utils.py": { + "a": 5, + "d": 5 + }, + "mne/io/base.py": { + "a": 3, + "d": 4 + }, + "mne/io/boxy/boxy.py": { + "a": 3, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 10 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 4, + "d": 4 + }, + "mne/io/bti/bti.py": { + "a": 3, + "d": 3 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 4, + "d": 4 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/eeg.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 2, + "d": 2 + }, + "mne/io/curry/curry.py": { + "a": 3, + "d": 3 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 8, + "d": 8 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 3 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/general.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 2, + "d": 2 + }, + "mne/io/eximia/eximia.py": { + "a": 3, + "d": 3 + }, + "mne/io/eyelink/eyelink.py": { + "a": 2, + "d": 2 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 3 + }, + "mne/io/fil/fil.py": { + "a": 3, + "d": 3 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 3, + "d": 6 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 2 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 2, + "d": 2 + }, + "mne/io/neuralynx/tests/test_neuralynx.py": { + "a": 1, + "d": 2 + }, + "mne/io/nicolet/nicolet.py": { + "a": 2, + "d": 2 + }, + "mne/io/nihon/nihon.py": { + "a": 7, + "d": 7 + }, + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 2 + }, + "mne/io/nsx/nsx.py": { + "a": 5, + "d": 5 + }, + "mne/io/persyst/persyst.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 6, + "d": 6 + }, + "mne/io/snirf/_snirf.py": { + "a": 4, + "d": 4 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 5, + "d": 5 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/misc.py": { + "a": 3, + "d": 3 + }, + "mne/morph.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eyetracking/_pupillometry.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/eyetracking/calibration.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 11, + "d": 11 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 3 + }, + "mne/report/report.py": { + "a": 4, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/source_space/_source_space.py": { + "a": 3, + "d": 3 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 2 + }, + "mne/stats/parametric.py": { + "a": 4, + "d": 5 + }, + "mne/stats/regression.py": { + "a": 5, + "d": 5 + }, + "mne/surface.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_annotations.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_rank.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/csd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 5, + "d": 5 + }, + "mne/transforms.py": { + "a": 4, + "d": 8 + }, + "mne/utils/check.py": { + "a": 6, + "d": 6 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 9 + }, + "mne/utils/misc.py": { + "a": 2, + "d": 27 + }, + "mne/utils/progressbar.py": { + "a": 2, + "d": 3 + }, + "mne/utils/tests/test_logging.py": { + "a": 6, + "d": 6 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 7, + "d": 7 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 3 + }, + "mne/viz/backends/_utils.py": { + "a": 3, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 10, + "d": 11 + }, + "mne/viz/evoked.py": { + "a": 19, + "d": 30 + }, + "mne/viz/montage.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 5 + }, + "mne/viz/ui_events.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 4 + }, + "pyproject.toml": { + "a": 2, + "d": 1 + }, + "tutorials/clinical/60_sleep.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 2, + "d": 4 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 1, + "d": 5 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 2, + "d": 2 + }, + "tutorials/inverse/10_stc_class.py": { + "a": 3, + "d": 2 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 2, + "d": 2 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 3, + "d": 3 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 2, + "d": 4 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 2, + "d": 2 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 3, + "d": 5 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 3, + "d": 3 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 3, + "d": 3 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 2, + "d": 2 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 2, + "d": 2 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 16, + "d": 16 + }, + "tutorials/visualization/10_publication_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12359.json b/mne-python/source/doc/sphinxext/prs/12359.json new file mode 100644 index 0000000000000000000000000000000000000000..25aede2b256bc5bf87f67659d8571283a0722860 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12359.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "87cfea5323c61ded31da970c07238c447f4fe37f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12361.json b/mne-python/source/doc/sphinxext/prs/12361.json new file mode 100644 index 0000000000000000000000000000000000000000..b5d9ac58ab38fe49a8af6c6ee7353ac3e32987a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12361.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "52a905928d43703f96517b7050f524e5a653a079", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 10, + "d": 4 + }, + "doc/conf.py": { + "a": 9, + "d": 0 + }, + "mne/conftest.py": { + "a": 9, + "d": 0 + }, + "mne/export/_egimff.py": { + "a": 1, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12362.json b/mne-python/source/doc/sphinxext/prs/12362.json new file mode 100644 index 0000000000000000000000000000000000000000..46f56faf5ceb5b27fd7454e89d76d865957554d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12362.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a6f0331685bf6fc63001ed7ba6b379ee464fd91d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/manual_install.rst": { + "a": 11, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12363.json b/mne-python/source/doc/sphinxext/prs/12363.json new file mode 100644 index 0000000000000000000000000000000000000000..61bad8e833593db419a9c509699a8add5c59b536 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12363.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b8708b46499882062872cf7dea114dc08ad2b8cb", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12364.json b/mne-python/source/doc/sphinxext/prs/12364.json new file mode 100644 index 0000000000000000000000000000000000000000..000005543efb9d079e245e7d675db26c57899fbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12364.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "acf7b887976dc30f3edf93883911dfa9e49faae8", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12366.json b/mne-python/source/doc/sphinxext/prs/12366.json new file mode 100644 index 0000000000000000000000000000000000000000..b336718a89c5180faf015ee2192731f89f9c2328 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12366.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "d917be12de5739654f3c690fe176382948e261d2", + "authors": [ + { + "n": "Qian Chu", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Alex Lepauvre", + "e": "alexander.lepauvre@ad.aesthetics.mpg.de" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12366.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "mne/_fiff/reference.py": { + "a": 103, + "d": 14 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 154, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 18, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12368.json b/mne-python/source/doc/sphinxext/prs/12368.json new file mode 100644 index 0000000000000000000000000000000000000000..bfb733f67d5df1f27fc117d559f6ef4203df6fdc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12368.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "566c6ea5a6c5c66657e9edcffb1e596d21ba6952", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/installers.rst": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12371.json b/mne-python/source/doc/sphinxext/prs/12371.json new file mode 100644 index 0000000000000000000000000000000000000000..c40c044bce83ab7cbff4e93532fe098e0b825dac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12371.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1b0d20850fa2ff60fb61b8a7e7a68a38323dcf07", + "authors": [ + { + "n": "Kristijan Armeni", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12371.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12374.json b/mne-python/source/doc/sphinxext/prs/12374.json new file mode 100644 index 0000000000000000000000000000000000000000..08d8d2efb80e87922c12a941593b500afc8cfc6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12374.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2f0d2f3ee2422dfb721d1bcc7138ff1a6fccd662", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12376.json b/mne-python/source/doc/sphinxext/prs/12376.json new file mode 100644 index 0000000000000000000000000000000000000000..568624224b8649a9e35c4814248d35e6e823bcfe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12376.json @@ -0,0 +1,175 @@ +{ + "merge_commit_sha": "990ce18d4eaf0af6d0f0aadbc41fd86aa826ea59", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12376.dependency.rst": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 4, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 14, + "d": 13 + }, + "mne/conftest.py": { + "a": 4, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 6, + "d": 2 + }, + "mne/forward/tests/test_forward.py": { + "a": 7, + "d": 4 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 1 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 3, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 6 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 9, + "d": 5 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 7, + "d": 4 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 1 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 7, + "d": 5 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 4, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 8, + "d": 10 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 8, + "d": 12 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 13, + "d": 7 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 7, + "d": 4 + }, + "mne/report/tests/test_report.py": { + "a": 8, + "d": 4 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 3, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 5, + "d": 3 + }, + "mne/tests/test_bem.py": { + "a": 21, + "d": 13 + }, + "mne/tests/test_chpi.py": { + "a": 8, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 2, + "d": 1 + }, + "mne/utils/tests/test_check.py": { + "a": 2, + "d": 1 + }, + "mne/utils/tests/test_logging.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 8, + "d": 5 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_misc.py": { + "a": 9, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 3, + "d": 3 + }, + "pyproject.toml": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12377.json b/mne-python/source/doc/sphinxext/prs/12377.json new file mode 100644 index 0000000000000000000000000000000000000000..dd3cb612ff609329ffe214b43d70f55a10e871df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12377.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e0af51dec97219655d59aae0eab09675363f3792", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 1, + "d": 3 + }, + "mne/conftest.py": { + "a": 4, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 6, + "d": 0 + }, + "pyproject.toml": { + "a": 2, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 6 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12378.json b/mne-python/source/doc/sphinxext/prs/12378.json new file mode 100644 index 0000000000000000000000000000000000000000..1e4b472d344b08b3c85924ae2abaef02132764a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12378.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5339e08d7188f94e480d3b98bb81716a2e84e7f4", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1238.json b/mne-python/source/doc/sphinxext/prs/1238.json new file mode 100644 index 0000000000000000000000000000000000000000..842da6c15262d09f12b459e23bb8652817b6e4bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1238.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bf0447e92afa53216381e45998e6a2274428ac07", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12380.json b/mne-python/source/doc/sphinxext/prs/12380.json new file mode 100644 index 0000000000000000000000000000000000000000..538dd6e9fac23c13df756d34d55e3e56e1ec59cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12380.json @@ -0,0 +1,175 @@ +{ + "merge_commit_sha": "71faac906f00baa14b546da50d0f97aceedc004a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12380.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 2, + "d": 0 + }, + "mne/_fiff/open.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/pick.py": { + "a": 5, + "d": 5 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 7, + "d": 5 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/event.py": { + "a": 7, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/export/_export.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/curry.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 1 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 6, + "d": 6 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/ssp.py": { + "a": 9, + "d": 5 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 3, + "d": 0 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 8, + "d": 2 + }, + "mne/source_space/_source_space.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 5, + "d": 3 + }, + "mne/utils/tests/test_docs.py": { + "a": 6, + "d": 6 + }, + "mne/utils/tests/test_logging.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_qt.py": { + "a": 4, + "d": 4 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 7, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 10, + "d": 10 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12382.json b/mne-python/source/doc/sphinxext/prs/12382.json new file mode 100644 index 0000000000000000000000000000000000000000..dd1d0a8705a1a9f678bc11ff0b4131c8e1b32f0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12382.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6305bd16975e2fe31b1eaf63408c9f93bfe1b535", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12382.apichange.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12382.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 19, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12383.json b/mne-python/source/doc/sphinxext/prs/12383.json new file mode 100644 index 0000000000000000000000000000000000000000..245d627dcd0c236f9a3ce1790ab7d0ca35a08df5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12383.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "03d78f43bf46e98cc4e2905c6e98e6190cf01924", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12383.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 23, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12385.json b/mne-python/source/doc/sphinxext/prs/12385.json new file mode 100644 index 0000000000000000000000000000000000000000..a9af41660777c584082d5146879dfd966f6530eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12385.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8419ca04f7f85e5861128593fa92462d0ccbfb27", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12326.other.rst": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12389.json b/mne-python/source/doc/sphinxext/prs/12389.json new file mode 100644 index 0000000000000000000000000000000000000000..8374b8ba62fa97b322c4d35951259c558d4a6464 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12389.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "4ccd30fed3d83953506b4ff0532429973a0f797a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12389.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/pick.py": { + "a": 11, + "d": 1 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 6, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 9, + "d": 5 + }, + "mne/datasets/phantom_kit/phantom_kit.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_regress.py": { + "a": 13, + "d": 11 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 13, + "d": 0 + }, + "tutorials/inverse/95_phantom_KIT.py": { + "a": 31, + "d": 94 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12393.json b/mne-python/source/doc/sphinxext/prs/12393.json new file mode 100644 index 0000000000000000000000000000000000000000..f4ec8237dbe9290fd3e973902fc67ca7432ad3aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12393.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4cea4a9237867f3cfcdfdf9f7a67d7ee6b790f27", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12393.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 23, + "d": 2 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12394.json b/mne-python/source/doc/sphinxext/prs/12394.json new file mode 100644 index 0000000000000000000000000000000000000000..5a3b64dfd2090786f2a56b41c023bcf59838fcd4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12394.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0aa4bec2228f5d14c38d11fc37cea7a1e8c5140c", + "authors": [ + { + "n": "Judy D Zhu", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12394.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/io/kit/coreg.py": { + "a": 13, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 19, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12399.json b/mne-python/source/doc/sphinxext/prs/12399.json new file mode 100644 index 0000000000000000000000000000000000000000..b15ed52fd19a97a1c867c52e64bc3dbbf4b0181c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12399.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "324899ae4f60fb5d4911bfd679e53e8815a081d1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12399.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/html/d3.v3.min.js": { + "a": 0, + "d": 5 + }, + "mne/html/mpld3.v0.2.min.js": { + "a": 0, + "d": 2 + }, + "mne/report/js_and_css/report.css": { + "a": 19, + "d": 0 + }, + "mne/report/js_and_css/report.sass": { + "a": 0, + "d": 19 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12400.json b/mne-python/source/doc/sphinxext/prs/12400.json new file mode 100644 index 0000000000000000000000000000000000000000..f8ad700fa7ad3b679f1409e9010a765b1ce6422b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12400.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "195a2cc8009160fd125e355b0280e903a941c874", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 0, + "d": 66 + }, + ".github/workflows/tests.yml": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12410.json b/mne-python/source/doc/sphinxext/prs/12410.json new file mode 100644 index 0000000000000000000000000000000000000000..488bf5dd52e1f96a2008dfbd72c53806963f673c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12410.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "d8ea2f5e60174d61301dbefbed9c76c9adc01ec9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12410.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 1, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 40, + "d": 6 + }, + "mne/utils/misc.py": { + "a": 4, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 13 + }, + "mne/viz/evoked.py": { + "a": 37, + "d": 24 + }, + "mne/viz/tests/test_evoked.py": { + "a": 23, + "d": 10 + }, + "mne/viz/utils.py": { + "a": 46, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12411.json b/mne-python/source/doc/sphinxext/prs/12411.json new file mode 100644 index 0000000000000000000000000000000000000000..a4826c96830fc3f360c522af8f6088bf1789b494 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12411.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "57611ae7142c3de407dcad60cffe110cc1c84c86", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 8, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 13, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12412.json b/mne-python/source/doc/sphinxext/prs/12412.json new file mode 100644 index 0000000000000000000000000000000000000000..2962494f518da694f9b6eba0eba7e2424a747cf5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12412.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "78e840d4de0e1748cf32eab31de75887ec3e8082", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12417.json b/mne-python/source/doc/sphinxext/prs/12417.json new file mode 100644 index 0000000000000000000000000000000000000000..d143a652aeed878f1d5f23167e493ffc2197685d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12417.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0f5c91bbdfa0258c44c71ef8274cad22a90c13eb", + "authors": [ + { + "n": "Kristijan Armeni", + "e": null + } + ], + "changes": { + "mne/io/neuralynx/neuralynx.py": { + "a": 8, + "d": 51 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12419.json b/mne-python/source/doc/sphinxext/prs/12419.json new file mode 100644 index 0000000000000000000000000000000000000000..220bc73e44c30611d1333f413815ccbf3f53a742 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12419.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4c84b3e1f94a2772deb363d4298a078e64f55139", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12420.json b/mne-python/source/doc/sphinxext/prs/12420.json new file mode 100644 index 0000000000000000000000000000000000000000..bc22f326c396b5b432b2bedd0300f2c80c30dd0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12420.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9f0dfefe612776226d22714958dec2f3e2c05e4b", + "authors": [ + { + "n": "Nabil Alibou", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12420.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12421.json b/mne-python/source/doc/sphinxext/prs/12421.json new file mode 100644 index 0000000000000000000000000000000000000000..650e8f6382330073ab711e37fc689e449ac29df4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12421.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e6b49ea773d522670a534ec4a03470ab9c2baf01", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12426.json b/mne-python/source/doc/sphinxext/prs/12426.json new file mode 100644 index 0000000000000000000000000000000000000000..a1bdab68016cc8bbfd7f846548b55c733d6d26c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12426.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e05e77c92480871f0be38a184894d2ef48694844", + "authors": [ + { + "n": "Nabil Alibou", + "e": null + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12428.json b/mne-python/source/doc/sphinxext/prs/12428.json new file mode 100644 index 0000000000000000000000000000000000000000..370c87deeb51c34774027fb59ad457b7bdaa8a1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12428.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "78fbfea6363555feb873ef01762f20a4f6c53f72", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "pyproject.toml": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1243.json b/mne-python/source/doc/sphinxext/prs/1243.json new file mode 100644 index 0000000000000000000000000000000000000000..232a5e6ec138e9c51089759538b71543bf80ba2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1243.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "1ecda6ffdbe048bc9f19e800e10f63e64f2713f0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 20, + "d": 0 + }, + "mne/fiff/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/array/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/fiff/array/array.py": { + "a": 126, + "d": 0 + }, + "mne/fiff/array/tests/test_array.py": { + "a": 99, + "d": 0 + }, + "mne/fiff/bti/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/bti/bti.py": { + "a": 0, + "d": 0 + }, + "mne/fiff/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/pick.py": { + "a": 2, + "d": 0 + }, + "mne/viz.py": { + "a": 4, + "d": 4 + }, + "setup.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12430.json b/mne-python/source/doc/sphinxext/prs/12430.json new file mode 100644 index 0000000000000000000000000000000000000000..06320b7298cdc6d6d193196bd642f1144e6b3c11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12430.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8e55fef3a354e2c3dbe086256dfa3a73f698e0c5", + "authors": [ + { + "n": "Alexander Kiefer", + "e": null + } + ], + "changes": { + "doc/changes/devel/12430.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 5, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12431.json b/mne-python/source/doc/sphinxext/prs/12431.json new file mode 100644 index 0000000000000000000000000000000000000000..e6a401de03cd1f4e42cc0a8ed308b165d75611d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12431.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2851fb5f8d2a780ff2ef5dd181678fe8f10f04c6", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12433.json b/mne-python/source/doc/sphinxext/prs/12433.json new file mode 100644 index 0000000000000000000000000000000000000000..214b756906afc09cd2da07c9543571396c9f0f68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12433.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cef847997255716045e43bf11967af6d5206c8ba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12436.json b/mne-python/source/doc/sphinxext/prs/12436.json new file mode 100644 index 0000000000000000000000000000000000000000..7088e6ddbebf53bffa70bd0f3f297068cdd40c90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12436.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ccf679457e0ccddc6a2aabeda6968da647f10c6e", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/12436.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 6, + "d": 3 + }, + "tutorials/clinical/20_seeg.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12437.json b/mne-python/source/doc/sphinxext/prs/12437.json new file mode 100644 index 0000000000000000000000000000000000000000..235efbcbff30fa286e3377ad8438d5e718afd342 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12437.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7436c9efc30c0d2679161a83e9255770f41ec21b", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12438.json b/mne-python/source/doc/sphinxext/prs/12438.json new file mode 100644 index 0000000000000000000000000000000000000000..eceef08fdab00b293ee5ebd143e4f152d84db2fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12438.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1db901c2ab7dd428f43e3ad8a79f04edff790edc", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1244.json b/mne-python/source/doc/sphinxext/prs/1244.json new file mode 100644 index 0000000000000000000000000000000000000000..9bc02a8f43e5c21de5222c5cd11347d31e8c745c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1244.json @@ -0,0 +1,163 @@ +{ + "merge_commit_sha": "ec3c0387437e76843614ada85b90a4b007470e43", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 2, + "d": 2 + }, + "doc/source/whats_new.rst": { + "a": 12, + "d": 6 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 3, + "d": 2 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 4, + "d": 4 + }, + "examples/plot_evoked_topomap.py": { + "a": 5, + "d": 3 + }, + "examples/plot_evoked_whitening.py": { + "a": 8, + "d": 8 + }, + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/plot_meg_eeg_fields_3d.py": { + "a": 8, + "d": 6 + }, + "examples/plot_megsim_data.py": { + "a": 8, + "d": 8 + }, + "examples/plot_megsim_data_single_trial.py": { + "a": 2, + "d": 2 + }, + "examples/plot_read_evoked.py": { + "a": 3, + "d": 3 + }, + "examples/plot_shift_evoked.py": { + "a": 9, + "d": 9 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 10, + "d": 8 + }, + "examples/plot_ssp_projs_sensitivity_map.py": { + "a": 4, + "d": 5 + }, + "examples/plot_ssp_projs_topomaps.py": { + "a": 8, + "d": 6 + }, + "examples/plot_topography.py": { + "a": 3, + "d": 2 + }, + "mne/fiff/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/evoked.py": { + "a": 163, + "d": 47 + }, + "mne/fiff/tests/test_compensator.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 74, + "d": 61 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 3, + "d": 5 + }, + "mne/forward/tests/test_forward.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 5, + "d": 4 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 4, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 8, + "d": 8 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_cov.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 11 + }, + "mne/tests/test_utils.py": { + "a": 9, + "d": 9 + }, + "mne/tests/test_viz.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12440.json b/mne-python/source/doc/sphinxext/prs/12440.json new file mode 100644 index 0000000000000000000000000000000000000000..b81400ba8cc83dcae452a2f0e917a64e55863757 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12440.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7f06cb0096b71d4a6a4cd60c8be666ed046cadd0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/conftest.py": { + "a": 0, + "d": 2 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12441.json b/mne-python/source/doc/sphinxext/prs/12441.json new file mode 100644 index 0000000000000000000000000000000000000000..e77fb839d79edcc015ce349ee7165772c2b59308 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12441.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "73661d10942187a263a61ced85d31ff5eb8e1ce8", + "authors": [ + { + "n": "rcmdnk", + "e": "rcmdnk@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12441.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 48, + "d": 61 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 133, + "d": 52 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 1, + "d": 3 + }, + "mne/io/tests/test_read_raw.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12442.json b/mne-python/source/doc/sphinxext/prs/12442.json new file mode 100644 index 0000000000000000000000000000000000000000..6af341b76f788f91e7fbd1a6f107cdd497d6b2e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12442.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fc771130d7e7bd0a06984848c84eee209af7f4b8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12443.json b/mne-python/source/doc/sphinxext/prs/12443.json new file mode 100644 index 0000000000000000000000000000000000000000..984daa718a8af09859b50b0538deab0846868958 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12443.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5e23fe00bf0f7ec9cf75708269bbf2bd95a2dad6", + "authors": [ + { + "n": "Sophie Herbst", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12443.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 17, + "d": 2 + }, + "mne/report/tests/test_report.py": { + "a": 14, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12444.json b/mne-python/source/doc/sphinxext/prs/12444.json new file mode 100644 index 0000000000000000000000000000000000000000..9a93f0eac3470049286c4da10c1d06bf6478d2f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12444.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "85ca0ed7df3ae689ecf7a0109cc95982c5be2895", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12444.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 13, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12445.json b/mne-python/source/doc/sphinxext/prs/12445.json new file mode 100644 index 0000000000000000000000000000000000000000..56d62254c8422784cd12400b364700b20c69e2e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12445.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "49e895fd9c5ab44b92c73aaa210b223d4ad633f7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12445.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 49, + "d": 19 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 74, + "d": 2 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 12, + "d": 11 + }, + "mne/transforms.py": { + "a": 23, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12446.json b/mne-python/source/doc/sphinxext/prs/12446.json new file mode 100644 index 0000000000000000000000000000000000000000..6b15f5c2166a898a3c4acc501b2d7030a2a3ed58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12446.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "abfa0a6256b8f7f938ea91b1a7146c1a522f01dc", + "authors": [ + { + "n": "Richard Scholz", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12446.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 14, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12447.json b/mne-python/source/doc/sphinxext/prs/12447.json new file mode 100644 index 0000000000000000000000000000000000000000..c5f6c731c17d7c7ed03aca08545bf38360820228 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12447.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c410b6ddeb1f04562f83eed7d5418ff21254f7fd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/report/report.py": { + "a": 58, + "d": 56 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12448.json b/mne-python/source/doc/sphinxext/prs/12448.json new file mode 100644 index 0000000000000000000000000000000000000000..af5855e6dde058e0395b0313fbec5e3161f6ea89 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12448.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "614424718fa911cc0cfacc0df85652b3efaee358", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12450.json b/mne-python/source/doc/sphinxext/prs/12450.json new file mode 100644 index 0000000000000000000000000000000000000000..4cfdcd88283400add151e7244050c93ceac69c20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12450.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9ae99424325ef5f100c0774f469a948884fe8b07", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/12450.other.rst": { + "a": 1, + "d": 0 + }, + "mne/export/_brainvision.py": { + "a": 141, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12451.json b/mne-python/source/doc/sphinxext/prs/12451.json new file mode 100644 index 0000000000000000000000000000000000000000..bd5d57418e582448dd3073b201c1eff77599700a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12451.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "a867e5cd372ab8ee980efffd14c7d157c5b73bf3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/12451.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12451.dependency.rst": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 11, + "d": 20 + }, + "mne/datasets/__init__.pyi": { + "a": 1, + "d": 1 + }, + "mne/datasets/_infant/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 8, + "d": 1 + }, + "mne/fixes.py": { + "a": 2, + "d": 3 + }, + "mne/io/base.py": { + "a": 7, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 28, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 43, + "d": 7 + }, + "mne/utils/check.py": { + "a": 19, + "d": 1 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12452.json b/mne-python/source/doc/sphinxext/prs/12452.json new file mode 100644 index 0000000000000000000000000000000000000000..2bb9331bf07094658fa677631882a091ff669c52 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12452.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b210678357b1dae7f880d11392863be5fda4983e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "pyproject.toml": { + "a": 2, + "d": 2 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12453.json b/mne-python/source/doc/sphinxext/prs/12453.json new file mode 100644 index 0000000000000000000000000000000000000000..f268ae084716bc7bf8dd9c40a7c7aa8fc34da527 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12453.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7d5329ee5aa1f14b5450abebaf9caeecd3ccdb8f", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12454.json b/mne-python/source/doc/sphinxext/prs/12454.json new file mode 100644 index 0000000000000000000000000000000000000000..5bbc0dccf4e53ee502579d78137ee4e3339ba7ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12454.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ae6e55e8eb41f080d6c209c129bb86ecdb2fc30d", + "authors": [ + { + "n": "Sophie Herbst", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12454.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 17, + "d": 3 + }, + "mne/report/tests/test_report.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12456.json b/mne-python/source/doc/sphinxext/prs/12456.json new file mode 100644 index 0000000000000000000000000000000000000000..1ef598f37ff334304025b31dce849bb91d246ff7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12456.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b8ff49750fd8381ad4ef6615aa941270d1e3c877", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/12456.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12461.json b/mne-python/source/doc/sphinxext/prs/12461.json new file mode 100644 index 0000000000000000000000000000000000000000..00adfaa637d2982f70f7fce97ff71b709f96553c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12461.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "69d29637db82563cd56d8effc396124f243cf4fb", + "authors": [ + { + "n": "Will Turner", + "e": "williamfrancisturner@gmail.com" + }, + { + "n": "Will Turner", + "e": "wturner@student.unimelb.edu.au" + } + ], + "changes": { + ".github/CONTRIBUTING.md": { + "a": 1, + "d": 1 + }, + ".github/PULL_REQUEST_TEMPLATE.md": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/12461.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12462.json b/mne-python/source/doc/sphinxext/prs/12462.json new file mode 100644 index 0000000000000000000000000000000000000000..0f9de3c36a6a429076df2277da6879d85dab28c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12462.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d17d885a36935a40b4d1b62796510cf5015b1d2b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Sophie Herbst", + "e": "ksherbst@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12462.newfeature.rst": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/epochs_metadata.py": { + "a": 171, + "d": 0 + }, + "mne/epochs.py": { + "a": 99, + "d": 21 + }, + "mne/tests/test_epochs.py": { + "a": 24, + "d": 6 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12463.json b/mne-python/source/doc/sphinxext/prs/12463.json new file mode 100644 index 0000000000000000000000000000000000000000..4c82766461630ace46f1ad007c18d7a65b6900fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12463.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f2fa901ca6f87eaadca6acd45f4c460f1c92f8fe", + "authors": [ + { + "n": "Kristijan Armeni", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12463.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 7, + "d": 0 + }, + "mne/decoding/search_light.py": { + "a": 7, + "d": 0 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 82, + "d": 0 + }, + "mne/io/neuralynx/tests/test_neuralynx.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12464.json b/mne-python/source/doc/sphinxext/prs/12464.json new file mode 100644 index 0000000000000000000000000000000000000000..127520283586e220bf894e11ba62c0213d83454e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12464.json @@ -0,0 +1,391 @@ +{ + "merge_commit_sha": "b8d9c1713bfef91e7b7bb663ec18a528a9b1691f", + "authors": [ + { + "n": "hasrat17", + "e": "hasrat407@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12464.other.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 3, + "d": 1 + }, + "doc/sphinxext/flow_diagram.py": { + "a": 5, + "d": 9 + }, + "doc/sphinxext/mne_substitutions.py": { + "a": 4, + "d": 8 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 8, + "d": 8 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_lead_dots.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 7, + "d": 8 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 5 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 8, + "d": 8 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 4 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 3, + "d": 4 + }, + "mne/io/base.py": { + "a": 20, + "d": 30 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 4, + "d": 4 + }, + "mne/io/curry/curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 4, + "d": 4 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 5, + "d": 8 + }, + "mne/io/fieldtrip/utils.py": { + "a": 4, + "d": 5 + }, + "mne/io/kit/coreg.py": { + "a": 4, + "d": 6 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 3 + }, + "mne/io/nirx/nirx.py": { + "a": 4, + "d": 4 + }, + "mne/label.py": { + "a": 32, + "d": 35 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 3, + "d": 4 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 3, + "d": 5 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 7 + }, + "mne/morph.py": { + "a": 17, + "d": 19 + }, + "mne/morph_map.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 8, + "d": 10 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 6 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/interpolate.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/maxwell.py": { + "a": 33, + "d": 42 + }, + "mne/preprocessing/otp.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 4, + "d": 8 + }, + "mne/preprocessing/xdawn.py": { + "a": 2, + "d": 2 + }, + "mne/proj.py": { + "a": 4, + "d": 4 + }, + "mne/rank.py": { + "a": 2, + "d": 2 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 19, + "d": 21 + }, + "mne/simulation/source.py": { + "a": 4, + "d": 5 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 21, + "d": 24 + }, + "mne/source_space/_source_space.py": { + "a": 41, + "d": 55 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 10 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 3 + }, + "mne/stats/tests/test_parametric.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 8, + "d": 11 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 7, + "d": 9 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_filter.py": { + "a": 4, + "d": 8 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_line_endings.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/multitaper.py": { + "a": 4, + "d": 7 + }, + "mne/time_frequency/tfr.py": { + "a": 14, + "d": 16 + }, + "mne/transforms.py": { + "a": 6, + "d": 10 + }, + "mne/utils/_bunch.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 6, + "d": 9 + }, + "mne/utils/check.py": { + "a": 16, + "d": 20 + }, + "mne/utils/config.py": { + "a": 3, + "d": 3 + }, + "mne/utils/dataframe.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 11 + }, + "mne/utils/mixin.py": { + "a": 2, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 22, + "d": 25 + }, + "mne/utils/tests/test_numerics.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 15, + "d": 20 + }, + "mne/viz/_brain/_brain.py": { + "a": 11, + "d": 11 + }, + "mne/viz/_brain/colormap.py": { + "a": 1, + "d": 3 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 3 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 4 + }, + "mne/viz/misc.py": { + "a": 6, + "d": 6 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 6 + }, + "pyproject.toml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12467.json b/mne-python/source/doc/sphinxext/prs/12467.json new file mode 100644 index 0000000000000000000000000000000000000000..f1c110c1fbcd9f42150f1f0c1ec722ae0d4b7dc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12467.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "5af2dd7f9f25511727716072bc27fcaed251a159", + "authors": [ + { + "n": "Ivo Pascal de Jong", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12467.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 6, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 19, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12469.json b/mne-python/source/doc/sphinxext/prs/12469.json new file mode 100644 index 0000000000000000000000000000000000000000..4a07ceb17118761d50dface9db96184f88b05720 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12469.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "985c1959d4b0e2229d9288e78d0a022926042b76", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1247.json b/mne-python/source/doc/sphinxext/prs/1247.json new file mode 100644 index 0000000000000000000000000000000000000000..41a9d4e4a7c5deff2a82c13034ea0a18de346e7c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1247.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e09aa4cb6371e8e8b647ddf19db62a56e5c1aec8", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 40, + "d": 12 + }, + "mne/gui/_fiducials_gui.py": { + "a": 1, + "d": 0 + }, + "mne/gui/_file_traits.py": { + "a": 3, + "d": 0 + }, + "mne/gui/_viewer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12470.json b/mne-python/source/doc/sphinxext/prs/12470.json new file mode 100644 index 0000000000000000000000000000000000000000..0f71e266244940249a61d77bc5cd300fc62d2d09 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12470.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "62a0c40fa01ec65910313109cd414e22b3b0d135", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12470.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12471.json b/mne-python/source/doc/sphinxext/prs/12471.json new file mode 100644 index 0000000000000000000000000000000000000000..23385f1d06bcdfb0a25181d8b24790d90169a415 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12471.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "668b508a7342828cf30e090a02f2e1a6e7402f35", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 3, + "d": 3 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12474.json b/mne-python/source/doc/sphinxext/prs/12474.json new file mode 100644 index 0000000000000000000000000000000000000000..456c0881933dd14e6eab3413398e3b43fc96b333 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12474.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "795d6d9510a691e589c43c8cc2aef4edd97661d7", + "authors": [ + { + "n": "Liberty Hamilton", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12474.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/defaults.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12476.json b/mne-python/source/doc/sphinxext/prs/12476.json new file mode 100644 index 0000000000000000000000000000000000000000..c4f137bb883893b3f4694daad7a84228b6d319e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12476.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e23e9e1bdd3ecf63af9386cd2a19129d26900864", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12476.bugfix.rst": { + "a": 1, + "d": 0 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 1, + "d": 0 + }, + "mne/cov.py": { + "a": 71, + "d": 21 + }, + "mne/decoding/csp.py": { + "a": 68, + "d": 11 + }, + "mne/decoding/tests/test_csp.py": { + "a": 87, + "d": 30 + }, + "mne/rank.py": { + "a": 69, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12477.json b/mne-python/source/doc/sphinxext/prs/12477.json new file mode 100644 index 0000000000000000000000000000000000000000..41d6a4687d0f7a414317714a2d57aa0829feae1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12477.json @@ -0,0 +1,223 @@ +{ + "merge_commit_sha": "64901c4e24db697b23930f7557480ca0b97b4f8c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 4, + "d": 4 + }, + "doc/sphinxext/unit_role.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/hf_sef_data.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 0, + "d": 1 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 0, + "d": 1 + }, + "examples/io/elekta_epochs.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/css.py": { + "a": 3, + "d": 3 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/xdawn_denoising.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/eyetracking_plot_heatmap.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/topo_compare_conditions.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/topo_customized.py": { + "a": 0, + "d": 1 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 3, + "d": 2 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 5, + "d": 3 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 0, + "d": 1 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 0, + "d": 1 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 3, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 6, + "d": 4 + }, + "mne/forward/tests/test_forward.py": { + "a": 3, + "d": 2 + }, + "mne/io/_read_raw.py": { + "a": 0, + "d": 1 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 3, + "d": 2 + }, + "mne/io/besa/tests/test_besa.py": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 3, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 3, + "d": 2 + }, + "mne/io/eyelink/_utils.py": { + "a": 0, + "d": 1 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 3, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 2 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_lof.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 6, + "d": 4 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 3, + "d": 2 + }, + "mne/report/js_and_css/bootstrap-icons/gen_css_for_mne.py": { + "a": 0, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 12, + "d": 6 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 3, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 9, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 0, + "d": 1 + }, + "mne/viz/evoked_field.py": { + "a": 22, + "d": 21 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 6, + "d": 6 + }, + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_misc.py": { + "a": 6, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 3, + "d": 2 + }, + "mne/viz/ui_events.py": { + "a": 1, + "d": 0 + }, + "tutorials/visualization/20_ui_events.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12478.json b/mne-python/source/doc/sphinxext/prs/12478.json new file mode 100644 index 0000000000000000000000000000000000000000..32801ccc78bfc5fef91c3c64b597718bbc797c65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12478.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "97b745a2ff2db3661ed64a3c54fc85abeea558cf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12481.json b/mne-python/source/doc/sphinxext/prs/12481.json new file mode 100644 index 0000000000000000000000000000000000000000..d2ae74bd588ea81e14e14e05bc7b5419d37243c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12481.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ae69b03a00eb2c72ae9b13c71ae541747daf55da", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + } + ], + "changes": { + "doc/changes/devel/12481.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12482.json b/mne-python/source/doc/sphinxext/prs/12482.json new file mode 100644 index 0000000000000000000000000000000000000000..2c413b57b3e738392659522d9e264649fa655ddf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12482.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "946c616b6fe65663b66cf7433064eef2ff0e2cc0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12483.json b/mne-python/source/doc/sphinxext/prs/12483.json new file mode 100644 index 0000000000000000000000000000000000000000..9eeab471b5d33a8b4d99f3251e41e25964fa34e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12483.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "72799349bd6c4987dcef8e71adaf1a4a8cc6e061", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12483.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_qt.py": { + "a": 26, + "d": 18 + }, + "mne/viz/backends/_utils.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12484.json b/mne-python/source/doc/sphinxext/prs/12484.json new file mode 100644 index 0000000000000000000000000000000000000000..feca0bc60c455f55ba45e4fb666623a30959c9cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12484.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b906b784430af749977828da0eeda922e28efd98", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12484.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 16, + "d": 0 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 33, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12487.json b/mne-python/source/doc/sphinxext/prs/12487.json new file mode 100644 index 0000000000000000000000000000000000000000..7a9372c9a21730043d6680a7ebf3abd5fbe690bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12487.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "a622a467074ea9ba0f1d1168c4ec3b8c6af74323", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_includes/channel_interpolation.rst": { + "a": 2, + "d": 2 + }, + "doc/_includes/forward.rst": { + "a": 35, + "d": 35 + }, + "doc/_includes/ssp.rst": { + "a": 2, + "d": 2 + }, + "doc/api/events.rst": { + "a": 1, + "d": 1 + }, + "doc/api/file_io.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v0.10.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v0.12.rst": { + "a": 35, + "d": 35 + }, + "doc/changes/v0.13.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v0.15.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v0.17.rst": { + "a": 42, + "d": 42 + }, + "doc/changes/v1.2.rst": { + "a": 1, + "d": 1 + }, + "doc/documentation/datasets.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12488.json b/mne-python/source/doc/sphinxext/prs/12488.json new file mode 100644 index 0000000000000000000000000000000000000000..bc538332fa0c575733932f0d9eab183d810f7f29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12488.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d7fdcb004ae5dc95d86f5be598bd87677ad1c251", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12489.json b/mne-python/source/doc/sphinxext/prs/12489.json new file mode 100644 index 0000000000000000000000000000000000000000..d953504a978eb1a4fdabdf4deec633f83503202b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12489.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "90067893e330c1941c055be22bc5f442ad320ec3", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12489.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/utils/misc.py": { + "a": 6, + "d": 5 + }, + "mne/utils/tests/test_misc.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12491.json b/mne-python/source/doc/sphinxext/prs/12491.json new file mode 100644 index 0000000000000000000000000000000000000000..aacc16579efd0c78338d4e479b47fd67a4e5374d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12491.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b752d2a3cd247df18371eae6d8c29ebb8a938b87", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "README.rst": { + "a": 3, + "d": 3 + }, + "doc/changes/devel/12491.dependency.rst": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 3, + "d": 7 + }, + "mne/viz/backends/_utils.py": { + "a": 32, + "d": 75 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 1, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12492.json b/mne-python/source/doc/sphinxext/prs/12492.json new file mode 100644 index 0000000000000000000000000000000000000000..d7a4ed77d1d20b04bd3f626ed2aa76d02893a4c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12492.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "25e6aecf1c0fd0b0f1e2b3fc8d46377dffa752e4", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 3, + "d": 6 + }, + "mne/_freesurfer.py": { + "a": 1, + "d": 1 + }, + "mne/_ola.py": { + "a": 3, + "d": 7 + }, + "mne/annotations.py": { + "a": 7, + "d": 10 + }, + "mne/bem.py": { + "a": 4, + "d": 5 + }, + "mne/channels/montage.py": { + "a": 3, + "d": 5 + }, + "mne/coreg.py": { + "a": 4, + "d": 4 + }, + "mne/cov.py": { + "a": 6, + "d": 8 + }, + "mne/dipole.py": { + "a": 5, + "d": 7 + }, + "mne/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 4, + "d": 18 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 2 + }, + "mne/io/array/array.py": { + "a": 2, + "d": 3 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + }, + "mne/label.py": { + "a": 3, + "d": 3 + }, + "mne/morph.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/csd.py": { + "a": 3, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 6 + }, + "pyproject.toml": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12494.json b/mne-python/source/doc/sphinxext/prs/12494.json new file mode 100644 index 0000000000000000000000000000000000000000..e080b83ff55b8526ad35fa935016a8274f961583 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12494.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b0ac8a3650a6094ed6efe5ef548aa0ad31513711", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/backends/_utils.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12496.json b/mne-python/source/doc/sphinxext/prs/12496.json new file mode 100644 index 0000000000000000000000000000000000000000..b410f6031101d60e4fa3fd8b5ec6adfefb87ad93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12496.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2a973338657e6d0609b1d60a8c109cad533c033c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_lof.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12498.json b/mne-python/source/doc/sphinxext/prs/12498.json new file mode 100644 index 0000000000000000000000000000000000000000..8ae290c38c73f45c1ee4b3f38c8e69af1276bbfa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12498.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "60505e96a7d90a56b48a6e1ea1e9f9f16a3dd87a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12498.bugfix.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 0, + "d": 1 + }, + "mne/report/report.py": { + "a": 2, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 12, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 3, + "d": 0 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12499.json b/mne-python/source/doc/sphinxext/prs/12499.json new file mode 100644 index 0000000000000000000000000000000000000000..11cafe255cd542ca0ff72929441b432d3eeac06d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12499.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "14ff9483cf92a40479b23f4b17886d3d384f65a5", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1250.json b/mne-python/source/doc/sphinxext/prs/1250.json new file mode 100644 index 0000000000000000000000000000000000000000..933118279795867c8693d04e5b6811aa1fae2464 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1250.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bd3fe74a73de5fed74f9c8e5f45bedfe5e9aa963", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 5, + "d": 0 + }, + "mne/fiff/edf/edf.py": { + "a": 122, + "d": 7 + }, + "mne/fiff/edf/tests/data/test.edf": { + "a": 7, + "d": 7 + }, + "mne/fiff/edf/tests/test_edf.py": { + "a": 88, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12501.json b/mne-python/source/doc/sphinxext/prs/12501.json new file mode 100644 index 0000000000000000000000000000000000000000..c870c0d63f4525dc315988915be986a82ae5ce62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12501.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5843ad17e2a883b5f029731252587ef9d01a8ab8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_lof.py": { + "a": 0, + "d": 4 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12504.json b/mne-python/source/doc/sphinxext/prs/12504.json new file mode 100644 index 0000000000000000000000000000000000000000..7f4934a8fe916ebf9687a12f37c32eebaee18685 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12504.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f65bc00ad6ee586acf101fe21b6ed5848dcd9523", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 2, + "d": 4 + }, + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12506.json b/mne-python/source/doc/sphinxext/prs/12506.json new file mode 100644 index 0000000000000000000000000000000000000000..3c77eba3dab186d372b9452cd4170cc85ea644e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12506.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cf6e13c1e7a0cf0fabbcb33865610007bd891ef3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 3, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12507.json b/mne-python/source/doc/sphinxext/prs/12507.json new file mode 100644 index 0000000000000000000000000000000000000000..f4ae938f67957f8926276280f040892a667d25d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12507.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "415e7f68ed71135baff0ea857ca4fab5a3690bf8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12507.bugfix.rst": { + "a": 5, + "d": 0 + }, + "mne/filter.py": { + "a": 8, + "d": 65 + }, + "mne/fixes.py": { + "a": 55, + "d": 0 + }, + "mne/tests/test_filter.py": { + "a": 55, + "d": 7 + }, + "mne/utils/docs.py": { + "a": 27, + "d": 12 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 12, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12509.json b/mne-python/source/doc/sphinxext/prs/12509.json new file mode 100644 index 0000000000000000000000000000000000000000..5d13f791628464a6fc224cdff7dcc1e0e4268250 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12509.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "c4d20c37d0c3f2a337428811f0e627ccdb078a09", + "authors": [ + { + "n": "Nabil Alibou", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/channel_types.rst": { + "a": 61, + "d": 29 + }, + "doc/changes/devel/12509.other.rst": { + "a": 2, + "d": 0 + }, + "doc/documentation/glossary.rst": { + "a": 15, + "d": 4 + }, + "doc/sphinxext/mne_substitutions.py": { + "a": 23, + "d": 1 + }, + "mne/_fiff/meas_info.py": { + "a": 22, + "d": 13 + }, + "mne/_fiff/pick.py": { + "a": 3, + "d": 4 + }, + "mne/defaults.py": { + "a": 6, + "d": 0 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1251.json b/mne-python/source/doc/sphinxext/prs/1251.json new file mode 100644 index 0000000000000000000000000000000000000000..c9bd64ffd42eb3e57f8c724704f6fe9ec2dc1fdc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1251.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "77959bb618cd0a71d7f2728cea5ff003781d75e8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/edf/tests/test_edf.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12510.json b/mne-python/source/doc/sphinxext/prs/12510.json new file mode 100644 index 0000000000000000000000000000000000000000..782beed53f23f706a896dcd7170b60504b713f8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12510.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6c4418c2dc00d8d84ee7fc29acc6d04dfc4e7fac", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/12510.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 6, + "d": 3 + }, + "mne/export/tests/test_export.py": { + "a": 27, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 16, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12511.json b/mne-python/source/doc/sphinxext/prs/12511.json new file mode 100644 index 0000000000000000000000000000000000000000..6b1db9fcfed59dabf16f93995a2107a25051cd08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12511.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "169372da67dc243b817f024820b349495a5aa109", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 2, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 5, + "d": 3 + }, + "tools/github_actions_dependencies.sh": { + "a": 10, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12513.json b/mne-python/source/doc/sphinxext/prs/12513.json new file mode 100644 index 0000000000000000000000000000000000000000..89d376957a608a6bb831e0c5b8ac8af394565da9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12513.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "eee8e6fe580034f4a3a4fb13bdca3bfc99240708", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12513.newfeature.rst": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 72, + "d": 26 + }, + "mne/report/tests/test_report.py": { + "a": 41, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12514.json b/mne-python/source/doc/sphinxext/prs/12514.json new file mode 100644 index 0000000000000000000000000000000000000000..037093c95c066807eb243948136c191ce702124d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12514.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8ee98c95f4bc9866679fd49111f9b041b5b0e2fa", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 12, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12515.json b/mne-python/source/doc/sphinxext/prs/12515.json new file mode 100644 index 0000000000000000000000000000000000000000..d838dc9ef4595568bd27e06965fa2f925e002327 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12515.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b56420f601a0675cdc211c24aa5d52e722ece099", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12518.json b/mne-python/source/doc/sphinxext/prs/12518.json new file mode 100644 index 0000000000000000000000000000000000000000..3fcc4697c7a7564f044b1aba7536970f9d728d56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12518.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5a1d009d02080f594414e45fc94543c035740e37", + "authors": [ + { + "n": "rcmdnk", + "e": "rcmdnk@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12518.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 46, + "d": 9 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 68, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1252.json b/mne-python/source/doc/sphinxext/prs/1252.json new file mode 100644 index 0000000000000000000000000000000000000000..8cad5b04e9ba3b30fadff72e6f1a35f4aed7eec0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1252.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f6cda36272b28f7b3a55b29ac751575b0edc608b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/egi/egi.py": { + "a": 27, + "d": 15 + }, + "mne/fiff/egi/tests/test_egi.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12520.json b/mne-python/source/doc/sphinxext/prs/12520.json new file mode 100644 index 0000000000000000000000000000000000000000..6a7ffba37871b8a39f75785617dbba125d0f5c3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12520.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "58a02c25998f46b9de587cc76a51d6351d96e415", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 4, + "d": 5 + }, + "azure-pipelines.yml": { + "a": 3, + "d": 3 + }, + "mne/export/_edf.py": { + "a": 17, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 11, + "d": 8 + }, + "mne/utils/dataframe.py": { + "a": 11, + "d": 2 + }, + "tools/azure_dependencies.sh": { + "a": 7, + "d": 31 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 42 + }, + "tools/install_pre_requirements.sh": { + "a": 82, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12522.json b/mne-python/source/doc/sphinxext/prs/12522.json new file mode 100644 index 0000000000000000000000000000000000000000..f3ce47f5e58450fdbd31991a645efe9dd579fc04 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12522.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3c101cdd88b1e83017190ae490654ed290785b94", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 2 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "doc/install/mne_tools_suite.rst": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12523.json b/mne-python/source/doc/sphinxext/prs/12523.json new file mode 100644 index 0000000000000000000000000000000000000000..27ca5bfea5206802a479612aecd3649ed878ff2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12523.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a02838fcf9673e4ed955fa79abbe79b07c968d63", + "authors": [ + { + "n": "Seyed (Yahya) Shirazi", + "e": "shirazi@ieee.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12523.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12524.json b/mne-python/source/doc/sphinxext/prs/12524.json new file mode 100644 index 0000000000000000000000000000000000000000..44a5f2007170c79f7ca3be940a3c0f2fcad95353 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12524.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0aef0795afdb1543dfee8fe76485d3a1ff40ed31", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12525.json b/mne-python/source/doc/sphinxext/prs/12525.json new file mode 100644 index 0000000000000000000000000000000000000000..18a5d7674be8a29c087ed23681d9816e496fbc13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12525.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8590d35cabeae22b0bda41d3b774587426ae961c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12526.json b/mne-python/source/doc/sphinxext/prs/12526.json new file mode 100644 index 0000000000000000000000000000000000000000..5b9e6c2031b7f039918b9c33e7d5cd96f4ec2369 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12526.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "675f38a036804b0c1259d05f2ff6b0131d69fc81", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12526.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 8, + "d": 1 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12529.json b/mne-python/source/doc/sphinxext/prs/12529.json new file mode 100644 index 0000000000000000000000000000000000000000..01d8f31506633673ca06468673e3344a0d6b9867 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12529.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "026e2622e9f32741ac20bc4c051bdc89bbbd3785", + "authors": [ + { + "n": "tom", + "e": "tdonoghue.research@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 14, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1253.json b/mne-python/source/doc/sphinxext/prs/1253.json new file mode 100644 index 0000000000000000000000000000000000000000..02e567d81a3503811f13848747b5c3a84ec59544 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1253.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3d068c5e67da500862b0ebd2c4b8bffbcb5f18b4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/channels.py": { + "a": 6, + "d": 4 + }, + "mne/fiff/fiff/tests/test_raw.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12531.json b/mne-python/source/doc/sphinxext/prs/12531.json new file mode 100644 index 0000000000000000000000000000000000000000..11e8f09157049134d940a2afe42f3317e24fb163 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12531.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "24c2e8f809eaae87c8e4c8d574fcf867b742f755", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/conf.py": { + "a": 0, + "d": 2 + }, + "mne/conftest.py": { + "a": 0, + "d": 3 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 12, + "d": 2 + }, + "mne/gui/tests/test_coreg.py": { + "a": 0, + "d": 3 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 10, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 18 + }, + "mne/utils/config.py": { + "a": 9, + "d": 0 + }, + "mne/utils/tests/test_config.py": { + "a": 21, + "d": 3 + }, + "pyproject.toml": { + "a": 4, + "d": 5 + }, + "tools/install_pre_requirements.sh": { + "a": 4, + "d": 3 + }, + "tools/pyqt6_requirements.txt": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12532.json b/mne-python/source/doc/sphinxext/prs/12532.json new file mode 100644 index 0000000000000000000000000000000000000000..37aa089fbd4110ba79f761f84b53c8e8fee8cbdb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12532.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "067715af11030c3dbe54362a957de132170c3f43", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 6, + "d": 3 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12533.json b/mne-python/source/doc/sphinxext/prs/12533.json new file mode 100644 index 0000000000000000000000000000000000000000..a910810bc2f6ceb23bc589e4b9dab505f7d1fb70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12533.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "940ac9553ce42c15b4c16ecd013824ca3ea7244a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d_overlay.py": { + "a": 1, + "d": 5 + }, + "mne/viz/backends/_pyvista.py": { + "a": 261, + "d": 298 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12534.json b/mne-python/source/doc/sphinxext/prs/12534.json new file mode 100644 index 0000000000000000000000000000000000000000..32c53321d986741f12c30a7c5bef09247a33b17d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12534.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "0d514882be5e255c6c31639f06bc845eea770cfe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/_fiff/pick.py": { + "a": 9, + "d": 32 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 1, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12535.json b/mne-python/source/doc/sphinxext/prs/12535.json new file mode 100644 index 0000000000000000000000000000000000000000..193ac9b96a5dfba43fa78047a8a7fb6ce3907cf8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12535.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "105c8b819c08d24262f65d870b55bf0b305340d7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/devel/12535.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 6, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12536.json b/mne-python/source/doc/sphinxext/prs/12536.json new file mode 100644 index 0000000000000000000000000000000000000000..9202703faa0c83da1640e89e01ed9524b1633367 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12536.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a92d798744035a304e307f0c5170db6268d75079", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/devel/12536.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 21, + "d": 2 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 20, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12537.json b/mne-python/source/doc/sphinxext/prs/12537.json new file mode 100644 index 0000000000000000000000000000000000000000..99adb4c0beb9400f8c852336059ce9dd7aab79e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12537.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b33e7a1906bb12617f0483abc770ff0ca91ba201", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12537.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 7, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12538.json b/mne-python/source/doc/sphinxext/prs/12538.json new file mode 100644 index 0000000000000000000000000000000000000000..1e7998f5470dfd8ec67b07d25798459a323faf1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12538.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bf74c045d5220682e6e229b95a6e406014c0c73a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 27, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12539.json b/mne-python/source/doc/sphinxext/prs/12539.json new file mode 100644 index 0000000000000000000000000000000000000000..fd00c15e1e3689886eb928f4faacdb7f4b4b6676 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12539.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e6dedb326910ddcd30acd207aa8f35491e14ca94", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_numerics.py": { + "a": 5, + "d": 1 + }, + "tutorials/preprocessing/80_opm_processing.py": { + "a": 60, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12540.json b/mne-python/source/doc/sphinxext/prs/12540.json new file mode 100644 index 0000000000000000000000000000000000000000..77c44bce31663b55cf1a6c9b9835be61bcd35c49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12540.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8c7daf49667d317b1759264eaaff01cc769ee656", + "authors": [ + { + "n": null, + "e": "erkkahe@gmail.com" + } + ], + "changes": { + "doc/install/mne_tools_suite.rst": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12541.json b/mne-python/source/doc/sphinxext/prs/12541.json new file mode 100644 index 0000000000000000000000000000000000000000..1a784c19d5df2811fbb07df03085878c4eb7f0a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12541.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "637b4343f059d3c03e9e68f7fd65ef1ffc3b33c7", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12544.json b/mne-python/source/doc/sphinxext/prs/12544.json new file mode 100644 index 0000000000000000000000000000000000000000..d984720415b7cc8bcdf1add577bd94914eb4a62d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12544.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b95fc4a9151f633d40074e7e43cb6f6487275a33", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12544.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/source_space/_source_space.py": { + "a": 3, + "d": 2 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12545.json b/mne-python/source/doc/sphinxext/prs/12545.json new file mode 100644 index 0000000000000000000000000000000000000000..ae35699e2e23f42f89ee0d7c90933cee468217a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12545.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "321825b5e13f771e5ce31d0383609468d0a1d5e8", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "examples/forward/left_cerebellum_volume_source.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12548.json b/mne-python/source/doc/sphinxext/prs/12548.json new file mode 100644 index 0000000000000000000000000000000000000000..56776600be5078cc5f8ea8093ae9bd9bd3a1c76f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12548.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6b5a59d2cb07177a0735b3b9a2701345cfc1d98b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 5, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1255.json b/mne-python/source/doc/sphinxext/prs/1255.json new file mode 100644 index 0000000000000000000000000000000000000000..9009f406b94be60b49a684c5da909cec5aa9654e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1255.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0f0f9509132533dffdfe39a439caca52c6d6c12b", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "mne/fiff/channels.py": { + "a": 26, + "d": 42 + }, + "mne/fiff/fiff/tests/test_raw.py": { + "a": 16, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12550.json b/mne-python/source/doc/sphinxext/prs/12550.json new file mode 100644 index 0000000000000000000000000000000000000000..7386a018c6220d3fb9932aedf55a3792541f78f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12550.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dddbe78f0c1a4140e9fd54904593a456b117f56a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12552.json b/mne-python/source/doc/sphinxext/prs/12552.json new file mode 100644 index 0000000000000000000000000000000000000000..67ef8e4883e58f27c4472e673187b7cd0311e53c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12552.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "27c07a8e2c8e2add8c8921c144986a9530455eb1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12554.json b/mne-python/source/doc/sphinxext/prs/12554.json new file mode 100644 index 0000000000000000000000000000000000000000..5e9d9c5aee53bad711a3c1378c6d96d9db86a25b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12554.json @@ -0,0 +1,183 @@ +{ + "merge_commit_sha": "0d781c8329a524c7bd66b27d69348eabb468681d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 5, + "d": 5 + }, + "doc/changes/devel/12554.dependency.rst": { + "a": 6, + "d": 0 + }, + "doc/conf.py": { + "a": 0, + "d": 2 + }, + "mne/_fiff/reference.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 0, + "d": 26 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 2 + }, + "mne/dipole.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 9 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 1, + "d": 58 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 5, + "d": 5 + }, + "mne/io/kit/coreg.py": { + "a": 3, + "d": 17 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 0, + "d": 14 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/xdawn.py": { + "a": 2, + "d": 2 + }, + "mne/report/report.py": { + "a": 6, + "d": 22 + }, + "mne/report/tests/test_report.py": { + "a": 0, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 9 + }, + "mne/time_frequency/multitaper.py": { + "a": 0, + "d": 12 + }, + "mne/time_frequency/spectrum.py": { + "a": 8, + "d": 17 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 0, + "d": 13 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 45 + }, + "mne/utils/__init__.pyi": { + "a": 4, + "d": 0 + }, + "mne/utils/check.py": { + "a": 2, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 4 + }, + "mne/utils/linalg.py": { + "a": 55, + "d": 0 + }, + "mne/utils/spectrum.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_mpl_figure.py": { + "a": 7, + "d": 27 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 6 + }, + "mne/viz/ica.py": { + "a": 13, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 4, + "d": 13 + }, + "mne/viz/utils.py": { + "a": 24, + "d": 66 + }, + "pyproject.toml": { + "a": 3, + "d": 3 + }, + "tools/dev/gen_css_for_mne.py": { + "a": 2, + "d": 1 + }, + "tools/github_actions_env_vars.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12556.json b/mne-python/source/doc/sphinxext/prs/12556.json new file mode 100644 index 0000000000000000000000000000000000000000..c1a5165f1330349682e8fe3701128a2a452924b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12556.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b72f02a5eab8ab931839e4f9bad6d8e8faa68861", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12556.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/html_templates/report/slider.html.jinja": { + "a": 6, + "d": 11 + }, + "mne/report/js_and_css/report.js": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12557.json b/mne-python/source/doc/sphinxext/prs/12557.json new file mode 100644 index 0000000000000000000000000000000000000000..f424f2fc350aceab6929dac2deafa7f650881785 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12557.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "96ac7afc522cd4775113b2327b0be7dc3a483e8f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report/js_and_css/report.js": { + "a": 13, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12560.json b/mne-python/source/doc/sphinxext/prs/12560.json new file mode 100644 index 0000000000000000000000000000000000000000..e553e6a52bf9971cf64481294f180e025133519f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12560.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f093b176565ef934bb5c0bcc6c2a5fc717f5e782", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12561.json b/mne-python/source/doc/sphinxext/prs/12561.json new file mode 100644 index 0000000000000000000000000000000000000000..e999b2f13eae3ef58c05cb2c1e32e9d60e89e7f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12561.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6e2ecad41bad6b19474173e38b6e3df1efd3e863", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12561.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/report/js_and_css/report.js": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12562.json b/mne-python/source/doc/sphinxext/prs/12562.json new file mode 100644 index 0000000000000000000000000000000000000000..6472bfb4c95d96188cfa944bca6167e66c4f2cee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12562.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "815db609f9142b88de54c297f9016abfc38da6c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12562.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 30, + "d": 8 + }, + "mne/decoding/csp.py": { + "a": 28, + "d": 4 + }, + "mne/decoding/tests/test_base.py": { + "a": 15, + "d": 6 + }, + "mne/decoding/tests/test_csp.py": { + "a": 27, + "d": 4 + }, + "mne/decoding/transformer.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12563.json b/mne-python/source/doc/sphinxext/prs/12563.json new file mode 100644 index 0000000000000000000000000000000000000000..6b8800da9577455b940d2adeda8c33ef553d785f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12563.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6fd4674673dafb944fbade0297a8c609d090a59c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report/report.py": { + "a": 0, + "d": 36 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12564.json b/mne-python/source/doc/sphinxext/prs/12564.json new file mode 100644 index 0000000000000000000000000000000000000000..92a305f1353dda228d96df91485d2412c6d03898 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12564.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "52d9a9b5a03503d00439c7ba999799d8dd4ac030", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12565.json b/mne-python/source/doc/sphinxext/prs/12565.json new file mode 100644 index 0000000000000000000000000000000000000000..7c66dbdd84c174144011f24017e0f939b99a1303 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12565.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9262ae4858b123b7dcd70d5fad99b3b4aa00d271", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 14, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12567.json b/mne-python/source/doc/sphinxext/prs/12567.json new file mode 100644 index 0000000000000000000000000000000000000000..46f043ca3f65b6ee4bf76ba20f9f8c735309ba55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12567.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "55cba826db9f5b7a9a28c6a12248108fddfadfa2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 5, + "d": 9 + }, + "mne/utils/config.py": { + "a": 25, + "d": 7 + }, + "mne/utils/tests/test_config.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12569.json b/mne-python/source/doc/sphinxext/prs/12569.json new file mode 100644 index 0000000000000000000000000000000000000000..b3254d4fbe1298061b02dd2dd3b269199b8dabd3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12569.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "7d36247e14f1f3ba8a10d4d4e73511e643355cda", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 3, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 11, + "d": 8 + }, + "azure-pipelines.yml": { + "a": 7, + "d": 0 + }, + "doc/changes/devel/12569.other.rst": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_flash_bem.py": { + "a": 1, + "d": 0 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 2, + "d": 56 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 37, + "d": 37 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 8, + "d": 5 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 6 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_utils.py": { + "a": 0, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 1 + }, + "pyproject.toml": { + "a": 14, + "d": 0 + }, + "tools/vulture_allowlist.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12570.json b/mne-python/source/doc/sphinxext/prs/12570.json new file mode 100644 index 0000000000000000000000000000000000000000..0c689b0c28ab6e23fda503eb32b8d20f525d538d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12570.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e43b5d897228df7de41799583df2e38adbcffc6e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 213, + "d": 199 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 2, + "d": 2 + }, + "tutorials/clinical/20_seeg.py": { + "a": 3, + "d": 4 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12571.json b/mne-python/source/doc/sphinxext/prs/12571.json new file mode 100644 index 0000000000000000000000000000000000000000..c0178746b90093e094a2154efcb1333005a70cb8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12571.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e3a40fc1b173cb4b49356864aa3551237c5d0d2d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 8, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12573.json b/mne-python/source/doc/sphinxext/prs/12573.json new file mode 100644 index 0000000000000000000000000000000000000000..125182830be4fe7c792a22c3d166632bf69bf050 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12573.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cfb232a41eb316e2173fb4dba3ab3b23ab326995", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12573.newfeature.rst": { + "a": 3, + "d": 0 + }, + "mne/report/report.py": { + "a": 4, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12574.json b/mne-python/source/doc/sphinxext/prs/12574.json new file mode 100644 index 0000000000000000000000000000000000000000..c77bf1ef4d4fe33f94ee210f489e680a87a221df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12574.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7c0c07a1dfb8229a9fafd81b993b6cc75ce10a27", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/conf.py": { + "a": 15, + "d": 257 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 245, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12575.json b/mne-python/source/doc/sphinxext/prs/12575.json new file mode 100644 index 0000000000000000000000000000000000000000..0b13092d91158657f808953e21ae7d8e72a27e9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12575.json @@ -0,0 +1,263 @@ +{ + "merge_commit_sha": "2db23cd669e2304504df86da53584b7b82036538", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/gen_commands.py": { + "a": 14, + "d": 1 + }, + "mne/_fiff/reference.py": { + "a": 0, + "d": 27 + }, + "mne/_fiff/utils.py": { + "a": 0, + "d": 25 + }, + "mne/_fiff/write.py": { + "a": 2, + "d": 11 + }, + "mne/_freesurfer.py": { + "a": 0, + "d": 17 + }, + "mne/channels/layout.py": { + "a": 0, + "d": 55 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 33 + }, + "mne/chpi.py": { + "a": 0, + "d": 6 + }, + "mne/coreg.py": { + "a": 0, + "d": 28 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 0, + "d": 12 + }, + "mne/filter.py": { + "a": 0, + "d": 24 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg.py": { + "a": 0, + "d": 2 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 0, + "d": 22 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 0, + "d": 3 + }, + "mne/io/bti/bti.py": { + "a": 12, + "d": 93 + }, + "mne/io/bti/read.py": { + "a": 0, + "d": 20 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 0, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 0, + "d": 3 + }, + "mne/io/egi/egimff.py": { + "a": 0, + "d": 19 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 0, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 0 + }, + "mne/io/neuralynx/tests/test_neuralynx.py": { + "a": 1, + "d": 1 + }, + "mne/io/persyst/persyst.py": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 0, + "d": 1 + }, + "mne/misc.py": { + "a": 0, + "d": 16 + }, + "mne/morph.py": { + "a": 11, + "d": 11 + }, + "mne/preprocessing/ecg.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 0, + "d": 6 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 4, + "d": 0 + }, + "mne/report/report.py": { + "a": 1, + "d": 11 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 5, + "d": 7 + }, + "mne/surface.py": { + "a": 0, + "d": 6 + }, + "mne/tests/test_chpi.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 0, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 0, + "d": 2 + }, + "mne/tests/test_line_endings.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 1, + "d": 0 + }, + "mne/transforms.py": { + "a": 0, + "d": 1 + }, + "mne/utils/__init__.pyi": { + "a": 0, + "d": 6 + }, + "mne/utils/_testing.py": { + "a": 0, + "d": 18 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 37 + }, + "mne/utils/numerics.py": { + "a": 0, + "d": 26 + }, + "mne/viz/_brain/_brain.py": { + "a": 0, + "d": 28 + }, + "mne/viz/_brain/surface.py": { + "a": 0, + "d": 9 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 0, + "d": 7 + }, + "mne/viz/backends/renderer.py": { + "a": 0, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 0, + "d": 6 + }, + "mne/viz/tests/test_montage.py": { + "a": 0, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 6 + }, + "pyproject.toml": { + "a": 10, + "d": 3 + }, + "tools/vulture_allowlist.py": { + "a": 119, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12576.json b/mne-python/source/doc/sphinxext/prs/12576.json new file mode 100644 index 0000000000000000000000000000000000000000..3b5212bda49719d2032c7e45de29d1303105b6f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12576.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "2448974c87828a4f4c2aac0e7c51376556e257b7", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12576.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_freesurfer.py": { + "a": 11, + "d": 7 + }, + "mne/surface.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_surface.py": { + "a": 0, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12578.json b/mne-python/source/doc/sphinxext/prs/12578.json new file mode 100644 index 0000000000000000000000000000000000000000..b6a4b88b25348aecf4f366dc7b350c35c5653c8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12578.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "59606aa0e3d43d7313a644d7c6be3e4ec863a1ea", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12578.bugfix.rst": { + "a": 3, + "d": 0 + }, + "mne/report/report.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12579.json b/mne-python/source/doc/sphinxext/prs/12579.json new file mode 100644 index 0000000000000000000000000000000000000000..c93064ff7b08e6287c3b6992c499f88d2a097e2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12579.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d99d498257eb06c479500a88cf6abf28e9d943bf", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/html_templates/report/slider.html.jinja": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1258.json b/mne-python/source/doc/sphinxext/prs/1258.json new file mode 100644 index 0000000000000000000000000000000000000000..f7bfbc41d57cd0096a13a95a8003b1292c654bcb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1258.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "88e84cdbe1d63b91799ec07cb4a1ccd5e83cae9c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_single_trial_spectra.py": { + "a": 12, + "d": 0 + }, + "mne/fiff/evoked.py": { + "a": 25, + "d": 12 + }, + "mne/tests/test_viz.py": { + "a": 3, + "d": 2 + }, + "mne/viz.py": { + "a": 61, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12580.json b/mne-python/source/doc/sphinxext/prs/12580.json new file mode 100644 index 0000000000000000000000000000000000000000..d20288748e4ffa4f4d66e5105ad0a4e8023d5c21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12580.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5a5b4f10467664b1444873ab879f4ae5724eedbb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "pyproject.toml": { + "a": 2, + "d": 2 + }, + "tools/pyqt6_requirements.txt": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12583.json b/mne-python/source/doc/sphinxext/prs/12583.json new file mode 100644 index 0000000000000000000000000000000000000000..24b472f36cf86d29b690b9eba6c2f8ae78aeb9a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12583.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "c55c44af394b611abcb4eb8553935d0b582f6e49", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12583.apichange.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/devel/12583.newfeature.rst": { + "a": 4, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 8, + "d": 74 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 7, + "d": 8 + }, + "mne/epochs.py": { + "a": 10, + "d": 7 + }, + "mne/evoked.py": { + "a": 9, + "d": 7 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 8 + }, + "mne/html_templates/_templates.py": { + "a": 118, + "d": 0 + }, + "mne/html_templates/repr/_acquisition.html.jinja": { + "a": 100, + "d": 0 + }, + "mne/html_templates/repr/_channels.html.jinja": { + "a": 51, + "d": 0 + }, + "mne/html_templates/repr/_filters.html.jinja": { + "a": 48, + "d": 0 + }, + "mne/html_templates/repr/_general.html.jinja": { + "a": 68, + "d": 0 + }, + "mne/html_templates/repr/_js_and_css.html.jinja": { + "a": 7, + "d": 0 + }, + "mne/html_templates/repr/epochs.html.jinja": { + "a": 10, + "d": 22 + }, + "mne/html_templates/repr/evoked.html.jinja": { + "a": 10, + "d": 30 + }, + "mne/html_templates/repr/forward.html.jinja": { + "a": 25, + "d": 8 + }, + "mne/html_templates/repr/info.html.jinja": { + "a": 10, + "d": 101 + }, + "mne/html_templates/repr/raw.html.jinja": { + "a": 10, + "d": 1 + }, + "mne/html_templates/repr/static/repr.css": { + "a": 105, + "d": 0 + }, + "mne/html_templates/repr/static/repr.js": { + "a": 35, + "d": 0 + }, + "mne/io/base.py": { + "a": 8, + "d": 8 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 2, + "d": 3 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_misc.py": { + "a": 3, + "d": 3 + }, + "tutorials/intro/70_report.py": { + "a": 28, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12584.json b/mne-python/source/doc/sphinxext/prs/12584.json new file mode 100644 index 0000000000000000000000000000000000000000..a2e4d0c75cae96526aeaa63c2a5ba91e2b7d7e96 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12584.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "47d26ec99ac4b65deeac5c561860bb9ed7473878", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12584.newfeature.rst": { + "a": 4, + "d": 0 + }, + "mne/report/report.py": { + "a": 16, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12585.json b/mne-python/source/doc/sphinxext/prs/12585.json new file mode 100644 index 0000000000000000000000000000000000000000..febd23e9db32ff45c1a787858f692b0f26b72055 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12585.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0b190849bac458e3dcbedb3b49f8e9891ded77ba", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/persyst/persyst.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12586.json b/mne-python/source/doc/sphinxext/prs/12586.json new file mode 100644 index 0000000000000000000000000000000000000000..9c63c4f02ed4e62b637ea7d9f8871e70ff8b198e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12586.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "43414ba878ee7746464a8fd5aa7f4a555ea0bd5e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".git_archival.txt": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12587.json b/mne-python/source/doc/sphinxext/prs/12587.json new file mode 100644 index 0000000000000000000000000000000000000000..c7e1fa3e46758b43b55508425e53a502043dbb42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12587.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8903b4a1a2a3f2a6c73e2e5793f8e793151de633", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/spectrum.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12588.json b/mne-python/source/doc/sphinxext/prs/12588.json new file mode 100644 index 0000000000000000000000000000000000000000..57cff37e14de2b4a6945fdfd8a2cfaf9f0a5401e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12588.json @@ -0,0 +1,939 @@ +{ + "merge_commit_sha": "e39995d9be6fc831c7a4a59f09b7a7c0a41ae315", + "authors": [ + { + "n": null, + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/flow_diagram.py": { + "a": 5, + "d": 5 + }, + "doc/sphinxext/gen_commands.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 1, + "d": 1 + }, + "examples/forward/forward_sensitivity_maps.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/label_activation_from_stc.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/label_from_stc.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/label_source_activations.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/psf_ctf_vertices_lcmv.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/read_inverse.py": { + "a": 8, + "d": 8 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 1, + "d": 1 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 3, + "d": 8 + }, + "examples/time_frequency/source_space_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/_digitization.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/compensator.py": { + "a": 6, + "d": 10 + }, + "mne/_fiff/ctf_comp.py": { + "a": 3, + "d": 3 + }, + "mne/_fiff/matrix.py": { + "a": 4, + "d": 4 + }, + "mne/_fiff/meas_info.py": { + "a": 25, + "d": 40 + }, + "mne/_fiff/open.py": { + "a": 4, + "d": 3 + }, + "mne/_fiff/pick.py": { + "a": 9, + "d": 9 + }, + "mne/_fiff/proc_history.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/proj.py": { + "a": 18, + "d": 23 + }, + "mne/_fiff/reference.py": { + "a": 11, + "d": 13 + }, + "mne/_fiff/tests/test_compensator.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_constants.py": { + "a": 5, + "d": 5 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tree.py": { + "a": 3, + "d": 4 + }, + "mne/_fiff/write.py": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 1, + "d": 1 + }, + "mne/_ola.py": { + "a": 11, + "d": 15 + }, + "mne/annotations.py": { + "a": 5, + "d": 8 + }, + "mne/baseline.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 4 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 3, + "d": 5 + }, + "mne/bem.py": { + "a": 57, + "d": 73 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 3, + "d": 3 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 6 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 7, + "d": 7 + }, + "mne/channels/tests/test_montage.py": { + "a": 10, + "d": 10 + }, + "mne/chpi.py": { + "a": 15, + "d": 25 + }, + "mne/commands/mne_anonymize.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 3, + "d": 3 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 14, + "d": 14 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 13, + "d": 13 + }, + "mne/commands/mne_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_flash_bem.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 6, + "d": 6 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_maxfilter.py": { + "a": 0, + "d": 257 + }, + "mne/commands/mne_report.py": { + "a": 6, + "d": 6 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_show_info.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_surf2bem.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 1, + "d": 1 + }, + "mne/commands/utils.py": { + "a": 3, + "d": 3 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 26, + "d": 26 + }, + "mne/cov.py": { + "a": 2, + "d": 4 + }, + "mne/cuda.py": { + "a": 5, + "d": 6 + }, + "mne/datasets/_fetch.py": { + "a": 2, + "d": 4 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/config.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 5, + "d": 9 + }, + "mne/datasets/utils.py": { + "a": 6, + "d": 6 + }, + "mne/decoding/csp.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 12, + "d": 12 + }, + "mne/dipole.py": { + "a": 16, + "d": 18 + }, + "mne/epochs.py": { + "a": 10, + "d": 15 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 5, + "d": 5 + }, + "mne/export/_export.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 9, + "d": 9 + }, + "mne/fixes.py": { + "a": 3, + "d": 3 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_lead_dots.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 13, + "d": 15 + }, + "mne/forward/forward.py": { + "a": 20, + "d": 22 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 3 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 14, + "d": 19 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 3, + "d": 3 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 21, + "d": 23 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 3, + "d": 3 + }, + "mne/io/artemis123/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 11, + "d": 11 + }, + "mne/io/besa/besa.py": { + "a": 2, + "d": 2 + }, + "mne/io/boxy/boxy.py": { + "a": 2, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 7, + "d": 7 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 2, + "d": 3 + }, + "mne/io/bti/bti.py": { + "a": 13, + "d": 15 + }, + "mne/io/bti/read.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/eeg.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/hc.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 10, + "d": 10 + }, + "mne/io/ctf/res4.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/trans.py": { + "a": 4, + "d": 4 + }, + "mne/io/curry/curry.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 3 + }, + "mne/io/eeglab/eeglab.py": { + "a": 7, + "d": 7 + }, + "mne/io/egi/egi.py": { + "a": 8, + "d": 10 + }, + "mne/io/egi/egimff.py": { + "a": 7, + "d": 7 + }, + "mne/io/egi/general.py": { + "a": 2, + "d": 2 + }, + "mne/io/eximia/eximia.py": { + "a": 1, + "d": 1 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 2, + "d": 2 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 2, + "d": 2 + }, + "mne/io/fieldtrip/utils.py": { + "a": 3, + "d": 3 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/hitachi/hitachi.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 9, + "d": 9 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/nihon/nihon.py": { + "a": 4, + "d": 4 + }, + "mne/io/nirx/nirx.py": { + "a": 3, + "d": 3 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/persyst.py": { + "a": 6, + "d": 6 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 16, + "d": 16 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 13, + "d": 13 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 7, + "d": 9 + }, + "mne/morph_map.py": { + "a": 3, + "d": 3 + }, + "mne/parallel.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_csd.py": { + "a": 5, + "d": 7 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/bads.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 15, + "d": 17 + }, + "mne/preprocessing/infomax_.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 23, + "d": 29 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_annotate_amplitude.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 2, + "d": 4 + }, + "mne/proj.py": { + "a": 2, + "d": 2 + }, + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 6, + "d": 10 + }, + "mne/simulation/metrics/metrics.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 5, + "d": 5 + }, + "mne/simulation/source.py": { + "a": 5, + "d": 5 + }, + "mne/simulation/tests/test_source.py": { + "a": 2, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 16, + "d": 18 + }, + "mne/source_space/_source_space.py": { + "a": 34, + "d": 34 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 2 + }, + "mne/stats/regression.py": { + "a": 3, + "d": 3 + }, + "mne/surface.py": { + "a": 15, + "d": 22 + }, + "mne/tests/test_annotations.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_bem.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_coreg.py": { + "a": 3, + "d": 5 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_event.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_line_endings.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stft.py": { + "a": 1, + "d": 3 + }, + "mne/time_frequency/csd.py": { + "a": 7, + "d": 7 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 12, + "d": 18 + }, + "mne/transforms.py": { + "a": 5, + "d": 5 + }, + "mne/utils/_bunch.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 7, + "d": 11 + }, + "mne/utils/config.py": { + "a": 9, + "d": 11 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 4 + }, + "mne/utils/misc.py": { + "a": 3, + "d": 3 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 10, + "d": 12 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 10 + }, + "mne/viz/_brain/_brain.py": { + "a": 7, + "d": 7 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 12, + "d": 19 + }, + "mne/viz/evoked_field.py": { + "a": 3, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 5, + "d": 5 + }, + "mne/viz/misc.py": { + "a": 21, + "d": 23 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 7, + "d": 9 + }, + "mne/viz/topomap.py": { + "a": 10, + "d": 15 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 4, + "d": 4 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 3, + "d": 3 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12592.json b/mne-python/source/doc/sphinxext/prs/12592.json new file mode 100644 index 0000000000000000000000000000000000000000..8bcc4f75bbba2a0a419abc1addce655745491d31 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12592.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7fd22d63e8e478db23e9f114abc9b1b5228ed822", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/autofix.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12593.json b/mne-python/source/doc/sphinxext/prs/12593.json new file mode 100644 index 0000000000000000000000000000000000000000..cc17927eacf34a8cec59059eb8c8ea5c5a8ba290 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12593.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "356e8546890b8f798a14777991ba7de6cd9ab9bb", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/12593.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 77, + "d": 23 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 23, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12595.json b/mne-python/source/doc/sphinxext/prs/12595.json new file mode 100644 index 0000000000000000000000000000000000000000..d6e779f92994cb583c4e3412f7df01f339c6e629 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12595.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "e28cba92d80d64ae6bceae0eac4447ea01b74144", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/funding/cds-dark.svg": { + "a": 26, + "d": 0 + }, + "doc/_static/funding/cds.png": { + "a": 0, + "d": 0 + }, + "doc/_static/funding/cds.svg": { + "a": 27, + "d": 0 + }, + "doc/_static/style.css": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 13, + "d": 2 + }, + "doc/funding.rst": { + "a": 5, + "d": 2 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12597.json b/mne-python/source/doc/sphinxext/prs/12597.json new file mode 100644 index 0000000000000000000000000000000000000000..760197f8ed5b2bbfa2c9ef00d95b3ecbebe89709 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12597.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "79d54dca56e4cb8c1ed6c0eec76ee4a5f66739ce", + "authors": [ + { + "n": "George O'Neill", + "e": null + } + ], + "changes": { + "doc/changes/devel/12597.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/fil/fil.py": { + "a": 1, + "d": 3 + }, + "mne/io/fil/tests/test_fil.py": { + "a": 32, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12598.json b/mne-python/source/doc/sphinxext/prs/12598.json new file mode 100644 index 0000000000000000000000000000000000000000..5057877a0e36ef5a45fad6bdea9d86c056d83cdc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12598.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "537faea66da9a0f2bb4b09efe39b90627c941d68", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/filter.py": { + "a": 9, + "d": 1 + }, + "mne/time_frequency/spectrum.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12600.json b/mne-python/source/doc/sphinxext/prs/12600.json new file mode 100644 index 0000000000000000000000000000000000000000..ba3b97ecd164b77564660445fbf4f07c058cb4e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12600.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7a4706b078b2cd0b9ccf4b3c6be83039ddc88617", + "authors": [ + { + "n": "Michal Žák", + "e": null + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/bug_report.yml": { + "a": 2, + "d": 2 + }, + "doc/changes/devel/12600.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12601.json b/mne-python/source/doc/sphinxext/prs/12601.json new file mode 100644 index 0000000000000000000000000000000000000000..dbfdfdffa02755653cacb5a3bb031cba3e156808 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12601.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "01a60d97a8cee2864dd81ac9c25d6ba126a4af2d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 12, + "d": 18 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 4 + }, + "pyproject.toml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12602.json b/mne-python/source/doc/sphinxext/prs/12602.json new file mode 100644 index 0000000000000000000000000000000000000000..11660f49cedffe23008772385bd97af1868c09f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12602.json @@ -0,0 +1,299 @@ +{ + "merge_commit_sha": "5b1c49e18a3a937c884cac529eebcc35a3e9ef04", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + ".github/actions/rename_towncrier/rename_towncrier.py": { + "a": 9, + "d": 11 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/meas_info.py": { + "a": 2, + "d": 4 + }, + "mne/_fiff/proj.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tests/test_constants.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/write.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 3, + "d": 3 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 4 + }, + "mne/decoding/transformer.py": { + "a": 4, + "d": 4 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/export/_egimff.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 3 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/io/besa/besa.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 3 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/persyst/persyst.py": { + "a": 2, + "d": 2 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/morph_map.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_csd.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ieeg/_volume.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/realign.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 8, + "d": 14 + }, + "mne/report/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/metrics/metrics.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/source_space/_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 3, + "d": 5 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_filter.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + }, + "mne/transforms.py": { + "a": 3, + "d": 3 + }, + "mne/utils/check.py": { + "a": 4, + "d": 4 + }, + "mne/utils/config.py": { + "a": 2, + "d": 2 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_logging.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_figure.py": { + "a": 2, + "d": 4 + }, + "mne/viz/circle.py": { + "a": 2, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 3 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12603.json b/mne-python/source/doc/sphinxext/prs/12603.json new file mode 100644 index 0000000000000000000000000000000000000000..579738678d5f8f473b7797e36ae59fbaddd05818 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12603.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1c5b39ff1d99bbcb2fc0e0071a989b3f3845ff30", + "authors": [ + { + "n": "Dimitri Papadopoulos Orfanos", + "e": null + } + ], + "changes": { + "tools/dev/ensure_headers.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12604.json b/mne-python/source/doc/sphinxext/prs/12604.json new file mode 100644 index 0000000000000000000000000000000000000000..69cb0508b244993b4d3b3a483c7fedad11224845 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12604.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "44c69f5a5990ecb57f0f6590b37986a81f2bd325", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12605.json b/mne-python/source/doc/sphinxext/prs/12605.json new file mode 100644 index 0000000000000000000000000000000000000000..e6d4ee4bf4ce1c6432b7c8437210e8ccd6252ec9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12605.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4cffc343a3cb7c75101a11294c517d845ab423eb", + "authors": [ + { + "n": "Michal Žák", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12605.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/pick.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 21, + "d": 18 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 15 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12609.json b/mne-python/source/doc/sphinxext/prs/12609.json new file mode 100644 index 0000000000000000000000000000000000000000..a4b6200e3d95e4edf383a47d140a4806e814a552 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12609.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "cf0e12d9e329440408b19caef974ab95a1439686", + "authors": [ + { + "n": "Fourcaud-Trocmé", + "e": "celicolimmo@free.fr" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12609.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 20, + "d": 20 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12610.json b/mne-python/source/doc/sphinxext/prs/12610.json new file mode 100644 index 0000000000000000000000000000000000000000..ed11cca70da11b3fd749ddd06c33172828e5aa2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12610.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "6cad308dd83be5054a63ad0748ead08b641d6ac0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".git-blame-ignore-revs": { + "a": 3, + "d": 0 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 3, + "d": 1 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_base.py": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 18, + "d": 6 + }, + "mne/stats/_adjacency.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 10 + }, + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12612.json b/mne-python/source/doc/sphinxext/prs/12612.json new file mode 100644 index 0000000000000000000000000000000000000000..e1d319ab340fe5e509430ccca3767818541111d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12612.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5a20b82e7d8e1ae2976bd41e7a92ba68daca171d", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12612.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12615.json b/mne-python/source/doc/sphinxext/prs/12615.json new file mode 100644 index 0000000000000000000000000000000000000000..31b9ed6151c773839d435988b4ea17aa889c8dfb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12615.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "823e25deb03ee23b2df1fde9c03944c14d25ef94", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 1 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12616.json b/mne-python/source/doc/sphinxext/prs/12616.json new file mode 100644 index 0000000000000000000000000000000000000000..e360da0535d348cd209b6aafebb0922ecf65c196 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12616.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4c9a176de185efd2ca3da466c81bca6094873beb", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/12616.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12617.json b/mne-python/source/doc/sphinxext/prs/12617.json new file mode 100644 index 0000000000000000000000000000000000000000..10e0b66fd8bffbfc8fb836afd1d184714ce615da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12617.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "15fee8910b6b18938464e22caedec238b8f5334d", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12619.json b/mne-python/source/doc/sphinxext/prs/12619.json new file mode 100644 index 0000000000000000000000000000000000000000..d9080f92d8faddf3b89ca3cd85a8655f39bf7a86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12619.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5c2a25567e5e1613c204ad40be58bf483db6a99e", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/source_space_snr.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12620.json b/mne-python/source/doc/sphinxext/prs/12620.json new file mode 100644 index 0000000000000000000000000000000000000000..28dec19f622f107a26fc8fd0daaa70d50e41d3a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12620.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b12396dfe051139682bdf566687b384789c034e7", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12620.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 16, + "d": 8 + }, + "tools/vulture_allowlist.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12622.json b/mne-python/source/doc/sphinxext/prs/12622.json new file mode 100644 index 0000000000000000000000000000000000000000..aa9f77984955d5a85213d5a5eaca7f0682de5f33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12622.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "07aecf85877621a37fd83b69a78d837f81df81e2", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/preprocessing/eyetracking/_pupillometry.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12624.json b/mne-python/source/doc/sphinxext/prs/12624.json new file mode 100644 index 0000000000000000000000000000000000000000..51e97bee2f7ee80079145fa3b4f18916e770652d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12624.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "8f66cbcb28c7f41bf972b22c067d03782b14d107", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/12583.newfeature.rst": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/html_templates/_templates.py": { + "a": 0, + "d": 2 + }, + "mne/html_templates/repr/_channels.html.jinja": { + "a": 2, + "d": 2 + }, + "tools/vulture_allowlist.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12625.json b/mne-python/source/doc/sphinxext/prs/12625.json new file mode 100644 index 0000000000000000000000000000000000000000..cd25c47a972a3cf9ab0ceb5a3ea59d847177c238 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12625.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c600f909571d5e27387dd6f63840019219449aae", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12628.json b/mne-python/source/doc/sphinxext/prs/12628.json new file mode 100644 index 0000000000000000000000000000000000000000..1cd6326bbcddc9c3ddeef23e4240934b909e539e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12628.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7f2c9315dc6f9709f480ac711ebe30368b052c36", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12628.newfeature.rst": { + "a": 4, + "d": 0 + }, + "doc/install/advanced.rst": { + "a": 12, + "d": 0 + }, + "pyproject.toml": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12629.json b/mne-python/source/doc/sphinxext/prs/12629.json new file mode 100644 index 0000000000000000000000000000000000000000..6f8b1da52c026705f51bf8cd975d474454eba302 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12629.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dff97690517ac087d22ef6e42c1a13dbd3f3d9d8", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12631.json b/mne-python/source/doc/sphinxext/prs/12631.json new file mode 100644 index 0000000000000000000000000000000000000000..bb97f0bf42b596b79e0c4a32faee106d8e7fe873 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12631.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5fe73cb91def82968b32fd7d41fd62281c56fbf0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12633.json b/mne-python/source/doc/sphinxext/prs/12633.json new file mode 100644 index 0000000000000000000000000000000000000000..b53f0aa3c68bc1883fac9378823860a2b90f81dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12633.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9a222ba21cb0b3c13e6ca73c11b85c1a16838c71", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/devel/12633.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/csd.py": { + "a": 6, + "d": 3 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12634.json b/mne-python/source/doc/sphinxext/prs/12634.json new file mode 100644 index 0000000000000000000000000000000000000000..b9fa2bdd35e6fa1311cc829a17e7111bd26cf836 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12634.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "704f3e25b8fedbeda0443ff623d2c3bfde210bb1", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/devel/12633.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/csd.py": { + "a": 6, + "d": 3 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12635.json b/mne-python/source/doc/sphinxext/prs/12635.json new file mode 100644 index 0000000000000000000000000000000000000000..d9c99052860ee1f152ed912638d96359a2eff625 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12635.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "07b69b33ffa6cbf7e4117590817e81123b03f17e", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12616.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12637.json b/mne-python/source/doc/sphinxext/prs/12637.json new file mode 100644 index 0000000000000000000000000000000000000000..da70e5622892c9905c2dac3d92b38b4cfb0b0966 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12637.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1d56eb98790be00cb80704c347a22b17631048aa", + "authors": [ + { + "n": "Nabil Alibou", + "e": null + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1264.json b/mne-python/source/doc/sphinxext/prs/1264.json new file mode 100644 index 0000000000000000000000000000000000000000..ee6352f5eb87cd98f70ffcd2d729319a78111ed8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1264.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "675120da19f33cc596a3c7aba75bd4be6992559a", + "authors": [ + { + "n": "marmaduke woodman", + "e": null + } + ], + "changes": { + "mne/filter.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12640.json b/mne-python/source/doc/sphinxext/prs/12640.json new file mode 100644 index 0000000000000000000000000000000000000000..7ebc2748d3d54d67d94ffbc10c33b6dd4bd94057 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12640.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b21960d10118fa567d6f409ce01547ccbc226073", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12645.json b/mne-python/source/doc/sphinxext/prs/12645.json new file mode 100644 index 0000000000000000000000000000000000000000..7ced64ab5826d8d71571079b5cceba55c4563404 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12645.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4ce0eb697ffecf8451bf43f3c67c015750ea9b27", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/check_changelog.yml": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 2 + }, + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12646.json b/mne-python/source/doc/sphinxext/prs/12646.json new file mode 100644 index 0000000000000000000000000000000000000000..7dde635c09b12875f97d3949469e987f150b8f69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12646.json @@ -0,0 +1,155 @@ +{ + "merge_commit_sha": "be5a1158a509bc8e9bb7801ab1690afdfaf4cb81", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12646.bugfix.rst": { + "a": 10, + "d": 0 + }, + "mne/_fiff/proc_history.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tag.py": { + "a": 15, + "d": 22 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 4, + "d": 4 + }, + "mne/_fiff/write.py": { + "a": 3, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 7 + }, + "mne/channels/tests/test_channels.py": { + "a": 3, + "d": 3 + }, + "mne/fixes.py": { + "a": 10, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 8, + "d": 8 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 1, + "d": 0 + }, + "mne/label.py": { + "a": 6, + "d": 6 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 29, + "d": 20 + }, + "mne/morph_map.py": { + "a": 5, + "d": 4 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 14, + "d": 14 + }, + "mne/source_space/_source_space.py": { + "a": 11, + "d": 9 + }, + "mne/stats/_adjacency.py": { + "a": 10, + "d": 9 + }, + "mne/stats/cluster_level.py": { + "a": 9, + "d": 5 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_permutations.py": { + "a": 3, + "d": 2 + }, + "mne/surface.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_label.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_morph.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_morph_map.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 9, + "d": 3 + }, + "mne/utils/tests/test_numerics.py": { + "a": 9, + "d": 9 + }, + "mne/viz/_brain/_brain.py": { + "a": 4, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 6, + "d": 6 + }, + "tools/environment_minimal.yml": { + "a": 15, + "d": 0 + }, + "tools/environment_old.yml": { + "a": 17, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 10, + "d": 9 + }, + "tools/github_actions_env_vars.sh": { + "a": 14, + "d": 16 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12647.json b/mne-python/source/doc/sphinxext/prs/12647.json new file mode 100644 index 0000000000000000000000000000000000000000..04b360c6e4588a61eadabd56209073bc82a491be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12647.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a307bbd5ea99d5ef35a5526ed9816b530b7e04a5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12649.json b/mne-python/source/doc/sphinxext/prs/12649.json new file mode 100644 index 0000000000000000000000000000000000000000..d7dca0c8298503ef4a20256394e8e790c7267121 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12649.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2e065838b82c0c28a39c5186f6ba6f3872a9fff1", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12649.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 28, + "d": 22 + }, + "mne/tests/test_epochs.py": { + "a": 15, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1265.json b/mne-python/source/doc/sphinxext/prs/1265.json new file mode 100644 index 0000000000000000000000000000000000000000..3d7c87ff8bd5bfc61446512942c78d66c08395eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1265.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "15beccae746dd450cc7eefff523a73a66fcff3f7", + "authors": [ + { + "n": "marmaduke woodman", + "e": null + } + ], + "changes": { + "mne/filter.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12650.json b/mne-python/source/doc/sphinxext/prs/12650.json new file mode 100644 index 0000000000000000000000000000000000000000..b44dddabd0bf7cd5e39a9ecd823f1793bb070b53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12650.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6fb9aaef6380033ad2fdeeaf38f0724fdb1aff70", + "authors": [ + { + "n": "Xabier de Zuazo", + "e": "xabier@zuazo.org" + } + ], + "changes": { + "doc/changes/devel/12650.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/help/faq.rst": { + "a": 5, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12651.json b/mne-python/source/doc/sphinxext/prs/12651.json new file mode 100644 index 0000000000000000000000000000000000000000..ce476bae57f2f46bb5f08ac801beb4e307a49d13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12651.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "07f429eeebf51a1a686be2bc25a9f760e9c66520", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/stats/_adjacency.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 9, + "d": 0 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 1, + "d": 0 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12652.json b/mne-python/source/doc/sphinxext/prs/12652.json new file mode 100644 index 0000000000000000000000000000000000000000..59ff3f45254bfd10fb0be142fc8513030675d9c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12652.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "69f7d88f2e44f43fe7be92885e0e533e84320a32", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/12652.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 7, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 52, + "d": 14 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 43, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12655.json b/mne-python/source/doc/sphinxext/prs/12655.json new file mode 100644 index 0000000000000000000000000000000000000000..e5c9c9d068398e825174146efb62093befc40d24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12655.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b1675730ac70d910abe43d042afa26bc653548c9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12655.newfeature.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 15, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 14, + "d": 7 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12656.json b/mne-python/source/doc/sphinxext/prs/12656.json new file mode 100644 index 0000000000000000000000000000000000000000..6755a485d1caca57cbe5aecc863f58784a192f4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12656.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3c6a054093d305a98757a97398e5e34988a3aced", + "authors": [ + { + "n": "Qian Chu", + "e": null + } + ], + "changes": { + "doc/changes/devel/12656.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/export/_brainvision.py": { + "a": 7, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 4, + "d": 1 + }, + "mne/export/_eeglab.py": { + "a": 11, + "d": 5 + }, + "mne/export/_export.py": { + "a": 7, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 82, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12657.json b/mne-python/source/doc/sphinxext/prs/12657.json new file mode 100644 index 0000000000000000000000000000000000000000..4624c2e77122bae1cfee4b6ba99381eb45c7df75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12657.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "382c7bae5297f966c8698d22b66dcca27dd2d563", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12659.json b/mne-python/source/doc/sphinxext/prs/12659.json new file mode 100644 index 0000000000000000000000000000000000000000..0a9ebe097a182de72c0410b79ab83546fc487fc9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12659.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d0eff795ad5d52c72428f61cb39cfb966bd60571", + "authors": [ + { + "n": "Ilian AZZ", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12659.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/install/mne_tools_suite.rst": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12661.json b/mne-python/source/doc/sphinxext/prs/12661.json new file mode 100644 index 0000000000000000000000000000000000000000..c30a8858c6ec7e4d7eab6a3cf0bac251a69807be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12661.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f90dd6eab35819df1da2b3e9aefb7f5d6ed3061c", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/12661.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 17, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12664.json b/mne-python/source/doc/sphinxext/prs/12664.json new file mode 100644 index 0000000000000000000000000000000000000000..b68f8df8eef45542eabb83235bddb9df36a8b85c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12664.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4da96f45ec13cdbbf8f88cd942b76d4a83609bfa", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/devel/12664.other.rst": { + "a": 1, + "d": 0 + }, + "mne/decoding/ssd.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12666.json b/mne-python/source/doc/sphinxext/prs/12666.json new file mode 100644 index 0000000000000000000000000000000000000000..800173e3427d285aafc1e6535324dddfed116773 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12666.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "663d7417fcf498f87c960e656672558f7efed698", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/release.yml": { + "a": 2, + "d": 4 + }, + "CITATION.cff": { + "a": 3, + "d": 3 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "codemeta.json": { + "a": 3, + "d": 3 + }, + "doc/changes/devel/12633.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/v1.7.rst": { + "a": 17, + "d": 0 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 17, + "d": 19 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 3 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/generate_codemeta.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12667.json b/mne-python/source/doc/sphinxext/prs/12667.json new file mode 100644 index 0000000000000000000000000000000000000000..c5f3b8dc5631c2784a3c6fdf6f674fcd5b8cedcb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12667.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1206b996eeff4f4ae359ca1188078f8a16474431", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/check_changelog.yml": { + "a": 1, + "d": 0 + }, + ".github/workflows/release.yml": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12668.json b/mne-python/source/doc/sphinxext/prs/12668.json new file mode 100644 index 0000000000000000000000000000000000000000..2caa63dc9c31f8c976dfada6e054e951c50521fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12668.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c24702cb9feff0ab4a38b9903d4b8e23378c35be", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "CITATION.cff": { + "a": 3, + "d": 3 + }, + "codemeta.json": { + "a": 3, + "d": 3 + }, + "doc/changes/v1.7.rst": { + "a": 17, + "d": 0 + }, + "doc/install/installers.rst": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12669.json b/mne-python/source/doc/sphinxext/prs/12669.json new file mode 100644 index 0000000000000000000000000000000000000000..a8acbd600def2d85caa0af4ad78543ed20d26e6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12669.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "88388994ca489c871ad5fa58adfd8af5e19bbb6c", + "authors": [ + { + "n": "NoahMarkowitz", + "e": null + } + ], + "changes": { + "doc/changes/devel/12669.newfeature.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 8, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12670.json b/mne-python/source/doc/sphinxext/prs/12670.json new file mode 100644 index 0000000000000000000000000000000000000000..4c9bd766a20ccc8aac128714eb2dab3fa6177e9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12670.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1792baef0253e256fec386449783ebd606bc1653", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 4, + "d": 4 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12671.json b/mne-python/source/doc/sphinxext/prs/12671.json new file mode 100644 index 0000000000000000000000000000000000000000..31274fc641c94ce4b5ce0a72628bac25fca8cf75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12671.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "564cc1a2fd0b3263a49660b6cfce04b2186d39dd", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/installers.rst": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12673.json b/mne-python/source/doc/sphinxext/prs/12673.json new file mode 100644 index 0000000000000000000000000000000000000000..83e83663a75b508329240c50139fcb2b803b3060 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12673.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d082461bcb701fd66b186e92535fb5288f047c38", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12674.json b/mne-python/source/doc/sphinxext/prs/12674.json new file mode 100644 index 0000000000000000000000000000000000000000..1174e0d22a87eec4252d7e80b198902b6a93b232 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12674.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3c15798383a132903506c6c101135580265d278f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12675.json b/mne-python/source/doc/sphinxext/prs/12675.json new file mode 100644 index 0000000000000000000000000000000000000000..80faec8bc39a9c1931702e73e38906ce66c43fa6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12675.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2c696d5ca0bc48b44f7916322b0759c760c54f94", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + ".github/release.yaml": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12676.json b/mne-python/source/doc/sphinxext/prs/12676.json new file mode 100644 index 0000000000000000000000000000000000000000..07ed3c37373f71346aeae009c23c55fd93c8d823 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12676.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e8854e1f485de868273c7510dfb646039835da25", + "authors": [ + { + "n": "Qian Chu", + "e": null + } + ], + "changes": { + "doc/changes/devel/12676.bugfix.rst": { + "a": 2, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 8, + "d": 3 + }, + "mne/export/tests/test_export.py": { + "a": 41, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12677.json b/mne-python/source/doc/sphinxext/prs/12677.json new file mode 100644 index 0000000000000000000000000000000000000000..3102dcf692cfee545e2e29475eb8ff7d07f435fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12677.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "df1e76115b70eed9754cd2ac8a29774b8d8f134b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + ".github/dependabot.yml": { + "a": 4, + "d": 0 + }, + ".github/workflows/tests.yml": { + "a": 0, + "d": 1 + }, + "environment.yml": { + "a": 3, + "d": 2 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tools/github_actions_env_vars.sh": { + "a": 3, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 1 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12678.json b/mne-python/source/doc/sphinxext/prs/12678.json new file mode 100644 index 0000000000000000000000000000000000000000..49f68c134859912c6ae473544986c62017449325 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12678.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "caba81b9fb263a409a2c339ba63a148a92415d0d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12679.json b/mne-python/source/doc/sphinxext/prs/12679.json new file mode 100644 index 0000000000000000000000000000000000000000..1973e5c2c0046c1e2aab4b70b4e294635360b044 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12679.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "078ad48bae80534bd7d88926a9a13a4df5d765e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + ".github/dependabot.yml": { + "a": 4, + "d": 0 + }, + ".github/workflows/tests.yml": { + "a": 0, + "d": 1 + }, + "environment.yml": { + "a": 3, + "d": 2 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tools/github_actions_env_vars.sh": { + "a": 1, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 1 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12680.json b/mne-python/source/doc/sphinxext/prs/12680.json new file mode 100644 index 0000000000000000000000000000000000000000..87a7cdc0afbaac814d7774ed39f29da383cffe8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12680.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9cc9fb1c1a2223e0ab349aae34c678b8b09ec9c2", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12681.json b/mne-python/source/doc/sphinxext/prs/12681.json new file mode 100644 index 0000000000000000000000000000000000000000..425933c29313f10719b8101825ecf850ffb9727b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12681.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "141162a48ad34fecad6ee339022ac0566c8e5d8c", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/dependabot.yml": { + "a": 2, + "d": 0 + }, + ".github/workflows/autofix.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12682.json b/mne-python/source/doc/sphinxext/prs/12682.json new file mode 100644 index 0000000000000000000000000000000000000000..152b99929768d15a0a5a5380a272c8bc6c220548 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12682.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "96679b70ce34b970f5225131e2b609ad59a599f2", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12686.json b/mne-python/source/doc/sphinxext/prs/12686.json new file mode 100644 index 0000000000000000000000000000000000000000..4f509532cd9f2873e1fe0907db7eaa2cf3458300 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12686.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "bbc2a8243c1060112f2870570c5eb4719459cce9", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12686.newfeature.rst": { + "a": 2, + "d": 0 + }, + "mne/html_templates/_templates.py": { + "a": 11, + "d": 0 + }, + "mne/html_templates/repr/_acquisition.html.jinja": { + "a": 9, + "d": 2 + }, + "mne/report/tests/test_report.py": { + "a": 3, + "d": 1 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12687.json b/mne-python/source/doc/sphinxext/prs/12687.json new file mode 100644 index 0000000000000000000000000000000000000000..120311f59fb137f67146e9576adcab0a0aba45f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12687.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f16ebc51335d0bc9030f38763517e30799bc756a", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12687.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 12, + "d": 2 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12688.json b/mne-python/source/doc/sphinxext/prs/12688.json new file mode 100644 index 0000000000000000000000000000000000000000..f76de999cb1ad2d1d07d6e23a5a25730e349597c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12688.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c9f9bd5e913a1d869a613940067291752e0398d8", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12688.other.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12689.json b/mne-python/source/doc/sphinxext/prs/12689.json new file mode 100644 index 0000000000000000000000000000000000000000..d42fe2fccdad8fa7af755858b51efd15d4a0902a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12689.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b65fce62aa49b7302dab15c20be18698453bb4f5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12691.json b/mne-python/source/doc/sphinxext/prs/12691.json new file mode 100644 index 0000000000000000000000000000000000000000..6f9356dbeedabbdfef23d3e6f9fe12cd3b30f548 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12691.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b87838f8988755b70d9506afc3b5c04fcbf4af3d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 16, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12692.json b/mne-python/source/doc/sphinxext/prs/12692.json new file mode 100644 index 0000000000000000000000000000000000000000..51a4c160fb2cb5f711327e230151abe2e21d96ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12692.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cb3ab67d7cca0b9b1a6c813167cc3305fa559630", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/PULL_REQUEST_TEMPLATE.md": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12694.json b/mne-python/source/doc/sphinxext/prs/12694.json new file mode 100644 index 0000000000000000000000000000000000000000..af14aaf264224b3c3787c21730061ad386e1899f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12694.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "31ef32efb478b6ee32669c5b50196114c13d2443", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12694.bugfix.rst": { + "a": 2, + "d": 0 + }, + "doc/development/governance.rst": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/tests/test_csp.py": { + "a": 24, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12695.json b/mne-python/source/doc/sphinxext/prs/12695.json new file mode 100644 index 0000000000000000000000000000000000000000..9e0bcfd895676b02508b8f852c9b1593d52ec623 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12695.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ac863e63e6233dd3ddb60e1058731f1839e55b02", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12694.bugfix.rst": { + "a": 2, + "d": 0 + }, + "doc/development/governance.rst": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/tests/test_csp.py": { + "a": 24, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12696.json b/mne-python/source/doc/sphinxext/prs/12696.json new file mode 100644 index 0000000000000000000000000000000000000000..f299d2b4601b701cf6476338ce2fcdcfbd028923 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12696.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e01a654ae05f8fcaec5d814a1081256947055205", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12697.json b/mne-python/source/doc/sphinxext/prs/12697.json new file mode 100644 index 0000000000000000000000000000000000000000..9772c0846fabdaae7c3f53f4990d98337568c034 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12697.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4954672afd85a8f01acf2c75f015ecadf0a53c59", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12697.other.rst": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 27, + "d": 37 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12699.json b/mne-python/source/doc/sphinxext/prs/12699.json new file mode 100644 index 0000000000000000000000000000000000000000..be87dab6f353d3c40f7ee397753fb2cdab6df88f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12699.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "aa45f40d969cf2808c3628ed0315fb0f3f31ae35", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12699.apichange.rst": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 30, + "d": 11 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12702.json b/mne-python/source/doc/sphinxext/prs/12702.json new file mode 100644 index 0000000000000000000000000000000000000000..b931637f9c547428c2b5784579c15901768986d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12702.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7af05c63eed37accef26682a9015beadcfabdf4e", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12703.json b/mne-python/source/doc/sphinxext/prs/12703.json new file mode 100644 index 0000000000000000000000000000000000000000..ce92df4fd4b2437d7179993c0da5c89dc9b93e3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12703.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "daca2b7910ae16dece5327e1b75eb60fc5df8406", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12703.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 2 + }, + "mne/viz/montage.py": { + "a": 40, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12706.json b/mne-python/source/doc/sphinxext/prs/12706.json new file mode 100644 index 0000000000000000000000000000000000000000..40a26782e676dcfeba68cfe734552dbd7552e669 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12706.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e5584427e6cc1bbcaf0c6dc114aeec6f716f97ae", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 5, + "d": 1 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12707.json b/mne-python/source/doc/sphinxext/prs/12707.json new file mode 100644 index 0000000000000000000000000000000000000000..c2ee5a58263f5787e4fec348202796465e6eeaa4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12707.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "26e5057adc81313bdb3084e3119bd334d7dc06bc", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/api/statistics.rst": { + "a": 7, + "d": 0 + }, + "doc/changes/devel/12707.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 11, + "d": 0 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "mne/stats/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/stats/erp.py": { + "a": 80, + "d": 0 + }, + "mne/stats/tests/test_erp.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12708.json b/mne-python/source/doc/sphinxext/prs/12708.json new file mode 100644 index 0000000000000000000000000000000000000000..389531a2f781d7c50d752e820e19da32784b174b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12708.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "2efa15cee622c4644e4d09ef5dc8d92c88c17de9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 5, + "d": 5 + }, + "doc/conf.py": { + "a": 5, + "d": 8 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 15, + "d": 4 + }, + "mne/report/report.py": { + "a": 11, + "d": 15 + }, + "mne/report/tests/test_report.py": { + "a": 13, + "d": 10 + }, + "tools/circleci_bash_env.sh": { + "a": 2, + "d": 3 + }, + "tools/circleci_download.sh": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12712.json b/mne-python/source/doc/sphinxext/prs/12712.json new file mode 100644 index 0000000000000000000000000000000000000000..8d85ee60df751dd88d504f921234f32c927b8509 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12712.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1a341b1ba937228370cb4ce915f17affcec53251", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/stats/erp.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12713.json b/mne-python/source/doc/sphinxext/prs/12713.json new file mode 100644 index 0000000000000000000000000000000000000000..8ace37b98ba198932da2dad6dbe91c6ff63136a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12713.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "95783f8fd0f3c2dead77b3d3efcc6707d9445a66", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "LICENSE.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12716.json b/mne-python/source/doc/sphinxext/prs/12716.json new file mode 100644 index 0000000000000000000000000000000000000000..b6914b0c6561df56ebbaa7cfe1a439947606f176 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12716.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "071a98fae28bd7c32c6ce357076263ef01031994", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/installers.rst": { + "a": 2, + "d": 22 + }, + "doc/install/manual_install.rst": { + "a": 31, + "d": 31 + }, + "mne/preprocessing/ecg.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 5, + "d": 0 + }, + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12718.json b/mne-python/source/doc/sphinxext/prs/12718.json new file mode 100644 index 0000000000000000000000000000000000000000..e6644e19e73a0cf78d3a2c793b343e5a3a78dc5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12718.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c9adde80da913eecbc455a35f48332894241ac51", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + }, + "mne/utils/progressbar.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12719.json b/mne-python/source/doc/sphinxext/prs/12719.json new file mode 100644 index 0000000000000000000000000000000000000000..1cd3cce003ddbde6d12c9a93e0fe4f89a78e3114 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12719.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3fff7d99287809a5ed086ffd58029b2b4e2228c2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12719.apichange.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12720.json b/mne-python/source/doc/sphinxext/prs/12720.json new file mode 100644 index 0000000000000000000000000000000000000000..96653fc464b4c9f5d2e98c86b661d48a4dbc53f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12720.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "e299f1efb180968aaf2bb10c1807b8a988124ffa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12720.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12720.newfeature.rst": { + "a": 2, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 34, + "d": 14 + }, + "mne/_fiff/tag.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 11, + "d": 4 + }, + "mne/_fiff/write.py": { + "a": 4, + "d": 3 + }, + "mne/export/_edf.py": { + "a": 0, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 5, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 15, + "d": 14 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 4, + "d": 5 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 1 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 4, + "d": 4 + }, + "mne/utils/__init__.pyi": { + "a": 4, + "d": 8 + }, + "mne/utils/numerics.py": { + "a": 12, + "d": 53 + }, + "mne/utils/tests/test_numerics.py": { + "a": 6, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12721.json b/mne-python/source/doc/sphinxext/prs/12721.json new file mode 100644 index 0000000000000000000000000000000000000000..64bf81a8d6a31cbbe7f22db17530dda87609fe87 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12721.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6ad28a461fe29d96e5d822e2de6c4c9d1b7c2537", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12721.bugfix.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 9, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 9, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 37, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12722.json b/mne-python/source/doc/sphinxext/prs/12722.json new file mode 100644 index 0000000000000000000000000000000000000000..3b29634e22c1b6b0ca0d394f299f27bbc1cec64a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12722.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "88c0374a1f2751128ba57a439730979b8d01b472", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "examples/visualization/evoked_topomap.py": { + "a": 1, + "d": 0 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12724.json b/mne-python/source/doc/sphinxext/prs/12724.json new file mode 100644 index 0000000000000000000000000000000000000000..cad123ff6af11ed9243a66c588010d5c333c0e24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12724.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f20348ef207e41b24a0a0a3dcfc55fa470ec971c", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12724.bugfix.rst": { + "a": 1, + "d": 0 + }, + "examples/io/elekta_epochs.py": { + "a": 0, + "d": 3 + }, + "examples/visualization/topo_compare_conditions.py": { + "a": 5, + "d": 5 + }, + "mne/viz/topo.py": { + "a": 11, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12725.json b/mne-python/source/doc/sphinxext/prs/12725.json new file mode 100644 index 0000000000000000000000000000000000000000..ba66d5a877dc32f34e996a9d56757942b665cc2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12725.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "0c369e0eaa1327e612137ba0e4a54ad776ea6e48", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12725.newfeature.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 34, + "d": 30 + }, + "mne/viz/tests/test_evoked.py": { + "a": 6, + "d": 5 + }, + "tutorials/evoked/40_whitened.py": { + "a": 1, + "d": 2 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12726.json b/mne-python/source/doc/sphinxext/prs/12726.json new file mode 100644 index 0000000000000000000000000000000000000000..25905cf5f87793484a1b3ea297ce61de0a7f3f30 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12726.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "56fa09a20182c8a8f788ded77a4c7b4ad03ba82c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/_css.py": { + "a": 14, + "d": 10 + }, + "mne/preprocessing/tests/test_css.py": { + "a": 10, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12727.json b/mne-python/source/doc/sphinxext/prs/12727.json new file mode 100644 index 0000000000000000000000000000000000000000..859b6ee7eb6c0acf519ead6ffeaabd7f4af2ca2d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12727.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "018e9dcf07c3e53b964b8e91322b6795ce96fa52", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12727.bugfix.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/devel/12727.newfeature.rst": { + "a": 3, + "d": 0 + }, + "examples/inverse/gamma_map_inverse.py": { + "a": 0, + "d": 2 + }, + "mne/cov.py": { + "a": 10, + "d": 1 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 5, + "d": 0 + }, + "mne/rank.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 37, + "d": 3 + }, + "mne/tests/test_rank.py": { + "a": 7, + "d": 3 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12729.json b/mne-python/source/doc/sphinxext/prs/12729.json new file mode 100644 index 0000000000000000000000000000000000000000..7e40a52bfe765276da4f5fc9187a252dbe846e62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12729.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f0e50d70aa89b1179b71b2b3efe323aaeed757c1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1273.json b/mne-python/source/doc/sphinxext/prs/1273.json new file mode 100644 index 0000000000000000000000000000000000000000..e941911f83f6d1302101e6ffe7eaa7a1fbeecc00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1273.json @@ -0,0 +1,1219 @@ +{ + "merge_commit_sha": "e4528f0d3f6062fd01f54a78790fb0f65cecc1e7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 8, + "d": 6 + }, + "doc/source/python_reference.rst": { + "a": 25, + "d": 54 + }, + "doc/source/python_tutorial.rst": { + "a": 7, + "d": 7 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 1 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 4, + "d": 4 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 3, + "d": 3 + }, + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 3, + "d": 3 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 3, + "d": 3 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 3, + "d": 3 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 3, + "d": 3 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 3, + "d": 3 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 4, + "d": 4 + }, + "examples/decoding/plot_decoding_sensors.py": { + "a": 5, + "d": 5 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 4, + "d": 4 + }, + "examples/decoding/plot_decoding_time_generalization.py": { + "a": 5, + "d": 7 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 4, + "d": 4 + }, + "examples/export/plot_epochs_as_data_frame.py": { + "a": 3, + "d": 3 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 4, + "d": 4 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 3, + "d": 2 + }, + "examples/export/plot_raw_to_nitime.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 5, + "d": 5 + }, + "examples/plot_channel_epochs_image.py": { + "a": 4, + "d": 4 + }, + "examples/plot_define_target_events.py": { + "a": 4, + "d": 4 + }, + "examples/plot_estimate_covariance_matrix_baseline.py": { + "a": 5, + "d": 5 + }, + "examples/plot_estimate_covariance_matrix_raw.py": { + "a": 4, + "d": 4 + }, + "examples/plot_evoked_delayed_ssp.py": { + "a": 4, + "d": 4 + }, + "examples/plot_evoked_topomap.py": { + "a": 1, + "d": 1 + }, + "examples/plot_evoked_topomap_delayed_ssp.py": { + "a": 4, + "d": 4 + }, + "examples/plot_evoked_whitening.py": { + "a": 2, + "d": 2 + }, + "examples/plot_extract_events_from_raw.py": { + "a": 1, + "d": 1 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 4, + "d": 4 + }, + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 5, + "d": 5 + }, + "examples/plot_meg_eeg_fields_3d.py": { + "a": 1, + "d": 1 + }, + "examples/plot_megsim_data.py": { + "a": 3, + "d": 3 + }, + "examples/plot_megsim_data_single_trial.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_and_write_raw_data.py": { + "a": 4, + "d": 4 + }, + "examples/plot_read_epochs.py": { + "a": 4, + "d": 4 + }, + "examples/plot_read_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/plot_shift_evoked.py": { + "a": 5, + "d": 4 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 3, + "d": 3 + }, + "examples/plot_ssp_projs_topomaps.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topo_channel_epochs_image.py": { + "a": 4, + "d": 4 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 3, + "d": 3 + }, + "examples/plot_topo_customized.py": { + "a": 3, + "d": 4 + }, + "examples/plot_topography.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 4, + "d": 4 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 3, + "d": 3 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 5, + "d": 5 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 3, + "d": 3 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 3, + "d": 3 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 3, + "d": 3 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 3, + "d": 3 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 4, + "d": 4 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 4, + "d": 4 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 3, + "d": 3 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 3, + "d": 3 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 4, + "d": 4 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 4, + "d": 4 + }, + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 4, + "d": 4 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 4, + "d": 4 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 4, + "d": 3 + }, + "examples/time_frequency/plot_compute_source_psd_epochs.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_single_trial_spectra.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_tfr_topography.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/plot_time_frequency.py": { + "a": 3, + "d": 3 + }, + "mne/__init__.py": { + "a": 7, + "d": 3 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 4, + "d": 4 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 5, + "d": 5 + }, + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/constants.py": { + "a": 0, + "d": 0 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 9, + "d": 9 + }, + "mne/decoding/classifier.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_classifier.py": { + "a": 10, + "d": 10 + }, + "mne/decoding/tests/test_csp.py": { + "a": 6, + "d": 6 + }, + "mne/decoding/tests/test_ems.py": { + "a": 4, + "d": 7 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/time_gen.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 14, + "d": 13 + }, + "mne/event.py": { + "a": 6, + "d": 6 + }, + "mne/fiff/__init__.py": { + "a": 65, + "d": 18 + }, + "mne/forward/_compute_forward.py": { + "a": 3, + "d": 3 + }, + "mne/forward/_field_interpolation.py": { + "a": 4, + "d": 4 + }, + "mne/forward/_make_forward.py": { + "a": 5, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 12, + "d": 12 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 3, + "d": 2 + }, + "mne/forward/tests/test_forward.py": { + "a": 4, + "d": 4 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 8, + "d": 8 + }, + "mne/gui/_coreg_gui.py": { + "a": 1, + "d": 2 + }, + "mne/gui/_fiducials_gui.py": { + "a": 2, + "d": 1 + }, + "mne/gui/_file_traits.py": { + "a": 2, + "d": 1 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_marker_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 2, + "d": 2 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 2, + "d": 2 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 33, + "d": 0 + }, + "mne/io/array/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 3, + "d": 3 + }, + "mne/io/base.py": { + "a": 4, + "d": 4 + }, + "mne/io/brainvision/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 3 + }, + "mne/io/brainvision/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test.eeg": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test.vhdr": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test.vmrk": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_bin_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_elp.txt": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 4, + "d": 2 + }, + "mne/io/bti/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/read.py": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/exported4D_linux.fif": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/exported4D_solaris.fif": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/test_config_linux": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/test_config_solaris": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/test_hs_linux": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/test_hs_solaris": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/test_pdf_linux": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/test_pdf_solaris": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 4, + "d": 3 + }, + "mne/io/bti/transforms.py": { + "a": 0, + "d": 0 + }, + "mne/io/channels.py": { + "a": 4, + "d": 4 + }, + "mne/io/compensator.py": { + "a": 1, + "d": 1 + }, + "mne/io/cov.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/diff.py": { + "a": 0, + "d": 0 + }, + "mne/io/edf/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/biosemi.hpts": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test.bdf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test.edf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test_bdf_eeglab.mat": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test_edf_eeglab.mat": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test_eeglab.mat": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 4, + "d": 3 + }, + "mne/io/egi/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/egi/tests/data/test_egi.raw": { + "a": 0, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 4, + "d": 2 + }, + "mne/io/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 4, + "d": 2 + }, + "mne/io/kit/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 0, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 3 + }, + "mne/io/kit/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/sns.txt": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test.sqd": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_Ykgw.mat": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_bin.fif": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_elp.txt": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_hsp.txt": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_mrk.sqd": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_mrk_post.sqd": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_mrk_pre.sqd": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/trans-sample.fif": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 4, + "d": 3 + }, + "mne/io/matrix.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 9, + "d": 10 + }, + "mne/io/open.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 2, + "d": 2 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/fsaverage-fiducials.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/process_raw.sh": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/sample-audvis-raw-trans.txt": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/small-src.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-ave-2.log": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-ave.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-ave.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-ave.log": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-cov.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-cov.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-eve-1.eve": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-eve-1.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-eve-old-style.eve": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-eve.eve": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-eve.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-eve.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-km-cov.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-lh.label": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-mpr-eve.eve": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-nf-ave.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-no-reject.ave": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-rh.label": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test.ave": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test.cov": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_bads.txt": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_chpi_raw_hp.txt": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_chpi_raw_sss.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_ctf_comp_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_ctf_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_empty_room.cov": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_erm-cov.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_ica.lout": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_keepmean.cov": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_proj.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_proj.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_raw-eve.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_raw.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_raw.lout": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_withbads_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_wrong_bads.txt": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_channels.py": { + "a": 4, + "d": 4 + }, + "mne/io/tests/test_compensator.py": { + "a": 3, + "d": 2 + }, + "mne/io/tests/test_evoked.py": { + "a": 3, + "d": 4 + }, + "mne/io/tests/test_meas_info.py": { + "a": 8, + "d": 7 + }, + "mne/io/tests/test_pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/tree.py": { + "a": 6, + "d": 7 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/layouts/layout.py": { + "a": 4, + "d": 3 + }, + "mne/layouts/tests/test_layout.py": { + "a": 8, + "d": 7 + }, + "mne/minimum_norm/inverse.py": { + "a": 9, + "d": 9 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 6, + "d": 6 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/pick.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 12, + "d": 12 + }, + "mne/preprocessing/maxfilter.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ssp.py": { + "a": 8, + "d": 7 + }, + "mne/preprocessing/stim.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 18, + "d": 18 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 2, + "d": 2 + }, + "mne/proj.py": { + "a": 9, + "d": 9 + }, + "mne/realtime/client.py": { + "a": 4, + "d": 4 + }, + "mne/realtime/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 5, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 62, + "d": 7 + }, + "mne/source_space.py": { + "a": 5, + "d": 5 + }, + "mne/surface.py": { + "a": 8, + "d": 8 + }, + "mne/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 21, + "d": 21 + }, + "mne/tests/test_event.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 30, + "d": 25 + }, + "mne/tests/test_viz.py": { + "a": 15, + "d": 15 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 8, + "d": 8 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 5, + "d": 5 + }, + "mne/transforms.py": { + "a": 5, + "d": 8 + }, + "mne/utils.py": { + "a": 11, + "d": 3 + }, + "mne/viz.py": { + "a": 7, + "d": 6 + }, + "setup.py": { + "a": 9, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12730.json b/mne-python/source/doc/sphinxext/prs/12730.json new file mode 100644 index 0000000000000000000000000000000000000000..5310953bf7a16fec2f33977d22e99c9dda89397f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12730.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "43fb9d8c28193ad2c0e11c9282e65338e02f98b7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/devel/12730.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/nirx/_localized_abbr.py": { + "a": 1, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 10, + "d": 8 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12731.json b/mne-python/source/doc/sphinxext/prs/12731.json new file mode 100644 index 0000000000000000000000000000000000000000..adbe5fafa9e03475c87237c1b7e5abc8f893da77 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12731.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "5843aa5c3f416dcc05495e9ddbbbd549596b6680", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".gitignore": { + "a": 5, + "d": 4 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/install/mne_tools_suite.rst": { + "a": 5, + "d": 34 + }, + "doc/sphinxext/related_software.py": { + "a": 235, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 0 + }, + "tools/circleci_bash_env.sh": { + "a": 1, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12732.json b/mne-python/source/doc/sphinxext/prs/12732.json new file mode 100644 index 0000000000000000000000000000000000000000..94a7f290885c57959d3e6af008175533e59f3fb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12732.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3987aa73a67251dc7b49f10f7db56e77040aaef8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12733.json b/mne-python/source/doc/sphinxext/prs/12733.json new file mode 100644 index 0000000000000000000000000000000000000000..3cf2598ea3b62fdff21b1ae034664b62e5c7c3f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12733.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1694d43b4ecfc3e680d4d5921b42ff043ecf78c1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12733.newfeature.rst": { + "a": 3, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12734.json b/mne-python/source/doc/sphinxext/prs/12734.json new file mode 100644 index 0000000000000000000000000000000000000000..6872b920bb86bc543c65ba24e8ba9e0d48a60c5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12734.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5ee0f2fcd42021d29e3cd92279e83b51cd4fc4a7", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12734.newfeature.rst": { + "a": 3, + "d": 0 + }, + "mne/datasets/_fetch.py": { + "a": 3, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 13, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12735.json b/mne-python/source/doc/sphinxext/prs/12735.json new file mode 100644 index 0000000000000000000000000000000000000000..b46ab253b34c54bb9365bbb109c12b2a29c5e0da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12735.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "64f8eaf453b28470af514660ae7a74549b720412", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12735.bugfix.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.pyi": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12736.json b/mne-python/source/doc/sphinxext/prs/12736.json new file mode 100644 index 0000000000000000000000000000000000000000..48385de5556fc077f22c14b328da75f662dcd3b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12736.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f5dcc6c1d70e0099ef20b5fc09ebbfc9e5a65268", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "tutorials/epochs/30_epochs_metadata.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12737.json b/mne-python/source/doc/sphinxext/prs/12737.json new file mode 100644 index 0000000000000000000000000000000000000000..4a017ede19c15e0b02daed4b36e8b5cfa4c8c78d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12737.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b4e43315dcdb12e86c1f11e8111f8e6c0217f147", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/utils/_typing.py": { + "a": 10, + "d": 0 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12738.json b/mne-python/source/doc/sphinxext/prs/12738.json new file mode 100644 index 0000000000000000000000000000000000000000..63dabdaa5db1fa65ea38a7e084f9ea13fd5635e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12738.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "7ecd1416df18645957fd14198635294f824d149f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 3, + "d": 2 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/html_templates/_templates.py": { + "a": 5, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 9, + "d": 7 + }, + "mne/report/report.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 6 + }, + "mne/viz/ui_events.py": { + "a": 8, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12741.json b/mne-python/source/doc/sphinxext/prs/12741.json new file mode 100644 index 0000000000000000000000000000000000000000..a466ef6912eb06e5fdf35f7cd155402a012d2d81 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12741.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bc63345e04c29caeed03c88e8765e6a5e906f90c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12742.json b/mne-python/source/doc/sphinxext/prs/12742.json new file mode 100644 index 0000000000000000000000000000000000000000..c4ef13fac6ca30a2f2865f3aac4042856dc71013 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12742.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "4e2eaf119e9148c2bf6589d995f1807e861a55d9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 2 + }, + "azure-pipelines.yml": { + "a": 12, + "d": 19 + }, + "doc/changes/devel/12742.dependency.rst": { + "a": 2, + "d": 0 + }, + "doc/install/manual_install.rst": { + "a": 1, + "d": 1 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 0, + "d": 4 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 5 + }, + "tools/install_pre_requirements.sh": { + "a": 8, + "d": 7 + }, + "tools/pyqt6_requirements.txt": { + "a": 0, + "d": 2 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/40_mne_fixed_free.py": { + "a": 24, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12743.json b/mne-python/source/doc/sphinxext/prs/12743.json new file mode 100644 index 0000000000000000000000000000000000000000..954e464685d3d9ccdd497c0171d249cba4c7c0fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12743.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a21b6da33b9459f24a2b66ee60fef64df770f270", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12744.json b/mne-python/source/doc/sphinxext/prs/12744.json new file mode 100644 index 0000000000000000000000000000000000000000..524fc64b24ee746da7d6e58a6cd9689a97a7fde3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12744.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "790be2d0f1fc6f32dde6f482ee8ffa91a677dea8", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12747.json b/mne-python/source/doc/sphinxext/prs/12747.json new file mode 100644 index 0000000000000000000000000000000000000000..648e05d3afc5868636c7ff38023da3a29882d8b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12747.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "b08f759efd08fa060e68f0bdee45f45e3fc5347a", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/12747.newfeature.rst": { + "a": 3, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 202, + "d": 70 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 294, + "d": 32 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 4 + }, + "mne/utils/spectrum.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12749.json b/mne-python/source/doc/sphinxext/prs/12749.json new file mode 100644 index 0000000000000000000000000000000000000000..f9d8e227c69bd8f583b4ef13ec9ae0f6f8081946 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12749.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3cc01923a591b933a0d6ecef5a12b8e185495eef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/get_minimal_commands.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12751.json b/mne-python/source/doc/sphinxext/prs/12751.json new file mode 100644 index 0000000000000000000000000000000000000000..5ae4c4a35601cf43e6bf5fceb944d3e3130a951e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12751.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4b538b6d84e5e688f2000f37a83f8861102a97c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_rank.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12752.json b/mne-python/source/doc/sphinxext/prs/12752.json new file mode 100644 index 0000000000000000000000000000000000000000..ddc1cac607f054f0bcb185a1dedffd2e01e399e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12752.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6e4cadf61b748415fd3b8e27e3326520de2cc981", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/report/report.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12754.json b/mne-python/source/doc/sphinxext/prs/12754.json new file mode 100644 index 0000000000000000000000000000000000000000..7fdea9c9741bfd2a61f89cd05536333e485882a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12754.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b6a24509354128baedebb9ad1d1214254bb6cdad", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12754.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 27, + "d": 35 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12757.json b/mne-python/source/doc/sphinxext/prs/12757.json new file mode 100644 index 0000000000000000000000000000000000000000..82da5d95d6098320b42635f6cf93dc4c9a8b04f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12757.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "aa0b303ce87bbd32d3496812f74c4264c5268ba9", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/install/advanced.rst": { + "a": 0, + "d": 1 + }, + "doc/install/check_installation.rst": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/eyetracking/_pupillometry.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12758.json b/mne-python/source/doc/sphinxext/prs/12758.json new file mode 100644 index 0000000000000000000000000000000000000000..05d94c585ebd341a5d8ebcbf18d359704dd7ecf4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12758.json @@ -0,0 +1,363 @@ +{ + "merge_commit_sha": "e06921d11af1251c17807a1e4dca84176ca8679d", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/define_target_events.py": { + "a": 3, + "d": 3 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/_digitization.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/utils.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/write.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 3, + "d": 3 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 5, + "d": 5 + }, + "mne/coreg.py": { + "a": 2, + "d": 6 + }, + "mne/datasets/limo/limo.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ems.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/search_light.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 4, + "d": 4 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 3 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 3 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 5, + "d": 3 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 4, + "d": 6 + }, + "mne/morph.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ctps_.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/xdawn.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/metrics/metrics.py": { + "a": 2, + "d": 4 + }, + "mne/simulation/raw.py": { + "a": 3, + "d": 4 + }, + "mne/source_space/_source_space.py": { + "a": 2, + "d": 2 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 3, + "d": 5 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 1 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_freesurfer.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stft.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/csd.py": { + "a": 3, + "d": 4 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 6, + "d": 13 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 3, + "d": 3 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/linalg.py": { + "a": 4, + "d": 6 + }, + "mne/utils/mixin.py": { + "a": 2, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 4, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 11, + "d": 9 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 8 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 3 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 4, + "d": 4 + }, + "tutorials/forward/30_forward.py": { + "a": 2, + "d": 2 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 6, + "d": 2 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 2, + "d": 2 + }, + "tutorials/simulation/80_dics.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12759.json b/mne-python/source/doc/sphinxext/prs/12759.json new file mode 100644 index 0000000000000000000000000000000000000000..e2c2fa6d839441cdbe78f371ed60024d28382904 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12759.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "dd6e155fb47812139da33bb9226cc0e6e5792427", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Sammi Chekroud", + "e": "sammi.chekroud@psy.ox.ac.uk" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12759.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/eyetracking/_pupillometry.py": { + "a": 7, + "d": 3 + }, + "mne/preprocessing/eyetracking/tests/test_pupillometry.py": { + "a": 15, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12760.json b/mne-python/source/doc/sphinxext/prs/12760.json new file mode 100644 index 0000000000000000000000000000000000000000..03edd63705b9f1031ec25345c4e78622ab66728c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12760.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a362e5ac3b2965d9cf129b9461e2907747618c30", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12760.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 11, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12761.json b/mne-python/source/doc/sphinxext/prs/12761.json new file mode 100644 index 0000000000000000000000000000000000000000..9c1f040e644c616b54fb871d1e49b1dda3e39ef4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12761.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "868746b427f8123dd0e6b4594a2bd18c7fa49331", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12763.json b/mne-python/source/doc/sphinxext/prs/12763.json new file mode 100644 index 0000000000000000000000000000000000000000..c228053e6402a962f0f18ed54f793954c8fdfea6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12763.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c339bccf730eb1220dba70055deb312cd6913d05", + "authors": [ + { + "n": "Farzin Negahbani", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12763.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 6, + "d": 4 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12765.json b/mne-python/source/doc/sphinxext/prs/12765.json new file mode 100644 index 0000000000000000000000000000000000000000..339afc7d1661870ea1c429d475d80ba27d19554e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12765.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "0f6e7d61c3e016385b71e67e98ae8a1d5c5e1c36", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 4, + "d": 4 + }, + ".pre-commit-config.yaml": { + "a": 8, + "d": 0 + }, + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 8, + "d": 324 + }, + "doc/changes/v1.7.rst": { + "a": 4, + "d": 4 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "doc/sphinxext/related_software.py": { + "a": 10, + "d": 1 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 13, + "d": 2 + }, + "mne/io/neuralynx/tests/test_neuralynx.py": { + "a": 2, + "d": 1 + }, + "pyproject.toml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1277.json b/mne-python/source/doc/sphinxext/prs/1277.json new file mode 100644 index 0000000000000000000000000000000000000000..690e031f54c9d0fafa1bade3187aefbfe89cb0e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1277.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "8310aaf28f60946c7232c2001e0eccb71fb22ee6", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 6, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 66, + "d": 0 + }, + "mne/io/array/array.py": { + "a": 8, + "d": 0 + }, + "mne/io/array/tests/test_array.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 43, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12770.json b/mne-python/source/doc/sphinxext/prs/12770.json new file mode 100644 index 0000000000000000000000000000000000000000..52474ac54abe3fbed320c39718268977eda496fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12770.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0b95d2869bad2fa20568b4f8e8483f14a5d74735", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/morph_volume_stc.py": { + "a": 3, + "d": 3 + }, + "tools/circleci_dependencies.sh": { + "a": 7, + "d": 2 + }, + "tools/install_pre_requirements.sh": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12771.json b/mne-python/source/doc/sphinxext/prs/12771.json new file mode 100644 index 0000000000000000000000000000000000000000..afbdc7d6a66db10775e876d3ddb65e65650abee4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12771.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "e42e1d6a5ff1c3c807e3e6ac3f79d63be589a7f2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12771.apichange.rst": { + "a": 4, + "d": 0 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 6, + "d": 8 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 49, + "d": 48 + }, + "mne/datasets/_infant/base.py": { + "a": 6, + "d": 7 + }, + "mne/datasets/_phantom/base.py": { + "a": 5, + "d": 6 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 45, + "d": 39 + }, + "mne/datasets/utils.py": { + "a": 10, + "d": 10 + }, + "mne/utils/config.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 7, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12774.json b/mne-python/source/doc/sphinxext/prs/12774.json new file mode 100644 index 0000000000000000000000000000000000000000..8bc18f8e221ce437788d20c6a42694e92ade6f47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12774.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "879361513bdd1c14ca4e223657517fe85b6085b0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 5 + }, + ".git-blame-ignore-revs": { + "a": 14, + "d": 7 + }, + ".github/workflows/credit.yml": { + "a": 43, + "d": 0 + }, + ".gitignore": { + "a": 1, + "d": 1 + }, + ".mailmap": { + "a": 73, + "d": 34 + }, + ".pre-commit-config.yaml": { + "a": 8, + "d": 5 + }, + "doc/.gitignore": { + "a": 1, + "d": 0 + }, + "doc/Makefile": { + "a": 1, + "d": 4 + }, + "doc/_templates/sidebar-quicklinks.html": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12774.other.rst": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 3, + "d": 0 + }, + "doc/credit.rst": { + "a": 12, + "d": 0 + }, + "doc/sphinxext/prs/12779.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/update_credit_rst.py": { + "a": 425, + "d": 0 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "pyproject.toml": { + "a": 3, + "d": 0 + }, + "tools/check_mne_location.py": { + "a": 1, + "d": 0 + }, + "tools/dev/check_steering_committee.py": { + "a": 3, + "d": 2 + }, + "tools/dev/ensure_headers.py": { + "a": 1, + "d": 0 + }, + "tools/dev/gen_css_for_mne.py": { + "a": 2, + "d": 1 + }, + "tools/dev/generate_pyi_files.py": { + "a": 1, + "d": 0 + }, + "tools/dev/update_credit_json.py": { + "a": 88, + "d": 0 + }, + "tools/generate_codemeta.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12776.json b/mne-python/source/doc/sphinxext/prs/12776.json new file mode 100644 index 0000000000000000000000000000000000000000..5bbb82f7be756f24cd31914c7251e04ab0f1eac5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12776.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4dcd4d16f961d4a614c105f2d28a3fd912a7c1b8", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 15, + "d": 9 + }, + "doc/_templates/copyright.html": { + "a": 1, + "d": 1 + }, + "doc/_templates/sidebar-quicklinks.html": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12777.json b/mne-python/source/doc/sphinxext/prs/12777.json new file mode 100644 index 0000000000000000000000000000000000000000..1eaa8d89c67bda830bbba977afbb75e718613dd2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12777.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "855ca5ea380498df0a3e1740a7b5134625e926e1", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "tools/check_qt_import.sh": { + "a": 4, + "d": 1 + }, + "tools/github_actions_env_vars.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12778.json b/mne-python/source/doc/sphinxext/prs/12778.json new file mode 100644 index 0000000000000000000000000000000000000000..995d907f6aef84cc1c20c97a07507b55292cc33b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12778.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6da505591cd76bc7f6579154475c4abb2a5cbb95", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/contrib_avatars.py": { + "a": 4, + "d": 1 + }, + "doc/sphinxext/gen_commands.py": { + "a": 1, + "d": 14 + }, + "mne/utils/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 13, + "d": 0 + }, + "mne/utils/tests/test_numerics.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12779.json b/mne-python/source/doc/sphinxext/prs/12779.json new file mode 100644 index 0000000000000000000000000000000000000000..584d8132188d8f765386760ee9171bde88b73e8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12779.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b8b168088cb474f27833f5f9db9d60abe00dca83", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/prs/1.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/3732.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1278.json b/mne-python/source/doc/sphinxext/prs/1278.json new file mode 100644 index 0000000000000000000000000000000000000000..4b5948f045d433c06cfb9cad89d6673758bfbc64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1278.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e072dd2b536ba6ec4f49c9c03ad1e59370492673", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/io/evoked.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12781.json b/mne-python/source/doc/sphinxext/prs/12781.json new file mode 100644 index 0000000000000000000000000000000000000000..a2b2151971087bb65d22f22c69b13444e4b3012b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12781.json @@ -0,0 +1,2911 @@ +{ + "merge_commit_sha": "ee64eba6f345e895e3d5e7d2804fa6aa2dac2e6d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/actions/rename_towncrier/rename_towncrier.py": { + "a": 4, + "d": 0 + }, + ".github/workflows/autofix.yml": { + "a": 3, + "d": 2 + }, + ".github/workflows/credit.yml": { + "a": 0, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/12781.other.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 8, + "d": 5 + }, + "doc/conftest.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/contrib_avatars.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/flow_diagram.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/gen_commands.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/gen_names.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/gh_substitutions.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 4, + "d": 0 + }, + "doc/sphinxext/mne_substitutions.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/newcontrib_substitutions.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/related_software.py": { + "a": 4, + "d": 0 + }, + "doc/sphinxext/unit_role.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/update_credit_rst.py": { + "a": 4, + "d": 0 + }, + "examples/datasets/kernel_phantom.py": { + "a": 2, + "d": 0 + }, + "examples/datasets/opm_data.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/custom_inverse_solver.py": { + "a": 2, + "d": 0 + }, + "examples/io/read_neo_format.py": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/contralateral_referencing.py": { + "a": 2, + "d": 0 + }, + "examples/visualization/eyetracking_plot_heatmap.py": { + "a": 2, + "d": 0 + }, + "examples/visualization/mne_helmet.py": { + "a": 2, + "d": 0 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "logo/generate_mne_logos.py": { + "a": 1, + "d": 2 + }, + "mne/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/__main__.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/_fiff/_digitization.py": { + "a": 1, + "d": 6 + }, + "mne/_fiff/compensator.py": { + "a": 2, + "d": 0 + }, + "mne/_fiff/constants.py": { + "a": 1, + "d": 3 + }, + "mne/_fiff/ctf_comp.py": { + "a": 1, + "d": 4 + }, + "mne/_fiff/matrix.py": { + "a": 1, + "d": 3 + }, + "mne/_fiff/meas_info.py": { + "a": 1, + "d": 5 + }, + "mne/_fiff/open.py": { + "a": 1, + "d": 3 + }, + "mne/_fiff/pick.py": { + "a": 1, + "d": 4 + }, + "mne/_fiff/proc_history.py": { + "a": 1, + "d": 2 + }, + "mne/_fiff/proj.py": { + "a": 1, + "d": 5 + }, + "mne/_fiff/reference.py": { + "a": 1, + "d": 4 + }, + "mne/_fiff/tag.py": { + "a": 1, + "d": 3 + }, + "mne/_fiff/tests/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/_fiff/tests/test_compensator.py": { + "a": 1, + "d": 2 + }, + "mne/_fiff/tests/test_constants.py": { + "a": 1, + "d": 2 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 1, + "d": 3 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 2, + "d": 0 + }, + "mne/_fiff/tests/test_proc_history.py": { + "a": 1, + "d": 2 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 1, + "d": 4 + }, + "mne/_fiff/tests/test_show_fiff.py": { + "a": 1, + "d": 2 + }, + "mne/_fiff/tests/test_utils.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tests/test_what.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_write.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tree.py": { + "a": 1, + "d": 3 + }, + "mne/_fiff/utils.py": { + "a": 1, + "d": 9 + }, + "mne/_fiff/what.py": { + "a": 1, + "d": 2 + }, + "mne/_fiff/write.py": { + "a": 1, + "d": 3 + }, + "mne/_freesurfer.py": { + "a": 2, + "d": 3 + }, + "mne/_ola.py": { + "a": 1, + "d": 2 + }, + "mne/annotations.py": { + "a": 1, + "d": 3 + }, + "mne/baseline.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 4 + }, + "mne/beamformer/_dics.py": { + "a": 2, + "d": 5 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 4 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/tests/test_external.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/tests/test_resolution_matrix.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 1, + "d": 5 + }, + "mne/channels/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 1, + "d": 11 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 2, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 10 + }, + "mne/channels/data/neighbors/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 3 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 9 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 11 + }, + "mne/channels/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 3 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 5 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 3 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 1, + "d": 3 + }, + "mne/channels/tests/test_unify_bads.py": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 18, + "d": 18 + }, + "mne/commands/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_anonymize.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 3, + "d": 10 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 2, + "d": 4 + }, + "mne/commands/mne_compare_fiff.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_flash_bem.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 7 + }, + "mne/commands/mne_prepare_bem_model.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_report.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_setup_forward_model.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_show_fiff.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_show_info.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_surf2bem.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_sys_info.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_what.py": { + "a": 1, + "d": 2 + }, + "mne/commands/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 0 + }, + "mne/commands/utils.py": { + "a": 1, + "d": 3 + }, + "mne/conftest.py": { + "a": 1, + "d": 2 + }, + "mne/coreg.py": { + "a": 1, + "d": 2 + }, + "mne/cov.py": { + "a": 1, + "d": 4 + }, + "mne/cuda.py": { + "a": 1, + "d": 2 + }, + "mne/data/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/_fake/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/_fake/_fake.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/_fetch.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/_fsaverage/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/_infant/__init__.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/_infant/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/_phantom/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/_phantom/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/config.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/eegbci/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/eegbci/tests/test_eegbci.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/epilepsy_ecog/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/epilepsy_ecog/_data.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/erp_core/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/erp_core/erp_core.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/eyelink/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/eyelink/eyelink.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/fieldtrip_cmc/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py": { + "a": 2, + "d": 3 + }, + "mne/datasets/fnirs_motor/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/fnirs_motor/fnirs_motor.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/hf_sef/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/kiloword/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/limo/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/limo/limo.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/misc/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/misc/_misc.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/mtrf/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/mtrf/mtrf.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/multimodal/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/opm/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/opm/opm.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/phantom_4dbti/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/phantom_4dbti/phantom_4dbti.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/phantom_kernel/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/phantom_kernel/phantom_kernel.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/phantom_kit/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/phantom_kit/phantom_kit.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/refmeg_noise/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/refmeg_noise/refmeg_noise.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sample/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/sample/sample.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/sleep_physionet/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/somato/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/somato/somato.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/spm_face/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/ssvep/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/ssvep/ssvep.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/testing/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/testing/_testing.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/ucl_opm_auditory/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/ucl_opm_auditory/ucl_opm_auditory.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 8 + }, + "mne/datasets/visual_92_categories/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/visual_92_categories/visual_92_categories.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 5 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 6 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 4 + }, + "mne/decoding/mixin.py": { + "a": 3, + "d": 0 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/search_light.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/ssd.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_base.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 5 + }, + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 2, + "d": 3 + }, + "mne/decoding/time_frequency.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 4 + }, + "mne/defaults.py": { + "a": 1, + "d": 4 + }, + "mne/dipole.py": { + "a": 1, + "d": 3 + }, + "mne/epochs.py": { + "a": 1, + "d": 7 + }, + "mne/event.py": { + "a": 1, + "d": 5 + }, + "mne/evoked.py": { + "a": 1, + "d": 7 + }, + "mne/export/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/export/_brainvision.py": { + "a": 1, + "d": 2 + }, + "mne/export/_edf.py": { + "a": 1, + "d": 2 + }, + "mne/export/_eeglab.py": { + "a": 1, + "d": 2 + }, + "mne/export/_egimff.py": { + "a": 1, + "d": 2 + }, + "mne/export/_export.py": { + "a": 1, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 2, + "d": 0 + }, + "mne/fixes.py": { + "a": 2, + "d": 4 + }, + "mne/forward/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 6 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 3 + }, + "mne/forward/_lead_dots.py": { + "a": 1, + "d": 4 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 5 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 4 + }, + "mne/forward/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 2, + "d": 0 + }, + "mne/forward/tests/test_forward.py": { + "a": 2, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 7, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 2, + "d": 0 + }, + "mne/gui/_gui.py": { + "a": 1, + "d": 2 + }, + "mne/gui/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/gui/tests/test_coreg.py": { + "a": 1, + "d": 2 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 1, + "d": 2 + }, + "mne/html_templates/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/html_templates/_templates.py": { + "a": 1, + "d": 0 + }, + "mne/inverse_sparse/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 2 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 1, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 3 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 3 + }, + "mne/inverse_sparse/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 1, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_debiasing.py": { + "a": 1, + "d": 3 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 3 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 1, + "d": 3 + }, + "mne/io/__init__.py": { + "a": 3, + "d": 3 + }, + "mne/io/_fiff_wrap.py": { + "a": 1, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 1, + "d": 2 + }, + "mne/io/array/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 2 + }, + "mne/io/array/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 2 + }, + "mne/io/artemis123/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 2 + }, + "mne/io/artemis123/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 1, + "d": 2 + }, + "mne/io/artemis123/utils.py": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 1, + "d": 9 + }, + "mne/io/besa/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/besa/besa.py": { + "a": 2, + "d": 0 + }, + "mne/io/besa/tests/test_besa.py": { + "a": 2, + "d": 0 + }, + "mne/io/boxy/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/boxy/boxy.py": { + "a": 1, + "d": 2 + }, + "mne/io/boxy/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/boxy/tests/test_boxy.py": { + "a": 1, + "d": 2 + }, + "mne/io/brainvision/__init__.py": { + "a": 1, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 8 + }, + "mne/io/brainvision/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 2, + "d": 3 + }, + "mne/io/bti/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 9 + }, + "mne/io/bti/constants.py": { + "a": 1, + "d": 2 + }, + "mne/io/bti/read.py": { + "a": 1, + "d": 2 + }, + "mne/io/bti/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 2 + }, + "mne/io/cnt/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/cnt/_utils.py": { + "a": 1, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 2, + "d": 3 + }, + "mne/io/cnt/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 1, + "d": 3 + }, + "mne/io/constants.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/constants.py": { + "a": 1, + "d": 3 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 3 + }, + "mne/io/ctf/eeg.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/hc.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/markers.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/res4.py": { + "a": 1, + "d": 3 + }, + "mne/io/ctf/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/trans.py": { + "a": 1, + "d": 2 + }, + "mne/io/curry/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/curry/curry.py": { + "a": 1, + "d": 4 + }, + "mne/io/curry/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 1, + "d": 3 + }, + "mne/io/edf/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 8 + }, + "mne/io/edf/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 7 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 1, + "d": 3 + }, + "mne/io/eeglab/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/_eeglab.py": { + "a": 2, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 4 + }, + "mne/io/eeglab/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 4 + }, + "mne/io/egi/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 4 + }, + "mne/io/egi/egimff.py": { + "a": 2, + "d": 0 + }, + "mne/io/egi/events.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/general.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 2 + }, + "mne/io/eximia/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/eximia/eximia.py": { + "a": 1, + "d": 3 + }, + "mne/io/eximia/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 1, + "d": 2 + }, + "mne/io/eyelink/__init__.py": { + "a": 1, + "d": 3 + }, + "mne/io/eyelink/_utils.py": { + "a": 2, + "d": 1 + }, + "mne/io/eyelink/eyelink.py": { + "a": 1, + "d": 4 + }, + "mne/io/eyelink/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 2, + "d": 0 + }, + "mne/io/fieldtrip/__init__.py": { + "a": 1, + "d": 4 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 1, + "d": 4 + }, + "mne/io/fieldtrip/tests/__init__.py": { + "a": 1, + "d": 4 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 2, + "d": 4 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 1, + "d": 4 + }, + "mne/io/fieldtrip/utils.py": { + "a": 2, + "d": 4 + }, + "mne/io/fiff/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 6 + }, + "mne/io/fiff/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 3 + }, + "mne/io/fil/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/fil/fil.py": { + "a": 1, + "d": 2 + }, + "mne/io/fil/sensors.py": { + "a": 1, + "d": 2 + }, + "mne/io/fil/tests/test_fil.py": { + "a": 1, + "d": 2 + }, + "mne/io/hitachi/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 2 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 1, + "d": 2 + }, + "mne/io/kit/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 3 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 4 + }, + "mne/io/kit/tests/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 1, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 2 + }, + "mne/io/nedf/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/nedf/nedf.py": { + "a": 2, + "d": 0 + }, + "mne/io/nedf/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/nedf/tests/test_nedf.py": { + "a": 2, + "d": 2 + }, + "mne/io/neuralynx/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 2, + "d": 0 + }, + "mne/io/neuralynx/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/neuralynx/tests/test_neuralynx.py": { + "a": 2, + "d": 0 + }, + "mne/io/nicolet/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 2 + }, + "mne/io/nicolet/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 1, + "d": 2 + }, + "mne/io/nihon/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/nihon/nihon.py": { + "a": 1, + "d": 2 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 1, + "d": 2 + }, + "mne/io/nirx/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/nirx/_localized_abbr.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 2 + }, + "mne/io/nirx/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 1, + "d": 3 + }, + "mne/io/nsx/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/nsx/nsx.py": { + "a": 2, + "d": 2 + }, + "mne/io/nsx/tests/test_nsx.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/persyst/persyst.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 1, + "d": 2 + }, + "mne/io/pick.py": { + "a": 1, + "d": 2 + }, + "mne/io/snirf/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 2 + }, + "mne/io/snirf/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/tests/data/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_apply_function.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 3 + }, + "mne/io/tests/test_read_raw.py": { + "a": 1, + "d": 2 + }, + "mne/label.py": { + "a": 1, + "d": 4 + }, + "mne/minimum_norm/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 1, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 4 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 1, + "d": 4 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 2, + "d": 3 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 1, + "d": 3 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 3 + }, + "mne/misc.py": { + "a": 1, + "d": 3 + }, + "mne/morph.py": { + "a": 1, + "d": 4 + }, + "mne/morph_map.py": { + "a": 1, + "d": 5 + }, + "mne/parallel.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/__init__.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/_annotate_amplitude.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/_annotate_nan.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/_css.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/_lof.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/_regress.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/bads.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ctps_.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/eyetracking/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/eyetracking/_pupillometry.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/eyetracking/calibration.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/eyetracking/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/eyetracking/tests/test_calibration.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/eyetracking/tests/test_eyetracking.py": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/eyetracking/tests/test_pupillometry.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eyetracking/utils.py": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/hfc.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/ieeg/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ieeg/_volume.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ieeg/tests/test_volume.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/interpolate.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 5 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/realign.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/stim.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/tests/test_annotate_amplitude.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_annotate_nan.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_css.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/tests/test_hfc.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_interpolate.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_lof.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_otp.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_peak_finder.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_realign.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 4 + }, + "mne/proj.py": { + "a": 1, + "d": 2 + }, + "mne/rank.py": { + "a": 2, + "d": 2 + }, + "mne/report/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 1, + "d": 4 + }, + "mne/report/tests/test_report.py": { + "a": 1, + "d": 3 + }, + "mne/simulation/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/simulation/_metrics.py": { + "a": 1, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 2, + "d": 4 + }, + "mne/simulation/metrics/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/simulation/metrics/metrics.py": { + "a": 1, + "d": 5 + }, + "mne/simulation/metrics/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/simulation/metrics/tests/test_metrics.py": { + "a": 1, + "d": 3 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 4 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 8 + }, + "mne/simulation/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 2 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 1, + "d": 3 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 4 + }, + "mne/simulation/tests/test_source.py": { + "a": 1, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 5 + }, + "mne/source_space/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/source_space/_source_space.py": { + "a": 1, + "d": 3 + }, + "mne/source_space/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 1, + "d": 3 + }, + "mne/stats/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/stats/_adjacency.py": { + "a": 1, + "d": 3 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 7 + }, + "mne/stats/erp.py": { + "a": 1, + "d": 0 + }, + "mne/stats/multi_comp.py": { + "a": 1, + "d": 5 + }, + "mne/stats/parametric.py": { + "a": 1, + "d": 4 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 2 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 6 + }, + "mne/stats/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/stats/tests/test_adjacency.py": { + "a": 1, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 3 + }, + "mne/stats/tests/test_erp.py": { + "a": 4, + "d": 0 + }, + "mne/stats/tests/test_multi_comp.py": { + "a": 2, + "d": 0 + }, + "mne/stats/tests/test_parametric.py": { + "a": 2, + "d": 0 + }, + "mne/stats/tests/test_permutations.py": { + "a": 1, + "d": 2 + }, + "mne/stats/tests/test_regression.py": { + "a": 1, + "d": 4 + }, + "mne/surface.py": { + "a": 1, + "d": 5 + }, + "mne/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_defaults.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_event.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 5 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_freesurfer.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_line_endings.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_misc.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_morph.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_morph_map.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_ola.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_parallel.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_rank.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_read_vectorview_selection.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/_stft.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 3 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 3 + }, + "mne/time_frequency/spectrum.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 6 + }, + "mne/transforms.py": { + "a": 1, + "d": 3 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/utils/_bunch.py": { + "a": 2, + "d": 4 + }, + "mne/utils/_logging.py": { + "a": 2, + "d": 2 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 2 + }, + "mne/utils/_typing.py": { + "a": 4, + "d": 0 + }, + "mne/utils/check.py": { + "a": 2, + "d": 2 + }, + "mne/utils/config.py": { + "a": 2, + "d": 2 + }, + "mne/utils/dataframe.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + }, + "mne/utils/fetching.py": { + "a": 2, + "d": 2 + }, + "mne/utils/linalg.py": { + "a": 2, + "d": 2 + }, + "mne/utils/misc.py": { + "a": 2, + "d": 2 + }, + "mne/utils/mixin.py": { + "a": 2, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 2, + "d": 3 + }, + "mne/utils/progressbar.py": { + "a": 2, + "d": 2 + }, + "mne/utils/spectrum.py": { + "a": 2, + "d": 0 + }, + "mne/utils/tests/test_bunch.py": { + "a": 1, + "d": 3 + }, + "mne/utils/tests/test_check.py": { + "a": 2, + "d": 3 + }, + "mne/utils/tests/test_config.py": { + "a": 2, + "d": 0 + }, + "mne/utils/tests/test_docs.py": { + "a": 2, + "d": 0 + }, + "mne/utils/tests/test_linalg.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_logging.py": { + "a": 2, + "d": 0 + }, + "mne/utils/tests/test_misc.py": { + "a": 2, + "d": 0 + }, + "mne/utils/tests/test_mixin.py": { + "a": 1, + "d": 2 + }, + "mne/utils/tests/test_numerics.py": { + "a": 2, + "d": 0 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 1, + "d": 2 + }, + "mne/utils/tests/test_testing.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 7 + }, + "mne/viz/_3d_overlay.py": { + "a": 1, + "d": 3 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/__init__.py": { + "a": 1, + "d": 7 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 7 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 2, + "d": 4 + }, + "mne/viz/_brain/_scraper.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/colormap.py": { + "a": 1, + "d": 5 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 6 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 6 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_brain/view.py": { + "a": 1, + "d": 6 + }, + "mne/viz/_dipole.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 2, + "d": 3 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_proj.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_scraper.py": { + "a": 1, + "d": 2 + }, + "mne/viz/backends/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 4 + }, + "mne/viz/backends/_notebook.py": { + "a": 1, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 5 + }, + "mne/viz/backends/_qt.py": { + "a": 1, + "d": 4 + }, + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 5 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 5 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 1, + "d": 5 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 1, + "d": 2 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 1, + "d": 5 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 1, + "d": 5 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 4 + }, + "mne/viz/conftest.py": { + "a": 1, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 9 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 8 + }, + "mne/viz/evoked_field.py": { + "a": 2, + "d": 0 + }, + "mne/viz/eyetracking/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/eyetracking/heatmap.py": { + "a": 1, + "d": 2 + }, + "mne/viz/eyetracking/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/eyetracking/tests/test_heatmap.py": { + "a": 1, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 5 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 7 + }, + "mne/viz/montage.py": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 4 + }, + "mne/viz/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 7 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 1, + "d": 7 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 4 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 7 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 9 + }, + "mne/viz/tests/test_figure.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 3 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 7 + }, + "mne/viz/tests/test_montage.py": { + "a": 1, + "d": 4 + }, + "mne/viz/tests/test_proj.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_scraper.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 6 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 6 + }, + "mne/viz/tests/test_ui_events.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_utils.py": { + "a": 1, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 8 + }, + "mne/viz/ui_events.py": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 9 + }, + "tools/check_mne_location.py": { + "a": 2, + "d": 0 + }, + "tools/dev/check_steering_committee.py": { + "a": 9, + "d": 4 + }, + "tools/dev/ensure_headers.py": { + "a": 125, + "d": 51 + }, + "tools/dev/gen_css_for_mne.py": { + "a": 1, + "d": 2 + }, + "tools/dev/generate_pyi_files.py": { + "a": 2, + "d": 0 + }, + "tools/dev/update_credit_json.py": { + "a": 4, + "d": 0 + }, + "tools/generate_codemeta.py": { + "a": 2, + "d": 0 + }, + "tools/vulture_allowlist.py": { + "a": 11, + "d": 1 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/40_whitened.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/10_background_freesurfer.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/30_forward.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/10_overview.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/15_inplace.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/30_info.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/10_stc_class.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 2, + "d": 0 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 2, + "d": 0 + }, + "tutorials/io/10_reading_meg_data.py": { + "a": 2, + "d": 0 + }, + "tutorials/io/20_reading_eeg_data.py": { + "a": 2, + "d": 0 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 2, + "d": 0 + }, + "tutorials/io/70_reading_eyetracking_data.py": { + "a": 2, + "d": 0 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/80_opm_processing.py": { + "a": 2, + "d": 0 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 2, + "d": 0 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 2, + "d": 0 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 2, + "d": 0 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 2, + "d": 0 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 2, + "d": 0 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 2, + "d": 0 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 2, + "d": 0 + }, + "tutorials/time-freq/10_spectrum_class.py": { + "a": 2, + "d": 0 + }, + "tutorials/visualization/20_ui_events.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12783.json b/mne-python/source/doc/sphinxext/prs/12783.json new file mode 100644 index 0000000000000000000000000000000000000000..3d4f0664e07f86e449ce833fda67e39b30eab654 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12783.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "01a1c1e40e81ef22ec8ee4d1564c3bdf87adfc88", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12786.json b/mne-python/source/doc/sphinxext/prs/12786.json new file mode 100644 index 0000000000000000000000000000000000000000..fbe4032ee0f3639a27ff3d6455106f7b2681a87d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12786.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c9f8ee2998e6a47d667076a9c76ee48da480e4e1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/stats-sensor-space/70_cluster_rmANOVA_time_freq.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12787.json b/mne-python/source/doc/sphinxext/prs/12787.json new file mode 100644 index 0000000000000000000000000000000000000000..045dd24450f18f6cd783a9ff16e302242e032948 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12787.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "828953e0ba584c149bcd2d6898d3599af1b30f40", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/12787.other.rst": { + "a": 1, + "d": 0 + }, + "mne/utils/config.py": { + "a": 55, + "d": 5 + }, + "mne/utils/tests/test_config.py": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12788.json b/mne-python/source/doc/sphinxext/prs/12788.json new file mode 100644 index 0000000000000000000000000000000000000000..787c8383b765771bf5947dfb17395c714fdbea96 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12788.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "dcb05a22cff16539e5753496668fa0a0b14b6c9a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 35, + "d": 10 + }, + "mne/html_templates/repr/_acquisition.html.jinja": { + "a": 13, + "d": 23 + }, + "mne/html_templates/repr/_channels.html.jinja": { + "a": 7, + "d": 17 + }, + "mne/html_templates/repr/_filters.html.jinja": { + "a": 6, + "d": 16 + }, + "mne/html_templates/repr/_general.html.jinja": { + "a": 8, + "d": 18 + }, + "mne/html_templates/repr/epochs.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/evoked.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/forward.html.jinja": { + "a": 3, + "d": 3 + }, + "mne/html_templates/repr/ica.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/info.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/inverse_operator.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/raw.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/spectrum.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/static/_section_header_row.html.jinja": { + "a": 12, + "d": 0 + }, + "mne/html_templates/repr/static/repr.css": { + "a": 95, + "d": 93 + }, + "mne/html_templates/repr/static/repr.js": { + "a": 17, + "d": 29 + }, + "mne/html_templates/repr/tfr.html.jinja": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 2 + }, + "tutorials/io/70_reading_eyetracking_data.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12792.json b/mne-python/source/doc/sphinxext/prs/12792.json new file mode 100644 index 0000000000000000000000000000000000000000..df21223b9d3ec367054515087528b3a08b29c87f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12792.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "ab69d3e235de846b53ac2052b33faddce9ffd4f9", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/api/reading_raw_data.rst": { + "a": 14, + "d": 13 + }, + "doc/changes/devel/12792.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/io/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 34, + "d": 10 + }, + "mne/io/ant/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/io/ant/ant.py": { + "a": 293, + "d": 0 + }, + "mne/io/ant/tests/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/io/ant/tests/test_ant.py": { + "a": 138, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 18, + "d": 15 + }, + "mne/io/nsx/nsx.py": { + "a": 8, + "d": 5 + }, + "mne/io/tests/test_read_raw.py": { + "a": 58, + "d": 1 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12793.json b/mne-python/source/doc/sphinxext/prs/12793.json new file mode 100644 index 0000000000000000000000000000000000000000..90d06e085272196eb5f212af3519c55a52217c93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12793.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "450acb1c33d19b2fe054be9c6b01f8a83f8c7a9b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/credit.yml": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12794.json b/mne-python/source/doc/sphinxext/prs/12794.json new file mode 100644 index 0000000000000000000000000000000000000000..a83bcc71056f45a6297442e0705a521eade93df3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12794.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "09696542308a8745b9a7d245bc5af00f8284d706", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/12747.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/12774.json": { + "a": 103, + "d": 0 + }, + "doc/sphinxext/prs/12778.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/12781.json": { + "a": 2911, + "d": 0 + }, + "doc/sphinxext/prs/12783.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12786.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12793.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12796.json b/mne-python/source/doc/sphinxext/prs/12796.json new file mode 100644 index 0000000000000000000000000000000000000000..76455afaccd9449d76f8cff20bdac515a801e50c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12796.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e108241dbc0392100cf1b5df1598bda2f1645459", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/12794.json": { + "a": 39, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12797.json b/mne-python/source/doc/sphinxext/prs/12797.json new file mode 100644 index 0000000000000000000000000000000000000000..050912edf2314db47941ba867ec218bf69841871 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12797.json @@ -0,0 +1,311 @@ +{ + "merge_commit_sha": "bf5173b3cdc69d86fb7db1f2fc2edd3b57fbc2a2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/credit.yml": { + "a": 1, + "d": 1 + }, + ".mailmap": { + "a": 2, + "d": 1 + }, + "CITATION.cff": { + "a": 39, + "d": 23 + }, + "codemeta.json": { + "a": 122, + "d": 74 + }, + "doc/_static/versions.json": { + "a": 7, + "d": 2 + }, + "doc/changes/devel.rst": { + "a": 0, + "d": 5 + }, + "doc/changes/devel/12300.apichange.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/12300.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12338.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12554.dependency.rst": { + "a": 0, + "d": 6 + }, + "doc/changes/devel/12556.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12561.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12562.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12569.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12573.newfeature.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/12576.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12578.bugfix.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/12583.apichange.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12583.newfeature.rst": { + "a": 0, + "d": 4 + }, + "doc/changes/devel/12584.newfeature.rst": { + "a": 0, + "d": 4 + }, + "doc/changes/devel/12593.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12597.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12600.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12605.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12609.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12612.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12616.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12620.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12628.newfeature.rst": { + "a": 0, + "d": 4 + }, + "doc/changes/devel/12633.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12646.bugfix.rst": { + "a": 0, + "d": 10 + }, + "doc/changes/devel/12649.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12650.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12652.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12655.newfeature.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12659.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12661.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12664.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12669.newfeature.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12676.bugfix.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12686.newfeature.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12687.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12688.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12694.bugfix.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12697.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12699.apichange.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12703.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12707.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12719.apichange.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12720.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12720.newfeature.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12721.bugfix.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12724.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12725.newfeature.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12727.bugfix.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/12727.newfeature.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/12730.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12733.newfeature.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/12734.newfeature.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/12735.bugfix.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12742.dependency.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12747.newfeature.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/12754.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12759.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12760.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12763.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12771.apichange.rst": { + "a": 0, + "d": 4 + }, + "doc/changes/devel/12774.other.rst": { + "a": 0, + "d": 2 + }, + "doc/changes/devel/12781.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/v1.8.rst": { + "a": 173, + "d": 0 + }, + "doc/development/whats_new.rst": { + "a": 1, + "d": 1 + }, + "doc/documentation/cited.rst": { + "a": 3, + "d": 3 + }, + "doc/sphinxext/update_credit_rst.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12798.json b/mne-python/source/doc/sphinxext/prs/12798.json new file mode 100644 index 0000000000000000000000000000000000000000..4bdcbf6adfecdee73f7a61ec5cd45b865344153a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12798.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "a82528d35c655b693b23143a88850fe7a851fa10", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + }, + "README.rst": { + "a": 8, + "d": 8 + }, + "doc/changes/devel.rst": { + "a": 5, + "d": 0 + }, + "doc/changes/devel/12798.dependency.rst": { + "a": 1, + "d": 0 + }, + "doc/development/contributing.rst": { + "a": 2, + "d": 2 + }, + "doc/development/whats_new.rst": { + "a": 1, + "d": 0 + }, + "doc/install/installers.rst": { + "a": 5, + "d": 5 + }, + "doc/links.inc": { + "a": 1, + "d": 0 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 3, + "d": 34 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 0, + "d": 4 + }, + "mne/export/_edf.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 3, + "d": 9 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 3, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 5, + "d": 131 + }, + "mne/utils/_logging.py": { + "a": 2, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 8 + }, + "mne/viz/_brain/_brain.py": { + "a": 0, + "d": 27 + }, + "pyproject.toml": { + "a": 2, + "d": 1 + }, + "tools/environment_old.yml": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12799.json b/mne-python/source/doc/sphinxext/prs/12799.json new file mode 100644 index 0000000000000000000000000000000000000000..72fd0c1a174c6f107ac3b78f2f80d3a479e2d230 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12799.json @@ -0,0 +1,251 @@ +{ + "merge_commit_sha": "362f9330925fb79a6adc19a42243672676dec63e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/open.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/pick.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/proj.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/reference.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/write.py": { + "a": 1, + "d": 1 + }, + "mne/_ola.py": { + "a": 2, + "d": 2 + }, + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 4, + "d": 4 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ssd.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 6, + "d": 6 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 3, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 4, + "d": 4 + }, + "mne/io/fil/fil.py": { + "a": 1, + "d": 1 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 3, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 4 + }, + "mne/morph.py": { + "a": 2, + "d": 4 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 5, + "d": 5 + }, + "mne/simulation/raw.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 4 + }, + "mne/stats/regression.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 6 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 3, + "d": 3 + }, + "mne/utils/misc.py": { + "a": 2, + "d": 2 + }, + "mne/utils/mixin.py": { + "a": 5, + "d": 5 + }, + "mne/utils/numerics.py": { + "a": 11, + "d": 11 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 4 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 5 + }, + "mne/viz/backends/_qt.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 11, + "d": 11 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 3 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 3 + }, + "pyproject.toml": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/128.json b/mne-python/source/doc/sphinxext/prs/128.json new file mode 100644 index 0000000000000000000000000000000000000000..b55db8362f1879e5fb93dfce43fae362853014b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/128.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7508cb24c38ddb1b7bd6180a2e581d7106fe0e39", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ssp.py": { + "a": 8, + "d": 3 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 38, + "d": 0 + }, + "mne/proj.py": { + "a": 22, + "d": 4 + }, + "mne/tests/test_proj.py": { + "a": 10, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12800.json b/mne-python/source/doc/sphinxext/prs/12800.json new file mode 100644 index 0000000000000000000000000000000000000000..ea5fadc2ff1880feec0c16dd9894ae94427887c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12800.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "de72aae04118d77afbf5e4f3c0a8b0037e5bc38b", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12801.json b/mne-python/source/doc/sphinxext/prs/12801.json new file mode 100644 index 0000000000000000000000000000000000000000..d5cf5ceb9e4fb6cc673fc12f752c75bea57f8a15 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12801.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dcd34d4e588e24c2f5de2995417407aa115c59d9", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12801.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 8, + "d": 7 + }, + "mne/gui/_gui.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12802.json b/mne-python/source/doc/sphinxext/prs/12802.json new file mode 100644 index 0000000000000000000000000000000000000000..3d68a76c3a07324e5f227ffe9e5aec3340940a0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12802.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "966121be5931918ec63497aa4e9ba1404858007e", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12803.json b/mne-python/source/doc/sphinxext/prs/12803.json new file mode 100644 index 0000000000000000000000000000000000000000..67c3cc3f4e75bdbdf98f6c4cee21cbd942f136a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12803.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "223d4aa9ebd1b7942329912a057b349912792d2c", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12803.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_freesurfer.py": { + "a": 19, + "d": 16 + }, + "mne/source_space/_source_space.py": { + "a": 3, + "d": 4 + }, + "mne/utils/check.py": { + "a": 29, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12804.json b/mne-python/source/doc/sphinxext/prs/12804.json new file mode 100644 index 0000000000000000000000000000000000000000..1a714b42ba2af5b6dfaa44fdf0fcb492a6391044 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12804.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "99dd0e1c24856aaaca7289e7e14d7a1390496134", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/institutional-partners.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/12804.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12805.json b/mne-python/source/doc/sphinxext/prs/12805.json new file mode 100644 index 0000000000000000000000000000000000000000..a3dfd5556378c5894e2359dd6b146cd2976c0846 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12805.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "0aae72dda030242d992866ce6d551206749474b2", + "authors": [ + { + "n": "Alex lepauvre", + "e": "alex.lepauvre@ae.mpg.de" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12805.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_base.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 13, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 71, + "d": 5 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 111, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 156, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12806.json b/mne-python/source/doc/sphinxext/prs/12806.json new file mode 100644 index 0000000000000000000000000000000000000000..c15a965b71f82d1bb6b93bdf1c01d936bd5d028b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12806.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "ac2c4c0d72f9843690aad70e63b48269f5269a0f", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/institutional-partners.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/12803.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12804.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "mne/_freesurfer.py": { + "a": 19, + "d": 16 + }, + "mne/forward/forward.py": { + "a": 5, + "d": 1 + }, + "mne/source_space/_source_space.py": { + "a": 3, + "d": 4 + }, + "mne/utils/check.py": { + "a": 29, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12810.json b/mne-python/source/doc/sphinxext/prs/12810.json new file mode 100644 index 0000000000000000000000000000000000000000..d091af6127705370484ca7e8963fa55bc9d1e9ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12810.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "af19be0a123735fd6b85e82e01adba86d6574188", + "authors": [ + { + "n": "Proloy Das", + "e": "proloy@umd.edu" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/ant/ant.py": { + "a": 57, + "d": 6 + }, + "mne/io/ant/tests/test_ant.py": { + "a": 188, + "d": 21 + }, + "tools/vulture_allowlist.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12811.json b/mne-python/source/doc/sphinxext/prs/12811.json new file mode 100644 index 0000000000000000000000000000000000000000..3cf0b022e14a9de7fef008f629a7d1bea4a48c52 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12811.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "bd8f9cbd2cb3d520d9671ad445eb81c8fb85b942", + "authors": [ + { + "n": "Victor Férat", + "e": "victor.ferat@live.Fr" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12811.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/utils.py": { + "a": 6, + "d": 2 + }, + "mne/epochs.py": { + "a": 7, + "d": 0 + }, + "mne/io/base.py": { + "a": 13, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 13, + "d": 6 + }, + "mne/io/tests/test_raw.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12812.json b/mne-python/source/doc/sphinxext/prs/12812.json new file mode 100644 index 0000000000000000000000000000000000000000..8111f32ed6ba2d771c9ee81097b730aff68598a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12812.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "08a383126bcf9bfc7b98e5462d5803dc1fa239a1", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/annotations.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12813.json b/mne-python/source/doc/sphinxext/prs/12813.json new file mode 100644 index 0000000000000000000000000000000000000000..30a9de7df4d7f6a6403e577b776d1d0c5132169f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12813.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b1203ada6f1a3ecaac4e8b67df45b9124a34dcd7", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/io/ant/tests/test_ant.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12814.json b/mne-python/source/doc/sphinxext/prs/12814.json new file mode 100644 index 0000000000000000000000000000000000000000..8ddb8f3403b4f300d164848b18f915ce3309d3ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12814.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "20871ff2286935a564a9db5320afa7437df18458", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12815.json b/mne-python/source/doc/sphinxext/prs/12815.json new file mode 100644 index 0000000000000000000000000000000000000000..6b0f7fd1f1b8b1f5c1008275f0338d2645f625c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12815.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f27bac8b5a128667d7f946f0089132fa5d0da9ba", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "examples/io/read_neo_format.py": { + "a": 1, + "d": 3 + }, + "mne/_fiff/meas_info.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12820.json b/mne-python/source/doc/sphinxext/prs/12820.json new file mode 100644 index 0000000000000000000000000000000000000000..73fa2132a6856705088d355fa4ada59ce634d7d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12820.json @@ -0,0 +1,159 @@ +{ + "merge_commit_sha": "13852f58bced5a49434d06e50d98efcf6b4292de", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".github/workflows/credit.yml": { + "a": 1, + "d": 1 + }, + ".mailmap": { + "a": 10, + "d": 8 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/v0.10.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/v0.11.rst": { + "a": 3, + "d": 3 + }, + "doc/changes/v0.12.rst": { + "a": 10, + "d": 10 + }, + "doc/changes/v0.13.rst": { + "a": 13, + "d": 13 + }, + "doc/changes/v0.14.rst": { + "a": 7, + "d": 7 + }, + "doc/changes/v0.15.rst": { + "a": 8, + "d": 8 + }, + "doc/changes/v0.16.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/v0.18.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/v0.20.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v0.21.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/v0.22.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/v0.23.rst": { + "a": 3, + "d": 3 + }, + "doc/changes/v0.24.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/v0.8.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/v0.9.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/v1.1.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/v1.7.rst": { + "a": 90, + "d": 90 + }, + "doc/changes/v1.8.rst": { + "a": 63, + "d": 63 + }, + "doc/conf.py": { + "a": 2, + "d": 3 + }, + "doc/sphinxext/credit_tools.py": { + "a": 88, + "d": 9 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 7, + "d": 0 + }, + "doc/sphinxext/related_software.py": { + "a": 10, + "d": 2 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/ems_filtering.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 1, + "d": 1 + }, + "examples/io/read_neo_format.py": { + "a": 4, + "d": 4 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12822.json b/mne-python/source/doc/sphinxext/prs/12822.json new file mode 100644 index 0000000000000000000000000000000000000000..c141dd3a44a604d0a0ee7bf53e8f450f6dcffae2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12822.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "346af6fec258e3bb0d30791dfacbe86cdb354f2b", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/12792.json": { + "a": 75, + "d": 0 + }, + "doc/sphinxext/prs/12796.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12797.json": { + "a": 311, + "d": 0 + }, + "doc/sphinxext/prs/12798.json": { + "a": 99, + "d": 0 + }, + "doc/sphinxext/prs/12799.json": { + "a": 251, + "d": 0 + }, + "doc/sphinxext/prs/12800.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12801.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12802.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12803.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12804.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/12805.json": { + "a": 51, + "d": 0 + }, + "doc/sphinxext/prs/12806.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/12810.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12811.json": { + "a": 51, + "d": 0 + }, + "doc/sphinxext/prs/12812.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12813.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12814.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12815.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12820.json": { + "a": 159, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12823.json b/mne-python/source/doc/sphinxext/prs/12823.json new file mode 100644 index 0000000000000000000000000000000000000000..fb637d0e6cd294bd8a91adf45ca58eca34e8169c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12823.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e221c6cb71ec42f7eebe1c5ea81089d78c91d4a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".git-blame-ignore-revs": { + "a": 1, + "d": 0 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 1, + "d": 0 + }, + "mne/morph.py": { + "a": 7, + "d": 1 + }, + "mne/preprocessing/ieeg/_volume.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 5, + "d": 1 + }, + "mne/transforms.py": { + "a": 22, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12825.json b/mne-python/source/doc/sphinxext/prs/12825.json new file mode 100644 index 0000000000000000000000000000000000000000..83fe12fffab3502c70f40726c6e1ffdf239a7582 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12825.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3f1c7803f73862dec3e4e85e36e916f2a6d642c9", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12826.json b/mne-python/source/doc/sphinxext/prs/12826.json new file mode 100644 index 0000000000000000000000000000000000000000..1ed6149866065e98e31def9ae6452673485b4052 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12826.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "013d6c9f630342e5af7633641162c7b85417782a", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/preprocessing/hfc.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12827.json b/mne-python/source/doc/sphinxext/prs/12827.json new file mode 100644 index 0000000000000000000000000000000000000000..80311bb192c563c1ec977b0736de62394e6a8ada --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12827.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f3a3ca4430e1d4b9c539e7949c946f4f83bdb43f", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12827.other.rst": { + "a": 1, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 52, + "d": 3 + }, + "mne/decoding/ssd.py": { + "a": 25, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12828.json b/mne-python/source/doc/sphinxext/prs/12828.json new file mode 100644 index 0000000000000000000000000000000000000000..6030dffc960261bd070f0cb3666d310d744c8d4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12828.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "176f64ff061136cf5628d76535a8d7e2e164d399", + "authors": [ + { + "n": "Shristi Baral", + "e": null + }, + { + "n": "shristi", + "e": "shristi.baral@aalto.fi" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12828.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 7, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 13, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12829.json b/mne-python/source/doc/sphinxext/prs/12829.json new file mode 100644 index 0000000000000000000000000000000000000000..78d7d0433f4da0572037d69982a0205481afcfd0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12829.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c993ae5d65b3c161876da407e293e6784c6e8ad9", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/devel/12829.apichange.rst": { + "a": 1, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12830.json b/mne-python/source/doc/sphinxext/prs/12830.json new file mode 100644 index 0000000000000000000000000000000000000000..7e46a12cc4ef26a5d7c5ce81d375fe69a82992e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12830.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3ecdd6b2102b00f97d7ad98ca2483a0f79e90b30", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12830.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 19, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 24, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12832.json b/mne-python/source/doc/sphinxext/prs/12832.json new file mode 100644 index 0000000000000000000000000000000000000000..7b877da05804dcedf2b485ddb42373278642df0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12832.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c46733a4812f5d19370699c7b18cb1c1c4ded9fa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12833.json b/mne-python/source/doc/sphinxext/prs/12833.json new file mode 100644 index 0000000000000000000000000000000000000000..e1f4124bf3ce10274531f4a2f93d4e5ee9e5b79e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12833.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2f299276fecedcb8b3626ea40fc4f1aecff51bce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/PULL_REQUEST_TEMPLATE.md": { + "a": 11, + "d": 4 + }, + "tools/github_actions_test.sh": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12834.json b/mne-python/source/doc/sphinxext/prs/12834.json new file mode 100644 index 0000000000000000000000000000000000000000..cf5154627ed7ce136c6fc5ed7fd002035318e016 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12834.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "5425ef42e41b6a427f3365e13ea57ecf9c0c12b0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12834.dependency.rst": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 28, + "d": 0 + }, + "examples/visualization/evoked_whitening.py": { + "a": 1, + "d": 0 + }, + "mne/cov.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/__init__.pyi": { + "a": 7, + "d": 2 + }, + "mne/decoding/base.py": { + "a": 24, + "d": 34 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/ems.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/mixin.py": { + "a": 0, + "d": 89 + }, + "mne/decoding/receptive_field.py": { + "a": 5, + "d": 13 + }, + "mne/decoding/search_light.py": { + "a": 7, + "d": 21 + }, + "mne/decoding/ssd.py": { + "a": 9, + "d": 9 + }, + "mne/decoding/tests/test_base.py": { + "a": 32, + "d": 42 + }, + "mne/decoding/tests/test_csp.py": { + "a": 7, + "d": 9 + }, + "mne/decoding/tests/test_ems.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 30, + "d": 37 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 24, + "d": 33 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 6, + "d": 4 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 4, + "d": 3 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 6, + "d": 10 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 0, + "d": 3 + }, + "mne/decoding/time_frequency.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 2 + }, + "mne/fixes.py": { + "a": 48, + "d": 228 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 12, + "d": 3 + }, + "pyproject.toml": { + "a": 4, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 3 + }, + "tools/vulture_allowlist.py": { + "a": 4, + "d": 0 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12837.json b/mne-python/source/doc/sphinxext/prs/12837.json new file mode 100644 index 0000000000000000000000000000000000000000..196fdf71511296f61b8f4ef4f9cc57e5c921b602 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12837.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9a2f887146f080357a83104c4af2c95e2176fe88", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12838.json b/mne-python/source/doc/sphinxext/prs/12838.json new file mode 100644 index 0000000000000000000000000000000000000000..3e4860bd08f4415bb3c27a21177463b3824277d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12838.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5cd52993c0027a958cfbc4f6810dff5d180301e5", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/utils/config.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12839.json b/mne-python/source/doc/sphinxext/prs/12839.json new file mode 100644 index 0000000000000000000000000000000000000000..f1f8d57e8aa5eedb38c56cf5d106d928167db813 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12839.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ebab915ea723155ee0fed788bcc92c2ff16a4f7f", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/_standard_montage_utils.py": { + "a": 9, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 5, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 55, + "d": 1 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1284.json b/mne-python/source/doc/sphinxext/prs/1284.json new file mode 100644 index 0000000000000000000000000000000000000000..61094b1f138ceee7eec57cb0c2f43079ac0742b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1284.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bbfab25bb2148fd74a3978dba6a430ea8c2a01f7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12841.json b/mne-python/source/doc/sphinxext/prs/12841.json new file mode 100644 index 0000000000000000000000000000000000000000..0165fbe7092558633c102a48146b1da9ec27486a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12841.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "528e04658c5ea7a5e55bcb5889ebb4c6d6847284", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/devel/12792.newfeature.rst": { + "a": 1, + "d": 1 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/ant/ant.py": { + "a": 2, + "d": 2 + }, + "mne/io/ant/tests/test_ant.py": { + "a": 218, + "d": 33 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/vulture_allowlist.py": { + "a": 1, + "d": 0 + }, + "tutorials/io/20_reading_eeg_data.py": { + "a": 28, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12842.json b/mne-python/source/doc/sphinxext/prs/12842.json new file mode 100644 index 0000000000000000000000000000000000000000..7647f81bc5c003ed87beaaa73995a5521e6f6643 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12842.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e999e853b263c8b48a6fcfeb60c82b445e20d88b", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/12842.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/decoding/receptive_field.py": { + "a": 5, + "d": 4 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 13, + "d": 9 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 7, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12843.json b/mne-python/source/doc/sphinxext/prs/12843.json new file mode 100644 index 0000000000000000000000000000000000000000..896123e0088e15085066ac4a7570e5af517ae30c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12843.json @@ -0,0 +1,195 @@ +{ + "merge_commit_sha": "10ff91a339642f75e18ba1497b60ead88c24cd2b", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12843.bugfix.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/devel/12843.other.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/open.py": { + "a": 22, + "d": 21 + }, + "mne/_fiff/tests/test_what.py": { + "a": 9, + "d": 4 + }, + "mne/_fiff/tree.py": { + "a": 9, + "d": 6 + }, + "mne/_fiff/utils.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/what.py": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 32, + "d": 38 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 15, + "d": 6 + }, + "mne/evoked.py": { + "a": 19, + "d": 6 + }, + "mne/export/_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 29, + "d": 30 + }, + "mne/gui/_gui.py": { + "a": 13, + "d": 15 + }, + "mne/io/base.py": { + "a": 67, + "d": 43 + }, + "mne/io/boxy/boxy.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 4, + "d": 3 + }, + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 2 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 4 + }, + "mne/io/fiff/raw.py": { + "a": 43, + "d": 23 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 52, + "d": 29 + }, + "mne/io/hitachi/hitachi.py": { + "a": 2, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/nedf/nedf.py": { + "a": 1, + "d": 1 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 1, + "d": 1 + }, + "mne/io/nihon/nihon.py": { + "a": 1, + "d": 1 + }, + "mne/io/persyst/persyst.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 2, + "d": 1 + }, + "mne/report/report.py": { + "a": 41, + "d": 56 + }, + "mne/source_space/_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 22, + "d": 0 + }, + "mne/utils/check.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/_notebook.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12844.json b/mne-python/source/doc/sphinxext/prs/12844.json new file mode 100644 index 0000000000000000000000000000000000000000..17e1ce65ad82367f87fb6906fea0b437e4b71a5e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12844.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a218f96927ef06fd8a4e38363b9d98f74a93f1c3", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/12844.other.rst": { + "a": 1, + "d": 0 + }, + "examples/datasets/limo_data.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/epochs_metadata.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 32, + "d": 5 + }, + "tutorials/clinical/60_sleep.py": { + "a": 4, + "d": 4 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 4, + "d": 4 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12845.json b/mne-python/source/doc/sphinxext/prs/12845.json new file mode 100644 index 0000000000000000000000000000000000000000..2cf94a62a251bb95ead22d41da24b91de2285d2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12845.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "efe8b6a9ce87c9a45dcdc20a8c44e99d2efb6c13", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 3, + "d": 0 + }, + "doc/_static/js/set_installer_tab.js": { + "a": 24, + "d": 11 + }, + "doc/_static/js/update_installer_version.js": { + "a": 1, + "d": 1 + }, + "doc/install/installers.rst": { + "a": 59, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12846.json b/mne-python/source/doc/sphinxext/prs/12846.json new file mode 100644 index 0000000000000000000000000000000000000000..efb06196e5f083979e5894421970aec213a4892e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12846.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "670330a1ead288f11cc3ffd5ca9d65136ca55ccd", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/devel/12846.bugfix.rst": { + "a": 1, + "d": 0 + }, + "examples/visualization/eyetracking_plot_heatmap.py": { + "a": 4, + "d": 0 + }, + "mne/defaults.py": { + "a": 9, + "d": 9 + }, + "tutorials/io/70_reading_eyetracking_data.py": { + "a": 33, + "d": 17 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 32, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12847.json b/mne-python/source/doc/sphinxext/prs/12847.json new file mode 100644 index 0000000000000000000000000000000000000000..9545c8aa667988503c51dd8217d325719eacc596 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12847.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9652572611a0ef6941e59b40575bdfc05a945387", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/12847.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 259, + "d": 110 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 120, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12848.json b/mne-python/source/doc/sphinxext/prs/12848.json new file mode 100644 index 0000000000000000000000000000000000000000..dc2401b2a9333ee55f8859c3f14a2276a2891dc4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12848.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "715784fb3f4276ee977f6bf12c67b57dd9e47843", + "authors": [ + { + "n": "Victor Férat", + "e": "victor.ferat@live.Fr" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12848.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 134, + "d": 5 + }, + "mne/report/tests/test_report.py": { + "a": 25, + "d": 1 + }, + "mne/source_space/_source_space.py": { + "a": 8, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 6, + "d": 5 + }, + "mne/utils/check.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/view.py": { + "a": 35, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 18, + "d": 8 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12850.json b/mne-python/source/doc/sphinxext/prs/12850.json new file mode 100644 index 0000000000000000000000000000000000000000..8cb357550c82245829b6790af05d675e23686b64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12850.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4f58e814b4e5d01311f359f3d8f8e2cbca391fbb", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/defaults.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12853.json b/mne-python/source/doc/sphinxext/prs/12853.json new file mode 100644 index 0000000000000000000000000000000000000000..4113fdfeac633d036f49d75d99e0130824a785fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12853.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2cab0257a430127c4bae348380ab2be99bffb412", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/devel/12853.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 18, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12856.json b/mne-python/source/doc/sphinxext/prs/12856.json new file mode 100644 index 0000000000000000000000000000000000000000..8eefad7827a29d93377ca7bcd8308d80f5784b57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12856.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "efbd97292592e92c2bdfe09e2fea9cf9b1d2e6f6", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1286.json b/mne-python/source/doc/sphinxext/prs/1286.json new file mode 100644 index 0000000000000000000000000000000000000000..c0dbb61fd6bd8ed04ee6438cff7777154d32a01a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1286.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b86e3c1f8caf86248e8e9321a4a75a045842a708", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 8, + "d": 3 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12860.json b/mne-python/source/doc/sphinxext/prs/12860.json new file mode 100644 index 0000000000000000000000000000000000000000..2220691beadfa4be9007fab7028c9b51d1fc6dbd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12860.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6f9646ff979294683bb385e63f3587aa3c7a6dd5", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_base.py": { + "a": 5, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 8, + "d": 7 + }, + "mne/utils/progressbar.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12861.json b/mne-python/source/doc/sphinxext/prs/12861.json new file mode 100644 index 0000000000000000000000000000000000000000..d7b6f00520638b592a7682d1b9ecf6861b5b8aee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12861.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fa841cbc30ce830e40c60a8a44518b84e2f7f0cf", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12862.json b/mne-python/source/doc/sphinxext/prs/12862.json new file mode 100644 index 0000000000000000000000000000000000000000..c89ada322dca253eea91d404a84fc09f51b8ddfc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12862.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b9cdca8638b20768e85822f5e5e57a5fe043d393", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12862.other.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 42, + "d": 9 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12865.json b/mne-python/source/doc/sphinxext/prs/12865.json new file mode 100644 index 0000000000000000000000000000000000000000..c52aeea46062f9676f6eee6a476c8b20a82c97a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12865.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e6f9c5df856418d331684dd3477e8c1d1c0f37e1", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12866.json b/mne-python/source/doc/sphinxext/prs/12866.json new file mode 100644 index 0000000000000000000000000000000000000000..deda3246f0f6013dfcce364ca36989107da41acb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12866.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ab2516826c4b3492f1246db978791207ad7f66d7", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/preprocessing/ecg.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12867.json b/mne-python/source/doc/sphinxext/prs/12867.json new file mode 100644 index 0000000000000000000000000000000000000000..dde94ea5570ba3b611bc016548701b1b3ae1884f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12867.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fc05aeb19e7e998356d400d5e93d977545a0511a", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12868.json b/mne-python/source/doc/sphinxext/prs/12868.json new file mode 100644 index 0000000000000000000000000000000000000000..a89104cb11e009808aa24d27726326591bef5029 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12868.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d248a5763e1ced3c9c65a12101e46d85e806df54", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/io/read_impedances.py": { + "a": 77, + "d": 0 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 0 + }, + "mne/io/ant/ant.py": { + "a": 1, + "d": 13 + }, + "mne/io/ant/tests/test_ant.py": { + "a": 1, + "d": 6 + }, + "pyproject.toml": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12869.json b/mne-python/source/doc/sphinxext/prs/12869.json new file mode 100644 index 0000000000000000000000000000000000000000..8abf2a3f1cdf6754292051fca2151050616bea1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12869.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1dd07a4ee95a3a16f2e0b6cf97b3e0416595dc7a", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1287.json b/mne-python/source/doc/sphinxext/prs/1287.json new file mode 100644 index 0000000000000000000000000000000000000000..810765f6111ad404ea499dc4376e7eb44f041ac7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1287.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d91654931e4845b080bffc831d79d7570658f800", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 5, + "d": 0 + }, + "examples/plot_extract_events_from_raw.py": { + "a": 7, + "d": 1 + }, + "mne/tests/test_viz.py": { + "a": 14, + "d": 0 + }, + "mne/viz.py": { + "a": 67, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12870.json b/mne-python/source/doc/sphinxext/prs/12870.json new file mode 100644 index 0000000000000000000000000000000000000000..d62c050fd91c1b35ff70802315af1b33db0f8a16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12870.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "50ce70a9d04645988a3fddead56e6892faa940fe", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 6, + "d": 0 + }, + "pyproject.toml": { + "a": 311, + "d": 314 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12871.json b/mne-python/source/doc/sphinxext/prs/12871.json new file mode 100644 index 0000000000000000000000000000000000000000..91385573801d9f04937a5b8b05b176bb47aca992 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12871.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "381688fc250e6f1b1a6e1bf26357379b0fec94a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12871.newfeature.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 4, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 12, + "d": 4 + }, + "mne/viz/backends/renderer.py": { + "a": 34, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12872.json b/mne-python/source/doc/sphinxext/prs/12872.json new file mode 100644 index 0000000000000000000000000000000000000000..ec74da5c20d7ccbbff1aca2e3e9b8b4dc3887bee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12872.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "78ea8b7527666bc92ed47b9a3056e8125ac786a4", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/development/roadmap.rst": { + "a": 148, + "d": 64 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12875.json b/mne-python/source/doc/sphinxext/prs/12875.json new file mode 100644 index 0000000000000000000000000000000000000000..124aa3135a3653ea16e45493478e009dcc81e218 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12875.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5492174fc0e64762056b5b99a330129ca6eefca4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12875.bugfix.rst": { + "a": 2, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 178, + "d": 114 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 15, + "d": 5 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 0 + }, + "mne/io/persyst/persyst.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12877.json b/mne-python/source/doc/sphinxext/prs/12877.json new file mode 100644 index 0000000000000000000000000000000000000000..f3906dedfa67fe2179d51d6213f828441d475722 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12877.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7af60e6329b79810061ccf99df4fa08b5232d1ac", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12877.bugfix.rst": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 19, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12878.json b/mne-python/source/doc/sphinxext/prs/12878.json new file mode 100644 index 0000000000000000000000000000000000000000..400bc5dd56e6435321955f636f325c1e8d9585b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12878.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8379668a42b68ba115310dfd9e5f821e3efb4db8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/fiff/raw.py": { + "a": 8, + "d": 5 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12879.json b/mne-python/source/doc/sphinxext/prs/12879.json new file mode 100644 index 0000000000000000000000000000000000000000..0f8fc811afaaadf30ce7b8dd39a5b54043f70ab9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12879.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "099cf6043732c511b403d5ec6df343a3f0060ed2", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1288.json b/mne-python/source/doc/sphinxext/prs/1288.json new file mode 100644 index 0000000000000000000000000000000000000000..6e68ad9b64b37b616935581e6fa824a56bcf1424 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1288.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5c18e533d3b345d83f9f2e40d83157a2316c9b26", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12880.json b/mne-python/source/doc/sphinxext/prs/12880.json new file mode 100644 index 0000000000000000000000000000000000000000..0ae1b4cfe37eb43a82c020f2e5e256bacb71aceb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12880.json @@ -0,0 +1,159 @@ +{ + "merge_commit_sha": "717bd1a13716a6b1c4a008e2fe6a907f317fe54a", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/12366.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/12787.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12788.json": { + "a": 91, + "d": 0 + }, + "doc/sphinxext/prs/12822.json": { + "a": 87, + "d": 0 + }, + "doc/sphinxext/prs/12823.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12825.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12826.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12827.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/12829.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12830.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12832.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12833.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12834.json": { + "a": 135, + "d": 0 + }, + "doc/sphinxext/prs/12837.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12838.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12839.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/12841.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/12842.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/12843.json": { + "a": 195, + "d": 0 + }, + "doc/sphinxext/prs/12844.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/12845.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12846.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/12850.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12853.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12856.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12860.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12861.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12862.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12865.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12866.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12867.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12868.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/12869.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12870.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12871.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/12875.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/12878.json": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12882.json b/mne-python/source/doc/sphinxext/prs/12882.json new file mode 100644 index 0000000000000000000000000000000000000000..dae0aedb81ae4e0ab500693aa2dd6be620564cb1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12882.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7e197c79a1314cf6293f6429aa932bbb7ef7378c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12846.bugfix.rst": { + "a": 2, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 3 + }, + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "doc/references.bib": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 3, + "d": 2 + }, + "tutorials/clinical/30_ecog.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12883.json b/mne-python/source/doc/sphinxext/prs/12883.json new file mode 100644 index 0000000000000000000000000000000000000000..c444f6e997a9aad55a59f34ce899637f9ce05f6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12883.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ed933b8d9d523a9f4f7006d6e6d1c81901e5478a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/html_templates/repr/_channels.html.jinja": { + "a": 1, + "d": 17 + }, + "mne/html_templates/repr/forward.html.jinja": { + "a": 18, + "d": 24 + }, + "mne/html_templates/repr/static/_channels.html.jinja": { + "a": 17, + "d": 0 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12884.json b/mne-python/source/doc/sphinxext/prs/12884.json new file mode 100644 index 0000000000000000000000000000000000000000..3420faeccb78f979c2e88dee14db2643641d30c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12884.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "bddaad9510941c1cf4e81266569172e993b59d92", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12884.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 10, + "d": 3 + }, + "mne/gui/tests/test_coreg.py": { + "a": 9, + "d": 1 + }, + "mne/preprocessing/realign.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_event.py": { + "a": 5, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 11, + "d": 4 + }, + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12885.json b/mne-python/source/doc/sphinxext/prs/12885.json new file mode 100644 index 0000000000000000000000000000000000000000..84274b6b372bb8cfee344753b752f315649d4d70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12885.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "53f258debb781aeee2c2e5cbf449f37822e3a898", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 28, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12886.json b/mne-python/source/doc/sphinxext/prs/12886.json new file mode 100644 index 0000000000000000000000000000000000000000..37116f2ea92b1b7db9f1daad63cd040e6e298746 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12886.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d4c0d1c4062110db8c1af0bee47df969d8968d8b", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "pyproject.toml": { + "a": 18, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12887.json b/mne-python/source/doc/sphinxext/prs/12887.json new file mode 100644 index 0000000000000000000000000000000000000000..d6286407d34697caa0bb9dc9b885d7c5cfa5b127 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12887.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "94fc435de1786bd7f5e4545970111d9bdc8aa7f9", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12888.json b/mne-python/source/doc/sphinxext/prs/12888.json new file mode 100644 index 0000000000000000000000000000000000000000..84d6ef07f512e5f58134b03836aa118a178a4edf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12888.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c0a98ed956c35ad42572253d2ce6f7ce0ed91a54", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1289.json b/mne-python/source/doc/sphinxext/prs/1289.json new file mode 100644 index 0000000000000000000000000000000000000000..c69b4320af2c5aea97802febfb58e7d2abf645ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1289.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "af31e0beb5b9108306c0f366c928607603e2c071", + "authors": [ + { + "n": "marmaduke woodman", + "e": null + } + ], + "changes": { + "mne/io/array/array.py": { + "a": 2, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12890.json b/mne-python/source/doc/sphinxext/prs/12890.json new file mode 100644 index 0000000000000000000000000000000000000000..fa84e8ae19966ae105ade588913c16173a2f6df1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12890.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "922a7801a0ca6af225c7b861fe6bd97b1518af3a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 15, + "d": 0 + }, + "README.rst": { + "a": 7, + "d": 32 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/hooks/sync_dependencies.py": { + "a": 95, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12891.json b/mne-python/source/doc/sphinxext/prs/12891.json new file mode 100644 index 0000000000000000000000000000000000000000..6e7a7b1a7844cbaa5bc63f15b6618ccfdb1477a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12891.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "06050bc72c637c297ff2e4fe0c7cba13243792e4", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12892.json b/mne-python/source/doc/sphinxext/prs/12892.json new file mode 100644 index 0000000000000000000000000000000000000000..ab2b8aebc6bbd549b7a090f78f811b7ab722dd4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12892.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "72faa3caa2239c6a4d973fc4cfd4a66a57ebcf00", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12896.json b/mne-python/source/doc/sphinxext/prs/12896.json new file mode 100644 index 0000000000000000000000000000000000000000..203d5d05c492df232777824ce98c711e2002ea6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12896.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a1a05ae11234929f0608d5a6b4fc30206af89031", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12896.other.rst": { + "a": 1, + "d": 0 + }, + "doc/development/governance.rst": { + "a": 251, + "d": 187 + }, + "doc/overview/people.rst": { + "a": 18, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12898.json b/mne-python/source/doc/sphinxext/prs/12898.json new file mode 100644 index 0000000000000000000000000000000000000000..7b39212813bc6cdb268ae4cf8426978707582534 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12898.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b831c28f96ef177462e3cab632f8910d44d22c22", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/install/manual_install_python.rst": { + "a": 13, + "d": 4 + }, + "doc/links.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12900.json b/mne-python/source/doc/sphinxext/prs/12900.json new file mode 100644 index 0000000000000000000000000000000000000000..64c7617bca8ba45d152cc950f2a7a5eb748a8bd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12900.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7250311b2ce52ed8f50bacf193636350bf796ffb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/default_linux_dock_icon.png": { + "a": 0, + "d": 0 + }, + "doc/_static/mne_python_dock_icon.png": { + "a": 0, + "d": 0 + }, + "doc/install/advanced.rst": { + "a": 31, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12901.json b/mne-python/source/doc/sphinxext/prs/12901.json new file mode 100644 index 0000000000000000000000000000000000000000..20d79a85b23386b3e0fa6d740a294d1877efeb1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12901.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "56e522ba303fe01a25a2a0d5d7507639a83fe02c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/12901.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12901.newfeature.rst": { + "a": 8, + "d": 0 + }, + "mne/html_templates/report/html.html.jinja": { + "a": 2, + "d": 6 + }, + "mne/html_templates/report/image.html.jinja": { + "a": 13, + "d": 13 + }, + "mne/html_templates/report/section.html.jinja": { + "a": 2, + "d": 6 + }, + "mne/html_templates/report/slider.html.jinja": { + "a": 3, + "d": 9 + }, + "mne/report/report.py": { + "a": 322, + "d": 122 + }, + "mne/report/tests/test_report.py": { + "a": 78, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 14, + "d": 8 + }, + "mne/viz/_3d.py": { + "a": 43, + "d": 17 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 2 + }, + "tutorials/intro/70_report.py": { + "a": 19, + "d": 1 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12902.json b/mne-python/source/doc/sphinxext/prs/12902.json new file mode 100644 index 0000000000000000000000000000000000000000..27cb64fbb700b2ab38cecc29015f9a76b61bd4fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12902.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f35aa5ae90616e97b0ce056a34dd98cdb7a9b184", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "environment.yml": { + "a": 12, + "d": 12 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12908.json b/mne-python/source/doc/sphinxext/prs/12908.json new file mode 100644 index 0000000000000000000000000000000000000000..5c7956c5050ef9d3b15c395697154e9606107ef0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12908.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "18c0d44668024e933514e63e459306bd5b1a89a9", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12909.json b/mne-python/source/doc/sphinxext/prs/12909.json new file mode 100644 index 0000000000000000000000000000000000000000..93097c15c54f5df702714c2c39ca0b5c175050cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12909.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "97f5b9c34e3f00433886f44f10b9cb09ae4b69a3", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/12909.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12910.json b/mne-python/source/doc/sphinxext/prs/12910.json new file mode 100644 index 0000000000000000000000000000000000000000..6240f4368c06cbd8de51069b3152e9af56803a07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12910.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "1d2635f84a55785c3531cfe4027eda3820a7fb31", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12910.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 10, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 195, + "d": 26 + }, + "mne/time_frequency/tfr.py": { + "a": 249, + "d": 113 + }, + "mne/utils/docs.py": { + "a": 12, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 24, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12911.json b/mne-python/source/doc/sphinxext/prs/12911.json new file mode 100644 index 0000000000000000000000000000000000000000..b55dbab3924ca7ac4aff14276b3f039f09f9c661 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12911.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f4597ba4d75416dbe25ab6a08df1eadf17d9ec27", + "authors": [ + { + "n": "Florian Hofer", + "e": null + } + ], + "changes": { + "doc/changes/devel/12911.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 2, + "d": 0 + }, + "mne/export/tests/test_export.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12912.json b/mne-python/source/doc/sphinxext/prs/12912.json new file mode 100644 index 0000000000000000000000000000000000000000..7b6b00fbeb8683b28488e3b867ffd72ddc8c3fbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12912.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c63da99a870c550a4eef1b57a51160b7052a3386", + "authors": [ + { + "n": "Richard Scholz", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12912.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 1, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 10, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12914.json b/mne-python/source/doc/sphinxext/prs/12914.json new file mode 100644 index 0000000000000000000000000000000000000000..bc0dd79541fed52103bd775ee8941195e4c5e7f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12914.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "0755ef01e4b0be6424e2758109bf6e7a6f41fc8e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 8, + "d": 1 + }, + "environment.yml": { + "a": 45, + "d": 51 + }, + "mne/utils/config.py": { + "a": 3, + "d": 1 + }, + "pyproject.toml": { + "a": 40, + "d": 35 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/hooks/update_environment_file.py": { + "a": 89, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12915.json b/mne-python/source/doc/sphinxext/prs/12915.json new file mode 100644 index 0000000000000000000000000000000000000000..7cd1579d31a078c7198e15bcf70da64b003169f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12915.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "92cf6f2bb72d3ae9668bd94daa9d28093671ec58", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12909.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12918.json b/mne-python/source/doc/sphinxext/prs/12918.json new file mode 100644 index 0000000000000000000000000000000000000000..a5fb64d446ac05e618ea138f2954ad6a5be77ccb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12918.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "e15292fc0bc8d5e32dd6d6099a839bf810963f3a", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/12918.apichange.rst": { + "a": 1, + "d": 0 + }, + "doc/documentation/datasets.rst": { + "a": 12, + "d": 6 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 6, + "d": 5 + }, + "examples/preprocessing/eeg_bridging.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/muscle_ica.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 55, + "d": 25 + }, + "mne/datasets/eegbci/tests/test_eegbci.py": { + "a": 16, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 3 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12920.json b/mne-python/source/doc/sphinxext/prs/12920.json new file mode 100644 index 0000000000000000000000000000000000000000..d41c1a8c642e2cab6bf298dbe467880c5d14a151 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12920.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f9ab4376906ea51da1cd38cae8bcd14cf559c154", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12924.json b/mne-python/source/doc/sphinxext/prs/12924.json new file mode 100644 index 0000000000000000000000000000000000000000..6d2d045aecdc1290b8bbbec01ab6b5006fe12823 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12924.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f00deb44e2996a3b707c3f0399cfa0d8b842c566", + "authors": [ + { + "n": "Simon M. Hofmann", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12924.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 9, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12925.json b/mne-python/source/doc/sphinxext/prs/12925.json new file mode 100644 index 0000000000000000000000000000000000000000..bec3acf2188e70421fdf7dfadce89601af98667e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12925.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "98d55b4a9e29065766c29c3453336640844096ab", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/backends/_qt.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12928.json b/mne-python/source/doc/sphinxext/prs/12928.json new file mode 100644 index 0000000000000000000000000000000000000000..b4f01d69fcb55eceb70cd9be95e8d5529bd35102 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12928.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "60346f64bce19a5657920fe63f8e1ab4a6498db0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 3, + "d": 3 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 0 + }, + "mne/stats/regression.py": { + "a": 3, + "d": 2 + }, + "mne/stats/tests/test_regression.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12931.json b/mne-python/source/doc/sphinxext/prs/12931.json new file mode 100644 index 0000000000000000000000000000000000000000..734ee4af5167e082142bfea9091082f90f05854c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12931.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "46089954167343ff2e0d089b9a313674ef7475b6", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12931.bugfix.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/devel/12931.other.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 68, + "d": 36 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12932.json b/mne-python/source/doc/sphinxext/prs/12932.json new file mode 100644 index 0000000000000000000000000000000000000000..91bf8c5fc55fd087b28a433a11f81533b71df1ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12932.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "424f0b4daaaefa96ff3fbecf0d20e2209b281755", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12933.json b/mne-python/source/doc/sphinxext/prs/12933.json new file mode 100644 index 0000000000000000000000000000000000000000..e6909e9e73f4bcebe6333e18e23dd7fd12704f52 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12933.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "de7f767c8cdc1496e56994265713bbd0e2de84af", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/io/ant/ant.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12935.json b/mne-python/source/doc/sphinxext/prs/12935.json new file mode 100644 index 0000000000000000000000000000000000000000..73389f6ffd2fa3b249ec6bf8b0c7fa9aafb73fc4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12935.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "4a61d42727997e57089722e5275bd73098205d9d", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/12872.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12877.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12879.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12880.json": { + "a": 159, + "d": 0 + }, + "doc/sphinxext/prs/12882.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12883.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12884.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/12885.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12886.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12887.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12888.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12890.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/12891.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12892.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12898.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12900.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12901.json": { + "a": 71, + "d": 0 + }, + "doc/sphinxext/prs/12902.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12908.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12909.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12911.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12912.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12914.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/12915.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12918.json": { + "a": 55, + "d": 0 + }, + "doc/sphinxext/prs/12920.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12924.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12925.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12928.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/12932.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12933.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12936.json b/mne-python/source/doc/sphinxext/prs/12936.json new file mode 100644 index 0000000000000000000000000000000000000000..4fbd5951c2c32442ceedf24c9b0c0414cc8e342f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12936.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "333d97189e9315ebbc274bbf5d5d439938b7f840", + "authors": [ + { + "n": "Genuster", + "e": null + } + ], + "changes": { + "doc/changes/devel/12936.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12937.json b/mne-python/source/doc/sphinxext/prs/12937.json new file mode 100644 index 0000000000000000000000000000000000000000..11618b8c1c9f11f94bc2ce035c97779da9da872a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12937.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ddca04beb56baa6af008b43e658ffbedac2c2228", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "tools/hooks/update_environment_file.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12938.json b/mne-python/source/doc/sphinxext/prs/12938.json new file mode 100644 index 0000000000000000000000000000000000000000..3da4cbe9b09ea5a43a7c21e7c076b82b15c144c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12938.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "899b7bf510966619a44acadf82023748e39d6529", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/viz/_scraper.py": { + "a": 4, + "d": 6 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12941.json b/mne-python/source/doc/sphinxext/prs/12941.json new file mode 100644 index 0000000000000000000000000000000000000000..0d98ac2cefbe48d3e9eecf562191c3b810287505 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12941.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b3ecaab2440668cf7237841cd8cc83c276f24075", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12942.json b/mne-python/source/doc/sphinxext/prs/12942.json new file mode 100644 index 0000000000000000000000000000000000000000..cae8206ee51b27f8ead59234e3e05e0d30285817 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12942.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c1ad98b577de30e93ac96ea99b279069fe435843", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12947.json b/mne-python/source/doc/sphinxext/prs/12947.json new file mode 100644 index 0000000000000000000000000000000000000000..f895056403c7d8f479a0c07d71fc258b8e67d6b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12947.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2983d2a19148e8760b67de399e85c91a3e040de7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/_static/js/set_installer_tab.js": { + "a": 10, + "d": 0 + }, + "doc/install/ides.rst": { + "a": 55, + "d": 0 + }, + "doc/install/index.rst": { + "a": 1, + "d": 0 + }, + "doc/install/installers.rst": { + "a": 21, + "d": 4 + }, + "doc/install/manual_install.rst": { + "a": 0, + "d": 56 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12948.json b/mne-python/source/doc/sphinxext/prs/12948.json new file mode 100644 index 0000000000000000000000000000000000000000..9c8f88baf308f668059c58c20d794d0941346d38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12948.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "649857aacb24a0afc3b069f1e75bb3cf843a8766", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1295.json b/mne-python/source/doc/sphinxext/prs/1295.json new file mode 100644 index 0000000000000000000000000000000000000000..f837bec35f8e0efdd1496929a605d8ec36ddca44 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1295.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a9e2f5fe33a03ffd181c25758ac938e925a023c7", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/surface.py": { + "a": 12, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12951.json b/mne-python/source/doc/sphinxext/prs/12951.json new file mode 100644 index 0000000000000000000000000000000000000000..5dae7e4cc909a70454c12292e2aca7399a5f0523 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12951.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "cd6dd5f4db008cdef407298e2e24014e75916693", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 11, + "d": 1 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 8, + "d": 3 + }, + "mne/decoding/search_light.py": { + "a": 16, + "d": 2 + }, + "mne/decoding/ssd.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_base.py": { + "a": 10, + "d": 1 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 12, + "d": 0 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12955.json b/mne-python/source/doc/sphinxext/prs/12955.json new file mode 100644 index 0000000000000000000000000000000000000000..dc2ee03614c881b56ceabb3997cc7f7c1fb4c07a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12955.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "060b60061f5d8226734fdb80340a2f1f53d37fd1", + "authors": [ + { + "n": "Leonardo Rochael Almeida", + "e": "leorochael@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12955.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/12955.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 3 + }, + "mne/io/base.py": { + "a": 23, + "d": 9 + }, + "mne/io/fiff/raw.py": { + "a": 4, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 36, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12957.json b/mne-python/source/doc/sphinxext/prs/12957.json new file mode 100644 index 0000000000000000000000000000000000000000..376c66f4f10777a0f9d9600b775a323726116e8a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12957.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ecc620d5919b6209bf7d76301fd9764c80fc2826", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/cov.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12958.json b/mne-python/source/doc/sphinxext/prs/12958.json new file mode 100644 index 0000000000000000000000000000000000000000..89e21215bb628fed08f256a326824bf50aa54f33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12958.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9832d4b7a9935898aa6ff6ddd0808e8b5aa3d7aa", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1296.json b/mne-python/source/doc/sphinxext/prs/1296.json new file mode 100644 index 0000000000000000000000000000000000000000..3bb58a910880e2740a3f8279f8ee7e0dcea3552e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1296.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a321f99dc2c2b32e7af04244d9fdd4f62fc660a4", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "examples/realtime/ftclient_rt_average.py": { + "a": 17, + "d": 5 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 36, + "d": 4 + }, + "mne/viz.py": { + "a": 28, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12960.json b/mne-python/source/doc/sphinxext/prs/12960.json new file mode 100644 index 0000000000000000000000000000000000000000..9184564422186b65c9a66ce90e9ecb5c921b0b15 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12960.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c3c1f2934f23bbb8409094c06576f7a470357abe", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12960.other.rst": { + "a": 1, + "d": 0 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 20, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12962.json b/mne-python/source/doc/sphinxext/prs/12962.json new file mode 100644 index 0000000000000000000000000000000000000000..eeb4d460256e4096504c2041468a29be9c663172 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12962.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1e7cef13d0e45355114a14beee68db365a91e315", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12962.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12966.json b/mne-python/source/doc/sphinxext/prs/12966.json new file mode 100644 index 0000000000000000000000000000000000000000..f3a1facee6ec7597790291f5b2a027bf94b19f57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12966.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f45b51b43bb6704e4567abc6a96ad995a58de0de", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12966.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 51, + "d": 12 + }, + "mne/preprocessing/maxwell.py": { + "a": 19, + "d": 14 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 179, + "d": 29 + }, + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12967.json b/mne-python/source/doc/sphinxext/prs/12967.json new file mode 100644 index 0000000000000000000000000000000000000000..50dd7318c05f6b8fea6893744a62c7cb110a9beb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12967.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d810cc5977f95f76c3eb82db6b7003af68bd6176", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 4, + "d": 4 + }, + "mne/_fiff/proc_history.py": { + "a": 34, + "d": 20 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 143, + "d": 56 + }, + "mne/_fiff/write.py": { + "a": 3, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 16, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12968.json b/mne-python/source/doc/sphinxext/prs/12968.json new file mode 100644 index 0000000000000000000000000000000000000000..bb6875d2c428b31aa44508b9ba02d58c99028307 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12968.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ede7f013a1b741da3fb4a565acad7a6c2e60e48e", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/devel/12968.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1297.json b/mne-python/source/doc/sphinxext/prs/1297.json new file mode 100644 index 0000000000000000000000000000000000000000..6a37d66738365955bbc4c843d593847bd1b3630c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1297.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e5a05af86da0ded5e29fd7fe44ff8dd2a9711387", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 17, + "d": 3 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12970.json b/mne-python/source/doc/sphinxext/prs/12970.json new file mode 100644 index 0000000000000000000000000000000000000000..90499062257bb722ed4d68dca74f8b7c3b1c225e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12970.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a267b8622587e32f992bb4c876a0f3a32d397b14", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12971.json b/mne-python/source/doc/sphinxext/prs/12971.json new file mode 100644 index 0000000000000000000000000000000000000000..fb6fe3789ff063f86bd540af9086705cbc5481a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12971.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "aa9dcb646d71f5b6fbee02a6bba12dcbe0ebeb60", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/12971.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/_eeglab.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12972.json b/mne-python/source/doc/sphinxext/prs/12972.json new file mode 100644 index 0000000000000000000000000000000000000000..67025bb3dbd71344c78321bb5a88705a5200aef7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12972.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cf8047f80fe1c674eeb6ce6a0e494e568eb585fb", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12973.json b/mne-python/source/doc/sphinxext/prs/12973.json new file mode 100644 index 0000000000000000000000000000000000000000..9585ba745a8f9cdc9ed1fa18919f56965cd0fefe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12973.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5a1f3a0966b3b941b7e70e4f6dc5df9bbf844f6e", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12975.json b/mne-python/source/doc/sphinxext/prs/12975.json new file mode 100644 index 0000000000000000000000000000000000000000..6a1532a6dd62fb85d80984077ededdaed4df02d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12975.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "eac719920b66ec854e818560854b6d9ea9fa5e80", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12976.json b/mne-python/source/doc/sphinxext/prs/12976.json new file mode 100644 index 0000000000000000000000000000000000000000..5cb40dac7cfe1a75aabc2deb7a2f714b933af0a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12976.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a99aa9f798d878ba144b3f6f3127311841d5d2b5", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/related_software.py": { + "a": 4, + "d": 4 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12978.json b/mne-python/source/doc/sphinxext/prs/12978.json new file mode 100644 index 0000000000000000000000000000000000000000..26f750a13486a8ff1b4e969d44c27cc59dbaef83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12978.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "149453c569645b5cf29103f1dc0e54e5286ce23d", + "authors": [ + { + "n": "Jacob", + "e": "jacob.phelan.jp@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12978.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12983.json b/mne-python/source/doc/sphinxext/prs/12983.json new file mode 100644 index 0000000000000000000000000000000000000000..abb29eec03f9eb60d4e6c963aca71a98371ddf3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12983.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f5d043a34e3dda3c83401a68d5722c1c664dc925", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/decoding/transformer.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12984.json b/mne-python/source/doc/sphinxext/prs/12984.json new file mode 100644 index 0000000000000000000000000000000000000000..3d0d3692a9bd40a31793539e50edaaf9a3f9ce39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12984.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "57076c91ff9e8d49e8119648c9ac38fa5f8b38d7", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/_fiff/reference.py": { + "a": 8, + "d": 11 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12986.json b/mne-python/source/doc/sphinxext/prs/12986.json new file mode 100644 index 0000000000000000000000000000000000000000..1b6ef2f21167a9e3047f919bc0af734340948ca0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12986.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "98f9949ce867a9247a14c508f51fadeb991d4618", + "authors": [ + { + "n": "ZIYI ZENG", + "e": "ziyizeng@link.cuhk.edu.cn" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/12986.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12988.json b/mne-python/source/doc/sphinxext/prs/12988.json new file mode 100644 index 0000000000000000000000000000000000000000..d9dd345caf4c66c0ae0a39d3dcf280b71b9d89b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12988.json @@ -0,0 +1,231 @@ +{ + "merge_commit_sha": "535b401eee7c8c1ce5ce79d99a754af8a374c0fc", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "doc/sphinxext/contrib_avatars.py": { + "a": 2, + "d": 1 + }, + "mne/_fiff/matrix.py": { + "a": 3, + "d": 4 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 2, + "d": 2 + }, + "mne/_ola.py": { + "a": 3, + "d": 9 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 5 + }, + "mne/channels/layout.py": { + "a": 6, + "d": 11 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 10, + "d": 10 + }, + "mne/cov.py": { + "a": 28, + "d": 25 + }, + "mne/datasets/utils.py": { + "a": 5, + "d": 2 + }, + "mne/decoding/ssd.py": { + "a": 6, + "d": 8 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 6, + "d": 4 + }, + "mne/event.py": { + "a": 11, + "d": 13 + }, + "mne/filter.py": { + "a": 15, + "d": 9 + }, + "mne/forward/_field_interpolation.py": { + "a": 7, + "d": 4 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 25, + "d": 23 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 32, + "d": 23 + }, + "mne/io/array/array.py": { + "a": 5, + "d": 7 + }, + "mne/io/base.py": { + "a": 8, + "d": 8 + }, + "mne/io/bti/bti.py": { + "a": 8, + "d": 9 + }, + "mne/io/ctf/ctf.py": { + "a": 13, + "d": 7 + }, + "mne/io/ctf/info.py": { + "a": 5, + "d": 5 + }, + "mne/io/egi/egimff.py": { + "a": 4, + "d": 4 + }, + "mne/io/egi/general.py": { + "a": 3, + "d": 2 + }, + "mne/io/fiff/raw.py": { + "a": 5, + "d": 7 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 14, + "d": 15 + }, + "mne/label.py": { + "a": 32, + "d": 31 + }, + "mne/minimum_norm/inverse.py": { + "a": 18, + "d": 25 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 5, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 18, + "d": 11 + }, + "mne/preprocessing/ica.py": { + "a": 14, + "d": 16 + }, + "mne/preprocessing/infomax_.py": { + "a": 5, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 21, + "d": 21 + }, + "mne/preprocessing/xdawn.py": { + "a": 4, + "d": 4 + }, + "mne/rank.py": { + "a": 10, + "d": 6 + }, + "mne/simulation/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 18, + "d": 21 + }, + "mne/source_space/_source_space.py": { + "a": 35, + "d": 24 + }, + "mne/stats/cluster_level.py": { + "a": 13, + "d": 7 + }, + "mne/surface.py": { + "a": 14, + "d": 11 + }, + "mne/tests/test_line_endings.py": { + "a": 2, + "d": 4 + }, + "mne/transforms.py": { + "a": 5, + "d": 3 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 3, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1299.json b/mne-python/source/doc/sphinxext/prs/1299.json new file mode 100644 index 0000000000000000000000000000000000000000..6ffd2bdd25663191ed64e0ce87c573d163126d19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1299.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "86a5d10f164856d7afe3a97e17bb8974d2668ece", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12991.json b/mne-python/source/doc/sphinxext/prs/12991.json new file mode 100644 index 0000000000000000000000000000000000000000..e309a6df7c4b1ec4adaf207d657660dc28e24970 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12991.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e06873d4d6e0a84bbd7d6b4a01ae4af340c7bedd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 2 + }, + "tools/install_pre_requirements.sh": { + "a": 6, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12995.json b/mne-python/source/doc/sphinxext/prs/12995.json new file mode 100644 index 0000000000000000000000000000000000000000..48d967dc7ebecc7b1ff9ec2c8a8ad19ceee751f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12995.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d987c2793148eb855e04e3ae9d4871e486d01e46", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12996.json b/mne-python/source/doc/sphinxext/prs/12996.json new file mode 100644 index 0000000000000000000000000000000000000000..b931ebcc541a90a24550c69f232299011a287a32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12996.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "ec77e7c36ce4a2d7897122513395b0e2418ea151", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/ant/ant.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12997.json b/mne-python/source/doc/sphinxext/prs/12997.json new file mode 100644 index 0000000000000000000000000000000000000000..7df9ddfa26bb1f9ea024f2393789dc3ac86e59b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12997.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0e09163e80013a426d419bda0c560ff3d48209bb", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "tutorials/forward/35_eeg_no_mri.py": { + "a": 9, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12998.json b/mne-python/source/doc/sphinxext/prs/12998.json new file mode 100644 index 0000000000000000000000000000000000000000..289620794a279b12156e821402822ec284a28d26 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12998.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "096243fe43c936587190a8e9e8e86b155446800e", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/12931.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12935.json": { + "a": 135, + "d": 0 + }, + "doc/sphinxext/prs/12936.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12937.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12938.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12941.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12942.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12947.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12948.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12951.json": { + "a": 59, + "d": 0 + }, + "doc/sphinxext/prs/12955.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/12957.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12958.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12960.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12962.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12966.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12967.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/12968.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12970.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12971.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12972.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12973.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12975.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12976.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12978.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/12983.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12984.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/12986.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12988.json": { + "a": 231, + "d": 0 + }, + "doc/sphinxext/prs/12991.json": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/12999.json b/mne-python/source/doc/sphinxext/prs/12999.json new file mode 100644 index 0000000000000000000000000000000000000000..4c71e401c33efbc6484fe889aea3cfbd398eddb9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/12999.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ed2fd8da1e16e449cdfe779491542fecad6ecbcb", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/autofix.yml": { + "a": 1, + "d": 1 + }, + ".mailmap": { + "a": 3, + "d": 0 + }, + "doc/sphinxext/credit_tools.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13.json b/mne-python/source/doc/sphinxext/prs/13.json new file mode 100644 index 0000000000000000000000000000000000000000..dd33542d93469c24cf7889eb04c045fe53f187bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cedb560fe02feeaae4e35113b9305d43b0bb2a79", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 80, + "d": 0 + }, + "mne/stats/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/stats/multi_comp.py": { + "a": 98, + "d": 0 + }, + "mne/stats/tests/test_multi_comp.py": { + "a": 36, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13000.json b/mne-python/source/doc/sphinxext/prs/13000.json new file mode 100644 index 0000000000000000000000000000000000000000..d813ea985605ad8e7723de60b5d81337b21370e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13000.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "53792b12a2d60229ada3c946987a184f3915c535", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 0, + "d": 2 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13001.json b/mne-python/source/doc/sphinxext/prs/13001.json new file mode 100644 index 0000000000000000000000000000000000000000..032c9a5714f8a409f1343a6dfb0ebee095059f19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13001.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b19ac58598f55975ca7f6458fa7bfa7d21e00ae0", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13003.json b/mne-python/source/doc/sphinxext/prs/13003.json new file mode 100644 index 0000000000000000000000000000000000000000..cda225124fa866370519bfc3981eef82a318c7bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13003.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "7071a0e24e121b28c851565f2e64a0128941e83a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/13003.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/_digitization.py": { + "a": 24, + "d": 5 + }, + "mne/_fiff/write.py": { + "a": 5, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 36, + "d": 12 + }, + "mne/channels/tests/test_montage.py": { + "a": 33, + "d": 14 + }, + "mne/viz/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13007.json b/mne-python/source/doc/sphinxext/prs/13007.json new file mode 100644 index 0000000000000000000000000000000000000000..7553cfa048b6bd6ef1ac88e5c95c6ebf31e7414e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13007.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d47c22fc2ba21d31b46ae7816eba054d5e13add9", + "authors": [ + { + "n": "Jacob Woessner", + "e": "Woessner.jacob@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13007.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 19, + "d": 3 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13009.json b/mne-python/source/doc/sphinxext/prs/13009.json new file mode 100644 index 0000000000000000000000000000000000000000..ecf5894f4897fefca2a432672cded570e9437335 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13009.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "391fd88dca91bca78aeacc996fa284712c3ea33b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/mne_doc_utils.py": { + "a": 22, + "d": 0 + }, + "examples/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1301.json b/mne-python/source/doc/sphinxext/prs/1301.json new file mode 100644 index 0000000000000000000000000000000000000000..c67efbf240f1da35939fa2b8afc512707baf497e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1301.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6ae6fe0af7cc3e7621a559077039049f6dd7918a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 0 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 11, + "d": 23 + }, + "mne/evoked.py": { + "a": 16, + "d": 5 + }, + "mne/tests/test_viz.py": { + "a": 5, + "d": 2 + }, + "mne/viz.py": { + "a": 71, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13010.json b/mne-python/source/doc/sphinxext/prs/13010.json new file mode 100644 index 0000000000000000000000000000000000000000..4f4b88a5406c523f2abf4afae435f1bd83cf0b64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13010.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4967ecd3f44968408046948b738977aa41521ea2", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/api/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/__init__.pyi": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13011.json b/mne-python/source/doc/sphinxext/prs/13011.json new file mode 100644 index 0000000000000000000000000000000000000000..ab057c0e83cc26147812ae80bf54000b6ed5b8cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13011.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "b329515933915fd077495ea41de876119ac04c97", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Thomas Grainger", + "e": "tagrain@gmail.com" + } + ], + "changes": { + ".github/workflows/autofix.yml": { + "a": 2, + "d": 0 + }, + ".github/workflows/codeql-analysis.yml": { + "a": 5, + "d": 3 + }, + ".github/workflows/credit.yml": { + "a": 6, + "d": 5 + }, + ".github/workflows/release.yml": { + "a": 2, + "d": 0 + }, + ".github/workflows/tests.yml": { + "a": 3, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 5, + "d": 0 + }, + "doc/changes/devel/13011.other.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13012.json b/mne-python/source/doc/sphinxext/prs/13012.json new file mode 100644 index 0000000000000000000000000000000000000000..066940ab6f5099969333e9ddfbe5398894fdb04e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13012.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9b7b5596ff7c089939bca179b98f1ce0094cb668", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13012.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/install/advanced.rst": { + "a": 14, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 8, + "d": 5 + }, + "mne/viz/backends/_qt.py": { + "a": 0, + "d": 1 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 12, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13015.json b/mne-python/source/doc/sphinxext/prs/13015.json new file mode 100644 index 0000000000000000000000000000000000000000..5b1371627594367e02fd3518e0e84985b8ef0c6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13015.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "31436fecd881a0e6fb29b83b4f36764ae81dabc7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/automerge.yml": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13017.json b/mne-python/source/doc/sphinxext/prs/13017.json new file mode 100644 index 0000000000000000000000000000000000000000..49b2ec0202b08a40aee9c2ea9522e2833e55ff82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13017.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b3eb56cf1e8993940daa1df68d5220f3110ecdbb", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13018.json b/mne-python/source/doc/sphinxext/prs/13018.json new file mode 100644 index 0000000000000000000000000000000000000000..ef9951d99029f0c853b588a5fe77c9a1b0b6d69b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13018.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "521d667f9802655a71166823fd890fbd00bae5a8", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13018.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/related_software.py": { + "a": 4, + "d": 0 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 65, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13019.json b/mne-python/source/doc/sphinxext/prs/13019.json new file mode 100644 index 0000000000000000000000000000000000000000..0d6677670c2db95f14f02744c2b9c974c82ba9e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13019.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4f1f4bbbc1a9d0f828e28de9be4e69c05f86d9f5", + "authors": [ + { + "n": "Santeri Ruuskanen", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13019.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/circle.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_circle.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13020.json b/mne-python/source/doc/sphinxext/prs/13020.json new file mode 100644 index 0000000000000000000000000000000000000000..5513e4c61537c9260357fc4fd032620fd332f9a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13020.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "730358c1e2e17baf0491c04e0c8269382a29c613", + "authors": [ + { + "n": "Santeri Ruuskanen", + "e": null + } + ], + "changes": { + "doc/development/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13021.json b/mne-python/source/doc/sphinxext/prs/13021.json new file mode 100644 index 0000000000000000000000000000000000000000..1d9a78d45cc607e7b651341eb9b22974978b66f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13021.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "bd4a160215be67e2de1df7e0a86e27425b074807", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 3, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 1 + }, + "doc/changes/devel/13021.dependency.rst": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 33, + "d": 22 + }, + "mne/utils/tests/test_config.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_docs.py": { + "a": 16, + "d": 15 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 5, + "d": 0 + }, + "tools/github_actions_env_vars.sh": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13024.json b/mne-python/source/doc/sphinxext/prs/13024.json new file mode 100644 index 0000000000000000000000000000000000000000..4feede48648fbd25e17762727500db775827c777 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13024.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a5bf268a1a8645a6b4addc467dec70eb0ec26ce3", + "authors": [ + { + "n": "Victor Férat", + "e": "victor.ferat@live.Fr" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13024.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 61, + "d": 29 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 8, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 102, + "d": 24 + }, + "mne/tests/test_bem.py": { + "a": 25, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13028.json b/mne-python/source/doc/sphinxext/prs/13028.json new file mode 100644 index 0000000000000000000000000000000000000000..7a162141000be901090f9317e278fedf519123f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13028.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d8149546e7010ee7d2b5a95335aeed0e9b202aaa", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/devel/13028.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 16, + "d": 12 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13029.json b/mne-python/source/doc/sphinxext/prs/13029.json new file mode 100644 index 0000000000000000000000000000000000000000..33a84c3f2c68488def32ed49f9af37787e7a06bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13029.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "f3a7fde522d69bc5bbc15844718812c7ab6480f4", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/12896.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/12995.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12996.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/12997.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/12998.json": { + "a": 131, + "d": 0 + }, + "doc/sphinxext/prs/12999.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13000.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13001.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13003.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13007.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13009.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13010.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13011.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13012.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13015.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13017.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13018.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13019.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13020.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13021.json": { + "a": 59, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13031.json b/mne-python/source/doc/sphinxext/prs/13031.json new file mode 100644 index 0000000000000000000000000000000000000000..428346e1b90f046e8cdd4e401cf3499ad63209f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13031.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5b06ca4bb8f9138bf4af85ea3171d95df07462c5", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/credit.yml": { + "a": 2, + "d": 2 + }, + "doc/documentation/cited.rst": { + "a": 3, + "d": 3 + }, + "doc/sphinxext/prs/13029.json": { + "a": 91, + "d": 0 + }, + "doc/sphinxext/prs/6915.json": { + "a": 43, + "d": 0 + }, + "tools/dev/update_credit_json.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13032.json b/mne-python/source/doc/sphinxext/prs/13032.json new file mode 100644 index 0000000000000000000000000000000000000000..041aa7dfe1b558ae7d726bae896eb589e0e76245 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13032.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b38385ef90d0fd8214d54b15c5fd91333c3bc032", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13035.json b/mne-python/source/doc/sphinxext/prs/13035.json new file mode 100644 index 0000000000000000000000000000000000000000..e9cf38b09c9e4fc80697141ffbdced48db152cb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13035.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "dcd26258c5fd83fd3974d73ba2b1e2773c33bc3d", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/io/ant/ant.py": { + "a": 14, + "d": 12 + }, + "mne/io/ant/tests/test_ant.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 23, + "d": 24 + }, + "mne/utils/tests/test_check.py": { + "a": 7, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 6 + }, + "tutorials/intro/70_report.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13036.json b/mne-python/source/doc/sphinxext/prs/13036.json new file mode 100644 index 0000000000000000000000000000000000000000..6ce98904756fc15f5fa28b3b77ad76e2b0fb618a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13036.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "41dbdd55eaff77314440ebc8700e0e58b1183113", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13036.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 26, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13037.json b/mne-python/source/doc/sphinxext/prs/13037.json new file mode 100644 index 0000000000000000000000000000000000000000..7de2d953e82130ba33fc66226227305d2515e427 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13037.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "4f53a3732917dd1dbc91d4725ae79fc1c7ad4661", + "authors": [ + { + "n": "Steinn Hauser Magnússon", + "e": null + }, + { + "n": "Emma Bailey", + "e": "bailey@cbs.mpg.de" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Steinn Magnusson", + "e": "s.magnusson@senec.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "emma-bailey", + "e": "93327939+emma-bailey@users.noreply.github.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 8, + "d": 1 + }, + "doc/api/datasets.rst": { + "a": 1, + "d": 0 + }, + "doc/api/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/13037.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "examples/preprocessing/esg_rm_heart_artefact_pcaobs.py": { + "a": 196, + "d": 0 + }, + "mne/datasets/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 29, + "d": 1 + }, + "mne/preprocessing/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/_pca_obs.py": { + "a": 333, + "d": 0 + }, + "mne/preprocessing/tests/test_pca_obs.py": { + "a": 107, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13038.json b/mne-python/source/doc/sphinxext/prs/13038.json new file mode 100644 index 0000000000000000000000000000000000000000..c988969d1dd9324f9c81ac8c50135d46bf60f326 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13038.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "14938b9657b255a38aa96482a4aaf410e8865859", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 2 + }, + "doc/sphinxext/prs/13031.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13032.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13035.json": { + "a": 51, + "d": 0 + }, + "doc/sphinxext/prs/13036.json": { + "a": 27, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 3, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 0, + "d": 1 + }, + "tools/hooks/update_environment_file.py": { + "a": 0, + "d": 3 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13040.json b/mne-python/source/doc/sphinxext/prs/13040.json new file mode 100644 index 0000000000000000000000000000000000000000..97a70ab4a3281012fd4a49d53921a1ac9b1707a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13040.json @@ -0,0 +1,171 @@ +{ + "merge_commit_sha": "637c231f40d8e6e022ab3ae04fa30911cbe0f78f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 4, + "d": 4 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_flash_bem.py": { + "a": 0, + "d": 20 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 2 + }, + "mne/conftest.py": { + "a": 5, + "d": 14 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 3, + "d": 23 + }, + "mne/datasets/eegbci/tests/test_eegbci.py": { + "a": 0, + "d": 12 + }, + "mne/decoding/csp.py": { + "a": 0, + "d": 13 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_base.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 2, + "d": 6 + }, + "mne/io/base.py": { + "a": 1, + "d": 18 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 0, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 0, + "d": 8 + }, + "mne/io/neuralynx/neuralynx.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 0, + "d": 16 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 0, + "d": 50 + }, + "mne/utils/linalg.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 5 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 3 + }, + "mne/viz/backends/_qt.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 0, + "d": 44 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 0, + "d": 2 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 3, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/montage.py": { + "a": 4, + "d": 20 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 5 + }, + "pyproject.toml": { + "a": 4, + "d": 4 + }, + "tools/dev/Makefile": { + "a": 3, + "d": 0 + }, + "tools/environment_old.yml": { + "a": 10, + "d": 9 + }, + "tools/hooks/sync_dependencies.py": { + "a": 11, + "d": 1 + }, + "tools/hooks/update_environment_file.py": { + "a": 37, + "d": 7 + }, + "tools/vulture_allowlist.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13041.json b/mne-python/source/doc/sphinxext/prs/13041.json new file mode 100644 index 0000000000000000000000000000000000000000..26790d0e3523fd09fdc840c95310fba3bc4abf74 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13041.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "90d9c91fe5d46e0390cb22c943fd6e0dbb578838", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/_acquisition.html.jinja": { + "a": 1, + "d": 1 + }, + "mne/html_templates/repr/_frequencies.html.jinja": { + "a": 62, + "d": 0 + }, + "mne/html_templates/repr/spectrum.html.jinja": { + "a": 9, + "d": 48 + }, + "mne/time_frequency/spectrum.py": { + "a": 3, + "d": 1 + }, + "tools/hooks/sync_dependencies.py": { + "a": 1, + "d": 2 + }, + "tutorials/time-freq/10_spectrum_class.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13042.json b/mne-python/source/doc/sphinxext/prs/13042.json new file mode 100644 index 0000000000000000000000000000000000000000..5f2d05f70130d5ea97106da8062b6bc0241b42fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13042.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ee2d0caa98b23fe40bcddea2a666b6803f64c3dd", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13042.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13043.json b/mne-python/source/doc/sphinxext/prs/13043.json new file mode 100644 index 0000000000000000000000000000000000000000..a67a958fa80e3910bc5f7a2068c0e6739b984e3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13043.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a51e32a9341bd1b44183356f6116af0821546fda", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13044.json b/mne-python/source/doc/sphinxext/prs/13044.json new file mode 100644 index 0000000000000000000000000000000000000000..0619fccfb98bde1ee4c0d388e3628d06f2d1affa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13044.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "7b316cb500a5039a9e79ada02f117f650801d17b", + "authors": [ + { + "n": "Antoine Collas", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13044.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 8, + "d": 0 + }, + "examples/preprocessing/interpolate_to.py": { + "a": 81, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 157, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 83, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13045.json b/mne-python/source/doc/sphinxext/prs/13045.json new file mode 100644 index 0000000000000000000000000000000000000000..cb3db89fefd1e5312c70dfce98074f40219b910d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13045.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fd8c1eed5209393e6a2527342b61354efcb813ee", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/13028.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13038.json": { + "a": 63, + "d": 0 + }, + "doc/sphinxext/prs/13040.json": { + "a": 171, + "d": 0 + }, + "doc/sphinxext/prs/13041.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/13042.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13043.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13046.json b/mne-python/source/doc/sphinxext/prs/13046.json new file mode 100644 index 0000000000000000000000000000000000000000..f946cb5a90a89ca24222920a960060c413460c73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13046.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d81b7a66b692cfc3065ba260f4702f842d45e414", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/v1.7.rst": { + "a": 4, + "d": 4 + }, + "doc/changes/v1.9.rst": { + "a": 4, + "d": 4 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13047.json b/mne-python/source/doc/sphinxext/prs/13047.json new file mode 100644 index 0000000000000000000000000000000000000000..9267f7fada0146bbbb724c90aa1637c193b0e14c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13047.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "47ea36043076e4e38896eda6241c6cb0d4c25938", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13048.json b/mne-python/source/doc/sphinxext/prs/13048.json new file mode 100644 index 0000000000000000000000000000000000000000..a111abed437fb25a0875794d1a87c47f26de37a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13048.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6bc7dfb3535ef954b7a6fcbad93887abe2aa7c92", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13048.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked_field.py": { + "a": 30, + "d": 39 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13049.json b/mne-python/source/doc/sphinxext/prs/13049.json new file mode 100644 index 0000000000000000000000000000000000000000..f66fcc1b6188a4d4d941c69226af706101f78f5f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13049.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "df350211b9177a26a2c5fe1e76ebc8e9d6cb4d99", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 9, + "d": 11 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "doc/development/contributing.rst": { + "a": 1, + "d": 1 + }, + "doc/install/installers.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 6, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 5, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 4, + "d": 4 + }, + "mne/export/tests/test_export.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 13, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/transforms.py": { + "a": 2, + "d": 3 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/hooks/update_environment_file.py": { + "a": 8, + "d": 38 + }, + "tools/install_pre_requirements.sh": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13051.json b/mne-python/source/doc/sphinxext/prs/13051.json new file mode 100644 index 0000000000000000000000000000000000000000..8a9acb2b2868e6fb359723a31a9fb50d8a0c0670 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13051.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5fec4e024a963c3f628693ab172d5b77cbafe6db", + "authors": [ + { + "n": "Simon Kern", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 15, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13053.json b/mne-python/source/doc/sphinxext/prs/13053.json new file mode 100644 index 0000000000000000000000000000000000000000..fc85ba79c3d5f81cb895882904c25dfb5a78829c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13053.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "dedb3921b0ebadcc5a630234530604706c6faddd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 7, + "d": 6 + }, + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "azure-pipelines.yml": { + "a": 10, + "d": 13 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 54, + "d": 3 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_parallel.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 0, + "d": 8 + }, + "mne/viz/tests/test_evoked.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 4 + }, + "pyproject.toml": { + "a": 0, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 0 + }, + "tools/get_minimal_commands.sh": { + "a": 5, + "d": 5 + }, + "tools/get_testing_version.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_env_vars.sh": { + "a": 16, + "d": 12 + }, + "tools/github_actions_test.sh": { + "a": 15, + "d": 9 + }, + "tools/hooks/update_environment_file.py": { + "a": 3, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 6, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13054.json b/mne-python/source/doc/sphinxext/prs/13054.json new file mode 100644 index 0000000000000000000000000000000000000000..3d8a7b9f99f6981d21f3e8ae0c2db1b477a22d70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13054.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2ae61edccb2af5b5f9f3a89a3131499b5c229c27", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/api/time_frequency.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/13054.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13056.json b/mne-python/source/doc/sphinxext/prs/13056.json new file mode 100644 index 0000000000000000000000000000000000000000..94aa0bd39b6a24fff3438642bb1dfd63a7dc37a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13056.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2abb7b220ed2580e141158499919300cfa1f6a3b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13056.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 11, + "d": 4 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 30, + "d": 18 + }, + "mne/_fiff/write.py": { + "a": 5, + "d": 4 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13058.json b/mne-python/source/doc/sphinxext/prs/13058.json new file mode 100644 index 0000000000000000000000000000000000000000..ef7ec02786e4724a1e1d1a5a0d36e050c19bba93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13058.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "f82d3993617d2a34744eb955385448c67672d6ec", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/api/time_frequency.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/13058.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 68, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 54, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 6 + }, + "mne/utils/numerics.py": { + "a": 33, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1306.json b/mne-python/source/doc/sphinxext/prs/1306.json new file mode 100644 index 0000000000000000000000000000000000000000..305057a5186599c1ac29b8225481312c8fce828c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1306.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f848f2cb86b0d20c4256a388622654a8addb526c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/channels.py": { + "a": 81, + "d": 0 + }, + "mne/io/tests/test_channels.py": { + "a": 45, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13060.json b/mne-python/source/doc/sphinxext/prs/13060.json new file mode 100644 index 0000000000000000000000000000000000000000..67c9ee551154584ea327d6cecba11d6c67959fe6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13060.json @@ -0,0 +1,423 @@ +{ + "merge_commit_sha": "d472c268cb39fb6e4bf0dad24c802b17efdd4a33", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/credit_tools.py": { + "a": 4, + "d": 4 + }, + "doc/sphinxext/related_software.py": { + "a": 3, + "d": 3 + }, + "doc/sphinxext/unit_role.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/vector_mne_solution.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/evoked_whitening.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/_digitization.py": { + "a": 1, + "d": 2 + }, + "mne/_fiff/meas_info.py": { + "a": 3, + "d": 4 + }, + "mne/_fiff/proj.py": { + "a": 7, + "d": 9 + }, + "mne/_fiff/reference.py": { + "a": 3, + "d": 3 + }, + "mne/_fiff/tag.py": { + "a": 1, + "d": 2 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_pick.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 5, + "d": 5 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 6, + "d": 8 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 6 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 1, + "d": 2 + }, + "mne/coreg.py": { + "a": 3, + "d": 6 + }, + "mne/cov.py": { + "a": 5, + "d": 5 + }, + "mne/datasets/_fetch.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/config.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 1, + "d": 4 + }, + "mne/epochs.py": { + "a": 6, + "d": 10 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 5, + "d": 7 + }, + "mne/export/_egimff.py": { + "a": 1, + "d": 1 + }, + "mne/export/_export.py": { + "a": 1, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 2, + "d": 3 + }, + "mne/forward/_field_interpolation.py": { + "a": 2, + "d": 3 + }, + "mne/forward/_make_forward.py": { + "a": 5, + "d": 6 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 7 + }, + "mne/gui/_coreg.py": { + "a": 2, + "d": 4 + }, + "mne/html_templates/_templates.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/_array.py": { + "a": 0, + "d": 0 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 3, + "d": 3 + }, + "mne/io/base.py": { + "a": 2, + "d": 3 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 1, + "d": 1 + }, + "mne/io/fil/tests/test_fil.py": { + "a": 9, + "d": 9 + }, + "mne/io/neuralynx/tests/test_neuralynx.py": { + "a": 6, + "d": 6 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 5, + "d": 9 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 2 + }, + "mne/morph.py": { + "a": 3, + "d": 6 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/hfc.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 8, + "d": 10 + }, + "mne/preprocessing/ieeg/_volume.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 2 + }, + "mne/report/report.py": { + "a": 7, + "d": 10 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 5 + }, + "mne/source_space/_source_space.py": { + "a": 4, + "d": 6 + }, + "mne/surface.py": { + "a": 8, + "d": 9 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_filter.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/_stft.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/csd.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/spectrum.py": { + "a": 9, + "d": 9 + }, + "mne/time_frequency/tfr.py": { + "a": 11, + "d": 12 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 5, + "d": 8 + }, + "mne/utils/config.py": { + "a": 6, + "d": 8 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 6 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 6, + "d": 6 + }, + "mne/viz/_proj.py": { + "a": 1, + "d": 2 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 3 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 9 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tools/dev/ensure_headers.py": { + "a": 6, + "d": 6 + }, + "tools/hooks/update_environment_file.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 2, + "d": 2 + }, + "tutorials/forward/30_forward.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/15_inplace.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 1, + "d": 2 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13061.json b/mne-python/source/doc/sphinxext/prs/13061.json new file mode 100644 index 0000000000000000000000000000000000000000..62ddd1e87e9482d012c161fb919f41067f407568 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13061.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9ef5c23927e377d0a66169185f394297ea29d7b4", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13056.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 11, + "d": 4 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 30, + "d": 18 + }, + "mne/_fiff/write.py": { + "a": 5, + "d": 4 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13062.json b/mne-python/source/doc/sphinxext/prs/13062.json new file mode 100644 index 0000000000000000000000000000000000000000..4160927b960b8d66ab5128d63c820737678d15d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13062.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c0da91db9098b92ec3c20d8c0e237d0e02683865", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/13062.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 9, + "d": 6 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13063.json b/mne-python/source/doc/sphinxext/prs/13063.json new file mode 100644 index 0000000000000000000000000000000000000000..77684e67814f0505d4b85af01dd995b8d1b019a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13063.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "087779c3bd5ba84dbcef7f3689a7d70f0b045da7", + "authors": [ + { + "n": "Santeri Ruuskanen", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13063.bugfix.rst": { + "a": 1, + "d": 0 + }, + "examples/visualization/evoked_topomap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 11, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 24, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13064.json b/mne-python/source/doc/sphinxext/prs/13064.json new file mode 100644 index 0000000000000000000000000000000000000000..c18116b1cd1f5e2f3afd0f5a759de37a494479f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13064.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "672bdf4357f815c63dfab91d9c8e257266bceb21", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/13062.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 9, + "d": 6 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13065.json b/mne-python/source/doc/sphinxext/prs/13065.json new file mode 100644 index 0000000000000000000000000000000000000000..071c98cd26fce1e7e3477b9e97f9e99b8be1b791 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13065.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "5f2b7f1a33d42c5a110f67e098f9efcf92be7fff", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/13065.bugfix.rst": { + "a": 7, + "d": 0 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/base.py": { + "a": 8, + "d": 3 + }, + "mne/decoding/csp.py": { + "a": 43, + "d": 56 + }, + "mne/decoding/ems.py": { + "a": 19, + "d": 6 + }, + "mne/decoding/search_light.py": { + "a": 56, + "d": 25 + }, + "mne/decoding/ssd.py": { + "a": 75, + "d": 63 + }, + "mne/decoding/tests/test_base.py": { + "a": 10, + "d": 4 + }, + "mne/decoding/tests/test_csp.py": { + "a": 31, + "d": 15 + }, + "mne/decoding/tests/test_ems.py": { + "a": 7, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 15, + "d": 15 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 44, + "d": 10 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 17, + "d": 6 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 71, + "d": 17 + }, + "mne/decoding/time_frequency.py": { + "a": 23, + "d": 9 + }, + "mne/decoding/transformer.py": { + "a": 127, + "d": 113 + }, + "mne/time_frequency/multitaper.py": { + "a": 8, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 2 + }, + "tools/vulture_allowlist.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13067.json b/mne-python/source/doc/sphinxext/prs/13067.json new file mode 100644 index 0000000000000000000000000000000000000000..e9a5c0338f2cc7df90b4cdf7989bfee0cc7df0c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13067.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8b9fc973e0bdaca9a5ba0c9333637722ed323633", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13067.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 12, + "d": 7 + }, + "mne/time_frequency/tfr.py": { + "a": 26, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13068.json b/mne-python/source/doc/sphinxext/prs/13068.json new file mode 100644 index 0000000000000000000000000000000000000000..832e45542e83bd20351c0703f3621f7af1625379 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13068.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b259e590401b9743e09fcf41ffb97c0f3ab56342", + "authors": [ + { + "n": "Beige Jerry Jin", + "e": null + } + ], + "changes": { + "doc/changes/dev/13068.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13069.json b/mne-python/source/doc/sphinxext/prs/13069.json new file mode 100644 index 0000000000000000000000000000000000000000..05319605699a055363d741be123b27830e3ca9d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13069.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "bd8c318537ffcabf4c5fadd4347ec5068bb91b67", + "authors": [ + { + "n": "Simon Kern", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13069.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 6, + "d": 3 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1307.json b/mne-python/source/doc/sphinxext/prs/1307.json new file mode 100644 index 0000000000000000000000000000000000000000..f89e4d228df2a443951878455fc8cc5aae676f86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1307.json @@ -0,0 +1,195 @@ +{ + "merge_commit_sha": "22b49010f1e479b3761f09483ae01e3830ee0fd0", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 9, + "d": 4 + }, + "mne/epochs.py": { + "a": 8, + "d": 3 + }, + "mne/event.py": { + "a": 7, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 11, + "d": 7 + }, + "mne/forward/tests/test_forward.py": { + "a": 11, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 8, + "d": 6 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 8, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 5, + "d": 5 + }, + "mne/io/bti/tests/data/exported4D_linux_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/exported4D_solaris_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/cov.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/evoked.py": { + "a": 7, + "d": 3 + }, + "mne/io/fiff/raw.py": { + "a": 7, + "d": 2 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 11, + "d": 3 + }, + "mne/io/kit/tests/data/test_bin_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 4, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/io/proj.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/data/test-1-eve.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-proj.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-proj.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_compensator.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_evoked.py": { + "a": 24, + "d": 16 + }, + "mne/layouts/tests/test_layout.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 13, + "d": 9 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 8, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 9, + "d": 4 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 18, + "d": 9 + }, + "mne/proj.py": { + "a": 11, + "d": 5 + }, + "mne/source_space.py": { + "a": 14, + "d": 7 + }, + "mne/tests/test_cov.py": { + "a": 18, + "d": 9 + }, + "mne/tests/test_epochs.py": { + "a": 22, + "d": 10 + }, + "mne/tests/test_event.py": { + "a": 22, + "d": 11 + }, + "mne/tests/test_label.py": { + "a": 5, + "d": 3 + }, + "mne/tests/test_proj.py": { + "a": 26, + "d": 8 + }, + "mne/tests/test_source_estimate.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 17, + "d": 4 + }, + "mne/tests/test_surface.py": { + "a": 3, + "d": 2 + }, + "mne/transforms.py": { + "a": 3, + "d": 5 + }, + "mne/utils.py": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13070.json b/mne-python/source/doc/sphinxext/prs/13070.json new file mode 100644 index 0000000000000000000000000000000000000000..635bf15d76ca64a687795d1b20bdba52a4f7ea79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13070.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "7daeceef4a2b80f4d849ec55a72a6450020c8c0c", + "authors": [ + { + "n": "Roy Eric", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/13070.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 4, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13071.json b/mne-python/source/doc/sphinxext/prs/13071.json new file mode 100644 index 0000000000000000000000000000000000000000..7efed2633d34c9bddad7e57fb7e8702b3ed6fbe4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13071.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "27386d7bc8240500efcfc618e2fa57f0bcea1ace", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/autofix.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13072.json b/mne-python/source/doc/sphinxext/prs/13072.json new file mode 100644 index 0000000000000000000000000000000000000000..2eda6ba713471f568da4dfd954825a7e6d27ff49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13072.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "96d22f87acb631c7cf04f5fcf0462f0956ba6f88", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13067.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/export/_export.py": { + "a": 9, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 0, + "d": 16 + }, + "mne/time_frequency/tfr.py": { + "a": 33, + "d": 19 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13073.json b/mne-python/source/doc/sphinxext/prs/13073.json new file mode 100644 index 0000000000000000000000000000000000000000..adf94fea4c7ffa4fa375f20565d132ccaf813574 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13073.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "99e985845759005c2d809c705241918589aa2a0e", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/check_changelog.yml": { + "a": 3, + "d": 0 + }, + ".github/workflows/circle_artifacts.yml": { + "a": 3, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13075.json b/mne-python/source/doc/sphinxext/prs/13075.json new file mode 100644 index 0000000000000000000000000000000000000000..94c1ec3210049bb6e13c09f698524d208bf0fcd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13075.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "f97a916bc79942df1cc5578ed98cddbcf1aef907", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/12656.bugfix.rst": { + "a": 1, + "d": 1 + }, + "mne/export/_export.py": { + "a": 5, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 5 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_env_vars.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13076.json b/mne-python/source/doc/sphinxext/prs/13076.json new file mode 100644 index 0000000000000000000000000000000000000000..bf05a88b72164b8bafb25db6628fbb98b300709e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13076.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6028982a3e34bf843d4694f60565a0fbb821ed2e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/related_software.py": { + "a": 16, + "d": 8 + }, + "mne/viz/backends/_pyvista.py": { + "a": 0, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 5, + "d": 5 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13077.json b/mne-python/source/doc/sphinxext/prs/13077.json new file mode 100644 index 0000000000000000000000000000000000000000..5ba2d52db90d63b205597b32e0b3aaa684f0b930 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13077.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4dc9fe44df5c0367ef9d250b18214832c90196fb", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/related_software.py": { + "a": 16, + "d": 8 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 5, + "d": 5 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13080.json b/mne-python/source/doc/sphinxext/prs/13080.json new file mode 100644 index 0000000000000000000000000000000000000000..f85b2afaea53226b437c2a3a798b8e281cdc1930 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13080.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "2119b22dbe5dba4ecbec06e1902be08c1b765371", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/13080.apichange.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/13080.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_ola.py": { + "a": 39, + "d": 24 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 2, + "d": 10 + }, + "mne/preprocessing/maxwell.py": { + "a": 351, + "d": 236 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 185, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_ola.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13081.json b/mne-python/source/doc/sphinxext/prs/13081.json new file mode 100644 index 0000000000000000000000000000000000000000..2d430f5a95356f7cc2b9ec3d80c3be401cc20662 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13081.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d596b6ddedac0680da889c5305ab4ab5d7626743", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Roy Eric", + "e": "139973278+Randomidous@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13070.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 4, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13082.json b/mne-python/source/doc/sphinxext/prs/13082.json new file mode 100644 index 0000000000000000000000000000000000000000..1eb2d448059b779e60c8f1b50810b49fad006f99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13082.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3db12ff5357d4d6666f3d2257e91cee877e83234", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13082.bugfix.rst": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/movement_detection.py": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 0, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13083.json b/mne-python/source/doc/sphinxext/prs/13083.json new file mode 100644 index 0000000000000000000000000000000000000000..2eaa9d71258b93ae9f20ad9050ba50dfbc8620bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13083.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "77195a2a5ff42fa0e193f889e712b279b6c65fd6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13083.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/_digitization.py": { + "a": 3, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 4, + "d": 22 + }, + "mne/_fiff/open.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tag.py": { + "a": 17, + "d": 7 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13084.json b/mne-python/source/doc/sphinxext/prs/13084.json new file mode 100644 index 0000000000000000000000000000000000000000..c08d21af74b89d588d3091e0fa28579a4b79fc82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13084.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d3d0bf520624a4eea2e8d34a927284c4bb19b87a", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13082.bugfix.rst": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/movement_detection.py": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 0, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13086.json b/mne-python/source/doc/sphinxext/prs/13086.json new file mode 100644 index 0000000000000000000000000000000000000000..261d6a9a0e361ae3cd239f318951034967604c69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13086.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "631ddb3e9da67456947e23c6a070aa869d853a26", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/_mpl_figure.py": { + "a": 2, + "d": 2 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13087.json b/mne-python/source/doc/sphinxext/prs/13087.json new file mode 100644 index 0000000000000000000000000000000000000000..1606b92a8c439516bc9b3be36460f44ab64d1eda --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13087.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4037ead8fe9ec27d7342263c574b99a7bc537104", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13088.json b/mne-python/source/doc/sphinxext/prs/13088.json new file mode 100644 index 0000000000000000000000000000000000000000..f23c44206b3a8dcdcdce50bcaa2e342888ec575b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13088.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "45fb777fbc53c88888032d40a14940c985079a93", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "mne/_fiff/proj.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13089.json b/mne-python/source/doc/sphinxext/prs/13089.json new file mode 100644 index 0000000000000000000000000000000000000000..b0ad8b2fce2799cd1c075c7544b6adceef7689a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13089.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "715540a823ae5dec335bee0b2499f1f7183c19c4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 4, + "d": 5 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13093.json b/mne-python/source/doc/sphinxext/prs/13093.json new file mode 100644 index 0000000000000000000000000000000000000000..548ee4917664c72e03f012ad3530bce6ee8961c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13093.json @@ -0,0 +1,187 @@ +{ + "merge_commit_sha": "24ef9aa2c618217c6532613abe318f4d5f65f5e3", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 5, + "d": 1 + }, + "doc/sphinxext/credit_tools.py": { + "a": 16, + "d": 16 + }, + "doc/sphinxext/prs/12071.json": { + "a": 67, + "d": 0 + }, + "doc/sphinxext/prs/12656.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/12828.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/12910.json": { + "a": 51, + "d": 0 + }, + "doc/sphinxext/prs/13037.json": { + "a": 107, + "d": 0 + }, + "doc/sphinxext/prs/13045.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13046.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13047.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13048.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13049.json": { + "a": 87, + "d": 0 + }, + "doc/sphinxext/prs/13051.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13053.json": { + "a": 87, + "d": 0 + }, + "doc/sphinxext/prs/13054.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13056.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13058.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/13060.json": { + "a": 423, + "d": 0 + }, + "doc/sphinxext/prs/13061.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13062.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13063.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13064.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13065.json": { + "a": 103, + "d": 0 + }, + "doc/sphinxext/prs/13067.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13069.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13070.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13071.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13072.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13073.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13075.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13076.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13077.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13081.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13082.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13084.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13086.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13087.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13088.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13089.json": { + "a": 23, + "d": 0 + }, + "examples/io/read_xdf.py": { + "a": 1, + "d": 2 + }, + "tools/install_pre_requirements.sh": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13096.json b/mne-python/source/doc/sphinxext/prs/13096.json new file mode 100644 index 0000000000000000000000000000000000000000..6b04f0c57cdf3e47cf7959cfe2bbb8bb42e3600a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13096.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "c4de9b61cd5f40a8771a853d483621c735390ec2", + "authors": [ + { + "n": "Young Truong", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Bru", + "e": "b.aristimunha@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13096.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/_eeglab.py": { + "a": 195, + "d": 7 + }, + "mne/io/eeglab/eeglab.py": { + "a": 63, + "d": 23 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 143, + "d": 2 + }, + "tools/azure_dependencies.sh": { + "a": 3, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 4, + "d": 0 + }, + "tools/github_actions_env_vars.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13097.json b/mne-python/source/doc/sphinxext/prs/13097.json new file mode 100644 index 0000000000000000000000000000000000000000..e9b51d2267344ee612cd75af7887c74ea400a60e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13097.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9e7fe95f99016709dcad50c9494ebce4323e4cfd", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13097.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13099.json b/mne-python/source/doc/sphinxext/prs/13099.json new file mode 100644 index 0000000000000000000000000000000000000000..18c7dc277877a5cebf00d8dafc9672bd06c8bde5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13099.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "21a185fe8c680da6aced6e6ba06309a140082842", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13100.json b/mne-python/source/doc/sphinxext/prs/13100.json new file mode 100644 index 0000000000000000000000000000000000000000..8093e0a90e9ce3bd8546647258c216c8f878d28c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13100.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e4cc4e27106774455347b5d95d8b7b58953af10b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/devel/13100.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 154, + "d": 154 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 0, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13101.json b/mne-python/source/doc/sphinxext/prs/13101.json new file mode 100644 index 0000000000000000000000000000000000000000..00058e144130cfd33bad7b1f2ad0e9ea1bb39b98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13101.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "afd69afe9ed9b07d48e860537d37fc349def6635", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/13101.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 7, + "d": 3 + }, + "mne/viz/evoked_field.py": { + "a": 5, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 15, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13104.json b/mne-python/source/doc/sphinxext/prs/13104.json new file mode 100644 index 0000000000000000000000000000000000000000..8433d97ace39d3621e1e750b4db3d9e1f142e11c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13104.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8eaa521270c17096586e45211f4df8a9f6bb57be", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13106.json b/mne-python/source/doc/sphinxext/prs/13106.json new file mode 100644 index 0000000000000000000000000000000000000000..1684477fe4e8c3cf50d80958b27997525032398c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13106.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "47b036953128b1fdc8e7d9631a89db9b296dce73", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/related_software.py": { + "a": 4, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13107.json b/mne-python/source/doc/sphinxext/prs/13107.json new file mode 100644 index 0000000000000000000000000000000000000000..32286c0624a0b025bd1371f128e4a52f35eca6ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13107.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "64ed25561841e6d91413564222e498c44244ad94", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13107.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 11, + "d": 2 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13109.json b/mne-python/source/doc/sphinxext/prs/13109.json new file mode 100644 index 0000000000000000000000000000000000000000..5d7ea355fc183e33c2a4218f941f0d4b3c49bcaf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13109.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "b1340eb1a24fccfe4d2bfd8dca74e3acd4ad926e", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/dev/13109.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 24, + "d": 3 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 37, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils/dataframe.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13110.json b/mne-python/source/doc/sphinxext/prs/13110.json new file mode 100644 index 0000000000000000000000000000000000000000..58cb8661ea4c80f0c08092c60a7423dfc238d348 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13110.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cf5ef5fea4412dcc4b8f7c79c14b0faf9342efb1", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13112.json b/mne-python/source/doc/sphinxext/prs/13112.json new file mode 100644 index 0000000000000000000000000000000000000000..faf066b82804e7e9073891366f4111521acd449f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13112.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "fa11865cd994405906ca270ba3e78144676beb3f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13112.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 1, + "d": 3 + }, + "mne/chpi.py": { + "a": 3, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 0, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 0 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 0 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13113.json b/mne-python/source/doc/sphinxext/prs/13113.json new file mode 100644 index 0000000000000000000000000000000000000000..c599bda3a09490974a3f5c521969b6b83494dedb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13113.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b4a7c64e5b36747cfd3621e7a043ddd839db4e96", + "authors": [ + { + "n": "GreasyCat", + "e": null + }, + { + "n": "Scott Huberty", + "e": "52462026+scott-huberty@users.noreply.github.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13113.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13114.json b/mne-python/source/doc/sphinxext/prs/13114.json new file mode 100644 index 0000000000000000000000000000000000000000..4439ce7eaf09d047e7a4cda91eb83c4f525de527 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13114.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "64e01e54a3e149460c86a082ecb913993cd93dc6", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13083.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/_digitization.py": { + "a": 3, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 4, + "d": 22 + }, + "mne/_fiff/open.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tag.py": { + "a": 17, + "d": 7 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13116.json b/mne-python/source/doc/sphinxext/prs/13116.json new file mode 100644 index 0000000000000000000000000000000000000000..e96e4ad3f5b0418cc20429edc74ac6b0d6f6377b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13116.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4c98f8ae5524fea24968fb1aa2bf2028886d5934", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/development/governance.rst": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13120.json b/mne-python/source/doc/sphinxext/prs/13120.json new file mode 100644 index 0000000000000000000000000000000000000000..7f237da3a389de4b70b27d70c10fafa80ef59eab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13120.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bd0da9bcb4905ac3ad1276df346e91254db7df90", + "authors": [ + { + "n": "Yixiao Shen", + "e": null + } + ], + "changes": { + "doc/changes/devel/13184.bugfix.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13123.json b/mne-python/source/doc/sphinxext/prs/13123.json new file mode 100644 index 0000000000000000000000000000000000000000..41e7a014fdbc2fc20153daad7905d7841621f5e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13123.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c0f166596edfc66e9ad15f7891048d27de08b803", + "authors": [ + { + "n": "Shresth Keshari", + "e": "kesharishresth5@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13123.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13125.json b/mne-python/source/doc/sphinxext/prs/13125.json new file mode 100644 index 0000000000000000000000000000000000000000..30e00acbbd6c8761b3fce75b574d56dc7e62cab8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13125.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a79809d018d4e261b39e5eed27402528befc9ac8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13126.json b/mne-python/source/doc/sphinxext/prs/13126.json new file mode 100644 index 0000000000000000000000000000000000000000..9034f95069f08e0f3c55e743f8410473c1016a8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13126.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c570cfccee22f9869ae1f40c0ce5e8046433f083", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13129.json b/mne-python/source/doc/sphinxext/prs/13129.json new file mode 100644 index 0000000000000000000000000000000000000000..cb83ac45521f80283cb583a76d312766ec20a1c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13129.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "11df2fabe0a5f53e450a73aefd307e8418c55d9b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_fiff/_digitization.py": { + "a": 2, + "d": 1 + }, + "mne/_fiff/constants.py": { + "a": 16, + "d": 4 + }, + "mne/_fiff/tests/test_constants.py": { + "a": 35, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 26, + "d": 13 + }, + "mne/transforms.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13132.json b/mne-python/source/doc/sphinxext/prs/13132.json new file mode 100644 index 0000000000000000000000000000000000000000..e0ae49e4093526180ed8f62d201f13605778b4ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13132.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "71669461372359ec238f9dfa8aff5499938b690e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/preprocessing/movement_compensation.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/otp.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 6, + "d": 1 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13134.json b/mne-python/source/doc/sphinxext/prs/13134.json new file mode 100644 index 0000000000000000000000000000000000000000..81cde97ba38454158cc8292c4401d475d0270edc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13134.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2587cda68e3f1795a8aa1c05084bf503ad91078c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "pyproject.toml": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13135.json b/mne-python/source/doc/sphinxext/prs/13135.json new file mode 100644 index 0000000000000000000000000000000000000000..73dd4c36e8a925f747b8396519d1a04c725193e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13135.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "4cce83f50a1086dd3ff5642f45f9e971ec858fa2", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/credit_tools.py": { + "a": 2, + "d": 1 + }, + "doc/sphinxext/prs/13044.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13080.json": { + "a": 63, + "d": 0 + }, + "doc/sphinxext/prs/13083.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13093.json": { + "a": 187, + "d": 0 + }, + "doc/sphinxext/prs/13097.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13099.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13100.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13101.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13104.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13106.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13107.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13110.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13113.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13114.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13116.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13123.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13125.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13126.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13129.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13132.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13134.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13140.json b/mne-python/source/doc/sphinxext/prs/13140.json new file mode 100644 index 0000000000000000000000000000000000000000..9ec2dba13cdb711ef365498347ec7830de442daf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13140.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1fe211a7b70d30cb1bb0c8eaa195469c1df2616f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/mne_doc_utils.py": { + "a": 27, + "d": 106 + }, + "mne/event.py": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 9, + "d": 2 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 4, + "d": 0 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13141.json b/mne-python/source/doc/sphinxext/prs/13141.json new file mode 100644 index 0000000000000000000000000000000000000000..daa2b9f34c955cc61fb1cbe9b12dfe4e9f49f6f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13141.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "266ccc9540f159609976fc6e1b2259c93923b2e3", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13143.json b/mne-python/source/doc/sphinxext/prs/13143.json new file mode 100644 index 0000000000000000000000000000000000000000..5eb11ca288fbaf180446bcfce9291819f63d2b4c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13143.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "73c4a7cb844a13377ce68f31d7d5dec822067986", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_includes/forward.rst": { + "a": 6, + "d": 6 + }, + "doc/documentation/cookbook.rst": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13144.json b/mne-python/source/doc/sphinxext/prs/13144.json new file mode 100644 index 0000000000000000000000000000000000000000..13efae843c868e119d834c7ac8157f5b69dbd36d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13144.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "61ebcf9e40302b16384c999aa89143407f7c80b1", + "authors": [ + { + "n": "Harrison Ritz", + "e": "hritz@princeton.edu" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13144.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 41, + "d": 4 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 0, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 18, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 15, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 102, + "d": 26 + }, + "tutorials/preprocessing/80_opm_processing.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13145.json b/mne-python/source/doc/sphinxext/prs/13145.json new file mode 100644 index 0000000000000000000000000000000000000000..6fe7f24cf50d05168e75f38983b9873732e72eab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13145.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a5073bf977b73e9981a2222cc546c93081914a7d", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/devel/13145.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/egi/events.py": { + "a": 9, + "d": 3 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13146.json b/mne-python/source/doc/sphinxext/prs/13146.json new file mode 100644 index 0000000000000000000000000000000000000000..47a2c5b2b99d7018700dbed03b2bc0df43a29810 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13146.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e7a593add4bbda513cff94f8ba7a1166919dc376", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/tests/test_abstract.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13147.json b/mne-python/source/doc/sphinxext/prs/13147.json new file mode 100644 index 0000000000000000000000000000000000000000..cea5666ae4c54a36d47abb90348974bf12834d49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13147.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "be27cf8dd32922ba6e15599f7746da635e9856c0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/parallel.py": { + "a": 15, + "d": 0 + }, + "mne/tests/test_filter.py": { + "a": 10, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13148.json b/mne-python/source/doc/sphinxext/prs/13148.json new file mode 100644 index 0000000000000000000000000000000000000000..d61b8ec3daf8bafca3a8bf6c2321d23f03ba3939 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13148.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7c531e49aa46083efd507921fe53a6ac0c89de49", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "mne/io/egi/egimff.py": { + "a": 9, + "d": 9 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13149.json b/mne-python/source/doc/sphinxext/prs/13149.json new file mode 100644 index 0000000000000000000000000000000000000000..07c5f9f2e0137ca1a436ceeaa10434f25c746389 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13149.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2cdc4af85a7d352f4e277a898b6fb118fc286233", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 1, + "d": 0 + }, + "mne/dipole.py": { + "a": 13, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13152.json b/mne-python/source/doc/sphinxext/prs/13152.json new file mode 100644 index 0000000000000000000000000000000000000000..1c5fc665bf7d95193763cb6aeec196fc35be6402 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13152.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ccaefd4439a77c3c3fa3618aa1ec41bae947e0c4", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13153.json b/mne-python/source/doc/sphinxext/prs/13153.json new file mode 100644 index 0000000000000000000000000000000000000000..72f735012fb6a8fa27305f54d56634e0020eaa86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13153.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "df4a3f1601418bf1dfd1a3621c34bfa3b1188f8b", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/beamformer/_rap_music.py": { + "a": 2, + "d": 2 + }, + "mne/dipole.py": { + "a": 74, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13155.json b/mne-python/source/doc/sphinxext/prs/13155.json new file mode 100644 index 0000000000000000000000000000000000000000..6e901901cf32bb00bec16a222e657e5c3fa6ae6e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13155.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3077476caa1e91df86ab3f52df7ce6a983b7fd86", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13156.json b/mne-python/source/doc/sphinxext/prs/13156.json new file mode 100644 index 0000000000000000000000000000000000000000..432e8072f7a3b54b0f8dd099d43dc182f43b3cd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13156.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "6f42037ba84c3f97214fb2d191e5d790be16c9c4", + "authors": [ + { + "n": "Santi Martínez", + "e": "santiaguzz@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13156.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/_edf/open.py": { + "a": 23, + "d": 0 + }, + "mne/fixes.py": { + "a": 32, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 439, + "d": 124 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 55, + "d": 2 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 21, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13162.json b/mne-python/source/doc/sphinxext/prs/13162.json new file mode 100644 index 0000000000000000000000000000000000000000..97f64b14cc4f7944b03125393f6dd33398405956 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13162.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1fb9dd6d5a3aa6734b9b07474c484d743338e8c2", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 7, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13163.json b/mne-python/source/doc/sphinxext/prs/13163.json new file mode 100644 index 0000000000000000000000000000000000000000..7ddb03bb82e137026bf8af4249134ad134243d14 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13163.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b43f4d48c4cd9aa70fb8f83c61f96986b8ab9180", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/development/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13164.json b/mne-python/source/doc/sphinxext/prs/13164.json new file mode 100644 index 0000000000000000000000000000000000000000..310b43818bb8927ed670aaf62f1374e644512d87 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13164.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b6cd5f4e5e42622950e369eeb44118c6500ecc70", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13171.json b/mne-python/source/doc/sphinxext/prs/13171.json new file mode 100644 index 0000000000000000000000000000000000000000..bb662310cfee57672f6c48848ff967e2bdb5d0d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13171.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "511b7a5c28151542e1547dc7273e5c6ee67f3c7e", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13172.json b/mne-python/source/doc/sphinxext/prs/13172.json new file mode 100644 index 0000000000000000000000000000000000000000..6c62e5273aa60710b697e4fcbdab4c79d59e51ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13172.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "618932d7fbb6ef7e4d9f110c90a1cc77f51ab082", + "authors": [ + { + "n": "Peter J. Molfese", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13172.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 19, + "d": 0 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13173.json b/mne-python/source/doc/sphinxext/prs/13173.json new file mode 100644 index 0000000000000000000000000000000000000000..d65144387827b322bfd3ff3be69d6d26af663dbb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13173.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a745fdc7f5b5925da4514d9f68ba6f9ffbf9403d", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13174.json b/mne-python/source/doc/sphinxext/prs/13174.json new file mode 100644 index 0000000000000000000000000000000000000000..5737f7bba52374c15f185aafa329109de5b7794e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13174.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e04c4d92bd6ce6cb6dca4e9d427a8897c5a19c20", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/devel/13174.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/export/_edf.py": { + "a": 12, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 5, + "d": 2 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13176.json b/mne-python/source/doc/sphinxext/prs/13176.json new file mode 100644 index 0000000000000000000000000000000000000000..857dc390edbc01ecfe4054ec95db12e2036c9456 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13176.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "88951b68c175cade9d6ac6ff64023dc51bf32fe1", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/_includes/dig_formats.rst": { + "a": 12, + "d": 10 + }, + "doc/api/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/dev/13176.dependency.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/dev/13176.newfeature.rst": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 4, + "d": 0 + }, + "mne/channels/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 45, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 61, + "d": 11 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/curry/curry.py": { + "a": 739, + "d": 450 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 262, + "d": 105 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 1 + }, + "tools/vulture_allowlist.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13178.json b/mne-python/source/doc/sphinxext/prs/13178.json new file mode 100644 index 0000000000000000000000000000000000000000..b0c066d5a20640c402df03b6586dcb3afea68f32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13178.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "704b3930e03c1428dc73481d8232c6838b4b1047", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13178.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 5, + "d": 1 + }, + "mne/bem.py": { + "a": 11, + "d": 31 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 16, + "d": 19 + }, + "mne/simulation/tests/test_raw.py": { + "a": 7, + "d": 3 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_bem.py": { + "a": 7, + "d": 8 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13179.json b/mne-python/source/doc/sphinxext/prs/13179.json new file mode 100644 index 0000000000000000000000000000000000000000..6028707180e9ede42fffebd246c3441ce425f0ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13179.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "9b93f0329127f31bd2e6c117767f10d45edd0527", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13179.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/13179.newfeature.rst": { + "a": 1, + "d": 0 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/mne_helmet.py": { + "a": 9, + "d": 3 + }, + "mne/forward/_field_interpolation.py": { + "a": 5, + "d": 1 + }, + "mne/surface.py": { + "a": 23, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 40, + "d": 28 + }, + "mne/viz/backends/_abstract.py": { + "a": 8, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 8, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 18, + "d": 6 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 1, + "d": 2 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1318.json b/mne-python/source/doc/sphinxext/prs/1318.json new file mode 100644 index 0000000000000000000000000000000000000000..5b61922546d61ead8eb3143243781a735d8bb09e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1318.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ecca44f7a2ee94cd54ff1bdee88bae46ef006978", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 63, + "d": 48 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13180.json b/mne-python/source/doc/sphinxext/prs/13180.json new file mode 100644 index 0000000000000000000000000000000000000000..76e76c922a6115520c4ecccc8e75249f850b3175 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13180.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "e65a55965958829a0cfc66d45a57175214241d16", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 6, + "d": 3 + }, + "doc/sphinxext/prs/13135.json": { + "a": 107, + "d": 0 + }, + "doc/sphinxext/prs/13140.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13141.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13143.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13145.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13146.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13147.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13148.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13149.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13152.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13153.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13155.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13162.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13163.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13164.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13171.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13174.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13178.json": { + "a": 63, + "d": 0 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13183.json b/mne-python/source/doc/sphinxext/prs/13183.json new file mode 100644 index 0000000000000000000000000000000000000000..ad99e840d2933457d017ef7cdc935aed9c29c95d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13183.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "68f666e655b9fddea8a95ffb38c5c9d8a9e7a4ff", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/13183.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/cuda.py": { + "a": 6, + "d": 3 + }, + "mne/filter.py": { + "a": 20, + "d": 3 + }, + "mne/tests/test_filter.py": { + "a": 100, + "d": 73 + }, + "mne/viz/_figure.py": { + "a": 47, + "d": 10 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13184.json b/mne-python/source/doc/sphinxext/prs/13184.json new file mode 100644 index 0000000000000000000000000000000000000000..5e6c181ef8b26b49fdda1afa481d92ec0f0ab766 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13184.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "729bdf38c88d61ea806a53fa3eb47fe2af0725cb", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/devel/13184.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/13184.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 57, + "d": 38 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 23, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1319.json b/mne-python/source/doc/sphinxext/prs/1319.json new file mode 100644 index 0000000000000000000000000000000000000000..47bedb1cae009bd039f95e600d2968179c6ad219 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1319.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "46a6babf98bf697ae6174c3b6fcf8361fc299316", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 7, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 7, + "d": 0 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 21, + "d": 23 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 30, + "d": 98 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 35, + "d": 169 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/bads.py": { + "a": 36, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 126, + "d": 25 + }, + "mne/preprocessing/eog.py": { + "a": 103, + "d": 32 + }, + "mne/preprocessing/ica.py": { + "a": 1020, + "d": 560 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 5, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 111, + "d": 78 + }, + "mne/tests/test_viz.py": { + "a": 64, + "d": 4 + }, + "mne/utils.py": { + "a": 36, + "d": 3 + }, + "mne/viz.py": { + "a": 491, + "d": 94 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13196.json b/mne-python/source/doc/sphinxext/prs/13196.json new file mode 100644 index 0000000000000000000000000000000000000000..cc4498f8c6ade45706e82fcb38b41ba226fc71bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13196.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "437d79be7c5fb855a81d44da30bf9a51c9f60413", + "authors": [ + { + "n": "Konstantinos Tsilimparis", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/api/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/dev/13196.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/interpolate_to.py": { + "a": 71, + "d": 4 + }, + "mne/channels/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 76, + "d": 133 + }, + "mne/channels/data/canonical_meg/ctf151.csv": { + "a": 152, + "d": 0 + }, + "mne/channels/data/canonical_meg/ctf275.csv": { + "a": 275, + "d": 0 + }, + "mne/channels/data/canonical_meg/neuromag306.csv": { + "a": 307, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 138, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 119, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 25, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13197.json b/mne-python/source/doc/sphinxext/prs/13197.json new file mode 100644 index 0000000000000000000000000000000000000000..ef39bd7dc8ee8bc4540da7313f4dc24d739b0155 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13197.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "daf7abfeef38fbab44c071d88c530b638bd9a372", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + } + ], + "changes": { + "examples/io/read_impedances.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13198.json b/mne-python/source/doc/sphinxext/prs/13198.json new file mode 100644 index 0000000000000000000000000000000000000000..84313ed33b2f1d605b8557d91bdbad6b2fcbcb1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13198.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "80ca92561f35e481805629b0302daa3f8adfa24e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1320.json b/mne-python/source/doc/sphinxext/prs/1320.json new file mode 100644 index 0000000000000000000000000000000000000000..8ea436e3aeb368bce653f78f565cb0f2914137e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1320.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "26cda4e781ceee46acb4c7202b7273fd95e7e15e", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_coregistration_transform.py": { + "a": 31, + "d": 0 + }, + "mne/forward/_field_interpolation.py": { + "a": 4, + "d": 24 + }, + "mne/tests/test_viz.py": { + "a": 19, + "d": 2 + }, + "mne/transforms.py": { + "a": 20, + "d": 0 + }, + "mne/viz.py": { + "a": 87, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13202.json b/mne-python/source/doc/sphinxext/prs/13202.json new file mode 100644 index 0000000000000000000000000000000000000000..8d03d015f407b250cc2d98976fe65ab345dec63f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13202.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6ac3c2dc2619270b63c85403579baa98b9085c62", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/mne_tools_suite.rst": { + "a": 0, + "d": 20 + }, + "doc/sphinxext/related_software.py": { + "a": 1, + "d": 8 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13205.json b/mne-python/source/doc/sphinxext/prs/13205.json new file mode 100644 index 0000000000000000000000000000000000000000..3fd2879847cdade28f29298cdc4cbbfce5c92f5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13205.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "21b2f344be1c5c7a9b81aad8c955dfcabd3107d6", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + } + ], + "changes": { + "doc/_includes/institutional-partners.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13207.json b/mne-python/source/doc/sphinxext/prs/13207.json new file mode 100644 index 0000000000000000000000000000000000000000..7a81181edded43658b5dc28a95223baba30c1507 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13207.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8ea69e113429aee4af7f461b73c38a9518963248", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13208.json b/mne-python/source/doc/sphinxext/prs/13208.json new file mode 100644 index 0000000000000000000000000000000000000000..0955ea904a6d81b9c1e03373c9a5dcc3f3bec926 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13208.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "46e7071d29d2babf21d4a9d199a3af30120c143e", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13208.bugfix.rst.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 6, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 22, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13210.json b/mne-python/source/doc/sphinxext/prs/13210.json new file mode 100644 index 0000000000000000000000000000000000000000..0d97753be813c29d89376593cd52ce0c572350f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13210.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "855cb53c3bcc501aef3e06699e9b84c33a53ef7f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/datasets/opm_data.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 25, + "d": 2 + }, + "mne/viz/tests/test_utils.py": { + "a": 10, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 13, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13212.json b/mne-python/source/doc/sphinxext/prs/13212.json new file mode 100644 index 0000000000000000000000000000000000000000..6b4575c84d06293b4d3afe528ee5ce98ed80ea8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13212.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a109ad5c711cddd27d45ec1ce50e1a221e55210a", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13214.json b/mne-python/source/doc/sphinxext/prs/13214.json new file mode 100644 index 0000000000000000000000000000000000000000..08598cd4fdde7498c4415742c11263a3b3b25c76 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13214.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a0dda10cd84d6b122b2f8e83efc091df8f4dc025", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13217.json b/mne-python/source/doc/sphinxext/prs/13217.json new file mode 100644 index 0000000000000000000000000000000000000000..eec25d977efc1ea33b936a641af6078bbe16cdd6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13217.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e9d96334afc13d3eb026e42c8e96b2d6101c9b9", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/time_frequency/spectrum.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13218.json b/mne-python/source/doc/sphinxext/prs/13218.json new file mode 100644 index 0000000000000000000000000000000000000000..3451bdc01118444ce622ea9b226180b6d814768b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13218.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d089b459c3a7a276d015e553920b2201ba1bdde9", + "authors": [ + { + "n": "Wei", + "e": null + } + ], + "changes": { + "doc/changes/devel/13218.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13222.json b/mne-python/source/doc/sphinxext/prs/13222.json new file mode 100644 index 0000000000000000000000000000000000000000..725d277dfaa5c099ce1af662b4a2ecf1711306e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13222.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f6c6bd78ac21b3433d5066e6ac8e539a9756e24c", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/zizmor.yml": { + "a": 5, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13225.json b/mne-python/source/doc/sphinxext/prs/13225.json new file mode 100644 index 0000000000000000000000000000000000000000..389fdf5c92dbd3142f5599454a24b19061bc4816 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13225.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1d34cd9414403f5b8d9e5c6ff5d5f3093f927def", + "authors": [ + { + "n": "Katia", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 10, + "d": 0 + }, + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/changes/devel/13225.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13226.json b/mne-python/source/doc/sphinxext/prs/13226.json new file mode 100644 index 0000000000000000000000000000000000000000..e62914416088004d7217caa35218c4e10fa8ea40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13226.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c18908cb6c9f010b52222a2f4d617da47af72426", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 17, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13228.json b/mne-python/source/doc/sphinxext/prs/13228.json new file mode 100644 index 0000000000000000000000000000000000000000..3c9442df59d98c4b380577d45d4272fbf1a00d1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13228.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "80a20717e912ee2a7982225e7e2c5ed6b70032f5", + "authors": [ + { + "n": "Pierre Guetschel", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13228.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 319, + "d": 30 + }, + "mne/epochs.py": { + "a": 19, + "d": 5 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 170, + "d": 11 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 3 + }, + "mne/utils/check.py": { + "a": 14, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1323.json b/mne-python/source/doc/sphinxext/prs/1323.json new file mode 100644 index 0000000000000000000000000000000000000000..29797328c2624765f0922820a8d66913897fcfa8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1323.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "732a49bf9307bc96698462416cf10178c9b11a67", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 0, + "d": 1 + }, + "mne/io/channels.py": { + "a": 4, + "d": 0 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 6, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13232.json b/mne-python/source/doc/sphinxext/prs/13232.json new file mode 100644 index 0000000000000000000000000000000000000000..7a9afeab554dfac818c83ba122fe4f823ac6e15b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13232.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0efaf9666de854bc5f35334423b794b63a29a5d9", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/13232.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/forward/_field_interpolation.py": { + "a": 7, + "d": 5 + }, + "mne/report/report.py": { + "a": 8, + "d": 5 + }, + "mne/report/tests/test_report.py": { + "a": 5, + "d": 0 + }, + "mne/tests/test_transforms.py": { + "a": 7, + "d": 2 + }, + "mne/transforms.py": { + "a": 24, + "d": 13 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13233.json b/mne-python/source/doc/sphinxext/prs/13233.json new file mode 100644 index 0000000000000000000000000000000000000000..f063bdf347f9d60815f978858ce79d312948ce2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13233.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2bb3ac284683ba60bee782f70e54bd1dcb5d4269", + "authors": [ + { + "n": "Sebastian Jentschke", + "e": null + } + ], + "changes": { + "doc/changes/devel/13233.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13234.json b/mne-python/source/doc/sphinxext/prs/13234.json new file mode 100644 index 0000000000000000000000000000000000000000..bac959c6a31ef2c022a635916f620452e3fd3364 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13234.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "dda454d7e4bd2766a2bdff37c06583fde99ba747", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13234.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/defaults.py": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 48, + "d": 16 + }, + "mne/report/tests/test_report.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13235.json b/mne-python/source/doc/sphinxext/prs/13235.json new file mode 100644 index 0000000000000000000000000000000000000000..80682d0d218ba2126b7147b9382a23f1344d3d49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13235.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0febd730da2b068f3218ee1a961a40debcc0770e", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13236.json b/mne-python/source/doc/sphinxext/prs/13236.json new file mode 100644 index 0000000000000000000000000000000000000000..aa4292b2378b4b1472552777f0fa2ace3eb8dbad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13236.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7f583df4ff4c4c098883e1a00ec5300f7e57db3f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13237.json b/mne-python/source/doc/sphinxext/prs/13237.json new file mode 100644 index 0000000000000000000000000000000000000000..6d61f4c6a627f9ef16144c3008bebf729abcb995 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13237.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "5df1721b488070e3b3928dface9dd0b8c39a3bef", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/credit_tools.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/prs/13120.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13144.json": { + "a": 51, + "d": 0 + }, + "doc/sphinxext/prs/13172.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13173.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13179.json": { + "a": 75, + "d": 0 + }, + "doc/sphinxext/prs/13180.json": { + "a": 95, + "d": 0 + }, + "doc/sphinxext/prs/13183.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13184.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13197.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13198.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13202.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13205.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13207.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13210.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13212.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13214.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13217.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13218.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13222.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13225.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13226.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13233.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13235.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13236.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13239.json b/mne-python/source/doc/sphinxext/prs/13239.json new file mode 100644 index 0000000000000000000000000000000000000000..703aadd1acf64d80145a2e115b7724dee63be89d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13239.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8f0fef638081525f2b13f239d66938ad0b2bdb1a", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13240.json b/mne-python/source/doc/sphinxext/prs/13240.json new file mode 100644 index 0000000000000000000000000000000000000000..d01d073580e4cac47d791c9b2e44ebce05730814 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13240.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7a50fd785e3353803e0a14df5425cc1d327251b4", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13241.json b/mne-python/source/doc/sphinxext/prs/13241.json new file mode 100644 index 0000000000000000000000000000000000000000..2457b4be4c8b06339d3b1df39677aebbd23d37a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13241.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "1ea5dbbdb056592980c3daa9816d91683abf13ba", + "authors": [ + { + "n": "Bru", + "e": "b.aristimunha@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13241.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/forward/_lead_dots.py": { + "a": 3, + "d": 3 + }, + "mne/utils/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/utils/config.py": { + "a": 76, + "d": 4 + }, + "mne/utils/tests/test_config.py": { + "a": 103, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13245.json b/mne-python/source/doc/sphinxext/prs/13245.json new file mode 100644 index 0000000000000000000000000000000000000000..2996bd5c464c29f4a0f5d79fdeecc2a688a0ac46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13245.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6696cec2edf456a626694056560fc8121d66174f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 9, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13246.json b/mne-python/source/doc/sphinxext/prs/13246.json new file mode 100644 index 0000000000000000000000000000000000000000..115aa7f76efb3d56a54f8383c09bc0f16ce4ea6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13246.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9849b3e4030740848d6899268a163445ec2a8b0c", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13247.json b/mne-python/source/doc/sphinxext/prs/13247.json new file mode 100644 index 0000000000000000000000000000000000000000..21f2e4d6da58cf105290cd97eb04568a6cf5d6be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13247.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "70f0255909ddaf428ef55517ad3c0116819937c2", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/report/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13249.json b/mne-python/source/doc/sphinxext/prs/13249.json new file mode 100644 index 0000000000000000000000000000000000000000..7d2b8b780d5c8650e63256144a3b1dc921eaf009 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13249.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e0cc99b5babebe90f13e92b270fd860ac40b43a3", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/documentation/datasets.rst": { + "a": 2, + "d": 1 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/10_background_freesurfer.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13251.json b/mne-python/source/doc/sphinxext/prs/13251.json new file mode 100644 index 0000000000000000000000000000000000000000..de9b32ad43409ec2fcdf3bf5bbc0f9c644a68f64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13251.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "181fea1e7e0bd73c2ec5cf67391cf598ad1af7bf", + "authors": [ + { + "n": null, + "e": "myd7349@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 0 + }, + "doc/changes/dev/13251.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/nihon/nihon.py": { + "a": 55, + "d": 11 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 8, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13255.json b/mne-python/source/doc/sphinxext/prs/13255.json new file mode 100644 index 0000000000000000000000000000000000000000..25420df1af4df96153ce3cb754e95cce8b24214b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13255.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "68b5523a1d2e301fb0e4f2460c67d42c465e46b7", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 23, + "d": 53 + }, + "mne/utils/config.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13256.json b/mne-python/source/doc/sphinxext/prs/13256.json new file mode 100644 index 0000000000000000000000000000000000000000..c1810a40760e5ecacaf27122d4ec5f1a6a03802e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13256.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "cc5e2e64a9adefdfaa5d438e839d4447c8f05613", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/tests/test_commands.py": { + "a": 4, + "d": 4 + }, + "mne/cov.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 2, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 8, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13259.json b/mne-python/source/doc/sphinxext/prs/13259.json new file mode 100644 index 0000000000000000000000000000000000000000..26f64c40dac867f62b3bf647878b617161be1f51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13259.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "b4c2a3b6f725185ba6afe3b50aeab3449c343d27", + "authors": [ + { + "n": "Genuster", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/ged.rst": { + "a": 107, + "d": 0 + }, + "doc/api/decoding.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/devel/13259.newfeature.rst": { + "a": 3, + "d": 0 + }, + "doc/documentation/implementation.rst": { + "a": 8, + "d": 0 + }, + "doc/references.bib": { + "a": 12, + "d": 0 + }, + "mne/decoding/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/decoding/_covs_ged.py": { + "a": 284, + "d": 0 + }, + "mne/decoding/_ged.py": { + "a": 131, + "d": 0 + }, + "mne/decoding/_mod_ged.py": { + "a": 132, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 252, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 103, + "d": 227 + }, + "mne/decoding/ssd.py": { + "a": 52, + "d": 161 + }, + "mne/decoding/tests/test_ged.py": { + "a": 388, + "d": 0 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 94, + "d": 9 + }, + "mne/decoding/xdawn.py": { + "a": 207, + "d": 0 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 20, + "d": 16 + }, + "mne/preprocessing/xdawn.py": { + "a": 4, + "d": 152 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 0 + }, + "tools/vulture_allowlist.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1326.json b/mne-python/source/doc/sphinxext/prs/1326.json new file mode 100644 index 0000000000000000000000000000000000000000..725c9e980e801cf64256681c3d117fb05d1f64db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1326.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5b9e92ed4589c4a37749bfd24fa03bd3194fd552", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fixes.py": { + "a": 24, + "d": 0 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_fixes.py": { + "a": 16, + "d": 3 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13261.json b/mne-python/source/doc/sphinxext/prs/13261.json new file mode 100644 index 0000000000000000000000000000000000000000..41a14e4f59d6dc15b601c50d45e758766f87d0df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13261.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "99275fa2f1be6b260bfa38f0eef4dd605bd8686c", + "authors": [ + { + "n": "LaurentLM", + "e": "laurent.lementec@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13261.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 24, + "d": 9 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 15, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_config.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13262.json b/mne-python/source/doc/sphinxext/prs/13262.json new file mode 100644 index 0000000000000000000000000000000000000000..737f055b9f9fd6bb93257fabeb28ee4f2fc55769 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13262.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9e5a929a309c66b0ce618795e6cc8123367f9896", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13266.json b/mne-python/source/doc/sphinxext/prs/13266.json new file mode 100644 index 0000000000000000000000000000000000000000..06d9e6545b3fa442a0b71a0b0cebd73ff8f9b612 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13266.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fc9078a93170ea1d2ccc88bffb85b48509757c4d", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "tutorials/visualization/10_publication_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13267.json b/mne-python/source/doc/sphinxext/prs/13267.json new file mode 100644 index 0000000000000000000000000000000000000000..e7d8b118a83fbb4193120c58124cf59927cb8801 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13267.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "b0e9a8596136c937eb90c86dc78c1870bf24853f", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/prs/13208.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13232.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13234.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13237.json": { + "a": 111, + "d": 0 + }, + "doc/sphinxext/prs/13239.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13240.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13241.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13245.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13246.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13247.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13249.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13255.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13256.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13262.json": { + "a": 27, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13268.json b/mne-python/source/doc/sphinxext/prs/13268.json new file mode 100644 index 0000000000000000000000000000000000000000..d48d7fc463fa5390d028b9586bca9d135d9b7178 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13268.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ecc33755375a49df8c5c27fb6263230b4d0b0193", + "authors": [ + { + "n": "Theodore Papadopoulo", + "e": "Theodore.Papadopoulo@inria.fr" + } + ], + "changes": { + "doc/changes/devel/13268.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/tag.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13273.json b/mne-python/source/doc/sphinxext/prs/13273.json new file mode 100644 index 0000000000000000000000000000000000000000..549448bee0f1e1c52110129e3df5b8b5183d763a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13273.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4033b3a339c1226e248953eeee30e7488d50659f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 2, + "d": 2 + }, + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "doc/martinos.rst": { + "a": 0, + "d": 37 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13274.json b/mne-python/source/doc/sphinxext/prs/13274.json new file mode 100644 index 0000000000000000000000000000000000000000..64f228f636110d415e1c08bd6eebc7a9ab559c4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13274.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "40b9232ecb01de8bbe0d039564e995214c90b630", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "mne/commands/tests/test_commands.py": { + "a": 6, + "d": 3 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/hooks/update_environment_file.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13276.json b/mne-python/source/doc/sphinxext/prs/13276.json new file mode 100644 index 0000000000000000000000000000000000000000..482b19ece742b20a30c24095826b46090315ac13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13276.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d9dcf118f0773f693722f2d9a651a09e5ada1df1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13276.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 14, + "d": 8 + }, + "mne/forward/_compute_forward.py": { + "a": 5, + "d": 0 + }, + "mne/simulation/tests/test_raw.py": { + "a": 26, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13277.json b/mne-python/source/doc/sphinxext/prs/13277.json new file mode 100644 index 0000000000000000000000000000000000000000..265557863ca679d53824d26944ad4a5af8a3afec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13277.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "58618f756d0c83dc5d57979ac14e87165394397d", + "authors": [ + { + "n": "user27182", + "e": "89109579+user27182@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13277.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1328.json b/mne-python/source/doc/sphinxext/prs/1328.json new file mode 100644 index 0000000000000000000000000000000000000000..15a1fbb95ff6976940ab376db58a521a62d12763 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1328.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "f3c721014a4115c451ce2e3c376194003f0f7818", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_eog_artifact_histogram.py": { + "a": 49, + "d": 0 + }, + "mne/epochs.py": { + "a": 30, + "d": 25 + }, + "mne/event.py": { + "a": 2, + "d": 26 + }, + "mne/io/base.py": { + "a": 40, + "d": 2 + }, + "mne/realtime/epochs.py": { + "a": 2, + "d": 13 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 6 + }, + "mne/tests/test_event.py": { + "a": 23, + "d": 0 + }, + "mne/utils.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13280.json b/mne-python/source/doc/sphinxext/prs/13280.json new file mode 100644 index 0000000000000000000000000000000000000000..3c39b3884721e406a97f0e3879299ef9fa079882 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13280.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "19264460d568eaa6243da44e68de9fbd662e03ff", + "authors": [ + { + "n": "Harrison Ritz", + "e": "hritz@princeton.edu" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13280.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13282.json b/mne-python/source/doc/sphinxext/prs/13282.json new file mode 100644 index 0000000000000000000000000000000000000000..1343ff41ca168910974323999561a52bfebeefbe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13282.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "69620eb71a3689dabf5d0f1d926a01c68a8b6664", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/autofix.yml": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13283.json b/mne-python/source/doc/sphinxext/prs/13283.json new file mode 100644 index 0000000000000000000000000000000000000000..b9c95b1989027eb3e62f88c91f12acfadcf309c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13283.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ed69487d690a7e835b342d9367bd189e41b38e6f", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13284.json b/mne-python/source/doc/sphinxext/prs/13284.json new file mode 100644 index 0000000000000000000000000000000000000000..4e5386216ffa3ef69bc3eb7e8fd7bb91d4cee42a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13284.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c4f5f0a0ea8d3f333c401449b96f77a9930e92d3", + "authors": [ + { + "n": "LaurentLM", + "e": "laurent.lementec@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13284.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 14, + "d": 3 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13286.json b/mne-python/source/doc/sphinxext/prs/13286.json new file mode 100644 index 0000000000000000000000000000000000000000..74bc01cb3b4a13bc3ae2fb453401e82cf21b5751 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13286.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8df70aea97c42a58d02e1c121679e9c1b2c62869", + "authors": [ + { + "n": "Ankang Hu", + "e": "23111220065@m.fudan.edu.cn" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13286.bugfix.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13290.json b/mne-python/source/doc/sphinxext/prs/13290.json new file mode 100644 index 0000000000000000000000000000000000000000..c9e72dea20b10ef3da815e3c49a3508a83f9eb9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13290.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a0e5a83962c800fcee21896cb891c63b6373c1cc", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13291.json b/mne-python/source/doc/sphinxext/prs/13291.json new file mode 100644 index 0000000000000000000000000000000000000000..fb90d348c3031e78e809307a2296bd021c50cbba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13291.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "729ce25d05280291469d0b5ddfd86007ae1b443d", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13293.json b/mne-python/source/doc/sphinxext/prs/13293.json new file mode 100644 index 0000000000000000000000000000000000000000..f519f306f73d36501b9a486306a0ee3cec040916 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13293.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bb34f369ada8b27299a74118b858118cbcbf346a", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/13293.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/pick.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13298.json b/mne-python/source/doc/sphinxext/prs/13298.json new file mode 100644 index 0000000000000000000000000000000000000000..778da14a3c492b79e78447e1d661101e8a2bc8a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13298.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "5009ee876e6b905eb25a37a0e45c75aa7b4c6e9f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/devel/13298.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 20, + "d": 16 + }, + "mne/viz/tests/test_raw.py": { + "a": 14, + "d": 9 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 9 + }, + "tutorials/time-freq/10_spectrum_class.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13299.json b/mne-python/source/doc/sphinxext/prs/13299.json new file mode 100644 index 0000000000000000000000000000000000000000..2d44f641fdf909b5b24c4478a9b5c045ebe076a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13299.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b78d661203f4e805d5a9412583c1a10af3a73106", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 4, + "d": 5 + }, + "mne/utils/tests/test_config.py": { + "a": 3, + "d": 1 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13300.json b/mne-python/source/doc/sphinxext/prs/13300.json new file mode 100644 index 0000000000000000000000000000000000000000..7e71d69f98e1e7e590ed6de05151ce08fb995438 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13300.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1652a7cf97a02a91ac3503e0f89f195cb505e191", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13301.json b/mne-python/source/doc/sphinxext/prs/13301.json new file mode 100644 index 0000000000000000000000000000000000000000..174e45f123522e0cd47c758f828a832a7784a295 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13301.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2e677b122980a605c1a3a86765f549b70ee0a534", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/time_frequency/spectrum.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13304.json b/mne-python/source/doc/sphinxext/prs/13304.json new file mode 100644 index 0000000000000000000000000000000000000000..edd336922531055a84657aadeb90971c73e5c92f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13304.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d193166134dcc30c3c2bf154ec188f63913d6ea6", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/links.inc": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13305.json b/mne-python/source/doc/sphinxext/prs/13305.json new file mode 100644 index 0000000000000000000000000000000000000000..8422ae14ff813d606ac82d712a87ca02ff412441 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13305.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a4a614f72da25c43a509b0ec987dbe7620d08981", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13306.json b/mne-python/source/doc/sphinxext/prs/13306.json new file mode 100644 index 0000000000000000000000000000000000000000..ef6dc8e99c3679acfdcbd24d2ac2af56a00f733d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13306.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "6ad882335644fb80f8744e508387c52f7231553a", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/credit_tools.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/prs/13228.json": { + "a": 59, + "d": 0 + }, + "doc/sphinxext/prs/13261.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13266.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13267.json": { + "a": 79, + "d": 0 + }, + "doc/sphinxext/prs/13268.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13273.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13274.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13276.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13277.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13280.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13282.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13283.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13284.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13286.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13290.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13291.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13293.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13299.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13300.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13301.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13307.json b/mne-python/source/doc/sphinxext/prs/13307.json new file mode 100644 index 0000000000000000000000000000000000000000..e540c8580aa3041a593521b938d7adfd53569aee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13307.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f66a254a8813bc0d35493ff7ef65d3767d08d839", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13307.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 42, + "d": 11 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 5, + "d": 2 + }, + "mne/simulation/raw.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13308.json b/mne-python/source/doc/sphinxext/prs/13308.json new file mode 100644 index 0000000000000000000000000000000000000000..e71f749d25afc48de6b0c5ada1805ffaf145fd8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13308.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "d970efb081463306fa29fde33d8c995ef649ee56", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "environment.yml": { + "a": 3, + "d": 3 + }, + "mne/decoding/_fixes.py": { + "a": 132, + "d": 0 + }, + "mne/decoding/tests/test_base.py": { + "a": 3, + "d": 1 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 6, + "d": 3 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 13, + "d": 3 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/environment_old.yml": { + "a": 1, + "d": 1 + }, + "tools/hooks/update_environment_file.py": { + "a": 1, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13310.json b/mne-python/source/doc/sphinxext/prs/13310.json new file mode 100644 index 0000000000000000000000000000000000000000..907ebbad1574c41ae872a7db288b615157c903fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13310.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3612f7bc3dbe57a4de2d976d749703bd75001d29", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/devel/13310.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 13, + "d": 0 + }, + "mne/utils/config.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13311.json b/mne-python/source/doc/sphinxext/prs/13311.json new file mode 100644 index 0000000000000000000000000000000000000000..c5f7fb6f04c95e0eca20d2e8e2ef3dd0d26b7c10 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13311.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2cc3715ce5591dc60fa70d34503a9e0eedb74bef", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13313.json b/mne-python/source/doc/sphinxext/prs/13313.json new file mode 100644 index 0000000000000000000000000000000000000000..3d059ab464c3eb06f6904776ac62df9b22b3aef4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13313.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "5fed2b6c85386021cb47a6b1ee44783ae223876d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 3, + "d": 3 + }, + "mne/_fiff/tests/test_constants.py": { + "a": 3, + "d": 0 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 15, + "d": 6 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 1 + }, + "mne/html_templates/report/forward.html.jinja": { + "a": 1, + "d": 0 + }, + "mne/html_templates/report/image.html.jinja": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 2, + "d": 2 + }, + "mne/report/report.py": { + "a": 150, + "d": 158 + }, + "mne/report/tests/test_report.py": { + "a": 7, + "d": 4 + }, + "tutorials/intro/70_report.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13314.json b/mne-python/source/doc/sphinxext/prs/13314.json new file mode 100644 index 0000000000000000000000000000000000000000..7184757b9b3225c9caf261239df42fa786372dce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13314.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "35398fdb1a9760e3926c0c5eff4ff931289c3d4d", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/devel/13314.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/defaults.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13315.json b/mne-python/source/doc/sphinxext/prs/13315.json new file mode 100644 index 0000000000000000000000000000000000000000..ec59f508ea9d0814d887bf734c3fcf22f83bb400 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13315.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0c0e72efe1f062cce5fb2aaa9509cf77036ae6f9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 11, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13317.json b/mne-python/source/doc/sphinxext/prs/13317.json new file mode 100644 index 0000000000000000000000000000000000000000..0280760ea6ff0316f7a73ff2d80967c5ea84c08e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13317.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4b3cf34c30a4b1ee135b44300437b6fafabb8b36", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13318.json b/mne-python/source/doc/sphinxext/prs/13318.json new file mode 100644 index 0000000000000000000000000000000000000000..f1c91424cf373b5af9066f53edbb15811f1ab45a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13318.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "56f863d9f99afca363468d14b478eef8761698f9", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/credit_tools.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/prs/12848.json": { + "a": 67, + "d": 0 + }, + "doc/sphinxext/prs/13298.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/13304.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13305.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13306.json": { + "a": 103, + "d": 0 + }, + "doc/sphinxext/prs/13308.json": { + "a": 67, + "d": 0 + }, + "doc/sphinxext/prs/13310.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13311.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13313.json": { + "a": 55, + "d": 0 + }, + "doc/sphinxext/prs/13314.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13315.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13319.json b/mne-python/source/doc/sphinxext/prs/13319.json new file mode 100644 index 0000000000000000000000000000000000000000..72baa446b07987afbd341b3da189207111449fc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13319.json @@ -0,0 +1,283 @@ +{ + "merge_commit_sha": "0c106bc9c00a0f3136fdd8a55cc9852b2d8f8959", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 7, + "d": 1 + }, + "CITATION.cff": { + "a": 57, + "d": 25 + }, + "SECURITY.md": { + "a": 3, + "d": 3 + }, + "codemeta.json": { + "a": 171, + "d": 69 + }, + "doc/_static/versions.json": { + "a": 7, + "d": 2 + }, + "doc/changes/devel.rst": { + "a": 0, + "d": 5 + }, + "doc/changes/devel/12071.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12656.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12828.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12848.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/12910.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13019.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13028.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13037.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13042.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13044.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13048.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13054.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13056.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13058.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13062.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13063.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13065.bugfix.rst": { + "a": 0, + "d": 7 + }, + "doc/changes/devel/13067.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13069.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13070.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13080.apichange.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13080.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13082.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13083.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13097.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13100.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13101.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13107.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13113.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13123.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13144.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13145.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13172.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13174.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13178.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13179.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13179.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13183.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13184.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13184.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13208.bugfix.rst.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13218.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13225.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13228.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13232.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13233.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13234.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13241.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13261.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13268.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13276.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13277.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13280.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13284.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13286.bugfix.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/devel/13293.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13298.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13310.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/devel/13314.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/v1.10.rst": { + "a": 129, + "d": 0 + }, + "doc/development/whats_new.rst": { + "a": 1, + "d": 1 + }, + "doc/documentation/cited.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13320.json b/mne-python/source/doc/sphinxext/prs/13320.json new file mode 100644 index 0000000000000000000000000000000000000000..34dd5b42c16a8fe61f5ffd96417d61d3ee2db01e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13320.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ed26706d11833e2c4260069cfbf0e020c55d47fe", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/v1.10.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13321.json b/mne-python/source/doc/sphinxext/prs/13321.json new file mode 100644 index 0000000000000000000000000000000000000000..381540eba1a9a7cff77a3d0bf4b4851a45d74429 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13321.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "48f158893f0a64f8696f2c13e30121f7a90585e6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 23, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 15, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13322.json b/mne-python/source/doc/sphinxext/prs/13322.json new file mode 100644 index 0000000000000000000000000000000000000000..3a3a875e59485178e2fda3dbea410ea4d2940485 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13322.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "85e675985f2ac6f2facfa8d4e79164b056d2ea0c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 5, + "d": 5 + }, + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 3, + "d": 3 + }, + "environment.yml": { + "a": 4, + "d": 4 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 2, + "d": 6 + }, + "mne/preprocessing/maxwell.py": { + "a": 9, + "d": 27 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 42, + "d": 6 + }, + "mne/report/report.py": { + "a": 0, + "d": 10 + }, + "mne/utils/config.py": { + "a": 2, + "d": 2 + }, + "mne/utils/dataframe.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_config.py": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 7, + "d": 7 + }, + "tools/github_actions_dependencies.sh": { + "a": 6, + "d": 3 + }, + "tools/install_pre_requirements.sh": { + "a": 37, + "d": 57 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13327.json b/mne-python/source/doc/sphinxext/prs/13327.json new file mode 100644 index 0000000000000000000000000000000000000000..8a2b2610453cb00c893fffbfe13f9975b367fe4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13327.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3ac330a4c5887b7c19a3f4dd961ed071ecebb54a", + "authors": [ + { + "n": "Genuster", + "e": null + } + ], + "changes": { + "examples/decoding/ssd_spatial_filters.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/ssd.py": { + "a": 32, + "d": 1 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 38, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13330.json b/mne-python/source/doc/sphinxext/prs/13330.json new file mode 100644 index 0000000000000000000000000000000000000000..9471407e8146835bf65a64ca81e763dcc70e97af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13330.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4130e46d0499d8d58a4303f1d338b66e830e0588", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 7 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13331.json b/mne-python/source/doc/sphinxext/prs/13331.json new file mode 100644 index 0000000000000000000000000000000000000000..dec2036021200e4ba1ec3029531ff217907aa57d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13331.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c31ae1d9bd5f69660d1e94931ff6dff412a23dfd", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/js/custom-icons.js": { + "a": 19, + "d": 0 + }, + "doc/_static/style.css": { + "a": 11, + "d": 1 + }, + "doc/conf.py": { + "a": 17, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13332.json b/mne-python/source/doc/sphinxext/prs/13332.json new file mode 100644 index 0000000000000000000000000000000000000000..2766cb13009cd001cc4fd45f83eca153d38776e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13332.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "0474b499fd5ede62db4f8673989fe24e1945f2d1", + "authors": [ + { + "n": "Genuster", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/ged.rst": { + "a": 1, + "d": 1 + }, + "doc/api/decoding.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/dev/13332.newfeature.rst": { + "a": 4, + "d": 0 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 6, + "d": 4 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 11, + "d": 2 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 42, + "d": 35 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 53, + "d": 18 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/__init__.pyi": { + "a": 3, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 61, + "d": 5 + }, + "mne/decoding/csp.py": { + "a": 12, + "d": 39 + }, + "mne/decoding/spatial_filter.py": { + "a": 639, + "d": 0 + }, + "mne/decoding/tests/test_base.py": { + "a": 123, + "d": 16 + }, + "mne/decoding/tests/test_spatial_filter.py": { + "a": 190, + "d": 0 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13333.json b/mne-python/source/doc/sphinxext/prs/13333.json new file mode 100644 index 0000000000000000000000000000000000000000..c4aaca9b030b29d8c73b1edd4a72407c92c4d245 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13333.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cb385eeb682cbb4a4b7ce6e3523507e375b58a5b", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/_static/js/custom-icons.js": { + "a": 19, + "d": 0 + }, + "doc/_static/style.css": { + "a": 11, + "d": 1 + }, + "doc/conf.py": { + "a": 17, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13334.json b/mne-python/source/doc/sphinxext/prs/13334.json new file mode 100644 index 0000000000000000000000000000000000000000..5d1d206bbdb7ad929d11886b7c90217a1a3be589 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13334.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "9d114d6c745e2651d2e6c946c466cdd7f85e4f12", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 0, + "d": 5 + }, + "mne/gui/_coreg.py": { + "a": 5, + "d": 4 + }, + "mne/viz/_brain/_brain.py": { + "a": 46, + "d": 77 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 18, + "d": 13 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 3 + }, + "tools/circleci_bash_env.sh": { + "a": 0, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13335.json b/mne-python/source/doc/sphinxext/prs/13335.json new file mode 100644 index 0000000000000000000000000000000000000000..5255dc8bfff64440ef52a627a5549d58214612f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13335.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "aacf0cfc36d5122e3f4118344a5b2a672041b626", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 7 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13336.json b/mne-python/source/doc/sphinxext/prs/13336.json new file mode 100644 index 0000000000000000000000000000000000000000..852b3bd2b21b6218638412fe60e53b9b6eb08349 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13336.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "00a84a3817ba1b4c679c6b6aeaf38b6983a5ea0c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/mne_doc_utils.py": { + "a": 12, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13337.json b/mne-python/source/doc/sphinxext/prs/13337.json new file mode 100644 index 0000000000000000000000000000000000000000..e6b4616b6ead21d6e125b581c6d129f6a0692076 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13337.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1d318a43bf78bf360ded4eefb790c85bc515644e", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/mne_doc_utils.py": { + "a": 12, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13338.json b/mne-python/source/doc/sphinxext/prs/13338.json new file mode 100644 index 0000000000000000000000000000000000000000..d2087a2e681801a8dd9a7f005da1aba1492d5f90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13338.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8f6ecb0090f5ba7fb0b99c19511d702cc5bb3811", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13340.json b/mne-python/source/doc/sphinxext/prs/13340.json new file mode 100644 index 0000000000000000000000000000000000000000..20a44a9eeeea17421000297f7fa05abf2c7de03e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13340.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bf57d9ce3412b147591b74a6bb126e5072bb7642", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/index.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13341.json b/mne-python/source/doc/sphinxext/prs/13341.json new file mode 100644 index 0000000000000000000000000000000000000000..2a72516078ab31d66e7b20f4f7f310e683ee5549 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13341.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "be0edb1e24c5f4998580d199d1d9551a0c3c1d21", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/devel/13341.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 3, + "d": 4 + }, + "mne/report/tests/test_report.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13343.json b/mne-python/source/doc/sphinxext/prs/13343.json new file mode 100644 index 0000000000000000000000000000000000000000..a8ca72834f983bc148e67b7b4397636425993812 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13343.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "17c79290c0caecac7e555dfe86c3441c4006843b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_templates/sidebar-quicklinks.html": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13344.json b/mne-python/source/doc/sphinxext/prs/13344.json new file mode 100644 index 0000000000000000000000000000000000000000..0db4606021e85086e2eccf249cfc983bf225be69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13344.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "489423bbe7ae4957c98ae34cf17ff8c480bc07a9", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/devel/13341.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 3, + "d": 4 + }, + "mne/report/tests/test_report.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13345.json b/mne-python/source/doc/sphinxext/prs/13345.json new file mode 100644 index 0000000000000000000000000000000000000000..7fed85558ce9f8aa9aaecc8200249ab92cf68b5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13345.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "60f76e87b475e666bd38fd9713c483517eb55fd7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13346.json b/mne-python/source/doc/sphinxext/prs/13346.json new file mode 100644 index 0000000000000000000000000000000000000000..092262edddf800434b46691241f43d2210c96d30 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13346.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "043c8beb67e6a9364473ded5a57b1abbe983bf3d", + "authors": [ + { + "n": "Genuster", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/_ged.py": { + "a": 36, + "d": 19 + }, + "mne/decoding/base.py": { + "a": 70, + "d": 19 + }, + "mne/decoding/tests/test_ged.py": { + "a": 15, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13347.json b/mne-python/source/doc/sphinxext/prs/13347.json new file mode 100644 index 0000000000000000000000000000000000000000..e6dcebc212f949212e7015082c361589c93d4f26 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13347.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "94d9871acc920a47a04e9481d1fb2dfb25be7bfe", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/conf.py": { + "a": 16, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13349.json b/mne-python/source/doc/sphinxext/prs/13349.json new file mode 100644 index 0000000000000000000000000000000000000000..1d1da85f1ca47bc6f88b0a941da89b5daec5a100 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13349.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "167872bf6b25a0e09d5662688acde8d068e68f9a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".github/workflows/check_changelog.yml": { + "a": 1, + "d": 1 + }, + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "doc/_static/versions.json": { + "a": 1, + "d": 1 + }, + "doc/changes/dev.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/dev.rst.template": { + "a": 0, + "d": 0 + }, + "doc/changes/dev/.gitignore": { + "a": 0, + "d": 0 + }, + "doc/changes/dev/13112.bugfix.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/dev/13259.newfeature.rst": { + "a": 0, + "d": 0 + }, + "doc/changes/dev/13341.bugfix.rst": { + "a": 0, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/development/contributing.rst": { + "a": 2, + "d": 2 + }, + "doc/development/whats_new.rst": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/credit_tools.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_config.py": { + "a": 2, + "d": 2 + }, + "pyproject.toml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1335.json b/mne-python/source/doc/sphinxext/prs/1335.json new file mode 100644 index 0000000000000000000000000000000000000000..f14d31794f850079554e8960eb7e22822894a799 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1335.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f4ff521d09e3cf3b38d1b037161b55ef25502f0c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/layouts/EGI256.lout": { + "a": 257, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13350.json b/mne-python/source/doc/sphinxext/prs/13350.json new file mode 100644 index 0000000000000000000000000000000000000000..6cae54c55efcf51f078391a61f812a8cb9320e9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13350.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "3fbf9865c8e27f6cffe15fa5335e922e82933af7", + "authors": [ + { + "n": "Emmanuel Ferdman", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13350.apichange.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/cov.py": { + "a": 33, + "d": 7 + }, + "mne/decoding/_covs_ged.py": { + "a": 3, + "d": 0 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/rank.py": { + "a": 54, + "d": 8 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_rank.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13351.json b/mne-python/source/doc/sphinxext/prs/13351.json new file mode 100644 index 0000000000000000000000000000000000000000..ae8330ee29e05e79d0c320916b4d458473d2a4eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13351.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1c9ac7c145f55416661a912a1de66302d2433ba6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/misc.py": { + "a": 30, + "d": 12 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 0, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13354.json b/mne-python/source/doc/sphinxext/prs/13354.json new file mode 100644 index 0000000000000000000000000000000000000000..05684c206a3a6a974687b494c2646a009dc0c293 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13354.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "75d3900ae0aabeda7fcc873d642b0ac3cf9c0172", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/dev/13354.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/15_inplace.py": { + "a": 9, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13355.json b/mne-python/source/doc/sphinxext/prs/13355.json new file mode 100644 index 0000000000000000000000000000000000000000..43a785c384ac2874df6ec924aa4f11267c929032 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13355.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "73f77b49606469863d510e307fa4a05311bc8251", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13356.json b/mne-python/source/doc/sphinxext/prs/13356.json new file mode 100644 index 0000000000000000000000000000000000000000..0d637beb779c7104bfcf3948e84527c3fda6a8d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13356.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d77db389a37ff4603aec52485253d5b45ed61c65", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "pyproject.toml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13357.json b/mne-python/source/doc/sphinxext/prs/13357.json new file mode 100644 index 0000000000000000000000000000000000000000..2f93fdcbcdc9eeb180342ed1bdbc352c22287c11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13357.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f04fcaa851e64b379a1a107f18cf3fd5b6b18f42", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13357.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 30, + "d": 7 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 25, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13358.json b/mne-python/source/doc/sphinxext/prs/13358.json new file mode 100644 index 0000000000000000000000000000000000000000..2323a5790fc4d729204fc87d3d179b9a1b3ef6ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13358.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "bbd67f15deceeda6c3a8aedd2ac8d0da14bb370c", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/development/contributing.rst": { + "a": 1, + "d": 1 + }, + "doc/install/mne_c.rst": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/prs/13112.json": { + "a": 67, + "d": 0 + }, + "doc/sphinxext/prs/13259.json": { + "a": 91, + "d": 0 + }, + "doc/sphinxext/prs/13317.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13318.json": { + "a": 63, + "d": 0 + }, + "doc/sphinxext/prs/13319.json": { + "a": 283, + "d": 0 + }, + "doc/sphinxext/prs/13320.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13321.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13322.json": { + "a": 79, + "d": 0 + }, + "doc/sphinxext/prs/13327.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13330.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13331.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13333.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13334.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/13335.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13336.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13337.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13338.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13340.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13341.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13343.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13344.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13345.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13346.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13349.json": { + "a": 75, + "d": 0 + }, + "doc/sphinxext/prs/13351.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13354.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13355.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13356.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13360.json b/mne-python/source/doc/sphinxext/prs/13360.json new file mode 100644 index 0000000000000000000000000000000000000000..003abba488f8ebf109d3ba43635b63aaa0745094 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13360.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "45c7faf355b76265a5e88b1bbd72543e362547f9", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13361.json b/mne-python/source/doc/sphinxext/prs/13361.json new file mode 100644 index 0000000000000000000000000000000000000000..b8ac9623df720bada47e94751e56bf7236bb3c73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13361.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f7cab3af285eb3e1e7afd3879d76b5539942a01e", + "authors": [ + { + "n": "Genuster", + "e": null + } + ], + "changes": { + "doc/changes/dev/13361.bugfix.rst": { + "a": 8, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 68, + "d": 39 + }, + "mne/decoding/tests/test_base.py": { + "a": 26, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13365.json b/mne-python/source/doc/sphinxext/prs/13365.json new file mode 100644 index 0000000000000000000000000000000000000000..e5ae8354ab486c39ef2d9453ad982b5662cc83e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13365.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a07f970945aa36fc484bcd6ce88ce35f20a19a44", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13367.json b/mne-python/source/doc/sphinxext/prs/13367.json new file mode 100644 index 0000000000000000000000000000000000000000..6ae2ee1f1d9fb535f5b4a1e46b30f9b7598daabb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13367.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "70fbbd891afabf562a7315749dcefe9139df0020", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/release.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/install/installers.rst": { + "a": 7, + "d": 7 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 2, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 0 + }, + "mne/utils/tests/test_config.py": { + "a": 1, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13368.json b/mne-python/source/doc/sphinxext/prs/13368.json new file mode 100644 index 0000000000000000000000000000000000000000..2413fc33ae327560482e600627aed5450500afeb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13368.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b64c8231febe93926ec798c01ff01b5cb78055c3", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13369.json b/mne-python/source/doc/sphinxext/prs/13369.json new file mode 100644 index 0000000000000000000000000000000000000000..e335e54c595bf7ac9e4652a4b1031fe6ac4540d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13369.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f8d8295beef7527938163af42ee9fc896c08a8a4", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".github/FUNDING.yml": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13371.json b/mne-python/source/doc/sphinxext/prs/13371.json new file mode 100644 index 0000000000000000000000000000000000000000..d5f72d1b05a1b3b605b26c013cb3e7e4df3cd623 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13371.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3014786c595f4c5c8bfc0b1563be2da0e87aaf7f", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/dev/13371.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 9, + "d": 0 + }, + "tools/github_actions_test.sh": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13373.json b/mne-python/source/doc/sphinxext/prs/13373.json new file mode 100644 index 0000000000000000000000000000000000000000..bf1be24a6e09072d3af15cd2e6e8fd0a3fc1933a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13373.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "be5fcefc67a66d35c87c2e33f6ac2a7951f0ee35", + "authors": [ + { + "n": "Shristi Baral", + "e": null + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13373.other.rst": { + "a": 1, + "d": 0 + }, + "doc/development/contributing.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13375.json b/mne-python/source/doc/sphinxext/prs/13375.json new file mode 100644 index 0000000000000000000000000000000000000000..eec373472ab541aa049949c3e9cc873f001f7253 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13375.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "97fd038b2add2b5a08923d735af72e3688d6ebf0", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/dev/13375.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 2 + }, + "mne/time_frequency/spectrum.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 29, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13376.json b/mne-python/source/doc/sphinxext/prs/13376.json new file mode 100644 index 0000000000000000000000000000000000000000..d693e4964428291ec0af6621f706457e8e6b5234 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13376.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "befc4180c123e91d463ed7f737d703dc0090fce1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/dev/13376.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_utils.py": { + "a": 6, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13378.json b/mne-python/source/doc/sphinxext/prs/13378.json new file mode 100644 index 0000000000000000000000000000000000000000..a24b7259c80eba3dc5a3604bd7048e78c99115da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13378.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "637ab4e030f11184239a1a70b6dbb57b0cc84f5d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 7, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1338.json b/mne-python/source/doc/sphinxext/prs/1338.json new file mode 100644 index 0000000000000000000000000000000000000000..922cb7b94eda5d471d278d4c2b6949994d9aa6ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1338.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "a2349e348353e3a8c735be20c47ec3abe1f2fc76", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 8, + "d": 2 + }, + "mne/evoked.py": { + "a": 5, + "d": 1 + }, + "mne/io/base.py": { + "a": 8, + "d": 1 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 14, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 11, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 39, + "d": 3 + }, + "mne/utils.py": { + "a": 117, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13380.json b/mne-python/source/doc/sphinxext/prs/13380.json new file mode 100644 index 0000000000000000000000000000000000000000..41515aea9bccdcef7c90e8fd7b7642a2cd6864b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13380.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ace9381898b3ad9da9590a3d0b99abedaa74e033", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13381.json b/mne-python/source/doc/sphinxext/prs/13381.json new file mode 100644 index 0000000000000000000000000000000000000000..039daa3e47b300f4c3e0019e13f029c343b8b7cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13381.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0b0d5eaa48752ddbbbd1b41d04a835e03472983c", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13385.json b/mne-python/source/doc/sphinxext/prs/13385.json new file mode 100644 index 0000000000000000000000000000000000000000..8f20e410670e5e56e698f79e7ca951bb32ebd221 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13385.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "87b98dcdaae3e84d5d208fba091aca0086c259bc", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/autofix.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/codeql-analysis.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/credit.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/release.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13387.json b/mne-python/source/doc/sphinxext/prs/13387.json new file mode 100644 index 0000000000000000000000000000000000000000..6347ffb1b2861a9d2bab566f36d5361f8f34412d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13387.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5268ba8af4a7e169104c0115eac707924ce88dd8", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13389.json b/mne-python/source/doc/sphinxext/prs/13389.json new file mode 100644 index 0000000000000000000000000000000000000000..27b3c8e3a5a34f64a05cf9e661c2e041ef8123ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13389.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "adeb86583c99f5bdd7baf7cefe2d62bb50388ab7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/transforms.py": { + "a": 2, + "d": 1 + }, + "pyproject.toml": { + "a": 18, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1339.json b/mne-python/source/doc/sphinxext/prs/1339.json new file mode 100644 index 0000000000000000000000000000000000000000..15181a8fd0c4372854d2fb471cc2cd5702b2419b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1339.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "08ed7aa3dd6697cdb4c85adadcb81774717b455d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13391.json b/mne-python/source/doc/sphinxext/prs/13391.json new file mode 100644 index 0000000000000000000000000000000000000000..945ca9549a10cda389785587b9a058603fa67118 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13391.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0b374c1bda31875a61bcc456bd09854e4b487394", + "authors": [ + { + "n": "Tharupahan Jayawardana", + "e": "tharupahanjayawardana@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13391.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13393.json b/mne-python/source/doc/sphinxext/prs/13393.json new file mode 100644 index 0000000000000000000000000000000000000000..8f78fe883020f3f7c6e32e9223fb316a4f725b73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13393.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "d25726187b699818ac671dfdac18d2648f504c78", + "authors": [ + { + "n": "Genuster", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13393.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/decoding/_fixes.py": { + "a": 41, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 17, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 59, + "d": 11 + }, + "mne/decoding/search_light.py": { + "a": 10, + "d": 4 + }, + "mne/decoding/tests/test_ged.py": { + "a": 2, + "d": 7 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 10, + "d": 25 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 1, + "d": 9 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 8, + "d": 2 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 6 + }, + "mne/decoding/tests/test_xdawn.py": { + "a": 17, + "d": 0 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 66, + "d": 24 + }, + "mne/decoding/transformer.py": { + "a": 14, + "d": 0 + }, + "mne/decoding/xdawn.py": { + "a": 7, + "d": 1 + }, + "tools/vulture_allowlist.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13394.json b/mne-python/source/doc/sphinxext/prs/13394.json new file mode 100644 index 0000000000000000000000000000000000000000..b324c18462b8f9e6404fbe29a1636bf0b9e26ee4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13394.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b00cf992aab87f0b60cf93a707d1c5eca5298ebb", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13395.json b/mne-python/source/doc/sphinxext/prs/13395.json new file mode 100644 index 0000000000000000000000000000000000000000..91f7da01bf1e6bd5de5877a87bf85713c73e46a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13395.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "17c4e03b50b1f504ea607db68a616e677891cf75", + "authors": [ + { + "n": "Emrecan Çelik", + "e": "emrecncelik@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13395.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13396.json b/mne-python/source/doc/sphinxext/prs/13396.json new file mode 100644 index 0000000000000000000000000000000000000000..51acabd9b811d91bf4f0b38b8cb97d3465dee6d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13396.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0836e429b462124cecac18c59d00281de88fb89e", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13398.json b/mne-python/source/doc/sphinxext/prs/13398.json new file mode 100644 index 0000000000000000000000000000000000000000..55a940c0c945d66e49e487cab152078021b028e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13398.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "174c540c04f93bbba052da053682d1ebb0ab2e7e", + "authors": [ + { + "n": "Paul Anders", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 4, + "d": 1 + }, + "doc/changes/dev/13398.apichange.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "examples/visualization/mne_helmet.py": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 6, + "d": 6 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/forward/_field_interpolation.py": { + "a": 22, + "d": 7 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 31, + "d": 11 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 4, + "d": 2 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 6, + "d": 1 + }, + "tutorials/visualization/20_ui_events.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/134.json b/mne-python/source/doc/sphinxext/prs/134.json new file mode 100644 index 0000000000000000000000000000000000000000..de62d3dbe8f841a24a87a184de5d0f77cad7e17a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/134.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "71b988a21b4f2fcff9b799dacc4d85e4e68fe6e7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/constants.py": { + "a": 5, + "d": 2 + }, + "mne/fiff/tests/data/fsaverage_audvis-meg-cropped-lh.stc": { + "a": 0, + "d": 0 + }, + "mne/fiff/tests/data/fsaverage_audvis-meg-cropped-rh.stc": { + "a": 0, + "d": 0 + }, + "mne/forward.py": { + "a": 5, + "d": 2 + }, + "mne/label.py": { + "a": 45, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 325, + "d": 77 + }, + "mne/source_space.py": { + "a": 141, + "d": 18 + }, + "mne/stats/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 686, + "d": 101 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 118, + "d": 33 + }, + "mne/surface.py": { + "a": 14, + "d": 7 + }, + "mne/tests/test_source_estimate.py": { + "a": 58, + "d": 11 + }, + "mne/tests/test_source_space.py": { + "a": 21, + "d": 2 + }, + "mne/utils.py": { + "a": 18, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13400.json b/mne-python/source/doc/sphinxext/prs/13400.json new file mode 100644 index 0000000000000000000000000000000000000000..dc64cd60cd15f5ee909c613009e0748eef44a845 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13400.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "288165207c9eed17ba24a9e4d827f78cbd727a91", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13400.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 8, + "d": 1 + }, + "mne/source_space/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 77, + "d": 77 + }, + "mne/utils/docs.py": { + "a": 31, + "d": 12 + }, + "mne/utils/tests/test_check.py": { + "a": 43, + "d": 7 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 121, + "d": 138 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13403.json b/mne-python/source/doc/sphinxext/prs/13403.json new file mode 100644 index 0000000000000000000000000000000000000000..38c4ee33babad58c42ce5e87631471185e05034c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13403.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "4b6004a90a1210f852210898df5504b029dbedf0", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/12847.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13332.json": { + "a": 79, + "d": 0 + }, + "doc/sphinxext/prs/13357.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13358.json": { + "a": 135, + "d": 0 + }, + "doc/sphinxext/prs/13360.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13361.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13365.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13367.json": { + "a": 51, + "d": 0 + }, + "doc/sphinxext/prs/13368.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13369.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13371.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13373.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13376.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13378.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13380.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13381.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13385.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13387.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13389.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13391.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13393.json": { + "a": 79, + "d": 0 + }, + "doc/sphinxext/prs/13394.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13396.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13400.json": { + "a": 43, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13404.json b/mne-python/source/doc/sphinxext/prs/13404.json new file mode 100644 index 0000000000000000000000000000000000000000..e122be61b75d0fadf4495a46e7a483dc27507459 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13404.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ce79aab062854c11349906b1ff2b11668b0b01a5", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13405.json b/mne-python/source/doc/sphinxext/prs/13405.json new file mode 100644 index 0000000000000000000000000000000000000000..54219b7ece0d6f5343c2c7ba0a21446105330af3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13405.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "07a63fdb39db2c37e02d717c725129ea7aea1e4e", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13407.json b/mne-python/source/doc/sphinxext/prs/13407.json new file mode 100644 index 0000000000000000000000000000000000000000..b55114b15abc0b54b2eabb396fe778b6c5895dfc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13407.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "bb8d7609ceca60154a77ad43d29f121e08e2585e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/dev/13407.bugfix.rst": { + "a": 1, + "d": 0 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 0, + "d": 2 + }, + "examples/simulation/simulated_raw_data_using_subject_anatomy.py": { + "a": 0, + "d": 2 + }, + "mne/_ola.py": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 3, + "d": 3 + }, + "mne/conftest.py": { + "a": 10, + "d": 5 + }, + "mne/dipole.py": { + "a": 12, + "d": 10 + }, + "mne/forward/_compute_forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 111, + "d": 32 + }, + "mne/forward/forward.py": { + "a": 6, + "d": 21 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 79, + "d": 5 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 11 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 7, + "d": 6 + }, + "mne/simulation/raw.py": { + "a": 3, + "d": 2 + }, + "mne/simulation/tests/test_raw.py": { + "a": 2, + "d": 7 + }, + "mne/source_space/_source_space.py": { + "a": 42, + "d": 24 + }, + "mne/surface.py": { + "a": 53, + "d": 5 + }, + "mne/tests/test_dipole.py": { + "a": 12, + "d": 5 + }, + "mne/tests/test_morph.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 3 + }, + "tutorials/forward/30_forward.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13408.json b/mne-python/source/doc/sphinxext/prs/13408.json new file mode 100644 index 0000000000000000000000000000000000000000..72f9ba5553e3e592858a57931c4d1ca993737566 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13408.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "ff1092b42de1021a9d40ddd95788741e4eb125e7", + "authors": [ + { + "n": "FT", + "e": null + } + ], + "changes": { + "doc/changes/dev/13408.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/snirf/_snirf.py": { + "a": 3, + "d": 4 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 27, + "d": 1 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 69, + "d": 23 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 28, + "d": 8 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 81, + "d": 50 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 58, + "d": 43 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 139, + "d": 48 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 25, + "d": 10 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 89, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13409.json b/mne-python/source/doc/sphinxext/prs/13409.json new file mode 100644 index 0000000000000000000000000000000000000000..18bbf9a4baac5bfd8f955204a7c0474ec32b3b17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13409.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "0e6a17804f536ae1a38076a1a8a5b05974c95d7c", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/autofix.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/credit.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/release.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 6, + "d": 1 + }, + "doc/sphinxext/related_software.py": { + "a": 4, + "d": 0 + }, + "mne/_ola.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1341.json b/mne-python/source/doc/sphinxext/prs/1341.json new file mode 100644 index 0000000000000000000000000000000000000000..f27164724ff3ee7931f5cfcd208e9b4b24aac3a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1341.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "4406e6ab6a731b444ed4fe04cf5fd4f2eca4ff81", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 5, + "d": 3 + }, + "examples/plot_evoked_delayed_ssp.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_epochs.py": { + "a": 1, + "d": 2 + }, + "examples/plot_read_evoked.py": { + "a": 6, + "d": 3 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 47, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 5, + "d": 0 + }, + "mne/viz.py": { + "a": 152, + "d": 60 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13410.json b/mne-python/source/doc/sphinxext/prs/13410.json new file mode 100644 index 0000000000000000000000000000000000000000..1f11d724763eace6127c4bf8427205f0d8cf7bca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13410.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e3339cb92d2656d6ac2a5304811cb8d58e843405", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13411.json b/mne-python/source/doc/sphinxext/prs/13411.json new file mode 100644 index 0000000000000000000000000000000000000000..0507f5f41c73a8924c89835d64936b453f7ba95d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13411.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1d3501ece2a74057bdc788a804d0ebcc7033c954", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13412.json b/mne-python/source/doc/sphinxext/prs/13412.json new file mode 100644 index 0000000000000000000000000000000000000000..89a8e19a26c62dab33b30a97f6c29ddac34cc4de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13412.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3a46357c0fa1c2723e43e7b107f129f155c6ae0e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/preprocessing/_regress.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13413.json b/mne-python/source/doc/sphinxext/prs/13413.json new file mode 100644 index 0000000000000000000000000000000000000000..745b48efd616d3ffc6896af376290b1cbb619b03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13413.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9ee6e52e49e669e32d12991d20b090ffc40f2b4b", + "authors": [ + { + "n": "Christodoulos Kechris", + "e": "christodouloskech@gmail.com" + } + ], + "changes": { + "doc/sphinxext/related_software.py": { + "a": 1, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13416.json b/mne-python/source/doc/sphinxext/prs/13416.json new file mode 100644 index 0000000000000000000000000000000000000000..46c7cefadb55247da4fb05ce15d55ffe8ed4e6a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13416.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a8e2fe8f0245abeb1276d434b333a4d1fd4d420e", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 19, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1342.json b/mne-python/source/doc/sphinxext/prs/1342.json new file mode 100644 index 0000000000000000000000000000000000000000..b8d6d4003fdb445568d6b2baead98607c757a067 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1342.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d93f39b3cf8fb81aaa641943e56f51b76dacce81", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13420.json b/mne-python/source/doc/sphinxext/prs/13420.json new file mode 100644 index 0000000000000000000000000000000000000000..4e00efe7d623dc57c8633c8428b11eb272298f2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13420.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "662fb510097e38667a342e41fa525330154c5f74", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13421.json b/mne-python/source/doc/sphinxext/prs/13421.json new file mode 100644 index 0000000000000000000000000000000000000000..cc10cbda0bef3235008c679453732d17c06bdab8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13421.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "52234feffb2d46ebcc7d204697ec9bec15fd6d75", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 1, + "d": 3 + }, + "tools/github_actions_dependencies.sh": { + "a": 0, + "d": 4 + }, + "tools/github_actions_env_vars.sh": { + "a": 1, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13423.json b/mne-python/source/doc/sphinxext/prs/13423.json new file mode 100644 index 0000000000000000000000000000000000000000..6172e1cda7c021985be6a0976507e64955f6c2ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13423.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ae1d4ae9686c91a195b7f83b57fdc60124b219aa", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/v1.10.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13424.json b/mne-python/source/doc/sphinxext/prs/13424.json new file mode 100644 index 0000000000000000000000000000000000000000..1603a6a68194c171110ce0ca2810c270ac17d221 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13424.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "523f221bbb451c03efbfcba8faa7a3261aafeaf9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13426.json b/mne-python/source/doc/sphinxext/prs/13426.json new file mode 100644 index 0000000000000000000000000000000000000000..3edd7d16b03054adeae350b5b2fd6ef42f9fae7d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13426.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "08ef1c7a8d5ef8086a7e3ffda94d60e5a1263055", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 9, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 8, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13427.json b/mne-python/source/doc/sphinxext/prs/13427.json new file mode 100644 index 0000000000000000000000000000000000000000..88c1afda3917cc53016badf653d1aca83ae45ad6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13427.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "936bfae75fc4604443e5dc3e16c095cd9bd612a2", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13428.json b/mne-python/source/doc/sphinxext/prs/13428.json new file mode 100644 index 0000000000000000000000000000000000000000..a8177bc04be9e975daffaad38af0c9087a7d2cc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13428.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3e29187ce3a2a63b4497dc83d30869ad33ecd1be", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13428.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/export/_eeglab.py": { + "a": 8, + "d": 0 + }, + "mne/export/tests/test_export.py": { + "a": 2, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13431.json b/mne-python/source/doc/sphinxext/prs/13431.json new file mode 100644 index 0000000000000000000000000000000000000000..f8fb6f633f946169c12f30b353f073f5c214f60a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13431.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "34e2743d7f1a1684f6359520392fd437bf2cd92f", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 13, + "d": 7 + }, + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "doc/sphinxext/related_software.py": { + "a": 0, + "d": 1 + }, + "environment.yml": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 5, + "d": 0 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 0 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 1, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 0 + }, + "tools/hooks/update_environment_file.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13432.json b/mne-python/source/doc/sphinxext/prs/13432.json new file mode 100644 index 0000000000000000000000000000000000000000..a1f9475b5c1c20ccf6e9714a58e137b521853046 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13432.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "51b6a5c5fe711d10e959f1669960b4506cb4ad6e", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/sphinxext/prs/13350.json": { + "a": 51, + "d": 0 + }, + "doc/sphinxext/prs/13375.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13395.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13398.json": { + "a": 75, + "d": 0 + }, + "doc/sphinxext/prs/13403.json": { + "a": 107, + "d": 0 + }, + "doc/sphinxext/prs/13404.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13405.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13407.json": { + "a": 107, + "d": 0 + }, + "doc/sphinxext/prs/13409.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13410.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13411.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13412.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13413.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13416.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13420.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13423.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13424.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13426.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13427.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13428.json": { + "a": 35, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13434.json b/mne-python/source/doc/sphinxext/prs/13434.json new file mode 100644 index 0000000000000000000000000000000000000000..3995a187bc22a4752c24d899814492f0caf1db4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13434.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4fdde3a1cc87c66263d9b0c663d6a81abfcd89b5", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 7, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13435.json b/mne-python/source/doc/sphinxext/prs/13435.json new file mode 100644 index 0000000000000000000000000000000000000000..fba54c8e7a7e0436170e198e8effc59290ec6070 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13435.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "61bc8b8755da982491d4cebf940bbde160b98e1a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13435.newfeature.rst": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/export/_edf_bdf.py": { + "a": 75, + "d": 34 + }, + "mne/export/_export.py": { + "a": 22, + "d": 16 + }, + "mne/export/tests/test_export.py": { + "a": 48, + "d": 0 + }, + "pyproject.toml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13436.json b/mne-python/source/doc/sphinxext/prs/13436.json new file mode 100644 index 0000000000000000000000000000000000000000..e42a8e1f9e8eeb3ca3dd5b8275ba923a0ea67ec6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13436.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f7df4e5cc88bfb6795932ebbd7a3e72fdaff39d1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/check_changelog.yml": { + "a": 4, + "d": 1 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 3, + "d": 3 + }, + "mne/surface.py": { + "a": 3, + "d": 8 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13437.json b/mne-python/source/doc/sphinxext/prs/13437.json new file mode 100644 index 0000000000000000000000000000000000000000..d522701eb73a6e96a60872d494b5f190dc1b6c42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13437.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "49b09fb6e0f6353f49239ee7a35a08b955c496ac", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/export/_edf_bdf.py": { + "a": 75, + "d": 34 + }, + "mne/export/_export.py": { + "a": 22, + "d": 16 + }, + "mne/export/tests/test_export.py": { + "a": 48, + "d": 0 + }, + "pyproject.toml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13439.json b/mne-python/source/doc/sphinxext/prs/13439.json new file mode 100644 index 0000000000000000000000000000000000000000..c1b249d43dfec1c0f9af3a1a7f385d12063afaa9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13439.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "adc01cdc40cdaaf00d39108923dce352bd3091b2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13440.json b/mne-python/source/doc/sphinxext/prs/13440.json new file mode 100644 index 0000000000000000000000000000000000000000..480fdfa9bbb56bf32d55ac08b6bef6ca49a12fe2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13440.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "231f2247f873094ef225ab0b364fcc073386e397", + "authors": [ + { + "n": "Johannes Herforth", + "e": "johannes@herforth.net" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/changes/dev/13440.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "doc/install/advanced.rst": { + "a": 1, + "d": 1 + }, + "mne/datasets/_fetch.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/_phantom/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/config.py": { + "a": 26, + "d": 26 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "tools/get_minimal_commands.sh": { + "a": 2, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13442.json b/mne-python/source/doc/sphinxext/prs/13442.json new file mode 100644 index 0000000000000000000000000000000000000000..ebc5cb550e337f922a4c4e0edfe941f425ddcab5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13442.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f3c00cc7996b48f3c8166269c8d0c1d5b772edea", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/codeql-analysis.yml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13443.json b/mne-python/source/doc/sphinxext/prs/13443.json new file mode 100644 index 0000000000000000000000000000000000000000..977425f1466901cd5ef92af98705a9b7f161e7a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13443.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "06d09def3a2b9cbbae2b0a4af77b4ba0d81c228a", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13445.json b/mne-python/source/doc/sphinxext/prs/13445.json new file mode 100644 index 0000000000000000000000000000000000000000..02c75b4862ff31d5c5a575393edb88424318d5dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13445.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "7fb19a1a7dbf4b8d710dd71a88a1b8ee73e1e100", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/dev/13445.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/install/installers.rst": { + "a": 7, + "d": 7 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 3, + "d": 1 + }, + "mne/gui/_coreg.py": { + "a": 1, + "d": 10 + }, + "mne/gui/tests/test_coreg.py": { + "a": 1, + "d": 7 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 46, + "d": 12 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13446.json b/mne-python/source/doc/sphinxext/prs/13446.json new file mode 100644 index 0000000000000000000000000000000000000000..5a9318f44a6afc532415c8f3ad6de9bb9ecb8179 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13446.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3cfac64bbc778b0c52dcd76f4b4799cc59226fae", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13448.json b/mne-python/source/doc/sphinxext/prs/13448.json new file mode 100644 index 0000000000000000000000000000000000000000..04779aef6137782f706eec263fcd9d2732bfd031 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13448.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "aa2d977c794a6e25d3b0855e523b69141d6416ad", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/dev/13448.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 10, + "d": 15 + }, + "mne/io/nihon/nihon.py": { + "a": 5, + "d": 3 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1345.json b/mne-python/source/doc/sphinxext/prs/1345.json new file mode 100644 index 0000000000000000000000000000000000000000..d4eaffe777a081f7e4d1c2e0d7b72ef5429a5ff6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1345.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "41cfed03b8d17611cc3cb4671a9ed134d0cc1a9b", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 40, + "d": 27 + }, + "doc/source/whats_new.rst": { + "a": 6, + "d": 1 + }, + "mne/__init__.py": { + "a": 4, + "d": 3 + }, + "mne/channels.py": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 12, + "d": 0 + }, + "mne/evoked.py": { + "a": 60, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/array/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 6, + "d": 74 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 72, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 49, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13451.json b/mne-python/source/doc/sphinxext/prs/13451.json new file mode 100644 index 0000000000000000000000000000000000000000..1394676a859b490407866cf62a092819b409ccd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13451.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "54644a5d36027f9ee5b672a15e998768b39b745c", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/spec_zero.yml": { + "a": 62, + "d": 0 + }, + ".yamllint.yml": { + "a": 2, + "d": 0 + }, + "doc/changes/dev/13451.other.rst": { + "a": 1, + "d": 0 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + }, + "tools/dev/spec_zero_update_versions.py": { + "a": 258, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13452.json b/mne-python/source/doc/sphinxext/prs/13452.json new file mode 100644 index 0000000000000000000000000000000000000000..01a919c507b5546ff9091fbb7c97ae074dc5a1a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13452.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "4fb5442b12d38427c4f1e818e5d5944e59323ec3", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 3, + "d": 3 + }, + "doc/changes/dev/13452.other.rst": { + "a": 3, + "d": 0 + }, + "doc/development/contributing.rst": { + "a": 2, + "d": 2 + }, + "doc/sphinxext/related_software.txt": { + "a": 37, + "d": 0 + }, + "mne/utils/tests/test_config.py": { + "a": 5, + "d": 1 + }, + "pyproject.toml": { + "a": 68, + "d": 67 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tools/circleci_dependencies.sh": { + "a": 7, + "d": 12 + }, + "tools/github_actions_dependencies.sh": { + "a": 12, + "d": 5 + }, + "tools/hooks/update_environment_file.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13453.json b/mne-python/source/doc/sphinxext/prs/13453.json new file mode 100644 index 0000000000000000000000000000000000000000..7d51a84a4591c9642c50f140ed683f76ecde2d6c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13453.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "447a3e279e72fa9eac01c03b0f8dd20eadc87dff", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13456.json b/mne-python/source/doc/sphinxext/prs/13456.json new file mode 100644 index 0000000000000000000000000000000000000000..1779fe8fef4719e4563019a7c0cb021818d6d996 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13456.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e6db33a24114d54d7b0baf4c6f2e5a8368acafd5", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/dev/13456.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 7, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 24, + "d": 3 + }, + "mne/channels/montage.py": { + "a": 9, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13458.json b/mne-python/source/doc/sphinxext/prs/13458.json new file mode 100644 index 0000000000000000000000000000000000000000..7f4af2859b6130a2d57502baa587c660e9f6bd13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13458.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "147ff5995f91a0a2b1dcce15b16980c2a03143a6", + "authors": [ + { + "n": null, + "e": "myd7349@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/dev/13458.apichange.rst": { + "a": 1, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 17, + "d": 14 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13459.json b/mne-python/source/doc/sphinxext/prs/13459.json new file mode 100644 index 0000000000000000000000000000000000000000..d21ccc9a4e6f36e3d587c0b347192442e4086f24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13459.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "2bc159e6210334af85edcfc179ebaf825bab5d50", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/credit.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/spec_zero.yml": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 1 + }, + "pyproject.toml": { + "a": 9, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13460.json b/mne-python/source/doc/sphinxext/prs/13460.json new file mode 100644 index 0000000000000000000000000000000000000000..475522df4ed9558b82fd58ec4518d4459b573328 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13460.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "65a717ced7b93d40cde68b13d037d0bba8690ba0", + "authors": [ + { + "n": "Johannes Herforth", + "e": "johannes@herforth.net" + }, + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/dev/13460.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 19, + "d": 17 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 5, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 9, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 8, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 16, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13462.json b/mne-python/source/doc/sphinxext/prs/13462.json new file mode 100644 index 0000000000000000000000000000000000000000..2617a9e7b75620204a0d2904e45922ddd1586df0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13462.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8b1a914d28b164b3ebe21395a9b6dea950147099", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 4, + "d": 0 + }, + "doc/overview/people.rst": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13463.json b/mne-python/source/doc/sphinxext/prs/13463.json new file mode 100644 index 0000000000000000000000000000000000000000..0bbee61cefae34e7750b873e3e69733568c47bad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13463.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e50d56542864e727705faf71501a2789bd59cc6f", + "authors": [ + { + "n": "Michael Straube", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13463.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 11, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13464.json b/mne-python/source/doc/sphinxext/prs/13464.json new file mode 100644 index 0000000000000000000000000000000000000000..a7d8d457db3f8569b813d3c08149cbe397512793 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13464.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6ec537f525050db438256be0254ee3bff707463f", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/release.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13465.json b/mne-python/source/doc/sphinxext/prs/13465.json new file mode 100644 index 0000000000000000000000000000000000000000..af7769ae5ed37cf05ca3fb8c277c442af41fbe49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13465.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "610ebe5193457909485db37dcc0f750c0e6ecaaf", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13466.json b/mne-python/source/doc/sphinxext/prs/13466.json new file mode 100644 index 0000000000000000000000000000000000000000..b55afb98fbb3b8fda7e925010ec30069d5a74cea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13466.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3d7722fecf2bf1d99e1a526654087912836d839a", + "authors": [ + { + "n": "Michael Straube", + "e": null + } + ], + "changes": { + "doc/changes/dev/13466.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/reference.py": { + "a": 1, + "d": 1 + }, + "mne/_fiff/tests/test_reference.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13468.json b/mne-python/source/doc/sphinxext/prs/13468.json new file mode 100644 index 0000000000000000000000000000000000000000..60bd734f2188516b5b2d2914e1b99b9ba1eabc04 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13468.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f443d1c3e97028ace9db5b652e5275523c6a1fb0", + "authors": [ + { + "n": null, + "e": "myd7349@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/dev/13468.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/nihon/nihon.py": { + "a": 15, + "d": 7 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 37, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13469.json b/mne-python/source/doc/sphinxext/prs/13469.json new file mode 100644 index 0000000000000000000000000000000000000000..d15a511194ad80443cb490d8e113601f0afb837e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13469.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f4a3f3f46477a8fda6b1adff0a8094faa670bec0", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/dev/13469.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 10, + "d": 3 + }, + "mne/preprocessing/eyetracking/tests/test_calibration.py": { + "a": 34, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13470.json b/mne-python/source/doc/sphinxext/prs/13470.json new file mode 100644 index 0000000000000000000000000000000000000000..b2634e21f57d66644c82b33c4fd4081070069919 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13470.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f09b3da1a23757b76fd0adfdb9c6ed29db14af29", + "authors": [ + { + "n": "Michael Straube", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13470.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13471.json b/mne-python/source/doc/sphinxext/prs/13471.json new file mode 100644 index 0000000000000000000000000000000000000000..951f05f1c04fe9c18aab0ec0219be4767439ff0f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13471.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "7cfcc6ba0bd409e2ec2bb76598853288f61d6dc0", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/directive_formatting.py": { + "a": 88, + "d": 0 + }, + "examples/preprocessing/css.py": { + "a": 1, + "d": 0 + }, + "examples/time_frequency/compute_source_psd_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 0 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13475.json b/mne-python/source/doc/sphinxext/prs/13475.json new file mode 100644 index 0000000000000000000000000000000000000000..fc9523995432291fb98d3c40d16fa2117021e44c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13475.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1815534a3252faf159594ae5d9480b529ab9fb3d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".mailmap": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13477.json b/mne-python/source/doc/sphinxext/prs/13477.json new file mode 100644 index 0000000000000000000000000000000000000000..c69a8ea630f72482fe76c804fe879b4638ba121f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13477.json @@ -0,0 +1,163 @@ +{ + "merge_commit_sha": "54fe09332dda67a4fcf8b617d10bb83dfde266ee", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/credit.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/spec_zero.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 6, + "d": 3 + }, + "doc/sphinxext/prs/13096.json": { + "a": 51, + "d": 0 + }, + "doc/sphinxext/prs/13251.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13347.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13421.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13431.json": { + "a": 59, + "d": 0 + }, + "doc/sphinxext/prs/13432.json": { + "a": 91, + "d": 0 + }, + "doc/sphinxext/prs/13434.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13435.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13436.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13437.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/13439.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13440.json": { + "a": 63, + "d": 0 + }, + "doc/sphinxext/prs/13442.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13443.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13445.json": { + "a": 55, + "d": 0 + }, + "doc/sphinxext/prs/13446.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13448.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13451.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/13452.json": { + "a": 67, + "d": 0 + }, + "doc/sphinxext/prs/13453.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13456.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13458.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13459.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13460.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13462.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13463.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13464.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13465.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13466.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13469.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13470.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13475.json": { + "a": 15, + "d": 0 + }, + "pyproject.toml": { + "a": 2, + "d": 0 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 0, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13478.json b/mne-python/source/doc/sphinxext/prs/13478.json new file mode 100644 index 0000000000000000000000000000000000000000..5f80409f2a1fe04c62463e0a0f696792d888487e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13478.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "41d139dc3a3a9f646b7baa6c6c52b1710e4ff605", + "authors": [ + { + "n": "Michael Straube", + "e": null + } + ], + "changes": { + "doc/changes/dev/13478.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13479.json b/mne-python/source/doc/sphinxext/prs/13479.json new file mode 100644 index 0000000000000000000000000000000000000000..a301de26641cbcbab9dd4bf2438bfd5521669360 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13479.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ce0e1c00b4ca38c55c0307a128d88a90f02e695b", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13480.json b/mne-python/source/doc/sphinxext/prs/13480.json new file mode 100644 index 0000000000000000000000000000000000000000..80d7007aed6420c00d25276462f1c692e130c024 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13480.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1b921f4af5154bad40202d87428a2583ef896a00", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/_fiff/tests/test_constants.py": { + "a": 1, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 2 + }, + "mne/utils/tests/test_config.py": { + "a": 1, + "d": 2 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13481.json b/mne-python/source/doc/sphinxext/prs/13481.json new file mode 100644 index 0000000000000000000000000000000000000000..bf9845af2639dae2b6c5cbcd186573c83fffb189 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13481.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "587c99faf04012c399bc89e821ca6f2ee1077705", + "authors": [ + { + "n": "Michael Straube", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/dev/13481.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13482.json b/mne-python/source/doc/sphinxext/prs/13482.json new file mode 100644 index 0000000000000000000000000000000000000000..fe1d1f64e018a6aa20f5e285599f925e30f99dab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13482.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7ed5e27dc794171ed5248605804034b4cc44c928", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/dependabot.yml": { + "a": 2, + "d": 0 + }, + ".pre-commit-config.yaml": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13484.json b/mne-python/source/doc/sphinxext/prs/13484.json new file mode 100644 index 0000000000000000000000000000000000000000..37f779647b02aac67879844de16fa7d38a4eaa74 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13484.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "0a06818fc780ce2a344b7fe70c7acdb8ac90ca9f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/api/preprocessing.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/dev/13484.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 4, + "d": 0 + }, + "mne/chpi.py": { + "a": 334, + "d": 16 + }, + "mne/conftest.py": { + "a": 6, + "d": 3 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 3, + "d": 12 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 5 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_chpi.py": { + "a": 154, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 7, + "d": 0 + }, + "mne/transforms.py": { + "a": 35, + "d": 7 + }, + "mne/utils/_testing.py": { + "a": 78, + "d": 18 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13486.json b/mne-python/source/doc/sphinxext/prs/13486.json new file mode 100644 index 0000000000000000000000000000000000000000..23a5dfe6b0c51bdaa9a64f49431395e90bd0d7f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13486.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "08f64a2a41a4f8559afef3d3d32cf0b79123f514", + "authors": [ + { + "n": "Emma", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13486.bugfix.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/related_software.py": { + "a": 0, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 27, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 50, + "d": 6 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 33, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13489.json b/mne-python/source/doc/sphinxext/prs/13489.json new file mode 100644 index 0000000000000000000000000000000000000000..aadd8c3123bb6bacb60914843a288f250b2ae6fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13489.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ff3e0d509dc755593ae8cc89ddcfa90313ce9d1a", + "authors": [ + { + "n": "Bru", + "e": null + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13489.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 246, + "d": 33 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 132, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13490.json b/mne-python/source/doc/sphinxext/prs/13490.json new file mode 100644 index 0000000000000000000000000000000000000000..b57031be423ac379de1ae30dab7b513ab3e1aa69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13490.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "4051f3102d39fd2dcc85e0b3079a86c11289816c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Carina Forster", + "e": "carinaforster0611@gmail.com" + }, + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + }, + { + "n": "Scott Huberty", + "e": "52462026+scott-huberty@users.noreply.github.com" + }, + { + "n": "Erica Peterson", + "e": "nordme@uw.edu" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/spec_zero.yml": { + "a": 15, + "d": 7 + }, + ".github/workflows/tests.yml": { + "a": 12, + "d": 3 + }, + "environment.yml": { + "a": 11, + "d": 11 + }, + "pyproject.toml": { + "a": 40, + "d": 30 + }, + "tools/check_pyproject_helpers.py": { + "a": 61, + "d": 0 + }, + "tools/dev/spec_zero_update_versions.py": { + "a": 29, + "d": 22 + }, + "tools/github_actions_check_old.py": { + "a": 0, + "d": 35 + }, + "tools/github_actions_check_old_env.py": { + "a": 68, + "d": 0 + }, + "tools/github_actions_check_old_lockfile.py": { + "a": 68, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 28, + "d": 6 + }, + "tools/github_actions_env_vars.sh": { + "a": 5, + "d": 6 + }, + "tools/pylock.ci-old.toml": { + "a": 656, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13494.json b/mne-python/source/doc/sphinxext/prs/13494.json new file mode 100644 index 0000000000000000000000000000000000000000..b61459edf3d8da6aa5050fde9b6c7bd2a10fe3b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13494.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "18350ce173cf5a0769389cb5bbd2b3b840c0e82d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Christian O'Reilly", + "e": "christian.oreilly@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13494.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/montage.py": { + "a": 8, + "d": 6 + }, + "mne/viz/tests/test_montage.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13495.json b/mne-python/source/doc/sphinxext/prs/13495.json new file mode 100644 index 0000000000000000000000000000000000000000..14bd7c7c75367adc414dfb4c6dc0850f1ef67135 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13495.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fee04a2c3afad5ea1b49e42c9b5b5350c1bb4748", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13496.json b/mne-python/source/doc/sphinxext/prs/13496.json new file mode 100644 index 0000000000000000000000000000000000000000..39eaa064c624eaae0a22aa00fc6ed4ed9e1ac68c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13496.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dc61256b5b13c9c0e5f743f2f9f905ddd53402ed", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/development/governance.rst": { + "a": 8, + "d": 8 + }, + "doc/overview/people.rst": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13497.json b/mne-python/source/doc/sphinxext/prs/13497.json new file mode 100644 index 0000000000000000000000000000000000000000..7b0afa4177a17dc3954dff85697a1aba619d67f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13497.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "823463e744a65b6c5b424ad092331d27a5b31215", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Dev Parikh", + "e": "dev.dpparikh@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13497.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13498.json b/mne-python/source/doc/sphinxext/prs/13498.json new file mode 100644 index 0000000000000000000000000000000000000000..f6fa77b43cb87cc0b3208bb96da43738987061a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13498.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "78887f13d9f1624808e0091e595074ad07a8237c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/related_software.py": { + "a": 15, + "d": 40 + }, + "doc/sphinxext/related_software.txt": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/related_software_nodeps.txt": { + "a": 4, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13499.json b/mne-python/source/doc/sphinxext/prs/13499.json new file mode 100644 index 0000000000000000000000000000000000000000..84fbd8344c1319b78b62e0daee0033d180723573 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13499.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "90e5232cd8353ae4e3dc792c5c153e55b77296f4", + "authors": [ + { + "n": "Scott Huberty", + "e": null + }, + { + "n": "Wouter Kroot", + "e": "wouter@Wouters-MacBook-Pro.local" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/dev/13499.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/io/eyelink/_utils.py": { + "a": 44, + "d": 4 + }, + "mne/io/eyelink/tests/test_eyelink.py": { + "a": 44, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1350.json b/mne-python/source/doc/sphinxext/prs/1350.json new file mode 100644 index 0000000000000000000000000000000000000000..bfa7de4db8360d2280c890b54359090dae121b61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1350.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7c2cc67a1ea22e169d2528a920fd8054123dbab3", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/decoding/classifier.py": { + "a": 13, + "d": 4 + }, + "mne/time_frequency/multitaper.py": { + "a": 11, + "d": 1 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 12, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13501.json b/mne-python/source/doc/sphinxext/prs/13501.json new file mode 100644 index 0000000000000000000000000000000000000000..b797199ed191e2e3fa7ed7badf0ff8d405458ac4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13501.json @@ -0,0 +1,351 @@ +{ + "merge_commit_sha": "6f6802c54b85c38effb0b3cca7f3f96ea4a1e109", + "authors": [ + { + "n": "github-actions[bot]", + "e": "41898282+github-actions[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 2, + "d": 0 + }, + "CITATION.cff": { + "a": 41, + "d": 17 + }, + "SECURITY.md": { + "a": 3, + "d": 3 + }, + "codemeta.json": { + "a": 119, + "d": 47 + }, + "doc/_static/versions.json": { + "a": 7, + "d": 2 + }, + "doc/changes/dev.rst": { + "a": 0, + "d": 5 + }, + "doc/changes/dev/12847.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13068.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13096.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13109.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13112.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13156.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13176.dependency.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13176.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13251.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13259.newfeature.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/dev/13307.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13332.newfeature.rst": { + "a": 0, + "d": 4 + }, + "doc/changes/dev/13341.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13350.apichange.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13354.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13357.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13361.bugfix.rst": { + "a": 0, + "d": 8 + }, + "doc/changes/dev/13371.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13373.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13375.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13376.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13391.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13393.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13395.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13398.apichange.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13400.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13407.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13428.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13435.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13440.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13445.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13448.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13451.other.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13452.other.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/dev/13456.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13458.apichange.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13460.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13463.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13466.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13468.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13469.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13470.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13478.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13481.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13484.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13486.bugfix.rst": { + "a": 0, + "d": 3 + }, + "doc/changes/dev/13489.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13494.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13497.bugfix.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13499.newfeature.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/v1.11.rst": { + "a": 122, + "d": 0 + }, + "doc/development/whats_new.rst": { + "a": 1, + "d": 1 + }, + "doc/documentation/cited.rst": { + "a": 2, + "d": 2 + }, + "doc/sphinxext/credit_tools.py": { + "a": 6, + "d": 3 + }, + "doc/sphinxext/prs/13068.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13109.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/13156.json": { + "a": 51, + "d": 0 + }, + "doc/sphinxext/prs/13176.json": { + "a": 103, + "d": 0 + }, + "doc/sphinxext/prs/13307.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13468.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13471.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13477.json": { + "a": 163, + "d": 0 + }, + "doc/sphinxext/prs/13478.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13479.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13480.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13481.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13482.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13484.json": { + "a": 79, + "d": 0 + }, + "doc/sphinxext/prs/13486.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13489.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13494.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13495.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13496.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13497.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13498.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13499.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/related_software.py": { + "a": 0, + "d": 4 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13503.json b/mne-python/source/doc/sphinxext/prs/13503.json new file mode 100644 index 0000000000000000000000000000000000000000..b928c0933a7524942d30cb8c82f58715ad6272e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13503.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "2c4a3b03968a29570f87c3d741d2adc53b35f1dc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "LICENSE.txt": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 2, + "d": 2 + }, + "doc/changes/dev.rst": { + "a": 5, + "d": 0 + }, + "doc/development/whats_new.rst": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "pyproject.toml": { + "a": 2, + "d": 1 + }, + "tools/hooks/update_environment_file.py": { + "a": 2, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13504.json b/mne-python/source/doc/sphinxext/prs/13504.json new file mode 100644 index 0000000000000000000000000000000000000000..302650ac5ea57dfa6cd9ee7a6915a6978b1c9c7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13504.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d6320e9f0a47b65563783946057d1f238ff10d01", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/export/tests/test_export.py": { + "a": 3, + "d": 4 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 12 + }, + "mne/report/report.py": { + "a": 2, + "d": 2 + }, + "mne/source_space/_source_space.py": { + "a": 1, + "d": 1 + }, + "tools/dev/Makefile": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13505.json b/mne-python/source/doc/sphinxext/prs/13505.json new file mode 100644 index 0000000000000000000000000000000000000000..9cd9cbd9718d70c5c6a8d46101232610659752a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13505.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "09905e5745b2e5f3c81b442e2ce36558af181c54", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/ant/tests/test_ant.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13509.json b/mne-python/source/doc/sphinxext/prs/13509.json new file mode 100644 index 0000000000000000000000000000000000000000..6b6717142834795480cc5c5de8c213f2e07060d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13509.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ea2ae10b5f17af15361a0f6f3fc431cd654292cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/release.yaml": { + "a": 2, + "d": 0 + }, + ".github/workflows/autopush.yml": { + "a": 36, + "d": 0 + }, + ".github/workflows/credit.yml": { + "a": 7, + "d": 6 + }, + ".github/workflows/spec_zero.yml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13510.json b/mne-python/source/doc/sphinxext/prs/13510.json new file mode 100644 index 0000000000000000000000000000000000000000..5640e85fc6a3295d325b7c28faff63ad6029a935 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13510.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "97cc9e90c87b576a3b42f3a5a4fbf3f15b9a7856", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13514.json b/mne-python/source/doc/sphinxext/prs/13514.json new file mode 100644 index 0000000000000000000000000000000000000000..2e244d7aea4eeaa096e3b8ada9b87c5843c1ff46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13514.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "002d04fcecd07fdde40f14d836b87baaa3cbce82", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "mne/decoding/ssd.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13515.json b/mne-python/source/doc/sphinxext/prs/13515.json new file mode 100644 index 0000000000000000000000000000000000000000..ec6d6bde7c5f5930ce689188aeb9f0c0f43e0379 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13515.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "88ffdaa20c10e34f018370b438874fdadc749b67", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "mne/decoding/ssd.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13516.json b/mne-python/source/doc/sphinxext/prs/13516.json new file mode 100644 index 0000000000000000000000000000000000000000..9194a3e0cd687d2f3d333fbbeab25a37a4289f78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13516.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "2b2113546757cfe1a49c8dbcf0b8eeb90eb45006", + "authors": [ + { + "n": "mne[bot]", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/js/contrib-avatars.js": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "doc/development/governance.rst": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/credit_tools.py": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/prs/13501.json": { + "a": 351, + "d": 0 + }, + "doc/sphinxext/prs/13503.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13504.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13505.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13509.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13510.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13514.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13515.json": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13517.json b/mne-python/source/doc/sphinxext/prs/13517.json new file mode 100644 index 0000000000000000000000000000000000000000..25a436b8d51c5b16206f6a211182ba11b94163db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13517.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "04cd7c50f1638e19b723ad98ecf99a4f94393912", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/autofix.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/autopush.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/check_changelog.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/codeql-analysis.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/credit.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/release.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/spec_zero.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13519.json b/mne-python/source/doc/sphinxext/prs/13519.json new file mode 100644 index 0000000000000000000000000000000000000000..b5ea69e037ea2652ed228b6724d7c5e26f05ddb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13519.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "12694e644657b142bbc1f17bf1f73f6ce2051586", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13520.json b/mne-python/source/doc/sphinxext/prs/13520.json new file mode 100644 index 0000000000000000000000000000000000000000..6fcd9e2d65d4cf380a3709d5209ba1d457db2da7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13520.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2eefeb96b0e240d2fdb5db0595b2c8c2a1e024be", + "authors": [ + { + "n": "yaylim", + "e": "melihyayli@hotmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13520.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 6, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13521.json b/mne-python/source/doc/sphinxext/prs/13521.json new file mode 100644 index 0000000000000000000000000000000000000000..3978d4b7ec58434d03f350dfac7cf116e056f3ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13521.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "adcbae3c131bb0b0367b1f996efcf8677ca70024", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/dev/13521.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 7, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 9, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13525.json b/mne-python/source/doc/sphinxext/prs/13525.json new file mode 100644 index 0000000000000000000000000000000000000000..c0fa05db86fd5633882f0ffd84c6bade5b9672b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13525.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "f4853ce70c16bcde2f558eead852d6c432581e9a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/dev/13525.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/directive_formatting.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 3, + "d": 4 + }, + "mne/chpi.py": { + "a": 58, + "d": 20 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13526.json b/mne-python/source/doc/sphinxext/prs/13526.json new file mode 100644 index 0000000000000000000000000000000000000000..bc5049557c1b8b4f46f8a3074f41a7f41854459e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13526.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "718aabf1356c07b5c11333c67cd30c6dcbe61cf9", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/dev/13526.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/spectrum.py": { + "a": 6, + "d": 2 + }, + "mne/time_frequency/tests/test_spectrum.py": { + "a": 21, + "d": 6 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 18, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "mne/utils/spectrum.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13527.json b/mne-python/source/doc/sphinxext/prs/13527.json new file mode 100644 index 0000000000000000000000000000000000000000..345e882052e40a8546aa595e3fa45ac365ebb74c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13527.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "653130a5aaf4371d6377899b68c33844311a30b0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/github_actions_env_vars.sh": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13528.json b/mne-python/source/doc/sphinxext/prs/13528.json new file mode 100644 index 0000000000000000000000000000000000000000..e7c12d8811784e97649fc3990945a84cde018371 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13528.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "80788c8b3ef913bfd796c10290442704a36afcdb", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/dev/13528.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 4, + "d": 0 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 7, + "d": 0 + }, + "mne/export/tests/test_export.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13532.json b/mne-python/source/doc/sphinxext/prs/13532.json new file mode 100644 index 0000000000000000000000000000000000000000..59c437b85700dca12109efe94eb41e6836db2cc8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13532.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a0973c2a14eae0b95dfc58854b91533f1de2625b", + "authors": [ + { + "n": "varshaa-1616", + "e": "varshaa.1616@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "tutorials/preprocessing/14_quality_control_report.py": { + "a": 267, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13534.json b/mne-python/source/doc/sphinxext/prs/13534.json new file mode 100644 index 0000000000000000000000000000000000000000..07d98db23e50d23d0eba6b812aa011ae1e3bc131 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13534.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "340841fde29e645fbc2465906d899db1568dc645", + "authors": [ + { + "n": "mne[bot]", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/spec_zero.yml": { + "a": 8, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "pyproject.toml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13536.json b/mne-python/source/doc/sphinxext/prs/13536.json new file mode 100644 index 0000000000000000000000000000000000000000..883b36450974e3483a2082734c402c8ab8e63670 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13536.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0a2bba393f495fdd2bcc0655a6afc315f896c9a0", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13539.json b/mne-python/source/doc/sphinxext/prs/13539.json new file mode 100644 index 0000000000000000000000000000000000000000..01e3ad8fe0c4ea94d74b29919a14e7c07112e655 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13539.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "825652aa74d0d1abb5a35c5fdd3c63982ef2229c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/dev/13539.bugfix.rst": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 46, + "d": 0 + }, + "mne/evoked.py": { + "a": 2, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 5, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13540.json b/mne-python/source/doc/sphinxext/prs/13540.json new file mode 100644 index 0000000000000000000000000000000000000000..5ff8317d6b37ee453b04c0b01b81700bffc3407b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13540.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "eb80c6d473edb7dca9265a6375af76e345d3c50a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13541.json b/mne-python/source/doc/sphinxext/prs/13541.json new file mode 100644 index 0000000000000000000000000000000000000000..216a43f467cd013d952ff11f52f44b8513693d1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13541.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7b189e9a58156cd5ddce4c93429202bc3bce812b", + "authors": [ + { + "n": "Natneal.B", + "e": "nati.new77@gmail.com" + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 4, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13542.json b/mne-python/source/doc/sphinxext/prs/13542.json new file mode 100644 index 0000000000000000000000000000000000000000..7897faf26da116fb2c220ddf2a4d52feb6048d54 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13542.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "bc4f23260a8b1cf9d019d77f5a61534e371524bb", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13525.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/directive_formatting.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 3, + "d": 4 + }, + "mne/chpi.py": { + "a": 58, + "d": 20 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13544.json b/mne-python/source/doc/sphinxext/prs/13544.json new file mode 100644 index 0000000000000000000000000000000000000000..418cf3ca062ee23c4c6681938296265547f9f967 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13544.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8a11b2e8be48f7844b9b4b907a4a4e8f976b9ab7", + "authors": [ + { + "n": "Teemu Taivainen", + "e": "ttaiv@outlook.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/related_software.py": { + "a": 2, + "d": 1 + }, + "doc/sphinxext/related_software_nodeps.txt": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13545.json b/mne-python/source/doc/sphinxext/prs/13545.json new file mode 100644 index 0000000000000000000000000000000000000000..da8363912c6939f739c6a92a68d0a96cec1afdb2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13545.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b16611a2d81ba21e5e93c772120eaef6fc8d82bd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13546.json b/mne-python/source/doc/sphinxext/prs/13546.json new file mode 100644 index 0000000000000000000000000000000000000000..c972847efe5e7c05cd2b7746c25c7022303c9a7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13546.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bb2bdc1bed8515f5a741d268411b0fb9ed2bf72c", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13549.json b/mne-python/source/doc/sphinxext/prs/13549.json new file mode 100644 index 0000000000000000000000000000000000000000..02f8f191a3fb925f82358da857705b6f8ef0163a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13549.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a365496bcbe0836235db5f159206dad523cd62cd", + "authors": [ + { + "n": "Michael Straube", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/dev/13549.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13551.json b/mne-python/source/doc/sphinxext/prs/13551.json new file mode 100644 index 0000000000000000000000000000000000000000..a7946928b96aef89d99582e5bb30ad1c46720bff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13551.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1df1f18a2de5d3069bdfd8f5a4a50efaf6440ef8", + "authors": [ + { + "n": "Shruti Bhale", + "e": null + } + ], + "changes": { + "doc/changes/dev/13551.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/tests/test_import_nesting.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13557.json b/mne-python/source/doc/sphinxext/prs/13557.json new file mode 100644 index 0000000000000000000000000000000000000000..878aeced3473be3728b8c833271a70b7c1c14b45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13557.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5ce7c8d145073a69c8d609937d994448e437b766", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/release.yml": { + "a": 2, + "d": 2 + }, + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13558.json b/mne-python/source/doc/sphinxext/prs/13558.json new file mode 100644 index 0000000000000000000000000000000000000000..064f70c880585dee833d9e3af32a580defc9de27 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13558.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "db089c9353c7cb549d090fb47ca05c0d5bbeeb21", + "authors": [ + { + "n": "Gnaneswar Lopinti", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Scott Huberty", + "e": "seh33@uw.edu" + } + ], + "changes": { + "doc/changes/dev/13558.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/eyetracking/calibration.py": { + "a": 4, + "d": 0 + }, + "tutorials/preprocessing/90_eyetracking_data.py": { + "a": 13, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13559.json b/mne-python/source/doc/sphinxext/prs/13559.json new file mode 100644 index 0000000000000000000000000000000000000000..c0df09e5298f7fa61af6e9b410a0249a862a9b34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13559.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "3d78451d5fe271859642ed25159668ef3962d68c", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/sphinxext/related_software.py": { + "a": 5, + "d": 0 + }, + "mne/surface.py": { + "a": 9, + "d": 2 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13561.json b/mne-python/source/doc/sphinxext/prs/13561.json new file mode 100644 index 0000000000000000000000000000000000000000..0a4ac5f753381782de75fa77f345387850635cc6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13561.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1b3973b3880f53c8decbebcd7c4b8eed5ed924f4", + "authors": [ + { + "n": "Varun Kasyap Pentamaraju", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13563.json b/mne-python/source/doc/sphinxext/prs/13563.json new file mode 100644 index 0000000000000000000000000000000000000000..739b568f70447c7e27a6dfb22884c27d3183b007 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13563.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "0a88d41c844fc42ce2f75b39f793683f5ad2bf00", + "authors": [ + { + "n": "Varun Kasyap Pentamaraju", + "e": null + }, + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + } + ], + "changes": { + "mne/_fiff/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eyetracking/calibration.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13566.json b/mne-python/source/doc/sphinxext/prs/13566.json new file mode 100644 index 0000000000000000000000000000000000000000..e94503fe598e18f6d6a08f073ad087ef51949b4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13566.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "16c75424d5493ae2369685627b3196f445d1b665", + "authors": [ + { + "n": "Varun Kasyap Pentamaraju", + "e": null + } + ], + "changes": { + "doc/changes/dev/13566.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1357.json b/mne-python/source/doc/sphinxext/prs/1357.json new file mode 100644 index 0000000000000000000000000000000000000000..eaa008c1e9b5733fbc3c3bfa5a1113f77b23e35d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1357.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "200c1f6a1b42c68ce8eb39eb86c64ac8c151610a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 45, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13570.json b/mne-python/source/doc/sphinxext/prs/13570.json new file mode 100644 index 0000000000000000000000000000000000000000..0dfeb33ff0abd40f7142385b2ce56e9029424987 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13570.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4a5479d6b496dc18bd325919bc6c346ce7563cfb", + "authors": [ + { + "n": "Aman Srivastava", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/dev/13570.newfeature.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13572.json b/mne-python/source/doc/sphinxext/prs/13572.json new file mode 100644 index 0000000000000000000000000000000000000000..fa5d66c35655b233d84b6c57a7736911b2125b90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13572.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "98afbb2cc61931bdb57158b68249164c2d568f59", + "authors": [ + { + "n": "mne[bot]", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/credit_tools.py": { + "a": 3, + "d": 1 + }, + "doc/sphinxext/prs/13516.json": { + "a": 63, + "d": 0 + }, + "doc/sphinxext/prs/13517.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13519.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13521.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13525.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13526.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13527.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13528.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13534.json": { + "a": 31, + "d": 0 + }, + "doc/sphinxext/prs/13536.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13539.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/13540.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13542.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13545.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13546.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13549.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13557.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13559.json": { + "a": 47, + "d": 0 + }, + "doc/sphinxext/prs/13561.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13563.json": { + "a": 55, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13574.json b/mne-python/source/doc/sphinxext/prs/13574.json new file mode 100644 index 0000000000000000000000000000000000000000..24cc29c8f91d2364d1ad2f94f3a8ddf7f261cb1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13574.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e3815f9c8b5db15ddc614b2993cff41f0f460fd1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13578.json b/mne-python/source/doc/sphinxext/prs/13578.json new file mode 100644 index 0000000000000000000000000000000000000000..1f513ee83ad2d79652061801aff45d4a83c951c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13578.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7e357df76cb6cb75ed70b9ad7286fa151252f584", + "authors": [ + { + "n": "Himanshu Mahor", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/proj.py": { + "a": 16, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13579.json b/mne-python/source/doc/sphinxext/prs/13579.json new file mode 100644 index 0000000000000000000000000000000000000000..288dbfbadc70b38dfdd19b2e43b1d9433b53497e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13579.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "29435fbc4f5b8e4983fd2b6e558ad5955ae2f584", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/dev/13579.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 1, + "d": 2 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 2, + "d": 2 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13580.json b/mne-python/source/doc/sphinxext/prs/13580.json new file mode 100644 index 0000000000000000000000000000000000000000..3ae084df2c36ba2dde09859d1ad9e20a2c759ce8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13580.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a1449adf9264b3eb02ff566a922e0249b35d21ef", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/dev/13579.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 1, + "d": 2 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 2, + "d": 2 + }, + "mne/report/report.py": { + "a": 1, + "d": 1 + }, + "tools/install_pre_requirements.sh": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13585.json b/mne-python/source/doc/sphinxext/prs/13585.json new file mode 100644 index 0000000000000000000000000000000000000000..e15375bd602317bfe083bd81290f3f63c6733725 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13585.json @@ -0,0 +1,191 @@ +{ + "merge_commit_sha": "f133bea61c63486b4ab6cc7611173af514dd1751", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/dev/13585.other.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/_digitization.py": { + "a": 2, + "d": 1 + }, + "mne/_fiff/tag.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/_rap_music.py": { + "a": 4, + "d": 4 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/tests/test_external.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 3, + "d": 2 + }, + "mne/chpi.py": { + "a": 3, + "d": 3 + }, + "mne/conftest.py": { + "a": 3, + "d": 0 + }, + "mne/decoding/receptive_field.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 8, + "d": 7 + }, + "mne/decoding/transformer.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/event.py": { + "a": 2, + "d": 1 + }, + "mne/filter.py": { + "a": 6, + "d": 6 + }, + "mne/fixes.py": { + "a": 41, + "d": 0 + }, + "mne/forward/_compute_forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_lead_dots.py": { + "a": 4, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 2 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 4, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/morph.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 2 + }, + "mne/source_space/_source_space.py": { + "a": 2, + "d": 2 + }, + "mne/stats/cluster_level.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_transforms.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13586.json b/mne-python/source/doc/sphinxext/prs/13586.json new file mode 100644 index 0000000000000000000000000000000000000000..453f4d5a562255734d37a6b58d8aee2a48a4c31e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13586.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "09ea7ab2b16650a5f44fd12e19a790572033d19c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/install_pre_requirements.sh": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13587.json b/mne-python/source/doc/sphinxext/prs/13587.json new file mode 100644 index 0000000000000000000000000000000000000000..76b82366a228a6a8f85b9522aba4b7e5b9bd113a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13587.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "581682f83f55e02f76129895a233ffb206f05394", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13588.json b/mne-python/source/doc/sphinxext/prs/13588.json new file mode 100644 index 0000000000000000000000000000000000000000..9b951b97d14065164bd64f88c00e4625248aa4fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13588.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "01b5bd430c57053160cd936e77a9916b3a6e06fc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1359.json b/mne-python/source/doc/sphinxext/prs/1359.json new file mode 100644 index 0000000000000000000000000000000000000000..c6cc86a49b31792c1a7c71cf4783a468d42793f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1359.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "56f57d039c1c230c40978644e3406def2b547ae4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 13, + "d": 11 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ctps_.py": { + "a": 169, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 53, + "d": 16 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 84, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13590.json b/mne-python/source/doc/sphinxext/prs/13590.json new file mode 100644 index 0000000000000000000000000000000000000000..cbb025f3e8e75720176fc68ac80ad58b5598c460 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13590.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1801e8689b2a8aee0a7c3118c20b47545aecd4db", + "authors": [ + { + "n": "Himanshu Mahor", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/io/base.py": { + "a": 4, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13591.json b/mne-python/source/doc/sphinxext/prs/13591.json new file mode 100644 index 0000000000000000000000000000000000000000..58a6c99159d806ac1cc74412973da471f4e2ee73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13591.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f337a0ddf6f6543748122e793a775c4b55822f60", + "authors": [ + { + "n": "Simon Kern", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/dev/13591.other.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 11, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 1 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 31, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13593.json b/mne-python/source/doc/sphinxext/prs/13593.json new file mode 100644 index 0000000000000000000000000000000000000000..cc18b3c142e3ef58f371975d51c1cd677ba7b9ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13593.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ae887e52b8bddac9bbeae65039b2dc7d253c3731", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13593.other.rst": { + "a": 1, + "d": 0 + }, + "mne/utils/config.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13594.json b/mne-python/source/doc/sphinxext/prs/13594.json new file mode 100644 index 0000000000000000000000000000000000000000..fa57cd1f0db4778e1dc4af46cb6c7ff314a52ed4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13594.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7518f9833bd4d719d0012a79124b3e326ea0105a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/io/egi/events.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13595.json b/mne-python/source/doc/sphinxext/prs/13595.json new file mode 100644 index 0000000000000000000000000000000000000000..56c48f814e8ebdc7873c3e30f9100a1b2e1f88c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13595.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "8b8edb0a70e2fabb4d6c80a5d72caf63349a4a5e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/changes/dev/13595.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 20, + "d": 6 + }, + "mne/tests/test_cov.py": { + "a": 8, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 10 + }, + "mne/viz/tests/test_evoked.py": { + "a": 18, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 20, + "d": 14 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 0, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13596.json b/mne-python/source/doc/sphinxext/prs/13596.json new file mode 100644 index 0000000000000000000000000000000000000000..d6d817b1d4c29dfdf4e2ae32e9f06e9db6ff9e72 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13596.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6c1e9a054513fb86ba8edf4e4ceaf6ba08bf7eab", + "authors": [ + { + "n": "Himanshu Mahor", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13599.json b/mne-python/source/doc/sphinxext/prs/13599.json new file mode 100644 index 0000000000000000000000000000000000000000..77bc6dc79d84058c60007d2872d6a771a1d2bdad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13599.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ed9497d88a24ec0a03cd55db17bd057e79268418", + "authors": [ + { + "n": "Himanshu Mahor", + "e": null + } + ], + "changes": { + "doc/changes/dev/13596.other.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13600.json b/mne-python/source/doc/sphinxext/prs/13600.json new file mode 100644 index 0000000000000000000000000000000000000000..a0e60b2dd21aa777103c1351c96997f9a305e3cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13600.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e997d084a07882851bbb1639140de09749ecd408", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/gh_substitutions.py": { + "a": 18, + "d": 2 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13601.json b/mne-python/source/doc/sphinxext/prs/13601.json new file mode 100644 index 0000000000000000000000000000000000000000..96715799c0461bdbe2774e007e31c9a31b74a84c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13601.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ecccc3e0e70089c0c7a1f206bab546a112a136ff", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13602.json b/mne-python/source/doc/sphinxext/prs/13602.json new file mode 100644 index 0000000000000000000000000000000000000000..63d7154b9f050b089dabbc58aad6c6c4b4457d3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13602.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9f784fa56102e7984a6690d98f245e83e77181f1", + "authors": [ + { + "n": "Himanshu Mahor", + "e": null + } + ], + "changes": { + "doc/changes/dev/13602.other.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 1, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13606.json b/mne-python/source/doc/sphinxext/prs/13606.json new file mode 100644 index 0000000000000000000000000000000000000000..51416790ecab37e33f9b8f1fdf30131462b47ded --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13606.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1ebb93e6dc9f0dc0e7aa2f788f77c3dc14ce81e2", + "authors": [ + { + "n": "Thomas A Caswell", + "e": "tcaswell@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13606.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 3, + "d": 9 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13607.json b/mne-python/source/doc/sphinxext/prs/13607.json new file mode 100644 index 0000000000000000000000000000000000000000..e91426b41e5d3e58599d2d0376a0a0c7f41b0fc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13607.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fb76357808296815b6abbe53e5f0462de83ec5e6", + "authors": [ + { + "n": "Hamza Abdelhedi", + "e": "hamza.abdelhedii@gmail.com" + } + ], + "changes": { + "doc/sphinxext/related_software.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13609.json b/mne-python/source/doc/sphinxext/prs/13609.json new file mode 100644 index 0000000000000000000000000000000000000000..233bb26bb5c351959eda68e2001b2110e2a025d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13609.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1300eae4e88d3f38a71cd2a95b4dff41ca75d4bb", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + ".github/workflows/spec_zero.yml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1361.json b/mne-python/source/doc/sphinxext/prs/1361.json new file mode 100644 index 0000000000000000000000000000000000000000..c8f127523ce682c0c5b74523fb44c228b9fcc9c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1361.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f13274cb3f05904b4428c2e0b4124cf6439ea495", + "authors": [ + { + "n": "marmaduke woodman", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13610.json b/mne-python/source/doc/sphinxext/prs/13610.json new file mode 100644 index 0000000000000000000000000000000000000000..fa64cbec87d56a8d0c236cd1f87244aac2918a7c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13610.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "ab6346ecf025f6bdd3fbe5c83f92564fdfea9496", + "authors": [ + { + "n": "Bru", + "e": null + }, + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/_includes/data_formats.rst": { + "a": 3, + "d": 0 + }, + "doc/api/reading_raw_data.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/dev/13610.newfeature.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.pyi": { + "a": 2, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 3, + "d": 0 + }, + "mne/io/mef/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/mef/_utils.py": { + "a": 345, + "d": 0 + }, + "mne/io/mef/mef.py": { + "a": 300, + "d": 0 + }, + "mne/io/mef/tests/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/io/mef/tests/test_mef.py": { + "a": 193, + "d": 0 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "pyproject.toml": { + "a": 3, + "d": 0 + }, + "tools/hooks/update_environment_file.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13611.json b/mne-python/source/doc/sphinxext/prs/13611.json new file mode 100644 index 0000000000000000000000000000000000000000..897f4e6070d5a39bd49d7fc8149daa992f434b46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13611.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "e236b2e3096366c0098fc95acf590a06d84cd3d5", + "authors": [ + { + "n": "mne[bot]", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/spec_zero.yml": { + "a": 2, + "d": 1 + }, + ".github/workflows/tests.yml": { + "a": 2, + "d": 0 + }, + "doc/changes/dev/13611.dependency.rst": { + "a": 8, + "d": 0 + }, + "environment.yml": { + "a": 3, + "d": 3 + }, + "mne/decoding/_fixes.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 11, + "d": 5 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 4, + "d": 0 + }, + "pyproject.toml": { + "a": 3, + "d": 3 + }, + "tools/dev/spec_zero_update_versions.py": { + "a": 44, + "d": 11 + }, + "tools/environment_old.yml": { + "a": 5, + "d": 5 + }, + "tools/github_actions_check_old.py": { + "a": 35, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13612.json b/mne-python/source/doc/sphinxext/prs/13612.json new file mode 100644 index 0000000000000000000000000000000000000000..63b3b26ad5bdc0a4c628f0c71a5ab2845d05a80c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13612.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7ee7155dfe3435d62bf9589eed632fb13f66ec21", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13613.json b/mne-python/source/doc/sphinxext/prs/13613.json new file mode 100644 index 0000000000000000000000000000000000000000..d3f512972ea3dff7113c236b696771fc64d7be24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13613.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "59c8ceae23a7dd337b892056c97bcd6cdd35be4d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + }, + "mne/utils/linalg.py": { + "a": 49, + "d": 6 + }, + "mne/viz/tests/test_raw.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13620.json b/mne-python/source/doc/sphinxext/prs/13620.json new file mode 100644 index 0000000000000000000000000000000000000000..4334b634cf3c34c8c2fa49419ad8a127adac688e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13620.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "90edf9b84ee0db4900f8e4b272d07a7edf5d9252", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/development/roadmap.rst": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13624.json b/mne-python/source/doc/sphinxext/prs/13624.json new file mode 100644 index 0000000000000000000000000000000000000000..1397a7e61bce3200e5f67ebdbe84f9dd1ad0c25f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13624.json @@ -0,0 +1,167 @@ +{ + "merge_commit_sha": "ee8502bdf9d6fada2b0159dc1dd36ac40175cf1a", + "authors": [ + { + "n": "mne[bot]", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 3, + "d": 0 + }, + "doc/changes/dev/13520.bugfix.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/dev/13532.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/dev/13541.other.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/credit_tools.py": { + "a": 5, + "d": 1 + }, + "doc/sphinxext/prs/13408.json": { + "a": 59, + "d": 0 + }, + "doc/sphinxext/prs/13520.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13532.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13541.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13551.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13558.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13566.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13572.json": { + "a": 99, + "d": 0 + }, + "doc/sphinxext/prs/13574.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13578.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13579.json": { + "a": 39, + "d": 0 + }, + "doc/sphinxext/prs/13580.json": { + "a": 43, + "d": 0 + }, + "doc/sphinxext/prs/13585.json": { + "a": 191, + "d": 0 + }, + "doc/sphinxext/prs/13586.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13587.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13588.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13590.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13591.json": { + "a": 35, + "d": 0 + }, + "doc/sphinxext/prs/13593.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13594.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13596.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13599.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13600.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13601.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13602.json": { + "a": 19, + "d": 0 + }, + "doc/sphinxext/prs/13606.json": { + "a": 27, + "d": 0 + }, + "doc/sphinxext/prs/13607.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13609.json": { + "a": 15, + "d": 0 + }, + "doc/sphinxext/prs/13611.json": { + "a": 107, + "d": 0 + }, + "doc/sphinxext/prs/13612.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13613.json": { + "a": 23, + "d": 0 + }, + "doc/sphinxext/prs/13620.json": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13625.json b/mne-python/source/doc/sphinxext/prs/13625.json new file mode 100644 index 0000000000000000000000000000000000000000..db0214ca7903404bada0c146e4c45d0c74e3a1d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13625.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8b9aeae77567a524aa14fa984e5f0905265277a4", + "authors": [ + { + "n": "mne[bot]", + "e": null + }, + { + "n": "autofix-ci[bot]", + "e": "114827586+autofix-ci[bot]@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/spec_zero.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/dev/13625.dependency.rst": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13626.json b/mne-python/source/doc/sphinxext/prs/13626.json new file mode 100644 index 0000000000000000000000000000000000000000..ead8fec3b3e158b204fb63a5647fd8a92f1d3f2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13626.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f3f1c96afb65db1199debc6b4319ee1fcae04cae", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tools/dev/check_steering_committee.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13628.json b/mne-python/source/doc/sphinxext/prs/13628.json new file mode 100644 index 0000000000000000000000000000000000000000..29bcac35e28c62ee50e863d139acbeec42dabe96 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13628.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1138f8b254907362a69cc8d00830b1c12ba66610", + "authors": [ + { + "n": "Bru", + "e": null + } + ], + "changes": { + "doc/changes/dev/13628.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 5, + "d": 0 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13629.json b/mne-python/source/doc/sphinxext/prs/13629.json new file mode 100644 index 0000000000000000000000000000000000000000..284a71fca502e379733b471597abba43925628db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13629.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e127c0ea125cbfed0eca8b139ad2a33b80919ef7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/related_software.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1363.json b/mne-python/source/doc/sphinxext/prs/1363.json new file mode 100644 index 0000000000000000000000000000000000000000..34dc7b0166d01798234292ec5e640fa7b5d7214f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1363.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "986317fc85970a7b2f9b6d711ad2e3ab0aa030a3", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 9, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13630.json b/mne-python/source/doc/sphinxext/prs/13630.json new file mode 100644 index 0000000000000000000000000000000000000000..6779c6e9397597105d7ab9fcf91558d555d88d28 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13630.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "454fffa267e110a29e74a9ecb91355c8f5d83632", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13630.bugfix.rst": { + "a": 1, + "d": 0 + }, + "examples/inverse/dics_epochs.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/_fetch.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13631.json b/mne-python/source/doc/sphinxext/prs/13631.json new file mode 100644 index 0000000000000000000000000000000000000000..a7af0a005b6d79de0cdb510911acc8fda440fedc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13631.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b515c2098d2ae983a1fd0af7dd8733df34f7eb79", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/overview/people.rst": { + "a": 25, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13632.json b/mne-python/source/doc/sphinxext/prs/13632.json new file mode 100644 index 0000000000000000000000000000000000000000..587b80f3b9a9a73971831cff2234808c8a09d46d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13632.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e1aa5ed77a22f961a36480c68109f770660d5069", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/links.inc": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13643.json b/mne-python/source/doc/sphinxext/prs/13643.json new file mode 100644 index 0000000000000000000000000000000000000000..b206e6818f103383be8a88ac093b86bdb9b4c249 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13643.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cd888c17eaf1bb004550f969fc28ade808225430", + "authors": [ + { + "n": "dependabot[bot]", + "e": "49699333+dependabot[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".github/workflows/autofix.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13645.json b/mne-python/source/doc/sphinxext/prs/13645.json new file mode 100644 index 0000000000000000000000000000000000000000..026d02e7d332a4c8ce0ddcf9bc4cbed14c497774 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13645.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "87d1051d6932383e825ba377b21a221b2670db11", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "doc/changes/dev/13611.dependency.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/dev/13625.dependency.rst": { + "a": 0, + "d": 5 + }, + "tools/dev/spec_zero_update_versions.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13646.json b/mne-python/source/doc/sphinxext/prs/13646.json new file mode 100644 index 0000000000000000000000000000000000000000..917330c0dc183dcf10190808aabebcda4597209a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13646.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cd9ae4db0bfe7836a640c7f17a473788c5ca8e06", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + }, + "mne/io/hitachi/hitachi.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13647.json b/mne-python/source/doc/sphinxext/prs/13647.json new file mode 100644 index 0000000000000000000000000000000000000000..80e965fcf40a8e81c49f350ad9ca947d0033656a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13647.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8f75a7da57f8eac5159a8a0201b4a3f847585a99", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/dev/13647.newfeature.rst": { + "a": 1, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 19, + "d": 5 + }, + "mne/_fiff/tests/test_meas_info.py": { + "a": 45, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 13, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13649.json b/mne-python/source/doc/sphinxext/prs/13649.json new file mode 100644 index 0000000000000000000000000000000000000000..e98a7247b1a39508f5002c78781791e3179020e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13649.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "5e389d0a88206810f51f9e064158966a009f28b2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/dev/13630.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/gh_substitutions.py": { + "a": 18, + "d": 2 + }, + "doc/sphinxext/mne_doc_utils.py": { + "a": 12, + "d": 0 + }, + "doc/sphinxext/related_software.txt": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/related_software_nodeps.txt": { + "a": 1, + "d": 0 + }, + "examples/inverse/dics_epochs.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/_fetch.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13652.json b/mne-python/source/doc/sphinxext/prs/13652.json new file mode 100644 index 0000000000000000000000000000000000000000..388c5eedd088eb9bc6c7687eb2fe7cd71921444e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13652.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d6e978467ff4545f81876ce383c520d4d832c993", + "authors": [ + { + "n": "Himanshu Mahor", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13654.json b/mne-python/source/doc/sphinxext/prs/13654.json new file mode 100644 index 0000000000000000000000000000000000000000..70ddd2f5682bfebe0cd670a2e787a44d0f12db03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13654.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "70326482061245f1642619e764649e4dda8ead85", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/dev/13654.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13655.json b/mne-python/source/doc/sphinxext/prs/13655.json new file mode 100644 index 0000000000000000000000000000000000000000..e36a670a57adddcb85bf4ec452eead6794fae6d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13655.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f067dd7ea1a19d1f931a6f8433bf4052376f5349", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13654.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13658.json b/mne-python/source/doc/sphinxext/prs/13658.json new file mode 100644 index 0000000000000000000000000000000000000000..e33cc255c135ad0ef46ddb8aa62fd59cfed37efd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13658.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6589b8672bac9de0d8df31a6ad4afce916b3046c", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/_includes/bem_model.rst": { + "a": 1, + "d": 1 + }, + "doc/links.inc": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 8, + "d": 1 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1366.json b/mne-python/source/doc/sphinxext/prs/1366.json new file mode 100644 index 0000000000000000000000000000000000000000..72e71b8b85266bd414c2595874a6bb87551aea12 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1366.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3aec0ec92ee3e92b1f72afafaf08d63190354ff6", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 6, + "d": 4 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 39, + "d": 25 + }, + "mne/tests/test_label.py": { + "a": 45, + "d": 42 + }, + "mne/tests/test_source_estimate.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13663.json b/mne-python/source/doc/sphinxext/prs/13663.json new file mode 100644 index 0000000000000000000000000000000000000000..ff4d1b297ac6767d68ff03468da039880d788abc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13663.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a64cc193bd0d609ed3adbf94ada6245abf07d7e8", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13665.json b/mne-python/source/doc/sphinxext/prs/13665.json new file mode 100644 index 0000000000000000000000000000000000000000..f7478b30125200a41bd034bcd68e1ba412a9b727 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13665.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7de840cd5940c879feb1dad1a2e0c4e8ec6efee9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/related_software.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13668.json b/mne-python/source/doc/sphinxext/prs/13668.json new file mode 100644 index 0000000000000000000000000000000000000000..8f85ad0ba5b2efe2a9538df8f2fbbe7ad1738bb0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13668.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8dd298f48f27a678ccde2e2bfa6a5f57e274c584", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_includes/institutional-partners.rst": { + "a": 8, + "d": 8 + }, + "doc/conf.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13669.json b/mne-python/source/doc/sphinxext/prs/13669.json new file mode 100644 index 0000000000000000000000000000000000000000..45cfbcfd39811ed13614abc68e162f2d46c4026e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13669.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "557eca671d50499cd584232334f636f76afe7c07", + "authors": [ + { + "n": "Scott Huberty", + "e": null + } + ], + "changes": { + "doc/changes/dev/13669.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.pyi": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1367.json b/mne-python/source/doc/sphinxext/prs/1367.json new file mode 100644 index 0000000000000000000000000000000000000000..79cb590d081aa54651c8425ef4190b4953081b06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1367.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "b98f90b6ca949547d0c7b83819e1aabffe75e9bc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 5, + "d": 8 + }, + "mne/evoked.py": { + "a": 1, + "d": 2 + }, + "mne/io/base.py": { + "a": 1, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 0, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 6, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 14, + "d": 16 + }, + "mne/io/tree.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_utils.py": { + "a": 2, + "d": 4 + }, + "mne/utils.py": { + "a": 11, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13670.json b/mne-python/source/doc/sphinxext/prs/13670.json new file mode 100644 index 0000000000000000000000000000000000000000..a0bde4d169a534676173d326beb9215ee20fb7e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13670.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b8496fa0b4bd482125822ed4b3baa01dd0042294", + "authors": [ + { + "n": "Lumberbot (aka Jack)", + "e": null + }, + { + "n": "Scott Huberty", + "e": "52462026+scott-huberty@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/dev/13669.bugfix.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.pyi": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13672.json b/mne-python/source/doc/sphinxext/prs/13672.json new file mode 100644 index 0000000000000000000000000000000000000000..08ed04fcbb64724ba17faad96a1c92e36d673990 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13672.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "dcc711615a1e56275f17382aa8bea639e6ba8ae5", + "authors": [ + { + "n": "Aniket", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/dev/13672.bugfix.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13674.json b/mne-python/source/doc/sphinxext/prs/13674.json new file mode 100644 index 0000000000000000000000000000000000000000..bf91bac06aea77c88cafee17f0902a6cab5bbc56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13674.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "e9f9bf68c2a0b9dea20fd440350531aa89d29b33", + "authors": [ + { + "n": "Aniket", + "e": null + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/dev/13674.other.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "mne/_fiff/meas_info.py": { + "a": 6, + "d": 6 + }, + "mne/_fiff/proj.py": { + "a": 3, + "d": 3 + }, + "mne/_fiff/reference.py": { + "a": 3, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 11, + "d": 11 + }, + "mne/filter.py": { + "a": 3, + "d": 3 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_regress.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eyetracking/eyetracking.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/interpolate.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13675.json b/mne-python/source/doc/sphinxext/prs/13675.json new file mode 100644 index 0000000000000000000000000000000000000000..16502845ca3257240b1f5d28f50588c1ab187133 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13675.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "371920011756d14af038db4eb87b00a3e901b5c3", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/dev/13675.other.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13677.json b/mne-python/source/doc/sphinxext/prs/13677.json new file mode 100644 index 0000000000000000000000000000000000000000..7bc06b8bd30419f3f584479a31ac25a2a398d9a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13677.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6646cba043594cf413e4163f13e1c587adf848e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/mne_doc_utils.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 0, + "d": 1 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13678.json b/mne-python/source/doc/sphinxext/prs/13678.json new file mode 100644 index 0000000000000000000000000000000000000000..e07184afb7fbecc18902195a25031aa7d898cf5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13678.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c089d8560de394be180b7a7b591cfd581b3d4532", + "authors": [ + { + "n": "pre-commit-ci[bot]", + "e": "66853113+pre-commit-ci[bot]@users.noreply.github.com" + }, + { + "n": "mne[bot]", + "e": "50266005+mne-bot@users.noreply.github.com" + } + ], + "changes": { + ".pre-commit-config.yaml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1368.json b/mne-python/source/doc/sphinxext/prs/1368.json new file mode 100644 index 0000000000000000000000000000000000000000..074bcac1f9e5f86e7aedec671fc21305bb430e42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1368.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a0f3548ebac093a403d616dabef711bee30ed288", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 5, + "d": 0 + }, + "examples/inverse/plot_mne_crosstalk_function.py": { + "a": 83, + "d": 0 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 102, + "d": 0 + }, + "mne/minimum_norm/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 431, + "d": 0 + }, + "mne/minimum_norm/tests/test_psf_ctf.py": { + "a": 79, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/13690.json b/mne-python/source/doc/sphinxext/prs/13690.json new file mode 100644 index 0000000000000000000000000000000000000000..9089f4c0b59412ba9b1ffb7e62c44e5419a9c0ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/13690.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ce94c0577b4ec0ee50bee00dddf82f062deb1bb3", + "authors": [ + { + "n": "Thomas S. Binns", + "e": "t.s.binns@outlook.com" + } + ], + "changes": { + "examples/datasets/limo_data.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 6, + "d": 6 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1371.json b/mne-python/source/doc/sphinxext/prs/1371.json new file mode 100644 index 0000000000000000000000000000000000000000..ff8b399858abe7e02a01e28518181f66a3cf2518 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1371.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2dea04cbed2c733689c09b9202c50abc0a475907", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1375.json b/mne-python/source/doc/sphinxext/prs/1375.json new file mode 100644 index 0000000000000000000000000000000000000000..92e980d1ac9767b012e4edc0b4c216edbb15ed66 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1375.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dfadeef3dbc3ae4df7975aee75e7c47f5fed018c", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1376.json b/mne-python/source/doc/sphinxext/prs/1376.json new file mode 100644 index 0000000000000000000000000000000000000000..3e4c11ddf04203543ea679ddbb67a9215e231214 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1376.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2df9ead7c1875251b63ee668a303e317c82bc143", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1378.json b/mne-python/source/doc/sphinxext/prs/1378.json new file mode 100644 index 0000000000000000000000000000000000000000..0e220de6e62823a2c3132d054624ea24857d0dcb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1378.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8211e58a844bf6ac496f5ae63b8f3b85a591ab87", + "authors": [ + { + "n": "Praveen Sripad", + "e": "pravsripad@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1380.json b/mne-python/source/doc/sphinxext/prs/1380.json new file mode 100644 index 0000000000000000000000000000000000000000..e5e41ab3087e84146dbe670f597cafd6e585c2ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1380.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "b1ecaab866d65754e6bb94f42aebacf6b149ecc9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 4, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 8, + "d": 8 + }, + "mne/forward/forward.py": { + "a": 45, + "d": 8 + }, + "mne/forward/tests/test_forward.py": { + "a": 14, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 6, + "d": 1 + }, + "mne/io/pick.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1381.json b/mne-python/source/doc/sphinxext/prs/1381.json new file mode 100644 index 0000000000000000000000000000000000000000..e1488d9041f0f831c6fbac8837b003a0b7edfcc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1381.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3b9b27169eb16a15c3d95831684b568be2e1f712", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 125, + "d": 45 + }, + "mne/io/constants.py": { + "a": 11, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 72, + "d": 15 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 26, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1387.json b/mne-python/source/doc/sphinxext/prs/1387.json new file mode 100644 index 0000000000000000000000000000000000000000..eb8dadec5a3de62f53dd457f01dbd4bcba4088a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1387.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7c53bc0f86dacb1ad6267115ad34e137d19f1eb6", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 20, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/139.json b/mne-python/source/doc/sphinxext/prs/139.json new file mode 100644 index 0000000000000000000000000000000000000000..57a1d591ee2eeb9b76d2241c662b61e21bf9df50 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/139.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "87fb7b122fefc0752a296f926e43e95f286bdcd8", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/export/plot_epochs_as_data_frame.py": { + "a": 40, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1390.json b/mne-python/source/doc/sphinxext/prs/1390.json new file mode 100644 index 0000000000000000000000000000000000000000..282df088966753546b68143c3804cb830a596d38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1390.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "f40a08e34cceb2ab31a8099293e0969f618d1e0d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "MANIFEST.in": { + "a": 4, + "d": 0 + }, + "doc/source/python_reference.rst": { + "a": 22, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 6, + "d": 6 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/montages/10-5-System_Mastoids_EGI129.csd": { + "a": 467, + "d": 0 + }, + "mne/montages/EGI_256.csd": { + "a": 258, + "d": 0 + }, + "mne/montages/GSN-HydroCel-128.sfp": { + "a": 131, + "d": 0 + }, + "mne/montages/GSN-HydroCel-129.sfp": { + "a": 132, + "d": 0 + }, + "mne/montages/GSN-HydroCel-256.sfp": { + "a": 259, + "d": 0 + }, + "mne/montages/GSN-HydroCel-257.sfp": { + "a": 260, + "d": 0 + }, + "mne/montages/GSN-HydroCel-32.sfp": { + "a": 36, + "d": 0 + }, + "mne/montages/GSN-HydroCel-64_1.0.sfp": { + "a": 67, + "d": 0 + }, + "mne/montages/GSN-HydroCel-65_1.0.sfp": { + "a": 68, + "d": 0 + }, + "mne/montages/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/montages/easycap-M1.txt": { + "a": 75, + "d": 0 + }, + "mne/montages/easycap-M10.txt": { + "a": 62, + "d": 0 + }, + "mne/montages/montage.py": { + "a": 202, + "d": 0 + }, + "mne/montages/standard_1005.elc": { + "a": 698, + "d": 0 + }, + "mne/montages/standard_1020.elc": { + "a": 200, + "d": 0 + }, + "mne/montages/standard_alphabetic.elc": { + "a": 142, + "d": 0 + }, + "mne/montages/standard_postfixed.elc": { + "a": 212, + "d": 0 + }, + "mne/montages/standard_prefixed.elc": { + "a": 160, + "d": 0 + }, + "mne/montages/standard_primed.elc": { + "a": 212, + "d": 0 + }, + "mne/montages/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/montages/tests/test_montage.py": { + "a": 69, + "d": 0 + }, + "mne/utils.py": { + "a": 11, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/montage.py": { + "a": 38, + "d": 0 + }, + "mne/viz/tests/test_montage.py": { + "a": 16, + "d": 0 + }, + "setup.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1392.json b/mne-python/source/doc/sphinxext/prs/1392.json new file mode 100644 index 0000000000000000000000000000000000000000..9ca34d20ce4a32da6c5216829877d2f5aaac72bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1392.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "390143b8c2188442837088649de14c6c022c3073", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1396.json b/mne-python/source/doc/sphinxext/prs/1396.json new file mode 100644 index 0000000000000000000000000000000000000000..1401c0aaf8112c014fa051445500fd3ef1714f6e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1396.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d34e4a227656a733425b0961cf8340c892eae367", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_kit2fiff_gui.py": { + "a": 26, + "d": 15 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 24, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1398.json b/mne-python/source/doc/sphinxext/prs/1398.json new file mode 100644 index 0000000000000000000000000000000000000000..f0fdf4812672d3abbfcea988a1707cd00730f51f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1398.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a08cf6f4a643489067a691641f4210983c8653c9", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 27, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 0 + }, + "mne/viz.py": { + "a": 48, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1399.json b/mne-python/source/doc/sphinxext/prs/1399.json new file mode 100644 index 0000000000000000000000000000000000000000..b4eaf64bccdf84c3c0e9a149bbaa5f385a9fffed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1399.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1dbda634b22647f1ec86fc9946a31385024d7aab", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 7, + "d": 5 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 39, + "d": 21 + }, + "mne/preprocessing/ica.py": { + "a": 54, + "d": 39 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/14.json b/mne-python/source/doc/sphinxext/prs/14.json new file mode 100644 index 0000000000000000000000000000000000000000..ec595ad56e880a7e77f928d8e3d036af53a8226c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/14.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "791cca17b426088dc5732ec5be71933912cc0942", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 163, + "d": 8 + }, + "mne/tests/test_source_estimate.py": { + "a": 18, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/140.json b/mne-python/source/doc/sphinxext/prs/140.json new file mode 100644 index 0000000000000000000000000000000000000000..fddb1a0fc4ad943a32ac49a9f60e08d95bae8ded --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/140.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d895111057a43047b707e22d0078e89df27c2923", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1402.json b/mne-python/source/doc/sphinxext/prs/1402.json new file mode 100644 index 0000000000000000000000000000000000000000..a5bc6869c8def5532a043eace1615f5e1f8e89d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1402.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "c525b255ada6ce0f263c89988e04adb0f65625d3", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_evoked_topomap.py": { + "a": 4, + "d": 5 + }, + "examples/plot_ssp_projs_topomaps.py": { + "a": 0, + "d": 3 + }, + "mne/evoked.py": { + "a": 18, + "d": 11 + }, + "mne/layouts/layout.py": { + "a": 23, + "d": 29 + }, + "mne/preprocessing/ica.py": { + "a": 12, + "d": 5 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 2 + }, + "mne/viz.py": { + "a": 267, + "d": 61 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1405.json b/mne-python/source/doc/sphinxext/prs/1405.json new file mode 100644 index 0000000000000000000000000000000000000000..09d7988bc573f7cf34c714df54f6135d63cd167e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1405.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1a6e5159fe0610acb5320f7858270aaa75b3371d", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/evoked.py": { + "a": 8, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 10, + "d": 3 + }, + "mne/tests/test_viz.py": { + "a": 3, + "d": 21 + }, + "mne/viz.py": { + "a": 21, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1406.json b/mne-python/source/doc/sphinxext/prs/1406.json new file mode 100644 index 0000000000000000000000000000000000000000..22c2069f3e0bb73d1c604f7ed40718f3631cf233 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1406.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "88ad4ce209b4ab3ea249315fc18bfc0f1879ec7d", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/tests/test_viz.py": { + "a": 9, + "d": 4 + }, + "mne/viz.py": { + "a": 13, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1408.json b/mne-python/source/doc/sphinxext/prs/1408.json new file mode 100644 index 0000000000000000000000000000000000000000..31f47e8a4430a4905b69c20ac81badbea2d49cf8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1408.json @@ -0,0 +1,651 @@ +{ + "merge_commit_sha": "8e50a3d326d54b8ead303f9a4b621dc1b96d44ba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_sensors.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 2, + "d": 2 + }, + "examples/export/plot_epochs_as_data_frame.py": { + "a": 1, + "d": 1 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 2, + "d": 2 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 1, + "d": 1 + }, + "examples/export/plot_raw_to_nitime.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_dipole_fit_result.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_morph_data.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_stc.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/plot_decimate_head_surface.py": { + "a": 1, + "d": 1 + }, + "examples/plot_define_target_events.py": { + "a": 1, + "d": 1 + }, + "examples/plot_estimate_covariance_matrix_baseline.py": { + "a": 1, + "d": 1 + }, + "examples/plot_estimate_covariance_matrix_raw.py": { + "a": 1, + "d": 1 + }, + "examples/plot_evoked_delayed_ssp.py": { + "a": 2, + "d": 2 + }, + "examples/plot_evoked_topomap_delayed_ssp.py": { + "a": 2, + "d": 2 + }, + "examples/plot_evoked_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/plot_extract_events_from_raw.py": { + "a": 1, + "d": 1 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 2, + "d": 2 + }, + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/plot_meg_eeg_fields_3d.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_and_write_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_bem_surfaces.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_forward.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_noise_covariance_matrix.py": { + "a": 1, + "d": 1 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "examples/plot_ssp_projs_sensitivity_map.py": { + "a": 1, + "d": 1 + }, + "examples/plot_ssp_projs_topomaps.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topo_channel_epochs_image.py": { + "a": 2, + "d": 2 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 2, + "d": 2 + }, + "examples/plot_topo_customized.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topography.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "examples/read_events.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_single_trial_spectra.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_tfr_topography.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/baseline.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/channels.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_surf2bem.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sample/sample.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/classifier.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/read.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/diff.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/matrix.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/open.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 2, + "d": 2 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_compensator.py": { + "a": 1, + "d": 1 + }, + "mne/io/tree.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/layouts/layout.py": { + "a": 2, + "d": 2 + }, + "mne/layouts/tests/test_layout.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/misc.py": { + "a": 1, + "d": 1 + }, + "mne/parallel.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/proj.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/mockclient.py": { + "a": 2, + "d": 2 + }, + "mne/selection.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 2 + }, + "mne/stats/multi_comp.py": { + "a": 1, + "d": 1 + }, + "mne/stats/parametric.py": { + "a": 2, + "d": 2 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_fixes.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz.py": { + "a": 1, + "d": 1 + }, + "setup.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1409.json b/mne-python/source/doc/sphinxext/prs/1409.json new file mode 100644 index 0000000000000000000000000000000000000000..66cad7e871fe94b9511f5c1b7093503ba1cbfa46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1409.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ac947d0723c093c4945bee92cfe7793940016643", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 23, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1411.json b/mne-python/source/doc/sphinxext/prs/1411.json new file mode 100644 index 0000000000000000000000000000000000000000..a6f107eb126164d8d4321c5e09b571f8ac5e60a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1411.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "585e5cbe08f3f3b0eb4588a292f734f2a911c1c7", + "authors": [ + { + "n": "marmaduke woodman", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1412.json b/mne-python/source/doc/sphinxext/prs/1412.json new file mode 100644 index 0000000000000000000000000000000000000000..72fdd63491ca797d98afeb2d8f30ddf93545af3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1412.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "14e9a0f015dd627b48416a6e0ce277696c1aed70", + "authors": [ + { + "n": "marmaduke woodman", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 4, + "d": 0 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1413.json b/mne-python/source/doc/sphinxext/prs/1413.json new file mode 100644 index 0000000000000000000000000000000000000000..d783b9a5a2aa3b5434371a89e2d07b232390f484 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1413.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "92bd8c7165d127cedf5608ec13a17ccdb26a43c6", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1415.json b/mne-python/source/doc/sphinxext/prs/1415.json new file mode 100644 index 0000000000000000000000000000000000000000..0eb8ad5bb73f9112031b39030a4ca79bf5e1b28e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1415.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "70b9035e162a4a9dd89585d8d1d752b7f18f65f4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 0 + }, + "mne/tests/test_utils.py": { + "a": 3, + "d": 1 + }, + "mne/utils.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1418.json b/mne-python/source/doc/sphinxext/prs/1418.json new file mode 100644 index 0000000000000000000000000000000000000000..343679133d7493361d08139615e3a1511ee061c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1418.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3ceb71122e7fbae757686cb148ac16995af1f950", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/viz.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1419.json b/mne-python/source/doc/sphinxext/prs/1419.json new file mode 100644 index 0000000000000000000000000000000000000000..e412b1a76212393f15dfca30e9bfaba723569653 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1419.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cf93bc65a6861a078539fde0a7e9847e7ea21548", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/evoked.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/142.json b/mne-python/source/doc/sphinxext/prs/142.json new file mode 100644 index 0000000000000000000000000000000000000000..3266ccb49aa81bf1420b3e7b8f3b91e19b25d085 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/142.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "6845038f3e7c0e080986ed83dda618c030a7b08c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 2, + "d": 2 + }, + "doc/source/whats_new.rst": { + "a": 12, + "d": 0 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 64, + "d": 0 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 34, + "d": 0 + }, + "examples/export/plot_raw_to_nitime.py": { + "a": 83, + "d": 0 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_and_write_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 56, + "d": 4 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/evoked.py": { + "a": 22, + "d": 0 + }, + "mne/fiff/raw.py": { + "a": 93, + "d": 1 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 17, + "d": 0 + }, + "mne/fiff/tests/test_raw.py": { + "a": 51, + "d": 3 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/proj.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 26, + "d": 0 + }, + "mne/time_frequency/ar.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1420.json b/mne-python/source/doc/sphinxext/prs/1420.json new file mode 100644 index 0000000000000000000000000000000000000000..756b4ed91a82c677e36aba37754159480c27f212 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1420.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "1f096f76619b6f63316bbd609756337e9d3a7ae8", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/tests/test_viz.py": { + "a": 0, + "d": 676 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "mne/viz.py": { + "a": 0, + "d": 5223 + }, + "mne/viz/_3d.py": { + "a": 635, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 19, + "d": 0 + }, + "mne/viz/circle.py": { + "a": 408, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 449, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 292, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 484, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 506, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 610, + "d": 0 + }, + "mne/viz/tests/__init__py": { + "a": 0, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 117, + "d": 0 + }, + "mne/viz/tests/test_circle.py": { + "a": 94, + "d": 0 + }, + "mne/viz/tests/test_epochs.py": { + "a": 118, + "d": 0 + }, + "mne/viz/tests/test_evoked.py": { + "a": 107, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 149, + "d": 0 + }, + "mne/viz/tests/test_misc.py": { + "a": 115, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 111, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 138, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 150, + "d": 0 + }, + "mne/viz/tests/test_utils.py": { + "a": 28, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 723, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 1029, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 365, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1422.json b/mne-python/source/doc/sphinxext/prs/1422.json new file mode 100644 index 0000000000000000000000000000000000000000..0c13b1d621d525fadeb4abbb944edd77a5ffc171 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1422.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d13681dfc8961b96654a17ee7e4e2584c1346260", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "examples/realtime/ftclient_rt_average.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 14, + "d": 7 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 68, + "d": 0 + }, + "mne/utils.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1424.json b/mne-python/source/doc/sphinxext/prs/1424.json new file mode 100644 index 0000000000000000000000000000000000000000..197a2d5e910c985b7b5d3b7da6be2520fee9db4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1424.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "05a38415479692438a526f87ea9b965b1c7a356d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/surface.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1425.json b/mne-python/source/doc/sphinxext/prs/1425.json new file mode 100644 index 0000000000000000000000000000000000000000..99f571f9f25075c87cb1c7cfc029cd23a36b51b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1425.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "3610ea9df2fe7cce4c29a8a257f2b2161f6281a3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 6, + "d": 3 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 5, + "d": 2 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 4, + "d": 4 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 3, + "d": 3 + }, + "mne/realtime/tests/test_stim_client_server.py": { + "a": 5, + "d": 2 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 6, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1426.json b/mne-python/source/doc/sphinxext/prs/1426.json new file mode 100644 index 0000000000000000000000000000000000000000..d2d00aeb567396fae774029e51083ca2dd8342c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1426.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "36e7244c90548c503f34fc36f2d9b57d0985025c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1427.json b/mne-python/source/doc/sphinxext/prs/1427.json new file mode 100644 index 0000000000000000000000000000000000000000..32f1ac8920bfe2754baa22e610082b189f557bac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1427.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5d71237763b800df6408f118a63a43e9c6975c7f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 63, + "d": 16 + }, + "mne/tests/test_source_space.py": { + "a": 13, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/143.json b/mne-python/source/doc/sphinxext/prs/143.json new file mode 100644 index 0000000000000000000000000000000000000000..2fd8b664e1837551c20180b3e3182c6cbca23b0e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/143.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1e2ddcff56ddfe887800d22000b6cef56b161e8c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 47, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1432.json b/mne-python/source/doc/sphinxext/prs/1432.json new file mode 100644 index 0000000000000000000000000000000000000000..4a1aa22d21f6873ce170c1a240a255c9eb11571f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1432.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5c0a828f030992729fff7b784b133b849bc0413c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 11, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1433.json b/mne-python/source/doc/sphinxext/prs/1433.json new file mode 100644 index 0000000000000000000000000000000000000000..3a350897d6e0e2c14a53d514c27818e09359c7df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1433.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "183b79d9671feb4fb821543a6c701c1778eec3a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "mne/_hdf5.py": { + "a": 156, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 27, + "d": 6 + }, + "mne/tests/test_hdf5.py": { + "a": 26, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 35, + "d": 15 + }, + "mne/utils.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1435.json b/mne-python/source/doc/sphinxext/prs/1435.json new file mode 100644 index 0000000000000000000000000000000000000000..b6f21255b1b886adf9f526a7e162c7d5bc776ac2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1435.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f64d1a6ba5caba88cd0eb800f897aff6d7e83aaa", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1437.json b/mne-python/source/doc/sphinxext/prs/1437.json new file mode 100644 index 0000000000000000000000000000000000000000..1890aa2a84c9e5e1c9f2aa645cf955f49894d66d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1437.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "268cb70c0e2340727d62ce5e9f6199dec6f53ecc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "setup.cfg": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1438.json b/mne-python/source/doc/sphinxext/prs/1438.json new file mode 100644 index 0000000000000000000000000000000000000000..f2f425c29571fa0031cd008ce56d40a77d1183c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1438.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e503ff689a826dfd0dcb68156a4afeeade478bc9", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/report.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_report.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1439.json b/mne-python/source/doc/sphinxext/prs/1439.json new file mode 100644 index 0000000000000000000000000000000000000000..5fe9cb6f4bdfad6b9d76b2e264e602cdcc5d17ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1439.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4befe9eb1cf5ef2114eab8b173682737b153668a", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1440.json b/mne-python/source/doc/sphinxext/prs/1440.json new file mode 100644 index 0000000000000000000000000000000000000000..4a488370f9b5f724c8af19dbb7032bf4fa3a7210 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1440.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "66adf49f071059057cbea7bf7044f03b06467c57", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/commands/mne_report.py": { + "a": 4, + "d": 1 + }, + "mne/report.py": { + "a": 249, + "d": 194 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1441.json b/mne-python/source/doc/sphinxext/prs/1441.json new file mode 100644 index 0000000000000000000000000000000000000000..efbc63e0144c91026d0eb78000b8a8aff8e4815f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1441.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "acc5d031a11679f162ec4d156fd65560d2c689a5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_hdf5.py": { + "a": 20, + "d": 9 + }, + "mne/io/array/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/tests/test_hdf5.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/__init__.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1445.json b/mne-python/source/doc/sphinxext/prs/1445.json new file mode 100644 index 0000000000000000000000000000000000000000..20a3976f4f96c3efda9156880626c4cf0dbf7d0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1445.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3e4a21ce7425aae03608fe936729bdff72bf03c2", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1447.json b/mne-python/source/doc/sphinxext/prs/1447.json new file mode 100644 index 0000000000000000000000000000000000000000..8fc804027d5263634bb7ad527e0a6cb05ceaacf2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1447.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "10249aa3e2ad1f428fb68fe15733e2017fdb0c1c", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1448.json b/mne-python/source/doc/sphinxext/prs/1448.json new file mode 100644 index 0000000000000000000000000000000000000000..8fb8dd05e98483db0eda8194b4850749e5433446 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1448.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4bd5f69eb2943e44cd708ed5917d00858cb6e895", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 12, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1450.json b/mne-python/source/doc/sphinxext/prs/1450.json new file mode 100644 index 0000000000000000000000000000000000000000..18b99dc9f3a41701801cb872c69a7b9c936335f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1450.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a26113eaf8fbc16e96aa07bb0cb11db58127fb33", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_read_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1455.json b/mne-python/source/doc/sphinxext/prs/1455.json new file mode 100644 index 0000000000000000000000000000000000000000..2c10c43e32867441d9c61da379ff1a10962d76c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1455.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "dcd6eb2e2e9ceee34a34e78accd6261e6bf417f2", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_topo_customized.py": { + "a": 15, + "d": 10 + }, + "mne/time_frequency/psd.py": { + "a": 10, + "d": 8 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 3, + "d": 3 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 9, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1456.json b/mne-python/source/doc/sphinxext/prs/1456.json new file mode 100644 index 0000000000000000000000000000000000000000..39860a3e279b951eb627d5539462df3cdb902ace --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1456.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "65acb03c71d72e207082750541fdecce2feb2812", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/export/plot_evoked_to_nitime.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mne_crosstalk_function.py": { + "a": 8, + "d": 8 + }, + "examples/plot_make_forward.py": { + "a": 17, + "d": 6 + }, + "examples/plot_read_and_write_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_forward.py": { + "a": 1, + "d": 1 + }, + "examples/plot_ssp_projs_sensitivity_map.py": { + "a": 1, + "d": 1 + }, + "examples/plot_ssp_projs_topomaps.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topo_customized.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1459.json b/mne-python/source/doc/sphinxext/prs/1459.json new file mode 100644 index 0000000000000000000000000000000000000000..418d7048185cebcdd5fb0d510caa95463b2eaa9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1459.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "5ea0d5bba127c462964fc94a8fedcd210b2ec39e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/decoding/plot_decoding_time_generalization.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 2, + "d": 1 + }, + "examples/plot_evoked_delayed_ssp.py": { + "a": 3, + "d": 2 + }, + "examples/plot_topo_customized.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 15, + "d": 9 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 4, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1460.json b/mne-python/source/doc/sphinxext/prs/1460.json new file mode 100644 index 0000000000000000000000000000000000000000..1170c2145737ea99c29012afbf608534bc609301 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1460.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aab2a2de13b99302f7204999f545109b1c507ddb", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1461.json b/mne-python/source/doc/sphinxext/prs/1461.json new file mode 100644 index 0000000000000000000000000000000000000000..66e394b07618715984a77e7a7d9feb658fbebd33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1461.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f9f3c34595e86574cdd5f36f9f2cf32ed0a05d0b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/report.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1462.json b/mne-python/source/doc/sphinxext/prs/1462.json new file mode 100644 index 0000000000000000000000000000000000000000..2d1c3cd639ba68d93d680ae6f23c91f6ce523261 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1462.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "981912ce2984072e93f244213f4aa5b13fef3aca", + "authors": [ + { + "n": "Alan Leggitt", + "e": "leggitta3@gmail.com" + } + ], + "changes": { + "examples/plot_left_cerebellum_volume_source.py": { + "a": 10, + "d": 5 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 12, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 56, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 106, + "d": 9 + }, + "mne/source_space.py": { + "a": 352, + "d": 45 + }, + "mne/tests/test_source_estimate.py": { + "a": 26, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 52, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1465.json b/mne-python/source/doc/sphinxext/prs/1465.json new file mode 100644 index 0000000000000000000000000000000000000000..ba03fc190f39d40fb255a970b12e79bb13b500d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1465.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5a599d33ad271710c8eb6f5afce82e855d1ba176", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_ica.py": { + "a": 10, + "d": 7 + }, + "mne/source_estimate.py": { + "a": 6, + "d": 5 + }, + "mne/stats/tests/test_regression.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 9, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 36, + "d": 24 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1466.json b/mne-python/source/doc/sphinxext/prs/1466.json new file mode 100644 index 0000000000000000000000000000000000000000..420197f8f94d0edb0cdf86dbb1ac426fd542a3de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1466.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4f6aa9c41e746a46d5f84ab203862a4f2497b8d2", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/mne-python.rst": { + "a": 1, + "d": 0 + }, + "doc/source/mne_report_tutorial.rst": { + "a": 87, + "d": 0 + }, + "mne/report.py": { + "a": 35, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1467.json b/mne-python/source/doc/sphinxext/prs/1467.json new file mode 100644 index 0000000000000000000000000000000000000000..f027f881012e850a6bb67f207dfcdbc649c4e2d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1467.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3591c2e8f05878432cd95169e653fc2b5d0e30a0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 4, + "d": 2 + }, + "mne/externals/tempita/__init__.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1468.json b/mne-python/source/doc/sphinxext/prs/1468.json new file mode 100644 index 0000000000000000000000000000000000000000..2ac35fe96b5a58b97a47ce26988790aa0dd8a4e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1468.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "65eed5d13285cea4bac4b378d7e5844241896e9d", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/mne_report_tutorial.rst": { + "a": 36, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1469.json b/mne-python/source/doc/sphinxext/prs/1469.json new file mode 100644 index 0000000000000000000000000000000000000000..3385ba55c21fe589eb7a905be5ce9918bd71cb5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1469.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e8d2a98e3623caa9d9bb8c3f2bfc94b548d7e263", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/mne_report_tutorial.rst": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/147.json b/mne-python/source/doc/sphinxext/prs/147.json new file mode 100644 index 0000000000000000000000000000000000000000..a27f745eb975bc19b97cf0d0b1cf1fa109b66f60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/147.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "273428798cd978f89e8a1761c420e15b77f99c38", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 7, + "d": 6 + }, + "mne/fiff/proj.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1470.json b/mne-python/source/doc/sphinxext/prs/1470.json new file mode 100644 index 0000000000000000000000000000000000000000..536a11a6ac68135e8d123568759b28cb8115f023 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1470.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6d30fc9168e77a57fdd4371c975f6018be5393a6", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1478.json b/mne-python/source/doc/sphinxext/prs/1478.json new file mode 100644 index 0000000000000000000000000000000000000000..b9c6898e467b46fc81d06183dd7ad90358d00621 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1478.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "05c82acafc1aceae80d8b2c2b8804e5fe7a2cf63", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 2, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 21, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1479.json b/mne-python/source/doc/sphinxext/prs/1479.json new file mode 100644 index 0000000000000000000000000000000000000000..7aab8b3ce897024e0885ef4df84983b42931fa61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1479.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7aca02a1279c98f72ca4f00981a90f07604c8334", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1481.json b/mne-python/source/doc/sphinxext/prs/1481.json new file mode 100644 index 0000000000000000000000000000000000000000..1d8333ed517bb9c0cae7a86dd67286195b10ac3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1481.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "127fd59bb852b39cf7134cf249b47027506bc46c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 6, + "d": 3 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_dipole_fit_result.py": { + "a": 6, + "d": 4 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 7, + "d": 4 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 8, + "d": 5 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 7, + "d": 9 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_single_trial_spectra.py": { + "a": 5, + "d": 2 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 2, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 8, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1484.json b/mne-python/source/doc/sphinxext/prs/1484.json new file mode 100644 index 0000000000000000000000000000000000000000..a0079ad1b1627b59b09112b959bc476bf5817022 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1484.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a0bc13679b0af9796f16499ea7bebf63a2e864a7", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1485.json b/mne-python/source/doc/sphinxext/prs/1485.json new file mode 100644 index 0000000000000000000000000000000000000000..dd40d4a5866620cb3c70c73e2312b7a9831599c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1485.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0b15b60cdadb8512761e20f98511b191dd8ae3fa", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1487.json b/mne-python/source/doc/sphinxext/prs/1487.json new file mode 100644 index 0000000000000000000000000000000000000000..1ed18842034842b91eaec137ddc8dd36c21d4c3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1487.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a0e10457953dbcc98d5ba9a6b40f5c131d71b80e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 21, + "d": 0 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1488.json b/mne-python/source/doc/sphinxext/prs/1488.json new file mode 100644 index 0000000000000000000000000000000000000000..73af1dc68fba9ed3907d0c0cc47b43d28b88a91c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1488.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "db5c64711c6eea94920ceba50a57db4f11e91861", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 12, + "d": 12 + }, + "MANIFEST.in": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1489.json b/mne-python/source/doc/sphinxext/prs/1489.json new file mode 100644 index 0000000000000000000000000000000000000000..18a81e406d3e2710780d2a7d1888be6007772a57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1489.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "92ac62aad15ed618e55b5f2ef34852a8f3377ac7", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/149.json b/mne-python/source/doc/sphinxext/prs/149.json new file mode 100644 index 0000000000000000000000000000000000000000..3f0df708bdcd6562b5be3147d6668183b1d48b1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/149.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d0af4cd9ec5011057f645040496d3680919cc36d", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 1, + "d": 3 + }, + "mne/fiff/proj.py": { + "a": 3, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 91, + "d": 126 + }, + "mne/fiff/tests/test_raw.py": { + "a": 45, + "d": 23 + }, + "mne/forward.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1491.json b/mne-python/source/doc/sphinxext/prs/1491.json new file mode 100644 index 0000000000000000000000000000000000000000..5569666a739ca7b8c7bb5ec1e035ba17f520fd55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1491.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "15eb500c3dea94c381c93a66e6314632a9375f55", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/surface.py": { + "a": 20, + "d": 11 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1492.json b/mne-python/source/doc/sphinxext/prs/1492.json new file mode 100644 index 0000000000000000000000000000000000000000..257dffdefa161858b65e03d50a2a6136d980711d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1492.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "36a599bf8e4e8633c33627409ee84c8d198a746a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_make_forward.py": { + "a": 2, + "d": 1 + }, + "examples/plot_read_forward.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 4, + "d": 6 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 6, + "d": 9 + }, + "mne/stats/cluster_level.py": { + "a": 21, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1493.json b/mne-python/source/doc/sphinxext/prs/1493.json new file mode 100644 index 0000000000000000000000000000000000000000..d1e48b1e9f5248623cebc2fbe36e1a344e06134e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1493.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "16814e8295442acf6b07b6538f128f4ab773515e", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 92, + "d": 13 + }, + "mne/tests/test_report.py": { + "a": 0, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1496.json b/mne-python/source/doc/sphinxext/prs/1496.json new file mode 100644 index 0000000000000000000000000000000000000000..bdf667c480c94407d7908fa6cd3070db7f9894ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1496.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "06d41b9b378f5e4bc30f0607398235d6c2d6ceef", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 34, + "d": 14 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 42, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1498.json b/mne-python/source/doc/sphinxext/prs/1498.json new file mode 100644 index 0000000000000000000000000000000000000000..d8cd64c6968a2d3c203deca4cc848eb505a46379 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1498.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "99e0ffcb69cfdac0a23adce1440ac1f1d0239825", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 23, + "d": 10 + }, + "mne/tests/test_report.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 20, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1499.json b/mne-python/source/doc/sphinxext/prs/1499.json new file mode 100644 index 0000000000000000000000000000000000000000..8a86241fcfcf55e61733fb7ff067397ff31c7041 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1499.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "dd0bc5e7305168d9ee367626f2fdfc344078854e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_read_noise_covariance_matrix.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 87, + "d": 62 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/15.json b/mne-python/source/doc/sphinxext/prs/15.json new file mode 100644 index 0000000000000000000000000000000000000000..4f01172af94e10b2f7999b96bc920691de5e656c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/15.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9682cf0954ae2826207b4913ca681148e7735a39", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 45, + "d": 22 + }, + "mne/fiff/tests/test_raw.py": { + "a": 30, + "d": 0 + }, + "mne/tests/test_raw.py": { + "a": 0, + "d": 46 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/150.json b/mne-python/source/doc/sphinxext/prs/150.json new file mode 100644 index 0000000000000000000000000000000000000000..20ef4a1104ac897c3a48b6dd26be931d4e4f8460 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/150.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dcb930b5d83bd3e850e8b10a23904c1b6c0b97c5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_cov.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1500.json b/mne-python/source/doc/sphinxext/prs/1500.json new file mode 100644 index 0000000000000000000000000000000000000000..3c8cc7e5e415887d2078c8ef20120163310cc6d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1500.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "48453697212c60dedc6f869767a27da4b07c4f2c", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/contributing.rst": { + "a": 40, + "d": 48 + }, + "doc/source/git_links.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1502.json b/mne-python/source/doc/sphinxext/prs/1502.json new file mode 100644 index 0000000000000000000000000000000000000000..d80761bb4fe94f5ed7341afbe9d24c8d245b919a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1502.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3bc342a55ea3c47e4c0e748d0c28e268c2e8f72c", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "examples/realtime/ftclient_rt_compute_psd.py": { + "a": 76, + "d": 0 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 38, + "d": 0 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 34, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1503.json b/mne-python/source/doc/sphinxext/prs/1503.json new file mode 100644 index 0000000000000000000000000000000000000000..7155bf0c7fffee5d355d45c10ca4fd4a3a7bc538 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1503.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8a286b29bbb815cc58c216a6d76c3fa7192e7328", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 57, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 21, + "d": 6 + }, + "mne/tests/test_label.py": { + "a": 9, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1504.json b/mne-python/source/doc/sphinxext/prs/1504.json new file mode 100644 index 0000000000000000000000000000000000000000..7e2e573d7f4e01102d3707b657defa3ad8f9ee64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1504.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "77881eceb89b343be62167f848aefc13b63663a8", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 66, + "d": 54 + }, + "mne/tests/test_label.py": { + "a": 48, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1509.json b/mne-python/source/doc/sphinxext/prs/1509.json new file mode 100644 index 0000000000000000000000000000000000000000..744fe14dad5848dabcae707f82051bb165d00ab2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1509.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "39d98e4a49114cf1005f7841a1449e3e42ae6807", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/151.json b/mne-python/source/doc/sphinxext/prs/151.json new file mode 100644 index 0000000000000000000000000000000000000000..ec7d03d97b9e19dc0ea918daa1a8c904c5e2ddd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/151.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "063e01596cfb7b8775b701116aa958619fbab289", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/tests/test_cov.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1513.json b/mne-python/source/doc/sphinxext/prs/1513.json new file mode 100644 index 0000000000000000000000000000000000000000..62b328af1bb48e12912062489fcded2d55e53e5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1513.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "09d7b82cf34053f031feadf31bd729e6ed3c21a6", + "authors": [ + { + "n": "Alan Leggitt", + "e": "leggitta3@gmail.com" + } + ], + "changes": { + "examples/plot_left_cerebellum_volume_source.py": { + "a": 97, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/data/FreeSurferColorLUT.txt": { + "a": 1397, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 27, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 56, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 158, + "d": 14 + }, + "mne/source_space.py": { + "a": 490, + "d": 25 + }, + "mne/tests/test_source_estimate.py": { + "a": 26, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 122, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1515.json b/mne-python/source/doc/sphinxext/prs/1515.json new file mode 100644 index 0000000000000000000000000000000000000000..016c444f3a73a05d2e95b1a8e7df25e4c30ead64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1515.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "55b53d5c7d5b7eeabde307f5fce8d7e8554fd6f3", + "authors": [ + { + "n": "Alan Leggitt", + "e": "leggitta3@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 25, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 10, + "d": 0 + }, + "examples/plot_left_cerebellum_volume_source.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1517.json b/mne-python/source/doc/sphinxext/prs/1517.json new file mode 100644 index 0000000000000000000000000000000000000000..55ed2531d103a4d4bab93d4d918bfbeabf121514 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1517.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "075f9933038235b1df83e5cef48ca6bb54bb5948", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/contributing.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 14, + "d": 8 + }, + "mne/viz/ica.py": { + "a": 41, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1519.json b/mne-python/source/doc/sphinxext/prs/1519.json new file mode 100644 index 0000000000000000000000000000000000000000..c47e976076fb9ff5ce44bbbb97c52d8dbd873d45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1519.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1713681dc3aead7c8893a08b4bd45f04d9abaa03", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/epochs.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/152.json b/mne-python/source/doc/sphinxext/prs/152.json new file mode 100644 index 0000000000000000000000000000000000000000..0e3bd6753a86a0321fc101180a42981a4dfe3b46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/152.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "10094ca7be875909ec1564c2999a1488dc45e0a7", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/__init__.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1520.json b/mne-python/source/doc/sphinxext/prs/1520.json new file mode 100644 index 0000000000000000000000000000000000000000..d0a0ab0ecaf7f85da4fdd72e4b78101a7d30a44b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1520.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "923a714f5a3a36cd7458852a02e6715859dd4c45", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 0, + "d": 1 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 5, + "d": 4 + }, + "mne/__init__.py": { + "a": 1, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 14 + }, + "mne/label.py": { + "a": 13, + "d": 80 + }, + "mne/layouts/layout.py": { + "a": 2, + "d": 20 + }, + "mne/layouts/tests/test_layout.py": { + "a": 0, + "d": 9 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 6 + }, + "mne/mixed_norm/__init__.py": { + "a": 0, + "d": 7 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 312 + }, + "mne/tests/test_label.py": { + "a": 94, + "d": 5 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 2, + "d": 7 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 4, + "d": 8 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 45 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 6, + "d": 10 + }, + "mne/viz/ica.py": { + "a": 0, + "d": 40 + }, + "mne/viz/topo.py": { + "a": 0, + "d": 232 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 14 + }, + "setup.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1523.json b/mne-python/source/doc/sphinxext/prs/1523.json new file mode 100644 index 0000000000000000000000000000000000000000..2184d3fc8d9d752b3a118eb8f253cc6af96ed29a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1523.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "77f3d7097096a8bf89bddb87bbedd96a63274c79", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 40, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1529.json b/mne-python/source/doc/sphinxext/prs/1529.json new file mode 100644 index 0000000000000000000000000000000000000000..ea8d4a713975216d99c5567d786fbcc29080753c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1529.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f125792c167b085cfe5be643344f9de93df1dd76", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/layouts/layout.py": { + "a": 19, + "d": 4 + }, + "mne/layouts/tests/test_layout.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/153.json b/mne-python/source/doc/sphinxext/prs/153.json new file mode 100644 index 0000000000000000000000000000000000000000..3b45f430bdd5480fc8bd222876e1a09f0bf37777 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/153.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ffdba6fc035f799d184b9d48670a362f3f4b3000", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 3, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/inverse/plot_morph_data.py": { + "a": 20, + "d": 5 + }, + "mne/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 229, + "d": 54 + }, + "mne/tests/test_source_estimate.py": { + "a": 14, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1533.json b/mne-python/source/doc/sphinxext/prs/1533.json new file mode 100644 index 0000000000000000000000000000000000000000..8a0e945f705cbfebf65abd56c6998c685fff9572 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1533.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "32a36b4dfbbb44c9aa9a6bc35422df7b0f87228c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels.py": { + "a": 7, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1535.json b/mne-python/source/doc/sphinxext/prs/1535.json new file mode 100644 index 0000000000000000000000000000000000000000..599a9e8f4daf0517af9724dc9a1c4a1df24a8a89 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1535.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1685beabc4f1395598cd09f621a2a28e35e85f96", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/stft.py": { + "a": 7, + "d": 6 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 21, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1536.json b/mne-python/source/doc/sphinxext/prs/1536.json new file mode 100644 index 0000000000000000000000000000000000000000..a0397f5853ce6ae389b9469b355e8c36961617cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1536.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d621f50184d10280ef3386e011ad9182c2e50116", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 12, + "d": 5 + }, + "mne/viz/topo.py": { + "a": 32, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1538.json b/mne-python/source/doc/sphinxext/prs/1538.json new file mode 100644 index 0000000000000000000000000000000000000000..e4285f3209136194fae29034a2c276b485403919 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1538.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "aaf68e924cf0bc960af476ecdd16370386843ef9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/contributing.rst": { + "a": 2, + "d": 2 + }, + "doc/source/mne_report_tutorial.rst": { + "a": 2, + "d": 2 + }, + "mne/__init__.py": { + "a": 1, + "d": 3 + }, + "mne/epochs.py": { + "a": 2, + "d": 19 + }, + "mne/evoked.py": { + "a": 9, + "d": 125 + }, + "mne/fiff/__init__.py": { + "a": 0, + "d": 79 + }, + "mne/source_space.py": { + "a": 2, + "d": 10 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 13 + }, + "mne/utils.py": { + "a": 2, + "d": 2 + }, + "setup.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1540.json b/mne-python/source/doc/sphinxext/prs/1540.json new file mode 100644 index 0000000000000000000000000000000000000000..790cd5033127a251f1e74990570bf744ec983329 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1540.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "352483afc627a179505be649b4712a699a4b161a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1543.json b/mne-python/source/doc/sphinxext/prs/1543.json new file mode 100644 index 0000000000000000000000000000000000000000..4f4579ba3200291c23628335e96f8531f7551275 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1543.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8086b4224f0c1ddb676018a8751fce7c3a560537", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1545.json b/mne-python/source/doc/sphinxext/prs/1545.json new file mode 100644 index 0000000000000000000000000000000000000000..aa188487b0607687773b51a968addf481ef215c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1545.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d6fbb058ab0ddb284b2e8dc6fc88df770e284c94", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/tests/data/test_ica.lout": { + "a": 3, + "d": 3 + }, + "mne/layouts/layout.py": { + "a": 160, + "d": 42 + }, + "mne/layouts/tests/test_layout.py": { + "a": 137, + "d": 49 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1546.json b/mne-python/source/doc/sphinxext/prs/1546.json new file mode 100644 index 0000000000000000000000000000000000000000..054390c4fb1d1240f27edfa2c9a9cecfba87544f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1546.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1dcc1cba093a7eb8fc1dccb7cdb1aebd692a22f7", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/155.json b/mne-python/source/doc/sphinxext/prs/155.json new file mode 100644 index 0000000000000000000000000000000000000000..03730776be168a342512ba931795bb7a9a7ff92a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/155.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "76c1d764f7beffb5de24821f26d7c3941eb2693f", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/artifacts/ica.py": { + "a": 18, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1550.json b/mne-python/source/doc/sphinxext/prs/1550.json new file mode 100644 index 0000000000000000000000000000000000000000..62e9479c624978547283cd40cea291d32bad7fe4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1550.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "81201d762867ac3acaa36b001de36cc9a4978bc5", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/layouts/layout.py": { + "a": 2, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1551.json b/mne-python/source/doc/sphinxext/prs/1551.json new file mode 100644 index 0000000000000000000000000000000000000000..20a64aef6933800ccdc337fd072e7dc462ebb0e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1551.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d30ff45e90da322142a6b6c9a017e2630fc88cbc", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/viz/circle.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1552.json b/mne-python/source/doc/sphinxext/prs/1552.json new file mode 100644 index 0000000000000000000000000000000000000000..d7cd9e442452d5caa31591470fa666e9723d1332 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1552.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b538c2a3808e36fb793af13df7dd5b017d3dd611", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/mne_report_tutorial.rst": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 110, + "d": 26 + }, + "mne/tests/test_report.py": { + "a": 19, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1554.json b/mne-python/source/doc/sphinxext/prs/1554.json new file mode 100644 index 0000000000000000000000000000000000000000..7cfb348a9105bfabcc0edf5ba30cce1adf9f18bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1554.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3c32f6059a0e8279d57679790c34bf9ff519078d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_misc.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1555.json b/mne-python/source/doc/sphinxext/prs/1555.json new file mode 100644 index 0000000000000000000000000000000000000000..4eb153e2c05aa47bf486b1d7c9d8af3261273365 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1555.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e4ce25460326423c1a5bbb83fce6acf92d1201c9", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1558.json b/mne-python/source/doc/sphinxext/prs/1558.json new file mode 100644 index 0000000000000000000000000000000000000000..de8ccc9c12db554899b32e0bb2290506d83a94c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1558.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4be3c611c7dcda04ce61b3d699f7611e25f14be9", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1559.json b/mne-python/source/doc/sphinxext/prs/1559.json new file mode 100644 index 0000000000000000000000000000000000000000..3ce809a7648efb00cc8ac8c02ea0e47e8096f098 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1559.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "17f8e54836839cff4659f30c833f739821a4fb16", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 12, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/156.json b/mne-python/source/doc/sphinxext/prs/156.json new file mode 100644 index 0000000000000000000000000000000000000000..49ee80a49648e07e52d27b7fa4ab998659e5fee4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/156.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "706d211ed3bb516752990503e605e7ef4aa274bb", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1561.json b/mne-python/source/doc/sphinxext/prs/1561.json new file mode 100644 index 0000000000000000000000000000000000000000..58ccc02e1509c0e52ab918a1af25b4a1ecd6e43b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1561.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "628e6776293f0d86df15034d8e45b6477ecf0d5b", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_file_traits.py": { + "a": 11, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1564.json b/mne-python/source/doc/sphinxext/prs/1564.json new file mode 100644 index 0000000000000000000000000000000000000000..2837af24a4748e979ef92f1c290e75627f405331 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1564.json @@ -0,0 +1,415 @@ +{ + "merge_commit_sha": "0826eca83da5839aea063cbfc34381eae17f5ff3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 3, + "d": 2 + }, + ".travis.yml": { + "a": 55, + "d": 23 + }, + "Makefile": { + "a": 15, + "d": 8 + }, + "bin/mne": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 33, + "d": 22 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 38, + "d": 33 + }, + "mne/commands/mne_browse_raw.py": { + "a": 11, + "d": 5 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 23, + "d": 16 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 17, + "d": 11 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 8, + "d": 3 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 41, + "d": 39 + }, + "mne/commands/mne_coreg.py": { + "a": 7, + "d": 2 + }, + "mne/commands/mne_flash_bem_model.py": { + "a": 15, + "d": 11 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 8, + "d": 2 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 24, + "d": 18 + }, + "mne/commands/mne_maxfilter.py": { + "a": 60, + "d": 54 + }, + "mne/commands/mne_report.py": { + "a": 12, + "d": 2 + }, + "mne/commands/mne_surf2bem.py": { + "a": 12, + "d": 6 + }, + "mne/commands/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 103, + "d": 0 + }, + "mne/commands/utils.py": { + "a": 11, + "d": 4 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 30, + "d": 23 + }, + "mne/coreg.py": { + "a": 22, + "d": 6 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 2, + "d": 4 + }, + "mne/datasets/megsim/megsim.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/sample/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sample/sample.py": { + "a": 1, + "d": 13 + }, + "mne/datasets/testing/__init__.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/testing/_testing.py": { + "a": 41, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 21, + "d": 13 + }, + "mne/decoding/tests/test_csp.py": { + "a": 3, + "d": 5 + }, + "mne/decoding/tests/test_ems.py": { + "a": 2, + "d": 4 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 3, + "d": 5 + }, + "mne/fixes.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_lead_dots.py": { + "a": 2, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 17, + "d": 25 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 17, + "d": 14 + }, + "mne/forward/tests/test_forward.py": { + "a": 46, + "d": 56 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 71, + "d": 73 + }, + "mne/gui/_coreg_gui.py": { + "a": 6, + "d": 31 + }, + "mne/gui/_fiducials_gui.py": { + "a": 5, + "d": 21 + }, + "mne/gui/_file_traits.py": { + "a": 37, + "d": 65 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 15, + "d": 10 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 12, + "d": 13 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 18, + "d": 17 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 2, + "d": 4 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 2, + "d": 3 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 17, + "d": 10 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 9, + "d": 4 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 4 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 4, + "d": 4 + }, + "mne/io/bti/bti.py": { + "a": 6, + "d": 6 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 2, + "d": 3 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 59, + "d": 12 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 2, + "d": 1 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 2, + "d": 3 + }, + "mne/io/tests/test_compensator.py": { + "a": 3, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 3, + "d": 4 + }, + "mne/layouts/tests/test_layout.py": { + "a": 4, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 101, + "d": 90 + }, + "mne/minimum_norm/tests/test_psf_ctf.py": { + "a": 8, + "d": 6 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 12, + "d": 8 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 8, + "d": 9 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 4, + "d": 4 + }, + "mne/simulation/tests/test_source.py": { + "a": 18, + "d": 12 + }, + "mne/source_space.py": { + "a": 225, + "d": 95 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 88, + "d": 85 + }, + "mne/stats/tests/test_regression.py": { + "a": 7, + "d": 8 + }, + "mne/tests/__init__.py": { + "a": 0, + "d": 3 + }, + "mne/tests/test_channels.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_coreg.py": { + "a": 10, + "d": 12 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_event.py": { + "a": 8, + "d": 6 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_hdf5.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 39, + "d": 47 + }, + "mne/tests/test_proj.py": { + "a": 12, + "d": 9 + }, + "mne/tests/test_report.py": { + "a": 22, + "d": 25 + }, + "mne/tests/test_source_estimate.py": { + "a": 37, + "d": 37 + }, + "mne/tests/test_source_space.py": { + "a": 109, + "d": 182 + }, + "mne/tests/test_surface.py": { + "a": 17, + "d": 11 + }, + "mne/tests/test_transforms.py": { + "a": 9, + "d": 9 + }, + "mne/tests/test_utils.py": { + "a": 38, + "d": 15 + }, + "mne/utils.py": { + "a": 177, + "d": 65 + }, + "mne/viz/tests/test_3d.py": { + "a": 14, + "d": 13 + }, + "mne/viz/tests/test_epochs.py": { + "a": 0, + "d": 6 + }, + "mne/viz/tests/test_evoked.py": { + "a": 0, + "d": 5 + }, + "mne/viz/tests/test_ica.py": { + "a": 0, + "d": 5 + }, + "mne/viz/tests/test_misc.py": { + "a": 10, + "d": 9 + }, + "mne/viz/tests/test_raw.py": { + "a": 0, + "d": 3 + }, + "mne/viz/tests/test_topo.py": { + "a": 0, + "d": 5 + }, + "mne/viz/tests/test_topomap.py": { + "a": 3, + "d": 3 + }, + "setup.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1565.json b/mne-python/source/doc/sphinxext/prs/1565.json new file mode 100644 index 0000000000000000000000000000000000000000..665e175542e23f2e865aee38c2e7080200566ef1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1565.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "69df199095bf66c3c070046eb8d20877804c038d", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_file_traits.py": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1566.json b/mne-python/source/doc/sphinxext/prs/1566.json new file mode 100644 index 0000000000000000000000000000000000000000..30feaf668df28839fb83fe0553bf4b6ae98b4f71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1566.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5f76748c8d77f326925564fbae837062654dc32c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/decoding/time_gen.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/157.json b/mne-python/source/doc/sphinxext/prs/157.json new file mode 100644 index 0000000000000000000000000000000000000000..1b3a8970b9e8c5d13d3b5b5a04f3d4f41df5693a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/157.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c675c086aa99d13c571c4ea787fdf1bc590bdec6", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1572.json b/mne-python/source/doc/sphinxext/prs/1572.json new file mode 100644 index 0000000000000000000000000000000000000000..295a827eabb71e23a8045b27c848094c8059e960 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1572.json @@ -0,0 +1,227 @@ +{ + "merge_commit_sha": "a71e2c046dcdfdb3e59fd26d1654c73e08a1f03f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 8 + }, + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 28, + "d": 44 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 3, + "d": 4 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 3, + "d": 4 + }, + "mne/commands/mne_flash_bem_model.py": { + "a": 6, + "d": 1 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_maxfilter.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_report.py": { + "a": 15, + "d": 4 + }, + "mne/commands/mne_surf2bem.py": { + "a": 1, + "d": 3 + }, + "mne/commands/tests/test_commands.py": { + "a": 82, + "d": 40 + }, + "mne/coreg.py": { + "a": 54, + "d": 63 + }, + "mne/cuda.py": { + "a": 85, + "d": 135 + }, + "mne/evoked.py": { + "a": 144, + "d": 151 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 98, + "d": 122 + }, + "mne/forward/tests/test_forward.py": { + "a": 33, + "d": 12 + }, + "mne/gui/_coreg_gui.py": { + "a": 11, + "d": 11 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 61, + "d": 86 + }, + "mne/gui/_marker_gui.py": { + "a": 29, + "d": 49 + }, + "mne/gui/_viewer.py": { + "a": 21, + "d": 31 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 15, + "d": 1 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 16, + "d": 2 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 16, + "d": 2 + }, + "mne/label.py": { + "a": 15, + "d": 20 + }, + "mne/minimum_norm/inverse.py": { + "a": 177, + "d": 196 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxfilter.py": { + "a": 7, + "d": 4 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 105, + "d": 156 + }, + "mne/source_space.py": { + "a": 9, + "d": 13 + }, + "mne/surface.py": { + "a": 64, + "d": 107 + }, + "mne/tests/test_epochs.py": { + "a": 57, + "d": 6 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_filter.py": { + "a": 10, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 21, + "d": 2 + }, + "mne/tests/test_report.py": { + "a": 68, + "d": 27 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 49, + "d": 12 + }, + "mne/tests/test_transforms.py": { + "a": 62, + "d": 6 + }, + "mne/tests/test_utils.py": { + "a": 17, + "d": 9 + }, + "mne/transforms.py": { + "a": 16, + "d": 75 + }, + "mne/utils.py": { + "a": 48, + "d": 61 + }, + "mne/viz/_3d.py": { + "a": 41, + "d": 20 + }, + "mne/viz/__init__.py": { + "a": 8, + "d": 9 + }, + "mne/viz/epochs.py": { + "a": 5, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 12, + "d": 0 + }, + "mne/viz/tests/test_epochs.py": { + "a": 15, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 8, + "d": 4 + }, + "mne/viz/tests/test_topo.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1574.json b/mne-python/source/doc/sphinxext/prs/1574.json new file mode 100644 index 0000000000000000000000000000000000000000..87d8ea4aa990b9196a3bdf3973e47bba1b37aad3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1574.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8e83d9fdc336709e857ed969b05850480878afd5", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 18, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1575.json b/mne-python/source/doc/sphinxext/prs/1575.json new file mode 100644 index 0000000000000000000000000000000000000000..3e758f69f245d9b1efae487713217ae160dd53e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1575.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ccf606f7693729747a2d7c11fe417cb6ba64b3b9", + "authors": [ + { + "n": "Kevin Schiesser", + "e": null + } + ], + "changes": { + "mne/filter.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1578.json b/mne-python/source/doc/sphinxext/prs/1578.json new file mode 100644 index 0000000000000000000000000000000000000000..69cfc49d229c9f578d0fcef4ebeed31abdd5ddb9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1578.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f620c624e6c3e4b0e351455179221cb635429040", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 0 + }, + "mne/externals/FieldTrip.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1579.json b/mne-python/source/doc/sphinxext/prs/1579.json new file mode 100644 index 0000000000000000000000000000000000000000..d6ae9eacb6a4bcdf6cb4504cdfd67e6375c5712b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1579.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0163a3f5d24c71368aa1449931618965cc1ff479", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fixes.py": { + "a": 36, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 33 + }, + "mne/tests/test_fixes.py": { + "a": 11, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1581.json b/mne-python/source/doc/sphinxext/prs/1581.json new file mode 100644 index 0000000000000000000000000000000000000000..a701add8ac929e49c87fce7a54f4d0c42dac084c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1581.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d94a10d27aad9a146070b33121c5e2e4b205808c", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/layouts/biosemi.lay": { + "a": 64, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1582.json b/mne-python/source/doc/sphinxext/prs/1582.json new file mode 100644 index 0000000000000000000000000000000000000000..71b31d29b7a5af26b110a95a0a5544c754ee0f1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1582.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9efc216892d8e49c26515483e5ba021ba346f28c", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 0, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1583.json b/mne-python/source/doc/sphinxext/prs/1583.json new file mode 100644 index 0000000000000000000000000000000000000000..ac1a4665a3f0367114b75bb07fe66610af28dbc6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1583.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f39a12dedaa84090dcf73c0dc561acb32a228d9f", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/event.py": { + "a": 37, + "d": 5 + }, + "mne/tests/test_event.py": { + "a": 20, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1584.json b/mne-python/source/doc/sphinxext/prs/1584.json new file mode 100644 index 0000000000000000000000000000000000000000..73b12ca108ceca4968285a592e3fb8f454adfd06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1584.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4a9ac46cca6dbb012de09c7752c611998b663ed8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 5, + "d": 1 + }, + "mne/realtime/tests/test_stim_client_server.py": { + "a": 31, + "d": 14 + }, + "mne/tests/test_fixes.py": { + "a": 21, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1588.json b/mne-python/source/doc/sphinxext/prs/1588.json new file mode 100644 index 0000000000000000000000000000000000000000..7ad263c2b90ced2029e0687903daa08dded004d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1588.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "295750ca7cc7eb7a34cac1506cc9984f058d6f0b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 10, + "d": 2 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 57, + "d": 48 + }, + "mne/commands/tests/test_commands.py": { + "a": 33, + "d": 1 + }, + "mne/commands/utils.py": { + "a": 0, + "d": 10 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 34, + "d": 15 + }, + "mne/tests/test_source_space.py": { + "a": 5, + "d": 8 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1589.json b/mne-python/source/doc/sphinxext/prs/1589.json new file mode 100644 index 0000000000000000000000000000000000000000..2e9edd6b23aab61af65b0913186269c1cb88ca10 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1589.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "70075e5f780787fbab8e1b6b01a30dc9a57c76ea", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/159.json b/mne-python/source/doc/sphinxext/prs/159.json new file mode 100644 index 0000000000000000000000000000000000000000..6d3e8eebcee295b90f047fe6a2dbc83410195555 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/159.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a6b8e55c7039e7337848571358021fca5d5d4eb3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1590.json b/mne-python/source/doc/sphinxext/prs/1590.json new file mode 100644 index 0000000000000000000000000000000000000000..964d04e8e1666eff16ee8274d1942222a60cdf2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1590.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "bf46062b42ba9e0702de81d833af9d2b5ec82f27", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 8, + "d": 3 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/constants.py": { + "a": 2, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 507, + "d": 283 + }, + "mne/io/kit/tests/data/test-epoch.raw": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test-eve.txt": { + "a": 2, + "d": 0 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 27, + "d": 4 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1592.json b/mne-python/source/doc/sphinxext/prs/1592.json new file mode 100644 index 0000000000000000000000000000000000000000..a76c1a76ffe0a9f109e89a320e44bbc0af6b995b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1592.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "834ba92eca3f66f623f72d582a2690511bb32a87", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 4, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 1, + "d": 0 + }, + "mne/realtime/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1593.json b/mne-python/source/doc/sphinxext/prs/1593.json new file mode 100644 index 0000000000000000000000000000000000000000..f3f7d2143dcf3ad7d63a29fa310359dfd9c8242e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1593.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e0f5f1ae1d2e26b5208eb06ecea821250869cbe3", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/filter.py": { + "a": 15, + "d": 3 + }, + "mne/io/base.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1594.json b/mne-python/source/doc/sphinxext/prs/1594.json new file mode 100644 index 0000000000000000000000000000000000000000..789b4d0548f3c073960dc2a7b2069c87af48e7ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1594.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "6097260d7fa6a239e3292f5b315a1ddc446d32fb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "mne/_hdf5.py": { + "a": 4, + "d": 5 + }, + "mne/commands/tests/test_commands.py": { + "a": 5, + "d": 5 + }, + "mne/datasets/megsim/megsim.py": { + "a": 5, + "d": 4 + }, + "mne/datasets/megsim/urls.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/sample/sample.py": { + "a": 3, + "d": 4 + }, + "mne/datasets/somato/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/somato/somato.py": { + "a": 4, + "d": 17 + }, + "mne/datasets/spm_face/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 4, + "d": 17 + }, + "mne/datasets/testing/_testing.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 12, + "d": 8 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 4, + "d": 3 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 15 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_hdf5.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 109, + "d": 57 + }, + "mne/utils.py": { + "a": 205, + "d": 329 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1595.json b/mne-python/source/doc/sphinxext/prs/1595.json new file mode 100644 index 0000000000000000000000000000000000000000..e9446bec73e22a712a59568d19249403c1813377 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1595.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a3e4b196c43113fc032b05e94779af9803d2686", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1596.json b/mne-python/source/doc/sphinxext/prs/1596.json new file mode 100644 index 0000000000000000000000000000000000000000..3e6a23933ded64ccb6c153f2677bb854411bd0eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1596.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6be17bc3bd689225e9df2cb40e5ad8ee41a307db", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/filter.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_filter.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1599.json b/mne-python/source/doc/sphinxext/prs/1599.json new file mode 100644 index 0000000000000000000000000000000000000000..914346734ad3b4e149146898679dd9976ab378ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1599.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4beaf453bd07e348a90f4752488aa4a27a75b311", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 6 + }, + "mne/report.py": { + "a": 24, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 32, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/16.json b/mne-python/source/doc/sphinxext/prs/16.json new file mode 100644 index 0000000000000000000000000000000000000000..c21afc1e07f74e33024c9c4ad8c35a966cf7aaee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/16.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "592f9afca21a68755042741af760790d93df69b8", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/read_events.py": { + "a": 4, + "d": 1 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 12, + "d": 10 + }, + "mne/event.py": { + "a": 53, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/160.json b/mne-python/source/doc/sphinxext/prs/160.json new file mode 100644 index 0000000000000000000000000000000000000000..df4c003592439b8946879efdb86dcd7d3ad6c01e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/160.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dcbe3420f0d762ec51e7771528bfa32f2cb005f0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/layouts/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "setup.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1601.json b/mne-python/source/doc/sphinxext/prs/1601.json new file mode 100644 index 0000000000000000000000000000000000000000..f8fa3daf75a2a64faeb7dfd1c39fc998b361aa21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1601.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "84f4a1359e9b5b3ae261df233a794cfa8e6e3020", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/mne_browse_raw.py": { + "a": 27, + "d": 2 + }, + "mne/io/base.py": { + "a": 22, + "d": 6 + }, + "mne/viz/raw.py": { + "a": 57, + "d": 3 + }, + "mne/viz/tests/test_raw.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1602.json b/mne-python/source/doc/sphinxext/prs/1602.json new file mode 100644 index 0000000000000000000000000000000000000000..c8f9d66b1ae24dde56682cd5359238d58e5be54b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1602.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "099742619867b85e918b4dc4d6bfab3d8f2e7e2c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_evoked_topomap.py": { + "a": 4, + "d": 1 + }, + "mne/evoked.py": { + "a": 8, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 5, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 29, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1603.json b/mne-python/source/doc/sphinxext/prs/1603.json new file mode 100644 index 0000000000000000000000000000000000000000..5250de229e4faa696bd01d2582c9739b6f07ffe7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1603.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b611de9e429d3bacd56f4ae10398b92272e0d59e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/mne_report_tutorial.rst": { + "a": 2, + "d": 2 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 71, + "d": 39 + }, + "mne/tests/test_report.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1606.json b/mne-python/source/doc/sphinxext/prs/1606.json new file mode 100644 index 0000000000000000000000000000000000000000..0fe85e09fa963efa205a39515b7244dc5ae65966 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1606.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c2b81d5578bb59a5aec366ebe44c9fb734549993", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1607.json b/mne-python/source/doc/sphinxext/prs/1607.json new file mode 100644 index 0000000000000000000000000000000000000000..aafc79b57b595e07666eef27597f090353826147 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1607.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "385a2555f35a50ad5881b6c8faac8cf78b0e4ae9", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/tests/test_coreg.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1608.json b/mne-python/source/doc/sphinxext/prs/1608.json new file mode 100644 index 0000000000000000000000000000000000000000..3a3c849d16e0767ac1f0da5712d8d24ffbf9a4a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1608.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a26c0f6eefdf34e92a21c3a217715011f2cb27a4", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/channels.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1609.json b/mne-python/source/doc/sphinxext/prs/1609.json new file mode 100644 index 0000000000000000000000000000000000000000..df5396fb579585dc2e729106d027c40f2d562d9e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1609.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9afd14672072a02261a0d428d31d6425cd850f9a", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1612.json b/mne-python/source/doc/sphinxext/prs/1612.json new file mode 100644 index 0000000000000000000000000000000000000000..4ed63906b7a85b9fc0acd2e1d379c259e25d3f1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1612.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fef061f1ed0711f18271e45920e9bc2b5550e031", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 18, + "d": 15 + }, + "mne/preprocessing/ica.py": { + "a": 9, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1614.json b/mne-python/source/doc/sphinxext/prs/1614.json new file mode 100644 index 0000000000000000000000000000000000000000..8ea209742533bab81506ef82bbadea2414ab1385 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1614.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d1914e1322075deb98c1bc6ae6fbc582668eafa8", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 2 + }, + "mne/_hdf5.py": { + "a": 10, + "d": 0 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 48, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 101, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1615.json b/mne-python/source/doc/sphinxext/prs/1615.json new file mode 100644 index 0000000000000000000000000000000000000000..820678c258f63f5abb3eec60177491fe5734b575 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1615.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "34c5a18f595420e63e1bcea0681fceb5b745973b", + "authors": [ + { + "n": "Kevin Schiesser", + "e": null + } + ], + "changes": { + "mne/filter.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1616.json b/mne-python/source/doc/sphinxext/prs/1616.json new file mode 100644 index 0000000000000000000000000000000000000000..14e2fe2716ca86fa64a4b6949837784cabd0d564 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1616.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4adf459f7cf7f0a9d428d310ef4b958d9c9e63cc", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1618.json b/mne-python/source/doc/sphinxext/prs/1618.json new file mode 100644 index 0000000000000000000000000000000000000000..6e064c37a3f474e032c70b9b58e63720971040c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1618.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "997597de0b962fcd4492faf6b7c531efc4109e62", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1619.json b/mne-python/source/doc/sphinxext/prs/1619.json new file mode 100644 index 0000000000000000000000000000000000000000..383b5fd5fab22bcb2d3d460157b7cefcde16ad9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1619.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "357d55728f13feef2c47d6bc43bcf17b57cac110", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 129, + "d": 91 + }, + "mne/channels/tests/test_layout.py": { + "a": 65, + "d": 17 + }, + "mne/layouts/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 17, + "d": 8 + }, + "mne/preprocessing/tests/test_maxfilter.py": { + "a": 95, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 13, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 22, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/162.json b/mne-python/source/doc/sphinxext/prs/162.json new file mode 100644 index 0000000000000000000000000000000000000000..aed76c37de8f7abc0fc399a2632a910e22549948 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/162.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5874483ed5d79d1fbfdf26b195dd7629cd58064f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/artifacts/tests/test_ica.py": { + "a": 9, + "d": 8 + }, + "mne/fiff/tests/test_raw.py": { + "a": 17, + "d": 13 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 4 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1620.json b/mne-python/source/doc/sphinxext/prs/1620.json new file mode 100644 index 0000000000000000000000000000000000000000..7bf08af1cda28dd21122326559d354f99d08795c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1620.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b086d95246f7e1e4c1d45875cdfa5eea96f6bd9f", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1621.json b/mne-python/source/doc/sphinxext/prs/1621.json new file mode 100644 index 0000000000000000000000000000000000000000..805a6de9c871fdf9e39cd54d1059a8439a38a761 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1621.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ef1325503c020ca49c8e568f067597421776c8ba", + "authors": [ + { + "n": "marmaduke woodman", + "e": null + } + ], + "changes": { + "mne/fixes.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1623.json b/mne-python/source/doc/sphinxext/prs/1623.json new file mode 100644 index 0000000000000000000000000000000000000000..88f447ac2a1a939b6c2e0b17e998bcaaa0d32479 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1623.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "b6daccc4239f15a2f43f50160a6298cbf67b5c06", + "authors": [ + { + "n": "marmaduke woodman", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/channels.py": { + "a": 2, + "d": 1 + }, + "mne/io/constants.py": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 0 + }, + "mne/io/pick.py": { + "a": 18, + "d": 8 + }, + "mne/io/tests/test_pick.py": { + "a": 70, + "d": 1 + }, + "mne/tests/test_channels.py": { + "a": 7, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 10, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1627.json b/mne-python/source/doc/sphinxext/prs/1627.json new file mode 100644 index 0000000000000000000000000000000000000000..43796eb0837ebbad5a676cfb7c9ece34701239de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1627.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ca7239d7252ba38698266c6cc45962d8cf4f3f74", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 35, + "d": 18 + }, + "mne/io/brainvision/tests/data/test_highpass.vhdr": { + "a": 142, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 14, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 4, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 15, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1629.json b/mne-python/source/doc/sphinxext/prs/1629.json new file mode 100644 index 0000000000000000000000000000000000000000..eefd58a38888d71b106cadf38792cfb31b592f7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1629.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "f17a53b755c7d2c1aff8742dcdeb6afce80a0d34", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_time_generalization.py": { + "a": 23, + "d": 57 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 75, + "d": 0 + }, + "mne/decoding/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 204, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 883, + "d": 7 + }, + "mne/tests/test_utils.py": { + "a": 39, + "d": 1 + }, + "mne/utils.py": { + "a": 31, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/decoding.py": { + "a": 126, + "d": 0 + }, + "mne/viz/tests/test_decoding.py": { + "a": 68, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/163.json b/mne-python/source/doc/sphinxext/prs/163.json new file mode 100644 index 0000000000000000000000000000000000000000..ea32df8456d1cca3fb9fa25394bd695e91c3285e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/163.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2a9aadcdef282bf1dad6e04d39a855a5fc7c456e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_channel_epochs_image.py": { + "a": 72, + "d": 0 + }, + "mne/viz.py": { + "a": 94, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1630.json b/mne-python/source/doc/sphinxext/prs/1630.json new file mode 100644 index 0000000000000000000000000000000000000000..36521356abe2298d3093a8a68b5de26baabd4793 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1630.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c6e90285f69a49866b30f62fa90c77902e8e1082", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1632.json b/mne-python/source/doc/sphinxext/prs/1632.json new file mode 100644 index 0000000000000000000000000000000000000000..8e7a1fc3fcee7d7e4745393adfaab0cb7a9640b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1632.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "936e3791cf4ed0945f678e882013e693e67cbd92", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 6, + "d": 4 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1636.json b/mne-python/source/doc/sphinxext/prs/1636.json new file mode 100644 index 0000000000000000000000000000000000000000..fd9f363684e4a25081d9be27f3c02803510d3977 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1636.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4e45ad1f8429edff31b24a291180a9a165c13b54", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 4, + "d": 4 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1638.json b/mne-python/source/doc/sphinxext/prs/1638.json new file mode 100644 index 0000000000000000000000000000000000000000..784aee982bf35c0816e10d21981fab177d02ece4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1638.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "62a2b4531a25a88b993ae16ab92f30dd8f5f5632", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_read_forward.py": { + "a": 32, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/164.json b/mne-python/source/doc/sphinxext/prs/164.json new file mode 100644 index 0000000000000000000000000000000000000000..b82d194ddf7bbf4f99ef0132df2ab3b417622f0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/164.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "7612f2b571a08dd5635d43c9ef66a3f55a1e8506", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 26, + "d": 5 + }, + "mne/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/event.py": { + "a": 64, + "d": 11 + }, + "mne/fiff/raw.py": { + "a": 43, + "d": 33 + }, + "mne/fiff/tests/data/test-mpr-eve.eve": { + "a": 32, + "d": 0 + }, + "mne/fiff/tests/test_raw.py": { + "a": 22, + "d": 0 + }, + "mne/tests/test_event.py": { + "a": 11, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1642.json b/mne-python/source/doc/sphinxext/prs/1642.json new file mode 100644 index 0000000000000000000000000000000000000000..cea3a2c1108e8bee19c7b70c9712ca374a716d06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1642.json @@ -0,0 +1,327 @@ +{ + "merge_commit_sha": "b7cc0f9b45a95a91c357fd8d8f32c0897f13b4d7", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "MANIFEST.in": { + "a": 7, + "d": 6 + }, + "doc/source/python_reference.rst": { + "a": 5, + "d": 9 + }, + "doc/source/whats_new.rst": { + "a": 6, + "d": 1 + }, + "examples/stats/plot_spatio_temporal_cluster_stats_sensor.py": { + "a": 157, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 4 + }, + "mne/channels/__init__.py": { + "a": 10, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 46, + "d": 18 + }, + "mne/channels/data/layouts/CTF-275.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/CTF151.lay": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/CTF275.lay": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/EEG1005.lay": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/EGI256.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/KIT-157.lout": { + "a": 1, + "d": 1 + }, + "mne/channels/data/layouts/Vectorview-all.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/Vectorview-grad.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/Vectorview-mag.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/biosemi.lay": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/magnesWH3600.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/10-5-System_Mastoids_EGI129.csd": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/EGI_256.csd": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/GSN-HydroCel-128.sfp": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/GSN-HydroCel-129.sfp": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/GSN-HydroCel-256.sfp": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/GSN-HydroCel-257.sfp": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/GSN-HydroCel-32.sfp": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/GSN-HydroCel-64_1.0.sfp": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/GSN-HydroCel-65_1.0.sfp": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/easycap-M1.txt": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/easycap-M10.txt": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/standard_1005.elc": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/standard_1020.elc": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/standard_alphabetic.elc": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/standard_postfixed.elc": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/standard_prefixed.elc": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/standard_primed.elc": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/__init__.py": { + "a": 6, + "d": 0 + }, + "mne/channels/data/neighbors/biosemi16_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/biosemi32_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/biosemi64_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/bti148_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/bti248_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/bti248grad_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/ctf151_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/ctf275_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/ctf64_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycap128ch-avg_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycap32ch-avg_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycap64ch-avg_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycapM11_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycapM14_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycapM15_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycapM1_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/neuromag122_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/neuromag306mag_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/neuromag306planar_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 197, + "d": 4 + }, + "mne/channels/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 14, + "d": 8 + }, + "mne/channels/tests/test_layout.py": { + "a": 4, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/layouts/__init__.py": { + "a": 21, + "d": 2 + }, + "mne/montages/__init__.py": { + "a": 0, + "d": 3 + }, + "mne/montages/montage.py": { + "a": 0, + "d": 202 + }, + "mne/montages/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 10, + "d": 10 + }, + "setup.py": { + "a": 9, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1644.json b/mne-python/source/doc/sphinxext/prs/1644.json new file mode 100644 index 0000000000000000000000000000000000000000..26aec18661dac18ad3426bfd3049ae5d82381020 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1644.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "da6bca13816721fd2c2753ca48782ee2b24c2af0", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/montages/montage.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1646.json b/mne-python/source/doc/sphinxext/prs/1646.json new file mode 100644 index 0000000000000000000000000000000000000000..8f18cbdbfdfacf306f1734ac047f461bc8109928 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1646.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "aa3d81879c109f4ae060f18c95c0bc9fd512d1a7", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 3, + "d": 3 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1651.json b/mne-python/source/doc/sphinxext/prs/1651.json new file mode 100644 index 0000000000000000000000000000000000000000..018d2363321320a38ecae880060df60468b78a04 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1651.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4800989b63212a700b175820d0583c32ea3cfc2e", + "authors": [ + { + "n": "Matthew A. Tucker", + "e": "matt.tucker@nyu.edu" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1656.json b/mne-python/source/doc/sphinxext/prs/1656.json new file mode 100644 index 0000000000000000000000000000000000000000..b50ab90207f58a36aee1ba33eb1bdc3fa1fdacb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1656.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "c2600d3ef4a263cdccb3f7524b3bef21c3077b58", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 8, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 17, + "d": 32 + }, + "mne/channels/tests/test_montage.py": { + "a": 10, + "d": 3 + }, + "mne/coreg.py": { + "a": 2, + "d": 54 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 3, + "d": 3 + }, + "mne/io/array/array.py": { + "a": 5, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 4, + "d": 1 + }, + "mne/io/base.py": { + "a": 31, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 67, + "d": 131 + }, + "mne/io/brainvision/tests/data/test.hpts": { + "a": 46, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 19, + "d": 23 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 7, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 76, + "d": 149 + }, + "mne/io/edf/tests/data/biosemi.hpts": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 17, + "d": 8 + }, + "mne/io/egi/egi.py": { + "a": 30, + "d": 6 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 6, + "d": 4 + }, + "mne/io/kit/kit.py": { + "a": 6, + "d": 3 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 0, + "d": 26 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 7, + "d": 3 + }, + "mne/tests/test_transforms.py": { + "a": 69, + "d": 2 + }, + "mne/transforms.py": { + "a": 77, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1658.json b/mne-python/source/doc/sphinxext/prs/1658.json new file mode 100644 index 0000000000000000000000000000000000000000..ac16bd18e2f59dbdd0afa01b226bd7c1a77f1f53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1658.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "376b07e00406fe40e70fac2d985045c56293e868", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 2 + }, + "mne/io/egi/egi.py": { + "a": 6, + "d": 6 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1661.json b/mne-python/source/doc/sphinxext/prs/1661.json new file mode 100644 index 0000000000000000000000000000000000000000..91e944fbc917a0288f0cb4c6e01b546c55797b9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1661.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0f36a626bb43d90d82b48109a3f6809aca0a1c1e", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1662.json b/mne-python/source/doc/sphinxext/prs/1662.json new file mode 100644 index 0000000000000000000000000000000000000000..e1bdbc4df76d211e7cd7871db01c84a94e185324 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1662.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e298f07fe0347b725a6f71193f636c89f8c86db", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/realtime/fieldtrip_client.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1663.json b/mne-python/source/doc/sphinxext/prs/1663.json new file mode 100644 index 0000000000000000000000000000000000000000..48ee46189154a3c1403e4a9326d6c140b7cb99fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1663.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9163a465c9663a3a0587c3da0b80a72ca3e724de", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/data/coil_def.dat": { + "a": 46, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1664.json b/mne-python/source/doc/sphinxext/prs/1664.json new file mode 100644 index 0000000000000000000000000000000000000000..8d3564eaabe7c12a5c13096df6f67762d5df8eb9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1664.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7dba8f60650ed70d7100840103dd34018ece0aa1", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/realtime/epochs.py": { + "a": 24, + "d": 5 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 92, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1667.json b/mne-python/source/doc/sphinxext/prs/1667.json new file mode 100644 index 0000000000000000000000000000000000000000..946c2cae34798e1597b465d3a92bd9df424cc249 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1667.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "15a7b675884a290f0696777806d5561a4154db8e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "doc/source/contributing.rst": { + "a": 1, + "d": 1 + }, + "doc/source/getting_started.rst": { + "a": 2, + "d": 0 + }, + "doc/source/known_projects.inc": { + "a": 5, + "d": 0 + }, + "mne/_hdf5.py": { + "a": 48, + "d": 56 + }, + "mne/tests/test_hdf5.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/utils.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1668.json b/mne-python/source/doc/sphinxext/prs/1668.json new file mode 100644 index 0000000000000000000000000000000000000000..cab9c170bf7455517e45711e1a72a7f68d5f4c51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1668.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5151807f693b26623f955ebdca4fd86785f1e3dd", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1669.json b/mne-python/source/doc/sphinxext/prs/1669.json new file mode 100644 index 0000000000000000000000000000000000000000..f5bb2906cfeb22bd45697e39449fc70bda360db4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1669.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d956e0310e165740d0e129edb350598eb51becba", + "authors": [ + { + "n": "Hari Bharadwaj", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1671.json b/mne-python/source/doc/sphinxext/prs/1671.json new file mode 100644 index 0000000000000000000000000000000000000000..6de98680a06be9a43f144b33eb9306b1abebd426 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1671.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "27502c56a8e4cb4a92ad057b6aa42517c672f698", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 5, + "d": 0 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 157, + "d": 0 + }, + "examples/plot_evoked_whitening.py": { + "a": 57, + "d": 23 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 4, + "d": 3 + }, + "mne/cov.py": { + "a": 574, + "d": 83 + }, + "mne/evoked.py": { + "a": 39, + "d": 0 + }, + "mne/fixes.py": { + "a": 173, + "d": 0 + }, + "mne/io/pick.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_pick.py": { + "a": 44, + "d": 4 + }, + "mne/tests/test_cov.py": { + "a": 145, + "d": 7 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 230, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1672.json b/mne-python/source/doc/sphinxext/prs/1672.json new file mode 100644 index 0000000000000000000000000000000000000000..a9f8135507f2866bde5221e911e9b6e7d39ea089 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1672.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6ba8d2988ab2593c9a7446ac19501261dc88d23c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 10, + "d": 5 + }, + "mne/channels/tests/test_layout.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1673.json b/mne-python/source/doc/sphinxext/prs/1673.json new file mode 100644 index 0000000000000000000000000000000000000000..851c02b952e9a93f31d6908b4a8b18996323e658 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1673.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "355c67b45171bb92cb592b5603007e44fdb92c88", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/egi/egi.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1674.json b/mne-python/source/doc/sphinxext/prs/1674.json new file mode 100644 index 0000000000000000000000000000000000000000..0ece3083c1c47ddec9330b374378de96a7ccd503 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1674.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "50303fc0b1a979a29a57af686c57cc473f74052d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1676.json b/mne-python/source/doc/sphinxext/prs/1676.json new file mode 100644 index 0000000000000000000000000000000000000000..ddc42637e20b6475d088347750c716ab25c799e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1676.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f99943965c8c692106d801fe1c28b15078d66017", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/realtime/epochs.py": { + "a": 13, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1677.json b/mne-python/source/doc/sphinxext/prs/1677.json new file mode 100644 index 0000000000000000000000000000000000000000..566f65353ea46439a1fa0d347a2d8a80890f9737 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1677.json @@ -0,0 +1,151 @@ +{ + "merge_commit_sha": "a3843cc90955db6e25230c3b57cbdc3c04b18f5c", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 5 + }, + "doc/source/whats_new.rst": { + "a": 16, + "d": 8 + }, + "examples/plot_ssp_projs_topomaps.py": { + "a": 3, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 54, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 22, + "d": 2 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 1, + "d": 25 + }, + "mne/cuda.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 5, + "d": 3 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 9, + "d": 9 + }, + "mne/gui/_marker_gui.py": { + "a": 16, + "d": 15 + }, + "mne/io/base.py": { + "a": 4, + "d": 2 + }, + "mne/io/brainvision/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/__init__.py": { + "a": 2, + "d": 6 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 6, + "d": 87 + }, + "mne/io/kit/kit.py": { + "a": 16, + "d": 35 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 3, + "d": 21 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 146, + "d": 4 + }, + "mne/io/pick.py": { + "a": 4, + "d": 3 + }, + "mne/io/proj.py": { + "a": 46, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 54, + "d": 2 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_regression.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/168.json b/mne-python/source/doc/sphinxext/prs/168.json new file mode 100644 index 0000000000000000000000000000000000000000..5c7a67c5934b85ff9603d3ab983e6d50acdcd4d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/168.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "05667f9c5e5f8ce3b55c0e68724a6af6df6d7566", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_ecg_artifacts_from_ica.py": { + "a": 103, + "d": 0 + }, + "examples/preprocessing/plot_eog_artifacts_from_ica.py": { + "a": 100, + "d": 0 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 66, + "d": 9 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 78, + "d": 23 + }, + "mne/artifacts/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/artifacts/eog.py": { + "a": 15, + "d": 6 + }, + "mne/artifacts/ica.py": { + "a": 408, + "d": 112 + }, + "mne/artifacts/tests/test_ica.py": { + "a": 47, + "d": 46 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1681.json b/mne-python/source/doc/sphinxext/prs/1681.json new file mode 100644 index 0000000000000000000000000000000000000000..71dbed3ddc06bf3f4bba35a6a349cb8b6f0f76d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1681.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "57bb75966bdbb8b627cdff1e9329af705c6a21c9", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 20, + "d": 16 + }, + "mne/io/edf/edf.py": { + "a": 48, + "d": 53 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 5, + "d": 4 + }, + "mne/io/egi/egi.py": { + "a": 9, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1685.json b/mne-python/source/doc/sphinxext/prs/1685.json new file mode 100644 index 0000000000000000000000000000000000000000..4f63a041898d7ebcaf3a10049d94570517b4ae64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1685.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7ff78dd55ada4375b2d287d3fbe804dc8ad0b3c6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "appveyor.yml": { + "a": 36, + "d": 0 + }, + "make/install_python.ps1": { + "a": 93, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1688.json b/mne-python/source/doc/sphinxext/prs/1688.json new file mode 100644 index 0000000000000000000000000000000000000000..8905dda4c1c9fda62c320b0f7d56b214cb75bbb8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1688.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fd5d67170396bbd836e8697d32003b7ba947163d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 56, + "d": 23 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1689.json b/mne-python/source/doc/sphinxext/prs/1689.json new file mode 100644 index 0000000000000000000000000000000000000000..e1a8da2fff0b12731816724a0e0cf0c10f941314 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1689.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "af5be4fc2b7fac257190cc9ede03ac5779576cd6", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/mne_report_tutorial.rst": { + "a": 19, + "d": 8 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 11, + "d": 4 + }, + "mne/tests/test_report.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/169.json b/mne-python/source/doc/sphinxext/prs/169.json new file mode 100644 index 0000000000000000000000000000000000000000..d6f9b1c50651111289252f50ebbf4460ec9b203f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/169.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "908ebe9d8b3e43d8b90d945ee45d6292a25e4f23", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_topo_channel_epochs_image.py": { + "a": 78, + "d": 0 + }, + "mne/viz.py": { + "a": 104, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1696.json b/mne-python/source/doc/sphinxext/prs/1696.json new file mode 100644 index 0000000000000000000000000000000000000000..a28ed88cb95c24471855ff4d97d150ccd689ddbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1696.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "7e344bcccbc6982245a69af9db15689627a5b5e9", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 5, + "d": 3 + }, + "examples/plot_interpolate_bad_channels.py": { + "a": 56, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 14, + "d": 2 + }, + "mne/channels/interpolation.py": { + "a": 167, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 80, + "d": 0 + }, + "mne/channels/utils.py": { + "a": 34, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/maxfilter.py": { + "a": 3, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1698.json b/mne-python/source/doc/sphinxext/prs/1698.json new file mode 100644 index 0000000000000000000000000000000000000000..9138a822818d3db8f11b95a13f5f3f2045da2dd7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1698.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fcc83f6ce48585b2199f79654aab3b058186577c", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/mne_report_tutorial.rst": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/17.json b/mne-python/source/doc/sphinxext/prs/17.json new file mode 100644 index 0000000000000000000000000000000000000000..bab164371107f22b567a9d1ada175b6afa49f9a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/17.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3bf8057497870dcdc119fb9657154abe11cd778c", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 35, + "d": 6 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 41, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1701.json b/mne-python/source/doc/sphinxext/prs/1701.json new file mode 100644 index 0000000000000000000000000000000000000000..f882fb1c30c4c7bf158dab4bbdc9a96df8df7388 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1701.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "944c5c04edea3d3422953e47faf43fa2d46fd5e1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1705.json b/mne-python/source/doc/sphinxext/prs/1705.json new file mode 100644 index 0000000000000000000000000000000000000000..9452d19e537d1b434c4ea489b66453137341e50c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1705.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "90ddfff2dfabffd6d899fa8ff9085ab50d55fac5", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_morph_data.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 6, + "d": 6 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 3, + "d": 3 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 4, + "d": 4 + }, + "mne/label.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_source.py": { + "a": 18, + "d": 18 + }, + "mne/source_estimate.py": { + "a": 57, + "d": 50 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/stats/cluster_level.py": { + "a": 10, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 16, + "d": 16 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1711.json b/mne-python/source/doc/sphinxext/prs/1711.json new file mode 100644 index 0000000000000000000000000000000000000000..6d83de785cfc6b87d8679a1cb1540b7bac755b49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1711.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c2f1a6c162c1472b2286678fd824afc478a17617", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 46, + "d": 27 + }, + "mne/minimum_norm/inverse.py": { + "a": 11, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1712.json b/mne-python/source/doc/sphinxext/prs/1712.json new file mode 100644 index 0000000000000000000000000000000000000000..a1cb9a32e72c18078d2ccb32a1a0738fe1d031f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1712.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "0204eae6323d5da698d633ad2ef074114bea0ecf", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 232, + "d": 19 + }, + "mne/io/base.py": { + "a": 22, + "d": 4 + }, + "mne/io/constants.py": { + "a": 22, + "d": 0 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 43, + "d": 15 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 2 + }, + "mne/io/pick.py": { + "a": 42, + "d": 0 + }, + "mne/io/proc_history.py": { + "a": 276, + "d": 0 + }, + "mne/io/tag.py": { + "a": 0, + "d": 1 + }, + "mne/io/tests/test_proc_history.py": { + "a": 47, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 89, + "d": 4 + }, + "mne/utils.py": { + "a": 14, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1716.json b/mne-python/source/doc/sphinxext/prs/1716.json new file mode 100644 index 0000000000000000000000000000000000000000..1c4bd1ecaca3920db345c260f3320461c3bfe674 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1716.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "75606c4efcda651c04208e2da3a8235730d537f8", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 3 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 0, + "d": 3 + }, + "mne/utils.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1718.json b/mne-python/source/doc/sphinxext/prs/1718.json new file mode 100644 index 0000000000000000000000000000000000000000..3bbbd9583ef5d3615c6c00c41388afbf1a49b2f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1718.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "6f091cc401625dc0ab7098a8f5e000d8bb3db981", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "appveyor.yml": { + "a": 7, + "d": 7 + }, + "make/install_python.ps1": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 3, + "d": 1 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 2, + "d": 1 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/forward/tests/test_forward.py": { + "a": 3, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 3, + "d": 1 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 1 + }, + "mne/io/constants.py": { + "a": 15, + "d": 18 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 9, + "d": 6 + }, + "mne/io/proc_history.py": { + "a": 24, + "d": 24 + }, + "mne/io/tests/test_proc_history.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 4, + "d": 1 + }, + "mne/minimum_norm/tests/test_psf_ctf.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 5, + "d": 3 + }, + "mne/tests/test_report.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 7, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/172.json b/mne-python/source/doc/sphinxext/prs/172.json new file mode 100644 index 0000000000000000000000000000000000000000..907d017adefcb5aaf5fbdf75d333abe603f642d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/172.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a8777cb319e7a66bf9b74aa341cfd60d1374d97f", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 28, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1721.json b/mne-python/source/doc/sphinxext/prs/1721.json new file mode 100644 index 0000000000000000000000000000000000000000..da7e2500e9b82904d395a44db99f40c491e42794 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1721.json @@ -0,0 +1,255 @@ +{ + "merge_commit_sha": "ec6eb7bfd6a7d10265dc0bfb9b0a73587d7f23de", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "appveyor.yml": { + "a": 1, + "d": 1 + }, + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "doc/source/conf.py": { + "a": 3, + "d": 10 + }, + "doc/source/contributing.rst": { + "a": 3, + "d": 1 + }, + "doc/source/python_reference.rst": { + "a": 4, + "d": 23 + }, + "doc/sphinxext/docscrape.py": { + "a": 0, + "d": 497 + }, + "doc/sphinxext/docscrape_sphinx.py": { + "a": 0, + "d": 137 + }, + "doc/sphinxext/gen_rst.py": { + "a": 466, + "d": 217 + }, + "doc/sphinxext/numpy_ext/docscrape.py": { + "a": 58, + "d": 45 + }, + "doc/sphinxext/numpy_ext/docscrape_sphinx.py": { + "a": 30, + "d": 16 + }, + "doc/sphinxext/numpy_ext/numpydoc.py": { + "a": 54, + "d": 25 + }, + "doc/sphinxext/numpy_ext_old/__init__.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext_old/docscrape.py": { + "a": 0, + "d": 490 + }, + "doc/sphinxext/numpy_ext_old/docscrape_sphinx.py": { + "a": 0, + "d": 133 + }, + "doc/sphinxext/numpy_ext_old/numpydoc.py": { + "a": 0, + "d": 111 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 5, + "d": 3 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 2, + "d": 0 + }, + "examples/plot_make_forward.py": { + "a": 5, + "d": 0 + }, + "examples/plot_read_bem_surfaces.py": { + "a": 2, + "d": 0 + }, + "examples/plot_read_forward.py": { + "a": 2, + "d": 0 + }, + "examples/plot_read_noise_covariance_matrix.py": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 1 + }, + "mne/decoding/classifier.py": { + "a": 6, + "d": 5 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/event.py": { + "a": 5, + "d": 1 + }, + "mne/evoked.py": { + "a": 12, + "d": 14 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 3, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/io/constants.py": { + "a": 3, + "d": 2 + }, + "mne/io/open.py": { + "a": 1, + "d": 2 + }, + "mne/io/pick.py": { + "a": 7, + "d": 7 + }, + "mne/io/proc_history.py": { + "a": 24, + "d": 24 + }, + "mne/label.py": { + "a": 13, + "d": 6 + }, + "mne/parallel.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 16, + "d": 23 + }, + "mne/preprocessing/ssp.py": { + "a": 0, + "d": 2 + }, + "mne/proj.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/client.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/mockclient.py": { + "a": 2, + "d": 0 + }, + "mne/simulation/evoked.py": { + "a": 10, + "d": 9 + }, + "mne/source_estimate.py": { + "a": 31, + "d": 33 + }, + "mne/stats/multi_comp.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 136, + "d": 0 + }, + "mne/time_frequency/csd.py": { + "a": 0, + "d": 2 + }, + "mne/time_frequency/stft.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 8 + }, + "mne/transforms.py": { + "a": 4, + "d": 4 + }, + "mne/utils.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 14, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1723.json b/mne-python/source/doc/sphinxext/prs/1723.json new file mode 100644 index 0000000000000000000000000000000000000000..b9ec695fbecf52ffaf84a28187e5a645a9be7e70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1723.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2fe7d512fd08c9993afa5f427ff3cf9808fb6ec1", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 15, + "d": 13 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1725.json b/mne-python/source/doc/sphinxext/prs/1725.json new file mode 100644 index 0000000000000000000000000000000000000000..032e1e7ad65800791b5d404edc149be62ce050f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1725.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "679020521e680e2d0051111ed78ae18c9f7e4e09", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1726.json b/mne-python/source/doc/sphinxext/prs/1726.json new file mode 100644 index 0000000000000000000000000000000000000000..fca2ee1772e14c8fa1f273109495e54177449bb6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1726.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f7a74af49f88c4a0107dcf202eaf97756128b4dc", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/fiff/raw.py": { + "a": 10, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1731.json b/mne-python/source/doc/sphinxext/prs/1731.json new file mode 100644 index 0000000000000000000000000000000000000000..28a417264983b5d497b2154b72fd07da19e821aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1731.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0b77988dfa592b05b804c39d94176d14e2889a60", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fixes.py": { + "a": 8, + "d": 3 + }, + "mne/tests/test_cov.py": { + "a": 17, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1732.json b/mne-python/source/doc/sphinxext/prs/1732.json new file mode 100644 index 0000000000000000000000000000000000000000..dd06c379f46b80aafc5057a8aee92907f101e474 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1732.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "3e35259323de85c0b3e9ccc3a5a7dd4c9c20fe3b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 15, + "d": 6 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 10, + "d": 7 + }, + "mne/evoked.py": { + "a": 62, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1733.json b/mne-python/source/doc/sphinxext/prs/1733.json new file mode 100644 index 0000000000000000000000000000000000000000..79798b1d54c49dec6638ff7dbee29897bbcf87eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1733.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "eabc924be4f0ee23bcf52f16c4e580a77e8cbdd7", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 11, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/plot_rereference_eeg.py": { + "a": 63, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 4, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 5, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 5, + "d": 0 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 3, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 5, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 13, + "d": 73 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 15, + "d": 14 + }, + "mne/io/constants.py": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 9, + "d": 4 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 1, + "d": 35 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 13, + "d": 4 + }, + "mne/io/proj.py": { + "a": 29, + "d": 13 + }, + "mne/io/reference.py": { + "a": 302, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 181, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 14, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 7, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_proj.py": { + "a": 52, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1735.json b/mne-python/source/doc/sphinxext/prs/1735.json new file mode 100644 index 0000000000000000000000000000000000000000..a70461f343c57b1ca173a41ccdbadd418c94618d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1735.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "85e98ff974dcdb16c020f2f795969e709ecbe9aa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1736.json b/mne-python/source/doc/sphinxext/prs/1736.json new file mode 100644 index 0000000000000000000000000000000000000000..eb6c3159d2352e1c17178595b57b2825d50e01a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1736.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "dff77d37ccc4fd611bfabb7362c8a13c85d3f913", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 7, + "d": 18 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 10, + "d": 13 + }, + "mne/parallel.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_filter.py": { + "a": 46, + "d": 44 + }, + "mne/time_frequency/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/_stockwell.py": { + "a": 64, + "d": 68 + }, + "mne/time_frequency/multitaper.py": { + "a": 5, + "d": 10 + }, + "mne/time_frequency/stft.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 26, + "d": 19 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 22, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 70, + "d": 81 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1740.json b/mne-python/source/doc/sphinxext/prs/1740.json new file mode 100644 index 0000000000000000000000000000000000000000..6d66d9629e2954a2941f41ce4e0bd1e9bc76f85a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1740.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "083524fc9e7979053b4a40b68ae242d1cf18e153", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/_hdf5.py": { + "a": 0, + "d": 8 + }, + "mne/channels/layout.py": { + "a": 13, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 4, + "d": 1 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 12, + "d": 17 + }, + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 27 + }, + "mne/io/bti/bti.py": { + "a": 5, + "d": 17 + }, + "mne/io/constants.py": { + "a": 14, + "d": 24 + }, + "mne/io/edf/edf.py": { + "a": 11, + "d": 18 + }, + "mne/io/egi/egi.py": { + "a": 4, + "d": 10 + }, + "mne/io/fiff/raw.py": { + "a": 18, + "d": 0 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 4, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 7, + "d": 19 + }, + "mne/io/meas_info.py": { + "a": 249, + "d": 51 + }, + "mne/io/proc_history.py": { + "a": 16, + "d": 4 + }, + "mne/simulation/evoked.py": { + "a": 5, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1744.json b/mne-python/source/doc/sphinxext/prs/1744.json new file mode 100644 index 0000000000000000000000000000000000000000..cf1a6695cf92cbb83ee78a5eff82f868bb81cb98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1744.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e4216638edf58fe9003a5bc9e294e6377afec661", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1746.json b/mne-python/source/doc/sphinxext/prs/1746.json new file mode 100644 index 0000000000000000000000000000000000000000..05bed132a81487f6204eee6dff7ac2a6b27522fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1746.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ac3bd177215911fa012e2832f20fe506e53ff24c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 27, + "d": 1 + }, + "mne/io/constants.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1747.json b/mne-python/source/doc/sphinxext/prs/1747.json new file mode 100644 index 0000000000000000000000000000000000000000..a4b47a099d3e0209575606f7688f19a184bf6ef9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1747.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b168657ec4adc2e6d8e0079d7fe8a1c509ec1092", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 50, + "d": 17 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 41, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/175.json b/mne-python/source/doc/sphinxext/prs/175.json new file mode 100644 index 0000000000000000000000000000000000000000..3e499aaf7ff15f9e43045f1955e82f316f236c34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/175.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "020b1691e78279c98488d8a3e3673c65dc9b7091", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/python_tutorial.rst": { + "a": 11, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 189, + "d": 1 + }, + "mne/event.py": { + "a": 26, + "d": 25 + }, + "mne/fiff/constants.py": { + "a": 3, + "d": 1 + }, + "mne/fiff/tag.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/write.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 22, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1751.json b/mne-python/source/doc/sphinxext/prs/1751.json new file mode 100644 index 0000000000000000000000000000000000000000..482f519b46f95ab1b04ce74495e1f0e0773ac0c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1751.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6c3bf4b96ecc39852a19bdf4c0707ae7dc89ecc0", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 2, + "d": 3 + }, + "mne/io/tests/test_reference.py": { + "a": 15, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1756.json b/mne-python/source/doc/sphinxext/prs/1756.json new file mode 100644 index 0000000000000000000000000000000000000000..5a866e4f618ba28165dbb1035958b908799c43cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1756.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "6761a2aa8afbf4758cb929ed7530fdacd5c83656", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 3 + }, + "mne/label.py": { + "a": 6, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 12, + "d": 10 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 8, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 28, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1759.json b/mne-python/source/doc/sphinxext/prs/1759.json new file mode 100644 index 0000000000000000000000000000000000000000..d0d040362b866621654c096b9901d4ef16f804e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1759.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0ae914e321a9971adc77e15fa68dfa4c9a29ffea", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 64, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/176.json b/mne-python/source/doc/sphinxext/prs/176.json new file mode 100644 index 0000000000000000000000000000000000000000..0a1a97af7ddfb8320cfa4337b94abad0ba5be640 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/176.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5714255bba5c6126a4011100f36e4ce710ae9fba", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1762.json b/mne-python/source/doc/sphinxext/prs/1762.json new file mode 100644 index 0000000000000000000000000000000000000000..b8ee3b21b80c14d6e8f76e50cf44fe271b984cee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1762.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "f3c8d3ac0c8873ab608fd0dff7b06b8b7d065cc7", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 12, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/plot_clickable_image.py": { + "a": 66, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 84, + "d": 0 + }, + "mne/channels/tests/test_layout.py": { + "a": 34, + "d": 1 + }, + "mne/data/image/custom_layout.lout": { + "a": 24, + "d": 0 + }, + "mne/data/image/mni_brain.gif": { + "a": 0, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 3 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 14 + }, + "mne/viz/tests/test_utils.py": { + "a": 49, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 9, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 148, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1763.json b/mne-python/source/doc/sphinxext/prs/1763.json new file mode 100644 index 0000000000000000000000000000000000000000..3e96130971e6579ab42f80c4eb1beb4211dffa2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1763.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3f1e532ddd59154a150f85d1264dd66dabfa5992", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 21, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1768.json b/mne-python/source/doc/sphinxext/prs/1768.json new file mode 100644 index 0000000000000000000000000000000000000000..305d0c4618dcfab91372e58b6ab77a1cc4370ea4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1768.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "087b568d88ae85c8478c7c4f8b9ccd974f98a43c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/bads.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1769.json b/mne-python/source/doc/sphinxext/prs/1769.json new file mode 100644 index 0000000000000000000000000000000000000000..e5e6a5c338bdd3329f2c32210edaf4784f3a4424 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1769.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b0d1952e0afc7d71d4120e6c0ec35a9eccc0fd7a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_hdf5.py": { + "a": 21, + "d": 9 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/proc_history.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_hdf5.py": { + "a": 8, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 13, + "d": 0 + }, + "mne/utils.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1771.json b/mne-python/source/doc/sphinxext/prs/1771.json new file mode 100644 index 0000000000000000000000000000000000000000..e96a5cd11fef64dccb9c49fe6dd51743a312ddbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1771.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6024057eebf809f30a20d09c0988a0bac4df5bb1", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 56, + "d": 64 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1772.json b/mne-python/source/doc/sphinxext/prs/1772.json new file mode 100644 index 0000000000000000000000000000000000000000..e9865be734c3282c50fe972884d6d54039dad342 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1772.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "626a2f004024074ada5b5fc8b67ee6aea4e6f873", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 15, + "d": 4 + }, + "doc/source/advanced_setup.rst": { + "a": 130, + "d": 0 + }, + "doc/source/conf.py": { + "a": 6, + "d": 8 + }, + "doc/source/getting_started.rst": { + "a": 68, + "d": 173 + }, + "doc/source/mne-python.rst": { + "a": 1, + "d": 0 + }, + "doc/source/python_reference.rst": { + "a": 5, + "d": 3 + }, + "doc/sphinxext/flow_diagram.py": { + "a": 166, + "d": 0 + }, + "doc/sphinxext/gen_rst.py": { + "a": 45, + "d": 34 + }, + "examples/inverse/plot_mne_crosstalk_function.py": { + "a": 8, + "d": 11 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 8, + "d": 16 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 8, + "d": 5 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 41, + "d": 38 + }, + "mne/minimum_norm/tests/test_psf_ctf.py": { + "a": 53, + "d": 55 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1776.json b/mne-python/source/doc/sphinxext/prs/1776.json new file mode 100644 index 0000000000000000000000000000000000000000..d8077e48532ba65785c499c214eda53271e84c3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1776.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fb3252956b06bffc1019ba23a3611e1ffd5fbbba", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/channels/interpolation.py": { + "a": 7, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1779.json b/mne-python/source/doc/sphinxext/prs/1779.json new file mode 100644 index 0000000000000000000000000000000000000000..f0f0bca1c39319b46b324f29625e04ecb23975b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1779.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6f7de25e6081151fabf3a8e9433e7a7e51b089ea", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/report.py": { + "a": 14, + "d": 4 + }, + "mne/tests/test_report.py": { + "a": 13, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/178.json b/mne-python/source/doc/sphinxext/prs/178.json new file mode 100644 index 0000000000000000000000000000000000000000..99b6d1f62da228efa74632e644ea6a2f6e88db83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/178.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "cffc01240a9cebbf8122904799d07d502ef1bded", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/tests/test_evoked.py": { + "a": 10, + "d": 0 + }, + "mne/fiff/tests/test_raw.py": { + "a": 10, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 19, + "d": 9 + }, + "mne/source_space.py": { + "a": 7, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 10, + "d": 0 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1782.json b/mne-python/source/doc/sphinxext/prs/1782.json new file mode 100644 index 0000000000000000000000000000000000000000..acb9c611468c05df2ceb12240e8f946c9e2c3e26 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1782.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "957e3f3d1c749f29384457478fef7bd3218c9c04", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 4, + "d": 3 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 4, + "d": 4 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 3, + "d": 4 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 2, + "d": 8 + }, + "examples/inverse/plot_mne_crosstalk_function.py": { + "a": 3, + "d": 9 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 3, + "d": 9 + }, + "examples/plot_read_forward.py": { + "a": 1, + "d": 1 + }, + "examples/plot_ssp_projs_sensitivity_map.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 3, + "d": 5 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 1, + "d": 2 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 23, + "d": 12 + }, + "mne/viz/_3d.py": { + "a": 106, + "d": 14 + }, + "mne/viz/tests/test_3d.py": { + "a": 55, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 44, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1785.json b/mne-python/source/doc/sphinxext/prs/1785.json new file mode 100644 index 0000000000000000000000000000000000000000..1929c37cf029f94b21fdc44b96fc16fd8dcab21f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1785.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "461efa998a2b67407761136807d4054852fb620e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 20, + "d": 7 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 9, + "d": 7 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 17, + "d": 20 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 9, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 162, + "d": 88 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 255, + "d": 57 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 4, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 38, + "d": 23 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 105, + "d": 17 + }, + "mne/io/proj.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1786.json b/mne-python/source/doc/sphinxext/prs/1786.json new file mode 100644 index 0000000000000000000000000000000000000000..816bce7588c1335a7b58dd276588b6fe59112bed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1786.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "7af8e9401be385a91f36f3a1fa5c77ad43e2b84c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/epochs.py": { + "a": 38, + "d": 41 + }, + "mne/evoked.py": { + "a": 0, + "d": 2 + }, + "mne/io/array/array.py": { + "a": 0, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 0, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 0, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 0, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 0, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 0, + "d": 1 + }, + "mne/io/proj.py": { + "a": 31, + "d": 2 + }, + "mne/realtime/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1788.json b/mne-python/source/doc/sphinxext/prs/1788.json new file mode 100644 index 0000000000000000000000000000000000000000..2c42fa08ba380e7ef47414c0795290a6d14fa764 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1788.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5e731476b4f1ea74063a402109f4d0605cd83eab", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1789.json b/mne-python/source/doc/sphinxext/prs/1789.json new file mode 100644 index 0000000000000000000000000000000000000000..a086993c7bb8171e25e72a3fcb92a53eb20ce3e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1789.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "244d21c7175671e5ed4dbc6c17e9c7453d10c6e5", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/179.json b/mne-python/source/doc/sphinxext/prs/179.json new file mode 100644 index 0000000000000000000000000000000000000000..282f74ed7a62a6059f24b1af836c30fb6ed1fcdb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/179.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fb8c7029ea423722278fc66448e602342841fad9", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1791.json b/mne-python/source/doc/sphinxext/prs/1791.json new file mode 100644 index 0000000000000000000000000000000000000000..c4bc41c63e6aa7250dff855f206de9c35bff327b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1791.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "48b5b4072a4999bf45c8bbf8f7446eae499c1058", + "authors": [ + { + "n": "Basile", + "e": null + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1794.json b/mne-python/source/doc/sphinxext/prs/1794.json new file mode 100644 index 0000000000000000000000000000000000000000..bbf11fe161b7217b475bcbd85966911d76961741 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1794.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "97ae7e36874dedc4399699ab43f5b41df06b4183", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1798.json b/mne-python/source/doc/sphinxext/prs/1798.json new file mode 100644 index 0000000000000000000000000000000000000000..e5336fa208f913c0edebfd89cb8ba91d2ef27965 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1798.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e5b719c2601d39717993a63e30b6500d9262c142", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/classifier.py": { + "a": 6, + "d": 2 + }, + "mne/decoding/tests/test_classifier.py": { + "a": 18, + "d": 2 + }, + "mne/filter.py": { + "a": 9, + "d": 0 + }, + "mne/tests/test_filter.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1799.json b/mne-python/source/doc/sphinxext/prs/1799.json new file mode 100644 index 0000000000000000000000000000000000000000..6a211dacc092dc16592c7437782bf21ba8f91bc4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1799.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "82540830ef4c35f1d2ccf4cd0224ee709fd57a00", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/epochs.py": { + "a": 57, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 37, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/18.json b/mne-python/source/doc/sphinxext/prs/18.json new file mode 100644 index 0000000000000000000000000000000000000000..08900f1e6f71d07a0351d8f7a48f19bc28cab0c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/18.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9f4167c7e43563755c7517ce14e1e8c9db69e82f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/fiff/evoked.py": { + "a": 44, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1802.json b/mne-python/source/doc/sphinxext/prs/1802.json new file mode 100644 index 0000000000000000000000000000000000000000..e3fdf9adb7ef7e7c320d786ab2a14f04aff04881 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1802.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "35fc7f8a57cd4d09eaa2743de90902f9700b1442", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 49, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 19, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1805.json b/mne-python/source/doc/sphinxext/prs/1805.json new file mode 100644 index 0000000000000000000000000000000000000000..67664633abf0d6e4f93343de784aa10a107c19d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1805.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b38f0cdd27d3f36f743811609d00cb00d8ea5b7c", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1809.json b/mne-python/source/doc/sphinxext/prs/1809.json new file mode 100644 index 0000000000000000000000000000000000000000..f58d5c1e7fb8792d5f1832a5afa9dc642558563d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1809.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "58d4be1bf21f3d3fcbebfb3092590328cd270089", + "authors": [ + { + "n": "aestrivex", + "e": "aestrivex@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/181.json b/mne-python/source/doc/sphinxext/prs/181.json new file mode 100644 index 0000000000000000000000000000000000000000..91dd01261014a6470673be3f090b9b779f9608e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/181.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "18dfdf960cf22335f7dbe5b2c7a3827aa7bb6de1", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1810.json b/mne-python/source/doc/sphinxext/prs/1810.json new file mode 100644 index 0000000000000000000000000000000000000000..5df21bc8bb8b339416a2e547311296a46d2ca609 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1810.json @@ -0,0 +1,995 @@ +{ + "merge_commit_sha": "538f8e74b93b44ae043c6b94988ce8f813b229cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 7, + "d": 1 + }, + "Makefile": { + "a": 9, + "d": 0 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 5, + "d": 4 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 5, + "d": 6 + }, + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 6, + "d": 6 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 8, + "d": 8 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 5, + "d": 4 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 6, + "d": 7 + }, + "examples/datasets/plot_megsim_data.py": { + "a": 2, + "d": 1 + }, + "examples/datasets/plot_megsim_data_single_trial.py": { + "a": 2, + "d": 1 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 1, + "d": 2 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 8, + "d": 7 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 7, + "d": 6 + }, + "examples/decoding/plot_decoding_sensors.py": { + "a": 5, + "d": 4 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 6, + "d": 7 + }, + "examples/decoding/plot_decoding_time_generalization.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 4, + "d": 4 + }, + "examples/export/plot_epochs_as_data_frame.py": { + "a": 1, + "d": 2 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 7, + "d": 6 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 4, + "d": 3 + }, + "examples/export/plot_raw_to_nitime.py": { + "a": 5, + "d": 7 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 1, + "d": 3 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 3, + "d": 4 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 6, + "d": 6 + }, + "examples/inverse/plot_dipole_fit_result.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_label_activation_from_stc.py": { + "a": 61, + "d": 61 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 3, + "d": 2 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 3, + "d": 4 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/plot_mne_crosstalk_function.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_morph_data.py": { + "a": 6, + "d": 5 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_read_stc.py": { + "a": 3, + "d": 2 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 1, + "d": 3 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/plot_bem_contour_mri.py": { + "a": 2, + "d": 0 + }, + "examples/plot_channel_epochs_image.py": { + "a": 5, + "d": 4 + }, + "examples/plot_coregistration_transform.py": { + "a": 2, + "d": 0 + }, + "examples/plot_decimate_head_surface.py": { + "a": 2, + "d": 2 + }, + "examples/plot_define_target_events.py": { + "a": 4, + "d": 4 + }, + "examples/plot_estimate_covariance_matrix_baseline.py": { + "a": 2, + "d": 2 + }, + "examples/plot_estimate_covariance_matrix_raw.py": { + "a": 2, + "d": 2 + }, + "examples/plot_evoked_delayed_ssp.py": { + "a": 3, + "d": 2 + }, + "examples/plot_evoked_topomap.py": { + "a": 2, + "d": 2 + }, + "examples/plot_evoked_topomap_delayed_ssp.py": { + "a": 3, + "d": 2 + }, + "examples/plot_evoked_whitening.py": { + "a": 2, + "d": 2 + }, + "examples/plot_extract_events_from_raw.py": { + "a": 2, + "d": 2 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 4, + "d": 3 + }, + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 4, + "d": 3 + }, + "examples/plot_interpolate_bad_channels.py": { + "a": 3, + "d": 2 + }, + "examples/plot_left_cerebellum_volume_source.py": { + "a": 2, + "d": 2 + }, + "examples/plot_make_forward.py": { + "a": 4, + "d": 3 + }, + "examples/plot_meg_eeg_fields_3d.py": { + "a": 2, + "d": 2 + }, + "examples/plot_read_and_write_raw_data.py": { + "a": 3, + "d": 2 + }, + "examples/plot_read_bem_surfaces.py": { + "a": 2, + "d": 2 + }, + "examples/plot_read_epochs.py": { + "a": 3, + "d": 2 + }, + "examples/plot_read_evoked.py": { + "a": 2, + "d": 2 + }, + "examples/plot_read_forward.py": { + "a": 12, + "d": 12 + }, + "examples/plot_read_noise_covariance_matrix.py": { + "a": 3, + "d": 3 + }, + "examples/plot_rereference_eeg.py": { + "a": 2, + "d": 0 + }, + "examples/plot_shift_evoked.py": { + "a": 2, + "d": 2 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 2, + "d": 2 + }, + "examples/plot_ssp_projs_sensitivity_map.py": { + "a": 4, + "d": 2 + }, + "examples/plot_ssp_projs_topomaps.py": { + "a": 3, + "d": 3 + }, + "examples/plot_topo_channel_epochs_image.py": { + "a": 3, + "d": 2 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 3, + "d": 1 + }, + "examples/plot_topo_customized.py": { + "a": 4, + "d": 4 + }, + "examples/plot_topography.py": { + "a": 3, + "d": 3 + }, + "examples/preprocessing/plot_eog_artifact_histogram.py": { + "a": 4, + "d": 1 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 4, + "d": 1 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 5, + "d": 2 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 3, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 3, + "d": 2 + }, + "examples/read_events.py": { + "a": 2, + "d": 2 + }, + "examples/realtime/ftclient_rt_average.py": { + "a": 7, + "d": 7 + }, + "examples/realtime/ftclient_rt_compute_psd.py": { + "a": 2, + "d": 4 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 8, + "d": 5 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 8, + "d": 8 + }, + "examples/realtime/rt_feedback_client.py": { + "a": 2, + "d": 3 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 8, + "d": 9 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 5, + "d": 5 + }, + "examples/stats/plot_cluster_methods_tutorial.py": { + "a": 4, + "d": 5 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 5, + "d": 6 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 4, + "d": 5 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 5, + "d": 5 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 6, + "d": 6 + }, + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 4, + "d": 4 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 2, + "d": 3 + }, + "examples/stats/plot_sensor_regression.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_spatio_temporal_cluster_stats_sensor.py": { + "a": 6, + "d": 9 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/plot_compute_source_psd_epochs.py": { + "a": 3, + "d": 4 + }, + "examples/time_frequency/plot_single_trial_spectra.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 7, + "d": 7 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 4, + "d": 3 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 4, + "d": 3 + }, + "examples/time_frequency/plot_stockwell.py": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 3, + "d": 2 + }, + "examples/time_frequency/plot_time_frequency_multitaper_sensors.py": { + "a": 3, + "d": 2 + }, + "examples/time_frequency/plot_time_frequency_sensors.py": { + "a": 4, + "d": 3 + }, + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 4, + "d": 4 + }, + "mne/_hdf5.py": { + "a": 0, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 3, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 5, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_browse_raw.py": { + "a": 3, + "d": 1 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 3, + "d": 1 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 7, + "d": 2 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 3, + "d": 3 + }, + "mne/commands/mne_report.py": { + "a": 1, + "d": 0 + }, + "mne/connectivity/effective.py": { + "a": 3, + "d": 3 + }, + "mne/connectivity/spectral.py": { + "a": 46, + "d": 41 + }, + "mne/connectivity/tests/test_effective.py": { + "a": 6, + "d": 6 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 11, + "d": 11 + }, + "mne/coreg.py": { + "a": 1, + "d": 2 + }, + "mne/cov.py": { + "a": 16, + "d": 15 + }, + "mne/cuda.py": { + "a": 5, + "d": 5 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 6, + "d": 5 + }, + "mne/datasets/megsim/megsim.py": { + "a": 4, + "d": 4 + }, + "mne/datasets/megsim/urls.py": { + "a": 3, + "d": 3 + }, + "mne/datasets/testing/_testing.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_classifier.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_csp.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/evoked.py": { + "a": 6, + "d": 6 + }, + "mne/filter.py": { + "a": 5, + "d": 5 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_lead_dots.py": { + "a": 11, + "d": 11 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 8, + "d": 8 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_forward.py": { + "a": 4, + "d": 4 + }, + "mne/gui/_coreg_gui.py": { + "a": 4, + "d": 4 + }, + "mne/gui/_fiducials_gui.py": { + "a": 6, + "d": 4 + }, + "mne/gui/_file_traits.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_marker_gui.py": { + "a": 4, + "d": 4 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 4, + "d": 4 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 4, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 10, + "d": 8 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 5, + "d": 5 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 26, + "d": 43 + }, + "mne/io/array/array.py": { + "a": 0, + "d": 3 + }, + "mne/io/base.py": { + "a": 8, + "d": 8 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 3 + }, + "mne/io/bti/bti.py": { + "a": 6, + "d": 4 + }, + "mne/io/bti/read.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf.py": { + "a": 9, + "d": 11 + }, + "mne/io/diff.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 39, + "d": 34 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 5, + "d": 2 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 3, + "d": 3 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 15, + "d": 15 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 1, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/open.py": { + "a": 8, + "d": 8 + }, + "mne/io/pick.py": { + "a": 5, + "d": 5 + }, + "mne/io/proc_history.py": { + "a": 2, + "d": 2 + }, + "mne/io/proj.py": { + "a": 3, + "d": 4 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 3 + }, + "mne/io/tree.py": { + "a": 2, + "d": 1 + }, + "mne/io/write.py": { + "a": 2, + "d": 41 + }, + "mne/label.py": { + "a": 2, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 15, + "d": 16 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 4, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/misc.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 20, + "d": 15 + }, + "mne/preprocessing/peak_finder.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 10, + "d": 8 + }, + "mne/preprocessing/tests/test_maxfilter.py": { + "a": 1, + "d": 2 + }, + "mne/proj.py": { + "a": 4, + "d": 3 + }, + "mne/realtime/client.py": { + "a": 3, + "d": 3 + }, + "mne/realtime/epochs.py": { + "a": 14, + "d": 15 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/mockclient.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/stim_server_client.py": { + "a": 3, + "d": 2 + }, + "mne/report.py": { + "a": 16, + "d": 22 + }, + "mne/simulation/tests/test_source.py": { + "a": 8, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 8, + "d": 10 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 2 + }, + "mne/stats/parametric.py": { + "a": 4, + "d": 5 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_parametric.py": { + "a": 8, + "d": 11 + }, + "mne/surface.py": { + "a": 5, + "d": 6 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_cov.py": { + "a": 15, + "d": 16 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/_stockwell.py": { + "a": 3, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 14, + "d": 10 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 5, + "d": 5 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 0, + "d": 1 + }, + "mne/transforms.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 14, + "d": 6 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/circle.py": { + "a": 8, + "d": 7 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 3 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 5, + "d": 4 + }, + "mne/viz/tests/test_evoked.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 4 + }, + "mne/viz/tests/test_misc.py": { + "a": 2, + "d": 4 + }, + "mne/viz/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 12, + "d": 13 + }, + "mne/viz/tests/test_topo.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 6, + "d": 6 + }, + "mne/viz/tests/test_utils.py": { + "a": 2, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 7, + "d": 6 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "setup.cfg": { + "a": 4, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1815.json b/mne-python/source/doc/sphinxext/prs/1815.json new file mode 100644 index 0000000000000000000000000000000000000000..e8ef22a3f45b9f341f988506727450d6ff6da5e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1815.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "193cf2f7799ba388654433b47e0ebeae0a5adfe4", + "authors": [ + { + "n": "Yousra Bekhti", + "e": "yousra.bekhti@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_rap_music.py": { + "a": 56, + "d": 0 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_rap_music.py": { + "a": 267, + "d": 0 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 149, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 121, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 16, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1816.json b/mne-python/source/doc/sphinxext/prs/1816.json new file mode 100644 index 0000000000000000000000000000000000000000..0f95ed895f9a5d277f1ca750259215e8609347da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1816.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3226cbf6fbe4f0b9f9f6c390bd4707865efbcea3", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 8, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1817.json b/mne-python/source/doc/sphinxext/prs/1817.json new file mode 100644 index 0000000000000000000000000000000000000000..385025d698c16549ba36951793f30be3ffa5ba83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1817.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "efd7571ca4f465ea68b9f03403f2173699b82bbc", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/plot_read_epochs.py": { + "a": 1, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1818.json b/mne-python/source/doc/sphinxext/prs/1818.json new file mode 100644 index 0000000000000000000000000000000000000000..0ffde8f097ea2741c22c009657d88d2735a17648 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1818.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "71332fbf18580829bed8cd6eba672fd5a5c6ebba", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 3, + "d": 3 + }, + "examples/plot_evoked_whitening.py": { + "a": 3, + "d": 3 + }, + "mne/cov.py": { + "a": 25, + "d": 6 + }, + "mne/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/fixes.py": { + "a": 0, + "d": 177 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1820.json b/mne-python/source/doc/sphinxext/prs/1820.json new file mode 100644 index 0000000000000000000000000000000000000000..c20e471f7f58010bc5e1482c215fc64c4bb2104c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1820.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2de9daf649d762193b62aa1ed973c62e7c97798d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 12, + "d": 10 + }, + "mne/beamformer/_lcmv.py": { + "a": 121, + "d": 37 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1822.json b/mne-python/source/doc/sphinxext/prs/1822.json new file mode 100644 index 0000000000000000000000000000000000000000..d596b0a414765e9a09642cb9eb26af7cee28eb3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1822.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9b7a8b7442efa1a8f7756d75c782d8fc325e8be9", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 8, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1824.json b/mne-python/source/doc/sphinxext/prs/1824.json new file mode 100644 index 0000000000000000000000000000000000000000..92c5da457dec219fae0a502c71e63b2b97b7d54f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1824.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cb0ecdeb69c5e28b2d9031fb57cc6a564f83b5f4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1825.json b/mne-python/source/doc/sphinxext/prs/1825.json new file mode 100644 index 0000000000000000000000000000000000000000..b7cb3197bf706b2e3c75b2fa9b3eae5ec76d4945 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1825.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7c5d7c30f42da1871ef9f125fc38ce359e404009", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 2, + "d": 5 + }, + "mne/channels/tests/test_channels.py": { + "a": 8, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1827.json b/mne-python/source/doc/sphinxext/prs/1827.json new file mode 100644 index 0000000000000000000000000000000000000000..8e7906f60814f94ae00e63778da90f9751415235 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1827.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "85a945ca65f0ad918dd37368183f18c2650338e0", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1828.json b/mne-python/source/doc/sphinxext/prs/1828.json new file mode 100644 index 0000000000000000000000000000000000000000..f16b0ae4d8fdbd097591f5f1442f7edb65f45629 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1828.json @@ -0,0 +1,199 @@ +{ + "merge_commit_sha": "614488b79855cc3129a2ff645950dcd25d600ab5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "doc/source/python_reference.rst": { + "a": 14, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_dipole_fit.py": { + "a": 81, + "d": 0 + }, + "examples/inverse/plot_dipole_fit_result.py": { + "a": 0, + "d": 85 + }, + "examples/plot_left_cerebellum_volume_source.py": { + "a": 2, + "d": 2 + }, + "make/install_python.ps1": { + "a": 2, + "d": 2 + }, + "mne/__init__.py": { + "a": 5, + "d": 4 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 321, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 0, + "d": 2 + }, + "mne/channels/interpolation.py": { + "a": 4, + "d": 4 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 2 + }, + "mne/channels/utils.py": { + "a": 0, + "d": 34 + }, + "mne/cov.py": { + "a": 72, + "d": 24 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 2, + "d": 1 + }, + "mne/dipole.py": { + "a": 361, + "d": 26 + }, + "mne/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/forward/_compute_forward.py": { + "a": 303, + "d": 121 + }, + "mne/forward/_field_interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 164, + "d": 162 + }, + "mne/forward/forward.py": { + "a": 20, + "d": 10 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 37, + "d": 7 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 1, + "d": 0 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 13, + "d": 4 + }, + "mne/io/pick.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 68 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 91, + "d": 88 + }, + "mne/surface.py": { + "a": 68, + "d": 28 + }, + "mne/tests/test_bem.py": { + "a": 0, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 13, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 99, + "d": 11 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/ar.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 32, + "d": 12 + }, + "mne/viz/_3d.py": { + "a": 14, + "d": 4 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1829.json b/mne-python/source/doc/sphinxext/prs/1829.json new file mode 100644 index 0000000000000000000000000000000000000000..50d799fac4307f396355f1e558ae5ed833291656 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1829.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "06fbaf15b22048ce5a4bf77fb9956876a48a1c99", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 112, + "d": 10 + }, + "mne/source_space.py": { + "a": 21, + "d": 6 + }, + "mne/tests/test_dipole.py": { + "a": 37, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1831.json b/mne-python/source/doc/sphinxext/prs/1831.json new file mode 100644 index 0000000000000000000000000000000000000000..54e3cf9af7ab63867882e152859787afd4bbc95f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1831.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f08e0d01439237025de4e04a0ad2588f40a373f7", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 49, + "d": 107 + }, + "mne/io/edf/tests/data/test_uneven_samp.edf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test_uneven_samp.mat": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1832.json b/mne-python/source/doc/sphinxext/prs/1832.json new file mode 100644 index 0000000000000000000000000000000000000000..874f075e062039909576423c2e87efd6fd08bb66 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1832.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "47674c285a9d85a652a1db5cdeb823e4ad125eaf", + "authors": [ + { + "n": null, + "e": "flKazemakase@gmail.com" + } + ], + "changes": { + "mne/preprocessing/infomax_.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1834.json b/mne-python/source/doc/sphinxext/prs/1834.json new file mode 100644 index 0000000000000000000000000000000000000000..6cd5b79555c8dc1e2b3af38d822aaa901029446b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1834.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e3e58e5047f7706b12ef1535fb70606936d28053", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 10, + "d": 6 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1835.json b/mne-python/source/doc/sphinxext/prs/1835.json new file mode 100644 index 0000000000000000000000000000000000000000..dec613995fb7f8d0b58255002eed74f0fa92f21a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1835.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c8c088dd5ff507879d1d0c44f9d157617aad8bde", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/io/tag.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1838.json b/mne-python/source/doc/sphinxext/prs/1838.json new file mode 100644 index 0000000000000000000000000000000000000000..23f198046e4282621e4f101c1c9fb9e8179388c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1838.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ab0bf315742959780bdc7ddd18d5147b7e7f32ce", + "authors": [ + { + "n": "Clement Moutard", + "e": "clement.moutard@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 11, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 22, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1842.json b/mne-python/source/doc/sphinxext/prs/1842.json new file mode 100644 index 0000000000000000000000000000000000000000..80953c4f1b924d17cd070fdf0d6ec2718bbf4811 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1842.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9256d6b2a7fd8132a986ccbb042db8f2c40edb5b", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/evoked.py": { + "a": 5, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1844.json b/mne-python/source/doc/sphinxext/prs/1844.json new file mode 100644 index 0000000000000000000000000000000000000000..db01e50051910ccf273320c557de518352ebf92b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1844.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "8ed925e150e9af82e33bdb47f65afc4924a0fa5e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_snr_estimate.py": { + "a": 29, + "d": 0 + }, + "mne/minimum_norm/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 118, + "d": 0 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 42, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 40, + "d": 0 + }, + "mne/viz/tests/test_misc.py": { + "a": 19, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1845.json b/mne-python/source/doc/sphinxext/prs/1845.json new file mode 100644 index 0000000000000000000000000000000000000000..8c9ffbe5ab5856ac5514f5beb70dd5ead6d9cd39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1845.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "84dccca8d6398f8f71e9a1d9b60552ecf86d68bf", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/kit/constants.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1851.json b/mne-python/source/doc/sphinxext/prs/1851.json new file mode 100644 index 0000000000000000000000000000000000000000..b2a62674c4e449f8fc79f7bb038977259c3ce93e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1851.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b3c8c4cd3cdce72fb4cf07d2ab0fd038c53c266c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/write.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1852.json b/mne-python/source/doc/sphinxext/prs/1852.json new file mode 100644 index 0000000000000000000000000000000000000000..47abb6546bce2f30024504548d2becef66d967f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1852.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "be463db0c007d35e9cc5102f688543c16d42aea2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 64, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 24, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1854.json b/mne-python/source/doc/sphinxext/prs/1854.json new file mode 100644 index 0000000000000000000000000000000000000000..821d0aaf76bde025cfbe3d146cad4f1cff1e960c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1854.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "d9c384f360005c2f88f2e71b706980aed417a7e4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/source/cite.rst": { + "a": 1, + "d": 1 + }, + "doc/source/contributing.rst": { + "a": 4, + "d": 4 + }, + "doc/source/getting_started.rst": { + "a": 1, + "d": 1 + }, + "doc/source/git_links.inc": { + "a": 23, + "d": 23 + }, + "doc/source/known_projects.inc": { + "a": 3, + "d": 3 + }, + "doc/source/manual/analyze.rst": { + "a": 1, + "d": 1 + }, + "doc/source/manual/convert.rst": { + "a": 3, + "d": 3 + }, + "doc/source/mne-cpp.rst": { + "a": 1, + "d": 1 + }, + "doc/source/this_project.inc": { + "a": 2, + "d": 3 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 4 + }, + "examples/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1855.json b/mne-python/source/doc/sphinxext/prs/1855.json new file mode 100644 index 0000000000000000000000000000000000000000..5c65196599bd548161bb7e32dc7a302ccd59826d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1855.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "5bda2c003ec1cfd3b3deb4ef1fc32cebe3e1f91e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 6, + "d": 11 + }, + "mne/cov.py": { + "a": 4, + "d": 5 + }, + "mne/dipole.py": { + "a": 9, + "d": 7 + }, + "mne/epochs.py": { + "a": 12, + "d": 12 + }, + "mne/evoked.py": { + "a": 10, + "d": 8 + }, + "mne/io/base.py": { + "a": 7, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 2, + "d": 7 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 17 + }, + "mne/tests/test_utils.py": { + "a": 11, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 5 + }, + "mne/utils.py": { + "a": 12, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 6, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 9, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1858.json b/mne-python/source/doc/sphinxext/prs/1858.json new file mode 100644 index 0000000000000000000000000000000000000000..6c3b37d7c29b3c1c0961572dd3be649c878b33f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1858.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ec35be4d87505e9c7b7a0912e6c5e572c4fd3323", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 16, + "d": 32 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 0, + "d": 10 + }, + "mne/io/reference.py": { + "a": 83, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 102, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1859.json b/mne-python/source/doc/sphinxext/prs/1859.json new file mode 100644 index 0000000000000000000000000000000000000000..8173a866647403908c6b13aa110c4d5b8c46f43e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1859.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "72368c9e2db4f99a7ad2f296c8c42752fa1712df", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 1 + }, + "mne/report.py": { + "a": 51, + "d": 4 + }, + "mne/tests/test_report.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/186.json b/mne-python/source/doc/sphinxext/prs/186.json new file mode 100644 index 0000000000000000000000000000000000000000..99af1c11bc452fec6a1d91f7e14ea64389474f46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/186.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d45c46d9dc3bddab51fa2c0312fd18e3689760c1", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fixes.py": { + "a": 214, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_fixes.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1860.json b/mne-python/source/doc/sphinxext/prs/1860.json new file mode 100644 index 0000000000000000000000000000000000000000..1be5b96523a6e45f2a59edcb1553926a9b76096e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1860.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c5dc39d285ca8395947e28fe512a0339838657b1", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 6, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1861.json b/mne-python/source/doc/sphinxext/prs/1861.json new file mode 100644 index 0000000000000000000000000000000000000000..7a92371118c841a090c615c6bbe79a1b9941aa17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1861.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "28bc08f7ed2996f3c80061ba397d47a074adf54c", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 4, + "d": 3 + }, + "mne/label.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 10, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1864.json b/mne-python/source/doc/sphinxext/prs/1864.json new file mode 100644 index 0000000000000000000000000000000000000000..4bd27d5f95399ea7d34b4f5d802b4e9d2870a1ff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1864.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "83bc6e189308e39db542878a0073be33233b5f37", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/plot_read_noise_covariance_matrix.py": { + "a": 6, + "d": 8 + }, + "mne/cov.py": { + "a": 34, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_misc.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1865.json b/mne-python/source/doc/sphinxext/prs/1865.json new file mode 100644 index 0000000000000000000000000000000000000000..3a97ffc6370ff13a2a440c6fa346c40d72270f31 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1865.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "7325131a3d17fa0a0e3b5221c5d06c691a617c51", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 2, + "d": 2 + }, + "examples/plot_read_bem_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 1 + }, + "mne/source_space.py": { + "a": 14, + "d": 8 + }, + "mne/surface.py": { + "a": 15, + "d": 8 + }, + "mne/tests/test_source_space.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_surface.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1866.json b/mne-python/source/doc/sphinxext/prs/1866.json new file mode 100644 index 0000000000000000000000000000000000000000..c8829d681479f286a6d417200ee4fdf60c856032 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1866.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cc35976c3d1ce7803cb67e3a757d7927f597299a", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/187.json b/mne-python/source/doc/sphinxext/prs/187.json new file mode 100644 index 0000000000000000000000000000000000000000..c76b13bd8327f6121dc5d5953c796806d699acc2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/187.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "12501872506415575f2b824f7a0a13a5d55ca88a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_morph_data.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 2, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 7 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1870.json b/mne-python/source/doc/sphinxext/prs/1870.json new file mode 100644 index 0000000000000000000000000000000000000000..b52bb76819cf4d43d6add38398891bededb7e8ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1870.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b54a39bb2947d68348157c55735246c33e1b765e", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1871.json b/mne-python/source/doc/sphinxext/prs/1871.json new file mode 100644 index 0000000000000000000000000000000000000000..059999b8fdf6346946548704d8488c71ffcc3b8f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1871.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fe5aaecfe2ce2bf6efb88064e9b5dbea4b9559c2", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/time_gen.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1873.json b/mne-python/source/doc/sphinxext/prs/1873.json new file mode 100644 index 0000000000000000000000000000000000000000..1216c879cddfce7290de153ea1c3080fd3dc2c5e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1873.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f675c61e93c5a4536ef3ab60318baa120c506beb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 29, + "d": 4 + }, + "mne/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1874.json b/mne-python/source/doc/sphinxext/prs/1874.json new file mode 100644 index 0000000000000000000000000000000000000000..76feda3235afd3ea8a46a30ce68b596117c6dd59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1874.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a0ca9af2d862e60ecf0ebb4e4280473b3dde8d85", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1876.json b/mne-python/source/doc/sphinxext/prs/1876.json new file mode 100644 index 0000000000000000000000000000000000000000..be24ce61a991de238d349c8f945575caa93cfcbd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1876.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "73ed901a32895b3c17bef5494eec6a558b747b7f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 3 + }, + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_dipole_fit.py": { + "a": 2, + "d": 34 + }, + "examples/inverse/plot_rap_music.py": { + "a": 3, + "d": 2 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 3, + "d": 3 + }, + "mne/bem.py": { + "a": 11, + "d": 9 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 4, + "d": 4 + }, + "mne/cov.py": { + "a": 5, + "d": 1 + }, + "mne/dipole.py": { + "a": 94, + "d": 18 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 41, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 6, + "d": 4 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 23, + "d": 4 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 0, + "d": 87 + }, + "mne/io/chpi.py": { + "a": 130, + "d": 0 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 1, + "d": 20 + }, + "mne/io/tests/test_chpi.py": { + "a": 52, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 4, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 27, + "d": 59 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 34, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 10, + "d": 9 + }, + "mne/viz/tests/test_misc.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1877.json b/mne-python/source/doc/sphinxext/prs/1877.json new file mode 100644 index 0000000000000000000000000000000000000000..7c00d5aea73ec72b995fd849e3c0327337ae03b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1877.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7bb23ab445a9aaee82d0b30250ee3d379dcc771c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 7, + "d": 7 + }, + "mne/io/proc_history.py": { + "a": 4, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1879.json b/mne-python/source/doc/sphinxext/prs/1879.json new file mode 100644 index 0000000000000000000000000000000000000000..ed022c1ddf0010a039c0540c163a0f7c5f603c2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1879.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "34e116f4043ef7b8b19fe15d8b9261fc05dd5cf6", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 55, + "d": 49 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1881.json b/mne-python/source/doc/sphinxext/prs/1881.json new file mode 100644 index 0000000000000000000000000000000000000000..5e14ac80ff48b7b193e7ea0f8c60c71c05268603 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1881.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "adf63c33fc5c4f7639af7799306a7e253b3ec3fa", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 5, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 11, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 5, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 6, + "d": 2 + }, + "mne/io/fiff/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 51, + "d": 0 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 3, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1884.json b/mne-python/source/doc/sphinxext/prs/1884.json new file mode 100644 index 0000000000000000000000000000000000000000..9c87f76e1e0635e73388ce1741e9735a21ab18f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1884.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3017c02048056aca97b5ef0bb8310dc895ef8785", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/io/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 5, + "d": 5 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/189.json b/mne-python/source/doc/sphinxext/prs/189.json new file mode 100644 index 0000000000000000000000000000000000000000..2b2dfa33e1e4fb1a47ed1a7ce5272b762c1aebc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/189.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f18dcaca4a18c3bf56d106cd5c9169e46a14f7d2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 29, + "d": 6 + }, + "mne/tests/test_source_estimate.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1891.json b/mne-python/source/doc/sphinxext/prs/1891.json new file mode 100644 index 0000000000000000000000000000000000000000..b9bbd0991c4f26728c35488a5daad960868a1270 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1891.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8e97c24e94c200664993b5f516df37e1387a08a5", + "authors": [ + { + "n": "moutard", + "e": "clement.moutard@gmail.com" + } + ], + "changes": { + "mne/decoding/time_gen.py": { + "a": 28, + "d": 8 + }, + "mne/viz/decoding.py": { + "a": 42, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1895.json b/mne-python/source/doc/sphinxext/prs/1895.json new file mode 100644 index 0000000000000000000000000000000000000000..8d72986cc000ca595f75740ce803aedbd89d7175 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1895.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3c875fce0419f6a1beabdde8f38fb5d903db2095", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1896.json b/mne-python/source/doc/sphinxext/prs/1896.json new file mode 100644 index 0000000000000000000000000000000000000000..16dd10c0e6327a0f5d8e43caf35d48b4bd36112c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1896.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "d1ad8e0606518a572a549a3a62bd81a18bb067d1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 3, + "d": 6 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 2, + "d": 2 + }, + "examples/plot_coregistration_transform.py": { + "a": 1, + "d": 1 + }, + "examples/plot_make_forward.py": { + "a": 2, + "d": 2 + }, + "examples/plot_meg_eeg_fields_3d.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 14, + "d": 9 + }, + "mne/forward/_make_forward.py": { + "a": 19, + "d": 13 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 6 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 4, + "d": 4 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 32, + "d": 34 + }, + "mne/report.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 12, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1897.json b/mne-python/source/doc/sphinxext/prs/1897.json new file mode 100644 index 0000000000000000000000000000000000000000..ff2c56a6a2a6d5b28db08237c16683c2432c0df6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1897.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "f5dd3c9207b670a91d603b9afe6ccbf00d176354", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 6, + "d": 5 + }, + "mne/epochs.py": { + "a": 14, + "d": 14 + }, + "mne/preprocessing/ecg.py": { + "a": 12, + "d": 6 + }, + "mne/preprocessing/eog.py": { + "a": 12, + "d": 6 + }, + "mne/preprocessing/ica.py": { + "a": 13, + "d": 6 + }, + "mne/preprocessing/ssp.py": { + "a": 6, + "d": 6 + }, + "mne/proj.py": { + "a": 12, + "d": 12 + }, + "mne/realtime/epochs.py": { + "a": 14, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/19.json b/mne-python/source/doc/sphinxext/prs/19.json new file mode 100644 index 0000000000000000000000000000000000000000..512b94571e44af9aed09470a1495e24661ab12e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/19.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b9a12876e7bbdae86f219d6dd071c81b73ccd17d", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 41, + "d": 28 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1901.json b/mne-python/source/doc/sphinxext/prs/1901.json new file mode 100644 index 0000000000000000000000000000000000000000..eddd8abb8cfacfe39548ef737cf1f281dfa3df0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1901.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5b65c7b003325ca2adb1395e7a95b04ac2514f4d", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 17, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1908.json b/mne-python/source/doc/sphinxext/prs/1908.json new file mode 100644 index 0000000000000000000000000000000000000000..bb445c7999fd70f8a41ef20f0aceaad3e7876199 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1908.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3fbdc6d689526743a6d1cf49a1d4aadbaa395a7f", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/191.json b/mne-python/source/doc/sphinxext/prs/191.json new file mode 100644 index 0000000000000000000000000000000000000000..9419f1d9f6ef7ddae554fa1c6bb3b52f3a05558f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/191.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b016aaaddde06d1dd79c4d7098d514475506f374", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_ecg_artifacts_from_ica.py": { + "a": 30, + "d": 24 + }, + "examples/preprocessing/plot_eog_artifacts_from_ica.py": { + "a": 23, + "d": 18 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 22, + "d": 6 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 26, + "d": 15 + }, + "mne/artifacts/ica.py": { + "a": 232, + "d": 98 + }, + "mne/artifacts/tests/test_ica.py": { + "a": 149, + "d": 75 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1911.json b/mne-python/source/doc/sphinxext/prs/1911.json new file mode 100644 index 0000000000000000000000000000000000000000..27466572fa234a7b3c61f7e920c86ed420974fc2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1911.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "47ec75c3a1c2ba4f16d0398c479707af65c3b7d9", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/decoding/classifier.py": { + "a": 10, + "d": 6 + }, + "mne/epochs.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1914.json b/mne-python/source/doc/sphinxext/prs/1914.json new file mode 100644 index 0000000000000000000000000000000000000000..ad610d2b3c16e360a9f2e9ba654bbac658523f37 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1914.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "90d297e918e28f8eab1f7d364d47f064abb66d32", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 5, + "d": 0 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 7, + "d": 7 + }, + "examples/time_frequency/plot_epochs_spectra.py": { + "a": 45, + "d": 0 + }, + "examples/time_frequency/plot_single_trial_spectra.py": { + "a": 0, + "d": 99 + }, + "mne/epochs.py": { + "a": 126, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 26, + "d": 6 + }, + "mne/time_frequency/psd.py": { + "a": 68, + "d": 42 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 59, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 17, + "d": 8 + }, + "mne/viz/__init__.py": { + "a": 4, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 94, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 81, + "d": 49 + }, + "mne/viz/tests/test_epochs.py": { + "a": 12, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 5, + "d": 5 + }, + "mne/viz/tests/test_topo.py": { + "a": 4, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 214, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1915.json b/mne-python/source/doc/sphinxext/prs/1915.json new file mode 100644 index 0000000000000000000000000000000000000000..a94d613c2351c19b022ed2a78a0398c1166434d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1915.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b7f0c3c06e58b766f84ae4d25d1defd814db931e", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 5, + "d": 2 + }, + "mne/decoding/time_gen.py": { + "a": 17, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1918.json b/mne-python/source/doc/sphinxext/prs/1918.json new file mode 100644 index 0000000000000000000000000000000000000000..b0a505bb2134eae808673bfb890b2007f13af80d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1918.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6498dd9871124776c71f4065fe22e70683c9de26", + "authors": [ + { + "n": "Hari Bharadwaj", + "e": null + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 10, + "d": 7 + }, + "mne/channels/tests/test_montage.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/192.json b/mne-python/source/doc/sphinxext/prs/192.json new file mode 100644 index 0000000000000000000000000000000000000000..cbd78bf020a560601b6e64842e0998a73c457d88 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/192.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "08ddd9a85e62a351773321c1bbc7bc4558cc9940", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 20, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1921.json b/mne-python/source/doc/sphinxext/prs/1921.json new file mode 100644 index 0000000000000000000000000000000000000000..497481140ddec53ce11032cacf10fd3e8a5f0646 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1921.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6ab25486e53d2197a97229d694fdfe2ff079eeaa", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1923.json b/mne-python/source/doc/sphinxext/prs/1923.json new file mode 100644 index 0000000000000000000000000000000000000000..f0569d716ad7950f9b696e0271d156935e2e25a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1923.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f83a81a73873adeef6822513a18faafe3ab2e369", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/reference.py": { + "a": 4, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1925.json b/mne-python/source/doc/sphinxext/prs/1925.json new file mode 100644 index 0000000000000000000000000000000000000000..8ff719682b9010b0cfc10a1c139b146c8e377e24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1925.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5e0ecd54e9e970b0e4e9b7cd5ad58c8b0d6f3a61", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 55 + }, + "mne/tests/test_epochs.py": { + "a": 69, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1929.json b/mne-python/source/doc/sphinxext/prs/1929.json new file mode 100644 index 0000000000000000000000000000000000000000..aee6c26c0717b39835f7824098fb22881bd37987 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1929.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "abf811e147c24397c161344841971426744e9773", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/193.json b/mne-python/source/doc/sphinxext/prs/193.json new file mode 100644 index 0000000000000000000000000000000000000000..45fcd531e008b9d86053b931329c43e06faa7678 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/193.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9063dc9da686322b356864253fec7108f5eaace4", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/artifacts/ica.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1931.json b/mne-python/source/doc/sphinxext/prs/1931.json new file mode 100644 index 0000000000000000000000000000000000000000..486931b80e6b3057eb5672875a98474e4430d76f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1931.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "54ea53109e14e7c707d92703797c220f5165e6c1", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 3, + "d": 2 + }, + "doc/source/whats_new.rst": { + "a": 23, + "d": 20 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 18, + "d": 2 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 268 + }, + "mne/channels/montage.py": { + "a": 487, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 3, + "d": 3 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 104, + "d": 6 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/layouts/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/montage.py": { + "a": 24, + "d": 9 + }, + "mne/viz/tests/test_montage.py": { + "a": 16, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1932.json b/mne-python/source/doc/sphinxext/prs/1932.json new file mode 100644 index 0000000000000000000000000000000000000000..0f3780c8f38309f31b1ec6ed63596864b7964961 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1932.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "14fdd49af1d809bdf2337b53c607f3f379b3bfed", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 7, + "d": 2 + }, + "mne/channels/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 96, + "d": 7 + }, + "mne/channels/tests/test_channels.py": { + "a": 30, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1933.json b/mne-python/source/doc/sphinxext/prs/1933.json new file mode 100644 index 0000000000000000000000000000000000000000..ac5482e7558095345e5d12992238c684d328fc1e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1933.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "66f4adde0bca70eca03c79bd86923ed36cc61934", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/classifier.py": { + "a": 6, + "d": 6 + }, + "mne/epochs.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1936.json b/mne-python/source/doc/sphinxext/prs/1936.json new file mode 100644 index 0000000000000000000000000000000000000000..601a51e80c6d11a519c8131c0a06799d6b30edd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1936.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ac9c1670e2c67613e11d3c466dc88159d89c62a6", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 10, + "d": 1 + }, + "mne/io/edf/tests/data/test_edf_eeglab.mat": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1937.json b/mne-python/source/doc/sphinxext/prs/1937.json new file mode 100644 index 0000000000000000000000000000000000000000..1a8fe4b4c77f2c6aa19743c1c25bea849ee49685 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1937.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4cdd5d227b8e7dbe5284e2fb4bd26d0d03ef1a34", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/viz/topo.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/194.json b/mne-python/source/doc/sphinxext/prs/194.json new file mode 100644 index 0000000000000000000000000000000000000000..0921e8f8375f0acae533ae8743027e634f8cba6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/194.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4684fc1dabe0218102e931c58a2d6dfdf22fffda", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "mne/time_frequency/stft.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1940.json b/mne-python/source/doc/sphinxext/prs/1940.json new file mode 100644 index 0000000000000000000000000000000000000000..32bcc0022f965a25223949ce287d839ee982a048 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1940.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "981995260f78317334b924a41ab7bb3f11cab354", + "authors": [ + { + "n": "Hafeza Anevar", + "e": "hafiza.taj@gmail.com" + } + ], + "changes": { + "mne/fixes.py": { + "a": 104, + "d": 0 + }, + "mne/utils.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1942.json b/mne-python/source/doc/sphinxext/prs/1942.json new file mode 100644 index 0000000000000000000000000000000000000000..35061f728850bab4b765ac93cbf87fe74ee614c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1942.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ca5440e1d0c7fe52e426c098b3d65d3ec007ebf9", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 6, + "d": 4 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1943.json b/mne-python/source/doc/sphinxext/prs/1943.json new file mode 100644 index 0000000000000000000000000000000000000000..cc78274604a99a2c5abafe3a3b62988b13f6e5bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1943.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "8773accb114d38ea93b2390c738d1c20196dc6da", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 0 + }, + "examples/plot_virtual_evoked.py": { + "a": 39, + "d": 0 + }, + "mne/evoked.py": { + "a": 25, + "d": 0 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 110, + "d": 13 + }, + "mne/forward/_lead_dots.py": { + "a": 214, + "d": 5 + }, + "mne/forward/_make_forward.py": { + "a": 19, + "d": 1 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 59, + "d": 4 + }, + "mne/utils.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1945.json b/mne-python/source/doc/sphinxext/prs/1945.json new file mode 100644 index 0000000000000000000000000000000000000000..58d111fc671090d9b5111f968f4cf9d485a0328f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1945.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a0c37d9f7572dce6271574aeaa3ab75a41818aa2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 0, + "d": 4 + }, + "mne/cuda.py": { + "a": 52, + "d": 41 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1946.json b/mne-python/source/doc/sphinxext/prs/1946.json new file mode 100644 index 0000000000000000000000000000000000000000..bb86cffe6de00fa240d50c5fa544d1a7034badf2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1946.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "100621bac4e89475c20b9055fba5a51b8a78177c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 5, + "d": 5 + }, + "mne/io/base.py": { + "a": 26, + "d": 21 + }, + "mne/io/bti/read.py": { + "a": 16, + "d": 16 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 23, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1947.json b/mne-python/source/doc/sphinxext/prs/1947.json new file mode 100644 index 0000000000000000000000000000000000000000..0329450658c7de92ea95e7a2ef53ae9bdf8034cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1947.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "966e489a408a6ea32ab4af3ed0a04a22dbc4879d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/gen_rst.py": { + "a": 1, + "d": 4 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 1, + "d": 4 + }, + "examples/inverse/plot_dipole_fit.py": { + "a": 1, + "d": 4 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 1, + "d": 4 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 2, + "d": 4 + }, + "examples/plot_decimate_head_surface.py": { + "a": 1, + "d": 4 + }, + "examples/plot_read_bem_surfaces.py": { + "a": 1, + "d": 4 + }, + "mne/commands/mne_flash_bem_model.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1948.json b/mne-python/source/doc/sphinxext/prs/1948.json new file mode 100644 index 0000000000000000000000000000000000000000..1b06c26590dd0299ddd2cb5f6741f428651f38c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1948.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c6884950188cecec2c6a8c7e536dd0b49eb2f044", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 24, + "d": 11 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 1 + }, + "mne/io/tests/test_apply_function.py": { + "a": 57, + "d": 0 + }, + "mne/utils.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1950.json b/mne-python/source/doc/sphinxext/prs/1950.json new file mode 100644 index 0000000000000000000000000000000000000000..4c74048cfd5cb80d51103f0572f4febe68ea0a49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1950.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "af34b75bb1657cf4f16b0da23fc4fdc7c9fa0d9e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 0 + }, + "mne/parallel.py": { + "a": 2, + "d": 2 + }, + "mne/stats/cluster_level.py": { + "a": 9, + "d": 5 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 39, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1951.json b/mne-python/source/doc/sphinxext/prs/1951.json new file mode 100644 index 0000000000000000000000000000000000000000..10eab72613bf996ded47117a03630d3c4cef5f5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1951.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6d83c531bce8a82923302201e5278a18713a798a", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 12, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1952.json b/mne-python/source/doc/sphinxext/prs/1952.json new file mode 100644 index 0000000000000000000000000000000000000000..aa337177d8b444ac72240b373ded9c43a0af778b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1952.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "8fd16d645994c2dd220d7455e6b0e89c750870ba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 1, + "d": 1 + }, + "examples/plot_decimate_head_surface.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_bem_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 6 + }, + "mne/forward/tests/test_forward.py": { + "a": 4, + "d": 2 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 21 + }, + "mne/io/base.py": { + "a": 54, + "d": 26 + }, + "mne/io/brainvision/brainvision.py": { + "a": 11, + "d": 26 + }, + "mne/io/bti/bti.py": { + "a": 4, + "d": 26 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 10, + "d": 23 + }, + "mne/io/egi/egi.py": { + "a": 7, + "d": 23 + }, + "mne/io/fiff/raw.py": { + "a": 18, + "d": 66 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 50, + "d": 51 + }, + "mne/io/kit/kit.py": { + "a": 7, + "d": 20 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 5 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1953.json b/mne-python/source/doc/sphinxext/prs/1953.json new file mode 100644 index 0000000000000000000000000000000000000000..c0c0635004193e44945213f31462de3159a0b7e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1953.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a43d49b2380f15f3e94f422cba1e21c254912943", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 4, + "d": 2 + }, + "mne/decoding/time_gen.py": { + "a": 28, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1955.json b/mne-python/source/doc/sphinxext/prs/1955.json new file mode 100644 index 0000000000000000000000000000000000000000..10dbb70ff3db88b70fd72f11bdd1c0ea48bb8b2d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1955.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "37a613a84820a5b72a2298c8912446caa8707eba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/export/README.txt": { + "a": 0, + "d": 5 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 0, + "d": 66 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 0, + "d": 35 + }, + "examples/export/plot_raw_to_nitime.py": { + "a": 0, + "d": 81 + }, + "examples/plot_epochs_as_data_frame.py": { + "a": 0, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 0 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 8, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 12, + "d": 9 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1956.json b/mne-python/source/doc/sphinxext/prs/1956.json new file mode 100644 index 0000000000000000000000000000000000000000..cc37f720a53b46068e8c1f697447140de8184d1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1956.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "3a3155f7e83bd8353ccdfb7208f749e1a7438695", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 0, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 6, + "d": 2 + }, + "examples/inverse/plot_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 2, + "d": 4 + }, + "mne/channels/channels.py": { + "a": 65, + "d": 1 + }, + "mne/evoked.py": { + "a": 10, + "d": 6 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 4, + "d": 4 + }, + "mne/io/pick.py": { + "a": 5, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 2, + "d": 3 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 8, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 14, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1957.json b/mne-python/source/doc/sphinxext/prs/1957.json new file mode 100644 index 0000000000000000000000000000000000000000..49d39037bb7f31965c0083aed7cd9c9549919182 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1957.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d565410fac89de75b6acd9adf172efc163dd9fdc", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/report.py": { + "a": 16, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1962.json b/mne-python/source/doc/sphinxext/prs/1962.json new file mode 100644 index 0000000000000000000000000000000000000000..81c828c5056949c3938b3a8d8035903daafbd35f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1962.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "263110920da7985453be4e50a6b8dfea6afab0da", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/channels/data/montages/biosemi-128.txt": { + "a": 132, + "d": 0 + }, + "mne/channels/data/montages/biosemi-16.txt": { + "a": 20, + "d": 0 + }, + "mne/channels/data/montages/biosemi-160.txt": { + "a": 164, + "d": 0 + }, + "mne/channels/data/montages/biosemi-256.txt": { + "a": 260, + "d": 0 + }, + "mne/channels/data/montages/biosemi-32.txt": { + "a": 36, + "d": 0 + }, + "mne/channels/data/montages/biosemi-64.txt": { + "a": 68, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1965.json b/mne-python/source/doc/sphinxext/prs/1965.json new file mode 100644 index 0000000000000000000000000000000000000000..c70e55cb58ff5e7fe43bdda7b70a357945a6c068 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1965.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c543fad284933f36c3ad1a654e516c97fbfb64de", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "examples/decoding/plot_decoding_time_generalization.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 25, + "d": 48 + }, + "mne/decoding/time_gen.py": { + "a": 28, + "d": 151 + }, + "mne/viz/decoding.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1967.json b/mne-python/source/doc/sphinxext/prs/1967.json new file mode 100644 index 0000000000000000000000000000000000000000..df64155f7768d823e6cb76f832298fabd6b5c094 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1967.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6a65c7247e1a2736d2ccb70f7521e37d2784e8c4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 29, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1969.json b/mne-python/source/doc/sphinxext/prs/1969.json new file mode 100644 index 0000000000000000000000000000000000000000..6af90c2fb7e67553e1ec50a8f4f5a7048bea3ce6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1969.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4ecfa061167e3556d54fd0cf828f0f2ed405b504", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1972.json b/mne-python/source/doc/sphinxext/prs/1972.json new file mode 100644 index 0000000000000000000000000000000000000000..3149bc0e483455a6e282ca33426ea9eb94bb9686 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1972.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6d785f170055e033e22f841ab0e1ae6284329dfa", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 11, + "d": 2 + }, + "mne/evoked.py": { + "a": 7, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 11, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 14, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 116, + "d": 58 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1974.json b/mne-python/source/doc/sphinxext/prs/1974.json new file mode 100644 index 0000000000000000000000000000000000000000..f9a2923753c9835b48653de49b6151049796e7ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1974.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d6ed0e35b4d85926ef155c1c830baba31d3fa7c6", + "authors": [ + { + "n": "manoj kumar", + "e": "mechcoder@google.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1977.json b/mne-python/source/doc/sphinxext/prs/1977.json new file mode 100644 index 0000000000000000000000000000000000000000..cf494b6740433b1000a4dcddffda0320b1e4c14f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1977.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "557e4d0b362e865b2f22c8b66692d62650d56524", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 10, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1978.json b/mne-python/source/doc/sphinxext/prs/1978.json new file mode 100644 index 0000000000000000000000000000000000000000..d10a56640ab80c7ffb4462b1d03de19022a040b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1978.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "000ebe8909933a20572685a7770c349478775bd4", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 4, + "d": 5 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 3 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 2 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 15, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1979.json b/mne-python/source/doc/sphinxext/prs/1979.json new file mode 100644 index 0000000000000000000000000000000000000000..8ef00080f1b41cc977437ffed2bd5547af87bf08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1979.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bf8b8758f440fc480d5cc601777cd0d8962870e7", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/faq.rst": { + "a": 73, + "d": 0 + }, + "doc/source/mne-python.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/198.json b/mne-python/source/doc/sphinxext/prs/198.json new file mode 100644 index 0000000000000000000000000000000000000000..069f148938b9bd455df83a498bb9ea77710826a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/198.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "22bec9c303824cc20da87d2da42f02e0b691d564", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fiff/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/fiff/proj.py": { + "a": 0, + "d": 25 + }, + "mne/fiff/raw.py": { + "a": 6, + "d": 106 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1980.json b/mne-python/source/doc/sphinxext/prs/1980.json new file mode 100644 index 0000000000000000000000000000000000000000..8de97ea2aae3bfb7d64c45f99eb820ce0d1887dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1980.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "29a44177e061c84ae3af122c9a843299ccfb1c3a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 9, + "d": 12 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 11 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1981.json b/mne-python/source/doc/sphinxext/prs/1981.json new file mode 100644 index 0000000000000000000000000000000000000000..70368a560e0954c419513a1bbca7c93979ad933d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1981.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "367e542c058105a8141dd15011f9690237ebf974", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 76, + "d": 76 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1984.json b/mne-python/source/doc/sphinxext/prs/1984.json new file mode 100644 index 0000000000000000000000000000000000000000..6228342e4a791686192731bf2cbdef8dfab42aa2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1984.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c1109e0001102b55c5dc056f88c12d9e9952a4c6", + "authors": [ + { + "n": "moutard", + "e": "clement.moutard@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 5, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1988.json b/mne-python/source/doc/sphinxext/prs/1988.json new file mode 100644 index 0000000000000000000000000000000000000000..05c93714da115fc0b46d80aa09e1d7e400123c56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1988.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "97708188c440becd3e048ec3e0f70fd15cb9e83b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 11, + "d": 8 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 2 + }, + "mne/utils.py": { + "a": 8, + "d": 0 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 4, + "d": 1 + }, + "mne/viz/tests/test_misc.py": { + "a": 0, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1990.json b/mne-python/source/doc/sphinxext/prs/1990.json new file mode 100644 index 0000000000000000000000000000000000000000..98d16bbecd18f8d9d08b913d7e2d3fdacc47a02b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1990.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d353056eceb24cd448f98f86695de5589772911c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/plot_topo_compare_conditions.py": { + "a": 7, + "d": 4 + }, + "mne/epochs.py": { + "a": 30, + "d": 8 + }, + "mne/tests/test_epochs.py": { + "a": 19, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1992.json b/mne-python/source/doc/sphinxext/prs/1992.json new file mode 100644 index 0000000000000000000000000000000000000000..2c4fbd822a3a438db3fcfc1920624bd1bc447a3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1992.json @@ -0,0 +1,123 @@ +{ + "merge_commit_sha": "8a69ca9240e97245c5c19692ccc6f04a4271b85e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 9, + "d": 10 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 5, + "d": 5 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 7 + }, + "mne/io/open.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 4, + "d": 4 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 6, + "d": 6 + }, + "mne/source_space.py": { + "a": 4, + "d": 4 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1993.json b/mne-python/source/doc/sphinxext/prs/1993.json new file mode 100644 index 0000000000000000000000000000000000000000..1b8bb3d5f3db5fa6f105e118a5d5bd4301332424 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1993.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e3144574326c16ec5ba786a81be6c68db5daa912", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/mne_report_tutorial.rst": { + "a": 10, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_report.py": { + "a": 21, + "d": 2 + }, + "mne/report.py": { + "a": 86, + "d": 15 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1994.json b/mne-python/source/doc/sphinxext/prs/1994.json new file mode 100644 index 0000000000000000000000000000000000000000..4777254b0d2a4fc267655ca8718af9cb4804d4c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1994.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5bb39fa8bb6bda7e27ce899813337254bc184628", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 2 + }, + "mne/report.py": { + "a": 50, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1997.json b/mne-python/source/doc/sphinxext/prs/1997.json new file mode 100644 index 0000000000000000000000000000000000000000..05a8ecc8f91146e4a9923c6aad3147b34f98cc01 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1997.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "8b0300df14b4115c70c91a53291afae408b2594b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 1 + }, + "mne/bem.py": { + "a": 13, + "d": 6 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 11, + "d": 5 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 7, + "d": 4 + }, + "mne/io/tests/test_pick.py": { + "a": 8, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/1998.json b/mne-python/source/doc/sphinxext/prs/1998.json new file mode 100644 index 0000000000000000000000000000000000000000..bca374160a3c51b7648537c2eb0b347cdb7bcf58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/1998.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ef381aaa52d7ec985bdb544c3625b2ff31022d02", + "authors": [ + { + "n": "Yousra Bekhti", + "e": "yousra.bekhti@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2.json b/mne-python/source/doc/sphinxext/prs/2.json new file mode 100644 index 0000000000000000000000000000000000000000..c6d9cef1ee1692aa0ff8e0a0314b711e10df0672 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "1886878b372506c2168f2084c7c39bd03dfaaeb1", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "Makefile": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 53, + "d": 0 + }, + "mne/cov.py": { + "a": 73, + "d": 164 + }, + "mne/forward.py": { + "a": 58, + "d": 43 + }, + "mne/minimum_norm/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 93, + "d": 183 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 27, + "d": 28 + }, + "mne/stats/cluster_level.py": { + "a": 5, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/20.json b/mne-python/source/doc/sphinxext/prs/20.json new file mode 100644 index 0000000000000000000000000000000000000000..75e99d71ecbc531484ebec3aaec5ee08dc83f7af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/20.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "a76fcb1b4198fa89e16be9a33d93af0c0d958177", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/conf.py": { + "a": 1, + "d": 1 + }, + "doc/source/getting_started.rst": { + "a": 9, + "d": 2 + }, + "doc/source/mne-python.rst": { + "a": 2, + "d": 1 + }, + "doc/source/python_tutorial.rst": { + "a": 329, + "d": 0 + }, + "mne/cov.py": { + "a": 4, + "d": 4 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/fiff/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/evoked.py": { + "a": 5, + "d": 5 + }, + "mne/fiff/open.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/pick.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/proj.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/tree.py": { + "a": 3, + "d": 3 + }, + "mne/forward.py": { + "a": 7, + "d": 7 + }, + "mne/minimum_norm/inverse.py": { + "a": 14, + "d": 14 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 3 + }, + "mne/source_space.py": { + "a": 4, + "d": 4 + }, + "mne/surface.py": { + "a": 4, + "d": 4 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2001.json b/mne-python/source/doc/sphinxext/prs/2001.json new file mode 100644 index 0000000000000000000000000000000000000000..223367bcfe04ad4d2e7e3fe75c7103332dd5d17c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2001.json @@ -0,0 +1,167 @@ +{ + "merge_commit_sha": "dd87dbd9b6ee92fc839b6b0defa04c7fa7d28459", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_hdf5.py": { + "a": 11, + "d": 2 + }, + "mne/bem.py": { + "a": 5, + "d": 5 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 4, + "d": 1 + }, + "mne/coreg.py": { + "a": 4, + "d": 2 + }, + "mne/cov.py": { + "a": 5, + "d": 5 + }, + "mne/dipole.py": { + "a": 8, + "d": 5 + }, + "mne/filter.py": { + "a": 43, + "d": 36 + }, + "mne/fixes.py": { + "a": 39, + "d": 40 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 0 + }, + "mne/io/array/array.py": { + "a": 0, + "d": 1 + }, + "mne/io/base.py": { + "a": 5, + "d": 5 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/bads.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ctps_.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 34, + "d": 25 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 7, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 15, + "d": 9 + }, + "mne/stats/parametric.py": { + "a": 12, + "d": 11 + }, + "mne/stats/regression.py": { + "a": 2, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_import_nesting.py": { + "a": 45, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 8, + "d": 7 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 4 + }, + "mne/utils.py": { + "a": 5, + "d": 6 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2003.json b/mne-python/source/doc/sphinxext/prs/2003.json new file mode 100644 index 0000000000000000000000000000000000000000..1643c696af3e2a162b63261325741790c56cef97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2003.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "2986294d438096b7a097c33f710e86ecf37e1b2c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/circle.py": { + "a": 5, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 13, + "d": 10 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 14, + "d": 13 + }, + "mne/viz/misc.py": { + "a": 6, + "d": 6 + }, + "mne/viz/montage.py": { + "a": 6, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 14, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 21, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2005.json b/mne-python/source/doc/sphinxext/prs/2005.json new file mode 100644 index 0000000000000000000000000000000000000000..8807129542e8949ab1a2b2e7f3836252b69d36f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2005.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e5ff306445eb68a247ce13994ab8042c1dec261f", + "authors": [ + { + "n": "Yousra Bekhti", + "e": "yousra.bekhti@gmail.com" + } + ], + "changes": { + "examples/plot_meg_eeg_fields_3d.py": { + "a": 11, + "d": 2 + }, + "mne/forward/_field_interpolation.py": { + "a": 10, + "d": 2 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2006.json b/mne-python/source/doc/sphinxext/prs/2006.json new file mode 100644 index 0000000000000000000000000000000000000000..1179f333d2a388de5f5a30fd2ed38b59fd7c9ffd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2006.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "854782b66b43bc2ed08a6a3a346859edcf51d0f5", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/channels/data/layouts/KIT-AD.lout": { + "a": 209, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2007.json b/mne-python/source/doc/sphinxext/prs/2007.json new file mode 100644 index 0000000000000000000000000000000000000000..8ace239f8c0e1a7b1c5593e8a4788356500fd7b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2007.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "614867cae51422ff93e9efce946973ed97a94510", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2008.json b/mne-python/source/doc/sphinxext/prs/2008.json new file mode 100644 index 0000000000000000000000000000000000000000..5e6c0dc74b9343b10666f9952cf708cc948c074e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2008.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "42027519e51a82f538fb25e743ce60343a23dfdf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/201.json b/mne-python/source/doc/sphinxext/prs/201.json new file mode 100644 index 0000000000000000000000000000000000000000..991f3eed7b40013312496d479dbab7b7fb726ef0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/201.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6b6688df63361b287fc58c331d8efb1c520aaaa1", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "doc/source/manual/analyze.rst": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2010.json b/mne-python/source/doc/sphinxext/prs/2010.json new file mode 100644 index 0000000000000000000000000000000000000000..72d1bd4319832160e606c5f4833486e99b4440f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2010.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bd4ccdea13ece088aa044093b8c864b3e2c9b72f", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2011.json b/mne-python/source/doc/sphinxext/prs/2011.json new file mode 100644 index 0000000000000000000000000000000000000000..2bfe9ab480882002acc7b91571ac3a31823f4f1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2011.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "ee041955ef298fd5846cd0145ef95319bb5da86a", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 2 + }, + "examples/plot_interpolate_bad_channels.py": { + "a": 21, + "d": 35 + }, + "mne/channels/channels.py": { + "a": 27, + "d": 3 + }, + "mne/channels/interpolation.py": { + "a": 59, + "d": 35 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 87, + "d": 50 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 8, + "d": 15 + }, + "mne/forward/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 55, + "d": 29 + }, + "mne/io/tests/test_apply_function.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_misc.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2013.json b/mne-python/source/doc/sphinxext/prs/2013.json new file mode 100644 index 0000000000000000000000000000000000000000..f5f8d5df113823e0d844dca4102acf65955547f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2013.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "04e89a7a68cb1e4b8903c7a6c5f2137ebc441db4", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/report.py": { + "a": 18, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2018.json b/mne-python/source/doc/sphinxext/prs/2018.json new file mode 100644 index 0000000000000000000000000000000000000000..e7a6b3d65227761311124b17340d96c24b20cd62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2018.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "46bf9a7366d52d1341347fb7bd8e63eb99a0a14a", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/report.py": { + "a": 16, + "d": 5 + }, + "mne/tests/test_report.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/202.json b/mne-python/source/doc/sphinxext/prs/202.json new file mode 100644 index 0000000000000000000000000000000000000000..1b1dfd281f280ccea55b7a626abc0adc69cebe2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/202.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "adb4759575dc14ba10114022ff6147d1ea2b79d2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 13, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/connectivity/README.txt": { + "a": 6, + "d": 0 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 80, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 133, + "d": 0 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 114, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/connectivity/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/connectivity/spectral.py": { + "a": 964, + "d": 0 + }, + "mne/connectivity/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 183, + "d": 0 + }, + "mne/connectivity/tests/test_utils.py": { + "a": 23, + "d": 0 + }, + "mne/connectivity/utils.py": { + "a": 45, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 53, + "d": 36 + }, + "mne/time_frequency/multitaper.py": { + "a": 47, + "d": 3 + }, + "mne/viz.py": { + "a": 45, + "d": 0 + }, + "setup.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2021.json b/mne-python/source/doc/sphinxext/prs/2021.json new file mode 100644 index 0000000000000000000000000000000000000000..cd740c3cc43b156a0087a07d2b4dc1a8416c16f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2021.json @@ -0,0 +1,211 @@ +{ + "merge_commit_sha": "bf5ee19168529488afc201afcea531077fd4882a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 25, + "d": 9 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 4, + "d": 7 + }, + "mne/beamformer/_dics.py": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 3, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 11, + "d": 5 + }, + "mne/decoding/classifier.py": { + "a": 8, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 0 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 6, + "d": 4 + }, + "mne/dipole.py": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 19, + "d": 8 + }, + "mne/evoked.py": { + "a": 5, + "d": 3 + }, + "mne/filter.py": { + "a": 2, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 4, + "d": 4 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 4 + }, + "mne/io/chpi.py": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 0 + }, + "mne/io/pick.py": { + "a": 2, + "d": 2 + }, + "mne/io/proj.py": { + "a": 2, + "d": 2 + }, + "mne/label.py": { + "a": 4, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/misc.py": { + "a": 7, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 13, + "d": 11 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/client.py": { + "a": 5, + "d": 0 + }, + "mne/realtime/epochs.py": { + "a": 16, + "d": 2 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 7, + "d": 1 + }, + "mne/realtime/mockclient.py": { + "a": 22, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 7, + "d": 3 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/parametric.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 53, + "d": 27 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 47, + "d": 3 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 7, + "d": 13 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 0 + }, + "mne/utils.py": { + "a": 12, + "d": 7 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 5, + "d": 5 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 5, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2023.json b/mne-python/source/doc/sphinxext/prs/2023.json new file mode 100644 index 0000000000000000000000000000000000000000..d2a529950407bb17e9f14e384d79d7954b489e70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2023.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5d65321e902382642edd4b381c9617e4ced269bf", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2028.json b/mne-python/source/doc/sphinxext/prs/2028.json new file mode 100644 index 0000000000000000000000000000000000000000..87b9aa7ea015538d62834739cc785c0305d637ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2028.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "678ae7b0583ce5cb78a4316d24d6c8618f1263dc", + "authors": [ + { + "n": "moutard", + "e": "clement.moutard@gmail.com" + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 4, + "d": 2 + }, + "mne/epochs.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2029.json b/mne-python/source/doc/sphinxext/prs/2029.json new file mode 100644 index 0000000000000000000000000000000000000000..ec648381b76ca543f1e4c41e38429ce01e819f5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2029.json @@ -0,0 +1,199 @@ +{ + "merge_commit_sha": "45cdcdaa3842b6adcb38595ae31240899e38ee2b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/contributing.rst": { + "a": 7, + "d": 7 + }, + "doc/source/python_reference.rst": { + "a": 6, + "d": 1 + }, + "doc/source/python_tutorial.rst": { + "a": 1, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 18, + "d": 12 + }, + "doc/sphinxext/gen_rst.py": { + "a": 4, + "d": 2 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_rap_music.py": { + "a": 12, + "d": 9 + }, + "mne/bem.py": { + "a": 4, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 35, + "d": 4 + }, + "mne/connectivity/effective.py": { + "a": 3, + "d": 4 + }, + "mne/connectivity/spectral.py": { + "a": 49, + "d": 47 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 8, + "d": 4 + }, + "mne/decoding/classifier.py": { + "a": 7, + "d": 6 + }, + "mne/decoding/csp.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/time_gen.py": { + "a": 33, + "d": 28 + }, + "mne/dipole.py": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 14, + "d": 11 + }, + "mne/event.py": { + "a": 8, + "d": 8 + }, + "mne/evoked.py": { + "a": 24, + "d": 8 + }, + "mne/filter.py": { + "a": 34, + "d": 23 + }, + "mne/io/base.py": { + "a": 24, + "d": 18 + }, + "mne/io/fiff/raw.py": { + "a": 4, + "d": 0 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 9, + "d": 0 + }, + "mne/io/reference.py": { + "a": 8, + "d": 4 + }, + "mne/io/tag.py": { + "a": 15, + "d": 2 + }, + "mne/io/tree.py": { + "a": 13, + "d": 5 + }, + "mne/label.py": { + "a": 15, + "d": 13 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 0 + }, + "mne/misc.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 32, + "d": 29 + }, + "mne/realtime/epochs.py": { + "a": 13, + "d": 12 + }, + "mne/report.py": { + "a": 9, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 34, + "d": 9 + }, + "mne/source_space.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 4, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 12, + "d": 0 + }, + "mne/transforms.py": { + "a": 30, + "d": 4 + }, + "mne/utils.py": { + "a": 22, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 8, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 12, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 14, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/203.json b/mne-python/source/doc/sphinxext/prs/203.json new file mode 100644 index 0000000000000000000000000000000000000000..9912b4f29adb9568e9351575c18541fa6f306527 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/203.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f5909c52185dbf311daa1238a9b6564a6083db42", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 27, + "d": 47 + }, + "mne/event.py": { + "a": 5, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 80, + "d": 2 + }, + "mne/fiff/tests/test_raw.py": { + "a": 44, + "d": 0 + }, + "mne/proj.py": { + "a": 4, + "d": 7 + }, + "mne/tests/test_proj.py": { + "a": 26, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2030.json b/mne-python/source/doc/sphinxext/prs/2030.json new file mode 100644 index 0000000000000000000000000000000000000000..25a7ff01d1299825e42247b3570acf6b4b6d8314 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2030.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "04262d6a9873bace9259bd23eddb7504daf78f23", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "mne/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2031.json b/mne-python/source/doc/sphinxext/prs/2031.json new file mode 100644 index 0000000000000000000000000000000000000000..1d8c18bd706ac30dfebd5682bac7c711f964ddb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2031.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "62b97041e2daf1b9a170c79075519ebe9f9b8098", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2036.json b/mne-python/source/doc/sphinxext/prs/2036.json new file mode 100644 index 0000000000000000000000000000000000000000..cc100f8c485538f664ab6eee69afa5ae99b0eb75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2036.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fbf64dcfb0a70a83988eca13741b06fa4b2ac3e1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2037.json b/mne-python/source/doc/sphinxext/prs/2037.json new file mode 100644 index 0000000000000000000000000000000000000000..c4194e127b2f51c51435eb61280f6e37e3da0bb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2037.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fb2ec6ceb116576c22e35caf8a02da1608a52dc5", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/preprocessing/ecg.py": { + "a": 16, + "d": 8 + }, + "mne/preprocessing/eog.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2038.json b/mne-python/source/doc/sphinxext/prs/2038.json new file mode 100644 index 0000000000000000000000000000000000000000..dba96405a3a0bfb4961cbba1101cc31ca0cc34f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2038.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "82400e1a41c098cf4b33bcdaa701e110120d8790", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2039.json b/mne-python/source/doc/sphinxext/prs/2039.json new file mode 100644 index 0000000000000000000000000000000000000000..63827eca7c2317c01fd43edcab35a307ef727b6c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2039.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c7da1c5c691cfdcd7fdae25ed77b024c0013baae", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 18, + "d": 6 + }, + "mne/tests/test_report.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/204.json b/mne-python/source/doc/sphinxext/prs/204.json new file mode 100644 index 0000000000000000000000000000000000000000..0a9459bb3606ffca120da23e0885490ff0df1d95 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/204.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "c647bbba5d1f4d943d7645d3c36a88b1eb528834", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/python_tutorial.rst": { + "a": 11, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 189, + "d": 1 + }, + "mne/event.py": { + "a": 26, + "d": 25 + }, + "mne/fiff/constants.py": { + "a": 3, + "d": 1 + }, + "mne/fiff/tag.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/write.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 22, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2041.json b/mne-python/source/doc/sphinxext/prs/2041.json new file mode 100644 index 0000000000000000000000000000000000000000..14cd8cc36e25b8ddea8b6e43e2f662852eb50b26 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2041.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dca676e32ad455aa6033e2fcc6bed4ace39acf67", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/channels/data/montages/biosemi-64.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2045.json b/mne-python/source/doc/sphinxext/prs/2045.json new file mode 100644 index 0000000000000000000000000000000000000000..6b1d67671d08b35d5a7ac6b0dfc6e1095933752f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2045.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4592164ca9c68b519496e9bd9f2f2d2e86b3e7aa", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2046.json b/mne-python/source/doc/sphinxext/prs/2046.json new file mode 100644 index 0000000000000000000000000000000000000000..8baca43ea63093db2a433fb5e904873c08ecd367 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2046.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "14aeefd220944c77888ab2afc506800c819e0d9b", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2053.json b/mne-python/source/doc/sphinxext/prs/2053.json new file mode 100644 index 0000000000000000000000000000000000000000..118f3266fd28f1435730d50bcefbdb7bd8dfc5b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2053.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1f47a58f175e42dce98026d554ac2bad2776cef6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2054.json b/mne-python/source/doc/sphinxext/prs/2054.json new file mode 100644 index 0000000000000000000000000000000000000000..f651fe37aaf80391a1dc6f2549cb590c4e7b7c1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2054.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "638d45ffe124e294f9bfe1c37ec00ca65ec2c739", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 22, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 40, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2055.json b/mne-python/source/doc/sphinxext/prs/2055.json new file mode 100644 index 0000000000000000000000000000000000000000..5468a3f8e0c48361b0e7c8194bc89dcdfdd22163 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2055.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6f87fc0fb637f69fe5a7570fd814991ead5da648", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/206.json b/mne-python/source/doc/sphinxext/prs/206.json new file mode 100644 index 0000000000000000000000000000000000000000..b868d243e40bb0addf89b5528524129127d52f0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/206.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4f57c7f5193016c996a104eb2abb1831f0a5d692", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/__init__.py": { + "a": 4, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 21, + "d": 3 + }, + "mne/surface.py": { + "a": 52, + "d": 7 + }, + "mne/tests/test_source_space.py": { + "a": 13, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 16, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2061.json b/mne-python/source/doc/sphinxext/prs/2061.json new file mode 100644 index 0000000000000000000000000000000000000000..816995bdbd94e4d787fc4e6a3218d728835c08cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2061.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "bd981b94673e632bacb6624b121a8e15554de798", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 8, + "d": 0 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 4, + "d": 5 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 4, + "d": 5 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 1, + "d": 5 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 1, + "d": 3 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 2, + "d": 6 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 3 + }, + "mne/cov.py": { + "a": 7, + "d": 5 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2063.json b/mne-python/source/doc/sphinxext/prs/2063.json new file mode 100644 index 0000000000000000000000000000000000000000..16ff376d95ae674963f7ea1f0964f182384ab490 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2063.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "589a25cf812a9a3c60dd1bf01e8043b29356a368", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2064.json b/mne-python/source/doc/sphinxext/prs/2064.json new file mode 100644 index 0000000000000000000000000000000000000000..e05e71f22999803bbc05cf2cdeea23bdf4785680 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2064.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "9733bcfb6c9e4e90b36d8151f65797f7f267290b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/tests/test_layout.py": { + "a": 3, + "d": 2 + }, + "mne/cov.py": { + "a": 12, + "d": 17 + }, + "mne/defaults.py": { + "a": 49, + "d": 0 + }, + "mne/epochs.py": { + "a": 9, + "d": 8 + }, + "mne/evoked.py": { + "a": 4, + "d": 4 + }, + "mne/io/base.py": { + "a": 4, + "d": 3 + }, + "mne/io/chpi.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_defaults.py": { + "a": 22, + "d": 0 + }, + "mne/tests/test_import_nesting.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 7 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 7 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 6, + "d": 7 + }, + "mne/viz/topomap.py": { + "a": 8, + "d": 18 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 44 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/207.json b/mne-python/source/doc/sphinxext/prs/207.json new file mode 100644 index 0000000000000000000000000000000000000000..8ed6b3f6cb7ae30eb845156a47f32f2de19e48dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/207.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "65e9b588020c9a35fddf332a0e04fc2680037329", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 1, + "d": 2 + }, + "examples/plot_topo_channel_epochs_image.py": { + "a": 2, + "d": 3 + }, + "examples/plot_topography.py": { + "a": 1, + "d": 2 + }, + "examples/time_frequency/plot_tfr_topography.py": { + "a": 4, + "d": 6 + }, + "mne/viz.py": { + "a": 366, + "d": 249 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2070.json b/mne-python/source/doc/sphinxext/prs/2070.json new file mode 100644 index 0000000000000000000000000000000000000000..93992f934c6476ded8a705f9c6093c617788dbad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2070.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d9b47afbd2eb862910bcebdaa6025a8e3510158e", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/channels/data/montages/biosemi128.txt": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/biosemi16.txt": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/biosemi160.txt": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/biosemi256.txt": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/biosemi32.txt": { + "a": 0, + "d": 0 + }, + "mne/channels/data/montages/biosemi64.txt": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2072.json b/mne-python/source/doc/sphinxext/prs/2072.json new file mode 100644 index 0000000000000000000000000000000000000000..7ee030eba44b1ee0258b7d48cf65d48df292d4b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2072.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ec087192b2428cfc93e41c2163627cd04b85af5e", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 16, + "d": 4 + }, + "mne/decoding/time_gen.py": { + "a": 239, + "d": 134 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/decoding.py": { + "a": 114, + "d": 32 + }, + "mne/viz/tests/test_decoding.py": { + "a": 65, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2073.json b/mne-python/source/doc/sphinxext/prs/2073.json new file mode 100644 index 0000000000000000000000000000000000000000..fcf363004f419ebf388772cab7e20165c3ee944a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2073.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "ab9421d7b646294ae2e0ff61c0e45474265af60c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 21, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 3 + }, + "mne/fixes.py": { + "a": 108, + "d": 4 + }, + "mne/io/array/tests/test_array.py": { + "a": 5, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 1 + }, + "mne/report.py": { + "a": 16, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 6, + "d": 3 + }, + "mne/source_space.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_import_nesting.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 6, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 71, + "d": 11 + }, + "mne/viz/tests/test_circle.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 11, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2076.json b/mne-python/source/doc/sphinxext/prs/2076.json new file mode 100644 index 0000000000000000000000000000000000000000..236ced1aa5d2179dfd36b81e280748498eb5686b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2076.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "9e477f1b6bc5d3b8e219d56b8b594bd13694e384", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/sample/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sample/sample.py": { + "a": 10, + "d": 3 + }, + "mne/datasets/somato/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/somato/somato.py": { + "a": 11, + "d": 4 + }, + "mne/datasets/spm_face/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 10, + "d": 3 + }, + "mne/datasets/testing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/testing/_testing.py": { + "a": 10, + "d": 3 + }, + "mne/datasets/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 15, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 19, + "d": 3 + }, + "mne/io/base.py": { + "a": 1, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 5, + "d": 1 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2077.json b/mne-python/source/doc/sphinxext/prs/2077.json new file mode 100644 index 0000000000000000000000000000000000000000..0d7e569f4d3ea101bec2c5ab0347a629c9953639 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2077.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b3756c391c5ae43155757095c70be66d930146bb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 5, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2078.json b/mne-python/source/doc/sphinxext/prs/2078.json new file mode 100644 index 0000000000000000000000000000000000000000..4662c1e6d70c1b621479f77b6580e6dddf4370be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2078.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6421d043596d44894f18e07fb49f324399b55e1e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_label.py": { + "a": 1, + "d": 3 + }, + "mne/viz/tests/test_circle.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2079.json b/mne-python/source/doc/sphinxext/prs/2079.json new file mode 100644 index 0000000000000000000000000000000000000000..c0c8c649af05c6242ee8a1525f94ed96d67f79da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2079.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "58bd351c612fd8b7c9232378605c9aff45fa9618", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/proj.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 14, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/208.json b/mne-python/source/doc/sphinxext/prs/208.json new file mode 100644 index 0000000000000000000000000000000000000000..5a86dc654650b955d053352bc5ba3fb22831299b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/208.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6ee3af2a5ef9cc61e874cc98bdde8ac1ec05d4a6", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + ".gitignore": { + "a": 3, + "d": 0 + }, + "examples/export/README.txt": { + "a": 2, + "d": 2 + }, + "mne/datasets/sample/__init__.py": { + "a": 27, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2080.json b/mne-python/source/doc/sphinxext/prs/2080.json new file mode 100644 index 0000000000000000000000000000000000000000..d9d98ad829254098c16e3c43ab39149a189fbad6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2080.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "e7c770592bda0eadd526bdd172dcd3b4d212b5ba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 84, + "d": 16 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 0 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 171, + "d": 157 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 14, + "d": 10 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 4, + "d": 60 + }, + "mne/io/kit/kit.py": { + "a": 40, + "d": 61 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2081.json b/mne-python/source/doc/sphinxext/prs/2081.json new file mode 100644 index 0000000000000000000000000000000000000000..541934ad68b896eee2e55e6bb69649e8d21218a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2081.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a63b7517029e9336818a6b49a99e4e2398ed9b0b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/proj.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2085.json b/mne-python/source/doc/sphinxext/prs/2085.json new file mode 100644 index 0000000000000000000000000000000000000000..4d56c3adcdf76880b486674c70841ab314029487 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2085.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "315764d7f93f7065c8313869760c4516bcd1fb17", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 2, + "d": 4 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 2, + "d": 5 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 2, + "d": 4 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 3, + "d": 5 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 2, + "d": 3 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 2, + "d": 3 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 4, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 13, + "d": 12 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 45, + "d": 46 + }, + "mne/viz/tests/test_3d.py": { + "a": 34, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2090.json b/mne-python/source/doc/sphinxext/prs/2090.json new file mode 100644 index 0000000000000000000000000000000000000000..45e9c17753d71936c0a9b0f153af15da702d10a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2090.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f4a1267970723e2dd39b9384465a0f15c80963c6", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 40, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2091.json b/mne-python/source/doc/sphinxext/prs/2091.json new file mode 100644 index 0000000000000000000000000000000000000000..9dd89731911b4e0a1ee6672c99f6306b69fb5f01 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2091.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a5dd6823068edbb97a82ef69f750a830b1b9c58c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/fiff/tests/test_raw.py": { + "a": 13, + "d": 12 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 6, + "d": 3 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2092.json b/mne-python/source/doc/sphinxext/prs/2092.json new file mode 100644 index 0000000000000000000000000000000000000000..8eaaa77cfb274284d1d8691773da7c230291e0a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2092.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "e3b6f6e2ed8d814a02f9ccd9c6f040b4f274ce4d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 15, + "d": 27 + }, + "doc/sphinxext/gen_rst.py": { + "a": 14, + "d": 2 + }, + "examples/datasets/plot_megsim_data.py": { + "a": 2, + "d": 2 + }, + "examples/datasets/plot_megsim_data_single_trial.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 4, + "d": 2 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_label_activation_from_stc.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_morph_data.py": { + "a": 4, + "d": 2 + }, + "examples/plot_clickable_image.py": { + "a": 2, + "d": 3 + }, + "examples/plot_epochs_to_data_frame.py": { + "a": 1, + "d": 1 + }, + "examples/plot_make_forward.py": { + "a": 1, + "d": 1 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 4, + "d": 0 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_methods_tutorial.py": { + "a": 4, + "d": 0 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 3, + "d": 4 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_sensor_regression.py": { + "a": 4, + "d": 7 + }, + "examples/time_frequency/plot_stockwell.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_sensors.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 11, + "d": 4 + }, + "mne/datasets/megsim/megsim.py": { + "a": 11, + "d": 4 + }, + "mne/defaults.py": { + "a": 5, + "d": 1 + }, + "mne/evoked.py": { + "a": 4, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 2 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2094.json b/mne-python/source/doc/sphinxext/prs/2094.json new file mode 100644 index 0000000000000000000000000000000000000000..290d26b7a118d9085d893c16451ab16ee1ca36a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2094.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9e6d4625c08e64ff5b20fef1eceb4be31b360e6c", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 9, + "d": 10 + }, + "mne/viz/tests/test_3d.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2096.json b/mne-python/source/doc/sphinxext/prs/2096.json new file mode 100644 index 0000000000000000000000000000000000000000..2bf20d59804515d8fad4b2673ea2f977c2f669e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2096.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f9d457444743c03f9de3d8c9c6b1bf1df5930762", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 10, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2097.json b/mne-python/source/doc/sphinxext/prs/2097.json new file mode 100644 index 0000000000000000000000000000000000000000..1ac11f8b5966739cbbed9247571815ca1106b8c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2097.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c92ff4af7bfb5948ee4f4572ed154a5cc7da4214", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2098.json b/mne-python/source/doc/sphinxext/prs/2098.json new file mode 100644 index 0000000000000000000000000000000000000000..a846729de31f617b39619e5700d4e3b94a3e8018 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2098.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "463cd9be1a773cb1f253e9973bf8a860f6a7cbcc", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 10, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/21.json b/mne-python/source/doc/sphinxext/prs/21.json new file mode 100644 index 0000000000000000000000000000000000000000..3d4626b6003ffd759e013f7ee161d22b751ca0c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/21.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2d416e02f76540ebc421a2691860732b36b97965", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/pick.py": { + "a": 34, + "d": 1 + }, + "mne/forward.py": { + "a": 195, + "d": 1 + }, + "mne/tests/test_forward.py": { + "a": 77, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/210.json b/mne-python/source/doc/sphinxext/prs/210.json new file mode 100644 index 0000000000000000000000000000000000000000..75e40b019f22bfc69ecb673a9b5c8498e9443fd7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/210.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "afc38a4e4938d9b80e5fee741f1e6fe18fd99223", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "bin/mne_clean_eog_ecg.py": { + "a": 2, + "d": 2 + }, + "doc/source/python_reference.rst": { + "a": 5, + "d": 3 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_ecg_artifacts_from_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_eog_artifacts_from_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "mne/artifacts/__init__.py": { + "a": 8, + "d": 3 + }, + "mne/artifacts/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 6, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/eog.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/peak_finder.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ssp.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/stim.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_peak_finder.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 2, + "d": 0 + }, + "setup.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2100.json b/mne-python/source/doc/sphinxext/prs/2100.json new file mode 100644 index 0000000000000000000000000000000000000000..d253b53d1b86a217495ce62d679e05e35a4789a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2100.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "19f6d545bf279ee3016afac90d08e6e995c48790", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/contributing.rst": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2101.json b/mne-python/source/doc/sphinxext/prs/2101.json new file mode 100644 index 0000000000000000000000000000000000000000..eee481615e5fbbb709c33468cdbab0b7432714b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2101.json @@ -0,0 +1,195 @@ +{ + "merge_commit_sha": "6860170610654021fc6fbc1431a1215443b93f00", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/README.txt": { + "a": 3, + "d": 5 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/forward/README.txt": { + "a": 6, + "d": 0 + }, + "examples/forward/plot_bem_contour_mri.py": { + "a": 0, + "d": 0 + }, + "examples/forward/plot_coregistration_transform.py": { + "a": 0, + "d": 0 + }, + "examples/forward/plot_decimate_head_surface.py": { + "a": 0, + "d": 0 + }, + "examples/forward/plot_left_cerebellum_volume_source.py": { + "a": 0, + "d": 0 + }, + "examples/forward/plot_make_forward.py": { + "a": 0, + "d": 0 + }, + "examples/forward/plot_read_bem_surfaces.py": { + "a": 0, + "d": 0 + }, + "examples/forward/plot_read_forward.py": { + "a": 0, + "d": 0 + }, + "examples/io/README.txt": { + "a": 5, + "d": 0 + }, + "examples/io/plot_epochs_to_data_frame.py": { + "a": 0, + "d": 0 + }, + "examples/io/plot_objects_from_arrays.py": { + "a": 0, + "d": 0 + }, + "examples/io/plot_read_and_write_raw_data.py": { + "a": 0, + "d": 0 + }, + "examples/io/plot_read_epochs.py": { + "a": 0, + "d": 0 + }, + "examples/io/plot_read_evoked.py": { + "a": 0, + "d": 0 + }, + "examples/io/plot_read_noise_covariance_matrix.py": { + "a": 0, + "d": 0 + }, + "examples/io/read_events.py": { + "a": 0, + "d": 0 + }, + "examples/plot_compute_mne_inverse.py": { + "a": 0, + "d": 0 + }, + "examples/plot_extract_events_from_raw.py": { + "a": 1, + "d": 1 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 13, + "d": 16 + }, + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 0, + "d": 72 + }, + "examples/preprocessing/plot_define_target_events.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/plot_estimate_covariance_matrix_baseline.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/plot_estimate_covariance_matrix_raw.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/plot_interpolate_bad_channels.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/plot_shift_evoked.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/plot_virtual_evoked.py": { + "a": 0, + "d": 0 + }, + "examples/simulation/README.txt": { + "a": 5, + "d": 0 + }, + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/README.txt": { + "a": 5, + "d": 0 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_clickable_image.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_evoked_delayed_ssp.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_evoked_erf_erp.py": { + "a": 48, + "d": 0 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_evoked_topomap_delayed_ssp.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_meg_eeg_fields_3d.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_ssp_projs_sensitivity_map.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_ssp_projs_topomaps.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_topo_channel_epochs_image.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_topo_compare_conditions.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_topo_customized.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/plot_topography.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2102.json b/mne-python/source/doc/sphinxext/prs/2102.json new file mode 100644 index 0000000000000000000000000000000000000000..94e82d67b33a7b8995e8572481df958c6a7005b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2102.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fd29153900a5c7b1c4f230208df07aa2d3647a2f", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 17, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2103.json b/mne-python/source/doc/sphinxext/prs/2103.json new file mode 100644 index 0000000000000000000000000000000000000000..8d0e0c11f7addb4db9273c7468286d435e6b0de8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2103.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6397b15a2b978dbf5ad9e4946fb66987b03f74bc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/_static/navy.css": { + "a": 1, + "d": 1 + }, + "doc/source/_templates/layout.html": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2104.json b/mne-python/source/doc/sphinxext/prs/2104.json new file mode 100644 index 0000000000000000000000000000000000000000..2b23f0cbe0b19f21a3ab4c33a575901bdc06ae40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2104.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "a9d697358ccfff7d67e02df5889c203f7da0daa3", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/plot_corrmap_detection.py": { + "a": 76, + "d": 0 + }, + "mne/cov.py": { + "a": 13, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 321, + "d": 11 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 17, + "d": 4 + }, + "mne/tests/test_import_nesting.py": { + "a": 17, + "d": 12 + }, + "mne/tests/test_utils.py": { + "a": 23, + "d": 2 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2107.json b/mne-python/source/doc/sphinxext/prs/2107.json new file mode 100644 index 0000000000000000000000000000000000000000..fc228c3a2bafb323f56f49e95710f9f4d944a704 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2107.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7c17694fb3c71434a2db347e1c4aa51ae6894f8f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 2, + "d": 2 + }, + "doc/sphinxext/gen_rst.py": { + "a": 10, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2110.json b/mne-python/source/doc/sphinxext/prs/2110.json new file mode 100644 index 0000000000000000000000000000000000000000..378e213e0e8b31aba6999b8e3bb4bdbc91272e19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2110.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "99f878f8cb0cb53b1c6298966d70916ef3d9153a", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2114.json b/mne-python/source/doc/sphinxext/prs/2114.json new file mode 100644 index 0000000000000000000000000000000000000000..492befc6b49947a41c7fe87b2106f945d6782f58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2114.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "14f89ce12865319fc7ebe62d669d78797afb727a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 7, + "d": 2 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 24, + "d": 6 + }, + "mne/evoked.py": { + "a": 12, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 11, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 12, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 0, + "d": 1 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_decoding.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 4, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 98, + "d": 80 + }, + "mne/viz/topomap.py": { + "a": 90, + "d": 48 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2115.json b/mne-python/source/doc/sphinxext/prs/2115.json new file mode 100644 index 0000000000000000000000000000000000000000..9d6f4514a2cb9589a48af223b311eae3bc106e1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2115.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7b53ef6364ed3f945d92e2dd0bd9bd0d1f7174c9", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/data/coil_def_Elekta.dat": { + "a": 70, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 568, + "d": 0 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 138, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2118.json b/mne-python/source/doc/sphinxext/prs/2118.json new file mode 100644 index 0000000000000000000000000000000000000000..da1a99b85ba2c7d1a8ecc8bd48a1b9d4c3e2df7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2118.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "748ae8366a8551b1454d41420e363798316334a6", + "authors": [ + { + "n": "sviter", + "e": "sviter33@gmail.com" + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/212.json b/mne-python/source/doc/sphinxext/prs/212.json new file mode 100644 index 0000000000000000000000000000000000000000..43fd65bfa084bed16f1e2f7a5ef2360484b02eec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/212.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "12d998b274c81194ce484312aefa1b2300ef4d47", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/datasets/sample/__init__.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2120.json b/mne-python/source/doc/sphinxext/prs/2120.json new file mode 100644 index 0000000000000000000000000000000000000000..8dbe2f7dafc756a026b5b9f06b260177246a6501 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2120.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a218bf7037f65913fc93648b62c89bf22e73e595", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 20, + "d": 14 + }, + "mne/decoding/time_gen.py": { + "a": 129, + "d": 124 + }, + "mne/viz/decoding.py": { + "a": 9, + "d": 9 + }, + "mne/viz/tests/test_decoding.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2123.json b/mne-python/source/doc/sphinxext/prs/2123.json new file mode 100644 index 0000000000000000000000000000000000000000..abc40336f4e5abb96b88c3c34eaff53c02d1f189 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2123.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "312eed5fbe4ed1eb1c2096f9f0afa4bd4d400a33", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/kit/kit.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2126.json b/mne-python/source/doc/sphinxext/prs/2126.json new file mode 100644 index 0000000000000000000000000000000000000000..c588148168007bb788266b299bc0a6f9242d598d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2126.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "11a5bcf8bf14efe6de58606ee8b5002d833c550c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 14, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 0 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2127.json b/mne-python/source/doc/sphinxext/prs/2127.json new file mode 100644 index 0000000000000000000000000000000000000000..b10cb6f9b73acdb2d2b306c80a87ccbd3b2e1a1d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2127.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "a227123a49db0dc7225453d40151a7bd7f18948b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 145, + "d": 13 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 8 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 9, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 40, + "d": 69 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 22, + "d": 13 + }, + "mne/io/egi/egi.py": { + "a": 5, + "d": 12 + }, + "mne/io/fiff/raw.py": { + "a": 67, + "d": 155 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 18, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 65, + "d": 101 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 12, + "d": 2 + }, + "mne/io/tag.py": { + "a": 5, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 31, + "d": 0 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2128.json b/mne-python/source/doc/sphinxext/prs/2128.json new file mode 100644 index 0000000000000000000000000000000000000000..15aace96110d76a56db54bf4ace2e15ef1b50043 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2128.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7115364cbe9cdf5d558d42da86df3ff2ccb1440d", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2129.json b/mne-python/source/doc/sphinxext/prs/2129.json new file mode 100644 index 0000000000000000000000000000000000000000..73c200d653984c76947fbe640b08997beaaaca19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2129.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2e98506a5175d94fde6ae296921930cd07151e37", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 3, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2131.json b/mne-python/source/doc/sphinxext/prs/2131.json new file mode 100644 index 0000000000000000000000000000000000000000..1172a72c2ad579adeadcdc7c5dc53d9d2bc02706 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2131.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "375d59feb8ec50c43cbc2aaaa94233801dc1345f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 6, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2132.json b/mne-python/source/doc/sphinxext/prs/2132.json new file mode 100644 index 0000000000000000000000000000000000000000..b5dd8ee975eabfb397c5b7a53ba932b88a496a31 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2132.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c0062c9979c3632d021c853465e382fd70948e5b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/_images/plot_time_frequency.png": { + "a": 0, + "d": 0 + }, + "doc/source/python_tutorial.rst": { + "a": 12, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2133.json b/mne-python/source/doc/sphinxext/prs/2133.json new file mode 100644 index 0000000000000000000000000000000000000000..1e8303dd6fb7b9368ee058c7b9dd03107bbff6b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2133.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f9909e5c4df78f188071cefa9938d4bcc00eddde", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2134.json b/mne-python/source/doc/sphinxext/prs/2134.json new file mode 100644 index 0000000000000000000000000000000000000000..de0071b34f54172214eabbdbff2881693cab3b00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2134.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b17b1a69a84fef58a80f63bcfe5a9f8b24ac354c", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2135.json b/mne-python/source/doc/sphinxext/prs/2135.json new file mode 100644 index 0000000000000000000000000000000000000000..8c221a12e48882ff7c9b6fca4d787ce6c2a0fa1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2135.json @@ -0,0 +1,207 @@ +{ + "merge_commit_sha": "22ff36bb645dc9e5bb1b57d2e2dac0b808906bb4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 3, + "d": 4 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 27 + }, + "mne/decoding/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 0, + "d": 24 + }, + "mne/decoding/time_gen.py": { + "a": 1, + "d": 102 + }, + "mne/defaults.py": { + "a": 1, + "d": 0 + }, + "mne/dipole.py": { + "a": 1, + "d": 31 + }, + "mne/epochs.py": { + "a": 5, + "d": 161 + }, + "mne/evoked.py": { + "a": 3, + "d": 127 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 7 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 8 + }, + "mne/forward/forward.py": { + "a": 5, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 136 + }, + "mne/io/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 8, + "d": 26 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 10 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 2, + "d": 36 + }, + "mne/io/pick.py": { + "a": 1, + "d": 65 + }, + "mne/io/reference.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_pick.py": { + "a": 8, + "d": 6 + }, + "mne/label.py": { + "a": 2, + "d": 41 + }, + "mne/layouts/__init__.py": { + "a": 0, + "d": 21 + }, + "mne/minimum_norm/inverse.py": { + "a": 12, + "d": 28 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 7, + "d": 8 + }, + "mne/preprocessing/stim.py": { + "a": 0, + "d": 64 + }, + "mne/report.py": { + "a": 2, + "d": 22 + }, + "mne/source_estimate.py": { + "a": 9, + "d": 85 + }, + "mne/source_space.py": { + "a": 2, + "d": 7 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 7 + }, + "mne/surface.py": { + "a": 2, + "d": 8 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 14 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 37 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 32 + }, + "mne/tests/test_evoked.py": { + "a": 3, + "d": 23 + }, + "mne/tests/test_report.py": { + "a": 0, + "d": 7 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 36 + }, + "mne/time_frequency/stft.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 28 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 26 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 9 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 8 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 17 + }, + "setup.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/214.json b/mne-python/source/doc/sphinxext/prs/214.json new file mode 100644 index 0000000000000000000000000000000000000000..17389ca2c0bb89e1fc4d9c479afc2b34dcbeb878 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/214.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4c03a6ca692c4273d856cac772f167bbb1592344", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/evoked.py": { + "a": 14, + "d": 4 + }, + "mne/viz.py": { + "a": 22, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2144.json b/mne-python/source/doc/sphinxext/prs/2144.json new file mode 100644 index 0000000000000000000000000000000000000000..782dcb616790d8fe2f36636706f329f3e17a24c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2144.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "afad3b1aa7c185523d1fe722d46b5d3dfee9e9e2", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2146.json b/mne-python/source/doc/sphinxext/prs/2146.json new file mode 100644 index 0000000000000000000000000000000000000000..18e7f02d99e128a938bc66d8120ddf7357ef3fd7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2146.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d58b86edf4161db159c289322ac1d0953a68a67b", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 11, + "d": 11 + }, + "mne/viz/ica.py": { + "a": 18, + "d": 10 + }, + "mne/viz/tests/test_ica.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2148.json b/mne-python/source/doc/sphinxext/prs/2148.json new file mode 100644 index 0000000000000000000000000000000000000000..82cd909f556df0c72b98e2d0ac061d5b893469a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2148.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "36c0b2adfec80ea285b34e9cc0056ed496f484e9", + "authors": [ + { + "n": "jmontoyam", + "e": "montoya.jair.m@gmail.com" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 5, + "d": 0 + }, + "mne/io/tests/test_pick.py": { + "a": 41, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2150.json b/mne-python/source/doc/sphinxext/prs/2150.json new file mode 100644 index 0000000000000000000000000000000000000000..504bb79cb6880e4f527c3234843291cdcb0ed829 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2150.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b671789739123bd552480242e9c027596c5a0661", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2152.json b/mne-python/source/doc/sphinxext/prs/2152.json new file mode 100644 index 0000000000000000000000000000000000000000..5f5aea3df8b278933e044e232b83d9a159006397 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2152.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d702effbc1715cda8de1143eac38dd67b0556740", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_kit2fiff_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2153.json b/mne-python/source/doc/sphinxext/prs/2153.json new file mode 100644 index 0000000000000000000000000000000000000000..a9b50fadd244f9b3286aa8ea4bcee322a2ce2f7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2153.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "60dfdb3ee782a24db58756e5ea9c532af76b7b9a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 5, + "d": 5 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 6, + "d": 6 + }, + "mne/stats/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/stats/parametric.py": { + "a": 107, + "d": 38 + }, + "mne/stats/tests/test_parametric.py": { + "a": 63, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2154.json b/mne-python/source/doc/sphinxext/prs/2154.json new file mode 100644 index 0000000000000000000000000000000000000000..441be69f0611a88b1ed714069c2b6f660a273e47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2154.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "37670b52f22b1929efb8f3e247c3ab59b0380ea4", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 4, + "d": 3 + }, + "mne/epochs.py": { + "a": 43, + "d": 7 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 600, + "d": 16 + }, + "mne/viz/raw.py": { + "a": 7, + "d": 51 + }, + "mne/viz/tests/test_epochs.py": { + "a": 49, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 51, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2156.json b/mne-python/source/doc/sphinxext/prs/2156.json new file mode 100644 index 0000000000000000000000000000000000000000..068b794debbe7f202df2b662d8a03895ffc0eef6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2156.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "de7914af588f7442f8155fa5d90965ac2c327fb6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2159.json b/mne-python/source/doc/sphinxext/prs/2159.json new file mode 100644 index 0000000000000000000000000000000000000000..c3bc32aa6cc64d47db8c7cc9c392b31eb96cea8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2159.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f03d958900a7d84828a32b80d08720ec43326224", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 48, + "d": 13 + }, + "mne/viz/tests/test_ica.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/216.json b/mne-python/source/doc/sphinxext/prs/216.json new file mode 100644 index 0000000000000000000000000000000000000000..2ec2a90c3408ed113dee60ca8496dc2cd8b3ff7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/216.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1cdaa936b247c710622d72fe1da496e1795d40cf", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/utils.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2164.json b/mne-python/source/doc/sphinxext/prs/2164.json new file mode 100644 index 0000000000000000000000000000000000000000..8a8dbd3ae0793dd34b5c7d1a0d25db033d36feee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2164.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "948fc07b92f88f01c169211066bca2c2300fb654", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/decoding/time_gen.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2166.json b/mne-python/source/doc/sphinxext/prs/2166.json new file mode 100644 index 0000000000000000000000000000000000000000..c9a2020da6ac085712373b058ad7629161e23b9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2166.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "51c916fd676c5c5bae4ed86fa6f8fdb7357c8968", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 18, + "d": 16 + }, + "mne/viz/raw.py": { + "a": 7, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 16, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2167.json b/mne-python/source/doc/sphinxext/prs/2167.json new file mode 100644 index 0000000000000000000000000000000000000000..e0fe02835b0c3bc6bc83d3c02125f50be3e7efa0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2167.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "114759c61ec12634a5b0259a69ac42b73ed63e0a", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "mne/forward/_compute_forward.py": { + "a": 406, + "d": 121 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2168.json b/mne-python/source/doc/sphinxext/prs/2168.json new file mode 100644 index 0000000000000000000000000000000000000000..2eda6eab4166e829eb0043d6eaaa844a79a44313 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2168.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "ce95d7388d3fc0c739c510dcedcc736eb67af692", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/forward/plot_make_forward.py": { + "a": 2, + "d": 3 + }, + "examples/forward/plot_read_forward.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mne_crosstalk_function.py": { + "a": 4, + "d": 7 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 4, + "d": 7 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 3, + "d": 3 + }, + "examples/plot_compute_mne_inverse.py": { + "a": 1, + "d": 2 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 2 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 26, + "d": 20 + }, + "mne/viz/tests/test_3d.py": { + "a": 45, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2169.json b/mne-python/source/doc/sphinxext/prs/2169.json new file mode 100644 index 0000000000000000000000000000000000000000..35feae5a39d9353d134f0e1f0d5e287f0cceec24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2169.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7adc444632a1a722c2379fb4001fb0c5002d2f64", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 4, + "d": 6 + }, + "mne/tests/test_label.py": { + "a": 32, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2171.json b/mne-python/source/doc/sphinxext/prs/2171.json new file mode 100644 index 0000000000000000000000000000000000000000..daeaf61df0c29f119c80ee5e8e5a68009f694d83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2171.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cb95a101a066686e58716d1a4b3fd3ab65e5aa5e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/dipole.py": { + "a": 21, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2173.json b/mne-python/source/doc/sphinxext/prs/2173.json new file mode 100644 index 0000000000000000000000000000000000000000..4d28b718774095213e98eea7417ada6883bc2f3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2173.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "581bf92ca33aa159cd5a5e509e8f4ccda986f979", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 4, + "d": 1 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/_fake/__init__.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/_fake/_fake.py": { + "a": 25, + "d": 0 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 6, + "d": 52 + }, + "mne/datasets/megsim/megsim.py": { + "a": 5, + "d": 51 + }, + "mne/datasets/megsim/urls.py": { + "a": 20, + "d": 9 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 28, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 105, + "d": 80 + }, + "mne/io/tests/test_chpi.py": { + "a": 28, + "d": 2 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_cov.py": { + "a": 12, + "d": 4 + }, + "mne/tests/test_fixes.py": { + "a": 30, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 27, + "d": 3 + }, + "mne/tests/test_source_estimate.py": { + "a": 41, + "d": 7 + }, + "mne/tests/test_source_space.py": { + "a": 19, + "d": 9 + }, + "mne/viz/tests/test_topo.py": { + "a": 22, + "d": 7 + }, + "mne/viz/tests/test_utils.py": { + "a": 18, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 4 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2179.json b/mne-python/source/doc/sphinxext/prs/2179.json new file mode 100644 index 0000000000000000000000000000000000000000..051c420055bb5a236a527ff297551a8fa224ad0f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2179.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a57c5de97f49e26fb923ea3219ec4ebde37bd104", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2181.json b/mne-python/source/doc/sphinxext/prs/2181.json new file mode 100644 index 0000000000000000000000000000000000000000..275d623d8b3928930bb62696bbfa0721c6aed38c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2181.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "735bdac076a8959db942824964462889a9458a47", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2182.json b/mne-python/source/doc/sphinxext/prs/2182.json new file mode 100644 index 0000000000000000000000000000000000000000..0277f7ab0275b4832048912e373e65a2c6d7c186 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2182.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e3b5485591621f3d3c93f5a1a393ac90723f9e1c", + "authors": [ + { + "n": "alexandre barachant", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 7, + "d": 6 + }, + "mne/io/edf/tests/data/test_edf_stim_channel.edf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test_edf_stim_channel.txt": { + "a": 717, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 30, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2184.json b/mne-python/source/doc/sphinxext/prs/2184.json new file mode 100644 index 0000000000000000000000000000000000000000..44cca04135bddc92ce6f19af63bf6d6db2fc9665 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2184.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "1c83be5fca87c60b8d45690ad185c1dffa9af47d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 10, + "d": 3 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 4, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 0 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2193.json b/mne-python/source/doc/sphinxext/prs/2193.json new file mode 100644 index 0000000000000000000000000000000000000000..d64ce6909ec17e8df50eabfe556dfd0006f937fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2193.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "77a5801f45d9e6ed059a37aace5387faefb530ce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 4, + "d": 1 + }, + "doc/source/python_tutorial.rst": { + "a": 2, + "d": 2 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/__init__.py": { + "a": 5, + "d": 5 + }, + "mne/bem.py": { + "a": 872, + "d": 6 + }, + "mne/coreg.py": { + "a": 3, + "d": 3 + }, + "mne/dipole.py": { + "a": 3, + "d": 3 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 1 + }, + "mne/source_space.py": { + "a": 2, + "d": 1 + }, + "mne/surface.py": { + "a": 8, + "d": 301 + }, + "mne/tests/test_bem.py": { + "a": 155, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2194.json b/mne-python/source/doc/sphinxext/prs/2194.json new file mode 100644 index 0000000000000000000000000000000000000000..46329bc2a302fcbc2a9b4765ca8f4e30fd0e55b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2194.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "0dc2ad484fe8d75fe5acbfbbd36f37123c4f6fab", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "Makefile": { + "a": 4, + "d": 2 + }, + "appveyor.yml": { + "a": 1, + "d": 1 + }, + "doc/source/python_reference.rst": { + "a": 8, + "d": 0 + }, + "mne/bem.py": { + "a": 119, + "d": 1 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 62, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 27, + "d": 2 + }, + "mne/utils.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2196.json b/mne-python/source/doc/sphinxext/prs/2196.json new file mode 100644 index 0000000000000000000000000000000000000000..b6b894765cfd6df16cd3e61c5ce91a36f9afc7ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2196.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "411a2e36e92bda5c3690f5802f7ed4575793d751", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/dipole.py": { + "a": 57, + "d": 17 + }, + "mne/tests/test_dipole.py": { + "a": 68, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2199.json b/mne-python/source/doc/sphinxext/prs/2199.json new file mode 100644 index 0000000000000000000000000000000000000000..9c50d92802d952bdc2cd901225d3e883f55daa80 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2199.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2b21479a3427ee2a2e05691969506e3271e766d5", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/tests/test_cov.py": { + "a": 15, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/22.json b/mne-python/source/doc/sphinxext/prs/22.json new file mode 100644 index 0000000000000000000000000000000000000000..4056c8b77f14b0ca50a4d233666458d5b7adf6eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/22.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dfd726a2a47ba83e281a65181dcb546e124c5ece", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 28, + "d": 26 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/220.json b/mne-python/source/doc/sphinxext/prs/220.json new file mode 100644 index 0000000000000000000000000000000000000000..00e51eaaf8c73d39815ee0f73f42eda58970cff5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/220.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1948d586dd9d108124a4b5bf18e8576af35e4dfe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 15, + "d": 28 + }, + "mne/tests/test_source_space.py": { + "a": 18, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2206.json b/mne-python/source/doc/sphinxext/prs/2206.json new file mode 100644 index 0000000000000000000000000000000000000000..02b0a20c60b6db30326df6fd685fa97e33a0994d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2206.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "8e9ca7cc106d34282392c726816030a482848400", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 2 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 10, + "d": 8 + }, + "mne/viz/epochs.py": { + "a": 294, + "d": 61 + }, + "mne/viz/tests/test_epochs.py": { + "a": 4, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2208.json b/mne-python/source/doc/sphinxext/prs/2208.json new file mode 100644 index 0000000000000000000000000000000000000000..0848588c0bef43388353792dbe09b35c252525cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2208.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e5ae39081645843336abf0ee308f75d17d1a53b8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/fiff/tests/test_raw.py": { + "a": 8, + "d": 2 + }, + "mne/source_space.py": { + "a": 9, + "d": 8 + }, + "mne/utils.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2209.json b/mne-python/source/doc/sphinxext/prs/2209.json new file mode 100644 index 0000000000000000000000000000000000000000..df9b7fd015697e983d226e34320bc924b90178e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2209.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "71cfe38ca884273ba61f4b70467c9f1057b5e6be", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 3 + }, + "mne/io/base.py": { + "a": 6, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 10, + "d": 5 + }, + "mne/viz/raw.py": { + "a": 74, + "d": 21 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/221.json b/mne-python/source/doc/sphinxext/prs/221.json new file mode 100644 index 0000000000000000000000000000000000000000..4693abd6634ff3b2ee8dde3ff05c915908a8727a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/221.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2a4bde822752d7e023339949cac44c274cfb2b14", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 19, + "d": 4 + }, + "mne/viz.py": { + "a": 26, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2211.json b/mne-python/source/doc/sphinxext/prs/2211.json new file mode 100644 index 0000000000000000000000000000000000000000..7eb8ed39a69b5ef9719cc1c4c2376ecc904d5469 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2211.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "632bb07ab246beff57c3e56d5322225524287cd1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_tf_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 5, + "d": 5 + }, + "mne/channels/tests/test_layout.py": { + "a": 4, + "d": 4 + }, + "mne/epochs.py": { + "a": 709, + "d": 682 + }, + "mne/evoked.py": { + "a": 13, + "d": 13 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 6, + "d": 1 + }, + "mne/io/base.py": { + "a": 10, + "d": 6 + }, + "mne/io/kit/kit.py": { + "a": 7, + "d": 8 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 0 + }, + "mne/io/pick.py": { + "a": 4, + "d": 0 + }, + "mne/io/proj.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/epochs.py": { + "a": 3, + "d": 7 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 6, + "d": 9 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 9, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 205, + "d": 15 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2214.json b/mne-python/source/doc/sphinxext/prs/2214.json new file mode 100644 index 0000000000000000000000000000000000000000..0848f4c25269d717a0c1294822ca11d82105cc78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2214.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bce71d0e2b90cc7ec8ab2cbecbc29c69100807d8", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 237, + "d": 24 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 16, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2215.json b/mne-python/source/doc/sphinxext/prs/2215.json new file mode 100644 index 0000000000000000000000000000000000000000..d177c39acbacce48c6c9b760742b08ec1b33d421 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2215.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3a6d15f2fcef509d800b7e4accb6b40a40e20d4d", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "mne/gui/_file_traits.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/222.json b/mne-python/source/doc/sphinxext/prs/222.json new file mode 100644 index 0000000000000000000000000000000000000000..ec6dc9ca6e79e1f1881c6549fe7ca726dec81f75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/222.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3247e9481fafd6ae835a590ab108bfbbdeb432b5", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2221.json b/mne-python/source/doc/sphinxext/prs/2221.json new file mode 100644 index 0000000000000000000000000000000000000000..fdb970014f2c28b5de9f7ce6002b5b1f020ce6b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2221.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8e080b2b0aa185ff54176688be68d3c515cbfd08", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/reference.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2222.json b/mne-python/source/doc/sphinxext/prs/2222.json new file mode 100644 index 0000000000000000000000000000000000000000..903894d9644c42de0365ce03cdccff2113d2cd75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2222.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cc54b626f74ab4574cb6b17eed788d132330df60", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 16, + "d": 18 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2228.json b/mne-python/source/doc/sphinxext/prs/2228.json new file mode 100644 index 0000000000000000000000000000000000000000..7a5b7c8cd7f4d1849fcf82a8bb7dcf4bf59d4e35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2228.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "eed10bdf499aee6abc88f92b806bc81b0cd83615", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/stats/multi_comp.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_multi_comp.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2229.json b/mne-python/source/doc/sphinxext/prs/2229.json new file mode 100644 index 0000000000000000000000000000000000000000..2838e590dd05f06a810524af1bdb6108f58db819 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2229.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "af858a3a4f9f94a8e462a9c7b626fdd91fe20c7a", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/io/pick.py": { + "a": 22, + "d": 12 + }, + "mne/minimum_norm/inverse.py": { + "a": 8, + "d": 3 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 3, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 66, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2231.json b/mne-python/source/doc/sphinxext/prs/2231.json new file mode 100644 index 0000000000000000000000000000000000000000..e0908ffce3aec2703f81b92e60d58cb19fb6e3c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2231.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0529b2ec7fbc3a561d57e7ca29401d77f2b9c948", + "authors": [ + { + "n": "dgwakeman", + "e": "dgwakeman@users.noreply.github.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2232.json b/mne-python/source/doc/sphinxext/prs/2232.json new file mode 100644 index 0000000000000000000000000000000000000000..1b585cfafb37840799b1a118a6bd953691903b32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2232.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bc57aeaa36ba002499a5de623e187e9a74c8d035", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "mne/io/fiff/raw.py": { + "a": 15, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2233.json b/mne-python/source/doc/sphinxext/prs/2233.json new file mode 100644 index 0000000000000000000000000000000000000000..2f6699b92856a96646b7f1e31e8f48e93f6cf658 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2233.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "09e9eb80cee45a920d47593d1ff9adcf0c8f7529", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2234.json b/mne-python/source/doc/sphinxext/prs/2234.json new file mode 100644 index 0000000000000000000000000000000000000000..7dfd672a58cb3ec9cea88026da3aec840d255e63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2234.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7e8845d2de02fbd07460a41e4016d7444f3c7c30", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/visualization/make_report.py": { + "a": 37, + "d": 0 + }, + "mne/report.py": { + "a": 142, + "d": 28 + }, + "mne/tests/test_report.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2238.json b/mne-python/source/doc/sphinxext/prs/2238.json new file mode 100644 index 0000000000000000000000000000000000000000..dac95a965ea1a511bc1ebd898a6d7a1dc58c9082 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2238.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "90a8c6e841d14fff45faff5c2e4da8ccb5dd5d5f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cuda.py": { + "a": 6, + "d": 2 + }, + "mne/filter.py": { + "a": 40, + "d": 45 + }, + "mne/tests/test_filter.py": { + "a": 19, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2239.json b/mne-python/source/doc/sphinxext/prs/2239.json new file mode 100644 index 0000000000000000000000000000000000000000..f5936a3865bf03bfa931f98a3f4ecf53345b521b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2239.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "89d70b27a56e13a7a36b167aab129f4695cfd0b2", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/gui/__init__.py": { + "a": 11, + "d": 5 + }, + "mne/gui/_coreg_gui.py": { + "a": 7, + "d": 7 + }, + "mne/gui/_file_traits.py": { + "a": 24, + "d": 23 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 12, + "d": 12 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2241.json b/mne-python/source/doc/sphinxext/prs/2241.json new file mode 100644 index 0000000000000000000000000000000000000000..bf19dc07cf8b9b333aa8a40bfca0ec4c65e68296 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2241.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "fd9a8a72b577aaf4202ec579f2bbcb3b1255e261", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 9, + "d": 1 + }, + "examples/visualization/plot_clickable_image.py": { + "a": 2, + "d": 1 + }, + "examples/visualization/plot_evoked_topomap_delayed_ssp.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_topo_compare_conditions.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 69, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 1 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 71, + "d": 0 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 74, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2244.json b/mne-python/source/doc/sphinxext/prs/2244.json new file mode 100644 index 0000000000000000000000000000000000000000..9eccc40f2c5f39e60a7161dfb23657ece512c0f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2244.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "164d92dde41658435d30a7cadf026c91a8e94799", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2247.json b/mne-python/source/doc/sphinxext/prs/2247.json new file mode 100644 index 0000000000000000000000000000000000000000..d5ea351c3d109d8cf6b012955dac9438108bbd2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2247.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f51168f03681380089cdf14fda87d3b517c3444d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 2, + "d": 8 + }, + "doc/source/mne_report_tutorial.rst": { + "a": 1, + "d": 1 + }, + "doc/source/python_tutorial.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2249.json b/mne-python/source/doc/sphinxext/prs/2249.json new file mode 100644 index 0000000000000000000000000000000000000000..615ea95d6c4618963bc53ece1f4f42c9084d33dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2249.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "48dbc81c8f404c139a99ffd6d518b5238f179502", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 21, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/225.json b/mne-python/source/doc/sphinxext/prs/225.json new file mode 100644 index 0000000000000000000000000000000000000000..f382f807504301bd804495995569c0bd52bbd148 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/225.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "af52f1bb7dc6811c73f7b3f952c328d447f0bdbc", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/epochs.py": { + "a": 22, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2250.json b/mne-python/source/doc/sphinxext/prs/2250.json new file mode 100644 index 0000000000000000000000000000000000000000..8df697ae1ca6aef0f763d24daccdf27ab9daf14a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2250.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "46e254e6914ea6bbc4833fc6c9c9b7db4ed916cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "appveyor.yml": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 0 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2251.json b/mne-python/source/doc/sphinxext/prs/2251.json new file mode 100644 index 0000000000000000000000000000000000000000..6055310cd4cff5b8a5c6c98a228ac6e138d11ddc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2251.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "a2472257051de3b69115e0f4526e038021cc4afe", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 19, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 250, + "d": 298 + }, + "mne/viz/ica.py": { + "a": 234, + "d": 24 + }, + "mne/viz/raw.py": { + "a": 204, + "d": 331 + }, + "mne/viz/tests/test_epochs.py": { + "a": 5, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 53, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 297, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2252.json b/mne-python/source/doc/sphinxext/prs/2252.json new file mode 100644 index 0000000000000000000000000000000000000000..850197ac64e4bb1f7dbab59f02f1a321b0caaed8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2252.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "138afe102c1410b512b6d6322237b9cec5101e84", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainak.jas@telecom-paristech.fr" + } + ], + "changes": { + "mne/report.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2261.json b/mne-python/source/doc/sphinxext/prs/2261.json new file mode 100644 index 0000000000000000000000000000000000000000..3628c9f7889e19e271f081aef696fa4598aa1aee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2261.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c1bcd9a01ed38a3580546ea33550f12a9f49616a", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2262.json b/mne-python/source/doc/sphinxext/prs/2262.json new file mode 100644 index 0000000000000000000000000000000000000000..0d1eb7509809cce1ea21d9aa0d80f8c373f76d0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2262.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d541a3e2e9c3657bdd98c528ef1a67bd96669cbe", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2263.json b/mne-python/source/doc/sphinxext/prs/2263.json new file mode 100644 index 0000000000000000000000000000000000000000..9f5be1e4010f999e8db5cfb96fa637c543aa35d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2263.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "24918d788f982d4798bcf3fefea45ae3f1757662", + "authors": [ + { + "n": "unknown", + "e": "rkmaddox@uw.edu" + } + ], + "changes": { + "mne/filter.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2265.json b/mne-python/source/doc/sphinxext/prs/2265.json new file mode 100644 index 0000000000000000000000000000000000000000..2a577c22167f606f01438587f9dbc75b5c26c8bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2265.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8ed69d9cf13c5d3141217337ea4832f28c948209", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 63, + "d": 40 + }, + "mne/tests/test_filter.py": { + "a": 55, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2266.json b/mne-python/source/doc/sphinxext/prs/2266.json new file mode 100644 index 0000000000000000000000000000000000000000..a68ce1c73f6ce2d05fbcd8cad84e96b7bd80f460 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2266.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e43d4d4edb3c055b95ad620a28874d8ab22f9d45", + "authors": [ + { + "n": "aestrivex", + "e": "aestrivex@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 7, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2269.json b/mne-python/source/doc/sphinxext/prs/2269.json new file mode 100644 index 0000000000000000000000000000000000000000..1c3eab72c72808ca996248c523e186696509eb20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2269.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bd0d47a28974694b0e7ac8775c226b0802208b69", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/channels/data/neighbors/KIT-157_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/KIT-208_neighb.mat": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2271.json b/mne-python/source/doc/sphinxext/prs/2271.json new file mode 100644 index 0000000000000000000000000000000000000000..8b43b45dd5d45e741c58cf775bab118d1499f19c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2271.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b2bb5d33777ddab1d036e3568a31484e366cc5a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2272.json b/mne-python/source/doc/sphinxext/prs/2272.json new file mode 100644 index 0000000000000000000000000000000000000000..7dd229b694dec1af35f83b72c52116d97efe532c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2272.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4a1635dc4a4649b668658d02270320d5a20f4ab4", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2274.json b/mne-python/source/doc/sphinxext/prs/2274.json new file mode 100644 index 0000000000000000000000000000000000000000..3221d0ca891d4ccc5c2ccd0a445fc7c97b40d1ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2274.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e3d7a6db0665877ce573df3f24128b2457978fc1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/data/coil_def_Elekta.dat": { + "a": 70, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 568, + "d": 0 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 138, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2278.json b/mne-python/source/doc/sphinxext/prs/2278.json new file mode 100644 index 0000000000000000000000000000000000000000..9cdc96ade25d3aed1b2d17cc7b113a77726503cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2278.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0b96c85bb2366f33221840d610215f995881a455", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/report.py": { + "a": 19, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2281.json b/mne-python/source/doc/sphinxext/prs/2281.json new file mode 100644 index 0000000000000000000000000000000000000000..65de30459f786f07ab89f6467d652e3e0750b1b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2281.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "67c4c7e29aeced45d8b32234acf428ed994b8c77", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/evoked.py": { + "a": 13, + "d": 5 + }, + "mne/io/proj.py": { + "a": 6, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 25, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 30, + "d": 12 + }, + "mne/viz/tests/test_topomap.py": { + "a": 8, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 10, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 66, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2285.json b/mne-python/source/doc/sphinxext/prs/2285.json new file mode 100644 index 0000000000000000000000000000000000000000..dbe719dbce186d3b7e44da3b16796f62446e4728 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2285.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3736825ade6308d6f8831e57f64bab5acc6d2354", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 4, + "d": 9 + }, + "mne/tests/test_filter.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2288.json b/mne-python/source/doc/sphinxext/prs/2288.json new file mode 100644 index 0000000000000000000000000000000000000000..52ed6cc6bc38634b5f4528eafdf65a559aaa56a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2288.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "16e34444ae185bb1c8dd8961b9341151dc9ac2ee", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2291.json b/mne-python/source/doc/sphinxext/prs/2291.json new file mode 100644 index 0000000000000000000000000000000000000000..e236d5d275e8b61a74b9e8693ecabbfdc776445f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2291.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "53ee179171629bbe41d7a4ebb713414b8fec0e5b", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 216, + "d": 121 + }, + "mne/io/base.py": { + "a": 2, + "d": 10 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 38 + }, + "mne/io/open.py": { + "a": 42, + "d": 1 + }, + "mne/io/write.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 0 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2296.json b/mne-python/source/doc/sphinxext/prs/2296.json new file mode 100644 index 0000000000000000000000000000000000000000..1bf1fe94246c498a94f546ec2040627134b174ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2296.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a4347895e92ab188472b884c26a528fda2214b9e", + "authors": [ + { + "n": "alexandre barachant", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 5, + "d": 0 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 101, + "d": 0 + }, + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 75, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 145, + "d": 0 + }, + "mne/preprocessing/xdawn.py": { + "a": 557, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2298.json b/mne-python/source/doc/sphinxext/prs/2298.json new file mode 100644 index 0000000000000000000000000000000000000000..aa2bbd01d0b9d788b267300e8dea30bb94ba27b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2298.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "16a78f8dcc00a874300e02ce39f955315a509962", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/preprocessing/plot_resample.py": { + "a": 85, + "d": 0 + }, + "mne/epochs.py": { + "a": 19, + "d": 6 + }, + "mne/event.py": { + "a": 5, + "d": 4 + }, + "mne/filter.py": { + "a": 55, + "d": 0 + }, + "mne/io/base.py": { + "a": 91, + "d": 37 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 62, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 15, + "d": 6 + }, + "mne/tests/test_filter.py": { + "a": 24, + "d": 3 + }, + "mne/tests/test_utils.py": { + "a": 2, + "d": 2 + }, + "mne/utils.py": { + "a": 34, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/23.json b/mne-python/source/doc/sphinxext/prs/23.json new file mode 100644 index 0000000000000000000000000000000000000000..8678446671686a6848602f4923346011008abd32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/23.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0722fe5803341001511200d07621974d5ed84be2", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/230.json b/mne-python/source/doc/sphinxext/prs/230.json new file mode 100644 index 0000000000000000000000000000000000000000..993402f211014d8d812d3c55d9b3d666d9835241 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/230.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "8a69346b2aaf878d8f7fc931e35ccf02c7d08208", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 23, + "d": 4 + }, + "mne/fiff/evoked.py": { + "a": 1, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 7, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 17, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 5 + }, + "mne/tests/test_source_estimate.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2301.json b/mne-python/source/doc/sphinxext/prs/2301.json new file mode 100644 index 0000000000000000000000000000000000000000..a5e4891120070c6e6750a5b7be60e47922759be3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2301.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "71d8694ffc2bf47f7153d6d9461ff187ed12b30e", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2302.json b/mne-python/source/doc/sphinxext/prs/2302.json new file mode 100644 index 0000000000000000000000000000000000000000..6e190cdaeb9589a6f0e1f9b8c180d91d8b083e22 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2302.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "d1aba302a4758085eaeb828ccdc3089af887df3b", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 66, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 31, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 37, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 30, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 37, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2303.json b/mne-python/source/doc/sphinxext/prs/2303.json new file mode 100644 index 0000000000000000000000000000000000000000..b26533b3940a001c34ae8b93def1ebd50814f5a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2303.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c46dabe0265c3681ccfac403cc5d85af907a7486", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 5, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 46, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2304.json b/mne-python/source/doc/sphinxext/prs/2304.json new file mode 100644 index 0000000000000000000000000000000000000000..fa2f65f3cb1509717f072e153262f0c8cfda95c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2304.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "174edbd8b46d30ce234c21c3d5773cf24447c34d", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/stats/plot_linear_regression_raw.py": { + "a": 64, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 10 + }, + "mne/stats/regression.py": { + "a": 205, + "d": 2 + }, + "mne/stats/tests/test_regression.py": { + "a": 46, + "d": 2 + }, + "mne/utils.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2305.json b/mne-python/source/doc/sphinxext/prs/2305.json new file mode 100644 index 0000000000000000000000000000000000000000..c2cd01117e916cb6442cee3c0b2971b9741154b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2305.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2a57065d8e9480f215d745209772eeefb629655a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 92, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2309.json b/mne-python/source/doc/sphinxext/prs/2309.json new file mode 100644 index 0000000000000000000000000000000000000000..fdfafae5da7710665c0ce1f6db48cc9b234ba9f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2309.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "54bae3c498edebd04237de5490bc68ff1208004b", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 21, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 47, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/231.json b/mne-python/source/doc/sphinxext/prs/231.json new file mode 100644 index 0000000000000000000000000000000000000000..7b8e5d92ac570477f650192ebe652c64130114f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/231.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c495307786db777ecacf0d1ed2465e3de74448a6", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/sphinxext/gen_rst.py": { + "a": 127, + "d": 2 + }, + "examples/inverse/plot_dipole_fit_result.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2318.json b/mne-python/source/doc/sphinxext/prs/2318.json new file mode 100644 index 0000000000000000000000000000000000000000..e7f9bc45cde61c267fa2c5054ebd6c6ea25da706 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2318.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ddb68713863e62e3fdc70305b4f69bfa57cc34fd", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 36, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 24, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2319.json b/mne-python/source/doc/sphinxext/prs/2319.json new file mode 100644 index 0000000000000000000000000000000000000000..3e473a5a98a2efe3d1637b47ed1558a951dc4911 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2319.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "569ca6a7d38e6e13af2dd73eb1052d8123bf4ec0", + "authors": [ + { + "n": "jmontoyam", + "e": "montoya.jair.m@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 15, + "d": 1 + }, + "mne/utils.py": { + "a": 38, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2320.json b/mne-python/source/doc/sphinxext/prs/2320.json new file mode 100644 index 0000000000000000000000000000000000000000..9235f671b1b50cd4672dab315283e6af6dd73b18 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2320.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "44800aa75a0c7ef3b0b5352de51f722c382e64c3", + "authors": [ + { + "n": "alexandre barachant", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 145, + "d": 65 + }, + "mne/decoding/csp.py": { + "a": 21, + "d": 69 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 75 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2322.json b/mne-python/source/doc/sphinxext/prs/2322.json new file mode 100644 index 0000000000000000000000000000000000000000..450212344d88604f54f2677d439f4571ed0ac11c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2322.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a0696cffd123b4bacc4bce498d230b71dee98fcd", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 68, + "d": 18 + }, + "mne/viz/tests/test_topomap.py": { + "a": 15, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 9, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 96, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2325.json b/mne-python/source/doc/sphinxext/prs/2325.json new file mode 100644 index 0000000000000000000000000000000000000000..b5c4dde174d85cd5539adab731aed88d04d354ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2325.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d1d1368712265209473b80adc6c498614119008e", + "authors": [ + { + "n": "Alan Leggitt", + "e": "leggitta3@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 7, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2327.json b/mne-python/source/doc/sphinxext/prs/2327.json new file mode 100644 index 0000000000000000000000000000000000000000..6c2044d6e1a27731b1d5d26cdd7df476ffa77608 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2327.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7ce3774a19b0e2faef28bc4bc4774ca3f1462607", + "authors": [ + { + "n": "jmontoyam", + "e": "montoya.jair.m@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 0 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/infomax_.py": { + "a": 48, + "d": 16 + }, + "mne/preprocessing/tests/data/eeglab_infomax_results_eeg_data.mat": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/data/eeglab_infomax_results_meg_data.mat": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 178, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2329.json b/mne-python/source/doc/sphinxext/prs/2329.json new file mode 100644 index 0000000000000000000000000000000000000000..a9512aa8a80f2a29bb52ab4e5812fdb467c57459 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2329.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0812b220e96e610764f6ecc7ba6de21895bc548d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/233.json b/mne-python/source/doc/sphinxext/prs/233.json new file mode 100644 index 0000000000000000000000000000000000000000..796e7af937a237e6fa19d2698675972d6f65973d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/233.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8347d3e4ff875e68826b54969600678d6b87f9d3", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_transformation.py": { + "a": 33, + "d": 0 + }, + "mne/transforms.py": { + "a": 81, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2335.json b/mne-python/source/doc/sphinxext/prs/2335.json new file mode 100644 index 0000000000000000000000000000000000000000..0d8c00f61bd226fed778afaefee68ae4bb5d52ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2335.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "888272a5d4d272a8feef8c46958386433107c572", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2337.json b/mne-python/source/doc/sphinxext/prs/2337.json new file mode 100644 index 0000000000000000000000000000000000000000..9542649d72a435c9f4d756c1e4bed45e53e121c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2337.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f4e04ad386c56677f3610129f6f629f3f6c4a7cb", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 4 + }, + "mne/epochs.py": { + "a": 39, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2338.json b/mne-python/source/doc/sphinxext/prs/2338.json new file mode 100644 index 0000000000000000000000000000000000000000..1cf31de847964ddc3e71585d9357d972ec4dde7c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2338.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8e40657cd7131d09dbcfbcafaad7613faf60a627", + "authors": [ + { + "n": "Ross Maddox", + "e": "rkmaddox@uw.edu" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 32, + "d": 10 + }, + "mne/io/brainvision/tests/data/test.vmrk": { + "a": 3, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 43, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2339.json b/mne-python/source/doc/sphinxext/prs/2339.json new file mode 100644 index 0000000000000000000000000000000000000000..19809fbe6ef3a61057e6f7e3a8ec306847768188 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2339.json @@ -0,0 +1,815 @@ +{ + "merge_commit_sha": "77ba8d1838c047aabb65262b32efe1515901eb10", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 3, + "d": 3 + }, + "Makefile": { + "a": 3, + "d": 3 + }, + "doc/Makefile": { + "a": 28, + "d": 28 + }, + "doc/_images/mne_helmet.png": { + "a": 0, + "d": 0 + }, + "doc/_static/branch_dropdown.png": { + "a": 0, + "d": 0 + }, + "doc/_static/favicon.ico": { + "a": 0, + "d": 0 + }, + "doc/_static/flow_diagram.svg": { + "a": 204, + "d": 0 + }, + "doc/_static/forking_button.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institutions.png": { + "a": 0, + "d": 0 + }, + "doc/_static/mne_logo.png": { + "a": 0, + "d": 0 + }, + "doc/_static/mne_logo_small.png": { + "a": 0, + "d": 0 + }, + "doc/_static/pull_button.png": { + "a": 0, + "d": 0 + }, + "doc/_static/style.css": { + "a": 46, + "d": 0 + }, + "doc/_templates/class.rst": { + "a": 0, + "d": 0 + }, + "doc/_templates/function.rst": { + "a": 0, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 4, + "d": 21 + }, + "doc/advanced_setup.rst": { + "a": 0, + "d": 0 + }, + "doc/cite.rst": { + "a": 4, + "d": 6 + }, + "doc/conf.py": { + "a": 107, + "d": 52 + }, + "doc/contributing.rst": { + "a": 10, + "d": 5 + }, + "doc/customizing_git.rst": { + "a": 0, + "d": 0 + }, + "doc/faq.rst": { + "a": 3, + "d": 1 + }, + "doc/getting_started.rst": { + "a": 321, + "d": 0 + }, + "doc/git_links.inc": { + "a": 0, + "d": 0 + }, + "doc/index.rst": { + "a": 136, + "d": 0 + }, + "doc/known_projects.inc": { + "a": 0, + "d": 0 + }, + "doc/links.inc": { + "a": 0, + "d": 0 + }, + "doc/manual/appendix/bem_model.rst": { + "a": 24, + "d": 49 + }, + "doc/manual/appendix/c_EULA.rst": { + "a": 8, + "d": 2 + }, + "doc/manual/appendix/c_misc.rst": { + "a": 99, + "d": 0 + }, + "doc/manual/appendix/c_release_notes.rst": { + "a": 91, + "d": 114 + }, + "doc/manual/appendix/martinos.rst": { + "a": 117, + "d": 0 + }, + "doc/manual/c_reference.rst": { + "a": 6442, + "d": 0 + }, + "doc/manual/cookbook.rst": { + "a": 412, + "d": 0 + }, + "doc/manual/datasets.rst": { + "a": 14, + "d": 75 + }, + "doc/manual/gui/analyze.rst": { + "a": 12, + "d": 85 + }, + "doc/manual/gui/browse.rst": { + "a": 31, + "d": 426 + }, + "doc/manual/gui/mne_analyze/MNE_preferences.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/adjust_alignment.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/adjust_lights.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/adjust_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/cont_hpi_data.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/dipole_list.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/dipole_parameters.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/dipoles_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/epoch_selector.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/field_mapping_pref.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/file_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/hardcopy_controls.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/help_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/image_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/label_list.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/labels_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/main_window.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/movie_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/mri_viewer.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/open_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/overlay_management.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/patch_selection_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/save_label_timecourse.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/scales_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/surface_controls.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/surface_selection_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/timecourse_manager.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/view_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/viewer.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/viewer_options.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/visualize_hpi.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/windows_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/adjust_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/adust_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/average_pref.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/channel_selection.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/file_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/filter_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/help_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/main.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/manage_averages_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/new_selection.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/new_ssp.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/open_dialog copy.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/open_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/process_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/process_menu2.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/scales_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/scales_dialog2.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/toolbar.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-0.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-1.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-10.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-11.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-12.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-13.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-14.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-15.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-16.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-17.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-2.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-3.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-4.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-5.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-6.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-7.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-8.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-9.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/index.rst": { + "a": 142, + "d": 0 + }, + "doc/manual/io.rst": { + "a": 343, + "d": 0 + }, + "doc/manual/matlab.rst": { + "a": 13, + "d": 7 + }, + "doc/manual/pics/CoordinateSystems.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/Digitizer-example.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/Flowchart.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/HeadCS.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/ICA_primer.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/cover.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/flat.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/morphed.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/neuromag.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/orig.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/proj-off-on.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/title_page.png": { + "a": 0, + "d": 0 + }, + "doc/manual/preprocessing/bads.rst": { + "a": 3, + "d": 0 + }, + "doc/manual/preprocessing/filter.rst": { + "a": 3, + "d": 0 + }, + "doc/manual/preprocessing/ica.rst": { + "a": 118, + "d": 0 + }, + "doc/manual/preprocessing/overview.rst": { + "a": 3, + "d": 0 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 128, + "d": 0 + }, + "doc/manual/source_localization/covariance.rst": { + "a": 5, + "d": 0 + }, + "doc/manual/source_localization/forward.rst": { + "a": 28, + "d": 476 + }, + "doc/manual/source_localization/inverse.rst": { + "a": 520, + "d": 0 + }, + "doc/manual/source_localization/morph.rst": { + "a": 141, + "d": 0 + }, + "doc/manual/statistics.rst": { + "a": 100, + "d": 0 + }, + "doc/manual/time_frequency.rst": { + "a": 3, + "d": 0 + }, + "doc/manual/visualization.rst": { + "a": 3, + "d": 0 + }, + "doc/mne_cpp.rst": { + "a": 0, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 5, + "d": 11 + }, + "doc/references.rst": { + "a": 0, + "d": 0 + }, + "doc/source/_static/default.css": { + "a": 0, + "d": 515 + }, + "doc/source/_static/institutions.png": { + "a": 0, + "d": 0 + }, + "doc/source/_static/navy.css": { + "a": 0, + "d": 515 + }, + "doc/source/_templates/sidebar.html": { + "a": 0, + "d": 5 + }, + "doc/source/getting_started.rst": { + "a": 0, + "d": 102 + }, + "doc/source/index.rst": { + "a": 0, + "d": 57 + }, + "doc/source/manual.rst": { + "a": 0, + "d": 28 + }, + "doc/source/manual/AppB.rst": { + "a": 0, + "d": 294 + }, + "doc/source/manual/AppInstall.rst": { + "a": 0, + "d": 174 + }, + "doc/source/manual/convert.rst": { + "a": 0, + "d": 2312 + }, + "doc/source/manual/cookbook.rst": { + "a": 0, + "d": 1066 + }, + "doc/source/manual/intro.rst": { + "a": 0, + "d": 45 + }, + "doc/source/manual/list.rst": { + "a": 0, + "d": 439 + }, + "doc/source/manual/mne.rst": { + "a": 0, + "d": 1323 + }, + "doc/source/manual/morph.rst": { + "a": 0, + "d": 409 + }, + "doc/source/manual/pics/Averaging-flowchart.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/utilities.rst": { + "a": 0, + "d": 1402 + }, + "doc/source/mne-python.rst": { + "a": 0, + "d": 29 + }, + "doc/source/python_tutorial.rst": { + "a": 0, + "d": 398 + }, + "doc/sphinxext/commands.py": { + "a": 80, + "d": 0 + }, + "doc/sphinxext/gen_rst.py": { + "a": 0, + "d": 1222 + }, + "doc/this_project.inc": { + "a": 0, + "d": 0 + }, + "doc/tutorials.rst": { + "a": 84, + "d": 0 + }, + "doc/tutorials/_images/plot_read_and_write_raw_data.png": { + "a": 0, + "d": 0 + }, + "doc/tutorials/_images/plot_read_epochs.png": { + "a": 0, + "d": 0 + }, + "doc/tutorials/_images/plot_time_frequency.png": { + "a": 0, + "d": 0 + }, + "doc/tutorials/command_line.rst": { + "a": 0, + "d": 0 + }, + "doc/tutorials/report.rst": { + "a": 3, + "d": 3 + }, + "doc/upload_html.sh": { + "a": 1, + "d": 1 + }, + "doc/utils/extract_config_doc.py": { + "a": 0, + "d": 73 + }, + "doc/utils/lut2sphinxtbl.py": { + "a": 0, + "d": 65 + }, + "doc/utils/make_clean_config.py": { + "a": 0, + "d": 30 + }, + "doc/whats_new.rst": { + "a": 6, + "d": 7 + }, + "examples/README.txt": { + "a": 2, + "d": 2 + }, + "examples/forward/plot_decimate_head_surface.py": { + "a": 9, + "d": 9 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 0, + "d": 81 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 47, + "d": 0 + }, + "mne/connectivity/spectral.py": { + "a": 6, + "d": 7 + }, + "mne/decoding/time_gen.py": { + "a": 18, + "d": 20 + }, + "mne/io/base.py": { + "a": 4, + "d": 4 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 98, + "d": 1 + }, + "mne/label.py": { + "a": 8, + "d": 7 + }, + "mne/selection.py": { + "a": 12, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 5 + }, + "mne/stats/parametric.py": { + "a": 15, + "d": 15 + }, + "mne/viz/epochs.py": { + "a": 6, + "d": 4 + }, + "tutorials/README.txt": { + "a": 4, + "d": 0 + }, + "tutorials/plot_cluster_1samp_test_time_frequency.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_cluster_methods_tutorial.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_cluster_stats_spatio_temporal.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_cluster_stats_time_frequency.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_creating_data_structures.py": { + "a": 180, + "d": 0 + }, + "tutorials/plot_epochs_objects.py": { + "a": 103, + "d": 0 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 11, + "d": 11 + }, + "tutorials/plot_info.py": { + "a": 90, + "d": 0 + }, + "tutorials/plot_introduction.py": { + "a": 373, + "d": 0 + }, + "tutorials/plot_modifying_data_inplace.py": { + "a": 74, + "d": 0 + }, + "tutorials/plot_raw_objects.py": { + "a": 133, + "d": 0 + }, + "tutorials/plot_source_localization_basics.py": { + "a": 98, + "d": 0 + }, + "tutorials/plot_spatio_temporal_cluster_stats_sensor.py": { + "a": 40, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2340.json b/mne-python/source/doc/sphinxext/prs/2340.json new file mode 100644 index 0000000000000000000000000000000000000000..34ca64c5958ed1aa2d6c5db34cf8e5b833c249d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2340.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "11af4dcfc9d7a5a00d9b033a9a21c1f93ab29beb", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/bem.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2343.json b/mne-python/source/doc/sphinxext/prs/2343.json new file mode 100644 index 0000000000000000000000000000000000000000..25988835c45a2006f1e15906af89c7c827db0171 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2343.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "010df1aac1b488d4a25312a83e0454650cba554d", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2348.json b/mne-python/source/doc/sphinxext/prs/2348.json new file mode 100644 index 0000000000000000000000000000000000000000..e67ce168146df09c93239d02992eba0c112760c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2348.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0497f8fdce9ec6e8bc6b0e854fa10af545538276", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 3, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/235.json b/mne-python/source/doc/sphinxext/prs/235.json new file mode 100644 index 0000000000000000000000000000000000000000..d59fbc142ef2b95b8083e00059878ab04c23acc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/235.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2ff1807312d587d03da2976b30342bf14647e6ab", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 2, + "d": 1 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 2, + "d": 1 + }, + "mne/fixes.py": { + "a": 13, + "d": 0 + }, + "mne/tests/test_fixes.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2350.json b/mne-python/source/doc/sphinxext/prs/2350.json new file mode 100644 index 0000000000000000000000000000000000000000..cfda9ccba9221527280322381f0bb3e2184263b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2350.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "792306dfa81d540d12abb4dbfed1e3736adc85b5", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 25, + "d": 4 + }, + "mne/io/tests/test_raw.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2351.json b/mne-python/source/doc/sphinxext/prs/2351.json new file mode 100644 index 0000000000000000000000000000000000000000..f8bf6d472f71c231acb4511357241064c4c0e946 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2351.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "630ef2fb56b5e934d0102381a0b12a20939dd05e", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 8, + "d": 7 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2352.json b/mne-python/source/doc/sphinxext/prs/2352.json new file mode 100644 index 0000000000000000000000000000000000000000..225555e16748d09dd4e3d855053ba0539417fa16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2352.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0b60da7036b68f5467a45646df1366d16edcde0d", + "authors": [ + { + "n": "Romain Trachel", + "e": "trachelr@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/csp.py": { + "a": 7, + "d": 2 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2355.json b/mne-python/source/doc/sphinxext/prs/2355.json new file mode 100644 index 0000000000000000000000000000000000000000..69a768dfe848e39de13424cee0dc7bb0a469b4c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2355.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "16ac16d99850f4cc473ccceeab0fc56a10b7b196", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "mne/dipole.py": { + "a": 16, + "d": 4 + }, + "mne/forward/_make_forward.py": { + "a": 149, + "d": 71 + }, + "mne/io/write.py": { + "a": 12, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 25, + "d": 86 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 27, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2358.json b/mne-python/source/doc/sphinxext/prs/2358.json new file mode 100644 index 0000000000000000000000000000000000000000..50dd57b6f9dbf5bf0ec4c8886bd2597ef9b91607 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2358.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "b6e4658a9a98e0ee934d6e930347406ff6910cc4", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 16, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 74, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/brainstorm/__init__.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 60, + "d": 0 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 59, + "d": 0 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 51, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 6, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 46, + "d": 3 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2359.json b/mne-python/source/doc/sphinxext/prs/2359.json new file mode 100644 index 0000000000000000000000000000000000000000..546ea85ad5e027763bba14d752a6429332d9a795 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2359.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bc385512f74b42ac67af3802e8c358d3f594ef58", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2361.json b/mne-python/source/doc/sphinxext/prs/2361.json new file mode 100644 index 0000000000000000000000000000000000000000..042b859c9cc59babecc24b27b3abdd0484965b64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2361.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e0f8417275e3650500832ba40020509058f971f9", + "authors": [ + { + "n": "Romain Trachel", + "e": "trachelr@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 2, + "d": 2 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 3, + "d": 3 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 9, + "d": 9 + }, + "mne/decoding/transformer.py": { + "a": 14, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2364.json b/mne-python/source/doc/sphinxext/prs/2364.json new file mode 100644 index 0000000000000000000000000000000000000000..5a998b53ac74b1b8961cda8469f776d009a01fc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2364.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ae47e17db8e9575c0fcaede1224e09a640050742", + "authors": [ + { + "n": "Natalie Klein", + "e": null + } + ], + "changes": { + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_event.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2366.json b/mne-python/source/doc/sphinxext/prs/2366.json new file mode 100644 index 0000000000000000000000000000000000000000..d4d6c806e02b75ce7af65150161eba0cf20cc937 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2366.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "8ffe2c39146c25dadd822a7e587d0cd018065828", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 2 + }, + "mne/defaults.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 64, + "d": 21 + }, + "mne/viz/ica.py": { + "a": 0, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2367.json b/mne-python/source/doc/sphinxext/prs/2367.json new file mode 100644 index 0000000000000000000000000000000000000000..849f1d977edb0b4dbe44b7f2c1cca79f40b401fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2367.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9795ce87b9c16e0b1e9bf7073f5719ab8207d3d6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_rap_music.py": { + "a": 3, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 17, + "d": 7 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 5, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2369.json b/mne-python/source/doc/sphinxext/prs/2369.json new file mode 100644 index 0000000000000000000000000000000000000000..12a3ba147c475ea52d9e8c3ea4c42fb0a9971f70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2369.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f902d090828b02c687532e34cff5ba5a26046b24", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "mne/forward/_make_forward.py": { + "a": 5, + "d": 5 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/237.json b/mne-python/source/doc/sphinxext/prs/237.json new file mode 100644 index 0000000000000000000000000000000000000000..83d1a661ffde5902b232f3384a4b3d3d83943ead --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/237.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "968c410c51800a6f26da6d798dc1cb2033c1f3d0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/proj.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2374.json b/mne-python/source/doc/sphinxext/prs/2374.json new file mode 100644 index 0000000000000000000000000000000000000000..ca91623e79aa277365a31ce4313aac90c1e5ae63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2374.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "08d49b8275a28665b6ca9dc6a69eb373a1aa417f", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 4, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 9, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 15, + "d": 3 + }, + "mne/commands/mne_show_fiff.py": { + "a": 27, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 8, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 4 + }, + "mne/data/coil_def_Elekta.dat": { + "a": 7, + "d": 3 + }, + "mne/decoding/base.py": { + "a": 4, + "d": 3 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 29, + "d": 31 + }, + "mne/forward/_make_forward.py": { + "a": 32, + "d": 15 + }, + "mne/io/constants.py": { + "a": 5, + "d": 2 + }, + "mne/io/open.py": { + "a": 9, + "d": 1 + }, + "mne/io/pick.py": { + "a": 1, + "d": 3 + }, + "mne/io/proc_history.py": { + "a": 35, + "d": 13 + }, + "mne/io/tests/test_apply_function.py": { + "a": 6, + "d": 12 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 698, + "d": 287 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 7, + "d": 10 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 344, + "d": 144 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 12, + "d": 15 + }, + "mne/tests/test_chpi.py": { + "a": 4, + "d": 10 + }, + "mne/tests/test_dipole.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_filter.py": { + "a": 27, + "d": 39 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 3, + "d": 3 + }, + "mne/transforms.py": { + "a": 10, + "d": 9 + }, + "mne/utils.py": { + "a": 20, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2375.json b/mne-python/source/doc/sphinxext/prs/2375.json new file mode 100644 index 0000000000000000000000000000000000000000..51db349cc69a4899d6f990b96c9bd7431797ce7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2375.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b97e8732f748b18ddedf526c9673e78ab9620a5a", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 3, + "d": 1 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/io/pick.py": { + "a": 41, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 5, + "d": 1 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2376.json b/mne-python/source/doc/sphinxext/prs/2376.json new file mode 100644 index 0000000000000000000000000000000000000000..b72402af2b95332c9d2291ca97913a746260696d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2376.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bb6b1340ca3676e0b29e1d726fe300f643a3b65d", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 18, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2378.json b/mne-python/source/doc/sphinxext/prs/2378.json new file mode 100644 index 0000000000000000000000000000000000000000..2b9617f23da697a8235580e6304ded96be45e337 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2378.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "26e88fbe56e9c5675d3a66a9cbe3c47d8cc21c7d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/flow_diagram.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 2, + "d": 1 + }, + "examples/realtime/ftclient_rt_average.py": { + "a": 2, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 4, + "d": 3 + }, + "mne/epochs.py": { + "a": 5, + "d": 2 + }, + "mne/event.py": { + "a": 2, + "d": 1 + }, + "mne/fixes.py": { + "a": 0, + "d": 2 + }, + "mne/forward/_lead_dots.py": { + "a": 14, + "d": 10 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 3, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/infomax_.py": { + "a": 2, + "d": 4 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 98, + "d": 55 + }, + "mne/preprocessing/xdawn.py": { + "a": 5, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 11, + "d": 15 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 1 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 2, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 16, + "d": 10 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2380.json b/mne-python/source/doc/sphinxext/prs/2380.json new file mode 100644 index 0000000000000000000000000000000000000000..b4be7617df83fa1f7779cb7eb0ef1b22f750bd4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2380.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b264aef94db83da0dd1b274f9e5d6055651e00a0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 33, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2382.json b/mne-python/source/doc/sphinxext/prs/2382.json new file mode 100644 index 0000000000000000000000000000000000000000..7272dacd3dda1174b7ca8d35ca9a867bb72706f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2382.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "06911f97a88915c02490bd35045dcd133c6babc9", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 27, + "d": 38 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2384.json b/mne-python/source/doc/sphinxext/prs/2384.json new file mode 100644 index 0000000000000000000000000000000000000000..c4dad9579a44e5cc1357ba18ecd77c620d1b79d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2384.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7deb3ba770acc2aca1006259d599fc957a970a0c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/Makefile": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2386.json b/mne-python/source/doc/sphinxext/prs/2386.json new file mode 100644 index 0000000000000000000000000000000000000000..8b21d841803e2023d57592f737db983a9a91499a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2386.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8121b2d60a751b506585cc91d648f7b0052c124e", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_sensors.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 6, + "d": 7 + }, + "mne/time_frequency/tfr.py": { + "a": 14, + "d": 13 + }, + "mne/viz/topomap.py": { + "a": 55, + "d": 56 + }, + "mne/viz/utils.py": { + "a": 11, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2387.json b/mne-python/source/doc/sphinxext/prs/2387.json new file mode 100644 index 0000000000000000000000000000000000000000..8a08e204647879928254d506ba57038028eef0e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2387.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "17138ca0586bdb502af102fcaf9940808a80a326", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/preprocessing/stim.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/239.json b/mne-python/source/doc/sphinxext/prs/239.json new file mode 100644 index 0000000000000000000000000000000000000000..254e6337b0dca74d885102612116e5d6041adaa0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/239.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2048cd364bc86442163adf0ec9b6dc80325c8b88", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/proj.py": { + "a": 4, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2394.json b/mne-python/source/doc/sphinxext/prs/2394.json new file mode 100644 index 0000000000000000000000000000000000000000..80c264d6af3971a62948beaeb093b955c976bb89 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2394.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1fedc47e766b954e11d884aaa295b3b5c01dbb95", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 50, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 4, + "d": 2 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2395.json b/mne-python/source/doc/sphinxext/prs/2395.json new file mode 100644 index 0000000000000000000000000000000000000000..7ac76c7ade712681188d9f650a1fb9eeeb4d019c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2395.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b8bf44c0910e28fe437f348db10427e6354725d7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/mne_logo.png": { + "a": 0, + "d": 0 + }, + "doc/_static/mne_logo_small.png": { + "a": 0, + "d": 0 + }, + "doc/generate_mne_logos.py": { + "a": 154, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2396.json b/mne-python/source/doc/sphinxext/prs/2396.json new file mode 100644 index 0000000000000000000000000000000000000000..ac6ead2334f83edd34d0826c739edcb366bcd137 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2396.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "319ba7a281e73af160667d84796f1644a473c5d4", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2398.json b/mne-python/source/doc/sphinxext/prs/2398.json new file mode 100644 index 0000000000000000000000000000000000000000..f56c4d2e53ec24bbe1d90dd4f6f999bc70ab7912 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2398.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bd5b94c9050a6484956f9f3c670db053e2448cc9", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 9, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2399.json b/mne-python/source/doc/sphinxext/prs/2399.json new file mode 100644 index 0000000000000000000000000000000000000000..9a151ef60032b7eac9b23ca1d6df715e8dccd3b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2399.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "58f1acbce1f2e6395ace5119e00dee2ff5ccf10b", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 22, + "d": 20 + }, + "mne/decoding/csp.py": { + "a": 22, + "d": 20 + }, + "mne/epochs.py": { + "a": 11, + "d": 9 + }, + "mne/evoked.py": { + "a": 11, + "d": 9 + }, + "mne/preprocessing/ica.py": { + "a": 11, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 11, + "d": 9 + }, + "mne/viz/tests/test_topomap.py": { + "a": 33, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 116, + "d": 82 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/24.json b/mne-python/source/doc/sphinxext/prs/24.json new file mode 100644 index 0000000000000000000000000000000000000000..4568a374a8029f9f5ebeb631c2fa0fbc817b8d45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/24.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6f9d6a2f0214cd21973843f9c662a62e1e00dda3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/cov.py": { + "a": 80, + "d": 3 + }, + "mne/epochs.py": { + "a": 8, + "d": 0 + }, + "mne/fiff/evoked.py": { + "a": 22, + "d": 18 + }, + "mne/fiff/raw.py": { + "a": 13, + "d": 19 + }, + "mne/tests/test_cov.py": { + "a": 33, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2400.json b/mne-python/source/doc/sphinxext/prs/2400.json new file mode 100644 index 0000000000000000000000000000000000000000..20c2dab26c8bc7d509f512316b8f18a40de8bdbb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2400.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "659bc393465355df2a065fb0ec8f4bd3276a7038", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 156, + "d": 32 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 102, + "d": 42 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2401.json b/mne-python/source/doc/sphinxext/prs/2401.json new file mode 100644 index 0000000000000000000000000000000000000000..2c86c4f6e030997e77c41028123adeb7c038ec80 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2401.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cd5970dddd3f250dfc49f127adf890acbbcf1c39", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/time_gen.py": { + "a": 60, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2402.json b/mne-python/source/doc/sphinxext/prs/2402.json new file mode 100644 index 0000000000000000000000000000000000000000..0cb1ffb98b05f3ab26c0872f27121870c9444a00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2402.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2e7df491b5182069859d8fb7d6f4896a9f48392c", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 36, + "d": 23 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 43, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2410.json b/mne-python/source/doc/sphinxext/prs/2410.json new file mode 100644 index 0000000000000000000000000000000000000000..567d00014c2c793a67c23a6a50ab265e16d98a46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2410.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2d1a3128da0337c877e3e6d967bb4b0d2c555780", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2412.json b/mne-python/source/doc/sphinxext/prs/2412.json new file mode 100644 index 0000000000000000000000000000000000000000..dd41d4079d3c0aedfcf2d47ae9933a9e22464ed7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2412.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "aea08472266f673f06c9c45c1ab0e73a466d2a5d", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 6, + "d": 4 + }, + "mne/decoding/time_gen.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2413.json b/mne-python/source/doc/sphinxext/prs/2413.json new file mode 100644 index 0000000000000000000000000000000000000000..96a79dfa5236236e50a52db353fac91f42c28948 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2413.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "14e10d78482ef917a8ce80e96f5db9605671bec3", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_eog_artifact_histogram.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_shift_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2414.json b/mne-python/source/doc/sphinxext/prs/2414.json new file mode 100644 index 0000000000000000000000000000000000000000..a1cf50713cbde38df0f13c109e916f9e856ea159 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2414.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0bca5b35fa4e6ef664d231f8af5574b92c2639b0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/index.rst": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2415.json b/mne-python/source/doc/sphinxext/prs/2415.json new file mode 100644 index 0000000000000000000000000000000000000000..9ab97e08d06c00f1258c64e3c194c66fdf2e6172 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2415.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "9d7f3947435c22f1f2ec2ee25b17a13c8f623818", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 3, + "d": 2 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 8, + "d": 2 + }, + "mne/filter.py": { + "a": 5, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/eog.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 6, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_decoding.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2417.json b/mne-python/source/doc/sphinxext/prs/2417.json new file mode 100644 index 0000000000000000000000000000000000000000..0db16b9785ed2d32cc0dffb599d93a702928da1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2417.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "873aac06d2dd727d6b584fabc36863c3ebc7bd0e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/_static/mne_helmet.png": { + "a": 0, + "d": 0 + }, + "doc/conf.py": { + "a": 3, + "d": 2 + }, + "doc/contributing.rst": { + "a": 10, + "d": 3 + }, + "doc/customizing_git.rst": { + "a": 4, + "d": 0 + }, + "examples/README.txt": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2418.json b/mne-python/source/doc/sphinxext/prs/2418.json new file mode 100644 index 0000000000000000000000000000000000000000..96287927c25eb72ae432e8273cc9a7adfbee56e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2418.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "745605ee16a731274fbb5ea4ee0a9d4d02c294fc", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "mne/stats/__init__.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/242.json b/mne-python/source/doc/sphinxext/prs/242.json new file mode 100644 index 0000000000000000000000000000000000000000..678958bfd995c2151b28600735785be738365adc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/242.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2a32d359695b6e8623c5c377a39ec1a9dd45dfc1", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_label_activation_from_stc.py": { + "a": 62, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2424.json b/mne-python/source/doc/sphinxext/prs/2424.json new file mode 100644 index 0000000000000000000000000000000000000000..0fc3a0dfa821cae993f67155025a5036276571bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2424.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "bd0ae234195402942260dc51b3ef7872b19cef36", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 4, + "d": 1 + }, + "mne/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/event.py": { + "a": 3, + "d": 2 + }, + "mne/externals/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/externals/h5io/__init__.py": { + "a": 6, + "d": 0 + }, + "mne/externals/h5io/_h5io.py": { + "a": 131, + "d": 14 + }, + "mne/source_estimate.py": { + "a": 7, + "d": 6 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_hdf5.py": { + "a": 0, + "d": 31 + }, + "mne/time_frequency/csd.py": { + "a": 7, + "d": 5 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 41, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 4, + "d": 4 + }, + "setup.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2427.json b/mne-python/source/doc/sphinxext/prs/2427.json new file mode 100644 index 0000000000000000000000000000000000000000..5ae49a696606b4349a221d02d3dfa6e32163ce57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2427.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "26d14bafcef40af134074f23a28c26d5dfb19f96", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2429.json b/mne-python/source/doc/sphinxext/prs/2429.json new file mode 100644 index 0000000000000000000000000000000000000000..6f5f2fd9eb744371ae9cfa12748413c6c6a0ecc1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2429.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "351f5f620c80e8854630929903a56b1d85e05924", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 44, + "d": 8 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/243.json b/mne-python/source/doc/sphinxext/prs/243.json new file mode 100644 index 0000000000000000000000000000000000000000..a2f45869cc1ab1d8f0c94d24796600f9d2f0719e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/243.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3a297af274af4f009d9c8dcf92842d1b286f3e22", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 7, + "d": 3 + }, + "mne/event.py": { + "a": 18, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2431.json b/mne-python/source/doc/sphinxext/prs/2431.json new file mode 100644 index 0000000000000000000000000000000000000000..87352f7710cb90d751d3f0bf1bfcdc9eccf2c9f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2431.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f6fb7db3a435265bb7de19ee10b78a3cb4b344ba", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_transformer.py": { + "a": 5, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2432.json b/mne-python/source/doc/sphinxext/prs/2432.json new file mode 100644 index 0000000000000000000000000000000000000000..fe33617299f6b22ce708d6c0a6534aa5852b08db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2432.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "70586b176875ae74a988c7e07b1093ef8010bcf4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2438.json b/mne-python/source/doc/sphinxext/prs/2438.json new file mode 100644 index 0000000000000000000000000000000000000000..e7c15963a5094440b4e0a684a9e9153d3fe4dc22 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2438.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "edc31f9c5b8ccdcdf3a1566f08f4962bf6262885", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2441.json b/mne-python/source/doc/sphinxext/prs/2441.json new file mode 100644 index 0000000000000000000000000000000000000000..0d12dde0d1ee6007544586e0b01b51354b3dbac3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2441.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a3a499ea759d7cf82838ddc190ad4759217febc4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_csp.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 40, + "d": 40 + }, + "mne/io/proj.py": { + "a": 14, + "d": 23 + }, + "mne/realtime/epochs.py": { + "a": 3, + "d": 8 + }, + "mne/tests/test_epochs.py": { + "a": 51, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2443.json b/mne-python/source/doc/sphinxext/prs/2443.json new file mode 100644 index 0000000000000000000000000000000000000000..d42dcb2efbcdd106b212ee304374df31aa9ce9e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2443.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d0c566f34ecc8dc4d2914b9c59a9eaf42dca785c", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2444.json b/mne-python/source/doc/sphinxext/prs/2444.json new file mode 100644 index 0000000000000000000000000000000000000000..dca4909384fe6c719fca45ea2ef262694a823160 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2444.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c2ff48783921fa9f98a16f8b805e74f971644798", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cuda.py": { + "a": 23, + "d": 10 + }, + "mne/filter.py": { + "a": 1, + "d": 0 + }, + "mne/proj.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_proj.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2449.json b/mne-python/source/doc/sphinxext/prs/2449.json new file mode 100644 index 0000000000000000000000000000000000000000..a6d932eaaec848b1939adc89b42240ce5d502402 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2449.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "2c930405985d3c233e4a4f601c4a3e9590519178", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 8, + "d": 24 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 181 + }, + "mne/viz/tests/test_epochs.py": { + "a": 6, + "d": 33 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/245.json b/mne-python/source/doc/sphinxext/prs/245.json new file mode 100644 index 0000000000000000000000000000000000000000..8823755cc09a05ff6568ec0f954f82b36ca197cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/245.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "025ac9c3517e589588784d32312722be4bd1ed1f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/data/icos.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 27 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2452.json b/mne-python/source/doc/sphinxext/prs/2452.json new file mode 100644 index 0000000000000000000000000000000000000000..72c7cab02081032bda753d92db570dad4e2df712 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2452.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "b91c2f914c6f7e7910c88c1bd3d52ef10bbdc293", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 5, + "d": 7 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 46, + "d": 34 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 3, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 17, + "d": 18 + }, + "mne/channels/tests/test_layout.py": { + "a": 3, + "d": 2 + }, + "mne/cov.py": { + "a": 5, + "d": 4 + }, + "mne/decoding/time_gen.py": { + "a": 7, + "d": 4 + }, + "mne/epochs.py": { + "a": 10, + "d": 10 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 1 + }, + "mne/io/base.py": { + "a": 6, + "d": 20 + }, + "mne/io/meas_info.py": { + "a": 23, + "d": 1 + }, + "mne/io/pick.py": { + "a": 19, + "d": 6 + }, + "mne/io/tests/test_pick.py": { + "a": 13, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 2 + }, + "mne/realtime/mockclient.py": { + "a": 3, + "d": 6 + }, + "mne/stats/regression.py": { + "a": 19, + "d": 14 + }, + "mne/tests/test_epochs.py": { + "a": 22, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2453.json b/mne-python/source/doc/sphinxext/prs/2453.json new file mode 100644 index 0000000000000000000000000000000000000000..b98dc36ea1e836b14f06c103d35bc72c15d97197 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2453.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c65288f90b1beef2b0ddf0d72815aa65f063a846", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/manual/time_frequency.rst": { + "a": 34, + "d": 3 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 52, + "d": 91 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2454.json b/mne-python/source/doc/sphinxext/prs/2454.json new file mode 100644 index 0000000000000000000000000000000000000000..95af9d2ffdd70148e3c0cc2cee30075794ae5371 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2454.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bc9782eb8540abfc6e7b734d3a1ebd5b1a4d3f76", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2455.json b/mne-python/source/doc/sphinxext/prs/2455.json new file mode 100644 index 0000000000000000000000000000000000000000..e66000452f3703a3d5d18be9bfdc671225dca14f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2455.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "08583e8b49edee05298ff3656fe11ff9cc486e80", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2456.json b/mne-python/source/doc/sphinxext/prs/2456.json new file mode 100644 index 0000000000000000000000000000000000000000..26c51c099752ca829ab778dd6a1b326d720ccf78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2456.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7af1ee3d52354334c7db4c06a71c5759bf7a1815", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/minimum_norm/time_frequency.py": { + "a": 74, + "d": 50 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2458.json b/mne-python/source/doc/sphinxext/prs/2458.json new file mode 100644 index 0000000000000000000000000000000000000000..a3e66e5309221947f864b58379d4452da9c3cd14 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2458.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1a329b5f0554f76477b08f8cd2ccba09c40fb0c6", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2459.json b/mne-python/source/doc/sphinxext/prs/2459.json new file mode 100644 index 0000000000000000000000000000000000000000..52c91459d166b10aa91fc81743caf10935b1a8ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2459.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "eda1216f583debcbc067a9b7c5db2509ded735e1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2460.json b/mne-python/source/doc/sphinxext/prs/2460.json new file mode 100644 index 0000000000000000000000000000000000000000..9c795122180cd9a46700093a20d6f5aa656b4a6b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2460.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "af1f4ede9d8bdc412c871f67c448d719a8c96928", + "authors": [ + { + "n": "jmontoyam", + "e": "montoya.jair.m@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/infomax_.py": { + "a": 24, + "d": 14 + }, + "mne/preprocessing/tests/data/eeglab_extended_infomax_results_eeg_data.mat": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/data/eeglab_extended_infomax_results_meg_data.mat": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 35, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2461.json b/mne-python/source/doc/sphinxext/prs/2461.json new file mode 100644 index 0000000000000000000000000000000000000000..e0f65ef8567b5fa83c4d0c6d4924378dd6cc45e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2461.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d46e566c99d976a89acc975e350c1704e7cf697c", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 3, + "d": 3 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 1 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 15, + "d": 3 + }, + "mne/viz/tests/test_epochs.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2463.json b/mne-python/source/doc/sphinxext/prs/2463.json new file mode 100644 index 0000000000000000000000000000000000000000..9e99a5d1d80f4ca28663b3215fb45112fcded087 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2463.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "199341c8017cf8a90593157de627997cd6cba691", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/beamformer/_dics.py": { + "a": 13, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2466.json b/mne-python/source/doc/sphinxext/prs/2466.json new file mode 100644 index 0000000000000000000000000000000000000000..7174c8dc51874467faf3f68b2ef351dd5da259ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2466.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c9e0b402b6519af499a030ca360242d11102f299", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 221, + "d": 98 + }, + "mne/io/tag.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 132, + "d": 94 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2468.json b/mne-python/source/doc/sphinxext/prs/2468.json new file mode 100644 index 0000000000000000000000000000000000000000..f63388045ad638b3e49c374a2a22aae587906317 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2468.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "28009f687074bc8e794fe4b20ff1365f99a34f2d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/dipole.py": { + "a": 145, + "d": 40 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 8, + "d": 4 + }, + "mne/tests/test_dipole.py": { + "a": 54, + "d": 17 + }, + "mne/transforms.py": { + "a": 19, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/247.json b/mne-python/source/doc/sphinxext/prs/247.json new file mode 100644 index 0000000000000000000000000000000000000000..2c5f20894838686edff4216d17a766ea34715680 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/247.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "4f9eae9c70f9385ccfc08fb8a5bc25df634560aa", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 5, + "d": 0 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 10, + "d": 7 + }, + "mne/fiff/tests/test_raw.py": { + "a": 21, + "d": 17 + }, + "mne/layouts/tests/test_layout.py": { + "a": 11, + "d": 6 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 7, + "d": 4 + }, + "mne/tests/test_cov.py": { + "a": 18, + "d": 11 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 6 + }, + "mne/tests/test_event.py": { + "a": 19, + "d": 16 + }, + "mne/tests/test_label.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 10, + "d": 5 + }, + "mne/tests/test_source_estimate.py": { + "a": 8, + "d": 5 + }, + "mne/tests/test_source_space.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2473.json b/mne-python/source/doc/sphinxext/prs/2473.json new file mode 100644 index 0000000000000000000000000000000000000000..e98edbd8f160181846e40bf092aa393d9c8b0631 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2473.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "31057cbd1893c14b111867d4d0bcb7d89de6fd83", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 154, + "d": 114 + }, + "mne/io/bti/constants.py": { + "a": 2, + "d": 10 + }, + "mne/io/bti/read.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 19, + "d": 3 + }, + "mne/io/bti/transforms.py": { + "a": 0, + "d": 102 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 17 + }, + "mne/io/meas_info.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2474.json b/mne-python/source/doc/sphinxext/prs/2474.json new file mode 100644 index 0000000000000000000000000000000000000000..3363d4df81008a8c84f321c00b3a10aa43e5c097 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2474.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1feddd90039aba4a34c9eaed5fb1de0042573fdd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2475.json b/mne-python/source/doc/sphinxext/prs/2475.json new file mode 100644 index 0000000000000000000000000000000000000000..74c7862451ea9d2642f3d5fc7835ce4ab588369d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2475.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "55f13faf86167ea6c823c3f6fbf69e682a71431a", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 22, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 23, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2477.json b/mne-python/source/doc/sphinxext/prs/2477.json new file mode 100644 index 0000000000000000000000000000000000000000..ddc4853bc3393b2bbe7110fd6886997ef67f3ae7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2477.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "98c69aea01a7e33987ff9ef49f88c33ef962a77a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "examples/forward/plot_coregistration_transform.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 2, + "d": 5 + }, + "mne/dipole.py": { + "a": 2, + "d": 4 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 6 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 8 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 3, + "d": 4 + }, + "mne/gui/_coreg_gui.py": { + "a": 2, + "d": 6 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 3, + "d": 5 + }, + "mne/io/bti/bti.py": { + "a": 12, + "d": 24 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 5 + }, + "mne/io/tag.py": { + "a": 6, + "d": 8 + }, + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 11 + }, + "mne/source_space.py": { + "a": 9, + "d": 20 + }, + "mne/surface.py": { + "a": 17, + "d": 5 + }, + "mne/tests/test_bem.py": { + "a": 2, + "d": 6 + }, + "mne/tests/test_transforms.py": { + "a": 13, + "d": 9 + }, + "mne/transforms.py": { + "a": 122, + "d": 54 + }, + "mne/viz/_3d.py": { + "a": 103, + "d": 47 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2479.json b/mne-python/source/doc/sphinxext/prs/2479.json new file mode 100644 index 0000000000000000000000000000000000000000..29ab8d2e95d8d6e4b3da9d309a4b49493ba6f553 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2479.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "618a736bf8c9c362ae01381d1a459338592eb9ed", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 28, + "d": 23 + }, + "mne/tests/test_bem.py": { + "a": 40, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2480.json b/mne-python/source/doc/sphinxext/prs/2480.json new file mode 100644 index 0000000000000000000000000000000000000000..c418a0602d814d14c1bcbc049e796f3c5d0336aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2480.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9e0976aa0b6d0c1ec928410ce1de5e943b2ced98", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 84, + "d": 47 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 108, + "d": 49 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2481.json b/mne-python/source/doc/sphinxext/prs/2481.json new file mode 100644 index 0000000000000000000000000000000000000000..9f8e7f95dd0f1362e66fa87a5d539215e69c47e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2481.json @@ -0,0 +1,151 @@ +{ + "merge_commit_sha": "b7ccda04c0897622c4cc0892af9f3e6e7e29a252", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 4, + "d": 2 + }, + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 20, + "d": 30 + }, + "examples/simulation/plot_simulate_raw_data.py": { + "a": 79, + "d": 0 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 3, + "d": 4 + }, + "mne/bem.py": { + "a": 44, + "d": 19 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 2 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/forward/__init__.py": { + "a": 5, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 115, + "d": 108 + }, + "mne/forward/forward.py": { + "a": 32, + "d": 15 + }, + "mne/forward/tests/test_forward.py": { + "a": 2, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/array/array.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ssp.py": { + "a": 3, + "d": 6 + }, + "mne/simulation/__init__.py": { + "a": 6, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 90, + "d": 11 + }, + "mne/simulation/metrics.py": { + "a": 68, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 571, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 131, + "d": 2 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 17, + "d": 25 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 52, + "d": 0 + }, + "mne/simulation/tests/test_raw.py": { + "a": 234, + "d": 0 + }, + "mne/simulation/tests/test_source.py": { + "a": 23, + "d": 47 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_bem.py": { + "a": 9, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 28, + "d": 0 + }, + "mne/time_frequency/ar.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 5, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2483.json b/mne-python/source/doc/sphinxext/prs/2483.json new file mode 100644 index 0000000000000000000000000000000000000000..4fb9260767b6f22953c7d8e3d6f2f40db3a5773f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2483.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "717276880a1b66e12f52cd85270697a53d125b16", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/time_gen.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2484.json b/mne-python/source/doc/sphinxext/prs/2484.json new file mode 100644 index 0000000000000000000000000000000000000000..e146229e68ba251bd7c80a50104cfe20277fcdfe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2484.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3125f6ef834a1796afc2fbb6b3805166751ae831", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "mne/stats/parametric.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2485.json b/mne-python/source/doc/sphinxext/prs/2485.json new file mode 100644 index 0000000000000000000000000000000000000000..b7d79663408e05ca81378c3b14193b51b0553c8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2485.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1aca4fd960624e40e3ce2b2d8505979cffa42360", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2487.json b/mne-python/source/doc/sphinxext/prs/2487.json new file mode 100644 index 0000000000000000000000000000000000000000..24389d6c264384ea240c398aa019f9e3f1f96835 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2487.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1df96993b84bcd553adc46ecaf2aabf662096ddf", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 262, + "d": 207 + }, + "mne/io/bti/read.py": { + "a": 44, + "d": 51 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 34, + "d": 2 + }, + "mne/io/tag.py": { + "a": 5, + "d": 4 + }, + "mne/io/tree.py": { + "a": 1, + "d": 2 + }, + "mne/realtime/client.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2488.json b/mne-python/source/doc/sphinxext/prs/2488.json new file mode 100644 index 0000000000000000000000000000000000000000..b9361f387cf7201dc3836c461fe615133beae74a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2488.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4d3b24e598b56dc72fa46974603f4d0e724da4bd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 64, + "d": 48 + }, + "mne/minimum_norm/inverse.py": { + "a": 6, + "d": 5 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 15, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 13 + }, + "mne/utils.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2492.json b/mne-python/source/doc/sphinxext/prs/2492.json new file mode 100644 index 0000000000000000000000000000000000000000..28798b2bd4e9396100709b51e3ff10b1f27839f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2492.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9571df483a7624fa700ed7542350eb9de518df93", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ecg.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/eog.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2495.json b/mne-python/source/doc/sphinxext/prs/2495.json new file mode 100644 index 0000000000000000000000000000000000000000..e272da9177e7acc1661059b502954db10ad932ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2495.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "e3938f170f3d682398e51c7fc97d1a6f3391c65b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/manual/cookbook.rst": { + "a": 3, + "d": 3 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_estimate_covariance_matrix_raw.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 2, + "d": 2 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 14, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2496.json b/mne-python/source/doc/sphinxext/prs/2496.json new file mode 100644 index 0000000000000000000000000000000000000000..097329a2852335f4505ac17515a0b91d77eedcb0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2496.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d9ec048f2eb6cd57d89e7b168be1acb4c1d81111", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/tag.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2498.json b/mne-python/source/doc/sphinxext/prs/2498.json new file mode 100644 index 0000000000000000000000000000000000000000..2873812df3b62bd07b2e63c70e97073e6fc2f685 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2498.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "337587fc9bf729837aac65896fedebacf99825fd", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 8, + "d": 8 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2499.json b/mne-python/source/doc/sphinxext/prs/2499.json new file mode 100644 index 0000000000000000000000000000000000000000..12be2660bd7f3fc9e163330931169b74ecde8ce2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2499.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "a8172e6432632bd442c43b75f1da91474228a36e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/chpi.py": { + "a": 428, + "d": 0 + }, + "mne/forward/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 6, + "d": 2 + }, + "mne/forward/_field_interpolation.py": { + "a": 8, + "d": 8 + }, + "mne/forward/_make_forward.py": { + "a": 40, + "d": 56 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 2, + "d": 4 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 45, + "d": 1 + }, + "mne/io/chpi.py": { + "a": 0, + "d": 133 + }, + "mne/io/constants.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 5 + }, + "mne/io/tests/test_chpi.py": { + "a": 0, + "d": 78 + }, + "mne/simulation/raw.py": { + "a": 18, + "d": 39 + }, + "mne/simulation/tests/test_raw.py": { + "a": 21, + "d": 11 + }, + "mne/tests/test_chpi.py": { + "a": 165, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 5, + "d": 13 + }, + "mne/transforms.py": { + "a": 9, + "d": 5 + }, + "mne/utils.py": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/25.json b/mne-python/source/doc/sphinxext/prs/25.json new file mode 100644 index 0000000000000000000000000000000000000000..021eead97ecafc3f65cf2211ba753f9b4be4cd13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/25.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ea471e0c297cef2804458d1120363845597e40ff", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 5, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/write.py": { + "a": 22, + "d": 0 + }, + "mne/surface.py": { + "a": 53, + "d": 8 + }, + "mne/tests/test_surface.py": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/250.json b/mne-python/source/doc/sphinxext/prs/250.json new file mode 100644 index 0000000000000000000000000000000000000000..f2ff3a17bc6c15908bf4a5df1b2ed40a59e414e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/250.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f317eb64a253949145769420bdc9588c8d18b37e", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/sphinxext/gen_rst.py": { + "a": 182, + "d": 52 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2501.json b/mne-python/source/doc/sphinxext/prs/2501.json new file mode 100644 index 0000000000000000000000000000000000000000..0bc3b6ef2182b226b40a6e5f12b60e6268735df0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2501.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "127c85d90614aafbd3e10453ee62ffbb481cbd0b", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 25, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2503.json b/mne-python/source/doc/sphinxext/prs/2503.json new file mode 100644 index 0000000000000000000000000000000000000000..cd91f5a6be9d120796b2a48aa6688095583eae0f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2503.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ac10457e321d67fe9933b49e85f5686298c68afa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 37, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 26, + "d": 0 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 27, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2504.json b/mne-python/source/doc/sphinxext/prs/2504.json new file mode 100644 index 0000000000000000000000000000000000000000..93f8d4340eaf7d546831d4523941dd42c700a047 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2504.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e24e720801842286c058f89a97a7cee35414c3a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2508.json b/mne-python/source/doc/sphinxext/prs/2508.json new file mode 100644 index 0000000000000000000000000000000000000000..30908978ab63c9ec39bc31ef5aedc723c3870fb6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2508.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "533e718d389c1c6a12b22c138dbc725be0746ff1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/manual/cookbook.rst": { + "a": 8, + "d": 0 + }, + "mne/bem.py": { + "a": 5, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2510.json b/mne-python/source/doc/sphinxext/prs/2510.json new file mode 100644 index 0000000000000000000000000000000000000000..b6fd7e6cf2cac7ddefebd8b2c28211ef0cfca110 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2510.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bdbddab75d233055722afb6abe90e07f17dd7eb6", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/kit/constants.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2512.json b/mne-python/source/doc/sphinxext/prs/2512.json new file mode 100644 index 0000000000000000000000000000000000000000..42d15ea72a2d313455ec2292f71c64d1de2aaa00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2512.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "511a6293a0c9da989f0a039c67edc03be2cf947d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 55, + "d": 27 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 40, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2513.json b/mne-python/source/doc/sphinxext/prs/2513.json new file mode 100644 index 0000000000000000000000000000000000000000..d1120414410cd81416a6094b78fae6b06c33eed7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2513.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2e1f390e328fe71d93948a3d55cda66793da373a", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2514.json b/mne-python/source/doc/sphinxext/prs/2514.json new file mode 100644 index 0000000000000000000000000000000000000000..74c67ef3afa9c7b6b09abf089aca12283b182a21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2514.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "936dce4d46f9de1c91a3f5b6836d81c1039d9dbe", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_evoked_erf_erp.py": { + "a": 3, + "d": 0 + }, + "mne/evoked.py": { + "a": 4, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 82, + "d": 5 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2515.json b/mne-python/source/doc/sphinxext/prs/2515.json new file mode 100644 index 0000000000000000000000000000000000000000..ef1f615d4f0a9e7668e7ebd7c5be7cb7f30b01ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2515.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "589a1c9e8990178b26c7babb548c392979efaf51", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2516.json b/mne-python/source/doc/sphinxext/prs/2516.json new file mode 100644 index 0000000000000000000000000000000000000000..703d242519dfb420ea2c37c329cc52dcb7dc2e1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2516.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d6eecdfcf402d2787fd0520f4a09049a214f7dcf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 14, + "d": 4 + }, + "mne/io/base.py": { + "a": 10, + "d": 7 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 2, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 29, + "d": 9 + }, + "mne/simulation/tests/test_raw.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2517.json b/mne-python/source/doc/sphinxext/prs/2517.json new file mode 100644 index 0000000000000000000000000000000000000000..287f01bb6a580437198e6fd6f3a250887cd6d19f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2517.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2dd9b435be5c44d141ed0ace4fc9783dc378bd57", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 120, + "d": 250 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 13, + "d": 12 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/252.json b/mne-python/source/doc/sphinxext/prs/252.json new file mode 100644 index 0000000000000000000000000000000000000000..1f1cbff7af6b5e0a3603b3bfcb361faa60f918c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/252.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "8bd48a05148f52ed235781d278400c5640ea7c6d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 13, + "d": 1 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 73, + "d": 0 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 3, + "d": 2 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 170, + "d": 23 + }, + "mne/fiff/evoked.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 56, + "d": 5 + }, + "mne/viz.py": { + "a": 18, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2522.json b/mne-python/source/doc/sphinxext/prs/2522.json new file mode 100644 index 0000000000000000000000000000000000000000..52a2baff82b1c32d1347709c6b5560a2d2b71552 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2522.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "92a0c5f1bdb1cfea779229a054f3691bfd6c024b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 14 + }, + "mne/label.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 3 + }, + "mne/simulation/source.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 60 + }, + "mne/source_space.py": { + "a": 142, + "d": 17 + }, + "mne/surface.py": { + "a": 62, + "d": 7 + }, + "mne/tests/test_source_space.py": { + "a": 16, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 20, + "d": 1 + }, + "mne/utils.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2525.json b/mne-python/source/doc/sphinxext/prs/2525.json new file mode 100644 index 0000000000000000000000000000000000000000..ff41a76d04c11c8645a7746158d8401b180890ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2525.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "95f3a68ec4f967c5d76b53bfd9be752f778d401a", + "authors": [ + { + "n": "jona-sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2526.json b/mne-python/source/doc/sphinxext/prs/2526.json new file mode 100644 index 0000000000000000000000000000000000000000..195c0c0c1d47f4de4b6d9aa87969f85fee50695b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2526.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8cd93206924b9971e4ef0cf24161d7f426cc53ac", + "authors": [ + { + "n": "jona-sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 5, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 16, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 32, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2527.json b/mne-python/source/doc/sphinxext/prs/2527.json new file mode 100644 index 0000000000000000000000000000000000000000..e1d0e073d688a28543181c7c680b38f23ec2b3cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2527.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9019cc469a1500125e80e393bb978ab319cd91c1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 10, + "d": 6 + }, + "mne/stats/regression.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2528.json b/mne-python/source/doc/sphinxext/prs/2528.json new file mode 100644 index 0000000000000000000000000000000000000000..503f81f0bdd3cfdb8be2574708cae3522487d477 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2528.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "d44b98154806443f89984b3dff81f066c12cf6a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 0, + "d": 1 + }, + "mne/channels/tests/test_layout.py": { + "a": 2, + "d": 8 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 6 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 7, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 3 + }, + "mne/io/bti/bti.py": { + "a": 31, + "d": 39 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 8, + "d": 8 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/egi/egi.py": { + "a": 0, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 0, + "d": 3 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 0, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/reference.py": { + "a": 0, + "d": 3 + }, + "mne/io/tag.py": { + "a": 27, + "d": 25 + }, + "mne/io/tests/test_meas_info.py": { + "a": 27, + "d": 14 + }, + "mne/io/tests/test_reference.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 3 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 0, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 3 + }, + "mne/viz/tests/test_topomap.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2529.json b/mne-python/source/doc/sphinxext/prs/2529.json new file mode 100644 index 0000000000000000000000000000000000000000..844e8417b576c857e7dfbc28d83ae289dc8c2a93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2529.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1acce09eba5f275f67508acd2ad308db6e2fdf8f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_compare_fiff.py": { + "a": 27, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 7, + "d": 1 + }, + "mne/commands/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 8, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2531.json b/mne-python/source/doc/sphinxext/prs/2531.json new file mode 100644 index 0000000000000000000000000000000000000000..7f1df71fe719b65819f5720dd589ca5b990f4a47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2531.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "60f16dfc4e254e0cbd89e4a6bd9fdacd47fe98f0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/connectivity/tests/test_spectral.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2536.json b/mne-python/source/doc/sphinxext/prs/2536.json new file mode 100644 index 0000000000000000000000000000000000000000..76c39c058ea560a0aae1099f5316941fef6525e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2536.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "738918db1a06444e642c98d19d7351bf1e5a5812", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/time_gen.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2538.json b/mne-python/source/doc/sphinxext/prs/2538.json new file mode 100644 index 0000000000000000000000000000000000000000..46d7e7a9e327110aa22383c59fa84c7fd6c804cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2538.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8aa412c21d6d445d5585f349511c5bb293174d63", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 5, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 33, + "d": 7 + }, + "mne/viz/tests/test_evoked.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2541.json b/mne-python/source/doc/sphinxext/prs/2541.json new file mode 100644 index 0000000000000000000000000000000000000000..52690563d916aa249ef0ca9ea75d60255e21eb22 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2541.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "aa274d59ed5b71ee5e408cc9f8f2f2305d5a7e58", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/report.py": { + "a": 19, + "d": 3 + }, + "mne/tests/test_report.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2542.json b/mne-python/source/doc/sphinxext/prs/2542.json new file mode 100644 index 0000000000000000000000000000000000000000..2d1ccbd9af4df369f09910b73d76bdba2ad50def --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2542.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d961a1223e3209a3be9708ec29f41ad3d4cd9cfd", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/index.rst": { + "a": 22, + "d": 22 + }, + "logo/generate_mne_logos.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_epochs_objects.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2545.json b/mne-python/source/doc/sphinxext/prs/2545.json new file mode 100644 index 0000000000000000000000000000000000000000..0f60cb896b86808873d4e6c14e2720c416886b48 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2545.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b07c80fcfe44b57d53a2e4c3ff3ed35db94c90ff", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/forward/plot_source_space_morphing.py": { + "a": 68, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 23, + "d": 8 + }, + "mne/source_estimate.py": { + "a": 37, + "d": 1 + }, + "mne/source_space.py": { + "a": 134, + "d": 37 + }, + "mne/tests/test_source_space.py": { + "a": 64, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2546.json b/mne-python/source/doc/sphinxext/prs/2546.json new file mode 100644 index 0000000000000000000000000000000000000000..7f6a06f0f2bfe05f3b005f914ff912f4525be924 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2546.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "1882f87647c0a87d22f5ed1c5af9f79a75f8dbc7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 3, + "d": 1 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/source.py": { + "a": 3, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 3, + "d": 3 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_import_nesting.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 5, + "d": 6 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 4, + "d": 4 + }, + "mne/utils.py": { + "a": 16, + "d": 35 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2549.json b/mne-python/source/doc/sphinxext/prs/2549.json new file mode 100644 index 0000000000000000000000000000000000000000..03edc16c3e92336a817890b9837489375bf83af0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2549.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f5dd1b5694bb42a974b8988a574f9dc741c7c77f", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 22, + "d": 21 + }, + "mne/forward/tests/test_forward.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2551.json b/mne-python/source/doc/sphinxext/prs/2551.json new file mode 100644 index 0000000000000000000000000000000000000000..830259b91cb8711edd5b31fc703533b5b5a91b28 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2551.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "cc3b95b5bf7fced80f5e3d911c52073a37fd0bfd", + "authors": [ + { + "n": "kingjr", + "e": "jeanremi.king+github@gmail.com" + } + ], + "changes": { + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/tests/test_utils.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 9, + "d": 13 + }, + "mne/evoked.py": { + "a": 14, + "d": 8 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 5, + "d": 4 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 5, + "d": 3 + }, + "mne/io/pick.py": { + "a": 9, + "d": 0 + }, + "mne/stats/tests/test_parametric.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 41, + "d": 15 + }, + "mne/tests/test_filter.py": { + "a": 7, + "d": 8 + }, + "mne/tests/test_fixes.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 7, + "d": 6 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_surface.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_transforms.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_utils.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2552.json b/mne-python/source/doc/sphinxext/prs/2552.json new file mode 100644 index 0000000000000000000000000000000000000000..dc07a0efff21f7c86bd22c4fea880f572300f779 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2552.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e29410ec4522d6b245121523939c0a721d40f272", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/proj.py": { + "a": 12, + "d": 8 + }, + "mne/tests/test_proj.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2554.json b/mne-python/source/doc/sphinxext/prs/2554.json new file mode 100644 index 0000000000000000000000000000000000000000..13586ba30a3ce34c3c5bb643d8e7325f0c96a8df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2554.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "7a1f14015cf0dc2ceac5c0d61a3f3be47eb9e6cf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/__init__.py": { + "a": 3, + "d": 4 + }, + "mne/bem.py": { + "a": 1, + "d": 21 + }, + "mne/commands/mne_flash_bem_model.py": { + "a": 0, + "d": 145 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 7 + }, + "mne/cov.py": { + "a": 0, + "d": 11 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 0, + "d": 6 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 7 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 28 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 6 + }, + "mne/io/__init__.py": { + "a": 0, + "d": 45 + }, + "mne/io/base.py": { + "a": 1, + "d": 23 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 25 + }, + "mne/simulation/__init__.py": { + "a": 2, + "d": 4 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 69 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 110 + }, + "mne/stats/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/stats/parametric.py": { + "a": 0, + "d": 22 + }, + "mne/tests/test_dipole.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 37 + }, + "mne/transforms.py": { + "a": 1, + "d": 126 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 13 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 4 + }, + "mne/viz/tests/test_topo.py": { + "a": 6, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 73 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2559.json b/mne-python/source/doc/sphinxext/prs/2559.json new file mode 100644 index 0000000000000000000000000000000000000000..4c5df19a6d86ac20d1bc87c96c2a9b06f0d8520e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2559.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "07ca1676c051097a527cbfe838f0267fe038b342", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 7, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/256.json b/mne-python/source/doc/sphinxext/prs/256.json new file mode 100644 index 0000000000000000000000000000000000000000..001b7b36d0101b13a842320159a9f9eb98fedc40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/256.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6ea3a4bf583025b494734c18628a43c06a074660", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 2, + "d": 1 + }, + "mne/fixes.py": { + "a": 146, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2560.json b/mne-python/source/doc/sphinxext/prs/2560.json new file mode 100644 index 0000000000000000000000000000000000000000..bf70429efeb2bda29c11a5965fb3e3f77b531302 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2560.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ba09bd44757771c447c4e3a7fcd0f763e83a8069", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 53, + "d": 44 + }, + "mne/viz/ica.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2562.json b/mne-python/source/doc/sphinxext/prs/2562.json new file mode 100644 index 0000000000000000000000000000000000000000..550d80fa6ef7609b343feed5b807dcc285997e8a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2562.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bb26e23f7d4b73064edd6b7380a18eb3c191bcb4", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "examples/visualization/plot_clickable_image.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_topography.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2565.json b/mne-python/source/doc/sphinxext/prs/2565.json new file mode 100644 index 0000000000000000000000000000000000000000..65c9a4dbe9d88f0180c790e8ee19a4f2cbd1f562 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2565.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a6fa7fea3690137731b87cbce79a3c3cf0826c01", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/evoked.py": { + "a": 8, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2566.json b/mne-python/source/doc/sphinxext/prs/2566.json new file mode 100644 index 0000000000000000000000000000000000000000..57ec1884e1cb104b130b8af4d73fce9a57114277 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2566.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c91495a07f04b66a4cffbfecf918ad0a9dff51e3", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "examples/visualization/plot_clickable_image.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_topography.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2569.json b/mne-python/source/doc/sphinxext/prs/2569.json new file mode 100644 index 0000000000000000000000000000000000000000..3892ce73bde635345cfc6af1a62ebcbef3f09e76 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2569.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9253da5c7b3ddfd7f44a0250a1c8b43109ad480d", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/__init__.py": { + "a": 2, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 27, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 61, + "d": 0 + }, + "mne/utils.py": { + "a": 73, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/257.json b/mne-python/source/doc/sphinxext/prs/257.json new file mode 100644 index 0000000000000000000000000000000000000000..fde40a9f027854e47a1eca7c4179e3e8d731375a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/257.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "dd0734b483bafa8143bfe7ac41fa705f574267ed", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 1, + "d": 2 + }, + "mne/fixes.py": { + "a": 165, + "d": 2 + }, + "mne/tests/test_fixes.py": { + "a": 17, + "d": 0 + }, + "mne/tests/test_utils.py": { + "a": 2, + "d": 12 + }, + "mne/utils.py": { + "a": 0, + "d": 157 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2570.json b/mne-python/source/doc/sphinxext/prs/2570.json new file mode 100644 index 0000000000000000000000000000000000000000..46b44e10fe762f48f488452319b5b31e97bb4eac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2570.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a26590ffb4fc8691e11133f52b1b00f296a55535", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "examples/visualization/plot_clickable_image.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2571.json b/mne-python/source/doc/sphinxext/prs/2571.json new file mode 100644 index 0000000000000000000000000000000000000000..69bd54fd2f73b284ccbf17253189c37f63f75aa3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2571.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f558693d683005b1d3b8b4b900b8af167bf0f1ea", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "examples/visualization/plot_clickable_image.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2573.json b/mne-python/source/doc/sphinxext/prs/2573.json new file mode 100644 index 0000000000000000000000000000000000000000..ecc98afb8894b8707a756482c1d210a57f95049b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2573.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "62df47fef6a385d4ce6b8f88e3908f126c795f11", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/io/base.py": { + "a": 61, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 81, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2576.json b/mne-python/source/doc/sphinxext/prs/2576.json new file mode 100644 index 0000000000000000000000000000000000000000..1f0118b9b34989d8e6079397c477b12bac2d1cf3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2576.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "03d01bcb6dc629d4d4dd80dad4add66bce322f57", + "authors": [ + { + "n": "Deleted user", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2578.json b/mne-python/source/doc/sphinxext/prs/2578.json new file mode 100644 index 0000000000000000000000000000000000000000..611cfa6c87510b348c48f2af74a80b799572d693 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2578.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "37ffe6236e71dafc6d44422ddf1b5b2d0fdbfaa8", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/topo.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2580.json b/mne-python/source/doc/sphinxext/prs/2580.json new file mode 100644 index 0000000000000000000000000000000000000000..78ab01f37651e018279c0a2e90e9bd60e8039d21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2580.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "e6ec06975cb5be82e0daa1c828ba41f406cf3287", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "appveyor.yml": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_fiducials_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_file_traits.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_help.py": { + "a": 16, + "d": 0 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 102, + "d": 49 + }, + "mne/gui/_marker_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_viewer.py": { + "a": 1, + "d": 1 + }, + "mne/gui/help/kit2fiff.json": { + "a": 7, + "d": 0 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 16, + "d": 6 + }, + "mne/io/kit/constants.py": { + "a": 27, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 52, + "d": 30 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 25, + "d": 1 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2586.json b/mne-python/source/doc/sphinxext/prs/2586.json new file mode 100644 index 0000000000000000000000000000000000000000..7990bc3253a6d83e37884e4c18a29fa3ec5575a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2586.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "20cfc04ef77c4d2184cc17b7ea8d66c910b51db0", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 263, + "d": 226 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2588.json b/mne-python/source/doc/sphinxext/prs/2588.json new file mode 100644 index 0000000000000000000000000000000000000000..207440a8bb8df69bf284e9a9f6d838358fa18856 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2588.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7fb6fc02a7542ad5d246dc9c458ab3041f85db22", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "appveyor.yml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/259.json b/mne-python/source/doc/sphinxext/prs/259.json new file mode 100644 index 0000000000000000000000000000000000000000..5bcb852645e735fd9f21c466ed82556cd97ef943 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/259.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "faf8db5da525ffbe919a680637b00e021ff34c27", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fixes.py": { + "a": 13, + "d": 145 + }, + "mne/tests/test_fixes.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2590.json b/mne-python/source/doc/sphinxext/prs/2590.json new file mode 100644 index 0000000000000000000000000000000000000000..1cfe97861b10f86890906c8bb66f2394032e0067 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2590.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "6414329f73fbe96d5d2bd7878535b80c9d12e160", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 7, + "d": 1 + }, + "examples/preprocessing/plot_maxwell_filter.py": { + "a": 45, + "d": 0 + }, + "mne/evoked.py": { + "a": 5, + "d": 2 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 378, + "d": 111 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 186, + "d": 43 + }, + "mne/viz/evoked.py": { + "a": 8, + "d": 3 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/26.json b/mne-python/source/doc/sphinxext/prs/26.json new file mode 100644 index 0000000000000000000000000000000000000000..b72ff84a7149ee0d89cfc33f57bb13430d57348d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/26.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0e12d7806d0cc11766928c2bff648de67ae93065", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "bin/mne_surf2bem.py": { + "a": 34, + "d": 0 + }, + "mne/surface.py": { + "a": 3, + "d": 2 + }, + "setup.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/260.json b/mne-python/source/doc/sphinxext/prs/260.json new file mode 100644 index 0000000000000000000000000000000000000000..f2eb8bfded66b5f5b0471cc7b8b4168f5dcf7c3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/260.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c92cc436f72f70fc572078c553aebe502d2755ed", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2601.json b/mne-python/source/doc/sphinxext/prs/2601.json new file mode 100644 index 0000000000000000000000000000000000000000..2398e105abe55a43a4db00df3b2c97267f7e5651 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2601.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cd0f9771588da97e9eba8454076c1642ce592aef", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 6, + "d": 10 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2605.json b/mne-python/source/doc/sphinxext/prs/2605.json new file mode 100644 index 0000000000000000000000000000000000000000..d683e0be2db26f220675421e2ef858417f465eef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2605.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "5832f7ac715d29bb65a4fdf5ea19dee280f4ffe8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 6, + "d": 6 + }, + "doc/sphinxext/numpy_ext/docscrape.py": { + "a": 3, + "d": 2 + }, + "mne/connectivity/spectral.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 13, + "d": 7 + }, + "mne/fixes.py": { + "a": 25, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 8 + }, + "mne/parallel.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 4 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/epochs.py": { + "a": 2, + "d": 5 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2607.json b/mne-python/source/doc/sphinxext/prs/2607.json new file mode 100644 index 0000000000000000000000000000000000000000..b890182036a7ebbf67ae22f17ef9794d6d94710a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2607.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "98fff46f59c371ae1332a302c853b0a7bba48409", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 48, + "d": 8 + }, + "mne/preprocessing/ica.py": { + "a": 43, + "d": 21 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 25, + "d": 6 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 73, + "d": 9 + }, + "mne/viz/tests/test_ica.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/261.json b/mne-python/source/doc/sphinxext/prs/261.json new file mode 100644 index 0000000000000000000000000000000000000000..f0dfd1e58399db356488f60dd2a8a213e8044039 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/261.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1227d06512040eb43baf344d61d1f52e981896ad", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 14, + "d": 3 + }, + "mne/proj.py": { + "a": 19, + "d": 10 + }, + "mne/tests/test_cov.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2610.json b/mne-python/source/doc/sphinxext/prs/2610.json new file mode 100644 index 0000000000000000000000000000000000000000..b49c3055feb90a1e2f6c112f41a0645c94b13e5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2610.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6bf5cd02b8ea599dd59d33ec201ebe00d06e4157", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2612.json b/mne-python/source/doc/sphinxext/prs/2612.json new file mode 100644 index 0000000000000000000000000000000000000000..8160863c87040b75234422f70ad91d28473bc8e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2612.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8c5281c874799a9ceee53fd0ed5592e4e025f35b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 1 + }, + "mne/report.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2617.json b/mne-python/source/doc/sphinxext/prs/2617.json new file mode 100644 index 0000000000000000000000000000000000000000..2bd2e06ca3fa9976f84996f204e8b03f2e998b31 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2617.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5a47387e604a430504278e94938903267849e53c", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 10, + "d": 10 + }, + "mne/decoding/time_gen.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2618.json b/mne-python/source/doc/sphinxext/prs/2618.json new file mode 100644 index 0000000000000000000000000000000000000000..4f6622148fce086d74478910892c95acba3acdab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2618.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2b1dbbb1dfcc31983adf3873d6c8ef20bbf2df8c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_report.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/262.json b/mne-python/source/doc/sphinxext/prs/262.json new file mode 100644 index 0000000000000000000000000000000000000000..7782019ce0373ea122b3585cd7e8f3011d79cc99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/262.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "506de4178e251ec0a6febccbdf8a1fc3b5abce1b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/export/plot_epochs_as_data_frame.py": { + "a": 140, + "d": 56 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 4 + }, + "mne/epochs.py": { + "a": 79, + "d": 22 + }, + "mne/fiff/evoked.py": { + "a": 67, + "d": 0 + }, + "mne/fiff/raw.py": { + "a": 75, + "d": 7 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 21, + "d": 1 + }, + "mne/fiff/tests/test_raw.py": { + "a": 18, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 21, + "d": 1 + }, + "mne/viz.py": { + "a": 33, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2620.json b/mne-python/source/doc/sphinxext/prs/2620.json new file mode 100644 index 0000000000000000000000000000000000000000..7a3d9cc90d0b2919458748a06bdb6526a98aab16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2620.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5cbc2b03e0287fba64a25fc3b8b36f9d1866ee4f", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 6, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2625.json b/mne-python/source/doc/sphinxext/prs/2625.json new file mode 100644 index 0000000000000000000000000000000000000000..915fa045ef6a26f94618cf4445811ce5cc99a1de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2625.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "94202d929aef8517edbefb69eea534998adcb8fa", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2626.json b/mne-python/source/doc/sphinxext/prs/2626.json new file mode 100644 index 0000000000000000000000000000000000000000..1d141a78e4a858202b4c6a63ffc8a53b1f3c4d04 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2626.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "5e476bb05419205b537f5eb351b4834414ac7fbc", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 4, + "d": 15 + }, + "mne/io/brainvision/brainvision.py": { + "a": 22, + "d": 36 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 9, + "d": 48 + }, + "mne/io/bti/bti.py": { + "a": 7, + "d": 2 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 5, + "d": 9 + }, + "mne/io/ctf/info.py": { + "a": 2, + "d": 7 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 3, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 71, + "d": 71 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 44, + "d": 96 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 2 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 8, + "d": 25 + }, + "mne/io/fiff/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 3 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 20, + "d": 64 + }, + "mne/io/meas_info.py": { + "a": 15, + "d": 7 + }, + "mne/io/nicolet/nicolet.py": { + "a": 7, + "d": 3 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 3, + "d": 27 + }, + "mne/io/tests/test_raw.py": { + "a": 92, + "d": 1 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2627.json b/mne-python/source/doc/sphinxext/prs/2627.json new file mode 100644 index 0000000000000000000000000000000000000000..d149e3ff1c471226ca0e4ee1e6983d2ac78670fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2627.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "073907fc72930ae0d6e0348832237b2555d278e2", + "authors": [ + { + "n": "Emily Stephen", + "e": "emilyps14@gmail.com" + } + ], + "changes": { + "doc/advanced_setup.rst": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2629.json b/mne-python/source/doc/sphinxext/prs/2629.json new file mode 100644 index 0000000000000000000000000000000000000000..3bd7ac828d057502ccccf3362e1ab4bf20677687 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2629.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b1fa700044b4519fd4ee340ec58f4f2a466b8aec", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 4 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/263.json b/mne-python/source/doc/sphinxext/prs/263.json new file mode 100644 index 0000000000000000000000000000000000000000..6e93c90b473360f46b11886cb8b3642ae097e47b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/263.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e5f8ca61b4528f920d96814861e000d8498e22cc", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 157, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 95, + "d": 4 + }, + "mne/utils.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2630.json b/mne-python/source/doc/sphinxext/prs/2630.json new file mode 100644 index 0000000000000000000000000000000000000000..d01fea0fe3d8b6526da877b36c274ed74837e5f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2630.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4371f76a94e54f3b2c8dcd672b8343d14e3d58be", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 25, + "d": 41 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2631.json b/mne-python/source/doc/sphinxext/prs/2631.json new file mode 100644 index 0000000000000000000000000000000000000000..cbce1522b3d767aee2041b5aa03df8fe242722b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2631.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "80664105f7f9ad904d9a59db5ed2cfceb191541c", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/report.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2633.json b/mne-python/source/doc/sphinxext/prs/2633.json new file mode 100644 index 0000000000000000000000000000000000000000..b8fb527af47ca4d5d868693e3107d32ee4ba9354 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2633.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b6e3de8dd409e946b044c6b4f299abe639764643", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/tests/test_report.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2634.json b/mne-python/source/doc/sphinxext/prs/2634.json new file mode 100644 index 0000000000000000000000000000000000000000..afeee745e38752517e1bdbd56c92f9c555b0e11e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2634.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4a263217d2a9d44817e992cf2dc7b1af9d3b282a", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 92, + "d": 29 + }, + "mne/io/brainvision/tests/data/test.vmrk": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/tests/data/testv2.vhdr": { + "a": 107, + "d": 0 + }, + "mne/io/brainvision/tests/data/testv2.vmrk": { + "a": 33, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2637.json b/mne-python/source/doc/sphinxext/prs/2637.json new file mode 100644 index 0000000000000000000000000000000000000000..8862d176dfb3224c8c478548df41589c3d4a00a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2637.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "e020ef1047ae0cedd8458f670eb68f47e157a83d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 5 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 8 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 6 + }, + "mne/viz/circle.py": { + "a": 2, + "d": 2 + }, + "mne/viz/decoding.py": { + "a": 4, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 13, + "d": 23 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 9 + }, + "mne/viz/ica.py": { + "a": 17, + "d": 37 + }, + "mne/viz/misc.py": { + "a": 6, + "d": 14 + }, + "mne/viz/montage.py": { + "a": 3, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 10, + "d": 16 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 9 + }, + "mne/viz/topomap.py": { + "a": 21, + "d": 27 + }, + "mne/viz/utils.py": { + "a": 13, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2640.json b/mne-python/source/doc/sphinxext/prs/2640.json new file mode 100644 index 0000000000000000000000000000000000000000..4f0c1b943338709601c28299a50ef2190022ba8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2640.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "148f918923b68051bb64677cec6715d135fd2b4f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2642.json b/mne-python/source/doc/sphinxext/prs/2642.json new file mode 100644 index 0000000000000000000000000000000000000000..729ff4aacacd56e3c1b1ee3011c2533f252cb7cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2642.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "777916e82149e8f888f972ecba8db9bc752c7206", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 3 + }, + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 2 + }, + "mne/coreg.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 5, + "d": 6 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 9 + }, + "mne/io/tests/test_pick.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 11, + "d": 11 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 347, + "d": 347 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 6 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2643.json b/mne-python/source/doc/sphinxext/prs/2643.json new file mode 100644 index 0000000000000000000000000000000000000000..8dc7b99d7f2973b80359823e450436c34506ab3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2643.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f9820d23269309da09ef44fdd3044a2c7991e9cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 38, + "d": 9 + }, + "mne/source_space.py": { + "a": 8, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 42, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/265.json b/mne-python/source/doc/sphinxext/prs/265.json new file mode 100644 index 0000000000000000000000000000000000000000..19b96a017e921c16faff9828f44c1ffb7d76688e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/265.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "cb712f48ed9829bedc535c8c507e293871429a4e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/mixed_norm/optim.py": { + "a": 6, + "d": 3 + }, + "mne/tests/test_cov.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2650.json b/mne-python/source/doc/sphinxext/prs/2650.json new file mode 100644 index 0000000000000000000000000000000000000000..f3adce86bc444a44d27161b4897754e7d0c3f729 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2650.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a430e2d551f5d47be846311836055ac09bd4f737", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 204, + "d": 31 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 24, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2651.json b/mne-python/source/doc/sphinxext/prs/2651.json new file mode 100644 index 0000000000000000000000000000000000000000..5245f8dd6871a341a9ce96ed642e1ef5dabf030e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2651.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6da9437c25c9e2595fbb21a52b7b061bca6963f0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 48, + "d": 43 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2654.json b/mne-python/source/doc/sphinxext/prs/2654.json new file mode 100644 index 0000000000000000000000000000000000000000..37152dec6259631ec7264edfc9c12f3501ec78f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2654.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2a6c549cdd40fc1cce761552649979e58d967a33", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/bem.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2656.json b/mne-python/source/doc/sphinxext/prs/2656.json new file mode 100644 index 0000000000000000000000000000000000000000..7a08bdc3dd0ff62d3cef9aec1c4b354180014412 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2656.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4cc4d6907609bd81701eacced142cc8903abc10b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/bem.py": { + "a": 20, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2657.json b/mne-python/source/doc/sphinxext/prs/2657.json new file mode 100644 index 0000000000000000000000000000000000000000..aaae934270fb5488aafdfafbd22faaf8805d54b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2657.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d4ab103133759ca7225f19708973cfa54e9a7f09", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 17, + "d": 38 + }, + "mne/tests/test_epochs.py": { + "a": 17, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2658.json b/mne-python/source/doc/sphinxext/prs/2658.json new file mode 100644 index 0000000000000000000000000000000000000000..809c72bb196d67cfc513031cf7ead3d8e5c5b208 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2658.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8360a8e3348eccdaea8da4663470c1eecd924369", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 9, + "d": 3 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2659.json b/mne-python/source/doc/sphinxext/prs/2659.json new file mode 100644 index 0000000000000000000000000000000000000000..634a963370b7dc9bfc2399dc1b86593511f9dfc2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2659.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "048923b7e4cb04197d7b7dcf566ece14674b7b22", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 3, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 24, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 4, + "d": 4 + }, + "mne/chpi.py": { + "a": 47, + "d": 8 + }, + "mne/epochs.py": { + "a": 181, + "d": 5 + }, + "mne/forward/_field_interpolation.py": { + "a": 55, + "d": 44 + }, + "mne/forward/_lead_dots.py": { + "a": 67, + "d": 62 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/maxwell.py": { + "a": 135, + "d": 114 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 15, + "d": 38 + }, + "mne/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/tests/common.py": { + "a": 48, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 18, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 91, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/266.json b/mne-python/source/doc/sphinxext/prs/266.json new file mode 100644 index 0000000000000000000000000000000000000000..c81208e84b530a7c122951d3f26f3158a2dcfcab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/266.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f5d90265f49e15cd3b44491d915211099bcab6b6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2666.json b/mne-python/source/doc/sphinxext/prs/2666.json new file mode 100644 index 0000000000000000000000000000000000000000..f15f994a135d642aeb5e752925ff7f577d103112 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2666.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3da3e972f404da577f59e0e36f3f0a521187c5d3", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 32, + "d": 10 + }, + "mne/decoding/tests/test_csp.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2667.json b/mne-python/source/doc/sphinxext/prs/2667.json new file mode 100644 index 0000000000000000000000000000000000000000..e7b1471254cde56cf76d5ca766beaacf29dcda39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2667.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4713411fd97d8c970fd38bc79481198f62115ba9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/evoked.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2668.json b/mne-python/source/doc/sphinxext/prs/2668.json new file mode 100644 index 0000000000000000000000000000000000000000..558adeea46c7840c913d3423283bb375fb36510c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2668.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "c1b029af86bf1304526164fa42edb3ecd7ef3be3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 3, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 10, + "d": 8 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 67, + "d": 93 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 24, + "d": 29 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 3 + }, + "mne/io/egi/egi.py": { + "a": 101, + "d": 124 + }, + "mne/io/egi/tests/data/test_egi.txt": { + "a": 257, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 27, + "d": 10 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 4 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 6 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 29, + "d": 41 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2669.json b/mne-python/source/doc/sphinxext/prs/2669.json new file mode 100644 index 0000000000000000000000000000000000000000..c9fcc1e7887b0b9cc38d6d97d182439c9c1d7e0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2669.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fb00a6e323d318349981925b0d81e4721b96d148", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 5, + "d": 4 + }, + "mne/utils.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/267.json b/mne-python/source/doc/sphinxext/prs/267.json new file mode 100644 index 0000000000000000000000000000000000000000..f61163840bddd63931f117fe3810e78fc5aadcfa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/267.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "37c378dc6ce7ed7004697b33ebcdb4670950bb2f", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2670.json b/mne-python/source/doc/sphinxext/prs/2670.json new file mode 100644 index 0000000000000000000000000000000000000000..e30bd9258229e5c6a4cb11184f0a292598d24c07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2670.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d1b9b5017e3c8c38d135bf370842bcfe4392a28b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 13, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 19, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2673.json b/mne-python/source/doc/sphinxext/prs/2673.json new file mode 100644 index 0000000000000000000000000000000000000000..560c9d103ce1b79d548a34b2b610bd3ab7f40ad1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2673.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1154c9ae04849bf011fa216b9256721dcca1a328", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_time_generalization.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 3, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 94, + "d": 34 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2675.json b/mne-python/source/doc/sphinxext/prs/2675.json new file mode 100644 index 0000000000000000000000000000000000000000..a1f9e41f8d1b643ff270a891bf77cbe529a5f98f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2675.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fc851c21f64741571b123541d212c2d5072e99f6", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2676.json b/mne-python/source/doc/sphinxext/prs/2676.json new file mode 100644 index 0000000000000000000000000000000000000000..1aec631d807b265ece5b6ccda2cb7c4a0cb2f1b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2676.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "f4ffbb42a0bd50150babd1369b65ab1cd2f565cd", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 12, + "d": 4 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 34, + "d": 5 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 5, + "d": 120 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + }, + "mne/io/eeglab/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 447, + "d": 0 + }, + "mne/io/eeglab/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 85, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 58, + "d": 61 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/io/utils.py": { + "a": 164, + "d": 0 + }, + "mne/transforms.py": { + "a": 7, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2678.json b/mne-python/source/doc/sphinxext/prs/2678.json new file mode 100644 index 0000000000000000000000000000000000000000..6718dca17b8b7c4240e2cc50a0204a0f9ce4dec0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2678.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "479e4ebfdf297022db64edd27e11d1b6d0fa00ae", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2681.json b/mne-python/source/doc/sphinxext/prs/2681.json new file mode 100644 index 0000000000000000000000000000000000000000..72ad4cb5bdbbea0673235c6472416118069711c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2681.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "91c08a85b2a4cca5ab50c0ea8b50c11d6c10cd31", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/stim.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2684.json b/mne-python/source/doc/sphinxext/prs/2684.json new file mode 100644 index 0000000000000000000000000000000000000000..bca6f2644cc3fbf22bde26bb697ff7a12909767b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2684.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0f5dd61b9f778b49b4dae1acbb7490e1086b344b", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2686.json b/mne-python/source/doc/sphinxext/prs/2686.json new file mode 100644 index 0000000000000000000000000000000000000000..da5204c3ae9468459fc13c0e8ad2d7e1b16a6bf7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2686.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "34d7e901710337a2bed38393f397a06fc9b4cefe", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/advanced_setup.rst": { + "a": 34, + "d": 5 + }, + "doc/getting_started.rst": { + "a": 3, + "d": 3 + }, + "doc/manual/datasets_index.rst": { + "a": 125, + "d": 0 + }, + "doc/manual/index.rst": { + "a": 5, + "d": 17 + }, + "doc/manual/io.rst": { + "a": 16, + "d": 2 + }, + "doc/manual/memory.rst": { + "a": 44, + "d": 0 + }, + "doc/manual/preprocessing/overview.rst": { + "a": 5, + "d": 3 + }, + "doc/manual/sample_dataset.rst": { + "a": 0, + "d": 0 + }, + "doc/tutorials/mne-report.png": { + "a": 0, + "d": 0 + }, + "doc/tutorials/report.rst": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2689.json b/mne-python/source/doc/sphinxext/prs/2689.json new file mode 100644 index 0000000000000000000000000000000000000000..141553b59877531cff925258f7c4988da75d568a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2689.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "26a3de0a18b84f01d065948839fb6f671c7f7c9f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2695.json b/mne-python/source/doc/sphinxext/prs/2695.json new file mode 100644 index 0000000000000000000000000000000000000000..de77ce0a42709200d39ba01a95614dbbf9287a7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2695.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "78771fd0ab7d1aef3fcf2e2054ce1c0bd8a4755e", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2696.json b/mne-python/source/doc/sphinxext/prs/2696.json new file mode 100644 index 0000000000000000000000000000000000000000..3e0fa08a0b90303273faa685d4da45eed9979f41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2696.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "afb8dfbc4b59f4cacdee12478c6f41085ab42d3f", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/time_gen.py": { + "a": 11, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2697.json b/mne-python/source/doc/sphinxext/prs/2697.json new file mode 100644 index 0000000000000000000000000000000000000000..b22d4ff6f8ca73be7bc956f78c2b0b9bf345ba70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2697.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e36331e399756eda0067f4a4da2dd9475c547399", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/advanced_setup.rst": { + "a": 3, + "d": 3 + }, + "doc/getting_started.rst": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 5, + "d": 2 + }, + "tutorials/plot_introduction.py": { + "a": 14, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2699.json b/mne-python/source/doc/sphinxext/prs/2699.json new file mode 100644 index 0000000000000000000000000000000000000000..109630f2b0d0ac7aa49c4e76f9dca19ef4e51728 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2699.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ddfe0714786e770af16e986c8e65f2580511a2a6", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/27.json b/mne-python/source/doc/sphinxext/prs/27.json new file mode 100644 index 0000000000000000000000000000000000000000..b4452c65ac34bf373cfdf1f89ba9f8d3f5bd54f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/27.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1694b8adbd630fcf6139a00a24dc4c0e5c3f29c1", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/fiff/raw.py": { + "a": 279, + "d": 7 + }, + "mne/fiff/tests/test_raw.py": { + "a": 72, + "d": 0 + }, + "mne/fiff/write.py": { + "a": 7, + "d": 0 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2701.json b/mne-python/source/doc/sphinxext/prs/2701.json new file mode 100644 index 0000000000000000000000000000000000000000..e26c327e834d1640bf47207ed184816630bcbdf6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2701.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "75193005557fd323e11feb7bfbf0c49de04336b3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 46, + "d": 44 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2703.json b/mne-python/source/doc/sphinxext/prs/2703.json new file mode 100644 index 0000000000000000000000000000000000000000..1cffad669f1be7fd1096b0d748c7d25f5938061f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2703.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "baa884653e918a02506eee290dbf4db14ba3a809", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 14, + "d": 2 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 22, + "d": 0 + }, + "mne/proj.py": { + "a": 8, + "d": 4 + }, + "mne/tests/test_proj.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2704.json b/mne-python/source/doc/sphinxext/prs/2704.json new file mode 100644 index 0000000000000000000000000000000000000000..5626b047b29abdd6b787fea8374cae4362189036 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2704.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "a6c1633c5802f51f94f7f0cbb23cbfc113977ee7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/manual/index.rst": { + "a": 1, + "d": 0 + }, + "doc/manual/preprocessing/maxwell.rst": { + "a": 76, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 22, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_movement_compensation.py": { + "a": 52, + "d": 0 + }, + "mne/chpi.py": { + "a": 406, + "d": 225 + }, + "mne/datasets/__init__.py": { + "a": 4, + "d": 3 + }, + "mne/datasets/misc/__init__.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/misc/_misc.py": { + "a": 18, + "d": 0 + }, + "mne/datasets/testing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 42, + "d": 32 + }, + "mne/epochs.py": { + "a": 52, + "d": 22 + }, + "mne/forward/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 3, + "d": 3 + }, + "mne/forward/_make_forward.py": { + "a": 39, + "d": 15 + }, + "mne/io/array/array.py": { + "a": 9, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 12, + "d": 4 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 478, + "d": 225 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 99, + "d": 18 + }, + "mne/simulation/raw.py": { + "a": 19, + "d": 15 + }, + "mne/simulation/tests/test_raw.py": { + "a": 7, + "d": 7 + }, + "mne/tests/common.py": { + "a": 35, + "d": 15 + }, + "mne/tests/test_chpi.py": { + "a": 68, + "d": 60 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 33, + "d": 19 + }, + "mne/tests/test_transforms.py": { + "a": 62, + "d": 3 + }, + "mne/transforms.py": { + "a": 127, + "d": 0 + }, + "mne/utils.py": { + "a": 23, + "d": 6 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2705.json b/mne-python/source/doc/sphinxext/prs/2705.json new file mode 100644 index 0000000000000000000000000000000000000000..e3ead4a9289c613e41612ef74a2ee2d5b42bb558 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2705.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c8bb2a36df34a9da29217f56e5d37a968c7ba4f5", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2707.json b/mne-python/source/doc/sphinxext/prs/2707.json new file mode 100644 index 0000000000000000000000000000000000000000..b1ba5479406aed6f2fed6e1e861b3c62b32b35ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2707.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fba74e044a732841e17b406b569ba34efa7b7dfc", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 11, + "d": 3 + }, + "mne/channels/montage.py": { + "a": 24, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2709.json b/mne-python/source/doc/sphinxext/prs/2709.json new file mode 100644 index 0000000000000000000000000000000000000000..7e87624a8a1e06fdee97dfbee784165ad28fd3c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2709.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "81546d7f2011c7495b0e00a382d74c8ffeda0fec", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 6, + "d": 3 + }, + "mne/epochs.py": { + "a": 9, + "d": 5 + }, + "mne/forward/_make_forward.py": { + "a": 62, + "d": 58 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 2, + "d": 3 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 6, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 12, + "d": 12 + }, + "mne/io/pick.py": { + "a": 33, + "d": 18 + }, + "mne/io/tests/test_pick.py": { + "a": 63, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 135, + "d": 52 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 102, + "d": 16 + }, + "mne/tests/common.py": { + "a": 27, + "d": 1 + }, + "mne/tests/test_bem.py": { + "a": 24, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/271.json b/mne-python/source/doc/sphinxext/prs/271.json new file mode 100644 index 0000000000000000000000000000000000000000..0ef1d35635ad18abb5f681ba9ea9c8b70bfa689e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/271.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "24c4a1e0f0d203c78991d7ec338d53b27e223008", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/constants.py": { + "a": 4, + "d": 6 + }, + "mne/preprocessing/ica.py": { + "a": 157, + "d": 189 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 23, + "d": 28 + }, + "mne/viz.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2710.json b/mne-python/source/doc/sphinxext/prs/2710.json new file mode 100644 index 0000000000000000000000000000000000000000..953f25e4768e0be2cf84f227c334b9715cb8b109 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2710.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "2534cdbf5f7ad55ec24848935f9712b2ec94f67d", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 2, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 6, + "d": 1 + }, + "examples/realtime/ftclient_rt_compute_psd.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 18, + "d": 1 + }, + "examples/time_frequency/plot_epochs_spectra.py": { + "a": 21, + "d": 0 + }, + "examples/visualization/plot_topo_customized.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/transformer.py": { + "a": 10, + "d": 18 + }, + "mne/epochs.py": { + "a": 43, + "d": 23 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/tests/test_raw.py": { + "a": 16, + "d": 8 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 79, + "d": 26 + }, + "mne/time_frequency/psd.py": { + "a": 256, + "d": 20 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 12, + "d": 5 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 121, + "d": 92 + }, + "mne/viz/epochs.py": { + "a": 24, + "d": 14 + }, + "mne/viz/raw.py": { + "a": 8, + "d": 9 + }, + "mne/viz/topomap.py": { + "a": 22, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2712.json b/mne-python/source/doc/sphinxext/prs/2712.json new file mode 100644 index 0000000000000000000000000000000000000000..30bd1a5a55054a076d809220ce89d1ced905fb39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2712.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "814dac7c7b6dfa93c8f79546066bd3c912baa8b8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/ctf/ctf.py": { + "a": 33, + "d": 10 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2713.json b/mne-python/source/doc/sphinxext/prs/2713.json new file mode 100644 index 0000000000000000000000000000000000000000..dfad21b084788d924462d442a5083af5c65ea8af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2713.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a8e93eca08e5c60a2ec2382fa5e3d40bd8625ce0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/stats/regression.py": { + "a": 18, + "d": 4 + }, + "mne/stats/tests/test_regression.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2714.json b/mne-python/source/doc/sphinxext/prs/2714.json new file mode 100644 index 0000000000000000000000000000000000000000..530fbf8e5bce7c2aaa142c92d7d8ba7b1beca8f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2714.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "8ed962512312b147d123cdf10b2dc818b11b81e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 3 + }, + "mne/channels/montage.py": { + "a": 117, + "d": 19 + }, + "mne/channels/tests/test_montage.py": { + "a": 53, + "d": 10 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 12, + "d": 12 + }, + "mne/io/meas_info.py": { + "a": 33, + "d": 20 + }, + "mne/tests/common.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2716.json b/mne-python/source/doc/sphinxext/prs/2716.json new file mode 100644 index 0000000000000000000000000000000000000000..5e6df916b42a0d239809e9ab5de8e712e008746f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2716.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b4bffef13ec405ff4c712bd2fef50912bb10f53a", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2717.json b/mne-python/source/doc/sphinxext/prs/2717.json new file mode 100644 index 0000000000000000000000000000000000000000..55c0eb4301626271be1642b8aba7a9e42157f7c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2717.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4a9364557efe3a124d2688848e2f47493e221558", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/this_project.inc": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 12, + "d": 5 + }, + "mne/tests/test_utils.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 93, + "d": 107 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2718.json b/mne-python/source/doc/sphinxext/prs/2718.json new file mode 100644 index 0000000000000000000000000000000000000000..29cf72e3d0c24235077c1e5abd19b894a572cb34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2718.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f7f9c9f34eaf241c2d69143d4e1c762a1baef0c4", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 26, + "d": 18 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/272.json b/mne-python/source/doc/sphinxext/prs/272.json new file mode 100644 index 0000000000000000000000000000000000000000..c6b5bf651f2e1bbef9a37eb672ef17e1f215d216 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/272.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "664c86d29f5d0f7046e2bbc68edc8ca2fc26a4e8", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 3, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 126, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 19, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 235, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 13, + "d": 6 + }, + "mne/tests/test_source_estimate.py": { + "a": 86, + "d": 2 + }, + "mne/viz.py": { + "a": 284, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2723.json b/mne-python/source/doc/sphinxext/prs/2723.json new file mode 100644 index 0000000000000000000000000000000000000000..2035606a4db0056cb5ca26edeb1eb8510bd52d44 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2723.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "792af3dd160d21d66e8c59e0da12f3d6c841372e", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 5, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2725.json b/mne-python/source/doc/sphinxext/prs/2725.json new file mode 100644 index 0000000000000000000000000000000000000000..546ab742536d666d6e9e157780ab0f3f75dc0948 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2725.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "be31d6d5523b0dcea2056c16244fc7815f0336ee", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2728.json b/mne-python/source/doc/sphinxext/prs/2728.json new file mode 100644 index 0000000000000000000000000000000000000000..ca80c0ee0fcab0b91facb1db602393c201b35577 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2728.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "821dd3d3cf866762114c905423b7b8f12ab64ead", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/contributing.rst": { + "a": 19, + "d": 3 + }, + "doc/manual/decoding.rst": { + "a": 168, + "d": 0 + }, + "doc/manual/index.rst": { + "a": 17, + "d": 1 + }, + "doc/manual/memory.rst": { + "a": 1, + "d": 0 + }, + "doc/manual/pitfalls.rst": { + "a": 27, + "d": 0 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 106, + "d": 38 + }, + "doc/python_reference.rst": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2729.json b/mne-python/source/doc/sphinxext/prs/2729.json new file mode 100644 index 0000000000000000000000000000000000000000..6bc97afccbc21ac951dec9448b576fdadff5ddaa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2729.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "51c3fc154bbc0325e8ddd447ce34040f91dc172a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/273.json b/mne-python/source/doc/sphinxext/prs/273.json new file mode 100644 index 0000000000000000000000000000000000000000..0a3a749ba86b9897a8d2fc069453d1719370618e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/273.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cd113fe0c672be244c01c9e31953e23f45348162", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 57, + "d": 71 + }, + "mne/fiff/raw.py": { + "a": 47, + "d": 17 + }, + "mne/fiff/tests/test_raw.py": { + "a": 13, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 32, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2732.json b/mne-python/source/doc/sphinxext/prs/2732.json new file mode 100644 index 0000000000000000000000000000000000000000..cb96e51f0a8e5072daf2c49fcdac62fcd8204e5b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2732.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e4f408e0a8ad14e9ae14f24731f0012a4dbf2c0", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 13, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2733.json b/mne-python/source/doc/sphinxext/prs/2733.json new file mode 100644 index 0000000000000000000000000000000000000000..2d81bb54f10c493b5c16a1962426e8bdb04456b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2733.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d034d63236538eb81387a9521cd2ba93f66df0f9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/epochs.py": { + "a": 24, + "d": 4 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 7, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2734.json b/mne-python/source/doc/sphinxext/prs/2734.json new file mode 100644 index 0000000000000000000000000000000000000000..d0adb35c919e0f86609ae59da0b3eab9cd8a36a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2734.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "b9db9c2dada4ea5179514fb7c779f47d5443e5b6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 8, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 48, + "d": 35 + }, + "mne/channels/tests/test_channels.py": { + "a": 4, + "d": 2 + }, + "mne/cov.py": { + "a": 6, + "d": 6 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 11, + "d": 3 + }, + "mne/io/proj.py": { + "a": 10, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 30, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2735.json b/mne-python/source/doc/sphinxext/prs/2735.json new file mode 100644 index 0000000000000000000000000000000000000000..83f76db77996fbaf5f90ca614798e15d4b47f492 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2735.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "871243a80239b0b77f7c3e244823a47c4c8d22ff", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2736.json b/mne-python/source/doc/sphinxext/prs/2736.json new file mode 100644 index 0000000000000000000000000000000000000000..df708b587930a44ee232e3662bd8e96300e0c92c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2736.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "76358323962c0ad00f7a04d4251840435e0b7d49", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_maxwell.py": { + "a": 40, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2737.json b/mne-python/source/doc/sphinxext/prs/2737.json new file mode 100644 index 0000000000000000000000000000000000000000..c6641272e0fd615607e67a7ad3c2b9661288c34a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2737.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d60e40c1447147e745813ff7057ea1922d532bc0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 12, + "d": 30 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2738.json b/mne-python/source/doc/sphinxext/prs/2738.json new file mode 100644 index 0000000000000000000000000000000000000000..1c1f3d3690560ba68728cad49167ea35c1509f43 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2738.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "823ec507c3ee78d8791c546340c154028afa47eb", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_joint_evoked_topomap.py": { + "a": 34, + "d": 0 + }, + "mne/evoked.py": { + "a": 52, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 180, + "d": 3 + }, + "mne/viz/tests/test_topo.py": { + "a": 5, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 7, + "d": 45 + }, + "mne/viz/utils.py": { + "a": 50, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2739.json b/mne-python/source/doc/sphinxext/prs/2739.json new file mode 100644 index 0000000000000000000000000000000000000000..a4322c6761c6e259908f1aad1b7d92510a907928 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2739.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dda326cafc8b55e3c0749ee85bc2bea229b91762", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/cov.py": { + "a": 9, + "d": 2 + }, + "mne/decoding/ems.py": { + "a": 13, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2741.json b/mne-python/source/doc/sphinxext/prs/2741.json new file mode 100644 index 0000000000000000000000000000000000000000..b88c58734d31494a26e66be1f2faecdf5da1763d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2741.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "68f9a9fc34c6762d72d330782e21b5e9ec6e3bac", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 28, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2743.json b/mne-python/source/doc/sphinxext/prs/2743.json new file mode 100644 index 0000000000000000000000000000000000000000..be2594f9ed3f009a00f46a338770b8f1f8aab792 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2743.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1fba8c52d2de3cdff225f0bd122f7d3682a7265d", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2755.json b/mne-python/source/doc/sphinxext/prs/2755.json new file mode 100644 index 0000000000000000000000000000000000000000..a11f964e63730b0a66154536386e22c48261cddc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2755.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "03888d2c6a2347922a1cd9558f5a551acba4c66d", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 20, + "d": 6 + }, + "mne/decoding/time_gen.py": { + "a": 41, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2758.json b/mne-python/source/doc/sphinxext/prs/2758.json new file mode 100644 index 0000000000000000000000000000000000000000..4feb3ddb1021927bcff053f86fcf935b4743e6a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2758.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "919564156ced45329039cf4bd277396c5653f653", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/manual/channel_interpolation.rst": { + "a": 74, + "d": 0 + }, + "doc/manual/index.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 8, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/276.json b/mne-python/source/doc/sphinxext/prs/276.json new file mode 100644 index 0000000000000000000000000000000000000000..70f982a60ab7d528ed357920c3a9f9cebab57257 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/276.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4c19b12ad4e79f16c4d39c0e0679f60100e5ad2b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 7, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 50, + "d": 0 + }, + "mne/viz.py": { + "a": 83, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2761.json b/mne-python/source/doc/sphinxext/prs/2761.json new file mode 100644 index 0000000000000000000000000000000000000000..b8204e837ec53fca7cb6946681cb1e3285253f03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2761.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dbb30a703dd9052994ed8907eaa165a457487ea6", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/Makefile": { + "a": 19, + "d": 13 + }, + "doc/conf.py": { + "a": 6, + "d": 8 + }, + "doc/contributing.rst": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2762.json b/mne-python/source/doc/sphinxext/prs/2762.json new file mode 100644 index 0000000000000000000000000000000000000000..f11edbda4f9d2d2f1b9989277a292c3857b5d9fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2762.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6476eac6bab76ce448073d9569648cf86db357f0", + "authors": [ + { + "n": "Sagun Pai", + "e": null + } + ], + "changes": { + "LICENSE.txt": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2764.json b/mne-python/source/doc/sphinxext/prs/2764.json new file mode 100644 index 0000000000000000000000000000000000000000..e3a059b92f2f14ac54c965b34915581334dede64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2764.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aea8bc93b4319a9922cc80c45e30166b8ceab5b6", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/io/tests/test_meas_info.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2765.json b/mne-python/source/doc/sphinxext/prs/2765.json new file mode 100644 index 0000000000000000000000000000000000000000..d7e7bfb62f8ad15057641ac6de854cee53d2333a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2765.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "ec0e0791cf7d7e81729e158cc6516a9aa5229014", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 0, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 0, + "d": 2 + }, + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 3 + }, + "mne/evoked.py": { + "a": 0, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 0, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 6, + "d": 7 + }, + "mne/forward/forward.py": { + "a": 0, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 6, + "d": 7 + }, + "mne/io/bti/bti.py": { + "a": 0, + "d": 2 + }, + "mne/io/ctf/info.py": { + "a": 0, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 4, + "d": 7 + }, + "mne/io/meas_info.py": { + "a": 192, + "d": 30 + }, + "mne/io/nicolet/nicolet.py": { + "a": 2, + "d": 3 + }, + "mne/io/pick.py": { + "a": 8, + "d": 6 + }, + "mne/io/reference.py": { + "a": 0, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 142, + "d": 3 + }, + "mne/io/tests/test_pick.py": { + "a": 0, + "d": 8 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 5 + }, + "mne/preprocessing/maxwell.py": { + "a": 0, + "d": 2 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 2 + }, + "mne/utils.py": { + "a": 7, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2767.json b/mne-python/source/doc/sphinxext/prs/2767.json new file mode 100644 index 0000000000000000000000000000000000000000..c0e18b69cfea21c59c5b36c0ef8e039d6d9cd2ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2767.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "57c520e0585c04bc37894f9c8ea0a2ed3c466b29", + "authors": [ + { + "n": "Kambiz Tavabi", + "e": "ktavabi@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2769.json b/mne-python/source/doc/sphinxext/prs/2769.json new file mode 100644 index 0000000000000000000000000000000000000000..90638a9d2cdb933877cec6eaeb5babb7133c9d3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2769.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fd2ccb6908ceb806702ccbea77f206260fa129c9", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 5, + "d": 17 + }, + "mne/io/bti/bti.py": { + "a": 23, + "d": 12 + }, + "mne/io/egi/egi.py": { + "a": 6, + "d": 15 + }, + "mne/io/kit/kit.py": { + "a": 42, + "d": 36 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/io/utils.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2777.json b/mne-python/source/doc/sphinxext/prs/2777.json new file mode 100644 index 0000000000000000000000000000000000000000..d1bdee206abaec09a8c1eb354a5ebf6fce5a3c68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2777.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9a0ce3c3b36b0da788449adcf7fd8187b19cfb5e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 37, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2779.json b/mne-python/source/doc/sphinxext/prs/2779.json new file mode 100644 index 0000000000000000000000000000000000000000..80266a1461fbea576d3c689b6780f2f4dc5783aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2779.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1e8b0fe292fa8013ab4f3837097a89d2dfb5fd77", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 5, + "d": 1 + }, + "mne/stats/tests/test_regression.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2781.json b/mne-python/source/doc/sphinxext/prs/2781.json new file mode 100644 index 0000000000000000000000000000000000000000..af6c67569585d2147a07f649e53c2fdd83846d2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2781.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4ca4d7594c1476a4c0327d49a5d72de70d7c65e5", + "authors": [ + { + "n": "FuTe Wong", + "e": "zuxfoucault@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2783.json b/mne-python/source/doc/sphinxext/prs/2783.json new file mode 100644 index 0000000000000000000000000000000000000000..9a7f3c38e962a1a04a6f2834300dda7853136eda --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2783.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "7711dcdc30d35867f366e74afe44af3156386c1b", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/manual/memory.rst": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 90, + "d": 0 + }, + "mne/io/base.py": { + "a": 23, + "d": 4 + }, + "mne/io/constants.py": { + "a": 3, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 38, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 8, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 58, + "d": 0 + }, + "mne/utils.py": { + "a": 0, + "d": 9 + }, + "mne/viz/raw.py": { + "a": 59, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2785.json b/mne-python/source/doc/sphinxext/prs/2785.json new file mode 100644 index 0000000000000000000000000000000000000000..96624b7addf7d411d5cc9dfc50eb330153c497a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2785.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1e6af29a8e3cccbb94addea534462261ca555cd0", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_reference.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2786.json b/mne-python/source/doc/sphinxext/prs/2786.json new file mode 100644 index 0000000000000000000000000000000000000000..7c7bb5ca0e2af6e8966cced447f4edceec5e5d35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2786.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cb5ad96b347cbd55ae06c0a5f7517c09ec24dc41", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 17, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2791.json b/mne-python/source/doc/sphinxext/prs/2791.json new file mode 100644 index 0000000000000000000000000000000000000000..dadd4b4c95939f6848c209aeac74624ad2ee610d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2791.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cf8e5d625ba2ebe1593a882eed7a49b02433f8b1", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 10, + "d": 3 + }, + "mne/stats/tests/test_regression.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2797.json b/mne-python/source/doc/sphinxext/prs/2797.json new file mode 100644 index 0000000000000000000000000000000000000000..4d9454853e43c8d8e888f4c31d6f91672d0ae7ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2797.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ebe2bfaf53f5617fd3529d47d5395a13136f56f5", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2798.json b/mne-python/source/doc/sphinxext/prs/2798.json new file mode 100644 index 0000000000000000000000000000000000000000..ed3960eb34fd69d8094a5b0c02ab6e83bcc4e4dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2798.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "51595b55e9e357d8a95ba7f0dc320f5da1761899", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/dipole.py": { + "a": 3, + "d": 5 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/280.json b/mne-python/source/doc/sphinxext/prs/280.json new file mode 100644 index 0000000000000000000000000000000000000000..f0f7b9cdcad0cc3491c6c1cfc7f93023e794a552 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/280.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0329e3f4da544f313912c8485e7a85d0a305281f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/tests/test_raw.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2802.json b/mne-python/source/doc/sphinxext/prs/2802.json new file mode 100644 index 0000000000000000000000000000000000000000..2130fdcbda9bc3ab15f853c91afe147047f968fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2802.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "e79aead7cb4302cccaad614c530d63476e7aec05", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 4, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 4, + "d": 3 + }, + "mne/io/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 7, + "d": 7 + }, + "mne/io/tests/test_raw.py": { + "a": 4, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 6 + }, + "mne/utils.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/281.json b/mne-python/source/doc/sphinxext/prs/281.json new file mode 100644 index 0000000000000000000000000000000000000000..55c2ff9b5bba349c4867f20d2ac15bf50481d36e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/281.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e6ca398a5d1c4667136a819f7b1630a1d00cab86", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/forward.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2819.json b/mne-python/source/doc/sphinxext/prs/2819.json new file mode 100644 index 0000000000000000000000000000000000000000..4401871a12363f78fe411896261fdddd533ee73b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2819.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b5f225538295ae6489d1bc5dd1d515d3e1760b8d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 1, + "d": 0 + }, + "mne/utils.py": { + "a": 16, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/282.json b/mne-python/source/doc/sphinxext/prs/282.json new file mode 100644 index 0000000000000000000000000000000000000000..f33423e0972024af26de7fe881f9d6ce14ca66d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/282.json @@ -0,0 +1,159 @@ +{ + "merge_commit_sha": "adcdb20b96e6bae91e2f5bd6d2bcd1dfee9777a7", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "bin/mne_clean_eog_ecg.py": { + "a": 6, + "d": 6 + }, + "bin/mne_flash_bem_model.py": { + "a": 5, + "d": 4 + }, + "mne/baseline.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 18, + "d": 5 + }, + "mne/epochs.py": { + "a": 15, + "d": 15 + }, + "mne/event.py": { + "a": 6, + "d": 6 + }, + "mne/fiff/channels.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/cov.py": { + "a": 6, + "d": 6 + }, + "mne/fiff/ctf.py": { + "a": 6, + "d": 6 + }, + "mne/fiff/matrix.py": { + "a": 6, + "d": 6 + }, + "mne/fiff/meas_info.py": { + "a": 7, + "d": 7 + }, + "mne/fiff/open.py": { + "a": 4, + "d": 4 + }, + "mne/fiff/proj.py": { + "a": 4, + "d": 4 + }, + "mne/fiff/raw.py": { + "a": 19, + "d": 19 + }, + "mne/fiff/tag.py": { + "a": 8, + "d": 8 + }, + "mne/filter.py": { + "a": 12, + "d": 12 + }, + "mne/fixes.py": { + "a": 0, + "d": 1 + }, + "mne/forward.py": { + "a": 5, + "d": 5 + }, + "mne/label.py": { + "a": 11, + "d": 11 + }, + "mne/layouts/layout.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 9, + "d": 10 + }, + "mne/preprocessing/ecg.py": { + "a": 6, + "d": 6 + }, + "mne/preprocessing/maxfilter.py": { + "a": 21, + "d": 21 + }, + "mne/preprocessing/peak_finder.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ssp.py": { + "a": 83, + "d": 83 + }, + "mne/preprocessing/stim.py": { + "a": 3, + "d": 3 + }, + "mne/proj.py": { + "a": 17, + "d": 18 + }, + "mne/source_estimate.py": { + "a": 12, + "d": 11 + }, + "mne/source_space.py": { + "a": 4, + "d": 4 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 31, + "d": 31 + }, + "mne/time_frequency/psd.py": { + "a": 10, + "d": 10 + }, + "mne/time_frequency/stft.py": { + "a": 8, + "d": 8 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + }, + "mne/viz.py": { + "a": 14, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2821.json b/mne-python/source/doc/sphinxext/prs/2821.json new file mode 100644 index 0000000000000000000000000000000000000000..b02d8bd36d0d2d8963661b500647ae283a37b6a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2821.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "045abeb46be8088f5fd8c3dd0415f5a4f79a182a", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/manual/cookbook.rst": { + "a": 13, + "d": 0 + }, + "doc/manual/preprocessing/annotations.rst": { + "a": 35, + "d": 0 + }, + "doc/tutorials.rst": { + "a": 3, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/annotations.py": { + "a": 28, + "d": 5 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 32, + "d": 14 + }, + "mne/io/base.py": { + "a": 41, + "d": 8 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/stats/regression.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 10, + "d": 24 + }, + "mne/viz/utils.py": { + "a": 13, + "d": 10 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 357, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2824.json b/mne-python/source/doc/sphinxext/prs/2824.json new file mode 100644 index 0000000000000000000000000000000000000000..18a34c0c6f45ddd2f26f503ba0a183838ae72a7c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2824.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d9d9f9a0c1df3b1a36d1aa2abc3a76a16825375c", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2826.json b/mne-python/source/doc/sphinxext/prs/2826.json new file mode 100644 index 0000000000000000000000000000000000000000..b8abaf77bae8e76f283aafb4d7ab98146a9be19d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2826.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "c49d7f686031a016335a98f421909a1c2f35c4ca", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 0, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 8, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 0, + "d": 1 + }, + "mne/utils.py": { + "a": 16, + "d": 11 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/283.json b/mne-python/source/doc/sphinxext/prs/283.json new file mode 100644 index 0000000000000000000000000000000000000000..d05ec64ebcb16f9a079bc2aebf055ceb45ad1696 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/283.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5df5a6996192c7541e8e2dbb33a104be09a4f8e0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 2, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 15, + "d": 78 + }, + "mne/viz.py": { + "a": 55, + "d": 307 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2830.json b/mne-python/source/doc/sphinxext/prs/2830.json new file mode 100644 index 0000000000000000000000000000000000000000..d110bcca6745b573486ba78d99f0001bfbdc9c65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2830.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a7cf79130bf306ca4c47d2d1e74f3f3f653fbb52", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 12, + "d": 0 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2833.json b/mne-python/source/doc/sphinxext/prs/2833.json new file mode 100644 index 0000000000000000000000000000000000000000..1dbc928b2af0b46b2fb10eaa659b19f65123e854 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2833.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e4c07c7dc5a22b158874f39fb4d8997c77c6a219", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 8, + "d": 0 + }, + "mne/decoding/time_gen.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2836.json b/mne-python/source/doc/sphinxext/prs/2836.json new file mode 100644 index 0000000000000000000000000000000000000000..5bb56ff74f648681747bd75f516b90dbef013340 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2836.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9cda691349854df2d08eb921e323555fc9b867ff", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 10, + "d": 1 + }, + "mne/utils.py": { + "a": 52, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2837.json b/mne-python/source/doc/sphinxext/prs/2837.json new file mode 100644 index 0000000000000000000000000000000000000000..3fe38d68051b07805ff00bc51584f2049292881d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2837.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "eff4d66788d0fb2567df325561bfb9c9e3df3419", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_csp.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2839.json b/mne-python/source/doc/sphinxext/prs/2839.json new file mode 100644 index 0000000000000000000000000000000000000000..beba42fb39a9d78825c1cc84f496ce8517b0ad82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2839.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "17035dfbe2ed130f3c6e7dd82c1798a2ef96383c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 3, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 17, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/284.json b/mne-python/source/doc/sphinxext/prs/284.json new file mode 100644 index 0000000000000000000000000000000000000000..8cb0f475c71e7a4db65b4569857f8c5cdf1869f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/284.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a28a9942b94a1ad9752accfefce88f48b6e89aee", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 5, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2843.json b/mne-python/source/doc/sphinxext/prs/2843.json new file mode 100644 index 0000000000000000000000000000000000000000..b45b1cba0e34cad6a937734f419807fe4b3564b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2843.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "242089e518b76d80e3fb5228647e2d82bfc51593", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 13, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 0, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2844.json b/mne-python/source/doc/sphinxext/prs/2844.json new file mode 100644 index 0000000000000000000000000000000000000000..b1ffeb64537ca96a6e0c2c967cabdfb258dce93d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2844.json @@ -0,0 +1,391 @@ +{ + "merge_commit_sha": "a61531d68ca55e9389855a2d87bc623bcbcb517c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/_dics.py": { + "a": 4, + "d": 6 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 4 + }, + "mne/bem.py": { + "a": 5, + "d": 5 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 6 + }, + "mne/channels/interpolation.py": { + "a": 3, + "d": 3 + }, + "mne/channels/montage.py": { + "a": 7, + "d": 8 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 4, + "d": 4 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 2 + }, + "mne/cov.py": { + "a": 10, + "d": 14 + }, + "mne/cuda.py": { + "a": 7, + "d": 9 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 3 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 31, + "d": 15 + }, + "mne/decoding/time_gen.py": { + "a": 4, + "d": 5 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 20, + "d": 26 + }, + "mne/event.py": { + "a": 3, + "d": 5 + }, + "mne/evoked.py": { + "a": 2, + "d": 3 + }, + "mne/filter.py": { + "a": 17, + "d": 18 + }, + "mne/forward/forward.py": { + "a": 12, + "d": 13 + }, + "mne/forward/tests/test_forward.py": { + "a": 4, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 8, + "d": 9 + }, + "mne/io/base.py": { + "a": 12, + "d": 17 + }, + "mne/io/brainvision/brainvision.py": { + "a": 6, + "d": 8 + }, + "mne/io/bti/bti.py": { + "a": 5, + "d": 6 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 22, + "d": 14 + }, + "mne/io/ctf/info.py": { + "a": 3, + "d": 4 + }, + "mne/io/edf/edf.py": { + "a": 12, + "d": 13 + }, + "mne/io/eeglab/eeglab.py": { + "a": 7, + "d": 8 + }, + "mne/io/egi/egi.py": { + "a": 3, + "d": 4 + }, + "mne/io/fiff/raw.py": { + "a": 4, + "d": 5 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 16, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 6, + "d": 8 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 2 + }, + "mne/io/proc_history.py": { + "a": 2, + "d": 2 + }, + "mne/io/proj.py": { + "a": 4, + "d": 5 + }, + "mne/io/reference.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_pick.py": { + "a": 4, + "d": 2 + }, + "mne/io/tests/test_reference.py": { + "a": 2, + "d": 1 + }, + "mne/label.py": { + "a": 11, + "d": 13 + }, + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 5 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 5 + }, + "mne/parallel.py": { + "a": 5, + "d": 6 + }, + "mne/preprocessing/ecg.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 8, + "d": 10 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 35, + "d": 28 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 6, + "d": 8 + }, + "mne/report.py": { + "a": 15, + "d": 17 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 5 + }, + "mne/simulation/source.py": { + "a": 4, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 12, + "d": 14 + }, + "mne/source_space.py": { + "a": 6, + "d": 7 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 10 + }, + "mne/stats/regression.py": { + "a": 5, + "d": 6 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 10, + "d": 9 + }, + "mne/stats/tests/test_regression.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 6, + "d": 8 + }, + "mne/tests/common.py": { + "a": 22, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 10, + "d": 7 + }, + "mne/tests/test_chpi.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 19, + "d": 7 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_event.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_label.py": { + "a": 23, + "d": 15 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 5, + "d": 3 + }, + "mne/tests/test_surface.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/_stockwell.py": { + "a": 3, + "d": 4 + }, + "mne/time_frequency/csd.py": { + "a": 5, + "d": 6 + }, + "mne/time_frequency/multitaper.py": { + "a": 5, + "d": 9 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 10, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 5, + "d": 5 + }, + "mne/utils.py": { + "a": 52, + "d": 11 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 12 + }, + "mne/viz/decoding.py": { + "a": 3, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 8, + "d": 9 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 4, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 6, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2849.json b/mne-python/source/doc/sphinxext/prs/2849.json new file mode 100644 index 0000000000000000000000000000000000000000..890e91125fe3d07f83ac2595b615f3ad75517e3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2849.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "f1a3e085aca64d88afaca15dfeef406af24ddd91", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 66, + "d": 0 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/forward/plot_make_forward.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/plot_simulate_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 8, + "d": 6 + }, + "mne/datasets/megsim/megsim.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/megsim/urls.py": { + "a": 7, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 29, + "d": 25 + }, + "mne/forward/_lead_dots.py": { + "a": 26, + "d": 13 + }, + "tutorials/plot_cluster_methods_tutorial.py": { + "a": 6, + "d": 5 + }, + "tutorials/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_spatio_temporal_cluster_stats_sensor.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2851.json b/mne-python/source/doc/sphinxext/prs/2851.json new file mode 100644 index 0000000000000000000000000000000000000000..818743680e09d38749f6ae24b40a006d083effeb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2851.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6a053953470b856254390cf13c2e7c06d82bf0d1", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2857.json b/mne-python/source/doc/sphinxext/prs/2857.json new file mode 100644 index 0000000000000000000000000000000000000000..5176cadfac5a117759c4678e3c8fbc0e7cf5fcc3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2857.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ea6689e43870f87c39b2051b56bf455b589aa26c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 44, + "d": 13 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 32, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2861.json b/mne-python/source/doc/sphinxext/prs/2861.json new file mode 100644 index 0000000000000000000000000000000000000000..7fe7ada4b0ff53708258b27348f5cdde77c478f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2861.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a87d7cbb6e3a3ffd27236b28d825f94f4284127d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/io/proj.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 6, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2863.json b/mne-python/source/doc/sphinxext/prs/2863.json new file mode 100644 index 0000000000000000000000000000000000000000..bc474ec9ce664667799e6a78ffda4a2d66f627ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2863.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "724ee0b2edd969f0679c78f0733e7be4b56a33c5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 6, + "d": 2 + }, + "mne/evoked.py": { + "a": 1, + "d": 0 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 3, + "d": 4 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 28, + "d": 23 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 12, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 1, + "d": 0 + }, + "mne/utils.py": { + "a": 11, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2865.json b/mne-python/source/doc/sphinxext/prs/2865.json new file mode 100644 index 0000000000000000000000000000000000000000..7258e2cccd66f5d4dcc55e3e3bf80bde780bee01 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2865.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ba4521f97495edbe55ce281843ee1e9ad92972bb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 0, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 0, + "d": 2 + }, + "mne/io/proj.py": { + "a": 1, + "d": 3 + }, + "mne/io/tag.py": { + "a": 291, + "d": 261 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2868.json b/mne-python/source/doc/sphinxext/prs/2868.json new file mode 100644 index 0000000000000000000000000000000000000000..7ec14ef817ad98480c74b47ddefa69fb7a5daf7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2868.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9edc61acebec2b76b391f78c6c23665caf004925", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/cov.py": { + "a": 153, + "d": 109 + }, + "mne/event.py": { + "a": 2, + "d": 1 + }, + "mne/tests/common.py": { + "a": 10, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 43, + "d": 24 + }, + "mne/tests/test_event.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/287.json b/mne-python/source/doc/sphinxext/prs/287.json new file mode 100644 index 0000000000000000000000000000000000000000..c51b4b68d8a8b555f0b311ad5c7ab025c3f4632d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/287.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "a9d769ed7c7b29ed706216e26d43691a38ce6e47", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/_static/branch_dropdown.png": { + "a": 0, + "d": 0 + }, + "doc/source/_static/forking_button.png": { + "a": 0, + "d": 0 + }, + "doc/source/_static/pull_button.png": { + "a": 0, + "d": 0 + }, + "doc/source/contributing.rst": { + "a": 649, + "d": 0 + }, + "doc/source/customizing_git.rst": { + "a": 7, + "d": 7 + }, + "doc/source/git_links.inc": { + "a": 27, + "d": 17 + }, + "doc/source/gitwash/branch_list.png": { + "a": 0, + "d": 0 + }, + "doc/source/gitwash/branch_list_compare.png": { + "a": 0, + "d": 0 + }, + "doc/source/gitwash/development_workflow.rst": { + "a": 0, + "d": 265 + }, + "doc/source/gitwash/following_latest.rst": { + "a": 0, + "d": 36 + }, + "doc/source/gitwash/forking_hell.rst": { + "a": 0, + "d": 33 + }, + "doc/source/gitwash/git_development.rst": { + "a": 0, + "d": 16 + }, + "doc/source/gitwash/git_install.rst": { + "a": 0, + "d": 26 + }, + "doc/source/gitwash/git_intro.rst": { + "a": 0, + "d": 18 + }, + "doc/source/gitwash/git_resources.rst": { + "a": 0, + "d": 59 + }, + "doc/source/gitwash/index.rst": { + "a": 0, + "d": 16 + }, + "doc/source/gitwash/patching.rst": { + "a": 0, + "d": 134 + }, + "doc/source/gitwash/set_up_fork.rst": { + "a": 0, + "d": 68 + }, + "doc/source/gitwash/setup.sh": { + "a": 0, + "d": 3 + }, + "doc/source/gitwash/this_project.inc": { + "a": 0, + "d": 5 + }, + "doc/source/known_projects.inc": { + "a": 6, + "d": 1 + }, + "doc/source/links.inc": { + "a": 0, + "d": 0 + }, + "doc/source/mne-python.rst": { + "a": 1, + "d": 1 + }, + "doc/source/this_project.inc": { + "a": 5, + "d": 0 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 5, + "d": 1 + }, + "examples/inverse/plot_dipole_fit_result.py": { + "a": 5, + "d": 1 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 5, + "d": 1 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 4, + "d": 1 + }, + "examples/plot_read_bem_surfaces.py": { + "a": 5, + "d": 1 + }, + "examples/plot_read_forward.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2880.json b/mne-python/source/doc/sphinxext/prs/2880.json new file mode 100644 index 0000000000000000000000000000000000000000..a4162b3424a5fc1d881040fefde2d5e9285385ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2880.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "672493edcbf45b444c288b4c4acbc08d7c062f94", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_dipole.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 14, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2882.json b/mne-python/source/doc/sphinxext/prs/2882.json new file mode 100644 index 0000000000000000000000000000000000000000..5f1628c32cfe38730d150fdefbc9ab2b213a002d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2882.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "dee6196375ec4f30bc7681fc5a707b12ed4236ba", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/ctf.py": { + "a": 7, + "d": 1 + }, + "mne/io/ctf/eeg.py": { + "a": 47, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2883.json b/mne-python/source/doc/sphinxext/prs/2883.json new file mode 100644 index 0000000000000000000000000000000000000000..d43f7ccb56fdd823b256626e75faafdaa487ba06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2883.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2b532f331404c78d0aebb5997d4b042a81ae69a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 15, + "d": 7 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 22, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2885.json b/mne-python/source/doc/sphinxext/prs/2885.json new file mode 100644 index 0000000000000000000000000000000000000000..f48ec9fc7ead7be4d17835e299e5f8d9205bbe68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2885.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "32bb34fd97b7e652ace090a38fe37b0a45dfde5c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2888.json b/mne-python/source/doc/sphinxext/prs/2888.json new file mode 100644 index 0000000000000000000000000000000000000000..44894d233b06b172df5901f8050481cabf45299c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2888.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "17ba5e3ef0c0d90401fab63cd1862fb20cacc330", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2889.json b/mne-python/source/doc/sphinxext/prs/2889.json new file mode 100644 index 0000000000000000000000000000000000000000..594a92fdc1fcd6e9e232c6d5c28058a880df9aed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2889.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b4d089e1a9088ec6dac237b4c323395e7005b897", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/289.json b/mne-python/source/doc/sphinxext/prs/289.json new file mode 100644 index 0000000000000000000000000000000000000000..835165848548f8e20f2ed7cb3b8b39548ecccbef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/289.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "20fc139f6da759cf8a78b8fe0666060ada0b29d7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/tests/test_evoked.py": { + "a": 4, + "d": 21 + }, + "mne/fiff/tests/test_raw.py": { + "a": 4, + "d": 20 + }, + "mne/layouts/tests/test_layout.py": { + "a": 2, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 5, + "d": 4 + }, + "mne/mixed_norm/tests/test_optim.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 21 + }, + "mne/tests/test_event.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 6 + }, + "mne/tests/test_proj.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_source_estimate.py": { + "a": 7, + "d": 8 + }, + "mne/tests/test_source_space.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_utils.py": { + "a": 4, + "d": 2 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 5, + "d": 10 + }, + "mne/utils.py": { + "a": 64, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2890.json b/mne-python/source/doc/sphinxext/prs/2890.json new file mode 100644 index 0000000000000000000000000000000000000000..009b8b2f4f185bf605d01a468e43f022d6410f10 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2890.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "15b81e358f39b1746911cc72009a164999a49215", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2891.json b/mne-python/source/doc/sphinxext/prs/2891.json new file mode 100644 index 0000000000000000000000000000000000000000..978302a167f9c57b0b55caa9dbc66bbef5ff454f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2891.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "85b1dcd1697b64d22ea3b50e50c65e098229dba4", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2893.json b/mne-python/source/doc/sphinxext/prs/2893.json new file mode 100644 index 0000000000000000000000000000000000000000..0a4c47f5b007d72743b0d8589693a23d9fe73ca4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2893.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0fad905afb248b023aa7b427f72ba4531823c8f6", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 4, + "d": 0 + }, + "mne/utils.py": { + "a": 6, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2895.json b/mne-python/source/doc/sphinxext/prs/2895.json new file mode 100644 index 0000000000000000000000000000000000000000..8d92c0a588bbe77de3844bfbef174fb02e14e248 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2895.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "722ac102aa37a77c02cabf10ebfaecb2f76540dc", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2896.json b/mne-python/source/doc/sphinxext/prs/2896.json new file mode 100644 index 0000000000000000000000000000000000000000..6498d2e30a1514b8591e95437fe5e880f535edd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2896.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "df5cdae8c78f519f26ba14e5ea9ba73519acf730", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 4, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/29.json b/mne-python/source/doc/sphinxext/prs/29.json new file mode 100644 index 0000000000000000000000000000000000000000..48eef63d628ef4b7357a3e70a0afe93710a62d11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/29.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "ef31128ae7504e4ad5c4b812190595e8a2a6085d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/ctf.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/matrix.py": { + "a": 42, + "d": 20 + }, + "mne/fiff/write.py": { + "a": 40, + "d": 66 + }, + "mne/minimum_norm/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 113, + "d": 18 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 40, + "d": 4 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 97, + "d": 2 + }, + "mne/surface.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/290.json b/mne-python/source/doc/sphinxext/prs/290.json new file mode 100644 index 0000000000000000000000000000000000000000..42f8d1eabe8ffa93f1f1b6f1366c60a2ff9dd6dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/290.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0b0cfaad1ee679654e0a314f322941870ac6bda3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 6, + "d": 6 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 38, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 20, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2902.json b/mne-python/source/doc/sphinxext/prs/2902.json new file mode 100644 index 0000000000000000000000000000000000000000..32a99313d40d381da180cb817d59f6b8f84db676 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2902.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8b3a6441b1076340acbd8392fc2962b2fac4020a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2903.json b/mne-python/source/doc/sphinxext/prs/2903.json new file mode 100644 index 0000000000000000000000000000000000000000..257b04d979204f7df9965634b3b44b6b12656ce1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2903.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bcf9b597231d0cca33aa03a55ec409d7ff9747ed", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/evoked.py": { + "a": 7, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2905.json b/mne-python/source/doc/sphinxext/prs/2905.json new file mode 100644 index 0000000000000000000000000000000000000000..341a5f0fc6553857b43290a4a880b5f1c41a3f1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2905.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fe4e3248e1d373c533f132f4d70bdb0dacd85e7c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 89, + "d": 52 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 56, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2907.json b/mne-python/source/doc/sphinxext/prs/2907.json new file mode 100644 index 0000000000000000000000000000000000000000..c7e3bca4dc0b722a005e30349869c5e87910583d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2907.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6b8c4a89c6ff3cdb0b70bb5ca0cd721db34bede3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/index.rst": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/291.json b/mne-python/source/doc/sphinxext/prs/291.json new file mode 100644 index 0000000000000000000000000000000000000000..575ade5bf59e9ab672a963c463bc73c8994a348c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/291.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "528e3ff3a9a0a2756d7940fcfb5769b0f25c3bf7", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2910.json b/mne-python/source/doc/sphinxext/prs/2910.json new file mode 100644 index 0000000000000000000000000000000000000000..ce7b8fdc5fbebb45dc4f6b2ea2479f0db53d2775 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2910.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "757e637886d5f383a043c8aabfe705a7e172557e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 1 + }, + "mne/bem.py": { + "a": 68, + "d": 23 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 3 + }, + "mne/channels/tests/test_layout.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 3 + }, + "mne/tests/common.py": { + "a": 6, + "d": 5 + }, + "mne/tests/test_bem.py": { + "a": 67, + "d": 35 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2911.json b/mne-python/source/doc/sphinxext/prs/2911.json new file mode 100644 index 0000000000000000000000000000000000000000..51bc1905591108cdcbf70d854124765898f9190d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2911.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3d4c74297b411e9a414bbeb5b3be6e23bac956f0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/tag.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2913.json b/mne-python/source/doc/sphinxext/prs/2913.json new file mode 100644 index 0000000000000000000000000000000000000000..e7a3d1af463f73f8f1b98991b06f193303bd033c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2913.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f82bf0b75655b88f438abaf06594c1c9aeac87c2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/fiff/raw.py": { + "a": 6, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 16, + "d": 29 + }, + "mne/simulation/tests/test_raw.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_chpi.py": { + "a": 4, + "d": 10 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2914.json b/mne-python/source/doc/sphinxext/prs/2914.json new file mode 100644 index 0000000000000000000000000000000000000000..afb32cf83a504e69880cbd181c7990d6567e160f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2914.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ccbaf544646cf41f4d72575dcfd715050ff73f56", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 4 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2915.json b/mne-python/source/doc/sphinxext/prs/2915.json new file mode 100644 index 0000000000000000000000000000000000000000..b3de17139d23cfb22483f850395a70a3954ebd9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2915.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5112448c3e04b26027d0f3603dfafe64876781c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_pick.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2916.json b/mne-python/source/doc/sphinxext/prs/2916.json new file mode 100644 index 0000000000000000000000000000000000000000..e4fcc43c86dacc3a477c063e90b78e3cb03ecdb9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2916.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4928671d35052c78fe35864bd87df4b036c20492", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 2, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2917.json b/mne-python/source/doc/sphinxext/prs/2917.json new file mode 100644 index 0000000000000000000000000000000000000000..9fb63d430f4ec9ac6792d5e4525d29d8e0618a1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2917.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ffacbfa2ef6ebff0b621113809dd695d682e10d4", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 26, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2918.json b/mne-python/source/doc/sphinxext/prs/2918.json new file mode 100644 index 0000000000000000000000000000000000000000..74bb9aaefd162a1af1ea7897e2ea51f3f38898b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2918.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "1428b8772101dba6eecd9b7eaa563aa6aeba871c", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": "bailey.cj@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/visualization/plot_topography.py": { + "a": 4, + "d": 2 + }, + "mne/channels/data/layouts/Vectorview-grad_norm.lout": { + "a": 103, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 4, + "d": 2 + }, + "mne/evoked.py": { + "a": 19, + "d": 16 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 60, + "d": 35 + }, + "mne/viz/topomap.py": { + "a": 13, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2921.json b/mne-python/source/doc/sphinxext/prs/2921.json new file mode 100644 index 0000000000000000000000000000000000000000..573fa56b26f4972ee0b5f312588871ef605f02da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2921.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6a3a6f60f6bc3384adcedbdb457be18ce535b87b", + "authors": [ + { + "n": "Asish Panda", + "e": "asishrocks95@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2924.json b/mne-python/source/doc/sphinxext/prs/2924.json new file mode 100644 index 0000000000000000000000000000000000000000..154054a543bb5697247b793ed75548c8fa068941 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2924.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8d6bf3c670512981dbf7d8358d5d243535e751f2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 7, + "d": 4 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2925.json b/mne-python/source/doc/sphinxext/prs/2925.json new file mode 100644 index 0000000000000000000000000000000000000000..49778e1d400299f28337deb8fccfd6b9334f9245 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2925.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6b0c16e77a0b8ba1a3b22d902b1b368037a5e05f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/_templates/function.rst": { + "a": 4, + "d": 0 + }, + "doc/conf.py": { + "a": 3, + "d": 2 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 81, + "d": 81 + }, + "mne/commands/mne_surf2bem.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2926.json b/mne-python/source/doc/sphinxext/prs/2926.json new file mode 100644 index 0000000000000000000000000000000000000000..5e41aa27a1a0bf1f2e8aa827bd5b398362128e91 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2926.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "48033b68ce172439316a1dd5ede59a236e92da92", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/baseline.py": { + "a": 13, + "d": 7 + }, + "mne/epochs.py": { + "a": 6, + "d": 4 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 7 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_utils.py": { + "a": 10, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 5 + }, + "mne/utils.py": { + "a": 6, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2929.json b/mne-python/source/doc/sphinxext/prs/2929.json new file mode 100644 index 0000000000000000000000000000000000000000..460e02edb533554c12aa6c6f1880f3494ea7181e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2929.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8a13540e95a4e39121e88810ffd1edd15af4f6df", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 5, + "d": 4 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 9, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/293.json b/mne-python/source/doc/sphinxext/prs/293.json new file mode 100644 index 0000000000000000000000000000000000000000..9bae1d460125cab93a7ff8ecf74bc80b5576322c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/293.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "749b12925f4d31abf67ffcfd1faa84b921937946", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2930.json b/mne-python/source/doc/sphinxext/prs/2930.json new file mode 100644 index 0000000000000000000000000000000000000000..ea5ffb523ef221090f3320f50e7c7a3007605e4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2930.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e4bd5f0710f4b21abe72d67d871b0a5ea0f0c4e9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 14, + "d": 5 + }, + "mne/utils.py": { + "a": 4, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2932.json b/mne-python/source/doc/sphinxext/prs/2932.json new file mode 100644 index 0000000000000000000000000000000000000000..8240de3634e6982aea99309033631a98154d05de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2932.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "815c52a9f0f1f438c0bbec7e7ef6da7a6c448b6d", + "authors": [ + { + "n": "Sourav Singh", + "e": "ssouravsingh12@gmail.com" + } + ], + "changes": { + "doc/manual/source_localization/forward.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2934.json b/mne-python/source/doc/sphinxext/prs/2934.json new file mode 100644 index 0000000000000000000000000000000000000000..d8e662ef6fd680bfdad3270f87326badeb8f7d65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2934.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4b6f99a07c5e688622d31b467fa0140a5907a621", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/multitaper.py": { + "a": 9, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2936.json b/mne-python/source/doc/sphinxext/prs/2936.json new file mode 100644 index 0000000000000000000000000000000000000000..166a3dd48248386206bac16ea6d1f872b63ce290 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2936.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b0618d337c09d6aaadd8d46efe2f4bb550530e8b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 8, + "d": 7 + }, + "mne/tests/test_utils.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2938.json b/mne-python/source/doc/sphinxext/prs/2938.json new file mode 100644 index 0000000000000000000000000000000000000000..8f5c9d889b0cc832b745caba0900758fc1b8f5c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2938.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ab0cdf112a9bf56da8461363e7fd4b27c75dcbe2", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_show_info.py": { + "a": 34, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2939.json b/mne-python/source/doc/sphinxext/prs/2939.json new file mode 100644 index 0000000000000000000000000000000000000000..243b230d657ae8d89f3c8cc51ac1e64e48579de9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2939.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b9485698c371b957a80e401d8ca94c4790192c32", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/compensator.py": { + "a": 2, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 28, + "d": 17 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 31, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2940.json b/mne-python/source/doc/sphinxext/prs/2940.json new file mode 100644 index 0000000000000000000000000000000000000000..9f50980685bab5c32b944e716356009619c35513 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2940.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "31396d3103f60490329ed20faae38528037021f7", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 21, + "d": 19 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2941.json b/mne-python/source/doc/sphinxext/prs/2941.json new file mode 100644 index 0000000000000000000000000000000000000000..3e84d756f5f9289cbb9ea32c41e8d7d473201f2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2941.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8d01478e04a7c30ac46db443e82e2a37c46bbdad", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2942.json b/mne-python/source/doc/sphinxext/prs/2942.json new file mode 100644 index 0000000000000000000000000000000000000000..b1d9b4af54e519c54d05a02ae6e4ad1e010d2e7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2942.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "6df109e7f21b553f253e624f7fd486cb40759465", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/defaults.py": { + "a": 7, + "d": 6 + }, + "mne/dipole.py": { + "a": 93, + "d": 5 + }, + "mne/evoked.py": { + "a": 212, + "d": 184 + }, + "mne/io/constants.py": { + "a": 18, + "d": 14 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 2 + }, + "mne/io/pick.py": { + "a": 16, + "d": 4 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 19, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_utils.py": { + "a": 15, + "d": 13 + }, + "mne/utils.py": { + "a": 8, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 31, + "d": 19 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2943.json b/mne-python/source/doc/sphinxext/prs/2943.json new file mode 100644 index 0000000000000000000000000000000000000000..8a91a6b3def7d0b072e911032e99330dd9576ba4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2943.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "963eda039acfa4b7dbcaacad02e2b21f386159d7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topo.py": { + "a": 6, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 158, + "d": 67 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2946.json b/mne-python/source/doc/sphinxext/prs/2946.json new file mode 100644 index 0000000000000000000000000000000000000000..ee90087e1284670df793fb805a4434918259432d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2946.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "4716a5461c9395e0ce24184b07b663520a76260a", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 19, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 33, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/read.py": { + "a": 0, + "d": 12 + }, + "mne/io/cnt/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 369, + "d": 0 + }, + "mne/io/cnt/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 28, + "d": 0 + }, + "mne/io/constants.py": { + "a": 7, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 13, + "d": 20 + }, + "mne/io/nicolet/nicolet.py": { + "a": 4, + "d": 25 + }, + "mne/io/utils.py": { + "a": 43, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/295.json b/mne-python/source/doc/sphinxext/prs/295.json new file mode 100644 index 0000000000000000000000000000000000000000..86255bda5db9d25752214fe031476cd8299ebe7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/295.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "20196c73cec697f0d6a9317725e4ac21f6c4d5d1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/export/plot_epochs_as_data_frame.py": { + "a": 21, + "d": 24 + }, + "mne/utils.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2950.json b/mne-python/source/doc/sphinxext/prs/2950.json new file mode 100644 index 0000000000000000000000000000000000000000..86dcd02367cc770b6dae9ce4da318f42f71c8fe7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2950.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "68218218a9066afa8d2dc65222e5d9a4b8c48079", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 17, + "d": 13 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 27, + "d": 0 + }, + "mne/io/pick.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2951.json b/mne-python/source/doc/sphinxext/prs/2951.json new file mode 100644 index 0000000000000000000000000000000000000000..60ba21874cf158d330a92ae1289a059f8cecc480 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2951.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "094a5bb7fbb71cb9941292f100893a843b9bacea", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 12, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2952.json b/mne-python/source/doc/sphinxext/prs/2952.json new file mode 100644 index 0000000000000000000000000000000000000000..47223a8365f577750990c9df5fc905a23294250c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2952.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "da42e7f395cd4a3bcf43725870a16548d4fbfdf3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_dipole_fit.py": { + "a": 40, + "d": 1 + }, + "mne/dipole.py": { + "a": 14, + "d": 9 + }, + "mne/forward/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 135, + "d": 4 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 111, + "d": 4 + }, + "mne/source_space.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2954.json b/mne-python/source/doc/sphinxext/prs/2954.json new file mode 100644 index 0000000000000000000000000000000000000000..bcba6f52af526f2201d9ced4e43a6cbb5441edfc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2954.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "94eb7cba22aa4a0786d5582ebc896e0b2464911f", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/cited.rst": { + "a": 112, + "d": 0 + }, + "doc/cited_mne.py": { + "a": 251, + "d": 0 + }, + "doc/index.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2955.json b/mne-python/source/doc/sphinxext/prs/2955.json new file mode 100644 index 0000000000000000000000000000000000000000..7690d9f10129a5831d02b43aa079c91305e529ff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2955.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3554e677c64db90388ef15dce6651f72d78c6d0c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 4, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2956.json b/mne-python/source/doc/sphinxext/prs/2956.json new file mode 100644 index 0000000000000000000000000000000000000000..d2816363cde2370523a07325650710b614d419af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2956.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "876f8936c1d291169333e3dc3fdb1b46a172854a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 5, + "d": 0 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2957.json b/mne-python/source/doc/sphinxext/prs/2957.json new file mode 100644 index 0000000000000000000000000000000000000000..0890ffd6d623df844f89f83a9369059fb22dc7e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2957.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e3fc2b11cfa517304113443a427879db1f53746b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 16, + "d": 16 + }, + "mne/viz/evoked.py": { + "a": 10, + "d": 10 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2958.json b/mne-python/source/doc/sphinxext/prs/2958.json new file mode 100644 index 0000000000000000000000000000000000000000..1dae7099304e59df717dd52e9ff1a29e54da6d4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2958.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "66a9285b100e2cca3d350d5b83b2732c6ee8a6cc", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/296.json b/mne-python/source/doc/sphinxext/prs/296.json new file mode 100644 index 0000000000000000000000000000000000000000..68ee92153f8e08dce7686c48c8d01872c1353162 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/296.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "354bf2d4f94773b2133cb83ef7db15744d567a62", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 284, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2961.json b/mne-python/source/doc/sphinxext/prs/2961.json new file mode 100644 index 0000000000000000000000000000000000000000..5a40f1ae8b6c7861c50568ba63e736d6e82462e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2961.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bc724819b62985445184a7f2e381a13ce175b944", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/manual/index.rst": { + "a": 8, + "d": 0 + }, + "doc/manual/migrating.rst": { + "a": 54, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2962.json b/mne-python/source/doc/sphinxext/prs/2962.json new file mode 100644 index 0000000000000000000000000000000000000000..5c7f58318fb7b4bcab89ef4cf5dd96b2a85f9272 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2962.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d3f61fd6b57cc56730aa6c34c70574ad67cf7c94", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2963.json b/mne-python/source/doc/sphinxext/prs/2963.json new file mode 100644 index 0000000000000000000000000000000000000000..20a3b62c8501ea591ced83ae29abe8c11dff21df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2963.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1295b83c460727df8e529622c3dfcaa39f5ac0d5", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2964.json b/mne-python/source/doc/sphinxext/prs/2964.json new file mode 100644 index 0000000000000000000000000000000000000000..41802f6e39ddbd50851ff1cc718f2d472bbdae54 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2964.json @@ -0,0 +1,155 @@ +{ + "merge_commit_sha": "10c20e72c41fcc58cc3a2e7807c6765d9b3c8889", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/advanced_setup.rst": { + "a": 0, + "d": 163 + }, + "doc/cite.rst": { + "a": 2, + "d": 2 + }, + "doc/cited.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 12, + "d": 11 + }, + "doc/contributing.rst": { + "a": 4, + "d": 4 + }, + "doc/faq.rst": { + "a": 54, + "d": 1 + }, + "doc/getting_started.rst": { + "a": 325, + "d": 104 + }, + "doc/git_links.inc": { + "a": 2, + "d": 6 + }, + "doc/index.rst": { + "a": 38, + "d": 33 + }, + "doc/manual/datasets_index.rst": { + "a": 6, + "d": 5 + }, + "doc/manual/index.rst": { + "a": 2, + "d": 5 + }, + "doc/manual/migrating.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/preprocessing/maxwell.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 3, + "d": 3 + }, + "doc/manual/time_frequency.rst": { + "a": 4, + "d": 4 + }, + "doc/martinos.rst": { + "a": 35, + "d": 0 + }, + "doc/mne_cpp.rst": { + "a": 9, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 10 + }, + "doc/this_project.inc": { + "a": 4, + "d": 1 + }, + "doc/tutorials/command_line.rst": { + "a": 2, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 6, + "d": 5 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/evoked.py": { + "a": 18, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 0, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 31, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_creating_data_structures.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_raw_objects.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2966.json b/mne-python/source/doc/sphinxext/prs/2966.json new file mode 100644 index 0000000000000000000000000000000000000000..f451645b31f9357ff880928de523dca8428de0dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2966.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d8416766ea5302764a4716836ab9c3658511a578", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2969.json b/mne-python/source/doc/sphinxext/prs/2969.json new file mode 100644 index 0000000000000000000000000000000000000000..ab2982d1dfc8ddfd0a49563f307676cde3cadd9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2969.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "055dbcf36cf7055ac647961dae37e47a31884881", + "authors": [ + { + "n": "Yousra Bekhti", + "e": "yousra.bekhti@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 58, + "d": 6 + }, + "doc/conf.py": { + "a": 5, + "d": 1 + }, + "doc/getting_started.rst": { + "a": 107, + "d": 528 + }, + "doc/index.rst": { + "a": 2, + "d": 1 + }, + "doc/install_mne_c.rst": { + "a": 258, + "d": 0 + }, + "doc/install_mne_python.rst": { + "a": 269, + "d": 0 + }, + "doc/manual/index.rst": { + "a": 115, + "d": 88 + }, + "doc/sphinxext/flow_diagram.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/gen_commands.py": { + "a": 8, + "d": 15 + }, + "doc/tutorials.rst": { + "a": 112, + "d": 52 + }, + "doc/tutorials/command_line.rst": { + "a": 19, + "d": 8 + }, + "doc/tutorials/mne-report.png": { + "a": 0, + "d": 0 + }, + "doc/tutorials/preprocessing/artifacts_suppression.rst": { + "a": 88, + "d": 0 + }, + "doc/tutorials/preprocessing/basic_preprocessing.rst": { + "a": 59, + "d": 0 + }, + "doc/tutorials/preprocessing/data_selection.rst": { + "a": 90, + "d": 0 + }, + "doc/tutorials/report.rst": { + "a": 36, + "d": 24 + }, + "examples/README.txt": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_maxfilter.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/297.json b/mne-python/source/doc/sphinxext/prs/297.json new file mode 100644 index 0000000000000000000000000000000000000000..1cd2819aebf143d0c295f3adbc8b87272f73a43a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/297.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a5a6edf28d8a26ca67a5ac7616bb2748a5bd666", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/utils.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2970.json b/mne-python/source/doc/sphinxext/prs/2970.json new file mode 100644 index 0000000000000000000000000000000000000000..b4f1c9de197b139c2ed5dbe98805e851fc576250 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2970.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "31805d288d4ff7f4bcae8d708d568b59a6c0e26d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/multitaper.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2972.json b/mne-python/source/doc/sphinxext/prs/2972.json new file mode 100644 index 0000000000000000000000000000000000000000..8381315292c56db1c69e0809669a9dc8d52498c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2972.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0b1d5d5ac013514c0202e12aa310751a5906fb48", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/preprocessing/plot_resample.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_linear_regression_raw.py": { + "a": 6, + "d": 5 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 6, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 7, + "d": 5 + }, + "mne/proj.py": { + "a": 7, + "d": 6 + }, + "mne/time_frequency/multitaper.py": { + "a": 30, + "d": 24 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2973.json b/mne-python/source/doc/sphinxext/prs/2973.json new file mode 100644 index 0000000000000000000000000000000000000000..07b5c2d3f39ef521f8ccce345e9034b5837f8223 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2973.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a3509ede1c9de56677824c5dae2a718b89872630", + "authors": [ + { + "n": "Asish Panda", + "e": "asishrocks95@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 15, + "d": 0 + }, + "mne/decoding/time_gen.py": { + "a": 18, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2974.json b/mne-python/source/doc/sphinxext/prs/2974.json new file mode 100644 index 0000000000000000000000000000000000000000..5b42ec638591614ee2a04c960335bd66a3a48c2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2974.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8fe026ef051216ca39d6622a661be1dc50f1e672", + "authors": [ + { + "n": "Camilo Lamus", + "e": null + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 24, + "d": 15 + }, + "mne/forward/tests/test_forward.py": { + "a": 14, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2977.json b/mne-python/source/doc/sphinxext/prs/2977.json new file mode 100644 index 0000000000000000000000000000000000000000..dfe35a4b177a7837c3764a68a0f29a0efa565486 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2977.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f4d6e141cfba1dde8eb90b1a3a5c520a574f51fc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 14, + "d": 10 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 72, + "d": 42 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 11, + "d": 9 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_lead_dots.py": { + "a": 20, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2978.json b/mne-python/source/doc/sphinxext/prs/2978.json new file mode 100644 index 0000000000000000000000000000000000000000..3b54126203e95156b5544246bc1e33c7ccdf69c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2978.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "85b6215e13c6c4caa0dd997c8fbb4bfa26b7cc1c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/preprocessing/plot_resample.py": { + "a": 5, + "d": 4 + }, + "mne/cuda.py": { + "a": 32, + "d": 20 + }, + "mne/epochs.py": { + "a": 9, + "d": 2 + }, + "mne/evoked.py": { + "a": 9, + "d": 2 + }, + "mne/filter.py": { + "a": 27, + "d": 7 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 9, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 15, + "d": 15 + }, + "mne/source_estimate.py": { + "a": 9, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 10, + "d": 7 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_cluster_stats_spatio_temporal.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/298.json b/mne-python/source/doc/sphinxext/prs/298.json new file mode 100644 index 0000000000000000000000000000000000000000..9e1f5e795cf91403d69b8692a657edd4f80fe310 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/298.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "62c1193f58857bfd9ab54f7d2e4dfa474c67aa01", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 46, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2980.json b/mne-python/source/doc/sphinxext/prs/2980.json new file mode 100644 index 0000000000000000000000000000000000000000..a4387f4c51ac4d3144f977512c52a96de1a1a26c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2980.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a72e96ff8523f9b1a2bedb3f482fe2495a43e80f", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2982.json b/mne-python/source/doc/sphinxext/prs/2982.json new file mode 100644 index 0000000000000000000000000000000000000000..7d944646792b51cb848b59983e298159d0a84a29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2982.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5c390fd94c1adc9edbb232f71c36324ceaae25f6", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 0, + "d": 2 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2984.json b/mne-python/source/doc/sphinxext/prs/2984.json new file mode 100644 index 0000000000000000000000000000000000000000..ef1f7db9da9529092722a699c98af99f5bb4949a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2984.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4fa4c5c383a80e48b5871815f1dfdf88810d1815", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2985.json b/mne-python/source/doc/sphinxext/prs/2985.json new file mode 100644 index 0000000000000000000000000000000000000000..b190f31404b8de36a22a45ccf2023186d340bbce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2985.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "af8a0369e8b5dcffd7ffbd188fb7ca5b499e799a", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2987.json b/mne-python/source/doc/sphinxext/prs/2987.json new file mode 100644 index 0000000000000000000000000000000000000000..7547081a61e83ca1d94ae3dc0d400396d62f3b27 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2987.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c728d5a9c523a2346785020c17b056747b689c6a", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/decoding.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2989.json b/mne-python/source/doc/sphinxext/prs/2989.json new file mode 100644 index 0000000000000000000000000000000000000000..b9cbcc24da049b63992f08b09565848c8b114111 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2989.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5efb1ff2d3de0ea74733dc69c2be601d34659ecc", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 3, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/299.json b/mne-python/source/doc/sphinxext/prs/299.json new file mode 100644 index 0000000000000000000000000000000000000000..8b6936798877c2a30759f095d7aed3f5e5952ee2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/299.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "480f54b0934a2eaa18f3b3f72e90b3d283f2d44a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 4, + "d": 6 + }, + "examples/plot_read_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 31, + "d": 18 + }, + "mne/fiff/evoked.py": { + "a": 82, + "d": 44 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 32, + "d": 16 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 3, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 35, + "d": 11 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2990.json b/mne-python/source/doc/sphinxext/prs/2990.json new file mode 100644 index 0000000000000000000000000000000000000000..f152ebe87d669737ecdf94eaa82e3c2d44c6df91 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2990.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "e4e46a69a4cb233f04ffd02c9bc9e1c81140e733", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 3, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_decoding_time_generalization.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 3, + "d": 3 + }, + "examples/stats/plot_linear_regression_raw.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_stockwell.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_clickable_image.py": { + "a": 1, + "d": 1 + }, + "mne/baseline.py": { + "a": 40, + "d": 40 + }, + "mne/datasets/spm_face/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 13, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 3, + "d": 3 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 14, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 7 + }, + "setup.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2991.json b/mne-python/source/doc/sphinxext/prs/2991.json new file mode 100644 index 0000000000000000000000000000000000000000..0e79201d658ae90837be36f73cf560c466d082f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2991.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8e4b3472dca575dae469f994c648aaf117bf11ec", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/defaults.py": { + "a": 4, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2992.json b/mne-python/source/doc/sphinxext/prs/2992.json new file mode 100644 index 0000000000000000000000000000000000000000..453ebdcca3247849b12cc7f67567f820ec0bc43f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2992.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1579466cb630fb000087a73f983a1a6469e2df9b", + "authors": [ + { + "n": "sviter", + "e": "sviter33@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/2993.json b/mne-python/source/doc/sphinxext/prs/2993.json new file mode 100644 index 0000000000000000000000000000000000000000..d759dbeebb068d9213205c835bf063694c69631d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/2993.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bb7a220bcfc6ea7b6dd5abaad5ec218369999742", + "authors": [ + { + "n": "Asish Panda", + "e": "asishrocks95@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 64, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 8, + "d": 8 + }, + "mne/viz/tests/test_epochs.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3.json b/mne-python/source/doc/sphinxext/prs/3.json new file mode 100644 index 0000000000000000000000000000000000000000..fa20109a540a3144f97ff34e9b1ccb251c2fa108 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "8891d764a4b580caa934e1864d43e1608a6d01d2", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/getting_started.rst": { + "a": 2, + "d": 22 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 84, + "d": 0 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 3, + "d": 3 + }, + "mne/baseline.py": { + "a": 5, + "d": 2 + }, + "mne/minimum_norm/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 28, + "d": 12 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 192, + "d": 93 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/30.json b/mne-python/source/doc/sphinxext/prs/30.json new file mode 100644 index 0000000000000000000000000000000000000000..3305ce4ec6a81b7b07c2d3cd1b643d31f7c879e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/30.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e62145fa93c2609fb2fbba40702e8a23db28b894", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/plot_estimate_covariance_matrix.py": { + "a": 2, + "d": 21 + }, + "examples/plot_read_noise_covariance_matrix.py": { + "a": 3, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 0 + }, + "mne/viz.py": { + "a": 63, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/300.json b/mne-python/source/doc/sphinxext/prs/300.json new file mode 100644 index 0000000000000000000000000000000000000000..b53d3e9594fe10fd5a7c2ff740d02a676a3cea0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/300.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "465d0ad8f5c6caf635aa37d3c6f1ac6676351cf1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 2, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3000.json b/mne-python/source/doc/sphinxext/prs/3000.json new file mode 100644 index 0000000000000000000000000000000000000000..8299f9aa96a30593b38c32af54ef60b01209484a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3000.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "be82dc45ed1c1cce9d86a5eca5266f89882c60d9", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3003.json b/mne-python/source/doc/sphinxext/prs/3003.json new file mode 100644 index 0000000000000000000000000000000000000000..489a9dbd7be551b3b420f2189fbf8e03710d463f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3003.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d786b6fcd76ee24adfe223d001d75fba470d6aef", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 7, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 12, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3004.json b/mne-python/source/doc/sphinxext/prs/3004.json new file mode 100644 index 0000000000000000000000000000000000000000..a52d6ec8f0ef7fccca777c1a37173312a20f62d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3004.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "65ca3c13900453604292f0c1a1cf4cc282d1e132", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3007.json b/mne-python/source/doc/sphinxext/prs/3007.json new file mode 100644 index 0000000000000000000000000000000000000000..c3c4fb934000f6a2e6d27c3d8e994058975ddaee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3007.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d3c9b765a39379fea432f174ed1b77a21e06fe09", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3008.json b/mne-python/source/doc/sphinxext/prs/3008.json new file mode 100644 index 0000000000000000000000000000000000000000..8dc8f179660f1b1092a521d57ad60f1a64481780 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3008.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "35193e90f8cb14a3d5441bf2ba7d6b0b148e130e", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 50, + "d": 15 + }, + "mne/stats/tests/test_regression.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3011.json b/mne-python/source/doc/sphinxext/prs/3011.json new file mode 100644 index 0000000000000000000000000000000000000000..910d90e8ac527d25a5069e16336414e6e15db476 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3011.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "710bb22848698f61bdd3f8b943f564ba3d890ce2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 0 + }, + "doc/faq.rst": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3012.json b/mne-python/source/doc/sphinxext/prs/3012.json new file mode 100644 index 0000000000000000000000000000000000000000..dd55539af9459c1361b53fc661ae9e1b5059c9d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3012.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "06b0f6991d4b575b33cb5978dcbd222290427509", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/data/coil_def.dat": { + "a": 28, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3016.json b/mne-python/source/doc/sphinxext/prs/3016.json new file mode 100644 index 0000000000000000000000000000000000000000..b0b3293230a02229872639740ccc746c0015147d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3016.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c9c743f0bb3631cf83d7579d84f3dc748c90cfa1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/cited_mne.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3018.json b/mne-python/source/doc/sphinxext/prs/3018.json new file mode 100644 index 0000000000000000000000000000000000000000..0ac4ee4c291a05267bef65e8954c5754e8630791 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3018.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "49fef4e73b95ffd62607f7da0579afe8601f45c9", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 11, + "d": 7 + }, + "mne/defaults.py": { + "a": 9, + "d": 8 + }, + "mne/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 0 + }, + "mne/io/pick.py": { + "a": 12, + "d": 5 + }, + "mne/io/tests/test_pick.py": { + "a": 11, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3019.json b/mne-python/source/doc/sphinxext/prs/3019.json new file mode 100644 index 0000000000000000000000000000000000000000..c508db9b3b23961bca23cbfe223e570cc4c4c1a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3019.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f2d2bcc41ffee3f27937948d8db5c5dc91c2d205", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "examples/realtime/plot_compute_rt_average.py": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3020.json b/mne-python/source/doc/sphinxext/prs/3020.json new file mode 100644 index 0000000000000000000000000000000000000000..797a36fe683064b3b2cf4913e7e4ef9735a9d179 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3020.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "a430554085baaf53dcdde4ed79e7c19215ca4932", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 28, + "d": 4 + }, + "mne/fixes.py": { + "a": 87, + "d": 8 + }, + "mne/io/base.py": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 25, + "d": 1 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3024.json b/mne-python/source/doc/sphinxext/prs/3024.json new file mode 100644 index 0000000000000000000000000000000000000000..f96adfca288c8fd7215fd8563c50dc4727931af9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3024.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2f425a6de169503fa36e2bb95790adf66fa5f37a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 65, + "d": 65 + }, + "doc/faq.rst": { + "a": 123, + "d": 5 + }, + "doc/getting_started.rst": { + "a": 2, + "d": 0 + }, + "doc/index.rst": { + "a": 1, + "d": 1 + }, + "doc/this_project.inc": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3026.json b/mne-python/source/doc/sphinxext/prs/3026.json new file mode 100644 index 0000000000000000000000000000000000000000..af3c9c4af0afe1d76e0bc6c9a03de3f9008c440a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3026.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7861b8329e0129d5703955eff1202e8806fe57e4", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3027.json b/mne-python/source/doc/sphinxext/prs/3027.json new file mode 100644 index 0000000000000000000000000000000000000000..22f3848905cbd460ef951f6fa6bb6ac401043649 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3027.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "39a3a3a89c6815ca529370ba0b5281e94920d290", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 13, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/303.json b/mne-python/source/doc/sphinxext/prs/303.json new file mode 100644 index 0000000000000000000000000000000000000000..18d3e46943688457c88a95774ba46fdb46039b33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/303.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "99fb1a0b55608226546eebb4017b2914527823a3", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 8, + "d": 0 + }, + "mne/viz.py": { + "a": 20, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3030.json b/mne-python/source/doc/sphinxext/prs/3030.json new file mode 100644 index 0000000000000000000000000000000000000000..94d0a29d23bd044bca636245c0bf39cb377e802d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3030.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0862dd1b9a322be04f64a3b2963f12bea39fde69", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/forward/plot_coregistration_transform.py": { + "a": 1, + "d": 3 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 41, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 128, + "d": 29 + }, + "mne/viz/tests/test_3d.py": { + "a": 32, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3031.json b/mne-python/source/doc/sphinxext/prs/3031.json new file mode 100644 index 0000000000000000000000000000000000000000..b6c9f098df736b79baad26002695a40a8ef11a1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3031.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0b923a5f10fd720857e5100809462eded8013746", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 9, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 19, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3032.json b/mne-python/source/doc/sphinxext/prs/3032.json new file mode 100644 index 0000000000000000000000000000000000000000..aad3e66009a5df8917fa4983eadfa727e1683aac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3032.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3092b72daf804ead4a1c38da707962786c938020", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/index.rst": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3033.json b/mne-python/source/doc/sphinxext/prs/3033.json new file mode 100644 index 0000000000000000000000000000000000000000..78ee493127b409be8ee0feb2e133abab44bd7ce2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3033.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "96ed572d38921e6305b686a8dbdc426da2833dd9", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 60, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 14, + "d": 10 + }, + "mne/viz/raw.py": { + "a": 8, + "d": 4 + }, + "mne/viz/tests/test_topo.py": { + "a": 9, + "d": 5 + }, + "mne/viz/topo.py": { + "a": 123, + "d": 70 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3034.json b/mne-python/source/doc/sphinxext/prs/3034.json new file mode 100644 index 0000000000000000000000000000000000000000..141bc570039f6380e38aff32b9461cdfdcb22304 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3034.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b531a80d4906ed1dc7ecf5b52ac2923bd99c47ad", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 13, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 57, + "d": 70 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3035.json b/mne-python/source/doc/sphinxext/prs/3035.json new file mode 100644 index 0000000000000000000000000000000000000000..04b426407895e78e81464cced9d35aa53afce649 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3035.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "77eb1fccd9e1a78b94cc5291ed1ec05f01c96457", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 22, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3040.json b/mne-python/source/doc/sphinxext/prs/3040.json new file mode 100644 index 0000000000000000000000000000000000000000..cfd2dc0ab87a7974c949ebd8e076c18d9e49a415 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3040.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1579eb5f3e71e4c73bbd4545b93c03310939fb26", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3041.json b/mne-python/source/doc/sphinxext/prs/3041.json new file mode 100644 index 0000000000000000000000000000000000000000..88b1c063b97c3792cbbdedb2d8efb22c6dff33ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3041.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1a9c1b0b4983bae6d3970560e896097e3069d449", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 13, + "d": 6 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3042.json b/mne-python/source/doc/sphinxext/prs/3042.json new file mode 100644 index 0000000000000000000000000000000000000000..d3975c9782b7c883e135b219be6600cd4898dda9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3042.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "da6adca4bef00de277368eeae9fab43831169f3a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 24, + "d": 10 + }, + "mne/tests/test_event.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3048.json b/mne-python/source/doc/sphinxext/prs/3048.json new file mode 100644 index 0000000000000000000000000000000000000000..bd94448c4f19acfe291376475c10e27627d1ddae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3048.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ecd7b17f7d0ee0ba8908e69514e629e70b2ba21e", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 17, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3050.json b/mne-python/source/doc/sphinxext/prs/3050.json new file mode 100644 index 0000000000000000000000000000000000000000..ce2c9297fce8fe6fa6c55e8df542cb2326e082ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3050.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d7d0224dac62ab47d11f0fd3c4e33a501a14420e", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_sensors.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 7, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3051.json b/mne-python/source/doc/sphinxext/prs/3051.json new file mode 100644 index 0000000000000000000000000000000000000000..2ca5449a970a9c60ebdd7371d593bf4553f140fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3051.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7774365d4ee44eb105b4b491a5f74ef525c7071c", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3055.json b/mne-python/source/doc/sphinxext/prs/3055.json new file mode 100644 index 0000000000000000000000000000000000000000..8c98bf642ddd5bed5cc3ff12fce8a29a2b672305 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3055.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4ea477bf6e876d353b270445b0fd8ffb48841d89", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3057.json b/mne-python/source/doc/sphinxext/prs/3057.json new file mode 100644 index 0000000000000000000000000000000000000000..8e708f8d02971451d5d7b4290d7d1b1cc0b002e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3057.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "caab61377a56cacbe75ea9804599e9a09152a831", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3058.json b/mne-python/source/doc/sphinxext/prs/3058.json new file mode 100644 index 0000000000000000000000000000000000000000..b5cc269ff133904502abdf2fb1c2b64ab86fa359 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3058.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "af40bd630ead348979fdaa055d510b8e7fb72f91", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 50, + "d": 24 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3059.json b/mne-python/source/doc/sphinxext/prs/3059.json new file mode 100644 index 0000000000000000000000000000000000000000..e5256574188c40fbbb7b5a8347438f168be89f5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3059.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5f389c5c44f80e9df4efeae15506c10515a56276", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 10, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/306.json b/mne-python/source/doc/sphinxext/prs/306.json new file mode 100644 index 0000000000000000000000000000000000000000..ad4c7742291d9d1aa1aa8d8edbf8835d2a3e8514 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/306.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e862d55d1df9cbd952b83ab80c7848c58adc1ebd", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/proj.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3064.json b/mne-python/source/doc/sphinxext/prs/3064.json new file mode 100644 index 0000000000000000000000000000000000000000..cf8a1d074db2b6463c94dbd0910b57ab288c38b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3064.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4227b7603898eb29f43787c3388517f758777875", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3065.json b/mne-python/source/doc/sphinxext/prs/3065.json new file mode 100644 index 0000000000000000000000000000000000000000..43e96812baebf41bd8152dbe7afd25c4e9590205 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3065.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "547e80eb73e054c535b49325b037b1a1459f6ecc", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 3, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_topo_channel_epochs_image.py": { + "a": 3, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 43, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 24, + "d": 2 + }, + "mne/channels/tests/test_layout.py": { + "a": 7, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 7 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 12, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 52, + "d": 12 + }, + "mne/viz/utils.py": { + "a": 129, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3066.json b/mne-python/source/doc/sphinxext/prs/3066.json new file mode 100644 index 0000000000000000000000000000000000000000..46f36fa1e3fb8b6e8d39700a9417cfc6e3bd8cfd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3066.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "62be106bae5b0f7b9cf455f1efd3186e88ef70b5", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 4, + "d": 6 + }, + "doc/Makefile": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3067.json b/mne-python/source/doc/sphinxext/prs/3067.json new file mode 100644 index 0000000000000000000000000000000000000000..d57313d86ab263f3dde95a8ac3a77381b7ea3bde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3067.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b16542351011e56ec1c778ea264260e5e9278a3b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 19, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/307.json b/mne-python/source/doc/sphinxext/prs/307.json new file mode 100644 index 0000000000000000000000000000000000000000..dfb44ff72dbc37a02326bd17aab945bda6c26a7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/307.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1cb92741cfee06b70c08ce24b847a6d667de0db9", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/tests/test_ica.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3072.json b/mne-python/source/doc/sphinxext/prs/3072.json new file mode 100644 index 0000000000000000000000000000000000000000..1b37e0dc8414af1df15d56c55773304d95ba0f33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3072.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4e83089dd911ff580f766c1ad2d4cfd0e2b700f1", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3074.json b/mne-python/source/doc/sphinxext/prs/3074.json new file mode 100644 index 0000000000000000000000000000000000000000..38b34dd5ffa1218a6d6ba3a0b81347874bff29df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3074.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cfd4f2e12217918c55fcb1eb1f0cc5ff390a14fd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 28, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3076.json b/mne-python/source/doc/sphinxext/prs/3076.json new file mode 100644 index 0000000000000000000000000000000000000000..7cb6c5c720307cdd5f80f13c068ae6c249dce4c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3076.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e61f8be7a8fbe77cfe2dc1aeede62440ebe216a5", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/event.py": { + "a": 36, + "d": 8 + }, + "mne/tests/test_event.py": { + "a": 32, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3077.json b/mne-python/source/doc/sphinxext/prs/3077.json new file mode 100644 index 0000000000000000000000000000000000000000..5c3e654cfe71853a7873b0ea8d1b5f637aec06ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3077.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4a1b3d517d4a8d922cf27f09f3a9cf4493c7abd5", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 22, + "d": 15 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 18, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3079.json b/mne-python/source/doc/sphinxext/prs/3079.json new file mode 100644 index 0000000000000000000000000000000000000000..8c5d5e42cf4b1e38d7f1b9370fe8b4d18780721d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3079.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "3b82ea99fe1a4637cef5f757c7f0feaf4cd9501a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 6, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 18, + "d": 10 + }, + "mne/io/base.py": { + "a": 109, + "d": 76 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/308.json b/mne-python/source/doc/sphinxext/prs/308.json new file mode 100644 index 0000000000000000000000000000000000000000..9a257845a55a67c41a74a969762ab4da7994515b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/308.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bb7aaff1664d8e09e60a3dda98babadc5000bf8e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3080.json b/mne-python/source/doc/sphinxext/prs/3080.json new file mode 100644 index 0000000000000000000000000000000000000000..06ef528096d36e1333abda40b5a63238b5dd1bd8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3080.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2bf44489c08a7d37380071f1667e484daf1d00f2", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/stats/regression.py": { + "a": 9, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3085.json b/mne-python/source/doc/sphinxext/prs/3085.json new file mode 100644 index 0000000000000000000000000000000000000000..fef4840e51003358af921b89d29c02f2c048d250 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3085.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f4f302f78486b9e6af99faac072e0ac6cda3b2d2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 7, + "d": 9 + }, + "mne/evoked.py": { + "a": 6, + "d": 4 + }, + "mne/stats/regression.py": { + "a": 8, + "d": 9 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3087.json b/mne-python/source/doc/sphinxext/prs/3087.json new file mode 100644 index 0000000000000000000000000000000000000000..5a99b2c2f7c0fd8e719d9ad6fd9a5aee230e60de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3087.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "4c0c323f79bfc77c80e7277da8734334782abc93", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/install_mne_c.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/cookbook.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/source_localization/forward.rst": { + "a": 6, + "d": 2 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 7, + "d": 7 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "tutorials/plot_creating_data_structures.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3093.json b/mne-python/source/doc/sphinxext/prs/3093.json new file mode 100644 index 0000000000000000000000000000000000000000..14afe8003278504abbe548968427b4e65bbdf059 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3093.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3ca35b7e3d6403e77788158922e7924146696761", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 12, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3096.json b/mne-python/source/doc/sphinxext/prs/3096.json new file mode 100644 index 0000000000000000000000000000000000000000..09b381af4a3b0b8e4b5df41394d6ec3e34c2b5af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3096.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "98d13c860df1f62841825194fc471fe6ddcd31d2", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3098.json b/mne-python/source/doc/sphinxext/prs/3098.json new file mode 100644 index 0000000000000000000000000000000000000000..da236cd90d8b67a0c88bd70b824da51344610232 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3098.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b96689e6d67c3c1d1375e2f728dfb31bfbebedac", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/stats/parametric.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_utils.py": { + "a": 7, + "d": 1 + }, + "mne/utils.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/31.json b/mne-python/source/doc/sphinxext/prs/31.json new file mode 100644 index 0000000000000000000000000000000000000000..0f3dc6bd6fb18907d3fa183b1041b2ee3f7b3710 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/31.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "1a62954a82835c4e9781151cdf0a387a0bc20dfd", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 30, + "d": 193 + }, + "mne/fiff/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/constants.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/cov.py": { + "a": 174, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 6, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3102.json b/mne-python/source/doc/sphinxext/prs/3102.json new file mode 100644 index 0000000000000000000000000000000000000000..2dcdf6085ac2beb70872fdd958899e89dda7b1d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3102.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4ab8801ded0649edb350156aaca300319ca1cb95", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/surface.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3104.json b/mne-python/source/doc/sphinxext/prs/3104.json new file mode 100644 index 0000000000000000000000000000000000000000..673f7a1dfd640f01283ae9abcc23ce3292e15377 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3104.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1e885652ec705edc9b39d3cd15fc0704e13ea74f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3106.json b/mne-python/source/doc/sphinxext/prs/3106.json new file mode 100644 index 0000000000000000000000000000000000000000..46eb94d600422df8ba8a0b33ace49f132e92b601 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3106.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6cb00360f539c413a79690ec67377e5b920279c2", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/decoding/transformer.py": { + "a": 2, + "d": 2 + }, + "mne/io/pick.py": { + "a": 7, + "d": 0 + }, + "mne/io/tests/test_pick.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3108.json b/mne-python/source/doc/sphinxext/prs/3108.json new file mode 100644 index 0000000000000000000000000000000000000000..67162f668e3c3734b688a852e08c3185f1def652 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3108.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e549bf408a1adcb10f41caf51350f7af1aebfc38", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 10, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3109.json b/mne-python/source/doc/sphinxext/prs/3109.json new file mode 100644 index 0000000000000000000000000000000000000000..61dbdebfa5db7b7546c15fd9dc498725ca0f1fb5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3109.json @@ -0,0 +1,447 @@ +{ + "merge_commit_sha": "dd945658a8d45b2b867d6d3e379050086a9e64e0", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/index.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/memory.rst": { + "a": 2, + "d": 2 + }, + "doc/manual/migrating.rst": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 1, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 1, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 1, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 1, + "d": 2 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 1, + "d": 2 + }, + "examples/datasets/plot_megsim_data.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_sensors.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 2, + "d": 3 + }, + "examples/io/plot_read_and_write_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/plot_extract_events_from_raw.py": { + "a": 1, + "d": 2 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_corrmap_detection.py": { + "a": 1, + "d": 3 + }, + "examples/preprocessing/plot_define_target_events.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_eog_artifact_histogram.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_estimate_covariance_matrix_baseline.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_estimate_covariance_matrix_raw.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_maxwell_filter.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_movement_compensation.py": { + "a": 3, + "d": 2 + }, + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_resample.py": { + "a": 1, + "d": 2 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 1, + "d": 2 + }, + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 9, + "d": 11 + }, + "examples/simulation/plot_simulate_raw_data.py": { + "a": 3, + "d": 2 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_sensor_regression.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_source_psd_epochs.py": { + "a": 1, + "d": 2 + }, + "examples/time_frequency/plot_epochs_spectra.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_stockwell.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_multitaper_sensors.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_sensors.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_evoked_delayed_ssp.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_evoked_topomap_delayed_ssp.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 3, + "d": 2 + }, + "examples/visualization/plot_topo_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_topo_compare_conditions.py": { + "a": 1, + "d": 2 + }, + "examples/visualization/plot_topo_customized.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_browse_raw.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_csp.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 4, + "d": 4 + }, + "mne/io/tests/test_proc_history.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 2, + "d": 1 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 3, + "d": 3 + }, + "mne/stats/tests/test_regression.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_event.py": { + "a": 6, + "d": 6 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_decoding.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_cluster_stats_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_source_localization_basics.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_spatio_temporal_cluster_stats_sensor.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/311.json b/mne-python/source/doc/sphinxext/prs/311.json new file mode 100644 index 0000000000000000000000000000000000000000..dd4299babfd646b5b7178dbdc100b9023cca3996 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/311.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "caeb8c2ae2d6b4a4e1e319d391f9c040a3d374a2", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3110.json b/mne-python/source/doc/sphinxext/prs/3110.json new file mode 100644 index 0000000000000000000000000000000000000000..c5b23eddcbb75631287913bc6d1782948d87504c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3110.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "f202ce34fcd296c5a9727bde808f6aa2383c1b9f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".gitignore": { + "a": 2, + "d": 1 + }, + "doc/manual/memory.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 1, + "d": 1 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 56, + "d": 25 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 22, + "d": 22 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 3 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_epochs.py": { + "a": 24, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3111.json b/mne-python/source/doc/sphinxext/prs/3111.json new file mode 100644 index 0000000000000000000000000000000000000000..a77a26f95f870df270217acd57e7d5e39cd36668 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3111.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7f84bd70c7830eb6cfd9673d21bd4a6c39019e1d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/base.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3114.json b/mne-python/source/doc/sphinxext/prs/3114.json new file mode 100644 index 0000000000000000000000000000000000000000..97a3b5ed35809be6511c01dec510bafe3fd05917 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3114.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d7530ddf5da295e0a23178df48fd648c7039a897", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/epochs.py": { + "a": 6, + "d": 0 + }, + "mne/evoked.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3115.json b/mne-python/source/doc/sphinxext/prs/3115.json new file mode 100644 index 0000000000000000000000000000000000000000..ee0d98a2342e5b4bfb8ccdd7cc58704d20ad38bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3115.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4c2b4a765c3a973b8bedfea798ad18796e309b39", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 26, + "d": 4 + }, + "mne/tests/test_cov.py": { + "a": 37, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3119.json b/mne-python/source/doc/sphinxext/prs/3119.json new file mode 100644 index 0000000000000000000000000000000000000000..95d1909fc28c8ca43c187a284a663160d4d39834 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3119.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "90c43d7ccaca46dc784b2001cf00e5d990f80e62", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_evoked_topomap_delayed_ssp.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_ssp_projs_sensitivity_map.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_ssp_projs_topomaps.py": { + "a": 4, + "d": 2 + }, + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 2 + }, + "mne/io/proj.py": { + "a": 8, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 5, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3122.json b/mne-python/source/doc/sphinxext/prs/3122.json new file mode 100644 index 0000000000000000000000000000000000000000..72f1ebb4d44d3757ce6640a95937a68e218339e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3122.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "38db591159f0f73b642594864a5770b78de36f0a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 6 + }, + "mne/dipole.py": { + "a": 286, + "d": 102 + }, + "mne/tests/test_dipole.py": { + "a": 54, + "d": 8 + }, + "tutorials/plot_dipole_fit.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3129.json b/mne-python/source/doc/sphinxext/prs/3129.json new file mode 100644 index 0000000000000000000000000000000000000000..b6cc632ba52e5c41db3bd17146499ff9c96e0dca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3129.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "741259072d81d17c70acf4f247cf18640934d5cc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 31, + "d": 23 + }, + "mne/utils.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/313.json b/mne-python/source/doc/sphinxext/prs/313.json new file mode 100644 index 0000000000000000000000000000000000000000..a009bf864b15e5063526ba19e6a23a4cf2f51733 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/313.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c033cdf5100eb707997da37bd06a5c722b631570", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/sphinxext/gen_rst.py": { + "a": 33, + "d": 5 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3131.json b/mne-python/source/doc/sphinxext/prs/3131.json new file mode 100644 index 0000000000000000000000000000000000000000..817296de28b6f9ec17a38e8392e53c753d4f6286 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3131.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "62bd319e587c0af0207bcead609545cc1ffa72c4", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/io/cnt/cnt.py": { + "a": 16, + "d": 14 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3132.json b/mne-python/source/doc/sphinxext/prs/3132.json new file mode 100644 index 0000000000000000000000000000000000000000..85739ad965ba9eed9ee31c3b164ff8e525ed0655 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3132.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "eb3fdfd6e7adf381744cb6d283efb9c3a087867f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 52, + "d": 47 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 9, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 25 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 8, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3136.json b/mne-python/source/doc/sphinxext/prs/3136.json new file mode 100644 index 0000000000000000000000000000000000000000..3fc7834eff6ef9c1d37d68b577369fa4182576b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3136.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c30f617fa59f4c4d1270c34be631d7889ebf87a0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_ssp_projs_sensitivity_map.py": { + "a": 2, + "d": 1 + }, + "mne/proj.py": { + "a": 6, + "d": 3 + }, + "mne/tests/test_proj.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3137.json b/mne-python/source/doc/sphinxext/prs/3137.json new file mode 100644 index 0000000000000000000000000000000000000000..37033eb79c8d4b10c40ba6faef73ee077c00c416 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3137.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "28f41b0add25d8e191f4bc208da21eb1fbd142c7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "appveyor.yml": { + "a": 1, + "d": 0 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3139.json b/mne-python/source/doc/sphinxext/prs/3139.json new file mode 100644 index 0000000000000000000000000000000000000000..eaff5172aa0c0d6a2cfac04d8d699996cd97fdde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3139.json @@ -0,0 +1,275 @@ +{ + "merge_commit_sha": "5346d694acc187c5407cd2356db31eba9721f1f7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_brainstorm_data.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_resample.py": { + "a": 6, + "d": 6 + }, + "examples/simulation/plot_simulate_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 2, + "d": 5 + }, + "mne/baseline.py": { + "a": 2, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 41, + "d": 29 + }, + "mne/channels/interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 5, + "d": 6 + }, + "mne/cov.py": { + "a": 13, + "d": 17 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_ems.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 29, + "d": 28 + }, + "mne/evoked.py": { + "a": 7, + "d": 4 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 14, + "d": 14 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 4, + "d": 4 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 39, + "d": 57 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 43, + "d": 43 + }, + "mne/io/matrix.py": { + "a": 8, + "d": 7 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/reference.py": { + "a": 6, + "d": 9 + }, + "mne/io/tests/test_pick.py": { + "a": 1, + "d": 5 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_reference.py": { + "a": 9, + "d": 10 + }, + "mne/label.py": { + "a": 12, + "d": 10 + }, + "mne/minimum_norm/inverse.py": { + "a": 17, + "d": 12 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 15, + "d": 27 + }, + "mne/preprocessing/stim.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 13, + "d": 13 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 13, + "d": 12 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 3, + "d": 3 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 4, + "d": 4 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 8, + "d": 6 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 32, + "d": 33 + }, + "mne/tests/test_evoked.py": { + "a": 9, + "d": 9 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 6, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 14, + "d": 6 + }, + "mne/utils.py": { + "a": 25, + "d": 6 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 5, + "d": 5 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 3 + }, + "mne/viz/tests/test_topo.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 4, + "d": 6 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_raw.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/314.json b/mne-python/source/doc/sphinxext/prs/314.json new file mode 100644 index 0000000000000000000000000000000000000000..89670ccd404b4e9127a40a89a0c4c3dab2c44383 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/314.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "17dc87d5fb2bf5c00fbca5d9e9cbda757ce4611d", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/_templates/layout.html": { + "a": 17, + "d": 0 + }, + "doc/source/conf.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3141.json b/mne-python/source/doc/sphinxext/prs/3141.json new file mode 100644 index 0000000000000000000000000000000000000000..709d75d38ddce7aa0e2bc5cdfbb001c672c931f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3141.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e0f8b1134aff9278721951629b97e1c5059635a0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 25, + "d": 15 + }, + "mne/source_space.py": { + "a": 34, + "d": 15 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3143.json b/mne-python/source/doc/sphinxext/prs/3143.json new file mode 100644 index 0000000000000000000000000000000000000000..f069ae4abbb70a083a2aef53ae707db7bf3d871c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3143.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "767d84b0f73cbfefa94b400287f8579f970b85f9", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 1 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 19, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 133, + "d": 59 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3144.json b/mne-python/source/doc/sphinxext/prs/3144.json new file mode 100644 index 0000000000000000000000000000000000000000..c7bf80b3a589b7eb7f201ab6fa1e21ca94a9cb81 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3144.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "40b668f8ea6d0d4412f586493d98ebd071a5081c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 41, + "d": 5 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 11, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3145.json b/mne-python/source/doc/sphinxext/prs/3145.json new file mode 100644 index 0000000000000000000000000000000000000000..e759c1cee51e1b5f1d3eb941e84ef721b58713b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3145.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e48d5e92b8a03b8636f7930e78f32d9167b9812", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3146.json b/mne-python/source/doc/sphinxext/prs/3146.json new file mode 100644 index 0000000000000000000000000000000000000000..492fc2d661504afd96c2a9f332065a37468a7914 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3146.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "1c2791dc6447678957f3c00b1f44d4dd6f600cd0", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/faq.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/appendix/c_release_notes.rst": { + "a": 4, + "d": 6 + }, + "doc/manual/c_reference.rst": { + "a": 17, + "d": 17 + }, + "doc/manual/channel_interpolation.rst": { + "a": 2, + "d": 1 + }, + "doc/manual/decoding.rst": { + "a": 2, + "d": 1 + }, + "doc/manual/gui/analyze.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/gui/browse.rst": { + "a": 2, + "d": 2 + }, + "doc/manual/index.rst": { + "a": 0, + "d": 1 + }, + "doc/manual/io.rst": { + "a": 6, + "d": 8 + }, + "doc/manual/matlab.rst": { + "a": 5, + "d": 6 + }, + "doc/manual/memory.rst": { + "a": 2, + "d": 1 + }, + "doc/manual/pitfalls.rst": { + "a": 21, + "d": 5 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/sample_dataset.rst": { + "a": 4, + "d": 3 + }, + "doc/manual/source_localization/covariance.rst": { + "a": 0, + "d": 5 + }, + "doc/manual/source_localization/inverse.rst": { + "a": 49, + "d": 33 + }, + "doc/tutorials.rst": { + "a": 0, + "d": 1 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 0, + "d": 84 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 1 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_compute_covariance.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_eeg_erp.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_info.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_raw.py": { + "a": 8, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3147.json b/mne-python/source/doc/sphinxext/prs/3147.json new file mode 100644 index 0000000000000000000000000000000000000000..9064197218f710957feaaee7db521ee537ec03bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3147.json @@ -0,0 +1,147 @@ +{ + "merge_commit_sha": "c5a52b496a19592ec53c153a4e861913eae4ff77", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 0, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 0 + }, + "mne/channels/tests/test_layout.py": { + "a": 22, + "d": 42 + }, + "mne/dipole.py": { + "a": 2, + "d": 0 + }, + "mne/forward/_field_interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 0 + }, + "mne/io/array/array.py": { + "a": 0, + "d": 1 + }, + "mne/io/base.py": { + "a": 5, + "d": 5 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 20, + "d": 170 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 5, + "d": 3 + }, + "mne/io/reference.py": { + "a": 3, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 5, + "d": 50 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 0 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3148.json b/mne-python/source/doc/sphinxext/prs/3148.json new file mode 100644 index 0000000000000000000000000000000000000000..406010061184739a3df6b13be00d786cac95e06d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3148.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "604cf50d6e7a65d80f7795e78557392587a1c7d5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/selection.py": { + "a": 61, + "d": 56 + }, + "mne/tests/test_selection.py": { + "a": 27, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3150.json b/mne-python/source/doc/sphinxext/prs/3150.json new file mode 100644 index 0000000000000000000000000000000000000000..dab23355f7b51b637d022ce3b9d7921442df5929 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3150.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "5bfde4dc14e643e30a009316437ee424c77b6b9d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 2, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 2 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/bem.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 6, + "d": 6 + }, + "mne/cov.py": { + "a": 3, + "d": 3 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 3 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_creating_data_structures.py": { + "a": 4, + "d": 4 + }, + "tutorials/plot_info.py": { + "a": 4, + "d": 4 + }, + "tutorials/plot_object_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_evoked.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_raw.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3151.json b/mne-python/source/doc/sphinxext/prs/3151.json new file mode 100644 index 0000000000000000000000000000000000000000..e2e50cb500ab8cc36b3b56dc7f2a7624abd7a92b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3151.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a9c5d3850fa5e8a35ef7817d4e7b6549484348d4", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/evoked.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3152.json b/mne-python/source/doc/sphinxext/prs/3152.json new file mode 100644 index 0000000000000000000000000000000000000000..2ac7483856fb48a15a72bb920b3419a423c6c93d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3152.json @@ -0,0 +1,187 @@ +{ + "merge_commit_sha": "bbaa5a80b4ebdfc99a942b87e670859c23a384f1", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 4, + "d": 0 + }, + "doc/tutorials.rst": { + "a": 0, + "d": 2 + }, + "examples/README.txt": { + "a": 0, + "d": 3 + }, + "examples/decoding/plot_decoding_time_generalization.py": { + "a": 0, + "d": 55 + }, + "examples/forward/plot_bem_contour_mri.py": { + "a": 0, + "d": 27 + }, + "examples/forward/plot_coregistration_transform.py": { + "a": 0, + "d": 31 + }, + "examples/io/README.txt": { + "a": 2, + "d": 1 + }, + "examples/io/plot_objects_from_arrays.py": { + "a": 5, + "d": 4 + }, + "examples/io/plot_read_evoked.py": { + "a": 5, + "d": 0 + }, + "examples/plot_compute_mne_inverse.py": { + "a": 0, + "d": 60 + }, + "examples/plot_extract_events_from_raw.py": { + "a": 0, + "d": 40 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 0, + "d": 77 + }, + "examples/preprocessing/plot_corrmap_detection.py": { + "a": 0, + "d": 74 + }, + "examples/preprocessing/plot_estimate_covariance_matrix_baseline.py": { + "a": 0, + "d": 55 + }, + "examples/preprocessing/plot_estimate_covariance_matrix_raw.py": { + "a": 0, + "d": 38 + }, + "examples/time_frequency/plot_stockwell.py": { + "a": 0, + "d": 50 + }, + "examples/time_frequency/plot_time_frequency_multitaper_sensors.py": { + "a": 0, + "d": 55 + }, + "examples/visualization/plot_evoked_erf_erp.py": { + "a": 0, + "d": 51 + }, + "examples/visualization/plot_joint_evoked_topomap.py": { + "a": 0, + "d": 34 + }, + "examples/visualization/plot_meg_eeg_fields_3d.py": { + "a": 0, + "d": 46 + }, + "examples/visualization/plot_ssp_projs_topomaps.py": { + "a": 0, + "d": 31 + }, + "examples/visualization/plot_topo_channel_epochs_image.py": { + "a": 0, + "d": 58 + }, + "examples/visualization/plot_topography.py": { + "a": 0, + "d": 33 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 5, + "d": 5 + }, + "tutorials/plot_artifacts_detection.py": { + "a": 56, + "d": 1 + }, + "tutorials/plot_artifacts_intro.py": { + "a": 0, + "d": 60 + }, + "tutorials/plot_compute_covariance.py": { + "a": 16, + "d": 7 + }, + "tutorials/plot_creating_data_structures.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 9, + "d": 1 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 29, + "d": 11 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 3, + "d": 0 + }, + "tutorials/plot_stats_cluster_methods.py": { + "a": 16, + "d": 8 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 30, + "d": 20 + }, + "tutorials/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 6, + "d": 3 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 52, + "d": 38 + }, + "tutorials/plot_stats_cluster_time_frequency.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 49, + "d": 31 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 17, + "d": 14 + }, + "tutorials/plot_visualize_epochs.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 35, + "d": 30 + }, + "tutorials/plot_visualize_raw.py": { + "a": 21, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3154.json b/mne-python/source/doc/sphinxext/prs/3154.json new file mode 100644 index 0000000000000000000000000000000000000000..5ffca38642c98a428130705b6bdb6f3d7a46c249 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3154.json @@ -0,0 +1,179 @@ +{ + "merge_commit_sha": "b9f34a994136c81b10b91bf1b3afc1c96e2d1ead", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 8, + "d": 0 + }, + "Makefile": { + "a": 8, + "d": 4 + }, + "dictionary.txt": { + "a": 254, + "d": 19 + }, + "doc/manual/c_reference.rst": { + "a": 3, + "d": 3 + }, + "doc/manual/io.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/preprocessing/maxwell.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/time_frequency.rst": { + "a": 3, + "d": 3 + }, + "doc/references.rst": { + "a": 7, + "d": 7 + }, + "doc/tutorials/seven_stories_about_mne.rst": { + "a": 2, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_resample.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 4, + "d": 4 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 2 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/infomax_.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/xdawn.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_forward.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3155.json b/mne-python/source/doc/sphinxext/prs/3155.json new file mode 100644 index 0000000000000000000000000000000000000000..c5f290450b14c2d1ed33c4e00262c985705c28f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3155.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f7c9eead4c0846ef997c22d79a2ae07092652313", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 56, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3157.json b/mne-python/source/doc/sphinxext/prs/3157.json new file mode 100644 index 0000000000000000000000000000000000000000..7b53bb88f13c1809588a4218087bcf2b4c9e6e0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3157.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "f05bd2a2563c96eb92f47a0225e0abf1a5ddeedc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 17, + "d": 14 + }, + "mne/channels/tests/test_channels.py": { + "a": 10, + "d": 6 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 14, + "d": 7 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/time_gen.py": { + "a": 2, + "d": 4 + }, + "mne/defaults.py": { + "a": 7, + "d": 6 + }, + "mne/epochs.py": { + "a": 7, + "d": 9 + }, + "mne/evoked.py": { + "a": 11, + "d": 13 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 2 + }, + "mne/io/pick.py": { + "a": 27, + "d": 18 + }, + "mne/io/tests/test_pick.py": { + "a": 36, + "d": 22 + }, + "mne/preprocessing/ica.py": { + "a": 14, + "d": 11 + }, + "mne/tests/test_epochs.py": { + "a": 10, + "d": 7 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 8, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3158.json b/mne-python/source/doc/sphinxext/prs/3158.json new file mode 100644 index 0000000000000000000000000000000000000000..56fdb68cabb7ab8bd68bb13f8e624220ccfad208 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3158.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0a181054a2dfa02ea2f9fa2e6a28f46989a3face", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 0, + "d": 1 + }, + "mne/forward/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 6 + }, + "mne/forward/forward.py": { + "a": 90, + "d": 17 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 14, + "d": 88 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3159.json b/mne-python/source/doc/sphinxext/prs/3159.json new file mode 100644 index 0000000000000000000000000000000000000000..3bfd447566509aaba34afff4b226a2107bc04545 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3159.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3f53de69ba7e2354bf304e25196bb2556fc5863a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 10, + "d": 2 + }, + "mne/dipole.py": { + "a": 16, + "d": 5 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 35, + "d": 33 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/316.json b/mne-python/source/doc/sphinxext/prs/316.json new file mode 100644 index 0000000000000000000000000000000000000000..fa889de0f6e81e30cf1982d2b03da5fbf9bb248a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/316.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4a886f6e8a7fd46bf7f990bbad2b786755555a1e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 13, + "d": 3 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 123, + "d": 20 + }, + "mne/fiff/tests/test_raw.py": { + "a": 38, + "d": 14 + }, + "mne/filter.py": { + "a": 324, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 59, + "d": 7 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3161.json b/mne-python/source/doc/sphinxext/prs/3161.json new file mode 100644 index 0000000000000000000000000000000000000000..d77c4e5b0928dfddc0db6f384178fd1f9346b6c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3161.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b5a7c26f8a843d615dbb63ed3b13aae7d65fde2e", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/stats/plot_linear_regression_raw.py": { + "a": 22, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3162.json b/mne-python/source/doc/sphinxext/prs/3162.json new file mode 100644 index 0000000000000000000000000000000000000000..b672f779bfa92fddfb66ef09e41d00069e1323ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3162.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "95355592de583a9758b4531ede4f12a88d543a2a", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 42, + "d": 25 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 81, + "d": 57 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3165.json b/mne-python/source/doc/sphinxext/prs/3165.json new file mode 100644 index 0000000000000000000000000000000000000000..a16aa0bd095bf41efee8aaedd765c2b02aae6ffc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3165.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4badef68fdb60412f0bdbda2d8f3d2a426e32c58", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 8, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 40, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3166.json b/mne-python/source/doc/sphinxext/prs/3166.json new file mode 100644 index 0000000000000000000000000000000000000000..598375c9e791a00c7d327f654ae1d5c226daca92 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3166.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d170cd108b11aa828696c2b50c3f5ccaef09bc7c", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "tutorials/plot_eeg_erp.py": { + "a": 64, + "d": 1 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 12, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 24, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3167.json b/mne-python/source/doc/sphinxext/prs/3167.json new file mode 100644 index 0000000000000000000000000000000000000000..9071b240c24ecf867d349b4945d05668936080a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3167.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b25fbf28a83ea45021933d891a74f02b4bdfe5a9", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/getting_started.rst": { + "a": 3, + "d": 3 + }, + "tutorials/plot_introduction.py": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3171.json b/mne-python/source/doc/sphinxext/prs/3171.json new file mode 100644 index 0000000000000000000000000000000000000000..913ab03e4833b60057f0a2f7f9d9c44a523ab452 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3171.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0ac35dc88f4711fbd54677025dd15a0627b18b39", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/stats/parametric.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3172.json b/mne-python/source/doc/sphinxext/prs/3172.json new file mode 100644 index 0000000000000000000000000000000000000000..43f7ae3a73cba10e89e2e90afb5829493d64ad29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3172.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "87d397fdb7098be195ad93c39fffc15943bce0d6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 49, + "d": 12 + }, + "doc/manual/pitfalls.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3174.json b/mne-python/source/doc/sphinxext/prs/3174.json new file mode 100644 index 0000000000000000000000000000000000000000..37ee80c4d65db6e27108a8da74a0ee0153c79951 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3174.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "ae040b3a1045c2fed73458ad0b8da6c919c533e2", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/faq.rst": { + "a": 11, + "d": 1 + }, + "doc/install_mne_python.rst": { + "a": 25, + "d": 0 + }, + "doc/manual/index.rst": { + "a": 87, + "d": 111 + }, + "doc/python_reference.rst": { + "a": 9, + "d": 5 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 8, + "d": 4 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 0 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 17, + "d": 11 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 24, + "d": 24 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3176.json b/mne-python/source/doc/sphinxext/prs/3176.json new file mode 100644 index 0000000000000000000000000000000000000000..975da6e5e0567f0c2258e4063dc1003bf9ed7387 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3176.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "47304def9521ca29ae4835d5ef591e1d8fce7872", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "tutorials/plot_epoching_and_averaging.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3177.json b/mne-python/source/doc/sphinxext/prs/3177.json new file mode 100644 index 0000000000000000000000000000000000000000..295dd81a76e6e40fa4d248493f456ac4185c2b9e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3177.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "831c0ba4089ad67367777f4ef1b27853584679e4", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "tutorials/plot_artifacts_correction_maxwell_filtering.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 9, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3178.json b/mne-python/source/doc/sphinxext/prs/3178.json new file mode 100644 index 0000000000000000000000000000000000000000..4ba15655ba03094dc81e7606e3ac90524ac86ae1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3178.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "393c2c81de10128f3b6f4aff26727f681fcb29fb", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/manual/migrating.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/318.json b/mne-python/source/doc/sphinxext/prs/318.json new file mode 100644 index 0000000000000000000000000000000000000000..ed8fae8836ebfea0dd9298bbba854b172620740d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/318.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "39e67d2543425a65ffd79e0f6c04841d1c8f2c5c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 4, + "d": 5 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 10, + "d": 11 + }, + "mne/fiff/constants.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 43, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 20, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3181.json b/mne-python/source/doc/sphinxext/prs/3181.json new file mode 100644 index 0000000000000000000000000000000000000000..bcf234efee12fbebbb22e2b987843b10d51cced8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3181.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ba0b3eff94e019c69fb063c04ccd50601413dd91", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3182.json b/mne-python/source/doc/sphinxext/prs/3182.json new file mode 100644 index 0000000000000000000000000000000000000000..e8b956336b368999f5ae7f3627a61f751703324e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3182.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4bf30daf575bdaf3c6155ce552d171a5bf3b3e72", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3185.json b/mne-python/source/doc/sphinxext/prs/3185.json new file mode 100644 index 0000000000000000000000000000000000000000..550f38809749e72108197c65f50c2349baf680c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3185.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "80fadbc7d5e586d90a14cc60ae82b602eee04dd5", + "authors": [ + { + "n": "cmoutard", + "e": "clement.moutard@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 39, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 87, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3188.json b/mne-python/source/doc/sphinxext/prs/3188.json new file mode 100644 index 0000000000000000000000000000000000000000..bd6e4a2fb61b752692eafe1ab1ff67863f55f3e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3188.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7cf5cd4d3c68eb8d2bee417a5826252ba67c5b2b", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 6, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3191.json b/mne-python/source/doc/sphinxext/prs/3191.json new file mode 100644 index 0000000000000000000000000000000000000000..3bda0e1c8d58e8cd85336988cd3b16182b1dede3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3191.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1795fbd55533fd75c856a928cd02fd243437cc4e", + "authors": [ + { + "n": "Mark Wronkiewicz", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/label.py": { + "a": 131, + "d": 30 + }, + "mne/tests/test_label.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3194.json b/mne-python/source/doc/sphinxext/prs/3194.json new file mode 100644 index 0000000000000000000000000000000000000000..8010fd74782d87c8c8ee4282ee62811f6997e1d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3194.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3a7cf4201535a061dbf3dad9f8ded23729886bb0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 12, + "d": 5 + }, + "mne/tests/test_cov.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3195.json b/mne-python/source/doc/sphinxext/prs/3195.json new file mode 100644 index 0000000000000000000000000000000000000000..cb877258dbf08a5127e6f4527e31bcde629bb38c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3195.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5064139dc838ebe02f366b73dcee357eb77f8421", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/event.py": { + "a": 18, + "d": 5 + }, + "mne/tests/test_event.py": { + "a": 13, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3197.json b/mne-python/source/doc/sphinxext/prs/3197.json new file mode 100644 index 0000000000000000000000000000000000000000..e48ad4a3a29516151bba08e3c49f2d6768c01d73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3197.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5a71c715331b590c2c9d95233e3bd38b972a6dce", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/event.py": { + "a": 12, + "d": 5 + }, + "mne/tests/test_event.py": { + "a": 15, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3199.json b/mne-python/source/doc/sphinxext/prs/3199.json new file mode 100644 index 0000000000000000000000000000000000000000..8f542130c97df3aa367ed2c77cf0448627d35079 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3199.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d3705ff657fe1b0e0b0eb9b4c0c4cb2cc60fbdc8", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 19, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 41, + "d": 9 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/32.json b/mne-python/source/doc/sphinxext/prs/32.json new file mode 100644 index 0000000000000000000000000000000000000000..fc2b0a73143e20a528b2bbedecec075266c98b45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/32.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3877ecb995794504094120a7c3f073d4620e24ee", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/320.json b/mne-python/source/doc/sphinxext/prs/320.json new file mode 100644 index 0000000000000000000000000000000000000000..244a1f24e06c0d841afc707d54ec90fe839c542b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/320.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "7e1026beff25b29128e6c3ef6fd1160d9b6caee6", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 4, + "d": 4 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 11, + "d": 15 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3202.json b/mne-python/source/doc/sphinxext/prs/3202.json new file mode 100644 index 0000000000000000000000000000000000000000..98bc85758121743a873289633d6db55a02b23e3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3202.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c93586e339393474d2fbc6f68ae43e88d1826551", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 8, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 11, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 37, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3203.json b/mne-python/source/doc/sphinxext/prs/3203.json new file mode 100644 index 0000000000000000000000000000000000000000..a5f9bfc336da9ddeb17775dd0cc87e1c8fb710af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3203.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f932004db951abaf7d0522f961ca9a3be6e72167", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 17, + "d": 9 + }, + "mne/viz/tests/test_raw.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3205.json b/mne-python/source/doc/sphinxext/prs/3205.json new file mode 100644 index 0000000000000000000000000000000000000000..a16f2794dcb892c0c6b0e823e80bd7685c3f4a41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3205.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "577d5fa2f244b83dc4bf30f3a46b1c5022969ef4", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/io/plot_elekta_epochs.py": { + "a": 68, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/multimodal/__init__.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 30, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 8, + "d": 2 + }, + "mne/event.py": { + "a": 457, + "d": 2 + }, + "mne/tests/test_event.py": { + "a": 81, + "d": 3 + }, + "mne/utils.py": { + "a": 5, + "d": 6 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3206.json b/mne-python/source/doc/sphinxext/prs/3206.json new file mode 100644 index 0000000000000000000000000000000000000000..9a4d957006c52f5474b6da5dc24cb354a33f930c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3206.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3b182bf67002ed51bed2a917bbc475162a3836eb", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 7, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3207.json b/mne-python/source/doc/sphinxext/prs/3207.json new file mode 100644 index 0000000000000000000000000000000000000000..7236892024b71524ec9b96a7972b972bc3443ffa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3207.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "747e1cb3873322adc5a7443ae7eb639577a06a00", + "authors": [ + { + "n": "pbnsilva", + "e": "pedrobnsilva@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3208.json b/mne-python/source/doc/sphinxext/prs/3208.json new file mode 100644 index 0000000000000000000000000000000000000000..962c47eabcb2c3337ed795bb98bea82becd712da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3208.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9108028e91255e1fa9ab255c25929ccada1a0cb6", + "authors": [ + { + "n": "MartinBaBer", + "e": "Martinb.nmb@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3209.json b/mne-python/source/doc/sphinxext/prs/3209.json new file mode 100644 index 0000000000000000000000000000000000000000..16b3dfc3acd1caa22a4d6779834a9bd282243a49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3209.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0271393994bf44d6a2489b078912733b62de1bee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/plot_object_epochs.py": { + "a": 11, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/321.json b/mne-python/source/doc/sphinxext/prs/321.json new file mode 100644 index 0000000000000000000000000000000000000000..4c1a513af50756fc81a5cca742fb38af46032096 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/321.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "87a851d459d44ee91a9fdc46c80e4d90035a821f", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 48, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3211.json b/mne-python/source/doc/sphinxext/prs/3211.json new file mode 100644 index 0000000000000000000000000000000000000000..b6c3c5a50264b44cc8bc16385703d2cb4dc6bdfa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3211.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1edafe34f02c14cda0d4fd28942c56d2871f9135", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 8 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 34, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3213.json b/mne-python/source/doc/sphinxext/prs/3213.json new file mode 100644 index 0000000000000000000000000000000000000000..c4ace65e567f110e8de85956238fb375329d1f78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3213.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "23aed0a07ba2cfa84452107dd005750cd4aba9b9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 56, + "d": 38 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 10, + "d": 6 + }, + "mne/io/fiff/raw.py": { + "a": 31, + "d": 23 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 69, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3215.json b/mne-python/source/doc/sphinxext/prs/3215.json new file mode 100644 index 0000000000000000000000000000000000000000..6904c7d53821895f36aced437b21989e6bc7e793 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3215.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "76245d0bc41170e1e02c0410659121eedaffe135", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 6, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 8, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3216.json b/mne-python/source/doc/sphinxext/prs/3216.json new file mode 100644 index 0000000000000000000000000000000000000000..040e143080d08db0226f728cbe5ee0446b55ac07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3216.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ee8ac19d81650426735be88bda023dd82e1f92bf", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/viz/tests/test_utils.py": { + "a": 2, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3217.json b/mne-python/source/doc/sphinxext/prs/3217.json new file mode 100644 index 0000000000000000000000000000000000000000..ac8b316319886566e97d709e6c28aec41838b8ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3217.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6248b46f9e41dc3fbdbad4f36e407f046aaa5a94", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3218.json b/mne-python/source/doc/sphinxext/prs/3218.json new file mode 100644 index 0000000000000000000000000000000000000000..a6f98893665e739f0133f0043a9f725c576f4bf5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3218.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "f533b636d2c2428d00e9c0e495a4353386828423", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 18, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/bem.py": { + "a": 2, + "d": 8 + }, + "mne/channels/channels.py": { + "a": 20, + "d": 40 + }, + "mne/chpi.py": { + "a": 1, + "d": 78 + }, + "mne/cov.py": { + "a": 9, + "d": 18 + }, + "mne/epochs.py": { + "a": 41, + "d": 85 + }, + "mne/evoked.py": { + "a": 9, + "d": 19 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 82 + }, + "mne/io/base.py": { + "a": 4, + "d": 63 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 28 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 0, + "d": 9 + }, + "mne/label.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 9 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 6 + }, + "mne/tests/test_bem.py": { + "a": 2, + "d": 5 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 27 + }, + "mne/tests/test_dipole.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 5 + }, + "mne/time_frequency/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 57 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 173 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 71, + "d": 82 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 12 + }, + "mne/utils.py": { + "a": 8, + "d": 11 + }, + "mne/viz/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/322.json b/mne-python/source/doc/sphinxext/prs/322.json new file mode 100644 index 0000000000000000000000000000000000000000..a3f886519f9d2da967fc5e25cd40429650718419 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/322.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ccf9522e79dd5333b83e20dd96c0f0126189584b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3222.json b/mne-python/source/doc/sphinxext/prs/3222.json new file mode 100644 index 0000000000000000000000000000000000000000..9b80522eb5a19e16a9e6b3d8a33787719c0d56f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3222.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "aa33645ada61a3d3f808c61fe7da1f1eac8d849c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/baseline.py": { + "a": 19, + "d": 8 + }, + "mne/epochs.py": { + "a": 36, + "d": 16 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 7, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3224.json b/mne-python/source/doc/sphinxext/prs/3224.json new file mode 100644 index 0000000000000000000000000000000000000000..099fc0bba9a9627db4f45eafdab1cbdb803d54bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3224.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a7525730809a7f591850a97039afa561730b7146", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/class.rst": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/numpy_ext/docscrape.py": { + "a": 3, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 22, + "d": 1 + }, + "mne/dipole.py": { + "a": 39, + "d": 16 + }, + "mne/epochs.py": { + "a": 82, + "d": 37 + }, + "mne/io/base.py": { + "a": 50, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 2 + }, + "mne/utils.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3228.json b/mne-python/source/doc/sphinxext/prs/3228.json new file mode 100644 index 0000000000000000000000000000000000000000..8fe73303755434d85db95f736f520cd0408dc836 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3228.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5e759b43b5c8a5aa69a4678b415efae77627ebc1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 3 + }, + "codecov.yml": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/323.json b/mne-python/source/doc/sphinxext/prs/323.json new file mode 100644 index 0000000000000000000000000000000000000000..fe4b6512b0208215e46baaf989e5583c783038ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/323.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cf18e25d167169f40b598aced1a9bb56a86cf3d7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/gen_rst.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3230.json b/mne-python/source/doc/sphinxext/prs/3230.json new file mode 100644 index 0000000000000000000000000000000000000000..46adc225016d760b4eb5435e0d4b8a849f49dabd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3230.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "74d85eca4e43aa542c2fce0d1d348a04e5658196", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 9, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3231.json b/mne-python/source/doc/sphinxext/prs/3231.json new file mode 100644 index 0000000000000000000000000000000000000000..16c2762cf8c78b1aad1cb486a83136a7aa4b43e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3231.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8cb4ffbf3b9194b39b316f0247146a31f47e2f44", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 5, + "d": 6 + }, + "codecov.yml": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3233.json b/mne-python/source/doc/sphinxext/prs/3233.json new file mode 100644 index 0000000000000000000000000000000000000000..8ab1253f74a9a52d225437ac0851275b6355f10a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3233.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0a861bf8fcbd3eb833cba9fc9468a2fd877532a9", + "authors": [ + { + "n": "Yaroslav Halchenko", + "e": null + } + ], + "changes": { + "mne/surface.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3234.json b/mne-python/source/doc/sphinxext/prs/3234.json new file mode 100644 index 0000000000000000000000000000000000000000..18902091c42a7fa24621198ae1b668008a04c567 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3234.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5fdb8b0c6795900e022e449596617d2f2560ebc6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_epochs.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3235.json b/mne-python/source/doc/sphinxext/prs/3235.json new file mode 100644 index 0000000000000000000000000000000000000000..286d23582697a8070ea9190869d9ba2f7105c6cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3235.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "60a7440269b12bb5c44bd246e90af80dd8551cf2", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 68, + "d": 20 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3236.json b/mne-python/source/doc/sphinxext/prs/3236.json new file mode 100644 index 0000000000000000000000000000000000000000..a6c3ea8f39a4c4096a2883cdf2773293f9885aff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3236.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ab461ad72a7530d5161d10e7d68d12ec9dba27ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 34, + "d": 73 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3237.json b/mne-python/source/doc/sphinxext/prs/3237.json new file mode 100644 index 0000000000000000000000000000000000000000..15a24882e2a9d3f1831aea0cc4948e91e8419124 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3237.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "b86ba4a6f4d6378a6499adfd918f20385a73becc", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 17, + "d": 2 + }, + "mne/data/mne_analyze.sel": { + "a": 7, + "d": 1 + }, + "mne/io/base.py": { + "a": 8, + "d": 4 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 0 + }, + "mne/selection.py": { + "a": 68, + "d": 2 + }, + "mne/utils.py": { + "a": 5, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 189, + "d": 46 + }, + "mne/viz/tests/test_raw.py": { + "a": 23, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 225, + "d": 35 + }, + "tutorials/plot_visualize_raw.py": { + "a": 33, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3238.json b/mne-python/source/doc/sphinxext/prs/3238.json new file mode 100644 index 0000000000000000000000000000000000000000..067d791f53659bd4d0c37c4bfcfe1efef8623486 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3238.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "251ec96443f560c3fdac752f1ad36788eed960ba", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 20, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 5, + "d": 4 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 0, + "d": 12 + }, + "mne/io/meas_info.py": { + "a": 30, + "d": 8 + }, + "mne/io/tests/test_meas_info.py": { + "a": 43, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/324.json b/mne-python/source/doc/sphinxext/prs/324.json new file mode 100644 index 0000000000000000000000000000000000000000..d0d17971f20bd21f24ce320d53393fa8c4455885 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/324.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "929b10daea23e4e6d23bd736f9460ed6a95230c8", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 311, + "d": 138 + }, + "mne/epochs.py": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3241.json b/mne-python/source/doc/sphinxext/prs/3241.json new file mode 100644 index 0000000000000000000000000000000000000000..a4aad779de52ba4dbcb98d25b7d8b0f4b98e3809 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3241.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e51fa95b309b13de1f242fde49f25d53361900b3", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/manual/appendix/bem_model.rst": { + "a": 8, + "d": 2 + }, + "mne/bem.py": { + "a": 15, + "d": 2 + }, + "mne/commands/mne_flash_bem.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3245.json b/mne-python/source/doc/sphinxext/prs/3245.json new file mode 100644 index 0000000000000000000000000000000000000000..a579ce4bd3767b5250c28fcb03b8a5071b8a2102 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3245.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3efd6f8b411571c481f45d03028c6fb9b83d43b1", + "authors": [ + { + "n": "Asish Panda", + "e": "asishrocks95@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_xdawn_transformer.py": { + "a": 48, + "d": 0 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_xdawn.py": { + "a": 97, + "d": 0 + }, + "mne/decoding/xdawn.py": { + "a": 174, + "d": 0 + }, + "mne/preprocessing/xdawn.py": { + "a": 164, + "d": 128 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3246.json b/mne-python/source/doc/sphinxext/prs/3246.json new file mode 100644 index 0000000000000000000000000000000000000000..e6ed3e6e0111c411683d9855f6b23dec29b4e7e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3246.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e55b6f3f0a6beb2273592be3404ee4ccb3659e2f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/dipole.py": { + "a": 69, + "d": 18 + }, + "mne/tests/test_dipole.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3250.json b/mne-python/source/doc/sphinxext/prs/3250.json new file mode 100644 index 0000000000000000000000000000000000000000..c96cfed1452b667c98a3908d8141af4b93bdc10a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3250.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f04d1460d10ebe3b9466ccad9c077040d42a6d5f", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3251.json b/mne-python/source/doc/sphinxext/prs/3251.json new file mode 100644 index 0000000000000000000000000000000000000000..10534f3820ee850052cdfbd605dda2f743214505 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3251.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2cacb24bedc0ac09077f71c7637cb7d707800268", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/evoked.py": { + "a": 15, + "d": 7 + }, + "mne/viz/evoked.py": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3253.json b/mne-python/source/doc/sphinxext/prs/3253.json new file mode 100644 index 0000000000000000000000000000000000000000..174185446e65fed882cf388a424590711efdfbfe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3253.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bacd4adfa5645827784e2d34ab80c33d129d98a6", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 6 + }, + "mne/viz/tests/test_topomap.py": { + "a": 5, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3254.json b/mne-python/source/doc/sphinxext/prs/3254.json new file mode 100644 index 0000000000000000000000000000000000000000..aeec60562d9741a57c7c132c8634441c5bcb7f81 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3254.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "63feb683cd1f8ddd598a78d12c8ef522f9ca2d78", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 7, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 9, + "d": 3 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/326.json b/mne-python/source/doc/sphinxext/prs/326.json new file mode 100644 index 0000000000000000000000000000000000000000..3706bcd68a44cb75e6dac471a151a50b7c15ec16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/326.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0be6f829b6157d1b94dbca119dde5c69a69ea9a8", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_ecg_artifacts_from_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_eog_artifacts_from_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 3, + "d": 3 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 9, + "d": 10 + }, + "mne/preprocessing/ica.py": { + "a": 83, + "d": 63 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 39, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3261.json b/mne-python/source/doc/sphinxext/prs/3261.json new file mode 100644 index 0000000000000000000000000000000000000000..793d06083cdffef623f2708026493490c05a0d0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3261.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0fff718f956ad86fb8b9154f87e6414c64c758c4", + "authors": [ + { + "n": "Pablo-Arias", + "e": "pablo12co@hotmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 34, + "d": 16 + }, + "mne/io/brainvision/tests/data/test.vhdr": { + "a": 10, + "d": 10 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 10, + "d": 1 + }, + "mne/io/constants.py": { + "a": 25, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3266.json b/mne-python/source/doc/sphinxext/prs/3266.json new file mode 100644 index 0000000000000000000000000000000000000000..03e2d3e8211bcb492d068727597a24088d21be2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3266.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bfb3f81e4813f4d65af8c3d84933ee08a94b9d09", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/externals/tempita/_looper.py": { + "a": 2, + "d": 2 + }, + "setup.cfg": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3270.json b/mne-python/source/doc/sphinxext/prs/3270.json new file mode 100644 index 0000000000000000000000000000000000000000..b140810fcc1101692aa6845dfb27d95f39d65db8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3270.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f5b226b3298bccbfe412f2ac5b7d83e762ef2e6f", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 37, + "d": 7 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 62, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3272.json b/mne-python/source/doc/sphinxext/prs/3272.json new file mode 100644 index 0000000000000000000000000000000000000000..2464f91fbeb67932e0b641d5f5c2155b50e38470 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3272.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a1cbb6bf96612dec707e19876bef492f9f5d12d0", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "mne/channels/tests/test_interpolation.py": { + "a": 0, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3273.json b/mne-python/source/doc/sphinxext/prs/3273.json new file mode 100644 index 0000000000000000000000000000000000000000..23a415e2da3ca52568b33eb982982ebcbf37c1f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3273.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "6be10dbd4462874acabad42eab48a277754ff6f0", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 73, + "d": 25 + }, + "mne/commands/mne_flash_bem.py": { + "a": 1, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 58, + "d": 0 + }, + "mne/surface.py": { + "a": 139, + "d": 15 + }, + "mne/tests/test_bem.py": { + "a": 46, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 6, + "d": 3 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3275.json b/mne-python/source/doc/sphinxext/prs/3275.json new file mode 100644 index 0000000000000000000000000000000000000000..a1ea8b18575278d8506812c803b6053e30e43dc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3275.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "6f69b79fea6c2af992a9a1efecaf5d9a8d8b2688", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 27, + "d": 1 + }, + "mne/event.py": { + "a": 9, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 53, + "d": 0 + }, + "mne/tests/test_event.py": { + "a": 5, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 24, + "d": 6 + }, + "mne/viz/ica.py": { + "a": 249, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 55, + "d": 1 + }, + "mne/viz/tests/test_utils.py": { + "a": 21, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 50, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 26, + "d": 0 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 35, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3277.json b/mne-python/source/doc/sphinxext/prs/3277.json new file mode 100644 index 0000000000000000000000000000000000000000..f428dfdbc49d0f49e338abb93bec3f5426fc9bdf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3277.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "97b38c9a75c06ffaecf5eef588a689899f86ded2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 2 + }, + "circle.yml": { + "a": 3, + "d": 3 + }, + "doc/conf.py": { + "a": 6, + "d": 1 + }, + "doc/faq.rst": { + "a": 1, + "d": 2 + }, + "doc/manual/cookbook.rst": { + "a": 0, + "d": 2 + }, + "doc/manual/io.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/source_localization/inverse.rst": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 1 + }, + "doc/tutorials.rst": { + "a": 11, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 24, + "d": 23 + }, + "mne/filter.py": { + "a": 126, + "d": 5 + }, + "mne/io/base.py": { + "a": 31, + "d": 73 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 64, + "d": 57 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 2 + }, + "mne/stats/parametric.py": { + "a": 7, + "d": 5 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 6, + "d": 2 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_background_filtering.py": { + "a": 396, + "d": 0 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_eeg_erp.py": { + "a": 1, + "d": 0 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_forward.py": { + "a": 3, + "d": 1 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 15, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3279.json b/mne-python/source/doc/sphinxext/prs/3279.json new file mode 100644 index 0000000000000000000000000000000000000000..f5b39de4887cfcdc3cbd91e71105486fbf04094e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3279.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "81bdd0f2f96e70d0628bd47d3c81540d75e052cb", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/328.json b/mne-python/source/doc/sphinxext/prs/328.json new file mode 100644 index 0000000000000000000000000000000000000000..38f84ca512696cff86fb21299dede823dda51f6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/328.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f3ae96e77cecd6decf887e2186f0fa62732c668c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/mixed_norm/tests/test_inverse.py": { + "a": 9, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3289.json b/mne-python/source/doc/sphinxext/prs/3289.json new file mode 100644 index 0000000000000000000000000000000000000000..c03d013201f4290f15c57bc5d45d9b55321dec30 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3289.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5e7f9e22679ca1f88972701ac403bb48ec7817f9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 19, + "d": 27 + }, + "mne/evoked.py": { + "a": 67, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 39, + "d": 5 + }, + "mne/tests/test_evoked.py": { + "a": 47, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/329.json b/mne-python/source/doc/sphinxext/prs/329.json new file mode 100644 index 0000000000000000000000000000000000000000..2aa10b39b8595ec10c8bfe285bda145e760819e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/329.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "10fb256c66a3b75e1ac828554c0b720bfd9b14ae", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3290.json b/mne-python/source/doc/sphinxext/prs/3290.json new file mode 100644 index 0000000000000000000000000000000000000000..f6271f214090ab0c1cef877bd3327a0eceeee8c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3290.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "a3ed1052e21b39c104915418890a6dbb7a5d823d", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 11, + "d": 3 + }, + "mne/decoding/base.py": { + "a": 28, + "d": 6 + }, + "mne/decoding/csp.py": { + "a": 28, + "d": 6 + }, + "mne/epochs.py": { + "a": 19, + "d": 5 + }, + "mne/evoked.py": { + "a": 23, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 14, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 21, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 41, + "d": 15 + }, + "mne/viz/epochs.py": { + "a": 23, + "d": 10 + }, + "mne/viz/evoked.py": { + "a": 27, + "d": 8 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 27, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 11, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 146, + "d": 50 + }, + "mne/viz/utils.py": { + "a": 102, + "d": 3 + }, + "tutorials/plot_visualize_epochs.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3298.json b/mne-python/source/doc/sphinxext/prs/3298.json new file mode 100644 index 0000000000000000000000000000000000000000..98d67e3612e34ba3646bccb5b1eaf1a6140b5062 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3298.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9ac4a3c32964d77a41a4da9b70c8e92a4fc3e2ac", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 6 + }, + "Makefile": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/33.json b/mne-python/source/doc/sphinxext/prs/33.json new file mode 100644 index 0000000000000000000000000000000000000000..3ec8d0e0497eb77864b89c1cfade9e05f10f244b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/33.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ce3e0e99f4974eec09701dc239afe30948348dbc", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 75, + "d": 26 + }, + "mne/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/proj.py": { + "a": 16, + "d": 1 + }, + "mne/fiff/tests/data/test_raw-eve.fif": { + "a": 0, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 14, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3303.json b/mne-python/source/doc/sphinxext/prs/3303.json new file mode 100644 index 0000000000000000000000000000000000000000..71e73ac75d2995d3e6f0a953e869310b3f4407e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3303.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "80f8f9165daad65ae534c66ff0b86725aa2712c8", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 3 + }, + "mne/io/brainvision/tests/data/test.vhdr": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3304.json b/mne-python/source/doc/sphinxext/prs/3304.json new file mode 100644 index 0000000000000000000000000000000000000000..586ee35b7fdaa9fa2f3fa1ec0bc0fc565cdd2437 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3304.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7ba03032d4d7fb70cbbe0816b21eaa97a953ced7", + "authors": [ + { + "n": "Michael", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3306.json b/mne-python/source/doc/sphinxext/prs/3306.json new file mode 100644 index 0000000000000000000000000000000000000000..fc59eadff5b9a3f9e7843afc874b0aaa1396a481 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3306.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c0e73eeb959a636fb25a6f4ca550ca3111f05852", + "authors": [ + { + "n": "Camilo Lamus", + "e": null + } + ], + "changes": { + "mne/simulation/tests/test_evoked.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3309.json b/mne-python/source/doc/sphinxext/prs/3309.json new file mode 100644 index 0000000000000000000000000000000000000000..08aaf40c6979b39fc0f4482d2377ded84533a98f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3309.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "811e8fc8783507c166bbe079b4647ebfe01adc38", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 22, + "d": 7 + }, + "mne/io/base.py": { + "a": 8, + "d": 5 + }, + "mne/selection.py": { + "a": 9, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 27, + "d": 23 + }, + "mne/viz/tests/test_raw.py": { + "a": 37, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 173, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/331.json b/mne-python/source/doc/sphinxext/prs/331.json new file mode 100644 index 0000000000000000000000000000000000000000..a2316bbdf8499149221d8b6f23ecd8a3dafef758 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/331.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c51c7050ddce81ba8ce59ffc13b9c745c59a39b4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 5, + "d": 1 + }, + "mne/fiff/evoked.py": { + "a": 8, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 3, + "d": 1 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 2, + "d": 0 + }, + "mne/fiff/tests/test_raw.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3312.json b/mne-python/source/doc/sphinxext/prs/3312.json new file mode 100644 index 0000000000000000000000000000000000000000..013cdec12cb3ac906c2e763e1177048b0528cea6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3312.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5ecd19e4a696a07f294e8e7f89c0cda46ed1fb70", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 10, + "d": 1 + }, + "mne/utils.py": { + "a": 20, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3313.json b/mne-python/source/doc/sphinxext/prs/3313.json new file mode 100644 index 0000000000000000000000000000000000000000..50ba941d4084201379e0044c964b48db06baac53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3313.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7dc194df1b92ac54c8772c656ef55289afb80224", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 32, + "d": 8 + }, + "mne/epochs.py": { + "a": 13, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 40, + "d": 9 + }, + "mne/tests/test_epochs.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3314.json b/mne-python/source/doc/sphinxext/prs/3314.json new file mode 100644 index 0000000000000000000000000000000000000000..1ff9171278df3e47ca651065d68f175885a4a57a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3314.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "ef1831679b0829518a5b889ccb74ac899ffba517", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 56, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 77, + "d": 55 + }, + "mne/source_space.py": { + "a": 32, + "d": 15 + }, + "mne/tests/test_label.py": { + "a": 52, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3315.json b/mne-python/source/doc/sphinxext/prs/3315.json new file mode 100644 index 0000000000000000000000000000000000000000..dc387787483c6a91b0a4af5097db339e226207df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3315.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8a7921ed7d9c89887ac707608b1871e638adbf1a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 5, + "d": 0 + }, + "mne/simulation/tests/test_source.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3316.json b/mne-python/source/doc/sphinxext/prs/3316.json new file mode 100644 index 0000000000000000000000000000000000000000..b8186058f9cbbedc6169e881a6ae6699fd80884e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3316.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "81e8f6309be5f864a691f85ba3f767c13cd7f86d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/simulation/evoked.py": { + "a": 7, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 6, + "d": 3 + }, + "mne/simulation/tests/test_source.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3318.json b/mne-python/source/doc/sphinxext/prs/3318.json new file mode 100644 index 0000000000000000000000000000000000000000..35fbd6731b59782b4156a5af04dcecd5ed3c8268 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3318.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "bfeb3fbed17d8e4868699119daf2db1eb65fd8fe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 7, + "d": 6 + }, + "mne/simulation/evoked.py": { + "a": 6, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 7, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 101, + "d": 15 + }, + "mne/simulation/tests/test_source.py": { + "a": 35, + "d": 13 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3319.json b/mne-python/source/doc/sphinxext/prs/3319.json new file mode 100644 index 0000000000000000000000000000000000000000..337c4c18c04c961d4ea47bad9e47be857c5ec667 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3319.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "83e95452fd1d0f2ded57481fd1a7312299011999", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/tests/test_transforms.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/332.json b/mne-python/source/doc/sphinxext/prs/332.json new file mode 100644 index 0000000000000000000000000000000000000000..f7b1992ed7467d194d5ec0b9ec456c7c1cf86953 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/332.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "683b93219a2027d8064b0b3bfa8f96b6518adc3c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/evoked.py": { + "a": 1, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 11, + "d": 4 + }, + "mne/fiff/tests/test_raw.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3320.json b/mne-python/source/doc/sphinxext/prs/3320.json new file mode 100644 index 0000000000000000000000000000000000000000..ab04484f6e1ee09aa514b14cd39fb8c28fd97460 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3320.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "727a8711bde1fc5fadabc02e0999379f7fb36593", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 87, + "d": 67 + }, + "mne/channels/tests/test_montage.py": { + "a": 18, + "d": 3 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 15, + "d": 16 + }, + "mne/gui/help/kit2fiff.json": { + "a": 4, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 3, + "d": 4 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 3 + }, + "mne/io/kit/tests/data/test.elp": { + "a": 37, + "d": 0 + }, + "mne/io/kit/tests/data/test.hsp": { + "a": 514, + "d": 0 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 15, + "d": 0 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 41, + "d": 13 + }, + "mne/io/meas_info.py": { + "a": 34, + "d": 4 + }, + "mne/io/tests/test_meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/transforms.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3321.json b/mne-python/source/doc/sphinxext/prs/3321.json new file mode 100644 index 0000000000000000000000000000000000000000..26b2ce34b0416fb0282c1a2544fb99e4f1bf13ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3321.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "545816811e9bdcdbbd4ee950230a51fb891260bd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_show_fiff.py": { + "a": 6, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/open.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3322.json b/mne-python/source/doc/sphinxext/prs/3322.json new file mode 100644 index 0000000000000000000000000000000000000000..0a0e083870e9b7b3fd5f9d28c23da13decade935 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3322.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "61885e6c5db39b1147dd9450ebc0922b2aa77c0b", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3323.json b/mne-python/source/doc/sphinxext/prs/3323.json new file mode 100644 index 0000000000000000000000000000000000000000..d060f4f512245ef21b2d1fb9442d61170fe80589 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3323.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "08cc8b8bfca1f869df563e51766f4cf65bbcdbc3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 9, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3324.json b/mne-python/source/doc/sphinxext/prs/3324.json new file mode 100644 index 0000000000000000000000000000000000000000..00e20a79ba92e28c9724e636145a3c2d153c444d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3324.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "42678aa7ec1d0c5eda464e31072892915095ae39", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".coveragerc": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 4 + }, + "mne/filter.py": { + "a": 169, + "d": 69 + }, + "mne/fixes.py": { + "a": 246, + "d": 11 + }, + "mne/io/base.py": { + "a": 5, + "d": 0 + }, + "mne/tests/test_filter.py": { + "a": 83, + "d": 17 + }, + "mne/tests/test_fixes.py": { + "a": 6, + "d": 3 + }, + "tutorials/plot_background_filtering.py": { + "a": 135, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3325.json b/mne-python/source/doc/sphinxext/prs/3325.json new file mode 100644 index 0000000000000000000000000000000000000000..a37245233e0821d2a96b99e79fb1ef2e39c59b19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3325.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "714ba90ec44cef321a6ffe4c9d9efd02ca9d89d6", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_forward.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3327.json b/mne-python/source/doc/sphinxext/prs/3327.json new file mode 100644 index 0000000000000000000000000000000000000000..b8790a2fb356c1bddf98901d59f6b02f51ed12e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3327.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b25bf9af35547d62a4dea7e359de00381a44661e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3329.json b/mne-python/source/doc/sphinxext/prs/3329.json new file mode 100644 index 0000000000000000000000000000000000000000..fa0b5765f1b35c314cf4e100d14da7db93a3a4e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3329.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "64a9c91c6cab7c34fada862cb825a5cb6add51a7", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 10, + "d": 103 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3331.json b/mne-python/source/doc/sphinxext/prs/3331.json new file mode 100644 index 0000000000000000000000000000000000000000..f9b060ff7acb59b2ac1d779d43845122c896fe6c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3331.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a361dced7663c616ac1fd184f7eed183d2b71580", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3332.json b/mne-python/source/doc/sphinxext/prs/3332.json new file mode 100644 index 0000000000000000000000000000000000000000..fe7a03de3182add45d064f064563e6743cb40f3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3332.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "e5054176380023eb19849a7b0e729d0d33b1dcfb", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_coreg.py": { + "a": 15, + "d": 1 + }, + "mne/coreg.py": { + "a": 90, + "d": 42 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 100, + "d": 88 + }, + "mne/gui/_fiducials_gui.py": { + "a": 8, + "d": 16 + }, + "mne/gui/_file_traits.py": { + "a": 35, + "d": 12 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 60, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3333.json b/mne-python/source/doc/sphinxext/prs/3333.json new file mode 100644 index 0000000000000000000000000000000000000000..bb9b64ce0149098ea8de96424f36d1cef4213ead --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3333.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "51a6e8ad22315b3dd16ab6e42f0bf939659d8b7c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fixes.py": { + "a": 19, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3334.json b/mne-python/source/doc/sphinxext/prs/3334.json new file mode 100644 index 0000000000000000000000000000000000000000..8b0069840d78cb7da52f2aa535e395d07394ae1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3334.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0a52ab33fa889e02242f5003fcd5d5f6cd7fc838", + "authors": [ + { + "n": "Nick Foti", + "e": null + } + ], + "changes": { + "mne/externals/h5io/_h5io.py": { + "a": 157, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3335.json b/mne-python/source/doc/sphinxext/prs/3335.json new file mode 100644 index 0000000000000000000000000000000000000000..7cb153639b97402f7af2bd37fd1e200b7441ae9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3335.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "01fa5736e64d990994513430a48c7256f4c8edfc", + "authors": [ + { + "n": "Félix Raimundo", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 36, + "d": 3 + }, + "mne/io/tests/data/test-ave-2.log": { + "a": 2, + "d": 0 + }, + "mne/io/tests/data/test-ave.log": { + "a": 1, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3337.json b/mne-python/source/doc/sphinxext/prs/3337.json new file mode 100644 index 0000000000000000000000000000000000000000..de33ef2672e757649d0932c77ec7622bfc72657a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3337.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "cd0300a12613b20052af79655e0a1a38a1ac5d06", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 8, + "d": 2 + }, + "doc/contributing.rst": { + "a": 216, + "d": 151 + }, + "doc/index.rst": { + "a": 2, + "d": 3 + }, + "doc/sphinxext/gen_commands.py": { + "a": 8, + "d": 5 + }, + "doc/sphinxext/numpy_ext/__init__.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext/docscrape.py": { + "a": 0, + "d": 514 + }, + "doc/sphinxext/numpy_ext/docscrape_sphinx.py": { + "a": 0, + "d": 240 + }, + "doc/sphinxext/numpy_ext/numpydoc.py": { + "a": 0, + "d": 192 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/time_gen.py": { + "a": 27, + "d": 29 + }, + "mne/decoding/transformer.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3339.json b/mne-python/source/doc/sphinxext/prs/3339.json new file mode 100644 index 0000000000000000000000000000000000000000..7adf2420b1ad52b0a1314763e8f66460a02feda8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3339.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bf568d5676714263821d2ec97bdfe7f4e738bf11", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "doc/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3341.json b/mne-python/source/doc/sphinxext/prs/3341.json new file mode 100644 index 0000000000000000000000000000000000000000..c10279f33521fb46e17b0ca713913e2165571b11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3341.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a4ea969b41d0f58c047ad481fff69c9abd73bc23", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "doc/getting_started.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3342.json b/mne-python/source/doc/sphinxext/prs/3342.json new file mode 100644 index 0000000000000000000000000000000000000000..52c1c71f74defc7a5fff54e6cc21e6556ec910a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3342.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bd3a8c16dca17435b70e572c2e5e29bf66a14ac2", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 6, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3343.json b/mne-python/source/doc/sphinxext/prs/3343.json new file mode 100644 index 0000000000000000000000000000000000000000..33424213387c1c6f40148fb49157b6ff4e787e3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3343.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "93e369654c2b0f881d433ac4a80c00ff3121a964", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3345.json b/mne-python/source/doc/sphinxext/prs/3345.json new file mode 100644 index 0000000000000000000000000000000000000000..213e1d87fb8e8bb37be234dec1848adbb166695d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3345.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "46ae90465382af29e2aa52be8ae42dc3da905fcd", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3346.json b/mne-python/source/doc/sphinxext/prs/3346.json new file mode 100644 index 0000000000000000000000000000000000000000..08615dedd514a343170e8494054a04a06f4b0f95 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3346.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "18836be178713f97e941827525501a80002b0d5a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3348.json b/mne-python/source/doc/sphinxext/prs/3348.json new file mode 100644 index 0000000000000000000000000000000000000000..ce409b3920b87c5df5754c143803c2c387db774c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3348.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1ff3f45a142754b17d9a437806c165a123ec3384", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/channels/data/neighbors/KIT-UMD_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/__init__.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3349.json b/mne-python/source/doc/sphinxext/prs/3349.json new file mode 100644 index 0000000000000000000000000000000000000000..085fc2f5bba1d226f2e66cac4d00933588eed927 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3349.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5d33ad298c409bee6b28e8688fe90391a3df063c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/channels/data/layouts/KIT-UMD.lout": { + "a": 158, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 38, + "d": 4 + }, + "mne/channels/tests/test_layout.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/335.json b/mne-python/source/doc/sphinxext/prs/335.json new file mode 100644 index 0000000000000000000000000000000000000000..5da6102edfbe70ade3b2ebf89c963c5621c50354 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/335.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a16b6c0a5a1713ed2f09b6c4168145471133b92c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 37, + "d": 8 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3350.json b/mne-python/source/doc/sphinxext/prs/3350.json new file mode 100644 index 0000000000000000000000000000000000000000..8ea6d3bc63a95462956dae5ba42905d5515e9e93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3350.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fff293de2003075d6b84f2716a43089910503f32", + "authors": [ + { + "n": "Nick Foti", + "e": null + } + ], + "changes": { + "doc/tutorials.rst": { + "a": 1, + "d": 0 + }, + "tutorials/plot_point_spread.py": { + "a": 171, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3352.json b/mne-python/source/doc/sphinxext/prs/3352.json new file mode 100644 index 0000000000000000000000000000000000000000..cd47f94b86c5d03dcb92a34b4ae7372515449a5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3352.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "994ac805a3d1ec4a5f2a98dcd0961789847daa41", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 5, + "d": 14 + }, + "mne/utils.py": { + "a": 8, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3353.json b/mne-python/source/doc/sphinxext/prs/3353.json new file mode 100644 index 0000000000000000000000000000000000000000..64fc96e9b72f063c9649ecde5e3d3592dfd99603 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3353.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b1ec497be3f265d58f8a25c983d7a509aa8a16d2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "appveyor.yml": { + "a": 9, + "d": 21 + }, + "make/install_python.ps1": { + "a": 0, + "d": 93 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3354.json b/mne-python/source/doc/sphinxext/prs/3354.json new file mode 100644 index 0000000000000000000000000000000000000000..b3f3b28c6e693422f2884ced582e49124719b910 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3354.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "11fc0ef2d923f35623a6d9baa6f1aa8af27fc278", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3355.json b/mne-python/source/doc/sphinxext/prs/3355.json new file mode 100644 index 0000000000000000000000000000000000000000..2a620e32b43050e3d6be158f0d14bcc225a59dfa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3355.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "e5fb9e9e0d3e72dfdab19d987ed0cc2304dd479d", + "authors": [ + { + "n": "Nick Foti", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 2, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 5, + "d": 5 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 6, + "d": 6 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 5, + "d": 5 + }, + "mne/beamformer/_dics.py": { + "a": 8, + "d": 8 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 19, + "d": 19 + }, + "mne/time_frequency/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 239, + "d": 54 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 225, + "d": 70 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3360.json b/mne-python/source/doc/sphinxext/prs/3360.json new file mode 100644 index 0000000000000000000000000000000000000000..bd1803b244434c7bc0392f7645c257d8745d2836 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3360.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1a641d7bb800e8170d916b0289443abc9627b7eb", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 11, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3364.json b/mne-python/source/doc/sphinxext/prs/3364.json new file mode 100644 index 0000000000000000000000000000000000000000..fd3415c07b9f2c5f88f40c2a6fa9a138f0e4abec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3364.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5a299f1e43cc7465b282da62f461784ccd980592", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3365.json b/mne-python/source/doc/sphinxext/prs/3365.json new file mode 100644 index 0000000000000000000000000000000000000000..76e19aea5de17eac04794a703d0debec0081adc9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3365.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "52a3ca01a66fd78c750f5bc62b756bbb06a62538", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 36, + "d": 11 + }, + "mne/surface.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 2 + }, + "tutorials/plot_background_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3368.json b/mne-python/source/doc/sphinxext/prs/3368.json new file mode 100644 index 0000000000000000000000000000000000000000..2f3969ff1203683838ef3932f1c94de6194c8bf5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3368.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "474b31a72659420a900b2453670c40b1938b5e91", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 12, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3371.json b/mne-python/source/doc/sphinxext/prs/3371.json new file mode 100644 index 0000000000000000000000000000000000000000..b1c41a7505113490509b6653cf7cbbd4f5cc1541 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3371.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7fe99df50119d06803cdd929c512a8d799ecd962", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 7, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 8, + "d": 1 + }, + "mne/viz/tests/test_utils.py": { + "a": 3, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 10, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3372.json b/mne-python/source/doc/sphinxext/prs/3372.json new file mode 100644 index 0000000000000000000000000000000000000000..147a782e9f3ad08d1928ebe38232015d6d6eca3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3372.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "abbc09736cccefe4e4b5dcd7865836aad4b08980", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/simulation/evoked.py": { + "a": 8, + "d": 2 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3373.json b/mne-python/source/doc/sphinxext/prs/3373.json new file mode 100644 index 0000000000000000000000000000000000000000..e012f1a50935d3ae2e0eb74c347b60d8320d8ede --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3373.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b6bab37a6154aa21c629ad19ac62f49f08f249bb", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 8, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3374.json b/mne-python/source/doc/sphinxext/prs/3374.json new file mode 100644 index 0000000000000000000000000000000000000000..95f66ae5025a74cb1226443a8c780548ba0327e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3374.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "420028b89d7cb9c17bc970b7b795a0f1bff10f18", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/bem.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3375.json b/mne-python/source/doc/sphinxext/prs/3375.json new file mode 100644 index 0000000000000000000000000000000000000000..e7eee1db69346ffeab60a63e116b19f28fa76474 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3375.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "23137be41a8fff39a869673c48804db772d9daef", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/defaults.py": { + "a": 0, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 38, + "d": 11 + }, + "mne/viz/_3d.py": { + "a": 69, + "d": 31 + }, + "mne/viz/tests/test_3d.py": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3376.json b/mne-python/source/doc/sphinxext/prs/3376.json new file mode 100644 index 0000000000000000000000000000000000000000..9142d9df0bf0be80f687ad48a0b12a648df5b3cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3376.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "19fb11a78fc10e66a51def22369d8975c4501d64", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3377.json b/mne-python/source/doc/sphinxext/prs/3377.json new file mode 100644 index 0000000000000000000000000000000000000000..a4b83f2b05e7d53e65230933b734b11d0e21c800 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3377.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "16b30b6665281e53ac2dd14c9a0074ff8ed59e02", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/data/layouts/KIT-UMD-3.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/KIT-UMD-1_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/KIT-UMD-2_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/KIT-UMD-3_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 16, + "d": 2 + }, + "mne/channels/tests/test_layout.py": { + "a": 30, + "d": 33 + }, + "mne/io/constants.py": { + "a": 4, + "d": 0 + }, + "mne/io/kit/constants.py": { + "a": 43, + "d": 18 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 1 + }, + "mne/io/kit/tests/data/test_umd-raw.sqd": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 15, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 29, + "d": 6 + }, + "mne/io/tests/test_meas_info.py": { + "a": 7, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3379.json b/mne-python/source/doc/sphinxext/prs/3379.json new file mode 100644 index 0000000000000000000000000000000000000000..bac27ef80e9a64c475cd0a7514d35ddc59717e57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3379.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0623de9142aa1aeabfde66f065618ef78e613ee5", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "tutorials/plot_artifacts_correction_ica.py": { + "a": 18, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3381.json b/mne-python/source/doc/sphinxext/prs/3381.json new file mode 100644 index 0000000000000000000000000000000000000000..7792377447724e0f8f05dfcccdb7b4ed0022eca7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3381.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0c57855cad9e77e02f2f4352abe1b44dd4c57199", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 38, + "d": 23 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 13, + "d": 0 + }, + "mne/decoding/search_light.py": { + "a": 574, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 109, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3382.json b/mne-python/source/doc/sphinxext/prs/3382.json new file mode 100644 index 0000000000000000000000000000000000000000..fde2d51bb013a524d4f6858a1b8a2577a969fe17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3382.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4c7efc7b41cd616d233bf2a8e557376f1fee493d", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 14, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 13, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3383.json b/mne-python/source/doc/sphinxext/prs/3383.json new file mode 100644 index 0000000000000000000000000000000000000000..cc464e424e086842fb25717abca436ad4a2e7560 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3383.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "4aa3f3a283b3cefd225e2020fcd288564ff96738", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 32, + "d": 4 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 4, + "d": 17 + }, + "mne/gui/_fiducials_gui.py": { + "a": 22, + "d": 9 + }, + "mne/gui/_file_traits.py": { + "a": 33, + "d": 15 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 4, + "d": 1 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 11, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3384.json b/mne-python/source/doc/sphinxext/prs/3384.json new file mode 100644 index 0000000000000000000000000000000000000000..f58ef92e8c6bbb0d8ad3a6299cf5cbe8e736c440 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3384.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "bcca63c1efdd53a6ec5cd4bc7cf2b249e13e8c45", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 9, + "d": 3 + }, + "mne/cov.py": { + "a": 48, + "d": 44 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 14, + "d": 1 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3387.json b/mne-python/source/doc/sphinxext/prs/3387.json new file mode 100644 index 0000000000000000000000000000000000000000..347dd1670fe53be4fd4d89031482576a99682dd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3387.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4ff58df47075b1c1edbc933d57db9eca17c38a61", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 13, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3389.json b/mne-python/source/doc/sphinxext/prs/3389.json new file mode 100644 index 0000000000000000000000000000000000000000..2144ea87f0a2a1426046ee6bdc108297327fadc4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3389.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f038626699ee95d27680dd5f8ae39c2df3b10ae6", + "authors": [ + { + "n": "Félix Raimundo", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 8, + "d": 0 + }, + "mne/io/tests/data/test-ave-2.log": { + "a": 4, + "d": 4 + }, + "mne/io/tests/data/test-ave.log": { + "a": 2, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 1, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/339.json b/mne-python/source/doc/sphinxext/prs/339.json new file mode 100644 index 0000000000000000000000000000000000000000..a3ffd78a1e22f39359da26d50fa564bb40cf4af5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/339.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1db0559c691039a8d1596af0c563d109201e8c42", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 17, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3390.json b/mne-python/source/doc/sphinxext/prs/3390.json new file mode 100644 index 0000000000000000000000000000000000000000..6fe81ee954c53bf484639b6f5e9ec2049f63d27d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3390.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f7c223e53b21c668191c1b36166850b5e3041511", + "authors": [ + { + "n": "Félix Raimundo", + "e": null + } + ], + "changes": { + "mne/baseline.py": { + "a": 7, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 35, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3391.json b/mne-python/source/doc/sphinxext/prs/3391.json new file mode 100644 index 0000000000000000000000000000000000000000..193cece9e76dd2f41f934937fd7a3d527031f26a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3391.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "47bf725320f9b0cc06d973d6a8d94cf7da634f2e", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 5, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 16, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3392.json b/mne-python/source/doc/sphinxext/prs/3392.json new file mode 100644 index 0000000000000000000000000000000000000000..174c40e6354c68d443fa89410809bc701c8aee0f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3392.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cc106f790840c87bcb75eda9d12e4d5a58f0b3de", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/cov.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3394.json b/mne-python/source/doc/sphinxext/prs/3394.json new file mode 100644 index 0000000000000000000000000000000000000000..a35f5b8dd52c6849389de3a676ba52502695002c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3394.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "920f0c3d31e1b939a93fd7ec37044a89076f0b71", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "examples/realtime/ftclient_rt_average.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3396.json b/mne-python/source/doc/sphinxext/prs/3396.json new file mode 100644 index 0000000000000000000000000000000000000000..d5036f33de783463805669899ef4dd19a01f1f9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3396.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3924c38cacf99c711138ca7d012bd08bb5992b31", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/stim_server_client.py": { + "a": 2, + "d": 6 + }, + "mne/realtime/tests/test_stim_client_server.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3397.json b/mne-python/source/doc/sphinxext/prs/3397.json new file mode 100644 index 0000000000000000000000000000000000000000..f521a6b019ef2560fcc781bbd1dab7a771c326b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3397.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "48ef96d37a5f6d8c6648ca0f54002898fa759bab", + "authors": [ + { + "n": "Félix Raimundo", + "e": null + } + ], + "changes": { + "doc/contributing.rst": { + "a": 3, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3398.json b/mne-python/source/doc/sphinxext/prs/3398.json new file mode 100644 index 0000000000000000000000000000000000000000..f72a53f0f8ad6385b30330396eaa2b6ecfe9d102 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3398.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0712b67327b009bd492ab51a34dbf997afedd967", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 15, + "d": 3 + }, + "mne/fixes.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 60, + "d": 17 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 36, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/34.json b/mne-python/source/doc/sphinxext/prs/34.json new file mode 100644 index 0000000000000000000000000000000000000000..c5f5a4dca110b87c416d343aed4ef2ef2867dd76 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/34.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "ad83d323d4afd6e50853bb165a9574d66e1dc3b9", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/_images/plot_read_and_write_raw_data.png": { + "a": 0, + "d": 0 + }, + "doc/source/_images/plot_read_epochs.png": { + "a": 0, + "d": 0 + }, + "doc/source/_images/plot_time_frequency.png": { + "a": 0, + "d": 0 + }, + "doc/source/_templates/class.rst": { + "a": 12, + "d": 0 + }, + "doc/source/_templates/function.rst": { + "a": 8, + "d": 0 + }, + "doc/source/conf.py": { + "a": 1, + "d": 1 + }, + "doc/source/mne-python.rst": { + "a": 1, + "d": 0 + }, + "doc/source/python_reference.rst": { + "a": 117, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 7, + "d": 4 + }, + "mne/artifacts/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/fiff/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/fiff/pick.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 9, + "d": 0 + }, + "mne/stats/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/viz.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3400.json b/mne-python/source/doc/sphinxext/prs/3400.json new file mode 100644 index 0000000000000000000000000000000000000000..68d7ca92aa5c38ed4a309fddedc2055c1ab0c15e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3400.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "c0d956cd46f7274d2b85e634873f88be34945c82", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "doc/_templates/class.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/pitfalls.rst": { + "a": 0, + "d": 13 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 52, + "d": 12 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 37, + "d": 36 + }, + "mne/utils.py": { + "a": 12, + "d": 4 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_eeg_erp.py": { + "a": 15, + "d": 9 + }, + "tutorials/plot_introduction.py": { + "a": 29, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3402.json b/mne-python/source/doc/sphinxext/prs/3402.json new file mode 100644 index 0000000000000000000000000000000000000000..6fc82416adc4aa33a97352be98e48dc73bb27f29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3402.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "0324f0009d408a8c7d6b2c50cd035369112904d3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 11, + "d": 5 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 3, + "d": 4 + }, + "mne/datasets/utils.py": { + "a": 7, + "d": 10 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 5 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 15, + "d": 15 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 11, + "d": 10 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 3 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3403.json b/mne-python/source/doc/sphinxext/prs/3403.json new file mode 100644 index 0000000000000000000000000000000000000000..364bb5a91892225d73fc5782f7a6120533de4f24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3403.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2ac5a96af70155dbfaabc4f2da73932593ad2f25", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/dipole.py": { + "a": 8, + "d": 5 + }, + "mne/simulation/tests/test_raw.py": { + "a": 31, + "d": 8 + }, + "mne/tests/test_dipole.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3404.json b/mne-python/source/doc/sphinxext/prs/3404.json new file mode 100644 index 0000000000000000000000000000000000000000..678686d62b47545f18f7f6bff3499a43c31298e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3404.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "570c7decd734e6b6c6318ecc218cfb87185fd691", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/epochs.py": { + "a": 6, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3407.json b/mne-python/source/doc/sphinxext/prs/3407.json new file mode 100644 index 0000000000000000000000000000000000000000..2be31c0223ddd2790d1cba6f582bc346cbfbe9af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3407.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "7e82836403d6f2a593e63620e489c99c00b10471", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 13, + "d": 1 + }, + "doc/Makefile": { + "a": 3, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 12, + "d": 0 + }, + "doc/tutorials.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 6, + "d": 2 + }, + "mne/datasets/brainstorm/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 50, + "d": 0 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 51, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 7, + "d": 4 + }, + "mne/dipole.py": { + "a": 63, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 5, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 20, + "d": 3 + }, + "mne/tests/test_import_nesting.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_line_endings.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_brainstorm_phantom_ctf.py": { + "a": 93, + "d": 0 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 101, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3408.json b/mne-python/source/doc/sphinxext/prs/3408.json new file mode 100644 index 0000000000000000000000000000000000000000..1129daf3b5caaf055b903b4261acc2a6e9cbca7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3408.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0fbc4cd0b54e3e51b3451e2c9f69fea194f3a633", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 6, + "d": 9 + }, + "mne/evoked.py": { + "a": 4, + "d": 7 + }, + "mne/io/base.py": { + "a": 38, + "d": 10 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_utils.py": { + "a": 20, + "d": 1 + }, + "mne/utils.py": { + "a": 37, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3409.json b/mne-python/source/doc/sphinxext/prs/3409.json new file mode 100644 index 0000000000000000000000000000000000000000..46828e07400420bef186fb2160e25937e13c5128 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3409.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "8a3fbf59d0e15b3e4f6abd6b479a37f32d2324b6", + "authors": [ + { + "n": "Asish Panda", + "e": "asishrocks95@gmail.com" + } + ], + "changes": { + "doc/manual/decoding.rst": { + "a": 4, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_decoding_xdawn_transformer.py": { + "a": 2, + "d": 2 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 2, + "d": 2 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 27, + "d": 2 + }, + "mne/decoding/transformer.py": { + "a": 105, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/341.json b/mne-python/source/doc/sphinxext/prs/341.json new file mode 100644 index 0000000000000000000000000000000000000000..dae89a60e3d52c72c09df172fc450e195b77902c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/341.json @@ -0,0 +1,363 @@ +{ + "merge_commit_sha": "a96b6473515a92af946d32e86524625a49661696", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 51, + "d": 7 + }, + "doc/source/python_tutorial.rst": { + "a": 27, + "d": 16 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/export/plot_epochs_as_data_frame.py": { + "a": 1, + "d": 1 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 1, + "d": 1 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 1, + "d": 1 + }, + "examples/export/plot_raw_to_nitime.py": { + "a": 1, + "d": 1 + }, + "examples/extract_events_from_raw.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_dipole_fit_result.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_label_activation_from_stc.py": { + "a": 33, + "d": 33 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_morph_data.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_stc.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/plot_estimate_covariance_matrix_baseline.py": { + "a": 1, + "d": 1 + }, + "examples/plot_estimate_covariance_matrix_raw.py": { + "a": 1, + "d": 1 + }, + "examples/plot_evoked_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_and_write_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_bem_surfaces.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_forward.py": { + "a": 1, + "d": 1 + }, + "examples/plot_read_noise_covariance_matrix.py": { + "a": 1, + "d": 1 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topo_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topography.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ecg_artifacts_from_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_eog_artifacts_from_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "examples/read_events.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_source_psd_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_tfr_topography.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/megsim/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/megsim/megsim.py": { + "a": 192, + "d": 0 + }, + "mne/datasets/megsim/urls.py": { + "a": 160, + "d": 0 + }, + "mne/datasets/sample/__init__.py": { + "a": 1, + "d": 97 + }, + "mne/datasets/sample/sample.py": { + "a": 141, + "d": 0 + }, + "mne/label.py": { + "a": 26, + "d": 28 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 2 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 1, + "d": 2 + }, + "mne/mixed_norm/tests/test_inverse.py": { + "a": 1, + "d": 2 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 2 + }, + "mne/simulation/tests/test_source.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_forward.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 21, + "d": 2 + }, + "mne/utils.py": { + "a": 341, + "d": 145 + }, + "mne/viz.py": { + "a": 10, + "d": 9 + }, + "setup.py": { + "a": 49, + "d": 49 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3413.json b/mne-python/source/doc/sphinxext/prs/3413.json new file mode 100644 index 0000000000000000000000000000000000000000..c9c17dfee3eed05d768c7d467840850e7ac5930a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3413.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "08691929b5a56cd1e6d3a33b9642e59afd05f5ae", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 446, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 42, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3414.json b/mne-python/source/doc/sphinxext/prs/3414.json new file mode 100644 index 0000000000000000000000000000000000000000..479954f055103448484ab9283c1849cc1c810571 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3414.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bc9ecbd9c1e15a0a15de6ad76b1e9d7e3ab44111", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 18, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3415.json b/mne-python/source/doc/sphinxext/prs/3415.json new file mode 100644 index 0000000000000000000000000000000000000000..e6126cc91fa1d7d3287d32698f7665928ad89289 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3415.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "22cbba65a894601e760eb64e2ce5ca7d097093cd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3418.json b/mne-python/source/doc/sphinxext/prs/3418.json new file mode 100644 index 0000000000000000000000000000000000000000..c23f318f7186f980320218412698a6148bcd813e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3418.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e680383bbd3f96a0313fee599ea96d3149887f96", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/data/coil_def.dat": { + "a": 16, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/342.json b/mne-python/source/doc/sphinxext/prs/342.json new file mode 100644 index 0000000000000000000000000000000000000000..42de9c2b3aadd461941501bd35dcf21242472bcb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/342.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "7b8a41751982740bed876de25870f01a6c5b253c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/baseline.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 5, + "d": 3 + }, + "mne/fiff/evoked.py": { + "a": 8, + "d": 0 + }, + "mne/fiff/open.py": { + "a": 5, + "d": 3 + }, + "mne/fiff/raw.py": { + "a": 5, + "d": 1 + }, + "mne/fiff/tag.py": { + "a": 90, + "d": 17 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 4, + "d": 7 + }, + "mne/fiff/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/forward.py": { + "a": 4, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 3, + "d": 3 + }, + "mne/mixed_norm/tests/test_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 3, + "d": 1 + }, + "mne/utils.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3422.json b/mne-python/source/doc/sphinxext/prs/3422.json new file mode 100644 index 0000000000000000000000000000000000000000..98b598c2b0e925adc641a44decd307dc80a84b51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3422.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2921f56c5a23ae39e5d6b4a9173695925d291bae", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/commands/mne_coreg.py": { + "a": 5, + "d": 5 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 3, + "d": 3 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 5, + "d": 4 + }, + "mne/utils.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3423.json b/mne-python/source/doc/sphinxext/prs/3423.json new file mode 100644 index 0000000000000000000000000000000000000000..fe28fb478a61f996eda39135ad2970309babf148 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3423.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d9a2d09acb93619ef4c63dd04f907e4305c472e0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 16, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3425.json b/mne-python/source/doc/sphinxext/prs/3425.json new file mode 100644 index 0000000000000000000000000000000000000000..936eb8736e3b9b9b2f3d73379b52b56f01036c9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3425.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "8823240c015a993c7a4585c0b268f42306faddf3", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "examples/decoding/plot_decoding_xdawn_transformer.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 2, + "d": 3 + }, + "mne/decoding/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/tests/test_xdawn.py": { + "a": 0, + "d": 97 + }, + "mne/decoding/xdawn.py": { + "a": 0, + "d": 174 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 123, + "d": 56 + }, + "mne/preprocessing/xdawn.py": { + "a": 421, + "d": 288 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3429.json b/mne-python/source/doc/sphinxext/prs/3429.json new file mode 100644 index 0000000000000000000000000000000000000000..506a55305ebfd1ab1b4291326167f9cfbe6e6364 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3429.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "aeceebdfc8d4e21d594263fc6b1304d209446944", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 36, + "d": 18 + }, + "mne/viz/tests/test_misc.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/343.json b/mne-python/source/doc/sphinxext/prs/343.json new file mode 100644 index 0000000000000000000000000000000000000000..98842912e23992bef899fe92892d85eca0ddc1fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/343.json @@ -0,0 +1,10 @@ +{ + "merge_commit_sha": "dfbd985583a9bc372951bc54311be17038210124", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": {} +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3431.json b/mne-python/source/doc/sphinxext/prs/3431.json new file mode 100644 index 0000000000000000000000000000000000000000..38849b02d203035548c2413cddefc712d22b1c8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3431.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bd7d7b7a90553a48eebf73fc05062d9c6ea5c3c5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3434.json b/mne-python/source/doc/sphinxext/prs/3434.json new file mode 100644 index 0000000000000000000000000000000000000000..8a5a7303f8156736f87ee28c9e5c577e9778cc5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3434.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "facfc051d1411b3d8c80023305a2850b746b16ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_csp.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 8, + "d": 7 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 5, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3436.json b/mne-python/source/doc/sphinxext/prs/3436.json new file mode 100644 index 0000000000000000000000000000000000000000..0b659bb402292108aa77cea34f509a2a4e9bfe2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3436.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "df88642e06748bb321e623e290d935e0142545e1", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 10, + "d": 10 + }, + "mne/proj.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3437.json b/mne-python/source/doc/sphinxext/prs/3437.json new file mode 100644 index 0000000000000000000000000000000000000000..9b6628437f41715cbd5b8c4e5c87377790259e47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3437.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "96765bbd30d3de2a50de2c699046fc33cedb176c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 0, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 10, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 25, + "d": 29 + }, + "mne/utils.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3438.json b/mne-python/source/doc/sphinxext/prs/3438.json new file mode 100644 index 0000000000000000000000000000000000000000..52fc15d6b636b719581b1b49101fcb055f92962b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3438.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a03fb06100be7c9f8ef4efdf7153c24b866ad54f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 7, + "d": 4 + }, + "mne/commands/tests/test_commands.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3439.json b/mne-python/source/doc/sphinxext/prs/3439.json new file mode 100644 index 0000000000000000000000000000000000000000..cad6fb0cbfb0e501f97eeade202122deb16e6864 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3439.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "ca0ded303cac3a5c6187186f0e517a23e4aa0df6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_file_traits.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 8, + "d": 3 + }, + "mne/utils.py": { + "a": 16, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3440.json b/mne-python/source/doc/sphinxext/prs/3440.json new file mode 100644 index 0000000000000000000000000000000000000000..12e7c39922f1eba87b5df7fa6f06989cfe7cc89f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3440.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "90e9e9c9840b537226b6f841f823dcfbdc1bfa24", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 4, + "d": 2 + }, + "mne/io/base.py": { + "a": 68, + "d": 29 + }, + "mne/io/compensator.py": { + "a": 22, + "d": 15 + }, + "mne/io/ctf/info.py": { + "a": 20, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 12, + "d": 27 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 107, + "d": 28 + }, + "mne/io/tests/test_compensator.py": { + "a": 32, + "d": 10 + }, + "mne/preprocessing/maxwell.py": { + "a": 5, + "d": 8 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 15, + "d": 12 + }, + "mne/tests/test_epochs.py": { + "a": 0, + "d": 3 + }, + "tutorials/plot_brainstorm_phantom_ctf.py": { + "a": 20, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3443.json b/mne-python/source/doc/sphinxext/prs/3443.json new file mode 100644 index 0000000000000000000000000000000000000000..35b9986f20a2e6bb59750e29aaea861001507c73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3443.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "50f0a4062e0d4985fe953def7d608bd0b7452613", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "examples/decoding/plot_decoding_xdawn_transformer.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3446.json b/mne-python/source/doc/sphinxext/prs/3446.json new file mode 100644 index 0000000000000000000000000000000000000000..e82b79da47be081e75fc4e1f1b96a2e7effab256 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3446.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e17e31fc42874461648c40a8b5d11e3aced74ab7", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 70, + "d": 33 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 57, + "d": 0 + }, + "mne/decoding/ems.py": { + "a": 118, + "d": 28 + }, + "mne/decoding/tests/test_ems.py": { + "a": 35, + "d": 3 + }, + "mne/decoding/time_gen.py": { + "a": 2, + "d": 35 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3448.json b/mne-python/source/doc/sphinxext/prs/3448.json new file mode 100644 index 0000000000000000000000000000000000000000..9538f393d791fca1f0a44cea7fa44e94f069d5b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3448.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b0a6ed3a75530e2d8a54d81bdba854a0db978deb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 16, + "d": 1 + }, + "mne/utils.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3449.json b/mne-python/source/doc/sphinxext/prs/3449.json new file mode 100644 index 0000000000000000000000000000000000000000..e87c12eba8bd01e4745ced95a3ceee623099b5b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3449.json @@ -0,0 +1,155 @@ +{ + "merge_commit_sha": "c674fe7e305c0eebc4ccb8f4bcbd0ee170f33d17", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 3, + "d": 0 + }, + "doc/tutorials.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 17, + "d": 1 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 3, + "d": 1 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 2, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 3, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 9, + "d": 3 + }, + "mne/decoding/transformer.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 685, + "d": 446 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 10, + "d": 9 + }, + "mne/io/base.py": { + "a": 85, + "d": 39 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 4 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 34, + "d": 27 + }, + "mne/io/tests/test_pick.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 7, + "d": 2 + }, + "mne/preprocessing/ssp.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 127, + "d": 151 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 9, + "d": 8 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 107, + "d": 104 + }, + "mne/time_frequency/csd.py": { + "a": 2, + "d": 3 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 44, + "d": 16 + }, + "tutorials/plot_background_filtering.py": { + "a": 351, + "d": 25 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_modifying_data_inplace.py": { + "a": 16, + "d": 10 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/345.json b/mne-python/source/doc/sphinxext/prs/345.json new file mode 100644 index 0000000000000000000000000000000000000000..aece076d843b669f3c72192649b3ec0901d4a03b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/345.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "90834d3c52aae1f2fecd4ee7e77001e949704b9f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz.py": { + "a": 21, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3450.json b/mne-python/source/doc/sphinxext/prs/3450.json new file mode 100644 index 0000000000000000000000000000000000000000..a0f3c598867029136d7f96fce0c65090535d72cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3450.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ad3dc3a6bbc342334f8b418cbd23b1786785620c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 52, + "d": 17 + }, + "mne/viz/tests/test_misc.py": { + "a": 3, + "d": 0 + }, + "tutorials/plot_forward.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3452.json b/mne-python/source/doc/sphinxext/prs/3452.json new file mode 100644 index 0000000000000000000000000000000000000000..21cb74cb13ef408f787116e69e262120ae5d7ad6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3452.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5ea20abbb53dc13cd6b39eeefa9721904eb0417c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 15, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3453.json b/mne-python/source/doc/sphinxext/prs/3453.json new file mode 100644 index 0000000000000000000000000000000000000000..e40801d67f87b118876f2483d01825adbea0d363 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3453.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6957b937e15fab9768c9f0cfd235b549bfceced6", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3456.json b/mne-python/source/doc/sphinxext/prs/3456.json new file mode 100644 index 0000000000000000000000000000000000000000..b53af04491fee9b58ee06191c568d826eb0455fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3456.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "403ab40f91a8bd196159e779a34d06823dc7209f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/tests/test_montage.py": { + "a": 20, + "d": 36 + }, + "mne/datasets/megsim/urls.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 3, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 35, + "d": 35 + }, + "tutorials/plot_stats_cluster_methods.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3457.json b/mne-python/source/doc/sphinxext/prs/3457.json new file mode 100644 index 0000000000000000000000000000000000000000..be2ae87a0d9d70d3bb6fdca1fefb85dca09f6960 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3457.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cb1f1197f6521740c03ab84337cc253ac45c2195", + "authors": [ + { + "n": "Guillaume Dumas", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 7, + "d": 4 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/346.json b/mne-python/source/doc/sphinxext/prs/346.json new file mode 100644 index 0000000000000000000000000000000000000000..69885f885fdc0e6a4c1cb962435b6619d1b16aae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/346.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "611a36e7bb008fe9a1d9f069ab06db916aab9ebb", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3462.json b/mne-python/source/doc/sphinxext/prs/3462.json new file mode 100644 index 0000000000000000000000000000000000000000..8957567cdd15ad644890b33db3590fe9e9fea9e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3462.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f28a3d54d5f30335359fc2b49a5784314c9a028b", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3463.json b/mne-python/source/doc/sphinxext/prs/3463.json new file mode 100644 index 0000000000000000000000000000000000000000..851eb884797eda09a9f0166fe76d963c8fbe6f72 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3463.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b02f5bd8a51274d6f683cd079d28af04e28bce63", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 180, + "d": 66 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 10, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 35, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3466.json b/mne-python/source/doc/sphinxext/prs/3466.json new file mode 100644 index 0000000000000000000000000000000000000000..3058ddcb6eaf8a6b52217c3ca27ab408875ce349 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3466.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "31c2c28a9134f3ca86f762ebb1a48de7659e9c22", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 39, + "d": 2 + }, + "mne/tests/test_coreg.py": { + "a": 35, + "d": 7 + }, + "mne/transforms.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3469.json b/mne-python/source/doc/sphinxext/prs/3469.json new file mode 100644 index 0000000000000000000000000000000000000000..ac761420980485560c5d23d384ac5c086f6799ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3469.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "50bee3363f1ab8a782fa6ed9d40a736061f4e13d", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_morph_data.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3472.json b/mne-python/source/doc/sphinxext/prs/3472.json new file mode 100644 index 0000000000000000000000000000000000000000..b2e36c2a15cc82da9ae88aff320dacb5e7ceb3a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3472.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "87b570c4592dcf68b631dfcba1d7f9d919514e57", + "authors": [ + { + "n": "Asish Panda", + "e": "asishrocks95@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 30, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 157, + "d": 1 + }, + "mne/filter.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3476.json b/mne-python/source/doc/sphinxext/prs/3476.json new file mode 100644 index 0000000000000000000000000000000000000000..af8835b5cb6d4e0c33011610b1454006608f97eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3476.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "7f716027a49e884978de738152aaca76b1f18b5b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 5, + "d": 5 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 32 + }, + "mne/time_frequency/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 158, + "d": 16 + }, + "mne/time_frequency/tfr.py": { + "a": 798, + "d": 581 + }, + "mne/utils.py": { + "a": 31, + "d": 0 + }, + "tutorials/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 28, + "d": 45 + }, + "tutorials/plot_stats_cluster_time_frequency.py": { + "a": 37, + "d": 52 + }, + "tutorials/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 26, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3477.json b/mne-python/source/doc/sphinxext/prs/3477.json new file mode 100644 index 0000000000000000000000000000000000000000..67170f21dd8dac9f219350ad118c2db34e961a3f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3477.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5d2a6493b3f3e5a4f3e7cbb8067617e0b7cbfcb0", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 11, + "d": 5 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3479.json b/mne-python/source/doc/sphinxext/prs/3479.json new file mode 100644 index 0000000000000000000000000000000000000000..4ba051fc622686ab989673a7df8382aa00a6e0ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3479.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "de463affe20f58dc50093c479c311ce40bed4e49", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 15, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 69, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 11, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 28, + "d": 3 + }, + "mne/utils.py": { + "a": 20, + "d": 0 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3481.json b/mne-python/source/doc/sphinxext/prs/3481.json new file mode 100644 index 0000000000000000000000000000000000000000..fb06f26b00826721d75fc96ceb7149f9ac0d8bad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3481.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bc8cab4b8b4b45085f3f786a73685dfdcd5bc306", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/search_light.py": { + "a": 93, + "d": 64 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 34, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3485.json b/mne-python/source/doc/sphinxext/prs/3485.json new file mode 100644 index 0000000000000000000000000000000000000000..11f2729723301d9bd54c8ee85daba0391be638f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3485.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "728b189f7221293affb1aa75ca5b05af8ab37b8a", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 209, + "d": 84 + }, + "mne/decoding/tests/test_csp.py": { + "a": 67, + "d": 27 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3486.json b/mne-python/source/doc/sphinxext/prs/3486.json new file mode 100644 index 0000000000000000000000000000000000000000..ee79cbecf637cc166557e2d194fb097f0b3413aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3486.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "859d2814d9b78c86396de176715457f3d3ef513a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/plot_object_raw.py": { + "a": 21, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3487.json b/mne-python/source/doc/sphinxext/prs/3487.json new file mode 100644 index 0000000000000000000000000000000000000000..9d0fef8c671a774473cb06d2ba3a7094e26f2c40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3487.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "b8ccffee83f0b6c15348924d1125f1b743ad9a5b", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 13, + "d": 21 + }, + "mne/channels/layout.py": { + "a": 0, + "d": 2 + }, + "mne/cov.py": { + "a": 7, + "d": 35 + }, + "mne/epochs.py": { + "a": 35, + "d": 370 + }, + "mne/evoked.py": { + "a": 25, + "d": 382 + }, + "mne/io/base.py": { + "a": 9, + "d": 209 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/pick.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 9, + "d": 244 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 96 + }, + "mne/tests/test_utils.py": { + "a": 120, + "d": 1 + }, + "mne/utils.py": { + "a": 171, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 6, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3488.json b/mne-python/source/doc/sphinxext/prs/3488.json new file mode 100644 index 0000000000000000000000000000000000000000..ef7af1e1698358cb87e30a26fda1dd02a253ea59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3488.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "a446cf13b0c34bd390af22aa192ba42f04eddc86", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/time_frequency/README.txt": { + "a": 1, + "d": 2 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 41, + "d": 0 + }, + "mne/decoding/time_frequency.py": { + "a": 152, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 82, + "d": 39 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3489.json b/mne-python/source/doc/sphinxext/prs/3489.json new file mode 100644 index 0000000000000000000000000000000000000000..0a8b91d78a6e154eb27e8f54b4b453c728059acc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3489.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "59c6e749bcdfbe4c43f553070452b3fe57ee3974", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/annotations.py": { + "a": 19, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3490.json b/mne-python/source/doc/sphinxext/prs/3490.json new file mode 100644 index 0000000000000000000000000000000000000000..4eb2ea9afbc291578400d0081cb21734af18fe68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3490.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "93972513cfbd2f96f14d281e27b2a8f852f3ffef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 220, + "d": 59 + }, + "mne/io/base.py": { + "a": 30, + "d": 8 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 8, + "d": 10 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 6, + "d": 4 + }, + "mne/tests/test_filter.py": { + "a": 79, + "d": 33 + }, + "tutorials/plot_background_filtering.py": { + "a": 123, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3491.json b/mne-python/source/doc/sphinxext/prs/3491.json new file mode 100644 index 0000000000000000000000000000000000000000..3fb8b9cfbab9a1a126e7bbeec784f2a7787422a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3491.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "baf9bf4f8f28725ffe70aa8f8b94281df8fef7f6", + "authors": [ + { + "n": "Simon-Shlomo Poil", + "e": null + } + ], + "changes": { + "tutorials/plot_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3492.json b/mne-python/source/doc/sphinxext/prs/3492.json new file mode 100644 index 0000000000000000000000000000000000000000..c4a6946ae5783f8a7ff93b088eaae260289b6f07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3492.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2cd00085753883b195987a0053c993c0cd679f4b", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/report.py": { + "a": 30, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3494.json b/mne-python/source/doc/sphinxext/prs/3494.json new file mode 100644 index 0000000000000000000000000000000000000000..4933d6c4390490a7a637e7489fc63fe749d5058d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3494.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5f623d90c8c71e91d07a7a44627bfa81411756a0", + "authors": [ + { + "n": "alexandre barachant", + "e": null + } + ], + "changes": { + "examples/decoding/plot_decoding_xdawn_transformer.py": { + "a": 38, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3496.json b/mne-python/source/doc/sphinxext/prs/3496.json new file mode 100644 index 0000000000000000000000000000000000000000..a3531971c301e7af751083810e65b9625eca075c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3496.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "112ffac0eba6df83cc6269c5c50ca7e64e5cd22a", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 16, + "d": 15 + }, + "mne/viz/tests/test_ica.py": { + "a": 23, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 21, + "d": 2 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 48, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3497.json b/mne-python/source/doc/sphinxext/prs/3497.json new file mode 100644 index 0000000000000000000000000000000000000000..ba4f59953ee78784c76f47ef87010367765dbbd4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3497.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1145f0b815337be0e91beb7fdaf960dc4160d27a", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3498.json b/mne-python/source/doc/sphinxext/prs/3498.json new file mode 100644 index 0000000000000000000000000000000000000000..6adf1ad45a1b44e524634089d0d1aa9eac136d53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3498.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c2e14b8789c6d5f79023ef45f09e4b0745d3bfd4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/35.json b/mne-python/source/doc/sphinxext/prs/35.json new file mode 100644 index 0000000000000000000000000000000000000000..a3073c62a8f9830efd8d6914096dbebf0af8a3cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/35.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "16a81f211c2c2b4410bb75d55a8e7ceadaf07fea", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 133, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/proj.py": { + "a": 4, + "d": 41 + }, + "mne/proj.py": { + "a": 115, + "d": 4 + }, + "mne/tests/test_proj.py": { + "a": 17, + "d": 13 + }, + "mne/utils.py": { + "a": 92, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/350.json b/mne-python/source/doc/sphinxext/prs/350.json new file mode 100644 index 0000000000000000000000000000000000000000..ce161288d4ab2abb2268962f216969f8f87e088a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/350.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "b4303ef661798f9dd128ce9db8d232cdb59535ca", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 22, + "d": 3 + }, + "mne/fiff/evoked.py": { + "a": 25, + "d": 5 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 13, + "d": 1 + }, + "mne/filter.py": { + "a": 49, + "d": 8 + }, + "mne/tests/test_epochs.py": { + "a": 31, + "d": 0 + }, + "mne/tests/test_filter.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3500.json b/mne-python/source/doc/sphinxext/prs/3500.json new file mode 100644 index 0000000000000000000000000000000000000000..9e18aa909285df5e71130b0ea2ee83bc330f3402 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3500.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3505b0e11dc66974158029f48bbe453d3c2c79a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/event.py": { + "a": 69, + "d": 25 + }, + "mne/realtime/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_event.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3501.json b/mne-python/source/doc/sphinxext/prs/3501.json new file mode 100644 index 0000000000000000000000000000000000000000..1d99c5e4c5f59695a39762094ccbba62956c96be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3501.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4b72527146af2e71675e3c19838fd6e13609ee36", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 58, + "d": 42 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_filter.py": { + "a": 17, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3502.json b/mne-python/source/doc/sphinxext/prs/3502.json new file mode 100644 index 0000000000000000000000000000000000000000..a465f0931dc5a1bde73d78ca10a97b81bddd4b93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3502.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a294c335d5bc5911aa452dad801f2ae62ae80224", + "authors": [ + { + "n": "Asish Panda", + "e": "asishrocks95@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/search_light.py": { + "a": 31, + "d": 5 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3504.json b/mne-python/source/doc/sphinxext/prs/3504.json new file mode 100644 index 0000000000000000000000000000000000000000..18b0e70c126f718fbc5d3af139faefa18a59b0cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3504.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ee84544768ea747825801634966b0bedbab20b00", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3505.json b/mne-python/source/doc/sphinxext/prs/3505.json new file mode 100644 index 0000000000000000000000000000000000000000..f3c9fc216dd74efb8fedea8a1ed7a953956774b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3505.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9ed6a7e43c060cba4d7a16f4014293fc0bf975b0", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/infomax_.py": { + "a": 60, + "d": 63 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3506.json b/mne-python/source/doc/sphinxext/prs/3506.json new file mode 100644 index 0000000000000000000000000000000000000000..cd249a282300f40d0ef9bdc45e55ad967ba74851 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3506.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e4a6257d5b3da5f454a9d7b967d3f9b016881d14", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 20, + "d": 6 + }, + "tutorials/plot_eeg_erp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/351.json b/mne-python/source/doc/sphinxext/prs/351.json new file mode 100644 index 0000000000000000000000000000000000000000..3b74d2bd7d864c7a6154230622c845081bb94fd3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/351.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e957546f1750cc0e4582dea8d81c8a5b43ffb516", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/sample/sample.py": { + "a": 5, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3510.json b/mne-python/source/doc/sphinxext/prs/3510.json new file mode 100644 index 0000000000000000000000000000000000000000..ef845d4b63d71d99da3086d9c22f693a2164a62a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3510.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d84d5cfb64507cd2e437cf0f35fbe25be55716d9", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 56, + "d": 15 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 24, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3511.json b/mne-python/source/doc/sphinxext/prs/3511.json new file mode 100644 index 0000000000000000000000000000000000000000..a6c0e1c38ce620c1c8fee74c36678b8e67412088 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3511.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "038e8687a974184184390523c996aa74c3370d25", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3514.json b/mne-python/source/doc/sphinxext/prs/3514.json new file mode 100644 index 0000000000000000000000000000000000000000..c7d7608aeb72c6003870b5ae2b0730f5b09734ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3514.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "93c8902a0c559b6c4274a4f1f652f8e1a2075bd8", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 2, + "d": 0 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3517.json b/mne-python/source/doc/sphinxext/prs/3517.json new file mode 100644 index 0000000000000000000000000000000000000000..c03e5af3b3a157f1bf449da17a259b98a69484a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3517.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e09124ed975eb7877897226c150979fda8976521", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/annotations.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3520.json b/mne-python/source/doc/sphinxext/prs/3520.json new file mode 100644 index 0000000000000000000000000000000000000000..6d4339a796e6498842a8ad8b47641c9a07b71f77 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3520.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5584a5c3d9d73985cf1501fa3e90465113158497", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/array/array.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 17, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3522.json b/mne-python/source/doc/sphinxext/prs/3522.json new file mode 100644 index 0000000000000000000000000000000000000000..074917cedaba699e108c5f973106d8f1351434b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3522.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ad19aef0f96376132b1fd4d8217a8dda17cdd1d6", + "authors": [ + { + "n": "Christopher Mullins", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 9, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 17, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3524.json b/mne-python/source/doc/sphinxext/prs/3524.json new file mode 100644 index 0000000000000000000000000000000000000000..3038ec8a80fd80e6a5707933f6d98db3c382ad17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3524.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "32dd32a288d85117747a8fb205e137df6ff58568", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 5, + "d": 0 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3526.json b/mne-python/source/doc/sphinxext/prs/3526.json new file mode 100644 index 0000000000000000000000000000000000000000..7bc56298f3e55c717a82e2f8dd3425a87050226b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3526.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1c11647a74fb604b6783dd92d89872c63c738348", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/353.json b/mne-python/source/doc/sphinxext/prs/353.json new file mode 100644 index 0000000000000000000000000000000000000000..363a47455ca318e7458830887427c407c1cfc6eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/353.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9689ff0499d2d4e0fabea86385720c3151f68b80", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3530.json b/mne-python/source/doc/sphinxext/prs/3530.json new file mode 100644 index 0000000000000000000000000000000000000000..221b1680c4cd9e2dc12d099f9a2b8447bae52771 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3530.json @@ -0,0 +1,271 @@ +{ + "merge_commit_sha": "019756bbc6006874a867ddcf2ada64133627532f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 6, + "d": 11 + }, + "README.rst": { + "a": 7, + "d": 8 + }, + "doc/Makefile": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 4 + }, + "mne/bem.py": { + "a": 3, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 3, + "d": 3 + }, + "mne/chpi.py": { + "a": 3, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 4, + "d": 3 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 29, + "d": 22 + }, + "mne/cov.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/sample/sample.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/somato/somato.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/testing/_testing.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/ems.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_ems.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 5, + "d": 3 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 4, + "d": 6 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/evoked.py": { + "a": 2, + "d": 4 + }, + "mne/filter.py": { + "a": 8, + "d": 10 + }, + "mne/fixes.py": { + "a": 5, + "d": 875 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 4 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 5, + "d": 9 + }, + "mne/io/base.py": { + "a": 2, + "d": 3 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 4, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/open.py": { + "a": 6, + "d": 6 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 7, + "d": 6 + }, + "mne/label.py": { + "a": 7, + "d": 8 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/maxwell.py": { + "a": 6, + "d": 5 + }, + "mne/simulation/tests/test_raw.py": { + "a": 4, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 7, + "d": 8 + }, + "mne/source_space.py": { + "a": 12, + "d": 10 + }, + "mne/stats/cluster_level.py": { + "a": 6, + "d": 7 + }, + "mne/stats/parametric.py": { + "a": 1, + "d": 2 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 5, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_fixes.py": { + "a": 4, + "d": 179 + }, + "mne/tests/test_label.py": { + "a": 9, + "d": 12 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_report.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_surface.py": { + "a": 3, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 3, + "d": 20 + }, + "mne/viz/circle.py": { + "a": 3, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3532.json b/mne-python/source/doc/sphinxext/prs/3532.json new file mode 100644 index 0000000000000000000000000000000000000000..8947513fcff620b0cd0c22ba3cf50c058736caf8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3532.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "89f5f5486259c96988d553db692d8a6a52243c56", + "authors": [ + { + "n": "Phillip Alday", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 10, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 114, + "d": 31 + }, + "mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.eeg": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.vhdr": { + "a": 156, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.vmrk": { + "a": 14, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 19, + "d": 4 + }, + "mne/tests/test_line_endings.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3534.json b/mne-python/source/doc/sphinxext/prs/3534.json new file mode 100644 index 0000000000000000000000000000000000000000..bce18578289821c870d0f32f580acbd57b2c7d14 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3534.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "71b15a704b94f2054cff9bd04c553cc862040405", + "authors": [ + { + "n": "Phillip Alday", + "e": null + } + ], + "changes": { + "mne/io/reference.py": { + "a": 22, + "d": 13 + }, + "mne/io/tests/test_reference.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3535.json b/mne-python/source/doc/sphinxext/prs/3535.json new file mode 100644 index 0000000000000000000000000000000000000000..ecc69870f2698fc1f0e58f34095bee9bc2d6c923 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3535.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9f056c80697b35e3a6b5d2c9b3f3715d240568af", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/index.rst": { + "a": 1, + "d": 1 + }, + "doc/tutorials.rst": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_introduction.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/354.json b/mne-python/source/doc/sphinxext/prs/354.json new file mode 100644 index 0000000000000000000000000000000000000000..8f542c2d008316d7caa0b14afe955db5a14103c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/354.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "893e18b6f7f4a8214a1faecde81c72d25cbd2983", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 8, + "d": 21 + }, + "mne/utils.py": { + "a": 12, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3540.json b/mne-python/source/doc/sphinxext/prs/3540.json new file mode 100644 index 0000000000000000000000000000000000000000..263469148cf951221d76d77abf8e10b423511306 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3540.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7ce837ad076a08f1de0c79ca7b4909e2a6a2d0d6", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 12, + "d": 12 + }, + "mne/io/base.py": { + "a": 67, + "d": 6 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 23, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 25, + "d": 16 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3544.json b/mne-python/source/doc/sphinxext/prs/3544.json new file mode 100644 index 0000000000000000000000000000000000000000..10df5865d667712dabf17667d2cd378573aea2a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3544.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6d780f01d7b888992441e602e8b6913e58992414", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 49, + "d": 10 + }, + "mne/tests/test_chpi.py": { + "a": 51, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3545.json b/mne-python/source/doc/sphinxext/prs/3545.json new file mode 100644 index 0000000000000000000000000000000000000000..2cc5784ba9a9e91ee63df10dd792b77a03f9d506 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3545.json @@ -0,0 +1,447 @@ +{ + "merge_commit_sha": "765cff8a214f45045b45ff2500a4a91ecdaa2b32", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + }, + "doc/manual/io.rst": { + "a": 19, + "d": 3 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 3, + "d": 3 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 2, + "d": 3 + }, + "mne/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 3, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 9, + "d": 6 + }, + "mne/channels/channels.py": { + "a": 47, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 9, + "d": 12 + }, + "mne/channels/tests/test_layout.py": { + "a": 6, + "d": 6 + }, + "mne/commands/tests/test_commands.py": { + "a": 20, + "d": 19 + }, + "mne/cov.py": { + "a": 2, + "d": 3 + }, + "mne/decoding/tests/test_csp.py": { + "a": 7, + "d": 5 + }, + "mne/decoding/tests/test_ems.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 18, + "d": 17 + }, + "mne/epochs.py": { + "a": 46, + "d": 22 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 3, + "d": 2 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 4, + "d": 4 + }, + "mne/io/array/tests/test_array.py": { + "a": 3, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 6, + "d": 6 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 11, + "d": 12 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 14, + "d": 23 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/raw.py": { + "a": 25, + "d": 21 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 184, + "d": 143 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 11, + "d": 14 + }, + "mne/io/proj.py": { + "a": 4, + "d": 3 + }, + "mne/io/reference.py": { + "a": 11, + "d": 8 + }, + "mne/io/tests/test_compensator.py": { + "a": 15, + "d": 9 + }, + "mne/io/tests/test_meas_info.py": { + "a": 17, + "d": 20 + }, + "mne/io/tests/test_pick.py": { + "a": 8, + "d": 5 + }, + "mne/io/tests/test_proc_history.py": { + "a": 7, + "d": 8 + }, + "mne/io/tests/test_raw.py": { + "a": 5, + "d": 5 + }, + "mne/io/tests/test_reference.py": { + "a": 40, + "d": 30 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 17, + "d": 15 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 11, + "d": 12 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 7, + "d": 5 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 36, + "d": 35 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 84, + "d": 79 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 7, + "d": 6 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 14, + "d": 9 + }, + "mne/proj.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/epochs.py": { + "a": 4, + "d": 3 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 14, + "d": 10 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/tests/test_raw.py": { + "a": 14, + "d": 10 + }, + "mne/stats/tests/test_regression.py": { + "a": 7, + "d": 8 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 21, + "d": 15 + }, + "mne/tests/test_cov.py": { + "a": 37, + "d": 31 + }, + "mne/tests/test_dipole.py": { + "a": 16, + "d": 14 + }, + "mne/tests/test_epochs.py": { + "a": 260, + "d": 245 + }, + "mne/tests/test_event.py": { + "a": 25, + "d": 20 + }, + "mne/tests/test_evoked.py": { + "a": 23, + "d": 22 + }, + "mne/tests/test_filter.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_proj.py": { + "a": 19, + "d": 18 + }, + "mne/tests/test_report.py": { + "a": 11, + "d": 15 + }, + "mne/tests/test_selection.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_surface.py": { + "a": 14, + "d": 18 + }, + "mne/tests/test_utils.py": { + "a": 4, + "d": 2 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 3, + "d": 5 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 9, + "d": 9 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 8, + "d": 10 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 10, + "d": 16 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 15, + "d": 15 + }, + "mne/utils.py": { + "a": 6, + "d": 6 + }, + "mne/viz/_3d.py": { + "a": 11, + "d": 9 + }, + "mne/viz/misc.py": { + "a": 4, + "d": 1 + }, + "mne/viz/tests/test_decoding.py": { + "a": 5, + "d": 3 + }, + "mne/viz/tests/test_epochs.py": { + "a": 13, + "d": 9 + }, + "mne/viz/tests/test_evoked.py": { + "a": 13, + "d": 8 + }, + "mne/viz/tests/test_ica.py": { + "a": 17, + "d": 18 + }, + "mne/viz/tests/test_misc.py": { + "a": 11, + "d": 14 + }, + "mne/viz/tests/test_raw.py": { + "a": 5, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 16, + "d": 13 + }, + "mne/viz/tests/test_topomap.py": { + "a": 6, + "d": 7 + }, + "mne/viz/tests/test_utils.py": { + "a": 4, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 12 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_maxwell_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_artifacts_correction_ssp.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_compute_covariance.py": { + "a": 4, + "d": 3 + }, + "tutorials/plot_eeg_erp.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 4, + "d": 3 + }, + "tutorials/plot_modifying_data_inplace.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_epochs.py": { + "a": 4, + "d": 3 + }, + "tutorials/plot_object_raw.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_visualize_epochs.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_visualize_raw.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3546.json b/mne-python/source/doc/sphinxext/prs/3546.json new file mode 100644 index 0000000000000000000000000000000000000000..6cd50721650fd96ade232f14b92508db9a3dfa2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3546.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a28f47bf61df9cb7908a511db88de575c99da8c9", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 19, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3549.json b/mne-python/source/doc/sphinxext/prs/3549.json new file mode 100644 index 0000000000000000000000000000000000000000..7d3143b24d4f80d4fc8e248dd89b315b58eecd4c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3549.json @@ -0,0 +1,911 @@ +{ + "merge_commit_sha": "24ca938c616b3ef5b4f57a9ffbcf9f35a9dfdf56", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 1 + }, + "Makefile": { + "a": 6, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/annotations.py": { + "a": 4, + "d": 4 + }, + "mne/baseline.py": { + "a": 5, + "d": 6 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 4 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 4 + }, + "mne/beamformer/_rap_music.py": { + "a": 5, + "d": 12 + }, + "mne/bem.py": { + "a": 48, + "d": 48 + }, + "mne/channels/__init__.py": { + "a": 3, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 24, + "d": 26 + }, + "mne/channels/data/neighbors/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 3, + "d": 5 + }, + "mne/channels/layout.py": { + "a": 18, + "d": 15 + }, + "mne/channels/montage.py": { + "a": 13, + "d": 11 + }, + "mne/channels/tests/test_montage.py": { + "a": 5, + "d": 5 + }, + "mne/chpi.py": { + "a": 13, + "d": 13 + }, + "mne/commands/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 7, + "d": 2 + }, + "mne/commands/mne_compare_fiff.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_flash_bem.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 6, + "d": 2 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_maxfilter.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_report.py": { + "a": 3, + "d": 1 + }, + "mne/commands/mne_show_fiff.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_show_info.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_surf2bem.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 4, + "d": 3 + }, + "mne/commands/utils.py": { + "a": 2, + "d": 4 + }, + "mne/connectivity/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/connectivity/effective.py": { + "a": 1, + "d": 2 + }, + "mne/connectivity/spectral.py": { + "a": 46, + "d": 37 + }, + "mne/connectivity/utils.py": { + "a": 1, + "d": 2 + }, + "mne/coreg.py": { + "a": 29, + "d": 25 + }, + "mne/cov.py": { + "a": 13, + "d": 13 + }, + "mne/cuda.py": { + "a": 10, + "d": 11 + }, + "mne/data/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/_fake/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/_fake/_fake.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 3, + "d": 4 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 3, + "d": 4 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 3, + "d": 4 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 3, + "d": 4 + }, + "mne/datasets/eegbci/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/megsim/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/megsim/megsim.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/megsim/urls.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/misc/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/misc/_misc.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/multimodal/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/sample/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/sample/sample.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/somato/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/somato/somato.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/spm_face/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/testing/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/testing/_testing.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 10, + "d": 11 + }, + "mne/decoding/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 25, + "d": 25 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/ems.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/mixin.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/search_light.py": { + "a": 36, + "d": 33 + }, + "mne/decoding/time_frequency.py": { + "a": 4, + "d": 5 + }, + "mne/decoding/time_gen.py": { + "a": 40, + "d": 39 + }, + "mne/decoding/transformer.py": { + "a": 27, + "d": 23 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 33, + "d": 29 + }, + "mne/epochs.py": { + "a": 78, + "d": 69 + }, + "mne/event.py": { + "a": 39, + "d": 40 + }, + "mne/evoked.py": { + "a": 34, + "d": 33 + }, + "mne/filter.py": { + "a": 21, + "d": 21 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + }, + "mne/forward/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/forward/_compute_forward.py": { + "a": 3, + "d": 6 + }, + "mne/forward/_field_interpolation.py": { + "a": 7, + "d": 5 + }, + "mne/forward/_lead_dots.py": { + "a": 9, + "d": 9 + }, + "mne/forward/_make_forward.py": { + "a": 13, + "d": 15 + }, + "mne/forward/forward.py": { + "a": 29, + "d": 38 + }, + "mne/gui/__init__.py": { + "a": 4, + "d": 4 + }, + "mne/gui/_backend.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 31, + "d": 23 + }, + "mne/gui/_fiducials_gui.py": { + "a": 12, + "d": 8 + }, + "mne/gui/_file_traits.py": { + "a": 21, + "d": 15 + }, + "mne/gui/_help.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 19, + "d": 18 + }, + "mne/gui/_marker_gui.py": { + "a": 18, + "d": 11 + }, + "mne/gui/_viewer.py": { + "a": 14, + "d": 11 + }, + "mne/inverse_sparse/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 9, + "d": 13 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 3 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 27, + "d": 25 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 4, + "d": 3 + }, + "mne/io/base.py": { + "a": 58, + "d": 54 + }, + "mne/io/brainvision/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 13, + "d": 10 + }, + "mne/io/bti/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 34, + "d": 41 + }, + "mne/io/bti/read.py": { + "a": 18, + "d": 18 + }, + "mne/io/cnt/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 5, + "d": 5 + }, + "mne/io/compensator.py": { + "a": 4, + "d": 7 + }, + "mne/io/constants.py": { + "a": 5, + "d": 6 + }, + "mne/io/ctf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 7, + "d": 7 + }, + "mne/io/ctf/eeg.py": { + "a": 3, + "d": 5 + }, + "mne/io/ctf/hc.py": { + "a": 3, + "d": 4 + }, + "mne/io/ctf/info.py": { + "a": 13, + "d": 14 + }, + "mne/io/ctf/res4.py": { + "a": 12, + "d": 13 + }, + "mne/io/ctf/trans.py": { + "a": 5, + "d": 5 + }, + "mne/io/ctf_comp.py": { + "a": 4, + "d": 4 + }, + "mne/io/diff.py": { + "a": 3, + "d": 2 + }, + "mne/io/edf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 10, + "d": 14 + }, + "mne/io/eeglab/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 13, + "d": 12 + }, + "mne/io/egi/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 9, + "d": 9 + }, + "mne/io/fiff/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 9, + "d": 8 + }, + "mne/io/kit/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 3, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 18, + "d": 16 + }, + "mne/io/matrix.py": { + "a": 3, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 20, + "d": 21 + }, + "mne/io/nicolet/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 4, + "d": 3 + }, + "mne/io/open.py": { + "a": 5, + "d": 5 + }, + "mne/io/pick.py": { + "a": 20, + "d": 20 + }, + "mne/io/proc_history.py": { + "a": 6, + "d": 6 + }, + "mne/io/proj.py": { + "a": 22, + "d": 20 + }, + "mne/io/tag.py": { + "a": 26, + "d": 28 + }, + "mne/io/tree.py": { + "a": 3, + "d": 5 + }, + "mne/io/utils.py": { + "a": 7, + "d": 8 + }, + "mne/io/write.py": { + "a": 27, + "d": 26 + }, + "mne/label.py": { + "a": 39, + "d": 43 + }, + "mne/minimum_norm/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 25, + "d": 28 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 5, + "d": 5 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 12, + "d": 13 + }, + "mne/misc.py": { + "a": 3, + "d": 5 + }, + "mne/parallel.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/bads.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ctps_.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/ecg.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/eog.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 49, + "d": 55 + }, + "mne/preprocessing/maxfilter.py": { + "a": 3, + "d": 28 + }, + "mne/preprocessing/maxwell.py": { + "a": 39, + "d": 40 + }, + "mne/preprocessing/peak_finder.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ssp.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/stim.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 2, + "d": 3 + }, + "mne/proj.py": { + "a": 5, + "d": 5 + }, + "mne/realtime/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/client.py": { + "a": 21, + "d": 21 + }, + "mne/realtime/epochs.py": { + "a": 10, + "d": 10 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 12, + "d": 16 + }, + "mne/realtime/mockclient.py": { + "a": 8, + "d": 8 + }, + "mne/realtime/stim_server_client.py": { + "a": 15, + "d": 20 + }, + "mne/report.py": { + "a": 43, + "d": 88 + }, + "mne/selection.py": { + "a": 2, + "d": 3 + }, + "mne/simulation/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/simulation/evoked.py": { + "a": 4, + "d": 4 + }, + "mne/simulation/metrics.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/raw.py": { + "a": 5, + "d": 5 + }, + "mne/simulation/source.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 93, + "d": 106 + }, + "mne/source_space.py": { + "a": 43, + "d": 47 + }, + "mne/stats/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 35, + "d": 32 + }, + "mne/stats/multi_comp.py": { + "a": 3, + "d": 4 + }, + "mne/stats/parametric.py": { + "a": 8, + "d": 9 + }, + "mne/stats/permutations.py": { + "a": 3, + "d": 5 + }, + "mne/stats/regression.py": { + "a": 10, + "d": 14 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 31, + "d": 32 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/_stockwell.py": { + "a": 6, + "d": 6 + }, + "mne/time_frequency/ar.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/csd.py": { + "a": 11, + "d": 10 + }, + "mne/time_frequency/multitaper.py": { + "a": 14, + "d": 17 + }, + "mne/time_frequency/psd.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/stft.py": { + "a": 4, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 45, + "d": 38 + }, + "mne/transforms.py": { + "a": 36, + "d": 32 + }, + "mne/utils.py": { + "a": 114, + "d": 115 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 11 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/viz/circle.py": { + "a": 5, + "d": 4 + }, + "mne/viz/decoding.py": { + "a": 5, + "d": 7 + }, + "mne/viz/epochs.py": { + "a": 29, + "d": 30 + }, + "mne/viz/evoked.py": { + "a": 29, + "d": 32 + }, + "mne/viz/ica.py": { + "a": 17, + "d": 17 + }, + "mne/viz/misc.py": { + "a": 8, + "d": 9 + }, + "mne/viz/montage.py": { + "a": 3, + "d": 4 + }, + "mne/viz/raw.py": { + "a": 13, + "d": 14 + }, + "mne/viz/tests/test_montage.py": { + "a": 5, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 15, + "d": 17 + }, + "mne/viz/topomap.py": { + "a": 25, + "d": 28 + }, + "mne/viz/utils.py": { + "a": 32, + "d": 33 + }, + "setup.cfg": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3551.json b/mne-python/source/doc/sphinxext/prs/3551.json new file mode 100644 index 0000000000000000000000000000000000000000..dbae1c1fadcc03d79c8f114dfd56da2b5207dd1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3551.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8aa4ad7c4eac0e0a87bc09f71a9be0aa59e6adaa", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 24, + "d": 30 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3553.json b/mne-python/source/doc/sphinxext/prs/3553.json new file mode 100644 index 0000000000000000000000000000000000000000..1bc0c838c2ccd106b76c65df937449ca910aa946 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3553.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8ea72065261f5cc03445e66980f782e9137b85a1", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 0 + }, + "tutorials/plot_background_filtering.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3557.json b/mne-python/source/doc/sphinxext/prs/3557.json new file mode 100644 index 0000000000000000000000000000000000000000..f2fe1b0eb35dd04f4bb1caf6bfb84ba97903f04e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3557.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c4174f7f8ac085d6b14b4d44c75075256dae7f57", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 13, + "d": 8 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3559.json b/mne-python/source/doc/sphinxext/prs/3559.json new file mode 100644 index 0000000000000000000000000000000000000000..5c83846492b76037ff682bcba1251d52cc072b7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3559.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7845d39a3cd642bdab6a162174697069d1c9056e", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/356.json b/mne-python/source/doc/sphinxext/prs/356.json new file mode 100644 index 0000000000000000000000000000000000000000..c6dbe01fe0c7806d09615feed4a39727129fc964 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/356.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0ae991fe24bd08e785d380f1b17c5b0513a28b57", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fiff/open.py": { + "a": 5, + "d": 2 + }, + "mne/fiff/tag.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3560.json b/mne-python/source/doc/sphinxext/prs/3560.json new file mode 100644 index 0000000000000000000000000000000000000000..41151214e82bebef26da164e7a5935f5b44f30ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3560.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "29645cd04cf795c077d7d5dd60737c87208155ee", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/event.py": { + "a": 3, + "d": 3 + }, + "mne/io/constants.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3561.json b/mne-python/source/doc/sphinxext/prs/3561.json new file mode 100644 index 0000000000000000000000000000000000000000..86fa3707ac8f5b5cae7027979a112f28a60b862e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3561.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3df939c6eae7e906f298db6715669a8084865d49", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3564.json b/mne-python/source/doc/sphinxext/prs/3564.json new file mode 100644 index 0000000000000000000000000000000000000000..8ab4bb7844ee7fde67d0ce090fba7d4e4f7eb1a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3564.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "90d1b1f2fc6b772b825f76a047b34ec511b47f55", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cuda.py": { + "a": 5, + "d": 4 + }, + "mne/utils.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3568.json b/mne-python/source/doc/sphinxext/prs/3568.json new file mode 100644 index 0000000000000000000000000000000000000000..25ea691baced1bacd2570bfc22e65fe930a4446c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3568.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7cd5d0e9cbf2b0472c8f0ba7b14ca97e6f3c874b", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/annotations.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/357.json b/mne-python/source/doc/sphinxext/prs/357.json new file mode 100644 index 0000000000000000000000000000000000000000..c50df690191b770f1f6d960a456dc2045f1ae3b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/357.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "876a3e9cb795f3eaa49df29fc1bdd94eb29ddcf9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/evoked.py": { + "a": 46, + "d": 33 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3574.json b/mne-python/source/doc/sphinxext/prs/3574.json new file mode 100644 index 0000000000000000000000000000000000000000..d09c15847b7dc73a82646c134b1ce373751e2f01 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3574.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "558a3a0e4e5bf6265e9c6c4904a8404ed635bb5f", + "authors": [ + { + "n": "Andreas Højlund", + "e": "linahn@clin.au.dk" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 6, + "d": 7 + }, + "mne/viz/tests/test_ica.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3575.json b/mne-python/source/doc/sphinxext/prs/3575.json new file mode 100644 index 0000000000000000000000000000000000000000..c975e80e66ede5c00f095b1c3ac7e44fcc5b5e83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3575.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b906cf79f045729615deaeb921345536efd1dd55", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/epochs.py": { + "a": 27, + "d": 23 + }, + "mne/evoked.py": { + "a": 14, + "d": 10 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3576.json b/mne-python/source/doc/sphinxext/prs/3576.json new file mode 100644 index 0000000000000000000000000000000000000000..78fb872d6b781a4ec272cb67573443f98004975e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3576.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "fc56f61f315f8f5ec4467ddb89573e15fb064cd8", + "authors": [ + { + "n": "Phillip Alday", + "e": null + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 60, + "d": 5 + }, + "mne/io/brainvision/tests/data/test_highpass_hz.vhdr": { + "a": 103, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_lowpass_s.vhdr": { + "a": 103, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_mixed_highpass.vhdr": { + "a": 103, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_mixed_highpass_hz.vhdr": { + "a": 103, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_mixed_lowpass.vhdr": { + "a": 103, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_mixed_lowpass_s.vhdr": { + "a": 103, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_partially_disabled_hw_filter.vhdr": { + "a": 103, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 158, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/358.json b/mne-python/source/doc/sphinxext/prs/358.json new file mode 100644 index 0000000000000000000000000000000000000000..a16a27e165f8bf8cbf85bf10da7bf38a83f65715 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/358.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "10c8ff7c5feb341c363b2acd8d1f261a15d70cd9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxfilter.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3580.json b/mne-python/source/doc/sphinxext/prs/3580.json new file mode 100644 index 0000000000000000000000000000000000000000..a15c39fdd5e2aaedf9c7d6ef6768f9e58ad7dee6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3580.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f350bd44754030f3e02afd63ad94197b4bd77299", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3581.json b/mne-python/source/doc/sphinxext/prs/3581.json new file mode 100644 index 0000000000000000000000000000000000000000..b7e505dc1640108dbb5670ed73cfe74e16f65ad7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3581.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fa0cdb03f72ea29ceaa8f5ecec058f3d5f2fdfa4", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3586.json b/mne-python/source/doc/sphinxext/prs/3586.json new file mode 100644 index 0000000000000000000000000000000000000000..624d92f2101a4927164264d4fa684eee57f50ee7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3586.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9e5cd907229a86efdd35bb9757eef8ebe9ec639a", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 45, + "d": 13 + }, + "mne/decoding/tests/test_csp.py": { + "a": 29, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3587.json b/mne-python/source/doc/sphinxext/prs/3587.json new file mode 100644 index 0000000000000000000000000000000000000000..37250ae3ac772256a90c93e517b72769a4de90f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3587.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8ade1fffea0bd7d252fae5d4d2f60207e95c6f69", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_time_gen.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 17, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3589.json b/mne-python/source/doc/sphinxext/prs/3589.json new file mode 100644 index 0000000000000000000000000000000000000000..6a2dfb76ce29e5289012f4a6c1b61764ffab4903 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3589.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "69345bf04f2dbdf9d4198c11251db9652016f7b0", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 4, + "d": 3 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3593.json b/mne-python/source/doc/sphinxext/prs/3593.json new file mode 100644 index 0000000000000000000000000000000000000000..b7d6e48287c6e0f8ede21404e89d3905380581d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3593.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f0fa05578b96d2cea83ecd811e1c71b03ec5267d", + "authors": [ + { + "n": "Phillip Alday", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 37, + "d": 22 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3594.json b/mne-python/source/doc/sphinxext/prs/3594.json new file mode 100644 index 0000000000000000000000000000000000000000..56d01f4ef93f878adc69ff7ccea5dffed0f7072e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3594.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d738cb996c3fa6edacf568e3a35c8f08d42131b3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 42, + "d": 15 + }, + "mne/io/base.py": { + "a": 18, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 4, + "d": 16 + }, + "mne/tests/test_evoked.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3595.json b/mne-python/source/doc/sphinxext/prs/3595.json new file mode 100644 index 0000000000000000000000000000000000000000..13053e66b1e8dd06cfa16218ff7922484cc84312 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3595.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "94a4dc230e78283f741d7c9925e1c2fccd99bfc6", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/index.rst": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3596.json b/mne-python/source/doc/sphinxext/prs/3596.json new file mode 100644 index 0000000000000000000000000000000000000000..07a86fdf34c73bf762b9e82051048d76cffed66e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3596.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e8f11200f18c789b4eddcada7094a5bf18218021", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 6, + "d": 5 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 31, + "d": 41 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/36.json b/mne-python/source/doc/sphinxext/prs/36.json new file mode 100644 index 0000000000000000000000000000000000000000..e96acadbeffa86395fdfbf275c2c3390ce1707bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/36.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fe27317f8b701fade51771ca5948888f3058bed2", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 61, + "d": 8 + }, + "mne/epochs.py": { + "a": 4, + "d": 12 + }, + "mne/fiff/evoked.py": { + "a": 2, + "d": 5 + }, + "mne/fiff/proj.py": { + "a": 52, + "d": 4 + }, + "mne/proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3600.json b/mne-python/source/doc/sphinxext/prs/3600.json new file mode 100644 index 0000000000000000000000000000000000000000..3e6dfc3b331b00ef4715f86f6206a35695c3c215 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3600.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "62b3bbd4a8cb717fdd544518f907931913167298", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 26, + "d": 8 + }, + "mne/channels/tests/test_channels.py": { + "a": 6, + "d": 1 + }, + "mne/defaults.py": { + "a": 15, + "d": 13 + }, + "mne/epochs.py": { + "a": 5, + "d": 4 + }, + "mne/evoked.py": { + "a": 10, + "d": 8 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 1 + }, + "mne/io/constants.py": { + "a": 29, + "d": 24 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 5, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 1 + }, + "mne/io/pick.py": { + "a": 33, + "d": 8 + }, + "mne/io/tests/test_pick.py": { + "a": 13, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 11, + "d": 7 + }, + "mne/viz/epochs.py": { + "a": 10, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 6, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3602.json b/mne-python/source/doc/sphinxext/prs/3602.json new file mode 100644 index 0000000000000000000000000000000000000000..ffca8e08404da302e5b374e5e3b8b753b1ca1c85 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3602.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e0938066a381720f54656ad6eadb5b754954c49", + "authors": [ + { + "n": "Keith Doelling", + "e": "keith.doelling@gmail.com" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3603.json b/mne-python/source/doc/sphinxext/prs/3603.json new file mode 100644 index 0000000000000000000000000000000000000000..2da833d8cc13ebe05feed96d72f07119b8471c0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3603.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1d6bade5f7b881b9e0c1acd128f65ce9add5fee0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 43, + "d": 32 + }, + "mne/tests/test_epochs.py": { + "a": 28, + "d": 2 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3606.json b/mne-python/source/doc/sphinxext/prs/3606.json new file mode 100644 index 0000000000000000000000000000000000000000..8b8fb599c07bc9558dead16b12ed98122eb6c878 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3606.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ee585e818380436f6d6765dbeaad040dfa35181a", + "authors": [ + { + "n": "Johannes Niediek", + "e": null + } + ], + "changes": { + "mne/time_frequency/_stockwell.py": { + "a": 7, + "d": 3 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 28, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3610.json b/mne-python/source/doc/sphinxext/prs/3610.json new file mode 100644 index 0000000000000000000000000000000000000000..f01affff8a27b1e5eec5b09bfc5167cb7293eee3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3610.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e9dd187de6d4ef7262f3c6a14d7c090ddbdb86ba", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/evoked.py": { + "a": 10, + "d": 8 + }, + "mne/io/fiff/raw.py": { + "a": 11, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3612.json b/mne-python/source/doc/sphinxext/prs/3612.json new file mode 100644 index 0000000000000000000000000000000000000000..f0f2cb81694c56b56aeaa6a4f93918895799b611 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3612.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8394c866b516ea7f1cb5885681381805bfe5bf69", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 0, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3613.json b/mne-python/source/doc/sphinxext/prs/3613.json new file mode 100644 index 0000000000000000000000000000000000000000..b936e95eb9909444eea3cef89d6a95ca017f9956 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3613.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "c44781dc96fba5aeb82437ae808eeea55d0ce428", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 18, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 4, + "d": 4 + }, + "examples/visualization/plot_warp_surfaces.py": { + "a": 83, + "d": 0 + }, + "mne/bem.py": { + "a": 65, + "d": 31 + }, + "mne/channels/layout.py": { + "a": 3, + "d": 6 + }, + "mne/channels/montage.py": { + "a": 18, + "d": 39 + }, + "mne/channels/tests/test_montage.py": { + "a": 13, + "d": 1 + }, + "mne/data/fsaverage/fsaverage-fiducials.fif": { + "a": 0, + "d": 0 + }, + "mne/data/fsaverage/fsaverage-head.fif": { + "a": 0, + "d": 0 + }, + "mne/data/fsaverage/fsaverage-inner_skull-bem.fif": { + "a": 0, + "d": 0 + }, + "mne/data/fsaverage/fsaverage-trans.fif": { + "a": 0, + "d": 0 + }, + "mne/filter.py": { + "a": 8, + "d": 8 + }, + "mne/fixes.py": { + "a": 64, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 20, + "d": 203 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 5, + "d": 28 + }, + "mne/selection.py": { + "a": 6, + "d": 4 + }, + "mne/source_space.py": { + "a": 3, + "d": 3 + }, + "mne/surface.py": { + "a": 44, + "d": 23 + }, + "mne/tests/common.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_fixes.py": { + "a": 17, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 120, + "d": 39 + }, + "mne/transforms.py": { + "a": 428, + "d": 27 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 3 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3614.json b/mne-python/source/doc/sphinxext/prs/3614.json new file mode 100644 index 0000000000000000000000000000000000000000..02a8c286ff0b552401ecf26b70cdef22c957cedc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3614.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b5a6bfc57199f7ecedf9ac11fbeb7674b7b6c46a", + "authors": [ + { + "n": "jmontoyam", + "e": "montoya.jair.m@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/infomax_.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3616.json b/mne-python/source/doc/sphinxext/prs/3616.json new file mode 100644 index 0000000000000000000000000000000000000000..8cd90e3ccc061df6eb28b95b610646d3b021ea1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3616.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b7771efabf3f2e22abd9963347de5e4a1b540bd7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 2 + }, + "mne/io/base.py": { + "a": 4, + "d": 7 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3617.json b/mne-python/source/doc/sphinxext/prs/3617.json new file mode 100644 index 0000000000000000000000000000000000000000..551a0d1d893d1abd56c81b747d92d29b8a131a02 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3617.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "a2b655f4dce5b848137932cfed504297c3b167cc", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 0, + "d": 3 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 17, + "d": 40 + }, + "examples/decoding/plot_decoding_xdawn_transformer.py": { + "a": 0, + "d": 76 + }, + "mne/decoding/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 10, + "d": 10 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 21, + "d": 21 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 11, + "d": 11 + }, + "mne/preprocessing/xdawn.py": { + "a": 4, + "d": 5 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3620.json b/mne-python/source/doc/sphinxext/prs/3620.json new file mode 100644 index 0000000000000000000000000000000000000000..6784302b8102b8589a15e1bddb821257b50e4691 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3620.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3b09ed062226bbe017243071f450e0254fc3a769", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/externals/FieldTrip.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3622.json b/mne-python/source/doc/sphinxext/prs/3622.json new file mode 100644 index 0000000000000000000000000000000000000000..6ee49fa66af65bd6eb7b63e95f7547b6639d13aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3622.json @@ -0,0 +1,559 @@ +{ + "merge_commit_sha": "0ad50cbb649122c5638ab5cdd6cf7fe9b0a6b702", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 12, + "d": 6 + }, + "doc/manual/io.rst": { + "a": 0, + "d": 8 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 3 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 2, + "d": 2 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_decoding_unsupervised_spatial_filter.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 7, + "d": 6 + }, + "examples/stats/plot_linear_regression_raw.py": { + "a": 4, + "d": 2 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 6, + "d": 9 + }, + "mne/channels/tests/test_channels.py": { + "a": 4, + "d": 4 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 4 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 13 + }, + "mne/decoding/tests/test_csp.py": { + "a": 6, + "d": 9 + }, + "mne/decoding/tests/test_ems.py": { + "a": 9, + "d": 7 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 5, + "d": 6 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 12, + "d": 53 + }, + "mne/decoding/transformer.py": { + "a": 3, + "d": 103 + }, + "mne/epochs.py": { + "a": 21, + "d": 42 + }, + "mne/event.py": { + "a": 8, + "d": 7 + }, + "mne/evoked.py": { + "a": 3, + "d": 57 + }, + "mne/filter.py": { + "a": 87, + "d": 119 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 26 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 2, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 3 + }, + "mne/io/base.py": { + "a": 65, + "d": 77 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 3, + "d": 3 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 3, + "d": 3 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/raw.py": { + "a": 8, + "d": 65 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 104, + "d": 160 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 3, + "d": 5 + }, + "mne/io/proj.py": { + "a": 1, + "d": 16 + }, + "mne/io/tests/test_compensator.py": { + "a": 5, + "d": 6 + }, + "mne/io/tests/test_meas_info.py": { + "a": 5, + "d": 5 + }, + "mne/io/tests/test_pick.py": { + "a": 4, + "d": 4 + }, + "mne/io/tests/test_raw.py": { + "a": 4, + "d": 4 + }, + "mne/io/tests/test_reference.py": { + "a": 18, + "d": 22 + }, + "mne/label.py": { + "a": 11, + "d": 21 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 4, + "d": 5 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 6, + "d": 6 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/stim.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 7, + "d": 10 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 15, + "d": 24 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 6, + "d": 11 + }, + "mne/proj.py": { + "a": 3, + "d": 4 + }, + "mne/realtime/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 10, + "d": 14 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 2 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 4, + "d": 8 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 3 + }, + "mne/stats/tests/test_regression.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 11, + "d": 17 + }, + "mne/tests/test_cov.py": { + "a": 17, + "d": 24 + }, + "mne/tests/test_dipole.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 184, + "d": 274 + }, + "mne/tests/test_event.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_evoked.py": { + "a": 3, + "d": 5 + }, + "mne/tests/test_filter.py": { + "a": 41, + "d": 56 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_proj.py": { + "a": 10, + "d": 11 + }, + "mne/tests/test_report.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_selection.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_utils.py": { + "a": 34, + "d": 46 + }, + "mne/time_frequency/__init__.py": { + "a": 3, + "d": 5 + }, + "mne/time_frequency/csd.py": { + "a": 0, + "d": 14 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 9, + "d": 9 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 7, + "d": 5 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 5, + "d": 3 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 24, + "d": 47 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 162 + }, + "mne/utils.py": { + "a": 1, + "d": 21 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 20 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_decoding.py": { + "a": 8, + "d": 9 + }, + "mne/viz/tests/test_epochs.py": { + "a": 10, + "d": 24 + }, + "mne/viz/tests/test_evoked.py": { + "a": 6, + "d": 19 + }, + "mne/viz/tests/test_ica.py": { + "a": 3, + "d": 5 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 4, + "d": 10 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 6 + }, + "mne/viz/tests/test_utils.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_maxwell_filtering.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_artifacts_correction_ssp.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_compute_covariance.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_eeg_erp.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_modifying_data_inplace.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_epochs.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_object_evoked.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_object_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 3, + "d": 4 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_epochs.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_visualize_raw.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3626.json b/mne-python/source/doc/sphinxext/prs/3626.json new file mode 100644 index 0000000000000000000000000000000000000000..3e62ae0d1883af6f6ea7141088689a31261de333 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3626.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2b0d9c990a3bf3af9fe96fc42565d4928e05a9c9", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 11, + "d": 1 + }, + "mne/decoding/time_gen.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3628.json b/mne-python/source/doc/sphinxext/prs/3628.json new file mode 100644 index 0000000000000000000000000000000000000000..703b8bcd8e12b74ab51e207cf3cd0e12243c4b1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3628.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "a9723e8215cdbf2721497516173c82f2ed64cf42", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 2 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 3, + "d": 4 + }, + "mne/decoding/transformer.py": { + "a": 8, + "d": 51 + }, + "mne/filter.py": { + "a": 326, + "d": 186 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 6 + }, + "mne/preprocessing/ecg.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/eog.py": { + "a": 7, + "d": 9 + }, + "mne/preprocessing/ica.py": { + "a": 8, + "d": 10 + }, + "mne/tests/test_filter.py": { + "a": 62, + "d": 63 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 280, + "d": 0 + }, + "mne/viz/tests/test_misc.py": { + "a": 30, + "d": 2 + }, + "tutorials/plot_background_filtering.py": { + "a": 76, + "d": 134 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 4, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/363.json b/mne-python/source/doc/sphinxext/prs/363.json new file mode 100644 index 0000000000000000000000000000000000000000..3eb983d8da79bfe342a0e5a242c121f3dde2114d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/363.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "32b04de7899d1d18b48b037c95967112b87860a5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 98, + "d": 20 + }, + "mne/source_estimate.py": { + "a": 0, + "d": 5 + }, + "mne/tests/test_label.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3630.json b/mne-python/source/doc/sphinxext/prs/3630.json new file mode 100644 index 0000000000000000000000000000000000000000..c09254c9df12fac95786ef8ba4c7d841559582cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3630.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e4ed71baf2b9e4175758e6d9939d7fe252b9d949", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3634.json b/mne-python/source/doc/sphinxext/prs/3634.json new file mode 100644 index 0000000000000000000000000000000000000000..ffd015b7204a47fbde56838b295eccd171a81c73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3634.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bcd57d65450b5f0271a221f786d1d42d27ec5f4c", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3637.json b/mne-python/source/doc/sphinxext/prs/3637.json new file mode 100644 index 0000000000000000000000000000000000000000..12234669aaab761803bbc39fcb2394e7a96bb1e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3637.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4b6a1744e8be9e8ff6e1e238953f5b6667062673", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "appveyor.yml": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/ar.py": { + "a": 33, + "d": 115 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 29, + "d": 14 + }, + "mne/utils.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3638.json b/mne-python/source/doc/sphinxext/prs/3638.json new file mode 100644 index 0000000000000000000000000000000000000000..45d63cfa0c6037df3c0dbf0106152e2d5d72c42d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3638.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "279f460a3bc27f7e1bcc75902e119b5c99358094", + "authors": [ + { + "n": "Annalisa Pascarella", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mixed_source_space_connectity.py": { + "a": 185, + "d": 0 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 142, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 42, + "d": 6 + }, + "mne/source_space.py": { + "a": 126, + "d": 21 + }, + "mne/tests/test_source_space.py": { + "a": 37, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3644.json b/mne-python/source/doc/sphinxext/prs/3644.json new file mode 100644 index 0000000000000000000000000000000000000000..c4ca50c4660a85bea6fb3bb267f1fade06928fbf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3644.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b45ac02756f4ce6644ab17a16ac0c77a6f4abb80", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 6, + "d": 4 + }, + "mne/gui/_fiducials_gui.py": { + "a": 11, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3646.json b/mne-python/source/doc/sphinxext/prs/3646.json new file mode 100644 index 0000000000000000000000000000000000000000..ae0b16184fb11993587030cb3a6e25249a74ebc8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3646.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f621a69c40950ac4f241331707468ddc87d313c1", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/realtime/fieldtrip_client.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3648.json b/mne-python/source/doc/sphinxext/prs/3648.json new file mode 100644 index 0000000000000000000000000000000000000000..904efc48575000a2128a01619989da3086d1736c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3648.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "85c42d12f4a99227673846601c343e393203ba79", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 11, + "d": 23 + }, + "mne/gui/_fiducials_gui.py": { + "a": 10, + "d": 19 + }, + "mne/gui/_file_traits.py": { + "a": 6, + "d": 15 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 11, + "d": 21 + }, + "mne/gui/_marker_gui.py": { + "a": 9, + "d": 18 + }, + "mne/gui/_viewer.py": { + "a": 10, + "d": 19 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 4, + "d": 4 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 2, + "d": 2 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 6, + "d": 6 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 1, + "d": 3 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 20, + "d": 3 + }, + "mne/utils.py": { + "a": 0, + "d": 7 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3649.json b/mne-python/source/doc/sphinxext/prs/3649.json new file mode 100644 index 0000000000000000000000000000000000000000..57fadbfb57819ee61c91f951e2631421926dc705 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3649.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "570eab27f3871389cc10ef529eb10c667bb07b51", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3650.json b/mne-python/source/doc/sphinxext/prs/3650.json new file mode 100644 index 0000000000000000000000000000000000000000..26cb5fb09dfa78a788ce8882d9dc87e3d8fd3cb6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3650.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6c215a52cb436a30f0f519b0e9c1ed504c659c68", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "circle.yml": { + "a": 4, + "d": 0 + }, + "examples/datasets/plot_megsim_data_single_trial.py": { + "a": 2, + "d": 2 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 4, + "d": 5 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 0 + }, + "examples/realtime/ftclient_rt_average.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3653.json b/mne-python/source/doc/sphinxext/prs/3653.json new file mode 100644 index 0000000000000000000000000000000000000000..96c8671923b4d8aefc4a83c2d7eb1786b785a211 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3653.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "55c587d043aae896c233b4a21cb413ab88b07bc8", + "authors": [ + { + "n": "Sheraz Khan", + "e": "sheraz.khan@pfizer.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3655.json b/mne-python/source/doc/sphinxext/prs/3655.json new file mode 100644 index 0000000000000000000000000000000000000000..2448fdf53a969970d33b25b2ab22cc0fececcb59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3655.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0dd4f75194fbd65a84662e6043b437426fa4ed6c", + "authors": [ + { + "n": "Yaroslav Halchenko", + "e": null + } + ], + "changes": { + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 2, + "d": 0 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 2, + "d": 0 + }, + "mne/utils.py": { + "a": 3, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3656.json b/mne-python/source/doc/sphinxext/prs/3656.json new file mode 100644 index 0000000000000000000000000000000000000000..e70fe14b8df9843e36aa380be536e0ba6b689f5e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3656.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c22b9ae75893723a875579862bedbdf80110da83", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3659.json b/mne-python/source/doc/sphinxext/prs/3659.json new file mode 100644 index 0000000000000000000000000000000000000000..0a10b018c0ceb86b73b52591826d931345e26b8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3659.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "65adad73899a68213a49f9b991ff2a48fca02a9f", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3660.json b/mne-python/source/doc/sphinxext/prs/3660.json new file mode 100644 index 0000000000000000000000000000000000000000..d7b55a2fa18058c2a917c8363227fa650fc23517 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3660.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fcad5f6c42b6d733cef5861b7d9281109e1cd5d4", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3661.json b/mne-python/source/doc/sphinxext/prs/3661.json new file mode 100644 index 0000000000000000000000000000000000000000..f1867003e370ce340034f460add56b9b5fbeeef6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3661.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2fa35d453670d759df3ff296c1f5c012f3f8a785", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3662.json b/mne-python/source/doc/sphinxext/prs/3662.json new file mode 100644 index 0000000000000000000000000000000000000000..73084f5710cafdaed27e9a2f0be48a04aee18c07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3662.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ae1b85553a183b6a15e2e26188ad12bccdccacf1", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "tutorials/plot_creating_data_structures.py": { + "a": 15, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/367.json b/mne-python/source/doc/sphinxext/prs/367.json new file mode 100644 index 0000000000000000000000000000000000000000..e7321291dd6b2c29b42d3ea110ec7209fb263c92 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/367.json @@ -0,0 +1,315 @@ +{ + "merge_commit_sha": "0f2c4dced889807eab11c7ccf3afa92d2cf58ebb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 7, + "d": 7 + }, + "doc/source/whats_new.rst": { + "a": 7, + "d": 0 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 3, + "d": 3 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 4, + "d": 4 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 3, + "d": 4 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 3, + "d": 3 + }, + "examples/export/plot_epochs_as_data_frame.py": { + "a": 3, + "d": 2 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 2, + "d": 2 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 2, + "d": 2 + }, + "examples/export/plot_raw_to_nitime.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 4, + "d": 2 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/plot_define_target_events.py": { + "a": 2, + "d": 2 + }, + "examples/plot_estimate_covariance_matrix_baseline.py": { + "a": 6, + "d": 6 + }, + "examples/plot_estimate_covariance_matrix_raw.py": { + "a": 2, + "d": 2 + }, + "examples/plot_evoked_whitening.py": { + "a": 2, + "d": 2 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 2, + "d": 2 + }, + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 2, + "d": 2 + }, + "examples/plot_read_and_write_raw_data.py": { + "a": 3, + "d": 4 + }, + "examples/plot_read_epochs.py": { + "a": 2, + "d": 2 + }, + "examples/plot_read_evoked.py": { + "a": 3, + "d": 2 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topo_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_ecg_artifacts_from_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_eog_artifacts_from_ica.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 2, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 6, + "d": 6 + }, + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 3, + "d": 2 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 5, + "d": 5 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_compute_source_psd_epochs.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_tfr_topography.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 14, + "d": 13 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 3, + "d": 4 + }, + "mne/cov.py": { + "a": 21, + "d": 24 + }, + "mne/epochs.py": { + "a": 12, + "d": 10 + }, + "mne/event.py": { + "a": 1, + "d": 2 + }, + "mne/fiff/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/pick.py": { + "a": 50, + "d": 40 + }, + "mne/fiff/proj.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 9, + "d": 14 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/tests/test_raw.py": { + "a": 9, + "d": 10 + }, + "mne/layouts/layout.py": { + "a": 4, + "d": 5 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/ecg.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 17, + "d": 18 + }, + "mne/preprocessing/ssp.py": { + "a": 26, + "d": 17 + }, + "mne/preprocessing/stim.py": { + "a": 11, + "d": 11 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 4 + }, + "mne/proj.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_cov.py": { + "a": 6, + "d": 8 + }, + "mne/tests/test_epochs.py": { + "a": 17, + "d": 7 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 5, + "d": 5 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 4, + "d": 4 + }, + "mne/viz.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3670.json b/mne-python/source/doc/sphinxext/prs/3670.json new file mode 100644 index 0000000000000000000000000000000000000000..79c0670910c07c17c851c3035f9946b44b40f9bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3670.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "334a3cdd5bedef2ad6e789078b401f683adf3a0f", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/chpi.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3675.json b/mne-python/source/doc/sphinxext/prs/3675.json new file mode 100644 index 0000000000000000000000000000000000000000..f97063fbdf4d38db69f709e021fb0b1c826e8e48 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3675.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6849756618335bb52bfb950050d9d1805528806f", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 18, + "d": 1 + }, + "mne/utils.py": { + "a": 18, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3677.json b/mne-python/source/doc/sphinxext/prs/3677.json new file mode 100644 index 0000000000000000000000000000000000000000..8df27d0b76ab18f462038507cec3bacfed4e2967 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3677.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "dbf108ba9cf563fdd9def67b07447998840f8f46", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/mne_logo.png": { + "a": 0, + "d": 0 + }, + "doc/_static/mne_logo_small.png": { + "a": 0, + "d": 0 + }, + "doc/_static/style.css": { + "a": 43, + "d": 7 + }, + "doc/_templates/layout.html": { + "a": 2, + "d": 2 + }, + "doc/cite.rst": { + "a": 0, + "d": 17 + }, + "doc/conf.py": { + "a": 84, + "d": 19 + }, + "doc/faq.rst": { + "a": 48, + "d": 0 + }, + "doc/getting_started.rst": { + "a": 91, + "d": 73 + }, + "doc/index.rst": { + "a": 119, + "d": 148 + }, + "doc/manual/appendix/c_release_notes.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/index.rst": { + "a": 37, + "d": 50 + }, + "doc/mne_cpp.rst": { + "a": 1, + "d": 3 + }, + "doc/tutorials.rst": { + "a": 0, + "d": 19 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 4, + "d": 4 + }, + "logo/generate_mne_logos.py": { + "a": 12, + "d": 10 + }, + "tutorials/plot_background_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_stats_cluster_methods.py": { + "a": 17, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3685.json b/mne-python/source/doc/sphinxext/prs/3685.json new file mode 100644 index 0000000000000000000000000000000000000000..f44de9b2f84bca6613aab1318ecaf36ab4fc565d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3685.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "65a4eb0407985c3320ed6efa058f4d97a324131c", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 3 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3687.json b/mne-python/source/doc/sphinxext/prs/3687.json new file mode 100644 index 0000000000000000000000000000000000000000..19f6b267ececf99aea371a61c658788ee5ac577d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3687.json @@ -0,0 +1,387 @@ +{ + "merge_commit_sha": "11047bc0ade8216ac10a15dfe0766d62c356c1e1", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/tutorials.rst": { + "a": 1, + "d": 0 + }, + "mne/baseline.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 10, + "d": 5 + }, + "mne/beamformer/_lcmv.py": { + "a": 12, + "d": 6 + }, + "mne/beamformer/_rap_music.py": { + "a": 2, + "d": 1 + }, + "mne/bem.py": { + "a": 16, + "d": 8 + }, + "mne/channels/channels.py": { + "a": 5, + "d": 2 + }, + "mne/channels/interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/chpi.py": { + "a": 4, + "d": 2 + }, + "mne/connectivity/effective.py": { + "a": 2, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 1 + }, + "mne/cov.py": { + "a": 15, + "d": 8 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/megsim/megsim.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ems.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/time_frequency.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 8, + "d": 5 + }, + "mne/dipole.py": { + "a": 12, + "d": 5 + }, + "mne/epochs.py": { + "a": 30, + "d": 20 + }, + "mne/event.py": { + "a": 2, + "d": 1 + }, + "mne/evoked.py": { + "a": 9, + "d": 5 + }, + "mne/filter.py": { + "a": 21, + "d": 12 + }, + "mne/forward/_compute_forward.py": { + "a": 4, + "d": 2 + }, + "mne/forward/_field_interpolation.py": { + "a": 4, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 10, + "d": 8 + }, + "mne/forward/forward.py": { + "a": 14, + "d": 7 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 4, + "d": 2 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 4, + "d": 2 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 8, + "d": 4 + }, + "mne/io/array/array.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 26, + "d": 14 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 4, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 4, + "d": 2 + }, + "mne/io/ctf/ctf.py": { + "a": 4, + "d": 2 + }, + "mne/io/ctf_comp.py": { + "a": 2, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 4, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 8, + "d": 4 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 4, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 8, + "d": 4 + }, + "mne/io/matrix.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 4 + }, + "mne/io/nicolet/nicolet.py": { + "a": 4, + "d": 2 + }, + "mne/io/open.py": { + "a": 4, + "d": 2 + }, + "mne/io/pick.py": { + "a": 2, + "d": 1 + }, + "mne/io/proj.py": { + "a": 13, + "d": 6 + }, + "mne/label.py": { + "a": 14, + "d": 7 + }, + "mne/minimum_norm/inverse.py": { + "a": 14, + "d": 8 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 4, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 8, + "d": 4 + }, + "mne/parallel.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/eog.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 22, + "d": 13 + }, + "mne/preprocessing/infomax_.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/peak_finder.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 6, + "d": 3 + }, + "mne/proj.py": { + "a": 8, + "d": 4 + }, + "mne/realtime/client.py": { + "a": 2, + "d": 5 + }, + "mne/realtime/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 2, + "d": 1 + }, + "mne/realtime/mockclient.py": { + "a": 2, + "d": 1 + }, + "mne/realtime/stim_server_client.py": { + "a": 17, + "d": 6 + }, + "mne/report.py": { + "a": 5, + "d": 2 + }, + "mne/selection.py": { + "a": 2, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 52, + "d": 26 + }, + "mne/source_space.py": { + "a": 23, + "d": 11 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 4 + }, + "mne/stats/permutations.py": { + "a": 2, + "d": 1 + }, + "mne/surface.py": { + "a": 12, + "d": 6 + }, + "mne/time_frequency/_stockwell.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 4, + "d": 2 + }, + "mne/time_frequency/stft.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 12, + "d": 7 + }, + "mne/transforms.py": { + "a": 6, + "d": 2 + }, + "mne/utils.py": { + "a": 26, + "d": 6 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_configuration.py": { + "a": 87, + "d": 0 + }, + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3689.json b/mne-python/source/doc/sphinxext/prs/3689.json new file mode 100644 index 0000000000000000000000000000000000000000..3729619526d27358a1b85dd1f34f18228be77750 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3689.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "faf973d77a2500af139d942ad3d21c934be912c9", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3690.json b/mne-python/source/doc/sphinxext/prs/3690.json new file mode 100644 index 0000000000000000000000000000000000000000..04232c6b8a8b4a6734750aaf57a6c547e014266e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3690.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8ede39da8e036ca707b890be14d9ad2f31255978", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 16, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3694.json b/mne-python/source/doc/sphinxext/prs/3694.json new file mode 100644 index 0000000000000000000000000000000000000000..834f5ac519216b8232685f5f0d2a6d6bee2d2c0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3694.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a184b6821f40c9e8f660a7809d697906dfa345eb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 9, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3698.json b/mne-python/source/doc/sphinxext/prs/3698.json new file mode 100644 index 0000000000000000000000000000000000000000..066635221ee5637a17872874061dc12b65ee3b03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3698.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "93d800cdd19ebb43178924c550583215563cfc10", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 4, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 8, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_parcellation.py": { + "a": 40, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 114, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/37.json b/mne-python/source/doc/sphinxext/prs/37.json new file mode 100644 index 0000000000000000000000000000000000000000..a67fe6a5e0674ed9e8fe4cdf8bcaa91c06591295 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/37.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5f776f2696d394ed3e193502b2cf99d9c081865c", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/forward.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/370.json b/mne-python/source/doc/sphinxext/prs/370.json new file mode 100644 index 0000000000000000000000000000000000000000..3b65182f19952743bc74a0e77b7b4c829407c0fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/370.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6536216b72f90ebbc1fd35acb36fbd89b4f70e50", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 217, + "d": 34 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 14, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3704.json b/mne-python/source/doc/sphinxext/prs/3704.json new file mode 100644 index 0000000000000000000000000000000000000000..cbc1d193569cc46c1b4032fbbb08f60b1a83150f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3704.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9aa6c94b0871bb6b8f8f0b354eed61199bff6ca8", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3705.json b/mne-python/source/doc/sphinxext/prs/3705.json new file mode 100644 index 0000000000000000000000000000000000000000..94f656588d2931196252cd6cdf77b68cf3dad01d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3705.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "930106e9e94fed915ca42b6c5f9fe9774eb30510", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 26, + "d": 16 + }, + "tutorials/plot_point_spread.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3706.json b/mne-python/source/doc/sphinxext/prs/3706.json new file mode 100644 index 0000000000000000000000000000000000000000..1fc8d3919d6e13b53f623969fe64bfa0a53e35af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3706.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6440eae0f542f33e539cd992375a809c1a02e3e4", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 5 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 18, + "d": 27 + }, + "mne/viz/utils.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3707.json b/mne-python/source/doc/sphinxext/prs/3707.json new file mode 100644 index 0000000000000000000000000000000000000000..352197effafb90473881b6de3fa7b2a8c8666eac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3707.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "7c51e252cc90602c91be6df0763baab62083d159", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/visualization/plot_eeg_on_scalp.py": { + "a": 25, + "d": 0 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 15, + "d": 23 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 5, + "d": 8 + }, + "mne/io/ctf/trans.py": { + "a": 5, + "d": 5 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 37, + "d": 12 + }, + "mne/transforms.py": { + "a": 6, + "d": 5 + }, + "mne/viz/_3d.py": { + "a": 93, + "d": 57 + }, + "mne/viz/tests/test_3d.py": { + "a": 20, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/371.json b/mne-python/source/doc/sphinxext/prs/371.json new file mode 100644 index 0000000000000000000000000000000000000000..ce614d2757d3606a1caf212a6510bda73ddc223d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/371.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "69602c9ed026b5be7b1c595d323849a2e8be1f4a", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 13, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3710.json b/mne-python/source/doc/sphinxext/prs/3710.json new file mode 100644 index 0000000000000000000000000000000000000000..63706663ef7120d1831fba02e14d8e15712ab222 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3710.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "259b3ded70038abc4e806948efe1c8dea5faeeee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 19 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3712.json b/mne-python/source/doc/sphinxext/prs/3712.json new file mode 100644 index 0000000000000000000000000000000000000000..e8b4c166aa3fa740eb728851806ca2228472d631 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3712.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7fea04ebb53d65e09c5877fbc0f227cf86b4cb92", + "authors": [ + { + "n": "Asish Panda", + "e": "asishrocks95@gmail.com" + } + ], + "changes": { + "doc/manual/decoding.rst": { + "a": 0, + "d": 6 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3713.json b/mne-python/source/doc/sphinxext/prs/3713.json new file mode 100644 index 0000000000000000000000000000000000000000..72faa5ee829397fd5e0733e3d91cc3f5cf45aec1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3713.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "b0fa44ec2fd88e2bc17ad0827fc7c42a90b8e092", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 10, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 29, + "d": 14 + }, + "mne/viz/tests/test_raw.py": { + "a": 6, + "d": 4 + }, + "tutorials/plot_artifacts_detection.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_visualize_raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3714.json b/mne-python/source/doc/sphinxext/prs/3714.json new file mode 100644 index 0000000000000000000000000000000000000000..9b8cec37159878c1dfa18c47c06b3751d4cff05b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3714.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2d104379b76ff7e37b94718aa837c83ddc358eaf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + }, + "doc/index.rst": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3715.json b/mne-python/source/doc/sphinxext/prs/3715.json new file mode 100644 index 0000000000000000000000000000000000000000..555aa2302865d0704c6e893f15622bdaae95dd0e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3715.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "089cf3500ae98b3c5697e43ec06de421308146a0", + "authors": [ + { + "n": "Leonardo S. Barbosa", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 63, + "d": 48 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3716.json b/mne-python/source/doc/sphinxext/prs/3716.json new file mode 100644 index 0000000000000000000000000000000000000000..b0cab5028bb5e1585ebf49f672b315004f7161c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3716.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "31883dfcef70860aa1f21238031773ebfe740317", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3718.json b/mne-python/source/doc/sphinxext/prs/3718.json new file mode 100644 index 0000000000000000000000000000000000000000..83fcd3d7a07930bc49e8dc73e77315f2972268eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3718.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f7ffe8aa068c1c743f6968ec09705270bef60c08", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 3, + "d": 3 + }, + "doc/index.rst": { + "a": 7, + "d": 21 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/cited_mne.py": { + "a": 2, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/372.json b/mne-python/source/doc/sphinxext/prs/372.json new file mode 100644 index 0000000000000000000000000000000000000000..e4cd27b826ab836831aa6909a760c1568aa687a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/372.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "335794d50b3c176ac922b7c14c7b04ee8021338d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3721.json b/mne-python/source/doc/sphinxext/prs/3721.json new file mode 100644 index 0000000000000000000000000000000000000000..78adf2e17339aeae2f74e36e13d99b5bdf3faa52 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3721.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "99cf565723612b35af67a23a38fbbfd7ace82c7f", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/io/kit/kit.py": { + "a": 27, + "d": 32 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3724.json b/mne-python/source/doc/sphinxext/prs/3724.json new file mode 100644 index 0000000000000000000000000000000000000000..06231bd386e02de8dcd17baf3bb7f0261bed7092 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3724.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "33d76289203fd5bd6a5083a36e5aa6fb84ceae9e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 22, + "d": 25 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 21, + "d": 40 + }, + "mne/commands/mne_surf2bem.py": { + "a": 2, + "d": 4 + }, + "mne/commands/tests/test_commands.py": { + "a": 16, + "d": 10 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 79, + "d": 1 + }, + "mne/gui/_file_traits.py": { + "a": 2, + "d": 1 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 5, + "d": 6 + }, + "mne/surface.py": { + "a": 19, + "d": 89 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3727.json b/mne-python/source/doc/sphinxext/prs/3727.json new file mode 100644 index 0000000000000000000000000000000000000000..26327bcabcdd8065e2b99f3829d0a8886d3554bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3727.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9df58a59140c8a723373120a45756554e1d2b726", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 12, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3728.json b/mne-python/source/doc/sphinxext/prs/3728.json new file mode 100644 index 0000000000000000000000000000000000000000..e287b688b3cca92829e68fbfc8176eafde847b8f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3728.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "be63cd40049a3d5526f9316c60b721cedf02bd74", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "circle.yml": { + "a": 4, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 18, + "d": 0 + }, + "doc/tutorials.rst": { + "a": 2, + "d": 1 + }, + "examples/decoding/plot_receptive_field.py": { + "a": 154, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/mtrf/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/mtrf/mtrf.py": { + "a": 30, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 22, + "d": 11 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/receptive_field.py": { + "a": 362, + "d": 0 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 150, + "d": 0 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + }, + "tutorials/plot_receptive_field.py": { + "a": 261, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3729.json b/mne-python/source/doc/sphinxext/prs/3729.json new file mode 100644 index 0000000000000000000000000000000000000000..6208810e1c83c05538ace4e23d98b61f60250083 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3729.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "6c43c09312a86c4010385c12c055dfd06ae2efce", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 1 + }, + "mne/annotations.py": { + "a": 1, + "d": 2 + }, + "mne/io/base.py": { + "a": 7, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 12, + "d": 5 + }, + "mne/viz/raw.py": { + "a": 24, + "d": 12 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3730.json b/mne-python/source/doc/sphinxext/prs/3730.json new file mode 100644 index 0000000000000000000000000000000000000000..818a18fda878bc3b335001fdaafba1572ddcb5a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3730.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "7562e23c3ee59681802e4768c0ed08676c45d426", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 3, + "d": 0 + }, + "doc/tutorials.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 2 + }, + "mne/transforms.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 66, + "d": 22 + }, + "mne/viz/tests/test_3d.py": { + "a": 6, + "d": 3 + }, + "tutorials/plot_ecog.py": { + "a": 47, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3732.json b/mne-python/source/doc/sphinxext/prs/3732.json new file mode 100644 index 0000000000000000000000000000000000000000..b7e2c233b192d814396310f8ae1d140d98d26edc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3732.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "96e704761e580d9d20d07b8aa816175519ed9423", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3734.json b/mne-python/source/doc/sphinxext/prs/3734.json new file mode 100644 index 0000000000000000000000000000000000000000..32494a86812e6b8ab6fd95fcf663c5ff6cdd188d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3734.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2331044def4a8dfc2b3f65a2211defc5b726389d", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3737.json b/mne-python/source/doc/sphinxext/prs/3737.json new file mode 100644 index 0000000000000000000000000000000000000000..4c1f689659379e3749d9823e19fd94f9aecc68e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3737.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bc323fb0b38abc8f31aa0f31b2c4868c4d2aad96", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/io/kit/kit.py": { + "a": 7, + "d": 5 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3738.json b/mne-python/source/doc/sphinxext/prs/3738.json new file mode 100644 index 0000000000000000000000000000000000000000..67052c05be09f568b2632a4ddbde66708bb2b893 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3738.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6c2e2222bcf7e45a911ecd6fdc3e4247dae31e18", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/realtime/epochs.py": { + "a": 28, + "d": 3 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 44, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/374.json b/mne-python/source/doc/sphinxext/prs/374.json new file mode 100644 index 0000000000000000000000000000000000000000..9dd6bdd4f9ca9d3aacf00d32c37b00cfa689ebf1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/374.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5c6c2775ec6ba86dea4c918e87ce7184a41d382d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3741.json b/mne-python/source/doc/sphinxext/prs/3741.json new file mode 100644 index 0000000000000000000000000000000000000000..4bfc40ab2cc9c4efda05be865f4c3382fa4acf06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3741.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3addedf8bfc108fd50d975d39fff605ea3744bb9", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 128, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 22, + "d": 2 + }, + "tutorials/plot_ecog.py": { + "a": 29, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3743.json b/mne-python/source/doc/sphinxext/prs/3743.json new file mode 100644 index 0000000000000000000000000000000000000000..5ccca5e31658f6202f0c2c34e6c5244367098124 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3743.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "09b6ada84a24c5574c749ec62ce96e383ae81a7b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 25, + "d": 12 + }, + "mne/io/tests/test_apply_function.py": { + "a": 8, + "d": 11 + }, + "tutorials/plot_modifying_data_inplace.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3744.json b/mne-python/source/doc/sphinxext/prs/3744.json new file mode 100644 index 0000000000000000000000000000000000000000..bc103910f806b34231bd4d7fc170ec5419634b71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3744.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "97fb61ed342fd05bacef03fb813e99812c406b1c", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 14, + "d": 4 + }, + "mne/io/base.py": { + "a": 4, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 251, + "d": 198 + }, + "mne/viz/raw.py": { + "a": 60, + "d": 11 + }, + "mne/viz/tests/test_evoked.py": { + "a": 12, + "d": 5 + }, + "mne/viz/tests/test_raw.py": { + "a": 10, + "d": 1 + }, + "tutorials/plot_visualize_raw.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3745.json b/mne-python/source/doc/sphinxext/prs/3745.json new file mode 100644 index 0000000000000000000000000000000000000000..8e34029ad4d100a7e8fadf25e8c27cb7bda28b8f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3745.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a9ab34c03a9cd06e3996379aed41413aae6619b1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/dipole.py": { + "a": 2, + "d": 10 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3747.json b/mne-python/source/doc/sphinxext/prs/3747.json new file mode 100644 index 0000000000000000000000000000000000000000..98a714ece0d47fcc9fc5034b96718512feea62b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3747.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "527a67f5b00c7c9b4591e797c86bca05223b5398", + "authors": [ + { + "n": "Keith Doelling", + "e": "keith.doelling@gmail.com" + } + ], + "changes": { + "mne/io/kit/kit.py": { + "a": 7, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 34, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3748.json b/mne-python/source/doc/sphinxext/prs/3748.json new file mode 100644 index 0000000000000000000000000000000000000000..fcb8acb9b20aaf37aca2b86bd43f8313fac4ad92 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3748.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4c7c061e1de3a6398e5f95f37281b9dfe48067a0", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3749.json b/mne-python/source/doc/sphinxext/prs/3749.json new file mode 100644 index 0000000000000000000000000000000000000000..81f91189c98780f854b1d220ea90809083d948e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3749.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "07102b961768c3c844a56002459cff3f3fdbdead", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 213, + "d": 167 + }, + "mne/channels/tests/test_montage.py": { + "a": 84, + "d": 44 + }, + "mne/io/meas_info.py": { + "a": 75, + "d": 71 + }, + "mne/io/tests/test_meas_info.py": { + "a": 8, + "d": 8 + }, + "mne/io/write.py": { + "a": 19, + "d": 13 + }, + "mne/transforms.py": { + "a": 4, + "d": 3 + }, + "mne/viz/montage.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3750.json b/mne-python/source/doc/sphinxext/prs/3750.json new file mode 100644 index 0000000000000000000000000000000000000000..c1b3909e38c962a03de7f9700d81800623df3dfb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3750.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b7f691299ec60a6ba60bb6c30c917696dc5d3e55", + "authors": [ + { + "n": "Keith Doelling", + "e": "keith.doelling@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3751.json b/mne-python/source/doc/sphinxext/prs/3751.json new file mode 100644 index 0000000000000000000000000000000000000000..7c2fccd4d5f3e28e946c8a54bacc27769dd819cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3751.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "599ae129dc82cbe435077c462ad8e19fee4504bf", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "examples/io/plot_objects_from_arrays.py": { + "a": 37, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3752.json b/mne-python/source/doc/sphinxext/prs/3752.json new file mode 100644 index 0000000000000000000000000000000000000000..4bcf0ef6e189774ef0c07e5ec4d21132818132f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3752.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6973da4709c62f54e5e16c125239180f04cdb07b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 46, + "d": 25 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 129, + "d": 114 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3754.json b/mne-python/source/doc/sphinxext/prs/3754.json new file mode 100644 index 0000000000000000000000000000000000000000..21c67bcde4692a491e5db83017761695c0c9d9b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3754.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "e58701054feef461c6598055a14efcaee84bb8bc", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 4, + "d": 1 + }, + "mne/data/coil_def.dat": { + "a": 78, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/artemis123/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/artemis123/artemis123.py": { + "a": 268, + "d": 0 + }, + "mne/io/artemis123/resources/Artemis123_ChannelMap.csv": { + "a": 146, + "d": 0 + }, + "mne/io/artemis123/resources/Artemis123_mneLoc.csv": { + "a": 144, + "d": 0 + }, + "mne/io/artemis123/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 46, + "d": 0 + }, + "mne/io/artemis123/utils.py": { + "a": 84, + "d": 0 + }, + "mne/tests/test_transforms.py": { + "a": 21, + "d": 1 + }, + "mne/transforms.py": { + "a": 41, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 2 + }, + "setup.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3756.json b/mne-python/source/doc/sphinxext/prs/3756.json new file mode 100644 index 0000000000000000000000000000000000000000..45284a3cc8a9c71ec1da499ed93c21e9af83889b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3756.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9dcc47684a24a6160d9b205e05e25f5f84a29f75", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/proj.py": { + "a": 4, + "d": 3 + }, + "mne/io/reference.py": { + "a": 11, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3758.json b/mne-python/source/doc/sphinxext/prs/3758.json new file mode 100644 index 0000000000000000000000000000000000000000..c180b1d0a3fa6ae602e82a447c1cea0f81599c3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3758.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e83c880e7c5b2176a6dfe4a3e7c8279780176dde", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 6, + "d": 1 + }, + "mne/io/reference.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3759.json b/mne-python/source/doc/sphinxext/prs/3759.json new file mode 100644 index 0000000000000000000000000000000000000000..00f00f85083b3e7110573e5a86c566811210c8de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3759.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4bdbd00cf0366608c6b70c62898c48d19f6baeca", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 49, + "d": 20 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 0 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/376.json b/mne-python/source/doc/sphinxext/prs/376.json new file mode 100644 index 0000000000000000000000000000000000000000..99c551874f8a3f59405dd9952536e755815fe483 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/376.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e90384186c53a74f384536f319f86835ef1cea03", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 17, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3760.json b/mne-python/source/doc/sphinxext/prs/3760.json new file mode 100644 index 0000000000000000000000000000000000000000..a4b15ab8fe5973a0325f8f076cb38e20373bfaa2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3760.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4292364b9d77a0e15159571485bf12e382b0e4c1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 6, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3762.json b/mne-python/source/doc/sphinxext/prs/3762.json new file mode 100644 index 0000000000000000000000000000000000000000..b5c27addf6b9872487cd947a135101c690d26e65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3762.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "81d238ab772a0b91e603881daa71d835b9be6a13", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/commands/mne_coreg.py": { + "a": 7, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 5, + "d": 2 + }, + "mne/gui/_coreg_gui.py": { + "a": 46, + "d": 42 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3763.json b/mne-python/source/doc/sphinxext/prs/3763.json new file mode 100644 index 0000000000000000000000000000000000000000..f92ac18b80b85b623843395ea83d3d08de78c437 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3763.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e5ce0cf1712ce080b9e8d3977dd1f0d2a019e70d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "setup.py": { + "a": 10, + "d": 46 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3765.json b/mne-python/source/doc/sphinxext/prs/3765.json new file mode 100644 index 0000000000000000000000000000000000000000..5eefbf33474cf2fe656e03e9235e571212e52fbd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3765.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "50672ae26009083fe99a3d84b74c5b9adae33afd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3766.json b/mne-python/source/doc/sphinxext/prs/3766.json new file mode 100644 index 0000000000000000000000000000000000000000..87b846420cffee5fc98281a8729aea9956dd9578 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3766.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "cb8707f43e62184c4a0f8651495ff6d3b2b81b7a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/externals/tempita/__init__.py": { + "a": 3, + "d": 1302 + }, + "mne/externals/tempita/_looper.py": { + "a": 2, + "d": 2 + }, + "mne/externals/tempita/_tempita.py": { + "a": 1182, + "d": 0 + }, + "mne/externals/tempita/compat3.py": { + "a": 11, + "d": 9 + }, + "setup.cfg": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3771.json b/mne-python/source/doc/sphinxext/prs/3771.json new file mode 100644 index 0000000000000000000000000000000000000000..9eeef8b0dfc912544d299f69d489e04381f74682 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3771.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0b104fa12a4710c38977879b7cb9779b1d36687d", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 6, + "d": 1 + }, + "mne/source_space.py": { + "a": 28, + "d": 12 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3772.json b/mne-python/source/doc/sphinxext/prs/3772.json new file mode 100644 index 0000000000000000000000000000000000000000..894e68cfe7447a8838012e7ac808951ad15dede6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3772.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "fe262fbbff21e52b56df68d830524ebb1848041e", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 6, + "d": 0 + }, + "mne/datasets/visual_92_categories/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/datasets/visual_92_categories/visual_92_categories.py": { + "a": 78, + "d": 0 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3773.json b/mne-python/source/doc/sphinxext/prs/3773.json new file mode 100644 index 0000000000000000000000000000000000000000..90b71595e40da33ca8a5bde34aaa6f0fe04f2bf0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3773.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "952de45498c3b108ac5f854335f98fb3bb5eec69", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 4, + "d": 3 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 4 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "setup.cfg": { + "a": 1, + "d": 1 + }, + "tutorials/plot_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_python_intro.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3775.json b/mne-python/source/doc/sphinxext/prs/3775.json new file mode 100644 index 0000000000000000000000000000000000000000..9a9ba9772348c876cfd695834c07e24228e6a2c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3775.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bc8cc665d132a2fe7147460261ac0df7a90547d0", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3776.json b/mne-python/source/doc/sphinxext/prs/3776.json new file mode 100644 index 0000000000000000000000000000000000000000..320d7589ef704558ad867cf7716f1b188e1e2f54 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3776.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bc3627ed4e60f7b19bfda0d6736e7ccb0515e905", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "examples/visualization/plot_channel_epochs_image.py": { + "a": 5, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3777.json b/mne-python/source/doc/sphinxext/prs/3777.json new file mode 100644 index 0000000000000000000000000000000000000000..2a12267ffb7dcf7c9a04053b705b461cc5eb2348 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3777.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8f87050533b0938758771fb0006c629a3a408074", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/io/kit/kit.py": { + "a": 34, + "d": 37 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3778.json b/mne-python/source/doc/sphinxext/prs/3778.json new file mode 100644 index 0000000000000000000000000000000000000000..cbb693af5b5deb169d2c240e2a30490266b35a86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3778.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fcf328a89e24c082ca41597a792643ae21d438cc", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/forward/plot_read_bem_surfaces.py": { + "a": 16, + "d": 23 + }, + "mne/surface.py": { + "a": 14, + "d": 5 + }, + "mne/viz/_3d.py": { + "a": 87, + "d": 16 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3779.json b/mne-python/source/doc/sphinxext/prs/3779.json new file mode 100644 index 0000000000000000000000000000000000000000..df5ca5f5968b4708f93b7dff9fe2e0542ef9d686 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3779.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e28b2b319847dc797957faf6ec8c8968ecd2efa8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/inverse_sparse/_gamma_map.py": { + "a": 7, + "d": 6 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/378.json b/mne-python/source/doc/sphinxext/prs/378.json new file mode 100644 index 0000000000000000000000000000000000000000..ead289b8c905590b07bb71fcc97534faa03b1bcb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/378.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "789cae1ae1901f8899bd313f04a801ecc6cc67af", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/constants.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3780.json b/mne-python/source/doc/sphinxext/prs/3780.json new file mode 100644 index 0000000000000000000000000000000000000000..546f9d3270d8795e8bec4daba000bc0bc9b92ce4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3780.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "eeb763060d134edc9fecb71df66b91f6116c318c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 22, + "d": 12 + }, + "mne/fixes.py": { + "a": 54, + "d": 0 + }, + "mne/io/base.py": { + "a": 6, + "d": 4 + }, + "mne/tests/test_filter.py": { + "a": 22, + "d": 7 + }, + "tutorials/plot_background_filtering.py": { + "a": 49, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3782.json b/mne-python/source/doc/sphinxext/prs/3782.json new file mode 100644 index 0000000000000000000000000000000000000000..d7cb818a525eac3f6bd5ae629304ba91d8524257 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3782.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "496db659369c671fc4a4a244cfdec3c6845cc800", + "authors": [ + { + "n": "Keith Doelling", + "e": "keith.doelling@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 4, + "d": 4 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3783.json b/mne-python/source/doc/sphinxext/prs/3783.json new file mode 100644 index 0000000000000000000000000000000000000000..79f9deaf772d27dfb9ddb5d12d1b67ccbfc05412 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3783.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a85cd392c112adef021916af2af8ba9866febdb5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 5, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 15, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3789.json b/mne-python/source/doc/sphinxext/prs/3789.json new file mode 100644 index 0000000000000000000000000000000000000000..a92187992c583ca21dae36f0948a73905c854899 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3789.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "0f5aaa5ee6c24eefc7cfbb0035fa07a06f44705f", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 5, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 4, + "d": 3 + }, + "mne/time_frequency/__init__.py": { + "a": 5, + "d": 4 + }, + "mne/time_frequency/_stockwell.py": { + "a": 20, + "d": 11 + }, + "mne/time_frequency/multitaper.py": { + "a": 93, + "d": 6 + }, + "mne/time_frequency/psd.py": { + "a": 22, + "d": 11 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 12, + "d": 13 + }, + "mne/time_frequency/tfr.py": { + "a": 88, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3792.json b/mne-python/source/doc/sphinxext/prs/3792.json new file mode 100644 index 0000000000000000000000000000000000000000..e7fb2223d4c6d05664507fbb358ef0af654db435 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3792.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "85670121195b5021f100e5470dcb4d66ebcf2e38", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 6, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 89, + "d": 12 + }, + "mne/viz/misc.py": { + "a": 24, + "d": 19 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_epochs.py": { + "a": 37, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3793.json b/mne-python/source/doc/sphinxext/prs/3793.json new file mode 100644 index 0000000000000000000000000000000000000000..8ee1e13a617bc3306d020a4863728c93e3230c23 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3793.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4aa330ed031f0c5b8ac0e72f46c155b50ba242e6", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 0 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3794.json b/mne-python/source/doc/sphinxext/prs/3794.json new file mode 100644 index 0000000000000000000000000000000000000000..fba08b6f897daddceec4dc9e8fb2671ff5eeaa9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3794.json @@ -0,0 +1,183 @@ +{ + "merge_commit_sha": "23575ddc79324e5e846318ee6adf9daf55baf4dd", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 16, + "d": 16 + }, + "mne/channels/interpolation.py": { + "a": 4, + "d": 4 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 79, + "d": 17 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 3 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 52, + "d": 11 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 4, + "d": 4 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 4, + "d": 4 + }, + "mne/io/nicolet/nicolet.py": { + "a": 2, + "d": 2 + }, + "mne/io/proj.py": { + "a": 5, + "d": 5 + }, + "mne/io/reference.py": { + "a": 6, + "d": 6 + }, + "mne/io/tests/test_reference.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 18, + "d": 18 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/stim.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/xdawn.py": { + "a": 7, + "d": 7 + }, + "mne/realtime/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 2 + }, + "mne/stats/regression.py": { + "a": 2, + "d": 2 + }, + "mne/tests/common.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 6 + }, + "mne/time_frequency/psd.py": { + "a": 5, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 6, + "d": 6 + }, + "mne/viz/ica.py": { + "a": 11, + "d": 11 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3796.json b/mne-python/source/doc/sphinxext/prs/3796.json new file mode 100644 index 0000000000000000000000000000000000000000..d3a00e252c12f6948a1757b3b5506727d654f5f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3796.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "095db9748280807d3e5c01c13d6b850cfb66f741", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 64, + "d": 43 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3797.json b/mne-python/source/doc/sphinxext/prs/3797.json new file mode 100644 index 0000000000000000000000000000000000000000..4ff52fa5118786720c74e87d17c9174f6443ab12 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3797.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "eb4ccea83a2eb483a4a51dce04e03364f4bacb78", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 23, + "d": 9 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 30, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3798.json b/mne-python/source/doc/sphinxext/prs/3798.json new file mode 100644 index 0000000000000000000000000000000000000000..f2cabb723091b22d8ce7344e788693042a372542 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3798.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "61b2decaacc3184ff01dff956836ea24065e542c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/dipole.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/38.json b/mne-python/source/doc/sphinxext/prs/38.json new file mode 100644 index 0000000000000000000000000000000000000000..0a9aa6330086f79e80414e5626176360d1109809 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/38.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dac473e1be85086a7509ec4f5285ced4a9d12254", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz.py": { + "a": 28, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3800.json b/mne-python/source/doc/sphinxext/prs/3800.json new file mode 100644 index 0000000000000000000000000000000000000000..a84afd1334fee96fb684a36ca34e7b5eb0e8993a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3800.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3842c11a33e919e3296aa4a9615bd52f1a545e2b", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3802.json b/mne-python/source/doc/sphinxext/prs/3802.json new file mode 100644 index 0000000000000000000000000000000000000000..48e87c160f44819bc1308700474ff618cb718d5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3802.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "630632c83b4e3b258a77e9bb4d602310b367660e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 4, + "d": 3 + }, + "mne/io/constants.py": { + "a": 16, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3803.json b/mne-python/source/doc/sphinxext/prs/3803.json new file mode 100644 index 0000000000000000000000000000000000000000..be5643f1abacec4c19e900a35a70a7db54148142 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3803.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e3c5cc0b80fdbbb0b5aac7d2e56f3d17195fe0d4", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 8, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3805.json b/mne-python/source/doc/sphinxext/prs/3805.json new file mode 100644 index 0000000000000000000000000000000000000000..2c05ef3f7b9f7cd103cdc10c4ac140d3f6265a86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3805.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e2f79af9ad9d97a417aab8633161d10652fa158f", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "tutorials/plot_visualize_evoked.py": { + "a": 24, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3806.json b/mne-python/source/doc/sphinxext/prs/3806.json new file mode 100644 index 0000000000000000000000000000000000000000..55ae1cf8cf2336bb0b6547cf81b17abe9db95745 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3806.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4ca914d00351d3f56eaf8a02ddf582dc8f4758d5", + "authors": [ + { + "n": "ppasler", + "e": "paul@ppasler.de" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3808.json b/mne-python/source/doc/sphinxext/prs/3808.json new file mode 100644 index 0000000000000000000000000000000000000000..5242dd400d62ea649c5b34e2ffac73d6fa012477 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3808.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8ecb2af8a969a76f5b3d115f4a362f06aebaf747", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 42, + "d": 24 + }, + "mne/tests/test_dipole.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3813.json b/mne-python/source/doc/sphinxext/prs/3813.json new file mode 100644 index 0000000000000000000000000000000000000000..24e9df9b2ea5ba4c08750ad10b57ff0efcf771d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3813.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b915f8481412633421c8546fe7c11f6af274c86d", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 27, + "d": 17 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3815.json b/mne-python/source/doc/sphinxext/prs/3815.json new file mode 100644 index 0000000000000000000000000000000000000000..ccc65efd50c4b6f2d5ed0f0e8b81220a6d27dc9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3815.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "16e7d2c89cc4f0430e701528588cbcec43e4f933", + "authors": [ + { + "n": "ppasler", + "e": "paul@ppasler.de" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3817.json b/mne-python/source/doc/sphinxext/prs/3817.json new file mode 100644 index 0000000000000000000000000000000000000000..662171c81d3514edc5ee7dbfe5c0e9943620e5de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3817.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7919f70b64866247ab1c172e2fa86c53ae13cc9c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/event.py": { + "a": 4, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 14, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3818.json b/mne-python/source/doc/sphinxext/prs/3818.json new file mode 100644 index 0000000000000000000000000000000000000000..430bc57bb88dde357bf16e0aa2d18044ed9d6784 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3818.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "cf2c0cc1f509243d3e32e73b6b877aa0c2f20535", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 14, + "d": 12 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 10, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 14, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3821.json b/mne-python/source/doc/sphinxext/prs/3821.json new file mode 100644 index 0000000000000000000000000000000000000000..cd2dae7190cfc8e4a9a5a301df7fc9bc74cfee6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3821.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d6c6dc36aceed1b5900d8920f76555967a448192", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 30, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 7, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 16, + "d": 33 + }, + "mne/viz/tests/test_raw.py": { + "a": 61, + "d": 20 + }, + "mne/viz/utils.py": { + "a": 401, + "d": 11 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 3, + "d": 0 + }, + "tutorials/plot_visualize_raw.py": { + "a": 13, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3823.json b/mne-python/source/doc/sphinxext/prs/3823.json new file mode 100644 index 0000000000000000000000000000000000000000..5491880c06b761dc57ca080a85770cd586bfcc5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3823.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d0e4c98368a553b72c8a805944cb8b5d55e60b48", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/fixes.py": { + "a": 432, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 7, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3825.json b/mne-python/source/doc/sphinxext/prs/3825.json new file mode 100644 index 0000000000000000000000000000000000000000..9b380cda75522703dcd242f554e4a83e97aa61e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3825.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4eac2dd9e8c70ea3c3c4db98533376c3ed31fde4", + "authors": [ + { + "n": "Niklas Wilming", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/io/ctf/ctf.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3826.json b/mne-python/source/doc/sphinxext/prs/3826.json new file mode 100644 index 0000000000000000000000000000000000000000..2eaf360f3101da4e84b4bfef8d7a2689b2f2c5f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3826.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "70062c9d9fcb70ce8e17dcdc4418cba78c6a39e6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 0 + }, + "mne/bem.py": { + "a": 6, + "d": 6 + }, + "mne/cov.py": { + "a": 11, + "d": 9 + }, + "mne/dipole.py": { + "a": 4, + "d": 3 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 2, + "d": 3 + }, + "mne/io/artemis123/artemis123.py": { + "a": 6, + "d": 1 + }, + "mne/io/base.py": { + "a": 4, + "d": 0 + }, + "mne/io/pick.py": { + "a": 4, + "d": 0 + }, + "mne/io/tests/test_pick.py": { + "a": 6, + "d": 4 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 4 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 33, + "d": 33 + }, + "mne/preprocessing/stim.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 22, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 5 + }, + "mne/stats/cluster_level.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_cov.py": { + "a": 38, + "d": 2 + }, + "mne/utils.py": { + "a": 7, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3828.json b/mne-python/source/doc/sphinxext/prs/3828.json new file mode 100644 index 0000000000000000000000000000000000000000..e0a4631aa5e2f7caeb911c1dedd2cb741f18e5c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3828.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "22f62a56109a87b62878962fcea332939f0b6c75", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 14, + "d": 4 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 4, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3829.json b/mne-python/source/doc/sphinxext/prs/3829.json new file mode 100644 index 0000000000000000000000000000000000000000..a31805f4fdbd6b30320790bfa2b93b99ecc0d1f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3829.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bac50dd08361b10d0a65c614ea2de06308750411", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3831.json b/mne-python/source/doc/sphinxext/prs/3831.json new file mode 100644 index 0000000000000000000000000000000000000000..9bdf051e5e320c1c9dadb5ab4e544036ab87c11f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3831.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "9254f5af667ee70673d5a0f69fa48686be02dced", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 45, + "d": 104 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 4, + "d": 3 + }, + "mne/report.py": { + "a": 16, + "d": 9 + }, + "mne/tests/test_report.py": { + "a": 7, + "d": 9 + }, + "mne/utils.py": { + "a": 5, + "d": 7 + }, + "mne/viz/misc.py": { + "a": 12, + "d": 12 + }, + "mne/viz/topomap.py": { + "a": 6, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 16, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3833.json b/mne-python/source/doc/sphinxext/prs/3833.json new file mode 100644 index 0000000000000000000000000000000000000000..56c56b91c0c00d2c8b48589045114eb079c0939f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3833.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "86abfc63c71d0beb95bf7ba17b48dc3b8c00dbc5", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 26, + "d": 0 + }, + "mne/decoding/search_light.py": { + "a": 23, + "d": 15 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 40, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3834.json b/mne-python/source/doc/sphinxext/prs/3834.json new file mode 100644 index 0000000000000000000000000000000000000000..35f1d47b5ce0248560178fd2d0ef38a639c69ad4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3834.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f83392c5420ddd13f0dc19d843525e89b1f7043d", + "authors": [ + { + "n": "Matteo Visconti di Oleggio Castello", + "e": null + } + ], + "changes": { + "mne/viz/decoding.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3835.json b/mne-python/source/doc/sphinxext/prs/3835.json new file mode 100644 index 0000000000000000000000000000000000000000..57f48a6c99e94cc434a70e29a7799fbf5fd4a538 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3835.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b62de8656c4606ec3858bb098abcd6731659d62e", + "authors": [ + { + "n": "Lorenzo Alfine", + "e": "lorenzo.alfine@gmail.com" + } + ], + "changes": { + "tutorials/plot_creating_data_structures.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3836.json b/mne-python/source/doc/sphinxext/prs/3836.json new file mode 100644 index 0000000000000000000000000000000000000000..46bf71f495f85f874f5bc955cd5b9b6528b3ac0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3836.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c2d1f3e7a569bd356416d0c9dde76ff03b5bb958", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3842.json b/mne-python/source/doc/sphinxext/prs/3842.json new file mode 100644 index 0000000000000000000000000000000000000000..6cb6f9ba7dc73feae773d2d3c434be8f54b7b2d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3842.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "6175ac800a991d84748ae4e9e5b325d9a8fb9fab", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 4 + }, + "doc/documentation.rst": { + "a": 3, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_vector_mne_solution.py": { + "a": 41, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 111, + "d": 58 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 84, + "d": 39 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 589, + "d": 310 + }, + "mne/tests/test_source_estimate.py": { + "a": 173, + "d": 83 + }, + "mne/viz/_3d.py": { + "a": 187, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 22, + "d": 2 + }, + "tutorials/plot_dipole_orientations.py": { + "a": 206, + "d": 0 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 24, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3843.json b/mne-python/source/doc/sphinxext/prs/3843.json new file mode 100644 index 0000000000000000000000000000000000000000..b7090229d06183ba93bcd52b3f32a363da278073 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3843.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "79d2ab8e03c03b4564c5c3904496659950b1e7ca", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_transformer.py": { + "a": 5, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3845.json b/mne-python/source/doc/sphinxext/prs/3845.json new file mode 100644 index 0000000000000000000000000000000000000000..684427b2c1af23b99f3144654c7c970b34924ef2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3845.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f852fb2d1c7d901f08894ada60c34464d0c735f3", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 14, + "d": 0 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3848.json b/mne-python/source/doc/sphinxext/prs/3848.json new file mode 100644 index 0000000000000000000000000000000000000000..815e0d8f390f8202a514608129662b71ff561f90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3848.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "faec5756927289374197667e8de563448de3281c", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 3, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3851.json b/mne-python/source/doc/sphinxext/prs/3851.json new file mode 100644 index 0000000000000000000000000000000000000000..fc93531ebf48cc919541718ebde99df39d4273a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3851.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "990159a3b1598b931449828bf6345e8a97bad6d0", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/baseline.py": { + "a": 5, + "d": 4 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3854.json b/mne-python/source/doc/sphinxext/prs/3854.json new file mode 100644 index 0000000000000000000000000000000000000000..7fe0a03d9758d82e2813c5d3509d5063bd130a7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3854.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "06e814b4b19834191e8b6d2dc50e4ac46d1de672", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 8, + "d": 0 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 9, + "d": 8 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 8, + "d": 7 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 8, + "d": 6 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 8, + "d": 6 + }, + "mne/beamformer/_dics.py": { + "a": 92, + "d": 103 + }, + "mne/beamformer/_lcmv.py": { + "a": 43, + "d": 125 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 41, + "d": 38 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 12, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3860.json b/mne-python/source/doc/sphinxext/prs/3860.json new file mode 100644 index 0000000000000000000000000000000000000000..30d8e762c471629f494161781fdcc8c23b098f3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3860.json @@ -0,0 +1,151 @@ +{ + "merge_commit_sha": "5355095401dea28687d5158ddf8a2ec3bcef3451", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/cited.rst": { + "a": 2, + "d": 0 + }, + "doc/contributing.rst": { + "a": 3, + "d": 1 + }, + "doc/customizing_git.rst": { + "a": 2, + "d": 0 + }, + "doc/faq.rst": { + "a": 2, + "d": 0 + }, + "doc/getting_started.rst": { + "a": 2, + "d": 0 + }, + "doc/manual/index.rst": { + "a": 2, + "d": 0 + }, + "doc/manual/sample_dataset.rst": { + "a": 1, + "d": 1 + }, + "doc/martinos.rst": { + "a": 3, + "d": 1 + }, + "doc/mne_cpp.rst": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 14, + "d": 0 + }, + "doc/references.rst": { + "a": 1, + "d": 1 + }, + "doc/tutorials.rst": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 14, + "d": 7 + }, + "mne/bem.py": { + "a": 8, + "d": 8 + }, + "mne/epochs.py": { + "a": 15, + "d": 6 + }, + "mne/evoked.py": { + "a": 0, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 0, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 3 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 8, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 6, + "d": 6 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 0, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 2 + }, + "mne/io/egi/egi.py": { + "a": 0, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 0, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 10, + "d": 10 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 7, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 8 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 0, + "d": 2 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3861.json b/mne-python/source/doc/sphinxext/prs/3861.json new file mode 100644 index 0000000000000000000000000000000000000000..d5887a173cd8c98c7632ffd20970885e924bb1ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3861.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "04a9c9c96977c9d1abb86fddb7f4aaeb76fb374a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 45, + "d": 36 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3865.json b/mne-python/source/doc/sphinxext/prs/3865.json new file mode 100644 index 0000000000000000000000000000000000000000..baffc3048bd8de0c09c3022ac7ea82ba2f16c523 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3865.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "80b7446482997c2221e855541576d0f5f21323e4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3866.json b/mne-python/source/doc/sphinxext/prs/3866.json new file mode 100644 index 0000000000000000000000000000000000000000..7d8c9c70a1081c7e0a6b2d7670427736e7b17509 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3866.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0b457fff9cc0bcc095d65d11c707ccd3f45b6e60", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/tests/test_montage.py": { + "a": 15, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3867.json b/mne-python/source/doc/sphinxext/prs/3867.json new file mode 100644 index 0000000000000000000000000000000000000000..6fa87091be06f7d3bb0c32b617bc57a67ecc15bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3867.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ba3d5852fd24cf55c06bae7d2d87177ba38c038b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/proj.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3868.json b/mne-python/source/doc/sphinxext/prs/3868.json new file mode 100644 index 0000000000000000000000000000000000000000..e2528561518049ba42077b9c6f8686c6a6bb3acb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3868.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "86c98fe1cbcbca9b7e8e8e4433a7f5238f99ba54", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 2, + "d": 3 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 4, + "d": 4 + }, + "mne/viz/misc.py": { + "a": 8, + "d": 7 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/387.json b/mne-python/source/doc/sphinxext/prs/387.json new file mode 100644 index 0000000000000000000000000000000000000000..c889a7b9f6cf87ab9e8f650b1e8ea83604662402 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/387.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a45d96be422003c474474879a4022acdb6b7c597", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 11, + "d": 0 + }, + "mne/fiff/tests/test_raw.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3872.json b/mne-python/source/doc/sphinxext/prs/3872.json new file mode 100644 index 0000000000000000000000000000000000000000..6a7e525105c327c3ab0f74cbf38b8177c02df4e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3872.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9c6a99e3c3ec693e3fb21014aea42c03f589bc5e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3873.json b/mne-python/source/doc/sphinxext/prs/3873.json new file mode 100644 index 0000000000000000000000000000000000000000..d45883256770bf38e5051811ae84cacd71e00bce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3873.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "74e1af45de44715ce93455fed74fd27b69a52947", + "authors": [ + { + "n": null, + "e": "erkkahe@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3874.json b/mne-python/source/doc/sphinxext/prs/3874.json new file mode 100644 index 0000000000000000000000000000000000000000..0a8514817c1829b79b2f7d1e50277d5b90209ee2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3874.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ab42e6a42548a98eb18910a21aeb0194bd506a40", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/search_light.py": { + "a": 20, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 28, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3881.json b/mne-python/source/doc/sphinxext/prs/3881.json new file mode 100644 index 0000000000000000000000000000000000000000..56729cfafc74b079a86f6a074616db96ae1a7c54 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3881.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "33e2f85e24400581d4c604ef86c7697e1b703d91", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "doc/contributing.rst": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3885.json b/mne-python/source/doc/sphinxext/prs/3885.json new file mode 100644 index 0000000000000000000000000000000000000000..842b3c6a058b79d1a4be408b45aecdc4379dedd3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3885.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0f3a38aa6f1bddd18e43168544298a187972770a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 17, + "d": 1 + }, + "mne/utils.py": { + "a": 32, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3887.json b/mne-python/source/doc/sphinxext/prs/3887.json new file mode 100644 index 0000000000000000000000000000000000000000..7a965d2a4221ed1a4c646c836da458f33f097869 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3887.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2169dd336b0956d3ba132b374e6f0302f13253dd", + "authors": [ + { + "n": "ppasler", + "e": "paul@ppasler.de" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 7, + "d": 11 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3888.json b/mne-python/source/doc/sphinxext/prs/3888.json new file mode 100644 index 0000000000000000000000000000000000000000..5ad94d8f16d46d24a35ad9fed3c10bf26c1d7425 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3888.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d00d27eff1ac14e21b1b7041316e8c8e8847e668", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 6, + "d": 10 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3892.json b/mne-python/source/doc/sphinxext/prs/3892.json new file mode 100644 index 0000000000000000000000000000000000000000..572476e092fc69e15a3ea005f07f8a2a7f192e09 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3892.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "e0faad3d65e3f4ad1c2eced112c4070b08cb1963", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 0, + "d": 3 + }, + "doc/advanced_setup.rst": { + "a": 120, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "doc/configure_git.rst": { + "a": 609, + "d": 0 + }, + "doc/contributing.rst": { + "a": 77, + "d": 859 + }, + "doc/customizing_git.rst": { + "a": 2, + "d": 0 + }, + "doc/faq.rst": { + "a": 0, + "d": 4 + }, + "doc/getting_started.rst": { + "a": 10, + "d": 10 + }, + "doc/git_links.inc": { + "a": 5, + "d": 2 + }, + "doc/install_mne_c.rst": { + "a": 17, + "d": 37 + }, + "doc/install_mne_python.rst": { + "a": 43, + "d": 196 + }, + "doc/known_projects.inc": { + "a": 6, + "d": 0 + }, + "mne/source_space.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3895.json b/mne-python/source/doc/sphinxext/prs/3895.json new file mode 100644 index 0000000000000000000000000000000000000000..5ff9e3cc4b38c7baa7128b63f5a2da74440a5b25 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3895.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "eb418d24e0cdab1254b4524e5893bf13bcc800ba", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3896.json b/mne-python/source/doc/sphinxext/prs/3896.json new file mode 100644 index 0000000000000000000000000000000000000000..39ff4a19f04350d8526d53239ae9604f0f52f796 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3896.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "04de57b3da07d47489be4f82076d0012fd25d121", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 46, + "d": 18 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 5, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3898.json b/mne-python/source/doc/sphinxext/prs/3898.json new file mode 100644 index 0000000000000000000000000000000000000000..692680f5e37ae61efd5deaebcd8c80de54c83c03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3898.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "34a68cc849be748d062701b6b9fdf16e801be176", + "authors": [ + { + "n": "ppasler", + "e": "paul@ppasler.de" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3899.json b/mne-python/source/doc/sphinxext/prs/3899.json new file mode 100644 index 0000000000000000000000000000000000000000..0da73e4d8dbc67d0b2c1b5d2c7c2fb51a5c9ad4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3899.json @@ -0,0 +1,231 @@ +{ + "merge_commit_sha": "10f69603a5788e6a44692dfed204d32cdbe90502", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "doc/configure_git.rst": { + "a": 4, + "d": 4 + }, + "doc/contributing.rst": { + "a": 5, + "d": 5 + }, + "doc/faq.rst": { + "a": 1, + "d": 1 + }, + "doc/getting_started.rst": { + "a": 2, + "d": 2 + }, + "doc/index.rst": { + "a": 2, + "d": 2 + }, + "doc/manual/datasets_index.rst": { + "a": 37, + "d": 23 + }, + "doc/manual/decoding.rst": { + "a": 3, + "d": 2 + }, + "doc/manual/migrating.rst": { + "a": 29, + "d": 29 + }, + "doc/manual/preprocessing/bads.rst": { + "a": 2, + "d": 0 + }, + "doc/manual/preprocessing/filter.rst": { + "a": 2, + "d": 0 + }, + "doc/manual/preprocessing/overview.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 6, + "d": 8 + }, + "doc/manual/statistics.rst": { + "a": 5, + "d": 5 + }, + "doc/manual/visualization.rst": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 129, + "d": 55 + }, + "doc/tutorials/seven_stories_about_mne.rst": { + "a": 4, + "d": 4 + }, + "doc/whats_new.rst": { + "a": 37, + "d": 37 + }, + "examples/io/plot_objects_from_arrays.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/chpi.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 45, + "d": 39 + }, + "mne/datasets/megsim/megsim.py": { + "a": 22, + "d": 20 + }, + "mne/datasets/utils.py": { + "a": 6, + "d": 8 + }, + "mne/decoding/base.py": { + "a": 13, + "d": 16 + }, + "mne/decoding/ems.py": { + "a": 27, + "d": 24 + }, + "mne/decoding/time_frequency.py": { + "a": 4, + "d": 5 + }, + "mne/decoding/transformer.py": { + "a": 9, + "d": 7 + }, + "mne/dipole.py": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 13, + "d": 8 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 4, + "d": 2 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 12, + "d": 6 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/infomax_.py": { + "a": 12, + "d": 14 + }, + "mne/preprocessing/xdawn.py": { + "a": 16, + "d": 45 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 5 + }, + "mne/source_space.py": { + "a": 2, + "d": 1 + }, + "mne/stats/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_ecog.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_eeg_erp.py": { + "a": 5, + "d": 5 + }, + "tutorials/plot_forward.py": { + "a": 7, + "d": 2 + }, + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/39.json b/mne-python/source/doc/sphinxext/prs/39.json new file mode 100644 index 0000000000000000000000000000000000000000..c5323ebcb2da669508133b3109695d05407be8d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/39.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "51367f258781e9d4e27cb43d5ea6054bab1573f3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 1 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 5, + "d": 0 + }, + "mne/cov.py": { + "a": 122, + "d": 39 + }, + "mne/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/pick.py": { + "a": 31, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 22, + "d": 1 + }, + "mne/viz.py": { + "a": 11, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3904.json b/mne-python/source/doc/sphinxext/prs/3904.json new file mode 100644 index 0000000000000000000000000000000000000000..2ad46ce008136b9fa85764d1131be762c174bdfc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3904.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a68fde2c71a475fd547bd14b31497beab7a5827e", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 20, + "d": 41 + }, + "mne/gui/_file_traits.py": { + "a": 5, + "d": 59 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3905.json b/mne-python/source/doc/sphinxext/prs/3905.json new file mode 100644 index 0000000000000000000000000000000000000000..8a86150cbb9cce059ad0f6acf82cd24b56a2be79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3905.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7cbfd5d295fcb32977f700485a008ea9a0fdd9d8", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 16, + "d": 8 + }, + "mne/viz/tests/test_topo.py": { + "a": 44, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 63, + "d": 22 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3909.json b/mne-python/source/doc/sphinxext/prs/3909.json new file mode 100644 index 0000000000000000000000000000000000000000..7364667c671f268b0100c0d9135785f474fcdd2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3909.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "953764b3ca2e9a9e4ee6a1d59fdf3d64ecdf2e2a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 23, + "d": 14 + }, + "mne/io/pick.py": { + "a": 8, + "d": 5 + }, + "mne/tests/test_cov.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/391.json b/mne-python/source/doc/sphinxext/prs/391.json new file mode 100644 index 0000000000000000000000000000000000000000..38ab32156e5ba68e69ef0d3525a1844550c90fcc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/391.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a5336ccdd4764dfa0c4baeea123e24626149cd68", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3910.json b/mne-python/source/doc/sphinxext/prs/3910.json new file mode 100644 index 0000000000000000000000000000000000000000..812230263bb3c86055c9940da8c189bca2411659 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3910.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "685a0d8db149bcc464a93c6a34fb56042ead2adc", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 22, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3911.json b/mne-python/source/doc/sphinxext/prs/3911.json new file mode 100644 index 0000000000000000000000000000000000000000..800d3295e4dcccbd3e2b0f6809a48f48876a42f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3911.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a94f81a5e228fe6592ee9e31902a48f24724b530", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3912.json b/mne-python/source/doc/sphinxext/prs/3912.json new file mode 100644 index 0000000000000000000000000000000000000000..a576b001cf1a54333f866026f525f1a7395327be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3912.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "06697e3f4926f59f1170a0dfbdcb1d6189c5bd4c", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3913.json b/mne-python/source/doc/sphinxext/prs/3913.json new file mode 100644 index 0000000000000000000000000000000000000000..88e17c3c1ed71a0fe43540f93e92877749e75fd8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3913.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b23d87371da5970c79f2d8b031af6071efef8482", + "authors": [ + { + "n": "Jon Houck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/label.py": { + "a": 5, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3918.json b/mne-python/source/doc/sphinxext/prs/3918.json new file mode 100644 index 0000000000000000000000000000000000000000..beb526b049e955887a0bd9044245e6dce6c2b80f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3918.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5fd78c159cf442853308393e774086367efdff27", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 0, + "d": 10 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 25, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3920.json b/mne-python/source/doc/sphinxext/prs/3920.json new file mode 100644 index 0000000000000000000000000000000000000000..81ec0ed99ee0bc0cb0cbca9111af0d3a6727a8a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3920.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b3b04811d1c7412e00b47e86d4126dad4843397c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 63, + "d": 32 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/raw.py": { + "a": 3, + "d": 4 + }, + "mne/simulation/tests/test_raw.py": { + "a": 4, + "d": 8 + }, + "mne/tests/test_chpi.py": { + "a": 167, + "d": 27 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3922.json b/mne-python/source/doc/sphinxext/prs/3922.json new file mode 100644 index 0000000000000000000000000000000000000000..6c81bf2cea9c12bdea00106d4b2b6dc7c454f80a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3922.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "86777861f193d25d8c717bc01b7de048671554d1", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/ctf/info.py": { + "a": 14, + "d": 2 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 17, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3923.json b/mne-python/source/doc/sphinxext/prs/3923.json new file mode 100644 index 0000000000000000000000000000000000000000..83ccdab209f3b8c501608fbc5aa2fcf17736c6c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3923.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "ef6b1063b642af19c08221923dc7679e5a865650", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/manual/datasets_index.rst": { + "a": 20, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 14, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 5, + "d": 1 + }, + "examples/decoding/decoding_rsa.py": { + "a": 180, + "d": 0 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 4, + "d": 4 + }, + "mne/epochs.py": { + "a": 7, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3924.json b/mne-python/source/doc/sphinxext/prs/3924.json new file mode 100644 index 0000000000000000000000000000000000000000..44af9a0862da502dab3b23aedafc1c8cc7731b6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3924.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f255803a30b153b217b6ad335a4c159fbf00f194", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3927.json b/mne-python/source/doc/sphinxext/prs/3927.json new file mode 100644 index 0000000000000000000000000000000000000000..a2f456b3aa28b2e015a1c60d50de8aeed18ca969 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3927.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7f725beb32c5fb2bc05c416f74967d9bb2f3e98b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3929.json b/mne-python/source/doc/sphinxext/prs/3929.json new file mode 100644 index 0000000000000000000000000000000000000000..2dbd8aacbc68c89410a597f5a2ca14499c59c597 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3929.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "883a276f417e8df6e31d9db6eb3ab6e838daf270", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 18, + "d": 11 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/393.json b/mne-python/source/doc/sphinxext/prs/393.json new file mode 100644 index 0000000000000000000000000000000000000000..120372c9ae2a413d72481417f864f37cc2c5eb7c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/393.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "1a39aaa4d1510abc2c37e98b9c39d0611e628b5a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 7, + "d": 0 + }, + "doc/source/getting_started.rst": { + "a": 27, + "d": 0 + }, + "doc/source/python_reference.rst": { + "a": 13, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 6, + "d": 1 + }, + "mne/cuda.py": { + "a": 386, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 9 + }, + "mne/fiff/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 51, + "d": 62 + }, + "mne/filter.py": { + "a": 373, + "d": 144 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 5 + }, + "mne/tests/test_filter.py": { + "a": 59, + "d": 6 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 4, + "d": 1 + }, + "mne/utils.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3931.json b/mne-python/source/doc/sphinxext/prs/3931.json new file mode 100644 index 0000000000000000000000000000000000000000..46d3c3d5c8767eb6003dd5d7065ec2d05cec2f0f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3931.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "83b9cedc1d460a20dc20ca9e84f29da01e26c762", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 4, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3935.json b/mne-python/source/doc/sphinxext/prs/3935.json new file mode 100644 index 0000000000000000000000000000000000000000..dad0e578508e368b19bee2aed500e26f46b42094 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3935.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4f948fa379b832b48e9c33af2fb458b27a173f32", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/mne_coreg.py": { + "a": 13, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 17, + "d": 4 + }, + "mne/gui/_coreg_gui.py": { + "a": 80, + "d": 65 + }, + "mne/gui/_file_traits.py": { + "a": 3, + "d": 4 + }, + "mne/gui/_viewer.py": { + "a": 7, + "d": 7 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 43, + "d": 35 + }, + "mne/surface.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3936.json b/mne-python/source/doc/sphinxext/prs/3936.json new file mode 100644 index 0000000000000000000000000000000000000000..afa0c41734478f8c01988e39bc0f0eda2b56cc33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3936.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "1241392f40554b7523a28ccc36cd9d991a72c65c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 2 + }, + "examples/visualization/plot_warp_surfaces.py": { + "a": 0, + "d": 83 + }, + "mne/source_space.py": { + "a": 74, + "d": 62 + }, + "mne/surface.py": { + "a": 5, + "d": 8 + }, + "mne/tests/test_source_space.py": { + "a": 30, + "d": 40 + }, + "mne/tests/test_transforms.py": { + "a": 7, + "d": 3 + }, + "mne/transforms.py": { + "a": 37, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3937.json b/mne-python/source/doc/sphinxext/prs/3937.json new file mode 100644 index 0000000000000000000000000000000000000000..e9af3d5c0529b4e1af3686c585db0689132d1fd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3937.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7d653f91d9cc3661dc7a27f411df457fd3b1ebeb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/__init__.py": { + "a": 18, + "d": 5 + }, + "mne/gui/_coreg_gui.py": { + "a": 89, + "d": 71 + }, + "mne/gui/_fiducials_gui.py": { + "a": 11, + "d": 8 + }, + "mne/gui/_file_traits.py": { + "a": 12, + "d": 8 + }, + "mne/utils.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3940.json b/mne-python/source/doc/sphinxext/prs/3940.json new file mode 100644 index 0000000000000000000000000000000000000000..e55c505bae7ea980c02a6176d409af1bfb1535b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3940.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d568dcd1254410739a06b9a9852814fbc9ffe35f", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 0, + "d": 5 + }, + "mne/gui/_viewer.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3941.json b/mne-python/source/doc/sphinxext/prs/3941.json new file mode 100644 index 0000000000000000000000000000000000000000..e0dbde7701581055ae158a79eeddcd66647b42a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3941.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7f780890efefa6bcfb151ac5f76f7d3ed907b3e4", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 3, + "d": 10 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 4, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3942.json b/mne-python/source/doc/sphinxext/prs/3942.json new file mode 100644 index 0000000000000000000000000000000000000000..f130219c93e83f087e6258555abf7da3f6f5df4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3942.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f7e4051b97ff36f855cca38ed4889301d837c0c1", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 2, + "d": 2 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 0, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3943.json b/mne-python/source/doc/sphinxext/prs/3943.json new file mode 100644 index 0000000000000000000000000000000000000000..5c8c6175c6e301e01809de658463bd0b495c3e00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3943.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7e0b06d3f0492c51a3b1c5591ddb5e3e0c5083b2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/forward/plot_left_cerebellum_volume_source.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3944.json b/mne-python/source/doc/sphinxext/prs/3944.json new file mode 100644 index 0000000000000000000000000000000000000000..21296b9479acd02f2d3cd0af0ce5aa37ac6da1ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3944.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "86fbb24595382b695904e608948239de824cd6e4", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_raw.py": { + "a": 6, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3946.json b/mne-python/source/doc/sphinxext/prs/3946.json new file mode 100644 index 0000000000000000000000000000000000000000..5ce6a22dc2591535eb37650a33e7fcf33ab856b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3946.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "117696c20f1fbf9a60015602c48373dccd7b3e9b", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/annotations.py": { + "a": 16, + "d": 6 + }, + "mne/io/base.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 21, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 15, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3947.json b/mne-python/source/doc/sphinxext/prs/3947.json new file mode 100644 index 0000000000000000000000000000000000000000..9bd15d04d650b5c140b3c6c15c90de50492d4dec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3947.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e08029c2211807e8b4c2531268918a1e6a7898aa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 4, + "d": 4 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3948.json b/mne-python/source/doc/sphinxext/prs/3948.json new file mode 100644 index 0000000000000000000000000000000000000000..df68960704a04e4247c5ca32360af4fe93eac6dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3948.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "4f677bcc08befee58666ea8c6d5bf75a5e37ddda", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/commands/mne_coreg.py": { + "a": 17, + "d": 4 + }, + "mne/gui/__init__.py": { + "a": 48, + "d": 22 + }, + "mne/gui/_backend.py": { + "a": 7, + "d": 0 + }, + "mne/gui/_coreg_gui.py": { + "a": 36, + "d": 20 + }, + "mne/gui/_file_traits.py": { + "a": 5, + "d": 3 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 61, + "d": 13 + }, + "mne/gui/_marker_gui.py": { + "a": 3, + "d": 6 + }, + "mne/gui/_viewer.py": { + "a": 6, + "d": 15 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 45, + "d": 25 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 4, + "d": 1 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 5, + "d": 3 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 26, + "d": 3 + }, + "mne/utils.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3949.json b/mne-python/source/doc/sphinxext/prs/3949.json new file mode 100644 index 0000000000000000000000000000000000000000..019315d0fa48d1ac112834a324ec5e073ec2dbff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3949.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "bbfdb076e00727cbdd5aae6ced190c4a853dfdaf", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/decoding/decoding_rsa.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 16, + "d": 17 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 6, + "d": 4 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 9, + "d": 7 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 9, + "d": 8 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 15, + "d": 14 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 50, + "d": 21 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 135, + "d": 38 + }, + "mne/decoding/tests/test_base.py": { + "a": 129, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3950.json b/mne-python/source/doc/sphinxext/prs/3950.json new file mode 100644 index 0000000000000000000000000000000000000000..b0a279af373c0d0c1ccc14aa9dab2d51a3a44540 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3950.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8d95b2c3b9df9d27c6d41430b3f3d5c07c9363bd", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 19, + "d": 8 + }, + "mne/utils.py": { + "a": 13, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3954.json b/mne-python/source/doc/sphinxext/prs/3954.json new file mode 100644 index 0000000000000000000000000000000000000000..25de3526af9ba6e38914b5d3317d8e5c9e7d6385 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3954.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4c7a243bc8a91c1f4c968287694d89899f6636bf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/proj.py": { + "a": 10, + "d": 7 + }, + "mne/tests/test_proj.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3955.json b/mne-python/source/doc/sphinxext/prs/3955.json new file mode 100644 index 0000000000000000000000000000000000000000..c75e7228968cffe19b940c91422b1159f30e516d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3955.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "210852aacf73f4da8e9a38cedf0f900f18a8bfcf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 16, + "d": 16 + }, + "mne/io/proj.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3958.json b/mne-python/source/doc/sphinxext/prs/3958.json new file mode 100644 index 0000000000000000000000000000000000000000..b5e9c707d6b84dd9603dfa0561247a10fee0e0fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3958.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "07c47b90e4590d0ff8077b0e88c2c553e8c326ff", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 28, + "d": 14 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 68, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3959.json b/mne-python/source/doc/sphinxext/prs/3959.json new file mode 100644 index 0000000000000000000000000000000000000000..231dce5d035321dafb461e2af0bca3d535d5779b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3959.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "50983c9dc5f4866c094d2e58ced0f8c88044ef14", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 4, + "d": 4 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 56, + "d": 37 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/396.json b/mne-python/source/doc/sphinxext/prs/396.json new file mode 100644 index 0000000000000000000000000000000000000000..d8fc4bf1ccec0e718f8e60c20f83654c1b505ef7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/396.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1c869fe4b99a4a9b07b8702ab2d3da2e93608a2f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/channels.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3962.json b/mne-python/source/doc/sphinxext/prs/3962.json new file mode 100644 index 0000000000000000000000000000000000000000..82b4c40355a42a5b33f1e7043791ae79f1b2da9e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3962.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "071d8a20fd7d39371b0b67c070a79f968b8ccd1e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 69, + "d": 54 + }, + "mne/io/bti/read.py": { + "a": 8, + "d": 0 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3964.json b/mne-python/source/doc/sphinxext/prs/3964.json new file mode 100644 index 0000000000000000000000000000000000000000..b5ed3989614a6dae665d38b93d17012ef8794cc3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3964.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "af2b41e0272c681ad7a7b34ee3c3377f72e68cd7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "doc/cited.rst": { + "a": 193, + "d": 110 + }, + "doc/sphinxext/cited_mne.py": { + "a": 12, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3965.json b/mne-python/source/doc/sphinxext/prs/3965.json new file mode 100644 index 0000000000000000000000000000000000000000..052cd754d37a9a70ef1284965441b46e45e8fa79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3965.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f1490275d16886b877c52cd1ca65524344ba2bba", + "authors": [ + { + "n": "Cristóbal Moënne-Loccoz", + "e": null + } + ], + "changes": { + "mne/io/pick.py": { + "a": 5, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3966.json b/mne-python/source/doc/sphinxext/prs/3966.json new file mode 100644 index 0000000000000000000000000000000000000000..278f2d3cc0dd122be9b04d698a1d4ea96d284d36 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3966.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "ec164a09e92b3faf998d5c32dd5ed0343b72edfb", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 2 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 85, + "d": 18 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 325, + "d": 15 + }, + "mne/viz/tests/test_3d.py": { + "a": 26, + "d": 1 + }, + "tutorials/plot_dipole_fit.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3967.json b/mne-python/source/doc/sphinxext/prs/3967.json new file mode 100644 index 0000000000000000000000000000000000000000..efc000a9ac6d43f8b0b8a20f2929c5985f5a8cbf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3967.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "baffd5af53612d2d06abbfe12675c05e869491d8", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 86, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3968.json b/mne-python/source/doc/sphinxext/prs/3968.json new file mode 100644 index 0000000000000000000000000000000000000000..8ae25d6779b11390f6a81553013b913117f71033 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3968.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3fa4664534a249c9fb5dd72c131d7b768d193893", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/397.json b/mne-python/source/doc/sphinxext/prs/397.json new file mode 100644 index 0000000000000000000000000000000000000000..c1496b6d4019ced314d57659e7fa743bb17d04dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/397.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c4f77855e6d132cd8b642eacf6e899433161d90e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_viz.py": { + "a": 149, + "d": 8 + }, + "mne/viz.py": { + "a": 10, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3972.json b/mne-python/source/doc/sphinxext/prs/3972.json new file mode 100644 index 0000000000000000000000000000000000000000..64092574c484e74cdd7bd680e727fb1476bb01c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3972.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "296154c3403532d131506bddd1d8f0a60cb4b562", + "authors": [ + { + "n": "Jakub Kaczmarzyk", + "e": "jakub.kaczmarzyk@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 12, + "d": 1 + }, + "mne/evoked.py": { + "a": 11, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 11, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 0 + }, + "tutorials/plot_creating_data_structures.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3973.json b/mne-python/source/doc/sphinxext/prs/3973.json new file mode 100644 index 0000000000000000000000000000000000000000..a945f27c24675db55455213a4de139ce127448a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3973.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ca463521216d4cdefc81a0be50cb99a7b02ed268", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 0, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3975.json b/mne-python/source/doc/sphinxext/prs/3975.json new file mode 100644 index 0000000000000000000000000000000000000000..b56e5c1a8192f45991514b1a767189a6fffe39d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3975.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "2c6d6faeaa38805b20249d966f0ec2dd8950843b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/cited.rst": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/cited_mne.py": { + "a": 3, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 15, + "d": 16 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 31, + "d": 23 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 4, + "d": 16 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 18, + "d": 18 + }, + "mne/report.py": { + "a": 3, + "d": 2 + }, + "mne/source_space.py": { + "a": 49, + "d": 0 + }, + "mne/utils.py": { + "a": 12, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 127, + "d": 76 + }, + "mne/viz/tests/test_3d.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3977.json b/mne-python/source/doc/sphinxext/prs/3977.json new file mode 100644 index 0000000000000000000000000000000000000000..2e4e6b8806179e0c67d33ab83478f64d949d592f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3977.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "1e3f0b7f193fe370dd4c69d37c4779c5e0c5e877", + "authors": [ + { + "n": "Martin", + "e": "mperezguevara@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 11, + "d": 3 + }, + "mne/channels/layout.py": { + "a": 19, + "d": 6 + }, + "mne/io/array/tests/test_array.py": { + "a": 17, + "d": 1 + }, + "mne/transforms.py": { + "a": 9, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 35, + "d": 34 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 6, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 18, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 22, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3980.json b/mne-python/source/doc/sphinxext/prs/3980.json new file mode 100644 index 0000000000000000000000000000000000000000..155aa8984881153c1024a06e7de072c4c68edc40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3980.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bba62a5e3b2d71ef0027e91fe1ba9530cc653e27", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 5, + "d": 5 + }, + "appveyor.yml": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3982.json b/mne-python/source/doc/sphinxext/prs/3982.json new file mode 100644 index 0000000000000000000000000000000000000000..1ed28ec2882113eb14b673831b71dbe9f242612b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3982.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "78191cd1f9ee4a9ae3c357f5863b2a2ed1824da6", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3983.json b/mne-python/source/doc/sphinxext/prs/3983.json new file mode 100644 index 0000000000000000000000000000000000000000..22e6e7b7824c040cae0354352ba8fbfd1b182ac9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3983.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "dc0967552dc7f4f5c9a5e265da6b2ea754a139b7", + "authors": [ + { + "n": "Matt Boggess", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 53, + "d": 5 + }, + "mne/channels/tests/test_montage.py": { + "a": 41, + "d": 3 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3984.json b/mne-python/source/doc/sphinxext/prs/3984.json new file mode 100644 index 0000000000000000000000000000000000000000..81b8b92fc576056a131e4948dcbe8ffb21ef3223 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3984.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a1f3b8f2b5978b7421e0da3787bee92e469d6bd5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "setup.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3986.json b/mne-python/source/doc/sphinxext/prs/3986.json new file mode 100644 index 0000000000000000000000000000000000000000..3de2c08670575c715f3dfe6a18c0087771ae2b75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3986.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0c31b1e248bea43343bded9b7fa0e2d7aa664210", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 106, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 94, + "d": 133 + }, + "mne/simulation/tests/test_raw.py": { + "a": 11, + "d": 15 + }, + "mne/tests/test_filter.py": { + "a": 20, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3989.json b/mne-python/source/doc/sphinxext/prs/3989.json new file mode 100644 index 0000000000000000000000000000000000000000..ecbb60648e6e55e6d18bb90154540a533f6151b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3989.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "25e6dfa4d933b637ec0e60908976787a88191114", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 11 + }, + "mne/forward/_lead_dots.py": { + "a": 2, + "d": 38 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 13, + "d": 17 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 7, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/399.json b/mne-python/source/doc/sphinxext/prs/399.json new file mode 100644 index 0000000000000000000000000000000000000000..fbcbf18131cbe82753830d59220c9ce121da0339 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/399.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "013d3bec907ac52270304e05598aef423ca90177", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cuda.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3991.json b/mne-python/source/doc/sphinxext/prs/3991.json new file mode 100644 index 0000000000000000000000000000000000000000..694d3f73eabaaa7a7c1e473d31fb3bfd4d4bb5b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3991.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "d136b9ac808dc65f1ffbbc3e6ef7b050f5ef0c84", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_meg_sensors.py": { + "a": 8, + "d": 1 + }, + "mne/commands/mne_coreg.py": { + "a": 3, + "d": 0 + }, + "mne/coreg.py": { + "a": 1, + "d": 0 + }, + "mne/defaults.py": { + "a": 18, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 4, + "d": 2 + }, + "mne/gui/_coreg_gui.py": { + "a": 115, + "d": 34 + }, + "mne/gui/_fiducials_gui.py": { + "a": 6, + "d": 3 + }, + "mne/gui/_file_traits.py": { + "a": 50, + "d": 25 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 6, + "d": 5 + }, + "mne/gui/_marker_gui.py": { + "a": 6, + "d": 3 + }, + "mne/gui/_viewer.py": { + "a": 73, + "d": 79 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 3, + "d": 3 + }, + "mne/surface.py": { + "a": 3, + "d": 1 + }, + "mne/utils.py": { + "a": 12, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 79, + "d": 41 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3993.json b/mne-python/source/doc/sphinxext/prs/3993.json new file mode 100644 index 0000000000000000000000000000000000000000..ee12dff8893e4cfdfb3da991d35f87140397d9b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3993.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "2beb31277d5c09c2c0b80bed624773f40bd529b1", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 98, + "d": 5 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 15, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 31, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3994.json b/mne-python/source/doc/sphinxext/prs/3994.json new file mode 100644 index 0000000000000000000000000000000000000000..a719cbc4ac2c31f796d4150e2c3c4ccdfa1e72f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3994.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "11826686eeb84572fa84883abcc3901ca721b166", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 10, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3995.json b/mne-python/source/doc/sphinxext/prs/3995.json new file mode 100644 index 0000000000000000000000000000000000000000..0e595524dc707c73c5c3d2d70a88c127c47d1928 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3995.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "670bc2862bdea5a92fd8a5f874f457cfcbaaf7df", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_rap_music.py": { + "a": 12, + "d": 3 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/3999.json b/mne-python/source/doc/sphinxext/prs/3999.json new file mode 100644 index 0000000000000000000000000000000000000000..d6b5f199eeb78c9f06f757e7846c4ae35a82236b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/3999.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b1786b2750b68b8d1d8501b3d2ae60ec40cb6d51", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/defaults.py": { + "a": 2, + "d": 0 + }, + "mne/gui/_fiducials_gui.py": { + "a": 9, + "d": 3 + }, + "mne/gui/_file_traits.py": { + "a": 4, + "d": 10 + }, + "mne/viz/_3d.py": { + "a": 84, + "d": 27 + }, + "mne/viz/tests/test_3d.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4.json b/mne-python/source/doc/sphinxext/prs/4.json new file mode 100644 index 0000000000000000000000000000000000000000..53cb6249b71b89d3c6ce30a836d2d97e4f34e94b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4b2ebd3fb53294bcd52c822cbaa0d0a9f3a99de3", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/40.json b/mne-python/source/doc/sphinxext/prs/40.json new file mode 100644 index 0000000000000000000000000000000000000000..e74109bfd725d0867dbd50e453e85de974770e1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/40.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "0bd6816104cc7e38ca6c97a7a22d34f005fadcf7", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 45, + "d": 90 + }, + "bin/mne_compute_proj_eog.py": { + "a": 157, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing.py": { + "a": 0, + "d": 59 + }, + "mne/preprocessing/__init__.py": { + "a": 10, + "d": 0 + }, + "mne/preprocessing/maxfilter.py": { + "a": 268, + "d": 0 + }, + "mne/preprocessing/ssp.py": { + "a": 313, + "d": 0 + }, + "mne/preprocessing/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 35, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/400.json b/mne-python/source/doc/sphinxext/prs/400.json new file mode 100644 index 0000000000000000000000000000000000000000..b15648b3786954671a6d903320944850c389429f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/400.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6f1c35b7ddb7c10bbae9cede4b3456889e6202b6", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 0, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4003.json b/mne-python/source/doc/sphinxext/prs/4003.json new file mode 100644 index 0000000000000000000000000000000000000000..f1b1ab04644872a89abd0fb583bfd7bac4b78551 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4003.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9e4ac8a4670b3906c9c9dea5acd574bdd318c85a", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 41, + "d": 24 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4004.json b/mne-python/source/doc/sphinxext/prs/4004.json new file mode 100644 index 0000000000000000000000000000000000000000..71c9789c15094854ed94a538945fd04eabfb1763 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4004.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "18a02e81fd9ededfa7e34a1147940d36e56a3846", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 9, + "d": 13 + }, + "mne/io/reference.py": { + "a": 86, + "d": 29 + }, + "mne/io/tests/test_reference.py": { + "a": 58, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4005.json b/mne-python/source/doc/sphinxext/prs/4005.json new file mode 100644 index 0000000000000000000000000000000000000000..cc5d0771675ec43a61b2e3ed6374f122391fd8f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4005.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e75afaded3f43e06ea6ccdbe623bc5faaf6cf0c9", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 19, + "d": 4 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/gui/_coreg_gui.py": { + "a": 50, + "d": 19 + }, + "mne/gui/_fiducials_gui.py": { + "a": 9, + "d": 2 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 14, + "d": 8 + }, + "mne/utils.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4006.json b/mne-python/source/doc/sphinxext/prs/4006.json new file mode 100644 index 0000000000000000000000000000000000000000..b2991164af755b68daea0a9553f22b4dcf37676f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4006.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5fa5f29ae9f7349dd6b0abffb5de82feb31290d2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 8, + "d": 4 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/raw.py": { + "a": 18, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4007.json b/mne-python/source/doc/sphinxext/prs/4007.json new file mode 100644 index 0000000000000000000000000000000000000000..8f0fe364d1f9ceb957406e726fcad70ee0ed2d83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4007.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "862a5c93e132557a305b067f10da4b8c3bbfbfc8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 172 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 8, + "d": 9 + }, + "mne/decoding/transformer.py": { + "a": 13, + "d": 3 + }, + "mne/externals/__init__.py": { + "a": 4, + "d": 3 + }, + "mne/externals/funcsigs.py": { + "a": 815, + "d": 0 + }, + "mne/fixes.py": { + "a": 127, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4009.json b/mne-python/source/doc/sphinxext/prs/4009.json new file mode 100644 index 0000000000000000000000000000000000000000..bc438c4a7850b3b77d94601829854de43be144fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4009.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "c59903d7b1ca6087b3417887b60e99b35c1d7cf5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 21, + "d": 36 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 3 + }, + "mne/evoked.py": { + "a": 12, + "d": 0 + }, + "mne/filter.py": { + "a": 4, + "d": 11 + }, + "mne/io/proj.py": { + "a": 3, + "d": 4 + }, + "mne/io/reference.py": { + "a": 8, + "d": 20 + }, + "mne/io/tests/test_reference.py": { + "a": 3, + "d": 7 + }, + "mne/preprocessing/stim.py": { + "a": 2, + "d": 10 + }, + "mne/stats/regression.py": { + "a": 2, + "d": 5 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 11, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4010.json b/mne-python/source/doc/sphinxext/prs/4010.json new file mode 100644 index 0000000000000000000000000000000000000000..e8163ae3949fbd8abe64754c61ea7eaa35e5ebe7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4010.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d94aee0c4f2143af435effc829e28fd20e2e8e76", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 15, + "d": 16 + }, + "mne/coreg.py": { + "a": 3, + "d": 3 + }, + "mne/source_space.py": { + "a": 8, + "d": 49 + }, + "mne/surface.py": { + "a": 60, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4013.json b/mne-python/source/doc/sphinxext/prs/4013.json new file mode 100644 index 0000000000000000000000000000000000000000..e738025eacdfeb0be783dd41a173759cb1d8a29b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4013.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "25993fa6531a81c4246f4f0203686bd3d9d8b79c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_kit2fiff_gui.py": { + "a": 5, + "d": 0 + }, + "mne/gui/_marker_gui.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4014.json b/mne-python/source/doc/sphinxext/prs/4014.json new file mode 100644 index 0000000000000000000000000000000000000000..339f28486b9c90fa8c72fbb09076797dac2f45d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4014.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6bb8995be480f2a888242890c97f9bb83806794b", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4015.json b/mne-python/source/doc/sphinxext/prs/4015.json new file mode 100644 index 0000000000000000000000000000000000000000..92669e428117730d2888cba6d31b61459a4245af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4015.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a547bb6105c9af646d5d3a326e5397d61d1e3c89", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 8, + "d": 3 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4017.json b/mne-python/source/doc/sphinxext/prs/4017.json new file mode 100644 index 0000000000000000000000000000000000000000..8a2f5a4e3a06ecb184e84bc61072b1b83b5140b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4017.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "7cbd69caa638bb308c72eafe590b9c00cedfd21d", + "authors": [ + { + "n": "ramonapariciog", + "e": "moncho_apa@hotmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 22, + "d": 33 + }, + "mne/io/egi/egimff.py": { + "a": 393, + "d": 0 + }, + "mne/io/egi/events.py": { + "a": 162, + "d": 0 + }, + "mne/io/egi/general.py": { + "a": 155, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 38, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4018.json b/mne-python/source/doc/sphinxext/prs/4018.json new file mode 100644 index 0000000000000000000000000000000000000000..9ac99afe8519a31f4201b7222d6f6bdcb902109b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4018.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "2c17b8f6e587326d32845f0318e42661cee06d50", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_sensor_noise_level.py": { + "a": 30, + "d": 0 + }, + "mne/io/base.py": { + "a": 8, + "d": 9 + }, + "mne/viz/epochs.py": { + "a": 8, + "d": 11 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 75, + "d": 40 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 4, + "d": 4 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 0, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4020.json b/mne-python/source/doc/sphinxext/prs/4020.json new file mode 100644 index 0000000000000000000000000000000000000000..a915fbf631984770c817245b98293c1b89d73a7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4020.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "214ba4135685fba881f25345ff29231a8a301ced", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 8, + "d": 6 + }, + "mne/io/base.py": { + "a": 4, + "d": 4 + }, + "mne/io/fiff/raw.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_annotations.py": { + "a": 8, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 59, + "d": 55 + }, + "mne/viz/utils.py": { + "a": 21, + "d": 23 + }, + "tutorials/plot_visualize_raw.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4022.json b/mne-python/source/doc/sphinxext/prs/4022.json new file mode 100644 index 0000000000000000000000000000000000000000..fafa62d8ddf5f15925cddda845970f7da0ee4713 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4022.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2a1022a08c550f3c56c4e7e2eb61e433ed57bc3c", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/fixes.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4023.json b/mne-python/source/doc/sphinxext/prs/4023.json new file mode 100644 index 0000000000000000000000000000000000000000..6aa9e2de5cbc6f5b7e429ebb421af574aa5dc79d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4023.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "e0bca2f7d1d791201aa588b622778ce18f53e241", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 25, + "d": 26 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 0 + }, + "mne/gui/_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 17, + "d": 17 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/maxwell.py": { + "a": 6, + "d": 8 + }, + "mne/stats/permutations.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 9, + "d": 4 + }, + "mne/time_frequency/multitaper.py": { + "a": 5, + "d": 10 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 0, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 7 + }, + "setup.cfg": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4024.json b/mne-python/source/doc/sphinxext/prs/4024.json new file mode 100644 index 0000000000000000000000000000000000000000..88dadf6931c42ad53649ad9a58369f6070346269 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4024.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "af290944ce3c0b164b92d96f9861823db149f2f2", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 4, + "d": 6 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4025.json b/mne-python/source/doc/sphinxext/prs/4025.json new file mode 100644 index 0000000000000000000000000000000000000000..48e9e9c56a9da6b3930a463213dd70594a9a3873 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4025.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e9be0d3784e0e44e2e8450fafcda413331f5e80d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/manual/decoding.rst": { + "a": 5, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 3 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 48, + "d": 24 + }, + "mne/decoding/transformer.py": { + "a": 113, + "d": 83 + }, + "mne/utils.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4029.json b/mne-python/source/doc/sphinxext/prs/4029.json new file mode 100644 index 0000000000000000000000000000000000000000..6c440b98a123877699bb027e568b08f1f52108bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4029.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8c88601b261e9b7fa77e4d6cf724214f7a75862e", + "authors": [ + { + "n": "Lorenz Esch", + "e": null + } + ], + "changes": { + "doc/mne_cpp.rst": { + "a": 19, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/403.json b/mne-python/source/doc/sphinxext/prs/403.json new file mode 100644 index 0000000000000000000000000000000000000000..96746a378fb1e2beb697675c2e14ef80cfd01685 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/403.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ceb4dc25c96f87034bf2555c3f935d80fcc39768", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 16, + "d": 8 + }, + "mne/epochs.py": { + "a": 12, + "d": 6 + }, + "mne/fiff/pick.py": { + "a": 1, + "d": 2 + }, + "mne/forward.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 9, + "d": 2 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4030.json b/mne-python/source/doc/sphinxext/prs/4030.json new file mode 100644 index 0000000000000000000000000000000000000000..0eb45d28dfca5a69a015b3c6376131581c34049a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4030.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "60a80b77b557d4963de2bd45040b959593bb5043", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 2 + }, + "examples/preprocessing/plot_head_positions.py": { + "a": 31, + "d": 0 + }, + "examples/preprocessing/plot_movement_compensation.py": { + "a": 6, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 91, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 17, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4031.json b/mne-python/source/doc/sphinxext/prs/4031.json new file mode 100644 index 0000000000000000000000000000000000000000..fb394f6ee5c2a2e9fdd4374031c6111ae7a7d0c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4031.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "8b1087a9574c46185a921e4006a6735122e9edbf", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 46, + "d": 14 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 5 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4040.json b/mne-python/source/doc/sphinxext/prs/4040.json new file mode 100644 index 0000000000000000000000000000000000000000..1c10b1bf2b266b504d264814e35f735e642f1446 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4040.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "85b7374f31b656111e8f7201495682cb021fb339", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/viz/topo.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4042.json b/mne-python/source/doc/sphinxext/prs/4042.json new file mode 100644 index 0000000000000000000000000000000000000000..b2bee255bd2b2d210cdaac0023e13e79e30f92d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4042.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7bdeaf5a72865506195c773e64b7111ec95edbac", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_topo_compare_conditions.py": { + "a": 0, + "d": 5 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 10, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 21, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4043.json b/mne-python/source/doc/sphinxext/prs/4043.json new file mode 100644 index 0000000000000000000000000000000000000000..464f10bd83d24c5ccbcd48b4a2ba033a56571cbd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4043.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e657529827b878d7210c70d9f72cebcb18197971", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 173, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4046.json b/mne-python/source/doc/sphinxext/prs/4046.json new file mode 100644 index 0000000000000000000000000000000000000000..82b44857f4d898474af1ed70a79d90a1164ef2e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4046.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ce9364bfccbbf83522f0dfe2c9498bcfece152ca", + "authors": [ + { + "n": "akshay0724", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 1, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4047.json b/mne-python/source/doc/sphinxext/prs/4047.json new file mode 100644 index 0000000000000000000000000000000000000000..877b07eb1dfa6101b3273fbf7ce84a379293a875 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4047.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "384ab09e6c4ebb07596c4cfa27821b1a25a7c05f", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/evoked.py": { + "a": 24, + "d": 7 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4048.json b/mne-python/source/doc/sphinxext/prs/4048.json new file mode 100644 index 0000000000000000000000000000000000000000..8c8d2f4882b2c7f7cf721505ad95ca9d1166b4f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4048.json @@ -0,0 +1,223 @@ +{ + "merge_commit_sha": "b3021dd7f974734da1bd4741f9c50ae90cb81041", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 4, + "d": 4 + }, + "mne/bem.py": { + "a": 9, + "d": 9 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 4 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 3, + "d": 3 + }, + "mne/chpi.py": { + "a": 4, + "d": 4 + }, + "mne/connectivity/spectral.py": { + "a": 3, + "d": 3 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/megsim/urls.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/time_gen.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 3, + "d": 3 + }, + "mne/epochs.py": { + "a": 7, + "d": 7 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 4, + "d": 4 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_lead_dots.py": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 2, + "d": 2 + }, + "mne/label.py": { + "a": 4, + "d": 4 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/mockclient.py": { + "a": 5, + "d": 5 + }, + "mne/report.py": { + "a": 2, + "d": 2 + }, + "mne/selection.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 3, + "d": 3 + }, + "mne/stats/parametric.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 15, + "d": 15 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/decoding.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 51, + "d": 51 + }, + "setup.cfg": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/405.json b/mne-python/source/doc/sphinxext/prs/405.json new file mode 100644 index 0000000000000000000000000000000000000000..463a04cec3a8d709fc0e0af9dc9aab6824add89e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/405.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "05f845c12adb0f415b3684663f5d17f1b55320cd", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/filter.py": { + "a": 16, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4052.json b/mne-python/source/doc/sphinxext/prs/4052.json new file mode 100644 index 0000000000000000000000000000000000000000..7ac1c2a5e1af11ae95f54bcf1eb85fbc96d7b136 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4052.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8eb11aa31e5b8e342f3909f4ba9836b822643ea0", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4057.json b/mne-python/source/doc/sphinxext/prs/4057.json new file mode 100644 index 0000000000000000000000000000000000000000..7183b7eb0592b2dd5f8cc859433d7da5b6abd69b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4057.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e983e93cf915312ca027d08c5fa54b443d0fceec", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 3, + "d": 0 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 4 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4058.json b/mne-python/source/doc/sphinxext/prs/4058.json new file mode 100644 index 0000000000000000000000000000000000000000..a510c1d1d44e88d767ffd3cbfeb2737da92e0b21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4058.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a5f0dc9f2f2571c08f75df4e4e92734f29cabbbc", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 7, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4061.json b/mne-python/source/doc/sphinxext/prs/4061.json new file mode 100644 index 0000000000000000000000000000000000000000..725d292061f8b63e63b771b23bf44ad48cac19f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4061.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4b0f362df04b21249faf6c9a2495c71c337a14a8", + "authors": [ + { + "n": "akshay0724", + "e": null + } + ], + "changes": { + "mne/decoding/transformer.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4062.json b/mne-python/source/doc/sphinxext/prs/4062.json new file mode 100644 index 0000000000000000000000000000000000000000..0c11748b31a24fce4f1c652631078c2bc5ae4954 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4062.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7b27c333e2b8409002302dbfa40b073c652fbf7a", + "authors": [ + { + "n": "Cristóbal Moënne-Loccoz", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4063.json b/mne-python/source/doc/sphinxext/prs/4063.json new file mode 100644 index 0000000000000000000000000000000000000000..57610b67a8b47848a1e38500bd5db6d51249fbac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4063.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5f2db6fbe84e77eda7c265d82d03f0740fb82069", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/topo.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4064.json b/mne-python/source/doc/sphinxext/prs/4064.json new file mode 100644 index 0000000000000000000000000000000000000000..e27eb842fb85ea6f0233e6def7c9f5b3e4ac6482 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4064.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "68c2d32fc915c5a730cc074a1cfff7b753fccde3", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4065.json b/mne-python/source/doc/sphinxext/prs/4065.json new file mode 100644 index 0000000000000000000000000000000000000000..f7c3885ae19ebcaa2b3b24f813847d0ad1ae37be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4065.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "56c637f271e03e70072e5c25f2dbbf91ac29dd19", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/commands/mne_kit2fiff.py": { + "a": 6, + "d": 0 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 13, + "d": 4 + }, + "mne/gui/_marker_gui.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4069.json b/mne-python/source/doc/sphinxext/prs/4069.json new file mode 100644 index 0000000000000000000000000000000000000000..9f114f623b51cf974756b32b6ac491d3c4591cfc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4069.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "395aff36c4adb512f49dbf87af5092a25ee0cf2e", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 451, + "d": 171 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 180, + "d": 14 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 56, + "d": 5 + }, + "mne/io/artemis123/utils.py": { + "a": 55, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 2 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 50, + "d": 6 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4071.json b/mne-python/source/doc/sphinxext/prs/4071.json new file mode 100644 index 0000000000000000000000000000000000000000..f4d484716b9e0bbbed72033defbcee47219a45bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4071.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bae9149e5fc14b5711191525ea96b19542ccfe62", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 28, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4074.json b/mne-python/source/doc/sphinxext/prs/4074.json new file mode 100644 index 0000000000000000000000000000000000000000..34c8717c6b9a34193bbc474812edded8362989fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4074.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "724eefccdc3fd085347be949799b8d1e44eb8f46", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4077.json b/mne-python/source/doc/sphinxext/prs/4077.json new file mode 100644 index 0000000000000000000000000000000000000000..0bb85b50d9cb0473602a202d056688121c37612c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4077.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d4a0f1c9b32f9b11e545a90680fbab08214b20dd", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 11, + "d": 2 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 14, + "d": 4 + }, + "mne/preprocessing/eog.py": { + "a": 15, + "d": 8 + }, + "mne/preprocessing/ica.py": { + "a": 53, + "d": 27 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4079.json b/mne-python/source/doc/sphinxext/prs/4079.json new file mode 100644 index 0000000000000000000000000000000000000000..655b59563035b818a346773da11d8d67c1743bd6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4079.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a2c5bb1e2e7a1adbf31df02b5fdb9eae2f39e207", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 13, + "d": 5 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4080.json b/mne-python/source/doc/sphinxext/prs/4080.json new file mode 100644 index 0000000000000000000000000000000000000000..c8565635cb32931e246af863870e6db55a408529 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4080.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "79b5da63d441a2008a1aae756bc9a7b776d0bc1e", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/bem.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4081.json b/mne-python/source/doc/sphinxext/prs/4081.json new file mode 100644 index 0000000000000000000000000000000000000000..e851283a311bc270bbcb3cf98ca9da972b839e10 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4081.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "db38c67918b19530219a18c30e93bd5b1b1eafad", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 5, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 94, + "d": 41 + }, + "mne/viz/tests/test_ica.py": { + "a": 6, + "d": 26 + }, + "mne/viz/tests/test_raw.py": { + "a": 34, + "d": 22 + }, + "mne/viz/utils.py": { + "a": 121, + "d": 13 + }, + "tutorials/plot_visualize_raw.py": { + "a": 18, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4082.json b/mne-python/source/doc/sphinxext/prs/4082.json new file mode 100644 index 0000000000000000000000000000000000000000..a03d799277ca680ffca3f48c14fbeb220132c6a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4082.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7d2ae7f33928dd6d8f612290579495aff3f3da3a", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 17, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4083.json b/mne-python/source/doc/sphinxext/prs/4083.json new file mode 100644 index 0000000000000000000000000000000000000000..bbf02283f3e0dfbbc10232f474fb669ee52e5c20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4083.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e5b0447baf2e0fe7d24fdcb1f11338257c89d33c", + "authors": [ + { + "n": "Steven Gutstein", + "e": null + } + ], + "changes": { + "mne/tests/test_report.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4084.json b/mne-python/source/doc/sphinxext/prs/4084.json new file mode 100644 index 0000000000000000000000000000000000000000..5f50ebbfff46f195bcf403d2abe27a2075854ffc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4084.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "96d8b48e4f9e989616beec897e642e5772cd590b", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 39, + "d": 5 + }, + "mne/io/reference.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4086.json b/mne-python/source/doc/sphinxext/prs/4086.json new file mode 100644 index 0000000000000000000000000000000000000000..6b79537e449f6452f14c8dc241f71ab2fe42aa90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4086.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6b16b7f4cea6fa6810d2ba7b132f02ba4b6b152d", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 7, + "d": 5 + }, + "mne/viz/_3d.py": { + "a": 264, + "d": 46 + }, + "mne/viz/tests/test_3d.py": { + "a": 34, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4088.json b/mne-python/source/doc/sphinxext/prs/4088.json new file mode 100644 index 0000000000000000000000000000000000000000..0e70b7fcb16b1ea703fe165008e7b0194e657e1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4088.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "52109930a4e483f3d325291c2e12cca9ff502c0b", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 115, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 18, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4089.json b/mne-python/source/doc/sphinxext/prs/4089.json new file mode 100644 index 0000000000000000000000000000000000000000..129b6506210a2194421f0b39070e866476857f99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4089.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b245cad2942873f6d0e1f78936cbf29a78d2e751", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 7, + "d": 0 + }, + "mne/io/reference.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/409.json b/mne-python/source/doc/sphinxext/prs/409.json new file mode 100644 index 0000000000000000000000000000000000000000..8ec600563e4d6026389b34e9342ff4fd1319a9ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/409.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8be43ab6f3a476b60cc5059ade85839af2c026aa", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4090.json b/mne-python/source/doc/sphinxext/prs/4090.json new file mode 100644 index 0000000000000000000000000000000000000000..dad2eb551e28eb1858aae09d557fba2a31291649 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4090.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "674e2cdf3bd128637c52e38c1f2e55cb0af3b95a", + "authors": [ + { + "n": "Matt Boggess", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 11, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4096.json b/mne-python/source/doc/sphinxext/prs/4096.json new file mode 100644 index 0000000000000000000000000000000000000000..cb9f2d974672e6e5d6a6743083ff63b73820fea9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4096.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "de4eb02405d4c80610f00cdb26d4cf0dbb4282de", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/commands/mne_show_fiff.py": { + "a": 12, + "d": 4 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 0 + }, + "mne/io/open.py": { + "a": 23, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4097.json b/mne-python/source/doc/sphinxext/prs/4097.json new file mode 100644 index 0000000000000000000000000000000000000000..5263af33a45bb7b8c874794de124b8eed531b64c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4097.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "12b329c9421376160055957ae88784ec639cbe33", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "doc/_static/favicon.ico": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4098.json b/mne-python/source/doc/sphinxext/prs/4098.json new file mode 100644 index 0000000000000000000000000000000000000000..fd294385b83710943c5bfdb392cea13813d7fc71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4098.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2aebcc4cde8601aa105a2b1d7fa6618763ef3bb5", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "examples/visualization/plot_3d_to_2d.py": { + "a": 120, + "d": 0 + }, + "examples/visualization/plot_clickable_image.py": { + "a": 0, + "d": 66 + }, + "mne/data/image/custom_layout.lout": { + "a": 23, + "d": 24 + }, + "mne/viz/utils.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4099.json b/mne-python/source/doc/sphinxext/prs/4099.json new file mode 100644 index 0000000000000000000000000000000000000000..97204794a1764db4970c0617e53568e7e53d5289 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4099.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7e15c0f5552aca66a10a3ca54d92a61bb3d781b9", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "examples/io/plot_read_events.py": { + "a": 77, + "d": 0 + }, + "examples/io/read_events.py": { + "a": 0, + "d": 31 + }, + "mne/event.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/41.json b/mne-python/source/doc/sphinxext/prs/41.json new file mode 100644 index 0000000000000000000000000000000000000000..eba675894bab5d3d85046dbd41d6ae65e5bad4a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/41.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "25f550f1586b339cedd203fff13921f02e84fe10", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/cov.py": { + "a": 2, + "d": 2 + }, + "mne/forward.py": { + "a": 6, + "d": 5 + }, + "mne/minimum_norm/inverse.py": { + "a": 37, + "d": 8 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/410.json b/mne-python/source/doc/sphinxext/prs/410.json new file mode 100644 index 0000000000000000000000000000000000000000..337857c55793b24518ac68cde25d85cede1ab345 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/410.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "badca76e57ce230c71cde14efef1169472a31039", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 24, + "d": 7 + }, + "mne/fiff/raw.py": { + "a": 34, + "d": 24 + }, + "mne/fiff/tag.py": { + "a": 80, + "d": 27 + }, + "mne/fiff/tests/test_raw.py": { + "a": 19, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4100.json b/mne-python/source/doc/sphinxext/prs/4100.json new file mode 100644 index 0000000000000000000000000000000000000000..16e030a2520f76f390514115ed819565c6c8c6a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4100.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d14d7b492cd8c7253e2b3216f1040491cb649de3", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "examples/decoding/decoding_rsa.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4103.json b/mne-python/source/doc/sphinxext/prs/4103.json new file mode 100644 index 0000000000000000000000000000000000000000..f86ed029228c449fc46991b95de4907099ad433b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4103.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "aa4e18940fbad7626c323502994141854f6879ba", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/manual/decoding.rst": { + "a": 38, + "d": 25 + }, + "doc/python_reference.rst": { + "a": 5, + "d": 5 + }, + "doc/whats_new.rst": { + "a": 10, + "d": 2 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 36, + "d": 28 + }, + "mne/decoding/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 230, + "d": 31 + }, + "mne/decoding/search_light.py": { + "a": 93, + "d": 114 + }, + "mne/decoding/tests/test_base.py": { + "a": 50, + "d": 5 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 47, + "d": 46 + }, + "mne/decoding/time_gen.py": { + "a": 5, + "d": 1 + }, + "mne/parallel.py": { + "a": 19, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/viz/decoding.py": { + "a": 3, + "d": 1 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 82, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4104.json b/mne-python/source/doc/sphinxext/prs/4104.json new file mode 100644 index 0000000000000000000000000000000000000000..fba9a72874a8608ef8b8e36582319712b15dcacb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4104.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e945956678fecdfd381b9a2078b4128adfe1abf1", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "examples/realtime/ftclient_rt_average.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 13, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4105.json b/mne-python/source/doc/sphinxext/prs/4105.json new file mode 100644 index 0000000000000000000000000000000000000000..41e1fb710a6fc95ffd86a54f5eb11171dc28a213 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4105.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "00a23a3cc62f14a563dc45aac38dc839a7277bf1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 1, + "d": 11 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 325 + }, + "mne/dipole.py": { + "a": 2, + "d": 7 + }, + "mne/epochs.py": { + "a": 39, + "d": 98 + }, + "mne/filter.py": { + "a": 1, + "d": 459 + }, + "mne/forward/_make_forward.py": { + "a": 10, + "d": 31 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 4 + }, + "mne/io/base.py": { + "a": 1, + "d": 6 + }, + "mne/io/fiff/raw.py": { + "a": 3, + "d": 20 + }, + "mne/realtime/epochs.py": { + "a": 4, + "d": 11 + }, + "mne/simulation/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/source_space.py": { + "a": 12, + "d": 51 + }, + "mne/tests/test_source_space.py": { + "a": 10, + "d": 16 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 151 + }, + "mne/viz/tests/test_3d.py": { + "a": 0, + "d": 14 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4106.json b/mne-python/source/doc/sphinxext/prs/4106.json new file mode 100644 index 0000000000000000000000000000000000000000..193f2c5265f9c9168f4d3976c5fd2277eb622223 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4106.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3506ebbe9146b337dc22c05297c4d39daed93ac9", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 5, + "d": 2 + }, + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4107.json b/mne-python/source/doc/sphinxext/prs/4107.json new file mode 100644 index 0000000000000000000000000000000000000000..38f6436356c11ac51653403a7c84012fdf3bce94 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4107.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "826c24616b3dde5e6ec3030800d499380392f126", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 20, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4109.json b/mne-python/source/doc/sphinxext/prs/4109.json new file mode 100644 index 0000000000000000000000000000000000000000..7c5368c9b7ed30c20d6db189d2469addae1fd22c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4109.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "176795b73e34e53a19f14d46a11bff8cd63646fe", + "authors": [ + { + "n": "Jean-Baptiste SCHIRATTI", + "e": "jean.baptiste.schiratti@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 12, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 36, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4111.json b/mne-python/source/doc/sphinxext/prs/4111.json new file mode 100644 index 0000000000000000000000000000000000000000..8bf09bde1b89e4596a0b2200099a75fa5854ed2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4111.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "148cd23d1a3fd2d0dd98fdd2381530c44ec2a428", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4112.json b/mne-python/source/doc/sphinxext/prs/4112.json new file mode 100644 index 0000000000000000000000000000000000000000..1cb3029658f563673c4fee073c821bfd564ad8fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4112.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1574ad4342ec1b8b85ef109849a756b7a1b62c87", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 43, + "d": 14 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 41, + "d": 11 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 38, + "d": 6 + }, + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 115, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4113.json b/mne-python/source/doc/sphinxext/prs/4113.json new file mode 100644 index 0000000000000000000000000000000000000000..7dda8c1070264c03ad3ccdcd7b9bcb99e900ca24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4113.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "add8370d54eae2ddef00ee9290b4dfcca411c44a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 1 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 31, + "d": 44 + }, + "mne/decoding/transformer.py": { + "a": 16, + "d": 4 + }, + "mne/filter.py": { + "a": 146, + "d": 59 + }, + "mne/io/array/tests/test_array.py": { + "a": 6, + "d": 11 + }, + "mne/io/base.py": { + "a": 31, + "d": 18 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 5, + "d": 4 + }, + "mne/io/pick.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 5 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 9, + "d": 12 + }, + "mne/tests/test_filter.py": { + "a": 51, + "d": 37 + }, + "tutorials/plot_background_filtering.py": { + "a": 52, + "d": 28 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4114.json b/mne-python/source/doc/sphinxext/prs/4114.json new file mode 100644 index 0000000000000000000000000000000000000000..a3f9b649c92341d2ade0dfc5e6d2ff40cde1d18c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4114.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "2b2510e53be77bddbe23a835dfdb06aa812f86ec", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 7, + "d": 5 + }, + "mne/io/base.py": { + "a": 6, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 5, + "d": 0 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_coreg.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4115.json b/mne-python/source/doc/sphinxext/prs/4115.json new file mode 100644 index 0000000000000000000000000000000000000000..b7a85514ead2c8c54e922f00fdad2ac476668ae5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4115.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f823a00bae2d7e39ebc587128822e673369b9420", + "authors": [ + { + "n": "Laura Gwilliams", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 111, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4118.json b/mne-python/source/doc/sphinxext/prs/4118.json new file mode 100644 index 0000000000000000000000000000000000000000..55a2b0a321e37566923a6a8c53b212d2a40c3baa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4118.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9a9c69e2caa5a5b268f44a53f7c55faaa7d211f2", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "doc/manual/datasets_index.rst": { + "a": 21, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4119.json b/mne-python/source/doc/sphinxext/prs/4119.json new file mode 100644 index 0000000000000000000000000000000000000000..676ab9f70d5b1edbed4267677040e62ecec62d58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4119.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "8fc2a545f494de0f828b931f2285dbff426e72ad", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/decoding/plot_receptive_field.py": { + "a": 2, + "d": 3 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/receptive_field.py": { + "a": 66, + "d": 35 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 92, + "d": 5 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 243, + "d": 0 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 5, + "d": 4 + }, + "tutorials/plot_receptive_field.py": { + "a": 101, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/412.json b/mne-python/source/doc/sphinxext/prs/412.json new file mode 100644 index 0000000000000000000000000000000000000000..dc745099722a88b91323e6c884bfe81084aafd48 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/412.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c0918bfd1dbbe92139b639a9c1bd891e7371f882", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/sphinxext/gen_rst.py": { + "a": 307, + "d": 139 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4120.json b/mne-python/source/doc/sphinxext/prs/4120.json new file mode 100644 index 0000000000000000000000000000000000000000..54643e18c4bcfd008dc42752c72f6fa823aba897 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4120.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e3a4dce3ee3bcfe744086b7ebdd4374793560e96", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4121.json b/mne-python/source/doc/sphinxext/prs/4121.json new file mode 100644 index 0000000000000000000000000000000000000000..516b87bd474c31ed1bed3bda5ee39a0c07321992 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4121.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "992662a474192778f709dfbc588f4e1fcfcab916", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/decoding/receptive_field.py": { + "a": 25, + "d": 14 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_receptive_field.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4123.json b/mne-python/source/doc/sphinxext/prs/4123.json new file mode 100644 index 0000000000000000000000000000000000000000..f2e454333e0e1d1aaa83c63f2cb489ccb4201171 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4123.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0130bf93adbe6f7efadcac250fc0985fe6f927d4", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/plot_forward.py": { + "a": 20, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/413.json b/mne-python/source/doc/sphinxext/prs/413.json new file mode 100644 index 0000000000000000000000000000000000000000..bb74515356cc7812a06b5c3b6c0a3bbdb04953f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/413.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "1692365eab0d92ec33e37efac27a26249b90c4ca", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 6, + "d": 7 + }, + "examples/plot_read_evoked.py": { + "a": 3, + "d": 5 + }, + "mne/fiff/evoked.py": { + "a": 8, + "d": 3 + }, + "mne/tests/test_viz.py": { + "a": 6, + "d": 1 + }, + "mne/viz.py": { + "a": 37, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4132.json b/mne-python/source/doc/sphinxext/prs/4132.json new file mode 100644 index 0000000000000000000000000000000000000000..f16b80cad5fa354947c33c8608eb5ee1293c6a7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4132.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "847347d14b858b86e5aac347a9db1bcf44b554d6", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 12, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4135.json b/mne-python/source/doc/sphinxext/prs/4135.json new file mode 100644 index 0000000000000000000000000000000000000000..2dd451a81e269f8952a97e7c44f06fa89dc7aa16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4135.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b53c5bdc1fd89df68dcc1fbebcf67858ac12ff23", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_rap_music.py": { + "a": 14, + "d": 17 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4138.json b/mne-python/source/doc/sphinxext/prs/4138.json new file mode 100644 index 0000000000000000000000000000000000000000..834635cbed774462e2f35482b238d710f5bf9305 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4138.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1df8195ac81a829e8db9ada4fa266a4c19676e46", + "authors": [ + { + "n": "Nicole Proulx", + "e": null + } + ], + "changes": { + "tutorials/plot_decoding_csp_timefreq.py": { + "a": 56, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4139.json b/mne-python/source/doc/sphinxext/prs/4139.json new file mode 100644 index 0000000000000000000000000000000000000000..224b38b70bdd6ae8c390c716c1ef30ab7546149f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4139.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b6bb7bf285b144c34a93b76963283b8d35e3f97c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 143, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/414.json b/mne-python/source/doc/sphinxext/prs/414.json new file mode 100644 index 0000000000000000000000000000000000000000..f41bfa7a0655c4505dab872ccc41a9d429ad6897 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/414.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2689932e0e52937b479c6063a29a0c31feca866d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4141.json b/mne-python/source/doc/sphinxext/prs/4141.json new file mode 100644 index 0000000000000000000000000000000000000000..b78de802f78248779dc60bd3f24c675ef90530bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4141.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3295ba7543d69abf4c740d4b1d3669649e894c2e", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "mne/preprocessing/ecg.py": { + "a": 3, + "d": 0 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4143.json b/mne-python/source/doc/sphinxext/prs/4143.json new file mode 100644 index 0000000000000000000000000000000000000000..ffd3fa739aeaa131fe05f89d6ec3d6f4831bef86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4143.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6fd0c4fb416e4705517b1aeee0c8dc2393887172", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "examples/decoding/README.txt": { + "a": 3, + "d": 3 + }, + "tutorials/plot_receptive_field.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4144.json b/mne-python/source/doc/sphinxext/prs/4144.json new file mode 100644 index 0000000000000000000000000000000000000000..58a84bfdf4a3137b47263183a9631b2f333422c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4144.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "1239f23d5c44c1e8b79d035221559163c595978e", + "authors": [ + { + "n": "alexandre barachant", + "e": null + } + ], + "changes": { + "circle.yml": { + "a": 4, + "d": 0 + }, + "doc/manual/decoding.rst": { + "a": 16, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 7, + "d": 0 + }, + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 84, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/fieldtrip_cmc/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py": { + "a": 32, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 14, + "d": 4 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 209, + "d": 29 + }, + "mne/decoding/tests/test_csp.py": { + "a": 103, + "d": 26 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4145.json b/mne-python/source/doc/sphinxext/prs/4145.json new file mode 100644 index 0000000000000000000000000000000000000000..20d8eba6dfa7e09237a78ae37c6637204d8a1130 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4145.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8207646a4af0b551163f98a3d89a1111ca6775d5", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 8, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4152.json b/mne-python/source/doc/sphinxext/prs/4152.json new file mode 100644 index 0000000000000000000000000000000000000000..bb7234c83b393a4880d3fc4fa24c0c1f766fd4d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4152.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "85b471be65f046b81b681a3b061897868a697fbc", + "authors": [ + { + "n": "Rodrigo Hübner", + "e": "rodrigohubner@utfpr.edu.br" + } + ], + "changes": { + "mne/dipole.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4154.json b/mne-python/source/doc/sphinxext/prs/4154.json new file mode 100644 index 0000000000000000000000000000000000000000..9711479d20302477a70b69e48cb35ab553fc3677 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4154.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ee5ecfe78d9a7ec5698ab015644e25d1b7596755", + "authors": [ + { + "n": "Rodrigo Hübner", + "e": "rodrigohubner@utfpr.edu.br" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4156.json b/mne-python/source/doc/sphinxext/prs/4156.json new file mode 100644 index 0000000000000000000000000000000000000000..694ca5c47ae05c36e2790d5d497a0db58436fa38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4156.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7b812a2c654290c509beae6fb3ef035127ea3a68", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/io/plot_objects_from_arrays.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4158.json b/mne-python/source/doc/sphinxext/prs/4158.json new file mode 100644 index 0000000000000000000000000000000000000000..e0670d08e798735b16eb612b8595d3399b1e42a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4158.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d512801d56091376f51c0d60cf0a1e82a87a351b", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/416.json b/mne-python/source/doc/sphinxext/prs/416.json new file mode 100644 index 0000000000000000000000000000000000000000..968ee853c07e212aabc072b9f59077173efb7679 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/416.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "906dff5a263cb84fb3425c3fd1f02741a14c1d79", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4160.json b/mne-python/source/doc/sphinxext/prs/4160.json new file mode 100644 index 0000000000000000000000000000000000000000..5f008918ca2af39d646969f1e6fffb4ffb73814a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4160.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f1b0fd4216324fe9609eca77a73d2a4617fcd876", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 16, + "d": 9 + }, + "mne/io/fiff/raw.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4162.json b/mne-python/source/doc/sphinxext/prs/4162.json new file mode 100644 index 0000000000000000000000000000000000000000..dbbc5d0061210e40faaada0c85cf84982fcd8073 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4162.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c8d52520e07091a83375ef0fcd170ef16cc932e4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4163.json b/mne-python/source/doc/sphinxext/prs/4163.json new file mode 100644 index 0000000000000000000000000000000000000000..e9ea5b979fa8e3d14dd84c2042021ac96b04b32a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4163.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "63c31843d61508a28d34e4cf2472ca388d4a8ef8", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4166.json b/mne-python/source/doc/sphinxext/prs/4166.json new file mode 100644 index 0000000000000000000000000000000000000000..e881cd484e2df8e28f917785c5395868a5de26af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4166.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ab51322a930062375f9b92ab4fac79e44e5a4dc6", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/io/plot_objects_from_arrays.py": { + "a": 1, + "d": 0 + }, + "mne/io/base.py": { + "a": 1, + "d": 5 + }, + "mne/io/fiff/raw.py": { + "a": 5, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4167.json b/mne-python/source/doc/sphinxext/prs/4167.json new file mode 100644 index 0000000000000000000000000000000000000000..86ab236abf1b8c33e92b27d8297f2e69845889d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4167.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3f961aa21a1d4e7a98327880da80dcd3dd782c34", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/eog.py": { + "a": 18, + "d": 7 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4168.json b/mne-python/source/doc/sphinxext/prs/4168.json new file mode 100644 index 0000000000000000000000000000000000000000..d16e8cc192451b092c1c8f348523bd4210a4d977 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4168.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "a8f7ad3eb49ea540814183635b6bc8a246e7f3ce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_unsupervised_spatial_filter.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_objects_from_arrays.py": { + "a": 3, + "d": 1 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_linear_regression_raw.py": { + "a": 3, + "d": 2 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 2, + "d": 1 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_topo_customized.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 3, + "d": 6 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 2 + }, + "tutorials/plot_modifying_data_inplace.py": { + "a": 3, + "d": 4 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4169.json b/mne-python/source/doc/sphinxext/prs/4169.json new file mode 100644 index 0000000000000000000000000000000000000000..201d436bd45d2e133a9c6930fef22b95a3216738 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4169.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "efc5096d141a785d9f525208fee0e2105a690aea", + "authors": [ + { + "n": "alexandre barachant", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 11, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4170.json b/mne-python/source/doc/sphinxext/prs/4170.json new file mode 100644 index 0000000000000000000000000000000000000000..36686fdf4a22440828111ae94b09e276cadb982a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4170.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "c86a836e27caf4e34194aa74205e48c027bbedb2", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "circle.yml": { + "a": 3, + "d": 0 + }, + "doc/manual/datasets_index.rst": { + "a": 11, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_hf_sef_data.py": { + "a": 37, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/hf_sef/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 99, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4172.json b/mne-python/source/doc/sphinxext/prs/4172.json new file mode 100644 index 0000000000000000000000000000000000000000..b5b557a21d87a099cf6fea421568db34ce48f185 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4172.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "04584cd6d9cadfd81f521bfde92fafab2bad2c66", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/contributing.rst": { + "a": 27, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4173.json b/mne-python/source/doc/sphinxext/prs/4173.json new file mode 100644 index 0000000000000000000000000000000000000000..020f16392abc6d243a9585b99ce9ca656549b6d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4173.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "d902ce646ae5195dd2e8a589947441fbb1b17cd4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 5 + }, + "doc/configure_git.rst": { + "a": 1, + "d": 1 + }, + "doc/contributing.rst": { + "a": 2, + "d": 2 + }, + "doc/documentation.rst": { + "a": 680, + "d": 0 + }, + "doc/getting_started.rst": { + "a": 38, + "d": 104 + }, + "doc/index.rst": { + "a": 0, + "d": 1 + }, + "doc/install_mne_python.rst": { + "a": 3, + "d": 4 + }, + "doc/manual/channel_interpolation.rst": { + "a": 2, + "d": 2 + }, + "doc/manual/cookbook.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/datasets_index.rst": { + "a": 2, + "d": 2 + }, + "doc/manual/decoding.rst": { + "a": 7, + "d": 7 + }, + "doc/manual/index.rst": { + "a": 0, + "d": 8 + }, + "doc/manual/io.rst": { + "a": 27, + "d": 0 + }, + "doc/manual/matlab.rst": { + "a": 3, + "d": 3 + }, + "doc/manual/pitfalls.rst": { + "a": 0, + "d": 30 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 4, + "d": 4 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 0 + }, + "doc/tutorials.rst": { + "a": 0, + "d": 178 + }, + "doc/tutorials/philosophy.rst": { + "a": 27, + "d": 45 + }, + "doc/whats_new.rst": { + "a": 14, + "d": 12 + }, + "examples/decoding/plot_receptive_field.py": { + "a": 1, + "d": 1 + }, + "examples/io/README.txt": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 7, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 16, + "d": 26 + }, + "mne/decoding/search_light.py": { + "a": 28, + "d": 31 + }, + "mne/decoding/transformer.py": { + "a": 2, + "d": 2 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_configuration.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4174.json b/mne-python/source/doc/sphinxext/prs/4174.json new file mode 100644 index 0000000000000000000000000000000000000000..ac89544a7dbb65651fb1c96f02f824b9e2894d29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4174.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d446fe79bc8bf6cadb7d8ab1209800b729b0c06a", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 3 + }, + "mne/io/ctf/info.py": { + "a": 10, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4179.json b/mne-python/source/doc/sphinxext/prs/4179.json new file mode 100644 index 0000000000000000000000000000000000000000..9cbbce009d96c52efee9f1cc9ecd1d1396f7de7e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4179.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "654c6e8a7c97156d9f65eec3d9d9686d83fe3646", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/418.json b/mne-python/source/doc/sphinxext/prs/418.json new file mode 100644 index 0000000000000000000000000000000000000000..2fd41de635b009ac8a5f94781578acab282eb247 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/418.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "43f44da622cf2990b4b6f0441b3a39dce0fcb397", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 9, + "d": 8 + }, + "mne/source_estimate.py": { + "a": 7, + "d": 4 + }, + "mne/viz.py": { + "a": 47, + "d": 30 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4181.json b/mne-python/source/doc/sphinxext/prs/4181.json new file mode 100644 index 0000000000000000000000000000000000000000..cdb6f4f3db7737872913e163fe03eda7e25fa5ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4181.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c9fa7918750c6e708f4fe8c0154428366251872e", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4182.json b/mne-python/source/doc/sphinxext/prs/4182.json new file mode 100644 index 0000000000000000000000000000000000000000..ef3ba42551e50a4c2e16046790f552f4805d29a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4182.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0c44a12ac95276c7c102660974fa8f5e1b074b26", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 10, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 24, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4183.json b/mne-python/source/doc/sphinxext/prs/4183.json new file mode 100644 index 0000000000000000000000000000000000000000..ef3e276a2476854c8e22bb615cc1ca7271ee1290 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4183.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e68c0662a829d68207f8ff8c111579965546641a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4186.json b/mne-python/source/doc/sphinxext/prs/4186.json new file mode 100644 index 0000000000000000000000000000000000000000..f9f4c044b1913d6127b0db3a884408c2793b7b7e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4186.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1fd891b772942e1885047a40795a25c5302c9f32", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 8, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4187.json b/mne-python/source/doc/sphinxext/prs/4187.json new file mode 100644 index 0000000000000000000000000000000000000000..becbf49a306a74233de422227703c6de88366488 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4187.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "884846fa1a3254ca7d9e5e4548b8f5ff521a2cf9", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 48, + "d": 32 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 8, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/419.json b/mne-python/source/doc/sphinxext/prs/419.json new file mode 100644 index 0000000000000000000000000000000000000000..6bfbc75ed8c33927999ca080bef0c145d66729d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/419.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "633145e4e0d6555109ff1c46f29eca8270b18b32", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 1, + "d": 1 + }, + "mne/fiff/meas_info.py": { + "a": 9, + "d": 3 + }, + "mne/fiff/raw.py": { + "a": 75, + "d": 19 + }, + "mne/fiff/tests/test_raw.py": { + "a": 52, + "d": 27 + }, + "mne/fiff/write.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4191.json b/mne-python/source/doc/sphinxext/prs/4191.json new file mode 100644 index 0000000000000000000000000000000000000000..224110c1da3b78e9e07b435b0b63a5fd72185550 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4191.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "52e7bb712e8ed480d6bf66dbefab50e8bd6fe647", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4193.json b/mne-python/source/doc/sphinxext/prs/4193.json new file mode 100644 index 0000000000000000000000000000000000000000..7e52e90a2fed14780d2273f712425cb7f6fd0ea9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4193.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b7f37de81210f0349faf78e091ee3cb73ebae647", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 3, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 70, + "d": 23 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/42.json b/mne-python/source/doc/sphinxext/prs/42.json new file mode 100644 index 0000000000000000000000000000000000000000..ddf90f0ab84d3291d0e30dc181cc6599a705ca13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/42.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "e2b8a83f7ca79c0cc8c513dbf539f51049dd05b0", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_make_inverse_operator.py": { + "a": 6, + "d": 2 + }, + "mne/fiff/channels.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/cov.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/meas_info.py": { + "a": 4, + "d": 2 + }, + "mne/fiff/pick.py": { + "a": 9, + "d": 6 + }, + "mne/forward.py": { + "a": 99, + "d": 20 + }, + "mne/minimum_norm/inverse.py": { + "a": 32, + "d": 15 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 5, + "d": 0 + }, + "mne/tests/test_forward.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/420.json b/mne-python/source/doc/sphinxext/prs/420.json new file mode 100644 index 0000000000000000000000000000000000000000..f96ff33b7f80f764b203189626685021dae423b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/420.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "22e0b13221f96931b59b0d5f595bdd680bd9edc4", + "authors": [ + { + "n": "Simon Kornblith", + "e": "simon@simonster.com" + } + ], + "changes": { + "mne/event.py": { + "a": 88, + "d": 6 + }, + "mne/tests/test_event.py": { + "a": 72, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4202.json b/mne-python/source/doc/sphinxext/prs/4202.json new file mode 100644 index 0000000000000000000000000000000000000000..9532b9a81b43ee4dec5fa1d55dfcd0fc15627cf1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4202.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "33b10960f6f88e898fcb694032eff876826c4b22", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4203.json b/mne-python/source/doc/sphinxext/prs/4203.json new file mode 100644 index 0000000000000000000000000000000000000000..15b1a8124812303796d1e3f95176a09f108b1034 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4203.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "a2b75f7d06fd753b7732f71a1f92802abc28dd63", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 12, + "d": 6 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 14, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 10, + "d": 4 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 46, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4204.json b/mne-python/source/doc/sphinxext/prs/4204.json new file mode 100644 index 0000000000000000000000000000000000000000..7994311ab5bb6015199b7f9239e9ad57bc9b0085 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4204.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "edbbcf475fa6a216193f9f4ed37f1efddbd1f646", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4205.json b/mne-python/source/doc/sphinxext/prs/4205.json new file mode 100644 index 0000000000000000000000000000000000000000..f075fa2e4c0a459f7c717767cebc7fa1b1cf03b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4205.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d130b748b43ba0ae944b322cf37c4b1a599a821b", + "authors": [ + { + "n": "Nicolas Barascud", + "e": null + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 24, + "d": 12 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 634, + "d": 137 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 68, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4210.json b/mne-python/source/doc/sphinxext/prs/4210.json new file mode 100644 index 0000000000000000000000000000000000000000..7415aea4a6e15e61d1563465f23bae0d50086c23 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4210.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "53900e6d5430a5b8a7179032d402f8fe6f8d90d6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 14, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 12, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4212.json b/mne-python/source/doc/sphinxext/prs/4212.json new file mode 100644 index 0000000000000000000000000000000000000000..324d73c057a7dc6b8943d182caae23561ce2bae6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4212.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8526a27fc9fa43040a1fd72bcdf254cb428b82a9", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/io/egi/egi.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4213.json b/mne-python/source/doc/sphinxext/prs/4213.json new file mode 100644 index 0000000000000000000000000000000000000000..aec80c7acb4a1073b5e9b72cf11a99bbb40bf8d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4213.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9f908e74c53cb8a3608080560d0072cbcdebc97f", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 69, + "d": 4 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 24, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4218.json b/mne-python/source/doc/sphinxext/prs/4218.json new file mode 100644 index 0000000000000000000000000000000000000000..01f272f148c070032c0afc7bb1d66b970dd87d88 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4218.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ddd84d8e199761fca6926f91c0493446e3ff0260", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/reference.py": { + "a": 60, + "d": 17 + }, + "mne/io/tests/test_reference.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4219.json b/mne-python/source/doc/sphinxext/prs/4219.json new file mode 100644 index 0000000000000000000000000000000000000000..5c8722070e081b5a77bdee540366eeeb5291d7ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4219.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ebabe331f06df5f222b2a00f9ce782b6267cf8f7", + "authors": [ + { + "n": "jdue", + "e": "jdue@dtu.dk" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4220.json b/mne-python/source/doc/sphinxext/prs/4220.json new file mode 100644 index 0000000000000000000000000000000000000000..2d5f875ab47a26fc0c411114ae6fc0ec016a1b59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4220.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "912c0e41e4467f622932f1ecb6f673e0717a1c0b", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 35, + "d": 34 + }, + "mne/viz/tests/test_topo.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4223.json b/mne-python/source/doc/sphinxext/prs/4223.json new file mode 100644 index 0000000000000000000000000000000000000000..9ab9a87c4383165331fb771e6a439ff6ed636981 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4223.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cda9d7b8362cb53618c71967b0b63ff46d311d9c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 22, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4224.json b/mne-python/source/doc/sphinxext/prs/4224.json new file mode 100644 index 0000000000000000000000000000000000000000..22db2f472cf6ce3bca9f5434f4956a07f74faf99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4224.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "a42677ff2f7342f2de93e6ec84f74d29c1983b4b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_evoked_topomap.py": { + "a": 0, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 3 + }, + "mne/viz/circle.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 4, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 79, + "d": 71 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 0 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4225.json b/mne-python/source/doc/sphinxext/prs/4225.json new file mode 100644 index 0000000000000000000000000000000000000000..accbf11aa93285596a471cfd1e16494a6702ccca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4225.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bda07a6a73d3dd24a93bb5ddcc43b578b5f274b8", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_ica.py": { + "a": 8, + "d": 5 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 47, + "d": 44 + }, + "mne/viz/topomap.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4236.json b/mne-python/source/doc/sphinxext/prs/4236.json new file mode 100644 index 0000000000000000000000000000000000000000..a50029c8611dac3f4c91f6b7693503348bcdf295 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4236.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c602de23c70cd0af18256865f3b4b44b1be55ded", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 10, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4237.json b/mne-python/source/doc/sphinxext/prs/4237.json new file mode 100644 index 0000000000000000000000000000000000000000..a02fd95b77525a642d24db158072670c49153d3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4237.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "932af71c4a0828fa87ddc141cd223c5a4ad9bede", + "authors": [ + { + "n": "Jean-Baptiste SCHIRATTI", + "e": "jean.baptiste.schiratti@gmail.com" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 11, + "d": 3 + }, + "mne/io/tests/test_reference.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4238.json b/mne-python/source/doc/sphinxext/prs/4238.json new file mode 100644 index 0000000000000000000000000000000000000000..9a4adfec8621a4343e8906147da19a15b82e3637 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4238.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7fdb3819cd76102a257a0b6edc8242a7d2b8ea3b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 5 + }, + "mne/viz/tests/test_topomap.py": { + "a": 12, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4239.json b/mne-python/source/doc/sphinxext/prs/4239.json new file mode 100644 index 0000000000000000000000000000000000000000..7af9e19f61f1fb62a9d0d2c80211f3ace34a97b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4239.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3c6b4671b2f3fce21aec75fe0ba0253a1be0f2e7", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 12, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/424.json b/mne-python/source/doc/sphinxext/prs/424.json new file mode 100644 index 0000000000000000000000000000000000000000..b1a751628f7417930578fe929fb194cc2c5dbbf4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/424.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1d8ad7be8ffd3d43993a87c0a5b45ec0e29cd359", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 7, + "d": 5 + }, + "mne/fiff/evoked.py": { + "a": 8, + "d": 5 + }, + "mne/fiff/raw.py": { + "a": 49, + "d": 23 + }, + "mne/fiff/tests/test_raw.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4243.json b/mne-python/source/doc/sphinxext/prs/4243.json new file mode 100644 index 0000000000000000000000000000000000000000..f0c32bdd015a98cc8c51f0b07f9a17d600e68228 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4243.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "18db2bb3f62bc17f3971c00b33f3f0a69891b6db", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_viewer.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4244.json b/mne-python/source/doc/sphinxext/prs/4244.json new file mode 100644 index 0000000000000000000000000000000000000000..7a649a044af0d74af42ff5b221521ddaa84692cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4244.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ed4bb163b97e5753029680a74044499693cbc0ca", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/_make_forward.py": { + "a": 2, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4247.json b/mne-python/source/doc/sphinxext/prs/4247.json new file mode 100644 index 0000000000000000000000000000000000000000..ad801be0be1d1da0f8e20bcb708c82bc19e27b37 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4247.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "64b070cc6014955ac125facfeb83d7755def48cd", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 5, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 24, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4248.json b/mne-python/source/doc/sphinxext/prs/4248.json new file mode 100644 index 0000000000000000000000000000000000000000..d6f82e090c9eb9e8517e213603e03ca35a884954 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4248.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f9892442ea3cfe2bc916e391998e64d216a61744", + "authors": [ + { + "n": "LaetitiaG", + "e": "laetitia.grabot@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/time_frequency.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/425.json b/mne-python/source/doc/sphinxext/prs/425.json new file mode 100644 index 0000000000000000000000000000000000000000..602914136d2d4ba6797e722b93a8205e1db45846 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/425.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "55697a4d6f585149ddacc459623d0b82c17d618e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 15 + }, + "doc/source/python_tutorial.rst": { + "a": 8, + "d": 2 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/cuda.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 32, + "d": 5 + }, + "mne/fiff/tests/test_raw.py": { + "a": 7, + "d": 5 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 11, + "d": 1 + }, + "mne/utils.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4250.json b/mne-python/source/doc/sphinxext/prs/4250.json new file mode 100644 index 0000000000000000000000000000000000000000..064cd9cb382a1b738214f1b764555d15eda77d0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4250.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "edd2f0eec6ae3d5f3fb0ac39c91f8df753de7b41", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 17, + "d": 6 + }, + "doc/Makefile": { + "a": 3, + "d": 0 + }, + "doc/_static/flag-icon.css": { + "a": 23, + "d": 0 + }, + "doc/_static/font-awesome.css": { + "a": 2337, + "d": 0 + }, + "doc/_static/fontawesome-webfont.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fontawesome-webfont.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fontawesome-webfont.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fontawesome-webfont.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fr.svg": { + "a": 7, + "d": 0 + }, + "doc/_static/institutions.png": { + "a": 0, + "d": 0 + }, + "doc/_static/style.css": { + "a": 149, + "d": 26 + }, + "doc/_static/us.svg": { + "a": 18, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 23, + "d": 4 + }, + "doc/carousel.inc": { + "a": 87, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "doc/documentation.rst": { + "a": 40, + "d": 15 + }, + "doc/index.rst": { + "a": 89, + "d": 83 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 1 + }, + "doc/sphinxext/gen_commands.py": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 4 + }, + "examples/decoding/plot_receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 6 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 8, + "d": 7 + }, + "tutorials/plot_receptive_field.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 3, + "d": 1 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 5, + "d": 4 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4254.json b/mne-python/source/doc/sphinxext/prs/4254.json new file mode 100644 index 0000000000000000000000000000000000000000..cc1b7552e6ed36fa3090dd6cc5120938ea7f4f61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4254.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "28a05e1f1eeaaa82ee10101a135449e8dadf0993", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 22, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4258.json b/mne-python/source/doc/sphinxext/prs/4258.json new file mode 100644 index 0000000000000000000000000000000000000000..f4ff5ec500e1bc871dab8b18dd318a56e6bbbfa9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4258.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "85be8ca1db9d4749518597f30b6516376ae190df", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/426.json b/mne-python/source/doc/sphinxext/prs/426.json new file mode 100644 index 0000000000000000000000000000000000000000..f97cb66f628176cc16f7747430cfbe29c64d84e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/426.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6491f8b3a4b19c7a18b55f11c1e9f133a8ce4b51", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4263.json b/mne-python/source/doc/sphinxext/prs/4263.json new file mode 100644 index 0000000000000000000000000000000000000000..21024ed74a2ac0873b61d193fc53b9b43ba04119 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4263.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d25b1a0fdabf0d0b2e9bf1d95c12042da1234a6d", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 3, + "d": 3 + }, + "mne/coreg.py": { + "a": 1, + "d": 0 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4267.json b/mne-python/source/doc/sphinxext/prs/4267.json new file mode 100644 index 0000000000000000000000000000000000000000..600ca416797b8c60c81bfbe35e90a045cc204226 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4267.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e78c637f054aaa9110c8ee7c6c4e1769e016ee48", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 12, + "d": 7 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/evoked.py": { + "a": 55, + "d": 18 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 21, + "d": 25 + }, + "mne/tests/test_dipole.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/427.json b/mne-python/source/doc/sphinxext/prs/427.json new file mode 100644 index 0000000000000000000000000000000000000000..112fe53c3a5dbabdbc3473982711f6e44057e3dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/427.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "abd356be9a845d3d504bb15f4b418ab7b7cedab1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 218, + "d": 83 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4270.json b/mne-python/source/doc/sphinxext/prs/4270.json new file mode 100644 index 0000000000000000000000000000000000000000..33d971e7fca8e572c403d9160c40558702bfc07e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4270.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6072ab04378c01557f29e67f1d1cbc5fa226943a", + "authors": [ + { + "n": "jdue", + "e": "jdue@dtu.dk" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4271.json b/mne-python/source/doc/sphinxext/prs/4271.json new file mode 100644 index 0000000000000000000000000000000000000000..37adc7035c69a3eed301be5633a7ac055649fade --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4271.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "67e27f74d616cea7ddae1cf78f67d078f37529e0", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 98, + "d": 37 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 0 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 25, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4273.json b/mne-python/source/doc/sphinxext/prs/4273.json new file mode 100644 index 0000000000000000000000000000000000000000..4a820513f739c459b108b3b32dfcd5f7132fc9e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4273.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d6c7f899f87c37ec0a35e74bacb23302a3ccb4ab", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4274.json b/mne-python/source/doc/sphinxext/prs/4274.json new file mode 100644 index 0000000000000000000000000000000000000000..9c5132578583ca463c14b2c65176d3d3e5b7d555 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4274.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4b4615d7f163263556edece4d5e4c1b28a165922", + "authors": [ + { + "n": "Laura Gwilliams", + "e": null + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 22, + "d": 23 + }, + "mne/decoding/tests/test_base.py": { + "a": 12, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4276.json b/mne-python/source/doc/sphinxext/prs/4276.json new file mode 100644 index 0000000000000000000000000000000000000000..7bf946d7c4a7ba368a0f6a9423150fe2e5c1ea92 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4276.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "690bd2124f63b81766e3e9a4da326f6048c9d05d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 4 + }, + "mne/viz/montage.py": { + "a": 29, + "d": 36 + }, + "mne/viz/tests/test_montage.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4277.json b/mne-python/source/doc/sphinxext/prs/4277.json new file mode 100644 index 0000000000000000000000000000000000000000..5562fea205a2d8178dd2462d770609ce3b60e1f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4277.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a4ba5dd96fda159010f709e054eb0a9666d10d58", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 5, + "d": 3 + }, + "tutorials/plot_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_point_spread.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4278.json b/mne-python/source/doc/sphinxext/prs/4278.json new file mode 100644 index 0000000000000000000000000000000000000000..bc0885433568e8dda56fa00b222d7ad46dc86185 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4278.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "55f4fbf470af0e3b33de58530b95566aed3b8861", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4280.json b/mne-python/source/doc/sphinxext/prs/4280.json new file mode 100644 index 0000000000000000000000000000000000000000..5abc318ad9e617fa79b084868b0bede478243740 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4280.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "685f6858315c6924c441d834976cfe7d55d9c2b1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/chpi.py": { + "a": 12, + "d": 3 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4281.json b/mne-python/source/doc/sphinxext/prs/4281.json new file mode 100644 index 0000000000000000000000000000000000000000..a0c535a50abf807e5e5dca3e73f4620ee7706eae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4281.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cac45d4113276138fb50f9df252eeafd999ebf97", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4282.json b/mne-python/source/doc/sphinxext/prs/4282.json new file mode 100644 index 0000000000000000000000000000000000000000..1b2f837bf581220c2e3ef918b14f2cd5c98b0a99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4282.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "573ad7eedc333fc3640e3097522546395c5e1a95", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4285.json b/mne-python/source/doc/sphinxext/prs/4285.json new file mode 100644 index 0000000000000000000000000000000000000000..5688cce07343a64a55fc555b5baa5565de9f9012 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4285.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b9f46fa05c8693f6cdc36f1009d2a5083c3a0bb7", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4289.json b/mne-python/source/doc/sphinxext/prs/4289.json new file mode 100644 index 0000000000000000000000000000000000000000..53f1b7350a3aa885c482c2b3167a12a0580aab77 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4289.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "525dab575f6003df9441a86358de5415c8e2eb1e", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 3, + "d": 3 + }, + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 71, + "d": 0 + }, + "mne/epochs.py": { + "a": 8, + "d": 5 + }, + "mne/viz/epochs.py": { + "a": 400, + "d": 120 + }, + "mne/viz/evoked.py": { + "a": 99, + "d": 66 + }, + "mne/viz/ica.py": { + "a": 8, + "d": 31 + }, + "mne/viz/tests/test_epochs.py": { + "a": 22, + "d": 6 + }, + "mne/viz/tests/test_evoked.py": { + "a": 13, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 32, + "d": 5 + }, + "tutorials/plot_visualize_epochs.py": { + "a": 16, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/429.json b/mne-python/source/doc/sphinxext/prs/429.json new file mode 100644 index 0000000000000000000000000000000000000000..3346d48cbd528a7c9617cfd0e45350fffc653397 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/429.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "10f590909a58b264440cb49cfd4855914e6be21e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 51, + "d": 37 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4291.json b/mne-python/source/doc/sphinxext/prs/4291.json new file mode 100644 index 0000000000000000000000000000000000000000..f48fd603f3fbae3c8cd6010c5ff79505e9f023c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4291.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d40958f5cab696acb0fa407f9dd55431f9b7746f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 13, + "d": 16 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 7 + }, + "mne/transforms.py": { + "a": 4, + "d": 4 + }, + "mne/utils.py": { + "a": 12, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 5 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4292.json b/mne-python/source/doc/sphinxext/prs/4292.json new file mode 100644 index 0000000000000000000000000000000000000000..1a0a71697bfbaf3d930c75c5da60ff9680237ed5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4292.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3da80f58e68ab1ed8e2231976013f9da7f85eb77", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/event.py": { + "a": 13, + "d": 5 + }, + "mne/tests/test_event.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4293.json b/mne-python/source/doc/sphinxext/prs/4293.json new file mode 100644 index 0000000000000000000000000000000000000000..81822928a4e35e2fd75147f03a6b0355a6657dc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4293.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8bf97d2a0763b5d317b98b26c0805bcf2bcd3df0", + "authors": [ + { + "n": "Phillip Alday", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 45, + "d": 9 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 41, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4294.json b/mne-python/source/doc/sphinxext/prs/4294.json new file mode 100644 index 0000000000000000000000000000000000000000..7161f467f800a8d66650f03f1064cc17635e2c75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4294.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4e8f76472b28f089f6853bd6440e2d5add9be050", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 9 + }, + "mne/preprocessing/stim.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4295.json b/mne-python/source/doc/sphinxext/prs/4295.json new file mode 100644 index 0000000000000000000000000000000000000000..fee798dee64ce4d6dc1e6a9c8b5ea7eb1657b08b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4295.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ca98e76c7c2b11dd0b220bc085c5a06eae524aee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 6, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4296.json b/mne-python/source/doc/sphinxext/prs/4296.json new file mode 100644 index 0000000000000000000000000000000000000000..8332261b072d78879cc3a8d0c273e23cc8070982 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4296.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "60151f8621fb2e324428385258408c71bf58d8e2", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 43, + "d": 15 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 37, + "d": 8 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 48, + "d": 23 + }, + "mne/inverse_sparse/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 24, + "d": 9 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 133, + "d": 17 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 4, + "d": 4 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 21, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 25, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4297.json b/mne-python/source/doc/sphinxext/prs/4297.json new file mode 100644 index 0000000000000000000000000000000000000000..9a1c0d45594890b5892649491d15b1138a64ace2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4297.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "26187fd29fa1f3cb769a216cf0a1df22c3be2626", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/manual/datasets_index.rst": { + "a": 11, + "d": 11 + }, + "doc/python_reference.rst": { + "a": 174, + "d": 326 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 4, + "d": 4 + }, + "mne/chpi.py": { + "a": 30, + "d": 30 + }, + "mne/connectivity/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/__init__.py": { + "a": 4, + "d": 1 + }, + "mne/datasets/brainstorm/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 8, + "d": 5 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 251, + "d": 58 + }, + "mne/io/proc_history.py": { + "a": 39, + "d": 42 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 5 + }, + "mne/realtime/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 4, + "d": 3 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 4, + "d": 2 + }, + "mne/simulation/tests/test_raw.py": { + "a": 16, + "d": 4 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/transforms.py": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_object_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4298.json b/mne-python/source/doc/sphinxext/prs/4298.json new file mode 100644 index 0000000000000000000000000000000000000000..08dac61c5ab764162f002b0f46519cc19d3d01d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4298.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fba848755adab14ebc88c2b89cf8cca4b23b6a7e", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 13, + "d": 14 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 300, + "d": 223 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4299.json b/mne-python/source/doc/sphinxext/prs/4299.json new file mode 100644 index 0000000000000000000000000000000000000000..ab39ac6c84fa8479e8f26f11ad624ca2118be570 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4299.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "75d17d52c6596234bd1e80d7206044aab07230dc", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "examples/io/plot_elekta_epochs.py": { + "a": 10, + "d": 10 + }, + "mne/event.py": { + "a": 1, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/43.json b/mne-python/source/doc/sphinxext/prs/43.json new file mode 100644 index 0000000000000000000000000000000000000000..1ae4b7bae8cda5cf8c0c6580a2b6d7287845dacc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/43.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fe9f7b7836aeb8cd508b318fbd6d61c592f2fb32", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 9, + "d": 0 + }, + "bin/mne_compute_proj_eog.py": { + "a": 5, + "d": 4 + }, + "bin/mne_maxfilter.py": { + "a": 143, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxfilter.py": { + "a": 4, + "d": 2 + }, + "setup.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/430.json b/mne-python/source/doc/sphinxext/prs/430.json new file mode 100644 index 0000000000000000000000000000000000000000..ea931906bcabb42585ef022dbbabf926d423f8c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/430.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9b91357c24632345d9c2562ff76787c24926512c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/event.py": { + "a": 39, + "d": 23 + }, + "mne/tests/test_event.py": { + "a": 13, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4300.json b/mne-python/source/doc/sphinxext/prs/4300.json new file mode 100644 index 0000000000000000000000000000000000000000..a4619a4601a937251377c2807e76be25305bd21e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4300.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "14da6b7c037a9946d1bfd33e970e4c4957258385", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4303.json b/mne-python/source/doc/sphinxext/prs/4303.json new file mode 100644 index 0000000000000000000000000000000000000000..1269c929a5e0d9f262e25c20a6e0f4c84ef38efd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4303.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "ccd2974b621274a1cdc43b4f7f66708a39c720b9", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/visualization/plot_topo_compare_conditions.py": { + "a": 3, + "d": 3 + }, + "mne/evoked.py": { + "a": 6, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 72, + "d": 41 + }, + "mne/viz/tests/test_topo.py": { + "a": 5, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 33, + "d": 16 + }, + "mne/viz/utils.py": { + "a": 40, + "d": 0 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4306.json b/mne-python/source/doc/sphinxext/prs/4306.json new file mode 100644 index 0000000000000000000000000000000000000000..430161dbab2025779aec738185ca3bf652e96d68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4306.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "000c9d29750c78b84af2e17b8d695055c14d5524", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4307.json b/mne-python/source/doc/sphinxext/prs/4307.json new file mode 100644 index 0000000000000000000000000000000000000000..0530f8bca674d80274f2877ea7509797b4fe5bee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4307.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "30c44bc1eaa06274b42fb00351c26350e8c8b9c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4310.json b/mne-python/source/doc/sphinxext/prs/4310.json new file mode 100644 index 0000000000000000000000000000000000000000..087523c5b4f967d2df7563fd8a0b11a9552b473f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4310.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "966442898b1db39fd4562a6999848653597a5d9c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/forward/_field_interpolation.py": { + "a": 6, + "d": 2 + }, + "mne/source_space.py": { + "a": 3, + "d": 3 + }, + "mne/transforms.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4315.json b/mne-python/source/doc/sphinxext/prs/4315.json new file mode 100644 index 0000000000000000000000000000000000000000..3325163f4085a9b05aba4c8dd195172114ab48f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4315.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a22466f326cdc0724b5dbd4ae5e85005193eef14", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_receptive_field.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/receptive_field.py": { + "a": 158, + "d": 81 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 70, + "d": 31 + }, + "tutorials/plot_receptive_field.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4316.json b/mne-python/source/doc/sphinxext/prs/4316.json new file mode 100644 index 0000000000000000000000000000000000000000..ace42103d64326d69dc676fec36baf5dc25bdd0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4316.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "acb6685bd2edee2216defd26d2eecc30275d51ed", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/432.json b/mne-python/source/doc/sphinxext/prs/432.json new file mode 100644 index 0000000000000000000000000000000000000000..4cf40eb3fc575293fe18f5136c28f8dc1767ffa5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/432.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b229e9dbe768998b32b83ff7b49474c197ff02e4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 16, + "d": 14 + }, + "mne/filter.py": { + "a": 105, + "d": 40 + }, + "mne/preprocessing/ecg.py": { + "a": 10, + "d": 4 + }, + "mne/preprocessing/eog.py": { + "a": 12, + "d": 5 + }, + "mne/preprocessing/ssp.py": { + "a": 9, + "d": 7 + }, + "mne/tests/test_filter.py": { + "a": 26, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4321.json b/mne-python/source/doc/sphinxext/prs/4321.json new file mode 100644 index 0000000000000000000000000000000000000000..f92b5e4ae24029b6d275797dd57fe3b9bb2c31d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4321.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b69afd1ff3337ac84f219b26c53537a5c8ceb1b9", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 17, + "d": 11 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 14, + "d": 5 + }, + "mne/beamformer/_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 200, + "d": 85 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 59, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4322.json b/mne-python/source/doc/sphinxext/prs/4322.json new file mode 100644 index 0000000000000000000000000000000000000000..7900ecf67af4b218a5fb4dfce34d92448a1110fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4322.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "b5363306d24ec645ea0d2b77a1ce652cfc4d1927", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "appveyor.yml": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 35, + "d": 43 + }, + "mne/cov.py": { + "a": 24, + "d": 16 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 40, + "d": 23 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 4, + "d": 3 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 59, + "d": 47 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 0, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 14 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 0 + }, + "mne/io/pick.py": { + "a": 10, + "d": 13 + }, + "mne/io/proj.py": { + "a": 3, + "d": 1 + }, + "mne/io/tag.py": { + "a": 4, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 6, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 20, + "d": 11 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 48, + "d": 56 + }, + "mne/simulation/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 19, + "d": 21 + }, + "mne/tests/test_chpi.py": { + "a": 11, + "d": 5 + }, + "mne/tests/test_cov.py": { + "a": 35, + "d": 39 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 0 + }, + "mne/transforms.py": { + "a": 2, + "d": 5 + }, + "mne/utils.py": { + "a": 19, + "d": 14 + }, + "mne/viz/tests/test_3d.py": { + "a": 17, + "d": 34 + }, + "mne/viz/tests/test_raw.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4324.json b/mne-python/source/doc/sphinxext/prs/4324.json new file mode 100644 index 0000000000000000000000000000000000000000..fbf2fcf5e0842cc2a4b200d5e592c894c1562a33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4324.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "671dcea98e7cef23a9e5678beee912491137f8a2", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "examples/forward/plot_forward_sensitivity_maps.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4325.json b/mne-python/source/doc/sphinxext/prs/4325.json new file mode 100644 index 0000000000000000000000000000000000000000..96e2ee05ad63e6c00a0e704f7e287f895854e139 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4325.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "76ac750d307cc99bd67037cbc8bc46497362b0a5", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4326.json b/mne-python/source/doc/sphinxext/prs/4326.json new file mode 100644 index 0000000000000000000000000000000000000000..8cd946c72973dc9933a07ff39539276ffdd66afe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4326.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1376596067158d348bf530a514e22ddb8337438c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/channels/data/montages/mgh60.elc": { + "a": 132, + "d": 0 + }, + "mne/channels/data/montages/mgh70.elc": { + "a": 152, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 10, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 18, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4332.json b/mne-python/source/doc/sphinxext/prs/4332.json new file mode 100644 index 0000000000000000000000000000000000000000..8e16e1155ee4054d665f0518d5cf96ac0604ae04 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4332.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "42323bfc7e7ecf306ba3bfe5aac953a2130d5bae", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/forward/plot_read_bem_surfaces.py": { + "a": 0, + "d": 32 + }, + "examples/visualization/plot_3d_to_2d.py": { + "a": 4, + "d": 3 + }, + "examples/visualization/plot_eeg_on_scalp.py": { + "a": 4, + "d": 4 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 6, + "d": 4 + }, + "mne/bem.py": { + "a": 6, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 4, + "d": 3 + }, + "mne/source_space.py": { + "a": 27, + "d": 5 + }, + "mne/surface.py": { + "a": 11, + "d": 0 + }, + "mne/tests/test_report.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 509, + "d": 3 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 4, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 69, + "d": 25 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_ecog.py": { + "a": 5, + "d": 3 + }, + "tutorials/plot_forward.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_source_alignment.py": { + "a": 98, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4333.json b/mne-python/source/doc/sphinxext/prs/4333.json new file mode 100644 index 0000000000000000000000000000000000000000..4e1d77517bb258d11419a6342437bf9d934667de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4333.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "40a66bde3326263b2ef32dc002a260d09edcb2f5", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 23, + "d": 15 + }, + "mne/decoding/tests/test_base.py": { + "a": 78, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4337.json b/mne-python/source/doc/sphinxext/prs/4337.json new file mode 100644 index 0000000000000000000000000000000000000000..41414b0c97547d346b26fa9b5b8a2572852f70ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4337.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "07954161fc77636d7d28b00e5a4f1143a5c748e7", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 4, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 38, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4339.json b/mne-python/source/doc/sphinxext/prs/4339.json new file mode 100644 index 0000000000000000000000000000000000000000..d29262e0e05a0e538f21f6d541d97f90b1d71728 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4339.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ad4ccbe285e6d92e3dac68fccda36da7658f49d1", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 6, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/434.json b/mne-python/source/doc/sphinxext/prs/434.json new file mode 100644 index 0000000000000000000000000000000000000000..77194e3cd3269597aaf732630f2fce586bbe0ed3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/434.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "342555b5026488f25403263fe92b6f838944c6a6", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/event.py": { + "a": 169, + "d": 62 + }, + "mne/tests/test_event.py": { + "a": 65, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4341.json b/mne-python/source/doc/sphinxext/prs/4341.json new file mode 100644 index 0000000000000000000000000000000000000000..0ea479995daadde94d86de8d591726640bedb568 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4341.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "ae380ee984031b9d70bcc4abf9161e0478d10427", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 76, + "d": 39 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 16, + "d": 10 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4344.json b/mne-python/source/doc/sphinxext/prs/4344.json new file mode 100644 index 0000000000000000000000000000000000000000..c78038331303d9c95f39ad14bc2a6c95feefb0c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4344.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "12de055f9f2755430f33ba81e785d75a80a75228", + "authors": [ + { + "n": "Annalisa Pascarella", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/source_space.py": { + "a": 45, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 31, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4345.json b/mne-python/source/doc/sphinxext/prs/4345.json new file mode 100644 index 0000000000000000000000000000000000000000..402e6942bd5b1df9d7bd3c559961415c30359f45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4345.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d0ba4b355bc88165b9e29b379599f0468e1bd5e9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 14, + "d": 5 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 21, + "d": 9 + }, + "mne/viz/raw.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4346.json b/mne-python/source/doc/sphinxext/prs/4346.json new file mode 100644 index 0000000000000000000000000000000000000000..ecffd0f7f8f0cfe2125e7f3a90e7357a821bc7a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4346.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "3dc19624816b02fe750de44c0100bb925bd67cb4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 3, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 30, + "d": 5 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_visualize_raw.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4347.json b/mne-python/source/doc/sphinxext/prs/4347.json new file mode 100644 index 0000000000000000000000000000000000000000..a5f44c8a3b0a54f73a62629562588156a1081725 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4347.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "032c654121907a490d11dafb87b4e9ea27c1ed85", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 2 + }, + "examples/visualization/make_report.py": { + "a": 23, + "d": 10 + }, + "mne/commands/mne_report.py": { + "a": 6, + "d": 1 + }, + "mne/report.py": { + "a": 135, + "d": 131 + }, + "mne/tests/test_report.py": { + "a": 10, + "d": 0 + }, + "mne/transforms.py": { + "a": 14, + "d": 9 + }, + "mne/viz/_3d.py": { + "a": 15, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4348.json b/mne-python/source/doc/sphinxext/prs/4348.json new file mode 100644 index 0000000000000000000000000000000000000000..7359de7c91cfd530f313db1184acb476a6b99298 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4348.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ce59e1dd07acb9750178f512a18cc9e29c97a3da", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4349.json b/mne-python/source/doc/sphinxext/prs/4349.json new file mode 100644 index 0000000000000000000000000000000000000000..c156bc871e751e95dc5f01788fb6d471770c0da6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4349.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "f6791a47f8e763bf5c35817fcf5a4c9448f9536f", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 4 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 22, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 15 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 20, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4351.json b/mne-python/source/doc/sphinxext/prs/4351.json new file mode 100644 index 0000000000000000000000000000000000000000..a5a4a70ee956309935d004d1b670a6cb3d811804 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4351.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "24ce31b48eb0921924573330149ba61f2b0e15ad", + "authors": [ + { + "n": "robintibor", + "e": "robintibor@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4354.json b/mne-python/source/doc/sphinxext/prs/4354.json new file mode 100644 index 0000000000000000000000000000000000000000..2f31dc283dd3fed57f5b15e9bfed1283d666bd7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4354.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "541bf857d7296fd1944fe59d63c6527d3b8771c1", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 21, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4355.json b/mne-python/source/doc/sphinxext/prs/4355.json new file mode 100644 index 0000000000000000000000000000000000000000..a87f838a379889744d17be0f5727743b7ed0156d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4355.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "6e61eb5147d25da0618b2d2b91b538141e9a8b49", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 16, + "d": 6 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/dipole.py": { + "a": 228, + "d": 74 + }, + "mne/source_space.py": { + "a": 22, + "d": 15 + }, + "mne/tests/test_dipole.py": { + "a": 51, + "d": 28 + }, + "tutorials/plot_dipole_fit.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4356.json b/mne-python/source/doc/sphinxext/prs/4356.json new file mode 100644 index 0000000000000000000000000000000000000000..58f890ded2b3e46da634154a861be36674e7e76a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4356.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5a9fe0332a768334b0e200a6b5ce50f0af3c4805", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 184, + "d": 6 + }, + "mne/channels/layout.py": { + "a": 4, + "d": 32 + }, + "mne/channels/tests/test_channels.py": { + "a": 44, + "d": 3 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4357.json b/mne-python/source/doc/sphinxext/prs/4357.json new file mode 100644 index 0000000000000000000000000000000000000000..f7c9d02df0389738040fb68bfb5d47f1ef9cd457 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4357.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8ab4ac83359a789a8efbc94c217c3af9a44016a1", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 14, + "d": 12 + }, + "mne/io/tests/test_reference.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4358.json b/mne-python/source/doc/sphinxext/prs/4358.json new file mode 100644 index 0000000000000000000000000000000000000000..4001205aadfbad427832707afcb05e55d6c9cc74 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4358.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3c69124e598b101e50996d110f5e64e360216b8f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 60, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/436.json b/mne-python/source/doc/sphinxext/prs/436.json new file mode 100644 index 0000000000000000000000000000000000000000..6f800f965b02a6aa6e6483bc48725aba44e5ada4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/436.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b05cccb509800f1c93af912cf0a87bc733f87159", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "mne/forward.py": { + "a": 111, + "d": 0 + }, + "mne/tests/test_forward.py": { + "a": 93, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4362.json b/mne-python/source/doc/sphinxext/prs/4362.json new file mode 100644 index 0000000000000000000000000000000000000000..694db274e7e69b5462099449a025223537efc365 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4362.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "99e10b1c90fa665b603f7dc93c3d2c3a5ba4ee04", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4363.json b/mne-python/source/doc/sphinxext/prs/4363.json new file mode 100644 index 0000000000000000000000000000000000000000..82fc304fbdaa74b58952c51396d247b13f74468c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4363.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "15a0856f15538200b8b2eb236b610342502551cf", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4365.json b/mne-python/source/doc/sphinxext/prs/4365.json new file mode 100644 index 0000000000000000000000000000000000000000..113b1334ebdec34a301412b77c5b33cfec7e0ee6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4365.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cbcbc43e98369622a90b8b025876be5b14f3f287", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 0 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/437.json b/mne-python/source/doc/sphinxext/prs/437.json new file mode 100644 index 0000000000000000000000000000000000000000..bbacb4ed8993451eb2bdcde8274c2d0223ad5232 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/437.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "7f537474e7a4846d62ea077b9c56b3d22736815f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 1 + }, + "examples/plot_read_and_write_raw_data.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/tests/data/fsaverage_audvis-meg-cropped-lh.stc": { + "a": 0, + "d": 0 + }, + "mne/fiff/tests/data/fsaverage_audvis-meg-cropped-rh.stc": { + "a": 0, + "d": 0 + }, + "mne/forward.py": { + "a": 18, + "d": 22 + }, + "mne/minimum_norm/inverse.py": { + "a": 12, + "d": 5 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 17, + "d": 11 + }, + "mne/mixed_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 19, + "d": 16 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 22, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4371.json b/mne-python/source/doc/sphinxext/prs/4371.json new file mode 100644 index 0000000000000000000000000000000000000000..c13f0fce75da474d2adf8366174acd1521ae43f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4371.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "593da2a002b9cfe3df158fa7017be6fa67f8dbb6", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 38, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4373.json b/mne-python/source/doc/sphinxext/prs/4373.json new file mode 100644 index 0000000000000000000000000000000000000000..fb2c20b2cb6258b2a00f0e93ba25ccbf4114130e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4373.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e68219bf8afe4c948534aa625cf1d010e85148ff", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 13, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4376.json b/mne-python/source/doc/sphinxext/prs/4376.json new file mode 100644 index 0000000000000000000000000000000000000000..c0e93d5b4b26414d328799edd868229364e16bc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4376.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f2edf685353b54e3d307bbb77115fd927b84d1d6", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 9, + "d": 13 + }, + "mne/preprocessing/xdawn.py": { + "a": 4, + "d": 8 + }, + "mne/utils.py": { + "a": 1, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4379.json b/mne-python/source/doc/sphinxext/prs/4379.json new file mode 100644 index 0000000000000000000000000000000000000000..da56cd8a1f99e4a3bc364235195745489cc9dca4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4379.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "67d9cec9f99016221415790c220caa203d386916", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "mne/dipole.py": { + "a": 5, + "d": 25 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/438.json b/mne-python/source/doc/sphinxext/prs/438.json new file mode 100644 index 0000000000000000000000000000000000000000..701682ad42899607aad44030faea54b932d1512f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/438.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0037034f90b49541592cc9fa08aecf12dcfb397c", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "mne/simulation/source.py": { + "a": 19, + "d": 7 + }, + "mne/simulation/tests/test_source.py": { + "a": 51, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4380.json b/mne-python/source/doc/sphinxext/prs/4380.json new file mode 100644 index 0000000000000000000000000000000000000000..151367f7c3ea1a8ae511a3b0b0aa80b2fc7bcfd4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4380.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "62d2139c9c05b37835111cc15d67416558ee6fa2", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/commands/utils.py": { + "a": 38, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4382.json b/mne-python/source/doc/sphinxext/prs/4382.json new file mode 100644 index 0000000000000000000000000000000000000000..47dda87e2da6f3e236beb461b65224796e430b13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4382.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "dddbd843e46eaa0dd91d90880eaf4034f4ce05bc", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 41, + "d": 33 + }, + "mne/io/reference.py": { + "a": 83, + "d": 55 + }, + "mne/io/tests/test_reference.py": { + "a": 24, + "d": 7 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 12, + "d": 10 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ssp.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_compute_covariance.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_eeg_erp.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4383.json b/mne-python/source/doc/sphinxext/prs/4383.json new file mode 100644 index 0000000000000000000000000000000000000000..ac8d632b70c09b69c8728f7d7bc532c7f5edb332 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4383.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c2fc6dba536f159068f2d0b3cb27839d867db7c0", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_xhemi.py": { + "a": 47, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 57, + "d": 25 + }, + "mne/surface.py": { + "a": 109, + "d": 78 + }, + "mne/tests/test_surface.py": { + "a": 20, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4384.json b/mne-python/source/doc/sphinxext/prs/4384.json new file mode 100644 index 0000000000000000000000000000000000000000..ba6cc95ea8a53b9e9aa00185dce9ecc169af0215 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4384.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6216b79bd9f8ed7c50bfa11c27c5d130b4b26dba", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 60, + "d": 23 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 14, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4387.json b/mne-python/source/doc/sphinxext/prs/4387.json new file mode 100644 index 0000000000000000000000000000000000000000..e184fa9a85f4b8992458233894a7152e3a38f9d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4387.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5d1fc7af7301a26f3415a876efee3c08cda28bb1", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 1 + }, + "MANIFEST.in": { + "a": 41, + "d": 19 + }, + "mne/viz/tests/__init__py": { + "a": 0, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4388.json b/mne-python/source/doc/sphinxext/prs/4388.json new file mode 100644 index 0000000000000000000000000000000000000000..a1737ffaa9c4f118ee4b7b8ef8256a155ce2764f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4388.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6d563135f4d9cb0312b5492b78d204f2e1580ce9", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4389.json b/mne-python/source/doc/sphinxext/prs/4389.json new file mode 100644 index 0000000000000000000000000000000000000000..10fa412dc85cc89eee179e15596c1a7c4e9de4f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4389.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0b58905d8b4da181c050866f77925db745e9d1b9", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 353, + "d": 102 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4394.json b/mne-python/source/doc/sphinxext/prs/4394.json new file mode 100644 index 0000000000000000000000000000000000000000..e9b25f26f675987b4dd1ea66d496667b529eef8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4394.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6840bb56ccbc642f77607072cc549ce7e5c86794", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4399.json b/mne-python/source/doc/sphinxext/prs/4399.json new file mode 100644 index 0000000000000000000000000000000000000000..b0bbf54e3ed4496887070cf2f528a7a07fa55d2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4399.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e2cb866381273824459909270e8188c62a645822", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/44.json b/mne-python/source/doc/sphinxext/prs/44.json new file mode 100644 index 0000000000000000000000000000000000000000..6eab5ce5f545309ea49fded3dd21a653b15c9344 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/44.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9d946c7ff78141433fa7ed5fa7bb443ca855659c", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 13, + "d": 13 + }, + "bin/mne_compute_proj_eog.py": { + "a": 13, + "d": 13 + }, + "bin/mne_maxfilter.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/440.json b/mne-python/source/doc/sphinxext/prs/440.json new file mode 100644 index 0000000000000000000000000000000000000000..fa391e318edee7931b2a4ed267205452885048d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/440.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "60cd1bece96954c0f56f8fb415f2c5b39bace109", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 37, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4400.json b/mne-python/source/doc/sphinxext/prs/4400.json new file mode 100644 index 0000000000000000000000000000000000000000..4b9b1d9d8cd3289b3aeaddec03d59617512d93d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4400.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c0013f35286e0134e37f8c7109f86d5c5c1b49bd", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/data/montages/10-5_EGI129.csd": { + "a": 0, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 42, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4401.json b/mne-python/source/doc/sphinxext/prs/4401.json new file mode 100644 index 0000000000000000000000000000000000000000..d4fe251f9b5055d543c41ba4885814185320374e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4401.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1a80a0e3b05b75bb96af3834757814d2c8ca83a1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 6, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4405.json b/mne-python/source/doc/sphinxext/prs/4405.json new file mode 100644 index 0000000000000000000000000000000000000000..2f3da189af7bbeca572f93d9ab46984105405608 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4405.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "828c241e66f5e4f1b26b96196e6beab880b230a2", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4406.json b/mne-python/source/doc/sphinxext/prs/4406.json new file mode 100644 index 0000000000000000000000000000000000000000..8a862f950c4cbdd02c7ca27d2a076298419583a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4406.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "778d532a1e3ff20d9d9e1a0755f8001133206c7e", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/441.json b/mne-python/source/doc/sphinxext/prs/441.json new file mode 100644 index 0000000000000000000000000000000000000000..7352bb14ab15acd27ce80f991fec9ecbffc33493 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/441.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0b3f22b7ff8adacecb05328b70b548547f773660", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/tests/data/fsaverage_audvis-meg-cropped-lh.stc": { + "a": 0, + "d": 0 + }, + "mne/fiff/tests/data/fsaverage_audvis-meg-cropped-rh.stc": { + "a": 0, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 4, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4413.json b/mne-python/source/doc/sphinxext/prs/4413.json new file mode 100644 index 0000000000000000000000000000000000000000..4de72ca6972070c365d14cc4e6c62cbe0aad4a05 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4413.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "58e051aba3b3a35ae5b0db2c0d49339223da1ce2", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/commands/mne_coreg.py": { + "a": 3, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 4, + "d": 2 + }, + "mne/gui/_coreg_gui.py": { + "a": 92, + "d": 76 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4414.json b/mne-python/source/doc/sphinxext/prs/4414.json new file mode 100644 index 0000000000000000000000000000000000000000..9e7e2d277c697937891057262f52341a845e9e2d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4414.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "7ad946f01bdc901581efcae235c6a207d9d656f1", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "circle.yml": { + "a": 7, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/manual/datasets_index.rst": { + "a": 11, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_metadata_query.py": { + "a": 108, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/kiloword/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 55, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 11, + "d": 4 + }, + "mne/datasets/visual_92_categories/__init__.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/visual_92_categories/visual_92_categories.py": { + "a": 4, + "d": 22 + }, + "mne/epochs.py": { + "a": 210, + "d": 47 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/io/constants.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 181, + "d": 28 + }, + "mne/utils.py": { + "a": 9, + "d": 5 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 7, + "d": 0 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 0, + "d": 2 + }, + "tutorials/plot_metadata_epochs.py": { + "a": 109, + "d": 0 + }, + "tutorials/plot_object_epochs.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4416.json b/mne-python/source/doc/sphinxext/prs/4416.json new file mode 100644 index 0000000000000000000000000000000000000000..268b520bf5014c589827b396c2e76803583bfc1e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4416.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "49007cf33e6674ffe3049e0dae375249dc9a3d2f", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4418.json b/mne-python/source/doc/sphinxext/prs/4418.json new file mode 100644 index 0000000000000000000000000000000000000000..bd8cf6b903729559074421864dff73e11ac93021 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4418.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "62627553e06949ac0bc7e92fffcf07031976cbb8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 4, + "d": 2 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 13, + "d": 0 + }, + "mne/forward/_field_interpolation.py": { + "a": 4, + "d": 2 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/442.json b/mne-python/source/doc/sphinxext/prs/442.json new file mode 100644 index 0000000000000000000000000000000000000000..790744c0502f522307c523d54cb3c4a553acb73f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/442.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f0402859017622176f136c72c6c113b7031faaf1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_viz.py": { + "a": 10, + "d": 1 + }, + "mne/viz.py": { + "a": 50, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4422.json b/mne-python/source/doc/sphinxext/prs/4422.json new file mode 100644 index 0000000000000000000000000000000000000000..30388ea75508884d384cab4db1fc40e841905c42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4422.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "51d554ef9a2530877899a7eac33090851e8110ff", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 15, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 17, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4424.json b/mne-python/source/doc/sphinxext/prs/4424.json new file mode 100644 index 0000000000000000000000000000000000000000..bd18b8431fa25217e7abdd3dec6ff49965c23bf9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4424.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b3a54072cd67068269d300d51def4014c1af1719", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 4, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 14, + "d": 7 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 11 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4426.json b/mne-python/source/doc/sphinxext/prs/4426.json new file mode 100644 index 0000000000000000000000000000000000000000..9d4e06fae142e1af6ff42b9780bfa31e92e1f2d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4426.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a5677e94ea2f32ed9b5d7175c4215f44051bd2f8", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 83, + "d": 31 + }, + "mne/tests/test_source_estimate.py": { + "a": 84, + "d": 36 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4427.json b/mne-python/source/doc/sphinxext/prs/4427.json new file mode 100644 index 0000000000000000000000000000000000000000..ed80377a1e69272c3f6dc7ee535dbca4369c5d9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4427.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5d8d11a665f2d2736cdbac0cadb832b5f78c9e76", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 5, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4428.json b/mne-python/source/doc/sphinxext/prs/4428.json new file mode 100644 index 0000000000000000000000000000000000000000..0bf6ab44a5f0d8bfc2a98d5b423cb9bbfcb1706f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4428.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3791f9c945f5f411e87a19dbf05295bec891c79b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_docstring_parameters.py": { + "a": 125, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4429.json b/mne-python/source/doc/sphinxext/prs/4429.json new file mode 100644 index 0000000000000000000000000000000000000000..0e6420658e34fd7b2267325bfd299c22322aaf20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4429.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bde61eddb0dc133f2e500a7429e2ed1744358416", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 41, + "d": 26 + }, + "Makefile": { + "a": 13, + "d": 16 + }, + "appveyor.yml": { + "a": 3, + "d": 4 + }, + "mne/io/tests/test_pick.py": { + "a": 3, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/443.json b/mne-python/source/doc/sphinxext/prs/443.json new file mode 100644 index 0000000000000000000000000000000000000000..9b866e8d0a0a8875c1d7f9dd54a98828a003fc64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/443.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "32d2ec90d60b132d6e893bfe954937f975297ecd", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 6, + "d": 3 + }, + "mne/fiff/evoked.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4432.json b/mne-python/source/doc/sphinxext/prs/4432.json new file mode 100644 index 0000000000000000000000000000000000000000..9da1b0d10f10afa65a498e0c894480a346792509 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4432.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "74f9b3fd9f63795a7e4f81a284cc783107ce6550", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4433.json b/mne-python/source/doc/sphinxext/prs/4433.json new file mode 100644 index 0000000000000000000000000000000000000000..7a7efcbfaf45146d09517b9f2527bba6b2c15390 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4433.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "578613071dcb1bd4bc4ecb034ca072adb2c9b55a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 3, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4435.json b/mne-python/source/doc/sphinxext/prs/4435.json new file mode 100644 index 0000000000000000000000000000000000000000..0d16346bb7ae081b87b58029690837a37a8e4d98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4435.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "01ba44236708589fbc6f7dbd566b0c83ff5e6835", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 15, + "d": 19 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/csp.py": { + "a": 19, + "d": 35 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4437.json b/mne-python/source/doc/sphinxext/prs/4437.json new file mode 100644 index 0000000000000000000000000000000000000000..c01d1f84c05fb1b9d6c86270d5b9135ed0b81032 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4437.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8f4e1d8c97d88af5d98beb5a33587bf3acd52c2a", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4439.json b/mne-python/source/doc/sphinxext/prs/4439.json new file mode 100644 index 0000000000000000000000000000000000000000..05d783c2cc5a5fd1624e6b6c2008e5c9abc65409 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4439.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e2c5128f6a6a4060870f95281587a1b5db023ae7", + "authors": [ + { + "n": "Lukáš Hejtmánek", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/444.json b/mne-python/source/doc/sphinxext/prs/444.json new file mode 100644 index 0000000000000000000000000000000000000000..3f4764b8e21d9cfda61098fe6b308e91c0e7cda9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/444.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "169f52bb934ce68fcdea2ca804377d6eb02230f6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 72, + "d": 0 + }, + "mne/fiff/tests/test_pick.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/tests/test_raw.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4440.json b/mne-python/source/doc/sphinxext/prs/4440.json new file mode 100644 index 0000000000000000000000000000000000000000..fa2dd1eb63e9ed4e3cd0b721173a23ed4fe8c4de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4440.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "32a7c88c20151e7086f6fda0dc517b5acff8b6da", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4441.json b/mne-python/source/doc/sphinxext/prs/4441.json new file mode 100644 index 0000000000000000000000000000000000000000..e814d44497d6834622bc8d10135e4cef6ce677c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4441.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "af0753b6627e8eec958c84fa89face45bb4eac84", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4442.json b/mne-python/source/doc/sphinxext/prs/4442.json new file mode 100644 index 0000000000000000000000000000000000000000..81e8491a5ae52e5a178a2831bb4a9672e07bdae4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4442.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cb6a7ff692c6625dd8a59470f9706a627e3e2571", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4443.json b/mne-python/source/doc/sphinxext/prs/4443.json new file mode 100644 index 0000000000000000000000000000000000000000..ea670bb5194a4c531a62a09729804929521aa7df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4443.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "79a0eb102fa3a1cd58b0574ae97c28341803e8b4", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "tutorials/plot_forward.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4444.json b/mne-python/source/doc/sphinxext/prs/4444.json new file mode 100644 index 0000000000000000000000000000000000000000..f9abc2d6f98854fd20918d4902908b1d30cbb0f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4444.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "25c1e644d64dc6ec83776508591c7206031a15a9", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/gui/_coreg_gui.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_file_traits.py": { + "a": 36, + "d": 4 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 15, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4447.json b/mne-python/source/doc/sphinxext/prs/4447.json new file mode 100644 index 0000000000000000000000000000000000000000..b1edabde87df86be3e935ba3eb6c2051c13686a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4447.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a412bac98d22ee759d67e7977bdf953bbdb2f120", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4448.json b/mne-python/source/doc/sphinxext/prs/4448.json new file mode 100644 index 0000000000000000000000000000000000000000..96e96b067adc2ca156c7dfe7ce45755810af68f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4448.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b956419dfcf9c615c0c08784689d3d79f7f662e8", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "tutorials/plot_object_epochs.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_object_raw.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4449.json b/mne-python/source/doc/sphinxext/prs/4449.json new file mode 100644 index 0000000000000000000000000000000000000000..aa8d429f96832693648d6fb75fd8d527385d6162 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4449.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fec3aae7e78cba4da6ce790265b54817430e4aa5", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4451.json b/mne-python/source/doc/sphinxext/prs/4451.json new file mode 100644 index 0000000000000000000000000000000000000000..544072d1b769ba2b1bf47ef8ffedc78773d4d6c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4451.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "71eb161e3e95dbc0dbb456fd97c247bc85c01fb0", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4453.json b/mne-python/source/doc/sphinxext/prs/4453.json new file mode 100644 index 0000000000000000000000000000000000000000..431ea34455e4801eff5f0a2489c1f2354081a027 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4453.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "372bdcecce8272ada0094583a06d66b1d6d2e565", + "authors": [ + { + "n": "jaeilepp", + "e": "jaeilepp@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4456.json b/mne-python/source/doc/sphinxext/prs/4456.json new file mode 100644 index 0000000000000000000000000000000000000000..a9da4fa0d35c55840d5f49106a02154e2baffd2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4456.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "916b168270d01d81f3cc6286190aa83bdceee6bd", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 16, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4458.json b/mne-python/source/doc/sphinxext/prs/4458.json new file mode 100644 index 0000000000000000000000000000000000000000..150a7d4820e259da2695028d14f225320ea6d1d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4458.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1486a513435e7fe030543b3691c00c31fdbfd401", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 5, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_space.py": { + "a": 6, + "d": 5 + }, + "mne/tests/test_dipole.py": { + "a": 6, + "d": 5 + }, + "mne/tests/test_source_space.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4460.json b/mne-python/source/doc/sphinxext/prs/4460.json new file mode 100644 index 0000000000000000000000000000000000000000..9593ce53d872536c6deadcfa7ddad27a3ff28634 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4460.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f9f98e189f0ab6f74dcb31acae2329bb120399e6", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_forward.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4461.json b/mne-python/source/doc/sphinxext/prs/4461.json new file mode 100644 index 0000000000000000000000000000000000000000..c85460d64289a64e93f86d919ce9b0ca67e5f2e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4461.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "134c50f731beed3913f2e2c24a0c3c60aae952f2", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_run_ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 14, + "d": 0 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4464.json b/mne-python/source/doc/sphinxext/prs/4464.json new file mode 100644 index 0000000000000000000000000000000000000000..e11b1726605040959d18caa59542eead985b9d41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4464.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3f40409c849080e6dd5a62c460427c3bad2992f3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 11, + "d": 3 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4465.json b/mne-python/source/doc/sphinxext/prs/4465.json new file mode 100644 index 0000000000000000000000000000000000000000..b59a9f515902cd1b286741d756822a62efca0ba1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4465.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5c8e9665e674663e1ed5ae4c3093a91a2378412a", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 52, + "d": 89 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4466.json b/mne-python/source/doc/sphinxext/prs/4466.json new file mode 100644 index 0000000000000000000000000000000000000000..62e11c1845d1db729a51bd364291ecf55213dbd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4466.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c439aef13a8ee2e600c34a0acf70899ea9d3e0b7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4468.json b/mne-python/source/doc/sphinxext/prs/4468.json new file mode 100644 index 0000000000000000000000000000000000000000..c58dfd99e8f5b3a07747783f1d688d6d41401238 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4468.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "601a98f580aafbee3ea7687d91ffda7e83b57af5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 18, + "d": 8 + }, + "doc/documentation.rst": { + "a": 0, + "d": 1 + }, + "doc/manual/cookbook.rst": { + "a": 2, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 15, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 22, + "d": 22 + }, + "examples/decoding/decoding_rsa.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 3, + "d": 1 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 3, + "d": 3 + }, + "examples/preprocessing/plot_resample.py": { + "a": 0, + "d": 2 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 6 + }, + "mne/decoding/mixin.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 1 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_compute_covariance.py": { + "a": 7, + "d": 5 + }, + "tutorials/plot_creating_data_structures.py": { + "a": 5, + "d": 4 + }, + "tutorials/plot_info.py": { + "a": 15, + "d": 17 + }, + "tutorials/plot_modifying_data_inplace.py": { + "a": 11, + "d": 12 + }, + "tutorials/plot_object_epochs.py": { + "a": 6, + "d": 8 + }, + "tutorials/plot_object_evoked.py": { + "a": 6, + "d": 4 + }, + "tutorials/plot_object_raw.py": { + "a": 15, + "d": 18 + }, + "tutorials/plot_python_intro.py": { + "a": 24, + "d": 24 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/447.json b/mne-python/source/doc/sphinxext/prs/447.json new file mode 100644 index 0000000000000000000000000000000000000000..5f0729af88cb91c3ec0caa22b16070ca932a5679 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/447.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f0ec89479364df5ab4dad5ddf099938cc92e2136", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/parallel.py": { + "a": 38, + "d": 6 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4470.json b/mne-python/source/doc/sphinxext/prs/4470.json new file mode 100644 index 0000000000000000000000000000000000000000..69c6e864e1c680200a98bf51a9d47017dfac0f15 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4470.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "61a531a78e46a6d042c5f14e238dc7fec14d8a62", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 36, + "d": 0 + }, + "mne/io/base.py": { + "a": 52, + "d": 33 + }, + "mne/tests/test_annotations.py": { + "a": 93, + "d": 6 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4476.json b/mne-python/source/doc/sphinxext/prs/4476.json new file mode 100644 index 0000000000000000000000000000000000000000..6941127e947eecd4987cd502999e8209329f27fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4476.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "93b342eb589471c1d6ec46725cd61fcf8d312d53", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 13, + "d": 4 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 6, + "d": 5 + }, + "mne/epochs.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4478.json b/mne-python/source/doc/sphinxext/prs/4478.json new file mode 100644 index 0000000000000000000000000000000000000000..202501a7403009ff415706867a6644708e68cdba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4478.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7097a122d682a7b09dcee6c2be0de38a3239a141", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 158, + "d": 150 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 87, + "d": 61 + }, + "mne/stats/tests/test_permutations.py": { + "a": 10, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/448.json b/mne-python/source/doc/sphinxext/prs/448.json new file mode 100644 index 0000000000000000000000000000000000000000..66821eeefc00764e8b461e866339fda574eb0c12 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/448.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a94e6db67890d95be0cda54437f1e647b3e3a9f6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cuda.py": { + "a": 53, + "d": 34 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 4, + "d": 16 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 21, + "d": 10 + }, + "mne/utils.py": { + "a": 49, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4482.json b/mne-python/source/doc/sphinxext/prs/4482.json new file mode 100644 index 0000000000000000000000000000000000000000..94372d4eeff05ae8645dc3e226594b7f2d738e57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4482.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "27413cbfcbbec4eab0778e80439eb34e93dd3e90", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 7, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 29, + "d": 18 + }, + "mne/channels/tests/test_montage.py": { + "a": 14, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4483.json b/mne-python/source/doc/sphinxext/prs/4483.json new file mode 100644 index 0000000000000000000000000000000000000000..2e06f000d7983e8e25488167874a181262ad1219 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4483.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "be4c1739167643d4b14aba3780b35d3d6b83eb3f", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 13, + "d": 6 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4485.json b/mne-python/source/doc/sphinxext/prs/4485.json new file mode 100644 index 0000000000000000000000000000000000000000..8a134abfcfa0633ba36f79286d156aba5057bb42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4485.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "6286b04e1214d0be8c2cda8c16ae0d1c8c8db2d8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_search_light.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 10, + "d": 6 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 8 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 9, + "d": 9 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 4, + "d": 3 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 3, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 1 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 2, + "d": 1 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 17 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4487.json b/mne-python/source/doc/sphinxext/prs/4487.json new file mode 100644 index 0000000000000000000000000000000000000000..e1edc23ea0277e4ef192717469f94784a354573b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4487.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "171996ee7bd014993448d6222ff1f48c3bdcaaea", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 5, + "d": 3 + }, + "doc/conf.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4488.json b/mne-python/source/doc/sphinxext/prs/4488.json new file mode 100644 index 0000000000000000000000000000000000000000..790d348007b3e4864bc1e29a1dc5c02346cfb0f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4488.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "20cead898c64b5f78f513ec97ce84b4ef5ede366", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + }, + "doc/_templates/layout.html": { + "a": 24, + "d": 3 + }, + "doc/conf.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4490.json b/mne-python/source/doc/sphinxext/prs/4490.json new file mode 100644 index 0000000000000000000000000000000000000000..a856022e2b7562bf103a50c2012467aa58793fa8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4490.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aa371d291bb0b373b55090cbaa3336dc2507dc1d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "appveyor.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4492.json b/mne-python/source/doc/sphinxext/prs/4492.json new file mode 100644 index 0000000000000000000000000000000000000000..ab5c678c4b42909d2fab2ee4b7bd47c248fd76e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4492.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "96bc9909107b078701c86c9d69004a357f1d9a65", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 7, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4495.json b/mne-python/source/doc/sphinxext/prs/4495.json new file mode 100644 index 0000000000000000000000000000000000000000..56d063cd9dd0267350f5d62b375ab555709ffa77 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4495.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aa6ad318087e179c1984df2377399a89c86858af", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/tests/test_montage.py": { + "a": 27, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/45.json b/mne-python/source/doc/sphinxext/prs/45.json new file mode 100644 index 0000000000000000000000000000000000000000..ad65eb961fb44822a12d7454b92a507a837f5a56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/45.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d622caa3ffdcb74c561141cb4b6dbf1e8e2654a5", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 15, + "d": 3 + }, + "bin/mne_compute_proj_eog.py": { + "a": 15, + "d": 3 + }, + "mne/preprocessing/ssp.py": { + "a": 23, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/450.json b/mne-python/source/doc/sphinxext/prs/450.json new file mode 100644 index 0000000000000000000000000000000000000000..ac96814462371befabc9340719784696919ada99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/450.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2fdd8867b0209f8b97ce99c1120ec4cc37d7e84f", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4500.json b/mne-python/source/doc/sphinxext/prs/4500.json new file mode 100644 index 0000000000000000000000000000000000000000..ec1680d893070786a4951d94cbb40e3d3a3b8bf0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4500.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2fd1241562e4086f6ae046994ff568af3e086817", + "authors": [ + { + "n": "Alejandro Weinstein", + "e": "alejandro.weinstein@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4504.json b/mne-python/source/doc/sphinxext/prs/4504.json new file mode 100644 index 0000000000000000000000000000000000000000..c78503968c6a22e1578383a7d21c7eedd4c4a42e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4504.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "ed67c91916022b2d6afd47aa2d01ea23d980336e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/carousel.inc": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_3d_to_2d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 12, + "d": 4 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 7, + "d": 7 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4505.json b/mne-python/source/doc/sphinxext/prs/4505.json new file mode 100644 index 0000000000000000000000000000000000000000..2b815dfeb6a512cab481936338edc6499635ede8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4505.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "881724422db9c50d45b13b0c374adddea7d14fc0", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4509.json b/mne-python/source/doc/sphinxext/prs/4509.json new file mode 100644 index 0000000000000000000000000000000000000000..7d7c20b90d8437fb7e9b53c8f75757eb32dffb81 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4509.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "65ebb736fb2d236609b32ba1a6283072d16c4138", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/451.json b/mne-python/source/doc/sphinxext/prs/451.json new file mode 100644 index 0000000000000000000000000000000000000000..579f1f26656931f86e127606da6e9c38a66fe49a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/451.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ae3708758ac342e123cf333f800ef95b7c2c0707", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 41, + "d": 41 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4510.json b/mne-python/source/doc/sphinxext/prs/4510.json new file mode 100644 index 0000000000000000000000000000000000000000..9d707b4317a54e60d07d1829c94fb29470a4436c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4510.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "187f098409b9688c91f7843bdafec97db2df9aa5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/pick.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 15, + "d": 11 + }, + "mne/viz/ica.py": { + "a": 10, + "d": 9 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 6, + "d": 8 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 17, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4511.json b/mne-python/source/doc/sphinxext/prs/4511.json new file mode 100644 index 0000000000000000000000000000000000000000..aae55b21d1c88fbb9b59ccbbf3baab5243245829 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4511.json @@ -0,0 +1,231 @@ +{ + "merge_commit_sha": "e5498454977ec9208011c48146dfac6fc9d84ca9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 2, + "d": 4 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 1, + "d": 2 + }, + "examples/visualization/plot_topo_compare_conditions.py": { + "a": 1, + "d": 9 + }, + "mne/beamformer/_rap_music.py": { + "a": 4, + "d": 4 + }, + "mne/channels/channels.py": { + "a": 33, + "d": 21 + }, + "mne/channels/layout.py": { + "a": 16, + "d": 18 + }, + "mne/cov.py": { + "a": 7, + "d": 15 + }, + "mne/decoding/ems.py": { + "a": 4, + "d": 6 + }, + "mne/decoding/transformer.py": { + "a": 5, + "d": 6 + }, + "mne/epochs.py": { + "a": 14, + "d": 26 + }, + "mne/evoked.py": { + "a": 5, + "d": 5 + }, + "mne/filter.py": { + "a": 17, + "d": 34 + }, + "mne/io/base.py": { + "a": 22, + "d": 72 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 6, + "d": 7 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 2 + }, + "mne/io/pick.py": { + "a": 161, + "d": 18 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 66, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 32, + "d": 51 + }, + "mne/preprocessing/otp.py": { + "a": 3, + "d": 6 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 6, + "d": 12 + }, + "mne/realtime/mockclient.py": { + "a": 9, + "d": 6 + }, + "mne/stats/regression.py": { + "a": 5, + "d": 7 + }, + "mne/time_frequency/ar.py": { + "a": 3, + "d": 5 + }, + "mne/time_frequency/csd.py": { + "a": 7, + "d": 16 + }, + "mne/time_frequency/psd.py": { + "a": 4, + "d": 9 + }, + "mne/time_frequency/tfr.py": { + "a": 33, + "d": 40 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 0, + "d": 17 + }, + "mne/utils/docs.py": { + "a": 23, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 1, + "d": 17 + }, + "mne/viz/epochs.py": { + "a": 14, + "d": 18 + }, + "mne/viz/evoked.py": { + "a": 27, + "d": 28 + }, + "mne/viz/ica.py": { + "a": 20, + "d": 29 + }, + "mne/viz/raw.py": { + "a": 6, + "d": 5 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 17, + "d": 20 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 3, + "d": 6 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 5 + }, + "tutorials/plot_artifacts_correction_maxwell_filtering.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 1, + "d": 3 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 5, + "d": 10 + }, + "tutorials/plot_compute_covariance.py": { + "a": 5, + "d": 7 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_introduction.py": { + "a": 6, + "d": 6 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 3, + "d": 5 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 1, + "d": 3 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4512.json b/mne-python/source/doc/sphinxext/prs/4512.json new file mode 100644 index 0000000000000000000000000000000000000000..cef59874e54587d23eb9ed1b16bbf2b11d64232a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4512.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "39217c4fcace87cdb19fc09f3cbaeb94cf4a9a83", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/constants.py": { + "a": 142, + "d": 116 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 215, + "d": 219 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 43, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4515.json b/mne-python/source/doc/sphinxext/prs/4515.json new file mode 100644 index 0000000000000000000000000000000000000000..e248af14368b44590b300931aca5ead287368a24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4515.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c3350041127bebed517bfc729f3b7e0a5ccc944a", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 29, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4519.json b/mne-python/source/doc/sphinxext/prs/4519.json new file mode 100644 index 0000000000000000000000000000000000000000..cef567cc3e2498bd18e0a4c26020084e74f2f450 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4519.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bb92dbbcd9be1b03e846f8ca2d07d0099400e1bf", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/452.json b/mne-python/source/doc/sphinxext/prs/452.json new file mode 100644 index 0000000000000000000000000000000000000000..8baef62c04b0dc18e38023d50732468830c58143 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/452.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c0b8dfcc84ea97682e79a13d06526caaff03695f", + "authors": [ + { + "n": "Christoph Dinh", + "e": null + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4520.json b/mne-python/source/doc/sphinxext/prs/4520.json new file mode 100644 index 0000000000000000000000000000000000000000..f2971251d01b69a1ec53f1cde8e35acb06c4ca50 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4520.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "83e46c4b4b3dc3901065ce44532f7f4a99299ddf", + "authors": [ + { + "n": "Jaakko Leppakangas", + "e": "jaeilepp@student.jyu.fi" + } + ], + "changes": { + "mne/io/cnt/cnt.py": { + "a": 16, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4524.json b/mne-python/source/doc/sphinxext/prs/4524.json new file mode 100644 index 0000000000000000000000000000000000000000..585ae242314249d0b2b5f48c3f8447a985830925 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4524.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e613a6444b2aa8631d1d4e75baf37397a165ee99", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 12, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 31, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4525.json b/mne-python/source/doc/sphinxext/prs/4525.json new file mode 100644 index 0000000000000000000000000000000000000000..6767e1a437b1a421e5c25f8dbb6099fadc795c38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4525.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c691fbf269a38290fae6fd07c75ab57aa5213d45", + "authors": [ + { + "n": "Alejandro Weinstein", + "e": "alejandro.weinstein@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4527.json b/mne-python/source/doc/sphinxext/prs/4527.json new file mode 100644 index 0000000000000000000000000000000000000000..d00206a88d6382b88bc46f2191810bcdf70ea5b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4527.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ccfc5029da960cfa9003a441b31418bdcfd4045b", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_base.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4528.json b/mne-python/source/doc/sphinxext/prs/4528.json new file mode 100644 index 0000000000000000000000000000000000000000..fd4841acff0539bb0838310cc9a49926f69c76d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4528.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cd775ca372fcc911d92297dc3131bac38530e131", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 25, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/453.json b/mne-python/source/doc/sphinxext/prs/453.json new file mode 100644 index 0000000000000000000000000000000000000000..04c9b5c7c56d292182a2ed50fe53c35f9b268a91 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/453.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c4a0a60c939416e8bb10925faf992ba0f7719f69", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/proj.py": { + "a": 7, + "d": 5 + }, + "mne/tests/test_proj.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4531.json b/mne-python/source/doc/sphinxext/prs/4531.json new file mode 100644 index 0000000000000000000000000000000000000000..8ecd3220aa9fbc2716d79ca7361ca21845ea4fd8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4531.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "73c80d65dda142165f3bbc27a4d3893244df150a", + "authors": [ + { + "n": "jdue", + "e": "jdue@dtu.dk" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 24, + "d": 11 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4535.json b/mne-python/source/doc/sphinxext/prs/4535.json new file mode 100644 index 0000000000000000000000000000000000000000..2c863f31817f292de9d3eef7460bd06e77f8068b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4535.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "af920972b9c7a7917d2d214c564713e959443573", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4536.json b/mne-python/source/doc/sphinxext/prs/4536.json new file mode 100644 index 0000000000000000000000000000000000000000..7e3a80144a16367997dab7c6343f076542ae1432 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4536.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "4e41f9a198c9746c6b7993f3bf93546a43f5cfaf", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 11, + "d": 27 + }, + "mne/stats/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/stats/parametric.py": { + "a": 13, + "d": 0 + }, + "mne/stats/permutations.py": { + "a": 31, + "d": 0 + }, + "mne/stats/tests/test_permutations.py": { + "a": 12, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 45 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4537.json b/mne-python/source/doc/sphinxext/prs/4537.json new file mode 100644 index 0000000000000000000000000000000000000000..95d9a334b316a80c7393c961e8e9bae3788d6bed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4537.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0c0b8de28d6d127aea8829ac0578231203ce856e", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4539.json b/mne-python/source/doc/sphinxext/prs/4539.json new file mode 100644 index 0000000000000000000000000000000000000000..c372e4bf119df74271fcd20e7f02f978005d2733 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4539.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0ca1bc1b92d9ab86c438d141b78427184c77bbb2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/454.json b/mne-python/source/doc/sphinxext/prs/454.json new file mode 100644 index 0000000000000000000000000000000000000000..0b8afcc0eaab014e0506109d190e64118d0f52ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/454.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "37aeb75b61fd3f67257edfa2be0058a4bf9370ee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/constants.py": { + "a": 170, + "d": 7 + }, + "mne/fiff/matrix.py": { + "a": 17, + "d": 8 + }, + "mne/fiff/open.py": { + "a": 94, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 18, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4541.json b/mne-python/source/doc/sphinxext/prs/4541.json new file mode 100644 index 0000000000000000000000000000000000000000..701ff3fb9543ac4beda96bec0264c8e6ed32b479 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4541.json @@ -0,0 +1,287 @@ +{ + "merge_commit_sha": "876192598da7c557dbf46a6dda2ced4b7088d4bb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 27, + "d": 29 + }, + "Makefile": { + "a": 3, + "d": 3 + }, + "appveyor.yml": { + "a": 7, + "d": 4 + }, + "doc/advanced_setup.rst": { + "a": 1, + "d": 1 + }, + "doc/configure_git.rst": { + "a": 1, + "d": 1 + }, + "doc/contributing.rst": { + "a": 2, + "d": 2 + }, + "doc/faq.rst": { + "a": 0, + "d": 1 + }, + "doc/git_links.inc": { + "a": 0, + "d": 2 + }, + "doc/known_projects.inc": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 3, + "d": 3 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 3, + "d": 2 + }, + "mne/commands/tests/test_commands.py": { + "a": 9, + "d": 6 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 3, + "d": 2 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 4 + }, + "mne/decoding/receptive_field.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_base.py": { + "a": 8, + "d": 12 + }, + "mne/decoding/tests/test_csp.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/tests/test_ems.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 8, + "d": 8 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/time_gen.py": { + "a": 2, + "d": 8 + }, + "mne/fixes.py": { + "a": 33, + "d": 0 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 3, + "d": 2 + }, + "mne/forward/tests/test_forward.py": { + "a": 3, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 5, + "d": 4 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 4, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 3, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 3, + "d": 2 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 3, + "d": 2 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 3, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 6, + "d": 5 + }, + "mne/io/tests/test_apply_function.py": { + "a": 4, + "d": 2 + }, + "mne/io/tests/test_reference.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 6, + "d": 5 + }, + "mne/minimum_norm/tests/test_psf_ctf.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 10, + "d": 9 + }, + "mne/simulation/tests/test_raw.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_bem.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 6, + "d": 5 + }, + "mne/tests/test_cov.py": { + "a": 11, + "d": 11 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 4, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_line_endings.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_report.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_source_estimate.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_source_space.py": { + "a": 9, + "d": 7 + }, + "mne/tests/test_surface.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 17, + "d": 43 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 0 + }, + "mne/viz/tests/test_decoding.py": { + "a": 6, + "d": 6 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_misc.py": { + "a": 4, + "d": 3 + }, + "mne/viz/tests/test_topomap.py": { + "a": 3, + "d": 3 + }, + "setup.cfg": { + "a": 2, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4542.json b/mne-python/source/doc/sphinxext/prs/4542.json new file mode 100644 index 0000000000000000000000000000000000000000..1b35c1a164b58a1190b44b57128ed8591ded3207 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4542.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "33146156f2660f122ecc04fa0d5b3fd3c34b549e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 17, + "d": 24 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 12, + "d": 3 + }, + "mne/io/reference.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/report.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4543.json b/mne-python/source/doc/sphinxext/prs/4543.json new file mode 100644 index 0000000000000000000000000000000000000000..a92c8a7f42c8a9078210914ca7f9575106a4bc0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4543.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "cf9ff8bcbcb4fec21e8ebbef46305e60e6ead20d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/documentation.rst": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 25, + "d": 87 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 156, + "d": 29 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 180, + "d": 82 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_receptive_field.py": { + "a": 51, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4544.json b/mne-python/source/doc/sphinxext/prs/4544.json new file mode 100644 index 0000000000000000000000000000000000000000..40f14c27ede35e5190e0a911d4bfce5fc4bf18dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4544.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "276d9c5dd5428b7eceabd240862e01847850d93d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 70, + "d": 37 + }, + "mne/tests/test_source_estimate.py": { + "a": 49, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4546.json b/mne-python/source/doc/sphinxext/prs/4546.json new file mode 100644 index 0000000000000000000000000000000000000000..d6d82efde817219f65d4052599e49996bf016b0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4546.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ce040f091f6e9346dbae05a8ab06649f6292319a", + "authors": [ + { + "n": "Nicolas Barascud", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "examples/decoding/plot_receptive_field.py": { + "a": 120, + "d": 9 + }, + "mne/decoding/receptive_field.py": { + "a": 47, + "d": 6 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 59, + "d": 7 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4547.json b/mne-python/source/doc/sphinxext/prs/4547.json new file mode 100644 index 0000000000000000000000000000000000000000..bb071585e78117d78f34799344bb171908130381 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4547.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "eccaf028b2c594b862975ae9e1c5cc92f625927e", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/search_light.py": { + "a": 10, + "d": 1 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4548.json b/mne-python/source/doc/sphinxext/prs/4548.json new file mode 100644 index 0000000000000000000000000000000000000000..a0607de9892dff2112169641322b493515d19133 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4548.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d2b214f410e61bb31b49dc40ac4e392c3bdd2383", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 8, + "d": 8 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4549.json b/mne-python/source/doc/sphinxext/prs/4549.json new file mode 100644 index 0000000000000000000000000000000000000000..d2cbf29a416b7ad8a0240c5e68970e1991f96a9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4549.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cd24596e14383dc978d754a51f8fe9fabbd76b21", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_space.py": { + "a": 8, + "d": 4 + }, + "mne/tests/test_source_space.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4550.json b/mne-python/source/doc/sphinxext/prs/4550.json new file mode 100644 index 0000000000000000000000000000000000000000..c1dfcd8227e84b3d6d300499ec02747ac801d69e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4550.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "4a99b6fff771031763c774eab9f66d32f2702f21", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "appveyor.yml": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_receptive_field.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/receptive_field.py": { + "a": 34, + "d": 22 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 148, + "d": 79 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 7, + "d": 6 + }, + "setup.cfg": { + "a": 1, + "d": 1 + }, + "tutorials/plot_receptive_field.py": { + "a": 9, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4552.json b/mne-python/source/doc/sphinxext/prs/4552.json new file mode 100644 index 0000000000000000000000000000000000000000..6c48d595b00bb6afc96944d65cd27cd0b6b23847 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4552.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "305621c64ade2e19579add8661953deb6645f26c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 26, + "d": 16 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4559.json b/mne-python/source/doc/sphinxext/prs/4559.json new file mode 100644 index 0000000000000000000000000000000000000000..a5581cd770474ad90b8d83ebf742056ad3693be6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4559.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9ac40200cc72ac81efc2d59996bbdbf91bf4666c", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/baseline.py": { + "a": 18, + "d": 14 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 30, + "d": 17 + }, + "mne/time_frequency/tfr.py": { + "a": 66, + "d": 41 + }, + "mne/viz/topomap.py": { + "a": 46, + "d": 42 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4560.json b/mne-python/source/doc/sphinxext/prs/4560.json new file mode 100644 index 0000000000000000000000000000000000000000..513344a0b11cfd26facebd9b87f6ab9b07e344c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4560.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d11af66dae0261b6edc8f3e4d5a7ceb051b85061", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 14, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 31, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4561.json b/mne-python/source/doc/sphinxext/prs/4561.json new file mode 100644 index 0000000000000000000000000000000000000000..b54628680a91d0d4e7bf5f25c91774ca31e3d4c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4561.json @@ -0,0 +1,123 @@ +{ + "merge_commit_sha": "f9443967f85880b95d36720bbd25d678bdccb6ad", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 5, + "d": 5 + }, + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 2, + "d": 2 + }, + "examples/visualization/plot_topo_customized.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 4, + "d": 4 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 3, + "d": 3 + }, + "mne/connectivity/effective.py": { + "a": 6, + "d": 5 + }, + "mne/connectivity/spectral.py": { + "a": 23, + "d": 30 + }, + "mne/connectivity/tests/test_effective.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/time_frequency.py": { + "a": 19, + "d": 10 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 4, + "d": 7 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 15, + "d": 18 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 9, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 27, + "d": 21 + }, + "mne/time_frequency/multitaper.py": { + "a": 21, + "d": 18 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 23, + "d": 24 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 38, + "d": 32 + }, + "mne/utils.py": { + "a": 8, + "d": 0 + }, + "tutorials/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 4, + "d": 4 + }, + "tutorials/plot_stats_cluster_time_frequency.py": { + "a": 5, + "d": 5 + }, + "tutorials/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 10, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4562.json b/mne-python/source/doc/sphinxext/prs/4562.json new file mode 100644 index 0000000000000000000000000000000000000000..cf3afb6849b39b54cf1aa2abe90cec55aa173ab8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4562.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "300f8734796c1d10da94f45eb8de0e9ee45fa90e", + "authors": [ + { + "n": "Yousra Bekhti", + "e": "yousra.bekhti@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 9, + "d": 8 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 7, + "d": 10 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 35, + "d": 24 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 37, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 51, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 50, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4563.json b/mne-python/source/doc/sphinxext/prs/4563.json new file mode 100644 index 0000000000000000000000000000000000000000..8e7f4321111d19acea81548fe9609de213684e9e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4563.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4e0635e0e3e718d4aa723f0ffc28c22020caf51c", + "authors": [ + { + "n": "Cristóbal Moënne-Loccoz", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 21, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4565.json b/mne-python/source/doc/sphinxext/prs/4565.json new file mode 100644 index 0000000000000000000000000000000000000000..dd591c24d25eb3fd30e0555645409edd738707c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4565.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "21dfeea128e1ac4fc4dab8789694ffe0cfbeaf74", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/cuda.py": { + "a": 22, + "d": 9 + }, + "mne/epochs.py": { + "a": 1, + "d": 53 + }, + "mne/evoked.py": { + "a": 1, + "d": 33 + }, + "mne/filter.py": { + "a": 278, + "d": 24 + }, + "mne/io/base.py": { + "a": 35, + "d": 33 + }, + "mne/tests/test_epochs.py": { + "a": 40, + "d": 14 + }, + "mne/tests/test_evoked.py": { + "a": 12, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 19, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4566.json b/mne-python/source/doc/sphinxext/prs/4566.json new file mode 100644 index 0000000000000000000000000000000000000000..048b14365107ae7f9d3f55605fcdc14d6b0e3094 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4566.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f5b8267f3750c450d411711c1c1a02ccc8b791ed", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 121, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4567.json b/mne-python/source/doc/sphinxext/prs/4567.json new file mode 100644 index 0000000000000000000000000000000000000000..5c2c4cb18141f77e427bde4d37eabad577a62a4c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4567.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a36dec28cea9b123102b082af95c3f69c180f878", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 35, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4569.json b/mne-python/source/doc/sphinxext/prs/4569.json new file mode 100644 index 0000000000000000000000000000000000000000..e8f7c2d6d72b63039e50f19911e7f0e9fb25a44d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4569.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "be9ae352cb40edbe16a5826a3a79d66fd5a099a6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 10, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 20, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/457.json b/mne-python/source/doc/sphinxext/prs/457.json new file mode 100644 index 0000000000000000000000000000000000000000..09d095b68dfeb38dbf8a20fa699ae440c4f3fd9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/457.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2f9d389171799dd0a84232166f17d69ab393f990", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 20, + "d": 3 + }, + "mne/tests/test_cov.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4570.json b/mne-python/source/doc/sphinxext/prs/4570.json new file mode 100644 index 0000000000000000000000000000000000000000..fa9c1c4d240d1d2bfcc57b8113fed058f73df12e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4570.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "3d503127e6ca99c3b5bb189dfb0fbaa1c889df4c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 7, + "d": 8 + }, + "doc/manual/channel_interpolation.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/cookbook.rst": { + "a": 20, + "d": 20 + }, + "doc/manual/decoding.rst": { + "a": 3, + "d": 3 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/sample_dataset.rst": { + "a": 1, + "d": 1 + }, + "doc/tutorials/report.rst": { + "a": 9, + "d": 9 + }, + "environment.yml": { + "a": 33, + "d": 0 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4571.json b/mne-python/source/doc/sphinxext/prs/4571.json new file mode 100644 index 0000000000000000000000000000000000000000..06682457483b1b9e27e524d55b1f69a6ad70e0ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4571.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d75f0821c39fff49e418ebb4df189f2a88a204c2", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/plot_info.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4576.json b/mne-python/source/doc/sphinxext/prs/4576.json new file mode 100644 index 0000000000000000000000000000000000000000..769003edece13bad05d934e240d2ee6fc51ba921 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4576.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2dcdc3ae1c61c6e4843ddf4cafdd3dcf51ed8aec", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/458.json b/mne-python/source/doc/sphinxext/prs/458.json new file mode 100644 index 0000000000000000000000000000000000000000..da6be6c53f226c47ddb787a44d60fecbccb17467 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/458.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1f42cd617522a04432172f93cca364aa308f1542", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4581.json b/mne-python/source/doc/sphinxext/prs/4581.json new file mode 100644 index 0000000000000000000000000000000000000000..64a1054480cc0960b925cec6e620269a9255bff8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4581.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9ef2b0dde60701f1597619edb5ac955f84320224", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4582.json b/mne-python/source/doc/sphinxext/prs/4582.json new file mode 100644 index 0000000000000000000000000000000000000000..d8da807af49117f76942ab349cbd12acdd3c9a52 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4582.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d2ac5a40c9f6660a2391fe4de55f9a74df5b6fc8", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 2, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 81, + "d": 38 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 6, + "d": 2 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4583.json b/mne-python/source/doc/sphinxext/prs/4583.json new file mode 100644 index 0000000000000000000000000000000000000000..0d9a7404b9e1c71cc784bfd01e1ab59c91dc2505 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4583.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c79b74e9c67dbe429e29007746aec2691189a794", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/egimff.py": { + "a": 245, + "d": 62 + }, + "mne/io/egi/events.py": { + "a": 4, + "d": 1 + }, + "mne/io/egi/general.py": { + "a": 16, + "d": 9 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 43, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4585.json b/mne-python/source/doc/sphinxext/prs/4585.json new file mode 100644 index 0000000000000000000000000000000000000000..dd47e7b4fb3830a9a9dbefafec32dd145028ccfe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4585.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "c6a9c3e4cc4cf3e671e05bd01fae890d6aa2b523", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 6, + "d": 2 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 6, + "d": 3 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 2, + "d": 2 + }, + "examples/datasets/plot_megsim_data_single_trial.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 3, + "d": 11 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 5, + "d": 3 + }, + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 1, + "d": 2 + }, + "examples/decoding/plot_receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 5, + "d": 9 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 5, + "d": 9 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 6, + "d": 9 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 4, + "d": 9 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 5, + "d": 9 + }, + "mne/datasets/utils.py": { + "a": 182, + "d": 133 + }, + "mne/utils.py": { + "a": 26, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4587.json b/mne-python/source/doc/sphinxext/prs/4587.json new file mode 100644 index 0000000000000000000000000000000000000000..0ba78de0f517f6501022ed52efc4e09699d9ca24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4587.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "69d1945404d8954d08ac526d92836ae57c9dab37", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 0, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4588.json b/mne-python/source/doc/sphinxext/prs/4588.json new file mode 100644 index 0000000000000000000000000000000000000000..a9f396b0d191f3489ef226a2c8683698b3516cd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4588.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "ab34726258cc124846134f350c0a907d8dd11318", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 7, + "d": 7 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/459.json b/mne-python/source/doc/sphinxext/prs/459.json new file mode 100644 index 0000000000000000000000000000000000000000..58a68a5c076229b227724519134a4b1db0c9ec75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/459.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "823e6d6d509d16be7a84efbeb6fe0a51227be5bf", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 13, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4590.json b/mne-python/source/doc/sphinxext/prs/4590.json new file mode 100644 index 0000000000000000000000000000000000000000..43b5182df9fa19413edbafd52e2d765cc01f7e0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4590.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e9bbae9bbbb37b37cc9b661a1e76c80af28b7f00", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/data/montages/10-5_EGI129.csd": { + "a": 0, + "d": 467 + }, + "mne/channels/montage.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4591.json b/mne-python/source/doc/sphinxext/prs/4591.json new file mode 100644 index 0000000000000000000000000000000000000000..0d4de09f346d617070f17d71af212dd3f74db742 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4591.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "791528101de7553dc3cdbefd82efd2d528842a3f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/plot_brainstorm_phantom_ctf.py": { + "a": 11, + "d": 2 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 45, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4592.json b/mne-python/source/doc/sphinxext/prs/4592.json new file mode 100644 index 0000000000000000000000000000000000000000..9934c612dcdf86ef20ed0652f2cb4706bfdec207 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4592.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "42794b4472d0fbf8712bab2fb6a8705092291fdd", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/montage.py": { + "a": 25, + "d": 1 + }, + "mne/viz/tests/test_montage.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4593.json b/mne-python/source/doc/sphinxext/prs/4593.json new file mode 100644 index 0000000000000000000000000000000000000000..5793b36c7308e8f97aa0cd59ecbb22adfc6136cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4593.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5fafe7202a61ef0cf0c4b8105ee4d845b0d15ae9", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_file_traits.py": { + "a": 59, + "d": 63 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4595.json b/mne-python/source/doc/sphinxext/prs/4595.json new file mode 100644 index 0000000000000000000000000000000000000000..3d9e2c30b52654957f752e1ecc6cbb92bb504b36 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4595.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "d12520c75882016f7cced853048cc85e78055402", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_topo_compare_conditions.py": { + "a": 3, + "d": 5 + }, + "mne/decoding/csp.py": { + "a": 31, + "d": 34 + }, + "mne/evoked.py": { + "a": 15, + "d": 18 + }, + "mne/io/base.py": { + "a": 9, + "d": 5 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 8, + "d": 2 + }, + "mne/utils.py": { + "a": 8, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_decoding.py": { + "a": 41, + "d": 32 + }, + "mne/viz/tests/test_epochs.py": { + "a": 14, + "d": 26 + }, + "mne/viz/tests/test_montage.py": { + "a": 10, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 12, + "d": 9 + }, + "mne/viz/tests/test_topo.py": { + "a": 7, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_utils.py": { + "a": 26, + "d": 19 + }, + "mne/viz/topo.py": { + "a": 9, + "d": 8 + }, + "mne/viz/topomap.py": { + "a": 28, + "d": 23 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 5 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4596.json b/mne-python/source/doc/sphinxext/prs/4596.json new file mode 100644 index 0000000000000000000000000000000000000000..4f1d58ba01e328a131b284feb6b6bc49948c8801 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4596.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1742decca63dd6d1bb6517a7b3ce465aebf1943f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4597.json b/mne-python/source/doc/sphinxext/prs/4597.json new file mode 100644 index 0000000000000000000000000000000000000000..28ee66fe09dd955e1640a5b987b8fb5cb80a561e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4597.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4314b7b1a5cc8f5f17101b4b79da53a54640c173", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 3, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4598.json b/mne-python/source/doc/sphinxext/prs/4598.json new file mode 100644 index 0000000000000000000000000000000000000000..b0c7cc3aca820d45692b80d7bfd45ffe452efb59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4598.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7f2066fe4d1ed0c59c5ae0105485479352163ec4", + "authors": [ + { + "n": "Jon Houck", + "e": null + } + ], + "changes": { + "mne/commands/mne_surf2bem.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/46.json b/mne-python/source/doc/sphinxext/prs/46.json new file mode 100644 index 0000000000000000000000000000000000000000..e54f24c5dd391268f3485d7ae5a6d0265e8fe778 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/46.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8ee29163c81d0509713037e3292755ce523857b9", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 13, + "d": 1 + }, + "bin/mne_compute_proj_eog.py": { + "a": 13, + "d": 1 + }, + "mne/artifacts/ecg.py": { + "a": 28, + "d": 7 + }, + "mne/artifacts/eog.py": { + "a": 7, + "d": 3 + }, + "mne/preprocessing/ssp.py": { + "a": 40, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4600.json b/mne-python/source/doc/sphinxext/prs/4600.json new file mode 100644 index 0000000000000000000000000000000000000000..c2eae41238f14ce8180dcb481d9858418c82e612 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4600.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "12f35943facddea33d32e99308fd4f148ecede05", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 8, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 5, + "d": 0 + }, + "mne/io/array/tests/test_array.py": { + "a": 13, + "d": 0 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 1 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 9, + "d": 5 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 11, + "d": 10 + }, + "mne/io/meas_info.py": { + "a": 23, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 3, + "d": 2 + }, + "mne/io/write.py": { + "a": 2, + "d": 7 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4601.json b/mne-python/source/doc/sphinxext/prs/4601.json new file mode 100644 index 0000000000000000000000000000000000000000..5805700e8de1da73ebd323bb665fdf57a4dd5e64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4601.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ce2486cda91f359cdcb9a7fc3410e2a36db7d428", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 7, + "d": 5 + }, + "mne/cov.py": { + "a": 52, + "d": 42 + }, + "mne/dipole.py": { + "a": 3, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 3, + "d": 22 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4602.json b/mne-python/source/doc/sphinxext/prs/4602.json new file mode 100644 index 0000000000000000000000000000000000000000..ce2666a87d23e20c15553aebb10faea5f2c88fbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4602.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a24fc0bc9a749c061d5c15684e44c559c9ae64ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_receptive_field.py": { + "a": 3, + "d": 1 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_import_nesting.py": { + "a": 3, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4603.json b/mne-python/source/doc/sphinxext/prs/4603.json new file mode 100644 index 0000000000000000000000000000000000000000..eb527a1f2d6ed873d044e78d86125bb0c0adcd3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4603.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5971f0ef4a90c8d369197e28fc3326e35ba5e973", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 23, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_file_traits.py": { + "a": 35, + "d": 26 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 6 + }, + "mne/viz/_3d.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4608.json b/mne-python/source/doc/sphinxext/prs/4608.json new file mode 100644 index 0000000000000000000000000000000000000000..1d9e3d64f1bfdb0578ecfffc9d0e13ef0ba90f11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4608.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "76afe82e742a97719cba58b8c4cba76068f29996", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 4 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 3, + "d": 3 + }, + "examples/io/plot_elekta_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_virtual_evoked.py": { + "a": 2, + "d": 2 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_sensor_regression.py": { + "a": 8, + "d": 7 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/csp.py": { + "a": 15, + "d": 13 + }, + "mne/decoding/transformer.py": { + "a": 12, + "d": 2 + }, + "mne/evoked.py": { + "a": 6, + "d": 5 + }, + "mne/filter.py": { + "a": 5, + "d": 5 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/utils.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 8, + "d": 13 + }, + "tutorials/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4609.json b/mne-python/source/doc/sphinxext/prs/4609.json new file mode 100644 index 0000000000000000000000000000000000000000..7a874a3317c59342a7305bc40f8acc3568b666f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4609.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "53669a18d1f7ae19b01ae4cedb1b5b27289b9b08", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 42, + "d": 46 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_bem.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4610.json b/mne-python/source/doc/sphinxext/prs/4610.json new file mode 100644 index 0000000000000000000000000000000000000000..36f2f1d59d8f6adb4cdff9a2ab2bd2e5ad2fddf0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4610.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "52c1e6f5472f823e49e5427e29548dfa594e9f44", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 1, + "d": 2 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 5, + "d": 5 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 2, + "d": 2 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4611.json b/mne-python/source/doc/sphinxext/prs/4611.json new file mode 100644 index 0000000000000000000000000000000000000000..5f3a363137e5404fe3319e7b4a096d7cf09df544 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4611.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "36f88e54cdcf27c785857025af602376463ad3ed", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 35, + "d": 40 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4616.json b/mne-python/source/doc/sphinxext/prs/4616.json new file mode 100644 index 0000000000000000000000000000000000000000..7d5a09f48d8b27d435edc072f7fad07370d13bc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4616.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f39093ef0d8099c88458abbdc25a8b8dfca3eea1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4617.json b/mne-python/source/doc/sphinxext/prs/4617.json new file mode 100644 index 0000000000000000000000000000000000000000..130840916879af852e2e6ed85d8868c03a7ff112 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4617.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "06962e287e7ce4f2f40b2defbbb47c9c7e986b96", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 17, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 54, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4618.json b/mne-python/source/doc/sphinxext/prs/4618.json new file mode 100644 index 0000000000000000000000000000000000000000..0dc10080c30252b2dcc68a46643dae5bd7bae66e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4618.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "72a9b26153ed6e71218dd6f13b57412bb5def205", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 0, + "d": 1 + }, + "examples/forward/plot_forward_sensitivity_maps.py": { + "a": 1, + "d": 1 + }, + "examples/forward/plot_source_space_morphing.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 0, + "d": 1 + }, + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 2, + "d": 3 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 28, + "d": 18 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 4, + "d": 4 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 3, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/io/pick.py": { + "a": 12, + "d": 11 + }, + "mne/minimum_norm/inverse.py": { + "a": 89, + "d": 87 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 119, + "d": 78 + }, + "mne/simulation/evoked.py": { + "a": 11, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4619.json b/mne-python/source/doc/sphinxext/prs/4619.json new file mode 100644 index 0000000000000000000000000000000000000000..bf0173a60aa333b283d0740aa66d469e32167b86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4619.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d6b390d6764778800988b2a44a62c25299a96ab8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 2 + }, + "mne/io/proj.py": { + "a": 78, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 26, + "d": 15 + }, + "mne/viz/topomap.py": { + "a": 83, + "d": 53 + }, + "tutorials/plot_artifacts_correction_ssp.py": { + "a": 10, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/462.json b/mne-python/source/doc/sphinxext/prs/462.json new file mode 100644 index 0000000000000000000000000000000000000000..a555c6e9bd320f0e8cb9fed836b654d0d30abc8f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/462.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "baabed706357525bd3b29f4cd1183fa3fed624b7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 79, + "d": 32 + }, + "mne/surface.py": { + "a": 22, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4620.json b/mne-python/source/doc/sphinxext/prs/4620.json new file mode 100644 index 0000000000000000000000000000000000000000..5044540395845ae129d1e88bb12ee03c1a9be87b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4620.json @@ -0,0 +1,175 @@ +{ + "merge_commit_sha": "bdbc4f9207822901f1af229394ba4bc05b347aa4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "examples/forward/plot_forward_sensitivity_maps.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 7, + "d": 1 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_rap_music.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 4, + "d": 1 + }, + "examples/visualization/plot_ssp_projs_sensitivity_map.py": { + "a": 3, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 8, + "d": 5 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 7, + "d": 5 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 236, + "d": 83 + }, + "mne/forward/tests/test_forward.py": { + "a": 82, + "d": 15 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 3, + "d": 3 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 7, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 15, + "d": 4 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 5, + "d": 3 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 5, + "d": 4 + }, + "mne/minimum_norm/inverse.py": { + "a": 10, + "d": 6 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 13, + "d": 5 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 13, + "d": 8 + }, + "mne/minimum_norm/tests/test_psf_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/raw.py": { + "a": 6, + "d": 3 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 4, + "d": 4 + }, + "mne/simulation/tests/test_raw.py": { + "a": 40, + "d": 25 + }, + "mne/simulation/tests/test_source.py": { + "a": 8, + "d": 6 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_forward.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_point_spread.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4622.json b/mne-python/source/doc/sphinxext/prs/4622.json new file mode 100644 index 0000000000000000000000000000000000000000..189cd2129279ed2029642f32d83122c8e62f4f54 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4622.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bbf2afaa3798c979002693be7de6e3e43ca0bdaa", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 9, + "d": 5 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 15, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4624.json b/mne-python/source/doc/sphinxext/prs/4624.json new file mode 100644 index 0000000000000000000000000000000000000000..e9522913f1e28e865cd077f0089bf3aa322bb961 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4624.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "25d565466a31e9d834b0bb6b8962022adcc2c983", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_parcellation.py": { + "a": 7, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 3, + "d": 6 + }, + "mne/datasets/utils.py": { + "a": 119, + "d": 17 + }, + "mne/label.py": { + "a": 6, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4625.json b/mne-python/source/doc/sphinxext/prs/4625.json new file mode 100644 index 0000000000000000000000000000000000000000..dd9ca0a4c33a0b1e5754599bb452e9c45adac47e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4625.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "a6fe01b56fa073d120c72454830bc858f8ea5ad0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 3, + "d": 3 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 3, + "d": 8 + }, + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 5, + "d": 5 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 0, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 4, + "d": 5 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 2, + "d": 4 + }, + "mne/label.py": { + "a": 7, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4626.json b/mne-python/source/doc/sphinxext/prs/4626.json new file mode 100644 index 0000000000000000000000000000000000000000..0066b846550246ba8de540354d121fb8e374af00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4626.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "57fe40c98a97db7d1be9143b859ff86d89e1a7d8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "appveyor.yml": { + "a": 3, + "d": 2 + }, + "environment.yml": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4628.json b/mne-python/source/doc/sphinxext/prs/4628.json new file mode 100644 index 0000000000000000000000000000000000000000..d33c899324a674c34239012234fa442a0c7a2384 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4628.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7ae3c15886f17f70f988e5c5a49454a7162e0e5b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 87, + "d": 10 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 62, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4629.json b/mne-python/source/doc/sphinxext/prs/4629.json new file mode 100644 index 0000000000000000000000000000000000000000..55901a446f93773171532605862043ef20146fd3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4629.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7e1d900658c5952758278edd219a5eb12b08a4a5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 5, + "d": 5 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_receptive_field.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4630.json b/mne-python/source/doc/sphinxext/prs/4630.json new file mode 100644 index 0000000000000000000000000000000000000000..7151269fe8919fae0506473d5567de693b1655c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4630.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "93958f591b3ffc2faac31b8d20b2bc2685810941", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_rap_music.py": { + "a": 8, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 16, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 0, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4632.json b/mne-python/source/doc/sphinxext/prs/4632.json new file mode 100644 index 0000000000000000000000000000000000000000..a66d546bad5bf0d83763703501ae46bb49773da1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4632.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6e980003c7f9295d13a4aaf7c05794bd68e73fb8", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 109, + "d": 107 + }, + "mne/tests/test_cov.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4633.json b/mne-python/source/doc/sphinxext/prs/4633.json new file mode 100644 index 0000000000000000000000000000000000000000..9bd988d3d9b2fb6efec00cd308e5d265cb20925e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4633.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "35eb5be96e7504c4192d608ceb4c27eb96c5ee48", + "authors": [ + { + "n": "Yousra Bekhti", + "e": "yousra.bekhti@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 15, + "d": 7 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 17, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 20, + "d": 0 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4635.json b/mne-python/source/doc/sphinxext/prs/4635.json new file mode 100644 index 0000000000000000000000000000000000000000..460de2bec9e97640aa677665e7d8e0824c89a7e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4635.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "933eccfe732b5ef3b73f40bf357d2c6cd44745b2", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_kit2fiff_gui.py": { + "a": 16, + "d": 3 + }, + "mne/io/kit/constants.py": { + "a": 7, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 52, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4636.json b/mne-python/source/doc/sphinxext/prs/4636.json new file mode 100644 index 0000000000000000000000000000000000000000..b8dc42224234c57b3c5151b81841402695a61579 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4636.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e9a5c6df6751f99c1fbc83fde6b780ba4305075b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 11, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4638.json b/mne-python/source/doc/sphinxext/prs/4638.json new file mode 100644 index 0000000000000000000000000000000000000000..1bca35fc6fb6782db33b04986e0e74ceede5c117 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4638.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8bf65d5032b8bf11c4efeba6ce6d954d88a0326d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".gitignore": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/464.json b/mne-python/source/doc/sphinxext/prs/464.json new file mode 100644 index 0000000000000000000000000000000000000000..03f13159c35b889ae876eeb18ba2a373b4e7c336 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/464.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d34d9fbdbd613f68813c949de4cdff323b79072c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/event.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4640.json b/mne-python/source/doc/sphinxext/prs/4640.json new file mode 100644 index 0000000000000000000000000000000000000000..a21663193cd2cea881f563f05e1980aaa02ffddc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4640.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0e3579fd08d2f45c2291ff7c50a111fdcb4d512d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 45, + "d": 27 + }, + "mne/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4641.json b/mne-python/source/doc/sphinxext/prs/4641.json new file mode 100644 index 0000000000000000000000000000000000000000..876544d011b4d52594e9667b88a8106b64d2fdd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4641.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "2a98e818567ddf0caf7b3e32d1c946f2c61a2727", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 14, + "d": 20 + }, + "doc/_static/copybutton.js": { + "a": 66, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 2, + "d": 0 + }, + "doc/advanced_setup.rst": { + "a": 50, + "d": 7 + }, + "doc/conf.py": { + "a": 0, + "d": 8 + }, + "doc/configure_git.rst": { + "a": 24, + "d": 24 + }, + "doc/contributing.rst": { + "a": 5, + "d": 5 + }, + "doc/faq.rst": { + "a": 2, + "d": 2 + }, + "doc/install_mne_c.rst": { + "a": 8, + "d": 8 + }, + "doc/install_mne_python.rst": { + "a": 49, + "d": 95 + }, + "doc/martinos.rst": { + "a": 3, + "d": 3 + }, + "doc/tutorials/report.rst": { + "a": 6, + "d": 6 + }, + "environment.yml": { + "a": 12, + "d": 4 + }, + "environment2.yml": { + "a": 38, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 0 + }, + "mne/gui/_viewer.py": { + "a": 2, + "d": 0 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 12, + "d": 0 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 10, + "d": 5 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 9, + "d": 0 + }, + "mne/tests/test_line_endings.py": { + "a": 3, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4644.json b/mne-python/source/doc/sphinxext/prs/4644.json new file mode 100644 index 0000000000000000000000000000000000000000..50c881ccd09ba7c05e8ad075d251a94414772745 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4644.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d5a8aa2ac687d0c423a8e222dab750ba51147ec9", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 12, + "d": 8 + }, + "mne/io/reference.py": { + "a": 11, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4645.json b/mne-python/source/doc/sphinxext/prs/4645.json new file mode 100644 index 0000000000000000000000000000000000000000..58cb8fcea985a8dd0e8143b842dda6ee43e01fb5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4645.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9b6b0b27620111d8cc59c17a6af0486c41d9d606", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 16, + "d": 14 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 10, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4646.json b/mne-python/source/doc/sphinxext/prs/4646.json new file mode 100644 index 0000000000000000000000000000000000000000..e19e31ee693a48f2d8698fe6d80a64303671fcca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4646.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "40dfc1163fbccf7da42e342fd717e5bb59575b70", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_marker_gui.py": { + "a": 39, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4652.json b/mne-python/source/doc/sphinxext/prs/4652.json new file mode 100644 index 0000000000000000000000000000000000000000..3526d035da3c188a359e3ed028280d0ccca4a4bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4652.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b5a2a96cdde880d894d0d10560b2a007b6ea81aa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ssp.py": { + "a": 38, + "d": 33 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4654.json b/mne-python/source/doc/sphinxext/prs/4654.json new file mode 100644 index 0000000000000000000000000000000000000000..39b3c07e0a25bc58755233f657cbc89c32e2b0c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4654.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "efa7b4cae0a84496ce2c6f9da9714fc73bd41ea2", + "authors": [ + { + "n": "Alejandro Weinstein", + "e": "alejandro.weinstein@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "mne/io/base.py": { + "a": 6, + "d": 6 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 70, + "d": 22 + }, + "mne/viz/tests/test_raw.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4656.json b/mne-python/source/doc/sphinxext/prs/4656.json new file mode 100644 index 0000000000000000000000000000000000000000..7ab1b822c7389b8f8462ab1d5972400e34a00de3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4656.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "64d5d222d008b84b0f1d4d341d1cd074e389ff21", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 11, + "d": 13 + }, + "mne/preprocessing/maxwell.py": { + "a": 6, + "d": 5 + }, + "mne/source_space.py": { + "a": 5, + "d": 4 + }, + "mne/utils.py": { + "a": 10, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4657.json b/mne-python/source/doc/sphinxext/prs/4657.json new file mode 100644 index 0000000000000000000000000000000000000000..7b4f2bc167441171e0d544644bd3e3104dc3fb86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4657.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "47368ab51847c4551e9df789f0de2fc5df3e17cc", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4661.json b/mne-python/source/doc/sphinxext/prs/4661.json new file mode 100644 index 0000000000000000000000000000000000000000..8208b43405f78e690306f07aa97031de19e3a055 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4661.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e189992d84d3e31f403afa4fa7773711ecec7dce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4662.json b/mne-python/source/doc/sphinxext/prs/4662.json new file mode 100644 index 0000000000000000000000000000000000000000..b1e590f87f143f96f17c27909dabb485a06486bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4662.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5fac33d8950acbdabfc97ffc3dde16cd49991905", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4664.json b/mne-python/source/doc/sphinxext/prs/4664.json new file mode 100644 index 0000000000000000000000000000000000000000..5f8f681c07e9ee7953e999da751fcb949df579ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4664.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ddc8b342c8ba2462f304a05dee954d57225863e6", + "authors": [ + { + "n": "Alexander Rudiuk", + "e": null + } + ], + "changes": { + "examples/decoding/decoding_rsa.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4665.json b/mne-python/source/doc/sphinxext/prs/4665.json new file mode 100644 index 0000000000000000000000000000000000000000..e4b817d37d71cd6152c0277c1f6033abeac0b5be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4665.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5dfd1fc65e1e8105ca280a8a422413f297840f61", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 5, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4666.json b/mne-python/source/doc/sphinxext/prs/4666.json new file mode 100644 index 0000000000000000000000000000000000000000..7ea5244c17cd7d6d27a5c68730ae7586d16b04d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4666.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ec9e82714a93529c8e1fdc98acd1614c89463b98", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 1, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 9, + "d": 9 + }, + "mne/stats/tests/test_permutations.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4668.json b/mne-python/source/doc/sphinxext/prs/4668.json new file mode 100644 index 0000000000000000000000000000000000000000..3661f92fc737a35e5188dae2a107c56a96e2876c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4668.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d09c02fda48bce2a8bffe432d8dad191f8622ad2", + "authors": [ + { + "n": "Yousra Bekhti", + "e": "yousra.bekhti@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4669.json b/mne-python/source/doc/sphinxext/prs/4669.json new file mode 100644 index 0000000000000000000000000000000000000000..6f748f2f3abdd8604ea8e3c49611ff9d82abe488 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4669.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "cb9f94891ed4252c9e7d88b1d6d77f06297cb375", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/cov.py": { + "a": 9, + "d": 5 + }, + "mne/evoked.py": { + "a": 10, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 3 + }, + "mne/io/proc_history.py": { + "a": 42, + "d": 2 + }, + "mne/io/tests/test_proc_history.py": { + "a": 5, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 90, + "d": 25 + }, + "mne/viz/tests/test_evoked.py": { + "a": 15, + "d": 3 + }, + "tutorials/plot_compute_covariance.py": { + "a": 56, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/467.json b/mne-python/source/doc/sphinxext/prs/467.json new file mode 100644 index 0000000000000000000000000000000000000000..d8581088c519859e55da25a2c5c3a9a30828becd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/467.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c4456e0113b4fa5485e9272e73c68cb15589872a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/bti/raw.py": { + "a": 13, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4672.json b/mne-python/source/doc/sphinxext/prs/4672.json new file mode 100644 index 0000000000000000000000000000000000000000..84697154e51e52d80e7ff6acb278322e2b5960a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4672.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ebfaf79e6476741b30d4c636a5c8c93ce075ae33", + "authors": [ + { + "n": "Alejandro Weinstein", + "e": "alejandro.weinstein@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4677.json b/mne-python/source/doc/sphinxext/prs/4677.json new file mode 100644 index 0000000000000000000000000000000000000000..b24e4b259c6216e92ec07cccadb56977ebd9da7d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4677.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "585ee85cd9148d18863cd11c0c06578f3ec6c1b9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 0, + "d": 3 + }, + "environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4679.json b/mne-python/source/doc/sphinxext/prs/4679.json new file mode 100644 index 0000000000000000000000000000000000000000..7bd89823b72bb0210b3ff3161d33e1298bdf3b1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4679.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "8dc6afc53f3c0ee484859d7648af8f8bc6449b2c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/realtime/rt_feedback_server.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 1 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_base.py": { + "a": 1, + "d": 0 + }, + "mne/forward/tests/test_forward.py": { + "a": 23, + "d": 7 + }, + "mne/gui/_file_traits.py": { + "a": 2, + "d": 1 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 5, + "d": 2 + }, + "mne/io/base.py": { + "a": 2, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 4, + "d": 2 + }, + "mne/stats/tests/test_regression.py": { + "a": 7, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 6, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 8, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 8, + "d": 5 + }, + "mne/viz/tests/test_decoding.py": { + "a": 5, + "d": 5 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 4, + "d": 1 + }, + "setup.cfg": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4681.json b/mne-python/source/doc/sphinxext/prs/4681.json new file mode 100644 index 0000000000000000000000000000000000000000..51ca1f20770b1cd79e3db669bb63db95ff14f9d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4681.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "14595ede292ac1db1cfcc0b85ef7a9c303a12e72", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/receptive_field.py": { + "a": 4, + "d": 2 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 8, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4683.json b/mne-python/source/doc/sphinxext/prs/4683.json new file mode 100644 index 0000000000000000000000000000000000000000..b9b4db8300de98cfb5da4653253c906f1c143b14 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4683.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7c5e6c8061c66ed31924195efdfee9696689d7a6", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4684.json b/mne-python/source/doc/sphinxext/prs/4684.json new file mode 100644 index 0000000000000000000000000000000000000000..d4cd046f37d3c6e2ba877c928e4b422fdd19d288 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4684.json @@ -0,0 +1,175 @@ +{ + "merge_commit_sha": "9ac6547284bbd73b4c18d7d7031042585388005c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/gen_commands.py": { + "a": 7, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 24, + "d": 99 + }, + "mne/beamformer/_rap_music.py": { + "a": 2, + "d": 9 + }, + "mne/connectivity/effective.py": { + "a": 2, + "d": 3 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 3 + }, + "mne/decoding/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 6, + "d": 15 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 0, + "d": 491 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 3, + "d": 5 + }, + "mne/decoding/time_frequency.py": { + "a": 2, + "d": 11 + }, + "mne/decoding/time_gen.py": { + "a": 0, + "d": 1567 + }, + "mne/decoding/transformer.py": { + "a": 10, + "d": 25 + }, + "mne/event.py": { + "a": 7, + "d": 18 + }, + "mne/evoked.py": { + "a": 11, + "d": 16 + }, + "mne/filter.py": { + "a": 22, + "d": 38 + }, + "mne/forward/forward.py": { + "a": 9, + "d": 41 + }, + "mne/forward/tests/test_forward.py": { + "a": 0, + "d": 23 + }, + "mne/io/base.py": { + "a": 12, + "d": 27 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 7 + }, + "mne/io/reference.py": { + "a": 7, + "d": 28 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 8 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 3, + "d": 4 + }, + "mne/simulation/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 3, + "d": 76 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 8 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 13 + }, + "mne/time_frequency/csd.py": { + "a": 2, + "d": 10 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 8, + "d": 14 + }, + "mne/utils.py": { + "a": 0, + "d": 16 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 448 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/viz/decoding.py": { + "a": 0, + "d": 238 + }, + "mne/viz/evoked.py": { + "a": 20, + "d": 59 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 11 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 8 + }, + "mne/viz/tests/test_decoding.py": { + "a": 0, + "d": 135 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 12 + }, + "tutorials/plot_dipole_orientations.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4685.json b/mne-python/source/doc/sphinxext/prs/4685.json new file mode 100644 index 0000000000000000000000000000000000000000..c96cc0513f9acbd3af56d5ebe731856c64001527 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4685.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c458b903d9fbb2d4d02c5c5bc510ecb751eebd67", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 200, + "d": 0 + }, + ".travis.yml": { + "a": 1, + "d": 1 + }, + "circle.yml": { + "a": 0, + "d": 204 + }, + "doc/manual/datasets_index.rst": { + "a": 1, + "d": 1 + }, + "examples/datasets/spm_faces_dataset.py": { + "a": 0, + "d": 0 + }, + "examples/io/plot_objects_from_arrays.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4687.json b/mne-python/source/doc/sphinxext/prs/4687.json new file mode 100644 index 0000000000000000000000000000000000000000..6b22199ce8246f644c3cd8a6bad49a7d53dfe8cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4687.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b33a264cca70c0e78847dfdcb42c96545e7313be", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 1, + "d": 1 + }, + "doc/_templates/navbar.html": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4688.json b/mne-python/source/doc/sphinxext/prs/4688.json new file mode 100644 index 0000000000000000000000000000000000000000..a8b545e6dccaf0b93ccf6d333a87a6a72ad45fe5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4688.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d0b959e867322c65edc52cfc35b9a00aad54cacf", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/469.json b/mne-python/source/doc/sphinxext/prs/469.json new file mode 100644 index 0000000000000000000000000000000000000000..32562145886e287fad787b37a878c4a5c09f1ec5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/469.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f0695c93332505a3999b582fe2368d6da170c2a8", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/bti/raw.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4692.json b/mne-python/source/doc/sphinxext/prs/4692.json new file mode 100644 index 0000000000000000000000000000000000000000..5484f090134f2650fa328294119e674e865496ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4692.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c772ede93a7eb54608ab6f66080c6bb8622ff18b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 5, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4696.json b/mne-python/source/doc/sphinxext/prs/4696.json new file mode 100644 index 0000000000000000000000000000000000000000..5a94ac25b06b6713f55284f185d83d42f1550016 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4696.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f0d9b8b22257562f4475d4eb72ca73bc14d5f469", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 13, + "d": 7 + }, + "mne/io/reference.py": { + "a": 5, + "d": 3 + }, + "mne/io/tests/test_reference.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4698.json b/mne-python/source/doc/sphinxext/prs/4698.json new file mode 100644 index 0000000000000000000000000000000000000000..90924ff028cd533a90fc1942bdd0f2d61f46de68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4698.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "cc749f5b41ec282acaa7b09e59b61ed35ed4d59a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/gui/_kit2fiff_gui.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/misc.py": { + "a": 6, + "d": 15 + }, + "mne/realtime/client.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 8, + "d": 8 + }, + "mne/time_frequency/multitaper.py": { + "a": 3, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/47.json b/mne-python/source/doc/sphinxext/prs/47.json new file mode 100644 index 0000000000000000000000000000000000000000..8f1b9505eb7e8c42ef2db5438779169839d933c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/47.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "f301620f7107e3f0fac172cec0fab17ee0e9a79b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_evoked_whitening.py": { + "a": 48, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/cov.py": { + "a": 45, + "d": 0 + }, + "mne/fiff/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 24, + "d": 2 + }, + "mne/viz.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/470.json b/mne-python/source/doc/sphinxext/prs/470.json new file mode 100644 index 0000000000000000000000000000000000000000..deda3ea1671b72da9d4817c0f42b22337c9ca968 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/470.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dc62e4384bf93b07a9a873f6693ef23734d21056", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/bti/read.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4701.json b/mne-python/source/doc/sphinxext/prs/4701.json new file mode 100644 index 0000000000000000000000000000000000000000..501330718e4e7b70b69e29472cf89fb2ec458396 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4701.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d1c039da7ef745187f45aa6c9576772183fd7fbd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_viewer.py": { + "a": 8, + "d": 6 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 46, + "d": 44 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 31, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4702.json b/mne-python/source/doc/sphinxext/prs/4702.json new file mode 100644 index 0000000000000000000000000000000000000000..8177e7e0dc573fb1f79d428aaccd089ebd7ade3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4702.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ad870227c6d9810b1a873c60c2139aa00fdd3d14", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4703.json b/mne-python/source/doc/sphinxext/prs/4703.json new file mode 100644 index 0000000000000000000000000000000000000000..4535d3cdbf02a94cc6bd7a5e5e2fd04a43d5203d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4703.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f58c782d120d8805d0d0f5553fd34067e85c2a73", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 24 + }, + "tutorials/plot_forward.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4704.json b/mne-python/source/doc/sphinxext/prs/4704.json new file mode 100644 index 0000000000000000000000000000000000000000..f7319d709844c74d76e25b426ff55c45235eb226 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4704.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4f61d23742382181f3a5fb12969abb48b7f30311", + "authors": [ + { + "n": "Jen Evans", + "e": null + } + ], + "changes": { + "mne/io/egi/egimff.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4705.json b/mne-python/source/doc/sphinxext/prs/4705.json new file mode 100644 index 0000000000000000000000000000000000000000..961587ead830a14a9c20bff16d7f93937bb4536d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4705.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1324f79c390a8cdf874513b1bb15481e8344700f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 129, + "d": 83 + }, + "mne/viz/tests/test_3d.py": { + "a": 7, + "d": 2 + }, + "tutorials/plot_forward.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4706.json b/mne-python/source/doc/sphinxext/prs/4706.json new file mode 100644 index 0000000000000000000000000000000000000000..abfe0ea0b72841637f44129a7e28cc636d125d78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4706.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "de0e785737bbff0b0ba2393e6bdfff8677a4f403", + "authors": [ + { + "n": "Alejandro Weinstein", + "e": "alejandro.weinstein@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 0 + }, + "mne/evoked.py": { + "a": 4, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4707.json b/mne-python/source/doc/sphinxext/prs/4707.json new file mode 100644 index 0000000000000000000000000000000000000000..4ce7e46b84d0d7263dc43eb01bb2bae21fe53a8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4707.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "405ef473f9f8eda9acffc8fd0ab89cf5349bc567", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "tutorials/plot_python_intro.py": { + "a": 19, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4708.json b/mne-python/source/doc/sphinxext/prs/4708.json new file mode 100644 index 0000000000000000000000000000000000000000..40e41a50cc50a4fb8152ad8855dd2a6a8104f0d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4708.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "46c8f2f67f2cf7b90bdb75171f1f8d2919782391", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 5, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 24, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4711.json b/mne-python/source/doc/sphinxext/prs/4711.json new file mode 100644 index 0000000000000000000000000000000000000000..02e5e4d3983e49ce4c5492c10c2b3cf7e217b7a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4711.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8ad8cf87ac8da137aebcd8d058ce19085cc8f21c", + "authors": [ + { + "n": "Erik Hornberger", + "e": "erik.hornberger@shi-g.com" + } + ], + "changes": { + "tutorials/plot_epoching_and_averaging.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4713.json b/mne-python/source/doc/sphinxext/prs/4713.json new file mode 100644 index 0000000000000000000000000000000000000000..3dfe30ccf49cd9789b88501703328b75d556fd64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4713.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "58a188253aebaa1934fdfcc044731ce1222c9b93", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 8, + "d": 3 + }, + "mne/viz/tests/test_3d.py": { + "a": 5, + "d": 0 + }, + "tutorials/plot_source_alignment.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4716.json b/mne-python/source/doc/sphinxext/prs/4716.json new file mode 100644 index 0000000000000000000000000000000000000000..78e9f6d62a83854908fba9e4b808573fa48b5b02 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4716.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "966e862b95861de47ffe259bd66c86feece524f6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4717.json b/mne-python/source/doc/sphinxext/prs/4717.json new file mode 100644 index 0000000000000000000000000000000000000000..5bde582e2b6461cf766bcda160a22401015f8a10 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4717.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "062e9b39983dcb288e78041532f35f34788a6fce", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 27, + "d": 32 + }, + "mne/io/base.py": { + "a": 20, + "d": 15 + }, + "mne/io/fiff/raw.py": { + "a": 6, + "d": 9 + }, + "mne/tests/test_annotations.py": { + "a": 123, + "d": 35 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4718.json b/mne-python/source/doc/sphinxext/prs/4718.json new file mode 100644 index 0000000000000000000000000000000000000000..262a5fb9d290a93600d16c5a65047b8d09bbab73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4718.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "867fdb5e08e159c6a7b77104f124011d773751e4", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 24, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 10, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4721.json b/mne-python/source/doc/sphinxext/prs/4721.json new file mode 100644 index 0000000000000000000000000000000000000000..9bc3f55ba2c8ce18bb7ae969434b0e17a8511b9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4721.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "de256c8c314e3e158371e0fb90242f86af9a4753", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/externals/h5io/_h5io.py": { + "a": 70, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4722.json b/mne-python/source/doc/sphinxext/prs/4722.json new file mode 100644 index 0000000000000000000000000000000000000000..ca43d0577a2c473b039f31f7bdd2d694470e5847 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4722.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "40b61be17116fee3f0e96b84f1b2a8eed3028092", + "authors": [ + { + "n": "Jon Houck", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 14, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 11, + "d": 0 + }, + "mne/viz/circle.py": { + "a": 14, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4725.json b/mne-python/source/doc/sphinxext/prs/4725.json new file mode 100644 index 0000000000000000000000000000000000000000..78276cb3f0d731731d900c3390e46f5d378d2ca8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4725.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "031141291063a15c24ca9f0b6e7255a0c468db00", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/bem.py": { + "a": 3, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 12, + "d": 1 + }, + "mne/source_space.py": { + "a": 15, + "d": 6 + }, + "mne/tests/test_bem.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_source_space.py": { + "a": 11, + "d": 1 + }, + "mne/transforms.py": { + "a": 19, + "d": 8 + }, + "mne/viz/_3d.py": { + "a": 59, + "d": 15 + }, + "mne/viz/tests/test_3d.py": { + "a": 8, + "d": 2 + }, + "tutorials/plot_source_alignment.py": { + "a": 154, + "d": 45 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4729.json b/mne-python/source/doc/sphinxext/prs/4729.json new file mode 100644 index 0000000000000000000000000000000000000000..d57c2847417d5cbed666639dd7cf078527136b6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4729.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f90ddb194df1cbb6651b921a6817c8b64fa85bb5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/institutions.png": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/473.json b/mne-python/source/doc/sphinxext/prs/473.json new file mode 100644 index 0000000000000000000000000000000000000000..d4674a12e675d3e166724eae2e03bff1730b39b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/473.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4467b441a07a57ecda2332076b88003c731f78d8", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/pick.py": { + "a": 21, + "d": 16 + }, + "mne/fiff/tests/test_raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4733.json b/mne-python/source/doc/sphinxext/prs/4733.json new file mode 100644 index 0000000000000000000000000000000000000000..867118150100d49b43151729ae2269dc52a3b98c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4733.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "73806bc0b00accd99bb2209c9d406dc11ab94bc4", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4735.json b/mne-python/source/doc/sphinxext/prs/4735.json new file mode 100644 index 0000000000000000000000000000000000000000..531e815bab9094ff51523dfefbeba2177c39234b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4735.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5c9d7df3b13701169212bd3772af06c65a4521db", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/baseline.py": { + "a": 44, + "d": 32 + }, + "mne/epochs.py": { + "a": 11, + "d": 18 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 26, + "d": 24 + }, + "mne/tests/test_epochs.py": { + "a": 46, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 53, + "d": 58 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4737.json b/mne-python/source/doc/sphinxext/prs/4737.json new file mode 100644 index 0000000000000000000000000000000000000000..5c08f803148ddc2084baa0f458caf47edf63114c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4737.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "029e14a7f94e6dccb34b75ed2de408871ebbc798", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4739.json b/mne-python/source/doc/sphinxext/prs/4739.json new file mode 100644 index 0000000000000000000000000000000000000000..3c20c6d524797a7672e127bf0726aa84b2a5eb68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4739.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9b70d8ab0ce3289dd2a9f5a8f21f90ea1d592b2b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4740.json b/mne-python/source/doc/sphinxext/prs/4740.json new file mode 100644 index 0000000000000000000000000000000000000000..6dc1e3d976188b8224a7fe277b838376e9190128 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4740.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5c5429ae0ebeba7dfc58edbda4388bc26304dc7a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 4, + "d": 3 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4743.json b/mne-python/source/doc/sphinxext/prs/4743.json new file mode 100644 index 0000000000000000000000000000000000000000..85083b05aeefa023461c0fa1af2ced7de6900bb1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4743.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "14e8f6064d7c9f8bdd62ecd4d773f8b5878df0c4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 8, + "d": 1 + }, + "doc/conf.py": { + "a": 4, + "d": 3 + }, + "doc/documentation.rst": { + "a": 6, + "d": 3 + }, + "doc/manual/index.rst": { + "a": 0, + "d": 136 + }, + "doc/manual/statistics.rst": { + "a": 0, + "d": 100 + }, + "doc/python_reference.rst": { + "a": 28, + "d": 7 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 0, + "d": 1 + }, + "mne/stats/__init__.py": { + "a": 5, + "d": 8 + }, + "mne/stats/cluster_level.py": { + "a": 269, + "d": 268 + }, + "mne/stats/parametric.py": { + "a": 73, + "d": 31 + }, + "mne/stats/permutations.py": { + "a": 27, + "d": 73 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 9, + "d": 0 + }, + "mne/stats/tests/test_permutations.py": { + "a": 7, + "d": 6 + }, + "tutorials/plot_background_statistics.py": { + "a": 646, + "d": 0 + }, + "tutorials/plot_stats_cluster_methods.py": { + "a": 0, + "d": 214 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4744.json b/mne-python/source/doc/sphinxext/prs/4744.json new file mode 100644 index 0000000000000000000000000000000000000000..621bf129906072d8c6bae5f6148d4ae0a0840ca9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4744.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9d52566923e0ab1518a5100a050acea26a9545f1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/event.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4745.json b/mne-python/source/doc/sphinxext/prs/4745.json new file mode 100644 index 0000000000000000000000000000000000000000..a6dc5fd62bcf4393876a48260624358204675bae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4745.json @@ -0,0 +1,163 @@ +{ + "merge_commit_sha": "59f56acde198b1eba20b4411cf3d334ec328a36f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 10, + "d": 15 + }, + "doc/tutorials/report.rst": { + "a": 17, + "d": 17 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "environment2.yml": { + "a": 9, + "d": 5 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 7, + "d": 7 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/plot_megsim_data.py": { + "a": 3, + "d": 3 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 3, + "d": 3 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 18, + "d": 31 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 4, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 21, + "d": 11 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_interpolate_bad_channels.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_resample.py": { + "a": 2, + "d": 2 + }, + "examples/simulation/plot_simulate_raw_data.py": { + "a": 5, + "d": 2 + }, + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 2, + "d": 2 + }, + "mne/connectivity/spectral.py": { + "a": 12, + "d": 8 + }, + "mne/label.py": { + "a": 5, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 4, + "d": 4 + }, + "mne/report.py": { + "a": 17, + "d": 12 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 12, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_compute_covariance.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_eeg_erp.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 14, + "d": 15 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 4, + "d": 4 + }, + "tutorials/plot_visualize_epochs.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4751.json b/mne-python/source/doc/sphinxext/prs/4751.json new file mode 100644 index 0000000000000000000000000000000000000000..5e1c86ab4f88ea4b0f2ccd93e274040b970b2d1e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4751.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a99d78a7c3b865bd7c34a348e14e06dfebd4bb28", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4752.json b/mne-python/source/doc/sphinxext/prs/4752.json new file mode 100644 index 0000000000000000000000000000000000000000..04053a9caa831caac8d2cada2f51710cf0d7cc57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4752.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "086478e8334b38fbe02be4c0f2a147429906ba4a", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/cov.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4755.json b/mne-python/source/doc/sphinxext/prs/4755.json new file mode 100644 index 0000000000000000000000000000000000000000..58a39ed56cb8cf2108b47913e6cd30d3161d3fde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4755.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "44bac44efbc85f234c1cc642fbb6b6c9524fc101", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/evoked.py": { + "a": 13, + "d": 8 + }, + "mne/io/pick.py": { + "a": 27, + "d": 11 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 419, + "d": 202 + }, + "mne/viz/tests/test_evoked.py": { + "a": 72, + "d": 24 + }, + "tutorials/plot_metadata_epochs.py": { + "a": 66, + "d": 24 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4756.json b/mne-python/source/doc/sphinxext/prs/4756.json new file mode 100644 index 0000000000000000000000000000000000000000..4b2b90b5387438a4fc48df751be8aa99530754f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4756.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "54897b95d624c3e86bd30ae7654aadbedb60b7a2", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/event.py": { + "a": 19, + "d": 4 + }, + "mne/io/edf/edf.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_event.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4758.json b/mne-python/source/doc/sphinxext/prs/4758.json new file mode 100644 index 0000000000000000000000000000000000000000..2ee87a1454bba4f97e8404876aca62abe1dc387a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4758.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4e5a6c36d120d988939e22edd9d6a818039be3d6", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/476.json b/mne-python/source/doc/sphinxext/prs/476.json new file mode 100644 index 0000000000000000000000000000000000000000..725cd4c0116f269513931614a782f8af4b5e17a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/476.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1b4f703817bbff32e592e4d776593dd5364f9ff5", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4761.json b/mne-python/source/doc/sphinxext/prs/4761.json new file mode 100644 index 0000000000000000000000000000000000000000..b023eb3048d9be51919e0365cbbfa7377a50e9e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4761.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "a7a62f2b77927b6e257a69fe3ce559d9d2e06fc9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/read.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 54, + "d": 54 + }, + "mne/io/tree.py": { + "a": 2, + "d": 5 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/client.py": { + "a": 3, + "d": 3 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4763.json b/mne-python/source/doc/sphinxext/prs/4763.json new file mode 100644 index 0000000000000000000000000000000000000000..05f57bff7c10468d96a4b92110c7c25f536f1730 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4763.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e0f75c4eca651314eec63d1788b060f0e5980f0c", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 8, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4765.json b/mne-python/source/doc/sphinxext/prs/4765.json new file mode 100644 index 0000000000000000000000000000000000000000..e7b26916b943deb07e4e16d99f9f0b68aa690247 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4765.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "caa5c8bbfe9042577502d837683d7033a4174b7d", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/stats/plot_sensor_regression.py": { + "a": 36, + "d": 59 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4767.json b/mne-python/source/doc/sphinxext/prs/4767.json new file mode 100644 index 0000000000000000000000000000000000000000..481bbb38b304cea0304d1049676efae633f9e587 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4767.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c2d7e24d41060917da66ec94ffc866b7023ef4d5", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 48, + "d": 42 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/477.json b/mne-python/source/doc/sphinxext/prs/477.json new file mode 100644 index 0000000000000000000000000000000000000000..c30829372ddbdb07f66759bec5b247329b0261d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/477.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4c93d0381866ada142292ad9575ff4039ad4f48e", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/forward.py": { + "a": 49, + "d": 29 + }, + "mne/tests/test_forward.py": { + "a": 5, + "d": 2 + }, + "mne/utils.py": { + "a": 36, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4772.json b/mne-python/source/doc/sphinxext/prs/4772.json new file mode 100644 index 0000000000000000000000000000000000000000..a22fbf02e01a4eb4a4cdbc8ecd4e9ebaebe93e06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4772.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fe6fa4963cf2080160b9d435c122b4c8ba87d77a", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "tutorials/plot_artifacts_correction_ica.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4773.json b/mne-python/source/doc/sphinxext/prs/4773.json new file mode 100644 index 0000000000000000000000000000000000000000..03834ad027b964f764cdacf70471b4322fbd720e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4773.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2d9a08e2a59dfd32763435fd1ef96b5be62fdf43", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 7, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4775.json b/mne-python/source/doc/sphinxext/prs/4775.json new file mode 100644 index 0000000000000000000000000000000000000000..c518cf8eecb4b9b47891c761bc99af5bce3b2b9e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4775.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "857b1fed003004aed704db7ffaad10b2e94ac402", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/stats/plot_sensor_regression.py": { + "a": 25, + "d": 9 + }, + "mne/viz/evoked.py": { + "a": 44, + "d": 12 + }, + "mne/viz/tests/test_evoked.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4778.json b/mne-python/source/doc/sphinxext/prs/4778.json new file mode 100644 index 0000000000000000000000000000000000000000..fc45f09d135b6098aabb6bcc75ad13c96b34356e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4778.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "723a5ddb885fa76f21b6a12e15e0d6725ca33528", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/478.json b/mne-python/source/doc/sphinxext/prs/478.json new file mode 100644 index 0000000000000000000000000000000000000000..476695a75a620ced0a8357cdba03166a5fae2c10 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/478.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "183b9f1806a054797b358370ec7647fcaf95ff0e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/bti/raw.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4781.json b/mne-python/source/doc/sphinxext/prs/4781.json new file mode 100644 index 0000000000000000000000000000000000000000..9dcba995f007c2b6ab59145ce35464ccb62bd65e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4781.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "57179af6e426d59591e2d6ff684e1478bc5b13f8", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 20, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4782.json b/mne-python/source/doc/sphinxext/prs/4782.json new file mode 100644 index 0000000000000000000000000000000000000000..4493d06f664dad2af84034658c992a1b6a990af0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4782.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0613771cbfb76022a1e9fb5594977ffbcc3e841f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4785.json b/mne-python/source/doc/sphinxext/prs/4785.json new file mode 100644 index 0000000000000000000000000000000000000000..f992ac1213e9388e407e0b85b0158181fa9a41d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4785.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "63e4e3b98493dd488c9e5806daf83ea2bb227463", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4786.json b/mne-python/source/doc/sphinxext/prs/4786.json new file mode 100644 index 0000000000000000000000000000000000000000..e040387573925a64cf9c14bd266b860bc17f33b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4786.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7ff5d64cb8b772e868087e56352563ea21952f0b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 4, + "d": 3 + }, + "mne/stats/tests/test_permutations.py": { + "a": 20, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4787.json b/mne-python/source/doc/sphinxext/prs/4787.json new file mode 100644 index 0000000000000000000000000000000000000000..824b6bf54f2f5edc0eb014662b184529a2453f13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4787.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6c641dd74f869f316877e43dc15ebc4cfe8077e6", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/egimff.py": { + "a": 18, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 37, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4789.json b/mne-python/source/doc/sphinxext/prs/4789.json new file mode 100644 index 0000000000000000000000000000000000000000..d51884d38e1d0b72ef3f23f892638de19fc301ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4789.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c3a5cf4c6e9afec1b0706eac731af4127dfe13ea", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/479.json b/mne-python/source/doc/sphinxext/prs/479.json new file mode 100644 index 0000000000000000000000000000000000000000..281bc21923b8e3940264ad2d63a8a32ef4072b35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/479.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c14ee59f039927c3b7911949c43ed0c1e24769de", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ssp.py": { + "a": 18, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4790.json b/mne-python/source/doc/sphinxext/prs/4790.json new file mode 100644 index 0000000000000000000000000000000000000000..688eb314896e1307062bd26b9f0233a75fbc6af7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4790.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b251871936be2d6c6489bf05412a13a9654c1f52", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4791.json b/mne-python/source/doc/sphinxext/prs/4791.json new file mode 100644 index 0000000000000000000000000000000000000000..8857818bdd3d0f2f2a317d176c3db58033ebf100 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4791.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2c17fa7776497b7b021299b69ce6151adf8fe83d", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/constants.py": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 12, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4793.json b/mne-python/source/doc/sphinxext/prs/4793.json new file mode 100644 index 0000000000000000000000000000000000000000..7422f4d4ec88b9c59849098f9ad93b49977545ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4793.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "fb0a8eb27b8a14fa894688e70242a895d4fc4790", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 6 + }, + "mne/report.py": { + "a": 13, + "d": 23 + }, + "mne/tests/test_report.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4794.json b/mne-python/source/doc/sphinxext/prs/4794.json new file mode 100644 index 0000000000000000000000000000000000000000..48565ab6a35ffa390c3cbf46dd39a9a2dcbcd75c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4794.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "04ecb9a6cbe73ba786783196fa39fbc2ca02e47c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4798.json b/mne-python/source/doc/sphinxext/prs/4798.json new file mode 100644 index 0000000000000000000000000000000000000000..c9bfb81da59f6c819c893cde8439dcba2f8d2eb0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4798.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fd5b5fa864ebe140d6f3311e35933a51e67c41ca", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 26, + "d": 8 + }, + "mne/viz/topomap.py": { + "a": 43, + "d": 8 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4799.json b/mne-python/source/doc/sphinxext/prs/4799.json new file mode 100644 index 0000000000000000000000000000000000000000..33c10960fb5031d6326d099aec5298a3d8d71184 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4799.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "e84b316cb188043c69a4958b74884bfb556d78d8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 4, + "d": 3 + }, + "examples/io/plot_read_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 12, + "d": 8 + }, + "mne/cov.py": { + "a": 2, + "d": 1 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 12, + "d": 54 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + }, + "mne/io/pick.py": { + "a": 2, + "d": 2 + }, + "mne/io/proc_history.py": { + "a": 3, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 40, + "d": 20 + }, + "mne/viz/evoked.py": { + "a": 97, + "d": 151 + }, + "mne/viz/ica.py": { + "a": 7, + "d": 10 + }, + "mne/viz/raw.py": { + "a": 41, + "d": 12 + }, + "mne/viz/tests/test_epochs.py": { + "a": 28, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 191, + "d": 168 + }, + "mne/viz/tests/test_raw.py": { + "a": 10, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 3, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 32, + "d": 10 + }, + "mne/viz/utils.py": { + "a": 200, + "d": 3 + }, + "tutorials/plot_compute_covariance.py": { + "a": 7, + "d": 8 + }, + "tutorials/plot_visualize_raw.py": { + "a": 11, + "d": 4 + }, + "tutorials/plot_whitened.py": { + "a": 71, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/48.json b/mne-python/source/doc/sphinxext/prs/48.json new file mode 100644 index 0000000000000000000000000000000000000000..d5edabfe8b6009d093ed89daa4b85f2b51c5d524 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/48.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "118b15b45738f49e44787d32f8520d0e95073386", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 65, + "d": 11 + }, + "mne/fiff/tests/test_raw.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/480.json b/mne-python/source/doc/sphinxext/prs/480.json new file mode 100644 index 0000000000000000000000000000000000000000..9aea8e0d477c3825b95af145d1b69abfd3428b69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/480.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3fb7465e3b4135bd5f274ea267ff84ae31784f9b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4800.json b/mne-python/source/doc/sphinxext/prs/4800.json new file mode 100644 index 0000000000000000000000000000000000000000..04e593e46ce6eb77aeb2b07fb30b41e1080dc3a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4800.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cb3f93d45d9e4391ab2ef3e060fa69ce8a3755fa", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 4, + "d": 2 + }, + "mne/decoding/tests/test_base.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4801.json b/mne-python/source/doc/sphinxext/prs/4801.json new file mode 100644 index 0000000000000000000000000000000000000000..2f84a41800a864fefc16f62dd600f9eae25ce95e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4801.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6dcc003dde543663ae11c389fbd5f830079f4056", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4803.json b/mne-python/source/doc/sphinxext/prs/4803.json new file mode 100644 index 0000000000000000000000000000000000000000..71457421bafc1278b19a4602e9daa1fd2029bd22 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4803.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4c03ce1d7d5581c2e8ed0c96112d4b7bb35e54a1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4806.json b/mne-python/source/doc/sphinxext/prs/4806.json new file mode 100644 index 0000000000000000000000000000000000000000..53d200ae1507971c40cccbcdd07f66232b67d60b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4806.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a4d91852fcecf2b9db99884653e255ba02eeecf9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_movement_compensation.py": { + "a": 23, + "d": 8 + }, + "mne/chpi.py": { + "a": 11, + "d": 5 + }, + "mne/viz/_3d.py": { + "a": 118, + "d": 10 + }, + "mne/viz/tests/test_3d.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4807.json b/mne-python/source/doc/sphinxext/prs/4807.json new file mode 100644 index 0000000000000000000000000000000000000000..3015020da6de7e80ff14b931c113d21ae3380b7c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4807.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "12e509c5384c7d5b73c056500ddc04788fb36506", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + ".travis.yml": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4808.json b/mne-python/source/doc/sphinxext/prs/4808.json new file mode 100644 index 0000000000000000000000000000000000000000..f1749313a6082d8f15871053a733fdf62b9de85c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4808.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "5c9b89ac88c1747f50e0d665a7ccd3dd2b22c296", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 3, + "d": 3 + }, + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 3, + "d": 3 + }, + "mne/cov.py": { + "a": 233, + "d": 259 + }, + "mne/decoding/csp.py": { + "a": 36, + "d": 28 + }, + "mne/decoding/tests/test_csp.py": { + "a": 2, + "d": 1 + }, + "mne/fixes.py": { + "a": 281, + "d": 0 + }, + "mne/preprocessing/xdawn.py": { + "a": 19, + "d": 11 + }, + "mne/tests/test_cov.py": { + "a": 13, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4809.json b/mne-python/source/doc/sphinxext/prs/4809.json new file mode 100644 index 0000000000000000000000000000000000000000..bff495016403768e5524bf0f5796e52c28abee4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4809.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "993240469782dd4eeb3717f088df19c70f8d3f11", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/event.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_event.py": { + "a": 22, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/481.json b/mne-python/source/doc/sphinxext/prs/481.json new file mode 100644 index 0000000000000000000000000000000000000000..cbe931f7e0ab362f4717d3c079494de4cf68bfdd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/481.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "affa3e884ae52fcd92350360b502b4a7543debe8", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 11, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 7, + "d": 0 + }, + "mne/connectivity/spectral.py": { + "a": 42, + "d": 31 + }, + "mne/minimum_norm/inverse.py": { + "a": 21, + "d": 8 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 6, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 232, + "d": 33 + }, + "mne/tests/test_source_estimate.py": { + "a": 69, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4810.json b/mne-python/source/doc/sphinxext/prs/4810.json new file mode 100644 index 0000000000000000000000000000000000000000..af2b10c143a6bfa132e902cdfb869fb98b4389ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4810.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "20920d731f1ab6c60b8101290c5212e471f229c1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/proc_history.py": { + "a": 2, + "d": 2 + }, + "mne/io/tag.py": { + "a": 21, + "d": 14 + }, + "mne/io/tests/test_meas_info.py": { + "a": 37, + "d": 1 + }, + "mne/io/write.py": { + "a": 24, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4811.json b/mne-python/source/doc/sphinxext/prs/4811.json new file mode 100644 index 0000000000000000000000000000000000000000..ab33f217678ed0f201c47c3d661861e20f26ee91 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4811.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f568738b10c5186a1475d41e5d62373f9134ead6", + "authors": [ + { + "n": "Yaroslav Halchenko", + "e": null + } + ], + "changes": { + "mne/externals/tempita/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4812.json b/mne-python/source/doc/sphinxext/prs/4812.json new file mode 100644 index 0000000000000000000000000000000000000000..c1e9a8d97050168c4cdedaa879b1d2daa81028ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4812.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "04ff09d594287d5fe6df20d124d13e7bc446477e", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 11, + "d": 11 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4814.json b/mne-python/source/doc/sphinxext/prs/4814.json new file mode 100644 index 0000000000000000000000000000000000000000..84ca64565feebcd6e34d122679581d6a28391354 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4814.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2d4b1d847222364fad93a4f9bc4f9d5b17542f46", + "authors": [ + { + "n": "Yaroslav Halchenko", + "e": null + } + ], + "changes": { + "mne/decoding/tests/test_receptive_field.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4825.json b/mne-python/source/doc/sphinxext/prs/4825.json new file mode 100644 index 0000000000000000000000000000000000000000..ac953f6a108817f6ab33a3ab49779d266b6d95e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4825.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d6654b1bbd0459557b320de3674a0a877aa055f8", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4827.json b/mne-python/source/doc/sphinxext/prs/4827.json new file mode 100644 index 0000000000000000000000000000000000000000..b4d4367d208f4c0094417c47d7a5c026fa05e15a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4827.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c3535731c2531b8ae5166a69ab78df9ca4c9badb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/preprocessing/plot_metadata_query.py": { + "a": 5, + "d": 2 + }, + "mne/epochs.py": { + "a": 69, + "d": 38 + }, + "mne/tests/test_epochs.py": { + "a": 46, + "d": 4 + }, + "tutorials/plot_metadata_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4830.json b/mne-python/source/doc/sphinxext/prs/4830.json new file mode 100644 index 0000000000000000000000000000000000000000..7691cf4cd047b235e20b81dbafa5cdc53e4d404b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4830.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "5c9d1404904cfdcfd33d4452c6697353e2f24e35", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 3 + }, + "mne/chpi.py": { + "a": 4, + "d": 2 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 42, + "d": 34 + }, + "mne/tests/test_chpi.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_report.py": { + "a": 8, + "d": 8 + }, + "mne/utils.py": { + "a": 0, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 5 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4836.json b/mne-python/source/doc/sphinxext/prs/4836.json new file mode 100644 index 0000000000000000000000000000000000000000..020a911f27149dbd029088bab8f03cb8243628bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4836.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0fef95cd69f031318fe6dc339b5d3d3e2707cd6a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/externals/h5io/_h5io.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_receptive_field.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4838.json b/mne-python/source/doc/sphinxext/prs/4838.json new file mode 100644 index 0000000000000000000000000000000000000000..629b340e7bc859676210636a5c987ddf456c5b2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4838.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2f21c1b3a8146501fefd770e466095053651bb33", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/search_light.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_base.py": { + "a": 19, + "d": 2 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/484.json b/mne-python/source/doc/sphinxext/prs/484.json new file mode 100644 index 0000000000000000000000000000000000000000..c30c50cba735c1dbf0c1dc6aaefa0b8a2c3a559f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/484.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9c4f57e85c55b761fe600f6ce99f61a2bbeca753", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 4 + }, + "mne/viz.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4840.json b/mne-python/source/doc/sphinxext/prs/4840.json new file mode 100644 index 0000000000000000000000000000000000000000..e811a81d0207014558a8feb1ec285cf249bfd1bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4840.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e23c3d148948bf8a720c6187fd750a6188dd09e5", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4842.json b/mne-python/source/doc/sphinxext/prs/4842.json new file mode 100644 index 0000000000000000000000000000000000000000..5f8b944e000492db5678c516cbd9853797eb4698 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4842.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "df7e00ecb760863bc6766e3052be625fc9a8ec5d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/pick.py": { + "a": 51, + "d": 49 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4844.json b/mne-python/source/doc/sphinxext/prs/4844.json new file mode 100644 index 0000000000000000000000000000000000000000..8b29ba3941bd935bea6c41140bdd8b5d1ad92208 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4844.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d4350a5d617a3422c69f40501568886b304b0bf4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 82, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 12 + }, + "mne/io/fiff/raw.py": { + "a": 3, + "d": 26 + }, + "mne/tests/test_annotations.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4845.json b/mne-python/source/doc/sphinxext/prs/4845.json new file mode 100644 index 0000000000000000000000000000000000000000..8f13fd05f16db6c329ea72a4f80146486be7d270 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4845.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "79959786786311aedd20da272fb4de94a20f16ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 10, + "d": 0 + }, + "mne/annotations.py": { + "a": 25, + "d": 12 + }, + "mne/io/base.py": { + "a": 49, + "d": 18 + }, + "mne/io/constants.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/raw.py": { + "a": 3, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 61, + "d": 9 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 0 + }, + "mne/io/open.py": { + "a": 7, + "d": 3 + }, + "mne/io/tag.py": { + "a": 17, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 4, + "d": 0 + }, + "mne/io/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 10, + "d": 5 + }, + "mne/tests/test_annotations.py": { + "a": 35, + "d": 4 + }, + "mne/viz/raw.py": { + "a": 14, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4846.json b/mne-python/source/doc/sphinxext/prs/4846.json new file mode 100644 index 0000000000000000000000000000000000000000..61a2e044d53b8aa028abbb559f61e39fecf9d6f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4846.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "350416249589047f117f1194e8d8cf6061258f0c", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 7, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4848.json b/mne-python/source/doc/sphinxext/prs/4848.json new file mode 100644 index 0000000000000000000000000000000000000000..6bc160c397616b36f87f6fd5c925f2a5b423ec22 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4848.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b50f0d8b198768cae3f33fd79f64271abd461f3e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 7, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/485.json b/mne-python/source/doc/sphinxext/prs/485.json new file mode 100644 index 0000000000000000000000000000000000000000..7aa8564abfffab281fab1db6f4e4b47dda2cf885 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/485.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ae20baeb3fe621164341717720dbf9bea92577a9", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4854.json b/mne-python/source/doc/sphinxext/prs/4854.json new file mode 100644 index 0000000000000000000000000000000000000000..cc9637249bdc0f5240af7401627ee70a1deb212e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4854.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "e62a46a1ae3200bfdfb8cb8d48c6bde3810c1fe6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "circle.yml": { + "a": 3, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_otp.py": { + "a": 84, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/otp.py": { + "a": 141, + "d": 0 + }, + "mne/preprocessing/tests/test_otp.py": { + "a": 104, + "d": 0 + }, + "mne/preprocessing/utils.py": { + "a": 59, + "d": 0 + }, + "tutorials/plot_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4857.json b/mne-python/source/doc/sphinxext/prs/4857.json new file mode 100644 index 0000000000000000000000000000000000000000..7b621833ef90262b79433a17a574bf04f881d02a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4857.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a556375549dc45c2d1c573de935d47f846468372", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 9, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4858.json b/mne-python/source/doc/sphinxext/prs/4858.json new file mode 100644 index 0000000000000000000000000000000000000000..1cbe1211c9eabf376886be8d643f41a871a602d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4858.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "548d8131d452720d9c6af7b74831c3182fd107fc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 4, + "d": 3 + }, + "mne/channels/interpolation.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/receptive_field.py": { + "a": 6, + "d": 6 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 2, + "d": 1 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 16, + "d": 0 + }, + "mne/forward/_compute_forward.py": { + "a": 8, + "d": 8 + }, + "mne/forward/_lead_dots.py": { + "a": 10, + "d": 9 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 14, + "d": 14 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/surface.py": { + "a": 11, + "d": 11 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/486.json b/mne-python/source/doc/sphinxext/prs/486.json new file mode 100644 index 0000000000000000000000000000000000000000..d597e5bbc3e69edfed23a2b9bdcb43a2e4d2a795 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/486.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "24952bf337564fb63cbadc7225f6b5232cfe5747", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "bin/mne_browse_raw.py": { + "a": 73, + "d": 0 + }, + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/python_tutorial.rst": { + "a": 1, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 4, + "d": 1 + }, + "examples/plot_read_and_write_raw_data.py": { + "a": 1, + "d": 6 + }, + "mne/fiff/proj.py": { + "a": 15, + "d": 5 + }, + "mne/fiff/raw.py": { + "a": 59, + "d": 0 + }, + "mne/tests/test_viz.py": { + "a": 6, + "d": 0 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + }, + "mne/viz.py": { + "a": 507, + "d": 4 + }, + "setup.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4860.json b/mne-python/source/doc/sphinxext/prs/4860.json new file mode 100644 index 0000000000000000000000000000000000000000..4dad9f96827c41856a32d0db4dab668653f0478a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4860.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "5551a88d7c6203483abb334d7e526f25c2885818", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 5, + "d": 4 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 3, + "d": 1 + }, + "mne/dipole.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 4, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 21, + "d": 21 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 10, + "d": 3 + }, + "mne/io/eeglab/eeglab.py": { + "a": 4, + "d": 3 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/io/tag.py": { + "a": 3, + "d": 1 + }, + "mne/source_space.py": { + "a": 6, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 5, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4861.json b/mne-python/source/doc/sphinxext/prs/4861.json new file mode 100644 index 0000000000000000000000000000000000000000..66e899049fb6eb733d83a6390118e6d826589810 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4861.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "244a2508cf7b4bfb75cb94f55d19e137c3bf5163", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 8, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 25, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4862.json b/mne-python/source/doc/sphinxext/prs/4862.json new file mode 100644 index 0000000000000000000000000000000000000000..4c39c3b139f5e7c466eac43c35af1a1df1f3b0f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4862.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9b6f0cab5763fa5b8e8672561fb67c5d7bcdac6c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 20, + "d": 13 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 18, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4864.json b/mne-python/source/doc/sphinxext/prs/4864.json new file mode 100644 index 0000000000000000000000000000000000000000..03d2a0a3d29365dcc5fdf7f4e311136cdeb15b70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4864.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fce5e9810af6df61b4fea853f9bb940fcaa3e43c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 55, + "d": 7 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4866.json b/mne-python/source/doc/sphinxext/prs/4866.json new file mode 100644 index 0000000000000000000000000000000000000000..f474ad83331b82e39fd3dd75e804dc9d9e4b14db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4866.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e159bffa218683f62d2ea1a4fffc63f3d0d8a240", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4867.json b/mne-python/source/doc/sphinxext/prs/4867.json new file mode 100644 index 0000000000000000000000000000000000000000..9dba61518368a9c0e514651b37a744ade9e3c1c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4867.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1efbe92e6e82b48ff33a74a97c24e5c68853e0e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 11, + "d": 16 + }, + "mne/tests/test_report.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4868.json b/mne-python/source/doc/sphinxext/prs/4868.json new file mode 100644 index 0000000000000000000000000000000000000000..31f614c05f36b20e61c69982c5e68bc37968bd57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4868.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4b7db5e66e5ad82ac1e76d5b75705fd3c3d0dede", + "authors": [ + { + "n": "Kambiz Tavabi", + "e": "ktavabi@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4870.json b/mne-python/source/doc/sphinxext/prs/4870.json new file mode 100644 index 0000000000000000000000000000000000000000..d670d41d5de1abdd3257d7892857e51cac95f5e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4870.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "b9c712b2376b54f2ae80550945a0df8fe7ec156b", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/externals/decorator.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 40, + "d": 21 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 4, + "d": 4 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 4 + }, + "mne/io/tests/test_raw.py": { + "a": 12, + "d": 2 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 20, + "d": 17 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_raw.py": { + "a": 7, + "d": 5 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4871.json b/mne-python/source/doc/sphinxext/prs/4871.json new file mode 100644 index 0000000000000000000000000000000000000000..69dde1d1a17dec26246d2fad467b1b958a9dada5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4871.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8a302bd0659bf41c77d505d52fc7a3ae94621599", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 14, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 4, + "d": 2 + }, + "mne/source_space.py": { + "a": 5, + "d": 10 + }, + "mne/utils.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4878.json b/mne-python/source/doc/sphinxext/prs/4878.json new file mode 100644 index 0000000000000000000000000000000000000000..518177e8d88593bfd2c6b002316149dd4521e884 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4878.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "491b412ee4f521e98a13e95d032e1c13ad67d3cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 15, + "d": 9 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4879.json b/mne-python/source/doc/sphinxext/prs/4879.json new file mode 100644 index 0000000000000000000000000000000000000000..147f10aa9e7158fbaaa8281ea43bec9d9a6bbafb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4879.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "329f1b10f625dc3169d82a6b36e941e10681bc96", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 61, + "d": 5 + }, + "doc/carousel.inc": { + "a": 1, + "d": 1 + }, + "doc/documentation.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_receptive_field_mtrf.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/488.json b/mne-python/source/doc/sphinxext/prs/488.json new file mode 100644 index 0000000000000000000000000000000000000000..174cc4bbd272509e00900b410c36a573e1c36707 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/488.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f5b4ebeb02872dfc4e855eccaf3f17fa1996fda7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4881.json b/mne-python/source/doc/sphinxext/prs/4881.json new file mode 100644 index 0000000000000000000000000000000000000000..c94df87ad52761d43af737fa294e308e72f85e20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4881.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "56b9f40de9bff253afa63e7a927db4b4597d7b1a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/mne_browse_raw.py": { + "a": 5, + "d": 5 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4883.json b/mne-python/source/doc/sphinxext/prs/4883.json new file mode 100644 index 0000000000000000000000000000000000000000..81def3b673ab26cd9195f3ab1cf216a0170eff8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4883.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d1a1c47c9fb2cc9c57bdd119736414e31b917525", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4884.json b/mne-python/source/doc/sphinxext/prs/4884.json new file mode 100644 index 0000000000000000000000000000000000000000..4a059a4fdcab98c230d751381c42fce77ad67491 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4884.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "323c2be3fd0d27fc42942d0f30df47f81df87ce3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4886.json b/mne-python/source/doc/sphinxext/prs/4886.json new file mode 100644 index 0000000000000000000000000000000000000000..887f4a987cd41375d8e42ed0ca555cefcecf87d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4886.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2336e3603f219b35e2e4a9e4a3d7cf9f7132d22f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4887.json b/mne-python/source/doc/sphinxext/prs/4887.json new file mode 100644 index 0000000000000000000000000000000000000000..a5889c5262b3e788fbf006c31b1a11e7d9a5a22a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4887.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b223ea351d9b6579aa64554748249eaa95bfba95", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 29, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4888.json b/mne-python/source/doc/sphinxext/prs/4888.json new file mode 100644 index 0000000000000000000000000000000000000000..78722f79342d8f86ae008d41af70082a18729d51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4888.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e6c2bc01588f11fb9f769f43451885024bcdb1f8", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 5 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/489.json b/mne-python/source/doc/sphinxext/prs/489.json new file mode 100644 index 0000000000000000000000000000000000000000..1aa2404a42c5cc8dff9e193ae82c674a30329c39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/489.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "64bbcd3188411034490deb8fe8cf22590d00551a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 38, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4891.json b/mne-python/source/doc/sphinxext/prs/4891.json new file mode 100644 index 0000000000000000000000000000000000000000..03e6fa7e3c8865cc43b889381858abf8798dd5c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4891.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c2e88b0498d23b067374444038455c7ea2428650", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 8, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4894.json b/mne-python/source/doc/sphinxext/prs/4894.json new file mode 100644 index 0000000000000000000000000000000000000000..cfb147959c3a5e1b56e977551d5c44923ba246d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4894.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ba7447ec2b2a3e6a006440e8151cae159b6335e0", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 24, + "d": 21 + }, + "mne/source_space.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_coreg.py": { + "a": 32, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4895.json b/mne-python/source/doc/sphinxext/prs/4895.json new file mode 100644 index 0000000000000000000000000000000000000000..e8e004669826c0f96c0816b5db293908a9382ddc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4895.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "412a1a65263495cdbbe42a455fd6899599adc794", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 14, + "d": 15 + }, + "mne/tests/test_transforms.py": { + "a": 28, + "d": 1 + }, + "mne/transforms.py": { + "a": 36, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/49.json b/mne-python/source/doc/sphinxext/prs/49.json new file mode 100644 index 0000000000000000000000000000000000000000..5b30cba2988c784ae61e6b5ada839de5f6664c0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/49.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a26c197ea96739d8fe4345bc700623d447b83e4b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_estimate_covariance_matrix_baseline.py": { + "a": 55, + "d": 0 + }, + "examples/plot_estimate_covariance_matrix_raw.py": { + "a": 0, + "d": 0 + }, + "mne/cov.py": { + "a": 14, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 18, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4900.json b/mne-python/source/doc/sphinxext/prs/4900.json new file mode 100644 index 0000000000000000000000000000000000000000..cbd46cb65559a94e254f2d59fa12ed99c321024e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4900.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "64d03eb6114e85168f9d4a0d5eae8cdc1470c378", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4902.json b/mne-python/source/doc/sphinxext/prs/4902.json new file mode 100644 index 0000000000000000000000000000000000000000..025ef25747b5a505a4c883c26e8b2fc620e77e29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4902.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a3c274c2c04346e26f1cb697b3a2561cf9480e15", + "authors": [ + { + "n": "Henrich Kolkhorst", + "e": null + } + ], + "changes": { + "mne/event.py": { + "a": 1, + "d": 0 + }, + "mne/realtime/epochs.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4903.json b/mne-python/source/doc/sphinxext/prs/4903.json new file mode 100644 index 0000000000000000000000000000000000000000..01de54da2e2a83839b1d18958cc05fd0642e1dad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4903.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ed4ef2df783669b0b3fa5095a60f84caf8f1093e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/defaults.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 16, + "d": 5 + }, + "mne/viz/tests/test_3d.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4905.json b/mne-python/source/doc/sphinxext/prs/4905.json new file mode 100644 index 0000000000000000000000000000000000000000..4fe501c162adf4fa1ef87df81207129cde4a2886 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4905.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4438451fb53180529ffc511b28899658cdeeaa43", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 8, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4908.json b/mne-python/source/doc/sphinxext/prs/4908.json new file mode 100644 index 0000000000000000000000000000000000000000..16948cff16f9c8507df9945a91988e8b5ac4ea6c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4908.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "94eb475d82125bfba0acade328d64fcae0f127a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 57, + "d": 7 + }, + "mne/channels/tests/test_channels.py": { + "a": 13, + "d": 0 + }, + "mne/io/base.py": { + "a": 4, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 7, + "d": 2 + }, + "mne/io/tests/test_pick.py": { + "a": 8, + "d": 6 + }, + "mne/tests/test_event.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4909.json b/mne-python/source/doc/sphinxext/prs/4909.json new file mode 100644 index 0000000000000000000000000000000000000000..5dd11cf43117181ad7607bd636ace173c0f04eb6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4909.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ab1580266d01561b6e273ee3c3c90c042a182d6b", + "authors": [ + { + "n": "Maksymenko Kostiantyn", + "e": "makkostya@ukr.net" + } + ], + "changes": { + "mne/annotations.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4910.json b/mne-python/source/doc/sphinxext/prs/4910.json new file mode 100644 index 0000000000000000000000000000000000000000..91f42023fd0ed27566848328ffa385fc7d6c966d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4910.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "76904ec1506f3efc0bf59e2675e071160b3e92ed", + "authors": [ + { + "n": "AnneSo", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/annotations.py": { + "a": 43, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4911.json b/mne-python/source/doc/sphinxext/prs/4911.json new file mode 100644 index 0000000000000000000000000000000000000000..4633d29cf3568f66549cbe28bb7170aa55ee594b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4911.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0e4cf70b742f36ada54550500b9e7d0133ec3d9b", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/io/ctf/eeg.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4913.json b/mne-python/source/doc/sphinxext/prs/4913.json new file mode 100644 index 0000000000000000000000000000000000000000..77cb480333b4cc35bd1d60c9af4cd2d1a7f3003c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4913.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "02334a9ce1ad1547d825028429fa8a5029262e91", + "authors": [ + { + "n": "Larry Eisenman", + "e": "lneisenman@hotmail.com" + } + ], + "changes": { + "examples/visualization/plot_3d_to_2d.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_ecog.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4915.json b/mne-python/source/doc/sphinxext/prs/4915.json new file mode 100644 index 0000000000000000000000000000000000000000..2dcba60075d3d62975def7ddca9f487abb536379 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4915.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "5a9d6c608907166aab72dbf94d7bf31aeea5e81a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "circle.yml": { + "a": 4, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/manual/datasets_index.rst": { + "a": 8, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/phantom_4dbti/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/phantom_4dbti/phantom_4dbti.py": { + "a": 29, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 9, + "d": 3 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_phantom_4DBTi.py": { + "a": 77, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4916.json b/mne-python/source/doc/sphinxext/prs/4916.json new file mode 100644 index 0000000000000000000000000000000000000000..629bc8a58050c2d3d0a7388e3c7a2e9d5e57f861 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4916.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7414eb93b62e5eb8acac6a5b8902a2cb51f40614", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/defaults.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4918.json b/mne-python/source/doc/sphinxext/prs/4918.json new file mode 100644 index 0000000000000000000000000000000000000000..a5934cab6df3e5ca45bcdedeb756f4d0996dc3ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4918.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "83274909e0772e2ca00ff8826dda813d620f1e2e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 27, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4919.json b/mne-python/source/doc/sphinxext/prs/4919.json new file mode 100644 index 0000000000000000000000000000000000000000..a4df99c61092e885a9ed0c67e121719fb1844b63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4919.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "38bd3c4fccf06445b6f5e8cdfa2a763c5bc95b5a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_phantom_4DBTi.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/492.json b/mne-python/source/doc/sphinxext/prs/492.json new file mode 100644 index 0000000000000000000000000000000000000000..950666dfe6b326a514784151a87c7dc9726b3d24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/492.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "85799b69570c4b530b48f8a0471184a469d76a62", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/kit/coreg.py": { + "a": 85, + "d": 43 + }, + "mne/fiff/kit/kit.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4920.json b/mne-python/source/doc/sphinxext/prs/4920.json new file mode 100644 index 0000000000000000000000000000000000000000..f0cc067c5ed0b3d1eee18923feacb987d8ce5519 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4920.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bcbde3bcdc62e1e3e1bf967f2f79c51f9fc4168e", + "authors": [ + { + "n": "Larry Eisenman", + "e": "lneisenman@hotmail.com" + } + ], + "changes": { + "doc/faq.rst": { + "a": 12, + "d": 0 + }, + "doc/install_mne_python.rst": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4921.json b/mne-python/source/doc/sphinxext/prs/4921.json new file mode 100644 index 0000000000000000000000000000000000000000..ac1da051e7e708cf62f5b12ac347afa6e96ddd83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4921.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "06afcc8166f9304d25a72ab159e954542f0cc177", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 7, + "d": 2 + }, + "mne/chpi.py": { + "a": 36, + "d": 35 + }, + "mne/preprocessing/maxwell.py": { + "a": 12, + "d": 5 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 8, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4924.json b/mne-python/source/doc/sphinxext/prs/4924.json new file mode 100644 index 0000000000000000000000000000000000000000..075ed1e1d4d5abea2fa8c692eaf01fbf7d7ffd79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4924.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5c8f9a58c7572962659bf3cb63935c1808eaf196", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 24, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4925.json b/mne-python/source/doc/sphinxext/prs/4925.json new file mode 100644 index 0000000000000000000000000000000000000000..46bcf7a640027a4734da41e66182d90d16c92b54 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4925.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "107a887543447e3bf5d8f49b50378dd9cd6b87a8", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4927.json b/mne-python/source/doc/sphinxext/prs/4927.json new file mode 100644 index 0000000000000000000000000000000000000000..e8b9214e59408bfdaf95ef481fae4b6183efcb99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4927.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7572b8c65bef636b3a630aa960f7b8259b721862", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4929.json b/mne-python/source/doc/sphinxext/prs/4929.json new file mode 100644 index 0000000000000000000000000000000000000000..c611f6c0fc38b10e980aeb3b855e4863ac502722 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4929.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0db9155293dc1d402eb762bdea04748d030ba8df", + "authors": [ + { + "n": "Claire Braboszcz", + "e": "claire@guakamole.org" + } + ], + "changes": { + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/493.json b/mne-python/source/doc/sphinxext/prs/493.json new file mode 100644 index 0000000000000000000000000000000000000000..4a12b9b2114457be21ac88aca2440989dee8128b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/493.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6f098e5e25667b6a816380685cf25cf31ee68c9d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/pick.py": { + "a": 15, + "d": 4 + }, + "mne/viz.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4932.json b/mne-python/source/doc/sphinxext/prs/4932.json new file mode 100644 index 0000000000000000000000000000000000000000..fdab495173f345b0934e7685fa2b15665d35cec0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4932.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "52bef7c42b32114016321819656b331cda2092ba", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".travis.yml": { + "a": 12, + "d": 8 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 10, + "d": 10 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4933.json b/mne-python/source/doc/sphinxext/prs/4933.json new file mode 100644 index 0000000000000000000000000000000000000000..45fb89b26cf4829a1830d532362f2d70ecd93037 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4933.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "21357b8f5ca4e44a568c63ac5af0d9c8923a7f5d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 117, + "d": 84 + }, + "mne/defaults.py": { + "a": 5, + "d": 4 + }, + "mne/io/pick.py": { + "a": 15, + "d": 12 + }, + "mne/tests/test_cov.py": { + "a": 7, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 5 + }, + "mne/viz/misc.py": { + "a": 21, + "d": 20 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4934.json b/mne-python/source/doc/sphinxext/prs/4934.json new file mode 100644 index 0000000000000000000000000000000000000000..1f126f14bc9f2431a531314e447480fb899c6dda --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4934.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f60a6ba591e45eefbe400725e27ea8a22fe52a65", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 4, + "d": 8 + }, + "mne/tests/test_cov.py": { + "a": 5, + "d": 0 + }, + "tutorials/plot_compute_covariance.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4935.json b/mne-python/source/doc/sphinxext/prs/4935.json new file mode 100644 index 0000000000000000000000000000000000000000..66dbc2bbe38837fe972e247c3e4d89df9e3bbeb8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4935.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f8ec6d74afa43a1053aa560605af171633ac344f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4936.json b/mne-python/source/doc/sphinxext/prs/4936.json new file mode 100644 index 0000000000000000000000000000000000000000..cda52e35b21516f2642f00e96f45ed0d6d78a5cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4936.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "2b01a969f24531eb73f1695da1b6198c6df04d2e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 82, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 30, + "d": 7 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 55, + "d": 5 + }, + "mne/tests/test_annotations.py": { + "a": 172, + "d": 2 + }, + "mne/utils.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4937.json b/mne-python/source/doc/sphinxext/prs/4937.json new file mode 100644 index 0000000000000000000000000000000000000000..bb1293564606bb08e5912753fbe18cb702ec07ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4937.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "a78a355417bd46fc35b8650bf4a167d932242c83", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_coreg.py": { + "a": 19, + "d": 10 + }, + "mne/coreg.py": { + "a": 3, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 9, + "d": 2 + }, + "mne/gui/_coreg_gui.py": { + "a": 10, + "d": 3 + }, + "mne/gui/_file_traits.py": { + "a": 11, + "d": 12 + }, + "mne/gui/_viewer.py": { + "a": 57, + "d": 11 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 7, + "d": 0 + }, + "mne/surface.py": { + "a": 28, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4938.json b/mne-python/source/doc/sphinxext/prs/4938.json new file mode 100644 index 0000000000000000000000000000000000000000..96317eb543fe2300bf6552d2860fdee6cbcf5874 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4938.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bab48aba426fc40c23cea9a9bb713e604a19d057", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/gui/_coreg_gui.py": { + "a": 1, + "d": 0 + }, + "mne/gui/_viewer.py": { + "a": 21, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4942.json b/mne-python/source/doc/sphinxext/prs/4942.json new file mode 100644 index 0000000000000000000000000000000000000000..a1fb8b234c20e35f1724f5c85c0dbdc67bd27113 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4942.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "318f433510afb0b0995f95614568da6e03b922df", + "authors": [ + { + "n": "Nathalie", + "e": "nat.gayraud@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 16, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4945.json b/mne-python/source/doc/sphinxext/prs/4945.json new file mode 100644 index 0000000000000000000000000000000000000000..5e4e45097f5ce62aad52655d9b95963c17e9039c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4945.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "99f8f0400563c2c49934349b3cf0aaf8167ed0bc", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/utils.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4946.json b/mne-python/source/doc/sphinxext/prs/4946.json new file mode 100644 index 0000000000000000000000000000000000000000..fe4fb2e93649f6baa0b48d6c8720984bd4a484c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4946.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "c702c75158626fbe4dd6cdff0485037d7cf98f61", + "authors": [ + { + "n": "Katrin Leinweber", + "e": null + } + ], + "changes": { + "doc/faq.rst": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_rap_music.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_sensor_noise_level.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_dipole_orientations.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/495.json b/mne-python/source/doc/sphinxext/prs/495.json new file mode 100644 index 0000000000000000000000000000000000000000..ecf6e245546b2ce83de4bc9ca0136bb764b9ffe0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/495.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d4ea654245b2ff006d168e8ed807d7456f73edce", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4951.json b/mne-python/source/doc/sphinxext/prs/4951.json new file mode 100644 index 0000000000000000000000000000000000000000..2dacd539933eda1a24743007d11440e8afe30af2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4951.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f31066490555870f7a5d160880126a29220cae09", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 6, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 23, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4955.json b/mne-python/source/doc/sphinxext/prs/4955.json new file mode 100644 index 0000000000000000000000000000000000000000..34405126aa9c7aaaf0913ecb088689262c4377e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4955.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8ef95c9afacc9139922896f805395a3166bafb74", + "authors": [ + { + "n": "Maksymenko Kostiantyn", + "e": "makkostya@ukr.net" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 159, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 40, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4956.json b/mne-python/source/doc/sphinxext/prs/4956.json new file mode 100644 index 0000000000000000000000000000000000000000..9c1881dd1ae6f22d642f64a96133f55e6b13f027 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4956.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c783f3f667c99d0ae015407cad220251173d8439", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 24, + "d": 8 + }, + "mne/preprocessing/xdawn.py": { + "a": 11, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/496.json b/mne-python/source/doc/sphinxext/prs/496.json new file mode 100644 index 0000000000000000000000000000000000000000..5e0799c9f9c15392b7ed75cefd6411d4c4a19d15 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/496.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "43d48ca1b9659770a5b8c312c33d4df280c858e1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4960.json b/mne-python/source/doc/sphinxext/prs/4960.json new file mode 100644 index 0000000000000000000000000000000000000000..ec4fb1d2eaab67b63a3474f845a5626ecf2835cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4960.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6e36f2b2094c041462a849b2222ecb26676bd308", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4962.json b/mne-python/source/doc/sphinxext/prs/4962.json new file mode 100644 index 0000000000000000000000000000000000000000..1268d93418fccf22da231c8db2e0587588e08884 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4962.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e22d010c183371e8700a19285564270f7fb9d505", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 10, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4964.json b/mne-python/source/doc/sphinxext/prs/4964.json new file mode 100644 index 0000000000000000000000000000000000000000..a1d74352852cd7bceba6323be0f5ce78996548f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4964.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3bb9b7458cc5d9872da1ed094fd6d527e279cc65", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4965.json b/mne-python/source/doc/sphinxext/prs/4965.json new file mode 100644 index 0000000000000000000000000000000000000000..c8494061cac29262291944ffb9b283c8a2ef7aa8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4965.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a4d027096fe21a35606b6fd02dfab6b1e9521cf8", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_channel_epochs_image.py": { + "a": 2, + "d": 2 + }, + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4966.json b/mne-python/source/doc/sphinxext/prs/4966.json new file mode 100644 index 0000000000000000000000000000000000000000..c86f2246a6e37aa56031946232d69941c3f10be2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4966.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "24668f4e9434cc6f81f05f641b2973e56a5b6b1e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/forward/plot_decimate_head_surface.py": { + "a": 1, + "d": 2 + }, + "mne/bem.py": { + "a": 4, + "d": 4 + }, + "mne/commands/mne_coreg.py": { + "a": 18, + "d": 3 + }, + "mne/coreg.py": { + "a": 1, + "d": 3 + }, + "mne/gui/__init__.py": { + "a": 38, + "d": 6 + }, + "mne/gui/_coreg_gui.py": { + "a": 181, + "d": 106 + }, + "mne/gui/_fiducials_gui.py": { + "a": 33, + "d": 25 + }, + "mne/gui/_file_traits.py": { + "a": 19, + "d": 5 + }, + "mne/gui/_viewer.py": { + "a": 91, + "d": 22 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 34, + "d": 8 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 5, + "d": 5 + }, + "mne/utils.py": { + "a": 4, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4967.json b/mne-python/source/doc/sphinxext/prs/4967.json new file mode 100644 index 0000000000000000000000000000000000000000..b79761f423bca267f4860995d0c0231c5532dafa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4967.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fe067e403cf1d20e5ede87d274933b026284083a", + "authors": [ + { + "n": "Erik Hornberger", + "e": null + } + ], + "changes": { + "examples/inverse/plot_vector_mne_solution.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4969.json b/mne-python/source/doc/sphinxext/prs/4969.json new file mode 100644 index 0000000000000000000000000000000000000000..28d1d60babba25c97a9c77eb7fae12f1554ea45e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4969.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "239c83dfe0686084d1c96c945579dc8cc10e895c", + "authors": [ + { + "n": "Phillip Alday", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/stats/regression.py": { + "a": 5, + "d": 4 + }, + "mne/stats/tests/test_regression.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/497.json b/mne-python/source/doc/sphinxext/prs/497.json new file mode 100644 index 0000000000000000000000000000000000000000..219880e600213f17f088bfb642af4f8a77f328d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/497.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7ec2d7355fe2e47a455625ae5321403cb8afbf3c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4971.json b/mne-python/source/doc/sphinxext/prs/4971.json new file mode 100644 index 0000000000000000000000000000000000000000..70350c4c20a8545e214a42514c945b8d21bf051c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4971.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "c51705e1915835fe48fd37ff040edadfcae45853", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 11, + "d": 3 + }, + "mne/commands/mne_coreg.py": { + "a": 11, + "d": 2 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 1 + }, + "mne/coreg.py": { + "a": 76, + "d": 197 + }, + "mne/gui/__init__.py": { + "a": 36, + "d": 33 + }, + "mne/gui/_coreg_gui.py": { + "a": 1252, + "d": 828 + }, + "mne/gui/_fiducials_gui.py": { + "a": 96, + "d": 39 + }, + "mne/gui/_file_traits.py": { + "a": 40, + "d": 35 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 22, + "d": 5 + }, + "mne/gui/_marker_gui.py": { + "a": 27, + "d": 49 + }, + "mne/gui/_viewer.py": { + "a": 221, + "d": 131 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 57, + "d": 45 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 11, + "d": 11 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 34, + "d": 22 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 43, + "d": 28 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 6, + "d": 5 + }, + "mne/surface.py": { + "a": 73, + "d": 40 + }, + "mne/tests/test_coreg.py": { + "a": 4, + "d": 69 + }, + "mne/tests/test_report.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 11, + "d": 6 + }, + "mne/tests/test_utils.py": { + "a": 2, + "d": 1 + }, + "mne/transforms.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 24, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 15, + "d": 17 + }, + "mne/viz/tests/test_3d.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4973.json b/mne-python/source/doc/sphinxext/prs/4973.json new file mode 100644 index 0000000000000000000000000000000000000000..05d022e102c372f65cc812fc1e94c55530f76a6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4973.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d2850c8a11288348cb322bf18c0e188883c98cbe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_source_estimate.py": { + "a": 29, + "d": 1 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 9, + "d": 7 + }, + "tutorials/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 8, + "d": 4 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 13, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4974.json b/mne-python/source/doc/sphinxext/prs/4974.json new file mode 100644 index 0000000000000000000000000000000000000000..64c043833e4ed56852087f59721d5c866407761c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4974.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "da6d93195cdd3ce7e9a4859c0ff7cc2d259c85e8", + "authors": [ + { + "n": "Erik Hornberger", + "e": null + } + ], + "changes": { + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 1, + "d": 6 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4976.json b/mne-python/source/doc/sphinxext/prs/4976.json new file mode 100644 index 0000000000000000000000000000000000000000..627e6bdde50ca0be389b31e728b867c6bd2ec66b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4976.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f6e3fe522bff721114212066d9dcecd330efdfd1", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4978.json b/mne-python/source/doc/sphinxext/prs/4978.json new file mode 100644 index 0000000000000000000000000000000000000000..3b91989d6727d6bc7e8750668bbf0a94e734ba42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4978.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "cdffbc0f437f185bd7fbb59a53f70e29419a500b", + "authors": [ + { + "n": "Pierre Ablin", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "environment.yml": { + "a": 2, + "d": 0 + }, + "environment2.yml": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_ica_comparison.py": { + "a": 65, + "d": 0 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 0, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 54, + "d": 16 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 102, + "d": 47 + }, + "mne/utils.py": { + "a": 12, + "d": 13 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 19, + "d": 2 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 15, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/498.json b/mne-python/source/doc/sphinxext/prs/498.json new file mode 100644 index 0000000000000000000000000000000000000000..9a1b7f1b559d324e5fdb3d372c0ef14257603f73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/498.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "06e22e578dfbb1d6f16e6fc83488a748e35c186c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 1 + }, + "mne/viz.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4981.json b/mne-python/source/doc/sphinxext/prs/4981.json new file mode 100644 index 0000000000000000000000000000000000000000..62535e5d3b74ae0839fe3d772509517e4e113d4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4981.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "d0f8da7d0f53a7c596b78f22d09197637b9230aa", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 31, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 44, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 487, + "d": 47 + }, + "mne/viz/epochs.py": { + "a": 6, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 18, + "d": 52 + }, + "mne/viz/topo.py": { + "a": 8, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 29, + "d": 37 + }, + "mne/viz/utils.py": { + "a": 70, + "d": 0 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 14, + "d": 4 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4983.json b/mne-python/source/doc/sphinxext/prs/4983.json new file mode 100644 index 0000000000000000000000000000000000000000..dae13c95600cd2bb04b8f5dd15f3fd032b13aa56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4983.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a188859b57044fa158af05852bcce2870fabde91", + "authors": [ + { + "n": "Pierre Ablin", + "e": null + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4985.json b/mne-python/source/doc/sphinxext/prs/4985.json new file mode 100644 index 0000000000000000000000000000000000000000..eb50ae044782b4ea3ea7ea8c25c40a04aaf3c72c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4985.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5b0ab911c897ef2f6830b97f1b366b68ff5f94de", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/manual/c_reference.rst": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4986.json b/mne-python/source/doc/sphinxext/prs/4986.json new file mode 100644 index 0000000000000000000000000000000000000000..1062e2cb36ff0ac8ca9486cd066eb3d02bfeb081 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4986.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "10b9ab9ef352a5f2fca4e786046b3c7ca7cf1098", + "authors": [ + { + "n": "Dominik Krzeminski (dokato)", + "e": "raymon92@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4988.json b/mne-python/source/doc/sphinxext/prs/4988.json new file mode 100644 index 0000000000000000000000000000000000000000..a869605b213f3b242cdd872a9787df4aba302e9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4988.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5f53bd96450e138bf98605d0d90d8018651926d2", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/_static/institutions.png": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/499.json b/mne-python/source/doc/sphinxext/prs/499.json new file mode 100644 index 0000000000000000000000000000000000000000..8faec1617fa235863b96aa5ab64e4a65f53471d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/499.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e92672eb5837fe47a915d325ae53f2121796a8d0", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/__init__.py": { + "a": 2, + "d": 3 + }, + "mne/fiff/raw.py": { + "a": 210, + "d": 242 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4990.json b/mne-python/source/doc/sphinxext/prs/4990.json new file mode 100644 index 0000000000000000000000000000000000000000..93a96c92f49f71c28921a9242f971e06aba66891 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4990.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d77cc95b0cf56b1df5886c9ebc52261a55695331", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 13 + }, + "mne/io/tests/test_meas_info.py": { + "a": 111, + "d": 93 + }, + "mne/io/write.py": { + "a": 8, + "d": 12 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4993.json b/mne-python/source/doc/sphinxext/prs/4993.json new file mode 100644 index 0000000000000000000000000000000000000000..2f7edb3c0cf2372e0dc60e50484e1f08bf67e055 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4993.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c179f30b18e1290c7d9f2d1c730631dcc67e621c", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 7, + "d": 7 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 60, + "d": 17 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 132, + "d": 10 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 23, + "d": 10 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 69, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4995.json b/mne-python/source/doc/sphinxext/prs/4995.json new file mode 100644 index 0000000000000000000000000000000000000000..52c3a6f99883f865a2ab73ae6d3579c64136a66a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4995.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0afb4e2e8130a38fcb6d793629640d8865b557bc", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4996.json b/mne-python/source/doc/sphinxext/prs/4996.json new file mode 100644 index 0000000000000000000000000000000000000000..d41763138ee8b62ba3d698e29bf5337d584b3b9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4996.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f4eb3600c56b4ba6bd511eb947948e8b91e1ab96", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 7, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4997.json b/mne-python/source/doc/sphinxext/prs/4997.json new file mode 100644 index 0000000000000000000000000000000000000000..2b3b24945a31189b82cd3566b0e9dbfa97936ca5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4997.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4887a6c05204b0a03d7f92357f004a429bd712d6", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_file_traits.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/4999.json b/mne-python/source/doc/sphinxext/prs/4999.json new file mode 100644 index 0000000000000000000000000000000000000000..fff517150d20c081a2173b40afb30463c1fb43ff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/4999.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8270c1840ea821d8307ba2e16e3f334f8913f01f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5.json b/mne-python/source/doc/sphinxext/prs/5.json new file mode 100644 index 0000000000000000000000000000000000000000..5fa245a8588730de064b2805f249c51b37b67930 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5.json @@ -0,0 +1,531 @@ +{ + "merge_commit_sha": "ad5ca5f0c222c47deb3dc1d2632629de05e21976", + "authors": [ + { + "n": "Yaroslav Halchenko", + "e": null + } + ], + "changes": { + "AUTHORS.rst": { + "a": 0, + "d": 0 + }, + "LICENSE.txt": { + "a": 0, + "d": 0 + }, + "MANIFEST.in": { + "a": 0, + "d": 0 + }, + "README.rst": { + "a": 0, + "d": 0 + }, + "bin/mne_flash_bem_model.py": { + "a": 0, + "d": 0 + }, + "doc/Makefile": { + "a": 0, + "d": 0 + }, + "doc/source/conf.py": { + "a": 0, + "d": 0 + }, + "doc/source/getting_started.rst": { + "a": 0, + "d": 0 + }, + "doc/source/index.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/AppA.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/AppB.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/AppEULA.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/AppInstall.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/AppReleaseNotes.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/analyze.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/browse.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/convert.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/cookbook.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/forward.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/intro.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/list.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/matlab.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/MNE_preferences.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/adjust_alignment.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/adjust_lights.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/adjust_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/cont_hpi_data.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/dipole_list.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/dipole_parameters.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/dipoles_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/epoch_selector.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/field_mapping_pref.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/file_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/hardcopy_controls.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/help_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/image_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/label_list.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/labels_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/main_window.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/movie_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/mri_viewer.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/open_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/overlay_management.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/patch_selection_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/save_label_timecourse.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/scales_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/surface_controls.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/surface_selection_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/timecourse_manager.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/view_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/viewer.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/viewer_options.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/visualize_hpi.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_analyze/windows_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/adjust_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/adust_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/average_pref.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/channel_selection.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/file_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/filter_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/help_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/main.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/manage_averages_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/new_selection.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/new_ssp.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/open_dialog copy.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/open_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/process_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/process_menu2.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/scales_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/scales_dialog2.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/toolbar.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-0.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-1.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-10.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-11.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-12.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-13.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-14.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-15.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-16.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-17.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-2.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-3.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-4.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-5.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-6.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-7.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-8.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu-9.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/mne_browse_raw/windows_menu.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/morph.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/Averaging-flowchart.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/CoordinateSystems.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/Digitizer-example.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/Flowchart.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/HeadCS.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/cover.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/flat.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/morphed.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/neuromag.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/orig.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/proj-off-on.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/pics/title_page.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/reading.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/sampledata.rst": { + "a": 0, + "d": 0 + }, + "doc/source/manual/utilities.rst": { + "a": 0, + "d": 0 + }, + "doc/source/mne-python.rst": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/README.txt": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/docscrape.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/docscrape_sphinx.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/gen_rst.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/ipython_console_highlighting.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext/__init__.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext/docscrape.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext/docscrape_sphinx.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext/numpydoc.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext_old/__init__.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext_old/docscrape.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext_old/docscrape_sphinx.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/numpy_ext_old/numpydoc.py": { + "a": 0, + "d": 0 + }, + "doc/sphinxext/only_directives.py": { + "a": 0, + "d": 0 + }, + "examples/README.txt": { + "a": 0, + "d": 0 + }, + "examples/inverse/README.txt": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/README.txt": { + "a": 0, + "d": 0 + }, + "examples/stats/README.txt": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/README.txt": { + "a": 0, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 0, + "d": 0 + }, + "setup.cfg": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/50.json b/mne-python/source/doc/sphinxext/prs/50.json new file mode 100644 index 0000000000000000000000000000000000000000..8d6211662fa7cb90cc2cdea5b6ed5e81ea0e68e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/50.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "82f35f7b09f05bbab9af9f64994e9364cb21d57a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 7, + "d": 5 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 6, + "d": 6 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 7, + "d": 7 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 5, + "d": 6 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 3, + "d": 4 + }, + "mne/epochs.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 60, + "d": 30 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 15, + "d": 16 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 20, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/500.json b/mne-python/source/doc/sphinxext/prs/500.json new file mode 100644 index 0000000000000000000000000000000000000000..ffd5337b0c1591e7898ea536a50d7ac547d57283 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/500.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c42c1c0f1a680ab9ee1634f233b87ffcc09190c8", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 0 + }, + "mne/viz.py": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5000.json b/mne-python/source/doc/sphinxext/prs/5000.json new file mode 100644 index 0000000000000000000000000000000000000000..125da27059de5ea52fe443d7594922ab5d96e3a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5000.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "58e59df8aa99aab046eced1374c80eff290c4f2a", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 26, + "d": 7 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 11, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5001.json b/mne-python/source/doc/sphinxext/prs/5001.json new file mode 100644 index 0000000000000000000000000000000000000000..d211674a53ab55caed2d2039e10594b0275f6b88 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5001.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dc5698e8b6e89179412699ba0237b6b24100b3f5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/dipole.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 12, + "d": 0 + }, + "tutorials/plot_dipole_fit.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5004.json b/mne-python/source/doc/sphinxext/prs/5004.json new file mode 100644 index 0000000000000000000000000000000000000000..9cceb0449674b2c6183cc242e14e2cf938f304ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5004.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "eb444700eed3157a6d42c129c3ccd8dfbb0babbc", + "authors": [ + { + "n": "Oleh Kozynets", + "e": null + } + ], + "changes": { + ".gitignore": { + "a": 3, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/ctf/ctf.py": { + "a": 24, + "d": 4 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 36, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5006.json b/mne-python/source/doc/sphinxext/prs/5006.json new file mode 100644 index 0000000000000000000000000000000000000000..9d60fbe980a423c1172a5bdbe2b0c54c73bfeb4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5006.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ade69aa3650712a94b40c7395f548a2109690c49", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5007.json b/mne-python/source/doc/sphinxext/prs/5007.json new file mode 100644 index 0000000000000000000000000000000000000000..e15ec7b79bd730f2f52aa5c6c1e306c5efc87f4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5007.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "44ddced58a39977e2c7b6b0af8be59736f38dc0e", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/utils.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/501.json b/mne-python/source/doc/sphinxext/prs/501.json new file mode 100644 index 0000000000000000000000000000000000000000..81da1927031c76b77ff363c3c18cd7c2194d8ce5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/501.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a0d91e18cf71565c312001a4282c565465f09fd0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/kit/kit.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/kit/test/test_kit.py": { + "a": 6, + "d": 2 + }, + "mne/forward.py": { + "a": 4, + "d": 0 + }, + "mne/proj.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 8, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 17, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5010.json b/mne-python/source/doc/sphinxext/prs/5010.json new file mode 100644 index 0000000000000000000000000000000000000000..2dcc966b887aeb7f4262b46b8eea6ea7744b5048 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5010.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "36446621d6e001ddf21fe850bf8d42ad59035930", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/stats/plot_sensor_regression.py": { + "a": 14, + "d": 1 + }, + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 8, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 127, + "d": 26 + }, + "mne/viz/tests/test_evoked.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5011.json b/mne-python/source/doc/sphinxext/prs/5011.json new file mode 100644 index 0000000000000000000000000000000000000000..7a3ad7081b257591066703480d5ec51f55788639 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5011.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fdd38711177ffd74af93c6a9cd8f37e7cebfb823", + "authors": [ + { + "n": "Dominik Krzeminski (dokato)", + "e": "raymon92@gmail.com" + } + ], + "changes": { + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5012.json b/mne-python/source/doc/sphinxext/prs/5012.json new file mode 100644 index 0000000000000000000000000000000000000000..d230a598791394648ff94188a0be74becc59e191 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5012.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "7915893dc27aea13c5ca1b550da043bc6867468b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 14, + "d": 7 + }, + ".travis.yml": { + "a": 1, + "d": 1 + }, + "doc/advanced_setup.rst": { + "a": 7, + "d": 19 + }, + "doc/documentation.rst": { + "a": 1, + "d": 1 + }, + "doc/install_mne_python.rst": { + "a": 57, + "d": 59 + }, + "doc/manual/datasets_index.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 4 + }, + "environment.yml": { + "a": 10, + "d": 7 + }, + "mne/io/eximia/eximia.py": { + "a": 2, + "d": 2 + }, + "mne/utils.py": { + "a": 11, + "d": 0 + }, + "tutorials/plot_compute_covariance.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5016.json b/mne-python/source/doc/sphinxext/prs/5016.json new file mode 100644 index 0000000000000000000000000000000000000000..425af35508e9ac466e58c91eee8951e28c8306a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5016.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "265c6696904bdb70f8f2cbf4f3c8dd93f617d8f8", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/forward/_compute_forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5019.json b/mne-python/source/doc/sphinxext/prs/5019.json new file mode 100644 index 0000000000000000000000000000000000000000..f2a17ea8cb7d620fbdba5779be407ec454a7fc35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5019.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e85df44c0636ab0910e4de1de4f49700b68efcb5", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5021.json b/mne-python/source/doc/sphinxext/prs/5021.json new file mode 100644 index 0000000000000000000000000000000000000000..ed6cbe8f506e5efa3a1744d3b84df00eeb775885 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5021.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "96654288dd107afcba9ae5cede7c72daf8c66ef0", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 14, + "d": 6 + }, + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 11, + "d": 9 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 8, + "d": 10 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 6, + "d": 6 + }, + "examples/time_frequency/plot_compute_csd.py": { + "a": 88, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 57, + "d": 56 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 77, + "d": 86 + }, + "mne/time_frequency/__init__.py": { + "a": 4, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1302, + "d": 235 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 679, + "d": 172 + }, + "mne/viz/__init__.py": { + "a": 4, + "d": 3 + }, + "mne/viz/misc.py": { + "a": 119, + "d": 0 + }, + "mne/viz/tests/test_misc.py": { + "a": 18, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/503.json b/mne-python/source/doc/sphinxext/prs/503.json new file mode 100644 index 0000000000000000000000000000000000000000..90953715b9ad0b63ae761d4f3d270d924efdb164 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/503.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "eb9d1153cf9a0a14450577c8bf45ac741bb58b32", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/kit/constants.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/kit/kit.py": { + "a": 244, + "d": 132 + }, + "mne/fiff/kit/test/data/test.sqd": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/test/data/test_Ykgw.mat": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/test/data/test_bin.fif": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/test/data/test_py.fif": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/test/test_kit.py": { + "a": 71, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5031.json b/mne-python/source/doc/sphinxext/prs/5031.json new file mode 100644 index 0000000000000000000000000000000000000000..af58ec91000e17b480ee6d27e3940330cd2a77d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5031.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "11ae455f3e69949c92d0fc7f98204a807a7f924f", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 7, + "d": 3 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 83, + "d": 60 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5034.json b/mne-python/source/doc/sphinxext/prs/5034.json new file mode 100644 index 0000000000000000000000000000000000000000..e86b8bd3c51ab5bb9e55a9ab8edca30dedad5d28 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5034.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6b40ace7df1a24f94c7477abb057f77fba776dfc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/evoked.py": { + "a": 5, + "d": 5 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5035.json b/mne-python/source/doc/sphinxext/prs/5035.json new file mode 100644 index 0000000000000000000000000000000000000000..e71bc7bce615c5f6b2d375fedb65636ea6774e1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5035.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "3a109ba9d5cbf9a08912d1c34ba44ddce8329a58", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/manual/source_localization/inverse.rst": { + "a": 3, + "d": 4 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 1, + "d": 1 + }, + "mne/defaults.py": { + "a": 1, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 2 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 145, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 148, + "d": 58 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 7, + "d": 41 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 107, + "d": 16 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 48, + "d": 34 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 29, + "d": 46 + }, + "mne/viz/tests/test_3d.py": { + "a": 5, + "d": 1 + }, + "tutorials/plot_dipole_orientations.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 43, + "d": 39 + }, + "tutorials/plot_mne_solutions.py": { + "a": 112, + "d": 0 + }, + "tutorials/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 0, + "d": 2 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 1, + "d": 3 + }, + "tutorials/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 0, + "d": 2 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 6, + "d": 8 + }, + "tutorials/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 0, + "d": 2 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5036.json b/mne-python/source/doc/sphinxext/prs/5036.json new file mode 100644 index 0000000000000000000000000000000000000000..37c1c6d49c7d8f7b7b8130b1e26467164bcc9e50 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5036.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "59c116e0ec3718586f2a6664702a889e06e3873e", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 36, + "d": 17 + }, + "mne/time_frequency/tfr.py": { + "a": 17, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5037.json b/mne-python/source/doc/sphinxext/prs/5037.json new file mode 100644 index 0000000000000000000000000000000000000000..d0ac9490aa09fe4238b7f3ae53577e7cb932e101 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5037.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ce9a165fd57ceeb7dfa8d5b75f732d95260c61bf", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5039.json b/mne-python/source/doc/sphinxext/prs/5039.json new file mode 100644 index 0000000000000000000000000000000000000000..ef3a3acfdd8449ac1ce0e9754ef420478eb0e7e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5039.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bb8dd9aa2b1c387497c396382e38defdb4698c0e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/multitaper.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/504.json b/mne-python/source/doc/sphinxext/prs/504.json new file mode 100644 index 0000000000000000000000000000000000000000..1fd823d23555dd601ab074bc1a4aead3dc07c6c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/504.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2225ce9909964db387d962e55f6dfe2605334e84", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 98, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5040.json b/mne-python/source/doc/sphinxext/prs/5040.json new file mode 100644 index 0000000000000000000000000000000000000000..48483c1a86070fc2233d7d5c5e7ca18185941e97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5040.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3154e6dc07b0da3b6709172b0c0348dbed6ad21d", + "authors": [ + { + "n": "Tommy Clausner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/peak_finder.py": { + "a": 10, + "d": 4 + }, + "mne/preprocessing/tests/test_peak_finder.py": { + "a": 35, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5041.json b/mne-python/source/doc/sphinxext/prs/5041.json new file mode 100644 index 0000000000000000000000000000000000000000..3bde4ed4a1546d26f6916cefdeacfed4afe3841b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5041.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "9f01effada074332ef93750138fc9deabef51ca9", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 24, + "d": 12 + }, + "mne/viz/evoked.py": { + "a": 27, + "d": 17 + }, + "mne/viz/utils.py": { + "a": 13, + "d": 10 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 35, + "d": 38 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5042.json b/mne-python/source/doc/sphinxext/prs/5042.json new file mode 100644 index 0000000000000000000000000000000000000000..cef967528762ef554adfd015386455da8f18afe4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5042.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ce59305d4ffaa4c6ce2bccbf7b1fc0cd7713eda7", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5043.json b/mne-python/source/doc/sphinxext/prs/5043.json new file mode 100644 index 0000000000000000000000000000000000000000..217e62f2cd8dbea918ddd9c83d1cb2cb5e887cbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5043.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "2d0d5b95c65674f9dd5b90cd8af55467e7b04c93", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 5, + "d": 6 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 7 + }, + "mne/io/eximia/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/eximia/eximia.py": { + "a": 93, + "d": 0 + }, + "mne/io/eximia/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 45, + "d": 0 + }, + "mne/io/utils.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5044.json b/mne-python/source/doc/sphinxext/prs/5044.json new file mode 100644 index 0000000000000000000000000000000000000000..5c416b2f9bf9e45088979599146759ac8a06de3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5044.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "374d4b53e17a3aa54efb6628e443448f0c0ca9f5", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "mne/inverse_sparse/mxne_inverse.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5045.json b/mne-python/source/doc/sphinxext/prs/5045.json new file mode 100644 index 0000000000000000000000000000000000000000..bbdc8ca86c7cc1abe7c72ca9cfa336af22862b58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5045.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "caf0862daf01ddbd47e6f51065b9fbedbb6ba494", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 37, + "d": 19 + }, + "mne/io/meas_info.py": { + "a": 11, + "d": 2 + }, + "mne/tests/test_coreg.py": { + "a": 38, + "d": 33 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5048.json b/mne-python/source/doc/sphinxext/prs/5048.json new file mode 100644 index 0000000000000000000000000000000000000000..74631cde9cddd4908c79adb96b8e132833dba732 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5048.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4ef915d9af22199654a5763670b4789da35d28f8", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5051.json b/mne-python/source/doc/sphinxext/prs/5051.json new file mode 100644 index 0000000000000000000000000000000000000000..0e53c0a4b56ab970885392d847bfa511c34678a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5051.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9f6d4f4432eb218153d6b7da193d549a23739a3a", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5052.json b/mne-python/source/doc/sphinxext/prs/5052.json new file mode 100644 index 0000000000000000000000000000000000000000..7f07fa1b1c0d0be8f1adac8d3919c88aefaf7ec9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5052.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "9a7f28c52799044660a9844b6b115a2438cfaa7a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 3, + "d": 20 + }, + "mne/filter.py": { + "a": 5, + "d": 12 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 14, + "d": 29 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 16 + }, + "mne/time_frequency/csd.py": { + "a": 6, + "d": 55 + }, + "mne/time_frequency/multitaper.py": { + "a": 35, + "d": 18 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 89, + "d": 61 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5055.json b/mne-python/source/doc/sphinxext/prs/5055.json new file mode 100644 index 0000000000000000000000000000000000000000..24aa54645a0020407a6738abfa738a98c5d91cbe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5055.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "375c3b67f6b5b73d7be6ec5902c6911e0c87b504", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 23, + "d": 3 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 111, + "d": 65 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 23, + "d": 19 + }, + "mne/time_frequency/stft.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5056.json b/mne-python/source/doc/sphinxext/prs/5056.json new file mode 100644 index 0000000000000000000000000000000000000000..e074b417a675518b4a0408eab27519db7bb610bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5056.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b1448c0b08f8a9c9595b29f365c89b71503cb40a", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 40, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5057.json b/mne-python/source/doc/sphinxext/prs/5057.json new file mode 100644 index 0000000000000000000000000000000000000000..c8d11eed268b80d8097063da67d7a8f2a64da3b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5057.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3521f790656edbaf4a8b55e574f441f49078ff97", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/506.json b/mne-python/source/doc/sphinxext/prs/506.json new file mode 100644 index 0000000000000000000000000000000000000000..87bd98b03c633e39210521b761f8b6031335e93e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/506.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e4c7db52455d484c854e72d9e82a1677a1e10d5b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 121, + "d": 0 + }, + "mne/stats/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 400, + "d": 282 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 97, + "d": 81 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5062.json b/mne-python/source/doc/sphinxext/prs/5062.json new file mode 100644 index 0000000000000000000000000000000000000000..c6d1de067cc83b649345ff50802d671d9d5b6b97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5062.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2b5aa25eb4a48bbdaec02a2b7eb53075cba186d3", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/time_frequency/csd.py": { + "a": 9, + "d": 9 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5063.json b/mne-python/source/doc/sphinxext/prs/5063.json new file mode 100644 index 0000000000000000000000000000000000000000..f6a83b4e71b597b7b64531ac824c789338bbbff6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5063.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b130a04973548819ebcf6cd4500ce92d77e3d7e8", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 5 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5064.json b/mne-python/source/doc/sphinxext/prs/5064.json new file mode 100644 index 0000000000000000000000000000000000000000..bc52f36dbdc51c535e3ba064ce5a50ca1173184e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5064.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "33161b33187113c44850d7f7a648922370d90c2b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5065.json b/mne-python/source/doc/sphinxext/prs/5065.json new file mode 100644 index 0000000000000000000000000000000000000000..b9c6e76ec9c79ae6fb8979119dbd0f049c702d6c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5065.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6bd1280150f4ad312265cf233273a1c77d2b30cf", + "authors": [ + { + "n": "Nathalie", + "e": "nat.gayraud@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 9, + "d": 12 + }, + "mne/defaults.py": { + "a": 1, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 26, + "d": 11 + }, + "mne/simulation/tests/test_raw.py": { + "a": 19, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5066.json b/mne-python/source/doc/sphinxext/prs/5066.json new file mode 100644 index 0000000000000000000000000000000000000000..fe2eb044453d6ccb014c45e57127cfa7f472fb39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5066.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "aefa4343fa9ed3cde21309ea73ca471851ce0c77", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 4, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 0, + "d": 88 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 19, + "d": 24 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 3, + "d": 5 + }, + "mne/beamformer/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 767, + "d": 95 + }, + "mne/beamformer/_lcmv.py": { + "a": 93, + "d": 14 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 470, + "d": 118 + }, + "tutorials/plot_dics.py": { + "a": 309, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5068.json b/mne-python/source/doc/sphinxext/prs/5068.json new file mode 100644 index 0000000000000000000000000000000000000000..3fd51bcc92f9c18a54049f2d1a1ae7276bad3dc6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5068.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "55da4e49709ca6d5189cdceffba84c107b0ac517", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/stats/plot_sensor_regression.py": { + "a": 6, + "d": 6 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 44, + "d": 16 + }, + "mne/viz/evoked.py": { + "a": 17, + "d": 63 + }, + "mne/viz/topo.py": { + "a": 10, + "d": 66 + }, + "mne/viz/utils.py": { + "a": 138, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5069.json b/mne-python/source/doc/sphinxext/prs/5069.json new file mode 100644 index 0000000000000000000000000000000000000000..e20a6a343c2734c17d5388bbf685e5ba3fedb35d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5069.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c1a0dc908a9ced0f938b3873f28b8a5998f3fd24", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 36, + "d": 20 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 88, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/507.json b/mne-python/source/doc/sphinxext/prs/507.json new file mode 100644 index 0000000000000000000000000000000000000000..4ef16b2a9f8c80c693b6a3a5ba1d7a3c82a0e91c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/507.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2d62a90a6cd120338542c8460fee6333036c807e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/plot_megsim_data.py": { + "a": 53, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5070.json b/mne-python/source/doc/sphinxext/prs/5070.json new file mode 100644 index 0000000000000000000000000000000000000000..a29747f38304594198b7885970e53b350126960c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5070.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "76b6d1e0fb2443d365adde706d75d43e1ad56883", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 7, + "d": 5 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5071.json b/mne-python/source/doc/sphinxext/prs/5071.json new file mode 100644 index 0000000000000000000000000000000000000000..d31b0f013e1814deb0b24cf2fa860dce49c36e29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5071.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0444774dc5251465d157aaa7ccfa4b6feaf4c5aa", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "tutorials/plot_stats_cluster_erp.py": { + "a": 149, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5075.json b/mne-python/source/doc/sphinxext/prs/5075.json new file mode 100644 index 0000000000000000000000000000000000000000..d911d201d42c73d05e53b6b5567f5930fd85a671 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5075.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8e0a423d9b62268e2dc8e03cbb1810a3cab34391", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_multidict_reweighted_tfmxne.py": { + "a": 126, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 22, + "d": 8 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 313, + "d": 68 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 50, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5076.json b/mne-python/source/doc/sphinxext/prs/5076.json new file mode 100644 index 0000000000000000000000000000000000000000..2589ccca6bda59711f066fb2a162d8d397cceda9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5076.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0813968da09d87ae21d4e88163198c2c8ecc7e55", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/manual/decoding.rst": { + "a": 2, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 10, + "d": 8 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 19, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 4, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 8, + "d": 3 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5077.json b/mne-python/source/doc/sphinxext/prs/5077.json new file mode 100644 index 0000000000000000000000000000000000000000..7a48f95d81c88770c08fd84e8eac01c55a8ff42d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5077.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "09b8fd3bdfec0650b390bf7c3ae9271af5c8903b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/kit/constants.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5078.json b/mne-python/source/doc/sphinxext/prs/5078.json new file mode 100644 index 0000000000000000000000000000000000000000..a93342c8f4541cdb33a34ea9bbd204c9cf32b175 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5078.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cffd02d4065eeb23ca4798f4f674678103105096", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/egi/egimff.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5079.json b/mne-python/source/doc/sphinxext/prs/5079.json new file mode 100644 index 0000000000000000000000000000000000000000..c9bf6847c149c40ae753c4f457a7dbee361557dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5079.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "dba99f19e24ed3e59f72bb8eaff6174c104568ca", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/manual/cookbook.rst": { + "a": 2, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/filter.py": { + "a": 8, + "d": 4 + }, + "mne/io/base.py": { + "a": 4, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 15 + }, + "mne/viz/ica.py": { + "a": 12, + "d": 21 + }, + "mne/viz/misc.py": { + "a": 20, + "d": 23 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 5 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_artifacts_correction_filtering.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 5 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_artifacts_correction_ssp.py": { + "a": 0, + "d": 3 + }, + "tutorials/plot_artifacts_detection.py": { + "a": 11, + "d": 10 + }, + "tutorials/plot_background_filtering.py": { + "a": 5, + "d": 4 + }, + "tutorials/plot_visualize_raw.py": { + "a": 0, + "d": 2 + }, + "tutorials/plot_whitened.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/508.json b/mne-python/source/doc/sphinxext/prs/508.json new file mode 100644 index 0000000000000000000000000000000000000000..3450025a30a2fa6ed71b3b10eda4bc775788308b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/508.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0d219bf734b7837d5b3f00838eec6f818b48a709", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 13, + "d": 7 + }, + "mne/source_estimate.py": { + "a": 5, + "d": 3 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 0 + }, + "mne/viz.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5080.json b/mne-python/source/doc/sphinxext/prs/5080.json new file mode 100644 index 0000000000000000000000000000000000000000..022b74d3294cf3fe2a3991ac888b5d0d2cf0fb47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5080.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5364ec5b842ab879a8fc71cf120bcd599a86260c", + "authors": [ + { + "n": "Desislava Petkova", + "e": "desislavka@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5082.json b/mne-python/source/doc/sphinxext/prs/5082.json new file mode 100644 index 0000000000000000000000000000000000000000..ff87ed7f93d9249935500dab3a5971fe0cdb0856 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5082.json @@ -0,0 +1,303 @@ +{ + "merge_commit_sha": "a2dd739e3d0a1cf82433d5cb2a075ebe4b1cd647", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/tutorials/report.rst": { + "a": 1, + "d": 1 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 3, + "d": 2 + }, + "examples/datasets/plot_megsim_data.py": { + "a": 2, + "d": 2 + }, + "examples/datasets/plot_megsim_data_single_trial.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_unsupervised_spatial_filter.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_rap_music.py": { + "a": 4, + "d": 2 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/io/plot_elekta_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_objects_from_arrays.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_evoked.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_define_target_events.py": { + "a": 5, + "d": 9 + }, + "examples/preprocessing/plot_interpolate_bad_channels.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_metadata_query.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_movement_compensation.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 6, + "d": 3 + }, + "examples/preprocessing/plot_shift_evoked.py": { + "a": 3, + "d": 3 + }, + "examples/preprocessing/plot_virtual_evoked.py": { + "a": 4, + "d": 4 + }, + "examples/realtime/ftclient_rt_average.py": { + "a": 2, + "d": 1 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/plot_simulate_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_linear_regression_raw.py": { + "a": 2, + "d": 1 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 2, + "d": 1 + }, + "examples/stats/plot_sensor_regression.py": { + "a": 3, + "d": 2 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 2, + "d": 1 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 7, + "d": 5 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 8, + "d": 2 + }, + "mne/evoked.py": { + "a": 34, + "d": 26 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/stats/parametric.py": { + "a": 5, + "d": 1 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 9 + }, + "mne/viz/evoked.py": { + "a": 65, + "d": 85 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 43, + "d": 35 + }, + "mne/viz/tests/test_topo.py": { + "a": 12, + "d": 6 + }, + "mne/viz/tests/test_topomap.py": { + "a": 16, + "d": 10 + }, + "mne/viz/topomap.py": { + "a": 44, + "d": 13 + }, + "mne/viz/utils.py": { + "a": 18, + "d": 0 + }, + "tutorials/plot_artifacts_correction_maxwell_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_artifacts_correction_ssp.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_artifacts_detection.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_background_filtering.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 5, + "d": 5 + }, + "tutorials/plot_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_compute_covariance.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_creating_data_structures.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_dipole_fit.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_eeg_erp.py": { + "a": 12, + "d": 10 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_metadata_epochs.py": { + "a": 5, + "d": 3 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 4, + "d": 3 + }, + "tutorials/plot_object_epochs.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_object_evoked.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_phantom_4DBTi.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 4, + "d": 1 + }, + "tutorials/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_cluster_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 9, + "d": 9 + }, + "tutorials/plot_whitened.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5083.json b/mne-python/source/doc/sphinxext/prs/5083.json new file mode 100644 index 0000000000000000000000000000000000000000..a5e7741faa51d1b94d2333cfd28f19610b94d7ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5083.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e92335a2320a98782966b89abf82d0af96ffe5b5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 32, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 44, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5084.json b/mne-python/source/doc/sphinxext/prs/5084.json new file mode 100644 index 0000000000000000000000000000000000000000..0518bfc78ffdac527b729597ad6f91b416de7efa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5084.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "a11c4650afe01e71366ef44b89cffe4d7168f2bb", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 10, + "d": 12 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 9 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 2 + }, + "mne/utils.py": { + "a": 14, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 10, + "d": 15 + }, + "mne/viz/ica.py": { + "a": 122, + "d": 101 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5086.json b/mne-python/source/doc/sphinxext/prs/5086.json new file mode 100644 index 0000000000000000000000000000000000000000..03de6dd694efbb1f8ef6ae5730748524e9445c85 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5086.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "342c0598381d4a8d6743c4ab6d924f2d1da8e634", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 56, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 53, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/509.json b/mne-python/source/doc/sphinxext/prs/509.json new file mode 100644 index 0000000000000000000000000000000000000000..1d57c993031ee60e6521345c6daa0c681f50e8e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/509.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "bc9f87af581de15ffb321447250dc74ff560667e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/event.py": { + "a": 8, + "d": 3 + }, + "mne/fiff/kit/kit.py": { + "a": 3, + "d": 2 + }, + "mne/fiff/kit/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/data/sns.txt": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/data/test.sqd": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/data/test_Ykgw.mat": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/data/test_bin.fif": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/data/test_elp.txt": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/data/test_hsp.txt": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/data/test_mrk.sqd": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/test_kit.py": { + "a": 2, + "d": 2 + }, + "mne/forward.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 19, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5090.json b/mne-python/source/doc/sphinxext/prs/5090.json new file mode 100644 index 0000000000000000000000000000000000000000..1b5840f2620ab2a86a6d1ce4e72c2e8192c17866 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5090.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2318bf21f7011ef084c045f21e93b4ff752aed52", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "mne/evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5091.json b/mne-python/source/doc/sphinxext/prs/5091.json new file mode 100644 index 0000000000000000000000000000000000000000..d4019c87094856469b4dba2411c6ebd80bac55c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5091.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b97735d87a58df107192319f042e2875b99d8470", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/channels/data/layouts/KIT-AS-2008.lout": { + "a": 158, + "d": 0 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5092.json b/mne-python/source/doc/sphinxext/prs/5092.json new file mode 100644 index 0000000000000000000000000000000000000000..56875684218bb3e3bd77a5632b650830c2b5031a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5092.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "09a8da01cc1019eaa6a10dcdd4f0357805ec019d", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 6, + "d": 4 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 4 + }, + "mne/beamformer/_lcmv.py": { + "a": 8, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 65, + "d": 61 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5093.json b/mne-python/source/doc/sphinxext/prs/5093.json new file mode 100644 index 0000000000000000000000000000000000000000..f649cbc7a4d6d6b345624402fbaba951491bf26f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5093.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3b6302205bc13fd68f9be05f85b6a5f2b2f3990a", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "mne/evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5094.json b/mne-python/source/doc/sphinxext/prs/5094.json new file mode 100644 index 0000000000000000000000000000000000000000..0d443169b53432168e056a1fe1ee14e696912228 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5094.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f771b51939e8266adcb3838e0331f1d8dcd9ef25", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5095.json b/mne-python/source/doc/sphinxext/prs/5095.json new file mode 100644 index 0000000000000000000000000000000000000000..890f6154aba5416918439b4de77aba42cdeddd8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5095.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "613e1c6931edb6da151036595789dc9923988ac7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 7, + "d": 11 + }, + "mne/utils.py": { + "a": 10, + "d": 7 + }, + "mne/viz/tests/test_topomap.py": { + "a": 14, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5096.json b/mne-python/source/doc/sphinxext/prs/5096.json new file mode 100644 index 0000000000000000000000000000000000000000..71e18316b86d04dcf0be082d55e723632e6f8dd7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5096.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a5fa0ceb47cf95ec4ee2619e02a91ae49896dc5d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 28, + "d": 21 + }, + "mne/stats/tests/test_permutations.py": { + "a": 14, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5097.json b/mne-python/source/doc/sphinxext/prs/5097.json new file mode 100644 index 0000000000000000000000000000000000000000..f84910d5cfa0d3d06eba667da3aa26a672ed40ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5097.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "eae216d42d5975771059544b8d2487ee0c4ccc52", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 36, + "d": 38 + }, + "mne/viz/tests/test_raw.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5098.json b/mne-python/source/doc/sphinxext/prs/5098.json new file mode 100644 index 0000000000000000000000000000000000000000..8a73cc98ce0a8065cd8d38b38f8896fe62e230e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5098.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ed90f692d135535c094fa4cbc9e42eac9f2f7c78", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5099.json b/mne-python/source/doc/sphinxext/prs/5099.json new file mode 100644 index 0000000000000000000000000000000000000000..e04b8616d3740436f1b946265077abb426c91a7d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5099.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "16920f11e5a643221bd9f9807195f66234ea06a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 4, + "d": 0 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/51.json b/mne-python/source/doc/sphinxext/prs/51.json new file mode 100644 index 0000000000000000000000000000000000000000..79f28d34f4aa2e908cdd94f84ec92ce9c4a0030f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/51.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fea6bdc752b765bb447615b077b235a948b0f8e4", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/data/mne_analyze.sel": { + "a": 13, + "d": 0 + }, + "mne/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/pick.py": { + "a": 73, + "d": 0 + }, + "mne/fiff/tests/test_pick.py": { + "a": 15, + "d": 1 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/510.json b/mne-python/source/doc/sphinxext/prs/510.json new file mode 100644 index 0000000000000000000000000000000000000000..a9547f1888d12a07578c318ee10e2021b58fd589 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/510.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "758eb05a4bfa80e6fed13c017ea88fa67dc285ad", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5100.json b/mne-python/source/doc/sphinxext/prs/5100.json new file mode 100644 index 0000000000000000000000000000000000000000..a1d5fa8c6a1caf21682a9e04c698d90d35f50f19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5100.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6abe9fc70168e10500a1e35ef0145ff13383a8fb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 27, + "d": 15 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5101.json b/mne-python/source/doc/sphinxext/prs/5101.json new file mode 100644 index 0000000000000000000000000000000000000000..f14e61d80849fba02146748ca730545774be6dc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5101.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "edde36d378ff535e59088fcb13490045c90bb31c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5103.json b/mne-python/source/doc/sphinxext/prs/5103.json new file mode 100644 index 0000000000000000000000000000000000000000..03d04ce31f60336ce5d36933ddfff5e4fc1d1e6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5103.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7e3fd16ff7b3e10c2b370b7025286f89d09cb389", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5106.json b/mne-python/source/doc/sphinxext/prs/5106.json new file mode 100644 index 0000000000000000000000000000000000000000..92bf239c618477c483ac4c03cde64d19f1249b79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5106.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4630594e54f2d7e5be5f57092f649daabe1a9ccd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 2, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5107.json b/mne-python/source/doc/sphinxext/prs/5107.json new file mode 100644 index 0000000000000000000000000000000000000000..b0f5532b129714d615c29dc5b5015b8bcb930a77 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5107.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e138e9779dc5f003670effe30a62c3abd6a9e376", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "tutorials/plot_forward.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/511.json b/mne-python/source/doc/sphinxext/prs/511.json new file mode 100644 index 0000000000000000000000000000000000000000..68dc470f56007bf0af47fb9d57f54d2a3337091c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/511.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c9a955a2db7c612e2a3dd1f335e689b757282a9a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 37, + "d": 20 + }, + "mne/tests/test_source_estimate.py": { + "a": 35, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5113.json b/mne-python/source/doc/sphinxext/prs/5113.json new file mode 100644 index 0000000000000000000000000000000000000000..88c872edebf69d97bdac7e8d436b26dc95e46829 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5113.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "394b2d668999232f53d3da48ffc23cce00771edf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 4, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 0, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 3, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 5, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 7, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 4 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 5, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 0, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 5, + "d": 4 + }, + "mne/viz/tests/test_ica.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5114.json b/mne-python/source/doc/sphinxext/prs/5114.json new file mode 100644 index 0000000000000000000000000000000000000000..91d98d887d8e404dafc3c68cfb8ff45f1f74e842 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5114.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1a09859c6e5a7749b25a6c78403c0f02b225f0f5", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 65, + "d": 84 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5119.json b/mne-python/source/doc/sphinxext/prs/5119.json new file mode 100644 index 0000000000000000000000000000000000000000..b850fde19c0cf25fdd9151446d8e81b71d251b55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5119.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f5e3399ad6d0c163f3b86f002fd3c6fb687e6315", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 66, + "d": 23 + }, + "mne/viz/utils.py": { + "a": 38, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/512.json b/mne-python/source/doc/sphinxext/prs/512.json new file mode 100644 index 0000000000000000000000000000000000000000..19890759ff444ba4bfe41b2332ca2fd3435b50a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/512.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "44c11f764f42726e2df31e72509e681125056495", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 3, + "d": 2 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 4, + "d": 1 + }, + "mne/forward.py": { + "a": 5, + "d": 0 + }, + "mne/label.py": { + "a": 106, + "d": 96 + }, + "mne/minimum_norm/inverse.py": { + "a": 14, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 14, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 10, + "d": 4 + }, + "mne/proj.py": { + "a": 4, + "d": 3 + }, + "mne/simulation/source.py": { + "a": 0, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 156, + "d": 71 + }, + "mne/source_space.py": { + "a": 0, + "d": 3 + }, + "mne/tests/test_label.py": { + "a": 24, + "d": 10 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 9, + "d": 10 + }, + "mne/utils.py": { + "a": 20, + "d": 0 + }, + "mne/viz.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5120.json b/mne-python/source/doc/sphinxext/prs/5120.json new file mode 100644 index 0000000000000000000000000000000000000000..fde1ab1478b7cab6e68c2d75735de90233521822 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5120.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "13d6aadcd1b9e3d1524daadc5ba3318ce2658c93", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/csp.py": { + "a": 8, + "d": 8 + }, + "mne/decoding/ems.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/receptive_field.py": { + "a": 7, + "d": 7 + }, + "mne/decoding/search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 8, + "d": 8 + }, + "mne/preprocessing/xdawn.py": { + "a": 5, + "d": 5 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5121.json b/mne-python/source/doc/sphinxext/prs/5121.json new file mode 100644 index 0000000000000000000000000000000000000000..8b105b08134a4b9e2608b8a07ecf58bdffb9bbca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5121.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f68f4cfd351b48add9626af5993ab475a9c9af35", + "authors": [ + { + "n": "Jen Evans", + "e": null + } + ], + "changes": { + "mne/io/egi/events.py": { + "a": 5, + "d": 3 + }, + "mne/io/egi/general.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5125.json b/mne-python/source/doc/sphinxext/prs/5125.json new file mode 100644 index 0000000000000000000000000000000000000000..8615bd2f3982c90c8251ba252111829317ab6ff0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5125.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "21d35c8963e9c616813fae8237ee6d8c6387c2dc", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ssp.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 57, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5126.json b/mne-python/source/doc/sphinxext/prs/5126.json new file mode 100644 index 0000000000000000000000000000000000000000..01819fc1646d0f525a41ba09dba2965e08829678 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5126.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d91a41c1cc34af7337a2d00d3b036e7cc0666636", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 13, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5130.json b/mne-python/source/doc/sphinxext/prs/5130.json new file mode 100644 index 0000000000000000000000000000000000000000..0e7b4fb1a8b9b9299942e6fdc91948f97db98a59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5130.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "96d891774553a6a11fe4332937eab072510741e2", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5131.json b/mne-python/source/doc/sphinxext/prs/5131.json new file mode 100644 index 0000000000000000000000000000000000000000..894d4264d7605bc84c67b12f1c7445f75185f06d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5131.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "85fca344548cf6ee26cb4cf565188338569eb020", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils.py": { + "a": 33, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5132.json b/mne-python/source/doc/sphinxext/prs/5132.json new file mode 100644 index 0000000000000000000000000000000000000000..a7bc84535761ca53d9ea2b41804fe3d69c7a5e27 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5132.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "74ac2f37cd62acfe44c91a0633b15ccf47868150", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 159, + "d": 23 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 14, + "d": 51 + }, + "mne/tests/test_coreg.py": { + "a": 80, + "d": 6 + }, + "mne/tests/test_transforms.py": { + "a": 43, + "d": 10 + }, + "mne/transforms.py": { + "a": 44, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5133.json b/mne-python/source/doc/sphinxext/prs/5133.json new file mode 100644 index 0000000000000000000000000000000000000000..063281c54357f435d910e4561cfe87ed0326828c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5133.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "786945eab780a04f9ffb9ea44de6034c09ed7bb2", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 1, + "d": 26 + }, + "mne/cov.py": { + "a": 8, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 8, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 12, + "d": 5 + }, + "mne/io/meas_info.py": { + "a": 53, + "d": 0 + }, + "mne/io/pick.py": { + "a": 22, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 36, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 18, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 8, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 43, + "d": 14 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 45, + "d": 1 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 35, + "d": 1 + }, + "mne/utils.py": { + "a": 9, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5134.json b/mne-python/source/doc/sphinxext/prs/5134.json new file mode 100644 index 0000000000000000000000000000000000000000..2863c363b2dc74a0c01cb259dae9c25fd541c43c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5134.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b659764133b00ee3d47eefa1214a5b14125a9ed1", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 241, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 3, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 6, + "d": 237 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5135.json b/mne-python/source/doc/sphinxext/prs/5135.json new file mode 100644 index 0000000000000000000000000000000000000000..1f246272f07a61b69fa1765ad72237a4cfae73f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5135.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "65e7ce0d49855f636e932697de80565dacc033eb", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 0, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 189, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 8, + "d": 99 + }, + "mne/beamformer/_lcmv.py": { + "a": 9, + "d": 125 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5137.json b/mne-python/source/doc/sphinxext/prs/5137.json new file mode 100644 index 0000000000000000000000000000000000000000..045dd40211f2a513552ba21817790d43efc66ff9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5137.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1dc1502215a53385cda15c6c336fcc4341dc4d3b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 66, + "d": 81 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5139.json b/mne-python/source/doc/sphinxext/prs/5139.json new file mode 100644 index 0000000000000000000000000000000000000000..2821dbdebb32f88157d148d5c1bc020fc77a3407 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5139.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7212c5bfb10430fd8a80341d5e923cc1e497aee4", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 19, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/514.json b/mne-python/source/doc/sphinxext/prs/514.json new file mode 100644 index 0000000000000000000000000000000000000000..00c3fa9c05c9965f42944de12de5be8cd75c652d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/514.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "397eab931514dff656cb6de434a573480265173c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/evoked.py": { + "a": 9, + "d": 7 + }, + "mne/fiff/proj.py": { + "a": 5, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/forward.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 9, + "d": 4 + }, + "mne/utils.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5140.json b/mne-python/source/doc/sphinxext/prs/5140.json new file mode 100644 index 0000000000000000000000000000000000000000..936e0015d008eb909d33ee3cca445101a171dc9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5140.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "248fe7eeb45d596592b4dc3277a229afc7b55a3d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 59 + }, + "mne/viz/topomap.py": { + "a": 101, + "d": 78 + }, + "tutorials/plot_dipole_fit.py": { + "a": 3, + "d": 7 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5141.json b/mne-python/source/doc/sphinxext/prs/5141.json new file mode 100644 index 0000000000000000000000000000000000000000..5db59ba2e77828252dbc6d517d583d5e049cea19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5141.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "fea9566c5571f40781568c1f1a43f4c28757545f", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 47, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/externals/pymatreader/pymatreader.py": { + "a": 1, + "d": 177 + }, + "mne/externals/pymatreader/utils.py": { + "a": 230, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/fieldtrip/__init__.py": { + "a": 8, + "d": 0 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 174, + "d": 0 + }, + "mne/io/fieldtrip/tests/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 270, + "d": 0 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 225, + "d": 0 + }, + "mne/io/fieldtrip/utils.py": { + "a": 324, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5143.json b/mne-python/source/doc/sphinxext/prs/5143.json new file mode 100644 index 0000000000000000000000000000000000000000..25ba50d76668bd188e218cab26419e5c297dc176 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5143.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5ec3ac4a18838191047cbc2d67fabdd4f416767a", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/time_frequency/csd.py": { + "a": 6, + "d": 6 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5145.json b/mne-python/source/doc/sphinxext/prs/5145.json new file mode 100644 index 0000000000000000000000000000000000000000..c6f5396cb7a37322f5223dd64ef422a8128c118e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5145.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "8c07f6002034041b695f80e6248586453dca44bb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 17, + "d": 14 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 34, + "d": 20 + }, + "mne/preprocessing/xdawn.py": { + "a": 10, + "d": 12 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5146.json b/mne-python/source/doc/sphinxext/prs/5146.json new file mode 100644 index 0000000000000000000000000000000000000000..c99f31b4e20c27ff843ab63f19ce8191e017bc78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5146.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "12c4d7a77e272e186564927746d8fccbe21d525d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ssp.py": { + "a": 24, + "d": 7 + }, + "mne/proj.py": { + "a": 55, + "d": 9 + }, + "mne/rank.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_proj.py": { + "a": 43, + "d": 11 + }, + "mne/tests/test_rank.py": { + "a": 15, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5147.json b/mne-python/source/doc/sphinxext/prs/5147.json new file mode 100644 index 0000000000000000000000000000000000000000..a3880ecf0fae499a190bd8ef82877ab4f1df108c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5147.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a7d3c208813732321aff4a4d7c853bf149653604", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_source_estimate.py": { + "a": 12, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5150.json b/mne-python/source/doc/sphinxext/prs/5150.json new file mode 100644 index 0000000000000000000000000000000000000000..dfdff8810d25b92ab9f648b9e8f5dbadc6f17b7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5150.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b07993e017b33830c5f448e7e64a758aeb1853b0", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 7, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 14, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5153.json b/mne-python/source/doc/sphinxext/prs/5153.json new file mode 100644 index 0000000000000000000000000000000000000000..c7da6a4a43d946ea488b6145522f1457ad6ef16e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5153.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9865f9275f596443668a06e84e54f2e2c645bddb", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/preprocessing/peak_finder.py": { + "a": 13, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5155.json b/mne-python/source/doc/sphinxext/prs/5155.json new file mode 100644 index 0000000000000000000000000000000000000000..a9d0e0b4865f3fc98423913d824d2a38c60a859e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5155.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "8341e066a6b11b3e9fd9d804f37b7e2cb6f81b3a", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 9, + "d": 4 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 42, + "d": 27 + }, + "mne/preprocessing/eog.py": { + "a": 20, + "d": 4 + }, + "mne/preprocessing/ssp.py": { + "a": 67, + "d": 108 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 20, + "d": 7 + }, + "mne/preprocessing/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5156.json b/mne-python/source/doc/sphinxext/prs/5156.json new file mode 100644 index 0000000000000000000000000000000000000000..19c282e771b131c8c9975438627ce8c1d318d811 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5156.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7472168a9ba8d7b54c5fecd0ce104b18d9147a74", + "authors": [ + { + "n": "Juergen Dammers", + "e": "j.dammers@fz-juelich.de" + } + ], + "changes": { + "mne/fixes.py": { + "a": 13, + "d": 0 + }, + "mne/preprocessing/ctps_.py": { + "a": 7, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5157.json b/mne-python/source/doc/sphinxext/prs/5157.json new file mode 100644 index 0000000000000000000000000000000000000000..50a2df23ed9e84e36eabc0aceb1ef89bb04f2a0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5157.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "75a058902bd142b0f2f5c203fd7232f02ecabf60", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_viewer.py": { + "a": 10, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5160.json b/mne-python/source/doc/sphinxext/prs/5160.json new file mode 100644 index 0000000000000000000000000000000000000000..3809b4420a2a892039674b166db7051573d141bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5160.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c2ad41f27f1e92a46a4aa4794ec900b1a7b5b661", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 11, + "d": 4 + }, + "mne/io/edf/tests/data/test_bdf_stim_channel.bdf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 22, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5166.json b/mne-python/source/doc/sphinxext/prs/5166.json new file mode 100644 index 0000000000000000000000000000000000000000..2820c118c825ae29a39561cde91a59f16885fb71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5166.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "057026f9a38c63607401ca568790202cf57a08c8", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/annotations.py": { + "a": 2, + "d": 1 + }, + "mne/cov.py": { + "a": 4, + "d": 2 + }, + "mne/dipole.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 4, + "d": 2 + }, + "mne/event.py": { + "a": 4, + "d": 2 + }, + "mne/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 2 + }, + "mne/proj.py": { + "a": 4, + "d": 2 + }, + "mne/source_space.py": { + "a": 6, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/517.json b/mne-python/source/doc/sphinxext/prs/517.json new file mode 100644 index 0000000000000000000000000000000000000000..1600f1b05b82666047ac69d7cb0ea9f9cd6b11d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/517.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9f4c4ec215225d4baa15bf58843be3e8dee4f981", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 27, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5173.json b/mne-python/source/doc/sphinxext/prs/5173.json new file mode 100644 index 0000000000000000000000000000000000000000..21ced61c5fe82c2e84ea6f79d9ede1df435fed17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5173.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9b132399497f5a982691e2f41bb30de02e925475", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5174.json b/mne-python/source/doc/sphinxext/prs/5174.json new file mode 100644 index 0000000000000000000000000000000000000000..bb4807314482db135fbd9654b8ca54635fcb6813 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5174.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "ca35ce9923ae9dc02fe55d7b321f71337903a81b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/documentation.rst": { + "a": 0, + "d": 1 + }, + "doc/install_mne_python.rst": { + "a": 31, + "d": 27 + }, + "doc/manual/time_frequency.rst": { + "a": 0, + "d": 4 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 5, + "d": 5 + }, + "tutorials/plot_dics.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5175.json b/mne-python/source/doc/sphinxext/prs/5175.json new file mode 100644 index 0000000000000000000000000000000000000000..a97e03c4e3f26f3f5b54ef2501d39acb17213f53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5175.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e17d46935861447a5112085dd010c33a865f835b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/navbar.html": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5177.json b/mne-python/source/doc/sphinxext/prs/5177.json new file mode 100644 index 0000000000000000000000000000000000000000..ecf9ce0bf190adfc5d49b584d79dfa8083492ede --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5177.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "a3e412691c8cdd734514084e1b421311b662f809", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 0, + "d": 6 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 306 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 304 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 183 + }, + "mne/dipole.py": { + "a": 2, + "d": 3 + }, + "mne/evoked.py": { + "a": 7, + "d": 7 + }, + "mne/forward/forward.py": { + "a": 5, + "d": 17 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 12, + "d": 40 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 17 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 18, + "d": 26 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/ssp.py": { + "a": 4, + "d": 19 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 0, + "d": 13 + }, + "mne/simulation/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 9 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 151 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 19, + "d": 343 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 12, + "d": 17 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 3 + }, + "mne/viz/tests/test_topomap.py": { + "a": 0, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 8, + "d": 23 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5178.json b/mne-python/source/doc/sphinxext/prs/5178.json new file mode 100644 index 0000000000000000000000000000000000000000..26faebe4a8ca2bf17d6120bae2aaf34a6d7b306b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5178.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d7ec5c8e0cb5957fe6249d72f9e0437c4777b9da", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 9, + "d": 4 + }, + "mne/simulation/raw.py": { + "a": 62, + "d": 25 + }, + "mne/simulation/tests/test_raw.py": { + "a": 49, + "d": 37 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5179.json b/mne-python/source/doc/sphinxext/prs/5179.json new file mode 100644 index 0000000000000000000000000000000000000000..b9192b18d1ca2eb65d344fdc78fdfd0202c4eef2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5179.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "eefc3fdfecf238249e1b0d8544c6fa5c53090c03", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 11, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5183.json b/mne-python/source/doc/sphinxext/prs/5183.json new file mode 100644 index 0000000000000000000000000000000000000000..a4e2e18ebbf9a20664a5dfd59bab0e375819dffc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5183.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bd35715c21098a15b8bf3450a5ea2d6091e3477c", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 9, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5184.json b/mne-python/source/doc/sphinxext/prs/5184.json new file mode 100644 index 0000000000000000000000000000000000000000..76cc0d139c88fe590b7c2df5d7c04f0c0ed4ba78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5184.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a9a8027690d79f3995e8da884fefd01c4c1eb07d", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/time_frequency/csd.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5186.json b/mne-python/source/doc/sphinxext/prs/5186.json new file mode 100644 index 0000000000000000000000000000000000000000..14faa68589b3cb06c0d22f7db7461a2c7cc9452f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5186.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "f21b843da8fc85de53ce188ab6c7cec7be5795d8", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 2, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 9 + }, + "mne/viz/misc.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_utils.py": { + "a": 9, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 47, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5188.json b/mne-python/source/doc/sphinxext/prs/5188.json new file mode 100644 index 0000000000000000000000000000000000000000..49311db0491dabd7aeff038fa32a428407c42ffd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5188.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9fefdf4ade454c0c0a40a4d8e4677c37fbef56e6", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/advanced_setup.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5189.json b/mne-python/source/doc/sphinxext/prs/5189.json new file mode 100644 index 0000000000000000000000000000000000000000..bc2d92351f51f410c58606d2b79d03713849ff47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5189.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "563867c2fb3560f06fae786e43b5e2dd8fb3cf60", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5193.json b/mne-python/source/doc/sphinxext/prs/5193.json new file mode 100644 index 0000000000000000000000000000000000000000..e2c1bf205c3e00aeba09106d94313a7967ced5fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5193.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "5cafa0f4287ae02fb2beafa557c0f70db8b7a1ed", + "authors": [ + { + "n": "Henrich Kolkhorst", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 8, + "d": 0 + }, + "examples/realtime/ftclient_rt_average.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/ftclient_rt_compute_psd.py": { + "a": 5, + "d": 0 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/rt_feedback_client.py": { + "a": 9, + "d": 52 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 10, + "d": 6 + }, + "mne/epochs.py": { + "a": 51, + "d": 7 + }, + "mne/realtime/epochs.py": { + "a": 159, + "d": 18 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 11, + "d": 7 + }, + "mne/realtime/mockclient.py": { + "a": 6, + "d": 2 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 116, + "d": 33 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 226, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5194.json b/mne-python/source/doc/sphinxext/prs/5194.json new file mode 100644 index 0000000000000000000000000000000000000000..525cd3e6fbe64f5cf6b61eedf8c66e372e70c160 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5194.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a277bdbe145a461d864c36555b2fff286619b009", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/base.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 29, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5196.json b/mne-python/source/doc/sphinxext/prs/5196.json new file mode 100644 index 0000000000000000000000000000000000000000..c7da71ac2c4f6cecf69dea44d32f57f1520ae2af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5196.json @@ -0,0 +1,291 @@ +{ + "merge_commit_sha": "04c6256dfa87fb6d58689d383f29b9de731e378c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 0, + "d": 1 + }, + "MANIFEST.in": { + "a": 1, + "d": 1 + }, + "Makefile": { + "a": 7, + "d": 4 + }, + "dictionary.txt": { + "a": 0, + "d": 4499 + }, + "doc/install_mne_c.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/appendix/c_release_notes.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/c_reference.rst": { + "a": 12, + "d": 12 + }, + "doc/manual/cookbook.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/gui/analyze.rst": { + "a": 3, + "d": 3 + }, + "doc/manual/gui/browse.rst": { + "a": 5, + "d": 5 + }, + "doc/manual/preprocessing/maxwell.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/time_frequency.rst": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 11, + "d": 9 + }, + "examples/io/README.txt": { + "a": 2, + "d": 2 + }, + "ignore_words.txt": { + "a": 11, + "d": 0 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 3, + "d": 3 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_viewer.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 3 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 3, + "d": 3 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/data/test_empty_room.cov": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 7 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 5 + }, + "mne/parallel.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 6 + }, + "mne/utils.py": { + "a": 2, + "d": 2 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_maxwell_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_rejection.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_background_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_background_statistics.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_configuration.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_eeg_erp.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5197.json b/mne-python/source/doc/sphinxext/prs/5197.json new file mode 100644 index 0000000000000000000000000000000000000000..7705fcf1c5c525f1ab6016d0484536cd7f923bf5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5197.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "71cea4bf9a2ced60503272c1570b6993aa38df35", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/_eloreta.py": { + "a": 4, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5198.json b/mne-python/source/doc/sphinxext/prs/5198.json new file mode 100644 index 0000000000000000000000000000000000000000..e07b7ea8f73490f332e44fd55bc6b91c991a2698 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5198.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "c38073288f2c32fea37c5d7c3a1bb5bcabc175f9", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 9, + "d": 11 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 11 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 4, + "d": 5 + }, + "mne/decoding/search_light.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 2, + "d": 3 + }, + "mne/epochs.py": { + "a": 2, + "d": 5 + }, + "mne/evoked.py": { + "a": 3, + "d": 4 + }, + "mne/filter.py": { + "a": 2, + "d": 3 + }, + "mne/io/base.py": { + "a": 1, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/reference.py": { + "a": 3, + "d": 7 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 5 + }, + "mne/utils.py": { + "a": 72, + "d": 61 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5199.json b/mne-python/source/doc/sphinxext/prs/5199.json new file mode 100644 index 0000000000000000000000000000000000000000..e57497603d76c5ee0e7c2c0e78daab12c65959b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5199.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "37003533a68353b46b8900789dc99989350f0162", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/52.json b/mne-python/source/doc/sphinxext/prs/52.json new file mode 100644 index 0000000000000000000000000000000000000000..7a2d415d3a077d48b2829888f7716cac968be74e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/52.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "23de0270b725b1eea298798d9ac927f807831f11", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/pick.py": { + "a": 14, + "d": 75 + }, + "mne/fiff/tests/test_pick.py": { + "a": 1, + "d": 14 + }, + "mne/selection.py": { + "a": 99, + "d": 0 + }, + "mne/tests/test_selection.py": { + "a": 29, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/520.json b/mne-python/source/doc/sphinxext/prs/520.json new file mode 100644 index 0000000000000000000000000000000000000000..59aee4797735680184fd1322f89d0c9bcfbf1b4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/520.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a4adae4fcf8862689afaef2b0e5c9a80bbcfa3ea", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/megsim/megsim.py": { + "a": 11, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5203.json b/mne-python/source/doc/sphinxext/prs/5203.json new file mode 100644 index 0000000000000000000000000000000000000000..aee26c7b1ae8c9596de6aa239d947063e4ddd3f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5203.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dc8fab44153c7e01cfc339dc65e17de538d391ec", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "tutorials/plot_stats_cluster_erp.py": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5209.json b/mne-python/source/doc/sphinxext/prs/5209.json new file mode 100644 index 0000000000000000000000000000000000000000..222034a2480c93c0ec506e6ed46dd0753645b459 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5209.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "60070e37959ad01125fa21f14f7479c07bf45dd5", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 7, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/521.json b/mne-python/source/doc/sphinxext/prs/521.json new file mode 100644 index 0000000000000000000000000000000000000000..eb165f587509b63009027ef2d191e8edf208d3c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/521.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e4bbd64e756fb94270746db6041220b7f6faa252", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 10, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5211.json b/mne-python/source/doc/sphinxext/prs/5211.json new file mode 100644 index 0000000000000000000000000000000000000000..15ff79c939e732b1a2a4838e3736386cc86ee5a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5211.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d2802775539f5200bda637a6419794bf9d107990", + "authors": [ + { + "n": "Sara Sommariva", + "e": "sommariva@dima.unige.it" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 16, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5213.json b/mne-python/source/doc/sphinxext/prs/5213.json new file mode 100644 index 0000000000000000000000000000000000000000..d7866936e3587da787df32d43997853df44d663b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5213.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ad438f61f0ba4c455acfeffa6068b7c4a7858aeb", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "mne/externals/pymatreader/__init__.py": { + "a": 28, + "d": 0 + }, + "mne/externals/pymatreader/pymatreader.py": { + "a": 202, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5215.json b/mne-python/source/doc/sphinxext/prs/5215.json new file mode 100644 index 0000000000000000000000000000000000000000..714abc447873013f147d5b190cf6d9342d8ac0d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5215.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9e266dd7001a05ef86aa56ecc39ede205ee12cb2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 6 + }, + "mne/tests/test_proj.py": { + "a": 34, + "d": 27 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5216.json b/mne-python/source/doc/sphinxext/prs/5216.json new file mode 100644 index 0000000000000000000000000000000000000000..71ab2fcb897eddd1daf84e2d196b5442a250684b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5216.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "424e768ea43fac9e4f9adf920ee30d0d5adaf949", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "ignore_words.txt": { + "a": 2, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 1 + }, + "tutorials/plot_background_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_dipole_fit.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5219.json b/mne-python/source/doc/sphinxext/prs/5219.json new file mode 100644 index 0000000000000000000000000000000000000000..766b6d051d6d63f146bf0ada9efc091864be9036 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5219.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "197a8418672a8e69c65a1940e45da4966decf45f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 5, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 64, + "d": 25 + }, + "mne/parallel.py": { + "a": 66, + "d": 69 + }, + "mne/stats/cluster_level.py": { + "a": 13, + "d": 22 + }, + "mne/tests/test_utils.py": { + "a": 70, + "d": 1 + }, + "mne/utils.py": { + "a": 88, + "d": 8 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 5, + "d": 4 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/522.json b/mne-python/source/doc/sphinxext/prs/522.json new file mode 100644 index 0000000000000000000000000000000000000000..c03d6e78d0e763e1ad3378f8ac12f9e45aa50877 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/522.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e014f859ebd7db68d0a41158711c9e06fb87c867", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/plot_megsim_data_single_trial.py": { + "a": 35, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5220.json b/mne-python/source/doc/sphinxext/prs/5220.json new file mode 100644 index 0000000000000000000000000000000000000000..21efdeadf67b9c1d152d36fc805363d37b2f3623 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5220.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "430d0d4b0603e785308f827f39a53be1dcf55e48", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 55, + "d": 6 + }, + "mne/tests/test_source_estimate.py": { + "a": 20, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5225.json b/mne-python/source/doc/sphinxext/prs/5225.json new file mode 100644 index 0000000000000000000000000000000000000000..648c556c41021ac07dc5c6d1b93347c6858dde4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5225.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "8efbe5c3034ca6fc2c96b033ab63e42081788b38", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/forward/_field_interpolation.py": { + "a": 4, + "d": 1 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 16, + "d": 1 + }, + "mne/stats/tests/test_parametric.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 7, + "d": 8 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 12, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 14, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 11, + "d": 0 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5227.json b/mne-python/source/doc/sphinxext/prs/5227.json new file mode 100644 index 0000000000000000000000000000000000000000..5d4aba807d710a06b4a7220a049f8d96eb7d80d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5227.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9ceb57d6d1cea1f7944265940d5f4005d6cf7ef7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5228.json b/mne-python/source/doc/sphinxext/prs/5228.json new file mode 100644 index 0000000000000000000000000000000000000000..9fefc8071f54661444ebd5c9e7b7f3f347ff2675 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5228.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "45898628a416691a89a8d48ca38860298cfb58fc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/data/montages/mgh70.elc": { + "a": 5, + "d": 5 + }, + "mne/channels/tests/test_montage.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5230.json b/mne-python/source/doc/sphinxext/prs/5230.json new file mode 100644 index 0000000000000000000000000000000000000000..661ed334d54d07c5fd27d998c16ec4e31b60a9d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5230.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "05a09f7e563bb8ef96aef9b64e206af216d8d909", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 6, + "d": 5 + }, + "doc/_static/reset-syntax.css": { + "a": 12, + "d": 0 + }, + "doc/_static/style.css": { + "a": 4, + "d": 64 + }, + "doc/_templates/layout.html": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/gen_commands.py": { + "a": 12, + "d": 11 + }, + "examples/stats/plot_sensor_regression.py": { + "a": 4, + "d": 5 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 3 + }, + "tutorials/plot_configuration.py": { + "a": 1, + "d": 0 + }, + "tutorials/plot_dics.py": { + "a": 0, + "d": 3 + }, + "tutorials/plot_introduction.py": { + "a": 7, + "d": 7 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5231.json b/mne-python/source/doc/sphinxext/prs/5231.json new file mode 100644 index 0000000000000000000000000000000000000000..7aa0fdbcba9c06edebe58cbc893fc2676bb265af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5231.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "a6ac948a4331d4560ad60dc4ae18eca3704bd576", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 0, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 8, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 3, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 85, + "d": 21 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 44, + "d": 30 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5232.json b/mne-python/source/doc/sphinxext/prs/5232.json new file mode 100644 index 0000000000000000000000000000000000000000..ceb573bd1b7e331f18c1e775126268f29296fa4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5232.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bbda6a575b488cf92d30402a5d766afae38f80cb", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/filter.py": { + "a": 27, + "d": 15 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5233.json b/mne-python/source/doc/sphinxext/prs/5233.json new file mode 100644 index 0000000000000000000000000000000000000000..7e048f634d5d40d85a80dfd42bd970847f0184c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5233.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "005f4ab7fc0fc8b145172b72831b2262622b4075", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/filter.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5239.json b/mne-python/source/doc/sphinxext/prs/5239.json new file mode 100644 index 0000000000000000000000000000000000000000..d399797212f8cc081b37ca79494111cb4097b877 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5239.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "62828d56ff129a271433cf673e417eec596ffabc", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "tutorials/plot_background_filtering.py": { + "a": 102, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/524.json b/mne-python/source/doc/sphinxext/prs/524.json new file mode 100644 index 0000000000000000000000000000000000000000..e398c139ee8cbf5765907fdb9522ad36aef526d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/524.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0c5263ae172a61998a41e2b26f7188c49c347905", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 55, + "d": 35 + }, + "mne/tests/test_source_space.py": { + "a": 10, + "d": 15 + }, + "mne/utils.py": { + "a": 46, + "d": 30 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5241.json b/mne-python/source/doc/sphinxext/prs/5241.json new file mode 100644 index 0000000000000000000000000000000000000000..cd72b1b6aa8770cd7a97d088b2c9f378c55c6371 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5241.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a62497855cfd2703e5043ff8def72f4a9d7b97f3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5242.json b/mne-python/source/doc/sphinxext/prs/5242.json new file mode 100644 index 0000000000000000000000000000000000000000..9921b23ebc60f5ac38f2b0c5f74bf1cec607783d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5242.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d8182e75d1be580e25556bb5e405b0657fc016fb", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5243.json b/mne-python/source/doc/sphinxext/prs/5243.json new file mode 100644 index 0000000000000000000000000000000000000000..bd8fa43426092a12321fe7fb25d13d724f748b9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5243.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "eaad1b8e22a1ffeddcafaaf5473e0a181b9abcc9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 5, + "d": 8 + }, + "mne/tests/test_filter.py": { + "a": 53, + "d": 50 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5245.json b/mne-python/source/doc/sphinxext/prs/5245.json new file mode 100644 index 0000000000000000000000000000000000000000..e874f3c2aa244b96853e2b57761599281d089de8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5245.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "819d8933eeabddf5cc40632467e5518605d1e4a7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5246.json b/mne-python/source/doc/sphinxext/prs/5246.json new file mode 100644 index 0000000000000000000000000000000000000000..dfeca03c8f650bc3018f85918d4795f508712b8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5246.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "55689e29123dc55b6ed2259b0ece375fa7db20f5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_vector_mne_solution.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 10, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5247.json b/mne-python/source/doc/sphinxext/prs/5247.json new file mode 100644 index 0000000000000000000000000000000000000000..6c9b39d72c8246105af501da8345ac75e1acaead --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5247.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "76c3662d7d036505522bc00c0a7de80d28aa75fa", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5250.json b/mne-python/source/doc/sphinxext/prs/5250.json new file mode 100644 index 0000000000000000000000000000000000000000..82beabd4d9e6bf38cd05f18a16dc045f846b1bee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5250.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "14ab6b69b4738007cafca005300df57139089857", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 2, + "d": 1 + }, + "mne/tests/test_import_nesting.py": { + "a": 13, + "d": 11 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5251.json b/mne-python/source/doc/sphinxext/prs/5251.json new file mode 100644 index 0000000000000000000000000000000000000000..edee23d95acc8c446c07e9ce8dd18f558be965f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5251.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "039cb1bf52770019bd48ac028795af0861792fa2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 34, + "d": 15 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "environment2.yml": { + "a": 0, + "d": 44 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 3, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 17, + "d": 18 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 4, + "d": 5 + }, + "mne/io/ctf/res4.py": { + "a": 40, + "d": 51 + }, + "mne/label.py": { + "a": 5, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 9, + "d": 6 + }, + "mne/tests/test_cov.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_dipole.py": { + "a": 8, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 1, + "d": 8 + }, + "mne/utils.py": { + "a": 4, + "d": 47 + }, + "requirements.txt": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5252.json b/mne-python/source/doc/sphinxext/prs/5252.json new file mode 100644 index 0000000000000000000000000000000000000000..f6f636a898034b78dcc4e0803371abe9f83f7ffd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5252.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b784a40919ba957f48009447df9cfb5327ac84e4", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 6, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5254.json b/mne-python/source/doc/sphinxext/prs/5254.json new file mode 100644 index 0000000000000000000000000000000000000000..cd93c6df018da3960d06daa41c1324bf743d0043 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5254.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "34676a287b6af246df6b59fc9cce26ba7309fa54", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 4, + "d": 8 + }, + "mne/channels/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 59, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 29, + "d": 2 + }, + "tutorials/plot_stats_cluster_erp.py": { + "a": 6, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5255.json b/mne-python/source/doc/sphinxext/prs/5255.json new file mode 100644 index 0000000000000000000000000000000000000000..2087e29a7623a329797484d410018e4efe76d332 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5255.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "1aea53a5e7b67ed82fa78c3fcf80d954bdf99a23", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 1, + "d": 0 + }, + "mne/io/ctf/ctf.py": { + "a": 6, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 35, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 9, + "d": 7 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 5, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 4, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5256.json b/mne-python/source/doc/sphinxext/prs/5256.json new file mode 100644 index 0000000000000000000000000000000000000000..503d671a86b94b787a3a446f363bf978e5897fbf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5256.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ab4571a83c4e5d5de0dcb2e9346f809f113dd619", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/install_mne_python.rst": { + "a": 38, + "d": 51 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "environment2.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5257.json b/mne-python/source/doc/sphinxext/prs/5257.json new file mode 100644 index 0000000000000000000000000000000000000000..8927b5ffb70aea1f2db0284c6b4edf50d9d048bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5257.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a10845b59dcf537818e0192fbce3cef8f858dba3", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 39, + "d": 8 + }, + "mne/viz/tests/test_evoked.py": { + "a": 8, + "d": 0 + }, + "tutorials/plot_stats_cluster_erp.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5259.json b/mne-python/source/doc/sphinxext/prs/5259.json new file mode 100644 index 0000000000000000000000000000000000000000..ae380c578bfaca0726a84bf9d74a8080f281a66b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5259.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6614a5be4c573bf06d2a2b19bd77d3b9adb5a84d", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 4 + }, + "mne/bem.py": { + "a": 4, + "d": 5 + }, + "mne/event.py": { + "a": 10, + "d": 16 + }, + "mne/evoked.py": { + "a": 1, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 10, + "d": 22 + }, + "mne/tests/test_event.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/526.json b/mne-python/source/doc/sphinxext/prs/526.json new file mode 100644 index 0000000000000000000000000000000000000000..043c764b46909c2a4c4f413cc9e9b790d8da0930 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/526.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e74cdf0e9c04da7a14e87750c9697fb075bbcd21", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 54, + "d": 21 + }, + "mne/tests/test_source_space.py": { + "a": 20, + "d": 3 + }, + "mne/utils.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5261.json b/mne-python/source/doc/sphinxext/prs/5261.json new file mode 100644 index 0000000000000000000000000000000000000000..19af8fe91402244691b188027755f62deac23e96 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5261.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "68084ccfd8114d496bd64d28bb4f10bf792239c9", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 74, + "d": 5 + }, + "mne/viz/tests/test_evoked.py": { + "a": 9, + "d": 0 + }, + "tutorials/plot_stats_cluster_erp.py": { + "a": 14, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5262.json b/mne-python/source/doc/sphinxext/prs/5262.json new file mode 100644 index 0000000000000000000000000000000000000000..88a57235e0556fedefb0d91e34bdc897e2e40a21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5262.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "106f567b2b3a16411e585373cb064d90d7928945", + "authors": [ + { + "n": "Manu Sutela", + "e": null + } + ], + "changes": { + "mne/stats/parametric.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5263.json b/mne-python/source/doc/sphinxext/prs/5263.json new file mode 100644 index 0000000000000000000000000000000000000000..3751d7a86924f190b02f325d9b06c4501e45e653 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5263.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9af6fa422d7c5240540e4a5c020afd65f8d8f3d1", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 27, + "d": 6 + }, + "mne/viz/tests/test_topo.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5268.json b/mne-python/source/doc/sphinxext/prs/5268.json new file mode 100644 index 0000000000000000000000000000000000000000..acb8a697ea55c6e88242c2437a1cc17e3bdd1561 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5268.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "da1d32978b6033dd89609f12af291ed619264c7d", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 2, + "d": 5 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 2, + "d": 5 + }, + "mne/utils.py": { + "a": 4, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 20, + "d": 29 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5270.json b/mne-python/source/doc/sphinxext/prs/5270.json new file mode 100644 index 0000000000000000000000000000000000000000..cdca6da45a8e221d78fe2d496bdafca077279a07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5270.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5fb47e0e75e8923a67c47715a3d030f74bf8a369", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 18, + "d": 12 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 73, + "d": 4 + }, + "mne/utils.py": { + "a": 29, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5271.json b/mne-python/source/doc/sphinxext/prs/5271.json new file mode 100644 index 0000000000000000000000000000000000000000..c841ecb1fd20a424d3a675c6531845aa997d4680 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5271.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e1b441460b3eb426dea9a90e1d250da18a169f12", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 12, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5272.json b/mne-python/source/doc/sphinxext/prs/5272.json new file mode 100644 index 0000000000000000000000000000000000000000..704824ca5148279735451e6e7334d997e8a2a722 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5272.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3022961cef39b79b750bd0c64660324cb2d08a73", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 17, + "d": 16 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 0 + }, + "mne/data/helmets/ARTEMIS123.fif.gz": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5274.json b/mne-python/source/doc/sphinxext/prs/5274.json new file mode 100644 index 0000000000000000000000000000000000000000..e685e91530a85fc077fca067578d3d949c40d3df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5274.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5c30a008cec4fe694b05294e4011460c41b206be", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 0 + }, + "mne/io/brainvision/tests/data/test.vmrk": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 17, + "d": 4 + }, + "mne/io/utils.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5278.json b/mne-python/source/doc/sphinxext/prs/5278.json new file mode 100644 index 0000000000000000000000000000000000000000..8b2fa23d06b1dea52e2e7c2e7fe3ea3da52ef883 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5278.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "23054e2567fbfb3c8679523d364dbe7191dfbe1e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/528.json b/mne-python/source/doc/sphinxext/prs/528.json new file mode 100644 index 0000000000000000000000000000000000000000..7d91348cd1aa6b84fa1ac4247677c55e44c34a49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/528.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "85b0cf97f340a0ec2d98bfa03595c75d0cb46b9b", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 39, + "d": 6 + }, + "mne/tests/test_source_estimate.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5285.json b/mne-python/source/doc/sphinxext/prs/5285.json new file mode 100644 index 0000000000000000000000000000000000000000..08864e7a8e151f30a0f8eb87fb070595e8ae9fcf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5285.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "76294a7b2e370fb207081e3887b1d7b246238eed", + "authors": [ + { + "n": "Steven Bethard", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 56, + "d": 54 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/529.json b/mne-python/source/doc/sphinxext/prs/529.json new file mode 100644 index 0000000000000000000000000000000000000000..45ef6712b09af1300862a7510d601351f3869d48 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/529.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d4b634b283083ceff8a260da967bfcb41d05944f", + "authors": [ + { + "n": "Mainak", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "bin/mne_compute_proj_eog.py": { + "a": 59, + "d": 53 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/eog.py": { + "a": 34, + "d": 14 + }, + "mne/preprocessing/ssp.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5291.json b/mne-python/source/doc/sphinxext/prs/5291.json new file mode 100644 index 0000000000000000000000000000000000000000..53a56884e4558e8ecfdc0bd6d184d298fa7af87f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5291.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ef08c9ef02e198b443e40364f502b192ee14f70e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 6 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 2, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 13, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5295.json b/mne-python/source/doc/sphinxext/prs/5295.json new file mode 100644 index 0000000000000000000000000000000000000000..79eb0a09d49757a47b306cfaa9ac263b331550ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5295.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e4c995b4517089f7f105a9afb997f1b05a4e3653", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5298.json b/mne-python/source/doc/sphinxext/prs/5298.json new file mode 100644 index 0000000000000000000000000000000000000000..a8efef5dc3f1d2dba1912a3d35f86312720e33cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5298.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a44caaa3a5b89318cadd11c7f0a27301f727cf24", + "authors": [ + { + "n": "Tristan Stenner", + "e": null + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/brainvision/tests/data/test_nV.vhdr": { + "a": 151, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/53.json b/mne-python/source/doc/sphinxext/prs/53.json new file mode 100644 index 0000000000000000000000000000000000000000..50757ef64773a6f7e6ccb955c0ac82fd92f2efe6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/53.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "8b8de0c0285175e18ea680899a581381b70bf615", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 73, + "d": 0 + }, + "mne/beamformer/__init__.py": { + "a": 4, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 114, + "d": 0 + }, + "mne/beamformer/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 66, + "d": 0 + }, + "mne/cov.py": { + "a": 44, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5301.json b/mne-python/source/doc/sphinxext/prs/5301.json new file mode 100644 index 0000000000000000000000000000000000000000..dfe27e55bb09c846bb508562240b34d5d0d851e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5301.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8b5e48aae28efb6d0f09a57244dcced7c041396d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "CODE_OF_CONDUCT.md": { + "a": 46, + "d": 0 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5304.json b/mne-python/source/doc/sphinxext/prs/5304.json new file mode 100644 index 0000000000000000000000000000000000000000..ed12032124cc181a8e98b8b9010984659298981d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5304.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "96bd8661599558024cdcd9edcc5eb0e12919722b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "README.rst": { + "a": 19, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5306.json b/mne-python/source/doc/sphinxext/prs/5306.json new file mode 100644 index 0000000000000000000000000000000000000000..5d44fb71e843005700add4236f84d75e637db8fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5306.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8812f9309ce2e9b345461684c7a8c190db111cc2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_source_space.py": { + "a": 60, + "d": 59 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5308.json b/mne-python/source/doc/sphinxext/prs/5308.json new file mode 100644 index 0000000000000000000000000000000000000000..290fe43c47263f9703f1ab378f1452a4e19e46ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5308.json @@ -0,0 +1,515 @@ +{ + "merge_commit_sha": "1442cc4b8cd6e30595bf34dae2972093a7ac584c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 5, + "d": 5 + }, + "Makefile": { + "a": 2, + "d": 3 + }, + "environment.yml": { + "a": 0, + "d": 1 + }, + "environment2.yml": { + "a": 0, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 44, + "d": 46 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 14, + "d": 16 + }, + "mne/channels/tests/test_channels.py": { + "a": 64, + "d": 65 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 15, + "d": 16 + }, + "mne/channels/tests/test_layout.py": { + "a": 38, + "d": 38 + }, + "mne/channels/tests/test_montage.py": { + "a": 30, + "d": 30 + }, + "mne/commands/tests/test_commands.py": { + "a": 15, + "d": 15 + }, + "mne/connectivity/tests/test_effective.py": { + "a": 5, + "d": 6 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 36, + "d": 39 + }, + "mne/connectivity/tests/test_utils.py": { + "a": 6, + "d": 7 + }, + "mne/datasets/sample/sample.py": { + "a": 8, + "d": 4 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 8, + "d": 4 + }, + "mne/datasets/testing/_testing.py": { + "a": 8, + "d": 4 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 8, + "d": 9 + }, + "mne/decoding/tests/test_base.py": { + "a": 14, + "d": 13 + }, + "mne/decoding/tests/test_csp.py": { + "a": 37, + "d": 38 + }, + "mne/decoding/tests/test_ems.py": { + "a": 7, + "d": 7 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 25, + "d": 26 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 27, + "d": 25 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 4, + "d": 2 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 22, + "d": 22 + }, + "mne/fixes.py": { + "a": 0, + "d": 78 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 21, + "d": 21 + }, + "mne/forward/tests/test_forward.py": { + "a": 48, + "d": 54 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 17, + "d": 19 + }, + "mne/gui/_marker_gui.py": { + "a": 2, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 26, + "d": 26 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 11, + "d": 11 + }, + "mne/inverse_sparse/tests/test_mxne_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 3, + "d": 3 + }, + "mne/io/array/tests/test_array.py": { + "a": 7, + "d": 7 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 3, + "d": 4 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 14, + "d": 14 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 19, + "d": 19 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 5, + "d": 6 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 16, + "d": 18 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 2, + "d": 6 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 14, + "d": 12 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 23, + "d": 22 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 7, + "d": 7 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 64, + "d": 67 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 5, + "d": 5 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 13, + "d": 15 + }, + "mne/io/tests/test_apply_function.py": { + "a": 11, + "d": 10 + }, + "mne/io/tests/test_compensator.py": { + "a": 4, + "d": 4 + }, + "mne/io/tests/test_pick.py": { + "a": 15, + "d": 15 + }, + "mne/io/tests/test_proc_history.py": { + "a": 20, + "d": 19 + }, + "mne/io/tests/test_raw.py": { + "a": 11, + "d": 11 + }, + "mne/io/tests/test_reference.py": { + "a": 44, + "d": 44 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 46, + "d": 49 + }, + "mne/minimum_norm/tests/test_psf_ctf.py": { + "a": 6, + "d": 9 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 19, + "d": 20 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 3, + "d": 4 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 83, + "d": 84 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 3, + "d": 7 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 48, + "d": 49 + }, + "mne/preprocessing/tests/test_peak_finder.py": { + "a": 7, + "d": 5 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 10, + "d": 11 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 8, + "d": 7 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 3, + "d": 3 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 2, + "d": 4 + }, + "mne/realtime/tests/test_stim_client_server.py": { + "a": 8, + "d": 10 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 4, + "d": 5 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 8, + "d": 7 + }, + "mne/simulation/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/tests/test_source.py": { + "a": 23, + "d": 20 + }, + "mne/source_space.py": { + "a": 15, + "d": 16 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 33, + "d": 32 + }, + "mne/stats/tests/test_multi_comp.py": { + "a": 14, + "d": 15 + }, + "mne/stats/tests/test_parametric.py": { + "a": 22, + "d": 20 + }, + "mne/stats/tests/test_permutations.py": { + "a": 1, + "d": 0 + }, + "mne/stats/tests/test_regression.py": { + "a": 16, + "d": 17 + }, + "mne/tests/common.py": { + "a": 17, + "d": 19 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_bem.py": { + "a": 38, + "d": 39 + }, + "mne/tests/test_chpi.py": { + "a": 29, + "d": 32 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 44, + "d": 50 + }, + "mne/tests/test_defaults.py": { + "a": 7, + "d": 9 + }, + "mne/tests/test_dipole.py": { + "a": 28, + "d": 28 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 7, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 212, + "d": 214 + }, + "mne/tests/test_event.py": { + "a": 35, + "d": 35 + }, + "mne/tests/test_evoked.py": { + "a": 68, + "d": 70 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_fixes.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 69, + "d": 68 + }, + "mne/tests/test_line_endings.py": { + "a": 6, + "d": 5 + }, + "mne/tests/test_misc.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_proj.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_report.py": { + "a": 32, + "d": 32 + }, + "mne/tests/test_selection.py": { + "a": 9, + "d": 8 + }, + "mne/tests/test_source_estimate.py": { + "a": 81, + "d": 84 + }, + "mne/tests/test_surface.py": { + "a": 9, + "d": 9 + }, + "mne/tests/test_transforms.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_utils.py": { + "a": 141, + "d": 134 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 0, + "d": 1 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 23, + "d": 25 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 13, + "d": 12 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 65, + "d": 65 + }, + "mne/viz/tests/test_3d.py": { + "a": 32, + "d": 34 + }, + "mne/viz/tests/test_circle.py": { + "a": 4, + "d": 5 + }, + "mne/viz/tests/test_epochs.py": { + "a": 11, + "d": 12 + }, + "mne/viz/tests/test_evoked.py": { + "a": 22, + "d": 22 + }, + "mne/viz/tests/test_ica.py": { + "a": 20, + "d": 20 + }, + "mne/viz/tests/test_misc.py": { + "a": 7, + "d": 8 + }, + "mne/viz/tests/test_montage.py": { + "a": 2, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 17, + "d": 16 + }, + "mne/viz/tests/test_topo.py": { + "a": 16, + "d": 17 + }, + "mne/viz/tests/test_topomap.py": { + "a": 42, + "d": 43 + }, + "mne/viz/tests/test_utils.py": { + "a": 27, + "d": 25 + }, + "setup.cfg": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5312.json b/mne-python/source/doc/sphinxext/prs/5312.json new file mode 100644 index 0000000000000000000000000000000000000000..89e0dfd1cb30d7cb0faa616d337bb5bf59566cb2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5312.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "de86b1d8f2c9cae6b5f98567dd1516457b0ed648", + "authors": [ + { + "n": null, + "e": "erkkahe@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 23, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 8, + "d": 6 + }, + "tutorials/plot_sensors_time_frequency.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5313.json b/mne-python/source/doc/sphinxext/prs/5313.json new file mode 100644 index 0000000000000000000000000000000000000000..83b8aba03e2aafbe7a800f10456958c54a1843a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5313.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d6f2ee670ea89d9d0d43c5d4d3aca58ee0881154", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 6 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 42, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5314.json b/mne-python/source/doc/sphinxext/prs/5314.json new file mode 100644 index 0000000000000000000000000000000000000000..9390df1c00c19271a620c066eb226e95c3ba5844 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5314.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f49022a6cf0a3d9617d7050838f09bff3e2757fd", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels/data/layouts/KIT-160.lay": { + "a": 162, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 4, + "d": 1 + }, + "mne/io/kit/constants.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5316.json b/mne-python/source/doc/sphinxext/prs/5316.json new file mode 100644 index 0000000000000000000000000000000000000000..a84c4100ed183f8d6e1064ab9afeb8dd52d693b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5316.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1f70786a6bcef53568585d4984acbb9eab5034a8", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/tutorial_links.inc": { + "a": 4, + "d": 0 + }, + "tutorials/plot_background_statistics.py": { + "a": 128, + "d": 121 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5317.json b/mne-python/source/doc/sphinxext/prs/5317.json new file mode 100644 index 0000000000000000000000000000000000000000..be446856d9f90fa5b9156efec24c63807da22d44 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5317.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e60cc0ab0be847a47f61f6f1f31a9ff7e961e611", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 10, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 30, + "d": 14 + }, + "mne/beamformer/_lcmv.py": { + "a": 32, + "d": 23 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 27, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 17, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 11, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5319.json b/mne-python/source/doc/sphinxext/prs/5319.json new file mode 100644 index 0000000000000000000000000000000000000000..7062a75810a78433ef5d6a3ab97b591bbbffbd2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5319.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9d47022eaa39d5ade0654dc9bc3f0b3eb3485a7c", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5321.json b/mne-python/source/doc/sphinxext/prs/5321.json new file mode 100644 index 0000000000000000000000000000000000000000..ff1b01af148875c630c42ff6d46b0dfc670a9d1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5321.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f2fcc5aec08893f2b29502992d8a283b83027b15", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 8, + "d": 4 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5322.json b/mne-python/source/doc/sphinxext/prs/5322.json new file mode 100644 index 0000000000000000000000000000000000000000..82dabe7293668b35bbd45877785df17dd4f39402 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5322.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1264cc711bbce07276c3fc2b79d6b64514e53d28", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5326.json b/mne-python/source/doc/sphinxext/prs/5326.json new file mode 100644 index 0000000000000000000000000000000000000000..e6391d5f112b3b5d1d99abdebf74c5ca5adef82a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5326.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "16feb1ae3ce490d6accbc078c83c0f737fe9ca9e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/known_projects.inc": { + "a": 3, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "mne/annotations.py": { + "a": 3, + "d": 1 + }, + "mne/externals/pymatreader/pymatreader.py": { + "a": 18, + "d": 7 + }, + "mne/io/eeglab/eeglab.py": { + "a": 73, + "d": 55 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 99, + "d": 60 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5327.json b/mne-python/source/doc/sphinxext/prs/5327.json new file mode 100644 index 0000000000000000000000000000000000000000..b27f5819388c90b48a74766d0df20b1782447718 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5327.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4df573c93fc76f42bd4bdb0568e96961e22fe7b6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5328.json b/mne-python/source/doc/sphinxext/prs/5328.json new file mode 100644 index 0000000000000000000000000000000000000000..974d4e782e3305af4344cc974b3ac61a6c2a0168 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5328.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "001e5c84dca33e10d8e72558b87e33c10bfbe65a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 39, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5329.json b/mne-python/source/doc/sphinxext/prs/5329.json new file mode 100644 index 0000000000000000000000000000000000000000..dd6f8933d2dcb048bc25c118361a21d95d8b8bc3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5329.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "0706ad95fa091003f29bd1d568a17324453bb297", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 15, + "d": 33 + }, + "mne/fixes.py": { + "a": 27, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 11, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 309, + "d": 11 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 43, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/533.json b/mne-python/source/doc/sphinxext/prs/533.json new file mode 100644 index 0000000000000000000000000000000000000000..4482982855f21d0106fe68c76e47d971161332be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/533.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7605647251572c12d4f873007e8bee1cac49d3cb", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5331.json b/mne-python/source/doc/sphinxext/prs/5331.json new file mode 100644 index 0000000000000000000000000000000000000000..9f9179cffccabfecf2e422ac35559fe9d372ea53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5331.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9b3883d4af81b239d6270e517f8296ec84b85f87", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 7, + "d": 16 + }, + "mne/io/reference.py": { + "a": 0, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5332.json b/mne-python/source/doc/sphinxext/prs/5332.json new file mode 100644 index 0000000000000000000000000000000000000000..06ae2f1c1d8ffffd37266b7e47860d2b0fcc58b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5332.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "8da6623382c2eca6aad1e431d6da51400b0bc6ec", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 5, + "d": 5 + }, + "mne/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/externals/decorator.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 4 + }, + "mne/forward/_make_forward.py": { + "a": 5, + "d": 5 + }, + "mne/io/constants.py": { + "a": 26, + "d": 23 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 3 + }, + "mne/io/tag.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_constants.py": { + "a": 252, + "d": 0 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 3, + "d": 4 + }, + "mne/utils.py": { + "a": 14, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/534.json b/mne-python/source/doc/sphinxext/prs/534.json new file mode 100644 index 0000000000000000000000000000000000000000..25c7459025125f315c21f42ca66279719deaa256 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/534.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c95036a4a8c00443f52d6490b4e6986bae6d4bbe", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 6, + "d": 2 + }, + "mne/viz.py": { + "a": 16, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5340.json b/mne-python/source/doc/sphinxext/prs/5340.json new file mode 100644 index 0000000000000000000000000000000000000000..44b469d968d98ab7edbff82d44c8f7aaea98a3e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5340.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "575164175b9c0faa506b6e87b25762c1e238403d", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "CONTRIBUTING.md": { + "a": 13, + "d": 0 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5341.json b/mne-python/source/doc/sphinxext/prs/5341.json new file mode 100644 index 0000000000000000000000000000000000000000..99328e401259e06e1e2176e44fc1eb848d450552 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5341.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1cedd32abe7b9ae1817e455788f664d2faa13e6c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 4, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5343.json b/mne-python/source/doc/sphinxext/prs/5343.json new file mode 100644 index 0000000000000000000000000000000000000000..a2e075f4d98e20e248e49645bec908e0a3a6be1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5343.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "a75970522eaf8ea2da04085024b32669adfb43dc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/array/array.py": { + "a": 0, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 10, + "d": 5 + }, + "mne/io/brainvision/brainvision.py": { + "a": 0, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 0, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 5, + "d": 3 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 2, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 0, + "d": 3 + }, + "mne/io/egi/egi.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 0, + "d": 1 + }, + "mne/io/eximia/eximia.py": { + "a": 0, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 8, + "d": 8 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 5 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 0, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5344.json b/mne-python/source/doc/sphinxext/prs/5344.json new file mode 100644 index 0000000000000000000000000000000000000000..63a09b7791b026d08b09d6f4ea9f7235a82adf4c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5344.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "512fafcf40faf457bb9eae577290df7e9ec34fc9", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 27, + "d": 26 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5348.json b/mne-python/source/doc/sphinxext/prs/5348.json new file mode 100644 index 0000000000000000000000000000000000000000..9e0e2473783fc4f7ebd413d44a9fe7b513498530 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5348.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5389a456c400701c7bc7c7f8452fb4e6c53a11ae", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 26 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 8, + "d": 7 + }, + "mne/tests/common.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5350.json b/mne-python/source/doc/sphinxext/prs/5350.json new file mode 100644 index 0000000000000000000000000000000000000000..9d31a47d4a8e7c4514ac889070c22c3bbc69e996 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5350.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8bccec4977f0fd75e2652572d81c9cee2e959525", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 57 + }, + "mne/tests/test_utils.py": { + "a": 19, + "d": 1 + }, + "mne/utils.py": { + "a": 73, + "d": 0 + }, + "tutorials/plot_background_filtering.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5352.json b/mne-python/source/doc/sphinxext/prs/5352.json new file mode 100644 index 0000000000000000000000000000000000000000..93645f26d2fabe47bc374e354adbfb9318c378fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5352.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e39e1f04cdaf4f7b7b1e1586e085ae790af1243f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5354.json b/mne-python/source/doc/sphinxext/prs/5354.json new file mode 100644 index 0000000000000000000000000000000000000000..bd9d6b7c42478ac6435152683d916dfdf2454ac2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5354.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "241161d00d685c988a5937888f8c76959d0cd224", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5361.json b/mne-python/source/doc/sphinxext/prs/5361.json new file mode 100644 index 0000000000000000000000000000000000000000..4cb670d08cf7cacbc2ea7af4ab587b03f84b89cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5361.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7e0e988b6e8f3461855a1dd36aec7e5d17b6c379", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 31, + "d": 5 + }, + "mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.vmrk": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/tests/data/testv2.vmrk": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 20, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5363.json b/mne-python/source/doc/sphinxext/prs/5363.json new file mode 100644 index 0000000000000000000000000000000000000000..929629dde03188b69450c853c45e3cd5ef55d3c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5363.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d109dd8d438e0287dd7b98a167166879204f41a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_csd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 3 + }, + "setup.cfg": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5367.json b/mne-python/source/doc/sphinxext/prs/5367.json new file mode 100644 index 0000000000000000000000000000000000000000..bc751ff2a62ec6eb1c02b95fdd1fa09460162b8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5367.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9358407481379f8738782ab0b9e0c124e974a3ac", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "mne/externals/pymatreader/pymatreader.py": { + "a": 15, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/537.json b/mne-python/source/doc/sphinxext/prs/537.json new file mode 100644 index 0000000000000000000000000000000000000000..b0e001636487f5f41b0415af76befcb41f058742 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/537.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d9fc70aaba832713e20d5bd9222da8a687b8e404", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/_static/default.css": { + "a": 11, + "d": 0 + }, + "doc/source/_static/navy.css": { + "a": 10, + "d": 0 + }, + "doc/source/_templates/layout.html": { + "a": 20, + "d": 0 + }, + "doc/source/conf.py": { + "a": 2, + "d": 1 + }, + "doc/source/mne-python.rst": { + "a": 3, + "d": 0 + }, + "doc/sphinxext/gen_rst.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5371.json b/mne-python/source/doc/sphinxext/prs/5371.json new file mode 100644 index 0000000000000000000000000000000000000000..d34499a6e7d38698c31b89baa72997d8ffaae3be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5371.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fdba42d36107a9c6388578cb7147de242b54a1d4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/proj.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5376.json b/mne-python/source/doc/sphinxext/prs/5376.json new file mode 100644 index 0000000000000000000000000000000000000000..ab9adfd0e9289a075a62d0e7fb9dd52551bf5e96 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5376.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0af60b0598e492ff2e43037ec7c838a361d21bd4", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5378.json b/mne-python/source/doc/sphinxext/prs/5378.json new file mode 100644 index 0000000000000000000000000000000000000000..0072b25576b58b3bc9772f86e177f4fc00b11e2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5378.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "52c432908a7d21ffd5c844a470e0ee7d2b626949", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 6, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 28, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/538.json b/mne-python/source/doc/sphinxext/prs/538.json new file mode 100644 index 0000000000000000000000000000000000000000..b3705c42496e452d81bdbaade0750804b810ac5f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/538.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "acc704c2a4f409cb9e3ef47d695dca7557f7f47f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fiff/pick.py": { + "a": 15, + "d": 5 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5380.json b/mne-python/source/doc/sphinxext/prs/5380.json new file mode 100644 index 0000000000000000000000000000000000000000..7ef5955165892e9e198826e999165f0f27fff421 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5380.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8e44a98692f6dbec059390d33cc78134a0e4f5ba", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 53, + "d": 0 + }, + "tutorials/plot_dipole_fit.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5381.json b/mne-python/source/doc/sphinxext/prs/5381.json new file mode 100644 index 0000000000000000000000000000000000000000..a42c1d8d405004b6ef4d935b14f8394df7d18d45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5381.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5179d6c809b2000b4aeee4fe479640e4b9e0955a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 24, + "d": 38 + }, + "mne/tests/test_bem.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5385.json b/mne-python/source/doc/sphinxext/prs/5385.json new file mode 100644 index 0000000000000000000000000000000000000000..53757e172b0b159d6360620b69bb55603daa1910 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5385.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "609515033e9917423aa4005c294a7c64919b21e6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 11, + "d": 6 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5386.json b/mne-python/source/doc/sphinxext/prs/5386.json new file mode 100644 index 0000000000000000000000000000000000000000..d12e12aaaa8f1c94a5c6b6236549ef7c7e461a7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5386.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "19a44282662786b12f6246bc0921bb5b0a2afab5", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 6, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5388.json b/mne-python/source/doc/sphinxext/prs/5388.json new file mode 100644 index 0000000000000000000000000000000000000000..4d8aca35d997115d5cd14c0e72c071fe27ba16f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5388.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "83e16e22b74f3eefd8eb69a8390a63519cd501ba", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/539.json b/mne-python/source/doc/sphinxext/prs/539.json new file mode 100644 index 0000000000000000000000000000000000000000..15e4ce8838a7b9fa2948baabe6f4c2dea5cd1879 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/539.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2ea0b66ce7a7a499e87d7668ea0bf7ab7b6507b1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/fiff/evoked.py": { + "a": 11, + "d": 10 + }, + "mne/fiff/raw.py": { + "a": 12, + "d": 17 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 5 + }, + "mne/viz.py": { + "a": 76, + "d": 55 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5391.json b/mne-python/source/doc/sphinxext/prs/5391.json new file mode 100644 index 0000000000000000000000000000000000000000..35111808679040b577b921deb5d14cc4b762543e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5391.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3d08007b755931bcd0955b6aacc6d3fb424ff7e6", + "authors": [ + { + "n": "Henrich Kolkhorst", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 72, + "d": 17 + }, + "mne/io/brainvision/tests/data/test.vmrk": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 57, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5392.json b/mne-python/source/doc/sphinxext/prs/5392.json new file mode 100644 index 0000000000000000000000000000000000000000..f9f4beb507cbddd97a35d19ef7a78ac6febad919 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5392.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "83217a86b28a07ed024d9647c942df1960519411", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 19, + "d": 17 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5393.json b/mne-python/source/doc/sphinxext/prs/5393.json new file mode 100644 index 0000000000000000000000000000000000000000..13560e9f2445d546989cc0cad8b7855b9ef84bed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5393.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "012b02bf402873c91987b9cac4fe0aaf56c89755", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/minimum_norm/psf_ctf.py": { + "a": 0, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5394.json b/mne-python/source/doc/sphinxext/prs/5394.json new file mode 100644 index 0000000000000000000000000000000000000000..12c84ff741b7b292f21f713927b6797e95f993e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5394.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5ae2ad3dce9b1289cd33439d49f94a8143a53997", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/search_light.py": { + "a": 8, + "d": 0 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 35, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5395.json b/mne-python/source/doc/sphinxext/prs/5395.json new file mode 100644 index 0000000000000000000000000000000000000000..5437aea71facdded89a836773fdea35a1a986b17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5395.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2e808f876e8bc09c75b2238e6b87547604f5545c", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/glossary.rst": { + "a": 147, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5396.json b/mne-python/source/doc/sphinxext/prs/5396.json new file mode 100644 index 0000000000000000000000000000000000000000..501cafcb588a074c26edae0f494411701608d1d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5396.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a3431eff2d7143faf57bc7f6f12e8d703bab7b19", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "tutorials/plot_object_epochs.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5398.json b/mne-python/source/doc/sphinxext/prs/5398.json new file mode 100644 index 0000000000000000000000000000000000000000..48f7e45d485273ca197b4bcd64db498dd0dba9b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5398.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "80dfec2b6324c761e4b186d96586ff0d423e4bae", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/utils.py": { + "a": 7, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5399.json b/mne-python/source/doc/sphinxext/prs/5399.json new file mode 100644 index 0000000000000000000000000000000000000000..d4fee8ff142559c4ea5947fec3195b98ff93faa0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5399.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9490d528eef7d1c87b1b9b530132aee70b7c7771", + "authors": [ + { + "n": "Sam Perry", + "e": null + } + ], + "changes": { + "mne/cuda.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_filter.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/54.json b/mne-python/source/doc/sphinxext/prs/54.json new file mode 100644 index 0000000000000000000000000000000000000000..349f8b429bbf799d6610807b9357cd5a2daa1a8a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/54.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_utils.py": { + "a": 11, + "d": 0 + }, + "mne/utils.py": { + "a": 158, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/540.json b/mne-python/source/doc/sphinxext/prs/540.json new file mode 100644 index 0000000000000000000000000000000000000000..ddec0ffcf0bbb1b5f5f6c559236e7884c90bdad5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/540.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "fb2186201103c44d2e4adf5873ba09f4f6ea5c29", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 16, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 51, + "d": 15 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 25, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5402.json b/mne-python/source/doc/sphinxext/prs/5402.json new file mode 100644 index 0000000000000000000000000000000000000000..d68e173fc8ab490bdcec71e805c7b92dd0b6866d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5402.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c248bd4c0ac151c76e17b56a5649e659bad58c7e", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 51, + "d": 14 + }, + "mne/viz/epochs.py": { + "a": 11, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5403.json b/mne-python/source/doc/sphinxext/prs/5403.json new file mode 100644 index 0000000000000000000000000000000000000000..d2227c89c20bb13834f3b54d317630dac2198e20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5403.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "1a499ea04322036f93e7e2d46e9994b856c40beb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/manual/cookbook.rst": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 10, + "d": 8 + }, + "examples/visualization/make_report.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 51, + "d": 15 + }, + "mne/tests/test_report.py": { + "a": 30, + "d": 5 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5404.json b/mne-python/source/doc/sphinxext/prs/5404.json new file mode 100644 index 0000000000000000000000000000000000000000..ac2f5419e39d84885d6c69067be74ed1c7a058d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5404.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "63763c7aa6f55726b5694d85a56b035b7a45c822", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5405.json b/mne-python/source/doc/sphinxext/prs/5405.json new file mode 100644 index 0000000000000000000000000000000000000000..bd33aade5264857b0f989673d52d1fed3572ad85 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5405.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3bc4bebf8cd1a2c52bea27b94c9c8c6d40bfcdd5", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5407.json b/mne-python/source/doc/sphinxext/prs/5407.json new file mode 100644 index 0000000000000000000000000000000000000000..7d8a434b62b3c025308320fe2b8b0f97e6ad7798 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5407.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ef0b547ec9ecd50dc9fa3312a0442406bd266130", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 9, + "d": 3 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5409.json b/mne-python/source/doc/sphinxext/prs/5409.json new file mode 100644 index 0000000000000000000000000000000000000000..e8b2044620e7c5926416559a57ba3f0fefd0bc34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5409.json @@ -0,0 +1,375 @@ +{ + "merge_commit_sha": "1d3cb1e2441d94a724a27a415c5bfd15eee58ed2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 4, + "d": 9 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 19, + "d": 29 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 0, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 4, + "d": 10 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 13, + "d": 15 + }, + "mne/channels/tests/test_layout.py": { + "a": 0, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 18, + "d": 27 + }, + "mne/commands/tests/test_commands.py": { + "a": 6, + "d": 8 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 0, + "d": 4 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 3, + "d": 11 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 7, + "d": 13 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 3, + "d": 4 + }, + "mne/forward/tests/test_forward.py": { + "a": 28, + "d": 36 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 6, + "d": 10 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 2, + "d": 6 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 0, + "d": 3 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 1, + "d": 6 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 20, + "d": 16 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 70, + "d": 54 + }, + "mne/io/array/tests/test_array.py": { + "a": 0, + "d": 3 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 4, + "d": 5 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 3 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 19, + "d": 22 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 0, + "d": 3 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 2, + "d": 6 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 6, + "d": 12 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 5, + "d": 16 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 3, + "d": 7 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 22, + "d": 38 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 5, + "d": 15 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 20, + "d": 43 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 9 + }, + "mne/io/tests/test_pick.py": { + "a": 1, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 4, + "d": 7 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 5, + "d": 9 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 0, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 0, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 74, + "d": 82 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 16, + "d": 28 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 5, + "d": 12 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 30, + "d": 35 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 1, + "d": 0 + }, + "mne/report.py": { + "a": 14, + "d": 9 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 0, + "d": 3 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 0, + "d": 3 + }, + "mne/simulation/tests/test_raw.py": { + "a": 0, + "d": 3 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 13, + "d": 23 + }, + "mne/stats/tests/test_regression.py": { + "a": 5, + "d": 11 + }, + "mne/tests/common.py": { + "a": 0, + "d": 20 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 12, + "d": 23 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 6 + }, + "mne/tests/test_coreg.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 27, + "d": 40 + }, + "mne/tests/test_dipole.py": { + "a": 4, + "d": 9 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 8, + "d": 8 + }, + "mne/tests/test_epochs.py": { + "a": 30, + "d": 56 + }, + "mne/tests/test_event.py": { + "a": 6, + "d": 17 + }, + "mne/tests/test_evoked.py": { + "a": 5, + "d": 13 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 9, + "d": 18 + }, + "mne/tests/test_proj.py": { + "a": 15, + "d": 33 + }, + "mne/tests/test_report.py": { + "a": 7, + "d": 20 + }, + "mne/tests/test_source_estimate.py": { + "a": 14, + "d": 26 + }, + "mne/tests/test_source_space.py": { + "a": 5, + "d": 12 + }, + "mne/tests/test_surface.py": { + "a": 6, + "d": 8 + }, + "mne/tests/test_transforms.py": { + "a": 2, + "d": 7 + }, + "mne/tests/test_utils.py": { + "a": 17, + "d": 34 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 3, + "d": 5 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 3, + "d": 4 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 4, + "d": 4 + }, + "mne/viz/misc.py": { + "a": 4, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 15, + "d": 25 + }, + "mne/viz/tests/test_epochs.py": { + "a": 32, + "d": 44 + }, + "mne/viz/tests/test_evoked.py": { + "a": 5, + "d": 9 + }, + "mne/viz/tests/test_ica.py": { + "a": 68, + "d": 74 + }, + "mne/viz/tests/test_misc.py": { + "a": 13, + "d": 9 + }, + "mne/viz/tests/test_raw.py": { + "a": 104, + "d": 101 + }, + "mne/viz/tests/test_topo.py": { + "a": 41, + "d": 39 + }, + "mne/viz/tests/test_topomap.py": { + "a": 6, + "d": 18 + }, + "mne/viz/tests/test_utils.py": { + "a": 0, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "setup.cfg": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/541.json b/mne-python/source/doc/sphinxext/prs/541.json new file mode 100644 index 0000000000000000000000000000000000000000..ae98b88ac09f8e784eec39007b63586ba65a061b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/541.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4fcd9386f0446b5c9e224f0207e988e674681afa", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5410.json b/mne-python/source/doc/sphinxext/prs/5410.json new file mode 100644 index 0000000000000000000000000000000000000000..7bd7a2033d593d8c9db49afdf9565849f69c486c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5410.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "18755d22c3752b767dd493ffb4ffa5360bd322b4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/io/proj.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5412.json b/mne-python/source/doc/sphinxext/prs/5412.json new file mode 100644 index 0000000000000000000000000000000000000000..bdfdcfba6c67cb43c7eba6d3183460d1ce7f489f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5412.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3b0270cad41e53da97fbaa96d2c361afc62e44a5", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 1 + }, + "mne/io/brainvision/tests/data/testv2.vmrk": { + "a": 7, + "d": 6 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5413.json b/mne-python/source/doc/sphinxext/prs/5413.json new file mode 100644 index 0000000000000000000000000000000000000000..aa365d592a15dca79bf283a5a8af0fe1658942a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5413.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ae560615a72dea7f807983a359f9b57838c1bd9d", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + ".github/CONTRIBUTING.md": { + "a": 0, + "d": 0 + }, + ".github/ISSUE_TEMPLATE/blank.md": { + "a": 5, + "d": 0 + }, + ".github/ISSUE_TEMPLATE/bug_report.md": { + "a": 50, + "d": 0 + }, + ".github/ISSUE_TEMPLATE/feature_request.md": { + "a": 22, + "d": 0 + }, + ".github/PULL_REQUEST_TEMPLATE.md": { + "a": 23, + "d": 0 + }, + "MANIFEST.in": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5414.json b/mne-python/source/doc/sphinxext/prs/5414.json new file mode 100644 index 0000000000000000000000000000000000000000..0143ee398d8b944a8699224a3ba4af188505e604 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5414.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c78271f983093f2c0bb5ab89a58714e036539dd7", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/commands/mne_flash_bem.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5415.json b/mne-python/source/doc/sphinxext/prs/5415.json new file mode 100644 index 0000000000000000000000000000000000000000..ea6f14b893e4a99dc5295b9f2d7f3deff1ff8535 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5415.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "beda451422b4d8016643438ce7e998c76cbd2f59", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5416.json b/mne-python/source/doc/sphinxext/prs/5416.json new file mode 100644 index 0000000000000000000000000000000000000000..fe0a3d734b580d677a09cf90f381ff2004d5da5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5416.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "487762415ef41c8d5dbc2f21e40bcf02b874f19a", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 3 + }, + "mne/annotations.py": { + "a": 16, + "d": 5 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 5 + }, + "mne/io/base.py": { + "a": 19, + "d": 18 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 2, + "d": 3 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 7 + }, + "mne/io/pick.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 5, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5418.json b/mne-python/source/doc/sphinxext/prs/5418.json new file mode 100644 index 0000000000000000000000000000000000000000..d29032f703ac2475b29839234355f8aa5756ec39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5418.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e6e61b30b616eed039959544340234f7897a2852", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 74, + "d": 1 + }, + "mne/io/base.py": { + "a": 31, + "d": 56 + }, + "mne/tests/test_annotations.py": { + "a": 54, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5422.json b/mne-python/source/doc/sphinxext/prs/5422.json new file mode 100644 index 0000000000000000000000000000000000000000..62ace603779115b54f85d51df91ad110d9206f53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5422.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b070c7087c2e575624515d70a6ec150f17d661e2", + "authors": [ + { + "n": "Thomas Jochmann", + "e": null + } + ], + "changes": { + "doc/faq.rst": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5423.json b/mne-python/source/doc/sphinxext/prs/5423.json new file mode 100644 index 0000000000000000000000000000000000000000..e8f767209b893636c75d25f07e4f571427a248be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5423.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ce9289fe13c2bee6506a18c63d93fbfea48f0f26", + "authors": [ + { + "n": "Thomas Jochmann", + "e": null + } + ], + "changes": { + "doc/configure_git.rst": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5424.json b/mne-python/source/doc/sphinxext/prs/5424.json new file mode 100644 index 0000000000000000000000000000000000000000..079f97dee694629379c50d97bbb274f804ea78eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5424.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "62ecf9e482bf84a7f58c5fefff766336068f8bce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5426.json b/mne-python/source/doc/sphinxext/prs/5426.json new file mode 100644 index 0000000000000000000000000000000000000000..0653bb65131643a842beecee456fd4ad85e33629 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5426.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "eb934fb23d58b86644578240160a2c5332f469be", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 25, + "d": 17 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 12, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5428.json b/mne-python/source/doc/sphinxext/prs/5428.json new file mode 100644 index 0000000000000000000000000000000000000000..aee031cc7e96da1aa32de9641a16502fd18a219e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5428.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "ff8ebca4a9d2497d4f8613c11b42300ccd3c9ba4", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 6, + "d": 4 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 7, + "d": 5 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_reference.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5429.json b/mne-python/source/doc/sphinxext/prs/5429.json new file mode 100644 index 0000000000000000000000000000000000000000..0b416b11e21959ed8528e3e56c39e4f281169c64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5429.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d3aba149f87adb34bdb64e75aa230f7203b0e86d", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "mne/externals/pymatreader/__init__.py": { + "a": 13, + "d": 9 + }, + "mne/externals/pymatreader/pymatreader.py": { + "a": 109, + "d": 64 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5431.json b/mne-python/source/doc/sphinxext/prs/5431.json new file mode 100644 index 0000000000000000000000000000000000000000..2ffeef9d6e718d604fa49186b9c195b775de38c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5431.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "35f54e709e8d8e33d2c5996f37699ae7e4b1a651", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 13, + "d": 5 + }, + "mne/tests/test_evoked.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5433.json b/mne-python/source/doc/sphinxext/prs/5433.json new file mode 100644 index 0000000000000000000000000000000000000000..510a5d92806a0ebb03dece532cade8ec99d6520d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5433.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "7ecc4a52faf0cc363e56f1fbb0e2109a76c7c8cb", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 74, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 0 + }, + "mne/io/base.py": { + "a": 37, + "d": 5 + }, + "mne/io/fiff/raw.py": { + "a": 19, + "d": 14 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 5, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 61, + "d": 28 + }, + "mne/io/tests/test_raw.py": { + "a": 64, + "d": 3 + }, + "mne/tests/test_annotations.py": { + "a": 23, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5434.json b/mne-python/source/doc/sphinxext/prs/5434.json new file mode 100644 index 0000000000000000000000000000000000000000..0914ac30e22d298404060ed98dc440398e048f3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5434.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5a60d29d6561204d95a4e0edbe95066c5404abdd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5435.json b/mne-python/source/doc/sphinxext/prs/5435.json new file mode 100644 index 0000000000000000000000000000000000000000..a2657aab564d3f32a27a0ca07b69639ad9f985bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5435.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "dd45dba7acc7289cceaca6aa669c2f70264e6643", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cuda.py": { + "a": 40, + "d": 53 + }, + "mne/filter.py": { + "a": 8, + "d": 15 + }, + "mne/tests/test_filter.py": { + "a": 20, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5437.json b/mne-python/source/doc/sphinxext/prs/5437.json new file mode 100644 index 0000000000000000000000000000000000000000..b6708bc09fb05ded1be1be093382f529dbb16901 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5437.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "986e8a3004f94bb740ffe74d12dce9d222493339", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 1, + "d": 5 + }, + "mne/stats/tests/test_regression.py": { + "a": 6, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5438.json b/mne-python/source/doc/sphinxext/prs/5438.json new file mode 100644 index 0000000000000000000000000000000000000000..1e2d338b8f41f611616c7c8316ec05a49ba0bed3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5438.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a0ffcf9f63dce1f6f6af89713e98903f905dcf34", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5442.json b/mne-python/source/doc/sphinxext/prs/5442.json new file mode 100644 index 0000000000000000000000000000000000000000..521e75ce0eef31afe455af0987c32319128fb443 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5442.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0d99a0d199a1f7a954003e86974ff88ed28b36d4", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 32, + "d": 28 + }, + "mne/io/brainvision/tests/data/testv2.vmrk": { + "a": 13, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5443.json b/mne-python/source/doc/sphinxext/prs/5443.json new file mode 100644 index 0000000000000000000000000000000000000000..49ee1e05f06e126c37fd895f8525277de26bfb98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5443.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "d232d8ec611513044d6a60d732e8f1d50fb6b457", + "authors": [ + { + "n": "Tommy Clausner", + "e": null + } + ], + "changes": { + "doc/_templates/class.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/documentation.rst": { + "a": 5, + "d": 1 + }, + "doc/manual/cookbook.rst": { + "a": 2, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 5 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_morph_data.py": { + "a": 0, + "d": 59 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 85, + "d": 0 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 88, + "d": 0 + }, + "examples/visualization/plot_xhemi.py": { + "a": 8, + "d": 6 + }, + "mne/__init__.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 189, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 8, + "d": 99 + }, + "mne/beamformer/_lcmv.py": { + "a": 9, + "d": 125 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 9, + "d": 1 + }, + "mne/label.py": { + "a": 10, + "d": 6 + }, + "mne/morph.py": { + "a": 1475, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 59, + "d": 519 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 275, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 83, + "d": 65 + }, + "mne/tests/test_source_space.py": { + "a": 26, + "d": 10 + }, + "mne/utils.py": { + "a": 7, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_background_freesurfer.py": { + "a": 118, + "d": 0 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 9, + "d": 4 + }, + "tutorials/plot_morph_stc.py": { + "a": 266, + "d": 0 + }, + "tutorials/plot_object_source_estimate.py": { + "a": 229, + "d": 0 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 5, + "d": 2 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5444.json b/mne-python/source/doc/sphinxext/prs/5444.json new file mode 100644 index 0000000000000000000000000000000000000000..9aebc25fedb118eff05e83d37a62fab9d92fa7b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5444.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c6e62d6c11c557cd69ce0b4e88bb17b5ca8c47dd", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 7 + }, + "mne/transforms.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5447.json b/mne-python/source/doc/sphinxext/prs/5447.json new file mode 100644 index 0000000000000000000000000000000000000000..5df82a6c54677e69ee194999b45993e0195dd57b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5447.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "552b4334457eef4d617c0420803199c974059c8e", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 15, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 6, + "d": 10 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 224, + "d": 213 + }, + "mne/beamformer/_dics.py": { + "a": 51, + "d": 22 + }, + "mne/beamformer/_lcmv.py": { + "a": 44, + "d": 26 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 23, + "d": 5 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 20, + "d": 52 + }, + "mne/cov.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 48, + "d": 2 + }, + "mne/utils.py": { + "a": 128, + "d": 6 + }, + "tutorials/plot_dics.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/545.json b/mne-python/source/doc/sphinxext/prs/545.json new file mode 100644 index 0000000000000000000000000000000000000000..07f9f5a583610997153a791313d6e0988eea588f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/545.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b6ce07846a7cbde7426303eb3c5991fbd4de34c4", + "authors": [ + { + "n": "Brad Buran", + "e": null + } + ], + "changes": { + "mne/utils.py": { + "a": 93, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5452.json b/mne-python/source/doc/sphinxext/prs/5452.json new file mode 100644 index 0000000000000000000000000000000000000000..5f119885bafc8637d110b768964aa71bf5928427 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5452.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "0fe359e9ad4002b2e4d1023e199bf7a005b27f25", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 5 + }, + "doc/advanced_setup.rst": { + "a": 16, + "d": 40 + }, + "doc/install_mne_python.rst": { + "a": 1, + "d": 2 + }, + "doc/known_projects.inc": { + "a": 3, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/cuda.py": { + "a": 74, + "d": 134 + }, + "mne/decoding/transformer.py": { + "a": 6, + "d": 6 + }, + "mne/filter.py": { + "a": 22, + "d": 22 + }, + "mne/io/base.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/ssp.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 12, + "d": 7 + }, + "mne/utils.py": { + "a": 3, + "d": 6 + }, + "setup.cfg": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5453.json b/mne-python/source/doc/sphinxext/prs/5453.json new file mode 100644 index 0000000000000000000000000000000000000000..91fca4dfe77d6838c451949086f4fe4db7aacaba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5453.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0802291704a45000b04c31d696c5c84828997c27", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5454.json b/mne-python/source/doc/sphinxext/prs/5454.json new file mode 100644 index 0000000000000000000000000000000000000000..4f3b60a9a764c8a1ab979462dd2ed450cd88ee7e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5454.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f6d4084bf0d304fe49a23545b34c4c2cf998951b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 0 + }, + "doc/advanced_setup.rst": { + "a": 17, + "d": 1 + }, + "doc/contributing.rst": { + "a": 2, + "d": 2 + }, + "doc/faq.rst": { + "a": 3, + "d": 27 + }, + "doc/install_mne_python.rst": { + "a": 26, + "d": 2 + }, + "environment.yml": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5459.json b/mne-python/source/doc/sphinxext/prs/5459.json new file mode 100644 index 0000000000000000000000000000000000000000..5d8c3b57f1e8b52edb52ffb9a9a3a5c2b6b5f1e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5459.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f7e2a95bf01981072c598bb806204e72630b26f6", + "authors": [ + { + "n": "Sergey Antopolskiy", + "e": "s.antopolsky@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/546.json b/mne-python/source/doc/sphinxext/prs/546.json new file mode 100644 index 0000000000000000000000000000000000000000..a341636ec4ae5d1b0a80cce43a68c04daf2527e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/546.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "edc00a11911b6fdc872e03988840677133ff19a6", + "authors": [ + { + "n": "Brad Buran", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5460.json b/mne-python/source/doc/sphinxext/prs/5460.json new file mode 100644 index 0000000000000000000000000000000000000000..9519690a79a1336811937dee46652ea6d5462ccf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5460.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "c5b43b0bea7017a2171d5e22b1351f3ee80e3906", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/annotations.py": { + "a": 12, + "d": 7 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 247, + "d": 133 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 97, + "d": 75 + }, + "mne/io/utils.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5461.json b/mne-python/source/doc/sphinxext/prs/5461.json new file mode 100644 index 0000000000000000000000000000000000000000..54b1324897ab3d13ba06a71e28602fb8e7e331f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5461.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9807547fee74b85f1db85295ae6d986523d68455", + "authors": [ + { + "n": "Peter J. Molfese", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/eog.py": { + "a": 14, + "d": 8 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5462.json b/mne-python/source/doc/sphinxext/prs/5462.json new file mode 100644 index 0000000000000000000000000000000000000000..6d97a8c574a26a3987b62b58bc7dfe138743f8c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5462.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8cc1068aa34c0aa43cdd3d2f42ba4961d0a189e9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 1, + "d": 1 + }, + "mne/data/helmets/CTF_275.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5464.json b/mne-python/source/doc/sphinxext/prs/5464.json new file mode 100644 index 0000000000000000000000000000000000000000..70d9aaca37ffd888836e1c567e37ac3adff507de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5464.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2dd7aa0bd05f3cae8dc5c17e951454ef6c71b17c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cuda.py": { + "a": 9, + "d": 6 + }, + "mne/decoding/receptive_field.py": { + "a": 30, + "d": 6 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 44, + "d": 29 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 109, + "d": 95 + }, + "mne/utils/progressbar.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5466.json b/mne-python/source/doc/sphinxext/prs/5466.json new file mode 100644 index 0000000000000000000000000000000000000000..8748271280449950e8b8f0921b226d0e9972c379 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5466.json @@ -0,0 +1,151 @@ +{ + "merge_commit_sha": "6104472f1101633c7a8166b36d2e9206e5aee0b3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/_templates/class.rst": { + "a": 0, + "d": 2 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/documentation.rst": { + "a": 5, + "d": 3 + }, + "doc/faq.rst": { + "a": 0, + "d": 26 + }, + "doc/glossary.rst": { + "a": 4, + "d": 0 + }, + "doc/manual/cookbook.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/source_localization/inverse.rst": { + "a": 2, + "d": 2 + }, + "doc/manual/source_localization/morph.rst": { + "a": 2, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 4 + }, + "doc/whats_new.rst": { + "a": 5, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_morph_data.py": { + "a": 0, + "d": 59 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 151, + "d": 0 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 160, + "d": 0 + }, + "examples/visualization/plot_xhemi.py": { + "a": 13, + "d": 20 + }, + "mne/__init__.py": { + "a": 4, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/label.py": { + "a": 19, + "d": 18 + }, + "mne/morph.py": { + "a": 1200, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 84, + "d": 588 + }, + "mne/surface.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 497, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 31, + "d": 123 + }, + "mne/tests/test_source_space.py": { + "a": 37, + "d": 10 + }, + "mne/utils.py": { + "a": 24, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_background_freesurfer.py": { + "a": 4, + "d": 3 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 7, + "d": 5 + }, + "tutorials/plot_morph_stc.py": { + "a": 265, + "d": 0 + }, + "tutorials/plot_object_source_estimate.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5467.json b/mne-python/source/doc/sphinxext/prs/5467.json new file mode 100644 index 0000000000000000000000000000000000000000..fcf3a8bbb0ebe9cff754f9a3db53cb57324ede82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5467.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fd0ecac68cab7ddb6d1649b72b70042eef081550", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 2, + "d": 0 + }, + "doc/glossary.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/cookbook.rst": { + "a": 2, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 2 + }, + "tutorials/plot_background_freesurfer.py": { + "a": 117, + "d": 0 + }, + "tutorials/plot_object_source_estimate.py": { + "a": 238, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5468.json b/mne-python/source/doc/sphinxext/prs/5468.json new file mode 100644 index 0000000000000000000000000000000000000000..19982089ae080cd47c46f82841fb7d908dcebf0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5468.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9dd6b8aa7927a86761d21992564f54697411f52c", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/io/kit/kit.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/547.json b/mne-python/source/doc/sphinxext/prs/547.json new file mode 100644 index 0000000000000000000000000000000000000000..764ba85c92ee2dd0c23f566b9c0eb9278e31e310 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/547.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "acd30858a4ad4a577d002e2a8486747771df85e1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5470.json b/mne-python/source/doc/sphinxext/prs/5470.json new file mode 100644 index 0000000000000000000000000000000000000000..a7a2e32108d4b120bc19256b4fbd841bf6efa8be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5470.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "14d0c6a3e6257692fd497614d9cedfc1c3bc2a60", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/base.py": { + "a": 33, + "d": 8 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5473.json b/mne-python/source/doc/sphinxext/prs/5473.json new file mode 100644 index 0000000000000000000000000000000000000000..b440573588b04250ce7d02c8b7c1d69e128951ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5473.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "971267567b443f5a7d6c9812711ee634bf01e874", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "examples/visualization/plot_parcellation.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5475.json b/mne-python/source/doc/sphinxext/prs/5475.json new file mode 100644 index 0000000000000000000000000000000000000000..aa3b2a9e849832d5fece0a093d579cf43cdfd13e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5475.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d91f99f56e4beb80808f396b4404f5434bedae8e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 23, + "d": 30 + }, + "mne/tests/test_dipole.py": { + "a": 14, + "d": 15 + }, + "tutorials/plot_brainstorm_phantom_ctf.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 16, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5477.json b/mne-python/source/doc/sphinxext/prs/5477.json new file mode 100644 index 0000000000000000000000000000000000000000..0465be7cfdb538fea5134a8741267785864956bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5477.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b7c8d9c7c9f84a62a3de28af678f32e6a314a2e0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 20, + "d": 18 + }, + "mne/minimum_norm/inverse.py": { + "a": 41, + "d": 34 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 53, + "d": 4 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 15, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5478.json b/mne-python/source/doc/sphinxext/prs/5478.json new file mode 100644 index 0000000000000000000000000000000000000000..947a3b3965bbea9cbde81a99f19510223dcba11f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5478.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cfe3b1e0705622c903e44893702396e1dd968a8a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5481.json b/mne-python/source/doc/sphinxext/prs/5481.json new file mode 100644 index 0000000000000000000000000000000000000000..bcfa6c5ca75b3944b86ab9317b5fff269e3cff73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5481.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "c80e57cd4eef1b753fa885af757ad8927430307f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 3, + "d": 2 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 3, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 283, + "d": 170 + }, + "mne/decoding/csp.py": { + "a": 10, + "d": 3 + }, + "mne/decoding/tests/test_csp.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/io/pick.py": { + "a": 13, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 8, + "d": 2 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 143, + "d": 32 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 8, + "d": 6 + }, + "tutorials/plot_compute_covariance.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_whitened.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5482.json b/mne-python/source/doc/sphinxext/prs/5482.json new file mode 100644 index 0000000000000000000000000000000000000000..f15bcc482541503af6c960a06040500a3fd6e3f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5482.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "aabc501d988298f286381bd94ec3ec628a9d4dac", + "authors": [ + { + "n": "Henrich Kolkhorst", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/realtime/ftclient_rt_average.py": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 9, + "d": 0 + }, + "mne/realtime/client.py": { + "a": 3, + "d": 4 + }, + "mne/realtime/epochs.py": { + "a": 7, + "d": 2 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 6, + "d": 4 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5486.json b/mne-python/source/doc/sphinxext/prs/5486.json new file mode 100644 index 0000000000000000000000000000000000000000..3694e36a6cb23daf6830d338b1799d72597fce8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5486.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "6cb40dbb55eb77938b9557388329bba0e53b3061", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/manual/cookbook.rst": { + "a": 3, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 9, + "d": 7 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 4, + "d": 4 + }, + "examples/visualization/plot_xhemi.py": { + "a": 4, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 7, + "d": 7 + }, + "mne/source_estimate.py": { + "a": 8, + "d": 6 + }, + "mne/tests/test_morph.py": { + "a": 26, + "d": 26 + }, + "mne/tests/test_source_space.py": { + "a": 7, + "d": 5 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5489.json b/mne-python/source/doc/sphinxext/prs/5489.json new file mode 100644 index 0000000000000000000000000000000000000000..ded3ece1dad464f5f37fdd21a72d050e6e1768df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5489.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6aff6e6cc11e7428fe6a89bf8516d9b3669d3938", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/549.json b/mne-python/source/doc/sphinxext/prs/549.json new file mode 100644 index 0000000000000000000000000000000000000000..f73583aafbaf5a0a4d9a498d401c59af47ccab4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/549.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b6dd77ab5d108816734b45f65e503a6a07c4b9fb", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 7, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5496.json b/mne-python/source/doc/sphinxext/prs/5496.json new file mode 100644 index 0000000000000000000000000000000000000000..344a6856fc5201bc1da2cc1769a537337bb5522b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5496.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "613df87f097323175784f3a7fdc32bbad0e604ac", + "authors": [ + { + "n": "Jasper J.F. van den Bosch", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5497.json b/mne-python/source/doc/sphinxext/prs/5497.json new file mode 100644 index 0000000000000000000000000000000000000000..317d02db05083d4483041677e05bc23474e57a33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5497.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fc6a6766b908c83dca8018b8aedba9405fb7d88f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "setup.cfg": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5498.json b/mne-python/source/doc/sphinxext/prs/5498.json new file mode 100644 index 0000000000000000000000000000000000000000..f2c3c6950810534a238d9752fbb6da0f495187e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5498.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "64be522285d5eeea4e3fb4c6df133984fc65b74e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/time_frequency/plot_compute_source_psd_epochs.py": { + "a": 31, + "d": 23 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 17, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/multitaper.py": { + "a": 6, + "d": 5 + }, + "mne/utils.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/55.json b/mne-python/source/doc/sphinxext/prs/55.json new file mode 100644 index 0000000000000000000000000000000000000000..23e0f12b2a3795dd16fb2e3497afea990aab4e20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/55.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b2b9ff400caac1561732793110b95d6f1ee64666", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_morph_data.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 56, + "d": 28 + }, + "mne/tests/test_source_estimate.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/550.json b/mne-python/source/doc/sphinxext/prs/550.json new file mode 100644 index 0000000000000000000000000000000000000000..34e9a03d13522c7f2398a0e56e1ec5b81eb35067 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/550.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5e5de599e8010031720b45b90fc3a26ccbd5b361", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_compute_source_psd_epochs.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5500.json b/mne-python/source/doc/sphinxext/prs/5500.json new file mode 100644 index 0000000000000000000000000000000000000000..02f3df9b5d170468a0424690469d497b571c99bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5500.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "d1e2cc88b83d26d45140ea6ff7b66e04082e7728", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 3 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 2, + "d": 3 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 25, + "d": 14 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5502.json b/mne-python/source/doc/sphinxext/prs/5502.json new file mode 100644 index 0000000000000000000000000000000000000000..47cc97e11d4eedf8a3fe2bab8c9f1f4ab6a8fd8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5502.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c95051f553d31da2ec7945b1ef0afe3594672f7b", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5504.json b/mne-python/source/doc/sphinxext/prs/5504.json new file mode 100644 index 0000000000000000000000000000000000000000..8e98a7b087c0b38b0e5d3070d1f5681fb9afebd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5504.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5a84ba9f247362da66b209634916485d1c691c13", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5505.json b/mne-python/source/doc/sphinxext/prs/5505.json new file mode 100644 index 0000000000000000000000000000000000000000..39023436b796ff7ee357ce9b8a0a224ec1249906 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5505.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9aaa6636c3a508df1aa87c6a38d1a388b5de0b39", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 6, + "d": 4 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 140, + "d": 23 + }, + "mne/tests/test_report.py": { + "a": 32, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5506.json b/mne-python/source/doc/sphinxext/prs/5506.json new file mode 100644 index 0000000000000000000000000000000000000000..acc69f47e8ff3720f56e759527d89fc267aa6b3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5506.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b6b0afe7b0e124f0b04465cd5b65b0a9f2651e68", + "authors": [ + { + "n": "ezemikulan", + "e": "e.mikulan@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 0 + }, + "mne/gui/_coreg_gui.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5511.json b/mne-python/source/doc/sphinxext/prs/5511.json new file mode 100644 index 0000000000000000000000000000000000000000..d505c34583cbf0f30ebbe2c73738f6a4ab063149 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5511.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "438206d4a3f41f6bd9fbc45ee756a516760ce86c", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 11, + "d": 7 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5513.json b/mne-python/source/doc/sphinxext/prs/5513.json new file mode 100644 index 0000000000000000000000000000000000000000..776ab81f1b6918c0eabfceb1813b20bfd9c2639a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5513.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9445db3e18f6b4f62497a484f6cfc92d20dbf325", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5514.json b/mne-python/source/doc/sphinxext/prs/5514.json new file mode 100644 index 0000000000000000000000000000000000000000..084892093c271f909b8010aac75ba9ce82916c62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5514.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "9382ee8c46d2c1d56e0fd9f8b79b07cd0bc0a855", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 1, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 11, + "d": 6 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 2, + "d": 1 + }, + "examples/visualization/plot_evoked_arrowmap.py": { + "a": 17, + "d": 15 + }, + "mne/data/helmets/CTF_275.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 41, + "d": 23 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 158, + "d": 89 + }, + "mne/source_estimate.py": { + "a": 28, + "d": 21 + }, + "mne/tests/test_source_estimate.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 9, + "d": 1 + }, + "mne/utils.py": { + "a": 4, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5518.json b/mne-python/source/doc/sphinxext/prs/5518.json new file mode 100644 index 0000000000000000000000000000000000000000..9d463a621598ed6cee988b739aedf24b3646829d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5518.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ee69dff86525644090f1e5a9c3587f200652f313", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/sphinxext/cited_mne.py": { + "a": 2, + "d": 2 + }, + "doc/sphinxext/ipython_console_highlighting.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/552.json b/mne-python/source/doc/sphinxext/prs/552.json new file mode 100644 index 0000000000000000000000000000000000000000..94720de6a581efca273216ea0043cdb1ec55c5aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/552.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "749715585be234efa7b6ce9ec16136e57ec2d7ed", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5522.json b/mne-python/source/doc/sphinxext/prs/5522.json new file mode 100644 index 0000000000000000000000000000000000000000..78b819389815abd81c71a92863b0aa3b2f9cd951 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5522.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4aa86acaeabd91dd6175b74c25fd3fdcbac531f0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 2, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 73, + "d": 47 + }, + "mne/viz/tests/test_3d.py": { + "a": 14, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5524.json b/mne-python/source/doc/sphinxext/prs/5524.json new file mode 100644 index 0000000000000000000000000000000000000000..20993d2c33d59fde37d2df50d1f4274aef3fbd19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5524.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "56ca913254a551ab6cb34b3b208f44374f80d121", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 31, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 22, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5525.json b/mne-python/source/doc/sphinxext/prs/5525.json new file mode 100644 index 0000000000000000000000000000000000000000..24cd65ae2b9a2ce311a1e3ab483ae718b75943bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5525.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "7f0d522073cbe5b0920ee133471b503f45fa6d60", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 4, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/manual/datasets_index.rst": { + "a": 34, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/datasets/plot_opm_data.py": { + "a": 117, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/opm/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/opm/opm.py": { + "a": 32, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 7, + "d": 1 + }, + "mne/dipole.py": { + "a": 3, + "d": 9 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 49, + "d": 7 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 52, + "d": 13 + }, + "mne/viz/tests/test_3d.py": { + "a": 33, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5527.json b/mne-python/source/doc/sphinxext/prs/5527.json new file mode 100644 index 0000000000000000000000000000000000000000..896b9b4e5b87957489c51ee928349378563f7633 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5527.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "445ca6951b6f92d2ae88a2ae07b410275ff0678c", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/tutorials/report.rst": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5528.json b/mne-python/source/doc/sphinxext/prs/5528.json new file mode 100644 index 0000000000000000000000000000000000000000..f16cc279679d8688570a01b9be3529051d3970ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5528.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "8f6ff4237b0f9cf31053de21fed4b66cbaf39b53", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 129, + "d": 111 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_visualize_stc.py": { + "a": 140, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/553.json b/mne-python/source/doc/sphinxext/prs/553.json new file mode 100644 index 0000000000000000000000000000000000000000..6fbaa3098f058db6b4cd77b9998252a6395f8dca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/553.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8c70883aca410f5f239a362c20c2d76ceee9290d", + "authors": [ + { + "n": "Brad Buran", + "e": null + } + ], + "changes": { + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 12, + "d": 2 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 17, + "d": 5 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 21, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5530.json b/mne-python/source/doc/sphinxext/prs/5530.json new file mode 100644 index 0000000000000000000000000000000000000000..491d4e5a70e40bd7fafc61de01c66de115c5903c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5530.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d69d7ba6dec94056d78526428b2496bb5f009588", + "authors": [ + { + "n": "Hubert Banville", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5531.json b/mne-python/source/doc/sphinxext/prs/5531.json new file mode 100644 index 0000000000000000000000000000000000000000..79d140f6bd740247f1b7f2d18745b70383302c40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5531.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "fa119971035fb8cf0f92acc98c846645d5f410d2", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/tutorials/report.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 147, + "d": 53 + }, + "mne/tests/test_report.py": { + "a": 64, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5532.json b/mne-python/source/doc/sphinxext/prs/5532.json new file mode 100644 index 0000000000000000000000000000000000000000..27320f43ca2b728e3a63d575df238183be3af1ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5532.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "50efb02eda5f9ea14e1e9ae4b6045b5e4bc0dba0", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 20, + "d": 18 + }, + "mne/tests/test_utils.py": { + "a": 14, + "d": 1 + }, + "mne/utils.py": { + "a": 49, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5533.json b/mne-python/source/doc/sphinxext/prs/5533.json new file mode 100644 index 0000000000000000000000000000000000000000..add9a9fa1b101834dbee724aa2628b9382a2062c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5533.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "02e17aed22045107553f01e88d8feed40c3d73ca", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 1, + "d": 2 + }, + "mne/io/base.py": { + "a": 6, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 4 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 1, + "d": 3 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 7, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5536.json b/mne-python/source/doc/sphinxext/prs/5536.json new file mode 100644 index 0000000000000000000000000000000000000000..5a4647e45c080a167bd322e696254603095d2e38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5536.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "de8f3bf0d40aa4532300eee227e326f6787a3895", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_backend.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5537.json b/mne-python/source/doc/sphinxext/prs/5537.json new file mode 100644 index 0000000000000000000000000000000000000000..c5dab730d62432e2c57a86a10d8d4f1be64e9293 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5537.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "204f29b9724ae32f1983944e82e635abb2da8055", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5538.json b/mne-python/source/doc/sphinxext/prs/5538.json new file mode 100644 index 0000000000000000000000000000000000000000..b7898d4bb20968cf3f9607bf8bf22bf57122458e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5538.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "59d51f0ce128921db74a8c1076f46a488e6de4e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/mne_coreg.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/554.json b/mne-python/source/doc/sphinxext/prs/554.json new file mode 100644 index 0000000000000000000000000000000000000000..05d1888ed79cf3ace422d77960b0bc67881e7ba2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/554.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "56c917bc2d234e147d3548295450dcd6f42708cb", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 115, + "d": 0 + }, + "mne/connectivity/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/connectivity/effective.py": { + "a": 164, + "d": 0 + }, + "mne/connectivity/spectral.py": { + "a": 131, + "d": 54 + }, + "mne/connectivity/tests/test_effective.py": { + "a": 42, + "d": 0 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 12, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5542.json b/mne-python/source/doc/sphinxext/prs/5542.json new file mode 100644 index 0000000000000000000000000000000000000000..8a42acfc65b5f83da91b86939fda66c556d82f5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5542.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3c1546a97243b7bbf6901bfbbab9bdcf3b70aaf9", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 2 + }, + "mne/channels/data/layouts/Neuromag_122.lout": { + "a": 123, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 42, + "d": 4 + }, + "mne/viz/tests/test_topomap.py": { + "a": 31, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 18, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5543.json b/mne-python/source/doc/sphinxext/prs/5543.json new file mode 100644 index 0000000000000000000000000000000000000000..6b03d465e7a05053c15c010ced8e392088fc7d68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5543.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b73ea28300a2d0a1dcfb518a5de904b411d743ff", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/tests/test_raw.py": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5545.json b/mne-python/source/doc/sphinxext/prs/5545.json new file mode 100644 index 0000000000000000000000000000000000000000..b7eeca3f8c35588d5b14655225611b3a19a2cd5b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5545.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b147f4310252040e3ad44de4e2f30c4116fdde37", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5547.json b/mne-python/source/doc/sphinxext/prs/5547.json new file mode 100644 index 0000000000000000000000000000000000000000..aa7e35aec240ea40255cd762f760c1c2f60e4b75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5547.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "473b24fbb71ab946ed19268a0f10e4b51e860629", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5549.json b/mne-python/source/doc/sphinxext/prs/5549.json new file mode 100644 index 0000000000000000000000000000000000000000..f2dd8e4165bae461b8edcf2282813c16c09e74fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5549.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "75c29da8e1e3857726156a6caea8fd727140a919", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/555.json b/mne-python/source/doc/sphinxext/prs/555.json new file mode 100644 index 0000000000000000000000000000000000000000..c85d686ddb35a7e83eb605521c9b76b22acf292a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/555.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "76c3a6df023b43fd4dfbc8fd8d411087c8473564", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5554.json b/mne-python/source/doc/sphinxext/prs/5554.json new file mode 100644 index 0000000000000000000000000000000000000000..f1ad2302619f99a6341c3320092a768fe8f04cd8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5554.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b619f1cd1f0860155b4d9ada2376b664fbce37b4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5557.json b/mne-python/source/doc/sphinxext/prs/5557.json new file mode 100644 index 0000000000000000000000000000000000000000..e98015ea1a0fa32b0db6bfa3218a465b62f379ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5557.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "6fd6dbd3350ff62f4093205df76bfda351a0ef6c", + "authors": [ + { + "n": "Sheraz Khan", + "e": "sheraz.khan@pfizer.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "examples/visualization/plot_evoked_arrowmap.py": { + "a": 74, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 18, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 175, + "d": 0 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5558.json b/mne-python/source/doc/sphinxext/prs/5558.json new file mode 100644 index 0000000000000000000000000000000000000000..88813b8e9f019659ff76743d8d62a1b44bd886cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5558.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fef6f063d0d81c54400f2868d91bf9c01b3ea2b3", + "authors": [ + { + "n": "Kambiz Tavabi", + "e": "ktavabi@gmail.com" + } + ], + "changes": { + "bin/mne": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_flash_bem.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5559.json b/mne-python/source/doc/sphinxext/prs/5559.json new file mode 100644 index 0000000000000000000000000000000000000000..67bb2f11c5480ff81b7eb13dc5be9742d0cd544b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5559.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "bcabf319eab3dcd3902125da344d13eafd1669a6", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/base.py": { + "a": 4, + "d": 1 + }, + "mne/decoding/tests/test_base.py": { + "a": 12, + "d": 7 + }, + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 27, + "d": 17 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/556.json b/mne-python/source/doc/sphinxext/prs/556.json new file mode 100644 index 0000000000000000000000000000000000000000..4d88a797557283a5682fb5dca49b7296aef1071e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/556.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f3041f5cdd64502fd8575dca53f601ea9ac33ae1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 15, + "d": 8 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_event.py": { + "a": 19, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5560.json b/mne-python/source/doc/sphinxext/prs/5560.json new file mode 100644 index 0000000000000000000000000000000000000000..60e5f7cdcaf7c87cab1d8a7eb0fa8bf85ea746b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5560.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1d6c5104656ba772e7527241568c228ca8f887c2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/constants.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5562.json b/mne-python/source/doc/sphinxext/prs/5562.json new file mode 100644 index 0000000000000000000000000000000000000000..6879cff5e42adf7e31169e6f60550d18899c6112 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5562.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "04549bc89e7cb3d177ae523ef69f42208481545e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 71, + "d": 35 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 51, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5564.json b/mne-python/source/doc/sphinxext/prs/5564.json new file mode 100644 index 0000000000000000000000000000000000000000..83c0ed37e110d4de4f4e08b166763c689b417043 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5564.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a87ce1c5a041bc3c4aad98dbb1fce309ec963349", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 61, + "d": 13 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 40, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5566.json b/mne-python/source/doc/sphinxext/prs/5566.json new file mode 100644 index 0000000000000000000000000000000000000000..ad47bbdcd76bb716844192903e84727bb7d09a47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5566.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d331cef343c116fe987ff9c22d9c0f2fc1c9d555", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 10, + "d": 0 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 43, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5569.json b/mne-python/source/doc/sphinxext/prs/5569.json new file mode 100644 index 0000000000000000000000000000000000000000..75045ba099056bcc1533b78a8f9ea815a71ceb9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5569.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fd23ba8bfc1f11dd046abcfa89868f7dd8569d76", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 4, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5570.json b/mne-python/source/doc/sphinxext/prs/5570.json new file mode 100644 index 0000000000000000000000000000000000000000..a1f2e313d12e1f8d5874d22358888a43cfab6073 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5570.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f38ab2e529cb73f91dda31bdd7288b722f5c99b9", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/manual/c_reference.rst": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 9, + "d": 7 + }, + "mne/io/utils.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5572.json b/mne-python/source/doc/sphinxext/prs/5572.json new file mode 100644 index 0000000000000000000000000000000000000000..886edea8f3eca249cfe6b5f6b396e5cdfa094da2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5572.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f02f043312e70e211a1bc9f194f7b2b4ac999a60", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5573.json b/mne-python/source/doc/sphinxext/prs/5573.json new file mode 100644 index 0000000000000000000000000000000000000000..64e52b6873632e143d29bfeef0a1f0300c1e3783 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5573.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f5e6965a89a85098bbd389bb6fc9c90e78e192d3", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/edf/tests/test_edf.py": { + "a": 16, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5574.json b/mne-python/source/doc/sphinxext/prs/5574.json new file mode 100644 index 0000000000000000000000000000000000000000..106bf6f8c552b557ad33948a1d7654ae51136f89 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5574.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0ddc0e4175f99105b025d879cf832cf29f25c268", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 6, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 155, + "d": 77 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 68, + "d": 4 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5575.json b/mne-python/source/doc/sphinxext/prs/5575.json new file mode 100644 index 0000000000000000000000000000000000000000..38cd690522f0aeacfffea7c46c018cb49d858a51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5575.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6521476a878ac71e2ffd27a701f3fd88595fd823", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 2, + "d": 3 + }, + "mne/utils.py": { + "a": 13, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 8, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5576.json b/mne-python/source/doc/sphinxext/prs/5576.json new file mode 100644 index 0000000000000000000000000000000000000000..c394b8abc6cf812ad93133a78a219c0ee2edbc4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5576.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "30d67493fb9231b3277d8470e006636e62084cc2", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/manual/c_reference.rst": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 16, + "d": 16 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/558.json b/mne-python/source/doc/sphinxext/prs/558.json new file mode 100644 index 0000000000000000000000000000000000000000..29f9fe8cd73e43b07b9ba63e4832fb604b07a9cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/558.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0eed1ff1033b5614726a769a2ca0ed94569798ab", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 5, + "d": 1 + }, + "mne/connectivity/tests/test_effective.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5580.json b/mne-python/source/doc/sphinxext/prs/5580.json new file mode 100644 index 0000000000000000000000000000000000000000..2cabac0b036e0585a4441339de9a69383cbd560d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5580.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "462695d5fbfcce6eed853dff6025076c7f616353", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 29, + "d": 15 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 41, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5581.json b/mne-python/source/doc/sphinxext/prs/5581.json new file mode 100644 index 0000000000000000000000000000000000000000..a51fc62dfddb892090091dc7643c77262a8669e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5581.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "46f3fa12d06827d975ba925f183637ad6916eaa8", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 0, + "d": 4 + }, + "mne/channels/interpolation.py": { + "a": 3, + "d": 5 + }, + "mne/cov.py": { + "a": 0, + "d": 8 + }, + "mne/forward/_make_forward.py": { + "a": 0, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 0, + "d": 8 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 20, + "d": 14 + }, + "mne/io/meas_info.py": { + "a": 0, + "d": 6 + }, + "mne/io/pick.py": { + "a": 9, + "d": 15 + }, + "mne/io/tests/test_meas_info.py": { + "a": 5, + "d": 8 + }, + "mne/io/tests/test_pick.py": { + "a": 5, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 11 + }, + "mne/preprocessing/ica.py": { + "a": 12, + "d": 28 + }, + "mne/viz/tests/test_topomap.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5582.json b/mne-python/source/doc/sphinxext/prs/5582.json new file mode 100644 index 0000000000000000000000000000000000000000..90590f3d538499ed8531560d81c21e68349ffeeb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5582.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0db3c5776de04ec2f926295f4a191010efe49c39", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 8, + "d": 8 + }, + "mne/viz/utils.py": { + "a": 19, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5583.json b/mne-python/source/doc/sphinxext/prs/5583.json new file mode 100644 index 0000000000000000000000000000000000000000..fb82bf5f043541dddf0504c7c03c00feb281fe1e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5583.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "28ce1c39503e86f343ac3d4520881019461b2ef6", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 29, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5585.json b/mne-python/source/doc/sphinxext/prs/5585.json new file mode 100644 index 0000000000000000000000000000000000000000..603b4c1012d86c0bbad9fdd7a5926c5ea7f96c6e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5585.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "81a69cc637d7a4aa68a766a1514af14eb0ffa956", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5586.json b/mne-python/source/doc/sphinxext/prs/5586.json new file mode 100644 index 0000000000000000000000000000000000000000..8fbb988bea577bdbfc3f468a963733c5ef753cf8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5586.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a10feadcbacc350c23a79e8c14fa7eec2ebda282", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/egi/egimff.py": { + "a": 28, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5587.json b/mne-python/source/doc/sphinxext/prs/5587.json new file mode 100644 index 0000000000000000000000000000000000000000..ca76f45f701daecca8dbb1b240c99fc631173a3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5587.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "672d66b9f3121ef3ba7f7aba1c6050094c56904c", + "authors": [ + { + "n": "Lorenz Esch", + "e": null + } + ], + "changes": { + "mne/data/coil_def.dat": { + "a": 104, + "d": 91 + }, + "mne/io/constants.py": { + "a": 8, + "d": 4 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5588.json b/mne-python/source/doc/sphinxext/prs/5588.json new file mode 100644 index 0000000000000000000000000000000000000000..88538d6fd426e94164f4c4de2811f1588d455ed6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5588.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e64802326c9ef0b048b785adcee4f4bd26ef268d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 2 + }, + "mne/channels/interpolation.py": { + "a": 7, + "d": 2 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_field_interpolation.py": { + "a": 10, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5589.json b/mne-python/source/doc/sphinxext/prs/5589.json new file mode 100644 index 0000000000000000000000000000000000000000..5fee330d1a9c8cacc03bcc7349c472f3f8ee104d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5589.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "17e1c2906c64e13e1f60213b5422ef7c103eae7c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 7, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 4, + "d": 0 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 110, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 11, + "d": 11 + }, + "mne/beamformer/_lcmv.py": { + "a": 22, + "d": 16 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 19, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 24, + "d": 3 + }, + "mne/utils.py": { + "a": 2, + "d": 0 + }, + "tutorials/plot_dics.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5590.json b/mne-python/source/doc/sphinxext/prs/5590.json new file mode 100644 index 0000000000000000000000000000000000000000..d42b96b5a81963dd31eb6af210394c7e25d7a00d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5590.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6cc5c42657e33ca165bbf9e009b3d9cac57d264e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/morph.py": { + "a": 16, + "d": 7 + }, + "mne/tests/test_morph.py": { + "a": 39, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5591.json b/mne-python/source/doc/sphinxext/prs/5591.json new file mode 100644 index 0000000000000000000000000000000000000000..fed9c1afb4656ee3ecf9d44dedce0a4e6ee5d247 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5591.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b5d4b6b455eeb3da5e2045696607aa5a47e7647b", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 83, + "d": 20 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 28, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5595.json b/mne-python/source/doc/sphinxext/prs/5595.json new file mode 100644 index 0000000000000000000000000000000000000000..edfc55eedafaaa1896bf18f272b8e19541c1b5f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5595.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "168121c49f763187c41f2766c1cd2a1317f30ad3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 26, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 46, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5596.json b/mne-python/source/doc/sphinxext/prs/5596.json new file mode 100644 index 0000000000000000000000000000000000000000..739d2c3217dff3c16641f5354f1dfedf2091786f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5596.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3703da76ac4ba3fb40fa2f248c407ac345046a64", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 7, + "d": 5 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 12, + "d": 17 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 10, + "d": 1 + }, + "mne/utils.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5598.json b/mne-python/source/doc/sphinxext/prs/5598.json new file mode 100644 index 0000000000000000000000000000000000000000..63db1b2122b206f064510ee5f27c0908f667e44b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5598.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f942ab14bbebe13206d76e02c4a5d6232084b36f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/tests/test_constants.py": { + "a": 108, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/56.json b/mne-python/source/doc/sphinxext/prs/56.json new file mode 100644 index 0000000000000000000000000000000000000000..8c791b8218a32feabfdc72083d4f0840812fc1dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/56.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c08bd5f6a40c7b2bc80571659c974a594c000178", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 17, + "d": 9 + }, + "mne/filter.py": { + "a": 69, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5601.json b/mne-python/source/doc/sphinxext/prs/5601.json new file mode 100644 index 0000000000000000000000000000000000000000..e882c316947c231a55956fc4964dd2b0a1ea4481 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5601.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "349636572155eced005e2105962467eabaa63261", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/glossary.rst": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/datasets/plot_opm_data.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 10, + "d": 7 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 18, + "d": 3 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 2 + }, + "tutorials/plot_introduction.py": { + "a": 50, + "d": 54 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5603.json b/mne-python/source/doc/sphinxext/prs/5603.json new file mode 100644 index 0000000000000000000000000000000000000000..a77ff5bd13ead3b3eec72c756cd42e0b0f493bf9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5603.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f3a2a9085fc5a34060d8087f3dc74d71b80f47fe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5606.json b/mne-python/source/doc/sphinxext/prs/5606.json new file mode 100644 index 0000000000000000000000000000000000000000..8f41ddf80552e92b1c06a9fb28e278de62d93035 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5606.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8521fc3cdec5bfb1eb0ff20dd748cb63c4b87b6d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 35, + "d": 12 + }, + "mne/forward/_compute_forward.py": { + "a": 9, + "d": 4 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 16, + "d": 6 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5608.json b/mne-python/source/doc/sphinxext/prs/5608.json new file mode 100644 index 0000000000000000000000000000000000000000..e197f5d8820d5ba706c2968d05546c3faf2a8904 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5608.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "df832f4b9b9ef41d30bf269bb056650e7566b080", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/glossary.rst": { + "a": 3, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 33, + "d": 12 + }, + "mne/tests/test_annotations.py": { + "a": 15, + "d": 0 + }, + "tutorials/plot_object_annotations.py": { + "a": 170, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5609.json b/mne-python/source/doc/sphinxext/prs/5609.json new file mode 100644 index 0000000000000000000000000000000000000000..3eb0ea7d4fef0fdb55f05fabc473e88ab42a07da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5609.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "935866b466da206569cc508c65c003de9a36c65c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 18, + "d": 14 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 13, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/561.json b/mne-python/source/doc/sphinxext/prs/561.json new file mode 100644 index 0000000000000000000000000000000000000000..d64cd3a8cb293d6221400c2abee09cd4e86fabf9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/561.json @@ -0,0 +1,135 @@ +{ + "merge_commit_sha": "999509cb812349be69b1500baa9a716a3bc42ff4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 5, + "d": 0 + }, + "dictionary.txt": { + "a": 4264, + "d": 0 + }, + "doc/source/manual/AppB.rst": { + "a": 1, + "d": 1 + }, + "doc/source/manual/AppReleaseNotes.rst": { + "a": 1, + "d": 1 + }, + "doc/source/manual/analyze.rst": { + "a": 1, + "d": 1 + }, + "doc/source/manual/convert.rst": { + "a": 3, + "d": 3 + }, + "doc/source/manual/forward.rst": { + "a": 2, + "d": 2 + }, + "doc/source/manual/mne.rst": { + "a": 8, + "d": 8 + }, + "doc/source/python_tutorial.rst": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 1, + "d": 1 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 3, + "d": 3 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 1, + "d": 1 + }, + "mne/baseline.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/bti/raw.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/compensator.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/pick.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 3, + "d": 3 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/peak_finder.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/viz.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5610.json b/mne-python/source/doc/sphinxext/prs/5610.json new file mode 100644 index 0000000000000000000000000000000000000000..3504348882ef25fb6795cb933e5efbcb04abe1ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5610.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "66891112791f9441f9e670401c30e109b9c51615", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 16, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5613.json b/mne-python/source/doc/sphinxext/prs/5613.json new file mode 100644 index 0000000000000000000000000000000000000000..6c9dee960677037b535124e98915c27c8b1652e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5613.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9df12aa57dce2a75ba619c90abc6a6547dde9997", + "authors": [ + { + "n": "Tom Dupré la Tour", + "e": null + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/562.json b/mne-python/source/doc/sphinxext/prs/562.json new file mode 100644 index 0000000000000000000000000000000000000000..62f6ccc7d60885e892b6671c800c2733bcd9c9dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/562.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "dc4cb72e6ad8a37b9910fb7fd9ec320861241d0d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 34, + "d": 30 + }, + "mne/fiff/evoked.py": { + "a": 12, + "d": 12 + }, + "mne/fiff/raw.py": { + "a": 10, + "d": 12 + }, + "mne/fiff/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 60, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 13, + "d": 1 + }, + "mne/utils.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5620.json b/mne-python/source/doc/sphinxext/prs/5620.json new file mode 100644 index 0000000000000000000000000000000000000000..beb05cff8daab1795ce7140e26cf05c4734ca2e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5620.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cc3f02e4fa1b0fc827348374462e656f8169d4d5", + "authors": [ + { + "n": "jeythekey", + "e": "44215387+jeythekey@users.noreply.github.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 116, + "d": 57 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5622.json b/mne-python/source/doc/sphinxext/prs/5622.json new file mode 100644 index 0000000000000000000000000000000000000000..d8614138c5fa992a8859c7f6c53813b651cfd429 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5622.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "517d3815a4ff519ecf9d09b9d714e87fa0ae92a8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 2, + "d": 3 + }, + "mne/data/coil_def_Elekta.dat": { + "a": 2, + "d": 6 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 15 + }, + "mne/io/constants.py": { + "a": 0, + "d": 2 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 7 + }, + "mne/preprocessing/maxwell.py": { + "a": 15, + "d": 8 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 53, + "d": 35 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5625.json b/mne-python/source/doc/sphinxext/prs/5625.json new file mode 100644 index 0000000000000000000000000000000000000000..e50bd03034e0f5f71ce40d78c86d148fa4e96281 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5625.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f4096adaf2646da32e6d2f5536e74c14b312ad5f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 35, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5626.json b/mne-python/source/doc/sphinxext/prs/5626.json new file mode 100644 index 0000000000000000000000000000000000000000..56f81e19c48277d389c7165cba97f6cfbded44ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5626.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6ec77282ce7e1d5b74d96eb44daa6e1287eadd09", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 11, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5628.json b/mne-python/source/doc/sphinxext/prs/5628.json new file mode 100644 index 0000000000000000000000000000000000000000..615ddddd90332a5b813d8b56380821d029d48ab8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5628.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "46585fb139a15d024941eb24273f7a0ab097515c", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/manual/datasets_index.rst": { + "a": 2, + "d": 3 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 4, + "d": 3 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5633.json b/mne-python/source/doc/sphinxext/prs/5633.json new file mode 100644 index 0000000000000000000000000000000000000000..9b95a581f1ff3a20a0d6a2dd64b58e9af72fb5e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5633.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "628b9c8ee2ae8d2912ed9a283ccb149d98084afc", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/base.py": { + "a": 37, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 26, + "d": 13 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 15, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 16, + "d": 7 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 15, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 55, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 16, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 36, + "d": 2 + }, + "mne/io/tests/test_utils.py": { + "a": 19, + "d": 0 + }, + "mne/io/utils.py": { + "a": 48, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5634.json b/mne-python/source/doc/sphinxext/prs/5634.json new file mode 100644 index 0000000000000000000000000000000000000000..5a4b85588c85cc7b572e806571f48c062420172f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5634.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4c670aae28eb83ed1feb67525eb2b67f81b3b1f7", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 3, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 10, + "d": 11 + }, + "mne/viz/tests/test_evoked.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5638.json b/mne-python/source/doc/sphinxext/prs/5638.json new file mode 100644 index 0000000000000000000000000000000000000000..aa0ebd79b7efc56d41aef4ea02590901344bed66 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5638.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2636aa90eb364a41931bfd31b34a03e9fc042b0e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/install_mne_c.rst": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/564.json b/mne-python/source/doc/sphinxext/prs/564.json new file mode 100644 index 0000000000000000000000000000000000000000..36d74243210220bd7eea9891d1a474a8bcd6adb9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/564.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "52a2ce106e89446e4b693e142e2b8fc365750839", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/datasets/megsim/megsim.py": { + "a": 2, + "d": 5 + }, + "mne/datasets/sample/sample.py": { + "a": 5, + "d": 6 + }, + "mne/utils.py": { + "a": 178, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5641.json b/mne-python/source/doc/sphinxext/prs/5641.json new file mode 100644 index 0000000000000000000000000000000000000000..97b470b58607181b02183d9fd2a1d8b885e8e063 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5641.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "7fef2d5eb698b7a2654f1d8535778f294eff815c", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "examples/io/plot_read_proj.py": { + "a": 91, + "d": 0 + }, + "mne/viz/tests/test_utils.py": { + "a": 9, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 52, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 26, + "d": 9 + }, + "tutorials/plot_artifacts_correction_ssp.py": { + "a": 6, + "d": 0 + }, + "tutorials/plot_visualize_raw.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5647.json b/mne-python/source/doc/sphinxext/prs/5647.json new file mode 100644 index 0000000000000000000000000000000000000000..b56196b8b59d162446bb9c5bedcfdabb901246c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5647.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "26cfc8fc85ec44021e251da40e7ac94116c0d982", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5648.json b/mne-python/source/doc/sphinxext/prs/5648.json new file mode 100644 index 0000000000000000000000000000000000000000..050cb063c3906255f1d9cc2d6fc0e63fafc39f48 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5648.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ea3549486711c50b2cc4b7b3b7fc1512f193bcc9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install_mne_python.rst": { + "a": 2, + "d": 2 + }, + "mne/utils.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5649.json b/mne-python/source/doc/sphinxext/prs/5649.json new file mode 100644 index 0000000000000000000000000000000000000000..577829044eeebc01fa72110857142a82923bc485 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5649.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "af89a09629689d1aea2aa64fc9d44c6195cc8561", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 3 + }, + "doc/tutorial_links.inc": { + "a": 1, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 30, + "d": 31 + }, + "mne/viz/topomap.py": { + "a": 12, + "d": 7 + }, + "tutorials/plot_background_statistics.py": { + "a": 28, + "d": 19 + }, + "tutorials/plot_stats_cluster_spatio_temporal.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_stats_cluster_time_frequency.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/565.json b/mne-python/source/doc/sphinxext/prs/565.json new file mode 100644 index 0000000000000000000000000000000000000000..f8684c8c14ee7b500a052e992ec08d8fe3537f1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/565.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "980acf98ced0514224ef4a9e245634fa2c9ac3b5", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/forward.py": { + "a": 3, + "d": 8 + }, + "mne/source_space.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_forward.py": { + "a": 33, + "d": 32 + }, + "mne/tests/test_label.py": { + "a": 6, + "d": 8 + }, + "mne/utils.py": { + "a": 21, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5651.json b/mne-python/source/doc/sphinxext/prs/5651.json new file mode 100644 index 0000000000000000000000000000000000000000..7ed7811956c3903e45e7fdfac313bb07cedb5436 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5651.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6f02d38ff83c0e078707d554054886b513ebb11e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 18, + "d": 4 + }, + "mne/filter.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 20, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5652.json b/mne-python/source/doc/sphinxext/prs/5652.json new file mode 100644 index 0000000000000000000000000000000000000000..21980f44a122ec51b4ac081443d951cc0b791e09 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5652.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bf7eba6bf372b6b5878d59aa0a241edd28a6909d", + "authors": [ + { + "n": "Johan van der Meer", + "e": null + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5656.json b/mne-python/source/doc/sphinxext/prs/5656.json new file mode 100644 index 0000000000000000000000000000000000000000..c8376b8fca16098d3363b7d92a75a522fdbc6cdc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5656.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b9020db166f08093bd24215c7b6a83ed030d1402", + "authors": [ + { + "n": "Antoine Gauthier", + "e": "antoine.gauthier@ensta.fr" + } + ], + "changes": { + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5658.json b/mne-python/source/doc/sphinxext/prs/5658.json new file mode 100644 index 0000000000000000000000000000000000000000..13a1bb58a7fc9d792d86f271f4cf880b3aabe90c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5658.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ce8df3b1a4b2c168e4dd2acddd9b43b8a2d1fb3e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 6 + }, + "tutorials/plot_background_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_background_statistics.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5659.json b/mne-python/source/doc/sphinxext/prs/5659.json new file mode 100644 index 0000000000000000000000000000000000000000..550e61297fde70c7d2f2b0e4cb4ab6606d602688 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5659.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e6ce2be09f57042e895d4affe86c62124a15f140", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 5, + "d": 1 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_import_nesting.py": { + "a": 38, + "d": 2 + }, + "mne/tests/test_report.py": { + "a": 15, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/566.json b/mne-python/source/doc/sphinxext/prs/566.json new file mode 100644 index 0000000000000000000000000000000000000000..71cf5ade379abd74bc19da618ea6ff48a0d9f238 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/566.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bd0b01222875ad0c9b34562f25862a145bc3abe8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 0 + }, + "mne/viz.py": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5663.json b/mne-python/source/doc/sphinxext/prs/5663.json new file mode 100644 index 0000000000000000000000000000000000000000..343c9e1a913121943f473e2bdd769934f509c31f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5663.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a77e2736f48551702ffbb7c79a50a728cfb30d22", + "authors": [ + { + "n": "Antoine Gauthier", + "e": "antoine.gauthier@ensta.fr" + } + ], + "changes": { + "mne/commands/mne_browse_raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5664.json b/mne-python/source/doc/sphinxext/prs/5664.json new file mode 100644 index 0000000000000000000000000000000000000000..9b030e8ff27ce2a01d0ef09cf9e69a9b46a69fa7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5664.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "922d00a893cadbceae932b9c66ce952a2b890661", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 29, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 28, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5666.json b/mne-python/source/doc/sphinxext/prs/5666.json new file mode 100644 index 0000000000000000000000000000000000000000..b2e91d20404f7a16717fe46924b59930d1b77461 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5666.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cd54354f4fc89fce84936ff9b5301d0a0d924d01", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 7, + "d": 2 + }, + "mne/gui/_viewer.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 15, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5667.json b/mne-python/source/doc/sphinxext/prs/5667.json new file mode 100644 index 0000000000000000000000000000000000000000..e4c32ab1eb8f6c9f5b17ae316ab95fb5bf7ae86c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5667.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9eb86b4497125caf28fc1cf6c034ee47ccf3345b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install_mne_c.rst": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5672.json b/mne-python/source/doc/sphinxext/prs/5672.json new file mode 100644 index 0000000000000000000000000000000000000000..8dc59e9ee7f62ce980ba46656956f624821d10ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5672.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e38a5737915032118a11c91abbeb62cdb99c7dd6", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 6 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5676.json b/mne-python/source/doc/sphinxext/prs/5676.json new file mode 100644 index 0000000000000000000000000000000000000000..4279acde07c8857990354d6c47dfb3fb144c4156 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5676.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c47f79914bc98fb042f53823b4f56e9cfe2310cf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "ignore_words.txt": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_montage.py": { + "a": 14, + "d": 6 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5677.json b/mne-python/source/doc/sphinxext/prs/5677.json new file mode 100644 index 0000000000000000000000000000000000000000..7d17319e3f92cc11ab86a0e7c61d7a320f44409d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5677.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "41e308cde25bf3371e179907d117e1b7f072fd2f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "appveyor.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5679.json b/mne-python/source/doc/sphinxext/prs/5679.json new file mode 100644 index 0000000000000000000000000000000000000000..206300cf2c62ac0d0e7a226a3fb5d9c512ddbeab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5679.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b71585bac18f613ea20adf41b5ac98a09a58d98a", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 5, + "d": 0 + }, + "mne/utils.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/568.json b/mne-python/source/doc/sphinxext/prs/568.json new file mode 100644 index 0000000000000000000000000000000000000000..49711f370a1924828b6114c1c6d19e7e099715fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/568.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "425fcf959ede4b61c60cc52bd644dda348cf779e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/open.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5681.json b/mne-python/source/doc/sphinxext/prs/5681.json new file mode 100644 index 0000000000000000000000000000000000000000..4ef38603d6131e1b99526f3e41751ca74e1bb814 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5681.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "944ab2906440e248bae9670807f68a2bdfdcc98b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_opm_data.py": { + "a": 2, + "d": 2 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 2 + }, + "mne/data/helmets/ARTEMIS123.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/surface.py": { + "a": 40, + "d": 8 + }, + "mne/tests/test_surface.py": { + "a": 20, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 11 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5683.json b/mne-python/source/doc/sphinxext/prs/5683.json new file mode 100644 index 0000000000000000000000000000000000000000..9cfa0e9b02645c10c293a02fe380326c33d13fc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5683.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "daa29715cf3e4447eb3267db5a6be28aebfeb890", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/tests/test_interpolation.py": { + "a": 10, + "d": 11 + }, + "mne/cov.py": { + "a": 1, + "d": 2 + }, + "mne/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/forward/_compute_forward.py": { + "a": 27, + "d": 20 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 13, + "d": 10 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/open.py": { + "a": 3, + "d": 3 + }, + "mne/io/pick.py": { + "a": 5, + "d": 0 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 2, + "d": 0 + }, + "mne/surface.py": { + "a": 27, + "d": 33 + }, + "mne/tests/test_coreg.py": { + "a": 12, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 4, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 67, + "d": 64 + }, + "mne/viz/tests/test_topo.py": { + "a": 8, + "d": 0 + }, + "requirements.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5687.json b/mne-python/source/doc/sphinxext/prs/5687.json new file mode 100644 index 0000000000000000000000000000000000000000..6e0901c366b8e5f83c768a71b674674a3c06b93f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5687.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d28e8b5f0eb046c17acf82b8216b0d7c40189684", + "authors": [ + { + "n": "buildqa", + "e": "s1152yb68@contbay.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 3, + "d": 0 + }, + "doc/install_mne_c.rst": { + "a": 51, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5689.json b/mne-python/source/doc/sphinxext/prs/5689.json new file mode 100644 index 0000000000000000000000000000000000000000..04286d6d2cee2b8956f51114729c21663e03ac0f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5689.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8185632046476d0ed14155b78620c922176068eb", + "authors": [ + { + "n": "Marcin Koculak", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5691.json b/mne-python/source/doc/sphinxext/prs/5691.json new file mode 100644 index 0000000000000000000000000000000000000000..2c87594c025a2005ddb2ffde99b37f75a5005adb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5691.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0f9eb55a951ff431f785b984fb8b58893ae1ebfb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/manual/matlab.rst": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 30, + "d": 1 + }, + "mne/io/proj.py": { + "a": 3, + "d": 3 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_constants.py": { + "a": 17, + "d": 3 + }, + "mne/preprocessing/maxwell.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5692.json b/mne-python/source/doc/sphinxext/prs/5692.json new file mode 100644 index 0000000000000000000000000000000000000000..cdf45344295837e199b9ee2ccabecc199c2111e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5692.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7ca50604d73f92ad7cfc6ea20b9b20df3e73efff", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/manual/datasets_index.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_opm_rest_data.py": { + "a": 214, + "d": 0 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5694.json b/mne-python/source/doc/sphinxext/prs/5694.json new file mode 100644 index 0000000000000000000000000000000000000000..6ae2a8bb6076e98491b414db5f74bb8c23e4daec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5694.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f0ef23913f127781d5800e22a6ed8f947d7a6e74", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5695.json b/mne-python/source/doc/sphinxext/prs/5695.json new file mode 100644 index 0000000000000000000000000000000000000000..4076dc43fa59a912b2f6fa07fa788ce3cee9239b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5695.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "ae38e1b7927c8a2e4e3f46025965f0cab2e0b4ff", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 0, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 7, + "d": 3 + }, + "mne/annotations.py": { + "a": 53, + "d": 7 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 4 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 3, + "d": 4 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 26 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/eeglab/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 20, + "d": 8 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 14, + "d": 6 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5696.json b/mne-python/source/doc/sphinxext/prs/5696.json new file mode 100644 index 0000000000000000000000000000000000000000..188234db91674f88b01e3467f7431a7d14231f58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5696.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "49f6131955676e8aec5c9b17c328483a16564276", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 1, + "d": 22 + }, + "mne/viz/tests/test_utils.py": { + "a": 19, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 46, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5697.json b/mne-python/source/doc/sphinxext/prs/5697.json new file mode 100644 index 0000000000000000000000000000000000000000..ca9812c452547c2d8e90068b151125275f91bed7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5697.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a7acc27894df173c295e65eb98ecdb4d670eaa67", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "environment.yml": { + "a": 0, + "d": 1 + }, + "requirements.txt": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5698.json b/mne-python/source/doc/sphinxext/prs/5698.json new file mode 100644 index 0000000000000000000000000000000000000000..b6cb3ea961ffb68da94f95c1dfb13cd2be8979c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5698.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8886f42e8a28d4987849802bc568003c0f44b9e1", + "authors": [ + { + "n": "David Sabbagh", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 0 + }, + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 3, + "d": 3 + }, + "mne/cov.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5699.json b/mne-python/source/doc/sphinxext/prs/5699.json new file mode 100644 index 0000000000000000000000000000000000000000..e058a48113c67cdafeaf1a67a6c45b852ec54b67 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5699.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f2be3438a8f2ea8a2622ec693c7556354485de5a", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 125, + "d": 24 + }, + "mne/tests/test_annotations.py": { + "a": 124, + "d": 1 + }, + "tutorials/plot_object_annotations.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/57.json b/mne-python/source/doc/sphinxext/prs/57.json new file mode 100644 index 0000000000000000000000000000000000000000..fc8b52fd01555856f0c2ad8b4d5c3e303a49044b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/57.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2bca78be7c9834179f1faccd97752fca9fe86344", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/570.json b/mne-python/source/doc/sphinxext/prs/570.json new file mode 100644 index 0000000000000000000000000000000000000000..7308f1e3775f4553602c6c6009cde0fa7245fd01 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/570.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "01cbb6f4113bb069a0e1c61275af8438fef802b9", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/utils.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5700.json b/mne-python/source/doc/sphinxext/prs/5700.json new file mode 100644 index 0000000000000000000000000000000000000000..4e405213a02cfd34f65b65fe4279574334a13c4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5700.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "0483a394f73db39b6ac28bed093aa5b5ec6c38ce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/mtrf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 14, + "d": 6 + }, + "mne/datasets/utils.py": { + "a": 42, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5701.json b/mne-python/source/doc/sphinxext/prs/5701.json new file mode 100644 index 0000000000000000000000000000000000000000..3da7008bfe9db92d0bcc73ecd96720443cce9962 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5701.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "32710eef50fae631c8514bc2dcd3c4fac3f8a074", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5702.json b/mne-python/source/doc/sphinxext/prs/5702.json new file mode 100644 index 0000000000000000000000000000000000000000..b29944611466ec308137e4b27625cb71e60b5a46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5702.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "90ebb365e77e6d34c9b2b92db2ac177f89ee2dc1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 21, + "d": 15 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5705.json b/mne-python/source/doc/sphinxext/prs/5705.json new file mode 100644 index 0000000000000000000000000000000000000000..775f3c4d1c406e4dc8407180ae7ec9fff211211d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5705.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b5dcc7a89d87cca33572478e73c8dc445c47e7f0", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "tutorials/plot_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5707.json b/mne-python/source/doc/sphinxext/prs/5707.json new file mode 100644 index 0000000000000000000000000000000000000000..6fbb5ca2524a102654bf5f02567c4b55a1ec827e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5707.json @@ -0,0 +1,207 @@ +{ + "merge_commit_sha": "908ef204f4110c1b003089d60fd259fa5faaf951", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 1 + }, + ".mailmap": { + "a": 3, + "d": 0 + }, + "doc/Makefile": { + "a": 2, + "d": 8 + }, + "doc/carousel.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 67, + "d": 14 + }, + "doc/contributing.rst": { + "a": 8, + "d": 3 + }, + "doc/documentation.rst": { + "a": 0, + "d": 2 + }, + "doc/manual/channel_interpolation.rst": { + "a": 1, + "d": 5 + }, + "doc/manual/decoding.rst": { + "a": 0, + "d": 200 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 16, + "d": 2 + }, + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 9, + "d": 10 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/plot_megsim_data.py": { + "a": 2, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_space.py": { + "a": 0, + "d": 113 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 13, + "d": 10 + }, + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 2, + "d": 1 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 2, + "d": 1 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 7, + "d": 11 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 7, + "d": 2 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 3, + "d": 2 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 31, + "d": 39 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_and_write_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_otp.py": { + "a": 2, + "d": 2 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 14, + "d": 14 + }, + "examples/visualization/plot_xhemi.py": { + "a": 2, + "d": 1 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 2, + "d": 2 + }, + "mne/connectivity/effective.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/csp.py": { + "a": 9, + "d": 3 + }, + "mne/decoding/transformer.py": { + "a": 7, + "d": 0 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 1, + "d": 2 + }, + "mne/io/proj.py": { + "a": 5, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 3 + }, + "mne/utils.py": { + "a": 13, + "d": 4 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 9, + "d": 9 + }, + "setup.cfg": { + "a": 1, + "d": 0 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_morph_stc.py": { + "a": 0, + "d": 12 + }, + "tutorials/plot_receptive_field.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 313, + "d": 46 + }, + "tutorials/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_visualize_stc.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5710.json b/mne-python/source/doc/sphinxext/prs/5710.json new file mode 100644 index 0000000000000000000000000000000000000000..ee2598437c5b03266c6fc4231cd4bca7abdc5bab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5710.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a399a006b90daaf698bb5ca977dad5e703e5a54", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "tutorials/plot_object_annotations.py": { + "a": 44, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5712.json b/mne-python/source/doc/sphinxext/prs/5712.json new file mode 100644 index 0000000000000000000000000000000000000000..c2d0b8a7720bac51607100bcefbd0cd69428bbd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5712.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "b064e1db4b4aa5aeff09b1853006c58ebdc2ef06", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 29, + "d": 13 + }, + "mne/annotations.py": { + "a": 4, + "d": 2 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 87, + "d": 49 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 51, + "d": 43 + }, + "mne/io/edf/edf.py": { + "a": 31, + "d": 10 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 13, + "d": 5 + }, + "mne/io/eeglab/eeglab.py": { + "a": 85, + "d": 51 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 26, + "d": 18 + }, + "mne/io/utils.py": { + "a": 11, + "d": 0 + }, + "mne/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5713.json b/mne-python/source/doc/sphinxext/prs/5713.json new file mode 100644 index 0000000000000000000000000000000000000000..b9704f7eed1867b33e7022e419cf5d0cd0e8c1df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5713.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "92ba16db1db88831a9a9ce618592943d706bad8a", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 44, + "d": 15 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5714.json b/mne-python/source/doc/sphinxext/prs/5714.json new file mode 100644 index 0000000000000000000000000000000000000000..bd45f38980ec2f58985bead3b2396de8cb23bdc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5714.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9db64d818d48d91da5ec1d790822c72326fcf5e7", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 18, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5715.json b/mne-python/source/doc/sphinxext/prs/5715.json new file mode 100644 index 0000000000000000000000000000000000000000..69dd5e7509b5386615498ff54f7ea846ba6959fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5715.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a6762914cc158cbac298f2a9f257cbb20320918a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "setup.cfg": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5716.json b/mne-python/source/doc/sphinxext/prs/5716.json new file mode 100644 index 0000000000000000000000000000000000000000..859d8ba4a76ba9b8ee01b66cb47d61e838163e0e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5716.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "56511470c630305ef84895ee6e80043dbecfe8e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 3, + "d": 2 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 4, + "d": 2 + }, + "mne/utils.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 25, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5717.json b/mne-python/source/doc/sphinxext/prs/5717.json new file mode 100644 index 0000000000000000000000000000000000000000..3b1677acde82ee9f07499f8a7b7c09942ede599e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5717.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "57272be1d342e1058670ebac0e3ab292deb56767", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5718.json b/mne-python/source/doc/sphinxext/prs/5718.json new file mode 100644 index 0000000000000000000000000000000000000000..61837c2a7a3d58b81b92ac3b646ce3ac0c72d304 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5718.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "b2de2e9a192301e4dfb106cef3963d1283d74024", + "authors": [ + { + "n": "Stanislas Chambon", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 0 + }, + ".gitignore": { + "a": 1, + "d": 0 + }, + ".travis.yml": { + "a": 3, + "d": 3 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/manual/datasets_index.rst": { + "a": 19, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 7, + "d": 0 + }, + "environment.yml": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 3, + "d": 5 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 201, + "d": 0 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 110, + "d": 0 + }, + "mne/datasets/sleep_physionet/age_records.csv": { + "a": 79, + "d": 0 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 107, + "d": 0 + }, + "mne/datasets/sleep_physionet/temazepam_records.csv": { + "a": 23, + "d": 0 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 161, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_utils.py": { + "a": 29, + "d": 4 + }, + "mne/utils.py": { + "a": 38, + "d": 6 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "tutorials/plot_sleep.py": { + "a": 306, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/572.json b/mne-python/source/doc/sphinxext/prs/572.json new file mode 100644 index 0000000000000000000000000000000000000000..43dc921df23b35cb4f6f426444dc927c72efd44a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/572.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8c8867a55faa43ed68b4a0408f17bd9a1d5cc857", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 87, + "d": 39 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5723.json b/mne-python/source/doc/sphinxext/prs/5723.json new file mode 100644 index 0000000000000000000000000000000000000000..ce2981cbb4ad82bd2b334c879a777b4d03b1beea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5723.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5b1ac27c54b280bda065f7741953e829b0f03305", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + "doc/_templates/navbar.html": { + "a": 2, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5724.json b/mne-python/source/doc/sphinxext/prs/5724.json new file mode 100644 index 0000000000000000000000000000000000000000..91af75269a7eb1997794c683fca3f3864d703dbe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5724.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c32f1363ed76be5cd96994c620a4853f52833194", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 4, + "d": 1 + }, + "README.rst": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5725.json b/mne-python/source/doc/sphinxext/prs/5725.json new file mode 100644 index 0000000000000000000000000000000000000000..b0d7c0679e269b9453a20d686794b611a3c85ad8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5725.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "dcc8ccf51e4fe024668d6f5c715b50b67646076b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/datasets/spm_faces_dataset.py": { + "a": 9, + "d": 3 + }, + "examples/decoding/decoding_rsa.py": { + "a": 5, + "d": 2 + }, + "mne/data/helmets/CTF_275.fif.gz": { + "a": 0, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5726.json b/mne-python/source/doc/sphinxext/prs/5726.json new file mode 100644 index 0000000000000000000000000000000000000000..35a3de058b2abb4f6cc0b9b5fae2c3a543d766d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5726.json @@ -0,0 +1,531 @@ +{ + "merge_commit_sha": "d7c8e865fbfe2dc8854956a446005b05a82300c6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".travis.yml": { + "a": 3, + "d": 3 + }, + "README.rst": { + "a": 6, + "d": 6 + }, + "doc/configure_git.rst": { + "a": 2, + "d": 1 + }, + "doc/install_mne_python.rst": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/gen_commands.py": { + "a": 0, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 10, + "d": 11 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 3 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 2 + }, + "mne/bem.py": { + "a": 12, + "d": 13 + }, + "mne/channels/channels.py": { + "a": 5, + "d": 6 + }, + "mne/channels/layout.py": { + "a": 0, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 5, + "d": 8 + }, + "mne/chpi.py": { + "a": 1, + "d": 2 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 0, + "d": 2 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 1, + "d": 4 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 1, + "d": 4 + }, + "mne/commands/mne_flash_bem.py": { + "a": 0, + "d": 2 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 0, + "d": 2 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 0, + "d": 2 + }, + "mne/commands/mne_surf2bem.py": { + "a": 0, + "d": 1 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 0, + "d": 1 + }, + "mne/connectivity/effective.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 2 + }, + "mne/coreg.py": { + "a": 3, + "d": 5 + }, + "mne/cov.py": { + "a": 6, + "d": 8 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/mixin.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 2 + }, + "mne/dipole.py": { + "a": 3, + "d": 4 + }, + "mne/epochs.py": { + "a": 11, + "d": 13 + }, + "mne/event.py": { + "a": 1, + "d": 3 + }, + "mne/evoked.py": { + "a": 2, + "d": 4 + }, + "mne/externals/__init__.py": { + "a": 0, + "d": 6 + }, + "mne/externals/six.py": { + "a": 0, + "d": 577 + }, + "mne/externals/tempita/__init__.py": { + "a": 8, + "d": 8 + }, + "mne/filter.py": { + "a": 9, + "d": 10 + }, + "mne/fixes.py": { + "a": 18, + "d": 579 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 5 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 4 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 0, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_fiducials_gui.py": { + "a": 0, + "d": 1 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 2, + "d": 3 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 0, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 0, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 0, + "d": 2 + }, + "mne/io/base.py": { + "a": 9, + "d": 10 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 3 + }, + "mne/io/bti/bti.py": { + "a": 13, + "d": 13 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 7, + "d": 7 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 11, + "d": 6 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 3 + }, + "mne/io/eeglab/eeglab.py": { + "a": 8, + "d": 9 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 3, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 6, + "d": 7 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 14, + "d": 15 + }, + "mne/io/open.py": { + "a": 5, + "d": 6 + }, + "mne/io/pick.py": { + "a": 2, + "d": 3 + }, + "mne/io/proc_history.py": { + "a": 3, + "d": 5 + }, + "mne/io/proj.py": { + "a": 2, + "d": 3 + }, + "mne/io/tag.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 2 + }, + "mne/io/utils.py": { + "a": 2, + "d": 3 + }, + "mne/io/write.py": { + "a": 4, + "d": 5 + }, + "mne/label.py": { + "a": 14, + "d": 16 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 3, + "d": 6 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 2 + }, + "mne/morph.py": { + "a": 3, + "d": 4 + }, + "mne/parallel.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 8 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/maxwell.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 5, + "d": 6 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/xdawn.py": { + "a": 2, + "d": 3 + }, + "mne/realtime/client.py": { + "a": 1, + "d": 3 + }, + "mne/realtime/stim_server_client.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 5, + "d": 5 + }, + "mne/realtime/tests/test_stim_client_server.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/raw.py": { + "a": 3, + "d": 4 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 3 + }, + "mne/source_space.py": { + "a": 7, + "d": 8 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 2 + }, + "mne/stats/parametric.py": { + "a": 3, + "d": 4 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 2 + }, + "mne/surface.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_fixes.py": { + "a": 2, + "d": 17 + }, + "mne/tests/test_import_nesting.py": { + "a": 0, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_source_space.py": { + "a": 0, + "d": 3 + }, + "mne/tests/test_surface.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 2 + }, + "mne/transforms.py": { + "a": 7, + "d": 8 + }, + "mne/utils.py": { + "a": 20, + "d": 18 + }, + "mne/viz/_3d.py": { + "a": 11, + "d": 12 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 4 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 8, + "d": 10 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 3 + }, + "mne/viz/misc.py": { + "a": 3, + "d": 6 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 0, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 5, + "d": 7 + }, + "setup.cfg": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5727.json b/mne-python/source/doc/sphinxext/prs/5727.json new file mode 100644 index 0000000000000000000000000000000000000000..1c5872e2a6c6af0b51e7f07eb03e722b8eccd142 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5727.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "531cb0afaa0313c51fef555a3bc377b0df11585c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_kit2fiff_gui.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5729.json b/mne-python/source/doc/sphinxext/prs/5729.json new file mode 100644 index 0000000000000000000000000000000000000000..ac2fcc69559153bb3f1a672a2bf6e15a9fea4a39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5729.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9220f501dae4ae5eef25ebeadea51be96df890c3", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "AUTHORS.rst": { + "a": 0, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/573.json b/mne-python/source/doc/sphinxext/prs/573.json new file mode 100644 index 0000000000000000000000000000000000000000..173e75b29230b3eec5fe8122b5a3a4a1e6b8dd43 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/573.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "196f09fffd30c3b0748c49aae8599ccb319c26ab", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "setup.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5730.json b/mne-python/source/doc/sphinxext/prs/5730.json new file mode 100644 index 0000000000000000000000000000000000000000..95d200c099f329e49a16ba991c771ba1bb9f3edf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5730.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2a9a0261d1fc27f1972efed13ed7287e9906ac7b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_parcellation.py": { + "a": 17, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 36, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 40, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5733.json b/mne-python/source/doc/sphinxext/prs/5733.json new file mode 100644 index 0000000000000000000000000000000000000000..466f7ca1453dcce7383e69dc91a166fccd789bbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5733.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "ac2157d7ff204cfc81771dafd195310ef1e10bd1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 2, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 5, + "d": 7 + }, + "mne/cov.py": { + "a": 165, + "d": 163 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/io/base.py": { + "a": 2, + "d": 22 + }, + "mne/io/brainvision/brainvision.py": { + "a": 18, + "d": 275 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 18, + "d": 234 + }, + "mne/io/eeglab/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 17, + "d": 313 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 16, + "d": 112 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 24 + }, + "mne/io/utils.py": { + "a": 3, + "d": 8 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 4, + "d": 5 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 11 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 3 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 0, + "d": 224 + }, + "mne/stats/parametric.py": { + "a": 1, + "d": 9 + }, + "mne/tests/test_cov.py": { + "a": 41, + "d": 40 + }, + "mne/tests/test_morph.py": { + "a": 5, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/574.json b/mne-python/source/doc/sphinxext/prs/574.json new file mode 100644 index 0000000000000000000000000000000000000000..5e1f260a74a3059a273b0c253e7fdaa7f8e832ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/574.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f91a3e163c052ad2714037f223794ab6c24d1fd2", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 155, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5741.json b/mne-python/source/doc/sphinxext/prs/5741.json new file mode 100644 index 0000000000000000000000000000000000000000..611103a67460afb9332b6346268aa0d01e5c74c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5741.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f85de59c9e052e6282c23aeb1f71fc2847ba84cd", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 167, + "d": 339 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 115, + "d": 259 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 10, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5742.json b/mne-python/source/doc/sphinxext/prs/5742.json new file mode 100644 index 0000000000000000000000000000000000000000..060e5b6930f3e0f2925f321efb334ebb4504225c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5742.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e4ed5fd91c93a69a7d34e9d304a2fc06494f9099", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/tutorials/philosophy.rst": { + "a": 11, + "d": 11 + }, + "tutorials/plot_creating_data_structures.py": { + "a": 12, + "d": 12 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_info.py": { + "a": 3, + "d": 5 + }, + "tutorials/plot_object_raw.py": { + "a": 19, + "d": 21 + }, + "tutorials/plot_point_spread.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5743.json b/mne-python/source/doc/sphinxext/prs/5743.json new file mode 100644 index 0000000000000000000000000000000000000000..8f5832df5f559c23664b9f1e5d192f4857ccffef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5743.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7ddeded7213f0f23707382eb1455f761f4a50957", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/contributing.rst": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5747.json b/mne-python/source/doc/sphinxext/prs/5747.json new file mode 100644 index 0000000000000000000000000000000000000000..5c9616bb8f55692416499baaecb0be575d02363d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5747.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "400f5389c8dbaafa97e0c8f0c66c4d38b7720a60", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/io/fiff/raw.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5748.json b/mne-python/source/doc/sphinxext/prs/5748.json new file mode 100644 index 0000000000000000000000000000000000000000..b909a685fa4510f6e07fa97a75c65f7ec4b81aba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5748.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3bd81a08f2ba4a837d5a078c5b666d15a0434fc1", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 34, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/575.json b/mne-python/source/doc/sphinxext/prs/575.json new file mode 100644 index 0000000000000000000000000000000000000000..e0243ba06e9dc9bc3957c7b00d5334f7b0656b06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/575.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6bd182407fda06e7bfe24d76b46dfb4046243311", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/layouts/layout.py": { + "a": 26, + "d": 0 + }, + "mne/viz.py": { + "a": 19, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5752.json b/mne-python/source/doc/sphinxext/prs/5752.json new file mode 100644 index 0000000000000000000000000000000000000000..e1d7383fd7016eb58701dc9b5ef328a31d15dfb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5752.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d5c52ec6d978be1c6c011884b7fa17134a5ae698", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5754.json b/mne-python/source/doc/sphinxext/prs/5754.json new file mode 100644 index 0000000000000000000000000000000000000000..0e37b7d704c2aed209e54f791be5442ee4e1d2da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5754.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "ef1929f4f71d1cef78eab43e67a79a2ce8f7a736", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 70, + "d": 14 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 18, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 19, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 175, + "d": 43 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 10, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5756.json b/mne-python/source/doc/sphinxext/prs/5756.json new file mode 100644 index 0000000000000000000000000000000000000000..74bbbbb06a037136cd3242e8bff47b81c701f336 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5756.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "8dc6485155f3571325a9f1cde3299cd2288ecf8e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 4 + }, + "appveyor.yml": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/gen_commands.py": { + "a": 4, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 84, + "d": 72 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 28, + "d": 24 + }, + "mne/commands/mne_flash_bem.py": { + "a": 7, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 29, + "d": 12 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 1, + "d": 0 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_import_nesting.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_source_space.py": { + "a": 2, + "d": 0 + }, + "requirements.txt": { + "a": 2, + "d": 0 + }, + "setup.cfg": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5762.json b/mne-python/source/doc/sphinxext/prs/5762.json new file mode 100644 index 0000000000000000000000000000000000000000..3544306ccf7a26cbe5947b88d342dc069f8b3f76 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5762.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "87c0563c86677be75fc23f3e372492a5c9b3ce9d", + "authors": [ + { + "n": "Keith Doelling", + "e": "keith.doelling@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 14, + "d": 11 + }, + "mne/epochs.py": { + "a": 2, + "d": 346 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 64, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 38, + "d": 29 + }, + "mne/utils.py": { + "a": 354, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5765.json b/mne-python/source/doc/sphinxext/prs/5765.json new file mode 100644 index 0000000000000000000000000000000000000000..ebc26869c623dc432cd6df3799167af62a89a6e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5765.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "71551ea8d0e5568473fa0865aaf0f46b0780476f", + "authors": [ + { + "n": "David Haslacher", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 8, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5768.json b/mne-python/source/doc/sphinxext/prs/5768.json new file mode 100644 index 0000000000000000000000000000000000000000..fdef6faa93da4d60f9e9e12cc9367c719da6e69d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5768.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d23e624ced15b9314b11199a42b39a33863aa03e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/contributing.rst": { + "a": 29, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/577.json b/mne-python/source/doc/sphinxext/prs/577.json new file mode 100644 index 0000000000000000000000000000000000000000..bbd8b1c4c3fba33fc30f6e7ab78c288b0508f60e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/577.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "da9bf190a491c426daf40c599fbf9943e1f29cca", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5770.json b/mne-python/source/doc/sphinxext/prs/5770.json new file mode 100644 index 0000000000000000000000000000000000000000..1e3430e1ac3e7cf9ec7727e62416973008e8b31e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5770.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f830351301282f2e350ae600046a2f6169a96927", + "authors": [ + { + "n": "Cristóbal Moënne-Loccoz", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5774.json b/mne-python/source/doc/sphinxext/prs/5774.json new file mode 100644 index 0000000000000000000000000000000000000000..4a8e51de5c0efe8e45b5a06344781359489c2932 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5774.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e96d706b65b6c6a21821d3dcbc06e10903e9c05b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_coreg.py": { + "a": 6, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 12, + "d": 3 + }, + "mne/gui/_coreg_gui.py": { + "a": 36, + "d": 8 + }, + "mne/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5775.json b/mne-python/source/doc/sphinxext/prs/5775.json new file mode 100644 index 0000000000000000000000000000000000000000..b4c0f30419ca3e366ae9961a3ad931aee59337a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5775.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b5860aa43569acaa59368605fa1ae4988ad027ea", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 4, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 2 + }, + "mne/utils.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5776.json b/mne-python/source/doc/sphinxext/prs/5776.json new file mode 100644 index 0000000000000000000000000000000000000000..eb25ad0a043adf20b035ecc81dd20e9ec78c80e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5776.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "48aa54ad3277b58afdec20b7bcba603f0abdbddb", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 4, + "d": 2 + }, + "doc/glossary.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/appendix/bem_model.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/appendix/c_EULA.rst": { + "a": 2, + "d": 1 + }, + "doc/manual/appendix/c_misc.rst": { + "a": 2, + "d": 0 + }, + "doc/manual/appendix/c_release_notes.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/c_reference.rst": { + "a": 60, + "d": 58 + }, + "doc/manual/cookbook.rst": { + "a": 12, + "d": 6 + }, + "doc/manual/gui/analyze.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/gui/browse.rst": { + "a": 3, + "d": 3 + }, + "doc/manual/io.rst": { + "a": 2, + "d": 2 + }, + "doc/manual/matlab.rst": { + "a": 5, + "d": 4 + }, + "doc/manual/sample_dataset.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/source_localization/c_forward.rst": { + "a": 891, + "d": 0 + }, + "doc/manual/source_localization/c_inverse.rst": { + "a": 535, + "d": 0 + }, + "doc/manual/source_localization/c_morph.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/source_localization/coil_geometries.rst": { + "a": 266, + "d": 0 + }, + "doc/manual/source_localization/forward.rst": { + "a": 59, + "d": 516 + }, + "doc/manual/source_localization/inverse.rst": { + "a": 45, + "d": 140 + }, + "doc/manual/source_localization/morph_stc.rst": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 7, + "d": 0 + }, + "tutorials/plot_background_freesurfer.py": { + "a": 2, + "d": 3 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_ctf.py": { + "a": 6, + "d": 2 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 5, + "d": 3 + }, + "tutorials/plot_compute_covariance.py": { + "a": 4, + "d": 2 + }, + "tutorials/plot_dipole_orientations.py": { + "a": 8, + "d": 0 + }, + "tutorials/plot_forward.py": { + "a": 23, + "d": 6 + }, + "tutorials/plot_object_source_estimate.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_source_alignment.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5777.json b/mne-python/source/doc/sphinxext/prs/5777.json new file mode 100644 index 0000000000000000000000000000000000000000..cc513f7b2c7443905f40bda3be8b9397505da761 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5777.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4b4e0630a6cf8577b16f66e62c544226c92ae232", + "authors": [ + { + "n": "Simon Kern", + "e": null + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/578.json b/mne-python/source/doc/sphinxext/prs/578.json new file mode 100644 index 0000000000000000000000000000000000000000..31e1b1c79d6f333aa909ddd05e22e4f3048bd41a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/578.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "9cc08caf7878ac52d0f528fc350c513a68b26845", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 4, + "d": 3 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 1 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 66, + "d": 0 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/__init__.py": { + "a": 8, + "d": 0 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 304, + "d": 0 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 10, + "d": 4 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 51, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/mixed_norm/__init__.py": { + "a": 5, + "d": 5 + }, + "mne/viz.py": { + "a": 6, + "d": 2 + }, + "setup.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5780.json b/mne-python/source/doc/sphinxext/prs/5780.json new file mode 100644 index 0000000000000000000000000000000000000000..cc9455a94c431dae45dd1317edfe6322282abaf8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5780.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "aea196ef6dcf43dbda5ca16d40704eed9b0db1ee", + "authors": [ + { + "n": "Cristóbal Moënne-Loccoz", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/reference.py": { + "a": 9, + "d": 9 + }, + "mne/io/tests/test_reference.py": { + "a": 47, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5783.json b/mne-python/source/doc/sphinxext/prs/5783.json new file mode 100644 index 0000000000000000000000000000000000000000..a89e708d6e7990319d5b8c41d43026bc5d608bc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5783.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "857de6e1c1e66f1f8b7adad0d98529ab744d6313", + "authors": [ + { + "n": "Jon Houck", + "e": null + } + ], + "changes": { + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 10, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5786.json b/mne-python/source/doc/sphinxext/prs/5786.json new file mode 100644 index 0000000000000000000000000000000000000000..8cc4fe499a72a7772dd983c36a2b1a78c1939e8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5786.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "91bf597e0f18259f25d0969a2f0956b17c3d8889", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5787.json b/mne-python/source/doc/sphinxext/prs/5787.json new file mode 100644 index 0000000000000000000000000000000000000000..46df346e89b4545dd134fa534cbb269b8b5f202a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5787.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "05afda7778f1746030785dccb9f86be5279c8613", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".travis.yml": { + "a": 1, + "d": 1 + }, + "appveyor.yml": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 2 + }, + "requirements.txt": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5788.json b/mne-python/source/doc/sphinxext/prs/5788.json new file mode 100644 index 0000000000000000000000000000000000000000..7bbf445dc32886f41a127e177be969590d77e528 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5788.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "fa91217b895957c4106d6175e27d72a48f4f05dc", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 5, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 36, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/579.json b/mne-python/source/doc/sphinxext/prs/579.json new file mode 100644 index 0000000000000000000000000000000000000000..ac196d60a1dccfb34573b497f0dec28569ecaa5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/579.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "025bc08e7bcf283f780b794c69d1033a15926016", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 28, + "d": 31 + }, + "mne/fiff/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 4, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 5, + "d": 1 + }, + "mne/viz.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5791.json b/mne-python/source/doc/sphinxext/prs/5791.json new file mode 100644 index 0000000000000000000000000000000000000000..c9bb48bc0d3f81644ec005c263d3463664af4d4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5791.json @@ -0,0 +1,147 @@ +{ + "merge_commit_sha": "382205d1f2074987b2540464b83d90f4785fc6cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 175, + "d": 63 + }, + "doc/Makefile": { + "a": 6, + "d": 6 + }, + "doc/conf.py": { + "a": 9, + "d": 3 + }, + "doc/contributing.rst": { + "a": 2, + "d": 2 + }, + "doc/documentation.rst": { + "a": 1, + "d": 1 + }, + "doc/faq.rst": { + "a": 6, + "d": 6 + }, + "doc/git_links.inc": { + "a": 9, + "d": 9 + }, + "doc/install_mne_c.rst": { + "a": 6, + "d": 6 + }, + "doc/known_projects.inc": { + "a": 3, + "d": 3 + }, + "doc/manual/appendix/bem_model.rst": { + "a": 1, + "d": 1 + }, + "doc/manual/datasets_index.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/io.rst": { + "a": 2, + "d": 2 + }, + "doc/mne_cpp.rst": { + "a": 19, + "d": 19 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 2 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_receptive_field_mtrf.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 2 + }, + "mne/stats/parametric.py": { + "a": 0, + "d": 1 + }, + "tutorials/plot_background_filtering.py": { + "a": 15, + "d": 13 + }, + "tutorials/plot_brainstorm_auditory.py": { + "a": 3, + "d": 2 + }, + "tutorials/plot_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_python_intro.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 5, + "d": 5 + }, + "tutorials/plot_source_alignment.py": { + "a": 4, + "d": 3 + }, + "tutorials/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5793.json b/mne-python/source/doc/sphinxext/prs/5793.json new file mode 100644 index 0000000000000000000000000000000000000000..7e58e2f4b5601fe94118156362b2f9a90b236847 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5793.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "92e8becbc2afedaf0ffde3d6933e042396d7eb73", + "authors": [ + { + "n": "Chris Holdgraf", + "e": null + } + ], + "changes": { + "logo/logo_hex.svg": { + "a": 189, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5795.json b/mne-python/source/doc/sphinxext/prs/5795.json new file mode 100644 index 0000000000000000000000000000000000000000..2d20a6026d1c62e33086109b79f1ec4531846cb5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5795.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e3ef29e667391e6977ea6b0e0861893e91054d95", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/annotations.py": { + "a": 71, + "d": 40 + }, + "mne/tests/test_annotations.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5796.json b/mne-python/source/doc/sphinxext/prs/5796.json new file mode 100644 index 0000000000000000000000000000000000000000..8466755147f8571477d3adb11be30a4502c82f35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5796.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "76ccce401f9efaf1b9f40bfe487ea04ea0486d4f", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "tutorials/plot_object_evoked.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5799.json b/mne-python/source/doc/sphinxext/prs/5799.json new file mode 100644 index 0000000000000000000000000000000000000000..d9182fd3b66dd0b2e32bb2666e6256f91fc89a0e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5799.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "58bc99fc1704a4654198b05ff19110b9f9252189", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 3, + "d": 5 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 3, + "d": 5 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/58.json b/mne-python/source/doc/sphinxext/prs/58.json new file mode 100644 index 0000000000000000000000000000000000000000..d0752c5e670d91347504c5c33f9c0529541e68be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/58.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6778ce339d577988f25d96360c3b7950a60c508c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 2, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 38, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/580.json b/mne-python/source/doc/sphinxext/prs/580.json new file mode 100644 index 0000000000000000000000000000000000000000..fc03d1e8903cd1c6aa3f3cd47416ecfb8990f4ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/580.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "947bf7d8d1ea065458f81c94f6ea5382354b7259", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 3, + "d": 3 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 280, + "d": 0 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 223, + "d": 0 + }, + "mne/stats/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 7, + "d": 0 + }, + "mne/stats/parametric.py": { + "a": 171, + "d": 1 + }, + "mne/stats/tests/test_parametric.py": { + "a": 68, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5800.json b/mne-python/source/doc/sphinxext/prs/5800.json new file mode 100644 index 0000000000000000000000000000000000000000..076c4353ccba7b001eac205559ce68b5963e28b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5800.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e2c538b923cb05be626419ddcca3b112d7306d51", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 24, + "d": 8 + }, + "mne/tests/test_annotations.py": { + "a": 68, + "d": 0 + }, + "tutorials/plot_object_annotations.py": { + "a": 59, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5801.json b/mne-python/source/doc/sphinxext/prs/5801.json new file mode 100644 index 0000000000000000000000000000000000000000..547451487826c97ea9519684ca1ceda8a107484f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5801.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3c0fdee5e71f5a6004c0093493c7c576753040a8", + "authors": [ + { + "n": "Keith Doelling", + "e": "keith.doelling@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 9, + "d": 37 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 22, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 19, + "d": 5 + }, + "mne/utils.py": { + "a": 53, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5804.json b/mne-python/source/doc/sphinxext/prs/5804.json new file mode 100644 index 0000000000000000000000000000000000000000..8e45bd4833ad38adde3bc7eeb3fc0a9ccec043b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5804.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "10209218a4e169453f4d9eeadd1cb8a37a80c5a4", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/faq.rst": { + "a": 11, + "d": 11 + }, + "doc/glossary.rst": { + "a": 42, + "d": 35 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 7, + "d": 7 + }, + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/plot_object_evoked.py": { + "a": 3, + "d": 2 + }, + "tutorials/source-modeling/plot_compute_covariance.py": { + "a": 10, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5805.json b/mne-python/source/doc/sphinxext/prs/5805.json new file mode 100644 index 0000000000000000000000000000000000000000..243b3dcad136894383cf6f6f3b45f594e4653ff5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5805.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "d4c24cb24cde540572d93f9541ee0c5f4f16a728", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 6, + "d": 1 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/event.py": { + "a": 12, + "d": 2 + }, + "mne/fixes.py": { + "a": 60, + "d": 0 + }, + "mne/label.py": { + "a": 183, + "d": 19 + }, + "mne/source_estimate.py": { + "a": 27, + "d": 38 + }, + "mne/tests/test_event.py": { + "a": 11, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 53, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5807.json b/mne-python/source/doc/sphinxext/prs/5807.json new file mode 100644 index 0000000000000000000000000000000000000000..4fce2630c8360a7138ea80cd0d8bea6e0e837152 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5807.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "49fd91882f52130ff66c613c2178bf7d981d1bd5", + "authors": [ + { + "n": "Jevri Hanna", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 170, + "d": 58 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 25, + "d": 10 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5808.json b/mne-python/source/doc/sphinxext/prs/5808.json new file mode 100644 index 0000000000000000000000000000000000000000..82d8faf6761b4c15f0b453169d645e610cff57b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5808.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6a40c41fb83d9b912eea1bfe363a383f0ef8f1c7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 4, + "d": 2 + }, + "mne/fixes.py": { + "a": 156, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 7, + "d": 139 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5809.json b/mne-python/source/doc/sphinxext/prs/5809.json new file mode 100644 index 0000000000000000000000000000000000000000..f9a504195c133b9989c3d35e7c486d40a0e1a565 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5809.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0ef0ffdc2aa91fe2028d3e922553c039d80dbd19", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/externals/pymatreader/utils.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/581.json b/mne-python/source/doc/sphinxext/prs/581.json new file mode 100644 index 0000000000000000000000000000000000000000..e2c6d996c7fded8d515d53b3fda62c792783000a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/581.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5ae3e54dfb403d8d3954d297d23f6df061f37a23", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 25, + "d": 12 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 5, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 95, + "d": 9 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 24, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5810.json b/mne-python/source/doc/sphinxext/prs/5810.json new file mode 100644 index 0000000000000000000000000000000000000000..8dbc50d02a8d89d19eb832957697ee0144b98fc3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5810.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "abe827fa9dd5334ec0dc7cc70d8381d7efd3881c", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 7, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5811.json b/mne-python/source/doc/sphinxext/prs/5811.json new file mode 100644 index 0000000000000000000000000000000000000000..bb3e3edb4a0576903f20339f55b3d671b491bc9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5811.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "1532f98616ec875a2414b2631b0b8f7bc5e4b693", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "conftest.py": { + "a": 20, + "d": 0 + }, + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 3 + }, + "mne/commands/tests/test_commands.py": { + "a": 0, + "d": 3 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 23, + "d": 25 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 4 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 48, + "d": 38 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 6 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 1, + "d": 5 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 0, + "d": 4 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_import_nesting.py": { + "a": 0, + "d": 45 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 6 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 3, + "d": 8 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 7 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 5 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 9 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 10 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 11 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 11 + }, + "mne/viz/tests/test_montage.py": { + "a": 1, + "d": 5 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 10 + }, + "mne/viz/tests/test_topo.py": { + "a": 2, + "d": 10 + }, + "mne/viz/tests/test_topomap.py": { + "a": 10, + "d": 16 + }, + "mne/viz/tests/test_utils.py": { + "a": 2, + "d": 9 + }, + "setup.cfg": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5813.json b/mne-python/source/doc/sphinxext/prs/5813.json new file mode 100644 index 0000000000000000000000000000000000000000..f2e3e64e76cc040e219dd032c0a40d2a9b21da0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5813.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "feb0bec3acf334ee391711109c9a541697813a30", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/autosummary/class.rst": { + "a": 0, + "d": 0 + }, + "doc/_templates/autosummary/function.rst": { + "a": 0, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/glossary.rst": { + "a": 11, + "d": 11 + }, + "doc/python_reference.rst": { + "a": 21, + "d": 144 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5814.json b/mne-python/source/doc/sphinxext/prs/5814.json new file mode 100644 index 0000000000000000000000000000000000000000..4d1e26ef1c64ca217fa3f07399c69ff974af0ee6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5814.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fd2e3d23bb41dce572d948f42a2e2990fb0e31e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/inverse_sparse/mxne_optim.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5819.json b/mne-python/source/doc/sphinxext/prs/5819.json new file mode 100644 index 0000000000000000000000000000000000000000..a0928fae965846a62b71fd231053a8adfcb392c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5819.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b535a53711fe1efb954ec81e6d94c4ceb768a686", + "authors": [ + { + "n": "Antoine Gauthier", + "e": "antoine.gauthier@ensta.fr" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 5, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 85, + "d": 9 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/582.json b/mne-python/source/doc/sphinxext/prs/582.json new file mode 100644 index 0000000000000000000000000000000000000000..7b7e78bc3051cc2099a935bab733fe9a9e957d75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/582.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "34a4c873dac6e7da730ef6cf239a06cf4b2bbfc9", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 11, + "d": 5 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5821.json b/mne-python/source/doc/sphinxext/prs/5821.json new file mode 100644 index 0000000000000000000000000000000000000000..4b52808b6df0c01986f86d17b9ae23dfd298c128 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5821.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b2b551274071f8b21fe2906631488b161c9aa312", + "authors": [ + { + "n": "Larry Eisenman", + "e": "leisenman@wustl.edu" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 7, + "d": 2 + }, + "mne/io/edf/tests/data/duplicate_channel_labels.edf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 12, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 32, + "d": 16 + }, + "mne/io/tests/test_meas_info.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5822.json b/mne-python/source/doc/sphinxext/prs/5822.json new file mode 100644 index 0000000000000000000000000000000000000000..8c18a13b35d18627f3844a031bae5fe84eb5cfae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5822.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "78561338b1ffe376455e8a1324f55e2833979ce1", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_fiducials_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_viewer.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 80, + "d": 202 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 441, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 62, + "d": 0 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 91, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 12, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5823.json b/mne-python/source/doc/sphinxext/prs/5823.json new file mode 100644 index 0000000000000000000000000000000000000000..266f3b87b2215c2029c4cef59525226a0d3cc1c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5823.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "68410a1468b7fa5d72ec631a844a1b448caf8223", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "mne/externals/pymatreader/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5824.json b/mne-python/source/doc/sphinxext/prs/5824.json new file mode 100644 index 0000000000000000000000000000000000000000..6a1c36163f0eccfb712e6cd6fc71d9c9b77bdf3f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5824.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d97fcc0c98981c8c36a81cd995ac2746632d14ee", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 34, + "d": 15 + }, + "mne/io/tests/test_raw.py": { + "a": 25, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5825.json b/mne-python/source/doc/sphinxext/prs/5825.json new file mode 100644 index 0000000000000000000000000000000000000000..3dc3bafd0d47c1efca014c5ffd17d4b70aaffad4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5825.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "41fc42be6a229c7d41d2be59850fa4ba66a194f9", + "authors": [ + { + "n": "Burkhard Maess", + "e": null + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5827.json b/mne-python/source/doc/sphinxext/prs/5827.json new file mode 100644 index 0000000000000000000000000000000000000000..041791b000ad807a418cbb551789dc70d4c6488b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5827.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "25dd447f892a89fc5ba220ebf9fa10bfb532a7f4", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 7, + "d": 2 + }, + "mne/io/edf/tests/data/duplicate_channel_labels.edf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 13, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 32, + "d": 16 + }, + "mne/io/tests/test_meas_info.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5828.json b/mne-python/source/doc/sphinxext/prs/5828.json new file mode 100644 index 0000000000000000000000000000000000000000..68fed45341036c1fcafe16a291b45eaf63a5ea56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5828.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "57091f02565402b2b7ba132ee7afe2b05f4647fc", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5829.json b/mne-python/source/doc/sphinxext/prs/5829.json new file mode 100644 index 0000000000000000000000000000000000000000..5695dcf895756405fb0071170cc245f32ef337e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5829.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e0588eedc173902a9b55dfe6436ea433c19bbf30", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "tutorials/plot_eeg_erp.py": { + "a": 8, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/583.json b/mne-python/source/doc/sphinxext/prs/583.json new file mode 100644 index 0000000000000000000000000000000000000000..88c235e4cfea083649b97118d7cab001ea9fbc3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/583.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "67be230abb59dfe592bd560df537b7271b594c5b", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "mne/simulation/source.py": { + "a": 23, + "d": 17 + }, + "mne/simulation/tests/test_source.py": { + "a": 96, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5831.json b/mne-python/source/doc/sphinxext/prs/5831.json new file mode 100644 index 0000000000000000000000000000000000000000..3104edcddf8d1f92d9e311cd522ca45bf2006e42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5831.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d7866514ffa4aa2e35f9989fa67262defe7588f5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 6, + "d": 6 + }, + "conftest.py": { + "a": 18, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 4, + "d": 3 + }, + "mne/utils.py": { + "a": 0, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "setup.cfg": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5832.json b/mne-python/source/doc/sphinxext/prs/5832.json new file mode 100644 index 0000000000000000000000000000000000000000..7e85aa70f8827e26b8208961f098d390dfe2d615 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5832.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "78e9e728619193e5a41e4218bf39c12d2e130a90", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "mne/externals/pymatreader/utils.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5835.json b/mne-python/source/doc/sphinxext/prs/5835.json new file mode 100644 index 0000000000000000000000000000000000000000..70cbeca36fd789ba0d543b7428b82fcab88b3802 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5835.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6a35cd65ede14f493ce4fcfa82c0fe94c6ab5a63", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "setup.cfg": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5837.json b/mne-python/source/doc/sphinxext/prs/5837.json new file mode 100644 index 0000000000000000000000000000000000000000..d29f5bdad22512401502fdf756c63170a219e5ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5837.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f951ba3331e6db05a30057b71fcf9f9f118c0e90", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 3 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "conftest.py": { + "a": 37, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 4, + "d": 3 + }, + "setup.cfg": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5838.json b/mne-python/source/doc/sphinxext/prs/5838.json new file mode 100644 index 0000000000000000000000000000000000000000..d6ec89352dadb1556ae167ca4dacdcdc1a51fa46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5838.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "658ddbe28a3dcb2d6d00bf15c3507ceb837e25d5", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/ctf/info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5840.json b/mne-python/source/doc/sphinxext/prs/5840.json new file mode 100644 index 0000000000000000000000000000000000000000..8a4e569007007e99c64c5d8b0b6c0ed7782eb3e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5840.json @@ -0,0 +1,319 @@ +{ + "merge_commit_sha": "d7fe74851707950408d2c2b2e34dfa5fdc1d0669", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "doc/_static/style.css": { + "a": 7, + "d": 0 + }, + "doc/conf.py": { + "a": 114, + "d": 9 + }, + "mne/annotations.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 5, + "d": 5 + }, + "mne/channels/layout.py": { + "a": 3, + "d": 3 + }, + "mne/connectivity/effective.py": { + "a": 3, + "d": 3 + }, + "mne/connectivity/spectral.py": { + "a": 4, + "d": 4 + }, + "mne/connectivity/utils.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/base.py": { + "a": 4, + "d": 3 + }, + "mne/decoding/csp.py": { + "a": 7, + "d": 7 + }, + "mne/decoding/ems.py": { + "a": 7, + "d": 6 + }, + "mne/decoding/mixin.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_frequency.py": { + "a": 10, + "d": 10 + }, + "mne/decoding/transformer.py": { + "a": 21, + "d": 21 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/event.py": { + "a": 8, + "d": 4 + }, + "mne/evoked.py": { + "a": 8, + "d": 8 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 4 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 5, + "d": 5 + }, + "mne/io/cnt/cnt.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 5, + "d": 10 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 3, + "d": 3 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 2, + "d": 2 + }, + "mne/io/proj.py": { + "a": 4, + "d": 4 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 15, + "d": 15 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 3, + "d": 3 + }, + "mne/morph.py": { + "a": 5, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 12, + "d": 11 + }, + "mne/preprocessing/xdawn.py": { + "a": 6, + "d": 6 + }, + "mne/realtime/client.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 6, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 28, + "d": 28 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/stats/cluster_level.py": { + "a": 6, + "d": 6 + }, + "mne/stats/regression.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/multitaper.py": { + "a": 6, + "d": 6 + }, + "mne/time_frequency/stft.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 56, + "d": 63 + }, + "mne/utils/_logging.py": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 27, + "d": 26 + }, + "mne/viz/circle.py": { + "a": 9, + "d": 9 + }, + "mne/viz/epochs.py": { + "a": 10, + "d": 10 + }, + "mne/viz/evoked.py": { + "a": 9, + "d": 9 + }, + "mne/viz/ica.py": { + "a": 13, + "d": 13 + }, + "mne/viz/misc.py": { + "a": 9, + "d": 9 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 11, + "d": 11 + }, + "mne/viz/topomap.py": { + "a": 9, + "d": 9 + }, + "mne/viz/utils.py": { + "a": 11, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5841.json b/mne-python/source/doc/sphinxext/prs/5841.json new file mode 100644 index 0000000000000000000000000000000000000000..04cc421f6c840ee48b97cedea4414ae5625c4513 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5841.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "42cf6876414b9b3d1ad97882962110ae5cbd908d", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 102, + "d": 67 + }, + "mne/io/edf/tests/data/test_stim_channel.edf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 27, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5842.json b/mne-python/source/doc/sphinxext/prs/5842.json new file mode 100644 index 0000000000000000000000000000000000000000..ee2fc347ce8564286996b0c0b5409167168a2977 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5842.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "52d2c268171070643e6946497ab192dee9b68b69", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "conftest.py": { + "a": 6, + "d": 0 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 0, + "d": 9 + }, + "mne/report.py": { + "a": 5, + "d": 5 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5845.json b/mne-python/source/doc/sphinxext/prs/5845.json new file mode 100644 index 0000000000000000000000000000000000000000..dcf8306bb7c3a4597b5bfde61b06923c9bc767b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5845.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "faefe1e78091d1df63c365869660441747146ca1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "appveyor.yml": { + "a": 4, + "d": 3 + }, + "environment.yml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5851.json b/mne-python/source/doc/sphinxext/prs/5851.json new file mode 100644 index 0000000000000000000000000000000000000000..e12da2ab643cf9fac0635534d1086b6f2afa5e83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5851.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7331ad6e0613f32f7dfb0c675fd8f58ee0f1d07c", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/base.py": { + "a": 5, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 43, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5855.json b/mne-python/source/doc/sphinxext/prs/5855.json new file mode 100644 index 0000000000000000000000000000000000000000..edf83dfd2d12dd5b4c2e67ef89c194738e27cd9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5855.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d5f1de425afaec65e86c12fb695514e2f730af1b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 5, + "d": 4 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5857.json b/mne-python/source/doc/sphinxext/prs/5857.json new file mode 100644 index 0000000000000000000000000000000000000000..206366115758e14e5a4b048bf536bd87a8a41d02 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5857.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1567fef198b0dbbdc25365f10ba71aa91d73eab0", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 12 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5859.json b/mne-python/source/doc/sphinxext/prs/5859.json new file mode 100644 index 0000000000000000000000000000000000000000..15378ef43d95c5ff787f3896d5ef21fb10734987 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5859.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "014f87ccd14955dbacfaf52ea4bf205604937d91", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/simulation/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 81, + "d": 6 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 53, + "d": 4 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/586.json b/mne-python/source/doc/sphinxext/prs/586.json new file mode 100644 index 0000000000000000000000000000000000000000..f454001c930ee90a05440be67bb9a935531d3e7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/586.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "77d7aea5eb35a6911abe4eea85f567656d7ae273", + "authors": [ + { + "n": "Romain Trachel", + "e": "trachelr@gmail.com" + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 12, + "d": 6 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 33, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5861.json b/mne-python/source/doc/sphinxext/prs/5861.json new file mode 100644 index 0000000000000000000000000000000000000000..512c1c9294ceb17f1267ae2e9dff26ee24c9bb22 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5861.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "647c7d3a95042b6f3d673855e89f3dc9029bddd6", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 8, + "d": 10 + }, + "mne/io/edf/tests/data/test_stim_channel.edf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 23, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5862.json b/mne-python/source/doc/sphinxext/prs/5862.json new file mode 100644 index 0000000000000000000000000000000000000000..1cccd1390669d9a2fcee6678f96aee51b5289fb5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5862.json @@ -0,0 +1,123 @@ +{ + "merge_commit_sha": "203a96cbba2732d2e349a8f96065e74bbfd2a53b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 19 + }, + "mne/tests/test_utils.py": { + "a": 0, + "d": 969 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 6, + "d": 1 + }, + "mne/utils.py": { + "a": 0, + "d": 3615 + }, + "mne/utils/__init__.py": { + "a": 43, + "d": 0 + }, + "mne/utils/check.py": { + "a": 332, + "d": 0 + }, + "mne/utils/config.py": { + "a": 528, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 391, + "d": 0 + }, + "mne/utils/fetching.py": { + "a": 184, + "d": 0 + }, + "mne/utils/logging.py": { + "a": 337, + "d": 0 + }, + "mne/utils/misc.py": { + "a": 226, + "d": 0 + }, + "mne/utils/mixin.py": { + "a": 456, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 784, + "d": 0 + }, + "mne/utils/progressbar.py": { + "a": 250, + "d": 0 + }, + "mne/utils/testing.py": { + "a": 404, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 38, + "d": 0 + }, + "mne/utils/tests/test_config.py": { + "a": 95, + "d": 0 + }, + "mne/utils/tests/test_docs.py": { + "a": 174, + "d": 0 + }, + "mne/utils/tests/test_fetching.py": { + "a": 29, + "d": 0 + }, + "mne/utils/tests/test_logging.py": { + "a": 114, + "d": 0 + }, + "mne/utils/tests/test_misc.py": { + "a": 8, + "d": 0 + }, + "mne/utils/tests/test_mixin.py": { + "a": 0, + "d": 0 + }, + "mne/utils/tests/test_numerics.py": { + "a": 341, + "d": 0 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 94, + "d": 0 + }, + "mne/utils/tests/test_testing.py": { + "a": 114, + "d": 0 + }, + "requirements.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5865.json b/mne-python/source/doc/sphinxext/prs/5865.json new file mode 100644 index 0000000000000000000000000000000000000000..25f8f806127a3fc84e9f9b9897b3f15cf813feec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5865.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "62d32c2bb616ef9ef6fb0e83c5f4838252029125", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5866.json b/mne-python/source/doc/sphinxext/prs/5866.json new file mode 100644 index 0000000000000000000000000000000000000000..5858a79b7e9d7d4c5d5fd286c09f085292f5a723 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5866.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "217aecf9efad53dadf0c48aef99fd73c7b01244d", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 1, + "d": 0 + }, + "mne/io/edf/_utils.py": { + "a": 33, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 37, + "d": 24 + }, + "mne/io/edf/gdf_encodes.txt": { + "a": 284, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 11, + "d": 0 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 11, + "d": 4 + }, + "setup.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5869.json b/mne-python/source/doc/sphinxext/prs/5869.json new file mode 100644 index 0000000000000000000000000000000000000000..a16092b5b248c8396e79757c0cb5fedcbbc1eef7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5869.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d214798d5ab53c41150f86263758480f00f7e74c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 36, + "d": 12 + }, + "mne/simulation/tests/test_raw.py": { + "a": 45, + "d": 45 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5870.json b/mne-python/source/doc/sphinxext/prs/5870.json new file mode 100644 index 0000000000000000000000000000000000000000..35095ac18e2712f81408400f7ae5043f3d21174d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5870.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "c6956e7c2385712a8b87c15682aaef5f0fcb9168", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/cov.py": { + "a": 10, + "d": 178 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 0, + "d": 34 + }, + "mne/io/proc_history.py": { + "a": 1, + "d": 50 + }, + "mne/io/tests/test_proc_history.py": { + "a": 1, + "d": 11 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 4 + }, + "mne/rank.py": { + "a": 234, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 8, + "d": 124 + }, + "mne/tests/test_rank.py": { + "a": 169, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 72 + }, + "mne/utils/tests/test_numerics.py": { + "a": 39, + "d": 12 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5871.json b/mne-python/source/doc/sphinxext/prs/5871.json new file mode 100644 index 0000000000000000000000000000000000000000..447b29bd782f300dcc2902830fc094e57e83d870 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5871.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "d5ae1c83a70dfb3c40f23914d389976c65a3cd11", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/utils/__init__.py": { + "a": 3, + "d": 3 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 3 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/utils/fetching.py": { + "a": 1, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + }, + "mne/utils/progressbar.py": { + "a": 1, + "d": 1 + }, + "mne/utils/testing.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5872.json b/mne-python/source/doc/sphinxext/prs/5872.json new file mode 100644 index 0000000000000000000000000000000000000000..d3a50e4aca07141b75eea453354a50ed852819dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5872.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "44c2ba414f2ab11d83bd5a477c599b9370f28449", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 9, + "d": 61 + }, + "mne/beamformer/_dics.py": { + "a": 6, + "d": 7 + }, + "mne/beamformer/_lcmv.py": { + "a": 9, + "d": 9 + }, + "mne/beamformer/_rap_music.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 7, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 5, + "d": 4 + }, + "mne/utils/check.py": { + "a": 67, + "d": 2 + }, + "mne/utils/tests/test_check.py": { + "a": 83, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5875.json b/mne-python/source/doc/sphinxext/prs/5875.json new file mode 100644 index 0000000000000000000000000000000000000000..618276a4897c455b7faddb63972e62783ba5b92f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5875.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cd53a2712c341a1641989962950f07fdb6b11a85", + "authors": [ + { + "n": "Hubert Banville", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 28, + "d": 15 + }, + "mne/io/tests/test_apply_function.py": { + "a": 20, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5876.json b/mne-python/source/doc/sphinxext/prs/5876.json new file mode 100644 index 0000000000000000000000000000000000000000..f52964b1b1fe5b485abf9dcf8addcf8ff6bbf4fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5876.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "544989c7ff9922e04bddad72c1b13156ce344ace", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 4, + "d": 46 + }, + "mne/beamformer/_dics.py": { + "a": 4, + "d": 3 + }, + "mne/beamformer/_lcmv.py": { + "a": 28, + "d": 21 + }, + "mne/cov.py": { + "a": 99, + "d": 148 + }, + "mne/decoding/csp.py": { + "a": 5, + "d": 4 + }, + "mne/io/base.py": { + "a": 9, + "d": 5 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 5 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 22, + "d": 8 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 10, + "d": 11 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 6, + "d": 2 + }, + "mne/rank.py": { + "a": 214, + "d": 50 + }, + "mne/tests/test_cov.py": { + "a": 54, + "d": 18 + }, + "mne/tests/test_rank.py": { + "a": 99, + "d": 47 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 4, + "d": 2 + }, + "mne/utils/check.py": { + "a": 44, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 21, + "d": 3 + }, + "mne/utils/numerics.py": { + "a": 17, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 8 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 39 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5877.json b/mne-python/source/doc/sphinxext/prs/5877.json new file mode 100644 index 0000000000000000000000000000000000000000..05f6a13c53fad4223fbdf2d59138c84ff3402ef1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5877.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "c4cfc5d18dd4b8d6499d3ff4eea4b469c9b2b9e5", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 41, + "d": 47 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 459, + "d": 213 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 23, + "d": 15 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/588.json b/mne-python/source/doc/sphinxext/prs/588.json new file mode 100644 index 0000000000000000000000000000000000000000..81a0b595a7039b48b6fb9e080110beb4e22aa66d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/588.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "df5f5509b87bb71c2dcb9992b28d7a57e7b190d9", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/tests/test_utils.py": { + "a": 16, + "d": 1 + }, + "mne/utils.py": { + "a": 12, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5887.json b/mne-python/source/doc/sphinxext/prs/5887.json new file mode 100644 index 0000000000000000000000000000000000000000..7ec24830ea190ce8f5dbc03b7fe2431c41162856 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5887.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "285dffd6f7a7ef19065cbffd40dc1bbd354977f9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 3 + }, + ".travis.yml": { + "a": 2, + "d": 2 + }, + "appveyor.yml": { + "a": 2, + "d": 2 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5888.json b/mne-python/source/doc/sphinxext/prs/5888.json new file mode 100644 index 0000000000000000000000000000000000000000..8f9e7c26948ba14ba1969838298d74740ac889c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5888.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "49a3e84755a44ef1d30b2f35d8b46f80de1b5688", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 1 + }, + "doc/install_mne_python.rst": { + "a": 15, + "d": 14 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_source_estimate.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5890.json b/mne-python/source/doc/sphinxext/prs/5890.json new file mode 100644 index 0000000000000000000000000000000000000000..e5185475066dfef87b3b8283975fc9afcabcc534 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5890.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "50c5da639662ce3f4cb30e5a397f51e4bd7dd5ce", + "authors": [ + { + "n": "José C. García Alanis", + "e": null + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5892.json b/mne-python/source/doc/sphinxext/prs/5892.json new file mode 100644 index 0000000000000000000000000000000000000000..032aece0f5a5760d63c63772a41c1bf5e68e65f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5892.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "33b317b688fc932856d874bb85400bab048f8f38", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/receptive_field.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 9, + "d": 8 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/stim_server_client.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5895.json b/mne-python/source/doc/sphinxext/prs/5895.json new file mode 100644 index 0000000000000000000000000000000000000000..8dc107a783792846f66545d98678e3acea14a070 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5895.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "8f6d2946c778ee2b131726f877e06b7a7c59d875", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/annotations.py": { + "a": 32, + "d": 8 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 12, + "d": 3 + }, + "mne/preprocessing/ecg.py": { + "a": 58, + "d": 15 + }, + "mne/preprocessing/ssp.py": { + "a": 3, + "d": 6 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 16, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 13, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5896.json b/mne-python/source/doc/sphinxext/prs/5896.json new file mode 100644 index 0000000000000000000000000000000000000000..7dff75c5387cab3b82e2be04173aea55307da9b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5896.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "14e45a5be062703429687385630787ae56e42abf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "appveyor.yml": { + "a": 4, + "d": 5 + }, + "doc/install_mne_python.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5897.json b/mne-python/source/doc/sphinxext/prs/5897.json new file mode 100644 index 0000000000000000000000000000000000000000..eabefdefe9fdc427abc1a1d9553cb3e898609fd9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5897.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6fdfb41246a1ca1a5ae2c381c5f7d97137a63265", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 22, + "d": 3 + }, + "mne/io/constants.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_constants.py": { + "a": 7, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 149, + "d": 129 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5898.json b/mne-python/source/doc/sphinxext/prs/5898.json new file mode 100644 index 0000000000000000000000000000000000000000..b34dc0ffa71a022f1350e84f615003ce871844c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5898.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bee5f219ab835e33746af62cac4f188ddd987227", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/manual/datasets_index.rst": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 11, + "d": 7 + }, + "tutorials/plot_python_intro.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_sensors_decoding.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/59.json b/mne-python/source/doc/sphinxext/prs/59.json new file mode 100644 index 0000000000000000000000000000000000000000..86e4048299c5d88b69770698018dcce0f5f56766 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/59.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "187d462ec2f7e47384cf61aff912dc727f558a93", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 34, + "d": 17 + }, + "mne/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/proj.py": { + "a": 11, + "d": 8 + }, + "mne/fiff/raw.py": { + "a": 18, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 12, + "d": 2 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5900.json b/mne-python/source/doc/sphinxext/prs/5900.json new file mode 100644 index 0000000000000000000000000000000000000000..ff7b09fc62397de4fa59361cfc33e643bbab558e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5900.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "39fab32f4a93bc7675fce4398fe3a05346cbae09", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 61, + "d": 29 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_annotations.py": { + "a": 31, + "d": 27 + }, + "mne/utils/testing.py": { + "a": 11, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5901.json b/mne-python/source/doc/sphinxext/prs/5901.json new file mode 100644 index 0000000000000000000000000000000000000000..93901d39d84e311b7b99ed805549f703569d67b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5901.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c1e353965e341919c22ece4d502720201f53b6e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_coreg.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5902.json b/mne-python/source/doc/sphinxext/prs/5902.json new file mode 100644 index 0000000000000000000000000000000000000000..5a43afa609e285c802428211e7f91fbbccd93c40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5902.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "65e510049d81ae3517f63c27244eacbc5cc8d320", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 5, + "d": 6 + }, + "mne/utils/config.py": { + "a": 24, + "d": 15 + }, + "mne/utils/tests/test_fetching.py": { + "a": 17, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5904.json b/mne-python/source/doc/sphinxext/prs/5904.json new file mode 100644 index 0000000000000000000000000000000000000000..79c9ac44b244c93e1645b9d0a2c3057237a1abdb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5904.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "fd91ebed2e1f69d742e32e40597938fd3b924706", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 105, + "d": 0 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 12, + "d": 14 + }, + "mne/connectivity/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/connectivity/envelope.py": { + "a": 100, + "d": 0 + }, + "mne/connectivity/tests/test_envelope.py": { + "a": 60, + "d": 0 + }, + "mne/connectivity/tests/test_utils.py": { + "a": 34, + "d": 1 + }, + "mne/connectivity/utils.py": { + "a": 47, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 3 + }, + "mne/io/ctf_comp.py": { + "a": 3, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 25, + "d": 19 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 16, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5905.json b/mne-python/source/doc/sphinxext/prs/5905.json new file mode 100644 index 0000000000000000000000000000000000000000..69ecec6dae66901202bfec61e0ff31d02b74dfb5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5905.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "3db66e03c9add0646cb722ee1d714da5c73f5c2d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/advanced_setup.rst": { + "a": 126, + "d": 66 + }, + "doc/contributing.rst": { + "a": 4, + "d": 4 + }, + "doc/documentation.rst": { + "a": 12, + "d": 5 + }, + "doc/getting_started.rst": { + "a": 12, + "d": 70 + }, + "doc/git_links.inc": { + "a": 19, + "d": 2 + }, + "doc/index.rst": { + "a": 1, + "d": 1 + }, + "doc/install_freesurfer.rst": { + "a": 25, + "d": 0 + }, + "doc/install_mne_c.rst": { + "a": 125, + "d": 236 + }, + "doc/install_mne_python.rst": { + "a": 48, + "d": 45 + }, + "doc/manual/c_reference.rst": { + "a": 4, + "d": 2 + }, + "doc/pre_install.rst": { + "a": 72, + "d": 0 + }, + "doc/this_project.inc": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5910.json b/mne-python/source/doc/sphinxext/prs/5910.json new file mode 100644 index 0000000000000000000000000000000000000000..971dec68dc5b7aa7f19db08b529762cf302da368 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5910.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "eb20842546fe4e8d19d5659af69dbbf33d275451", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5911.json b/mne-python/source/doc/sphinxext/prs/5911.json new file mode 100644 index 0000000000000000000000000000000000000000..478a20201760dd6694c2fce2b87c495d82f6a830 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5911.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3e29d773e537c502f4e6504384846e3cbef99052", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5913.json b/mne-python/source/doc/sphinxext/prs/5913.json new file mode 100644 index 0000000000000000000000000000000000000000..c5e7934379873555f5cf9fc53bfc1edf9d027378 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5913.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "62acff0fe93ac9abe2460ab731c4ae804461e786", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 27, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5914.json b/mne-python/source/doc/sphinxext/prs/5914.json new file mode 100644 index 0000000000000000000000000000000000000000..0931b7c4b794aaf4e7d351263c880804f9b51aae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5914.json @@ -0,0 +1,227 @@ +{ + "merge_commit_sha": "d54144fb725acc2b97665288b1162b4c2f1752db", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".lgtm.yml": { + "a": 13, + "d": 0 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 1, + "d": 0 + }, + "logo/generate_mne_logos.py": { + "a": 0, + "d": 1 + }, + "mne/annotations.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/_dics.py": { + "a": 0, + "d": 2 + }, + "mne/bem.py": { + "a": 0, + "d": 1 + }, + "mne/coreg.py": { + "a": 13, + "d": 12 + }, + "mne/cov.py": { + "a": 0, + "d": 3 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/megsim/megsim.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/mixin.py": { + "a": 9, + "d": 3 + }, + "mne/epochs.py": { + "a": 4, + "d": 3 + }, + "mne/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/fixes.py": { + "a": 1, + "d": 5 + }, + "mne/forward/_lead_dots.py": { + "a": 6, + "d": 7 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 9, + "d": 19 + }, + "mne/gui/_fiducials_gui.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 2 + }, + "mne/io/base.py": { + "a": 5, + "d": 6 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 4, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 4, + "d": 2 + }, + "mne/io/proc_history.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 5, + "d": 6 + }, + "mne/minimum_norm/inverse.py": { + "a": 0, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/ctps_.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 17 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/peak_finder.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/xdawn.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/epochs.py": { + "a": 4, + "d": 2 + }, + "mne/source_space.py": { + "a": 0, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + }, + "mne/transforms.py": { + "a": 14, + "d": 16 + }, + "mne/utils/mixin.py": { + "a": 20, + "d": 13 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 6 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 11, + "d": 9 + }, + "mne/viz/utils.py": { + "a": 15, + "d": 15 + }, + "setup.py": { + "a": 31, + "d": 28 + }, + "tutorials/plot_info.py": { + "a": 6, + "d": 5 + }, + "tutorials/plot_sleep.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5915.json b/mne-python/source/doc/sphinxext/prs/5915.json new file mode 100644 index 0000000000000000000000000000000000000000..d8e919c0e609436c9d3743eda59b902dfc8d76d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5915.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "11e73a493a830f7b148413ba82d8a3399ad921cf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5917.json b/mne-python/source/doc/sphinxext/prs/5917.json new file mode 100644 index 0000000000000000000000000000000000000000..17b62c3081d79b6fc1fb18bb86e4ae90e12d9162 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5917.json @@ -0,0 +1,247 @@ +{ + "merge_commit_sha": "63a8ce271eac9b2d488c353e04a3117aa1c5e772", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 3 + }, + "mne/channels/interpolation.py": { + "a": 3, + "d": 3 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 2 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 7, + "d": 7 + }, + "mne/event.py": { + "a": 3, + "d": 3 + }, + "mne/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/externals/funcsigs.py": { + "a": 20, + "d": 20 + }, + "mne/externals/h5io/_h5io.py": { + "a": 6, + "d": 6 + }, + "mne/fixes.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_help.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 6, + "d": 6 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 2, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 3 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 6 + }, + "mne/io/pick.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 1, + "d": 2 + }, + "mne/morph.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 18, + "d": 18 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 4 + }, + "mne/selection.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/parametric.py": { + "a": 3, + "d": 3 + }, + "mne/stats/regression.py": { + "a": 9, + "d": 9 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + }, + "mne/transforms.py": { + "a": 3, + "d": 3 + }, + "mne/utils/check.py": { + "a": 2, + "d": 2 + }, + "mne/utils/mixin.py": { + "a": 2, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 10, + "d": 11 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 3 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 4, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 8, + "d": 8 + }, + "mne/viz/utils.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5920.json b/mne-python/source/doc/sphinxext/prs/5920.json new file mode 100644 index 0000000000000000000000000000000000000000..9c150f26a1b0cd0aabf54f13698c4e1b7a296d78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5920.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4ec61d8710c698cecba9c2dbb7c050f1d907316c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/epochs.py": { + "a": 5, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 67, + "d": 0 + }, + "mne/utils/mixin.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5921.json b/mne-python/source/doc/sphinxext/prs/5921.json new file mode 100644 index 0000000000000000000000000000000000000000..7dbae2f6c21afabb770c71ba27b9929f99939b2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5921.json @@ -0,0 +1,483 @@ +{ + "merge_commit_sha": "5a0bbee4ddaaa880dadee3efd092c7f5c2168e93", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 1, + "d": 4 + }, + "mne/baseline.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 4 + }, + "mne/beamformer/_dics.py": { + "a": 5, + "d": 15 + }, + "mne/beamformer/_lcmv.py": { + "a": 5, + "d": 15 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 3 + }, + "mne/bem.py": { + "a": 10, + "d": 28 + }, + "mne/channels/channels.py": { + "a": 5, + "d": 19 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 3 + }, + "mne/chpi.py": { + "a": 4, + "d": 12 + }, + "mne/connectivity/effective.py": { + "a": 1, + "d": 3 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 3 + }, + "mne/coreg.py": { + "a": 4, + "d": 12 + }, + "mne/cov.py": { + "a": 8, + "d": 23 + }, + "mne/cuda.py": { + "a": 1, + "d": 4 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 2, + "d": 5 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/megsim/megsim.py": { + "a": 2, + "d": 4 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/utils.py": { + "a": 6, + "d": 7 + }, + "mne/datasets/visual_92_categories/visual_92_categories.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/ems.py": { + "a": 3, + "d": 5 + }, + "mne/decoding/search_light.py": { + "a": 5, + "d": 9 + }, + "mne/decoding/time_frequency.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/transformer.py": { + "a": 7, + "d": 12 + }, + "mne/dipole.py": { + "a": 13, + "d": 19 + }, + "mne/epochs.py": { + "a": 20, + "d": 51 + }, + "mne/event.py": { + "a": 1, + "d": 3 + }, + "mne/evoked.py": { + "a": 9, + "d": 16 + }, + "mne/externals/decorator.py": { + "a": 314, + "d": 113 + }, + "mne/externals/doccer.py": { + "a": 144, + "d": 0 + }, + "mne/filter.py": { + "a": 8, + "d": 30 + }, + "mne/forward/_compute_forward.py": { + "a": 2, + "d": 6 + }, + "mne/forward/_field_interpolation.py": { + "a": 2, + "d": 6 + }, + "mne/forward/_make_forward.py": { + "a": 6, + "d": 15 + }, + "mne/forward/forward.py": { + "a": 7, + "d": 21 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 3 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 6 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 1, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 9 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 3, + "d": 9 + }, + "mne/io/array/array.py": { + "a": 3, + "d": 4 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 4 + }, + "mne/io/base.py": { + "a": 13, + "d": 43 + }, + "mne/io/brainvision/brainvision.py": { + "a": 5, + "d": 7 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 6 + }, + "mne/io/cnt/cnt.py": { + "a": 6, + "d": 9 + }, + "mne/io/ctf/ctf.py": { + "a": 5, + "d": 7 + }, + "mne/io/ctf_comp.py": { + "a": 1, + "d": 3 + }, + "mne/io/edf/edf.py": { + "a": 11, + "d": 16 + }, + "mne/io/eeglab/eeglab.py": { + "a": 8, + "d": 13 + }, + "mne/io/egi/egi.py": { + "a": 3, + "d": 5 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 2 + }, + "mne/io/eximia/eximia.py": { + "a": 5, + "d": 5 + }, + "mne/io/fiff/raw.py": { + "a": 6, + "d": 10 + }, + "mne/io/kit/kit.py": { + "a": 8, + "d": 13 + }, + "mne/io/matrix.py": { + "a": 1, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 18 + }, + "mne/io/nicolet/nicolet.py": { + "a": 4, + "d": 7 + }, + "mne/io/open.py": { + "a": 3, + "d": 6 + }, + "mne/io/pick.py": { + "a": 2, + "d": 6 + }, + "mne/io/proj.py": { + "a": 6, + "d": 19 + }, + "mne/io/reference.py": { + "a": 2, + "d": 6 + }, + "mne/label.py": { + "a": 12, + "d": 32 + }, + "mne/minimum_norm/inverse.py": { + "a": 8, + "d": 22 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 2, + "d": 6 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 12 + }, + "mne/morph.py": { + "a": 13, + "d": 24 + }, + "mne/parallel.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 6 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 6 + }, + "mne/preprocessing/ica.py": { + "a": 13, + "d": 39 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/peak_finder.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 6 + }, + "mne/proj.py": { + "a": 5, + "d": 12 + }, + "mne/realtime/client.py": { + "a": 3, + "d": 4 + }, + "mne/realtime/epochs.py": { + "a": 5, + "d": 11 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 3, + "d": 4 + }, + "mne/realtime/mockclient.py": { + "a": 4, + "d": 3 + }, + "mne/realtime/stim_server_client.py": { + "a": 8, + "d": 24 + }, + "mne/report.py": { + "a": 5, + "d": 8 + }, + "mne/selection.py": { + "a": 1, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 2, + "d": 6 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 31, + "d": 72 + }, + "mne/source_space.py": { + "a": 14, + "d": 44 + }, + "mne/stats/cluster_level.py": { + "a": 4, + "d": 12 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 3 + }, + "mne/surface.py": { + "a": 6, + "d": 18 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 8, + "d": 8 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 3 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 3 + }, + "mne/time_frequency/csd.py": { + "a": 7, + "d": 28 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 6 + }, + "mne/time_frequency/psd.py": { + "a": 3, + "d": 9 + }, + "mne/time_frequency/stft.py": { + "a": 1, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 12, + "d": 28 + }, + "mne/transforms.py": { + "a": 2, + "d": 8 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 48, + "d": 25 + }, + "mne/utils/docs.py": { + "a": 15, + "d": 2 + }, + "mne/utils/fetching.py": { + "a": 1, + "d": 3 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 4 + }, + "mne/utils/tests/test_docs.py": { + "a": 11, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 17 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 10 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5922.json b/mne-python/source/doc/sphinxext/prs/5922.json new file mode 100644 index 0000000000000000000000000000000000000000..85e12469dfb166077304d92704db99dd32abef8a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5922.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e4848ae37bc6847af3081600b4253c061ec454a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 5, + "d": 1 + }, + "mne/externals/funcsigs.py": { + "a": 0, + "d": 815 + }, + "mne/externals/h5io/_h5io.py": { + "a": 119, + "d": 11 + }, + "mne/io/base.py": { + "a": 2, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5923.json b/mne-python/source/doc/sphinxext/prs/5923.json new file mode 100644 index 0000000000000000000000000000000000000000..eb33cb83befb3ecfa2205a380fc6bcd5c8be831d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5923.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "6067ee7f82560429e2b1346a10283bb2065bc158", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "environment.yml": { + "a": 3, + "d": 3 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 5, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 67, + "d": 0 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5927.json b/mne-python/source/doc/sphinxext/prs/5927.json new file mode 100644 index 0000000000000000000000000000000000000000..ae81713d320008b538dd45bba4298d9148e42e00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5927.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c7f9624cf1af7ec9751daa32adc96f4adc02a233", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/593.json b/mne-python/source/doc/sphinxext/prs/593.json new file mode 100644 index 0000000000000000000000000000000000000000..60c95e6a4896898fb11521403c2e551730d216f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/593.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9af93f1d3679c3fd624ac9cfe58c7444c7eab7e2", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/stats/tests/test_parametric.py": { + "a": 26, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5930.json b/mne-python/source/doc/sphinxext/prs/5930.json new file mode 100644 index 0000000000000000000000000000000000000000..b7d9ef0804f377929495563ba8eae082b355272d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5930.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1e532042a5877b28fe2a2ef88977d98264716a9b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 0, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5931.json b/mne-python/source/doc/sphinxext/prs/5931.json new file mode 100644 index 0000000000000000000000000000000000000000..88cee01697415a94d9558de4032791acb5e28695 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5931.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2502260f48b84299c00530ab09fdc9e2b2a4cddf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 8, + "d": 17 + }, + ".travis.yml": { + "a": 4, + "d": 1 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 1, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5932.json b/mne-python/source/doc/sphinxext/prs/5932.json new file mode 100644 index 0000000000000000000000000000000000000000..76bfbefa0ee5f4a85bd2b72cdc7a901c954a1c5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5932.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "90b91a313f2f96fcec046f4a254e4d2f8981a50f", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "mne/datasets/sleep_physionet/SHA1SUMS": { + "a": 394, + "d": 0 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 17, + "d": 21 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 4, + "d": 2 + }, + "mne/datasets/sleep_physionet/age_records.csv": { + "a": 228, + "d": 0 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 11, + "d": 10 + }, + "mne/datasets/sleep_physionet/temazepam_records.csv": { + "a": 22, + "d": 0 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 4, + "d": 2 + }, + "setup.py": { + "a": 2, + "d": 1 + }, + "tutorials/plot_sleep.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5934.json b/mne-python/source/doc/sphinxext/prs/5934.json new file mode 100644 index 0000000000000000000000000000000000000000..edc7113d0ef72a4c55ef386748825fe88c512be8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5934.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fd99e1b16616af12dd99a13d5c8860a6e3094c08", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 31, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5936.json b/mne-python/source/doc/sphinxext/prs/5936.json new file mode 100644 index 0000000000000000000000000000000000000000..f047d13674a576d8d83bc33858ff4035943c7cc4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5936.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a4aac69816a02337ce3448ec58a21f77ce6e2ab5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_3d_to_2d.py": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 3, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ssp.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_ecog.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5939.json b/mne-python/source/doc/sphinxext/prs/5939.json new file mode 100644 index 0000000000000000000000000000000000000000..8a62f2ad406e94d4237c06dd2b33bebf2152aa95 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5939.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "58f22d75b0f80fa643ddc8db10dbaaa607cce47a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 6, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 5, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/594.json b/mne-python/source/doc/sphinxext/prs/594.json new file mode 100644 index 0000000000000000000000000000000000000000..1d207dac9642a7aa7ffd6f48a45f91a3c8106991 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/594.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "200fe5660f8226799501abeca73c5b56b1f9f9b4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 11, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5940.json b/mne-python/source/doc/sphinxext/prs/5940.json new file mode 100644 index 0000000000000000000000000000000000000000..c6e85461207e3b01dac8316f022ddd82c1f98966 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5940.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0656d8eef747ecb0d86631c18675feba3ab1fcae", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 5, + "d": 3 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 7, + "d": 15 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 36, + "d": 7 + }, + "mne/simulation/tests/test_raw.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5942.json b/mne-python/source/doc/sphinxext/prs/5942.json new file mode 100644 index 0000000000000000000000000000000000000000..7c5f2ef7c6fd87c7dd308df42e4a84b47ef8e6fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5942.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "12a85495333e07a80d676dcb0e19a562bd7d380f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/edf/_utils.py": { + "a": 8, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5946.json b/mne-python/source/doc/sphinxext/prs/5946.json new file mode 100644 index 0000000000000000000000000000000000000000..56cd76b015d3e0fa1ae6bce898926920b0d456fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5946.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b9f18ea32c6e303aaa1e0b0e7aa4f7e3695dfcf4", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5947.json b/mne-python/source/doc/sphinxext/prs/5947.json new file mode 100644 index 0000000000000000000000000000000000000000..10dc502d906f4fd8f127a4cc5704f0fdabf71f0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5947.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "8dc463497f160e0c7fde772c7effec76beaa7f32", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 0, + "d": 0 + }, + "doc/manual/c_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 4, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 2, + "d": 7 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 77, + "d": 56 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 151, + "d": 36 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 20, + "d": 56 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 176, + "d": 221 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 7, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 7 + }, + "mne/simulation/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 32, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 5, + "d": 0 + }, + "mne/utils/check.py": { + "a": 18, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5949.json b/mne-python/source/doc/sphinxext/prs/5949.json new file mode 100644 index 0000000000000000000000000000000000000000..7bd0cd44c36d477e1f105a3f72006565846d8f8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5949.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8b00fc96ec8574c364007ea6b9655eb288d464bb", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5950.json b/mne-python/source/doc/sphinxext/prs/5950.json new file mode 100644 index 0000000000000000000000000000000000000000..f2b418ccb81ada0ccc3a8efab222d3eeb5162c0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5950.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "4fef3d02881d1b75d22c4de5399c11c736855f86", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 8 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 21, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 30, + "d": 30 + }, + "mne/rank.py": { + "a": 18, + "d": 10 + }, + "mne/tests/test_cov.py": { + "a": 39, + "d": 24 + }, + "mne/tests/test_rank.py": { + "a": 13, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5954.json b/mne-python/source/doc/sphinxext/prs/5954.json new file mode 100644 index 0000000000000000000000000000000000000000..711355dd4cb2e976ab796d27632e962030daff67 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5954.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5778168e9eaf597997fdd638c712fa3d01326fbc", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/glossary.rst": { + "a": 10, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 42, + "d": 14 + }, + "mne/tests/test_source_space.py": { + "a": 8, + "d": 3 + }, + "tutorials/plot_forward.py": { + "a": 46, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5955.json b/mne-python/source/doc/sphinxext/prs/5955.json new file mode 100644 index 0000000000000000000000000000000000000000..12adc92b9ccc26a59802f56f41488f3bdcc3a9f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5955.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4d932c2d2fea79e073715e42c08e94b06ea3cf9e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5957.json b/mne-python/source/doc/sphinxext/prs/5957.json new file mode 100644 index 0000000000000000000000000000000000000000..1682137c583f5993920d012b6c46f0581c2ef1fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5957.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c2f9adc34625990ea6ec287c158d7cbed706f7a1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 14, + "d": 14 + }, + "mne/channels/tests/test_channels.py": { + "a": 9, + "d": 0 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5958.json b/mne-python/source/doc/sphinxext/prs/5958.json new file mode 100644 index 0000000000000000000000000000000000000000..e09ac587f1b128856df0d6a38e78ffdc5086d535 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5958.json @@ -0,0 +1,235 @@ +{ + "merge_commit_sha": "73ea718b82c7ea5f09b70490ca3ba7de2fd79f78", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/baseline.py": { + "a": 3, + "d": 5 + }, + "mne/beamformer/_dics.py": { + "a": 4, + "d": 9 + }, + "mne/beamformer/_lcmv.py": { + "a": 4, + "d": 9 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 7 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 5 + }, + "mne/chpi.py": { + "a": 5, + "d": 11 + }, + "mne/cov.py": { + "a": 4, + "d": 8 + }, + "mne/datasets/megsim/megsim.py": { + "a": 4, + "d": 7 + }, + "mne/decoding/csp.py": { + "a": 3, + "d": 4 + }, + "mne/decoding/time_frequency.py": { + "a": 2, + "d": 4 + }, + "mne/decoding/transformer.py": { + "a": 3, + "d": 5 + }, + "mne/dipole.py": { + "a": 2, + "d": 5 + }, + "mne/epochs.py": { + "a": 5, + "d": 12 + }, + "mne/event.py": { + "a": 2, + "d": 4 + }, + "mne/evoked.py": { + "a": 5, + "d": 15 + }, + "mne/filter.py": { + "a": 2, + "d": 4 + }, + "mne/fixes.py": { + "a": 2, + "d": 4 + }, + "mne/forward/_field_interpolation.py": { + "a": 9, + "d": 17 + }, + "mne/io/base.py": { + "a": 6, + "d": 10 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 3, + "d": 4 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 6 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/label.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 8, + "d": 14 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 2, + "d": 4 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 4 + }, + "mne/morph.py": { + "a": 2, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/maxwell.py": { + "a": 5, + "d": 8 + }, + "mne/preprocessing/stim.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/xdawn.py": { + "a": 3, + "d": 3 + }, + "mne/proj.py": { + "a": 5, + "d": 10 + }, + "mne/report.py": { + "a": 9, + "d": 17 + }, + "mne/simulation/metrics.py": { + "a": 3, + "d": 4 + }, + "mne/simulation/source.py": { + "a": 2, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 10 + }, + "mne/stats/cluster_level.py": { + "a": 4, + "d": 7 + }, + "mne/stats/parametric.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 5, + "d": 13 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 35, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 7 + }, + "mne/utils/tests/test_check.py": { + "a": 24, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 11, + "d": 36 + }, + "mne/viz/misc.py": { + "a": 3, + "d": 3 + }, + "mne/viz/montage.py": { + "a": 2, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 4, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/596.json b/mne-python/source/doc/sphinxext/prs/596.json new file mode 100644 index 0000000000000000000000000000000000000000..90e576f031d1327fe5015987fb70d0748b0dd27b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/596.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a78f46ff7299c0e036d3661884dd4aefdd5cbffa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/matrix.py": { + "a": 6, + "d": 0 + }, + "mne/forward.py": { + "a": 6, + "d": 5 + }, + "mne/tests/test_forward.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5962.json b/mne-python/source/doc/sphinxext/prs/5962.json new file mode 100644 index 0000000000000000000000000000000000000000..caec5b00d00ddfc23e1cf6bb70f62b4cedffd0f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5962.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b0e691f895be4d7d7dbd8a445a6242c567924ee0", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_ica_comparison.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 17, + "d": 14 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 0, + "d": 1 + }, + "tutorials/plot_artifacts_correction_ica.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_ica_from_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5963.json b/mne-python/source/doc/sphinxext/prs/5963.json new file mode 100644 index 0000000000000000000000000000000000000000..92d6265e2fdee9315eb5b754199ad66bb644ddf9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5963.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c3e7571a9b698034cda94aae53004b55265057a9", + "authors": [ + { + "n": "Jevri Hanna", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 10, + "d": 7 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 54, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5964.json b/mne-python/source/doc/sphinxext/prs/5964.json new file mode 100644 index 0000000000000000000000000000000000000000..13eea7d2ec32f3fade5a4fe122a8d5784ad75e12 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5964.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "09901960a0b9c4254b3f8ca0ab483444445ffa31", + "authors": [ + { + "n": "Jeyhte Key", + "e": "jeythekey@tutanota.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5969.json b/mne-python/source/doc/sphinxext/prs/5969.json new file mode 100644 index 0000000000000000000000000000000000000000..101203b707e804cd1467e1c007027d5699900b60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5969.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4e1f0632aea44af1d0e07dba331391cee8979df1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 14, + "d": 3 + }, + "mne/viz/tests/test_topo.py": { + "a": 14, + "d": 9 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/597.json b/mne-python/source/doc/sphinxext/prs/597.json new file mode 100644 index 0000000000000000000000000000000000000000..d57845b9e5aa705aeec495954be6f306cce5e4a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/597.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6fda3c4a6ae34fea103605551beed4bc377d85cd", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 19, + "d": 7 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5971.json b/mne-python/source/doc/sphinxext/prs/5971.json new file mode 100644 index 0000000000000000000000000000000000000000..922081ef401137e3612c3e2ad3a4a4b020a22f0f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5971.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b9ab993c6e34195499d2c4406dca7a54d58eaa4f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5973.json b/mne-python/source/doc/sphinxext/prs/5973.json new file mode 100644 index 0000000000000000000000000000000000000000..7d3ccdb051a971337dfd7da5a1662449ce475835 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5973.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "7c21bd6c43c79d325fa47c39925daaa001882790", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 23, + "d": 8 + }, + "mne/source_estimate.py": { + "a": 273, + "d": 233 + }, + "mne/tests/test_morph.py": { + "a": 20, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 33, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5976.json b/mne-python/source/doc/sphinxext/prs/5976.json new file mode 100644 index 0000000000000000000000000000000000000000..fc3e00e823de6e3d3684b998aae0aae2d1a7be97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5976.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "571a792299d07c298b9707fa84ad0b31badd5deb", + "authors": [ + { + "n": "Quentin Bertrand", + "e": "quentin.bertrand@mila.quebec" + } + ], + "changes": { + "mne/simulation/source.py": { + "a": 3, + "d": 0 + }, + "mne/simulation/tests/test_source.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5978.json b/mne-python/source/doc/sphinxext/prs/5978.json new file mode 100644 index 0000000000000000000000000000000000000000..e28dd1816ac2db7d3b8ed8ed863fbcb00f4bf262 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5978.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2c659d59f89ff0e107c0af02d3cd5b506d8896cc", + "authors": [ + { + "n": "Simon Kern", + "e": null + } + ], + "changes": { + "mne/io/pick.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5979.json b/mne-python/source/doc/sphinxext/prs/5979.json new file mode 100644 index 0000000000000000000000000000000000000000..5c196f31d9364222546217582907afde885db352 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5979.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5633254b08c6cd97c4e261c06e08459eb51f9516", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 6, + "d": 11 + }, + "mne/beamformer/_lcmv.py": { + "a": 30, + "d": 53 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 22, + "d": 10 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 57, + "d": 1 + }, + "mne/utils/check.py": { + "a": 14, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5981.json b/mne-python/source/doc/sphinxext/prs/5981.json new file mode 100644 index 0000000000000000000000000000000000000000..2764dabc3d9e4f0eb4313b1d1ac3f0f9cf0bec8f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5981.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3d12b2b7b3b0ddb3f50962e4293cddf8ccf6ba52", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/plot_simulate_raw_data.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5982.json b/mne-python/source/doc/sphinxext/prs/5982.json new file mode 100644 index 0000000000000000000000000000000000000000..90cb5b8da1abf5db1593448d1c6e28c1cea60e2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5982.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "46055a3a4122bf30740f6cefcfb03310ce064738", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/manual/io.rst": { + "a": 37, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5983.json b/mne-python/source/doc/sphinxext/prs/5983.json new file mode 100644 index 0000000000000000000000000000000000000000..02a8290323e07ea901fb840812fe8b4be083eae0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5983.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d3bff5a6570c071da590243b493cc59198b143f2", + "authors": [ + { + "n": "José C. García Alanis", + "e": null + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5984.json b/mne-python/source/doc/sphinxext/prs/5984.json new file mode 100644 index 0000000000000000000000000000000000000000..db0a0a94a46b5dce3bc09033eb5696fafeb9d3f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5984.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "f7bb2ef4a40bf3bc3e20c82feba145e0e6e35aac", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "conftest.py": { + "a": 64, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 52, + "d": 0 + }, + "mne/defaults.py": { + "a": 4, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 76, + "d": 15 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 6, + "d": 4 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 22, + "d": 17 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 10, + "d": 5 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 4, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 44, + "d": 43 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 80, + "d": 139 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 8, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5987.json b/mne-python/source/doc/sphinxext/prs/5987.json new file mode 100644 index 0000000000000000000000000000000000000000..0c74bb3238457138274f104ad2587efaa7c701e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5987.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "25dafcf3cc0a9e53f7ccd2d5117da47400c0a644", + "authors": [ + { + "n": "Jeyhte Key", + "e": "jeythekey@tutanota.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5988.json b/mne-python/source/doc/sphinxext/prs/5988.json new file mode 100644 index 0000000000000000000000000000000000000000..0d51aaba3dd5574f7fe40c183d0cfbebac375ccb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5988.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "541860518239b541eaf7be85db271327ec90085c", + "authors": [ + { + "n": "Jeyhte Key", + "e": "jeythekey@tutanota.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 7, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 33, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5991.json b/mne-python/source/doc/sphinxext/prs/5991.json new file mode 100644 index 0000000000000000000000000000000000000000..70e8608d44b9b71d83cc9a68054dc7654805c065 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5991.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f9d19f48971d23113c2ef047df8910b6da37cd9f", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/datasets/sleep_physionet/_utils.py": { + "a": 1, + "d": 3 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 0, + "d": 1 + }, + "tutorials/plot_sleep.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5998.json b/mne-python/source/doc/sphinxext/prs/5998.json new file mode 100644 index 0000000000000000000000000000000000000000..9f3093ee64612dfa1b95d4a0a424d631deb891dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5998.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "57d33722dc80a5065444031068cac94c73aa9568", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 11, + "d": 1 + }, + "doc/sphinxext/gen_commands.py": { + "a": 3, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/5999.json b/mne-python/source/doc/sphinxext/prs/5999.json new file mode 100644 index 0000000000000000000000000000000000000000..a0431845c9f46b9e47d79d0bc6ac30c83cca57b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/5999.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "693bd2d8c958cd343d1c6ea4f132ad8714a0c116", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 3, + "d": 5 + }, + "mne/forward/forward.py": { + "a": 41, + "d": 42 + }, + "mne/forward/tests/test_forward.py": { + "a": 40, + "d": 9 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 5, + "d": 15 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 6, + "d": 21 + }, + "mne/io/pick.py": { + "a": 42, + "d": 13 + }, + "mne/minimum_norm/inverse.py": { + "a": 70, + "d": 107 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6.json b/mne-python/source/doc/sphinxext/prs/6.json new file mode 100644 index 0000000000000000000000000000000000000000..f4653208fac0a9dd929d02bba758f0bcc6e54646 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "a280a289a55bcec49e62cd3675d52f40994a2ed0", + "authors": [ + { + "n": "Yaroslav Halchenko", + "e": null + } + ], + "changes": { + "doc/source/command_line_tutorial.rst": { + "a": 1, + "d": 1 + }, + "doc/source/manual/AppInstall.rst": { + "a": 1, + "d": 1 + }, + "doc/source/manual/cookbook.rst": { + "a": 3, + "d": 3 + }, + "doc/source/manual/forward.rst": { + "a": 2, + "d": 2 + }, + "doc/source/manual/intro.rst": { + "a": 1, + "d": 1 + }, + "doc/source/manual/matlab.rst": { + "a": 3, + "d": 3 + }, + "doc/source/manual/mne.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/60.json b/mne-python/source/doc/sphinxext/prs/60.json new file mode 100644 index 0000000000000000000000000000000000000000..dc762c64b0b658e421ae2ac5deb2f1814db5452b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/60.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a7b4502fdbc6a41e22ced21a87a62c53146e897a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 63, + "d": 0 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/ar.py": { + "a": 111, + "d": 0 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 42, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/600.json b/mne-python/source/doc/sphinxext/prs/600.json new file mode 100644 index 0000000000000000000000000000000000000000..d3dd1da54987c4b4d0fec6e3f9bcd192bbfa7cbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/600.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ec9ec08976190404846c5357aae761ed83dc581d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fixes.py": { + "a": 96, + "d": 0 + }, + "mne/stats/parametric.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6004.json b/mne-python/source/doc/sphinxext/prs/6004.json new file mode 100644 index 0000000000000000000000000000000000000000..09d32435a834cd84959c4acb585287fb5b9e5199 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6004.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "170e941b09ed18a7d7a83ee2554e8f9b3f40d220", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/data/coil_def.dat": { + "a": 11, + "d": 0 + }, + "mne/io/constants.py": { + "a": 4, + "d": 0 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6005.json b/mne-python/source/doc/sphinxext/prs/6005.json new file mode 100644 index 0000000000000000000000000000000000000000..1bcce42de144bc1ce8a68747cc9005aee8cd1636 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6005.json @@ -0,0 +1,203 @@ +{ + "merge_commit_sha": "e1e1f8bc4bbde70cb5ce48da4d8569714bdd6d7b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 1, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 0, + "d": 5 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 0, + "d": 1 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 3, + "d": 7 + }, + "examples/preprocessing/plot_resample.py": { + "a": 3, + "d": 3 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/plot_topo_compare_conditions.py": { + "a": 0, + "d": 1 + }, + "logo/generate_mne_logos.py": { + "a": 3, + "d": 3 + }, + "mne/bem.py": { + "a": 0, + "d": 3 + }, + "mne/connectivity/spectral.py": { + "a": 108, + "d": 143 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 134, + "d": 138 + }, + "mne/cov.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 0, + "d": 1 + }, + "mne/fixes.py": { + "a": 0, + "d": 10 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_backend.py": { + "a": 31, + "d": 1 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 4, + "d": 3 + }, + "mne/gui/_marker_gui.py": { + "a": 7, + "d": 7 + }, + "mne/gui/_viewer.py": { + "a": 0, + "d": 3 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 5, + "d": 32 + }, + "mne/io/utils.py": { + "a": 0, + "d": 1 + }, + "mne/label.py": { + "a": 0, + "d": 4 + }, + "mne/report.py": { + "a": 4, + "d": 5 + }, + "mne/stats/cluster_level.py": { + "a": 0, + "d": 1 + }, + "mne/surface.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 9, + "d": 10 + }, + "mne/transforms.py": { + "a": 0, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 0, + "d": 29 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_background_filtering.py": { + "a": 2, + "d": 4 + }, + "tutorials/plot_background_statistics.py": { + "a": 0, + "d": 2 + }, + "tutorials/plot_configuration.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_dipole_fit.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_dipole_orientations.py": { + "a": 4, + "d": 4 + }, + "tutorials/plot_ecog.py": { + "a": 3, + "d": 3 + }, + "tutorials/plot_epoching_and_averaging.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 4, + "d": 4 + }, + "tutorials/plot_modifying_data_inplace.py": { + "a": 2, + "d": 2 + }, + "tutorials/plot_receptive_field.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6007.json b/mne-python/source/doc/sphinxext/prs/6007.json new file mode 100644 index 0000000000000000000000000000000000000000..36b93de0f3f266a168495bfaa16190d8e884a6dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6007.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ac83a6c229da94a137d6e15cdbc3af7add7be423", + "authors": [ + { + "n": "Steve Matindi", + "e": null + } + ], + "changes": { + "LICENSE.txt": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6008.json b/mne-python/source/doc/sphinxext/prs/6008.json new file mode 100644 index 0000000000000000000000000000000000000000..df852f66abaec586ffea7c2f4c184a605bd71635 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6008.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a8f17bb0fa7cc70940757c202bbffe4cf46beefc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 8, + "d": 0 + }, + ".gitignore": { + "a": 0, + "d": 1 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/601.json b/mne-python/source/doc/sphinxext/prs/601.json new file mode 100644 index 0000000000000000000000000000000000000000..2644a959aceed98291c5965a80122fceaf59eb00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/601.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c90423c06047e581ff3ac61b522bc45a96ce83c4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6011.json b/mne-python/source/doc/sphinxext/prs/6011.json new file mode 100644 index 0000000000000000000000000000000000000000..faa5f4fbb9013927ea5b272d69335c47dd307628 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6011.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "ce50c2b20ac1197d79e68665900c9f6646505b13", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + ".travis.yml": { + "a": 6, + "d": 5 + }, + "azure-pipelines.yml": { + "a": 77, + "d": 0 + }, + "conftest.py": { + "a": 6, + "d": 2 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 0 + }, + "mne/utils/testing.py": { + "a": 2, + "d": 1 + }, + "requirements.txt": { + "a": 2, + "d": 2 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6012.json b/mne-python/source/doc/sphinxext/prs/6012.json new file mode 100644 index 0000000000000000000000000000000000000000..857f459a0195e9c7186e02aa53f5a84f2703a3f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6012.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2797c6a61087ce4b465db3360c2db7edf61dcd84", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6013.json b/mne-python/source/doc/sphinxext/prs/6013.json new file mode 100644 index 0000000000000000000000000000000000000000..2247f17c43a3f053e85fb7294bd75a70b9dddd4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6013.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3ced40c87a2a3007fc64e17ce1b86601836e52da", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6015.json b/mne-python/source/doc/sphinxext/prs/6015.json new file mode 100644 index 0000000000000000000000000000000000000000..1d25e8a66533d9b9dac987d015d9aa8fe9bafb0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6015.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b6571d655fa053a976320d48f987e5a696062656", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 1, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 5 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6017.json b/mne-python/source/doc/sphinxext/prs/6017.json new file mode 100644 index 0000000000000000000000000000000000000000..b0efd296e9b36747270259aeec4bd4edef09eed0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6017.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "40f3fa070b82ade35d33ae3ec53e19efd92b7152", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/nihon/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 377, + "d": 0 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 65, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6019.json b/mne-python/source/doc/sphinxext/prs/6019.json new file mode 100644 index 0000000000000000000000000000000000000000..cb43fbcda9f6a7b7f8e1cf8aee59342be8f96b78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6019.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "194e2e3dc98dd3b545421d5750eff458263c25e7", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/602.json b/mne-python/source/doc/sphinxext/prs/602.json new file mode 100644 index 0000000000000000000000000000000000000000..b4d7ed192723bc17accfa89f2b2b4ae3171f6f67 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/602.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2c2f4223337a162cd2b39c4d001bd720d8f2cfb5", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 16, + "d": 19 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6020.json b/mne-python/source/doc/sphinxext/prs/6020.json new file mode 100644 index 0000000000000000000000000000000000000000..d84051358efa2b33c6fe6f1256f95fd15d10e699 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6020.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bf4a580cfb05af4b5ff22e0cbc98be3d88c81fa7", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6021.json b/mne-python/source/doc/sphinxext/prs/6021.json new file mode 100644 index 0000000000000000000000000000000000000000..cbefa2084cb489665aeb04fd5035a0ec9f8e756a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6021.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "914f3d2def9643d5d6157381db3b6588094ceb28", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".gitignore": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6022.json b/mne-python/source/doc/sphinxext/prs/6022.json new file mode 100644 index 0000000000000000000000000000000000000000..27bac6427df14e70af82089442715eaad7948b40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6022.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b757ff19c5556e328111661a304d46dff279d818", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6023.json b/mne-python/source/doc/sphinxext/prs/6023.json new file mode 100644 index 0000000000000000000000000000000000000000..3db8ce3c5c9566e8adec18fa87d71d6e8d998dd3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6023.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "64e3f3ba7c2a82ff039a06877334fe48fb400d6d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6025.json b/mne-python/source/doc/sphinxext/prs/6025.json new file mode 100644 index 0000000000000000000000000000000000000000..8c1db15896bf21c1c452a90edb0f747bff0d4b38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6025.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f15e4bc322be80e58398bb23fdff40e87b566437", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 9, + "d": 30 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6026.json b/mne-python/source/doc/sphinxext/prs/6026.json new file mode 100644 index 0000000000000000000000000000000000000000..eb4daffc9d2570e3a088a466fd54bbcdf68b84c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6026.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e6a1f5e6e9640d2d90349b387b1395bf842560d7", + "authors": [ + { + "n": "Nicolas Legrand", + "e": "nicolas.legrand@cas.au.dk" + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6028.json b/mne-python/source/doc/sphinxext/prs/6028.json new file mode 100644 index 0000000000000000000000000000000000000000..c66273270265f606e7e87ab59edc1e71531d9876 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6028.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "56ce204fda6763458540755988f97c76a69bbcbd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 29 + }, + "mne/cov.py": { + "a": 16, + "d": 10 + }, + "mne/io/array/array.py": { + "a": 22, + "d": 9 + }, + "mne/io/array/tests/test_array.py": { + "a": 36, + "d": 0 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 5, + "d": 0 + }, + "mne/io/pick.py": { + "a": 159, + "d": 100 + }, + "mne/io/tests/test_pick.py": { + "a": 130, + "d": 16 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 2, + "d": 4 + }, + "mne/rank.py": { + "a": 27, + "d": 10 + }, + "mne/tests/test_rank.py": { + "a": 38, + "d": 25 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 12, + "d": 5 + }, + "mne/utils/testing.py": { + "a": 7, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6029.json b/mne-python/source/doc/sphinxext/prs/6029.json new file mode 100644 index 0000000000000000000000000000000000000000..33ffd8737182494ae51702bc34a65ad5b8b803dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6029.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0a033205ef720f10d8f71bf0057f8b6bc5ad76eb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/externals/decorator.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 0, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 0, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_background_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_dipole_orientations.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6035.json b/mne-python/source/doc/sphinxext/prs/6035.json new file mode 100644 index 0000000000000000000000000000000000000000..6e0ff7fc01bb83e75af3e7bc52485ff41613e1f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6035.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "03771c19f6275067a861381261baa4058565c31d", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "mne/externals/pymatreader/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6036.json b/mne-python/source/doc/sphinxext/prs/6036.json new file mode 100644 index 0000000000000000000000000000000000000000..c9f372357c17271b14f6b8fd8e0085621d941def --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6036.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cffcf4b1aeaf04655f6917718029c59ff412c917", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 8, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 0 + }, + "mne/utils/check.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6037.json b/mne-python/source/doc/sphinxext/prs/6037.json new file mode 100644 index 0000000000000000000000000000000000000000..44208d450c88ed5c183228dabc38e748b87d5b44 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6037.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "f7dc2398ec827702d1998c13b119e2e05b0f74a3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "conftest.py": { + "a": 2, + "d": 6 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 7, + "d": 1 + }, + "examples/simulation/plot_simulate_raw_data.py": { + "a": 17, + "d": 15 + }, + "mne/datasets/testing/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/testing/_testing.py": { + "a": 8, + "d": 0 + }, + "mne/filter.py": { + "a": 11, + "d": 20 + }, + "mne/forward/_field_interpolation.py": { + "a": 2, + "d": 4 + }, + "mne/forward/forward.py": { + "a": 67, + "d": 44 + }, + "mne/io/base.py": { + "a": 5, + "d": 4 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 7, + "d": 4 + }, + "mne/simulation/raw.py": { + "a": 580, + "d": 353 + }, + "mne/simulation/tests/test_raw.py": { + "a": 286, + "d": 113 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 5 + }, + "mne/source_space.py": { + "a": 15, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 7, + "d": 21 + }, + "mne/utils/docs.py": { + "a": 35, + "d": 0 + }, + "tutorials/plot_dics.py": { + "a": 27, + "d": 43 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/604.json b/mne-python/source/doc/sphinxext/prs/604.json new file mode 100644 index 0000000000000000000000000000000000000000..d00031218c0c564581df6f58a6c78274a5462b06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/604.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "54d655264475c519589cc70a131e2edeba7bee04", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/plot_single_trial_spectra.py": { + "a": 84, + "d": 0 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 68, + "d": 6 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 51, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6040.json b/mne-python/source/doc/sphinxext/prs/6040.json new file mode 100644 index 0000000000000000000000000000000000000000..3aca484323648b9795e2056aedffb3b65b402353 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6040.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "208991216be438e61d6e62bdd0b8b3a5d87c7604", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6041.json b/mne-python/source/doc/sphinxext/prs/6041.json new file mode 100644 index 0000000000000000000000000000000000000000..1ffcbbf85beb27612e7c35b0d73c34049b83552e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6041.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "52cf011b50a26b05df3992530fef807a14311b40", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 4, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6042.json b/mne-python/source/doc/sphinxext/prs/6042.json new file mode 100644 index 0000000000000000000000000000000000000000..99ca130e5b1c1041e08cfc2ac8483a4a968c49c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6042.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "7e0e09f4c2bdfc9d938fb709a6c07e055957ba4f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 17, + "d": 10 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 83, + "d": 102 + }, + "mne/beamformer/_dics.py": { + "a": 22, + "d": 109 + }, + "mne/beamformer/_lcmv.py": { + "a": 50, + "d": 58 + }, + "mne/beamformer/_rap_music.py": { + "a": 7, + "d": 13 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 48, + "d": 38 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 53, + "d": 24 + }, + "mne/cov.py": { + "a": 3, + "d": 5 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 41, + "d": 33 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 35, + "d": 25 + }, + "mne/rank.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 9, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6044.json b/mne-python/source/doc/sphinxext/prs/6044.json new file mode 100644 index 0000000000000000000000000000000000000000..50d088c00a2636c5d70c4a72474163f07b9095b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6044.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "01a1aef46792d22dff39f38516268434a2497795", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6045.json b/mne-python/source/doc/sphinxext/prs/6045.json new file mode 100644 index 0000000000000000000000000000000000000000..342bf279a6db530e19be225c0f68ed07f5c97a76 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6045.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b52c9d5436bd3d887750249f47a24ec77dcd3c0d", + "authors": [ + { + "n": "Sebastián Castaño-Candamil", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6046.json b/mne-python/source/doc/sphinxext/prs/6046.json new file mode 100644 index 0000000000000000000000000000000000000000..a129accda7d5d807e3fef36c1547d7c505090f79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6046.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "951df43c1ae96c5cc94043eadfd2fca0602c126f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 10, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 32, + "d": 15 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/fixes.py": { + "a": 8, + "d": 0 + }, + "mne/morph.py": { + "a": 59, + "d": 53 + }, + "mne/source_estimate.py": { + "a": 9, + "d": 6 + }, + "mne/source_space.py": { + "a": 13, + "d": 18 + }, + "mne/tests/test_morph.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_source_estimate.py": { + "a": 3, + "d": 3 + }, + "mne/transforms.py": { + "a": 25, + "d": 7 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 15, + "d": 0 + }, + "mne/utils/check.py": { + "a": 9, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 248, + "d": 134 + }, + "mne/viz/tests/test_3d.py": { + "a": 64, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6047.json b/mne-python/source/doc/sphinxext/prs/6047.json new file mode 100644 index 0000000000000000000000000000000000000000..9e27a9c1e5590e64213d4a553984c74b8a40a06b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6047.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "9d71dc0c315190bb1572f534b55904035b54af59", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 0 + }, + "mne/annotations.py": { + "a": 4, + "d": 0 + }, + "mne/io/cnt/_utils.py": { + "a": 95, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 199, + "d": 81 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 35, + "d": 0 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 17, + "d": 15 + }, + "mne/io/utils.py": { + "a": 29, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6053.json b/mne-python/source/doc/sphinxext/prs/6053.json new file mode 100644 index 0000000000000000000000000000000000000000..66fb663a75f755b49fdb5e343361fdea1356c5be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6053.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c4c3abcd26bef60be757a02b90c7f7911292d0d5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 3, + "d": 2 + }, + "mne/connectivity/envelope.py": { + "a": 4, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6055.json b/mne-python/source/doc/sphinxext/prs/6055.json new file mode 100644 index 0000000000000000000000000000000000000000..620d808fd0d0a673c03030cdb3ab4f4850998bae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6055.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "69a5b6aee344413a97e42aed3a6051fac8caea57", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 10, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6056.json b/mne-python/source/doc/sphinxext/prs/6056.json new file mode 100644 index 0000000000000000000000000000000000000000..e68f31766f93a3fac55a616f86a140fdab05f1c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6056.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "39fdbdc0111ca6b80157cbee45c8e929769b094b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 72, + "d": 60 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6057.json b/mne-python/source/doc/sphinxext/prs/6057.json new file mode 100644 index 0000000000000000000000000000000000000000..78bca08f8c968db2656ed7e67f231e47daaf091e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6057.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7686801d1c4bf05b536b6078d51ef82d3bfe8cdb", + "authors": [ + { + "n": "Nicolas Legrand", + "e": "nicolas.legrand@cas.au.dk" + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6058.json b/mne-python/source/doc/sphinxext/prs/6058.json new file mode 100644 index 0000000000000000000000000000000000000000..bbc12d172420933f8b15f618814f585505cade09 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6058.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9324ffdaabc6c7d41785675592a65892525dad8c", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 3, + "d": 4 + }, + "appveyor.yml": { + "a": 0, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/606.json b/mne-python/source/doc/sphinxext/prs/606.json new file mode 100644 index 0000000000000000000000000000000000000000..67ede0400a4919496e23903c30ed6fd25baa36f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/606.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5de74c891e199595123910390ebf4af9625c8149", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 48, + "d": 19 + }, + "mne/fiff/proj.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6060.json b/mne-python/source/doc/sphinxext/prs/6060.json new file mode 100644 index 0000000000000000000000000000000000000000..6fc12449709ef7aa644a5932e81fef4e0fc62c35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6060.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "41f6f2bcd0b8e90807837e131314be81e0cd5ca6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 1, + "d": 0 + }, + "mne/utils/fetching.py": { + "a": 18, + "d": 11 + }, + "mne/utils/tests/test_fetching.py": { + "a": 25, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6061.json b/mne-python/source/doc/sphinxext/prs/6061.json new file mode 100644 index 0000000000000000000000000000000000000000..97e0625fc0237cdd21ad489a31931baf6fe3deb4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6061.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "717eedd5f9ce22431e40a15c378863de6730d3e8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 3, + "d": 4 + }, + "mne/viz/raw.py": { + "a": 44, + "d": 31 + }, + "mne/viz/tests/test_raw.py": { + "a": 13, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6063.json b/mne-python/source/doc/sphinxext/prs/6063.json new file mode 100644 index 0000000000000000000000000000000000000000..7e1d52ca326b7c83eb297137e97be30c9574d4ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6063.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f2594e24244353a950cbb2728d07ae63bcc30115", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6064.json b/mne-python/source/doc/sphinxext/prs/6064.json new file mode 100644 index 0000000000000000000000000000000000000000..c93adaac1f84537581936f871430f58d68f6a8b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6064.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5e46b9748412ef5059f57f702954855c41f9ab49", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_flash_bem.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6065.json b/mne-python/source/doc/sphinxext/prs/6065.json new file mode 100644 index 0000000000000000000000000000000000000000..d4a15cbaf50e572995cea5b79f09feb5d9d4d1a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6065.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "100f0d8580c0a75b6177a081b1216dc30fd7cbbf", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 11, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6066.json b/mne-python/source/doc/sphinxext/prs/6066.json new file mode 100644 index 0000000000000000000000000000000000000000..4ef66d5afa9760de776013e82b8bdd0ff92b795c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6066.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "32bf58dfb3f0b6c61faba5b7b33f4565eb36a205", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/egi/egimff.py": { + "a": 3, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6067.json b/mne-python/source/doc/sphinxext/prs/6067.json new file mode 100644 index 0000000000000000000000000000000000000000..299744f5045f66e6f882fa3d23d73067416c0bbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6067.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "561ded7f8fa4c2c63ca8f429a2da98323d28d311", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 3, + "d": 8 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 7 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6068.json b/mne-python/source/doc/sphinxext/prs/6068.json new file mode 100644 index 0000000000000000000000000000000000000000..fc5033803b4436ccd1f68b3111879258e5ba12a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6068.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d11419306011a484405dc1e2a882c50a71e7f6bf", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/607.json b/mne-python/source/doc/sphinxext/prs/607.json new file mode 100644 index 0000000000000000000000000000000000000000..bdfbed92843c73908f14f0a4b0163d592eee1c51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/607.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c244a50e94036835221c4ff471856edea79fc696", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 6, + "d": 19 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 6, + "d": 20 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 6, + "d": 20 + }, + "mne/stats/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 55, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 16, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6070.json b/mne-python/source/doc/sphinxext/prs/6070.json new file mode 100644 index 0000000000000000000000000000000000000000..0ac6d45f412f27d2691229aea0bd100e4bb76d03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6070.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2a0a55c6a795f618cf0a1603e22a72ee8e879f62", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/constants.py": { + "a": 5, + "d": 2 + }, + "mne/io/tests/test_constants.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6073.json b/mne-python/source/doc/sphinxext/prs/6073.json new file mode 100644 index 0000000000000000000000000000000000000000..4d9728bb9b5ca3f15a2787a2fb612ae2d9e55b8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6073.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7288928c346a49efd3489c848fadff9dbc4c9f81", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6076.json b/mne-python/source/doc/sphinxext/prs/6076.json new file mode 100644 index 0000000000000000000000000000000000000000..190fe61e91d8d8c3cea21f7da7e8b1eb2ca86fe4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6076.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c37acb9d6166e2a5fa32698748ffdc8e3b8247ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6079.json b/mne-python/source/doc/sphinxext/prs/6079.json new file mode 100644 index 0000000000000000000000000000000000000000..858ad4180c7dcf9c117da199b27d2c001277484b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6079.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5fc58e5ddd6afb7f2bfd7f22a579fb91001815af", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/configure_git.rst": { + "a": 44, + "d": 40 + }, + "doc/git_links.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6080.json b/mne-python/source/doc/sphinxext/prs/6080.json new file mode 100644 index 0000000000000000000000000000000000000000..788d85b68a5f38096ea30d104f35ad0c654d2aa3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6080.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fd667a2e4270d42e7a4942a1746dde4fee85a7ff", + "authors": [ + { + "n": "Dirk Gütlin", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 16, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 29, + "d": 8 + }, + "mne/utils/__init__.py": { + "a": 5, + "d": 5 + }, + "mne/utils/numerics.py": { + "a": 28, + "d": 0 + }, + "mne/utils/tests/test_numerics.py": { + "a": 35, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6081.json b/mne-python/source/doc/sphinxext/prs/6081.json new file mode 100644 index 0000000000000000000000000000000000000000..7bc8614510c0d66321dafd79dc1aca439ca04b66 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6081.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "b74bb10d779dfd8144a4b6fd8fc5444f441f2141", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fixes.py": { + "a": 90, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 10 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 13 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 11, + "d": 10 + }, + "mne/utils/_testing.py": { + "a": 11, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 93, + "d": 0 + }, + "mne/utils/tests/test_numerics.py": { + "a": 40, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6083.json b/mne-python/source/doc/sphinxext/prs/6083.json new file mode 100644 index 0000000000000000000000000000000000000000..d444fa07be1fafdc181eb4c8af2cbf60f89fdb51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6083.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1d31e89d7c23aca1f4b6aedec85b611237dc3f3e", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6088.json b/mne-python/source/doc/sphinxext/prs/6088.json new file mode 100644 index 0000000000000000000000000000000000000000..3abafe04cc2ea567279938b336be552cfa89605a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6088.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "c30e70c53cd25997a8a9831ab5c3e827dd5f2966", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 3, + "d": 19 + }, + "mne/filter.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/flat.py": { + "a": 99, + "d": 0 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 61, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 15, + "d": 0 + }, + "mne/utils/progressbar.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6089.json b/mne-python/source/doc/sphinxext/prs/6089.json new file mode 100644 index 0000000000000000000000000000000000000000..8998f9b4a6ccf7b35852575d527be1239ae304c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6089.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8610eddc10d2e32bdb42e59085aaae506819e140", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/decoding/receptive_field.py": { + "a": 8, + "d": 8 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 5, + "d": 1 + }, + "tutorials/plot_receptive_field.py": { + "a": 1, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6092.json b/mne-python/source/doc/sphinxext/prs/6092.json new file mode 100644 index 0000000000000000000000000000000000000000..ade0c78302cbd6bfd76f013918ac68dfa9131c8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6092.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0078e1af13a92ab47498dd167bc5ec73be864427", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 6, + "d": 3 + }, + "mne/tests/test_annotations.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6095.json b/mne-python/source/doc/sphinxext/prs/6095.json new file mode 100644 index 0000000000000000000000000000000000000000..d2b01c0021a945b9f7a4da588ee09283ddbe5b9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6095.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d7cb4380664368ea9aa12efb5157058d66921323", + "authors": [ + { + "n": "Achilleas Koutsou", + "e": "achilleas@koutsou.net" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6098.json b/mne-python/source/doc/sphinxext/prs/6098.json new file mode 100644 index 0000000000000000000000000000000000000000..01c71e56e8335392c87a1688aa8ccc8cdf59a382 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6098.json @@ -0,0 +1,159 @@ +{ + "merge_commit_sha": "f384253d77d46893d91c4ae678ff50f7287cc384", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "doc/_static/style.css": { + "a": 33, + "d": 17 + }, + "doc/conf.py": { + "a": 3, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 1, + "d": 10 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 2 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 3, + "d": 4 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 2 + }, + "mne/io/constants.py": { + "a": 3, + "d": 18 + }, + "mne/io/ctf/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 39, + "d": 39 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 221, + "d": 223 + }, + "mne/io/kit/constants.py": { + "a": 4, + "d": 3 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 3, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 65, + "d": 13 + }, + "mne/io/tests/test_meas_info.py": { + "a": 11, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 5, + "d": 5 + }, + "mne/morph.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 42, + "d": 44 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 9, + "d": 10 + }, + "mne/source_space.py": { + "a": 4, + "d": 1 + }, + "mne/tests/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/tests/common.py": { + "a": 0, + "d": 106 + }, + "mne/tests/test_chpi.py": { + "a": 5, + "d": 8 + }, + "mne/tests/test_cov.py": { + "a": 10, + "d": 12 + }, + "mne/tests/test_dipole.py": { + "a": 32, + "d": 34 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 7 + }, + "mne/utils/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/utils/_bunch.py": { + "a": 93, + "d": 0 + }, + "mne/utils/_testing.py": { + "a": 101, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6099.json b/mne-python/source/doc/sphinxext/prs/6099.json new file mode 100644 index 0000000000000000000000000000000000000000..623a1f0ef5807b5f99190ed1a4b49d24c6e75dbe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6099.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "87cb63994a9ade4a0a0675f14ec2bb1edff88d65", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/61.json b/mne-python/source/doc/sphinxext/prs/61.json new file mode 100644 index 0000000000000000000000000000000000000000..5627986d5f941596bed0b6cb63d7a14c8d804ad7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/61.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7fa79864d502199866a5348b67865827aa0f9010", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/datasets/sample/__init__.py": { + "a": 44, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/610.json b/mne-python/source/doc/sphinxext/prs/610.json new file mode 100644 index 0000000000000000000000000000000000000000..40d1154e05adbe7798f274afb45a0ba735953a2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/610.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6ce8b7110aa91bee4e61219de72863aadd6b4de9", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 20, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6100.json b/mne-python/source/doc/sphinxext/prs/6100.json new file mode 100644 index 0000000000000000000000000000000000000000..9aa600d1e2fd9c338f2302d73b64df7d2cfdf05d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6100.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "673573cabc21f7414741fee7e9c417d0e5f1d4b5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 29, + "d": 0 + }, + "doc/sphinxext/gen_commands.py": { + "a": 39, + "d": 14 + }, + "mne/commands/mne_browse_raw.py": { + "a": 6, + "d": 4 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 17, + "d": 11 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 5, + "d": 2 + }, + "mne/commands/mne_compare_fiff.py": { + "a": 5, + "d": 2 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 7, + "d": 4 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 12, + "d": 8 + }, + "mne/commands/mne_coreg.py": { + "a": 6, + "d": 1 + }, + "mne/commands/mne_flash_bem.py": { + "a": 24, + "d": 20 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 5, + "d": 2 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 11, + "d": 2 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 6, + "d": 1 + }, + "mne/commands/mne_maxfilter.py": { + "a": 4, + "d": 2 + }, + "mne/commands/mne_report.py": { + "a": 7, + "d": 4 + }, + "mne/commands/mne_show_fiff.py": { + "a": 9, + "d": 3 + }, + "mne/commands/mne_show_info.py": { + "a": 6, + "d": 2 + }, + "mne/commands/mne_surf2bem.py": { + "a": 7, + "d": 3 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6103.json b/mne-python/source/doc/sphinxext/prs/6103.json new file mode 100644 index 0000000000000000000000000000000000000000..37c6d2cd418fb6ad8a488867cebf24fce535ef8f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6103.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "9d521373a4d4c1ca89e975c43348d2d5a6ff8d6f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/effective.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 26, + "d": 20 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/flat.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 12, + "d": 10 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 22, + "d": 8 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6104.json b/mne-python/source/doc/sphinxext/prs/6104.json new file mode 100644 index 0000000000000000000000000000000000000000..dd2026c002ee70a25872f3d2756f81b02b4e6fac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6104.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "eefbd78658664acd889887d4cb3e571db057b938", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 16, + "d": 13 + }, + "mne/time_frequency/tfr.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6105.json b/mne-python/source/doc/sphinxext/prs/6105.json new file mode 100644 index 0000000000000000000000000000000000000000..8037ac68f2014ce4143b5a656d52a4b98630d714 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6105.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0bb4e479e385fd9c67b469f8ea0ae00bb3c54bd9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_peak_finder.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6106.json b/mne-python/source/doc/sphinxext/prs/6106.json new file mode 100644 index 0000000000000000000000000000000000000000..1eda09926e3788eacb0e86204d5be60e5cb8a5ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6106.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a35bcc361778de096ba2803ed255d8acf587b3dc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/git_links.inc": { + "a": 1, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6108.json b/mne-python/source/doc/sphinxext/prs/6108.json new file mode 100644 index 0000000000000000000000000000000000000000..638b2dfbb0dbef303a556882d18434def62189c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6108.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "027f82d79b8055bad5c997829d409035de348fe8", + "authors": [ + { + "n": "Katarina Slama", + "e": "slamakatarina@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 22, + "d": 2 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 71, + "d": 24 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6110.json b/mne-python/source/doc/sphinxext/prs/6110.json new file mode 100644 index 0000000000000000000000000000000000000000..a83d948aa0dda5cef6c6bdc2c2c232b656453911 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6110.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "3cc76b9f0058ade446411f5c0cfa362e073d29f6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 2, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation_volume.py": { + "a": 96, + "d": 0 + }, + "mne/connectivity/envelope.py": { + "a": 16, + "d": 9 + }, + "mne/epochs.py": { + "a": 5, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 144, + "d": 0 + }, + "mne/io/base.py": { + "a": 4, + "d": 124 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/parallel.py": { + "a": 9, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 26, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 5, + "d": 5 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6111.json b/mne-python/source/doc/sphinxext/prs/6111.json new file mode 100644 index 0000000000000000000000000000000000000000..69a376062a383b59a1828005aa9018dd27144a84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6111.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9b5ae5104ecdeaea13a88273c712382bf131162c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/topo.py": { + "a": 20, + "d": 16 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6113.json b/mne-python/source/doc/sphinxext/prs/6113.json new file mode 100644 index 0000000000000000000000000000000000000000..b82af474ca41d2170c8cd31243385dfecb763a2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6113.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "dd3cc4b087975357becef12a2f7258ada5b28478", + "authors": [ + { + "n": "José C. García Alanis", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 4, + "d": 0 + }, + "examples/datasets/plot_limo_data.py": { + "a": 178, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/limo/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/limo/limo.py": { + "a": 225, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6115.json b/mne-python/source/doc/sphinxext/prs/6115.json new file mode 100644 index 0000000000000000000000000000000000000000..a9d08bb0b92e4640f4bcd33e2e9943a2f7ad86e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6115.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "127a75c55ca614477a927637e39cd3473535121e", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/utils/config.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6118.json b/mne-python/source/doc/sphinxext/prs/6118.json new file mode 100644 index 0000000000000000000000000000000000000000..8e142f2d612db0d9e160973c76ea5cafa4e3035f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6118.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "56909cdbf35511d9837a5999ce1ffe2f47eee7bb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/autosummary/class.rst": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/612.json b/mne-python/source/doc/sphinxext/prs/612.json new file mode 100644 index 0000000000000000000000000000000000000000..0c4c38e9f7f59f07f5570155f372a9cd85de6312 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/612.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "7851b08c73d83fcbdb63230de90cfc47917345b8", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 2, + "d": 2 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/epochs.py": { + "a": 8, + "d": 19 + }, + "mne/fiff/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/fiff/compensator.py": { + "a": 89, + "d": 116 + }, + "mne/fiff/ctf.py": { + "a": 7, + "d": 9 + }, + "mne/fiff/kit/kit.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/raw.py": { + "a": 52, + "d": 20 + }, + "mne/fiff/tests/data/test_ctf_comp_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/fiff/tests/test_compensator.py": { + "a": 20, + "d": 0 + }, + "mne/fiff/tests/test_raw.py": { + "a": 37, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6120.json b/mne-python/source/doc/sphinxext/prs/6120.json new file mode 100644 index 0000000000000000000000000000000000000000..1ddaec54aed15418d4bdc2a146d9ee1cf18cf742 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6120.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "56106059442264c43cdd489684418a35b2135fe4", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/realtime/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/realtime/base_client.py": { + "a": 199, + "d": 0 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 2, + "d": 2 + }, + "mne/realtime/lsl_client.py": { + "a": 120, + "d": 0 + }, + "mne/realtime/tests/test_lsl_client.py": { + "a": 67, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 3, + "d": 3 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 0 + }, + "mne/utils/check.py": { + "a": 13, + "d": 0 + }, + "requirements.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6122.json b/mne-python/source/doc/sphinxext/prs/6122.json new file mode 100644 index 0000000000000000000000000000000000000000..bcd92d89151e3966637de238d5d6f1b14ff9cacf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6122.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c2a5fe704e89ee4910049e7509cc17daac180e88", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 32, + "d": 24 + }, + "mne/viz/tests/test_evoked.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6124.json b/mne-python/source/doc/sphinxext/prs/6124.json new file mode 100644 index 0000000000000000000000000000000000000000..2a171cb7208aa00b850508dab8890e66ad2537d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6124.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6e1a2ba41e442a148d68bbcb06bb895099e29333", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6126.json b/mne-python/source/doc/sphinxext/prs/6126.json new file mode 100644 index 0000000000000000000000000000000000000000..988659de942d233d169dd44b3b05017b2d11a070 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6126.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8f52bc76f3992db96098ace9479c3f9c912b59bf", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "tutorials/plot_introduction.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_object_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6129.json b/mne-python/source/doc/sphinxext/prs/6129.json new file mode 100644 index 0000000000000000000000000000000000000000..f4383ba5001c17945a2bbbbb0594481eb0f20c03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6129.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6b2d50e6ddbf2b274cec084b0e8ab8c29549afb9", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "tutorials/plot_object_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6131.json b/mne-python/source/doc/sphinxext/prs/6131.json new file mode 100644 index 0000000000000000000000000000000000000000..acf148874d30529773649e168cf15c922a58652f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6131.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "205e9b2fe1e552ee6b76cfa5be0a6d64fd792fa1", + "authors": [ + { + "n": "Bruno Nicenboim", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/cuda.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6132.json b/mne-python/source/doc/sphinxext/prs/6132.json new file mode 100644 index 0000000000000000000000000000000000000000..62ced5c99f1a658c43195c5672247749fe5d4976 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6132.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d3747b5d05f214eb3745492fcd2160bb596c1ce9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 9, + "d": 4 + }, + "mne/tests/test_report.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6133.json b/mne-python/source/doc/sphinxext/prs/6133.json new file mode 100644 index 0000000000000000000000000000000000000000..f17f73cfe8359646411e03d5b286682f6f5b48d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6133.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f108848606d63434f6bb667954a3914327736b49", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 21, + "d": 11 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 15, + "d": 10 + }, + "mne/tests/test_bem.py": { + "a": 30, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6134.json b/mne-python/source/doc/sphinxext/prs/6134.json new file mode 100644 index 0000000000000000000000000000000000000000..1b9a8d8d9d510994aa8ac3b3dc7c28df1406765d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6134.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "546a2bbc3422af65def90706828d9e7f1a82ca62", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 2, + "d": 1 + }, + "mne/connectivity/utils.py": { + "a": 10, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6135.json b/mne-python/source/doc/sphinxext/prs/6135.json new file mode 100644 index 0000000000000000000000000000000000000000..27e641dbdc0c386c7f4cc8dcc12ed10a7376d94b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6135.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "35d7c539c93bd0bff7788fad93ce08686e0cc760", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_space.py": { + "a": 40, + "d": 38 + }, + "mne/surface.py": { + "a": 43, + "d": 3 + }, + "mne/tests/test_source_space.py": { + "a": 38, + "d": 21 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6136.json b/mne-python/source/doc/sphinxext/prs/6136.json new file mode 100644 index 0000000000000000000000000000000000000000..610135123886480fba820de2c63e9f74f29b98a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6136.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "cd3f4fb2fe42d99d3eaa2d6a7d1dc56e08d69749", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/connectivity/envelope.py": { + "a": 15, + "d": 12 + }, + "mne/connectivity/tests/test_envelope.py": { + "a": 9, + "d": 5 + }, + "mne/epochs.py": { + "a": 3, + "d": 16 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6139.json b/mne-python/source/doc/sphinxext/prs/6139.json new file mode 100644 index 0000000000000000000000000000000000000000..c39ffd9de29966b6282548eba3a504f2b7de1cb6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6139.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "aa74f02c3be4e69963b78cf835af9b9e08a81a67", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_label.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/614.json b/mne-python/source/doc/sphinxext/prs/614.json new file mode 100644 index 0000000000000000000000000000000000000000..62df19a5f0d5810e06d005f31503e95eddb55f67 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/614.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "04b6e4c7a1912f0d0e311749cf51e2cd723d8fd3", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 11, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6141.json b/mne-python/source/doc/sphinxext/prs/6141.json new file mode 100644 index 0000000000000000000000000000000000000000..fcb2ab794a82b38ad29e53a9eb8517cd471648a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6141.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "c9fa690f0d551f4290872e1a4fba69d25ea2f6a3", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_lslclient_rt.py": { + "a": 55, + "d": 0 + }, + "mne/realtime/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/realtime/base_client.py": { + "a": 16, + "d": 3 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 93, + "d": 200 + }, + "mne/realtime/lsl_client.py": { + "a": 5, + "d": 5 + }, + "mne/realtime/mock_lsl_stream.py": { + "a": 83, + "d": 0 + }, + "mne/realtime/tests/test_lsl_client.py": { + "a": 24, + "d": 44 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6142.json b/mne-python/source/doc/sphinxext/prs/6142.json new file mode 100644 index 0000000000000000000000000000000000000000..df47781da15b78f8535cf129f94f2e445c3e1cfd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6142.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "55ac67e0862ac517daa91c7c25eb99a13ea2a578", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "conftest.py": { + "a": 17, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 46, + "d": 58 + }, + "mne/viz/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 66, + "d": 47 + }, + "mne/viz/backends/_utils.py": { + "a": 21, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 47, + "d": 23 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 23, + "d": 0 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 53, + "d": 14 + }, + "mne/viz/tests/test_3d.py": { + "a": 35, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6143.json b/mne-python/source/doc/sphinxext/prs/6143.json new file mode 100644 index 0000000000000000000000000000000000000000..3fdd87a7faa2942dfeed458ab6ebbb012a14be0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6143.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "aa7b3a0ba1038e6ad7fb357e60844696e234c40b", + "authors": [ + { + "n": "Nichalas", + "e": "nikos.ch01@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/event.py": { + "a": 7, + "d": 3 + }, + "mne/tests/test_event.py": { + "a": 19, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6145.json b/mne-python/source/doc/sphinxext/prs/6145.json new file mode 100644 index 0000000000000000000000000000000000000000..9bfb840ce5eec3bfe9cee0bf995f762eeb8c21d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6145.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bc5bd2dd0ea17f87c9f887ed48fc48d3f19094c1", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6146.json b/mne-python/source/doc/sphinxext/prs/6146.json new file mode 100644 index 0000000000000000000000000000000000000000..152ce0f0ccf2dc699d8c5302f18a02e19d2894fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6146.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "639b7381d0f3f57bfdeaa94513fece040a3dc8fb", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/manual/datasets_index.rst": { + "a": 4, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "tutorials/plot_eeg_no_mri.py": { + "a": 76, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6147.json b/mne-python/source/doc/sphinxext/prs/6147.json new file mode 100644 index 0000000000000000000000000000000000000000..9084acdb78a6e2b21a2e7af8668e3e7405ff45ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6147.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b147676776d20d0027801a4ea3d83dbe8bc24d36", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6149.json b/mne-python/source/doc/sphinxext/prs/6149.json new file mode 100644 index 0000000000000000000000000000000000000000..d01ce4fc2eea1d46ad62d23b409feef25668b275 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6149.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9a47e8e2b3c1f55a26683fee2f6d498cfca74802", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6150.json b/mne-python/source/doc/sphinxext/prs/6150.json new file mode 100644 index 0000000000000000000000000000000000000000..bbd23773f1b7f72b8c8cf8f5e13b0bebd1088ca5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6150.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "57bcaa877b896a4b7ccaca3207de81bf73e8b51b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6151.json b/mne-python/source/doc/sphinxext/prs/6151.json new file mode 100644 index 0000000000000000000000000000000000000000..804b8cf2880fc01044948192d88dcc8828aae90c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6151.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4555011717b9008f41eaa4926d598bb570e42fca", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 11, + "d": 3 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 22, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6152.json b/mne-python/source/doc/sphinxext/prs/6152.json new file mode 100644 index 0000000000000000000000000000000000000000..a78d2f51f60d7877f0cf19cf2defbddbf0389441 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6152.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "ece75432a4d51692dfc946fc7e6615be00b6a0dd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/_static/style.css": { + "a": 4, + "d": 0 + }, + "doc/_templates/autosummary/class.rst": { + "a": 1, + "d": 3 + }, + "doc/conf.py": { + "a": 41, + "d": 69 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 3, + "d": 0 + }, + "mne/bem.py": { + "a": 3, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_lead_dots.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_background_filtering.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6153.json b/mne-python/source/doc/sphinxext/prs/6153.json new file mode 100644 index 0000000000000000000000000000000000000000..32b87fbfde3ea4d2d088b1d2f8812fdb201869b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6153.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "3f9399f90d6660f8dcd27b00fbd4bb0b48ecf477", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 7, + "d": 0 + }, + "conftest.py": { + "a": 9, + "d": 4 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_vtki.py": { + "a": 296, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 16, + "d": 5 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 16, + "d": 10 + }, + "requirements.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6158.json b/mne-python/source/doc/sphinxext/prs/6158.json new file mode 100644 index 0000000000000000000000000000000000000000..67349369b4fcd0ec943536cf60fb2537daacbbe0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6158.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0b637d8bafeccf44ff7046cc4ef9b42bc8b7c050", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "examples/visualization/plot_montage.py": { + "a": 47, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 13, + "d": 7 + }, + "tutorials/plot_eeg_no_mri.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6160.json b/mne-python/source/doc/sphinxext/prs/6160.json new file mode 100644 index 0000000000000000000000000000000000000000..19825d53284bf0e91c7119d65ed042858b0a3d8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6160.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b3183fc68982d4a7d25b6488b06adcdfad53453c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/proj.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 36, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6161.json b/mne-python/source/doc/sphinxext/prs/6161.json new file mode 100644 index 0000000000000000000000000000000000000000..f9698ddf50deec6fd2e48a2d28b87d9648b3db33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6161.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2c215d8f61e79f86a908da7f9e995819c5d62ddf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 15, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6169.json b/mne-python/source/doc/sphinxext/prs/6169.json new file mode 100644 index 0000000000000000000000000000000000000000..8133943a286be80d0f90cbdfa3f8e6ada325db13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6169.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "69dbf4bbc1045e55894750bfac8f6aece2c20b1f", + "authors": [ + { + "n": "Dirk Gütlin", + "e": null + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 12, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6172.json b/mne-python/source/doc/sphinxext/prs/6172.json new file mode 100644 index 0000000000000000000000000000000000000000..f365d65d17063e24e6d50d67496a7859ac4da25e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6172.json @@ -0,0 +1,10 @@ +{ + "merge_commit_sha": "8ac51be3e8eeaeb25adaafd8d580fee4dff0f558", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": {} +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6173.json b/mne-python/source/doc/sphinxext/prs/6173.json new file mode 100644 index 0000000000000000000000000000000000000000..13abecdf432340e702bf52438faa27dc197eb895 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6173.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "52949f1bea6d21fc286997838239e3b8109998de", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6174.json b/mne-python/source/doc/sphinxext/prs/6174.json new file mode 100644 index 0000000000000000000000000000000000000000..375387ef9da3ee6c055eb577f396a122901d3d08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6174.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "9cc5d1457c29151eea73fa7f14619724182960c1", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 0 + }, + "MANIFEST.in": { + "a": 2, + "d": 0 + }, + "doc/manual/datasets_index.rst": { + "a": 7, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 9, + "d": 0 + }, + "mne/datasets/_fsaverage/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 146, + "d": 0 + }, + "mne/datasets/_fsaverage/bem.txt": { + "a": 11, + "d": 0 + }, + "mne/datasets/_fsaverage/root.txt": { + "a": 179, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 67, + "d": 18 + }, + "mne/datasets/utils.py": { + "a": 35, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6175.json b/mne-python/source/doc/sphinxext/prs/6175.json new file mode 100644 index 0000000000000000000000000000000000000000..cb4de9d442f086c5c186c24a551bfe95190a0002 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6175.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8aad459ab6d1443b38c5699822886a83ba2a8388", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/datasets/_fsaverage/base.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 11, + "d": 4 + }, + "mne/utils/tests/test_config.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6176.json b/mne-python/source/doc/sphinxext/prs/6176.json new file mode 100644 index 0000000000000000000000000000000000000000..a3b6f7dfa7727501e6db02c35cb1851cd4ed26f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6176.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "b94eff339a5be230fce74ead7e562f7813b8c40d", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 18, + "d": 6 + }, + "doc/conf.py": { + "a": 5, + "d": 1 + }, + "doc/documentation.rst": { + "a": 4, + "d": 3 + }, + "examples/realtime/ftclient_rt_average.py": { + "a": 0, + "d": 94 + }, + "examples/realtime/ftclient_rt_compute_psd.py": { + "a": 0, + "d": 79 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 2, + "d": 2 + }, + "examples/realtime/plot_ftclient_rt_average.py": { + "a": 104, + "d": 0 + }, + "examples/realtime/plot_ftclient_rt_compute_psd.py": { + "a": 90, + "d": 0 + }, + "examples/realtime/plot_lslclient_rt.py": { + "a": 16, + "d": 20 + }, + "examples/realtime/plot_rt_feedback_server.py": { + "a": 124, + "d": 0 + }, + "examples/realtime/rt_feedback_client.py": { + "a": 0, + "d": 1 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 0, + "d": 147 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 3, + "d": 0 + }, + "mne/realtime/mock_lsl_stream.py": { + "a": 10, + "d": 3 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 13, + "d": 42 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 50, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6181.json b/mne-python/source/doc/sphinxext/prs/6181.json new file mode 100644 index 0000000000000000000000000000000000000000..4067ca4aa7cbde814fec3298bb66e021b822bdee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6181.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a2f4634d3bb4e00436ca6c90121d3f1e457875dd", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6182.json b/mne-python/source/doc/sphinxext/prs/6182.json new file mode 100644 index 0000000000000000000000000000000000000000..8613154aac8b558f5236dcc4ce44ec9bd4795494 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6182.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "287f42345aae86a134acedffae2bd64e0581f87b", + "authors": [ + { + "n": "Ivana Kojcic", + "e": null + } + ], + "changes": { + "doc/contributing.rst": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6184.json b/mne-python/source/doc/sphinxext/prs/6184.json new file mode 100644 index 0000000000000000000000000000000000000000..d2c623875cbd131425efe77edb3f692afb3d1cee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6184.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a3adefb9c60f7db5b8a314365244e1f519de8fe5", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/annotations.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 19, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6186.json b/mne-python/source/doc/sphinxext/prs/6186.json new file mode 100644 index 0000000000000000000000000000000000000000..504c484077d9fde48f1535789356d312a424a3d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6186.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3a207b37f5d4356b139e7ccf102b4ad95d556217", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 83, + "d": 56 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6187.json b/mne-python/source/doc/sphinxext/prs/6187.json new file mode 100644 index 0000000000000000000000000000000000000000..03cee0a77be93dc07e8db513e8bca56ee328a057 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6187.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5799a185a85e69043a9b3845e1b93cd59509ce81", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6188.json b/mne-python/source/doc/sphinxext/prs/6188.json new file mode 100644 index 0000000000000000000000000000000000000000..71576ba143fa595ed0e6e0e5b01b40b6c582e3a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6188.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1e6a2a0f57ab3ced1c9f2ab44e44e24caf585aa3", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 2 + }, + "mne/io/brainvision/tests/data/test_bad_date.vhdr": { + "a": 142, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_bad_date.vmrk": { + "a": 25, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6189.json b/mne-python/source/doc/sphinxext/prs/6189.json new file mode 100644 index 0000000000000000000000000000000000000000..ff43aa93d0df7cf8a97403229500052c0420f1d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6189.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ffa71dbd0b7890af75285848776dc192843ccddc", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 192, + "d": 132 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/619.json b/mne-python/source/doc/sphinxext/prs/619.json new file mode 100644 index 0000000000000000000000000000000000000000..110741147adbd515c5db25f1d91ace98dc1180c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/619.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2e9ef2250532fc3f3da7d75f5b6fdac53b25bda4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6191.json b/mne-python/source/doc/sphinxext/prs/6191.json new file mode 100644 index 0000000000000000000000000000000000000000..b21fa5eeab9964dc2c1edbc9b39e6c91b09b1f1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6191.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b9a76420a4a436c8460c3d431ef2a5ae78af866a", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "doc/manual/migrating.rst": { + "a": 31, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6192.json b/mne-python/source/doc/sphinxext/prs/6192.json new file mode 100644 index 0000000000000000000000000000000000000000..ecbe7f541814169e6fec52faad0e4a2368bff7a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6192.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "e8ea87f866b2cce26366e0964b5db416f70840a8", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/manual/datasets_index.rst": { + "a": 9, + "d": 1 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 3, + "d": 3 + }, + "examples/datasets/plot_opm_rest_data.py": { + "a": 0, + "d": 1 + }, + "mne/bem.py": { + "a": 37, + "d": 20 + }, + "mne/commands/mne_flash_bem.py": { + "a": 5, + "d": 1 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 6, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 46, + "d": 52 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6193.json b/mne-python/source/doc/sphinxext/prs/6193.json new file mode 100644 index 0000000000000000000000000000000000000000..ab7ad7fc5676043471cf8c0ca5c7c1b885f7dfb8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6193.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "42c6bf2bd822e2e81af0c8dd49b50c50fa193ba2", + "authors": [ + { + "n": "Samuel Deslauriers-Gauthier", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/label.py": { + "a": 90, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 52, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6194.json b/mne-python/source/doc/sphinxext/prs/6194.json new file mode 100644 index 0000000000000000000000000000000000000000..368ea78b9505e95246288a38cb3c3a97d6249881 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6194.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7b6998094dcbccf53594cd1e2b4662acd8dece0f", + "authors": [ + { + "n": "Deleted user", + "e": null + } + ], + "changes": { + "mne/realtime/lsl_client.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6197.json b/mne-python/source/doc/sphinxext/prs/6197.json new file mode 100644 index 0000000000000000000000000000000000000000..1137977eaaa1b432c6c897b08afbb838254dcd9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6197.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "92f61faef72a335d6de63e816bd5bcfeaceffa09", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 4, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 9, + "d": 0 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6198.json b/mne-python/source/doc/sphinxext/prs/6198.json new file mode 100644 index 0000000000000000000000000000000000000000..6502b39946d9f47bf21eece5210fa106d8f3e0e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6198.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "b05968e60a039ca62bb1cb5be8a10fdb161d0b40", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "examples/preprocessing/plot_eog_artifact_histogram.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 23, + "d": 5 + }, + "mne/realtime/epochs.py": { + "a": 6, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 0 + }, + "tutorials/plot_sleep.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/62.json b/mne-python/source/doc/sphinxext/prs/62.json new file mode 100644 index 0000000000000000000000000000000000000000..f1467f921c5f0990a14173914db17d2082c9dfd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/62.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7aa71d75b86e728d956b1c8d034895810c6162ac", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/fiff/proj.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6200.json b/mne-python/source/doc/sphinxext/prs/6200.json new file mode 100644 index 0000000000000000000000000000000000000000..0a865811f5b56ebd92c461ac6dae0f63448c21f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6200.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "925423c50120462bd4125aa0c0378f7cc994b5a6", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 55, + "d": 16 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 7, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 7, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 6, + "d": 0 + }, + "tutorials/plot_epochs_to_data_frame.py": { + "a": 22, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6201.json b/mne-python/source/doc/sphinxext/prs/6201.json new file mode 100644 index 0000000000000000000000000000000000000000..590fd69a0997fe3bcbcc13c54f97074e0a4fb1e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6201.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d66a8683911d217b594a82f46cedd209e52912e3", + "authors": [ + { + "n": "Nathalie", + "e": "nat.gayraud@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 41, + "d": 29 + }, + "mne/simulation/tests/test_source.py": { + "a": 35, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6202.json b/mne-python/source/doc/sphinxext/prs/6202.json new file mode 100644 index 0000000000000000000000000000000000000000..f4dc0841a3015111b4ee50f72089129a0d4bb598 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6202.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1889555ff187d19590c126c32fe68374ebebc9b8", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6205.json b/mne-python/source/doc/sphinxext/prs/6205.json new file mode 100644 index 0000000000000000000000000000000000000000..32b473da0f948937bf4dafcbb0bd43c69b5b3a7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6205.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c4a83c5a1792fa68315baa87f1d7b26d9b6d709b", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 40, + "d": 0 + }, + "mne/utils/tests/test_docs.py": { + "a": 0, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 5, + "d": 182 + }, + "mne/viz/backends/_vtki.py": { + "a": 24, + "d": 2 + }, + "mne/viz/backends/base_renderer.py": { + "a": 246, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6207.json b/mne-python/source/doc/sphinxext/prs/6207.json new file mode 100644 index 0000000000000000000000000000000000000000..88ae51dcc60a2b893e2f4d5ce7ae2633f1f39653 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6207.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5a9ae3c3d66b6275fffec217cf560acf651913d7", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/evoked.py": { + "a": 7, + "d": 1 + }, + "tutorials/plot_eeg_erp.py": { + "a": 1, + "d": 1 + }, + "tutorials/plot_introduction.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6208.json b/mne-python/source/doc/sphinxext/prs/6208.json new file mode 100644 index 0000000000000000000000000000000000000000..dd2042b7d1a1ff42302fcfaa719c38303f20c6ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6208.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ab49f9c124fe61f0d1c437ab33c2970833f2e71e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/manual/preprocessing/filter.rst": { + "a": 0, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/621.json b/mne-python/source/doc/sphinxext/prs/621.json new file mode 100644 index 0000000000000000000000000000000000000000..92f774244eeacf581c4905a8ce84ef845d65a681 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/621.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cc8077d73a383d0321408ef6def3bb0d4ef87ef4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 35, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6210.json b/mne-python/source/doc/sphinxext/prs/6210.json new file mode 100644 index 0000000000000000000000000000000000000000..b38869acefa66b78cb5a0ee9cb0a15b460f5705c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6210.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "bc94beb201ca0a7c7c9e6fcd86d9b793e8694194", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/defaults.py": { + "a": 9, + "d": 7 + }, + "mne/epochs.py": { + "a": 6, + "d": 4 + }, + "mne/io/pick.py": { + "a": 4, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 105, + "d": 146 + }, + "mne/viz/ica.py": { + "a": 6, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_epochs.py": { + "a": 36, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6211.json b/mne-python/source/doc/sphinxext/prs/6211.json new file mode 100644 index 0000000000000000000000000000000000000000..e0ddd942eb09dc009d5d1fcdc7521ada3a13a603 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6211.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3d33e8eeb3e77b50b6b405b8cdf0ebdd5d5d8658", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 272, + "d": 114 + }, + "mne/viz/tests/test_evoked.py": { + "a": 16, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 9, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 27, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 28, + "d": 10 + }, + "tutorials/plot_visualize_evoked.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6213.json b/mne-python/source/doc/sphinxext/prs/6213.json new file mode 100644 index 0000000000000000000000000000000000000000..4042b705fd02aa471e919c95c7a861c32adc233f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6213.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "39ae853190df11d5dcd49f142f268c815c6d260d", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 5, + "d": 0 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 87, + "d": 62 + }, + "mne/beamformer/tests/test_external.py": { + "a": 98, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 7, + "d": 7 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6214.json b/mne-python/source/doc/sphinxext/prs/6214.json new file mode 100644 index 0000000000000000000000000000000000000000..b067093de47b462c0f36b8c20baf2442ff844ffd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6214.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d0b8c005d3e14f911c6615788e4428052cbe2819", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6215.json b/mne-python/source/doc/sphinxext/prs/6215.json new file mode 100644 index 0000000000000000000000000000000000000000..2025acfe5cb9bc62a68118e2e8429a0922d67059 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6215.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7a8404959f686ad7a0bcf9257836b1bd13c0fe40", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/annotations.py": { + "a": 9, + "d": 8 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6217.json b/mne-python/source/doc/sphinxext/prs/6217.json new file mode 100644 index 0000000000000000000000000000000000000000..04a9c4298109ee3484aef20a4960d1620c90bb89 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6217.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "55c455b48884e4cff45219d4127c7706c30f7f71", + "authors": [ + { + "n": "Deleted user", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 20, + "d": 15 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6218.json b/mne-python/source/doc/sphinxext/prs/6218.json new file mode 100644 index 0000000000000000000000000000000000000000..3b0a06923a3cae30962d461cc9e93f791b5ed865 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6218.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "767cd9246370d25b132b4d98206095e15779044f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/_rap_music.py": { + "a": 4, + "d": 2 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/622.json b/mne-python/source/doc/sphinxext/prs/622.json new file mode 100644 index 0000000000000000000000000000000000000000..e0f68d6ea04eb797c43236c6db78043b52a65bc8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/622.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7689d310146aa908a596b250e69620f518c4f58b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 96, + "d": 23 + }, + "mne/tests/test_proj.py": { + "a": 23, + "d": 48 + }, + "mne/tests/test_source_estimate.py": { + "a": 12, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6220.json b/mne-python/source/doc/sphinxext/prs/6220.json new file mode 100644 index 0000000000000000000000000000000000000000..b931cfa33e896ad7d400916feabbcce54e69c47b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6220.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cc175020e8949b435a11cf9db82f6f25713508b2", + "authors": [ + { + "n": "Quentin Bertrand", + "e": "quentin.bertrand@mila.quebec" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 79, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6224.json b/mne-python/source/doc/sphinxext/prs/6224.json new file mode 100644 index 0000000000000000000000000000000000000000..0f0eb835f83fbc1b9bf83ce754b0e50e4e6e5175 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6224.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "be294971ab3f6467fc6930404ce6c0166c3519b9", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/cited.rst": { + "a": 4, + "d": 191 + }, + "doc/sphinxext/cited_mne.py": { + "a": 0, + "d": 261 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6227.json b/mne-python/source/doc/sphinxext/prs/6227.json new file mode 100644 index 0000000000000000000000000000000000000000..22aa954281bc20d494b714713492e20a9110f646 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6227.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "454b69eb865e0dea7a3bd3d9795c010796946ac6", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 30, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 4, + "d": 11 + }, + "mne/beamformer/_lcmv.py": { + "a": 50, + "d": 7 + }, + "mne/beamformer/tests/test_external.py": { + "a": 31, + "d": 30 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6228.json b/mne-python/source/doc/sphinxext/prs/6228.json new file mode 100644 index 0000000000000000000000000000000000000000..7de2ceffe0dc6fafcb0cfb975d4daa0d3b4d20e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6228.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a9bbb9eded90321545e211857eec935d387e065c", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + }, + { + "n": "Teon Brooks", + "e": "teon.brooks@gmail.com" + }, + { + "n": "Teon Brooks", + "e": "teon.brooks@gmail.com" + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 77, + "d": 121 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 14, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6229.json b/mne-python/source/doc/sphinxext/prs/6229.json new file mode 100644 index 0000000000000000000000000000000000000000..8413635342fee14e4408d1e3326c9bc3d81dc298 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6229.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "297422c6ef2b36ce0b4ad736fa97b5f00ae2399b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6230.json b/mne-python/source/doc/sphinxext/prs/6230.json new file mode 100644 index 0000000000000000000000000000000000000000..7f9c632b27b62c61c9b989a347244eee63dc0f64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6230.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6a3a438fe23f0c459a50af8401a3e3083edd8fea", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 8, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 55, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6231.json b/mne-python/source/doc/sphinxext/prs/6231.json new file mode 100644 index 0000000000000000000000000000000000000000..f0ecfea2123cdff964fb373987b8ded58165cd1e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6231.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d2089d28ba1dae9b0a1159046f235e1dd596f8ea", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6233.json b/mne-python/source/doc/sphinxext/prs/6233.json new file mode 100644 index 0000000000000000000000000000000000000000..f62c2f29cc915e0aed0dd2015583b9098d14d965 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6233.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "a750523f8364c935263a6c6d154cc1248cf515ee", + "authors": [ + { + "n": "Maksymenko Kostiantyn", + "e": "makkostya@ukr.net" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Joan Massich", + "e": "sik@visor.udg.edu" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 59, + "d": 0 + }, + "doc/simulation.rst": { + "a": 20, + "d": 0 + }, + "examples/simulation/plot_stc_metrics.py": { + "a": 260, + "d": 0 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "mne/simulation/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/simulation/_metrics.py": { + "a": 3, + "d": 4 + }, + "mne/simulation/metrics/__init__.py": { + "a": 9, + "d": 0 + }, + "mne/simulation/metrics/metrics.py": { + "a": 572, + "d": 0 + }, + "mne/simulation/metrics/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/metrics/tests/test_metrics.py": { + "a": 241, + "d": 0 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 18, + "d": 12 + }, + "mne/utils/docs.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6234.json b/mne-python/source/doc/sphinxext/prs/6234.json new file mode 100644 index 0000000000000000000000000000000000000000..99060216225f2048009514da77510c1316c611a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6234.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5d80e26f541d83dbd267c3e0957d8aa8e6a154f4", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "examples/realtime/plot_rt_feedback_server.py": { + "a": 3, + "d": 3 + }, + "mne/realtime/mock_lsl_stream.py": { + "a": 1, + "d": 1 + }, + "mne/realtime/tests/test_lsl_client.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6236.json b/mne-python/source/doc/sphinxext/prs/6236.json new file mode 100644 index 0000000000000000000000000000000000000000..c66cb851ddd11556782d5484f6cd9a4266b1fe3d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6236.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "360c51342d7de61310b5ef2935f0f68c0f9dfb81", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6237.json b/mne-python/source/doc/sphinxext/prs/6237.json new file mode 100644 index 0000000000000000000000000000000000000000..85f983db63c5a2ee03239e2616ec33b0e9f411c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6237.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b9dcbe1eac621e22b5cff6883e4b3a889846e303", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "setup.cfg": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6239.json b/mne-python/source/doc/sphinxext/prs/6239.json new file mode 100644 index 0000000000000000000000000000000000000000..7213008dc0b63509b557c3c03cf844b20064c371 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6239.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "03bc75e9067483166bb8ebbb2827ccaf45425031", + "authors": [ + { + "n": "Oleh Kozynets", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 12, + "d": 10 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_vtki.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/624.json b/mne-python/source/doc/sphinxext/prs/624.json new file mode 100644 index 0000000000000000000000000000000000000000..538aebb06cb58d9eaec2d5d89c72c9736e3f9e62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/624.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "389ff2de81b46424fb16af5b6a2d57be03d04646", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "AUTHORS.rst": { + "a": 11, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6240.json b/mne-python/source/doc/sphinxext/prs/6240.json new file mode 100644 index 0000000000000000000000000000000000000000..86370aef3d4d2036b8ce67059b156ef435f6652a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6240.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ec8d35c35c8f550d3815eae8af4e9759f0d5627e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6241.json b/mne-python/source/doc/sphinxext/prs/6241.json new file mode 100644 index 0000000000000000000000000000000000000000..2e3f34fb6aaff926d6b71b7d7100353b9613d557 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6241.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ce9953a72bbd54109168f5a0fb2ff79a0969cf6c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "tutorials/plot_epochs_to_data_frame.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6242.json b/mne-python/source/doc/sphinxext/prs/6242.json new file mode 100644 index 0000000000000000000000000000000000000000..d2860060354fe7983059e2d58fb7ad4991bbba26 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6242.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "24261065e59e82a84c83e4e8e006631c7d4795c3", + "authors": [ + { + "n": "Jeyhte Key", + "e": "jeythekey@tutanota.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 5, + "d": 3 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 36, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6243.json b/mne-python/source/doc/sphinxext/prs/6243.json new file mode 100644 index 0000000000000000000000000000000000000000..a36f9b1af4dd9834b93ba7c53a3cb8d6e5645afd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6243.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2970a72758df09d4c4d901ea39bcd3e650012c37", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/simulation/plot_source_simulator.py": { + "a": 84, + "d": 0 + }, + "mne/simulation/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 207, + "d": 0 + }, + "mne/simulation/tests/test_source.py": { + "a": 176, + "d": 81 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6244.json b/mne-python/source/doc/sphinxext/prs/6244.json new file mode 100644 index 0000000000000000000000000000000000000000..1b0bca520fdae31a0e526a4c458505995564b573 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6244.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ba0b59cabf25d25989ca10bf4df5bdd2e8ef9b24", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6245.json b/mne-python/source/doc/sphinxext/prs/6245.json new file mode 100644 index 0000000000000000000000000000000000000000..09be7f87c8ef8485c9c234f98593690d4f943825 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6245.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4e81a4857fc9b3a99ec6f409f4ddd9b63ff35154", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_cov.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6246.json b/mne-python/source/doc/sphinxext/prs/6246.json new file mode 100644 index 0000000000000000000000000000000000000000..e0d3f90351798ee24e26c203a8324f41a23fc045 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6246.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8ce77a0ad91844b0bb2a5f99bf383f1cc9d39fe6", + "authors": [ + { + "n": "Jeyhte Key", + "e": "jeythekey@tutanota.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 8, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 92, + "d": 78 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6247.json b/mne-python/source/doc/sphinxext/prs/6247.json new file mode 100644 index 0000000000000000000000000000000000000000..f6ac495c92e167993516b4306087684d41a26d51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6247.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "af340be8359c3dd2514e103b83306eca0f78c5f0", + "authors": [ + { + "n": "Jeyhte Key", + "e": "jeythekey@tutanota.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6251.json b/mne-python/source/doc/sphinxext/prs/6251.json new file mode 100644 index 0000000000000000000000000000000000000000..fa24f37e08ac7a7641fb8d223dc17cab504f0d1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6251.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "36fad3c74b6c6d4773287be16d848842df2741e3", + "authors": [ + { + "n": "tom", + "e": "tdonoghue.research@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 7, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6252.json b/mne-python/source/doc/sphinxext/prs/6252.json new file mode 100644 index 0000000000000000000000000000000000000000..71dc56d1e0780a52dddc4d212881047ab4f1a305 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6252.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f80a8de283b45319e538b19c30e7eb9648380ca6", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/utils/_bunch.py": { + "a": 23, + "d": 13 + }, + "mne/utils/tests/test_bunch.py": { + "a": 25, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6253.json b/mne-python/source/doc/sphinxext/prs/6253.json new file mode 100644 index 0000000000000000000000000000000000000000..f0f3ca11ead3f6a6b6ea7d664170571e45ce177e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6253.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a96f0e0a62219b63868904e3330f1202e20cf67b", + "authors": [ + { + "n": "Jeyhte Key", + "e": "jeythekey@tutanota.com" + } + ], + "changes": { + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6254.json b/mne-python/source/doc/sphinxext/prs/6254.json new file mode 100644 index 0000000000000000000000000000000000000000..837c56294a27f7a88aac9f4a3fd5534168f32cc2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6254.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "39f46ade8e94c9b47acf40570c45c6c555c02820", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "CONTRIBUTING.rst": { + "a": 34, + "d": 0 + }, + "doc/_static/style.css": { + "a": 5, + "d": 1 + }, + "doc/advanced_setup.rst": { + "a": 4, + "d": 33 + }, + "doc/configure_git.rst": { + "a": 0, + "d": 613 + }, + "doc/contributing.rst": { + "a": 754, + "d": 154 + }, + "doc/customizing_git.rst": { + "a": 0, + "d": 131 + }, + "doc/documentation.rst": { + "a": 0, + "d": 2 + }, + "doc/install_mne_python.rst": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 13, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6255.json b/mne-python/source/doc/sphinxext/prs/6255.json new file mode 100644 index 0000000000000000000000000000000000000000..d7981bd665b043af2491b53da29a9874875c65ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6255.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a0dbca96c3a1dfabb7bf28c298d04684b12e6cc7", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6260.json b/mne-python/source/doc/sphinxext/prs/6260.json new file mode 100644 index 0000000000000000000000000000000000000000..ee694cea6255d2b164fbb9e1b323406507358f63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6260.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "14a0f195e7301c1504c72b3cc09476609b0b0029", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/annotations.py": { + "a": 18, + "d": 14 + }, + "mne/tests/test_annotations.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6261.json b/mne-python/source/doc/sphinxext/prs/6261.json new file mode 100644 index 0000000000000000000000000000000000000000..7c8c649806e43b397965922fc6052e02e76367c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6261.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6bc9643448c41aca2b628397d0d1e9d17643e139", + "authors": [ + { + "n": "Ivana Kojcic", + "e": null + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/simulation/plot_simulated_raw_data_using_subject_anatomy.py": { + "a": 195, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6262.json b/mne-python/source/doc/sphinxext/prs/6262.json new file mode 100644 index 0000000000000000000000000000000000000000..3f5e53f8f9555d0d83f9aa146dc2e5dff6207eb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6262.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "c086e760dc1c1f138e4b153102574abd571f62bd", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/glossary.rst": { + "a": 10, + "d": 0 + }, + "doc/overview/roadmap.rst": { + "a": 3, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_evoked_ers_source_power.py": { + "a": 130, + "d": 0 + }, + "examples/inverse/plot_mne_cov_power.py": { + "a": 139, + "d": 0 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 92, + "d": 68 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 53, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 20, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6264.json b/mne-python/source/doc/sphinxext/prs/6264.json new file mode 100644 index 0000000000000000000000000000000000000000..61092af969647c4fa6b285e7823738ef7d94fc29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6264.json @@ -0,0 +1,435 @@ +{ + "merge_commit_sha": "37b00c4cc16982eb0d0f210acd20e0cef3fc539d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 14, + "d": 1 + }, + "doc/documentation.rst": { + "a": 54, + "d": 55 + }, + "doc/glossary.rst": { + "a": 7, + "d": 11 + }, + "doc/manual/cookbook.rst": { + "a": 2, + "d": 3 + }, + "doc/manual/datasets_index.rst": { + "a": 15, + "d": 15 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 2, + "d": 2 + }, + "doc/manual/source_localization/c_inverse.rst": { + "a": 1, + "d": 2 + }, + "doc/manual/source_localization/inverse.rst": { + "a": 4, + "d": 5 + }, + "doc/manual/source_localization/morph_stc.rst": { + "a": 8, + "d": 12 + }, + "doc/tutorials/philosophy.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 3, + "d": 3 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_megsim_data.py": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_opm_data.py": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_opm_rest_data.py": { + "a": 2, + "d": 0 + }, + "examples/datasets/spm_faces_dataset.py": { + "a": 2, + "d": 0 + }, + "examples/decoding/decoding_rsa.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_receptive_field_mtrf.py": { + "a": 2, + "d": 0 + }, + "examples/forward/plot_forward_sensitivity_maps.py": { + "a": 3, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 2, + "d": 0 + }, + "examples/io/plot_elekta_epochs.py": { + "a": 2, + "d": 0 + }, + "examples/io/plot_objects_from_arrays.py": { + "a": 2, + "d": 0 + }, + "examples/io/plot_read_events.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_proj.py": { + "a": 1, + "d": 2 + }, + "examples/preprocessing/plot_otp.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_3d_to_2d.py": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 2, + "d": 0 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 2, + "d": 6 + }, + "mne/io/base.py": { + "a": 1, + "d": 3 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 2 + }, + "tutorials/discussions/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/discussions/plot_background_filtering.py": { + "a": 4, + "d": 4 + }, + "tutorials/discussions/plot_background_statistics.py": { + "a": 3, + "d": 1 + }, + "tutorials/epochs/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/epochs/plot_epochs_to_data_frame.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/plot_metadata_epochs.py": { + "a": 2, + "d": 1 + }, + "tutorials/epochs/plot_object_epochs.py": { + "a": 3, + "d": 3 + }, + "tutorials/epochs/plot_visualize_epochs.py": { + "a": 0, + "d": 0 + }, + "tutorials/evoked/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 0, + "d": 0 + }, + "tutorials/evoked/plot_object_evoked.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/plot_visualize_evoked.py": { + "a": 3, + "d": 3 + }, + "tutorials/evoked/plot_whitened.py": { + "a": 0, + "d": 0 + }, + "tutorials/intro/README.txt": { + "a": 7, + "d": 0 + }, + "tutorials/intro/plot_epoching_and_averaging.py": { + "a": 3, + "d": 4 + }, + "tutorials/intro/plot_info.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/plot_introduction.py": { + "a": 0, + "d": 0 + }, + "tutorials/intro/plot_object_annotations.py": { + "a": 5, + "d": 3 + }, + "tutorials/machine-learning/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/machine-learning/plot_receptive_field.py": { + "a": 0, + "d": 0 + }, + "tutorials/machine-learning/plot_sensors_decoding.py": { + "a": 1, + "d": 1 + }, + "tutorials/misc/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/misc/plot_configuration.py": { + "a": 0, + "d": 0 + }, + "tutorials/misc/plot_ecog.py": { + "a": 0, + "d": 0 + }, + "tutorials/misc/plot_modifying_data_inplace.py": { + "a": 0, + "d": 0 + }, + "tutorials/plot_python_intro.py": { + "a": 0, + "d": 46 + }, + "tutorials/preprocessing/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/preprocessing/plot_artifacts_correction_filtering.py": { + "a": 3, + "d": 1 + }, + "tutorials/preprocessing/plot_artifacts_correction_ica.py": { + "a": 4, + "d": 3 + }, + "tutorials/preprocessing/plot_artifacts_correction_maxwell_filtering.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/plot_artifacts_correction_rejection.py": { + "a": 4, + "d": 3 + }, + "tutorials/preprocessing/plot_artifacts_correction_ssp.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/plot_artifacts_detection.py": { + "a": 9, + "d": 10 + }, + "tutorials/preprocessing/plot_ica_from_raw.py": { + "a": 0, + "d": 0 + }, + "tutorials/raw/README.txt": { + "a": 6, + "d": 0 + }, + "tutorials/raw/plot_object_raw.py": { + "a": 4, + "d": 2 + }, + "tutorials/raw/plot_visualize_raw.py": { + "a": 2, + "d": 0 + }, + "tutorials/sample-datasets/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/sample-datasets/plot_brainstorm_auditory.py": { + "a": 2, + "d": 0 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_ctf.py": { + "a": 0, + "d": 0 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_elekta.py": { + "a": 2, + "d": 0 + }, + "tutorials/sample-datasets/plot_phantom_4DBTi.py": { + "a": 0, + "d": 0 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 2, + "d": 0 + }, + "tutorials/simulation/README.txt": { + "a": 6, + "d": 0 + }, + "tutorials/simulation/plot_creating_data_structures.py": { + "a": 1, + "d": 2 + }, + "tutorials/simulation/plot_dics.py": { + "a": 0, + "d": 0 + }, + "tutorials/simulation/plot_point_spread.py": { + "a": 0, + "d": 0 + }, + "tutorials/source-modeling/README.txt": { + "a": 4, + "d": 0 + }, + "tutorials/source-modeling/plot_background_freesurfer.py": { + "a": 4, + "d": 3 + }, + "tutorials/source-modeling/plot_compute_covariance.py": { + "a": 0, + "d": 0 + }, + "tutorials/source-modeling/plot_dipole_fit.py": { + "a": 0, + "d": 0 + }, + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 2, + "d": 0 + }, + "tutorials/source-modeling/plot_eeg_no_mri.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 3, + "d": 1 + }, + "tutorials/source-modeling/plot_mne_solutions.py": { + "a": 2, + "d": 0 + }, + "tutorials/source-modeling/plot_object_source_estimate.py": { + "a": 6, + "d": 6 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 0, + "d": 0 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-sensor-space/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_erp.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_time_frequency.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-sensor-space/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-source-space/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 2, + "d": 0 + }, + "tutorials/time-freq/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/time-freq/plot_sensors_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/627.json b/mne-python/source/doc/sphinxext/prs/627.json new file mode 100644 index 0000000000000000000000000000000000000000..581486c967a5bf4ff89bcc29850538ff194fd7c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/627.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c65515c51f3dffea9cb53b42ae6522805c365cb9", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_delayed_ssp_projector.py": { + "a": 11, + "d": 7 + }, + "mne/epochs.py": { + "a": 62, + "d": 36 + }, + "mne/tests/test_epochs.py": { + "a": 19, + "d": 6 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 1 + }, + "mne/viz.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6270.json b/mne-python/source/doc/sphinxext/prs/6270.json new file mode 100644 index 0000000000000000000000000000000000000000..7911a80fb8feec59143c9d29bedf033b504ec5e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6270.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f39331cc51b7043ae1726561218d85a638ec1a7f", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/stats/parametric.py": { + "a": 1, + "d": 7 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 16, + "d": 4 + }, + "mne/viz/tests/test_evoked.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6272.json b/mne-python/source/doc/sphinxext/prs/6272.json new file mode 100644 index 0000000000000000000000000000000000000000..160837b783a7ceae5ec37a61366b8f388771bfaf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6272.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "7d64af376f9c991b3645ca4ec95e516405b01c8d", + "authors": [ + { + "n": "Dirk Gütlin", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 13, + "d": 7 + }, + "mne/io/__init__.py": { + "a": 5, + "d": 4 + }, + "mne/io/curry/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/curry/curry.py": { + "a": 345, + "d": 0 + }, + "mne/io/curry/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 266, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6274.json b/mne-python/source/doc/sphinxext/prs/6274.json new file mode 100644 index 0000000000000000000000000000000000000000..51893f46220485d3e5f75c0c452bee6449878b2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6274.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "86b8aeb54ff914064c96b9e21c884d06224c45f4", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/git_links.inc": { + "a": 0, + "d": 8 + }, + "doc/install_mne_c.rst": { + "a": 25, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6275.json b/mne-python/source/doc/sphinxext/prs/6275.json new file mode 100644 index 0000000000000000000000000000000000000000..a7c6398b216bc5bf30b9a694092a30856ad8e206 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6275.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1293e1dfebb5ebbaa39fb6aca4c8257d0c05f792", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/628.json b/mne-python/source/doc/sphinxext/prs/628.json new file mode 100644 index 0000000000000000000000000000000000000000..41dbcf163d2e3d1d50892564a3a81aa1c8fb7d5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/628.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b01cc08273304f006f73a1382248d581d940f8f0", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 1 + }, + "examples/plot_evoked_delayed_ssp.py": { + "a": 15, + "d": 13 + }, + "examples/plot_evoked_topomap_delayed_ssp.py": { + "a": 61, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/evoked.py": { + "a": 6, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 1, + "d": 0 + }, + "mne/viz.py": { + "a": 70, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6280.json b/mne-python/source/doc/sphinxext/prs/6280.json new file mode 100644 index 0000000000000000000000000000000000000000..03733fe3ffd9edf0994faf6ca068fd9aeffb295c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6280.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c61298e30af477aa9d8b645910925b8b4f96f402", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/fixes.py": { + "a": 11, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 28, + "d": 13 + }, + "mne/viz/utils.py": { + "a": 31, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6281.json b/mne-python/source/doc/sphinxext/prs/6281.json new file mode 100644 index 0000000000000000000000000000000000000000..28c3ec138a35a2a4550f140875afc64a93758d2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6281.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "499ae778697c8a06e8b258a45e7de1aaabe18ab5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/dipole.py": { + "a": 4, + "d": 1 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_elekta.py": { + "a": 12, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6285.json b/mne-python/source/doc/sphinxext/prs/6285.json new file mode 100644 index 0000000000000000000000000000000000000000..bed9c3adb95998d09a6729bc4b7350b8bdc4ea30 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6285.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4a52511469992d2abe0686bc6d1588f7469cbb3f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/receptive_field.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 62, + "d": 50 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6286.json b/mne-python/source/doc/sphinxext/prs/6286.json new file mode 100644 index 0000000000000000000000000000000000000000..2f899d9e76fc2a396dfe2416bd68b2754216ec5b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6286.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2682e32be43af610bdb67f5eabfbfcb1472a3e7f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 23, + "d": 4 + }, + "doc/manual/datasets_index.rst": { + "a": 2, + "d": 0 + }, + "doc/manual/io.rst": { + "a": 3, + "d": 1 + }, + "tutorials/intro/plot_introduction.py": { + "a": 339, + "d": 366 + }, + "tutorials/time-freq/plot_sensors_time_frequency.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6288.json b/mne-python/source/doc/sphinxext/prs/6288.json new file mode 100644 index 0000000000000000000000000000000000000000..323f16a14b81e5296cc0ca7c3a1d854b47b98359 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6288.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5d58b3cca5e1426981820444ec0e6f8bef92044f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/io/pick.py": { + "a": 13, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 6, + "d": 9 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6289.json b/mne-python/source/doc/sphinxext/prs/6289.json new file mode 100644 index 0000000000000000000000000000000000000000..c4bd799d2fac4d7c4932d4eab35036e06387b1f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6289.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d5752051b37f74713233929382bcc632d404f837", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/629.json b/mne-python/source/doc/sphinxext/prs/629.json new file mode 100644 index 0000000000000000000000000000000000000000..1a1bc7842485ed4a44f05fbc8889b06be14a5b32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/629.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dc8eccbfcee3a7e520c77552f60afb24da041955", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/tests/test_viz.py": { + "a": 76, + "d": 11 + }, + "mne/viz.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6291.json b/mne-python/source/doc/sphinxext/prs/6291.json new file mode 100644 index 0000000000000000000000000000000000000000..7cd485e919e6e62eaa8a84d7eb208d8acc625619 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6291.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "9db91c1775617fd26c161a8ee8cf68b8a5297009", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 47, + "d": 20 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 37, + "d": 0 + }, + "mne/io/open.py": { + "a": 23, + "d": 5 + }, + "mne/io/tag.py": { + "a": 6, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6293.json b/mne-python/source/doc/sphinxext/prs/6293.json new file mode 100644 index 0000000000000000000000000000000000000000..3224e25fcd83ddde4a4abd3c7a32324a67abff1a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6293.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ee0b69b176951b22c1a1761122f051619881277c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/tests/test_datasets.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6294.json b/mne-python/source/doc/sphinxext/prs/6294.json new file mode 100644 index 0000000000000000000000000000000000000000..257ccf5e746d535520250a307d5ec6fe3f5ef74d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6294.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "9a5d3743a831c2b46721727fabcf7aacd8032854", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 8, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 7, + "d": 25 + }, + "mne/filter.py": { + "a": 248, + "d": 362 + }, + "mne/fixes.py": { + "a": 14, + "d": 2 + }, + "mne/io/base.py": { + "a": 62, + "d": 171 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 3 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 4 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 148, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 117, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 90, + "d": 33 + }, + "tutorials/discussions/plot_background_filtering.py": { + "a": 212, + "d": 191 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6296.json b/mne-python/source/doc/sphinxext/prs/6296.json new file mode 100644 index 0000000000000000000000000000000000000000..f3a475a0d0869975a3b330989d75146c9faf701e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6296.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fbec15ccfaba7d9ab8d817a10073450f1cec8811", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6297.json b/mne-python/source/doc/sphinxext/prs/6297.json new file mode 100644 index 0000000000000000000000000000000000000000..e897503703b2a9c7cabf8002f06e5b5471d5d13c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6297.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1dfbe87ef75a33aa59927c0e1692c6cbc0574189", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "setup.cfg": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6299.json b/mne-python/source/doc/sphinxext/prs/6299.json new file mode 100644 index 0000000000000000000000000000000000000000..2eb7c3c750abce4e5df33f3ac3057de416c9dad5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6299.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "ae02bcba43a50a70b714ca19a62ba155e6320050", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/git_links.inc": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 0, + "d": 3 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 2, + "d": 2 + }, + "tutorials/source-modeling/plot_dipole_fit.py": { + "a": 2, + "d": 4 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/63.json b/mne-python/source/doc/sphinxext/prs/63.json new file mode 100644 index 0000000000000000000000000000000000000000..d0dcd55e7c106a3034fa70d1f0a5eea58780a6ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/63.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "244c2bd28d79da67bc7c901442f5c93803b870a4", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 3 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 11, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 22, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/630.json b/mne-python/source/doc/sphinxext/prs/630.json new file mode 100644 index 0000000000000000000000000000000000000000..98a85f8ce79f7c7e9cdc4465cb62610737b05f73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/630.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e5fb4eff992b87f349233a3e57c85c62f931bfea", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 113, + "d": 97 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6300.json b/mne-python/source/doc/sphinxext/prs/6300.json new file mode 100644 index 0000000000000000000000000000000000000000..0f5ea025e2f7f5fdef20e8eb4d712b83d2654c8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6300.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "022acdb68ce11c6f149f414018d00c09c3ba10bb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 5, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6301.json b/mne-python/source/doc/sphinxext/prs/6301.json new file mode 100644 index 0000000000000000000000000000000000000000..e4a8b5f1714a55ffe5f509f44282b90c3cf6ef40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6301.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "56c408d363a01043594b6965b5ede3e1123bdcff", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "conftest.py": { + "a": 5, + "d": 5 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 14, + "d": 14 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 7, + "d": 7 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6303.json b/mne-python/source/doc/sphinxext/prs/6303.json new file mode 100644 index 0000000000000000000000000000000000000000..46829f73f015f3f00723d7d7bf36f577bb1aa3a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6303.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8cbdcccd31910111263d90bf61239a24bce15fcc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/gui/_viewer.py": { + "a": 4, + "d": 0 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 27, + "d": 26 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6305.json b/mne-python/source/doc/sphinxext/prs/6305.json new file mode 100644 index 0000000000000000000000000000000000000000..5daa18f4b22438142a24ebf6463cb93d8d544061 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6305.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "017d156706984b88a524b146ec71415c65b42391", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_dics_source_power.py": { + "a": 43, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6306.json b/mne-python/source/doc/sphinxext/prs/6306.json new file mode 100644 index 0000000000000000000000000000000000000000..40d789f2577170bf183e723196caf40642185b11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6306.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ef7c95fd4ec9256753f81e7572d3ecd9d44eff36", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_elekta.py": { + "a": 7, + "d": 8 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 7, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6307.json b/mne-python/source/doc/sphinxext/prs/6307.json new file mode 100644 index 0000000000000000000000000000000000000000..0b7951d182a7ef539493045498415519dbc39511 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6307.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0ee91f3dff16bdd4da8ff8bebcabb0b143559cec", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 12, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6308.json b/mne-python/source/doc/sphinxext/prs/6308.json new file mode 100644 index 0000000000000000000000000000000000000000..6b9e24d9c8b84df84b15fb54c65a7a51d0bbf327 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6308.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "57ad16858a6c6a94831ac293b0eb45bedd5370fd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6309.json b/mne-python/source/doc/sphinxext/prs/6309.json new file mode 100644 index 0000000000000000000000000000000000000000..636fb59546e66fe62d4987ae4d5844466e6db32f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6309.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5bc0a8ff7a4abc047c845b3f0f0d0edf71bb05e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 0, + "d": 1 + }, + "mne/conftest.py": { + "a": 55, + "d": 0 + }, + "setup.cfg": { + "a": 0, + "d": 38 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6310.json b/mne-python/source/doc/sphinxext/prs/6310.json new file mode 100644 index 0000000000000000000000000000000000000000..b9cdea657d5c2696dcee33f700774bf7ed434bf4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6310.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0c76381a84153f0b44e5db132322f3fe4e14f0c9", + "authors": [ + { + "n": "Zhenya", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/flat.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 20, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6311.json b/mne-python/source/doc/sphinxext/prs/6311.json new file mode 100644 index 0000000000000000000000000000000000000000..97700fdf08e37af9e10be810518b5cab198ec739 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6311.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "14d05270290a3c3b356cbd6de98c7146a8b0064f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/utils/_testing.py": { + "a": 8, + "d": 6 + }, + "mne/utils/misc.py": { + "a": 5, + "d": 3 + }, + "mne/viz/backends/renderer.py": { + "a": 4, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6313.json b/mne-python/source/doc/sphinxext/prs/6313.json new file mode 100644 index 0000000000000000000000000000000000000000..637b631b39a66fbac412dc60c77ecdd193a0c1bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6313.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0f7c7aa1d8a8b59030cb62b0fa7d770847f5635d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_annotations.py": { + "a": 19, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6314.json b/mne-python/source/doc/sphinxext/prs/6314.json new file mode 100644 index 0000000000000000000000000000000000000000..4d055619386f4933100efc4ed20fa4e60ff7b2e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6314.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5a8533a2ab269c65dd61d7131a9aa9ffab52142b", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6316.json b/mne-python/source/doc/sphinxext/prs/6316.json new file mode 100644 index 0000000000000000000000000000000000000000..6f8b259cd0bacf6aafc2b7472fcfc9c1f65caabf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6316.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "419c8e4437ec6439f0681313ab27506fbb80ea7b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 0, + "d": 9 + }, + "mne/tests/test_epochs.py": { + "a": 27, + "d": 17 + }, + "setup.cfg": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6317.json b/mne-python/source/doc/sphinxext/prs/6317.json new file mode 100644 index 0000000000000000000000000000000000000000..9603c3ca73b6de4d865983ae4b83a47314e87585 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6317.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3b130c8dff4b766da4788a788f5401513f57d9f8", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/contributing.rst": { + "a": 23, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6318.json b/mne-python/source/doc/sphinxext/prs/6318.json new file mode 100644 index 0000000000000000000000000000000000000000..7e3f8ba592be1c0e6ca14875bc72ff27b1e9da9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6318.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7cd131cc246f53b0754082979d3293206c8fe235", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/_make_forward.py": { + "a": 3, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 19, + "d": 10 + }, + "mne/tests/test_bem.py": { + "a": 4, + "d": 4 + }, + "mne/transforms.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6319.json b/mne-python/source/doc/sphinxext/prs/6319.json new file mode 100644 index 0000000000000000000000000000000000000000..2668f0fda922c321d1565a27db749f0606f5fa00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6319.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3926e12badfb5ca75aa375680f98403eba46170e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/632.json b/mne-python/source/doc/sphinxext/prs/632.json new file mode 100644 index 0000000000000000000000000000000000000000..91f1d32ff6f2e248b5f32c7627f67ddfd29f24a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/632.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f69e35dbd7b6137fe0cf94838a1deac41245eab8", + "authors": [ + { + "n": "Yoursa BEKHTI", + "e": "ybekhti@is222485.intra.cea.fr" + } + ], + "changes": { + "mne/layouts/layout.py": { + "a": 36, + "d": 20 + }, + "mne/viz.py": { + "a": 12, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6320.json b/mne-python/source/doc/sphinxext/prs/6320.json new file mode 100644 index 0000000000000000000000000000000000000000..bcb312c4f996b318253eff028936ad170d2cfba3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6320.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "805ff576565939a1cc970b7b533bb7f131bc7b3c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 8, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 12, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 0, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 0, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 10, + "d": 2 + }, + "mne/viz/tests/test_utils.py": { + "a": 4, + "d": 5 + }, + "mne/viz/topo.py": { + "a": 4, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 11, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6323.json b/mne-python/source/doc/sphinxext/prs/6323.json new file mode 100644 index 0000000000000000000000000000000000000000..0176e13ecf19050011178cf4120f7143f082752d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6323.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b31e573bd1bb97ab8daf6e813a6f5fa77ba266c4", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/intro/plot_introduction.py": { + "a": 15, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6324.json b/mne-python/source/doc/sphinxext/prs/6324.json new file mode 100644 index 0000000000000000000000000000000000000000..03219d42e9f50138e3396f6a7686caf1ec0c9153 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6324.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9d5a4a5f87ffa7ed0e1a659ae89f76b724ff51ee", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 16, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6326.json b/mne-python/source/doc/sphinxext/prs/6326.json new file mode 100644 index 0000000000000000000000000000000000000000..5bdd3887942817da5cd0e383922cf80122752b99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6326.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3454474192ec8cb770b07d4c57dc0bcc7b1640a5", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/annotations.py": { + "a": 27, + "d": 11 + }, + "mne/io/brainvision/brainvision.py": { + "a": 38, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 64, + "d": 21 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6327.json b/mne-python/source/doc/sphinxext/prs/6327.json new file mode 100644 index 0000000000000000000000000000000000000000..7bd177ed406e9a9d21f1fd834e06ca351d992c02 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6327.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3c9073f2c872af70db696e577420ab329495966f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6328.json b/mne-python/source/doc/sphinxext/prs/6328.json new file mode 100644 index 0000000000000000000000000000000000000000..54709a3ff3b13a38116bfb679a9268b68fd06c55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6328.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "184486630b05c88948fd9044f40db98b707fe2d4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "logo/generate_mne_logos.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6331.json b/mne-python/source/doc/sphinxext/prs/6331.json new file mode 100644 index 0000000000000000000000000000000000000000..4780de18f06d0291888737d536a2a36a1f66c54b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6331.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4ff3bad13ac4a37fe0c15128d41adc789a9ca510", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_hf_sef_data.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 9, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6333.json b/mne-python/source/doc/sphinxext/prs/6333.json new file mode 100644 index 0000000000000000000000000000000000000000..b2c737ed7dfb08639b4e0e7536df0ec58965d9a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6333.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "53520484c6df836d4acbc0ebbad8ecc5a665fb1d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 8, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 8, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6334.json b/mne-python/source/doc/sphinxext/prs/6334.json new file mode 100644 index 0000000000000000000000000000000000000000..0e1ce3dbb3b91c9956bbcf35400529ad202e9226 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6334.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "fe7ee249d09f9b69453f23d1a5114dbed47927dd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + "mne/datasets/sleep_physionet/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 3 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6335.json b/mne-python/source/doc/sphinxext/prs/6335.json new file mode 100644 index 0000000000000000000000000000000000000000..7846cd3ace4e8a42d8efd5e20c30b74f7e7c06d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6335.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "724d6defd1053e92263250524c4c9c0a4c803f63", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 4 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_receptive_field_mtrf.py": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6336.json b/mne-python/source/doc/sphinxext/prs/6336.json new file mode 100644 index 0000000000000000000000000000000000000000..245e43cca2f06ac20c4e2ed2cc7d565b8b26597f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6336.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5105bad5229c93eabb09697aa3438008bf4b1f71", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 1 + }, + "tutorials/intro/plot_configuration.py": { + "a": 230, + "d": 0 + }, + "tutorials/misc/plot_configuration.py": { + "a": 0, + "d": 88 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6337.json b/mne-python/source/doc/sphinxext/prs/6337.json new file mode 100644 index 0000000000000000000000000000000000000000..4bda12e3171d42d66f0b4fa2a32a9d301f8923e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6337.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "441181daff6065c3ef6ee8daa9df3d19196fd129", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + "doc/_templates/navbar.html": { + "a": 2, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/634.json b/mne-python/source/doc/sphinxext/prs/634.json new file mode 100644 index 0000000000000000000000000000000000000000..14a97d495bd7ca99d69c5b5a01c196a8e9429fcd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/634.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b28ec9b08101f6b4441bd486d47692c3b6b4ef28", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 9, + "d": 5 + }, + "mne/layouts/layout.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 11, + "d": 0 + }, + "mne/viz.py": { + "a": 155, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6342.json b/mne-python/source/doc/sphinxext/prs/6342.json new file mode 100644 index 0000000000000000000000000000000000000000..c28c6a8eef810e668d192eb9b54992fe93982d39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6342.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "f26d81604a45577ff17bb2e63eb57cf66219eaa1", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_ftclient_rt_average.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_ftclient_rt_compute_psd.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_lslclient_rt.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/plot_rt_feedback_server.py": { + "a": 1, + "d": 1 + }, + "examples/realtime/rt_feedback_client.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/realtime/client.py": { + "a": 5, + "d": 1 + }, + "mne/realtime/epochs.py": { + "a": 6, + "d": 1 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 6, + "d": 1 + }, + "mne/realtime/lsl_client.py": { + "a": 6, + "d": 1 + }, + "mne/realtime/mock_lsl_stream.py": { + "a": 6, + "d": 1 + }, + "mne/realtime/mockclient.py": { + "a": 6, + "d": 1 + }, + "mne/realtime/stim_server_client.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6346.json b/mne-python/source/doc/sphinxext/prs/6346.json new file mode 100644 index 0000000000000000000000000000000000000000..1f8b5f051035581f5a72639341eeca2f0c979721 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6346.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0e461822c052d058cdea386e08200a04451c65a1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 13, + "d": 10 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6347.json b/mne-python/source/doc/sphinxext/prs/6347.json new file mode 100644 index 0000000000000000000000000000000000000000..505d18a63653d207ebea32275e58bad355a84f34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6347.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "10f52395c8b9ae8f121d9401d0219c0eadb4d77a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/event.py": { + "a": 10, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6348.json b/mne-python/source/doc/sphinxext/prs/6348.json new file mode 100644 index 0000000000000000000000000000000000000000..0dd02f6022c1a8ba704756aace160ed99aa1e92e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6348.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f0a1ae5b8803dcb3c6486b4c0089ba3b1a490c48", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 4, + "d": 4 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 17 + }, + "mne/io/cnt/cnt.py": { + "a": 6, + "d": 5 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 11, + "d": 17 + }, + "mne/io/eeglab/eeglab.py": { + "a": 4, + "d": 18 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 2, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/635.json b/mne-python/source/doc/sphinxext/prs/635.json new file mode 100644 index 0000000000000000000000000000000000000000..dddc239c506996e2de3eb27bdd60bfa1e4132bb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/635.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "38f133e51eb8bd74efd7c48e690a610b4d159b99", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 0, + "d": 5 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6350.json b/mne-python/source/doc/sphinxext/prs/6350.json new file mode 100644 index 0000000000000000000000000000000000000000..9a520f384d42d980a247253468f4f27fcea38e91 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6350.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "d12fffa6f73c4fc8f99822d649821e71f3e200cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 12 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 18 + }, + "doc/whats_new.rst": { + "a": 9, + "d": 9 + }, + "examples/realtime/README.txt": { + "a": 0, + "d": 5 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 0, + "d": 61 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 0, + "d": 122 + }, + "examples/realtime/plot_ftclient_rt_average.py": { + "a": 0, + "d": 104 + }, + "examples/realtime/plot_ftclient_rt_compute_psd.py": { + "a": 0, + "d": 90 + }, + "examples/realtime/plot_lslclient_rt.py": { + "a": 0, + "d": 51 + }, + "examples/realtime/plot_rt_feedback_server.py": { + "a": 0, + "d": 124 + }, + "examples/realtime/rt_feedback_client.py": { + "a": 0, + "d": 71 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6351.json b/mne-python/source/doc/sphinxext/prs/6351.json new file mode 100644 index 0000000000000000000000000000000000000000..d4ee9e3d647834fcb032e55385d46f7a602993a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6351.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "ca3bb6392e75c6f80707ce36241667fbe0e8d95e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/documentation.rst": { + "a": 1, + "d": 12 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 18 + }, + "doc/whats_new.rst": { + "a": 18, + "d": 10 + }, + "examples/realtime/README.txt": { + "a": 0, + "d": 5 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 0, + "d": 61 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 0, + "d": 122 + }, + "examples/realtime/plot_ftclient_rt_average.py": { + "a": 0, + "d": 104 + }, + "examples/realtime/plot_ftclient_rt_compute_psd.py": { + "a": 0, + "d": 90 + }, + "examples/realtime/plot_lslclient_rt.py": { + "a": 0, + "d": 51 + }, + "examples/realtime/plot_rt_feedback_server.py": { + "a": 0, + "d": 124 + }, + "examples/realtime/rt_feedback_client.py": { + "a": 0, + "d": 71 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6352.json b/mne-python/source/doc/sphinxext/prs/6352.json new file mode 100644 index 0000000000000000000000000000000000000000..ec10499a91955934161ef81b01af7113054499cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6352.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "30dbe3de08772c2b27515e7a98de988d926e8727", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 0, + "d": 1 + }, + "mne/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/realtime/__init__.py": { + "a": 0, + "d": 17 + }, + "mne/realtime/base_client.py": { + "a": 0, + "d": 212 + }, + "mne/realtime/client.py": { + "a": 0, + "d": 372 + }, + "mne/realtime/epochs.py": { + "a": 0, + "d": 588 + }, + "mne/realtime/fieldtrip_client.py": { + "a": 0, + "d": 264 + }, + "mne/realtime/lsl_client.py": { + "a": 0, + "d": 127 + }, + "mne/realtime/mock_lsl_stream.py": { + "a": 0, + "d": 95 + }, + "mne/realtime/mockclient.py": { + "a": 0, + "d": 204 + }, + "mne/realtime/stim_server_client.py": { + "a": 0, + "d": 306 + }, + "mne/realtime/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/realtime/tests/test_fieldtrip_client.py": { + "a": 0, + "d": 141 + }, + "mne/realtime/tests/test_lsl_client.py": { + "a": 0, + "d": 49 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 0, + "d": 386 + }, + "mne/realtime/tests/test_stim_client_server.py": { + "a": 0, + "d": 82 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6353.json b/mne-python/source/doc/sphinxext/prs/6353.json new file mode 100644 index 0000000000000000000000000000000000000000..32a89481e49728e894d544d2d1c7e4b07fda2d7c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6353.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "34d358d24bad903d65d184ac7720d6ee56d57741", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 4 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6355.json b/mne-python/source/doc/sphinxext/prs/6355.json new file mode 100644 index 0000000000000000000000000000000000000000..eb0943f23cf437f6e82e3ae8dc137ec4bea34cee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6355.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "06c7785aabe72fc7394cc6e6ba1c7d5aec1d2c76", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 15, + "d": 6 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 11 + }, + "mne/tests/test_annotations.py": { + "a": 3, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/utils/misc.py": { + "a": 10, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6356.json b/mne-python/source/doc/sphinxext/prs/6356.json new file mode 100644 index 0000000000000000000000000000000000000000..94936dbf438a9ee940859147bd3d11ea840e9def --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6356.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "580373859af9e65518660a0b8357003e1a5fdb95", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/discussions/plot_background_filtering.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6357.json b/mne-python/source/doc/sphinxext/prs/6357.json new file mode 100644 index 0000000000000000000000000000000000000000..55ab509c9b9afdea3f3d9ebb8aca21eacebcc07a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6357.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "595ab7e66fcc4854fa82eb6c00d5b20d5046fb3d", + "authors": [ + { + "n": "Kambiz Tavabi", + "e": "ktavabi@gmail.com" + } + ], + "changes": { + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6358.json b/mne-python/source/doc/sphinxext/prs/6358.json new file mode 100644 index 0000000000000000000000000000000000000000..65d9af02dc33f13ee0957979b7920bcc9eaaef94 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6358.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "532f6589e35c4519dc16bcf8768ed758e6b3fe45", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/annotation-controls.png": { + "a": 0, + "d": 0 + }, + "doc/glossary.rst": { + "a": 14, + "d": 10 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 14, + "d": 6 + }, + "mne/preprocessing/infomax_.py": { + "a": 5, + "d": 4 + }, + "mne/simulation/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/source.py": { + "a": 10, + "d": 4 + }, + "mne/stats/cluster_level.py": { + "a": 20, + "d": 8 + }, + "mne/stats/permutations.py": { + "a": 5, + "d": 2 + }, + "mne/utils/check.py": { + "a": 6, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/plot_introduction.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/plot_object_annotations.py": { + "a": 262, + "d": 209 + }, + "tutorials/raw/plot_annotating_raw.py": { + "a": 249, + "d": 0 + }, + "tutorials/raw/plot_events.py": { + "a": 179, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6360.json b/mne-python/source/doc/sphinxext/prs/6360.json new file mode 100644 index 0000000000000000000000000000000000000000..e1ed3b638eb086438a1823c3d45fb5edb53a762f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6360.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b9b2c6884dc663ef42338bdccc9e7838820b29b3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 25, + "d": 7 + }, + "mne/io/constants.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 30, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6366.json b/mne-python/source/doc/sphinxext/prs/6366.json new file mode 100644 index 0000000000000000000000000000000000000000..ca0de30bed81811c0c90b5d220806db49f66172a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6366.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "109312c1d3dac7f6204ec347a081adaf29793e21", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 2 + }, + "doc/documentation.rst": { + "a": 3, + "d": 3 + }, + "doc/git_links.inc": { + "a": 0, + "d": 99 + }, + "doc/glossary.rst": { + "a": 1, + "d": 3 + }, + "doc/index.rst": { + "a": 0, + "d": 3 + }, + "doc/install/advanced.rst": { + "a": 1, + "d": 1 + }, + "doc/install/contributing.rst": { + "a": 30, + "d": 30 + }, + "doc/install/freesurfer.rst": { + "a": 10, + "d": 8 + }, + "doc/install/index.rst": { + "a": 6, + "d": 7 + }, + "doc/install/mne_c.rst": { + "a": 5, + "d": 5 + }, + "doc/install/mne_python.rst": { + "a": 3, + "d": 3 + }, + "doc/install/pre_install.rst": { + "a": 17, + "d": 18 + }, + "doc/known_projects.inc": { + "a": 0, + "d": 63 + }, + "doc/links.inc": { + "a": 216, + "d": 4 + }, + "doc/this_project.inc": { + "a": 0, + "d": 12 + }, + "doc/tutorial_links.inc": { + "a": 0, + "d": 5 + }, + "doc/tutorials/philosophy.rst": { + "a": 1, + "d": 1 + }, + "tutorials/discussions/plot_background_statistics.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/plot_configuration.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/plot_sensors_decoding.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6368.json b/mne-python/source/doc/sphinxext/prs/6368.json new file mode 100644 index 0000000000000000000000000000000000000000..1705fcdf9e1de04db733f7fc40f9e602bb21e4a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6368.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "087a88edc27e41f63b1a3944fa5055c38893bed4", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/digitization/__init__.py": { + "a": 5, + "d": 0 + }, + "mne/digitization/_utils.py": { + "a": 393, + "d": 0 + }, + "mne/digitization/base.py": { + "a": 75, + "d": 0 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_marker_gui.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 17, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 1 + }, + "mne/io/artemis123/utils.py": { + "a": 5, + "d": 24 + }, + "mne/io/bti/bti.py": { + "a": 12, + "d": 52 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 6, + "d": 6 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 38, + "d": 100 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 11, + "d": 267 + }, + "mne/io/tests/test_meas_info.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6369.json b/mne-python/source/doc/sphinxext/prs/6369.json new file mode 100644 index 0000000000000000000000000000000000000000..874df98387574930ea04110b632939e5fdab9ed5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6369.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "dbda5849082e686770c02e12d97f2ef6f048937f", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/digitization/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/digitization/base.py": { + "a": 31, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 3, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_digitization.py": { + "a": 40, + "d": 0 + }, + "mne/utils/_bunch.py": { + "a": 3, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6370.json b/mne-python/source/doc/sphinxext/prs/6370.json new file mode 100644 index 0000000000000000000000000000000000000000..57e048f8161968339a9acc4ba7fa4df6191d622b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6370.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "62c0af865811cb4a2d22e231c2519a6e06f4bac4", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 38, + "d": 35 + }, + "mne/viz/backends/renderer.py": { + "a": 49, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6372.json b/mne-python/source/doc/sphinxext/prs/6372.json new file mode 100644 index 0000000000000000000000000000000000000000..ea9b2efc665242938b737a6717729b4aca8626da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6372.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "56bc9909a35081d1bf86fbbab0bf4dfaf5e9cc33", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 6, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/documentation.rst": { + "a": 361, + "d": 649 + }, + "doc/sphinxext/sphinx_bootstrap_divs/__init__.py": { + "a": 160, + "d": 0 + }, + "doc/sphinxext/sphinx_bootstrap_divs/bootstrap_divs.css": { + "a": 9, + "d": 0 + }, + "doc/sphinxext/sphinx_bootstrap_divs/bootstrap_divs.js": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6373.json b/mne-python/source/doc/sphinxext/prs/6373.json new file mode 100644 index 0000000000000000000000000000000000000000..e72b48f54e0a9376710b18d6145d8e95855dbad2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6373.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5e3b220d121f83b5edbf0d2c6fe6586b4f493d29", + "authors": [ + { + "n": "Ivana Kojcic", + "e": null + } + ], + "changes": { + "examples/simulation/plot_simulated_raw_data_using_subject_anatomy.py": { + "a": 67, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6374.json b/mne-python/source/doc/sphinxext/prs/6374.json new file mode 100644 index 0000000000000000000000000000000000000000..b044c5f835d5681cbd520c3824924f6480738aa9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6374.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5093d0061500787c9c8a617d8ac7f4020afb460c", + "authors": [ + { + "n": "Dirk Gütlin", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6376.json b/mne-python/source/doc/sphinxext/prs/6376.json new file mode 100644 index 0000000000000000000000000000000000000000..89b182ed540d6c8d5924be46924c0214bdc1005e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6376.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f37903d48850a8af4eb6535df7d8dd1b5219385e", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/install/pre_install.rst": { + "a": 2, + "d": 2 + }, + "doc/links.inc": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/638.json b/mne-python/source/doc/sphinxext/prs/638.json new file mode 100644 index 0000000000000000000000000000000000000000..3bfedd6b8565d52cffe76f02fb52b964d97ef616 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/638.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2a359d02745cb9816c376ce3d3eed9ac7719a2f0", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 6, + "d": 0 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6381.json b/mne-python/source/doc/sphinxext/prs/6381.json new file mode 100644 index 0000000000000000000000000000000000000000..c498fe15318116084a948ee55fc141373db2274f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6381.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "90a7202352a1dc68177f15349ce806d262075c50", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 4, + "d": 6 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6384.json b/mne-python/source/doc/sphinxext/prs/6384.json new file mode 100644 index 0000000000000000000000000000000000000000..d8f482f08d371883dcd139594fd07bfbf2d3693f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6384.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c5e205fa8ebdd0d0d01f7e0d3561077169a85f71", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6385.json b/mne-python/source/doc/sphinxext/prs/6385.json new file mode 100644 index 0000000000000000000000000000000000000000..748d9384c5c5fd5aa96822c5be8677d01f1daeec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6385.json @@ -0,0 +1,155 @@ +{ + "merge_commit_sha": "06b4a1ef458f61c2d7313a8bd4d284a547aa8229", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/cov.py": { + "a": 2, + "d": 4 + }, + "mne/decoding/base.py": { + "a": 3, + "d": 4 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/search_light.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 2, + "d": 3 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 10, + "d": 13 + }, + "mne/forward/_lead_dots.py": { + "a": 5, + "d": 5 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 4 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 3, + "d": 3 + }, + "mne/label.py": { + "a": 10, + "d": 15 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 6, + "d": 8 + }, + "mne/morph.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 12 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 5 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 4 + }, + "mne/proj.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 3, + "d": 4 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 5, + "d": 11 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 2 + }, + "mne/source_space.py": { + "a": 4, + "d": 6 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 28 + }, + "mne/stats/permutations.py": { + "a": 2, + "d": 7 + }, + "mne/time_frequency/_stockwell.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/csd.py": { + "a": 7, + "d": 14 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/psd.py": { + "a": 3, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 19, + "d": 5 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6386.json b/mne-python/source/doc/sphinxext/prs/6386.json new file mode 100644 index 0000000000000000000000000000000000000000..2155630bd0af2e1285b712634611b34ab1f7c165 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6386.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5409a89233b764f3f3f3136cf9bf6b8d5fb0a4fe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 5, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6387.json b/mne-python/source/doc/sphinxext/prs/6387.json new file mode 100644 index 0000000000000000000000000000000000000000..0a81d6614634fa15e72064816fc7341c46760235 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6387.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0e71bec27a738dd3db69166264144729b9b1a8aa", + "authors": [ + { + "n": "Thomas Radman", + "e": "radman.thomas@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6388.json b/mne-python/source/doc/sphinxext/prs/6388.json new file mode 100644 index 0000000000000000000000000000000000000000..18fe999ec4bf0c106e691d4d7cceb7125b3c17ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6388.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "e1c4f0c1c3c76f8fc4c04e34af92090cae6ea10b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 8, + "d": 0 + }, + "doc/data_formats.rst": { + "a": 76, + "d": 0 + }, + "doc/glossary.rst": { + "a": 9, + "d": 8 + }, + "doc/manual/io.rst": { + "a": 64, + "d": 83 + }, + "doc/precision.rst": { + "a": 27, + "d": 0 + }, + "doc/units.rst": { + "a": 35, + "d": 0 + }, + "tutorials/intro/plot_info.py": { + "a": 2, + "d": 2 + }, + "tutorials/intro/plot_introduction.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/plot_object_raw.py": { + "a": 527, + "d": 91 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6391.json b/mne-python/source/doc/sphinxext/prs/6391.json new file mode 100644 index 0000000000000000000000000000000000000000..a674c6085583c1e8d3cecf2499014c42e1fbe5ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6391.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "db453878c085a2865cfe9801feabcb6d79065e5c", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/annotations.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6392.json b/mne-python/source/doc/sphinxext/prs/6392.json new file mode 100644 index 0000000000000000000000000000000000000000..6640f4dfb8db24209392250add4889a6fd87ad6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6392.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "109aa4b6f5b7e7bd4c5d9cac199cdaf55c569dde", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/mne_browse_raw.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6393.json b/mne-python/source/doc/sphinxext/prs/6393.json new file mode 100644 index 0000000000000000000000000000000000000000..7b027d083196fc1f4e19de31b6d52dcde89f003c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6393.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3db7d50866ae625a40749ca353b0f067b2575e23", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/mne_python.rst": { + "a": 92, + "d": 37 + }, + "doc/sphinxext/sphinx_bootstrap_divs/__init__.py": { + "a": 72, + "d": 36 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6394.json b/mne-python/source/doc/sphinxext/prs/6394.json new file mode 100644 index 0000000000000000000000000000000000000000..0ac483834a3993802f6710f0cba50b0c079d57fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6394.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3a89b550c95ea7d55031d68503e16b6db296809c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/misc/plot_sensor_locations.py": { + "a": 215, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6395.json b/mne-python/source/doc/sphinxext/prs/6395.json new file mode 100644 index 0000000000000000000000000000000000000000..d9fff626458924c75b47447e0dd4fc2b60fbcc26 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6395.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0679e350cc20a07f3d043fec0be9a2153aa99a2b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6396.json b/mne-python/source/doc/sphinxext/prs/6396.json new file mode 100644 index 0000000000000000000000000000000000000000..a7134729075efb636913443409057d7fbc08f65e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6396.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6e0f8d83b5f5e95ef94aba541c639b213fa104d6", + "authors": [ + { + "n": "José C. García Alanis", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6398.json b/mne-python/source/doc/sphinxext/prs/6398.json new file mode 100644 index 0000000000000000000000000000000000000000..6616a9463fd32f794f56ed75d6b820a156867724 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6398.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bd2e5e9b6ab33fca2e91e91bc13cb254961d85e1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "LICENSE.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6399.json b/mne-python/source/doc/sphinxext/prs/6399.json new file mode 100644 index 0000000000000000000000000000000000000000..bc9cd3e9be5a15f2b37e13798eb5d198469c4d35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6399.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ff70048d8ba11c9a395ddb11d07dd0afd16254da", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 5, + "d": 3 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/64.json b/mne-python/source/doc/sphinxext/prs/64.json new file mode 100644 index 0000000000000000000000000000000000000000..4ac391941cd7d1c29e0dc9b045a6b80119850cb9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/64.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2fd38c04c8bd07fc231064c50133c6de76cad4b7", + "authors": [ + { + "n": "Louis Thibault", + "e": null + } + ], + "changes": { + "mne/event.py": { + "a": 10, + "d": 5 + }, + "mne/fiff/raw.py": { + "a": 21, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/640.json b/mne-python/source/doc/sphinxext/prs/640.json new file mode 100644 index 0000000000000000000000000000000000000000..95f9482397dab778a73efb4a21fadff28ceade92 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/640.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "422ea3229199c7c7b9fdf70de7a4f9583850d160", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/layouts/CTF151.lay": { + "a": 153, + "d": 0 + }, + "mne/layouts/CTF275.lay": { + "a": 275, + "d": 0 + }, + "mne/layouts/layout.py": { + "a": 68, + "d": 24 + }, + "mne/layouts/tests/test_layout.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6400.json b/mne-python/source/doc/sphinxext/prs/6400.json new file mode 100644 index 0000000000000000000000000000000000000000..4bced4a744c5276d729c33fd3302b9faadb32118 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6400.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "21fc47f8c385da235fd3c9fad37882774e376b49", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/manual/datasets_index.rst": { + "a": 66, + "d": 43 + }, + "examples/datasets/plot_hf_sef_data.py": { + "a": 3, + "d": 1 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 2, + "d": 0 + }, + "tutorials/sample-datasets/plot_phantom_4DBTi.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6401.json b/mne-python/source/doc/sphinxext/prs/6401.json new file mode 100644 index 0000000000000000000000000000000000000000..8eacd762e5c1f9cf8b766b3d37bdb70910ea8792 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6401.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "43481253de2b21c2acb257115136c96bca3f4ba7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/proj.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6403.json b/mne-python/source/doc/sphinxext/prs/6403.json new file mode 100644 index 0000000000000000000000000000000000000000..64d823b5b9f36c44382d1d0d241396732947bb99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6403.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "910c1e6276eb1abd9e6e5af312c0543a2fd7dcbb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 33, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6404.json b/mne-python/source/doc/sphinxext/prs/6404.json new file mode 100644 index 0000000000000000000000000000000000000000..d6245eeef539f626e4c8d856071923047902b4e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6404.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2191e3d403e6da5176e4fef646c454eadede2504", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/install/mne_python.rst": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6405.json b/mne-python/source/doc/sphinxext/prs/6405.json new file mode 100644 index 0000000000000000000000000000000000000000..be8b0065466122bfb2c57ad5a873ffd7e799d9ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6405.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d7d8c889112a40fb0bdb478dc7e393aac9c99b8d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 4, + "d": 2 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 5, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 11, + "d": 6 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 26, + "d": 30 + }, + "mne/viz/tests/test_3d.py": { + "a": 19, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6407.json b/mne-python/source/doc/sphinxext/prs/6407.json new file mode 100644 index 0000000000000000000000000000000000000000..c817ee3eeb131f25aac033eb47c264ef54339690 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6407.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "3ea72bee527cc3e451733f80a8ca377144b185dc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 5, + "d": 5 + }, + "examples/time_frequency/plot_source_power_spectrum_opm.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/transformer.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 1 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6408.json b/mne-python/source/doc/sphinxext/prs/6408.json new file mode 100644 index 0000000000000000000000000000000000000000..82dfc581167dd4e38b54f397a5e23236e664ba3d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6408.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e1a160c88b8409c8a582e8993cff4806fc0a921e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/pick.py": { + "a": 21, + "d": 13 + }, + "mne/viz/tests/test_epochs.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6409.json b/mne-python/source/doc/sphinxext/prs/6409.json new file mode 100644 index 0000000000000000000000000000000000000000..2e99c808412e674d54253b4a9121ec9065367256 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6409.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c2b917619c297110d4e1b9d907a10a16bd7473f7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 55, + "d": 13 + }, + "mne/viz/tests/test_raw.py": { + "a": 34, + "d": 9 + }, + "mne/viz/utils.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6413.json b/mne-python/source/doc/sphinxext/prs/6413.json new file mode 100644 index 0000000000000000000000000000000000000000..c5e868cfb986d95d64e8f50bd57d2f6c0fd5ff94 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6413.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bd4b8064cdc7c07f0c56193e95ae63ea13ee268d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 20, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6414.json b/mne-python/source/doc/sphinxext/prs/6414.json new file mode 100644 index 0000000000000000000000000000000000000000..d99a5963e8c04b218906eee08310e51278bda48d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6414.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3acb8dc8c621629bb15c9d1c686e99af3d72c106", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/manual/datasets_index.rst": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 14, + "d": 7 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 9, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 9, + "d": 8 + }, + "tutorials/time-freq/plot_sensors_time_frequency.py": { + "a": 12, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6416.json b/mne-python/source/doc/sphinxext/prs/6416.json new file mode 100644 index 0000000000000000000000000000000000000000..d674292792606e3a4814a725148fbd957a464c81 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6416.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b786f219b15b881ff7e9a1a74f194a0818d657b0", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/tutorials/report.rst": { + "a": 4, + "d": 4 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/io/fiff/raw.py": { + "a": 6, + "d": 5 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 7 + }, + "mne/utils/tests/test_check.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6417.json b/mne-python/source/doc/sphinxext/prs/6417.json new file mode 100644 index 0000000000000000000000000000000000000000..f58a74ff83e58a4aa1d38fe063a797b154593afd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6417.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a420019e1360d3b1bfad28c5040070309c341cbc", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 13, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 7, + "d": 5 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/642.json b/mne-python/source/doc/sphinxext/prs/642.json new file mode 100644 index 0000000000000000000000000000000000000000..3b515d208aa39d88838e05a062a9232f6dbb2809 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/642.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7a66502914ca8d9b63639900306e77b5defd5e11", + "authors": [ + { + "n": "Yousra BEKHTI", + "e": "yousra.bekhti@gmail.com" + } + ], + "changes": { + "mne/viz.py": { + "a": 14, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6420.json b/mne-python/source/doc/sphinxext/prs/6420.json new file mode 100644 index 0000000000000000000000000000000000000000..1c935efc88d71f358ab0bd8c21ce3dae47220eff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6420.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "f4b66b57ba6ea6ccfa6b835a49198aa2d5778f9c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/_static/institution_logos/Aalto.svg": { + "a": 2466, + "d": 0 + }, + "doc/_static/institution_logos/Aarhus.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/BIDS.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/BU.svg": { + "a": 1, + "d": 0 + }, + "doc/_static/institution_logos/CEA.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Graz.jpg": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Harvard.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/ICM.jpg": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Ilmenau.gif": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Inserm.svg": { + "a": 46, + "d": 0 + }, + "doc/_static/institution_logos/Julich.svg": { + "a": 41, + "d": 0 + }, + "doc/_static/institution_logos/MGH.svg": { + "a": 18, + "d": 0 + }, + "doc/_static/institution_logos/MIT.svg": { + "a": 9, + "d": 0 + }, + "doc/_static/institution_logos/Martinos.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/NYU.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Telecom_Paris_Tech.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Washington.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/inria.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institutions.png": { + "a": 0, + "d": 0 + }, + "doc/_static/style.css": { + "a": 26, + "d": 6 + }, + "doc/_templates/layout.html": { + "a": 20, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6422.json b/mne-python/source/doc/sphinxext/prs/6422.json new file mode 100644 index 0000000000000000000000000000000000000000..75dcfe6fd101e8db7544b16fa128437431983e53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6422.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "5859fb1292dfd95dc1b60171c8fa99d0ac5a0fd9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 16, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 408, + "d": 413 + }, + "mne/viz/evoked.py": { + "a": 709, + "d": 760 + }, + "mne/viz/tests/test_epochs.py": { + "a": 91, + "d": 35 + }, + "mne/viz/tests/test_evoked.py": { + "a": 111, + "d": 121 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 92, + "d": 76 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6423.json b/mne-python/source/doc/sphinxext/prs/6423.json new file mode 100644 index 0000000000000000000000000000000000000000..795c6a155516b5ed7e630f42e80120a56c01d292 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6423.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3f4c82a7e7401a38c485deca7d9e3b655d605b62", + "authors": [ + { + "n": "José C. García Alanis", + "e": null + } + ], + "changes": { + "mne/datasets/limo/limo.py": { + "a": 21, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6426.json b/mne-python/source/doc/sphinxext/prs/6426.json new file mode 100644 index 0000000000000000000000000000000000000000..d84f945a65fa92fe65f975c5ca01f53e8a649f5a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6426.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "36522874ca0e0f50864a135de7a7a4624661fabf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 4 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6427.json b/mne-python/source/doc/sphinxext/prs/6427.json new file mode 100644 index 0000000000000000000000000000000000000000..809111455f8b66af7b1a307637e3ffd26506ff4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6427.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "69f8db962f2956f119000fd9fc4ee2cc609b9a53", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/misc.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6428.json b/mne-python/source/doc/sphinxext/prs/6428.json new file mode 100644 index 0000000000000000000000000000000000000000..abf2546a28d47c749254096357008641c74db118 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6428.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8dfbe7fd4d7528b5033407feba1bf0825682bf2a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/preprocessing/plot_eog_artifact_histogram.py": { + "a": 5, + "d": 4 + }, + "tutorials/misc/plot_sensor_locations.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6429.json b/mne-python/source/doc/sphinxext/prs/6429.json new file mode 100644 index 0000000000000000000000000000000000000000..296729059108b740a239555a4c693ad4e668dc8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6429.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9b10fba6defa0df87eacc0b28d9486a0789de933", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 10, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/643.json b/mne-python/source/doc/sphinxext/prs/643.json new file mode 100644 index 0000000000000000000000000000000000000000..0f7c92388f0d67829814ca7c8157df8f01ef31bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/643.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "430adcd0c5ec2dc819219964bdf44642e1b33fab", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 7, + "d": 7 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6430.json b/mne-python/source/doc/sphinxext/prs/6430.json new file mode 100644 index 0000000000000000000000000000000000000000..d01d9be5a8f88135db1e8c4f43be469ea40fc6d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6430.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "33b6dde0eec1449eb4257321de44b56972491972", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 21, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6432.json b/mne-python/source/doc/sphinxext/prs/6432.json new file mode 100644 index 0000000000000000000000000000000000000000..0f3e5477925f07ece8c21dec5fd9fff783c9cfbb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6432.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2fedaac463db67ac7a3435e419d6161e11a5edfb", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 20, + "d": 17 + }, + "doc/glossary.rst": { + "a": 2, + "d": 2 + }, + "tutorials/source-modeling/plot_background_freesurfer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6433.json b/mne-python/source/doc/sphinxext/prs/6433.json new file mode 100644 index 0000000000000000000000000000000000000000..cad24a052c696e1d48d62a2a3adcee1a0450c480 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6433.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "f2b7ed55cd8c80a3e3dd9bc89e2c32036bc1bd58", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 0, + "d": 1 + }, + ".gitignore": { + "a": 1, + "d": 1 + }, + "doc/_static/style.css": { + "a": 8, + "d": 0 + }, + "doc/conf.py": { + "a": 10, + "d": 2 + }, + "doc/documentation.rst": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_make_report.py": { + "a": 5, + "d": 4 + }, + "mne/html/jquery.js": { + "a": 0, + "d": 0 + }, + "mne/report.py": { + "a": 70, + "d": 5 + }, + "mne/tests/test_report.py": { + "a": 43, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6435.json b/mne-python/source/doc/sphinxext/prs/6435.json new file mode 100644 index 0000000000000000000000000000000000000000..39081b00d26936d80aaa416f78d4feb49c765e0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6435.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1f25533df6c2b75ef54122ff245d4f5cd2284179", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 15, + "d": 7 + }, + "mne/viz/backends/renderer.py": { + "a": 2, + "d": 4 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6436.json b/mne-python/source/doc/sphinxext/prs/6436.json new file mode 100644 index 0000000000000000000000000000000000000000..e5313814d96bcfc106b5ca53580f02c3ef44aeb4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6436.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0348292ec18f038982bf2d4e2ab99e7971933e2d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 66, + "d": 3 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6437.json b/mne-python/source/doc/sphinxext/prs/6437.json new file mode 100644 index 0000000000000000000000000000000000000000..20de880468d6d07906f877a8a385906fa56c72ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6437.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a2c75903d4471587582bc2715985dc82eff9ac12", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 23, + "d": 2 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6438.json b/mne-python/source/doc/sphinxext/prs/6438.json new file mode 100644 index 0000000000000000000000000000000000000000..d9cd087d107dabe0770c030114a03f1ffe2132ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6438.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8ea467d2799ddce525a59f490d72f1b50d71abc0", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 3 + }, + "mne/viz/tests/test_evoked.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6439.json b/mne-python/source/doc/sphinxext/prs/6439.json new file mode 100644 index 0000000000000000000000000000000000000000..5cfcf1f6b2a35fc9889aa1840850dc67c5e9663d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6439.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b07a871906ec4b03d40b3d8529e923b2d51037bf", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 8, + "d": 5 + }, + "mne/viz/tests/test_epochs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6440.json b/mne-python/source/doc/sphinxext/prs/6440.json new file mode 100644 index 0000000000000000000000000000000000000000..4ef0ddc4d8efebe4d8f1c80793a2d3c99243d611 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6440.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "033f8c13fb03772c26142a1782c18a2a65dc9e8e", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/defaults.py": { + "a": 3, + "d": 2 + }, + "mne/io/pick.py": { + "a": 3, + "d": 3 + }, + "mne/viz/tests/test_epochs.py": { + "a": 52, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6441.json b/mne-python/source/doc/sphinxext/prs/6441.json new file mode 100644 index 0000000000000000000000000000000000000000..1ebed886cda09fedfa1bcb062805b6951ac3f0b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6441.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d7c16766f7f32955bbd694ef0de2b1295ca6a96c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/freesurfer.rst": { + "a": 1, + "d": 1 + }, + "tutorials/raw/plot_object_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6442.json b/mne-python/source/doc/sphinxext/prs/6442.json new file mode 100644 index 0000000000000000000000000000000000000000..e13b9b1e05da7a719f56dde9c89ca26c0929a415 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6442.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8e4acd7f35cf6ea34d80a8d950b7a889b10d5153", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 10, + "d": 5 + }, + "mne/viz/tests/test_3d.py": { + "a": 10, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6443.json b/mne-python/source/doc/sphinxext/prs/6443.json new file mode 100644 index 0000000000000000000000000000000000000000..8030ee075940489d79a652cdecfc7a1515b971ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6443.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "376c2bdc067636c38488b1f7e3502d1b4e558efc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 9 + }, + "mne/tests/test_source_estimate.py": { + "a": 20, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6446.json b/mne-python/source/doc/sphinxext/prs/6446.json new file mode 100644 index 0000000000000000000000000000000000000000..661760ef0c4dae4cef5252faedf3dd22914471e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6446.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1ea4b49412c81588b6f149658e3c0c066fe710e0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/tutorials/report.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6447.json b/mne-python/source/doc/sphinxext/prs/6447.json new file mode 100644 index 0000000000000000000000000000000000000000..07cce11fe0a87cf8cc9121cac2f79d5dea574d47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6447.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ec11e7b8a536d1177af299a5aea59666774ea5f7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/source_space.py": { + "a": 16, + "d": 4 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 65, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6448.json b/mne-python/source/doc/sphinxext/prs/6448.json new file mode 100644 index 0000000000000000000000000000000000000000..c49ae050bd8168375e9df7fdb6d40fd1c763483d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6448.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5329dba29161aca72cb179759d258b0e0c9cd5ff", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/realtime/mock_lsl_stream.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6449.json b/mne-python/source/doc/sphinxext/prs/6449.json new file mode 100644 index 0000000000000000000000000000000000000000..6fdf45178334ce0d77e76206d573f652367fd955 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6449.json @@ -0,0 +1,283 @@ +{ + "merge_commit_sha": "0f9910f96c2ee82ff815ca4ab3758788c1a4dd1d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/_static/institution_logos/Aalto.svg": { + "a": 2466, + "d": 0 + }, + "doc/_static/institution_logos/Aarhus.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/BIDS.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/BU.svg": { + "a": 1, + "d": 0 + }, + "doc/_static/institution_logos/CEA.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Graz.jpg": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Harvard.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/ICM.jpg": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Ilmenau.gif": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Inserm.svg": { + "a": 46, + "d": 0 + }, + "doc/_static/institution_logos/Julich.svg": { + "a": 41, + "d": 0 + }, + "doc/_static/institution_logos/MGH.svg": { + "a": 18, + "d": 0 + }, + "doc/_static/institution_logos/MIT.svg": { + "a": 9, + "d": 0 + }, + "doc/_static/institution_logos/Martinos.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/NYU.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Telecom_Paris_Tech.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Washington.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/inria.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institutions.png": { + "a": 0, + "d": 0 + }, + "doc/_static/style.css": { + "a": 26, + "d": 6 + }, + "doc/_templates/layout.html": { + "a": 20, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 11, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 27, + "d": 6 + }, + "mne/conftest.py": { + "a": 2, + "d": 5 + }, + "mne/cov.py": { + "a": 2, + "d": 4 + }, + "mne/decoding/base.py": { + "a": 3, + "d": 4 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/search_light.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 2, + "d": 3 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 10, + "d": 13 + }, + "mne/forward/_lead_dots.py": { + "a": 5, + "d": 5 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 4 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 3, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 11, + "d": 16 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 14, + "d": 0 + }, + "mne/label.py": { + "a": 10, + "d": 12 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 6, + "d": 8 + }, + "mne/morph.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 6 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 4 + }, + "mne/proj.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 3, + "d": 4 + }, + "mne/simulation/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 5, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 2 + }, + "mne/source_space.py": { + "a": 4, + "d": 6 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 16 + }, + "mne/stats/permutations.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_annotations.py": { + "a": 3, + "d": 0 + }, + "mne/time_frequency/_stockwell.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/csd.py": { + "a": 7, + "d": 14 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/psd.py": { + "a": 3, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 6 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 19, + "d": 5 + }, + "mne/utils/misc.py": { + "a": 10, + "d": 6 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6450.json b/mne-python/source/doc/sphinxext/prs/6450.json new file mode 100644 index 0000000000000000000000000000000000000000..e24169efad7f23583d53169702bff63eec61f425 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6450.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e793105333158d5e6bcd7b87d9c4c768e3cfdce4", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 10, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6451.json b/mne-python/source/doc/sphinxext/prs/6451.json new file mode 100644 index 0000000000000000000000000000000000000000..37518bc85ec942db0c93b83717cbeb7f85c6c8ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6451.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "3b1704f581798cf71a88cbb5c352dc8beefa20ca", + "authors": [ + { + "n": "Jevri Hanna", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 5, + "d": 0 + }, + "examples/visualization/plot_sensor_noise_level.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 11, + "d": 7 + }, + "mne/io/base.py": { + "a": 14, + "d": 13 + }, + "mne/utils/docs.py": { + "a": 73, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 51, + "d": 60 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 46, + "d": 277 + }, + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 3, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 209, + "d": 2 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 4, + "d": 2 + }, + "tutorials/time-freq/plot_sensors_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6452.json b/mne-python/source/doc/sphinxext/prs/6452.json new file mode 100644 index 0000000000000000000000000000000000000000..8862f78e1e7ff47aea5afef5d4784667f9c59f2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6452.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d36440176cf3f3532f64e6f046c4a6a3eca028de", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 9, + "d": 2 + }, + "mne/report.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6453.json b/mne-python/source/doc/sphinxext/prs/6453.json new file mode 100644 index 0000000000000000000000000000000000000000..9b1e72a7e7e51d9087f046c3ff37f9c7779750b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6453.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "569924b3ddcca4245725930ebca243ef213b31ee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/tests/test_datasets.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6456.json b/mne-python/source/doc/sphinxext/prs/6456.json new file mode 100644 index 0000000000000000000000000000000000000000..1fa5d58185c1db678b0b3603e864578b6449e8d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6456.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0576ce744bb1649bab717a4a31c73d888673b32a", + "authors": [ + { + "n": "Ivana Kojcic", + "e": null + } + ], + "changes": { + "doc/manual/source_localization/forward.rst": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6457.json b/mne-python/source/doc/sphinxext/prs/6457.json new file mode 100644 index 0000000000000000000000000000000000000000..9b126430f3250f36a92270873bef459f629d1058 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6457.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5d2f027758ca2f456ae266dc02da15f250e0eb06", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/io/plot_read_proj.py": { + "a": 4, + "d": 2 + }, + "tutorials/preprocessing/plot_artifacts_correction_rejection.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/README.txt": { + "a": 3, + "d": 3 + }, + "tutorials/raw/plot_visualize_raw.py": { + "a": 164, + "d": 124 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6460.json b/mne-python/source/doc/sphinxext/prs/6460.json new file mode 100644 index 0000000000000000000000000000000000000000..b1a951a4daa1946ddef44410acc9e55e6570bb4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6460.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "ad305e0d51287e66b89e66cfdb49ba7620b5fad8", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/__init__.py": { + "a": 14, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 448, + "d": 0 + }, + "mne/viz/_brain/colormap.py": { + "a": 108, + "d": 0 + }, + "mne/viz/_brain/surface.py": { + "a": 184, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 88, + "d": 0 + }, + "mne/viz/_brain/view.py": { + "a": 26, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 22, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 32, + "d": 18 + }, + "mne/viz/backends/_utils.py": { + "a": 13, + "d": 0 + }, + "mne/viz/backends/base_renderer.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6464.json b/mne-python/source/doc/sphinxext/prs/6464.json new file mode 100644 index 0000000000000000000000000000000000000000..f537a4bc265f72cdcaf3b7ec3e0ad8abbfe8cbfe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6464.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "2638d929ba01a6ee937196ee3b23492cdd7fbc5f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/documentation.rst": { + "a": 0, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 4, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 3, + "d": 64 + }, + "examples/datasets/plot_opm_data.py": { + "a": 3, + "d": 3 + }, + "examples/forward/plot_decimate_head_surface.py": { + "a": 0, + "d": 35 + }, + "examples/forward/plot_left_cerebellum_volume_source.py": { + "a": 12, + "d": 37 + }, + "examples/inverse/plot_mne_crosstalk_function.py": { + "a": 3, + "d": 4 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 3, + "d": 4 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 20, + "d": 17 + }, + "examples/time_frequency/plot_source_power_spectrum_opm.py": { + "a": 2, + "d": 2 + }, + "examples/visualization/plot_3d_to_2d.py": { + "a": 3, + "d": 3 + }, + "examples/visualization/plot_eeg_on_scalp.py": { + "a": 2, + "d": 3 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 2, + "d": 12 + }, + "examples/visualization/plot_montage.py": { + "a": 3, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 88, + "d": 3 + }, + "mne/viz/__init__.py": { + "a": 4, + "d": 2 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 52, + "d": 5 + }, + "mne/viz/backends/_pyvista.py": { + "a": 26, + "d": 3 + }, + "mne/viz/backends/base_renderer.py": { + "a": 83, + "d": 2 + }, + "mne/viz/backends/renderer.py": { + "a": 55, + "d": 0 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 15, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 27, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6465.json b/mne-python/source/doc/sphinxext/prs/6465.json new file mode 100644 index 0000000000000000000000000000000000000000..9c155611f97e9a21d35442f7fd8985b23e6a0f9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6465.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ca870d2f04c20cee8957257df5f2d2c64d448b34", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "tutorials/evoked/plot_eeg_erp.py": { + "a": 4, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6469.json b/mne-python/source/doc/sphinxext/prs/6469.json new file mode 100644 index 0000000000000000000000000000000000000000..058b1606261e0b70a80e18c7d0fc2d080ce2e3ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6469.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d048fdea501502b42e6ad0a2597a3cf3c1d329b7", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 29, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 11, + "d": 2 + }, + "mne/utils/tests/test_numerics.py": { + "a": 23, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/647.json b/mne-python/source/doc/sphinxext/prs/647.json new file mode 100644 index 0000000000000000000000000000000000000000..9ee626e97f5d2be10a146a285ef4c7bf1472dad8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/647.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a9e074f60d58825eb22a580d3a98c48bdb0feb52", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/layouts/layout.py": { + "a": 32, + "d": 34 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6470.json b/mne-python/source/doc/sphinxext/prs/6470.json new file mode 100644 index 0000000000000000000000000000000000000000..6df07ea2807e432bcbdb2e5dbc7229f3618b16bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6470.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9dee0a7a37aeaf22d4ad9ddaf916f96802514340", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/io/egi/egi.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6471.json b/mne-python/source/doc/sphinxext/prs/6471.json new file mode 100644 index 0000000000000000000000000000000000000000..0ac6de151c019c634d94849cfb10cfe00e66a7b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6471.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "352d3f04d7f2472a75e9738994bb8064f7edf2e0", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/cnt/cnt.py": { + "a": 3, + "d": 2 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 25, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6472.json b/mne-python/source/doc/sphinxext/prs/6472.json new file mode 100644 index 0000000000000000000000000000000000000000..66990024e737e647b0100a542c14f284f3cbaba0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6472.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "f0149397503af6b585604d60bfe1d1327a4ac08a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 0, + "d": 4 + }, + "doc/documentation.rst": { + "a": 0, + "d": 2 + }, + "doc/manual/datasets_index.rst": { + "a": 0, + "d": 19 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 1 + }, + "examples/datasets/plot_megsim_data.py": { + "a": 0, + "d": 55 + }, + "examples/datasets/plot_megsim_data_single_trial.py": { + "a": 0, + "d": 36 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/megsim/__init__.py": { + "a": 0, + "d": 3 + }, + "mne/datasets/megsim/megsim.py": { + "a": 0, + "d": 162 + }, + "mne/datasets/megsim/urls.py": { + "a": 0, + "d": 179 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 0, + "d": 11 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 7 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6473.json b/mne-python/source/doc/sphinxext/prs/6473.json new file mode 100644 index 0000000000000000000000000000000000000000..f74a8583b2e0981226294cb63956bf58dd729774 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6473.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2272435bd21157d32b3c90d34d1bb7d15930c1e2", + "authors": [ + { + "n": "Elizabeth DuPre", + "e": null + } + ], + "changes": { + "doc/manual/preprocessing/ica.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6474.json b/mne-python/source/doc/sphinxext/prs/6474.json new file mode 100644 index 0000000000000000000000000000000000000000..6ba2c23c081572e3d88b8d478b5021f20fa6e2a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6474.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4b0c4e7fe9b2a2b8ca19c0f3efd7a84b944dc9e0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/intro/README.txt": { + "a": 4, + "d": 4 + }, + "tutorials/intro/plot_introduction.py": { + "a": 2, + "d": 5 + }, + "tutorials/intro/plot_projectors_intro.py": { + "a": 428, + "d": 0 + }, + "tutorials/raw/plot_annotating_raw.py": { + "a": 4, + "d": 8 + }, + "tutorials/raw/plot_object_raw.py": { + "a": 3, + "d": 5 + }, + "tutorials/raw/plot_visualize_raw.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6475.json b/mne-python/source/doc/sphinxext/prs/6475.json new file mode 100644 index 0000000000000000000000000000000000000000..864f99c945814c781c1face577813e15b648bded --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6475.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "03d42b46c9c13d4a9205331058ee3755e72e27d3", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6476.json b/mne-python/source/doc/sphinxext/prs/6476.json new file mode 100644 index 0000000000000000000000000000000000000000..828bd024baca55ec66a06e28865685d425cacc0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6476.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e6dc3bf9bf3a7faf24188958d8965439caa9c4b7", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 3, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 45, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6477.json b/mne-python/source/doc/sphinxext/prs/6477.json new file mode 100644 index 0000000000000000000000000000000000000000..8815b116b877982696d1f63f03822e8099d6a114 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6477.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "bef2afe5260f5afb48410f0fbe40263e32a929d5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/manual/datasets_index.rst": { + "a": 1, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "ignore_words.txt": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 3 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 58, + "d": 14 + }, + "mne/io/base.py": { + "a": 16, + "d": 108 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 7, + "d": 0 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6478.json b/mne-python/source/doc/sphinxext/prs/6478.json new file mode 100644 index 0000000000000000000000000000000000000000..1c470d72fc7d9abcb77266a0b7f01d9a60bc8e5e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6478.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "31ec9f401fb74f66f67d492e5ea04b636a04b5d8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 10, + "d": 3 + }, + "mne/io/reference.py": { + "a": 17, + "d": 9 + }, + "mne/io/tests/test_reference.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6480.json b/mne-python/source/doc/sphinxext/prs/6480.json new file mode 100644 index 0000000000000000000000000000000000000000..cddd170e056a32d1d3679669ec7c484cad05296b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6480.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2549c536721dfad921940cdbd821e3596fc513fa", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 9, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 75, + "d": 58 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 34, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6483.json b/mne-python/source/doc/sphinxext/prs/6483.json new file mode 100644 index 0000000000000000000000000000000000000000..7b35166d021b8da3b02992ae7a6291c94c9575d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6483.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "6c36f8806dffe48bd82e461ad6cc8aad782e5f43", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/dipole.py": { + "a": 15, + "d": 12 + }, + "mne/viz/_3d.py": { + "a": 76, + "d": 36 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 5, + "d": 2 + }, + "tutorials/misc/plot_ecog.py": { + "a": 2, + "d": 3 + }, + "tutorials/misc/plot_sensor_locations.py": { + "a": 1, + "d": 2 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_elekta.py": { + "a": 16, + "d": 20 + }, + "tutorials/sample-datasets/plot_phantom_4DBTi.py": { + "a": 11, + "d": 9 + }, + "tutorials/simulation/plot_dics.py": { + "a": 8, + "d": 5 + }, + "tutorials/simulation/plot_point_spread.py": { + "a": 2, + "d": 5 + }, + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 38, + "d": 16 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 9, + "d": 13 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6484.json b/mne-python/source/doc/sphinxext/prs/6484.json new file mode 100644 index 0000000000000000000000000000000000000000..99d34a9042ffc7d619b17cc714ccac7a0c1900ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6484.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d78574cc91ce42bec1fcccca2c4c26e643038e28", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/intro/plot_projectors_intro.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6486.json b/mne-python/source/doc/sphinxext/prs/6486.json new file mode 100644 index 0000000000000000000000000000000000000000..763ce74b5c6fa0e37c1835ad4586a4a78ed300b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6486.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1bec9934efc131321e4e5ad3625bf09007250166", + "authors": [ + { + "n": "Keith Doelling", + "e": "keith.doelling@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 2 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 2, + "d": 2 + }, + "mne/io/reference.py": { + "a": 34, + "d": 6 + }, + "mne/io/tests/test_reference.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6487.json b/mne-python/source/doc/sphinxext/prs/6487.json new file mode 100644 index 0000000000000000000000000000000000000000..176e5d399a99c9894992965e4b0959ec615e108e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6487.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "16df3204d4c75e13b4319dbcddd22b09ad918b47", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/io/pick.py": { + "a": 8, + "d": 8 + }, + "tutorials/intro/plot_info.py": { + "a": 147, + "d": 78 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6489.json b/mne-python/source/doc/sphinxext/prs/6489.json new file mode 100644 index 0000000000000000000000000000000000000000..45327b82e62e19b0bcff5256584261e9d950bb3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6489.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "2f9873e7759e62f8471326e37a2ad1cdd2c2e65d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/documentation.rst": { + "a": 7, + "d": 7 + }, + "tutorials/epochs/plot_epoching_and_averaging.py": { + "a": 0, + "d": 0 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 5, + "d": 4 + }, + "tutorials/intro/plot_20_events_from_raw.py": { + "a": 10, + "d": 8 + }, + "tutorials/intro/plot_30_info.py": { + "a": 3, + "d": 3 + }, + "tutorials/intro/plot_40_projectors_background.py": { + "a": 3, + "d": 1 + }, + "tutorials/intro/plot_50_configure_mne.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/plot_artifacts_correction_rejection.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/plot_10_raw_overview.py": { + "a": 5, + "d": 5 + }, + "tutorials/raw/plot_20_event_arrays.py": { + "a": 5, + "d": 3 + }, + "tutorials/raw/plot_30_annotate_raw.py": { + "a": 3, + "d": 1 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/649.json b/mne-python/source/doc/sphinxext/prs/649.json new file mode 100644 index 0000000000000000000000000000000000000000..fc613ec0b8c4c1a967c7d51cb1d9c1711b5d7eba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/649.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "65928ef2b39d035b3479f4dfe0cf53d2307f1e8a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_topo_compare_conditions.py": { + "a": 0, + "d": 1 + }, + "examples/plot_topography.py": { + "a": 1, + "d": 4 + }, + "examples/time_frequency/plot_tfr_topography.py": { + "a": 3, + "d": 5 + }, + "mne/viz.py": { + "a": 94, + "d": 58 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6490.json b/mne-python/source/doc/sphinxext/prs/6490.json new file mode 100644 index 0000000000000000000000000000000000000000..cf046ff893fb9af8be3530e597d610a742d28102 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6490.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ec5dd172358f8b082f7d82f6f67bd150f8047362", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 8, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6491.json b/mne-python/source/doc/sphinxext/prs/6491.json new file mode 100644 index 0000000000000000000000000000000000000000..acc53ea6c5be27d766c6356e0e15facee424bde5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6491.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "54efecca8ec333831a13cbd288b93925c52b9fbb", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 23, + "d": 13 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 4, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6492.json b/mne-python/source/doc/sphinxext/prs/6492.json new file mode 100644 index 0000000000000000000000000000000000000000..01936fe12da3c9ffe98ad335984dd2930059d27f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6492.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "226dcff0826518a385a7e62822dc7abf8e610d06", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 6, + "d": 4 + }, + "mne/evoked.py": { + "a": 35, + "d": 24 + }, + "mne/tests/test_evoked.py": { + "a": 18, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6494.json b/mne-python/source/doc/sphinxext/prs/6494.json new file mode 100644 index 0000000000000000000000000000000000000000..0c2ee11022921470bb3ba184ba7be4ab9ef4a13a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6494.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "68f5d09da60a17b5d162cd902c4d64379ad3d87e", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 48, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6495.json b/mne-python/source/doc/sphinxext/prs/6495.json new file mode 100644 index 0000000000000000000000000000000000000000..77cbc41b841873d27cbd3b367897627b28c7f55d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6495.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "e96b2d879c2c66bb69ede5a1519cf95a55b02ce4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 2, + "d": 2 + }, + "mne/cuda.py": { + "a": 4, + "d": 3 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 3, + "d": 3 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 9, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 6 + }, + "mne/time_frequency/csd.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/multitaper.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6496.json b/mne-python/source/doc/sphinxext/prs/6496.json new file mode 100644 index 0000000000000000000000000000000000000000..3243786f2edd29b9b9c1e1c773e0c7ccdb4b44eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6496.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4939f5144775b67f8da5c9457fcd83dd6d824f67", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6497.json b/mne-python/source/doc/sphinxext/prs/6497.json new file mode 100644 index 0000000000000000000000000000000000000000..2c8c815a42256e5f4884320d3d9ca7cfea4fa56a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6497.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "25b38f87c1a48385164396e0c5ad7a0dab85155d", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/nicolet/nicolet.py": { + "a": 2, + "d": 2 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 33, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6499.json b/mne-python/source/doc/sphinxext/prs/6499.json new file mode 100644 index 0000000000000000000000000000000000000000..0adba176c47fdc12573e15c17b0b22f536ebfaba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6499.json @@ -0,0 +1,263 @@ +{ + "merge_commit_sha": "cc1f8f29b6e297397c6dac9e752e287691fb7d2d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/font-awesome.css": { + "a": 2, + "d": 2 + }, + "doc/_static/font-source-code-pro.css": { + "a": 167, + "d": 0 + }, + "doc/_static/font-source-sans-pro.css": { + "a": 131, + "d": 0 + }, + "doc/_static/fonts/fontawesome/fontawesome-webfont.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/fontawesome/fontawesome-webfont.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/fontawesome/fontawesome-webfont.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/fontawesome/fontawesome-webfont.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-Bold.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-BoldIt.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-It.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-Regular.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-Semibold.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-SemiboldIt.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-Bold.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-BoldIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-It.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-Regular.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-Semibold.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-SemiboldIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-Bold.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-BoldIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-It.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-Regular.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-Semibold.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-SemiboldIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-Bold.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-BoldIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-It.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-Regular.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-Semibold.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-SemiboldIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-Bold.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-BoldIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-It.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-Regular.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-Semibold.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-SemiboldIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-Bold.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-BoldIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-It.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-Regular.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-Semibold.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-SemiboldIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-Bold.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-BoldIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-It.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-Regular.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-Semibold.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-SemiboldIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-Bold.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-BoldIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-It.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-Regular.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-Semibold.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-SemiboldIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-Bold.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-BoldIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-It.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-Regular.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-Semibold.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-SemiboldIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/style.css": { + "a": 23, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/65.json b/mne-python/source/doc/sphinxext/prs/65.json new file mode 100644 index 0000000000000000000000000000000000000000..6fe04009a69656aba5605a6ce92724e48caa263c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/65.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "24c78ffc745e27c513efc11003d349bd61d1cf1c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "doc/source/python_tutorial.rst": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/650.json b/mne-python/source/doc/sphinxext/prs/650.json new file mode 100644 index 0000000000000000000000000000000000000000..8b791b6e584223901e4fdd01e44a3f362f8edac2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/650.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f2fdc2363df87e3a40e878d424c407ac7fc16916", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/tests/test_viz.py": { + "a": 2, + "d": 0 + }, + "mne/viz.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6503.json b/mne-python/source/doc/sphinxext/prs/6503.json new file mode 100644 index 0000000000000000000000000000000000000000..4774cfa2704143c8f042cffeba8dd7a02b2dbbe2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6503.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "344cf674630c644ebb4d599e53cccdc35bf847d3", + "authors": [ + { + "n": "Dirk Gütlin", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6504.json b/mne-python/source/doc/sphinxext/prs/6504.json new file mode 100644 index 0000000000000000000000000000000000000000..736740f136ca035937bfd73889e470f724e30280 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6504.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fc1d25497fe2c47bd9aa129bf13ffb38aaaaf335", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 21, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6505.json b/mne-python/source/doc/sphinxext/prs/6505.json new file mode 100644 index 0000000000000000000000000000000000000000..b258da35d6b2d3ffa926cd05a751b12b71193344 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6505.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5e9d54822d99d85cf8c2d88f6438e78a909f41b8", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 43, + "d": 9 + }, + "mne/viz/tests/test_3d.py": { + "a": 12, + "d": 1 + }, + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 7, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6506.json b/mne-python/source/doc/sphinxext/prs/6506.json new file mode 100644 index 0000000000000000000000000000000000000000..994925a577d47c49c88e15140c740deb1461ed29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6506.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3b3c6e6565d3ec97faef18cab9a4323ba7b71b9d", + "authors": [ + { + "n": "Jevri Hanna", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6507.json b/mne-python/source/doc/sphinxext/prs/6507.json new file mode 100644 index 0000000000000000000000000000000000000000..16bc53962713a55296cfad9ca4bd2fa8dfe1f862 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6507.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ec117dfea5a0f5e3591ab5d9710500ac4b2036f4", + "authors": [ + { + "n": "Paul Roujansky", + "e": "paul@roujansky.eu" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 18, + "d": 9 + }, + "mne/tests/test_epochs.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6509.json b/mne-python/source/doc/sphinxext/prs/6509.json new file mode 100644 index 0000000000000000000000000000000000000000..10209f9349b3fe625934a5dc376fb829e89a0c11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6509.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "831aaf42e93237e75bfd49e7d672eea38045625c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_3d.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/651.json b/mne-python/source/doc/sphinxext/prs/651.json new file mode 100644 index 0000000000000000000000000000000000000000..e3ccd3f5d5e5b99cf38be670ff6a5b1d4f68f324 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/651.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4bfad1779b4c8c07cf5870182e5e6f0777026804", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/artifacts/__init__.py": { + "a": 0, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6510.json b/mne-python/source/doc/sphinxext/prs/6510.json new file mode 100644 index 0000000000000000000000000000000000000000..e36c583acf7353f542eed370caa7af95465262d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6510.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f2a6afa8e4c44881ab8c8dfbc744c205ddf564b3", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6511.json b/mne-python/source/doc/sphinxext/prs/6511.json new file mode 100644 index 0000000000000000000000000000000000000000..2d0deb8ffe8351e6f50d6c385ee4f879beb13dab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6511.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "87bd40c0be41183c2f640627577101ce0ed40acf", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/egi/egi.py": { + "a": 4, + "d": 2 + }, + "mne/io/egi/egimff.py": { + "a": 4, + "d": 2 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 33, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6512.json b/mne-python/source/doc/sphinxext/prs/6512.json new file mode 100644 index 0000000000000000000000000000000000000000..228a35154323e7f13927fc0a33bea1c41d527113 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6512.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "897c3b2d12d0562f888784c5e18c2da31ed27ceb", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/bem.py": { + "a": 10, + "d": 8 + }, + "mne/surface.py": { + "a": 53, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 21, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 16, + "d": 2 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6513.json b/mne-python/source/doc/sphinxext/prs/6513.json new file mode 100644 index 0000000000000000000000000000000000000000..37a5e86bdda200f82ec601bf35ec514082760f03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6513.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7df663911b414b5f21241d3c301dc7318150c16d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 4, + "d": 4 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6514.json b/mne-python/source/doc/sphinxext/prs/6514.json new file mode 100644 index 0000000000000000000000000000000000000000..72b074cb8b31646eaa551c5dbb67133b04f87998 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6514.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "23fdb4136384696b866288032ceb5c47a4e0a589", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/commands/utils.py": { + "a": 5, + "d": 20 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6515.json b/mne-python/source/doc/sphinxext/prs/6515.json new file mode 100644 index 0000000000000000000000000000000000000000..34b2106876937a985c106151ab75348cf88f03a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6515.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e922e9fff8d42e996e5faa2d2b635eed76234671", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 103, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6516.json b/mne-python/source/doc/sphinxext/prs/6516.json new file mode 100644 index 0000000000000000000000000000000000000000..a81d3877963085548dcd25adcf407d11b08fac45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6516.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "70789c466133eaba410e1fc254c4b88723e30b77", + "authors": [ + { + "n": "Maksymenko Kostiantyn", + "e": "makkostya@ukr.net" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 8, + "d": 0 + }, + "mne/simulation/tests/test_source.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6517.json b/mne-python/source/doc/sphinxext/prs/6517.json new file mode 100644 index 0000000000000000000000000000000000000000..a5017778b359a77abefcd07f5c92d654100fb43d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6517.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "73e9f22ef2e9e3092121a09b46e74356606162d9", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_read_inverse.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6519.json b/mne-python/source/doc/sphinxext/prs/6519.json new file mode 100644 index 0000000000000000000000000000000000000000..4b5e467493c7fbab5de65159184f56c0deff8701 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6519.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4684eb5f38943dca74b04bf31f2527b1b2eb4977", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 0, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/652.json b/mne-python/source/doc/sphinxext/prs/652.json new file mode 100644 index 0000000000000000000000000000000000000000..4a89b3b6833dc043e18fd04b65065ab632c8e66a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/652.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "dc270325491d236d948c49c4b23fc58272d13131", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 4, + "d": 4 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 1, + "d": 1 + }, + "mne/forward.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 53, + "d": 28 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 11, + "d": 10 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 4, + "d": 4 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 28, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6520.json b/mne-python/source/doc/sphinxext/prs/6520.json new file mode 100644 index 0000000000000000000000000000000000000000..32151338f2a155c8781717c39a0d230d7065ac20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6520.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b3b14b91264d1089a61850b93847d44ba4bd587b", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 0, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 22, + "d": 4 + }, + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/base_renderer.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 5, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6521.json b/mne-python/source/doc/sphinxext/prs/6521.json new file mode 100644 index 0000000000000000000000000000000000000000..740edc7bc31e94d63a854fdeec326868970bb1c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6521.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "dd54d3c9c7c555c2c5d89f4a20a0f0d32cfc766b", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/channels/tests/test_montage.py": { + "a": 127, + "d": 5 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 0, + "d": 29 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 0, + "d": 25 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 0, + "d": 71 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 29 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 32 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 1, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6522.json b/mne-python/source/doc/sphinxext/prs/6522.json new file mode 100644 index 0000000000000000000000000000000000000000..03208fd42c38d11284f986b0772f8ee299ddf22c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6522.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e4caaf4142d476d3f108a1a0b1c77beeb447915", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/pre_install.rst": { + "a": 35, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6524.json b/mne-python/source/doc/sphinxext/prs/6524.json new file mode 100644 index 0000000000000000000000000000000000000000..e3cda7a284e5a61fd81697fc5c1c27d0c449ac8a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6524.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "047c9a707593095e8b2dd1af5e40afc82e7742aa", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 20, + "d": 9 + }, + "mne/viz/backends/base_renderer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 7, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6529.json b/mne-python/source/doc/sphinxext/prs/6529.json new file mode 100644 index 0000000000000000000000000000000000000000..b36379cd582776c82d61a83b8a4e54db2a93977e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6529.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5bc8457a1122da120148ee9e0dc8b09d33615c0b", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 86, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/653.json b/mne-python/source/doc/sphinxext/prs/653.json new file mode 100644 index 0000000000000000000000000000000000000000..a90b761018e7cb407e098403550f9cadeae1b1cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/653.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "641f62b78ae7ee2f403b1efebf06b715477d9bc5", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/export/plot_epochs_as_data_frame.py": { + "a": 19, + "d": 17 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 1, + "d": 1 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 3, + "d": 3 + }, + "examples/plot_evoked_topomap_delayed_ssp.py": { + "a": 4, + "d": 4 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 11, + "d": 18 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 17, + "d": 15 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 3, + "d": 2 + }, + "mne/epochs.py": { + "a": 9, + "d": 10 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 21, + "d": 17 + }, + "mne/source_estimate.py": { + "a": 8, + "d": 10 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 4, + "d": 2 + }, + "mne/viz.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6532.json b/mne-python/source/doc/sphinxext/prs/6532.json new file mode 100644 index 0000000000000000000000000000000000000000..01ee579220c025b322f9938cc024f1c972be8e76 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6532.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0bb360be833bde585f6d2cf59f9348e6b067dd48", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 12, + "d": 41 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6533.json b/mne-python/source/doc/sphinxext/prs/6533.json new file mode 100644 index 0000000000000000000000000000000000000000..a9ef95c07bfa51386f85d752d4f417d7b7fa6ad4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6533.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "201ce50343a7a6abe33c6383a6dbb3efce1489d2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/carousel.inc": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6534.json b/mne-python/source/doc/sphinxext/prs/6534.json new file mode 100644 index 0000000000000000000000000000000000000000..ee371865b9771db45415122fc7f3e98c18a66b29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6534.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "8c9a3a8ecbee675c7a2285fcd6b45d343e94c523", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 8 + }, + "mne/channels/montage.py": { + "a": 3, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 7, + "d": 3 + }, + "mne/epochs.py": { + "a": 1, + "d": 4 + }, + "mne/io/brainvision/brainvision.py": { + "a": 7, + "d": 15 + }, + "mne/io/cnt/cnt.py": { + "a": 10, + "d": 13 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 12, + "d": 25 + }, + "mne/io/eeglab/eeglab.py": { + "a": 38, + "d": 21 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 20, + "d": 16 + }, + "mne/io/egi/egi.py": { + "a": 5, + "d": 9 + }, + "mne/io/egi/egimff.py": { + "a": 5, + "d": 9 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 1, + "d": 2 + }, + "mne/io/nicolet/nicolet.py": { + "a": 9, + "d": 9 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 0, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 6, + "d": 0 + }, + "mne/io/utils.py": { + "a": 14, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6536.json b/mne-python/source/doc/sphinxext/prs/6536.json new file mode 100644 index 0000000000000000000000000000000000000000..89c8cabbf3c430f3114eb86510dac67d56df59b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6536.json @@ -0,0 +1,123 @@ +{ + "merge_commit_sha": "f71468814df671700feb6460dce34c259ac77b39", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 20, + "d": 17 + }, + "mne/filter.py": { + "a": 14, + "d": 9 + }, + "mne/fixes.py": { + "a": 18, + "d": 10 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 2 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/source.py": { + "a": 2, + "d": 1 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 5, + "d": 2 + }, + "mne/simulation/tests/test_raw.py": { + "a": 8, + "d": 2 + }, + "mne/simulation/tests/test_source.py": { + "a": 7, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 2, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 6, + "d": 2 + }, + "mne/stats/tests/test_permutations.py": { + "a": 5, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 4 + }, + "mne/tests/test_filter.py": { + "a": 7, + "d": 11 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/csd.py": { + "a": 0, + "d": 3 + }, + "mne/time_frequency/stft.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 5, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 7, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 3, + "d": 1 + }, + "mne/utils/tests/test_check.py": { + "a": 10, + "d": 2 + }, + "tutorials/discussions/plot_background_filtering.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6537.json b/mne-python/source/doc/sphinxext/prs/6537.json new file mode 100644 index 0000000000000000000000000000000000000000..a3f5c168a5fe7521e6a0a712d959f95c5391271c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6537.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7f77f3c7829abb89027f6e1194392d65dd1e8b17", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/cnt/_utils.py": { + "a": 47, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 13, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/654.json b/mne-python/source/doc/sphinxext/prs/654.json new file mode 100644 index 0000000000000000000000000000000000000000..348441ff71b14c8e303bcb3e5cac6aacc97a95e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/654.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "53f0c5b6aa68668dfc08d94b288c6cdca5c01804", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 14, + "d": 1 + }, + "examples/plot_estimate_covariance_matrix_raw.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6540.json b/mne-python/source/doc/sphinxext/prs/6540.json new file mode 100644 index 0000000000000000000000000000000000000000..fe0bb5e53b48c8f56c4ccfbf83406ed0cd4cd2f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6540.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "eb8f19f2ad96c52ecab5d37a78da5ab426c36e94", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 17, + "d": 17 + }, + "azure-pipelines.yml": { + "a": 9, + "d": 12 + }, + "doc/install/contributing.rst": { + "a": 41, + "d": 84 + }, + "doc/install/mne_python.rst": { + "a": 44, + "d": 19 + }, + "doc/links.inc": { + "a": 0, + "d": 1 + }, + "environment.yml": { + "a": 3, + "d": 3 + }, + "requirements.txt": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6541.json b/mne-python/source/doc/sphinxext/prs/6541.json new file mode 100644 index 0000000000000000000000000000000000000000..f079e9653e2f54de78dd4a086f035309f690dbc8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6541.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "964ea6c360b3cd89733c554671d97dc9ec0054de", + "authors": [ + { + "n": "Dirk Gütlin", + "e": null + } + ], + "changes": { + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 12 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 6 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 12 + }, + "mne/io/cnt/cnt.py": { + "a": 2, + "d": 12 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 12 + }, + "mne/io/edf/edf.py": { + "a": 5, + "d": 30 + }, + "mne/io/eeglab/eeglab.py": { + "a": 6, + "d": 14 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 6 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 6 + }, + "mne/io/eximia/eximia.py": { + "a": 2, + "d": 4 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 12 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 9 + }, + "mne/io/nicolet/nicolet.py": { + "a": 2, + "d": 12 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6545.json b/mne-python/source/doc/sphinxext/prs/6545.json new file mode 100644 index 0000000000000000000000000000000000000000..30233067e9f7d5cc7e4b8fecc2b4c3ed2855c240 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6545.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8fa3652b3a105a07230061fb90f3ee8371173798", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/brainvision/tests/data/test.vmrk": { + "a": 3, + "d": 3 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6546.json b/mne-python/source/doc/sphinxext/prs/6546.json new file mode 100644 index 0000000000000000000000000000000000000000..327e3c9134940c6279f96428589fce2ed185163a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6546.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "988986a55555f9d08b793b8b7d2b4c9b5477d5ba", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 1, + "d": 5 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6548.json b/mne-python/source/doc/sphinxext/prs/6548.json new file mode 100644 index 0000000000000000000000000000000000000000..71e2e6d9ec25cb018c0f1101d2694ebbb0c09b93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6548.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "26231ff6c79dd8543310302abb67f9be5bc31be9", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "CONTRIBUTING.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6549.json b/mne-python/source/doc/sphinxext/prs/6549.json new file mode 100644 index 0000000000000000000000000000000000000000..32d0f7a6d592a8d0140d51f925b755545335b9fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6549.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2b11463a704a017b2e75dac71c99e5335de21395", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/655.json b/mne-python/source/doc/sphinxext/prs/655.json new file mode 100644 index 0000000000000000000000000000000000000000..1e62ed9de08a1cf73e7d381fb634c04be734c1b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/655.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "407355aed4da0b07c01251efd352e27c0a7cc44a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_ecg_artifacts_from_ica.py": { + "a": 0, + "d": 109 + }, + "examples/preprocessing/plot_eog_artifacts_from_ica.py": { + "a": 0, + "d": 105 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 27, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6551.json b/mne-python/source/doc/sphinxext/prs/6551.json new file mode 100644 index 0000000000000000000000000000000000000000..3703a437d8307d8132f330868a3a60407d0d7dc9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6551.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "f64d6139464e83686cc44b15bc1b25774ffbf36c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 18, + "d": 4 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mne_crosstalk_function.py": { + "a": 2, + "d": 5 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 2, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 0, + "d": 4 + }, + "mne/viz/backends/_pyvista.py": { + "a": 163, + "d": 93 + }, + "mne/viz/tests/test_3d.py": { + "a": 0, + "d": 3 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tutorials/misc/plot_ecog.py": { + "a": 1, + "d": 1 + }, + "tutorials/simulation/plot_dics.py": { + "a": 9, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6553.json b/mne-python/source/doc/sphinxext/prs/6553.json new file mode 100644 index 0000000000000000000000000000000000000000..93ecba234e18fccb5e02adf31dbdbc93b2fb477b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6553.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "e2090d79154ddb3244ed4961544053612af2aa76", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 6, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/sphinx_bootstrap_divs/__init__.py": { + "a": 196, + "d": 0 + }, + "doc/sphinxext/sphinx_bootstrap_divs/bootstrap_divs.css": { + "a": 9, + "d": 0 + }, + "doc/sphinxext/sphinx_bootstrap_divs/bootstrap_divs.js": { + "a": 6, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 17, + "d": 15 + }, + "requirements.txt": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6554.json b/mne-python/source/doc/sphinxext/prs/6554.json new file mode 100644 index 0000000000000000000000000000000000000000..6a108fe7c0315d873b8b0f5d06edd7c4d31e60d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6554.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "60ca3f434389779eeed865b1893f3fa1caf37889", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 2, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 3 + }, + "tutorials/epochs/plot_metadata_epochs.py": { + "a": 2, + "d": 2 + }, + "tutorials/epochs/plot_visualize_epochs.py": { + "a": 5, + "d": 7 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 1, + "d": 2 + }, + "tutorials/stats-sensor-space/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6558.json b/mne-python/source/doc/sphinxext/prs/6558.json new file mode 100644 index 0000000000000000000000000000000000000000..5e6ef8e9159a268bd4d7bfd939f4fb10633a9b70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6558.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "31d356b6da8919835cfc7a69e6f07fc8680ceeb4", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/656.json b/mne-python/source/doc/sphinxext/prs/656.json new file mode 100644 index 0000000000000000000000000000000000000000..1dbd22e58df9be20e8af5279fc05c39faeabcda5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/656.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ad02680d49d4d827aef77cebbb0bef0c5a46c482", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/time_frequency/plot_tfr_topography.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6560.json b/mne-python/source/doc/sphinxext/prs/6560.json new file mode 100644 index 0000000000000000000000000000000000000000..68bf410a46ca53b61cb277cefa588d7cc5f3a4a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6560.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "91b5f2aa7a51e60232c8e8501ccd3f8cb59f027a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/epochs/plot_visualize_epochs.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6561.json b/mne-python/source/doc/sphinxext/prs/6561.json new file mode 100644 index 0000000000000000000000000000000000000000..3df61ed87b54c633c9622a9e5014a6616accc940 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6561.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6fe6b64c6601a0eb58bf15ba6e01bb20cca786c5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_filter.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6563.json b/mne-python/source/doc/sphinxext/prs/6563.json new file mode 100644 index 0000000000000000000000000000000000000000..998e9bf501df3f9d94234cb73f0911276d9e12a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6563.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "58cc2d3d094d88a4a88f08831ae00b459d334999", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/documentation.rst": { + "a": 6, + "d": 6 + }, + "tutorials/preprocessing/plot_10_preprocessing_overview.py": { + "a": 248, + "d": 0 + }, + "tutorials/preprocessing/plot_20_rejecting_bad_data.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/plot_30_filtering_resampling.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_45_ica_from_raw.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/plot_artifacts_detection.py": { + "a": 0, + "d": 137 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6564.json b/mne-python/source/doc/sphinxext/prs/6564.json new file mode 100644 index 0000000000000000000000000000000000000000..2c6387bd7e5e70fb00d09ad61c704ccc3f573771 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6564.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0e4354ebf423b2bc9e0b9ca9f000250af43688fb", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 3, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 66, + "d": 1 + }, + "mne/digitization/_utils.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6565.json b/mne-python/source/doc/sphinxext/prs/6565.json new file mode 100644 index 0000000000000000000000000000000000000000..641114b762f683f55e174872a694b9eb83ebf44a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6565.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2828cf7952ba892ad3116752c88226e6fca008e5", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/preprocessing/ecg.py": { + "a": 7, + "d": 3 + }, + "mne/preprocessing/eog.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6567.json b/mne-python/source/doc/sphinxext/prs/6567.json new file mode 100644 index 0000000000000000000000000000000000000000..5c56340e2f8c53c2a76318b7496fb2b3c9613b51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6567.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7d27ad33bdfaa59465e45c620c8bb864adc7375f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6570.json b/mne-python/source/doc/sphinxext/prs/6570.json new file mode 100644 index 0000000000000000000000000000000000000000..39732dc94549ee377cf4d32b2ceebc5f83e0348d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6570.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3eb246e4d71e1d6b81652224de7209213a4db3ed", + "authors": [ + { + "n": "Robert Seymour", + "e": null + } + ], + "changes": { + "mne/channels/data/layouts/KIT-125.lout": { + "a": 126, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 3, + "d": 0 + }, + "mne/io/kit/constants.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6571.json b/mne-python/source/doc/sphinxext/prs/6571.json new file mode 100644 index 0000000000000000000000000000000000000000..9d6dc95517e193d6892465917c5f6bbb88ee8766 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6571.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "702c6c91af896e4ddd0b56d5e803ba2ba0badd83", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6572.json b/mne-python/source/doc/sphinxext/prs/6572.json new file mode 100644 index 0000000000000000000000000000000000000000..9d1dde65fe26c5c62be5a5b9846d2a8571df698a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6572.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bfc1b0cc2eaf08a9f73652a8efcc0fce71667fe3", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/commands/utils.py": { + "a": 19, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6573.json b/mne-python/source/doc/sphinxext/prs/6573.json new file mode 100644 index 0000000000000000000000000000000000000000..0d3829136a0425bb4493a030dc419f5f8afeb0d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6573.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cea6f69f1aba4f495ff0808f542f6980f5ef4c10", + "authors": [ + { + "n": "Dirk Gütlin", + "e": null + } + ], + "changes": { + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6574.json b/mne-python/source/doc/sphinxext/prs/6574.json new file mode 100644 index 0000000000000000000000000000000000000000..05f95969fd8bf1e86e2f932b1f1003828af2453e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6574.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0cc24766de2f50fa062c009d00cf71c7caaa41a1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 38, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6575.json b/mne-python/source/doc/sphinxext/prs/6575.json new file mode 100644 index 0000000000000000000000000000000000000000..9898b0add91c6573e69e3248396e5e604e0b84e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6575.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "04997085e5f9cb67ed9a7a61d28551906f615580", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/annotation-controls.png": { + "a": 0, + "d": 0 + }, + "doc/manual/cookbook.rst": { + "a": 1, + "d": 1 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 2, + "d": 0 + }, + "tutorials/preprocessing/plot_10_preprocessing_overview.py": { + "a": 7, + "d": 14 + }, + "tutorials/preprocessing/plot_15_handling_bad_channels.py": { + "a": 268, + "d": 0 + }, + "tutorials/preprocessing/plot_20_rejecting_bad_data.py": { + "a": 199, + "d": 163 + }, + "tutorials/raw/plot_30_annotate_raw.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6577.json b/mne-python/source/doc/sphinxext/prs/6577.json new file mode 100644 index 0000000000000000000000000000000000000000..2cef0aef1c21796f49be47e65fd215d05bb4a750 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6577.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "141f061874197b795f2e6f3c9ce146e11e598316", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/morph.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6578.json b/mne-python/source/doc/sphinxext/prs/6578.json new file mode 100644 index 0000000000000000000000000000000000000000..5f2f79b95449748fc87d207cb096ef7d784abfa0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6578.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dd236d928e036356019685cede2f8109b7b6fd77", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 3 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/658.json b/mne-python/source/doc/sphinxext/prs/658.json new file mode 100644 index 0000000000000000000000000000000000000000..e4c4b996f82b442b102077f1712cd4de4f4e0991 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/658.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "de9fdfe2b012c8497e9f0e8a8ac78a1dfa09ce00", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "examples/plot_read_forward.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6582.json b/mne-python/source/doc/sphinxext/prs/6582.json new file mode 100644 index 0000000000000000000000000000000000000000..c335e8478706a95cf3bec67007608d767118425c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6582.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a7b39388b3f5225df554cd7cf770a80b0136fe94", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 27, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6585.json b/mne-python/source/doc/sphinxext/prs/6585.json new file mode 100644 index 0000000000000000000000000000000000000000..b2c7da8cd74df5b448a7dc36229b9343fd21c9c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6585.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d54333b4411e0bd810f33b0bf7629351c7968408", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_10_preprocessing_overview.py": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6586.json b/mne-python/source/doc/sphinxext/prs/6586.json new file mode 100644 index 0000000000000000000000000000000000000000..dd2829f6dad081d5f1e2737aa997c172ab4a07aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6586.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9d4fdc2d36aeee9dd20f713f8fd23afd2149adf0", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/base.py": { + "a": 12, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6589.json b/mne-python/source/doc/sphinxext/prs/6589.json new file mode 100644 index 0000000000000000000000000000000000000000..36f8da6739547ca73814de6ac5fda3a851c29e94 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6589.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "40f1f5e652cf0f85af0d82e796a366850322abef", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/659.json b/mne-python/source/doc/sphinxext/prs/659.json new file mode 100644 index 0000000000000000000000000000000000000000..ace9dd787ce8e4b0aa8dba4c54c44b1ed775aad1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/659.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "054938e95566ffd71e7ab10458dbbd9e70480984", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 2, + "d": 0 + }, + "mne/fiff/bti/raw.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/kit/kit.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/meas_info.py": { + "a": 52, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/tests/test_info.py": { + "a": 41, + "d": 0 + }, + "mne/viz.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6590.json b/mne-python/source/doc/sphinxext/prs/6590.json new file mode 100644 index 0000000000000000000000000000000000000000..ed8abd4e7dc678e1658637348d6ce8a00cd33077 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6590.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5bab96d4a76609f34b4e505b57746925b557173a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6591.json b/mne-python/source/doc/sphinxext/prs/6591.json new file mode 100644 index 0000000000000000000000000000000000000000..cb0a21c8d495fdca9e5e2f225d5ee2de70136c17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6591.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "368a490f9d7a298050ee04c2aa7882629c9fab21", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/annotations.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 15, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 9, + "d": 1 + }, + "mne/io/ctf/markers.py": { + "a": 77, + "d": 0 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 73, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6593.json b/mne-python/source/doc/sphinxext/prs/6593.json new file mode 100644 index 0000000000000000000000000000000000000000..7494c783eff2d6d670a00c208aa321876baeeb33 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6593.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e5a99df7c3440a3ca188218c12b82a212f779e09", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6594.json b/mne-python/source/doc/sphinxext/prs/6594.json new file mode 100644 index 0000000000000000000000000000000000000000..bfba4ef816b1a09353e103f6974e266fd0792c59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6594.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d75bce15717ee4cbf2abbdb5c6e5148959000a91", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/manual/datasets_index.rst": { + "a": 8, + "d": 8 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/plot_10_raw_overview.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6595.json b/mne-python/source/doc/sphinxext/prs/6595.json new file mode 100644 index 0000000000000000000000000000000000000000..82a58286e63b1fd027233a7c2321f33f80e77bbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6595.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "00806ca8b7e33f65a9782bfe8eb9b08b89c9ec70", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 11, + "d": 8 + }, + "mne/viz/tests/test_ica.py": { + "a": 14, + "d": 8 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 5, + "d": 2 + }, + "tutorials/preprocessing/plot_45_ica_from_raw.py": { + "a": 12, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6596.json b/mne-python/source/doc/sphinxext/prs/6596.json new file mode 100644 index 0000000000000000000000000000000000000000..1403fa089cfab2755b0110885ad6766ff229c4fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6596.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "060e40049f44893ffddb8a3dc28da7a5dc59f858", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 9, + "d": 0 + }, + "doc/_static/diagrams/ica.dot": { + "a": 72, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 0, + "d": 17 + }, + "mne/preprocessing/ica.py": { + "a": 43, + "d": 39 + }, + "mne/viz/ica.py": { + "a": 4, + "d": 3 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 508, + "d": 229 + }, + "tutorials/preprocessing/plot_45_ica_from_raw.py": { + "a": 0, + "d": 135 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6598.json b/mne-python/source/doc/sphinxext/prs/6598.json new file mode 100644 index 0000000000000000000000000000000000000000..60c4f0d0f5fca4f055f3995e00069a4e97450df3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6598.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1d0e34eb53c6f1d979eaf2704d5b440ecea9962d", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/bem.py": { + "a": 8, + "d": 8 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6599.json b/mne-python/source/doc/sphinxext/prs/6599.json new file mode 100644 index 0000000000000000000000000000000000000000..0cc0bf1db7a21e72e8a9becde33e4a82bfead706 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6599.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "14fe4fa5e92884dcf665fd96a71ec5bb49e4da96", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/conftest.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/66.json b/mne-python/source/doc/sphinxext/prs/66.json new file mode 100644 index 0000000000000000000000000000000000000000..83c600904ff2dfba0802e901a725e033ee146e0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/66.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "aab4e168ffb3e1446d4e9c18b54debe74aace403", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/time_frequency/stft.py": { + "a": 203, + "d": 0 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 43, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/660.json b/mne-python/source/doc/sphinxext/prs/660.json new file mode 100644 index 0000000000000000000000000000000000000000..fc94ba7e8746a4c91ed052f117d8422acf56de9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/660.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ec1d44ace6a92043872a39940ded41a422c77941", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 10, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6600.json b/mne-python/source/doc/sphinxext/prs/6600.json new file mode 100644 index 0000000000000000000000000000000000000000..042255eefe8da736a0a353bbb395304e5d896cae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6600.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "69d992c03b35b797407c876aa60dd7daabcce053", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 24, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 12, + "d": 5 + }, + "mne/io/brainvision/brainvision.py": { + "a": 15, + "d": 4 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 24, + "d": 1 + }, + "mne/transforms.py": { + "a": 22, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6602.json b/mne-python/source/doc/sphinxext/prs/6602.json new file mode 100644 index 0000000000000000000000000000000000000000..734b6b94e7aae901713d75daf92835f364399d81 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6602.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "65c4e60444da276ed09f086b81ee45bd13cb0375", + "authors": [ + { + "n": "Theodore Papadopoulo", + "e": "Theodore.Papadopoulo@inria.fr" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 3 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6603.json b/mne-python/source/doc/sphinxext/prs/6603.json new file mode 100644 index 0000000000000000000000000000000000000000..9ea49922fa182d2c9af481d07650b7526ca6b2dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6603.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "988653c69e37876e0ca64fc211d3937e9e42076f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".coveragerc": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 27, + "d": 10 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 13, + "d": 9 + }, + "mne/cov.py": { + "a": 3, + "d": 3 + }, + "mne/dipole.py": { + "a": 12, + "d": 8 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 55, + "d": 30 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 4 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 12, + "d": 14 + }, + "mne/io/pick.py": { + "a": 7, + "d": 3 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 18, + "d": 15 + }, + "mne/minimum_norm/inverse.py": { + "a": 11, + "d": 7 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 10, + "d": 8 + }, + "mne/utils/__init__.py": { + "a": 4, + "d": 1 + }, + "mne/utils/linalg.py": { + "a": 230, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 14, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/661.json b/mne-python/source/doc/sphinxext/prs/661.json new file mode 100644 index 0000000000000000000000000000000000000000..566aa995685604419ca176d9668c98ac6b41b0a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/661.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3c7e1d8fe40dedd5a319e90f0764e423b145d268", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 33, + "d": 15 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 40, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6611.json b/mne-python/source/doc/sphinxext/prs/6611.json new file mode 100644 index 0000000000000000000000000000000000000000..777f08aa80c89ced5bfab27277cbc011577d8c29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6611.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4624e5fe7b110d49b3d67ebdb5dfbb73a5b4ea91", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 12, + "d": 9 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 56, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6612.json b/mne-python/source/doc/sphinxext/prs/6612.json new file mode 100644 index 0000000000000000000000000000000000000000..49e2f2472ea7cff6dcbe82b039bc436ede3fedba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6612.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "935193090b2d101fbe5849d8392873ae0ecfd327", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "README.rst": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/install/mne_python.rst": { + "a": 4, + "d": 1 + }, + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 21, + "d": 0 + }, + "mne/forward/_compute_forward.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 103, + "d": 83 + }, + "mne/tests/test_surface.py": { + "a": 5, + "d": 2 + }, + "mne/utils/config.py": { + "a": 7, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6614.json b/mne-python/source/doc/sphinxext/prs/6614.json new file mode 100644 index 0000000000000000000000000000000000000000..1140a735616ac53775dd4b86ac0f927bc51bc515 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6614.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cc836c2635b7a720ec6c60074a1997fe52d7ca2f", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 0, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6617.json b/mne-python/source/doc/sphinxext/prs/6617.json new file mode 100644 index 0000000000000000000000000000000000000000..af0f6dd2c2e98189f615f80d9719066a0cd079ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6617.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dec30fe5e4266898ac2f93af39f64e3ae9686fb5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 16, + "d": 13 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/662.json b/mne-python/source/doc/sphinxext/prs/662.json new file mode 100644 index 0000000000000000000000000000000000000000..cbeeac58b41820a4f12d6c599c4a62fa9a0d93c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/662.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3b767fe77429a468b5fc9fb3a7f33a162afe1781", + "authors": [ + { + "n": "Romain Trachel", + "e": "trachelr@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_decoding_csp_space.py": { + "a": 101, + "d": 0 + }, + "mne/csp.py": { + "a": 163, + "d": 0 + }, + "mne/tests/test_csp.py": { + "a": 63, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6620.json b/mne-python/source/doc/sphinxext/prs/6620.json new file mode 100644 index 0000000000000000000000000000000000000000..ccf1ead17a5eaa00c5117324ecbd4e9d6aa46232 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6620.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7a790639d51d99afe9590809b05cc4b01a871aac", + "authors": [ + { + "n": "Lorenz Esch", + "e": null + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6622.json b/mne-python/source/doc/sphinxext/prs/6622.json new file mode 100644 index 0000000000000000000000000000000000000000..2bef835bd0808a6b8318725a7df503088ccd8f56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6622.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "18f06d118a45c23fa733b218c81630d968085e73", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/autosummary/class.rst": { + "a": 5, + "d": 1 + }, + "doc/_templates/autosummary/function.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 27, + "d": 3 + }, + "doc/sphinxext/README.txt": { + "a": 0, + "d": 25 + }, + "doc/sphinxext/gen_commands.py": { + "a": 10, + "d": 10 + }, + "doc/sphinxext/ipython_console_highlighting.py": { + "a": 0, + "d": 100 + }, + "doc/sphinxext/only_directives.py": { + "a": 0, + "d": 65 + }, + "examples/time_frequency/plot_compute_csd.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/.gitignore": { + "a": 1, + "d": 0 + }, + "tutorials/sample-datasets/plot_brainstorm_auditory.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6623.json b/mne-python/source/doc/sphinxext/prs/6623.json new file mode 100644 index 0000000000000000000000000000000000000000..3f440ee6308478b8cdfc0e79e9f12d1f8e05f464 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6623.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "07e605fa8ed49b1c7558051746033c2553db350e", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/brainvision/tests/data/test_bad_date.vhdr": { + "a": 0, + "d": 142 + }, + "mne/io/brainvision/tests/data/test_bad_date.vmrk": { + "a": 0, + "d": 25 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 59, + "d": 68 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6624.json b/mne-python/source/doc/sphinxext/prs/6624.json new file mode 100644 index 0000000000000000000000000000000000000000..8d60c27b61b0014c93d69c7fcba8bc2c3fce0f96 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6624.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "15c2cb0da6ab76072547e2a74a6a9e4564a55e8e", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 10, + "d": 3 + }, + "mne/stats/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 28, + "d": 5 + }, + "mne/stats/tests/test_permutations.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6625.json b/mne-python/source/doc/sphinxext/prs/6625.json new file mode 100644 index 0000000000000000000000000000000000000000..0dfe1e196276626bd4455c76eea6b38e3dfa1cb6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6625.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4d8b50db8656bcd35d2ce84a1c8004c50cb70cb2", + "authors": [ + { + "n": "Jevri Hanna", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6628.json b/mne-python/source/doc/sphinxext/prs/6628.json new file mode 100644 index 0000000000000000000000000000000000000000..aeb0253462e2bac6198b772d9335395b63d4ac38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6628.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d89e3ae132e6e1d49d3bf60f9e831763ec8cb155", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 3, + "d": 1 + }, + "mne/annotations.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_annotations.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/663.json b/mne-python/source/doc/sphinxext/prs/663.json new file mode 100644 index 0000000000000000000000000000000000000000..f1edfa569b753beda2f9c5157b1162bfd5143217 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/663.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4f08ce2001bc024e777d59b2936de2ba9f99b601", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 10, + "d": 24 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6630.json b/mne-python/source/doc/sphinxext/prs/6630.json new file mode 100644 index 0000000000000000000000000000000000000000..0e037bb32c299a8cf501148c50da8aeacfaa92c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6630.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "176ccfe72d22994cef2085b1b02fbaccd850d8ad", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 17, + "d": 23 + }, + "mne/forward/_compute_forward.py": { + "a": 9, + "d": 8 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 3 + }, + "tutorials/preprocessing/plot_10_preprocessing_overview.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6631.json b/mne-python/source/doc/sphinxext/prs/6631.json new file mode 100644 index 0000000000000000000000000000000000000000..7559f3161b8bf9810170a70fcfcd228d6ee3dac0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6631.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "486db19e7a06e4107d37c82290f22c4a3948d44c", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 3, + "d": 6 + }, + "mne/tests/test_annotations.py": { + "a": 20, + "d": 3 + }, + "tutorials/raw/plot_30_annotate_raw.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6633.json b/mne-python/source/doc/sphinxext/prs/6633.json new file mode 100644 index 0000000000000000000000000000000000000000..e57f926e185af320989ec182164927695387d940 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6633.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "98e720db27a5e02117d3e2372299bb0b9770be0d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 5, + "d": 4 + }, + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6635.json b/mne-python/source/doc/sphinxext/prs/6635.json new file mode 100644 index 0000000000000000000000000000000000000000..2e2fdbe8927111f254860868ac5f29523adbf548 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6635.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a193b52845b9484dccaec0cd68232cd33e02b258", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/reset-syntax.css": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6636.json b/mne-python/source/doc/sphinxext/prs/6636.json new file mode 100644 index 0000000000000000000000000000000000000000..92f15fc958f4fcf2a91bcef0cc49d0460478f8d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6636.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8705374530947482dae5c07d0ed3fa6e45c08861", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 32, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6638.json b/mne-python/source/doc/sphinxext/prs/6638.json new file mode 100644 index 0000000000000000000000000000000000000000..bc9757b17b5f6e56e9bd8aa32ad871f9d4bee9ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6638.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2ceb9c70e59b5cf143f4a2d9d2f541cb387d8c5e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/links.inc": { + "a": 1, + "d": 0 + }, + "tutorials/discussions/plot_background_statistics.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6639.json b/mne-python/source/doc/sphinxext/prs/6639.json new file mode 100644 index 0000000000000000000000000000000000000000..03cf7fb77e384b5f1d0047a20a36598f12d62f8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6639.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "0600f811dbdcbe288d4c51b1b2b4a055b193e9c3", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/visualization/plot_3d_to_2d.py": { + "a": 3, + "d": 4 + }, + "mne/channels/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 306, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 362, + "d": 258 + }, + "mne/channels/tests/test_montage.py": { + "a": 112, + "d": 47 + }, + "mne/coreg.py": { + "a": 1, + "d": 0 + }, + "mne/digitization/_utils.py": { + "a": 18, + "d": 8 + }, + "mne/gui/_file_traits.py": { + "a": 3, + "d": 11 + }, + "mne/io/array/tests/test_array.py": { + "a": 8, + "d": 8 + }, + "mne/io/fieldtrip/utils.py": { + "a": 4, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 1 + }, + "tutorials/misc/plot_ecog.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6640.json b/mne-python/source/doc/sphinxext/prs/6640.json new file mode 100644 index 0000000000000000000000000000000000000000..bb1141c0846c08d5d790649bbd1f732ff3a772b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6640.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c6226d792907be781095e93955e75a8f0ef0bfcb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/time_frequency/plot_source_power_spectrum_opm.py": { + "a": 8, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 13, + "d": 11 + }, + "tutorials/epochs/plot_visualize_epochs.py": { + "a": 2, + "d": 4 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6642.json b/mne-python/source/doc/sphinxext/prs/6642.json new file mode 100644 index 0000000000000000000000000000000000000000..7cbacdecaa45f368d0c73a84e5c74e3b15470e70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6642.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ae266c89814cd8f1ab3f77bbfeb7dfba8eeed295", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 10, + "d": 0 + }, + "examples/preprocessing/plot_movement_compensation.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 4 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 190, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6646.json b/mne-python/source/doc/sphinxext/prs/6646.json new file mode 100644 index 0000000000000000000000000000000000000000..00a632003eb4b85ab115569ed9c33a7863a248af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6646.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c952d71f78b63765037743ba4c641ec472516899", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_10_preprocessing_overview.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6648.json b/mne-python/source/doc/sphinxext/prs/6648.json new file mode 100644 index 0000000000000000000000000000000000000000..327dda1a73b8c83ababcabbf7097dfbd8c2a2985 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6648.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dcf01314bc2895a60bb26cb83ade53ad50f9ad95", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_55_setting_eeg_reference.py": { + "a": 211, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6650.json b/mne-python/source/doc/sphinxext/prs/6650.json new file mode 100644 index 0000000000000000000000000000000000000000..626e5e4309f292a97d8cd19d8b71050fa68e107b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6650.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "f954ef64ab2ff88f4e80ecebd50a87591c3a7225", + "authors": [ + { + "n": "Milan Rybář", + "e": "kontakt@milanrybar.cz" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 5, + "d": 0 + }, + "mne/io/tests/test_compensator.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 3 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6651.json b/mne-python/source/doc/sphinxext/prs/6651.json new file mode 100644 index 0000000000000000000000000000000000000000..4ad584605afc7d4503bf4b9172478881cfba63f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6651.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1f6f4f89a81df875ecb0a8c86c2542337dfbaaa9", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "environment.yml": { + "a": 0, + "d": 1 + }, + "requirements.txt": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6653.json b/mne-python/source/doc/sphinxext/prs/6653.json new file mode 100644 index 0000000000000000000000000000000000000000..4c20799f4fad0fb0b27d5b54b8ee68694e3ec0fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6653.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9e5329b267068b358bb13eda303038276964f2cb", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6655.json b/mne-python/source/doc/sphinxext/prs/6655.json new file mode 100644 index 0000000000000000000000000000000000000000..d0390ba42385886e4d78966c551cec1cf1da91db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6655.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e13ab53cbf8e0024774ab14d5e968fee2076121f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 1, + "d": 0 + }, + "mne/io/edf/_utils.py": { + "a": 0, + "d": 39 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 6 + }, + "mne/io/edf/gdf_encodes.txt": { + "a": 0, + "d": 284 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 1, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6658.json b/mne-python/source/doc/sphinxext/prs/6658.json new file mode 100644 index 0000000000000000000000000000000000000000..cc3fbb55eb5a45473feb98a2839a7d01fdb122c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6658.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "0ad37f0d156e74ed5949ad2a6046a5eb1826281d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".coveragerc": { + "a": 5, + "d": 0 + }, + "mne/fixes.py": { + "a": 3, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 119, + "d": 50 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 48, + "d": 25 + }, + "mne/surface.py": { + "a": 4, + "d": 4 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_erp.py": { + "a": 10, + "d": 9 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal.py": { + "a": 0, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 0, + "d": 2 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6659.json b/mne-python/source/doc/sphinxext/prs/6659.json new file mode 100644 index 0000000000000000000000000000000000000000..fc91be3ab78892685bfc54a98985379fdc6cc86e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6659.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "312b661e8822c2ae8e04d0e56fab5bf3779235c6", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/utils/mixin.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/666.json b/mne-python/source/doc/sphinxext/prs/666.json new file mode 100644 index 0000000000000000000000000000000000000000..a291bf6c9f57cb38f9351c999443f00d939126ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/666.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8f64083a981745837dc4f52565de29b7a339abe4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 15, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 37, + "d": 1 + }, + "mne/tests/test_viz.py": { + "a": 14, + "d": 6 + }, + "mne/viz.py": { + "a": 141, + "d": 39 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6660.json b/mne-python/source/doc/sphinxext/prs/6660.json new file mode 100644 index 0000000000000000000000000000000000000000..76051e932e40e68520a478e64c0591b07656e3e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6660.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3e3becd1062aa12e89a7e662df561321191de100", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 5, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6661.json b/mne-python/source/doc/sphinxext/prs/6661.json new file mode 100644 index 0000000000000000000000000000000000000000..48c1a42759b228c5c157265babd1e549359be72b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6661.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3a95f054a46abd989a529cd16f4c6eff468ee2de", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/_eloreta.py": { + "a": 20, + "d": 10 + }, + "mne/utils/linalg.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6663.json b/mne-python/source/doc/sphinxext/prs/6663.json new file mode 100644 index 0000000000000000000000000000000000000000..759367a58ca8ab49c8b17251850d9442ee85bd36 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6663.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "cc3473efd4a124897cb873ff482380c91c5a0cb7", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Alex Rockhill", + "e": "aprockhill206@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 66, + "d": 8 + }, + "mne/channels/tests/test_montage.py": { + "a": 40, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6664.json b/mne-python/source/doc/sphinxext/prs/6664.json new file mode 100644 index 0000000000000000000000000000000000000000..efd5d32dfc63842cc88ef9e49a29b8b42272998d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6664.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2649f92ae577c6a25c8b943b04ecdd97bb470173", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 17, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 9, + "d": 12 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6668.json b/mne-python/source/doc/sphinxext/prs/6668.json new file mode 100644 index 0000000000000000000000000000000000000000..048c32fe8f924bdc079f35213280b98187548bc9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6668.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3db196b0e0ecee3718ae2945b9a0a977902513e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 39, + "d": 21 + }, + "mne/commands/mne_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_report.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 21, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6669.json b/mne-python/source/doc/sphinxext/prs/6669.json new file mode 100644 index 0000000000000000000000000000000000000000..fc35044b5bd0d9bb437fbcadb066ffafc9b7d907 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6669.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cc0391dd51efd1ce0287631114f05052dc9dacf2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 8, + "d": 20 + }, + "mne/tests/test_coreg.py": { + "a": 14, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/667.json b/mne-python/source/doc/sphinxext/prs/667.json new file mode 100644 index 0000000000000000000000000000000000000000..a08a276659a2340fd56730898ec45656caeb9659 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/667.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a2da0c468ed371bfb77b7fbad76d2fe0b24672bd", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "mne/proj.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6670.json b/mne-python/source/doc/sphinxext/prs/6670.json new file mode 100644 index 0000000000000000000000000000000000000000..4e54b4fc7e721208c4557e240a4ebbfb516eeda3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6670.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "93c75710e7b991e78466e8361bf2d15d3bffa77a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 28, + "d": 49 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 6 + }, + "mne/viz/raw.py": { + "a": 17, + "d": 38 + }, + "mne/viz/utils.py": { + "a": 119, + "d": 60 + }, + "tutorials/preprocessing/plot_15_handling_bad_channels.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6674.json b/mne-python/source/doc/sphinxext/prs/6674.json new file mode 100644 index 0000000000000000000000000000000000000000..5bf45dca355bbf7dcb14ea09474290c2841cb2d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6674.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "8861432a3711a5355820b34f76ff6f1ce5d4ad43", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/_includes/data_formats.rst": { + "a": 2, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 0 + }, + "mne/cov.py": { + "a": 9, + "d": 2 + }, + "mne/defaults.py": { + "a": 6, + "d": 5 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 0 + }, + "mne/io/nirx/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 283, + "d": 0 + }, + "mne/io/nirx/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 89, + "d": 0 + }, + "mne/io/pick.py": { + "a": 24, + "d": 9 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_pick.py": { + "a": 16, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 7, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 10, + "d": 9 + }, + "tutorials/io/plot_30_reading_fnirs_data.py": { + "a": 38, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6677.json b/mne-python/source/doc/sphinxext/prs/6677.json new file mode 100644 index 0000000000000000000000000000000000000000..d723d8ff6aca295bbd17179789e7338b509362a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6677.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "694f4f2c184a538fc95444fd492e13a367c465ec", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6678.json b/mne-python/source/doc/sphinxext/prs/6678.json new file mode 100644 index 0000000000000000000000000000000000000000..a53872983cd59d6348c360fac5ab1f43f36889e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6678.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "86ab29166f75ec92a43f0c97241e784b4c527fbc", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6679.json b/mne-python/source/doc/sphinxext/prs/6679.json new file mode 100644 index 0000000000000000000000000000000000000000..b37a4eec4c23013091128a3131172b8b115acb41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6679.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0123589b2d8e257c348ffe999f9d6d43f0100773", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/artifact_path": { + "a": 1, + "d": 0 + }, + ".circleci/config.yml": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6680.json b/mne-python/source/doc/sphinxext/prs/6680.json new file mode 100644 index 0000000000000000000000000000000000000000..f1444ebce85385fec180253726b8d6c79f776db1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6680.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "55eac8915e23fb254cdc64c68c53eb0b6b6a266f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 19, + "d": 11 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 37, + "d": 32 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6681.json b/mne-python/source/doc/sphinxext/prs/6681.json new file mode 100644 index 0000000000000000000000000000000000000000..e5c4011f6e959f8caf0a751b8cf8b650c964f764 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6681.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "bf5df349e1046e607f1b46a7d553106f02ca7f8d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "bin/mne": { + "a": 1, + "d": 36 + }, + "doc/install/contributing.rst": { + "a": 32, + "d": 0 + }, + "mne/__main__.py": { + "a": 7, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 2, + "d": 5 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_compare_fiff.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 7 + }, + "mne/commands/mne_flash_bem.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 4 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 3, + "d": 3 + }, + "mne/commands/mne_maxfilter.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_report.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_show_fiff.py": { + "a": 1, + "d": 11 + }, + "mne/commands/mne_show_info.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_surf2bem.py": { + "a": 1, + "d": 3 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 2, + "d": 3 + }, + "mne/commands/utils.py": { + "a": 34, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6682.json b/mne-python/source/doc/sphinxext/prs/6682.json new file mode 100644 index 0000000000000000000000000000000000000000..5ba019a07ed095ccf22614ea4734b20c70cd21c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6682.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d41949910bfc1e88d171ef89e49ce58056bdf44e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 9, + "d": 0 + }, + "mne/io/open.py": { + "a": 6, + "d": 5 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6683.json b/mne-python/source/doc/sphinxext/prs/6683.json new file mode 100644 index 0000000000000000000000000000000000000000..430af0783fa1770db65bb2e5b4e8c2d32fad29bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6683.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "9530c96ffbe6c16764c0d3b5e87ec155df368f95", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 5, + "d": 2 + }, + "mne/epochs.py": { + "a": 5, + "d": 2 + }, + "mne/evoked.py": { + "a": 5, + "d": 2 + }, + "mne/io/base.py": { + "a": 6, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 9, + "d": 0 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 9, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6684.json b/mne-python/source/doc/sphinxext/prs/6684.json new file mode 100644 index 0000000000000000000000000000000000000000..dc27f926f3f0e3f09f28872a18316c04d896ef72 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6684.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "abaaccf5572dacc91415a47f01efb567edd15132", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/progressbar.py": { + "a": 11, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6688.json b/mne-python/source/doc/sphinxext/prs/6688.json new file mode 100644 index 0000000000000000000000000000000000000000..bdfc2820b1345fe25193a166337d7f718b7d73f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6688.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "490e39b726a6bdc0a1ebb44b425229b049a1f342", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 120, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 61, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6689.json b/mne-python/source/doc/sphinxext/prs/6689.json new file mode 100644 index 0000000000000000000000000000000000000000..c71976fce62a5597448987f6af97b2cabb3ebe3f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6689.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e3cbdb5442b9e39dfe79b685b2eb5d75871cecaa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/source_space.py": { + "a": 168, + "d": 105 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6690.json b/mne-python/source/doc/sphinxext/prs/6690.json new file mode 100644 index 0000000000000000000000000000000000000000..365fac7ae0fcad5dfa40f0df9d6115d2e57a1ccf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6690.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "65fe6d6a0d30a49c30b2a5f583dfc7a4395fa354", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/parallel.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6691.json b/mne-python/source/doc/sphinxext/prs/6691.json new file mode 100644 index 0000000000000000000000000000000000000000..1bb853ac768cec3670476e17b69e28ba5dde243b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6691.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "1189d1a755f4297dcb7212d053f7e1b0d12fd082", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.10.inc": { + "a": 148, + "d": 0 + }, + "doc/changes/0.11.inc": { + "a": 92, + "d": 0 + }, + "doc/changes/0.12.inc": { + "a": 211, + "d": 0 + }, + "doc/changes/0.13.inc": { + "a": 248, + "d": 0 + }, + "doc/changes/0.14.inc": { + "a": 250, + "d": 0 + }, + "doc/changes/0.15.inc": { + "a": 329, + "d": 0 + }, + "doc/changes/0.16.inc": { + "a": 258, + "d": 0 + }, + "doc/changes/0.17.inc": { + "a": 317, + "d": 0 + }, + "doc/changes/0.18.inc": { + "a": 268, + "d": 0 + }, + "doc/changes/0.2.inc": { + "a": 40, + "d": 0 + }, + "doc/changes/0.3.inc": { + "a": 40, + "d": 0 + }, + "doc/changes/0.4.inc": { + "a": 52, + "d": 0 + }, + "doc/changes/0.5.inc": { + "a": 125, + "d": 0 + }, + "doc/changes/0.6.inc": { + "a": 156, + "d": 0 + }, + "doc/changes/0.7.inc": { + "a": 136, + "d": 0 + }, + "doc/changes/0.8.inc": { + "a": 194, + "d": 0 + }, + "doc/changes/0.9.inc": { + "a": 239, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 154, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 256, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 20, + "d": 3531 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6692.json b/mne-python/source/doc/sphinxext/prs/6692.json new file mode 100644 index 0000000000000000000000000000000000000000..7605bfb5d0e892b875fdbe73b64079b3d6387705 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6692.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "adb70865accfbf2e473d0f78e5be69c090581c0d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/glossary.md": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6694.json b/mne-python/source/doc/sphinxext/prs/6694.json new file mode 100644 index 0000000000000000000000000000000000000000..37b0d3cd34051c1514327c89a55beeae3d8df12d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6694.json @@ -0,0 +1,147 @@ +{ + "merge_commit_sha": "d247e5577f30e8d101f400c49f17d1a71c0cfd35", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_includes/channel_types.rst": { + "a": 66, + "d": 0 + }, + "doc/_includes/data_formats.rst": { + "a": 9, + "d": 5 + }, + "doc/_includes/precision.rst": { + "a": 6, + "d": 5 + }, + "doc/_includes/units.rst": { + "a": 6, + "d": 5 + }, + "doc/conf.py": { + "a": 4, + "d": 4 + }, + "doc/documentation.rst": { + "a": 0, + "d": 440 + }, + "doc/glossary.rst": { + "a": 12, + "d": 8 + }, + "doc/install/contributing.rst": { + "a": 11, + "d": 9 + }, + "doc/install/index.rst": { + "a": 4, + "d": 3 + }, + "doc/install/pre_install.rst": { + "a": 3, + "d": 9 + }, + "doc/manual/index.rst": { + "a": 39, + "d": 0 + }, + "doc/manual/io.rst": { + "a": 12, + "d": 6 + }, + "doc/overview/cite.rst": { + "a": 31, + "d": 0 + }, + "doc/overview/command_line.rst": { + "a": 2, + "d": 0 + }, + "doc/overview/design_philosophy.rst": { + "a": 94, + "d": 0 + }, + "doc/overview/faq.rst": { + "a": 110, + "d": 92 + }, + "doc/overview/get_help.rst": { + "a": 16, + "d": 0 + }, + "doc/overview/implementation.rst": { + "a": 46, + "d": 0 + }, + "doc/overview/index.rst": { + "a": 60, + "d": 0 + }, + "doc/overview/learn_python.rst": { + "a": 29, + "d": 0 + }, + "doc/sphinxext/gen_commands.py": { + "a": 3, + "d": 1 + }, + "doc/tutorials/_images/plot_read_and_write_raw_data.png": { + "a": 0, + "d": 0 + }, + "doc/tutorials/_images/plot_read_epochs.png": { + "a": 0, + "d": 0 + }, + "doc/tutorials/_images/plot_time_frequency.png": { + "a": 0, + "d": 0 + }, + "doc/tutorials/mne-report.png": { + "a": 0, + "d": 0 + }, + "doc/tutorials/philosophy.rst": { + "a": 0, + "d": 153 + }, + "doc/tutorials/report.rst": { + "a": 0, + "d": 172 + }, + "examples/README.txt": { + "a": 11, + "d": 5 + }, + "examples/visualization/plot_make_report.py": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_report.py": { + "a": 59, + "d": 5 + }, + "mne/report.py": { + "a": 20, + "d": 12 + }, + "tutorials/README.txt": { + "a": 9, + "d": 1 + }, + "tutorials/misc/plot_report.py": { + "a": 197, + "d": 0 + }, + "tutorials/raw/plot_10_raw_overview.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/67.json b/mne-python/source/doc/sphinxext/prs/67.json new file mode 100644 index 0000000000000000000000000000000000000000..dbb0b0d2ee2db6f138705b9db58ab569aae102d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/67.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "395e203452d16181b2da1a4dc18008734188c17c", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/artifacts/stim.py": { + "a": 61, + "d": 0 + }, + "mne/artifacts/tests/test_stim.py": { + "a": 32, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/670.json b/mne-python/source/doc/sphinxext/prs/670.json new file mode 100644 index 0000000000000000000000000000000000000000..cb218cea0eb825f1b33f769275282e6a21784b75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/670.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6a232c948f32eaebb9c5ca0e118e803e9c37f105", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 6, + "d": 0 + }, + "mne/fiff/pick.py": { + "a": 5, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 34, + "d": 9 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 2 + }, + "mne/viz.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6700.json b/mne-python/source/doc/sphinxext/prs/6700.json new file mode 100644 index 0000000000000000000000000000000000000000..7ef4212d1976a6e2a90279532565b5bedcf66859 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6700.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "376999338ffc88e9f889ee4848273628769632c9", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/changes/0.18.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 0, + "d": 2 + }, + "doc/changes/names.inc": { + "a": 0, + "d": 1 + }, + "doc/conf.py": { + "a": 0, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 2 + }, + "mne/_digitization/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/_digitization/_utils.py": { + "a": 0, + "d": 0 + }, + "mne/_digitization/base.py": { + "a": 8, + "d": 5 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_marker_gui.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 18, + "d": 7 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_digitization.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6701.json b/mne-python/source/doc/sphinxext/prs/6701.json new file mode 100644 index 0000000000000000000000000000000000000000..895171c97c65d2f755cd9d9d4013fabcb82e9f23 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6701.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "bf03e17f323341a877dea62963c86cf140757896", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 2, + "d": 1 + }, + "mne/conftest.py": { + "a": 26, + "d": 1 + }, + "mne/fixes.py": { + "a": 17, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 2 + }, + "mne/forward/tests/test_forward.py": { + "a": 10, + "d": 14 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 9, + "d": 13 + }, + "mne/io/base.py": { + "a": 12, + "d": 28 + }, + "mne/io/fiff/raw.py": { + "a": 9, + "d": 11 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 43, + "d": 56 + }, + "mne/io/write.py": { + "a": 8, + "d": 6 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 11, + "d": 2 + }, + "mne/source_space.py": { + "a": 8, + "d": 1 + }, + "mne/surface.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 8, + "d": 10 + }, + "mne/tests/test_cov.py": { + "a": 13, + "d": 16 + }, + "mne/tests/test_source_estimate.py": { + "a": 21, + "d": 27 + }, + "mne/tests/test_source_space.py": { + "a": 43, + "d": 52 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 34, + "d": 18 + }, + "mne/utils/misc.py": { + "a": 2, + "d": 1 + }, + "mne/utils/tests/test_check.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 5 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6702.json b/mne-python/source/doc/sphinxext/prs/6702.json new file mode 100644 index 0000000000000000000000000000000000000000..7d16b2beaeb4d8fed9cf49a51cf3b018e0c1d174 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6702.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "d05dd9f9f5b7550189b4ffbd32dd5183a005fa28", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/faq.rst": { + "a": 15, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_what.py": { + "a": 25, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 9, + "d": 1 + }, + "mne/event.py": { + "a": 3, + "d": 1 + }, + "mne/io/tests/test_what.py": { + "a": 54, + "d": 0 + }, + "mne/io/what.py": { + "a": 70, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6704.json b/mne-python/source/doc/sphinxext/prs/6704.json new file mode 100644 index 0000000000000000000000000000000000000000..eccb8b91f77fcdd75d60a0a03a1667e2e300f433 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6704.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "bfef3b614f616afc14cad6f5e8e9330627d515b5", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 0 + }, + "mne/_digitization/_utils.py": { + "a": 4, + "d": 0 + }, + "mne/_digitization/base.py": { + "a": 16, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 24, + "d": 1 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 18, + "d": 18 + }, + "mne/channels/montage.py": { + "a": 331, + "d": 50 + }, + "mne/channels/tests/test_montage.py": { + "a": 371, + "d": 5 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6706.json b/mne-python/source/doc/sphinxext/prs/6706.json new file mode 100644 index 0000000000000000000000000000000000000000..1ef528b46c1d83cbdb2ec34ecdf3b5a0a20350c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6706.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b7dd664ab27fcd1b61a15165369ad3cce51e0220", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 3, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 41, + "d": 9 + }, + "mne/channels/montage.py": { + "a": 164, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 59, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6709.json b/mne-python/source/doc/sphinxext/prs/6709.json new file mode 100644 index 0000000000000000000000000000000000000000..0f600f23eb10f78088f65eba326927d54cfc23c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6709.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "27e0108b3a3d92973ceb92b339e18956499032f7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/671.json b/mne-python/source/doc/sphinxext/prs/671.json new file mode 100644 index 0000000000000000000000000000000000000000..b1147c4fefe96dabfc08be5f9e430eb8500f0254 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/671.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "993ca205bf22e263a1e4a9ffdde99a3077eec31d", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 9, + "d": 4 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 7, + "d": 7 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 41, + "d": 33 + }, + "mne/connectivity/spectral.py": { + "a": 5, + "d": 4 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 11, + "d": 10 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 14, + "d": 9 + }, + "mne/source_estimate.py": { + "a": 460, + "d": 259 + }, + "mne/tests/test_source_estimate.py": { + "a": 59, + "d": 19 + }, + "mne/tests/test_viz.py": { + "a": 1, + "d": 1 + }, + "mne/viz.py": { + "a": 7, + "d": 92 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6711.json b/mne-python/source/doc/sphinxext/prs/6711.json new file mode 100644 index 0000000000000000000000000000000000000000..e47f6b9fbf4922fe1daf980ab55e01b674e5c68a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6711.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b97cfbe2195115772a27e7489df6b705f6216372", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/evoked.py": { + "a": 12, + "d": 25 + }, + "mne/tests/test_evoked.py": { + "a": 5, + "d": 5 + }, + "mne/utils/numerics.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6712.json b/mne-python/source/doc/sphinxext/prs/6712.json new file mode 100644 index 0000000000000000000000000000000000000000..27a3771deb64bffe0604e6ec7a021df622e53041 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6712.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "3e60a9a45c2e48177c46348720737501dcd57918", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 0, + "d": 56 + }, + "mne/channels/montage.py": { + "a": 52, + "d": 14 + }, + "mne/channels/tests/test_montage.py": { + "a": 17, + "d": 10 + }, + "mne/gui/_file_traits.py": { + "a": 2, + "d": 2 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_montage.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6713.json b/mne-python/source/doc/sphinxext/prs/6713.json new file mode 100644 index 0000000000000000000000000000000000000000..edd8cab8ea2edc5d204866445eb9d675023b84ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6713.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "cd203d3b0f3d8054490b8705e40ebd318a939c74", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 4, + "d": 2 + }, + "mne/transforms.py": { + "a": 3, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 20, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6714.json b/mne-python/source/doc/sphinxext/prs/6714.json new file mode 100644 index 0000000000000000000000000000000000000000..023797b5452bca3aebb5fd912e0812d9e6d6dd5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6714.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "e99226eeed132daff799ac9544267eef38046f26", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/visualization/plot_montage.py": { + "a": 44, + "d": 16 + }, + "mne/_digitization/_utils.py": { + "a": 72, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 2, + "d": 72 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 181, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 97, + "d": 7 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 56, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6715.json b/mne-python/source/doc/sphinxext/prs/6715.json new file mode 100644 index 0000000000000000000000000000000000000000..5acef2d0f681843e4ac137675972a963fabbff4c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6715.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "751347db894da259c6c2ecaf65e81ab8c4aaffdf", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/visualization/plot_eeg_on_scalp.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 3, + "d": 1 + }, + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 4, + "d": 4 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6719.json b/mne-python/source/doc/sphinxext/prs/6719.json new file mode 100644 index 0000000000000000000000000000000000000000..ca00ac4b259a727b062362794e8983494fb0456c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6719.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6d1aa1c3017513efaa5c2a9a37b2ed6208dc5255", + "authors": [ + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6720.json b/mne-python/source/doc/sphinxext/prs/6720.json new file mode 100644 index 0000000000000000000000000000000000000000..f856e4b76a864a01d4f0dd3f20a18d31e0ffaf82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6720.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b3f46657fad1599262b6290b0c97a14d264ffc78", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6721.json b/mne-python/source/doc/sphinxext/prs/6721.json new file mode 100644 index 0000000000000000000000000000000000000000..bf762a002d036f5726eb05524fc3b7f5856d7fd0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6721.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9e8bb9113464800971895b0dff025bfa7718de0a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/data/coil_def.dat": { + "a": 7, + "d": 7 + }, + "mne/io/constants.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6722.json b/mne-python/source/doc/sphinxext/prs/6722.json new file mode 100644 index 0000000000000000000000000000000000000000..65d4eb7c8e2423c0169e4df2412d74b1f87cb021 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6722.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "79cc67d783cd95d400f1ba9c3f176cf41aca6550", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6723.json b/mne-python/source/doc/sphinxext/prs/6723.json new file mode 100644 index 0000000000000000000000000000000000000000..3e6fc90083a83d4f48a93714691f6c1b88a4d580 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6723.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d9d009fa4bd7f964a8a7756b93746fe9e814038d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/intro/plot_40_projectors_background.py": { + "a": 11, + "d": 9 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 370, + "d": 62 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6725.json b/mne-python/source/doc/sphinxext/prs/6725.json new file mode 100644 index 0000000000000000000000000000000000000000..6e3aa88cb81c5ac0038175709085b16c800f66b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6725.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c0d472b8894dc8f57d184d3a00debde602ce645a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_eeg_on_scalp.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 4, + "d": 4 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6726.json b/mne-python/source/doc/sphinxext/prs/6726.json new file mode 100644 index 0000000000000000000000000000000000000000..57d3136025c243bcbf8143e3ba34b3c5289a65ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6726.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "ef84593ab1a60065758f0bfedb7a8b2630494704", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 8, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 10, + "d": 7 + }, + "mne/viz/raw.py": { + "a": 11, + "d": 6 + }, + "mne/viz/tests/test_raw.py": { + "a": 6, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 88, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6727.json b/mne-python/source/doc/sphinxext/prs/6727.json new file mode 100644 index 0000000000000000000000000000000000000000..0d998f8e51bab661ebfc575dc0a6cafd68bdfc53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6727.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "84cee6d70c435b520ab3a3229c6c57d5634fccaf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 4, + "d": 1 + }, + "doc/manual/c_reference.rst": { + "a": 4, + "d": 7 + }, + "doc/manual/source_localization/morph_stc.rst": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6729.json b/mne-python/source/doc/sphinxext/prs/6729.json new file mode 100644 index 0000000000000000000000000000000000000000..39fbf2656b2026b6dce0bef9d3a0f20528291cc9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6729.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "68c2a57d433e3ec2dc7ebe0b642629f5df0e8f3c", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 3, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6730.json b/mne-python/source/doc/sphinxext/prs/6730.json new file mode 100644 index 0000000000000000000000000000000000000000..96ea0ded7bcad14559a93262ff1796d9ae65a877 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6730.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "daa0458a0ca91ebada2682fee43bb95ec388cd0d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 3, + "d": 2 + }, + "doc/manual/appendix/c_misc.rst": { + "a": 64, + "d": 61 + }, + "doc/manual/c_reference.rst": { + "a": 6, + "d": 2 + }, + "doc/manual/cookbook.rst": { + "a": 4, + "d": 4 + }, + "doc/manual/gui/analyze.rst": { + "a": 32, + "d": 24 + }, + "doc/manual/gui/browse.rst": { + "a": 95, + "d": 66 + }, + "doc/manual/index.rst": { + "a": 20, + "d": 21 + }, + "doc/manual/io.rst": { + "a": 6, + "d": 3 + }, + "doc/manual/matlab.rst": { + "a": 6, + "d": 6 + }, + "doc/manual/preprocessing/bads.rst": { + "a": 0, + "d": 5 + }, + "doc/manual/preprocessing/overview.rst": { + "a": 0, + "d": 5 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 48, + "d": 144 + }, + "doc/manual/source_localization/c_forward.rst": { + "a": 323, + "d": 262 + }, + "doc/manual/source_localization/c_inverse.rst": { + "a": 351, + "d": 309 + }, + "doc/manual/source_localization/c_morph.rst": { + "a": 108, + "d": 98 + }, + "doc/manual/source_localization/coil_geometries.rst": { + "a": 0, + "d": 266 + }, + "doc/manual/source_localization/forward.rst": { + "a": 0, + "d": 436 + }, + "doc/manual/source_localization/inverse.rst": { + "a": 0, + "d": 439 + }, + "doc/manual/source_localization/morph_stc.rst": { + "a": 0, + "d": 249 + }, + "doc/overview/faq.rst": { + "a": 2, + "d": 2 + }, + "doc/overview/index.rst": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 2, + "d": 1 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 2, + "d": 0 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_background_freesurfer.py": { + "a": 3, + "d": 2 + }, + "tutorials/source-modeling/plot_compute_covariance.py": { + "a": 3, + "d": 3 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6731.json b/mne-python/source/doc/sphinxext/prs/6731.json new file mode 100644 index 0000000000000000000000000000000000000000..47855a0c92d1fb79389610d8152a6e0615ac2d0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6731.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "93c525408450b01f61cf78851247c330d67a9f9e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_xhemi.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 26, + "d": 14 + }, + "mne/viz/_brain/_brain.py": { + "a": 453, + "d": 164 + }, + "mne/viz/_brain/colormap.py": { + "a": 105, + "d": 55 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 63, + "d": 18 + }, + "mne/viz/_brain/utils.py": { + "a": 100, + "d": 0 + }, + "mne/viz/_brain/view.py": { + "a": 25, + "d": 12 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 75, + "d": 13 + }, + "mne/viz/backends/_pyvista.py": { + "a": 86, + "d": 29 + }, + "mne/viz/backends/base_renderer.py": { + "a": 20, + "d": 6 + }, + "mne/viz/backends/renderer.py": { + "a": 6, + "d": 5 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 12, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 6 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6732.json b/mne-python/source/doc/sphinxext/prs/6732.json new file mode 100644 index 0000000000000000000000000000000000000000..ccce55d806f43323420d493eb9c52f648683db78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6732.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d1730caab121416351bb88d92aa6ffae0ab71c83", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_coreg_gui.py": { + "a": 72, + "d": 35 + }, + "mne/gui/_viewer.py": { + "a": 27, + "d": 21 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 4 + }, + "mne/source_space.py": { + "a": 11, + "d": 70 + }, + "mne/surface.py": { + "a": 75, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6733.json b/mne-python/source/doc/sphinxext/prs/6733.json new file mode 100644 index 0000000000000000000000000000000000000000..46b8179baf2a32ae1876f13f9ac76acb3c1ffe61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6733.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "17fe1132ea2ad9486217be1bc9ceedd738a602e1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 10, + "d": 0 + }, + "mne/coreg.py": { + "a": 55, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_fiducials_gui.py": { + "a": 10, + "d": 1 + }, + "mne/gui/_file_traits.py": { + "a": 6, + "d": 11 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 42, + "d": 43 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 12, + "d": 11 + }, + "mne/io/tests/test_what.py": { + "a": 2, + "d": 1 + }, + "mne/io/what.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_coreg.py": { + "a": 21, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6735.json b/mne-python/source/doc/sphinxext/prs/6735.json new file mode 100644 index 0000000000000000000000000000000000000000..ee148942b068e28d8ddf95ad1eba3ad591ee507d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6735.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "bf7dd06bc6e693dbe53dd607e122a5424a579cbe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 1 + }, + "README.rst": { + "a": 5, + "d": 6 + }, + "doc/changes/latest.inc": { + "a": 8, + "d": 0 + }, + "mne/filter.py": { + "a": 2, + "d": 4 + }, + "mne/fixes.py": { + "a": 26, + "d": 156 + }, + "mne/tests/test_fixes.py": { + "a": 0, + "d": 25 + }, + "mne/utils/linalg.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 21 + }, + "mne/viz/circle.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 7, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 3 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 9, + "d": 13 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 10, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6736.json b/mne-python/source/doc/sphinxext/prs/6736.json new file mode 100644 index 0000000000000000000000000000000000000000..6da510cf8ef46beda3177b88e737c71a49806879 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6736.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "25701d80296c53c7d1250b99a483569f61202072", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 5, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + }, + "mne/transforms.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 23, + "d": 32 + }, + "mne/viz/tests/test_raw.py": { + "a": 9, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6739.json b/mne-python/source/doc/sphinxext/prs/6739.json new file mode 100644 index 0000000000000000000000000000000000000000..0d20cb0addee5b3093ff9a35bd5dbcc20705ed61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6739.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ae1deeeded4d341e9991e92137c84d8590926d37", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6742.json b/mne-python/source/doc/sphinxext/prs/6742.json new file mode 100644 index 0000000000000000000000000000000000000000..57b687df393995ffdf07d8fd86c66d8311739c0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6742.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "21a224062e7f1cc088d94cdaef59aa2ed9efb675", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 2, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6743.json b/mne-python/source/doc/sphinxext/prs/6743.json new file mode 100644 index 0000000000000000000000000000000000000000..089aae334efa78887c9ff51b9adf4aff9f4075f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6743.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "80471f114bdcb80be6d66f62f18a9ab060e80a1e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.15.inc": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 3, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6744.json b/mne-python/source/doc/sphinxext/prs/6744.json new file mode 100644 index 0000000000000000000000000000000000000000..0f18f580ff5c4d0d70a2442b3636668e3d24d4c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6744.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8cc11b5fb08fd1aa1836f2e7f190cdb3e5dc53cc", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/viz/montage.py": { + "a": 4, + "d": 1 + }, + "mne/viz/tests/test_montage.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6745.json b/mne-python/source/doc/sphinxext/prs/6745.json new file mode 100644 index 0000000000000000000000000000000000000000..dc3d0c8ad9fddb94b53b2597e6024767e7478a7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6745.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "e16d112026d22850a12a5db8d819f334f7ff0886", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/visualization/plot_publication_figure.py": { + "a": 165, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 44, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 84, + "d": 80 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 35, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6747.json b/mne-python/source/doc/sphinxext/prs/6747.json new file mode 100644 index 0000000000000000000000000000000000000000..993d161111af4d1cb8dec67982966e13b03199bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6747.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dbed4f6f0e7c3c1efd1a76ba29f3149bbf6e15d1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/advanced.rst": { + "a": 4, + "d": 2 + }, + "doc/install/contributing.rst": { + "a": 15, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6748.json b/mne-python/source/doc/sphinxext/prs/6748.json new file mode 100644 index 0000000000000000000000000000000000000000..aaa25bdc3d699c11c63ffe5a8ffbce5b2e7099f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6748.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "88a2e3dae4b22ca13d088db8b2213745cd9a653c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 75, + "d": 22 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 65, + "d": 1 + }, + "tutorials/time-freq/plot_sensors_time_frequency.py": { + "a": 45, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6749.json b/mne-python/source/doc/sphinxext/prs/6749.json new file mode 100644 index 0000000000000000000000000000000000000000..9bca6be68852e1723f07edfed646f990c265f488 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6749.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "affc6854168e32e73a075a0104e7af8bddd7eefe", + "authors": [ + { + "n": "Victor Férat", + "e": "victor.ferat@live.Fr" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 135, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 33, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6750.json b/mne-python/source/doc/sphinxext/prs/6750.json new file mode 100644 index 0000000000000000000000000000000000000000..fbac43409d1459049dc80f770e43b1970956231d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6750.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a7ef05dd462aa4fa1710c5cd135bd2fb4f49a3b6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6751.json b/mne-python/source/doc/sphinxext/prs/6751.json new file mode 100644 index 0000000000000000000000000000000000000000..4e2fb6d86a4c70514e612894053de23f19ba81ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6751.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "13c8e69012d0b8a9cae44530c7acf96da66efb75", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 4, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6753.json b/mne-python/source/doc/sphinxext/prs/6753.json new file mode 100644 index 0000000000000000000000000000000000000000..850eade3030a55579113905d61d0e47aad13e600 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6753.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "17ffea91f5034005e6b47d8c9a89647bb11a678c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6754.json b/mne-python/source/doc/sphinxext/prs/6754.json new file mode 100644 index 0000000000000000000000000000000000000000..b97fd61d096b4c49b6446ea1799b872265dc2df3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6754.json @@ -0,0 +1,763 @@ +{ + "merge_commit_sha": "76ee63ff92b0424a304a12532d0cb53c0833a0ec", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 1, + "d": 1 + }, + "examples/datasets/spm_faces_dataset.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_rsa.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_stc.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_and_write_raw_data.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_events.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/io/plot_read_noise_covariance_matrix.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_evoked_whitening.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_ssp_projs_sensitivity_map.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_topo_compare_conditions.py": { + "a": 1, + "d": 1 + }, + "mne/_digitization/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/_digitization/base.py": { + "a": 1, + "d": 1 + }, + "mne/baseline.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_surf2bem.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/_fake/_fake.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/misc/_misc.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/opm/opm.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sample/sample.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/somato/somato.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/testing/_testing.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf_comp.py": { + "a": 1, + "d": 1 + }, + "mne/io/diff.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/matrix.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/open.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_compensator.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/tree.py": { + "a": 1, + "d": 1 + }, + "mne/io/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/misc.py": { + "a": 1, + "d": 1 + }, + "mne/parallel.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/selection.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/multi_comp.py": { + "a": 1, + "d": 1 + }, + "mne/stats/parametric.py": { + "a": 1, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_permutations.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_digitization.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/colormap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/view.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/base_renderer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "setup.py": { + "a": 3, + "d": 3 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 1, + "d": 1 + }, + "tutorials/time-freq/plot_sensors_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6755.json b/mne-python/source/doc/sphinxext/prs/6755.json new file mode 100644 index 0000000000000000000000000000000000000000..0923d42f752888c609ea6406b5fe090815c62b2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6755.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9585e93f8c2af699000bb47c2d6da1e9a6d79251", + "authors": [ + { + "n": "Abram Hindle", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 25, + "d": 20 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6756.json b/mne-python/source/doc/sphinxext/prs/6756.json new file mode 100644 index 0000000000000000000000000000000000000000..ce942546f8d9699052c4d82bc181b32f123aa3ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6756.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "edc1a48c1653f400ae4f223431c462ce5082d70a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "Makefile": { + "a": 5, + "d": 3 + }, + "setup.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6759.json b/mne-python/source/doc/sphinxext/prs/6759.json new file mode 100644 index 0000000000000000000000000000000000000000..5504aee37607bb1f6c080d3da078e13dc52cb87e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6759.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "812f8c468901a7334127cc96cfb8dcacb99c9478", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 0, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6761.json b/mne-python/source/doc/sphinxext/prs/6761.json new file mode 100644 index 0000000000000000000000000000000000000000..cd243201bd6c8205fe72aafafe7923ba4f29eca9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6761.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "e51e2cd5c3244f6d9b6aae4da713d838089cfa63", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 25, + "d": 14 + }, + "mne/viz/backends/_pyvista.py": { + "a": 13, + "d": 9 + }, + "mne/viz/backends/_utils.py": { + "a": 26, + "d": 1 + }, + "mne/viz/backends/base_renderer.py": { + "a": 50, + "d": 24 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 6, + "d": 6 + }, + "mne/viz/backends/tests/test_utils.py": { + "a": 41, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6764.json b/mne-python/source/doc/sphinxext/prs/6764.json new file mode 100644 index 0000000000000000000000000000000000000000..56f59c6bd73245192fe2ecd2987bef2819b6922a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6764.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "52f064415e7c9fa8fe243d22108dcdf3d86505b9", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/_includes/dig_formats.rst": { + "a": 41, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 10, + "d": 6 + }, + "doc/glossary.rst": { + "a": 16, + "d": 1 + }, + "doc/overview/implementation.rst": { + "a": 9, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 1 + }, + "mne/channels/__init__.py": { + "a": 4, + "d": 1 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 4, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 187, + "d": 61 + }, + "mne/channels/montage.py": { + "a": 246, + "d": 44 + }, + "mne/channels/tests/test_channels.py": { + "a": 6, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 297, + "d": 72 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 3, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 7, + "d": 6 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 5, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 3, + "d": 3 + }, + "mne/viz/montage.py": { + "a": 33, + "d": 17 + }, + "mne/viz/tests/test_montage.py": { + "a": 14, + "d": 11 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 1, + "d": 1 + }, + "tutorials/misc/plot_sensor_locations.py": { + "a": 27, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6765.json b/mne-python/source/doc/sphinxext/prs/6765.json new file mode 100644 index 0000000000000000000000000000000000000000..17e174c63c2fa146e2335497d5907c790e927f4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6765.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "f1f8e5413e04913011614e17f5daaa1ee84f973e", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 7, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 22, + "d": 31 + }, + "mne/channels/channels.py": { + "a": 23, + "d": 3 + }, + "mne/channels/montage.py": { + "a": 195, + "d": 38 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 274, + "d": 83 + }, + "mne/io/array/tests/test_array.py": { + "a": 4, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 27, + "d": 21 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 50, + "d": 10 + }, + "mne/io/eeglab/tests/_utils.py": { + "a": 38, + "d": 0 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 25, + "d": 33 + }, + "mne/io/fieldtrip/utils.py": { + "a": 3, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 8, + "d": 23 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 0, + "d": 1 + }, + "mne/viz/tests/test_montage.py": { + "a": 10, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6766.json b/mne-python/source/doc/sphinxext/prs/6766.json new file mode 100644 index 0000000000000000000000000000000000000000..c60c2f14b6800495a26889ee0440583a69c91954 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6766.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "7ffb345f1e3acf19070552b71961858b9c921373", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".github/CONTRIBUTING.md": { + "a": 1, + "d": 1 + }, + ".github/ISSUE_TEMPLATE/bug_report.md": { + "a": 1, + "d": 1 + }, + ".github/PULL_REQUEST_TEMPLATE.md": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 6, + "d": 6 + }, + "doc/index.rst": { + "a": 8, + "d": 8 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_docs.py": { + "a": 1, + "d": 1 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6767.json b/mne-python/source/doc/sphinxext/prs/6767.json new file mode 100644 index 0000000000000000000000000000000000000000..96afc253a8e55db0d1bcd1512c10e6ecbfaeb108 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6767.json @@ -0,0 +1,543 @@ +{ + "merge_commit_sha": "ff349f356edb04e1b5f0db13deda8d1a20aca351", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/glossary.rst": { + "a": 1, + "d": 1 + }, + "doc/install/freesurfer.rst": { + "a": 1, + "d": 1 + }, + "doc/install/index.rst": { + "a": 9, + "d": 2 + }, + "doc/install/mne_c.rst": { + "a": 2, + "d": 5 + }, + "doc/install/pre_install.rst": { + "a": 15, + "d": 17 + }, + "doc/links.inc": { + "a": 1, + "d": 0 + }, + "doc/manual/appendix/c_EULA.rst": { + "a": 0, + "d": 140 + }, + "doc/manual/appendix/c_misc.rst": { + "a": 0, + "d": 104 + }, + "doc/manual/appendix/c_release_notes.rst": { + "a": 0, + "d": 854 + }, + "doc/manual/appendix/martinos.rst": { + "a": 0, + "d": 117 + }, + "doc/manual/c_reference.rst": { + "a": 0, + "d": 6449 + }, + "doc/manual/gui/analyze.rst": { + "a": 0, + "d": 2681 + }, + "doc/manual/gui/browse.rst": { + "a": 0, + "d": 2267 + }, + "doc/manual/gui/mne_analyze/MNE_preferences.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/adjust_alignment.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/adjust_lights.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/adjust_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/cont_hpi_data.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/dipole_list.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/dipole_parameters.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/dipoles_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/epoch_selector.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/field_mapping_pref.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/file_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/hardcopy_controls.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/help_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/image_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/label_list.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/labels_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/main_window.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/movie_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/mri_viewer.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/open_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/overlay_management.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/patch_selection_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/save_label_timecourse.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/scales_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/surface_controls.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/surface_selection_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/timecourse_manager.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/view_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/viewer.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/viewer_options.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/visualize_hpi.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_analyze/windows_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/adjust_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/adust_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/average_pref.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/channel_selection.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/file_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/filter_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/help_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/main.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/manage_averages_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/new_selection.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/new_ssp.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/open_dialog copy.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/open_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/process_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/process_menu2.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/scales_dialog.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/scales_dialog2.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/toolbar.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-0.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-1.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-10.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-11.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-12.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-13.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-14.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-15.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-16.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-17.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-2.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-3.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-4.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-5.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-6.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-7.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-8.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu-9.png": { + "a": 0, + "d": 0 + }, + "doc/manual/gui/mne_browse_raw/windows_menu.png": { + "a": 0, + "d": 0 + }, + "doc/manual/index.rst": { + "a": 0, + "d": 38 + }, + "doc/manual/io.rst": { + "a": 0, + "d": 514 + }, + "doc/manual/migrating.rst": { + "a": 0, + "d": 56 + }, + "doc/manual/pics/Flowchart.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/ICA_primer.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/cover.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/flat.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/morphed.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/neuromag.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/orig.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/proj-off-on.png": { + "a": 0, + "d": 0 + }, + "doc/manual/pics/title_page.png": { + "a": 0, + "d": 0 + }, + "doc/manual/preprocessing/ica.rst": { + "a": 0, + "d": 118 + }, + "doc/manual/preprocessing/ssp.rst": { + "a": 0, + "d": 103 + }, + "doc/manual/sample_dataset.rst": { + "a": 0, + "d": 708 + }, + "doc/manual/visualization.rst": { + "a": 0, + "d": 5 + }, + "doc/overview/algorithms/bem_model.rst": { + "a": 15, + "d": 168 + }, + "doc/overview/algorithms/channel_interpolation.rst": { + "a": 0, + "d": 0 + }, + "doc/overview/algorithms/forward.rst": { + "a": 82, + "d": 238 + }, + "doc/overview/algorithms/images/CoordinateSystems.png": { + "a": 0, + "d": 0 + }, + "doc/overview/algorithms/images/HeadCS.png": { + "a": 0, + "d": 0 + }, + "doc/overview/algorithms/inverse.rst": { + "a": 23, + "d": 150 + }, + "doc/overview/algorithms/maxwell.rst": { + "a": 0, + "d": 0 + }, + "doc/overview/algorithms/memory.rst": { + "a": 1, + "d": 2 + }, + "doc/overview/algorithms/morph.rst": { + "a": 3, + "d": 36 + }, + "doc/overview/algorithms/ssp.rst": { + "a": 110, + "d": 0 + }, + "doc/overview/algorithms/time_frequency.rst": { + "a": 0, + "d": 0 + }, + "doc/overview/cookbook.rst": { + "a": 10, + "d": 21 + }, + "doc/overview/datasets_index.rst": { + "a": 65, + "d": 3 + }, + "doc/overview/faq.rst": { + "a": 2, + "d": 2 + }, + "doc/overview/images/Digitizer-example.png": { + "a": 0, + "d": 0 + }, + "doc/overview/images/flow_diagram.svg": { + "a": 0, + "d": 0 + }, + "doc/overview/implementation.rst": { + "a": 18, + "d": 0 + }, + "doc/overview/index.rst": { + "a": 14, + "d": 14 + }, + "doc/overview/matlab.rst": { + "a": 52, + "d": 44 + }, + "doc/overview/migrating.rst": { + "a": 76, + "d": 0 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 0, + "d": 3 + }, + "mne/coreg.py": { + "a": 2, + "d": 2 + }, + "tutorials/discussions/plot_background_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/discussions/plot_background_ica.py": { + "a": 97, + "d": 0 + }, + "tutorials/epochs/plot_visualize_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/plot_40_projectors_background.py": { + "a": 61, + "d": 7 + }, + "tutorials/sample-datasets/plot_brainstorm_auditory.py": { + "a": 1, + "d": 3 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/simulation/plot_creating_data_structures.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_background_freesurfer.py": { + "a": 3, + "d": 4 + }, + "tutorials/source-modeling/plot_compute_covariance.py": { + "a": 4, + "d": 3 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6768.json b/mne-python/source/doc/sphinxext/prs/6768.json new file mode 100644 index 0000000000000000000000000000000000000000..e11c874ab1faf74a717869f8e3f62fc86130b18b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6768.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a551eb83f28c2b479718b0ed758cbb7fd57d0e7c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/cuda.py": { + "a": 32, + "d": 2 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6769.json b/mne-python/source/doc/sphinxext/prs/6769.json new file mode 100644 index 0000000000000000000000000000000000000000..8221c65622b4f79f94783746803ac0bb55993427 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6769.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d9e278826e5301802d8ad22a91220304471b343d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/_make_forward.py": { + "a": 38, + "d": 36 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6771.json b/mne-python/source/doc/sphinxext/prs/6771.json new file mode 100644 index 0000000000000000000000000000000000000000..b3919129fa1fbf6632b479a1d2dc7eeb8320a17b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6771.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2545faf2f1b755d33184b9b1bcbbd8cd77a4bf4e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/links.inc": { + "a": 1, + "d": 1 + }, + "doc/overview/design_philosophy.rst": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6773.json b/mne-python/source/doc/sphinxext/prs/6773.json new file mode 100644 index 0000000000000000000000000000000000000000..5d7d88cd3fbfa367de8b9a7518a105c357780f55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6773.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "df6684669e974b3c58be9c8e3fe5386248f2db4a", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "tutorials/source-modeling/plot_forward.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6774.json b/mne-python/source/doc/sphinxext/prs/6774.json new file mode 100644 index 0000000000000000000000000000000000000000..b4761e1e04e7c29ac368ff4803fb6708954e8281 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6774.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "da5ffc58556c475db36b8c0f6bcf9df5df9a9519", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/_digitization/_utils.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 5, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/data/coil_def.dat": { + "a": 128, + "d": 13 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/io/constants.py": { + "a": 25, + "d": 5 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 127, + "d": 12 + }, + "mne/io/proc_history.py": { + "a": 8, + "d": 9 + }, + "mne/io/tests/test_constants.py": { + "a": 4, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 38, + "d": 24 + }, + "mne/surface.py": { + "a": 5, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 7, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6776.json b/mne-python/source/doc/sphinxext/prs/6776.json new file mode 100644 index 0000000000000000000000000000000000000000..d2d572f24c3cb74fe5798b1620cb8757232fd2da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6776.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "09a5b563e4060da6a105b208e412a56237513c08", + "authors": [ + { + "n": "Christian Clauss", + "e": "cclauss@me.com" + } + ], + "changes": { + ".travis.yml": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6780.json b/mne-python/source/doc/sphinxext/prs/6780.json new file mode 100644 index 0000000000000000000000000000000000000000..4ed094ec771bfd13fda3a3a2b2cd2c0b73524bd2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6780.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "859b926b4afb287fce3bf93fff057ce54395096e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6781.json b/mne-python/source/doc/sphinxext/prs/6781.json new file mode 100644 index 0000000000000000000000000000000000000000..8e62e03fd0cbcd8a5f140222bdd508a3882ad72e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6781.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "864eff175dfba286ebf7458614e3ea21b912d7c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6783.json b/mne-python/source/doc/sphinxext/prs/6783.json new file mode 100644 index 0000000000000000000000000000000000000000..6e7d53537f088336635bbbe4e7c1c786ea24a156 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6783.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "df2cdd4654bcf562bb75dd1eb9137103b4b0a7c6", + "authors": [ + { + "n": "José C. García Alanis", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 27, + "d": 0 + }, + "examples/datasets/plot_limo_data.py": { + "a": 247, + "d": 106 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 3, + "d": 2 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6785.json b/mne-python/source/doc/sphinxext/prs/6785.json new file mode 100644 index 0000000000000000000000000000000000000000..e13422b12cbde8d4f208e02730295ceade8a169f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6785.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5efc6ecf638853a1b7c1f9922e8913fc0ce9d138", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 5, + "d": 1 + }, + "mne/report.py": { + "a": 4, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 46, + "d": 14 + }, + "tutorials/source-modeling/plot_compute_covariance.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6786.json b/mne-python/source/doc/sphinxext/prs/6786.json new file mode 100644 index 0000000000000000000000000000000000000000..c5b7b2b34edc778907ce2938d158c7dd082dd140 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6786.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "381c409bb5ed8fdb23c2a686f89da89ede699907", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/mne_browse_raw.py": { + "a": 2, + "d": 6 + }, + "mne/commands/mne_coreg.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_report.py": { + "a": 2, + "d": 3 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 2, + "d": 3 + }, + "mne/commands/utils.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6787.json b/mne-python/source/doc/sphinxext/prs/6787.json new file mode 100644 index 0000000000000000000000000000000000000000..57dee42ab758e42942b89103961ca97214e37184 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6787.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "29b05f2f593f997168d2f29a41829f68f56ad5df", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6789.json b/mne-python/source/doc/sphinxext/prs/6789.json new file mode 100644 index 0000000000000000000000000000000000000000..a53748b6d7db4e29ed7303674c63aefd936e2042 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6789.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8df597484c0fd53fdb857cc2df5ca2bb53cce2d3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 64, + "d": 48 + }, + "mne/tests/test_source_estimate.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/679.json b/mne-python/source/doc/sphinxext/prs/679.json new file mode 100644 index 0000000000000000000000000000000000000000..819c5b369576450d09648029f7bfabd992edd1b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/679.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2c9ff2fb5d4e454dd2d8c727d98a41aa06c84aca", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 29, + "d": 8 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6790.json b/mne-python/source/doc/sphinxext/prs/6790.json new file mode 100644 index 0000000000000000000000000000000000000000..f4b638c6f572ada23b9d77ff1e7aaeec1f1d7f7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6790.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5cc1331229208faf20f7e2eb00cd38ceccaf5bef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_read_source_space.py": { + "a": 0, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6791.json b/mne-python/source/doc/sphinxext/prs/6791.json new file mode 100644 index 0000000000000000000000000000000000000000..d71a3709161715927bd2bb78027a5e42d0dc0c78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6791.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "e73dfe8ed1491ce2dada8ea70215229bdfc0c6eb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/visualization/plot_montage.py": { + "a": 12, + "d": 28 + }, + "mne/_digitization/_utils.py": { + "a": 4, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 58, + "d": 36 + }, + "mne/channels/montage.py": { + "a": 6, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 36, + "d": 11 + }, + "mne/data/coil_def.dat": { + "a": 7, + "d": 7 + }, + "mne/datasets/limo/limo.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 7 + }, + "mne/io/tests/test_meas_info.py": { + "a": 5, + "d": 2 + }, + "mne/transforms.py": { + "a": 3, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 18, + "d": 32 + }, + "setup.cfg": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_eeg_no_mri.py": { + "a": 14, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6793.json b/mne-python/source/doc/sphinxext/prs/6793.json new file mode 100644 index 0000000000000000000000000000000000000000..43be2fca44578e263012e74f7242b0e4109be8ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6793.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "5cd3000a6713c10361478b1b1293f687ee2781b9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_receptive_field_mtrf.py": { + "a": 2, + "d": 3 + }, + "examples/visualization/plot_3d_to_2d.py": { + "a": 6, + "d": 1 + }, + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 16, + "d": 4 + }, + "mne/channels/montage.py": { + "a": 6, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 3, + "d": 5 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 6 + }, + "tutorials/misc/plot_ecog.py": { + "a": 6, + "d": 1 + }, + "tutorials/misc/plot_sensor_locations.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 17, + "d": 1 + }, + "tutorials/source-modeling/plot_eeg_no_mri.py": { + "a": 17, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6797.json b/mne-python/source/doc/sphinxext/prs/6797.json new file mode 100644 index 0000000000000000000000000000000000000000..ea2c6c639d7a963d3f685879995e6ef1d55ab845 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6797.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "05d7eea578dbb8533dbaf34451fd6b92a80c0eb9", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 0, + "d": 7 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 27, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6798.json b/mne-python/source/doc/sphinxext/prs/6798.json new file mode 100644 index 0000000000000000000000000000000000000000..555f012fc3113c606f6504b5f708d20c5b1d150b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6798.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "42380c2d633c50b03c6c51d84a5db822a2fb9261", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_limo_data.py": { + "a": 1, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 6, + "d": 5 + }, + "mne/channels/montage.py": { + "a": 7, + "d": 1 + }, + "mne/datasets/limo/limo.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6799.json b/mne-python/source/doc/sphinxext/prs/6799.json new file mode 100644 index 0000000000000000000000000000000000000000..2155a22447889067c1c645866b65b2b2772a4cdc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6799.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9bb4bf21f8284ed7074ebc5f75f673a077f7e7b1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/68.json b/mne-python/source/doc/sphinxext/prs/68.json new file mode 100644 index 0000000000000000000000000000000000000000..da934d175a73766877cddf570cfaf645878d5639 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/68.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "5eda6a5b832cb9bedcc25bbf0b75c19d19685f16", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 0 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 85, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/label.py": { + "a": 147, + "d": 1 + }, + "mne/simulation/__init__.py": { + "a": 6, + "d": 0 + }, + "mne/simulation/evoked.py": { + "a": 125, + "d": 0 + }, + "mne/simulation/source.py": { + "a": 178, + "d": 0 + }, + "mne/simulation/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/simulation/tests/test_source.py": { + "a": 70, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 30, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 16, + "d": 1 + }, + "mne/time_frequency/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/ar.py": { + "a": 30, + "d": 0 + }, + "mne/utils.py": { + "a": 18, + "d": 0 + }, + "mne/viz.py": { + "a": 155, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6800.json b/mne-python/source/doc/sphinxext/prs/6800.json new file mode 100644 index 0000000000000000000000000000000000000000..b11128659683fe52f467c9378c784553676d488b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6800.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7c02660735181abc992662fcbd82c4b6f28f4775", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 0 + }, + "mne/channels/data/neighbors/KIT-NYU-2019_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 9, + "d": 2 + }, + "mne/io/kit/constants.py": { + "a": 21, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6804.json b/mne-python/source/doc/sphinxext/prs/6804.json new file mode 100644 index 0000000000000000000000000000000000000000..d3886efb063455f77830c266e63eddcd925678e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6804.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d123ec6f3d3a6e011469f2c04adfcd631915a178", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 7, + "d": 2 + }, + "mne/io/pick.py": { + "a": 11, + "d": 8 + }, + "mne/tests/test_filter.py": { + "a": 36, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6805.json b/mne-python/source/doc/sphinxext/prs/6805.json new file mode 100644 index 0000000000000000000000000000000000000000..7b7987228a8b07f6c20d691e4c502a042a180dab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6805.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "80817108a43f152b5fa67bc94d25e3bdb675838e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 2, + "d": 5 + }, + "mne/minimum_norm/inverse.py": { + "a": 9, + "d": 5 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 12, + "d": 5 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6806.json b/mne-python/source/doc/sphinxext/prs/6806.json new file mode 100644 index 0000000000000000000000000000000000000000..ffd5c782397d8d86a57f54764fe0c54531c1be78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6806.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1b25e8485609627abd39e31a4f1e396315211392", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6808.json b/mne-python/source/doc/sphinxext/prs/6808.json new file mode 100644 index 0000000000000000000000000000000000000000..e047c6281c2a4acecfb618553d961818de9b4b4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6808.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "007a7c0c2790f3bbaa301adf6f99fde90f67812a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6809.json b/mne-python/source/doc/sphinxext/prs/6809.json new file mode 100644 index 0000000000000000000000000000000000000000..531a6fd001aae9dbd48d96acbb3aa47a77d602df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6809.json @@ -0,0 +1,147 @@ +{ + "merge_commit_sha": "b0ea04b4217d4945c13525e81607a9061d7768dc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 6, + "d": 4 + }, + "doc/_images/CoordinateSystems.png": { + "a": 0, + "d": 0 + }, + "doc/_images/HeadCS.png": { + "a": 0, + "d": 0 + }, + "doc/_includes/bem_model.rst": { + "a": 166, + "d": 0 + }, + "doc/_includes/channel_interpolation.rst": { + "a": 18, + "d": 10 + }, + "doc/_includes/data_formats.rst": { + "a": 29, + "d": 36 + }, + "doc/_includes/forward.rst": { + "a": 164, + "d": 235 + }, + "doc/_includes/inverse.rst": { + "a": 29, + "d": 27 + }, + "doc/_includes/memory.rst": { + "a": 68, + "d": 0 + }, + "doc/_includes/morph.rst": { + "a": 18, + "d": 10 + }, + "doc/_includes/ssp.rst": { + "a": 17, + "d": 8 + }, + "doc/conf.py": { + "a": 6, + "d": 0 + }, + "doc/overview/algorithms/bem_model.rst": { + "a": 0, + "d": 205 + }, + "doc/overview/algorithms/maxwell.rst": { + "a": 0, + "d": 76 + }, + "doc/overview/algorithms/memory.rst": { + "a": 0, + "d": 53 + }, + "doc/overview/algorithms/time_frequency.rst": { + "a": 0, + "d": 30 + }, + "doc/overview/command_line.rst": { + "a": 0, + "d": 114 + }, + "doc/overview/cookbook.rst": { + "a": 2, + "d": 2 + }, + "doc/overview/implementation.rst": { + "a": 85, + "d": 16 + }, + "doc/overview/matlab.rst": { + "a": 2, + "d": 3 + }, + "mne/bem.py": { + "a": 16, + "d": 16 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 8, + "d": 6 + }, + "tutorials/intro/README.txt": { + "a": 2, + "d": 2 + }, + "tutorials/intro/plot_40_sensor_locations.py": { + "a": 2, + "d": 0 + }, + "tutorials/io/README.txt": { + "a": 7, + "d": 0 + }, + "tutorials/io/plot_10_reading_meg_data.py": { + "a": 294, + "d": 0 + }, + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 189, + "d": 0 + }, + "tutorials/preprocessing/plot_15_handling_bad_channels.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_45_projectors_background.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 28, + "d": 1 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/sample-datasets/plot_brainstorm_auditory.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6811.json b/mne-python/source/doc/sphinxext/prs/6811.json new file mode 100644 index 0000000000000000000000000000000000000000..158248a372d6d9c84d88e3167a093da49d99ecb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6811.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c019da4859be286999752d417b45859760a61388", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 18, + "d": 20 + }, + "mne/channels/tests/test_montage.py": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6812.json b/mne-python/source/doc/sphinxext/prs/6812.json new file mode 100644 index 0000000000000000000000000000000000000000..2e36fe10e2325e8b2e0e84ef527b9157589e7612 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6812.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "50657ba05301bcf1230d5034a2ed76ccaaf52352", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 13, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6815.json b/mne-python/source/doc/sphinxext/prs/6815.json new file mode 100644 index 0000000000000000000000000000000000000000..519d68c168afa18d8d74393ecca49ca1858e40dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6815.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dcada0c29b9de284d5b2fd323e8aa1d04929d1a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/tests/test_make_forward.py": { + "a": 18, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6817.json b/mne-python/source/doc/sphinxext/prs/6817.json new file mode 100644 index 0000000000000000000000000000000000000000..58777837645c910ac65b38574be8e359b88c7a9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6817.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3247bd1f7aafb120a20c70dd0b348c396bb74cc5", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + "doc/_templates/navbar.html": { + "a": 2, + "d": 1 + }, + "doc/changes/0.19.inc": { + "a": 3, + "d": 3 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6818.json b/mne-python/source/doc/sphinxext/prs/6818.json new file mode 100644 index 0000000000000000000000000000000000000000..b30d232ec01e0cf7443e3db6c890d23bbbab6059 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6818.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6e332b112da0fe2b155c481c746adeeb82e3fda2", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 23, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6819.json b/mne-python/source/doc/sphinxext/prs/6819.json new file mode 100644 index 0000000000000000000000000000000000000000..700474c2d2281325c0ff41d38bd72b96da1ab39f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6819.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5561394ca585b27dd7b276f85fd1584657667f5b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_import_nesting.py": { + "a": 15, + "d": 21 + }, + "mne/utils/misc.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/682.json b/mne-python/source/doc/sphinxext/prs/682.json new file mode 100644 index 0000000000000000000000000000000000000000..aade8b3100db7f5b3160e0a20457b54d720bf828 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/682.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9590d8c5b92d0725fdb2f307d3e47aeaac075bff", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 16, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6821.json b/mne-python/source/doc/sphinxext/prs/6821.json new file mode 100644 index 0000000000000000000000000000000000000000..549e2588e63b47d34727cec722463ac3a9897e2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6821.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5e1662522fd7481c6e76addded6c337f9b406364", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 5, + "d": 41 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 1, + "d": 2 + }, + "mne/io/utils.py": { + "a": 0, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6822.json b/mne-python/source/doc/sphinxext/prs/6822.json new file mode 100644 index 0000000000000000000000000000000000000000..c02cb88f501c3dc8d7955b288fcbf9e8459b15ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6822.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5a623c7da096017c8fe27e7f357671e19ae5e66d", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/_templates/navbar.html": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6823.json b/mne-python/source/doc/sphinxext/prs/6823.json new file mode 100644 index 0000000000000000000000000000000000000000..a0c9d6fd1db04a82286f41784036d8154362509c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6823.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "8a4cef803db165e2f8a00ad0f304ab60a79bc6f3", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "doc/changes/0.13.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.14.inc": { + "a": 6, + "d": 6 + }, + "doc/changes/0.15.inc": { + "a": 6, + "d": 6 + }, + "doc/changes/0.17.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.19.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 0, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 3 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 4, + "d": 102 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 13 + }, + "mne/channels/montage.py": { + "a": 76, + "d": 975 + }, + "mne/channels/tests/test_montage.py": { + "a": 52, + "d": 650 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 3, + "d": 9 + }, + "mne/io/brainvision/brainvision.py": { + "a": 11, + "d": 17 + }, + "mne/io/cnt/cnt.py": { + "a": 13, + "d": 23 + }, + "mne/io/edf/edf.py": { + "a": 10, + "d": 22 + }, + "mne/io/eeglab/eeglab.py": { + "a": 11, + "d": 34 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 5, + "d": 8 + }, + "mne/io/egi/egi.py": { + "a": 5, + "d": 8 + }, + "mne/io/egi/egimff.py": { + "a": 4, + "d": 7 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 18 + }, + "mne/io/nicolet/nicolet.py": { + "a": 3, + "d": 11 + }, + "mne/io/tests/test_meas_info.py": { + "a": 0, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + }, + "mne/viz/montage.py": { + "a": 12, + "d": 31 + }, + "mne/viz/tests/test_montage.py": { + "a": 10, + "d": 6 + }, + "tutorials/intro/plot_40_sensor_locations.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6825.json b/mne-python/source/doc/sphinxext/prs/6825.json new file mode 100644 index 0000000000000000000000000000000000000000..824a1515600eb693147ecad6a963aa997ef6c5d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6825.json @@ -0,0 +1,155 @@ +{ + "merge_commit_sha": "222deb6f5e97036274b9ac117582c20bee18d13a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.12.inc": { + "a": 1, + "d": 1 + }, + "examples/simulation/plot_simulate_raw_data.py": { + "a": 1, + "d": 2 + }, + "examples/simulation/plot_simulated_raw_data_using_subject_anatomy.py": { + "a": 1, + "d": 2 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 9 + }, + "mne/evoked.py": { + "a": 1, + "d": 41 + }, + "mne/forward/forward.py": { + "a": 7, + "d": 19 + }, + "mne/forward/tests/test_forward.py": { + "a": 1, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 9 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 2 + }, + "mne/io/base.py": { + "a": 1, + "d": 80 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 11 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 9, + "d": 10 + }, + "mne/morph.py": { + "a": 1, + "d": 72 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 7 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 9 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 2, + "d": 2 + }, + "mne/rank.py": { + "a": 5, + "d": 14 + }, + "mne/simulation/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 31 + }, + "mne/simulation/raw.py": { + "a": 12, + "d": 100 + }, + "mne/simulation/tests/test_raw.py": { + "a": 41, + "d": 119 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 11 + }, + "mne/tests/test_rank.py": { + "a": 0, + "d": 4 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 2, + "d": 20 + }, + "mne/utils/config.py": { + "a": 0, + "d": 6 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 28 + }, + "mne/utils/tests/test_numerics.py": { + "a": 1, + "d": 17 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 23 + }, + "mne/viz/evoked.py": { + "a": 5, + "d": 26 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 10 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 4 + }, + "mne/viz/tests/test_evoked.py": { + "a": 0, + "d": 5 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6826.json b/mne-python/source/doc/sphinxext/prs/6826.json new file mode 100644 index 0000000000000000000000000000000000000000..d9d075f278572e988b1d1f9c3bb426afe951c487 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6826.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e154730cfe3dc65cc0715634f8e814ecd3015baa", + "authors": [ + { + "n": "Joan Massich", + "e": "mailsik@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 5, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6827.json b/mne-python/source/doc/sphinxext/prs/6827.json new file mode 100644 index 0000000000000000000000000000000000000000..478aa988ff7b0bd48254000ba60d380c22fa43aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6827.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "978437d1b0eadf54c5b36d8223fb56a8c4e54881", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/defaults.py": { + "a": 8, + "d": 5 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_optical_density.py": { + "a": 47, + "d": 0 + }, + "mne/preprocessing/tests/test_optical_density.py": { + "a": 59, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/683.json b/mne-python/source/doc/sphinxext/prs/683.json new file mode 100644 index 0000000000000000000000000000000000000000..7147f292d810b4de565eefaab9e4e03aebe61b21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/683.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ecc77d892f309b812daaafc1e2c6ec1a88ddc11d", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "mne/preprocessing/stim.py": { + "a": 9, + "d": 6 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 46, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6830.json b/mne-python/source/doc/sphinxext/prs/6830.json new file mode 100644 index 0000000000000000000000000000000000000000..98e6f1dc5b682f0d64156d18d644f495b22ed30a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6830.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b822c1c9a1925e57dab04cab0ab5dfdf1766ed06", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.15.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.18.inc": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 58 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 0, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6831.json b/mne-python/source/doc/sphinxext/prs/6831.json new file mode 100644 index 0000000000000000000000000000000000000000..4b06de9c5832f7763fdf3c252474ae7f9173d634 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6831.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7ae8e611f8722554f0c93b1314233604ae787914", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 6, + "d": 1 + }, + "doc/contributing.html": { + "a": 9, + "d": 0 + }, + "doc/documentation.html": { + "a": 9, + "d": 0 + }, + "doc/getting_started.html": { + "a": 9, + "d": 0 + }, + "doc/install_mne_python.html": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6835.json b/mne-python/source/doc/sphinxext/prs/6835.json new file mode 100644 index 0000000000000000000000000000000000000000..45a9335f4c74a1158462fe2ab83915ac2b9f23f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6835.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "3fd31bb969a0073e26463682c1fafd7dad62a2cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "mne/event.py": { + "a": 39, + "d": 24 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 2, + "d": 2 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/data/fsaverage-fiducials.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_raw-annot.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_show_fiff.py": { + "a": 29, + "d": 0 + }, + "mne/tests/test_event.py": { + "a": 50, + "d": 24 + }, + "mne/utils/tests/test_testing.py": { + "a": 0, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6838.json b/mne-python/source/doc/sphinxext/prs/6838.json new file mode 100644 index 0000000000000000000000000000000000000000..1cf4d751ce65b1f203abe0e346a9540c92be752d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6838.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "713de842ffc17be20f0d6de67b2bd6e1fd4020b5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 2, + "d": 3 + }, + "mne/source_space.py": { + "a": 17, + "d": 6 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6848.json b/mne-python/source/doc/sphinxext/prs/6848.json new file mode 100644 index 0000000000000000000000000000000000000000..c90e3f949fc0e9850dfaeecd84807acf7010c015 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6848.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9a65a1bd5a9cec2cf5fc0a016db6d4d16e53ef3b", + "authors": [ + { + "n": "Kaisu Lankinen", + "e": null + } + ], + "changes": { + "mne/source_space.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6849.json b/mne-python/source/doc/sphinxext/prs/6849.json new file mode 100644 index 0000000000000000000000000000000000000000..2dbf14457da008bf031c4ff9ca8e41966f82881d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6849.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "08d699e15f891c39f2a145801dc1eb54caf1c16b", + "authors": [ + { + "n": "Padma Sundaram", + "e": "tottochan@gmail.com" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6852.json b/mne-python/source/doc/sphinxext/prs/6852.json new file mode 100644 index 0000000000000000000000000000000000000000..110add349a1e2197123b89033e659048de8be98f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6852.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9afcbcb21ca5df53eaf26911d0199dcc04bfc4ba", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 12, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6855.json b/mne-python/source/doc/sphinxext/prs/6855.json new file mode 100644 index 0000000000000000000000000000000000000000..20abde3cae5da17dbf0d34a258088a2ca38bbf3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6855.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b42a91c6771ae85c3307d3ce945d5e0be1bb250a", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 40, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6856.json b/mne-python/source/doc/sphinxext/prs/6856.json new file mode 100644 index 0000000000000000000000000000000000000000..4ff9f5add1f201340b6d276539593197067694dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6856.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "03b58ad2e90fa6c609289c2ae49ba6cba06279eb", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 3 + }, + "mne/coreg.py": { + "a": 5, + "d": 1 + }, + "mne/defaults.py": { + "a": 2, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 31, + "d": 7 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 61, + "d": 39 + }, + "mne/viz/_3d.py": { + "a": 24, + "d": 20 + }, + "mne/viz/tests/test_3d.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6857.json b/mne-python/source/doc/sphinxext/prs/6857.json new file mode 100644 index 0000000000000000000000000000000000000000..a7dd5d3d665e31418cbbe8d0a976ac815a571899 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6857.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "36eaa1c9aca28efce74df449140e932177cf37f4", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 8, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6859.json b/mne-python/source/doc/sphinxext/prs/6859.json new file mode 100644 index 0000000000000000000000000000000000000000..5fe6d116be1d021349a06b8e3674a8c87648d474 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6859.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "301f194e709d45065a24293b0786b3c2d821d2cf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 12, + "d": 7 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 15, + "d": 15 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 4, + "d": 7 + }, + "mne/datasets/_fsaverage/bem.txt": { + "a": 1, + "d": 0 + }, + "mne/morph.py": { + "a": 179, + "d": 101 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 5 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 31, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6863.json b/mne-python/source/doc/sphinxext/prs/6863.json new file mode 100644 index 0000000000000000000000000000000000000000..31cef4fb06b0aedc8c9bf2e709df4c4b87350d24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6863.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8902d8b9b0d795059779eb4145932ef341177297", + "authors": [ + { + "n": "Adonay Nunes", + "e": "adonay.s.nunes@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 2, + "d": 2 + }, + "mne/connectivity/spectral.py": { + "a": 48, + "d": 11 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6864.json b/mne-python/source/doc/sphinxext/prs/6864.json new file mode 100644 index 0000000000000000000000000000000000000000..28b35968165fca30f1ab070ed2e0e89461bbd4f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6864.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ba5c83e55776fabe306f2a702a56f8b7391fb5bc", + "authors": [ + { + "n": "Nataliia Kozhemiako", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6865.json b/mne-python/source/doc/sphinxext/prs/6865.json new file mode 100644 index 0000000000000000000000000000000000000000..ae029031ffdb25fcb8f31e9831028cb81e33f096 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6865.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b5ac3014096e323053a7a155153dd09cf3d30b29", + "authors": [ + { + "n": "Kaisu Lankinen", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6866.json b/mne-python/source/doc/sphinxext/prs/6866.json new file mode 100644 index 0000000000000000000000000000000000000000..9734732a4a9fbedd18e2f87b34a45b13f18a69b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6866.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "81ab01de410f7de45d08c21f564571a3c28f8863", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6867.json b/mne-python/source/doc/sphinxext/prs/6867.json new file mode 100644 index 0000000000000000000000000000000000000000..86c1798651bffe0c7026db295f4381a22eb9655b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6867.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "edaef78a9a8909decee02486cf7b9585117a7ab1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 3 + }, + "examples/datasets/plot_opm_data.py": { + "a": 2, + "d": 1 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 4, + "d": 2 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/687.json b/mne-python/source/doc/sphinxext/prs/687.json new file mode 100644 index 0000000000000000000000000000000000000000..892be9599a2114ee4b8a7cf81967d7a834b1505f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/687.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e4137fec06a78751cd39036e817c5f0d0d80074d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6871.json b/mne-python/source/doc/sphinxext/prs/6871.json new file mode 100644 index 0000000000000000000000000000000000000000..2339d0aa78ca7e6f77b60949dab9e6245160e6db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6871.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1e9b065b91d70d401b49c1b1a5a16767e00d9592", + "authors": [ + { + "n": "Fahimeh Mamashli", + "e": "fahimeh.mamashli@pfizer.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 3 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 30, + "d": 12 + }, + "mne/tests/test_epochs.py": { + "a": 50, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6872.json b/mne-python/source/doc/sphinxext/prs/6872.json new file mode 100644 index 0000000000000000000000000000000000000000..07911f34e0eb15cd0d168f209c959dbb59175ade --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6872.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e78ac34a81216ad3bcccfcfa1ea991dc7c8bfdc3", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_30_filtering_resampling.py": { + "a": 229, + "d": 91 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6873.json b/mne-python/source/doc/sphinxext/prs/6873.json new file mode 100644 index 0000000000000000000000000000000000000000..7a7ab4047f664d001816a0b70e4af2e20a36e7c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6873.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "18bd6eeca4a00a4956fb72e755cb1213566fad2c", + "authors": [ + { + "n": "Mohammad Daneshzand", + "e": "mdaneshz@my.bridgeport.edu" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 16, + "d": 11 + }, + "mne/utils/tests/test_numerics.py": { + "a": 2, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6874.json b/mne-python/source/doc/sphinxext/prs/6874.json new file mode 100644 index 0000000000000000000000000000000000000000..3784489670e216246a301260f7e92fb7ce1ab398 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6874.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cfab03350b00f4b0e129ce83dfb70ed73554b8e0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 0, + "d": 2 + }, + "tutorials/discussions/plot_background_filtering.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6875.json b/mne-python/source/doc/sphinxext/prs/6875.json new file mode 100644 index 0000000000000000000000000000000000000000..8937a5a1d6d13c7c8f9873e4d2e9353b80d6e636 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6875.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "70bf11cfce28ee3d989e4842939a7ca3c8b51ab6", + "authors": [ + { + "n": "Mohamed Sherif", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6876.json b/mne-python/source/doc/sphinxext/prs/6876.json new file mode 100644 index 0000000000000000000000000000000000000000..bf903342ca2ed6b36bec75e15d4048bb8e4b43c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6876.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9400438ffdced3f639bccb4c46dac4fab1f78cef", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/0.19.inc": { + "a": 11, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 30, + "d": 12 + }, + "mne/tests/test_epochs.py": { + "a": 50, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6877.json b/mne-python/source/doc/sphinxext/prs/6877.json new file mode 100644 index 0000000000000000000000000000000000000000..632fef2653675e6c551e94bbe18e42112f7bd6a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6877.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "63522e48f0420081b5698591f0062c86ff4bcd38", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 3, + "d": 2 + }, + "examples/inverse/plot_mne_crosstalk_function.py": { + "a": 0, + "d": 67 + }, + "examples/inverse/plot_mne_point_spread_function.py": { + "a": 0, + "d": 82 + }, + "examples/inverse/plot_psf_ctf_vertices.py": { + "a": 97, + "d": 0 + }, + "mne/minimum_norm/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 5, + "d": 1 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 284, + "d": 0 + }, + "mne/minimum_norm/tests/test_psf_ctf.py": { + "a": 10, + "d": 8 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 124, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6878.json b/mne-python/source/doc/sphinxext/prs/6878.json new file mode 100644 index 0000000000000000000000000000000000000000..60d2be91a5df2fbbb81257cb5d81f4531315236a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6878.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "474e1abc737d40d3c0a42a4362755b12321d3094", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6879.json b/mne-python/source/doc/sphinxext/prs/6879.json new file mode 100644 index 0000000000000000000000000000000000000000..49f132390c1c7f6383dec1f9bcfec76956f37f1e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6879.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e1b44fa5a2fc80f52d6d19a5d7c239ec4a09a8bc", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/688.json b/mne-python/source/doc/sphinxext/prs/688.json new file mode 100644 index 0000000000000000000000000000000000000000..f816e6c545dd1ac09916b0afd39f97707d3a7e93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/688.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5728b7a205a683851b87148dede318c5282b33f1", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/contributing.rst": { + "a": 124, + "d": 3 + }, + "doc/source/git_links.inc": { + "a": 27, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6880.json b/mne-python/source/doc/sphinxext/prs/6880.json new file mode 100644 index 0000000000000000000000000000000000000000..450a404f629b0621de640ac47666049cd0121218 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6880.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d2e5b55c91bde5a0627cdd7ac2895c948cea39a4", + "authors": [ + { + "n": "Mohamed Sherif", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6881.json b/mne-python/source/doc/sphinxext/prs/6881.json new file mode 100644 index 0000000000000000000000000000000000000000..41f10e441739abc4096006c6aef4cf88beadbaf7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6881.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "311317b2fdf2c87b124c72032122914611daaede", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6882.json b/mne-python/source/doc/sphinxext/prs/6882.json new file mode 100644 index 0000000000000000000000000000000000000000..4163daee4ae34be66b2b1e277cd290af5879f664 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6882.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3a26fade683b6582e9c0693f9eb728260e266f58", + "authors": [ + { + "n": "Robert Oostenveld", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_30_filtering_resampling.py": { + "a": 44, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6883.json b/mne-python/source/doc/sphinxext/prs/6883.json new file mode 100644 index 0000000000000000000000000000000000000000..70384970cce5486402c84409c6759b0c0cb0d493 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6883.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a81a5f85507a8874ce2b59e9b3673e4155aa57aa", + "authors": [ + { + "n": "Nataliia Kozhemiako", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 18, + "d": 4 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_head_positions.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6885.json b/mne-python/source/doc/sphinxext/prs/6885.json new file mode 100644 index 0000000000000000000000000000000000000000..3bb3ab2b5f222f379e7134d74c717f3e484b1a56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6885.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f59d54ef3632fa7bde410d8550a6276b4311895b", + "authors": [ + { + "n": "Fahimeh Mamashli", + "e": "fahimeh.mamashli@pfizer.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6887.json b/mne-python/source/doc/sphinxext/prs/6887.json new file mode 100644 index 0000000000000000000000000000000000000000..2e03f6c47f8ee9161417094f58151598ee415e30 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6887.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9de684d70e489d8a66f2e33c2c5af0170b766fda", + "authors": [ + { + "n": "Fahimeh Mamashli", + "e": "fahimeh.mamashli@pfizer.com" + } + ], + "changes": { + "mne/transforms.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6889.json b/mne-python/source/doc/sphinxext/prs/6889.json new file mode 100644 index 0000000000000000000000000000000000000000..3efe99cef3d5d81e60671cd0fe82da2f791707d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6889.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a7664c58674412cf4e842960581406533edcc615", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 12, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6892.json b/mne-python/source/doc/sphinxext/prs/6892.json new file mode 100644 index 0000000000000000000000000000000000000000..46c0e7c3e66743b47f345eb0120f7c68f94c09ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6892.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e07cc5059cb6e2fb7e5abe0ed3db0fad7f590959", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 6 + }, + "mne/commands/mne_anonymize.py": { + "a": 99, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 13, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 117, + "d": 12 + }, + "mne/io/tests/test_meas_info.py": { + "a": 93, + "d": 65 + }, + "mne/tests/test_report.py": { + "a": 18, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6894.json b/mne-python/source/doc/sphinxext/prs/6894.json new file mode 100644 index 0000000000000000000000000000000000000000..400c64b0ae04eda341ad41450435b6e152def641 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6894.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "e86d78d3f1c6c530e7b3fdae03caeb56cf127b05", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 45, + "d": 13 + }, + "mne/channels/tests/test_montage.py": { + "a": 6, + "d": 3 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/_digitization.py": { + "a": 8, + "d": 5 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/transforms.py": { + "a": 18, + "d": 6 + }, + "mne/utils/check.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 11 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_eeg_mri_coords.py": { + "a": 156, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6895.json b/mne-python/source/doc/sphinxext/prs/6895.json new file mode 100644 index 0000000000000000000000000000000000000000..51ef9600d796f93ce616e8cfe34eca680dc561ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6895.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5e52983a22a5e1727f01d4b1240c111dc09a7ff0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/preprocessing/plot_45_projectors_background.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6896.json b/mne-python/source/doc/sphinxext/prs/6896.json new file mode 100644 index 0000000000000000000000000000000000000000..d68468ce1cc2de65ebdaad2ca712b0eac53528c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6896.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1fec322892911ba3a3175df378fbdc7458612845", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 5, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6897.json b/mne-python/source/doc/sphinxext/prs/6897.json new file mode 100644 index 0000000000000000000000000000000000000000..1bb6ab386ef1d9c769d7d6bbcc2efddc1ab4145b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6897.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2c2488c172f6fbcc653cb38317a9bca5e1ddb867", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 5, + "d": 4 + }, + "mne/io/brainvision/tests/data/test.hpts": { + "a": 3, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6899.json b/mne-python/source/doc/sphinxext/prs/6899.json new file mode 100644 index 0000000000000000000000000000000000000000..092e4808337f5f02111e8c1b9f2b9dd2379287b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6899.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0b20f152d0fdcb1c6217c60f06e9ba087d291fa8", + "authors": [ + { + "n": "Nicolas Legrand", + "e": "nicolas.legrand@cas.au.dk" + } + ], + "changes": { + "tutorials/misc/plot_modifying_data_inplace.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/69.json b/mne-python/source/doc/sphinxext/prs/69.json new file mode 100644 index 0000000000000000000000000000000000000000..8f16e0cc458ebc1b9826dc6789c26e4f2a44ad36 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/69.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "edfe5063a9fb366d37af37d302822d637f86ab6d", + "authors": [ + { + "n": "Daniel Strohmeier", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 85, + "d": 10 + }, + "mne/tests/test_epochs.py": { + "a": 57, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/690.json b/mne-python/source/doc/sphinxext/prs/690.json new file mode 100644 index 0000000000000000000000000000000000000000..aa5152a32bb3dfa94f4137db0eb1204bed2ea715 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/690.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5ef1710b5074aef193983e21d31224ac07e45f11", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/decoding/plot_decoding_csp_space.py": { + "a": 2, + "d": 3 + }, + "mne/decoding/csp.py": { + "a": 12, + "d": 14 + }, + "mne/decoding/tests/test_csp.py": { + "a": 19, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6900.json b/mne-python/source/doc/sphinxext/prs/6900.json new file mode 100644 index 0000000000000000000000000000000000000000..77bca536d57b5ef08b2c6964ff4ba485ad9cf9f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6900.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "52498f95e1c56ba67e893eb974c07c2b3f755d78", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 27, + "d": 30 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6902.json b/mne-python/source/doc/sphinxext/prs/6902.json new file mode 100644 index 0000000000000000000000000000000000000000..c70617d0bf5db39f165c34af104d8105054def85 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6902.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ab7176a0fc1a9d7b81791ccb9d69f8a29ad3be8e", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 11, + "d": 13 + }, + "mne/channels/tests/test_layout.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6903.json b/mne-python/source/doc/sphinxext/prs/6903.json new file mode 100644 index 0000000000000000000000000000000000000000..f9153cc1c5bbb58468792a0eb976cde5eee38b38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6903.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "32156db6c0819617791c23e389c3c088cfbe6f68", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_digitization/__init__.py": { + "a": 0, + "d": 5 + }, + "mne/_digitization/base.py": { + "a": 0, + "d": 124 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 3, + "d": 4 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 1, + "d": 2 + }, + "mne/io/_digitization.py": { + "a": 127, + "d": 24 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 3 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 2 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 10 + }, + "mne/io/tests/test_digitization.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/montage.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6904.json b/mne-python/source/doc/sphinxext/prs/6904.json new file mode 100644 index 0000000000000000000000000000000000000000..fadc7d781d9e53770cc0d7dd39eb95389fb5a087 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6904.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "050e3f84efc2be7dafaf65408f6b3152d41938ec", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/io/proj.py": { + "a": 14, + "d": 27 + }, + "mne/utils/docs.py": { + "a": 55, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 17, + "d": 67 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 2, + "d": 2 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6906.json b/mne-python/source/doc/sphinxext/prs/6906.json new file mode 100644 index 0000000000000000000000000000000000000000..167651fb254d5f9ff51105fcdbee7e834e2c236b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6906.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "359e3410dd5e61829433b3c41f102332973e96fe", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_resolution_metrics.py": { + "a": 124, + "d": 0 + }, + "examples/inverse/plot_resolution_metrics_eegmeg.py": { + "a": 134, + "d": 0 + }, + "mne/minimum_norm/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 334, + "d": 0 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 159, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6907.json b/mne-python/source/doc/sphinxext/prs/6907.json new file mode 100644 index 0000000000000000000000000000000000000000..45bf95c21333d1cdd02af6fb9207f55de41bfd5b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6907.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "0563399e20c9643a98fb909aba9647bc90f4c49f", + "authors": [ + { + "n": "Adonay Nunes", + "e": "adonay.s.nunes@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 14, + "d": 5 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 10, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 16, + "d": 9 + }, + "mne/utils/check.py": { + "a": 15, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6908.json b/mne-python/source/doc/sphinxext/prs/6908.json new file mode 100644 index 0000000000000000000000000000000000000000..0db117d5266ee61744325c0a97a7a892e807731c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6908.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "341a078160db624bc86a9c3be26ae3e1f1adbb4a", + "authors": [ + { + "n": "Kaisu Lankinen", + "e": null + } + ], + "changes": { + "examples/inverse/plot_source_space_snr.py": { + "a": 100, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 71, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6909.json b/mne-python/source/doc/sphinxext/prs/6909.json new file mode 100644 index 0000000000000000000000000000000000000000..10dbde08c4ed9ec560a7f39a79b952ac2d76a950 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6909.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "194d4eda74621b9a2d9a8e3e89f4e12a07c74996", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/_includes/dig_formats.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 5, + "d": 5 + }, + "mne/channels/montage.py": { + "a": 74, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 43, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 15, + "d": 8 + }, + "tutorials/intro/plot_40_sensor_locations.py": { + "a": 2, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/691.json b/mne-python/source/doc/sphinxext/prs/691.json new file mode 100644 index 0000000000000000000000000000000000000000..32f0574c7c13d690b09b61a0f57bbd70428f3ea7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/691.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d0aeec4b8d8fb0795b527b0306c51d2cd94775ed", + "authors": [ + { + "n": "Romain Trachel", + "e": "trachelr@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_decoding_csp_space.py": { + "a": 6, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 62, + "d": 8 + }, + "mne/decoding/tests/test_csp.py": { + "a": 29, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6910.json b/mne-python/source/doc/sphinxext/prs/6910.json new file mode 100644 index 0000000000000000000000000000000000000000..691a2b2b498f6dd21e36c9196c1a7e42640c39ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6910.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "3fafe437413f29b91f36ca2726a4cceb87dfbab7", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/preprocessing/plot_eeg_csd.py": { + "a": 96, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 4 + }, + "mne/channels/interpolation.py": { + "a": 23, + "d": 3 + }, + "mne/cov.py": { + "a": 7, + "d": 3 + }, + "mne/defaults.py": { + "a": 7, + "d": 6 + }, + "mne/io/ctf/info.py": { + "a": 2, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 4, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/pick.py": { + "a": 23, + "d": 14 + }, + "mne/io/tests/test_pick.py": { + "a": 14, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_csd.py": { + "a": 189, + "d": 0 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 195, + "d": 0 + }, + "mne/report.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 0, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 13, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6911.json b/mne-python/source/doc/sphinxext/prs/6911.json new file mode 100644 index 0000000000000000000000000000000000000000..321595109196dd15d6b69ff2dbdf2db129bb6c71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6911.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "74ceb7dc4a4c71cd4749fc5af385d548eef57749", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/externals/jdcal.py": { + "a": 0, + "d": 116 + }, + "mne/io/tag.py": { + "a": 2, + "d": 2 + }, + "mne/io/write.py": { + "a": 2, + "d": 3 + }, + "mne/utils/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 96, + "d": 0 + }, + "mne/utils/tests/test_numerics.py": { + "a": 23, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6912.json b/mne-python/source/doc/sphinxext/prs/6912.json new file mode 100644 index 0000000000000000000000000000000000000000..46a1c81ce95531cb32106abc855dc594f16bacd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6912.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b8862d9d7549cdab9ed8d1e216f3bb8b268ac9e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 3, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/io/_digitization.py": { + "a": 1, + "d": 30 + }, + "mne/io/tests/test_digitization.py": { + "a": 0, + "d": 39 + }, + "mne/io/tests/test_raw.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6913.json b/mne-python/source/doc/sphinxext/prs/6913.json new file mode 100644 index 0000000000000000000000000000000000000000..bf2e20e94756f38ab63a957b0d9befa05af39d70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6913.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "98ebb2e1333a491d40550e48fe2955992af7370e", + "authors": [ + { + "n": "Kaisu Lankinen", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6914.json b/mne-python/source/doc/sphinxext/prs/6914.json new file mode 100644 index 0000000000000000000000000000000000000000..761f6cc549e1417ce91322a5271a7fd8b4a83994 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6914.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ec1058fc03a4c5e4fb472916159a96398fe7b8cb", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6915.json b/mne-python/source/doc/sphinxext/prs/6915.json new file mode 100644 index 0000000000000000000000000000000000000000..24abd2f2a8cb14d17063b7ea9db1445e6aee0416 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6915.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "610ec2a50d7a0e17d1ae8a229793a51370dec81d", + "authors": [ + { + "n": "Fahimeh Mamashli", + "e": "fahimeh.mamashli@pfizer.com" + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/tests.yml": { + "a": 2, + "d": 2 + }, + "doc/changes/devel/6915.newfeature.rst": { + "a": 1, + "d": 0 + }, + "examples/datasets/brainstorm_data.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/stim.py": { + "a": 56, + "d": 9 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 35, + "d": 0 + }, + "tools/install_pre_requirements.sh": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6916.json b/mne-python/source/doc/sphinxext/prs/6916.json new file mode 100644 index 0000000000000000000000000000000000000000..138d2bfbe62caa56e75ce676713fcaac0d5b811c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6916.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a41dd08b695d02ffdbf0f37119728e8b5e4d1f26", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6918.json b/mne-python/source/doc/sphinxext/prs/6918.json new file mode 100644 index 0000000000000000000000000000000000000000..c750b3e4d8eff96cd586fed497511d98f90e2f3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6918.json @@ -0,0 +1,211 @@ +{ + "merge_commit_sha": "e18950e9c8635997139c3cc4d940512a64dc5723", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 2, + "d": 2 + }, + "doc/changes/0.8.inc": { + "a": 1, + "d": 1 + }, + "doc/references.rst": { + "a": 2, + "d": 2 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 2, + "d": 2 + }, + "examples/io/plot_read_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 5, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/data/coil_def.dat": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 9, + "d": 6 + }, + "mne/forward/_field_interpolation.py": { + "a": 6, + "d": 0 + }, + "mne/forward/_lead_dots.py": { + "a": 5, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 5, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 5, + "d": 2 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 3 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 6, + "d": 6 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/_digitization.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/constants.py": { + "a": 2, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 2, + "d": 1 + }, + "mne/io/ctf/res4.py": { + "a": 2, + "d": 1 + }, + "mne/io/ctf_comp.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/matrix.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/open.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/tree.py": { + "a": 1, + "d": 1 + }, + "mne/io/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/selection.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 5, + "d": 2 + }, + "mne/surface.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/692.json b/mne-python/source/doc/sphinxext/prs/692.json new file mode 100644 index 0000000000000000000000000000000000000000..bb9d049cdd146daa9cb458e364c0991311fd6a93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/692.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "ab82e2ba16163fe83b26f3e332a3c9d3761cd138", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/realtime/rt_feedback_client.py": { + "a": 116, + "d": 0 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 143, + "d": 0 + }, + "mne/realtime/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/realtime/mockclient.py": { + "a": 78, + "d": 2 + }, + "mne/realtime/stim_server_client.py": { + "a": 262, + "d": 0 + }, + "mne/realtime/tests/test_mockclient.py": { + "a": 26, + "d": 7 + }, + "mne/realtime/tests/test_stim_client_server.py": { + "a": 46, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6920.json b/mne-python/source/doc/sphinxext/prs/6920.json new file mode 100644 index 0000000000000000000000000000000000000000..bed99f2474ad8625ea97f8c50e095bc94f59d454 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6920.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3c5770522827205e65ed401dddf4abc9e50d776a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/morph.py": { + "a": 25, + "d": 32 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6921.json b/mne-python/source/doc/sphinxext/prs/6921.json new file mode 100644 index 0000000000000000000000000000000000000000..a4228d3baab9889294f742caf19bca1506665f06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6921.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8fa427b8a5496115d9587fa6eaa82349c42bff69", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6922.json b/mne-python/source/doc/sphinxext/prs/6922.json new file mode 100644 index 0000000000000000000000000000000000000000..7f0e8629a59d6d38ff07facf87f9ff5b2c3555af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6922.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "249bdb60ffd68d325881282591a2e31485ef3455", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/proj.py": { + "a": 11, + "d": 59 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 4, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 94, + "d": 53 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6923.json b/mne-python/source/doc/sphinxext/prs/6923.json new file mode 100644 index 0000000000000000000000000000000000000000..30f428d281fdb3468d7ef59517fc6baa47e73217 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6923.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "475b55298715a2be04ad31c039e853456a3102a9", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 38, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6924.json b/mne-python/source/doc/sphinxext/prs/6924.json new file mode 100644 index 0000000000000000000000000000000000000000..c55cca862674460b01901533f42dc707bc0165a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6924.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "26a0d938a4a532615493718a3fbb689958ce2893", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 15, + "d": 12 + }, + "mne/coreg.py": { + "a": 6, + "d": 13 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 55, + "d": 93 + }, + "mne/tests/test_morph.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 11, + "d": 16 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 7, + "d": 26 + }, + "mne/viz/_3d.py": { + "a": 73, + "d": 69 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6925.json b/mne-python/source/doc/sphinxext/prs/6925.json new file mode 100644 index 0000000000000000000000000000000000000000..d9198920fd2cb0d7ac0225370e54a3e3e2c5a708 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6925.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1d4cc2749fccf4325ffd3e4efba594bcda5e5917", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/links.inc": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6926.json b/mne-python/source/doc/sphinxext/prs/6926.json new file mode 100644 index 0000000000000000000000000000000000000000..1c0cdf724576f857a39deb0e3995530f74ab1e6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6926.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8e770f1de183940552b3b5415b1cbcb577c43e6b", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/preprocessing/_optical_density.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/tests/test_optical_density.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6927.json b/mne-python/source/doc/sphinxext/prs/6927.json new file mode 100644 index 0000000000000000000000000000000000000000..d8a4cccf7b21cd3c59826b156dbf095fb91d93a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6927.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9d2fcbaf054fb168d56f8250a568afd3d9555d89", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 9, + "d": 7 + }, + "mne/tests/test_evoked.py": { + "a": 11, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6928.json b/mne-python/source/doc/sphinxext/prs/6928.json new file mode 100644 index 0000000000000000000000000000000000000000..1175f22d2e3173e03062e050097ee2c438c0cbcb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6928.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "a7db5f4924560344fa111b650dfbea5cd64c2452", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 4, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 3, + "d": 8 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 30, + "d": 13 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6930.json b/mne-python/source/doc/sphinxext/prs/6930.json new file mode 100644 index 0000000000000000000000000000000000000000..dc522b8a7e9e0914d9031052e0c6a1e32394052b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6930.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "852a44536bfbfe2f35e43729c07d060902787991", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6931.json b/mne-python/source/doc/sphinxext/prs/6931.json new file mode 100644 index 0000000000000000000000000000000000000000..51443ce7a57458e1759473829d9c3c467400c3e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6931.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "ee20e842efc6c950e0b93757b881c3fcf867c588", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_includes/channel_interpolation.rst": { + "a": 2, + "d": 4 + }, + "doc/_includes/forward.rst": { + "a": 11, + "d": 3 + }, + "doc/_includes/inverse.rst": { + "a": 4, + "d": 6 + }, + "doc/_static/style.css": { + "a": 3, + "d": 1 + }, + "doc/bibliography.rst": { + "a": 8, + "d": 0 + }, + "doc/conf.py": { + "a": 11, + "d": 1 + }, + "doc/overview/datasets_index.rst": { + "a": 23, + "d": 29 + }, + "doc/overview/faq.rst": { + "a": 10, + "d": 14 + }, + "doc/overview/implementation.rst": { + "a": 2, + "d": 10 + }, + "doc/overview/index.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 1663, + "d": 0 + }, + "doc/references.rst": { + "a": 24, + "d": 99 + }, + "mne/beamformer/_dics.py": { + "a": 24, + "d": 39 + }, + "mne/filter.py": { + "a": 6, + "d": 7 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/plot_45_projectors_background.py": { + "a": 3, + "d": 4 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 3, + "d": 4 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 7, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6933.json b/mne-python/source/doc/sphinxext/prs/6933.json new file mode 100644 index 0000000000000000000000000000000000000000..0911785fae1a0a56770243897b9defe35ba9b0ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6933.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cf005b93f60cd1f2aa1701e5069c892c9290c14c", + "authors": [ + { + "n": "Stefan Repplinger", + "e": "stefan.repplinger@posteo.net" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6934.json b/mne-python/source/doc/sphinxext/prs/6934.json new file mode 100644 index 0000000000000000000000000000000000000000..c50862f6f2951cec39cce1a49f4242a0d31a4d6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6934.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ac4abee16e1f106055437f5b7feaa99786831a6f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 17, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 6 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 0, + "d": 1 + }, + "tutorials/time-freq/plot_sensors_time_frequency.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6936.json b/mne-python/source/doc/sphinxext/prs/6936.json new file mode 100644 index 0000000000000000000000000000000000000000..47f19cfd76093ffa61360ea926b4e603fb8c92f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6936.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3557ed1028ef8d572f3da294e23899376dc9e32d", + "authors": [ + { + "n": "Adonay Nunes", + "e": "adonay.s.nunes@gmail.com" + } + ], + "changes": { + "doc/overview/faq.rst": { + "a": 23, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6938.json b/mne-python/source/doc/sphinxext/prs/6938.json new file mode 100644 index 0000000000000000000000000000000000000000..db004886c0cdd2ee835ce16453c9e9e1d3de5d08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6938.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "ec63d985c7af85db32e01e559335bebe8d32a705", + "authors": [ + { + "n": "Christian O'Reilly", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Jona Sassenhagen", + "e": "jona.sassenhagen@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 107, + "d": 41 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 89, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6939.json b/mne-python/source/doc/sphinxext/prs/6939.json new file mode 100644 index 0000000000000000000000000000000000000000..0e9caa212a27df03f197af35578358c985ea8910 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6939.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "731973aaa2e7b3b7dac1e7cc75a482586a165151", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/flat.py": { + "a": 9, + "d": 3 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 19, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6940.json b/mne-python/source/doc/sphinxext/prs/6940.json new file mode 100644 index 0000000000000000000000000000000000000000..1e6cff3656261c78bba613601d1f38718d79e4b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6940.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "76d84953b7d3dcbf1e1cd0ba5ded6cb1c8d96fe6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/annotations.py": { + "a": 3, + "d": 3 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/flat.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 248, + "d": 96 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 18, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 88, + "d": 0 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 25, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6941.json b/mne-python/source/doc/sphinxext/prs/6941.json new file mode 100644 index 0000000000000000000000000000000000000000..aa5bfb3b1b92e24a0feac00f7a0b7b595c7f2e1d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6941.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6601b7ce5cd2b8caa8dda9ac913ffadc62fda5bb", + "authors": [ + { + "n": "Darlene Heliokinde", + "e": "demetres.kostas@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 15, + "d": 8 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6942.json b/mne-python/source/doc/sphinxext/prs/6942.json new file mode 100644 index 0000000000000000000000000000000000000000..01e01b0b29bb689c32f0a7223641e7d015d8d0e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6942.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "050665001dd8b5f30d9a718c378a4a3598eadc51", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/0.19.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6944.json b/mne-python/source/doc/sphinxext/prs/6944.json new file mode 100644 index 0000000000000000000000000000000000000000..fbacb8ac195cf26062f924bf60f77d2a40444c34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6944.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "30fa09c049476ec2aa17811a0521420fca8cae49", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 14, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6946.json b/mne-python/source/doc/sphinxext/prs/6946.json new file mode 100644 index 0000000000000000000000000000000000000000..91d740fa5f03f1a2b92fdfaa9a9e8e44ab208828 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6946.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "47796f3349ddd84abec06f02c1bc263039dd30e8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_xdawn.py": { + "a": 11, + "d": 6 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 3, + "d": 4 + }, + "mne/utils/config.py": { + "a": 23, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6948.json b/mne-python/source/doc/sphinxext/prs/6948.json new file mode 100644 index 0000000000000000000000000000000000000000..c96117bc9ee295dd4810188e549c7e148d01c8a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6948.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5f0430f81a40803a7d0ae72ec49d8bdcd9be4475", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 10, + "d": 0 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6949.json b/mne-python/source/doc/sphinxext/prs/6949.json new file mode 100644 index 0000000000000000000000000000000000000000..a6b80e7ec512c0c570df1424273e0d6ebc9e969d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6949.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "eb8d4a9ef5147a22b6945754be8bb651dd04b99e", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "tutorials/source-modeling/plot_dipole_fit.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/695.json b/mne-python/source/doc/sphinxext/prs/695.json new file mode 100644 index 0000000000000000000000000000000000000000..7b4a55678c1f98b5c6d84216db7524ae0fbf7021 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/695.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3a930fed6c8f00a89a939d0bac82feea69b7482e", + "authors": [ + { + "n": "Romain Trachel", + "e": "trachelr@gmail.com" + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 11, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6954.json b/mne-python/source/doc/sphinxext/prs/6954.json new file mode 100644 index 0000000000000000000000000000000000000000..be9c28709556495e06857733a90bdbd45156b680 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6954.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "91af33a3035b879d1efdaf0c3b0a7bc610ff7ae1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6955.json b/mne-python/source/doc/sphinxext/prs/6955.json new file mode 100644 index 0000000000000000000000000000000000000000..23d04404f4e3054be6332e5d3ddd11725086205c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6955.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "19524d0fca2db68e0c358cd1eaf26f939a97ab7f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6959.json b/mne-python/source/doc/sphinxext/prs/6959.json new file mode 100644 index 0000000000000000000000000000000000000000..3330140782baeb9dedbc74645e197138ebfc9241 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6959.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4dce919a08d40d8b505b3505e211086ea8a975b1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 8, + "d": 6 + }, + "mne/io/curry/curry.py": { + "a": 0, + "d": 1 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 8, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6960.json b/mne-python/source/doc/sphinxext/prs/6960.json new file mode 100644 index 0000000000000000000000000000000000000000..94980175da533272928e24004b2cd6efd0db440e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6960.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "132a72023fec55d0e3e523aeecf1a854763f3738", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6961.json b/mne-python/source/doc/sphinxext/prs/6961.json new file mode 100644 index 0000000000000000000000000000000000000000..0b143a5ca1eb87766721d0b5c0cc940c9b574d2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6961.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cf5698ce79c57d69ec17c41a0808d387dc388aef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/externals/tempita/__init__.py": { + "a": 7, + "d": 2 + }, + "mne/report.py": { + "a": 3, + "d": 2 + }, + "mne/utils/_bunch.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6962.json b/mne-python/source/doc/sphinxext/prs/6962.json new file mode 100644 index 0000000000000000000000000000000000000000..54331e19f98a6493c1fdfd1a0113796cf9c614d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6962.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b4b03583bcb4cbb944a5bcff60f874e1e54db975", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 8, + "d": 6 + }, + "mne/io/curry/curry.py": { + "a": 0, + "d": 1 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 8, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6964.json b/mne-python/source/doc/sphinxext/prs/6964.json new file mode 100644 index 0000000000000000000000000000000000000000..20d1ac89225d4f76bd6275465331e476955c46e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6964.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b0a89dbfc4aba6384fbad0f399fa9e856a0dac87", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6966.json b/mne-python/source/doc/sphinxext/prs/6966.json new file mode 100644 index 0000000000000000000000000000000000000000..3d288056d69c59f4383074c2d7a31e1bf5696682 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6966.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b7f2cdb0f19424738f0d1781c610bf2f378910e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 17, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6967.json b/mne-python/source/doc/sphinxext/prs/6967.json new file mode 100644 index 0000000000000000000000000000000000000000..d9a9905c241473aa8e6bf07aaa6025cb4bded692 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6967.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e2befdb95131658dadce64d3d512b39499950cc", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6969.json b/mne-python/source/doc/sphinxext/prs/6969.json new file mode 100644 index 0000000000000000000000000000000000000000..5f0458c2ec717779bd6ebacc641dfd69940506e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6969.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fc451b57c8e4c3a0b273b25241288a517467400f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/697.json b/mne-python/source/doc/sphinxext/prs/697.json new file mode 100644 index 0000000000000000000000000000000000000000..45fcb4d2d8b13d13831376b558318836ea5688b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/697.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "adab1d0c2008021ba40e3cd8f90e805f5d27c685", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 31, + "d": 18 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 6, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 96, + "d": 108 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 52, + "d": 32 + }, + "mne/viz.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6971.json b/mne-python/source/doc/sphinxext/prs/6971.json new file mode 100644 index 0000000000000000000000000000000000000000..4c77cb780597fd97657049dc9dc78c04dd5061e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6971.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f37219e56099020848a38ca8ca1ad07b133b2b66", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 37, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6972.json b/mne-python/source/doc/sphinxext/prs/6972.json new file mode 100644 index 0000000000000000000000000000000000000000..c7aeeac08c7213a670f830c38130d05ea9ab2d30 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6972.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3e71210f034e53427fac25b8cda7c936c077f41d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_publication_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6975.json b/mne-python/source/doc/sphinxext/prs/6975.json new file mode 100644 index 0000000000000000000000000000000000000000..3acacd219c1184bd9586797e6d2b15e196b4886f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6975.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "a76fb4496310af8a080d27c06ca5746ec5cac834", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/data/extinction_coef.mat": { + "a": 0, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 0, + "d": 13 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 7, + "d": 5 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_beer_lambert_law.py": { + "a": 137, + "d": 0 + }, + "mne/preprocessing/tests/test_beer_lambert_law.py": { + "a": 73, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6976.json b/mne-python/source/doc/sphinxext/prs/6976.json new file mode 100644 index 0000000000000000000000000000000000000000..fc6b38fd1f2d4b85a3efe2cc6262c8f7039483b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6976.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0ffb606e36ce36a98db442de9a7784fce85c5928", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 18, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6977.json b/mne-python/source/doc/sphinxext/prs/6977.json new file mode 100644 index 0000000000000000000000000000000000000000..c71de59ea4d221cadadb4c7b47041a7f7e511282 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6977.json @@ -0,0 +1,331 @@ +{ + "merge_commit_sha": "26d5a49c6e44da063e0b1f3b17fe8a72f2f53ac0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 3, + "d": 5 + }, + "mne/bem.py": { + "a": 12, + "d": 12 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 4 + }, + "mne/connectivity/effective.py": { + "a": 7, + "d": 7 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 2 + }, + "mne/coreg.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 2, + "d": 4 + }, + "mne/datasets/sample/sample.py": { + "a": 12, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/receptive_field.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/transformer.py": { + "a": 6, + "d": 6 + }, + "mne/dipole.py": { + "a": 0, + "d": 2 + }, + "mne/epochs.py": { + "a": 6, + "d": 8 + }, + "mne/event.py": { + "a": 17, + "d": 18 + }, + "mne/evoked.py": { + "a": 4, + "d": 4 + }, + "mne/filter.py": { + "a": 0, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 0, + "d": 2 + }, + "mne/gui/__init__.py": { + "a": 14, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 6, + "d": 7 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 6, + "d": 6 + }, + "mne/io/base.py": { + "a": 4, + "d": 4 + }, + "mne/io/brainvision/brainvision.py": { + "a": 0, + "d": 1 + }, + "mne/io/curry/curry.py": { + "a": 0, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 41, + "d": 26 + }, + "mne/io/eeglab/eeglab.py": { + "a": 16, + "d": 17 + }, + "mne/io/egi/egi.py": { + "a": 4, + "d": 4 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 14, + "d": 18 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 2 + }, + "mne/io/open.py": { + "a": 5, + "d": 0 + }, + "mne/io/pick.py": { + "a": 4, + "d": 5 + }, + "mne/io/reference.py": { + "a": 33, + "d": 33 + }, + "mne/label.py": { + "a": 4, + "d": 7 + }, + "mne/minimum_norm/inverse.py": { + "a": 7, + "d": 7 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 11, + "d": 6 + }, + "mne/misc.py": { + "a": 5, + "d": 1 + }, + "mne/morph.py": { + "a": 5, + "d": 0 + }, + "mne/parallel.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/_optical_density.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 7, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 4, + "d": 4 + }, + "mne/selection.py": { + "a": 0, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 21, + "d": 21 + }, + "mne/source_space.py": { + "a": 4, + "d": 5 + }, + "mne/stats/cluster_level.py": { + "a": 6, + "d": 6 + }, + "mne/stats/multi_comp.py": { + "a": 0, + "d": 1 + }, + "mne/stats/parametric.py": { + "a": 0, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 0, + "d": 2 + }, + "mne/surface.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 42, + "d": 84 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stft.py": { + "a": 1, + "d": 11 + }, + "mne/time_frequency/_stockwell.py": { + "a": 8, + "d": 8 + }, + "mne/time_frequency/csd.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/multitaper.py": { + "a": 0, + "d": 3 + }, + "mne/time_frequency/psd.py": { + "a": 10, + "d": 10 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 12 + }, + "mne/utils/_logging.py": { + "a": 15, + "d": 10 + }, + "mne/utils/config.py": { + "a": 2, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 3 + }, + "mne/viz/backends/renderer.py": { + "a": 12, + "d": 13 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 4, + "d": 5 + }, + "mne/viz/misc.py": { + "a": 8, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 7, + "d": 7 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 19, + "d": 14 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/698.json b/mne-python/source/doc/sphinxext/prs/698.json new file mode 100644 index 0000000000000000000000000000000000000000..5701949f4437d70e6bb76730546e09df07860dbe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/698.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a629463849b5e00bd01fc13e90d0f775ef52afd2", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/decoding/classifier.py": { + "a": 0, + "d": 73 + }, + "mne/decoding/csp.py": { + "a": 7, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6981.json b/mne-python/source/doc/sphinxext/prs/6981.json new file mode 100644 index 0000000000000000000000000000000000000000..edb9dacc0c3c86ab45fd7ebfbc092743a591fbb8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6981.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "309a63861723e073b133181dee857ea01c2178ed", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 41, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6982.json b/mne-python/source/doc/sphinxext/prs/6982.json new file mode 100644 index 0000000000000000000000000000000000000000..065d092d5e1a73c4d4e12175ef0640e3965f5c6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6982.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e58b72fb3be7ff2b2ca7a7498e685fa599626b8e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/nirx/tests/test_nirx.py": { + "a": 8, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 17, + "d": 10 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 22, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6983.json b/mne-python/source/doc/sphinxext/prs/6983.json new file mode 100644 index 0000000000000000000000000000000000000000..69fa79fbec178c1a75ca5e6ec67bb6183fcfc209 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6983.json @@ -0,0 +1,291 @@ +{ + "merge_commit_sha": "9e588fca0007e8bda43c8a1349d679aaa71c0768", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 6, + "d": 9 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 4 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 2 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 9, + "d": 9 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sample/sample.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/search_light.py": { + "a": 3, + "d": 3 + }, + "mne/decoding/transformer.py": { + "a": 3, + "d": 3 + }, + "mne/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/event.py": { + "a": 9, + "d": 10 + }, + "mne/evoked.py": { + "a": 8, + "d": 8 + }, + "mne/filter.py": { + "a": 7, + "d": 6 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 3 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/open.py": { + "a": 2, + "d": 2 + }, + "mne/io/pick.py": { + "a": 25, + "d": 25 + }, + "mne/label.py": { + "a": 38, + "d": 49 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 7, + "d": 7 + }, + "mne/misc.py": { + "a": 2, + "d": 2 + }, + "mne/morph.py": { + "a": 4, + "d": 7 + }, + "mne/parallel.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/eog.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 38, + "d": 37 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 15, + "d": 15 + }, + "mne/simulation/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/source.py": { + "a": 15, + "d": 27 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 26, + "d": 31 + }, + "mne/stats/cluster_level.py": { + "a": 12, + "d": 12 + }, + "mne/stats/multi_comp.py": { + "a": 15, + "d": 16 + }, + "mne/stats/parametric.py": { + "a": 2, + "d": 2 + }, + "mne/stats/permutations.py": { + "a": 3, + "d": 5 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 8 + }, + "mne/time_frequency/_stft.py": { + "a": 12, + "d": 12 + }, + "mne/time_frequency/ar.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/csd.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/multitaper.py": { + "a": 7, + "d": 7 + }, + "mne/time_frequency/psd.py": { + "a": 9, + "d": 9 + }, + "mne/time_frequency/tfr.py": { + "a": 10, + "d": 10 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 9 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 12, + "d": 12 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 6, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6985.json b/mne-python/source/doc/sphinxext/prs/6985.json new file mode 100644 index 0000000000000000000000000000000000000000..cb9af09e3bafb32430defc4812b2e44f0fa965c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6985.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ea9137f55baf9ea96820a87098ce3313fd0f334c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 6, + "d": 0 + }, + "mne/evoked.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6986.json b/mne-python/source/doc/sphinxext/prs/6986.json new file mode 100644 index 0000000000000000000000000000000000000000..41c01e31f424875ede532ae7ced32148dbbcea8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6986.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "633689fada385d562beedacc1cafb518f5dca4ce", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 13, + "d": 11 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 51, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6989.json b/mne-python/source/doc/sphinxext/prs/6989.json new file mode 100644 index 0000000000000000000000000000000000000000..8e1c322ceb5d60c99ab530c1fc02c59b23c3d0ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6989.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f78c18fff5aeff05261278fdfb62c42c30736fd6", + "authors": [ + { + "n": "Victor Férat", + "e": "victor.ferat@live.Fr" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_setup_forward_model.py": { + "a": 121, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6991.json b/mne-python/source/doc/sphinxext/prs/6991.json new file mode 100644 index 0000000000000000000000000000000000000000..e7c36de7574772119c3debc1e715ffd658609d84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6991.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "799c2ecb74604ad0ab432b6cee5739dca5c85ca6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6992.json b/mne-python/source/doc/sphinxext/prs/6992.json new file mode 100644 index 0000000000000000000000000000000000000000..8cce4fe711712789ef02363fdd8b8d8c39e46c8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6992.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0a45ec5f8a0fef47dea39739bd97618c310e6f34", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 72, + "d": 31 + }, + "mne/viz/tests/test_misc.py": { + "a": 8, + "d": 6 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 21, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6993.json b/mne-python/source/doc/sphinxext/prs/6993.json new file mode 100644 index 0000000000000000000000000000000000000000..969d7327a184e2ecf772fcb0e3f75f0466c470f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6993.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "058f396660d763fcd175bedf917cd27d923f511d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 5 + }, + "mne/channels/interpolation.py": { + "a": 6, + "d": 10 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 26, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6996.json b/mne-python/source/doc/sphinxext/prs/6996.json new file mode 100644 index 0000000000000000000000000000000000000000..4d5c113d02f5b1ca5b44c6a3cd52e7212ec8a814 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6996.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "eb9fa1eb489491868453ed8a3c75440708547542", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 15, + "d": 14 + }, + "mne/epochs.py": { + "a": 2, + "d": 37 + }, + "mne/evoked.py": { + "a": 19, + "d": 57 + }, + "mne/filter.py": { + "a": 1, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 40, + "d": 8 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 45, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6998.json b/mne-python/source/doc/sphinxext/prs/6998.json new file mode 100644 index 0000000000000000000000000000000000000000..90b08f28bff85d39a3c0be11a00ae28e49dba573 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6998.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9771649ba90e0129e779923d4891b80ccf0a9b6a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/renderer.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/6999.json b/mne-python/source/doc/sphinxext/prs/6999.json new file mode 100644 index 0000000000000000000000000000000000000000..989ec811f6c453dd641d4a689f200b974558a0a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/6999.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d2e86a157608072374f898098bbd3ec64457f77b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/_beer_lambert_law.py": { + "a": 9, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7.json b/mne-python/source/doc/sphinxext/prs/7.json new file mode 100644 index 0000000000000000000000000000000000000000..dd9a6d5b7292ebc9b5974e1d9e5dad383b1b21fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "602a264c1ca3f037f7b531084123c1ac9a41da25", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 77, + "d": 11 + }, + "mne/tests/test_epochs.py": { + "a": 40, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/70.json b/mne-python/source/doc/sphinxext/prs/70.json new file mode 100644 index 0000000000000000000000000000000000000000..5d343a5ae87920c35fa0e51e9a55b5ca19864980 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/70.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "67524c1a03b36954407fbcdd65ca614905cd021a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 71, + "d": 0 + }, + "mne/forward.py": { + "a": 54, + "d": 5 + }, + "mne/minimum_norm/inverse.py": { + "a": 50, + "d": 36 + }, + "mne/mixed_norm/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/mixed_norm/debiasing.py": { + "a": 126, + "d": 0 + }, + "mne/mixed_norm/inverse.py": { + "a": 226, + "d": 0 + }, + "mne/mixed_norm/optim.py": { + "a": 315, + "d": 0 + }, + "mne/mixed_norm/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/mixed_norm/tests/test_debiasing.py": { + "a": 22, + "d": 0 + }, + "mne/mixed_norm/tests/test_inverse.py": { + "a": 48, + "d": 0 + }, + "mne/mixed_norm/tests/test_optim.py": { + "a": 36, + "d": 0 + }, + "mne/viz.py": { + "a": 29, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7000.json b/mne-python/source/doc/sphinxext/prs/7000.json new file mode 100644 index 0000000000000000000000000000000000000000..9668ecbbb7b175c62d238283d4254aa70a4371e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7000.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e0688805e90d30c74bb1fc17eff1343edada5ce0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 8, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 4 + }, + "mne/io/reference.py": { + "a": 26, + "d": 9 + }, + "mne/io/tests/test_constants.py": { + "a": 10, + "d": 5 + }, + "mne/io/tests/test_reference.py": { + "a": 16, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7001.json b/mne-python/source/doc/sphinxext/prs/7001.json new file mode 100644 index 0000000000000000000000000000000000000000..10a81f3316e72d3fd4af6ac7552794b2e37a60b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7001.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4cae8234a6d2c02982f1210907059ab944f8cc56", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 5, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7002.json b/mne-python/source/doc/sphinxext/prs/7002.json new file mode 100644 index 0000000000000000000000000000000000000000..8592755e79a1c90b8fe90cdf121a408e1ac6c6a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7002.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f6a7fa74289192030dbbc5bc23b0bb9f25180a14", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/defaults.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7004.json b/mne-python/source/doc/sphinxext/prs/7004.json new file mode 100644 index 0000000000000000000000000000000000000000..820dd3684dbdb57bfded96a79a2f9a831bbde734 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7004.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6233196394b1712f65be858227d9846b534fa150", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/datasets/hf_sef/hf_sef.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7005.json b/mne-python/source/doc/sphinxext/prs/7005.json new file mode 100644 index 0000000000000000000000000000000000000000..14013deda7bbf2ed4fc1df994a3d6bd027bb0b47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7005.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "54e07b3257ee44ae28c5253f47ef73909ef23bfd", + "authors": [ + { + "n": "Victor Férat", + "e": "victor.ferat@live.Fr" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_prepare_bem_model.py": { + "a": 55, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 21, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7008.json b/mne-python/source/doc/sphinxext/prs/7008.json new file mode 100644 index 0000000000000000000000000000000000000000..c2f4f73f7621a9b990f615d13c4aa1ed1565af5f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7008.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "6ca8ec3786d864f53ab379f59e1f6668afd1ff5e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_make_report.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 2, + "d": 7 + }, + "mne/report.py": { + "a": 20, + "d": 27 + }, + "mne/tests/test_report.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 49, + "d": 16 + }, + "mne/viz/backends/_pyvista.py": { + "a": 31, + "d": 8 + }, + "mne/viz/backends/renderer.py": { + "a": 14, + "d": 5 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7010.json b/mne-python/source/doc/sphinxext/prs/7010.json new file mode 100644 index 0000000000000000000000000000000000000000..0c6d626688dc7200976fb039a6118d6050e0035e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7010.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2f787cecacf203cb037cd96d5840916a8a260a7c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 0, + "d": 3 + }, + "mne/bem.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7011.json b/mne-python/source/doc/sphinxext/prs/7011.json new file mode 100644 index 0000000000000000000000000000000000000000..8425b08473081babca9ec84bf1bc98649f771b42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7011.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fbd75733e1d57f3fdbb65b01500de18d05185fc5", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 413, + "d": 0 + }, + "tutorials/epochs/plot_object_epochs.py": { + "a": 0, + "d": 167 + }, + "tutorials/epochs/plot_visualize_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_20_rejecting_bad_data.py": { + "a": 2, + "d": 0 + }, + "tutorials/raw/plot_20_event_arrays.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7014.json b/mne-python/source/doc/sphinxext/prs/7014.json new file mode 100644 index 0000000000000000000000000000000000000000..56a5d784a860346c02a20918653cc4047b0f4a7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7014.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "23e10c19da1803159e24709a6dfdb9cde9413798", + "authors": [ + { + "n": "Adonay Nunes", + "e": "adonay.s.nunes@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 13, + "d": 6 + }, + "mne/tests/test_annotations.py": { + "a": 39, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7016.json b/mne-python/source/doc/sphinxext/prs/7016.json new file mode 100644 index 0000000000000000000000000000000000000000..ff9d94eb6ff160ab38eb7c8de5ec93c56732ddf2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7016.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bb8cd6953757f051a9781f38198e5986511d7329", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 109, + "d": 29 + }, + "mne/io/tests/test_meas_info.py": { + "a": 48, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7017.json b/mne-python/source/doc/sphinxext/prs/7017.json new file mode 100644 index 0000000000000000000000000000000000000000..881f96f4700c82806109340c0de516565735ef51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7017.json @@ -0,0 +1,243 @@ +{ + "merge_commit_sha": "42948689ea8c3fdb926f36a211d4d83fb9382789", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 2, + "d": 2 + }, + "examples/datasets/spm_faces_dataset.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_comparison.py": { + "a": 1, + "d": 0 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 2, + "d": 1 + }, + "mne/commands/mne_coreg.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_maxfilter.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_prepare_bem_model.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_report.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_show_fiff.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_watershed_bem.py": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_what.py": { + "a": 1, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 0 + }, + "mne/commands/utils.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/_fake/_fake.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/misc/_misc.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/mtrf/mtrf.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/phantom_4dbti/phantom_4dbti.py": { + "a": 2, + "d": 0 + }, + "mne/datasets/somato/somato.py": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 1, + "d": 0 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_marker_gui.py": { + "a": 1, + "d": 1 + }, + "mne/io/_digitization.py": { + "a": 2, + "d": 1 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 0 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 0 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 5, + "d": 5 + }, + "mne/io/egi/egimff.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 0 + }, + "mne/utils/check.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 4, + "d": 4 + }, + "mne/viz/backends/_pyvista.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_misc.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "setup.cfg": { + "a": 1, + "d": 5 + }, + "setup.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_45_projectors_background.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7018.json b/mne-python/source/doc/sphinxext/prs/7018.json new file mode 100644 index 0000000000000000000000000000000000000000..3bcbf884bd9ea19125c2518f9e8ee0881fec4619 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7018.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "25f93eb8063936c8db2fd18d35c89724d65a21fd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 18, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/fnirs_motor/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/fnirs_motor/fnirs_motor.py": { + "a": 30, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 8, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 186, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7019.json b/mne-python/source/doc/sphinxext/prs/7019.json new file mode 100644 index 0000000000000000000000000000000000000000..8a38554b75989d9f6df26f820e6840766f6a0f9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7019.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b6f82798af05b1f457663179d64771341f66fd86", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 17, + "d": 21 + }, + "azure-pipelines.yml": { + "a": 69, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/702.json b/mne-python/source/doc/sphinxext/prs/702.json new file mode 100644 index 0000000000000000000000000000000000000000..510630bdbb172967b5abdbcf1a04b84fd1dc7930 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/702.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ac3216cf5ae91af1b0d2ee24b32e675792a45403", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 2, + "d": 1 + }, + "bin/mne_compute_proj_eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 17, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7022.json b/mne-python/source/doc/sphinxext/prs/7022.json new file mode 100644 index 0000000000000000000000000000000000000000..1e67df2b9674c3a6aecee5e81a8844bd9a061479 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7022.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4106d6dfa3bf79d7d39e3b68edab4ae8cd67c245", + "authors": [ + { + "n": "mathurinm", + "e": "mathurin.massias@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7023.json b/mne-python/source/doc/sphinxext/prs/7023.json new file mode 100644 index 0000000000000000000000000000000000000000..d88c81730e77b2bd324e5115d9f899b094810ac0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7023.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d37f45790ec28f85b342321e41ec50c0e43100b5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7025.json b/mne-python/source/doc/sphinxext/prs/7025.json new file mode 100644 index 0000000000000000000000000000000000000000..7cfebd4691b5fc15f19fc7c5ce68a7271d05d79c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7025.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0e09618b63085867204479bf2571a561d72f437c", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 17, + "d": 6 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 11, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7026.json b/mne-python/source/doc/sphinxext/prs/7026.json new file mode 100644 index 0000000000000000000000000000000000000000..aad0838fb8900606a9bd468a58e78a263f11d438 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7026.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c80badd8939423d9c5dd342a60135bd8ead6cc13", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 30, + "d": 9 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7028.json b/mne-python/source/doc/sphinxext/prs/7028.json new file mode 100644 index 0000000000000000000000000000000000000000..11916ab7ebd75ba5b2b7109bad0a1a5fffec619a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7028.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e04a8d127bbef82a96dd6659e1754759418b10cb", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7029.json b/mne-python/source/doc/sphinxext/prs/7029.json new file mode 100644 index 0000000000000000000000000000000000000000..c41861ccfff121f2ec1c28227ca724dbe794cedf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7029.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "b12a220d2b6d5b5c89b05e5536be28bb21cfc361", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 14, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 71, + "d": 26 + }, + "mne/channels/tests/test_channels.py": { + "a": 49, + "d": 3 + }, + "mne/cov.py": { + "a": 25, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 39, + "d": 1 + }, + "mne/forward/tests/test_forward.py": { + "a": 12, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 31, + "d": 1 + }, + "mne/io/pick.py": { + "a": 30, + "d": 8 + }, + "mne/io/tests/test_meas_info.py": { + "a": 11, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 30, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 13, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/csd.py": { + "a": 69, + "d": 35 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 11, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/703.json b/mne-python/source/doc/sphinxext/prs/703.json new file mode 100644 index 0000000000000000000000000000000000000000..a7e54e8b7702d1a8e861659d3ff3981cb64568ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/703.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7e037bb095e77528571d07a22879d2415c8a73bb", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fiff/constants.py": { + "a": 5, + "d": 1 + }, + "mne/fiff/pick.py": { + "a": 30, + "d": 3 + }, + "mne/viz.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7030.json b/mne-python/source/doc/sphinxext/prs/7030.json new file mode 100644 index 0000000000000000000000000000000000000000..5e711bab32fc54b1054aa288196f552a75a41947 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7030.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "965cffb205b3e5d11df8ac81c019716799125ded", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 17, + "d": 0 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7031.json b/mne-python/source/doc/sphinxext/prs/7031.json new file mode 100644 index 0000000000000000000000000000000000000000..9b8a1d98d09c276b9e9896745970bcd27ff13e75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7031.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "34b6ed1b6807d90669b2b42080f5826851ae21bd", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 25, + "d": 44 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 8, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7032.json b/mne-python/source/doc/sphinxext/prs/7032.json new file mode 100644 index 0000000000000000000000000000000000000000..7b8eb145eb6d1113fbefd536e1c4e5400d29f0a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7032.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "bd8616679dbf757930e34cb4b5ddc6d3d242c57a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 98, + "d": 86 + }, + "mne/fixes.py": { + "a": 27, + "d": 10 + }, + "mne/utils/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/utils/linalg.py": { + "a": 0, + "d": 86 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7033.json b/mne-python/source/doc/sphinxext/prs/7033.json new file mode 100644 index 0000000000000000000000000000000000000000..4bfd18bedec2096c4ea5ff6861c4b1ad89e0b03c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7033.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a2a0e2c763715d174398eb137270045bf21232c6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/_eloreta.py": { + "a": 9, + "d": 12 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/linalg.py": { + "a": 0, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7035.json b/mne-python/source/doc/sphinxext/prs/7035.json new file mode 100644 index 0000000000000000000000000000000000000000..c95cf3ab912681c97f5536baed0c65aff72d66a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7035.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e165f22dacd2a89c9181c2f2f97806eeea11dd37", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_beer_lambert_law.py": { + "a": 16, + "d": 3 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7036.json b/mne-python/source/doc/sphinxext/prs/7036.json new file mode 100644 index 0000000000000000000000000000000000000000..83a5eb2fe7fcbf412e479b30a203b7a123247ca5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7036.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "fb98a50de7c03fa8a95456c05f33fdc743ed66e7", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/704.json b/mne-python/source/doc/sphinxext/prs/704.json new file mode 100644 index 0000000000000000000000000000000000000000..bb403fff4ad68d5cadd2171c792a07ba41575798 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/704.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2c1ddf0983d424c99c9d3cc001832d79d90a478b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 14, + "d": 14 + }, + "mne/preprocessing/ica.py": { + "a": 18, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7040.json b/mne-python/source/doc/sphinxext/prs/7040.json new file mode 100644 index 0000000000000000000000000000000000000000..841691ab031cddff9ea39c9eaf7fd1d7341da096 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7040.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a26834b14ba0e1a9f67f6fa831657fd1f682a278", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/matrix.py": { + "a": 2, + "d": 4 + }, + "mne/io/open.py": { + "a": 2, + "d": 2 + }, + "mne/io/tag.py": { + "a": 19, + "d": 99 + }, + "mne/source_space.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7041.json b/mne-python/source/doc/sphinxext/prs/7041.json new file mode 100644 index 0000000000000000000000000000000000000000..35279722b7ddf653cdd3030b1e964461f57f45c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7041.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3ee879a9b6ff78f592e4a2d330ee2e6382fab143", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/search_light.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/tests/test_base.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 10, + "d": 0 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 2, + "d": 2 + }, + "mne/stats/tests/test_regression.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7042.json b/mne-python/source/doc/sphinxext/prs/7042.json new file mode 100644 index 0000000000000000000000000000000000000000..4a55d6ccc578687469596c5c12002194d2783efa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7042.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e84f78a7f01bd889746d3ec3c09a8d0db61c56f0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_resolution_metrics.py": { + "a": 28, + "d": 18 + }, + "examples/inverse/plot_resolution_metrics_eegmeg.py": { + "a": 27, + "d": 17 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 0, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7043.json b/mne-python/source/doc/sphinxext/prs/7043.json new file mode 100644 index 0000000000000000000000000000000000000000..b5a8bddadd1cbac1bff0ad690d0a403ce93e30c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7043.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "e1e7cc1f891308261dc98144890392111bf49afa", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 6, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 26, + "d": 10 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 8, + "d": 15 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 14, + "d": 12 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 10, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7044.json b/mne-python/source/doc/sphinxext/prs/7044.json new file mode 100644 index 0000000000000000000000000000000000000000..c60a427be25d5ef21b558cf841f31b34fc917c81 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7044.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "63ca985352d493ecb3a14df753dcbc8bc33b8e67", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7045.json b/mne-python/source/doc/sphinxext/prs/7045.json new file mode 100644 index 0000000000000000000000000000000000000000..87380a8589234c01e01b849feffd7b9bbf3738d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7045.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "793fdaa0bf5897b26bc6720ae9806a186635eb3c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/705.json b/mne-python/source/doc/sphinxext/prs/705.json new file mode 100644 index 0000000000000000000000000000000000000000..9752f3ffa13ad9ea23a4c4de83f021dae6015521 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/705.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f822aff865eec167ae7683cb30cb3006a601f721", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_stim.py": { + "a": 8, + "d": 8 + }, + "mne/source_estimate.py": { + "a": 13, + "d": 8 + }, + "mne/tests/test_viz.py": { + "a": 1, + "d": 1 + }, + "mne/viz.py": { + "a": 69, + "d": 57 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7050.json b/mne-python/source/doc/sphinxext/prs/7050.json new file mode 100644 index 0000000000000000000000000000000000000000..84f039da36d935e048f66719b36242d96af04400 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7050.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "76f198a6dafde5930341c9b8d093cddc0d1f2593", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7051.json b/mne-python/source/doc/sphinxext/prs/7051.json new file mode 100644 index 0000000000000000000000000000000000000000..d65eaa973ac9178fa2eca880bd13b4e6f69cdbce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7051.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ea33a0aa7adc758eb9e2f7899c03d561eec2b707", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/inverse_sparse/_gamma_map.py": { + "a": 3, + "d": 3 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 11, + "d": 3 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7054.json b/mne-python/source/doc/sphinxext/prs/7054.json new file mode 100644 index 0000000000000000000000000000000000000000..0c214844f981c98817e47008963640ccba1fa090 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7054.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "87756588a69514970ff5f24295773e9829e2d9ed", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/mne_python.rst": { + "a": 27, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7055.json b/mne-python/source/doc/sphinxext/prs/7055.json new file mode 100644 index 0000000000000000000000000000000000000000..a4d67e86e488e114135c14a4d95eb9b310f153dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7055.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "b906de881c150850eb0d36082c79add6970b2ca4", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 2 + }, + "doc/python_reference.rst": { + "a": 13, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 6, + "d": 6 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 11, + "d": 0 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 7, + "d": 34 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 55, + "d": 0 + }, + "mne/preprocessing/tests/test_beer_lambert_law.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_optical_density.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 6, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7059.json b/mne-python/source/doc/sphinxext/prs/7059.json new file mode 100644 index 0000000000000000000000000000000000000000..c3853dbdde695e2a6557f2310223fe2250af1c2d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7059.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "67d03cc0d0554b0d939ddd8ec2d2665add84d4ed", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/pre_install.rst": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7060.json b/mne-python/source/doc/sphinxext/prs/7060.json new file mode 100644 index 0000000000000000000000000000000000000000..fccccea42466cf477de1628dba77dd318a49e2e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7060.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "6dda707b0714618c8cbf4484b3aa780b048b4122", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/inverse.rst": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_vector_mne_solution.py": { + "a": 5, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 52, + "d": 24 + }, + "mne/viz/_brain/_brain.py": { + "a": 141, + "d": 21 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 35, + "d": 16 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 11, + "d": 6 + }, + "mne/viz/_brain/utils.py": { + "a": 0, + "d": 120 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 7, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 104, + "d": 15 + }, + "mne/viz/backends/base_renderer.py": { + "a": 12, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 6, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 7 + }, + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7061.json b/mne-python/source/doc/sphinxext/prs/7061.json new file mode 100644 index 0000000000000000000000000000000000000000..5dc97e7a77a6c1c8e72cf9faa2b70228f6c4cad4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7061.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ef7d7c1899911b821312cc5be1558cc2d6ae4816", + "authors": [ + { + "n": "ezemikulan", + "e": "e.mikulan@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7063.json b/mne-python/source/doc/sphinxext/prs/7063.json new file mode 100644 index 0000000000000000000000000000000000000000..6f7128ace36c1ad9bef3c1bbc9fead9c588197e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7063.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "3091cac2e780a3baf1763fc888da22660e5554a2", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 11, + "d": 11 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_beer_lambert_law.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 0 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 60, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7064.json b/mne-python/source/doc/sphinxext/prs/7064.json new file mode 100644 index 0000000000000000000000000000000000000000..b8cb1bf996498714f5414ff6b3d3cd531a89c0c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7064.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f784fde5d4ee738eff603bdc3823cfc3ca12b5bd", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 3, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7066.json b/mne-python/source/doc/sphinxext/prs/7066.json new file mode 100644 index 0000000000000000000000000000000000000000..b763e014e23afb10b447a9fa7d56d38e0f2f2769 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7066.json @@ -0,0 +1,227 @@ +{ + "merge_commit_sha": "1325c1abffa0db8cf57c9cd6410a4c92fcb0586c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 7, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 5, + "d": 4 + }, + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 1, + "d": 3 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 31, + "d": 36 + }, + "examples/forward/plot_left_cerebellum_volume_source.py": { + "a": 4, + "d": 4 + }, + "examples/io/plot_read_proj.py": { + "a": 4, + "d": 32 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 6, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 3, + "d": 2 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 2, + "d": 1 + }, + "mne/bem.py": { + "a": 6, + "d": 8 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 13, + "d": 11 + }, + "mne/channels/layout.py": { + "a": 31, + "d": 21 + }, + "mne/channels/montage.py": { + "a": 5, + "d": 6 + }, + "mne/channels/tests/test_layout.py": { + "a": 27, + "d": 22 + }, + "mne/datasets/eegbci/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 20, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 12, + "d": 40 + }, + "mne/defaults.py": { + "a": 3, + "d": 0 + }, + "mne/epochs.py": { + "a": 6, + "d": 4 + }, + "mne/evoked.py": { + "a": 16, + "d": 11 + }, + "mne/externals/doccer.py": { + "a": 5, + "d": 1 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 0 + }, + "mne/io/proj.py": { + "a": 13, + "d": 9 + }, + "mne/preprocessing/ica.py": { + "a": 13, + "d": 21 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 3, + "d": 2 + }, + "mne/source_space.py": { + "a": 30, + "d": 20 + }, + "mne/tests/test_source_space.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 8, + "d": 29 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 44, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 109, + "d": 62 + }, + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 9, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 48, + "d": 38 + }, + "mne/viz/ica.py": { + "a": 8, + "d": 7 + }, + "mne/viz/montage.py": { + "a": 7, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 15, + "d": 12 + }, + "mne/viz/tests/test_topomap.py": { + "a": 31, + "d": 52 + }, + "mne/viz/topomap.py": { + "a": 356, + "d": 586 + }, + "mne/viz/utils.py": { + "a": 37, + "d": 38 + }, + "tutorials/intro/plot_40_sensor_locations.py": { + "a": 150, + "d": 125 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 23, + "d": 11 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 3, + "d": 3 + }, + "tutorials/stats-sensor-space/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 5, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/707.json b/mne-python/source/doc/sphinxext/prs/707.json new file mode 100644 index 0000000000000000000000000000000000000000..8a0e8fcccdcf580dde51318656f13765f5f00de4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/707.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f8ddaeca19ae20a4d73038de41408f9e7e13ec2d", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/parallel.py": { + "a": 49, + "d": 7 + }, + "mne/stats/cluster_level.py": { + "a": 97, + "d": 24 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 28, + "d": 12 + }, + "mne/utils.py": { + "a": 42, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7070.json b/mne-python/source/doc/sphinxext/prs/7070.json new file mode 100644 index 0000000000000000000000000000000000000000..424c7986375a2dcf5c05a8e05748edc61c3e71d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7070.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "d495b13bb0b4bef05118e3bd75ce6860af641337", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "vpeterson", + "e": "victoriapeterson09@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 21, + "d": 0 + }, + "examples/decoding/plot_ssd_spatial_filters.py": { + "a": 138, + "d": 0 + }, + "mne/decoding/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/ssd.py": { + "a": 288, + "d": 0 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 233, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7074.json b/mne-python/source/doc/sphinxext/prs/7074.json new file mode 100644 index 0000000000000000000000000000000000000000..93f977980a31d5d904c676b0d89c4f527f16a28c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7074.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "50cc4f28f8ed0dfae8e78139ddabe93a80b6d1f9", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7076.json b/mne-python/source/doc/sphinxext/prs/7076.json new file mode 100644 index 0000000000000000000000000000000000000000..e80293173b9fb78a46a368e205ec6d2e5b6b593e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7076.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "01d964670e502f497670e7653512dc05689a59d4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 0 + }, + "bin/mne": { + "a": 0, + "d": 5 + }, + "doc/install/mne_python.rst": { + "a": 24, + "d": 5 + }, + "mne/gui/_backend.py": { + "a": 17, + "d": 34 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_marker_gui.py": { + "a": 2, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 19, + "d": 0 + }, + "mne/utils/config.py": { + "a": 4, + "d": 6 + }, + "setup.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7078.json b/mne-python/source/doc/sphinxext/prs/7078.json new file mode 100644 index 0000000000000000000000000000000000000000..7e1c5825494075854a6e4d23ad7182e7f7d2ab97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7078.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1e8c30d4969050a9313d720ba1feb41226a4e303", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/install/advanced.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7079.json b/mne-python/source/doc/sphinxext/prs/7079.json new file mode 100644 index 0000000000000000000000000000000000000000..72252ff0ea1554ca25ab2c8618b35f1a58b29199 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7079.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0c4c3b710eda33a2333b9dd0b6c66c03fc65146a", + "authors": [ + { + "n": "Christian O'Reilly", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 5 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 0 + }, + "mne/viz/_brain/surface.py": { + "a": 5, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 25, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7084.json b/mne-python/source/doc/sphinxext/prs/7084.json new file mode 100644 index 0000000000000000000000000000000000000000..1b602aae2d1f60c03586555f350a6a71be572804 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7084.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ec6df570e59d05ab4c5d35d74f9c153ba1fc7af0", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 13, + "d": 11 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7085.json b/mne-python/source/doc/sphinxext/prs/7085.json new file mode 100644 index 0000000000000000000000000000000000000000..baa240ec0640c4f4a2dad5e649fb2a372c6258c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7085.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5de659d2aa1dca4a0529e022036c9ff2a40ecc33", + "authors": [ + { + "n": "Britta Westner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan.mccloy@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/references.bib": { + "a": 11, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 0, + "d": 125 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 0, + "d": 132 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 274, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7086.json b/mne-python/source/doc/sphinxext/prs/7086.json new file mode 100644 index 0000000000000000000000000000000000000000..18be3ec1bc6727b4ee59c3712cae06a78fc169dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7086.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a62d596be99949f104360b4ba794105d35bf94c7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/misc.py": { + "a": 16, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7087.json b/mne-python/source/doc/sphinxext/prs/7087.json new file mode 100644 index 0000000000000000000000000000000000000000..5945b431d18a8ca34c066060ac3b74a052e59c08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7087.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "61b058d9b7387713bf6f165c69230cd475ded4e4", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Alex", + "e": "aprockhill206@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 182, + "d": 64 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7089.json b/mne-python/source/doc/sphinxext/prs/7089.json new file mode 100644 index 0000000000000000000000000000000000000000..54d12d1d19937c398e31df8c08d1650ceee50b71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7089.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3459c84cc7cc76c37356dbf163c7768f03c81182", + "authors": [ + { + "n": "Chun-Hui Li", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/base.py": { + "a": 7, + "d": 2 + }, + "mne/decoding/tests/test_base.py": { + "a": 105, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/709.json b/mne-python/source/doc/sphinxext/prs/709.json new file mode 100644 index 0000000000000000000000000000000000000000..267ed50ff2ccef2f66468db027d89326923d0ef2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/709.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b94101eb1fe2b393ad076921e0ba9d5830dd818d", + "authors": [ + { + "n": "Mads Jensen", + "e": null + } + ], + "changes": { + "mne/preprocessing/maxfilter.py": { + "a": 16, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7090.json b/mne-python/source/doc/sphinxext/prs/7090.json new file mode 100644 index 0000000000000000000000000000000000000000..5fcfe3a1cf3bb8a0ff7d375abe16815b0114a1b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7090.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f7e7bd3d460a609f22cca7166ddef9dd5311acea", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 10, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7091.json b/mne-python/source/doc/sphinxext/prs/7091.json new file mode 100644 index 0000000000000000000000000000000000000000..3cfe5856f1eee98a4a25ae93226b847024ac4298 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7091.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6861595ea11e30db2a4cb1262d90518f1a01bfcf", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 10, + "d": 6 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7095.json b/mne-python/source/doc/sphinxext/prs/7095.json new file mode 100644 index 0000000000000000000000000000000000000000..2e455fabe6ed5f1f680fd6ae8dc0aada8d056fa9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7095.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "1689df918f18a44fd4602b691ea59c781a0c8763", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 3, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_psf_ctf_vertices.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_psf_ctf_vertices_lcmv.py": { + "a": 137, + "d": 0 + }, + "examples/inverse/plot_resolution_metrics.py": { + "a": 5, + "d": 5 + }, + "examples/inverse/plot_resolution_metrics_eegmeg.py": { + "a": 23, + "d": 17 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 104, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 0 + }, + "mne/beamformer/tests/test_resolution_matrix.py": { + "a": 94, + "d": 0 + }, + "mne/cov.py": { + "a": 11, + "d": 4 + }, + "mne/minimum_norm/__init__.py": { + "a": 2, + "d": 3 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 6, + "d": 3 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 12, + "d": 10 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 7, + "d": 7 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7096.json b/mne-python/source/doc/sphinxext/prs/7096.json new file mode 100644 index 0000000000000000000000000000000000000000..319abe911f7dc92bcbf81a1f4717655e784afde1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7096.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "cce705bcfa34226f0f3a1c0abaed94d565539095", + "authors": [ + { + "n": "Adonay Nunes", + "e": "adonay.s.nunes@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_artifact_detection.py": { + "a": 81, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 212, + "d": 0 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 49, + "d": 0 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7097.json b/mne-python/source/doc/sphinxext/prs/7097.json new file mode 100644 index 0000000000000000000000000000000000000000..0493481f6500e6626116a33055ef46aafb83e07c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7097.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "76f38bdd351627504618516be29cf03947096a85", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/bug_report.md": { + "a": 26, + "d": 30 + }, + "CONTRIBUTING.rst": { + "a": 9, + "d": 19 + }, + "doc/_static/diagrams/git_setup.dot": { + "a": 64, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 60, + "d": 39 + }, + "doc/install/mne_python.rst": { + "a": 12, + "d": 1 + }, + "doc/links.inc": { + "a": 1, + "d": 0 + }, + "doc/overview/faq.rst": { + "a": 49, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/710.json b/mne-python/source/doc/sphinxext/prs/710.json new file mode 100644 index 0000000000000000000000000000000000000000..ebf30a1751612ebf5c70e53b0c772a6e5102d587 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/710.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ea0ddc4ac91b067b2200b374e5b860e7065862b2", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/constants.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 37, + "d": 15 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7100.json b/mne-python/source/doc/sphinxext/prs/7100.json new file mode 100644 index 0000000000000000000000000000000000000000..9e6692109dd866f559a6b296f4c4afcacf2784f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7100.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c59c5d959bd13715dc0ae7801ef95e7bc846bb4b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7102.json b/mne-python/source/doc/sphinxext/prs/7102.json new file mode 100644 index 0000000000000000000000000000000000000000..083662dd5389b780af6ced38911c1699d714fb0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7102.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "27e3f1d75f3c8605272d9071b5d5a2d77a7d1f22", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/io/plot_read_events.py": { + "a": 2, + "d": 2 + }, + "mne/event.py": { + "a": 2, + "d": 2 + }, + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 12, + "d": 0 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 210, + "d": 0 + }, + "tutorials/epochs/plot_epoching_and_averaging.py": { + "a": 0, + "d": 166 + }, + "tutorials/epochs/plot_visualize_epochs.py": { + "a": 0, + "d": 94 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 0, + "d": 3 + }, + "tutorials/evoked/plot_visualize_evoked.py": { + "a": 2, + "d": 1 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7103.json b/mne-python/source/doc/sphinxext/prs/7103.json new file mode 100644 index 0000000000000000000000000000000000000000..2f03209130752d5e5377137235718079f4b0b7a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7103.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "701312c2f66dbe6910d0845169d259afdfbd814a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/misc.py": { + "a": 37, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7104.json b/mne-python/source/doc/sphinxext/prs/7104.json new file mode 100644 index 0000000000000000000000000000000000000000..357b2a332a095ea8d235a4363584fa153259245e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7104.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "538597485f8f69b343690cdc5911665b4b98c131", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/ctf/ctf.py": { + "a": 3, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 6, + "d": 3 + }, + "mne/io/ctf/markers.py": { + "a": 16, + "d": 10 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7105.json b/mne-python/source/doc/sphinxext/prs/7105.json new file mode 100644 index 0000000000000000000000000000000000000000..fc7d38f1335df18e7007537ac4ab9c56957cf7ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7105.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "7410696b8897c8782ae293e1c453a43b20197acd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 1 + }, + ".travis.yml": { + "a": 3, + "d": 22 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 4 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/install/mne_python.rst": { + "a": 1, + "d": 1 + }, + "doc/overview/faq.rst": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_sys_info.py": { + "a": 29, + "d": 0 + }, + "mne/commands/tests/test_commands.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7106.json b/mne-python/source/doc/sphinxext/prs/7106.json new file mode 100644 index 0000000000000000000000000000000000000000..c588f27da12a5cd47ef07f0418211b598fb3b090 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7106.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "fedd892e3cfd2e4243061187e164bf10aafe9ffc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/glossary.rst": { + "a": 1, + "d": 1 + }, + "doc/overview/matlab.rst": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 3 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7108.json b/mne-python/source/doc/sphinxext/prs/7108.json new file mode 100644 index 0000000000000000000000000000000000000000..af1a22d2e44db4af64ba9f65bd83bbf58e6a5e8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7108.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "15b45a74c762f559f1c25199a67b290a5f18a26e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/coreg.py": { + "a": 4, + "d": 1 + }, + "mne/label.py": { + "a": 73, + "d": 25 + }, + "mne/source_space.py": { + "a": 62, + "d": 43 + }, + "mne/tests/test_coreg.py": { + "a": 46, + "d": 30 + }, + "mne/tests/test_label.py": { + "a": 19, + "d": 11 + }, + "mne/tests/test_source_space.py": { + "a": 38, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7109.json b/mne-python/source/doc/sphinxext/prs/7109.json new file mode 100644 index 0000000000000000000000000000000000000000..722b427c0116539df7cb4ab19d33529ab4b76a1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7109.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "de3e189f24cc029db9dab047f46c7deede6a255a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_10_preprocessing_overview.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7110.json b/mne-python/source/doc/sphinxext/prs/7110.json new file mode 100644 index 0000000000000000000000000000000000000000..358fc227380ee96f503558ce046a63e26fab3d64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7110.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "38973795d3c9c9ba694d74d710ce7a48c053a45b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/rank.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7111.json b/mne-python/source/doc/sphinxext/prs/7111.json new file mode 100644 index 0000000000000000000000000000000000000000..0a21c7be024653d6fa380e65e1d3c7a8fcdc7117 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7111.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "da9cd19a9b65e792e2523f159820549ec6082f9d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 26, + "d": 21 + }, + "mne/viz/tests/test_misc.py": { + "a": 28, + "d": 8 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7113.json b/mne-python/source/doc/sphinxext/prs/7113.json new file mode 100644 index 0000000000000000000000000000000000000000..9de91a2284e833cee700666ddbc6c1782ce84a13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7113.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "bb2beaf266254e1c2870e7a4b3cbc53d7cb72214", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 22, + "d": 10 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_base.py": { + "a": 4, + "d": 20 + }, + "mne/epochs.py": { + "a": 4, + "d": 1 + }, + "mne/label.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7117.json b/mne-python/source/doc/sphinxext/prs/7117.json new file mode 100644 index 0000000000000000000000000000000000000000..695c37ea7ff07873492bb4adf6a2646d0ddda1de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7117.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9216386526b76e4a6c39d06065b04a1077aa7bdb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 14, + "d": 7 + }, + "mne/tests/test_chpi.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7118.json b/mne-python/source/doc/sphinxext/prs/7118.json new file mode 100644 index 0000000000000000000000000000000000000000..e3944cab1f5111667cae0a58d110b7c9dd6155d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7118.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c8e1759c75d1cbec43d19b6e49cbb43c8f01d51c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.19.inc": { + "a": 7, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 14, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 2 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7119.json b/mne-python/source/doc/sphinxext/prs/7119.json new file mode 100644 index 0000000000000000000000000000000000000000..0a98fe62f6be5078ddc1160268b22917780410cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7119.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f8358f7bf9920088313c08bd71d7e241f29cf7e9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 16, + "d": 5 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/712.json b/mne-python/source/doc/sphinxext/prs/712.json new file mode 100644 index 0000000000000000000000000000000000000000..3f09a6aa932ef9087222099118792eaed57a88cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/712.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5983b5c44b94a24f292636f1f38f7cd18596052b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 14, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7120.json b/mne-python/source/doc/sphinxext/prs/7120.json new file mode 100644 index 0000000000000000000000000000000000000000..d71e117e239794cc856d87777a5a56686023e14e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7120.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a8e853ea3328d2d9de437d71161edc4fa729f204", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7121.json b/mne-python/source/doc/sphinxext/prs/7121.json new file mode 100644 index 0000000000000000000000000000000000000000..b9632aaafb094fe6cdf4d895f141df4384b9f4df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7121.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f1c048a763d6415d0743a248cd79bab089616f67", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7122.json b/mne-python/source/doc/sphinxext/prs/7122.json new file mode 100644 index 0000000000000000000000000000000000000000..9381717e462bf6f5b5459cb68b7905fc3eb85f1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7122.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "22dfbb5c55f09b88f595dd5c6d83dac71335df97", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.19.inc": { + "a": 9, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 14, + "d": 4 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 2 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 4 + }, + "mne/io/tests/test_meas_info.py": { + "a": 14, + "d": 2 + }, + "mne/label.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7124.json b/mne-python/source/doc/sphinxext/prs/7124.json new file mode 100644 index 0000000000000000000000000000000000000000..5591630437468c52a0f89d321205e60a4e5219ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7124.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "b3f22f9e044443e3b448b9e38b1234d9f2dc9380", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 11, + "d": 1 + }, + "mne/annotations.py": { + "a": 129, + "d": 110 + }, + "mne/channels/channels.py": { + "a": 37, + "d": 4 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 8, + "d": 6 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 17 + }, + "mne/io/base.py": { + "a": 38, + "d": 42 + }, + "mne/io/brainvision/brainvision.py": { + "a": 5, + "d": 10 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 10, + "d": 9 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf/info.py": { + "a": 2, + "d": 3 + }, + "mne/io/ctf/markers.py": { + "a": 3, + "d": 4 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 8, + "d": 6 + }, + "mne/io/edf/edf.py": { + "a": 23, + "d": 21 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 2, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 7, + "d": 6 + }, + "mne/io/kit/kit.py": { + "a": 4, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 52, + "d": 75 + }, + "mne/io/tests/test_meas_info.py": { + "a": 48, + "d": 29 + }, + "mne/io/tests/test_raw.py": { + "a": 11, + "d": 16 + }, + "mne/report.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/evoked.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 99, + "d": 44 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 4 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 4, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 29, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 3, + "d": 3 + }, + "tutorials/raw/plot_30_annotate_raw.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7125.json b/mne-python/source/doc/sphinxext/prs/7125.json new file mode 100644 index 0000000000000000000000000000000000000000..42b052141a3e85a73faacbd97d4c6e8b7abb1b86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7125.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ba810eb69b4ebac07cb8fb756a6b2b5ceee901dc", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 4 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7126.json b/mne-python/source/doc/sphinxext/prs/7126.json new file mode 100644 index 0000000000000000000000000000000000000000..737e7c0a2e2d81fbebf2a130f2e87975796d3764 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7126.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9a7b5e58e52a4d4007a942fa21a72d95a7124d8c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 30, + "d": 13 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7128.json b/mne-python/source/doc/sphinxext/prs/7128.json new file mode 100644 index 0000000000000000000000000000000000000000..c0cbf592ab8e880a16c9111f50cc0b0add1da5fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7128.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "558802eff2315bf60948c8087c9e983c577435fb", + "authors": [ + { + "n": "Henrich Kolkhorst", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 27, + "d": 2 + }, + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 8, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 97, + "d": 3 + }, + "mne/preprocessing/xdawn.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7129.json b/mne-python/source/doc/sphinxext/prs/7129.json new file mode 100644 index 0000000000000000000000000000000000000000..d219b09a2cb3c50593c2b83ee654a6c0189d4290 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7129.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "49cb69d72a57124709b5ed104b9d6255942cd939", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 9, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 22, + "d": 10 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/mixin.py": { + "a": 14, + "d": 2 + }, + "mne/decoding/search_light.py": { + "a": 8, + "d": 9 + }, + "mne/decoding/time_frequency.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 7, + "d": 7 + }, + "mne/dipole.py": { + "a": 3, + "d": 6 + }, + "mne/epochs.py": { + "a": 14, + "d": 10 + }, + "mne/event.py": { + "a": 0, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 10, + "d": 11 + }, + "mne/io/base.py": { + "a": 19, + "d": 16 + }, + "mne/io/proj.py": { + "a": 8, + "d": 7 + }, + "mne/label.py": { + "a": 6, + "d": 4 + }, + "mne/morph.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 20, + "d": 17 + }, + "mne/report.py": { + "a": 3, + "d": 10 + }, + "mne/simulation/source.py": { + "a": 3, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 43, + "d": 30 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 37, + "d": 7 + }, + "mne/time_frequency/csd.py": { + "a": 7, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 11, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/713.json b/mne-python/source/doc/sphinxext/prs/713.json new file mode 100644 index 0000000000000000000000000000000000000000..9be1e4eeedb69a9562391e51670ff38cba886370 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/713.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8b5d827b0d9dd49fbab53efc8f05b67e8e07bc8e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 17, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7130.json b/mne-python/source/doc/sphinxext/prs/7130.json new file mode 100644 index 0000000000000000000000000000000000000000..0e352a9e12897b8578331dd5a21cb045a7920171 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7130.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "74750eb88a3068790ad62400b309d11aefaa0c82", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "CODE_OF_CONDUCT.md": { + "a": 0, + "d": 46 + }, + "CONTRIBUTING.rst": { + "a": 1, + "d": 1 + }, + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7131.json b/mne-python/source/doc/sphinxext/prs/7131.json new file mode 100644 index 0000000000000000000000000000000000000000..652b7b55f9de08df6fc968536774e752268280e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7131.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9d2abf35b6983ceaf0016d68b7c63d49e8b7a093", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7132.json b/mne-python/source/doc/sphinxext/prs/7132.json new file mode 100644 index 0000000000000000000000000000000000000000..f8284e35d0365472fb2b5b5328c212aa62140467 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7132.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "71a854d8eafe21676e545d8286b51422f34b26c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7133.json b/mne-python/source/doc/sphinxext/prs/7133.json new file mode 100644 index 0000000000000000000000000000000000000000..51438f44adde36be41c16c4a928d9a59efaabfc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7133.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "68a7757c074e5fa51fdd13cca5bfd1559c0e2658", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 19, + "d": 14 + }, + "mne/fixes.py": { + "a": 14, + "d": 2 + }, + "mne/forward/_compute_forward.py": { + "a": 93, + "d": 59 + }, + "mne/surface.py": { + "a": 38, + "d": 40 + }, + "mne/transforms.py": { + "a": 13, + "d": 7 + }, + "mne/utils/_testing.py": { + "a": 5, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7135.json b/mne-python/source/doc/sphinxext/prs/7135.json new file mode 100644 index 0000000000000000000000000000000000000000..d787960a30ec64d81444d8d210540be8276a9bf9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7135.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a41ca39fcda5784cf2cd099de0f240b24b0f8cfa", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 40, + "d": 24 + }, + "mne/io/tests/test_meas_info.py": { + "a": 7, + "d": 0 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7138.json b/mne-python/source/doc/sphinxext/prs/7138.json new file mode 100644 index 0000000000000000000000000000000000000000..06a005602d8728d4708bfccda872ce618ba723d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7138.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a3a71b7d6606e8393f6e26f6a3c934b3084b5e03", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/overview/datasets_index.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/utils/mixin.py": { + "a": 9, + "d": 8 + }, + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 6, + "d": 3 + }, + "tutorials/epochs/plot_30_epochs_metadata.py": { + "a": 177, + "d": 0 + }, + "tutorials/epochs/plot_metadata_epochs.py": { + "a": 0, + "d": 154 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/714.json b/mne-python/source/doc/sphinxext/prs/714.json new file mode 100644 index 0000000000000000000000000000000000000000..984543fee299233323d4c84a2df19be13b91b5cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/714.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c3531e5524c66c711275ebb7f2d3a720a31e36b5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 36, + "d": 19 + }, + "mne/tests/test_label.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7142.json b/mne-python/source/doc/sphinxext/prs/7142.json new file mode 100644 index 0000000000000000000000000000000000000000..72d137ad4877dc3c61a1819d00c2130cb57d6215 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7142.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8ba88e2388d2ba5ff8e997401bfeac5b255d88a7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 4 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7144.json b/mne-python/source/doc/sphinxext/prs/7144.json new file mode 100644 index 0000000000000000000000000000000000000000..5725c9efe69261b16ce2829be02d3719192e8018 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7144.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "02173651e9986977899888d383319fe10c43eba8", + "authors": [ + { + "n": "Yu-Han Luo", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7145.json b/mne-python/source/doc/sphinxext/prs/7145.json new file mode 100644 index 0000000000000000000000000000000000000000..e24d61ca259fd8255e2d93b84df4186dd462efb6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7145.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "bbb57464b299824c5417beb3e9fcd5e9805f293f", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 4, + "d": 3 + }, + "mne/viz/tests/test_topomap.py": { + "a": 17, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7146.json b/mne-python/source/doc/sphinxext/prs/7146.json new file mode 100644 index 0000000000000000000000000000000000000000..8b718e505194da8869990ed8f69567b36b25a4a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7146.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "412ce469f55528b9657847fd3aea78aa2b1709c2", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7147.json b/mne-python/source/doc/sphinxext/prs/7147.json new file mode 100644 index 0000000000000000000000000000000000000000..9bb6965cd661432f2a1a2cf06b6dee84730b271e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7147.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "6c73272e1f057e4cdfb3e43063036f3d459c5d27", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 19, + "d": 10 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 4, + "d": 4 + }, + "mne/viz/backends/_pyvista.py": { + "a": 13, + "d": 6 + }, + "mne/viz/backends/base_renderer.py": { + "a": 12, + "d": 4 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7148.json b/mne-python/source/doc/sphinxext/prs/7148.json new file mode 100644 index 0000000000000000000000000000000000000000..0b0cb6d9f5e8806c173036455bbf6488ca704a23 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7148.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9b03152ebb9cc312e418f496d9c929ed01b902d2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/715.json b/mne-python/source/doc/sphinxext/prs/715.json new file mode 100644 index 0000000000000000000000000000000000000000..a3eae34fbfa6659c3b5896cfcf6dd2c70a327550 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/715.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "368e62b5361caa0514d7f8988b9139118a6d0e53", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/time_frequency/csd.py": { + "a": 5, + "d": 0 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7150.json b/mne-python/source/doc/sphinxext/prs/7150.json new file mode 100644 index 0000000000000000000000000000000000000000..325c8a8090e866e1fe0511b1ec915cffad7e5e38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7150.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cd0eff12535880cd7a6551ad4ceeff771ea8b3a9", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 0 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7151.json b/mne-python/source/doc/sphinxext/prs/7151.json new file mode 100644 index 0000000000000000000000000000000000000000..e02f21eda3ddf216b253160ee25239fa4e575e7e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7151.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "724878c5f2baa2c54ce6eaf1bdb39a47d82475b7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7153.json b/mne-python/source/doc/sphinxext/prs/7153.json new file mode 100644 index 0000000000000000000000000000000000000000..13615b29bfb05b5feea7e85ad5b47d540113c560 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7153.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "9cb664813f04be66d758c4ad6321a2a58924bfc8", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 173, + "d": 22 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 228, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 34, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 35, + "d": 6 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7155.json b/mne-python/source/doc/sphinxext/prs/7155.json new file mode 100644 index 0000000000000000000000000000000000000000..f99ee24f9f370aac32cd0a5fe65abd9f85fb34d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7155.json @@ -0,0 +1,151 @@ +{ + "merge_commit_sha": "361fa5fde83c192f705b9a0dd792858237c4b0b1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 4, + "d": 7 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 4, + "d": 5 + }, + "mne/externals/tqdm/__init__.py": { + "a": 12, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/__init__.py": { + "a": 40, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/__main__.py": { + "a": 2, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/_main.py": { + "a": 7, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/_monitor.py": { + "a": 99, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/_tqdm.py": { + "a": 7, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/_tqdm_gui.py": { + "a": 7, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/_tqdm_notebook.py": { + "a": 7, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/_tqdm_pandas.py": { + "a": 46, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/_utils.py": { + "a": 6, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/_version.py": { + "a": 59, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/auto.py": { + "a": 6, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/autonotebook.py": { + "a": 18, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/cli.py": { + "a": 228, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/contrib/__init__.py": { + "a": 10, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/gui.py": { + "a": 321, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/notebook.py": { + "a": 261, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/std.py": { + "a": 1464, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/tqdm.1": { + "a": 255, + "d": 0 + }, + "mne/externals/tqdm/_tqdm/utils.py": { + "a": 345, + "d": 0 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 3 + }, + "mne/parallel.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/flat.py": { + "a": 26, + "d": 26 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/utils/fetching.py": { + "a": 5, + "d": 16 + }, + "mne/utils/progressbar.py": { + "a": 73, + "d": 167 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 33, + "d": 23 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7156.json b/mne-python/source/doc/sphinxext/prs/7156.json new file mode 100644 index 0000000000000000000000000000000000000000..1b2d9eaa45db1eea73dc908feb15b6f14476c852 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7156.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "7de4420d5dd79866719b52d65b88f41e3ab6f96c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 17, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 112, + "d": 32 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 207, + "d": 50 + }, + "mne/proj.py": { + "a": 0, + "d": 3 + }, + "mne/tests/test_proj.py": { + "a": 0, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7157.json b/mne-python/source/doc/sphinxext/prs/7157.json new file mode 100644 index 0000000000000000000000000000000000000000..3cf1907e34b30ce0f4931fa4e155afeea78b1924 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7157.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "47d1cd50392fbb6f57b7df17573080fb8f8e4b99", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 7, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 10, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7158.json b/mne-python/source/doc/sphinxext/prs/7158.json new file mode 100644 index 0000000000000000000000000000000000000000..d975bf906c98c37eac9587e3a96a5f54a195514c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7158.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "642f4e13fedd1879bf6cad6c6d13ed28ebe68cd9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_transforms.py": { + "a": 12, + "d": 1 + }, + "mne/transforms.py": { + "a": 44, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/716.json b/mne-python/source/doc/sphinxext/prs/716.json new file mode 100644 index 0000000000000000000000000000000000000000..3fa3fb2fc7a0c26a1d2bf1a9c0cebf470f4c3aa3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/716.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "608e33bd310045ce30725e573aa6f0cd7b091b9a", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 3, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 11, + "d": 9 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 79, + "d": 0 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 161, + "d": 77 + }, + "mne/beamformer/_lcmv.py": { + "a": 60, + "d": 42 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 94, + "d": 24 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 52, + "d": 28 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 40, + "d": 21 + }, + "mne/viz.py": { + "a": 11, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7160.json b/mne-python/source/doc/sphinxext/prs/7160.json new file mode 100644 index 0000000000000000000000000000000000000000..1f7a602fa144485519841097a320ea726781241a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7160.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "eba30878532e1851b74bf99009c1582ed4591e16", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/channel_interpolation.rst": { + "a": 2, + "d": 2 + }, + "doc/_includes/inverse.rst": { + "a": 226, + "d": 129 + }, + "doc/_includes/ssp.rst": { + "a": 2, + "d": 2 + }, + "doc/overview/implementation.rst": { + "a": 1, + "d": 1 + }, + "doc/overview/matlab.rst": { + "a": 1, + "d": 1 + }, + "doc/references.bib": { + "a": 11, + "d": 12 + }, + "mne/minimum_norm/inverse.py": { + "a": 8, + "d": 15 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 12, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7163.json b/mne-python/source/doc/sphinxext/prs/7163.json new file mode 100644 index 0000000000000000000000000000000000000000..fde1e678840ef52ecfc687e5c844e1e4dc8173f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7163.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "241e11944787476271d45bb9c6bc946bf731104a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 5, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7164.json b/mne-python/source/doc/sphinxext/prs/7164.json new file mode 100644 index 0000000000000000000000000000000000000000..8ecc4e460ef803cc2f0e9f74a979142c4b00662b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7164.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c4d352adc86cff78aca589d7bae80694847d023b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 11, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7165.json b/mne-python/source/doc/sphinxext/prs/7165.json new file mode 100644 index 0000000000000000000000000000000000000000..782354c68dd438ad548510ed4885fd5e35bdb0ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7165.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6f1c79f1cfaa237e4182d283950706bbe7c841f3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7166.json b/mne-python/source/doc/sphinxext/prs/7166.json new file mode 100644 index 0000000000000000000000000000000000000000..bbf59c0e9eed16a42227dbc32cef8fbcad404898 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7166.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "96d6eef7f050de2640c5129c92c130ac70ac1071", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 14, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7167.json b/mne-python/source/doc/sphinxext/prs/7167.json new file mode 100644 index 0000000000000000000000000000000000000000..993f0d9467092c890fe92a07d874f0a0f7be16c2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7167.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "13d52a7b347aeb75ff2d5977b6e7d6c6aeeb5831", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7168.json b/mne-python/source/doc/sphinxext/prs/7168.json new file mode 100644 index 0000000000000000000000000000000000000000..fb6fc45f68ba5f4797b91bc35339f4b1919478b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7168.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4701f2ba93c4ba53519ca9edc3f8c84a77f7a26c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 39, + "d": 20 + }, + "mne/beamformer/_dics.py": { + "a": 2, + "d": 22 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 14 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 3, + "d": 5 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 52, + "d": 48 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7171.json b/mne-python/source/doc/sphinxext/prs/7171.json new file mode 100644 index 0000000000000000000000000000000000000000..89ba8ff3cc39b582bc0271d5c0f822f58ddd25e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7171.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1403b54396618888e4475a3b32026ebe4a0c7adc", + "authors": [ + { + "n": "Nicolas Barascud", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/annotations.py": { + "a": 100, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 79, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7172.json b/mne-python/source/doc/sphinxext/prs/7172.json new file mode 100644 index 0000000000000000000000000000000000000000..7cf24328b02d95d08b37169f0337310e8dfda21f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7172.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0b02ac91ae23fe50459bc11343c6aa2cae6d7c9c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7173.json b/mne-python/source/doc/sphinxext/prs/7173.json new file mode 100644 index 0000000000000000000000000000000000000000..d6bef57b580d363acbe33bc661da7b8bce0cf41d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7173.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1672c60776fb71eeccc19ddd80a404f8763cc432", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 2, + "d": 3 + }, + "mne/fixes.py": { + "a": 34, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7174.json b/mne-python/source/doc/sphinxext/prs/7174.json new file mode 100644 index 0000000000000000000000000000000000000000..65b4cef8b0aa004edf2f38f9a2b8635482c27efb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7174.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c437ed0bbcef3b6bf3a8beab2221ab5bff47722f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/reset-syntax.css": { + "a": 0, + "d": 9 + }, + "doc/_static/style.css": { + "a": 19, + "d": 1 + }, + "doc/_templates/layout.html": { + "a": 0, + "d": 2 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7175.json b/mne-python/source/doc/sphinxext/prs/7175.json new file mode 100644 index 0000000000000000000000000000000000000000..de5bee19d5072162479c88a3503a2704da8ea385 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7175.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2b75319adaa5711efcb5f5a8d6eca9484c359138", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 4 + }, + "mne/channels/montage.py": { + "a": 48, + "d": 46 + }, + "mne/channels/tests/test_montage.py": { + "a": 27, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7176.json b/mne-python/source/doc/sphinxext/prs/7176.json new file mode 100644 index 0000000000000000000000000000000000000000..c12c1c01a1123b1d2c51154c23c761673fa4a396 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7176.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d4aa1d48f1fa7c1199553101989d6311075cad73", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "doc/install/mne_python.rst": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7177.json b/mne-python/source/doc/sphinxext/prs/7177.json new file mode 100644 index 0000000000000000000000000000000000000000..4b38f7d28a2a6e02b89509d5759478dfdaba127d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7177.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "69d271e942bf1397ccb0e8832873831a98cdbe83", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/morph.py": { + "a": 5, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 9, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7178.json b/mne-python/source/doc/sphinxext/prs/7178.json new file mode 100644 index 0000000000000000000000000000000000000000..b3195f578f08d89b7a210b7fc31836bf2b7a9f17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7178.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "7a825b6bf8575d6440b262d4b03f0fa2407fa363", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 14, + "d": 18 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 4, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 3, + "d": 2 + }, + "mne/viz/montage.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/718.json b/mne-python/source/doc/sphinxext/prs/718.json new file mode 100644 index 0000000000000000000000000000000000000000..83a396307b78a8ae85a9666a6ada3b74721a0033 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/718.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6cd7d77fa2fef767f7514a884c3778a721aa870d", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/event.py": { + "a": 56, + "d": 36 + }, + "mne/tests/test_event.py": { + "a": 21, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7180.json b/mne-python/source/doc/sphinxext/prs/7180.json new file mode 100644 index 0000000000000000000000000000000000000000..6cdf487085f917b7ae36a81dc6bd02d34f9bef6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7180.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9f3b76f0c9ef71e997b522492d28d0a09c76c4bd", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 16, + "d": 11 + }, + "tutorials/epochs/plot_40_epochs_to_data_frame.py": { + "a": 155, + "d": 0 + }, + "tutorials/epochs/plot_epochs_to_data_frame.py": { + "a": 0, + "d": 252 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_erp.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7181.json b/mne-python/source/doc/sphinxext/prs/7181.json new file mode 100644 index 0000000000000000000000000000000000000000..808c6603f337d743b10317b45afec2737d25923c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7181.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ce15d3f918587dc885e54e444244b2becbd5b75a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 16, + "d": 2 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7182.json b/mne-python/source/doc/sphinxext/prs/7182.json new file mode 100644 index 0000000000000000000000000000000000000000..162063aad0878c044a22d83c63d2ce33ff741e4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7182.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "c13590ab42ea50ece798c5b6fe7874a0796c2b4e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_receptive_field_mtrf.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_3d_to_2d.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 43 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 8, + "d": 10 + }, + "mne/datasets/limo/limo.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 4 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 46, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7183.json b/mne-python/source/doc/sphinxext/prs/7183.json new file mode 100644 index 0000000000000000000000000000000000000000..a43a646f0599a385ab8cf2b7ae1892d3e9dd4d5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7183.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "67d5c87d7ab7fc6b49a68c75f3edbe49b80e68de", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/annotations.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7184.json b/mne-python/source/doc/sphinxext/prs/7184.json new file mode 100644 index 0000000000000000000000000000000000000000..b9fb6981404e84a0c9659ef1d21024caab855a18 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7184.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1ec8f801893c05ff1f5dfd01a296d271cbeacd32", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_montage.py": { + "a": 4, + "d": 2 + }, + "tutorials/misc/plot_ecog.py": { + "a": 1, + "d": 1 + }, + "tutorials/simulation/plot_creating_data_structures.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7186.json b/mne-python/source/doc/sphinxext/prs/7186.json new file mode 100644 index 0000000000000000000000000000000000000000..cb8c11a0338d4547e5d77473f1b0c31956db74c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7186.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e49718902918d61108cc356c69a51c5e066909b3", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 3, + "d": 33 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7187.json b/mne-python/source/doc/sphinxext/prs/7187.json new file mode 100644 index 0000000000000000000000000000000000000000..c3d29da774156caad064b917e960c26b23b6dcb5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7187.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0527c80feeb1c81de0ca3931fc581c7f6f4b2004", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7188.json b/mne-python/source/doc/sphinxext/prs/7188.json new file mode 100644 index 0000000000000000000000000000000000000000..7ef96443ee3b868e34de66f7b20c44e5a5248d86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7188.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "740638148806a3d73214ab6505a57a571f23204a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 58, + "d": 57 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 90, + "d": 16 + }, + "mne/viz/_brain/colormap.py": { + "a": 48, + "d": 33 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 99, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/719.json b/mne-python/source/doc/sphinxext/prs/719.json new file mode 100644 index 0000000000000000000000000000000000000000..71539edc21a980d28b93269efa8a4cb40c0d8cde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/719.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "72f5de257385b9b5f423ea4243ac6a7130306496", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 12, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 35, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7190.json b/mne-python/source/doc/sphinxext/prs/7190.json new file mode 100644 index 0000000000000000000000000000000000000000..06a331263ac304b5d620f4547653d3d32fad4384 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7190.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9d512217cf367f0b71d69602c91839dfd96298cf", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7191.json b/mne-python/source/doc/sphinxext/prs/7191.json new file mode 100644 index 0000000000000000000000000000000000000000..f6412632f2b90712edffcdff4b15833677214f19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7191.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9a2143313006d078bfeef0c69172aaef749b0263", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/utils.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7193.json b/mne-python/source/doc/sphinxext/prs/7193.json new file mode 100644 index 0000000000000000000000000000000000000000..e47663bcbfdfe56808a7dee7f32d13e8cdacd407 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7193.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6f0847ef6ac98348a313bef03406e1e6b462fca4", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/io/proj.py": { + "a": 15, + "d": 9 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 40, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 39, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7194.json b/mne-python/source/doc/sphinxext/prs/7194.json new file mode 100644 index 0000000000000000000000000000000000000000..c1e0b8cd40a56d3d3e0cbd3946cb1dae66f0e007 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7194.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bf94f340c6f8da8f48e23af3cec7f853fd6cdca3", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 25, + "d": 9 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 26, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7196.json b/mne-python/source/doc/sphinxext/prs/7196.json new file mode 100644 index 0000000000000000000000000000000000000000..7d8fdf86e38226ec54f34fbcbf2f7626c12ea61b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7196.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "44b44b1d324c95a36d51e76e7fc369d191118b3b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7197.json b/mne-python/source/doc/sphinxext/prs/7197.json new file mode 100644 index 0000000000000000000000000000000000000000..c0445a27234166fcd7d0bb11bfe666fc8d6faa78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7197.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "16503f0169f8c7246ea14d56003bb09b0ea2c298", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7199.json b/mne-python/source/doc/sphinxext/prs/7199.json new file mode 100644 index 0000000000000000000000000000000000000000..957d280b474be6274eb0f5668e9c72497708625a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7199.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f86caafd75130fa974519b9bc859a43289d98f90", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/72.json b/mne-python/source/doc/sphinxext/prs/72.json new file mode 100644 index 0000000000000000000000000000000000000000..7214230a7bc2ef5a4319456e9966d33b49366cb1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/72.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "16afe1b8739c8d0f692b796f416eaf40b937b534", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 66, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/720.json b/mne-python/source/doc/sphinxext/prs/720.json new file mode 100644 index 0000000000000000000000000000000000000000..c1ee00aecbfb9dc238577f0fb0150b7eab69d103 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/720.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e5c12b35d7a34ec5ebac73f96e7d5865e83a9883", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "mne/fiff/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 85, + "d": 0 + }, + "mne/fiff/tests/data/test_chpi_raw_hp.txt": { + "a": 5, + "d": 0 + }, + "mne/fiff/tests/data/test_chpi_raw_sss.fif": { + "a": 0, + "d": 0 + }, + "mne/fiff/tests/test_raw.py": { + "a": 21, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7200.json b/mne-python/source/doc/sphinxext/prs/7200.json new file mode 100644 index 0000000000000000000000000000000000000000..f92269604834491669b8e454a76a5ea16f700996 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7200.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a35f8cf303de97ebb9c90cbabe67ec70c61f3985", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 25, + "d": 6 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 104, + "d": 32 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 21, + "d": 4 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7202.json b/mne-python/source/doc/sphinxext/prs/7202.json new file mode 100644 index 0000000000000000000000000000000000000000..0b0788f8ae0c630605b3bb790960b7077ec1c522 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7202.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "68bed7e43adb1145dad4c3c0a769fa8785dcbe6a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 3 + }, + ".travis.yml": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7205.json b/mne-python/source/doc/sphinxext/prs/7205.json new file mode 100644 index 0000000000000000000000000000000000000000..d960cf8e447b69596e87925e75883642806a8dbf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7205.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "634e30df5fdc644684a15c43330a2abfdb5e800c", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/channels/data/neighbors/KIT-UMD-4_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/io/kit/constants.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7206.json b/mne-python/source/doc/sphinxext/prs/7206.json new file mode 100644 index 0000000000000000000000000000000000000000..9fc4825cfd678990e26916d87c85616ba7b9612a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7206.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "d2a5660db534c2d67af514b3d89b08abb67aa696", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 62, + "d": 3 + }, + "mne/evoked.py": { + "a": 53, + "d": 4 + }, + "mne/io/base.py": { + "a": 59, + "d": 189 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 4, + "d": 4 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 31, + "d": 11 + }, + "mne/source_estimate.py": { + "a": 58, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 53, + "d": 28 + }, + "mne/tests/test_evoked.py": { + "a": 36, + "d": 13 + }, + "mne/tests/test_source_estimate.py": { + "a": 32, + "d": 15 + }, + "mne/utils/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/utils/check.py": { + "a": 29, + "d": 7 + }, + "mne/utils/dataframe.py": { + "a": 88, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 61, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7207.json b/mne-python/source/doc/sphinxext/prs/7207.json new file mode 100644 index 0000000000000000000000000000000000000000..23e2600dbabffb7aa038a2cf0add38cab452c47c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7207.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b377cfa96033bcff3f2d69c95d9a88eac6bbafe4", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7214.json b/mne-python/source/doc/sphinxext/prs/7214.json new file mode 100644 index 0000000000000000000000000000000000000000..b43329b80e206a470271ff93dae73728e254fb9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7214.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3b304eb2871e523d6b183b0603b02149841160c8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7215.json b/mne-python/source/doc/sphinxext/prs/7215.json new file mode 100644 index 0000000000000000000000000000000000000000..129da8402bcdb13e5ac4b22f194cf5380d037a55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7215.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "b15366d5d30805775f5849f223d058e2a59ec37f", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 2, + "d": 32 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 65, + "d": 0 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 30, + "d": 0 + }, + "mne/preprocessing/tests/test_scalp_coupling_index.py": { + "a": 60, + "d": 0 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7218.json b/mne-python/source/doc/sphinxext/prs/7218.json new file mode 100644 index 0000000000000000000000000000000000000000..33a10b44dd13cdb9ea5e9d4aaaa320827e8f9855 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7218.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "32291b774f786b358e5cb63d7c485fa21c5a7301", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 3, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 52, + "d": 1 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 40, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7219.json b/mne-python/source/doc/sphinxext/prs/7219.json new file mode 100644 index 0000000000000000000000000000000000000000..928aaa74af27164fb96f3a087cbcf614f9230d4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7219.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2b579cb676d317d8c1ec1817583f62087bd76887", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 120, + "d": 110 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 116, + "d": 45 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 20, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7220.json b/mne-python/source/doc/sphinxext/prs/7220.json new file mode 100644 index 0000000000000000000000000000000000000000..c331895aee965ad74797dc878739be114c67d86d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7220.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "726086f29612d0fb9911196ca5127610f9e57dce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 16, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7222.json b/mne-python/source/doc/sphinxext/prs/7222.json new file mode 100644 index 0000000000000000000000000000000000000000..461c0626c784416443aeb2aefed6bf0efb61c6a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7222.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "01b90ceef3f7714d63d65e79dec860e93b68b6c0", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7223.json b/mne-python/source/doc/sphinxext/prs/7223.json new file mode 100644 index 0000000000000000000000000000000000000000..8023ffca236aa6c31d4c4b2a96949f86e6f381f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7223.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "82087a212796e9b607493391d03da636f57f0d20", + "authors": [ + { + "n": "FuTe Wong", + "e": "zuxfoucault@gmail.com" + } + ], + "changes": { + "doc/_includes/bem_model.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7224.json b/mne-python/source/doc/sphinxext/prs/7224.json new file mode 100644 index 0000000000000000000000000000000000000000..ace70a5ceef9cfd5c92d9d9bb8341249f0b7cd73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7224.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1ef6ebeccb4361da5ea18a4a35f731cd9a1bfc74", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 0 + }, + "examples/visualization/plot_montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 19, + "d": 28 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7226.json b/mne-python/source/doc/sphinxext/prs/7226.json new file mode 100644 index 0000000000000000000000000000000000000000..218279e3a29b1ea879766e9bfea89b8fed724a2d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7226.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a1dea207a0c0cb00f255a705311329822a15ef1a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 20, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7227.json b/mne-python/source/doc/sphinxext/prs/7227.json new file mode 100644 index 0000000000000000000000000000000000000000..063e75fb015f571028c4420b844d08623f689bb1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7227.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "f6e036d8191b00fc407cdcbc4965f71d84a9878d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 30, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 144, + "d": 68 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 16, + "d": 11 + }, + "mne/viz/backends/_pyvista.py": { + "a": 20, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 37, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/723.json b/mne-python/source/doc/sphinxext/prs/723.json new file mode 100644 index 0000000000000000000000000000000000000000..bab5ef3606b713bd9901fc6305b13d85f22672ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/723.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "73b5ba03e827aab59346109cc0995e95a555b041", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7231.json b/mne-python/source/doc/sphinxext/prs/7231.json new file mode 100644 index 0000000000000000000000000000000000000000..62ca975d38e49be67617ed1d695ffee31b2156c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7231.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "291d8529819a454b26d4056f1f3fc069c4e8c351", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7236.json b/mne-python/source/doc/sphinxext/prs/7236.json new file mode 100644 index 0000000000000000000000000000000000000000..9b0dbdbdfd8786de8840d70448adc65e12bcc2a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7236.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "328e026795b787cbe6acd7ad2a8ea1535bad28a3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7237.json b/mne-python/source/doc/sphinxext/prs/7237.json new file mode 100644 index 0000000000000000000000000000000000000000..6841b3f290a7e0662fcd6c469554c52341c6b00e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7237.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c45aec9bf94cadc97f7ccaaec0a6c06a12750f1c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/overview/faq.rst": { + "a": 76, + "d": 2 + }, + "mne/bem.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7238.json b/mne-python/source/doc/sphinxext/prs/7238.json new file mode 100644 index 0000000000000000000000000000000000000000..b9cc944ddb95d6d79617ad33cd66c3a319393cb6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7238.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2147495a620c0e6008ff7d34dcfdf5490f8d323a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/724.json b/mne-python/source/doc/sphinxext/prs/724.json new file mode 100644 index 0000000000000000000000000000000000000000..cb7d522b212d6b8f0745b3a6eb6ed5e431a2a44e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/724.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c5d3f9c23aa91342d0be1f6eb70bbf174be649e6", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 36, + "d": 50 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 16, + "d": 2 + }, + "mne/utils.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7240.json b/mne-python/source/doc/sphinxext/prs/7240.json new file mode 100644 index 0000000000000000000000000000000000000000..3647cf68287b580db536c575e771d1a787996068 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7240.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "89f453882476d3f701642ed46271e2147c0edc92", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7242.json b/mne-python/source/doc/sphinxext/prs/7242.json new file mode 100644 index 0000000000000000000000000000000000000000..ac1d0adb4a312ba157d31ffa00ffc1e3a452256b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7242.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1bab4a5a0637a04769272dd3a0f75e1661f63f1d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 4 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7245.json b/mne-python/source/doc/sphinxext/prs/7245.json new file mode 100644 index 0000000000000000000000000000000000000000..f63c4ca01b279ff87e3644aacaeb5a8ebc2a4997 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7245.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8b3ef2ddddd0e1e351454c987df13cfc7be36f6b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/dipole.py": { + "a": 140, + "d": 44 + }, + "mne/tests/test_dipole.py": { + "a": 65, + "d": 3 + }, + "setup.cfg": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7246.json b/mne-python/source/doc/sphinxext/prs/7246.json new file mode 100644 index 0000000000000000000000000000000000000000..a4d3e46e8ec54cae929179d6be49746bc92b8669 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7246.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "17c5670b0f52243ee9e250f93250fd61a0d8edac", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/overview/index.rst": { + "a": 1, + "d": 0 + }, + "doc/overview/roadmap.rst": { + "a": 177, + "d": 0 + }, + "doc/sphinxext/gh_substitutions.py": { + "a": 30, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7247.json b/mne-python/source/doc/sphinxext/prs/7247.json new file mode 100644 index 0000000000000000000000000000000000000000..e46338a702449be902b88f2ce71ed855f9132b08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7247.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "1a36309bcef356f06db8f51fd206afb1b4a30ec5", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 6, + "d": 3 + }, + "mne/source_space.py": { + "a": 4, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 32, + "d": 6 + }, + "mne/viz/_brain/_brain.py": { + "a": 27, + "d": 25 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 234, + "d": 8 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 117, + "d": 25 + }, + "mne/viz/backends/_pyvista.py": { + "a": 46, + "d": 17 + }, + "mne/viz/backends/renderer.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7249.json b/mne-python/source/doc/sphinxext/prs/7249.json new file mode 100644 index 0000000000000000000000000000000000000000..eaeca5b07b378cbc510f53d8924b41128939eb5b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7249.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "91811222a9f271f6f3c366998a43f8512a2f2c10", + "authors": [ + { + "n": "FuTe Wong", + "e": "zuxfoucault@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7252.json b/mne-python/source/doc/sphinxext/prs/7252.json new file mode 100644 index 0000000000000000000000000000000000000000..47e6b18dbbfe0c050a44542ae107733f21353369 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7252.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c2029d684cdc12daa7542bf9a02a1907ecfef179", + "authors": [ + { + "n": "Sebastian Major", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 11, + "d": 6 + }, + "mne/io/brainvision/tests/data/test_mixed_lowpass.vhdr": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7253.json b/mne-python/source/doc/sphinxext/prs/7253.json new file mode 100644 index 0000000000000000000000000000000000000000..4a00bffd49ec50b174dc265f4ececccde2224510 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7253.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0e664011756a5e2f59a2dc6cc7c0327f3eaa835d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 3, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7256.json b/mne-python/source/doc/sphinxext/prs/7256.json new file mode 100644 index 0000000000000000000000000000000000000000..4972249c9a03d181892ce7179a6e889ae589e38f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7256.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "837d63ba9f9a43ee229306c508cad4f2eb2320cc", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7257.json b/mne-python/source/doc/sphinxext/prs/7257.json new file mode 100644 index 0000000000000000000000000000000000000000..e4b3707ca683ef381acda8731fd006bcc98fbd7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7257.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "7f6120bf020ec39dfb58a5f172f5a9c1984093cd", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 195, + "d": 36 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 141, + "d": 9 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 27, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 2, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7258.json b/mne-python/source/doc/sphinxext/prs/7258.json new file mode 100644 index 0000000000000000000000000000000000000000..0ce5d6973af4cdbbe59ed89da3197bd51aa3f440 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7258.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "96911d657bee2077a04b8e35d32c816ef74135f3", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "examples/visualization/plot_evoked_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7261.json b/mne-python/source/doc/sphinxext/prs/7261.json new file mode 100644 index 0000000000000000000000000000000000000000..7045118e1180c963399f44b7948f4ee27281413c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7261.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "634f11d9c220b3725f9eb72cd9cb254f4fc4d5cb", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7262.json b/mne-python/source/doc/sphinxext/prs/7262.json new file mode 100644 index 0000000000000000000000000000000000000000..e7a19c643e7b06a2bf0716f1d5d3d0235562743b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7262.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7b1918b0c46a8e5a8d902276552672c20ec8f2d6", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/curry/curry.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 25, + "d": 71 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 3, + "d": 7 + }, + "mne/io/utils.py": { + "a": 0, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7263.json b/mne-python/source/doc/sphinxext/prs/7263.json new file mode 100644 index 0000000000000000000000000000000000000000..9a9b91f3a2db985792843c67fc671154cf36e1ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7263.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bd3d30cb1448a32fe9d6fe824c0d1265054f4bd1", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 10 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 47, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7264.json b/mne-python/source/doc/sphinxext/prs/7264.json new file mode 100644 index 0000000000000000000000000000000000000000..df7b8495600e72d8c06be79ee1d79e3e8b0b7c0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7264.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d977b5a87d8d6aaf0bcc5368fd0836c2c14d7c66", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/search_light.py": { + "a": 4, + "d": 5 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7265.json b/mne-python/source/doc/sphinxext/prs/7265.json new file mode 100644 index 0000000000000000000000000000000000000000..10af597fbe5c050eb41665896ad33e41b911e286 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7265.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "845e5d0cf764263d93a433a8fd0484f99c24d62f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/decoding/base.py": { + "a": 15, + "d": 3 + }, + "mne/decoding/tests/test_base.py": { + "a": 132, + "d": 27 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/transformer.py": { + "a": 17, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7266.json b/mne-python/source/doc/sphinxext/prs/7266.json new file mode 100644 index 0000000000000000000000000000000000000000..640304009774ebe05438bd649bd78b06b70677d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7266.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "03eaec1c3bd1a11b30d052b41d8452ca3cdda58c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 0, + "d": 2 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 2, + "d": 3 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 34, + "d": 14 + }, + "mne/tests/test_report.py": { + "a": 16, + "d": 20 + }, + "mne/tests/test_surface.py": { + "a": 3, + "d": 5 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 7 + }, + "mne/viz/_brain/surface.py": { + "a": 8, + "d": 10 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 16, + "d": 18 + }, + "mne/viz/backends/_pyvista.py": { + "a": 24, + "d": 25 + }, + "mne/viz/backends/_utils.py": { + "a": 0, + "d": 10 + }, + "mne/viz/backends/renderer.py": { + "a": 49, + "d": 34 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 8, + "d": 8 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7267.json b/mne-python/source/doc/sphinxext/prs/7267.json new file mode 100644 index 0000000000000000000000000000000000000000..7219af78b35d772b24e85b52add36ccce3d072a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7267.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "26b81437485f5287daa175c256608f011c185b67", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7269.json b/mne-python/source/doc/sphinxext/prs/7269.json new file mode 100644 index 0000000000000000000000000000000000000000..2474c2cb5d9ae43d4f83ce1b65bd7c35d34e52bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7269.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "14d0f416d82e6a876a5a33de8349a77d92e272bd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 7 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 3, + "d": 5 + }, + "mne/source_space.py": { + "a": 2, + "d": 4 + }, + "mne/surface.py": { + "a": 95, + "d": 16 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 5 + }, + "mne/tests/test_surface.py": { + "a": 21, + "d": 3 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 19, + "d": 2 + }, + "mne/utils/check.py": { + "a": 16, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7271.json b/mne-python/source/doc/sphinxext/prs/7271.json new file mode 100644 index 0000000000000000000000000000000000000000..c6855b30385b3cba24b4a71e1d0c85965c57c40a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7271.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6337b1e9bcd9fcdc5db15211acb8ead64015c242", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 12, + "d": 12 + }, + "mne/viz/backends/renderer.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7272.json b/mne-python/source/doc/sphinxext/prs/7272.json new file mode 100644 index 0000000000000000000000000000000000000000..6a9d1f8545ed4197bc7915b0348a745b4968d90c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7272.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1213e4c8c0c1765a56a36bc706ea9a89cbb856a1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/_coreg_gui.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_marker_gui.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_viewer.py": { + "a": 3, + "d": 2 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 32, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7273.json b/mne-python/source/doc/sphinxext/prs/7273.json new file mode 100644 index 0000000000000000000000000000000000000000..a89897828a2fc4fd6a1ddefdbd9a2d24a580cb8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7273.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f529c5f127c62d8a4d548b8c2a113a990398ebb2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/epochs.py": { + "a": 24, + "d": 7 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 0 + }, + "mne/utils/mixin.py": { + "a": 17, + "d": 13 + }, + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7276.json b/mne-python/source/doc/sphinxext/prs/7276.json new file mode 100644 index 0000000000000000000000000000000000000000..1f65ddbdcb6ea84a569ec3290d1807f90a9124b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7276.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "00476f86595275683ef5c734665598f823e1c332", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 7, + "d": 2 + }, + "mne/viz/backends/renderer.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7278.json b/mne-python/source/doc/sphinxext/prs/7278.json new file mode 100644 index 0000000000000000000000000000000000000000..fcd9837a1498823dc4a19fa73797163d7c8a3348 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7278.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8faa5f776015c06e899737cdd0fec69233f2b8ba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 8, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7279.json b/mne-python/source/doc/sphinxext/prs/7279.json new file mode 100644 index 0000000000000000000000000000000000000000..292183846d628f47a9b30f90c11bdce77b8935cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7279.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f474eb196eca50104f09948c6a4215d628a971f5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/surface.py": { + "a": 3, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7280.json b/mne-python/source/doc/sphinxext/prs/7280.json new file mode 100644 index 0000000000000000000000000000000000000000..18799192b2ecbbacc64e556441f366dde866c190 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7280.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3a5197d6fc3ca8ffcb20b5d8e25e1aa7c30961d4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 29, + "d": 6 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 14 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 11, + "d": 5 + }, + "mne/viz/backends/renderer.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7281.json b/mne-python/source/doc/sphinxext/prs/7281.json new file mode 100644 index 0000000000000000000000000000000000000000..8ca434f8f81fcb5282e71d6cc03f1b7b0a78efcf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7281.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "5044aaebb242068da31bdd6fbb4782e8ea0adf9a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 115, + "d": 70 + }, + "mne/viz/_brain/_brain.py": { + "a": 9, + "d": 7 + }, + "mne/viz/_brain/colormap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 72, + "d": 5 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7284.json b/mne-python/source/doc/sphinxext/prs/7284.json new file mode 100644 index 0000000000000000000000000000000000000000..a611c1719411c374fdf2d891f39cbe5f904d43ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7284.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "c081fbd58b8647eeeadc7c9ae11741daf8a4c2e9", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 10, + "d": 0 + }, + "mne/externals/h5io/_h5io.py": { + "a": 150, + "d": 7 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 3, + "d": 12 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 7, + "d": 12 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 8, + "d": 23 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 12, + "d": 18 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7285.json b/mne-python/source/doc/sphinxext/prs/7285.json new file mode 100644 index 0000000000000000000000000000000000000000..6aaef9771dd0e1e9e78230c140fe1b8804a31b6c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7285.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f0f3b4d828bebff58e30841c5d4402b2823cc505", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 25, + "d": 6 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7286.json b/mne-python/source/doc/sphinxext/prs/7286.json new file mode 100644 index 0000000000000000000000000000000000000000..1a459a6c62a97660f909eac15e3989999113fbde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7286.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "43098b81696f30ab5171a3b3b9064b191e961006", + "authors": [ + { + "n": "Geoff Brookshire", + "e": "Geoff.Brookshire@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7288.json b/mne-python/source/doc/sphinxext/prs/7288.json new file mode 100644 index 0000000000000000000000000000000000000000..9570d0f422878d4099b1b0cbb7fa4bca7547e96e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7288.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2434a41d5ccc5729371a2de1d7ad9b946b168fd2", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 9, + "d": 4 + }, + "mne/tests/test_annotations.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7289.json b/mne-python/source/doc/sphinxext/prs/7289.json new file mode 100644 index 0000000000000000000000000000000000000000..745f81eee71046e9e2b0b60c51975962e6445c9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7289.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "33f224d4486b4b13facf543aae7e1867e3606898", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/surface.py": { + "a": 20, + "d": 4 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7290.json b/mne-python/source/doc/sphinxext/prs/7290.json new file mode 100644 index 0000000000000000000000000000000000000000..d04e180bc838c08990ae0adfee4528969b2c7103 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7290.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "178d7bf345d9dbe6248cf939a1b2f7ce63ec04ab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "doc/glossary.rst": { + "a": 3, + "d": 3 + }, + "doc/python_reference.rst": { + "a": 4, + "d": 1 + }, + "examples/preprocessing/plot_artifact_detection.py": { + "a": 6, + "d": 5 + }, + "examples/preprocessing/plot_head_positions.py": { + "a": 0, + "d": 33 + }, + "mne/chpi.py": { + "a": 581, + "d": 599 + }, + "mne/dipole.py": { + "a": 7, + "d": 5 + }, + "mne/fixes.py": { + "a": 21, + "d": 0 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 4, + "d": 4 + }, + "mne/io/artemis123/artemis123.py": { + "a": 15, + "d": 5 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 10, + "d": 6 + }, + "mne/io/base.py": { + "a": 19, + "d": 18 + }, + "mne/io/pick.py": { + "a": 14, + "d": 9 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/maxwell.py": { + "a": 25, + "d": 23 + }, + "mne/preprocessing/ssp.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 10, + "d": 8 + }, + "mne/simulation/tests/test_raw.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 166, + "d": 46 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 14, + "d": 1 + }, + "mne/transforms.py": { + "a": 51, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 39, + "d": 0 + }, + "mne/utils/progressbar.py": { + "a": 11, + "d": 5 + }, + "tutorials/preprocessing/plot_59_head_positions.py": { + "a": 80, + "d": 0 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7292.json b/mne-python/source/doc/sphinxext/prs/7292.json new file mode 100644 index 0000000000000000000000000000000000000000..02a6daa625ae76da9a33b6e9abb1bb10093cc098 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7292.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4d51e1443a58b8dff8ee331e272690e4f56d499a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/renderer.py": { + "a": 31, + "d": 23 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7294.json b/mne-python/source/doc/sphinxext/prs/7294.json new file mode 100644 index 0000000000000000000000000000000000000000..7304205b3316873f040403e2c4b0a8d758a8e78a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7294.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "95ad0eec8a2e1e9c7c74e25852157e650aea7df0", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 0, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 0, + "d": 2 + }, + "environment.yml": { + "a": 0, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 6 + }, + "mne/viz/_brain/_brain.py": { + "a": 44, + "d": 198 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 9, + "d": 141 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 27 + }, + "mne/viz/backends/renderer.py": { + "a": 2, + "d": 2 + }, + "requirements.txt": { + "a": 0, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7295.json b/mne-python/source/doc/sphinxext/prs/7295.json new file mode 100644 index 0000000000000000000000000000000000000000..8540de7c55cecc06d6eec4672b1e6ce9507bf350 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7295.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9081ae329c95b4657dea833f607d7d0bded4cb8a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_3d.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7297.json b/mne-python/source/doc/sphinxext/prs/7297.json new file mode 100644 index 0000000000000000000000000000000000000000..edfcdd79bc02ff9280f8f23f05368792d85a41b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7297.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "0bb0eeb92928ce18c75280fb7740bb9017521fc6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 5, + "d": 7 + }, + "mne/io/ctf/trans.py": { + "a": 2, + "d": 2 + }, + "mne/io/curry/curry.py": { + "a": 183, + "d": 52 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 173, + "d": 5 + }, + "mne/surface.py": { + "a": 11, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 9, + "d": 1 + }, + "mne/utils/check.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7298.json b/mne-python/source/doc/sphinxext/prs/7298.json new file mode 100644 index 0000000000000000000000000000000000000000..d7f4cc3a3043368984091cd8512b05a2da6fdac8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7298.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "325bfc30c6533b63b3fb675fbf34df14b5ddc6e6", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 6, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7299.json b/mne-python/source/doc/sphinxext/prs/7299.json new file mode 100644 index 0000000000000000000000000000000000000000..377973a85d2e1ec13fc8d8333c398cdcfd397c53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7299.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "be4dfac706828d23580162381c543ac172810bd7", + "authors": [ + { + "n": "Sophie Herbst", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/73.json b/mne-python/source/doc/sphinxext/prs/73.json new file mode 100644 index 0000000000000000000000000000000000000000..9f337adfec3c04debdcf8ca8210294e5fafe4d8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/73.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0e7f195aa1b48ef7a80ed7a4cb238aa48f4c43f4", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/plot_simulate_evoked_data.py": { + "a": 3, + "d": 3 + }, + "mne/simulation/evoked.py": { + "a": 8, + "d": 8 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 19, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/730.json b/mne-python/source/doc/sphinxext/prs/730.json new file mode 100644 index 0000000000000000000000000000000000000000..557992099031e7fe419668e939dd719e6f90066c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/730.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "205701479f2b8f8d8707b66f71039ce6fe6a7a02", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_label_from_stc.py": { + "a": 105, + "d": 0 + }, + "mne/label.py": { + "a": 78, + "d": 27 + }, + "mne/source_estimate.py": { + "a": 15, + "d": 3 + }, + "mne/tests/test_label.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7303.json b/mne-python/source/doc/sphinxext/prs/7303.json new file mode 100644 index 0000000000000000000000000000000000000000..7c926597f2adcdfbb972ef23d88e8a423728e33b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7303.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f76c7b38614af324b5884176c1d526d960bca249", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 6, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 15, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7304.json b/mne-python/source/doc/sphinxext/prs/7304.json new file mode 100644 index 0000000000000000000000000000000000000000..b0cc9bcb4076e58e6aa7d39fad70f29b61d423f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7304.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "478d38ead72139bc6bb2e354e29438f7b5519ba2", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 7, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 45, + "d": 3 + }, + "mne/io/fieldtrip/utils.py": { + "a": 18, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7305.json b/mne-python/source/doc/sphinxext/prs/7305.json new file mode 100644 index 0000000000000000000000000000000000000000..552b7f5ef53657100697990b66b6fad19e0a1c65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7305.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "18259f59917f105aea80242daba0dbf309f89abc", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 39, + "d": 11 + }, + "mne/viz/utils.py": { + "a": 14, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7307.json b/mne-python/source/doc/sphinxext/prs/7307.json new file mode 100644 index 0000000000000000000000000000000000000000..fd34d3c88d85623a4e08e9a36922b6fe943df3ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7307.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b49528206273a5b5bcddd65cfa439ad241df1b24", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7309.json b/mne-python/source/doc/sphinxext/prs/7309.json new file mode 100644 index 0000000000000000000000000000000000000000..dfb0c6c02659770e710c92804c67c130c2e5d1b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7309.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "963278c135ffd7972c42d2060491177fd527a7cd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/731.json b/mne-python/source/doc/sphinxext/prs/731.json new file mode 100644 index 0000000000000000000000000000000000000000..2a8b773e30a4d8b51909853079a67ae12165e9e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/731.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "c4bccec6459e26b2a1f76e5e40e26d0279a9e61a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "bin/mne_make_scalp_surfaces.py": { + "a": 115, + "d": 0 + }, + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 9, + "d": 0 + }, + "examples/plot_decimate_head_surface.py": { + "a": 40, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 56, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 22, + "d": 2 + }, + "mne/utils.py": { + "a": 21, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7312.json b/mne-python/source/doc/sphinxext/prs/7312.json new file mode 100644 index 0000000000000000000000000000000000000000..76e9873d14522b9c68bb2d2be9b71c721b92fa2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7312.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "740fdce08d8de0cbfc232806686fcaf45de8dc56", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/overview/roadmap.rst": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7314.json b/mne-python/source/doc/sphinxext/prs/7314.json new file mode 100644 index 0000000000000000000000000000000000000000..a0154246276f625dd3736c2a208534d41803c1cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7314.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8de73099c98679e0d6c9a5784e2d63ec95c5d4ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 9, + "d": 4 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7317.json b/mne-python/source/doc/sphinxext/prs/7317.json new file mode 100644 index 0000000000000000000000000000000000000000..3ef249c3240445e5acecc4f80b3031b6b42a0ed5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7317.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0226c5ee292f11894c57c72858e743cce3fdd008", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 2, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7318.json b/mne-python/source/doc/sphinxext/prs/7318.json new file mode 100644 index 0000000000000000000000000000000000000000..a1a226b9a2ac2e0683128d7aaad149e6488b7791 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7318.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b0bdabd8f1a39db62b19fc4e9a27afa012047fc6", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7319.json b/mne-python/source/doc/sphinxext/prs/7319.json new file mode 100644 index 0000000000000000000000000000000000000000..ea57a47ec550548ebabffb54682bd511173d1274 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7319.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5152d60bbc1714d4920decce3e9f8416d8d86598", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_scalp_coupling_index.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7322.json b/mne-python/source/doc/sphinxext/prs/7322.json new file mode 100644 index 0000000000000000000000000000000000000000..eb37cf8528fb09e11d4f264c10197545244888e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7322.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a43db5731fad6bd1abed1faab0e723bbc38e7fff", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7324.json b/mne-python/source/doc/sphinxext/prs/7324.json new file mode 100644 index 0000000000000000000000000000000000000000..59ff6bacb37ddf70317e7a68cb066c67661f0ec2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7324.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2b9a707f1600af9f120df20b15e55d6c6ce18c62", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 9, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7325.json b/mne-python/source/doc/sphinxext/prs/7325.json new file mode 100644 index 0000000000000000000000000000000000000000..2ffad533c47f9a202b807a32f25853cb247aeb62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7325.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "ee47fc349ae1a5c907f84c8c8ee47526afc976ec", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 11, + "d": 10 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 3, + "d": 1 + }, + "mne/coreg.py": { + "a": 46, + "d": 31 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/trans.py": { + "a": 13, + "d": 69 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 116, + "d": 5 + }, + "mne/transforms.py": { + "a": 72, + "d": 10 + }, + "mne/utils/tests/test_numerics.py": { + "a": 4, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7326.json b/mne-python/source/doc/sphinxext/prs/7326.json new file mode 100644 index 0000000000000000000000000000000000000000..ee03d7083008017f58de728100944ecc011f6071 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7326.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "1a3b63941c600cfa755d84f9b509bafacae11892", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 12, + "d": 5 + }, + "mne/evoked.py": { + "a": 12, + "d": 5 + }, + "mne/io/base.py": { + "a": 16, + "d": 10 + }, + "mne/source_estimate.py": { + "a": 9, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/dataframe.py": { + "a": 11, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7327.json b/mne-python/source/doc/sphinxext/prs/7327.json new file mode 100644 index 0000000000000000000000000000000000000000..b4a6c1a6712ab5d02905fd8de381fe4077825826 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7327.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3f6dc9b496132f4673c26e4cd4e3c92de961a887", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 1, + "d": 3 + }, + "mne/channels/montage.py": { + "a": 8, + "d": 10 + }, + "mne/channels/tests/test_montage.py": { + "a": 7, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7328.json b/mne-python/source/doc/sphinxext/prs/7328.json new file mode 100644 index 0000000000000000000000000000000000000000..bebc872b8d0895891d119bad6303fcf215687dd8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7328.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6c0df72a979bd871b63f53e39d0afde8d8d42aca", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 24, + "d": 10 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 32, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7329.json b/mne-python/source/doc/sphinxext/prs/7329.json new file mode 100644 index 0000000000000000000000000000000000000000..d63d7b1b60197f95cbaa09f675b6eefec361da75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7329.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "72e22a543f4b7c3404a04270b3fc67c6f3bca8a5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/infomax_.py": { + "a": 10, + "d": 2 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/733.json b/mne-python/source/doc/sphinxext/prs/733.json new file mode 100644 index 0000000000000000000000000000000000000000..467d8e7b919fafacd5dd03b9afea753ddc399b95 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/733.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "620609f79b40b17cb79b3d60dc5414352198f828", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz.py": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7331.json b/mne-python/source/doc/sphinxext/prs/7331.json new file mode 100644 index 0000000000000000000000000000000000000000..42842dd53fbfa39e5c545c5718bfbf12682f7a11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7331.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "61382c1805efa5c6333d83ad27d24268b6fd2e13", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/overview/migrating.rst": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 12, + "d": 5 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 27, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7333.json b/mne-python/source/doc/sphinxext/prs/7333.json new file mode 100644 index 0000000000000000000000000000000000000000..27e6f8f67e54165d61a97de718e3b591f6d962e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7333.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d9e729fb8c7379437f6f9647c494f76a67e489a9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + ".travis.yml": { + "a": 1, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 13, + "d": 11 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 8, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7336.json b/mne-python/source/doc/sphinxext/prs/7336.json new file mode 100644 index 0000000000000000000000000000000000000000..aebb8ce2ed9f256858442c7a6344c0a5c11c49d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7336.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fa38f2b24c65cdc16e65776a2912f255c2807343", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 29, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7337.json b/mne-python/source/doc/sphinxext/prs/7337.json new file mode 100644 index 0000000000000000000000000000000000000000..b3882dc71804be2be3037e8b9dc720744c97068a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7337.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4968e692ac4626930aac2a25035ca9afc1a940b5", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7338.json b/mne-python/source/doc/sphinxext/prs/7338.json new file mode 100644 index 0000000000000000000000000000000000000000..74333a8edf6d3d011140535c9cb9ac9b4f41df68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7338.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fc49cde2f3a27d666624dc58dde1e367d272f950", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 11, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7339.json b/mne-python/source/doc/sphinxext/prs/7339.json new file mode 100644 index 0000000000000000000000000000000000000000..c29e92c5d74598f558fbe98c99508200d7a67a51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7339.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "da7b6c24dacdddec846cf12b33084a2cab9e78c2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 4, + "d": 4 + }, + "mne/simulation/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 36, + "d": 8 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_misc.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/734.json b/mne-python/source/doc/sphinxext/prs/734.json new file mode 100644 index 0000000000000000000000000000000000000000..9ab123edc145741dfd53973092bb6405668ea787 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/734.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "df97a0c35a9959c3641c7f0bfcb5e7ea7854c8be", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "bin/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 6 + }, + "examples/plot_decimate_head_surface.py": { + "a": 9, + "d": 10 + }, + "mne/surface.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7342.json b/mne-python/source/doc/sphinxext/prs/7342.json new file mode 100644 index 0000000000000000000000000000000000000000..8612ac7e22cdc3f92bcdb70700bc50b24499326c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7342.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e3c4474f3b7d932ca90ae264254e3432ee5c5d18", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 20, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7343.json b/mne-python/source/doc/sphinxext/prs/7343.json new file mode 100644 index 0000000000000000000000000000000000000000..bb4e0dfcd9ebedcb8ffc7b89ee07f48b5f182f14 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7343.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "cc24a220a4e421f527e7616773c79dbccd04f4ed", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 24, + "d": 14 + }, + "mne/viz/tests/test_misc.py": { + "a": 5, + "d": 3 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7344.json b/mne-python/source/doc/sphinxext/prs/7344.json new file mode 100644 index 0000000000000000000000000000000000000000..f57e7b324631e3d60f1b603e6efdb348852e666b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7344.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dae99dfa17baba405d2d1068950426f2535ea1ed", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 6, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7346.json b/mne-python/source/doc/sphinxext/prs/7346.json new file mode 100644 index 0000000000000000000000000000000000000000..85361098e5384ef9d96efb062f01c7c948b17b75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7346.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "20a6c4d8f3a074d36850b2572216628c19b6d2d2", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/preprocessing/nirs/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 31, + "d": 3 + }, + "mne/preprocessing/tests/test_nirs.py": { + "a": 81, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7348.json b/mne-python/source/doc/sphinxext/prs/7348.json new file mode 100644 index 0000000000000000000000000000000000000000..d221887ae09fecd3364bf082bc506eb3a50355b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7348.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "afab0e1e9122997147008437aa4f5aa0c74a57cc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/inverse.rst": { + "a": 68, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 11, + "d": 0 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/fixes.py": { + "a": 0, + "d": 27 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 116, + "d": 98 + }, + "mne/minimum_norm/inverse.py": { + "a": 26, + "d": 24 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 139, + "d": 60 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 1 + }, + "mne/utils/linalg.py": { + "a": 29, + "d": 0 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 3, + "d": 5 + }, + "tutorials/source-modeling/plot_mne_solutions.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7349.json b/mne-python/source/doc/sphinxext/prs/7349.json new file mode 100644 index 0000000000000000000000000000000000000000..9757a1d95db7e82efd35b98ac6a125063fe71ae8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7349.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "beeb35dc8b92c55811521152c7d6ea03cbed7b56", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 17, + "d": 79 + }, + "mne/minimum_norm/inverse.py": { + "a": 46, + "d": 18 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 22, + "d": 17 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 27, + "d": 12 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 3 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 9, + "d": 3 + }, + "mne/source_space.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 81, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7351.json b/mne-python/source/doc/sphinxext/prs/7351.json new file mode 100644 index 0000000000000000000000000000000000000000..84fda6f09dff835673b0518f007f2e571d640872 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7351.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b75bfec5d184784bdc5f2f208e8b05bdc018c9a4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7352.json b/mne-python/source/doc/sphinxext/prs/7352.json new file mode 100644 index 0000000000000000000000000000000000000000..0acf2ba3533aa4ee03fe1981a07b3b1f5db719e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7352.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "00fea96eab2198dcc1c241bd2d305e9ff0fb014d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7353.json b/mne-python/source/doc/sphinxext/prs/7353.json new file mode 100644 index 0000000000000000000000000000000000000000..aa58593e82bdcd15ef6d52aa2c61bfd9999e35dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7353.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8d22915819d85f82a27c36b9c1b06c0b2132fbe6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 315, + "d": 0 + }, + "tutorials/evoked/plot_object_evoked.py": { + "a": 0, + "d": 89 + }, + "tutorials/evoked/plot_visualize_evoked.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7356.json b/mne-python/source/doc/sphinxext/prs/7356.json new file mode 100644 index 0000000000000000000000000000000000000000..4072df7b5fb1d5020564226f46bccf6b384a1905 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7356.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5b9166cf6b2e3ba8c5455445ae21c61f875bf93c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/constants.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7357.json b/mne-python/source/doc/sphinxext/prs/7357.json new file mode 100644 index 0000000000000000000000000000000000000000..2a6633fc58a2b9f179351bb0ae00ee2fc3e6ae89 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7357.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "db89fd67b04f934ce0bec0a7ffc105ede50e5b71", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7358.json b/mne-python/source/doc/sphinxext/prs/7358.json new file mode 100644 index 0000000000000000000000000000000000000000..14d880bcf4c8d43f1903158d6a872c325c541b8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7358.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "56f98a7b7a08ebf31ffc0b0a64021619fd42c5c5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 24, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7361.json b/mne-python/source/doc/sphinxext/prs/7361.json new file mode 100644 index 0000000000000000000000000000000000000000..e72a9dbba3c1f15f17e0dfad8d37e1d1241d5e97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7361.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e6c0a1bd8ed8a9eb9428eb01a70641f8272c3a06", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7362.json b/mne-python/source/doc/sphinxext/prs/7362.json new file mode 100644 index 0000000000000000000000000000000000000000..84e8f481a2709a8c83b713faf73bb04caebca4ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7362.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7d691d2f3462234bb3f8fe75a75e449750708bf6", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/viz/circle.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7364.json b/mne-python/source/doc/sphinxext/prs/7364.json new file mode 100644 index 0000000000000000000000000000000000000000..7a9efbb04fcdf330a20123a0b67133905115c52f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7364.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8675bfaa98570e30cdb63a40dba72ecb93b8ef11", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 0 + }, + "mne/io/brainvision/tests/data/test.hpts": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7366.json b/mne-python/source/doc/sphinxext/prs/7366.json new file mode 100644 index 0000000000000000000000000000000000000000..c81d8e671ced81f150b9d5f5c70d53df28f92dac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7366.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "4400c2bcc45f4e673fa011f396184486a1923ba6", + "authors": [ + { + "n": "Sophie Herbst", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 32, + "d": 0 + }, + "mne/evoked.py": { + "a": 5, + "d": 2 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 41, + "d": 17 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 22, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7367.json b/mne-python/source/doc/sphinxext/prs/7367.json new file mode 100644 index 0000000000000000000000000000000000000000..643191b01aa48cce3a13d49e4f3b11af7f8b97ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7367.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "076f8d5a4c9f109714e3bc2e11085cae3e539928", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 6, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 57, + "d": 42 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7369.json b/mne-python/source/doc/sphinxext/prs/7369.json new file mode 100644 index 0000000000000000000000000000000000000000..70ad984be388ef857339796ffcab593a00497524 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7369.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c5aa0b88211eef54346539127fe80fede09f0ac8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 10, + "d": 9 + }, + "mne/tests/test_cov.py": { + "a": 53, + "d": 25 + }, + "mne/utils/_testing.py": { + "a": 4, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7370.json b/mne-python/source/doc/sphinxext/prs/7370.json new file mode 100644 index 0000000000000000000000000000000000000000..b14ec641b08e802722bf7168109dca90a9d7f01c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7370.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "914f1ee2fb38e8e76fa0c8c7ce88b53fe68dca54", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 3, + "d": 4 + }, + "mne/commands/tests/test_commands.py": { + "a": 11, + "d": 10 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_scalp_coupling_index.py": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 3, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 20, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7371.json b/mne-python/source/doc/sphinxext/prs/7371.json new file mode 100644 index 0000000000000000000000000000000000000000..5f92f7d27c690a2198b61b2c11814fe53e634851 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7371.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1acbcfbad1a5a9d2bebb54c1c0f2b9b77c08519b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/overview/roadmap.rst": { + "a": 29, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7372.json b/mne-python/source/doc/sphinxext/prs/7372.json new file mode 100644 index 0000000000000000000000000000000000000000..bef90695b44323342dfa65e67c66417ec1cd4395 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7372.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "cb73c5601845b23dcea8b41d915e0a97afd18201", + "authors": [ + { + "n": "Ramiro Gatti", + "e": "rgatti@ingenieria.uner.edu.ar" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 1, + "d": 0 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 1, + "d": 0 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 1, + "d": 0 + }, + "tutorials/source-modeling/plot_eeg_no_mri.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7374.json b/mne-python/source/doc/sphinxext/prs/7374.json new file mode 100644 index 0000000000000000000000000000000000000000..612fd7d24caa05096520713c5b8ca3662fe83744 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7374.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "66acf7e945d5d225018184add219e6f8691446cc", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/evoked.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7378.json b/mne-python/source/doc/sphinxext/prs/7378.json new file mode 100644 index 0000000000000000000000000000000000000000..eaa4e0303cb73d337937ed540c054838a7dbaf57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7378.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "17e4cca9efbfb5938ed1a573e816787196d3b6fb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/fetching.py": { + "a": 26, + "d": 61 + }, + "mne/utils/tests/test_fetching.py": { + "a": 7, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7380.json b/mne-python/source/doc/sphinxext/prs/7380.json new file mode 100644 index 0000000000000000000000000000000000000000..c8425cce93e16ddaf2858b859bbebe831b0e49d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7380.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "b884155c707c9e7d5224bb38f1854a54599a5b37", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 16, + "d": 6 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 7, + "d": 6 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 6, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 12, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7381.json b/mne-python/source/doc/sphinxext/prs/7381.json new file mode 100644 index 0000000000000000000000000000000000000000..0215e9c20518f5a65db000d6fe847778e0ec0bcc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7381.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3bde3d23a60d5a52cceae916936ba08779e20673", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7382.json b/mne-python/source/doc/sphinxext/prs/7382.json new file mode 100644 index 0000000000000000000000000000000000000000..2dd9fc13a3c3a0aa39dd8a347b868b466a83e794 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7382.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bbd17ddbd332cb22f5b09e3f783d05392d3ce912", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 4, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7383.json b/mne-python/source/doc/sphinxext/prs/7383.json new file mode 100644 index 0000000000000000000000000000000000000000..1eaceb3fbdccb4cc0de488c3672f44b3899f37c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7383.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3f9ef1c3767a030074f181196d1c359e843cb3fe", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7386.json b/mne-python/source/doc/sphinxext/prs/7386.json new file mode 100644 index 0000000000000000000000000000000000000000..0d003d94390e5d8f28310776b7ab43e23f76ea9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7386.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e88179aaef6c485db03e2432289a7f8cabb30775", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 10, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7387.json b/mne-python/source/doc/sphinxext/prs/7387.json new file mode 100644 index 0000000000000000000000000000000000000000..7810983da37dffc1d72b7e33299079109f876a4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7387.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "067b0144f3b9f8e572f53e1af1dbe417aa9e6d98", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "examples/inverse/plot_dics_source_power.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7388.json b/mne-python/source/doc/sphinxext/prs/7388.json new file mode 100644 index 0000000000000000000000000000000000000000..89be4fd27a0d30ccba71067a585ded2f94c02d9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7388.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9afac0a8f8543922cef27bea55ca35a930241a17", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/source-modeling/plot_forward.py": { + "a": 17, + "d": 20 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 8, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7389.json b/mne-python/source/doc/sphinxext/prs/7389.json new file mode 100644 index 0000000000000000000000000000000000000000..80caf90c6a334c6456b8dd7778855214e9688968 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7389.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "077d33fc909e9ae3e32b305a8b3a37461dda3c12", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7390.json b/mne-python/source/doc/sphinxext/prs/7390.json new file mode 100644 index 0000000000000000000000000000000000000000..8b522e016d18b2f8db716b9796c5f5560d3ac825 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7390.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c7af21496a1ff80c9fbc9da4f1d95334bf8f9e90", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 5, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 0 + }, + "mne/viz/backends/base_renderer.py": { + "a": 5, + "d": 0 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7391.json b/mne-python/source/doc/sphinxext/prs/7391.json new file mode 100644 index 0000000000000000000000000000000000000000..96664f98b0cd1b8c801ff8eb4bfbf6c67f37ab6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7391.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d6706509ec55f3cf4777dd6e96d2a2b42eb55c37", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/bads.py": { + "a": 6, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7392.json b/mne-python/source/doc/sphinxext/prs/7392.json new file mode 100644 index 0000000000000000000000000000000000000000..3e1c471dfc88ee064b330a638812303af5008d9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7392.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f6c029be1a190c122ead63d0fbd0e6d44a0c4766", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7393.json b/mne-python/source/doc/sphinxext/prs/7393.json new file mode 100644 index 0000000000000000000000000000000000000000..a31d2b56bba1a845ce2a9b07362624eafa4464f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7393.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6fd65ef1324819e854d9b2758ddf510038b99be8", + "authors": [ + { + "n": "Liberty Hamilton", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/reference.py": { + "a": 30, + "d": 25 + }, + "mne/io/tests/test_reference.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7394.json b/mne-python/source/doc/sphinxext/prs/7394.json new file mode 100644 index 0000000000000000000000000000000000000000..44f0872b1cd46050bb20f8a97dd8b197446f564d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7394.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8e3fc949e177d10bb3acf9ecf93524924b346240", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 10, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7396.json b/mne-python/source/doc/sphinxext/prs/7396.json new file mode 100644 index 0000000000000000000000000000000000000000..ea75ff56073512883c6aae2949ce8027a0c610de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7396.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "32048ae44faf65dd2f0761d25f17b6a7b160d8f0", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7399.json b/mne-python/source/doc/sphinxext/prs/7399.json new file mode 100644 index 0000000000000000000000000000000000000000..de9f56128a187fa137e005d59b2d625685114d2d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7399.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1cf95cc90f2e13a73a75d1d46799f0414e2deead", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/74.json b/mne-python/source/doc/sphinxext/prs/74.json new file mode 100644 index 0000000000000000000000000000000000000000..085772f2f22dede48515d947ee9106fdbe74cbaa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/74.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "438dea14ed8aff90c5994ad17295a42a4d0e7e91", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 55, + "d": 0 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 21, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 132, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/740.json b/mne-python/source/doc/sphinxext/prs/740.json new file mode 100644 index 0000000000000000000000000000000000000000..cb66ffb3115cee04175410f66930440e267411a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/740.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a423272af7c686de62c0c79ab5e3f4a12c2444f3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7400.json b/mne-python/source/doc/sphinxext/prs/7400.json new file mode 100644 index 0000000000000000000000000000000000000000..4349d969d7d320ce08e296be16d588e1029eac61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7400.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ef65f8f0fc74fc703d96a85ede37a1ac5dc39d3d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7401.json b/mne-python/source/doc/sphinxext/prs/7401.json new file mode 100644 index 0000000000000000000000000000000000000000..0455c85bea35a708edf8aa22f0d9bcbce13224cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7401.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3cc92424a94b7d73f3838732ccf5c8abbb72e652", + "authors": [ + { + "n": "Britta Westner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 21, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7402.json b/mne-python/source/doc/sphinxext/prs/7402.json new file mode 100644 index 0000000000000000000000000000000000000000..938231ea3973226c6738c11d43333917ea3a3f00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7402.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4622f8836d7946435452e291dc27605688a01711", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 93, + "d": 63 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7403.json b/mne-python/source/doc/sphinxext/prs/7403.json new file mode 100644 index 0000000000000000000000000000000000000000..94534cac38d29d83192141546e347cf0189d468a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7403.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5a89c3d322139e1ae64202df1b40ec324346a6da", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 7, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7407.json b/mne-python/source/doc/sphinxext/prs/7407.json new file mode 100644 index 0000000000000000000000000000000000000000..9bc025ec1fbeedb4a2a737ad6718a0f1971232ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7407.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "e3cc4b1cb5e6ac4e452494933377858d18c1268e", + "authors": [ + { + "n": "Adonay Nunes", + "e": "adonay.s.nunes@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "examples/preprocessing/plot_muscle_detection.py": { + "a": 80, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 107, + "d": 2 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 28, + "d": 1 + }, + "tutorials/preprocessing/plot_30_filtering_resampling.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7408.json b/mne-python/source/doc/sphinxext/prs/7408.json new file mode 100644 index 0000000000000000000000000000000000000000..f78679dcd33614bab8dbca38f66a0d5156872550 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7408.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a2d1461142d7d4dfdd23586c6d6fdd08d4671934", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/conftest.py": { + "a": 26, + "d": 0 + }, + "mne/viz/tests/test_topo.py": { + "a": 9, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 8, + "d": 14 + }, + "mne/viz/topo.py": { + "a": 6, + "d": 0 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7409.json b/mne-python/source/doc/sphinxext/prs/7409.json new file mode 100644 index 0000000000000000000000000000000000000000..1a8a037a420b591261bc3830cb21ffa8e88eefd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7409.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ff2442f156004e452fb7c40a6e3477c7dbe6e9d1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/stats/multi_comp.py": { + "a": 2, + "d": 0 + }, + "mne/stats/tests/test_multi_comp.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/741.json b/mne-python/source/doc/sphinxext/prs/741.json new file mode 100644 index 0000000000000000000000000000000000000000..78d038ee6dc0210a30346967ab207e897352c3a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/741.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "a35cc7e505270de0ee11492bda31cd4b3b5c7a5e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 4, + "d": 0 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 4, + "d": 25 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 7, + "d": 22 + }, + "mne/epochs.py": { + "a": 33, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 31, + "d": 33 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 0, + "d": 6 + }, + "mne/tests/test_viz.py": { + "a": 7, + "d": 0 + }, + "mne/viz.py": { + "a": 126, + "d": 61 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7411.json b/mne-python/source/doc/sphinxext/prs/7411.json new file mode 100644 index 0000000000000000000000000000000000000000..542dd712d506435afa7c6c58b28c51028e8330b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7411.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9f05d2405b5597743bf4a10db17032f00086987a", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 12, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7412.json b/mne-python/source/doc/sphinxext/prs/7412.json new file mode 100644 index 0000000000000000000000000000000000000000..2ba983aa4fca918012338da85a504c8097176bc9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7412.json @@ -0,0 +1,123 @@ +{ + "merge_commit_sha": "7ce4bb77e7cfbbb887a9550915777d09d5ba787e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 3 + }, + "README.rst": { + "a": 6, + "d": 6 + }, + "doc/changes/latest.inc": { + "a": 8, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 11, + "d": 29 + }, + "mne/decoding/tests/test_base.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_ems.py": { + "a": 4, + "d": 8 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 2 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 5, + "d": 7 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 4 + }, + "mne/filter.py": { + "a": 5, + "d": 6 + }, + "mne/fixes.py": { + "a": 3, + "d": 168 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 2 + }, + "mne/label.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ctps_.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 9 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 6, + "d": 8 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 2 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + }, + "mne/viz/montage.py": { + "a": 2, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 7 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7413.json b/mne-python/source/doc/sphinxext/prs/7413.json new file mode 100644 index 0000000000000000000000000000000000000000..8fdcf6072039686e32f23e97b2444dfbd6b695c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7413.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1bbe385fb4473f10fc6942ce7c38ad75deefda9e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/discussions/plot_background_filtering.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7414.json b/mne-python/source/doc/sphinxext/prs/7414.json new file mode 100644 index 0000000000000000000000000000000000000000..d65e1c7fb111427f35cf93473286940d85dc0aba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7414.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4e32966c5df0f294141ebb9da16ba3756228f808", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 37, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 21, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 95, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7416.json b/mne-python/source/doc/sphinxext/prs/7416.json new file mode 100644 index 0000000000000000000000000000000000000000..2837f542367394c94c332cd09c124ebca043a27c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7416.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b5ec42534f7651a9bf041b2d1a31888b533c06ab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 33, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7417.json b/mne-python/source/doc/sphinxext/prs/7417.json new file mode 100644 index 0000000000000000000000000000000000000000..e21a5f2f7343e29dae2c1af9930b5317826ee6ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7417.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9e852f266025ba15464fafaad6327fcf73d5ffa1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/annotations.py": { + "a": 7, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 16, + "d": 28 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 48, + "d": 17 + }, + "mne/utils/check.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7419.json b/mne-python/source/doc/sphinxext/prs/7419.json new file mode 100644 index 0000000000000000000000000000000000000000..0a79a5d9af5a4dc4dcaf32ec948c4a52d7150842 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7419.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "34e72956f60326b883e07a9694a9808ca73f9627", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 58 + }, + "mne/utils/docs.py": { + "a": 43, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/742.json b/mne-python/source/doc/sphinxext/prs/742.json new file mode 100644 index 0000000000000000000000000000000000000000..ec0ca1fe56b9f2f3a76b092ad9a9c28ea34e6c09 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/742.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "f3c07007862f82e4cbe171d0f3f3601f33d17cb9", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 112, + "d": 0 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 123, + "d": 0 + }, + "mne/beamformer/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 185, + "d": 8 + }, + "mne/beamformer/_lcmv.py": { + "a": 278, + "d": 5 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 102, + "d": 18 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 202, + "d": 54 + }, + "mne/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/csd.py": { + "a": 28, + "d": 14 + }, + "mne/time_frequency/multitaper.py": { + "a": 9, + "d": 3 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 29, + "d": 19 + }, + "mne/viz.py": { + "a": 87, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7422.json b/mne-python/source/doc/sphinxext/prs/7422.json new file mode 100644 index 0000000000000000000000000000000000000000..009edc5b8f4145b32b06c1641f892bd06257fa12 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7422.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "36fcc968e016fdb6e22f61e27e09df4926e6bea1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7423.json b/mne-python/source/doc/sphinxext/prs/7423.json new file mode 100644 index 0000000000000000000000000000000000000000..62ade2f7e4d812a8db1619e35eab62fdbbed9af1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7423.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0083c2b99f6ba9da3849dd9edef05b1063e1affa", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 25, + "d": 54 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 294, + "d": 231 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7424.json b/mne-python/source/doc/sphinxext/prs/7424.json new file mode 100644 index 0000000000000000000000000000000000000000..13dbc9602a8602ea044e9d3a45c44cbd4b1aa38e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7424.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d8db438592b4a6e62d71692715b176834192d9aa", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7427.json b/mne-python/source/doc/sphinxext/prs/7427.json new file mode 100644 index 0000000000000000000000000000000000000000..1100fd8a899d2a8456fe6fe7e7a76b35bc62661e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7427.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "586c09f55615ffd8933ca7e2cc543d0e6bbe1ff5", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 29, + "d": 0 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 3, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 5, + "d": 4 + }, + "mne/viz/tests/conftest.py": { + "a": 21, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 17, + "d": 16 + }, + "mne/viz/topo.py": { + "a": 6, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 36, + "d": 34 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7428.json b/mne-python/source/doc/sphinxext/prs/7428.json new file mode 100644 index 0000000000000000000000000000000000000000..0f6664d57a99203ee404d7a0db7f24f27fefa64b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7428.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "86d7988b89de6daa1575e60f42586efc5d2c6dec", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 56, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 21, + "d": 0 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/743.json b/mne-python/source/doc/sphinxext/prs/743.json new file mode 100644 index 0000000000000000000000000000000000000000..b1009dd162feb383b97af2475a005adc169c8f07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/743.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "65a0a7faf7e8fe7d870e03c64eb591e4a62be27b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/tests/test_classifier.py": { + "a": 15, + "d": 9 + }, + "mne/fiff/tests/test_compensator.py": { + "a": 2, + "d": 0 + }, + "mne/fiff/tests/test_raw.py": { + "a": 6, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 5, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 13, + "d": 5 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 6, + "d": 5 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 11, + "d": 5 + }, + "mne/tests/test_cov.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 9, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 6, + "d": 3 + }, + "mne/tests/test_viz.py": { + "a": 6, + "d": 2 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 2, + "d": 0 + }, + "mne/viz.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7431.json b/mne-python/source/doc/sphinxext/prs/7431.json new file mode 100644 index 0000000000000000000000000000000000000000..c5125dadfd856945d723c9c004ab9155c0b9236b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7431.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7cec1e43350099358acc267ec3dd43203f63eb07", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7432.json b/mne-python/source/doc/sphinxext/prs/7432.json new file mode 100644 index 0000000000000000000000000000000000000000..51851c423553b6c5d04675a5029b009eebb4e643 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7432.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2fd229f75903fc2cca08874959369f749a864f6b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 117, + "d": 94 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 6, + "d": 7 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 19, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7434.json b/mne-python/source/doc/sphinxext/prs/7434.json new file mode 100644 index 0000000000000000000000000000000000000000..d8065abb78821ba5393baa0db34d4cf746a575e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7434.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "9ae1a832b36f8c6688e36e567e0aa129ea0a03e4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/externals/decorator.py": { + "a": 5, + "d": 6 + }, + "mne/filter.py": { + "a": 0, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 0, + "d": 1 + }, + "mne/io/base.py": { + "a": 5, + "d": 7 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 2 + }, + "mne/io/ctf/ctf.py": { + "a": 0, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 0, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/utils/_logging.py": { + "a": 47, + "d": 39 + }, + "mne/utils/config.py": { + "a": 0, + "d": 14 + }, + "mne/utils/misc.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_config.py": { + "a": 1, + "d": 19 + }, + "mne/utils/tests/test_logging.py": { + "a": 40, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7435.json b/mne-python/source/doc/sphinxext/prs/7435.json new file mode 100644 index 0000000000000000000000000000000000000000..609267d7714956740fef41024d5fc841b47a1a5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7435.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b11c4ab22d18732fd0d9eee2a7784098ccd07965", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 12, + "d": 13 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7438.json b/mne-python/source/doc/sphinxext/prs/7438.json new file mode 100644 index 0000000000000000000000000000000000000000..a9e57a4bb9c9c8740f02666b1108f7abd792edff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7438.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "debae7841621e69e2f6b5d99898c4dd8c57c2068", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7439.json b/mne-python/source/doc/sphinxext/prs/7439.json new file mode 100644 index 0000000000000000000000000000000000000000..59efc18ba1b3786eff71b452381f754e22e77d2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7439.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5d74f84574a944ed201dfab61f49e3720a0244a2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 2, + "d": 0 + }, + "tutorials/evoked/plot_20_visualize_evoked.py": { + "a": 254, + "d": 0 + }, + "tutorials/evoked/plot_visualize_evoked.py": { + "a": 0, + "d": 214 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/744.json b/mne-python/source/doc/sphinxext/prs/744.json new file mode 100644 index 0000000000000000000000000000000000000000..da58fed6ccda59407d95f385fcb431a5358d28ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/744.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8c2a6911bd0a066dbd760c9172ade5a5760df175", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/fiff/constants.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7440.json b/mne-python/source/doc/sphinxext/prs/7440.json new file mode 100644 index 0000000000000000000000000000000000000000..538ec656910a4eaec74ba2314af2e0145b5397e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7440.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "69429ef9de6efb299ea27e9c4a7a5af20dc06089", + "authors": [ + { + "n": "FuTe Wong", + "e": "zuxfoucault@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_dics_source_power.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_evoked_ers_source_power.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7441.json b/mne-python/source/doc/sphinxext/prs/7441.json new file mode 100644 index 0000000000000000000000000000000000000000..c7e3dc8d7699c02077ccadf23e3cee80e474fe9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7441.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "41978e88e37b254f2adc3c92acf81f57bfc9e215", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/annotations.py": { + "a": 5, + "d": 8 + }, + "mne/tests/test_annotations.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7443.json b/mne-python/source/doc/sphinxext/prs/7443.json new file mode 100644 index 0000000000000000000000000000000000000000..3ba4576640eca9d09c7ff4e8caf68300b2634217 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7443.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8c153f3c695ec63093bb00da0412f9ba87899405", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 10, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7444.json b/mne-python/source/doc/sphinxext/prs/7444.json new file mode 100644 index 0000000000000000000000000000000000000000..4b301b551c277b060c75844766ee5664625dc3d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7444.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "248bb02ef73dc16487998e4099bbc58b006e3119", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 7, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 8, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 55, + "d": 33 + }, + "mne/viz/utils.py": { + "a": 43, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7446.json b/mne-python/source/doc/sphinxext/prs/7446.json new file mode 100644 index 0000000000000000000000000000000000000000..3eb72c0ada8222d3c2e85c1129868365d187a2d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7446.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d31ba496505fb1e8d8eea6cc6c7bc360dd941161", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7448.json b/mne-python/source/doc/sphinxext/prs/7448.json new file mode 100644 index 0000000000000000000000000000000000000000..3551be9b8c2e5edfb19e3fb456278663d52d1b84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7448.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "20124d8ed2ba27cd68aec3506a34a6f310af8ee2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 48, + "d": 55 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7451.json b/mne-python/source/doc/sphinxext/prs/7451.json new file mode 100644 index 0000000000000000000000000000000000000000..cf0a935f8632d1fac050f41e979e2817003abb09 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7451.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a1d423d0f09e9b28f7ee9eaff4f8f1c8da0dcb0a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 3, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 64, + "d": 40 + }, + "mne/io/tests/test_meas_info.py": { + "a": 12, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7454.json b/mne-python/source/doc/sphinxext/prs/7454.json new file mode 100644 index 0000000000000000000000000000000000000000..f4b2b786c35b38cc46168f2e0e06cdbf23b6bece --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7454.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fd5a8c5e9cbbbae047c39b320495525b9f5c96ba", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7455.json b/mne-python/source/doc/sphinxext/prs/7455.json new file mode 100644 index 0000000000000000000000000000000000000000..4b7736f03d5b1c22aeef2601d7ce0bdef922b759 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7455.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "f6cb5110deddeee724f153ecd93bc5a5aa13adca", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/visualization/plot_eeglab_head_sphere.py": { + "a": 124, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 3, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 4 + }, + "tutorials/intro/plot_40_sensor_locations.py": { + "a": 56, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7456.json b/mne-python/source/doc/sphinxext/prs/7456.json new file mode 100644 index 0000000000000000000000000000000000000000..0909355e12a6dd47ed64142bef404f0b1f3eff07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7456.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9646e22ed8447234a25571e759633d8fa1c4c8dd", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 24, + "d": 10 + }, + "mne/utils/tests/test_numerics.py": { + "a": 18, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7457.json b/mne-python/source/doc/sphinxext/prs/7457.json new file mode 100644 index 0000000000000000000000000000000000000000..a5ddca14eaf1511a6200e9ea9bb57017aa5ea90b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7457.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4cb2798cac7514b8f0d2f0b6f80252d378737e76", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7458.json b/mne-python/source/doc/sphinxext/prs/7458.json new file mode 100644 index 0000000000000000000000000000000000000000..aa340becbcdb564be4556075720f23239985dea7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7458.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e1b02121eb183c683b6b796fc01998aa4512d7c3", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 2, + "d": 32 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 10, + "d": 8 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7459.json b/mne-python/source/doc/sphinxext/prs/7459.json new file mode 100644 index 0000000000000000000000000000000000000000..dd18812fef6d7051a0e58e188092518f97d77386 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7459.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6915a368e1b47f4a2e495cad12da65a6353117ac", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 23, + "d": 7 + }, + "mne/tests/test_chpi.py": { + "a": 57, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/746.json b/mne-python/source/doc/sphinxext/prs/746.json new file mode 100644 index 0000000000000000000000000000000000000000..9bcd54b74d7554382a2e0c3602246c56e2e30746 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/746.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4504172c8bb28f5d25e074627c2a0f88ac158f67", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/viz.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7460.json b/mne-python/source/doc/sphinxext/prs/7460.json new file mode 100644 index 0000000000000000000000000000000000000000..bee8ffa05896bba98dda2050491927a4c7b6d230 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7460.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "487759e4b8f003311c1653f2f54592609a42c029", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 1 + }, + "mne/io/proc_history.py": { + "a": 2, + "d": 5 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 178, + "d": 152 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 7, + "d": 4 + }, + "mne/preprocessing/utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 6, + "d": 7 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 19, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7462.json b/mne-python/source/doc/sphinxext/prs/7462.json new file mode 100644 index 0000000000000000000000000000000000000000..b8bd5b706dcf8b4d0b491b9e32089c9c30314487 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7462.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8ac813c35941f70b317a36af91a6065453a7b0d8", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 1, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 2, + "d": 2 + }, + "examples/forward/plot_forward_sensitivity_maps.py": { + "a": 10, + "d": 13 + }, + "mne/viz/_brain/_brain.py": { + "a": 11, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7465.json b/mne-python/source/doc/sphinxext/prs/7465.json new file mode 100644 index 0000000000000000000000000000000000000000..c6718efa1f6d796c9d81e6a70676c8a4df64fe63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7465.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "aa7ea77b7f4be41e99665c45ae571cb7ea9e8a66", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/visualization/plot_evoked_arrowmap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7468.json b/mne-python/source/doc/sphinxext/prs/7468.json new file mode 100644 index 0000000000000000000000000000000000000000..797e06f14e6af919493c8ef0bc4fb83944995b5e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7468.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "acaaa84d3dac50f314917c981709c58962455ba0", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7469.json b/mne-python/source/doc/sphinxext/prs/7469.json new file mode 100644 index 0000000000000000000000000000000000000000..9673a22786f50781a9f83b8d1b6d9e73d467030b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7469.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "25f6e5e097d8492bfcc3abb6e77804d372f68a9d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 1, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 1, + "d": 1 + }, + "examples/forward/plot_forward_sensitivity_maps.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 100, + "d": 78 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/747.json b/mne-python/source/doc/sphinxext/prs/747.json new file mode 100644 index 0000000000000000000000000000000000000000..c30bf3eb0e1797213d394d44456ccb7eb939c598 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/747.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e97fad175d1174b7f22d27e19ecf4382f7c0c512", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 10, + "d": 10 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_2samp.py": { + "a": 10, + "d": 10 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 4 + }, + "mne/viz.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7470.json b/mne-python/source/doc/sphinxext/prs/7470.json new file mode 100644 index 0000000000000000000000000000000000000000..c0f7ebf245cb7420a48f2c25c0fb342807ab6c85 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7470.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b1b31428b60d485a81e6d2f643b689d9ce74558a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 88, + "d": 270 + }, + "mne/utils/docs.py": { + "a": 111, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7473.json b/mne-python/source/doc/sphinxext/prs/7473.json new file mode 100644 index 0000000000000000000000000000000000000000..1b52ec4ff95e83b8c7bf645a3e399b4014c99beb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7473.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "11beee2b677e6971ba013f17041d047865c20050", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_bem.py": { + "a": 46, + "d": 36 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7474.json b/mne-python/source/doc/sphinxext/prs/7474.json new file mode 100644 index 0000000000000000000000000000000000000000..6b25617e7923657e797a8f6e402ce6c1a9e449d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7474.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "fcbe5aec41cb346f5a3b0add845442ab93f6fcf3", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "drammock@users.noreply.github.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "drammock@users.noreply.github.com" + } + ], + "changes": { + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 8, + "d": 6 + }, + "mne/channels/channels.py": { + "a": 5, + "d": 54 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 0, + "d": 6 + }, + "mne/io/reference.py": { + "a": 9, + "d": 58 + }, + "mne/utils/docs.py": { + "a": 44, + "d": 0 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 11, + "d": 16 + }, + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/plot_55_setting_eeg_reference.py": { + "a": 3, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7476.json b/mne-python/source/doc/sphinxext/prs/7476.json new file mode 100644 index 0000000000000000000000000000000000000000..f9b2a0f7863aaa165079626b3cd3d59bda234c5e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7476.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3c51cf10ec0f573def4a8d67a739502cfc26dd0f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 8, + "d": 29 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7477.json b/mne-python/source/doc/sphinxext/prs/7477.json new file mode 100644 index 0000000000000000000000000000000000000000..a8b7e3ffc919f11266fb0dbfa7eba9e0e38fca94 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7477.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "94f8ecf49fe8be427ffe9a3636fbc5cc4789da46", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/io/_digitization.py": { + "a": 7, + "d": 0 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/utils.py": { + "a": 3, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 62, + "d": 3 + }, + "mne/io/proj.py": { + "a": 14, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/748.json b/mne-python/source/doc/sphinxext/prs/748.json new file mode 100644 index 0000000000000000000000000000000000000000..2fcd6b904040090cc62192ee53472ed97004c169 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/748.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1e6607ef574f4a57027c048bdb90517232ec9cd4", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/fiff/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/meas_info.py": { + "a": 57, + "d": 4 + }, + "mne/fiff/tests/test_meas_info.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7480.json b/mne-python/source/doc/sphinxext/prs/7480.json new file mode 100644 index 0000000000000000000000000000000000000000..a2baafd65ff219cae411a065134eb2f25fdcc48b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7480.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bb58e0346d844ecf6224248ed133901864eae538", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 58, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7481.json b/mne-python/source/doc/sphinxext/prs/7481.json new file mode 100644 index 0000000000000000000000000000000000000000..373a117c2e04f95a7253fc1143fbd1a36d27dbfb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7481.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "be48643efeba31cba7dcdc0c583b24dea9a77a8c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".mailmap": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7483.json b/mne-python/source/doc/sphinxext/prs/7483.json new file mode 100644 index 0000000000000000000000000000000000000000..1012e4618e05c875659fae24bdd5a17098be46a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7483.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e4c1e7810f1b777793832a1ceb701855894cb161", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 26, + "d": 17 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 3, + "d": 1 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7484.json b/mne-python/source/doc/sphinxext/prs/7484.json new file mode 100644 index 0000000000000000000000000000000000000000..66fafcb63fedc9cb0e9beea9a4a5ee4de3d50325 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7484.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2953c77a907905311ac81205b03f4d3138f0a07d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/utils/tests/test_numerics.py": { + "a": 0, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7486.json b/mne-python/source/doc/sphinxext/prs/7486.json new file mode 100644 index 0000000000000000000000000000000000000000..961181d6dde934e548ee939c5653b4ccf6b8d70e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7486.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "9e785061f325191b809ade41590887230c1378ec", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 14, + "d": 4 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 2, + "d": 4 + }, + "mne/io/pick.py": { + "a": 12, + "d": 6 + }, + "mne/io/tests/test_pick.py": { + "a": 10, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_rank.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 6, + "d": 7 + }, + "mne/viz/evoked.py": { + "a": 6, + "d": 7 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/plot_30_info.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7488.json b/mne-python/source/doc/sphinxext/prs/7488.json new file mode 100644 index 0000000000000000000000000000000000000000..cbda032da68b549a8e238831161f2a63f51dee3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7488.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "55b78208c360cfeb25fe09cbb7b0e5a19911463e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7489.json b/mne-python/source/doc/sphinxext/prs/7489.json new file mode 100644 index 0000000000000000000000000000000000000000..0cf9e4c8fc321b4af589d405837f8b38ac09f9a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7489.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "943dee405fcc68f985107a8f7c6912ee2adfa87a", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 5, + "d": 4 + }, + "mne/preprocessing/tests/test_scalp_coupling_index.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/749.json b/mne-python/source/doc/sphinxext/prs/749.json new file mode 100644 index 0000000000000000000000000000000000000000..43f1eb85a6a6cfbbaccf5498f2880c7ab86ae2b2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/749.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f524a10c5e0801882483ef5c6555bd06a9ee2293", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/meas_info.py": { + "a": 14, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7490.json b/mne-python/source/doc/sphinxext/prs/7490.json new file mode 100644 index 0000000000000000000000000000000000000000..98920c0aa40a9fce012696306c05f5c8dacaadd6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7490.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "98057d96ced28227a1f06f3a432eb129c6442171", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 2, + "d": 0 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7491.json b/mne-python/source/doc/sphinxext/prs/7491.json new file mode 100644 index 0000000000000000000000000000000000000000..3f83833608768669101769c5d60cc9e1e8189b37 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7491.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e7cee41c3f30e4fedd4e6ae931cc7dd64e378d7b", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/nirs/nirs.py": { + "a": 9, + "d": 1 + }, + "mne/preprocessing/tests/test_beer_lambert_law.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7494.json b/mne-python/source/doc/sphinxext/prs/7494.json new file mode 100644 index 0000000000000000000000000000000000000000..ce74f5476d2d59d0cb3a1f89fbc12f8f172ca005 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7494.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "967cfc416bd65fad2d8f20ea3a79fc7d54d29c46", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7495.json b/mne-python/source/doc/sphinxext/prs/7495.json new file mode 100644 index 0000000000000000000000000000000000000000..0579179d096838be3bde11ecc364d3eb7c39aaee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7495.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0b1bf55f8e3eca094b7928f21cedcfed7f4cf66a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 5, + "d": 4 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 18, + "d": 1 + }, + "mne/utils/check.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7496.json b/mne-python/source/doc/sphinxext/prs/7496.json new file mode 100644 index 0000000000000000000000000000000000000000..37b47ed7df5ce99830f87f1dd543e1c562ea643f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7496.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "96cfef579c7e10a040102bb10a0eadcafcaaabb8", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7497.json b/mne-python/source/doc/sphinxext/prs/7497.json new file mode 100644 index 0000000000000000000000000000000000000000..50882dafea1f87813449d8d5fe2156713fccb6b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7497.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "c18283ab83c588f8dfc483bd3cd09683aa832aa0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_includes/units.rst": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 2, + "d": 2 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/defaults.py": { + "a": 3, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 6, + "d": 6 + }, + "mne/io/curry/curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_utils.py": { + "a": 5, + "d": 5 + }, + "mne/io/utils.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 3 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/plot_40_epochs_to_data_frame.py": { + "a": 3, + "d": 3 + }, + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 2, + "d": 2 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/plot_20_rejecting_bad_data.py": { + "a": 5, + "d": 5 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 3, + "d": 3 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_erp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7498.json b/mne-python/source/doc/sphinxext/prs/7498.json new file mode 100644 index 0000000000000000000000000000000000000000..fcae443684cdf1d4178edad92efccd7dd1a05fb9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7498.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4021b0b788c459b8de4188a6668efec4daa32123", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/mne_python.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7499.json b/mne-python/source/doc/sphinxext/prs/7499.json new file mode 100644 index 0000000000000000000000000000000000000000..15e6e279c1658ae0f82f5e6e827f8126b939e2a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7499.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "90f1d507f889c49987fa4c5627917cf3caec1b57", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/preprocessing/nirs/nirs.py": { + "a": 12, + "d": 0 + }, + "mne/preprocessing/tests/test_beer_lambert_law.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/75.json b/mne-python/source/doc/sphinxext/prs/75.json new file mode 100644 index 0000000000000000000000000000000000000000..34603dd91ef0ccb7350606027277ddea54450b26 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/75.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0e31c0df6e161aafe1481a052821aa7f83c70a1f", + "authors": [ + { + "n": "Brad Buran", + "e": null + } + ], + "changes": { + "mne/parallel.py": { + "a": 20, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/750.json b/mne-python/source/doc/sphinxext/prs/750.json new file mode 100644 index 0000000000000000000000000000000000000000..6be5ca3cd2a5a7f147f18213c3a3d3587ab7d466 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/750.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "be551d67972f4e3b82879e9e5c6b6eed3b37a2c1", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 14, + "d": 0 + }, + "mne/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/transforms/__init__.py": { + "a": 5, + "d": 1 + }, + "mne/transforms/coreg.py": { + "a": 843, + "d": 21 + }, + "mne/transforms/tests/test_coreg.py": { + "a": 139, + "d": 14 + }, + "mne/transforms/transforms.py": { + "a": 48, + "d": 9 + }, + "mne/utils.py": { + "a": 5, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7500.json b/mne-python/source/doc/sphinxext/prs/7500.json new file mode 100644 index 0000000000000000000000000000000000000000..4e84d4bb61ab6409233a54824e25d3e8a2afd76a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7500.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2c344f61b29468eba1b4b7a12acd9d6dc2a0bafe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 4, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 10, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 6, + "d": 0 + }, + "mne/utils/check.py": { + "a": 4, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7501.json b/mne-python/source/doc/sphinxext/prs/7501.json new file mode 100644 index 0000000000000000000000000000000000000000..ac0415748dea80313415143ba9858456f02a807a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7501.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6354f8ab496421606d043646e101da0614d97261", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/install/advanced.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7505.json b/mne-python/source/doc/sphinxext/prs/7505.json new file mode 100644 index 0000000000000000000000000000000000000000..00afccfaf0cf0875ccbe804425691ff69374b471 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7505.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6918981e2788432e4fe6b704cb0503e240e253c2", + "authors": [ + { + "n": "Dmitrii Altukhov", + "e": "dm.altukhov@ya.ru" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_report.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7506.json b/mne-python/source/doc/sphinxext/prs/7506.json new file mode 100644 index 0000000000000000000000000000000000000000..c42a46984bfb66245b7db272504aef2bfaaa1692 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7506.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "68fbbeed03f7304b79f9a8077a724efeefeb2bcd", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 3, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7507.json b/mne-python/source/doc/sphinxext/prs/7507.json new file mode 100644 index 0000000000000000000000000000000000000000..0af86b3426a77017226f95f303704fa8833ccfd3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7507.json @@ -0,0 +1,163 @@ +{ + "merge_commit_sha": "c0b139bc2f9f8c14c5263415a3c5ab56b89f9124", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation_volume.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 2, + "d": 1 + }, + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_eeg_csd.py": { + "a": 3, + "d": 4 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_linear_regression_raw.py": { + "a": 2, + "d": 2 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 2, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 15, + "d": 2 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 59, + "d": 20 + }, + "mne/io/brainvision/brainvision.py": { + "a": 20, + "d": 16 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 15, + "d": 18 + }, + "mne/io/curry/curry.py": { + "a": 10, + "d": 14 + }, + "mne/io/edf/edf.py": { + "a": 28, + "d": 20 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/egi.py": { + "a": 6, + "d": 5 + }, + "mne/io/egi/egimff.py": { + "a": 112, + "d": 101 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 6, + "d": 2 + }, + "mne/io/eximia/eximia.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 4, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 10, + "d": 11 + }, + "mne/io/kit/kit.py": { + "a": 7, + "d": 8 + }, + "mne/io/nicolet/nicolet.py": { + "a": 2, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 1 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 32, + "d": 0 + }, + "mne/io/utils.py": { + "a": 3, + "d": 3 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 5, + "d": 5 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 2, + "d": 2 + }, + "tutorials/raw/plot_10_raw_overview.py": { + "a": 2, + "d": 2 + }, + "tutorials/sample-datasets/plot_brainstorm_auditory.py": { + "a": 4, + "d": 5 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_eeg_mri_coords.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7508.json b/mne-python/source/doc/sphinxext/prs/7508.json new file mode 100644 index 0000000000000000000000000000000000000000..8e6a95d09bb09c78bd01e375bf4362e03b5f5d07 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7508.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "fdbb78ab5029e7abb7fd39186d609e468f59ce3d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/filter.py": { + "a": 8, + "d": 2 + }, + "mne/io/base.py": { + "a": 48, + "d": 30 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 19, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7509.json b/mne-python/source/doc/sphinxext/prs/7509.json new file mode 100644 index 0000000000000000000000000000000000000000..657b5cccd3bfcc3673470624a1ef774c2052b573 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7509.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b3af2f66cb4ca46a1b1e1b24e60545dbe3693227", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 14, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7510.json b/mne-python/source/doc/sphinxext/prs/7510.json new file mode 100644 index 0000000000000000000000000000000000000000..ad70a954561c3b56eb65caf2bca1202aa461ffe9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7510.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e2155cf1906edff3b5b8adeb59558867f07b40f6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 57, + "d": 22 + }, + "mne/tests/test_morph.py": { + "a": 29, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7511.json b/mne-python/source/doc/sphinxext/prs/7511.json new file mode 100644 index 0000000000000000000000000000000000000000..6e204713d453b8b17c696affaf15f19fe4dc504d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7511.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "009fca888ad97d7c621681da316803eae7c9fcd0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 43, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7516.json b/mne-python/source/doc/sphinxext/prs/7516.json new file mode 100644 index 0000000000000000000000000000000000000000..58929a85b1b10752f3c856d5b0cd0b9abe329f09 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7516.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "69f8defd065801969a8cb53d702630024b9f35aa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 37, + "d": 0 + }, + "mne/utils/tests/test_numerics.py": { + "a": 34, + "d": 1 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7517.json b/mne-python/source/doc/sphinxext/prs/7517.json new file mode 100644 index 0000000000000000000000000000000000000000..c08d5fb1109f3415e611473e1b1e3e53397b2f79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7517.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "691c59b234d361e2d537e1407ef6d389e3cdbb0a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 11, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7519.json b/mne-python/source/doc/sphinxext/prs/7519.json new file mode 100644 index 0000000000000000000000000000000000000000..502cb7ede66b7f309a1b0fbc3a5f908835061460 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7519.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b00f49122e053372b312053aa752a5e80a1aab04", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 10, + "d": 16 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 5 + }, + "mne/viz/backends/renderer.py": { + "a": 11, + "d": 17 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 8, + "d": 8 + }, + "mne/viz/tests/test_3d.py": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/752.json b/mne-python/source/doc/sphinxext/prs/752.json new file mode 100644 index 0000000000000000000000000000000000000000..c6ae56a46101d6990c451051b87e767f6deb4b1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/752.json @@ -0,0 +1,259 @@ +{ + "merge_commit_sha": "a9c1604430c358c32b8c5b8580d6267be57993f5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/baseline.py": { + "a": 1, + "d": 3 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 4 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 4 + }, + "mne/connectivity/effective.py": { + "a": 1, + "d": 3 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 5 + }, + "mne/cov.py": { + "a": 2, + "d": 4 + }, + "mne/cuda.py": { + "a": 1, + "d": 4 + }, + "mne/datasets/megsim/megsim.py": { + "a": 0, + "d": 3 + }, + "mne/datasets/sample/sample.py": { + "a": 10, + "d": 5 + }, + "mne/decoding/classifier.py": { + "a": 0, + "d": 3 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 1 + }, + "mne/dipole.py": { + "a": 1, + "d": 3 + }, + "mne/epochs.py": { + "a": 1, + "d": 4 + }, + "mne/event.py": { + "a": 1, + "d": 5 + }, + "mne/fiff/bti/raw.py": { + "a": 1, + "d": 4 + }, + "mne/fiff/bti/read.py": { + "a": 0, + "d": 3 + }, + "mne/fiff/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/compensator.py": { + "a": 0, + "d": 4 + }, + "mne/fiff/cov.py": { + "a": 1, + "d": 4 + }, + "mne/fiff/ctf.py": { + "a": 1, + "d": 4 + }, + "mne/fiff/diff.py": { + "a": 1, + "d": 4 + }, + "mne/fiff/evoked.py": { + "a": 1, + "d": 6 + }, + "mne/fiff/kit/kit.py": { + "a": 1, + "d": 4 + }, + "mne/fiff/matrix.py": { + "a": 1, + "d": 4 + }, + "mne/fiff/meas_info.py": { + "a": 1, + "d": 4 + }, + "mne/fiff/open.py": { + "a": 1, + "d": 3 + }, + "mne/fiff/pick.py": { + "a": 1, + "d": 4 + }, + "mne/fiff/proj.py": { + "a": 1, + "d": 5 + }, + "mne/fiff/raw.py": { + "a": 1, + "d": 5 + }, + "mne/fiff/tree.py": { + "a": 1, + "d": 4 + }, + "mne/fiff/write.py": { + "a": 1, + "d": 2 + }, + "mne/filter.py": { + "a": 1, + "d": 4 + }, + "mne/forward.py": { + "a": 1, + "d": 5 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 4 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 1, + "d": 5 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 4 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 4 + }, + "mne/label.py": { + "a": 1, + "d": 5 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 4 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 4 + }, + "mne/parallel.py": { + "a": 2, + "d": 3 + }, + "mne/preprocessing/ecg.py": { + "a": 6, + "d": 8 + }, + "mne/preprocessing/eog.py": { + "a": 10, + "d": 12 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/maxfilter.py": { + "a": 9, + "d": 11 + }, + "mne/preprocessing/peak_finder.py": { + "a": 2, + "d": 6 + }, + "mne/preprocessing/ssp.py": { + "a": 2, + "d": 4 + }, + "mne/proj.py": { + "a": 2, + "d": 4 + }, + "mne/realtime/client.py": { + "a": 1, + "d": 4 + }, + "mne/realtime/epochs.py": { + "a": 6, + "d": 8 + }, + "mne/selection.py": { + "a": 1, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 5 + }, + "mne/source_space.py": { + "a": 1, + "d": 5 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 5 + }, + "mne/surface.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/csd.py": { + "a": 3, + "d": 6 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 17 + }, + "mne/time_frequency/stft.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 8 + }, + "mne/transforms/transforms.py": { + "a": 0, + "d": 3 + }, + "mne/utils.py": { + "a": 2, + "d": 2 + }, + "mne/viz.py": { + "a": 3, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7520.json b/mne-python/source/doc/sphinxext/prs/7520.json new file mode 100644 index 0000000000000000000000000000000000000000..709011813347c3fc5dfbbb4fa20ff67b91f89f8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7520.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1e882d05cab139530b2859bf4940c681f5b4b5e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/forward/plot_source_space_morphing.py": { + "a": 4, + "d": 4 + }, + "mne/utils/check.py": { + "a": 8, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 18, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 47, + "d": 53 + }, + "mne/viz/_brain/_brain.py": { + "a": 15, + "d": 25 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 73, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7522.json b/mne-python/source/doc/sphinxext/prs/7522.json new file mode 100644 index 0000000000000000000000000000000000000000..ff86fd522f6eb31a3ccea872abbd1a6ba7092dd3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7522.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "84b71308b7a2e0afa2874116195ab7e9c957c61c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 3, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/glossary.rst": { + "a": 12, + "d": 1 + }, + "doc/sphinxext/mne_substitutions.py": { + "a": 48, + "d": 0 + }, + "mne/defaults.py": { + "a": 3, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 6, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 12, + "d": 10 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7523.json b/mne-python/source/doc/sphinxext/prs/7523.json new file mode 100644 index 0000000000000000000000000000000000000000..d5134d97c186c5f9f1184404dfe8a7a717246395 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7523.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "225c90a591c6755b5660fc6d74f5f3b7c4cc1544", + "authors": [ + { + "n": "Ariel Rokem", + "e": "arokem@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7524.json b/mne-python/source/doc/sphinxext/prs/7524.json new file mode 100644 index 0000000000000000000000000000000000000000..23c4ea3d08418bff39602e5857de38e9ba8571c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7524.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4f66d81b5f42dcba84cbf4314fa8b947ebe988f7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7525.json b/mne-python/source/doc/sphinxext/prs/7525.json new file mode 100644 index 0000000000000000000000000000000000000000..c28d553dd634d3469276bff4f773cbdb91a519c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7525.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c38ccb70b8c40b28e484984f6151492da447da14", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/carousel.inc": { + "a": 2, + "d": 2 + }, + "doc/index.rst": { + "a": 0, + "d": 30 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7527.json b/mne-python/source/doc/sphinxext/prs/7527.json new file mode 100644 index 0000000000000000000000000000000000000000..2e2b55e4319e69785430145fd00399537666c24c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7527.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9ca6b11553a8dc9eaee7e5cdbcdbe7f02d26aaa6", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_psf_ctf_vertices_lcmv.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_publication_figure.py": { + "a": 6, + "d": 4 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 5 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7529.json b/mne-python/source/doc/sphinxext/prs/7529.json new file mode 100644 index 0000000000000000000000000000000000000000..921769c8074d351688ff241271dd647a426f047d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7529.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "43315379ec273c4c20df764ffc7a5cc004a5943f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 10, + "d": 1 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 33, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7530.json b/mne-python/source/doc/sphinxext/prs/7530.json new file mode 100644 index 0000000000000000000000000000000000000000..0c7db8d7dea3e9b0306997c186aa41d9d892b635 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7530.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "750c6ac6b4f5e7e0d8ff031dc76930fd7b126e39", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7531.json b/mne-python/source/doc/sphinxext/prs/7531.json new file mode 100644 index 0000000000000000000000000000000000000000..fc53a734d14a4b6cae8740b549c8c298f1cd01c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7531.json @@ -0,0 +1,163 @@ +{ + "merge_commit_sha": "e42c86a1210169f5f51e98b997bea6616d4856d9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.12.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.18.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.20.inc": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 60 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 27 + }, + "mne/chpi.py": { + "a": 1, + "d": 6 + }, + "mne/decoding/csp.py": { + "a": 8, + "d": 21 + }, + "mne/dipole.py": { + "a": 1, + "d": 9 + }, + "mne/epochs.py": { + "a": 4, + "d": 8 + }, + "mne/evoked.py": { + "a": 6, + "d": 10 + }, + "mne/io/base.py": { + "a": 2, + "d": 5 + }, + "mne/io/edf/edf.py": { + "a": 3, + "d": 12 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 2 + }, + "mne/io/fieldtrip/utils.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 29 + }, + "mne/io/pick.py": { + "a": 1, + "d": 7 + }, + "mne/io/proj.py": { + "a": 4, + "d": 9 + }, + "mne/io/tests/test_meas_info.py": { + "a": 3, + "d": 6 + }, + "mne/io/tests/test_pick.py": { + "a": 1, + "d": 7 + }, + "mne/minimum_norm/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/minimum_norm/psf_ctf.py": { + "a": 0, + "d": 407 + }, + "mne/minimum_norm/tests/test_psf_ctf.py": { + "a": 0, + "d": 81 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/bads.py": { + "a": 0, + "d": 26 + }, + "mne/preprocessing/ica.py": { + "a": 10, + "d": 178 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 14 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 5 + }, + "mne/source_space.py": { + "a": 7, + "d": 20 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 0, + "d": 3 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 24, + "d": 32 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/dataframe.py": { + "a": 0, + "d": 11 + }, + "mne/utils/docs.py": { + "a": 0, + "d": 26 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 7 + }, + "mne/viz/topomap.py": { + "a": 40, + "d": 92 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7532.json b/mne-python/source/doc/sphinxext/prs/7532.json new file mode 100644 index 0000000000000000000000000000000000000000..d4a247c91bc3a8de57d2f480634060dd913254cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7532.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "15b9c95db383a1462719d9fbf11f735fa774a0c6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "doc/_includes/forward.rst": { + "a": 2, + "d": 2 + }, + "doc/_static/CoordinateSystems.png": { + "a": 0, + "d": 0 + }, + "doc/_static/HeadCS.png": { + "a": 0, + "d": 0 + }, + "doc/_static/amazon.svg": { + "a": 17, + "d": 0 + }, + "doc/_static/anr.jpeg": { + "a": 0, + "d": 0 + }, + "doc/_static/cds.png": { + "a": 0, + "d": 0 + }, + "doc/_static/doe.png": { + "a": 0, + "d": 0 + }, + "doc/_static/erc.png": { + "a": 0, + "d": 0 + }, + "doc/_static/google.svg": { + "a": 1, + "d": 0 + }, + "doc/_static/mne_logo.png": { + "a": 0, + "d": 0 + }, + "doc/_static/mne_logo.svg": { + "a": 744, + "d": 0 + }, + "doc/_static/mne_logo_small.png": { + "a": 0, + "d": 0 + }, + "doc/_static/mne_logo_small.svg": { + "a": 70, + "d": 0 + }, + "doc/_static/nih.png": { + "a": 0, + "d": 0 + }, + "doc/_static/nsf.png": { + "a": 0, + "d": 0 + }, + "doc/_static/style.css": { + "a": 314, + "d": 251 + }, + "doc/_templates/layout.html": { + "a": 25, + "d": 36 + }, + "doc/_templates/navbar.html": { + "a": 29, + "d": 21 + }, + "doc/carousel.inc": { + "a": 26, + "d": 32 + }, + "doc/conf.py": { + "a": 2, + "d": 6 + }, + "doc/index.rst": { + "a": 56, + "d": 76 + }, + "doc/overview/index.rst": { + "a": 1, + "d": 0 + }, + "doc/whats_new.rst": { + "a": 0, + "d": 2 + }, + "logo/generate_mne_logos.py": { + "a": 9, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7533.json b/mne-python/source/doc/sphinxext/prs/7533.json new file mode 100644 index 0000000000000000000000000000000000000000..4faca4f5801e975116f221b72100adb61e20fba7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7533.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a932cbb76006329e62fb4901628db68b471774e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/cov.py": { + "a": 10, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7535.json b/mne-python/source/doc/sphinxext/prs/7535.json new file mode 100644 index 0000000000000000000000000000000000000000..e48a07e819013fd4f791738cd0cdf3f0900ecbc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7535.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fdd0752de4c4ebbd34c520d5b6ace2806c27fbf0", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7536.json b/mne-python/source/doc/sphinxext/prs/7536.json new file mode 100644 index 0000000000000000000000000000000000000000..be5177fd0927a95ab91a0c1958f39bd35546b40a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7536.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3d1646f9e2ba16e92a2c3ce6105da2c336a27fed", + "authors": [ + { + "n": "Maureen Shader", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 17, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7538.json b/mne-python/source/doc/sphinxext/prs/7538.json new file mode 100644 index 0000000000000000000000000000000000000000..531c3dcb7e56a67b76644225a0fac35a94e1be5b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7538.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1639ab47dd41a73e9e95962e766c80c102cc70f1", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7539.json b/mne-python/source/doc/sphinxext/prs/7539.json new file mode 100644 index 0000000000000000000000000000000000000000..a5e05f75f1dd2ef889fec25af1d7617568a8fded --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7539.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e69e581d58bdeada61c8b863885387aa28ede1da", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/brainvision/tests/data/test_units.vhdr": { + "a": 3, + "d": 3 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 18, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7541.json b/mne-python/source/doc/sphinxext/prs/7541.json new file mode 100644 index 0000000000000000000000000000000000000000..5aed1ba17e90402ae97fbbe1dc855a293649dae9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7541.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "83dc0e1e4f772805428cce0c0c1ca45936262394", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 3, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 5, + "d": 7 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 49, + "d": 42 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7542.json b/mne-python/source/doc/sphinxext/prs/7542.json new file mode 100644 index 0000000000000000000000000000000000000000..f48a6a8aff1aca8a4509d08bb4caeb389c5b45a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7542.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "09d6c58a46d48749def8b8a01422c7cf35b88a25", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/0.20.inc": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7545.json b/mne-python/source/doc/sphinxext/prs/7545.json new file mode 100644 index 0000000000000000000000000000000000000000..814801abec8f7a52c877a8c09c9462120a2d81f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7545.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e2f32970fe2ee8244c1608d962f4a851bed937d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 56, + "d": 55 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7546.json b/mne-python/source/doc/sphinxext/prs/7546.json new file mode 100644 index 0000000000000000000000000000000000000000..21f2933c4c091ba78dd3cfea09df89563a28d3ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7546.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "caae4b2b231abf4e58cd009f813c183d7d7b0234", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 44, + "d": 47 + }, + "mne/utils/progressbar.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7547.json b/mne-python/source/doc/sphinxext/prs/7547.json new file mode 100644 index 0000000000000000000000000000000000000000..0689e74ec4b07bb5e76d5bd45242da8d0c63a9e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7547.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3b4992ae4abca36285290741d7dcedd4823821b6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/advanced.rst": { + "a": 28, + "d": 3 + }, + "doc/overview/get_help.rst": { + "a": 14, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7550.json b/mne-python/source/doc/sphinxext/prs/7550.json new file mode 100644 index 0000000000000000000000000000000000000000..33246a400bfeeea1e1fa48531438158426fb87bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7550.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ddc007f44c5eb840fcfd16dd3987b6535bed9f44", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 3 + }, + "mne/forward/tests/test_forward.py": { + "a": 19, + "d": 18 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 11, + "d": 1 + }, + "mne/source_space.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7551.json b/mne-python/source/doc/sphinxext/prs/7551.json new file mode 100644 index 0000000000000000000000000000000000000000..f33820ed7e7d98e3352a4a3109e3c10a52e26336 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7551.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "2a74f551890bcbbc058ad3be5536f827ca9a1196", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 0, + "d": 6 + }, + "mne/dipole.py": { + "a": 14, + "d": 14 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/externals/h5io/_h5io.py": { + "a": 4, + "d": 4 + }, + "mne/fixes.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_lead_dots.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 2, + "d": 2 + }, + "mne/io/write.py": { + "a": 83, + "d": 83 + }, + "mne/source_estimate.py": { + "a": 9, + "d": 9 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7553.json b/mne-python/source/doc/sphinxext/prs/7553.json new file mode 100644 index 0000000000000000000000000000000000000000..66b4838fd29dc1e673924838d8e69c776372f446 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7553.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ab29bdbb48f5283ed4b423700071d5677f1955ec", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/egi/general.py": { + "a": 8, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7554.json b/mne-python/source/doc/sphinxext/prs/7554.json new file mode 100644 index 0000000000000000000000000000000000000000..26895686724a575b017dae42e27106748f358373 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7554.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "901ffd8ce21943216375b89af1e573890e3de5ed", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7556.json b/mne-python/source/doc/sphinxext/prs/7556.json new file mode 100644 index 0000000000000000000000000000000000000000..d60f1b837de777f1ce453713338351554d220fc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7556.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "50f9f7b4539069128fc365624914b72e77767d86", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 11, + "d": 0 + }, + "examples/preprocessing/plot_fnirs_artifact_removal.py": { + "a": 92, + "d": 0 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/nirs/_temporal_derivative_distribution_repair.py": { + "a": 144, + "d": 0 + }, + "mne/preprocessing/tests/test_temporal_derivative_distribution_repair.py": { + "a": 35, + "d": 0 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 15, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7557.json b/mne-python/source/doc/sphinxext/prs/7557.json new file mode 100644 index 0000000000000000000000000000000000000000..0cab45940dee7cb71902ee06e14d9d8787e44376 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7557.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "01929ae628236bdb886c5f0a81a81b90c04beb67", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7558.json b/mne-python/source/doc/sphinxext/prs/7558.json new file mode 100644 index 0000000000000000000000000000000000000000..989a548b83a9c3a6adab955957e278fa3128a0de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7558.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "59925bb5adc8dc1b616cd2aaed50276ffd2fc530", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 6, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 18, + "d": 9 + }, + "mne/viz/tests/test_3d.py": { + "a": 14, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7559.json b/mne-python/source/doc/sphinxext/prs/7559.json new file mode 100644 index 0000000000000000000000000000000000000000..2ec4be4cb02c62c86ff0adb4d28cf4ff3283b2f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7559.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ef1c86f4a9e022009e936468ec25d504e2b28d8a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7560.json b/mne-python/source/doc/sphinxext/prs/7560.json new file mode 100644 index 0000000000000000000000000000000000000000..a96c37dd3b8d96729f1e2678eea9bb976c978920 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7560.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0c6f22001b617124a8188e94d845c627128b9a77", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 30, + "d": 13 + }, + "mne/io/tag.py": { + "a": 7, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 27, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7562.json b/mne-python/source/doc/sphinxext/prs/7562.json new file mode 100644 index 0000000000000000000000000000000000000000..8b77e5cd8d5a5064ba66a1d71ac634aaef19637d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7562.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "036c2fd71f929a7c34c503691a927da81cf8fde7", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7563.json b/mne-python/source/doc/sphinxext/prs/7563.json new file mode 100644 index 0000000000000000000000000000000000000000..76f11bd66520b2c6bd0aa8abda47d1f86092ce98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7563.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4aba0b78ac9ec229da09cd5d12a3a38d04727d72", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7565.json b/mne-python/source/doc/sphinxext/prs/7565.json new file mode 100644 index 0000000000000000000000000000000000000000..efc2dcced611b98527cbea7db91597503e5490de --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7565.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9193ce2dd8b892132613fb65b8a4baf959d16230", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 2, + "d": 2 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7566.json b/mne-python/source/doc/sphinxext/prs/7566.json new file mode 100644 index 0000000000000000000000000000000000000000..f3fb3b269bd4ab4f07950847e43d1fc4cd93f9e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7566.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "50d65402a8234c6b97b66dc1b75ff6249c348129", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/parallel.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7567.json b/mne-python/source/doc/sphinxext/prs/7567.json new file mode 100644 index 0000000000000000000000000000000000000000..e47ef0323693f01dcac79c15f031ae9dec94bf82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7567.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fd349f5c079c905ac3ab65a72719f2512ecd6d43", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7569.json b/mne-python/source/doc/sphinxext/prs/7569.json new file mode 100644 index 0000000000000000000000000000000000000000..de1617c34c4bb8cb2ac79ffa076810ea7d778b98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7569.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cf1f8c663a2341319c4e36fcee049b0b64419900", + "authors": [ + { + "n": "Adonay Nunes", + "e": "adonay.s.nunes@gmail.com" + } + ], + "changes": { + "examples/preprocessing/plot_movement_detection.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/757.json b/mne-python/source/doc/sphinxext/prs/757.json new file mode 100644 index 0000000000000000000000000000000000000000..8aba8a0c2924b0fd48cb94cabdabc6520ada1331 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/757.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "30b95046462b50b78993abfd1bae7a7a0a91d868", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "bin/mne_make_scalp_surfaces.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7572.json b/mne-python/source/doc/sphinxext/prs/7572.json new file mode 100644 index 0000000000000000000000000000000000000000..ee7d1d6466fc287a0a3ee6197df933a2269c2683 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7572.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ab50b2320e6aa40f2c087c6d27b309935ad79e9d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7573.json b/mne-python/source/doc/sphinxext/prs/7573.json new file mode 100644 index 0000000000000000000000000000000000000000..d9ed8a3863cc311da8a2bf9b3304a389b0fef25f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7573.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1867bfeb6119778f5697294244e0ad24eeb86b46", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_publication_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7574.json b/mne-python/source/doc/sphinxext/prs/7574.json new file mode 100644 index 0000000000000000000000000000000000000000..1cd59da845fa40fb3eeef0ef9d5e2b786cad704a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7574.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "a720b8f4d5e615a45f0d1691e2bf204798cb67fb", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 129, + "d": 5 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 13, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 2, + "d": 2 + }, + "requirements.txt": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7578.json b/mne-python/source/doc/sphinxext/prs/7578.json new file mode 100644 index 0000000000000000000000000000000000000000..0bdea6ced5d18329b23923dd503bdae97294493e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7578.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "d839a6ce32da840d7ed4f4cec5340e479f8bde55", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 4, + "d": 0 + }, + "doc/overview/cookbook.rst": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/io/bti/bti.py": { + "a": 4, + "d": 2 + }, + "mne/io/constants.py": { + "a": 93, + "d": 0 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 5 + }, + "mne/io/tag.py": { + "a": 15, + "d": 5 + }, + "mne/io/tests/test_compensator.py": { + "a": 11, + "d": 14 + }, + "mne/io/tests/test_constants.py": { + "a": 24, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 12, + "d": 0 + }, + "mne/io/utils.py": { + "a": 1, + "d": 2 + }, + "mne/report.py": { + "a": 3, + "d": 2 + }, + "mne/source_space.py": { + "a": 40, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 16, + "d": 5 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 3 + }, + "mne/viz/misc.py": { + "a": 3, + "d": 16 + }, + "tutorials/source-modeling/plot_background_freesurfer.py": { + "a": 49, + "d": 34 + }, + "tutorials/source-modeling/plot_background_freesurfer_mne.py": { + "a": 431, + "d": 0 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 11, + "d": 0 + }, + "tutorials/source-modeling/plot_object_source_estimate.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7579.json b/mne-python/source/doc/sphinxext/prs/7579.json new file mode 100644 index 0000000000000000000000000000000000000000..4847e61fd8da5c1c5c3670a91717efaddc3b884c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7579.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ef9c259733fd5928dc7cf78fdb461d7a30d5fe02", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "tutorials/source-modeling/plot_eeg_mri_coords.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/758.json b/mne-python/source/doc/sphinxext/prs/758.json new file mode 100644 index 0000000000000000000000000000000000000000..e5d3ed9761da34e6dfcd7d1ea34f1be434e54e57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/758.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cd5ddf7e15f8d6c16957ff79afaad49e8aed7ba0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7580.json b/mne-python/source/doc/sphinxext/prs/7580.json new file mode 100644 index 0000000000000000000000000000000000000000..c4d3b8be865b52cbdd17ad673f29373ce451f976 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7580.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f3eb193897a5bbb8ebb501b649a89f2183cc6555", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 11, + "d": 6 + }, + "mne/viz/_brain/_brain.py": { + "a": 10, + "d": 3 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7581.json b/mne-python/source/doc/sphinxext/prs/7581.json new file mode 100644 index 0000000000000000000000000000000000000000..609f28bc0261afa3cb0de380f7e82572a0a32a18 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7581.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8801dcb53262022a221738b96dda248ea786fe61", + "authors": [ + { + "n": "Svea Marie Meyer", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7583.json b/mne-python/source/doc/sphinxext/prs/7583.json new file mode 100644 index 0000000000000000000000000000000000000000..598e4c3a3d3f40efdfed8700512dda3d1f7ece3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7583.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "09ac18f621efc177fc0a07e1f1f3eec4831a2ae8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 6, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 10, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7584.json b/mne-python/source/doc/sphinxext/prs/7584.json new file mode 100644 index 0000000000000000000000000000000000000000..9060b46308cca3d71def30a58bdc773c82143130 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7584.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bc876405aeabb2e6ebcc47b468eecc14eb0f7ef9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 0, + "d": 3 + }, + "doc/install/mne_python.rst": { + "a": 1, + "d": 2 + }, + "environment.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7587.json b/mne-python/source/doc/sphinxext/prs/7587.json new file mode 100644 index 0000000000000000000000000000000000000000..c5da83c01b2396cfe25c64754d0dfe5a049c00fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7587.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3badeef66a6b7fcc91bf4280cb933fa2e2f6a727", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7588.json b/mne-python/source/doc/sphinxext/prs/7588.json new file mode 100644 index 0000000000000000000000000000000000000000..f9f23ef1c27c7a480e77dc15ae5cdf1023a9c080 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7588.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1c9295163319e2a55ec5ebbab77cf33727b2e00f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7589.json b/mne-python/source/doc/sphinxext/prs/7589.json new file mode 100644 index 0000000000000000000000000000000000000000..86c121d72bf2d013e4176ae5cae942a921bb25db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7589.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "550dd1b5e24aa4820cefbb1b101d03bf713bc182", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 3, + "d": 0 + }, + "mne.qrc": { + "a": 13, + "d": 0 + }, + "mne/images/clear-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/images/help-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/images/pause-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/images/play-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/images/restore-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/images/scale-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/images/screenshot-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/images/visibility_off-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/images/visibility_on-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 74, + "d": 0 + }, + "mne/viz/_brain/resources.py": { + "a": 394, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/759.json b/mne-python/source/doc/sphinxext/prs/759.json new file mode 100644 index 0000000000000000000000000000000000000000..cccaef08901e632b15859254dd197ef99de87996 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/759.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f2c1d8c6566ee5ddd95470278d7178a699273b3e", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/kit/kit.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7590.json b/mne-python/source/doc/sphinxext/prs/7590.json new file mode 100644 index 0000000000000000000000000000000000000000..c176abcaa5f57ce3cb2739a00762e8e670913ec3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7590.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "688db27e0445b2edc7076b3a3c9443a2f2e12910", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 25, + "d": 19 + }, + "mne/io/_digitization.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7593.json b/mne-python/source/doc/sphinxext/prs/7593.json new file mode 100644 index 0000000000000000000000000000000000000000..c388b032274646efd7cb91c8a75ea94c158065f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7593.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7b3d86907cc1bed2ba4b61b65d3fe06b6f6fd8ab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Roeland Hancock", + "e": "rhancock@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/egimff.py": { + "a": 137, + "d": 75 + }, + "mne/io/egi/events.py": { + "a": 5, + "d": 7 + }, + "mne/io/egi/general.py": { + "a": 8, + "d": 5 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 77, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7594.json b/mne-python/source/doc/sphinxext/prs/7594.json new file mode 100644 index 0000000000000000000000000000000000000000..a399a85875e7c38a622673a3de57692e5c87d356 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7594.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "83f84ba2c914ce1cf2bde8dfe97f93742f194e6d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_brainstorm_data.py": { + "a": 2, + "d": 1 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 41, + "d": 34 + }, + "examples/time_frequency/plot_source_power_spectrum_opm.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7596.json b/mne-python/source/doc/sphinxext/prs/7596.json new file mode 100644 index 0000000000000000000000000000000000000000..28bb994a16b542e153dcaaf83fa6e5a813484355 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7596.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8aa26ac5612e014fb839abe544a5748b85073231", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "tutorials/intro/plot_20_events_from_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 1, + "d": 1 + }, + "tutorials/raw/plot_20_event_arrays.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7597.json b/mne-python/source/doc/sphinxext/prs/7597.json new file mode 100644 index 0000000000000000000000000000000000000000..f9755edeb74880d941a658b0e305e71564650524 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7597.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "dd2a1f40d0d8e3499b941c5a3403ddd550fd4c2d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 11, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 32, + "d": 11 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/conftest.py": { + "a": 104, + "d": 3 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 7, + "d": 6 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 21, + "d": 31 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 35, + "d": 1 + }, + "mne/morph.py": { + "a": 12, + "d": 8 + }, + "mne/proj.py": { + "a": 4, + "d": 10 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 6, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 248, + "d": 202 + }, + "mne/source_space.py": { + "a": 68, + "d": 26 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_morph.py": { + "a": 6, + "d": 5 + }, + "mne/tests/test_source_estimate.py": { + "a": 95, + "d": 48 + }, + "mne/tests/test_source_space.py": { + "a": 22, + "d": 11 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 11, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 15, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 5 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7598.json b/mne-python/source/doc/sphinxext/prs/7598.json new file mode 100644 index 0000000000000000000000000000000000000000..80fb2977078660c61e22999ee7582f9463db895a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7598.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b50a78fb3e099e148927734009ca2152b4635585", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_ola.py": { + "a": 436, + "d": 0 + }, + "mne/filter.py": { + "a": 0, + "d": 96 + }, + "mne/preprocessing/otp.py": { + "a": 52, + "d": 49 + }, + "mne/preprocessing/utils.py": { + "a": 0, + "d": 59 + }, + "mne/simulation/raw.py": { + "a": 102, + "d": 105 + }, + "mne/tests/test_filter.py": { + "a": 8, + "d": 23 + }, + "mne/tests/test_ola.py": { + "a": 112, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/76.json b/mne-python/source/doc/sphinxext/prs/76.json new file mode 100644 index 0000000000000000000000000000000000000000..05c8ce5681b74ff48fe98b28cebbceff4bc4f874 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/76.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "559121948c95463bb3a1a916fd43ec0fd74b4630", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 233, + "d": 41 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 66, + "d": 5 + }, + "mne/cov.py": { + "a": 24, + "d": 5 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 25 + }, + "mne/source_space.py": { + "a": 41, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7600.json b/mne-python/source/doc/sphinxext/prs/7600.json new file mode 100644 index 0000000000000000000000000000000000000000..b887b5a3bf1409008bcc2f7e680d7c12a70383d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7600.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "51c4cbaf3d3c3fb7a5d9371ba89b54e3a9dbe4e6", + "authors": [ + { + "n": "alexandra.corneyllie", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7603.json b/mne-python/source/doc/sphinxext/prs/7603.json new file mode 100644 index 0000000000000000000000000000000000000000..b03dd5e88a08ef1b06d22179dffff71a781990b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7603.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "093ac9cdb8075b6bdd4ed62302be0353ffb5fd51", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 19, + "d": 12 + }, + "mne/defaults.py": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/io/proj.py": { + "a": 6, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 24, + "d": 8 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 93, + "d": 54 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7606.json b/mne-python/source/doc/sphinxext/prs/7606.json new file mode 100644 index 0000000000000000000000000000000000000000..498722b41244a55d73e049e5c0fa82bd4d6995e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7606.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "90c5c8efddfcd55210317e64852c46c2def7bd64", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 2 + }, + "mne.qrc": { + "a": 0, + "d": 14 + }, + "mne/icons/README.rst": { + "a": 18, + "d": 0 + }, + "mne/icons/clear-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/icons/help-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/icons/mne.qrc": { + "a": 14, + "d": 0 + }, + "mne/icons/movie-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/icons/pause-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/icons/play-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/icons/resources.py": { + "a": 13, + "d": 23 + }, + "mne/icons/restore-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/icons/scale-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/icons/screenshot-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/icons/visibility_off-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/icons/visibility_on-black-18dp.svg": { + "a": 0, + "d": 0 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 14, + "d": 6 + }, + "setup.cfg": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7607.json b/mne-python/source/doc/sphinxext/prs/7607.json new file mode 100644 index 0000000000000000000000000000000000000000..73a6e57d484bdb38fb4ab8681ee862095106e4e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7607.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0dbfe7f7070d82077b703a1626d5638f6a44d687", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7609.json b/mne-python/source/doc/sphinxext/prs/7609.json new file mode 100644 index 0000000000000000000000000000000000000000..8b9d3c7b3591adfb5a86c73435023e9fc37c5478 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7609.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "58984593fc3b8bbc51c8b9732b118f7ef8916677", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/filter.py": { + "a": 134, + "d": 72 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 51, + "d": 26 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + }, + "tutorials/preprocessing/plot_30_filtering_resampling.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7610.json b/mne-python/source/doc/sphinxext/prs/7610.json new file mode 100644 index 0000000000000000000000000000000000000000..f48810b180d86ec2b8e14ce68874693b62687370 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7610.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "18d2cee8e96b83a5a08fe433a2eeffddf24276ae", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 10, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7612.json b/mne-python/source/doc/sphinxext/prs/7612.json new file mode 100644 index 0000000000000000000000000000000000000000..1fd45c2a5385b7e011d0b839e266389ffc56c1bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7612.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bfbb8cbecaea6620f2625507bbf4cc321b3bd3ce", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne.qrc": { + "a": 1, + "d": 0 + }, + "mne/images/movie-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 95, + "d": 3 + }, + "mne/viz/_brain/resources.py": { + "a": 189, + "d": 161 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7613.json b/mne-python/source/doc/sphinxext/prs/7613.json new file mode 100644 index 0000000000000000000000000000000000000000..6fa279e3645544315fea3caedb59b703c69f1a45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7613.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fe1d1c6901e61a0578c76388a37af7b142597669", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7614.json b/mne-python/source/doc/sphinxext/prs/7614.json new file mode 100644 index 0000000000000000000000000000000000000000..d64e35bb9721b452b5be7a5b980b1f44d665b9e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7614.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "54177ca854ebff50b645239d781afbce441ecf2e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_vector_mne_solution.py": { + "a": 27, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 0, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 0, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 3, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7616.json b/mne-python/source/doc/sphinxext/prs/7616.json new file mode 100644 index 0000000000000000000000000000000000000000..fb760b0e94540b9aaaa15a912e840374e92781f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7616.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7157222b112d01133d49065f0f6e4824c6910ce2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_setup_forward_model.py": { + "a": 4, + "d": 0 + }, + "mne/commands/mne_setup_source_space.py": { + "a": 13, + "d": 3 + }, + "mne/commands/tests/test_commands.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7618.json b/mne-python/source/doc/sphinxext/prs/7618.json new file mode 100644 index 0000000000000000000000000000000000000000..a610e11793ffe777d0f7e9d39d1056e042b49131 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7618.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c4119388444e5867ee1a054100c78f57c9f2da25", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 69, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 21, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 94, + "d": 101 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 30, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7619.json b/mne-python/source/doc/sphinxext/prs/7619.json new file mode 100644 index 0000000000000000000000000000000000000000..53189fe2bc9984fdfba172da4b39c16b05d37674 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7619.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "972ca8c980246fc0245504889e5087d0bc14919b", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 28, + "d": 7 + }, + "mne/channels/tests/test_montage.py": { + "a": 38, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 4, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/762.json b/mne-python/source/doc/sphinxext/prs/762.json new file mode 100644 index 0000000000000000000000000000000000000000..ca7bf75f256912bc6abee412bb6d98a96bebdbf5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/762.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3e79e6279853a1dd9ac2232cd7b7079c5e25a166", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/fiff/raw.py": { + "a": 8, + "d": 2 + }, + "mne/viz.py": { + "a": 38, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7620.json b/mne-python/source/doc/sphinxext/prs/7620.json new file mode 100644 index 0000000000000000000000000000000000000000..c3a6ecc4795c3e3d73f94986083299da2cb9f6f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7620.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1d44c29cb0123f72176f251bf688be709284f522", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 24, + "d": 5 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 27, + "d": 15 + }, + "mne/viz/tests/test_3d.py": { + "a": 19, + "d": 0 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 22, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7621.json b/mne-python/source/doc/sphinxext/prs/7621.json new file mode 100644 index 0000000000000000000000000000000000000000..2ccf46340a18d31e6d1eaaf2cc974bba94ff713a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7621.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "db6f16531d0aaf826ce1fea6b47fd7e340913ba5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7623.json b/mne-python/source/doc/sphinxext/prs/7623.json new file mode 100644 index 0000000000000000000000000000000000000000..18de73802f5693265b751353447cb8175b3cd6bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7623.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "26e38513ca7be1a96b012f0853c832b2ec3b2e9f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 76, + "d": 102 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7624.json b/mne-python/source/doc/sphinxext/prs/7624.json new file mode 100644 index 0000000000000000000000000000000000000000..71e843384e76d0e4c0b5fc506917ef0d8e664f04 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7624.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "df0ace5ba0cec9cd339b87f6efb0cf97ccf79242", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/utils/config.py": { + "a": 3, + "d": 2 + }, + "mne/utils/tests/test_config.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7625.json b/mne-python/source/doc/sphinxext/prs/7625.json new file mode 100644 index 0000000000000000000000000000000000000000..95fc8e45fa7a246e3bf5c226ef0b0c70e8063cec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7625.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d058bb54eb2733c12ab2edfe8893ca72b4869931", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/surface.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7626.json b/mne-python/source/doc/sphinxext/prs/7626.json new file mode 100644 index 0000000000000000000000000000000000000000..fd7f9393ad7e78b9dc677f15fa50fd23deaee18a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7626.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1e791d703768045f34b4e0f25433979c3faba11b", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7627.json b/mne-python/source/doc/sphinxext/prs/7627.json new file mode 100644 index 0000000000000000000000000000000000000000..9cd8e8ccf1db11584a56624a60d16cc08568b1c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7627.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f1e2927d7d894935860676927d3993bce488fa8f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 63, + "d": 71 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7629.json b/mne-python/source/doc/sphinxext/prs/7629.json new file mode 100644 index 0000000000000000000000000000000000000000..42fd2bda8d902140e126284d10f219d13fb7422b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7629.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "86218c899db7e875d24d82d9f450f9036aa073e7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/tests/test_external.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 4, + "d": 2 + }, + "mne/epochs.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 46, + "d": 27 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/763.json b/mne-python/source/doc/sphinxext/prs/763.json new file mode 100644 index 0000000000000000000000000000000000000000..26d62c22f814edef452ee2ea364cfd109fc7de36 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/763.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "65324a60211320696e44b7e5ca9ca4e3efb292da", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "bin/mne_kit2fiff.py": { + "a": 11, + "d": 11 + }, + "mne/fiff/kit/constants.py": { + "a": 11, + "d": 11 + }, + "mne/fiff/kit/coreg.py": { + "a": 147, + "d": 175 + }, + "mne/fiff/kit/kit.py": { + "a": 277, + "d": 83 + }, + "mne/fiff/kit/tests/test_coreg.py": { + "a": 75, + "d": 0 + }, + "mne/fiff/kit/tests/test_kit.py": { + "a": 42, + "d": 40 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7630.json b/mne-python/source/doc/sphinxext/prs/7630.json new file mode 100644 index 0000000000000000000000000000000000000000..681935391e9cf79932b1af0a89e31ddea132e090 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7630.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "46197d4926f4654dc1df2e0cabbfb26642fd884d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 3 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 17, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7634.json b/mne-python/source/doc/sphinxext/prs/7634.json new file mode 100644 index 0000000000000000000000000000000000000000..cd71729916cbf0e3a0d57eff564a8ed0a9b06c37 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7634.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7f8f5b595d9f4203c66e56c9ab9f7a9cc2a07759", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7638.json b/mne-python/source/doc/sphinxext/prs/7638.json new file mode 100644 index 0000000000000000000000000000000000000000..9fd877e72c6df5a7062d5052e7e6b9ecd915ae17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7638.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "24eae37c4098b897bfa170524e4788c5d8d5283e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 4, + "d": 4 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + }, + "doc/install/mne_python.rst": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 5, + "d": 4 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 2, + "d": 4 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 7, + "d": 10 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 9 + }, + "mne/channels/tests/test_montage.py": { + "a": 11, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 23 + }, + "mne/datasets/utils.py": { + "a": 1, + "d": 2 + }, + "mne/fixes.py": { + "a": 0, + "d": 16 + }, + "mne/io/_digitization.py": { + "a": 6, + "d": 10 + }, + "mne/io/what.py": { + "a": 1, + "d": 3 + }, + "mne/io/write.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7639.json b/mne-python/source/doc/sphinxext/prs/7639.json new file mode 100644 index 0000000000000000000000000000000000000000..4b0de5a59ee127c2fb40cced1c38f933757908aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7639.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "676ed97f4500511b1dca88ecb1f1ee25dc705d19", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 7, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 21, + "d": 1 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 317, + "d": 173 + }, + "mne/source_space.py": { + "a": 321, + "d": 229 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 167, + "d": 7 + }, + "mne/tests/test_source_space.py": { + "a": 71, + "d": 33 + }, + "mne/transforms.py": { + "a": 7, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 78, + "d": 14 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7640.json b/mne-python/source/doc/sphinxext/prs/7640.json new file mode 100644 index 0000000000000000000000000000000000000000..def5a1be366da883093570574926513ff604549f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7640.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2376ad38fe1aac01ac9bc2c327100bba4a86b6d0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 6, + "d": 6 + }, + "mne/tests/test_report.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7641.json b/mne-python/source/doc/sphinxext/prs/7641.json new file mode 100644 index 0000000000000000000000000000000000000000..5f461e529527f374b03c030f0a706d2928bf6346 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7641.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6004b08a5f5880c4c74c2d5dbe078096e9c229db", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 8, + "d": 5 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 17, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7642.json b/mne-python/source/doc/sphinxext/prs/7642.json new file mode 100644 index 0000000000000000000000000000000000000000..a37567fcb4b33c5fc968a5181a67946e227d87b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7642.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "d6a4eb056617056d31d2c71ecf1b6d9287015139", + "authors": [ + { + "n": "Britta Westner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 10, + "d": 24 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 9, + "d": 8 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/linalg.py": { + "a": 16, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 2, + "d": 1 + }, + "mne/utils/tests/test_linalg.py": { + "a": 72, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7643.json b/mne-python/source/doc/sphinxext/prs/7643.json new file mode 100644 index 0000000000000000000000000000000000000000..9c8a060769aaea514e0e8ee19cd8da2969ac7565 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7643.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "87e7157a932d4625a5aeb788bd35514d2bdb9f5a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 12, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7646.json b/mne-python/source/doc/sphinxext/prs/7646.json new file mode 100644 index 0000000000000000000000000000000000000000..dfd78008c7f41d1394f0aabc4abf129db0082ab5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7646.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "fd43bbe2ca013d742b3d082f0284c2d73d06a52a", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/_includes/dig_formats.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/0.19.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "mne/channels/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 40, + "d": 10 + }, + "mne/channels/tests/test_montage.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7647.json b/mne-python/source/doc/sphinxext/prs/7647.json new file mode 100644 index 0000000000000000000000000000000000000000..f11a9bcc8c4e8a8ac98b3ecb2229c48aade47305 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7647.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1270bb8d3d842f9e7c27f7a9855280e06033958c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 42, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 87, + "d": 78 + }, + "mne/tests/test_source_estimate.py": { + "a": 45, + "d": 25 + }, + "mne/utils/docs.py": { + "a": 13, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7649.json b/mne-python/source/doc/sphinxext/prs/7649.json new file mode 100644 index 0000000000000000000000000000000000000000..48bbebe3a34a18c97eaf72631dfc49d41c33a832 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7649.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3cb776d78d9286eab9d83959fcd9ee0169a7516d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 34, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/765.json b/mne-python/source/doc/sphinxext/prs/765.json new file mode 100644 index 0000000000000000000000000000000000000000..bbc17c501be83aa2a36ec92ef413d8bd903ebb19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/765.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b10acb752ca725c28db33af0bf97e4c6a4ea75f0", + "authors": [ + { + "n": "Yousra BEKHTI", + "e": "yousra.bekhti@gmail.com" + } + ], + "changes": { + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7650.json b/mne-python/source/doc/sphinxext/prs/7650.json new file mode 100644 index 0000000000000000000000000000000000000000..2289c5e9e18f4e7e514b0eac6f66a713a9c71d31 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7650.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b111b2ebdbbb98e1fc80c70ac6b30d96c4133953", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/_ola.py": { + "a": 33, + "d": 26 + }, + "mne/tests/test_ola.py": { + "a": 11, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7651.json b/mne-python/source/doc/sphinxext/prs/7651.json new file mode 100644 index 0000000000000000000000000000000000000000..cfd16708dabd474ca5f37a2af61fe1d22a36c212 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7651.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "066db2d13e4520db3b04c6610f0dfb508ff54871", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_envelope_correlation_volume.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7653.json b/mne-python/source/doc/sphinxext/prs/7653.json new file mode 100644 index 0000000000000000000000000000000000000000..fcafed6b2ad3c2f112676e0b22df02ea232be585 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7653.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "beaff02d91a80c2cf12e626d47b3f1678188472d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/source_space.py": { + "a": 11, + "d": 13 + }, + "mne/tests/test_morph.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7656.json b/mne-python/source/doc/sphinxext/prs/7656.json new file mode 100644 index 0000000000000000000000000000000000000000..d6c3fabe309b37512b7664e919db01dfed7ad955 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7656.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "1391ad239bfbc1ad989bda0f578a397b96db4c66", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "britta-wstnr", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Alex", + "e": "aprockhill206@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 11, + "d": 0 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 19, + "d": 14 + }, + "examples/inverse/plot_tf_lcmv.py": { + "a": 0, + "d": 145 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 164, + "d": 167 + }, + "mne/beamformer/_dics.py": { + "a": 113, + "d": 105 + }, + "mne/beamformer/_lcmv.py": { + "a": 88, + "d": 53 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 130, + "d": 78 + }, + "mne/beamformer/tests/test_external.py": { + "a": 22, + "d": 15 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 178, + "d": 26 + }, + "mne/cov.py": { + "a": 14, + "d": 8 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 60, + "d": 0 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/rank.py": { + "a": 10, + "d": 8 + }, + "mne/time_frequency/csd.py": { + "a": 26, + "d": 6 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 3 + }, + "mne/utils/check.py": { + "a": 14, + "d": 14 + }, + "mne/utils/docs.py": { + "a": 58, + "d": 0 + }, + "mne/utils/linalg.py": { + "a": 21, + "d": 20 + }, + "mne/utils/numerics.py": { + "a": 32, + "d": 37 + }, + "mne/utils/tests/test_linalg.py": { + "a": 43, + "d": 12 + }, + "mne/utils/tests/test_numerics.py": { + "a": 8, + "d": 4 + }, + "tutorials/simulation/plot_dics.py": { + "a": 6, + "d": 4 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7658.json b/mne-python/source/doc/sphinxext/prs/7658.json new file mode 100644 index 0000000000000000000000000000000000000000..2ef39aac3d62a54b1a5d0c3224b9a31e19080bb8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7658.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b437776e8ebd8bd8295e90b50f0fd8c257ed7f2e", + "authors": [ + { + "n": "Yu-Han Luo", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 16, + "d": 21 + }, + "mne/commands/tests/test_commands.py": { + "a": 23, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7659.json b/mne-python/source/doc/sphinxext/prs/7659.json new file mode 100644 index 0000000000000000000000000000000000000000..4379ebd38d5f13ac9e99421524b99272222bcdd6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7659.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "76f871511db93f11c27177a712df48b259092bdd", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/visualization/plot_parcellation.py": { + "a": 1, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 197, + "d": 18 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 19, + "d": 3 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 2 + }, + "mne/viz/backends/base_renderer.py": { + "a": 16, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/766.json b/mne-python/source/doc/sphinxext/prs/766.json new file mode 100644 index 0000000000000000000000000000000000000000..c5c481090bea2d7812cb9f5694fcd04ca4e19ec1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/766.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "ae5165b2eb96d8adef298148f015cca1f7e5979a", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 9, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 6, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/coreg.py": { + "a": 5, + "d": 0 + }, + "mne/fiff/kit/tests/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/fiff/kit/tests/data/test_mrk_post.sqd": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/data/test_mrk_pre.sqd": { + "a": 0, + "d": 0 + }, + "mne/fiff/tests/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 89, + "d": 0 + }, + "mne/gui/_coreg_gui.py": { + "a": 1372, + "d": 0 + }, + "mne/gui/_fiducials_gui.py": { + "a": 462, + "d": 0 + }, + "mne/gui/_file_traits.py": { + "a": 427, + "d": 0 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 518, + "d": 0 + }, + "mne/gui/_marker_gui.py": { + "a": 447, + "d": 0 + }, + "mne/gui/_viewer.py": { + "a": 340, + "d": 0 + }, + "mne/gui/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 157, + "d": 0 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 68, + "d": 0 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 110, + "d": 0 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 65, + "d": 0 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 47, + "d": 0 + }, + "mne/utils.py": { + "a": 7, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7660.json b/mne-python/source/doc/sphinxext/prs/7660.json new file mode 100644 index 0000000000000000000000000000000000000000..3ac730938f17cf31af5a3f39edb4e53f6d1c5f5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7660.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "58b42b381561f0256fda54385a903701ab4f0247", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 4, + "d": 6 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7663.json b/mne-python/source/doc/sphinxext/prs/7663.json new file mode 100644 index 0000000000000000000000000000000000000000..54f491ec5b95a94303d7aaf3a557cea0c836acc6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7663.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a0691c8c8c0431b14fee57fecd35986e6f34e07f", + "authors": [ + { + "n": "Yu-Han Luo", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 5, + "d": 9 + }, + "mne/commands/tests/test_commands.py": { + "a": 18, + "d": 13 + }, + "mne/datasets/sample/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/datasets/sample/sample.py": { + "a": 1, + "d": 27 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 5, + "d": 44 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7664.json b/mne-python/source/doc/sphinxext/prs/7664.json new file mode 100644 index 0000000000000000000000000000000000000000..5fa8a67bc8f441446c1ebdd96239bfd706f50ce0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7664.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0ccd8028f8a2bbcf74595cce3649d1756b77dfdd", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 77, + "d": 27 + }, + "mne/viz/tests/test_misc.py": { + "a": 32, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7665.json b/mne-python/source/doc/sphinxext/prs/7665.json new file mode 100644 index 0000000000000000000000000000000000000000..edee70a3d3a1ecc42c0b7f5af5c6fed071cde08f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7665.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b8960d8d46fd4db6b1c4f07fdc94353942235e8d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7667.json b/mne-python/source/doc/sphinxext/prs/7667.json new file mode 100644 index 0000000000000000000000000000000000000000..6ddbc7d0822f1d50af1d959b80265106394ec4ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7667.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "01750aad31508519ecfe3e7945e54a3fbe1c9bbe", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 41, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 47, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 85, + "d": 1 + }, + "mne/io/_digitization.py": { + "a": 61, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7668.json b/mne-python/source/doc/sphinxext/prs/7668.json new file mode 100644 index 0000000000000000000000000000000000000000..65523a765c2f24f27308bd24d16954c1f9a65a1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7668.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "16ee599cba2758a6c645f79ce018f226ebcd303a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 12, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/767.json b/mne-python/source/doc/sphinxext/prs/767.json new file mode 100644 index 0000000000000000000000000000000000000000..50ff3f465726cde4ed7f3c41bbe4df0f3244235a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/767.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a94e1347ee5c083098e83f3591bc83ffa8a6b7f1", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7670.json b/mne-python/source/doc/sphinxext/prs/7670.json new file mode 100644 index 0000000000000000000000000000000000000000..633e1d752e913a58184a44ed4dad44676c6300d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7670.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4415abb6388f8abd2249a0f09056de2f537736ac", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 3, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7672.json b/mne-python/source/doc/sphinxext/prs/7672.json new file mode 100644 index 0000000000000000000000000000000000000000..7e79091c09fd5e22a213bbed2bde661e495d1a84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7672.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d0b8bcf5201d7b5c278e7410e4035dc5aead30b8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 10, + "d": 4 + }, + ".travis.yml": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7674.json b/mne-python/source/doc/sphinxext/prs/7674.json new file mode 100644 index 0000000000000000000000000000000000000000..646891be724adc75508e30b95b596b28620993b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7674.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b10e14592689f70e5f6cab48a1e0d439b92733c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 6, + "d": 3 + }, + ".travis.yml": { + "a": 4, + "d": 4 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/install/mne_python.rst": { + "a": 21, + "d": 19 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 29, + "d": 26 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7675.json b/mne-python/source/doc/sphinxext/prs/7675.json new file mode 100644 index 0000000000000000000000000000000000000000..c8fd14a9c1997dcbfda88c5c8771263668ab4390 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7675.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5ce8a086a67be5ac433f56023efab366310c9932", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7677.json b/mne-python/source/doc/sphinxext/prs/7677.json new file mode 100644 index 0000000000000000000000000000000000000000..06945d130888e4c9674fdf9be34baa801fa0cac9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7677.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "df14ae94ff76572cf1896392910eb76f34a9f9da", + "authors": [ + { + "n": "Mainak Jas", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/preprocessing/plot_20_rejecting_bad_data.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7682.json b/mne-python/source/doc/sphinxext/prs/7682.json new file mode 100644 index 0000000000000000000000000000000000000000..b48f8493a52b27a65f353923ae60977fb0826280 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7682.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0adc1699cc235c0d3b9a5588cbd2dec818a59fd1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/overview/roadmap.rst": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 12 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7685.json b/mne-python/source/doc/sphinxext/prs/7685.json new file mode 100644 index 0000000000000000000000000000000000000000..d285e2156536f868341c8400a3517160a003d330 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7685.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c166d0fe07c12fe859d6fe3cdd09449f70e450ba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 9 + }, + "mne/channels/montage.py": { + "a": 18, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 44, + "d": 7 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7686.json b/mne-python/source/doc/sphinxext/prs/7686.json new file mode 100644 index 0000000000000000000000000000000000000000..3d8b8b2b3731e7b40e53245203f2759c9a93a0a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7686.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "68acfab7b6ffa3b5fb90f0d7e23915c482d7e9cb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/stats/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 7 + }, + "mne/stats/parametric.py": { + "a": 49, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 40, + "d": 1 + }, + "mne/stats/tests/test_parametric.py": { + "a": 46, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7687.json b/mne-python/source/doc/sphinxext/prs/7687.json new file mode 100644 index 0000000000000000000000000000000000000000..10151c17712597caf186d8366bb8f9875aac1059 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7687.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cef447520ed78dc3849ed78f906a8106eb0885fb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7688.json b/mne-python/source/doc/sphinxext/prs/7688.json new file mode 100644 index 0000000000000000000000000000000000000000..28954a4eab7bd9e931cb352c022f57ed3ed6c093 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7688.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5f4c9046fb07cf75a316d56d809e4b7266753ceb", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 16, + "d": 16 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 4, + "d": 4 + }, + "mne/viz/backends/renderer.py": { + "a": 14, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7690.json b/mne-python/source/doc/sphinxext/prs/7690.json new file mode 100644 index 0000000000000000000000000000000000000000..1e3807ef8321879133e6b88a7d79dabb95445bee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7690.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "9e0e02fa2f5995d4a41cb539fe1813a2e4b9d649", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 16, + "d": 0 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 4, + "d": 3 + }, + "mne/utils/check.py": { + "a": 1, + "d": 0 + }, + "mne/utils/tests/test_logging.py": { + "a": 72, + "d": 70 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7695.json b/mne-python/source/doc/sphinxext/prs/7695.json new file mode 100644 index 0000000000000000000000000000000000000000..1472a411f5c072818babc1c24e979bbde9a4b7e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7695.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9eeb1e2e3758e894cac05f7139d19c6e1d61072a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 8, + "d": 28 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7698.json b/mne-python/source/doc/sphinxext/prs/7698.json new file mode 100644 index 0000000000000000000000000000000000000000..de66ff8b24e0fc56e2fa7801072ff6612dbf0f2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7698.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7096a3dbf38e6722f1e6383baea24df55e615aad", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/icons/mne.qrc": { + "a": 10, + "d": 10 + }, + "mne/icons/movie-black-18dp.svg": { + "a": 72, + "d": 1 + }, + "mne/icons/resources.py": { + "a": 332, + "d": 182 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7699.json b/mne-python/source/doc/sphinxext/prs/7699.json new file mode 100644 index 0000000000000000000000000000000000000000..9bf1a81f277f13056fe9e52a17cad8e21e9e9471 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7699.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e9c8a90b770cf345d3f5dca8d9623922e0cd0298", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/multitaper.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/77.json b/mne-python/source/doc/sphinxext/prs/77.json new file mode 100644 index 0000000000000000000000000000000000000000..cd9d840fc052c62acc809c57f8a59ae96e95cb25 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/77.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1c24cddb93f15771a8a5b50d2c9d128d4564d20d", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/manual/convert.rst": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7700.json b/mne-python/source/doc/sphinxext/prs/7700.json new file mode 100644 index 0000000000000000000000000000000000000000..979d7eb4c193bee895fb87c813edbb97e7270c3d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7700.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a2fab967c637309caa07b9e58f3b6294cb58902f", + "authors": [ + { + "n": "Anton Nikolas Waniek", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7701.json b/mne-python/source/doc/sphinxext/prs/7701.json new file mode 100644 index 0000000000000000000000000000000000000000..925d8fc3f26920038710d1c5eb49947c510ae042 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7701.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "163ffb90958f997d3b95180b1f11f0255abb8247", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 7, + "d": 7 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7702.json b/mne-python/source/doc/sphinxext/prs/7702.json new file mode 100644 index 0000000000000000000000000000000000000000..c0e581ab164831f94ad5d6f0a8b00cb166adc4a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7702.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3b5a497235b80688b6609f266c0386b05d83340c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7703.json b/mne-python/source/doc/sphinxext/prs/7703.json new file mode 100644 index 0000000000000000000000000000000000000000..62d500590045703509b46fb90529ba9c1b623aab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7703.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c66e1a262ee192627c39a77a85c7b3494a8949b9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_vector_mne_solution.py": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 47, + "d": 30 + }, + "mne/tests/test_source_estimate.py": { + "a": 51, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7704.json b/mne-python/source/doc/sphinxext/prs/7704.json new file mode 100644 index 0000000000000000000000000000000000000000..aa697aa8ea6f5cc298248bce70d9c27fe9fd6f9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7704.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5b45394a3a0c16097ceda56ee2500348b9b1827a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 6 + }, + ".travis.yml": { + "a": 1, + "d": 12 + }, + "MANIFEST.in": { + "a": 2, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 61, + "d": 6 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 2 + }, + "mne/utils/config.py": { + "a": 0, + "d": 1 + }, + "tools/get_minimal_commands.sh": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7705.json b/mne-python/source/doc/sphinxext/prs/7705.json new file mode 100644 index 0000000000000000000000000000000000000000..fdb74297b2df830de06b3753426eea2205f63ad4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7705.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a837aa3206e7826eb20c92cacebbddda8b0a6f2a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 17, + "d": 1 + }, + "examples/decoding/plot_linear_model_patterns.py": { + "a": 12, + "d": 13 + }, + "examples/decoding/plot_receptive_field_mtrf.py": { + "a": 25, + "d": 23 + }, + "mne/decoding/base.py": { + "a": 4, + "d": 10 + }, + "tutorials/machine-learning/plot_sensors_decoding.py": { + "a": 20, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7706.json b/mne-python/source/doc/sphinxext/prs/7706.json new file mode 100644 index 0000000000000000000000000000000000000000..c19dded20c10028e4ef766b9cc63f6bb518f9036 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7706.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "9ad12c935539d9ca0e6af0de90113f2fa8fc483e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 4, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 117, + "d": 123 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7707.json b/mne-python/source/doc/sphinxext/prs/7707.json new file mode 100644 index 0000000000000000000000000000000000000000..b34421687722c71f49445ca3d04e9750aaae93c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7707.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "30646229f23cee554884fe144726baf7947ff0a1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7708.json b/mne-python/source/doc/sphinxext/prs/7708.json new file mode 100644 index 0000000000000000000000000000000000000000..72971ef74b6f25a10f56337907b05c3cb00e778e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7708.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2dc244f7bb55a6f4bc119aab055290f601270d02", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/backends/renderer.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/771.json b/mne-python/source/doc/sphinxext/prs/771.json new file mode 100644 index 0000000000000000000000000000000000000000..62c112356161091b435e4c304800c3ce09575a03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/771.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "85cb206d94758ff747e5a37eecf5e4094b2ff187", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 5, + "d": 3 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 80 + }, + "mne/surface.py": { + "a": 266, + "d": 4 + }, + "mne/tests/test_surface.py": { + "a": 17, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7712.json b/mne-python/source/doc/sphinxext/prs/7712.json new file mode 100644 index 0000000000000000000000000000000000000000..11c6b7e55c8c800f35eeb46e8dac53646903e7f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7712.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6d044fedb3841ee3c65fb8e7dcc05225a0773268", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7714.json b/mne-python/source/doc/sphinxext/prs/7714.json new file mode 100644 index 0000000000000000000000000000000000000000..85a4cba76200d10fd92223a626f2b592fb3efb8f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7714.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "52fc7a9c2147c2f28ebe2d17eecb20978e859082", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 6, + "d": 4 + }, + "tutorials/source-modeling/plot_dipole_fit.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7717.json b/mne-python/source/doc/sphinxext/prs/7717.json new file mode 100644 index 0000000000000000000000000000000000000000..8fcee156800eeaccef8da260d11fe719dbe0ce2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7717.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "832f48c28f212a9bb0312d2555e1f0f4754e9f36", + "authors": [ + { + "n": "Kyle Mathewson", + "e": "kylemath@gmail.com" + }, + { + "n": "Kyle Mathewson", + "e": "kylemath@gmail.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Jonathan Kuziek", + "e": "kuziek@ualberta.ca" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + } + ], + "changes": { + "doc/_includes/data_formats.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 13, + "d": 4 + }, + "mne/defaults.py": { + "a": 8, + "d": 2 + }, + "mne/evoked.py": { + "a": 8, + "d": 8 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/boxy/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/boxy/boxy.py": { + "a": 262, + "d": 0 + }, + "mne/io/boxy/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/boxy/tests/test_boxy.py": { + "a": 190, + "d": 0 + }, + "mne/io/pick.py": { + "a": 37, + "d": 20 + }, + "mne/io/utils.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_defaults.py": { + "a": 3, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "tutorials/io/plot_30_reading_fnirs_data.py": { + "a": 29, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/772.json b/mne-python/source/doc/sphinxext/prs/772.json new file mode 100644 index 0000000000000000000000000000000000000000..25cbcd953467040a762dfc353133f0dd78c0ffde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/772.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2478b3173310439d04edd6a117e71ed6909810db", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 26, + "d": 18 + }, + "mne/utils.py": { + "a": 13, + "d": 0 + }, + "mne/viz.py": { + "a": 169, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7722.json b/mne-python/source/doc/sphinxext/prs/7722.json new file mode 100644 index 0000000000000000000000000000000000000000..af950158acc5539286c3f6b330d2175a28a925ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7722.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "282754ec94cf018f62feb91750296a5dfb537187", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7724.json b/mne-python/source/doc/sphinxext/prs/7724.json new file mode 100644 index 0000000000000000000000000000000000000000..02da041c741911dd7e852168fc0041144dbc1a00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7724.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "44ea73e9bf02fab3152331d462ddeaad1a06baa2", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/index.rst": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7725.json b/mne-python/source/doc/sphinxext/prs/7725.json new file mode 100644 index 0000000000000000000000000000000000000000..b00e2d8fa9f6abd469fb5967250b96e13e0fa32a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7725.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5b7d8170804167b81965cb30c65f8abbd8ebedf5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 33, + "d": 42 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7726.json b/mne-python/source/doc/sphinxext/prs/7726.json new file mode 100644 index 0000000000000000000000000000000000000000..24f977f9cba7edad1bcf179d8426cd5211bfe201 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7726.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ba988750f43314760a1af15761f6dac776bc51ba", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 61, + "d": 97 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7728.json b/mne-python/source/doc/sphinxext/prs/7728.json new file mode 100644 index 0000000000000000000000000000000000000000..4714550232edea67b2b1ea7a90ff7681d8f66094 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7728.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "96420e71ab6fad2d4cc702c230b342d3743d2ebc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/morph.py": { + "a": 66, + "d": 44 + }, + "mne/tests/test_morph.py": { + "a": 46, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7729.json b/mne-python/source/doc/sphinxext/prs/7729.json new file mode 100644 index 0000000000000000000000000000000000000000..8bae0d17445cba3841953fed6fb07f3c478b52a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7729.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4ef1a84b2c8a81b04c1e018bd36963697723ff63", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 3, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7730.json b/mne-python/source/doc/sphinxext/prs/7730.json new file mode 100644 index 0000000000000000000000000000000000000000..855d9bb4226d2d508b0b96f4ec5e5815309fd533 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7730.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6f59cd9e2a39ef5783aa67856e251226d24fad43", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7731.json b/mne-python/source/doc/sphinxext/prs/7731.json new file mode 100644 index 0000000000000000000000000000000000000000..af26d6894d53b8df3716e382dcb7c03ef438375f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7731.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ef16a2d7f38f78ceb4401d41dfa4afee1846889e", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 6, + "d": 2 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7733.json b/mne-python/source/doc/sphinxext/prs/7733.json new file mode 100644 index 0000000000000000000000000000000000000000..5ea9cb2516fd1e93dd10aaadeedfc24cf9e61dc4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7733.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2cad786d17c3126e4cfbe9dc140671b5c5d51bcc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 25, + "d": 11 + }, + "mne/tests/test_epochs.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7734.json b/mne-python/source/doc/sphinxext/prs/7734.json new file mode 100644 index 0000000000000000000000000000000000000000..91cbcdcf382694c2f41c8da7c664d7bb636c4568 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7734.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "92914823931c1e330f79b91f4ff6d7f3ff397d7c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 37, + "d": 24 + }, + "mne/morph.py": { + "a": 152, + "d": 96 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_morph.py": { + "a": 97, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7735.json b/mne-python/source/doc/sphinxext/prs/7735.json new file mode 100644 index 0000000000000000000000000000000000000000..910ab6abd42f1d031540002959d480184fa39e0d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7735.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "12fc0e7686be7fdf07e28ca97370c2fafed9c6be", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 5, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7736.json b/mne-python/source/doc/sphinxext/prs/7736.json new file mode 100644 index 0000000000000000000000000000000000000000..abb9b339c3dbe3b66d22611ff17e18bc37ff632a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7736.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "426ab6f954b54c224dd5f41582c19d461f91ca78", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/rank.py": { + "a": 25, + "d": 19 + }, + "mne/tests/test_rank.py": { + "a": 33, + "d": 13 + }, + "mne/utils/docs.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7737.json b/mne-python/source/doc/sphinxext/prs/7737.json new file mode 100644 index 0000000000000000000000000000000000000000..b39001b1c625c6d8a5f511be8a140e6a14ae48bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7737.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7618a58eb45b75c3f00f08ebf18738f0f41e0886", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 29, + "d": 11 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7740.json b/mne-python/source/doc/sphinxext/prs/7740.json new file mode 100644 index 0000000000000000000000000000000000000000..4e2a40fb7b1ae7956b2050b2a9f7450fb338ed90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7740.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "d0dc8f3d51cfd0db8bcec8f1adee98050152d2df", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/transformer.py": { + "a": 4, + "d": 2 + }, + "mne/epochs.py": { + "a": 40, + "d": 8 + }, + "mne/io/base.py": { + "a": 4, + "d": 5 + }, + "mne/io/write.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 34, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7742.json b/mne-python/source/doc/sphinxext/prs/7742.json new file mode 100644 index 0000000000000000000000000000000000000000..d1dc8d45e67ff5cacc2cbdb7f7711941830889e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7742.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "fdb2eaf26bc4b55bf89140eb6832b93bd9d40971", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7747.json b/mne-python/source/doc/sphinxext/prs/7747.json new file mode 100644 index 0000000000000000000000000000000000000000..063f03027e7d4cad6e678265e065b38455300b2a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7747.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4f493e1fd240acab1a3838a8c3f82fa062b76e97", + "authors": [ + { + "n": "Kyle Mathewson", + "e": "kylemath@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/defaults.py": { + "a": 5, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 30, + "d": 7 + }, + "mne/viz/tests/test_3d.py": { + "a": 29, + "d": 0 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7748.json b/mne-python/source/doc/sphinxext/prs/7748.json new file mode 100644 index 0000000000000000000000000000000000000000..d0cbb266f882ab0811e3730400042846c85b57db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7748.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "899c40f7cf9b2bc4ca1ffab0ee3dd875c893b921", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/autosummary/class.rst": { + "a": 4, + "d": 3 + }, + "doc/_templates/autosummary/function.rst": { + "a": 3, + "d": 2 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 4, + "d": 0 + }, + "mne/morph.py": { + "a": 4, + "d": 2 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 4, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7749.json b/mne-python/source/doc/sphinxext/prs/7749.json new file mode 100644 index 0000000000000000000000000000000000000000..0dc1de786663efe7c40be229b678e5b529273b4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7749.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a2095faa49b115b9668dd4c94b94590088a18ac5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "README.rst": { + "a": 8, + "d": 3 + }, + "codecov.yml": { + "a": 18, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/775.json b/mne-python/source/doc/sphinxext/prs/775.json new file mode 100644 index 0000000000000000000000000000000000000000..dc06ddcc0afcaef4937a48ba3428e2a850f70d90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/775.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "911e95f4cc8825f07395e6cb55d6a3d2a37bca59", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/fiff/bti/raw.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 10, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 17, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7750.json b/mne-python/source/doc/sphinxext/prs/7750.json new file mode 100644 index 0000000000000000000000000000000000000000..ed46d3538968d7c2dc5b9bf45613d7b0067a27ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7750.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d61b28174b8ada91774c99bb636f51170446c5f4", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7752.json b/mne-python/source/doc/sphinxext/prs/7752.json new file mode 100644 index 0000000000000000000000000000000000000000..851f084b36830ea542a1d04749a6756b4b87ec1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7752.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "09530fdb7a8c197f852bd0f91c9ddeaaca964ffc", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 15, + "d": 16 + }, + "mne/channels/tests/test_montage.py": { + "a": 0, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7754.json b/mne-python/source/doc/sphinxext/prs/7754.json new file mode 100644 index 0000000000000000000000000000000000000000..8f28429bf1d50de3f62618d13d4f1dbee277eb13 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7754.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "807b02405750d7173298f7d1defdf244f70d5488", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7755.json b/mne-python/source/doc/sphinxext/prs/7755.json new file mode 100644 index 0000000000000000000000000000000000000000..728643be16e25a440b79eddd3d03b01cef17b775 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7755.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "de3128b5f3434490943eff92dd9a4efbb5a8dca2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 14, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 7, + "d": 3 + }, + "mne/label.py": { + "a": 34, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7756.json b/mne-python/source/doc/sphinxext/prs/7756.json new file mode 100644 index 0000000000000000000000000000000000000000..85b0a56a535e569ce5103300e7aca6d08edf69f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7756.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "60b2b2448173bb6d0fbd1c332bbf7669c6213bfa", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 7, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 14, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7758.json b/mne-python/source/doc/sphinxext/prs/7758.json new file mode 100644 index 0000000000000000000000000000000000000000..ff557acad6b7a6c0e69fad85e9f9c6ec3a07cd6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7758.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "64499b764a77bd2ccdfcf397c3cd0a6b7b7f6e6d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 51, + "d": 12 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/install/advanced.rst": { + "a": 13, + "d": 0 + }, + "doc/install/mne_python.rst": { + "a": 7, + "d": 0 + }, + "mne/conftest.py": { + "a": 20, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 14, + "d": 8 + }, + "mne/viz/_brain/_brain.py": { + "a": 16, + "d": 1 + }, + "mne/viz/_brain/_notebook.py": { + "a": 40, + "d": 0 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 25, + "d": 11 + }, + "mne/viz/_brain/tests/test.ipynb": { + "a": 62, + "d": 0 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 22, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 164, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 14, + "d": 3 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 5, + "d": 1 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 19, + "d": 1 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 1, + "d": 2 + }, + "server_environment.yml": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7759.json b/mne-python/source/doc/sphinxext/prs/7759.json new file mode 100644 index 0000000000000000000000000000000000000000..56b22e12aa14881969df855e9f7bfe0e6649daa8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7759.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "861e82505ce59e7ea84887227d6066776bdc6401", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 31, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/776.json b/mne-python/source/doc/sphinxext/prs/776.json new file mode 100644 index 0000000000000000000000000000000000000000..1ce5dfb38b81b4e33620c8da66f3ac36e4be86c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/776.json @@ -0,0 +1,127 @@ +{ + "merge_commit_sha": "f9fc2a38040605e4972bc64647d7ab5a3e446267", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 3, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 4, + "d": 0 + }, + "examples/plot_make_forward.py": { + "a": 54, + "d": 0 + }, + "examples/plot_read_forward.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 4, + "d": 2 + }, + "mne/data/coil_def.dat": { + "a": 416, + "d": 0 + }, + "mne/fiff/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/compensator.py": { + "a": 5, + "d": 6 + }, + "mne/fiff/constants.py": { + "a": 42, + "d": 0 + }, + "mne/fiff/meas_info.py": { + "a": 24, + "d": 2 + }, + "mne/fiff/pick.py": { + "a": 2, + "d": 0 + }, + "mne/fiff/tag.py": { + "a": 5, + "d": 1 + }, + "mne/fiff/tests/data/sample-audvis-raw-trans.txt": { + "a": 4, + "d": 0 + }, + "mne/fiff/write.py": { + "a": 22, + "d": 1 + }, + "mne/forward/__init__.py": { + "a": 12, + "d": 0 + }, + "mne/forward/_compute_forward.py": { + "a": 346, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 474, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 172, + "d": 96 + }, + "mne/forward/tests/test_forward.py": { + "a": 51, + "d": 92 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 172, + "d": 0 + }, + "mne/proj.py": { + "a": 11, + "d": 7 + }, + "mne/source_space.py": { + "a": 28, + "d": 14 + }, + "mne/surface.py": { + "a": 323, + "d": 187 + }, + "mne/tests/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 16 + }, + "mne/tests/test_source_space.py": { + "a": 9, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 28, + "d": 5 + }, + "mne/tests/test_transforms.py": { + "a": 14, + "d": 1 + }, + "mne/transforms.py": { + "a": 22, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7761.json b/mne-python/source/doc/sphinxext/prs/7761.json new file mode 100644 index 0000000000000000000000000000000000000000..291a95f0fce171758f4d18eb155b0b3b1975984a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7761.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9455fa845d393b6f083d266d337173826867a500", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 20, + "d": 18 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 48, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7762.json b/mne-python/source/doc/sphinxext/prs/7762.json new file mode 100644 index 0000000000000000000000000000000000000000..886864513b00166181df86f4fc64de27f23a5a47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7762.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "224cce85577ab8fc4f66a48eba684c1fd31bfc5b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/overview/roadmap.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7763.json b/mne-python/source/doc/sphinxext/prs/7763.json new file mode 100644 index 0000000000000000000000000000000000000000..6b6e3392eed70ca7bab7802f4858c277747ac367 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7763.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "cd84e02cf7ae2462272e1b2226a562694daa2763", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 2 + }, + "examples/visualization/plot_make_report.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 23, + "d": 39 + }, + "mne/tests/test_report.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 119 + }, + "mne/viz/misc.py": { + "a": 109, + "d": 48 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7764.json b/mne-python/source/doc/sphinxext/prs/7764.json new file mode 100644 index 0000000000000000000000000000000000000000..6d1e103990dfc193a37db2c44036aebaec515c9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7764.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3e12ef4d12f5178b13631bbaf667e2a97dc62525", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7766.json b/mne-python/source/doc/sphinxext/prs/7766.json new file mode 100644 index 0000000000000000000000000000000000000000..76635aefbd8c9d54df850ec3108e01e9b16d667d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7766.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4140bc82aed2cb9d032782ab989e26e01879e3c7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/index.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7767.json b/mne-python/source/doc/sphinxext/prs/7767.json new file mode 100644 index 0000000000000000000000000000000000000000..50065346712813fd3399fe32b3b15ad985954020 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7767.json @@ -0,0 +1,119 @@ +{ + "merge_commit_sha": "ed6f12f3a292665b41554ddb590d18e3d8d44e7a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 4, + "d": 4 + }, + "mne/surface.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 8, + "d": 8 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + }, + "mne/utils/numerics.py": { + "a": 4, + "d": 4 + }, + "mne/utils/tests/test_logging.py": { + "a": 2, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 17, + "d": 17 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 4, + "d": 4 + }, + "mne/viz/raw.py": { + "a": 5, + "d": 4 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 3 + }, + "tutorials/simulation/plot_point_spread.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7768.json b/mne-python/source/doc/sphinxext/prs/7768.json new file mode 100644 index 0000000000000000000000000000000000000000..08467bdbe9fb513071cb2d22ce2ccb5f1242b4d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7768.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "65b0c6ed590dc88a135ce3f7e78946bf5bbcf305", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "tutorials/misc/plot_ecog.py": { + "a": 110, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7770.json b/mne-python/source/doc/sphinxext/prs/7770.json new file mode 100644 index 0000000000000000000000000000000000000000..498fbe4f49d288d1f2277a19f910e1219a993a6b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7770.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a367fef86c916cc0bb9272c41d4d81af324c3c7b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7772.json b/mne-python/source/doc/sphinxext/prs/7772.json new file mode 100644 index 0000000000000000000000000000000000000000..1a6473f6bb610c86d95160bf33ca2b848306be5e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7772.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "153963826b5bd16ed4fe9a96c52e13c079b24513", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 10, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7775.json b/mne-python/source/doc/sphinxext/prs/7775.json new file mode 100644 index 0000000000000000000000000000000000000000..83a03354eca39adf7a769e76dfb6afb2f0ad8202 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7775.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "de3237c9d91c64fe94330fb8d485f7c2837146f5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 21, + "d": 4 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 6, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 20, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7777.json b/mne-python/source/doc/sphinxext/prs/7777.json new file mode 100644 index 0000000000000000000000000000000000000000..23b197450625d67ce30d5ea07051b5b4bf72071b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7777.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3e551c3e07b94655866ab69df4657b0d4e8cb2f9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/stats/parametric.py": { + "a": 14, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7780.json b/mne-python/source/doc/sphinxext/prs/7780.json new file mode 100644 index 0000000000000000000000000000000000000000..3642e8b9a1b8492be75b39fae4db35ebb2abd3b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7780.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e68d1963fee51c78969eb2523e9877a62024fb8a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + ".travis.yml": { + "a": 4, + "d": 3 + }, + "azure-pipelines.yml": { + "a": 5, + "d": 5 + }, + "mne/cov.py": { + "a": 2, + "d": 7 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 2, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7781.json b/mne-python/source/doc/sphinxext/prs/7781.json new file mode 100644 index 0000000000000000000000000000000000000000..d3b9185eed8d89e0f492788bd3926732e550523b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7781.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f8276a8c6aebcb1f0cffcdfef5879342cf737fc1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 14, + "d": 8 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 41, + "d": 29 + }, + "mne/stats/tests/test_permutations.py": { + "a": 2, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7783.json b/mne-python/source/doc/sphinxext/prs/7783.json new file mode 100644 index 0000000000000000000000000000000000000000..49836f3058e6352a7cc0e8c648e4779cf289e7ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7783.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "99536bc419d64c5815b3d82e5abc0b14c10edbeb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 6, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7784.json b/mne-python/source/doc/sphinxext/prs/7784.json new file mode 100644 index 0000000000000000000000000000000000000000..c9880871d5ecbfc40e8490292b1c467ae741a4b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7784.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "292a4784f05ae607e97686d3ca05ae4c3852f8db", + "authors": [ + { + "n": "Yu-Han Luo", + "e": null + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 10, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7786.json b/mne-python/source/doc/sphinxext/prs/7786.json new file mode 100644 index 0000000000000000000000000000000000000000..502b19943c6fef84a4b952426f0eba463d6fe7ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7786.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "07cdaf9f30aa8c421f43a7c75e92ae3fe9ccdc5f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 2, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 1, + "d": 1 + }, + "tutorials/discussions/plot_background_statistics.py": { + "a": 4, + "d": 4 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 2, + "d": 1 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_time_frequency.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7791.json b/mne-python/source/doc/sphinxext/prs/7791.json new file mode 100644 index 0000000000000000000000000000000000000000..b7a2b3f8e77d3313653f746bacdc4bf915eedf71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7791.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "9800cf3dbda3485f14d0ee4e92e70517abb520a4", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 3, + "d": 0 + }, + "doc/install/mne_python.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 4, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/utils/config.py": { + "a": 10, + "d": 3 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 10, + "d": 3 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 96, + "d": 50 + }, + "requirements.txt": { + "a": 4, + "d": 2 + }, + "tutorials/machine-learning/plot_receptive_field.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7794.json b/mne-python/source/doc/sphinxext/prs/7794.json new file mode 100644 index 0000000000000000000000000000000000000000..8aba3b4a691cc60c4b8edbdb6279d375facbdf6e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7794.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a214d66520c3c111d4010e98de80627cbbd6f1a0", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/io/utils.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7795.json b/mne-python/source/doc/sphinxext/prs/7795.json new file mode 100644 index 0000000000000000000000000000000000000000..63871a830d8b1a74538a50725aa5d8beabf6af00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7795.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5874885c1736edc321ec202cb6e15d88e4324a5c", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/externals/pymatreader/pymatreader.py": { + "a": 1, + "d": 1 + }, + "mne/externals/pymatreader/utils.py": { + "a": 36, + "d": 8 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7796.json b/mne-python/source/doc/sphinxext/prs/7796.json new file mode 100644 index 0000000000000000000000000000000000000000..909fb352c311afed0a79378b9145c799a516184f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7796.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a6afbaa3f38219c842ead9bd1beac11c97286f66", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/mne_python.rst": { + "a": 46, + "d": 0 + }, + "doc/install/pre_install.rst": { + "a": 4, + "d": 2 + }, + "environment.yml": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7797.json b/mne-python/source/doc/sphinxext/prs/7797.json new file mode 100644 index 0000000000000000000000000000000000000000..b00b4f527324d630be6e6bbb33ae35698a927024 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7797.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bb908f197823c3ae27da493d2cd89895136717bf", + "authors": [ + { + "n": "Christian O'Reilly", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 0, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/780.json b/mne-python/source/doc/sphinxext/prs/780.json new file mode 100644 index 0000000000000000000000000000000000000000..b26b7673d99778f0a1398b320496e63935472477 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/780.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c90e8a2330e0db99c1b8d4c2791d08c06753d13c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/fiff/pick.py": { + "a": 2, + "d": 7 + }, + "mne/fiff/proj.py": { + "a": 1, + "d": 33 + }, + "mne/fiff/raw.py": { + "a": 4, + "d": 24 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 101 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7800.json b/mne-python/source/doc/sphinxext/prs/7800.json new file mode 100644 index 0000000000000000000000000000000000000000..a836a848691a8d92515c436a8c763649601b0ec8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7800.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "bfe65c72be7ff6b21f64c75f066b9c0fb8629c90", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_fnirs_artifact_removal.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 16, + "d": 7 + }, + "mne/preprocessing/tests/test_temporal_derivative_distribution_repair.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7801.json b/mne-python/source/doc/sphinxext/prs/7801.json new file mode 100644 index 0000000000000000000000000000000000000000..e60bd8bf548f78065479af9cf418bc27343d60f2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7801.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7726509b9b19eefc5e1908d1ec9bd34168f7a452", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 4, + "d": 2 + }, + "requirements.txt": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7802.json b/mne-python/source/doc/sphinxext/prs/7802.json new file mode 100644 index 0000000000000000000000000000000000000000..fc0b4d55c4349c18b44ecb7b3c43b6bcf46e8374 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7802.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ba960fd7752d2f041185ff35f139d511d98f3434", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 8, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 4, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 40, + "d": 2 + }, + "mne/io/fieldtrip/utils.py": { + "a": 37, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7804.json b/mne-python/source/doc/sphinxext/prs/7804.json new file mode 100644 index 0000000000000000000000000000000000000000..b88ea5c4167f280bb3a13edcdb03ca1b0a640753 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7804.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "683613a04fccf59826f1c9bfb984ef984a109632", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7806.json b/mne-python/source/doc/sphinxext/prs/7806.json new file mode 100644 index 0000000000000000000000000000000000000000..41877f220ad8d57b83b7bdeea3273a7c6add3694 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7806.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5701738ba10d65e2c5a713e0c6480aa04cd1a4ae", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 6, + "d": 8 + }, + "doc/_templates/autosummary/class.rst": { + "a": 2, + "d": 5 + }, + "doc/_templates/autosummary/function.rst": { + "a": 2, + "d": 5 + }, + "doc/conf.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7809.json b/mne-python/source/doc/sphinxext/prs/7809.json new file mode 100644 index 0000000000000000000000000000000000000000..39e7cebdb3334d0c9d7eaee17a7d507cc55947ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7809.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "432d5b77270e2900c8034cbc1f7f576935b7de68", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 84, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_read_raw.py": { + "a": 38, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/781.json b/mne-python/source/doc/sphinxext/prs/781.json new file mode 100644 index 0000000000000000000000000000000000000000..3fa398e0f1977c0c2c6b79dfd50f7c5bccdd0f53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/781.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "3a5c623e2d709febd8a5337a9cb0ef97bfd4b9e8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 4, + "d": 3 + }, + "mne/coreg/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/coreg/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/forward.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 43 + }, + "mne/source_space.py": { + "a": 612, + "d": 36 + }, + "mne/surface.py": { + "a": 108, + "d": 13 + }, + "mne/tests/test_source_space.py": { + "a": 93, + "d": 16 + }, + "mne/tests/test_surface.py": { + "a": 11, + "d": 1 + }, + "mne/tests/test_utils.py": { + "a": 22, + "d": 1 + }, + "mne/transforms/__init__.py": { + "a": 2, + "d": 3 + }, + "mne/transforms/transforms.py": { + "a": 55, + "d": 2 + }, + "mne/utils.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7810.json b/mne-python/source/doc/sphinxext/prs/7810.json new file mode 100644 index 0000000000000000000000000000000000000000..65ece580e89c7c557b4e560243ed95c4cf193a51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7810.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "7afa43778a0ef2096a61437eb30d2c98ad8c7598", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "jeff", + "e": "jeff.hanna@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 13, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 8, + "d": 0 + }, + "examples/preprocessing/plot_find_ref_artifacts.py": { + "a": 139, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/refmeg_noise/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/refmeg_noise/refmeg_noise.py": { + "a": 30, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 9, + "d": 2 + }, + "mne/preprocessing/bads.py": { + "a": 32, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 103, + "d": 30 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 17, + "d": 11 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7811.json b/mne-python/source/doc/sphinxext/prs/7811.json new file mode 100644 index 0000000000000000000000000000000000000000..bdd73415eb7c1b510dd658133fb0c6b59c619267 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7811.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "15866de8908d37337930a2afa2a54277a8a78ebe", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 11, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 21, + "d": 15 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7812.json b/mne-python/source/doc/sphinxext/prs/7812.json new file mode 100644 index 0000000000000000000000000000000000000000..754cc538445dcc0111954cf4a4f78c63e5e1d250 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7812.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "18b8f40c37850748fae4bea30498c8d533b00134", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7817.json b/mne-python/source/doc/sphinxext/prs/7817.json new file mode 100644 index 0000000000000000000000000000000000000000..85fedfc43fe5385b23f9cd4837e0193157b213cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7817.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bb0b50c6be08961b10dfff8535c966f4c6675f46", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7819.json b/mne-python/source/doc/sphinxext/prs/7819.json new file mode 100644 index 0000000000000000000000000000000000000000..7ee4f872d4b6f5208cfa8ab5764c6c2da6ee5db0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7819.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bbc853ec2560a741f8afbc08379a51a66db5056f", + "authors": [ + { + "n": "Yu-Han Luo", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 10, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 60, + "d": 7 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 19, + "d": 11 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/782.json b/mne-python/source/doc/sphinxext/prs/782.json new file mode 100644 index 0000000000000000000000000000000000000000..8b09f06ce98c74a14838cd7920d59e944139d65d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/782.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b3dcbc9dca9d1c198f621143479bfbc7ba3f9b6a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7820.json b/mne-python/source/doc/sphinxext/prs/7820.json new file mode 100644 index 0000000000000000000000000000000000000000..d188d9e7d9ba1f60c0e4568d489ac93e02299a6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7820.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5f95ebb543dac03ca3b6cde31342da4d80bf4451", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 16, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7822.json b/mne-python/source/doc/sphinxext/prs/7822.json new file mode 100644 index 0000000000000000000000000000000000000000..8b54402f7c5839563c2cc8d1caf09d8d83441147 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7822.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "a1638516b22ae128153087d72d601afdf7622ce0", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 5, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7823.json b/mne-python/source/doc/sphinxext/prs/7823.json new file mode 100644 index 0000000000000000000000000000000000000000..fd886283d5efe394152ddc5c53ccdf670ebfd6bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7823.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "002a5cfc9baecdd0ecdaff1f38555b44a141de35", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "examples/preprocessing/plot_find_ref_artifacts.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_ica_comparison.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 9, + "d": 7 + }, + "mne/beamformer/tests/test_resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 7 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 3, + "d": 3 + }, + "mne/io/pick.py": { + "a": 35, + "d": 19 + }, + "mne/io/tests/test_pick.py": { + "a": 21, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_rank.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_check.py": { + "a": 2, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_30_filtering_resampling.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7824.json b/mne-python/source/doc/sphinxext/prs/7824.json new file mode 100644 index 0000000000000000000000000000000000000000..f4cb1400ed2e50536a0aea61d3f7ad09e5ed601a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7824.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "78bc2a4c6d7f2a0ad545d242fa715b711510eb02", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/blender_import_obj/blender_import_obj1.jpg": { + "a": 0, + "d": 0 + }, + "doc/_static/blender_import_obj/blender_import_obj2.jpg": { + "a": 0, + "d": 0 + }, + "doc/_static/blender_import_obj/blender_import_obj3.jpg": { + "a": 0, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/surface.py": { + "a": 117, + "d": 31 + }, + "mne/tests/test_surface.py": { + "a": 8, + "d": 0 + }, + "tutorials/source-modeling/plot_fix_bem_in_blender.py": { + "a": 136, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7825.json b/mne-python/source/doc/sphinxext/prs/7825.json new file mode 100644 index 0000000000000000000000000000000000000000..23e72b78d940417bc3dd17ae29ecb5462b74fc11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7825.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "68b93fcca5231506837eb4be1b2ceb035fde89cb", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 37, + "d": 11 + }, + "mne/viz/tests/test_ica.py": { + "a": 21, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7826.json b/mne-python/source/doc/sphinxext/prs/7826.json new file mode 100644 index 0000000000000000000000000000000000000000..b4206c3a98b8bc367255c6ff10f17a74cef6ed97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7826.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d96532567f4f8f00e3629123eb4a7de8d01a85ed", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/mne_c.rst": { + "a": 4, + "d": 4 + }, + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7827.json b/mne-python/source/doc/sphinxext/prs/7827.json new file mode 100644 index 0000000000000000000000000000000000000000..6c4696d7cfd8b01156cce95fde086193b4bfbc57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7827.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "19c4b877fba3810341354c6445f21c9e1cd27b20", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/mne_python.rst": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7830.json b/mne-python/source/doc/sphinxext/prs/7830.json new file mode 100644 index 0000000000000000000000000000000000000000..9117e6a82c837fa93ba8c7d502fe38db968b61af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7830.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f4982c28429d24f4f7dee772e46347b3806d9a44", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_snr_estimate.py": { + "a": 5, + "d": 4 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/viz/evoked.py": { + "a": 21, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7831.json b/mne-python/source/doc/sphinxext/prs/7831.json new file mode 100644 index 0000000000000000000000000000000000000000..c807b4b670f76452120f55eb37d55b71c3874856 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7831.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a610fbcacda540c1ebff6c9500c85644aaef8ae7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 3, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 20, + "d": 28 + }, + "mne/viz/tests/test_evoked.py": { + "a": 18, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7832.json b/mne-python/source/doc/sphinxext/prs/7832.json new file mode 100644 index 0000000000000000000000000000000000000000..35a3669ca318ad4db3796a040ecad2cf10758a90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7832.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fe801b12256c798bdbcea32d444b9320c400bfcc", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7833.json b/mne-python/source/doc/sphinxext/prs/7833.json new file mode 100644 index 0000000000000000000000000000000000000000..ffa02a803e3ee0cab0be4df3828ac75315f5522c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7833.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a9b3a69094a8d84327d873375b19f48e91d8e79a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/tests/test_meas_info.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7835.json b/mne-python/source/doc/sphinxext/prs/7835.json new file mode 100644 index 0000000000000000000000000000000000000000..5d304c42e98c4dcd8f88d41e1580cee330484370 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7835.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d1662c1e74c738f5e2f177df82683174c73f1648", + "authors": [ + { + "n": "sarasommariva", + "e": "sommariva@dima.unige.it" + } + ], + "changes": { + "doc/install/pre_install.rst": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7839.json b/mne-python/source/doc/sphinxext/prs/7839.json new file mode 100644 index 0000000000000000000000000000000000000000..66411d0f167cb72caf10b3ee294bed42a53aef37 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7839.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "7d1a25088fe2b2c64acd27af8672b2abd884cdce", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/anr.jpeg": { + "a": 0, + "d": 0 + }, + "doc/_static/doe.png": { + "a": 0, + "d": 0 + }, + "doc/_static/erc.png": { + "a": 0, + "d": 0 + }, + "doc/_static/funding/amazon.svg": { + "a": 0, + "d": 0 + }, + "doc/_static/funding/anr.svg": { + "a": 6, + "d": 0 + }, + "doc/_static/funding/cds.png": { + "a": 0, + "d": 0 + }, + "doc/_static/funding/czi.svg": { + "a": 19, + "d": 0 + }, + "doc/_static/funding/doe.svg": { + "a": 1659, + "d": 0 + }, + "doc/_static/funding/erc.svg": { + "a": 662, + "d": 0 + }, + "doc/_static/funding/google.svg": { + "a": 0, + "d": 0 + }, + "doc/_static/funding/nih.png": { + "a": 0, + "d": 0 + }, + "doc/_static/funding/nsf.png": { + "a": 0, + "d": 0 + }, + "doc/index.rst": { + "a": 9, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7840.json b/mne-python/source/doc/sphinxext/prs/7840.json new file mode 100644 index 0000000000000000000000000000000000000000..8f8cff3eb36de57555cb1c694c0cc92b2bb190e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7840.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1fdacb362d765c76f22bbd6d00fe9ecbd8de12d2", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 2 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7841.json b/mne-python/source/doc/sphinxext/prs/7841.json new file mode 100644 index 0000000000000000000000000000000000000000..f2952f31c178db2abf200cee46fe4c419ad8387d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7841.json @@ -0,0 +1,339 @@ +{ + "merge_commit_sha": "f641957dba4fbd4bfed8e3329cb33891792d3de5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/bem_model.rst": { + "a": 5, + "d": 5 + }, + "doc/_includes/channel_interpolation.rst": { + "a": 1, + "d": 1 + }, + "doc/_includes/forward.rst": { + "a": 4, + "d": 4 + }, + "doc/_includes/inverse.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/0.10.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.12.inc": { + "a": 4, + "d": 4 + }, + "doc/changes/0.13.inc": { + "a": 4, + "d": 4 + }, + "doc/changes/0.14.inc": { + "a": 3, + "d": 3 + }, + "doc/changes/0.15.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.16.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.17.inc": { + "a": 7, + "d": 7 + }, + "doc/changes/0.18.inc": { + "a": 10, + "d": 10 + }, + "doc/changes/0.19.inc": { + "a": 8, + "d": 8 + }, + "doc/changes/0.20.inc": { + "a": 9, + "d": 9 + }, + "doc/changes/0.6.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.7.inc": { + "a": 6, + "d": 6 + }, + "doc/changes/0.8.inc": { + "a": 3, + "d": 3 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 2 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/install/pre_install.rst": { + "a": 2, + "d": 2 + }, + "doc/overview/cookbook.rst": { + "a": 1, + "d": 1 + }, + "doc/overview/faq.rst": { + "a": 10, + "d": 10 + }, + "doc/overview/matlab.rst": { + "a": 2, + "d": 2 + }, + "doc/overview/roadmap.rst": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/sphinxext/gen_commands.py": { + "a": 7, + "d": 8 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 1, + "d": 1 + }, + "examples/stats/plot_sensor_regression.py": { + "a": 3, + "d": 2 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 4, + "d": 4 + }, + "examples/visualization/plot_topo_customized.py": { + "a": 2, + "d": 2 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 7 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 3, + "d": 3 + }, + "mne/commands/mne_anonymize.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/csp.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 22, + "d": 19 + }, + "mne/evoked.py": { + "a": 7, + "d": 7 + }, + "mne/forward/_field_interpolation.py": { + "a": 3, + "d": 3 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 26, + "d": 25 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 1, + "d": 1 + }, + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 2 + }, + "mne/source_space.py": { + "a": 13, + "d": 13 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/permutations.py": { + "a": 3, + "d": 3 + }, + "mne/stats/regression.py": { + "a": 4, + "d": 4 + }, + "mne/surface.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 22, + "d": 22 + }, + "mne/utils/docs.py": { + "a": 16, + "d": 8 + }, + "mne/viz/_3d.py": { + "a": 10, + "d": 8 + }, + "mne/viz/epochs.py": { + "a": 5, + "d": 4 + }, + "mne/viz/evoked.py": { + "a": 29, + "d": 28 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 3, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 4, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 9, + "d": 29 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 6 + }, + "tutorials/discussions/plot_background_filtering.py": { + "a": 4, + "d": 4 + }, + "tutorials/intro/plot_20_events_from_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/plot_10_reading_meg_data.py": { + "a": 1, + "d": 1 + }, + "tutorials/misc/plot_report.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_15_handling_bad_channels.py": { + "a": 1, + "d": 1 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 3, + "d": 2 + }, + "tutorials/simulation/plot_creating_data_structures.py": { + "a": 14, + "d": 13 + }, + "tutorials/simulation/plot_point_spread.py": { + "a": 4, + "d": 4 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 5, + "d": 9 + }, + "tutorials/source-modeling/plot_object_source_estimate.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7843.json b/mne-python/source/doc/sphinxext/prs/7843.json new file mode 100644 index 0000000000000000000000000000000000000000..648a85a5b53bec5edb64379ed501085daa28be39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7843.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "bbeb2ae768b1310094a59d42f09c55f7d5412429", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 5 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 1 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 6, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 5, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 10, + "d": 4 + }, + "mne/viz/backends/base_renderer.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7845.json b/mne-python/source/doc/sphinxext/prs/7845.json new file mode 100644 index 0000000000000000000000000000000000000000..2f95e1bf2c1eab7e2d95d278b2886cf7eded9a24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7845.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3cda35975958e1bdc2b7e7b2ddef9f60e315b48f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 98, + "d": 10 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 81, + "d": 13 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 94, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7846.json b/mne-python/source/doc/sphinxext/prs/7846.json new file mode 100644 index 0000000000000000000000000000000000000000..d0036873af54232d16b7bb3bda956af4c9c24bc3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7846.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "342dc600d7a5b1e1d63cb5c60ec110ef66c9f858", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/testing/_testing.py": { + "a": 6, + "d": 3 + }, + "mne/io/fiff/raw.py": { + "a": 11, + "d": 3 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 19, + "d": 0 + }, + "mne/io/tag.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7847.json b/mne-python/source/doc/sphinxext/prs/7847.json new file mode 100644 index 0000000000000000000000000000000000000000..21ae18d970faa5787925c0cee6a8b46a48e65635 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7847.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4d02d026030c921b814bbc0ad47187dff4b96f17", + "authors": [ + { + "n": "Simeon Wong", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/785.json b/mne-python/source/doc/sphinxext/prs/785.json new file mode 100644 index 0000000000000000000000000000000000000000..55a33df60da97c62b5af57c657e78837a892f96a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/785.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3e28b3d473f185181ab7319f1e9474b396416b31", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fixes.py": { + "a": 13, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7851.json b/mne-python/source/doc/sphinxext/prs/7851.json new file mode 100644 index 0000000000000000000000000000000000000000..1d3ae7bcf9e3eb8108e8f04712bc6f5a760af9cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7851.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "508cfbc13bc2e068efb3bf8b7999b83047851729", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 22, + "d": 7 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 5, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7852.json b/mne-python/source/doc/sphinxext/prs/7852.json new file mode 100644 index 0000000000000000000000000000000000000000..c2522a22f20a4e16ae9db0c5792056ea7a30f518 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7852.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7e2fbcc8a40bb4357543e8745c26c8edd65b60e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_movement_compensation.py": { + "a": 11, + "d": 2 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7855.json b/mne-python/source/doc/sphinxext/prs/7855.json new file mode 100644 index 0000000000000000000000000000000000000000..cb85dced748978b4429b28eba5454d38320faa6f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7855.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "89647f3363fcb5de306cc18e55e7b9fa89fe0315", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7863.json b/mne-python/source/doc/sphinxext/prs/7863.json new file mode 100644 index 0000000000000000000000000000000000000000..cb2626f1a35a9c35b772c7983e9878ba47cdcda1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7863.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a6ea90c7619c4294f5ae5731ea622cebd45923a8", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 47, + "d": 10 + }, + "examples/preprocessing/plot_eeg_csd.py": { + "a": 4, + "d": 12 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/defaults.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/_csd.py": { + "a": 22, + "d": 32 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 77, + "d": 103 + }, + "mne/tests/test_defaults.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7864.json b/mne-python/source/doc/sphinxext/prs/7864.json new file mode 100644 index 0000000000000000000000000000000000000000..097549ce18238d87d85b6c6613caec08e8d23337 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7864.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "121364d0c59e36f6b71c25f5905297f1ead36116", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/references.bib": { + "a": 11, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 7, + "d": 10 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7866.json b/mne-python/source/doc/sphinxext/prs/7866.json new file mode 100644 index 0000000000000000000000000000000000000000..5137e4201b51c6b2746c873e9820c56d5e365cb4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7866.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "110b57006d2aef39963a444036e1f458ba1e0582", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_external.py": { + "a": 8, + "d": 3 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/gui/_coreg_gui.py": { + "a": 6, + "d": 1 + }, + "mne/gui/_viewer.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_defaults.py": { + "a": 62, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7869.json b/mne-python/source/doc/sphinxext/prs/7869.json new file mode 100644 index 0000000000000000000000000000000000000000..4f6246a1c3a8807cef9dbffcf60ef42648d0d1ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7869.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "4bfeb85c6b9e9f59c314d37ad42483f21b7fd5ff", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/datasets/plot_limo_data.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_linear_regression_raw.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 18, + "d": 17 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 6 + }, + "mne/tests/test_evoked.py": { + "a": 42, + "d": 57 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 3 + }, + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 4, + "d": 5 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 13, + "d": 11 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 4, + "d": 5 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 1, + "d": 1 + }, + "tutorials/sample-datasets/plot_brainstorm_auditory.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_erp.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/787.json b/mne-python/source/doc/sphinxext/prs/787.json new file mode 100644 index 0000000000000000000000000000000000000000..35b9b492d280badf6eba776e2a5f411300b1cfd0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/787.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2d622cd3db26da9a6005d4db60359b2b7281075f", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/tests/test_source_space.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 12, + "d": 6 + }, + "mne/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7870.json b/mne-python/source/doc/sphinxext/prs/7870.json new file mode 100644 index 0000000000000000000000000000000000000000..94a3861db8de9ed4edabec214bb8a9380b253a08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7870.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "27341bb95a119b555234df13162b79c273b864aa", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7875.json b/mne-python/source/doc/sphinxext/prs/7875.json new file mode 100644 index 0000000000000000000000000000000000000000..b3417213face46d039a22d384545e5ef0ade0dac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7875.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b2615a3cfe0dcc7f867fae576506fc520577bd2e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 13, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7877.json b/mne-python/source/doc/sphinxext/prs/7877.json new file mode 100644 index 0000000000000000000000000000000000000000..3189966a08d69483c5309a0c561b4584ecec1733 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7877.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "3fdd5024e8e45708fc807b6edc3ff9856bf0bfbb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/install/advanced.rst": { + "a": 11, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/gui/_coreg_gui.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 0, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 53, + "d": 5 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7878.json b/mne-python/source/doc/sphinxext/prs/7878.json new file mode 100644 index 0000000000000000000000000000000000000000..6959f3a7537527f1d8579f663249ed676c5dc7e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7878.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f8d2ce12fef6db5f8ec35d978797249ec3937a17", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/io/pick.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_pick.py": { + "a": 22, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7879.json b/mne-python/source/doc/sphinxext/prs/7879.json new file mode 100644 index 0000000000000000000000000000000000000000..2a686eb423e0bca106606a489947888b88d598a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7879.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5b2275657c8b79200c7d852cba8e02043cc2a68f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 36, + "d": 46 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 34, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/788.json b/mne-python/source/doc/sphinxext/prs/788.json new file mode 100644 index 0000000000000000000000000000000000000000..cb9fcf453c3924d652289e8dbefd76ee17e0584b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/788.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1dfeb5c635240418ffea4a391cc0a8e36bf52be4", + "authors": [ + { + "n": "Romain Trachel", + "e": "trachelr@gmail.com" + } + ], + "changes": { + "mne/stats/cluster_level.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7880.json b/mne-python/source/doc/sphinxext/prs/7880.json new file mode 100644 index 0000000000000000000000000000000000000000..56118d455995c403a5177babcf1f75fab99eecac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7880.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "30ef40adc8ab9d6911ca90292ec6f9948bca7411", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 6, + "d": 1 + }, + "environment.yml": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 4, + "d": 2 + }, + "mne/gui/_coreg_gui.py": { + "a": 6, + "d": 1 + }, + "mne/gui/_viewer.py": { + "a": 6, + "d": 2 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 3, + "d": 1 + }, + "requirements.txt": { + "a": 2, + "d": 2 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7881.json b/mne-python/source/doc/sphinxext/prs/7881.json new file mode 100644 index 0000000000000000000000000000000000000000..e1aca6b49ac1134bb82e13698089b22990efd81b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7881.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fdd68c3fa037d058aae9f6dd76bbd6512b0fe658", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 12, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7882.json b/mne-python/source/doc/sphinxext/prs/7882.json new file mode 100644 index 0000000000000000000000000000000000000000..f4a4e83de7a7730a26c950f7c2135ffc6968a7d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7882.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "98b0bb332076ca49b40abde0856cee169a9ed94e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7883.json b/mne-python/source/doc/sphinxext/prs/7883.json new file mode 100644 index 0000000000000000000000000000000000000000..e6e2122a5e11595c7390bc91cce9cff365a155fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7883.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "181a57270f1f7aead8570bc8aa9a915c5322d39e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_vector_mne_solution.py": { + "a": 16, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 19, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 90, + "d": 5 + }, + "mne/tests/test_source_estimate.py": { + "a": 70, + "d": 13 + }, + "mne/utils/check.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7887.json b/mne-python/source/doc/sphinxext/prs/7887.json new file mode 100644 index 0000000000000000000000000000000000000000..ff4a6ec5947bef5e41f069e2e29ec6cab89ead46 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7887.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "f6c6ff2842ff020816bfc203f00e03410c9e0ea3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/events.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 23, + "d": 8 + }, + "mne/io/tests/test_raw.py": { + "a": 11, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7888.json b/mne-python/source/doc/sphinxext/prs/7888.json new file mode 100644 index 0000000000000000000000000000000000000000..2aabb7565a7d7b3a47ef8e5320faa3e690115f98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7888.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e5f57cb36a316ba04aea7eba2da44dd5b58fe4c3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 3, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 120, + "d": 142 + }, + "mne/tests/test_source_space.py": { + "a": 25, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7889.json b/mne-python/source/doc/sphinxext/prs/7889.json new file mode 100644 index 0000000000000000000000000000000000000000..881e483ee48d60238d1998bf43d1057f345bdcf6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7889.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ddd54e11d6e11dbed9c9c7c4bf52a6bb1a9368e4", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/index.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/789.json b/mne-python/source/doc/sphinxext/prs/789.json new file mode 100644 index 0000000000000000000000000000000000000000..312151a6b238ebf73a40beb8c614fbe350e60521 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/789.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fbb9cb1137927f24848c9cd9a8bd92334fcf80ac", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/export/plot_epochs_as_data_frame.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/evoked.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7890.json b/mne-python/source/doc/sphinxext/prs/7890.json new file mode 100644 index 0000000000000000000000000000000000000000..b7d9c84dacaa27e18ce32322cbf2024a59609091 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7890.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "03276c7c3d1d5a6cf7ca042f97d6cef51b14422e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/ctf/info.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egi.py": { + "a": 0, + "d": 1 + }, + "mne/io/egi/events.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 40, + "d": 10 + }, + "mne/io/tests/test_raw.py": { + "a": 11, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 6, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 5, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7891.json b/mne-python/source/doc/sphinxext/prs/7891.json new file mode 100644 index 0000000000000000000000000000000000000000..eb068ff64a57d40f31f1bf3fdaf7d67e97bddfc6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7891.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0f9cf21c8ba6a8c30ed9c9d6f546fa50b1ba1a34", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 40, + "d": 11 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 21, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7895.json b/mne-python/source/doc/sphinxext/prs/7895.json new file mode 100644 index 0000000000000000000000000000000000000000..32718506e199d334fb0cae0f483a82d9a9623cda --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7895.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "52128c2fa5f556048f0d3c49f3e77e5ce3f3bdd2", + "authors": [ + { + "n": "Alejandro Weinstein", + "e": "alejandro.weinstein@gmail.com" + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7896.json b/mne-python/source/doc/sphinxext/prs/7896.json new file mode 100644 index 0000000000000000000000000000000000000000..a4db5db2b7654534b96117447664e28f3d14c07e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7896.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "126cf98acaa42a226729da8a90ae0ea3431b7da5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 8, + "d": 0 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 5, + "d": 8 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/morph.py": { + "a": 61, + "d": 39 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 100, + "d": 6 + }, + "mne/viz/_3d.py": { + "a": 19, + "d": 9 + }, + "mne/viz/tests/test_3d.py": { + "a": 12, + "d": 7 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7898.json b/mne-python/source/doc/sphinxext/prs/7898.json new file mode 100644 index 0000000000000000000000000000000000000000..7eb1052c5b27b03652035efe113f4111c023400a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7898.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6a7636a3b3ac15b9381048a31b9cfde142ca4036", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 7, + "d": 1 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7899.json b/mne-python/source/doc/sphinxext/prs/7899.json new file mode 100644 index 0000000000000000000000000000000000000000..6e12947b9b2a3e2fa36f70b7cb67fb5901d80167 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7899.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0bf19a7bbb28cc399470690b31714f54efe11acc", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/79.json b/mne-python/source/doc/sphinxext/prs/79.json new file mode 100644 index 0000000000000000000000000000000000000000..88fcd444448d866700cd22bdf3f0158be9afe32f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/79.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "15d2d83e606cca85a5502f741a88c4810476b255", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 3, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 123, + "d": 0 + }, + "mne/fiff/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/mixed_norm/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/mixed_norm/inverse.py": { + "a": 178, + "d": 7 + }, + "mne/mixed_norm/optim.py": { + "a": 265, + "d": 15 + }, + "mne/mixed_norm/tests/test_inverse.py": { + "a": 46, + "d": 13 + }, + "mne/mixed_norm/tests/test_optim.py": { + "a": 54, + "d": 4 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/stft.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7900.json b/mne-python/source/doc/sphinxext/prs/7900.json new file mode 100644 index 0000000000000000000000000000000000000000..d9a2ca45b1dde41ef6ebb94b1df814271c4d99a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7900.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7a16f2c4dce3d565cb2403091b7c7e7b2cc618f4", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/overview/faq.rst": { + "a": 2, + "d": 2 + }, + "tutorials/source-modeling/plot_fix_bem_in_blender.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7902.json b/mne-python/source/doc/sphinxext/prs/7902.json new file mode 100644 index 0000000000000000000000000000000000000000..864526ecc6547e822f895fc6d9705803a28e3251 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7902.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "408c5c803a6ad634a48829310b5b92ee4d907872", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 2, + "d": 2 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7904.json b/mne-python/source/doc/sphinxext/prs/7904.json new file mode 100644 index 0000000000000000000000000000000000000000..2bdba33650d154ce4a8b2ceb99efff0718c3468a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7904.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "676e627f3f9b9e292e131480c46aa7ab12429cdb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 3, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 3, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 1, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/_digitization.py": { + "a": 9, + "d": 7 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 2, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 2, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 1, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 47, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 2 + }, + "mne/io/utils.py": { + "a": 2, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7905.json b/mne-python/source/doc/sphinxext/prs/7905.json new file mode 100644 index 0000000000000000000000000000000000000000..773da89ca1e9ab6ef1c4ba6f588d3c1203013f02 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7905.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e4ace23bf16b2ed3ac66ead5c8b38e57fbad577c", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 38, + "d": 29 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7906.json b/mne-python/source/doc/sphinxext/prs/7906.json new file mode 100644 index 0000000000000000000000000000000000000000..08b3b44619e36dade5655c5ee1d8d864a82e6397 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7906.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "59b0307e551f76e1c5f7bb7fc907fd828ca34245", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 5, + "d": 2 + }, + ".travis.yml": { + "a": 14, + "d": 14 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/plot_sensors_decoding.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7908.json b/mne-python/source/doc/sphinxext/prs/7908.json new file mode 100644 index 0000000000000000000000000000000000000000..4c449a376ef325519fc26845f2a3bb15fd038e5b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7908.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "437ae4763bf843c9c84f823fec3abba3f6d79886", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/fixes.py": { + "a": 13, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/791.json b/mne-python/source/doc/sphinxext/prs/791.json new file mode 100644 index 0000000000000000000000000000000000000000..3031e0eddcc48a9794bec3311cb6211ad60021eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/791.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5d379d65f8378dc3b39b4234e224efe3a02eedca", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7910.json b/mne-python/source/doc/sphinxext/prs/7910.json new file mode 100644 index 0000000000000000000000000000000000000000..4271abc71c2b26fd38e0910e3f5eed7e2d00a32e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7910.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "171917801f6d197d31af82fda7350d3553d8300f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 12, + "d": 10 + }, + "mne/evoked.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 24, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7916.json b/mne-python/source/doc/sphinxext/prs/7916.json new file mode 100644 index 0000000000000000000000000000000000000000..48e69105f28d4f19620dfce54d8c9b36b06441a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7916.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "d122dca68ccd7c8681481b4e624ad1553cc60c6b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.15.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.19.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 9, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 13, + "d": 12 + }, + "mne/__init__.py": { + "a": 25, + "d": 8 + }, + "mne/_version.py": { + "a": 6, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 8, + "d": 4 + }, + "mne/channels/channels.py": { + "a": 52, + "d": 52 + }, + "mne/channels/tests/test_channels.py": { + "a": 30, + "d": 30 + }, + "mne/label.py": { + "a": 5, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 68, + "d": 68 + }, + "mne/source_space.py": { + "a": 3, + "d": 3 + }, + "mne/stats/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/stats/_adjacency.py": { + "a": 93, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 122, + "d": 107 + }, + "mne/stats/tests/test_adjacency.py": { + "a": 44, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 70, + "d": 68 + }, + "mne/stats/tests/test_permutations.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 42, + "d": 42 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 30, + "d": 11 + }, + "mne/utils/tests/test_docs.py": { + "a": 13, + "d": 1 + }, + "setup.py": { + "a": 1, + "d": 1 + }, + "tutorials/discussions/plot_background_statistics.py": { + "a": 21, + "d": 21 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 43, + "d": 14 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_erp.py": { + "a": 2, + "d": 2 + }, + "tutorials/stats-sensor-space/plot_stats_spatio_temporal_cluster_sensors.py": { + "a": 8, + "d": 8 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal.py": { + "a": 4, + "d": 4 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_2samp.py": { + "a": 5, + "d": 5 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal_repeated_measures_anova.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7917.json b/mne-python/source/doc/sphinxext/prs/7917.json new file mode 100644 index 0000000000000000000000000000000000000000..15fe420049b58d7ba4de37a1395054a8d3163cb5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7917.json @@ -0,0 +1,295 @@ +{ + "merge_commit_sha": "959d191e09294bb5238c369043af5b151876a0ab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/plot_simulated_raw_data_using_subject_anatomy.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 2 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 5, + "d": 0 + }, + "mne/connectivity/effective.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 4, + "d": 4 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 5, + "d": 5 + }, + "mne/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 3, + "d": 3 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 4 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 13, + "d": 13 + }, + "mne/inverse_sparse/tests/test_mxne_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/utils.py": { + "a": 3, + "d": 3 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 4 + }, + "mne/io/bti/read.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 2, + "d": 2 + }, + "mne/io/ctf_comp.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_compensator.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 4, + "d": 4 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 6, + "d": 6 + }, + "mne/morph.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/_peak_finder.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/bads.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_source.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 3, + "d": 3 + }, + "mne/stats/cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stft.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/_stockwell.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/colormap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 5, + "d": 4 + }, + "mne/viz/circle.py": { + "a": 3, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7923.json b/mne-python/source/doc/sphinxext/prs/7923.json new file mode 100644 index 0000000000000000000000000000000000000000..ebd4bc65c1927e337ce467e7de6f22133c09b16a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7923.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "c8364811813708ed13112b065b7d337ddd6f5282", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + } + ], + "changes": { + "examples/preprocessing/plot_fnirs_artifact_removal.py": { + "a": 3, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 6 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 6, + "d": 5 + }, + "mne/defaults.py": { + "a": 8, + "d": 7 + }, + "mne/evoked.py": { + "a": 5, + "d": 4 + }, + "mne/io/constants.py": { + "a": 4, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 11, + "d": 0 + }, + "mne/io/pick.py": { + "a": 32, + "d": 15 + }, + "mne/io/tests/test_constants.py": { + "a": 8, + "d": 5 + }, + "mne/io/tests/test_pick.py": { + "a": 6, + "d": 5 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_beer_lambert_law.py": { + "a": 10, + "d": 3 + }, + "mne/preprocessing/tests/test_optical_density.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7924.json b/mne-python/source/doc/sphinxext/prs/7924.json new file mode 100644 index 0000000000000000000000000000000000000000..d6639c76e04517bfd04278256406f4f05652b462 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7924.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4353b2c0e1c00320ff743f3d1f3deece11bc49da", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/time_frequency/csd.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7925.json b/mne-python/source/doc/sphinxext/prs/7925.json new file mode 100644 index 0000000000000000000000000000000000000000..694389685748b469b5f73568e3c04af7975dbc80 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7925.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dfcbd29086d5420accc81572927a922b29f31d23", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 18, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7927.json b/mne-python/source/doc/sphinxext/prs/7927.json new file mode 100644 index 0000000000000000000000000000000000000000..659e8d51cf82b55b7ffb9066d29ea68701b6dd5f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7927.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "bd6f426aa564522b21470ab7510b74a226cc507b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 4 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 2 + }, + "mne/viz/_brain/_scraper.py": { + "a": 63, + "d": 0 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 74, + "d": 68 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 20, + "d": 3 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 0 + }, + "requirements_testing.txt": { + "a": 1, + "d": 0 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 0 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7928.json b/mne-python/source/doc/sphinxext/prs/7928.json new file mode 100644 index 0000000000000000000000000000000000000000..ad0756cbb2a3696db29804d498d26fd4383f49b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7928.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "969c7d8c870d10760728362195398db9dcda7d5e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 7, + "d": 5 + }, + "mne/viz/_brain/_notebook.py": { + "a": 12, + "d": 1 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7929.json b/mne-python/source/doc/sphinxext/prs/7929.json new file mode 100644 index 0000000000000000000000000000000000000000..fa21385af701db8fcccbe2d7787afbfd136bc4e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7929.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "a4088816648d07606b4b498ed08fca3d6f5949d2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 15, + "d": 5 + }, + "mne/chpi.py": { + "a": 3, + "d": 3 + }, + "mne/epochs.py": { + "a": 7, + "d": 7 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 11, + "d": 10 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7930.json b/mne-python/source/doc/sphinxext/prs/7930.json new file mode 100644 index 0000000000000000000000000000000000000000..a39d48edb03aa1c425b63bf61d819a377266460b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7930.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c9064e763f4b4befd7c34a02a23ab061fcb03def", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/surface.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7931.json b/mne-python/source/doc/sphinxext/prs/7931.json new file mode 100644 index 0000000000000000000000000000000000000000..a72399df7f9eada7469e187cc49d2f6734deb499 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7931.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "95a88e2884e44585f352744f35d86667195cdad6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 2 + }, + ".travis.yml": { + "a": 0, + "d": 1 + }, + "environment.yml": { + "a": 0, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7934.json b/mne-python/source/doc/sphinxext/prs/7934.json new file mode 100644 index 0000000000000000000000000000000000000000..db7ed2df850c1f8b26a2bbfe7c7866106db6850e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7934.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "31a82ecb3813e0016295ba1b8ec79fc10d2e2d6f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 39, + "d": 114 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 11, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7935.json b/mne-python/source/doc/sphinxext/prs/7935.json new file mode 100644 index 0000000000000000000000000000000000000000..841798af0c310fe7d2caf51744c9749dfb1a49c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7935.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1d9058074ba6ae41cf35188380b38ff48c8d4d1b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 5, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 14, + "d": 7 + }, + "mne/viz/tests/test_evoked.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/794.json b/mne-python/source/doc/sphinxext/prs/794.json new file mode 100644 index 0000000000000000000000000000000000000000..df98bea9c0c290ca537ba428a2a53a33e451def1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/794.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d29cdaa7e8a1b98084f4691828a1a180240c5553", + "authors": [ + { + "n": "Emanuele Olivetti", + "e": null + } + ], + "changes": { + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7940.json b/mne-python/source/doc/sphinxext/prs/7940.json new file mode 100644 index 0000000000000000000000000000000000000000..2426262e6bbd840ac24a0b281b79413022dda567 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7940.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ce30458703d31c855d791546602a9c28df54b5ba", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_notebook.py": { + "a": 35, + "d": 18 + }, + "mne/viz/backends/_notebook.py": { + "a": 11, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7943.json b/mne-python/source/doc/sphinxext/prs/7943.json new file mode 100644 index 0000000000000000000000000000000000000000..4d0fd8d44b04eeba6029ecf09b796010275653a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7943.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "b04ff04df17852a8d933075c4c5e3f4b5ee78b12", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 29, + "d": 30 + }, + "doc/conftest.py": { + "a": 1, + "d": 1 + }, + "doc/sphinxext/flow_diagram.py": { + "a": 2, + "d": 2 + }, + "environment.yml": { + "a": 1, + "d": 3 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 2, + "d": 1 + }, + "mne/bem.py": { + "a": 2, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 7 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 58, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "mne/io/proj.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 3, + "d": 2 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 7, + "d": 6 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 1 + }, + "server_environment.yml": { + "a": 2, + "d": 1 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7948.json b/mne-python/source/doc/sphinxext/prs/7948.json new file mode 100644 index 0000000000000000000000000000000000000000..d9757d5bd9e8e1ab5d4ca58383040713239089c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7948.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "8fa7eb322e256c908c4cd0d234ae922941a1b421", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 7, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7949.json b/mne-python/source/doc/sphinxext/prs/7949.json new file mode 100644 index 0000000000000000000000000000000000000000..c1370a16a98a4b87c78d720c565ce372e1a680a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7949.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0de98a86938917eab0667249f54eb62719c73c6d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/mne_python.rst": { + "a": 2, + "d": 2 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7950.json b/mne-python/source/doc/sphinxext/prs/7950.json new file mode 100644 index 0000000000000000000000000000000000000000..6e74e7b8b3903dda1936d9a9f86c3fa5e9d41c8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7950.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "54b88d2c4c83a3dcd8afc403d017c3c0e0b33e79", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/source_space.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7951.json b/mne-python/source/doc/sphinxext/prs/7951.json new file mode 100644 index 0000000000000000000000000000000000000000..377752986bd259cc94bc82192554a9f04034cb3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7951.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5acdd588e89d0cf2ed21e0240795fc7504b9e173", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 15, + "d": 14 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7952.json b/mne-python/source/doc/sphinxext/prs/7952.json new file mode 100644 index 0000000000000000000000000000000000000000..1259c8ffef549b1d8af2a8742d3228537840dff2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7952.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a8a82697f6773e70203f71b4db3c75a87fada0b6", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 3, + "d": 1 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7953.json b/mne-python/source/doc/sphinxext/prs/7953.json new file mode 100644 index 0000000000000000000000000000000000000000..2d338ec4cadff3aeec0c1f7b0e32672809721db3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7953.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c7273e48cddfe547f62f78ee340e74e712e28228", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 0, + "d": 2 + }, + "mne/conftest.py": { + "a": 0, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7954.json b/mne-python/source/doc/sphinxext/prs/7954.json new file mode 100644 index 0000000000000000000000000000000000000000..1da518f90e0b24c102c079736dd23abf1e2d978c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7954.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "517c49612da33491fe4f147588deb00072526874", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7955.json b/mne-python/source/doc/sphinxext/prs/7955.json new file mode 100644 index 0000000000000000000000000000000000000000..b3c79b0c469d1eb6c89217863251e1fcb08c7297 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7955.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "b1cc4651e5d23b914329eb3b2b11a2de682408d6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/selection.py": { + "a": 5, + "d": 3 + }, + "mne/viz/_figure.py": { + "a": 1848, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 202, + "d": 398 + }, + "mne/viz/tests/test_raw.py": { + "a": 305, + "d": 121 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 76, + "d": 119 + }, + "tutorials/raw/plot_30_annotate_raw.py": { + "a": 27, + "d": 27 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7957.json b/mne-python/source/doc/sphinxext/prs/7957.json new file mode 100644 index 0000000000000000000000000000000000000000..d9e40834e0aedefecdb6ff5be83afa4c4746ae2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7957.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "666d169921897047b37b21d8f05cfbe02acd7f58", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/796.json b/mne-python/source/doc/sphinxext/prs/796.json new file mode 100644 index 0000000000000000000000000000000000000000..0ff73dd17c19532c970352f1ab33de02256a65a1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/796.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1ff24815855e7152b90cf1d6a0599d974d899294", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7961.json b/mne-python/source/doc/sphinxext/prs/7961.json new file mode 100644 index 0000000000000000000000000000000000000000..8855afc820c3485fab8d9875d380a8467e97a41c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7961.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "556ce8ed7f1990b1b164f1f20c45f3481035a7f6", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/stats-sensor-space/plot_stats_cluster_erp.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7962.json b/mne-python/source/doc/sphinxext/prs/7962.json new file mode 100644 index 0000000000000000000000000000000000000000..0425af6d7eb84e79757a16ae50e37e9f915821f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7962.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "6e5beb64aa9abea19c89e321962856cfdb12ea5a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 6, + "d": 2 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 55, + "d": 20 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 5, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 4, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7963.json b/mne-python/source/doc/sphinxext/prs/7963.json new file mode 100644 index 0000000000000000000000000000000000000000..01b9aa3777245dc6c5a13cccb39fe936d5606101 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7963.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a00ab1686ab84c9037d546305715cb4d4325eee5", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 9, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7964.json b/mne-python/source/doc/sphinxext/prs/7964.json new file mode 100644 index 0000000000000000000000000000000000000000..e2857bf15da64678a314bebe741fff561e94b720 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7964.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7267af6eb4e64567be160ab98674602af3b9beb7", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 30, + "d": 11 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 5, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 6, + "d": 1 + }, + "mne/viz/backends/base_renderer.py": { + "a": 16, + "d": 0 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7965.json b/mne-python/source/doc/sphinxext/prs/7965.json new file mode 100644 index 0000000000000000000000000000000000000000..c7d7d51a8927bd51f8a2cb95998f633bd4af4451 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7965.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5ff1cb5fb9b2f105de2b7a750cf63c087e310dab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/ctf/ctf.py": { + "a": 7, + "d": 4 + }, + "mne/io/ctf/info.py": { + "a": 6, + "d": 14 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 44, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7967.json b/mne-python/source/doc/sphinxext/prs/7967.json new file mode 100644 index 0000000000000000000000000000000000000000..093370f1ccb4c07820427174ddd2f370ba9629b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7967.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "85bc0063c7582a4deb2e453ea6c41e49036254a4", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 22, + "d": 5 + }, + "mne/io/base.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 26, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7968.json b/mne-python/source/doc/sphinxext/prs/7968.json new file mode 100644 index 0000000000000000000000000000000000000000..61cd7c38381960c460400c670ebfbec40d08f2c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7968.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c53ce68999b1d460ec8a2e120a213b9a34949807", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 71, + "d": 54 + }, + "mne/tests/test_epochs.py": { + "a": 50, + "d": 39 + }, + "mne/utils/mixin.py": { + "a": 4, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7970.json b/mne-python/source/doc/sphinxext/prs/7970.json new file mode 100644 index 0000000000000000000000000000000000000000..0369c3eab28e761bfd4fa734a42fe3ca04c59ef7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7970.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "c3795a2fe5fbea43ca008d91e239f226ac9c9a85", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 9, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 2 + }, + "mne/bem.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 0, + "d": 58 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 2 + }, + "mne/io/proj.py": { + "a": 1, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 3 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7971.json b/mne-python/source/doc/sphinxext/prs/7971.json new file mode 100644 index 0000000000000000000000000000000000000000..9c7ce381e446396762ddf02a4961d88466df2e14 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7971.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "2965cc3644538c97b297f131bbb46ce9f954ea6f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".travis.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/install/advanced.rst": { + "a": 7, + "d": 0 + }, + "doc/install/mne_python.rst": { + "a": 94, + "d": 57 + }, + "doc/install/pre_install.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7972.json b/mne-python/source/doc/sphinxext/prs/7972.json new file mode 100644 index 0000000000000000000000000000000000000000..bfb0917059eaf1e98a6cce1ed60b145f785364a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7972.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "1439ff81d5fe6da13ab59bb1152bbf261123452b", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Robert Luke", + "e": "mail@robertluke.net" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 203, + "d": 0 + }, + "mne/io/snirf/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 100, + "d": 0 + }, + "mne/utils/check.py": { + "a": 7, + "d": 0 + }, + "tutorials/io/plot_30_reading_fnirs_data.py": { + "a": 17, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7974.json b/mne-python/source/doc/sphinxext/prs/7974.json new file mode 100644 index 0000000000000000000000000000000000000000..a474212c896c38fb9996ec3d4ad61803c1875f10 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7974.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "05df66f4441980211ba5e17279c1d89fd5e7b38c", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Jan Sedivy", + "e": "sedivy@rtsoft.cz" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 108, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_highpass.vhdr": { + "a": 1, + "d": 4 + }, + "mne/io/brainvision/tests/data/test_mixed_lowpass.vhdr": { + "a": 49, + "d": 6 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 55, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 4, + "d": 1 + }, + "mne/utils/tests/test_numerics.py": { + "a": 2, + "d": 0 + }, + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7976.json b/mne-python/source/doc/sphinxext/prs/7976.json new file mode 100644 index 0000000000000000000000000000000000000000..f93453452bce367fb02c14a3ae1d7a25ba6fc5a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7976.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "75fc445cbf0fb406da94fb44df6bd2190214c05d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 27, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7979.json b/mne-python/source/doc/sphinxext/prs/7979.json new file mode 100644 index 0000000000000000000000000000000000000000..5ac230c1686d38b22a9b4ba357ed0d6268f4c262 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7979.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "76fc838e954e70697f33cab0edbca61872ca1c23", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 10, + "d": 0 + }, + "doc/install/advanced.rst": { + "a": 7, + "d": 0 + }, + "doc/install/mne_python.rst": { + "a": 158, + "d": 55 + }, + "doc/install/pre_install.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7980.json b/mne-python/source/doc/sphinxext/prs/7980.json new file mode 100644 index 0000000000000000000000000000000000000000..cf6de6226cac963e4a87a394e2603d1a68c4a125 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7980.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b75032c8a0713e6ff80f7b7127d085857f319b2f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/plot_20_visualize_evoked.py": { + "a": 7, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7982.json b/mne-python/source/doc/sphinxext/prs/7982.json new file mode 100644 index 0000000000000000000000000000000000000000..9a4037b69b5487bef905e701197c6abf849ec33c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7982.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "13be7776156cfab917daedf6e4fd45000f9128a1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/preprocessing/maxwell.py": { + "a": 37, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7983.json b/mne-python/source/doc/sphinxext/prs/7983.json new file mode 100644 index 0000000000000000000000000000000000000000..dff7532b2d544f862fbcc178ae21949b022017aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7983.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "31f4923342c112a1d9affcd580971af6ff09f0cc", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 19, + "d": 5 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 15, + "d": 8 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 12, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7986.json b/mne-python/source/doc/sphinxext/prs/7986.json new file mode 100644 index 0000000000000000000000000000000000000000..84980ede6323c8ef13c5c97bb9e2a1f9a8c5bdaf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7986.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6bfa9c8d95d2ebcd6b3fcc5cf82c394777d8377a", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 59, + "d": 32 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7987.json b/mne-python/source/doc/sphinxext/prs/7987.json new file mode 100644 index 0000000000000000000000000000000000000000..5dcf0793a04b0f2f1da3bd00efcb873a7efbcc8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7987.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0b907234c66cef2fd6e9ab135633bcf07d5f2842", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/cited.rst": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7988.json b/mne-python/source/doc/sphinxext/prs/7988.json new file mode 100644 index 0000000000000000000000000000000000000000..5866d90437187d618fc01a3d15e9edeeeb8764c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7988.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4c4b9278c7232583a58c61b3dd243333a3c49bd6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/misc.py": { + "a": 13, + "d": 3 + }, + "mne/viz/tests/test_misc.py": { + "a": 13, + "d": 6 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/799.json b/mne-python/source/doc/sphinxext/prs/799.json new file mode 100644 index 0000000000000000000000000000000000000000..af51395f39d19f62a084dc0ab3651efc2d81848e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/799.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a508da2e18b059460003dc984ce5db7b373a14d6", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 4, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 21, + "d": 1 + }, + "mne/surface.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7990.json b/mne-python/source/doc/sphinxext/prs/7990.json new file mode 100644 index 0000000000000000000000000000000000000000..5b4bd66cae15484ab57069bed71314a19eaac425 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7990.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4903cf2b9c5aef7fabb01ce84bf7d20203568d94", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 44, + "d": 31 + }, + "tutorials/misc/plot_report.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7991.json b/mne-python/source/doc/sphinxext/prs/7991.json new file mode 100644 index 0000000000000000000000000000000000000000..afe683d88a64da3ace0f039ce802608b5714923b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7991.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "492afc2c0aef39f0b822923adca1111037814428", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 87, + "d": 15 + }, + "mne/tests/test_report.py": { + "a": 11, + "d": 2 + }, + "tutorials/misc/plot_report.py": { + "a": 33, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7994.json b/mne-python/source/doc/sphinxext/prs/7994.json new file mode 100644 index 0000000000000000000000000000000000000000..b92fb69b743b8a23d15990cf92c9f1691fe94aa2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7994.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ca3595f0b073ed4c75470eae634d046236007838", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 29, + "d": 11 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7996.json b/mne-python/source/doc/sphinxext/prs/7996.json new file mode 100644 index 0000000000000000000000000000000000000000..e3aff2ba6ebe3f6c3e1e8414265eb365aa249e62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7996.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4c32643b996e6306018b49401a22c3c1b3feea7f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/_stockwell.py": { + "a": 9, + "d": 5 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7997.json b/mne-python/source/doc/sphinxext/prs/7997.json new file mode 100644 index 0000000000000000000000000000000000000000..3a7c9b35a058d824dbdd7cca2f4b1e15d5b7983a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7997.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "bab6cb31f59341c3cf02cfe6f96d10e9adcf52cc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 5 + }, + ".travis.yml": { + "a": 2, + "d": 4 + }, + "MANIFEST.in": { + "a": 2, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 5, + "d": 29 + }, + "doc/install/contributing.rst": { + "a": 10, + "d": 4 + }, + "environment.yml": { + "a": 1, + "d": 10 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 6, + "d": 6 + }, + "mne/viz/backends/_pyvista.py": { + "a": 4, + "d": 4 + }, + "requirements.txt": { + "a": 1, + "d": 11 + }, + "requirements_doc.txt": { + "a": 9, + "d": 0 + }, + "requirements_testing.txt": { + "a": 14, + "d": 0 + }, + "setup.cfg": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/7998.json b/mne-python/source/doc/sphinxext/prs/7998.json new file mode 100644 index 0000000000000000000000000000000000000000..01e976f420abec7878fd40231002f2877d821587 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/7998.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "18ffbfa47005223dd343257daa69b4540f72b9b5", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 35, + "d": 30 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 8 + }, + "mne/utils/docs.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8.json b/mne-python/source/doc/sphinxext/prs/8.json new file mode 100644 index 0000000000000000000000000000000000000000..c0c200dab2de7a99460c67888292211585ee927d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1c6805e6866a78edaea4d1d8e22bd46146ac2a70", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "Makefile": { + "a": 4, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 79, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/80.json b/mne-python/source/doc/sphinxext/prs/80.json new file mode 100644 index 0000000000000000000000000000000000000000..5981cc60ebf67a025be40511e321f058a2b6e82b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/80.json @@ -0,0 +1,187 @@ +{ + "merge_commit_sha": "70973e15373c8b70b5117b3d09d714633a30ae62", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/artifacts/stim.py": { + "a": 1, + "d": 1 + }, + "mne/artifacts/tests/test_ecg.py": { + "a": 2, + "d": 3 + }, + "mne/artifacts/tests/test_eog.py": { + "a": 2, + "d": 2 + }, + "mne/artifacts/tests/test_peak_finder.py": { + "a": 2, + "d": 2 + }, + "mne/artifacts/tests/test_stim.py": { + "a": 5, + "d": 5 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 6, + "d": 3 + }, + "mne/fiff/matrix.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/tests/test_pick.py": { + "a": 1, + "d": 2 + }, + "mne/fiff/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 7, + "d": 7 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 6, + "d": 6 + }, + "mne/mixed_norm/debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/mixed_norm/tests/test_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/mixed_norm/tests/test_inverse.py": { + "a": 4, + "d": 4 + }, + "mne/mixed_norm/tests/test_optim.py": { + "a": 1, + "d": 1 + }, + "mne/selection.py": { + "a": 0, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_source.py": { + "a": 3, + "d": 5 + }, + "mne/source_space.py": { + "a": 1, + "d": 0 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_permutations.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 8 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_forward.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_misc.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_selection.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_source_space.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_utils.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_viz.py": { + "a": 3, + "d": 3 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 5, + "d": 4 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 9, + "d": 9 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + }, + "mne/utils.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8002.json b/mne-python/source/doc/sphinxext/prs/8002.json new file mode 100644 index 0000000000000000000000000000000000000000..8a9d500f38cbd4696ed63478ef92ae931ab6eb4c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8002.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7cc37e2f6a98a62d4d405fb88a9380ec754519a6", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 19, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 23, + "d": 13 + }, + "mne/io/proj.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8003.json b/mne-python/source/doc/sphinxext/prs/8003.json new file mode 100644 index 0000000000000000000000000000000000000000..a3c2968b5cf5dcfc318517d8a16d0ef7076552fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8003.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b1dfd53f4c017b5b0e1e51af1d98d38e318c3676", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 12, + "d": 0 + }, + "mne/io/proj.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8005.json b/mne-python/source/doc/sphinxext/prs/8005.json new file mode 100644 index 0000000000000000000000000000000000000000..b568b95e67557c9a9579559216867f148e076e03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8005.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "327de96a146d89aaaa612137bc7afdb3bf4cc8f7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8006.json b/mne-python/source/doc/sphinxext/prs/8006.json new file mode 100644 index 0000000000000000000000000000000000000000..5de816c2e59c2fe24bac55ed3b4cd114560f7975 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8006.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "de43183adb18c744f25cb3461d1b32c6d04c8ae8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 19, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8007.json b/mne-python/source/doc/sphinxext/prs/8007.json new file mode 100644 index 0000000000000000000000000000000000000000..772c5deadef508964cf0f618865cee11115319fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8007.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "859796c0ae0ca23d3750c113e8ea8eb3b822b8f1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_topomap.py": { + "a": 5, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/801.json b/mne-python/source/doc/sphinxext/prs/801.json new file mode 100644 index 0000000000000000000000000000000000000000..ed8f991b4ba655137100c90b91b366c2e759adcf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/801.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a8287ddc73bd02c3424e00f44a88444d81952234", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/tests/test_viz.py": { + "a": 2, + "d": 0 + }, + "mne/viz.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8010.json b/mne-python/source/doc/sphinxext/prs/8010.json new file mode 100644 index 0000000000000000000000000000000000000000..87c7538d093db10065bcf4e28f34219fd095a5db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8010.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b20223fb430778a5eda4a6de7d5c5728138c1a22", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "server_environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8011.json b/mne-python/source/doc/sphinxext/prs/8011.json new file mode 100644 index 0000000000000000000000000000000000000000..12160755e812c9b5bf2088086a96c664f1bb0469 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8011.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "638847ea5539be32919b6ac4dd85ef8c4c3b79aa", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8012.json b/mne-python/source/doc/sphinxext/prs/8012.json new file mode 100644 index 0000000000000000000000000000000000000000..f5bf194b9f3155b72db3bdf367015681b4c684b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8012.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "056c273f1bb96bb3229e60874122f830f946746c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8014.json b/mne-python/source/doc/sphinxext/prs/8014.json new file mode 100644 index 0000000000000000000000000000000000000000..2a226b765ceab15692b4fead07f12318102e1b70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8014.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "1a3a392f63216f010de1658949a2bff5439eda46", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@inria.fr" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@inria.fr" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 142, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 68, + "d": 2 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8017.json b/mne-python/source/doc/sphinxext/prs/8017.json new file mode 100644 index 0000000000000000000000000000000000000000..c46cb39cf2802bfb6174383a123fc2a8e8742050 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8017.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c70260fead8b17c5f84bcf706702836010e05501", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 16, + "d": 5 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 6, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8018.json b/mne-python/source/doc/sphinxext/prs/8018.json new file mode 100644 index 0000000000000000000000000000000000000000..7686c3ac1768ca42a32b21c1317df53346158dd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8018.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6db1b3344c0f0d3643361961b89aa32a1a3dd623", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 70, + "d": 47 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 7, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 42, + "d": 17 + }, + "mne/viz/backends/base_renderer.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/802.json b/mne-python/source/doc/sphinxext/prs/802.json new file mode 100644 index 0000000000000000000000000000000000000000..79d2ee0e941a075e48bb63915adfa55100d5095f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/802.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5eaceafb3fac57ee24fa284d0c211819a17e7131", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 2, + "d": 0 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/source_space.py": { + "a": 105, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 79, + "d": 2 + }, + "mne/utils.py": { + "a": 42, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8020.json b/mne-python/source/doc/sphinxext/prs/8020.json new file mode 100644 index 0000000000000000000000000000000000000000..6468399e270037aecbd336375736663cdd2eb2d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8020.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8b3ca8a88909dcd14fd2619c08c9587effe232e0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/mne_python.rst": { + "a": 6, + "d": 6 + }, + "environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8021.json b/mne-python/source/doc/sphinxext/prs/8021.json new file mode 100644 index 0000000000000000000000000000000000000000..760ba9931d5c067dcf21884a8543bf575c623d8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8021.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "adc70d404e88dad1f13c004c7283ae80220a9983", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "server_environment.yml": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8022.json b/mne-python/source/doc/sphinxext/prs/8022.json new file mode 100644 index 0000000000000000000000000000000000000000..be332331a3fde1930a6f2e2d411275dfe2cd9825 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8022.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aab9bae4cad04783d9457d2ae0edcbccf527e7b0", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8023.json b/mne-python/source/doc/sphinxext/prs/8023.json new file mode 100644 index 0000000000000000000000000000000000000000..70bc4b0ba64d216285e77d2f141da20a09824b79 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8023.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "de5e36939f37c7e8aef7e1674f393b5b258297d4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/forward/plot_forward_sensitivity_maps.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_time_frequency_simulated.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 0, + "d": 1 + }, + "mne/viz/tests/test_utils.py": { + "a": 9, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 0, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 37, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8024.json b/mne-python/source/doc/sphinxext/prs/8024.json new file mode 100644 index 0000000000000000000000000000000000000000..40f54c04707e8b6b6d9945034f95c7f138adc389 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8024.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "9613c71f24b8f3f289fcbace86be57dcc66360ed", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_interpolate_bad_channels.py": { + "a": 23, + "d": 17 + }, + "mne/channels/channels.py": { + "a": 34, + "d": 7 + }, + "mne/channels/interpolation.py": { + "a": 52, + "d": 38 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 49, + "d": 24 + }, + "mne/defaults.py": { + "a": 1, + "d": 0 + }, + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_field_interpolation.py": { + "a": 84, + "d": 40 + }, + "mne/forward/_lead_dots.py": { + "a": 4, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8029.json b/mne-python/source/doc/sphinxext/prs/8029.json new file mode 100644 index 0000000000000000000000000000000000000000..baa276eafa056ab5980979b1dca2e3be2b03e7c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8029.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bf08aca0bf47ee3d7a085c0a262371545e7eae2d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 19, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 34 + }, + "mne/utils/docs.py": { + "a": 40, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8033.json b/mne-python/source/doc/sphinxext/prs/8033.json new file mode 100644 index 0000000000000000000000000000000000000000..ca3e0ff7f14acff599fc5627df692765a348b353 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8033.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a12cbb70471766abc6ff8a322acb7663c37ea8cd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/proj.py": { + "a": 24, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 26, + "d": 9 + }, + "mne/viz/tests/test_evoked.py": { + "a": 71, + "d": 8 + }, + "mne/viz/tests/test_topo.py": { + "a": 15, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 7, + "d": 7 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 59, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8034.json b/mne-python/source/doc/sphinxext/prs/8034.json new file mode 100644 index 0000000000000000000000000000000000000000..7b8e0f8140efad82aae56dd2cf5e47693150cea3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8034.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4b282c833b9d6b86ab390b374863e2323fee131d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/visualization/plot_evoked_arrowmap.py": { + "a": 4, + "d": 7 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8035.json b/mne-python/source/doc/sphinxext/prs/8035.json new file mode 100644 index 0000000000000000000000000000000000000000..c03736628856bbf3c72c14a40966da95ff31bd60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8035.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0b3ad0344d041590635bb380c3880849a0d21881", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 3 + }, + "azure-pipelines.yml": { + "a": 9, + "d": 7 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 3, + "d": 1 + }, + "requirements_testing.txt": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8037.json b/mne-python/source/doc/sphinxext/prs/8037.json new file mode 100644 index 0000000000000000000000000000000000000000..2fb24e088bc5748c9f8fcb33809904a43fb19618 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8037.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "607fb4613fb5a80dd225132a4a53fe43b8fde0fb", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8041.json b/mne-python/source/doc/sphinxext/prs/8041.json new file mode 100644 index 0000000000000000000000000000000000000000..3322495ecef308f642b698cd3ef1f2fe49ea4135 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8041.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4acbad2cf9dff6704a975d42539aead9f327cc2b", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 7, + "d": 11 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 0, + "d": 6 + }, + "mne/viz/backends/_pyvista.py": { + "a": 82, + "d": 77 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8042.json b/mne-python/source/doc/sphinxext/prs/8042.json new file mode 100644 index 0000000000000000000000000000000000000000..66d1dbb6c37f64e495cd2c95e8f9e3762bd1705d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8042.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a525db9e7c6f8f0939094699dd01ab98d791dce6", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "environment.yml": { + "a": 7, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8046.json b/mne-python/source/doc/sphinxext/prs/8046.json new file mode 100644 index 0000000000000000000000000000000000000000..78b0d4cc0077241c82cb4d511cbe005bd94c3b4c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8046.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0e56673d9032eee88156ca5af4dd4b95098a9d15", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/linux_conda.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 0, + "d": 1 + }, + "environment.yml": { + "a": 13, + "d": 16 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8047.json b/mne-python/source/doc/sphinxext/prs/8047.json new file mode 100644 index 0000000000000000000000000000000000000000..05d103f2531c0b2ddf47c6c96e150cc17b25fba7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8047.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "98b87d1e3e745aab3f7c56571f444162209b37eb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8049.json b/mne-python/source/doc/sphinxext/prs/8049.json new file mode 100644 index 0000000000000000000000000000000000000000..8ca8a80ad3228d20d1e9e02dc2f6ed793b63807c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8049.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0681845f4e7ffaa280c4fc0ba1e0bb1730790d62", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/805.json b/mne-python/source/doc/sphinxext/prs/805.json new file mode 100644 index 0000000000000000000000000000000000000000..cb99e2429431dc1c575c202977f91de1f294645d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/805.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "872c0a14cfbb4a6b1bfc0ebf0fb27d05e932fe24", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 25, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8050.json b/mne-python/source/doc/sphinxext/prs/8050.json new file mode 100644 index 0000000000000000000000000000000000000000..a68832294c3a2cfec6e2207ba66d4da6b5ec2eec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8050.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "3545c3f26d4c1cffbe4b3b925eb059fb01663967", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 3, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 5, + "d": 5 + }, + "mne/conftest.py": { + "a": 8, + "d": 0 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 1, + "d": 1 + }, + "mne/io/open.py": { + "a": 11, + "d": 0 + }, + "mne/io/tests/test_apply_function.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_what.py": { + "a": 1, + "d": 1 + }, + "mne/io/what.py": { + "a": 3, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 3, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 3 + }, + "mne/tests/test_chpi.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 4, + "d": 3 + }, + "mne/transforms.py": { + "a": 3, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 13, + "d": 2 + }, + "tools/get_minimal_commands.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8051.json b/mne-python/source/doc/sphinxext/prs/8051.json new file mode 100644 index 0000000000000000000000000000000000000000..f3a6f6fde5a6b870fb8cd7d8e5d71a1b0e8711aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8051.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "18ca39583175a75fe19177520b0858942e78611f", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8054.json b/mne-python/source/doc/sphinxext/prs/8054.json new file mode 100644 index 0000000000000000000000000000000000000000..c51bde8f52957b2573a7acce2b91384c32c77611 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8054.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8b732abd096430bdf95d250823c5413f2342a3b4", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 17, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8055.json b/mne-python/source/doc/sphinxext/prs/8055.json new file mode 100644 index 0000000000000000000000000000000000000000..c29231dbda6443e80b44a521c90ae8e59bce6cf3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8055.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b5d651bd128c9009f6266896f8a18b59ad19f1fc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 2, + "d": 1 + }, + "requirements.txt": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8056.json b/mne-python/source/doc/sphinxext/prs/8056.json new file mode 100644 index 0000000000000000000000000000000000000000..280af87ed16b02b6040015bcb190ccd0a8d16bd9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8056.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "b62d8297f60c4b8c8f3ec44e499353b4a73efee1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 3 + }, + "azure-pipelines.yml": { + "a": 3, + "d": 3 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 5 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 11, + "d": 9 + }, + "mne/utils/_testing.py": { + "a": 8, + "d": 3 + }, + "mne/utils/config.py": { + "a": 2, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 2, + "d": 0 + }, + "mne/utils/tests/test_config.py": { + "a": 3, + "d": 3 + }, + "mne/utils/tests/test_logging.py": { + "a": 4, + "d": 1 + }, + "mne/viz/topo.py": { + "a": 1, + "d": 1 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8057.json b/mne-python/source/doc/sphinxext/prs/8057.json new file mode 100644 index 0000000000000000000000000000000000000000..011bafe28f51fccebece5072c62134253b16ca03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8057.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8af5846a8ae47fea351d7624f5d9a48b038ace65", + "authors": [ + { + "n": "Zhenya", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/install/contributing.rst": { + "a": 25, + "d": 0 + }, + "doc/sphinxext/gen_commands.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8058.json b/mne-python/source/doc/sphinxext/prs/8058.json new file mode 100644 index 0000000000000000000000000000000000000000..5ff9415da870fb301291dd0dde38b44988bceb6e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8058.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f7c898acb3d594d85177d1fc4a6130f7f0ff6481", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8059.json b/mne-python/source/doc/sphinxext/prs/8059.json new file mode 100644 index 0000000000000000000000000000000000000000..efd2af3fd5a628e9ea75aa3f38c6e0cc3186ed3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8059.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4c2f1c69747a2a9bbbbd54b1d009765c9b0129b1", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/806.json b/mne-python/source/doc/sphinxext/prs/806.json new file mode 100644 index 0000000000000000000000000000000000000000..0caeef0d4cceac677d54a810eb9811b204c0fcbd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/806.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f263f3f470ac607254f53cd0125e435fccd5c6b9", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/kit/kit.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8061.json b/mne-python/source/doc/sphinxext/prs/8061.json new file mode 100644 index 0000000000000000000000000000000000000000..750d0a2c7865392b3f1e26537990d41f4ec99bf7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8061.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b4e47862011f891cd9888930fde18897cc4df0e6", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8063.json b/mne-python/source/doc/sphinxext/prs/8063.json new file mode 100644 index 0000000000000000000000000000000000000000..b087b78255fced05c5c4842cc3215ddd8682a731 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8063.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "6bf644f79e019a171ca4cf15dcb59a639f6c8090", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 3, + "d": 2 + }, + "mne/conftest.py": { + "a": 8, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 79, + "d": 22 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 1, + "d": 7 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 2, + "d": 14 + }, + "mne/minimum_norm/inverse.py": { + "a": 9, + "d": 41 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 107, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 8, + "d": 9 + }, + "mne/utils/docs.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8064.json b/mne-python/source/doc/sphinxext/prs/8064.json new file mode 100644 index 0000000000000000000000000000000000000000..fe8dcfcf6c1c155e1ac896393e48707ed01336b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8064.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "a78e20d99f7d51f6b1617dc0330d139def76bc35", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 12, + "d": 2 + }, + "mne/conftest.py": { + "a": 16, + "d": 0 + }, + "mne/defaults.py": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 97, + "d": 45 + }, + "mne/utils/docs.py": { + "a": 33, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 80, + "d": 32 + }, + "mne/viz/_brain/_brain.py": { + "a": 411, + "d": 180 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 253, + "d": 109 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 201, + "d": 63 + }, + "mne/viz/_brain/view.py": { + "a": 34, + "d": 29 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 13, + "d": 11 + }, + "mne/viz/backends/_pyvista.py": { + "a": 45, + "d": 19 + }, + "mne/viz/backends/base_renderer.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 66, + "d": 27 + }, + "setup.cfg": { + "a": 2, + "d": 1 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 22, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8066.json b/mne-python/source/doc/sphinxext/prs/8066.json new file mode 100644 index 0000000000000000000000000000000000000000..178543791875e7152688bdbd942d819e0f31ec53 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8066.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7f30d1d840f953cbb0b01c77610f4acab6e09493", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Robert Luke", + "e": "mail@robertluke.net" + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 4, + "d": 9 + }, + "mne/io/snirf/_snirf.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8068.json b/mne-python/source/doc/sphinxext/prs/8068.json new file mode 100644 index 0000000000000000000000000000000000000000..248907a9736c2dfcc0f758434051858897372d9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8068.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "000dac95c0f7a4439ee60fb92f1007fd288f9611", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 131, + "d": 174 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/807.json b/mne-python/source/doc/sphinxext/prs/807.json new file mode 100644 index 0000000000000000000000000000000000000000..e5dc178820d9edbe25610922e0dfae1e80a29a99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/807.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "da1c1c44f162ec4a5cc6ed7cc862dcfe1cffbc0d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/simulation/__init__.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8072.json b/mne-python/source/doc/sphinxext/prs/8072.json new file mode 100644 index 0000000000000000000000000000000000000000..76723910db6fb28032bc4767e7db2995a1eee482 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8072.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "01f504710baaec959ec3296287faa31005fe0554", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 21, + "d": 21 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8073.json b/mne-python/source/doc/sphinxext/prs/8073.json new file mode 100644 index 0000000000000000000000000000000000000000..a228afa9af958f31c1171cf5b59ee481cb50e7bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8073.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "1783b970b39b5cf70363549d728cb108aff22286", + "authors": [ + { + "n": "Rahul Nadkarni", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 17, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8075.json b/mne-python/source/doc/sphinxext/prs/8075.json new file mode 100644 index 0000000000000000000000000000000000000000..d74db05c70d927846537116b70ea434f6ee8e93d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8075.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0e5ec90ebc3a5d428ef3a80aa9c3f14ee5329c0d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/io/fieldtrip/fieldtrip.py": { + "a": 3, + "d": 3 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 14, + "d": 1 + }, + "mne/io/fieldtrip/utils.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8077.json b/mne-python/source/doc/sphinxext/prs/8077.json new file mode 100644 index 0000000000000000000000000000000000000000..19e0c65be9f38b5c492114d2c9df4db7b27e48c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8077.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f52272a4cacc12624f0e92270495c22191367bc9", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 5 + }, + "mne/evoked.py": { + "a": 2, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8079.json b/mne-python/source/doc/sphinxext/prs/8079.json new file mode 100644 index 0000000000000000000000000000000000000000..b30e5b84ee6756eb1e3be21ba901b971133d260f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8079.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d82a2e7fe36cb6d1374df74ab667d89d88d9496c", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Robert Luke", + "e": "mail@robertluke.net" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 0 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 3, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 45, + "d": 0 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 38, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/808.json b/mne-python/source/doc/sphinxext/prs/808.json new file mode 100644 index 0000000000000000000000000000000000000000..0ab3bae948e43fc8f4fc74f7fc3ee46b974d633c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/808.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e21546e88e75dc5e0e88099a70e37b69948bf2cf", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/getting_started.rst": { + "a": 44, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8082.json b/mne-python/source/doc/sphinxext/prs/8082.json new file mode 100644 index 0000000000000000000000000000000000000000..e37a27dd82d1bdf889fe6104739f1ffc376d185a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8082.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "64e3dd09ec3307586514bb8c063ff2d06d8b7986", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 15, + "d": 10 + }, + "mne/surface.py": { + "a": 47, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 7, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 15, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 58, + "d": 14 + }, + "mne/viz/_brain/_brain.py": { + "a": 42, + "d": 18 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 12, + "d": 5 + }, + "mne/viz/_brain/colormap.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/surface.py": { + "a": 18, + "d": 14 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 10, + "d": 8 + }, + "mne/viz/_brain/view.py": { + "a": 28, + "d": 22 + }, + "mne/viz/backends/_pyvista.py": { + "a": 27, + "d": 18 + }, + "mne/viz/tests/test_3d.py": { + "a": 29, + "d": 3 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8083.json b/mne-python/source/doc/sphinxext/prs/8083.json new file mode 100644 index 0000000000000000000000000000000000000000..0826dd3fbe8687e6825592483afcc15b1ba2ed7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8083.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "8fd3c1096c07c1a6dfaa7bb2a4021ba97f02b4fb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 40, + "d": 0 + }, + "mne/epochs.py": { + "a": 9, + "d": 18 + }, + "mne/evoked.py": { + "a": 6, + "d": 13 + }, + "mne/externals/doccer.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_regress.py": { + "a": 87, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/eog.py": { + "a": 6, + "d": 2 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 38, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 5, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 37, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 0 + }, + "tutorials/preprocessing/plot_35_artifact_correction_regression.py": { + "a": 172, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8084.json b/mne-python/source/doc/sphinxext/prs/8084.json new file mode 100644 index 0000000000000000000000000000000000000000..3045622b6cd8ae5d692039ee9150b863890a7371 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8084.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bb56d3e6c10925540ce4a970e3c3811c50d2a26e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8086.json b/mne-python/source/doc/sphinxext/prs/8086.json new file mode 100644 index 0000000000000000000000000000000000000000..5b0e5c467072a29b47adef7f258e3b66b111977b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8086.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "20963b79a57adab8a8058fc29d46ac037208fbe5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 13, + "d": 0 + }, + "mne/baseline.py": { + "a": 2, + "d": 9 + }, + "mne/epochs.py": { + "a": 9, + "d": 28 + }, + "mne/evoked.py": { + "a": 5, + "d": 18 + }, + "mne/report.py": { + "a": 24, + "d": 11 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_report.py": { + "a": 6, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 20, + "d": 0 + }, + "tutorials/misc/plot_report.py": { + "a": 29, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8089.json b/mne-python/source/doc/sphinxext/prs/8089.json new file mode 100644 index 0000000000000000000000000000000000000000..610551815a3747be75edc6f40e74018c3169e531 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8089.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "38f3c2bc34a604d4f39c88697e846389581ea50e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 7, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8090.json b/mne-python/source/doc/sphinxext/prs/8090.json new file mode 100644 index 0000000000000000000000000000000000000000..37f90f19086c885968612713016f167774af4b38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8090.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b16e81957731b1373a1819702a1c6d1a220dc2ac", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/morph.py": { + "a": 17, + "d": 14 + }, + "mne/source_space.py": { + "a": 23, + "d": 4 + }, + "mne/tests/test_source_space.py": { + "a": 9, + "d": 0 + }, + "mne/utils/_logging.py": { + "a": 16, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8091.json b/mne-python/source/doc/sphinxext/prs/8091.json new file mode 100644 index 0000000000000000000000000000000000000000..e6e1a21f68acdfcb22597d38aeb562a6b1042ade --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8091.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8f6b548229ffd0f6a92f1b72e357a5000fbfd6c2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8095.json b/mne-python/source/doc/sphinxext/prs/8095.json new file mode 100644 index 0000000000000000000000000000000000000000..d7ee107dc397ea1f0e00e325788829100b718c32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8095.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "256589149882fab099f01ec1dcea1da3bf5a0a8e", + "authors": [ + { + "n": "Yu-Han Luo", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8098.json b/mne-python/source/doc/sphinxext/prs/8098.json new file mode 100644 index 0000000000000000000000000000000000000000..31750bbd69ed681a799b9196bdffd83f79afe6f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8098.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "81c10a0f1cba9f1ba3c38d9da0c48a626b1147e7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 6, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 23, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8099.json b/mne-python/source/doc/sphinxext/prs/8099.json new file mode 100644 index 0000000000000000000000000000000000000000..2f5831b98cc854929d80580b40c3548dfcba744a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8099.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9dbb10156a8faf6610f3a8d979ffe9b853dd20dd", + "authors": [ + { + "n": "Martin", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/filter.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/81.json b/mne-python/source/doc/sphinxext/prs/81.json new file mode 100644 index 0000000000000000000000000000000000000000..d70d5f2cb36ee67105f07ea56747b02be50b9b4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/81.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "7581f380b790d169af687b37c286dd4880ab1b8d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/Makefile": { + "a": 5, + "d": 1 + }, + "doc/source/_images/mne_helmet.png": { + "a": 0, + "d": 0 + }, + "doc/source/manual/list.rst": { + "a": 4, + "d": 1 + }, + "doc/source/python_reference.rst": { + "a": 55, + "d": 2 + }, + "doc/sphinxext/gen_rst.py": { + "a": 254, + "d": 52 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 3, + "d": 4 + }, + "examples/inverse/plot_read_inverse.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/plot_read_source_space.py": { + "a": 1, + "d": 0 + }, + "examples/plot_read_bem_surfaces.py": { + "a": 1, + "d": 2 + }, + "examples/plot_read_forward.py": { + "a": 1, + "d": 0 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/label.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/maxfilter.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/psd.py": { + "a": 2, + "d": 2 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + }, + "mne/viz.py": { + "a": 12, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8100.json b/mne-python/source/doc/sphinxext/prs/8100.json new file mode 100644 index 0000000000000000000000000000000000000000..2d2783c970bebaff0fbb22d9106f8723c17433e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8100.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "9a80b610299fe798285296682fc5c84558302d07", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 8, + "d": 0 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 2, + "d": 3 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 2 + }, + "mne/channels/layout.py": { + "a": 5, + "d": 4 + }, + "mne/channels/tests/test_layout.py": { + "a": 6, + "d": 4 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/_digitization.py": { + "a": 8, + "d": 5 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/constants.py": { + "a": 34, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 198, + "d": 74 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 66, + "d": 2 + }, + "mne/surface.py": { + "a": 14, + "d": 5 + }, + "mne/tests/test_surface.py": { + "a": 3, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 2 + }, + "tutorials/io/plot_10_reading_meg_data.py": { + "a": 13, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8102.json b/mne-python/source/doc/sphinxext/prs/8102.json new file mode 100644 index 0000000000000000000000000000000000000000..67a1e4ce4970ce1b4ce658aaa557d50ea9d8d89e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8102.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0441154d287f3c5593843082389cf188df740887", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 5, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8103.json b/mne-python/source/doc/sphinxext/prs/8103.json new file mode 100644 index 0000000000000000000000000000000000000000..d22bba156d64824c8c5e7ce73f19674754a8de17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8103.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "9c7788a1a40e1476f9d7d94cfdd978812c75d65b", + "authors": [ + { + "n": "Yu-Han Luo", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/cov.py": { + "a": 1, + "d": 4 + }, + "mne/epochs.py": { + "a": 9, + "d": 9 + }, + "mne/preprocessing/ecg.py": { + "a": 2, + "d": 6 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 9, + "d": 15 + }, + "mne/tests/test_epochs.py": { + "a": 16, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 18, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 17, + "d": 7 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 5 + }, + "mne/viz/tests/test_ica.py": { + "a": 19, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8107.json b/mne-python/source/doc/sphinxext/prs/8107.json new file mode 100644 index 0000000000000000000000000000000000000000..12948145cde0d108de43535dc88506bd21cd288f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8107.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "270b77768e4d2cf0f3f7ae4defd229c9f39eb2af", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 2, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 8, + "d": 7 + }, + "mne/channels/montage.py": { + "a": 21, + "d": 20 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 1 + }, + "mne/io/what.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8108.json b/mne-python/source/doc/sphinxext/prs/8108.json new file mode 100644 index 0000000000000000000000000000000000000000..8531922706154e4f4b34e7abe35cbec91201590a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8108.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c85cf38a2c4550caf5520295756654ce6bb890a5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 11, + "d": 41 + }, + "mne/tests/test_report.py": { + "a": 13, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8109.json b/mne-python/source/doc/sphinxext/prs/8109.json new file mode 100644 index 0000000000000000000000000000000000000000..460c33858ffd5e3fb02cfb1cc750f541c7765e82 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8109.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "421cb1bc2f432f8eb93a49a3c38be1ac48838497", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/811.json b/mne-python/source/doc/sphinxext/prs/811.json new file mode 100644 index 0000000000000000000000000000000000000000..88c03b9745a775a843aefc884a9992d78fc98105 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/811.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8dc2d3e627fbf19e9dce7240928519d9c4d8485e", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8111.json b/mne-python/source/doc/sphinxext/prs/8111.json new file mode 100644 index 0000000000000000000000000000000000000000..878b8ca367aa470f7596f49394f7e5fcc69d6012 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8111.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "989f2d4d6a58c73963fb907bf9da3a53587c9b62", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 4, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 38, + "d": 97 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 122, + "d": 160 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 23, + "d": 10 + }, + "mne/viz/backends/_pyvista.py": { + "a": 82, + "d": 12 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8112.json b/mne-python/source/doc/sphinxext/prs/8112.json new file mode 100644 index 0000000000000000000000000000000000000000..791ccef5aca630d6bf6698be0030f0cd07691887 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8112.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dc3bffdbbbd9dd4249561792f73328ced0b5c2c0", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 11, + "d": 2 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 60, + "d": 15 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8113.json b/mne-python/source/doc/sphinxext/prs/8113.json new file mode 100644 index 0000000000000000000000000000000000000000..dd87f6450adc236e0b858a59169df2b37c07667b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8113.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "c997dc0d0ebed9f4f1fede5c869e700c8d687a6a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "wronk", + "e": "wronk.mark@gmail.com" + } + ], + "changes": { + "doc/python_reference.rst": { + "a": 3, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 8, + "d": 40 + }, + "mne/externals/doccer.py": { + "a": 5, + "d": 4 + }, + "mne/io/egi/egimff.py": { + "a": 2, + "d": 2 + }, + "mne/io/tag.py": { + "a": 6, + "d": 4 + }, + "mne/preprocessing/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 434, + "d": 19 + }, + "mne/preprocessing/maxwell.py": { + "a": 68, + "d": 46 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 116, + "d": 17 + }, + "mne/utils/docs.py": { + "a": 26, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8116.json b/mne-python/source/doc/sphinxext/prs/8116.json new file mode 100644 index 0000000000000000000000000000000000000000..c5bfa594998387f70fb00c9d3ba4c7b5436bcef0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8116.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "13a5ea40f005e9d9f45ab0057c8faaefadb10eb5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_mne_helmet.py": { + "a": 32, + "d": 0 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/icons/mne_icon.png": { + "a": 0, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 25, + "d": 10 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 12 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 5, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 15, + "d": 6 + }, + "mne/viz/backends/base_renderer.py": { + "a": 9, + "d": 3 + }, + "mne/viz/backends/renderer.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8117.json b/mne-python/source/doc/sphinxext/prs/8117.json new file mode 100644 index 0000000000000000000000000000000000000000..5950b7fdfd44e73381136ba10332f0aa445551f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8117.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1c29127598282be7f177406c02acde3fd38eb4d8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "logo/generate_mne_logos.py": { + "a": 19, + "d": 2 + }, + "mne/icons/mne.qrc": { + "a": 1, + "d": 0 + }, + "mne/icons/resources.py": { + "a": 824, + "d": 151 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 1, + "d": 14 + }, + "mne/viz/backends/_pyvista.py": { + "a": 27, + "d": 1 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/812.json b/mne-python/source/doc/sphinxext/prs/812.json new file mode 100644 index 0000000000000000000000000000000000000000..9cb891be52fa3b97b6281e19ebf96cecbdff3e3d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/812.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8683b15314d53ff3cbd141a80ab7c8afe4b9e56b", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "examples/inverse/plot_tf_lcmv.py": { + "a": 9, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 11, + "d": 4 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8122.json b/mne-python/source/doc/sphinxext/prs/8122.json new file mode 100644 index 0000000000000000000000000000000000000000..0f4e24a329af58fbff7a8bb38393a8f5cd552e8d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8122.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "6d0b634bda6488919feb468855563674d430a421", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 3 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 90, + "d": 4 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_beer_lambert_law.py": { + "a": 6, + "d": 4 + }, + "mne/preprocessing/tests/test_nirs.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/tests/test_optical_density.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_scalp_coupling_index.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/tests/test_temporal_derivative_distribution_repair.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8123.json b/mne-python/source/doc/sphinxext/prs/8123.json new file mode 100644 index 0000000000000000000000000000000000000000..e392c6ef1e801ecc5521bb328c3c9e48c1a9600b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8123.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bfbdc83d87135890ef18f3663394e96302fb816b", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8125.json b/mne-python/source/doc/sphinxext/prs/8125.json new file mode 100644 index 0000000000000000000000000000000000000000..7b78fc906bc4c8cbbe6869187b2649b986fe1d47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8125.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "0686c1424dd46b9275791734cb3cd1b5fab4b40d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/icons/mne-circle-black.png": { + "a": 0, + "d": 0 + }, + "mne/icons/mne.qrc": { + "a": 1, + "d": 0 + }, + "mne/icons/reset-black-18dp.svg": { + "a": 1, + "d": 0 + }, + "mne/icons/resources.py": { + "a": 368, + "d": 335 + }, + "mne/viz/_brain/_brain.py": { + "a": 11, + "d": 1 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 16, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8126.json b/mne-python/source/doc/sphinxext/prs/8126.json new file mode 100644 index 0000000000000000000000000000000000000000..8aee5511b00ad68734932437e60f60fce839901a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8126.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c3283d3b0dfd8f28851b27ee6ae745c4b0404aba", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 4, + "d": 2 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 38, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8129.json b/mne-python/source/doc/sphinxext/prs/8129.json new file mode 100644 index 0000000000000000000000000000000000000000..b0f98fcb343295ad0b0cc55f4d001efc6d148989 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8129.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "19358a187ad405866df4bdd8c74c226afa1bc31b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/fixes.py": { + "a": 3, + "d": 4 + }, + "mne/morph.py": { + "a": 31, + "d": 17 + }, + "mne/tests/test_morph.py": { + "a": 27, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/813.json b/mne-python/source/doc/sphinxext/prs/813.json new file mode 100644 index 0000000000000000000000000000000000000000..3b8de0ecaaab6160f990b71fabd9691ba6a49b63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/813.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "b873db2c77ca57bd95203eb23a36162f83a8ebb5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 4, + "d": 1 + }, + "mne/baseline.py": { + "a": 5, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 8, + "d": 5 + }, + "mne/cov.py": { + "a": 15, + "d": 9 + }, + "mne/fiff/raw.py": { + "a": 29, + "d": 15 + }, + "mne/fiff/tests/test_raw.py": { + "a": 4, + "d": 4 + }, + "mne/filter.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 10, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 18, + "d": 3 + }, + "mne/preprocessing/peak_finder.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 5, + "d": 3 + }, + "mne/stats/cluster_level.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/multitaper.py": { + "a": 6, + "d": 6 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8132.json b/mne-python/source/doc/sphinxext/prs/8132.json new file mode 100644 index 0000000000000000000000000000000000000000..b7bb00d19a4a06248a33ba58690e54381967fb9f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8132.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "8b0a515ccd2c6389fc62c99bc60a4f1b7136b49e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 14, + "d": 0 + }, + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 20, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 23 + }, + "mne/io/reference.py": { + "a": 41, + "d": 74 + }, + "mne/io/tests/test_reference.py": { + "a": 62, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 46, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8134.json b/mne-python/source/doc/sphinxext/prs/8134.json new file mode 100644 index 0000000000000000000000000000000000000000..3c79d0deb8bfd801ad24d7dcbb742b787e957498 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8134.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4287eda8985e9131634cd0abee89e444d14aeedd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 16, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 28, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8135.json b/mne-python/source/doc/sphinxext/prs/8135.json new file mode 100644 index 0000000000000000000000000000000000000000..a1833f2fc8436f4a03e181cbb5bed60e607780cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8135.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9502518b5214ea7fdf1e835d849fd9cbdefc884f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8137.json b/mne-python/source/doc/sphinxext/prs/8137.json new file mode 100644 index 0000000000000000000000000000000000000000..80accf1ce07c0b702d96c5be817aa782db7c3c89 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8137.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "f2d019339ad786d8704d63a52871ade6d05f3248", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 0 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 6, + "d": 8 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 7, + "d": 1 + }, + "mne/beamformer/_rap_music.py": { + "a": 60, + "d": 35 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 22, + "d": 15 + }, + "mne/forward/forward.py": { + "a": 30, + "d": 17 + }, + "mne/forward/tests/test_forward.py": { + "a": 10, + "d": 1 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 16, + "d": 23 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 71, + "d": 23 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 46, + "d": 24 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 129, + "d": 24 + }, + "mne/io/proj.py": { + "a": 6, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 10, + "d": 5 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 44, + "d": 29 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8138.json b/mne-python/source/doc/sphinxext/prs/8138.json new file mode 100644 index 0000000000000000000000000000000000000000..c7cff1034fbf0ec80da036815d5fba164777de26 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8138.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ae68fc4b23d505ec3b57f6a65a7c4fd2203784d8", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 8, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/814.json b/mne-python/source/doc/sphinxext/prs/814.json new file mode 100644 index 0000000000000000000000000000000000000000..c99c96e2b0c2638ea49dbcecf24f22ac2a1b4995 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/814.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c3614e11dc054edb481a757106c83a1970657f37", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "examples/inverse/plot_tf_dics.py": { + "a": 5, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 10, + "d": 3 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8141.json b/mne-python/source/doc/sphinxext/prs/8141.json new file mode 100644 index 0000000000000000000000000000000000000000..8b789ddb4eb3b77e7b0c46bf6304eaef790df2fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8141.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4c44bd6ae90dd4d5c6c2e925d93f1b2fbf7bda6a", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8146.json b/mne-python/source/doc/sphinxext/prs/8146.json new file mode 100644 index 0000000000000000000000000000000000000000..7c6b00c7c18bb5d90c2548f1e45343530054c3d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8146.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "56cc7bb8dd0a955c319e800a14eba4146d471866", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8151.json b/mne-python/source/doc/sphinxext/prs/8151.json new file mode 100644 index 0000000000000000000000000000000000000000..3c8dbacc88f1f7804841a47c1cb6bc3b1ae0929b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8151.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "9f4ace5a51174f3922fdbbf887ad3d866faa8e24", + "authors": [ + { + "n": null, + "e": "flKazemakase@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 9, + "d": 0 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 2, + "d": 2 + }, + "examples/decoding/plot_decoding_csp_timefreq.py": { + "a": 5, + "d": 5 + }, + "mne/decoding/csp.py": { + "a": 166, + "d": 127 + }, + "mne/decoding/tests/test_csp.py": { + "a": 78, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8153.json b/mne-python/source/doc/sphinxext/prs/8153.json new file mode 100644 index 0000000000000000000000000000000000000000..174c4ab5220629085de2405e50442d8a96a1e9ff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8153.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3168a9aa68c4989420c5a447ac1dc38bba07fc7e", + "authors": [ + { + "n": "Lau Møller Andersen", + "e": "lmandersen@cfin.au.dk" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 11, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 8, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 37, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8155.json b/mne-python/source/doc/sphinxext/prs/8155.json new file mode 100644 index 0000000000000000000000000000000000000000..8a7d6f85895bdadb22f2f9957c685d4a6b98e29d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8155.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1cf59be1e6454f6ef5aa81209866346c1c0fbd65", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/pick.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8156.json b/mne-python/source/doc/sphinxext/prs/8156.json new file mode 100644 index 0000000000000000000000000000000000000000..2a9a9ca662b276d2c4ba78b7c44823ae839a2954 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8156.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "7f34517b9444a5d6c0585699a27d8c94e3840ab7", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 0 + }, + "mne/baseline.py": { + "a": 41, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 3, + "d": 2 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 5, + "d": 2 + }, + "mne/conftest.py": { + "a": 2, + "d": 1 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 58, + "d": 55 + }, + "mne/evoked.py": { + "a": 164, + "d": 27 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 5, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 4, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 6, + "d": 2 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 6, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 22, + "d": 5 + }, + "mne/tests/test_evoked.py": { + "a": 36, + "d": 3 + }, + "mne/tests/test_morph.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 6, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 44, + "d": 15 + }, + "mne/viz/tests/test_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 1 + }, + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 19, + "d": 0 + }, + "tutorials/evoked/plot_20_visualize_evoked.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8161.json b/mne-python/source/doc/sphinxext/prs/8161.json new file mode 100644 index 0000000000000000000000000000000000000000..400b53a0577b014b9d896c16b876a18c2797d09f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8161.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e09fa30b86ba2af0574e01abe45f9674cdd5cc4d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".github/workflows/ci.yml": { + "a": 75, + "d": 0 + }, + ".travis.yml": { + "a": 2, + "d": 17 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 6, + "d": 6 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8164.json b/mne-python/source/doc/sphinxext/prs/8164.json new file mode 100644 index 0000000000000000000000000000000000000000..a2b4f4aeca5907eaed3eb1e67fe70e4808840354 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8164.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "3bd482e446d7fcd0751dfcf666afb0393a24809f", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 49, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8165.json b/mne-python/source/doc/sphinxext/prs/8165.json new file mode 100644 index 0000000000000000000000000000000000000000..1c2d0d5747ccf59964edc1694db904f43a9a24be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8165.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fbc546240c1123d2942cc87ad5d9336fbfbea39f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_timeviewer.py": { + "a": 14, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8166.json b/mne-python/source/doc/sphinxext/prs/8166.json new file mode 100644 index 0000000000000000000000000000000000000000..50cd17441aa0574b61691e0846ed4b7c6432b5ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8166.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7ce47156f6e7405977d4fc9c470b3358768049a5", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/renderer.py": { + "a": 24, + "d": 4 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 2, + "d": 1 + }, + "tutorials/source-modeling/plot_background_freesurfer_mne.py": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8169.json b/mne-python/source/doc/sphinxext/prs/8169.json new file mode 100644 index 0000000000000000000000000000000000000000..2c73ac30d7a327ab2edf4243ad939e1aa4a6d7b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8169.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "7cf71560436e8ca6156a9fe95cb87cbe3ab655b3", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/report.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/817.json b/mne-python/source/doc/sphinxext/prs/817.json new file mode 100644 index 0000000000000000000000000000000000000000..86ff6a148b1d18d6c170b3284ddf04dab7a16354 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/817.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "603e479f4d50938927759ee39fa227b97c132762", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/kit/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/fiff/kit/coreg.py": { + "a": 6, + "d": 4 + }, + "mne/fiff/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/kit/tests/test_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/kit/tests/test_kit.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8170.json b/mne-python/source/doc/sphinxext/prs/8170.json new file mode 100644 index 0000000000000000000000000000000000000000..194e59010dad7e08b48ac65d87f981cb77707bc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8170.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d4b76bd7ca518d6fbd56e7b266fbb804ab4eee61", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 22, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8174.json b/mne-python/source/doc/sphinxext/prs/8174.json new file mode 100644 index 0000000000000000000000000000000000000000..1ff2fd6142e51fa821fdb15fe8d8736fb17479dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8174.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "61feb1686b8859bd666866f62c1179e6c0ddbe08", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 3, + "d": 5 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8175.json b/mne-python/source/doc/sphinxext/prs/8175.json new file mode 100644 index 0000000000000000000000000000000000000000..7d2fef7e9d9e358af0931089baa2e93915dd66e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8175.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cabc08f9ee07eccd8e9ee0c610b2f7a0db90b755", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8176.json b/mne-python/source/doc/sphinxext/prs/8176.json new file mode 100644 index 0000000000000000000000000000000000000000..651f418378599b0883e8d2e34947487ba81c8b66 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8176.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "1cda89a6dc845f717a6498e685a938392efb01aa", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_includes/data_formats.rst": { + "a": 3, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 0, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/io/persyst/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/persyst/persyst.py": { + "a": 410, + "d": 0 + }, + "mne/io/persyst/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 215, + "d": 0 + }, + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8177.json b/mne-python/source/doc/sphinxext/prs/8177.json new file mode 100644 index 0000000000000000000000000000000000000000..40e151b7e4b1520ffe9430430c7c25421cea204c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8177.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "92254198f02e19ca9227888fd2b1d5f8a90c8084", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/utils/progressbar.py": { + "a": 13, + "d": 3 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8178.json b/mne-python/source/doc/sphinxext/prs/8178.json new file mode 100644 index 0000000000000000000000000000000000000000..c94c925aee9cea361dda5426195be0ec3de87e2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8178.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "54259a8e151163381b0bb72de691607839c27236", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 32, + "d": 10 + }, + "mne/channels/montage.py": { + "a": 5, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 81, + "d": 19 + }, + "mne/preprocessing/_csd.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 20, + "d": 2 + }, + "mne/viz/montage.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8179.json b/mne-python/source/doc/sphinxext/prs/8179.json new file mode 100644 index 0000000000000000000000000000000000000000..9c85b087e8d2597b1427663f01fdb884ddd6e2b3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8179.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dfe419501b2c77d8938f80845e1df283cebd0fb8", + "authors": [ + { + "n": "Hubert Banville", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/sample-datasets/plot_sleep.py": { + "a": 16, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/818.json b/mne-python/source/doc/sphinxext/prs/818.json new file mode 100644 index 0000000000000000000000000000000000000000..ae76730859f8617d24e7b33e12f9ac4d74da032f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/818.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6d156371994920c6b7294b9eeef4712da4582589", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 198, + "d": 25 + }, + "mne/tests/test_label.py": { + "a": 47, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8180.json b/mne-python/source/doc/sphinxext/prs/8180.json new file mode 100644 index 0000000000000000000000000000000000000000..5bda83b3597cef8cf8775459c5c9b8bd4d718414 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8180.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "db0bacc5a01bf1d45ede7d21b5cdedfa234ded36", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/viz/tests/test_epochs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8181.json b/mne-python/source/doc/sphinxext/prs/8181.json new file mode 100644 index 0000000000000000000000000000000000000000..3cb26becb29cde48017078a720158f7960522949 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8181.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0d88b2ef0ec924c1bcfdc6c1a9fe7b8cd7a752bd", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 160, + "d": 0 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 5, + "d": 443 + }, + "mne/viz/_brain/callback.py": { + "a": 185, + "d": 0 + }, + "mne/viz/_brain/mplcanvas.py": { + "a": 116, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 20, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8182.json b/mne-python/source/doc/sphinxext/prs/8182.json new file mode 100644 index 0000000000000000000000000000000000000000..c839f6147b853d1472c26f4b604d7d7b247eeb1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8182.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ff6751d8ef3b4b1e495ac3e68c59c3e1a41f2edf", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 40, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8185.json b/mne-python/source/doc/sphinxext/prs/8185.json new file mode 100644 index 0000000000000000000000000000000000000000..f95067f15d16507fb8cb8f1e7b7a693754fceb28 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8185.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b76890bb4f8202282a70cffb5dabed11977dc832", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 17, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8187.json b/mne-python/source/doc/sphinxext/prs/8187.json new file mode 100644 index 0000000000000000000000000000000000000000..cf97db33bdce17bcfa8c5afd8d4f4f0b2f222bf2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8187.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "174ab824bb99dc7d4ba8246d16f179f973554256", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/constants.py": { + "a": 12, + "d": 4 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8188.json b/mne-python/source/doc/sphinxext/prs/8188.json new file mode 100644 index 0000000000000000000000000000000000000000..7fdac32886b9f9766c8d23d04bc4c2a9c108d698 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8188.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e77de58173b0c2b3bd1a85ec42f55fd808d8b20e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 2, + "d": 3 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 10, + "d": 4 + }, + "tutorials/source-modeling/plot_dipole_fit.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8189.json b/mne-python/source/doc/sphinxext/prs/8189.json new file mode 100644 index 0000000000000000000000000000000000000000..7c326929dfc995b7cc987fec2d4cf07f6854b831 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8189.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "a240a55f78382baae269b2bc834fdfbec3a68899", + "authors": [ + { + "n": "Hubert Banville", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 3, + "d": 12 + }, + "mne/conftest.py": { + "a": 10, + "d": 0 + }, + "mne/datasets/sleep_physionet/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 25, + "d": 6 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 27, + "d": 8 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 69, + "d": 26 + }, + "mne/epochs.py": { + "a": 8, + "d": 14 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 7 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 29, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 15, + "d": 1 + }, + "requirements_testing.txt": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8190.json b/mne-python/source/doc/sphinxext/prs/8190.json new file mode 100644 index 0000000000000000000000000000000000000000..1e17f7625ab22f26d6ceb52fd87f48d5417fb3e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8190.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "f6b58d4ad1ee23a695b986b2e12e84af186be5cc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 105, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 68, + "d": 5 + }, + "tutorials/misc/plot_ecog.py": { + "a": 22, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8191.json b/mne-python/source/doc/sphinxext/prs/8191.json new file mode 100644 index 0000000000000000000000000000000000000000..3b79800725fb3864e36cdf33107f424a73d85d4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8191.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "09d50eb26721930d660c8c0a09893588f64aab4e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/bem.py": { + "a": 122, + "d": 60 + }, + "mne/tests/test_bem.py": { + "a": 22, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8193.json b/mne-python/source/doc/sphinxext/prs/8193.json new file mode 100644 index 0000000000000000000000000000000000000000..f4986ad5cac991254f324cd43ce1ddadd701aca8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8193.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "af1120c4cdea7086c2af661fefd37ef93ac8f410", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 9, + "d": 6 + }, + "mne/channels/tests/test_montage.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8194.json b/mne-python/source/doc/sphinxext/prs/8194.json new file mode 100644 index 0000000000000000000000000000000000000000..60e2a07b995f3e6aa34460931ccd30d7666cb80e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8194.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "62fabdbdd4453a52d9f87d15109ffe2e3eee8b87", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 21, + "d": 12 + }, + "mne/viz/backends/_pyvista.py": { + "a": 45, + "d": 59 + }, + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 17, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8197.json b/mne-python/source/doc/sphinxext/prs/8197.json new file mode 100644 index 0000000000000000000000000000000000000000..2b9305a0c5f568f176ff1a05846e8c0a62d1ffd7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8197.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "f0e20c05511145927b666b40b774fb99cc64d2f2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_mne_cov_power.py": { + "a": 8, + "d": 22 + }, + "mne/cov.py": { + "a": 86, + "d": 2 + }, + "mne/externals/doccer.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 111, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 32, + "d": 26 + }, + "mne/viz/tests/test_topomap.py": { + "a": 10, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 21, + "d": 82 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8198.json b/mne-python/source/doc/sphinxext/prs/8198.json new file mode 100644 index 0000000000000000000000000000000000000000..f773502562b613bced150ebf37234e386ba4146a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8198.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "fbbf85b44bd3ce000a6777eb3dc9cac2f34d3e2f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 3, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 6, + "d": 3 + }, + "mne/utils/check.py": { + "a": 7, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 16, + "d": 9 + }, + "mne/viz/misc.py": { + "a": 16, + "d": 5 + }, + "mne/viz/tests/test_misc.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/82.json b/mne-python/source/doc/sphinxext/prs/82.json new file mode 100644 index 0000000000000000000000000000000000000000..d65ea180aa05cd749df92ab9945c8e33b6e38923 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/82.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9244365010531de07ac37252f8d5a80cab6d0f56", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/artifacts/stim.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/forward.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8200.json b/mne-python/source/doc/sphinxext/prs/8200.json new file mode 100644 index 0000000000000000000000000000000000000000..a950fdebd3803d6c2dcebd05c3ea3f0f3a635cfd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8200.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c1f90498dec08227c19cf7277745454f1551257f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8202.json b/mne-python/source/doc/sphinxext/prs/8202.json new file mode 100644 index 0000000000000000000000000000000000000000..f3304986e3fd19f23f58bcf3003367109926d045 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8202.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "97498364165e8702e07d582cd13cfb48cea51b06", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_vector_mne_solution.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8206.json b/mne-python/source/doc/sphinxext/prs/8206.json new file mode 100644 index 0000000000000000000000000000000000000000..b728922b9706308d51f1d544c393fe795421199c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8206.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5e5c2e102d06eedcef19af799e22741afec92a68", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/backends/renderer.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8207.json b/mne-python/source/doc/sphinxext/prs/8207.json new file mode 100644 index 0000000000000000000000000000000000000000..ea99195659cc2783888ac467cccb60b6c1db1cce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8207.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "053faee1d4151d4dee9b82680e93772ed880faa3", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8209.json b/mne-python/source/doc/sphinxext/prs/8209.json new file mode 100644 index 0000000000000000000000000000000000000000..03e91525453a000ae1d4b1d60e716f7b0f2a7540 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8209.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "48823ad1dd1138b8a07e0770ef64368ae24de64e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/821.json b/mne-python/source/doc/sphinxext/prs/821.json new file mode 100644 index 0000000000000000000000000000000000000000..408bd95118ac4dae1f66e5c19f9c6c6555a714ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/821.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e8a6bab0af6466788453f9467ce62c258b597924", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 2, + "d": 1 + }, + "mne/utils.py": { + "a": 18, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8210.json b/mne-python/source/doc/sphinxext/prs/8210.json new file mode 100644 index 0000000000000000000000000000000000000000..37efe01ea2929cce67b0e81b8c1d7e567eb62c80 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8210.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "06f232cd75c203765b7165a8d94df1a52d5c7cea", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 25, + "d": 3 + }, + "mne/io/base.py": { + "a": 31, + "d": 9 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 5 + }, + "mne/io/cnt/cnt.py": { + "a": 19, + "d": 30 + }, + "mne/io/edf/edf.py": { + "a": 56, + "d": 69 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 8, + "d": 2 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 3, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 11, + "d": 9 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 14, + "d": 4 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 3, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 7, + "d": 4 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 2 + }, + "mne/io/snirf/_snirf.py": { + "a": 3, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 143, + "d": 3 + }, + "mne/io/utils.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8212.json b/mne-python/source/doc/sphinxext/prs/8212.json new file mode 100644 index 0000000000000000000000000000000000000000..6c91c120c82d769ec1c843c021a8128be09ffa34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8212.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "039e712156066d5a4d2a10b5d8797f7b72614dce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/viz/raw.py": { + "a": 17, + "d": 7 + }, + "mne/viz/tests/test_raw.py": { + "a": 13, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 9, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8214.json b/mne-python/source/doc/sphinxext/prs/8214.json new file mode 100644 index 0000000000000000000000000000000000000000..3b4b2cde063342acb8da1b2571282b551104c536 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8214.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3d16144b9e8779abbfdb7b66192d5ab339601996", + "authors": [ + { + "n": "Jeroen Van Der Donckt", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/822.json b/mne-python/source/doc/sphinxext/prs/822.json new file mode 100644 index 0000000000000000000000000000000000000000..025a8e354aa8398f1b51ee87bf2560aadf1e4f78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/822.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "061f1b0bd69ac4306c0fbaace8af4c9b5e48f033", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 23, + "d": 38 + }, + "mne/fiff/raw.py": { + "a": 44, + "d": 1 + }, + "mne/tests/test_viz.py": { + "a": 15, + "d": 0 + }, + "mne/viz.py": { + "a": 114, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8220.json b/mne-python/source/doc/sphinxext/prs/8220.json new file mode 100644 index 0000000000000000000000000000000000000000..e5c74df34d584940b43d9cb20f285693c327adac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8220.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6c882c68f18ef7321c18372b1baf11007bf673ba", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_utils.py": { + "a": 5, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8223.json b/mne-python/source/doc/sphinxext/prs/8223.json new file mode 100644 index 0000000000000000000000000000000000000000..6377930d519c5c3032af9f3a373152554a9980f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8223.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "84517fd90a5e57f02cc84157b086562e074efa1f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_coreg.py": { + "a": 7, + "d": 4 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8224.json b/mne-python/source/doc/sphinxext/prs/8224.json new file mode 100644 index 0000000000000000000000000000000000000000..6ca0d199ffcd90a925864a9e018e9daf2e34277c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8224.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "2a423f9aa7613e0809bbe2bafcd7469d313234bb", + "authors": [ + { + "n": "Nikolai M Chapochnikov", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/time_frequency/_stockwell.py": { + "a": 17, + "d": 19 + }, + "mne/time_frequency/multitaper.py": { + "a": 4, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 14, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8225.json b/mne-python/source/doc/sphinxext/prs/8225.json new file mode 100644 index 0000000000000000000000000000000000000000..4223c85f015596b51fe58e4a566bbc513cbf2e86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8225.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b90ca523cef1b3260b4a3d69db4b7871b64d11e5", + "authors": [ + { + "n": "Steven Bierer", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 28, + "d": 28 + }, + "mne/tests/test_chpi.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8227.json b/mne-python/source/doc/sphinxext/prs/8227.json new file mode 100644 index 0000000000000000000000000000000000000000..b6fc3cdfed658a0a82f15637e712548408fa2170 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8227.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ce24bdca2ed34aee6a123e572769913032921cd9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/glossary.rst": { + "a": 11, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/plot_whitened.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8228.json b/mne-python/source/doc/sphinxext/prs/8228.json new file mode 100644 index 0000000000000000000000000000000000000000..5efaf94a4dce8a5ef89d8d9f518faacc5cc08b05 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8228.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d87f7f715900c149517153a05cf664af2442c20e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 27, + "d": 4 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 34, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8229.json b/mne-python/source/doc/sphinxext/prs/8229.json new file mode 100644 index 0000000000000000000000000000000000000000..29715bc84ca8499bb9a460504b4a485c01daf2a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8229.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "9bb050bdf61a4a3c7f4d6514323fa4a638ef6874", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.18.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.20.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/flat.py": { + "a": 61, + "d": 11 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 22, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/823.json b/mne-python/source/doc/sphinxext/prs/823.json new file mode 100644 index 0000000000000000000000000000000000000000..8cc7b3cdce0c397ef96bc6b1d0bbac2ff49eb6ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/823.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0ae7b614db435a4e8643e7d082024b1a5b935a58", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_csp.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8230.json b/mne-python/source/doc/sphinxext/prs/8230.json new file mode 100644 index 0000000000000000000000000000000000000000..df2ac694ff7a1e059de0b8f7ccf71e4e7b602671 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8230.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bbe61820638c347f86982e56717be8d224e6c8aa", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 0, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8234.json b/mne-python/source/doc/sphinxext/prs/8234.json new file mode 100644 index 0000000000000000000000000000000000000000..99f2190eaf8c010b81f1f613c91570d7f0b6b994 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8234.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bd1d12255deaa5b4b064aba9b7af428d27258e8a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 2, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 70, + "d": 6 + }, + "mne/utils/tests/test_logging.py": { + "a": 29, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8235.json b/mne-python/source/doc/sphinxext/prs/8235.json new file mode 100644 index 0000000000000000000000000000000000000000..69cf8b0cdefd2e7baf8f602c34f42b8f4674c289 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8235.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "821f186c3bdf58e0d2b71c4d6653b39fa390e0a6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_notebook.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8239.json b/mne-python/source/doc/sphinxext/prs/8239.json new file mode 100644 index 0000000000000000000000000000000000000000..4d668b9bc86847c4472302ac7c89320805f0f2ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8239.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b3e28c12f812eb81bd9ef453dc368c40bc504717", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/824.json b/mne-python/source/doc/sphinxext/prs/824.json new file mode 100644 index 0000000000000000000000000000000000000000..1061d503502b96baf36f382d1a49d970ed5db7ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/824.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b732c2c42cfb03978b7eee9810492742309ebac3", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/getting_started.rst": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8240.json b/mne-python/source/doc/sphinxext/prs/8240.json new file mode 100644 index 0000000000000000000000000000000000000000..7851e1f8fcc786aea4f7693501c4d7a403c772f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8240.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e63190c3b63ed080d7e7442405277515823d9d18", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".coveragerc": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 39, + "d": 0 + }, + "requirements_testing.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8243.json b/mne-python/source/doc/sphinxext/prs/8243.json new file mode 100644 index 0000000000000000000000000000000000000000..beb4c9a9c2c8e4b88319842444b4f603db0fe613 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8243.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "0bfa27fc31ec614b2046122ec4ded77b377006e3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/layout.py": { + "a": 2, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 12, + "d": 11 + }, + "mne/channels/tests/test_montage.py": { + "a": 18, + "d": 2 + }, + "mne/coreg.py": { + "a": 2, + "d": 1 + }, + "mne/io/_digitization.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 0 + }, + "tutorials/misc/plot_ecog.py": { + "a": 22, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8244.json b/mne-python/source/doc/sphinxext/prs/8244.json new file mode 100644 index 0000000000000000000000000000000000000000..2f41da24d7fb25704a6030c16fca8f05308d0b50 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8244.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2806dd8f7bfba7302568466cc35a83ebb8018804", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_includes/forward.rst": { + "a": 2, + "d": 2 + }, + "doc/install/mne_c.rst": { + "a": 1, + "d": 1 + }, + "doc/overview/faq.rst": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8245.json b/mne-python/source/doc/sphinxext/prs/8245.json new file mode 100644 index 0000000000000000000000000000000000000000..aae93bd038731119a61ffce320131fe8ac0aca54 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8245.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "132c05128be3b94a2d1bccdbcc69f8456166ae82", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/defaults.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 29, + "d": 3 + }, + "mne/viz/_brain/view.py": { + "a": 2, + "d": 4 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 2 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8246.json b/mne-python/source/doc/sphinxext/prs/8246.json new file mode 100644 index 0000000000000000000000000000000000000000..46433b7fd7fc5c9773e92c1c19afd57c41acd733 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8246.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ca3e787ca40059ee72b93e517adbe7506688c2a3", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 8, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8248.json b/mne-python/source/doc/sphinxext/prs/8248.json new file mode 100644 index 0000000000000000000000000000000000000000..2d9843a7546b28817b79ac389d4db7e083470884 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8248.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "018320e72107c6cb6691772edc4f78b15cc73703", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 5, + "d": 97 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 115, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8252.json b/mne-python/source/doc/sphinxext/prs/8252.json new file mode 100644 index 0000000000000000000000000000000000000000..148938456161cb50caab7535968214631fc1e271 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8252.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e5a963411e48c717da98c51565a816395bdfb70d", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 35, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8253.json b/mne-python/source/doc/sphinxext/prs/8253.json new file mode 100644 index 0000000000000000000000000000000000000000..d55ea8df8ca6cf698af9f73a9bca47e4b4b10e41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8253.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f5080a8f6a2c0c3ffc1d2d36bebf34c630a6a5c7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/proj.py": { + "a": 31, + "d": 26 + }, + "mne/tests/test_proj.py": { + "a": 12, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8254.json b/mne-python/source/doc/sphinxext/prs/8254.json new file mode 100644 index 0000000000000000000000000000000000000000..dc3228ebb5d3286f1150d85f78e4fa2f6c772c29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8254.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "b911a769d098b17bf5d40c472a2bed16db8b371d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 2, + "d": 5 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 2 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 10, + "d": 5 + }, + "tutorials/source-modeling/plot_mne_solutions.py": { + "a": 3, + "d": 4 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8255.json b/mne-python/source/doc/sphinxext/prs/8255.json new file mode 100644 index 0000000000000000000000000000000000000000..bf7f549409972587a14c1a33e234fb8948962452 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8255.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d5ea2b00c45a780b985e7a600546a45201461d3d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 7, + "d": 3 + }, + "mne/time_frequency/tfr.py": { + "a": 7, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 11, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8256.json b/mne-python/source/doc/sphinxext/prs/8256.json new file mode 100644 index 0000000000000000000000000000000000000000..128e94396b856ce7633009a717de58e3cd7079eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8256.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "66314aca8df5e13deef848fd0aebea3c9c64c34d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/plot_opm_data.py": { + "a": 10, + "d": 4 + }, + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_multidict_reweighted_tfmxne.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_rap_music.py": { + "a": 2, + "d": 1 + }, + "examples/visualization/plot_make_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/826.json b/mne-python/source/doc/sphinxext/prs/826.json new file mode 100644 index 0000000000000000000000000000000000000000..fc59a6c2f476554b668bfacfe68ee224c826fee2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/826.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d54cf6cc3803a9996b087dd66186003e1765e4b8", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/realtime/stim_server_client.py": { + "a": 54, + "d": 27 + }, + "mne/realtime/tests/test_stim_client_server.py": { + "a": 25, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8260.json b/mne-python/source/doc/sphinxext/prs/8260.json new file mode 100644 index 0000000000000000000000000000000000000000..79fa65e89158bf53d4bd225a98eb9a9cf9c64524 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8260.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "0facbb48f719122acf215d27e7c703954a1c4ba9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_dics_source_power.py": { + "a": 12, + "d": 6 + }, + "examples/inverse/plot_source_space_snr.py": { + "a": 5, + "d": 18 + }, + "mne/fixes.py": { + "a": 19, + "d": 7 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 33, + "d": 22 + }, + "mne/minimum_norm/inverse.py": { + "a": 17, + "d": 23 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 28, + "d": 27 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 1, + "d": 0 + }, + "tutorials/source-modeling/plot_mne_solutions.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8261.json b/mne-python/source/doc/sphinxext/prs/8261.json new file mode 100644 index 0000000000000000000000000000000000000000..b41c9b1c7fc89f936e83d54c3067fa4f034d02b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8261.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "1c3a4288871ff87b69256f84e404adb11f3e6ca5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 0, + "d": 6 + }, + "mne/baseline.py": { + "a": 2, + "d": 41 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 3 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 2, + "d": 5 + }, + "mne/conftest.py": { + "a": 1, + "d": 2 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 55, + "d": 58 + }, + "mne/evoked.py": { + "a": 28, + "d": 165 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 2, + "d": 5 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 2, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 6 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 22 + }, + "mne/tests/test_evoked.py": { + "a": 3, + "d": 36 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 3 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 15, + "d": 44 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 2 + }, + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 0, + "d": 19 + }, + "tutorials/evoked/plot_20_visualize_evoked.py": { + "a": 2, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8262.json b/mne-python/source/doc/sphinxext/prs/8262.json new file mode 100644 index 0000000000000000000000000000000000000000..fcf5f111e1611c0b01ae7996f739117374fdf68b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8262.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "cb11a650a9836cf0b3193179851522d638ffa23a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/glossary.rst": { + "a": 5, + "d": 0 + }, + "mne/conftest.py": { + "a": 10, + "d": 9 + }, + "mne/minimum_norm/inverse.py": { + "a": 35, + "d": 11 + }, + "mne/source_estimate.py": { + "a": 16, + "d": 10 + }, + "mne/source_space.py": { + "a": 8, + "d": 3 + }, + "mne/tests/test_source_estimate.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 6, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8264.json b/mne-python/source/doc/sphinxext/prs/8264.json new file mode 100644 index 0000000000000000000000000000000000000000..1612523d224082a83a32fd8b87dc6e27e92ec778 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8264.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b96a760bc133f31715fa383b0a5b5999ae9aa564", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 24, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8265.json b/mne-python/source/doc/sphinxext/prs/8265.json new file mode 100644 index 0000000000000000000000000000000000000000..6acd849bd3ed0e319e081400a06d93508d71f116 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8265.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "724f9ae3e9bbf36eec60bca71ccbb26f20961f37", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 3, + "d": 0 + }, + "doc/carousel.inc": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_vector_mne_solution.py": { + "a": 6, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 4, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 31, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 171, + "d": 88 + }, + "mne/viz/_brain/_scraper.py": { + "a": 68, + "d": 43 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 23, + "d": 10 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 8 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 5, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8266.json b/mne-python/source/doc/sphinxext/prs/8266.json new file mode 100644 index 0000000000000000000000000000000000000000..6b5c8c31f00e3470789676b03e991edad6ea3218 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8266.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "8c1c30b7a5140f4a2cfaf1a2348cd04649aa1d68", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".gitignore": { + "a": 1, + "d": 0 + }, + "doc/carousel.inc": { + "a": 1, + "d": 1 + }, + "examples/forward/plot_left_cerebellum_volume_source.py": { + "a": 14, + "d": 17 + }, + "examples/inverse/plot_covariance_whitening_dspm.py": { + "a": 3, + "d": 0 + }, + "examples/inverse/plot_custom_inverse_solver.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_multidict_reweighted_tfmxne.py": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_rap_music.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_vector_mne_solution.py": { + "a": 3, + "d": 0 + }, + "examples/visualization/montage.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_make_report.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 7, + "d": 3 + }, + "tutorials/intro/plot_40_sensor_locations.py": { + "a": 1, + "d": 2 + }, + "tutorials/misc/plot_report.py": { + "a": 10, + "d": 10 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 2, + "d": 2 + }, + "tutorials/source-modeling/plot_compute_covariance.py": { + "a": 2, + "d": 1 + }, + "tutorials/source-modeling/plot_dipole_fit.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_forward.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 24, + "d": 49 + }, + "tutorials/source-modeling/plot_mne_solutions.py": { + "a": 2, + "d": 2 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 2, + "d": 4 + }, + "tutorials/stats-source-space/plot_stats_cluster_time_frequency_repeated_measures_anova.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8268.json b/mne-python/source/doc/sphinxext/prs/8268.json new file mode 100644 index 0000000000000000000000000000000000000000..844fcb4331b2ea68e1021d6e9a37fdf368ae61e4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8268.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "eec85d4b864bb18fa0a5fa5b36a13b722d383bc8", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/references.bib": { + "a": 9, + "d": 0 + }, + "examples/inverse/plot_mne_cov_power.py": { + "a": 8, + "d": 1 + }, + "mne/cov.py": { + "a": 11, + "d": 22 + }, + "mne/minimum_norm/inverse.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8269.json b/mne-python/source/doc/sphinxext/prs/8269.json new file mode 100644 index 0000000000000000000000000000000000000000..b1cfef7036c0b25c7435dee32f31642255c62c65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8269.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7a713186f216b1e80c3c01b15c6d47eb5af4daff", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/ci.yml": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 49, + "d": 36 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8275.json b/mne-python/source/doc/sphinxext/prs/8275.json new file mode 100644 index 0000000000000000000000000000000000000000..26e1e114fddbb0dd5973c6ab4ec8dc0f51b20ad1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8275.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "edb868390d0e2aadc66dc837a6eca109026fac81", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_psf_ctf_label_leakage.py": { + "a": 187, + "d": 0 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 182, + "d": 43 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 62, + "d": 19 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 1, + "d": 11 + }, + "mne/utils/docs.py": { + "a": 61, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8276.json b/mne-python/source/doc/sphinxext/prs/8276.json new file mode 100644 index 0000000000000000000000000000000000000000..07e1abf0df062a29e4a95d80226ed87acdd83913 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8276.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3ea9a661c1a33a7dbd2f029a529ba1a22817e46d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 3, + "d": 3 + }, + "mne/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 23, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8278.json b/mne-python/source/doc/sphinxext/prs/8278.json new file mode 100644 index 0000000000000000000000000000000000000000..6c05a1a30c99111ddf8a2a409136cfe68c66019a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8278.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e50d215454c88727007db2f5598c355e5c775a8a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 0, + "d": 9 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8279.json b/mne-python/source/doc/sphinxext/prs/8279.json new file mode 100644 index 0000000000000000000000000000000000000000..4ed6e75ae0902b4716f0ce14f1fb63daa56f15c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8279.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "678b5cb72e319cfb17d6d58ab01d2f0e72fda896", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 14, + "d": 1 + }, + "mne/utils/tests/test_config.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8282.json b/mne-python/source/doc/sphinxext/prs/8282.json new file mode 100644 index 0000000000000000000000000000000000000000..fcb5b7168dd6f818e1754ce1246739fd8eb0e07e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8282.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d056af3d463edb2beb237a563a14a60af35c53a7", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 3 + }, + ".mailmap": { + "a": 2, + "d": 0 + }, + "doc/_templates/navbar.html": { + "a": 2, + "d": 1 + }, + "doc/changes/0.21.inc": { + "a": 54, + "d": 3 + }, + "doc/cited.rst": { + "a": 2, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 1 + }, + "mne/_version.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8283.json b/mne-python/source/doc/sphinxext/prs/8283.json new file mode 100644 index 0000000000000000000000000000000000000000..c8b9459d0e3f6e7ff8b66b5bc82e85140964f02d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8283.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e6a22e8950a4aa665eee4450170d94f02013b4d7", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 1 + }, + "doc/sphinxext/gh_substitutions.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 7, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 25, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8285.json b/mne-python/source/doc/sphinxext/prs/8285.json new file mode 100644 index 0000000000000000000000000000000000000000..7cbcc9b8f02e777ef48d86f4f4be7eb8cfe079af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8285.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f81fbe4c9118f6633f80a15fdd8e2a490a9c46d7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8286.json b/mne-python/source/doc/sphinxext/prs/8286.json new file mode 100644 index 0000000000000000000000000000000000000000..0360ed865cf64b80ba207cfaf62c8e3c0286a499 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8286.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a95ecdcb57172d284c5d7c4c1b672254d18903b3", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/0.21.inc": { + "a": 12, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8287.json b/mne-python/source/doc/sphinxext/prs/8287.json new file mode 100644 index 0000000000000000000000000000000000000000..bc7ae2fce7d195b9527b6bcde6dfbeb8021cf141 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8287.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cffdc0843428b9841bd493a961e795e570e58549", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 27, + "d": 4 + }, + "doc/index.rst": { + "a": 62, + "d": 27 + }, + "doc/overview/index.rst": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8288.json b/mne-python/source/doc/sphinxext/prs/8288.json new file mode 100644 index 0000000000000000000000000000000000000000..8c6e86f961754e624be2eda76dfc2b2ea0f58588 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8288.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fa168dccc221b12ad91d919c5d2b1afc9465a7ba", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/machine-learning/plot_sensors_decoding.py": { + "a": 17, + "d": 35 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8297.json b/mne-python/source/doc/sphinxext/prs/8297.json new file mode 100644 index 0000000000000000000000000000000000000000..cec917a766609fd7b6e5ee409175c6a200a3dbe2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8297.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5227c19a5f88835659785226148fbeb8c64f43bf", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "setup.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8298.json b/mne-python/source/doc/sphinxext/prs/8298.json new file mode 100644 index 0000000000000000000000000000000000000000..1fb39d0a1b64966a1fa1b86bfee5f034d37f0152 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8298.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "14bbb047ab2f188c5916397bf1ed4752c8d0b160", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8299.json b/mne-python/source/doc/sphinxext/prs/8299.json new file mode 100644 index 0000000000000000000000000000000000000000..126f05d3aa86a5027831c4ea9752077d1f710215 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8299.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9e8943b629a6edd1e947ce0838cd055597c3e4af", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "setup.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/83.json b/mne-python/source/doc/sphinxext/prs/83.json new file mode 100644 index 0000000000000000000000000000000000000000..214e695d560256daf6ed25d6da5abd46a2702e6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/83.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0141232b6509ac733de1f337a13ed9749229005c", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/simulation/tests/test_evoked.py": { + "a": 70, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/830.json b/mne-python/source/doc/sphinxext/prs/830.json new file mode 100644 index 0000000000000000000000000000000000000000..a4d1a5e5a7c815eb932f2e854d6caf0f9190e985 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/830.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1a806b0d7882581a0709e538502e9f52da020a36", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "bin/mne_make_scalp_surfaces.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8301.json b/mne-python/source/doc/sphinxext/prs/8301.json new file mode 100644 index 0000000000000000000000000000000000000000..7fbffa649d51d9af7ca915f5bc5888b1d613fc55 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8301.json @@ -0,0 +1,167 @@ +{ + "merge_commit_sha": "ecf639298f7bc9b9e9406a712eb852cb95586c74", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.15.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.19.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.20.inc": { + "a": 2, + "d": 2 + }, + "doc/python_reference.rst": { + "a": 0, + "d": 1 + }, + "mne/__init__.py": { + "a": 0, + "d": 17 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 3, + "d": 12 + }, + "mne/beamformer/_lcmv.py": { + "a": 2, + "d": 293 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 174 + }, + "mne/bem.py": { + "a": 7, + "d": 17 + }, + "mne/channels/__init__.py": { + "a": 0, + "d": 5 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 31 + }, + "mne/channels/tests/test_montage.py": { + "a": 0, + "d": 9 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/filter.py": { + "a": 1, + "d": 4 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 8 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 2 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 3, + "d": 5 + }, + "mne/io/pick.py": { + "a": 5, + "d": 34 + }, + "mne/io/tests/test_pick.py": { + "a": 6, + "d": 6 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/flat.py": { + "a": 1, + "d": 50 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 16 + }, + "mne/preprocessing/tests/test_beer_lambert_law.py": { + "a": 0, + "d": 6 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 1, + "d": 6 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 3 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 105 + }, + "mne/source_space.py": { + "a": 1, + "d": 6 + }, + "mne/stats/cluster_level.py": { + "a": 6, + "d": 33 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 0, + "d": 5 + }, + "mne/tests/test_bem.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 6, + "d": 10 + }, + "mne/tests/test_source_estimate.py": { + "a": 0, + "d": 5 + }, + "mne/utils/check.py": { + "a": 0, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 6 + }, + "mne/viz/tests/test_epochs.py": { + "a": 0, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 6, + "d": 30 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8303.json b/mne-python/source/doc/sphinxext/prs/8303.json new file mode 100644 index 0000000000000000000000000000000000000000..7002cca08e0caf479018465b93f5789a22127b9b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8303.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7c1233ba612bdb08d640c924ef4220b2fe13fb71", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/reference.py": { + "a": 4, + "d": 5 + }, + "mne/io/tests/test_reference.py": { + "a": 30, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8306.json b/mne-python/source/doc/sphinxext/prs/8306.json new file mode 100644 index 0000000000000000000000000000000000000000..26cf127c1dc0706ed6d38053116089202f9b63ed --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8306.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b2d759a8231003b0555283617f6d319e0657089e", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8310.json b/mne-python/source/doc/sphinxext/prs/8310.json new file mode 100644 index 0000000000000000000000000000000000000000..2f0891e9b8dffa888d17ac7efbc20b5575498f22 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8310.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c7f9773ccab6fcf8f5fe38334a99aa1c6a43d97b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 28 + }, + "mne/utils/docs.py": { + "a": 35, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8314.json b/mne-python/source/doc/sphinxext/prs/8314.json new file mode 100644 index 0000000000000000000000000000000000000000..b6419da6ac099bf5849e9e0e5b2c47ab8c065aa2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8314.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "695ab958376a3e284f6ecbf76555a3db59276f6a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 65, + "d": 61 + }, + "mne/viz/_brain/_scraper.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 12, + "d": 12 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8317.json b/mne-python/source/doc/sphinxext/prs/8317.json new file mode 100644 index 0000000000000000000000000000000000000000..5e53d737d5e2a3d7a91ad846dad8acda14d2ccb8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8317.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "82df946e29a8b66da0184d08b9a016ae6371545f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "examples/inverse/plot_dics_source_power.py": { + "a": 5, + "d": 5 + }, + "examples/inverse/plot_evoked_ers_source_power.py": { + "a": 4, + "d": 2 + }, + "examples/inverse/plot_multidict_reweighted_tfmxne.py": { + "a": 4, + "d": 14 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 6, + "d": 21 + }, + "tutorials/time-freq/plot_sensors_time_frequency.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8318.json b/mne-python/source/doc/sphinxext/prs/8318.json new file mode 100644 index 0000000000000000000000000000000000000000..33dac2f56a96493c5881ab928a90fc89daba6682 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8318.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5a04a45aca85d2ff32c3eb13c4eb4eff0a0181bf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 4, + "d": 2 + }, + "mne/io/tests/test_compensator.py": { + "a": 18, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/832.json b/mne-python/source/doc/sphinxext/prs/832.json new file mode 100644 index 0000000000000000000000000000000000000000..040a153235bff3d2de05a32b4b7a78f4adc3c24b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/832.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "1e2d0be9595a9d6f1f823d4d8bbec61ef9052b23", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/edf/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/fiff/edf/edf.py": { + "a": 509, + "d": 0 + }, + "mne/fiff/edf/tests/data/biosemi.hpts": { + "a": 82, + "d": 0 + }, + "mne/fiff/edf/tests/data/test.bdf": { + "a": 3222, + "d": 0 + }, + "mne/fiff/edf/tests/data/test.edf": { + "a": 9591, + "d": 0 + }, + "mne/fiff/edf/tests/data/test_bdf_eeglab.mat": { + "a": 0, + "d": 0 + }, + "mne/fiff/edf/tests/data/test_edf_eeglab.mat": { + "a": 0, + "d": 0 + }, + "mne/fiff/edf/tests/data/test_eeglab.mat": { + "a": 0, + "d": 0 + }, + "mne/fiff/edf/tests/test_edf.py": { + "a": 88, + "d": 0 + }, + "mne/fiff/meas_info.py": { + "a": 1, + "d": 1 + }, + "setup.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8320.json b/mne-python/source/doc/sphinxext/prs/8320.json new file mode 100644 index 0000000000000000000000000000000000000000..47e78a35beba6000d93ff3cd2d50ee532007bb98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8320.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "ff8ee2bbdd9d6b5f542b04e2dce76c31af46a2d3", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8321.json b/mne-python/source/doc/sphinxext/prs/8321.json new file mode 100644 index 0000000000000000000000000000000000000000..91272a3a4a2dcf2147e0e0382aa2f7d3771e017b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8321.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4270859dc3ba2208bb3eed4f73403b5de26125b8", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 7, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 104, + "d": 30 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 62, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8323.json b/mne-python/source/doc/sphinxext/prs/8323.json new file mode 100644 index 0000000000000000000000000000000000000000..ee2cd2737b217648e3e48ed525a4ca6fb1d4b8d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8323.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5fb608a82d5c82ced7fc66abc7781a9162d9b8ac", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "examples/decoding/plot_receptive_field_mtrf.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 20, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8326.json b/mne-python/source/doc/sphinxext/prs/8326.json new file mode 100644 index 0000000000000000000000000000000000000000..a2372ed2de73aad3c5958fbf52e1cfbc93edcdd0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8326.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "47ce37e3cacd63fed04ca4e078dba60f0330f161", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/glossary.rst": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 98, + "d": 84 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 125, + "d": 63 + }, + "mne/utils/tests/test_numerics.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8329.json b/mne-python/source/doc/sphinxext/prs/8329.json new file mode 100644 index 0000000000000000000000000000000000000000..bd0a7b76d3fa688c6e14e655e8c389f2fd05b503 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8329.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4483677c5d203897ad343754d8fa6701591d3bae", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 23, + "d": 19 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/833.json b/mne-python/source/doc/sphinxext/prs/833.json new file mode 100644 index 0000000000000000000000000000000000000000..079e892c7f1d2964659d9651a316f67a02647ad5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/833.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "48477b4803e1f4d1059bd480fe00f0c6dfddaeee", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/datasets/sample/sample.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8330.json b/mne-python/source/doc/sphinxext/prs/8330.json new file mode 100644 index 0000000000000000000000000000000000000000..cd1a9fbfc17c0320f97bd2e08c6ffb414c849b24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8330.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "74f6f41f827df552d258c4db4d4c99a5b71863d6", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + } + ], + "changes": { + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8331.json b/mne-python/source/doc/sphinxext/prs/8331.json new file mode 100644 index 0000000000000000000000000000000000000000..57022e065058f025fec3351fccae3cc27ae5b7c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8331.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "145a2b6eb60d5700d3cdc427e73bcd0eaa2212d4", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8333.json b/mne-python/source/doc/sphinxext/prs/8333.json new file mode 100644 index 0000000000000000000000000000000000000000..f49fec012f841f7998f1ff3802bb4f8f06217fd6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8333.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "3d8816c0571050aacee8dcb26ebad65a85f590dd", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 5, + "d": 6 + }, + "mne/decoding/time_frequency.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/xdawn.py": { + "a": 3, + "d": 3 + }, + "mne/utils/check.py": { + "a": 10, + "d": 4 + }, + "mne/utils/tests/test_check.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 10, + "d": 10 + }, + "mne/viz/_brain/surface.py": { + "a": 1, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8335.json b/mne-python/source/doc/sphinxext/prs/8335.json new file mode 100644 index 0000000000000000000000000000000000000000..dc2f59d95f0343158c1a342887d501ae66707e7d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8335.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "957556e19be1c5ee899b30065816a8e9dbe79f6c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 33, + "d": 18 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 291, + "d": 96 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 8, + "d": 8 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 118, + "d": 16 + }, + "mne/viz/backends/renderer.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/834.json b/mne-python/source/doc/sphinxext/prs/834.json new file mode 100644 index 0000000000000000000000000000000000000000..97263e99f63f5f9dadd0b51b7df93acdd0842c48 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/834.json @@ -0,0 +1,291 @@ +{ + "merge_commit_sha": "317ebed92115799af5af8dfdd5516a5c14ac5329", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "bin/mne_browse_raw.py": { + "a": 6, + "d": 6 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 4, + "d": 4 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 3, + "d": 3 + }, + "examples/decoding/plot_decoding_sensors.py": { + "a": 12, + "d": 12 + }, + "examples/export/plot_epochs_as_data_frame.py": { + "a": 3, + "d": 3 + }, + "examples/export/plot_epochs_to_nitime.py": { + "a": 2, + "d": 2 + }, + "examples/export/plot_evoked_to_nitime.py": { + "a": 2, + "d": 2 + }, + "examples/export/plot_raw_to_nitime.py": { + "a": 7, + "d": 7 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 5, + "d": 5 + }, + "examples/inverse/plot_compute_mne_inverse_epochs_in_label.py": { + "a": 10, + "d": 10 + }, + "examples/inverse/plot_compute_mne_inverse_raw_in_label.py": { + "a": 5, + "d": 5 + }, + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 10, + "d": 11 + }, + "examples/inverse/plot_dics_beamformer.py": { + "a": 8, + "d": 8 + }, + "examples/inverse/plot_gamma_map_inverse.py": { + "a": 5, + "d": 4 + }, + "examples/inverse/plot_label_activation_from_stc.py": { + "a": 12, + "d": 12 + }, + "examples/inverse/plot_label_from_stc.py": { + "a": 8, + "d": 8 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 12, + "d": 12 + }, + "examples/inverse/plot_lcmv_beamformer.py": { + "a": 10, + "d": 10 + }, + "examples/inverse/plot_lcmv_beamformer_volume.py": { + "a": 14, + "d": 14 + }, + "examples/inverse/plot_make_inverse_operator.py": { + "a": 15, + "d": 15 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 6, + "d": 6 + }, + "examples/inverse/plot_morph_data.py": { + "a": 8, + "d": 8 + }, + "examples/inverse/plot_read_stc.py": { + "a": 5, + "d": 5 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 7, + "d": 6 + }, + "examples/plot_channel_epochs_image.py": { + "a": 3, + "d": 3 + }, + "examples/plot_define_target_events.py": { + "a": 10, + "d": 10 + }, + "examples/plot_evoked_delayed_ssp.py": { + "a": 6, + "d": 6 + }, + "examples/plot_evoked_whitening.py": { + "a": 2, + "d": 2 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 7, + "d": 7 + }, + "examples/plot_from_raw_to_multiple_epochs_to_evoked.py": { + "a": 9, + "d": 9 + }, + "examples/plot_make_forward.py": { + "a": 12, + "d": 12 + }, + "examples/plot_megsim_data.py": { + "a": 3, + "d": 3 + }, + "examples/plot_megsim_data_single_trial.py": { + "a": 0, + "d": 1 + }, + "examples/plot_read_forward.py": { + "a": 12, + "d": 12 + }, + "examples/plot_read_noise_covariance_matrix.py": { + "a": 4, + "d": 4 + }, + "examples/plot_shift_evoked.py": { + "a": 2, + "d": 2 + }, + "examples/plot_simulate_evoked_data.py": { + "a": 5, + "d": 5 + }, + "examples/plot_ssp_projs_sensitivity_map.py": { + "a": 3, + "d": 3 + }, + "examples/plot_ssp_projs_topomaps.py": { + "a": 2, + "d": 2 + }, + "examples/plot_topo_channel_epochs_image.py": { + "a": 2, + "d": 2 + }, + "examples/plot_topo_compare_conditions.py": { + "a": 3, + "d": 3 + }, + "examples/plot_topography.py": { + "a": 2, + "d": 2 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 6, + "d": 6 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 5, + "d": 5 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 4, + "d": 4 + }, + "examples/preprocessing/plot_ica_from_raw.py": { + "a": 25, + "d": 25 + }, + "examples/realtime/plot_compute_rt_decoder.py": { + "a": 13, + "d": 13 + }, + "examples/realtime/rt_feedback_server.py": { + "a": 14, + "d": 13 + }, + "examples/stats/plot_cluster_1samp_test_time_frequency.py": { + "a": 24, + "d": 26 + }, + "examples/stats/plot_cluster_methods_tutorial.py": { + "a": 9, + "d": 9 + }, + "examples/stats/plot_cluster_stats_evoked.py": { + "a": 18, + "d": 17 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 14, + "d": 14 + }, + "examples/stats/plot_cluster_stats_time_frequency.py": { + "a": 22, + "d": 22 + }, + "examples/stats/plot_cluster_stats_time_frequency_repeated_measures_anova.py": { + "a": 34, + "d": 34 + }, + "examples/stats/plot_fdr_stats_evoked.py": { + "a": 14, + "d": 14 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 10, + "d": 10 + }, + "examples/time_frequency/plot_compute_source_psd_epochs.py": { + "a": 6, + "d": 6 + }, + "examples/time_frequency/plot_source_label_time_frequency.py": { + "a": 22, + "d": 22 + }, + "examples/time_frequency/plot_source_power_spectrum.py": { + "a": 6, + "d": 6 + }, + "examples/time_frequency/plot_source_space_time_frequency.py": { + "a": 8, + "d": 8 + }, + "examples/time_frequency/plot_temporal_whitening.py": { + "a": 13, + "d": 13 + }, + "examples/time_frequency/plot_tfr_topography.py": { + "a": 3, + "d": 3 + }, + "examples/time_frequency/plot_time_frequency.py": { + "a": 29, + "d": 29 + }, + "mne/fiff/evoked.py": { + "a": 18, + "d": 16 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 4, + "d": 4 + }, + "mne/viz.py": { + "a": 223, + "d": 216 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8340.json b/mne-python/source/doc/sphinxext/prs/8340.json new file mode 100644 index 0000000000000000000000000000000000000000..dc957d3447df870c6100b705817af4cbad34eada --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8340.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "629db04a49b5dec6aedad5a2857d3ea9781c1c2e", + "authors": [ + { + "n": "examplename", + "e": "e.ort@vu.nl" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 22, + "d": 1 + }, + "mne/io/open.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8341.json b/mne-python/source/doc/sphinxext/prs/8341.json new file mode 100644 index 0000000000000000000000000000000000000000..baef78d4dafe0ff4de56a5d593eafb605e3d213e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8341.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "666669ae2b2d5147d8cd58290e2b4d5de2f08ce0", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8343.json b/mne-python/source/doc/sphinxext/prs/8343.json new file mode 100644 index 0000000000000000000000000000000000000000..bcd336879e902531525fce2cdaa4da7f59e19ea5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8343.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "697f7e9a4730c2e7e1dc21e101cefb1e5da8c57f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 60, + "d": 48 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 86, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8344.json b/mne-python/source/doc/sphinxext/prs/8344.json new file mode 100644 index 0000000000000000000000000000000000000000..14bfcffb77ee5f62205ad41d64d254c334cd382d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8344.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ce4d514ad022c685084947c3e098cf5b16ba2821", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_evoked.py": { + "a": 13, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8345.json b/mne-python/source/doc/sphinxext/prs/8345.json new file mode 100644 index 0000000000000000000000000000000000000000..d1a8917465d5f2cde1e864fda622d62b8ec010dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8345.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ad43de7ce030189e6b595eb3c44c32b9ae9d4567", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/835.json b/mne-python/source/doc/sphinxext/prs/835.json new file mode 100644 index 0000000000000000000000000000000000000000..1f22e6671ed7b1395fee59c7ce6dd2b5eab4a7ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/835.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5dfeb56593d0103687efe354ae929fec25e46748", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 0 + }, + "mne/viz.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8350.json b/mne-python/source/doc/sphinxext/prs/8350.json new file mode 100644 index 0000000000000000000000000000000000000000..7a4936cdef8a08c674899eda8a2749178ffe34b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8350.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "09513aa1a7cf1c1d6fe3bc71ba5001cd8725a6e1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 28, + "d": 25 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 1 + }, + "mne/utils/tests/test_docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8351.json b/mne-python/source/doc/sphinxext/prs/8351.json new file mode 100644 index 0000000000000000000000000000000000000000..cdaa46794b3a247648c6f7f747b2da1666f0f74c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8351.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "91473147e57464173dedb00ce20f3d5aefd883bd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/_static/diagrams/ica.dot": { + "a": 9, + "d": 4 + }, + "doc/changes/latest.inc": { + "a": 8, + "d": 4 + }, + "mne/epochs.py": { + "a": 10, + "d": 35 + }, + "mne/preprocessing/ica.py": { + "a": 201, + "d": 193 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 114, + "d": 150 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 22, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 15, + "d": 9 + }, + "mne/viz/tests/test_ica.py": { + "a": 35, + "d": 39 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 22, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8352.json b/mne-python/source/doc/sphinxext/prs/8352.json new file mode 100644 index 0000000000000000000000000000000000000000..38b4b5bb53876c238ff94eed9fbbc4879cefc1c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8352.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "af671e78561d7eb9e05eb69170149142ae336855", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/icons/README.rst": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 8 + }, + "mne/viz/_brain/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 1134, + "d": 29 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 53, + "d": 57 + }, + "mne/viz/_brain/_notebook.py": { + "a": 5, + "d": 6 + }, + "mne/viz/_brain/_scraper.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_timeviewer.py": { + "a": 0, + "d": 1049 + }, + "mne/viz/_brain/mplcanvas.py": { + "a": 8, + "d": 8 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 48, + "d": 55 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8354.json b/mne-python/source/doc/sphinxext/prs/8354.json new file mode 100644 index 0000000000000000000000000000000000000000..0efb483c62766b2e73439984465ab36d89e90ba4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8354.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "734e6ace282f510e017bc67851142c02954be440", + "authors": [ + { + "n": "Evan Hathaway", + "e": null + }, + { + "n": "Justus Schwabedal", + "e": "jschwabedal@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/egimff.py": { + "a": 237, + "d": 34 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 82, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "server_environment.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8356.json b/mne-python/source/doc/sphinxext/prs/8356.json new file mode 100644 index 0000000000000000000000000000000000000000..807613986c7ba0004398a82074a2150a576c2289 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8356.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c2d9a3fab4de5cc9974cc4bc23ec84c0a3e5bfca", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 20, + "d": 25 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 98, + "d": 104 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 7, + "d": 11 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8357.json b/mne-python/source/doc/sphinxext/prs/8357.json new file mode 100644 index 0000000000000000000000000000000000000000..6cbbb5421fa2917628ad4f51a733365b92cf2eca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8357.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "c0388970e1d267713f5ead4e28c7ae297c8d36a1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "examplename", + "e": "e.ort@vu.nl" + }, + { + "n": "eort", + "e": "eduardxort@gmail.com" + }, + { + "n": "examplename", + "e": "e.ort@vu.nl" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/raw.py": { + "a": 23, + "d": 6 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 11, + "d": 6 + }, + "mne/utils/check.py": { + "a": 3, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 14, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8358.json b/mne-python/source/doc/sphinxext/prs/8358.json new file mode 100644 index 0000000000000000000000000000000000000000..6918af267c350d83127fa4f8e15ab9366d107b69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8358.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7781b9eb8604cc9e2c466a10e90ea83bf6202cd6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "SECURITY.md": { + "a": 30, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8359.json b/mne-python/source/doc/sphinxext/prs/8359.json new file mode 100644 index 0000000000000000000000000000000000000000..70cb1c35d3b5cce1075968bdc6b0175d4faa6553 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8359.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "b20e7964c12b5e8e34e4feba368a1a30d8f36903", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/references.bib": { + "a": 26, + "d": 0 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 7, + "d": 5 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 3, + "d": 7 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation_volume.py": { + "a": 3, + "d": 7 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 7, + "d": 7 + }, + "examples/datasets/plot_brainstorm_data.py": { + "a": 6, + "d": 8 + }, + "examples/datasets/plot_limo_data.py": { + "a": 12, + "d": 18 + }, + "examples/decoding/decoding_rsa.py": { + "a": 9, + "d": 18 + }, + "examples/decoding/plot_decoding_csp_eeg.py": { + "a": 9, + "d": 16 + }, + "examples/decoding/plot_decoding_spoc_CMC.py": { + "a": 7, + "d": 7 + }, + "examples/decoding/plot_decoding_time_generalization_conditions.py": { + "a": 7, + "d": 8 + }, + "examples/decoding/plot_decoding_xdawn_eeg.py": { + "a": 5, + "d": 12 + }, + "examples/decoding/plot_ems_filtering.py": { + "a": 6, + "d": 8 + }, + "mne/datasets/utils.py": { + "a": 4, + "d": 5 + }, + "mne/decoding/csp.py": { + "a": 3, + "d": 5 + }, + "mne/decoding/ems.py": { + "a": 6, + "d": 8 + }, + "mne/decoding/receptive_field.py": { + "a": 6, + "d": 25 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8361.json b/mne-python/source/doc/sphinxext/prs/8361.json new file mode 100644 index 0000000000000000000000000000000000000000..4b666b879a1aa62e48335f59afa42f2d45511f80 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8361.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3c8f49dd750c425d564d13e5481e1448233e2fcb", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 4, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8365.json b/mne-python/source/doc/sphinxext/prs/8365.json new file mode 100644 index 0000000000000000000000000000000000000000..d5e9e356cc08936f479d7e2ff87b8b10d3aa6581 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8365.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "6dff3f2102f5cc4c8b9cb35a64b0ead88b21ecac", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/blank.md": { + "a": 0, + "d": 5 + }, + ".github/ISSUE_TEMPLATE/bug_report.md": { + "a": 24, + "d": 16 + }, + ".github/ISSUE_TEMPLATE/config.yml": { + "a": 8, + "d": 0 + }, + ".github/ISSUE_TEMPLATE/documentation.md": { + "a": 15, + "d": 0 + }, + ".github/ISSUE_TEMPLATE/feature_request.md": { + "a": 16, + "d": 11 + }, + ".github/ISSUE_TEMPLATE/glossary.md": { + "a": 0, + "d": 13 + }, + ".github/ISSUE_TEMPLATE/question.md": { + "a": 19, + "d": 0 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "SECURITY.md": { + "a": 30, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8366.json b/mne-python/source/doc/sphinxext/prs/8366.json new file mode 100644 index 0000000000000000000000000000000000000000..28ba710adc2cbb1e1e81c8c89f36a56f48ff9241 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8366.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f2cdcc8a87a87a8c13fbb7f355660017a0ee56ee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_morph_volume_stc.py": { + "a": 15, + "d": 1 + }, + "mne/morph.py": { + "a": 171, + "d": 92 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_morph.py": { + "a": 118, + "d": 48 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8367.json b/mne-python/source/doc/sphinxext/prs/8367.json new file mode 100644 index 0000000000000000000000000000000000000000..2db79b5199bce5c5200bc19d4e40037e25ae4585 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8367.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6f16c3771d79dda19b5ff0a058396f468a3e57f6", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 4 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 11, + "d": 5 + }, + "mne/viz/backends/_pyvista.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8368.json b/mne-python/source/doc/sphinxext/prs/8368.json new file mode 100644 index 0000000000000000000000000000000000000000..22239dee643c688e12dd377eb962fab72749c4c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8368.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "092a1268ba0cff0b184797e6457dd14c5244a22b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/837.json b/mne-python/source/doc/sphinxext/prs/837.json new file mode 100644 index 0000000000000000000000000000000000000000..7e5b5fe9cc15b602fd17f6bcd75badaa78655ed3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/837.json @@ -0,0 +1,171 @@ +{ + "merge_commit_sha": "8bddf07d25443889c1864819e4e1c9d795d3b2c8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 2, + "d": 2 + }, + "examples/stats/plot_cluster_stats_spatio_temporal.py": { + "a": 4, + "d": 4 + }, + "examples/stats/plot_cluster_stats_spatio_temporal_repeated_measures_anova.py": { + "a": 4, + "d": 4 + }, + "mne/__init__.py": { + "a": 36, + "d": 36 + }, + "mne/connectivity/spectral.py": { + "a": 3, + "d": 3 + }, + "mne/datasets/megsim/megsim.py": { + "a": 2, + "d": 2 + }, + "mne/decoding/classifier.py": { + "a": 2, + "d": 2 + }, + "mne/epochs.py": { + "a": 7, + "d": 8 + }, + "mne/fiff/__init__.py": { + "a": 7, + "d": 7 + }, + "mne/fiff/bti/raw.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/bti/tests/test_bti.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/cov.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/evoked.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/matrix.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/fiff/proj.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 2, + "d": 2 + }, + "mne/fiff/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 14, + "d": 13 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/__init__.py": { + "a": 6, + "d": 6 + }, + "mne/minimum_norm/inverse.py": { + "a": 11, + "d": 11 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 6, + "d": 5 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 13, + "d": 13 + }, + "mne/stats/__init__.py": { + "a": 7, + "d": 7 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 7, + "d": 7 + }, + "mne/stats/tests/test_parametric.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_coreg.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_cov.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_filter.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_label.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_source_estimate.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_utils.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_viz.py": { + "a": 7, + "d": 7 + }, + "mne/time_frequency/csd.py": { + "a": 2, + "d": 2 + }, + "mne/viz.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8371.json b/mne-python/source/doc/sphinxext/prs/8371.json new file mode 100644 index 0000000000000000000000000000000000000000..080ccf8a3924a3adc7b079c6954fed79f17a8ee4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8371.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "59e6c546020d3ec6e123e46a72cbb803a33591f3", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8372.json b/mne-python/source/doc/sphinxext/prs/8372.json new file mode 100644 index 0000000000000000000000000000000000000000..a6a0038b88a9430fce5866e5cef1a682a62a773e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8372.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "56bf0c9c49cfeac1aec6f1a2782c919506c4346a", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/0.21.inc": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8373.json b/mne-python/source/doc/sphinxext/prs/8373.json new file mode 100644 index 0000000000000000000000000000000000000000..688847f5d681392bfbb8fee44dfa20feea68529a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8373.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "db510cc35604bd0d72cae6a1bb7d1d05eb18c0ac", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fixes.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8374.json b/mne-python/source/doc/sphinxext/prs/8374.json new file mode 100644 index 0000000000000000000000000000000000000000..e9a11ee5186b77f9642c4bd17d853fc58a2259c9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8374.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "864426c4839bab05fd0d142ee20938c336c0b78e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 2 + }, + "README.rst": { + "a": 6, + "d": 7 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 4, + "d": 19 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 5 + }, + "mne/decoding/tests/test_base.py": { + "a": 2, + "d": 5 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/fixes.py": { + "a": 3, + "d": 183 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 4, + "d": 9 + }, + "mne/time_frequency/multitaper.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 18, + "d": 15 + }, + "mne/viz/epochs.py": { + "a": 5, + "d": 11 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 4 + }, + "mne/viz/raw.py": { + "a": 0, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 0, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 4 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8377.json b/mne-python/source/doc/sphinxext/prs/8377.json new file mode 100644 index 0000000000000000000000000000000000000000..2ecfd4852ace413aac222a5dc89c083cdda1b1ba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8377.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6f2465dbe5e9baa53ffddb8503d673d4f995376d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 13, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8379.json b/mne-python/source/doc/sphinxext/prs/8379.json new file mode 100644 index 0000000000000000000000000000000000000000..a951e5ceef7c8feffe2fba71b5cb14b62120cddb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8379.json @@ -0,0 +1,187 @@ +{ + "merge_commit_sha": "06298716dc48db52f69496e4248927f90925ee65", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 19, + "d": 111 + }, + ".gitignore": { + "a": 2, + "d": 0 + }, + "doc/Makefile": { + "a": 17, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "doc/conf.py": { + "a": 23, + "d": 5 + }, + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 4, + "d": 4 + }, + "examples/decoding/plot_receptive_field_mtrf.py": { + "a": 0, + "d": 3 + }, + "examples/inverse/plot_evoked_ers_source_power.py": { + "a": 23, + "d": 10 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 14, + "d": 14 + }, + "examples/inverse/plot_psf_ctf_vertices.py": { + "a": 13, + "d": 9 + }, + "examples/inverse/plot_psf_ctf_vertices_lcmv.py": { + "a": 17, + "d": 14 + }, + "examples/inverse/plot_resolution_metrics.py": { + "a": 14, + "d": 4 + }, + "examples/inverse/plot_resolution_metrics_eegmeg.py": { + "a": 12, + "d": 2 + }, + "examples/inverse/plot_vector_mne_solution.py": { + "a": 4, + "d": 0 + }, + "examples/preprocessing/plot_find_ref_artifacts.py": { + "a": 7, + "d": 4 + }, + "examples/time_frequency/plot_source_power_spectrum_opm.py": { + "a": 28, + "d": 14 + }, + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 50, + "d": 22 + }, + "mne/conftest.py": { + "a": 34, + "d": 1 + }, + "mne/fixes.py": { + "a": 12, + "d": 3 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 14, + "d": 15 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 9, + "d": 20 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 48, + "d": 17 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 26, + "d": 0 + }, + "mne/utils/numerics.py": { + "a": 16, + "d": 6 + }, + "mne/utils/tests/test_numerics.py": { + "a": 15, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 71, + "d": 19 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 26, + "d": 8 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 9, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 1 + }, + "tools/circleci_download.sh": { + "a": 111, + "d": 0 + }, + "tutorials/misc/plot_ecog.py": { + "a": 8, + "d": 7 + }, + "tutorials/simulation/plot_dics.py": { + "a": 28, + "d": 26 + }, + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 18, + "d": 22 + }, + "tutorials/source-modeling/plot_eeg_mri_coords.py": { + "a": 4, + "d": 3 + }, + "tutorials/source-modeling/plot_eeg_no_mri.py": { + "a": 2, + "d": 2 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/838.json b/mne-python/source/doc/sphinxext/prs/838.json new file mode 100644 index 0000000000000000000000000000000000000000..c062e3b8bec792904aaead6ec773054398c0d71b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/838.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3438259e1bc336ec9be4db87ec046a45418b6e46", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fixes.py": { + "a": 14, + "d": 1 + }, + "mne/tests/test_viz.py": { + "a": 16, + "d": 1 + }, + "mne/viz.py": { + "a": 17, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8381.json b/mne-python/source/doc/sphinxext/prs/8381.json new file mode 100644 index 0000000000000000000000000000000000000000..3ced551bf85a794c81368e95a5a2be401f71f946 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8381.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "8cf161eee8c7e938eee2e1c16bc3fc9e9322d28d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 0 + }, + "mne/epochs.py": { + "a": 15, + "d": 5 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 20, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 23, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 440, + "d": 153 + }, + "mne/viz/epochs.py": { + "a": 164, + "d": 1214 + }, + "mne/viz/ica.py": { + "a": 172, + "d": 259 + }, + "mne/viz/raw.py": { + "a": 16, + "d": 339 + }, + "mne/viz/tests/test_epochs.py": { + "a": 116, + "d": 104 + }, + "mne/viz/tests/test_figure.py": { + "a": 12, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 41, + "d": 24 + }, + "mne/viz/tests/test_raw.py": { + "a": 42, + "d": 52 + }, + "mne/viz/tests/test_utils.py": { + "a": 23, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 44, + "d": 965 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 16, + "d": 9 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 27, + "d": 26 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 21, + "d": 21 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8384.json b/mne-python/source/doc/sphinxext/prs/8384.json new file mode 100644 index 0000000000000000000000000000000000000000..832491090c9f3918f7afea5fa925483f476fd841 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8384.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "108e165b600635ad1990d612c3503f5cc1001432", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 5, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8389.json b/mne-python/source/doc/sphinxext/prs/8389.json new file mode 100644 index 0000000000000000000000000000000000000000..57b0d9202427821c6bf17bf692db168ae5e042cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8389.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "59cfcd7a7ffb0740deecbcea587b3fc55c3c5e63", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 27, + "d": 15 + }, + "mne/tests/test_source_estimate.py": { + "a": 7, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/839.json b/mne-python/source/doc/sphinxext/prs/839.json new file mode 100644 index 0000000000000000000000000000000000000000..882053a51bd4ce856d37cb014ab2635537b7e8ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/839.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "2504fee2d311003a049acb636798f66c047fc2ce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 4, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 5, + "d": 5 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 4, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 13, + "d": 5 + }, + "mne/datasets/sample/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sample/sample.py": { + "a": 27, + "d": 1 + }, + "mne/forward/tests/test_forward.py": { + "a": 7, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 6, + "d": 3 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 39, + "d": 8 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 6, + "d": 3 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 3, + "d": 2 + }, + "mne/simulation/tests/test_source.py": { + "a": 17, + "d": 11 + }, + "mne/tests/test_dipole.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 11, + "d": 1 + }, + "mne/tests/test_proj.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 10, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 14, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_transforms.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_viz.py": { + "a": 64, + "d": 21 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 3, + "d": 1 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 4, + "d": 4 + }, + "mne/utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8390.json b/mne-python/source/doc/sphinxext/prs/8390.json new file mode 100644 index 0000000000000000000000000000000000000000..0dcb696c3d83ec379dc54f9d543d0ef55d536b27 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8390.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "6b7352f2f9e4c7d26e06d1977984392ea61896ac", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/references.bib": { + "a": 15, + "d": 3 + }, + "examples/inverse/plot_mixed_norm_inverse.py": { + "a": 3, + "d": 10 + }, + "examples/inverse/plot_morph_surface_stc.py": { + "a": 7, + "d": 8 + }, + "examples/inverse/plot_rap_music.py": { + "a": 6, + "d": 8 + }, + "examples/inverse/plot_resolution_metrics.py": { + "a": 5, + "d": 8 + }, + "examples/inverse/plot_resolution_metrics_eegmeg.py": { + "a": 6, + "d": 9 + }, + "examples/inverse/plot_source_space_snr.py": { + "a": 3, + "d": 6 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 7, + "d": 7 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 7, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8392.json b/mne-python/source/doc/sphinxext/prs/8392.json new file mode 100644 index 0000000000000000000000000000000000000000..4a46d674f72ce1f0e2f1222f16e34dec914c0646 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8392.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8fa5aa57947274a4bda7de3381ae898037aac504", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test.ipynb": { + "a": 27, + "d": 5 + }, + "mne/viz/backends/_notebook.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8393.json b/mne-python/source/doc/sphinxext/prs/8393.json new file mode 100644 index 0000000000000000000000000000000000000000..9be0fdd2d61e95e5b2b5c998190a620e65f8dfd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8393.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "641e9d161987de1e5ff270b1c9828f9990f2ba2b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 20, + "d": 13 + }, + "mne/viz/tests/test_3d.py": { + "a": 20, + "d": 51 + }, + "tutorials/misc/plot_ecog.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8395.json b/mne-python/source/doc/sphinxext/prs/8395.json new file mode 100644 index 0000000000000000000000000000000000000000..e9fff136ed119ccc007af3c151d9a224a746c7df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8395.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "71dd449e24824a7f855060f209d5ad25ac304069", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8396.json b/mne-python/source/doc/sphinxext/prs/8396.json new file mode 100644 index 0000000000000000000000000000000000000000..9689824715fd383608f4b8d8e4283023e0fc14ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8396.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "69340341e44decadb3b3df1a34f6b9489f54b797", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + } + ], + "changes": { + "mne/io/nihon/nihon.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/84.json b/mne-python/source/doc/sphinxext/prs/84.json new file mode 100644 index 0000000000000000000000000000000000000000..066d523f28423faa1f381a44686a1b80c6a76bc5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/84.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "67a72ea7856f05010201a1d9fa7d60793d4011a8", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 8, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/840.json b/mne-python/source/doc/sphinxext/prs/840.json new file mode 100644 index 0000000000000000000000000000000000000000..be13144eec90603f4b0fd20c5455e33904e50676 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/840.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "75cdcf3546bd084595c847a9f010e39d266a5e1c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 5, + "d": 2 + }, + "mne/fiff/tests/test_raw.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8400.json b/mne-python/source/doc/sphinxext/prs/8400.json new file mode 100644 index 0000000000000000000000000000000000000000..06aac175217431443842502a080a359e42f84204 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8400.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f4077c0582ed70520e51315a6f9bc025c3bc4cce", + "authors": [ + { + "n": "Tod Flak", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/curry/curry.py": { + "a": 67, + "d": 3 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 52, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8402.json b/mne-python/source/doc/sphinxext/prs/8402.json new file mode 100644 index 0000000000000000000000000000000000000000..02e905c1b21b12e3e3e4def8772e021fb65b5439 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8402.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "cdeb44348efb1f73f90619b4dd6365a64a06ad00", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/Makefile": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 100, + "d": 28 + }, + "mne/tests/test_source_estimate.py": { + "a": 33, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 2 + }, + "mne/viz/_brain/_scraper.py": { + "a": 1, + "d": 0 + }, + "tutorials/misc/plot_ecog.py": { + "a": 9, + "d": 0 + }, + "tutorials/misc/plot_seeg.py": { + "a": 163, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8404.json b/mne-python/source/doc/sphinxext/prs/8404.json new file mode 100644 index 0000000000000000000000000000000000000000..125550f32a8465ad211d7fd5d394262a8cd3a552 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8404.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "539d5c973fb01ced7cd0c8b26272bc49b3955a60", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/bem.py": { + "a": 15, + "d": 15 + }, + "mne/forward/_compute_forward.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8405.json b/mne-python/source/doc/sphinxext/prs/8405.json new file mode 100644 index 0000000000000000000000000000000000000000..583b5a64e6ff007bc7757ed661cd1a4b93cdc54e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8405.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2cc6d7e275a60ae27c377de9c09272db5705155d", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_3d_to_2d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8406.json b/mne-python/source/doc/sphinxext/prs/8406.json new file mode 100644 index 0000000000000000000000000000000000000000..6e8d2f26183a48b84a7100b56d8f565136d23e75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8406.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "529dd9ce448d2cbb2d987e4caa524c72cb2ab273", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/misc.py": { + "a": 5, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 15, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8408.json b/mne-python/source/doc/sphinxext/prs/8408.json new file mode 100644 index 0000000000000000000000000000000000000000..5ba17cea8d526d31c33f84c275fce44362f2ae1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8408.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "86db55a81fb7a0cb5e9d43ad63919c69af17b86a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8409.json b/mne-python/source/doc/sphinxext/prs/8409.json new file mode 100644 index 0000000000000000000000000000000000000000..cc043cfe99a6e5901d8e2d460dc19ee6c393275e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8409.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a60424def32dd7ae4f91a82df1be8ed656e84d55", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/841.json b/mne-python/source/doc/sphinxext/prs/841.json new file mode 100644 index 0000000000000000000000000000000000000000..c142b531f317fd069850844ba306239f7d15742f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/841.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cd4e480db06ed39bcfb125f037b3d3be9c13e333", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "mne/label.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8412.json b/mne-python/source/doc/sphinxext/prs/8412.json new file mode 100644 index 0000000000000000000000000000000000000000..1a83f8cc1938acaf85c1537a56e8f6bdc712b5c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8412.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0c8d48c1b0ac4b6d79643fed0b26b8db0b6ddc79", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8413.json b/mne-python/source/doc/sphinxext/prs/8413.json new file mode 100644 index 0000000000000000000000000000000000000000..1e2810a8a241cf52aac4b51e625129b2a719ca0e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8413.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d882353358ea174bf3c7da3bafc5cda229f2032d", + "authors": [ + { + "n": "Tod Flak", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8414.json b/mne-python/source/doc/sphinxext/prs/8414.json new file mode 100644 index 0000000000000000000000000000000000000000..e1f3263c0f4f6cb7c7dc02aff791ae0be6a0c275 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8414.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "5cb467c54c4f37935f1de86fad35e664aa9de2db", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 4, + "d": 11 + }, + "mne/source_space.py": { + "a": 30, + "d": 23 + }, + "mne/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_source_space.py": { + "a": 8, + "d": 9 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 4, + "d": 4 + }, + "tutorials/source-modeling/plot_background_freesurfer_mne.py": { + "a": 45, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8415.json b/mne-python/source/doc/sphinxext/prs/8415.json new file mode 100644 index 0000000000000000000000000000000000000000..c7a1172f36ed0783dcf55027bac812b091157f16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8415.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "21a3a08476c33ac90bf16437fd6bbbf35964fc8c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 19, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8416.json b/mne-python/source/doc/sphinxext/prs/8416.json new file mode 100644 index 0000000000000000000000000000000000000000..11d47c39238dd2bb8a5336b3efb3c032f80980cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8416.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "9ffaaf7fe60cd41061a1221ed080078281ec20cf", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_layout.py": { + "a": 2, + "d": 2 + }, + "mne/io/meas_info.py": { + "a": 22, + "d": 3 + }, + "mne/io/reference.py": { + "a": 4, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 10, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 8, + "d": 6 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8417.json b/mne-python/source/doc/sphinxext/prs/8417.json new file mode 100644 index 0000000000000000000000000000000000000000..3f7624a66c62115f101492289e5d1efbdba4d1da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8417.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "74041b7175828badd6fc2f2896bbad0c35f5401c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/0.21.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8418.json b/mne-python/source/doc/sphinxext/prs/8418.json new file mode 100644 index 0000000000000000000000000000000000000000..df039c40ebce74f69f0b9eecfb6243a0abc96490 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8418.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fae559c520cd010bde64f9d8c3b09d64d8d5bd45", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test.ipynb": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/842.json b/mne-python/source/doc/sphinxext/prs/842.json new file mode 100644 index 0000000000000000000000000000000000000000..40a95a841edbc8234733336ef27faf7fb9283a01 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/842.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "aef6c57aadb5baddcaf219901238f12bdaa611eb", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 107, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 52, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8420.json b/mne-python/source/doc/sphinxext/prs/8420.json new file mode 100644 index 0000000000000000000000000000000000000000..4fac6675584df323df16d286998fff8abd26a4be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8420.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d759c60d718811988998e9c1c24d5326f7da7a22", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/visualization/plot_publication_figure.py": { + "a": 127, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8422.json b/mne-python/source/doc/sphinxext/prs/8422.json new file mode 100644 index 0000000000000000000000000000000000000000..262a32459c399d06510f79f272cfa29f8ae51228 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8422.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "360e62d2d353fe158de758c1b8fbb5e44409a877", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 18, + "d": 0 + }, + "tutorials/intro/plot_20_events_from_raw.py": { + "a": 13, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8427.json b/mne-python/source/doc/sphinxext/prs/8427.json new file mode 100644 index 0000000000000000000000000000000000000000..b3d431513164325665718782614852c2ea2657b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8427.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "92bcf294ed543a2569ed1bbaae27a63d23050ee4", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 0 + }, + ".travis.yml": { + "a": 2, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 10, + "d": 4 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8431.json b/mne-python/source/doc/sphinxext/prs/8431.json new file mode 100644 index 0000000000000000000000000000000000000000..b8009a7546f2f16e0b4bfea0b0a4ced8adaacefd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8431.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "010d4c6363a36193d7fa2ddb2139a155e33f693c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 2, + "d": 1 + }, + "tutorials/intro/plot_20_events_from_raw.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8433.json b/mne-python/source/doc/sphinxext/prs/8433.json new file mode 100644 index 0000000000000000000000000000000000000000..91548409e9c97cddb2bd3e797040a03f161149d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8433.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3a7e354a2eb120274b475a30a391aabce9e4dcfc", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/0.21.inc": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8434.json b/mne-python/source/doc/sphinxext/prs/8434.json new file mode 100644 index 0000000000000000000000000000000000000000..8395ad86a39138d63d9ecb869b136bd5e1fbd559 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8434.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "87553ab47e6b0fb0a3be09ba5302029f549b3ee7", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 3 + }, + "mne/io/brainvision/tests/data/test.vhdr": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8435.json b/mne-python/source/doc/sphinxext/prs/8435.json new file mode 100644 index 0000000000000000000000000000000000000000..3385c75749fcb5b2cb716b82f87491bf5c57419b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8435.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cc9e53cb96ceea205a500273af0b427ebe54d67b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 6, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8437.json b/mne-python/source/doc/sphinxext/prs/8437.json new file mode 100644 index 0000000000000000000000000000000000000000..af9893e64604e66e0234a5cc7c11c26ba8f48418 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8437.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2690cc0a464a1a268d92e83d2cf314b2c21f1f03", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/0.21.inc": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 8, + "d": 3 + }, + "mne/io/brainvision/tests/data/test.vhdr": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8439.json b/mne-python/source/doc/sphinxext/prs/8439.json new file mode 100644 index 0000000000000000000000000000000000000000..4592a821a197558672f045764070f67a5a07c628 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8439.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ff5eaffe9c39ad6adc434a484b3c49df278f9390", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/844.json b/mne-python/source/doc/sphinxext/prs/844.json new file mode 100644 index 0000000000000000000000000000000000000000..75c09ada13c9e3d297eed9b3e3a8528a15a41cd0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/844.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "c02ca49596eed8144947074ce0e7ca47947c97ee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "bin/mne_compute_proj_ecg.py": { + "a": 76, + "d": 57 + }, + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "mne/fiff/constants.py": { + "a": 0, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 5, + "d": 1 + }, + "mne/filter.py": { + "a": 7, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 68, + "d": 40 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 3 + }, + "mne/preprocessing/ssp.py": { + "a": 31, + "d": 22 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 17, + "d": 16 + }, + "mne/proj.py": { + "a": 9, + "d": 8 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_proj.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8442.json b/mne-python/source/doc/sphinxext/prs/8442.json new file mode 100644 index 0000000000000000000000000000000000000000..6de91e6f4890b89cb41bc8df16947d4ef641a99f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8442.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "157a0409de8790a105b60266b8970496b21da895", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/style.css": { + "a": 4, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 50, + "d": 50 + }, + "doc/install/contributing.rst": { + "a": 70, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8444.json b/mne-python/source/doc/sphinxext/prs/8444.json new file mode 100644 index 0000000000000000000000000000000000000000..59eac2e8fd1aa1c55b4fce8118629b422e91eb8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8444.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1ba8cfe3a1a5dab21033fb44f762e9abe77fb3e0", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 2 + }, + "mne/epochs.py": { + "a": 124, + "d": 57 + }, + "mne/io/tests/test_pick.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 81, + "d": 15 + }, + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8446.json b/mne-python/source/doc/sphinxext/prs/8446.json new file mode 100644 index 0000000000000000000000000000000000000000..418a7a6d5710810fbe2077b29a4266f8bcdccbe2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8446.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "67d5013d513c48f71780fba340bd5a2bdce29158", + "authors": [ + { + "n": "Keith Doelling", + "e": "keith.doelling@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "examples/datasets/plot_opm_data.py": { + "a": 5, + "d": 4 + }, + "examples/preprocessing/plot_movement_detection.py": { + "a": 4, + "d": 6 + }, + "examples/visualization/plot_eeg_on_scalp.py": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 34, + "d": 5 + }, + "mne/viz/tests/test_3d.py": { + "a": 12, + "d": 2 + }, + "tutorials/intro/plot_40_sensor_locations.py": { + "a": 1, + "d": 2 + }, + "tutorials/misc/plot_seeg.py": { + "a": 2, + "d": 1 + }, + "tutorials/source-modeling/plot_eeg_no_mri.py": { + "a": 1, + "d": 2 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8447.json b/mne-python/source/doc/sphinxext/prs/8447.json new file mode 100644 index 0000000000000000000000000000000000000000..410bfb701d3d8de38ae57fff32ad5fe5280231fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8447.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "29a32f49b943616de4c72bf6a5e17fcad1ff8501", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 48, + "d": 11 + }, + "mne/morph.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 194, + "d": 3 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8448.json b/mne-python/source/doc/sphinxext/prs/8448.json new file mode 100644 index 0000000000000000000000000000000000000000..d4ec6cf807ede725c53fb67a5d2936e0d9f2f59d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8448.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "606163ef1372b4f96e1245eb3312a0f87f6e3f43", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 57, + "d": 24 + }, + "mne/io/base.py": { + "a": 5, + "d": 0 + }, + "mne/io/tests/test_write.py": { + "a": 21, + "d": 0 + }, + "mne/io/write.py": { + "a": 16, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 109, + "d": 31 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8449.json b/mne-python/source/doc/sphinxext/prs/8449.json new file mode 100644 index 0000000000000000000000000000000000000000..22af48a78c9e664e35540b19750cebf0167a864f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8449.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1922bbdc9b4008c5d14dbef69462f761214953f2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 66, + "d": 17 + }, + "mne/tests/test_epochs.py": { + "a": 53, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8450.json b/mne-python/source/doc/sphinxext/prs/8450.json new file mode 100644 index 0000000000000000000000000000000000000000..05f5003a3add963e25b45cdf5f89851ecc464b21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8450.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a96f65415a55f7f22da516a2bdf43e84b7c9510b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 3, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8452.json b/mne-python/source/doc/sphinxext/prs/8452.json new file mode 100644 index 0000000000000000000000000000000000000000..76ed69141b153188c18b99b9347063f24a60b97d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8452.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9e15df76f003677b8ddc9fdfa4be32c10f7620c3", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 24, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 29, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8454.json b/mne-python/source/doc/sphinxext/prs/8454.json new file mode 100644 index 0000000000000000000000000000000000000000..58c2e0e185ff6524e16da748dde8b8e469a0f13d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8454.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8d6905d35dbae5cc16769989bc666e01c4e289ef", + "authors": [ + { + "n": "Jussi Nurminen", + "e": "jnu@iki.fi" + } + ], + "changes": { + "examples/visualization/plot_topo_customized.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8458.json b/mne-python/source/doc/sphinxext/prs/8458.json new file mode 100644 index 0000000000000000000000000000000000000000..154c4000cabc078c4638d22dfed39b810cec437b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8458.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0e31cd647c6e273f96ed94749f2b9968748ced48", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/annotations.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8459.json b/mne-python/source/doc/sphinxext/prs/8459.json new file mode 100644 index 0000000000000000000000000000000000000000..a894ae80425b51afd6fafa7230346644a9ac706a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8459.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a738bab71c17fdb18621794bcf3aee84f9be8e32", + "authors": [ + { + "n": "Mads Jensen", + "e": null + } + ], + "changes": { + "tutorials/machine-learning/plot_sensors_decoding.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/846.json b/mne-python/source/doc/sphinxext/prs/846.json new file mode 100644 index 0000000000000000000000000000000000000000..0786a8d67a59b76b046f085fd39fe54d8049aaae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/846.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4361537350956926bc9c82568198c13ac1eb6def", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/tests/data/test-lh.label": { + "a": 101, + "d": 0 + }, + "mne/fiff/tests/data/test-rh.label": { + "a": 102, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 24, + "d": 15 + }, + "mne/tests/test_viz.py": { + "a": 4, + "d": 2 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 4, + "d": 6 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 3, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8460.json b/mne-python/source/doc/sphinxext/prs/8460.json new file mode 100644 index 0000000000000000000000000000000000000000..f69173c3d8c373dabf86e75ea9f75401d22118dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8460.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "844847cd70afa78e21b6262f940ee0f1aecdcf3e", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 45, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8462.json b/mne-python/source/doc/sphinxext/prs/8462.json new file mode 100644 index 0000000000000000000000000000000000000000..e8a73f36ed6b02fc5bb7112aa6dcce7687e09eaa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8462.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "111302b2bcc046556183485ef7342b0233f8d21e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 0 + }, + "mne/morph.py": { + "a": 66, + "d": 43 + }, + "mne/tests/test_morph.py": { + "a": 7, + "d": 13 + }, + "mne/tests/test_source_estimate.py": { + "a": 34, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8463.json b/mne-python/source/doc/sphinxext/prs/8463.json new file mode 100644 index 0000000000000000000000000000000000000000..ad27da0f16dd2398f797ee19cdb212d4c9c8a032 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8463.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9f393dead191f60504ab7a215ae74d1a8ca0d89e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 0, + "d": 1 + }, + "mne/label.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8464.json b/mne-python/source/doc/sphinxext/prs/8464.json new file mode 100644 index 0000000000000000000000000000000000000000..76a40dd207067306f58ee16902f3b431f5eca149 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8464.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6e3a560ba7d620acb0c7cac1a6eef74d93005708", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 30, + "d": 21 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 26, + "d": 5 + }, + "mne/preprocessing/stim.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8466.json b/mne-python/source/doc/sphinxext/prs/8466.json new file mode 100644 index 0000000000000000000000000000000000000000..13165912cda84759416dc54218de1d1e3f91a41c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8466.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9f73f5a3c857d21dc2fb6e8f14509f79d8126ad6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/visualization/plot_publication_figure.py": { + "a": 15, + "d": 28 + }, + "mne/viz/utils.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8467.json b/mne-python/source/doc/sphinxext/prs/8467.json new file mode 100644 index 0000000000000000000000000000000000000000..0bda1cfd39a801e728458ffb31e6bf65d789e147 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8467.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4bc95d273ab34df9b1d1b5ca3ba9d007f069317d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/morph.py": { + "a": 64, + "d": 144 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8468.json b/mne-python/source/doc/sphinxext/prs/8468.json new file mode 100644 index 0000000000000000000000000000000000000000..7698087baa70cbef2ca46fb67fdb566128650e56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8468.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "57248c9ad7b17e76cf3bcfe25e9b2ffc3cff38d6", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/inverse/plot_label_source_activations.py": { + "a": 1, + "d": 1 + }, + "tutorials/misc/plot_seeg.py": { + "a": 20, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8469.json b/mne-python/source/doc/sphinxext/prs/8469.json new file mode 100644 index 0000000000000000000000000000000000000000..aebb767fa928b975a401ec3ff09beab5247f9b39 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8469.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7a87d0c627c98c840cc86664355c9fbb38229e28", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/847.json b/mne-python/source/doc/sphinxext/prs/847.json new file mode 100644 index 0000000000000000000000000000000000000000..e6e48c09193695c8b7e338d3b4111164aa94cced --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/847.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "83d9e2aa2438fdc491d2b3493c9f08b497f6818c", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8471.json b/mne-python/source/doc/sphinxext/prs/8471.json new file mode 100644 index 0000000000000000000000000000000000000000..653ff089f516d008bf16283e3959f47004594e8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8471.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3930aec85edcb8a63a664f7658ddb33579a00f62", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8474.json b/mne-python/source/doc/sphinxext/prs/8474.json new file mode 100644 index 0000000000000000000000000000000000000000..33e9fb9eabc7d888caacac0e5cdbde2e93977b0e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8474.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8db510fd078bb58fae8cf0fa13aa5b7ed13c3d7e", + "authors": [ + { + "n": "Aniket Pradhan", + "e": "aniketpradhan1999@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 1 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8475.json b/mne-python/source/doc/sphinxext/prs/8475.json new file mode 100644 index 0000000000000000000000000000000000000000..049f81ac3a6d3f4d5b25a3cdb823384501dcdc3e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8475.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "dd1f8b7563ec962694aad301b580c4a63c3faace", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 9, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8477.json b/mne-python/source/doc/sphinxext/prs/8477.json new file mode 100644 index 0000000000000000000000000000000000000000..753ea19f2b879e4f2b8558a2489b58587e129940 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8477.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "a1a3e27b437c3eab6b029d89ea4b2b50464ef073", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 3, + "d": 3 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 2, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 2, + "d": 0 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 1, + "d": 0 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 5, + "d": 0 + }, + "mne/tests/test_source_space.py": { + "a": 3, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/conftest.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8478.json b/mne-python/source/doc/sphinxext/prs/8478.json new file mode 100644 index 0000000000000000000000000000000000000000..293a026c69e8a90bac8ba9005894e3e7005c53c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8478.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0e080a5a645b5934445ef4da6da744d7dfa7f68d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/base.py": { + "a": 42, + "d": 13 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 28, + "d": 5 + }, + "mne/io/utils.py": { + "a": 10, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/848.json b/mne-python/source/doc/sphinxext/prs/848.json new file mode 100644 index 0000000000000000000000000000000000000000..2c0e7857e52906b5786eba0e212e04ac78b921a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/848.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "89dc2f9b6fc69c0acc574a91081620c7a1abb13a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8482.json b/mne-python/source/doc/sphinxext/prs/8482.json new file mode 100644 index 0000000000000000000000000000000000000000..0649bddf7ff7f17121d610e1974072740a711956 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8482.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ef42e43c1583b1e50fbafaba65bcb1b9918abaf2", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/preprocessing/stim.py": { + "a": 8, + "d": 4 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 10, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8483.json b/mne-python/source/doc/sphinxext/prs/8483.json new file mode 100644 index 0000000000000000000000000000000000000000..75343ad10f9e172ae490aca5a037d3decbe366be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8483.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6ed368d4ac8b607dcc0dd7ceb86e4f9cca726332", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 23, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8484.json b/mne-python/source/doc/sphinxext/prs/8484.json new file mode 100644 index 0000000000000000000000000000000000000000..8b0b5a424d2561511b24310af2833bce8ff8baa6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8484.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2db6ffac6016346adb97eccd121bfcba482e0e2d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/io/reference.py": { + "a": 3, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 15, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8485.json b/mne-python/source/doc/sphinxext/prs/8485.json new file mode 100644 index 0000000000000000000000000000000000000000..acbd02cd96fae4ff4f5a0c3b50a891458b7720b7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8485.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0febcfa17efc651d9539fcc7be3498ab58d5b877", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8486.json b/mne-python/source/doc/sphinxext/prs/8486.json new file mode 100644 index 0000000000000000000000000000000000000000..504c86d29588a061ab053cfa556ebdde3aa4ba24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8486.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7cc7766df0d27208b9a345680206a1a84aa41e64", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 24, + "d": 0 + }, + "mne/tests/test_report.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8489.json b/mne-python/source/doc/sphinxext/prs/8489.json new file mode 100644 index 0000000000000000000000000000000000000000..ba512b7418f8f84f860c8e8405a12690142e996f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8489.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "3b909b7361f3f00f2b15b03e7057e59dc1027c44", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".github/workflows/ci.yml": { + "a": 0, + "d": 76 + }, + ".github/workflows/linux.yml": { + "a": 61, + "d": 0 + }, + ".github/workflows/macos.yml": { + "a": 56, + "d": 0 + }, + ".travis.yml": { + "a": 1, + "d": 11 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 2, + "d": 4 + }, + "tools/get_minimal_commands.sh": { + "a": 1, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 5, + "d": 0 + }, + "tools/github_actions_download.sh": { + "a": 3, + "d": 0 + }, + "tools/github_actions_infos.sh": { + "a": 4, + "d": 0 + }, + "tools/github_actions_install.sh": { + "a": 4, + "d": 0 + }, + "tools/github_actions_locale.sh": { + "a": 5, + "d": 0 + }, + "tools/github_actions_test.sh": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/849.json b/mne-python/source/doc/sphinxext/prs/849.json new file mode 100644 index 0000000000000000000000000000000000000000..1708a965fd991e81ce90752c9c70ace772ef0a63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/849.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d3c9079798dc9529462fe6f92b41e80bd92e5abc", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 4, + "d": 4 + }, + "Makefile": { + "a": 6, + "d": 0 + }, + "mne/parallel.py": { + "a": 11, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_viz.py": { + "a": 1, + "d": 0 + }, + "mne/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8490.json b/mne-python/source/doc/sphinxext/prs/8490.json new file mode 100644 index 0000000000000000000000000000000000000000..e2eea046ca0c77dfb5c72cbe9b956ceee3429d59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8490.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "28b36c06a744074b54993128fa1908ea10464ff2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 11, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8491.json b/mne-python/source/doc/sphinxext/prs/8491.json new file mode 100644 index 0000000000000000000000000000000000000000..e90de531d8f9d7e7ec5611e81d8e2a07d52adec3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8491.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b9a7fb7a5e1fdb823a10ead989b1bd74ed117154", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 0, + "d": 4 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8492.json b/mne-python/source/doc/sphinxext/prs/8492.json new file mode 100644 index 0000000000000000000000000000000000000000..a72a99419e51a02c4f745cab620688f9b762f4b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8492.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "bb16a3e6ea99024e468fa84c2ec55c344b47df7e", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 6, + "d": 1 + }, + "mne/io/brainvision/tests/data/test.vmrk": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 60, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8494.json b/mne-python/source/doc/sphinxext/prs/8494.json new file mode 100644 index 0000000000000000000000000000000000000000..ab30e1b7ab0fcf651a830bf90d4b0a84b1d14a29 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8494.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e70247800458ff0a36fbe90b134841087ce95c6e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8495.json b/mne-python/source/doc/sphinxext/prs/8495.json new file mode 100644 index 0000000000000000000000000000000000000000..5e888ee837a0c1db7005d07007696e8a74ccbb60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8495.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "dacca023885184a5063152de6cf6705ceb721c16", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".travis.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 3, + "d": 4 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 6 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 0 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8496.json b/mne-python/source/doc/sphinxext/prs/8496.json new file mode 100644 index 0000000000000000000000000000000000000000..5512db25a9e969d93d1ce8465512f0cec5ce1a69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8496.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "49bb34f993b93a9ca28dda26f7bc23cb3af2bcb5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.21.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_label_source_activations.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 9, + "d": 20 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 2, + "d": 7 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8498.json b/mne-python/source/doc/sphinxext/prs/8498.json new file mode 100644 index 0000000000000000000000000000000000000000..d270ba86d74509ad65a4428f4a9e4741f7f80253 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8498.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0ca1c5c8eb3a46b8a170ed21e8a98d2dfa533a04", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/overview/faq.rst": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/filter.py": { + "a": 3, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/85.json b/mne-python/source/doc/sphinxext/prs/85.json new file mode 100644 index 0000000000000000000000000000000000000000..a30817acb255d86ddef7baa7bef3dbd2abeac217 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/85.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a18146827bfe216375f4e48066d36004903183e4", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/constants.py": { + "a": 29, + "d": 30 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/850.json b/mne-python/source/doc/sphinxext/prs/850.json new file mode 100644 index 0000000000000000000000000000000000000000..461c5a35cf5a2458a240b85aa60ec588c7defb2e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/850.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e85f39b06783eaecb34bb7d84d8895a4cadcecba", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "README.rst": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8500.json b/mne-python/source/doc/sphinxext/prs/8500.json new file mode 100644 index 0000000000000000000000000000000000000000..e584793d6c9c6ad1a1aff1dab4a5c5cdde88496f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8500.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6734953dd15070550cf792004b5ffa1079001541", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/utils/mixin.py": { + "a": 48, + "d": 34 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8502.json b/mne-python/source/doc/sphinxext/prs/8502.json new file mode 100644 index 0000000000000000000000000000000000000000..9d656efba5a4a0a4d624019f076dd5eae7db5c47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8502.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "3e1b5819ab640c3f349baa856d56d2c65c125d98", + "authors": [ + { + "n": "Zhenya", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 9, + "d": 0 + }, + "mne/datasets/limo/limo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_scraper.py": { + "a": 5, + "d": 1 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8503.json b/mne-python/source/doc/sphinxext/prs/8503.json new file mode 100644 index 0000000000000000000000000000000000000000..2f7d5c7f566374182db75be0dff1e0ba9b8acecd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8503.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "cab14251d246268997c27a07fb9260b5f173b149", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 141, + "d": 86 + }, + "mne/viz/_brain/_notebook.py": { + "a": 0, + "d": 67 + }, + "mne/viz/_brain/mplcanvas.py": { + "a": 24, + "d": 12 + }, + "mne/viz/_brain/tests/test.ipynb": { + "a": 12, + "d": 7 + }, + "mne/viz/backends/_notebook.py": { + "a": 5, + "d": 148 + }, + "server_environment.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8504.json b/mne-python/source/doc/sphinxext/prs/8504.json new file mode 100644 index 0000000000000000000000000000000000000000..4506f713cfef1bb6fbe5c573a4459f8c67f446d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8504.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b8f5e5ce0da8acfeb7298c8eb1d26a75d5526eac", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/preprocessing/nirs/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8506.json b/mne-python/source/doc/sphinxext/prs/8506.json new file mode 100644 index 0000000000000000000000000000000000000000..c63fbdadad41a7c1638137d9647a678ee512fbf6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8506.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "db49d5dad2fb077d2a9bc8a30cfc5569e2671144", + "authors": [ + { + "n": "Thomas Hartmann", + "e": "thomas.hartmann@th-ht.de" + } + ], + "changes": { + "mne/externals/pymatreader/pymatreader.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8508.json b/mne-python/source/doc/sphinxext/prs/8508.json new file mode 100644 index 0000000000000000000000000000000000000000..0bee29729b400c05befd64f5c01bf2fde15cced7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8508.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1fa17ddf895b42c08aea3120d127572834ac5c96", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 36, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/851.json b/mne-python/source/doc/sphinxext/prs/851.json new file mode 100644 index 0000000000000000000000000000000000000000..0f818a76fb8c5f2428ebecc9200c6d7963804320 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/851.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "7742303f25ef9784031c0a0db9b82c94e69217db", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 1 + }, + "doc/source/whats_new.rst": { + "a": 3, + "d": 0 + }, + "examples/datasets/README.txt": { + "a": 5, + "d": 0 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 118, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/sample/sample.py": { + "a": 15, + "d": 152 + }, + "mne/datasets/spm_face/__init__.py": { + "a": 4, + "d": 0 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 30, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 185, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 1 + }, + "mne/utils.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8514.json b/mne-python/source/doc/sphinxext/prs/8514.json new file mode 100644 index 0000000000000000000000000000000000000000..39c627173d2a1187b3605704c76a4356b68e9ff1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8514.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "c046c9c84a0f7f9874fd0f58ef259eaa5e2f6c08", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 38, + "d": 0 + }, + ".github/workflows/compat_minimal.yml": { + "a": 65, + "d": 0 + }, + ".github/workflows/compat_old.yml": { + "a": 60, + "d": 0 + }, + ".github/workflows/linux_conda.yml": { + "a": 6, + "d": 5 + }, + ".github/workflows/linux_pip.yml": { + "a": 60, + "d": 0 + }, + ".github/workflows/macos_conda.yml": { + "a": 4, + "d": 3 + }, + ".travis.yml": { + "a": 0, + "d": 135 + }, + "azure-pipelines.yml": { + "a": 244, + "d": 230 + }, + "tools/get_minimal_commands.sh": { + "a": 19, + "d": 17 + }, + "tools/github_actions_dependencies.sh": { + "a": 15, + "d": 2 + }, + "tools/github_actions_download.sh": { + "a": 3, + "d": 1 + }, + "tools/github_actions_test.sh": { + "a": 22, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8515.json b/mne-python/source/doc/sphinxext/prs/8515.json new file mode 100644 index 0000000000000000000000000000000000000000..44d04bfa3a4696e2ea0a155197c12fa6f4bc918e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8515.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "d73e0ab014c1fe6125d80f4649a5c066858d8c5f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/utils.py": { + "a": 25, + "d": 22 + }, + "mne/decoding/ssd.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 2, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 12, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + }, + "mne/utils/progressbar.py": { + "a": 3, + "d": 3 + }, + "mne/utils/tests/test_check.py": { + "a": 13, + "d": 1 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 7, + "d": 0 + }, + "tools/circleci_download.sh": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8516.json b/mne-python/source/doc/sphinxext/prs/8516.json new file mode 100644 index 0000000000000000000000000000000000000000..9872abcd6d54e302b3c1059952aedebefbbf37bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8516.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e82aee041d55fc0f18dd18a94939646be3fcca7f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/io/plot_objects_from_arrays.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 3, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 16, + "d": 2 + }, + "tutorials/evoked/plot_whitened.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8519.json b/mne-python/source/doc/sphinxext/prs/8519.json new file mode 100644 index 0000000000000000000000000000000000000000..281bd624a25f938b0916eb12621d9d1505be2839 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8519.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "23acc99e65aae9180ee72eddc2ba0ae2842e5e26", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/label.py": { + "a": 30, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/852.json b/mne-python/source/doc/sphinxext/prs/852.json new file mode 100644 index 0000000000000000000000000000000000000000..03f08c1fc6fc82b624fc6064ba13b2c77cfcd11f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/852.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4d1a6617239cdd21ed7aa7d9270dafd3f3c0a504", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 53, + "d": 0 + }, + "mne/fiff/kit/coreg.py": { + "a": 0, + "d": 53 + }, + "mne/fiff/kit/kit.py": { + "a": 3, + "d": 2 + }, + "mne/fiff/kit/tests/test_coreg.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8520.json b/mne-python/source/doc/sphinxext/prs/8520.json new file mode 100644 index 0000000000000000000000000000000000000000..61c1f96f2118ae6063659750bc36d11e85add48c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8520.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5efddb9e80dbf9935ae9340d1708737b867e4237", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 20, + "d": 17 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8521.json b/mne-python/source/doc/sphinxext/prs/8521.json new file mode 100644 index 0000000000000000000000000000000000000000..52bcf5dd719f78bc3e89f9420872877c90315a3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8521.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "aacafb171a13ad7325fb854d5603efd6bb951e00", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/source_space.py": { + "a": 103, + "d": 71 + }, + "mne/tests/test_morph.py": { + "a": 98, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8522.json b/mne-python/source/doc/sphinxext/prs/8522.json new file mode 100644 index 0000000000000000000000000000000000000000..b57b669f3fc9acb6d87aac462993698592fde61e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8522.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9775db1407c7c91f1b020d0c63f868430130b77c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8524.json b/mne-python/source/doc/sphinxext/prs/8524.json new file mode 100644 index 0000000000000000000000000000000000000000..cb2d3f3dfe9efc5b6264a2304b911b2e48704b92 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8524.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5c3e7424b63798a5093ff3a1971e841d23d4f61a", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8526.json b/mne-python/source/doc/sphinxext/prs/8526.json new file mode 100644 index 0000000000000000000000000000000000000000..3497f4d5631cf6af4b8349e351a6e3d4b07f6b7d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8526.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cedae25792da3dede4fa7fed943f4b7b7b1bb7c5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/forward/plot_left_cerebellum_volume_source.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 57, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8527.json b/mne-python/source/doc/sphinxext/prs/8527.json new file mode 100644 index 0000000000000000000000000000000000000000..27e5a949a7737796f4ddd68356f2e796dfa90616 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8527.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5d43084ffc12ae4c8d73c5db991856ea8e2e47e5", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/decoding/plot_ssd_spatial_filters.py": { + "a": 3, + "d": 2 + }, + "mne/decoding/ssd.py": { + "a": 13, + "d": 14 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8528.json b/mne-python/source/doc/sphinxext/prs/8528.json new file mode 100644 index 0000000000000000000000000000000000000000..2a92011a82c323d4c28366521161995928353ee0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8528.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0473162138943de2675d9a8cce0bb4766c3d5523", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 1, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8529.json b/mne-python/source/doc/sphinxext/prs/8529.json new file mode 100644 index 0000000000000000000000000000000000000000..18074fa2d3770e9c9db56ca8e83a9d6246d15d6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8529.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5db8876c5ca038c5cc5f0277e2bf17a19ddde717", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_morph_volume_stc.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 54, + "d": 27 + }, + "mne/tests/test_morph.py": { + "a": 40, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8532.json b/mne-python/source/doc/sphinxext/prs/8532.json new file mode 100644 index 0000000000000000000000000000000000000000..8471a47474932ed92d417d938a3d079093cf5570 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8532.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "40872a8b836a86a48d013a1654b2bfffb59ea5b8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 7, + "d": 7 + }, + "mne/channels/tests/test_montage.py": { + "a": 15, + "d": 22 + }, + "mne/io/_digitization.py": { + "a": 7, + "d": 2 + }, + "mne/utils/_testing.py": { + "a": 18, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8533.json b/mne-python/source/doc/sphinxext/prs/8533.json new file mode 100644 index 0000000000000000000000000000000000000000..58dbd7dad0334584a184d41dc41a4c30705052ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8533.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "7b0468f805c027818e864b92137664364d2a9a1b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/circle_artifacts.yml": { + "a": 0, + "d": 0 + }, + ".github/workflows/linux_conda.yml": { + "a": 1, + "d": 3 + }, + ".github/workflows/linux_pip.yml": { + "a": 4, + "d": 6 + }, + "README.rst": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 5, + "d": 7 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 14, + "d": 7 + }, + "tools/setup_xvfb.sh": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8534.json b/mne-python/source/doc/sphinxext/prs/8534.json new file mode 100644 index 0000000000000000000000000000000000000000..75a077c6fad3b8c49b551b3c79a70dd2b0357934 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8534.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "fe8eb45abb779e5f8ec5739486a0dbadf8d408de", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "examples/forward/plot_forward_sensitivity_maps.py": { + "a": 40, + "d": 3 + }, + "mne/source_space.py": { + "a": 64, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 66, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8536.json b/mne-python/source/doc/sphinxext/prs/8536.json new file mode 100644 index 0000000000000000000000000000000000000000..e476c2998a85993e9cd738eb8566dea792de522a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8536.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5305feef94a1b8df9355900cb5281f90eeb762f4", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/utils.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8537.json b/mne-python/source/doc/sphinxext/prs/8537.json new file mode 100644 index 0000000000000000000000000000000000000000..de5a200f0967803887d2878814738e870b153223 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8537.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "02db0b82d3cc42c1f30fc27a850340d890c4a538", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 6, + "d": 36 + }, + "mne/channels/tests/test_channels.py": { + "a": 8, + "d": 7 + }, + "mne/io/array/tests/test_array.py": { + "a": 4, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 4, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 19, + "d": 36 + }, + "mne/io/pick.py": { + "a": 62, + "d": 19 + }, + "mne/io/tests/test_pick.py": { + "a": 7, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8538.json b/mne-python/source/doc/sphinxext/prs/8538.json new file mode 100644 index 0000000000000000000000000000000000000000..d6c62e1549d058efc5fca86e59f068dbeffb8d8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8538.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "8a2a765ff0b959de55ff851d279b2ec3774f8be8", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 16, + "d": 1 + }, + ".github/workflows/compat_minimal.yml": { + "a": 17, + "d": 4 + }, + ".github/workflows/compat_old.yml": { + "a": 17, + "d": 6 + }, + ".github/workflows/linux_conda.yml": { + "a": 16, + "d": 3 + }, + ".github/workflows/linux_pip.yml": { + "a": 16, + "d": 3 + }, + ".github/workflows/macos_conda.yml": { + "a": 16, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8539.json b/mne-python/source/doc/sphinxext/prs/8539.json new file mode 100644 index 0000000000000000000000000000000000000000..7b4fe6542ce93468ea72ff8165818267a21afe19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8539.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d120a32dca2a1dc66e2827a1586d86ab3212d94e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/visualization/plot_eeglab_head_sphere.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/854.json b/mne-python/source/doc/sphinxext/prs/854.json new file mode 100644 index 0000000000000000000000000000000000000000..f09ee375a3674f96be14f6220b3ecc8d5075c00b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/854.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ac07d28fb314c0856eb67a7f5aa15d97d6912f53", + "authors": [ + { + "n": "Yaroslav Halchenko", + "e": null + } + ], + "changes": { + "debian/changelog": { + "a": 1, + "d": 1 + }, + "debian/compat": { + "a": 1, + "d": 1 + }, + "debian/control": { + "a": 2, + "d": 2 + }, + "debian/gbp.conf": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8540.json b/mne-python/source/doc/sphinxext/prs/8540.json new file mode 100644 index 0000000000000000000000000000000000000000..6b3a3995ac1603b1dc6a14a29799fa1d16be2fdc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8540.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "50d5863e1a823db06b369547a5452b9cd9a67a85", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/realign.py": { + "a": 107, + "d": 0 + }, + "mne/preprocessing/tests/test_realign.py": { + "a": 116, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8541.json b/mne-python/source/doc/sphinxext/prs/8541.json new file mode 100644 index 0000000000000000000000000000000000000000..054cb0ba4cf5f9609f00fdad5898bf197a5ac4b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8541.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "344f5ab46d3dee155837cf3299fecfa4a884040c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/compat_minimal.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/linux_conda.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/linux_pip.yml": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/setup_xvfb.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8542.json b/mne-python/source/doc/sphinxext/prs/8542.json new file mode 100644 index 0000000000000000000000000000000000000000..ab30ffbeb5bf1a502d467110c1371677792a29ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8542.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "92a29ff3c4e95fdae546cafd193cd0dc899a43bd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/constants.py": { + "a": 6, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 0 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 17, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8543.json b/mne-python/source/doc/sphinxext/prs/8543.json new file mode 100644 index 0000000000000000000000000000000000000000..6b835bfdab7e79786b05501fb07f5462d6a69f45 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8543.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8b0b8a967b1a8e2fd88c47221f535d73ca7d6fb2", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 15, + "d": 7 + }, + "mne/tests/test_label.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8545.json b/mne-python/source/doc/sphinxext/prs/8545.json new file mode 100644 index 0000000000000000000000000000000000000000..4f015d303196d42c48696cd1efb459c481c25545 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8545.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "75866351036ea00d36450dfa754be907d1e9c36a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 1 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 88, + "d": 95 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8546.json b/mne-python/source/doc/sphinxext/prs/8546.json new file mode 100644 index 0000000000000000000000000000000000000000..d4023fd7b57c454a0915075c1d65b2e0aa49deba --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8546.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "2b4605fbf50d1d03edc34ad013b5b4577f948b81", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_figure.py": { + "a": 171, + "d": 27 + }, + "mne/viz/epochs.py": { + "a": 11, + "d": 24 + }, + "mne/viz/raw.py": { + "a": 11, + "d": 18 + }, + "mne/viz/tests/test_figure.py": { + "a": 7, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 22, + "d": 19 + }, + "mne/viz/utils.py": { + "a": 5, + "d": 85 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 25, + "d": 25 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8547.json b/mne-python/source/doc/sphinxext/prs/8547.json new file mode 100644 index 0000000000000000000000000000000000000000..1237115c7955385f5f5caa2aed943386ecf971c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8547.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "54ac2d86a63a5a2ee556944df3f091cc612c4b8a", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 16, + "d": 29 + }, + "mne/viz/_brain/_brain.py": { + "a": 35, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8548.json b/mne-python/source/doc/sphinxext/prs/8548.json new file mode 100644 index 0000000000000000000000000000000000000000..4be8b0714873c31bad70e91f9a0b439809a2d952 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8548.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e280d1d2309d4bf22daf54066f05cc251840a31c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 8 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 24, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8549.json b/mne-python/source/doc/sphinxext/prs/8549.json new file mode 100644 index 0000000000000000000000000000000000000000..39e6792d483ebc682a60f0bbc1a5551dc72794a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8549.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ce6713c2df66d57974eb822cacebbc31425b0d12", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/tests/test_3d.py": { + "a": 5, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/855.json b/mne-python/source/doc/sphinxext/prs/855.json new file mode 100644 index 0000000000000000000000000000000000000000..96a866635d2aeac21a2306652b3496afef3ec3e2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/855.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0070ef4308c22426583d1d62724f05535f8036b2", + "authors": [ + { + "n": "Yaroslav Halchenko", + "e": null + } + ], + "changes": { + "debian/rules": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8552.json b/mne-python/source/doc/sphinxext/prs/8552.json new file mode 100644 index 0000000000000000000000000000000000000000..8efc77b47a1c83bec8afb876994799f3756b1462 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8552.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0eefe3145d17fa5bbac75baf83a21b3f3ff16da9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/references.bib": { + "a": 0, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8553.json b/mne-python/source/doc/sphinxext/prs/8553.json new file mode 100644 index 0000000000000000000000000000000000000000..d81014a373863cdeb839d92b514ccda16b0a1ffc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8553.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "9139c345ef40a6b5c4a1ee4e6943ae76e25d8276", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/defaults.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_coreg_gui.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_viewer.py": { + "a": 12, + "d": 6 + }, + "mne/viz/_3d.py": { + "a": 40, + "d": 16 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 35, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 16, + "d": 3 + }, + "mne/viz/backends/_utils.py": { + "a": 2, + "d": 1 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8554.json b/mne-python/source/doc/sphinxext/prs/8554.json new file mode 100644 index 0000000000000000000000000000000000000000..6a4ce83a5596c4004f9c52c7768f53a3ba3789f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8554.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "622f910ac9c54cc2ccba89013176be788fb2e016", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/gui/_backend.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8557.json b/mne-python/source/doc/sphinxext/prs/8557.json new file mode 100644 index 0000000000000000000000000000000000000000..1fbcf8d0c4c2e3443ebce7f3d8ad4b8b8a18090a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8557.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d34b797bf2d5df0356a2c6f6ef1cf2f549fcdac4", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + }, + "ignore_words.txt": { + "a": 1, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8558.json b/mne-python/source/doc/sphinxext/prs/8558.json new file mode 100644 index 0000000000000000000000000000000000000000..e659710bed3d1eb44a420dfdfcfe9092cb011db8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8558.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2c5bf45edf3f9039d5a77baf53db1ef22434ce9f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 42, + "d": 14 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 49, + "d": 13 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/856.json b/mne-python/source/doc/sphinxext/prs/856.json new file mode 100644 index 0000000000000000000000000000000000000000..1b8f841dc4d11cc1ef67d20dbaad42376ec28cc0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/856.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e2db91ccfe440bc11a1c6985b2247e68db5501a2", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/fiff/meas_info.py": { + "a": 17, + "d": 1 + }, + "mne/fiff/tag.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/tests/data/fsaverage-fiducials.fif": { + "a": 0, + "d": 0 + }, + "mne/fiff/tests/test_meas_info.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8560.json b/mne-python/source/doc/sphinxext/prs/8560.json new file mode 100644 index 0000000000000000000000000000000000000000..999c79020fcf50198d355c7a9e6e58964a4244e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8560.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "895ebf905adc22fd7ff7839ff73647b3ce293314", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 4, + "d": 0 + }, + "mne/viz/tests/test_epochs.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8561.json b/mne-python/source/doc/sphinxext/prs/8561.json new file mode 100644 index 0000000000000000000000000000000000000000..e120fe6b846c146b19be346ed6f5d5959333a7db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8561.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bd3fa021b2161ddf77418c35a139e3546ca5a986", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/install/pre_install.rst": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8564.json b/mne-python/source/doc/sphinxext/prs/8564.json new file mode 100644 index 0000000000000000000000000000000000000000..9145a5c30fc5fc7dc47742b97da502ff649081d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8564.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ea8120f4a516124b4bd5fd884efb47bfd848ad3e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 2 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8567.json b/mne-python/source/doc/sphinxext/prs/8567.json new file mode 100644 index 0000000000000000000000000000000000000000..f233417382301ada2ddff617259deb99e6c2d48e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8567.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "245d455bbf8b32ce96a445862029710ca5564489", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 20, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8569.json b/mne-python/source/doc/sphinxext/prs/8569.json new file mode 100644 index 0000000000000000000000000000000000000000..bd03dc5e7f8fc78921bb9baff0fe1660535a1dbd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8569.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fe9361ad49985c1f97984df494a93ce2fdf25ef9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "requirements.txt": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/857.json b/mne-python/source/doc/sphinxext/prs/857.json new file mode 100644 index 0000000000000000000000000000000000000000..d7a919f730e36524ea25cd452602186e96f66bc3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/857.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1c67a41c74424c90af131ffd9afab7a92857cfa5", + "authors": [ + { + "n": "Romain Trachel", + "e": "trachelr@gmail.com" + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8570.json b/mne-python/source/doc/sphinxext/prs/8570.json new file mode 100644 index 0000000000000000000000000000000000000000..633fc43ded63fb29d57f7293ee9cfb2855d5b156 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8570.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ff45e9fc45fbb18776c4a5162a1b437d2e3b9345", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/discussions/plot_background_filtering.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_background_freesurfer.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8572.json b/mne-python/source/doc/sphinxext/prs/8572.json new file mode 100644 index 0000000000000000000000000000000000000000..85ee0927a57ba6eb0e95c1a04b93deb1c90e9fee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8572.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7206f8e434106982e64728939794bee46adfc5f2", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 3, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 4 + }, + "mne/viz/backends/base_renderer.py": { + "a": 108, + "d": 104 + }, + "mne/viz/backends/renderer.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8574.json b/mne-python/source/doc/sphinxext/prs/8574.json new file mode 100644 index 0000000000000000000000000000000000000000..4b8c2d51ee2ed76ad93a7a803f1b0ba6669618c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8574.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "f9e62e04cbb4e0f2f5019919be58a470c8e9289e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 21, + "d": 17 + }, + "mne/channels/montage.py": { + "a": 3, + "d": 3 + }, + "mne/channels/tests/test_channels.py": { + "a": 0, + "d": 4 + }, + "mne/cov.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 4, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 13, + "d": 11 + }, + "mne/io/array/tests/test_array.py": { + "a": 5, + "d": 1 + }, + "mne/io/constants.py": { + "a": 18, + "d": 0 + }, + "mne/io/ctf_comp.py": { + "a": 27, + "d": 0 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 2 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 6, + "d": 7 + }, + "mne/io/meas_info.py": { + "a": 140, + "d": 47 + }, + "mne/io/proj.py": { + "a": 8, + "d": 20 + }, + "mne/io/tag.py": { + "a": 9, + "d": 1 + }, + "mne/io/tests/test_constants.py": { + "a": 5, + "d": 4 + }, + "mne/io/tests/test_meas_info.py": { + "a": 157, + "d": 3 + }, + "mne/io/tests/test_reference.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 0, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8575.json b/mne-python/source/doc/sphinxext/prs/8575.json new file mode 100644 index 0000000000000000000000000000000000000000..c107c543f73a632405f3c51d0c379e10f08c09db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8575.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "606e88fb976b0a320154e5912629705957f7b71b", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8576.json b/mne-python/source/doc/sphinxext/prs/8576.json new file mode 100644 index 0000000000000000000000000000000000000000..cb03b0d9ad5cba7eebc777de6595e9bba882a7a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8576.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5274110cb3be610beed591cba6bab633a0cc4211", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_source_space_snr.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 249, + "d": 187 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/callback.py": { + "a": 8, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 37, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8577.json b/mne-python/source/doc/sphinxext/prs/8577.json new file mode 100644 index 0000000000000000000000000000000000000000..5d1c8369ec40341b47fbd1d31d1f49eedbe453bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8577.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "679f954b51ae6d51be29423eab53e500be9d8755", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 24, + "d": 29 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8580.json b/mne-python/source/doc/sphinxext/prs/8580.json new file mode 100644 index 0000000000000000000000000000000000000000..eb22105717391eee23b0aab6163db0a77a6708d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8580.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "34c944a6c2e67f7ba464a5520726d3890dc73f07", + "authors": [ + { + "n": "Hongjiang YE", + "e": "hongjiang.ye@outlook.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8584.json b/mne-python/source/doc/sphinxext/prs/8584.json new file mode 100644 index 0000000000000000000000000000000000000000..42ff4acff11bdbd810b78e0b921256a7e4ef42cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8584.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "01a6ec08ee90266435cbccc460396e137313251e", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/datasets/testing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/testing/_testing.py": { + "a": 8, + "d": 5 + }, + "mne/io/edf/edf.py": { + "a": 9, + "d": 2 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 53, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8585.json b/mne-python/source/doc/sphinxext/prs/8585.json new file mode 100644 index 0000000000000000000000000000000000000000..c56ed6a57a4cf08c94346572decdf22e6139369b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8585.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "25524596480868d83fa0adb9748b4091c3568d55", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8586.json b/mne-python/source/doc/sphinxext/prs/8586.json new file mode 100644 index 0000000000000000000000000000000000000000..b69804c9093cbfe8c52aef109d9f2536b5df618f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8586.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "021fc1c7113b688586e2908c52a65ce056025020", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/overview/faq.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8589.json b/mne-python/source/doc/sphinxext/prs/8589.json new file mode 100644 index 0000000000000000000000000000000000000000..1b3a6aa75901442f6b391a1dd6549d6e6bdf7ea3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8589.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2b0f0c5a4cd1a3fe68ba04a0af2f1d141e1ec750", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8590.json b/mne-python/source/doc/sphinxext/prs/8590.json new file mode 100644 index 0000000000000000000000000000000000000000..3e99000b0e4fcd93f47643da7f03a8f896257470 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8590.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6e627f964f30d18b1af286bc4526a66b1cac24fe", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 10, + "d": 8 + }, + "tutorials/evoked/plot_20_visualize_evoked.py": { + "a": 46, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8594.json b/mne-python/source/doc/sphinxext/prs/8594.json new file mode 100644 index 0000000000000000000000000000000000000000..d860fbeb00f88ed35b01799fcf902d976a350e85 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8594.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c23df983dbd0e8f5bd481af07ceeb5453de8ca84", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 22, + "d": 3 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 69, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8595.json b/mne-python/source/doc/sphinxext/prs/8595.json new file mode 100644 index 0000000000000000000000000000000000000000..cfbc3e5129eeeb846a1d41f4002b83f61419a0db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8595.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "73e2e7a8d6c71d6abe4f5c3e8d88f8efcade89ff", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8596.json b/mne-python/source/doc/sphinxext/prs/8596.json new file mode 100644 index 0000000000000000000000000000000000000000..4a36905894196eb5ec604f0d1ccce8e907f050ae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8596.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "5a62f4719f28733687b5dd1f8fb9674f9f641c2f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "examples/io/README.txt": { + "a": 3, + "d": 2 + }, + "examples/io/plot_objects_from_arrays.py": { + "a": 0, + "d": 166 + }, + "examples/io/plot_read_and_write_raw_data.py": { + "a": 0, + "d": 45 + }, + "examples/io/plot_read_epochs.py": { + "a": 0, + "d": 48 + }, + "examples/io/plot_read_events.py": { + "a": 0, + "d": 77 + }, + "examples/io/plot_read_evoked.py": { + "a": 0, + "d": 36 + }, + "examples/io/plot_read_neo_format.py": { + "a": 34, + "d": 0 + }, + "examples/io/plot_read_proj.py": { + "a": 0, + "d": 64 + }, + "examples/preprocessing/plot_find_ecg_artifacts.py": { + "a": 0, + "d": 51 + }, + "examples/preprocessing/plot_find_eog_artifacts.py": { + "a": 0, + "d": 49 + }, + "examples/preprocessing/plot_metadata_query.py": { + "a": 0, + "d": 111 + }, + "examples/preprocessing/plot_rereference_eeg.py": { + "a": 0, + "d": 90 + }, + "examples/preprocessing/plot_resample.py": { + "a": 0, + "d": 83 + }, + "examples/time_frequency/plot_compute_raw_data_spectrum.py": { + "a": 0, + "d": 125 + }, + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/plot_10_reading_meg_data.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/plot_10_preprocessing_overview.py": { + "a": 3, + "d": 3 + }, + "tutorials/preprocessing/plot_55_setting_eeg_reference.py": { + "a": 27, + "d": 0 + }, + "tutorials/raw/plot_20_event_arrays.py": { + "a": 5, + "d": 0 + }, + "tutorials/simulation/plot_creating_data_structures.py": { + "a": 151, + "d": 148 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8598.json b/mne-python/source/doc/sphinxext/prs/8598.json new file mode 100644 index 0000000000000000000000000000000000000000..bd413e63a560bcd54bfebd68007efb406a2507e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8598.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "63dabf5165a1ccf0800267f2c56ed942a41d96be", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 46, + "d": 35 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 16, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tutorials/misc/plot_ecog.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/86.json b/mne-python/source/doc/sphinxext/prs/86.json new file mode 100644 index 0000000000000000000000000000000000000000..f0c1190c72f11677baae62917aea44cf21230f56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/86.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ccf0bc9a3ecdebf20f3368920bf74285f775f3cd", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/constants.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8601.json b/mne-python/source/doc/sphinxext/prs/8601.json new file mode 100644 index 0000000000000000000000000000000000000000..bc4a76177dd701bed19100e64c8872cfa5a9efcf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8601.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ce4c5ad2055d69d95131e9a215e6d142b5c58d0d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/fixes.py": { + "a": 25, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8603.json b/mne-python/source/doc/sphinxext/prs/8603.json new file mode 100644 index 0000000000000000000000000000000000000000..71b295b6387236e4e1cd48bb0572042b052c3f21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8603.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1e622deb5257ea59dd7929eadf549ce8ca564a17", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 98, + "d": 42 + }, + "mne/viz/tests/test_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8605.json b/mne-python/source/doc/sphinxext/prs/8605.json new file mode 100644 index 0000000000000000000000000000000000000000..ac65332b4b9b2af3a48a21438191d21a5b0ac716 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8605.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d45a85a841709e48861db73a3d4fde0619c243a9", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 12, + "d": 10 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 11, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8608.json b/mne-python/source/doc/sphinxext/prs/8608.json new file mode 100644 index 0000000000000000000000000000000000000000..a5ee7418331832f8d8fcb38ec809a5f661133eb0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8608.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ef2a2e491763db89d7411eee4c0dd49b1c8032ee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/csd.py": { + "a": 13, + "d": 13 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 37, + "d": 23 + }, + "mne/utils/tests/test_progressbar.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/861.json b/mne-python/source/doc/sphinxext/prs/861.json new file mode 100644 index 0000000000000000000000000000000000000000..0bd05b7ddad27623c353f01ffaf1f97672df37da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/861.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bcb98eb48dfe3944c67786d712ab3bbc0c98195f", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 13, + "d": 2 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8610.json b/mne-python/source/doc/sphinxext/prs/8610.json new file mode 100644 index 0000000000000000000000000000000000000000..c99668f7fcf791a94d478e686a8734bd3749b94c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8610.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "5ba77c8b947001da1598671503b165f232687dca", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 24, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 13, + "d": 10 + }, + "mne/beamformer/_lcmv.py": { + "a": 4, + "d": 22 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 64, + "d": 10 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 101, + "d": 32 + }, + "mne/conftest.py": { + "a": 15, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 44, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8611.json b/mne-python/source/doc/sphinxext/prs/8611.json new file mode 100644 index 0000000000000000000000000000000000000000..5708cab5b029162e50fc18410e3b5e71ae1df111 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8611.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a00ed0ab22852941b1cd6288590d25b88086bfaf", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8612.json b/mne-python/source/doc/sphinxext/prs/8612.json new file mode 100644 index 0000000000000000000000000000000000000000..b3429da70b046c30631683d278f4eb4e05da9526 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8612.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "76e386ca0d588c30a58519b125448162f735a8e9", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 18 + }, + "mne/preprocessing/ecg.py": { + "a": 28, + "d": 66 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ssp.py": { + "a": 8, + "d": 4 + }, + "mne/proj.py": { + "a": 9, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 86, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8618.json b/mne-python/source/doc/sphinxext/prs/8618.json new file mode 100644 index 0000000000000000000000000000000000000000..4a3194f2c8d38fe8d7f250c828aae02b175f6468 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8618.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2ae5c408513293d5f9f32a379afc5f99540398d9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 81, + "d": 71 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 3, + "d": 3 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 7, + "d": 4 + }, + "mne/io/kit/kit.py": { + "a": 46, + "d": 42 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8619.json b/mne-python/source/doc/sphinxext/prs/8619.json new file mode 100644 index 0000000000000000000000000000000000000000..3dfb99bb1ac1431442167c27b34f836615aa299f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8619.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3db29c459f6b612b3981e2c54cc05111038d292c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8621.json b/mne-python/source/doc/sphinxext/prs/8621.json new file mode 100644 index 0000000000000000000000000000000000000000..4b5f10652e544363eda853d9ccc65160597baa00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8621.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "35fcbca549a1a7b91cbda18768b8dc8dcf32b547", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8622.json b/mne-python/source/doc/sphinxext/prs/8622.json new file mode 100644 index 0000000000000000000000000000000000000000..aefd3140e16c29aaf43182c4add79cd7b876f357 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8622.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "90f4dec944d6096b0a8860e6923572fedd7728cd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 16, + "d": 5 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 4, + "d": 3 + }, + "mne/io/_digitization.py": { + "a": 3, + "d": 155 + }, + "mne/io/kit/coreg.py": { + "a": 115, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 12, + "d": 13 + }, + "mne/utils/docs.py": { + "a": 14, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8624.json b/mne-python/source/doc/sphinxext/prs/8624.json new file mode 100644 index 0000000000000000000000000000000000000000..225675b4fcd23f25bb1571afa0e0bfdf6f1db664 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8624.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "cfd5659ba5639b1af9b64edd9e9701a58c3262c3", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 123, + "d": 50 + }, + "mne/viz/raw.py": { + "a": 0, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 12, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8626.json b/mne-python/source/doc/sphinxext/prs/8626.json new file mode 100644 index 0000000000000000000000000000000000000000..810a0efb0f871dee10a74c3bbe955353135de414 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8626.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cfada9d37b4f9e2f01657779c1f2f89e7832f763", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 12, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8627.json b/mne-python/source/doc/sphinxext/prs/8627.json new file mode 100644 index 0000000000000000000000000000000000000000..a0fa263546942fd99b4ace106e23c88be31ebd51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8627.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "46f3c151ba8c431a882daa609403d4f996c0b1e7", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_source_space_snr.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 19, + "d": 13 + }, + "tutorials/misc/plot_seeg.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8629.json b/mne-python/source/doc/sphinxext/prs/8629.json new file mode 100644 index 0000000000000000000000000000000000000000..aad65441b6f68fabbcba3543b4f7fd2d978fbc2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8629.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c4c96152d2e28b95f2b3f644bd2fc5f2a3cf006a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/863.json b/mne-python/source/doc/sphinxext/prs/863.json new file mode 100644 index 0000000000000000000000000000000000000000..fc34e76c92866d2821bca02532ce99f891458a36 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/863.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fe29b83339d418baf06b9b133622f0ec6b580d37", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/python_tutorial.rst": { + "a": 17, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8630.json b/mne-python/source/doc/sphinxext/prs/8630.json new file mode 100644 index 0000000000000000000000000000000000000000..f9cd067af82a0389c953b51b804e3a3d74da59dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8630.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d282fbec34de472136dfd3d5449c591e84fc9300", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 4 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8631.json b/mne-python/source/doc/sphinxext/prs/8631.json new file mode 100644 index 0000000000000000000000000000000000000000..b518f7c6b779934466159f0d1bc077487ce8767c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8631.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b3fd2f16895ecd785d02f2cbf7762919819cfa71", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 3, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8633.json b/mne-python/source/doc/sphinxext/prs/8633.json new file mode 100644 index 0000000000000000000000000000000000000000..d2e425a44b82efd27328192c747ae15aa99a1862 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8633.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5eeca84cef086a3ee6edab577b138ffa43ff965c", + "authors": [ + { + "n": "Jeff Stout", + "e": null + }, + { + "n": "Jeff Stout", + "e": "stoutjd@nih.gov" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/tests/test_raw.py": { + "a": 38, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8636.json b/mne-python/source/doc/sphinxext/prs/8636.json new file mode 100644 index 0000000000000000000000000000000000000000..c1e137d844b22f3a862704407414d6678d4131b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8636.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "89cb6bbdc9547594a6a3ff5f524b9e68289588f3", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + } + ], + "changes": { + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8638.json b/mne-python/source/doc/sphinxext/prs/8638.json new file mode 100644 index 0000000000000000000000000000000000000000..a222a1d1ff344a5989c4a78e3c4fe6fb555046c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8638.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "74e098581f06cbf078cdbb0eb3379e7e02d40bd4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 0, + "d": 1 + }, + "examples/visualization/plot_evoked_topomap.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 7, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 6, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 4, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 12, + "d": 6 + }, + "mne/viz/tests/test_topomap.py": { + "a": 9, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 60, + "d": 53 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8639.json b/mne-python/source/doc/sphinxext/prs/8639.json new file mode 100644 index 0000000000000000000000000000000000000000..b5e52e968caed27b75a569de0932921e5aa78683 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8639.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "4e4e70798535c6df881e7d840547be7f905fa3b0", + "authors": [ + { + "n": null, + "e": "olaf.hauk@mrc-cbu.cam.ac.uk" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 0, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 65, + "d": 20 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 18, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 22, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/864.json b/mne-python/source/doc/sphinxext/prs/864.json new file mode 100644 index 0000000000000000000000000000000000000000..d2acf1f42d35b88a4a945cd63686c40453c56813 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/864.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e1bb84310f30e250573f43f17763eb15c39801b8", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 9, + "d": 6 + }, + "mne/source_estimate.py": { + "a": 25, + "d": 39 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8643.json b/mne-python/source/doc/sphinxext/prs/8643.json new file mode 100644 index 0000000000000000000000000000000000000000..78de47f4f1aa7166248fa6812ee878331ea50a4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8643.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "e2357ad7848a3c3968678557ef5ded4602bed0c8", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/inverse/plot_source_space_snr.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_vector_mne_solution.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 5 + }, + "mne/viz/backends/_pyvista.py": { + "a": 14, + "d": 12 + }, + "mne/viz/backends/_utils.py": { + "a": 7, + "d": 0 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 2, + "d": 1 + }, + "tutorials/misc/plot_seeg.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8644.json b/mne-python/source/doc/sphinxext/prs/8644.json new file mode 100644 index 0000000000000000000000000000000000000000..7cf93b07a4d71a8243844b954220fc4db2f06503 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8644.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a087895ebd69d98afc3e236677d7bf17a76d5921", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8645.json b/mne-python/source/doc/sphinxext/prs/8645.json new file mode 100644 index 0000000000000000000000000000000000000000..3e0a8b6c1621343e693c486078e28174e6e9cf3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8645.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ae9ed2332cf24209ec2a178e61c0d02fdd35b03c", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 9, + "d": 9 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8647.json b/mne-python/source/doc/sphinxext/prs/8647.json new file mode 100644 index 0000000000000000000000000000000000000000..769fa0fd291dc3dd2748bfdb7c4dcaef27f4db7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8647.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "76b64ff884474c7b1569cf74d6183e2ab13b7e9f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 33, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8648.json b/mne-python/source/doc/sphinxext/prs/8648.json new file mode 100644 index 0000000000000000000000000000000000000000..7597744fec6db50fea93cbee180ef8d9f8347286 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8648.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "52e97df12b6da69a66e645c951a35795733ac9a5", + "authors": [ + { + "n": "dengemann", + "e": "denis.engemann@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/decoding/plot_ssd_spatial_filters.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ssd.py": { + "a": 22, + "d": 16 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 94, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8651.json b/mne-python/source/doc/sphinxext/prs/8651.json new file mode 100644 index 0000000000000000000000000000000000000000..334289f4a8172c63e99195725743f89e3479fb5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8651.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5d7ddd2bb64f22a150ff49e7f2c61f7dab2a6e53", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 2, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 8, + "d": 2 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 13, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8653.json b/mne-python/source/doc/sphinxext/prs/8653.json new file mode 100644 index 0000000000000000000000000000000000000000..e385a3aeba768db5dec15d44fa9eaa89b2a170ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8653.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e40e592d3d2c6aeaa5c44bab2602d4aa486fc830", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 0, + "d": 1 + }, + "examples/preprocessing/plot_eeg_csd.py": { + "a": 1, + "d": 1 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8655.json b/mne-python/source/doc/sphinxext/prs/8655.json new file mode 100644 index 0000000000000000000000000000000000000000..5e79be68c631ccdb331b3e64a2203462e5ffb7f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8655.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "51f38b25034cbe24ebcdf0a1d4158597a64e04e0", + "authors": [ + { + "n": "Josh Koen", + "e": "koen.joshua@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/references.bib": { + "a": 35, + "d": 0 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 247, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8656.json b/mne-python/source/doc/sphinxext/prs/8656.json new file mode 100644 index 0000000000000000000000000000000000000000..04c6a394be4f9092fdf721fc67d514609ca67a83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8656.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "52c4fffc32fdcce39e3c8b654f77b2ba5f89543f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 3, + "d": 2 + }, + "server_environment.yml": { + "a": 10, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8657.json b/mne-python/source/doc/sphinxext/prs/8657.json new file mode 100644 index 0000000000000000000000000000000000000000..0fc117a18384dbc8470df5e3ecd53a6aad758d34 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8657.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "391f462317e5487b6dceeaa3c5361fe97f9deba2", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_notebook.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8658.json b/mne-python/source/doc/sphinxext/prs/8658.json new file mode 100644 index 0000000000000000000000000000000000000000..e13f4b8ef4c39095a4cfeaecbdf2227f1940d581 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8658.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d4f99de184f80a069a42302e9427f2e9b0aad8fb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 1, + "d": 0 + }, + "mne/connectivity/envelope.py": { + "a": 33, + "d": 6 + }, + "mne/connectivity/tests/test_envelope.py": { + "a": 40, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/866.json b/mne-python/source/doc/sphinxext/prs/866.json new file mode 100644 index 0000000000000000000000000000000000000000..0870ca58e30a821669597db3f4d9c645a883de21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/866.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "5995a3a5cbd1fa935c106fc72a688d59b21c7f65", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 1 + }, + "bin/mne": { + "a": 46, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_flash_bem_model.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_maxfilter.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_surf2bem.py": { + "a": 0, + "d": 0 + }, + "setup.py": { + "a": 5, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8662.json b/mne-python/source/doc/sphinxext/prs/8662.json new file mode 100644 index 0000000000000000000000000000000000000000..8047680a5074915d1043c59aab96cb81e8075b2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8662.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "ae750c60b3a6f97b8ba610fecf272c10c5a4a227", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 2 + }, + "mne/time_frequency/psd.py": { + "a": 18, + "d": 14 + }, + "mne/time_frequency/tests/test_psd.py": { + "a": 16, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 2, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 7, + "d": 2 + }, + "mne/viz/tests/test_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8663.json b/mne-python/source/doc/sphinxext/prs/8663.json new file mode 100644 index 0000000000000000000000000000000000000000..92b6ec5f231503f0bbca90caf0f47ae95dc88b5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8663.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "88d9be9f8694911c2a923154411f24229b437310", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 10, + "d": 5 + }, + "mne/viz/_brain/_brain.py": { + "a": 7, + "d": 4 + }, + "mne/viz/_brain/colormap.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 16, + "d": 8 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 2 + }, + "tutorials/misc/plot_seeg.py": { + "a": 1, + "d": 0 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8665.json b/mne-python/source/doc/sphinxext/prs/8665.json new file mode 100644 index 0000000000000000000000000000000000000000..0cea7def619393fe4c892095e13027c02fd84adc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8665.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "1b9d2228bc40f817ef1765686bc2ec6e81079d13", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 130, + "d": 130 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 31, + "d": 33 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 9, + "d": 5 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 5, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 23, + "d": 18 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 13, + "d": 15 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 192, + "d": 164 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 124, + "d": 117 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8668.json b/mne-python/source/doc/sphinxext/prs/8668.json new file mode 100644 index 0000000000000000000000000000000000000000..8429c6e3d080f8bdeac8fd76d8ba3f998b3afaea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8668.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "92a41a284093a845697b81dab89afed8bc3eeb4b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 2, + "d": 12 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 8 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ica.py": { + "a": 14, + "d": 62 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 12, + "d": 86 + }, + "mne/source_estimate.py": { + "a": 9, + "d": 20 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 9 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 12 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8669.json b/mne-python/source/doc/sphinxext/prs/8669.json new file mode 100644 index 0000000000000000000000000000000000000000..ab3af8371f3c2880c99ac25ad6f2f87dae8cad47 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8669.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "415ae684e35a8facbe9e8c5c049b2461de119fe1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".mailmap": { + "a": 48, + "d": 6 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "codemeta.json": { + "a": 1413, + "d": 0 + }, + "requirements.txt": { + "a": 2, + "d": 2 + }, + "setup.py": { + "a": 10, + "d": 1 + }, + "tools/generate_codemeta.py": { + "a": 137, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8672.json b/mne-python/source/doc/sphinxext/prs/8672.json new file mode 100644 index 0000000000000000000000000000000000000000..0a0ef1c92afdda4dab2b4cd5ebbcdd03b2f41b86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8672.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3cc39e31a9f74f72e27dd64855d533c89cd74c58", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 2, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 7 + }, + "tutorials/evoked/plot_20_visualize_evoked.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 45, + "d": 45 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 19, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8673.json b/mne-python/source/doc/sphinxext/prs/8673.json new file mode 100644 index 0000000000000000000000000000000000000000..2594958aba9e9ba9e0ff3e8b7ee265bc2070591d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8673.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7a689df121d1193d0efec099fbc26b63db40e583", + "authors": [ + { + "n": "Mainak Jas", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/install/advanced.rst": { + "a": 37, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8675.json b/mne-python/source/doc/sphinxext/prs/8675.json new file mode 100644 index 0000000000000000000000000000000000000000..d9a4836ee683884e46458044550fee95d84b07b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8675.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1371d440e9e162c6b734276dad501f363363172e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 7, + "d": 7 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8676.json b/mne-python/source/doc/sphinxext/prs/8676.json new file mode 100644 index 0000000000000000000000000000000000000000..41711cf06d21df4b6e0fc4ed2eaa8bfebc0f2923 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8676.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8204c90211bf6a0d9385cd9e8f5fe41741a54ea2", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/868.json b/mne-python/source/doc/sphinxext/prs/868.json new file mode 100644 index 0000000000000000000000000000000000000000..033fde52b7d3f4a3fb5def86c3bbf751e3d61a63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/868.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "23d0f05c64ab129d05f08cbabd5cb28926505032", + "authors": [ + { + "n": "Yaroslav Halchenko", + "e": null + } + ], + "changes": { + "bin/mne": { + "a": 1, + "d": 11 + }, + "mne/commands/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 3, + "d": 3 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_surf2bem.py": { + "a": 7, + "d": 11 + }, + "mne/commands/utils.py": { + "a": 39, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8682.json b/mne-python/source/doc/sphinxext/prs/8682.json new file mode 100644 index 0000000000000000000000000000000000000000..d906307f59647ffa7b5ab31a38cee1ff3a1714e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8682.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "40629b6709e7352eecdd948e4b96307cef4a55c7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8683.json b/mne-python/source/doc/sphinxext/prs/8683.json new file mode 100644 index 0000000000000000000000000000000000000000..26b38c7846c5563fed8a16e6ac2b63b9f0bbcb06 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8683.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "14a0e9a81350ee42a5f7a9eee6bf3408701433d0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 0, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8688.json b/mne-python/source/doc/sphinxext/prs/8688.json new file mode 100644 index 0000000000000000000000000000000000000000..773a2b42a20e53198aee2132ba7bd8e0488f5f68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8688.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "53b4c1807dc16189db82d2ffc9a45160c2ee3c7a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 14, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8689.json b/mne-python/source/doc/sphinxext/prs/8689.json new file mode 100644 index 0000000000000000000000000000000000000000..d6973893295380453a9ed4b594a90a83b75de886 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8689.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "303fabe4438c366194b1ea5bf7f507813ff5bab1", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8690.json b/mne-python/source/doc/sphinxext/prs/8690.json new file mode 100644 index 0000000000000000000000000000000000000000..9feb180a5b40ec028d9d0f033bd06ead503f0460 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8690.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a36cd9e27f893476a7961d77203a96be2bc6a01c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 71, + "d": 38 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8695.json b/mne-python/source/doc/sphinxext/prs/8695.json new file mode 100644 index 0000000000000000000000000000000000000000..831121cb6bab99e8b5dc8870130ad3e23ac1c175 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8695.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "c4215cb7bcf0e9709549fec09d3ed751b3678fba", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 8, + "d": 0 + }, + ".github/workflows/compat_old.yml": { + "a": 8, + "d": 0 + }, + ".github/workflows/linux_conda.yml": { + "a": 8, + "d": 0 + }, + ".github/workflows/linux_pip.yml": { + "a": 8, + "d": 0 + }, + ".github/workflows/macos_conda.yml": { + "a": 8, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 23, + "d": 0 + }, + "tools/get_testing_version.sh": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8696.json b/mne-python/source/doc/sphinxext/prs/8696.json new file mode 100644 index 0000000000000000000000000000000000000000..f2ad1dfcbf69a9123fda425e3f0125df344c035a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8696.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "1386e1444f2097d247592ec7e6a6c7190aafceb6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/tests/test_datasets.py": { + "a": 54, + "d": 12 + }, + "mne/datasets/utils.py": { + "a": 13, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8697.json b/mne-python/source/doc/sphinxext/prs/8697.json new file mode 100644 index 0000000000000000000000000000000000000000..eb3aa8bd0409dc6344f9e6d4d44e33d30dbccacc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8697.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "9f231cfa8416b5bfe06dc996fa6d50c87b488d37", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 0, + "d": 6 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_multidict_reweighted_tfmxne.py": { + "a": 26, + "d": 39 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 36, + "d": 25 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/_stft.py": { + "a": 19, + "d": 20 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 13, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8698.json b/mne-python/source/doc/sphinxext/prs/8698.json new file mode 100644 index 0000000000000000000000000000000000000000..b452795c23612865fda4ad9b99966485113155fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8698.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "77e7735e2a5b02c597ae5df353179e83f888859b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/bug_report.md": { + "a": 3, + "d": 5 + }, + ".github/ISSUE_TEMPLATE/config.yml": { + "a": 2, + "d": 5 + }, + ".github/ISSUE_TEMPLATE/question.md": { + "a": 3, + "d": 7 + }, + "CONTRIBUTING.rst": { + "a": 3, + "d": 6 + }, + "README.rst": { + "a": 3, + "d": 3 + }, + "doc/install/advanced.rst": { + "a": 1, + "d": 1 + }, + "doc/install/contributing.rst": { + "a": 3, + "d": 5 + }, + "doc/install/mne_c.rst": { + "a": 2, + "d": 2 + }, + "doc/install/mne_python.rst": { + "a": 2, + "d": 2 + }, + "doc/install/pre_install.rst": { + "a": 2, + "d": 2 + }, + "doc/links.inc": { + "a": 1, + "d": 2 + }, + "doc/overview/datasets_index.rst": { + "a": 2, + "d": 2 + }, + "doc/overview/faq.rst": { + "a": 9, + "d": 18 + }, + "doc/overview/get_help.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8702.json b/mne-python/source/doc/sphinxext/prs/8702.json new file mode 100644 index 0000000000000000000000000000000000000000..8bec860e9389e03e841337a4deaaa16bc3898679 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8702.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "68e02f51918b038979e4bbd1ed295e412fbb7a8c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 137, + "d": 61 + }, + "mne/utils/config.py": { + "a": 6, + "d": 1 + }, + "requirements_doc.txt": { + "a": 2, + "d": 2 + }, + "requirements_testing.txt": { + "a": 3, + "d": 3 + }, + "tools/circleci_download.sh": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8707.json b/mne-python/source/doc/sphinxext/prs/8707.json new file mode 100644 index 0000000000000000000000000000000000000000..fb1335755a58c60f05f7984bd021294af110f449 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8707.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "01b8b364698f86630d22fad573058233ab6a58a5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/rank.py": { + "a": 0, + "d": 19 + }, + "mne/utils/docs.py": { + "a": 41, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8708.json b/mne-python/source/doc/sphinxext/prs/8708.json new file mode 100644 index 0000000000000000000000000000000000000000..46a1cf1d156adbafdc5c0758e8c9b4488b862fc2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8708.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "72c8f61e615b04b2f00e9e36202572cd23ae0c47", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 3, + "d": 1 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 83, + "d": 59 + }, + "mne/viz/_brain/tests/test.ipynb": { + "a": 39, + "d": 5 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 52, + "d": 1 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 0, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 42, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 13, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 44, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8709.json b/mne-python/source/doc/sphinxext/prs/8709.json new file mode 100644 index 0000000000000000000000000000000000000000..708b9be5e24de3bb153d02fed6c38c2802b69607 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8709.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d9a47232e7eaf6382a7c89c8cc6688f6a6695731", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 17, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8711.json b/mne-python/source/doc/sphinxext/prs/8711.json new file mode 100644 index 0000000000000000000000000000000000000000..110b7aa05724f8da6b9c5934ca01ae965808c60f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8711.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "22770ec3d2fbd83e40fa98377ff1a86eac52e6e2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8712.json b/mne-python/source/doc/sphinxext/prs/8712.json new file mode 100644 index 0000000000000000000000000000000000000000..0b6c4d45a577d483fb91debd008b6eb0053bf7c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8712.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8756d81963f0fe742667bb40d2c66ca37722a69f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nicolet/nicolet.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8713.json b/mne-python/source/doc/sphinxext/prs/8713.json new file mode 100644 index 0000000000000000000000000000000000000000..c8983ef4365a28c91cf657a1f82db1c2858b79cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8713.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "7d5cd307bc1c7de4e7587624fda263c4b4230ce5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 21, + "d": 67 + }, + "mne/tests/test_report.py": { + "a": 38, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_topomap.py": { + "a": 1, + "d": 0 + }, + "tools/setup_xvfb.sh": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8720.json b/mne-python/source/doc/sphinxext/prs/8720.json new file mode 100644 index 0000000000000000000000000000000000000000..1ff9c76e74ad333160d27aeab718f809b5673bb0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8720.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "48d848e8ca0972da9edfaa7701003b3735bdf40e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/bug_report.md": { + "a": 3, + "d": 5 + }, + ".github/ISSUE_TEMPLATE/config.yml": { + "a": 2, + "d": 5 + }, + ".github/ISSUE_TEMPLATE/question.md": { + "a": 3, + "d": 7 + }, + "CONTRIBUTING.rst": { + "a": 3, + "d": 6 + }, + "README.rst": { + "a": 3, + "d": 3 + }, + "doc/install/advanced.rst": { + "a": 1, + "d": 1 + }, + "doc/install/contributing.rst": { + "a": 3, + "d": 5 + }, + "doc/install/mne_c.rst": { + "a": 2, + "d": 2 + }, + "doc/install/mne_python.rst": { + "a": 2, + "d": 2 + }, + "doc/install/pre_install.rst": { + "a": 2, + "d": 2 + }, + "doc/links.inc": { + "a": 1, + "d": 2 + }, + "doc/overview/datasets_index.rst": { + "a": 2, + "d": 2 + }, + "doc/overview/faq.rst": { + "a": 9, + "d": 18 + }, + "doc/overview/get_help.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8721.json b/mne-python/source/doc/sphinxext/prs/8721.json new file mode 100644 index 0000000000000000000000000000000000000000..34b432294a0a208da74af3bfead8bf7f8f0284f8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8721.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f2caf79ae5db82378ef0ed717992312b8bdefff4", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/rank.py": { + "a": 0, + "d": 19 + }, + "mne/utils/docs.py": { + "a": 41, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8723.json b/mne-python/source/doc/sphinxext/prs/8723.json new file mode 100644 index 0000000000000000000000000000000000000000..6fc06d3a2a2fd038fa5b3acffceecb9e2f96c598 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8723.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "700d7c0a06655933adb9d7806153a7d00bbdde25", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "examples/visualization/plot_make_report.py": { + "a": 0, + "d": 53 + }, + "mne/report.py": { + "a": 64, + "d": 29 + }, + "tutorials/misc/plot_report.py": { + "a": 20, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8725.json b/mne-python/source/doc/sphinxext/prs/8725.json new file mode 100644 index 0000000000000000000000000000000000000000..71631358e100ba7f8000c9430b4749b2d0b8315e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8725.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "8808612e787773118fcc3a0e5b8b321da0e35c8a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/report.py": { + "a": 79, + "d": 61 + }, + "mne/viz/_brain/mplcanvas.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 6 + }, + "mne/viz/misc.py": { + "a": 13, + "d": 8 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 17, + "d": 0 + }, + "tutorials/misc/plot_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8727.json b/mne-python/source/doc/sphinxext/prs/8727.json new file mode 100644 index 0000000000000000000000000000000000000000..85efac4144f0bd8100f27516a900dcd51203b277 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8727.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "038832403ae7d2cf3ea4d05a944b2bb354bb386f", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/forward/_compute_forward.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8728.json b/mne-python/source/doc/sphinxext/prs/8728.json new file mode 100644 index 0000000000000000000000000000000000000000..f1f452368122b7aa4a33c916a09387a37837bfe3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8728.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "99f957fa3a3289da8bedc113ec187f7397811277", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/io/reference.py": { + "a": 3, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 36, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8730.json b/mne-python/source/doc/sphinxext/prs/8730.json new file mode 100644 index 0000000000000000000000000000000000000000..226be4db901d03c6eb67103a903a26734d232a8b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8730.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1a990c8c0404824b6aea0daa338e5d6113d4975e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 18, + "d": 7 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 13, + "d": 1 + }, + "tutorials/misc/plot_report.py": { + "a": 28, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8731.json b/mne-python/source/doc/sphinxext/prs/8731.json new file mode 100644 index 0000000000000000000000000000000000000000..c52212b306f562ef8501e98b384b2f5339826b4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8731.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f394bbd643c49544bffd157ae42e341568d54c6e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8734.json b/mne-python/source/doc/sphinxext/prs/8734.json new file mode 100644 index 0000000000000000000000000000000000000000..b02006084c06bf6fc93e74e51133d900dddaf2e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8734.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "81051e6eb9ec1a58c1b1f1c956dddfedfcf6b47f", + "authors": [ + { + "n": "Tristan Stenner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/nedf/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/nedf/nedf.py": { + "a": 217, + "d": 0 + }, + "mne/io/nedf/tests/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/nedf/tests/test_nedf.py": { + "a": 131, + "d": 0 + }, + "mne/io/utils.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8736.json b/mne-python/source/doc/sphinxext/prs/8736.json new file mode 100644 index 0000000000000000000000000000000000000000..c83b7a1b4bf9cdde14d13b45baeed952d42f8525 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8736.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "826ddd2f669fb35e574698042378c83e9b1217ca", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 9, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8738.json b/mne-python/source/doc/sphinxext/prs/8738.json new file mode 100644 index 0000000000000000000000000000000000000000..825f93a5759e1ca87ae5bc47226b62bb771a9f43 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8738.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "5f17b357bbd549626d92c73f82daede8751bb711", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 6, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 33, + "d": 1 + }, + "mne/datasets/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 13, + "d": 24 + }, + "mne/datasets/_infant/ANTS1-0Months3T.txt": { + "a": 117, + "d": 0 + }, + "mne/datasets/_infant/ANTS10-5Months3T.txt": { + "a": 115, + "d": 0 + }, + "mne/datasets/_infant/ANTS12-0Months3T.txt": { + "a": 121, + "d": 0 + }, + "mne/datasets/_infant/ANTS15-0Months3T.txt": { + "a": 121, + "d": 0 + }, + "mne/datasets/_infant/ANTS18-0Months3T.txt": { + "a": 121, + "d": 0 + }, + "mne/datasets/_infant/ANTS2-0Weeks3T.txt": { + "a": 117, + "d": 0 + }, + "mne/datasets/_infant/ANTS2-0Years3T.txt": { + "a": 121, + "d": 0 + }, + "mne/datasets/_infant/ANTS3-0Months3T.txt": { + "a": 121, + "d": 0 + }, + "mne/datasets/_infant/ANTS4-5Months3T.txt": { + "a": 121, + "d": 0 + }, + "mne/datasets/_infant/ANTS6-0Months3T.txt": { + "a": 121, + "d": 0 + }, + "mne/datasets/_infant/ANTS7-5Months3T.txt": { + "a": 121, + "d": 0 + }, + "mne/datasets/_infant/ANTS9-0Months3T.txt": { + "a": 121, + "d": 0 + }, + "mne/datasets/_infant/base.py": { + "a": 94, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 18, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 4, + "d": 2 + }, + "setup.py": { + "a": 2, + "d": 0 + }, + "tutorials/source-modeling/plot_eeg_no_mri.py": { + "a": 65, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8739.json b/mne-python/source/doc/sphinxext/prs/8739.json new file mode 100644 index 0000000000000000000000000000000000000000..8b5f28d18710dac0dd35b2d057269a756fa4af0e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8739.json @@ -0,0 +1,187 @@ +{ + "merge_commit_sha": "e4fcd77a60bc50085640aec34e9fba1f1c74a8b3", + "authors": [ + { + "n": "Richard M. Köhler", + "e": "koehler.richard@charite.de" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "codemeta.json": { + "a": 2, + "d": 1 + }, + "doc/_includes/channel_types.rst": { + "a": 2, + "d": 0 + }, + "doc/_includes/units.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 14, + "d": 12 + }, + "mne/channels/montage.py": { + "a": 4, + "d": 4 + }, + "mne/channels/tests/test_channels.py": { + "a": 7, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 2 + }, + "mne/cov.py": { + "a": 10, + "d": 6 + }, + "mne/defaults.py": { + "a": 17, + "d": 15 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 6, + "d": 4 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 4, + "d": 2 + }, + "mne/io/constants.py": { + "a": 2, + "d": 0 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 4, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 3 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 23, + "d": 14 + }, + "mne/io/reference.py": { + "a": 5, + "d": 5 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 25, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 22, + "d": 6 + }, + "mne/preprocessing/ica.py": { + "a": 8, + "d": 5 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 24, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 5, + "d": 5 + }, + "mne/tests/test_epochs.py": { + "a": 20, + "d": 9 + }, + "mne/tests/test_filter.py": { + "a": 3, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 10, + "d": 7 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 8, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 5 + }, + "tools/generate_codemeta.py": { + "a": 2, + "d": 1 + }, + "tutorials/raw/plot_10_raw_overview.py": { + "a": 3, + "d": 3 + }, + "tutorials/simulation/plot_creating_data_structures.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/874.json b/mne-python/source/doc/sphinxext/prs/874.json new file mode 100644 index 0000000000000000000000000000000000000000..c4b2980c4185840e16b9134166b1dc3d9c9e3020 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/874.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "301e1767ccc7d1f72e2412079e451a42db08807a", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8741.json b/mne-python/source/doc/sphinxext/prs/8741.json new file mode 100644 index 0000000000000000000000000000000000000000..fabacfe92c8c443c631648bff110f1960c4d368b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8741.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "203d6fe6e13e6f7beac5258368784f24fc084b73", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 18, + "d": 4 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 6, + "d": 1 + }, + "mne/viz/backends/_notebook.py": { + "a": 24, + "d": 9 + }, + "mne/viz/backends/_qt.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8742.json b/mne-python/source/doc/sphinxext/prs/8742.json new file mode 100644 index 0000000000000000000000000000000000000000..4ebe99c03abb481f170c159d7ee477b6d8a8be2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8742.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0c4db6f8ef12999d119085aa7c496cadb32411bd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8744.json b/mne-python/source/doc/sphinxext/prs/8744.json new file mode 100644 index 0000000000000000000000000000000000000000..c02812493e378a9a8b38ae6a9cfaab3611de9b69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8744.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d528da8e94f5b4754e529a194c7393958b7a493b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 58, + "d": 27 + }, + "mne/tests/test_report.py": { + "a": 47, + "d": 8 + }, + "server_environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8752.json b/mne-python/source/doc/sphinxext/prs/8752.json new file mode 100644 index 0000000000000000000000000000000000000000..1cbf898c743cf6790c39ec6cc85328f5def2b15c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8752.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3a83e2cc6b5323e7b8bf97d1f9b0daa3698c1f1d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8754.json b/mne-python/source/doc/sphinxext/prs/8754.json new file mode 100644 index 0000000000000000000000000000000000000000..8651d0143901d6787efbede38a35dcbc0e7ead6a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8754.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "63927883e90cd65bff4ee947edd6322b175d2ed6", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 3 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 3, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8757.json b/mne-python/source/doc/sphinxext/prs/8757.json new file mode 100644 index 0000000000000000000000000000000000000000..9ea9d84afc912de78e4302324176529871f0242e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8757.json @@ -0,0 +1,651 @@ +{ + "merge_commit_sha": "b1d4124b29bde8c5c0ea97fc0ac34d38eb05fb58", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Joris Van den Bossche", + "e": "jorisvandenbossche@gmail.com" + } + ], + "changes": { + ".mailmap": { + "a": 1, + "d": 0 + }, + "doc/_includes/bem_model.rst": { + "a": 1, + "d": 6 + }, + "doc/_includes/channel_interpolation.rst": { + "a": 0, + "d": 6 + }, + "doc/_includes/forward.rst": { + "a": 0, + "d": 9 + }, + "doc/_includes/inverse.rst": { + "a": 0, + "d": 9 + }, + "doc/_includes/morph.rst": { + "a": 0, + "d": 5 + }, + "doc/_includes/ssp.rst": { + "a": 1, + "d": 1 + }, + "doc/_static/flag-icon.css": { + "a": 0, + "d": 23 + }, + "doc/_static/font-awesome.css": { + "a": 0, + "d": 2337 + }, + "doc/_static/fonts/fontawesome/fontawesome-webfont.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/fontawesome/fontawesome-webfont.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/fontawesome/fontawesome-webfont.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/fontawesome/fontawesome-webfont.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-Light.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-LightIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-Light.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-LightIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-Light.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-LightIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-Light.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-LightIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fr.svg": { + "a": 0, + "d": 7 + }, + "doc/_static/mne_logo_small.svg": { + "a": 78, + "d": 66 + }, + "doc/_static/scrollfix.js": { + "a": 31, + "d": 0 + }, + "doc/_static/style.css": { + "a": 144, + "d": 550 + }, + "doc/_static/us.svg": { + "a": 0, + "d": 18 + }, + "doc/_templates/docs-navbar.html": { + "a": 68, + "d": 0 + }, + "doc/_templates/docs-toc.html": { + "a": 17, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 60, + "d": 74 + }, + "doc/_templates/navbar.html": { + "a": 0, + "d": 35 + }, + "doc/_templates/sidebar-funders.html": { + "a": 17, + "d": 0 + }, + "doc/_templates/sidebar-quicklinks.html": { + "a": 12, + "d": 0 + }, + "doc/bibliography.rst": { + "a": 4, + "d": 0 + }, + "doc/carousel.inc": { + "a": 0, + "d": 81 + }, + "doc/cited.rst": { + "a": 5, + "d": 7 + }, + "doc/conf.py": { + "a": 537, + "d": 486 + }, + "doc/connectivity.rst": { + "a": 20, + "d": 0 + }, + "doc/covariance.rst": { + "a": 19, + "d": 0 + }, + "doc/creating_from_arrays.rst": { + "a": 13, + "d": 0 + }, + "doc/datasets.rst": { + "a": 40, + "d": 0 + }, + "doc/decoding.rst": { + "a": 40, + "d": 0 + }, + "doc/events.rst": { + "a": 55, + "d": 0 + }, + "doc/file_io.rst": { + "a": 63, + "d": 0 + }, + "doc/forward.rst": { + "a": 60, + "d": 0 + }, + "doc/glossary.rst": { + "a": 85, + "d": 60 + }, + "doc/index.rst": { + "a": 21, + "d": 81 + }, + "doc/install/advanced.rst": { + "a": 29, + "d": 33 + }, + "doc/install/contributing.rst": { + "a": 7, + "d": 32 + }, + "doc/install/freesurfer.rst": { + "a": 0, + "d": 2 + }, + "doc/install/index.rst": { + "a": 33, + "d": 17 + }, + "doc/install/mne_c.rst": { + "a": 2, + "d": 4 + }, + "doc/install/mne_python.rst": { + "a": 15, + "d": 21 + }, + "doc/install/pre_install.rst": { + "a": 17, + "d": 19 + }, + "doc/inverse.rst": { + "a": 98, + "d": 0 + }, + "doc/logging.rst": { + "a": 47, + "d": 0 + }, + "doc/most_used_classes.rst": { + "a": 12, + "d": 0 + }, + "doc/mri.rst": { + "a": 24, + "d": 0 + }, + "doc/overview/cite.rst": { + "a": 35, + "d": 17 + }, + "doc/overview/cookbook.rst": { + "a": 11, + "d": 11 + }, + "doc/overview/datasets_index.rst": { + "a": 13, + "d": 18 + }, + "doc/overview/design_philosophy.rst": { + "a": 3, + "d": 3 + }, + "doc/overview/development.rst": { + "a": 28, + "d": 0 + }, + "doc/overview/faq.rst": { + "a": 2, + "d": 5 + }, + "doc/overview/get_help.rst": { + "a": 12, + "d": 7 + }, + "doc/overview/implementation.rst": { + "a": 0, + "d": 5 + }, + "doc/overview/index.rst": { + "a": 19, + "d": 21 + }, + "doc/overview/learn_python.rst": { + "a": 0, + "d": 2 + }, + "doc/overview/matlab.rst": { + "a": 0, + "d": 4 + }, + "doc/overview/roadmap.rst": { + "a": 0, + "d": 7 + }, + "doc/preprocessing.rst": { + "a": 181, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 33, + "d": 1099 + }, + "doc/reading_raw_data.rst": { + "a": 58, + "d": 0 + }, + "doc/realtime.rst": { + "a": 5, + "d": 0 + }, + "doc/references.bib": { + "a": 23, + "d": 1 + }, + "doc/references.rst": { + "a": 0, + "d": 70 + }, + "doc/report.rst": { + "a": 13, + "d": 0 + }, + "doc/sensor_space.rst": { + "a": 37, + "d": 0 + }, + "doc/simulation.rst": { + "a": 25, + "d": 0 + }, + "doc/source_space.rst": { + "a": 44, + "d": 0 + }, + "doc/sphinxext/gen_commands.py": { + "a": 0, + "d": 4 + }, + "doc/sphinxext/sphinx_bootstrap_divs/__init__.py": { + "a": 7, + "d": 7 + }, + "doc/sphinxext/sphinx_bootstrap_divs/bootstrap_divs.css": { + "a": 2, + "d": 2 + }, + "doc/sphinxext/sphinx_bootstrap_divs/bootstrap_divs.js": { + "a": 2, + "d": 2 + }, + "doc/statistics.rst": { + "a": 66, + "d": 0 + }, + "doc/time_frequency.rst": { + "a": 71, + "d": 0 + }, + "doc/upload_html.sh": { + "a": 0, + "d": 5 + }, + "doc/visualization.rst": { + "a": 78, + "d": 0 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/plot_source_power_spectrum_opm.py": { + "a": 0, + "d": 4 + }, + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 3, + "d": 3 + }, + "examples/visualization/plot_eeglab_head_sphere.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/plot_meg_sensors.py": { + "a": 0, + "d": 4 + }, + "examples/visualization/plot_publication_figure.py": { + "a": 0, + "d": 4 + }, + "examples/visualization/plot_roi_erpimage_by_rt.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 17, + "d": 10 + }, + "requirements_doc.txt": { + "a": 2, + "d": 3 + }, + "tools/generate_codemeta.py": { + "a": 1, + "d": 0 + }, + "tutorials/discussions/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/discussions/plot_background_filtering.py": { + "a": 0, + "d": 3 + }, + "tutorials/discussions/plot_background_ica.py": { + "a": 0, + "d": 4 + }, + "tutorials/discussions/plot_background_statistics.py": { + "a": 0, + "d": 5 + }, + "tutorials/epochs/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 0, + "d": 4 + }, + "tutorials/epochs/plot_20_visualize_epochs.py": { + "a": 0, + "d": 4 + }, + "tutorials/epochs/plot_30_epochs_metadata.py": { + "a": 0, + "d": 4 + }, + "tutorials/epochs/plot_40_epochs_to_data_frame.py": { + "a": 0, + "d": 4 + }, + "tutorials/evoked/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 1, + "d": 5 + }, + "tutorials/evoked/plot_20_visualize_evoked.py": { + "a": 1, + "d": 5 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 0, + "d": 4 + }, + "tutorials/intro/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/intro/plot_10_overview.py": { + "a": 0, + "d": 4 + }, + "tutorials/intro/plot_20_events_from_raw.py": { + "a": 0, + "d": 4 + }, + "tutorials/intro/plot_30_info.py": { + "a": 0, + "d": 4 + }, + "tutorials/intro/plot_40_sensor_locations.py": { + "a": 1, + "d": 5 + }, + "tutorials/intro/plot_50_configure_mne.py": { + "a": 0, + "d": 4 + }, + "tutorials/io/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/io/plot_10_reading_meg_data.py": { + "a": 0, + "d": 5 + }, + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 0, + "d": 5 + }, + "tutorials/io/plot_30_reading_fnirs_data.py": { + "a": 0, + "d": 5 + }, + "tutorials/machine-learning/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/plot_sensors_decoding.py": { + "a": 0, + "d": 4 + }, + "tutorials/misc/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/misc/plot_report.py": { + "a": 0, + "d": 4 + }, + "tutorials/preprocessing/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/plot_10_preprocessing_overview.py": { + "a": 0, + "d": 4 + }, + "tutorials/preprocessing/plot_15_handling_bad_channels.py": { + "a": 1, + "d": 5 + }, + "tutorials/preprocessing/plot_20_rejecting_bad_data.py": { + "a": 0, + "d": 4 + }, + "tutorials/preprocessing/plot_30_filtering_resampling.py": { + "a": 0, + "d": 4 + }, + "tutorials/preprocessing/plot_35_artifact_correction_regression.py": { + "a": 0, + "d": 4 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 0, + "d": 4 + }, + "tutorials/preprocessing/plot_45_projectors_background.py": { + "a": 1, + "d": 5 + }, + "tutorials/preprocessing/plot_50_artifact_correction_ssp.py": { + "a": 0, + "d": 4 + }, + "tutorials/preprocessing/plot_55_setting_eeg_reference.py": { + "a": 0, + "d": 4 + }, + "tutorials/preprocessing/plot_60_maxwell_filtering_sss.py": { + "a": 1, + "d": 5 + }, + "tutorials/preprocessing/plot_70_fnirs_processing.py": { + "a": 0, + "d": 4 + }, + "tutorials/raw/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/raw/plot_10_raw_overview.py": { + "a": 0, + "d": 4 + }, + "tutorials/raw/plot_20_event_arrays.py": { + "a": 0, + "d": 4 + }, + "tutorials/raw/plot_30_annotate_raw.py": { + "a": 0, + "d": 4 + }, + "tutorials/raw/plot_40_visualize_raw.py": { + "a": 0, + "d": 4 + }, + "tutorials/sample-datasets/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 0, + "d": 4 + }, + "tutorials/simulation/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/simulation/plot_creating_data_structures.py": { + "a": 0, + "d": 4 + }, + "tutorials/source-modeling/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_background_freesurfer.py": { + "a": 0, + "d": 3 + }, + "tutorials/source-modeling/plot_background_freesurfer_mne.py": { + "a": 0, + "d": 3 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 0, + "d": 5 + }, + "tutorials/source-modeling/plot_compute_covariance.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_eeg_mri_coords.py": { + "a": 0, + "d": 5 + }, + "tutorials/source-modeling/plot_eeg_no_mri.py": { + "a": 6, + "d": 9 + }, + "tutorials/source-modeling/plot_object_source_estimate.py": { + "a": 0, + "d": 3 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 0, + "d": 4 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 1, + "d": 4 + }, + "tutorials/stats-sensor-space/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/stats-source-space/README.txt": { + "a": 1, + "d": 1 + }, + "tutorials/time-freq/README.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8758.json b/mne-python/source/doc/sphinxext/prs/8758.json new file mode 100644 index 0000000000000000000000000000000000000000..960c8bfb4acf8031855887a5dd902af02d0db5a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8758.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "baaf9e33f2b54f6a40454a8aa146577bde1d6f58", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 7, + "d": 7 + }, + "CONTRIBUTING.rst": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 9, + "d": 9 + }, + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/_includes/forward.rst": { + "a": 1, + "d": 1 + }, + "doc/_templates/layout.html": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/glossary.rst": { + "a": 1, + "d": 1 + }, + "doc/install/advanced.rst": { + "a": 6, + "d": 6 + }, + "doc/install/contributing.rst": { + "a": 17, + "d": 17 + }, + "doc/install/mne_python.rst": { + "a": 4, + "d": 4 + }, + "doc/links.inc": { + "a": 1, + "d": 1 + }, + "doc/overview/faq.rst": { + "a": 1, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_fetching.py": { + "a": 1, + "d": 1 + }, + "tools/circleci_download.sh": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8759.json b/mne-python/source/doc/sphinxext/prs/8759.json new file mode 100644 index 0000000000000000000000000000000000000000..9adc21025284428d2096ee370d4879899cfc9c94 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8759.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "5feaee815b65ad4bf779987ee2ff9c5b154720c9", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 22, + "d": 12 + }, + "mne/io/egi/egi.py": { + "a": 10, + "d": 4 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/876.json b/mne-python/source/doc/sphinxext/prs/876.json new file mode 100644 index 0000000000000000000000000000000000000000..e4e0db6943787396c7b3ad6b4487005f32ebd4f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/876.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6626d2e6c29607636115640a81530d5870ff6531", + "authors": [ + { + "n": "Andrew R. Dykstra", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_viz.py": { + "a": 1, + "d": 1 + }, + "mne/viz.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8760.json b/mne-python/source/doc/sphinxext/prs/8760.json new file mode 100644 index 0000000000000000000000000000000000000000..765cb901c6f9a2008fb9a21602f0b93ec9d62a0b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8760.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "51fd3cd93f2017c7c30ac6f47c43ae38c4d7603b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 87, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 40, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8762.json b/mne-python/source/doc/sphinxext/prs/8762.json new file mode 100644 index 0000000000000000000000000000000000000000..4f8fbb6a9ce99985a7a17152fa10ce50ae5c7034 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8762.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "52011825822c9c79ded515c952077176f309e56e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 16, + "d": 0 + }, + "mne/tests/test_report.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8763.json b/mne-python/source/doc/sphinxext/prs/8763.json new file mode 100644 index 0000000000000000000000000000000000000000..f886dadc6629dbf87fd6cb3859ad8de8f2b12409 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8763.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a46546ba86bfea5903d306b5598ca20b9aa6296d", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/glossary.rst": { + "a": 16, + "d": 3 + }, + "examples/visualization/plot_eeglab_head_sphere.py": { + "a": 2, + "d": 3 + }, + "tutorials/intro/plot_40_sensor_locations.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8768.json b/mne-python/source/doc/sphinxext/prs/8768.json new file mode 100644 index 0000000000000000000000000000000000000000..71fa9926e45282e19c95b4cd08901481f5642ca8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8768.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "94a75a5c6c4124c950d96c9eec7e1d69c068b7ef", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/event.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8769.json b/mne-python/source/doc/sphinxext/prs/8769.json new file mode 100644 index 0000000000000000000000000000000000000000..81746c6a5af33000208becde8b60ae8ed0f9a304 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8769.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9a2031897735de9b7ffc0a9658b7c4f89b36d88c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 31, + "d": 54 + }, + "mne/viz/backends/_pyvista.py": { + "a": 180, + "d": 192 + }, + "mne/viz/backends/_utils.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8770.json b/mne-python/source/doc/sphinxext/prs/8770.json new file mode 100644 index 0000000000000000000000000000000000000000..cdf3bbcee119813d4806aeeba2f9a5ef580e673d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8770.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "250eabfb3e5ca4806d302d6de12935daea418cc6", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8771.json b/mne-python/source/doc/sphinxext/prs/8771.json new file mode 100644 index 0000000000000000000000000000000000000000..2473edd88ee6fcbad6d8441690848f23aa16de85 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8771.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "fa779fc945dba0b77c466ad91aefe213a5be9681", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 10, + "d": 8 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 12, + "d": 5 + }, + "mne/viz/_brain/_brain.py": { + "a": 28, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 6, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 1 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 2, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8774.json b/mne-python/source/doc/sphinxext/prs/8774.json new file mode 100644 index 0000000000000000000000000000000000000000..b694d470420739e0b6d4543d537313fc8b7940d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8774.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ae8a466051a43ac929eaf23e02b40c27a6d62e1a", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 11, + "d": 3 + }, + "mne/viz/tests/test_evoked.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8775.json b/mne-python/source/doc/sphinxext/prs/8775.json new file mode 100644 index 0000000000000000000000000000000000000000..030a9daada99c6ff999282206175d2baed013af7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8775.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "21b3c10445675b9578f2efd11b76719a74402587", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "doc/references.bib": { + "a": 45, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 30, + "d": 8 + }, + "mne/viz/tests/test_evoked.py": { + "a": 41, + "d": 17 + }, + "tutorials/evoked/plot_20_visualize_evoked.py": { + "a": 6, + "d": 1 + }, + "tutorials/evoked/plot_eeg_erp.py": { + "a": 47, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8777.json b/mne-python/source/doc/sphinxext/prs/8777.json new file mode 100644 index 0000000000000000000000000000000000000000..b30336c122ea685567745cb2061ab39969c76a4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8777.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "33f76fae73f37dac8b402fcf6dd4899e8eafe1c8", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/bem.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8778.json b/mne-python/source/doc/sphinxext/prs/8778.json new file mode 100644 index 0000000000000000000000000000000000000000..f62a919161da12df77e85371535907bba10bd05a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8778.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6ae3b22033c745cce5cd5de9b92da54c13c36484", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 0, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 11 + }, + "mne/viz/tests/test_evoked.py": { + "a": 0, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8780.json b/mne-python/source/doc/sphinxext/prs/8780.json new file mode 100644 index 0000000000000000000000000000000000000000..2592d5d3e90948d55b4d003deefc2d63aec09e2c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8780.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f70f508a1bd5f73bdb4797e657340c11cc138d64", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 24, + "d": 8 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 29, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8783.json b/mne-python/source/doc/sphinxext/prs/8783.json new file mode 100644 index 0000000000000000000000000000000000000000..a9e2ddba43fc3af67aa2e1c1192a4e62b559a819 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8783.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9db75c108ae2d475050c395e57dd0062f78ee44d", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 21, + "d": 9 + }, + "mne/tests/test_annotations.py": { + "a": 22, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8787.json b/mne-python/source/doc/sphinxext/prs/8787.json new file mode 100644 index 0000000000000000000000000000000000000000..18355f9a6b6c83494c2cbbe983373122a1827a3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8787.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d8d5474fa5ce7b81b3abef0359235e231f39a53b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8789.json b/mne-python/source/doc/sphinxext/prs/8789.json new file mode 100644 index 0000000000000000000000000000000000000000..e489a2e172f48fc34af5233dde68b2a11e429ffa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8789.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a36c74f8b88b93e41806c14465ff1308bf585c4a", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/egi/egimff.py": { + "a": 47, + "d": 10 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8790.json b/mne-python/source/doc/sphinxext/prs/8790.json new file mode 100644 index 0000000000000000000000000000000000000000..92ee01fb53c4fb28fdb3896627d9106aea5bf493 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8790.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b45fc5cdb83114ed855b5aed7fd2a0c3a01d4cb5", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/gui/_file_traits.py": { + "a": 74, + "d": 64 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 20, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8792.json b/mne-python/source/doc/sphinxext/prs/8792.json new file mode 100644 index 0000000000000000000000000000000000000000..60bb0ad796ea9f4a2ce8276096d9122ad38998c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8792.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "74a7f32d561e84f918a4f42bd6471d204cafe2f9", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 59, + "d": 4 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8793.json b/mne-python/source/doc/sphinxext/prs/8793.json new file mode 100644 index 0000000000000000000000000000000000000000..852443269eb23d6853ebbedad086f2a09fb88360 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8793.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "9fc8623eebd62d31039e90927744e376f5ee611c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.9.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/commands/mne_surf2bem.py": { + "a": 1, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 12, + "d": 2 + }, + "mne/gui/_coreg_gui.py": { + "a": 26, + "d": 10 + }, + "mne/gui/_fiducials_gui.py": { + "a": 21, + "d": 53 + }, + "mne/gui/_viewer.py": { + "a": 4, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8794.json b/mne-python/source/doc/sphinxext/prs/8794.json new file mode 100644 index 0000000000000000000000000000000000000000..98e5d1967b04b9e05ad0ebf66d0f9d7fdfd4c0ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8794.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "982b0e093865ec4cc8116c47a1fc7349fbdf682e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/label.py": { + "a": 10, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 45, + "d": 11 + }, + "mne/viz/_brain/surface.py": { + "a": 15, + "d": 15 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 21, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8799.json b/mne-python/source/doc/sphinxext/prs/8799.json new file mode 100644 index 0000000000000000000000000000000000000000..6d3195028d200e24786a63b6e65c90d777568749 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8799.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "bd72072b1ff4690cdb2c4a7b36a15c93e25e8fee", + "authors": [ + { + "n": "ZHANG Zhi", + "e": "zhi271.zhang@connect.polyu.hk" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 25, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 29, + "d": 0 + }, + "mne/io/constants.py": { + "a": 20, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 3, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/88.json b/mne-python/source/doc/sphinxext/prs/88.json new file mode 100644 index 0000000000000000000000000000000000000000..08da019862922b251c7cfd96d5fa77a325f8e381 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/88.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "04188fbd948cf7dac0bae3035d83e9b236c5a04f", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_dipole_fit_result.py": { + "a": 76, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/dipole.py": { + "a": 40, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/880.json b/mne-python/source/doc/sphinxext/prs/880.json new file mode 100644 index 0000000000000000000000000000000000000000..1b2d12bfb456b3a9cb1c5c9d0b777e4c42d953e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/880.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d34a4b09382ff764a9ab4c7216b71740a1253206", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "setup.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8800.json b/mne-python/source/doc/sphinxext/prs/8800.json new file mode 100644 index 0000000000000000000000000000000000000000..72ea4607b770bdc5b5a205f464ff8073b60311a8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8800.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cff4c3709aaa9f2a50e10fca29c199cd2f5bb526", + "authors": [ + { + "n": "Yu-Han Luo", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8801.json b/mne-python/source/doc/sphinxext/prs/8801.json new file mode 100644 index 0000000000000000000000000000000000000000..47a1f333ce813b49ef8c6bb61313f6f3f7b8be37 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8801.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "59429c3b8022f61cf3539dc421cadff4ab675d24", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/baseline.py": { + "a": 5, + "d": 3 + }, + "mne/conftest.py": { + "a": 22, + "d": 13 + }, + "mne/epochs.py": { + "a": 32, + "d": 21 + }, + "mne/forward/forward.py": { + "a": 0, + "d": 1 + }, + "mne/io/base.py": { + "a": 20, + "d": 17 + }, + "mne/io/pick.py": { + "a": 7, + "d": 12 + }, + "mne/preprocessing/ica.py": { + "a": 11, + "d": 20 + }, + "mne/preprocessing/realign.py": { + "a": 0, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 18 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 0, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 10, + "d": 3 + }, + "mne/utils/numerics.py": { + "a": 19, + "d": 1 + }, + "mne/utils/tests/test_numerics.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8804.json b/mne-python/source/doc/sphinxext/prs/8804.json new file mode 100644 index 0000000000000000000000000000000000000000..1074b24376a36b73bb4db69060b7d956cfbb4d4a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8804.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "f31643185741aa6e46ef4869673e5178740c4980", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 17, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 13, + "d": 4 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 3, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8805.json b/mne-python/source/doc/sphinxext/prs/8805.json new file mode 100644 index 0000000000000000000000000000000000000000..4de5cd7e92075bbfc821ba75f3cbcc7022e2001c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8805.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "7e867ce57cc035c32f1362734031d250b2ac0734", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 23, + "d": 12 + }, + "mne/rank.py": { + "a": 53, + "d": 15 + }, + "mne/tests/test_cov.py": { + "a": 28, + "d": 8 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 6, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 13, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 7, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8806.json b/mne-python/source/doc/sphinxext/prs/8806.json new file mode 100644 index 0000000000000000000000000000000000000000..cb488304c18b492a247628d8eeb6e7fa0d260a50 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8806.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "9b57cbd8ec711e3af33846e62ad7d1fbbdcaf5cd", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Andres Rodriguez", + "e": "rodriguezandr@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Andres Rodriguez", + "e": "rodriguezandr@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/persyst/persyst.py": { + "a": 63, + "d": 15 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 64, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8807.json b/mne-python/source/doc/sphinxext/prs/8807.json new file mode 100644 index 0000000000000000000000000000000000000000..835348689d1083c319f20011279aa4e8a3592263 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8807.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c5c6d2306194393cbbbc4d7235d9dcc91d3851bc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 7, + "d": 2 + }, + "mne/io/_read_raw.py": { + "a": 20, + "d": 17 + }, + "mne/io/tests/test_read_raw.py": { + "a": 12, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 5, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8808.json b/mne-python/source/doc/sphinxext/prs/8808.json new file mode 100644 index 0000000000000000000000000000000000000000..e347f98070f1097f8b73aea007dde6287356727a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8808.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d8201c9bbb2ade3e20dae0284f0333a80a62d3a9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 5, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 23, + "d": 18 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 6, + "d": 4 + }, + "mne/viz/tests/test_3d.py": { + "a": 41, + "d": 20 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8809.json b/mne-python/source/doc/sphinxext/prs/8809.json new file mode 100644 index 0000000000000000000000000000000000000000..d03b7b432b31b1a0c87c26957bbe0003748dd774 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8809.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "32402f9000aba9ca7ad62fc0439ba8a8c9f8020f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/tests/test_datasets.py": { + "a": 13, + "d": 9 + }, + "mne/datasets/utils.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/881.json b/mne-python/source/doc/sphinxext/prs/881.json new file mode 100644 index 0000000000000000000000000000000000000000..caf0a9bf89d7d17469d99d24afeacaa3bfcd9c19 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/881.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7883ecbb4c81e076be6bd514cb81b4847947e8f8", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 18, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8811.json b/mne-python/source/doc/sphinxext/prs/8811.json new file mode 100644 index 0000000000000000000000000000000000000000..de219cf14ba8b6630337fa2f5b4659c1fbe2ccac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8811.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5a6688b94f97d365a0abf256d86109d6a092cc6a", + "authors": [ + { + "n": "Christopher J. Bailey", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8813.json b/mne-python/source/doc/sphinxext/prs/8813.json new file mode 100644 index 0000000000000000000000000000000000000000..ba95ed05b8342c686929b0d08b311cee52a80997 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8813.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "d4a1ce5d8a7f5db605543f09d29ccdd1ec92676f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "monkeyman192", + "e": "monkey_man_192@yahoo.com.au" + }, + { + "n": "monkeyman192", + "e": "monkey_man_192@yahoo.com.au" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 5, + "d": 1 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 89, + "d": 5 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 0 + }, + "mne/io/kit/coreg.py": { + "a": 18, + "d": 9 + }, + "mne/io/kit/kit.py": { + "a": 13, + "d": 7 + }, + "mne/tests/test_chpi.py": { + "a": 40, + "d": 15 + }, + "mne/viz/_3d.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8817.json b/mne-python/source/doc/sphinxext/prs/8817.json new file mode 100644 index 0000000000000000000000000000000000000000..3a8e190676b11f1d0b6e5b57ab6340028e8bcd20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8817.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9069a696fa9b55e3376cb8f4f013b8e8a40c1929", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 13, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8818.json b/mne-python/source/doc/sphinxext/prs/8818.json new file mode 100644 index 0000000000000000000000000000000000000000..98710dbd8fa361ecf274b4c7a3b1ba3d51cceb68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8818.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dbe91585fb505de2acf9ade215aa05bb1400c5bb", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 14, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8819.json b/mne-python/source/doc/sphinxext/prs/8819.json new file mode 100644 index 0000000000000000000000000000000000000000..f96beb8d9811538f65004cec46c0d338665a4616 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8819.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "02572faaeba4c8e33f0e7cde0f4a336224271d8b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/tests/test_edf.py": { + "a": 7, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 10, + "d": 2 + }, + "mne/utils/tests/test_testing.py": { + "a": 10, + "d": 13 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 5, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/882.json b/mne-python/source/doc/sphinxext/prs/882.json new file mode 100644 index 0000000000000000000000000000000000000000..a363ec5784d945c325a1b5569b95ea3ac3b06671 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/882.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "d9c062402b7a5efb89d606e132b1f70b91325eb8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/bti/raw.py": { + "a": 18, + "d": 16 + }, + "mne/fiff/bti/tests/test_bti.py": { + "a": 4, + "d": 3 + }, + "mne/fiff/kit/kit.py": { + "a": 8, + "d": 6 + }, + "mne/fiff/kit/tests/data/trans-sample.fif": { + "a": 0, + "d": 0 + }, + "mne/fiff/kit/tests/test_kit.py": { + "a": 3, + "d": 0 + }, + "mne/fiff/pick.py": { + "a": 12, + "d": 0 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/tag.py": { + "a": 11, + "d": 6 + }, + "mne/fiff/write.py": { + "a": 11, + "d": 7 + }, + "mne/forward/_make_forward.py": { + "a": 30, + "d": 12 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 76, + "d": 25 + }, + "mne/source_space.py": { + "a": 12, + "d": 0 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8820.json b/mne-python/source/doc/sphinxext/prs/8820.json new file mode 100644 index 0000000000000000000000000000000000000000..59f3e63a517c23c33b8bda6c17a0605ccc6f12cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8820.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9458a30bacc5fa96ca56c3a31b4cceb5925990a7", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 10, + "d": 6 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8821.json b/mne-python/source/doc/sphinxext/prs/8821.json new file mode 100644 index 0000000000000000000000000000000000000000..ab3bdd97355eafa227c96707c77b55fc54758e9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8821.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "6bcf041825abde39aefce603022f900c0be80024", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 40, + "d": 11 + }, + "mne/tests/test_epochs.py": { + "a": 37, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8822.json b/mne-python/source/doc/sphinxext/prs/8822.json new file mode 100644 index 0000000000000000000000000000000000000000..d4c2741cd288502903509190424b5700584c6f80 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8822.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "1bc407a2814edd0537b08c6ffdbc8fbd60749bce", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 68, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 31, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8823.json b/mne-python/source/doc/sphinxext/prs/8823.json new file mode 100644 index 0000000000000000000000000000000000000000..892cea5cf597ffae5194333c3b971e79f61e8799 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8823.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "971c290a0dd2fc564607c6eeff042bde371e3608", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 17, + "d": 1 + }, + "mne/annotations.py": { + "a": 7, + "d": 1 + }, + "mne/bem.py": { + "a": 5, + "d": 10 + }, + "mne/coreg.py": { + "a": 2, + "d": 5 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 19, + "d": 17 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 6, + "d": 2 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 7, + "d": 5 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 7, + "d": 6 + }, + "mne/decoding/base.py": { + "a": 0, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 3, + "d": 2 + }, + "mne/dipole.py": { + "a": 0, + "d": 1 + }, + "mne/epochs.py": { + "a": 7, + "d": 4 + }, + "mne/event.py": { + "a": 11, + "d": 5 + }, + "mne/fixes.py": { + "a": 21, + "d": 20 + }, + "mne/io/base.py": { + "a": 0, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 2 + }, + "mne/label.py": { + "a": 16, + "d": 5 + }, + "mne/preprocessing/_regress.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 3, + "d": 2 + }, + "mne/report.py": { + "a": 7, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 2, + "d": 2 + }, + "mne/utils/mixin.py": { + "a": 0, + "d": 1 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8827.json b/mne-python/source/doc/sphinxext/prs/8827.json new file mode 100644 index 0000000000000000000000000000000000000000..75ae44a2b49e1626c35febcc9a82dba7b8c1c8c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8827.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8178cca9fa63011b4113b9f84a7bbe8a5a06285d", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "mne/chpi.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8828.json b/mne-python/source/doc/sphinxext/prs/8828.json new file mode 100644 index 0000000000000000000000000000000000000000..6a713bc8326afbfbd0217366350a24160c413768 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8828.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2f7df8843401433b28af0278666fe629fd9f0c28", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 8 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 6, + "d": 4 + }, + "mne/viz/backends/_utils.py": { + "a": 11, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8829.json b/mne-python/source/doc/sphinxext/prs/8829.json new file mode 100644 index 0000000000000000000000000000000000000000..55057f655172da08df16e8b078925767e1ddfd9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8829.json @@ -0,0 +1,323 @@ +{ + "merge_commit_sha": "0735446dd5bfe265346d08aa64d6b7cee680cff8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 7, + "d": 7 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/_rap_music.py": { + "a": 4, + "d": 2 + }, + "mne/bem.py": { + "a": 2, + "d": 2 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 3, + "d": 3 + }, + "mne/connectivity/spectral.py": { + "a": 2, + "d": 1 + }, + "mne/cov.py": { + "a": 2, + "d": 1 + }, + "mne/cuda.py": { + "a": 3, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 3, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ssd.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 2, + "d": 1 + }, + "mne/dipole.py": { + "a": 14, + "d": 4 + }, + "mne/externals/h5io/_h5io.py": { + "a": 11, + "d": 5 + }, + "mne/filter.py": { + "a": 3, + "d": 1 + }, + "mne/fixes.py": { + "a": 28, + "d": 8 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 2, + "d": 1 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 2, + "d": 3 + }, + "mne/inverse_sparse/_gamma_map.py": { + "a": 4, + "d": 5 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 4, + "d": 5 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 19, + "d": 13 + }, + "mne/io/compensator.py": { + "a": 1, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 2, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 2 + }, + "mne/io/open.py": { + "a": 1, + "d": 1 + }, + "mne/io/proc_history.py": { + "a": 2, + "d": 2 + }, + "mne/io/proj.py": { + "a": 2, + "d": 2 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 2, + "d": 2 + }, + "mne/label.py": { + "a": 3, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 2, + "d": 3 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 9, + "d": 4 + }, + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 3 + }, + "mne/preprocessing/ica.py": { + "a": 3, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/xdawn.py": { + "a": 2, + "d": 1 + }, + "mne/proj.py": { + "a": 3, + "d": 3 + }, + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/metrics.py": { + "a": 1, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 8, + "d": 3 + }, + "mne/source_space.py": { + "a": 6, + "d": 3 + }, + "mne/stats/_adjacency.py": { + "a": 1, + "d": 1 + }, + "mne/stats/cluster_level.py": { + "a": 4, + "d": 1 + }, + "mne/stats/regression.py": { + "a": 3, + "d": 2 + }, + "mne/surface.py": { + "a": 4, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_import_nesting.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/_stft.py": { + "a": 4, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 14, + "d": 10 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 3, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 4, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 5 + }, + "mne/transforms.py": { + "a": 8, + "d": 6 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/utils/_logging.py": { + "a": 2, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 51, + "d": 6 + }, + "mne/utils/fetching.py": { + "a": 4, + "d": 2 + }, + "mne/utils/linalg.py": { + "a": 40, + "d": 35 + }, + "mne/utils/numerics.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/883.json b/mne-python/source/doc/sphinxext/prs/883.json new file mode 100644 index 0000000000000000000000000000000000000000..42fcf7e927b3d5323332a82cd4485fe52846ef3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/883.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b658f0636df1f118c1831eab4aac72bfd08608e4", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/kit/kit.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8831.json b/mne-python/source/doc/sphinxext/prs/8831.json new file mode 100644 index 0000000000000000000000000000000000000000..548c2c4b2f0248d395554eb9d76dac7921a679f6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8831.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "74750e6b53a26e92a0d509c8458790b5d42d5117", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 5, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 16, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8834.json b/mne-python/source/doc/sphinxext/prs/8834.json new file mode 100644 index 0000000000000000000000000000000000000000..064eb6824ecf567ee3da0ec37bd14ce7cef8fc7b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8834.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "91f60810771db6cc24268be18eb910161779dea2", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/datasets.rst": { + "a": 1, + "d": 0 + }, + "doc/events.rst": { + "a": 1, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 26, + "d": 0 + }, + "doc/references.bib": { + "a": 13, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 3, + "d": 2 + }, + "mne/datasets/erp_core/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/erp_core/erp_core.py": { + "a": 26, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 13, + "d": 5 + }, + "mne/epochs.py": { + "a": 295, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 76, + "d": 2 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "tools/circleci_download.sh": { + "a": 3, + "d": 0 + }, + "tutorials/epochs/plot_40_autogenerate_metadata.py": { + "a": 432, + "d": 0 + }, + "tutorials/epochs/plot_50_epochs_to_data_frame.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8835.json b/mne-python/source/doc/sphinxext/prs/8835.json new file mode 100644 index 0000000000000000000000000000000000000000..f5c293c3b1edd65af8b5dfdea24b8adddb41fb65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8835.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7b6b2c53d6f14fee8fa4515b9ca2a30ec0e7daeb", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + } + ], + "changes": { + "mne/viz/backends/renderer.py": { + "a": 45, + "d": 45 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8838.json b/mne-python/source/doc/sphinxext/prs/8838.json new file mode 100644 index 0000000000000000000000000000000000000000..c52e7c910cc673a6d5f2385f21b8dc2750d240a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8838.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fa83dadb9cd2d3607b91638aedd5b400059b149f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "codecov.yml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8839.json b/mne-python/source/doc/sphinxext/prs/8839.json new file mode 100644 index 0000000000000000000000000000000000000000..9372170d437009a372995c0d91095d7f695a7ff2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8839.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c5f58fb48972127dcfc262a10591de2d7e390e98", + "authors": [ + { + "n": "apadee", + "e": "anna.padee@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/connectivity/spectral.py": { + "a": 25, + "d": 14 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 46, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/884.json b/mne-python/source/doc/sphinxext/prs/884.json new file mode 100644 index 0000000000000000000000000000000000000000..dc82f3831c7757b67baf9256972bdb913e6acc58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/884.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "73a35fb025e7656901ecad508da5167744d5ecd3", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/forward/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8841.json b/mne-python/source/doc/sphinxext/prs/8841.json new file mode 100644 index 0000000000000000000000000000000000000000..72aa205dab6e2cdb90830549613bfcdc276d61c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8841.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "19fb479de44865d5ce79ad5af539a06081fae0c5", + "authors": [ + { + "n": "Yu-Han Luo", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 31, + "d": 2 + }, + "mne/tests/test_bem.py": { + "a": 29, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 0 + }, + "tutorials/source-modeling/plot_fix_bem_in_blender.py": { + "a": 78, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8842.json b/mne-python/source/doc/sphinxext/prs/8842.json new file mode 100644 index 0000000000000000000000000000000000000000..e7e7fe81e4aee8b5f059e0d778291a14d6645c6b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8842.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "a3719e58b8b8891e58571ac01513916964e8002d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/stats/cluster_level.py": { + "a": 15, + "d": 6 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 41, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 9, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8843.json b/mne-python/source/doc/sphinxext/prs/8843.json new file mode 100644 index 0000000000000000000000000000000000000000..1eaa52b8666170bf512832efec2dcfe2df2a50a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8843.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bf57aa0fa63e1605355b4f89b76cadb6e88b94ff", + "authors": [ + { + "n": "Manorama Kadwani", + "e": "54645550+mkadwani@users.noreply.github.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/source-modeling/plot_fix_bem_in_blender.py": { + "a": 66, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8844.json b/mne-python/source/doc/sphinxext/prs/8844.json new file mode 100644 index 0000000000000000000000000000000000000000..fb26e94d19fb84ab0b4eefd20e61fad599d909b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8844.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3034b4d2384f652cad4a44205a3db904620c20ec", + "authors": [ + { + "n": "enricovara", + "e": "enricovarano@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8845.json b/mne-python/source/doc/sphinxext/prs/8845.json new file mode 100644 index 0000000000000000000000000000000000000000..740bb2ef14b75cce04fb85bf08ec116a727a3390 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8845.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c304072d1c67912da9b4ac62fe64e07ed41f2dd6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8846.json b/mne-python/source/doc/sphinxext/prs/8846.json new file mode 100644 index 0000000000000000000000000000000000000000..c6fa659c78d65e9a4545438491e6da5b6ec812fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8846.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4f5ccc3e3af7f3bd1dad8589f8639e33051f7b6f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 18, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8847.json b/mne-python/source/doc/sphinxext/prs/8847.json new file mode 100644 index 0000000000000000000000000000000000000000..45bb4fb1db9ba14a35c06c325402331f513fc396 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8847.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d8ce89703471bec29a43d3413ec69587625720b5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/linux_conda.yml": { + "a": 3, + "d": 0 + }, + ".github/workflows/linux_pip.yml": { + "a": 3, + "d": 0 + }, + ".github/workflows/macos_conda.yml": { + "a": 3, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 0, + "d": 6 + }, + "tools/get_minimal_commands.sh": { + "a": 29, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8849.json b/mne-python/source/doc/sphinxext/prs/8849.json new file mode 100644 index 0000000000000000000000000000000000000000..c6abc1d942e6655853429a460b64edd6d2a927ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8849.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6a7d660b72b3535ada54517c3a60f8d11bd6578a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 3 + }, + "tools/get_minimal_commands.sh": { + "a": 58, + "d": 44 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/885.json b/mne-python/source/doc/sphinxext/prs/885.json new file mode 100644 index 0000000000000000000000000000000000000000..b171a56eda5107353ebda8371880f328da1de029 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/885.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2d903aa84fbcd719a17032dc4a7e8dcfdd54fb9d", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/tests/test_transforms.py": { + "a": 17, + "d": 1 + }, + "mne/transforms.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8851.json b/mne-python/source/doc/sphinxext/prs/8851.json new file mode 100644 index 0000000000000000000000000000000000000000..648e30183de1539bc1ab35db50819d27ab14a418 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8851.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9c7bb88b324e8c94df0538fd7e165f8b469ace5f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8852.json b/mne-python/source/doc/sphinxext/prs/8852.json new file mode 100644 index 0000000000000000000000000000000000000000..455f7134971362ccab6c108cd4dae56cb424d39f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8852.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5faf63705cd795a846f305d9545fc2fd72b1fdee", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + }, + "tutorials/stats-source-space/plot_stats_cluster_spatio_temporal.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8856.json b/mne-python/source/doc/sphinxext/prs/8856.json new file mode 100644 index 0000000000000000000000000000000000000000..39a696b874e7a9bd721c96ce0d608be32d5a74da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8856.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2c6b0dd6407c7c6b30f4a2437d85b88edbe08c62", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8857.json b/mne-python/source/doc/sphinxext/prs/8857.json new file mode 100644 index 0000000000000000000000000000000000000000..15d26406f33918c7660a5fe79f41c4e5c891c98c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8857.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "851885cb713b7e5b44775d40efdc4ad935ff1aa9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/bem.py": { + "a": 99, + "d": 47 + }, + "mne/dipole.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 7, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 5, + "d": 20 + }, + "mne/viz/_3d.py": { + "a": 33, + "d": 93 + }, + "mne/viz/tests/test_3d.py": { + "a": 8, + "d": 3 + }, + "tutorials/sample-datasets/plot_brainstorm_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8858.json b/mne-python/source/doc/sphinxext/prs/8858.json new file mode 100644 index 0000000000000000000000000000000000000000..021bbcdb345712780b533b4fe88e23f6b12d5c32 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8858.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "97dc6e18e06bc39072db37b63feff51b76a413e8", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 7, + "d": 1 + }, + "mne/io/pick.py": { + "a": 4, + "d": 4 + }, + "tutorials/sample-datasets/plot_sleep.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8860.json b/mne-python/source/doc/sphinxext/prs/8860.json new file mode 100644 index 0000000000000000000000000000000000000000..4cee7e803f61d6c9399fad8df005ff1baa8f7574 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8860.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7efad3b52c7b79460b5aa05475e1287c2c6acc4e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/_peak_finder.py": { + "a": 4, + "d": 3 + }, + "mne/preprocessing/eog.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8861.json b/mne-python/source/doc/sphinxext/prs/8861.json new file mode 100644 index 0000000000000000000000000000000000000000..96148d9f93b503e63b0aa46ff4ad65ccb6c88beb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8861.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "204720ea7b92831cdf2ca15602d96cf3839e85b4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/plot_sensor_connectivity.py": { + "a": 2, + "d": 3 + }, + "mne/connectivity/spectral.py": { + "a": 19, + "d": 10 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 17, + "d": 2 + }, + "mne/utils/_logging.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8862.json b/mne-python/source/doc/sphinxext/prs/8862.json new file mode 100644 index 0000000000000000000000000000000000000000..cf3ce0717754f13a0bc077a7a2eef687fed8311b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8862.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "940a1fe97be5744bae9eba21b8aafbef02cd2a13", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".coveragerc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 372, + "d": 370 + }, + "mne/viz/_brain/_linkviewer.py": { + "a": 25, + "d": 25 + }, + "mne/viz/_brain/callback.py": { + "a": 94, + "d": 112 + }, + "mne/viz/_brain/tests/test.ipynb": { + "a": 3, + "d": 3 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 23, + "d": 20 + }, + "mne/viz/backends/_abstract.py": { + "a": 92, + "d": 6 + }, + "mne/viz/backends/_notebook.py": { + "a": 201, + "d": 39 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 45 + }, + "mne/viz/backends/_qt.py": { + "a": 251, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8863.json b/mne-python/source/doc/sphinxext/prs/8863.json new file mode 100644 index 0000000000000000000000000000000000000000..923a48a6118e7a9e25959547bb08fd9782080930 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8863.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "13d2dd486d12f711594bca828358cf89e56ffd40", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/utils/_logging.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8867.json b/mne-python/source/doc/sphinxext/prs/8867.json new file mode 100644 index 0000000000000000000000000000000000000000..3e59239ef42930626f6b6190b0e71df086331288 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8867.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "4514ea7887ddef6357d0197b5271cb5020c669ce", + "authors": [ + { + "n": "Dominik Welke", + "e": "dominik.welke@web.de" + }, + { + "n": "kalenkovich", + "e": "e.kalenkovich@gmail.com" + }, + { + "n": "Zhenya", + "e": "e.kalenkovich@gmail.com" + }, + { + "n": "Zhenya", + "e": "e.kalenkovich@gmail.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "kalenkovich", + "e": "e.kalenkovich@gmail.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/datasets.rst": { + "a": 1, + "d": 0 + }, + "doc/overview/datasets_index.rst": { + "a": 18, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/ssvep/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/ssvep/ssvep.py": { + "a": 30, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 13, + "d": 5 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "tools/circleci_download.sh": { + "a": 3, + "d": 0 + }, + "tutorials/time-freq/plot_ssvep.py": { + "a": 675, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8869.json b/mne-python/source/doc/sphinxext/prs/8869.json new file mode 100644 index 0000000000000000000000000000000000000000..b124633fce77d3d8ced063f07c123af0ce92837f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8869.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b487dcf662a9249e67ab01823a75f227a637fd10", + "authors": [ + { + "n": "Christian O'Reilly", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/datasets/_infant/ANTS2-0Months3T.txt": { + "a": 117, + "d": 0 + }, + "mne/datasets/_infant/base.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8870.json b/mne-python/source/doc/sphinxext/prs/8870.json new file mode 100644 index 0000000000000000000000000000000000000000..653bb45f33e5729ead5d5edee97e8ac4badfc6a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8870.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "53f1b859d2bea2a432e153a02c386b428c71d566", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.12.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 3, + "d": 2 + }, + "doc/sensor_space.rst": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 6, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/channels/__init__.py": { + "a": 4, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 166, + "d": 2 + }, + "mne/selection.py": { + "a": 0, + "d": 189 + }, + "mne/tests/test_read_vectorview_selection.py": { + "a": 13, + "d": 12 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_check.py": { + "a": 3, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 3, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 4 + }, + "tutorials/simulation/plot_dics.py": { + "a": 2, + "d": 1 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_1samp_test_time_frequency.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8874.json b/mne-python/source/doc/sphinxext/prs/8874.json new file mode 100644 index 0000000000000000000000000000000000000000..104822c622e80f492230783f95fe0e2001af75df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8874.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "dfc05947ebdd047aa078776328ae456e9d0fba77", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 3 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8875.json b/mne-python/source/doc/sphinxext/prs/8875.json new file mode 100644 index 0000000000000000000000000000000000000000..3a48fa452d4f8cf4343fe78de566a17d049d412b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8875.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3810dde8d5c0e580a08ea3d81e2e23f042592887", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8879.json b/mne-python/source/doc/sphinxext/prs/8879.json new file mode 100644 index 0000000000000000000000000000000000000000..e0692c8e961d301379149eef3387fa0ee03fa239 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8879.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "2b09a1752dd227640cc4234115676d05bba6350a", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/fixes.py": { + "a": 15, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 42, + "d": 0 + }, + "mne/time_frequency/tfr.py": { + "a": 34, + "d": 3 + }, + "mne/utils/check.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/888.json b/mne-python/source/doc/sphinxext/prs/888.json new file mode 100644 index 0000000000000000000000000000000000000000..7192b88cb0320609e1b7752dc566b9f043dd6537 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/888.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a8cf342b0eb6da7abd448f84cd79b544baa14d80", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/source_space.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8884.json b/mne-python/source/doc/sphinxext/prs/8884.json new file mode 100644 index 0000000000000000000000000000000000000000..323cfe4de741fde2a17dcd16945e075cee40638d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8884.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "24377ad3200b6099ed47576e9cf8b27578d571ef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 3 + }, + "mne/io/base.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 2, + "d": 1 + }, + "mne/utils/tests/test_logging.py": { + "a": 59, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8886.json b/mne-python/source/doc/sphinxext/prs/8886.json new file mode 100644 index 0000000000000000000000000000000000000000..2b5de656290cf802d62fbc418c83867fba432a42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8886.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "3f1c589c93b891d3afe8cf5871cbe8e67c9887fe", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/commands/mne_report.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 10, + "d": 5 + }, + "mne/io/fiff/raw.py": { + "a": 9, + "d": 7 + }, + "mne/report.py": { + "a": 1, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 11, + "d": 5 + }, + "tutorials/misc/plot_report.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8889.json b/mne-python/source/doc/sphinxext/prs/8889.json new file mode 100644 index 0000000000000000000000000000000000000000..d8880c416762c29f6f63d8ad9195078b4fa9531d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8889.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "08baf0d82d11a0829dd3cff3e02953f8b7bd9937", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 0, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/889.json b/mne-python/source/doc/sphinxext/prs/889.json new file mode 100644 index 0000000000000000000000000000000000000000..9c2ea44f4ec07ef918ded59d8d9be2c7e7fc875d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/889.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7f44bbcc4789b7c7aae71fccf96a57a404fbfe14", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/edf/tests/__init__.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8891.json b/mne-python/source/doc/sphinxext/prs/8891.json new file mode 100644 index 0000000000000000000000000000000000000000..aad56df3b7826285d431f20eecad80e07c8abcee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8891.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "dc86ec0519632ac86eb8f1f640972d0f6df45562", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 6, + "d": 4 + }, + "mne/channels/data/neighbors/neuromag122_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 13, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8896.json b/mne-python/source/doc/sphinxext/prs/8896.json new file mode 100644 index 0000000000000000000000000000000000000000..fea9294bb0fc544417f686c81240e456fcc3e699 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8896.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "0de802aab6d858132e92c4dd74534ca0299f960f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 1 + }, + "mne/annotations.py": { + "a": 185, + "d": 57 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 2 + }, + "mne/bem.py": { + "a": 4, + "d": 8 + }, + "mne/channels/channels.py": { + "a": 14, + "d": 12 + }, + "mne/dipole.py": { + "a": 4, + "d": 3 + }, + "mne/epochs.py": { + "a": 1, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 4, + "d": 8 + }, + "mne/io/base.py": { + "a": 8, + "d": 5 + }, + "mne/morph.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 2 + }, + "mne/report.py": { + "a": 5, + "d": 3 + }, + "mne/source_space.py": { + "a": 6, + "d": 9 + }, + "mne/surface.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_annotations.py": { + "a": 143, + "d": 113 + }, + "mne/time_frequency/tfr.py": { + "a": 8, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 24, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8898.json b/mne-python/source/doc/sphinxext/prs/8898.json new file mode 100644 index 0000000000000000000000000000000000000000..3e22fa5d11105775ca1a1cf5ddef0b0b9d989879 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8898.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9b01f00073c7f232dbbee9c3ea187cda59776480", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8899.json b/mne-python/source/doc/sphinxext/prs/8899.json new file mode 100644 index 0000000000000000000000000000000000000000..d9907719463a1b18830df1ebecf688e060633442 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8899.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5909e1bb0044e558536e62d441f0d694be65377a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/89.json b/mne-python/source/doc/sphinxext/prs/89.json new file mode 100644 index 0000000000000000000000000000000000000000..9ce54b366a453167aff3cd5e8967dec3ac22b72a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/89.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "3ed097155ce04da18fab2873ea2574e0c7b8576f", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/plot_compute_source_psd_epochs.py": { + "a": 88, + "d": 0 + }, + "mne/minimum_norm/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 64, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 202, + "d": 0 + }, + "mne/time_frequency/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/time_frequency/multitaper.py": { + "a": 480, + "d": 0 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 43, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/891.json b/mne-python/source/doc/sphinxext/prs/891.json new file mode 100644 index 0000000000000000000000000000000000000000..cbda5d5274fd2ee32c63e58c925612e90525368c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/891.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b6c6fd2ec6e2f381e473b335c1fde54700a83134", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/coreg.py": { + "a": 196, + "d": 98 + }, + "mne/tests/test_coreg.py": { + "a": 10, + "d": 1 + }, + "mne/utils.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/892.json b/mne-python/source/doc/sphinxext/prs/892.json new file mode 100644 index 0000000000000000000000000000000000000000..ab8127fb121343b5f7f1cd35208b7242d358cce6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/892.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6237972a4a8be14979cdde7d4e957b467492dc6b", + "authors": [ + { + "n": "Mainak Jas", + "e": "mainakjas@gmail.com" + } + ], + "changes": { + "mne/__init__.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/893.json b/mne-python/source/doc/sphinxext/prs/893.json new file mode 100644 index 0000000000000000000000000000000000000000..8d535366e7e5f2eeddb2353af26bf3e5f2a722c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/893.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d08e8b8028ba88dfa412b27f4fd1750ce18f3a08", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/source_space.py": { + "a": 18, + "d": 4 + }, + "mne/tests/test_source_space.py": { + "a": 7, + "d": 0 + }, + "mne/utils.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/895.json b/mne-python/source/doc/sphinxext/prs/895.json new file mode 100644 index 0000000000000000000000000000000000000000..aaabd844f3ffd19528a7d02af982ee295545df5b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/895.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "67d65c4ae68c2267a2a5042c87ca93f3570e0c66", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/mne-python.rst": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8953.json b/mne-python/source/doc/sphinxext/prs/8953.json new file mode 100644 index 0000000000000000000000000000000000000000..1184ed5f486cf214a060f2d3fbf9300683c6ebd9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8953.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0b784b857de259d8ddce59b207533052483014bb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 2, + "d": 2 + }, + "requirements.txt": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8954.json b/mne-python/source/doc/sphinxext/prs/8954.json new file mode 100644 index 0000000000000000000000000000000000000000..63782ba7c22b8e091289470f1dc909c4cee2cab3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8954.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "52ebe7258a2430b4f826f4f471dfeb148ad8038a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 3, + "d": 1 + }, + "mne/viz/tests/test_raw.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8956.json b/mne-python/source/doc/sphinxext/prs/8956.json new file mode 100644 index 0000000000000000000000000000000000000000..0f2fb614a713d92ec119fe1e27f5002aacaef082 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8956.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4928c5cc7d7f37668eb9b69c07d898fd39f27303", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/chpi.py": { + "a": 12, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8959.json b/mne-python/source/doc/sphinxext/prs/8959.json new file mode 100644 index 0000000000000000000000000000000000000000..7f6e8edd50100c761c4dedd2ae3a629f335b2982 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8959.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "5ea4bda51244d36b5af8bf198af4672e66fab6ee", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/896.json b/mne-python/source/doc/sphinxext/prs/896.json new file mode 100644 index 0000000000000000000000000000000000000000..ab04fd9fa30fb9d3ac32c2932ab44691e51678d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/896.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "934fc1827441ac80bb83a7b59b2b0418592b36bc", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/edf/edf.py": { + "a": 19, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8960.json b/mne-python/source/doc/sphinxext/prs/8960.json new file mode 100644 index 0000000000000000000000000000000000000000..80ce8d8a5169001a82636822b6401284e4a6d927 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8960.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8e3bcefe2da6b47d1725eee5a487468277e8f5dd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/edf/tests/test_gdf.py": { + "a": 9, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8961.json b/mne-python/source/doc/sphinxext/prs/8961.json new file mode 100644 index 0000000000000000000000000000000000000000..ea20a1cf9d3822eebdf4047263a1faa932126ff3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8961.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3a0812f1ef4823cc2b9e012ee948c82ebc0a2e7f", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 0 + }, + "doc/_static/scrollfix.js": { + "a": 0, + "d": 31 + }, + "doc/_static/style.css": { + "a": 0, + "d": 21 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8963.json b/mne-python/source/doc/sphinxext/prs/8963.json new file mode 100644 index 0000000000000000000000000000000000000000..a1237e2179436cc2feaa30eae7302c92925e87bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8963.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "df227e7a9f67f61cf1322686308a78627d2289f4", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8965.json b/mne-python/source/doc/sphinxext/prs/8965.json new file mode 100644 index 0000000000000000000000000000000000000000..fd0db4837ae6580d30d41cf7e9f31e0fa924b008 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8965.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "fe6775b7069812e8589bbf6819d4d55e72d19fb6", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 11, + "d": 9 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8967.json b/mne-python/source/doc/sphinxext/prs/8967.json new file mode 100644 index 0000000000000000000000000000000000000000..ba8ee575bcbd76f69aec9d851aeaa07e4272eee3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8967.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6f64726adffead86cc9397d390f3c0396a3a3615", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/preprocessing/plot_run_ica.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 4, + "d": 3 + }, + "mne/viz/tests/test_ica.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/897.json b/mne-python/source/doc/sphinxext/prs/897.json new file mode 100644 index 0000000000000000000000000000000000000000..3bf3ca32de43ff0d6259125e9eb5de6c841bc877 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/897.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "fdd7d3b901825c5c8981124e86790cd51d28bde4", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 6, + "d": 3 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 1 + }, + "mne/cov.py": { + "a": 14, + "d": 8 + }, + "mne/decoding/classifier.py": { + "a": 8, + "d": 4 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/fiff/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/fiff/kit/kit.py": { + "a": 4, + "d": 2 + }, + "mne/fiff/kit/tests/test_kit.py": { + "a": 4, + "d": 2 + }, + "mne/fiff/pick.py": { + "a": 9, + "d": 3 + }, + "mne/fiff/proj.py": { + "a": 4, + "d": 2 + }, + "mne/fiff/raw.py": { + "a": 11, + "d": 9 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 6, + "d": 4 + }, + "mne/layouts/layout.py": { + "a": 7, + "d": 3 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 15, + "d": 14 + }, + "mne/preprocessing/ssp.py": { + "a": 10, + "d": 9 + }, + "mne/proj.py": { + "a": 3, + "d": 3 + }, + "mne/realtime/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 2, + "d": 1 + }, + "mne/viz.py": { + "a": 20, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8970.json b/mne-python/source/doc/sphinxext/prs/8970.json new file mode 100644 index 0000000000000000000000000000000000000000..6ac6535a4d8f69f7859cc63f2d053934cd41ed60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8970.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f20c60ec23481e8c9888fb9f7da1544378dd2489", + "authors": [ + { + "n": "kimcoco", + "e": "kimjico@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/beamformer/_dics.py": { + "a": 6, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8971.json b/mne-python/source/doc/sphinxext/prs/8971.json new file mode 100644 index 0000000000000000000000000000000000000000..70405752102be10be5f415c7a9cefcb192d0d079 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8971.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "22ea75b6d981b6233462ed511c9865cb74e7fdbc", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8972.json b/mne-python/source/doc/sphinxext/prs/8972.json new file mode 100644 index 0000000000000000000000000000000000000000..2a33b96ca6b238aa74684f340a88220d94962a16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8972.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "04d31007afc081512146f2879937840819f00ced", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 0, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 17, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8973.json b/mne-python/source/doc/sphinxext/prs/8973.json new file mode 100644 index 0000000000000000000000000000000000000000..8c721328798c35a9aa3b5bd89329547a3fd4a3c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8973.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "01bf14e0cb60fd73270f3f91d81a3b4698afdc26", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 8 + }, + ".github/workflows/linux_pip.yml": { + "a": 2, + "d": 2 + }, + "azure-pipelines.yml": { + "a": 4, + "d": 29 + }, + "tools/azure_dependencies.sh": { + "a": 24, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 10, + "d": 0 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8975.json b/mne-python/source/doc/sphinxext/prs/8975.json new file mode 100644 index 0000000000000000000000000000000000000000..a39e85479ec96ee8adfab46eb78c20b7bae9a545 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8975.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "d6476f81fcb5639af507ef15ec911818ca8e1163", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 34, + "d": 22 + }, + "mne/viz/_brain/callback.py": { + "a": 5, + "d": 7 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 14, + "d": 28 + }, + "mne/viz/backends/_qt.py": { + "a": 67, + "d": 45 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8977.json b/mne-python/source/doc/sphinxext/prs/8977.json new file mode 100644 index 0000000000000000000000000000000000000000..3396759b4e8919d52a7a31cb4b7f2e9cff3b8943 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8977.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "fc6ebb04890cf53b3be85e43f33d4adfaada4fe2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 6, + "d": 1 + }, + "tutorials/epochs/plot_30_epochs_metadata.py": { + "a": 9, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8978.json b/mne-python/source/doc/sphinxext/prs/8978.json new file mode 100644 index 0000000000000000000000000000000000000000..2d42d2432128b96b5f53c66ba3d2a6cf70e9237b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8978.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "632f11915d3027dbba9cd156e6817455c2c74831", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 12, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/898.json b/mne-python/source/doc/sphinxext/prs/898.json new file mode 100644 index 0000000000000000000000000000000000000000..9824c2cd2a712be9a6d6ebbf57a61db62aa57dbb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/898.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "95b49c1caead546a5cd45f7e21de3e8e9b6cfd9b", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "setup.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8980.json b/mne-python/source/doc/sphinxext/prs/8980.json new file mode 100644 index 0000000000000000000000000000000000000000..783ac613fb02cdd39da3b72d0d337d36e024f931 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8980.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "951dbb8562f3f071f254adfdb6b3a334480bb8b4", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/overview/index.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8983.json b/mne-python/source/doc/sphinxext/prs/8983.json new file mode 100644 index 0000000000000000000000000000000000000000..2bdff582ddf59e6187bef5e2163b67249c89866f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8983.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f68d047d4305cc0622241e2886c8632059192d64", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 9, + "d": 16 + }, + "tutorials/misc/plot_ecog.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8984.json b/mne-python/source/doc/sphinxext/prs/8984.json new file mode 100644 index 0000000000000000000000000000000000000000..e2a7a70c719fe0c63f6400c6ca36a677869b8493 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8984.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e98991e2c328c558854bc37933e6ff34471e8acc", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/0.22.inc": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8985.json b/mne-python/source/doc/sphinxext/prs/8985.json new file mode 100644 index 0000000000000000000000000000000000000000..9f0aaceee0ce23cfc4db355ca530b5bd548ee7be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8985.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "0135fcabe720801d4bf00442a366a9f59eeeb1c7", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 7, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 89, + "d": 43 + }, + "mne/viz/_brain/callback.py": { + "a": 13, + "d": 42 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 22, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8988.json b/mne-python/source/doc/sphinxext/prs/8988.json new file mode 100644 index 0000000000000000000000000000000000000000..b26426a480409551bccadde13bfe71e66fcd8f4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8988.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "20ed020d32092fd38269962974be861006340f42", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8989.json b/mne-python/source/doc/sphinxext/prs/8989.json new file mode 100644 index 0000000000000000000000000000000000000000..ad291d536cc0caa76a7442f6498f7a3ff62d75d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8989.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "31d1d0c042fa7bb25702708eb489a129adbcc1a9", + "authors": [ + { + "n": "Judy D Zhu", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/kit/coreg.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/899.json b/mne-python/source/doc/sphinxext/prs/899.json new file mode 100644 index 0000000000000000000000000000000000000000..f6d5faede38afefa4289d8b3a6ff5a080da65c4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/899.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d89655b94dd590e544f2195062fdf8292b14f6e3", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/edf/edf.py": { + "a": 98, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8996.json b/mne-python/source/doc/sphinxext/prs/8996.json new file mode 100644 index 0000000000000000000000000000000000000000..1ffd8b61e0ab45f02fafa6fca259097ad3f61068 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8996.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "75fa7b125edea476802a571517e7fbef8534acc9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 7, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8998.json b/mne-python/source/doc/sphinxext/prs/8998.json new file mode 100644 index 0000000000000000000000000000000000000000..d3cf7cf95a37e5a6de8bb706c69a184c589c958c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8998.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4cecd9d09c0f4219bfd525f804c49c81a78ae98c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 13, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/8999.json b/mne-python/source/doc/sphinxext/prs/8999.json new file mode 100644 index 0000000000000000000000000000000000000000..d4e416113b939ef79b85566e1d6b58053e6f9cca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/8999.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "14a418fff0889be6cfa9b38a158c50bdcf7c0915", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 4, + "d": 4 + }, + "mne/viz/backends/_pyvista.py": { + "a": 46, + "d": 41 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9.json b/mne-python/source/doc/sphinxext/prs/9.json new file mode 100644 index 0000000000000000000000000000000000000000..c80630e985b9ac6b67d7751903281c6fbef21c31 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "777bdac4668e072a5897b6e495e6c0784e0eb627", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/inverse/plot_compute_mne_inverse_volume.py": { + "a": 56, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/constants.py": { + "a": 6, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 28, + "d": 30 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 17, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 5 + }, + "mne/parallel.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 134, + "d": 27 + }, + "mne/source_space.py": { + "a": 63, + "d": 1 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/90.json b/mne-python/source/doc/sphinxext/prs/90.json new file mode 100644 index 0000000000000000000000000000000000000000..f30d6211e750d8314a0c2e24d1f73cade0f96b7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/90.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "b72c2db75f0d21d80c03502b3fbc942f50c86b3d", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_dipole_fit_result.py": { + "a": 78, + "d": 0 + }, + "examples/inverse/plot_morph_data.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/plot_read_stc.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_lcmv.py": { + "a": 3, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 40, + "d": 0 + }, + "mne/fiff/constants.py": { + "a": 42, + "d": 0 + }, + "mne/fiff/tag.py": { + "a": 6, + "d": 5 + }, + "mne/label.py": { + "a": 279, + "d": 89 + }, + "mne/minimum_norm/inverse.py": { + "a": 3, + "d": 13 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 6, + "d": 3 + }, + "mne/mixed_norm/inverse.py": { + "a": 3, + "d": 2 + }, + "mne/mixed_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 18, + "d": 13 + }, + "mne/simulation/tests/test_source.py": { + "a": 9, + "d": 5 + }, + "mne/source_estimate.py": { + "a": 248, + "d": 128 + }, + "mne/source_space.py": { + "a": 6, + "d": 4 + }, + "mne/tests/test_dipole.py": { + "a": 21, + "d": 0 + }, + "mne/tests/test_forward.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 75, + "d": 18 + }, + "mne/tests/test_source_estimate.py": { + "a": 22, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9009.json b/mne-python/source/doc/sphinxext/prs/9009.json new file mode 100644 index 0000000000000000000000000000000000000000..b874985391696d963a113e63c5623045481a7c51 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9009.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2d2e2ce2dc95813c88ee13d4452be4118952c170", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/viz/epochs.py": { + "a": 4, + "d": 6 + }, + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 10, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/901.json b/mne-python/source/doc/sphinxext/prs/901.json new file mode 100644 index 0000000000000000000000000000000000000000..65fc8a9c2bbab3a554b29530de915be851de005b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/901.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "44f3c09324fbfbfaa46e88daf545cfe53ba14f62", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "examples/plot_ssp_projs_sensitivity_map.py": { + "a": 3, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9010.json b/mne-python/source/doc/sphinxext/prs/9010.json new file mode 100644 index 0000000000000000000000000000000000000000..9996e42090b8872a8c0484a28d2f34a0b45b0110 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9010.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4f0ba23e8df4bbd875e3040c72a079da3628c1a0", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/connectivity/sensor_connectivity.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 19, + "d": 2 + }, + "mne/viz/_brain/view.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 16, + "d": 11 + }, + "tutorials/forward/10_background_freesurfer.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9012.json b/mne-python/source/doc/sphinxext/prs/9012.json new file mode 100644 index 0000000000000000000000000000000000000000..241e82f4265a0be0b841ebedd658aeb60c6051dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9012.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a40ad4bc22a707135c924b001c9d7a3644f00cca", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 10, + "d": 10 + }, + "tools/github_actions_dependencies.sh": { + "a": 5, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9013.json b/mne-python/source/doc/sphinxext/prs/9013.json new file mode 100644 index 0000000000000000000000000000000000000000..a048962ef7ae611df4555cf0eb2ce81f350e94f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9013.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9d2c2b6c04331c3bb445204bf14c2ecf86f4bbd7", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 15, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9014.json b/mne-python/source/doc/sphinxext/prs/9014.json new file mode 100644 index 0000000000000000000000000000000000000000..2bf18d43825673aa9ad47fc3de26aad0108f63e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9014.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "97a69e6004ca0647e0f26d9024e8f144a504262b", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 24, + "d": 29 + }, + "mne/viz/backends/_abstract.py": { + "a": 30, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 29, + "d": 5 + }, + "mne/viz/backends/_pyvista.py": { + "a": 8, + "d": 8 + }, + "mne/viz/backends/_qt.py": { + "a": 41, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9015.json b/mne-python/source/doc/sphinxext/prs/9015.json new file mode 100644 index 0000000000000000000000000000000000000000..2648fafcd73c77794c5a3bbe566a8bf7a4c301c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9015.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "633bee397ed2f63dded0e8f3169556893408976b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 4, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 10, + "d": 3 + }, + "tutorials/misc/plot_report.py": { + "a": 42, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9016.json b/mne-python/source/doc/sphinxext/prs/9016.json new file mode 100644 index 0000000000000000000000000000000000000000..38025ba5061b15fad5e7a4abe12031d0a00ad95c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9016.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "9e5916e6ad3951e43106fae55f9312e7de1d59b2", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 124, + "d": 280 + }, + "mne/viz/_brain/callback.py": { + "a": 0, + "d": 32 + }, + "mne/viz/_brain/mplcanvas.py": { + "a": 0, + "d": 128 + }, + "mne/viz/_brain/tests/test.ipynb": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_abstract.py": { + "a": 189, + "d": 9 + }, + "mne/viz/backends/_notebook.py": { + "a": 141, + "d": 52 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 6, + "d": 3 + }, + "mne/viz/backends/_qt.py": { + "a": 194, + "d": 26 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9017.json b/mne-python/source/doc/sphinxext/prs/9017.json new file mode 100644 index 0000000000000000000000000000000000000000..43b233f7e6974d1c5fdfb6f9b4fefc3244e186c1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9017.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "64c90ce224b96358eb7d083e5b89c8faf226c909", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + } + ], + "changes": { + "tutorials/epochs/plot_10_epochs_overview.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9019.json b/mne-python/source/doc/sphinxext/prs/9019.json new file mode 100644 index 0000000000000000000000000000000000000000..471d5f54113adf5f94a4e38726a828f9fd923a60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9019.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aabdda6f443ca1699b9bc047bffdf820835730f8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_file_traits.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/902.json b/mne-python/source/doc/sphinxext/prs/902.json new file mode 100644 index 0000000000000000000000000000000000000000..1afcbceccaf13d6bf32e186e10edab36b42de3bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/902.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9423f28a8998ec659cbbb32ff2770e35ef3e3f81", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/Makefile": { + "a": 5, + "d": 0 + }, + "doc/source/_static/logo.png": { + "a": 0, + "d": 0 + }, + "doc/source/_templates/layout.html": { + "a": 1, + "d": 0 + }, + "doc/source/cite.rst": { + "a": 10, + "d": 0 + }, + "doc/source/index.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9023.json b/mne-python/source/doc/sphinxext/prs/9023.json new file mode 100644 index 0000000000000000000000000000000000000000..421fec7f24be29f5a852c3b97e44dea26bc01d85 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9023.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e94b439fb5f507488de311dd8556249daf7de364", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 8, + "d": 6 + }, + "tutorials/misc/plot_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9024.json b/mne-python/source/doc/sphinxext/prs/9024.json new file mode 100644 index 0000000000000000000000000000000000000000..6860f8fa3514eb50cce4b0552c651827041e7590 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9024.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7b4d4e41910473db53f97f0aaa8fe699e87f0331", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9026.json b/mne-python/source/doc/sphinxext/prs/9026.json new file mode 100644 index 0000000000000000000000000000000000000000..56871918393df77a2ba0e96ac55c2f978bda4789 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9026.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b707d37dc880205154773de703b2e47a438cc051", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "codecov.yml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9027.json b/mne-python/source/doc/sphinxext/prs/9027.json new file mode 100644 index 0000000000000000000000000000000000000000..7587fe64f9da85866e1abf993749c7cac66daade --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9027.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "c2d4e4bd276760b895acbee5597ad2834aa2691f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/evoked.py": { + "a": 25, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 21, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9028.json b/mne-python/source/doc/sphinxext/prs/9028.json new file mode 100644 index 0000000000000000000000000000000000000000..f82d0eafb587832d494851cb1f282dfa8d22c74c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9028.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e889e26285aacc5a20caaeaacaa90e7d98578d76", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 0, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9029.json b/mne-python/source/doc/sphinxext/prs/9029.json new file mode 100644 index 0000000000000000000000000000000000000000..23dd59d2ecf14abe4337331d8994ec3685173aa3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9029.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6cfd3040aed69d9970c618b782e6126ed56adb65", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 55, + "d": 42 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 11, + "d": 29 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 18 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9032.json b/mne-python/source/doc/sphinxext/prs/9032.json new file mode 100644 index 0000000000000000000000000000000000000000..16eba63d95c21e5a1cddc463808b4dca1eb0374c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9032.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "623553f46701ce679f4c62d28d3b4bc3a1df97a4", + "authors": [ + { + "n": "Gensollen", + "e": "nicolas.gensollen@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_parcellation.py": { + "a": 9, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9033.json b/mne-python/source/doc/sphinxext/prs/9033.json new file mode 100644 index 0000000000000000000000000000000000000000..fa31355817fa245b26c02ce6fb150cd28beea296 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9033.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "014e9526306a07f8cd47bbcb30ac33cd7779392e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 50, + "d": 10 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 45, + "d": 7 + }, + "mne/viz/tests/test_ica.py": { + "a": 3, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 6, + "d": 0 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 24, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9034.json b/mne-python/source/doc/sphinxext/prs/9034.json new file mode 100644 index 0000000000000000000000000000000000000000..7e45848b3ef879e71fbb34e7c68dda9441722154 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9034.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "4add7d137958468c5accc2a1877664ebb9603c23", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 0, + "d": 1 + }, + "environment.yml": { + "a": 3, + "d": 0 + }, + "mne/conftest.py": { + "a": 5, + "d": 3 + }, + "mne/viz/_brain/tests/test.ipynb": { + "a": 0, + "d": 123 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 108, + "d": 16 + }, + "mne/viz/conftest.py": { + "a": 129, + "d": 0 + }, + "mne/viz/tests/conftest.py": { + "a": 0, + "d": 45 + }, + "requirements.txt": { + "a": 2, + "d": 0 + }, + "requirements_testing.txt": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9035.json b/mne-python/source/doc/sphinxext/prs/9035.json new file mode 100644 index 0000000000000000000000000000000000000000..49155fb710d30d42458912a1d643745b19759dd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9035.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1ae8e10cf49b5aecb3d0b21f1e2b86052a98471c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 1, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9036.json b/mne-python/source/doc/sphinxext/prs/9036.json new file mode 100644 index 0000000000000000000000000000000000000000..ea6a46b051f68994ea2876279778d9cd47c21338 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9036.json @@ -0,0 +1,287 @@ +{ + "merge_commit_sha": "d309e3dc37657e0dfbc0a663e5292db6f49e4e5b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + "doc/_static/font-source-code-pro.css": { + "a": 0, + "d": 167 + }, + "doc/_static/font-source-sans-pro.css": { + "a": 0, + "d": 131 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-Bold.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-BoldIt.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-It.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-Regular.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-Semibold.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/EOT/SourceCodePro-SemiboldIt.eot": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-Bold.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-BoldIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-It.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-Regular.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-Semibold.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/OTF/SourceCodePro-SemiboldIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-Bold.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-BoldIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-It.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-Regular.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-Semibold.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/TTF/SourceCodePro-SemiboldIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-Bold.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-BoldIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-It.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-Regular.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-Semibold.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF/SourceCodePro-SemiboldIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-Bold.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-BoldIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-It.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-Regular.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-Semibold.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_code_pro/WOFF2/SourceCodePro-SemiboldIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-Bold.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-BoldIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-It.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-Light.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-LightIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-Regular.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-Semibold.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/OTF/SourceSansPro-SemiboldIt.otf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-Bold.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-BoldIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-It.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-Light.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-LightIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-Regular.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-Semibold.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/TTF/SourceSansPro-SemiboldIt.ttf": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-Bold.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-BoldIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-It.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-Light.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-LightIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-Regular.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-Semibold.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF/SourceSansPro-SemiboldIt.otf.woff": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-Bold.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-BoldIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-It.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-Light.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-LightIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-Regular.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-Semibold.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/fonts/source_sans_pro/WOFF2/SourceSansPro-SemiboldIt.ttf.woff2": { + "a": 0, + "d": 0 + }, + "doc/_static/style.css": { + "a": 36, + "d": 13 + }, + "doc/_templates/docs-navbar.html": { + "a": 18, + "d": 66 + }, + "doc/conf.py": { + "a": 15, + "d": 4 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9037.json b/mne-python/source/doc/sphinxext/prs/9037.json new file mode 100644 index 0000000000000000000000000000000000000000..aeafe9eabdfcb5499ff25daadfbf20b2b9c0af68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9037.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2114c06d8f6f8901ec03d1d03ae17ad75101bb64", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 16, + "d": 0 + }, + "mne/tests/test_report.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9039.json b/mne-python/source/doc/sphinxext/prs/9039.json new file mode 100644 index 0000000000000000000000000000000000000000..3b564bda2112a8b64aa51e6e184e71ee25d9cc3f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9039.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3319fafd30d3d68c10ae07307ad330f56580dcea", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "tutorials/source-modeling/plot_beamformer_lcmv.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9041.json b/mne-python/source/doc/sphinxext/prs/9041.json new file mode 100644 index 0000000000000000000000000000000000000000..46b557eec5730a2ff8dca994dacbd581ee251464 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9041.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f751fe390b775926a72f63c8f217021deea14965", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9042.json b/mne-python/source/doc/sphinxext/prs/9042.json new file mode 100644 index 0000000000000000000000000000000000000000..76b7faeb9b19b9d9aeca984e6efd9f0e486d1834 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9042.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b0778b86404506414501bf83a4629d3a73970ae9", + "authors": [ + { + "n": "Eduard", + "e": "eduardxort@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_evoked_whitening.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9043.json b/mne-python/source/doc/sphinxext/prs/9043.json new file mode 100644 index 0000000000000000000000000000000000000000..33c7fefcfbbcc44edae734b54d4e22dc8122567a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9043.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d489bcf68f02a8535a1ec7bc323fcd7107ab84e9", + "authors": [ + { + "n": "Valerii", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 19, + "d": 24 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9044.json b/mne-python/source/doc/sphinxext/prs/9044.json new file mode 100644 index 0000000000000000000000000000000000000000..54760dff951823d71a7843db09b217257dbed900 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9044.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0d8a7b0717dc33e75dc20c9cdd356f51a515309d", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "tutorials/sample-datasets/plot_sleep.py": { + "a": 10, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9046.json b/mne-python/source/doc/sphinxext/prs/9046.json new file mode 100644 index 0000000000000000000000000000000000000000..cd3034fc66d915b04aea45651ebaf98c781fb61c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9046.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2f908df809f3c099d26bce373286e3bf16efa6fa", + "authors": [ + { + "n": "Silvia Cotroneo", + "e": "silvia.cotroneo@aalto.fi" + } + ], + "changes": { + "tutorials/discussions/plot_background_statistics.py": { + "a": 9, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9047.json b/mne-python/source/doc/sphinxext/prs/9047.json new file mode 100644 index 0000000000000000000000000000000000000000..e46199a45ec862a4aeca505538f2e762464e743b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9047.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9798a638a50ed5a034d81f6619deee483fe57154", + "authors": [ + { + "n": "kimcoco", + "e": "kimjico@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9048.json b/mne-python/source/doc/sphinxext/prs/9048.json new file mode 100644 index 0000000000000000000000000000000000000000..46d4be4d1e8b8a3e5fe965e26d816ebfc1733f99 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9048.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "51677154fea57d90cbe7a989c5b59803ec901064", + "authors": [ + { + "n": "Ram PARI", + "e": null + } + ], + "changes": { + "mne/simulation/raw.py": { + "a": 4, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9049.json b/mne-python/source/doc/sphinxext/prs/9049.json new file mode 100644 index 0000000000000000000000000000000000000000..a0de79f9d21a1b69fb16ed35caa6324e8bdacbf7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9049.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1171b4a12f91756a1576077c181cf37b267da446", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "examples/preprocessing/plot_otp.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9050.json b/mne-python/source/doc/sphinxext/prs/9050.json new file mode 100644 index 0000000000000000000000000000000000000000..7819eb38cb883d5923848e5b50b15fd7d39de59d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9050.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f98e9222700e47308c0cd759410d82f6da058dda", + "authors": [ + { + "n": "Matteo Anelli", + "e": "matteanelli.96.11@gmail.com" + } + ], + "changes": { + "examples/time_frequency/plot_source_power_spectrum_opm.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9051.json b/mne-python/source/doc/sphinxext/prs/9051.json new file mode 100644 index 0000000000000000000000000000000000000000..e846c407b146035619c4f87b937980f4b0b1d186 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9051.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "18cd16b971902b5bed979fb5a5c88a3e318245b5", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 4, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9052.json b/mne-python/source/doc/sphinxext/prs/9052.json new file mode 100644 index 0000000000000000000000000000000000000000..9c9f1a22d4a54a26e7ec8be042efaf1c401abd71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9052.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c25aeee579fabdc2533c5ee591d9654e6d40f063", + "authors": [ + { + "n": "Giorgio_M", + "e": "giorgio.marinato@unitn.it" + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_global_field_power.py": { + "a": 8, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9053.json b/mne-python/source/doc/sphinxext/prs/9053.json new file mode 100644 index 0000000000000000000000000000000000000000..557df9c6bb1c20ccc93b9cfd19f51a4d80ddda03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9053.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b495090403202aebb8bbf6dd02a81a439cbcfcb5", + "authors": [ + { + "n": null, + "e": "timon.merk@charite.de" + } + ], + "changes": { + "examples/simulation/plot_simulated_raw_data_using_subject_anatomy.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9054.json b/mne-python/source/doc/sphinxext/prs/9054.json new file mode 100644 index 0000000000000000000000000000000000000000..6beaf55a17752b9dc9affaa7bea3d945a5e3f594 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9054.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "eec545f5c6a94877cd87060a7f2f12adc1c7fcba", + "authors": [ + { + "n": "Felix Klotzsche", + "e": "klotzsche@cbs.mpg.de" + } + ], + "changes": { + "examples/time_frequency/plot_time_frequency_erds.py": { + "a": 5, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9055.json b/mne-python/source/doc/sphinxext/prs/9055.json new file mode 100644 index 0000000000000000000000000000000000000000..a8479ecad3b70dd3bee4b876b735e26e65c50328 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9055.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4dacaa33542d028820b96caba99e44d0f04a0d7b", + "authors": [ + { + "n": "DataFox", + "e": "sfox@riseup.net" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/references.bib": { + "a": 14, + "d": 0 + }, + "mne/stats/multi_comp.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9056.json b/mne-python/source/doc/sphinxext/prs/9056.json new file mode 100644 index 0000000000000000000000000000000000000000..ea54e0d397ddc8baae2dbc563aaf1a515e3d446f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9056.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3ca43776bc2a380a10b1c1f7aef33c619c5a2af2", + "authors": [ + { + "n": "Falach", + "e": "rotemfa0@gmail.com" + } + ], + "changes": { + "mne/label.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9058.json b/mne-python/source/doc/sphinxext/prs/9058.json new file mode 100644 index 0000000000000000000000000000000000000000..34251183a5bc53a73b288c8be0095b128adf2464 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9058.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c8f0f51b4a747dc3f08128c7c232ce3ac005cdba", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/stats/plot_sensor_regression.py": { + "a": 6, + "d": 10 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 2, + "d": 4 + }, + "tutorials/stats-sensor-space/plot_stats_cluster_erp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9059.json b/mne-python/source/doc/sphinxext/prs/9059.json new file mode 100644 index 0000000000000000000000000000000000000000..0e6c90e62abceccf5301be1bfb676e8a4273cd1d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9059.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "428e73badd512e528aa7eb236785b30a2eaac53e", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + } + ], + "changes": { + "examples/visualization/plot_mne_helmet.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/906.json b/mne-python/source/doc/sphinxext/prs/906.json new file mode 100644 index 0000000000000000000000000000000000000000..056cb6b56f6ada551b37a75e729dff3201889727 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/906.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0b01386260f71eff2252d3ca81ba5ca143ba77da", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/getting_started.rst": { + "a": 9, + "d": 4 + }, + "examples/plot_evoked_whitening.py": { + "a": 0, + "d": 1 + }, + "mne/viz.py": { + "a": 22, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9061.json b/mne-python/source/doc/sphinxext/prs/9061.json new file mode 100644 index 0000000000000000000000000000000000000000..3d55e8d1d6286cdb92a48e94a8c5c3c8c0e740d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9061.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "77cf51cf70c8b1a891d9dd0dbd93e70ca4ed2f34", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9062.json b/mne-python/source/doc/sphinxext/prs/9062.json new file mode 100644 index 0000000000000000000000000000000000000000..0b1bf95b58f17ae7c291d94b8e10e7f46cdf7c86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9062.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "04bb93a2e8bf47e39049b9b2b874a23d1f079ee3", + "authors": [ + { + "n": "Valerii", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9063.json b/mne-python/source/doc/sphinxext/prs/9063.json new file mode 100644 index 0000000000000000000000000000000000000000..6ee1f48bbe5fc73e946410c728fb1e65b902e4f3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9063.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d167f95aa5534136f8390e3c971e668b5bb02ef2", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + "mne/stats/permutations.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9064.json b/mne-python/source/doc/sphinxext/prs/9064.json new file mode 100644 index 0000000000000000000000000000000000000000..88ac8c55c6a4a2e9241beed73b358e542a40ace8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9064.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1fb6e41e7de3c896114453880267e301659c7105", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "tutorials/discussions/plot_background_filtering.py": { + "a": 46, + "d": 68 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9065.json b/mne-python/source/doc/sphinxext/prs/9065.json new file mode 100644 index 0000000000000000000000000000000000000000..d36dba995ede2eeacdee840c74b8739d6228fb90 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9065.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8be65850012d54155758545594d671d9cc93e04b", + "authors": [ + { + "n": "Silvia Cotroneo", + "e": "silvia.cotroneo@aalto.fi" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 9, + "d": 9 + }, + "tutorials/discussions/plot_background_statistics.py": { + "a": 9, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9066.json b/mne-python/source/doc/sphinxext/prs/9066.json new file mode 100644 index 0000000000000000000000000000000000000000..e2a95b7ea4c31dfa0b0d8914ccebd0b034167224 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9066.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8e6858e0cfda78923cd745bb83d2f53bc6f6b02f", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "tutorials/source-modeling/plot_compute_covariance.py": { + "a": 5, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9067.json b/mne-python/source/doc/sphinxext/prs/9067.json new file mode 100644 index 0000000000000000000000000000000000000000..d3f38097f76caadc81109ca10e7a56c412d1e2f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9067.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5e63884ceff9bc7658f56c0699d5bf115d20723a", + "authors": [ + { + "n": "Matteo Anelli", + "e": "matteanelli.96.11@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/preprocessing/xdawn.py": { + "a": 7, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9068.json b/mne-python/source/doc/sphinxext/prs/9068.json new file mode 100644 index 0000000000000000000000000000000000000000..a4aaa026e2f076fa3f102289899ab5387dbe7738 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9068.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c22263c70c85d755ccb424b98d226a43c73534c3", + "authors": [ + { + "n": "Felix Klotzsche", + "e": "klotzsche@cbs.mpg.de" + } + ], + "changes": { + "tutorials/stats-sensor-space/plot_stats_cluster_erp.py": { + "a": 4, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/907.json b/mne-python/source/doc/sphinxext/prs/907.json new file mode 100644 index 0000000000000000000000000000000000000000..3933ee10ec5ce2b26c9f536eb4421c8331c730a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/907.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "437e3d08a1f09e53e0605e41ee329e74dfa13f8c", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 3 + }, + "mne/epochs.py": { + "a": 7, + "d": 17 + }, + "mne/fiff/compensator.py": { + "a": 11, + "d": 2 + }, + "mne/fiff/ctf.py": { + "a": 12, + "d": 8 + }, + "mne/fiff/evoked.py": { + "a": 4, + "d": 3 + }, + "mne/fiff/raw.py": { + "a": 14, + "d": 9 + }, + "mne/fiff/tests/test_compensator.py": { + "a": 51, + "d": 2 + }, + "mne/fiff/tests/test_raw.py": { + "a": 19, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 18, + "d": 15 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 15, + "d": 1 + }, + "mne/realtime/epochs.py": { + "a": 7, + "d": 10 + }, + "mne/tests/test_viz.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9070.json b/mne-python/source/doc/sphinxext/prs/9070.json new file mode 100644 index 0000000000000000000000000000000000000000..7242e48854b441b5b223d99e3b6bad996c33c596 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9070.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f0aa3841b0023d83c96bd2b27ec6f0515cb82719", + "authors": [ + { + "n": "vpeterson", + "e": "victoriapeterson09@gmail.com" + } + ], + "changes": { + "examples/visualization/plot_sensor_noise_level.py": { + "a": 6, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9071.json b/mne-python/source/doc/sphinxext/prs/9071.json new file mode 100644 index 0000000000000000000000000000000000000000..3b3b5eebdfbd1921a2624c2869944a741d8206b0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9071.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0974fc51f0f9bc76c8ebeec3695726f2680b11ff", + "authors": [ + { + "n": "Eduard", + "e": "eduardxort@gmail.com" + } + ], + "changes": { + "tutorials/preprocessing/plot_15_handling_bad_channels.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9072.json b/mne-python/source/doc/sphinxext/prs/9072.json new file mode 100644 index 0000000000000000000000000000000000000000..4ee144991b99c442ccd43319fd69969582dfdf57 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9072.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6d1ee18a4cd7e753a0c42306a89630d7e8d092cb", + "authors": [ + { + "n": "Catalina M. Galván", + "e": null + } + ], + "changes": { + "mne/connectivity/envelope.py": { + "a": 2, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9074.json b/mne-python/source/doc/sphinxext/prs/9074.json new file mode 100644 index 0000000000000000000000000000000000000000..420f58472cea11bcd0801a779d1805809c3ea6dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9074.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f1ff6ba253c1a09dfbbb7369ad34e1a34a7865d6", + "authors": [ + { + "n": "nordme", + "e": "nordme@uw.edu" + } + ], + "changes": { + "mne/datasets/limo/limo.py": { + "a": 8, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9075.json b/mne-python/source/doc/sphinxext/prs/9075.json new file mode 100644 index 0000000000000000000000000000000000000000..4f4c44a4b4b4f6f7cdc154293f766fb1e90173cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9075.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "271eb1076f9ce5c1afc40fc9cd5356bdc7f37df2", + "authors": [ + { + "n": "ChristinaZhao", + "e": null + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/datasets/eegbci/eegbci.py": { + "a": 5, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9077.json b/mne-python/source/doc/sphinxext/prs/9077.json new file mode 100644 index 0000000000000000000000000000000000000000..d1df234775999801bc1360621bb5f6c46524de9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9077.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "505e7a03e389e0552cf521dc044cf7ee93614be6", + "authors": [ + { + "n": "Maggie Clarke", + "e": "mdclarke@uw.edu" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9079.json b/mne-python/source/doc/sphinxext/prs/9079.json new file mode 100644 index 0000000000000000000000000000000000000000..55ea0497775eab404fcfefe6dff54be6985dc5c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9079.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b465989273481d3b6264964a0baf877d1e913873", + "authors": [ + { + "n": "Steven Bierer", + "e": null + }, + { + "n": "Steven Bierer", + "e": "neurolaunch@gmail.copm" + } + ], + "changes": { + "doc/references.bib": { + "a": 12, + "d": 0 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 7, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/908.json b/mne-python/source/doc/sphinxext/prs/908.json new file mode 100644 index 0000000000000000000000000000000000000000..6f6b7d95b9b9734c9212d2f29d9b9b3ab494676a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/908.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6d2ff00952ebc332ef514af397f65c66778c2c55", + "authors": [ + { + "n": "Romek Goj", + "e": "roman.goj@gmail.com" + } + ], + "changes": { + "mne/viz.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9080.json b/mne-python/source/doc/sphinxext/prs/9080.json new file mode 100644 index 0000000000000000000000000000000000000000..97ade6739576eda5668791fb8286d2400e201ec4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9080.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "c29a32d474809785225c24053dcb41bf054a6e32", + "authors": [ + { + "n": "nordme", + "e": "nordme@uw.edu" + } + ], + "changes": { + "mne/datasets/hf_sef/hf_sef.py": { + "a": 3, + "d": 3 + }, + "mne/datasets/limo/limo.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9081.json b/mne-python/source/doc/sphinxext/prs/9081.json new file mode 100644 index 0000000000000000000000000000000000000000..1c559f271213c7eafd3d4725adaa809de74ca7be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9081.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "94870a5532a43a0ca850d58789a77ceeb532a3b5", + "authors": [ + { + "n": "Ram PARI", + "e": null + } + ], + "changes": { + "tutorials/machine-learning/plot_receptive_field.py": { + "a": 9, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9083.json b/mne-python/source/doc/sphinxext/prs/9083.json new file mode 100644 index 0000000000000000000000000000000000000000..269c1ee9263cc90ef28856d5724b787d51409086 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9083.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fabd29fc8e0d2508399ed006a74f5fd3463b38b4", + "authors": [ + { + "n": "Maggie Clarke", + "e": "mdclarke@uw.edu" + } + ], + "changes": { + "tutorials/sample-datasets/plot_brainstorm_phantom_elekta.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9084.json b/mne-python/source/doc/sphinxext/prs/9084.json new file mode 100644 index 0000000000000000000000000000000000000000..540c2abffb15b2c68af12037deabb76b2d0be35e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9084.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e1dacb5e63ea97d89ff71016a4edcf35e7edb1dc", + "authors": [ + { + "n": "Maggie Clarke", + "e": "mdclarke@uw.edu" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/otp.py": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9085.json b/mne-python/source/doc/sphinxext/prs/9085.json new file mode 100644 index 0000000000000000000000000000000000000000..489fb1959457015c485161ffc95e00c42cd8ea3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9085.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7168e683e319f99a3c57ec68f7f0e844eafcb463", + "authors": [ + { + "n": "Maggie Clarke", + "e": "mdclarke@uw.edu" + } + ], + "changes": { + "examples/io/plot_read_noise_covariance_matrix.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9087.json b/mne-python/source/doc/sphinxext/prs/9087.json new file mode 100644 index 0000000000000000000000000000000000000000..cc179cbcb4355989d1e581e566be315a8c1bed1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9087.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "59008cfa021f617c9c6de50593f55cdbdbf17538", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Adam Li", + "e": "adam2392@gmail.com" + }, + { + "n": "Liberty Hamilton", + "e": "libertyhamilton@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 3, + "d": 0 + }, + "doc/datasets.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/epilepsy_ecog/__init__.py": { + "a": 3, + "d": 0 + }, + "mne/datasets/epilepsy_ecog/_data.py": { + "a": 31, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 14, + "d": 8 + }, + "mne/source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/utils/config.py": { + "a": 2, + "d": 0 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + }, + "tools/circleci_download.sh": { + "a": 3, + "d": 0 + }, + "tutorials/misc/plot_ecog.py": { + "a": 118, + "d": 130 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9088.json b/mne-python/source/doc/sphinxext/prs/9088.json new file mode 100644 index 0000000000000000000000000000000000000000..11affaf4b7df3c99b1b5eb4da4f95eff9863555b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9088.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "49536e31fdd3a69dcfe21a0b2efd69958dead5cd", + "authors": [ + { + "n": "vpeterson", + "e": "victoriapeterson09@gmail.com" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "nordme", + "e": "nordme@uw.edu" + } + ], + "changes": { + "mne/epochs.py": { + "a": 55, + "d": 1 + }, + "mne/evoked.py": { + "a": 54, + "d": 2 + }, + "mne/io/base.py": { + "a": 7, + "d": 36 + }, + "mne/tests/test_epochs.py": { + "a": 35, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 21, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 55, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9089.json b/mne-python/source/doc/sphinxext/prs/9089.json new file mode 100644 index 0000000000000000000000000000000000000000..adfaabcdc2403fcca32b9dfe944d9b2728148f50 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9089.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "727807d2922b473a43cd7665fd56a5d7a645eed9", + "authors": [ + { + "n": "ChristinaZhao", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9090.json b/mne-python/source/doc/sphinxext/prs/9090.json new file mode 100644 index 0000000000000000000000000000000000000000..874cbfcede26e513fe6de81c16968eebbe5883c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9090.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cc80458ba6aec4f790a56cc445e3f024740732de", + "authors": [ + { + "n": "Christian Mista", + "e": "cmista@ingenieria.uner.edu.ar" + } + ], + "changes": { + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 15, + "d": 42 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9091.json b/mne-python/source/doc/sphinxext/prs/9091.json new file mode 100644 index 0000000000000000000000000000000000000000..166b13facef0d9ebde1783ef882af11426b822f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9091.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "53757d01c8f5e86fa6c2c0bd1934cb0a1f58aa3f", + "authors": [ + { + "n": "Valerii", + "e": null + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 22, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9092.json b/mne-python/source/doc/sphinxext/prs/9092.json new file mode 100644 index 0000000000000000000000000000000000000000..bf10f19ec5fef2d76b12ec3d91cc85ef06c562a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9092.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "04c58d73112916444b71710bd2b60f77723028fc", + "authors": [ + { + "n": "Eduard", + "e": "eduardxort@gmail.com" + } + ], + "changes": { + "examples/preprocessing/plot_virtual_evoked.py": { + "a": 18, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9095.json b/mne-python/source/doc/sphinxext/prs/9095.json new file mode 100644 index 0000000000000000000000000000000000000000..63118640501bd2f7cf854279aa7db46db758cdbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9095.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "80b029d305872aef82e03d1f9353a191e17da7c6", + "authors": [ + { + "n": "Giorgio_M", + "e": "giorgio.marinato@unitn.it" + } + ], + "changes": { + "doc/references.bib": { + "a": 13, + "d": 0 + }, + "examples/visualization/plot_channel_epochs_image.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9096.json b/mne-python/source/doc/sphinxext/prs/9096.json new file mode 100644 index 0000000000000000000000000000000000000000..0c4fd99793d25beb8642aafdc06ad1169f541acc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9096.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "a6abf3649bdf754c86bb983f393f690791816048", + "authors": [ + { + "n": "Silvia Cotroneo", + "e": "silvia.cotroneo@aalto.fi" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 8, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9097.json b/mne-python/source/doc/sphinxext/prs/9097.json new file mode 100644 index 0000000000000000000000000000000000000000..586f6837f6dba486614bfa51a2ecbcb3682eea4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9097.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "523413f911e23bfef98ca92e3cfa00c80501f94d", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 1 + }, + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/glossary.rst": { + "a": 8, + "d": 0 + }, + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "mne/epochs.py": { + "a": 9, + "d": 4 + }, + "tutorials/epochs/plot_40_autogenerate_metadata.py": { + "a": 13, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9098.json b/mne-python/source/doc/sphinxext/prs/9098.json new file mode 100644 index 0000000000000000000000000000000000000000..4e45214c54bd4bbd3aab0e783848a179a3b1bef2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9098.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "602a94f62127736834fa65e0c33fe037763efdb2", + "authors": [ + { + "n": "Ram PARI", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9099.json b/mne-python/source/doc/sphinxext/prs/9099.json new file mode 100644 index 0000000000000000000000000000000000000000..46ab3abf988665f801b83c1ec729f01126b581e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9099.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "56e9fbe67a554272a71dfd2b9ae96eb7fd58d104", + "authors": [ + { + "n": "kimcoco", + "e": "kimjico@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 30, + "d": 10 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 51, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 10, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/91.json b/mne-python/source/doc/sphinxext/prs/91.json new file mode 100644 index 0000000000000000000000000000000000000000..2090d5b980c8b005bdd5888d26c1a66f007de18c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/91.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a77d9f05ee4b0b964e2098c0e247913f2412a900", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/minimum_norm/time_frequency.py": { + "a": 5, + "d": 3 + }, + "mne/time_frequency/multitaper.py": { + "a": 13, + "d": 12 + }, + "mne/time_frequency/tests/test_multitaper.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/910.json b/mne-python/source/doc/sphinxext/prs/910.json new file mode 100644 index 0000000000000000000000000000000000000000..aaa652e25b8b21096ce2e34659f0e4505aa7f622 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/910.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "88f6478aedd6bc1285be07b1b5aa3dec50dff29f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "Makefile": { + "a": 1, + "d": 0 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 0, + "d": 1 + }, + "mne/fixes.py": { + "a": 42, + "d": 63 + }, + "mne/tests/test_fixes.py": { + "a": 63, + "d": 7 + }, + "mne/tests/test_utils.py": { + "a": 54, + "d": 4 + }, + "mne/tests/test_viz.py": { + "a": 37, + "d": 2 + }, + "mne/utils.py": { + "a": 8, + "d": 14 + }, + "mne/viz.py": { + "a": 18, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9100.json b/mne-python/source/doc/sphinxext/prs/9100.json new file mode 100644 index 0000000000000000000000000000000000000000..1ab71051df55086fc0719ac1c0f7aa9f44798678 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9100.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1703bfd2a159feb105e145699764c54b2592e5cf", + "authors": [ + { + "n": "Ram PARI", + "e": null + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + } + ], + "changes": { + "tutorials/time-freq/plot_sensors_time_frequency.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9102.json b/mne-python/source/doc/sphinxext/prs/9102.json new file mode 100644 index 0000000000000000000000000000000000000000..a77ac78256f7c46cadaa04b80ba1a33bd572eb3f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9102.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0a61e1c7c271829bb3cc9480ea8fb08142c91e7b", + "authors": [ + { + "n": "Catalina M. Galván", + "e": null + } + ], + "changes": { + "examples/preprocessing/plot_xdawn_denoising.py": { + "a": 6, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9103.json b/mne-python/source/doc/sphinxext/prs/9103.json new file mode 100644 index 0000000000000000000000000000000000000000..3def439a642ab8ba28d6073b0393422b6785afe2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9103.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "050a1f35fa91e013973ee3df2c3ca8a4ad362264", + "authors": [ + { + "n": "Falach", + "e": "rotemfa0@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 2 + }, + "mne/io/tests/test_meas_info.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9104.json b/mne-python/source/doc/sphinxext/prs/9104.json new file mode 100644 index 0000000000000000000000000000000000000000..dd60a3a10ba9bfe4bbdb0450689c8e9796003a95 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9104.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3da7e332c3ecd75613feb31c6f34c3b362e32d97", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + } + ], + "changes": { + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 6, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9105.json b/mne-python/source/doc/sphinxext/prs/9105.json new file mode 100644 index 0000000000000000000000000000000000000000..405780bec17f9d85ccc0c233a6ab9fb52d5ed2f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9105.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "1026ad762371b0a802c67af89e163434ac9640b6", + "authors": [ + { + "n": "Catalina M. Galván", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/datasets/sleep_physionet/age.py": { + "a": 3, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9106.json b/mne-python/source/doc/sphinxext/prs/9106.json new file mode 100644 index 0000000000000000000000000000000000000000..760158ded0ccd36eb8be692ec5ce7937be404655 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9106.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b239ad314fb7d74fb43fdf1e34eada94ed32659d", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + } + ], + "changes": { + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9109.json b/mne-python/source/doc/sphinxext/prs/9109.json new file mode 100644 index 0000000000000000000000000000000000000000..350258b11846db38a330bf006be6ed8cc9f83fee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9109.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "88cbfa8f42f885a6e4a400d4c9eece839cee0c77", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9113.json b/mne-python/source/doc/sphinxext/prs/9113.json new file mode 100644 index 0000000000000000000000000000000000000000..1e5c644e2fafa78808e539d986f5868b7ccc6e69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9113.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fc3f2b56bc172eb3b747751e636d55b0cbb56861", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/report.py": { + "a": 48, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9114.json b/mne-python/source/doc/sphinxext/prs/9114.json new file mode 100644 index 0000000000000000000000000000000000000000..b4f7983e9aeb412bbc3111551364903cc9d7e30d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9114.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "0ddde8c7703331644dbe06b1b023d979738eebb8", + "authors": [ + { + "n": "Valerii", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_mixed_source_space_inverse.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 31, + "d": 18 + }, + "mne/viz/tests/test_3d.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9115.json b/mne-python/source/doc/sphinxext/prs/9115.json new file mode 100644 index 0000000000000000000000000000000000000000..e9e007faa691ffd933ee62af078d9b93a99c850a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9115.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "afce272d889feac294c2c1cd27e28ceb3e68f880", + "authors": [ + { + "n": "Matteo Anelli", + "e": "matteanelli.96.11@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 5, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9117.json b/mne-python/source/doc/sphinxext/prs/9117.json new file mode 100644 index 0000000000000000000000000000000000000000..060a7474f163e8aad829a5178c2121750b19f596 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9117.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c638f74ac727aeaca3b9616e56115b990a84c7ba", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/datasets/limo/limo.py": { + "a": 6, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9118.json b/mne-python/source/doc/sphinxext/prs/9118.json new file mode 100644 index 0000000000000000000000000000000000000000..6c5f734cbdb78e6cc41b4e523776e0db5a80ce1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9118.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "ee187764ca1ecaddcb4c5f4bd94b192ccb5886e2", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 55, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 32, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9121.json b/mne-python/source/doc/sphinxext/prs/9121.json new file mode 100644 index 0000000000000000000000000000000000000000..7b671e4c76eb9a76e338536b305b22829a2bd50d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9121.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bd6dcf71e0ac975363491ddc2136845fd5a11e11", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 12, + "d": 24 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9122.json b/mne-python/source/doc/sphinxext/prs/9122.json new file mode 100644 index 0000000000000000000000000000000000000000..8e723fb4c57ea00d76efb1572e7219df7c64fab4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9122.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b9859ed6cc20cc5f006e00ae72621aa513f0cc9a", + "authors": [ + { + "n": "Britta Westner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "examples/inverse/plot_tf_dics.py": { + "a": 0, + "d": 124 + }, + "mne/beamformer/_dics.py": { + "a": 4, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9123.json b/mne-python/source/doc/sphinxext/prs/9123.json new file mode 100644 index 0000000000000000000000000000000000000000..0c82d2fd281d2ac7dfb3938f87c45e6dd9050fd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9123.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5f0beb93f325ecd53e88fca500f1d08fbead863e", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 14, + "d": 6 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 4, + "d": 5 + }, + "mne/viz/backends/_abstract.py": { + "a": 49, + "d": 22 + }, + "mne/viz/backends/_notebook.py": { + "a": 22, + "d": 10 + }, + "mne/viz/backends/_qt.py": { + "a": 25, + "d": 13 + }, + "mne/viz/utils.py": { + "a": 14, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9124.json b/mne-python/source/doc/sphinxext/prs/9124.json new file mode 100644 index 0000000000000000000000000000000000000000..43e7259cf1aad6cf6934769a660ee8d4bccb976e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9124.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "5ae29cd69aa6075dc9ecd97402571ff7b2a03d21", + "authors": [ + { + "n": "Felix Klotzsche", + "e": "klotzsche@cbs.mpg.de" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "eioe", + "e": "klotzsche@cbs.mpg.de" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 252, + "d": 65 + }, + "mne/time_frequency/tfr.py": { + "a": 135, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9127.json b/mne-python/source/doc/sphinxext/prs/9127.json new file mode 100644 index 0000000000000000000000000000000000000000..547b1a66f5d0989edb3cafdd4d55a7708ddfa6d6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9127.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "ab0f417b94767890e06ba62e6f770e46e912be6d", + "authors": [ + { + "n": "Ram PARI", + "e": null + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/references.bib": { + "a": 12, + "d": 0 + }, + "tutorials/preprocessing/plot_55_setting_eeg_reference.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9128.json b/mne-python/source/doc/sphinxext/prs/9128.json new file mode 100644 index 0000000000000000000000000000000000000000..ba71facb5b22031e9fab7a2ec524967e5db008e5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9128.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "82f8476316385233dd35a4dc4e448730f4c39726", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/cancel.yml": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/913.json b/mne-python/source/doc/sphinxext/prs/913.json new file mode 100644 index 0000000000000000000000000000000000000000..2226f7aedb93052d3f67827d5f87889a3713bc4e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/913.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cf980143f2302af3d452d0d7615878674570a6d6", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 11, + "d": 55 + }, + "mne/tests/test_source_estimate.py": { + "a": 0, + "d": 25 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9130.json b/mne-python/source/doc/sphinxext/prs/9130.json new file mode 100644 index 0000000000000000000000000000000000000000..e41b35ce1afb75206ba8054da06278b23acb2b4c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9130.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "34d338bcff0f21fae35114e14c692ccbe7213e10", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + } + ], + "changes": { + ".gitignore": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9132.json b/mne-python/source/doc/sphinxext/prs/9132.json new file mode 100644 index 0000000000000000000000000000000000000000..b2962fd2c4e482b42140895a647d9ce25fa83d56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9132.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "d8dbf98c005822f99112f5927975e13894f9c2ca", + "authors": [ + { + "n": "Matteo Anelli", + "e": "matteanelli.96.11@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 7, + "d": 0 + }, + "mne/viz/tests/test_evoked.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9135.json b/mne-python/source/doc/sphinxext/prs/9135.json new file mode 100644 index 0000000000000000000000000000000000000000..a5ea9f9461267f017ee4053f4a06ffdfbf0ffdf7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9135.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "62ca227ef00086cd644b2a1ddcb291501a506485", + "authors": [ + { + "n": "Falach", + "e": "rotemfa0@gmail.com" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/channels/channels.py": { + "a": 21, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 25, + "d": 0 + }, + "mne/io/reference.py": { + "a": 3, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9136.json b/mne-python/source/doc/sphinxext/prs/9136.json new file mode 100644 index 0000000000000000000000000000000000000000..3e6a3ad4e0f1c3bf9fd0f3b4929ef1bed6387a4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9136.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "98fb5c26dee0b5c36a666e945fecd4423e0b712e", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/defaults.py": { + "a": 7, + "d": 0 + }, + "mne/io/base.py": { + "a": 122, + "d": 2 + }, + "mne/io/tests/test_raw.py": { + "a": 73, + "d": 0 + }, + "mne/tests/test_defaults.py": { + "a": 5, + "d": 47 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9139.json b/mne-python/source/doc/sphinxext/prs/9139.json new file mode 100644 index 0000000000000000000000000000000000000000..52f042eebdfa4757813210c4809a7e785e1f7719 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9139.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "598cde5e7b6304a06d80fd68dbd3c163d2563711", + "authors": [ + { + "n": "Catalina M. Galván", + "e": null + } + ], + "changes": { + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/914.json b/mne-python/source/doc/sphinxext/prs/914.json new file mode 100644 index 0000000000000000000000000000000000000000..3f81a99a9a6648736eff319a3756021ab268752b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/914.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2181d56d29adbe6a23f0d9f5fd744b8fb810beef", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/classifier.py": { + "a": 6, + "d": 5 + }, + "mne/fiff/raw.py": { + "a": 8, + "d": 7 + }, + "mne/filter.py": { + "a": 54, + "d": 37 + }, + "mne/preprocessing/ssp.py": { + "a": 13, + "d": 10 + }, + "mne/tests/test_filter.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9140.json b/mne-python/source/doc/sphinxext/prs/9140.json new file mode 100644 index 0000000000000000000000000000000000000000..e2c8677cc1694975dbc69f9554f8d29c19297d1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9140.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b27e06fb1d7f2d8445f7d26f3b4be907fe066335", + "authors": [ + { + "n": "Catalina M. Galván", + "e": null + } + ], + "changes": { + "tutorials/sample-datasets/plot_brainstorm_auditory.py": { + "a": 4, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9141.json b/mne-python/source/doc/sphinxext/prs/9141.json new file mode 100644 index 0000000000000000000000000000000000000000..b1d745bc0188f967be38c88c975ca2a9a716b3e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9141.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "e4a157174c3ae386072a6ead360efb8b32a5f729", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Johann Benerradi", + "e": "johann.benerradi@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 6, + "d": 2 + }, + "mne/channels/data/montages/artinis-brite23.elc": { + "a": 48, + "d": 0 + }, + "mne/channels/data/montages/artinis-octamon.elc": { + "a": 32, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 59, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 173, + "d": 4 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 138, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9142.json b/mne-python/source/doc/sphinxext/prs/9142.json new file mode 100644 index 0000000000000000000000000000000000000000..f9d8307d5f369d2f724133f930b42530cefb0128 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9142.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f09dfb38010e1d0bfbb251409ae53730b5787014", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + } + ], + "changes": { + "mne/stats/parametric.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9143.json b/mne-python/source/doc/sphinxext/prs/9143.json new file mode 100644 index 0000000000000000000000000000000000000000..45e7e7d5aa655c1a25a2c36808be93cc8498cf0e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9143.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "56e41c942af6b06082f2756b19cf2e499674289c", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + } + ], + "changes": { + "tutorials/sample-datasets/plot_brainstorm_phantom_ctf.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9144.json b/mne-python/source/doc/sphinxext/prs/9144.json new file mode 100644 index 0000000000000000000000000000000000000000..ba7e5ad7643eb9cef2d03435f9752135fbcbbc76 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9144.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4ca89e6322a583fd16bfe957d98314b2ce8f0f72", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + } + ], + "changes": { + "tutorials/source-modeling/plot_dipole_orientations.py": { + "a": 10, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9145.json b/mne-python/source/doc/sphinxext/prs/9145.json new file mode 100644 index 0000000000000000000000000000000000000000..6faf506563d76f38009a9ae36aeba1cbcb53320b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9145.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b24f531d39c954d7923d49ff454c50bb4dc8e43d", + "authors": [ + { + "n": "Giorgio_M", + "e": "giorgio.marinato@unitn.it" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "examples/preprocessing/plot_run_ica.py": { + "a": 0, + "d": 64 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 51, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9146.json b/mne-python/source/doc/sphinxext/prs/9146.json new file mode 100644 index 0000000000000000000000000000000000000000..59d860133021b941d3b00762eb37d55570de6f5e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9146.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "0816e31439a01e7ba6a1488fb006ae75dd25ac57", + "authors": [ + { + "n": "Catalina M. Galván", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9147.json b/mne-python/source/doc/sphinxext/prs/9147.json new file mode 100644 index 0000000000000000000000000000000000000000..c49e39374947449e1dcfd15beb6a9250564f6c1b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9147.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "82b3459a35c1c61c3c2d1ab724aaf9ee831d791d", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + } + ], + "changes": { + "mne/connectivity/spectral.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9149.json b/mne-python/source/doc/sphinxext/prs/9149.json new file mode 100644 index 0000000000000000000000000000000000000000..016643c3ee6813ec353b58c6789f5ed7b5b41527 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9149.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "acf25ef4d0b781aeff573797238f422a048cb9c8", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 11, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 4, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 3, + "d": 0 + }, + "mne/viz/backends/_qt.py": { + "a": 42, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9150.json b/mne-python/source/doc/sphinxext/prs/9150.json new file mode 100644 index 0000000000000000000000000000000000000000..4a8e90fcd3dfa5c0961a58c93917400a7110486c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9150.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "10e1869f39a41250ef4706949b906361a9bc33fd", + "authors": [ + { + "n": "Eduard", + "e": "eduardxort@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 42, + "d": 9 + }, + "mne/time_frequency/tfr.py": { + "a": 56, + "d": 45 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9151.json b/mne-python/source/doc/sphinxext/prs/9151.json new file mode 100644 index 0000000000000000000000000000000000000000..c21ceda509d87d7a8c98a8165895dab4d77d020c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9151.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "39524d220bafae4935c9224140179b767ebd2689", + "authors": [ + { + "n": "Matteo Anelli", + "e": "matteanelli.96.11@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/check.py": { + "a": 10, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_evoked.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9152.json b/mne-python/source/doc/sphinxext/prs/9152.json new file mode 100644 index 0000000000000000000000000000000000000000..66727bec0d96222c68c03376fb54ccb7c6902dac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9152.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "46d00e571a2bc7511f17ab103d64b4d6fafbde3d", + "authors": [ + { + "n": "Maggie Clarke", + "e": "mdclarke@uw.edu" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 11, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9153.json b/mne-python/source/doc/sphinxext/prs/9153.json new file mode 100644 index 0000000000000000000000000000000000000000..d397d1aedf01a614c9399177a1b10b034022d845 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9153.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "916f364ebacc0ac6ed8ee7854dbf904d143ee984", + "authors": [ + { + "n": "Ana Radanovic", + "e": null + } + ], + "changes": { + "doc/references.bib": { + "a": 12, + "d": 0 + }, + "mne/connectivity/spectral.py": { + "a": 14, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9154.json b/mne-python/source/doc/sphinxext/prs/9154.json new file mode 100644 index 0000000000000000000000000000000000000000..18096e410d5435043ad53cc7a115420d866a8959 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9154.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b1148741a95ac102e250d47c4f965c0df3e62618", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/datasets/spm_faces_dataset.py": { + "a": 2, + "d": 1 + }, + "examples/preprocessing/plot_find_ref_artifacts.py": { + "a": 4, + "d": 2 + }, + "examples/preprocessing/plot_ica_comparison.py": { + "a": 1, + "d": 1 + }, + "examples/preprocessing/plot_run_ica.py": { + "a": 3, + "d": 1 + }, + "tutorials/preprocessing/plot_40_artifact_correction_ica.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9156.json b/mne-python/source/doc/sphinxext/prs/9156.json new file mode 100644 index 0000000000000000000000000000000000000000..6afcccda90b3eae44f0605f2c87a45630cba34d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9156.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d885e4a43dd407a3d4e137e57e7df34683ed9390", + "authors": [ + { + "n": "nordme", + "e": "nordme@uw.edu" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/epochs/plot_60_make_fixed_length_epochs.py": { + "a": 132, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9157.json b/mne-python/source/doc/sphinxext/prs/9157.json new file mode 100644 index 0000000000000000000000000000000000000000..850610419e5e49f8e9a92143a5ab2b92aca09983 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9157.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8c5f92d112b3c01a1fe96ee31f75552d0781d067", + "authors": [ + { + "n": "Apoorva Karekal", + "e": null + } + ], + "changes": { + "mne/transforms.py": { + "a": 8, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/916.json b/mne-python/source/doc/sphinxext/prs/916.json new file mode 100644 index 0000000000000000000000000000000000000000..eb6b98f6e32f4e2a75239b028b2019f2b032af9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/916.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4a1f46b77a384564e47cf3a69d8891f4f38969ab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_viz.py": { + "a": 37, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9160.json b/mne-python/source/doc/sphinxext/prs/9160.json new file mode 100644 index 0000000000000000000000000000000000000000..8036f4baca6486814f97e1df8db722680b4a27dc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9160.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "fd1723fecccdbe01150b033a2943b03d9fe5292b", + "authors": [ + { + "n": "Eduard", + "e": "eduardxort@gmail.com" + } + ], + "changes": { + "mne/source_estimate.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9161.json b/mne-python/source/doc/sphinxext/prs/9161.json new file mode 100644 index 0000000000000000000000000000000000000000..0444e3ab3b5593178f7f4996a572dbf38361b634 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9161.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "bc78db538a6cd761742c614d716904a571aa8ee1", + "authors": [ + { + "n": "Valerii", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/data/html_templates.py": { + "a": 67, + "d": 0 + }, + "mne/io/base.py": { + "a": 8, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 26, + "d": 1 + }, + "mne/report.py": { + "a": 3, + "d": 85 + }, + "tutorials/intro/plot_30_info.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9162.json b/mne-python/source/doc/sphinxext/prs/9162.json new file mode 100644 index 0000000000000000000000000000000000000000..aeb4a24d5351a66c29d38ff6aef149c1c8d9b263 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9162.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "bbcba957bcef31af9b49262ff1435a3c45c2e1df", + "authors": [ + { + "n": "Ram PARI", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9163.json b/mne-python/source/doc/sphinxext/prs/9163.json new file mode 100644 index 0000000000000000000000000000000000000000..c08c6c1d0ddbf0c1395c773639becaf24dd952df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9163.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e9dc11fd496c1085bab519e3881cf5764c8645ee", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/channels/layout.py": { + "a": 6, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 10, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9164.json b/mne-python/source/doc/sphinxext/prs/9164.json new file mode 100644 index 0000000000000000000000000000000000000000..80ed20db9ee6817bf8ab7837a11ac8796010c29d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9164.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2500586c484a759062c802fa5679322afaf8237c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_transformer.py": { + "a": 44, + "d": 33 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9165.json b/mne-python/source/doc/sphinxext/prs/9165.json new file mode 100644 index 0000000000000000000000000000000000000000..9f8abf26668c74df9ff1fc133f2fc7b3514fa27f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9165.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "856f6122001f34436b2b11bdf7ebcf471c7cef63", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 1, + "d": 2 + }, + "mne/coreg.py": { + "a": 4, + "d": 51 + }, + "mne/source_space.py": { + "a": 49, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9166.json b/mne-python/source/doc/sphinxext/prs/9166.json new file mode 100644 index 0000000000000000000000000000000000000000..68aa41271274413cabc3ee351e57e76d3c46fd49 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9166.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "0c225f44f990b13c42389c56719f2008b0f9b4f6", + "authors": [ + { + "n": "Steven Bierer", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/simulation/raw.py": { + "a": 11, + "d": 4 + }, + "mne/simulation/source.py": { + "a": 63, + "d": 38 + }, + "mne/simulation/tests/test_raw.py": { + "a": 28, + "d": 1 + }, + "mne/simulation/tests/test_source.py": { + "a": 36, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9169.json b/mne-python/source/doc/sphinxext/prs/9169.json new file mode 100644 index 0000000000000000000000000000000000000000..c893985026bdd2514ac072babd78c58f1076614f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9169.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "dc4545c7d0a80791a26d9e3c3651d336202b2bb1", + "authors": [ + { + "n": "Apoorva Karekal", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/overview/migrating.rst": { + "a": 33, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/917.json b/mne-python/source/doc/sphinxext/prs/917.json new file mode 100644 index 0000000000000000000000000000000000000000..d472e11c02ec3cec3972d7f5321d460236a4a838 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/917.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "397036343047346375672e8e78b9591914ae4a9a", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 9, + "d": 1 + }, + "examples/connectivity/plot_cwt_sensor_connectivity.py": { + "a": 3, + "d": 3 + }, + "examples/datasets/plot_spm_faces_dataset.py": { + "a": 0, + "d": 2 + }, + "examples/plot_ssp_projs_topomaps.py": { + "a": 5, + "d": 5 + }, + "examples/plot_topo_channel_epochs_image.py": { + "a": 1, + "d": 2 + }, + "examples/stats/plot_sensor_permutation_test.py": { + "a": 1, + "d": 2 + }, + "examples/time_frequency/plot_tfr_topography.py": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 2, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 2 + }, + "mne/layouts/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/layouts/layout.py": { + "a": 98, + "d": 16 + }, + "mne/layouts/tests/test_layout.py": { + "a": 99, + "d": 3 + }, + "mne/utils.py": { + "a": 28, + "d": 0 + }, + "mne/viz.py": { + "a": 10, + "d": 54 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9170.json b/mne-python/source/doc/sphinxext/prs/9170.json new file mode 100644 index 0000000000000000000000000000000000000000..47e4c45045c30804bfe7af6949277052a178e66e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9170.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "12b43d605332b567382d2a9ed350d37d1e0042a2", + "authors": [ + { + "n": "nordme", + "e": "nordme@uw.edu" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9171.json b/mne-python/source/doc/sphinxext/prs/9171.json new file mode 100644 index 0000000000000000000000000000000000000000..9beb6af30e627148b58fe3ff639790e2226bb9ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9171.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8eda56f0c0ca106194f81e9a27064291d1ffa245", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/epochs/plot_60_make_fixed_length_epochs.py": { + "a": 31, + "d": 51 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9172.json b/mne-python/source/doc/sphinxext/prs/9172.json new file mode 100644 index 0000000000000000000000000000000000000000..08aaae88774c7babfc1e12a2f71ba755fd48ca16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9172.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "1e403b2f5708f624871eed7661a2b81b6259114c", + "authors": [ + { + "n": "Valerii", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/data/html_templates.py": { + "a": 13, + "d": 3 + }, + "mne/io/base.py": { + "a": 5, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9174.json b/mne-python/source/doc/sphinxext/prs/9174.json new file mode 100644 index 0000000000000000000000000000000000000000..7c2fc3c6da000e9dd3d7bd8bf6367d8fecc8766c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9174.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7db3238ce80d094bc65518486c4f3d1c83421640", + "authors": [ + { + "n": "Valerii", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 5, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 24, + "d": 35 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9175.json b/mne-python/source/doc/sphinxext/prs/9175.json new file mode 100644 index 0000000000000000000000000000000000000000..a535f2ecedf516b9f24ba05bc5c2021e0cfd0001 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9175.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b5e9c38eef38565799596205ecc0e1a2dc967f0b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 30, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9178.json b/mne-python/source/doc/sphinxext/prs/9178.json new file mode 100644 index 0000000000000000000000000000000000000000..a2abbc62bf420f7fcd71eb3f06b3ee4972bdb3ab --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9178.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "66430ed77e2f08745b9f4622801c5dc4ca1a5d73", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/io/pick.py": { + "a": 10, + "d": 8 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 5, + "d": 2 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 112, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9179.json b/mne-python/source/doc/sphinxext/prs/9179.json new file mode 100644 index 0000000000000000000000000000000000000000..699e742433fb39fce0ee865cdf1912eb7d158aff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9179.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "75a408ed7069bdcd6c6fd12ae12385328ef13e70", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/918.json b/mne-python/source/doc/sphinxext/prs/918.json new file mode 100644 index 0000000000000000000000000000000000000000..ee8abe59321b9ed72ac31f4c3e61ae78356c510c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/918.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "29b509dd5045cf62cbf092e95e358dd77e45938f", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/datasets/sample/sample.py": { + "a": 3, + "d": 6 + }, + "mne/datasets/utils.py": { + "a": 10, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9180.json b/mne-python/source/doc/sphinxext/prs/9180.json new file mode 100644 index 0000000000000000000000000000000000000000..3eae20754a9086b72eddc737a1d753da8d03f0fb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9180.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "2c888c5e68af64a8babe62539d34704c9ffca2bd", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 6 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_abstract.py": { + "a": 14, + "d": 6 + }, + "mne/viz/backends/_notebook.py": { + "a": 6, + "d": 12 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 37 + }, + "mne/viz/backends/_qt.py": { + "a": 69, + "d": 60 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9183.json b/mne-python/source/doc/sphinxext/prs/9183.json new file mode 100644 index 0000000000000000000000000000000000000000..ee8f7814033fbb3ffbca52884e640055ed5d4578 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9183.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e430158cee998776551efffbb343e4e42a45ae37", + "authors": [ + { + "n": "Valerii", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 9, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 94, + "d": 46 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9184.json b/mne-python/source/doc/sphinxext/prs/9184.json new file mode 100644 index 0000000000000000000000000000000000000000..22af9ad1ba61f752d44567b5787c505f662417be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9184.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e365bfb18f48f863975ed3e099c7c290787c4b45", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/preprocessing/nirs/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 3, + "d": 0 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 21, + "d": 2 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 120, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9185.json b/mne-python/source/doc/sphinxext/prs/9185.json new file mode 100644 index 0000000000000000000000000000000000000000..2bc8d97087b693d0e293565bed12d5cb0333bb4c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9185.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "70709f5069ddb413c2719f4d2b41fd6bfea2349a", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 66, + "d": 24 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 56, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9187.json b/mne-python/source/doc/sphinxext/prs/9187.json new file mode 100644 index 0000000000000000000000000000000000000000..ac7599a071c99466a70b5d9dad8f5de00b46f6f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9187.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "19db73552fda221499f652b7c7b30335fccae045", + "authors": [ + { + "n": "Sumalyo Datta", + "e": null + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9189.json b/mne-python/source/doc/sphinxext/prs/9189.json new file mode 100644 index 0000000000000000000000000000000000000000..b5836711a984d9f69ae734cacf37f354f2883cb0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9189.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "a98c4f5ce9d8272b0b7528b3054c74b8d43373ae", + "authors": [ + { + "n": "Valerii", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/data/html_templates.py": { + "a": 25, + "d": 0 + }, + "mne/epochs.py": { + "a": 26, + "d": 0 + }, + "mne/report.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 0 + }, + "tutorials/misc/plot_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9190.json b/mne-python/source/doc/sphinxext/prs/9190.json new file mode 100644 index 0000000000000000000000000000000000000000..49a97a8163dffcbe77eb5a842b37e21e73e5a3e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9190.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "176680a238a7c4f132fdd9198fc7bbe7797d764f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 63, + "d": 83 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 8, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 26, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 61, + "d": 38 + }, + "mne/viz/backends/_pyvista.py": { + "a": 0, + "d": 6 + }, + "mne/viz/backends/_qt.py": { + "a": 59, + "d": 39 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9191.json b/mne-python/source/doc/sphinxext/prs/9191.json new file mode 100644 index 0000000000000000000000000000000000000000..66adfee0ef97bb1c0fa8a03718b84ddea48dde80 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9191.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "13a0de51bd0f13113d866e73522fb60bdde37809", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9192.json b/mne-python/source/doc/sphinxext/prs/9192.json new file mode 100644 index 0000000000000000000000000000000000000000..bc67c40683a65490ea1b77f794d9c8e6cfd87b21 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9192.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "c6b22e82b64da0ed0f52a5f28bd4711e47090f9e", + "authors": [ + { + "n": "Jack Zhang", + "e": "me@jackzhang.me" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 52, + "d": 2 + }, + "mne/io/base.py": { + "a": 57, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 24, + "d": 1 + }, + "mne/io/utils.py": { + "a": 21, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 29, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 56, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 21, + "d": 0 + }, + "requirements_testing_extra.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9194.json b/mne-python/source/doc/sphinxext/prs/9194.json new file mode 100644 index 0000000000000000000000000000000000000000..e44c1dad71388a9420df4c056cfff59babc63389 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9194.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7350ca8697d149ead8454045fcd4fd1f7db50192", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + ".github/config.yml": { + "a": 21, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9196.json b/mne-python/source/doc/sphinxext/prs/9196.json new file mode 100644 index 0000000000000000000000000000000000000000..c342398208f1e2a11ea8a08ead6980b18eef7dd5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9196.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "acffc2ec986de456792503b5a6901fd68889bf8a", + "authors": [ + { + "n": "Sumalyo Datta", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9197.json b/mne-python/source/doc/sphinxext/prs/9197.json new file mode 100644 index 0000000000000000000000000000000000000000..77cbf243e574ecfac258cb005bf84eb08dd575fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9197.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4ba386be39394ac1406e0e4366b27a5e416e8f03", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/simulation/plot_source_simulator.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 2, + "d": 12 + }, + "mne/simulation/source.py": { + "a": 8, + "d": 5 + }, + "mne/simulation/tests/test_source.py": { + "a": 2, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9200.json b/mne-python/source/doc/sphinxext/prs/9200.json new file mode 100644 index 0000000000000000000000000000000000000000..f08f77d9da807a17742ef07f8682ad2ab398ab20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9200.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "148de1661d5e43cc88d62e27731ce44e78892951", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 7, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 12, + "d": 13 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9202.json b/mne-python/source/doc/sphinxext/prs/9202.json new file mode 100644 index 0000000000000000000000000000000000000000..7c1575556d903d09b44be7207cf808a360c62831 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9202.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "88df35fc65015a65b806d825ea7ea39488ea597c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 8, + "d": 20 + }, + "doc/_templates/docs-toc.html": { + "a": 0, + "d": 17 + }, + "doc/_templates/layout.html": { + "a": 28, + "d": 11 + }, + "doc/_templates/sidebar-funders.html": { + "a": 0, + "d": 17 + }, + "doc/_templates/sidebar-quicklinks.html": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 56, + "d": 18 + }, + "doc/funding.rst": { + "a": 50, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9203.json b/mne-python/source/doc/sphinxext/prs/9203.json new file mode 100644 index 0000000000000000000000000000000000000000..e75cb797073fdccc4287ab60a0d602aeee334ec8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9203.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2897d4b2609300da29f86707caf06fe29ecee74f", + "authors": [ + { + "n": "Jack Zhang", + "e": "me@jackzhang.me" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 41, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 7, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 53, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9204.json b/mne-python/source/doc/sphinxext/prs/9204.json new file mode 100644 index 0000000000000000000000000000000000000000..bc6d1f60c0f8af9282c6e33a48f69df9ccaa1611 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9204.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3afa03029f7237ff26b35b4fa4ae962661dcfd1d", + "authors": [ + { + "n": "Jack Zhang", + "e": "me@jackzhang.me" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/eeglab/eeglab.py": { + "a": 5, + "d": 0 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9207.json b/mne-python/source/doc/sphinxext/prs/9207.json new file mode 100644 index 0000000000000000000000000000000000000000..c019aa640137e6a8e891a97dcc7e64d4d3d1d44f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9207.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a067a3fbf2c19e60237e1b7ee76ed3ee9038a366", + "authors": [ + { + "n": "Ram PARI", + "e": null + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 16, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9208.json b/mne-python/source/doc/sphinxext/prs/9208.json new file mode 100644 index 0000000000000000000000000000000000000000..07aa44b7dd32140481b4224777eb4b2e27b59c84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9208.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "2a8d56b453ccf4e7b3b22a80bdd42d4ac604474e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 28, + "d": 101 + }, + "mne/utils/docs.py": { + "a": 75, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/921.json b/mne-python/source/doc/sphinxext/prs/921.json new file mode 100644 index 0000000000000000000000000000000000000000..2e098380fdf7d463204f26b74f2be3c89d7ee249 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/921.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "bb7cbaf14b8e1be34fc671ed760b32621beab3e0", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/getting_started.rst": { + "a": 4, + "d": 5 + }, + "doc/source/whats_new.rst": { + "a": 6, + "d": 2 + }, + "examples/inverse/plot_mixed_norm_L21_inverse.py": { + "a": 0, + "d": 3 + }, + "examples/inverse/plot_time_frequency_mixed_norm_inverse.py": { + "a": 0, + "d": 3 + }, + "examples/plot_evoked_delayed_ssp.py": { + "a": 1, + "d": 3 + }, + "examples/plot_megsim_data.py": { + "a": 0, + "d": 2 + }, + "examples/plot_shift_evoked.py": { + "a": 7, + "d": 4 + }, + "examples/preprocessing/plot_ica_from_epochs.py": { + "a": 0, + "d": 1 + }, + "examples/realtime/plot_compute_rt_average.py": { + "a": 7, + "d": 14 + }, + "mne/tests/test_viz.py": { + "a": 86, + "d": 77 + }, + "mne/viz.py": { + "a": 26, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9210.json b/mne-python/source/doc/sphinxext/prs/9210.json new file mode 100644 index 0000000000000000000000000000000000000000..978305d455bb7c3fb806b44b17ee2b80928cbea9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9210.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "53a86345321d5289e5895de2d59a1c188a182a74", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/baseline.py": { + "a": 77, + "d": 0 + }, + "mne/dipole.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 7, + "d": 80 + }, + "mne/evoked.py": { + "a": 127, + "d": 18 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_evoked.py": { + "a": 46, + "d": 4 + }, + "mne/tests/test_report.py": { + "a": 4, + "d": 2 + }, + "tutorials/evoked/plot_10_evoked_overview.py": { + "a": 20, + "d": 0 + }, + "tutorials/evoked/plot_20_visualize_evoked.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9211.json b/mne-python/source/doc/sphinxext/prs/9211.json new file mode 100644 index 0000000000000000000000000000000000000000..249e27a1e6b71c8491680c2005fd4007e96dc76c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9211.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8d6b115fa3475e87c2b2dbf638724a1697df09cd", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/preprocessing/nirs/nirs.py": { + "a": 5, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9212.json b/mne-python/source/doc/sphinxext/prs/9212.json new file mode 100644 index 0000000000000000000000000000000000000000..6109b0d80a0cff4cf31201640824ba20ff62c316 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9212.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5e38787306c147595252dbcf59572c017f4c8795", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 0 + }, + ".github/workflows/compat_minimal.yml": { + "a": 1, + "d": 0 + }, + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 0 + }, + ".github/workflows/linux_conda.yml": { + "a": 1, + "d": 0 + }, + ".github/workflows/linux_pip.yml": { + "a": 1, + "d": 0 + }, + ".github/workflows/macos_conda.yml": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9213.json b/mne-python/source/doc/sphinxext/prs/9213.json new file mode 100644 index 0000000000000000000000000000000000000000..dc9d089afd38ee5c87023cd0fe2c0e66a167c568 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9213.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "02bb98b35a34d49d22037e3d494ba1e4f83994de", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + ".github/workflows/cancel.yml": { + "a": 0, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9217.json b/mne-python/source/doc/sphinxext/prs/9217.json new file mode 100644 index 0000000000000000000000000000000000000000..abd36ceea47883bbf9aaead796a2fd9dd78a1aa1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9217.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b619f54aa80d248e353b54c8be1f6c4932dc3d80", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/utils/_testing.py": { + "a": 6, + "d": 4 + }, + "mne/viz/tests/test_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9218.json b/mne-python/source/doc/sphinxext/prs/9218.json new file mode 100644 index 0000000000000000000000000000000000000000..b7701e754bff5a4db2ad028300bf3bbbc17f08c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9218.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "58ccac70efcea3c4c785a14b4ca593523e466237", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 3, + "d": 9 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 21, + "d": 57 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9227.json b/mne-python/source/doc/sphinxext/prs/9227.json new file mode 100644 index 0000000000000000000000000000000000000000..f8999f827140897e234ef22f44024c6fcdd34697 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9227.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "53ce5871b6ceb466f665d41bc8db2938a2aa0084", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 2, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/boxy/boxy.py": { + "a": 2, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 3, + "d": 6 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 6, + "d": 4 + }, + "mne/io/curry/curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 5, + "d": 4 + }, + "mne/io/egi/egi.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/egimff.py": { + "a": 3, + "d": 1 + }, + "mne/io/eximia/eximia.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 7, + "d": 7 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 29, + "d": 6 + }, + "mne/io/nedf/nedf.py": { + "a": 2, + "d": 1 + }, + "mne/io/nihon/nihon.py": { + "a": 2, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 5, + "d": 4 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/persyst/persyst.py": { + "a": 2, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 2, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 36, + "d": 3 + }, + "mne/utils/check.py": { + "a": 19, + "d": 8 + }, + "mne/utils/tests/test_check.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9229.json b/mne-python/source/doc/sphinxext/prs/9229.json new file mode 100644 index 0000000000000000000000000000000000000000..ae7c65c604df52e16ccd93546f15da309bc3dd40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9229.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e243ee0e3e055c4e20a3f426bc9709fe5529010e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 57, + "d": 8 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 17, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9230.json b/mne-python/source/doc/sphinxext/prs/9230.json new file mode 100644 index 0000000000000000000000000000000000000000..3327894b91bc475baf7cb65e7aee053c8b75b5e7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9230.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b6542f5bbf4b5f5b444b8a9c601e32cd0b667de8", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9235.json b/mne-python/source/doc/sphinxext/prs/9235.json new file mode 100644 index 0000000000000000000000000000000000000000..eb244e608c0422cfbdad932220d1db69c75f89bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9235.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "5cc6eb8d7ebd102049843336d9d4a342f0f3e966", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 8, + "d": 8 + }, + "mne/evoked.py": { + "a": 3, + "d": 5 + }, + "mne/io/base.py": { + "a": 4, + "d": 5 + }, + "mne/io/tests/test_apply_function.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 24, + "d": 28 + }, + "mne/tests/test_evoked.py": { + "a": 8, + "d": 15 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9236.json b/mne-python/source/doc/sphinxext/prs/9236.json new file mode 100644 index 0000000000000000000000000000000000000000..de32a7edc7b7db9deaabc310ea3d8a03963247e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9236.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "067d25ab95b097f41de05c6b05a7b0967bafccbb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 26, + "d": 15 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9237.json b/mne-python/source/doc/sphinxext/prs/9237.json new file mode 100644 index 0000000000000000000000000000000000000000..3b40c4c832c2bbc9930770dd05d8128d259b9d40 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9237.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5cc8f2912329ea2aaf92bd02b6f144a37972d5c1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 15, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9239.json b/mne-python/source/doc/sphinxext/prs/9239.json new file mode 100644 index 0000000000000000000000000000000000000000..eaf104d9c604c06d15c0087e5007754f56e55d15 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9239.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a055120031b46ada317ebcf24b6eecd6a57cb322", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/stats/regression.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/924.json b/mne-python/source/doc/sphinxext/prs/924.json new file mode 100644 index 0000000000000000000000000000000000000000..8bdeeab0773c8df7d5dedbf6f4d65129035555e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/924.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ad3378490c66fa749873b295de3087646bf59890", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/forward/forward.py": { + "a": 8, + "d": 5 + }, + "mne/forward/tests/test_forward.py": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/inverse.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 0, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9240.json b/mne-python/source/doc/sphinxext/prs/9240.json new file mode 100644 index 0000000000000000000000000000000000000000..b2d9bc3681b5ceee5cfafb82024ac01a025cc97d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9240.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5f676980648e755f3fb84415eb44a504a27e3a8b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 1, + "d": 0 + }, + "tutorials/source-modeling/plot_mne_dspm_source_localization.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9241.json b/mne-python/source/doc/sphinxext/prs/9241.json new file mode 100644 index 0000000000000000000000000000000000000000..8e9b41e9564f7e19e9212d989744323fa8facf72 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9241.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "4080b4366fd5465a3f27df59f20cee050c430502", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 11, + "d": 5 + }, + "mne/channels/interpolation.py": { + "a": 8, + "d": 48 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 40, + "d": 2 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/interpolate.py": { + "a": 67, + "d": 0 + }, + "mne/preprocessing/tests/test_interpolate.py": { + "a": 60, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9243.json b/mne-python/source/doc/sphinxext/prs/9243.json new file mode 100644 index 0000000000000000000000000000000000000000..5d11e2480548fa4f6fec58be01b7b1c07add9a60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9243.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "7fbbef4dacff82d249826f99b2ec12474cef8f08", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/icons/README.rst": { + "a": 1, + "d": 1 + }, + "mne/icons/mne-bigsur-white.png": { + "a": 0, + "d": 0 + }, + "mne/icons/mne.qrc": { + "a": 1, + "d": 0 + }, + "mne/icons/resources.py": { + "a": 3445, + "d": 461 + }, + "mne/viz/backends/_pyvista.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9246.json b/mne-python/source/doc/sphinxext/prs/9246.json new file mode 100644 index 0000000000000000000000000000000000000000..253b551f34888b4e2376684421b16e72627b094a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9246.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ed485f9651c8d0a4ca116e3e7a6b6ad95741f364", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 4 + }, + "mne/channels/channels.py": { + "a": 8, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 34, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9247.json b/mne-python/source/doc/sphinxext/prs/9247.json new file mode 100644 index 0000000000000000000000000000000000000000..a376ef4b450b0dceb83df0a5566942490e86080f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9247.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "dcdbd071b117746d68972821da668d67fd225841", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 130, + "d": 78 + }, + "doc/conf.py": { + "a": 24, + "d": 8 + }, + "doc/install/mne_c.rst": { + "a": 2, + "d": 3 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/morph.py": { + "a": 5, + "d": 6 + }, + "tools/circleci_dependencies.sh": { + "a": 38, + "d": 9 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9248.json b/mne-python/source/doc/sphinxext/prs/9248.json new file mode 100644 index 0000000000000000000000000000000000000000..041602c6b77c49dc2bdd5228fe43717b6f8383bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9248.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2bfac6534e07a1b6f6f2e41aea446cdfbc4a4b32", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 3 + }, + "mne/viz/tests/test_3d.py": { + "a": 15, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/925.json b/mne-python/source/doc/sphinxext/prs/925.json new file mode 100644 index 0000000000000000000000000000000000000000..8bc104ef549ab2edb6e2492260fb191c61fdee59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/925.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "04a0e30246ea617ec8c8be7dee455476b0016ee5", + "authors": [ + { + "n": "Praveen Sripad", + "e": "pravsripad@gmail.com" + } + ], + "changes": { + "examples/time_frequency/plot_single_trial_spectra.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9251.json b/mne-python/source/doc/sphinxext/prs/9251.json new file mode 100644 index 0000000000000000000000000000000000000000..17ba464b993c696790d1c2dd28c3a78144ef86e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9251.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f6b4dd8326975aac3f1a1ec9899dd38c04879c4a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/tests/test_file_traits.py": { + "a": 4, + "d": 4 + }, + "mne/io/_digitization.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 31, + "d": 43 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 68, + "d": 38 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9252.json b/mne-python/source/doc/sphinxext/prs/9252.json new file mode 100644 index 0000000000000000000000000000000000000000..4316f67b84ecf35b791e53f04228db52248425a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9252.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d33e105e8f75965ae5171167032525e2e6b5501b", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9253.json b/mne-python/source/doc/sphinxext/prs/9253.json new file mode 100644 index 0000000000000000000000000000000000000000..7cf4a31b8ec7cdbebc6af768c65fad921fd82e0e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9253.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4891268d6e846324ca17884a5ac55354589b23e8", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9254.json b/mne-python/source/doc/sphinxext/prs/9254.json new file mode 100644 index 0000000000000000000000000000000000000000..a30d11a6d7dad2bbbbc4b14ac115abd5a97fdf24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9254.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "96b1d89364f867e9f901a2dcdd63d681371b6f98", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "doc/_static/style.css": { + "a": 2, + "d": 1 + }, + "doc/_templates/layout.html": { + "a": 0, + "d": 12 + }, + "doc/references.bib": { + "a": 104, + "d": 134 + }, + "tutorials/epochs/plot_40_autogenerate_metadata.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9259.json b/mne-python/source/doc/sphinxext/prs/9259.json new file mode 100644 index 0000000000000000000000000000000000000000..72e702e93025d0a2c04e4515eab02e96384ebedb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9259.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "ee639afd82c6ef2f04dc26eb156226a2fd0f1f2a", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 9, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9261.json b/mne-python/source/doc/sphinxext/prs/9261.json new file mode 100644 index 0000000000000000000000000000000000000000..ac0d6287a274dd4e4c2be8f660cadce82efd28d2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9261.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3ea17053b81df811e4a13f01985bce2f2d0291e6", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 56, + "d": 27 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9262.json b/mne-python/source/doc/sphinxext/prs/9262.json new file mode 100644 index 0000000000000000000000000000000000000000..ecaea1b4c6ee8f1b0e88fdfad962899a6a713f18 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9262.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3893c4e61d5d17526ecd8cb4b4cfbbf5799a195b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 5, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 30, + "d": 23 + }, + "mne/viz/tests/test_raw.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9266.json b/mne-python/source/doc/sphinxext/prs/9266.json new file mode 100644 index 0000000000000000000000000000000000000000..eec26e09fb877d275bd187d752125d7f68fda658 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9266.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "3bc8f4e35fb09f135a1b2c0e5ba9519cba470080", + "authors": [ + { + "n": "Mainak Jas", + "e": null + } + ], + "changes": { + "mne/channels/interpolation.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9268.json b/mne-python/source/doc/sphinxext/prs/9268.json new file mode 100644 index 0000000000000000000000000000000000000000..641f4f6f4c1ec9c87fbdf99c7f7c1288b0b34fbb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9268.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3d00c4567f59315ea253fb53f2fcfecdb00f31eb", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 7, + "d": 7 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 22, + "d": 0 + }, + "mne/io/open.py": { + "a": 10, + "d": 4 + }, + "mne/io/tag.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9269.json b/mne-python/source/doc/sphinxext/prs/9269.json new file mode 100644 index 0000000000000000000000000000000000000000..1cb75d4df947df16ab3cd22530a4add9d081b752 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9269.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e57f087e8bb368f75dcc5dad95f70417f7b10172", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/eog.py": { + "a": 37, + "d": 31 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 18, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/927.json b/mne-python/source/doc/sphinxext/prs/927.json new file mode 100644 index 0000000000000000000000000000000000000000..45d776bf206b839bc9ecbb486a166e809e14cf78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/927.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e391254f632e170ae14906de4fd26e2e7a8197e2", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/layouts/layout.py": { + "a": 5, + "d": 0 + }, + "mne/layouts/tests/test_layout.py": { + "a": 3, + "d": 0 + }, + "mne/tests/test_viz.py": { + "a": 8, + "d": 0 + }, + "mne/viz.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9270.json b/mne-python/source/doc/sphinxext/prs/9270.json new file mode 100644 index 0000000000000000000000000000000000000000..0c4231934ab38b050a3eed44ba5709b55d6d6b67 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9270.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "350f76bff4b590e3662830cf0308492638c27703", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + }, + { + "n": "Mainak Jas", + "e": "jasmainak@users.noreply.github.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/reference.py": { + "a": 80, + "d": 43 + }, + "mne/io/tests/test_reference.py": { + "a": 6, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9274.json b/mne-python/source/doc/sphinxext/prs/9274.json new file mode 100644 index 0000000000000000000000000000000000000000..80310177134c27be7c5a50ef154f386c77db53b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9274.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "392d5cab6e9460f177b5832d3201366ce58967e4", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 7, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 6, + "d": 2 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9275.json b/mne-python/source/doc/sphinxext/prs/9275.json new file mode 100644 index 0000000000000000000000000000000000000000..1312449294ba38f72715fbbb686a5016c7cbfae5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9275.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "dece6792280a7e3fe566b58e0e3c917b75edbcb5", + "authors": [ + { + "n": "Felix Klotzsche", + "e": "klotzsche@cbs.mpg.de" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 79, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9277.json b/mne-python/source/doc/sphinxext/prs/9277.json new file mode 100644 index 0000000000000000000000000000000000000000..3208e0ecb6f2b504fed345258072d01e4a48df4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9277.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "eaeef19153154c2e087961fd6d1fdcc6613d0b88", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ssp.py": { + "a": 4, + "d": 4 + }, + "mne/preprocessing/tests/test_ssp.py": { + "a": 12, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9278.json b/mne-python/source/doc/sphinxext/prs/9278.json new file mode 100644 index 0000000000000000000000000000000000000000..3aa959a144ee3c07d527c509175dcc7b2209bf56 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9278.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "7b428b96c2a719902ae72a498618062f879d674c", + "authors": [ + { + "n": "Ram PARI", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/evoked.py": { + "a": 7, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 10, + "d": 6 + }, + "mne/viz/tests/test_topo.py": { + "a": 7, + "d": 0 + }, + "mne/viz/topo.py": { + "a": 17, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/928.json b/mne-python/source/doc/sphinxext/prs/928.json new file mode 100644 index 0000000000000000000000000000000000000000..8312c410c8787ba628deb8950b30c18b5d59b70f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/928.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9044b1fa76fa17de4a5e98e1709fa82323279841", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9280.json b/mne-python/source/doc/sphinxext/prs/9280.json new file mode 100644 index 0000000000000000000000000000000000000000..45567ad5a3168cbf2c924e2564d43fce4de0f2a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9280.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "53a79ec1b6d3c42951263a1e1aa6e7f9a4c2c6be", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/channels/interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 19, + "d": 19 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 23, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9282.json b/mne-python/source/doc/sphinxext/prs/9282.json new file mode 100644 index 0000000000000000000000000000000000000000..22a424ec79b1e1423004c6470f55d822119acb26 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9282.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "df6115ead7474c0374eda5958266fd02c9b5b1e0", + "authors": [ + { + "n": "Johann Benerradi", + "e": null + } + ], + "changes": { + "mne/channels/interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 6, + "d": 7 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9283.json b/mne-python/source/doc/sphinxext/prs/9283.json new file mode 100644 index 0000000000000000000000000000000000000000..f4d96c80afe3fd31c2ed32b74105764a8139a3f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9283.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "dcec6c68a887c06541ddee1cf0ecd253982b5936", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/edf/edf.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9284.json b/mne-python/source/doc/sphinxext/prs/9284.json new file mode 100644 index 0000000000000000000000000000000000000000..6f87b52a2bc3f327eab466afefb965343d6ac517 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9284.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "e8b28f25c000bc2ea7e730c170eecf65acc18b34", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/connectivity/plot_mixed_source_space_connectivity.py": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_coherence_epochs.py": { + "a": 0, + "d": 1 + }, + "examples/connectivity/plot_mne_inverse_connectivity_spectrum.py": { + "a": 1, + "d": 0 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation.py": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_envelope_correlation_volume.py": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_label_connectivity.py": { + "a": 2, + "d": 2 + }, + "examples/connectivity/plot_mne_inverse_psi_visual.py": { + "a": 0, + "d": 1 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 16, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 51, + "d": 0 + }, + "mne/utils/check.py": { + "a": 16, + "d": 13 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 5 + }, + "tools/get_minimal_commands.sh": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9285.json b/mne-python/source/doc/sphinxext/prs/9285.json new file mode 100644 index 0000000000000000000000000000000000000000..acc8866d6f261a148febb5254921126295e8066a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9285.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "36f5dcd355ab15dbc5b5e86fa7cc679997078f45", + "authors": [ + { + "n": "Ram PARI", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topo.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9287.json b/mne-python/source/doc/sphinxext/prs/9287.json new file mode 100644 index 0000000000000000000000000000000000000000..cdb20d4492dda800ee11692499fd6f767014a419 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9287.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "02978dfa847d5b089064897c2a22796ea0b1b88d", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/nicolet/nicolet.py": { + "a": 12, + "d": 5 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9288.json b/mne-python/source/doc/sphinxext/prs/9288.json new file mode 100644 index 0000000000000000000000000000000000000000..cd27cab92d3a1d07f0280acae7089f972f89dd37 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9288.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "f6d9c737cd3eb83b17b7cfead9e8fe78b3ffee53", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/copybutton.js": { + "a": 0, + "d": 66 + }, + "doc/_static/institution_logos/Telecom_Paris_Tech.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/Telecom_Paris_Tech.svg": { + "a": 1, + "d": 0 + }, + "doc/_static/mne_logo.svg": { + "a": 172, + "d": 740 + }, + "doc/_static/style.css": { + "a": 6, + "d": 5 + }, + "doc/_templates/copyright.html": { + "a": 1, + "d": 0 + }, + "doc/_templates/docs-navbar.html": { + "a": 0, + "d": 20 + }, + "doc/_templates/homepage.html": { + "a": 44, + "d": 0 + }, + "doc/_templates/layout.html": { + "a": 6, + "d": 53 + }, + "doc/_templates/version-switcher.html": { + "a": 11, + "d": 0 + }, + "doc/conf.py": { + "a": 8, + "d": 5 + }, + "doc/funding.rst": { + "a": 1, + "d": 1 + }, + "doc/index.rst": { + "a": 1, + "d": 1 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9289.json b/mne-python/source/doc/sphinxext/prs/9289.json new file mode 100644 index 0000000000000000000000000000000000000000..e3ac18e6603538152cab8863c408e7aa37fe47b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9289.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "c5b12979e4f3b0dd6861b71d26d4302e2288a027", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/references.bib": { + "a": 24, + "d": 14 + }, + "examples/io/plot_read_xdf.py": { + "a": 42, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + }, + "tutorials/io/plot_20_reading_eeg_data.py": { + "a": 101, + "d": 79 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/929.json b/mne-python/source/doc/sphinxext/prs/929.json new file mode 100644 index 0000000000000000000000000000000000000000..5247917cf751023090a659ef1b70082cc72e66f1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/929.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bf0afc451c7967c03d8000786382ff194dedf4dc", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/_static/institutions.png": { + "a": 0, + "d": 0 + }, + "doc/source/_static/logo.png": { + "a": 0, + "d": 0 + }, + "doc/source/_static/mne_logo.png": { + "a": 0, + "d": 0 + }, + "doc/source/_templates/layout.html": { + "a": 10, + "d": 2 + }, + "doc/upload_html.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9291.json b/mne-python/source/doc/sphinxext/prs/9291.json new file mode 100644 index 0000000000000000000000000000000000000000..f80ef5c84d0a901ab5bee9bdc051ec52cbef32c0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9291.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "d0a069547470ecbbf8210abae4ef06fff32d1e59", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 3, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 9, + "d": 12 + }, + "mne/viz/tests/test_3d.py": { + "a": 6, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9292.json b/mne-python/source/doc/sphinxext/prs/9292.json new file mode 100644 index 0000000000000000000000000000000000000000..fe9d672b2c192bb73c14f3130f0bf8e42fb89ef8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9292.json @@ -0,0 +1,819 @@ +{ + "merge_commit_sha": "507b3a4ed46325f1505ff2277ec2df58df36d875", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/_includes/channel_interpolation.rst": { + "a": 1, + "d": 1 + }, + "doc/_templates/layout.html": { + "a": 13, + "d": 0 + }, + "doc/conf.py": { + "a": 210, + "d": 4 + }, + "doc/overview/design_philosophy.rst": { + "a": 2, + "d": 0 + }, + "doc/overview/faq.rst": { + "a": 1, + "d": 2 + }, + "examples/connectivity/cwt_sensor_connectivity.py": { + "a": 0, + "d": 0 + }, + "examples/connectivity/mixed_source_space_connectivity.py": { + "a": 0, + "d": 0 + }, + "examples/connectivity/mne_inverse_coherence_epochs.py": { + "a": 0, + "d": 0 + }, + "examples/connectivity/mne_inverse_connectivity_spectrum.py": { + "a": 0, + "d": 0 + }, + "examples/connectivity/mne_inverse_envelope_correlation.py": { + "a": 0, + "d": 0 + }, + "examples/connectivity/mne_inverse_envelope_correlation_volume.py": { + "a": 0, + "d": 0 + }, + "examples/connectivity/mne_inverse_label_connectivity.py": { + "a": 0, + "d": 0 + }, + "examples/connectivity/mne_inverse_psi_visual.py": { + "a": 0, + "d": 0 + }, + "examples/connectivity/sensor_connectivity.py": { + "a": 0, + "d": 0 + }, + "examples/datasets/brainstorm_data.py": { + "a": 0, + "d": 0 + }, + "examples/datasets/hf_sef_data.py": { + "a": 0, + "d": 0 + }, + "examples/datasets/limo_data.py": { + "a": 0, + "d": 0 + }, + "examples/datasets/opm_data.py": { + "a": 0, + "d": 0 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 0, + "d": 0 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 0, + "d": 0 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 2, + "d": 0 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 0, + "d": 0 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 0, + "d": 0 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 2, + "d": 0 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 0, + "d": 0 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 0, + "d": 0 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 2, + "d": 0 + }, + "examples/decoding/ems_filtering.py": { + "a": 2, + "d": 0 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 2, + "d": 0 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 0, + "d": 0 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 0, + "d": 0 + }, + "examples/forward/forward_sensitivity_maps.py": { + "a": 0, + "d": 0 + }, + "examples/forward/left_cerebellum_volume_source.py": { + "a": 0, + "d": 0 + }, + "examples/forward/source_space_morphing.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/compute_mne_inverse_epochs_in_label.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/compute_mne_inverse_raw_in_label.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/covariance_whitening_dspm.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/custom_inverse_solver.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/dics_source_power.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/gamma_map_inverse.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/label_activation_from_stc.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/label_from_stc.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/label_source_activations.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/mne_cov_power.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/morph_surface_stc.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 1, + "d": 2 + }, + "examples/inverse/multidict_reweighted_tfmxne.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/psf_ctf_vertices.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/psf_ctf_vertices_lcmv.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/rap_music.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/read_inverse.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/read_stc.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/resolution_metrics.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/resolution_metrics_eegmeg.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/snr_estimate.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/source_space_snr.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 0, + "d": 0 + }, + "examples/inverse/vector_mne_solution.py": { + "a": 0, + "d": 0 + }, + "examples/io/elekta_epochs.py": { + "a": 0, + "d": 0 + }, + "examples/io/read_neo_format.py": { + "a": 0, + "d": 0 + }, + "examples/io/read_noise_covariance_matrix.py": { + "a": 0, + "d": 0 + }, + "examples/io/read_xdf.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/define_target_events.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/fnirs_artifact_removal.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/ica_comparison.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/interpolate_bad_channels.py": { + "a": 2, + "d": 0 + }, + "examples/preprocessing/movement_compensation.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/movement_detection.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/muscle_detection.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/otp.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/shift_evoked.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/virtual_evoked.py": { + "a": 0, + "d": 0 + }, + "examples/preprocessing/xdawn_denoising.py": { + "a": 2, + "d": 0 + }, + "examples/simulation/simulate_evoked_data.py": { + "a": 0, + "d": 0 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 0, + "d": 0 + }, + "examples/simulation/simulated_raw_data_using_subject_anatomy.py": { + "a": 0, + "d": 0 + }, + "examples/simulation/source_simulator.py": { + "a": 0, + "d": 0 + }, + "examples/stats/cluster_stats_evoked.py": { + "a": 0, + "d": 0 + }, + "examples/stats/fdr_stats_evoked.py": { + "a": 0, + "d": 0 + }, + "examples/stats/linear_regression_raw.py": { + "a": 0, + "d": 0 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 0, + "d": 0 + }, + "examples/stats/sensor_regression.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/compute_csd.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/compute_source_psd_epochs.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/source_power_spectrum.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/source_space_time_frequency.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/temporal_whitening.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 0, + "d": 0 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/3d_to_2d.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/channel_epochs_image.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 2, + "d": 0 + }, + "examples/visualization/eeglab_head_sphere.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/evoked_arrowmap.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/evoked_topomap.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/evoked_whitening.py": { + "a": 2, + "d": 0 + }, + "examples/visualization/meg_sensors.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/mne_helmet.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/montage_sgskip.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/parcellation.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/publication_figure.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/roi_erpimage_by_rt.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/sensor_noise_level.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/ssp_projs_sensitivity_map.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/topo_compare_conditions.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/topo_customized.py": { + "a": 0, + "d": 0 + }, + "examples/visualization/xhemi.py": { + "a": 0, + "d": 0 + }, + "tutorials/clinical/20_seeg.py": { + "a": 0, + "d": 0 + }, + "tutorials/clinical/30_ecog.py": { + "a": 0, + "d": 0 + }, + "tutorials/clinical/60_sleep.py": { + "a": 0, + "d": 0 + }, + "tutorials/clinical/README.txt": { + "a": 4, + "d": 0 + }, + "tutorials/discussions/README.txt": { + "a": 0, + "d": 5 + }, + "tutorials/discussions/plot_background_ica.py": { + "a": 0, + "d": 93 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 0, + "d": 0 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 0, + "d": 0 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 0, + "d": 0 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 0, + "d": 0 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 0, + "d": 0 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 0, + "d": 0 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 0, + "d": 0 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 0, + "d": 0 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 0, + "d": 0 + }, + "tutorials/evoked/40_whitened.py": { + "a": 0, + "d": 0 + }, + "tutorials/forward/10_background_freesurfer.py": { + "a": 0, + "d": 0 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 0, + "d": 0 + }, + "tutorials/forward/30_forward.py": { + "a": 1, + "d": 2 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 0, + "d": 0 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 0, + "d": 0 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 2, + "d": 0 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 2, + "d": 3 + }, + "tutorials/forward/README.txt": { + "a": 5, + "d": 0 + }, + "tutorials/intro/10_overview.py": { + "a": 0, + "d": 0 + }, + "tutorials/intro/15_inplace.py": { + "a": 101, + "d": 0 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/30_info.py": { + "a": 0, + "d": 0 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 1, + "d": 2 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 0, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 13, + "d": 5 + }, + "tutorials/inverse/10_stc_class.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/40_mne_fixed_free.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 0, + "d": 0 + }, + "tutorials/inverse/README.txt": { + "a": 2, + "d": 2 + }, + "tutorials/io/10_reading_meg_data.py": { + "a": 0, + "d": 0 + }, + "tutorials/io/20_reading_eeg_data.py": { + "a": 0, + "d": 0 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 0, + "d": 0 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 3, + "d": 3 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 0, + "d": 0 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 7, + "d": 8 + }, + "tutorials/misc/README.txt": { + "a": 0, + "d": 5 + }, + "tutorials/misc/plot_modifying_data_inplace.py": { + "a": 0, + "d": 78 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 9, + "d": 2 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 3, + "d": 1 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 0, + "d": 0 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 0, + "d": 0 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 0, + "d": 0 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 0, + "d": 0 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 0, + "d": 0 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 0, + "d": 0 + }, + "tutorials/sample-datasets/README.txt": { + "a": 0, + "d": 5 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 0, + "d": 0 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 0, + "d": 0 + }, + "tutorials/simulation/80_dics.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 0, + "d": 0 + }, + "tutorials/stats-source-space/70_cluster_rmANOVA_time_freq.py": { + "a": 0, + "d": 0 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 0, + "d": 0 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9296.json b/mne-python/source/doc/sphinxext/prs/9296.json new file mode 100644 index 0000000000000000000000000000000000000000..0a79a9309b0e28a69229edc75ee0b53706eb32e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9296.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "70bc735b3f95574fe93394c57bfebff15e12cf0c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_epochs.py": { + "a": 21, + "d": 0 + }, + "mne/utils/mixin.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9298.json b/mne-python/source/doc/sphinxext/prs/9298.json new file mode 100644 index 0000000000000000000000000000000000000000..0fa525c90f64ac3a42c605cf7e5e88da70ecc669 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9298.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8b2394b3ad6b18461c989b872396cc6228be6662", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9299.json b/mne-python/source/doc/sphinxext/prs/9299.json new file mode 100644 index 0000000000000000000000000000000000000000..3d3626eff4a813242c444409a9d33e93a92fe2d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9299.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "19b62e9054e954f147273a146e8e1d95f7339fa1", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 7, + "d": 2 + }, + "mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter_longname.vhdr": { + "a": 156, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 13, + "d": 2 + }, + "mne/tests/test_line_endings.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/93.json b/mne-python/source/doc/sphinxext/prs/93.json new file mode 100644 index 0000000000000000000000000000000000000000..32f5f89fc0c6575427c5097e3ea9cd70e4bcbf2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/93.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5e3c3c65356d1a01c22d5a17dba5653f8fd7483d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/raw.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/930.json b/mne-python/source/doc/sphinxext/prs/930.json new file mode 100644 index 0000000000000000000000000000000000000000..c7ddf63c952e8dbd08160f24b4c81c009023113c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/930.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "1cbb07e2a47e5321453dff540ec547baf2646cbf", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/source/_static/institutions.png": { + "a": 0, + "d": 0 + }, + "doc/source/_static/logo.png": { + "a": 0, + "d": 0 + }, + "doc/source/_static/mne_logo.png": { + "a": 0, + "d": 0 + }, + "doc/source/_templates/layout.html": { + "a": 10, + "d": 2 + }, + "doc/source/index.rst": { + "a": 7, + "d": 0 + }, + "doc/source/python_reference.rst": { + "a": 2, + "d": 2 + }, + "doc/upload_html.sh": { + "a": 2, + "d": 2 + }, + "mne/gui/__init__.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9300.json b/mne-python/source/doc/sphinxext/prs/9300.json new file mode 100644 index 0000000000000000000000000000000000000000..fc482ca6e0278882bd3fc1c46bd4f7eed3b89576 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9300.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bc9ed3f48d7fe1619af033a80ba0fef89abbcb1b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_transformer.py": { + "a": 0, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9305.json b/mne-python/source/doc/sphinxext/prs/9305.json new file mode 100644 index 0000000000000000000000000000000000000000..6301b8dab05be330a1889cee8d09c14cdfd13225 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9305.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ead743b4e6fbeb37aa8eca5547b958931f150c90", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9313.json b/mne-python/source/doc/sphinxext/prs/9313.json new file mode 100644 index 0000000000000000000000000000000000000000..5c589d6e510424e3932c7e60dc79a8ab9093766b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9313.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e8207aecf6bff7dda7b4290d2e30daed6b776669", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 1 + }, + "tutorials/sample-datasets/plot_phantom_4DBTi.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9314.json b/mne-python/source/doc/sphinxext/prs/9314.json new file mode 100644 index 0000000000000000000000000000000000000000..0d0e1e00f79d042749b8093accfa1067e12ade0c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9314.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "208a081ff36f867d33df1b0472d9a2e3b5156cb9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9315.json b/mne-python/source/doc/sphinxext/prs/9315.json new file mode 100644 index 0000000000000000000000000000000000000000..5de32c89a2189d243e4a725377e0c56333139f74 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9315.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "71e6476a471a548e72a9506ce70beaf7337b88fd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/surface.py": { + "a": 4, + "d": 0 + }, + "mne/viz/_brain/view.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 7, + "d": 3 + }, + "tools/circleci_download.sh": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_visualize_stc.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9316.json b/mne-python/source/doc/sphinxext/prs/9316.json new file mode 100644 index 0000000000000000000000000000000000000000..a713d0ed254bf58cbbfbc6b33b0e275642654d01 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9316.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6cd38e39dfc95ae99958373575f8d607fa6d1029", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9317.json b/mne-python/source/doc/sphinxext/prs/9317.json new file mode 100644 index 0000000000000000000000000000000000000000..7ae8aedd82ecbbf771bad919bc9336e488a0a539 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9317.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7c5448a3408a045f9e3bd872f8a2d58645bc4454", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 7, + "d": 4 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9318.json b/mne-python/source/doc/sphinxext/prs/9318.json new file mode 100644 index 0000000000000000000000000000000000000000..bc24c4586c3b8457341168807982f7db40e4c48c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9318.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0afbf07446a9b76d8094ea3c3377cf02833754de", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "examples/simulation/plot_simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_qt.py": { + "a": 2, + "d": 0 + }, + "tutorials/sample-datasets/plot_phantom_4DBTi.py": { + "a": 1, + "d": 1 + }, + "tutorials/source-modeling/plot_source_alignment.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/932.json b/mne-python/source/doc/sphinxext/prs/932.json new file mode 100644 index 0000000000000000000000000000000000000000..4a5e188e889a4e74bd0f6f3b760bf9b513b2b932 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/932.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "882fb9a5a06dc54cdc09df418490a76d065574ac", + "authors": [ + { + "n": "Hari Bharadwaj", + "e": null + } + ], + "changes": { + "mne/fiff/edf/edf.py": { + "a": 5, + "d": 4 + }, + "mne/fiff/edf/tests/data/biosemi.hpts": { + "a": 1, + "d": 1 + }, + "mne/fiff/edf/tests/test_edf.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9320.json b/mne-python/source/doc/sphinxext/prs/9320.json new file mode 100644 index 0000000000000000000000000000000000000000..4d2a75834411aa3db2a02dca9715aefa8b800a9d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9320.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "87c9eafdaf8fdab33ff1063d0d7bb03afac60bb5", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9321.json b/mne-python/source/doc/sphinxext/prs/9321.json new file mode 100644 index 0000000000000000000000000000000000000000..989b56bc12cb3ba0f5a9f4c62d171f2b9d3ea4df --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9321.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f10d0d34a7a9e01c8d9f7db3fb35df528de68989", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9323.json b/mne-python/source/doc/sphinxext/prs/9323.json new file mode 100644 index 0000000000000000000000000000000000000000..ccc612ad14b1d2c0ca3e29f4c9074084720291cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9323.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ec1d69950f94047c91a92e9c53b521304cba6a9c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 15, + "d": 15 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/sphinxext/gen_names.py": { + "a": 30, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9324.json b/mne-python/source/doc/sphinxext/prs/9324.json new file mode 100644 index 0000000000000000000000000000000000000000..690ae4ad829ea49c6b1e78953d60e056c90a6da9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9324.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "fe0d3e3317eef48dd7f18bacda620c43abc8cb0c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 11, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 4, + "d": 4 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 3, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 6, + "d": 3 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9325.json b/mne-python/source/doc/sphinxext/prs/9325.json new file mode 100644 index 0000000000000000000000000000000000000000..ae7671ae967533035a3fec7ee8170d29e36248f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9325.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9b2fc9cac7e96244d52f961ab734fe3dbf3348ab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 12, + "d": 12 + }, + "mne/report.py": { + "a": 5, + "d": 2 + }, + "tools/circleci_download.sh": { + "a": 3, + "d": 3 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9326.json b/mne-python/source/doc/sphinxext/prs/9326.json new file mode 100644 index 0000000000000000000000000000000000000000..042344ee8a90e437c6fd5ea741cb4ea7fa4ba469 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9326.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f96dfe27b2ccf9b21a513478fb96e62e133f0b38", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 32, + "d": 34 + }, + "mne/viz/epochs.py": { + "a": 0, + "d": 4 + }, + "mne/viz/ica.py": { + "a": 0, + "d": 4 + }, + "mne/viz/raw.py": { + "a": 0, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9329.json b/mne-python/source/doc/sphinxext/prs/9329.json new file mode 100644 index 0000000000000000000000000000000000000000..157ee1d584f8bdcc452b7e7c996e8b877031ef7a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9329.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aa526c8ed7049046734ca28493d99e841672b0eb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "tutorials/raw/30_annotate_raw.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9331.json b/mne-python/source/doc/sphinxext/prs/9331.json new file mode 100644 index 0000000000000000000000000000000000000000..91f074a5cf2de59847fc2ca3d41b118515f8c10d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9331.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "723ac8fe6f32ae2fbd6775983cfbe9885fcd67e6", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9332.json b/mne-python/source/doc/sphinxext/prs/9332.json new file mode 100644 index 0000000000000000000000000000000000000000..9f559fa80ecec3bd9061622f9a0de11478956c78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9332.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f90c5957bd99a98f7cfa286f62ccf2501f6ae6ed", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/tests/test_report.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9337.json b/mne-python/source/doc/sphinxext/prs/9337.json new file mode 100644 index 0000000000000000000000000000000000000000..442b7cff88d128190211e1cd1f8ef0ac9c6a3b98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9337.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "73bf7083d9b931d89227b28d5aab76e1f94a8332", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 3, + "d": 3 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "requirements_doc.txt": { + "a": 2, + "d": 1 + }, + "requirements_testing.txt": { + "a": 1, + "d": 3 + }, + "requirements_testing_extra.txt": { + "a": 4, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9340.json b/mne-python/source/doc/sphinxext/prs/9340.json new file mode 100644 index 0000000000000000000000000000000000000000..532fdf795fef35bf1e6b716715d506a44112b26e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9340.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "6ac763359a7fb2e9ee9aa610d02c475aedb44a7d", + "authors": [ + { + "n": "Britta Westner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/beamformer/_dics.py": { + "a": 14, + "d": 2 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9341.json b/mne-python/source/doc/sphinxext/prs/9341.json new file mode 100644 index 0000000000000000000000000000000000000000..e5857c5f9533f09674b339db974e32ba5774825c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9341.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "844d53c866bbea932dd6c89ab444bb7f882f0b6f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 2, + "d": 2 + }, + "environment.yml": { + "a": 3, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 6 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 6 + }, + "mne/viz/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 6 + }, + "requirements.txt": { + "a": 3, + "d": 3 + }, + "server_environment.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9344.json b/mne-python/source/doc/sphinxext/prs/9344.json new file mode 100644 index 0000000000000000000000000000000000000000..242d98b6bde79fe329aafb610b32625a776f2b92 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9344.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "b3cbe52713075f79087de3239133f25ad1606cf1", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 3 + }, + "mne/epochs.py": { + "a": 9, + "d": 7 + }, + "mne/io/base.py": { + "a": 6, + "d": 5 + }, + "mne/io/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9345.json b/mne-python/source/doc/sphinxext/prs/9345.json new file mode 100644 index 0000000000000000000000000000000000000000..675099606d1babe8894276cfff52db7c01028bbb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9345.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "307c99722201649873867ecb5ddda96384af1942", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/evoked/30_eeg_erp.py": { + "a": 286, + "d": 151 + }, + "tutorials/intro/15_inplace.py": { + "a": 16, + "d": 14 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 19, + "d": 17 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9346.json b/mne-python/source/doc/sphinxext/prs/9346.json new file mode 100644 index 0000000000000000000000000000000000000000..8d65a971c10ecfcdef25c4ca14f500e7ffcb093f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9346.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8a7115b731df45c0b997f68822eb94bff94f18ce", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9347.json b/mne-python/source/doc/sphinxext/prs/9347.json new file mode 100644 index 0000000000000000000000000000000000000000..3039f0242c3385785dde4d16f0d084ae32bfeea5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9347.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "e9924c0a693b4d5f0788168967c9e02c1d59fda1", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 9 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 69, + "d": 14 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 65, + "d": 12 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 11, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 0 + }, + "tools/get_testing_version.sh": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9348.json b/mne-python/source/doc/sphinxext/prs/9348.json new file mode 100644 index 0000000000000000000000000000000000000000..8aa0032b094f67104b56d4391ec1f346e5eeeebd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9348.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "2d1e3dfe569c569bf0331b7faca41c483e8b8237", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "David JULIEN", + "e": "david.julien@ifsttar.fr" + }, + { + "n": "Romain Derollepot", + "e": "romain.derollepot@univ-eiffel.fr" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 4, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 96, + "d": 31 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 91, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/annotate_nan.py": { + "a": 35, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 30, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9349.json b/mne-python/source/doc/sphinxext/prs/9349.json new file mode 100644 index 0000000000000000000000000000000000000000..8e6be3f9e8f02ff1998d7b432cba78ac83512fa5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9349.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "26abeb6b56cd1705d70acb09c804ff2c35bdb336", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/report.py": { + "a": 38, + "d": 13 + }, + "tutorials/intro/70_report.py": { + "a": 14, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/935.json b/mne-python/source/doc/sphinxext/prs/935.json new file mode 100644 index 0000000000000000000000000000000000000000..6d15be9ae491ed73ef521bff4949a236798226ec --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/935.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d22d8640d4864cf0ec6c778c5c8a6edb255f8fc7", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + ".travis.yml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9351.json b/mne-python/source/doc/sphinxext/prs/9351.json new file mode 100644 index 0000000000000000000000000000000000000000..cc7dfe21d9fb3ba6f7ae26c69c98315711cc093f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9351.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "255092b586a7aaded68c311bac4258bd75374eb9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 21, + "d": 8 + }, + "mne/viz/backends/_qt.py": { + "a": 17, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9352.json b/mne-python/source/doc/sphinxext/prs/9352.json new file mode 100644 index 0000000000000000000000000000000000000000..6bbe5ecd710283e5ae1b341fe79553dbb54365a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9352.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a352a8db3e6e57dddec4c0fb25c5dc31bd37c749", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".mailmap": { + "a": 27, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9353.json b/mne-python/source/doc/sphinxext/prs/9353.json new file mode 100644 index 0000000000000000000000000000000000000000..f8d5280c4b4f5fdf5b4f7feac1981579203a41e0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9353.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "286d39c91e79542e79d7ef1707726e860400111d", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9356.json b/mne-python/source/doc/sphinxext/prs/9356.json new file mode 100644 index 0000000000000000000000000000000000000000..4201ab0fec16fecaf6a7c205c152609eaf7fe322 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9356.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "96fffbb3f4796ea116fe1775abdaf30c35c88c22", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 36, + "d": 0 + }, + "doc/file_io.rst": { + "a": 0, + "d": 1 + }, + "doc/inverse.rst": { + "a": 0, + "d": 1 + }, + "mne/__init__.py": { + "a": 0, + "d": 4 + }, + "mne/beamformer/__init__.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/_dics.py": { + "a": 5, + "d": 339 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 148 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 8 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 10 + }, + "mne/preprocessing/tests/test_eog.py": { + "a": 0, + "d": 6 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 37 + }, + "mne/viz/tests/test_ica.py": { + "a": 0, + "d": 10 + }, + "mne/viz/tests/test_topomap.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9357.json b/mne-python/source/doc/sphinxext/prs/9357.json new file mode 100644 index 0000000000000000000000000000000000000000..7380bbb060d32c4385991a5e5236e32223c40776 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9357.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bc49d19a824d431aad3b1e8c6eacd93411fb9a11", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "environment.yml": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9358.json b/mne-python/source/doc/sphinxext/prs/9358.json new file mode 100644 index 0000000000000000000000000000000000000000..f8cbdcccd1448395a504ef00e5750ad59133f6b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9358.json @@ -0,0 +1,575 @@ +{ + "merge_commit_sha": "f1e6097c36e7232514d67d4b04af568e36ac5758", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/compat_old.yml": { + "a": 3, + "d": 3 + }, + "README.rst": { + "a": 11, + "d": 10 + }, + "doc/_templates/layout.html": { + "a": 0, + "d": 13 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "doc/overview/matlab.rst": { + "a": 3, + "d": 2 + }, + "doc/overview/roadmap.rst": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 3, + "d": 5 + }, + "mne/beamformer/tests/test_external.py": { + "a": 0, + "d": 4 + }, + "mne/bem.py": { + "a": 5, + "d": 6 + }, + "mne/channels/_dig_montage_utils.py": { + "a": 1, + "d": 9 + }, + "mne/channels/montage.py": { + "a": 2, + "d": 18 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 6 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 0, + "d": 4 + }, + "mne/channels/tests/test_layout.py": { + "a": 8, + "d": 13 + }, + "mne/channels/tests/test_montage.py": { + "a": 7, + "d": 9 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 3, + "d": 3 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 4, + "d": 4 + }, + "mne/commands/tests/test_commands.py": { + "a": 1, + "d": 4 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/coreg.py": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 2, + "d": 9 + }, + "mne/decoding/base.py": { + "a": 2, + "d": 6 + }, + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 4 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 4 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 4 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/fixes.py": { + "a": 20, + "d": 76 + }, + "mne/forward/_field_interpolation.py": { + "a": 15, + "d": 33 + }, + "mne/forward/_lead_dots.py": { + "a": 9, + "d": 10 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 2 + }, + "mne/forward/tests/test_field_interpolation.py": { + "a": 1, + "d": 5 + }, + "mne/forward/tests/test_forward.py": { + "a": 1, + "d": 5 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 5 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 1, + "d": 5 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 1, + "d": 4 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 1, + "d": 5 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 1, + "d": 5 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 1, + "d": 5 + }, + "mne/inverse_sparse/tests/test_gamma_map.py": { + "a": 1, + "d": 4 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 4 + }, + "mne/io/_digitization.py": { + "a": 0, + "d": 2 + }, + "mne/io/array/tests/test_array.py": { + "a": 0, + "d": 4 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 2, + "d": 6 + }, + "mne/io/base.py": { + "a": 1, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 4 + }, + "mne/io/bti/bti.py": { + "a": 2, + "d": 2 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 4 + }, + "mne/io/cnt/cnt.py": { + "a": 0, + "d": 3 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 1, + "d": 5 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 5 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 1, + "d": 4 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 0, + "d": 4 + }, + "mne/io/eeglab/tests/_utils.py": { + "a": 0, + "d": 38 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 2, + "d": 2 + }, + "mne/io/eximia/tests/test_eximia.py": { + "a": 0, + "d": 4 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 2, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 0, + "d": 1 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 0, + "d": 4 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 0, + "d": 4 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 4, + "d": 9 + }, + "mne/io/proc_history.py": { + "a": 1, + "d": 2 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 1, + "d": 4 + }, + "mne/io/tests/test_compensator.py": { + "a": 1, + "d": 4 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_pick.py": { + "a": 1, + "d": 4 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 2 + }, + "mne/io/tests/test_reference.py": { + "a": 2, + "d": 5 + }, + "mne/io/tests/test_what.py": { + "a": 1, + "d": 4 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 14, + "d": 15 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 0, + "d": 4 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/tests/test_time_frequency.py": { + "a": 0, + "d": 4 + }, + "mne/morph.py": { + "a": 4, + "d": 2 + }, + "mne/morph_map.py": { + "a": 232, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/tests/test_eeglab_infomax.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 3, + "d": 6 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/tests/test_otp.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/tests/test_peak_finder.py": { + "a": 0, + "d": 4 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 1, + "d": 2 + }, + "mne/report.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/raw.py": { + "a": 3, + "d": 4 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 4 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 0, + "d": 4 + }, + "mne/simulation/tests/test_source.py": { + "a": 1, + "d": 4 + }, + "mne/source_estimate.py": { + "a": 11, + "d": 15 + }, + "mne/stats/tests/test_permutations.py": { + "a": 1, + "d": 4 + }, + "mne/stats/tests/test_regression.py": { + "a": 1, + "d": 4 + }, + "mne/surface.py": { + "a": 11, + "d": 225 + }, + "mne/tests/test_annotations.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_coreg.py": { + "a": 1, + "d": 5 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_event.py": { + "a": 0, + "d": 4 + }, + "mne/tests/test_evoked.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_filter.py": { + "a": 1, + "d": 5 + }, + "mne/tests/test_label.py": { + "a": 7, + "d": 11 + }, + "mne/tests/test_line_endings.py": { + "a": 3, + "d": 6 + }, + "mne/tests/test_misc.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_morph_map.py": { + "a": 60, + "d": 0 + }, + "mne/tests/test_proj.py": { + "a": 0, + "d": 4 + }, + "mne/tests/test_read_vectorview_selection.py": { + "a": 0, + "d": 4 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 5 + }, + "mne/tests/test_source_estimate.py": { + "a": 5, + "d": 4 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_surface.py": { + "a": 13, + "d": 57 + }, + "mne/tests/test_transforms.py": { + "a": 30, + "d": 34 + }, + "mne/time_frequency/_stockwell.py": { + "a": 0, + "d": 1 + }, + "mne/time_frequency/tests/test_ar.py": { + "a": 1, + "d": 4 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 5, + "d": 8 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 0, + "d": 4 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 4, + "d": 7 + }, + "mne/transforms.py": { + "a": 2, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 4 + }, + "mne/utils/_testing.py": { + "a": 0, + "d": 28 + }, + "mne/utils/check.py": { + "a": 1, + "d": 11 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "mne/viz/_figure.py": { + "a": 1, + "d": 2 + }, + "mne/viz/backends/_abstract.py": { + "a": 3, + "d": 2 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 2 + }, + "mne/viz/backends/_pyvista.py": { + "a": 1, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 7 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 4 + }, + "mne/viz/tests/test_ica.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_topo.py": { + "a": 0, + "d": 4 + }, + "mne/viz/tests/test_utils.py": { + "a": 0, + "d": 4 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 3 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "setup.py": { + "a": 1, + "d": 1 + }, + "tools/github_actions_test.sh": { + "a": 0, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9359.json b/mne-python/source/doc/sphinxext/prs/9359.json new file mode 100644 index 0000000000000000000000000000000000000000..347283d5e2bdf6185ee1994e3e0452918f139a16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9359.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "61349981d3de5d749043e604790422b6754081b8", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "tutorials/evoked/20_visualize_evoked.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/10_background_freesurfer.py": { + "a": 96, + "d": 84 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 38, + "d": 40 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 3, + "d": 5 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9361.json b/mne-python/source/doc/sphinxext/prs/9361.json new file mode 100644 index 0000000000000000000000000000000000000000..1c88c53f8488749183f7cbb612c51752b86dbdd1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9361.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a3655f33e38d9703fe51b90d39d880557a2fc168", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 0, + "d": 16 + }, + ".github/workflows/compat_old.yml": { + "a": 0, + "d": 17 + }, + ".github/workflows/linux_conda.yml": { + "a": 0, + "d": 16 + }, + ".github/workflows/linux_pip.yml": { + "a": 0, + "d": 16 + }, + ".github/workflows/macos_conda.yml": { + "a": 0, + "d": 16 + }, + "doc/install/contributing.rst": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9362.json b/mne-python/source/doc/sphinxext/prs/9362.json new file mode 100644 index 0000000000000000000000000000000000000000..06331e6cedab07d90253a16cfd277c68a6477adc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9362.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "7e241cce1f78d1a21a0607ae9e2186e7f964e402", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/install/advanced.rst": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9363.json b/mne-python/source/doc/sphinxext/prs/9363.json new file mode 100644 index 0000000000000000000000000000000000000000..6a6df1e142ca062c0202a8aebf7831fb4cc062bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9363.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "674b8bd7f832d765266e048762074bc25cd100da", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/evoked/30_eeg_erp.py": { + "a": 8, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9365.json b/mne-python/source/doc/sphinxext/prs/9365.json new file mode 100644 index 0000000000000000000000000000000000000000..dbfcdf0bcd3c19cc2f2cf1e5cbbe4143d0d2977e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9365.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "68f1ec9670fdb38fd19020df4708c35c280bbc90", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/stats/_adjacency.py": { + "a": 24, + "d": 9 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9366.json b/mne-python/source/doc/sphinxext/prs/9366.json new file mode 100644 index 0000000000000000000000000000000000000000..3b764aafe20a93bc3ca70e974a4b2edc2def7429 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9366.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4ea049e5e825eec545b9aac4acf5156da6da5f2d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report.py": { + "a": 1, + "d": 2 + }, + "tutorials/intro/70_report.py": { + "a": 16, + "d": 14 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9367.json b/mne-python/source/doc/sphinxext/prs/9367.json new file mode 100644 index 0000000000000000000000000000000000000000..2c9248b19c01a5836b4ee67afda0a9da7d0a6ddc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9367.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "cb3c34f9a32fdc78777e2e4a0ecf0f7258860182", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/data/html_templates.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9368.json b/mne-python/source/doc/sphinxext/prs/9368.json new file mode 100644 index 0000000000000000000000000000000000000000..f156e49f15a618a757b530245e68ea0717354a28 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9368.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f3ff4f795a0248e757d025528ae80d3b02a73d78", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/io/nirx/nirx.py": { + "a": 3, + "d": 1 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 9, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9369.json b/mne-python/source/doc/sphinxext/prs/9369.json new file mode 100644 index 0000000000000000000000000000000000000000..bcf99d80f9e93d6ca6abbb89ab7162d9629aa98f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9369.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "8ccc3999da6c15efa03840230c13aeb7bab5618d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.23.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 39, + "d": 9 + }, + "mne/simulation/raw.py": { + "a": 2, + "d": 2 + }, + "mne/simulation/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 33, + "d": 7 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 0 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9375.json b/mne-python/source/doc/sphinxext/prs/9375.json new file mode 100644 index 0000000000000000000000000000000000000000..03b34aadba82fd218bb0436be058791a472e3706 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9375.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3149819463d4690146b3f038dca8441157abb36b", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 11, + "d": 10 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 19, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9376.json b/mne-python/source/doc/sphinxext/prs/9376.json new file mode 100644 index 0000000000000000000000000000000000000000..09d01ec353b2bf5ef9d1e12d2f796fd8224ffdd3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9376.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "a68e3dbf816946ba357e202d9f3d9dfe2a558636", + "authors": [ + { + "n": "mdovgialo", + "e": "marian.dowgialo@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/source_space.rst": { + "a": 1, + "d": 0 + }, + "mne/label.py": { + "a": 55, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 20, + "d": 2 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9378.json b/mne-python/source/doc/sphinxext/prs/9378.json new file mode 100644 index 0000000000000000000000000000000000000000..f96629407f0e68d15c2d62a91f7afd42ff38b8c7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9378.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "908f52a6e2c98308b4860e724ea3daa0a1d7ee3a", + "authors": [ + { + "n": "Jan Sosulski", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/evoked.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/938.json b/mne-python/source/doc/sphinxext/prs/938.json new file mode 100644 index 0000000000000000000000000000000000000000..fa660e58f1700ef9be100e47f4739a60cafaa6cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/938.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "dc015f8f2500751a28f3404c880c74561633c7f4", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 3, + "d": 3 + }, + "mne/gui/_coreg_gui.py": { + "a": 8, + "d": 5 + }, + "mne/gui/_file_traits.py": { + "a": 3, + "d": 0 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9381.json b/mne-python/source/doc/sphinxext/prs/9381.json new file mode 100644 index 0000000000000000000000000000000000000000..43f5c1a4a84c49f089d08e12f10d61dacb41882c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9381.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6afc7224de9e7423e57604ca307941cf0b3449f1", + "authors": [ + { + "n": "Xiaokai Xia", + "e": "xia@xiaokai.me" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/curry/curry.py": { + "a": 9, + "d": 6 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9384.json b/mne-python/source/doc/sphinxext/prs/9384.json new file mode 100644 index 0000000000000000000000000000000000000000..ea948b566d49c455d6e0b3fe396dd771c587fd9a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9384.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5e2a6d8eb0edefe3c46a5b3250a3a546224d1ce2", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9386.json b/mne-python/source/doc/sphinxext/prs/9386.json new file mode 100644 index 0000000000000000000000000000000000000000..508fd99d6675b0918fd53861d87908a1f7a0c4ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9386.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e8727cb016d034263a4f17e68e12b1ebf5dacc8d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 2, + "d": 2 + }, + "mne/dipole.py": { + "a": 2, + "d": 1 + }, + "mne/fixes.py": { + "a": 30, + "d": 0 + }, + "mne/io/reference.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9387.json b/mne-python/source/doc/sphinxext/prs/9387.json new file mode 100644 index 0000000000000000000000000000000000000000..19cfa7149b5f4970d39471a72dc6a3dbef398ae6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9387.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "ca991d8f6ec9121c6da00147baa961c04c74fa2a", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + }, + "doc/install/index.rst": { + "a": 1, + "d": 1 + }, + "doc/install/mne_python.rst": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9388.json b/mne-python/source/doc/sphinxext/prs/9388.json new file mode 100644 index 0000000000000000000000000000000000000000..4049873d42ca3523adf7f2e1bf25905b28970e1e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9388.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "ed64dc7bd0750bab2e99a1cfcbce2928eb37e202", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "CONTRIBUTING.rst": { + "a": 1, + "d": 1 + }, + "doc/_includes/institutional-partners.rst": { + "a": 41, + "d": 0 + }, + "doc/_static/institution_logos/CHOP.svg": { + "a": 1, + "d": 0 + }, + "doc/_static/institution_logos/MPIB.svg": { + "a": 3, + "d": 0 + }, + "doc/_static/institution_logos/Macquarie.png": { + "a": 0, + "d": 0 + }, + "doc/_static/institution_logos/SWPS.svg": { + "a": 151, + "d": 0 + }, + "doc/_templates/version-switcher.html": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 18, + "d": 1 + }, + "doc/funding.rst": { + "a": 19, + "d": 23 + }, + "doc/glossary.rst": { + "a": 5, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 3, + "d": 3 + }, + "doc/links.inc": { + "a": 10, + "d": 5 + }, + "doc/overview/development.rst": { + "a": 1, + "d": 0 + }, + "doc/overview/governance.rst": { + "a": 314, + "d": 0 + }, + "doc/overview/people.rst": { + "a": 44, + "d": 0 + }, + "doc/overview/roadmap.rst": { + "a": 140, + "d": 121 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/939.json b/mne-python/source/doc/sphinxext/prs/939.json new file mode 100644 index 0000000000000000000000000000000000000000..6fec6e29864f03ebcc95bb53483965d3ceca28a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/939.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "948584a6662cb82d7018aeb81e6f488328e387df", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9390.json b/mne-python/source/doc/sphinxext/prs/9390.json new file mode 100644 index 0000000000000000000000000000000000000000..3ee6be52563d80bd4336dc9b9d1735a0d13445ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9390.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e0ec4a0de8d9722f2f8488797bafdf9334cb4b0a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tools/generate_codemeta.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9391.json b/mne-python/source/doc/sphinxext/prs/9391.json new file mode 100644 index 0000000000000000000000000000000000000000..b22f7bfa41bd811e5eeff3936132799b5cb6d7eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9391.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "5bc18f950aa4fec908873c528f68fcfc63f48f16", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/reading_raw_data.rst": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 6, + "d": 0 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/io/hitachi/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/io/hitachi/hitachi.py": { + "a": 283, + "d": 0 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 274, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 6, + "d": 3 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 5, + "d": 3 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 18, + "d": 26 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 13, + "d": 0 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9392.json b/mne-python/source/doc/sphinxext/prs/9392.json new file mode 100644 index 0000000000000000000000000000000000000000..b7aef5a35e59c889d6b5781cecca880df65ef2a2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9392.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8aeb4ac07c9b2a2694badb33656fa0b510c8bbcd", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "README.rst": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9394.json b/mne-python/source/doc/sphinxext/prs/9394.json new file mode 100644 index 0000000000000000000000000000000000000000..e2bbc2b0d8140b6b8489ea93f5e32813f594324c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9394.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "323ab3fd683d81be55bf328d7c2bc8083c4ec104", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/data/coil_def.dat": { + "a": 64, + "d": 8 + }, + "mne/io/constants.py": { + "a": 10, + "d": 0 + }, + "mne/io/tests/test_constants.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9396.json b/mne-python/source/doc/sphinxext/prs/9396.json new file mode 100644 index 0000000000000000000000000000000000000000..4473d191a06090a6cdbabc0c877fcdaf97d96f86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9396.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "052ff0131250e68bf2869cbe088f70b29dbbf084", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 7, + "d": 8 + }, + "mne/morph.py": { + "a": 8, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 26, + "d": 4 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 30, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9398.json b/mne-python/source/doc/sphinxext/prs/9398.json new file mode 100644 index 0000000000000000000000000000000000000000..29baccb044d628464fc00f44c77b6a4e0bfbd6cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9398.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c56228da616ae3fc3c6f900d37fed9e52e5714f1", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 10, + "d": 4 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9399.json b/mne-python/source/doc/sphinxext/prs/9399.json new file mode 100644 index 0000000000000000000000000000000000000000..8bcc728d62cec913477780efd77db48fc5bd13a0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9399.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f1ea915b3f27349411d5c6231d7223e4b46445c6", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/epochs.py": { + "a": 4, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 22, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9401.json b/mne-python/source/doc/sphinxext/prs/9401.json new file mode 100644 index 0000000000000000000000000000000000000000..6bc7018f83e1b7dcb1c407f09bae3ba4bf3b7470 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9401.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "b3f4b05b3933a3b73458205c7e786166f90ad1f7", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 0, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 112, + "d": 54 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 94, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 30, + "d": 6 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 84, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9403.json b/mne-python/source/doc/sphinxext/prs/9403.json new file mode 100644 index 0000000000000000000000000000000000000000..ce59af4bcd778257f31d476592da3ce1d239d1f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9403.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ddacc565962bab96d163e2cdb790304febf22582", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/data/html_templates.py": { + "a": 7, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 8, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 8, + "d": 0 + }, + "tutorials/intro/30_info.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9404.json b/mne-python/source/doc/sphinxext/prs/9404.json new file mode 100644 index 0000000000000000000000000000000000000000..d80ad181174247d4cd0df24c8c5b243797ce3f62 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9404.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "22c570577840eaa510af06278e687fda67515801", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/data/html_templates.py": { + "a": 2, + "d": 0 + }, + "mne/io/base.py": { + "a": 3, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9405.json b/mne-python/source/doc/sphinxext/prs/9405.json new file mode 100644 index 0000000000000000000000000000000000000000..ddcac88bd5829b800cc956bf8a138f9eda7f8a75 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9405.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4de23ac16f120442d5fd322436ce6e746a94236e", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/overview/people.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9406.json b/mne-python/source/doc/sphinxext/prs/9406.json new file mode 100644 index 0000000000000000000000000000000000000000..ae711ca214761df97405c22de93e0246019ee5aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9406.json @@ -0,0 +1,59 @@ +{ + "merge_commit_sha": "8702d0e25f737070315f59a395b441662c7911e0", + "authors": [ + { + "n": "Evan Hathaway", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/export.rst": { + "a": 2, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/export/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/export/_egimff.py": { + "a": 150, + "d": 0 + }, + "mne/export/_export.py": { + "a": 59, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 83, + "d": 3 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 19, + "d": 10 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 3, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9407.json b/mne-python/source/doc/sphinxext/prs/9407.json new file mode 100644 index 0000000000000000000000000000000000000000..68d586dafdbe5ce483fdb1285d0d8a51fcf21cd6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9407.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "65f74fa1c4609d7e5219bca2cc3b840650cf978f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 10, + "d": 7 + }, + "mne/surface.py": { + "a": 29, + "d": 20 + }, + "mne/tests/test_coreg.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_source_space.py": { + "a": 6, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 12, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 60, + "d": 34 + }, + "mne/viz/_brain/surface.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 21, + "d": 6 + }, + "mne/viz/backends/_abstract.py": { + "a": 6, + "d": 4 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 5, + "d": 4 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9408.json b/mne-python/source/doc/sphinxext/prs/9408.json new file mode 100644 index 0000000000000000000000000000000000000000..7a1b697d79871140314afdd500447eaeb350287b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9408.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "81034518a5d96db2905d9230175c46991404271e", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tutorials/io/30_reading_fnirs_data.py": { + "a": 66, + "d": 22 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9411.json b/mne-python/source/doc/sphinxext/prs/9411.json new file mode 100644 index 0000000000000000000000000000000000000000..e2cdcc0c4f12a93d9972e2f4526828a75e78296b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9411.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "9a56c47d5bed3e6f98c9940d2611468d4b90d5d0", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9412.json b/mne-python/source/doc/sphinxext/prs/9412.json new file mode 100644 index 0000000000000000000000000000000000000000..f7fa0fa3de86821cb7c8a6631dd5867241bb7448 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9412.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d8768e2c0b4fbd65f92c9c7d625b03f4ec171d34", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9414.json b/mne-python/source/doc/sphinxext/prs/9414.json new file mode 100644 index 0000000000000000000000000000000000000000..ef089869c12ccb20be5397b7dcf8c4ab03adab5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9414.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0079f5b2973b979743ac97d9ba8ea882e50e3548", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9416.json b/mne-python/source/doc/sphinxext/prs/9416.json new file mode 100644 index 0000000000000000000000000000000000000000..f1cc123b5df2ef3456ba0525454113c3385e6391 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9416.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "162368a48429c848e083072a9ab39205928e9e22", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "tutorials/io/30_reading_fnirs_data.py": { + "a": 47, + "d": 48 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9419.json b/mne-python/source/doc/sphinxext/prs/9419.json new file mode 100644 index 0000000000000000000000000000000000000000..afe774d1748525196ba294eb20388d1cb56b5e23 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9419.json @@ -0,0 +1,95 @@ +{ + "merge_commit_sha": "bd644550776f9cf343118deb6551237c06b6ebed", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/io/base.py": { + "a": 6, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 4, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 74, + "d": 9 + }, + "mne/viz/epochs.py": { + "a": 1, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 7, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 6, + "d": 4 + }, + "mne/viz/tests/test_epochs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_raw.py": { + "a": 18, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/942.json b/mne-python/source/doc/sphinxext/prs/942.json new file mode 100644 index 0000000000000000000000000000000000000000..18cc911e030f548aaa506ea290f3d76dacabfd6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/942.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "40b9ce0d74da647960f7ca25c6507e204461dd79", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/event.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9420.json b/mne-python/source/doc/sphinxext/prs/9420.json new file mode 100644 index 0000000000000000000000000000000000000000..c5980c3c73c322ed8797037054ab4807fa915358 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9420.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "208968d83181ef55af6f31da82ae02d67b1e321c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/egi/egimff.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9422.json b/mne-python/source/doc/sphinxext/prs/9422.json new file mode 100644 index 0000000000000000000000000000000000000000..41725578030a4f0cd9cfa077e8ac50cc35728e4d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9422.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3384bbcc12595a89f2ceaa1f0c12abc4af920687", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/tests/test_notebook.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9423.json b/mne-python/source/doc/sphinxext/prs/9423.json new file mode 100644 index 0000000000000000000000000000000000000000..aae76686c24debad869e7b186c70a63ad12436cc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9423.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4ecca868906479eba9f90428b616e4408e781a35", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 2, + "d": 3 + }, + "tools/github_actions_dependencies.sh": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9424.json b/mne-python/source/doc/sphinxext/prs/9424.json new file mode 100644 index 0000000000000000000000000000000000000000..5bd6bcee231ea42c8fb808c77c67ef936ac9e078 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9424.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "cd2fd28134826438c4f308fb1c90f0f1ab4215a9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/label.py": { + "a": 114, + "d": 44 + }, + "mne/surface.py": { + "a": 8, + "d": 0 + }, + "mne/tests/test_dipole.py": { + "a": 4, + "d": 0 + }, + "mne/tests/test_label.py": { + "a": 59, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 11, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 16, + "d": 22 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 12, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9426.json b/mne-python/source/doc/sphinxext/prs/9426.json new file mode 100644 index 0000000000000000000000000000000000000000..9acffc7985a7a34638a6a649c177a130da20bd6e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9426.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3b69e9b936ee01fcb357e732ee35cb75086a6bf8", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 12 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9427.json b/mne-python/source/doc/sphinxext/prs/9427.json new file mode 100644 index 0000000000000000000000000000000000000000..82ca7d2c392ada76365fa629e1043f13bd2da216 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9427.json @@ -0,0 +1,83 @@ +{ + "merge_commit_sha": "abfe37b2c046375bebb210cd711025c455068a3e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/export.rst": { + "a": 17, + "d": 0 + }, + "doc/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 3, + "d": 0 + }, + "mne/epochs.py": { + "a": 4, + "d": 35 + }, + "mne/export/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/export/_eeglab.py": { + "a": 69, + "d": 0 + }, + "mne/export/_export.py": { + "a": 121, + "d": 0 + }, + "mne/export/tests/test_export.py": { + "a": 64, + "d": 0 + }, + "mne/io/base.py": { + "a": 4, + "d": 39 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 23 + }, + "mne/io/utils.py": { + "a": 0, + "d": 21 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 29 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 0, + "d": 43 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9430.json b/mne-python/source/doc/sphinxext/prs/9430.json new file mode 100644 index 0000000000000000000000000000000000000000..3849e6ae25e2ae926721c47b84adf2fd40a0dd03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9430.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "ea1212dfb044f138bf2cd2b290483e28fd68b2fd", + "authors": [ + { + "n": "PAB", + "e": null + }, + { + "n": "Pierre-Antoine Bannier", + "e": "pierre-antoine@macbook-pro-de-pierre-antoine.home" + }, + { + "n": "Pierre-Antoine Bannier", + "e": "pierre-antoine@mbpdepieantoine.home" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 6, + "d": 2 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 12, + "d": 0 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 5, + "d": 5 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 209, + "d": 19 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 26, + "d": 9 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 81, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9431.json b/mne-python/source/doc/sphinxext/prs/9431.json new file mode 100644 index 0000000000000000000000000000000000000000..6df55a2c497dd7bff959fbfdfe2f29041d82ae80 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9431.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f42f61284c280145c4f396aa3e9fa9ed504d7114", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/interpolation.py": { + "a": 2, + "d": 4 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9434.json b/mne-python/source/doc/sphinxext/prs/9434.json new file mode 100644 index 0000000000000000000000000000000000000000..688385fcb6e6e34aefba042e1bd387c151a26fc6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9434.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e6a029802bb2174eaee21f0ab544b4b64c71c1da", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg_gui.py": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9435.json b/mne-python/source/doc/sphinxext/prs/9435.json new file mode 100644 index 0000000000000000000000000000000000000000..31b5bda96821fb6ee4d18bafafb1d47465802cf9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9435.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f3fa1ca666419893def1635f16065f502739604b", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_rank.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9437.json b/mne-python/source/doc/sphinxext/prs/9437.json new file mode 100644 index 0000000000000000000000000000000000000000..f4a6015c544664976f61ac3c7939bda9e335489b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9437.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "52ea86beac5df90eb067776cf8226b72ae6df42f", + "authors": [ + { + "n": "Fede Raimondo", + "e": "f.raimondo@fz-juelich.de" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 98, + "d": 26 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9438.json b/mne-python/source/doc/sphinxext/prs/9438.json new file mode 100644 index 0000000000000000000000000000000000000000..a9155d175efe73470e79fff9843a37a16bac9ea4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9438.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "3b85ebb33c6f1f54671ee129c64ea6836fc874d1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 16, + "d": 39 + }, + "mne/evoked.py": { + "a": 13, + "d": 6 + }, + "mne/io/base.py": { + "a": 10, + "d": 4 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 19, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 50, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9440.json b/mne-python/source/doc/sphinxext/prs/9440.json new file mode 100644 index 0000000000000000000000000000000000000000..e115f4e136c19d1d3c8af8a941ef7b7a8f1df72a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9440.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "e009e5c538c70df4b2dd7e9d3b8315437ef71413", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/connectivity/mne_inverse_envelope_correlation.py": { + "a": 12, + "d": 10 + }, + "examples/connectivity/mne_inverse_envelope_correlation_volume.py": { + "a": 4, + "d": 3 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 13, + "d": 7 + }, + "examples/inverse/psf_ctf_vertices.py": { + "a": 1, + "d": 0 + }, + "examples/inverse/psf_ctf_vertices_lcmv.py": { + "a": 6, + "d": 7 + }, + "mne/label.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 4, + "d": 3 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 7, + "d": 13 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 6, + "d": 4 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9442.json b/mne-python/source/doc/sphinxext/prs/9442.json new file mode 100644 index 0000000000000000000000000000000000000000..6f6691c6009e5f023bc6832fcd33e96a705ae6f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9442.json @@ -0,0 +1,107 @@ +{ + "merge_commit_sha": "deec72a2d14c3ecacc0f7d67b1a71593cb3ed0ce", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/0.1.inc": { + "a": 18, + "d": 0 + }, + "doc/changes/0.10.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.11.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.12.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.13.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.14.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.15.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.16.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.17.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.18.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.19.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.2.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.20.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.21.inc": { + "a": 4, + "d": 4 + }, + "doc/changes/0.22.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.23.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.3.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.4.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.5.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.6.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.7.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.8.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/0.9.inc": { + "a": 2, + "d": 2 + }, + "doc/whats_new.rst": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9443.json b/mne-python/source/doc/sphinxext/prs/9443.json new file mode 100644 index 0000000000000000000000000000000000000000..6cc004133e267630611e7a5a8112bd268d7590e8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9443.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "04fd78be051ec4fa193d29e532fd36ba8bac5408", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/_read_raw.py": { + "a": 2, + "d": 1 + }, + "mne/report.py": { + "a": 3, + "d": 2 + }, + "mne/tests/test_report.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9444.json b/mne-python/source/doc/sphinxext/prs/9444.json new file mode 100644 index 0000000000000000000000000000000000000000..8242be54a2b9d31c5e9629c2beae40d13b4233e9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9444.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a0d5d76ee35d6a59120f91500dddfda05b02da6d", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 19, + "d": 19 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9445.json b/mne-python/source/doc/sphinxext/prs/9445.json new file mode 100644 index 0000000000000000000000000000000000000000..d474f4da00f05abc82881c192a258cdc3f2d0fb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9445.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "07af2f95fa92427120575f923b588160046a7ca3", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 218, + "d": 2 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 138, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 90, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9447.json b/mne-python/source/doc/sphinxext/prs/9447.json new file mode 100644 index 0000000000000000000000000000000000000000..350fd7c381fbfcfd2fb487e4e617cb736d4b0f6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9447.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6953e748bad6cf4c55df71c1fb6bb702c0dd35fc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 163, + "d": 151 + }, + "mne/channels/tests/test_montage.py": { + "a": 36, + "d": 1 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 25, + "d": 66 + }, + "mne/io/fieldtrip/utils.py": { + "a": 23, + "d": 55 + }, + "mne/utils/numerics.py": { + "a": 17, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9448.json b/mne-python/source/doc/sphinxext/prs/9448.json new file mode 100644 index 0000000000000000000000000000000000000000..01e874385620d3d40e2fefd2c51c0217839875d0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9448.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "b05983ea589836c6f63ef665fcf12df659fc8930", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 40, + "d": 31 + }, + "mne/utils/misc.py": { + "a": 6, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 15, + "d": 7 + }, + "mne/viz/backends/_qt.py": { + "a": 5, + "d": 0 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 0, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9449.json b/mne-python/source/doc/sphinxext/prs/9449.json new file mode 100644 index 0000000000000000000000000000000000000000..fa8934761ed73194a7af51587f23e420d5b0572c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9449.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0d5068dbbce76598c9c6433e1ace1265e1955564", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/time_frequency/multitaper.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/psd.py": { + "a": 4, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9450.json b/mne-python/source/doc/sphinxext/prs/9450.json new file mode 100644 index 0000000000000000000000000000000000000000..5ea5e00ab5286e3edba3778d10f422a8b0dea27c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9450.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a759bb35cb08cc5b5eb9e7fc177f12bcdc3b86db", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/CONTRIBUTING.md": { + "a": 2, + "d": 2 + }, + "CONTRIBUTING.md": { + "a": 9, + "d": 0 + }, + "CONTRIBUTING.rst": { + "a": 0, + "d": 21 + }, + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "doc/overview/development.rst": { + "a": 18, + "d": 12 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9453.json b/mne-python/source/doc/sphinxext/prs/9453.json new file mode 100644 index 0000000000000000000000000000000000000000..c897390e61504bb4ee06ad5d292c87855daf1827 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9453.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "903f66aabd769db88a7ba7973abd624ed666695a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 2 + }, + ".github/workflows/circle_artifacts.yml": { + "a": 1, + "d": 0 + }, + ".gitignore": { + "a": 1, + "d": 0 + }, + "azure-pipelines.yml": { + "a": 27, + "d": 18 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9456.json b/mne-python/source/doc/sphinxext/prs/9456.json new file mode 100644 index 0000000000000000000000000000000000000000..eec89175e2c61a05d374dc54d25340cec4f00c5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9456.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "43777569587b7ba5f07210eabe72ab1e87226576", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + ".github/ISSUE_TEMPLATE/question.md": { + "a": 0, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9458.json b/mne-python/source/doc/sphinxext/prs/9458.json new file mode 100644 index 0000000000000000000000000000000000000000..806d20682bc504520c0c4bfdf5c6201880290337 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9458.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c0d431acf0307a8bf92ab01995397194563f6920", + "authors": [ + { + "n": "Ross", + "e": "ross.maddox@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9459.json b/mne-python/source/doc/sphinxext/prs/9459.json new file mode 100644 index 0000000000000000000000000000000000000000..01a0fef09c5511af86e58257e7901b0d70417dac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9459.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8d9b3521bd1a06847304fed9b8f36277f05d4607", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 11, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9460.json b/mne-python/source/doc/sphinxext/prs/9460.json new file mode 100644 index 0000000000000000000000000000000000000000..01d0e522421fb884aee4cab1f2bbe89aa7afd173 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9460.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "651720ea6954f458332d03f609c91c9c67bc8cab", + "authors": [ + { + "n": "Ryan M.C. Law", + "e": "ryan.law@mrc-cbu.cam.ac.uk" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Ryan Law", + "e": "ryalaw@dccn.nl" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/ctf/ctf.py": { + "a": 5, + "d": 0 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9461.json b/mne-python/source/doc/sphinxext/prs/9461.json new file mode 100644 index 0000000000000000000000000000000000000000..3ccc0a1da08038026f7afb3d40b2103c6b9fbd71 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9461.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8432c29c193d96f13f521b5059a1dd616c942eaa", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/io/snirf/_snirf.py": { + "a": 11, + "d": 10 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 18, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9463.json b/mne-python/source/doc/sphinxext/prs/9463.json new file mode 100644 index 0000000000000000000000000000000000000000..b6ab97611a4be8ae9900656f4febe5a37f3fc6db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9463.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "c40056c11023ff2d57b4e7bd16904deda280880a", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/forward.rst": { + "a": 1, + "d": 0 + }, + "mne/bem.py": { + "a": 102, + "d": 2 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 10, + "d": 85 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9464.json b/mne-python/source/doc/sphinxext/prs/9464.json new file mode 100644 index 0000000000000000000000000000000000000000..0b5550a6f0ffc1601333fc58230d10b99b064f7f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9464.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "51f25d33231e1e05c0f54e05d0e9f8c84d3603d6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 4, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9465.json b/mne-python/source/doc/sphinxext/prs/9465.json new file mode 100644 index 0000000000000000000000000000000000000000..35166be4216fde13b36632b7257bbbeca6bcd8ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9465.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "6d7dadd73d1243bf650985aca0e7123017653da9", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/check.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 5, + "d": 0 + }, + "mne/utils/tests/test_config.py": { + "a": 16, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9467.json b/mne-python/source/doc/sphinxext/prs/9467.json new file mode 100644 index 0000000000000000000000000000000000000000..8676da72cf5defda62778282d0c4e08291981ecf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9467.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "66d839032bd66c0fd1d6f2761509b38ee88e5ec9", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/utils/tests/test_config.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9468.json b/mne-python/source/doc/sphinxext/prs/9468.json new file mode 100644 index 0000000000000000000000000000000000000000..798af005c2e0cb7e83673f04691f44402510afd9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9468.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "b6a36089a963a97380488845491fe38e8d3b610b", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 31, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 51, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/947.json b/mne-python/source/doc/sphinxext/prs/947.json new file mode 100644 index 0000000000000000000000000000000000000000..8fb02f007d7b974e94563d186e8b9a5d75e2a559 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/947.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "bb5fcd25fca2abb16f34c0cad5dc57ce65b03c57", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "doc/source/python_reference.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 111, + "d": 44 + }, + "mne/gui/_coreg_gui.py": { + "a": 18, + "d": 7 + }, + "mne/gui/_fiducials_gui.py": { + "a": 1, + "d": 0 + }, + "mne/gui/_file_traits.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9471.json b/mne-python/source/doc/sphinxext/prs/9471.json new file mode 100644 index 0000000000000000000000000000000000000000..bae8b9e0f572c58d21d47959b7cc4733b54b27b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9471.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ad443737b81949a79ff8330c95705ae90aaafefc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9472.json b/mne-python/source/doc/sphinxext/prs/9472.json new file mode 100644 index 0000000000000000000000000000000000000000..4c72ef81ffc975dc7cfe767a65a51169f2cc8645 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9472.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "dfc673936734a418d1b2d23380c591e551f6136c", + "authors": [ + { + "n": "Lukas Hecker", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/install/pre_install.rst": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9474.json b/mne-python/source/doc/sphinxext/prs/9474.json new file mode 100644 index 0000000000000000000000000000000000000000..7cebe840175f215dfdf59c229ff18c2ca4d4f4c6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9474.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "fa6738da08480ed5142851b0dcf38e78d3eb2fee", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/channels/montage.py": { + "a": 12, + "d": 5 + }, + "mne/channels/tests/test_montage.py": { + "a": 7, + "d": 0 + }, + "mne/io/meas_info.py": { + "a": 7, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9476.json b/mne-python/source/doc/sphinxext/prs/9476.json new file mode 100644 index 0000000000000000000000000000000000000000..10cad30bedc538b8ec16d607fbbf6ed3e5293be5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9476.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "25f60579aca14e879a98399d1c083c70f9ae1327", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9477.json b/mne-python/source/doc/sphinxext/prs/9477.json new file mode 100644 index 0000000000000000000000000000000000000000..a07669841107809c4309b22872d7d9c9ad113f97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9477.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8b9616dfbc377ce468a6d52b43f7a973eac47cab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/overview/roadmap.rst": { + "a": 23, + "d": 0 + }, + "examples/datasets/opm_data.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9478.json b/mne-python/source/doc/sphinxext/prs/9478.json new file mode 100644 index 0000000000000000000000000000000000000000..5373e757c164d45e820e626a58c9a5a8a6b56975 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9478.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f5460789ec67f59bdd21d0f29898d38683b7d7d4", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 7, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "tutorials/clinical/20_seeg.py": { + "a": 33, + "d": 9 + }, + "tutorials/clinical/30_ecog.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/948.json b/mne-python/source/doc/sphinxext/prs/948.json new file mode 100644 index 0000000000000000000000000000000000000000..a7e3e5a3a207c3ae6cfb694be9c462dcc8ac79b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/948.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "117e322f75cf00cf6c2647a033de07a6d46a3395", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/epochs.py": { + "a": 15, + "d": 0 + }, + "mne/tests/test_epochs.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9480.json b/mne-python/source/doc/sphinxext/prs/9480.json new file mode 100644 index 0000000000000000000000000000000000000000..5ab2a0d158c23f5be4d401c5ae5a241e62a39df5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9480.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "fb7cf920c18a41d64aaa452bfb1b3bda5d9ae6a7", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/_includes/inverse.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/0.13.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.21.inc": { + "a": 1, + "d": 1 + }, + "doc/overview/datasets_index.rst": { + "a": 1, + "d": 1 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 1, + "d": 1 + }, + "examples/io/README.txt": { + "a": 1, + "d": 1 + }, + "examples/io/read_neo_format.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 2, + "d": 2 + }, + "tutorials/clinical/30_ecog.py": { + "a": 2, + "d": 2 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/10_reading_meg_data.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 1, + "d": 1 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 7, + "d": 7 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 1, + "d": 1 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9481.json b/mne-python/source/doc/sphinxext/prs/9481.json new file mode 100644 index 0000000000000000000000000000000000000000..3d03ab237655dbbca1418cb3a27dfb47cd19b3b1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9481.json @@ -0,0 +1,87 @@ +{ + "merge_commit_sha": "080e7a879d325ad8f0c11fe28a8ff9f5983dfd2f", + "authors": [ + { + "n": "PAB", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Pierre-Antoine Bannier", + "e": "pierre-antoine@macbook-pro-de-pierre-antoine.home" + }, + { + "n": "Pierre-Antoine Bannier", + "e": "pierre-antoine@mbpdepieantoine.home" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Pierre-Antoine Bannier", + "e": "pierre-antoine@222-194.wifi-inria-saclay.saclay.inria.fr" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 15, + "d": 0 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 94, + "d": 19 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 3, + "d": 3 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9484.json b/mne-python/source/doc/sphinxext/prs/9484.json new file mode 100644 index 0000000000000000000000000000000000000000..a332dcd4663b6f07e25026580b592384ad2923d4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9484.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "44f5ecb6b19d15bddd13582e489bd2a5a88827f6", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "doc/mri.rst": { + "a": 2, + "d": 0 + }, + "doc/references.bib": { + "a": 12, + "d": 0 + }, + "mne/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/morph.py": { + "a": 9, + "d": 2 + }, + "mne/surface.py": { + "a": 109, + "d": 0 + }, + "mne/tests/test_surface.py": { + "a": 27, + "d": 3 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 0 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 469, + "d": 0 + }, + "tutorials/clinical/20_seeg.py": { + "a": 3, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9485.json b/mne-python/source/doc/sphinxext/prs/9485.json new file mode 100644 index 0000000000000000000000000000000000000000..4ce176921d5bf86d051264e7519413aa22bfa9ff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9485.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "22b95895860ffe7cb907c0e8ac8929140c170a8c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 20, + "d": 12 + }, + "mne/tests/test_epochs.py": { + "a": 27, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9486.json b/mne-python/source/doc/sphinxext/prs/9486.json new file mode 100644 index 0000000000000000000000000000000000000000..8d55ccd8eacbcaef9d69110c8ee44ef3757dc2ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9486.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b3768fe8347039e90d8e5a0bfd648315f9f345fa", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/datasets/_fsaverage/base.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9487.json b/mne-python/source/doc/sphinxext/prs/9487.json new file mode 100644 index 0000000000000000000000000000000000000000..03463467adf478e3cae82640530116d286513e17 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9487.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "03affdcd7a7e706471aeb757932d465f93e8259e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9489.json b/mne-python/source/doc/sphinxext/prs/9489.json new file mode 100644 index 0000000000000000000000000000000000000000..adfd39b9fb4f43fb07e64cf59b55a5d15627dd69 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9489.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bdaa1d460201a3bc3cec95b67fc2b8d31a933652", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9490.json b/mne-python/source/doc/sphinxext/prs/9490.json new file mode 100644 index 0000000000000000000000000000000000000000..485fb1188da03f2809b78d8deff39532c117f530 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9490.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f8a51e0afb6c2eba37b06a18eaaabf62ac98a6a9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9491.json b/mne-python/source/doc/sphinxext/prs/9491.json new file mode 100644 index 0000000000000000000000000000000000000000..9b33a6fe08c098c3e6c95d1c024ff8fb2cdc3611 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9491.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "869bf9e3ad78f3e7e5626351ad34cc0d5a25e62f", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9493.json b/mne-python/source/doc/sphinxext/prs/9493.json new file mode 100644 index 0000000000000000000000000000000000000000..58753c1ec34f11b787cf8d3a0eccfe49b348c0ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9493.json @@ -0,0 +1,139 @@ +{ + "merge_commit_sha": "702bdaccee9131798c68a82d81ad497c286aac4a", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Adam Li", + "e": "adam2392@Adams-MBP-2.home" + }, + { + "n": "Adam Li", + "e": "adam2392@new-host-2.home" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 34, + "d": 15 + }, + "doc/overview/datasets_index.rst": { + "a": 1, + "d": 1 + }, + "examples/connectivity/README.txt": { + "a": 4, + "d": 0 + }, + "examples/connectivity/cwt_sensor_connectivity.py": { + "a": 0, + "d": 85 + }, + "examples/connectivity/mixed_source_space_connectivity.py": { + "a": 0, + "d": 187 + }, + "examples/connectivity/mne_inverse_coherence_epochs.py": { + "a": 0, + "d": 149 + }, + "examples/connectivity/mne_inverse_connectivity_spectrum.py": { + "a": 0, + "d": 99 + }, + "examples/connectivity/mne_inverse_envelope_correlation.py": { + "a": 0, + "d": 110 + }, + "examples/connectivity/mne_inverse_envelope_correlation_volume.py": { + "a": 0, + "d": 95 + }, + "examples/connectivity/mne_inverse_label_connectivity.py": { + "a": 0, + "d": 181 + }, + "examples/connectivity/mne_inverse_psi_visual.py": { + "a": 0, + "d": 118 + }, + "examples/connectivity/sensor_connectivity.py": { + "a": 0, + "d": 57 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/connectivity/effective.py": { + "a": 7, + "d": 8 + }, + "mne/connectivity/envelope.py": { + "a": 3, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 3, + "d": 2 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 3, + "d": 1 + }, + "mne/connectivity/utils.py": { + "a": 4, + "d": 0 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 3, + "d": 1 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 8, + "d": 1 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9494.json b/mne-python/source/doc/sphinxext/prs/9494.json new file mode 100644 index 0000000000000000000000000000000000000000..2d6d282196c255d2ab493152b551132ed9b71c04 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9494.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "e4b16dc57a6a188aa06332b73d911e8131972522", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/backends/_pyvista.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9497.json b/mne-python/source/doc/sphinxext/prs/9497.json new file mode 100644 index 0000000000000000000000000000000000000000..061da5f2ca708b75486efe850ea759176a2eede0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9497.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "0af111f4238d735fc05a260b4347ddb9958f39f1", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9498.json b/mne-python/source/doc/sphinxext/prs/9498.json new file mode 100644 index 0000000000000000000000000000000000000000..c5df12b91024e9e820f52608dc8b173aea7cc894 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9498.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0a0f3cef00ccf61278530ded0b98d90b2a751d45", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/0.23.inc": { + "a": 2, + "d": 2 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9499.json b/mne-python/source/doc/sphinxext/prs/9499.json new file mode 100644 index 0000000000000000000000000000000000000000..a7d304b2933b15046c41a22615e7215c678b701d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9499.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8c9c078e38cc4c7d67aa4e4f8a9b19eb32bb075e", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/io/meas_info.py": { + "a": 4, + "d": 5 + }, + "mne/io/tests/test_meas_info.py": { + "a": 2, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9500.json b/mne-python/source/doc/sphinxext/prs/9500.json new file mode 100644 index 0000000000000000000000000000000000000000..4430f9c52fec4a73efccf506ab1a76e1e6a8e629 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9500.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "15168c50a362af6753851eeb2aff4ac06fa022b2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 7, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 18, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9504.json b/mne-python/source/doc/sphinxext/prs/9504.json new file mode 100644 index 0000000000000000000000000000000000000000..4f2b4237b6421e5705bc402dcce343a9957f5a96 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9504.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "9690573def6fd672c7a18bce5fe7ba94a5e64c01", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/surface.py": { + "a": 4, + "d": 0 + }, + "requirements_doc.txt": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9505.json b/mne-python/source/doc/sphinxext/prs/9505.json new file mode 100644 index 0000000000000000000000000000000000000000..8fb2a838c44660282efe662e284b8b483cdaed98 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9505.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3078533f8704820a168797578f5b47ddff4be347", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 23, + "d": 10 + }, + "mne/viz/tests/test_epochs.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/951.json b/mne-python/source/doc/sphinxext/prs/951.json new file mode 100644 index 0000000000000000000000000000000000000000..4d55c262052be2d7748ee41f2f984c7243690eb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/951.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b3f227ca3b0f39d973db85e56bf0eb0b95dcfe2b", + "authors": [ + { + "n": "Praveen Sripad", + "e": "pravsripad@gmail.com" + } + ], + "changes": { + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 3, + "d": 3 + }, + "mne/commands/utils.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9512.json b/mne-python/source/doc/sphinxext/prs/9512.json new file mode 100644 index 0000000000000000000000000000000000000000..48a5f1b71b728c369f1bfe50cb8d416ef5fb9f08 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9512.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f1ff361a6426513bba4110b122ab867dea44e012", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/linux_conda.yml": { + "a": 2, + "d": 2 + }, + "azure-pipelines.yml": { + "a": 6, + "d": 6 + }, + "requirements.txt": { + "a": 4, + "d": 3 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9513.json b/mne-python/source/doc/sphinxext/prs/9513.json new file mode 100644 index 0000000000000000000000000000000000000000..d806e8fb73e0ac7d14528cc92b1816eadca89367 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9513.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "99e39ef2a268da0b8f89db14858671d0314eafb0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/forward/forward.py": { + "a": 9, + "d": 5 + }, + "mne/simulation/evoked.py": { + "a": 7, + "d": 4 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9514.json b/mne-python/source/doc/sphinxext/prs/9514.json new file mode 100644 index 0000000000000000000000000000000000000000..146ba7d36128eae82f48c75fb1a28aeec0fb66dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9514.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2e200aa7778a1462b4da6ce7bf4253b99cde3d6a", + "authors": [ + { + "n": "nordme", + "e": "nordme@uw.edu" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/realign.py": { + "a": 14, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9516.json b/mne-python/source/doc/sphinxext/prs/9516.json new file mode 100644 index 0000000000000000000000000000000000000000..5b790c401d6582ff9a647e201e1d7841910d4387 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9516.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "f15663010c468a2abeda6ba44833e089374a2349", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 1 + }, + "doc/mri.rst": { + "a": 1, + "d": 0 + }, + "mne/coreg.py": { + "a": 645, + "d": 2 + }, + "mne/io/_digitization.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_meas_info.py": { + "a": 3, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 86, + "d": 7 + }, + "tutorials/forward/25_automated_coreg.py": { + "a": 82, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9517.json b/mne-python/source/doc/sphinxext/prs/9517.json new file mode 100644 index 0000000000000000000000000000000000000000..634dda9b2011a4a95c21f132ac94165ae44f5c3f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9517.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "630ab79374b9f71a978f6ddd15f1590ada5270fe", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 2, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9518.json b/mne-python/source/doc/sphinxext/prs/9518.json new file mode 100644 index 0000000000000000000000000000000000000000..6835591e0ae518b9cd32038bfd543944556218b8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9518.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "bdd7a12f94aadbfb547d97b02f4de1cc02197e33", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 6, + "d": 5 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 2, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 5, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9519.json b/mne-python/source/doc/sphinxext/prs/9519.json new file mode 100644 index 0000000000000000000000000000000000000000..f2ca82039374dba6caa4a85925185113d0ebe9d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9519.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "4656e131bd04c85335531f475dffdb35388d0d4e", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 3, + "d": 2 + }, + "mne/viz/epochs.py": { + "a": 8, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 8, + "d": 2 + }, + "mne/viz/tests/test_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9521.json b/mne-python/source/doc/sphinxext/prs/9521.json new file mode 100644 index 0000000000000000000000000000000000000000..c2c41ba2ff56d36b7c9e72ba3f49dd2afd1502f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9521.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "9fb78760f0fa367db02574feb981978353f845e9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alex", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 4 + }, + "doc/mri.rst": { + "a": 3, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/defaults.py": { + "a": 8, + "d": 1 + }, + "mne/morph.py": { + "a": 13, + "d": 94 + }, + "mne/tests/test_morph.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_transforms.py": { + "a": 31, + "d": 1 + }, + "mne/transforms.py": { + "a": 248, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 74, + "d": 0 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 116, + "d": 192 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9522.json b/mne-python/source/doc/sphinxext/prs/9522.json new file mode 100644 index 0000000000000000000000000000000000000000..445d2b9a8398f5481a90c240818238096dd99293 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9522.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "8b4ed3cc0ef7c1e6ddac899992cddcdbc86a9a7b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 18, + "d": 10 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 14, + "d": 11 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 4, + "d": 2 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 7, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9524.json b/mne-python/source/doc/sphinxext/prs/9524.json new file mode 100644 index 0000000000000000000000000000000000000000..ae62c6e4b6587aa9dce6df9475d0e6e4a78f0505 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9524.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "e1801abea4cb18f08a34e0a017825ab53175298d", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 3, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 24, + "d": 3 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9525.json b/mne-python/source/doc/sphinxext/prs/9525.json new file mode 100644 index 0000000000000000000000000000000000000000..0ce06df96e30d46ffb9040a89b190d78f95e2fac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9525.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "ae98d7e5aa0a7c1030526e2bdc288389ee5461a1", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 2 + }, + "mne/annotations.py": { + "a": 36, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 54, + "d": 1 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9528.json b/mne-python/source/doc/sphinxext/prs/9528.json new file mode 100644 index 0000000000000000000000000000000000000000..983f06dfd124b28e11a81084c00d72f438c70b2b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9528.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3c60678f631978dec042ec518e570c9ef195406e", + "authors": [ + { + "n": "Mikolaj Magnuski", + "e": "mmagnuski@swps.edu.pl" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 19, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9529.json b/mne-python/source/doc/sphinxext/prs/9529.json new file mode 100644 index 0000000000000000000000000000000000000000..29ba9fd1fe7295b6c1e10025ae8ec8bbad8c9377 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9529.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a4025a9eb5dd88874dc6942f23313bb81fd98795", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/annotations.py": { + "a": 44, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 30, + "d": 0 + }, + "mne/utils/check.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/953.json b/mne-python/source/doc/sphinxext/prs/953.json new file mode 100644 index 0000000000000000000000000000000000000000..6a1c4451b210c0c79eaf5dfe0a40dc5d50c2ccc1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/953.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "b48e9adac2103b6951bd091cea951c3879dd9958", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/decoding/plot_decoding_time_generalization.py": { + "a": 93, + "d": 0 + }, + "mne/decoding/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/decoding/tests/test_time_gen.py": { + "a": 41, + "d": 0 + }, + "mne/decoding/time_gen.py": { + "a": 123, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9530.json b/mne-python/source/doc/sphinxext/prs/9530.json new file mode 100644 index 0000000000000000000000000000000000000000..9ee301286c94ad4e0e68dd0f2986e96a673ea12f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9530.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8a0f5cdd8039245e84aec1312c0e302326ad15e3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9531.json b/mne-python/source/doc/sphinxext/prs/9531.json new file mode 100644 index 0000000000000000000000000000000000000000..814fd509893660776e0e38a76bcc411cb4776171 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9531.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "7e27ce91070569f76bc5ffa0e0732c7cf4297821", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/maxwell.py": { + "a": 8, + "d": 0 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 47, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9532.json b/mne-python/source/doc/sphinxext/prs/9532.json new file mode 100644 index 0000000000000000000000000000000000000000..7d432a074e55fcd134abd37815a506e0d3da78e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9532.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "032d6112d1a141ae00c6807713106a880d46e8ad", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "tutorials/intro/40_sensor_locations.py": { + "a": 131, + "d": 141 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9534.json b/mne-python/source/doc/sphinxext/prs/9534.json new file mode 100644 index 0000000000000000000000000000000000000000..1b921293aa1a7cce62daa53d270f838f6b98b7cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9534.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b377a687466dc10b7b342d236dcba9c6eb8b9b5b", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/time_frequency/time_frequency_erds.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9535.json b/mne-python/source/doc/sphinxext/prs/9535.json new file mode 100644 index 0000000000000000000000000000000000000000..a4d61732f8e886c3d7a33706fb69bbf54fd56dde --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9535.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "e7cb1b795016ef5d88ab167e011ded1f543fd79d", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 16, + "d": 19 + }, + "mne/tests/test_epochs.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9537.json b/mne-python/source/doc/sphinxext/prs/9537.json new file mode 100644 index 0000000000000000000000000000000000000000..b2a5a9e88d743b87881f8045badb8132e25aded6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9537.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "720a95c7599d933526b5db7fae823e4349176a01", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/viz/raw.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9538.json b/mne-python/source/doc/sphinxext/prs/9538.json new file mode 100644 index 0000000000000000000000000000000000000000..a3dbf5c864fb3b866dabacc9949a79d1f18bffd2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9538.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "14c139d492b8826764645a17cd3a3bb69e576819", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/annotations.py": { + "a": 6, + "d": 14 + }, + "mne/channels/channels.py": { + "a": 3, + "d": 6 + }, + "mne/tests/test_annotations.py": { + "a": 2, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 35, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9539.json b/mne-python/source/doc/sphinxext/prs/9539.json new file mode 100644 index 0000000000000000000000000000000000000000..8da4b11abf02e2ab228f190b697e9896aa723a78 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9539.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4308cc3912808d12f65e595221cc36ac60017503", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "mne/annotations.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_annotations.py": { + "a": 5, + "d": 0 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 19, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9540.json b/mne-python/source/doc/sphinxext/prs/9540.json new file mode 100644 index 0000000000000000000000000000000000000000..7bbf29f7ddab8885a2fa3423c68ccfa463bc0e84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9540.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "3a4a048c5fc5ee77875a705848eb4be8354732f7", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/glossary.rst": { + "a": 10, + "d": 0 + }, + "doc/links.inc": { + "a": 0, + "d": 9 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/defaults.py": { + "a": 38, + "d": 0 + }, + "mne/surface.py": { + "a": 21, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 109, + "d": 15 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 6, + "d": 0 + }, + "mne/viz/backends/_pyvista.py": { + "a": 13, + "d": 7 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 0, + "d": 2 + }, + "tutorials/clinical/20_seeg.py": { + "a": 21, + "d": 3 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 20, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9541.json b/mne-python/source/doc/sphinxext/prs/9541.json new file mode 100644 index 0000000000000000000000000000000000000000..0e9df5a01c46a4a43ef8fe67e0c0af68546fa9ce --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9541.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ba053a6843a0acae892d6046ce9bc2c752fbbcb9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 51, + "d": 8 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 10, + "d": 3 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 6, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 39, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9543.json b/mne-python/source/doc/sphinxext/prs/9543.json new file mode 100644 index 0000000000000000000000000000000000000000..4702c311e6bd3ef486d6bec19754b6fe3577a6b9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9543.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "3b9ec94e43aed102fe759752b899514c80afc5f5", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/links.inc": { + "a": 7, + "d": 0 + }, + "doc/mri.rst": { + "a": 5, + "d": 0 + }, + "doc/source_space.rst": { + "a": 0, + "d": 4 + }, + "mne/__init__.py": { + "a": 5, + "d": 4 + }, + "mne/_freesurfer.py": { + "a": 499, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 4, + "d": 2 + }, + "mne/datasets/_fsaverage/base.py": { + "a": 1, + "d": 1 + }, + "mne/dipole.py": { + "a": 2, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 4, + "d": 3 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 2, + "d": 2 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 3, + "d": 3 + }, + "mne/source_space.py": { + "a": 9, + "d": 495 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_freesurfer.py": { + "a": 143, + "d": 0 + }, + "mne/tests/test_morph.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_source_space.py": { + "a": 4, + "d": 128 + }, + "mne/utils/__init__.py": { + "a": 6, + "d": 5 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9544.json b/mne-python/source/doc/sphinxext/prs/9544.json new file mode 100644 index 0000000000000000000000000000000000000000..eb3e61093ccd1e010e22432f9711b942116a8ad1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9544.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "4875e04cdebba132fc637ca65b3cb50584aee8b7", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/mri.rst": { + "a": 1, + "d": 1 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/_digitization.py": { + "a": 3, + "d": 2 + }, + "mne/surface.py": { + "a": 208, + "d": 4 + }, + "mne/tests/test_surface.py": { + "a": 103, + "d": 5 + }, + "mne/tests/test_transforms.py": { + "a": 16, + "d": 1 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 57, + "d": 93 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9545.json b/mne-python/source/doc/sphinxext/prs/9545.json new file mode 100644 index 0000000000000000000000000000000000000000..df97d4667010677bf06366e68bc42debb8458ada --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9545.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "b91e4f77d31f434dfcf496c3115ab1168539c514", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/links.inc": { + "a": 8, + "d": 0 + }, + "doc/mri.rst": { + "a": 1, + "d": 0 + }, + "doc/visualization.rst": { + "a": 1, + "d": 0 + }, + "mne/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 28, + "d": 1 + }, + "mne/surface.py": { + "a": 120, + "d": 47 + }, + "mne/tests/test_freesurfer.py": { + "a": 9, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 34, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 79, + "d": 0 + }, + "mne/viz/tests/test_circle.py": { + "a": 21, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 40, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9547.json b/mne-python/source/doc/sphinxext/prs/9547.json new file mode 100644 index 0000000000000000000000000000000000000000..938af4f8207202274a1b4078035100da8d2f3a14 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9547.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f367c0b4d8d8153150e53b9fe54b92066b508aa7", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/io/_digitization.py": { + "a": 5, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 13, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9549.json b/mne-python/source/doc/sphinxext/prs/9549.json new file mode 100644 index 0000000000000000000000000000000000000000..3f85dad6b7caeb8293a5f5166e724b0580c4c2bb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9549.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ff02cb1806d5671cc93edb0ceb16b05085681dae", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 0 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9550.json b/mne-python/source/doc/sphinxext/prs/9550.json new file mode 100644 index 0000000000000000000000000000000000000000..c78cc0c9b5362771fe2dd1dc5fe95ba783f00337 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9550.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "0156284d20f0b1ae2ca8630acf3a507b4b50b21d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fixes.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 14, + "d": 7 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_topo.py": { + "a": 4, + "d": 1 + }, + "mne/viz/tests/test_topomap.py": { + "a": 20, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 5, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9552.json b/mne-python/source/doc/sphinxext/prs/9552.json new file mode 100644 index 0000000000000000000000000000000000000000..c8a41433e57a08e303af74be66bc074c69a6cd3b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9552.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6a074844ccd1fd8eaf4f9b84095aaaaff357d532", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9553.json b/mne-python/source/doc/sphinxext/prs/9553.json new file mode 100644 index 0000000000000000000000000000000000000000..838c48cc824f966bef21db0a830123ed405b0890 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9553.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "19bdd7941e3dedaf4fd8dcc49805d2e7dacfbecc", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Johann Benerradi", + "e": "johann.benerradi@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 34, + "d": 15 + }, + "mne/io/base.py": { + "a": 53, + "d": 46 + }, + "mne/tests/test_epochs.py": { + "a": 35, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 20, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9554.json b/mne-python/source/doc/sphinxext/prs/9554.json new file mode 100644 index 0000000000000000000000000000000000000000..fc837c7d05f1f93bde1a87c23c1c4df7acc1353a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9554.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a8c197d47cb32d07b16cf8e257ff168b05d9fe1a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9555.json b/mne-python/source/doc/sphinxext/prs/9555.json new file mode 100644 index 0000000000000000000000000000000000000000..658211d2c5258bea8cfb505fee499651610fd06c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9555.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "3843c36cec7310eb7b7c793e825be608f81af852", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 2, + "d": 8 + }, + "mne/evoked.py": { + "a": 21, + "d": 0 + }, + "mne/io/tests/test_reference.py": { + "a": 2, + "d": 3 + }, + "mne/tests/test_evoked.py": { + "a": 14, + "d": 0 + }, + "setup.cfg": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9556.json b/mne-python/source/doc/sphinxext/prs/9556.json new file mode 100644 index 0000000000000000000000000000000000000000..58d7825b34a6ce8c517268df5bcc99cb04bf3d2d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9556.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "08b4b0ec8494b85977802872ee539b08e30a7685", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/epochs.py": { + "a": 23, + "d": 3 + }, + "mne/evoked.py": { + "a": 9, + "d": 2 + }, + "mne/io/base.py": { + "a": 64, + "d": 3 + }, + "mne/io/tests/test_raw.py": { + "a": 39, + "d": 0 + }, + "mne/preprocessing/ecg.py": { + "a": 30, + "d": 6 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 11, + "d": 2 + }, + "mne/rank.py": { + "a": 1, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 0 + }, + "mne/tests/test_evoked.py": { + "a": 14, + "d": 0 + }, + "mne/utils/check.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9557.json b/mne-python/source/doc/sphinxext/prs/9557.json new file mode 100644 index 0000000000000000000000000000000000000000..3bbda895ceb7f52cc7ac9765a85da85031a8c4d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9557.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "308a0abf7c8b8b14c9afc6db2e3ed5b57787be31", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/visualization/evoked_topomap.py": { + "a": 1, + "d": 0 + }, + "examples/visualization/evoked_whitening.py": { + "a": 0, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9558.json b/mne-python/source/doc/sphinxext/prs/9558.json new file mode 100644 index 0000000000000000000000000000000000000000..5d8efa91c1cb65172e8a482b250d09616f16349f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9558.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "bd9bf85b28beb3e488289cf532dc0e30919b3ba2", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/edf/edf.py": { + "a": 40, + "d": 34 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 13, + "d": 0 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 5, + "d": 0 + }, + "mne/time_frequency/psd.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9561.json b/mne-python/source/doc/sphinxext/prs/9561.json new file mode 100644 index 0000000000000000000000000000000000000000..691f112127a84062bd8bb8082e4368c3e095c634 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9561.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "80e4910831d7eec822786314daccd43bdd558b87", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_topomap.py": { + "a": 4, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 7, + "d": 5 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9564.json b/mne-python/source/doc/sphinxext/prs/9564.json new file mode 100644 index 0000000000000000000000000000000000000000..9700267e37c6819454c56946e01b4e0a9ca2e205 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9564.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c0d99c262ac5d042e5cf48e4ff9679d8ea6d4f5c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 3 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9565.json b/mne-python/source/doc/sphinxext/prs/9565.json new file mode 100644 index 0000000000000000000000000000000000000000..b70f734ea19d3617e7b89dc3cc2e83236b35ffd4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9565.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "155540e5325b43dac44c7f35575ef10f305e4e94", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/egimff.py": { + "a": 19, + "d": 7 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 18, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9567.json b/mne-python/source/doc/sphinxext/prs/9567.json new file mode 100644 index 0000000000000000000000000000000000000000..1e6ebeadbaed66df1b6dfef546d28e4da57b998b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9567.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "688c4cf9753c357666b0428a3974d379a8ce8a3d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9568.json b/mne-python/source/doc/sphinxext/prs/9568.json new file mode 100644 index 0000000000000000000000000000000000000000..c811854d9169b10bfe1ec53319b79396bf844856 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9568.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "03dc756c9fa93f3929cc47d1012fb103959a766c", + "authors": [ + { + "n": "Jean-Rémi KING", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 38, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9569.json b/mne-python/source/doc/sphinxext/prs/9569.json new file mode 100644 index 0000000000000000000000000000000000000000..4c93fd90210484970d7fd2eb8010b8471305f68d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9569.json @@ -0,0 +1,1979 @@ +{ + "merge_commit_sha": "a22a3ca42687fb63975070cc46ac7754af409732", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "examples/connectivity/cwt_sensor_connectivity.py": { + "a": 5, + "d": 3 + }, + "examples/connectivity/mixed_source_space_connectivity.py": { + "a": 4, + "d": 2 + }, + "examples/connectivity/mne_inverse_coherence_epochs.py": { + "a": 8, + "d": 6 + }, + "examples/connectivity/mne_inverse_connectivity_spectrum.py": { + "a": 3, + "d": 1 + }, + "examples/connectivity/mne_inverse_envelope_correlation.py": { + "a": 3, + "d": 1 + }, + "examples/connectivity/mne_inverse_envelope_correlation_volume.py": { + "a": 3, + "d": 1 + }, + "examples/connectivity/mne_inverse_label_connectivity.py": { + "a": 8, + "d": 6 + }, + "examples/connectivity/mne_inverse_psi_visual.py": { + "a": 4, + "d": 2 + }, + "examples/connectivity/sensor_connectivity.py": { + "a": 4, + "d": 2 + }, + "examples/datasets/brainstorm_data.py": { + "a": 4, + "d": 2 + }, + "examples/datasets/hf_sef_data.py": { + "a": 6, + "d": 4 + }, + "examples/datasets/limo_data.py": { + "a": 20, + "d": 18 + }, + "examples/datasets/opm_data.py": { + "a": 6, + "d": 4 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 8, + "d": 6 + }, + "examples/decoding/decoding_csp_eeg.py": { + "a": 5, + "d": 3 + }, + "examples/decoding/decoding_csp_timefreq.py": { + "a": 8, + "d": 6 + }, + "examples/decoding/decoding_rsa_sgskip.py": { + "a": 3, + "d": 1 + }, + "examples/decoding/decoding_spatio_temporal_source.py": { + "a": 7, + "d": 5 + }, + "examples/decoding/decoding_spoc_CMC.py": { + "a": 3, + "d": 1 + }, + "examples/decoding/decoding_time_generalization_conditions.py": { + "a": 6, + "d": 4 + }, + "examples/decoding/decoding_unsupervised_spatial_filter.py": { + "a": 3, + "d": 1 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 6, + "d": 4 + }, + "examples/decoding/ems_filtering.py": { + "a": 3, + "d": 1 + }, + "examples/decoding/linear_model_patterns.py": { + "a": 7, + "d": 5 + }, + "examples/decoding/receptive_field_mtrf.py": { + "a": 10, + "d": 8 + }, + "examples/decoding/ssd_spatial_filters.py": { + "a": 8, + "d": 6 + }, + "examples/forward/forward_sensitivity_maps.py": { + "a": 8, + "d": 6 + }, + "examples/forward/left_cerebellum_volume_source.py": { + "a": 6, + "d": 4 + }, + "examples/forward/source_space_morphing.py": { + "a": 3, + "d": 1 + }, + "examples/inverse/compute_mne_inverse_epochs_in_label.py": { + "a": 5, + "d": 3 + }, + "examples/inverse/compute_mne_inverse_raw_in_label.py": { + "a": 4, + "d": 2 + }, + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 3, + "d": 1 + }, + "examples/inverse/covariance_whitening_dspm.py": { + "a": 5, + "d": 3 + }, + "examples/inverse/custom_inverse_solver.py": { + "a": 6, + "d": 4 + }, + "examples/inverse/dics_source_power.py": { + "a": 11, + "d": 9 + }, + "examples/inverse/evoked_ers_source_power.py": { + "a": 9, + "d": 7 + }, + "examples/inverse/gamma_map_inverse.py": { + "a": 8, + "d": 6 + }, + "examples/inverse/label_activation_from_stc.py": { + "a": 3, + "d": 1 + }, + "examples/inverse/label_from_stc.py": { + "a": 5, + "d": 3 + }, + "examples/inverse/label_source_activations.py": { + "a": 6, + "d": 4 + }, + "examples/inverse/mixed_norm_inverse.py": { + "a": 10, + "d": 8 + }, + "examples/inverse/mixed_source_space_inverse.py": { + "a": 14, + "d": 12 + }, + "examples/inverse/mne_cov_power.py": { + "a": 10, + "d": 8 + }, + "examples/inverse/morph_surface_stc.py": { + "a": 12, + "d": 10 + }, + "examples/inverse/morph_volume_stc.py": { + "a": 10, + "d": 8 + }, + "examples/inverse/multidict_reweighted_tfmxne.py": { + "a": 8, + "d": 6 + }, + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 12, + "d": 10 + }, + "examples/inverse/psf_ctf_vertices.py": { + "a": 5, + "d": 3 + }, + "examples/inverse/psf_ctf_vertices_lcmv.py": { + "a": 5, + "d": 3 + }, + "examples/inverse/rap_music.py": { + "a": 4, + "d": 2 + }, + "examples/inverse/read_inverse.py": { + "a": 4, + "d": 2 + }, + "examples/inverse/read_stc.py": { + "a": 3, + "d": 1 + }, + "examples/inverse/resolution_metrics.py": { + "a": 12, + "d": 10 + }, + "examples/inverse/resolution_metrics_eegmeg.py": { + "a": 12, + "d": 10 + }, + "examples/inverse/snr_estimate.py": { + "a": 3, + "d": 1 + }, + "examples/inverse/source_space_snr.py": { + "a": 5, + "d": 3 + }, + "examples/inverse/time_frequency_mixed_norm_inverse.py": { + "a": 10, + "d": 8 + }, + "examples/inverse/vector_mne_solution.py": { + "a": 7, + "d": 5 + }, + "examples/io/elekta_epochs.py": { + "a": 8, + "d": 6 + }, + "examples/io/read_neo_format.py": { + "a": 3, + "d": 1 + }, + "examples/io/read_noise_covariance_matrix.py": { + "a": 4, + "d": 2 + }, + "examples/io/read_xdf.py": { + "a": 4, + "d": 2 + }, + "examples/preprocessing/define_target_events.py": { + "a": 6, + "d": 4 + }, + "examples/preprocessing/eeg_csd.py": { + "a": 10, + "d": 8 + }, + "examples/preprocessing/eog_artifact_histogram.py": { + "a": 5, + "d": 3 + }, + "examples/preprocessing/find_ref_artifacts.py": { + "a": 11, + "d": 9 + }, + "examples/preprocessing/fnirs_artifact_removal.py": { + "a": 9, + "d": 7 + }, + "examples/preprocessing/ica_comparison.py": { + "a": 9, + "d": 7 + }, + "examples/preprocessing/interpolate_bad_channels.py": { + "a": 6, + "d": 4 + }, + "examples/preprocessing/movement_compensation.py": { + "a": 10, + "d": 8 + }, + "examples/preprocessing/movement_detection.py": { + "a": 5, + "d": 3 + }, + "examples/preprocessing/muscle_detection.py": { + "a": 7, + "d": 5 + }, + "examples/preprocessing/otp.py": { + "a": 7, + "d": 5 + }, + "examples/preprocessing/shift_evoked.py": { + "a": 3, + "d": 1 + }, + "examples/preprocessing/virtual_evoked.py": { + "a": 7, + "d": 5 + }, + "examples/preprocessing/xdawn_denoising.py": { + "a": 7, + "d": 5 + }, + "examples/simulation/simulate_evoked_data.py": { + "a": 7, + "d": 5 + }, + "examples/simulation/simulate_raw_data.py": { + "a": 3, + "d": 1 + }, + "examples/simulation/simulated_raw_data_using_subject_anatomy.py": { + "a": 10, + "d": 8 + }, + "examples/simulation/source_simulator.py": { + "a": 3, + "d": 1 + }, + "examples/stats/cluster_stats_evoked.py": { + "a": 7, + "d": 5 + }, + "examples/stats/fdr_stats_evoked.py": { + "a": 7, + "d": 5 + }, + "examples/stats/linear_regression_raw.py": { + "a": 3, + "d": 1 + }, + "examples/stats/sensor_permutation_test.py": { + "a": 5, + "d": 3 + }, + "examples/stats/sensor_regression.py": { + "a": 3, + "d": 1 + }, + "examples/time_frequency/compute_csd.py": { + "a": 9, + "d": 7 + }, + "examples/time_frequency/compute_source_psd_epochs.py": { + "a": 6, + "d": 4 + }, + "examples/time_frequency/source_label_time_frequency.py": { + "a": 4, + "d": 2 + }, + "examples/time_frequency/source_power_spectrum.py": { + "a": 5, + "d": 3 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 9, + "d": 7 + }, + "examples/time_frequency/source_space_time_frequency.py": { + "a": 5, + "d": 3 + }, + "examples/time_frequency/temporal_whitening.py": { + "a": 4, + "d": 2 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 7, + "d": 5 + }, + "examples/time_frequency/time_frequency_global_field_power.py": { + "a": 6, + "d": 4 + }, + "examples/time_frequency/time_frequency_simulated.py": { + "a": 11, + "d": 9 + }, + "examples/visualization/3d_to_2d.py": { + "a": 6, + "d": 4 + }, + "examples/visualization/channel_epochs_image.py": { + "a": 6, + "d": 4 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 3, + "d": 1 + }, + "examples/visualization/eeglab_head_sphere.py": { + "a": 7, + "d": 5 + }, + "examples/visualization/evoked_arrowmap.py": { + "a": 6, + "d": 4 + }, + "examples/visualization/evoked_topomap.py": { + "a": 12, + "d": 10 + }, + "examples/visualization/evoked_whitening.py": { + "a": 7, + "d": 5 + }, + "examples/visualization/meg_sensors.py": { + "a": 8, + "d": 6 + }, + "examples/visualization/mne_helmet.py": { + "a": 2, + "d": 0 + }, + "examples/visualization/montage_sgskip.py": { + "a": 5, + "d": 3 + }, + "examples/visualization/parcellation.py": { + "a": 6, + "d": 4 + }, + "examples/visualization/publication_figure.py": { + "a": 14, + "d": 14 + }, + "examples/visualization/roi_erpimage_by_rt.py": { + "a": 7, + "d": 5 + }, + "examples/visualization/sensor_noise_level.py": { + "a": 5, + "d": 3 + }, + "examples/visualization/ssp_projs_sensitivity_map.py": { + "a": 4, + "d": 2 + }, + "examples/visualization/topo_compare_conditions.py": { + "a": 5, + "d": 3 + }, + "examples/visualization/topo_customized.py": { + "a": 3, + "d": 1 + }, + "examples/visualization/xhemi.py": { + "a": 3, + "d": 1 + }, + "logo/generate_mne_logos.py": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 1, + "d": 1 + }, + "mne/_ola.py": { + "a": 1, + "d": 1 + }, + "mne/_version.py": { + "a": 1, + "d": 1 + }, + "mne/annotations.py": { + "a": 1, + "d": 1 + }, + "mne/baseline.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_compute_beamformer.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_lcmv.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_external.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/bem.py": { + "a": 1, + "d": 1 + }, + "mne/channels/_standard_montage_utils.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_channels.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 1, + "d": 1 + }, + "mne/chpi.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_surf2bem.py": { + "a": 1, + "d": 1 + }, + "mne/commands/utils.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/effective.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/envelope.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/spectral.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/tests/test_envelope.py": { + "a": 1, + "d": 1 + }, + "mne/connectivity/utils.py": { + "a": 1, + "d": 1 + }, + "mne/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/cuda.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/limo/limo.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/ssd.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_base.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_csp.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_ems.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_search_light.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/tests/test_transformer.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_delaying_ridge.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/decoding/transformer.py": { + "a": 1, + "d": 1 + }, + "mne/defaults.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/event.py": { + "a": 1, + "d": 1 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/export/_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/export/_egimff.py": { + "a": 1, + "d": 1 + }, + "mne/export/_export.py": { + "a": 1, + "d": 1 + }, + "mne/export/tests/test_export.py": { + "a": 1, + "d": 1 + }, + "mne/externals/h5io/_h5io.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_compute_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_lead_dots.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/forward.py": { + "a": 1, + "d": 1 + }, + "mne/gui/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_backend.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_fiducials_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_file_traits.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_help.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_marker_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/_viewer.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_debiasing.py": { + "a": 1, + "d": 1 + }, + "mne/io/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/_digitization.py": { + "a": 1, + "d": 1 + }, + "mne/io/_read_raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 1 + }, + "mne/io/array/tests/test_array.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/io/boxy/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/boxy/boxy.py": { + "a": 1, + "d": 1 + }, + "mne/io/boxy/tests/test_boxy.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/bti/tests/test_bti.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/cnt/tests/test_cnt.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/eeg.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/hc.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/markers.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/res4.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf/trans.py": { + "a": 1, + "d": 1 + }, + "mne/io/ctf_comp.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 1, + "d": 1 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/events.py": { + "a": 1, + "d": 1 + }, + "mne/io/egi/general.py": { + "a": 1, + "d": 1 + }, + "mne/io/eximia/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/eximia/eximia.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/fieldtrip.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/tests/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/tests/test_fieldtrip.py": { + "a": 1, + "d": 1 + }, + "mne/io/fieldtrip/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/hitachi/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 1 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 1, + "d": 1 + }, + "mne/io/matrix.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/nedf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/nedf/tests/test_nedf.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/nicolet/tests/test_nicolet.py": { + "a": 1, + "d": 1 + }, + "mne/io/nihon/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/nihon/nihon.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/open.py": { + "a": 1, + "d": 1 + }, + "mne/io/persyst/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/persyst/persyst.py": { + "a": 1, + "d": 1 + }, + "mne/io/pick.py": { + "a": 1, + "d": 1 + }, + "mne/io/proj.py": { + "a": 1, + "d": 1 + }, + "mne/io/reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/io/tag.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_apply_function.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_compensator.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_read_raw.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_reference.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_show_fiff.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/tests/test_write.py": { + "a": 1, + "d": 1 + }, + "mne/io/tree.py": { + "a": 1, + "d": 1 + }, + "mne/io/utils.py": { + "a": 1, + "d": 1 + }, + "mne/io/what.py": { + "a": 1, + "d": 1 + }, + "mne/io/write.py": { + "a": 1, + "d": 1 + }, + "mne/label.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/_eloreta.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/inverse.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/spatial_resolution.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_resolution_matrix.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_resolution_metrics.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 1, + "d": 1 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/misc.py": { + "a": 1, + "d": 1 + }, + "mne/morph.py": { + "a": 1, + "d": 1 + }, + "mne/morph_map.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_csd.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/_regress.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/annotate_nan.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/bads.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/flat.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/infomax_.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxfilter.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_optical_density.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_scalp_coupling_index.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_tddr.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_optical_density.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/realign.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ssp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/stim.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ctps.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_infomax.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_otp.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_realign.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_regress.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_stim.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/xdawn.py": { + "a": 1, + "d": 1 + }, + "mne/proj.py": { + "a": 1, + "d": 1 + }, + "mne/rank.py": { + "a": 1, + "d": 1 + }, + "mne/report.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/metrics.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/source.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_metrics.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 1, + "d": 1 + }, + "mne/simulation/tests/test_source.py": { + "a": 1, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 1 + }, + "mne/stats/multi_comp.py": { + "a": 1, + "d": 1 + }, + "mne/stats/regression.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_permutations.py": { + "a": 1, + "d": 1 + }, + "mne/stats/tests/test_regression.py": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_line_endings.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_misc.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_morph.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_morph_map.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_estimate.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_source_space.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_surface.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/ar.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_stft.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tests/test_stockwell.py": { + "a": 1, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_bunch.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_logging.py": { + "a": 1, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/utils/dataframe.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/utils/fetching.py": { + "a": 1, + "d": 1 + }, + "mne/utils/linalg.py": { + "a": 1, + "d": 1 + }, + "mne/utils/misc.py": { + "a": 1, + "d": 1 + }, + "mne/utils/mixin.py": { + "a": 1, + "d": 1 + }, + "mne/utils/numerics.py": { + "a": 1, + "d": 1 + }, + "mne/utils/progressbar.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_bunch.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_check.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_linalg.py": { + "a": 1, + "d": 1 + }, + "mne/viz/conftest.py": { + "a": 2, + "d": 2 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "setup.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 15, + "d": 13 + }, + "tutorials/clinical/20_seeg.py": { + "a": 12, + "d": 10 + }, + "tutorials/clinical/30_ecog.py": { + "a": 8, + "d": 6 + }, + "tutorials/clinical/60_sleep.py": { + "a": 3, + "d": 1 + }, + "tutorials/epochs/10_epochs_overview.py": { + "a": 30, + "d": 28 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 17, + "d": 15 + }, + "tutorials/epochs/30_epochs_metadata.py": { + "a": 13, + "d": 11 + }, + "tutorials/epochs/40_autogenerate_metadata.py": { + "a": 18, + "d": 16 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 9, + "d": 7 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 8, + "d": 6 + }, + "tutorials/evoked/10_evoked_overview.py": { + "a": 17, + "d": 15 + }, + "tutorials/evoked/20_visualize_evoked.py": { + "a": 19, + "d": 17 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 28, + "d": 26 + }, + "tutorials/evoked/40_whitened.py": { + "a": 7, + "d": 5 + }, + "tutorials/forward/10_background_freesurfer.py": { + "a": 3, + "d": 1 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 11, + "d": 9 + }, + "tutorials/forward/30_forward.py": { + "a": 16, + "d": 14 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 3, + "d": 1 + }, + "tutorials/forward/50_background_freesurfer_mne.py": { + "a": 22, + "d": 20 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 9, + "d": 7 + }, + "tutorials/forward/90_compute_covariance.py": { + "a": 11, + "d": 9 + }, + "tutorials/intro/10_overview.py": { + "a": 16, + "d": 14 + }, + "tutorials/intro/15_inplace.py": { + "a": 6, + "d": 4 + }, + "tutorials/intro/20_events_from_raw.py": { + "a": 13, + "d": 11 + }, + "tutorials/intro/30_info.py": { + "a": 15, + "d": 13 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 19, + "d": 17 + }, + "tutorials/intro/50_configure_mne.py": { + "a": 17, + "d": 15 + }, + "tutorials/intro/70_report.py": { + "a": 17, + "d": 15 + }, + "tutorials/inverse/10_stc_class.py": { + "a": 10, + "d": 8 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 6, + "d": 4 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 13, + "d": 11 + }, + "tutorials/inverse/35_dipole_orientations.py": { + "a": 10, + "d": 10 + }, + "tutorials/inverse/40_mne_fixed_free.py": { + "a": 13, + "d": 11 + }, + "tutorials/inverse/50_beamformer_lcmv.py": { + "a": 18, + "d": 16 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 17, + "d": 15 + }, + "tutorials/inverse/70_eeg_mri_coords.py": { + "a": 3, + "d": 1 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 13, + "d": 11 + }, + "tutorials/inverse/85_brainstorm_phantom_ctf.py": { + "a": 12, + "d": 10 + }, + "tutorials/inverse/90_phantom_4DBTi.py": { + "a": 6, + "d": 4 + }, + "tutorials/io/10_reading_meg_data.py": { + "a": 2, + "d": 0 + }, + "tutorials/io/20_reading_eeg_data.py": { + "a": 2, + "d": 0 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 8, + "d": 6 + }, + "tutorials/io/60_ctf_bst_auditory.py": { + "a": 30, + "d": 28 + }, + "tutorials/machine-learning/30_strf.py": { + "a": 12, + "d": 10 + }, + "tutorials/machine-learning/50_decoding.py": { + "a": 12, + "d": 10 + }, + "tutorials/preprocessing/10_preprocessing_overview.py": { + "a": 11, + "d": 9 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 12, + "d": 10 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 15, + "d": 13 + }, + "tutorials/preprocessing/25_background_filtering.py": { + "a": 28, + "d": 28 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 12, + "d": 10 + }, + "tutorials/preprocessing/35_artifact_correction_regression.py": { + "a": 9, + "d": 7 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 30, + "d": 28 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 15, + "d": 13 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 23, + "d": 21 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 12, + "d": 10 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 10, + "d": 8 + }, + "tutorials/preprocessing/60_maxwell_filtering_sss.py": { + "a": 12, + "d": 10 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 22, + "d": 20 + }, + "tutorials/raw/10_raw_overview.py": { + "a": 26, + "d": 24 + }, + "tutorials/raw/20_event_arrays.py": { + "a": 12, + "d": 10 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 14, + "d": 12 + }, + "tutorials/raw/40_visualize_raw.py": { + "a": 10, + "d": 8 + }, + "tutorials/simulation/10_array_objs.py": { + "a": 11, + "d": 9 + }, + "tutorials/simulation/70_point_spread.py": { + "a": 12, + "d": 10 + }, + "tutorials/simulation/80_dics.py": { + "a": 14, + "d": 14 + }, + "tutorials/stats-sensor-space/10_background_stats.py": { + "a": 19, + "d": 17 + }, + "tutorials/stats-sensor-space/20_erp_stats.py": { + "a": 3, + "d": 1 + }, + "tutorials/stats-sensor-space/40_cluster_1samp_time_freq.py": { + "a": 7, + "d": 5 + }, + "tutorials/stats-sensor-space/50_cluster_between_time_freq.py": { + "a": 7, + "d": 5 + }, + "tutorials/stats-sensor-space/75_cluster_ftest_spatiotemporal.py": { + "a": 9, + "d": 7 + }, + "tutorials/stats-source-space/20_cluster_1samp_spatiotemporal.py": { + "a": 11, + "d": 9 + }, + "tutorials/stats-source-space/30_cluster_ftest_spatiotemporal.py": { + "a": 6, + "d": 4 + }, + "tutorials/stats-source-space/60_cluster_rmANOVA_spatiotemporal.py": { + "a": 15, + "d": 13 + }, + "tutorials/stats-source-space/70_cluster_rmANOVA_time_freq.py": { + "a": 14, + "d": 12 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 15, + "d": 13 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 13, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/957.json b/mne-python/source/doc/sphinxext/prs/957.json new file mode 100644 index 0000000000000000000000000000000000000000..8b5945260d0b9843d1b04c8c6853a761b95a11fe --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/957.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f8ee3acee790b249d52015afbeece81db6ced5ed", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/tests/test_viz.py": { + "a": 1, + "d": 1 + }, + "mne/viz.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9570.json b/mne-python/source/doc/sphinxext/prs/9570.json new file mode 100644 index 0000000000000000000000000000000000000000..8e3db8a535fb0781ab4169cedf8610b831f99619 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9570.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "0446fcf6efb4a04e51f38b3f72b1d1a187e50d26", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "doc/visualization.rst": { + "a": 1, + "d": 0 + }, + "mne/chpi.py": { + "a": 149, + "d": 32 + }, + "mne/tests/test_chpi.py": { + "a": 17, + "d": 1 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 77, + "d": 0 + }, + "mne/viz/tests/test_misc.py": { + "a": 27, + "d": 9 + }, + "tutorials/preprocessing/59_head_positions.py": { + "a": 17, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9574.json b/mne-python/source/doc/sphinxext/prs/9574.json new file mode 100644 index 0000000000000000000000000000000000000000..953a0908a2a07a2938e843e48ed8294a746031ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9574.json @@ -0,0 +1,247 @@ +{ + "merge_commit_sha": "ec2aaa7b1ff40fa2d7a38bd1c376b217d251376f", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/beamformer/_dics.py": { + "a": 1, + "d": 2 + }, + "mne/beamformer/_lcmv.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/_rap_music.py": { + "a": 3, + "d": 3 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 4, + "d": 5 + }, + "mne/bem.py": { + "a": 3, + "d": 7 + }, + "mne/channels/channels.py": { + "a": 14, + "d": 17 + }, + "mne/channels/layout.py": { + "a": 13, + "d": 15 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 2 + }, + "mne/chpi.py": { + "a": 3, + "d": 6 + }, + "mne/coreg.py": { + "a": 6, + "d": 3 + }, + "mne/cov.py": { + "a": 5, + "d": 10 + }, + "mne/decoding/csp.py": { + "a": 4, + "d": 6 + }, + "mne/decoding/ssd.py": { + "a": 1, + "d": 3 + }, + "mne/decoding/transformer.py": { + "a": 3, + "d": 5 + }, + "mne/dipole.py": { + "a": 1, + "d": 2 + }, + "mne/epochs.py": { + "a": 4, + "d": 7 + }, + "mne/event.py": { + "a": 3, + "d": 3 + }, + "mne/evoked.py": { + "a": 3, + "d": 5 + }, + "mne/forward/_field_interpolation.py": { + "a": 1, + "d": 2 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 8 + }, + "mne/forward/forward.py": { + "a": 7, + "d": 10 + }, + "mne/io/array/array.py": { + "a": 1, + "d": 2 + }, + "mne/io/base.py": { + "a": 3, + "d": 4 + }, + "mne/io/brainvision/brainvision.py": { + "a": 2, + "d": 2 + }, + "mne/io/compensator.py": { + "a": 3, + "d": 2 + }, + "mne/io/fiff/raw.py": { + "a": 1, + "d": 2 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 4 + }, + "mne/io/meas_info.py": { + "a": 11, + "d": 15 + }, + "mne/io/pick.py": { + "a": 10, + "d": 12 + }, + "mne/io/proj.py": { + "a": 7, + "d": 10 + }, + "mne/minimum_norm/inverse.py": { + "a": 4, + "d": 5 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 2 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 3, + "d": 4 + }, + "mne/rank.py": { + "a": 6, + "d": 9 + }, + "mne/simulation/evoked.py": { + "a": 1, + "d": 2 + }, + "mne/simulation/raw.py": { + "a": 1, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 1, + "d": 2 + }, + "mne/source_space.py": { + "a": 1, + "d": 2 + }, + "mne/surface.py": { + "a": 2, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 4, + "d": 8 + }, + "mne/utils/config.py": { + "a": 3, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 15, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 5, + "d": 9 + }, + "mne/viz/misc.py": { + "a": 5, + "d": 5 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 3 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9575.json b/mne-python/source/doc/sphinxext/prs/9575.json new file mode 100644 index 0000000000000000000000000000000000000000..c08ac0a6c206e7465ae48b6a3b1a19faf83ee316 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9575.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "144a58c9466563de2d379f3d51b7c3404729e37a", + "authors": [ + { + "n": "Darin Erat Sleiter", + "e": "darin@ae.studio" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 2, + "d": 1 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 10, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9578.json b/mne-python/source/doc/sphinxext/prs/9578.json new file mode 100644 index 0000000000000000000000000000000000000000..55fa232a7f8a93dac3abe7585f5d5236cee6bb43 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9578.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "c659bde91d22c994570571d84d61b960acbd09bb", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "doc/changes/0.22.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.23.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/epochs.py": { + "a": 0, + "d": 2 + }, + "mne/evoked.py": { + "a": 8, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 3, + "d": 3 + }, + "mne/tests/test_event.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 13, + "d": 2 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9579.json b/mne-python/source/doc/sphinxext/prs/9579.json new file mode 100644 index 0000000000000000000000000000000000000000..76ec129174328c5b1556dbafdf8879c280ef9f27 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9579.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "f3a7dece8d4361265e055f617e98c197c7cba07e", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/source_space.rst": { + "a": 0, + "d": 1 + }, + "mne/dipole.py": { + "a": 63, + "d": 2 + }, + "mne/label.py": { + "a": 0, + "d": 52 + }, + "mne/tests/test_dipole.py": { + "a": 11, + "d": 1 + }, + "mne/tests/test_label.py": { + "a": 3, + "d": 21 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 12, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/958.json b/mne-python/source/doc/sphinxext/prs/958.json new file mode 100644 index 0000000000000000000000000000000000000000..9a84b2b2d6dffc29d91d6328426cee3b1ad0c1bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/958.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6ce00d9c5bd57d2d461ef450a6b6b6878bb65121", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "examples/plot_estimate_covariance_matrix_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9582.json b/mne-python/source/doc/sphinxext/prs/9582.json new file mode 100644 index 0000000000000000000000000000000000000000..4378656a62fdff9638dda2bce58be765f85bd9f0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9582.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "b5767013e44a6b47393bc55d4534ea17a6b7b8bf", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "tutorials/machine-learning/50_decoding.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9585.json b/mne-python/source/doc/sphinxext/prs/9585.json new file mode 100644 index 0000000000000000000000000000000000000000..9f8319c0ef827067cff6877b96f0c9462f3af894 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9585.json @@ -0,0 +1,123 @@ +{ + "merge_commit_sha": "6756eab3dc55dc9c8fc5d30c3e4a5f5ad18659bd", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/_includes/forward.rst": { + "a": 1, + "d": 1 + }, + "doc/changes/0.21.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 8, + "d": 0 + }, + "doc/mri.rst": { + "a": 1, + "d": 0 + }, + "doc/overview/cookbook.rst": { + "a": 1, + "d": 1 + }, + "mne/_freesurfer.py": { + "a": 83, + "d": 2 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 1, + "d": 3 + }, + "mne/coreg.py": { + "a": 2, + "d": 1 + }, + "mne/defaults.py": { + "a": 2, + "d": 0 + }, + "mne/io/tag.py": { + "a": 4, + "d": 0 + }, + "mne/io/tests/test_meas_info.py": { + "a": 12, + "d": 0 + }, + "mne/surface.py": { + "a": 33, + "d": 42 + }, + "mne/tests/test_surface.py": { + "a": 42, + "d": 39 + }, + "mne/transforms.py": { + "a": 16, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 42, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 389, + "d": 419 + }, + "mne/viz/_brain/_brain.py": { + "a": 101, + "d": 12 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 32, + "d": 23 + }, + "mne/viz/tests/test_3d.py": { + "a": 55, + "d": 40 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 41, + "d": 35 + }, + "tutorials/forward/20_source_alignment.py": { + "a": 8, + "d": 7 + }, + "tutorials/intro/40_sensor_locations.py": { + "a": 2, + "d": 2 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 10, + "d": 13 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 8, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9586.json b/mne-python/source/doc/sphinxext/prs/9586.json new file mode 100644 index 0000000000000000000000000000000000000000..90df6c37e88d3b7a99e02f0cce98395ac5eb2718 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9586.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "4375989ef05990574bfe70c34cef111340ac2383", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/mri.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/gui/__init__.py": { + "a": 41, + "d": 0 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 883, + "d": 0 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 155, + "d": 0 + }, + "mne/surface.py": { + "a": 54, + "d": 34 + }, + "mne/tests/test_surface.py": { + "a": 8, + "d": 5 + }, + "mne/utils/_testing.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 4 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 121, + "d": 44 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9587.json b/mne-python/source/doc/sphinxext/prs/9587.json new file mode 100644 index 0000000000000000000000000000000000000000..114f40563e26bc4ffb470e99b86a9962d6ebfd00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9587.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "ace9e127a76e46883daa302ac3dacf80a9cbd675", + "authors": [ + { + "n": "PAB", + "e": null + }, + { + "n": "Pierre-Antoine Bannier", + "e": "pierre-antoine@macbook-pro-de-pierre-antoine.home" + }, + { + "n": "Pierre-Antoine Bannier", + "e": "pierre-antoine@mbpdepieantoine.home" + } + ], + "changes": { + "mne/inverse_sparse/mxne_optim.py": { + "a": 3, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 23, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9588.json b/mne-python/source/doc/sphinxext/prs/9588.json new file mode 100644 index 0000000000000000000000000000000000000000..581f1d35383834d315491e0cb1c929fb4d165b83 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9588.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "35e867ad6506d50a4fa1bef71cc2610bf1aad6f3", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/overview/roadmap.rst": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9589.json b/mne-python/source/doc/sphinxext/prs/9589.json new file mode 100644 index 0000000000000000000000000000000000000000..b6fd0a92dfd8e1310a46af4dc5227baa7f93c0af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9589.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "49253e74308137e14187561a204d784ea28f12a7", + "authors": [ + { + "n": "Gansheng TAN", + "e": null + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/959.json b/mne-python/source/doc/sphinxext/prs/959.json new file mode 100644 index 0000000000000000000000000000000000000000..087d4e16b79c6e579e469b893d88b658eb5e4b30 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/959.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3652601497564e5c1235a10771b2908489161729", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/epochs.py": { + "a": 16, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9590.json b/mne-python/source/doc/sphinxext/prs/9590.json new file mode 100644 index 0000000000000000000000000000000000000000..c50ba013aa2c5984265acd279b7d356b04ef2d28 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9590.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "575fae2221bd02f37603308b7151d03f81dfe7a9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_figure.py": { + "a": 4, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9592.json b/mne-python/source/doc/sphinxext/prs/9592.json new file mode 100644 index 0000000000000000000000000000000000000000..fd5f3d35739e0f4f290f3f38f0a62adfbfde7ec5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9592.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "57d792ff0a2240fc87599faac8e17eda33f04143", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 5, + "d": 0 + }, + ".github/workflows/compat_minimal.yml": { + "a": 3, + "d": 0 + }, + ".github/workflows/compat_old.yml": { + "a": 3, + "d": 0 + }, + ".github/workflows/linux_conda.yml": { + "a": 3, + "d": 0 + }, + ".github/workflows/linux_pip.yml": { + "a": 3, + "d": 0 + }, + ".github/workflows/macos_conda.yml": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9593.json b/mne-python/source/doc/sphinxext/prs/9593.json new file mode 100644 index 0000000000000000000000000000000000000000..9b83937f8bb07c1c7957b22f6b679bebe5cf8af8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9593.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "c1557623904877274607b6b7af7706c759d50571", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "doc/mri.rst": { + "a": 0, + "d": 1 + }, + "mne/surface.py": { + "a": 57, + "d": 44 + }, + "mne/tests/test_surface.py": { + "a": 25, + "d": 6 + }, + "mne/transforms.py": { + "a": 4, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 12, + "d": 13 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 0, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 0, + "d": 2 + }, + "tutorials/clinical/20_seeg.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9596.json b/mne-python/source/doc/sphinxext/prs/9596.json new file mode 100644 index 0000000000000000000000000000000000000000..12aafdc6c5ae0c8ab88ecb8c8b9b7af595fe9880 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9596.json @@ -0,0 +1,91 @@ +{ + "merge_commit_sha": "6c896a649d0de38dd68e98d2836aabe6fc17a123", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 103, + "d": 2 + }, + "mne/utils/config.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 235, + "d": 2244 + }, + "mne/viz/_mpl_figure.py": { + "a": 2352, + "d": 0 + }, + "mne/viz/backends/_utils.py": { + "a": 5, + "d": 0 + }, + "mne/viz/backends/renderer.py": { + "a": 6, + "d": 6 + }, + "mne/viz/epochs.py": { + "a": 6, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 4, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 5, + "d": 3 + }, + "mne/viz/tests/test_epochs.py": { + "a": 83, + "d": 125 + }, + "mne/viz/tests/test_figure.py": { + "a": 3, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 14, + "d": 14 + }, + "mne/viz/tests/test_raw.py": { + "a": 217, + "d": 221 + }, + "mne/viz/utils.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9598.json b/mne-python/source/doc/sphinxext/prs/9598.json new file mode 100644 index 0000000000000000000000000000000000000000..71ce5b9212c2f3c7ea69ae739dd075f6888b46e6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9598.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1df66682b6d460ac9b22d4c678034cc8706ff680", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 27, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 86, + "d": 60 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 18, + "d": 12 + }, + "mne/viz/backends/renderer.py": { + "a": 7, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9599.json b/mne-python/source/doc/sphinxext/prs/9599.json new file mode 100644 index 0000000000000000000000000000000000000000..675ada0adacae223a2f43c8796e4a7fe46a626dd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9599.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "fb074dd23f3a3364349415c4612d6401e1affece", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "examples/connectivity/mne_inverse_coherence_epochs.py": { + "a": 7, + "d": 5 + }, + "examples/inverse/covariance_whitening_dspm.py": { + "a": 10, + "d": 6 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 1, + "d": 1 + }, + "tutorials/simulation/80_dics.py": { + "a": 2, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/96.json b/mne-python/source/doc/sphinxext/prs/96.json new file mode 100644 index 0000000000000000000000000000000000000000..1abdede2e79730762091217b14a7a247c2c29dc3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/96.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6a1dc4d8784ff7dbbec063b066fefb89437ed47d", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/fiff/ctf.py": { + "a": 8, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9600.json b/mne-python/source/doc/sphinxext/prs/9600.json new file mode 100644 index 0000000000000000000000000000000000000000..554bb4831e1f8206acee530c14167a0101df4e3a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9600.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cd735c4d18918c4e0b1fa336d7d91fb828b32c4e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/tests/test_brain.py": { + "a": 1, + "d": 3 + }, + "server_environment.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9601.json b/mne-python/source/doc/sphinxext/prs/9601.json new file mode 100644 index 0000000000000000000000000000000000000000..c98a932111aac8db88b750ee8d9958acd870e0db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9601.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "64d51d6b122c5520a13825a0a360623993075d66", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 18, + "d": 1 + }, + "mne/channels/tests/test_montage.py": { + "a": 9, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 14, + "d": 26 + }, + "tutorials/clinical/20_seeg.py": { + "a": 33, + "d": 63 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9603.json b/mne-python/source/doc/sphinxext/prs/9603.json new file mode 100644 index 0000000000000000000000000000000000000000..ff4d37445418c324d2143c6a65c5fb00cc2781b5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9603.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9b43b2beeca84931049bdc83717aa579a747f2ea", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 1 + }, + "mne/conftest.py": { + "a": 5, + "d": 4 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 4, + "d": 3 + }, + "mne/source_space.py": { + "a": 7, + "d": 2 + }, + "mne/tests/test_source_space.py": { + "a": 11, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9605.json b/mne-python/source/doc/sphinxext/prs/9605.json new file mode 100644 index 0000000000000000000000000000000000000000..79294c4168077edcfa0d8cc005ca707ff60c9ea9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9605.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "5815375bf84f941e64d5338b7f159076dad3b010", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 50, + "d": 29 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 27, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9607.json b/mne-python/source/doc/sphinxext/prs/9607.json new file mode 100644 index 0000000000000000000000000000000000000000..43725252fd677d3fd2c17fb035e24c0f7a34a217 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9607.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "fe1086261e1849e983f36338aeb6a9b104b9a7a0", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 20, + "d": 19 + }, + "mne/utils/config.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 7, + "d": 7 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 10, + "d": 10 + }, + "mne/viz/backends/_qt.py": { + "a": 1, + "d": 4 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 88, + "d": 65 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 14, + "d": 3 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 40, + "d": 12 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 16 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9608.json b/mne-python/source/doc/sphinxext/prs/9608.json new file mode 100644 index 0000000000000000000000000000000000000000..c0e80b84d998da2b4ee967383f34777854e3d385 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9608.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "4d37ad3ced0f1a653b019a73f4a8fdaa2e49cab0", + "authors": [ + { + "n": "PAB", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Pierre-Antoine Bannier", + "e": "pierre-antoine@mbpdepieantoine.home" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 8, + "d": 1 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 5, + "d": 4 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9612.json b/mne-python/source/doc/sphinxext/prs/9612.json new file mode 100644 index 0000000000000000000000000000000000000000..29c9039b42edf52757b94794ed25679ccff1a86e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9612.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "6c9f5af6dc0e07c209d3bc8f0d1b964a80e7ad71", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 3, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 8, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 8, + "d": 3 + }, + "mne/tests/test_chpi.py": { + "a": 1, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 0 + }, + "tools/github_actions_test.sh": { + "a": 0, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9613.json b/mne-python/source/doc/sphinxext/prs/9613.json new file mode 100644 index 0000000000000000000000000000000000000000..cfcb0bf756f45aedb864df641d42dba24dff8919 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9613.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "96e830b3b02394f2c6aaea619ab46664580ed72b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/cov.py": { + "a": 4, + "d": 2 + }, + "mne/epochs.py": { + "a": 17, + "d": 17 + }, + "mne/evoked.py": { + "a": 7, + "d": 2 + }, + "mne/forward/forward.py": { + "a": 5, + "d": 5 + }, + "mne/io/base.py": { + "a": 8, + "d": 4 + }, + "mne/io/eeglab/eeglab.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 20, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 2 + }, + "mne/minimum_norm/inverse.py": { + "a": 5, + "d": 2 + }, + "mne/report/report.py": { + "a": 4, + "d": 4 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 1 + }, + "mne/source_estimate.py": { + "a": 19, + "d": 9 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/time_frequency/csd.py": { + "a": 1, + "d": 0 + }, + "mne/transforms.py": { + "a": 4, + "d": 2 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 9, + "d": 2 + }, + "mne/utils/config.py": { + "a": 7, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 0 + }, + "mne/utils/tests/test_check.py": { + "a": 6, + "d": 6 + }, + "mne/utils/tests/test_config.py": { + "a": 11, + "d": 5 + }, + "mne/viz/tests/test_evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9614.json b/mne-python/source/doc/sphinxext/prs/9614.json new file mode 100644 index 0000000000000000000000000000000000000000..64f0a04a06771bd91734248259c57a8322114615 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9614.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f73907c01ce6a18e4941969d3491cc561617c32d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "mne/gui/_file_traits.py": { + "a": 3, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9617.json b/mne-python/source/doc/sphinxext/prs/9617.json new file mode 100644 index 0000000000000000000000000000000000000000..d569ba289a6c144438635c0be0c475249862f152 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9617.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "474da964415c5233e955663b56e85531093be0a4", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/_freesurfer.py": { + "a": 13, + "d": 0 + }, + "mne/source_space.py": { + "a": 1, + "d": 14 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9618.json b/mne-python/source/doc/sphinxext/prs/9618.json new file mode 100644 index 0000000000000000000000000000000000000000..5c10340e66796a046d00558f0616f56eb9aaa304 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9618.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a7be363558c2126a88812e373408fa3e3cb69b26", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/_freesurfer.py": { + "a": 69, + "d": 4 + }, + "mne/viz/_3d.py": { + "a": 11, + "d": 62 + }, + "mne/viz/_brain/_brain.py": { + "a": 42, + "d": 3 + }, + "mne/viz/_brain/surface.py": { + "a": 3, + "d": 0 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 5, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9621.json b/mne-python/source/doc/sphinxext/prs/9621.json new file mode 100644 index 0000000000000000000000000000000000000000..3281e629f80e79f945caad8e3f52886bf2d6786f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9621.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3c720e8f7a93d86e1db20fd949eee315cbced981", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/bem.py": { + "a": 1, + "d": 4 + }, + "mne/tests/test_bem.py": { + "a": 3, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 10, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9622.json b/mne-python/source/doc/sphinxext/prs/9622.json new file mode 100644 index 0000000000000000000000000000000000000000..ba798c06183ad5426c469506cfc517e7a5720c93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9622.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "33d2aea4a3790953c38dcc28582d614c20419649", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/transforms.py": { + "a": 33, + "d": 30 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9625.json b/mne-python/source/doc/sphinxext/prs/9625.json new file mode 100644 index 0000000000000000000000000000000000000000..f4ff54eb37cefb417b03d6b01bd0d68e0a612ca2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9625.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b66734cf6f174b6806b52d4162830adb8d2a1825", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/_freesurfer.py": { + "a": 46, + "d": 22 + }, + "mne/report.py": { + "a": 5, + "d": 7 + }, + "mne/viz/misc.py": { + "a": 21, + "d": 34 + }, + "tutorials/forward/30_forward.py": { + "a": 4, + "d": 3 + }, + "tutorials/intro/70_report.py": { + "a": 21, + "d": 20 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9626.json b/mne-python/source/doc/sphinxext/prs/9626.json new file mode 100644 index 0000000000000000000000000000000000000000..d491805d447ffe23c61f95f76220fe782517847a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9626.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "57e5e7f73b4a10d1cf3bfeb91685df7f88fcdbd9", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "examples/visualization/brain.py": { + "a": 113, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9629.json b/mne-python/source/doc/sphinxext/prs/9629.json new file mode 100644 index 0000000000000000000000000000000000000000..f437ae5037625e8f5004385d7e1a2e43a1e73438 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9629.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2328a7fad54c40cbc0cea03e3fc60d594f036b93", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_figure.py": { + "a": 2, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 15, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9630.json b/mne-python/source/doc/sphinxext/prs/9630.json new file mode 100644 index 0000000000000000000000000000000000000000..2c15858014ef20fbcab035d51895d854a32dcb5d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9630.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8d8609ade86b6daca5173faa7414885bde04df29", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9634.json b/mne-python/source/doc/sphinxext/prs/9634.json new file mode 100644 index 0000000000000000000000000000000000000000..1fd35574d6f3d8ba7c4504d474979ffe0f0670da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9634.json @@ -0,0 +1,79 @@ +{ + "merge_commit_sha": "8f62deb0f34b8f1abb40558cc804d412c716cb16", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Robert Luke", + "e": "748691+rob-luke@users.noreply.github.com" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 13, + "d": 4 + }, + "doc/install/advanced.rst": { + "a": 22, + "d": 22 + }, + "doc/install/index.rst": { + "a": 22, + "d": 12 + }, + "doc/install/install_python.rst": { + "a": 132, + "d": 0 + }, + "doc/install/mne_python.rst": { + "a": 58, + "d": 140 + }, + "doc/install/updating.rst": { + "a": 77, + "d": 0 + }, + "doc/links.inc": { + "a": 1, + "d": 0 + }, + "doc/overview/faq.rst": { + "a": 2, + "d": 2 + }, + "doc/overview/get_help.rst": { + "a": 2, + "d": 1 + }, + "doc/overview/index.rst": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9637.json b/mne-python/source/doc/sphinxext/prs/9637.json new file mode 100644 index 0000000000000000000000000000000000000000..a718c5f3f35b4934a2e2b037d13ca5665d2a0504 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9637.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "89a975df53bea691398000b5a8e5261c3fb9ac0d", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/reference.py": { + "a": 22, + "d": 9 + }, + "mne/io/tests/test_reference.py": { + "a": 7, + "d": 7 + }, + "mne/utils/docs.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9640.json b/mne-python/source/doc/sphinxext/prs/9640.json new file mode 100644 index 0000000000000000000000000000000000000000..42e7fd3266ff1459d1ac3a6e3e0433366e8918d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9640.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "53d0f5de8a8a99e3f4211a8dc1361930e3cc3cd8", + "authors": [ + { + "n": "PAB", + "e": null + }, + { + "n": "Pierre-Antoine Bannier", + "e": "pierre-antoine@MacBook-Pro-de-Pierre-Antoine.local" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 22, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9642.json b/mne-python/source/doc/sphinxext/prs/9642.json new file mode 100644 index 0000000000000000000000000000000000000000..11c5635439686df4db786d5376d8641230b8bf86 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9642.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8df2aeebb87e0b34937c9a70c2b8d0025470f1a4", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9643.json b/mne-python/source/doc/sphinxext/prs/9643.json new file mode 100644 index 0000000000000000000000000000000000000000..4f84636916e0da40d500b9a7e19f93fd205c1ad5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9643.json @@ -0,0 +1,111 @@ +{ + "merge_commit_sha": "59c3b921cf7609d0f2ffc19c1a7dc276110100a3", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/conftest.py": { + "a": 4, + "d": 1 + }, + "mne/export/_edf.py": { + "a": 225, + "d": 0 + }, + "mne/export/_export.py": { + "a": 5, + "d": 2 + }, + "mne/export/tests/test_export.py": { + "a": 132, + "d": 4 + }, + "mne/io/base.py": { + "a": 5, + "d": 2 + }, + "mne/io/tests/data/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/utils/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/utils/check.py": { + "a": 14, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 12, + "d": 0 + }, + "requirements_testing_extra.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9644.json b/mne-python/source/doc/sphinxext/prs/9644.json new file mode 100644 index 0000000000000000000000000000000000000000..bd891cf5340c9f9b9943290ce4fd795aafbdf20c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9644.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "759d1f9630c82109210da1eb41b45a7cd30a0f12", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "examples/visualization/eeglab_head_sphere.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9646.json b/mne-python/source/doc/sphinxext/prs/9646.json new file mode 100644 index 0000000000000000000000000000000000000000..4334b5bc57c9d24f39ae57f570b020cdf170be9c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9646.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c1891279801e1a9690017c53d211e0d7e4a45a90", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9647.json b/mne-python/source/doc/sphinxext/prs/9647.json new file mode 100644 index 0000000000000000000000000000000000000000..998a25c99bf68fb1f00b14b42eacf622dfe573fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9647.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c9752455b79de10fac672d3ed25911f2618f71cc", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/decoding/csp.py": { + "a": 2, + "d": 9 + }, + "mne/utils/docs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/topomap.py": { + "a": 7, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9648.json b/mne-python/source/doc/sphinxext/prs/9648.json new file mode 100644 index 0000000000000000000000000000000000000000..58e70232356db523ebf252b3ce1875ed37fe5611 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9648.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c556894a79e94c3a079725cb2ba9f5cc00076bb9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 10, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9650.json b/mne-python/source/doc/sphinxext/prs/9650.json new file mode 100644 index 0000000000000000000000000000000000000000..2a0a73a899b77610926ac32108f2edd49c6545d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9650.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "855edbf48835bcee80e773eb7047d0a4caa14a1c", + "authors": [ + { + "n": "Jeff Stout", + "e": null + }, + { + "n": "Jeff Stout", + "e": "stoutjd@nih.gov" + } + ], + "changes": { + "mne/_freesurfer.py": { + "a": 6, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9651.json b/mne-python/source/doc/sphinxext/prs/9651.json new file mode 100644 index 0000000000000000000000000000000000000000..76e7a33beaecbec1e44b77ef0b04b504c7165448 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9651.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4fd5b1d8dc0e89de4b0953cb4ca1825774e27588", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "examples/visualization/evoked_topomap.py": { + "a": 31, + "d": 1 + }, + "mne/decoding/csp.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 16, + "d": 5 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9656.json b/mne-python/source/doc/sphinxext/prs/9656.json new file mode 100644 index 0000000000000000000000000000000000000000..d851e071d4665579b3f23aeedb15c5e41102c353 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9656.json @@ -0,0 +1,307 @@ +{ + "merge_commit_sha": "9b16524bc8b98211d351afb19efd264f04c18e60", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/_templates/layout.html": { + "a": 0, + "d": 0 + }, + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 0, + "d": 0 + }, + "mne/beamformer/resolution_matrix.py": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/CTF-275.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/KIT-AS-2008.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/Vectorview-all.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/Vectorview-grad.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/Vectorview-mag.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/layouts/magnesWH3600.lout": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/biosemi16_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/biosemi32_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/biosemi64_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/bti148_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/bti248_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/bti248grad_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/ctf151_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/ctf275_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/ctf64_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycap128ch-avg_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycap32ch-avg_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycap64ch-avg_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycapM11_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycapM14_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycapM15_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/easycapM1_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/neuromag306mag_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/channels/data/neighbors/neuromag306planar_neighb.mat": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_bti2fiff.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_clean_eog_ecg.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_compare_fiff.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_compute_proj_ecg.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_compute_proj_eog.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_coreg.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_freeview_bem_surfaces.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_make_scalp_surfaces.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_maxfilter.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_report.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_show_fiff.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_show_info.py": { + "a": 0, + "d": 0 + }, + "mne/commands/mne_surf2bem.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/mxne_debiasing.py": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/tests/test_mxne_debiasing.py": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test.eeg": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test.vhdr": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test.vmrk": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_highpass.vhdr": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_lowpass_s.vhdr": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_mixed_highpass.vhdr": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_partially_disabled_hw_filter.vhdr": { + "a": 0, + "d": 0 + }, + "mne/io/brainvision/tests/data/test_units.vhdr": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/test_config_linux": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/test_hs_linux": { + "a": 0, + "d": 0 + }, + "mne/io/bti/tests/data/test_pdf_linux": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test_edf_stim_channel.edf": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test_edf_stim_channel.txt": { + "a": 0, + "d": 0 + }, + "mne/io/edf/tests/data/test_uneven_samp.edf": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_elp.txt": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_hsp.txt": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_mrk.sqd": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_mrk_post.sqd": { + "a": 0, + "d": 0 + }, + "mne/io/kit/tests/data/test_mrk_pre.sqd": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-ave.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-cov.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-eve.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test-no-reject.ave": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test.ave": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test.cov": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_keepmean.cov": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_raw-eve.fif": { + "a": 0, + "d": 0 + }, + "mne/io/tests/data/test_raw.fif": { + "a": 0, + "d": 0 + }, + "mne/preprocessing/tests/test_artifact_detection.py": { + "a": 0, + "d": 0 + }, + "setup.py": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9657.json b/mne-python/source/doc/sphinxext/prs/9657.json new file mode 100644 index 0000000000000000000000000000000000000000..5bf0a1a529446e73dae9ca67b9cc362a6313e20e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9657.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "95facbd1a28e471cf81e1d86735fa272a66d13d1", + "authors": [ + { + "n": "Hubert Banville", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "mne/datasets/sleep_physionet/_utils.py": { + "a": 4, + "d": 10 + }, + "mne/datasets/sleep_physionet/age.py": { + "a": 6, + "d": 10 + }, + "mne/datasets/sleep_physionet/temazepam.py": { + "a": 7, + "d": 10 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 17, + "d": 19 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9658.json b/mne-python/source/doc/sphinxext/prs/9658.json new file mode 100644 index 0000000000000000000000000000000000000000..650709ecf32f5f7fd4828c7f720d83598e1e7a35 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9658.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "2f6d6b4667af1a3214e1a84ae21f8109429770a3", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "mne/channels/__init__.py": { + "a": 3, + "d": 3 + }, + "mne/channels/montage.py": { + "a": 55, + "d": 0 + }, + "mne/channels/tests/test_montage.py": { + "a": 33, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9663.json b/mne-python/source/doc/sphinxext/prs/9663.json new file mode 100644 index 0000000000000000000000000000000000000000..04c88b02d36fafcfc33e85b4b00e798cc31e1ca2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9663.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "977397f575f8f37177bb62a05d272f2aa1874a6e", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_evoked.py": { + "a": 16, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9665.json b/mne-python/source/doc/sphinxext/prs/9665.json new file mode 100644 index 0000000000000000000000000000000000000000..f21de316da5d9bf40f32050552db785a6fdbe07f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9665.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "4f510337d5008a6fcfbaa134fbba921a49ec18b9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 4, + "d": 0 + }, + "tools/circleci_dependencies.sh": { + "a": 3, + "d": 4 + }, + "tools/setup_xvfb.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9666.json b/mne-python/source/doc/sphinxext/prs/9666.json new file mode 100644 index 0000000000000000000000000000000000000000..33a6a0b4aeccbb067ff6473d4f66f0843ddf33f4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9666.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8e5ab68d05cb59a7e7d95275ca01d548432d2c9a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/datasets/utils.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9667.json b/mne-python/source/doc/sphinxext/prs/9667.json new file mode 100644 index 0000000000000000000000000000000000000000..6b788730d3d6ff14e0f8cbd53bbfd34f95d17f38 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9667.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7636a58a744bb95b59816144cce7d01746fe6db7", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/967.json b/mne-python/source/doc/sphinxext/prs/967.json new file mode 100644 index 0000000000000000000000000000000000000000..91b8887ec87019df21dfe3f42962f0e7f6927795 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/967.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "d6a2a01f1c0db51ca8d397cb238add43afd035a8", + "authors": [ + { + "n": "Hari Bharadwaj", + "e": null + } + ], + "changes": { + "mne/utils.py": { + "a": 236, + "d": 44 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9670.json b/mne-python/source/doc/sphinxext/prs/9670.json new file mode 100644 index 0000000000000000000000000000000000000000..7ba3c4ccaf9bda0ad200d17d73e12b390294d475 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9670.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "9d75a529c6a30e9de47409c8e6e9730dd7026bcc", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/psf_ctf_label_leakage.py": { + "a": 3, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9671.json b/mne-python/source/doc/sphinxext/prs/9671.json new file mode 100644 index 0000000000000000000000000000000000000000..3554237fe307207a3ecd032758fc53a7adff0ceb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9671.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a14e7e35cbbc5f55585492a8993196198dc392b7", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9672.json b/mne-python/source/doc/sphinxext/prs/9672.json new file mode 100644 index 0000000000000000000000000000000000000000..2e3168442b235fd8c097b2ccceb5739297d9592f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9672.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e0e98c0bd9c73f1a84430e66923c0e414ff320d9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 29, + "d": 15 + }, + "mne/tests/test_coreg.py": { + "a": 12, + "d": 9 + }, + "tools/circleci_dependencies.sh": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9674.json b/mne-python/source/doc/sphinxext/prs/9674.json new file mode 100644 index 0000000000000000000000000000000000000000..52e6a00f2ad0e217ec3caf924c82d5e2ae0356a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9674.json @@ -0,0 +1,75 @@ +{ + "merge_commit_sha": "68c19a6fd81f101999ef910d8907c765e7c61392", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 0 + }, + "doc/changes/0.12.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.15.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.18.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.19.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.20.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.22.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.23.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 2, + "d": 2 + }, + "doc/connectivity.rst": { + "a": 2, + "d": 16 + }, + "doc/visualization.rst": { + "a": 0, + "d": 1 + }, + "examples/io/read_neo_format.py": { + "a": 1, + "d": 1 + }, + "mne/viz/circle.py": { + "a": 21, + "d": 2 + }, + "tutorials/clinical/20_seeg.py": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9676.json b/mne-python/source/doc/sphinxext/prs/9676.json new file mode 100644 index 0000000000000000000000000000000000000000..c252d4caaf007f72dbf8cb6ef07404e12456b37e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9676.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6f8947d5a611297cd32298af9f55d974ba2cdee0", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9677.json b/mne-python/source/doc/sphinxext/prs/9677.json new file mode 100644 index 0000000000000000000000000000000000000000..8fcbd2f6ad1203850c15abe5ddada8e9e58887aa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9677.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "9b4ec7e68a6bb5ada2296058dce131397ebbeec4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/artifact_detection.py": { + "a": 2, + "d": 2 + }, + "mne/stats/cluster_level.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_rank.py": { + "a": 1, + "d": 1 + }, + "mne/utils/tests/test_numerics.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 3, + "d": 3 + }, + "tutorials/inverse/20_dipole_fit.py": { + "a": 4, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9678.json b/mne-python/source/doc/sphinxext/prs/9678.json new file mode 100644 index 0000000000000000000000000000000000000000..9674ed5b0ef19176a86e0823870ead7c8349c1da --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9678.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "043e7d5e5dabccb5504c59f54b44b6c0e0cb5694", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "examples/inverse/compute_mne_inverse_volume.py": { + "a": 2, + "d": 2 + }, + "examples/visualization/publication_figure.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 6, + "d": 1 + }, + "tutorials/forward/30_forward.py": { + "a": 3, + "d": 3 + }, + "tutorials/inverse/30_mne_dspm_loreta.py": { + "a": 2, + "d": 1 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 10, + "d": 8 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 2, + "d": 1 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9682.json b/mne-python/source/doc/sphinxext/prs/9682.json new file mode 100644 index 0000000000000000000000000000000000000000..9159a5bf83a84f17f30e0527e5d7b736ee9e5cdb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9682.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "cf307a48e130ca27868c3706100bf2c402c9de1f", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/datasets/opm_data.py": { + "a": 1, + "d": 1 + }, + "examples/forward/left_cerebellum_volume_source.py": { + "a": 5, + "d": 4 + }, + "examples/time_frequency/source_power_spectrum_opm.py": { + "a": 3, + "d": 3 + }, + "examples/visualization/3d_to_2d.py": { + "a": 20, + "d": 11 + }, + "mne/channels/montage.py": { + "a": 45, + "d": 3 + }, + "mne/channels/tests/test_montage.py": { + "a": 14, + "d": 3 + }, + "mne/data/image/custom_layout.lout": { + "a": 65, + "d": 23 + }, + "mne/viz/_brain/_brain.py": { + "a": 15, + "d": 11 + }, + "tutorials/clinical/20_seeg.py": { + "a": 1, + "d": 3 + }, + "tutorials/clinical/30_ecog.py": { + "a": 18, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9684.json b/mne-python/source/doc/sphinxext/prs/9684.json new file mode 100644 index 0000000000000000000000000000000000000000..35035c7087345f0ee7876174a665d1d760141e31 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9684.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "041068d510cc746b0a994609a59213f279be0c81", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/montage.py": { + "a": 28, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9685.json b/mne-python/source/doc/sphinxext/prs/9685.json new file mode 100644 index 0000000000000000000000000000000000000000..1902cf94e288f5d30fdfb1a54f4a20dca0bb3531 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9685.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5ac71c35403983091c6fb6ebe552b73d79c3d9db", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 15, + "d": 12 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9687.json b/mne-python/source/doc/sphinxext/prs/9687.json new file mode 100644 index 0000000000000000000000000000000000000000..9a8de586597529ab650e16e9fa9de0da37fd0b2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9687.json @@ -0,0 +1,143 @@ +{ + "merge_commit_sha": "5bafe5287dd27ef6e07a64609615326110536578", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + ".github/workflows/compat_minimal.yml": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 7, + "d": 5 + }, + "doc/changes/latest.inc": { + "a": 5, + "d": 1 + }, + "doc/cited.rst": { + "a": 3, + "d": 3 + }, + "doc/visualization.rst": { + "a": 3, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/commands/mne_browse_raw.py": { + "a": 2, + "d": 3 + }, + "mne/conftest.py": { + "a": 48, + "d": 6 + }, + "mne/io/base.py": { + "a": 5, + "d": 4 + }, + "mne/utils/config.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 23, + "d": 0 + }, + "mne/utils/tests/test_config.py": { + "a": 3, + "d": 1 + }, + "mne/viz/__init__.py": { + "a": 4, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 305, + "d": 56 + }, + "mne/viz/_mpl_figure.py": { + "a": 53, + "d": 187 + }, + "mne/viz/epochs.py": { + "a": 2, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 1, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 25, + "d": 10 + }, + "mne/viz/tests/test_epochs.py": { + "a": 16, + "d": 16 + }, + "mne/viz/tests/test_ica.py": { + "a": 4, + "d": 4 + }, + "mne/viz/tests/test_raw.py": { + "a": 327, + "d": 226 + }, + "mne/viz/utils.py": { + "a": 32, + "d": 1 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "tools/github_actions_infos.sh": { + "a": 1, + "d": 0 + }, + "tools/github_actions_test.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9688.json b/mne-python/source/doc/sphinxext/prs/9688.json new file mode 100644 index 0000000000000000000000000000000000000000..62f3c7851399bfa6280efd9555c95bd9f9be7cd6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9688.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "27c5d536808d9c8226047a825582b43df1218c95", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 23, + "d": 13 + }, + "mne/viz/_brain/_brain.py": { + "a": 123, + "d": 15 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 14, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 9, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 9, + "d": 6 + }, + "mne/viz/backends/_pyvista.py": { + "a": 4, + "d": 4 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9689.json b/mne-python/source/doc/sphinxext/prs/9689.json new file mode 100644 index 0000000000000000000000000000000000000000..f5b88e10fc1432da92b5684005726552dd336eb6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9689.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "53335f68227374b584ede6f4300f0f97f5efb0aa", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 54, + "d": 16 + }, + "mne/gui/_coreg.py": { + "a": 976, + "d": 0 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 91, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 7, + "d": 3 + }, + "requirements.txt": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/969.json b/mne-python/source/doc/sphinxext/prs/969.json new file mode 100644 index 0000000000000000000000000000000000000000..f4fa7739247bb9010fc64c7285cd9a86143a2255 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/969.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "5c97f2c476dc45fc7eccf167f7201c42696b7fb6", + "authors": [ + { + "n": "Teon L Brooks", + "e": null + } + ], + "changes": { + "mne/fiff/kit/kit.py": { + "a": 20, + "d": 13 + }, + "mne/fiff/kit/tests/test_coreg.py": { + "a": 3, + "d": 4 + }, + "mne/fiff/kit/tests/test_kit.py": { + "a": 7, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9690.json b/mne-python/source/doc/sphinxext/prs/9690.json new file mode 100644 index 0000000000000000000000000000000000000000..b0fcee856b3c3e4e976a680988df0a6d24ccba7c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9690.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e2ea2d093e0b3fded4251794ed7998bc7a51c53c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".gitignore": { + "a": 2, + "d": 0 + }, + "mne/coreg.py": { + "a": 25, + "d": 0 + }, + "mne/tests/test_coreg.py": { + "a": 88, + "d": 6 + }, + "tutorials/forward/25_automated_coreg.py": { + "a": 10, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9691.json b/mne-python/source/doc/sphinxext/prs/9691.json new file mode 100644 index 0000000000000000000000000000000000000000..7c20c669ace04e3744508fa7545ae1a549ca640c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9691.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c890338c82c1da589221f41c59ee50cd2e185373", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/references.bib": { + "a": 6, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9692.json b/mne-python/source/doc/sphinxext/prs/9692.json new file mode 100644 index 0000000000000000000000000000000000000000..f0f29a1a7d3ffdef116fc0f8644efc3519076b16 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9692.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "accfe88c75eebac39c85f85ceb648de999198e41", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + }, + { + "n": "Britta Westner", + "e": "britta.wstnr@gmail.com" + } + ], + "changes": { + ".github/CODEOWNERS": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9693.json b/mne-python/source/doc/sphinxext/prs/9693.json new file mode 100644 index 0000000000000000000000000000000000000000..ce1b6548412da2c6c65e37edba1f3254a7566dd0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9693.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9d00983119a41e5e0292577e746c03474f981f8e", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 3, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9694.json b/mne-python/source/doc/sphinxext/prs/9694.json new file mode 100644 index 0000000000000000000000000000000000000000..736def681ce87c872eb9bdeb5f2656afe52e6e41 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9694.json @@ -0,0 +1,99 @@ +{ + "merge_commit_sha": "a2036aaaf1f34a5fdfd84a6c1eb75986dd2608b7", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 5, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 2, + "d": 2 + }, + "mne/export/_edf.py": { + "a": 55, + "d": 13 + }, + "mne/export/_export.py": { + "a": 8, + "d": 4 + }, + "mne/export/tests/test_export.py": { + "a": 137, + "d": 16 + }, + "mne/io/base.py": { + "a": 4, + "d": 2 + }, + "mne/io/edf/edf.py": { + "a": 101, + "d": 3 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 19, + "d": 3 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 23, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9695.json b/mne-python/source/doc/sphinxext/prs/9695.json new file mode 100644 index 0000000000000000000000000000000000000000..2657be68d27922b2e9c642027173f8ede9cc0f61 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9695.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bcf2b2f7d5479060d6cff9a227ffbb795cbe7f85", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 2, + "d": 1 + }, + "mne/io/nihon/tests/test_nihon.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9696.json b/mne-python/source/doc/sphinxext/prs/9696.json new file mode 100644 index 0000000000000000000000000000000000000000..c809dc9a91a9d4c065d833037074509e92a94731 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9696.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2e672de3de6599320c11480f41e353e16877ba24", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_mpl_figure.py": { + "a": 11, + "d": 8 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9697.json b/mne-python/source/doc/sphinxext/prs/9697.json new file mode 100644 index 0000000000000000000000000000000000000000..e98e05c2720ceddaf7bbdb06d76721ef154361fc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9697.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2291946a916798dff4e26a0f3a0c7a35d395fe6c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 2 + }, + "mne/viz/tests/test_3d_mpl.py": { + "a": 9, + "d": 0 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9698.json b/mne-python/source/doc/sphinxext/prs/9698.json new file mode 100644 index 0000000000000000000000000000000000000000..9f1b382d1523848f17f1eb0e538d54e4e0dfcafb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9698.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "89dba30445e759ca98102998f6b39eaca292b0fd", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fixes.py": { + "a": 20, + "d": 0 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 5 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 1 + }, + "mne/viz/backends/_pyvista.py": { + "a": 11, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9699.json b/mne-python/source/doc/sphinxext/prs/9699.json new file mode 100644 index 0000000000000000000000000000000000000000..2f5b2d7593d936c437915df385fb71054edb91eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9699.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "22cd7747529db7895345917c4d3884a482ed8ab3", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/forward/25_automated_coreg.py": { + "a": 9, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/970.json b/mne-python/source/doc/sphinxext/prs/970.json new file mode 100644 index 0000000000000000000000000000000000000000..f3e0efcd3f2b0c1131e54233537f708fd07be172 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/970.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "13483b856318e3866a9ae1064a0d29decc17b2a9", + "authors": [ + { + "n": "Alan Leggitt", + "e": "leggitta3@gmail.com" + } + ], + "changes": { + "mne/fiff/edf/edf.py": { + "a": 6, + "d": 0 + }, + "mne/fiff/edf/tests/test_edf.py": { + "a": 11, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9705.json b/mne-python/source/doc/sphinxext/prs/9705.json new file mode 100644 index 0000000000000000000000000000000000000000..c0e6911379adf47a87058add423fc387ad54b3d9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9705.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3ff69f61d692ce34731ce94c277d16ae18319516", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/io/tests/test_raw.py": { + "a": 4, + "d": 1 + }, + "mne/utils/tests/test_numerics.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9706.json b/mne-python/source/doc/sphinxext/prs/9706.json new file mode 100644 index 0000000000000000000000000000000000000000..188fc77c7f619299b1606c0a7ca685f47f97ce11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9706.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "2606a9bbf53f038e3c79d2799442ea9edb7fd2dc", + "authors": [ + { + "n": "Tim Gates", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/decoding/tests/test_ssd.py": { + "a": 1, + "d": 1 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/io/constants.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 1, + "d": 1 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9708.json b/mne-python/source/doc/sphinxext/prs/9708.json new file mode 100644 index 0000000000000000000000000000000000000000..0fbd1be4e137920cf9a0e8dc0861b931828555d5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9708.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "6ab3c551910fd21d6da7c2a9b9aa3712b75c9352", + "authors": [ + { + "n": "Evgeny Goldstein", + "e": "evgenygoldstein@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_channels.py": { + "a": 20, + "d": 0 + }, + "mne/io/pick.py": { + "a": 10, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9711.json b/mne-python/source/doc/sphinxext/prs/9711.json new file mode 100644 index 0000000000000000000000000000000000000000..66a34392f1ec4d35055c85a7d9bc30590a6c854d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9711.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "b20f6b314b57d53c1c0f0277c1aaee5658004e06", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/defaults.py": { + "a": 4, + "d": 4 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9712.json b/mne-python/source/doc/sphinxext/prs/9712.json new file mode 100644 index 0000000000000000000000000000000000000000..5a622ad8bd01b425a5b97668fe694df1da6feb00 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9712.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8983996fdeb679157db102de075852bce97796b0", + "authors": [ + { + "n": "Reza Shoorangiz", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/io/curry/curry.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9714.json b/mne-python/source/doc/sphinxext/prs/9714.json new file mode 100644 index 0000000000000000000000000000000000000000..80d6943b36f5c8195a1a5d7f2a59936ef2e48998 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9714.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3e7914e18549d28087440c3f87d88a5520064bd4", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 161, + "d": 113 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + }, + "tutorials/forward/35_eeg_no_mri.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9719.json b/mne-python/source/doc/sphinxext/prs/9719.json new file mode 100644 index 0000000000000000000000000000000000000000..e22ed81415e0cbff9b7d10b70c1a8257cf3b4ca5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9719.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "db0219e5f6e083f7e377beb5301d725d03ec3526", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/cov.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 34, + "d": 60 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 26, + "d": 13 + }, + "mne/rank.py": { + "a": 5, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 19, + "d": 0 + }, + "mne/tests/test_rank.py": { + "a": 39, + "d": 0 + }, + "mne/viz/tests/test_ica.py": { + "a": 12, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9721.json b/mne-python/source/doc/sphinxext/prs/9721.json new file mode 100644 index 0000000000000000000000000000000000000000..deb48041e737cb7f706d1d816edd2d6706454872 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9721.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ff3ba8629496bed2fc5b34e77abac48f930abe1c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 9, + "d": 0 + }, + "tutorials/inverse/40_mne_fixed_free.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9723.json b/mne-python/source/doc/sphinxext/prs/9723.json new file mode 100644 index 0000000000000000000000000000000000000000..0d33a66c83251d4356fbbb43a0d7a1e3b8a89183 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9723.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f20ffa0eb46e76baf4e30437bc03d765da83b38a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/funding.rst": { + "a": 2, + "d": 2 + }, + "doc/links.inc": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9724.json b/mne-python/source/doc/sphinxext/prs/9724.json new file mode 100644 index 0000000000000000000000000000000000000000..27097abf016236526dd0cae103b4441b812f9f24 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9724.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9a9782c46a1c09991941d1392ffa3d8b493e7b93", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 0 + }, + "doc/funding.rst": { + "a": 28, + "d": 8 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9725.json b/mne-python/source/doc/sphinxext/prs/9725.json new file mode 100644 index 0000000000000000000000000000000000000000..ca8fae597b01701963b4b14dbccc592b114c8e0a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9725.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "e43136c22014cde2a0567f9e332faacb75f876dd", + "authors": [ + { + "n": "Valerii", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/data/html_templates.py": { + "a": 2, + "d": 5 + }, + "mne/defaults.py": { + "a": 3, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 44, + "d": 19 + }, + "mne/io/tests/test_meas_info.py": { + "a": 10, + "d": 0 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9728.json b/mne-python/source/doc/sphinxext/prs/9728.json new file mode 100644 index 0000000000000000000000000000000000000000..19b43c0aaada9a868b2300991533990003caf332 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9728.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "4327725e18a87e6fa3c75c637fa9297d053d95ed", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9729.json b/mne-python/source/doc/sphinxext/prs/9729.json new file mode 100644 index 0000000000000000000000000000000000000000..6401092cc9f4b3270caecf6d896934c0eb221112 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9729.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "2adf9a63218e932399710618a095305ae0bd5d0d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9731.json b/mne-python/source/doc/sphinxext/prs/9731.json new file mode 100644 index 0000000000000000000000000000000000000000..4a47347757dd4613aa1868160eb0d08d09bc22d3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9731.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b527dc6683165d1e5982036d6144010fd710860f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_cov.py": { + "a": 4, + "d": 2 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 4 + }, + "tools/github_actions_dependencies.sh": { + "a": 3, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9732.json b/mne-python/source/doc/sphinxext/prs/9732.json new file mode 100644 index 0000000000000000000000000000000000000000..9e5afe8d6386e3b609753ecaf51492909426d5f5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9732.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "82487bc6a8976b0fa55ab9c7a2d8af56fd8b7ae3", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/utils/_logging.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9735.json b/mne-python/source/doc/sphinxext/prs/9735.json new file mode 100644 index 0000000000000000000000000000000000000000..3779adc496aee69b901228365a4c86546e5d3116 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9735.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a000c574a1a3aec40cffff6a0a8ad6499625fa5f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/_logging.py": { + "a": 10, + "d": 4 + }, + "mne/utils/tests/test_logging.py": { + "a": 22, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9739.json b/mne-python/source/doc/sphinxext/prs/9739.json new file mode 100644 index 0000000000000000000000000000000000000000..47f7ac5223a89ce570cd5f25072be2c56facf779 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9739.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e4ed2a607c9090f153da7c1558cb56edb975c1a7", + "authors": [ + { + "n": "Steve Matindi", + "e": null + } + ], + "changes": { + "LICENSE.txt": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9741.json b/mne-python/source/doc/sphinxext/prs/9741.json new file mode 100644 index 0000000000000000000000000000000000000000..43d69f4f8b69ea8e20c14d73a56e2a3de9748e11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9741.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "41033b0edd7d770625006b908c5131307fef9fa8", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 9, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 54, + "d": 23 + }, + "tutorials/clinical/30_ecog.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9742.json b/mne-python/source/doc/sphinxext/prs/9742.json new file mode 100644 index 0000000000000000000000000000000000000000..b6456e8efe90df1220053bc1580dbc9f5a85860d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9742.json @@ -0,0 +1,155 @@ +{ + "merge_commit_sha": "c42a7b7a6dee8a48239c293c32d21d88040b9adf", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "MANIFEST.in": { + "a": 2, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 2, + "d": 1 + }, + "mne/data/dataset_checksums.txt": { + "a": 46, + "d": 0 + }, + "mne/data/eegbci_checksums.txt": { + "a": 3058, + "d": 0 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 4, + "d": 6 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 4, + "d": 5 + }, + "mne/datasets/config.py": { + "a": 217, + "d": 0 + }, + "mne/datasets/eegbci/eegbci.py": { + "a": 55, + "d": 8 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 19, + "d": 54 + }, + "mne/datasets/limo/limo.py": { + "a": 116, + "d": 68 + }, + "mne/datasets/sleep_physionet/_utils.py": { + "a": 34, + "d": 13 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 14, + "d": 11 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 23, + "d": 17 + }, + "mne/datasets/utils.py": { + "a": 238, + "d": 419 + }, + "mne/export/_edf.py": { + "a": 6, + "d": 0 + }, + "mne/export/tests/test_export.py": { + "a": 3, + "d": 8 + }, + "mne/io/tests/test_constants.py": { + "a": 14, + "d": 4 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 4, + "d": 4 + }, + "mne/utils/check.py": { + "a": 23, + "d": 36 + }, + "mne/utils/fetching.py": { + "a": 0, + "d": 127 + }, + "mne/utils/misc.py": { + "a": 24, + "d": 0 + }, + "mne/utils/tests/test_fetching.py": { + "a": 0, + "d": 44 + }, + "requirements.txt": { + "a": 1, + "d": 0 + }, + "requirements_testing.txt": { + "a": 1, + "d": 0 + }, + "server_environment.yml": { + "a": 1, + "d": 0 + }, + "setup.py": { + "a": 2, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 0 + }, + "tools/get_testing_version.sh": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9743.json b/mne-python/source/doc/sphinxext/prs/9743.json new file mode 100644 index 0000000000000000000000000000000000000000..f10148f30eba9f537e5d39622a5880cf5a17e943 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9743.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "533f5895e8686a41285ad2f15289e23ff6762df2", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/io/bti/bti.py": { + "a": 16, + "d": 13 + }, + "mne/io/edf/edf.py": { + "a": 9, + "d": 15 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 0 + }, + "tools/circleci_download.sh": { + "a": 1, + "d": 1 + }, + "tutorials/clinical/60_sleep.py": { + "a": 6, + "d": 12 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9746.json b/mne-python/source/doc/sphinxext/prs/9746.json new file mode 100644 index 0000000000000000000000000000000000000000..1f347fe626f3d43c7a4464c42280b611c3adccf2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9746.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a0faac5bbf5d43f5b264444fd7138ea10af1fd13", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/persyst/persyst.py": { + "a": 5, + "d": 2 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9749.json b/mne-python/source/doc/sphinxext/prs/9749.json new file mode 100644 index 0000000000000000000000000000000000000000..d5720aae4248b98c15712df25fe5cc56b2689e6d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9749.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "c74cc7180b25f20b4b99d0144cbb6ef99c597e8a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 2, + "d": 0 + }, + "mne/report/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 24, + "d": 24 + }, + "mne/report/tests/test_report.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9750.json b/mne-python/source/doc/sphinxext/prs/9750.json new file mode 100644 index 0000000000000000000000000000000000000000..cb93552aefcde337acf1a580481235bc65a68c2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9750.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "aea40ff54c976a1166b573da5ec3a6188ba7b725", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/visualization/eeg_on_scalp.py": { + "a": 9, + "d": 0 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/utils/check.py": { + "a": 12, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 13, + "d": 14 + }, + "mne/viz/_brain/_brain.py": { + "a": 116, + "d": 111 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 6, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 4, + "d": 5 + }, + "mne/viz/tests/test_3d.py": { + "a": 17, + "d": 7 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 7 + }, + "mne/viz/utils.py": { + "a": 5, + "d": 5 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9751.json b/mne-python/source/doc/sphinxext/prs/9751.json new file mode 100644 index 0000000000000000000000000000000000000000..ed67c79fd4a87b47840ae65dda6e625da094fe50 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9751.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3aeee826450c823464282657a38c6751d9cdc5a2", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9754.json b/mne-python/source/doc/sphinxext/prs/9754.json new file mode 100644 index 0000000000000000000000000000000000000000..7a3e145edb9e14e1e2e4bd0c339a7bc8ad40ccb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9754.json @@ -0,0 +1,299 @@ +{ + "merge_commit_sha": "6763cac6b4b3d379a9e5319dd3575f1f124c0060", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Adam Li", + "e": "adam2392@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Clemens Brunner", + "e": "clemens.brunner@gmail.com" + }, + { + "n": "Valerii", + "e": "42982039+vagechirkov@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 26, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 7, + "d": 3 + }, + "mne/data/html_templates.py": { + "a": 40, + "d": 2 + }, + "mne/defaults.py": { + "a": 10, + "d": 0 + }, + "mne/evoked.py": { + "a": 1, + "d": 0 + }, + "mne/fixes.py": { + "a": 35, + "d": 3 + }, + "mne/forward/forward.py": { + "a": 36, + "d": 20 + }, + "mne/html/bootstrap.min.css": { + "a": 0, + "d": 7 + }, + "mne/html/bootstrap.min.js": { + "a": 0, + "d": 7 + }, + "mne/html/jquery-ui.min.css": { + "a": 0, + "d": 6 + }, + "mne/html/jquery-ui.min.js": { + "a": 0, + "d": 12 + }, + "mne/html/jquery.js": { + "a": 0, + "d": 6 + }, + "mne/icons/mne_icon-cropped.png": { + "a": 0, + "d": 0 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 0, + "d": 16 + }, + "mne/io/meas_info.py": { + "a": 12, + "d": 6 + }, + "mne/minimum_norm/inverse.py": { + "a": 33, + "d": 14 + }, + "mne/report/js_and_css/bootstrap.bundle.min.js": { + "a": 7, + "d": 0 + }, + "mne/report/js_and_css/bootstrap.min.css": { + "a": 7, + "d": 0 + }, + "mne/report/js_and_css/highlightjs/atom-one-dark-reasonable.min.css": { + "a": 1, + "d": 0 + }, + "mne/report/js_and_css/highlightjs/atom-one-light.min.css": { + "a": 1, + "d": 0 + }, + "mne/report/js_and_css/highlightjs/default.min.css": { + "a": 9, + "d": 0 + }, + "mne/report/js_and_css/highlightjs/highlight.min.js": { + "a": 1282, + "d": 0 + }, + "mne/report/js_and_css/jquery-3.6.0.min.js": { + "a": 2, + "d": 0 + }, + "mne/report/js_and_css/report.js": { + "a": 224, + "d": 0 + }, + "mne/report/js_and_css/report.sass": { + "a": 19, + "d": 0 + }, + "mne/report/report.py": { + "a": 2448, + "d": 1401 + }, + "mne/report/templates/code.html": { + "a": 24, + "d": 0 + }, + "mne/report/templates/cov.html": { + "a": 23, + "d": 0 + }, + "mne/report/templates/epochs.html": { + "a": 25, + "d": 0 + }, + "mne/report/templates/evoked.html": { + "a": 26, + "d": 0 + }, + "mne/report/templates/footer.html": { + "a": 10, + "d": 0 + }, + "mne/report/templates/forward.html": { + "a": 23, + "d": 0 + }, + "mne/report/templates/header.html": { + "a": 56, + "d": 0 + }, + "mne/report/templates/html.html": { + "a": 23, + "d": 0 + }, + "mne/report/templates/image.html": { + "a": 36, + "d": 0 + }, + "mne/report/templates/inverse.html": { + "a": 23, + "d": 0 + }, + "mne/report/templates/raw.html": { + "a": 25, + "d": 0 + }, + "mne/report/templates/slider.html": { + "a": 60, + "d": 0 + }, + "mne/report/templates/toc.html": { + "a": 12, + "d": 0 + }, + "mne/report/tests/test_report.py": { + "a": 318, + "d": 170 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 3, + "d": 5 + }, + "mne/utils/docs.py": { + "a": 69, + "d": 52 + }, + "mne/viz/_3d.py": { + "a": 10, + "d": 19 + }, + "mne/viz/backends/renderer.py": { + "a": 9, + "d": 3 + }, + "mne/viz/evoked.py": { + "a": 9, + "d": 1 + }, + "mne/viz/misc.py": { + "a": 89, + "d": 48 + }, + "mne/viz/tests/test_topo.py": { + "a": 1, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "mne/viz/utils.py": { + "a": 6, + "d": 3 + }, + "tutorials/intro/70_report.py": { + "a": 441, + "d": 207 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9758.json b/mne-python/source/doc/sphinxext/prs/9758.json new file mode 100644 index 0000000000000000000000000000000000000000..ec0d5a35a2edaee833294d07555f18ac0aa7d028 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9758.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "034ff3f03ae1ae01a6fe52e3e91e10682c977aff", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 9, + "d": 8 + }, + "mne/tests/test_epochs.py": { + "a": 17, + "d": 7 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9760.json b/mne-python/source/doc/sphinxext/prs/9760.json new file mode 100644 index 0000000000000000000000000000000000000000..9493fcbe3dfe1a64907150eba30cd26e549a73c3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9760.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "05382cf02d49a5f8fbaf6030979e9ebb9d126608", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/export/_edf.py": { + "a": 142, + "d": 134 + }, + "tools/azure_dependencies.sh": { + "a": 0, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9762.json b/mne-python/source/doc/sphinxext/prs/9762.json new file mode 100644 index 0000000000000000000000000000000000000000..6a26e89aaab99f97cee4f867b4773bb94ea2c81c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9762.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9627d0965ced345fc5339caeb828e4180afacaa6", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/data/dataset_checksums.txt": { + "a": 0, + "d": 46 + }, + "mne/datasets/config.py": { + "a": 267, + "d": 120 + }, + "mne/datasets/testing/_testing.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 63, + "d": 38 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9763.json b/mne-python/source/doc/sphinxext/prs/9763.json new file mode 100644 index 0000000000000000000000000000000000000000..7952c9cc486a62b033aa81e4d0b04c0d30c7c316 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9763.json @@ -0,0 +1,167 @@ +{ + "merge_commit_sha": "0b503d8b64bd1383eee0450c3998700ad354a1ef", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "doc/datasets.rst": { + "a": 2, + "d": 1 + }, + "examples/visualization/3d_to_2d.py": { + "a": 15, + "d": 7 + }, + "mne/datasets/__init__.py": { + "a": 3, + "d": 1 + }, + "mne/datasets/_fake/_fake.py": { + "a": 5, + "d": 4 + }, + "mne/datasets/_fetch.py": { + "a": 292, + "d": 0 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 7, + "d": 6 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/config.py": { + "a": 5, + "d": 4 + }, + "mne/datasets/epilepsy_ecog/_data.py": { + "a": 6, + "d": 5 + }, + "mne/datasets/erp_core/erp_core.py": { + "a": 6, + "d": 5 + }, + "mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/fnirs_motor/fnirs_motor.py": { + "a": 6, + "d": 5 + }, + "mne/datasets/hf_sef/hf_sef.py": { + "a": 24, + "d": 10 + }, + "mne/datasets/kiloword/kiloword.py": { + "a": 5, + "d": 4 + }, + "mne/datasets/misc/_misc.py": { + "a": 5, + "d": 4 + }, + "mne/datasets/mtrf/mtrf.py": { + "a": 6, + "d": 5 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 6, + "d": 5 + }, + "mne/datasets/opm/opm.py": { + "a": 6, + "d": 5 + }, + "mne/datasets/phantom_4dbti/phantom_4dbti.py": { + "a": 6, + "d": 5 + }, + "mne/datasets/refmeg_noise/refmeg_noise.py": { + "a": 7, + "d": 6 + }, + "mne/datasets/sample/sample.py": { + "a": 7, + "d": 5 + }, + "mne/datasets/somato/somato.py": { + "a": 7, + "d": 5 + }, + "mne/datasets/spm_face/spm_data.py": { + "a": 7, + "d": 5 + }, + "mne/datasets/ssvep/ssvep.py": { + "a": 8, + "d": 5 + }, + "mne/datasets/testing/_testing.py": { + "a": 7, + "d": 5 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 49, + "d": 235 + }, + "mne/datasets/visual_92_categories/visual_92_categories.py": { + "a": 6, + "d": 4 + }, + "mne/export/tests/test_export.py": { + "a": 2, + "d": 4 + }, + "setup.py": { + "a": 0, + "d": 1 + }, + "tutorials/clinical/20_seeg.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9764.json b/mne-python/source/doc/sphinxext/prs/9764.json new file mode 100644 index 0000000000000000000000000000000000000000..1d048f75b8a1409b9e993fd1633444614139628b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9764.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6c0006dfc73588927936b95a1ae364556a55fbc0", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 32, + "d": 72 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9766.json b/mne-python/source/doc/sphinxext/prs/9766.json new file mode 100644 index 0000000000000000000000000000000000000000..0c51d05ccc8d1dd2e51cd154ed401a39f661236d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9766.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "45b257d96a352310b00f1478b7053b46bb57e0b7", + "authors": [ + { + "n": "Jan Sosulski", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 10, + "d": 9 + }, + "mne/tests/test_epochs.py": { + "a": 8, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/977.json b/mne-python/source/doc/sphinxext/prs/977.json new file mode 100644 index 0000000000000000000000000000000000000000..bd3dc68ecc5968332309ce007f3bf571ec0b225e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/977.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "2ff835f644f3fc751f84398e1758da06ea631fb8", + "authors": [ + { + "n": "Martin Luessi", + "e": null + } + ], + "changes": { + "doc/Makefile": { + "a": 12, + "d": 1 + }, + "doc/source/_templates/layout.html": { + "a": 6, + "d": 3 + }, + "doc/source/_templates/sidebar.html": { + "a": 5, + "d": 0 + }, + "doc/source/conf.py": { + "a": 5, + "d": 2 + }, + "doc/sphinxext/gen_rst.py": { + "a": 14, + "d": 10 + }, + "doc/upload_html.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9770.json b/mne-python/source/doc/sphinxext/prs/9770.json new file mode 100644 index 0000000000000000000000000000000000000000..2060439de4f31476f04b8370bda1f80474ce2156 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9770.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "59560dfe179ffbb30d79ad88898121043539a2c1", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/gui/_ieeg_locate_gui.py": { + "a": 5, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9771.json b/mne-python/source/doc/sphinxext/prs/9771.json new file mode 100644 index 0000000000000000000000000000000000000000..393b31f7b5cfa4183ffc5d634628890a924d3ed8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9771.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "f967b3dd4fb6f3db1af09cf1a708774acde24a0d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/data/html_templates.py": { + "a": 1, + "d": 1 + }, + "mne/defaults.py": { + "a": 8, + "d": 5 + }, + "mne/tests/test_defaults.py": { + "a": 16, + "d": 0 + }, + "mne/viz/tests/test_raw.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9772.json b/mne-python/source/doc/sphinxext/prs/9772.json new file mode 100644 index 0000000000000000000000000000000000000000..872ab365c9407cbe9fc5e3c031464ac4c5c3fb18 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9772.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "52c7007b461181a15720438d46eaffc81385f0cc", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 45, + "d": 9 + }, + "doc/conf.py": { + "a": 13, + "d": 3 + }, + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + }, + "mne/tests/test_cov.py": { + "a": 1, + "d": 1 + }, + "requirements_doc.txt": { + "a": 1, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9777.json b/mne-python/source/doc/sphinxext/prs/9777.json new file mode 100644 index 0000000000000000000000000000000000000000..20826e8e1b89c10dda789f23789f1e1375c103bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9777.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "a39a0e8caa340ff22eba7441bec2399c93fa496d", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9780.json b/mne-python/source/doc/sphinxext/prs/9780.json new file mode 100644 index 0000000000000000000000000000000000000000..b687454517ee1f5877412cb6310cff1e0a685513 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9780.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "9c7e837f59e480fff1b6ea5841630e089aa5a235", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/annotations.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 7, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9781.json b/mne-python/source/doc/sphinxext/prs/9781.json new file mode 100644 index 0000000000000000000000000000000000000000..f1a3563cd77418b6ff752eaf21e1002b8623ce59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9781.json @@ -0,0 +1,115 @@ +{ + "merge_commit_sha": "040a40509ec600e83d572d6bc03a209a05a72a07", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/datasets.rst": { + "a": 1, + "d": 0 + }, + "mne/datasets/__init__.py": { + "a": 2, + "d": 2 + }, + "mne/datasets/_fetch.py": { + "a": 44, + "d": 42 + }, + "mne/datasets/brainstorm/bst_auditory.py": { + "a": 2, + "d": 7 + }, + "mne/datasets/brainstorm/bst_phantom_ctf.py": { + "a": 2, + "d": 7 + }, + "mne/datasets/brainstorm/bst_phantom_elekta.py": { + "a": 1, + "d": 7 + }, + "mne/datasets/brainstorm/bst_raw.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/brainstorm/bst_resting.py": { + "a": 2, + "d": 6 + }, + "mne/datasets/epilepsy_ecog/_data.py": { + "a": 11, + "d": 5 + }, + "mne/datasets/erp_core/erp_core.py": { + "a": 1, + "d": 5 + }, + "mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py": { + "a": 5, + "d": 12 + }, + "mne/datasets/fnirs_motor/fnirs_motor.py": { + "a": 10, + "d": 5 + }, + "mne/datasets/mtrf/mtrf.py": { + "a": 2, + "d": 5 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 9, + "d": 5 + }, + "mne/datasets/opm/opm.py": { + "a": 9, + "d": 5 + }, + "mne/datasets/phantom_4dbti/phantom_4dbti.py": { + "a": 10, + "d": 5 + }, + "mne/datasets/refmeg_noise/refmeg_noise.py": { + "a": 12, + "d": 7 + }, + "mne/datasets/sample/sample.py": { + "a": 9, + "d": 5 + }, + "mne/datasets/somato/somato.py": { + "a": 9, + "d": 5 + }, + "mne/datasets/ssvep/ssvep.py": { + "a": 10, + "d": 6 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 8, + "d": 8 + }, + "mne/datasets/utils.py": { + "a": 31, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9782.json b/mne-python/source/doc/sphinxext/prs/9782.json new file mode 100644 index 0000000000000000000000000000000000000000..cc9336a3a241e50721d07e0d30c09ec1fdee8269 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9782.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "c74e60a00825bbe3bbb977369df53b1f2287b00f", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/epochs.py": { + "a": 7, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 4, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9784.json b/mne-python/source/doc/sphinxext/prs/9784.json new file mode 100644 index 0000000000000000000000000000000000000000..93b350ee426b9c9af7d206aacdab53def0c9d713 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9784.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "08a02e3ce7af03604cde74b2d2b4352f00ab879d", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 5, + "d": 2 + }, + "doc/overview/datasets_index.rst": { + "a": 18, + "d": 9 + }, + "examples/visualization/3d_to_2d.py": { + "a": 25, + "d": 39 + }, + "mne/data/image/custom_layout.lout": { + "a": 257, + "d": 65 + }, + "mne/gui/__init__.py": { + "a": 40, + "d": 0 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 30, + "d": 1 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 26, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9789.json b/mne-python/source/doc/sphinxext/prs/9789.json new file mode 100644 index 0000000000000000000000000000000000000000..995a65d6f7d69a939f9e98507e8c0cd963aca3bf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9789.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "51a1ea3f370bcdadd2306bfd27ac4f2b5d6e4a7f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 3, + "d": 3 + }, + "azure-pipelines.yml": { + "a": 26, + "d": 28 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 8, + "d": 0 + }, + "doc/install/contributing.rst": { + "a": 2, + "d": 3 + }, + "doc/install/index.rst": { + "a": 1, + "d": 1 + }, + "doc/links.inc": { + "a": 4, + "d": 4 + }, + "doc/references.bib": { + "a": 2, + "d": 4 + }, + "mne/commands/mne_sys_info.py": { + "a": 7, + "d": 1 + }, + "mne/conftest.py": { + "a": 4, + "d": 1 + }, + "mne/utils/config.py": { + "a": 20, + "d": 6 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 3 + }, + "tools/github_actions_infos.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9794.json b/mne-python/source/doc/sphinxext/prs/9794.json new file mode 100644 index 0000000000000000000000000000000000000000..881bf155cb547da8160bcecf4678e11ceea9fcb0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9794.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "d973a1fa714534eab6e553f8073ceb9abce35fae", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/time_frequency/tests/test_tfr.py": { + "a": 72, + "d": 1 + }, + "mne/time_frequency/tfr.py": { + "a": 46, + "d": 12 + }, + "mne/utils/check.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9795.json b/mne-python/source/doc/sphinxext/prs/9795.json new file mode 100644 index 0000000000000000000000000000000000000000..f35481fbf3614dddc798a790d253885f2d4fdf97 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9795.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "66ac824c7f2a04baccd33699f69a5f2443768184", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/brainvision/brainvision.py": { + "a": 22, + "d": 2 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 10, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9796.json b/mne-python/source/doc/sphinxext/prs/9796.json new file mode 100644 index 0000000000000000000000000000000000000000..5e0c7f6a00cc2d56ce2ec435789eddf81d8face8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9796.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "fb98000c6b9998b3a05ab3d887d0e65c4d3d72a0", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "MANIFEST.in": { + "a": 1, + "d": 0 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/datasets.rst": { + "a": 2, + "d": 1 + }, + "mne/datasets/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/datasets/_phantom/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/datasets/_phantom/base.py": { + "a": 62, + "d": 0 + }, + "mne/datasets/_phantom/phantom_otaniemi.txt": { + "a": 3, + "d": 0 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 33, + "d": 6 + }, + "mne/dipole.py": { + "a": 4, + "d": 0 + }, + "setup.py": { + "a": 1, + "d": 0 + }, + "tutorials/inverse/80_brainstorm_phantom_elekta.py": { + "a": 21, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9799.json b/mne-python/source/doc/sphinxext/prs/9799.json new file mode 100644 index 0000000000000000000000000000000000000000..82fe346aa554821b9597ce864943a09b4215c1a4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9799.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "4f37eb6f895728cdf8e4ebf320427136bba76896", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/utils.py": { + "a": 4, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/980.json b/mne-python/source/doc/sphinxext/prs/980.json new file mode 100644 index 0000000000000000000000000000000000000000..7fc548941500958c7f519b1d206a6d086efbed72 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/980.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c493a447f7415b961bf187db8615dc77bc00ffbf", + "authors": [ + { + "n": "Brad Buran", + "e": null + } + ], + "changes": { + "mne/utils.py": { + "a": 11, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9800.json b/mne-python/source/doc/sphinxext/prs/9800.json new file mode 100644 index 0000000000000000000000000000000000000000..ba512b183cd609b6710ed1704e3eb56f94d9c7d8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9800.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "6bb3eb742b880a520431e10bfb5b113872ff67a0", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 13, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/ieeg/__init__.py": { + "a": 7, + "d": 0 + }, + "mne/preprocessing/ieeg/_projection.py": { + "a": 104, + "d": 0 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 68, + "d": 0 + }, + "mne/preprocessing/nirs/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 31, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9801.json b/mne-python/source/doc/sphinxext/prs/9801.json new file mode 100644 index 0000000000000000000000000000000000000000..000aa6687e9bfe5244f8533de0ac6deb48318a5f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9801.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "8863c1bed699d0ca428a6840101fd44730173347", + "authors": [ + { + "n": "Joshua Teves", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/utils/config.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9802.json b/mne-python/source/doc/sphinxext/prs/9802.json new file mode 100644 index 0000000000000000000000000000000000000000..655ca2e802bcbc3b6c80abc3ee482c74e5378e91 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9802.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "32f4ee82bf6178c287539f72323ab470ef711cb4", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/datasets/_fetch.py": { + "a": 26, + "d": 35 + }, + "mne/datasets/config.py": { + "a": 11, + "d": 13 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 16, + "d": 2 + }, + "mne/datasets/utils.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9803.json b/mne-python/source/doc/sphinxext/prs/9803.json new file mode 100644 index 0000000000000000000000000000000000000000..27637760eb17f94aa1fff374337ff144effcf0f9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9803.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "ccc8f5cd09fd5fd7c766c10cf12b30853d1884e9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "mne/utils/_testing.py": { + "a": 8, + "d": 5 + }, + "mne/viz/evoked.py": { + "a": 1, + "d": 0 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 2 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9804.json b/mne-python/source/doc/sphinxext/prs/9804.json new file mode 100644 index 0000000000000000000000000000000000000000..a5f2c0337b759f3137a53a9ebf50d53a4a292e94 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9804.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "3c84129576713d74e1fd889c2691240909e44161", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 4, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 35, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 12, + "d": 3 + }, + "mne/viz/tests/test_3d.py": { + "a": 13, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9805.json b/mne-python/source/doc/sphinxext/prs/9805.json new file mode 100644 index 0000000000000000000000000000000000000000..81f04d12364c070d1b3179f7f349deae137aa91d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9805.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "61608aa4038a888d1c1f7c9dd5bb1a02203719de", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "requirements_testing_extra.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9807.json b/mne-python/source/doc/sphinxext/prs/9807.json new file mode 100644 index 0000000000000000000000000000000000000000..cd2440d99583bd5ab9debe805fd606e5accf200c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9807.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "aabdefdc97c035f8d269b6acdc4065a4ee21786c", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/datasets/_fetch.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9808.json b/mne-python/source/doc/sphinxext/prs/9808.json new file mode 100644 index 0000000000000000000000000000000000000000..27274564fd0741c9e17eb9e05339daf3158f9cc7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9808.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "2e3aca50802415686a4223c711f8f1d535d407c9", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/nirx/nirx.py": { + "a": 8, + "d": 5 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 15, + "d": 4 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 18, + "d": 4 + }, + "mne/io/tests/test_raw.py": { + "a": 9, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/981.json b/mne-python/source/doc/sphinxext/prs/981.json new file mode 100644 index 0000000000000000000000000000000000000000..2b4f3a3b9991630f256afaef2b1f7d0e3bcc8477 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/981.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "3ce0cdea0bfd52d90fb71435c802c8b082b0ae43", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/fiff/kit/coreg.py": { + "a": 1, + "d": 1 + }, + "mne/fiff/kit/kit.py": { + "a": 2, + "d": 2 + }, + "mne/source_estimate.py": { + "a": 14, + "d": 17 + }, + "mne/surface.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9810.json b/mne-python/source/doc/sphinxext/prs/9810.json new file mode 100644 index 0000000000000000000000000000000000000000..bf7c6abef98145de75fba7080e4b246210f8842c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9810.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "8cb783813a6691fa9b55d12aa8c90690228868e9", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/dipole.py": { + "a": 24, + "d": 12 + }, + "mne/evoked.py": { + "a": 1, + "d": 1 + }, + "mne/forward/_make_forward.py": { + "a": 3, + "d": 5 + }, + "mne/preprocessing/maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_dipole.py": { + "a": 8, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9814.json b/mne-python/source/doc/sphinxext/prs/9814.json new file mode 100644 index 0000000000000000000000000000000000000000..54bc289ce25d90a84a31c01499f447a823d11c42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9814.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "dd5ca5b7c5a66c5a6afc31089e0bbb58e9e1f2c5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 6, + "d": 5 + }, + "mne/report/report.py": { + "a": 18, + "d": 23 + }, + "mne/utils/misc.py": { + "a": 6, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 2, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 15 + }, + "tutorials/io/10_reading_meg_data.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9815.json b/mne-python/source/doc/sphinxext/prs/9815.json new file mode 100644 index 0000000000000000000000000000000000000000..53b620570415b0a3f8f44b1430487597d0d6ae65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9815.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "48a33e376843b7ecc0279805b0b9e24c996ba972", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/epochs.py": { + "a": 3, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 0 + }, + "mne/viz/epochs.py": { + "a": 6, + "d": 2 + }, + "mne/viz/raw.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9817.json b/mne-python/source/doc/sphinxext/prs/9817.json new file mode 100644 index 0000000000000000000000000000000000000000..4e9308c4607b437224d2c3e25a717244532e0203 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9817.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cfd743aa33350c94a9b41dd51e72f53977939de6", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/io/snirf/_snirf.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9818.json b/mne-python/source/doc/sphinxext/prs/9818.json new file mode 100644 index 0000000000000000000000000000000000000000..9bb2c04c87238ffaeb09632e784c2eff28c00b65 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9818.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f3f0e086b4fbc18ebd3018770e0650604d70b9c5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/report/report.py": { + "a": 13, + "d": 8 + }, + "mne/viz/misc.py": { + "a": 44, + "d": 28 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9820.json b/mne-python/source/doc/sphinxext/prs/9820.json new file mode 100644 index 0000000000000000000000000000000000000000..b9753ef1da02c1f9bab93c7f28a1283ae7634cb7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9820.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "194ba0f8a849dbe16c66c3425e919b9a9f9f59eb", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/utils/docs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/ica.py": { + "a": 14, + "d": 15 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9822.json b/mne-python/source/doc/sphinxext/prs/9822.json new file mode 100644 index 0000000000000000000000000000000000000000..de7bb2b8697aa0953425b579381d89908a002cbf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9822.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7154c6d16389c38447f16534847f7ae7503d42fc", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 0 + }, + "requirements_testing_extra.txt": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9823.json b/mne-python/source/doc/sphinxext/prs/9823.json new file mode 100644 index 0000000000000000000000000000000000000000..8005def2c8fae39af9f099ad5876b1b66ab5d229 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9823.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "42c5a72d1f7e1981fb60fa98a75fddf46418ca0d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 3, + "d": 1 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9824.json b/mne-python/source/doc/sphinxext/prs/9824.json new file mode 100644 index 0000000000000000000000000000000000000000..bf56a462c40293f53433e03a14a783f2f2c34428 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9824.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "118f37901e348aaed3972085b9c20a4f06241e5d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 21, + "d": 7 + }, + "mne/viz/tests/test_ica.py": { + "a": 9, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9825.json b/mne-python/source/doc/sphinxext/prs/9825.json new file mode 100644 index 0000000000000000000000000000000000000000..d71569ab0bbabe9caca5ff3eca5cfdcca6f78c3c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9825.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "832b71dca7148bf68e6891cf9d6c308f1bc3fabc", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/ica.py": { + "a": 8, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9826.json b/mne-python/source/doc/sphinxext/prs/9826.json new file mode 100644 index 0000000000000000000000000000000000000000..db719b568eb7ff9f3b95c389f4cc9d80cc89444a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9826.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "adca0e6c4b25ad84406301c204d48a413fa657e1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/topomap.py": { + "a": 10, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9827.json b/mne-python/source/doc/sphinxext/prs/9827.json new file mode 100644 index 0000000000000000000000000000000000000000..6ae5b8056c1fb3b0e592f9a71175fe7e4e88b332 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9827.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "11864803848d08ce2abf1d379f4a6b0f03e133ee", + "authors": [ + { + "n": "Dominique Makowski", + "e": "D.Makowski@sussex.ac.uk" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 17, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9828.json b/mne-python/source/doc/sphinxext/prs/9828.json new file mode 100644 index 0000000000000000000000000000000000000000..66b092c4288a540549f1a7cde5c8fd53c2af30c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9828.json @@ -0,0 +1,71 @@ +{ + "merge_commit_sha": "1b0f8280f9b3a93b58daacffd85598b63511e5b1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/data/html_templates.py": { + "a": 35, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 92, + "d": 15 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 11, + "d": 0 + }, + "mne/report/report.py": { + "a": 370, + "d": 9 + }, + "mne/report/templates/ica.html": { + "a": 29, + "d": 0 + }, + "mne/report/tests/test_report.py": { + "a": 26, + "d": 3 + }, + "mne/viz/ica.py": { + "a": 3, + "d": 0 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 3, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 72, + "d": 0 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9829.json b/mne-python/source/doc/sphinxext/prs/9829.json new file mode 100644 index 0000000000000000000000000000000000000000..af8323a611cdfc991ef671c1bb3ec428af8b159e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9829.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4f74ee2a96c618b506afeda3c09e0bf578cc607a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 1, + "d": 1 + }, + "environment.yml": { + "a": 1, + "d": 0 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/report/report.py": { + "a": 14, + "d": 19 + }, + "mne/viz/topomap.py": { + "a": 2, + "d": 3 + }, + "requirements.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9831.json b/mne-python/source/doc/sphinxext/prs/9831.json new file mode 100644 index 0000000000000000000000000000000000000000..15d5862a26ed20bd9787c82109d36bf30bcba203 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9831.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e285e91bb33c9b5855e09563ed8cb2e7a2b997ab", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/datasets/config.py": { + "a": 20, + "d": 18 + }, + "mne/io/edf/edf.py": { + "a": 8, + "d": 3 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 28, + "d": 8 + }, + "mne/tests/test_annotations.py": { + "a": 15, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9834.json b/mne-python/source/doc/sphinxext/prs/9834.json new file mode 100644 index 0000000000000000000000000000000000000000..261e99fbae0ff1719dc0df77ec51fd998f439b20 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9834.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "22728cee967bdf8bdfb69002d92df49bd9de3948", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/minimum_norm/tests/test_inverse.py": { + "a": 4, + "d": 3 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 3 + }, + "mne/viz/backends/_pyvista.py": { + "a": 17, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9835.json b/mne-python/source/doc/sphinxext/prs/9835.json new file mode 100644 index 0000000000000000000000000000000000000000..7f1f39aa8e347895d2a80dffa0a470f8830752c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9835.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "9a474f51fffe4e5da4179cedcd649dcf2b86d351", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 4, + "d": 5 + }, + "doc/install/index.rst": { + "a": 23, + "d": 8 + }, + "doc/install/mne_python.rst": { + "a": 4, + "d": 2 + }, + "doc/links.inc": { + "a": 2, + "d": 42 + }, + "requirements.txt": { + "a": 1, + "d": 1 + }, + "setup.py": { + "a": 30, + "d": 9 + }, + "tools/azure_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9837.json b/mne-python/source/doc/sphinxext/prs/9837.json new file mode 100644 index 0000000000000000000000000000000000000000..e7cbbcc312fde9d4e1ccb6beca982055e22a817b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9837.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a04b6e518ce20ec0835f8813d5b7155b6bd7e5d5", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9839.json b/mne-python/source/doc/sphinxext/prs/9839.json new file mode 100644 index 0000000000000000000000000000000000000000..52521740f53cda652fe35846e4de1a5e5bbd1ba2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9839.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "718a14901f81de8a0261e1f7e2529378cce783c1", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/viz/backends/renderer.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/984.json b/mne-python/source/doc/sphinxext/prs/984.json new file mode 100644 index 0000000000000000000000000000000000000000..a5a6b70647b6cb4853975e3ccae7c0e84894d094 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/984.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "dc9bfe6970f6b0bd9ff3c8bcbe4147c56b13201b", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/inverse/plot_compute_mne_inverse.py": { + "a": 9, + "d": 1 + }, + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 10, + "d": 0 + }, + "mne/fiff/evoked.py": { + "a": 146, + "d": 0 + }, + "mne/fiff/tests/test_evoked.py": { + "a": 45, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 74, + "d": 0 + }, + "mne/tests/test_source_estimate.py": { + "a": 28, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9840.json b/mne-python/source/doc/sphinxext/prs/9840.json new file mode 100644 index 0000000000000000000000000000000000000000..77b1f9740a8efde6e43d75657baeb6c017e829cf --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9840.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d32125d5da1996dd7537f652ecd022cc24055204", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/decoding/tests/test_receptive_field.py": { + "a": 1, + "d": 0 + }, + "mne/export/tests/test_export.py": { + "a": 1, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_misc.py": { + "a": 1, + "d": 0 + }, + "setup.cfg": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9841.json b/mne-python/source/doc/sphinxext/prs/9841.json new file mode 100644 index 0000000000000000000000000000000000000000..3de962114b22710a65378a39f37e3ecdcd25f08f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9841.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "402077808100f5c0f6e90ba64176bab38ec32295", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 12, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9843.json b/mne-python/source/doc/sphinxext/prs/9843.json new file mode 100644 index 0000000000000000000000000000000000000000..07272830916f19aa3342ebe5699a9b665cacdd7e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9843.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "44f4b0f027f8f926d155ea0dc23c17de21d0488e", + "authors": [ + { + "n": "Rob Luke", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/tests/test_interpolation.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_standard_montage.py": { + "a": 1, + "d": 1 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 5, + "d": 5 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 7, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 4, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 1, + "d": 1 + }, + "mne/viz/conftest.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/70_fnirs_processing.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9845.json b/mne-python/source/doc/sphinxext/prs/9845.json new file mode 100644 index 0000000000000000000000000000000000000000..562e46ab09a76d20a1415af2a37719c4ac7f5d68 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9845.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "022f1a8f69c52062f956f015fba3c3b6f5ee7a1d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 11, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9847.json b/mne-python/source/doc/sphinxext/prs/9847.json new file mode 100644 index 0000000000000000000000000000000000000000..7dfb9f36ee1123a58fe0045a4dec78c3f0434fb2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9847.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "138f0459ba19de9a84ea0a8b5799df49d45bce54", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9851.json b/mne-python/source/doc/sphinxext/prs/9851.json new file mode 100644 index 0000000000000000000000000000000000000000..302548d336d89b9073005c3e6fdb73d8ee8b5281 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9851.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "556751d8e23025deb281902ad04f2c8b40b27171", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "examples/time_frequency/time_frequency_erds.py": { + "a": 46, + "d": 49 + }, + "mne/time_frequency/tfr.py": { + "a": 10, + "d": 4 + }, + "mne/viz/tests/test_utils.py": { + "a": 1, + "d": 19 + }, + "mne/viz/topo.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 10, + "d": 11 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9858.json b/mne-python/source/doc/sphinxext/prs/9858.json new file mode 100644 index 0000000000000000000000000000000000000000..d6ad12811be7a9469e3b2c6474d01f7ffb83b63e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9858.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b5b3f78c1b8b7ffacf27f04149428d6ea541ff84", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 120, + "d": 81 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 5, + "d": 6 + }, + "mne/utils/docs.py": { + "a": 12, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9859.json b/mne-python/source/doc/sphinxext/prs/9859.json new file mode 100644 index 0000000000000000000000000000000000000000..af73e2b11ea2a08225ce07a20b18576430917f11 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9859.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "b8d1cb9512d8a04061180fc063e5e2256a16bd55", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 42, + "d": 8 + }, + "mne/tests/test_epochs.py": { + "a": 14, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9860.json b/mne-python/source/doc/sphinxext/prs/9860.json new file mode 100644 index 0000000000000000000000000000000000000000..fa6b11e8f5eff911e2bbcc8f757559d7dc0413ac --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9860.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "75a13167e3d89fae36aeda7da2f34cd00cd3e995", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9861.json b/mne-python/source/doc/sphinxext/prs/9861.json new file mode 100644 index 0000000000000000000000000000000000000000..6efb83cee2dfdb226020a3c22f343ca6802d6ee0 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9861.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "668c28b22d05a334d3d5202d9cb882eac2f038e0", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 3, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 6, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9862.json b/mne-python/source/doc/sphinxext/prs/9862.json new file mode 100644 index 0000000000000000000000000000000000000000..84b4a75f2ff18a06386ac80b2dc2a10acc8c1d63 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9862.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "4c286e9159539e1e51163e01c0ae241cbdd79fb5", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 6, + "d": 8 + }, + "mne/report/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 3 + }, + "tutorials/intro/70_report.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9863.json b/mne-python/source/doc/sphinxext/prs/9863.json new file mode 100644 index 0000000000000000000000000000000000000000..88b506685e35d5fc650b376dc9b5fa0c809935ad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9863.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "e9a5dbab56785bfe2cd56c06abcd0c73b3c2f80f", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 59, + "d": 38 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9864.json b/mne-python/source/doc/sphinxext/prs/9864.json new file mode 100644 index 0000000000000000000000000000000000000000..3471e801d2ed73a255da7b8e25a454333fd9df73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9864.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "bf6a510c9f1c96f6f043a0d1d1dfb02d7d6dc34d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 0, + "d": 1 + }, + "mne/viz/_mpl_figure.py": { + "a": 1, + "d": 0 + }, + "tutorials/epochs/20_visualize_epochs.py": { + "a": 5, + "d": 5 + }, + "tutorials/intro/10_overview.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9866.json b/mne-python/source/doc/sphinxext/prs/9866.json new file mode 100644 index 0000000000000000000000000000000000000000..55962342003e157654cf8d3990418ff891c31d72 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9866.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "9e6b3c8e670f0415116b94f2631eae781dbede38", + "authors": [ + { + "n": "Riessarius", + "e": "rie.acad@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 3, + "d": 1 + }, + "mne/time_frequency/multitaper.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/psd.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9867.json b/mne-python/source/doc/sphinxext/prs/9867.json new file mode 100644 index 0000000000000000000000000000000000000000..b3d3f6ea06509f7e4e7003174e72ea2957d097fd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9867.json @@ -0,0 +1,419 @@ +{ + "merge_commit_sha": "fde89c53dedd89338346bebd1ac67335fb80375f", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/decoding/decoding_xdawn_eeg.py": { + "a": 4, + "d": 4 + }, + "examples/inverse/mne_cov_power.py": { + "a": 1, + "d": 1 + }, + "examples/simulation/simulate_evoked_data.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/temporal_whitening.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 2, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 1 + }, + "mne/channels/montage.py": { + "a": 6, + "d": 3 + }, + "mne/channels/tests/test_layout.py": { + "a": 6, + "d": 2 + }, + "mne/channels/tests/test_montage.py": { + "a": 2, + "d": 1 + }, + "mne/chpi.py": { + "a": 4, + "d": 2 + }, + "mne/decoding/csp.py": { + "a": 4, + "d": 2 + }, + "mne/decoding/transformer.py": { + "a": 4, + "d": 2 + }, + "mne/dipole.py": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 2, + "d": 1 + }, + "mne/evoked.py": { + "a": 5, + "d": 2 + }, + "mne/filter.py": { + "a": 7, + "d": 4 + }, + "mne/forward/forward.py": { + "a": 15, + "d": 13 + }, + "mne/gui/_file_traits.py": { + "a": 1, + "d": 0 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 6, + "d": 5 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 2 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 2, + "d": 1 + }, + "mne/io/artemis123/artemis123.py": { + "a": 18, + "d": 11 + }, + "mne/io/base.py": { + "a": 7, + "d": 5 + }, + "mne/io/brainvision/brainvision.py": { + "a": 4, + "d": 2 + }, + "mne/io/bti/bti.py": { + "a": 16, + "d": 13 + }, + "mne/io/cnt/cnt.py": { + "a": 1, + "d": 0 + }, + "mne/io/ctf/ctf.py": { + "a": 3, + "d": 2 + }, + "mne/io/ctf/info.py": { + "a": 1, + "d": 0 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 2, + "d": 1 + }, + "mne/io/curry/curry.py": { + "a": 12, + "d": 8 + }, + "mne/io/edf/edf.py": { + "a": 9, + "d": 5 + }, + "mne/io/egi/egi.py": { + "a": 1, + "d": 0 + }, + "mne/io/egi/egimff.py": { + "a": 8, + "d": 4 + }, + "mne/io/fieldtrip/tests/helpers.py": { + "a": 10, + "d": 6 + }, + "mne/io/fieldtrip/utils.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/raw.py": { + "a": 2, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 7, + "d": 4 + }, + "mne/io/hitachi/hitachi.py": { + "a": 4, + "d": 3 + }, + "mne/io/kit/kit.py": { + "a": 4, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 5, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 216, + "d": 37 + }, + "mne/io/nedf/nedf.py": { + "a": 2, + "d": 1 + }, + "mne/io/nicolet/nicolet.py": { + "a": 1, + "d": 0 + }, + "mne/io/nihon/nihon.py": { + "a": 2, + "d": 1 + }, + "mne/io/nirx/nirx.py": { + "a": 2, + "d": 1 + }, + "mne/io/persyst/persyst.py": { + "a": 5, + "d": 4 + }, + "mne/io/pick.py": { + "a": 9, + "d": 5 + }, + "mne/io/proj.py": { + "a": 17, + "d": 9 + }, + "mne/io/reference.py": { + "a": 8, + "d": 4 + }, + "mne/io/snirf/_snirf.py": { + "a": 17, + "d": 13 + }, + "mne/io/tests/test_meas_info.py": { + "a": 106, + "d": 44 + }, + "mne/io/tests/test_reference.py": { + "a": 10, + "d": 5 + }, + "mne/minimum_norm/resolution_matrix.py": { + "a": 3, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 11, + "d": 8 + }, + "mne/minimum_norm/time_frequency.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/_csd.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 5, + "d": 4 + }, + "mne/preprocessing/ica.py": { + "a": 11, + "d": 8 + }, + "mne/preprocessing/maxwell.py": { + "a": 10, + "d": 6 + }, + "mne/preprocessing/realign.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_csd.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_ecg.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_flat.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 14, + "d": 7 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 2, + "d": 1 + }, + "mne/report/tests/test_report.py": { + "a": 3, + "d": 1 + }, + "mne/simulation/tests/test_evoked.py": { + "a": 2, + "d": 1 + }, + "mne/simulation/tests/test_raw.py": { + "a": 5, + "d": 3 + }, + "mne/stats/regression.py": { + "a": 2, + "d": 1 + }, + "mne/stats/tests/test_regression.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_annotations.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_chpi.py": { + "a": 22, + "d": 15 + }, + "mne/tests/test_cov.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 43, + "d": 25 + }, + "mne/tests/test_event.py": { + "a": 2, + "d": 1 + }, + "mne/tests/test_evoked.py": { + "a": 10, + "d": 5 + }, + "mne/tests/test_proj.py": { + "a": 10, + "d": 5 + }, + "mne/tests/test_source_estimate.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 2, + "d": 1 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 7, + "d": 5 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 1 + }, + "mne/utils/_testing.py": { + "a": 2, + "d": 2 + }, + "mne/utils/check.py": { + "a": 2, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 3, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 4, + "d": 2 + }, + "mne/viz/ica.py": { + "a": 4, + "d": 2 + }, + "mne/viz/misc.py": { + "a": 2, + "d": 1 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_3d.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_epochs.py": { + "a": 2, + "d": 1 + }, + "mne/viz/tests/test_evoked.py": { + "a": 4, + "d": 2 + }, + "mne/viz/tests/test_ica.py": { + "a": 6, + "d": 3 + }, + "mne/viz/tests/test_raw.py": { + "a": 14, + "d": 7 + }, + "mne/viz/tests/test_topomap.py": { + "a": 6, + "d": 3 + }, + "mne/viz/topo.py": { + "a": 3, + "d": 4 + }, + "mne/viz/topomap.py": { + "a": 4, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 4 + }, + "tutorials/time-freq/50_ssvep.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9869.json b/mne-python/source/doc/sphinxext/prs/9869.json new file mode 100644 index 0000000000000000000000000000000000000000..c7cb38f3ed21411dad9f82431b5a4a2e45aaeaae --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9869.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "c3a483fbc0418f41d8046fca68ee9452931cd082", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 23, + "d": 9 + }, + "mne/io/base.py": { + "a": 1, + "d": 2 + }, + "mne/io/utils.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_epochs.py": { + "a": 27, + "d": 0 + }, + "mne/utils/docs.py": { + "a": 7, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9871.json b/mne-python/source/doc/sphinxext/prs/9871.json new file mode 100644 index 0000000000000000000000000000000000000000..e3449f9f4044643ffd2017a39574337600147237 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9871.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "3ed5afdb484122d5bb0d829ae4b48cd1101ae9c4", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 59, + "d": 25 + }, + "mne/report/templates/epochs.html": { + "a": 1, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9873.json b/mne-python/source/doc/sphinxext/prs/9873.json new file mode 100644 index 0000000000000000000000000000000000000000..3a9cf50775b4b7d048422ebb304ffe1cfeefab80 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9873.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "2385d91b3681d1ce6f02d0916c2b39929150a3f4", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/topomap.py": { + "a": 3, + "d": 0 + }, + "tutorials/time-freq/20_sensors_time_frequency.py": { + "a": 13, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9874.json b/mne-python/source/doc/sphinxext/prs/9874.json new file mode 100644 index 0000000000000000000000000000000000000000..dab29ec5662348a86713891d44d0b69fd50125e1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9874.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "2dd65c0cf74667b0dc5978fd1cdfa0afc465d927", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "doc/visualization.rst": { + "a": 2, + "d": 0 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 16, + "d": 0 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 5, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9875.json b/mne-python/source/doc/sphinxext/prs/9875.json new file mode 100644 index 0000000000000000000000000000000000000000..84488b631f055e397cc333305103631d75c6909d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9875.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "598b7253228c27eeb953d15d7cdab908b1bcf83c", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 52, + "d": 28 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9876.json b/mne-python/source/doc/sphinxext/prs/9876.json new file mode 100644 index 0000000000000000000000000000000000000000..1cc9f96c9ab9b71f10ce81f1a1cd2afb0f1d1750 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9876.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f87be3000ce333ff9ccfddc45b47a2da7d92d69c", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "mne/io/reference.py": { + "a": 8, + "d": 9 + }, + "mne/io/tests/test_reference.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9877.json b/mne-python/source/doc/sphinxext/prs/9877.json new file mode 100644 index 0000000000000000000000000000000000000000..aa7ecfb23b5762fb2f422f1ccd9ead383824213a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9877.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "5226862369e28682e919af9eb69fa5014565d7eb", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 83, + "d": 1 + }, + "mne/gui/tests/test_gui_api.py": { + "a": 117, + "d": 0 + }, + "mne/viz/backends/_abstract.py": { + "a": 43, + "d": 4 + }, + "mne/viz/backends/_notebook.py": { + "a": 114, + "d": 10 + }, + "mne/viz/backends/_qt.py": { + "a": 147, + "d": 18 + }, + "mne/viz/conftest.py": { + "a": 0, + "d": 84 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9878.json b/mne-python/source/doc/sphinxext/prs/9878.json new file mode 100644 index 0000000000000000000000000000000000000000..5bf70f7c7dd544f57e25d8eb58619a69a82629ca --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9878.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6ca1752cc3ad49cd8cd9b162e98ec3e4e07da99f", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/viz/_3d.py": { + "a": 107, + "d": 32 + }, + "mne/viz/tests/test_3d.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/988.json b/mne-python/source/doc/sphinxext/prs/988.json new file mode 100644 index 0000000000000000000000000000000000000000..ba3aa5c2b3cad6894ecfa34e9fe34bc589ae935a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/988.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f114073096311ba775eaaa82f8500ca28df51ac1", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/fiff/evoked.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9880.json b/mne-python/source/doc/sphinxext/prs/9880.json new file mode 100644 index 0000000000000000000000000000000000000000..9597ee5338111f16f6fecf96e7c34c1eb376ae70 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9880.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ce04060614315ae048473c387e1f74eea2ed1d2d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/tests/test_transforms.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9881.json b/mne-python/source/doc/sphinxext/prs/9881.json new file mode 100644 index 0000000000000000000000000000000000000000..2fd01b4c6b465c289d8deaf1016d664d99c8829b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9881.json @@ -0,0 +1,47 @@ +{ + "merge_commit_sha": "44ac64b42a942846061e42a2f0064f430df56153", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/channels/layout.py": { + "a": 1, + "d": 1 + }, + "mne/channels/tests/test_layout.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 59, + "d": 25 + }, + "mne/report/tests/test_report.py": { + "a": 42, + "d": 0 + }, + "mne/utils/check.py": { + "a": 20, + "d": 3 + }, + "mne/utils/tests/test_check.py": { + "a": 29, + "d": 2 + }, + "mne/viz/evoked.py": { + "a": 3, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 3, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9884.json b/mne-python/source/doc/sphinxext/prs/9884.json new file mode 100644 index 0000000000000000000000000000000000000000..dfe968e902b279a5f13dc647bc95cbf495f685ff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9884.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "0a70b126e12315a713f56f0151620dbb218c219a", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + ".gitignore": { + "a": 0, + "d": 1 + }, + "brain.png": { + "a": 0, + "d": 0 + }, + "figures/Figure_1.png": { + "a": 0, + "d": 0 + }, + "figures/Figure_2.png": { + "a": 0, + "d": 0 + }, + "figures/Figure_3.png": { + "a": 0, + "d": 0 + }, + "figures/Figure_4.png": { + "a": 0, + "d": 0 + }, + "figures/Figure_5.png": { + "a": 0, + "d": 0 + }, + "figures/Figure_6.png": { + "a": 0, + "d": 0 + }, + "paper.bib": { + "a": 110, + "d": 0 + }, + "paper.md": { + "a": 87, + "d": 0 + }, + "test.png": { + "a": 0, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9886.json b/mne-python/source/doc/sphinxext/prs/9886.json new file mode 100644 index 0000000000000000000000000000000000000000..480aca1b4e6ff85feb0345444de5e80281353c42 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9886.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "549096c35b775cbdddbc1936f72a1fc843055508", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".coveragerc": { + "a": 0, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 4, + "d": 2 + }, + "mne/utils/config.py": { + "a": 4, + "d": 17 + }, + "requirements_testing_extra.txt": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9887.json b/mne-python/source/doc/sphinxext/prs/9887.json new file mode 100644 index 0000000000000000000000000000000000000000..e6bdcf328f7fb354aca6ad0001b3edfaf887236b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9887.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "68dcfd7d9a46d1d6f04151aac3877bcebf0c5c6e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "mne/report/report.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9888.json b/mne-python/source/doc/sphinxext/prs/9888.json new file mode 100644 index 0000000000000000000000000000000000000000..7114a626f18f1aa825deeba06f6ed9d7159d7a4b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9888.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "6920db460f9bb709f2c78ffcfaf625106d66a7ad", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_chpi.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9889.json b/mne-python/source/doc/sphinxext/prs/9889.json new file mode 100644 index 0000000000000000000000000000000000000000..f8cb26bb788d9cd4a9aedb7307a46e78c7cdc6bc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9889.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8e435cf5d19ce2f56180360633180181248f6ad7", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "mne/io/base.py": { + "a": 7, + "d": 7 + }, + "mne/io/tests/test_raw.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9890.json b/mne-python/source/doc/sphinxext/prs/9890.json new file mode 100644 index 0000000000000000000000000000000000000000..c069a109b91fca8fb547288883e17c7ece201dc9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9890.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "babf7780c8479a7d260a98ae11b67372c25bdb7d", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + } + ], + "changes": { + "tutorials/evoked/30_eeg_erp.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9891.json b/mne-python/source/doc/sphinxext/prs/9891.json new file mode 100644 index 0000000000000000000000000000000000000000..fc7ba51d483aa443f74778dab6c0295345343f66 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9891.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "3887bb2900f3eb1a8101658e8bd87d38b761e301", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 29, + "d": 34 + }, + "tutorials/intro/70_report.py": { + "a": 3, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9892.json b/mne-python/source/doc/sphinxext/prs/9892.json new file mode 100644 index 0000000000000000000000000000000000000000..386ce326ba289e984be427c29a184e1219e6063d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9892.json @@ -0,0 +1,67 @@ +{ + "merge_commit_sha": "c7734446c054e95485a27bf9cd132e4b19a1e281", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + }, + { + "n": "johnsam7", + "e": "johnsam@mit.edu" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 2, + "d": 0 + }, + "doc/preprocessing.rst": { + "a": 1, + "d": 0 + }, + "doc/references.bib": { + "a": 10, + "d": 0 + }, + "examples/preprocessing/css.py": { + "a": 95, + "d": 0 + }, + "mne/preprocessing/__init__.py": { + "a": 1, + "d": 0 + }, + "mne/preprocessing/_css.py": { + "a": 91, + "d": 0 + }, + "mne/preprocessing/tests/test_css.py": { + "a": 37, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9893.json b/mne-python/source/doc/sphinxext/prs/9893.json new file mode 100644 index 0000000000000000000000000000000000000000..26df274e4af9c016846bfbd8b088555beb1935af --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9893.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "e3c46808b3f116c94ba5866179499a55420f0c2c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 34, + "d": 7 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 29, + "d": 1 + }, + "mne/source_space.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9896.json b/mne-python/source/doc/sphinxext/prs/9896.json new file mode 100644 index 0000000000000000000000000000000000000000..eb5d2a52a59e4dc9a115483c86471cfafb3f4b8a --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9896.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "d2b4de1811e9ba146b2f6b86c1b510e31640745b", + "authors": [ + { + "n": "Stefan Appelhoff", + "e": "stefan.appelhoff@mailbox.org" + } + ], + "changes": { + "mne/annotations.py": { + "a": 2, + "d": 2 + }, + "mne/io/brainvision/brainvision.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9897.json b/mne-python/source/doc/sphinxext/prs/9897.json new file mode 100644 index 0000000000000000000000000000000000000000..2e66a29e80ce145a37dca896e26027e59602ae84 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9897.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "131c67682a2b1f1343afdefeb814db22543d539f", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/filter.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_filter.py": { + "a": 26, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9898.json b/mne-python/source/doc/sphinxext/prs/9898.json new file mode 100644 index 0000000000000000000000000000000000000000..073d9a756f27f539aae68daf689754e5d7c3a000 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9898.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "940125813cda9212767f8a97774841c49d35f6c4", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/names.inc": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9899.json b/mne-python/source/doc/sphinxext/prs/9899.json new file mode 100644 index 0000000000000000000000000000000000000000..fe47c1ee48cb5699055d524faace3ffee2650d8e --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9899.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "d336828ffaba5095950cbcb7691073a466f7a258", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/conf.py": { + "a": 3, + "d": 1 + }, + "mne/fixes.py": { + "a": 0, + "d": 1 + }, + "mne/utils/linalg.py": { + "a": 6, + "d": 2 + }, + "mne/viz/_brain/_brain.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/990.json b/mne-python/source/doc/sphinxext/prs/990.json new file mode 100644 index 0000000000000000000000000000000000000000..7faac6f7be65902fae7615554a66f4f108d755a3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/990.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a9c5a18c1e2dbb801edc08081e33dafcfe05ff66", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "doc/source/whats_new.rst": { + "a": 2, + "d": 0 + }, + "examples/plot_topo_customized.py": { + "a": 58, + "d": 0 + }, + "mne/viz.py": { + "a": 162, + "d": 86 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9900.json b/mne-python/source/doc/sphinxext/prs/9900.json new file mode 100644 index 0000000000000000000000000000000000000000..c578d6dc8f0b87ee877f6a4e240d2549091c0bf7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9900.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "4b47a143ac787fc5791e43be148e5aa498db19a8", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/glossary.rst": { + "a": 7, + "d": 3 + }, + "mne/beamformer/tests/test_dics.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ecg.py": { + "a": 11, + "d": 0 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 2 + }, + "mne/report/report.py": { + "a": 6, + "d": 6 + }, + "mne/report/tests/test_report.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 27, + "d": 17 + }, + "mne/viz/misc.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9901.json b/mne-python/source/doc/sphinxext/prs/9901.json new file mode 100644 index 0000000000000000000000000000000000000000..ce2d1c689a201a68c0365443270c1966835ff5b6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9901.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "616b9430392d0d2bbf73063e738c7b8c378defcd", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "tutorials/intro/70_report.py": { + "a": 27, + "d": 23 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9902.json b/mne-python/source/doc/sphinxext/prs/9902.json new file mode 100644 index 0000000000000000000000000000000000000000..6506d0b29bddbd01b184bc7956ff284dd6b229a7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9902.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "cd76bf2d839c6003d919a385d6daf3ebb808f340", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/decoding/search_light.py": { + "a": 9, + "d": 26 + }, + "mne/utils/docs.py": { + "a": 19, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9903.json b/mne-python/source/doc/sphinxext/prs/9903.json new file mode 100644 index 0000000000000000000000000000000000000000..ea892f98abda4c8cab655c87ef25e2c40d2cf455 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9903.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "cd50d8e68708b8667f04b1efb9b2cacf21001a28", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/tests/test_epochs.py": { + "a": 31, + "d": 27 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9904.json b/mne-python/source/doc/sphinxext/prs/9904.json new file mode 100644 index 0000000000000000000000000000000000000000..fe775e9fa53d6c1e6560d438721d3cd96e9856a5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9904.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "3a9b06652f644a8bda3c99f91705396b7373368a", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 8, + "d": 0 + }, + "doc/mri.rst": { + "a": 0, + "d": 1 + }, + "examples/datasets/spm_faces_dataset_sgskip.py": { + "a": 1, + "d": 1 + }, + "examples/inverse/label_from_stc.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 11, + "d": 2 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/gui/__init__.py": { + "a": 7, + "d": 1 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 5, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 12, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 5, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9907.json b/mne-python/source/doc/sphinxext/prs/9907.json new file mode 100644 index 0000000000000000000000000000000000000000..b74088a4817551bad3fb947df78bd1271f3d0f58 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9907.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bf945f19d221a4955b59758fdb9777d35315c042", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/surface.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9909.json b/mne-python/source/doc/sphinxext/prs/9909.json new file mode 100644 index 0000000000000000000000000000000000000000..421aaec779588e24888b496ae9eac30affb55655 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9909.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "b005ea698a1ef53e0a4bbc2e3d411201bd94307c", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 3, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 2, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 19, + "d": 9 + }, + "mne/utils/tests/test_docs.py": { + "a": 16, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/991.json b/mne-python/source/doc/sphinxext/prs/991.json new file mode 100644 index 0000000000000000000000000000000000000000..8975dd96ce432e54d5ab8921e31e09c01cc66c43 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/991.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "7870269da65ec9341a09d9c0ef60bd4eb760d409", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": { + "mne/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/datasets/utils.py": { + "a": 8, + "d": 10 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9911.json b/mne-python/source/doc/sphinxext/prs/9911.json new file mode 100644 index 0000000000000000000000000000000000000000..78017c724df1954dbc9f2c9590c8e2f340948c5c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9911.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f6b1ba7a52a0907e1f04782e055409a2d12c330a", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9913.json b/mne-python/source/doc/sphinxext/prs/9913.json new file mode 100644 index 0000000000000000000000000000000000000000..71159738c6bab79a7ab02a5bc44b16c8f2c31a4f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9913.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "3eca0adfadbe1a9ac0e45845c57278cf7d19ec21", + "authors": [ + { + "n": "Guillaume Favelier", + "e": "guillaume.favelier@gmail.com" + } + ], + "changes": { + "mne/gui/_coreg.py": { + "a": 1, + "d": 1 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 18, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9914.json b/mne-python/source/doc/sphinxext/prs/9914.json new file mode 100644 index 0000000000000000000000000000000000000000..44569617c17beb5ee40147dbc0666b1b5674a0cb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9914.json @@ -0,0 +1,55 @@ +{ + "merge_commit_sha": "dac4f16903171c5b8a03b1a35b9c99e7bb753e25", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 1 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 1 + }, + "mne/io/fieldtrip/utils.py": { + "a": 2, + "d": 2 + }, + "mne/io/hitachi/hitachi.py": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 10, + "d": 0 + }, + "mne/io/nirx/nirx.py": { + "a": 1, + "d": 1 + }, + "mne/io/reference.py": { + "a": 2, + "d": 1 + }, + "mne/simulation/raw.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_cov.py": { + "a": 2, + "d": 1 + }, + "tutorials/simulation/80_dics.py": { + "a": 1, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9915.json b/mne-python/source/doc/sphinxext/prs/9915.json new file mode 100644 index 0000000000000000000000000000000000000000..700670f066ebb524de23f359c292433a97baf6f7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9915.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "ee164e673af146c60fa9cd6cb9925316cec9117a", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/versions.json": { + "a": 46, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9916.json b/mne-python/source/doc/sphinxext/prs/9916.json new file mode 100644 index 0000000000000000000000000000000000000000..1588ed6a2feb0080af0f0e8efc682a43a22c9095 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9916.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "4679e87ece4bfd5174e56b595671088a5da6e925", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_static/style.css": { + "a": 0, + "d": 11 + }, + "doc/_static/versions.json": { + "a": 6, + "d": 3 + }, + "doc/_templates/version-switcher.html": { + "a": 0, + "d": 11 + }, + "doc/conf.py": { + "a": 6, + "d": 17 + }, + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9917.json b/mne-python/source/doc/sphinxext/prs/9917.json new file mode 100644 index 0000000000000000000000000000000000000000..22cbad89c93c8e0ea3b27e579e03106c23348177 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9917.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "e8dd72b3920e6f7d9ee6de315e76cec51ba9153c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 15, + "d": 11 + }, + "mne/conftest.py": { + "a": 1, + "d": 0 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 1, + "d": 0 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 0 + }, + "mne/surface.py": { + "a": 1, + "d": 0 + }, + "mne/tests/test_bem.py": { + "a": 1, + "d": 0 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9918.json b/mne-python/source/doc/sphinxext/prs/9918.json new file mode 100644 index 0000000000000000000000000000000000000000..0229aca817a2cccb86fefd339d7694f88225d9cd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9918.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "f10502b4fa861738d72f581cfb93b5b58117de48", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 7, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/992.json b/mne-python/source/doc/sphinxext/prs/992.json new file mode 100644 index 0000000000000000000000000000000000000000..8b5c3e36b49b1b6a1255bf8f4f46032e436d6eff --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/992.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "45eafe53e5974ed62710ea5bada516f9e20e2de1", + "authors": [ + { + "n": "Denis A. Engemann", + "e": null + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 8, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9920.json b/mne-python/source/doc/sphinxext/prs/9920.json new file mode 100644 index 0000000000000000000000000000000000000000..3776006248899532c2d6f896dee88d455b5ba324 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9920.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "f078b9076d0d9ca83bb5e973315066a3c4911e24", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/channels/channels.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 15, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9921.json b/mne-python/source/doc/sphinxext/prs/9921.json new file mode 100644 index 0000000000000000000000000000000000000000..bb0fec5635a932b577645a8cc2931422971f44c5 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9921.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "47c011266cc4df88ca92ad122317f96886347538", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/_static/blender_import_obj/blender_import_obj4.jpg": { + "a": 0, + "d": 0 + }, + "tutorials/forward/80_fix_bem_in_blender.py": { + "a": 22, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9922.json b/mne-python/source/doc/sphinxext/prs/9922.json new file mode 100644 index 0000000000000000000000000000000000000000..fa1bc1c6ab1114c2ed265d2a05e0a0acb38d2f85 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9922.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "870d867c8b60697a5fef8cb353e6a51e209d99c3", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/kit/kit.py": { + "a": 3, + "d": 3 + }, + "mne/io/meas_info.py": { + "a": 101, + "d": 67 + }, + "mne/io/tests/test_meas_info.py": { + "a": 0, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9924.json b/mne-python/source/doc/sphinxext/prs/9924.json new file mode 100644 index 0000000000000000000000000000000000000000..32c3515c138470a624ef353fb1dc1cf0caa820e3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9924.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "5d1f34ce0ae4f5b2d6175f67eb598daf70df30f7", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9925.json b/mne-python/source/doc/sphinxext/prs/9925.json new file mode 100644 index 0000000000000000000000000000000000000000..37e2e03c994a35910fed8321e09620a68af1f74f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9925.json @@ -0,0 +1,339 @@ +{ + "merge_commit_sha": "b97da4357f9ffb584eef5949c958187b3a7cc566", + "authors": [ + { + "n": "Clemens Brunner", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_dics.py": { + "a": 2, + "d": 2 + }, + "mne/beamformer/tests/test_lcmv.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_channels.py": { + "a": 2, + "d": 2 + }, + "mne/channels/tests/test_layout.py": { + "a": 8, + "d": 8 + }, + "mne/channels/tests/test_montage.py": { + "a": 22, + "d": 21 + }, + "mne/commands/tests/test_commands.py": { + "a": 20, + "d": 20 + }, + "mne/conftest.py": { + "a": 3, + "d": 3 + }, + "mne/datasets/sleep_physionet/tests/test_physionet.py": { + "a": 6, + "d": 6 + }, + "mne/datasets/tests/test_datasets.py": { + "a": 22, + "d": 22 + }, + "mne/export/tests/test_export.py": { + "a": 6, + "d": 6 + }, + "mne/forward/tests/test_forward.py": { + "a": 9, + "d": 9 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 15, + "d": 15 + }, + "mne/gui/_coreg.py": { + "a": 2, + "d": 0 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 6, + "d": 9 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 4, + "d": 4 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 4, + "d": 4 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 4, + "d": 4 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 2, + "d": 2 + }, + "mne/io/artemis123/tests/test_artemis123.py": { + "a": 2, + "d": 2 + }, + "mne/io/base.py": { + "a": 3, + "d": 0 + }, + "mne/io/brainvision/tests/test_brainvision.py": { + "a": 23, + "d": 23 + }, + "mne/io/ctf/tests/test_ctf.py": { + "a": 5, + "d": 5 + }, + "mne/io/curry/tests/test_curry.py": { + "a": 9, + "d": 9 + }, + "mne/io/edf/tests/test_edf.py": { + "a": 18, + "d": 16 + }, + "mne/io/edf/tests/test_gdf.py": { + "a": 2, + "d": 2 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 18, + "d": 18 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 4, + "d": 4 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 73, + "d": 71 + }, + "mne/io/hitachi/tests/test_hitachi.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/tests/test_coreg.py": { + "a": 2, + "d": 2 + }, + "mne/io/kit/tests/test_kit.py": { + "a": 4, + "d": 4 + }, + "mne/io/nirx/tests/test_nirx.py": { + "a": 12, + "d": 12 + }, + "mne/io/persyst/tests/test_persyst.py": { + "a": 8, + "d": 8 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 3, + "d": 3 + }, + "mne/io/tests/test_compensator.py": { + "a": 4, + "d": 4 + }, + "mne/io/tests/test_constants.py": { + "a": 11, + "d": 10 + }, + "mne/io/tests/test_meas_info.py": { + "a": 28, + "d": 28 + }, + "mne/io/tests/test_what.py": { + "a": 2, + "d": 2 + }, + "mne/io/tests/test_write.py": { + "a": 2, + "d": 2 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 12, + "d": 11 + }, + "mne/minimum_norm/tests/test_snr.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/ieeg/tests/test_projection.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 3, + "d": 3 + }, + "mne/preprocessing/nirs/tests/test_scalp_coupling_index.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/nirs/tests/test_temporal_derivative_distribution_repair.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_fine_cal.py": { + "a": 2, + "d": 2 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 17, + "d": 17 + }, + "mne/preprocessing/tests/test_maxwell.py": { + "a": 8, + "d": 8 + }, + "mne/report/tests/test_report.py": { + "a": 40, + "d": 40 + }, + "mne/simulation/tests/test_raw.py": { + "a": 2, + "d": 2 + }, + "mne/stats/tests/test_cluster_level.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_annotations.py": { + "a": 34, + "d": 28 + }, + "mne/tests/test_bem.py": { + "a": 15, + "d": 15 + }, + "mne/tests/test_chpi.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_coreg.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_cov.py": { + "a": 17, + "d": 17 + }, + "mne/tests/test_dipole.py": { + "a": 14, + "d": 14 + }, + "mne/tests/test_epochs.py": { + "a": 47, + "d": 47 + }, + "mne/tests/test_event.py": { + "a": 7, + "d": 7 + }, + "mne/tests/test_evoked.py": { + "a": 19, + "d": 19 + }, + "mne/tests/test_filter.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_freesurfer.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_label.py": { + "a": 8, + "d": 8 + }, + "mne/tests/test_line_endings.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_morph.py": { + "a": 10, + "d": 10 + }, + "mne/tests/test_morph_map.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_proj.py": { + "a": 4, + "d": 4 + }, + "mne/tests/test_source_estimate.py": { + "a": 27, + "d": 26 + }, + "mne/tests/test_source_space.py": { + "a": 30, + "d": 29 + }, + "mne/tests/test_surface.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_transforms.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tests/test_csd.py": { + "a": 4, + "d": 4 + }, + "mne/time_frequency/tests/test_tfr.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_check.py": { + "a": 4, + "d": 5 + }, + "mne/utils/tests/test_config.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_logging.py": { + "a": 4, + "d": 4 + }, + "mne/utils/tests/test_numerics.py": { + "a": 2, + "d": 2 + }, + "mne/utils/tests/test_testing.py": { + "a": 6, + "d": 5 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 18, + "d": 16 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 2, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 5, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9927.json b/mne-python/source/doc/sphinxext/prs/9927.json new file mode 100644 index 0000000000000000000000000000000000000000..d7040edd664cff913af639494f554b77c0fe2a1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9927.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8ba1888704d7611be3a0a22aa38a024287b2de46", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "mne/viz/evoked.py": { + "a": 39, + "d": 4 + }, + "mne/viz/topo.py": { + "a": 11, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9928.json b/mne-python/source/doc/sphinxext/prs/9928.json new file mode 100644 index 0000000000000000000000000000000000000000..5c0a5de50633eac2d236a8ecb1435fc0805f7812 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9928.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "9cbff29afd2cd7bb4063108dd243998149134257", + "authors": [ + { + "n": "Luke Bloy", + "e": "luke.bloy@gmail.com" + } + ], + "changes": { + "mne/coreg.py": { + "a": 11, + "d": 5 + }, + "mne/gui/_coreg.py": { + "a": 46, + "d": 12 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 45, + "d": 0 + }, + "mne/io/snirf/_snirf.py": { + "a": 1, + "d": 1 + }, + "mne/tests/test_coreg.py": { + "a": 25, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9929.json b/mne-python/source/doc/sphinxext/prs/9929.json new file mode 100644 index 0000000000000000000000000000000000000000..0edd364cae7aa8ef1977ecd1e00e003ab5097dbc --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9929.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "f6213029576560493a3c5c5f4bcef63e24ffc108", + "authors": [ + { + "n": "Rob Luke", + "e": null + } + ], + "changes": { + "mne/datasets/config.py": { + "a": 2, + "d": 2 + }, + "mne/io/snirf/_snirf.py": { + "a": 88, + "d": 53 + }, + "mne/io/snirf/tests/test_snirf.py": { + "a": 48, + "d": 19 + }, + "mne/io/tests/test_raw.py": { + "a": 4, + "d": 0 + }, + "mne/preprocessing/nirs/nirs.py": { + "a": 47, + "d": 29 + }, + "tutorials/io/30_reading_fnirs_data.py": { + "a": 20, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/993.json b/mne-python/source/doc/sphinxext/prs/993.json new file mode 100644 index 0000000000000000000000000000000000000000..307de033f15b331d1ccc15d0c90e8fa7171b5a1c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/993.json @@ -0,0 +1,10 @@ +{ + "merge_commit_sha": "fc15283fcbcdc6c6dad5764a9c27720910e2d6ff", + "authors": [ + { + "n": "Tal Linzen", + "e": "linzen@nyu.edu" + } + ], + "changes": {} +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9933.json b/mne-python/source/doc/sphinxext/prs/9933.json new file mode 100644 index 0000000000000000000000000000000000000000..a19229965210d97aaf6fc789354c4f1ed3e1dfb3 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9933.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a1d4eb907b1ed30c8bc713c0f315c7d481e0dd57", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "examples/visualization/3d_to_2d.py": { + "a": 0, + "d": 2 + }, + "mne/viz/_3d.py": { + "a": 8, + "d": 5 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 13, + "d": 61 + }, + "mne/viz/backends/_pyvista.py": { + "a": 4, + "d": 2 + }, + "tutorials/clinical/30_ecog.py": { + "a": 3, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9934.json b/mne-python/source/doc/sphinxext/prs/9934.json new file mode 100644 index 0000000000000000000000000000000000000000..00f7bac2fc0e0325d782c08b7bf9611e2e3712fa --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9934.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "f8283e89d4d4464b84c68d3eee7e4be0168aed56", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/preprocessing/ica.py": { + "a": 1, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 16, + "d": 17 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9936.json b/mne-python/source/doc/sphinxext/prs/9936.json new file mode 100644 index 0000000000000000000000000000000000000000..e6b8963e2e4907ad8d65057a4b6f06a2e1fddf93 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9936.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "93da0582c09eebd6778df97e994e4dc27d89202b", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/decoding/receptive_field.py": { + "a": 3, + "d": 5 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 1, + "d": 3 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9937.json b/mne-python/source/doc/sphinxext/prs/9937.json new file mode 100644 index 0000000000000000000000000000000000000000..06bbb51390030c8350495ecb6bb1a1d9983ba586 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9937.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b8b49ab0ea4bbf0f18942c293445be3bf7b0d565", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/beamformer/tests/test_lcmv.py": { + "a": 4, + "d": 2 + }, + "mne/beamformer/tests/test_rap_music.py": { + "a": 3, + "d": 1 + }, + "mne/io/fiff/tests/test_raw_fiff.py": { + "a": 40, + "d": 38 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 21, + "d": 9 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 4, + "d": 3 + }, + "mne/tests/test_epochs.py": { + "a": 9, + "d": 1 + }, + "mne/tests/test_rank.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9940.json b/mne-python/source/doc/sphinxext/prs/9940.json new file mode 100644 index 0000000000000000000000000000000000000000..2a30a25d72e3e7b7dd72caf83a2ad34a56b1dd59 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9940.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "27de73142d5f35c019fe962e6a0d6c90eb677ac5", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/surface.py": { + "a": 6, + "d": 2 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9943.json b/mne-python/source/doc/sphinxext/prs/9943.json new file mode 100644 index 0000000000000000000000000000000000000000..48de5e377cc7295bcc1240776bf4178af4d475d1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9943.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "f873c3f2059ead9dbc1588a2f0a022ecc2e4b0e5", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 2, + "d": 1 + }, + "README.rst": { + "a": 1, + "d": 1 + }, + "azure-pipelines.yml": { + "a": 2, + "d": 2 + }, + "doc/install/contributing.rst": { + "a": 1, + "d": 13 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9944.json b/mne-python/source/doc/sphinxext/prs/9944.json new file mode 100644 index 0000000000000000000000000000000000000000..a3fe00c060d3bd4f10a27a5f02b175fbbd121685 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9944.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "1221b9ca280de1df1c52b6ab3960a3c99ca34968", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/conftest.py": { + "a": 7, + "d": 0 + }, + "mne/coreg.py": { + "a": 5, + "d": 0 + }, + "mne/gui/_coreg.py": { + "a": 13, + "d": 4 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 5, + "d": 2 + }, + "mne/viz/backends/_abstract.py": { + "a": 6, + "d": 0 + }, + "mne/viz/backends/_notebook.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 2, + "d": 0 + }, + "mne/viz/backends/_qt.py": { + "a": 3, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9945.json b/mne-python/source/doc/sphinxext/prs/9945.json new file mode 100644 index 0000000000000000000000000000000000000000..c3f0df3a723fd0028f939e63d8a588dd46f9a330 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9945.json @@ -0,0 +1,255 @@ +{ + "merge_commit_sha": "a7bbdf0d5f2a1e228ed8c0240f97e1236fb81c76", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + }, + "doc/conf.py": { + "a": 5, + "d": 19 + }, + "doc/install/advanced.rst": { + "a": 2, + "d": 24 + }, + "doc/install/contributing.rst": { + "a": 1, + "d": 1 + }, + "doc/install/mne_python.rst": { + "a": 0, + "d": 24 + }, + "doc/links.inc": { + "a": 0, + "d": 1 + }, + "doc/overview/design_philosophy.rst": { + "a": 5, + "d": 4 + }, + "doc/overview/faq.rst": { + "a": 4, + "d": 5 + }, + "doc/overview/roadmap.rst": { + "a": 0, + "d": 14 + }, + "environment.yml": { + "a": 0, + "d": 3 + }, + "examples/visualization/3d_to_2d.py": { + "a": 1, + "d": 1 + }, + "mne/channels/channels.py": { + "a": 1, + "d": 1 + }, + "mne/commands/mne_coreg.py": { + "a": 14, + "d": 19 + }, + "mne/commands/mne_kit2fiff.py": { + "a": 4, + "d": 9 + }, + "mne/commands/tests/test_commands.py": { + "a": 2, + "d": 5 + }, + "mne/conftest.py": { + "a": 7, + "d": 39 + }, + "mne/dipole.py": { + "a": 4, + "d": 4 + }, + "mne/gui/__init__.py": { + "a": 35, + "d": 120 + }, + "mne/gui/_backend.py": { + "a": 0, + "d": 53 + }, + "mne/gui/_coreg_gui.py": { + "a": 0, + "d": 2147 + }, + "mne/gui/_fiducials_gui.py": { + "a": 0, + "d": 515 + }, + "mne/gui/_file_traits.py": { + "a": 0, + "d": 577 + }, + "mne/gui/_help.py": { + "a": 0, + "d": 16 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 0, + "d": 6 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 0, + "d": 758 + }, + "mne/gui/_marker_gui.py": { + "a": 0, + "d": 455 + }, + "mne/gui/_viewer.py": { + "a": 0, + "d": 564 + }, + "mne/gui/help/kit2fiff.json": { + "a": 0, + "d": 10 + }, + "mne/gui/tests/test_coreg_gui.py": { + "a": 1, + "d": 320 + }, + "mne/gui/tests/test_fiducials_gui.py": { + "a": 0, + "d": 68 + }, + "mne/gui/tests/test_file_traits.py": { + "a": 0, + "d": 137 + }, + "mne/gui/tests/test_kit2fiff_gui.py": { + "a": 0, + "d": 162 + }, + "mne/gui/tests/test_marker_gui.py": { + "a": 0, + "d": 78 + }, + "mne/io/egi/tests/test_egi.py": { + "a": 1, + "d": 1 + }, + "mne/report/report.py": { + "a": 8, + "d": 8 + }, + "mne/report/tests/test_report.py": { + "a": 2, + "d": 2 + }, + "mne/source_space.py": { + "a": 2, + "d": 2 + }, + "mne/surface.py": { + "a": 8, + "d": 1 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 4, + "d": 28 + }, + "mne/tests/test_import_nesting.py": { + "a": 1, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 5, + "d": 6 + }, + "mne/utils/_logging.py": { + "a": 0, + "d": 14 + }, + "mne/utils/_testing.py": { + "a": 0, + "d": 48 + }, + "mne/utils/check.py": { + "a": 5, + "d": 8 + }, + "mne/utils/config.py": { + "a": 1, + "d": 5 + }, + "mne/utils/tests/test_check.py": { + "a": 4, + "d": 13 + }, + "mne/viz/_3d.py": { + "a": 44, + "d": 111 + }, + "mne/viz/_brain/_brain.py": { + "a": 5, + "d": 9 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 2, + "d": 8 + }, + "mne/viz/backends/_abstract.py": { + "a": 1, + "d": 1 + }, + "mne/viz/backends/_pysurfer_mayavi.py": { + "a": 0, + "d": 511 + }, + "mne/viz/backends/_utils.py": { + "a": 0, + "d": 1 + }, + "mne/viz/backends/renderer.py": { + "a": 45, + "d": 54 + }, + "mne/viz/backends/tests/_utils.py": { + "a": 0, + "d": 12 + }, + "mne/viz/backends/tests/test_renderer.py": { + "a": 2, + "d": 5 + }, + "mne/viz/tests/test_3d.py": { + "a": 27, + "d": 64 + }, + "mne/viz/utils.py": { + "a": 7, + "d": 5 + }, + "requirements.txt": { + "a": 0, + "d": 3 + }, + "setup.py": { + "a": 0, + "d": 1 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 1 + }, + "tutorials/inverse/60_visualize_stc.py": { + "a": 4, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9946.json b/mne-python/source/doc/sphinxext/prs/9946.json new file mode 100644 index 0000000000000000000000000000000000000000..46a60069c9204715e21388a9a76e5e912f40a564 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9946.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6c9fca05e49f23da2794f4a5f112e90f6552e882", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/0.24.inc": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9947.json b/mne-python/source/doc/sphinxext/prs/9947.json new file mode 100644 index 0000000000000000000000000000000000000000..ffb9a8ba8d5ac4aa319f7c43a4cacba67e0526d7 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9947.json @@ -0,0 +1,203 @@ +{ + "merge_commit_sha": "c69ec3db5e5f7945b3be4f0143716d747b0d1573", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 1 + }, + "README.rst": { + "a": 7, + "d": 7 + }, + "mne/__init__.py": { + "a": 0, + "d": 1 + }, + "mne/conftest.py": { + "a": 0, + "d": 1 + }, + "mne/connectivity/__init__.py": { + "a": 0, + "d": 6 + }, + "mne/connectivity/effective.py": { + "a": 0, + "d": 159 + }, + "mne/connectivity/envelope.py": { + "a": 0, + "d": 154 + }, + "mne/connectivity/spectral.py": { + "a": 0, + "d": 1094 + }, + "mne/connectivity/tests/__init__.py": { + "a": 0, + "d": 0 + }, + "mne/connectivity/tests/test_effective.py": { + "a": 0, + "d": 39 + }, + "mne/connectivity/tests/test_envelope.py": { + "a": 0, + "d": 100 + }, + "mne/connectivity/tests/test_spectral.py": { + "a": 0, + "d": 274 + }, + "mne/connectivity/tests/test_utils.py": { + "a": 0, + "d": 56 + }, + "mne/connectivity/utils.py": { + "a": 0, + "d": 97 + }, + "mne/cuda.py": { + "a": 2, + "d": 3 + }, + "mne/datasets/epilepsy_ecog/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/epilepsy_ecog/_data.py": { + "a": 3, + "d": 13 + }, + "mne/datasets/fnirs_motor/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/fnirs_motor/fnirs_motor.py": { + "a": 3, + "d": 13 + }, + "mne/datasets/multimodal/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/multimodal/multimodal.py": { + "a": 3, + "d": 12 + }, + "mne/datasets/opm/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/opm/opm.py": { + "a": 3, + "d": 12 + }, + "mne/datasets/phantom_4dbti/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/phantom_4dbti/phantom_4dbti.py": { + "a": 3, + "d": 13 + }, + "mne/datasets/refmeg_noise/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/refmeg_noise/refmeg_noise.py": { + "a": 3, + "d": 13 + }, + "mne/datasets/sample/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/sample/sample.py": { + "a": 3, + "d": 12 + }, + "mne/datasets/somato/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/somato/somato.py": { + "a": 3, + "d": 12 + }, + "mne/datasets/ssvep/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/datasets/ssvep/ssvep.py": { + "a": 3, + "d": 12 + }, + "mne/datasets/utils.py": { + "a": 0, + "d": 11 + }, + "mne/filter.py": { + "a": 2, + "d": 3 + }, + "mne/fixes.py": { + "a": 4, + "d": 28 + }, + "mne/inverse_sparse/mxne_inverse.py": { + "a": 3, + "d": 4 + }, + "mne/inverse_sparse/mxne_optim.py": { + "a": 7, + "d": 196 + }, + "mne/inverse_sparse/tests/test_mxne_inverse.py": { + "a": 0, + "d": 9 + }, + "mne/inverse_sparse/tests/test_mxne_optim.py": { + "a": 0, + "d": 33 + }, + "mne/tests/test_docstring_parameters.py": { + "a": 1, + "d": 2 + }, + "mne/time_frequency/_stft.py": { + "a": 3, + "d": 4 + }, + "mne/time_frequency/_stockwell.py": { + "a": 4, + "d": 5 + }, + "mne/time_frequency/csd.py": { + "a": 2, + "d": 3 + }, + "mne/time_frequency/multitaper.py": { + "a": 3, + "d": 4 + }, + "mne/time_frequency/tfr.py": { + "a": 1, + "d": 2 + }, + "mne/viz/tests/test_3d.py": { + "a": 1, + "d": 27 + }, + "mne/viz/tests/test_circle.py": { + "a": 1, + "d": 81 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9948.json b/mne-python/source/doc/sphinxext/prs/9948.json new file mode 100644 index 0000000000000000000000000000000000000000..0db1ea092ebc6e884b15af38a756cc8d3bc2010f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9948.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "490b0b8ec2c5b0d2c0a36f0a5151d1b7683d7805", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9949.json b/mne-python/source/doc/sphinxext/prs/9949.json new file mode 100644 index 0000000000000000000000000000000000000000..273348ee6c827394ed06e8841133b5200629d4ea --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9949.json @@ -0,0 +1,103 @@ +{ + "merge_commit_sha": "7892c081b7b26f100a40e934c22971cbd8bcda46", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.10.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.16.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.18.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.20.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.21.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.23.inc": { + "a": 4, + "d": 4 + }, + "doc/changes/0.24.inc": { + "a": 5, + "d": 5 + }, + "doc/changes/0.9.inc": { + "a": 1, + "d": 1 + }, + "mne/io/meas_info.py": { + "a": 5, + "d": 7 + }, + "mne/io/tests/test_meas_info.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/eog.py": { + "a": 2, + "d": 9 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 175 + }, + "mne/preprocessing/nirs/_beer_lambert_law.py": { + "a": 3, + "d": 8 + }, + "mne/preprocessing/nirs/tests/test_beer_lambert_law.py": { + "a": 1, + "d": 5 + }, + "mne/preprocessing/nirs/tests/test_nirs.py": { + "a": 1, + "d": 4 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 0, + "d": 44 + }, + "mne/report/report.py": { + "a": 4, + "d": 374 + }, + "mne/report/tests/test_report.py": { + "a": 0, + "d": 51 + }, + "mne/time_frequency/tfr.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_brain/_brain.py": { + "a": 6, + "d": 22 + }, + "mne/viz/_brain/tests/test_brain.py": { + "a": 0, + "d": 3 + }, + "mne/viz/utils.py": { + "a": 2, + "d": 48 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/995.json b/mne-python/source/doc/sphinxext/prs/995.json new file mode 100644 index 0000000000000000000000000000000000000000..803784a2d4cba0e3ef8766b725fe36d305c20f64 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/995.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "1d0412f3b7b0109b45c65eb1ca1c2bc89567894e", + "authors": [ + { + "n": "Alexandre Gramfort", + "e": "alexandre.gramfort@m4x.org" + } + ], + "changes": { + "examples/plot_from_raw_to_epochs_to_evoked.py": { + "a": 1, + "d": 2 + }, + "mne/epochs.py": { + "a": 78, + "d": 63 + }, + "mne/fiff/constants.py": { + "a": 2, + "d": 2 + }, + "mne/tests/test_epochs.py": { + "a": 61, + "d": 30 + }, + "mne/viz.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9950.json b/mne-python/source/doc/sphinxext/prs/9950.json new file mode 100644 index 0000000000000000000000000000000000000000..7615ad4217e765ba82fcdbbea81bbe95682d77eb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9950.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "c2ee7ae2d50f4de4558f305f53d1bbc7b64a6193", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "mne/tests/test_surface.py": { + "a": 6, + "d": 6 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9951.json b/mne-python/source/doc/sphinxext/prs/9951.json new file mode 100644 index 0000000000000000000000000000000000000000..71d103de47cd8c7906e3ee91a58b73237a919364 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9951.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0eb4aa64228bb55b79d521a827bc3d2644539564", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9952.json b/mne-python/source/doc/sphinxext/prs/9952.json new file mode 100644 index 0000000000000000000000000000000000000000..d3fb312d6e92cf4680d5b2ea874a859a42ae16c8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9952.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "c2aaaa8aad83d62ee36b7030bca56d50315020e4", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/gui/_ieeg_locate_gui.py": { + "a": 51, + "d": 3 + }, + "mne/gui/tests/test_ieeg_locate_gui.py": { + "a": 7, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9955.json b/mne-python/source/doc/sphinxext/prs/9955.json new file mode 100644 index 0000000000000000000000000000000000000000..97be1d5465b47b614241cd072cc644b8abf90c73 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9955.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "67c7f3e6f33f0ed91fe818754488ab9645b5c30f", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/utils/config.py": { + "a": 1, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9956.json b/mne-python/source/doc/sphinxext/prs/9956.json new file mode 100644 index 0000000000000000000000000000000000000000..2b8f756f9736db068ce0fe8e6f2949a261dbb110 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9956.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4a7d2a9b1e69da8ac14a5e6de7510d79126431d6", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "requirements_doc.txt": { + "a": 1, + "d": 1 + }, + "tutorials/epochs/60_make_fixed_length_epochs.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9957.json b/mne-python/source/doc/sphinxext/prs/9957.json new file mode 100644 index 0000000000000000000000000000000000000000..71ab6c93d4f5947f434abe92a39b892eb4d1e998 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9957.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "81fa0411b8ec68985c92b182d91a561d5407ad8c", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 4, + "d": 3 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9959.json b/mne-python/source/doc/sphinxext/prs/9959.json new file mode 100644 index 0000000000000000000000000000000000000000..d52bf27f5e64f61dea62287bbb77aaab3ec47ee2 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9959.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "4d1510388a66b2d8fffa0992e12bb8611aa09a9e", + "authors": [ + { + "n": "Adam Li", + "e": null + } + ], + "changes": { + "doc/changes/0.19.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.23.inc": { + "a": 1, + "d": 1 + }, + "doc/visualization.rst": { + "a": 0, + "d": 1 + }, + "mne/utils/__init__.py": { + "a": 0, + "d": 7 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 90 + }, + "mne/viz/__init__.py": { + "a": 2, + "d": 4 + }, + "mne/viz/backends/renderer.py": { + "a": 0, + "d": 2 + }, + "mne/viz/circle.py": { + "a": 1, + "d": 112 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9960.json b/mne-python/source/doc/sphinxext/prs/9960.json new file mode 100644 index 0000000000000000000000000000000000000000..da16190a6a59de58ba9573e1376ec9438c92b055 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9960.json @@ -0,0 +1,187 @@ +{ + "merge_commit_sha": "ad095ba6e0e5b97ddbbb0def3846fa8551add30d", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Martin Schulz", + "e": "dev@earthman-music.de" + } + ], + "changes": { + ".circleci/config.yml": { + "a": 10, + "d": 4 + }, + ".gitignore": { + "a": 1, + "d": 0 + }, + "Makefile": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "doc/conf.py": { + "a": 16, + "d": 0 + }, + "examples/inverse/compute_mne_inverse_raw_in_label.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/source_power_spectrum.py": { + "a": 1, + "d": 1 + }, + "examples/time_frequency/source_space_time_frequency.py": { + "a": 1, + "d": 1 + }, + "mne/conftest.py": { + "a": 20, + "d": 2 + }, + "mne/epochs.py": { + "a": 1, + "d": 1 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/ica.py": { + "a": 1, + "d": 1 + }, + "mne/preprocessing/tests/test_ica.py": { + "a": 6, + "d": 7 + }, + "mne/report/report.py": { + "a": 8, + "d": 6 + }, + "mne/tests/test_epochs.py": { + "a": 1, + "d": 3 + }, + "mne/utils/config.py": { + "a": 2, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 3 + }, + "mne/utils/tests/test_config.py": { + "a": 2, + "d": 2 + }, + "mne/viz/__init__.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_figure.py": { + "a": 24, + "d": 9 + }, + "mne/viz/_mpl_figure.py": { + "a": 5, + "d": 1 + }, + "mne/viz/_scraper.py": { + "a": 57, + "d": 0 + }, + "mne/viz/backends/_utils.py": { + "a": 1, + "d": 1 + }, + "mne/viz/epochs.py": { + "a": 5, + "d": 5 + }, + "mne/viz/ica.py": { + "a": 6, + "d": 5 + }, + "mne/viz/raw.py": { + "a": 5, + "d": 11 + }, + "mne/viz/tests/test_epochs.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_figure.py": { + "a": 1, + "d": 1 + }, + "mne/viz/tests/test_ica.py": { + "a": 15, + "d": 15 + }, + "mne/viz/tests/test_scraper.py": { + "a": 24, + "d": 0 + }, + "mne/viz/utils.py": { + "a": 33, + "d": 10 + }, + "tools/circleci_dependencies.sh": { + "a": 1, + "d": 0 + }, + "tutorials/epochs/50_epochs_to_data_frame.py": { + "a": 6, + "d": 0 + }, + "tutorials/evoked/30_eeg_erp.py": { + "a": 2, + "d": 1 + }, + "tutorials/intro/10_overview.py": { + "a": 2, + "d": 2 + }, + "tutorials/preprocessing/15_handling_bad_channels.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/20_rejecting_bad_data.py": { + "a": 1, + "d": 1 + }, + "tutorials/preprocessing/30_filtering_resampling.py": { + "a": 3, + "d": 2 + }, + "tutorials/preprocessing/40_artifact_correction_ica.py": { + "a": 2, + "d": 1 + }, + "tutorials/preprocessing/45_projectors_background.py": { + "a": 4, + "d": 2 + }, + "tutorials/preprocessing/50_artifact_correction_ssp.py": { + "a": 6, + "d": 3 + }, + "tutorials/preprocessing/55_setting_eeg_reference.py": { + "a": 4, + "d": 2 + }, + "tutorials/raw/30_annotate_raw.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9962.json b/mne-python/source/doc/sphinxext/prs/9962.json new file mode 100644 index 0000000000000000000000000000000000000000..69179252733357e39546b57a22e7be2a8c78d7b4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9962.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "0dd33332144db31a087ccd535fc52bef7e3ada89", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "azure-pipelines.yml": { + "a": 8, + "d": 2 + }, + "environment.yml": { + "a": 2, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9963.json b/mne-python/source/doc/sphinxext/prs/9963.json new file mode 100644 index 0000000000000000000000000000000000000000..bfc7e8e17120ca2e61a619288d5998f9b9f1a06b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9963.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "1be2f5619ab4cd9661a8de9442db47eadeab22ab", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_templates/homepage.html": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9964.json b/mne-python/source/doc/sphinxext/prs/9964.json new file mode 100644 index 0000000000000000000000000000000000000000..541062cd32e06ac3f26a7f7844f7b683bbe22cad --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9964.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6ab3cfb90d330d1779dc4df061149362042645d9", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/_templates/homepage.html": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9966.json b/mne-python/source/doc/sphinxext/prs/9966.json new file mode 100644 index 0000000000000000000000000000000000000000..d841fa8f70350b3886600e0e115504b4d109dd60 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9966.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "8d3f48b776459affc0a7ce1314f1abeb65d03986", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9968.json b/mne-python/source/doc/sphinxext/prs/9968.json new file mode 100644 index 0000000000000000000000000000000000000000..4641a7bef55f18b47631ede39eeeffb78d058ca1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9968.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "8ee595239fb0b5a04da04d189a4c708b4fc0d4f4", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/forward/_make_forward.py": { + "a": 1, + "d": 1 + }, + "mne/forward/tests/test_make_forward.py": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9969.json b/mne-python/source/doc/sphinxext/prs/9969.json new file mode 100644 index 0000000000000000000000000000000000000000..98ba9d472400aff740e458e79701e0ad0076bc74 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9969.json @@ -0,0 +1,51 @@ +{ + "merge_commit_sha": "8d24f39220d6b2080f4837ccb9a37e2e37035e35", + "authors": [ + { + "n": "Adam Li", + "e": null + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Adam Li", + "e": "adam2392@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 187, + "d": 1 + }, + "mne/tests/test_epochs.py": { + "a": 194, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9970.json b/mne-python/source/doc/sphinxext/prs/9970.json new file mode 100644 index 0000000000000000000000000000000000000000..934f3d01970599b68d2b91faa57882be3b170e43 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9970.json @@ -0,0 +1,39 @@ +{ + "merge_commit_sha": "b470ddbd0eafcf18fa1af40fafa641b10b82c2d6", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/0.24.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 53, + "d": 17 + }, + "mne/report/tests/test_report.py": { + "a": 36, + "d": 0 + }, + "tutorials/intro/70_report.py": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9972.json b/mne-python/source/doc/sphinxext/prs/9972.json new file mode 100644 index 0000000000000000000000000000000000000000..b7748b95f993b1077478f6d821afb003d75c9bc8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9972.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "83d25a31d715b086f6c6e6fad3d082c5815562fa", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/gui/__init__.py": { + "a": 8, + "d": 8 + }, + "mne/gui/_coreg.py": { + "a": 7, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 20, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 2, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9973.json b/mne-python/source/doc/sphinxext/prs/9973.json new file mode 100644 index 0000000000000000000000000000000000000000..33990833a9705803cc875927ecca2d76773f6803 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9973.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "09621ea3d14b40392744d21b47bc40943e756987", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "mne/externals/pymatreader/pymatreader.py": { + "a": 2, + "d": 3 + }, + "mne/externals/pymatreader/utils.py": { + "a": 11, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 5, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/viz/_3d.py": { + "a": 4, + "d": 1 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9975.json b/mne-python/source/doc/sphinxext/prs/9975.json new file mode 100644 index 0000000000000000000000000000000000000000..5d121ab564ff54cab8b2f58adfbfa1bdb6804b2d --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9975.json @@ -0,0 +1,63 @@ +{ + "merge_commit_sha": "7169435c716581d51fd407f96efa79eb6170a48e", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 5, + "d": 2 + }, + "mne/export/_egimff.py": { + "a": 14, + "d": 2 + }, + "mne/export/_export.py": { + "a": 18, + "d": 5 + }, + "mne/export/tests/test_export.py": { + "a": 35, + "d": 5 + }, + "mne/io/base.py": { + "a": 6, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9976.json b/mne-python/source/doc/sphinxext/prs/9976.json new file mode 100644 index 0000000000000000000000000000000000000000..47435c0d491e784617744c383959d8e947ffa1ee --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9976.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "0335fc7cb480dc8e6cd70ac2cb400678dabbac1a", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9977.json b/mne-python/source/doc/sphinxext/prs/9977.json new file mode 100644 index 0000000000000000000000000000000000000000..a79706d632078a7d4ef98c82ddc77a1f0a43d4a9 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9977.json @@ -0,0 +1,131 @@ +{ + "merge_commit_sha": "d995aa2aa8361ef29d2ffb896fc2387ed1cde2cc", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Mathieu Scheltienne", + "e": "73893616+mscheltienne@users.noreply.github.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/0.18.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/0.24.inc": { + "a": 4, + "d": 0 + }, + "doc/changes/names.inc": { + "a": 0, + "d": 2 + }, + "doc/conf.py": { + "a": 1, + "d": 0 + }, + "mne/epochs.py": { + "a": 5, + "d": 2 + }, + "mne/export/_egimff.py": { + "a": 14, + "d": 2 + }, + "mne/export/_export.py": { + "a": 18, + "d": 5 + }, + "mne/export/tests/test_export.py": { + "a": 35, + "d": 5 + }, + "mne/externals/pymatreader/pymatreader.py": { + "a": 2, + "d": 3 + }, + "mne/externals/pymatreader/utils.py": { + "a": 11, + "d": 2 + }, + "mne/gui/__init__.py": { + "a": 2, + "d": 5 + }, + "mne/gui/_coreg.py": { + "a": 7, + "d": 1 + }, + "mne/io/base.py": { + "a": 6, + "d": 2 + }, + "mne/io/eeglab/eeglab.py": { + "a": 5, + "d": 3 + }, + "mne/minimum_norm/tests/test_inverse.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 20, + "d": 0 + }, + "mne/viz/_3d.py": { + "a": 6, + "d": 6 + }, + "mne/viz/topomap.py": { + "a": 1, + "d": 1 + }, + "tools/github_actions_dependencies.sh": { + "a": 2, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9978.json b/mne-python/source/doc/sphinxext/prs/9978.json new file mode 100644 index 0000000000000000000000000000000000000000..611bf00f8cc4cea1a22aba447ba9939c1ef01f03 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9978.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "4c7fa46e20c071968ef305195738d414925d3442", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 27, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9979.json b/mne-python/source/doc/sphinxext/prs/9979.json new file mode 100644 index 0000000000000000000000000000000000000000..056d90c8cedef719c73a2046c826c538e4db3119 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9979.json @@ -0,0 +1,19 @@ +{ + "merge_commit_sha": "bdedc788b79f7b620167ba6358965ce312ec51be", + "authors": [ + { + "n": "Daniel McCloy", + "e": null + } + ], + "changes": { + "doc/changes/0.18.inc": { + "a": 1, + "d": 1 + }, + "doc/changes/names.inc": { + "a": 0, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/998.json b/mne-python/source/doc/sphinxext/prs/998.json new file mode 100644 index 0000000000000000000000000000000000000000..03715b6289782548f3d6885319c855cca26ca7a6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/998.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "d6a3ae446dc58aa750655681868797d08a89995d", + "authors": [ + { + "n": "Christian Brodbeck", + "e": null + } + ], + "changes": { + "mne/coreg.py": { + "a": 24, + "d": 0 + }, + "mne/fiff/brainvision/brainvision.py": { + "a": 229, + "d": 134 + }, + "mne/fiff/brainvision/tests/test_brainvision.py": { + "a": 64, + "d": 8 + }, + "mne/fiff/kit/__init__.py": { + "a": 2, + "d": 1 + }, + "mne/fiff/kit/coreg.py": { + "a": 0, + "d": 28 + }, + "mne/fiff/kit/kit.py": { + "a": 9, + "d": 4 + }, + "mne/gui/_kit2fiff_gui.py": { + "a": 4, + "d": 2 + }, + "mne/tests/test_coreg.py": { + "a": 14, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9980.json b/mne-python/source/doc/sphinxext/prs/9980.json new file mode 100644 index 0000000000000000000000000000000000000000..6fc5259796a72dbaea952ff29021d57127c231c4 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9980.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "84dd3ff13cf9fad9212456cdb9066ff6e4122142", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/source_estimate.py": { + "a": 31, + "d": 18 + }, + "mne/tests/test_source_estimate.py": { + "a": 4, + "d": 4 + }, + "tutorials/clinical/30_ecog.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9981.json b/mne-python/source/doc/sphinxext/prs/9981.json new file mode 100644 index 0000000000000000000000000000000000000000..4dbe9df66ded00e74afc7fb5faa4341359e13d3f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9981.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "a8522d213cf4b54ef682f2a874065bf62af65fdb", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/conf.py": { + "a": 2, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9982.json b/mne-python/source/doc/sphinxext/prs/9982.json new file mode 100644 index 0000000000000000000000000000000000000000..ca5802d2c59c04eb410fd5aeb7c7113324deb6ef --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9982.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "a50535b709d02acad0d48b9ac4bc701dc5659022", + "authors": [ + { + "n": "Martin G. Schulz", + "e": "dev@mgschulz.de" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 1, + "d": 1 + }, + "mne/utils/config.py": { + "a": 2, + "d": 2 + }, + "mne/utils/docs.py": { + "a": 3, + "d": 2 + }, + "mne/viz/_figure.py": { + "a": 12, + "d": 12 + }, + "mne/viz/raw.py": { + "a": 2, + "d": 2 + }, + "mne/viz/utils.py": { + "a": 0, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9984.json b/mne-python/source/doc/sphinxext/prs/9984.json new file mode 100644 index 0000000000000000000000000000000000000000..8388f0d6d095d47dadc9a1458b7b76471fe79c8c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9984.json @@ -0,0 +1,27 @@ +{ + "merge_commit_sha": "43bef6607a48fb272428d2f4a931df97cae688e1", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + } + ], + "changes": { + "mne/cuda.py": { + "a": 4, + "d": 6 + }, + "mne/filter.py": { + "a": 3, + "d": 2 + }, + "mne/io/base.py": { + "a": 1, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 6, + "d": 4 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9986.json b/mne-python/source/doc/sphinxext/prs/9986.json new file mode 100644 index 0000000000000000000000000000000000000000..c2f776d59e973e456ece1ce1b16b98197c12846b --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9986.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "aa6ad2f6e6d946425ad53ca4b3bb3f8e14080a1d", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "paper.md": { + "a": 7, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9987.json b/mne-python/source/doc/sphinxext/prs/9987.json new file mode 100644 index 0000000000000000000000000000000000000000..84effb8082b6ac08d036041befb1f2d11c601cc6 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9987.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "faf4569ff3d26e79cc439727254460c6bae3aae1", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "tutorials/clinical/10_ieeg_localize.py": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9988.json b/mne-python/source/doc/sphinxext/prs/9988.json new file mode 100644 index 0000000000000000000000000000000000000000..69a81a56409cfdc309e37b9bd87f663db1a67ba1 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9988.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "bf116a35a68e00bee351f2ac7f36ff103d64df0d", + "authors": [ + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "mne/utils/check.py": { + "a": 6, + "d": 5 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9990.json b/mne-python/source/doc/sphinxext/prs/9990.json new file mode 100644 index 0000000000000000000000000000000000000000..f1fd43cb9e7a38fb74e91c67418ccd507ad11d5f --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9990.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "7491370569855921981b993c9ca63c3e72046589", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + }, + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/io/eeglab/eeglab.py": { + "a": 34, + "d": 8 + }, + "mne/io/eeglab/tests/test_eeglab.py": { + "a": 27, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9991.json b/mne-python/source/doc/sphinxext/prs/9991.json new file mode 100644 index 0000000000000000000000000000000000000000..1705ba1eae40d69560bee3244fa1d91081a751db --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9991.json @@ -0,0 +1,31 @@ +{ + "merge_commit_sha": "e44caebb8f50127af268ba152b183267be9a4483", + "authors": [ + { + "n": "Alex Rockhill", + "e": "aprockhill@mailbox.org" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/tests/test_morph.py": { + "a": 3, + "d": 4 + }, + "mne/tests/test_transforms.py": { + "a": 1, + "d": 1 + }, + "mne/transforms.py": { + "a": 17, + "d": 22 + }, + "tutorials/clinical/10_ieeg_localize.py": { + "a": 4, + "d": 9 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9992.json b/mne-python/source/doc/sphinxext/prs/9992.json new file mode 100644 index 0000000000000000000000000000000000000000..04fbfeb7b5570a616f218e6d1c78c150ad59c1be --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9992.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "8c611886826db50f42b4ccbd6fd5718269d1fb31", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9994.json b/mne-python/source/doc/sphinxext/prs/9994.json new file mode 100644 index 0000000000000000000000000000000000000000..ab8a570e8e358368ee597536454556933b3a46bd --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9994.json @@ -0,0 +1,43 @@ +{ + "merge_commit_sha": "6509aa8c75b5d1015983ccc9d229d2d9954a21f7", + "authors": [ + { + "n": "Mathieu Scheltienne", + "e": "mathieu.scheltienne@fcbg.ch" + }, + { + "n": "Daniel McCloy", + "e": "dan@mccloy.info" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/epochs.py": { + "a": 5, + "d": 1 + }, + "mne/export/_egimff.py": { + "a": 10, + "d": 1 + }, + "mne/export/_export.py": { + "a": 24, + "d": 3 + }, + "mne/export/tests/test_export.py": { + "a": 14, + "d": 2 + }, + "mne/io/base.py": { + "a": 5, + "d": 1 + }, + "mne/utils/docs.py": { + "a": 15, + "d": 3 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9995.json b/mne-python/source/doc/sphinxext/prs/9995.json new file mode 100644 index 0000000000000000000000000000000000000000..7c7cabf1f955e0935540321f242f74ef42511cf8 --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9995.json @@ -0,0 +1,35 @@ +{ + "merge_commit_sha": "ca40d9a44b9864cdeb745e7abef3111a610e2652", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + ".github/workflows/codespell_and_flake.yml": { + "a": 2, + "d": 1 + }, + ".github/workflows/compat_minimal.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/compat_old.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/linux_conda.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/linux_pip.yml": { + "a": 1, + "d": 1 + }, + ".github/workflows/macos_conda.yml": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9996.json b/mne-python/source/doc/sphinxext/prs/9996.json new file mode 100644 index 0000000000000000000000000000000000000000..fe7acb0805240d453a5eee9d1572ae5887d97aeb --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9996.json @@ -0,0 +1,15 @@ +{ + "merge_commit_sha": "6cbf4708dcaa196c7a5ddf232ef80c79ea87aa98", + "authors": [ + { + "n": "Eric Larson", + "e": "larson.eric.d@gmail.com" + } + ], + "changes": { + "requirements_doc.txt": { + "a": 1, + "d": 1 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/prs/9998.json b/mne-python/source/doc/sphinxext/prs/9998.json new file mode 100644 index 0000000000000000000000000000000000000000..ab1a0cb79c4c1b006d429462e8323f41b475d57c --- /dev/null +++ b/mne-python/source/doc/sphinxext/prs/9998.json @@ -0,0 +1,23 @@ +{ + "merge_commit_sha": "a2ab1e25fde473dc1e47dcc83e4426ce60397461", + "authors": [ + { + "n": "Marijn van Vliet", + "e": "w.m.vanvliet@gmail.com" + }, + { + "n": "Richard Höchenberger", + "e": "richard.hoechenberger@gmail.com" + } + ], + "changes": { + "doc/changes/latest.inc": { + "a": 2, + "d": 0 + }, + "mne/report/report.py": { + "a": 4, + "d": 2 + } + } +} \ No newline at end of file diff --git a/mne-python/source/doc/sphinxext/related_software.py b/mne-python/source/doc/sphinxext/related_software.py new file mode 100644 index 0000000000000000000000000000000000000000..d1df773b3802c62d20320ab39895f75256422d2f --- /dev/null +++ b/mne-python/source/doc/sphinxext/related_software.py @@ -0,0 +1,243 @@ +"""Create a list of related software. + +To add a package to the list: + +1. Add it to the MNE-installers if possible, and it will automatically appear. +2. If it's on PyPI and not in the MNE-installers, add it to the PYPI_PACKAGES set. +3. If it's not on PyPI, add it to the MANUAL_PACKAGES dictionary. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import functools +import importlib.metadata +import os +import pathlib +import urllib.error +import urllib.request + +import joblib +from docutils import nodes +from docutils.parsers.rst import Directive +from mne_doc_utils import sphinx_logger +from sphinx.errors import ExtensionError +from sphinx.util.display import status_iterator + +# If a package is in MNE-Installers (preferred method), no need to add it here. +# But still add it to doc/sphinxext/related_software.txt! + +# If it's available on PyPI, add it to this set: +PYPI_PACKAGES = { + "cross-domain-saliency-maps", + "meggie", + "niseq", + "sesameeg", + "mne-kit-gui", # moved to its own env in the installers +} + +# If it's not available on PyPI, add it to this dict: +MANUAL_PACKAGES = { + # TODO: These packages are not pip-installable as of 2025/11/19, so we have to + # manually populate them -- should open issues on their package repos. + "best-python": { + "Home-page": "https://github.com/multifunkim/best-python", + "Summary": "The goal of this project is to provide a way to use the best-brainstorm Matlab solvers in Python, compatible with MNE-Python.", # noqa: E501 + }, + "mne-hcp": { + "Home-page": "https://github.com/mne-tools/mne-hcp", + "Summary": "We provide Python tools for seamless integration of MEG data from the Human Connectome Project into the Python ecosystem", # noqa: E501 + }, + "posthoc": { + "Home-page": "https://users.aalto.fi/~vanvlm1/posthoc/python", + "Summary": "post-hoc modification of linear models", + }, + # https://github.com/freesurfer/surfa/pull/66 + "surfa": { + "Home-page": "https://github.com/freesurfer/surfa", + "Summary": "Utilities for medical image and surface processing.", + }, + # This package does not provide wheels, so don't force CircleCI to build it. + # If it eventually provides binary wheels we could add it to + # `tools/circleci_dependencies.sh` and remove from here. + # https://github.com/Eelbrain/Eelbrain/issues/130 + "eelbrain": { + "Home-page": "https://eelbrain.readthedocs.io/en/stable/", + "Summary": "Open-source Python toolkit for MEG and EEG data analysis.", + }, + # TODO: these do not set a valid homepage or documentation page on PyPI + "mffpy": { + "Home-page": "https://github.com/BEL-Public/mffpy", + "Summary": "Reader and Writer for Philips' MFF file format.", + }, + # not on PyPI + "conpy": { + "Home-page": "https://github.com/aaltoimaginglanguage/conpy", + "Summary": "Functions and classes for performing connectivity analysis on MEG data.", # noqa: E501 + }, +} + +REQUIRE_INSTALLED = os.getenv("MNE_REQUIRE_RELATED_SOFTWARE_INSTALLED", "false").lower() +REQUIRE_INSTALLED = REQUIRE_INSTALLED in ("true", "1") +REQUIRE_METADATA = REQUIRE_INSTALLED + +# These packages pip-install with a different name than the package name +RENAMES = { + "python-neo": "neo", + "matplotlib-base": "matplotlib", +} + +_memory = joblib.Memory(location=pathlib.Path(__file__).parent / ".joblib", verbose=0) + + +@_memory.cache(cache_validation_callback=joblib.expires_after(days=7)) +def _get_installer_packages(): + """Get the MNE-Python installer package list YAML.""" + with urllib.request.urlopen( + "https://raw.githubusercontent.com/mne-tools/mne-installers/main/recipes/mne-python/construct.yaml" + ) as url: + data = url.read().decode("utf-8") + # Parse data for list of names of packages + lines = [line.strip() for line in data.splitlines()] + start_idx = lines.index("# <<< BEGIN RELATED SOFTWARE LIST >>>") + 1 + stop_idx = lines.index("# <<< END RELATED SOFTWARE LIST >>>") + packages = [ + # Lines look like + # - mne-ari =0.0.0 + # or similar. + line.split()[1] + for line in lines[start_idx:stop_idx] + if not line.startswith("#") + ] + return packages + + +@functools.lru_cache +def _get_packages() -> dict[str, str]: + try: + packages = _get_installer_packages() + except urllib.error.URLError as exc: # e.g., bad internet connection + if not REQUIRE_METADATA: + sphinx_logger.warning(f"Could not fetch package list, got: {exc}") + return dict() + raise + # There can be duplicates in manual and installer packages because some of the + # PyPI entries for installer packages are incorrect or unusable (see above), so + # we don't enforce that. But PyPI and manual should be disjoint: + dups = set(MANUAL_PACKAGES) & set(PYPI_PACKAGES) + assert not dups, f"Duplicates in MANUAL_PACKAGES and PYPI_PACKAGES: {sorted(dups)}" + # And the installer and PyPI-only should be disjoint: + dups = set(PYPI_PACKAGES) & set(packages) + assert not dups, ( + f"Duplicates in PYPI_PACKAGES and installer packages: {sorted(dups)}" + ) + for name in PYPI_PACKAGES | set(MANUAL_PACKAGES): + if name not in packages: + packages.append(name) + # Simple alphabetical order + packages = sorted(packages, key=lambda x: x.lower()) + packages = [RENAMES.get(package, package) for package in packages] + out = dict() + reasons = [] + for package in status_iterator( + packages, f"Adding {len(packages)} related software packages: " + ): + out[package] = dict() + try: + if package in MANUAL_PACKAGES: + md = MANUAL_PACKAGES[package] + else: + md = importlib.metadata.metadata(package) + except importlib.metadata.PackageNotFoundError: + reasons.append(f"{package}: not found, needs to be installed") + continue # raise a complete error later + else: + # Every project should really have this + do_continue = False + for key in ("Summary",): + if key not in md: + reasons.extend(f"{package}: missing {repr(key)}") + do_continue = True + if do_continue: + continue + # It is annoying to find the home page + url = None + if "Home-page" in md: + url = md["Home-page"] + else: + for prefix in ("homepage", "documentation", "user documentation"): + for key, val in md.items(): + if key == "Project-URL" and val.lower().startswith( + f"{prefix}, " + ): + url = val.split(", ", 1)[1] + break + if url is not None: + break + else: + reasons.append( + f"{package}: could not find Home-page in {sorted(md)}" + ) + continue + out[package]["url"] = url + out[package]["description"] = md["Summary"].replace("\n", "") + if not REQUIRE_INSTALLED: + reasons = [ + reason + for reason in reasons + if "not found, needs to be installed" not in reason + ] + reason_str = "\n".join(reasons) + if reason_str and REQUIRE_METADATA: + raise ExtensionError( + f"Could not find suitable metadata for related software:\n{reason_str}" + ) + + return out + + +class RelatedSoftwareDirective(Directive): + """Create a directive that inserts a bullet list of related software.""" + + def run(self): + """Run the directive.""" + my_list = nodes.bullet_list(bullet="*") + for package, data in _get_packages().items(): + item = nodes.list_item() + if "description" not in data: + para = nodes.paragraph(text=f"{package}") + else: + para = nodes.paragraph(text=f": {data['description']}") + refnode = nodes.reference( + "url", + package, + internal=False, + refuri=data["url"], + ) + para.insert(0, refnode) + item += para + my_list.append(item) + return [my_list] + + +def setup(app): + app.add_directive("related-software", RelatedSoftwareDirective) + # Run it as soon as this is added as a Sphinx extension so that any errors + # / new packages are reported early. The next call in run() will be cached. + _get_packages() + return { + "version": "0.1", + "parallel_read_safe": True, + "parallel_write_safe": True, + } + + +if __name__ == "__main__": # pragma: no cover + # running `python doc/sphinxext/related_software.py` for testing + # require metadata for any installed packages (for debugging) + REQUIRE_METADATA = True + items = list(RelatedSoftwareDirective.run(None)[0].children) + print(f"Got {len(items)} related software packages:") + for item in items: + print(f"- {item.astext()}") diff --git a/mne-python/source/doc/sphinxext/related_software.txt b/mne-python/source/doc/sphinxext/related_software.txt new file mode 100644 index 0000000000000000000000000000000000000000..3bc9b73033d34d6f74c6b9ec51846263f3feb951 --- /dev/null +++ b/mne-python/source/doc/sphinxext/related_software.txt @@ -0,0 +1,40 @@ +# cross-domain-saliency-maps requirements are onerous (torch and tensorflow) +# so we don't add it here, and install it separately in circleci_dependencies.sh +alphaCSC +autoreject +bycycle +conpy +curryreader +dcm2niix +eeg_positions +emd +fooof +meegkit +meggie +mne-ari +mne-bids-pipeline +mne-denoise +mne-faster +mne-features +mne-icalabel +mne-lsl +mne-microstates +mne-nirs +mne-rsa +mnelab +neurodsp +neurokit2 +niseq +nitime +pactools +plotly +pybvrf +pycrostates +pyprep +pyriemann +python-picard +sesameeg +sleepecg +tensorpac +wfdb +yasa diff --git a/mne-python/source/doc/sphinxext/related_software_nodeps.txt b/mne-python/source/doc/sphinxext/related_software_nodeps.txt new file mode 100644 index 0000000000000000000000000000000000000000..712e2834496a217cea4bd877380749a7b8053c1f --- /dev/null +++ b/mne-python/source/doc/sphinxext/related_software_nodeps.txt @@ -0,0 +1,5 @@ +# deps with onerous requirements (tensorflow, wxPython, mayavi, opencv) +cross-domain-saliency-maps +fsleyes +mne-kit-gui +mne-videobrowser diff --git a/mne-python/source/doc/sphinxext/unit_role.py b/mne-python/source/doc/sphinxext/unit_role.py new file mode 100644 index 0000000000000000000000000000000000000000..bf31ddf76c444d5100de6bf4853113389bff600c --- /dev/null +++ b/mne-python/source/doc/sphinxext/unit_role.py @@ -0,0 +1,34 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from docutils import nodes + + +def unit_role(name, rawtext, text, lineno, inliner, options={}, content=[]): # noqa: B006 + parts = text.split() + + def pass_error_to_sphinx(rawtext, text, lineno, inliner): + msg = inliner.reporter.error( + f"The :unit: role requires a space-separated number and unit; got {text}", + line=lineno, + ) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + + # ensure only two parts + if len(parts) != 2: + return pass_error_to_sphinx(rawtext, text, lineno, inliner) + # ensure first part is a number + try: + _ = float(parts[0]) + except ValueError: + return pass_error_to_sphinx(rawtext, text, lineno, inliner) + # input is well-formatted: proceed + node = nodes.Text("\u202f".join(parts)) + return [node], [] + + +def setup(app): + app.add_role("unit", unit_role) + return diff --git a/mne-python/source/environment.yml b/mne-python/source/environment.yml new file mode 100644 index 0000000000000000000000000000000000000000..d6e573c8372cba21547750abe2c95939d202228f --- /dev/null +++ b/mne-python/source/environment.yml @@ -0,0 +1,69 @@ +# THIS FILE IS AUTO-GENERATED BY tools/hooks/update_environment_file.py AND WILL BE OVERWRITTEN +name: mne +channels: + - conda-forge +dependencies: + - python >=3.10 + - antio >=0.5.0 + - curryreader >=0.1.2 + - darkdetect + - decorator >=5.1 + - defusedxml + - dipy >=0.8 + - edfio >=0.4.10 + - eeglabio + - filelock >=3.18.0 + - h5io >=0.2.4 + - h5py >=2.4 + - imageio >=2.6.1 + - imageio-ffmpeg >=0.4.1 + - ipyevents + - ipympl + - ipython >=2.0,!=8.7.0 + - ipywidgets + - jinja2 >=3.1 + - joblib >=0.8 + - jupyter + - lazy_loader >=0.3 + - mamba + - matplotlib >=3.8 + - mffpy >=0.5.7 + - mne-qt-browser + - nibabel >=2.0 + - nilearn + - nomkl + - numba >=0.35 + - numpy >=1.26,<3 + - openmeeg >=2.5.7 + - packaging + - pandas >=2.2 + - pillow + - pip + - pooch >=1.5 + - pyarrow + - pybv + - pymatreader + - PySide6 !=6.9.1 + - python-neo + - python-picard >=0.4 + - pyvista >=0.43 + - pyvistaqt >=0.11 + - qdarkstyle !=3.2.2 + - qtpy + - scikit-learn >=1.4 + - scipy >=1.12 + - sip + - snirf + - statsmodels >=0.6 + - threadpoolctl + - tqdm >=4.66 + - traitlets + - trame + - trame-vtk + - trame-vuetify + - vtk >=9.2 + - xlrd + - pip: + - nest-asyncio2 + - pymef + - pyobjc-framework-Cocoa >=5.2.0;platform_system=='Darwin' diff --git a/mne-python/source/examples/README.txt b/mne-python/source/examples/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..a73e00373926dd9175056336c6646fbb3397c22a --- /dev/null +++ b/mne-python/source/examples/README.txt @@ -0,0 +1,19 @@ +Examples Gallery +================ + +The examples gallery provides working code samples demonstrating various +analysis and visualization techniques. These examples often lack the narrative +explanations seen in the tutorials, and do not follow any specific order. These +examples are a useful way to discover new analysis or plotting ideas, or to see +how a particular technique you’ve read about can be applied using MNE-Python. + +.. note:: + If example-scripts contain plots and are run locally, using the + interactive interactive flag with ``python -i tutorial_script.py`` + keeps them open. + +.. warning:: + + These examples sometimes use simulations or shortcuts (such as intentionally + adding noise to recordings) to illustrate a point. Use caution when + copy-pasting code samples. diff --git a/mne-python/source/examples/connectivity/README.txt b/mne-python/source/examples/connectivity/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..1d1630fe8cbd034a73aafd884572c6b2c0933e6a --- /dev/null +++ b/mne-python/source/examples/connectivity/README.txt @@ -0,0 +1,10 @@ + +Connectivity Analysis Examples +------------------------------ + +Examples demonstrating connectivity analysis in sensor and source space. + +.. note:: + Connectivity functionality has moved into the + :mod:`mne-connectivity:mne_connectivity` package. Examples can be found at + :doc:`mne-connectivity:auto_examples/index`. diff --git a/mne-python/source/examples/datasets/README.txt b/mne-python/source/examples/datasets/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..983b7effd351dfe81aee095fa28be39adc64ea2b --- /dev/null +++ b/mne-python/source/examples/datasets/README.txt @@ -0,0 +1,5 @@ + +Examples on open datasets +------------------------- + +Some demos on common/public datasets using MNE. diff --git a/mne-python/source/examples/datasets/brainstorm_data.py b/mne-python/source/examples/datasets/brainstorm_data.py new file mode 100644 index 0000000000000000000000000000000000000000..ab5499fea7176c52514371871b7240e0e1ce2916 --- /dev/null +++ b/mne-python/source/examples/datasets/brainstorm_data.py @@ -0,0 +1,90 @@ +""" +.. _ex-brainstorm-raw: + +===================================== +Brainstorm raw (median nerve) dataset +===================================== + +Here we compute the evoked from raw for the Brainstorm +tutorial dataset. For comparison, see :footcite:`TadelEtAl2011` and +https://neuroimage.usc.edu/brainstorm/Tutorials/MedianNerveCtf. +""" + +# Authors: Mainak Jas +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.datasets.brainstorm import bst_raw +from mne.io import read_raw_ctf + +print(__doc__) + +tmin, tmax, event_id = -0.1, 0.3, 2 # take right-hand somato +reject = dict(mag=4e-12, eog=250e-6) + +data_path = bst_raw.data_path() + +raw_path = data_path / "MEG" / "bst_raw" / "subj001_somatosensory_20111109_01_AUX-f.ds" +# Here we crop to half the length to save memory +raw = read_raw_ctf(raw_path).crop(0, 120).load_data() +raw.plot() + +# set EOG channel +raw.set_channel_types({"EEG058": "eog"}) +raw.set_eeg_reference("average", projection=True) + +# show power line interference and remove it +raw.compute_psd(tmax=60).plot( + average=False, amplitude=False, picks="data", exclude="bads" +) +raw.notch_filter(np.arange(60, 181, 60), fir_design="firwin") + +events = mne.find_events(raw, stim_channel="UPPT001") + +# pick MEG channels +picks = mne.pick_types( + raw.info, meg=True, eeg=False, stim=False, eog=True, exclude="bads" +) + +# Compute epochs +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + reject=reject, + preload=False, +) + +# compute evoked +evoked = epochs.average() + +# remove physiological artifacts (eyeblinks, heartbeats) using SSP on baseline +evoked.add_proj(mne.compute_proj_evoked(evoked.copy().crop(tmax=0))) +evoked.apply_proj() + +# fix stim artifact +mne.preprocessing.fix_stim_artifact(evoked) + +# correct delays due to hardware (stim artifact is at 4 ms) +evoked.shift_time(-0.004) + +# plot the result +evoked.plot(time_unit="s") + +# show topomaps +evoked.plot_topomap(times=np.array([0.016, 0.030, 0.060, 0.070]), time_unit="s") + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/datasets/hf_sef_data.py b/mne-python/source/examples/datasets/hf_sef_data.py new file mode 100644 index 0000000000000000000000000000000000000000..44aa6e8f9a48a4cbe2e594b0bef4ae32b956f5fa --- /dev/null +++ b/mne-python/source/examples/datasets/hf_sef_data.py @@ -0,0 +1,40 @@ +""" +.. _ex-hf-sef-data: + +============== +HF-SEF dataset +============== + +This example looks at high-frequency SEF responses. +""" +# Author: Jussi Nurminen (jnu@iki.fi) +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import os + +import mne +from mne.datasets import hf_sef + +fname_evoked = os.path.join(hf_sef.data_path(), "MEG/subject_b/hf_sef_15min-ave.fif") + +print(__doc__) + +# %% +# Read evoked data +evoked = mne.Evoked(fname_evoked) + +# %% +# Create a highpass filtered version +evoked_hp = evoked.copy() +evoked_hp.filter(l_freq=300, h_freq=None) + +# %% +# Compare high-pass filtered and unfiltered data on a single channel +ch = "MEG0443" +pick = evoked.ch_names.index(ch) +edi = {"HF": evoked_hp, "Regular": evoked} +mne.viz.plot_compare_evokeds(edi, picks=pick) diff --git a/mne-python/source/examples/datasets/kernel_phantom.py b/mne-python/source/examples/datasets/kernel_phantom.py new file mode 100644 index 0000000000000000000000000000000000000000..da17f708454ea1d662665569b45ec6ebea46f6a8 --- /dev/null +++ b/mne-python/source/examples/datasets/kernel_phantom.py @@ -0,0 +1,108 @@ +""" +.. _ex-kernel-opm-phantom: + +Kernel OPM phantom data +======================= + +In this dataset, a Neuromag phantom was placed inside the Kernel OPM helmet and +stimulated with 7 modules active (121 channels). Here we show some example traces. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +import mne + +data_path = mne.datasets.phantom_kernel.data_path() +fname = data_path / "phantom_32_100nam_raw.fif" +raw = mne.io.read_raw_fif(fname).load_data() +events = mne.find_events(raw, stim_channel="STI101") + +# Bads identified by inspecting averages +raw.info["bads"] = [ + "RC2.bx.ave", + "LC3.bx.ave", + "RC2.by.7", + "RC2.bz.7", + "RC2.bx.4", + "RC2.by.4", + "LC3.bx.5", +] +# Drop the module-average channels +raw.drop_channels([ch_name for ch_name in raw.ch_names if ".ave" in ch_name]) +# Add field correction projectors +raw.add_proj(mne.preprocessing.compute_proj_hfc(raw.info, order=2)) +raw.pick("meg", exclude="bads") +raw.filter(0.5, 40) +epochs = mne.Epochs( + raw, + events, + tmin=-0.1, + tmax=0.25, + decim=5, + preload=True, + baseline=(None, 0), +) +evoked = epochs["17"].average() # a high-SNR dipole for these data +fig = evoked.plot() +t_peak = 0.016 # based on visual inspection of evoked +fig.axes[0].axvline(t_peak, color="k", ls=":", lw=3, zorder=2) + +# %% +# The data covariance has an interesting structure because of densely packed sensors: + +cov = mne.compute_covariance(epochs, tmax=-0.01) +mne.viz.plot_cov(cov, raw.info) + +# %% +# So let's be careful and compute rank ahead of time and regularize: + +rank = mne.compute_rank(epochs, tol=1e-3, tol_kind="relative") +cov = mne.compute_covariance(epochs, tmax=-0.01, rank=rank, method="shrunk") +mne.viz.plot_cov(cov, raw.info) + +# %% +# Look at our alignment: + +sphere = mne.make_sphere_model(r0=(0.0, 0.0, 0.0), head_radius=0.08) +trans = mne.transforms.Transform("head", "mri", np.eye(4)) +align_kwargs = dict( + trans=trans, + bem=sphere, + surfaces={"outer_skin": 0.2}, + show_axes=True, +) +mne.viz.plot_alignment( + raw.info, + coord_frame="meg", + meg=dict(sensors=1.0, helmet=0.05), + **align_kwargs, +) + +# %% +# Let's do dipole fits, which are not great because the dev_head_t is approximate and +# the sensor coverage is sparse: + +data = list() +for ii in range(1, 33): + evoked = epochs[str(ii)][1:-1].average().crop(t_peak, t_peak) + data.append(evoked.data[:, 0]) +evoked = mne.EvokedArray(np.array(data).T, evoked.info, tmin=0.0) +del epochs +dip, residual = mne.fit_dipole(evoked, cov, sphere, n_jobs=None) +actual_pos, actual_ori = mne.dipole.get_phantom_dipoles() +actual_amp = np.ones(len(dip)) # fake amp, needed to create Dipole instance +actual_gof = np.ones(len(dip)) # fake GOF, needed to create Dipole instance +dip_true = mne.Dipole(dip.times, actual_pos, actual_amp, actual_ori, actual_gof) + +fig = mne.viz.plot_alignment( + evoked.info, coord_frame="head", meg="sensors", **align_kwargs +) +mne.viz.plot_dipole_locations( + dipoles=dip_true, mode="arrow", color=(0.0, 0.0, 0.0), fig=fig +) +mne.viz.plot_dipole_locations(dipoles=dip, mode="arrow", color=(0.2, 1.0, 0.5), fig=fig) +mne.viz.set_3d_view(figure=fig, azimuth=30, elevation=70, distance=0.4) diff --git a/mne-python/source/examples/datasets/limo_data.py b/mne-python/source/examples/datasets/limo_data.py new file mode 100644 index 0000000000000000000000000000000000000000..614a13309b91a65588f6a34067b8582a97e95cc6 --- /dev/null +++ b/mne-python/source/examples/datasets/limo_data.py @@ -0,0 +1,313 @@ +""" +.. _ex-limo-data: + +============================================================= +Single trial linear regression analysis with the LIMO dataset +============================================================= + +Here we explore the structure of the data contained in the +`LIMO dataset`_. +This example replicates and extends some of the main analysis +and tools integrated in `LIMO MEEG`_, a MATLAB toolbox originally designed +to interface with EEGLAB_. + +In summary, the example: + +- Fetches epoched data files for a single subject of the LIMO dataset + :footcite:`Rousselet2016`. If the LIMO files are not found on disk, the + fetcher `mne.datasets.limo.load_data()` will automatically download + the files from a remote repository. + +- During import, information about the data (i.e., sampling rate, number of + epochs per condition, number and name of EEG channels per subject, etc.) is + extracted from the LIMO :file:`.mat` files stored on disk and added to the + epochs structure as metadata. + +- Fits linear models on the single subject's data and visualizes inferential + measures to evaluate the significance of the estimated effects. + +.. _LIMO dataset: https://datashare.is.ed.ac.uk/handle/10283/2189?show=full +.. _LIMO MEEG: https://github.com/LIMO-EEG-Toolbox +.. _EEGLAB: https://sccn.ucsd.edu/eeglab/index.php +.. _Fig 1: https://bmcneurosci.biomedcentral.com/articles/10.1186/1471-2202-9-98/figures/1 +.. _least squares: https://docs.scipy.org/doc/scipy/reference/generated/scipy.linalg.lstsq.html +""" # noqa: E501 +# Authors: Jose C. Garcia Alanis +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +import matplotlib.pyplot as plt +import numpy as np + +from mne import combine_evoked +from mne.datasets.limo import load_data +from mne.stats import linear_regression +from mne.viz import plot_compare_evokeds, plot_events + +print(__doc__) + +# subject to use +subj = 1 + +# %% +# About the data +# -------------- +# +# In the original LIMO experiment (see :footcite:`RousseletEtAl2010`), +# participants performed a +# two-alternative forced choice task, discriminating between two face stimuli. +# The same two faces were used during the whole experiment, +# with varying levels of noise added, making the faces more or less +# discernible to the observer (see `Fig 1`_ in :footcite:`RousseletEtAl2008` +# for a similar approach). +# +# The presented faces varied across a noise-signal (or phase-coherence) +# continuum spanning from 0 to 85% in increasing steps of 5%. +# In other words, faces with high phase-coherence (e.g., 85%) were easy to +# identify, while faces with low phase-coherence (e.g., 5%) were hard to +# identify and by extension very hard to discriminate. +# +# +# Load the data +# ------------- +# +# We'll begin by loading the data from subject 1 of the LIMO dataset. + +# This step can take a little while if you're loading the data for the +# first time. +limo_epochs = load_data(subject=subj) + +# %% +# Note that the result of the loading process is an +# :class:`mne.EpochsArray` containing the data ready to interface +# with MNE-Python. + +print(limo_epochs) + +# %% +# Visualize events +# ---------------- +# +# We can visualise the distribution of the face events contained in the +# ``limo_epochs`` structure. Events should appear clearly grouped, as the +# epochs are ordered by condition. + +fig = plot_events(limo_epochs.events, event_id=limo_epochs.event_id) +fig.suptitle("Distribution of events in LIMO epochs") + +# %% +# As it can be seen above, conditions are coded as ``Face/A`` and ``Face/B``. +# Information about the phase-coherence of the presented faces is stored in the +# epochs metadata. These information can be easily accessed by calling +# ``limo_epochs.metadata``. As shown below, the epochs metadata also contains +# information about the presented faces for convenience. + +print(limo_epochs.metadata.head()) + +# %% +# Now let us take a closer look at the information in the epochs +# metadata. + +# We want include all columns in the summary table +epochs_summary = limo_epochs.metadata.describe(include="all").round(3) +print(epochs_summary) + +# %% +# The first column of the summary table above provides more or less the same +# information as the ``print(limo_epochs)`` command we ran before. There are +# 1055 faces (i.e., epochs), subdivided in 2 conditions (i.e., Face A and +# Face B) and, for this particular subject, there are more epochs for the +# condition Face B. +# +# In addition, we can see in the second column that the values for the +# phase-coherence variable range from -1.619 to 1.642. This is because the +# phase-coherence values are provided as a z-scored variable in the LIMO +# dataset. Note that they have a mean of zero and a standard deviation of 1. +# +# +# Visualize condition ERPs +# ------------------------ +# +# Let's plot the ERPs evoked by Face A and Face B, to see how similar they are. + +# only show -250 to 500 ms +ts_args = dict(xlim=(-0.25, 0.5)) + +# plot evoked response for face A +limo_epochs["Face/A"].average().plot_joint( + times=[0.15], title="Evoked response: Face A", ts_args=ts_args +) +# and face B +limo_epochs["Face/B"].average().plot_joint( + times=[0.15], title="Evoked response: Face B", ts_args=ts_args +) + +# %% +# We can also compute the difference wave contrasting Face A and Face B. +# Although, looking at the evoked responses above, we shouldn't expect great +# differences among these face-stimuli. + +# Face A minus Face B +difference_wave = combine_evoked( + [limo_epochs["Face/A"].average(), limo_epochs["Face/B"].average()], weights=[1, -1] +) + +# plot difference wave +difference_wave.plot_joint(times=[0.15], title="Difference Face A - Face B") + +# %% +# As expected, no clear pattern appears when contrasting +# Face A and Face B. However, we could narrow our search a little bit more. +# Since this is a "visual paradigm" it might be best to look at electrodes +# located over the occipital lobe, as differences between stimuli (if any) +# might easier to spot over visual areas. + +# Create a dictionary containing the evoked responses +conditions = ["Face/A", "Face/B"] +evokeds = {condition: limo_epochs[condition].average() for condition in conditions} + +# concentrate analysis an occipital electrodes (e.g. B11) +pick = evokeds["Face/A"].ch_names.index("B11") + +# compare evoked responses +plot_compare_evokeds(evokeds, picks=pick, ylim=dict(eeg=(-15, 7.5))) + +# %% +# We do see a difference between Face A and B, but it is pretty small. +# +# +# Visualize effect of stimulus phase-coherence +# -------------------------------------------- +# +# Since phase-coherence +# determined whether a face stimulus could be easily identified, +# one could expect that faces with high phase-coherence should evoke stronger +# activation patterns along occipital electrodes. + +phase_coh = limo_epochs.metadata["phase-coherence"] +# get levels of phase coherence +levels = sorted(phase_coh.unique()) +# create labels for levels of phase coherence (i.e., 0 - 85%) +labels = [f"{i:.2f}" for i in np.arange(0.0, 0.90, 0.05)] + +# create dict of evokeds for each level of phase-coherence +evokeds = { + label: limo_epochs[phase_coh == level].average() + for level, label in zip(levels, labels) +} + +# pick channel to plot +electrodes = ["C22", "B11"] +# create figures +for electrode in electrodes: + fig, ax = plt.subplots(figsize=(8, 4)) + plot_compare_evokeds( + evokeds, + axes=ax, + ylim=dict(eeg=(-20, 15)), + picks=electrode, + cmap=("Phase coherence", "magma"), + ) + +# %% +# As shown above, there are some considerable differences between the +# activation patterns evoked by stimuli with low vs. high phase-coherence at +# the chosen electrodes. +# +# +# Prepare data for linear regression analysis +# -------------------------------------------- +# +# Before we test the significance of these differences using linear +# regression, we'll interpolate missing channels that were +# dropped during preprocessing of the data. +# Furthermore, we'll drop the EOG channels (marked by the "EXG" prefix) +# present in the data: + +limo_epochs.interpolate_bads(reset_bads=True) +limo_epochs.drop_channels(["EXG1", "EXG2", "EXG3", "EXG4"]) + +# %% +# Define predictor variables and design matrix +# -------------------------------------------- +# +# To run the regression analysis, +# we need to create a design matrix containing information about the +# variables (i.e., predictors) we want to use for prediction of brain +# activity patterns. For this purpose, we'll use the information we have in +# ``limo_epochs.metadata``: phase-coherence and Face A vs. Face B. + +# name of predictors + intercept +predictor_vars = ["face a - face b", "phase-coherence", "intercept"] + +# create design matrix +design = limo_epochs.metadata[["phase-coherence", "face"]].copy() +design["face a - face b"] = np.where(design["face"] == "A", 1, -1) +design["intercept"] = 1 +design = design[predictor_vars] + +# %% +# Now we can set up the linear model to be used in the analysis using +# MNE-Python's :func:`~mne.stats.linear_regression` function. + +reg = linear_regression(limo_epochs, design_matrix=design, names=predictor_vars) + +# %% +# Extract regression coefficients +# ------------------------------- +# +# The results are stored within the object ``reg``, +# which is a dictionary of evoked objects containing +# multiple inferential measures for each predictor in the design matrix. + +print("predictors are:", list(reg)) +print("fields are:", [field for field in getattr(reg["intercept"], "_fields")]) + +# %% +# Plot model results +# ------------------ +# +# Now we can access and plot the results of the linear regression analysis by +# calling :samp:`reg['{}'].{}` and +# using the +# :meth:`~mne.Evoked.plot_joint` method just as we would do with any other +# evoked object. +# Below we can see a clear effect of phase-coherence, with higher +# phase-coherence (i.e., better "face visibility") having a negative effect on +# the activity measured at occipital electrodes around 200 to 250 ms following +# stimulus onset. + +reg["phase-coherence"].beta.plot_joint( + ts_args=ts_args, title="Effect of Phase-coherence", times=[0.23] +) + +# %% +# We can also plot the corresponding T values. + +# use unit=False and scale=1 to keep values at their original +# scale (i.e., avoid conversion to micro-volt). +ts_args = dict(xlim=(-0.25, 0.5), unit=False) +topomap_args = dict(scalings=dict(eeg=1), average=0.05) + +# sphinx_gallery_thumbnail_number = 9 +fig = reg["phase-coherence"].t_val.plot_joint( + ts_args=ts_args, topomap_args=topomap_args, times=[0.23] +) +fig.axes[0].set_ylabel("T-value") + +# %% +# Conversely, there appears to be no (or very small) systematic effects when +# comparing Face A and Face B stimuli. This is largely consistent with the +# difference wave approach presented above. +ts_args = dict(xlim=(-0.25, 0.5)) + +reg["face a - face b"].beta.plot_joint( + ts_args=ts_args, title="Effect of Face A vs. Face B", times=[0.23] +) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/datasets/opm_data.py b/mne-python/source/examples/datasets/opm_data.py new file mode 100644 index 0000000000000000000000000000000000000000..8f68e29d3185e74eb9f23700de99ff2e2565fd5f --- /dev/null +++ b/mne-python/source/examples/datasets/opm_data.py @@ -0,0 +1,154 @@ +""" +.. _ex-opm-somatosensory: + +Optically pumped magnetometer (OPM) data +======================================== + +In this dataset, electrical median nerve stimulation was delivered to the +left wrist of the subject. Somatosensory evoked fields were measured using +nine QuSpin SERF OPMs placed over the right-hand side somatomotor area. Here +we demonstrate how to localize these custom OPM data in MNE. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# sphinx_gallery_thumbnail_number = 4 + +import numpy as np + +import mne + +data_path = mne.datasets.opm.data_path() +subject = "OPM_sample" +subjects_dir = data_path / "subjects" +raw_fname = data_path / "MEG" / "OPM" / "OPM_SEF_raw.fif" +bem_fname = subjects_dir / subject / "bem" / f"{subject}-5120-5120-5120-bem-sol.fif" +fwd_fname = data_path / "MEG" / "OPM" / "OPM_sample-fwd.fif" +coil_def_fname = data_path / "MEG" / "OPM" / "coil_def.dat" + +# %% +# Prepare data for localization +# ----------------------------- +# First we filter and epoch the data: + +raw = mne.io.read_raw_fif(raw_fname, preload=True) +raw.filter(None, 90, h_trans_bandwidth=10.0) +raw.notch_filter(50.0, notch_widths=1) + + +# Set epoch rejection threshold a bit larger than for SQUIDs +reject = dict(mag=2e-10) +tmin, tmax = -0.5, 1 + +# Find median nerve stimulator trigger +event_id = dict(Median=257) +events = mne.find_events(raw, stim_channel="STI101", mask=257, mask_type="and") +picks = mne.pick_types(raw.info, meg=True, eeg=False) +# We use verbose='error' to suppress warning about decimation causing aliasing, +# ideally we would low-pass and then decimate instead +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + verbose="error", + reject=reject, + picks=picks, + proj=False, + decim=10, + preload=True, +) +evoked = epochs.average() +evoked.plot() +cov = mne.compute_covariance(epochs, tmax=0.0) +del epochs, raw + +# %% +# Examine our coordinate alignment for source localization and compute a +# forward operator: +# +# .. note:: The Head<->MRI transform is an identity matrix, as the +# co-registration method used equates the two coordinate +# systems. This mis-defines the head coordinate system +# (which should be based on the LPA, Nasion, and RPA) +# but should be fine for these analyses. + +bem = mne.read_bem_solution(bem_fname) +trans = mne.transforms.Transform("head", "mri") # identity transformation + +# To compute the forward solution, we must +# provide our temporary/custom coil definitions, which can be done as:: +# +# with mne.use_coil_def(coil_def_fname): +# fwd = mne.make_forward_solution( +# raw.info, trans, src, bem, eeg=False, mindist=5.0, +# n_jobs=None, verbose=True) + +fwd = mne.read_forward_solution(fwd_fname) +# use fixed orientation here just to save memory later +mne.convert_forward_solution(fwd, force_fixed=True, copy=False) + +with mne.use_coil_def(coil_def_fname): + fig = mne.viz.plot_alignment( + evoked.info, + trans=trans, + subject=subject, + subjects_dir=subjects_dir, + surfaces=("head", "pial"), + bem=bem, + ) + +mne.viz.set_3d_view( + figure=fig, azimuth=45, elevation=60, distance=0.4, focalpoint=(0.02, 0, 0.04) +) + +# %% +# Perform dipole fitting +# ---------------------- + +# Fit dipoles on a subset of time points +with mne.use_coil_def(coil_def_fname): + dip_opm, _ = mne.fit_dipole( + evoked.copy().crop(0.040, 0.080), cov, bem, trans, verbose=True + ) +idx = np.argmax(dip_opm.gof) +print( + f"Best dipole at t={1000 * dip_opm.times[idx]:0.1f} ms with " + f"{dip_opm.gof[idx]:0.1f}% GOF" +) + +# Plot N20m dipole as an example +dip_opm.plot_locations(trans, subject, subjects_dir, mode="orthoview", idx=idx) + +# %% +# Perform minimum-norm localization +# --------------------------------- +# Due to the small number of sensors, there will be some leakage of activity +# to areas with low/no sensitivity. Constraining the source space to +# areas we are sensitive to might be a good idea. + +inverse_operator = mne.minimum_norm.make_inverse_operator( + evoked.info, fwd, cov, loose=0.0, depth=None +) +del fwd, cov + +method = "MNE" +snr = 3.0 +lambda2 = 1.0 / snr**2 +stc = mne.minimum_norm.apply_inverse( + evoked, inverse_operator, lambda2, method=method, pick_ori=None, verbose=True +) + +# Plot source estimate at time of best dipole fit +brain = stc.plot( + hemi="rh", + views="lat", + subjects_dir=subjects_dir, + initial_time=dip_opm.times[idx], + clim=dict(kind="percent", lims=[99, 99.9, 99.99]), + size=(800, 600), + background="w", +) diff --git a/mne-python/source/examples/datasets/spm_faces_dataset.py b/mne-python/source/examples/datasets/spm_faces_dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..32df7d1a9edd06aa6a00f2de4dc784dc8a116d5f --- /dev/null +++ b/mne-python/source/examples/datasets/spm_faces_dataset.py @@ -0,0 +1,102 @@ +""" +.. _ex-spm-faces: + +========================================== +From raw data to dSPM on SPM Faces dataset +========================================== + +Runs a full pipeline using MNE-Python. This example does quite a bit of processing, so +even on a fast machine it can take several minutes to complete. +""" +# Authors: Alexandre Gramfort +# Denis Engemann +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import mne +from mne import combine_evoked, io +from mne.datasets import spm_face +from mne.minimum_norm import apply_inverse, make_inverse_operator +from mne.preprocessing import ICA, create_eog_epochs + +print(__doc__) + +data_path = spm_face.data_path() +subjects_dir = data_path / "subjects" +spm_path = data_path / "MEG" / "spm" + +# %% +# Load data, filter it, and fit ICA. + +raw_fname = spm_path / "SPM_CTF_MEG_example_faces1_3D.ds" +raw = io.read_raw_ctf(raw_fname, preload=True) # Take first run +# Here to save memory and time we'll downsample heavily -- this is not +# advised for real data as it can effectively jitter events! +raw.resample(100) +raw.filter(1.0, None) # high-pass +reject = dict(mag=5e-12) +ica = ICA(n_components=0.95, max_iter="auto", random_state=0) +ica.fit(raw, reject=reject) +# compute correlation scores, get bad indices sorted by score +eog_epochs = create_eog_epochs(raw, ch_name="MRT31-2908", reject=reject) +eog_inds, eog_scores = ica.find_bads_eog(eog_epochs, ch_name="MRT31-2908") +ica.plot_scores(eog_scores, eog_inds) # see scores the selection is based on +ica.plot_components(eog_inds) # view topographic sensitivity of components +ica.exclude += eog_inds[:1] # we saw the 2nd ECG component looked too dipolar +ica.plot_overlay(eog_epochs.average()) # inspect artifact removal + +# %% +# Epoch data and apply ICA. +events = mne.find_events(raw, stim_channel="UPPT001") +event_ids = {"faces": 1, "scrambled": 2} +tmin, tmax = -0.2, 0.6 +epochs = mne.Epochs( + raw, + events, + event_ids, + tmin, + tmax, + picks="meg", + baseline=None, + preload=True, + reject=reject, +) +del raw +ica.apply(epochs) # clean data, default in place +evoked = [epochs[k].average() for k in event_ids] +contrast = combine_evoked(evoked, weights=[-1, 1]) # Faces - scrambled +evoked.append(contrast) +for e in evoked: + e.plot(ylim=dict(mag=[-400, 400])) + +# %% +# Estimate noise covariance and look at the whitened evoked data + +noise_cov = mne.compute_covariance(epochs, tmax=0, method="shrunk", rank=None) +evoked[0].plot_white(noise_cov) + +# %% +# Compute forward model + +trans_fname = spm_path / "SPM_CTF_MEG_example_faces1_3D_raw-trans.fif" +src = subjects_dir / "spm" / "bem" / "spm-oct-6-src.fif" +bem = subjects_dir / "spm" / "bem" / "spm-5120-5120-5120-bem-sol.fif" +forward = mne.make_forward_solution(contrast.info, trans_fname, src, bem) + +# %% +# Compute inverse solution and plot + +# sphinx_gallery_thumbnail_number = 8 + +snr = 3.0 +lambda2 = 1.0 / snr**2 +inverse_operator = make_inverse_operator(contrast.info, forward, noise_cov) +stc = apply_inverse(contrast, inverse_operator, lambda2, method="dSPM", pick_ori=None) +brain = stc.plot( + hemi="both", + subjects_dir=subjects_dir, + initial_time=0.170, + views=["ven"], + clim={"kind": "value", "lims": [3.0, 6.0, 9.0]}, +) diff --git a/mne-python/source/examples/decoding/README.txt b/mne-python/source/examples/decoding/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..86e0d085091917d5399dc82105e661e2b1ea5eed --- /dev/null +++ b/mne-python/source/examples/decoding/README.txt @@ -0,0 +1,5 @@ + +Machine Learning (Decoding, Encoding, and MVPA) +----------------------------------------------- + +Decoding, encoding, and general machine learning examples. diff --git a/mne-python/source/examples/decoding/decoding_csp_eeg.py b/mne-python/source/examples/decoding/decoding_csp_eeg.py new file mode 100644 index 0000000000000000000000000000000000000000..758c674e16e157095b404b03a5317cb57e5f31f3 --- /dev/null +++ b/mne-python/source/examples/decoding/decoding_csp_eeg.py @@ -0,0 +1,147 @@ +""" +.. _ex-decoding-csp-eeg: + +=========================================================================== +Motor imagery decoding from EEG data using the Common Spatial Pattern (CSP) +=========================================================================== + +Decoding of motor imagery applied to EEG data decomposed using CSP. A +classifier is then applied to features extracted on CSP-filtered signals. + +See https://en.wikipedia.org/wiki/Common_spatial_pattern and +:footcite:`Koles1991`. The EEGBCI dataset is documented in +:footcite:`SchalkEtAl2004` and on the +`PhysioNet documentation page `_. +The dataset is available at PhysioNet :footcite:`GoldbergerEtAl2000`. +""" + +# Authors: Martin Billinger +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from sklearn.discriminant_analysis import LinearDiscriminantAnalysis +from sklearn.model_selection import ShuffleSplit, cross_val_score +from sklearn.pipeline import Pipeline + +from mne import Epochs, pick_types +from mne.channels import make_standard_montage +from mne.datasets import eegbci +from mne.decoding import CSP, get_spatial_filter_from_estimator +from mne.io import concatenate_raws, read_raw_edf + +print(__doc__) + +# ############################################################################# +# # Set parameters and read data + +# avoid classification of evoked responses by using epochs that start 1s after +# cue onset. +tmin, tmax = -1.0, 4.0 +subjects = 1 +runs = [6, 10, 14] # motor imagery: hands vs feet + +raw_fnames = eegbci.load_data(subjects, runs) +raw = concatenate_raws([read_raw_edf(f, preload=True) for f in raw_fnames]) +eegbci.standardize(raw) # set channel names +montage = make_standard_montage("standard_1005") +raw.set_montage(montage) +raw.annotations.rename(dict(T1="hands", T2="feet")) # as documented on PhysioNet +raw.set_eeg_reference(projection=True) + +# Apply band-pass filter +raw.filter(7.0, 30.0, fir_design="firwin", skip_by_annotation="edge") + +picks = pick_types(raw.info, meg=False, eeg=True, stim=False, eog=False, exclude="bads") + +# Read epochs (train will be done only between 1 and 2s) +# Testing will be done with a running classifier +epochs = Epochs( + raw, + event_id=["hands", "feet"], + tmin=tmin, + tmax=tmax, + proj=True, + picks=picks, + baseline=None, + preload=True, +) +epochs_train = epochs.copy().crop(tmin=1.0, tmax=2.0) +labels = epochs.events[:, -1] - 2 + +# %% +# Classification with linear discrimant analysis + +# Define a monte-carlo cross-validation generator (reduce variance): +scores = [] +epochs_data = epochs.get_data(copy=False) +epochs_data_train = epochs_train.get_data(copy=False) +cv = ShuffleSplit(10, test_size=0.2, random_state=42) +cv_split = cv.split(epochs_data_train) + +# Assemble a classifier +lda = LinearDiscriminantAnalysis() +csp = CSP(n_components=4, reg=None, log=True, norm_trace=False) + +# Use scikit-learn Pipeline with cross_val_score function +clf = Pipeline([("CSP", csp), ("LDA", lda)]) +scores = cross_val_score(clf, epochs_data_train, labels, cv=cv, n_jobs=None) + +# Printing the results +class_balance = np.mean(labels == labels[0]) +class_balance = max(class_balance, 1.0 - class_balance) +print(f"Classification accuracy: {np.mean(scores)} / Chance level: {class_balance}") + +# plot eigenvalues and patterns estimated on full data for visualization +csp.fit_transform(epochs_data, labels) +spf = get_spatial_filter_from_estimator(csp, info=epochs.info) +spf.plot_scree() +spf.plot_patterns(components=np.arange(4)) + +# %% +# Look at performance over time + +sfreq = raw.info["sfreq"] +w_length = int(sfreq * 0.5) # running classifier: window length +w_step = int(sfreq * 0.1) # running classifier: window step size +w_start = np.arange(0, epochs_data.shape[2] - w_length, w_step) + +scores_windows = [] + +for train_idx, test_idx in cv_split: + y_train, y_test = labels[train_idx], labels[test_idx] + + X_train = csp.fit_transform(epochs_data_train[train_idx], y_train) + X_test = csp.transform(epochs_data_train[test_idx]) + + # fit classifier + lda.fit(X_train, y_train) + + # running classifier: test classifier on sliding window + score_this_window = [] + for n in w_start: + X_test = csp.transform(epochs_data[test_idx][:, :, n : (n + w_length)]) + score_this_window.append(lda.score(X_test, y_test)) + scores_windows.append(score_this_window) + +# Plot scores over time +w_times = (w_start + w_length / 2.0) / sfreq + epochs.tmin + +plt.figure() +plt.plot(w_times, np.mean(scores_windows, 0), label="Score") +plt.axvline(0, linestyle="--", color="k", label="Onset") +plt.axhline(0.5, linestyle="-", color="k", label="Chance") +plt.xlabel("time (s)") +plt.ylabel("classification accuracy") +plt.title("Classification score over time") +plt.legend(loc="lower right") +plt.show() + +############################################################################## +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/decoding/decoding_csp_timefreq.py b/mne-python/source/examples/decoding/decoding_csp_timefreq.py new file mode 100644 index 0000000000000000000000000000000000000000..9c26bf05444859f6ff9361e90d0f939a4ab1f8ed --- /dev/null +++ b/mne-python/source/examples/decoding/decoding_csp_timefreq.py @@ -0,0 +1,187 @@ +""" +.. _ex-decoding-csp-eeg-timefreq: + +==================================================================== +Decoding in time-frequency space using Common Spatial Patterns (CSP) +==================================================================== + +The time-frequency decomposition is estimated by iterating over raw data that +has been band-passed at different frequencies. This is used to compute a +covariance matrix over each epoch or a rolling time-window and extract the CSP +filtered signals. A linear discriminant classifier is then applied to these +signals. +""" +# Authors: Laura Gwilliams +# Jean-Rémi King +# Alex Barachant +# Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from sklearn.discriminant_analysis import LinearDiscriminantAnalysis +from sklearn.model_selection import StratifiedKFold, cross_val_score +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import LabelEncoder + +from mne import Epochs, create_info +from mne.datasets import eegbci +from mne.decoding import CSP +from mne.io import concatenate_raws, read_raw_edf +from mne.time_frequency import AverageTFRArray + +# %% +# Set parameters and read data +subject = 1 +runs = [6, 10, 14] +raw_fnames = eegbci.load_data(subject, runs) +raw = concatenate_raws([read_raw_edf(f) for f in raw_fnames]) +raw.annotations.rename(dict(T1="hands", T2="feet")) + +# Extract information from the raw file +sfreq = raw.info["sfreq"] +raw.pick(picks="eeg", exclude="bads") +raw.load_data() + +# Assemble the classifier using scikit-learn pipeline +clf = make_pipeline( + CSP(n_components=4, reg=None, log=True, norm_trace=False), + LinearDiscriminantAnalysis(), +) +n_splits = 3 # for cross-validation, 5 is better, here we use 3 for speed +cv = StratifiedKFold(n_splits=n_splits, shuffle=True, random_state=42) + +# Classification & time-frequency parameters +tmin, tmax = -0.200, 2.000 +n_cycles = 10.0 # how many complete cycles: used to define window size +min_freq = 8.0 +max_freq = 20.0 +n_freqs = 6 # how many frequency bins to use + +# Assemble list of frequency range tuples +freqs = np.linspace(min_freq, max_freq, n_freqs) # assemble frequencies +freq_ranges = list(zip(freqs[:-1], freqs[1:])) # make freqs list of tuples + +# Infer window spacing from the max freq and number of cycles to avoid gaps +window_spacing = n_cycles / np.max(freqs) / 2.0 +centered_w_times = np.arange(tmin, tmax, window_spacing)[1:] +n_windows = len(centered_w_times) + +# Instantiate label encoder +le = LabelEncoder() + +# %% +# Loop through frequencies, apply classifier and save scores + +# init scores +freq_scores = np.zeros((n_freqs - 1,)) + +# Loop through each frequency range of interest +for freq, (fmin, fmax) in enumerate(freq_ranges): + # Infer window size based on the frequency being used + w_size = n_cycles / ((fmax + fmin) / 2.0) # in seconds + + # Apply band-pass filter to isolate the specified frequencies + raw_filter = raw.copy().filter( + fmin, fmax, fir_design="firwin", skip_by_annotation="edge" + ) + + # Extract epochs from filtered data, padded by window size + epochs = Epochs( + raw_filter, + event_id=["hands", "feet"], + tmin=tmin - w_size, + tmax=tmax + w_size, + proj=False, + baseline=None, + preload=True, + ) + epochs.drop_bad() + y = le.fit_transform(epochs.events[:, 2]) + + X = epochs.get_data(copy=False) + + # Save mean scores over folds for each frequency and time window + freq_scores[freq] = np.mean( + cross_val_score(estimator=clf, X=X, y=y, scoring="roc_auc", cv=cv), axis=0 + ) + +# %% +# Plot frequency results + +plt.bar( + freqs[:-1], freq_scores, width=np.diff(freqs)[0], align="edge", edgecolor="black" +) +plt.xticks(freqs) +plt.ylim([0, 1]) +plt.axhline( + len(epochs["feet"]) / len(epochs), color="k", linestyle="--", label="chance level" +) +plt.legend() +plt.xlabel("Frequency (Hz)") +plt.ylabel("Decoding Scores") +plt.title("Frequency Decoding Scores") + +# %% +# Loop through frequencies and time, apply classifier and save scores + +# init scores +tf_scores = np.zeros((n_freqs - 1, n_windows)) + +# Loop through each frequency range of interest +for freq, (fmin, fmax) in enumerate(freq_ranges): + # Infer window size based on the frequency being used + w_size = n_cycles / ((fmax + fmin) / 2.0) # in seconds + + # Apply band-pass filter to isolate the specified frequencies + raw_filter = raw.copy().filter( + fmin, fmax, fir_design="firwin", skip_by_annotation="edge" + ) + + # Extract epochs from filtered data, padded by window size + epochs = Epochs( + raw_filter, + event_id=["hands", "feet"], + tmin=tmin - w_size, + tmax=tmax + w_size, + proj=False, + baseline=None, + preload=True, + ) + epochs.drop_bad() + y = le.fit_transform(epochs.events[:, 2]) + + # Roll covariance, csp and lda over time + for t, w_time in enumerate(centered_w_times): + # Center the min and max of the window + w_tmin = w_time - w_size / 2.0 + w_tmax = w_time + w_size / 2.0 + + # Crop data into time-window of interest + X = epochs.get_data(tmin=w_tmin, tmax=w_tmax, copy=False) + + # Save mean scores over folds for each frequency and time window + tf_scores[freq, t] = np.mean( + cross_val_score(estimator=clf, X=X, y=y, scoring="roc_auc", cv=cv), axis=0 + ) + +# %% +# Plot time-frequency results + +# Set up time frequency object +av_tfr = AverageTFRArray( + info=create_info(["freq"], sfreq), + data=tf_scores[np.newaxis, :], + times=centered_w_times, + freqs=freqs[1:], + nave=1, +) + +chance = np.mean(y) # set chance level to white in the plot +av_tfr.plot( + [0], vlim=(chance, None), title="Time-Frequency Decoding Scores", cmap=plt.cm.Reds +) diff --git a/mne-python/source/examples/decoding/decoding_rsa_sgskip.py b/mne-python/source/examples/decoding/decoding_rsa_sgskip.py new file mode 100644 index 0000000000000000000000000000000000000000..1daaabb9619c7013c484899cf8e4d4d7a148e5ba --- /dev/null +++ b/mne-python/source/examples/decoding/decoding_rsa_sgskip.py @@ -0,0 +1,194 @@ +""" +.. _ex-rsa-noplot: + +==================================== +Representational Similarity Analysis +==================================== + +Representational Similarity Analysis is used to perform summary statistics +on supervised classifications where the number of classes is relatively high. +It consists in characterizing the structure of the confusion matrix to infer +the similarity between brain responses and serves as a proxy for characterizing +the space of mental representations +:footcite:`Shepard1980,LaaksoCottrell2000,KriegeskorteEtAl2008`. + +In this example, we perform RSA on responses to 24 object images (among +a list of 92 images). Subjects were presented with images of human, animal +and inanimate objects :footcite:`CichyEtAl2014`. Here we use the 24 unique +images of faces and body parts. + +.. note:: this example will download a very large (~6GB) file, so we will not + build the images below. +""" + +# Authors: Jean-Rémi King +# Jaakko Leppakangas +# Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from pandas import read_csv +from sklearn.linear_model import LogisticRegression +from sklearn.manifold import MDS +from sklearn.metrics import roc_auc_score +from sklearn.model_selection import StratifiedKFold +from sklearn.multiclass import OneVsRestClassifier +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import StandardScaler + +import mne +from mne.datasets import visual_92_categories +from mne.io import concatenate_raws, read_raw_fif + +print(__doc__) + +data_path = visual_92_categories.data_path() + +# Define stimulus - trigger mapping +fname = data_path / "visual_stimuli.csv" +conds = read_csv(fname) +print(conds.head(5)) + +############################################################################## +# Let's restrict the number of conditions to speed up computation +max_trigger = 24 +conds = conds[:max_trigger] # take only the first 24 rows + +############################################################################## +# Define stimulus - trigger mapping +conditions = [] +for c in conds.values: + cond_tags = list(c[:2]) + cond_tags += [ + ("not-" if i == 0 else "") + conds.columns[k] for k, i in enumerate(c[2:], 2) + ] + conditions.append("/".join(map(str, cond_tags))) +print(conditions[:10]) + +############################################################################## +# Let's make the event_id dictionary +event_id = dict(zip(conditions, conds.trigger + 1)) +event_id["0/human bodypart/human/not-face/animal/natural"] + +############################################################################## +# Read MEG data +n_runs = 4 # 4 for full data (use less to speed up computations) +fnames = [data_path / f"sample_subject_{b}_tsss_mc.fif" for b in range(n_runs)] +raws = [ + read_raw_fif(fname, verbose="error", on_split_missing="ignore") for fname in fnames +] # ignore filename warnings +raw = concatenate_raws(raws) + +events = mne.find_events(raw, min_duration=0.002) + +events = events[events[:, 2] <= max_trigger] + +############################################################################## +# Epoch data +picks = mne.pick_types(raw.info, meg=True) +epochs = mne.Epochs( + raw, + events=events, + event_id=event_id, + baseline=None, + picks=picks, + tmin=-0.1, + tmax=0.500, + preload=True, +) + +############################################################################## +# Let's plot some conditions +epochs["face"].average().plot() +epochs["not-face"].average().plot() + +############################################################################## +# Representational Similarity Analysis (RSA) is a neuroimaging-specific +# appelation to refer to statistics applied to the confusion matrix +# also referred to as the representational dissimilarity matrices (RDM). +# +# Compared to the approach from Cichy et al. we'll use a multiclass +# classifier (Multinomial Logistic Regression) while the paper uses +# all pairwise binary classification task to make the RDM. +# Also we use here the ROC-AUC as performance metric while the +# paper uses accuracy. Finally here for the sake of time we use +# RSA on a window of data while Cichy et al. did it for all time +# instants separately. + +# Classify using the average signal in the window 50ms to 300ms +# to focus the classifier on the time interval with best SNR. +clf = make_pipeline( + StandardScaler(), + OneVsRestClassifier(LogisticRegression(C=1)), +) +X = epochs.copy().crop(0.05, 0.3).get_data().mean(axis=2) +y = epochs.events[:, 2] + +classes = set(y) +cv = StratifiedKFold(n_splits=5, random_state=0, shuffle=True) + +# Compute confusion matrix for each cross-validation fold +y_pred = np.zeros((len(y), len(classes))) +for train, test in cv.split(X, y): + # Fit + clf.fit(X[train], y[train]) + # Probabilistic prediction (necessary for ROC-AUC scoring metric) + y_pred[test] = clf.predict_proba(X[test]) + +############################################################################## +# Compute confusion matrix using ROC-AUC +confusion = np.zeros((len(classes), len(classes))) +for ii, train_class in enumerate(classes): + for jj in range(ii, len(classes)): + confusion[ii, jj] = roc_auc_score(y == train_class, y_pred[:, jj]) + confusion[jj, ii] = confusion[ii, jj] + +############################################################################## +# Plot +labels = [""] * 5 + ["face"] + [""] * 11 + ["bodypart"] + [""] * 6 +fig, ax = plt.subplots(1, layout="constrained") +im = ax.matshow(confusion, cmap="RdBu_r", clim=[0.3, 0.7]) +ax.set_yticks(range(len(classes))) +ax.set_yticklabels(labels) +ax.set_xticks(range(len(classes))) +ax.set_xticklabels(labels, rotation=40, ha="left") +ax.axhline(11.5, color="k") +ax.axvline(11.5, color="k") +plt.colorbar(im) +plt.show() + +############################################################################## +# Confusion matrix related to mental representations have been historically +# summarized with dimensionality reduction using multi-dimensional scaling [1]. +# See how the face samples cluster together. +fig, ax = plt.subplots(1, layout="constrained") +mds = MDS(2, random_state=0, dissimilarity="precomputed") +chance = 0.5 +summary = mds.fit_transform(chance - confusion) +cmap = plt.colormaps["rainbow"] +colors = ["r", "b"] +names = list(conds["condition"].values) +for color, name in zip(colors, set(names)): + sel = np.where([this_name == name for this_name in names])[0] + size = 500 if name == "human face" else 100 + ax.scatter( + summary[sel, 0], + summary[sel, 1], + s=size, + facecolors=color, + label=name, + edgecolors="k", + ) +ax.axis("off") +ax.legend(loc="lower right", scatterpoints=1, ncol=2) +plt.show() + +############################################################################## +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/decoding/decoding_spatio_temporal_source.py b/mne-python/source/examples/decoding/decoding_spatio_temporal_source.py new file mode 100644 index 0000000000000000000000000000000000000000..f724ea97b3bb8296f257f5c2a73dbddb5eaaed82 --- /dev/null +++ b/mne-python/source/examples/decoding/decoding_spatio_temporal_source.py @@ -0,0 +1,146 @@ +""" +.. _ex-dec-st-source: + +========================== +Decoding source space data +========================== + +Decoding to MEG data in source space on the left cortical surface. Here +univariate feature selection is employed for speed purposes to confine the +classification to a small number of potentially relevant features. The +classifier then is trained to selected features of epochs in source space. +""" +# sphinx_gallery_thumbnail_number = 2 + +# Author: Denis A. Engemann +# Alexandre Gramfort +# Jean-Rémi King +# Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from sklearn.feature_selection import SelectKBest, f_classif +from sklearn.linear_model import LogisticRegression +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import StandardScaler + +import mne +from mne.decoding import LinearModel, SlidingEstimator, cross_val_multiscore, get_coef +from mne.minimum_norm import apply_inverse_epochs, read_inverse_operator + +print(__doc__) + +data_path = mne.datasets.sample.data_path() +meg_path = data_path / "MEG" / "sample" +fname_fwd = meg_path / "sample_audvis-meg-oct-6-fwd.fif" +fname_evoked = meg_path / "sample_audvis-ave.fif" +subjects_dir = data_path / "subjects" + +# %% +# Set parameters +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +fname_cov = meg_path / "sample_audvis-cov.fif" +fname_inv = meg_path / "sample_audvis-meg-oct-6-meg-inv.fif" + +tmin, tmax = -0.2, 0.8 +event_id = dict(aud_r=2, vis_r=4) # load contra-lateral conditions + +# Setup for reading the raw data +raw = mne.io.read_raw_fif(raw_fname, preload=True) +raw.filter(None, 10.0, fir_design="firwin") +events = mne.read_events(event_fname) + +# Set up pick list: MEG - bad channels (modify to your needs) +raw.info["bads"] += ["MEG 2443"] # mark bads +picks = mne.pick_types( + raw.info, meg=True, eeg=False, stim=True, eog=True, exclude="bads" +) + +# Read epochs +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + proj=True, + picks=picks, + baseline=(None, 0), + preload=True, + reject=dict(grad=4000e-13, eog=150e-6), + decim=5, +) # decimate to save memory and increase speed + +# %% +# Compute inverse solution +snr = 3.0 +noise_cov = mne.read_cov(fname_cov) +inverse_operator = read_inverse_operator(fname_inv) + +stcs = apply_inverse_epochs( + epochs, + inverse_operator, + lambda2=1.0 / snr**2, + verbose=False, + method="dSPM", + pick_ori="normal", +) + +# %% +# Decoding in sensor space using a logistic regression + +# Retrieve source space data into an array +X = np.array([stc.lh_data for stc in stcs]) # only keep left hemisphere +y = epochs.events[:, 2] + +# prepare a series of classifier applied at each time sample +clf = make_pipeline( + StandardScaler(), # z-score normalization + SelectKBest(f_classif, k=500), # select features for speed + LinearModel(LogisticRegression(C=1, solver="liblinear")), +) +time_decod = SlidingEstimator(clf, scoring="roc_auc") + +# Run cross-validated decoding analyses: +scores = cross_val_multiscore(time_decod, X, y, cv=5, n_jobs=None) + +# Plot average decoding scores of 5 splits +fig, ax = plt.subplots(1) +ax.plot(epochs.times, scores.mean(0), label="score") +ax.axhline(0.5, color="k", linestyle="--", label="chance") +ax.axvline(0, color="k") +plt.legend() + +# %% +# To investigate weights, we need to retrieve the patterns of a fitted model + +# The fitting needs not be cross validated because the weights are based on +# the training sets +time_decod.fit(X, y) + +# Retrieve patterns after inversing the z-score normalization step: +patterns = get_coef(time_decod, "patterns_", inverse_transform=True) + +stc = stcs[0] # for convenience, lookup parameters from first stc +vertices = [stc.lh_vertno, np.array([], int)] # empty array for right hemi +stc_feat = mne.SourceEstimate( + np.abs(patterns), + vertices=vertices, + tmin=stc.tmin, + tstep=stc.tstep, + subject="sample", +) + +brain = stc_feat.plot( + views=["lat"], + transparent=True, + initial_time=0.1, + time_unit="s", + subjects_dir=subjects_dir, +) diff --git a/mne-python/source/examples/decoding/decoding_spoc_CMC.py b/mne-python/source/examples/decoding/decoding_spoc_CMC.py new file mode 100644 index 0000000000000000000000000000000000000000..3accd5b2cd6114b5b777db1bf0c7b71553e232ce --- /dev/null +++ b/mne-python/source/examples/decoding/decoding_spoc_CMC.py @@ -0,0 +1,99 @@ +""" +.. _ex-spoc-cmc: + +==================================== +Continuous Target Decoding with SPoC +==================================== + +Source Power Comodulation (SPoC) :footcite:`DahneEtAl2014` allows to identify +the composition of +orthogonal spatial filters that maximally correlate with a continuous target. + +SPoC can be seen as an extension of the CSP for continuous variables. + +Here, SPoC is applied to decode the (continuous) fluctuation of an +electromyogram from MEG beta activity using data from +`Cortico-Muscular Coherence example of FieldTrip +`_ +""" + +# Author: Alexandre Barachant +# Jean-Rémi King +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +import matplotlib.pyplot as plt +from sklearn.linear_model import Ridge +from sklearn.model_selection import KFold, cross_val_predict +from sklearn.pipeline import make_pipeline + +import mne +from mne import Epochs +from mne.datasets.fieldtrip_cmc import data_path +from mne.decoding import SPoC, get_spatial_filter_from_estimator + +# Define parameters +fname = data_path() / "SubjectCMC.ds" +raw = mne.io.read_raw_ctf(fname) +raw.crop(50.0, 200.0) # crop for memory purposes + +# Filter muscular activity to only keep high frequencies +emg = raw.copy().pick(["EMGlft"]).load_data() +emg.filter(20.0, None) + +# Filter MEG data to focus on beta band +raw.pick(picks=["meg", "ref_meg"]).load_data() +raw.filter(15.0, 30.0) + +# Build epochs as sliding windows over the continuous raw file +events = mne.make_fixed_length_events(raw, id=1, duration=0.75) + +# Epoch length is 1.5 second +meg_epochs = Epochs(raw, events, tmin=0.0, tmax=1.5, baseline=None, detrend=1, decim=12) +emg_epochs = Epochs(emg, events, tmin=0.0, tmax=1.5, baseline=None) + +# Prepare classification +X = meg_epochs.get_data() +y = emg_epochs.get_data().var(axis=2)[:, 0] # target is EMG power + +# Classification pipeline with SPoC spatial filtering and Ridge Regression +spoc = SPoC(n_components=2, log=True, reg="oas", rank="full") +clf = make_pipeline(spoc, Ridge()) +# Define a two fold cross-validation +cv = KFold(n_splits=2, shuffle=False) + +# Run cross validation +y_preds = cross_val_predict(clf, X, y, cv=cv) + +# Plot the True EMG power and the EMG power predicted from MEG data +fig, ax = plt.subplots(1, 1, figsize=[10, 4], layout="constrained") +times = raw.times[meg_epochs.events[:, 0] - raw.first_samp] +ax.plot(times, y_preds, color="b", label="Predicted EMG") +ax.plot(times, y, color="r", label="True EMG") +ax.set_xlabel("Time (s)") +ax.set_ylabel("EMG Power") +ax.set_title("SPoC MEG Predictions") +plt.legend() +plt.show() + +############################################################################## +# Plot the contributions to the detected components (i.e., the forward model) + +spoc.fit(X, y) +spf = get_spatial_filter_from_estimator(spoc, info=meg_epochs.info) +spf.plot_scree() + +# Plot patterns for the first three components +# with largest absolute generalized eigenvalues, +# as we can see on the scree plot +spf.plot_patterns(components=[0, 1, 2]) + + +############################################################################## +# References +# ---------- +# .. footbibliography:: + +# %% diff --git a/mne-python/source/examples/decoding/decoding_time_generalization_conditions.py b/mne-python/source/examples/decoding/decoding_time_generalization_conditions.py new file mode 100644 index 0000000000000000000000000000000000000000..cc9e62f06cfa3f74f04a1a28cd4a1b1ff67e564a --- /dev/null +++ b/mne-python/source/examples/decoding/decoding_time_generalization_conditions.py @@ -0,0 +1,113 @@ +""" +.. _ex-linear-sensor-decoding: + +========================================================================= +Decoding sensor space data with generalization across time and conditions +========================================================================= + +This example runs the analysis described in :footcite:`KingDehaene2014`. It +illustrates how one can fit a linear classifier to identify a discriminatory +topography at a given time instant and subsequently assess whether this linear +model can accurately predict all of the time samples of a second set of conditions. +""" +# Authors: Jean-Rémi King +# Alexandre Gramfort +# Denis Engemann +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +from sklearn.linear_model import LogisticRegression +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import StandardScaler + +import mne +from mne.datasets import sample +from mne.decoding import GeneralizingEstimator + +print(__doc__) + +# Preprocess data +data_path = sample.data_path() +# Load and filter data, set up epochs +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +events_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +raw = mne.io.read_raw_fif(raw_fname, preload=True) +picks = mne.pick_types(raw.info, meg=True, exclude="bads") # Pick MEG channels +raw.filter(1.0, 30.0, fir_design="firwin") # Band pass filtering signals +events = mne.read_events(events_fname) +event_id = { + "Auditory/Left": 1, + "Auditory/Right": 2, + "Visual/Left": 3, + "Visual/Right": 4, +} +tmin = -0.050 +tmax = 0.400 +# decimate to make the example faster to run, but then use verbose='error' in +# the Epochs constructor to suppress warning about decimation causing aliasing +decim = 2 +epochs = mne.Epochs( + raw, + events, + event_id=event_id, + tmin=tmin, + tmax=tmax, + proj=True, + picks=picks, + baseline=None, + preload=True, + reject=dict(mag=5e-12), + decim=decim, + verbose="error", +) + +# %% +# We will train the classifier on all left visual vs auditory trials +# and test on all right visual vs auditory trials. +clf = make_pipeline( + StandardScaler(), + LogisticRegression(solver="liblinear"), # liblinear is faster than lbfgs +) +time_gen = GeneralizingEstimator(clf, scoring="roc_auc", n_jobs=None, verbose=True) + +# Fit classifiers on the epochs where the stimulus was presented to the left. +# Note that the experimental condition y indicates auditory or visual +time_gen.fit(X=epochs["Left"].get_data(copy=False), y=epochs["Left"].events[:, 2] > 2) + +# %% +# Score on the epochs where the stimulus was presented to the right. +scores = time_gen.score( + X=epochs["Right"].get_data(copy=False), y=epochs["Right"].events[:, 2] > 2 +) + +# %% +# Plot +fig, ax = plt.subplots(layout="constrained") +im = ax.matshow( + scores, + vmin=0, + vmax=1.0, + cmap="RdBu_r", + origin="lower", + extent=epochs.times[[0, -1, 0, -1]], +) +ax.axhline(0.0, color="k") +ax.axvline(0.0, color="k") +ax.xaxis.set_ticks_position("bottom") +ax.set_xlabel( + 'Condition: "Right"\nTesting Time (s)', +) +ax.set_ylabel('Condition: "Left"\nTraining Time (s)') +ax.set_title("Generalization across time and condition", fontweight="bold") +fig.colorbar(im, ax=ax, label="Performance (ROC AUC)") +plt.show() + +############################################################################## +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/decoding/decoding_unsupervised_spatial_filter.py b/mne-python/source/examples/decoding/decoding_unsupervised_spatial_filter.py new file mode 100644 index 0000000000000000000000000000000000000000..2fb1a8fec46273cbbeb6a638a48e5b912918ce6a --- /dev/null +++ b/mne-python/source/examples/decoding/decoding_unsupervised_spatial_filter.py @@ -0,0 +1,86 @@ +""" +.. _ex-ica-pca-decoding: + +================================================================== +Analysis of evoked response using ICA and PCA reduction techniques +================================================================== + +This example computes PCA and ICA of evoked or epochs data. Then the +PCA / ICA components, a.k.a. spatial filters, are used to transform +the channel data to new sources / virtual channels. The output is +visualized on the average of all the epochs. +""" +# Authors: Jean-Rémi King +# Asish Panda +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from sklearn.decomposition import PCA, FastICA + +import mne +from mne.datasets import sample +from mne.decoding import UnsupervisedSpatialFilter + +print(__doc__) + +# Preprocess data +data_path = sample.data_path() + +# Load and filter data, set up epochs +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +tmin, tmax = -0.1, 0.3 +event_id = dict(aud_l=1, aud_r=2, vis_l=3, vis_r=4) + +raw = mne.io.read_raw_fif(raw_fname, preload=True) +raw.filter(1, 20, fir_design="firwin") +events = mne.read_events(event_fname) + +picks = mne.pick_types( + raw.info, meg=False, eeg=True, stim=False, eog=False, exclude="bads" +) + +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + proj=False, + picks=picks, + baseline=None, + preload=True, + verbose=False, +) + +X = epochs.get_data(copy=False) + +############################################################################## +# Transform data with PCA computed on the average ie evoked response +pca = UnsupervisedSpatialFilter(PCA(30), average=False) +pca_data = pca.fit_transform(X) +ev = mne.EvokedArray( + np.mean(pca_data, axis=0), + mne.create_info(30, epochs.info["sfreq"], ch_types="eeg"), + tmin=tmin, +) +ev.plot(show=False, window_title="PCA", time_unit="s") + +############################################################################## +# Transform data with ICA computed on the raw epochs (no averaging) +ica = UnsupervisedSpatialFilter(FastICA(30, whiten="unit-variance"), average=False) +ica_data = ica.fit_transform(X) +ev1 = mne.EvokedArray( + np.mean(ica_data, axis=0), + mne.create_info(30, epochs.info["sfreq"], ch_types="eeg"), + tmin=tmin, +) +ev1.plot(show=False, window_title="ICA", time_unit="s") + +plt.show() diff --git a/mne-python/source/examples/decoding/decoding_xdawn_eeg.py b/mne-python/source/examples/decoding/decoding_xdawn_eeg.py new file mode 100644 index 0000000000000000000000000000000000000000..a7d70bcb5bb4c69438f0aeb16849af74227007e6 --- /dev/null +++ b/mne-python/source/examples/decoding/decoding_xdawn_eeg.py @@ -0,0 +1,153 @@ +""" +.. _ex-xdawn-decoding: + +============================ +XDAWN Decoding From EEG data +============================ + +ERP decoding with Xdawn :footcite:`RivetEtAl2009,RivetEtAl2011`. For each event +type, a set of spatial Xdawn filters are trained and applied on the signal. +Channels are concatenated and rescaled to create features vectors that will be +fed into a logistic regression. +""" + +# Authors: Alexandre Barachant +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from sklearn.linear_model import LogisticRegression +from sklearn.metrics import classification_report, confusion_matrix +from sklearn.model_selection import StratifiedKFold +from sklearn.multiclass import OneVsRestClassifier +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import MinMaxScaler + +from mne import Epochs, io, pick_types, read_events +from mne.datasets import sample +from mne.decoding import Vectorizer, XdawnTransformer, get_spatial_filter_from_estimator +from mne.utils import check_version + +print(__doc__) + +data_path = sample.data_path() + +# %% +# Set parameters and read data +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +tmin, tmax = -0.1, 0.3 +event_id = { + "Auditory/Left": 1, + "Auditory/Right": 2, + "Visual/Left": 3, + "Visual/Right": 4, +} +n_filter = 3 + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname, preload=True) +raw.filter(1, 20, fir_design="firwin") +events = read_events(event_fname) + +picks = pick_types(raw.info, meg=False, eeg=True, stim=False, eog=False, exclude="bads") + +epochs = Epochs( + raw, + events, + event_id, + tmin, + tmax, + proj=False, + picks=picks, + baseline=None, + preload=True, + verbose=False, +) + +# Create classification pipeline +kwargs = dict() +if check_version("sklearn", "1.8"): + kwargs["l1_ratio"] = 1 +else: + kwargs["penalty"] = "l1" +clf = make_pipeline( + XdawnTransformer(n_components=n_filter), + Vectorizer(), + MinMaxScaler(), + OneVsRestClassifier(LogisticRegression(solver="liblinear", **kwargs)), +) + +# Get the data and labels +# X is of shape (n_epochs, n_channels, n_times) +X = epochs.get_data(copy=False) +y = epochs.events[:, -1] + +# Cross validator +cv = StratifiedKFold(n_splits=10, shuffle=True, random_state=42) + +# Do cross-validation +preds = np.empty(len(y)) +for train, test in cv.split(epochs, y): + clf.fit(X[train], y[train]) + preds[test] = clf.predict(X[test]) + +# Classification report +target_names = ["aud_l", "aud_r", "vis_l", "vis_r"] +report = classification_report(y, preds, target_names=target_names) +print(report) + +# Normalized confusion matrix +cm = confusion_matrix(y, preds) +cm_normalized = cm.astype(float) / cm.sum(axis=1)[:, np.newaxis] + +# Plot confusion matrix +fig, ax = plt.subplots(1, layout="constrained") +im = ax.imshow(cm_normalized, interpolation="nearest", cmap=plt.cm.Blues) +ax.set(title="Normalized Confusion matrix") +fig.colorbar(im) +tick_marks = np.arange(len(target_names)) +plt.xticks(tick_marks, target_names, rotation=45) +plt.yticks(tick_marks, target_names) +ax.set(ylabel="True label", xlabel="Predicted label") + +# %% +# Patterns of a fitted XdawnTransformer instance (here from the last +# cross-validation fold) can be visualized using SpatialFilter container. + +# Instantiate SpatialFilter +spf = get_spatial_filter_from_estimator( + clf, info=epochs.info, step_name="xdawntransformer" +) + +# Let's first examine the scree plot of generalized eigenvalues +# for each class. +spf.plot_scree(title="") + +# We can see that for all four classes ~five largest components +# capture most of the variance, let's plot their patterns. +# Each class will now return its own figure +components_to_plot = np.arange(5) +figs = spf.plot_patterns( + # Indices of patterns to plot, + # we will plot the first three for each class + components=components_to_plot, + show=False, # to set the titles below +) + +# Set the class titles +event_id_reversed = {v: k for k, v in event_id.items()} +for fig, class_idx in zip(figs, clf[0].classes_): + class_name = event_id_reversed[class_idx] + fig.suptitle(class_name, fontsize=16) + + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/decoding/ems_filtering.py b/mne-python/source/examples/decoding/ems_filtering.py new file mode 100644 index 0000000000000000000000000000000000000000..d1e04e2e0965b71c84dc0cb855afe1d2225adad0 --- /dev/null +++ b/mne-python/source/examples/decoding/ems_filtering.py @@ -0,0 +1,145 @@ +""" +.. _ex-ems-filtering: + +============================================== +Compute effect-matched-spatial filtering (EMS) +============================================== + +This example computes the EMS to reconstruct the time course of the +experimental effect as described in :footcite:`SchurgerEtAl2013`. + +This technique is used to create spatial filters based on the difference +between two conditions. By projecting the trial onto the corresponding spatial +filters, surrogate single trials are created in which multi-sensor activity is +reduced to one time series which exposes experimental effects, if present. + +We will first plot a trials × times image of the single trials and order the +trials by condition. A second plot shows the average time series for each +condition. Finally a topographic plot is created which exhibits the temporal +evolution of the spatial filters. +""" +# Author: Denis Engemann +# Jean-Rémi King +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from sklearn.model_selection import StratifiedKFold + +import mne +from mne import EvokedArray, io +from mne.datasets import sample +from mne.decoding import EMS, compute_ems + +print(__doc__) + +data_path = sample.data_path() + +# Preprocess the data +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +event_ids = {"AudL": 1, "VisL": 3} + +# Read data and create epochs +raw = io.read_raw_fif(raw_fname, preload=True) +raw.filter(0.5, 45, fir_design="firwin") +events = mne.read_events(event_fname) + +raw.pick(["grad", "eog"], exclude="bads") + +epochs = mne.Epochs( + raw, + events, + event_ids, + tmin=-0.2, + tmax=0.5, + baseline=None, + reject=dict(grad=4000e-13, eog=150e-6), + preload=True, +) +epochs.pick("grad") + +# Setup the data to use it a scikit-learn way: +X = epochs.get_data(copy=False) # The MEG data +y = epochs.events[:, 2] # The conditions indices +n_epochs, n_channels, n_times = X.shape + +############################################################################# + +# Initialize EMS transformer +ems = EMS() + +# Initialize the variables of interest +X_transform = np.zeros((n_epochs, n_times)) # Data after EMS transformation +filters = list() # Spatial filters at each time point + +# In the original paper, the cross-validation is a leave-one-out. However, +# we recommend using a Stratified KFold, because leave-one-out tends +# to overfit and cannot be used to estimate the variance of the +# prediction within a given fold. + +for train, test in StratifiedKFold(n_splits=5).split(X, y): + # In the original paper, the z-scoring is applied outside the CV. + # However, we recommend to apply this preprocessing inside the CV. + # Note that such scaling should be done separately for each channels if the + # data contains multiple channel types. + X_scaled = X / np.std(X[train]) + + # Fit and store the spatial filters + ems.fit(X_scaled[train], y[train]) + + # Store filters for future plotting + filters.append(ems.filters_) + + # Generate the transformed data + X_transform[test] = ems.transform(X_scaled[test]) + +# Average the spatial filters across folds +filters = np.mean(filters, axis=0) + +# Plot individual trials +plt.figure() +plt.title("single trial surrogates") +plt.imshow( + X_transform[y.argsort()], + origin="lower", + aspect="auto", + extent=[epochs.times[0], epochs.times[-1], 1, len(X_transform)], + cmap="RdBu_r", +) +plt.xlabel("Time (ms)") +plt.ylabel("Trials (reordered by condition)") + +# Plot average response +plt.figure() +plt.title("Average EMS signal") +mappings = [(key, value) for key, value in event_ids.items()] +for key, value in mappings: + ems_ave = X_transform[y == value] + plt.plot(epochs.times, ems_ave.mean(0), label=key) +plt.xlabel("Time (ms)") +plt.ylabel("a.u.") +plt.legend(loc="best") +plt.show() + +# Visualize spatial filters across time +evoked = EvokedArray(filters, epochs.info, tmin=epochs.tmin) +evoked.plot_topomap(scalings=1) + +############################################################################# +# Note that a similar transformation can be applied with ``compute_ems`` +# However, this function replicates Schurger et al's original paper, and thus +# applies the normalization outside a leave-one-out cross-validation, which we +# recommend not to do. +epochs.equalize_event_counts(event_ids) +X_transform, filters, classes = compute_ems(epochs) + +############################################################################## +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/decoding/linear_model_patterns.py b/mne-python/source/examples/decoding/linear_model_patterns.py new file mode 100644 index 0000000000000000000000000000000000000000..48d679ed1fd98f1a912174d1b73df3c2fcb59af8 --- /dev/null +++ b/mne-python/source/examples/decoding/linear_model_patterns.py @@ -0,0 +1,158 @@ +""" +.. _ex-linear-patterns: + +=============================================================== +Linear classifier on sensor data with plot patterns and filters +=============================================================== + +Here decoding, a.k.a MVPA or supervised machine learning, is applied to M/EEG +data in sensor space. Fit a linear classifier with the LinearModel object +providing topographical patterns which are more neurophysiologically +interpretable :footcite:`HaufeEtAl2014` than the classifier filters (weight +vectors). The patterns explain how the MEG and EEG data were generated from +the discriminant neural sources which are extracted by the filters. +Note patterns/filters in MEG data are more similar than EEG data +because the noise is less spatially correlated in MEG than EEG. +""" + +# Authors: Alexandre Gramfort +# Romain Trachel +# Jean-Rémi King +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +from sklearn.linear_model import LogisticRegression +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import StandardScaler + +import mne +from mne import io +from mne.datasets import sample + +# import a linear classifier from mne.decoding +from mne.decoding import ( + LinearModel, + SpatialFilter, + Vectorizer, + get_spatial_filter_from_estimator, +) + +print(__doc__) + +data_path = sample.data_path() +sample_path = data_path / "MEG" / "sample" + +# %% +# Set parameters +raw_fname = sample_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = sample_path / "sample_audvis_filt-0-40_raw-eve.fif" +tmin, tmax = -0.1, 0.4 +event_id = dict(aud_l=1, vis_l=3) + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname, preload=True) +raw.filter(0.5, 25, fir_design="firwin") +events = mne.read_events(event_fname) + +# Read epochs +epochs = mne.Epochs( + raw, events, event_id, tmin, tmax, proj=True, decim=2, baseline=None, preload=True +) +del raw + +labels = epochs.events[:, -1] + +# get MEG data +meg_epochs = epochs.copy().pick(picks="meg", exclude="bads") +meg_data = meg_epochs.get_data(copy=False).reshape(len(labels), -1) + +# %% +# Decoding in sensor space using a LogisticRegression classifier +# -------------------------------------------------------------- + +clf = LogisticRegression(solver="liblinear") # liblinear is faster than lbfgs +scaler = StandardScaler() + +# create a linear model with LogisticRegression +model = LinearModel(clf) + +# fit the classifier on MEG data +X = scaler.fit_transform(meg_data) +model.fit(X, labels) + +coefs = dict() +for name, coef in (("patterns", model.patterns_), ("filters", model.filters_)): + # We fit the linear model on Z-scored data. To make the filters + # interpretable, we must reverse this normalization step + coef = scaler.inverse_transform([coef])[0] + + # The data was vectorized to fit a single model across all time points and + # all channels. We thus reshape it: + coefs[name] = coef.reshape(len(meg_epochs.ch_names), -1).T + +# Now we can instantiate the visualization container +spf = SpatialFilter(info=meg_epochs.info, **coefs) +fig = spf.plot_patterns( + # we will automatically select patterns + components="auto", + # as our filters and patterns correspond to actual times + # we can align them + tmin=epochs.tmin, + units="fT", # it's physical - we inversed the scaling + show=False, # to set the title below + name_format=None, # to plot actual times +) +fig.suptitle("MEG patterns") +# Same for filters +fig = spf.plot_filters( + components="auto", + tmin=epochs.tmin, + units="fT", + show=False, + name_format=None, +) +fig.suptitle("MEG filters") + +# %% +# Let's do the same on EEG data using a scikit-learn pipeline + +X = epochs.pick(picks="eeg", exclude="bads") +y = epochs.events[:, 2] + +# Define a unique pipeline to sequentially: +clf = make_pipeline( + Vectorizer(), # 1) vectorize across time and channels + StandardScaler(), # 2) normalize features across trials + LinearModel( # 3) fits a logistic regression + LogisticRegression(solver="liblinear") + ), +) +clf.fit(X, y) +spf = get_spatial_filter_from_estimator( + clf, info=epochs.info, inverse_transform=True, step_name="linearmodel" +) +fig = spf.plot_patterns( + components="auto", + tmin=epochs.tmin, + units="uV", + show=False, + name_format=None, +) +fig.suptitle("EEG patterns") +# Same for filters +fig = spf.plot_filters( + components="auto", + tmin=epochs.tmin, + units="uV", + show=False, + name_format=None, +) +fig.suptitle("EEG filters") + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/decoding/receptive_field_mtrf.py b/mne-python/source/examples/decoding/receptive_field_mtrf.py new file mode 100644 index 0000000000000000000000000000000000000000..89a97956559a8c6d91ffc92f70b354c14d653935 --- /dev/null +++ b/mne-python/source/examples/decoding/receptive_field_mtrf.py @@ -0,0 +1,295 @@ +""" +.. _ex-receptive-field-mtrf: + +========================================= +Receptive Field Estimation and Prediction +========================================= + +This example reproduces figures from Lalor et al.'s mTRF toolbox in +MATLAB :footcite:`CrosseEtAl2016`. We will show how the +:class:`mne.decoding.ReceptiveField` class +can perform a similar function along with scikit-learn. We will first fit a +linear encoding model using the continuously-varying speech envelope to predict +activity of a 128 channel EEG system. Then, we will take the reverse approach +and try to predict the speech envelope from the EEG (known in the literature +as a decoding model, or simply stimulus reconstruction). + +.. _figure 1: https://www.frontiersin.org/articles/10.3389/fnhum.2016.00604/full#F1 +.. _figure 2: https://www.frontiersin.org/articles/10.3389/fnhum.2016.00604/full#F2 +.. _figure 5: https://www.frontiersin.org/articles/10.3389/fnhum.2016.00604/full#F5 +""" + +# Authors: Chris Holdgraf +# Eric Larson +# Nicolas Barascud +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from os.path import join + +import matplotlib.pyplot as plt +import numpy as np +from scipy.io import loadmat +from sklearn.model_selection import KFold +from sklearn.preprocessing import scale + +import mne +from mne.decoding import ReceptiveField + +# %% +# Load the data from the publication +# ---------------------------------- +# +# First we will load the data collected in :footcite:`CrosseEtAl2016`. +# In this experiment subjects +# listened to natural speech. Raw EEG and the speech stimulus are provided. +# We will load these below, downsampling the data in order to speed up +# computation since we know that our features are primarily low-frequency in +# nature. Then we'll visualize both the EEG and speech envelope. + +path = mne.datasets.mtrf.data_path() +decim = 2 +data = loadmat(join(path, "speech_data.mat")) +raw = data["EEG"].T +speech = data["envelope"].T +sfreq = float(data["Fs"].item()) +sfreq /= decim +speech = mne.filter.resample(speech, down=decim, method="polyphase") +raw = mne.filter.resample(raw, down=decim, method="polyphase") + +# Read in channel positions and create our MNE objects from the raw data +montage = mne.channels.make_standard_montage("biosemi128") +info = mne.create_info(montage.ch_names, sfreq, "eeg").set_montage(montage) +raw = mne.io.RawArray(raw, info) +n_channels = len(raw.ch_names) + +# Plot a sample of brain and stimulus activity +fig, ax = plt.subplots(layout="constrained") +lns = ax.plot(scale(raw[:, :800][0].T), color="k", alpha=0.1) +ln1 = ax.plot(scale(speech[0, :800]), color="r", lw=2) +ax.legend([lns[0], ln1[0]], ["EEG", "Speech Envelope"], frameon=False) +ax.set(title="Sample activity", xlabel="Time (s)") + +# %% +# Create and fit a receptive field model +# -------------------------------------- +# +# We will construct an encoding model to find the linear relationship between +# a time-delayed version of the speech envelope and the EEG signal. This allows +# us to make predictions about the response to new stimuli. + +# Define the delays that we will use in the receptive field +tmin, tmax = -0.2, 0.4 + +# Initialize the model +rf = ReceptiveField( + tmin, tmax, sfreq, feature_names=["envelope"], estimator=1.0, scoring="corrcoef" +) +# We'll have (tmax - tmin) * sfreq delays +# and an extra 2 delays since we are inclusive on the beginning / end index +n_delays = int((tmax - tmin) * sfreq) + 2 + +n_splits = 3 +cv = KFold(n_splits) + +# Prepare model data (make time the first dimension) +speech = speech.T +Y, _ = raw[:] # Outputs for the model +Y = Y.T + +# Iterate through splits, fit the model, and predict/test on held-out data +coefs = np.zeros((n_splits, n_channels, n_delays)) +scores = np.zeros((n_splits, n_channels)) +for ii, (train, test) in enumerate(cv.split(speech)): + print(f"split {ii + 1} / {n_splits}") + rf.fit(speech[train], Y[train]) + scores[ii] = rf.score(speech[test], Y[test]) + # coef_ is shape (n_outputs, n_features, n_delays). we only have 1 feature + coefs[ii] = rf.coef_[:, 0, :] +times = rf.delays_ / float(rf.sfreq) + +# Average scores and coefficients across CV splits +mean_coefs = coefs.mean(axis=0) +mean_scores = scores.mean(axis=0) + +# Plot mean prediction scores across all channels +fig, ax = plt.subplots(layout="constrained") +ix_chs = np.arange(n_channels) +ax.plot(ix_chs, mean_scores) +ax.axhline(0, ls="--", color="r") +ax.set(title="Mean prediction score", xlabel="Channel", ylabel="Score ($r$)") + +# %% +# Investigate model coefficients +# ============================== +# Finally, we will look at how the linear coefficients (sometimes +# referred to as beta values) are distributed across time delays as well as +# across the scalp. We will recreate `figure 1`_ and `figure 2`_ from +# :footcite:`CrosseEtAl2016`. + +# sphinx_gallery_thumbnail_number = 3 + +# Print mean coefficients across all time delays / channels (see Fig 1) +time_plot = 0.180 # For highlighting a specific time. +fig, ax = plt.subplots(figsize=(4, 8), layout="constrained") +max_coef = mean_coefs.max() +ax.pcolormesh( + times, + ix_chs, + mean_coefs, + cmap="RdBu_r", + vmin=-max_coef, + vmax=max_coef, + shading="gouraud", +) +ax.axvline(time_plot, ls="--", color="k", lw=2) +ax.set( + xlabel="Delay (s)", + ylabel="Channel", + title="Mean Model\nCoefficients", + xlim=times[[0, -1]], + ylim=[len(ix_chs) - 1, 0], + xticks=np.arange(tmin, tmax + 0.2, 0.2), +) +plt.setp(ax.get_xticklabels(), rotation=45) + +# Make a topographic map of coefficients for a given delay (see Fig 2C) +ix_plot = np.argmin(np.abs(time_plot - times)) +fig, ax = plt.subplots(layout="constrained") +mne.viz.plot_topomap( + mean_coefs[:, ix_plot], pos=info, axes=ax, show=False, vlim=(-max_coef, max_coef) +) +ax.set(title=f"Topomap of model coefficients\nfor delay {time_plot}") + +# %% +# Create and fit a stimulus reconstruction model +# ---------------------------------------------- +# +# We will now demonstrate another use case for the for the +# :class:`mne.decoding.ReceptiveField` class as we try to predict the stimulus +# activity from the EEG data. This is known in the literature as a decoding, or +# stimulus reconstruction model :footcite:`CrosseEtAl2016`. +# A decoding model aims to find the +# relationship between the speech signal and a time-delayed version of the EEG. +# This can be useful as we exploit all of the available neural data in a +# multivariate context, compared to the encoding case which treats each M/EEG +# channel as an independent feature. Therefore, decoding models might provide a +# better quality of fit (at the expense of not controlling for stimulus +# covariance), especially for low SNR stimuli such as speech. + +# We use the same lags as in :footcite:`CrosseEtAl2016`. Negative lags now +# index the relationship +# between the neural response and the speech envelope earlier in time, whereas +# positive lags would index how a unit change in the amplitude of the EEG would +# affect later stimulus activity (obviously this should have an amplitude of +# zero). +tmin, tmax = -0.2, 0.0 + +# Initialize the model. Here the features are the EEG data. We also specify +# ``patterns=True`` to compute inverse-transformed coefficients during model +# fitting (cf. next section and :footcite:`HaufeEtAl2014`). +# We'll use a ridge regression estimator with an alpha value similar to +# Crosse et al. +sr = ReceptiveField( + tmin, + tmax, + sfreq, + feature_names=raw.ch_names, + estimator=1e4, + scoring="corrcoef", + patterns=True, +) +# We'll have (tmax - tmin) * sfreq delays +# and an extra 2 delays since we are inclusive on the beginning / end index +n_delays = int((tmax - tmin) * sfreq) + 2 + +n_splits = 3 +cv = KFold(n_splits) + +# Iterate through splits, fit the model, and predict/test on held-out data +coefs = np.zeros((n_splits, n_channels, n_delays)) +patterns = coefs.copy() +scores = np.zeros((n_splits,)) +for ii, (train, test) in enumerate(cv.split(speech)): + print(f"split {ii + 1} / {n_splits}") + sr.fit(Y[train], speech[train]) + scores[ii] = sr.score(Y[test], speech[test])[0] + # coef_ is shape (n_outputs, n_features, n_delays). We have 128 features + coefs[ii] = sr.coef_[0, :, :] + patterns[ii] = sr.patterns_[0, :, :] +times = sr.delays_ / float(sr.sfreq) + +# Average scores and coefficients across CV splits +mean_coefs = coefs.mean(axis=0) +mean_patterns = patterns.mean(axis=0) +mean_scores = scores.mean(axis=0) +max_coef = np.abs(mean_coefs).max() +max_patterns = np.abs(mean_patterns).max() + +# %% +# Visualize stimulus reconstruction +# ================================= +# +# To get a sense of our model performance, we can plot the actual and predicted +# stimulus envelopes side by side. + +y_pred = sr.predict(Y[test]) +time = np.linspace(0, 2.0, 5 * int(sfreq)) +fig, ax = plt.subplots(figsize=(8, 4), layout="constrained") +ax.plot( + time, speech[test][sr.valid_samples_][: int(5 * sfreq)], color="grey", lw=2, ls="--" +) +ax.plot(time, y_pred[sr.valid_samples_][: int(5 * sfreq)], color="r", lw=2) +ax.legend([lns[0], ln1[0]], ["Envelope", "Reconstruction"], frameon=False) +ax.set(title="Stimulus reconstruction") +ax.set_xlabel("Time (s)") + +# %% +# Investigate model coefficients +# ============================== +# +# Finally, we will look at how the decoding model coefficients are distributed +# across the scalp. We will attempt to recreate `figure 5`_ from +# :footcite:`CrosseEtAl2016`. The +# decoding model weights reflect the channels that contribute most toward +# reconstructing the stimulus signal, but are not directly interpretable in a +# neurophysiological sense. Here we also look at the coefficients obtained +# via an inversion procedure :footcite:`HaufeEtAl2014`, which have a more +# straightforward +# interpretation as their value (and sign) directly relates to the stimulus +# signal's strength (and effect direction). + +time_plot = (-0.140, -0.125) # To average between two timepoints. +ix_plot = np.arange( + np.argmin(np.abs(time_plot[0] - times)), np.argmin(np.abs(time_plot[1] - times)) +) +fig, ax = plt.subplots(1, 2) +mne.viz.plot_topomap( + np.mean(mean_coefs[:, ix_plot], axis=1), + pos=info, + axes=ax[0], + show=False, + vlim=(-max_coef, max_coef), +) +ax[0].set(title=f"Model coefficients\nbetween delays {time_plot[0]} and {time_plot[1]}") + +mne.viz.plot_topomap( + np.mean(mean_patterns[:, ix_plot], axis=1), + pos=info, + axes=ax[1], + show=False, + vlim=(-max_patterns, max_patterns), +) +ax[1].set( + title=( + f"Inverse-transformed coefficients\nbetween delays {time_plot[0]} and " + f"{time_plot[1]}" + ) +) + +# %% +# References +# ---------- +# +# .. footbibliography:: diff --git a/mne-python/source/examples/decoding/ssd_spatial_filters.py b/mne-python/source/examples/decoding/ssd_spatial_filters.py new file mode 100644 index 0000000000000000000000000000000000000000..7938fe6ad2a54aae16c42e8ce6af44a3b9bb5dc3 --- /dev/null +++ b/mne-python/source/examples/decoding/ssd_spatial_filters.py @@ -0,0 +1,159 @@ +""" +.. _ex-ssd-spatial-filters: + +================================================================ +Compute spatial filters with Spatio-Spectral Decomposition (SSD) +================================================================ + +In this example, we will compute spatial filters for retaining +oscillatory brain activity and down-weighting 1/f background signals +as proposed by :footcite:`NikulinEtAl2011`. +The idea is to learn spatial filters that separate oscillatory dynamics +from surrounding non-oscillatory noise based on the covariance in the +frequency band of interest and the noise covariance based on surrounding +frequencies. +""" + +# Author: Denis A. Engemann +# Victoria Peterson +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne import Epochs +from mne.datasets.fieldtrip_cmc import data_path +from mne.decoding import SSD, get_spatial_filter_from_estimator + +# %% +# Define parameters +fname = data_path() / "SubjectCMC.ds" + +# Prepare data +raw = mne.io.read_raw_ctf(fname) +raw.crop(tmin=50.0, tmax=110.0).load_data() # crop for memory purposes +raw.resample(sfreq=250) + +raw.pick_types(meg=True, ref_meg=False) + +freqs_sig = 9, 12 +freqs_noise = 8, 13 + + +ssd = SSD( + info=raw.info, + reg="oas", + sort_by_spectral_ratio=False, # False for purpose of example. + filt_params_signal=dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ), + filt_params_noise=dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ), +) +ssd.fit(X=raw.get_data()) + + +# %% +# Let's investigate spatial filter with the max power ratio. +# We will first inspect the topographies. +# According to Nikulin et al. (2011), this is done by either inverting the filters +# (W^{-1}) or by multiplying the noise cov with the filters Eq. (22) (C_n W)^t. +# We rely on the inversion approach here. + +spf = get_spatial_filter_from_estimator(ssd, info=ssd.info) +spf.plot_patterns(components=list(range(4))) + +# The topographies suggest that we picked up a parietal alpha generator. + +# Transform +ssd_sources = ssd.transform(X=raw.get_data()) + +# Get psd of SSD-filtered signals. +psd, freqs = mne.time_frequency.psd_array_welch( + ssd_sources, sfreq=raw.info["sfreq"], n_fft=4096 +) + +# Get spec_ratio information (already sorted) +# Note that this is not necessary if sort_by_spectral_ratio=True (default) +spec_ratio, sorter = ssd.get_spectral_ratio(ssd_sources) + +# Plot spectral ratio (see Eq. 24 in Nikulin et al., 2011). +fig, ax = plt.subplots(1) +ax.plot(spec_ratio, color="black") +ax.plot(spec_ratio[sorter], color="orange", label="sorted eigenvalues") +ax.set_xlabel("Eigenvalue Index") +ax.set_ylabel(r"Spectral Ratio $\frac{P_f}{P_{sf}}$") +ax.legend() +ax.axhline(1, linestyle="--") + +# We can see that the initial sorting based on the eigenvalues +# was already quite good. However, when using few components only +# the sorting might make a difference. + +# %% +# Let's also look at the power spectrum of that source and compare it +# to the power spectrum of the source with lowest SNR. + +below50 = freqs < 50 +# for highlighting the freq. band of interest +bandfilt = (freqs_sig[0] <= freqs) & (freqs <= freqs_sig[1]) +fig, ax = plt.subplots(1) +ax.loglog(freqs[below50], psd[0, below50], label="max SNR") +ax.loglog(freqs[below50], psd[-1, below50], label="min SNR") +ax.loglog(freqs[below50], psd[:, below50].mean(axis=0), label="mean") +ax.fill_between(freqs[bandfilt], 0, 10000, color="green", alpha=0.15) +ax.set_xlabel("log(frequency)") +ax.set_ylabel("log(power)") +ax.legend() + +# We can clearly see that the selected component enjoys an SNR that is +# way above the average power spectrum. + +# %% +# Epoched data +# ------------ +# Although we suggest using this method before epoching, there might be some +# situations in which data can only be treated by chunks. + +# Build epochs as sliding windows over the continuous raw file. +events = mne.make_fixed_length_events(raw, id=1, duration=5.0, overlap=0.0) + +# Epoch length is 5 seconds. +epochs = Epochs(raw, events, tmin=0.0, tmax=5, baseline=None, preload=True) + +ssd_epochs = SSD( + info=epochs.info, + reg="oas", + filt_params_signal=dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ), + filt_params_noise=dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ), +) +ssd_epochs.fit(X=epochs.get_data(copy=False)) + +# Plot topographies. +spf = get_spatial_filter_from_estimator(ssd_epochs, info=ssd_epochs.info) +spf.plot_patterns(components=list(range(4))) +# %% +# References +# ---------- +# +# .. footbibliography:: diff --git a/mne-python/source/examples/forward/README.txt b/mne-python/source/examples/forward/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..89db5587dc80571fb11ba2e2aa0e21956d7a922e --- /dev/null +++ b/mne-python/source/examples/forward/README.txt @@ -0,0 +1,6 @@ + +Forward modeling +---------------- + +From BEM segmentation, coregistration, setting up source spaces +to actual computation of forward solution. diff --git a/mne-python/source/examples/forward/forward_sensitivity_maps.py b/mne-python/source/examples/forward/forward_sensitivity_maps.py new file mode 100644 index 0000000000000000000000000000000000000000..c9163b5b7928d201b248d92663c6993c1f329838 --- /dev/null +++ b/mne-python/source/examples/forward/forward_sensitivity_maps.py @@ -0,0 +1,115 @@ +""" +.. _ex-sensitivity-maps: + +================================================ +Display sensitivity maps for EEG and MEG sensors +================================================ + +Sensitivity maps can be produced from forward operators that +indicate how well different sensor types will be able to detect +neural currents from different regions of the brain. + +To get started with forward modeling see :ref:`tut-forward`. +""" + +# Author: Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.datasets import sample +from mne.source_estimate import SourceEstimate +from mne.source_space import compute_distance_to_sensors + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +subjects_dir = data_path / "subjects" + +# Read the forward solutions with surface orientation +fwd = mne.read_forward_solution(fwd_fname) +mne.convert_forward_solution(fwd, surf_ori=True, copy=False) +leadfield = fwd["sol"]["data"] +print("Leadfield shape : {leadfield.shape}") + +# %% +# Compute sensitivity maps + +grad_map = mne.sensitivity_map(fwd, ch_type="grad", mode="fixed") +mag_map = mne.sensitivity_map(fwd, ch_type="mag", mode="fixed") +eeg_map = mne.sensitivity_map(fwd, ch_type="eeg", mode="fixed") + +# %% +# Show gain matrix a.k.a. leadfield matrix with sensitivity map + +picks_meg = mne.pick_types(fwd["info"], meg=True, eeg=False) +picks_eeg = mne.pick_types(fwd["info"], meg=False, eeg=True) + +fig, axes = plt.subplots(2, 1, figsize=(10, 8), sharex=True) +fig.suptitle("Lead field matrix (500 dipoles only)", fontsize=14) +for ax, picks, ch_type in zip(axes, [picks_meg, picks_eeg], ["meg", "eeg"]): + im = ax.imshow(leadfield[picks, :500], origin="lower", aspect="auto", cmap="RdBu_r") + ax.set_title(ch_type.upper()) + ax.set_xlabel("sources") + ax.set_ylabel("sensors") + fig.colorbar(im, ax=ax) + +fig_2, ax = plt.subplots() +ax.hist( + [grad_map.data.ravel(), mag_map.data.ravel(), eeg_map.data.ravel()], + bins=20, + label=["Gradiometers", "Magnetometers", "EEG"], + color=["c", "b", "k"], +) +fig_2.legend() +ax.set(title="Normal orientation sensitivity", xlabel="sensitivity", ylabel="count") + +# sphinx_gallery_thumbnail_number = 3 +brain_sens = grad_map.plot( + subjects_dir=subjects_dir, clim=dict(lims=[0, 50, 100]), figure=1 +) +brain_sens.add_text(0.1, 0.9, "Gradiometer sensitivity", "title", font_size=16) + +# %% +# Compare sensitivity map with distribution of source depths + +# source space with vertices +src = fwd["src"] + +# Compute minimum Euclidean distances between vertices and MEG sensors +depths = compute_distance_to_sensors(src=src, info=fwd["info"], picks=picks_meg).min( + axis=1 +) +maxdep = depths.max() # for scaling + +vertices = [src[0]["vertno"], src[1]["vertno"]] + +depths_map = SourceEstimate(data=depths, vertices=vertices, tmin=0.0, tstep=1.0) + +brain_dep = depths_map.plot( + subject="sample", + subjects_dir=subjects_dir, + clim=dict(kind="value", lims=[0, maxdep / 2.0, maxdep]), + figure=2, +) +brain_dep.add_text(0.1, 0.9, "Source depth (m)", "title", font_size=16) + +# %% +# Sensitivity is likely to co-vary with the distance between sources to +# sensors. To determine the strength of this relationship, we can compute the +# correlation between source depth and sensitivity values. +corr = np.corrcoef(depths, grad_map.data[:, 0])[0, 1] +print(f"Correlation between source depth and gradiomter sensitivity values: {corr:f}.") + +# %% +# Gradiometer sensitiviy is highest close to the sensors, and decreases rapidly +# with inreasing source depth. This is confirmed by the high negative +# correlation between the two. diff --git a/mne-python/source/examples/forward/left_cerebellum_volume_source.py b/mne-python/source/examples/forward/left_cerebellum_volume_source.py new file mode 100644 index 0000000000000000000000000000000000000000..ff810493e997565afd541930fb43bd79dbd742a1 --- /dev/null +++ b/mne-python/source/examples/forward/left_cerebellum_volume_source.py @@ -0,0 +1,80 @@ +""" +.. _ex-cerebellum-source-space: + +============================================== +Generate a left cerebellum volume source space +============================================== + +Generate a volume source space of the left cerebellum and plot its vertices +relative to the left cortical surface source space and the FreeSurfer +segmentation file. +""" + +# Author: Alan Leggitt +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne import setup_source_space, setup_volume_source_space +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +subject = "sample" +aseg_fname = subjects_dir / "sample" / "mri" / "aseg.mgz" + +# %% +# Setup the source spaces + +# setup a cortical surface source space and extract left hemisphere +surf = setup_source_space(subject, subjects_dir=subjects_dir, add_dist=False) +lh_surf = surf[0] + +# setup a volume source space of the left cerebellum cortex +volume_label = "Left-Cerebellum-Cortex" +sphere = (0, 0, 0, 0.12) +lh_cereb = setup_volume_source_space( + subject, + mri=aseg_fname, + sphere=sphere, + volume_label=volume_label, + subjects_dir=subjects_dir, + sphere_units="m", +) + +# Combine the source spaces +src = surf + lh_cereb + +# %% +# Plot the positions of each source space + +fig = mne.viz.plot_alignment( + subject=subject, + subjects_dir=subjects_dir, + surfaces="white", + coord_frame="mri", + src=src, +) +mne.viz.set_3d_view( + fig, azimuth=180, elevation=90, distance=0.30, focalpoint=(-0.03, -0.01, 0.03) +) + +# %% +# You can export source positions to a NIfTI file:: +# +# >>> nii_fname = 'mne_sample_lh-cerebellum-cortex.nii' +# >>> src.export_volume(nii_fname, mri_resolution=True) +# +# And display source positions in freeview:: +# +# >>> from mne.utils import run_subprocess +# >>> mri_fname = subjects_dir / "sample" / "mri" / "brain.mgz" +# >>> run_subprocess(["freeview", "-v", str(mri_fname), "-v", +# f"{aseg_fname}:colormap=lut:opacity=0.5", +# "-v", f"{nii_fname}:colormap=jet:colorscale=0,2", +# "--slice", "157", "75", "105"]) diff --git a/mne-python/source/examples/forward/source_space_morphing.py b/mne-python/source/examples/forward/source_space_morphing.py new file mode 100644 index 0000000000000000000000000000000000000000..fd5b992696e0309306ae92f8601e4e2d04c183ea --- /dev/null +++ b/mne-python/source/examples/forward/source_space_morphing.py @@ -0,0 +1,72 @@ +""" +.. _ex-source-space-morphing: + +========================= +Use source space morphing +========================= + +This example shows how to use source space morphing (as opposed to +:class:`~mne.SourceEstimate` morphing) to create data that can be compared +between subjects. + +.. warning:: Source space morphing will likely lead to source spaces that are + less evenly sampled than source spaces created for individual + subjects. Use with caution and check effects on localization + before use. +""" +# Authors: Denis A. Engemann +# Eric larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne + +data_path = mne.datasets.sample.data_path() +subjects_dir = data_path / "subjects" +fname_trans = data_path / "MEG" / "sample" / "sample_audvis_raw-trans.fif" +fname_bem = subjects_dir / "sample" / "bem" / "sample-5120-bem-sol.fif" +fname_src_fs = subjects_dir / "fsaverage" / "bem" / "fsaverage-ico-5-src.fif" +raw_fname = data_path / "MEG" / "sample" / "sample_audvis_raw.fif" + +# Get relevant channel information +info = mne.io.read_info(raw_fname) +info = mne.pick_info(info, mne.pick_types(info, meg=True, eeg=False, exclude=[])) + +# Morph fsaverage's source space to sample +src_fs = mne.read_source_spaces(fname_src_fs) +src_morph = mne.morph_source_spaces( + src_fs, subject_to="sample", subjects_dir=subjects_dir +) + +# Compute the forward with our morphed source space +fwd = mne.make_forward_solution(info, trans=fname_trans, src=src_morph, bem=fname_bem) +mag_map = mne.sensitivity_map(fwd, ch_type="mag") + +# Return this SourceEstimate (on sample's surfaces) to fsaverage's surfaces +mag_map_fs = mag_map.to_original_src(src_fs, subjects_dir=subjects_dir) + +# Plot the result, which tracks the sulcal-gyral folding +# outliers may occur, we'll place the cutoff at 99 percent. +kwargs = dict( + clim=dict(kind="percent", lims=[0, 50, 99]), + # no smoothing, let's see the dipoles on the cortex. + smoothing_steps=1, + hemi="rh", + views=["lat"], +) + +# Now note that the dipoles on fsaverage are almost equidistant while +# morphing will distribute the dipoles unevenly across the given subject's +# cortical surface to achieve the closest approximation to the average brain. +# Our testing code suggests a correlation of higher than 0.99. + +brain_subject = mag_map.plot( # plot forward in subject source space (morphed) + time_label="Morphed", subjects_dir=subjects_dir, **kwargs +) + +brain_fs = mag_map_fs.plot( # plot forward in original source space (remapped) + time_label="Remapped", subjects_dir=subjects_dir, **kwargs +) diff --git a/mne-python/source/examples/inverse/README.txt b/mne-python/source/examples/inverse/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..69559c3557a9c9f35ab890dbb177964f32cd5def --- /dev/null +++ b/mne-python/source/examples/inverse/README.txt @@ -0,0 +1,7 @@ + +Inverse problem and source analysis +----------------------------------- + +Estimate source activations, extract activations in +labels, morph data between subjects etc. + diff --git a/mne-python/source/examples/inverse/compute_mne_inverse_epochs_in_label.py b/mne-python/source/examples/inverse/compute_mne_inverse_epochs_in_label.py new file mode 100644 index 0000000000000000000000000000000000000000..ca15c80efcc8ef666fdfabd67ba8d5c0ac9f2af7 --- /dev/null +++ b/mne-python/source/examples/inverse/compute_mne_inverse_epochs_in_label.py @@ -0,0 +1,143 @@ +""" +.. _ex-dSPM-epochs: + +================================================== +Compute MNE-dSPM inverse solution on single epochs +================================================== + +Compute dSPM inverse solution on single trial epochs restricted +to a brain label. +""" +# Author: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.datasets import sample +from mne.minimum_norm import apply_inverse, apply_inverse_epochs, read_inverse_operator + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fname_inv = meg_path / "sample_audvis-meg-oct-6-meg-inv.fif" +fname_raw = meg_path / "sample_audvis_filt-0-40_raw.fif" +fname_event = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +label_name = "Aud-lh" +fname_label = meg_path / "labels" / f"{label_name}.label" + +event_id, tmin, tmax = 1, -0.2, 0.5 + +# Using the same inverse operator when inspecting single trials Vs. evoked +snr = 3.0 # Standard assumption for average data but using it for single trial +lambda2 = 1.0 / snr**2 + +method = "dSPM" # use dSPM method (could also be MNE or sLORETA) + +# Load data +inverse_operator = read_inverse_operator(fname_inv) +label = mne.read_label(fname_label) +raw = mne.io.read_raw_fif(fname_raw) +events = mne.read_events(fname_event) + +# Set up pick list +include = [] + +# Add a bad channel +raw.info["bads"] += ["EEG 053"] # bads + 1 more + +# pick MEG channels +picks = mne.pick_types( + raw.info, meg=True, eeg=False, stim=False, eog=True, include=include, exclude="bads" +) +# Read epochs +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + reject=dict(mag=4e-12, grad=4000e-13, eog=150e-6), +) + +# Get evoked data (averaging across trials in sensor space) +evoked = epochs.average() + +# Compute inverse solution and stcs for each epoch +# Use the same inverse operator as with evoked data (i.e., set nave) +# If you use a different nave, dSPM just scales by a factor sqrt(nave) +stcs = apply_inverse_epochs( + epochs, + inverse_operator, + lambda2, + method, + label, + pick_ori="normal", + nave=evoked.nave, +) + +# Mean across trials but not across vertices in label +mean_stc = sum(stcs) / len(stcs) + +# compute sign flip to avoid signal cancellation when averaging signed values +flip = mne.label_sign_flip(label, inverse_operator["src"]) + +label_mean = np.mean(mean_stc.data, axis=0) +label_mean_flip = np.mean(flip[:, np.newaxis] * mean_stc.data, axis=0) + +# Get inverse solution by inverting evoked data +stc_evoked = apply_inverse(evoked, inverse_operator, lambda2, method, pick_ori="normal") + +# apply_inverse() does whole brain, so sub-select label of interest +stc_evoked_label = stc_evoked.in_label(label) + +# Average over label (not caring to align polarities here) +label_mean_evoked = np.mean(stc_evoked_label.data, axis=0) + +# %% +# View activation time-series to illustrate the benefit of aligning/flipping + +times = 1e3 * stcs[0].times # times in ms + +plt.figure() +h0 = plt.plot(times, mean_stc.data.T, "k") +(h1,) = plt.plot(times, label_mean, "r", linewidth=3) +(h2,) = plt.plot(times, label_mean_flip, "g", linewidth=3) +plt.legend((h0[0], h1, h2), ("all dipoles in label", "mean", "mean with sign flip")) +plt.xlabel("time (ms)") +plt.ylabel("dSPM value") +plt.show() + +# %% +# Viewing single trial dSPM and average dSPM for unflipped pooling over label +# Compare to (1) Inverse (dSPM) then average, (2) Evoked then dSPM + +# Single trial +plt.figure() +for k, stc_trial in enumerate(stcs): + plt.plot( + times, + np.mean(stc_trial.data, axis=0).T, + "k--", + label="Single Trials" if k == 0 else "_nolegend_", + alpha=0.5, + ) + +# Single trial inverse then average.. making linewidth large to not be masked +plt.plot(times, label_mean, "b", linewidth=6, label="dSPM first, then average") + +# Evoked and then inverse +plt.plot(times, label_mean_evoked, "r", linewidth=2, label="Average first, then dSPM") + +plt.xlabel("time (ms)") +plt.ylabel("dSPM value") +plt.legend() +plt.show() diff --git a/mne-python/source/examples/inverse/compute_mne_inverse_raw_in_label.py b/mne-python/source/examples/inverse/compute_mne_inverse_raw_in_label.py new file mode 100644 index 0000000000000000000000000000000000000000..b462c09e180f85f9acacefde256f580f13e43875 --- /dev/null +++ b/mne-python/source/examples/inverse/compute_mne_inverse_raw_in_label.py @@ -0,0 +1,59 @@ +""" +.. _example-sLORETA: + +============================================= +Compute sLORETA inverse solution on raw data +============================================= + +Compute sLORETA inverse solution on raw dataset restricted +to a brain label and stores the solution in stc files for +visualisation. + +""" +# Author: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne.datasets import sample +from mne.minimum_norm import apply_inverse_raw, read_inverse_operator + +print(__doc__) + +data_path = sample.data_path() +fname_inv = data_path / "MEG" / "sample" / "sample_audvis-meg-oct-6-meg-inv.fif" +fname_raw = data_path / "MEG" / "sample" / "sample_audvis_raw.fif" +label_name = "Aud-lh" +fname_label = data_path / "MEG" / "sample" / "labels" / f"{label_name}.label" + +snr = 1.0 # use smaller SNR for raw data +lambda2 = 1.0 / snr**2 +method = "sLORETA" # use sLORETA method (could also be MNE or dSPM) + +# Load data +raw = mne.io.read_raw_fif(fname_raw) +inverse_operator = read_inverse_operator(fname_inv) +label = mne.read_label(fname_label) + +raw.set_eeg_reference("average", projection=True) # set average reference. +start, stop = raw.time_as_index([0, 15]) # read the first 15s of data + +# Compute inverse solution +stc = apply_inverse_raw( + raw, inverse_operator, lambda2, method, label, start, stop, pick_ori=None +) + +# Save result in stc files +stc.save(f"mne_{method}_raw_inverse_{label_name}", overwrite=True) + +# %% +# View activation time-series +plt.plot(1e3 * stc.times, stc.data[::100, :].T) +plt.xlabel("time (ms)") +plt.ylabel(f"{method} value") +plt.show() diff --git a/mne-python/source/examples/inverse/compute_mne_inverse_volume.py b/mne-python/source/examples/inverse/compute_mne_inverse_volume.py new file mode 100644 index 0000000000000000000000000000000000000000..b4889df67a61072ee11e7bc25608400b56278fd1 --- /dev/null +++ b/mne-python/source/examples/inverse/compute_mne_inverse_volume.py @@ -0,0 +1,60 @@ +""" +.. _ex-inverse-volume: + +======================================================================= +Compute MNE-dSPM inverse solution on evoked data in volume source space +======================================================================= + +Compute dSPM inverse solution on MNE evoked dataset in a volume source +space and stores the solution in a nifti file for visualisation. +""" +# Author: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +from nilearn.image import index_img +from nilearn.plotting import plot_stat_map + +from mne import read_evokeds +from mne.datasets import sample +from mne.minimum_norm import apply_inverse, read_inverse_operator + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fname_inv = meg_path / "sample_audvis-meg-vol-7-meg-inv.fif" +fname_evoked = meg_path / "sample_audvis-ave.fif" + +snr = 3.0 +lambda2 = 1.0 / snr**2 +method = "dSPM" # use dSPM method (could also be MNE or sLORETA) + +# Load data +evoked = read_evokeds(fname_evoked, condition=0, baseline=(None, 0)) +inverse_operator = read_inverse_operator(fname_inv) +src = inverse_operator["src"] + +# Compute inverse solution +stc = apply_inverse(evoked, inverse_operator, lambda2, method) +stc.crop(0.0, 0.2) + +# Export result as a 4D nifti object +img = stc.as_volume(src, mri_resolution=False) # set True for full MRI resolution + +# Save it as a nifti file +# nib.save(img, f"mne_{method}_inverse.nii.gz") + +t1_fname = data_path / "subjects" / "sample" / "mri" / "T1.mgz" + +# %% +# Plot with nilearn: +plot_stat_map( + index_img(img, 61), + str(t1_fname), + threshold=8.0, + title=f"{method} (t={stc.times[61]:.1f} s.)", +) diff --git a/mne-python/source/examples/inverse/custom_inverse_solver.py b/mne-python/source/examples/inverse/custom_inverse_solver.py new file mode 100644 index 0000000000000000000000000000000000000000..e8444dcd046478feee7361a02c65cef43c37b35a --- /dev/null +++ b/mne-python/source/examples/inverse/custom_inverse_solver.py @@ -0,0 +1,194 @@ +""" +.. _ex-custom-inverse: + +================================================ +Source localization with a custom inverse solver +================================================ + +The objective of this example is to show how to plug a custom inverse solver +in MNE in order to facilate empirical comparison with the methods MNE already +implements (wMNE, dSPM, sLORETA, eLORETA, LCMV, DICS, (TF-)MxNE etc.). + +This script is educational and shall be used for methods +evaluations and new developments. It is not meant to be an example +of good practice to analyse your data. + +The example makes use of 2 functions ``apply_solver`` and ``solver`` +so changes can be limited to the ``solver`` function (which only takes three +parameters: the whitened data, the gain matrix and the number of orientations) +in order to try out another inverse algorithm. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np +from scipy import linalg + +import mne +from mne.datasets import sample +from mne.viz import plot_sparse_source_estimates + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +ave_fname = meg_path / "sample_audvis-ave.fif" +cov_fname = meg_path / "sample_audvis-shrunk-cov.fif" +subjects_dir = data_path / "subjects" +condition = "Left Auditory" + +# Read noise covariance matrix +noise_cov = mne.read_cov(cov_fname) +# Handling average file +evoked = mne.read_evokeds(ave_fname, condition=condition, baseline=(None, 0)) +evoked.crop(tmin=0.04, tmax=0.18) + +evoked = evoked.pick(picks="meg", exclude="bads") +# Handling forward solution +forward = mne.read_forward_solution(fwd_fname) + + +# %% +# Auxiliary function to run the solver + + +def apply_solver(solver, evoked, forward, noise_cov, loose=0.2, depth=0.8): + """Call a custom solver on evoked data. + + This function does all the necessary computation: + + - to select the channels in the forward given the available ones in + the data + - to take into account the noise covariance and do the spatial whitening + - to apply loose orientation constraint as MNE solvers + - to apply a weigthing of the columns of the forward operator as in the + weighted Minimum Norm formulation in order to limit the problem + of depth bias. + + Parameters + ---------- + solver : callable + The solver takes 3 parameters: data M, gain matrix G, number of + dipoles orientations per location (1 or 3). A solver shall return + 2 variables: X which contains the time series of the active dipoles + and an active set which is a boolean mask to specify what dipoles are + present in X. + evoked : instance of mne.Evoked + The evoked data + forward : instance of Forward + The forward solution. + noise_cov : instance of Covariance + The noise covariance. + loose : float in [0, 1] | 'auto' + Value that weights the source variances of the dipole components + that are parallel (tangential) to the cortical surface. If loose + is 0 then the solution is computed with fixed orientation. + If loose is 1, it corresponds to free orientations. + The default value ('auto') is set to 0.2 for surface-oriented source + space and set to 1.0 for volumic or discrete source space. + depth : None | float in [0, 1] + Depth weighting coefficients. If None, no depth weighting is performed. + + Returns + ------- + stc : instance of SourceEstimate + The source estimates. + """ + # Import the necessary private functions + from mne.inverse_sparse.mxne_inverse import ( + _make_sparse_stc, + _prepare_gain, + _reapply_source_weighting, + is_fixed_orient, + ) + + all_ch_names = evoked.ch_names + + # Handle depth weighting and whitening (here is no weights) + forward, gain, gain_info, whitener, source_weighting, mask = _prepare_gain( + forward, + evoked.info, + noise_cov, + pca=False, + depth=depth, + loose=loose, + weights=None, + weights_min=None, + rank=None, + ) + + # Select channels of interest + sel = [all_ch_names.index(name) for name in gain_info["ch_names"]] + M = evoked.data[sel] + + # Whiten data + M = np.dot(whitener, M) + + n_orient = 1 if is_fixed_orient(forward) else 3 + X, active_set = solver(M, gain, n_orient) + X = _reapply_source_weighting(X, source_weighting, active_set) + + stc = _make_sparse_stc( + X, active_set, forward, tmin=evoked.times[0], tstep=1.0 / evoked.info["sfreq"] + ) + + return stc + + +# %% +# Define your solver + + +def solver(M, G, n_orient): + """Run L2 penalized regression and keep 10 strongest locations. + + Parameters + ---------- + M : array, shape (n_channels, n_times) + The whitened data. + G : array, shape (n_channels, n_dipoles) + The gain matrix a.k.a. the forward operator. The number of locations + is n_dipoles / n_orient. n_orient will be 1 for a fixed orientation + constraint or 3 when using a free orientation model. + n_orient : int + Can be 1 or 3 depending if one works with fixed or free orientations. + If n_orient is 3, then ``G[:, 2::3]`` corresponds to the dipoles that + are normal to the cortex. + + Returns + ------- + X : array, (n_active_dipoles, n_times) + The time series of the dipoles in the active set. + active_set : array (n_dipoles) + Array of bool. Entry j is True if dipole j is in the active set. + We have ``X_full[active_set] == X`` where X_full is the full X matrix + such that ``M = G X_full``. + """ + inner = np.dot(G, G.T) + trace = np.trace(inner) + K = linalg.solve(inner + 4e-6 * trace * np.eye(G.shape[0]), G).T + K /= np.linalg.norm(K, axis=1)[:, None] + X = np.dot(K, M) + + indices = np.argsort(np.sum(X**2, axis=1))[-10:] + active_set = np.zeros(G.shape[1], dtype=bool) + for idx in indices: + idx -= idx % n_orient + active_set[idx : idx + n_orient] = True + X = X[active_set] + return X, active_set + + +# %% +# Apply your custom solver + +# loose, depth = 0.2, 0.8 # corresponds to loose orientation +loose, depth = 1.0, 0.0 # corresponds to free orientation +stc = apply_solver(solver, evoked, forward, noise_cov, loose, depth) + +# %% +# View in 2D and 3D ("glass" brain like 3D plot) +plot_sparse_source_estimates(forward["src"], stc, bgcolor=(1, 1, 1), opacity=0.1) diff --git a/mne-python/source/examples/inverse/dics_epochs.py b/mne-python/source/examples/inverse/dics_epochs.py new file mode 100644 index 0000000000000000000000000000000000000000..1900e3af34bd7a5a259bc02c00acd57159569a3d --- /dev/null +++ b/mne-python/source/examples/inverse/dics_epochs.py @@ -0,0 +1,133 @@ +""" +.. _ex-inverse-dics-epochs: + +======================================================================= +Compute source level time-frequency timecourses using a DICS beamformer +======================================================================= + +In this example, a Dynamic Imaging of Coherent Sources (DICS) :footcite:`GrossEtAl2001` +beamformer is used to transform sensor-level time-frequency objects to the source level. +We will look at the event-related synchronization (ERS) of beta band activity in the +:ref:`somato dataset `. +""" +# Authors: Marijn van Vliet +# Alex Rockhill +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +import mne +from mne.beamformer import apply_dics_tfr_epochs, make_dics +from mne.datasets import somato +from mne.time_frequency import csd_tfr + +print(__doc__) + +# %% +# Organize the data that we will use for this example. + +data_path = somato.data_path() +subject = "01" +task = "somato" +raw_fname = data_path / f"sub-{subject}" / "meg" / f"sub-{subject}_task-{task}_meg.fif" +fname_fwd = ( + data_path / "derivatives" / f"sub-{subject}" / f"sub-{subject}_task-{task}-fwd.fif" +) +subjects_dir = data_path / "derivatives" / "freesurfer" / "subjects" + +# %% +# First, we load the data and compute for each epoch the time-frequency +# decomposition in sensor space. + +# Load raw data and make epochs. +raw = mne.io.read_raw_fif(raw_fname) +events = mne.find_events(raw) +epochs = mne.Epochs( + raw, + events[:22], # just for execution speed of the tutorial + event_id=1, + tmin=-1, + tmax=2.5, + reject=dict( + grad=5000e-13, # unit: T / m (gradiometers) + mag=5e-12, # unit: T (magnetometers) + eog=250e-6, # unit: V (EOG channels) + ), + preload=True, +) + +# We are mostly interested in the beta band since it has been shown to be +# active for somatosensory stimulation +freqs = np.linspace(13, 31, 5) + +# Use Morlet wavelets to compute sensor-level time-frequency (TFR) +# decomposition for each epoch. We must pass ``output='complex'`` if we wish to +# use this TFR later with a DICS beamformer. We also pass ``average=False`` to +# compute the TFR for each individual epoch. +epochs_tfr = epochs.compute_tfr( + "morlet", freqs, n_cycles=5, return_itc=False, output="complex", average=False +) + +# crop either side to use a buffer to remove edge artifact +epochs_tfr.crop(tmin=-0.5, tmax=2) + +# %% +# Now, we build a DICS beamformer and project the sensor-level TFR to the +# source level. + +# Compute the Cross-Spectral Density (CSD) matrix for the sensor-level TFRs. +# We are interested in increases in power relative to the baseline period, so +# we will make a separate CSD for just that period as well. +csd = csd_tfr(epochs_tfr, tmin=-0.5, tmax=2) +baseline_csd = csd_tfr(epochs_tfr, tmin=-0.5, tmax=-0.1) + +# use the CSDs and the forward model to build the DICS beamformer +fwd = mne.read_forward_solution(fname_fwd) + +# compute scalar DICS beamfomer +filters = make_dics( + epochs.info, + fwd, + csd, + noise_csd=baseline_csd, + pick_ori="max-power", + reduce_rank=True, + real_filter=True, +) + +# project the TFR for each epoch to source space +epochs_stcs = apply_dics_tfr_epochs(epochs_tfr, filters, return_generator=True) + +# average across frequencies and epochs +data = np.zeros((fwd["nsource"], epochs_tfr.times.size)) +for epoch_stcs in epochs_stcs: + for stc in epoch_stcs: + data += (stc.data * np.conj(stc.data)).real + +stc.data = data / len(epochs) / len(freqs) + +# apply a baseline correction +stc.apply_baseline((-0.5, -0.1)) + +# %% +# Let's visualize the source time course estimate. We can see the +# expected activation of the two gyri bordering the central sulcus, the +# primary somatosensory and motor cortices (S1 and M1). + +fmax = 4500 +brain = stc.plot( + subjects_dir=subjects_dir, + hemi="both", + views="dorsal", + initial_time=1.2, + brain_kwargs=dict(show=False), + add_data_kwargs=dict( + fmin=fmax / 10, + fmid=fmax / 2, + fmax=fmax, + scale_factor=0.0001, + colorbar_kwargs=dict(label_font_size=10), + ), +) diff --git a/mne-python/source/examples/inverse/dics_source_power.py b/mne-python/source/examples/inverse/dics_source_power.py new file mode 100644 index 0000000000000000000000000000000000000000..586044cdd9fe2c54446d308d145dd487913563f3 --- /dev/null +++ b/mne-python/source/examples/inverse/dics_source_power.py @@ -0,0 +1,116 @@ +""" +.. _ex-inverse-source-power: + +========================================== +Compute source power using DICS beamformer +========================================== + +Compute a Dynamic Imaging of Coherent Sources (DICS) :footcite:`GrossEtAl2001` +filter from single-trial activity to estimate source power across a frequency +band. This example demonstrates how to source localize the event-related +synchronization (ERS) of beta band activity in the +:ref:`somato dataset `. +""" +# Author: Marijn van Vliet +# Roman Goj +# Denis Engemann +# Stefan Appelhoff +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.beamformer import apply_dics_csd, make_dics +from mne.datasets import somato +from mne.time_frequency import csd_morlet + +print(__doc__) + +# %% +# Reading the raw data and creating epochs: +data_path = somato.data_path() +subject = "01" +task = "somato" +raw_fname = data_path / f"sub-{subject}" / "meg" / f"sub-{subject}_task-{task}_meg.fif" + +# Use a shorter segment of raw just for speed here +raw = mne.io.read_raw_fif(raw_fname) +raw.crop(0, 120) # one minute for speed (looks similar to using all ~800 s) + +# Read epochs +events = mne.find_events(raw) + +epochs = mne.Epochs(raw, events, event_id=1, tmin=-1.5, tmax=2, preload=True) +del raw + +# Paths to forward operator and FreeSurfer subject directory +fname_fwd = ( + data_path / "derivatives" / f"sub-{subject}" / f"sub-{subject}_task-{task}-fwd.fif" +) + +subjects_dir = data_path / "derivatives" / "freesurfer" / "subjects" + +# %% +# We are interested in the beta band. Define a range of frequencies, using a +# log scale, from 12 to 30 Hz. +freqs = np.logspace(np.log10(12), np.log10(30), 9) + +# %% +# Computing the cross-spectral density matrix for the beta frequency band, for +# different time intervals. We use a decim value of 20 to speed up the +# computation in this example at the loss of accuracy. +csd = csd_morlet(epochs, freqs, tmin=-1, tmax=1.5, decim=20) +csd_baseline = csd_morlet(epochs, freqs, tmin=-1, tmax=0, decim=20) +# ERS activity starts at 0.5 seconds after stimulus onset +csd_ers = csd_morlet(epochs, freqs, tmin=0.5, tmax=1.5, decim=20) +info = epochs.info +del epochs + +# %% +# To compute the source power for a frequency band, rather than each frequency +# separately, we average the CSD objects across frequencies. +csd = csd.mean() +csd_baseline = csd_baseline.mean() +csd_ers = csd_ers.mean() + +# %% +# Computing DICS spatial filters using the CSD that was computed on the entire +# timecourse. +fwd = mne.read_forward_solution(fname_fwd) +filters = make_dics( + info, + fwd, + csd, + noise_csd=csd_baseline, + pick_ori="max-power", + reduce_rank=True, + real_filter=True, +) +del fwd + +# %% +# Applying DICS spatial filters separately to the CSD computed using the +# baseline and the CSD computed during the ERS activity. +baseline_source_power, freqs = apply_dics_csd(csd_baseline, filters) +beta_source_power, freqs = apply_dics_csd(csd_ers, filters) + +# %% +# Visualizing source power during ERS activity relative to the baseline power. +stc = beta_source_power / baseline_source_power +message = "DICS source power in the 12-30 Hz frequency band" +brain = stc.plot( + hemi="both", + views="axial", + subjects_dir=subjects_dir, + subject=subject, + time_label=message, +) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/evoked_ers_source_power.py b/mne-python/source/examples/inverse/evoked_ers_source_power.py new file mode 100644 index 0000000000000000000000000000000000000000..7e12b3c8028257ef57eaa7f7fbf498c25c6c3332 --- /dev/null +++ b/mne-python/source/examples/inverse/evoked_ers_source_power.py @@ -0,0 +1,193 @@ +""" +.. _ex-source-loc-methods: + +===================================================================== +Compute evoked ERS source power using DICS, LCMV beamformer, and dSPM +===================================================================== + +Here we examine 3 ways of localizing event-related synchronization (ERS) of +beta band activity in this dataset: :ref:`somato-dataset` using +:term:`DICS`, :term:`LCMV beamformer`, and :term:`dSPM` applied to active and +baseline covariance matrices. +""" +# Authors: Luke Bloy +# Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.beamformer import apply_dics_csd, apply_lcmv_cov, make_dics, make_lcmv +from mne.cov import compute_covariance +from mne.datasets import somato +from mne.minimum_norm import apply_inverse_cov, make_inverse_operator +from mne.time_frequency import csd_morlet + +print(__doc__) + +# %% +# Reading the raw data and creating epochs: +data_path = somato.data_path() +subject = "01" +task = "somato" +raw_fname = data_path / f"sub-{subject}" / "meg" / f"sub-{subject}_task-{task}_meg.fif" + +# crop to 5 minutes to save memory +raw = mne.io.read_raw_fif(raw_fname).crop(0, 300) + +# We are interested in the beta band (12-30 Hz) +raw.load_data().filter(12, 30) + +# The DICS beamformer currently only supports a single sensor type. +# We'll use the gradiometers in this example. +picks = mne.pick_types(raw.info, meg="grad", exclude="bads") + +# Read epochs +events = mne.find_events(raw) +epochs = mne.Epochs( + raw, events, event_id=1, tmin=-1.5, tmax=2, picks=picks, preload=True, decim=3 +) + +# Read forward operator and point to freesurfer subject directory +fname_fwd = ( + data_path / "derivatives" / f"sub-{subject}" / f"sub-{subject}_task-{task}-fwd.fif" +) +subjects_dir = data_path / "derivatives" / "freesurfer" / "subjects" + +fwd = mne.read_forward_solution(fname_fwd) + +# %% +# Compute covariances +# ------------------- +# ERS activity starts at 0.5 seconds after stimulus onset. Because these +# data have been processed by MaxFilter directly (rather than MNE-Python's +# version), we have to be careful to compute the rank with a more conservative +# threshold in order to get the correct data rank (64). Once this is used in +# combination with an advanced covariance estimator like "shrunk", the rank +# will be correctly preserved. + +rank = mne.compute_rank(epochs, tol=1e-6, tol_kind="relative") +active_win = (0.5, 1.5) +baseline_win = (-1, 0) +baseline_cov = compute_covariance( + epochs, + tmin=baseline_win[0], + tmax=baseline_win[1], + method="shrunk", + rank=rank, + verbose=True, +) +active_cov = compute_covariance( + epochs, + tmin=active_win[0], + tmax=active_win[1], + method="shrunk", + rank=rank, + verbose=True, +) + +# Weighted averaging is already in the addition of covariance objects. +common_cov = baseline_cov + active_cov +baseline_cov.plot(epochs.info) + +# %% +# Compute some source estimates +# ----------------------------- +# Here we will use DICS, LCMV beamformer, and dSPM. +# +# See :ref:`ex-inverse-source-power` for more information about DICS. + + +def _gen_dics(active_win, baseline_win, epochs): + freqs = np.logspace(np.log10(12), np.log10(30), 9) + csd = csd_morlet(epochs, freqs, tmin=-1, tmax=1.5, decim=20) + csd_baseline = csd_morlet( + epochs, freqs, tmin=baseline_win[0], tmax=baseline_win[1], decim=20 + ) + csd_ers = csd_morlet( + epochs, freqs, tmin=active_win[0], tmax=active_win[1], decim=20 + ) + filters = make_dics( + epochs.info, + fwd, + csd.mean(), + pick_ori="max-power", + reduce_rank=True, + real_filter=True, + rank=rank, + ) + stc_base, freqs = apply_dics_csd(csd_baseline.mean(), filters) + stc_act, freqs = apply_dics_csd(csd_ers.mean(), filters) + stc_act /= stc_base + return stc_act + + +# generate lcmv source estimate +def _gen_lcmv(active_cov, baseline_cov, common_cov): + filters = make_lcmv( + epochs.info, fwd, common_cov, reg=0.05, noise_cov=None, pick_ori="max-power" + ) + stc_base = apply_lcmv_cov(baseline_cov, filters) + stc_act = apply_lcmv_cov(active_cov, filters) + stc_act /= stc_base + return stc_act + + +# generate mne/dSPM source estimate +def _gen_mne(active_cov, baseline_cov, common_cov, fwd, info, method="dSPM"): + inverse_operator = make_inverse_operator(info, fwd, common_cov) + stc_act = apply_inverse_cov( + active_cov, info, inverse_operator, method=method, verbose=True + ) + stc_base = apply_inverse_cov( + baseline_cov, info, inverse_operator, method=method, verbose=True + ) + stc_act /= stc_base + return stc_act + + +# Compute source estimates +stc_dics = _gen_dics(active_win, baseline_win, epochs) +stc_lcmv = _gen_lcmv(active_cov, baseline_cov, common_cov) +stc_dspm = _gen_mne(active_cov, baseline_cov, common_cov, fwd, epochs.info) + +# %% +# Plot source estimates +# --------------------- +# DICS: + +# sphinx_gallery_thumbnail_number = 3 +brain_dics = stc_dics.plot( + hemi="rh", + subjects_dir=subjects_dir, + subject=subject, + time_label="DICS source power in the 12-30 Hz frequency band", +) + +# %% +# LCMV: + +brain_lcmv = stc_lcmv.plot( + hemi="rh", + subjects_dir=subjects_dir, + subject=subject, + time_label="LCMV source power in the 12-30 Hz frequency band", +) + +# %% +# dSPM: + +brain_dspm = stc_dspm.plot( + hemi="rh", + subjects_dir=subjects_dir, + subject=subject, + time_label="dSPM source power in the 12-30 Hz frequency band", +) + +# %% +# For more advanced usage, see +# :ref:`mne-gui-addons:sphx_glr_auto_examples_evoked_ers_source_power.py`. diff --git a/mne-python/source/examples/inverse/gamma_map_inverse.py b/mne-python/source/examples/inverse/gamma_map_inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..1085a6bb7495a1141f681075b8d4ea972fa7ce62 --- /dev/null +++ b/mne-python/source/examples/inverse/gamma_map_inverse.py @@ -0,0 +1,120 @@ +""" +.. _ex-gamma-map: + +=============================================================================== +Compute a sparse inverse solution using the Gamma-MAP empirical Bayesian method +=============================================================================== + +See :footcite:`WipfNagarajan2009` for details. +""" +# Author: Martin Luessi +# Daniel Strohmeier +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.datasets import sample +from mne.inverse_sparse import gamma_map, make_stc_from_dipoles +from mne.viz import ( + plot_dipole_amplitudes, + plot_dipole_locations, + plot_sparse_source_estimates, +) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +evoked_fname = meg_path / "sample_audvis-ave.fif" +cov_fname = meg_path / "sample_audvis-cov.fif" + +# Read the evoked response and crop it +condition = "Left visual" +evoked = mne.read_evokeds(evoked_fname, condition=condition, baseline=(None, 0)) +evoked.crop(tmin=-50e-3, tmax=300e-3) + +# Read the forward solution +forward = mne.read_forward_solution(fwd_fname) + +# Read noise noise covariance matrix and regularize it +cov = mne.read_cov(cov_fname) +cov = mne.cov.regularize(cov, evoked.info, rank=None) + +# Run the Gamma-MAP method with dipole output +alpha = 0.5 +dipoles, residual = gamma_map( + evoked, + forward, + cov, + alpha, + xyz_same_gamma=True, + return_residual=True, + return_as_dipoles=True, +) + +# %% +# Plot dipole activations +plot_dipole_amplitudes(dipoles) + +# Plot dipole location of the strongest dipole with MRI slices +idx = np.argmax([np.max(np.abs(dip.amplitude)) for dip in dipoles]) +plot_dipole_locations( + dipoles[idx], + forward["mri_head_t"], + "sample", + subjects_dir=subjects_dir, + mode="orthoview", + idx="amplitude", +) + +# # Plot dipole locations of all dipoles with MRI slices +# for dip in dipoles: +# plot_dipole_locations(dip, forward['mri_head_t'], 'sample', +# subjects_dir=subjects_dir, mode='orthoview', +# idx='amplitude') + +# %% +# Show the evoked response and the residual for gradiometers +ylim = dict(grad=[-120, 120]) +evoked.pick(picks="grad", exclude="bads") +evoked.plot( + titles=dict(grad="Evoked Response Gradiometers"), + ylim=ylim, + proj=True, + time_unit="s", +) + +residual.pick(picks="grad", exclude="bads") +residual.plot( + titles=dict(grad="Residuals Gradiometers"), ylim=ylim, proj=True, time_unit="s" +) + +# %% +# Generate stc from dipoles +stc = make_stc_from_dipoles(dipoles, forward["src"]) + +# %% +# View in 2D and 3D ("glass" brain like 3D plot) +# Show the sources as spheres scaled by their strength +scale_factors = np.max(np.abs(stc.data), axis=1) +scale_factors = 0.5 * (1 + scale_factors / np.max(scale_factors)) + +plot_sparse_source_estimates( + forward["src"], + stc, + bgcolor=(1, 1, 1), + modes=["sphere"], + opacity=0.1, + scale_factors=(scale_factors, None), + fig_name="Gamma-MAP", +) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/label_activation_from_stc.py b/mne-python/source/examples/inverse/label_activation_from_stc.py new file mode 100644 index 0000000000000000000000000000000000000000..daaf4c4ae12e935f56a35f0dc5b53bddc282b1c9 --- /dev/null +++ b/mne-python/source/examples/inverse/label_activation_from_stc.py @@ -0,0 +1,68 @@ +""" +.. _ex-label-time-course: + +================================================== +Extracting time course from source_estimate object +================================================== + +Load a SourceEstimate object from stc files and +extract the time course of activation in +individual labels, as well as in a complex label +formed through merging two labels. + +""" +# Author: Christian Brodbeck +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" + +# load the stc +stc = mne.read_source_estimate(meg_path / "sample_audvis-meg") + +# load the labels +aud_lh = mne.read_label(meg_path / "labels" / "Aud-lh.label") +aud_rh = mne.read_label(meg_path / "labels" / "Aud-rh.label") + +# extract the time course for different labels from the stc +stc_lh = stc.in_label(aud_lh) +stc_rh = stc.in_label(aud_rh) +stc_bh = stc.in_label(aud_lh + aud_rh) + +# calculate center of mass and transform to mni coordinates +vtx, _, t_lh = stc_lh.center_of_mass("sample", subjects_dir=subjects_dir) +mni_lh = mne.vertex_to_mni(vtx, 0, "sample", subjects_dir=subjects_dir)[0] +vtx, _, t_rh = stc_rh.center_of_mass("sample", subjects_dir=subjects_dir) +mni_rh = mne.vertex_to_mni(vtx, 1, "sample", subjects_dir=subjects_dir)[0] + +# plot the activation +plt.figure() +plt.axes([0.1, 0.275, 0.85, 0.625]) +hl = plt.plot(stc.times, stc_lh.data.mean(0), "b")[0] +hr = plt.plot(stc.times, stc_rh.data.mean(0), "g")[0] +hb = plt.plot(stc.times, stc_bh.data.mean(0), "r")[0] +plt.xlabel("Time (s)") +plt.ylabel("Source amplitude (dSPM)") +plt.xlim(stc.times[0], stc.times[-1]) + +# add a legend including center-of-mass mni coordinates to the plot +labels = [ + f"LH: center of mass = {mni_lh.round(2)}", + f"RH: center of mass = {mni_rh.round(2)}", + "Combined LH & RH", +] +plt.figlegend([hl, hr, hb], labels, loc="lower center") +plt.suptitle("Average activation in auditory cortex labels", fontsize=20) +plt.show() diff --git a/mne-python/source/examples/inverse/label_from_stc.py b/mne-python/source/examples/inverse/label_from_stc.py new file mode 100644 index 0000000000000000000000000000000000000000..76545d4895faabc65bdfbd4764b7f45a379dc14f --- /dev/null +++ b/mne-python/source/examples/inverse/label_from_stc.py @@ -0,0 +1,116 @@ +""" +.. _ex-functional-label: + +================================================= +Generate a functional label from source estimates +================================================= + +Threshold source estimates and produce a functional label. The label +is typically the region of interest that contains high values. +Here we compare the average time course in the anatomical label obtained +by FreeSurfer segmentation and the average time course from the +functional label. As expected the time course in the functional +label yields higher values. +""" +# Author: Luke Bloy +# Alex Gramfort +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.datasets import sample +from mne.minimum_norm import apply_inverse, read_inverse_operator + +print(__doc__) + +data_path = sample.data_path() +fname_inv = data_path / "MEG" / "sample" / "sample_audvis-meg-oct-6-meg-inv.fif" +fname_evoked = data_path / "MEG" / "sample" / "sample_audvis-ave.fif" +subjects_dir = data_path / "subjects" +subject = "sample" + +snr = 3.0 +lambda2 = 1.0 / snr**2 +method = "dSPM" # use dSPM method (could also be MNE or sLORETA) + +# Compute a label/ROI based on the peak power between 80 and 120 ms. +# The label bankssts-lh is used for the comparison. +aparc_label_name = "bankssts-lh" +tmin, tmax = 0.080, 0.120 + +# Load data +evoked = mne.read_evokeds(fname_evoked, condition=0, baseline=(None, 0)) +inverse_operator = read_inverse_operator(fname_inv) +src = inverse_operator["src"] # get the source space + +# Compute inverse solution +stc = apply_inverse(evoked, inverse_operator, lambda2, method, pick_ori="normal") + +# Make an STC in the time interval of interest and take the mean +stc_mean = stc.copy().crop(tmin, tmax).mean() + +# use the stc_mean to generate a functional label +# region growing is halted at 60% of the peak value within the +# anatomical label / ROI specified by aparc_label_name +label = mne.read_labels_from_annot( + subject, parc="aparc", subjects_dir=subjects_dir, regexp=aparc_label_name +)[0] +stc_mean_label = stc_mean.in_label(label) +data = np.abs(stc_mean_label.data) +stc_mean_label.data[data < 0.6 * np.max(data)] = 0.0 + +# 8.5% of original source space vertices were omitted during forward +# calculation, suppress the warning here with verbose='error' +func_labels, _ = mne.stc_to_label( + stc_mean_label, + src=src, + smooth=True, + subjects_dir=subjects_dir, + connected=True, + verbose="error", +) + +# take first as func_labels are ordered based on maximum values in stc +func_label = func_labels[0] + +# load the anatomical ROI for comparison +anat_label = mne.read_labels_from_annot( + subject, parc="aparc", subjects_dir=subjects_dir, regexp=aparc_label_name +)[0] + +# extract the anatomical time course for each label +stc_anat_label = stc.in_label(anat_label) +pca_anat = stc.extract_label_time_course(anat_label, src, mode="pca_flip")[0] + +stc_func_label = stc.in_label(func_label) +pca_func = stc.extract_label_time_course(func_label, src, mode="pca_flip")[0] + +# flip the pca so that the max power between tmin and tmax is positive +pca_anat *= np.sign(pca_anat[np.argmax(np.abs(pca_anat))]) +pca_func *= np.sign(pca_func[np.argmax(np.abs(pca_anat))]) + +# %% +# plot the time courses.... +plt.figure() +plt.plot( + 1e3 * stc_anat_label.times, pca_anat, "k", label=f"Anatomical {aparc_label_name}" +) +plt.plot( + 1e3 * stc_func_label.times, pca_func, "b", label=f"Functional {aparc_label_name}" +) +plt.legend() +plt.show() + +# %% +# plot brain in 3D with mne.viz.Brain if available +brain = stc_mean.plot(hemi="lh", subjects_dir=subjects_dir) +brain.show_view("lateral") + +# show both labels +brain.add_label(anat_label, borders=True, color="k") +brain.add_label(func_label, borders=True, color="b") diff --git a/mne-python/source/examples/inverse/label_source_activations.py b/mne-python/source/examples/inverse/label_source_activations.py new file mode 100644 index 0000000000000000000000000000000000000000..74d338486b0bcc9691c130517237147d427971f9 --- /dev/null +++ b/mne-python/source/examples/inverse/label_source_activations.py @@ -0,0 +1,119 @@ +""" +.. _ex-label-time-series: + +==================================================== +Extracting the time series of activations in a label +==================================================== + +We first apply a dSPM inverse operator to get signed activations in a label +(with positive and negative values) and we then compare different strategies +to average the times series in a label. We compare a simple average, with an +averaging using the dipoles normal (flip mode) and then a PCA, +also using a sign flip. +""" +# Authors: Alexandre Gramfort +# Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.patheffects as path_effects +import matplotlib.pyplot as plt + +import mne +from mne.datasets import sample +from mne.minimum_norm import apply_inverse, read_inverse_operator + +print(__doc__) + +data_path = sample.data_path() +label = "Aud-lh" +meg_path = data_path / "MEG" / "sample" +label_fname = meg_path / "labels" / f"{label}.label" +fname_inv = meg_path / "sample_audvis-meg-oct-6-meg-inv.fif" +fname_evoked = meg_path / "sample_audvis-ave.fif" + +snr = 3.0 +lambda2 = 1.0 / snr**2 +method = "dSPM" # use dSPM method (could also be MNE or sLORETA) + +# Load data +evoked = mne.read_evokeds(fname_evoked, condition=0, baseline=(None, 0)) +inverse_operator = read_inverse_operator(fname_inv) +src = inverse_operator["src"] + +# %% +# Compute inverse solution +# ------------------------ +pick_ori = "normal" # Get signed values to see the effect of sign flip +stc = apply_inverse(evoked, inverse_operator, lambda2, method, pick_ori=pick_ori) + +label = mne.read_label(label_fname) + +stc_label = stc.in_label(label) +modes = ("mean", "mean_flip", "pca_flip") +tcs = dict() +for mode in modes: + tcs[mode] = stc.extract_label_time_course(label, src, mode=mode) +print(f"Number of vertices : {len(stc_label.data)}") + +# %% +# View source activations +# ----------------------- + +fig, ax = plt.subplots(1, layout="constrained") +t = 1e3 * stc_label.times +ax.plot(t, stc_label.data.T, "k", linewidth=0.5, alpha=0.5) +pe = [ + path_effects.Stroke(linewidth=5, foreground="w", alpha=0.5), + path_effects.Normal(), +] +for mode, tc in tcs.items(): + ax.plot(t, tc[0], linewidth=3, label=str(mode), path_effects=pe) +xlim = t[[0, -1]] +ylim = [-27, 22] +ax.legend(loc="upper right") +ax.set( + xlabel="Time (ms)", + ylabel="Source amplitude", + title=f"Activations in Label {label.name!r}", + xlim=xlim, + ylim=ylim, +) + +# %% +# Using vector solutions +# ---------------------- +# It's also possible to compute label time courses for a +# :class:`mne.VectorSourceEstimate`, but only with ``mode='mean'``. + +pick_ori = "vector" +stc_vec = apply_inverse(evoked, inverse_operator, lambda2, method, pick_ori=pick_ori) +data = stc_vec.extract_label_time_course(label, src) +fig, ax = plt.subplots(1, layout="constrained") +stc_vec_label = stc_vec.in_label(label) +colors = ["#EE6677", "#228833", "#4477AA"] +for ii, name in enumerate("XYZ"): + color = colors[ii] + ax.plot( + t, stc_vec_label.data[:, ii].T, color=color, lw=0.5, alpha=0.5, zorder=5 - ii + ) + ax.plot( + t, + data[0, ii], + lw=3, + color=color, + label="+" + name, + zorder=8 - ii, + path_effects=pe, + ) +ax.legend(loc="upper right") +ax.set( + xlabel="Time (ms)", + ylabel="Source amplitude", + title=f"Mean vector activations in Label {label.name!r}", + xlim=xlim, + ylim=ylim, +) diff --git a/mne-python/source/examples/inverse/mixed_norm_inverse.py b/mne-python/source/examples/inverse/mixed_norm_inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..70764a53973352d4761aac8f07db483001392414 --- /dev/null +++ b/mne-python/source/examples/inverse/mixed_norm_inverse.py @@ -0,0 +1,169 @@ +""" +.. _ex-mixed-norm-inverse: + +================================================================ +Compute sparse inverse solution with mixed norm: MxNE and irMxNE +================================================================ + +Runs an (ir)MxNE (L1/L2 :footcite:`GramfortEtAl2012` or L0.5/L2 +:footcite:`StrohmeierEtAl2014` mixed norm) inverse solver. +L0.5/L2 is done with irMxNE which allows for sparser source estimates with less +amplitude bias due to the non-convexity of the L0.5/L2 mixed norm penalty. +""" +# Author: Alexandre Gramfort +# Daniel Strohmeier +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +# sphinx_gallery_thumbnail_number = 2 + +import numpy as np + +import mne +from mne.datasets import sample +from mne.inverse_sparse import make_stc_from_dipoles, mixed_norm +from mne.minimum_norm import apply_inverse, make_inverse_operator +from mne.viz import ( + plot_dipole_amplitudes, + plot_dipole_locations, + plot_sparse_source_estimates, +) + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +ave_fname = meg_path / "sample_audvis-ave.fif" +cov_fname = meg_path / "sample_audvis-shrunk-cov.fif" +subjects_dir = data_path / "subjects" + +# Read noise covariance matrix +cov = mne.read_cov(cov_fname) +# Handling average file +condition = "Left Auditory" +evoked = mne.read_evokeds(ave_fname, condition=condition, baseline=(None, 0)) +evoked.crop(tmin=0, tmax=0.3) +# Handling forward solution +forward = mne.read_forward_solution(fwd_fname) + +# %% +# Run solver with SURE criterion :footcite:`DeledalleEtAl2014` +alpha = "sure" # regularization parameter between 0 and 100 or SURE criterion +loose, depth = 0.9, 0.9 # loose orientation & depth weighting +n_mxne_iter = 10 # if > 1 use L0.5/L2 reweighted mixed norm solver +# if n_mxne_iter > 1 dSPM weighting can be avoided. + +# Compute dSPM solution to be used as weights in MxNE +inverse_operator = make_inverse_operator( + evoked.info, forward, cov, depth=depth, fixed=True, use_cps=True +) +stc_dspm = apply_inverse(evoked, inverse_operator, lambda2=1.0 / 9.0, method="dSPM") + +# Compute (ir)MxNE inverse solution with dipole output +dipoles, residual = mixed_norm( + evoked, + forward, + cov, + alpha, + loose=loose, + depth=depth, + maxit=3000, + tol=1e-4, + active_set_size=10, + debias=False, + weights=stc_dspm, + weights_min=8.0, + n_mxne_iter=n_mxne_iter, + return_residual=True, + return_as_dipoles=True, + verbose=True, + random_state=0, + # for this dataset we know we should use a high alpha, so avoid some + # of the slower (lower) alpha values + sure_alpha_grid=np.linspace(100, 40, 10), +) + +t = 0.083 +tidx = evoked.time_as_index(t).item() +for di, dip in enumerate(dipoles, 1): + print(f"Dipole #{di} GOF at {1000 * t:0.1f} ms: {float(dip.gof[tidx]):0.1f}%") + +# %% +# Plot dipole activations +plot_dipole_amplitudes(dipoles) + +# Plot dipole location of the strongest dipole with MRI slices +idx = np.argmax([np.max(np.abs(dip.amplitude)) for dip in dipoles]) +plot_dipole_locations( + dipoles[idx], + forward["mri_head_t"], + "sample", + subjects_dir=subjects_dir, + mode="orthoview", + idx="amplitude", +) + +# Plot dipole locations of all dipoles with MRI slices +for dip in dipoles: + plot_dipole_locations( + dip, + forward["mri_head_t"], + "sample", + subjects_dir=subjects_dir, + mode="orthoview", + idx="amplitude", + ) + +# %% +# Plot residual +ylim = dict(eeg=[-10, 10], grad=[-400, 400], mag=[-600, 600]) +evoked.pick(picks=["meg", "eeg"], exclude="bads") +evoked.plot(ylim=ylim, proj=True, time_unit="s") +residual.pick(picks=["meg", "eeg"], exclude="bads") +residual.plot(ylim=ylim, proj=True, time_unit="s") + +# %% +# Generate stc from dipoles +stc = make_stc_from_dipoles(dipoles, forward["src"]) + +# %% +# View in 2D and 3D ("glass" brain like 3D plot) +solver = "MxNE" if n_mxne_iter == 1 else "irMxNE" +plot_sparse_source_estimates( + forward["src"], + stc, + bgcolor=(1, 1, 1), + fig_name=f"{solver} (cond {condition})", + opacity=0.1, +) + +# %% +# Morph onto fsaverage brain and view +morph = mne.compute_source_morph( + stc, + subject_from="sample", + subject_to="fsaverage", + spacing=None, + sparse=True, + subjects_dir=subjects_dir, +) +stc_fsaverage = morph.apply(stc) +src_fsaverage_fname = subjects_dir / "fsaverage" / "bem" / "fsaverage-ico-5-src.fif" +src_fsaverage = mne.read_source_spaces(src_fsaverage_fname) + +plot_sparse_source_estimates( + src_fsaverage, + stc_fsaverage, + bgcolor=(1, 1, 1), + fig_name=f"Morphed {solver} (cond {condition})", + opacity=0.1, +) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/mixed_source_space_inverse.py b/mne-python/source/examples/inverse/mixed_source_space_inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..c4e5d29fbf3a43e63e6070c31a87f88409c83baa --- /dev/null +++ b/mne-python/source/examples/inverse/mixed_source_space_inverse.py @@ -0,0 +1,201 @@ +""" +.. _ex-mixed-source-space-inverse: + +===================================================================== +Compute MNE inverse solution on evoked data with a mixed source space +===================================================================== + +Create a mixed source space and compute an MNE inverse solution on an evoked dataset. +""" +# Author: Annalisa Pascarella +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +from nilearn import plotting + +import mne +from mne.minimum_norm import apply_inverse, make_inverse_operator + +# Set dir +data_path = mne.datasets.sample.data_path() +subject = "sample" +data_dir = data_path / "MEG" / subject +subjects_dir = data_path / "subjects" +bem_dir = subjects_dir / subject / "bem" + +# Set file names +fname_mixed_src = bem_dir / f"{subject}-oct-6-mixed-src.fif" +fname_aseg = subjects_dir / subject / "mri" / "aseg.mgz" + +fname_model = bem_dir / f"{subject}-5120-bem.fif" +fname_bem = bem_dir / f"{subject}-5120-bem-sol.fif" + +fname_evoked = data_dir / f"{subject}_audvis-ave.fif" +fname_trans = data_dir / f"{subject}_audvis_raw-trans.fif" +fname_fwd = data_dir / f"{subject}_audvis-meg-oct-6-mixed-fwd.fif" +fname_cov = data_dir / f"{subject}_audvis-shrunk-cov.fif" + +# %% +# Set up our source space +# ----------------------- +# List substructures we are interested in. We select only the +# sub structures we want to include in the source space: + +labels_vol = [ + "Left-Amygdala", + "Left-Thalamus-Proper", + "Left-Cerebellum-Cortex", + "Brain-Stem", + "Right-Amygdala", + "Right-Thalamus-Proper", + "Right-Cerebellum-Cortex", +] + +# %% +# Get a surface-based source space, here with few source points for speed +# in this demonstration, in general you should use oct6 spacing! +src = mne.setup_source_space( + subject, spacing="oct5", add_dist=False, subjects_dir=subjects_dir +) + +# %% +# Now we create a mixed src space by adding the volume regions specified in the +# list labels_vol. First, read the aseg file and the source space bounds +# using the inner skull surface (here using 10mm spacing to save time, +# we recommend something smaller like 5.0 in actual analyses): + +vol_src = mne.setup_volume_source_space( + subject, + mri=fname_aseg, + pos=10.0, + bem=fname_model, + volume_label=labels_vol, + subjects_dir=subjects_dir, + add_interpolator=False, # just for speed, usually this should be True + verbose=True, +) + +# Generate the mixed source space +src += vol_src +print( + f"The source space contains {len(src)} spaces and " + f"{sum(s['nuse'] for s in src)} vertices" +) + +# %% +# View the source space +# --------------------- + +src.plot(subjects_dir=subjects_dir) + +# %% +# We could write the mixed source space with:: +# +# >>> write_source_spaces(fname_mixed_src, src, overwrite=True) +# +# We can also export source positions to NIfTI file and visualize it again: + +nii_fname = bem_dir / f"{subject}-mixed-src.nii" +src.export_volume(nii_fname, mri_resolution=True, overwrite=True) +plotting.plot_img(str(nii_fname), cmap="nipy_spectral") + +# %% +# Compute the fwd matrix +# ---------------------- +fwd = mne.make_forward_solution( + fname_evoked, + fname_trans, + src, + fname_bem, + mindist=5.0, # ignore sources<=5mm from innerskull + meg=True, + eeg=False, + n_jobs=None, +) +del src # save memory + +leadfield = fwd["sol"]["data"] +ns, nd = leadfield.shape +print(f"Leadfield size : {ns} sensors x {nd} dipoles") +print( + f"The fwd source space contains {len(fwd['src'])} spaces and " + f"{sum(s['nuse'] for s in fwd['src'])} vertices" +) + +# Load data +condition = "Left Auditory" +evoked = mne.read_evokeds(fname_evoked, condition=condition, baseline=(None, 0)) +noise_cov = mne.read_cov(fname_cov) + +# %% +# Compute inverse solution +# ------------------------ +snr = 3.0 # use smaller SNR for raw data +inv_method = "dSPM" # sLORETA, MNE, dSPM +parc = "aparc" # the parcellation to use, e.g., 'aparc' 'aparc.a2009s' +loose = dict(surface=0.2, volume=1.0) + +lambda2 = 1.0 / snr**2 + +inverse_operator = make_inverse_operator( + evoked.info, fwd, noise_cov, depth=None, loose=loose, verbose=True +) +del fwd + +stc = apply_inverse(evoked, inverse_operator, lambda2, inv_method, pick_ori=None) +src = inverse_operator["src"] + +# %% +# Plot the mixed source estimate +# ------------------------------ + +# sphinx_gallery_thumbnail_number = 3 +initial_time = 0.1 +stc_vec = apply_inverse( + evoked, inverse_operator, lambda2, inv_method, pick_ori="vector" +) +brain = stc_vec.plot( + hemi="both", + src=inverse_operator["src"], + views="coronal", + initial_time=initial_time, + subjects_dir=subjects_dir, + brain_kwargs=dict(silhouette=True), + smoothing_steps=7, +) + +# %% +# Plot the surface +# ---------------- +brain = stc.surface().plot( + initial_time=initial_time, subjects_dir=subjects_dir, smoothing_steps=7 +) +# %% +# Plot the volume +# --------------- + +fig = stc.volume().plot(initial_time=initial_time, src=src, subjects_dir=subjects_dir) + +# %% +# Process labels +# -------------- +# Average the source estimates within each label of the cortical parcellation +# and each sub structure contained in the src space + +# Get labels for FreeSurfer 'aparc' cortical parcellation with 34 labels/hemi +labels_parc = mne.read_labels_from_annot(subject, parc=parc, subjects_dir=subjects_dir) + +label_ts = mne.extract_label_time_course( + [stc], labels_parc, src, mode="mean", allow_empty=True +) + +# plot the times series of 2 labels +fig, axes = plt.subplots(1, layout="constrained") +axes.plot(1e3 * stc.times, label_ts[0][0, :], "k", label="bankssts-lh") +axes.plot(1e3 * stc.times, label_ts[0][-1, :].T, "r", label="Brain-stem") +axes.set(xlabel="Time (ms)", ylabel="MNE current (nAm)") +axes.legend() diff --git a/mne-python/source/examples/inverse/mne_cov_power.py b/mne-python/source/examples/inverse/mne_cov_power.py new file mode 100644 index 0000000000000000000000000000000000000000..a6cf0df181f5b9384c12207b1dd8ed337d0951c1 --- /dev/null +++ b/mne-python/source/examples/inverse/mne_cov_power.py @@ -0,0 +1,165 @@ +""" +.. _ex-cov-power: + +=================================================================== +Compute source power estimate by projecting the covariance with MNE +=================================================================== + +We can apply the MNE inverse operator to a covariance matrix to obtain +an estimate of source power. This is computationally more efficient than first +estimating the source timecourses and then computing their power. This +code is based on the code from :footcite:`Sabbagh2020` and has been useful to +correct for individual field spread using source localization in the context of +predictive modeling. + +References +---------- +.. footbibliography:: +""" +# Author: Denis A. Engemann +# Luke Bloy +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.datasets import sample +from mne.minimum_norm import apply_inverse_cov, make_inverse_operator + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +raw = mne.io.read_raw_fif(raw_fname) + +# %% +# Compute empty-room covariance +# ----------------------------- +# First we compute an empty-room covariance, which captures noise from the +# sensors and environment. + +raw_empty_room_fname = data_path / "MEG" / "sample" / "ernoise_raw.fif" +raw_empty_room = mne.io.read_raw_fif(raw_empty_room_fname) +raw_empty_room.crop(0, 30) # cropped just for speed +raw_empty_room.info["bads"] = ["MEG 2443"] +raw_empty_room.add_proj(raw.info["projs"]) +noise_cov = mne.compute_raw_covariance(raw_empty_room, method="shrunk") +del raw_empty_room + +# %% +# Epoch the data +# -------------- + +raw.pick(["meg", "stim", "eog"]).load_data().filter(4, 12) +raw.info["bads"] = ["MEG 2443"] +events = mne.find_events(raw, stim_channel="STI 014") +event_id = dict(aud_l=1, aud_r=2, vis_l=3, vis_r=4) +tmin, tmax = -0.2, 0.5 +baseline = (None, 0) # means from the first instant to t = 0 +reject = dict(grad=4000e-13, mag=4e-12, eog=150e-6) +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + proj=True, + picks=("meg", "eog"), + baseline=None, + reject=reject, + preload=True, + decim=5, + verbose="error", +) +del raw + +# %% +# Compute and plot covariances +# ---------------------------- +# In addition to the empty-room covariance above, we compute two additional +# covariances: +# +# 1. Baseline covariance, which captures signals not of interest in our +# analysis (e.g., sensor noise, environmental noise, physiological +# artifacts, and also resting-state-like brain activity / "noise"). +# 2. Data covariance, which captures our activation of interest (in addition +# to noise sources). + +base_cov = mne.compute_covariance( + epochs, tmin=-0.2, tmax=0, method="shrunk", verbose=True +) +data_cov = mne.compute_covariance( + epochs, tmin=0.0, tmax=0.2, method="shrunk", verbose=True +) + +fig_noise_cov = mne.viz.plot_cov(noise_cov, epochs.info, show_svd=False) +fig_base_cov = mne.viz.plot_cov(base_cov, epochs.info, show_svd=False) +fig_data_cov = mne.viz.plot_cov(data_cov, epochs.info, show_svd=False) + +# %% +# We can also look at the covariances using topomaps, here we just show the +# baseline and data covariances, followed by the data covariance whitened +# by the baseline covariance: + +evoked = epochs.average().pick("meg") +evoked.drop_channels(evoked.info["bads"]) +evoked.plot(time_unit="s") +evoked.plot_topomap(times=np.linspace(0.05, 0.15, 5), ch_type="mag") + +loop = { + "Noise": (noise_cov, dict()), + "Data": (data_cov, dict()), + "Whitened data": (data_cov, dict(noise_cov=noise_cov)), +} +for title, (_cov, _kw) in loop.items(): + fig = _cov.plot_topomap(evoked.info, "grad", **_kw) + fig.suptitle(title) + +# %% +# Apply inverse operator to covariance +# ------------------------------------ +# Finally, we can construct an inverse using the empty-room noise covariance: + +# Read the forward solution and compute the inverse operator +fname_fwd = meg_path / "sample_audvis-meg-oct-6-fwd.fif" +fwd = mne.read_forward_solution(fname_fwd) +# make an MEG inverse operator +info = evoked.info +inverse_operator = make_inverse_operator(info, fwd, noise_cov, loose=0.2, depth=0.8) + +# %% +# Project our data and baseline covariance to source space: + +stc_data = apply_inverse_cov( + data_cov, + evoked.info, + inverse_operator, + nave=len(epochs), + method="dSPM", + verbose=True, +) +stc_base = apply_inverse_cov( + base_cov, + evoked.info, + inverse_operator, + nave=len(epochs), + method="dSPM", + verbose=True, +) + +# %% +# And visualize power is relative to the baseline: + +# sphinx_gallery_thumbnail_number = 9 + +stc_data /= stc_base +brain = stc_data.plot( + subject="sample", + subjects_dir=subjects_dir, + clim=dict(kind="percent", lims=(50, 90, 98)), + smoothing_steps=7, +) diff --git a/mne-python/source/examples/inverse/morph_surface_stc.py b/mne-python/source/examples/inverse/morph_surface_stc.py new file mode 100644 index 0000000000000000000000000000000000000000..abf84345e146ffc5e3d963fdd4105e98b74c5eb9 --- /dev/null +++ b/mne-python/source/examples/inverse/morph_surface_stc.py @@ -0,0 +1,172 @@ +""" +.. _ex-morph-surface: + +============================= +Morph surface source estimate +============================= + +This example demonstrates how to morph an individual subject's +:class:`mne.SourceEstimate` to a common reference space. We achieve this using +:class:`mne.SourceMorph`. Pre-computed data will be morphed based on +a spherical representation of the cortex computed using the spherical +registration of :ref:`FreeSurfer ` +(https://surfer.nmr.mgh.harvard.edu/fswiki/SurfaceRegAndTemplates) +:footcite:`GreveEtAl2013`. This +transform will be used to morph the surface vertices of the subject towards the +reference vertices. Here we will use 'fsaverage' as a reference space (see +https://surfer.nmr.mgh.harvard.edu/fswiki/FsAverage). + +The transformation will be applied to the surface source estimate. A plot +depicting the successful morph will be created for the spherical and inflated +surface representation of ``'fsaverage'``, overlaid with the morphed surface +source estimate. + +.. note:: For background information about morphing see :ref:`ch_morph`. +""" +# Author: Tommy Clausner +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +import mne +from mne.datasets import sample + +print(__doc__) + +# %% +# Setup paths + +data_path = sample.data_path() +sample_dir = data_path / "MEG" / "sample" +subjects_dir = data_path / "subjects" +fname_src = subjects_dir / "sample" / "bem" / "sample-oct-6-src.fif" +fname_fwd = sample_dir / "sample_audvis-meg-oct-6-fwd.fif" +fname_fsaverage_src = subjects_dir / "fsaverage" / "bem" / "fsaverage-ico-5-src.fif" +fname_stc = sample_dir / "sample_audvis-meg" + +# %% +# Load example data + +# Read stc from file +stc = mne.read_source_estimate(fname_stc, subject="sample") + +# %% +# Setting up SourceMorph for SourceEstimate +# ----------------------------------------- +# +# In MNE, surface source estimates represent the source space simply as +# lists of vertices (see :ref:`tut-source-estimate-class`). +# This list can either be obtained from :class:`mne.SourceSpaces` (src) or from +# the ``stc`` itself. If you use the source space, be sure to use the +# source space from the forward or inverse operator, because vertices +# can be excluded during forward computation due to proximity to the BEM +# inner skull surface: + +src_orig = mne.read_source_spaces(fname_src) +print(src_orig) # n_used=4098, 4098 +fwd = mne.read_forward_solution(fname_fwd) +print(fwd["src"]) # n_used=3732, 3766 +print([len(v) for v in stc.vertices]) + +# %% +# We also need to specify the set of vertices to morph to. This can be done +# using the ``spacing`` parameter, but for consistency it's better to pass the +# ``src_to`` parameter. +# +# .. note:: +# Since the default values of :func:`mne.compute_source_morph` are +# ``spacing=5, subject_to='fsaverage'``, in this example +# we could actually omit the ``src_to`` and ``subject_to`` arguments +# below. The ico-5 ``fsaverage`` source space contains the +# special values ``[np.arange(10242)] * 2``, but in general this will +# not be true for other spacings or other subjects. Thus it is recommended +# to always pass the destination ``src`` for consistency. +# +# Initialize SourceMorph for SourceEstimate + +src_to = mne.read_source_spaces(fname_fsaverage_src) +print(src_to[0]["vertno"]) # special, np.arange(10242) +morph = mne.compute_source_morph( + stc, + subject_from="sample", + subject_to="fsaverage", + src_to=src_to, + subjects_dir=subjects_dir, +) + +# %% +# Apply morph to (Vector) SourceEstimate +# -------------------------------------- +# +# The morph will be applied to the source estimate data, by giving it as the +# first argument to the morph we computed above. + +stc_fsaverage = morph.apply(stc) + +# %% +# Plot results +# ------------ + +# Define plotting parameters +surfer_kwargs = dict( + hemi="lh", + subjects_dir=subjects_dir, + clim=dict(kind="value", lims=[8, 12, 15]), + views="lateral", + initial_time=0.09, + time_unit="s", + size=(800, 800), + smoothing_steps=5, +) + +# As spherical surface +brain = stc_fsaverage.plot(surface="sphere", **surfer_kwargs) + +# Add title +brain.add_text(0.1, 0.9, "Morphed to fsaverage (spherical)", "title", font_size=16) + +# %% +# As inflated surface +brain_inf = stc_fsaverage.plot(surface="inflated", **surfer_kwargs) + +# Add title +brain_inf.add_text(0.1, 0.9, "Morphed to fsaverage (inflated)", "title", font_size=16) + +# %% +# Reading and writing SourceMorph from and to disk +# ------------------------------------------------ +# +# An instance of SourceMorph can be saved, by calling +# :meth:`morph.save `. +# +# This method allows for specification of a filename under which the ``morph`` +# will be save in ".h5" format. If no file extension is provided, "-morph.h5" +# will be appended to the respective defined filename:: +# +# >>> morph.save('my-file-name') +# +# Reading a saved source morph can be achieved by using +# :func:`mne.read_source_morph`:: +# +# >>> morph = mne.read_source_morph('my-file-name-morph.h5') +# +# Once the environment is set up correctly, no information such as +# ``subject_from`` or ``subjects_dir`` must be provided, since it can be +# inferred from the data and use morph to 'fsaverage' by default. SourceMorph +# can further be used without creating an instance and assigning it to a +# variable. Instead :func:`mne.compute_source_morph` and +# :meth:`mne.SourceMorph.apply` can be +# easily chained into a handy one-liner. Taking this together the shortest +# possible way to morph data directly would be: + +stc_fsaverage = mne.compute_source_morph(stc, subjects_dir=subjects_dir).apply(stc) + +# %% +# For more examples, check out :ref:`examples using SourceMorph.apply +# `. +# +# +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/morph_volume_stc.py b/mne-python/source/examples/inverse/morph_volume_stc.py new file mode 100644 index 0000000000000000000000000000000000000000..67c7fa1152d71557ba89bb57c0d4bf18a70001a8 --- /dev/null +++ b/mne-python/source/examples/inverse/morph_volume_stc.py @@ -0,0 +1,169 @@ +""" +.. _ex-morph-volume: + +================================ +Morph volumetric source estimate +================================ + +This example demonstrates how to morph an individual subject's +:class:`mne.VolSourceEstimate` to a common reference space. We achieve this using +:class:`mne.SourceMorph`. Data will be morphed based on an affine transformation and +a nonlinear registration method known as Symmetric Diffeomorphic Registration (SDR) by +:footcite:`AvantsEtAl2008`. + +Transformation is estimated from the subject's anatomical T1 weighted MRI +(brain) to `FreeSurfer's 'fsaverage' T1 weighted MRI (brain) +`__. + +Afterwards the transformation will be applied to the volumetric source estimate. The +result will be plotted, showing the fsaverage T1 weighted anatomical MRI, overlaid with +the morphed volumetric source estimate. +""" +# Author: Tommy Clausner +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +import nibabel as nib +from nilearn.plotting import plot_glass_brain + +import mne +from mne.datasets import fetch_fsaverage, sample +from mne.minimum_norm import apply_inverse, read_inverse_operator + +print(__doc__) + +# %% +# Setup paths +sample_dir_raw = sample.data_path() +sample_dir = sample_dir_raw / "MEG" / "sample" +subjects_dir = sample_dir_raw / "subjects" + +fname_evoked = sample_dir / "sample_audvis-ave.fif" +fname_inv = sample_dir / "sample_audvis-meg-vol-7-meg-inv.fif" + +fname_t1_fsaverage = subjects_dir / "fsaverage" / "mri" / "brain.mgz" +fetch_fsaverage(subjects_dir) # ensure fsaverage src exists +fname_src_fsaverage = subjects_dir / "fsaverage" / "bem" / "fsaverage-vol-5-src.fif" + +# %% +# Compute example data. For reference see :ref:`ex-inverse-volume`. +# +# Load data: +evoked = mne.read_evokeds(fname_evoked, condition=0, baseline=(None, 0)) +inverse_operator = read_inverse_operator(fname_inv) + +# Apply inverse operator +stc = apply_inverse(evoked, inverse_operator, 1.0 / 3.0**2, "dSPM") + +# To save time +stc.crop(0.09, 0.09) + +# %% +# Get a SourceMorph object for VolSourceEstimate +# ---------------------------------------------- +# +# ``subject_from`` can typically be inferred from +# :class:`src `, +# and ``subject_to`` is set to 'fsaverage' by default. ``subjects_dir`` can be +# None when set in the environment. In that case SourceMorph can be initialized +# taking ``src`` as only argument. See :class:`mne.SourceMorph` for more +# details. +# +# The default parameter setting for *zooms* will cause the reference volumes +# to be resliced before computing the transform. A value of '5' would cause +# the function to reslice to an isotropic voxel size of 5 mm. The higher this +# value the less accurate but faster the computation will be. +# +# The recommended way to use this is to morph to a specific destination source +# space so that different ``subject_from`` morphs will go to the same space.` +# A standard usage for volumetric data reads: + +src_fs = mne.read_source_spaces(fname_src_fsaverage) +morph = mne.compute_source_morph( + inverse_operator["src"], + subject_from="sample", + subjects_dir=subjects_dir, + niter_affine=[10, 10, 5], + niter_sdr=[10, 10, 5], # just for speed + src_to=src_fs, + verbose=True, +) + +# %% +# Apply morph to VolSourceEstimate +# -------------------------------- +# +# The morph can be applied to the source estimate data, by giving it as the +# first argument to the :meth:`morph.apply() ` method. +# +# .. note:: +# Volumetric morphing is much slower than surface morphing because the +# volume for each time point is individually resampled and SDR morphed. +# The :meth:`mne.SourceMorph.compute_vol_morph_mat` method can be used +# to compute an equivalent sparse matrix representation by computing the +# transformation for each source point individually. This generally takes +# a few minutes to compute, but can be +# :meth:`saved ` to disk and be reused. The +# resulting sparse matrix operation is very fast (about 400× faster) to +# :meth:`apply `. This approach is more efficient +# when the number of time points to be morphed exceeds the number of +# source space points, which is generally in the thousands. This can +# easily occur when morphing many time points and multiple conditions. + +stc_fsaverage = morph.apply(stc) + +# %% +# Convert morphed VolSourceEstimate into NIfTI +# -------------------------------------------- +# +# We can convert our morphed source estimate into a NIfTI volume using +# :meth:`morph.apply(..., output='nifti1') `. + +# Create mri-resolution volume of results +img_fsaverage = morph.apply(stc, mri_resolution=2, output="nifti1") + +# %% +# Plot results +# ------------ + +# Load fsaverage anatomical image +t1_fsaverage = nib.load(fname_t1_fsaverage) + +# Plot glass brain (change to plot_anat to display an overlaid anatomical T1) +display = plot_glass_brain( + t1_fsaverage, title="subject results to fsaverage", draw_cross=False, annotate=True +) + +# Add functional data as overlay +display.add_overlay(img_fsaverage, transparency=0.75) + + +# %% +# Reading and writing SourceMorph from and to disk +# ------------------------------------------------ +# +# An instance of SourceMorph can be saved, by calling +# :meth:`morph.save `. +# +# This methods allows for specification of a filename under which the ``morph`` +# will be save in ".h5" format. If no file extension is provided, "-morph.h5" +# will be appended to the respective defined filename:: +# +# >>> morph.save('my-file-name') +# +# Reading a saved source morph can be achieved by using +# :func:`mne.read_source_morph`:: +# +# >>> morph = mne.read_source_morph('my-file-name-morph.h5') +# +# Once the environment is set up correctly, no information such as +# ``subject_from`` or ``subjects_dir`` must be provided, since it can be +# inferred from the data and used morph to 'fsaverage' by default, e.g.:: +# +# >>> morph.apply(stc) +# +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/multi_dipole_model.py b/mne-python/source/examples/inverse/multi_dipole_model.py new file mode 100644 index 0000000000000000000000000000000000000000..b6985bcc182b07d08ee3f7f5bcb18c9d9962a087 --- /dev/null +++ b/mne-python/source/examples/inverse/multi_dipole_model.py @@ -0,0 +1,173 @@ +""" +.. _ex-multi-dipole: + +================================================================= +Computing source timecourses with an XFit-like multi-dipole model +================================================================= + +MEGIN's XFit program offers a "guided ECD modeling" interface, where multiple +dipoles can be fitted interactively. By manually selecting subsets of sensors +and time ranges, dipoles can be fitted to specific signal components. Then, +source timecourses can be computed using a multi-dipole model. The advantage of +using a multi-dipole model over fitting each dipole in isolation, is that when +multiple dipoles contribute to the same signal component, the model can make +sure that activity assigned to one dipole is not also assigned to another. This +example shows how to build a multi-dipole model for estimating source +timecourses for evokeds or single epochs. + +The XFit program is the recommended approach for guided ECD modeling, because +it offers a convenient graphical user interface for it. These dipoles can then +be imported into MNE-Python by using the :func:`mne.read_dipole` function for +building and applying the multi-dipole model. In addition, this example will +also demonstrate how to perform guided ECD modeling using only MNE-Python +functionality, which is less convenient than using XFit, but has the benefit of +being reproducible. +""" +# Author: Marijn van Vliet +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +############################################################################### +# Importing everything and setting up the data paths for the MNE-Sample +# dataset. +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.channels import read_vectorview_selection +from mne.datasets import sample +from mne.minimum_norm import apply_inverse, apply_inverse_epochs, make_inverse_operator + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_raw.fif" +cov_fname = meg_path / "sample_audvis-shrunk-cov.fif" +bem_dir = data_path / "subjects" / "sample" / "bem" +bem_fname = bem_dir / "sample-5120-5120-5120-bem-sol.fif" + +############################################################################### +# Read the MEG data from the audvis experiment. Make epochs and evokeds for the +# left and right auditory conditions. +raw = mne.io.read_raw_fif(raw_fname) +raw = raw.pick(picks=["meg", "eog", "stim"]) +info = raw.info + +# Create epochs for auditory events +events = mne.find_events(raw) +event_id = dict(right=1, left=2) +epochs = mne.Epochs( + raw, + events, + event_id, + tmin=-0.1, + tmax=0.3, + baseline=(None, 0), + reject=dict(mag=4e-12, grad=4000e-13, eog=150e-6), +) + +# Create evokeds for left and right auditory stimulation +evoked_left = epochs["left"].average() +evoked_right = epochs["right"].average() + +############################################################################### +# Guided dipole modeling, meaning fitting dipoles to a manually selected subset +# of sensors as a manually chosen time, can now be performed in MEGINs XFit on +# the evokeds we computed above. However, it is possible to do it completely +# in MNE-Python. + +# Setup conductor model +cov = mne.read_cov(cov_fname) # bad channels were already excluded here +bem = mne.read_bem_solution(bem_fname) + +# Fit two dipoles at t=80ms. The first dipole is fitted using only the sensors +# on the left side of the helmet. The second dipole is fitted using only the +# sensors on the right side of the helmet. +picks_left = read_vectorview_selection("Left", info=info) +evoked_fit_left = evoked_left.copy().crop(0.08, 0.08) +evoked_fit_left.pick(picks_left) +cov_fit_left = cov.copy().pick_channels(picks_left, ordered=True) + +picks_right = read_vectorview_selection("Right", info=info) +picks_right = list(set(picks_right) - set(info["bads"])) +evoked_fit_right = evoked_right.copy().crop(0.08, 0.08) +evoked_fit_right.pick(picks_right) +cov_fit_right = cov.copy().pick_channels(picks_right, ordered=True) + +# Any SSS projections that are active on this data need to be re-normalized +# after picking channels. +evoked_fit_left.info.normalize_proj() +evoked_fit_right.info.normalize_proj() +cov_fit_left["projs"] = evoked_fit_left.info["projs"] +cov_fit_right["projs"] = evoked_fit_right.info["projs"] + +# Fit the dipoles with the subset of sensors. +dip_left, _ = mne.fit_dipole(evoked_fit_left, cov_fit_left, bem) +dip_right, _ = mne.fit_dipole(evoked_fit_right, cov_fit_right, bem) + +############################################################################### +# Now that we have the location and orientations of the dipoles, compute the +# full timecourses using MNE, assigning activity to both dipoles at the same +# time while preventing leakage between the two. We use a very low ``lambda`` +# value to ensure both dipoles are fully used. + +fwd, _ = mne.make_forward_dipole([dip_left, dip_right], bem, info) + +# Apply MNE inverse +inv = make_inverse_operator(info, fwd, cov, fixed=True, depth=0) +stc_left = apply_inverse(evoked_left, inv, method="MNE", lambda2=1e-6) +stc_right = apply_inverse(evoked_right, inv, method="MNE", lambda2=1e-6) + +# Plot the timecourses of the resulting source estimate +fig, axes = plt.subplots(nrows=2, sharex=True, sharey=True) +axes[0].plot(stc_left.times, stc_left.data.T) +axes[0].set_title("Left auditory stimulation") +axes[0].legend(["Dipole 1", "Dipole 2"]) +axes[1].plot(stc_right.times, stc_right.data.T) +axes[1].set_title("Right auditory stimulation") +axes[1].set_xlabel("Time (s)") +fig.supylabel("Dipole amplitude") + +############################################################################### +# We can also fit the timecourses to single epochs. Here, we do it for each +# experimental condition separately. + +stcs_left = apply_inverse_epochs(epochs["left"], inv, lambda2=1e-6, method="MNE") +stcs_right = apply_inverse_epochs(epochs["right"], inv, lambda2=1e-6, method="MNE") + +############################################################################### +# To summarize and visualize the single-epoch dipole amplitudes, we will create +# a detailed plot of the mean amplitude of the dipoles during different +# experimental conditions. + +# Summarize the single epoch timecourses by computing the mean amplitude from +# 60-90ms. +amplitudes_left = [] +amplitudes_right = [] +for stc in stcs_left: + amplitudes_left.append(stc.crop(0.06, 0.09).mean().data) +for stc in stcs_right: + amplitudes_right.append(stc.crop(0.06, 0.09).mean().data) +amplitudes = np.vstack([amplitudes_left, amplitudes_right]) + +# Visualize the epoch-by-epoch dipole ampltudes in a detailed figure. +n = len(amplitudes) +n_left = len(amplitudes_left) +mean_left = np.mean(amplitudes_left, axis=0) +mean_right = np.mean(amplitudes_right, axis=0) + +fig, ax = plt.subplots(figsize=(8, 4)) +ax.scatter(np.arange(n), amplitudes[:, 0], label="Dipole 1") +ax.scatter(np.arange(n), amplitudes[:, 1], label="Dipole 2") +transition_point = n_left - 0.5 +ax.plot([0, transition_point], [mean_left[0], mean_left[0]], color="C0") +ax.plot([0, transition_point], [mean_left[1], mean_left[1]], color="C1") +ax.plot([transition_point, n], [mean_right[0], mean_right[0]], color="C0") +ax.plot([transition_point, n], [mean_right[1], mean_right[1]], color="C1") +ax.axvline(transition_point, color="black") +ax.set_xlabel("Epochs") +ax.set_ylabel("Dipole amplitude") +ax.legend() +fig.suptitle("Single epoch dipole amplitudes") +fig.text(0.30, 0.9, "Left auditory stimulation", ha="center") +fig.text(0.70, 0.9, "Right auditory stimulation", ha="center") diff --git a/mne-python/source/examples/inverse/multidict_reweighted_tfmxne.py b/mne-python/source/examples/inverse/multidict_reweighted_tfmxne.py new file mode 100644 index 0000000000000000000000000000000000000000..aed27ea880bd3193e9b3b751d23394207ddf71f3 --- /dev/null +++ b/mne-python/source/examples/inverse/multidict_reweighted_tfmxne.py @@ -0,0 +1,122 @@ +""" +.. _ex-iterative-reweighted-tf-mxne: + +============================================================================== +Compute iterative reweighted TF-MxNE with multiscale time-frequency dictionary +============================================================================== + +The iterative reweighted TF-MxNE solver is a distributed inverse method +based on the TF-MxNE solver, which promotes focal (sparse) sources +:footcite:`StrohmeierEtAl2015`. The benefits of this approach are that: + +- it is spatio-temporal without assuming stationarity (source properties + can vary over time), +- activations are localized in space, time, and frequency in one step, +- the solver uses non-convex penalties in the TF domain, which results in a + solution less biased towards zero than when simple TF-MxNE is used, +- using a multiscale dictionary allows to capture short transient + activations along with slower brain waves :footcite:`BekhtiEtAl2016`. +""" +# Author: Mathurin Massias +# Yousra Bekhti +# Daniel Strohmeier +# Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.datasets import somato +from mne.inverse_sparse import make_stc_from_dipoles, tf_mixed_norm +from mne.viz import plot_sparse_source_estimates + +print(__doc__) + + +# %% +# Load somatosensory MEG data + +data_path = somato.data_path() +subject = "01" +task = "somato" +raw_fname = data_path / f"sub-{subject}" / "meg" / f"sub-{subject}_task-{task}_meg.fif" +fwd_fname = ( + data_path / "derivatives" / f"sub-{subject}" / f"sub-{subject}_task-{task}-fwd.fif" +) + +# Read evoked +raw = mne.io.read_raw_fif(raw_fname) +raw.pick(picks=["meg", "eog", "stim"]) +events = mne.find_events(raw, stim_channel="STI 014") + +reject = dict(grad=4000e-13, eog=350e-6) +event_id, tmin, tmax = dict(unknown=1), -0.5, 0.5 +epochs = mne.Epochs( + raw, events, event_id, tmin, tmax, reject=reject, baseline=(None, 0) +) +evoked = epochs.average() + +evoked.crop(tmin=0.0, tmax=0.2) + +# Compute noise covariance matrix +cov = mne.compute_covariance(epochs, rank="info", tmax=0.0) +del epochs, raw + +# Handling forward solution +forward = mne.read_forward_solution(fwd_fname) + +# %% +# Run iterative reweighted multidict TF-MxNE solver + +alpha, l1_ratio = 20, 0.05 +loose, depth = 0.9, 1.0 +# Use a multiscale time-frequency dictionary +wsize, tstep = [4, 16], [2, 4] + + +n_tfmxne_iter = 10 +# Compute TF-MxNE inverse solution with dipole output +dipoles, residual = tf_mixed_norm( + evoked, + forward, + cov, + alpha=alpha, + l1_ratio=l1_ratio, + n_tfmxne_iter=n_tfmxne_iter, + loose=loose, + depth=depth, + tol=1e-3, + wsize=wsize, + tstep=tstep, + return_as_dipoles=True, + return_residual=True, +) + +# %% +# Generate stc from dipoles + +stc = make_stc_from_dipoles(dipoles, forward["src"]) +plot_sparse_source_estimates( + forward["src"], + stc, + bgcolor=(1, 1, 1), + opacity=0.1, + fig_name=f"irTF-MxNE (cond {evoked.comment})", +) + +# %% +# Show the evoked response and the residual for gradiometers +ylim = dict(grad=[-300, 300]) +evoked.copy().pick(picks="grad").plot( + titles=dict(grad="Evoked Response: Gradiometers"), ylim=ylim +) +residual.copy().pick(picks="grad").plot( + titles=dict(grad="Residuals: Gradiometers"), ylim=ylim +) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/psf_ctf_label_leakage.py b/mne-python/source/examples/inverse/psf_ctf_label_leakage.py new file mode 100644 index 0000000000000000000000000000000000000000..4991ae6eaf3da2d7874df12d546fc6ed7639198b --- /dev/null +++ b/mne-python/source/examples/inverse/psf_ctf_label_leakage.py @@ -0,0 +1,209 @@ +""" +.. _ex-source-leakage: + +============================================================ +Visualize source leakage among labels using a circular graph +============================================================ + +This example computes all-to-all pairwise leakage among 68 regions in +source space based on MNE inverse solutions and a FreeSurfer cortical +parcellation. Label-to-label leakage is estimated as the correlation among the +labels' point-spread functions (PSFs). It is visualized using a circular graph +which is ordered based on the locations of the regions in the axial plane. +""" +# Authors: Olaf Hauk +# Martin Luessi +# Alexandre Gramfort +# Nicolas P. Rougier (graph code borrowed from his matplotlib gallery) +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from mne_connectivity.viz import plot_connectivity_circle + +import mne +from mne.datasets import sample +from mne.minimum_norm import ( + get_point_spread, + make_inverse_resolution_matrix, + read_inverse_operator, +) +from mne.viz import circular_layout + +print(__doc__) + +# %% +# Load forward solution and inverse operator +# ------------------------------------------ +# +# We need a matching forward solution and inverse operator to compute +# resolution matrices for different methods. + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fname_fwd = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +fname_inv = meg_path / "sample_audvis-meg-oct-6-meg-fixed-inv.fif" +forward = mne.read_forward_solution(fname_fwd) +# Convert forward solution to fixed source orientations +mne.convert_forward_solution(forward, surf_ori=True, force_fixed=True, copy=False) +inverse_operator = read_inverse_operator(fname_inv) + +# Compute resolution matrices for MNE +rm_mne = make_inverse_resolution_matrix( + forward, inverse_operator, method="MNE", lambda2=1.0 / 3.0**2 +) +src = inverse_operator["src"] +del forward, inverse_operator # save memory + +# %% +# Read and organise labels for cortical parcellation +# -------------------------------------------------- +# +# Get labels for FreeSurfer 'aparc' cortical parcellation with 34 labels/hemi +labels = mne.read_labels_from_annot("sample", parc="aparc", subjects_dir=subjects_dir) +n_labels = len(labels) +label_colors = [label.color for label in labels] +# First, we reorder the labels based on their location in the left hemi +label_names = [label.name for label in labels] +lh_labels = [name for name in label_names if name.endswith("lh")] + +# Get the y-location of the label +label_ypos = list() +for name in lh_labels: + idx = label_names.index(name) + ypos = np.mean(labels[idx].pos[:, 1]) + label_ypos.append(ypos) + +# Reorder the labels based on their location +lh_labels = [label for (yp, label) in sorted(zip(label_ypos, lh_labels))] + +# For the right hemi +rh_labels = [label[:-2] + "rh" for label in lh_labels] + +# %% +# Compute point-spread function summaries (PCA) for all labels +# ------------------------------------------------------------ +# +# We summarise the PSFs per label by their first five principal components, and +# use the first component to evaluate label-to-label leakage below. + +# Compute first PCA component across PSFs within labels. +# Note the differences in explained variance, probably due to different +# spatial extents of labels. +n_comp = 5 +stcs_psf_mne, pca_vars_mne = get_point_spread( + rm_mne, src, labels, mode="pca", n_comp=n_comp, norm=None, return_pca_vars=True +) +n_verts = rm_mne.shape[0] +del rm_mne + +# %% +# We can show the explained variances of principal components per label. Note +# how they differ across labels, most likely due to their varying spatial +# extent. + +with np.printoptions(precision=1): + for [name, var] in zip(label_names, pca_vars_mne): + print(f"{name}: {var.sum():.1f}% {var}") + +# %% +# The output shows the summed variance explained by the first five principal +# components as well as the explained variances of the individual components. +# +# Evaluate leakage based on label-to-label PSF correlations +# --------------------------------------------------------- +# +# Note that correlations ignore the overall amplitude of PSFs, i.e. they do +# not show which region will potentially be the bigger "leaker". + +# get PSFs from Source Estimate objects into matrix +psfs_mat = np.zeros([n_labels, n_verts]) +# Leakage matrix for MNE, get first principal component per label +for [i, s] in enumerate(stcs_psf_mne): + psfs_mat[i, :] = s.data[:, 0] +# Compute label-to-label leakage as Pearson correlation of PSFs +# Sign of correlation is arbitrary, so take absolute values +leakage_mne = np.abs(np.corrcoef(psfs_mat)) + +# Save the plot order and create a circular layout +node_order = lh_labels[::-1] + rh_labels # mirror label order across hemis +node_angles = circular_layout( + label_names, node_order, start_pos=90, group_boundaries=[0, len(label_names) / 2] +) +# Plot the graph using node colors from the FreeSurfer parcellation. We only +# show the 200 strongest connections. +fig, ax = plt.subplots( + figsize=(8, 8), facecolor="black", subplot_kw=dict(projection="polar") +) +plot_connectivity_circle( + leakage_mne, + label_names, + n_lines=200, + node_angles=node_angles, + node_colors=label_colors, + title="MNE Leakage", + ax=ax, +) + +# %% +# Most leakage occurs for neighbouring regions, but also for deeper regions +# across hemispheres. +# +# Save the figure (optional) +# -------------------------- +# +# Matplotlib controls figure facecolor separately for interactive display +# versus for saved figures. Thus when saving you must specify ``facecolor``, +# else your labels, title, etc will not be visible:: +# +# >>> fname_fig = meg_path / 'plot_label_leakage.png' +# >>> fig.savefig(fname_fig, facecolor='black') +# +# Plot PSFs for individual labels +# ------------------------------- +# +# Let us confirm for left and right lateral occipital lobes that there is +# indeed no leakage between them, as indicated by the correlation graph. +# We can plot the summary PSFs for both labels to examine the spatial extent of +# their leakage. + +# left and right lateral occipital +idx = [22, 23] +stc_lh = stcs_psf_mne[idx[0]] +stc_rh = stcs_psf_mne[idx[1]] + +# Maximum for scaling across plots +max_val = np.max([stc_lh.data, stc_rh.data]) + +# %% +# Point-spread function for the lateral occipital label in the left hemisphere + +brain_lh = stc_lh.plot( + subjects_dir=subjects_dir, + subject="sample", + hemi="both", + views="caudal", + clim=dict(kind="value", pos_lims=(0, max_val / 2.0, max_val)), +) +brain_lh.add_text(0.1, 0.9, label_names[idx[0]], "title", font_size=16) + +# %% +# and in the right hemisphere. + +brain_rh = stc_rh.plot( + subjects_dir=subjects_dir, + subject="sample", + hemi="both", + views="caudal", + clim=dict(kind="value", pos_lims=(0, max_val / 2.0, max_val)), +) +brain_rh.add_text(0.1, 0.9, label_names[idx[1]], "title", font_size=16) + +# %% +# Both summary PSFs are confined to their respective hemispheres, indicating +# that there is indeed low leakage between these two regions. diff --git a/mne-python/source/examples/inverse/psf_ctf_vertices.py b/mne-python/source/examples/inverse/psf_ctf_vertices.py new file mode 100644 index 0000000000000000000000000000000000000000..e6ab88a5fef088ef025495818a061e39caedca45 --- /dev/null +++ b/mne-python/source/examples/inverse/psf_ctf_vertices.py @@ -0,0 +1,114 @@ +""" +.. _ex-psd-ctf: + +================================================================== +Plot point-spread functions (PSFs) and cross-talk functions (CTFs) +================================================================== + +Visualise PSF and CTF at one vertex for sLORETA. +""" +# Authors: Olaf Hauk +# Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.datasets import sample +from mne.minimum_norm import ( + get_cross_talk, + get_point_spread, + make_inverse_resolution_matrix, +) + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fname_fwd = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +fname_cov = meg_path / "sample_audvis-cov.fif" +fname_evo = meg_path / "sample_audvis-ave.fif" + +# read forward solution +forward = mne.read_forward_solution(fname_fwd) +# forward operator with fixed source orientations +mne.convert_forward_solution(forward, surf_ori=True, force_fixed=True, copy=False) + +# noise covariance matrix +noise_cov = mne.read_cov(fname_cov) + +# evoked data for info +evoked = mne.read_evokeds(fname_evo, 0) + +# make inverse operator from forward solution +# free source orientation +inverse_operator = mne.minimum_norm.make_inverse_operator( + info=evoked.info, forward=forward, noise_cov=noise_cov, loose=0.0, depth=None +) + +# regularisation parameter +snr = 3.0 +lambda2 = 1.0 / snr**2 + +# compute resolution matrix for sLORETA +rm_lor = make_inverse_resolution_matrix( + forward, inverse_operator, method="sLORETA", lambda2=lambda2 +) + +# get PSF and CTF for sLORETA at one vertex +sources = [1000] + +stc_psf = get_point_spread(rm_lor, forward["src"], sources, norm=True) + +stc_ctf = get_cross_talk(rm_lor, forward["src"], sources, norm=True) +del rm_lor + +############################################################################## +# Visualize +# --------- +# PSF: + +# Which vertex corresponds to selected source +vertno_lh = forward["src"][0]["vertno"] +verttrue = [vertno_lh[sources[0]]] # just one vertex + +# find vertices with maxima in PSF and CTF +vert_max_psf = vertno_lh[stc_psf.data.argmax()] +vert_max_ctf = vertno_lh[stc_ctf.data.argmax()] + +brain_psf = stc_psf.plot("sample", "inflated", "lh", subjects_dir=subjects_dir) +brain_psf.show_view("ventral") +brain_psf.add_text(0.1, 0.9, "sLORETA PSF", "title", font_size=16) + +# True source location for PSF +brain_psf.add_foci( + verttrue, coords_as_verts=True, scale_factor=1.0, hemi="lh", color="green" +) + +# Maximum of PSF +brain_psf.add_foci( + vert_max_psf, coords_as_verts=True, scale_factor=1.0, hemi="lh", color="black" +) + +# %% +# CTF: + +brain_ctf = stc_ctf.plot("sample", "inflated", "lh", subjects_dir=subjects_dir) +brain_ctf.add_text(0.1, 0.9, "sLORETA CTF", "title", font_size=16) +brain_ctf.show_view("ventral") +brain_ctf.add_foci( + verttrue, coords_as_verts=True, scale_factor=1.0, hemi="lh", color="green" +) + +# Maximum of CTF +brain_ctf.add_foci( + vert_max_ctf, coords_as_verts=True, scale_factor=1.0, hemi="lh", color="black" +) + + +# %% +# The green spheres indicate the true source location, and the black +# spheres the maximum of the distribution. diff --git a/mne-python/source/examples/inverse/psf_ctf_vertices_lcmv.py b/mne-python/source/examples/inverse/psf_ctf_vertices_lcmv.py new file mode 100644 index 0000000000000000000000000000000000000000..bf7009374e0aadb94c56433a3fdaee29f78c5ae9 --- /dev/null +++ b/mne-python/source/examples/inverse/psf_ctf_vertices_lcmv.py @@ -0,0 +1,183 @@ +""" +.. _ex-psf-ctf-lcmv: + +================================================= +Compute cross-talk functions for LCMV beamformers +================================================= + +Visualise cross-talk functions at one vertex for LCMV beamformers computed +with different data covariance matrices, which affects their cross-talk +functions. +""" +# Author: Olaf Hauk +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.beamformer import make_lcmv, make_lcmv_resolution_matrix +from mne.datasets import sample +from mne.minimum_norm import get_cross_talk + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fname_fwd = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +fname_cov = meg_path / "sample_audvis-cov.fif" +fname_evo = meg_path / "sample_audvis-ave.fif" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" + +# Read raw data +raw = mne.io.read_raw_fif(raw_fname) + +# only pick good EEG/MEG sensors +raw.info["bads"] += ["EEG 053"] # bads + 1 more +picks = mne.pick_types(raw.info, meg=True, eeg=True, exclude="bads") + +# Find events +events = mne.find_events(raw) + +# event_id = {'aud/l': 1, 'aud/r': 2, 'vis/l': 3, 'vis/r': 4} +event_id = {"vis/l": 3, "vis/r": 4} + +tmin, tmax = -0.2, 0.25 # epoch duration +epochs = mne.Epochs( + raw, + events, + event_id=event_id, + tmin=tmin, + tmax=tmax, + picks=picks, + baseline=(-0.2, 0.0), + preload=True, +) +del raw + +# covariance matrix for pre-stimulus interval +tmin, tmax = -0.2, 0.0 +cov_pre = mne.compute_covariance(epochs, tmin=tmin, tmax=tmax, method="empirical") + +# covariance matrix for post-stimulus interval (around main evoked responses) +tmin, tmax = 0.05, 0.25 +cov_post = mne.compute_covariance(epochs, tmin=tmin, tmax=tmax, method="empirical") +info = epochs.info +del epochs + +# read forward solution +forward = mne.read_forward_solution(fname_fwd) +# use forward operator with fixed source orientations +mne.convert_forward_solution(forward, surf_ori=True, force_fixed=True, copy=False) + +# read noise covariance matrix +noise_cov = mne.read_cov(fname_cov) + +# regularize noise covariance (we used 'empirical' above) +noise_cov = mne.cov.regularize(noise_cov, info, mag=0.1, grad=0.1, eeg=0.1, rank="info") + +############################################################################## +# Compute LCMV filters with different data covariance matrices +# ------------------------------------------------------------ + +# compute LCMV beamformer filters for pre-stimulus interval +filters_pre = make_lcmv( + info, + forward, + cov_pre, + reg=0.05, + noise_cov=noise_cov, + pick_ori=None, + rank=None, + weight_norm=None, + reduce_rank=False, + verbose=False, +) + +# compute LCMV beamformer filters for post-stimulus interval +filters_post = make_lcmv( + info, + forward, + cov_post, + reg=0.05, + noise_cov=noise_cov, + pick_ori=None, + rank=None, + weight_norm=None, + reduce_rank=False, + verbose=False, +) + +############################################################################## +# Compute resolution matrices for the two LCMV beamformers +# -------------------------------------------------------- + +# compute cross-talk functions (CTFs) for one target vertex +sources = [3000] +verttrue = [forward["src"][0]["vertno"][sources[0]]] # pick one vertex +rm_pre = make_lcmv_resolution_matrix(filters_pre, forward, info) +stc_pre = get_cross_talk(rm_pre, forward["src"], sources, norm=True) +del rm_pre + +############################################################################## +rm_post = make_lcmv_resolution_matrix(filters_post, forward, info) +stc_post = get_cross_talk(rm_post, forward["src"], sources, norm=True) +del rm_post + +############################################################################## +# Visualize +# --------- +# Pre: + +brain_pre = stc_pre.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=1, + clim=dict(kind="value", lims=(0, 0.2, 0.4)), +) + +brain_pre.add_text( + 0.1, + 0.9, + "LCMV beamformer with pre-stimulus\ndata covariance matrix", + "title", + font_size=16, +) + +# mark true source location for CTFs +brain_pre.add_foci( + verttrue, coords_as_verts=True, scale_factor=1.0, hemi="lh", color="green" +) + +# %% +# Post: + +brain_post = stc_post.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=2, + clim=dict(kind="value", lims=(0, 0.2, 0.4)), +) + +brain_post.add_text( + 0.1, + 0.9, + "LCMV beamformer with post-stimulus\ndata covariance matrix", + "title", + font_size=16, +) + +brain_post.add_foci( + verttrue, coords_as_verts=True, scale_factor=1.0, hemi="lh", color="green" +) + +# %% +# The pre-stimulus beamformer's CTF has lower values in parietal regions +# suppressed alpha activity?) but larger values in occipital regions (less +# suppression of visual activity?). diff --git a/mne-python/source/examples/inverse/psf_volume.py b/mne-python/source/examples/inverse/psf_volume.py new file mode 100644 index 0000000000000000000000000000000000000000..91af78b9dfc1a3073391778403fef11fbc5f0625 --- /dev/null +++ b/mne-python/source/examples/inverse/psf_volume.py @@ -0,0 +1,102 @@ +""" +.. _ex-psd-vol: + +=============================================== +Plot point-spread functions (PSFs) for a volume +=============================================== + +Visualise PSF at one volume vertex for sLORETA. +""" +# Authors: Olaf Hauk +# Alexandre Gramfort +# Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.datasets import sample +from mne.minimum_norm import get_point_spread, make_inverse_resolution_matrix + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fname_cov = meg_path / "sample_audvis-cov.fif" +fname_evo = meg_path / "sample_audvis-ave.fif" +fname_trans = meg_path / "sample_audvis_raw-trans.fif" +fname_bem = subjects_dir / "sample" / "bem" / "sample-5120-bem-sol.fif" + +# %% +# For the volume, create a coarse source space for speed (don't do this in +# real code!), then compute the forward using this source space. + +# read noise cov and and evoked +noise_cov = mne.read_cov(fname_cov) +evoked = mne.read_evokeds(fname_evo, 0) + +# create a coarse source space +src_vol = mne.setup_volume_source_space( # this is a very course resolution! + "sample", pos=15.0, subjects_dir=subjects_dir, add_interpolator=False +) # usually you want True, this is just for speed + +# compute the forward +forward_vol = mne.make_forward_solution( # MEG-only for speed + evoked.info, fname_trans, src_vol, fname_bem, eeg=False +) +del src_vol + +# %% +# Now make an inverse operator and compute the PSF at a source. +inverse_operator_vol = mne.minimum_norm.make_inverse_operator( + info=evoked.info, forward=forward_vol, noise_cov=noise_cov +) + +# compute resolution matrix for sLORETA +rm_lor_vol = make_inverse_resolution_matrix( + forward_vol, inverse_operator_vol, method="sLORETA", lambda2=1.0 / 9.0 +) + +# get PSF and CTF for sLORETA at one vertex +sources_vol = [100] +stc_psf_vol = get_point_spread(rm_lor_vol, forward_vol["src"], sources_vol, norm=True) +del rm_lor_vol + +############################################################################## +# Visualize +# --------- +# PSF: + +# Which vertex corresponds to selected source +src_vol = forward_vol["src"] +verttrue_vol = src_vol[0]["vertno"][sources_vol] + +# find vertex with maximum in PSF +max_vert_idx, _ = np.unravel_index(stc_psf_vol.data.argmax(), stc_psf_vol.data.shape) +vert_max_ctf_vol = src_vol[0]["vertno"][[max_vert_idx]] + +# plot them +brain_psf_vol = stc_psf_vol.plot_3d( + "sample", + src=forward_vol["src"], + views="ven", + subjects_dir=subjects_dir, + volume_options=dict(alpha=0.5), +) +brain_psf_vol.add_text(0.1, 0.9, "Volumetric sLORETA PSF", "title", font_size=16) +brain_psf_vol.add_foci( + verttrue_vol, coords_as_verts=True, scale_factor=1, hemi="vol", color="green" +) +brain_psf_vol.add_foci( + vert_max_ctf_vol, + coords_as_verts=True, + scale_factor=1.25, + hemi="vol", + color="black", + alpha=0.3, +) diff --git a/mne-python/source/examples/inverse/rap_music.py b/mne-python/source/examples/inverse/rap_music.py new file mode 100644 index 0000000000000000000000000000000000000000..cc386605dc1f3d1feaa5d466259d4c761dc9600b --- /dev/null +++ b/mne-python/source/examples/inverse/rap_music.py @@ -0,0 +1,61 @@ +""" +.. _ex-rap-music: + +================================ +Compute Rap-Music on evoked data +================================ + +Compute a Recursively Applied and Projected MUltiple Signal Classification +(RAP-MUSIC) :footcite:`MosherLeahy1999` on evoked data. +""" + +# Author: Yousra Bekhti +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.beamformer import rap_music +from mne.datasets import sample +from mne.viz import plot_dipole_amplitudes, plot_dipole_locations + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +evoked_fname = meg_path / "sample_audvis-ave.fif" +cov_fname = meg_path / "sample_audvis-cov.fif" + +# Read the evoked response and crop it +condition = "Right Auditory" +evoked = mne.read_evokeds(evoked_fname, condition=condition, baseline=(None, 0)) +# select N100 +evoked.crop(tmin=0.05, tmax=0.15) + +evoked.pick(picks="meg", exclude="bads") + +# Read the forward solution +forward = mne.read_forward_solution(fwd_fname) + +# Read noise covariance matrix +noise_cov = mne.read_cov(cov_fname) + +dipoles, residual = rap_music( + evoked, forward, noise_cov, n_dipoles=2, return_residual=True, verbose=True +) +trans = forward["mri_head_t"] +plot_dipole_locations(dipoles, trans, "sample", subjects_dir=subjects_dir) +plot_dipole_amplitudes(dipoles) + +# Plot the evoked data and the residual. +evoked.plot(ylim=dict(grad=[-300, 300], mag=[-800, 800], eeg=[-6, 8]), time_unit="s") +residual.plot(ylim=dict(grad=[-300, 300], mag=[-800, 800], eeg=[-6, 8]), time_unit="s") + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/read_inverse.py b/mne-python/source/examples/inverse/read_inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..148d09d84af1ff549fb0d5fb36df38aa307db9ca --- /dev/null +++ b/mne-python/source/examples/inverse/read_inverse.py @@ -0,0 +1,56 @@ +""" +.. _ex-read-inverse: + +=========================== +Reading an inverse operator +=========================== + +The inverse operator's source space is shown in 3D. +""" +# Author: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.datasets import sample +from mne.minimum_norm import read_inverse_operator +from mne.viz import set_3d_view + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fname_trans = meg_path / "sample_audvis_raw-trans.fif" +inv_fname = meg_path / "sample_audvis-meg-oct-6-meg-inv.fif" + +inv = read_inverse_operator(inv_fname) + +print(f"Method: {inv['methods']}") +print(f"fMRI prior: {inv['fmri_prior']}") +print(f"Number of sources: {inv['nsource']}") +print(f"Number of channels: {inv['nchan']}") + +src = inv["src"] # get the source space + +# Get access to the triangulation of the cortex + +print(f"Number of vertices on the left hemisphere: {len(src[0]['rr'])}") +print(f"Number of triangles on left hemisphere: {len(src[0]['use_tris'])}") +print(f"Number of vertices on the right hemisphere: {len(src[1]['rr'])}") +print(f"Number of triangles on right hemisphere: {len(src[1]['use_tris'])}") + +# %% +# Show the 3D source space + +fig = mne.viz.plot_alignment( + subject="sample", + subjects_dir=subjects_dir, + trans=fname_trans, + surfaces="white", + src=src, +) +set_3d_view(fig, focalpoint=(0.0, 0.0, 0.06)) diff --git a/mne-python/source/examples/inverse/read_stc.py b/mne-python/source/examples/inverse/read_stc.py new file mode 100644 index 0000000000000000000000000000000000000000..b06f61d14f8f4207ea109d9ca2923ef309432109 --- /dev/null +++ b/mne-python/source/examples/inverse/read_stc.py @@ -0,0 +1,38 @@ +""" +.. _ex-read-stc: + +=================== +Reading an STC file +=================== + +STC files contain activations on cortex ie. source +reconstructions +""" +# Author: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fname = meg_path / "sample_audvis-meg" + +stc = mne.read_source_estimate(fname) + +n_vertices, n_samples = stc.data.shape +print(f"stc data size: {n_vertices} (nb of vertices) x {n_samples} (nb of samples)") + +# View source activations +plt.plot(stc.times, stc.data[::100, :].T) +plt.xlabel("time (ms)") +plt.ylabel("Source amplitude") +plt.show() diff --git a/mne-python/source/examples/inverse/resolution_metrics.py b/mne-python/source/examples/inverse/resolution_metrics.py new file mode 100644 index 0000000000000000000000000000000000000000..5ab39d3c645ceb79a0ce4b6c1260b84687f2b505 --- /dev/null +++ b/mne-python/source/examples/inverse/resolution_metrics.py @@ -0,0 +1,181 @@ +""" +.. _ex-res-metrics: + +================================================== +Compute spatial resolution metrics in source space +================================================== + +Compute peak localisation error and spatial deviation for the point-spread +functions of dSPM and MNE. Plot their distributions and difference of +distributions. This example mimics some results from :footcite:`HaukEtAl2019`, +namely Figure 3 (peak localisation error for PSFs, L2-MNE vs dSPM) and Figure 4 +(spatial deviation for PSFs, L2-MNE vs dSPM). +""" +# Author: Olaf Hauk +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.datasets import sample +from mne.minimum_norm import make_inverse_resolution_matrix, resolution_metrics + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fname_fwd = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +fname_cov = meg_path / "sample_audvis-cov.fif" +fname_evo = meg_path / "sample_audvis-ave.fif" + +# read forward solution +forward = mne.read_forward_solution(fname_fwd) +# forward operator with fixed source orientations +mne.convert_forward_solution(forward, surf_ori=True, force_fixed=True, copy=False) + +# noise covariance matrix +noise_cov = mne.read_cov(fname_cov) + +# evoked data for info +evoked = mne.read_evokeds(fname_evo, 0) + +# make inverse operator from forward solution +# free source orientation +inverse_operator = mne.minimum_norm.make_inverse_operator( + info=evoked.info, forward=forward, noise_cov=noise_cov, loose=0.0, depth=None +) + +# regularisation parameter +snr = 3.0 +lambda2 = 1.0 / snr**2 + +# %% +# MNE +# --- +# Compute resolution matrices, peak localisation error (PLE) for point spread +# functions (PSFs), spatial deviation (SD) for PSFs: + +rm_mne = make_inverse_resolution_matrix( + forward, inverse_operator, method="MNE", lambda2=lambda2 +) +ple_mne_psf = resolution_metrics( + rm_mne, inverse_operator["src"], function="psf", metric="peak_err" +) +sd_mne_psf = resolution_metrics( + rm_mne, inverse_operator["src"], function="psf", metric="sd_ext" +) +del rm_mne + +# %% +# dSPM +# ---- +# Do the same for dSPM: + +rm_dspm = make_inverse_resolution_matrix( + forward, inverse_operator, method="dSPM", lambda2=lambda2 +) +ple_dspm_psf = resolution_metrics( + rm_dspm, inverse_operator["src"], function="psf", metric="peak_err" +) +sd_dspm_psf = resolution_metrics( + rm_dspm, inverse_operator["src"], function="psf", metric="sd_ext" +) +del rm_dspm, forward + +# %% +# Visualize results +# ----------------- +# Visualise peak localisation error (PLE) across the whole cortex for MNE PSF: +brain_ple_mne = ple_mne_psf.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=1, + clim=dict(kind="value", lims=(0, 2, 4)), +) +brain_ple_mne.add_text(0.1, 0.9, "PLE MNE", "title", font_size=16) + +# %% +# And dSPM: + +brain_ple_dspm = ple_dspm_psf.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=2, + clim=dict(kind="value", lims=(0, 2, 4)), +) +brain_ple_dspm.add_text(0.1, 0.9, "PLE dSPM", "title", font_size=16) + +# %% +# Subtract the two distributions and plot this difference +diff_ple = ple_mne_psf - ple_dspm_psf + +brain_ple_diff = diff_ple.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=3, + clim=dict(kind="value", pos_lims=(0.0, 1.0, 2.0)), +) +brain_ple_diff.add_text(0.1, 0.9, "PLE MNE-dSPM", "title", font_size=16) + +# %% +# These plots show that dSPM has generally lower peak localization error (red +# color) than MNE in deeper brain areas, but higher error (blue color) in more +# superficial areas. +# +# Next we'll visualise spatial deviation (SD) across the whole cortex for MNE +# PSF: + +brain_sd_mne = sd_mne_psf.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=4, + clim=dict(kind="value", lims=(0, 2, 4)), +) +brain_sd_mne.add_text(0.1, 0.9, "SD MNE", "title", font_size=16) + +# %% +# And dSPM: + +brain_sd_dspm = sd_dspm_psf.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=5, + clim=dict(kind="value", lims=(0, 2, 4)), +) +brain_sd_dspm.add_text(0.1, 0.9, "SD dSPM", "title", font_size=16) + +# %% +# Subtract the two distributions and plot this difference: + +diff_sd = sd_mne_psf - sd_dspm_psf + +brain_sd_diff = diff_sd.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=6, + clim=dict(kind="value", pos_lims=(0.0, 1.0, 2.0)), +) +brain_sd_diff.add_text(0.1, 0.9, "SD MNE-dSPM", "title", font_size=16) + +# %% +# These plots show that dSPM has generally higher spatial deviation than MNE +# (blue color), i.e. worse performance to distinguish different sources. +# +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/resolution_metrics_eegmeg.py b/mne-python/source/examples/inverse/resolution_metrics_eegmeg.py new file mode 100644 index 0000000000000000000000000000000000000000..51acd51fd94f0109a413623e856344bcc41667b3 --- /dev/null +++ b/mne-python/source/examples/inverse/resolution_metrics_eegmeg.py @@ -0,0 +1,198 @@ +""" +.. _ex-res-metrics-meeg: + +============================================================== +Compute spatial resolution metrics to compare MEG with EEG+MEG +============================================================== + +Compute peak localisation error and spatial deviation for the point-spread +functions of dSPM and MNE. Plot their distributions and difference of +distributions. This example mimics some results from :footcite:`HaukEtAl2019`, +namely Figure 3 (peak localisation error for PSFs, L2-MNE vs dSPM) and Figure 4 +(spatial deviation for PSFs, L2-MNE vs dSPM). It shows that combining MEG with +EEG reduces the point-spread function and increases the spatial resolution of +source imaging, especially for deeper sources. +""" +# Author: Olaf Hauk +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.datasets import sample +from mne.minimum_norm.resolution_matrix import make_inverse_resolution_matrix +from mne.minimum_norm.spatial_resolution import resolution_metrics + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects/" +meg_path = data_path / "MEG" / "sample" +fname_fwd_emeg = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +fname_cov = meg_path / "sample_audvis-cov.fif" +fname_evo = meg_path / "sample_audvis-ave.fif" + +# read forward solution with EEG and MEG +forward_emeg = mne.read_forward_solution(fname_fwd_emeg) +# forward operator with fixed source orientations +forward_emeg = mne.convert_forward_solution( + forward_emeg, surf_ori=True, force_fixed=True +) + +# create a forward solution with MEG only +forward_meg = mne.pick_types_forward(forward_emeg, meg=True, eeg=False) + +# noise covariance matrix +noise_cov = mne.read_cov(fname_cov) + +# evoked data for info +evoked = mne.read_evokeds(fname_evo, 0) + +# make inverse operator from forward solution for MEG and EEGMEG +inv_emeg = mne.minimum_norm.make_inverse_operator( + info=evoked.info, forward=forward_emeg, noise_cov=noise_cov, loose=0.0, depth=None +) + +inv_meg = mne.minimum_norm.make_inverse_operator( + info=evoked.info, forward=forward_meg, noise_cov=noise_cov, loose=0.0, depth=None +) + +# regularisation parameter +snr = 3.0 +lambda2 = 1.0 / snr**2 + +# %% +# EEGMEG +# ------ +# Compute resolution matrices, localization error, and spatial deviations +# for MNE: + +rm_emeg = make_inverse_resolution_matrix( + forward_emeg, inv_emeg, method="MNE", lambda2=lambda2 +) +ple_psf_emeg = resolution_metrics( + rm_emeg, inv_emeg["src"], function="psf", metric="peak_err" +) +sd_psf_emeg = resolution_metrics( + rm_emeg, inv_emeg["src"], function="psf", metric="sd_ext" +) +del rm_emeg + +# %% +# MEG +# --- +# Do the same for MEG: + +rm_meg = make_inverse_resolution_matrix( + forward_meg, inv_meg, method="MNE", lambda2=lambda2 +) +ple_psf_meg = resolution_metrics( + rm_meg, inv_meg["src"], function="psf", metric="peak_err" +) +sd_psf_meg = resolution_metrics(rm_meg, inv_meg["src"], function="psf", metric="sd_ext") +del rm_meg + +# %% +# Visualization +# ------------- +# Look at peak localisation error (PLE) across the whole cortex for PSF: + +brain_ple_emeg = ple_psf_emeg.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=1, + clim=dict(kind="value", lims=(0, 2, 4)), +) + +brain_ple_emeg.add_text(0.1, 0.9, "PLE PSF EMEG", "title", font_size=16) + +# %% +# For MEG only: + +brain_ple_meg = ple_psf_meg.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=2, + clim=dict(kind="value", lims=(0, 2, 4)), +) + +brain_ple_meg.add_text(0.1, 0.9, "PLE PSF MEG", "title", font_size=16) + +# %% +# Subtract the two distributions and plot this difference: + +diff_ple = ple_psf_emeg - ple_psf_meg + +brain_ple_diff = diff_ple.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=3, + clim=dict(kind="value", pos_lims=(0.0, 0.5, 1.0)), + smoothing_steps=20, +) + +brain_ple_diff.add_text(0.1, 0.9, "PLE EMEG-MEG", "title", font_size=16) + +# %% +# These plots show that with respect to peak localization error, adding EEG to +# MEG does not bring much benefit. Next let's visualise spatial deviation (SD) +# across the whole cortex for PSF: + +brain_sd_emeg = sd_psf_emeg.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=4, + clim=dict(kind="value", lims=(0, 2, 4)), +) + +brain_sd_emeg.add_text(0.1, 0.9, "SD PSF EMEG", "title", font_size=16) + +# %% +# For MEG only: + +brain_sd_meg = sd_psf_meg.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=5, + clim=dict(kind="value", lims=(0, 2, 4)), +) + +brain_sd_meg.add_text(0.1, 0.9, "SD PSF MEG", "title", font_size=16) + +# %% +# Subtract the two distributions and plot this difference: + +diff_sd = sd_psf_emeg - sd_psf_meg + +brain_sd_diff = diff_sd.plot( + "sample", + "inflated", + "lh", + subjects_dir=subjects_dir, + figure=6, + clim=dict(kind="value", pos_lims=(0.0, 0.5, 1.0)), + smoothing_steps=20, +) + +brain_sd_diff.add_text(0.1, 0.9, "SD EMEG-MEG", "title", font_size=16) + +# %% +# Adding EEG to MEG decreases the spatial extent of point-spread +# functions (lower spatial deviation, blue colors), thus increasing +# resolution, especially for deeper source locations. +# +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/snr_estimate.py b/mne-python/source/examples/inverse/snr_estimate.py new file mode 100644 index 0000000000000000000000000000000000000000..fda8ada5d0c722e643e3b915832398e1c98221b5 --- /dev/null +++ b/mne-python/source/examples/inverse/snr_estimate.py @@ -0,0 +1,32 @@ +""" +.. _ex-snr-estimate: + +================================== +Estimate data SNR using an inverse +================================== + +This estimates the SNR as a function of time for a set of data +using a minimum-norm inverse operator. +""" +# Author: Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +from mne import read_evokeds +from mne.datasets.sample import data_path +from mne.minimum_norm import read_inverse_operator +from mne.viz import plot_snr_estimate + +print(__doc__) + +data_dir = data_path() / "MEG" / "sample" +fname_inv = data_dir / "sample_audvis-meg-oct-6-meg-inv.fif" +fname_evoked = data_dir / "sample_audvis-ave.fif" + +inv = read_inverse_operator(fname_inv) +evoked = read_evokeds(fname_evoked, baseline=(None, 0))[0] + +plot_snr_estimate(evoked, inv) diff --git a/mne-python/source/examples/inverse/source_space_snr.py b/mne-python/source/examples/inverse/source_space_snr.py new file mode 100644 index 0000000000000000000000000000000000000000..965c57d86ca60fcb9ef403ae54359249f0c5560e --- /dev/null +++ b/mne-python/source/examples/inverse/source_space_snr.py @@ -0,0 +1,94 @@ +""" +.. _ex-source-space-snr: + +========================== +Computing source space SNR +========================== + +This example shows how to compute and plot source space SNR as in +:footcite:`GoldenholzEtAl2009`. +""" + +# Author: Padma Sundaram +# Kaisu Lankinen +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +# sphinx_gallery_thumbnail_number = 2 + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.datasets import sample +from mne.minimum_norm import apply_inverse, make_inverse_operator + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" + +# Read data +meg_path = data_path / "MEG" / "sample" +fname_evoked = meg_path / "sample_audvis-ave.fif" +evoked = mne.read_evokeds(fname_evoked, condition="Left Auditory", baseline=(None, 0)) +fname_fwd = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +fname_cov = meg_path / "sample_audvis-cov.fif" +fwd = mne.read_forward_solution(fname_fwd) +cov = mne.read_cov(fname_cov) + +# Read inverse operator: +inv_op = make_inverse_operator(evoked.info, fwd, cov, fixed=True, verbose=True) + +# Calculate MNE: +snr = 3.0 +lambda2 = 1.0 / snr**2 +stc = apply_inverse(evoked, inv_op, lambda2, "MNE", verbose=True) + +# Calculate SNR in source space: +snr_stc = stc.estimate_snr(evoked.info, fwd, cov) + +# Plot an average SNR across source points over time: +ave = np.mean(snr_stc.data, axis=0) + +fig, ax = plt.subplots(layout="constrained") +ax.plot(evoked.times, ave) +ax.set(xlabel="Time (s)", ylabel="SNR MEG-EEG") + +# Find time point of maximum SNR +maxidx = np.argmax(ave) + +# Plot SNR on source space at the time point of maximum SNR: +kwargs = dict( + initial_time=evoked.times[maxidx], + hemi="split", + views=["lat", "med"], + subjects_dir=subjects_dir, + size=(600, 600), + clim=dict(kind="value", lims=(-100, -70, -40)), + transparent=True, + colormap="viridis", +) +brain = snr_stc.plot(**kwargs) + +# %% +# EEG +# --- +# Next we do the same for EEG and plot the result on the cortex: + +evoked_eeg = evoked.copy().pick(picks="eeg", exclude="bads") +inv_op_eeg = make_inverse_operator(evoked_eeg.info, fwd, cov, fixed=True, verbose=True) +stc_eeg = apply_inverse(evoked_eeg, inv_op_eeg, lambda2, "MNE", verbose=True) +snr_stc_eeg = stc_eeg.estimate_snr(evoked_eeg.info, fwd, cov) +brain = snr_stc_eeg.plot(**kwargs) + +# %% +# The same can be done for MEG, which looks more similar to the MEG-EEG case +# than the EEG case does. +# +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/time_frequency_mixed_norm_inverse.py b/mne-python/source/examples/inverse/time_frequency_mixed_norm_inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..bdd1134f39a0b23b637502d3b01555c183132fcb --- /dev/null +++ b/mne-python/source/examples/inverse/time_frequency_mixed_norm_inverse.py @@ -0,0 +1,182 @@ +""" +.. _ex-tfr-mixed-norm: + +============================================= +Compute MxNE with time-frequency sparse prior +============================================= + +The TF-MxNE solver is a distributed inverse method (like dSPM or sLORETA) +that promotes focal (sparse) sources (such as dipole fitting techniques) +:footcite:`GramfortEtAl2013b,GramfortEtAl2011`. +The benefit of this approach is that: + + - it is spatio-temporal without assuming stationarity (sources properties + can vary over time) + - activations are localized in space, time and frequency in one step. + - with a built-in filtering process based on a short time Fourier + transform (STFT), data does not need to be low passed (just high pass + to make the signals zero mean). + - the solver solves a convex optimization problem, hence cannot be + trapped in local minima. +""" +# Author: Alexandre Gramfort +# Daniel Strohmeier +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.datasets import sample +from mne.inverse_sparse import make_stc_from_dipoles, tf_mixed_norm +from mne.minimum_norm import apply_inverse, make_inverse_operator +from mne.viz import ( + plot_dipole_amplitudes, + plot_dipole_locations, + plot_sparse_source_estimates, +) + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +ave_fname = meg_path / "sample_audvis-no-filter-ave.fif" +cov_fname = meg_path / "sample_audvis-shrunk-cov.fif" + +# Read noise covariance matrix +cov = mne.read_cov(cov_fname) + +# Handling average file +condition = "Left visual" +evoked = mne.read_evokeds(ave_fname, condition=condition, baseline=(None, 0)) +# We make the window slightly larger than what you'll eventually be interested +# in ([-0.05, 0.3]) to avoid edge effects. +evoked.crop(tmin=-0.1, tmax=0.4) + +# Handling forward solution +forward = mne.read_forward_solution(fwd_fname) + +# %% +# Run solver + +# alpha parameter is between 0 and 100 (100 gives 0 active source) +alpha = 40.0 # general regularization parameter +# l1_ratio parameter between 0 and 1 promotes temporal smoothness +# (0 means no temporal regularization) +l1_ratio = 0.03 # temporal regularization parameter + +loose, depth = 0.2, 0.9 # loose orientation & depth weighting + +# Compute dSPM solution to be used as weights in MxNE +inverse_operator = make_inverse_operator( + evoked.info, forward, cov, loose=loose, depth=depth +) +stc_dspm = apply_inverse(evoked, inverse_operator, lambda2=1.0 / 9.0, method="dSPM") + +# Compute TF-MxNE inverse solution with dipole output +dipoles, residual = tf_mixed_norm( + evoked, + forward, + cov, + alpha=alpha, + l1_ratio=l1_ratio, + loose=loose, + depth=depth, + maxit=200, + tol=1e-6, + weights=stc_dspm, + weights_min=8.0, + debias=True, + wsize=16, + tstep=4, + window=0.05, + return_as_dipoles=True, + return_residual=True, +) + +# Crop to remove edges +for dip in dipoles: + dip.crop(tmin=-0.05, tmax=0.3) +evoked.crop(tmin=-0.05, tmax=0.3) +residual.crop(tmin=-0.05, tmax=0.3) + +# %% +# Plot dipole activations +plot_dipole_amplitudes(dipoles) + +# %% +# Plot location of the strongest dipole with MRI slices +idx = np.argmax([np.max(np.abs(dip.amplitude)) for dip in dipoles]) +plot_dipole_locations( + dipoles[idx], + forward["mri_head_t"], + "sample", + subjects_dir=subjects_dir, + mode="orthoview", + idx="amplitude", +) + +# # Plot dipole locations of all dipoles with MRI slices: +# for dip in dipoles: +# plot_dipole_locations(dip, forward['mri_head_t'], 'sample', +# subjects_dir=subjects_dir, mode='orthoview', +# idx='amplitude') + +# %% +# Show the evoked response and the residual for gradiometers +ylim = dict(grad=[-120, 120]) +evoked.pick(picks="grad", exclude="bads") +evoked.plot( + titles=dict(grad="Evoked Response: Gradiometers"), + ylim=ylim, + proj=True, + time_unit="s", +) + +residual.pick(picks="grad", exclude="bads") +residual.plot( + titles=dict(grad="Residuals: Gradiometers"), ylim=ylim, proj=True, time_unit="s" +) + +# %% +# Generate stc from dipoles +stc = make_stc_from_dipoles(dipoles, forward["src"]) + +# %% +# View in 2D and 3D ("glass" brain like 3D plot) +plot_sparse_source_estimates( + forward["src"], + stc, + bgcolor=(1, 1, 1), + opacity=0.1, + fig_name=f"TF-MxNE (cond {condition})", + modes=["sphere"], + scale_factors=[1.0], +) + +time_label = "TF-MxNE time=%0.2f ms" +clim = dict(kind="value", lims=[10e-9, 15e-9, 20e-9]) +brain = stc.plot( + "sample", + "inflated", + "rh", + views="medial", + clim=clim, + time_label=time_label, + smoothing_steps=5, + subjects_dir=subjects_dir, + initial_time=150, + time_unit="ms", +) +brain.add_label("V1", color="yellow", scalar_thresh=0.5, borders=True) +brain.add_label("V2", color="red", scalar_thresh=0.5, borders=True) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/trap_music.py b/mne-python/source/examples/inverse/trap_music.py new file mode 100644 index 0000000000000000000000000000000000000000..08dee1e54a9b1f717fd9a6fd070749ac27d93274 --- /dev/null +++ b/mne-python/source/examples/inverse/trap_music.py @@ -0,0 +1,61 @@ +""" +.. _ex-trap-music: + +================================= +Compute Trap-Music on evoked data +================================= + +Compute a Truncated Recursively Applied and Projected MUltiple Signal Classification +(TRAP-MUSIC) :footcite:`Makela2018` on evoked data. +""" + +# Author: Théodore Papadopoulo +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.beamformer import trap_music +from mne.datasets import sample +from mne.viz import plot_dipole_amplitudes, plot_dipole_locations + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +evoked_fname = meg_path / "sample_audvis-ave.fif" +cov_fname = meg_path / "sample_audvis-cov.fif" + +# Read the evoked response and crop it +condition = "Right Auditory" +evoked = mne.read_evokeds(evoked_fname, condition=condition, baseline=(None, 0)) +# select N100 +evoked.crop(tmin=0.05, tmax=0.15) + +evoked.pick(picks="meg", exclude="bads") + +# Read the forward solution +forward = mne.read_forward_solution(fwd_fname) + +# Read noise covariance matrix +noise_cov = mne.read_cov(cov_fname) + +dipoles, residual = trap_music( + evoked, forward, noise_cov, n_dipoles=2, return_residual=True, verbose=True +) +trans = forward["mri_head_t"] +plot_dipole_locations(dipoles, trans, "sample", subjects_dir=subjects_dir) +plot_dipole_amplitudes(dipoles) + +# Plot the evoked data and the residual. +evoked.plot(ylim=dict(grad=[-300, 300], mag=[-800, 800], eeg=[-6, 8]), time_unit="s") +residual.plot(ylim=dict(grad=[-300, 300], mag=[-800, 800], eeg=[-6, 8]), time_unit="s") + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/inverse/vector_mne_solution.py b/mne-python/source/examples/inverse/vector_mne_solution.py new file mode 100644 index 0000000000000000000000000000000000000000..f6ae788c145ee68c968bab4de0238a769e56ca8e --- /dev/null +++ b/mne-python/source/examples/inverse/vector_mne_solution.py @@ -0,0 +1,116 @@ +""" +.. _ex-vector-mne-solution: + +============================================ +Plotting the full vector-valued MNE solution +============================================ + +The source space that is used for the inverse computation defines a set of +dipoles, distributed across the cortex. When visualizing a source estimate, it +is sometimes useful to show the dipole directions in addition to their +estimated magnitude. This can be accomplished by computing a +:class:`mne.VectorSourceEstimate` and plotting it with +:meth:`stc.plot `, which uses +:func:`~mne.viz.plot_vector_source_estimates` under the hood rather than +:func:`~mne.viz.plot_source_estimates`. + +It can also be instructive to visualize the actual dipole/activation locations +in 3D space in a glass brain, as opposed to activations imposed on an inflated +surface (as typically done in :meth:`mne.SourceEstimate.plot`), as it allows +you to get a better sense of the underlying source geometry. +""" +# Author: Marijn van Vliet +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.datasets import sample +from mne.minimum_norm import apply_inverse, read_inverse_operator + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +smoothing_steps = 7 + +# Read evoked data +meg_path = data_path / "MEG" / "sample" +fname_evoked = meg_path / "sample_audvis-ave.fif" +evoked = mne.read_evokeds(fname_evoked, condition=0, baseline=(None, 0)) + +# Read inverse solution +fname_inv = meg_path / "sample_audvis-meg-oct-6-meg-inv.fif" +inv = read_inverse_operator(fname_inv) + +# Apply inverse solution, set pick_ori='vector' to obtain a +# :class:`mne.VectorSourceEstimate` object +snr = 3.0 +lambda2 = 1.0 / snr**2 +stc = apply_inverse(evoked, inv, lambda2, "dSPM", pick_ori="vector") + +# Use peak getter to move visualization to the time point of the peak magnitude +_, peak_time = stc.magnitude().get_peak(hemi="lh") + +# %% +# Plot the source estimate: + +# sphinx_gallery_thumbnail_number = 2 +brain = stc.plot( + initial_time=peak_time, + hemi="lh", + subjects_dir=subjects_dir, + smoothing_steps=smoothing_steps, +) + +# You can save a brain movie with: +# brain.save_movie(time_dilation=20, tmin=0.05, tmax=0.16, framerate=10, +# interpolation='linear', time_viewer=True) + +# %% +# Plot the activation in the direction of maximal power for this data: + +stc_max, directions = stc.project("pca", src=inv["src"]) +# These directions must by design be close to the normals because this +# inverse was computed with loose=0.2 +print( + "Absolute cosine similarity between source normals and directions: " + f"{np.abs(np.sum(directions * inv['source_nn'][2::3], axis=-1)).mean()}" +) +brain_max = stc_max.plot( + initial_time=peak_time, + hemi="lh", + subjects_dir=subjects_dir, + time_label="Max power", + smoothing_steps=smoothing_steps, +) + +# %% +# The normal is very similar: + +brain_normal = stc.project("normal", inv["src"])[0].plot( + initial_time=peak_time, + hemi="lh", + subjects_dir=subjects_dir, + time_label="Normal", + smoothing_steps=smoothing_steps, +) + +# %% +# You can also do this with a fixed-orientation inverse. It looks a lot like +# the result above because the ``loose=0.2`` orientation constraint keeps +# sources close to fixed orientation: + +fname_inv_fixed = meg_path / "sample_audvis-meg-oct-6-meg-fixed-inv.fif" +inv_fixed = read_inverse_operator(fname_inv_fixed) +stc_fixed = apply_inverse(evoked, inv_fixed, lambda2, "dSPM", pick_ori="vector") +brain_fixed = stc_fixed.plot( + initial_time=peak_time, + hemi="lh", + subjects_dir=subjects_dir, + smoothing_steps=smoothing_steps, +) diff --git a/mne-python/source/examples/io/README.txt b/mne-python/source/examples/io/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..779893019525f6e67eec9da0973ebf10f313a846 --- /dev/null +++ b/mne-python/source/examples/io/README.txt @@ -0,0 +1,7 @@ + +Input/Output +------------ + +Recipes for reading and writing files. See also our :ref:`tutorials on reading +data from various recording systems ` and our :ref:`tutorial +on manipulating MNE-Python data structures `. diff --git a/mne-python/source/examples/io/elekta_epochs.py b/mne-python/source/examples/io/elekta_epochs.py new file mode 100644 index 0000000000000000000000000000000000000000..35922b69531570f8ae1f55daad81f193ab766ed2 --- /dev/null +++ b/mne-python/source/examples/io/elekta_epochs.py @@ -0,0 +1,69 @@ +""" +.. _ex-io-ave-fiff: + +====================================== +Getting averaging info from .fif files +====================================== + +Parse averaging information defined in Elekta Vectorview/TRIUX DACQ (data acquisition). +Extract and average epochs accordingly. Modify some averaging parameters and get epochs. +""" +# Author: Jussi Nurminen (jnu@iki.fi) +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import os + +import mne +from mne.datasets import multimodal + +fname_raw = os.path.join(multimodal.data_path(), "multimodal_raw.fif") + + +print(__doc__) + +# %% +# Read raw file +raw = mne.io.read_raw_fif(fname_raw) + +# %% +# Check DACQ defined averaging categories and other info +print(raw.acqparser) + +# %% +# Extract epochs corresponding to a category +cond = raw.acqparser.get_condition(raw, "Auditory right") +epochs = mne.Epochs(raw, **cond) +epochs.average().plot_topo(background_color="w") + +# %% +# Get epochs from all conditions, average +evokeds = [] +for cat in raw.acqparser.categories: + cond = raw.acqparser.get_condition(raw, cat) + # copy (supported) rejection parameters from DACQ settings + epochs = mne.Epochs( + raw, reject=raw.acqparser.reject, flat=raw.acqparser.flat, **cond + ) + evoked = epochs.average() + evoked.comment = cat["comment"] + evokeds.append(evoked) + +# %% +# Make a new averaging category +newcat = dict() +newcat["comment"] = "Visual lower left, longer epochs" +newcat["event"] = 3 # reference event +newcat["start"] = -0.2 # epoch start rel. to ref. event (in seconds) +newcat["end"] = 0.7 # epoch end +newcat["reqevent"] = 0 # additional required event; 0 if none +newcat["reqwithin"] = 0.5 # ...required within .5 s (before or after) +newcat["reqwhen"] = 2 # ...required before (1) or after (2) ref. event +newcat["index"] = 9 # can be set freely + +cond = raw.acqparser.get_condition(raw, newcat) +epochs = mne.Epochs(raw, reject=raw.acqparser.reject, flat=raw.acqparser.flat, **cond) +epochs.average().plot(time_unit="s") diff --git a/mne-python/source/examples/io/read_impedances.py b/mne-python/source/examples/io/read_impedances.py new file mode 100644 index 0000000000000000000000000000000000000000..e1b7061c4c99690f18a75f337dafb549d28f0d87 --- /dev/null +++ b/mne-python/source/examples/io/read_impedances.py @@ -0,0 +1,77 @@ +""" +.. _ex-io-impedances: + +================================= +Getting impedances from raw files +================================= + +Many EEG systems provide impedance measurements for each channel within their file +format. MNE does not parse this information and does not store it in the +:class:`~mne.io.Raw` object. However, it is possible to extract this information from +the raw data and store it in a separate data structure. + +ANT Neuro +--------- + +The ``.cnt`` file format from ANT Neuro stores impedance information in the form of +triggers. The function :func:`mne.io.read_raw_ant` reads this information and marks the +time-segment during which an impedance measurement was performed as +:class:`~mne.Annotations` with the description set in the argument +``impedance_annotation``. However, it doesn't extract the impedance values themselves. +To do so, use the function ``antio.parser.read_triggers``. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from antio import read_cnt +from antio.parser import read_triggers +from matplotlib import pyplot as plt + +from mne.datasets import testing +from mne.io import read_raw_ant +from mne.viz import plot_topomap + +fname = testing.data_path() / "antio" / "CA_208" / "test_CA_208.cnt" +cnt = read_cnt(fname) +_, _, _, impedances, _ = read_triggers(cnt) + +raw = read_raw_ant(fname, eog=r"EOG") +impedances = [{ch: imp[k] for k, ch in enumerate(raw.ch_names)} for imp in impedances] +print(impedances[0]) # impedances measurement at the beginning of the recording + +# %% +# Note that the impedance measurement contains all channels, including the bipolar ones. +# We can visualize the impedances on a topographic map; below we show a topography of +# impedances before and after the recording for the EEG channels only. + +raw.pick("eeg").set_montage("standard_1020") +impedances = [{ch: imp[ch] for ch in raw.ch_names} for imp in impedances] + +f, ax = plt.subplots(1, 2, layout="constrained", figsize=(10, 5)) +f.suptitle("Impedances (kOhm)") +impedance = list(impedances[0].values()) +plot_topomap( + impedance, + raw.info, + vlim=(0, 50), + axes=ax[0], + show=False, + names=[f"{elt:.1f}" for elt in impedance], +) +ax[0].set_title("Impedances at the beginning of the recording") +impedance = list(impedances[-1].values()) +plot_topomap( + impedance, + raw.info, + vlim=(0, 50), + axes=ax[1], + show=False, + names=[f"{elt:.1f}" for elt in impedance], +) +ax[1].set_title("Impedances at the end of the recording") +plt.show() + +# %% +# In this very short test file, the impedances are stable over time. diff --git a/mne-python/source/examples/io/read_neo_format.py b/mne-python/source/examples/io/read_neo_format.py new file mode 100644 index 0000000000000000000000000000000000000000..a34ff0cd4f4c8f5187a42b663870381aa2982128 --- /dev/null +++ b/mne-python/source/examples/io/read_neo_format.py @@ -0,0 +1,40 @@ +""" +.. _ex-read-neo: + +=============================================== +How to use data in neural ensemble (NEO) format +=============================================== + +This example shows how to create an MNE-Python `~mne.io.Raw` object from data +in the `neural ensemble `_ format. For general +information on creating MNE-Python's data objects from NumPy arrays, see +:ref:`tut-creating-data-structures`. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import neo + +import mne + +# %% +# This example uses NEO's ``ExampleIO`` object for creating fake data. The data will be +# all zeros, so the plot won't be very interesting, but it should demonstrate the steps +# to using NEO data. For actual data and different file formats, consult the NEO +# documentation. + +reader = neo.io.ExampleIO("fakedata.nof") +block = reader.read(lazy=False)[0] # get the first block +segment = block.segments[0] # get data from first (and only) segment +signals = segment.analogsignals[0] # get first (multichannel) signal + +data = signals.rescale("V").magnitude.T +sfreq = signals.sampling_rate.magnitude +ch_names = [f"Neo {(idx + 1):02}" for idx in range(signals.shape[1])] +ch_types = ["eeg"] * len(ch_names) # if not specified, type 'misc' is assumed + +info = mne.create_info(ch_names=ch_names, ch_types=ch_types, sfreq=sfreq) +raw = mne.io.RawArray(data, info) +raw.plot(show_scrollbars=False) diff --git a/mne-python/source/examples/io/read_noise_covariance_matrix.py b/mne-python/source/examples/io/read_noise_covariance_matrix.py new file mode 100644 index 0000000000000000000000000000000000000000..b8b1dc5832c994a0df62f725457bb1c022a3fcc3 --- /dev/null +++ b/mne-python/source/examples/io/read_noise_covariance_matrix.py @@ -0,0 +1,31 @@ +""" +.. _ex-read-noise-cov: + +========================================= +Reading/Writing a noise covariance matrix +========================================= + +How to plot a noise covariance matrix. +""" +# Author: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.datasets import sample + +data_path = sample.data_path() +fname_cov = data_path / "MEG" / "sample" / "sample_audvis-cov.fif" +fname_evo = data_path / "MEG" / "sample" / "sample_audvis-ave.fif" + +cov = mne.read_cov(fname_cov) +print(cov) +ev_info = mne.io.read_info(fname_evo) + +# %% +# Plot covariance + +cov.plot(ev_info, exclude="bads", show_svd=False) diff --git a/mne-python/source/examples/io/read_xdf.py b/mne-python/source/examples/io/read_xdf.py new file mode 100644 index 0000000000000000000000000000000000000000..ee8524702a5ea03e7a42d37584f9fc93e23ab734 --- /dev/null +++ b/mne-python/source/examples/io/read_xdf.py @@ -0,0 +1,40 @@ +""" +.. _ex-read-xdf: + +==================== +Reading XDF EEG data +==================== + +Here we read some sample XDF data. Although we do not analyze it here, this +recording is of a short parallel auditory response (pABR) experiment +:footcite:`PolonenkoMaddox2019` and was provided by the `Maddox Lab `_. +""" +# Authors: Clemens Brunner +# Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import pyxdf + +import mne +from mne.datasets import misc + +fname = misc.data_path() / "xdf" / "sub-P001_ses-S004_task-Default_run-001_eeg_a2.xdf" +streams, header = pyxdf.load_xdf(fname) +data = streams[0]["time_series"].T +assert data.shape[0] == 5 # four raw EEG plus one stim channel +data[:4:2] -= data[1:4:2] # subtract (rereference) to get two bipolar EEG +data = data[::2] # subselect +data[:2] *= 1e-6 / 50 / 2 # uV -> V and preamp gain +sfreq = float(streams[0]["info"]["nominal_srate"][0]) +info = mne.create_info(3, sfreq, ["eeg", "eeg", "stim"]) +raw = mne.io.RawArray(data, info) +raw.plot(scalings=dict(eeg=100e-6), duration=1, start=14) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/README.txt b/mne-python/source/examples/preprocessing/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..bd197e073b55a844dc63979924a68e3c9be1b70c --- /dev/null +++ b/mne-python/source/examples/preprocessing/README.txt @@ -0,0 +1,29 @@ + +Preprocessing +------------- + +Examples related to data preprocessing (artifact detection / rejection etc.) + +.. raw:: html + +
+ +.. raw:: html + +
+ +.. only:: html + + .. image:: https://mne.tools/mne-gui-addons/_images/sphx_glr_locate_ieeg_micro_001.png + :alt: + + :ref:`ex-ieeg-micro` + +.. raw:: html + +
Locating micro-scale intracranial electrode contacts
+
+ +.. raw:: html + +
\ No newline at end of file diff --git a/mne-python/source/examples/preprocessing/contralateral_referencing.py b/mne-python/source/examples/preprocessing/contralateral_referencing.py new file mode 100644 index 0000000000000000000000000000000000000000..b2ae199817d3040c9787d1b5cbe6b05150a4057f --- /dev/null +++ b/mne-python/source/examples/preprocessing/contralateral_referencing.py @@ -0,0 +1,66 @@ +""" +.. _ex-contralateral-referencing: + +======================================= +Using contralateral referencing for EEG +======================================= + +Instead of using a single reference electrode for all channels, some +researchers reference the EEG electrodes in each hemisphere to an electrode in +the contralateral hemisphere (often an electrode over the mastoid bone; this is +common in sleep research for example). Here we demonstrate how to set a +contralateral EEG reference. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import mne + +ssvep_folder = mne.datasets.ssvep.data_path() +ssvep_data_raw_path = ( + ssvep_folder / "sub-02" / "ses-01" / "eeg" / "sub-02_ses-01_task-ssvep_eeg.vhdr" +) +raw = mne.io.read_raw(ssvep_data_raw_path, preload=True) +_ = raw.set_montage("easycap-M1") + +# %% +# The electrodes TP9 and TP10 are near the mastoids so we'll use them as our +# contralateral reference channels. Then we'll create our hemisphere groups. + +raw.rename_channels({"TP9": "M1", "TP10": "M2"}) + +# this splits electrodes into 3 groups; left, midline, and right +ch_names = mne.channels.make_1020_channel_selections(raw.info, return_ch_names=True) + +# remove the ref channels from the lists of to-be-rereferenced channels +ch_names["Left"].remove("M1") +ch_names["Right"].remove("M2") + +# %% +# Finally we do the referencing. For the midline channels we'll reference them +# to the mean of the two mastoid channels; the left and right hemispheres we'll +# reference to the single contralateral mastoid channel. + +# midline referencing to mean of mastoids: +mastoids = ["M1", "M2"] +rereferenced_midline_chs = ( + raw.copy() + .pick(mastoids + ch_names["Midline"]) + .set_eeg_reference(mastoids) + .drop_channels(mastoids) +) + +# contralateral referencing (alters channels in `raw` in-place): +for ref, hemi in dict(M2=ch_names["Left"], M1=ch_names["Right"]).items(): + mne.set_bipolar_reference(raw, anode=hemi, cathode=[ref] * len(hemi), copy=False) +# strip off '-M1' and '-M2' suffixes added to each bipolar-referenced channel +raw.rename_channels(lambda ch_name: ch_name.split("-")[0]) + +# replace unreferenced midline with rereferenced midline +_ = raw.drop_channels(ch_names["Midline"]).add_channels([rereferenced_midline_chs]) + +# %% +# Make sure the channel locations still look right: +fig = raw.plot_sensors(show_names=True, sphere="eeglab") diff --git a/mne-python/source/examples/preprocessing/css.py b/mne-python/source/examples/preprocessing/css.py new file mode 100644 index 0000000000000000000000000000000000000000..c6684b742731b88dbaf5e4cf7c9ff08ad21784ad --- /dev/null +++ b/mne-python/source/examples/preprocessing/css.py @@ -0,0 +1,106 @@ +""" +.. _ex-css: + +================================================================= +Cortical Signal Suppression (CSS) for removal of cortical signals +================================================================= + +This script shows an example of how to use CSS +:footcite:`Samuelsson2019` . CSS suppresses the cortical contribution +to the signal subspace in EEG data using MEG data, facilitating +detection of subcortical signals. We will illustrate how it works by +simulating one cortical and one subcortical oscillation at different +frequencies; 40 Hz and 239 Hz for cortical and subcortical activity, +respectively, then process it with CSS and look at the power spectral +density of the raw and processed data. + +""" +# Author: John G Samuelsson +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.datasets import sample +from mne.simulation import simulate_evoked, simulate_sparse_stc + +############################################################################### +# Load sample subject data +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +ave_fname = meg_path / "sample_audvis-no-filter-ave.fif" +cov_fname = meg_path / "sample_audvis-cov.fif" +trans_fname = meg_path / "sample_audvis_raw-trans.fif" +bem_fname = subjects_dir / "sample" / "bem" / "/sample-5120-bem-sol.fif" + +raw = mne.io.read_raw_fif(meg_path / "sample_audvis_raw.fif") +fwd = mne.read_forward_solution(fwd_fname) +fwd = mne.convert_forward_solution(fwd, force_fixed=True, surf_ori=True) +fwd = mne.pick_types_forward(fwd, meg=True, eeg=True, exclude=raw.info["bads"]) +cov = mne.read_cov(cov_fname) + +############################################################################### +# Find patches (labels) to activate +all_labels = mne.read_labels_from_annot(subject="sample", subjects_dir=subjects_dir) +labels = [] +for select_label in ["parahippocampal-lh", "postcentral-rh"]: + labels.append([lab for lab in all_labels if lab.name in select_label][0]) +hiplab, postcenlab = labels + +############################################################################### +# Simulate one cortical dipole (40 Hz) and one subcortical (239 Hz) + + +def cortical_waveform(times): + """Create a cortical waveform.""" + return 10e-9 * np.cos(times * 2 * np.pi * 40) + + +def subcortical_waveform(times): + """Create a subcortical waveform.""" + return 10e-9 * np.cos(times * 2 * np.pi * 239) + + +times = np.linspace(0, 0.5, int(0.5 * raw.info["sfreq"])) +stc = simulate_sparse_stc( + fwd["src"], + n_dipoles=2, + times=times, + location="center", + subjects_dir=subjects_dir, + labels=[postcenlab, hiplab], + data_fun=cortical_waveform, +) +stc.data[np.where(np.isin(stc.vertices[0], hiplab.vertices))[0], :] = ( + subcortical_waveform(times) +) +evoked = simulate_evoked(fwd, stc, raw.info, cov, nave=15) + +############################################################################### +# Process with CSS and plot PSD of EEG data before and after processing +evoked_subcortical = mne.preprocessing.cortical_signal_suppression(evoked, n_proj=6) +chs = mne.pick_types(evoked.info, meg=False, eeg=True) + +psd = np.mean(np.abs(np.fft.rfft(evoked.data)) ** 2, axis=0) +psd_proc = np.mean(np.abs(np.fft.rfft(evoked_subcortical.data)) ** 2, axis=0) +freq = np.arange( + 0, stop=int(evoked.info["sfreq"] / 2), step=evoked.info["sfreq"] / (2 * len(psd)) +) + +fig, ax = plt.subplots() +ax.plot(freq, psd, label="raw") +ax.plot(freq, psd_proc, label="processed") +ax.text(0.2, 0.7, "cortical", transform=ax.transAxes) +ax.text(0.8, 0.25, "subcortical", transform=ax.transAxes) +ax.set(ylabel="EEG Power spectral density", xlabel="Frequency (Hz)") +ax.legend() + +############################################################################### +# References +# ^^^^^^^^^^ +# +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/define_target_events.py b/mne-python/source/examples/preprocessing/define_target_events.py new file mode 100644 index 0000000000000000000000000000000000000000..f438d07c7535990b6e58558787ceed6d14fbc3c6 --- /dev/null +++ b/mne-python/source/examples/preprocessing/define_target_events.py @@ -0,0 +1,116 @@ +""" +.. _ex-tag-events: + +============================================================ +Define target events based on time lag, plot evoked response +============================================================ + +This script shows how to define higher order events based on +time lag between reference and target events. For +illustration, we will put face stimuli presented into two +classes, that is 1) followed by an early button press +(within 590 milliseconds) and followed by a late button +press (later than 590 milliseconds). Finally, we will +visualize the evoked responses to both 'quickly-processed' +and 'slowly-processed' face stimuli. + +""" +# Authors: Denis Engemann +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne import io +from mne.datasets import sample +from mne.event import define_target_events + +print(__doc__) + +data_path = sample.data_path() + +# %% +# Set parameters +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname) +events = mne.read_events(event_fname) + +# Set up pick list: EEG + STI 014 - bad channels (modify to your needs) +include = [] # or stim channels ['STI 014'] +raw.info["bads"] += ["EEG 053"] # bads + +# pick MEG channels +picks = mne.pick_types( + raw.info, + meg="mag", + eeg=False, + stim=False, + eog=True, + include=include, + exclude="bads", +) + +# %% +# Find stimulus event followed by quick button presses + +reference_id = 5 # presentation of a smiley face +target_id = 32 # button press +sfreq = raw.info["sfreq"] # sampling rate +tmin = 0.1 # trials leading to very early responses will be rejected +tmax = 0.59 # ignore face stimuli followed by button press later than 590 ms +new_id = 42 # the new event id for a hit. If None, reference_id is used. +fill_na = 99 # the fill value for misses + +events_, lag = define_target_events( + events, reference_id, target_id, sfreq, tmin, tmax, new_id, fill_na +) + +print(events_) # The 99 indicates missing or too late button presses + +# besides the events also the lag between target and reference is returned +# this could e.g. be used as parametric regressor in subsequent analyses. + +print(lag[lag != fill_na]) # lag in milliseconds + +# ############################################################################# +# Construct epochs + +tmin_ = -0.2 +tmax_ = 0.4 +event_id = dict(early=new_id, late=fill_na) + +epochs = mne.Epochs( + raw, + events_, + event_id, + tmin_, + tmax_, + picks=picks, + baseline=(None, 0), + reject=dict(mag=4e-12), +) + +# average epochs and get an Evoked dataset. + +early, late = (epochs[k].average() for k in event_id) + +# %% +# View evoked response + +times = 1e3 * epochs.times # time in milliseconds +title = "Evoked response followed by {} button press" + +fig, axes = plt.subplots(2, 1) +early.plot(axes=axes[0], time_unit="s") +axes[0].set(title=title.format("late"), ylabel="Evoked field (fT)") +late.plot(axes=axes[1], time_unit="s") +axes[1].set(title=title.format("early"), ylabel="Evoked field (fT)") +plt.show() diff --git a/mne-python/source/examples/preprocessing/eeg_bridging.py b/mne-python/source/examples/preprocessing/eeg_bridging.py new file mode 100644 index 0000000000000000000000000000000000000000..37d85c55df6452b6a257e355d00ca47f915a3408 --- /dev/null +++ b/mne-python/source/examples/preprocessing/eeg_bridging.py @@ -0,0 +1,407 @@ +""" +.. _ex-eeg-bridging: + +=============================================== +Identify EEG Electrodes Bridged by too much Gel +=============================================== + +Research-grade EEG often uses a gel based system, and when too much gel is +applied the gel conducting signal from the scalp to the electrode for one +electrode connects with the gel conducting signal from another electrode +"bridging" the two signals. This is undesirable because the signals from the +two (or more) electrodes are not as independent as they would otherwise be; +they are very similar to each other introducing additional +spatial smearing. An algorithm has been developed to detect electrode +bridging :footcite:`TenkeKayser2001`, which has been implemented in EEGLAB +:footcite:`DelormeMakeig2004`. Unfortunately, there is not a lot to be +done about electrode brigding once the data has been collected as far as +preprocessing other than interpolating bridged channels. Therefore, our +recommendation is to check for electrode bridging early in data collection +and address the problem. Or, if the data has already been collected, quantify +the extent of the bridging so as not to introduce bias into the data from this +effect and exclude subjects with bridging that might effect the outcome of a +study. Preventing electrode bridging is ideal but awareness of the problem at +least will mitigate its potential as a confound to a study. This tutorial +follows the eBridge tutorial from https://psychophysiology.cpmc.columbia.edu. + +.. _electrodes.tsv: https://bids-specification.readthedocs.io/en/stable/04-modality-specific-files/03-electroencephalography.html#electrodes-description-_electrodestsv +""" # noqa: E501 +# Authors: Alex Rockhill +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +# sphinx_gallery_thumbnail_number = 2 + +import matplotlib.pyplot as plt +import numpy as np +from matplotlib.colors import LinearSegmentedColormap + +import mne + +print(__doc__) + +# %% +# Compute Electrical Distance Metric +# ---------------------------------- +# First, let's compute electrical distance metrics for a group of example +# subjects from the EEGBCI dataset in order to estimate electrode bridging. +# The electrical distance is just the variance of signals subtracted +# pairwise. Channels with activity that mirror another channel nearly +# exactly will have very low electrical distance. By inspecting the +# distribution of electrical distances, we can look for pairwise distances +# that are consistently near zero which are indicative of bridging. +# +# .. note:: It is likely to be sufficient to run this algorithm on a +# small portion (~3 minutes is probably plenty) of the data but +# that gel might settle over the course of a study causing more +# bridging so using the last segment of the data will +# give the most conservative estimate. + +montage = mne.channels.make_standard_montage("standard_1005") +ed_data = dict() # electrical distance/bridging data +raw_data = dict() # store infos for electrode positions +for sub in range(1, 11): + print(f"Computing electrode bridges for subject {sub}") + raw_fname = mne.datasets.eegbci.load_data(subjects=sub, runs=(1,))[0] + raw = mne.io.read_raw(raw_fname, preload=True, verbose=False) + mne.datasets.eegbci.standardize(raw) # set channel names + raw.set_montage(montage, verbose=False) + raw_data[sub] = raw + ed_data[sub] = mne.preprocessing.compute_bridged_electrodes(raw) + + +# %% +# Examine an Electrical Distance Matrix +# ------------------------------------- +# Before we look at the electrical distance distributions across subjects, +# let's look at the distance matrix for one subject and try and understand +# how the algorithm works. We'll use subject 6 as it is a good example of +# bridging. In the zoomed out color scale version on the right, we can see +# that there is a distribution of electrical distances that are specific to +# that subject's head physiology/geometry and brain activity during the +# recording. On the right, when we clip the color range to zoom in, we can +# see several electrical distance outliers that are near zero; +# these indicate bridging. + +bridged_idx, ed_matrix = ed_data[6] + +fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), layout="constrained") +fig.suptitle("Subject 6 Electrical Distance Matrix") + +# take median across epochs, only use upper triangular, lower is NaNs +ed_plot = np.zeros(ed_matrix.shape[1:]) * np.nan +triu_idx = np.triu_indices(ed_plot.shape[0], 1) +for idx0, idx1 in np.array(triu_idx).T: + ed_plot[idx0, idx1] = np.nanmedian(ed_matrix[:, idx0, idx1]) + +# plot full distribution color range +im1 = ax1.imshow(ed_plot, aspect="auto") +cax1 = fig.colorbar(im1, ax=ax1) +cax1.set_label(r"Electrical Distance ($\mu$$V^2$)") + +# plot zoomed in colors +im2 = ax2.imshow(ed_plot, aspect="auto", vmax=5) +cax2 = fig.colorbar(im2, ax=ax2) +cax2.set_label(r"Electrical Distance ($\mu$$V^2$)") +for ax in (ax1, ax2): + ax.set_xlabel("Channel Index") + ax.set_ylabel("Channel Index") + +# %% +# Examine the Distribution of Electrical Distances +# ------------------------------------------------ +# Now let's plot a histogram of the electrical distance matrix. Note that the +# electrical distance matrix from the previous plot is upper triangular but +# does not include the diagonal. This means that the pairwise electrical +# distances are not computed between the same channel (which makes sense as +# the differences between a channel and itself would just be zero). The initial +# peak near zero therefore represents pairs of different channels that +# are nearly identical which is indicative of bridging. EEG recordings +# without bridged electrodes do not have a peak near zero. + +fig, ax = plt.subplots(figsize=(5, 5)) +fig.suptitle("Subject 6 Electrical Distance Matrix Distribution") +ax.hist(ed_matrix[~np.isnan(ed_matrix)], bins=np.linspace(0, 500, 51)) +ax.set_xlabel(r"Electrical Distance ($\mu$$V^2$)") +ax.set_ylabel("Count (channel pairs for all epochs)") + +# %% +# Plot Electrical Distances on a Topomap +# -------------------------------------- +# Now, let's look at the topography of the electrical distance matrix and +# see where our bridged channels are and check that their spatial +# arrangement makes sense. Here, we are looking at the minimum electrical +# distance for each channel and taking the median across all epochs +# (the raw data is epoched into 2 second non-overlapping intervals). +# This example is of the subject from the EEGBCI dataset with the most +# bridged channels so there are many light areas and red lines. They are +# generally grouped together and are biased toward horizontal connections +# (this may be because the EEG experimenter usually stands to the side and +# may have inserted the gel syringe tip in too far). + +mne.viz.plot_bridged_electrodes( + raw_data[6].info, + bridged_idx, + ed_matrix, + title="Subject 6 Bridged Electrodes", + topomap_args=dict(vlim=(None, 5)), +) + +# %% +# Plot the Raw Voltage Time Series for Bridged Electrodes +# ------------------------------------------------------- +# Finally, let's do a sanity check and make sure that the bridged electrodes +# are indeed implausibly similar. We'll plot two bridged electrode pairs: +# F2-F4 and FC2-FC4, for subject 6 where they are bridged and subject 1 +# where they are not. As we can see, the pairs are nearly identical for +# subject 6 confirming that they are likely bridged. Interestingly, even +# though the two pairs are adjacent to each other, there are two distinctive +# pairs, meaning that it is unlikely that all four of these electrodes are +# bridged. + +raw = raw_data[6].copy().pick(["FC2", "FC4", "F2", "F4"]) +raw.add_channels( + [ + mne.io.RawArray( + raw.get_data(ch1) - raw.get_data(ch2), + mne.create_info([f"{ch1}-{ch2}"], raw.info["sfreq"], "eeg"), + raw.first_samp, + ) + for ch1, ch2 in [("F2", "F4"), ("FC2", "FC4")] + ] +) +raw.plot(duration=20, scalings=dict(eeg=2e-4)) + +raw = raw_data[1].copy().pick(["FC2", "FC4", "F2", "F4"]) +raw.add_channels( + [ + mne.io.RawArray( + raw.get_data(ch1) - raw.get_data(ch2), + mne.create_info([f"{ch1}-{ch2}"], raw.info["sfreq"], "eeg"), + raw.first_samp, + ) + for ch1, ch2 in [("F2", "F4"), ("FC2", "FC4")] + ] +) +raw.plot(duration=20, scalings=dict(eeg=2e-4)) + +# %% +# Compare Bridging Across Subjects in the EEGBCI Dataset +# ------------------------------------------------------- +# Now, let's look at the histograms of electrical distances for the whole +# EEGBCI dataset. As we can see in the zoomed in insert on the right, +# for subjects 6, 7 and 8 (and to a lesser extent 2 and 4), there is a +# different shape of the distribution of electrical distances around +# 0 :math:`{\mu}V^2` than for the other subjects. These subjects' +# distributions have a peak around 0 :math:`{\mu}V^2` distance +# and a trough around 5 :math:`{\mu}V^2` which is indicative of +# electrode bridging. The rest of the subjects' distributions increase +# monotonically, indicating normal spatial separation of sources. The +# large discrepancy in shapes of distributions is likely driven primarily by +# artifacts such as blinks which are an order of magnitude larger than +# neural data since this data has not been preprocessed but likely +# reflect neural or at least anatomical differences as well (i.e. the +# distance from the sensors to the brain). + +fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(8, 4), layout="constrained") +fig.suptitle("Electrical Distance Distribution for EEGBCI Subjects") +for ax in (ax1, ax2): + ax.set_ylabel("Count") + ax.set_xlabel(r"Electrical Distance ($\mu$$V^2$)") + +for sub, (bridged_idx, ed_matrix) in ed_data.items(): + # ed_matrix is upper triangular so exclude bottom half of NaNs + hist, edges = np.histogram( + ed_matrix[~np.isnan(ed_matrix)].flatten(), bins=np.linspace(0, 1000, 101) + ) + centers = (edges[1:] + edges[:-1]) / 2 + ax1.plot(centers, hist) + hist, edges = np.histogram( + ed_matrix[~np.isnan(ed_matrix)].flatten(), bins=np.linspace(0, 30, 21) + ) + centers = (edges[1:] + edges[:-1]) / 2 + ax2.plot(centers, hist, label=f"Sub {sub} #={len(bridged_idx)}") + +ax1.axvspan(0, 30, color="r", alpha=0.5) +ax2.legend(loc=(1.04, 0)) + +# %% +# For the group of subjects, let's look at their electrical distances +# and bridging. Especially since this is the same task, the lack of +# low electrical distances in many of the subjects is compelling +# evidence that the low electrical distance is caused by bridging +# and that it is avoidable given more judicious application of gel or +# other conductive electrolyte solution. + +for sub, (bridged_idx, ed_matrix) in ed_data.items(): + mne.viz.plot_bridged_electrodes( + raw_data[sub].info, + bridged_idx, + ed_matrix, + title=f"Subject {sub} Bridged Electrodes", + topomap_args=dict(vlim=(None, 5)), + ) + +# %% +# For subjects with many bridged channels like Subject 6 shown in the example +# above, it is advisable to exclude the subject. This because EEG recording +# montage will not be comparable with the other subjects. And, if we tried to +# interpole, the interpolation would depend on other channels which are also +# bridged in that case. However, for subjects with only a few bridged channels, +# those channels can be interpolated. Since the bridged data is still +# biological (i.e. it is recording the subject's brain), it's just spatially +# smeared, we can use :func:`mne.preprocessing.interpolate_bridged_electrodes` +# to make a virtual channel midway between the two bridged channels +# to aid in interpolation. + +# use subject 2, only one bridged electrode pair +bridged_idx = ed_data[2][0] +raw = mne.preprocessing.interpolate_bridged_electrodes( + raw_data[2].copy(), bridged_idx=bridged_idx +) + +# %% +# Let's make sure that our virtual channel aided the interpolation. We can do +# this by simulating a bridge to make sure that we recover the original data +# better with the virtual channel method. If we make two channels nearly the +# same to simulate a bridged electrode but save the original data, we can +# compare the two interpolation methods. As we can see, the virtual channel +# recovers the original data more slightly closely. However, as shown in the +# plots, there is still residual signal for both methods implying that it is +# there is still a loss of data compared to unbridged channels. + +raw = raw_data[2].copy() + +# pick two channels to simulate a bridge +idx0, idx1 = 9, 10 +ch0, ch1 = raw.ch_names[idx0], raw.ch_names[idx1] +bridged_idx_simulated = [(idx0, idx1)] +# get the original data to compare to +data_orig = raw_data[2].get_data(picks=(idx0, idx1)) + +# simulate a bridge between the two channels by taking their mean and adding +# some noise +rng = np.random.default_rng(11) # seed for reproducibility +raw_sim = raw.copy() # raw with simulated electrode bridge +# remove channels with original data +raw_sim = raw_sim.drop_channels([ch0, ch1]) +bridged_data = np.tile(np.mean(data_orig, axis=0), (2, 1)) # copy mean +# add separate noise for each channel +bridged_data[0] += 1e-7 * rng.normal(size=raw.times.size) +bridged_data[1] += 1e-7 * rng.normal(size=raw.times.size) +# add back simulated data +raw_sim = raw_sim.add_channels( + [ + mne.io.RawArray( + bridged_data, + mne.create_info([ch0, ch1], raw.info["sfreq"], "eeg"), + raw.first_samp, + ) + ] +) +raw_sim.set_montage(montage) # add back channel positions + +# use virtual channel method +raw_virtual = mne.preprocessing.interpolate_bridged_electrodes( + raw_sim.copy(), bridged_idx=bridged_idx_simulated +) +data_virtual = raw_virtual.get_data(picks=(idx0, idx1)) + +# set bads to be bridged electrodes to interpolate without a virtual channel +raw_comp = raw_sim.copy() +raw_comp.info["bads"] = [raw_sim.ch_names[idx0], raw_sim.ch_names[idx1]] +raw_comp.interpolate_bads() +data_comp = raw_comp.get_data(picks=(idx0, idx1)) + +# compute variance of residuals +print( + "Variance of residual (interpolated data - original data)\n\n" + f"With adding virtual channel: {np.mean(np.var(data_virtual - data_orig, axis=1))}\n" + f"Compared to interpolation only using other channels: {np.mean(np.var(data_comp - data_orig, axis=1))}" + "" +) + +# plot results +raw = raw.pick([ch0, ch1]) +raw = raw.add_channels( + [ + mne.io.RawArray( + np.concatenate([data_virtual, data_virtual - data_orig]), + mne.create_info( + [ + f"{ch0} virtual", + f"{ch1} virtual", + f"{ch0} virtual diff", + f"{ch1} virtual diff", + ], + raw.info["sfreq"], + "eeg", + ), + raw.first_samp, + ) + ] +) +raw = raw.add_channels( + [ + mne.io.RawArray( + np.concatenate([data_comp, data_comp - data_orig]), + mne.create_info( + [f"{ch0} comp", f"{ch1} comp", f"{ch0} comp diff", f"{ch1} comp diff"], + raw.info["sfreq"], + "eeg", + ), + raw.first_samp, + ) + ] +) +raw.plot(scalings=dict(eeg=7e-5)) + +# %% +# The Relationship Between Bridging and Impedances +# ------------------------------------------------ +# Electrode bridging is often brought about by inserting more gel in order +# to bring impendances down. Thus it can be helpful to compare bridging +# to impedances in the quest to be an ideal EEG technician! Low +# impedances lead to less noisy data and EEG without bridging is more +# spatially precise. Brain Imaging Data Structure (BIDS) recommends that +# impedances be stored in an EEG dataset in the `electrodes.tsv`_ file. +# Since the impedances are not stored for this dataset, we will fake +# them to demonstrate how they would be plotted. Here, the impedances +# are plotted as is typical at the end of a setup; most channels are +# good but there are a few that need to have their impedance lowered. +# The impedances should ideally all be less than 25 KOhm before +# starting an experiment when using active systems and less than 5 KOhm +# when using a passive system. + +rng = np.random.default_rng(11) # seed for reproducibility +raw = raw_data[1] +# typically impedances < 25 kOhm are acceptable for active systems and +# impedances < 5 kOhm are desirable for a passive system +impedances = rng.random(len(raw.ch_names)) * 30 +impedances[10] = 80 # set a few bad impendances +impedances[25] = 99 +cmap = LinearSegmentedColormap.from_list( + name="impedance_cmap", colors=["g", "y", "r"], N=256 +) +fig, ax = plt.subplots(figsize=(5, 5)) +im, cn = mne.viz.plot_topomap(impedances, raw.info, axes=ax, cmap=cmap, vlim=(25, 75)) +ax.set_title("Electrode Impendances") +cax = fig.colorbar(im, ax=ax) +cax.set_label(r"Impedance (k$\Omega$)") + +# %% +# Summary +# ------- +# In this example, we have shown a dataset where electrical bridging occurred +# during the EEG setup for several subjects. Hopefully this is convincing as to +# the importance of proper technique as well as checking your work to +# learn and improve as an EEG experimenter, and hopefully this tool will help +# us all collect better EEG data in the future. + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/eeg_csd.py b/mne-python/source/examples/preprocessing/eeg_csd.py new file mode 100644 index 0000000000000000000000000000000000000000..e5c6086c068cf330895fb28b89e7f97b6a90c0e2 --- /dev/null +++ b/mne-python/source/examples/preprocessing/eeg_csd.py @@ -0,0 +1,97 @@ +""" +.. _ex-eeg-csd: + +===================================================== +Transform EEG data using current source density (CSD) +===================================================== + +This script shows an example of how to use CSD +:footcite:`PerrinEtAl1987,PerrinEtAl1989,Cohen2014,KayserTenke2015`. +CSD takes the spatial Laplacian of the sensor signal (derivative in both +x and y). It does what a planar gradiometer does in MEG. Computing these +spatial derivatives reduces point spread. CSD transformed data have a sharper +or more distinct topography, reducing the negative impact of volume conduction. +""" +# Authors: Alex Rockhill +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +# sphinx_gallery_thumbnail_number = 6 + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() + +# %% +# Load sample subject data +meg_path = data_path / "MEG" / "sample" +raw = mne.io.read_raw_fif(meg_path / "sample_audvis_raw.fif") +raw = raw.pick(picks=["eeg", "eog", "ecg", "stim"], exclude="bads").load_data() +events = mne.find_events(raw) +raw.set_eeg_reference(projection=True).apply_proj() + +# %% +# Plot the raw data and CSD-transformed raw data: + +raw_csd = mne.preprocessing.compute_current_source_density(raw) +raw.plot() +raw_csd.plot() + +# %% +# Also look at the power spectral densities: + +raw.compute_psd().plot(picks="data", exclude="bads", amplitude=False) +raw_csd.compute_psd().plot(picks="data", exclude="bads", amplitude=False) + +# %% +# CSD can also be computed on Evoked (averaged) data. +# Here we epoch and average the data so we can demonstrate that. + +event_id = { + "auditory/left": 1, + "auditory/right": 2, + "visual/left": 3, + "visual/right": 4, + "smiley": 5, + "button": 32, +} +epochs = mne.Epochs(raw, events, event_id=event_id, tmin=-0.2, tmax=0.5, preload=True) +evoked = epochs["auditory"].average() + +# %% +# First let's look at how CSD affects scalp topography: + +times = np.array([-0.1, 0.0, 0.05, 0.1, 0.15]) +evoked_csd = mne.preprocessing.compute_current_source_density(evoked) +evoked.plot_joint(title="Average Reference", show=False) +evoked_csd.plot_joint(title="Current Source Density") + +# %% +# CSD has parameters ``stiffness`` and ``lambda2`` affecting smoothing and +# spline flexibility, respectively. Let's see how they affect the solution: + +fig, ax = plt.subplots(4, 4, layout="constrained") +fig.set_size_inches(10, 10) +for i, lambda2 in enumerate([0, 1e-7, 1e-5, 1e-3]): + for j, m in enumerate([5, 4, 3, 2]): + this_evoked_csd = mne.preprocessing.compute_current_source_density( + evoked, stiffness=m, lambda2=lambda2 + ) + this_evoked_csd.plot_topomap( + 0.1, axes=ax[i, j], contours=4, time_unit="s", colorbar=False, show=False + ) + ax[i, j].set_title(f"stiffness={m}\nλ²={lambda2}") + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/eog_artifact_histogram.py b/mne-python/source/examples/preprocessing/eog_artifact_histogram.py new file mode 100644 index 0000000000000000000000000000000000000000..ac51d8b1f39905c87ee2f475441e403de513bd5c --- /dev/null +++ b/mne-python/source/examples/preprocessing/eog_artifact_histogram.py @@ -0,0 +1,55 @@ +""" +.. _ex-eog: + +======================== +Show EOG artifact timing +======================== + +Compute the distribution of timing for EOG artifacts. + +""" +# Authors: Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne import io +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() + +# %% +# Set parameters +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname, preload=True) +events = mne.find_events(raw, "STI 014") +eog_event_id = 512 +eog_events = mne.preprocessing.find_eog_events(raw, eog_event_id) +raw.add_events(eog_events, "STI 014") + +# Read epochs +picks = mne.pick_types(raw.info, meg=False, eeg=False, stim=True, eog=False) +tmin, tmax = -0.2, 0.5 +event_ids = {"AudL": 1, "AudR": 2, "VisL": 3, "VisR": 4} +epochs = mne.Epochs(raw, events, event_ids, tmin, tmax, picks=picks) + +# Get the stim channel data +data = epochs.get_data(picks="STI 014").squeeze() +data = np.sum((data.astype(int) & eog_event_id) == eog_event_id, axis=0) + +# %% +# Plot EOG artifact distribution +fig, ax = plt.subplots(layout="constrained") +ax.stem(1e3 * epochs.times, data) +ax.set(xlabel="Times (ms)", ylabel=f"Blink counts (from {len(epochs)} trials)") diff --git a/mne-python/source/examples/preprocessing/eog_regression.py b/mne-python/source/examples/preprocessing/eog_regression.py new file mode 100644 index 0000000000000000000000000000000000000000..e3b8341e744a9fe8eea9c0694d0be7baa2913555 --- /dev/null +++ b/mne-python/source/examples/preprocessing/eog_regression.py @@ -0,0 +1,79 @@ +""" +======================================= +Reduce EOG artifacts through regression +======================================= + +Reduce artifacts by regressing the EOG channels onto the rest of the channels +and then subtracting the EOG signal. + +This is a quick example to show the most basic application of the technique. +See the :ref:`tutorial ` for a more thorough +explanation that demonstrates more advanced approaches. +""" + +# Author: Marijn van Vliet +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +# Import packages and load data +# ----------------------------- +# +# We begin as always by importing the necessary Python modules and loading some +# data, in this case the :ref:`MNE sample dataset `. + +from matplotlib import pyplot as plt + +import mne +from mne.datasets import sample +from mne.preprocessing import EOGRegression + +print(__doc__) + +data_path = sample.data_path() +raw_fname = data_path / "MEG" / "sample" / "sample_audvis_filt-0-40_raw.fif" + +# Read raw data +raw = mne.io.read_raw_fif(raw_fname, preload=True) +events = mne.find_events(raw, "STI 014") + +# Highpass filter to eliminate slow drifts +raw.filter(0.3, None, picks="all") + +# %% +# Perform regression and remove EOG +# --------------------------------- + +# Fit the regression model +weights = EOGRegression().fit(raw) +raw_clean = weights.apply(raw, copy=True) + +# Show the filter weights in a topomap +weights.plot() + +# %% +# Before/after comparison +# ----------------------- +# Let's compare the signal before and after cleaning with EOG regression. This +# is best visualized by extracting epochs and plotting the evoked potential. + +tmin, tmax = -0.1, 0.5 +event_id = {"visual/left": 3, "visual/right": 4} +evoked_before = mne.Epochs( + raw, events, event_id, tmin, tmax, baseline=(tmin, 0) +).average() +evoked_after = mne.Epochs( + raw_clean, events, event_id, tmin, tmax, baseline=(tmin, 0) +).average() + +# Create epochs after EOG correction +epochs_after = mne.Epochs(raw_clean, events, event_id, tmin, tmax, baseline=(tmin, 0)) +evoked_after = epochs_after.average() + +fig, ax = plt.subplots( + nrows=3, ncols=2, figsize=(10, 7), sharex=True, sharey="row", layout="constrained" +) +evoked_before.plot(axes=ax[:, 0], spatial_colors=True) +evoked_after.plot(axes=ax[:, 1], spatial_colors=True) +fig.suptitle("Before --> After") diff --git a/mne-python/source/examples/preprocessing/epochs_metadata.py b/mne-python/source/examples/preprocessing/epochs_metadata.py new file mode 100644 index 0000000000000000000000000000000000000000..9c46368afa0e12c0436eef73443eed15a384098b --- /dev/null +++ b/mne-python/source/examples/preprocessing/epochs_metadata.py @@ -0,0 +1,171 @@ +""" +.. _epochs-metadata: + +=============================================================== +Automated epochs metadata generation with variable time windows +=============================================================== + +When working with :class:`~mne.Epochs`, :ref:`metadata ` can be +invaluable. There is an extensive tutorial on +:ref:`how it can be generated automatically `. +In the brief examples below, we will demonstrate different ways to bound the time +windows used to generate the metadata. + +""" +# Authors: Richard Höchenberger +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +# We will use data from an EEG recording during an Eriksen flanker task. For the +# purpose of demonstration, we'll only load the first 60 seconds of data. + +import mne + +data_dir = mne.datasets.erp_core.data_path() +infile = data_dir / "ERP-CORE_Subject-001_Task-Flankers_eeg.fif" + +raw = mne.io.read_raw(infile, preload=True) +raw.crop(tmax=60).filter(l_freq=0.1, h_freq=40) + +# %% +# Visualizing the events +# ^^^^^^^^^^^^^^^^^^^^^^ +# +# All experimental events are stored in the :class:`~mne.io.Raw` instance as +# :class:`~mne.Annotations`. We first need to convert these to events and the +# corresponding mapping from event codes to event names (``event_id``). +# We then visualize the events. +all_events, all_event_id = mne.events_from_annotations(raw) +mne.viz.plot_events(events=all_events, event_id=all_event_id, sfreq=raw.info["sfreq"]) + + +# %% +# As you can see, there are four types of ``stimulus`` and two types of ``response`` +# events. +# +# Declaring "row events" +# ^^^^^^^^^^^^^^^^^^^^^^ +# +# For the sake of this example, we will assume that during analysis our epochs will be +# time-locked to the stimulus onset events. Hence, we would like to create metadata with +# one row per ``stimulus``. We can achieve this by specifying all stimulus event names +# as ``row_events``. + +row_events = [ + "stimulus/compatible/target_left", + "stimulus/compatible/target_right", + "stimulus/incompatible/target_left", + "stimulus/incompatible/target_right", +] + +# %% +# Specifying metadata time windows +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +# +# Now, we will explore different ways of specifying the time windows around the +# ``row_events`` when generating metadata. Any events falling within the same time +# window will be added to the same row in the metadata table. +# +# Fixed time window +# ~~~~~~~~~~~~~~~~~ +# +# A simple way to specify the time window extent is by specifying the time in seconds +# relative to the row event. In the following example, the time window spans from the +# row event (time point zero) up until three seconds later. + +metadata_tmin = 0.0 +metadata_tmax = 3.0 + +metadata, events, event_id = mne.epochs.make_metadata( + events=all_events, + event_id=all_event_id, + tmin=metadata_tmin, + tmax=metadata_tmax, + sfreq=raw.info["sfreq"], + row_events=row_events, +) + +metadata + +# %% +# This looks good at the first glance. However, for example in the 2nd and 3rd row, we +# have two responses listed (left and right). This is because the 3-second time window +# is obviously a bit too wide and captures more than one trial. While we could make it +# narrower, this could lead to a loss of events – if the window might become **too** +# narrow. Ultimately, this problem arises because the response time varies from trial +# to trial, so it's difficult for us to set a fixed upper bound for the time window. +# +# Fixed time window with ``keep_first`` +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# One workaround is using the ``keep_first`` parameter, which will create a new column +# containing the first event of the specified type. + +metadata_tmin = 0.0 +metadata_tmax = 3.0 +keep_first = "response" # <-- new + +metadata, events, event_id = mne.epochs.make_metadata( + events=all_events, + event_id=all_event_id, + tmin=metadata_tmin, + tmax=metadata_tmax, + sfreq=raw.info["sfreq"], + row_events=row_events, + keep_first=keep_first, # <-- new +) + +metadata + +# %% +# As you can see, a new column ``response`` was created with the time of the first +# response event falling inside the time window. The ``first_response`` column specifies +# **which** response occurred first (left or right). +# +# Variable time window +# ~~~~~~~~~~~~~~~~~~~~ +# +# Another way to address the challenge of variable time windows **without** the need to +# create new columns is by specifying ``tmin`` and ``tmax`` as event names. In this +# example, we use ``tmin=row_events``, because we want the time window to start +# with the time-locked event. ``tmax``, on the other hand, are the response events: +# The first response event following ``tmin`` will be used to determine the duration of +# the time window. + +metadata_tmin = row_events +metadata_tmax = ["response/left", "response/right"] + +metadata, events, event_id = mne.epochs.make_metadata( + events=all_events, + event_id=all_event_id, + tmin=metadata_tmin, + tmax=metadata_tmax, + sfreq=raw.info["sfreq"], + row_events=row_events, +) + +metadata + +# %% +# Variable time window (simplified) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# We can slightly simplify the above code: Since ``tmin`` shall be set to the +# ``row_events``, we can paass ``tmin=None``, which is a more convenient way to express +# ``tmin=row_events``. The resulting metadata looks the same as in the previous example. + +metadata_tmin = None # <-- new +metadata_tmax = ["response/left", "response/right"] + +metadata, events, event_id = mne.epochs.make_metadata( + events=all_events, + event_id=all_event_id, + tmin=metadata_tmin, + tmax=metadata_tmax, + sfreq=raw.info["sfreq"], + row_events=row_events, +) + +metadata diff --git a/mne-python/source/examples/preprocessing/esg_rm_heart_artefact_pcaobs.py b/mne-python/source/examples/preprocessing/esg_rm_heart_artefact_pcaobs.py new file mode 100644 index 0000000000000000000000000000000000000000..a6c6bb3c2baa82b524acaa19638af88c35bc7ceb --- /dev/null +++ b/mne-python/source/examples/preprocessing/esg_rm_heart_artefact_pcaobs.py @@ -0,0 +1,196 @@ +""" +.. _ex-pcaobs: + +===================================================================================== +Principal Component Analysis - Optimal Basis Sets (PCA-OBS) removing cardiac artefact +===================================================================================== + +This script shows an example of how to use an adaptation of PCA-OBS +:footcite:`NiazyEtAl2005`. PCA-OBS was originally designed to remove +the ballistocardiographic artefact in simultaneous EEG-fMRI. Here, it +has been adapted to remove the delay between the detected R-peak and the +ballistocardiographic artefact such that the algorithm can be applied to +remove the cardiac artefact in EEG (electroencephalography) and ESG +(electrospinography) data. We will illustrate how it works by applying the +algorithm to ESG data, where the effect of removal is most pronounced. + +See: https://www.biorxiv.org/content/10.1101/2024.09.05.611423v1 +for more details on the dataset and application for ESG data. + +""" + +# Authors: Emma Bailey , +# Steinn Hauser Magnusson +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import glob + +import numpy as np + +# %% +# Download sample subject data from OpenNeuro if you haven't already. +# This will download simultaneous EEG and ESG data from a single run of a +# single participant after median nerve stimulation of the left wrist. +import openneuro +from matplotlib import pyplot as plt + +import mne +from mne import Epochs, events_from_annotations +from mne.io import read_raw_eeglab +from mne.preprocessing import find_ecg_events, fix_stim_artifact + +# add the path where you want the OpenNeuro data downloaded. Each run is ~2GB of data +ds = "ds004388" +target_dir = mne.datasets.default_path() / ds +run_name = "sub-001/eeg/*median_run-03_eeg*.set" +if not glob.glob(str(target_dir / run_name)): + target_dir.mkdir(exist_ok=True) + openneuro.download(dataset=ds, target_dir=target_dir, include=run_name[:-4]) +block_files = glob.glob(str(target_dir / run_name)) +assert len(block_files) == 1 + +# %% +# Define the esg channels (arranged in two patches over the neck and lower back). + +esg_chans = [ + "S35", + "S24", + "S36", + "Iz", + "S17", + "S15", + "S32", + "S22", + "S19", + "S26", + "S28", + "S9", + "S13", + "S11", + "S7", + "SC1", + "S4", + "S18", + "S8", + "S31", + "SC6", + "S12", + "S16", + "S5", + "S30", + "S20", + "S34", + "S21", + "S25", + "L1", + "S29", + "S14", + "S33", + "S3", + "L4", + "S6", + "S23", +] + +# Interpolation window in seconds for ESG data to remove stimulation artefact +tstart_esg = -7e-3 +tmax_esg = 7e-3 + +# Define timing of heartbeat epochs in seconds relative to R-peaks +iv_baseline = [-400e-3, -300e-3] +iv_epoch = [-400e-3, 600e-3] + +# %% +# Next, we perform minimal preprocessing including removing the +# stimulation artefact, downsampling and filtering. + +raw = read_raw_eeglab(block_files[0], verbose="error") +raw.set_channel_types(dict(ECG="ecg")) +# Isolate the ESG channels (include the ECG channel for R-peak detection) +raw.pick(esg_chans + ["ECG"]) +# Trim duration and downsample (from 10kHz) to improve example speed +raw.crop(0, 60).load_data().resample(2000) + +# Find trigger timings to remove the stimulation artefact +events, event_dict = events_from_annotations(raw) +trigger_name = "Median - Stimulation" + +fix_stim_artifact( + raw, + events=events, + event_id=event_dict[trigger_name], + tmin=tstart_esg, + tmax=tmax_esg, + mode="linear", + stim_channel=None, +) + +# %% +# Find ECG events and add to the raw structure as event annotations. + +ecg_events, ch_ecg, average_pulse = find_ecg_events(raw, ch_name="ECG") +ecg_event_samples = np.asarray( + [[ecg_event[0] for ecg_event in ecg_events]] +) # Samples only + +qrs_event_time = [ + x / raw.info["sfreq"] for x in ecg_event_samples.reshape(-1) +] # Divide by sampling rate to make times +duration = np.repeat(0.0, len(ecg_event_samples)) +description = ["qrs"] * len(ecg_event_samples) + +raw.annotations.append( + qrs_event_time, duration, description, ch_names=[esg_chans] * len(qrs_event_time) +) + +# %% +# Create evoked response around the detected R-peaks +# before and after cardiac artefact correction. + +events, event_ids = events_from_annotations(raw) +event_id_dict = {key: value for key, value in event_ids.items() if key == "qrs"} +epochs = Epochs( + raw, + events, + event_id=event_id_dict, + tmin=iv_epoch[0], + tmax=iv_epoch[1], + baseline=tuple(iv_baseline), +) +evoked_before = epochs.average() + +# Apply function - modifies the data in place. Optionally high-pass filter +# the data before applying PCA-OBS to remove low frequency drifts +raw = mne.preprocessing.apply_pca_obs( + raw, picks=esg_chans, n_jobs=5, qrs_times=raw.times[ecg_event_samples.reshape(-1)] +) + +epochs = Epochs( + raw, + events, + event_id=event_id_dict, + tmin=iv_epoch[0], + tmax=iv_epoch[1], + baseline=tuple(iv_baseline), +) +evoked_after = epochs.average() + +# %% +# Compare evoked responses to assess completeness of artefact removal. + +fig, axes = plt.subplots(1, 1, layout="constrained") +data_before = evoked_before.get_data(units=dict(eeg="uV")).T +data_after = evoked_after.get_data(units=dict(eeg="uV")).T +hs = list() +hs.append(axes.plot(epochs.times, data_before, color="k")[0]) +hs.append(axes.plot(epochs.times, data_after, color="green", label="after")[0]) +axes.set(ylim=[-500, 1000], ylabel="Amplitude (µV)", xlabel="Time (s)") +axes.set(title="ECG artefact removal using PCA-OBS") +axes.legend(hs, ["before", "after"]) +plt.show() + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/find_ref_artifacts.py b/mne-python/source/examples/preprocessing/find_ref_artifacts.py new file mode 100644 index 0000000000000000000000000000000000000000..90e3d1fb0da851d9ed1ed4f46dae40f19d7dd901 --- /dev/null +++ b/mne-python/source/examples/preprocessing/find_ref_artifacts.py @@ -0,0 +1,152 @@ +""" +.. _ex-megnoise_processing: + +==================================== +Find MEG reference channel artifacts +==================================== + +Use ICA decompositions of MEG reference channels to remove intermittent noise. + +Many MEG systems have an array of reference channels which are used to detect +external magnetic noise. However, standard techniques that use reference +channels to remove noise from standard channels often fail when noise is +intermittent. The technique described here (using ICA on the reference +channels) often succeeds where the standard techniques do not. + +There are two algorithms to choose from: separate and together (default). In +the "separate" algorithm, two ICA decompositions are made: one on the reference +channels, and one on reference + standard channels. The reference + standard +channel components which correlate with the reference channel components are +removed. + +In the "together" algorithm, a single ICA decomposition is made on reference + +standard channels, and those components whose weights are particularly heavy +on the reference channels are removed. + +This technique is fully described and validated in :footcite:`HannaEtAl2020` + +""" +# Authors: Jeff Hanna +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne import io +from mne.datasets import refmeg_noise +from mne.preprocessing import ICA + +print(__doc__) + +data_path = refmeg_noise.data_path() + +# %% +# Read raw data, cropping to 5 minutes to save memory + +raw_fname = data_path / "sample_reference_MEG_noise-raw.fif" +raw = io.read_raw_fif(raw_fname).crop(300, 600).load_data() + +# %% +# Note that even though standard noise removal has already +# been applied to these data, much of the noise in the reference channels +# (bottom of the plot) can still be seen in the standard channels. +select_picks = np.concatenate( + ( + mne.pick_types(raw.info, meg=True)[-32:], + mne.pick_types(raw.info, meg=False, ref_meg=True), + ) +) +plot_kwargs = dict( + duration=100, + order=select_picks, + n_channels=len(select_picks), + scalings={"mag": 8e-13, "ref_meg": 2e-11}, +) +raw.plot(**plot_kwargs) + +# %% +# The PSD of these data show the noise as clear peaks. +raw.compute_psd(fmax=30).plot(picks="data", exclude="bads", amplitude=False) + +# %% +# Run the "together" algorithm. +raw_tog = raw.copy() +ica_kwargs = dict( + method="picard", + fit_params=dict(tol=1e-4), # use a high tol here for speed +) +all_picks = mne.pick_types(raw_tog.info, meg=True, ref_meg=True) +ica_tog = ICA(n_components=60, max_iter="auto", allow_ref_meg=True, **ica_kwargs) +ica_tog.fit(raw_tog, picks=all_picks) +# low threshold (2.0) here because of cropped data, entire recording can use +# a higher threshold (2.5) +bad_comps, scores = ica_tog.find_bads_ref(raw_tog, threshold=2.0) + +# Plot scores with bad components marked. +ica_tog.plot_scores(scores, bad_comps) + +# Examine the properties of removed components. It's clear from the time +# courses and topographies that these components represent external, +# intermittent noise. +ica_tog.plot_properties(raw_tog, picks=bad_comps) + +# Remove the components. +raw_tog = ica_tog.apply(raw_tog, exclude=bad_comps) + +# %% +# Cleaned data: +raw_tog.compute_psd(fmax=30).plot(picks="data", exclude="bads", amplitude=False) + +# %% +# Now try the "separate" algorithm. +raw_sep = raw.copy() + +# Do ICA only on the reference channels. +ref_picks = mne.pick_types(raw_sep.info, meg=False, ref_meg=True) +ica_ref = ICA(n_components=2, max_iter="auto", allow_ref_meg=True, **ica_kwargs) +ica_ref.fit(raw_sep, picks=ref_picks) + +# Do ICA on both reference and standard channels. Here, we can just reuse +# ica_tog from the section above. +ica_sep = ica_tog.copy() + +# Extract the time courses of these components and add them as channels +# to the raw data. Think of them the same way as EOG/EKG channels, but instead +# of giving info about eye movements/cardiac activity, they give info about +# external magnetic noise. +ref_comps = ica_ref.get_sources(raw_sep) +for c in ref_comps.ch_names: # they need to have REF_ prefix to be recognised + ref_comps.rename_channels({c: "REF_" + c}) +raw_sep.add_channels([ref_comps]) + +# Now that we have our noise channels, we run the separate algorithm. +bad_comps, scores = ica_sep.find_bads_ref(raw_sep, method="separate") + +# Plot scores with bad components marked. +ica_sep.plot_scores(scores, bad_comps) + +# Examine the properties of removed components. +ica_sep.plot_properties(raw_sep, picks=bad_comps) + +# Remove the components. +raw_sep = ica_sep.apply(raw_sep, exclude=bad_comps) + +# %% +# Cleaned raw data traces: + +raw_sep.plot(**plot_kwargs) + +# %% +# Cleaned raw data PSD: + +raw_sep.compute_psd(fmax=30).plot(picks="data", exclude="bads", amplitude=False) + +############################################################################## +# References +# ---------- +# +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/fnirs_artifact_removal.py b/mne-python/source/examples/preprocessing/fnirs_artifact_removal.py new file mode 100644 index 0000000000000000000000000000000000000000..7c4855086a7215ba63b87ab28fd731f039a76582 --- /dev/null +++ b/mne-python/source/examples/preprocessing/fnirs_artifact_removal.py @@ -0,0 +1,98 @@ +""" +.. _ex-fnirs-artifacts: + +========================================== +Visualise NIRS artifact correction methods +========================================== + +Here we artificially introduce several fNIRS artifacts and observe +how artifact correction techniques attempt to correct the data. + +""" +# Authors: Robert Luke +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import os + +import mne +from mne.preprocessing.nirs import ( + optical_density, + temporal_derivative_distribution_repair, +) + +# %% +# Import data +# ----------- +# +# Here we will work with the :ref:`fNIRS motor data `. +# We resample the data to make indexing exact times more convenient. +# We then convert the data to optical density to perform corrections on +# and plot these signals. + +fnirs_data_folder = mne.datasets.fnirs_motor.data_path() +fnirs_cw_amplitude_dir = os.path.join(fnirs_data_folder, "Participant-1") +raw_intensity = mne.io.read_raw_nirx(fnirs_cw_amplitude_dir, verbose=True) +raw_intensity.load_data().resample(3, npad="auto") +raw_od = optical_density(raw_intensity) +new_annotations = mne.Annotations( + [31, 187, 317], [8, 8, 8], ["Movement", "Movement", "Movement"] +) +raw_od.set_annotations(new_annotations) +raw_od.plot(n_channels=15, duration=400, show_scrollbars=False) + +# %% +# We can see some small artifacts in the above data from movement around 40, +# 190 and 240 seconds. However, this data is relatively clean so we will +# add some additional artifacts below. + + +# %% +# Add artificial artifacts to data +# -------------------------------- +# +# Two common types of artifacts in NIRS data are spikes and baseline shifts. +# Spikes often occur when a person moves and the optode moves relative to the +# scalp and then returns to its original position. +# Baseline shifts occur if the optode moves relative to the scalp and does not +# return to its original position. +# We add a spike type artifact at 100 seconds and a baseline shift at 200 +# seconds to the data. + +corrupted_data = raw_od.get_data() +corrupted_data[:, 298:302] = corrupted_data[:, 298:302] - 0.06 +corrupted_data[:, 450:750] = corrupted_data[:, 450:750] + 0.03 +corrupted_od = mne.io.RawArray( + corrupted_data, raw_od.info, first_samp=raw_od.first_samp +) +new_annotations.append([95, 145, 245], [10, 10, 10], ["Spike", "Baseline", "Baseline"]) +corrupted_od.set_annotations(new_annotations) + +corrupted_od.plot(n_channels=15, duration=400, show_scrollbars=False) + + +# %% +# Apply temporal derivative distribution repair +# --------------------------------------------- +# +# This approach corrects baseline shift and spike artifacts without the need +# for any user-supplied parameters :footcite:`FishburnEtAl2019`. + +corrected_tddr = temporal_derivative_distribution_repair(corrupted_od) +corrected_tddr.plot(n_channels=15, duration=400, show_scrollbars=False) + + +# %% +# We can see in the data above that the introduced spikes and shifts are +# largely removed, but some residual smaller artifact remains. +# The same can be said for the artifacts in the original data. + + +# %% +# References +# ---------- +# +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/ica_comparison.py b/mne-python/source/examples/preprocessing/ica_comparison.py new file mode 100644 index 0000000000000000000000000000000000000000..d4246b803623ad3bf8e5e4624df428ade32d014a --- /dev/null +++ b/mne-python/source/examples/preprocessing/ica_comparison.py @@ -0,0 +1,76 @@ +""" +.. _ex-ica-comp: + +=========================================== +Compare the different ICA algorithms in MNE +=========================================== + +Different ICA algorithms are fit to raw MEG data, and the corresponding maps +are displayed. + +""" +# Authors: Pierre Ablin +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +from time import time + +import mne +from mne.datasets import sample +from mne.preprocessing import ICA + +print(__doc__) + +# %% +# Read and preprocess the data. Preprocessing consists of: +# +# - MEG channel selection +# - 1-30 Hz band-pass filter + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" + +raw = mne.io.read_raw_fif(raw_fname).crop(0, 60).pick("meg").load_data() + +reject = dict(mag=5e-12, grad=4000e-13) +raw.filter(1, 30, fir_design="firwin") + + +# %% +# Define a function that runs ICA on the raw MEG data and plots the components + + +def run_ica(method, fit_params=None): + ica = ICA( + n_components=20, + method=method, + fit_params=fit_params, + max_iter="auto", + random_state=0, + ) + t0 = time() + ica.fit(raw, reject=reject) + fit_time = time() - t0 + title = f"ICA decomposition using {method} (took {fit_time:.1f}s)" + ica.plot_components(title=title) + + +# %% +# FastICA +run_ica("fastica") + +# %% +# Picard +run_ica("picard") + +# %% +# Infomax +run_ica("infomax") + +# %% +# Extended Infomax +run_ica("infomax", fit_params=dict(extended=True)) diff --git a/mne-python/source/examples/preprocessing/interpolate_bad_channels.py b/mne-python/source/examples/preprocessing/interpolate_bad_channels.py new file mode 100644 index 0000000000000000000000000000000000000000..a56aec7d8f77c4ec0aa04ba7d42d3195b0175bb1 --- /dev/null +++ b/mne-python/source/examples/preprocessing/interpolate_bad_channels.py @@ -0,0 +1,54 @@ +""" +.. _ex-interpolate-bad-channels: + +============================================= +Interpolate bad channels for MEG/EEG channels +============================================= + +This example shows how to interpolate bad MEG/EEG channels + +- Using spherical splines from :footcite:`PerrinEtAl1989` for EEG data. +- Using field interpolation for MEG and EEG data. + +In this example, the bad channels will still be marked as bad. +Only the data in those channels is replaced. +""" +# Authors: Denis A. Engemann +# Mainak Jas +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +# sphinx_gallery_thumbnail_number = 2 + +import mne +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fname = meg_path / "sample_audvis-ave.fif" +evoked = mne.read_evokeds(fname, condition="Left Auditory", baseline=(None, 0)) + +# plot with bads +evoked.plot(exclude=[], picks=("grad", "eeg")) + +# %% +# Compute interpolation (also works with Raw and Epochs objects) +evoked_interp = evoked.copy().interpolate_bads(reset_bads=False) +evoked_interp.plot(exclude=[], picks=("grad", "eeg")) + +# %% +# You can also use minimum-norm for EEG as well as MEG +evoked_interp_mne = evoked.copy().interpolate_bads( + reset_bads=False, method=dict(eeg="MNE"), verbose=True +) +evoked_interp_mne.plot(exclude=[], picks=("grad", "eeg")) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/interpolate_to.py b/mne-python/source/examples/preprocessing/interpolate_to.py new file mode 100644 index 0000000000000000000000000000000000000000..5672dca3dd83cf68605e5d6864ba847a6531cace --- /dev/null +++ b/mne-python/source/examples/preprocessing/interpolate_to.py @@ -0,0 +1,148 @@ +""" +.. _ex-interpolate-to-any-montage: + +====================================================== +Interpolate MEG or EEG data to any montage +====================================================== + +This example demonstrates both EEG montage interpolation and MEG system +transformation. + +For EEG, this can be useful for standardizing +EEG channel layouts across different datasets (see :footcite:`MellotEtAl2024`). + +- Using the field interpolation for EEG data. +- Using the target montage "biosemi16". +- Using the MNE interpolation for MEG data to transform from Neuromag + (planar gradiometers and magnetometers) to CTF (axial gradiometers). + + +In the first example, the data from the original EEG channels will be +interpolated onto the positions defined by the "biosemi16" montage. + +In the second example, we will interpolate MEG data from a 306-sensor Neuromag +to 275-sensor CTF system. +""" + +# Authors: Antoine Collas +# Konstantinos Tsilimparis +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import matplotlib.pyplot as plt + +import mne +from mne.channels import make_standard_montage +from mne.datasets import sample + +print(__doc__) +ylim = (-10, 10) + +# %% +# Part 1: EEG System Transformation +# ================================== + +# Load EEG data +data_path = sample.data_path() +eeg_file_path = data_path / "MEG" / "sample" / "sample_audvis-ave.fif" +evoked = mne.read_evokeds(eeg_file_path, condition="Left Auditory", baseline=(None, 0)) + +# Select only EEG channels +evoked.pick("eeg") + +# Plot the original EEG layout +evoked.plot(exclude=[], picks="eeg", ylim=dict(eeg=ylim)) + +# %% +# Define the target montage +standard_montage = make_standard_montage("biosemi16") + +# %% +# Use interpolate_to to project EEG data to the standard montage +evoked_interpolated_spline = evoked.copy().interpolate_to( + standard_montage, method="spline" +) + +# Plot the interpolated EEG layout +evoked_interpolated_spline.plot(exclude=[], picks="eeg", ylim=dict(eeg=ylim)) + +# %% +# Use interpolate_to to project EEG data to the standard montage +evoked_interpolated_mne = evoked.copy().interpolate_to(standard_montage, method="MNE") + +# Plot the interpolated EEG layout +evoked_interpolated_mne.plot(exclude=[], picks="eeg", ylim=dict(eeg=ylim)) + +# %% +# Comparing before and after interpolation +fig, axs = plt.subplots(3, 1, figsize=(8, 6), constrained_layout=True) +evoked.plot(exclude=[], picks="eeg", axes=axs[0], show=False, ylim=dict(eeg=ylim)) +axs[0].set_title("Original EEG Layout") +evoked_interpolated_spline.plot( + exclude=[], picks="eeg", axes=axs[1], show=False, ylim=dict(eeg=ylim) +) +axs[1].set_title("Interpolated to Standard 1020 Montage using spline interpolation") +evoked_interpolated_mne.plot( + exclude=[], picks="eeg", axes=axs[2], show=False, ylim=dict(eeg=ylim) +) +axs[2].set_title("Interpolated to Standard 1020 Montage using MNE interpolation") + +# %% +# Part 2: MEG System Transformation +# ================================== +# We demonstrate transforming MEG data from Neuromag (planar gradiometers +# and magnetometers) to CTF (axial gradiometers) sensor configuration. + +# Load the full evoked data with MEG channels +evoked_meg = mne.read_evokeds( + eeg_file_path, condition="Left Auditory", baseline=(None, 0) +) +evoked_meg.pick("meg") + +print("Original Neuromag system:") +print(f" Number of magnetometers: {len(mne.pick_types(evoked_meg.info, meg='mag'))}") +print(f" Number of gradiometers: {len(mne.pick_types(evoked_meg.info, meg='grad'))}") + +# %% +# Transform to CTF sensor configuration +# ====================================== + +# Interpolate Neuromag to CTF +evoked_ctf = evoked_meg.copy().interpolate_to("ctf275", mode="accurate") + +print("\nTransformed to CTF system:") +print(f" Number of MEG channels: {len(mne.pick_types(evoked_ctf.info, meg=True))}") +print(f" Bad channels in original: {evoked_meg.info['bads']}") + +# %% +# Compare evoked responses: Original Neuromag vs Transformed CTF +# The data should be similar but projected onto different sensor arrays + +# Set consistent y-limits for comparison +ylim_meg = dict(grad=[-300, 300], mag=[-600, 600], meg=[-300, 300]) + +fig, axes = plt.subplots(3, 1, figsize=(10, 8), layout="constrained") + +# Plot original Neuromag gradiometers +evoked_meg.copy().pick("grad").plot( + axes=axes[0], show=False, spatial_colors=True, ylim=ylim_meg, time_unit="s" +) +axes[0].set_title("Original Neuromag Planar Gradiometers", fontsize=14) + + +# Plot original Neuromag magnetometers +evoked_meg.copy().pick("mag").plot( + axes=axes[1], show=False, spatial_colors=True, ylim=ylim_meg, time_unit="s" +) +axes[1].set_title("Original Neuromag Magnetometers", fontsize=14) + +# Plot transformed CTF gradiometers +evoked_ctf.plot( + axes=axes[2], show=False, spatial_colors=True, ylim=ylim_meg, time_unit="s" +) +axes[2].set_title("Transformed to CTF275 Axial Gradiometers", fontsize=14) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/movement_compensation.py b/mne-python/source/examples/preprocessing/movement_compensation.py new file mode 100644 index 0000000000000000000000000000000000000000..4577a7e0a519901296371e76034521febb7ed37b --- /dev/null +++ b/mne-python/source/examples/preprocessing/movement_compensation.py @@ -0,0 +1,88 @@ +""" +.. _ex-movement-comp: + +============================================== +Maxwell filter data with movement compensation +============================================== + +Demonstrate movement compensation on simulated data. The simulated data +contains bilateral activation of auditory cortices, repeated over 14 +different head rotations (head center held fixed). See the following for +details: + + https://github.com/mne-tools/mne-misc-data/blob/master/movement/simulate.py + +""" +# Authors: Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.preprocessing import maxwell_filter + +print(__doc__) + +data_path = mne.datasets.misc.data_path(verbose=True) / "movement" + +head_pos = mne.chpi.read_head_pos(data_path / "simulated_quats.pos") +raw = mne.io.read_raw_fif(data_path / "simulated_movement_raw.fif") +raw_stat = mne.io.read_raw_fif(data_path / "simulated_stationary_raw.fif") + +# %% +# Visualize the "subject" head movements. By providing the measurement +# information, the distance to the nearest sensor in each direction +# (e.g., left/right for the X direction, forward/backward for Y) can +# be shown in blue, and the destination (if given) shown in red. + +mne.viz.plot_head_positions( + head_pos, mode="traces", destination=raw.info["dev_head_t"], info=raw.info +) + +# %% +# This can also be visualized using a quiver. + +mne.viz.plot_head_positions( + head_pos, mode="field", destination=raw.info["dev_head_t"], info=raw.info +) + +# %% +# Process our simulated raw data (taking into account head movements). + +# extract our resulting events +events = mne.find_events(raw, stim_channel="STI 014") +events[:, 2] = 1 +raw.plot(events=events) + +topo_kwargs = dict(times=[0, 0.1, 0.2], ch_type="mag", vlim=(-500, 500)) + +# %% +# First, take the average of stationary data (bilateral auditory patterns). +evoked_stat = mne.Epochs(raw_stat, events, 1, -0.2, 0.8).average() +fig = evoked_stat.plot_topomap(**topo_kwargs) +fig.suptitle("Stationary") + +# %% +# Second, take a naive average, which averages across epochs that have been +# simulated to have different head positions and orientations, thereby +# spatially smearing the activity. +epochs = mne.Epochs(raw, events, 1, -0.2, 0.8) +evoked = epochs.average() +fig = evoked.plot_topomap(**topo_kwargs) +fig.suptitle("Moving: naive average") + +# %% +# Third, use raw movement compensation (restores pattern). +raw_sss = maxwell_filter(raw, head_pos=head_pos, mc_interp="hann") +evoked_raw_mc = mne.Epochs(raw_sss, events, 1, -0.2, 0.8).average() +fig = evoked_raw_mc.plot_topomap(**topo_kwargs) +fig.suptitle("Moving: movement compensated (raw)") + +# %% +# Fourth, use evoked movement compensation. For these data, which contain +# very large rotations, it does not as cleanly restore the pattern. +evoked_evo_mc = mne.epochs.average_movements(epochs, head_pos=head_pos) +fig = evoked_evo_mc.plot_topomap(**topo_kwargs) +fig.suptitle("Moving: movement compensated (evoked)") diff --git a/mne-python/source/examples/preprocessing/movement_detection.py b/mne-python/source/examples/preprocessing/movement_detection.py new file mode 100644 index 0000000000000000000000000000000000000000..dd468feb464ae09a46a722d63348f3cc2eedf3a0 --- /dev/null +++ b/mne-python/source/examples/preprocessing/movement_detection.py @@ -0,0 +1,94 @@ +""" +.. _ex-movement-detect: + +===================================================== +Annotate movement artifacts and reestimate dev_head_t +===================================================== + +Periods, where the participant moved considerably, are contaminated by low +amplitude artifacts. When averaging the magnetic fields, the more spread the +head position, the bigger the cancellation due to different locations. +Similarly, the covariance will also be affected by severe head movement, +and source estimation will suffer low/smeared coregistration accuracy. + +This example uses the continuous head position indicators (cHPI) times series +to annotate periods of head movement, then the device to head transformation +matrix is estimated from the artifact-free segments. The new head position will +be more representative of the actual head position during the recording. +""" +# Authors: Adonay Nunes +# Luke Bloy +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.datasets.brainstorm import bst_auditory +from mne.io import read_raw_ctf +from mne.preprocessing import annotate_movement, compute_average_dev_head_t + +# Load data +data_path = bst_auditory.data_path() +data_path_MEG = data_path / "MEG" +subject = "bst_auditory" +subjects_dir = data_path / "subjects" +trans_fname = data_path / "MEG" / "bst_auditory" / "bst_auditory-trans.fif" +raw_fname1 = data_path_MEG / "bst_auditory" / "S01_AEF_20131218_01.ds" +raw_fname2 = data_path_MEG / "bst_auditory" / "S01_AEF_20131218_02.ds" +# read and concatenate two files, ignoring device<->head mismatch +raw = read_raw_ctf(raw_fname1, preload=False) +mne.io.concatenate_raws( + [raw, read_raw_ctf(raw_fname2, preload=False)], on_mismatch="ignore" +) +raw.crop(350, 410).load_data() +raw.resample(100, npad="auto") + +# %% +# Plot continuous head position with respect to the mean recording position +# -------------------------------------------------------------------------- + +# Get cHPI time series and compute average +chpi_locs = mne.chpi.extract_chpi_locs_ctf(raw) +head_pos = mne.chpi.compute_head_pos(raw.info, chpi_locs) +original_head_dev_t = mne.transforms.invert_transform(raw.info["dev_head_t"]) +average_head_dev_t = mne.transforms.invert_transform( + compute_average_dev_head_t(raw, head_pos) +) +fig = mne.viz.plot_head_positions(head_pos) +for ax, val, val_ori in zip( + fig.axes[::2], + average_head_dev_t["trans"][:3, 3], + original_head_dev_t["trans"][:3, 3], +): + ax.axhline(1000 * val, color="r") + ax.axhline(1000 * val_ori, color="g") + +# The green horizontal lines represent the original head position, whereas the +# red lines are the new head position averaged over all the time points. + +# %% +# Plot raw data with annotated movement +# ------------------------------------------------------------------ + +mean_distance_limit = 0.0015 # in meters +annotation_movement, hpi_disp = annotate_movement( + raw, head_pos, mean_distance_limit=mean_distance_limit +) +raw.set_annotations(annotation_movement) +raw.plot(n_channels=100, duration=20) + +############################################################################## +# After checking the annotated movement artifacts, calculate the new transform +# and plot it: + +new_dev_head_t = compute_average_dev_head_t(raw, head_pos) +raw.info["dev_head_t"] = new_dev_head_t +fig = mne.viz.plot_alignment( + raw.info, + show_axes=True, + subject=subject, + trans=trans_fname, + subjects_dir=subjects_dir, +) +mne.viz.set_3d_view(fig, azimuth=90, elevation=60) diff --git a/mne-python/source/examples/preprocessing/muscle_detection.py b/mne-python/source/examples/preprocessing/muscle_detection.py new file mode 100644 index 0000000000000000000000000000000000000000..3e0e140c8029987b52338250ae3a06d797f54834 --- /dev/null +++ b/mne-python/source/examples/preprocessing/muscle_detection.py @@ -0,0 +1,88 @@ +""" +.. _ex-muscle-artifacts: + +========================= +Annotate muscle artifacts +========================= + +Muscle contractions produce high frequency activity that can mask brain signal +of interest. Muscle artifacts can be produced when clenching the jaw, +swallowing, or twitching a cranial muscle. Muscle artifacts are most +noticeable in the range of 110-140 Hz. + +This example uses :func:`~mne.preprocessing.annotate_muscle_zscore` to annotate +segments where muscle activity is likely present. This is done by band-pass +filtering the data in the 110-140 Hz range. Then, the envelope is taken using +the hilbert analytical signal to only consider the absolute amplitude and not +the phase of the high frequency signal. The envelope is z-scored and summed +across channels and divided by the square root of the number of channels. +Because muscle artifacts last several hundred milliseconds, a low-pass filter +is applied on the averaged z-scores at 4 Hz, to remove transient peaks. +Segments above a set threshold are annotated as ``BAD_muscle``. In addition, +the ``min_length_good`` parameter determines the cutoff for whether short +spans of "good data" in between muscle artifacts are included in the +surrounding "BAD" annotation. + +""" +# Authors: Adonay Nunes +# Luke Bloy +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +from mne.datasets.brainstorm import bst_auditory +from mne.io import read_raw_ctf +from mne.preprocessing import annotate_muscle_zscore + +# Load data +data_path = bst_auditory.data_path() +raw_fname = data_path / "MEG" / "bst_auditory" / "S01_AEF_20131218_01.ds" + +raw = read_raw_ctf(raw_fname, preload=False) + +raw.crop(130, 160).load_data() # just use a fraction of data for speed here +raw.resample(300, npad="auto") + +# %% +# Notch filter the data: +# +# .. note:: +# If line noise is present, you should perform notch-filtering *before* +# detecting muscle artifacts. See :ref:`tut-section-line-noise` for an +# example. + +raw.notch_filter([60, 120]) + +# %% + +# The threshold is data dependent, check the optimal threshold by plotting +# ``scores_muscle``. +threshold_muscle = 5 # z-score +# Choose one channel type, if there are axial gradiometers and magnetometers, +# select magnetometers as they are more sensitive to muscle activity. +annot_muscle, scores_muscle = annotate_muscle_zscore( + raw, + ch_type="mag", + threshold=threshold_muscle, + min_length_good=0.2, + filter_freq=[110, 140], +) + +# %% +# Plot muscle z-scores across recording +# -------------------------------------------------------------------------- + +fig, ax = plt.subplots() +ax.plot(raw.times, scores_muscle) +ax.axhline(y=threshold_muscle, color="r") +ax.set(xlabel="time, (s)", ylabel="zscore", title="Muscle activity") +# %% +# View the annotations +# -------------------------------------------------------------------------- +order = np.arange(144, 164) +raw.set_annotations(annot_muscle) +raw.plot(start=5, duration=20, order=order) diff --git a/mne-python/source/examples/preprocessing/muscle_ica.py b/mne-python/source/examples/preprocessing/muscle_ica.py new file mode 100644 index 0000000000000000000000000000000000000000..f61d1e22bc41d7c52790f217aa6c09b2275a2f5b --- /dev/null +++ b/mne-python/source/examples/preprocessing/muscle_ica.py @@ -0,0 +1,126 @@ +""" +.. _ex-muscle-ica: + +============================== +Removing muscle ICA components +============================== + +Gross movements produce widespread high-frequency activity across all channels +that is usually not recoverable and so the epoch must be rejected as shown in +:ref:`ex-muscle-artifacts`. More ubiquitously than gross movements, muscle +artifact is produced during postural maintenance. This is more appropriately +removed by ICA otherwise there wouldn't be any epochs left! Note that muscle +artifacts of this kind are much more pronounced in EEG than they are in MEG. +""" +# Authors: Alex Rockhill +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne + +data_path = mne.datasets.sample.data_path() +raw_fname = data_path / "MEG" / "sample" / "sample_audvis_raw.fif" +raw = mne.io.read_raw_fif(raw_fname) +raw.crop(tmin=100, tmax=130) # take 30 seconds for speed + +# pick only EEG channels, muscle artifact is basically not picked up by MEG +# if you have a simultaneous recording, you may want to do ICA on MEG and EEG +# separately +raw.pick(picks="eeg", exclude="bads") + +# ICA works best with a highpass filter applied +raw.load_data() +raw.filter(l_freq=1.0, h_freq=None) + +# %% +# Run ICA +ica = mne.preprocessing.ICA( + n_components=15, method="picard", max_iter="auto", random_state=97 +) +ica.fit(raw) + +# %% +# Remove components with postural muscle artifact using ICA +ica.plot_sources(raw) + +# %% +# By inspection, let's select out the muscle-artifact components based on +# :footcite:`DharmapraniEtAl2016` manually. +# +# The criteria are: +# +# - Positive slope of log-log power spectrum between 7 and 75 Hz +# (here just flat because it's not in log-log) +# - Peripheral focus or dipole/multi-pole foci (the blue and red +# blobs in the topomap are far from the vertex where the most +# muscle is) +# - Single focal point (low spatial smoothness; there is just one focus +# of the topomap compared to components like the first ones that are +# more likely neural which spread across the topomap) +# +# The other attribute worth noting is that the time course in +# :func:`mne.preprocessing.ICA.plot_sources` looks like EMG; you can +# see spikes when each motor unit fires so that the time course looks fuzzy +# and sometimes has large spikes that are often at regular intervals. +# +# ICA component 13 is a textbook example of what muscle artifact looks like. +# The focus of the topomap for this component is right on the temporalis +# muscle near the ears. There is also a minimum in the power spectrum at around +# 10 Hz, then a maximum at around 25 Hz, generally resulting in a positive +# slope in log-log units; this is a very typical pattern for muscle artifact. + +muscle_idx = [6, 7, 8, 9, 10, 11, 12, 13, 14] +ica.plot_properties(raw, picks=muscle_idx, log_scale=True) + +# first, remove blinks and heartbeat to compare +blink_idx = [0] +heartbeat_idx = [5] +ica.apply(raw, exclude=blink_idx + heartbeat_idx) +ica.plot_overlay(raw, exclude=muscle_idx) + +# %% +# Finally, let's try an automated algorithm to find muscle components +# and ensure that it gets the same components we did manually. +muscle_idx_auto, scores = ica.find_bads_muscle(raw) +ica.plot_scores(scores, exclude=muscle_idx_auto) +print( + f"Manually found muscle artifact ICA components: {muscle_idx}\n" + f"Automatically found muscle artifact ICA components: {muscle_idx_auto}" +) + +# %% +# Let's now replicate this on the EEGBCI dataset +# ---------------------------------------------- + +for sub in (1, 2): + raw = mne.io.read_raw_edf( + mne.datasets.eegbci.load_data(subjects=sub, runs=(1,))[0], preload=True + ) + mne.datasets.eegbci.standardize(raw) # set channel names + montage = mne.channels.make_standard_montage("standard_1005") + raw.set_montage(montage) + raw.filter(l_freq=1.0, h_freq=None) + + # Run ICA + ica = mne.preprocessing.ICA( + n_components=15, method="picard", max_iter="auto", random_state=97 + ) + ica.fit(raw) + ica.plot_sources(raw) + muscle_idx_auto, scores = ica.find_bads_muscle(raw) + ica.plot_properties(raw, picks=muscle_idx_auto, log_scale=True) + ica.plot_scores(scores, exclude=muscle_idx_auto) + + print( + f"Manually found muscle artifact ICA components: {muscle_idx}\n" + "Automatically found muscle artifact ICA components: " + f"{muscle_idx_auto}" + ) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/otp.py b/mne-python/source/examples/preprocessing/otp.py new file mode 100644 index 0000000000000000000000000000000000000000..a7d45d4cbc720cc752d6c284326f1b9a43869b9d --- /dev/null +++ b/mne-python/source/examples/preprocessing/otp.py @@ -0,0 +1,89 @@ +""" +.. _ex-otp: + +=========================================================== +Plot sensor denoising using oversampled temporal projection +=========================================================== + +This demonstrates denoising using the OTP algorithm :footcite:`LarsonTaulu2018` on data +with with sensor artifacts (flux jumps) and random noise. +""" +# Author: Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +import numpy as np + +import mne +from mne import find_events, fit_dipole +from mne.datasets.brainstorm import bst_phantom_elekta +from mne.io import read_raw_fif + +print(__doc__) + +# %% +# Plot the phantom data, lowpassed to get rid of high-frequency artifacts. +# We also crop to a single 10-second segment for speed. +# Notice that there are two large flux jumps on channel 1522 that could +# spread to other channels when performing subsequent spatial operations +# (e.g., Maxwell filtering, SSP, or ICA). + +dipole_number = 1 +data_path = bst_phantom_elekta.data_path() +raw = read_raw_fif(data_path / "kojak_all_200nAm_pp_no_chpi_no_ms_raw.fif") +raw.crop(40.0, 50.0).load_data() +order = list(range(160, 170)) +raw.copy().filter(0.0, 40.0).plot(order=order, n_channels=10) + +# %% +# Now we can clean the data with OTP, lowpass, and plot. The flux jumps have +# been suppressed alongside the random sensor noise. + +raw_clean = mne.preprocessing.oversampled_temporal_projection(raw) +raw_clean.filter(0.0, 40.0) +raw_clean.plot(order=order, n_channels=10) + + +# %% +# We can also look at the effect on single-trial phantom localization. +# See the :ref:`tut-brainstorm-elekta-phantom` +# for more information. Here we use a version that does single-trial +# localization across the 17 trials are in our 10-second window: + + +def compute_bias(raw): + events = find_events(raw, "STI201", verbose=False) + events = events[1:] # first one has an artifact + tmin, tmax = -0.2, 0.1 + epochs = mne.Epochs( + raw, + events, + dipole_number, + tmin, + tmax, + baseline=(None, -0.01), + preload=True, + verbose=False, + ) + sphere = mne.make_sphere_model(r0=(0.0, 0.0, 0.0), head_radius=None, verbose=False) + cov = mne.compute_covariance(epochs, tmax=0, method="oas", rank=None, verbose=False) + idx = epochs.time_as_index(0.036)[0] + data = epochs.get_data(copy=False)[:, :, idx].T + evoked = mne.EvokedArray(data, epochs.info, tmin=0.0) + dip = fit_dipole(evoked, cov, sphere, verbose=False)[0] + actual_pos = mne.dipole.get_phantom_dipoles()[0][dipole_number - 1] + misses = 1000 * np.linalg.norm(dip.pos - actual_pos, axis=-1) + return misses + + +bias = compute_bias(raw) +print(f"Raw bias: {np.mean(bias):0.1f}mm (worst: {np.max(bias):0.1f}mm)") +bias_clean = compute_bias(raw_clean) +print(f"OTP bias: {np.mean(bias_clean):0.1f}mm (worst: {np.max(bias_clean):0.1f}m)") + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/preprocessing/shift_evoked.py b/mne-python/source/examples/preprocessing/shift_evoked.py new file mode 100644 index 0000000000000000000000000000000000000000..0e8c52676fe11bc054304c5e5cef36d5e723c667 --- /dev/null +++ b/mne-python/source/examples/preprocessing/shift_evoked.py @@ -0,0 +1,63 @@ +""" +.. _ex-shift-evoked: + +================================== +Shifting time-scale in evoked data +================================== + +""" +# Author: Mainak Jas +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fname = meg_path / "sample_audvis-ave.fif" + +# Reading evoked data +condition = "Left Auditory" +evoked = mne.read_evokeds(fname, condition=condition, baseline=(None, 0), proj=True) + +picks = ["MEG 2332"] + +# Create subplots +f, (ax1, ax2, ax3) = plt.subplots(3) +evoked.plot( + exclude=[], + picks=picks, + axes=ax1, + titles=dict(grad="Before time shifting"), + time_unit="s", +) + +# Apply relative time-shift of 500 ms +evoked.shift_time(0.5, relative=True) + +evoked.plot( + exclude=[], + picks=picks, + axes=ax2, + titles=dict(grad="Relative shift: 500 ms"), + time_unit="s", +) + +# Apply absolute time-shift of 500 ms +evoked.shift_time(0.5, relative=False) + +evoked.plot( + exclude=[], + picks=picks, + axes=ax3, + titles=dict(grad="Absolute shift: 500 ms"), + time_unit="s", +) diff --git a/mne-python/source/examples/preprocessing/virtual_evoked.py b/mne-python/source/examples/preprocessing/virtual_evoked.py new file mode 100644 index 0000000000000000000000000000000000000000..20f7527f1daab74a6fbbc3ef37d7dd04c0d7a63a --- /dev/null +++ b/mne-python/source/examples/preprocessing/virtual_evoked.py @@ -0,0 +1,62 @@ +""" +.. _ex-virtual-evoked: + +======================= +Remap MEG channel types +======================= + +In this example, MEG data are remapped from one channel type to another. +This is useful to: + + - visualize combined magnetometers and gradiometers as magnetometers + or gradiometers. + - run statistics from both magnetometers and gradiometers while + working with a single type of channels. +""" + +# Author: Mainak Jas + +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.datasets import sample + +print(__doc__) + +# read the evoked +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fname = meg_path / "sample_audvis-ave.fif" +evoked = mne.read_evokeds(fname, condition="Left Auditory", baseline=(None, 0)) + +# %% +# First, let's call remap gradiometers to magnometers, and plot +# the original and remapped topomaps of the magnetometers. + +# go from grad + mag to mag and plot original mag +virt_evoked = evoked.as_type("mag") +fig = evoked.plot_topomap(ch_type="mag") +fig.suptitle("mag (original)") +# %% + +# plot interpolated grad + mag +fig = virt_evoked.plot_topomap(ch_type="mag") +fig.suptitle("mag (interpolated from mag + grad)") + +# %% +# Now, we remap magnometers to gradiometers, and plot +# the original and remapped topomaps of the gradiometers + +# go from grad + mag to grad and plot original grad +virt_evoked = evoked.as_type("grad") +fig = evoked.plot_topomap(ch_type="grad") +fig.suptitle("grad (original)") + +# %% + +# plot interpolated grad + mag +fig = virt_evoked.plot_topomap(ch_type="grad") +fig.suptitle("grad (interpolated from mag + grad)") diff --git a/mne-python/source/examples/preprocessing/xdawn_denoising.py b/mne-python/source/examples/preprocessing/xdawn_denoising.py new file mode 100644 index 0000000000000000000000000000000000000000..20a6abc72fbc2023c1251f45340ebf6a9122c03b --- /dev/null +++ b/mne-python/source/examples/preprocessing/xdawn_denoising.py @@ -0,0 +1,94 @@ +""" +.. _ex-xdawn-denoising: + +=============== +XDAWN Denoising +=============== + +XDAWN filters are trained from epochs, signal is projected in the sources +space and then projected back in the sensor space using only the first two +XDAWN components. The process is similar to an ICA, but is +supervised in order to maximize the signal to signal + noise ratio of the +evoked response :footcite:`RivetEtAl2009, RivetEtAl2011`. + +.. warning:: As this denoising method exploits the known events to + maximize SNR of the contrast between conditions it can lead + to overfitting. To avoid a statistical analysis problem you + should split epochs used in fit with the ones used in + apply method. +""" + +# Authors: Alexandre Barachant +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +from mne import Epochs, compute_raw_covariance, io, pick_types, read_events +from mne.datasets import sample +from mne.preprocessing import Xdawn +from mne.viz import plot_epochs_image + +print(__doc__) + +data_path = sample.data_path() + +# %% +# Set parameters and read data +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +tmin, tmax = -0.1, 0.3 +event_id = dict(vis_r=4) + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname, preload=True) +raw.filter(1, 20, fir_design="firwin") # replace baselining with high-pass +events = read_events(event_fname) + +raw.info["bads"] = ["MEG 2443"] # set bad channels +picks = pick_types(raw.info, meg=True, eeg=False, stim=False, eog=False, exclude="bads") +# Epoching +epochs = Epochs( + raw, + events, + event_id, + tmin, + tmax, + proj=False, + picks=picks, + baseline=None, + preload=True, + verbose=False, +) + +# Plot image epoch before xdawn +plot_epochs_image(epochs["vis_r"], picks=[230], vmin=-500, vmax=500) + +# %% +# Now, we estimate a set of xDAWN filters for the epochs (which contain only +# the ``vis_r`` class). + +# Estimates signal covariance +signal_cov = compute_raw_covariance(raw, picks=picks) + +# Xdawn instance +xd = Xdawn(n_components=2, signal_cov=signal_cov) + +# Fit xdawn +xd.fit(epochs) + +# %% +# Epochs are denoised by calling ``apply``, which by default keeps only the +# signal subspace corresponding to the first ``n_components`` specified in the +# ``Xdawn`` constructor above. +epochs_denoised = xd.apply(epochs) + +# Plot image epoch after Xdawn +plot_epochs_image(epochs_denoised["vis_r"], picks=[230], vmin=-500, vmax=500) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/simulation/README.txt b/mne-python/source/examples/simulation/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..bec6bcce350a5b73532ab31536a09a5e7a000587 --- /dev/null +++ b/mne-python/source/examples/simulation/README.txt @@ -0,0 +1,5 @@ + +Data Simulation +--------------- + +Tools to generate simulation data. diff --git a/mne-python/source/examples/simulation/plot_stc_metrics.py b/mne-python/source/examples/simulation/plot_stc_metrics.py new file mode 100644 index 0000000000000000000000000000000000000000..8b481aed9e6f1298ba60423293e1f2b48d637614 --- /dev/null +++ b/mne-python/source/examples/simulation/plot_stc_metrics.py @@ -0,0 +1,284 @@ +""" +=============================================== +Compare simulated and estimated source activity +=============================================== + +This example illustrates how to compare the simulated and estimated +source time courses (STC) by computing different metrics. Simulated +source is a cortical region or dipole. It is meant to be a brief +introduction and only highlights the simplest use case. + +""" +# Author: Kostiantyn Maksymenko +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from functools import partial + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.datasets import sample +from mne.minimum_norm import apply_inverse, make_inverse_operator +from mne.simulation.metrics import ( + cosine_score, + f1_score, + peak_position_error, + precision_score, + recall_score, + region_localization_error, + spatial_deviation_error, +) + +random_state = 42 # set random state to make this example deterministic + +# Import sample data +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +subject = "sample" +evoked_fname = data_path / "MEG" / subject / "sample_audvis-ave.fif" +info = mne.io.read_info(evoked_fname) +tstep = 1.0 / info["sfreq"] + +# Import forward operator and source space +fwd_fname = data_path / "MEG" / subject / "sample_audvis-meg-eeg-oct-6-fwd.fif" +fwd = mne.read_forward_solution(fwd_fname) +src = fwd["src"] + +# To select source, we use the caudal middle frontal to grow +# a region of interest. +selected_label = mne.read_labels_from_annot( + subject, regexp="caudalmiddlefrontal-lh", subjects_dir=subjects_dir +)[0] + + +############################################################################### +# In this example we simulate two types of cortical sources: a region and +# a dipole sources. We will test corresponding performance metrics. + +############################################################################### +# Define main parameters of sources +# --------------------------------- +# +# First we define both region and dipole sources in terms of +# Where?, What? and When?. + +# WHERE? + +# Region +location = "center" # Use the center of the label as a seed. +extent = 20.0 # Extent in mm of the region. +label_region = mne.label.select_sources( + subject, + selected_label, + location=location, + extent=extent, + subjects_dir=subjects_dir, + random_state=random_state, +) + +# Dipole +location = 1915 # Use the index of the vertex as a seed +extent = 0.0 # One dipole source +label_dipole = mne.label.select_sources( + subject, + selected_label, + location=location, + extent=extent, + subjects_dir=subjects_dir, + random_state=random_state, +) + +# WHAT? +# Define the time course of the activity +source_time_series = np.sin(2.0 * np.pi * 18.0 * np.arange(100) * tstep) * 10e-9 + +# WHEN? +# Define when the activity occurs using events. +n_events = 50 +events = np.zeros((n_events, 3), int) +events[:, 0] = 200 * np.arange(n_events) # Events sample. +events[:, 2] = 1 # All events have the sample id. + +############################################################################### +# Create simulated source activity +# -------------------------------- +# +# Here, :class:`~mne.simulation.SourceSimulator` is used. + +# Region +source_simulator_region = mne.simulation.SourceSimulator(src, tstep=tstep) +source_simulator_region.add_data(label_region, source_time_series, events) + +# Dipole +source_simulator_dipole = mne.simulation.SourceSimulator(src, tstep=tstep) +source_simulator_dipole.add_data(label_dipole, source_time_series, events) + +############################################################################### +# Simulate raw data +# ----------------- +# +# Project the source time series to sensor space with multivariate Gaussian +# noise obtained from the noise covariance from the sample data. + +# Region +raw_region = mne.simulation.simulate_raw(info, source_simulator_region, forward=fwd) +raw_region = raw_region.pick(picks=["eeg", "stim"], exclude="bads") +cov = mne.make_ad_hoc_cov(raw_region.info) +mne.simulation.add_noise( + raw_region, cov, iir_filter=[0.2, -0.2, 0.04], random_state=random_state +) + +# Dipole +raw_dipole = mne.simulation.simulate_raw(info, source_simulator_dipole, forward=fwd) +raw_dipole = raw_dipole.pick(picks=["eeg", "stim"], exclude="bads") +cov = mne.make_ad_hoc_cov(raw_dipole.info) +mne.simulation.add_noise( + raw_dipole, cov, iir_filter=[0.2, -0.2, 0.04], random_state=random_state +) + +############################################################################### +# Compute evoked from raw data +# ---------------------------- +# +# Averaging epochs corresponding to events. + +# Region +events = mne.find_events(raw_region, initial_event=True) +tmax = (len(source_time_series) - 1) * tstep +epochs = mne.Epochs(raw_region, events, 1, tmin=0, tmax=tmax, baseline=None) +evoked_region = epochs.average() + +# Dipole +events = mne.find_events(raw_dipole, initial_event=True) +tmax = (len(source_time_series) - 1) * tstep +epochs = mne.Epochs(raw_dipole, events, 1, tmin=0, tmax=tmax, baseline=None) +evoked_dipole = epochs.average() + +############################################################################### +# Create true stcs corresponding to evoked +# ---------------------------------------- +# +# Before we computed stcs corresponding to raw data. To be able to compare +# it with the reconstruction, based on the evoked, true stc should have the +# same number of time samples. + +# Region +stc_true_region = source_simulator_region.get_stc( + start_sample=0, stop_sample=len(source_time_series) +) + +# Dipole +stc_true_dipole = source_simulator_dipole.get_stc( + start_sample=0, stop_sample=len(source_time_series) +) + +############################################################################### +# Reconstruct simulated sources +# ----------------------------- +# +# Compute inverse solution using sLORETA. + +# Region +snr = 30.0 +inv_method = "sLORETA" +lambda2 = 1.0 / snr**2 + +inverse_operator = make_inverse_operator( + evoked_region.info, fwd, cov, loose="auto", depth=0.8, fixed=True +) + +stc_est_region = apply_inverse( + evoked_region, inverse_operator, lambda2, inv_method, pick_ori=None +) + +# Dipole +snr = 3.0 +inv_method = "sLORETA" +lambda2 = 1.0 / snr**2 + +inverse_operator = make_inverse_operator( + evoked_dipole.info, fwd, cov, loose="auto", depth=0.8, fixed=True +) + +stc_est_dipole = apply_inverse( + evoked_dipole, inverse_operator, lambda2, inv_method, pick_ori=None +) + +############################################################################### +# Compute performance scores for different source amplitude thresholds +# -------------------------------------------------------------------- +# + +thresholds = [10, 30, 50, 70, 80, 90, 95, 99] + +############################################################################### +# For region +# ^^^^^^^^^^ +# + +# create a set of scorers +scorers = { + "RLE": partial(region_localization_error, src=src), + "Precision": precision_score, + "Recall": recall_score, + "F1 score": f1_score, +} + +# compute results +region_results = {} +for name, scorer in scorers.items(): + region_results[name] = [ + scorer(stc_true_region, stc_est_region, threshold=f"{thx}%", per_sample=False) + for thx in thresholds + ] + +# Plot the results +f, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, sharex="col", layout="constrained") +for ax, (title, results) in zip([ax1, ax2, ax3, ax4], region_results.items()): + ax.plot(thresholds, results, ".-") + ax.set(title=title, ylabel="score", xlabel="Threshold", xticks=thresholds) + +f.suptitle("Performance scores per threshold") # Add Super title +ax1.ticklabel_format(axis="y", style="sci", scilimits=(0, 1)) # tweak RLE + +# Cosine score with respect to time +f, ax1 = plt.subplots(layout="constrained") +ax1.plot(stc_true_region.times, cosine_score(stc_true_region, stc_est_region)) +ax1.set(title="Cosine score", xlabel="Time", ylabel="Score") + + +############################################################################### +# For Dipoles +# ^^^^^^^^^^^ +# + +# create a set of scorers +scorers = { + "Peak Position Error": peak_position_error, + "Spatial Deviation Error": spatial_deviation_error, +} + + +# compute results +dipole_results = {} +for name, scorer in scorers.items(): + dipole_results[name] = [ + scorer( + stc_true_dipole, + stc_est_dipole, + src=src, + threshold=f"{thx}%", + per_sample=False, + ) + for thx in thresholds + ] + + +# Plot the results +for name, results in dipole_results.items(): + f, ax1 = plt.subplots(layout="constrained") + ax1.plot(thresholds, 100 * np.array(results), ".-") + ax1.set(title=name, ylabel="Error (cm)", xlabel="Threshold", xticks=thresholds) diff --git a/mne-python/source/examples/simulation/simulate_evoked_data.py b/mne-python/source/examples/simulation/simulate_evoked_data.py new file mode 100644 index 0000000000000000000000000000000000000000..447f548e7790c52e4a20fbfab458446d85ded37c --- /dev/null +++ b/mne-python/source/examples/simulation/simulate_evoked_data.py @@ -0,0 +1,93 @@ +""" +.. _ex-sim-evoked: + +============================== +Generate simulated evoked data +============================== + +Use :func:`~mne.simulation.simulate_sparse_stc` to simulate evoked data. +""" +# Author: Daniel Strohmeier +# Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.datasets import sample +from mne.simulation import simulate_evoked, simulate_sparse_stc +from mne.time_frequency import fit_iir_model_raw +from mne.viz import plot_sparse_source_estimates + +print(__doc__) + +# %% +# Load real data as templates +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw = mne.io.read_raw_fif(meg_path / "sample_audvis_raw.fif") +proj = mne.read_proj(meg_path / "sample_audvis_ecg-proj.fif") +raw.add_proj(proj) +raw.info["bads"] = ["MEG 2443", "EEG 053"] # mark bad channels + +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +ave_fname = meg_path / "sample_audvis-no-filter-ave.fif" +cov_fname = meg_path / "sample_audvis-cov.fif" + +fwd = mne.read_forward_solution(fwd_fname) +fwd = mne.pick_types_forward(fwd, meg=True, eeg=True, exclude=raw.info["bads"]) +cov = mne.read_cov(cov_fname) +info = mne.io.read_info(ave_fname) + +label_names = ["Aud-lh", "Aud-rh"] +labels = [mne.read_label(meg_path / "labels" / f"{ln}.label") for ln in label_names] + +# %% +# Generate source time courses from 2 dipoles and the corresponding evoked data + +times = np.arange(300, dtype=np.float64) / raw.info["sfreq"] - 0.1 +rng = np.random.RandomState(42) + + +def data_fun(times): + """Generate random source time courses.""" + return ( + 50e-9 + * np.sin(30.0 * times) + * np.exp(-((times - 0.15 + 0.05 * rng.randn(1)) ** 2) / 0.01) + ) + + +stc = simulate_sparse_stc( + fwd["src"], + n_dipoles=2, + times=times, + random_state=42, + labels=labels, + data_fun=data_fun, +) + +# %% +# Generate noisy evoked data +picks = mne.pick_types(raw.info, meg=True, exclude="bads") +iir_filter = fit_iir_model_raw(raw, order=5, picks=picks, tmin=60, tmax=180)[1] +nave = 100 # simulate average of 100 epochs +evoked = simulate_evoked( + fwd, stc, info, cov, nave=nave, use_cps=True, iir_filter=iir_filter +) + +# %% +# Plot +plot_sparse_source_estimates( + fwd["src"], stc, bgcolor=(1, 1, 1), opacity=0.5, high_resolution=True +) + +plt.figure() +plt.psd(evoked.data[0]) + +evoked.plot(time_unit="s") diff --git a/mne-python/source/examples/simulation/simulate_raw_data.py b/mne-python/source/examples/simulation/simulate_raw_data.py new file mode 100644 index 0000000000000000000000000000000000000000..0fbefca4480946420ab6816c9eba087319d71df0 --- /dev/null +++ b/mne-python/source/examples/simulation/simulate_raw_data.py @@ -0,0 +1,95 @@ +""" +.. _ex-sim-raw: + +=========================== +Generate simulated raw data +=========================== + +This example generates raw data by repeating a desired source activation +multiple times. +""" +# Authors: Yousra Bekhti +# Mark Wronkiewicz +# Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne import Epochs, compute_covariance, find_events, make_ad_hoc_cov +from mne.datasets import sample +from mne.simulation import ( + add_ecg, + add_eog, + add_noise, + simulate_raw, + simulate_sparse_stc, +) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_raw.fif" +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" + +# Load real data as the template +raw = mne.io.read_raw_fif(raw_fname) +raw.set_eeg_reference(projection=True) + +############################################################################## +# Generate dipole time series +n_dipoles = 4 # number of dipoles to create +epoch_duration = 2.0 # duration of each epoch/event +n = 0 # harmonic number +rng = np.random.RandomState(0) # random state (make reproducible) + + +def data_fun(times): + """Generate time-staggered sinusoids at harmonics of 10Hz.""" + global n + n_samp = len(times) + window = np.zeros(n_samp) + start, stop = ( + int(ii * float(n_samp) / (2 * n_dipoles)) for ii in (2 * n, 2 * n + 1) + ) + window[start:stop] = 1.0 + n += 1 + data = 25e-9 * np.sin(2.0 * np.pi * 10.0 * n * times) + data *= window + return data + + +times = raw.times[: int(raw.info["sfreq"] * epoch_duration)] +fwd = mne.read_forward_solution(fwd_fname) +src = fwd["src"] +stc = simulate_sparse_stc( + src, n_dipoles=n_dipoles, times=times, data_fun=data_fun, random_state=rng +) +# look at our source data +fig, ax = plt.subplots(1) +ax.plot(times, 1e9 * stc.data.T) +ax.set(ylabel="Amplitude (nAm)", xlabel="Time (s)") +mne.viz.utils.plt_show() + +############################################################################## +# Simulate raw data +raw_sim = simulate_raw(raw.info, [stc] * 10, forward=fwd, verbose=True) +cov = make_ad_hoc_cov(raw_sim.info) +add_noise(raw_sim, cov, iir_filter=[0.2, -0.2, 0.04], random_state=rng) +add_ecg(raw_sim, random_state=rng) +add_eog(raw_sim, random_state=rng) +raw_sim.plot() + +############################################################################## +# Plot evoked data +events = find_events(raw_sim) # only 1 pos, so event number == 1 +epochs = Epochs(raw_sim, events, 1, tmin=-0.2, tmax=epoch_duration) +cov = compute_covariance( + epochs, tmax=0.0, method="empirical", verbose="error" +) # quick calc +evoked = epochs.average() +evoked.plot_white(cov, time_unit="s") diff --git a/mne-python/source/examples/simulation/simulated_raw_data_using_subject_anatomy.py b/mne-python/source/examples/simulation/simulated_raw_data_using_subject_anatomy.py new file mode 100644 index 0000000000000000000000000000000000000000..ce6803e2ebe73768285287006a8e5002852b0c12 --- /dev/null +++ b/mne-python/source/examples/simulation/simulated_raw_data_using_subject_anatomy.py @@ -0,0 +1,249 @@ +""" +.. _ex-sim-raw-sub: + +======================================= +Simulate raw data using subject anatomy +======================================= + +This example illustrates how to generate source estimates and simulate raw data +using subject anatomy with the :class:`mne.simulation.SourceSimulator` class. +Once the raw data is simulated, generated source estimates are reconstructed +using dynamic statistical parametric mapping (dSPM) inverse operator. +""" + +# Author: Ivana Kojcic +# Eric Larson +# Kostiantyn Maksymenko +# Samuel Deslauriers-Gauthier + +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.datasets import sample + +# %% +# In this example, raw data will be simulated for the sample subject, so its +# information needs to be loaded. This step will download the data if it not +# already on your machine. Subjects directory is also set so it doesn't need +# to be given to functions. + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +subject = "sample" +meg_path = data_path / "MEG" / subject + +# %% +# First, we get an info structure from the sample subject. + +fname_info = meg_path / "sample_audvis_raw.fif" +info = mne.io.read_info(fname_info) +tstep = 1 / info["sfreq"] + +# %% +# To simulate sources, we also need a source space. It can be obtained from the +# forward solution of the sample subject. + +fwd_fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +fwd = mne.read_forward_solution(fwd_fname) +src = fwd["src"] + +# %% +# To simulate raw data, we need to define when the activity occurs using events +# matrix and specify the IDs of each event. +# Noise covariance matrix also needs to be defined. +# Here, both are loaded from the sample dataset, but they can also be specified +# by the user. + +fname_event = meg_path / "sample_audvis_raw-eve.fif" +fname_cov = meg_path / "sample_audvis-cov.fif" + +events = mne.read_events(fname_event) +noise_cov = mne.read_cov(fname_cov) + +# Standard sample event IDs. These values will correspond to the third column +# in the events matrix. +event_id = { + "auditory/left": 1, + "auditory/right": 2, + "visual/left": 3, + "visual/right": 4, + "smiley": 5, + "button": 32, +} + + +# Take only a few events for speed +events = events[:80] + +# %% +# In order to simulate source time courses, labels of desired active regions +# need to be specified for each of the 4 simulation conditions. +# Make a dictionary that maps conditions to activation strengths within +# aparc.a2009s :footcite:`DestrieuxEtAl2010` labels. +# In the aparc.a2009s parcellation: +# +# - 'G_temp_sup-G_T_transv' is the label for primary auditory area +# - 'S_calcarine' is the label for primary visual area +# +# In each of the 4 conditions, only the primary area is activated. This means +# that during the activations of auditory areas, there are no activations in +# visual areas and vice versa. +# Moreover, for each condition, contralateral region is more active (here, 2 +# times more) than the ipsilateral. + +activations = { + "auditory/left": [ + ("G_temp_sup-G_T_transv-lh", 30), # label, activation (nAm) + ("G_temp_sup-G_T_transv-rh", 60), + ], + "auditory/right": [ + ("G_temp_sup-G_T_transv-lh", 60), + ("G_temp_sup-G_T_transv-rh", 30), + ], + "visual/left": [("S_calcarine-lh", 30), ("S_calcarine-rh", 60)], + "visual/right": [("S_calcarine-lh", 60), ("S_calcarine-rh", 30)], +} + +annot = "aparc.a2009s" + +# Load the 4 necessary label names. +label_names = sorted( + set( + activation[0] + for activation_list in activations.values() + for activation in activation_list + ) +) +region_names = list(activations.keys()) + +# %% +# Create simulated source activity +# -------------------------------- +# +# Generate source time courses for each region. In this example, we want to +# simulate source activity for a single condition at a time. Therefore, each +# evoked response will be parametrized by latency and duration. + + +def data_fun(times, latency, duration): + """Generate source time courses for evoked responses.""" + f = 15 # oscillating frequency, beta band [Hz] + sigma = 0.375 * duration + sinusoid = np.sin(2 * np.pi * f * (times - latency)) + gf = np.exp( + -((times - latency - (sigma / 4.0) * rng.rand(1)) ** 2) / (2 * (sigma**2)) + ) + return 1e-9 * sinusoid * gf + + +# %% +# Here, :class:`~mne.simulation.SourceSimulator` is used, which allows to +# specify where (label), what (source_time_series), and when (events) event +# type will occur. +# +# We will add data for 4 areas, each of which contains 2 labels. Since add_data +# method accepts 1 label per call, it will be called 2 times per area. +# +# Evoked responses are generated such that the main component peaks at 100ms +# with a duration of around 30ms, which first appears in the contralateral +# cortex. This is followed by a response in the ipsilateral cortex with a peak +# about 15ms after. The amplitude of the activations will be 2 times higher in +# the contralateral region, as explained before. +# +# When the activity occurs is defined using events. In this case, they are +# taken from the original raw data. The first column is the sample of the +# event, the second is not used. The third one is the event id, which is +# different for each of the 4 areas. + +times = np.arange(150, dtype=np.float64) / info["sfreq"] +duration = 0.03 +rng = np.random.RandomState(7) +source_simulator = mne.simulation.SourceSimulator(src, tstep=tstep) + +for region_id, region_name in enumerate(region_names, 1): + events_tmp = events[np.where(events[:, 2] == region_id)[0], :] + for i in range(2): + label_name = activations[region_name][i][0] + label_tmp = mne.read_labels_from_annot( + subject, annot, subjects_dir=subjects_dir, regexp=label_name, verbose=False + ) + label_tmp = label_tmp[0] + amplitude_tmp = activations[region_name][i][1] + if region_name.split("/")[1][0] == label_tmp.hemi[0]: + latency_tmp = 0.115 + else: + latency_tmp = 0.1 + wf_tmp = data_fun(times, latency_tmp, duration) + source_simulator.add_data(label_tmp, amplitude_tmp * wf_tmp, events_tmp) + +# To obtain a SourceEstimate object, we need to use `get_stc()` method of +# SourceSimulator class. +stc_data = source_simulator.get_stc() + +# %% +# Simulate raw data +# ----------------- +# +# Project the source time series to sensor space. Three types of noise will be +# added to the simulated raw data: +# +# - multivariate Gaussian noise obtained from the noise covariance from the +# sample data +# - blink (EOG) noise +# - ECG noise +# +# The :class:`~mne.simulation.SourceSimulator` can be given directly to the +# :func:`~mne.simulation.simulate_raw` function. + +raw_sim = mne.simulation.simulate_raw(info, source_simulator, forward=fwd) +raw_sim.set_eeg_reference(projection=True) + +mne.simulation.add_noise(raw_sim, cov=noise_cov, random_state=0) +mne.simulation.add_eog(raw_sim, random_state=0) +mne.simulation.add_ecg(raw_sim, random_state=0) + +# Plot original and simulated raw data. +raw_sim.plot(title="Simulated raw data") + +# %% +# Extract epochs and compute evoked responsses +# -------------------------------------------- +# + +epochs = mne.Epochs(raw_sim, events, event_id, tmin=-0.2, tmax=0.3, baseline=(None, 0)) +evoked_aud_left = epochs["auditory/left"].average() +evoked_vis_right = epochs["visual/right"].average() + +# Visualize the evoked data +evoked_aud_left.plot(spatial_colors=True) +evoked_vis_right.plot(spatial_colors=True) + +# %% +# Reconstruct simulated source time courses using dSPM inverse operator +# --------------------------------------------------------------------- +# +# Here, source time courses for auditory and visual areas are reconstructed +# separately and their difference is shown. This was done merely for better +# visual representation of source reconstruction. +# As expected, when high activations appear in primary auditory areas, primary +# visual areas will have low activations and vice versa. + +method, lambda2 = "dSPM", 1.0 / 9.0 +inv = mne.minimum_norm.make_inverse_operator(epochs.info, fwd, noise_cov) +stc_aud = mne.minimum_norm.apply_inverse(evoked_aud_left, inv, lambda2, method) +stc_vis = mne.minimum_norm.apply_inverse(evoked_vis_right, inv, lambda2, method) +stc_diff = stc_aud - stc_vis + +brain = stc_diff.plot( + subjects_dir=subjects_dir, initial_time=0.1, hemi="split", views=["lat", "med"] +) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/simulation/source_simulator.py b/mne-python/source/examples/simulation/source_simulator.py new file mode 100644 index 0000000000000000000000000000000000000000..f417b96f181f25e7ae02e0b900360bca01aa33b2 --- /dev/null +++ b/mne-python/source/examples/simulation/source_simulator.py @@ -0,0 +1,96 @@ +""" +.. _ex-sim-source: + +============================== +Generate simulated source data +============================== + +This example illustrates how to use the :class:`mne.simulation.SourceSimulator` +class to generate source estimates and raw data. It is meant to be a brief +introduction and only highlights the simplest use case. + +""" +# Author: Kostiantyn Maksymenko +# Samuel Deslauriers-Gauthier +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne.datasets import sample + +print(__doc__) + +# %% +# For this example, we will be using the information of the sample subject. +# This will download the data if it not already on your machine. We also set +# the subjects directory so we don't need to give it to functions. +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +subject = "sample" + +# %% +# First, we get an info structure from the test subject. +evoked_fname = data_path / "MEG" / subject / "sample_audvis-ave.fif" +info = mne.io.read_info(evoked_fname) +tstep = 1.0 / info["sfreq"] + +# %% +# To simulate sources, we also need a source space. It can be obtained from the +# forward solution of the sample subject. +fwd_fname = data_path / "MEG" / subject / "sample_audvis-meg-eeg-oct-6-fwd.fif" +fwd = mne.read_forward_solution(fwd_fname) +src = fwd["src"] + +# %% +# To select a region to activate, we use the caudal middle frontal to grow +# a region of interest. +selected_label = mne.read_labels_from_annot( + subject, regexp="caudalmiddlefrontal-lh", subjects_dir=subjects_dir +)[0] +location = "center" # Use the center of the region as a seed. +extent = 10.0 # Extent in mm of the region. +label = mne.label.select_sources( + subject, selected_label, location=location, extent=extent, subjects_dir=subjects_dir +) + +# %% +# Define the time course of the activity for each source of the region to +# activate. Here we use a sine wave at 18 Hz with a peak amplitude +# of 10 nAm. +source_time_series = np.sin(2.0 * np.pi * 18.0 * np.arange(100) * tstep) * 10e-9 + +# %% +# Define when the activity occurs using events. The first column is the sample +# of the event, the second is not used, and the third is the event id. Here the +# events occur every 200 samples. +n_events = 50 +events = np.zeros((n_events, 3), int) +events[:, 0] = 100 + 200 * np.arange(n_events) # Events sample. +events[:, 2] = 1 # All events have the sample id. + +# %% +# Create simulated source activity. Here we use a SourceSimulator whose +# add_data method is key. It specified where (label), what +# (source_time_series), and when (events) an event type will occur. +source_simulator = mne.simulation.SourceSimulator(src, tstep=tstep) +source_simulator.add_data(label, source_time_series, events) + +# %% +# Project the source time series to sensor space and add some noise. The source +# simulator can be given directly to the simulate_raw function. +raw = mne.simulation.simulate_raw(info, source_simulator, forward=fwd) +cov = mne.make_ad_hoc_cov(raw.info) +mne.simulation.add_noise(raw, cov, iir_filter=[0.2, -0.2, 0.04]) +raw.plot() + +# %% +# Plot evoked data to get another view of the simulated raw data. +events = mne.find_events(raw) +epochs = mne.Epochs(raw, events, 1, tmin=-0.05, tmax=0.2) +evoked = epochs.average() +evoked.plot() diff --git a/mne-python/source/examples/stats/README.txt b/mne-python/source/examples/stats/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..b395d8f941b83603044cc1cec144c409cec4e071 --- /dev/null +++ b/mne-python/source/examples/stats/README.txt @@ -0,0 +1,6 @@ + +Statistics Examples +------------------- + +Some examples of how to compute statistics on M/EEG data with MNE. + diff --git a/mne-python/source/examples/stats/cluster_stats_evoked.py b/mne-python/source/examples/stats/cluster_stats_evoked.py new file mode 100644 index 0000000000000000000000000000000000000000..b51601f2f32f4640dee1d24b7e1bbb5f2f077a33 --- /dev/null +++ b/mne-python/source/examples/stats/cluster_stats_evoked.py @@ -0,0 +1,99 @@ +""" +.. _ex-cluster-evoked: + +======================================================= +Permutation F-test on sensor data with 1D cluster level +======================================================= + +One tests if the evoked response is significantly different +between conditions. Multiple comparison problem is addressed +with cluster level permutation test. + +""" +# Authors: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne import io +from mne.datasets import sample +from mne.stats import permutation_cluster_test + +print(__doc__) + +# %% +# Set parameters +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +tmin = -0.2 +tmax = 0.5 + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname) +events = mne.read_events(event_fname) + +channel = "MEG 1332" # include only this channel in analysis +include = [channel] + +# %% +# Read epochs for the channel of interest +picks = mne.pick_types(raw.info, meg=False, eog=True, include=include, exclude="bads") +event_id = 1 +reject = dict(grad=4000e-13, eog=150e-6) +epochs1 = mne.Epochs( + raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), reject=reject +) +condition1 = epochs1.get_data() # as 3D matrix + +event_id = 2 +epochs2 = mne.Epochs( + raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), reject=reject +) +condition2 = epochs2.get_data() # as 3D matrix + +condition1 = condition1[:, 0, :] # take only one channel to get a 2D array +condition2 = condition2[:, 0, :] # take only one channel to get a 2D array + +# %% +# Compute statistic +threshold = 6.0 +T_obs, clusters, cluster_p_values, H0 = permutation_cluster_test( + [condition1, condition2], + n_permutations=1000, + threshold=threshold, + tail=1, + n_jobs=None, + out_type="mask", +) + +# %% +# Plot +times = epochs1.times +fig, (ax, ax2) = plt.subplots(2, 1, figsize=(8, 4)) +ax.set_title("Channel : " + channel) +ax.plot( + times, + condition1.mean(axis=0) - condition2.mean(axis=0), + label="ERF Contrast (Event 1 - Event 2)", +) +ax.set_ylabel("MEG (T / m)") +ax.legend() + +for i_c, c in enumerate(clusters): + c = c[0] + if cluster_p_values[i_c] <= 0.05: + h = ax2.axvspan(times[c.start], times[c.stop - 1], color="r", alpha=0.3) + else: + ax2.axvspan(times[c.start], times[c.stop - 1], color=(0.3, 0.3, 0.3), alpha=0.3) + +hf = plt.plot(times, T_obs, "g") +ax2.legend((h,), ("cluster p-value < 0.05",)) +ax2.set_xlabel("time (ms)") +ax2.set_ylabel("f-values") diff --git a/mne-python/source/examples/stats/fdr_stats_evoked.py b/mne-python/source/examples/stats/fdr_stats_evoked.py new file mode 100644 index 0000000000000000000000000000000000000000..f7b78f7c5597b7864317dc0832dce76f5164010e --- /dev/null +++ b/mne-python/source/examples/stats/fdr_stats_evoked.py @@ -0,0 +1,108 @@ +""" +.. _ex-fdr-evoked: + +======================================= +FDR correction on T-test on sensor data +======================================= + +One tests if the evoked response significantly deviates from 0. +Multiple comparison problem is addressed with +False Discovery Rate (FDR) correction. + +""" +# Authors: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from scipy import stats + +import mne +from mne import io +from mne.datasets import sample +from mne.stats import bonferroni_correction, fdr_correction + +print(__doc__) + +# %% +# Set parameters +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +event_id, tmin, tmax = 1, -0.2, 0.5 + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname) +events = mne.read_events(event_fname)[:30] + +channel = "MEG 1332" # include only this channel in analysis +include = [channel] + +# %% +# Read epochs for the channel of interest +picks = mne.pick_types(raw.info, meg=False, eog=True, include=include, exclude="bads") +event_id = 1 +reject = dict(grad=4000e-13, eog=150e-6) +epochs = mne.Epochs( + raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), reject=reject +) +X = epochs.get_data() # as 3D matrix +X = X[:, 0, :] # take only one channel to get a 2D array + +# %% +# Compute statistic +T, pval = stats.ttest_1samp(X, 0) +alpha = 0.05 + +n_samples, n_tests = X.shape +threshold_uncorrected = stats.t.ppf(1.0 - alpha, n_samples - 1) + +reject_bonferroni, pval_bonferroni = bonferroni_correction(pval, alpha=alpha) +threshold_bonferroni = stats.t.ppf(1.0 - alpha / n_tests, n_samples - 1) + +reject_fdr, pval_fdr = fdr_correction(pval, alpha=alpha, method="indep") +threshold_fdr = np.min(np.abs(T)[reject_fdr]) + +# %% +# Plot +times = 1e3 * epochs.times + +plt.close("all") +plt.plot(times, T, "k", label="T-stat") +xmin, xmax = plt.xlim() +plt.hlines( + threshold_uncorrected, + xmin, + xmax, + linestyle="--", + colors="k", + label="p=0.05 (uncorrected)", + linewidth=2, +) +plt.hlines( + threshold_bonferroni, + xmin, + xmax, + linestyle="--", + colors="r", + label="p=0.05 (Bonferroni)", + linewidth=2, +) +plt.hlines( + threshold_fdr, + xmin, + xmax, + linestyle="--", + colors="b", + label="p=0.05 (FDR)", + linewidth=2, +) +plt.legend() +plt.xlabel("Time (ms)") +plt.ylabel("T-stat") +plt.show() diff --git a/mne-python/source/examples/stats/linear_regression_raw.py b/mne-python/source/examples/stats/linear_regression_raw.py new file mode 100644 index 0000000000000000000000000000000000000000..5c09e5a9443b833a2f72b4d193e5792182cc1b78 --- /dev/null +++ b/mne-python/source/examples/stats/linear_regression_raw.py @@ -0,0 +1,82 @@ +""" +.. _ex-linear-regression-raw: + +======================================== +Regression on continuous data (rER[P/F]) +======================================== + +This demonstrates how rER[P/F]s - regressing the continuous data - is a +generalisation of traditional averaging. If all preprocessing steps +are the same, no overlap between epochs exists, and if all +predictors are binary, regression is virtually identical to traditional +averaging. +If overlap exists and/or predictors are continuous, traditional averaging +is inapplicable, but regression can estimate effects, including those of +continuous predictors. + +rERPs are described in :footcite:t:`SmithKutas2015`. +""" # noqa D400 +# Authors: Jona Sassenhagen +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne.datasets import sample +from mne.stats.regression import linear_regression_raw + +# Load and preprocess data +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +raw = mne.io.read_raw_fif(raw_fname) +raw.pick(["grad", "stim"], exclude="bads").load_data() +raw.filter(1, None, fir_design="firwin") # high-pass + +# Set up events +events = mne.find_events(raw) +event_id = {"Aud/L": 1, "Aud/R": 2} +tmin, tmax = -0.1, 0.5 + +# regular epoching +picks = mne.pick_types(raw.info, meg=True) +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + reject=None, + baseline=None, + preload=True, + verbose=False, +) + +# rERF +evokeds = linear_regression_raw( + raw, events=events, event_id=event_id, reject=None, tmin=tmin, tmax=tmax +) +# linear_regression_raw returns a dict of evokeds +# select conditions similarly to mne.Epochs objects + +# plot both results, and their difference +cond = "Aud/L" +fig, (ax1, ax2, ax3) = plt.subplots(3, 1) +params = dict( + spatial_colors=True, show=False, ylim=dict(grad=(-200, 200)), time_unit="s" +) +epochs[cond].average().plot(axes=ax1, **params) +evokeds[cond].plot(axes=ax2, **params) +contrast = mne.combine_evoked([evokeds[cond], epochs[cond].average()], weights=[1, -1]) +contrast.plot(axes=ax3, **params) +ax1.set_title("Traditional averaging") +ax2.set_title("rERF") +ax3.set_title("Difference") +plt.show() + +# %% +# .. footbibliography:: diff --git a/mne-python/source/examples/stats/sensor_permutation_test.py b/mne-python/source/examples/stats/sensor_permutation_test.py new file mode 100644 index 0000000000000000000000000000000000000000..ded8cb9c314ba6268d7a7ddb0d6bfb084cee807b --- /dev/null +++ b/mne-python/source/examples/stats/sensor_permutation_test.py @@ -0,0 +1,93 @@ +""" +.. _ex-perm-test: + +================================= +Permutation T-test on sensor data +================================= + +One tests if the signal significantly deviates from 0 +during a fixed time window of interest. Here computation +is performed on MNE sample dataset between 40 and 60 ms. + +""" +# Authors: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne import io +from mne.datasets import sample +from mne.stats import permutation_t_test + +print(__doc__) + +# %% +# Set parameters +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +event_id = 1 +tmin = -0.2 +tmax = 0.5 + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname) +events = mne.read_events(event_fname) + +# pick MEG Gradiometers +picks = mne.pick_types( + raw.info, meg="grad", eeg=False, stim=False, eog=True, exclude="bads" +) +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + reject=dict(grad=4000e-13, eog=150e-6), +) +data = epochs.get_data() +times = epochs.times + +temporal_mask = np.logical_and(0.04 <= times, times <= 0.06) +data = np.mean(data[:, :, temporal_mask], axis=2) + +n_permutations = 50000 +T0, p_values, H0 = permutation_t_test(data, n_permutations, n_jobs=None) + +significant_sensors = picks[p_values <= 0.05] +significant_sensors_names = [raw.ch_names[k] for k in significant_sensors] + +print(f"Number of significant sensors : {len(significant_sensors)}") +print(f"Sensors names : {significant_sensors_names}") + +# %% +# View location of significantly active sensors + +evoked = mne.EvokedArray(-np.log10(p_values)[:, np.newaxis], epochs.info, tmin=0.0) + +# Extract mask and indices of active sensors in the layout +mask = p_values[:, np.newaxis] <= 0.05 + +evoked.plot_topomap( + ch_type="grad", + times=[0], + scalings=1, + time_format=None, + cmap="Reds", + vlim=(0.0, np.max), + units="-log10(p)", + cbar_fmt="-%0.1f", + mask=mask, + size=3, + show_names=lambda x: x[4:] + " " * 20, + time_unit="s", +) diff --git a/mne-python/source/examples/stats/sensor_regression.py b/mne-python/source/examples/stats/sensor_regression.py new file mode 100644 index 0000000000000000000000000000000000000000..e3f1452badb850aa822997b5c1abe0bbc53f047b --- /dev/null +++ b/mne-python/source/examples/stats/sensor_regression.py @@ -0,0 +1,89 @@ +""" +.. _ex-sensor-regression: + +========================================================================= +Analysing continuous features with binning and regression in sensor space +========================================================================= + +Predict single trial activity from a continuous variable. +A single-trial regression is performed in each sensor and timepoint +individually, resulting in an :class:`mne.Evoked` object which contains the +regression coefficient (beta value) for each combination of sensor and +timepoint. This example shows the regression coefficient; the t and p values +are also calculated automatically. + +Here, we repeat a few of the analyses from :footcite:`DufauEtAl2015`. This +can be easily performed by accessing the metadata object, which contains +word-level information about various psycholinguistically relevant features +of the words for which we have EEG activity. + +For the general methodology, see e.g. :footcite:`HaukEtAl2006`. +""" +# Authors: Tal Linzen +# Denis A. Engemann +# Jona Sassenhagen +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import pandas as pd + +import mne +from mne.datasets import kiloword +from mne.stats import fdr_correction, linear_regression +from mne.viz import plot_compare_evokeds + +# Load the data +path = kiloword.data_path() / "kword_metadata-epo.fif" +epochs = mne.read_epochs(path) +print(epochs.metadata.head()) + +# %% +# Psycholinguistically relevant word characteristics are continuous. I.e., +# concreteness or imaginability is a graded property. In the metadata, +# we have concreteness ratings on a 5-point scale. We can show the dependence +# of the EEG on concreteness by dividing the data into bins and plotting the +# mean activity per bin, color coded. +name = "Concreteness" +df = epochs.metadata +df[name] = pd.cut(df[name], 11, labels=False) / 10 +colors = {str(val): val for val in df[name].unique()} +epochs.metadata = df.assign(Intercept=1) # Add an intercept for later +evokeds = {val: epochs[name + " == " + val].average() for val in colors} +plot_compare_evokeds( + evokeds, colors=colors, split_legend=True, cmap=(name + " Percentile", "viridis") +) + +# %% +# We observe that there appears to be a monotonic dependence of EEG on +# concreteness. We can also conduct a continuous analysis: single-trial level +# regression with concreteness as a continuous (although here, binned) +# feature. We can plot the resulting regression coefficient just like an +# Event-related Potential. +names = ["Intercept", name] +res = linear_regression(epochs, epochs.metadata[names], names=names) +for cond in names: + res[cond].beta.plot_joint( + title=cond, ts_args=dict(time_unit="s"), topomap_args=dict(time_unit="s") + ) + +# %% +# Because the :func:`~mne.stats.linear_regression` function also estimates +# p values, we can -- +# after applying FDR correction for multiple comparisons -- also visualise the +# statistical significance of the regression of word concreteness. +# The :func:`mne.viz.plot_evoked_image` function takes a ``mask`` parameter. +# If we supply it with a boolean mask of the positions where we can reject +# the null hypothesis, points that are not significant will be shown +# transparently, and if desired, in a different colour palette and surrounded +# by dark contour lines. +reject_H0, fdr_pvals = fdr_correction(res["Concreteness"].p_val.data) +evoked = res["Concreteness"].beta +evoked.plot_image(mask=reject_H0, time_unit="s") + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/time_frequency/README.txt b/mne-python/source/examples/time_frequency/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..c6b0ab6be49d3728c9f536bca3a9166094397f8a --- /dev/null +++ b/mne-python/source/examples/time_frequency/README.txt @@ -0,0 +1,5 @@ + +Time-Frequency Examples +----------------------- + +Some examples of how to explore time-frequency content of M/EEG data with MNE. diff --git a/mne-python/source/examples/time_frequency/compute_csd.py b/mne-python/source/examples/time_frequency/compute_csd.py new file mode 100644 index 0000000000000000000000000000000000000000..7d46770c14cc33b1a9131dbae330cbde1c28b394 --- /dev/null +++ b/mne-python/source/examples/time_frequency/compute_csd.py @@ -0,0 +1,104 @@ +""" +.. _ex-csd-matrix: + +============================================= +Compute a cross-spectral density (CSD) matrix +============================================= + +A cross-spectral density (CSD) matrix is similar to a covariance matrix, but in +the time-frequency domain. It is the first step towards computing +sensor-to-sensor coherence or a DICS beamformer. + +This script demonstrates the three methods that MNE-Python provides to compute +the CSD: + +1. Using short-term Fourier transform: :func:`mne.time_frequency.csd_fourier` +2. Using a multitaper approach: :func:`mne.time_frequency.csd_multitaper` +3. Using Morlet wavelets: :func:`mne.time_frequency.csd_morlet` +""" +# Author: Marijn van Vliet +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +import mne +from mne.datasets import sample +from mne.time_frequency import csd_fourier, csd_morlet, csd_multitaper + +print(__doc__) + +# %% +# In the following example, the computation of the CSD matrices can be +# performed using multiple cores. Set ``n_jobs`` to a value >1 to select the +# number of cores to use. +n_jobs = 1 + +# %% +# Loading the sample dataset. +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fname_raw = meg_path / "sample_audvis_raw.fif" +fname_event = meg_path / "sample_audvis_raw-eve.fif" +raw = mne.io.read_raw_fif(fname_raw) +events = mne.read_events(fname_event) + +# %% +# By default, CSD matrices are computed using all MEG/EEG channels. When +# interpreting a CSD matrix with mixed sensor types, be aware that the +# measurement units, and thus the scalings, differ across sensors. In this +# example, for speed and clarity, we select a single channel type: +# gradiometers. +picks = mne.pick_types(raw.info, meg="grad") + +# Make some epochs, based on events with trigger code 1 +epochs = mne.Epochs( + raw, + events, + event_id=1, + tmin=-0.2, + tmax=1, + picks=picks, + baseline=(None, 0), + reject=dict(grad=4000e-13), + preload=True, +) + +# %% +# Computing CSD matrices using short-term Fourier transform and (adaptive) +# multitapers is straightforward: +csd_fft = csd_fourier(epochs, fmin=15, fmax=20, n_jobs=n_jobs) +csd_mt = csd_multitaper(epochs, fmin=15, fmax=20, adaptive=True, n_jobs=n_jobs) + +# %% +# When computing the CSD with Morlet wavelets, you specify the exact +# frequencies at which to compute it. For each frequency, a corresponding +# wavelet will be constructed and convolved with the signal, resulting in a +# time-frequency decomposition. +# +# The CSD is constructed by computing the correlation between the +# time-frequency representations between all sensor-to-sensor pairs. The +# time-frequency decomposition originally has the same sampling rate as the +# signal, in our case ~600Hz. This means the decomposition is over-specified in +# time and we may not need to use all samples during our CSD computation, just +# enough to get a reliable correlation statistic. By specifying ``decim=10``, +# we use every 10th sample, which will greatly speed up the computation and +# will have a minimal effect on the CSD. +frequencies = [16, 17, 18, 19, 20] +csd_wav = csd_morlet(epochs, frequencies, decim=10, n_jobs=n_jobs) + +# %% +# The resulting :class:`mne.time_frequency.CrossSpectralDensity` objects have a +# plotting function we can use to compare the results of the different methods. +# We're plotting the mean CSD across frequencies. +# :func:`mne.time_frequency.CrossSpectralDensity.plot()` returns a list of +# created figures; in this case, each returned list has only one figure +# so we use a Python trick of including a comma after our variable name +# to assign the figure (not the list) to our ``fig`` variable: +plot_dict = { + "Short-time Fourier transform": csd_fft, + "Adaptive multitapers": csd_mt, + "Morlet wavelet transform": csd_wav, +} +for title, csd in plot_dict.items(): + (fig,) = csd.mean().plot() + fig.suptitle(title) diff --git a/mne-python/source/examples/time_frequency/compute_source_psd_epochs.py b/mne-python/source/examples/time_frequency/compute_source_psd_epochs.py new file mode 100644 index 0000000000000000000000000000000000000000..21901e82eaa4b446ca3db7b9112545e7bb721fe2 --- /dev/null +++ b/mne-python/source/examples/time_frequency/compute_source_psd_epochs.py @@ -0,0 +1,121 @@ +""" +.. _ex-psd-inverse: + +===================================================================== +Compute Power Spectral Density of inverse solution from single epochs +===================================================================== + +Compute PSD of dSPM inverse solution on single trial epochs restricted +to a brain label. The PSD is computed using a multi-taper method with +Discrete Prolate Spheroidal Sequence (DPSS) windows. +""" +# Author: Martin Luessi +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne.datasets import sample +from mne.minimum_norm import compute_source_psd_epochs, read_inverse_operator + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +fname_inv = meg_path / "sample_audvis-meg-oct-6-meg-inv.fif" +fname_raw = meg_path / "sample_audvis_raw.fif" +fname_event = meg_path / "sample_audvis_raw-eve.fif" +label_name = "Aud-lh" +fname_label = meg_path / "labels" / f"{label_name}.label" +subjects_dir = data_path / "subjects" + +event_id, tmin, tmax = 1, -0.2, 0.5 +snr = 1.0 # use smaller SNR for raw data +lambda2 = 1.0 / snr**2 +method = "dSPM" # use dSPM method (could also be MNE or sLORETA) + +# Load data +inverse_operator = read_inverse_operator(fname_inv) +label = mne.read_label(fname_label) +raw = mne.io.read_raw_fif(fname_raw) +events = mne.read_events(fname_event) + +# Set up pick list +include = [] +raw.info["bads"] += ["EEG 053"] # bads + 1 more + +# pick MEG channels +picks = mne.pick_types( + raw.info, meg=True, eeg=False, stim=False, eog=True, include=include, exclude="bads" +) +# Read epochs +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + reject=dict(mag=4e-12, grad=4000e-13, eog=150e-6), +) + +# define frequencies of interest +fmin, fmax = 0.0, 70.0 +bandwidth = 4.0 # bandwidth of the windows in Hz + +# %% +# Compute source space PSD in label +# --------------------------------- +# +# .. note:: By using "return_generator=True" stcs will be a generator object +# instead of a list. This allows us so to iterate without having to +# keep everything in memory. + +n_epochs_use = 10 +stcs = compute_source_psd_epochs( + epochs[:n_epochs_use], + inverse_operator, + lambda2=lambda2, + method=method, + fmin=fmin, + fmax=fmax, + bandwidth=bandwidth, + label=label, + return_generator=True, + verbose=True, +) + +# compute average PSD over the first 10 epochs +psd_avg = 0.0 +for i, stc in enumerate(stcs): + psd_avg += stc.data +psd_avg /= n_epochs_use +freqs = stc.times # the frequencies are stored here +stc.data = psd_avg # overwrite the last epoch's data with the average + +# %% +# Visualize the 10 Hz PSD: + +brain = stc.plot( + initial_time=10.0, + hemi="lh", + views="lat", # 10 HZ + clim=dict(kind="value", lims=(20, 40, 60)), + smoothing_steps=3, + subjects_dir=subjects_dir, +) +brain.add_label(label, borders=True, color="k") + +# %% +# Visualize the entire spectrum: + +fig, ax = plt.subplots() +ax.plot(freqs, psd_avg.mean(axis=0)) +ax.set_xlabel("Freq (Hz)") +ax.set_xlim(stc.times[[0, -1]]) +ax.set_ylabel("Power Spectral Density") diff --git a/mne-python/source/examples/time_frequency/source_label_time_frequency.py b/mne-python/source/examples/time_frequency/source_label_time_frequency.py new file mode 100644 index 0000000000000000000000000000000000000000..80a25fffab9c8715e23b1f9134cf30affb9535e4 --- /dev/null +++ b/mne-python/source/examples/time_frequency/source_label_time_frequency.py @@ -0,0 +1,167 @@ +""" +.. _ex-source-space-power-phase-locking: + +========================================================= +Compute power and phase lock in label of the source space +========================================================= + +Compute time-frequency maps of power and phase lock in the source space. +The inverse method is linear based on dSPM inverse operator. + +The example also shows the difference in the time-frequency maps +when they are computed with and without subtracting the evoked response +from each epoch. The former results in induced activity only while the +latter also includes evoked (stimulus-locked) activity. +""" +# Authors: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne import io +from mne.datasets import sample +from mne.minimum_norm import read_inverse_operator, source_induced_power + +print(__doc__) + +# %% +# Set parameters +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_raw.fif" +fname_inv = meg_path / "sample_audvis-meg-oct-6-meg-inv.fif" +label_names = ["Aud-lh", "Aud-rh"] +fname_labels = [meg_path / "labels" / f"{ln}.label" for ln in label_names] + +tmin, tmax, event_id = -0.2, 0.5, 2 + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname) +events = mne.find_events(raw, stim_channel="STI 014") +inverse_operator = read_inverse_operator(fname_inv) + +include = [] +raw.info["bads"] += ["MEG 2443", "EEG 053"] # bads + 2 more + +# Picks MEG channels +picks = mne.pick_types( + raw.info, meg=True, eeg=False, eog=True, stim=False, include=include, exclude="bads" +) +reject = dict(grad=4000e-13, mag=4e-12, eog=150e-6) + +# Load epochs +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + reject=reject, + preload=True, +) + +# Compute a source estimate per frequency band including and excluding the +# evoked response +freqs = np.arange(7, 30, 2) # define frequencies of interest +labels = [mne.read_label(fl) for fl in fname_labels] +label = labels[0] +n_cycles = freqs / 3.0 # different number of cycle per frequency + +# subtract the evoked response in order to exclude evoked activity +epochs_induced = epochs.copy().subtract_evoked() + +fig, axes = plt.subplots(2, 2, layout="constrained") +for ii, (this_epochs, title) in enumerate( + zip([epochs, epochs_induced], ["evoked + induced", "induced only"]) +): + # compute the source space power and the inter-trial coherence + power, itc = source_induced_power( + this_epochs, + inverse_operator, + freqs, + label, + baseline=(-0.1, 0), + baseline_mode="percent", + n_cycles=n_cycles, + n_jobs=None, + ) + + power = np.mean(power, axis=0) # average over sources + itc = np.mean(itc, axis=0) # average over sources + times = epochs.times + + ########################################################################## + # View time-frequency plots + ax = axes[ii, 0] + ax.imshow( + 20 * power, + extent=[times[0], times[-1], freqs[0], freqs[-1]], + aspect="auto", + origin="lower", + vmin=0.0, + vmax=30.0, + cmap="RdBu_r", + ) + ax.set(xlabel="Time (s)", ylabel="Frequency (Hz)", title=f"Power ({title})") + + ax = axes[ii, 1] + ax.imshow( + itc, + extent=[times[0], times[-1], freqs[0], freqs[-1]], + aspect="auto", + origin="lower", + vmin=0, + vmax=0.7, + cmap="RdBu_r", + ) + ax.set(xlabel="Time (s)", ylabel="Frequency (Hz)", title=f"ITC ({title})") + fig.colorbar(ax.images[0], ax=axes[ii]) + +# %% + +############################################################################## +# In the example above, we averaged power across vertices after calculating +# power because we provided a single label for power calculation and therefore +# power of all sources within the single label were returned separately. When +# we provide a list of labels, power is averaged across sources within each +# label automatically. With a list of labels, averaging is performed before +# rescaling, so choose a baseline method appropriately. + + +# Get power from multiple labels +multi_label_power = source_induced_power( + epochs, + inverse_operator, + freqs, + labels, + baseline=(-0.1, 0), + baseline_mode="mean", + n_cycles=n_cycles, + n_jobs=None, + return_plv=False, +) + +# visually compare evoked power in left and right auditory regions +fig, axes = plt.subplots(ncols=2, layout="constrained") +for l_idx, l_power in enumerate(multi_label_power): + ax = axes[l_idx] + ax.imshow( + l_power, + extent=[epochs.times[0], epochs.times[-1], freqs[0], freqs[-1]], + aspect="auto", + origin="lower", + vmin=multi_label_power.min(), + vmax=multi_label_power.max(), + cmap="RdBu_r", + ) + title = f"{labels[l_idx].hemi.upper()} Evoked Power" + ax.set(xlabel="Time (s)", ylabel="Frequency (Hz)", title=title) + fig.colorbar(ax.images[0], ax=ax) diff --git a/mne-python/source/examples/time_frequency/source_power_spectrum.py b/mne-python/source/examples/time_frequency/source_power_spectrum.py new file mode 100644 index 0000000000000000000000000000000000000000..77af97a87269b153e779bd838b3a65d192f1dd23 --- /dev/null +++ b/mne-python/source/examples/time_frequency/source_power_spectrum.py @@ -0,0 +1,74 @@ +""" +.. _ex-label-psd: + +====================================================== +Compute source power spectral density (PSD) in a label +====================================================== + +Returns an STC file containing the PSD (in dB) of each of the sources +within a label. +""" +# Authors: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne import io +from mne.datasets import sample +from mne.minimum_norm import compute_source_psd, read_inverse_operator + +print(__doc__) + +# %% +# Set parameters +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_raw.fif" +fname_inv = meg_path / "sample_audvis-meg-oct-6-meg-inv.fif" +fname_label = meg_path / "labels" / "Aud-lh.label" + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname, verbose=False) +events = mne.find_events(raw, stim_channel="STI 014") +inverse_operator = read_inverse_operator(fname_inv) +raw.info["bads"] = ["MEG 2443", "EEG 053"] + +# picks MEG gradiometers +picks = mne.pick_types( + raw.info, meg=True, eeg=False, eog=True, stim=False, exclude="bads" +) + +tmin, tmax = 0, 120 # use the first 120s of data +fmin, fmax = 4, 100 # look at frequencies between 4 and 100Hz +n_fft = 2048 # the FFT size (n_fft). Ideally a power of 2 +label = mne.read_label(fname_label) + +stc = compute_source_psd( + raw, + inverse_operator, + lambda2=1.0 / 9.0, + method="dSPM", + tmin=tmin, + tmax=tmax, + fmin=fmin, + fmax=fmax, + pick_ori="normal", + n_fft=n_fft, + label=label, + dB=True, +) + +stc.save("psd_dSPM", overwrite=True) + +# %% +# View PSD of sources in label +plt.plot(stc.times, stc.data.T) +plt.xlabel("Frequency (Hz)") +plt.ylabel("PSD (dB)") +plt.title("Source Power Spectrum (PSD)") +plt.show() diff --git a/mne-python/source/examples/time_frequency/source_power_spectrum_opm.py b/mne-python/source/examples/time_frequency/source_power_spectrum_opm.py new file mode 100644 index 0000000000000000000000000000000000000000..ae8152670f2d22492ec145d277bac2e79f15e788 --- /dev/null +++ b/mne-python/source/examples/time_frequency/source_power_spectrum_opm.py @@ -0,0 +1,233 @@ +""" +.. _ex-opm-resting-state: + +====================================================================== +Compute source power spectral density (PSD) of VectorView and OPM data +====================================================================== + +Here we compute the resting state from raw for data recorded using +a Neuromag VectorView system and a custom OPM system. +The pipeline is meant to mostly follow the Brainstorm :footcite:`TadelEtAl2011` +`OMEGA resting tutorial pipeline +`__. +The steps we use are: + +1. Filtering: downsample heavily. +2. Artifact detection: use SSP for EOG and ECG. +3. Source localization: dSPM, depth weighting, cortically constrained. +4. Frequency: power spectral density (Welch), 4 s window, 50% overlap. +5. Standardize: normalize by relative power for each source. + +Preprocessing +------------- +""" +# Authors: Denis Engemann +# Luke Bloy +# Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.filter import next_fast_len + +print(__doc__) + +data_path = mne.datasets.opm.data_path() +subject = "OPM_sample" + +subjects_dir = data_path / "subjects" +bem_dir = subjects_dir / subject / "bem" +bem_fname = bem_dir / f"{subject}-5120-5120-5120-bem-sol.fif" +src_fname = bem_dir / f"{subject}-oct6-src.fif" +vv_fname = data_path / "MEG" / "SQUID" / "SQUID_resting_state.fif" +vv_erm_fname = data_path / "MEG" / "SQUID" / "SQUID_empty_room.fif" +vv_trans_fname = data_path / "MEG" / "SQUID" / "SQUID-trans.fif" +opm_fname = data_path / "MEG" / "OPM" / "OPM_resting_state_raw.fif" +opm_erm_fname = data_path / "MEG" / "OPM" / "OPM_empty_room_raw.fif" +opm_trans = mne.transforms.Transform("head", "mri") # use identity transform +opm_coil_def_fname = data_path / "MEG" / "OPM" / "coil_def.dat" + +############################################################################## +# Load data, resample. We will store the raw objects in dicts with entries +# "vv" and "opm" to simplify housekeeping and simplify looping later. + +raws = dict() +raw_erms = dict() +new_sfreq = 60.0 # Nyquist frequency (30 Hz) < line noise freq (50 Hz) +raws["vv"] = mne.io.read_raw_fif(vv_fname, verbose="error") # ignore naming +raws["vv"].load_data().resample(new_sfreq, method="polyphase") +raws["vv"].info["bads"] = ["MEG2233", "MEG1842"] +raw_erms["vv"] = mne.io.read_raw_fif(vv_erm_fname, verbose="error") +raw_erms["vv"].load_data().resample(new_sfreq, method="polyphase") +raw_erms["vv"].info["bads"] = ["MEG2233", "MEG1842"] + +raws["opm"] = mne.io.read_raw_fif(opm_fname) +raws["opm"].load_data().resample(new_sfreq, method="polyphase") +raw_erms["opm"] = mne.io.read_raw_fif(opm_erm_fname) +raw_erms["opm"].load_data().resample(new_sfreq, method="polyphase") +# Make sure our assumptions later hold +assert raws["opm"].info["sfreq"] == raws["vv"].info["sfreq"] + +############################################################################## +# Explore data + +titles = dict(vv="VectorView", opm="OPM") +kinds = ("vv", "opm") +n_fft = next_fast_len(int(round(4 * new_sfreq))) +print(f"Using n_fft={n_fft} ({n_fft / raws['vv'].info['sfreq']:0.1f} s)") +for kind in kinds: + fig = ( + raws[kind] + .compute_psd(n_fft=n_fft, proj=True) + .plot(picks="data", exclude="bads", amplitude=True) + ) + fig.suptitle(titles[kind]) + +############################################################################## +# Alignment and forward +# --------------------- + +# Here we use a reduced size source space (oct5) just for speed +src = mne.setup_source_space(subject, "oct5", add_dist=False, subjects_dir=subjects_dir) +# This line removes source-to-source distances that we will not need. +# We only do it here to save a bit of memory, in general this is not required. +del src[0]["dist"], src[1]["dist"] +bem = mne.read_bem_solution(bem_fname) +# For speed, let's just use a 1-layer BEM +bem = mne.make_bem_solution(bem["surfs"][-1:]) +fwd = dict() + +# check alignment and generate forward for VectorView +kwargs = dict(azimuth=0, elevation=90, distance=0.6, focalpoint=(0.0, 0.0, 0.0)) +fig = mne.viz.plot_alignment( + raws["vv"].info, + trans=vv_trans_fname, + subject=subject, + subjects_dir=subjects_dir, + dig=True, + coord_frame="mri", + surfaces=("head", "white"), +) +mne.viz.set_3d_view(figure=fig, **kwargs) +fwd["vv"] = mne.make_forward_solution( + raws["vv"].info, vv_trans_fname, src, bem, eeg=False, verbose=True +) + +############################################################################## +# And for OPM: + +with mne.use_coil_def(opm_coil_def_fname): + fig = mne.viz.plot_alignment( + raws["opm"].info, + trans=opm_trans, + subject=subject, + subjects_dir=subjects_dir, + dig=False, + coord_frame="mri", + surfaces=("head", "white"), + ) + mne.viz.set_3d_view(figure=fig, **kwargs) + fwd["opm"] = mne.make_forward_solution( + raws["opm"].info, opm_trans, src, bem, eeg=False, verbose=True + ) + +del src, bem + +############################################################################## +# Compute and apply inverse to PSD estimated using multitaper + Welch. +# Group into frequency bands, then normalize each source point and sensor +# independently. This makes the value of each sensor point and source location +# in each frequency band the percentage of the PSD accounted for by that band. + +freq_bands = dict(alpha=(8, 12), beta=(15, 29)) +topos = dict(vv=dict(), opm=dict()) +stcs = dict(vv=dict(), opm=dict()) + +snr = 3.0 +lambda2 = 1.0 / snr**2 +for kind in kinds: + noise_cov = mne.compute_raw_covariance(raw_erms[kind]) + inverse_operator = mne.minimum_norm.make_inverse_operator( + raws[kind].info, forward=fwd[kind], noise_cov=noise_cov, verbose=True + ) + stc_psd, sensor_psd = mne.minimum_norm.compute_source_psd( + raws[kind], + inverse_operator, + lambda2=lambda2, + n_fft=n_fft, + dB=False, + return_sensor=True, + verbose=True, + ) + topo_norm = sensor_psd.data.sum(axis=1, keepdims=True) + stc_norm = stc_psd.sum() # same operation on MNE object, sum across freqs + # Normalize each source point by the total power across freqs + for band, limits in freq_bands.items(): + data = sensor_psd.copy().crop(*limits).data.sum(axis=1, keepdims=True) + topos[kind][band] = mne.EvokedArray(100 * data / topo_norm, sensor_psd.info) + stcs[kind][band] = 100 * stc_psd.copy().crop(*limits).sum() / stc_norm.data + del inverse_operator +del fwd, raws, raw_erms + + +# %% +# Now we can make some plots of each frequency band. Note that the OPM head +# coverage is only over right motor cortex, so only localization +# of beta is likely to be worthwhile. +# +# Alpha +# ----- + + +def plot_band(kind, band): + """Plot activity within a frequency band on the subject's brain.""" + lf, hf = freq_bands[band] + title = f"{titles[kind]} {band}\n({lf:d}-{hf:d} Hz)" + topos[kind][band].plot_topomap( + times=0.0, + scalings=1.0, + cbar_fmt="%0.1f", + vlim=(0, None), + cmap="inferno", + time_format=title, + ) + brain = stcs[kind][band].plot( + subject=subject, + subjects_dir=subjects_dir, + views="cau", + hemi="both", + time_label=title, + title=title, + colormap="inferno", + time_viewer=False, + show_traces=False, + clim=dict(kind="percent", lims=(70, 85, 99)), + smoothing_steps=10, + ) + brain.show_view(azimuth=0, elevation=0, roll=0) + return fig, brain + + +fig_alpha, brain_alpha = plot_band("vv", "alpha") + +# %% +# Beta +# ---- +# Here we also show OPM data, which shows a profile similar to the VectorView +# data beneath the sensors. VectorView first: + +fig_beta, brain_beta = plot_band("vv", "beta") + +# %% +# Then OPM: + +# sphinx_gallery_thumbnail_number = 10 +fig_beta_opm, brain_beta_opm = plot_band("opm", "beta") + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/time_frequency/source_space_time_frequency.py b/mne-python/source/examples/time_frequency/source_space_time_frequency.py new file mode 100644 index 0000000000000000000000000000000000000000..c5ca425dd4cb5c10751897e099d1d47e311aaf25 --- /dev/null +++ b/mne-python/source/examples/time_frequency/source_space_time_frequency.py @@ -0,0 +1,85 @@ +""" +.. _ex-source-space-tfr: + +=================================================== +Compute induced power in the source space with dSPM +=================================================== + +Returns STC files ie source estimates of induced power +for different bands in the source space. The inverse method +is linear based on dSPM inverse operator. + +""" +# Authors: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne import io +from mne.datasets import sample +from mne.minimum_norm import read_inverse_operator, source_band_induced_power + +print(__doc__) + +# %% +# Set parameters +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_raw.fif" +fname_inv = meg_path / "sample_audvis-meg-oct-6-meg-inv.fif" +tmin, tmax, event_id = -0.2, 0.5, 1 + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname) +events = mne.find_events(raw, stim_channel="STI 014") +inverse_operator = read_inverse_operator(fname_inv) + +include = [] +raw.info["bads"] += ["MEG 2443", "EEG 053"] # bads + 2 more + +# picks MEG gradiometers +picks = mne.pick_types( + raw.info, meg=True, eeg=False, eog=True, stim=False, include=include, exclude="bads" +) + +# Load condition 1 +event_id = 1 +events = events[:10] # take 10 events to keep the computation time low +# Use linear detrend to reduce any edge artifacts +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + reject=dict(grad=4000e-13, eog=150e-6), + preload=True, + detrend=1, +) + +# Compute a source estimate per frequency band +bands = dict(alpha=[9, 11], beta=[18, 22]) + +stcs = source_band_induced_power( + epochs, inverse_operator, bands, n_cycles=2, use_fft=False, n_jobs=None +) + +for b, stc in stcs.items(): + stc.save(f"induced_power_{b}", overwrite=True) + +# %% +# plot mean power +plt.plot(stcs["alpha"].times, stcs["alpha"].data.mean(axis=0), label="Alpha") +plt.plot(stcs["beta"].times, stcs["beta"].data.mean(axis=0), label="Beta") +plt.xlabel("Time (ms)") +plt.ylabel("Power") +plt.legend() +plt.title("Mean source induced power") +plt.show() diff --git a/mne-python/source/examples/time_frequency/temporal_whitening.py b/mne-python/source/examples/time_frequency/temporal_whitening.py new file mode 100644 index 0000000000000000000000000000000000000000..3a0a04c01c58c59805e610b165fd9819fa1c6d15 --- /dev/null +++ b/mne-python/source/examples/time_frequency/temporal_whitening.py @@ -0,0 +1,66 @@ +""" +.. _ex-temporal-whitening: + +================================ +Temporal whitening with AR model +================================ + +Here we fit an AR model to the data and use it +to temporally whiten the signals. + +""" +# Authors: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np +from scipy import signal + +import mne +from mne.datasets import sample +from mne.time_frequency import fit_iir_model_raw + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_raw.fif" +proj_fname = meg_path / "sample_audvis_ecg-proj.fif" + +raw = mne.io.read_raw_fif(raw_fname) +proj = mne.read_proj(proj_fname) +raw.add_proj(proj) +raw.info["bads"] = ["MEG 2443", "EEG 053"] # mark bad channels + +# Set up pick list: Gradiometers - bad channels +picks = mne.pick_types(raw.info, meg="grad", exclude="bads") + +order = 5 # define model order +picks = picks[:1] + +# Estimate AR models on raw data +b, a = fit_iir_model_raw(raw, order=order, picks=picks, tmin=60, tmax=180) +d, times = raw[0, 10000:20000] # look at one channel from now on +d = d.ravel() # make flat vector +innovation = signal.convolve(d, a, "valid") +d_ = signal.lfilter(b, a, innovation) # regenerate the signal +d_ = np.r_[d_[0] * np.ones(order), d_] # dummy samples to keep signal length + +# %% +# Plot the different time series and PSDs +plt.close("all") +plt.figure() +plt.plot(d[:100], label="signal") +plt.plot(d_[:100], label="regenerated signal") +plt.legend() + +plt.figure() +plt.psd(d, Fs=raw.info["sfreq"], NFFT=2048) +plt.psd(innovation, Fs=raw.info["sfreq"], NFFT=2048) +plt.psd(d_, Fs=raw.info["sfreq"], NFFT=2048, linestyle="--") +plt.legend(("Signal", "Innovation", "Regenerated signal")) +plt.show() diff --git a/mne-python/source/examples/time_frequency/time_frequency_erds.py b/mne-python/source/examples/time_frequency/time_frequency_erds.py new file mode 100644 index 0000000000000000000000000000000000000000..93272eb7aa31dc1f38400ef6ca13d3f3b9a6a48a --- /dev/null +++ b/mne-python/source/examples/time_frequency/time_frequency_erds.py @@ -0,0 +1,227 @@ +""" +.. _ex-tfr-erds: + +=============================== +Compute and visualize ERDS maps +=============================== + +This example calculates and displays ERDS maps of event-related EEG data. +ERDS (sometimes also written as ERD/ERS) is short for event-related +desynchronization (ERD) and event-related synchronization (ERS) +:footcite:`PfurtschellerLopesdaSilva1999`. Conceptually, ERD corresponds to a +decrease in power in a specific frequency band relative to a baseline. +Similarly, ERS corresponds to an increase in power. An ERDS map is a +time/frequency representation of ERD/ERS over a range of frequencies +:footcite:`GraimannEtAl2002`. ERDS maps are also known as ERSP (event-related +spectral perturbation) :footcite:`Makeig1993`. + +In this example, we use an EEG BCI data set containing two different motor +imagery tasks (imagined hand and feet movement). Our goal is to generate ERDS +maps for each of the two tasks. + +First, we load the data and create epochs of 5s length. The data set contains +multiple channels, but we will only consider C3, Cz, and C4. We compute maps +containing frequencies ranging from 2 to 35Hz. We map ERD to red color and ERS +to blue color, which is customary in many ERDS publications. Finally, we +perform cluster-based permutation tests to estimate significant ERDS values +(corrected for multiple comparisons within channels). +""" +# Authors: Clemens Brunner +# Felix Klotzsche +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +# As usual, we import everything we need. + +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import seaborn as sns +from matplotlib.colors import TwoSlopeNorm + +import mne +from mne.datasets import eegbci +from mne.io import concatenate_raws, read_raw_edf +from mne.stats import permutation_cluster_1samp_test as pcluster_test + +# %% +# First, we load and preprocess the data. We use runs 6, 10, and 14 from +# subject 1 (these runs contains hand and feet motor imagery). + +fnames = eegbci.load_data(subjects=1, runs=(6, 10, 14)) +raw = concatenate_raws([read_raw_edf(f, preload=True) for f in fnames]) + +raw.rename_channels(lambda x: x.strip(".")) # remove dots from channel names +# rename descriptions to be more easily interpretable +raw.annotations.rename(dict(T1="hands", T2="feet")) + +# %% +# Now we can create 5-second epochs around events of interest. + +tmin, tmax = -1, 4 +event_ids = dict(hands=2, feet=3) # map event IDs to tasks + +epochs = mne.Epochs( + raw, + event_id=["hands", "feet"], + tmin=tmin - 0.5, + tmax=tmax + 0.5, + picks=("C3", "Cz", "C4"), + baseline=None, + preload=True, +) + +# %% +# .. _cnorm-example: +# +# Here we set suitable values for computing ERDS maps. Note especially the +# ``cnorm`` variable, which sets up an *asymmetric* colormap where the middle +# color is mapped to zero, even though zero is not the middle *value* of the +# colormap range. This does two things: it ensures that zero values will be +# plotted in white (given that below we select the ``RdBu`` colormap), and it +# makes synchronization and desynchronization look equally prominent in the +# plots, even though their extreme values are of different magnitudes. + +freqs = np.arange(2, 36) # frequencies from 2-35Hz +vmin, vmax = -1, 1.5 # set min and max ERDS values in plot +baseline = (-1, 0) # baseline interval (in s) +cnorm = TwoSlopeNorm(vmin=vmin, vcenter=0, vmax=vmax) # min, center & max ERDS + +kwargs = dict( + n_permutations=100, step_down_p=0.05, seed=1, buffer_size=None, out_type="mask" +) # for cluster test + +# %% +# Finally, we perform time/frequency decomposition over all epochs. +tfr = epochs.compute_tfr( + method="multitaper", + freqs=freqs, + n_cycles=freqs, + use_fft=True, + return_itc=False, + average=False, + decim=2, +) +tfr.crop(tmin, tmax).apply_baseline(baseline, mode="percent") + +for event in event_ids: + # select desired epochs for visualization + tfr_ev = tfr[event] + fig, axes = plt.subplots( + 1, 4, figsize=(12, 4), gridspec_kw={"width_ratios": [10, 10, 10, 1]} + ) + for ch, ax in enumerate(axes[:-1]): # for each channel + # positive clusters + _, c1, p1, _ = pcluster_test(tfr_ev.data[:, ch], tail=1, **kwargs) + # negative clusters + _, c2, p2, _ = pcluster_test(tfr_ev.data[:, ch], tail=-1, **kwargs) + + # note that we keep clusters with p <= 0.05 from the combined clusters + # of two independent tests; in this example, we do not correct for + # these two comparisons + c = np.stack(c1 + c2, axis=2) # combined clusters + p = np.concatenate((p1, p2)) # combined p-values + mask = c[..., p <= 0.05].any(axis=-1) + + # plot TFR (ERDS map with masking) + tfr_ev.average().plot( + [ch], + cmap="RdBu", + cnorm=cnorm, + axes=ax, + colorbar=False, + show=False, + mask=mask, + mask_style="mask", + ) + + ax.set_title(epochs.ch_names[ch], fontsize=10) + ax.axvline(0, linewidth=1, color="black", linestyle=":") # event + if ch != 0: + ax.set_ylabel("") + ax.set_yticklabels("") + fig.colorbar(axes[0].images[-1], cax=axes[-1]).ax.set_yscale("linear") + fig.suptitle(f"ERDS ({event})") + plt.show() + +# %% +# Similar to `~mne.Epochs` objects, we can also export data from +# `~mne.time_frequency.EpochsTFR` and `~mne.time_frequency.AverageTFR` objects +# to a :class:`Pandas DataFrame `. By default, the `time` +# column of the exported data frame is in milliseconds. Here, to be consistent +# with the time-frequency plots, we want to keep it in seconds, which we can +# achieve by setting ``time_format=None``: + +df = tfr.to_data_frame(time_format=None) +df.head() + +# %% +# This allows us to use additional plotting functions like +# :func:`seaborn.lineplot` to plot confidence bands: + +df = tfr.to_data_frame(time_format=None, long_format=True) + +# Map to frequency bands: +freq_bounds = {"_": 0, "delta": 3, "theta": 7, "alpha": 13, "beta": 35, "gamma": 140} +df["band"] = pd.cut( + df["freq"], list(freq_bounds.values()), labels=list(freq_bounds)[1:] +) + +# Filter to retain only relevant frequency bands: +freq_bands_of_interest = ["delta", "theta", "alpha", "beta"] +df = df[df.band.isin(freq_bands_of_interest)] +df["band"] = df["band"].cat.remove_unused_categories() + +# Order channels for plotting: +df["channel"] = df["channel"].cat.reorder_categories(("C3", "Cz", "C4"), ordered=True) + +g = sns.FacetGrid(df, row="band", col="channel", margin_titles=True) +g.map(sns.lineplot, "time", "value", "condition", n_boot=10) +axline_kw = dict(color="black", linestyle="dashed", linewidth=0.5, alpha=0.5) +g.map(plt.axhline, y=0, **axline_kw) +g.map(plt.axvline, x=0, **axline_kw) +g.set(ylim=(None, 1.5)) +g.set_axis_labels("Time (s)", "ERDS") +g.set_titles(col_template="{col_name}", row_template="{row_name}") +g.add_legend(ncol=2, loc="lower center") +g.fig.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.08) + +# %% +# Having the data as a DataFrame also facilitates subsetting, +# grouping, and other transforms. +# Here, we use seaborn to plot the average ERDS in the motor imagery interval +# as a function of frequency band and imagery condition: + +df_mean = ( + df.query("time > 1") + .groupby(["condition", "epoch", "band", "channel"], observed=False)[["value"]] + .mean() + .reset_index() +) + +g = sns.FacetGrid( + df_mean, col="condition", col_order=["hands", "feet"], margin_titles=True +) +g = g.map( + sns.violinplot, + "channel", + "value", + "band", + cut=0, + palette="deep", + order=["C3", "Cz", "C4"], + hue_order=freq_bands_of_interest, + linewidth=0.5, +).add_legend(ncol=4, loc="lower center") + +g.map(plt.axhline, **axline_kw) +g.set_axis_labels("", "ERDS") +g.set_titles(col_template="{col_name}", row_template="{row_name}") +g.fig.subplots_adjust(left=0.1, right=0.9, top=0.9, bottom=0.3) + +# %% +# References +# ========== +# .. footbibliography:: diff --git a/mne-python/source/examples/time_frequency/time_frequency_global_field_power.py b/mne-python/source/examples/time_frequency/time_frequency_global_field_power.py new file mode 100644 index 0000000000000000000000000000000000000000..cc4ff14ce2aa76778cca73ed49ca5e79bee49fc4 --- /dev/null +++ b/mne-python/source/examples/time_frequency/time_frequency_global_field_power.py @@ -0,0 +1,154 @@ +""" +.. _ex-time-freq-global-field-power: + +=========================================================== +Explore event-related dynamics for specific frequency bands +=========================================================== + +The objective is to show you how to explore spectrally localized +effects. For this purpose we adapt the method described in +:footcite:`HariSalmelin1997` and use it on the somato dataset. +The idea is to track the band-limited temporal evolution +of spatial patterns by using the :term:`global field power` (GFP). + +We first bandpass filter the signals and then apply a Hilbert transform. To +reveal oscillatory activity the evoked response is then subtracted from every +single trial. Finally, we rectify the signals prior to averaging across trials +by taking the magnitude of the Hilbert. +Then the :term:`GFP` is computed as described in +:footcite:`EngemannGramfort2015`, using the sum of the +squares but without normalization by the rank. +Baselining is subsequently applied to make the :term:`GFP` comparable +between frequencies. +The procedure is then repeated for each frequency band of interest and +all :term:`GFPs` are visualized. To estimate uncertainty, non-parametric +confidence intervals are computed as described in :footcite:`EfronHastie2016` +across channels. + +The advantage of this method over summarizing the Space × Time × Frequency +output of a Morlet Wavelet in frequency bands is relative speed and, more +importantly, the clear-cut comparability of the spectral decomposition (the +same type of filter is used across all bands). + +We will use this dataset: :ref:`somato-dataset` + +References +---------- +.. footbibliography:: + +""" # noqa: E501 +# Authors: Denis A. Engemann +# Stefan Appelhoff +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne.baseline import rescale +from mne.datasets import somato +from mne.stats import bootstrap_confidence_interval + +# %% +# Set parameters +data_path = somato.data_path() +subject = "01" +task = "somato" +raw_fname = data_path / f"sub-{subject}" / "meg" / f"sub-{subject}_task-{task}_meg.fif" + +# let's explore some frequency bands +iter_freqs = [("Theta", 4, 7), ("Alpha", 8, 12), ("Beta", 13, 25), ("Gamma", 30, 45)] + +# %% +# We create average power time courses for each frequency band + +# set epoching parameters +event_id, tmin, tmax = 1, -1.0, 3.0 +baseline = None + +# get the header to extract events +raw = mne.io.read_raw_fif(raw_fname) +events = mne.find_events(raw, stim_channel="STI 014") + +frequency_map = list() + +for band, fmin, fmax in iter_freqs: + # (re)load the data to save memory + raw = mne.io.read_raw_fif(raw_fname) + raw.pick(picks=["grad", "eog"]) # we just look at gradiometers + raw.load_data() + + # bandpass filter + raw.filter( + fmin, + fmax, + n_jobs=None, # use more jobs to speed up. + l_trans_bandwidth=1, # make sure filter params are the same + h_trans_bandwidth=1, + ) # in each band and skip "auto" option. + + # epoch + epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + baseline=baseline, + reject=dict(grad=4000e-13, eog=350e-6), + preload=True, + ) + # remove evoked response + epochs.subtract_evoked() + + # get analytic signal (envelope) + epochs.apply_hilbert(envelope=True) + frequency_map.append(((band, fmin, fmax), epochs.average())) + del epochs +del raw + +# %% +# Now we can compute the Global Field Power +# We can track the emergence of spatial patterns compared to baseline +# for each frequency band, with a bootstrapped confidence interval. +# +# We see dominant responses in the Alpha and Beta bands. + + +# Helper function for plotting spread +def stat_fun(x): + """Return sum of squares.""" + return np.sum(x**2, axis=0) + + +# Plot +fig, axes = plt.subplots(4, 1, figsize=(10, 7), sharex=True, sharey=True) +colors = plt.colormaps["winter_r"](np.linspace(0, 1, 4)) +for ((freq_name, fmin, fmax), average), color, ax in zip( + frequency_map, colors, axes.ravel()[::-1] +): + times = average.times * 1e3 + gfp = np.sum(average.data**2, axis=0) + gfp = mne.baseline.rescale(gfp, times, baseline=(None, 0)) + ax.plot(times, gfp, label=freq_name, color=color, linewidth=2.5) + ax.axhline(0, linestyle="--", color="grey", linewidth=2) + ci_low, ci_up = bootstrap_confidence_interval( + average.data, random_state=0, stat_fun=stat_fun + ) + ci_low = rescale(ci_low, average.times, baseline=(None, 0)) + ci_up = rescale(ci_up, average.times, baseline=(None, 0)) + ax.fill_between(times, gfp + ci_up, gfp - ci_low, color=color, alpha=0.3) + ax.grid(True) + ax.set_ylabel("GFP") + ax.annotate( + f"{freq_name} ({fmin:d}-{fmax:d}Hz)", + xy=(0.95, 0.8), + horizontalalignment="right", + xycoords="axes fraction", + ) + ax.set_xlim(-1000, 3000) + +axes.ravel()[-1].set_xlabel("Time [ms]") diff --git a/mne-python/source/examples/time_frequency/time_frequency_simulated.py b/mne-python/source/examples/time_frequency/time_frequency_simulated.py new file mode 100644 index 0000000000000000000000000000000000000000..dc42f16da3a73b44562705f4249a78480b6b886a --- /dev/null +++ b/mne-python/source/examples/time_frequency/time_frequency_simulated.py @@ -0,0 +1,278 @@ +""" +.. _ex-tfr-comparison: + +================================================================================== +Time-frequency on simulated data (Multitaper vs. Morlet vs. Stockwell vs. Hilbert) +================================================================================== + +This example demonstrates the different time-frequency estimation methods +on simulated data. It shows the time-frequency resolution trade-off +and the problem of estimation variance. In addition it highlights +alternative functions for generating TFRs without averaging across +trials, or by operating on numpy arrays. +""" # noqa E501 +# Authors: Hari Bharadwaj +# Denis Engemann +# Chris Holdgraf +# Alex Rockhill +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np +from matplotlib import pyplot as plt + +from mne import Epochs, create_info +from mne.io import RawArray +from mne.time_frequency import AverageTFRArray, EpochsTFRArray, tfr_array_morlet + +print(__doc__) + +# %% +# Simulate data +# ------------- +# +# We'll simulate data with a known spectro-temporal structure. + +sfreq = 1000.0 +ch_names = ["SIM0001", "SIM0002"] +ch_types = ["grad", "grad"] +info = create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types) + +n_times = 1024 # Just over 1 second epochs +n_epochs = 40 +seed = 42 +rng = np.random.RandomState(seed) +data = rng.randn(len(ch_names), n_times * n_epochs + 200) # buffer + +# Add a 50 Hz sinusoidal burst to the noise and ramp it. +t = np.arange(n_times, dtype=np.float64) / sfreq +signal = np.sin(np.pi * 2.0 * 50.0 * t) # 50 Hz sinusoid signal +signal[np.logical_or(t < 0.45, t > 0.55)] = 0.0 # hard windowing +on_time = np.logical_and(t >= 0.45, t <= 0.55) +signal[on_time] *= np.hanning(on_time.sum()) # ramping +data[:, 100:-100] += np.tile(signal, n_epochs) # add signal + +raw = RawArray(data, info) +events = np.zeros((n_epochs, 3), dtype=int) +events[:, 0] = np.arange(n_epochs) * n_times +epochs = Epochs( + raw, + events, + dict(sin50hz=0), + tmin=0, + tmax=n_times / sfreq, + reject=dict(grad=4000), + baseline=None, +) + +epochs.average().plot() + +# %% +# Calculate a time-frequency representation (TFR) +# ----------------------------------------------- +# +# Below we'll demonstrate the output of several TFR functions in MNE: +# +# * :func:`mne.time_frequency.tfr_multitaper` +# * :func:`mne.time_frequency.tfr_stockwell` +# * :func:`mne.time_frequency.tfr_morlet` +# * :meth:`mne.Epochs.filter` and :meth:`mne.Epochs.apply_hilbert` +# +# Multitaper transform +# ==================== +# First we'll use the multitaper method for calculating the TFR. +# This creates several orthogonal tapering windows in the TFR estimation, +# which reduces variance. We'll also show some of the parameters that can be +# tweaked (e.g., ``time_bandwidth``) that will result in different multitaper +# properties, and thus a different TFR. You can trade time resolution or +# frequency resolution or both in order to get a reduction in variance. + +freqs = np.arange(5.0, 100.0, 3.0) +vmin, vmax = -3.0, 3.0 # Define our color limits. + +fig, axs = plt.subplots(1, 3, figsize=(15, 5), sharey=True, layout="constrained") +for n_cycles, time_bandwidth, ax, title in zip( + [freqs / 2, freqs, freqs / 2], # number of cycles + [2.0, 4.0, 8.0], # time bandwidth + axs, + [ + "Sim: Least smoothing, most variance", + "Sim: Less frequency smoothing,\nmore time smoothing", + "Sim: Less time smoothing,\nmore frequency smoothing", + ], +): + power = epochs.compute_tfr( + method="multitaper", + freqs=freqs, + n_cycles=n_cycles, + time_bandwidth=time_bandwidth, + return_itc=False, + average=True, + ) + ax.set_title(title) + # Plot results. Baseline correct based on first 100 ms. + power.plot( + [0], + baseline=(0.0, 0.1), + mode="mean", + vlim=(vmin, vmax), + axes=ax, + show=False, + colorbar=False, + ) + +############################################################################## +# Stockwell (S) transform +# ======================= +# +# Stockwell uses a Gaussian window to balance temporal and spectral resolution. +# Importantly, frequency bands are phase-normalized, hence strictly comparable +# with regard to timing, and, the input signal can be recoverd from the +# transform in a lossless way if we disregard numerical errors. In this case, +# we control the spectral / temporal resolution by specifying different widths +# of the gaussian window using the ``width`` parameter. + +fig, axs = plt.subplots(1, 3, figsize=(15, 5), sharey=True, layout="constrained") +fmin, fmax = freqs[[0, -1]] +for width, ax in zip((0.2, 0.7, 3.0), axs): + power = epochs.compute_tfr(method="stockwell", freqs=(fmin, fmax), width=width) + power.plot( + [0], baseline=(0.0, 0.1), mode="mean", axes=ax, show=False, colorbar=False + ) + ax.set_title(f"Sim: Using S transform, width = {width:0.1f}") + +# %% +# Morlet Wavelets +# =============== +# +# Next, we'll show the TFR using morlet wavelets, which are a sinusoidal wave +# with a gaussian envelope. We can control the balance between spectral and +# temporal resolution with the ``n_cycles`` parameter, which defines the +# number of cycles to include in the window. + +fig, axs = plt.subplots(1, 3, figsize=(15, 5), sharey=True, layout="constrained") +all_n_cycles = [1, 3, freqs / 2.0] +for n_cycles, ax in zip(all_n_cycles, axs): + power = epochs.compute_tfr( + method="morlet", freqs=freqs, n_cycles=n_cycles, return_itc=False, average=True + ) + power.plot( + [0], + baseline=(0.0, 0.1), + mode="mean", + vlim=(vmin, vmax), + axes=ax, + show=False, + colorbar=False, + ) + n_cycles = "scaled by freqs" if not isinstance(n_cycles, int) else n_cycles + ax.set_title(f"Sim: Using Morlet wavelet, n_cycles = {n_cycles}") + +# %% +# Narrow-bandpass Filter and Hilbert Transform +# ============================================ +# +# Finally, we'll show a time-frequency representation using a narrow bandpass +# filter and the Hilbert transform. Choosing the right filter parameters is +# important so that you isolate only one oscillation of interest, generally +# the width of this filter is recommended to be about 2 Hz. + +fig, axs = plt.subplots(1, 3, figsize=(15, 5), sharey=True, layout="constrained") +bandwidths = [1.0, 2.0, 4.0] +for bandwidth, ax in zip(bandwidths, axs): + data = np.zeros( + (len(epochs), len(ch_names), freqs.size, epochs.times.size), dtype=complex + ) + for idx, freq in enumerate(freqs): + # Filter raw data and re-epoch to avoid the filter being longer than + # the epoch data for low frequencies and short epochs, such as here. + raw_filter = raw.copy() + # NOTE: The bandwidths of the filters are changed from their defaults + # to exaggerate differences. With the default transition bandwidths, + # these are all very similar because the filters are almost the same. + # In practice, using the default is usually a wise choice. + raw_filter.filter( + l_freq=freq - bandwidth / 2, + h_freq=freq + bandwidth / 2, + # no negative values for large bandwidth and low freq + l_trans_bandwidth=min([4 * bandwidth, freq - bandwidth]), + h_trans_bandwidth=4 * bandwidth, + ) + raw_filter.apply_hilbert() + epochs_hilb = Epochs( + raw_filter, events, tmin=0, tmax=n_times / sfreq, baseline=(0, 0.1) + ) + data[:, :, idx] = epochs_hilb.get_data() + power = EpochsTFRArray(epochs.info, data, epochs.times, freqs, method="hilbert") + power.average().plot( + [0], + baseline=(0.0, 0.1), + mode="mean", + vlim=(0, 0.1), + axes=ax, + show=False, + colorbar=False, + ) + n_cycles = "scaled by freqs" if not isinstance(n_cycles, int) else n_cycles + ax.set_title( + "Sim: Using narrow bandpass filter Hilbert,\n" + f"bandwidth = {bandwidth}, " + f"transition bandwidth = {4 * bandwidth}" + ) + +# %% +# Calculating a TFR without averaging over epochs +# ----------------------------------------------- +# +# It is also possible to calculate a TFR without averaging across trials. +# We can do this by using ``average=False``. In this case, an instance of +# :class:`mne.time_frequency.EpochsTFR` is returned. + +n_cycles = freqs / 2.0 +power = epochs.compute_tfr( + method="morlet", freqs=freqs, n_cycles=n_cycles, return_itc=False, average=False +) +print(type(power)) +avgpower = power.average() +avgpower.plot( + [0], + baseline=(0.0, 0.1), + mode="mean", + vlim=(vmin, vmax), + title="Using Morlet wavelets and EpochsTFR", + show=False, +) + +# %% +# Operating on arrays +# ------------------- +# +# MNE-Python also has functions that operate on :class:`NumPy arrays ` +# instead of MNE-Python objects. These are :func:`~mne.time_frequency.tfr_array_morlet` +# and :func:`~mne.time_frequency.tfr_array_multitaper`. They expect inputs of the shape +# ``(n_epochs, n_channels, n_times)`` and return an array of shape +# ``(n_epochs, n_channels, n_freqs, n_times)`` (or optionally, can collapse the epochs +# dimension if you want average power or inter-trial coherence; see ``output`` param). + +power = tfr_array_morlet( + epochs.get_data(), + sfreq=epochs.info["sfreq"], + freqs=freqs, + n_cycles=n_cycles, + output="avg_power", + zero_mean=False, +) +# Put it into a TFR container for easy plotting +tfr = AverageTFRArray( + info=epochs.info, data=power, times=epochs.times, freqs=freqs, nave=len(epochs) +) +tfr.plot( + baseline=(0.0, 0.1), + picks=[0], + mode="mean", + vlim=(vmin, vmax), + title="TFR calculated on a NumPy array", +) diff --git a/mne-python/source/examples/visualization/3d_to_2d.py b/mne-python/source/examples/visualization/3d_to_2d.py new file mode 100644 index 0000000000000000000000000000000000000000..47b223e839666f9404b5587a210764e6d0069f56 --- /dev/null +++ b/mne-python/source/examples/visualization/3d_to_2d.py @@ -0,0 +1,137 @@ +""" +.. _ex-electrode-pos-2d: + +=================================================== +How to convert 3D electrode positions to a 2D image +=================================================== + +Sometimes we want to convert a 3D representation of electrodes into a 2D +image. For example, if we are using electrocorticography it is common to create +scatterplots on top of a brain, with each point representing an electrode. + +In this example, we'll show two ways of doing this in MNE-Python. First, +if we have the 3D locations of each electrode then we can use PyVista to +take a snapshot of a view of the brain. If we do not have these 3D locations, +and only have a 2D image of the electrodes on the brain, we can use the +:class:`mne.viz.ClickableImage` class to choose our own electrode positions +on the image. +""" +# Authors: Christopher Holdgraf +# Alex Rockhill +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np +from matplotlib import pyplot as plt + +import mne +from mne.io.fiff.raw import read_raw_fif +from mne.viz import ( + ClickableImage, # noqa: F401 + plot_alignment, + set_3d_view, + snapshot_brain_montage, +) + +misc_path = mne.datasets.misc.data_path() +subjects_dir = misc_path / "ecog" +ecog_data_fname = subjects_dir / "sample_ecog_ieeg.fif" + +# We've already clicked and exported +layout_name = subjects_dir / "custom_layout.lout" + +# %% +# Load data +# --------- +# +# First we will load a sample ECoG dataset which we'll use for generating +# a 2D snapshot. + +raw = read_raw_fif(ecog_data_fname) +raw.pick([f"G{i}" for i in range(1, 257)]) # pick just one grid + +# Since we loaded in the ecog data from FIF, the coordinates +# are in 'head' space, but we actually want them in 'mri' space. +# So we will apply the head->mri transform that was used when +# generating the dataset (the estimated head->mri transform). +montage = raw.get_montage() +trans = mne.coreg.estimate_head_mri_t("sample_ecog", subjects_dir) +montage.apply_trans(trans) + +# %% +# Project 3D electrodes to a 2D snapshot +# -------------------------------------- +# +# Because we have the 3D location of each electrode, we can use the +# :func:`mne.viz.snapshot_brain_montage` function to return a 2D image along +# with the electrode positions on that image. We use this in conjunction with +# :func:`mne.viz.plot_alignment`, which visualizes electrode positions. + +fig = plot_alignment( + raw.info, + trans=trans, + subject="sample_ecog", + subjects_dir=subjects_dir, + surfaces=dict(pial=0.9), +) +set_3d_view(figure=fig, azimuth=20, elevation=80) +xy, im = snapshot_brain_montage(fig, montage) + +# Convert from a dictionary to array to plot +xy_pts = np.vstack([xy[ch] for ch in raw.ch_names]) + +# Compute beta power to visualize +raw.load_data() +beta_power = raw.filter(20, 30).apply_hilbert(envelope=True).get_data() +beta_power = beta_power.max(axis=1) # take maximum over time + +# This allows us to use matplotlib to create arbitrary 2d scatterplots +fig2, ax = plt.subplots(figsize=(10, 10)) +ax.imshow(im) +cmap = ax.scatter(*xy_pts.T, c=beta_power, s=100, cmap="coolwarm") +cbar = fig2.colorbar(cmap) +cbar.ax.set_ylabel("Beta Power") +ax.set_axis_off() + +# fig2.savefig('./brain.png', bbox_inches='tight') # For ClickableImage + +# %% +# Manually creating 2D electrode positions +# ---------------------------------------- +# +# If we don't have the 3D electrode positions then we can still create a +# 2D representation of the electrodes. Assuming that you can see the electrodes +# on the 2D image, we can use :class:`mne.viz.ClickableImage` to open the image +# interactively. You can click points on the image and the x/y coordinate will +# be stored. +# +# We'll open an image file, then use ClickableImage to +# return 2D locations of mouse clicks (or load a file already created). +# Then, we'll return these xy positions as a layout for use with plotting topo +# maps. + + +# This code opens the image so you can click on it. Commented out +# because we've stored the clicks as a layout file already. + +# # The click coordinates are stored as a list of tuples +# im = plt.imread('./brain.png') +# click = ClickableImage(im) +# click.plot_clicks() + +# # Generate a layout from our clicks and normalize by the image +# print('Generating and saving layout...') +# lt = click.to_layout() +# lt.save(layout_name) # save if we want + +# # We've already got the layout, load it +lt = mne.channels.read_layout(layout_name, scale=False) +x = lt.pos[:, 0] * float(im.shape[1]) +y = (1 - lt.pos[:, 1]) * float(im.shape[0]) # Flip the y-position +fig, ax = plt.subplots(layout="constrained") +ax.imshow(im) +ax.scatter(x, y, s=80, color="r") +ax.set_axis_off() diff --git a/mne-python/source/examples/visualization/README.txt b/mne-python/source/examples/visualization/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..25af47af50b6c3a1b1143c9648c32590dbab7330 --- /dev/null +++ b/mne-python/source/examples/visualization/README.txt @@ -0,0 +1,5 @@ + +Visualization +------------- + +Looking at data and processing output. diff --git a/mne-python/source/examples/visualization/brain.py b/mne-python/source/examples/visualization/brain.py new file mode 100644 index 0000000000000000000000000000000000000000..8e7c8226449ac6bded72dd86d06952523a9aa359 --- /dev/null +++ b/mne-python/source/examples/visualization/brain.py @@ -0,0 +1,168 @@ +""" +.. _ex-brain: + +=============================== +Plotting with ``mne.viz.Brain`` +=============================== + +In this example, we'll show how to use :class:`mne.viz.Brain`. +""" +# Author: Alex Rockhill +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +# Load data +# --------- +# +# In this example we use the ``sample`` data which is data from a subject +# being presented auditory and visual stimuli to display the functionality +# of :class:`mne.viz.Brain` for plotting data on a brain. + +import matplotlib.pyplot as plt +from matplotlib.cm import ScalarMappable +from matplotlib.colors import Normalize + +import mne +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() +subjects_dir = data_path / "subjects" +sample_dir = data_path / "MEG" / "sample" + +# %% +# Add source information +# ---------------------- +# +# Plot source information. + +brain_kwargs = dict(alpha=0.1, background="white", cortex="low_contrast") +brain = mne.viz.Brain("sample", subjects_dir=subjects_dir, **brain_kwargs) + +stc = mne.read_source_estimate(sample_dir / "sample_audvis-meg") +stc.crop(0.09, 0.1) + +kwargs = dict( + fmin=stc.data.min(), + fmax=stc.data.max(), + alpha=0.25, + smoothing_steps="nearest", + time=stc.times, +) +brain.add_data(stc.lh_data, hemi="lh", vertices=stc.lh_vertno, **kwargs) +brain.add_data(stc.rh_data, hemi="rh", vertices=stc.rh_vertno, **kwargs) + +# %% +# Modify the view of the brain +# ---------------------------- +# +# You can adjust the view of the brain using ``show_view`` method. + +brain = mne.viz.Brain("sample", subjects_dir=subjects_dir, **brain_kwargs) +brain.show_view(azimuth=190, elevation=70, distance=350, focalpoint=(0, 0, 20)) + +# %% +# Highlight a region on the brain +# ------------------------------- +# +# It can be useful to highlight a region of the brain for analyses. +# To highlight a region on the brain you can use the ``add_label`` method. +# Labels are stored in the Freesurfer label directory from the ``recon-all`` +# for that subject. Labels can also be made following the +# `Freesurfer instructions +# `_ +# Here we will show Brodmann Area 44. +# +# .. note:: The MNE sample dataset contains only a subselection of the +# Freesurfer labels created during the ``recon-all``. + +brain = mne.viz.Brain("sample", subjects_dir=subjects_dir, **brain_kwargs) +brain.add_label("BA44", hemi="lh", color="green", borders=True) +brain.show_view(azimuth=190, elevation=70, distance=350, focalpoint=(0, 0, 20)) + +# %% +# Include the head in the image +# ----------------------------- +# +# Add a head image using the ``add_head`` method. + +brain = mne.viz.Brain("sample", subjects_dir=subjects_dir, **brain_kwargs) +brain.add_head(alpha=0.5) + +# %% +# Add sensors positions +# --------------------- +# +# To put into context the data that generated the source time course, +# the sensor positions can be displayed as well. + +brain = mne.viz.Brain("sample", subjects_dir=subjects_dir, **brain_kwargs) +evoked = mne.read_evokeds(sample_dir / "sample_audvis-ave.fif")[0] +trans = mne.read_trans(sample_dir / "sample_audvis_raw-trans.fif") +brain.add_sensors(evoked.info, trans) +brain.show_view(distance=500) # move back to show sensors + +# %% +# Add current dipoles +# ------------------- +# +# Dipole modeling as in :ref:`tut-dipole-orientations` can be plotted on the +# brain as well. + +brain = mne.viz.Brain("sample", subjects_dir=subjects_dir, **brain_kwargs) +dip = mne.read_dipole(sample_dir / "sample_audvis_set1.dip") +cmap = plt.colormaps["YlOrRd"] +colors = [cmap(gof / dip.gof.max()) for gof in dip.gof] +brain.add_dipole(dip, trans, colors=colors, scales=list(dip.amplitude * 1e8)) +brain.show_view(azimuth=-20, elevation=60, distance=300) +img = brain.screenshot() # for next section + +# %% +# Create a screenshot for exporting the brain image +# ------------------------------------------------- +# Also, we can a static image of the brain using ``screenshot`` (above), +# which will allow us to add a colorbar. This is useful for figures in +# publications. + +fig, ax = plt.subplots() +ax.imshow(img) +ax.axis("off") +cax = fig.add_axes([0.9, 0.1, 0.05, 0.8]) +norm = Normalize(vmin=0, vmax=dip.gof.max()) +fig.colorbar(ScalarMappable(norm=norm, cmap=cmap), cax=cax) +fig.suptitle("Dipole Fits Scaled by Amplitude and Colored by GOF") + + +# %% +# Use per-vertex opacity for distributed data +# -------------------------------------------- +# +# You can provide an array for ``alpha`` in :meth:`mne.viz.Brain.add_data` +# to control transparency per vertex. This can be useful to emphasize a +# subset of vertices while still showing surrounding context. + +brain = mne.viz.Brain("sample", subjects_dir=subjects_dir, hemi="lh", **brain_kwargs) +coords = brain.geo["lh"].coords +n_vertices = len(coords) + +# Build synthetic data: a smooth left-to-right gradient color-wise in the Y +# (front-back) direction, plus a matching opacity ramp from mostly transparent to +# fully opaque in the X (left-right) direction. +data = coords[:, 1] +data = (data - data.min()) / (data.max() - data.min()) +vertex_alpha = -coords[:, 0] +vertex_alpha = (vertex_alpha - vertex_alpha.min()) / ( + vertex_alpha.max() - vertex_alpha.min() +) + +brain.add_data( + data, + hemi="lh", + alpha=vertex_alpha, + colormap="viridis", + smoothing_steps=5, +) +brain.show_view(azimuth=190, elevation=70, distance=350, focalpoint=(0, 0, 20)) diff --git a/mne-python/source/examples/visualization/channel_epochs_image.py b/mne-python/source/examples/visualization/channel_epochs_image.py new file mode 100644 index 0000000000000000000000000000000000000000..9281270a8c1b8c782fe3adbd1fcf04bafe92b447 --- /dev/null +++ b/mne-python/source/examples/visualization/channel_epochs_image.py @@ -0,0 +1,103 @@ +""" +.. _ex-epochs-image: + +========================================= +Visualize channel over epochs as an image +========================================= + +This will produce what is sometimes called an event related +potential / field (ERP/ERF) image. + +Two images are produced, one with a good channel and one with a channel +that does not show any evoked field. + +It is also demonstrated how to reorder the epochs using a 1D spectral +embedding as described in :footcite:`GramfortEtAl2010`. +""" +# Authors: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne import io +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() + +# %% +# Set parameters +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +event_id, tmin, tmax = 1, -0.2, 0.4 + +# Setup for reading the raw data +raw = io.read_raw_fif(raw_fname) +events = mne.read_events(event_fname) + +# Set up pick list: EEG + MEG - bad channels (modify to your needs) +raw.info["bads"] = ["MEG 2443", "EEG 053"] + +# Create epochs, here for gradiometers + EOG only for simplicity +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + proj=True, + picks=("grad", "eog"), + baseline=(None, 0), + preload=True, + reject=dict(grad=4000e-13, eog=150e-6), +) + +# %% +# Show event-related fields images + +# and order with spectral reordering +# If you don't have scikit-learn installed set order_func to None +from sklearn.manifold import spectral_embedding # noqa +from sklearn.metrics.pairwise import rbf_kernel # noqa + + +def order_func(times, data): + this_data = data[:, (times > 0.0) & (times < 0.350)] + this_data /= np.sqrt(np.sum(this_data**2, axis=1))[:, np.newaxis] + return np.argsort( + spectral_embedding( + rbf_kernel(this_data, gamma=1.0), n_components=1, random_state=0 + ).ravel() + ) + + +good_pick = 97 # channel with a clear evoked response +bad_pick = 98 # channel with no evoked response + +# We'll also plot a sample time onset for each trial +plt_times = np.linspace(0, 0.2, len(epochs)) + +plt.close("all") +mne.viz.plot_epochs_image( + epochs, + [good_pick, bad_pick], + sigma=0.5, + order=order_func, + vmin=-250, + vmax=250, + overlay_times=plt_times, + show=True, +) + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/visualization/eeg_on_scalp.py b/mne-python/source/examples/visualization/eeg_on_scalp.py new file mode 100644 index 0000000000000000000000000000000000000000..1146ae229ef9471fb8261c3765e86e1c46e423bc --- /dev/null +++ b/mne-python/source/examples/visualization/eeg_on_scalp.py @@ -0,0 +1,42 @@ +""" +.. _ex-eeg-on-scalp: + +================================= +Plotting EEG sensors on the scalp +================================= + +In this example, digitized EEG sensor locations are shown on the scalp surface. +""" +# Author: Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.viz import plot_alignment, set_3d_view + +print(__doc__) + +data_path = mne.datasets.sample.data_path() +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +trans = mne.read_trans(meg_path / "sample_audvis_raw-trans.fif") +raw = mne.io.read_raw_fif(meg_path / "sample_audvis_raw.fif") + +# Plot electrode locations on scalp +fig = plot_alignment( + raw.info, + trans, + subject="sample", + dig=False, + eeg=["original", "projected"], + meg=[], + coord_frame="head", + subjects_dir=subjects_dir, + show_channel_names=True, +) + +# Set viewing angle +set_3d_view(figure=fig, azimuth=135, elevation=80) diff --git a/mne-python/source/examples/visualization/evoked_arrowmap.py b/mne-python/source/examples/visualization/evoked_arrowmap.py new file mode 100644 index 0000000000000000000000000000000000000000..bdad8d4ad79b930a8f53a654017b246f6b4b0dba --- /dev/null +++ b/mne-python/source/examples/visualization/evoked_arrowmap.py @@ -0,0 +1,86 @@ +""" +.. _ex-arrowmap: + +============================================= +Plotting topographic arrowmaps of evoked data +============================================= + +Load evoked data and plot arrowmaps along with the topomap for selected time +points. An arrowmap is based upon the Hosaka-Cohen transformation and +represents an estimation of the current flow underneath the MEG sensors. +They are a poor man's MNE. + +See :footcite:`CohenHosaka1976` for details. + +References +---------- +.. footbibliography:: +""" + +# Authors: Sheraz Khan +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import numpy as np + +import mne +from mne import read_evokeds +from mne.datasets import sample +from mne.datasets.brainstorm import bst_raw +from mne.viz import plot_arrowmap + +print(__doc__) + +path = sample.data_path() +fname = path / "MEG" / "sample" / "sample_audvis-ave.fif" + +# load evoked data +condition = "Left Auditory" +evoked = read_evokeds(fname, condition=condition, baseline=(None, 0)) +evoked_mag = evoked.copy().pick(picks="mag", exclude="bads") +evoked_grad = evoked.copy().pick(picks="grad", exclude="bads") + +# %% +# Plot magnetometer data as an arrowmap along with the topoplot at the time +# of the maximum sensor space activity: +max_time_idx = np.abs(evoked_mag.data).mean(axis=0).argmax() +plot_arrowmap(evoked_mag.data[:, max_time_idx], evoked_mag.info) + +# Since planar gradiometers takes gradients along latitude and longitude, +# they need to be projected to the flatten manifold span by magnetometer +# or radial gradiometers before taking the gradients in the 2D Cartesian +# coordinate system for visualization on the 2D topoplot. You can use the +# ``info_from`` and ``info_to`` parameters to interpolate from +# gradiometer data to magnetometer data. + +# %% +# Plot gradiometer data as an arrowmap along with the topoplot at the time +# of the maximum sensor space activity: +plot_arrowmap( + evoked_grad.data[:, max_time_idx], + info_from=evoked_grad.info, + info_to=evoked_mag.info, +) + +# %% +# Since Vectorview 102 system perform sparse spatial sampling of the magnetic +# field, data from the Vectorview (info_from) can be projected to the high +# density CTF 272 system (info_to) for visualization +# +# Plot gradiometer data as an arrowmap along with the topoplot at the time +# of the maximum sensor space activity: +path = bst_raw.data_path() +raw_fname = path / "MEG" / "bst_raw" / "subj001_somatosensory_20111109_01_AUX-f.ds" +raw_ctf = mne.io.read_raw_ctf(raw_fname) +raw_ctf_info = mne.pick_info( + raw_ctf.info, mne.pick_types(raw_ctf.info, meg=True, ref_meg=False) +) +plot_arrowmap( + evoked_grad.data[:, max_time_idx], + info_from=evoked_grad.info, + info_to=raw_ctf_info, + scale=6e-10, +) diff --git a/mne-python/source/examples/visualization/evoked_topomap.py b/mne-python/source/examples/visualization/evoked_topomap.py new file mode 100644 index 0000000000000000000000000000000000000000..53b7a60dbba3749707bc5374d7a8773da382b587 --- /dev/null +++ b/mne-python/source/examples/visualization/evoked_topomap.py @@ -0,0 +1,195 @@ +""" +.. _ex-evoked-topomap: + +======================================== +Plotting topographic maps of evoked data +======================================== + +Load evoked data and plot topomaps for selected time points using +multiple additional options. +""" +# Authors: Christian Brodbeck +# Tal Linzen +# Denis A. Engeman +# Mikołaj Magnuski +# Eric Larson +# Alex Rockhill +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +# sphinx_gallery_thumbnail_number = 5 + +import matplotlib.pyplot as plt +import numpy as np + +from mne import read_evokeds +from mne.datasets import sample + +print(__doc__) + +path = sample.data_path() +fname = path / "MEG" / "sample" / "sample_audvis-ave.fif" + +# load evoked corresponding to a specific condition +# from the fif file and subtract baseline +condition = "Left Auditory" +evoked = read_evokeds(fname, condition=condition, baseline=(None, 0)) + +# %% +# Basic :func:`~mne.viz.plot_topomap` options +# ------------------------------------------- +# +# We plot evoked topographies using :func:`mne.Evoked.plot_topomap`. The first +# argument, ``times`` allows to specify time instants (in seconds!) for which +# topographies will be shown. We select timepoints from 50 to 150 ms with a +# step of 20ms and plot magnetometer data: +times = np.arange(0.05, 0.151, 0.02) +evoked.plot_topomap(times, ch_type="mag") + +# %% +# If times is set to None at most 10 regularly spaced topographies will be +# shown: +evoked.plot_topomap(ch_type="mag") + +# %% +# We can use ``nrows`` and ``ncols`` parameter to create multiline plots +# with more timepoints. +all_times = np.arange(-0.2, 0.5, 0.03) +evoked.plot_topomap(all_times, ch_type="mag", ncols=8, nrows="auto") + +# %% +# Instead of showing topographies at specific time points we can compute +# averages of 50 ms bins centered on these time points to reduce the noise in +# the topographies: +evoked.plot_topomap(times, ch_type="mag", average=0.05) + +# %% +# We can plot gradiometer data (plots the RMS for each pair of gradiometers) +evoked.plot_topomap(times, ch_type="grad") + +# %% +# Additional :func:`~mne.viz.plot_topomap` options +# ------------------------------------------------ +# +# We can also use a range of various :func:`mne.viz.plot_topomap` arguments +# that control how the topography is drawn. For example: +# +# * ``cmap`` - to specify the color map +# * ``res`` - to control the resolution of the topographies (lower resolution +# means faster plotting) +# * ``contours`` to define how many contour lines should be plotted +evoked.plot_topomap(times, ch_type="mag", cmap="Spectral_r", res=32, contours=4) + +# %% +# If you look at the edges of the head circle of a single topomap you'll see +# the effect of extrapolation. There are three extrapolation modes: +# +# - ``extrapolate='local'`` extrapolates only to points close to the sensors. +# - ``extrapolate='head'`` extrapolates out to the head circle. +# - ``extrapolate='box'`` extrapolates to a large box stretching beyond the +# head circle. +# +# The default value ``extrapolate='auto'`` will use ``'local'`` for MEG sensors +# and ``'head'`` otherwise. Here we show each option: + +extrapolations = ["local", "head", "box"] +fig, axes = plt.subplots(figsize=(7.5, 4.5), nrows=2, ncols=3, layout="constrained") + +# Here we look at EEG channels, and use a custom head sphere to get all the +# sensors to be well within the drawn head surface +for axes_row, ch_type in zip(axes, ("mag", "eeg")): + for ax, extr in zip(axes_row, extrapolations): + evoked.plot_topomap( + 0.1, + ch_type=ch_type, + size=2, + extrapolate=extr, + axes=ax, + show=False, + colorbar=False, + sphere=(0.0, 0.0, 0.0, 0.09), + ) + ax.set_title(f"{ch_type.upper()} {extr}", fontsize=14) + +# %% +# More advanced usage +# ------------------- +# +# Now we plot magnetometer data as topomap at a single time point: 100 ms +# post-stimulus, add channel labels, title and adjust plot margins: + +fig = evoked.plot_topomap( + 0.1, ch_type="mag", show_names=True, colorbar=False, size=6, res=128 +) +fig.suptitle("Auditory response") + +# %% +# We can also highlight specific channels by adding a mask, to e.g. mark +# channels exceeding a threshold at a given time: + +# Define a threshold and create the mask +mask = evoked.data > 1e-13 + +# Select times and plot +times = (0.09, 0.1, 0.11) +mask_params = dict(markersize=10, markerfacecolor="y") +evoked.plot_topomap(times, ch_type="mag", mask=mask, mask_params=mask_params) + +# %% +# Or by manually picking the channels to highlight at different times: + +times = (0.09, 0.1, 0.11) +_times = ((np.abs(evoked.times - t)).argmin() for t in times) +significant_channels = [ + ("MEG 0231", "MEG 1611", "MEG 1621", "MEG 1631", "MEG 1811"), + ("MEG 2411", "MEG 2421"), + ("MEG 1621"), +] +_channels = [np.isin(evoked.ch_names, ch) for ch in significant_channels] + +mask = np.zeros(evoked.data.shape, dtype="bool") +for _chs, _time in zip(_channels, _times): + mask[_chs, _time] = True + +evoked.plot_topomap(times, ch_type="mag", mask=mask, mask_params=mask_params) + +# %% +# Interpolating topomaps +# ---------------------- +# We can also look at the effects of interpolating our data. Perhaps, we +# might have data per channel such as the impedance of each electrode that +# we don't want interpolated, or we just want to visualize the data without +# interpolation as a sanity check. We can use ``image_interp='nearest'`` to +# prevent any interpolation or ``image_interp='linear'`` to do a linear +# interpolation instead of the default cubic interpolation. + +# %% +# The default cubic interpolation is the smoothest and is great for +# publications. + +evoked.plot_topomap(times, ch_type="eeg", image_interp="cubic") + +# %% +# The linear interpolation might be helpful in some cases. + +evoked.plot_topomap(times, ch_type="eeg", image_interp="linear") + +# %% +# The nearest (Voronoi, no interpolation) interpolation is especially helpful +# for debugging and seeing the values assigned to the topomap unaltered. + +evoked.plot_topomap(times, ch_type="eeg", image_interp="nearest", contours=0) + +# %% +# Animating the topomap +# --------------------- +# +# Instead of using a still image we can plot magnetometer data as an animation, +# which animates properly only in matplotlib interactive mode. + +# sphinx_gallery_thumbnail_number = 9 +times = np.arange(0.05, 0.151, 0.01) +fig, anim = evoked.animate_topomap(times=times, ch_type="mag", frame_rate=2, blit=False) diff --git a/mne-python/source/examples/visualization/evoked_whitening.py b/mne-python/source/examples/visualization/evoked_whitening.py new file mode 100644 index 0000000000000000000000000000000000000000..4bcb4bc8c049af6d6b86e3d6cf08e55de5527365 --- /dev/null +++ b/mne-python/source/examples/visualization/evoked_whitening.py @@ -0,0 +1,106 @@ +""" +.. _ex-evoked-whitening: + +============================================= +Whitening evoked data with a noise covariance +============================================= + +Evoked data are loaded and then whitened using a given noise covariance +matrix. It's an excellent quality check to see if baseline signals match +the assumption of Gaussian white noise during the baseline period. + +Covariance estimation and diagnostic plots are based on +:footcite:`EngemannGramfort2015`. + +References +---------- +.. footbibliography:: +""" + +# Authors: Alexandre Gramfort +# Denis A. Engemann +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne import io +from mne.cov import compute_covariance +from mne.datasets import sample + +print(__doc__) + +# %% +# Set parameters + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" + +raw = io.read_raw_fif(raw_fname, preload=True) +raw.filter(1, 40, fir_design="firwin") +raw.info["bads"] += ["MEG 2443"] # bads + 1 more +events = mne.read_events(event_fname) + +# let's look at rare events, button presses +event_id, tmin, tmax = 2, -0.2, 0.5 +reject = dict(mag=4e-12, grad=4000e-13, eeg=80e-6) + +epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=("meg", "eeg"), + baseline=None, + reject=reject, + preload=True, +) + +# Uncomment next line to use fewer samples and study regularization effects +# epochs = epochs[:20] # For your data, use as many samples as you can! + +# %% +# Compute covariance using automated regularization +method_params = dict(diagonal_fixed=dict(mag=0.01, grad=0.01, eeg=0.01)) +noise_covs = compute_covariance( + epochs, + tmin=None, + tmax=0, + method="auto", + return_estimators=True, + n_jobs=None, + projs=None, + rank=None, + method_params=method_params, + verbose=True, +) + +# With "return_estimator=True" all estimated covariances sorted +# by log-likelihood are returned. + +print("Covariance estimates sorted from best to worst") +for c in noise_covs: + print(f"{c['method']} : {c['loglik']}") + +# %% +# Show the evoked data: + +evoked = epochs.average() + +evoked.plot(time_unit="s") # plot evoked response + +# %% +# We can then show whitening for our various noise covariance estimates. +# +# Here we should look to see if baseline signals match the +# assumption of Gaussian white noise. we expect values centered at +# 0 within 2 standard deviations for 95% of the time points. +# +# For the Global field power we expect a value of 1. + +evoked.plot_white(noise_covs, time_unit="s") diff --git a/mne-python/source/examples/visualization/eyetracking_plot_heatmap.py b/mne-python/source/examples/visualization/eyetracking_plot_heatmap.py new file mode 100644 index 0000000000000000000000000000000000000000..07983685b5eb5dc27a6c981996672698b3823c2b --- /dev/null +++ b/mne-python/source/examples/visualization/eyetracking_plot_heatmap.py @@ -0,0 +1,112 @@ +""" +.. _tut-eyetrack-heatmap: + +============================================= +Plotting eye-tracking heatmaps in MNE-Python +============================================= + +This tutorial covers plotting eye-tracking position data as a heatmap. + +.. seealso:: + + :ref:`tut-importing-eyetracking-data` + :ref:`tut-eyetrack` + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% +# Data loading +# ------------ +# +# As usual we start by importing the modules we need and loading some +# :ref:`example data `: eye-tracking data recorded from SR research's +# ``'.asc'`` file format. + +import matplotlib.pyplot as plt + +import mne +from mne.viz.eyetracking import plot_gaze + +task_fpath = mne.datasets.eyelink.data_path() / "freeviewing" +et_fpath = task_fpath / "sub-01_task-freeview_eyetrack.asc" +stim_fpath = task_fpath / "stim" / "naturalistic.png" + +raw = mne.io.read_raw_eyelink(et_fpath) +calibration = mne.preprocessing.eyetracking.read_eyelink_calibration( + et_fpath, + screen_resolution=(1920, 1080), + screen_size=(0.53, 0.3), + screen_distance=0.9, +)[0] + +# %% +# Process and epoch the data +# -------------------------- +# +# First we will interpolate missing data during blinks and epoch the data. + +mne.preprocessing.eyetracking.interpolate_blinks(raw, interpolate_gaze=True) +raw.annotations.rename({"dvns": "natural"}) # more intuitive + +epochs = mne.Epochs(raw, event_id=["natural"], tmin=0, tmax=20, baseline=None) + + +# %% +# Plot a heatmap of the eye-tracking data +# --------------------------------------- +# +# To make a heatmap of the eye-tracking data, we can use the function +# :func:`~mne.viz.eyetracking.plot_gaze`. We will need to define the dimensions of our +# canvas; for this file, the eye position data are reported in pixels, so we'll use the +# screen resolution of the participant screen (1920x1080) as the width and height. We +# can also use the sigma parameter to smooth the plot. + +cmap = plt.get_cmap("viridis") +plot_gaze(epochs["natural"], calibration=calibration, cmap=cmap, sigma=50) + +# %% +# .. note:: The (0, 0) pixel coordinates are at the top-left of the +# trackable area of the screen for many eye trackers. + +# %% +# Overlaying plots with images +# ---------------------------- +# +# We can use matplotlib to plot gaze heatmaps on top of stimuli images. We'll +# customize a :class:`~matplotlib.colors.Colormap` to make some values of the heatmap +# completely transparent. We'll then use the ``vlim`` parameter to force the heatmap to +# start at a value greater than the darkest value in our previous heatmap, which will +# make the darkest colors of the heatmap transparent. + +cmap.set_under("k", alpha=0) # make the lowest values transparent +ax = plt.subplot() +ax.imshow(plt.imread(stim_fpath)) +plot_gaze( + epochs["natural"], + calibration=calibration, + vlim=(0.0003, None), + sigma=50, + cmap=cmap, + axes=ax, +) + +# %% +# Displaying the heatmap in units of visual angle +# ----------------------------------------------- +# +# In scientific publications it is common to report gaze data as the visual angle +# from the participants eye to the screen. We can convert the units of our gaze data to +# radians of visual angle before plotting the heatmap: + +# %% +epochs.load_data() +mne.preprocessing.eyetracking.convert_units(epochs, calibration, to="radians") +plot_gaze( + epochs["natural"], + calibration=calibration, + sigma=50, +) diff --git a/mne-python/source/examples/visualization/meg_sensors.py b/mne-python/source/examples/visualization/meg_sensors.py new file mode 100644 index 0000000000000000000000000000000000000000..182a8ee894072dc33f00b4bdd50ad4dc789beb08 --- /dev/null +++ b/mne-python/source/examples/visualization/meg_sensors.py @@ -0,0 +1,86 @@ +""" +.. _ex-plot-meg-sensors: + +====================================== +Plotting sensor layouts of MEG systems +====================================== + +Show sensor layouts of different MEG systems. +""" +# Author: Eric Larson +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +from pathlib import Path + +import mne +from mne.datasets import sample, spm_face, testing +from mne.io import ( + read_raw_artemis123, + read_raw_bti, + read_raw_ctf, + read_raw_fif, + read_raw_kit, +) +from mne.viz import plot_alignment, set_3d_title + +print(__doc__) + +root_path = Path(mne.__file__).parent.absolute() + +# %% +# Neuromag +# -------- + +kwargs = dict(eeg=False, coord_frame="meg", show_axes=True, verbose=True) + +raw = read_raw_fif(sample.data_path() / "MEG" / "sample" / "sample_audvis_raw.fif") +fig = plot_alignment(raw.info, meg=("helmet", "sensors"), **kwargs) +set_3d_title(figure=fig, title="Neuromag") + +# %% +# CTF +# --- + +raw = read_raw_ctf( + spm_face.data_path() / "MEG" / "spm" / "SPM_CTF_MEG_example_faces1_3D.ds" +) +fig = plot_alignment(raw.info, meg=("helmet", "sensors", "ref"), **kwargs) +set_3d_title(figure=fig, title="CTF 275") + +# %% +# BTi +# --- + +bti_path = root_path / "io" / "bti" / "tests" / "data" +raw = read_raw_bti( + bti_path / "test_pdf_linux", + bti_path / "test_config_linux", + bti_path / "test_hs_linux", +) +fig = plot_alignment(raw.info, meg=("helmet", "sensors", "ref"), **kwargs) +set_3d_title(figure=fig, title="Magnes 3600wh") + +# %% +# KIT +# --- + +kit_path = root_path / "io" / "kit" / "tests" / "data" +raw = read_raw_kit(kit_path / "test.sqd") +fig = plot_alignment(raw.info, meg=("helmet", "sensors"), **kwargs) +set_3d_title(figure=fig, title="KIT") + +# %% +# Artemis123 +# ---------- + +raw = read_raw_artemis123( + testing.data_path() + / "ARTEMIS123" + / "Artemis_Data_2017-04-14-10h-38m-59s_Phantom_1k_HPI_1s.bin" +) +fig = plot_alignment(raw.info, meg=("helmet", "sensors", "ref"), **kwargs) +set_3d_title(figure=fig, title="Artemis123") diff --git a/mne-python/source/examples/visualization/mne_helmet.py b/mne-python/source/examples/visualization/mne_helmet.py new file mode 100644 index 0000000000000000000000000000000000000000..ceb149d77ba6c365758fac13cfa87696c6188b58 --- /dev/null +++ b/mne-python/source/examples/visualization/mne_helmet.py @@ -0,0 +1,69 @@ +""" +.. _ex-mne-helmet: + +============================= +Plot the MNE brain and helmet +============================= + +This tutorial shows how to make the MNE helmet + brain image. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne + +sample_path = mne.datasets.sample.data_path() +subjects_dir = sample_path / "subjects" +fname_evoked = sample_path / "MEG" / "sample" / "sample_audvis-ave.fif" +fname_inv = sample_path / "MEG" / "sample" / "sample_audvis-meg-oct-6-meg-inv.fif" +fname_trans = sample_path / "MEG" / "sample" / "sample_audvis_raw-trans.fif" +inv = mne.minimum_norm.read_inverse_operator(fname_inv) +evoked = mne.read_evokeds( + fname_evoked, + baseline=(None, 0), + proj=True, + verbose=False, + condition="Left Auditory", +) +maps = mne.make_field_map( + evoked, + trans=fname_trans, + ch_type="meg", + subject="sample", + subjects_dir=subjects_dir, + upsampling=2, + origin="auto", +) +time = 0.083 +fig = mne.viz.create_3d_figure((512, 512), bgcolor="w", title="MNE helmet") +mne.viz.plot_alignment( + evoked.info, + subject="sample", + subjects_dir=subjects_dir, + fig=fig, + trans=fname_trans, + meg="sensors", + eeg=False, + surfaces="pial", + coord_frame="mri", +) +evoked.plot_field( + maps, + time=time, + fig=fig, + time_label=None, + vmax=5e-13, + time_viewer=False, +) +mne.viz.set_3d_view( + fig, + azimuth=40, + elevation=87, + focalpoint=(0.0, -0.01, 0.04), + roll=-105, + distance=0.55, +) diff --git a/mne-python/source/examples/visualization/montage_sgskip.py b/mne-python/source/examples/visualization/montage_sgskip.py new file mode 100644 index 0000000000000000000000000000000000000000..b3d0524785513a25a0da04938f2c15673f9f6d69 --- /dev/null +++ b/mne-python/source/examples/visualization/montage_sgskip.py @@ -0,0 +1,71 @@ +""" +.. _plot_montage: + +Plotting sensor layouts of EEG systems +====================================== + +This example illustrates how to load all the EEG system montages +shipped in MNE-python, and display it on the fsaverage template subject. +""" # noqa: D205, D400 +# Authors: Alexandre Gramfort +# Joan Massich +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import os.path as op + +import numpy as np + +import mne +from mne.channels.montage import get_builtin_montages +from mne.datasets import fetch_fsaverage +from mne.viz import set_3d_title, set_3d_view + +# %% +# Check all montages against a sphere + +for current_montage in get_builtin_montages(): + montage = mne.channels.make_standard_montage(current_montage) + info = mne.create_info(ch_names=montage.ch_names, sfreq=100.0, ch_types="eeg") + info.set_montage(montage) + sphere = mne.make_sphere_model(r0="auto", head_radius="auto", info=info) + fig = mne.viz.plot_alignment( + # Plot options + show_axes=True, + dig="fiducials", + surfaces="head", + trans=mne.Transform("head", "mri", trans=np.eye(4)), # identity + bem=sphere, + info=info, + ) + set_3d_view(figure=fig, azimuth=135, elevation=80) + set_3d_title(figure=fig, title=current_montage) + + +# %% +# Check all montages against fsaverage + +subjects_dir = op.dirname(fetch_fsaverage()) + +for current_montage in get_builtin_montages(): + montage = mne.channels.make_standard_montage(current_montage) + # Create dummy info + info = mne.create_info(ch_names=montage.ch_names, sfreq=100.0, ch_types="eeg") + info.set_montage(montage) + fig = mne.viz.plot_alignment( + # Plot options + show_axes=True, + dig="fiducials", + surfaces="head", + mri_fiducials=True, + subject="fsaverage", + subjects_dir=subjects_dir, + info=info, + coord_frame="mri", + trans="fsaverage", # transform from head coords to fsaverage's MRI + ) + set_3d_view(figure=fig, azimuth=135, elevation=80) + set_3d_title(figure=fig, title=current_montage) diff --git a/mne-python/source/examples/visualization/parcellation.py b/mne-python/source/examples/visualization/parcellation.py new file mode 100644 index 0000000000000000000000000000000000000000..d92a849b970032c8b37b9e6c5838abced831b1dc --- /dev/null +++ b/mne-python/source/examples/visualization/parcellation.py @@ -0,0 +1,86 @@ +""" +.. _ex-parcellation: + +============================ +Plot a cortical parcellation +============================ + +In this example, we download the HCP-MMP1.0 parcellation +:footcite:`GlasserEtAl2016` and show it on ``fsaverage``. +We will also download the customized 448-label aparc +parcellation from :footcite:`KhanEtAl2018`. + +.. note:: The HCP-MMP dataset has license terms restricting its use. + Of particular relevance: + + "I will acknowledge the use of WU-Minn HCP data and data + derived from WU-Minn HCP data when publicly presenting any + results or algorithms that benefitted from their use." + +""" +# Author: Eric Larson +# Denis Engemann +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne + +Brain = mne.viz.get_brain_class() + +subjects_dir = mne.datasets.sample.data_path() / "subjects" +mne.datasets.fetch_hcp_mmp_parcellation(subjects_dir=subjects_dir, verbose=True) + +mne.datasets.fetch_aparc_sub_parcellation(subjects_dir=subjects_dir, verbose=True) + +labels = mne.read_labels_from_annot( + "fsaverage", "HCPMMP1", "lh", subjects_dir=subjects_dir +) + +brain = Brain( + "fsaverage", + "lh", + "inflated", + subjects_dir=subjects_dir, + cortex="low_contrast", + background="white", + size=(800, 600), +) +brain.add_annotation("HCPMMP1") +aud_label = [label for label in labels if label.name == "L_A1_ROI-lh"][0] +brain.add_label(aud_label, borders=False) + +# %% +# We can also plot a combined set of labels (23 per hemisphere). + +brain = Brain( + "fsaverage", + "lh", + "inflated", + subjects_dir=subjects_dir, + cortex="low_contrast", + background="white", + size=(800, 600), +) +brain.add_annotation("HCPMMP1_combined") + +# %% +# We can add another custom parcellation + +brain = Brain( + "fsaverage", + "lh", + "inflated", + subjects_dir=subjects_dir, + cortex="low_contrast", + background="white", + size=(800, 600), +) +brain.add_annotation("aparc_sub") + +# %% +# References +# ---------- +# .. footbibliography:: diff --git a/mne-python/source/examples/visualization/roi_erpimage_by_rt.py b/mne-python/source/examples/visualization/roi_erpimage_by_rt.py new file mode 100644 index 0000000000000000000000000000000000000000..f9cd9f708cfeccdf44d74e95306890f20eaa8a1c --- /dev/null +++ b/mne-python/source/examples/visualization/roi_erpimage_by_rt.py @@ -0,0 +1,122 @@ +""" +.. _roi-erp: + +=========================================================== +Plot single trial activity, grouped by ROI and sorted by RT +=========================================================== + +This will produce what is sometimes called an event related +potential / field (ERP/ERF) image. + +The EEGLAB example file, which contains an experiment with button press +responses to simple visual stimuli, is read in and response times are calculated. +Regions of Interest are determined by the channel types (in 10/20 channel +notation, even channels are right, odd are left, and 'z' are central). The +median and the Global Field Power within each channel group is calculated, +and the trials are plotted, sorting by response time. +""" +# Authors: Jona Sassenhagen +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne +from mne.channels import make_1020_channel_selections +from mne.event import define_target_events + +print(__doc__) + +# %% +# Load EEGLAB example data (a small EEG dataset) +data_path = mne.datasets.testing.data_path() +fname = data_path / "EEGLAB" / "test_raw.set" + +event_id = {"rt": 1, "square": 2} # must be specified for str events +raw = mne.io.read_raw_eeglab(fname) + +mapping = { + "EEG 000": "Fpz", + "EEG 001": "EOG1", + "EEG 002": "F3", + "EEG 003": "Fz", + "EEG 004": "F4", + "EEG 005": "EOG2", + "EEG 006": "FC5", + "EEG 007": "FC1", + "EEG 008": "FC2", + "EEG 009": "FC6", + "EEG 010": "T7", + "EEG 011": "C3", + "EEG 012": "C4", + "EEG 013": "Cz", + "EEG 014": "T8", + "EEG 015": "CP5", + "EEG 016": "CP1", + "EEG 017": "CP2", + "EEG 018": "CP6", + "EEG 019": "P7", + "EEG 020": "P3", + "EEG 021": "Pz", + "EEG 022": "P4", + "EEG 023": "P8", + "EEG 024": "PO7", + "EEG 025": "PO3", + "EEG 026": "POz", + "EEG 027": "PO4", + "EEG 028": "PO8", + "EEG 029": "O1", + "EEG 030": "Oz", + "EEG 031": "O2", +} +raw.rename_channels(mapping) +raw.set_channel_types({"EOG1": "eog", "EOG2": "eog"}) +raw.set_montage("standard_1020") + +events = mne.events_from_annotations(raw, event_id)[0] + +# %% +# Create Epochs + +# define target events: +# 1. find response times: distance between "square" and "rt" events +# 2. extract A. "square" events B. followed by a button press within 700 msec +tmax = 0.7 +sfreq = raw.info["sfreq"] +reference_id, target_id = 2, 1 +new_events, rts = define_target_events( + events, reference_id, target_id, sfreq, tmin=0.0, tmax=tmax, new_id=2 +) + +epochs = mne.Epochs(raw, events=new_events, tmax=tmax + 0.1, event_id={"square": 2}) + +# %% +# Plot using :term:`global field power` + +# Parameters for plotting +order = rts.argsort() # sorting from fast to slow trials + +selections = make_1020_channel_selections(epochs.info, midline="12z") + +# The actual plots (GFP) +epochs.plot_image( + group_by=selections, + order=order, + sigma=1.5, + overlay_times=rts / 1000.0, + combine="gfp", + ts_args=dict(vlines=[0, rts.mean() / 1000.0]), +) + +# %% +# Plot using median + +epochs.plot_image( + group_by=selections, + order=order, + sigma=1.5, + overlay_times=rts / 1000.0, + combine="median", + ts_args=dict(vlines=[0, rts.mean() / 1000.0]), +) diff --git a/mne-python/source/examples/visualization/ssp_projs_sensitivity_map.py b/mne-python/source/examples/visualization/ssp_projs_sensitivity_map.py new file mode 100644 index 0000000000000000000000000000000000000000..65a96cd9908e5e545754b8d089c83be45871ae56 --- /dev/null +++ b/mne-python/source/examples/visualization/ssp_projs_sensitivity_map.py @@ -0,0 +1,53 @@ +""" +.. _ex-ssp-proj: + +================================== +Sensitivity map of SSP projections +================================== + +This example shows the sources that have a forward field +similar to the first SSP vector correcting for ECG. +""" +# Author: Alexandre Gramfort +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +from mne import read_forward_solution, read_proj, sensitivity_map +from mne.datasets import sample + +print(__doc__) + +data_path = sample.data_path() + +subjects_dir = data_path / "subjects" +meg_path = data_path / "MEG" / "sample" +fname = meg_path / "sample_audvis-meg-eeg-oct-6-fwd.fif" +ecg_fname = meg_path / "sample_audvis_ecg-proj.fif" + +fwd = read_forward_solution(fname) + +projs = read_proj(ecg_fname) +# take only one projection per channel type +projs = projs[::2] + +# Compute sensitivity map +ssp_ecg_map = sensitivity_map(fwd, ch_type="grad", projs=projs, mode="angle") + +# %% +# Show sensitivity map + +plt.hist(ssp_ecg_map.data.ravel()) +plt.show() + +args = dict( + clim=dict(kind="value", lims=(0.2, 0.6, 1.0)), + smoothing_steps=7, + hemi="rh", + subjects_dir=subjects_dir, +) +ssp_ecg_map.plot(subject="sample", time_label="ECG SSP sensitivity", **args) diff --git a/mne-python/source/examples/visualization/topo_compare_conditions.py b/mne-python/source/examples/visualization/topo_compare_conditions.py new file mode 100644 index 0000000000000000000000000000000000000000..eb2699eb262097f85fd06e1990fdb0715892c698 --- /dev/null +++ b/mne-python/source/examples/visualization/topo_compare_conditions.py @@ -0,0 +1,64 @@ +""" +.. _ex-topo-compare: + +================================================= +Compare evoked responses for different conditions +================================================= + +In this example, an Epochs object for visual and auditory responses is created. +Both conditions are then accessed by their respective names to create a sensor +layout plot of the related evoked responses. + +""" + +# Authors: Denis Engemann +# Alexandre Gramfort + +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt + +import mne +from mne.datasets import sample +from mne.viz import plot_evoked_topo + +print(__doc__) + +data_path = sample.data_path() + +# %% +# Set parameters. +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" +event_fname = meg_path / "sample_audvis_filt-0-40_raw-eve.fif" +tmin = -0.2 +tmax = 0.5 + +# Setup for reading the raw data. +raw = mne.io.read_raw_fif(raw_fname) +events = mne.read_events(event_fname) + +# Set up amplitude-peak rejection values for MEG channels. +reject = dict(grad=4000e-13, mag=4e-12) + +# Create epochs including different events. +event_id = {"audio/left": 1, "audio/right": 2, "visual/left": 3, "visual/right": 4} +epochs = mne.Epochs( + raw, events, event_id, tmin, tmax, picks="meg", baseline=(None, 0), reject=reject +) + +# Generate list of evoked objects from conditions names +evokeds = [epochs[name].average() for name in ("left", "right")] + +# %% +# Show topography for two different conditions. + +colors = "blue", "red" +title = "MNE sample data\nleft vs right (A/V combined)" + +plot_evoked_topo(evokeds, color=colors, title=title, background_color="w") + +plt.show() diff --git a/mne-python/source/examples/visualization/topo_customized.py b/mne-python/source/examples/visualization/topo_customized.py new file mode 100644 index 0000000000000000000000000000000000000000..2303961f9da4db23e712fea6041afdcfd4633842 --- /dev/null +++ b/mne-python/source/examples/visualization/topo_customized.py @@ -0,0 +1,70 @@ +""" +.. _ex-topo-custom: + +======================================== +Plot custom topographies for MEG sensors +======================================== + +This example exposes the :func:`~mne.viz.iter_topography` function that makes +it very easy to generate custom sensor topography plots. +Here we will plot the power spectrum of each channel on a topographic +layout. + +""" + +# Author: Denis A. Engemann +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import matplotlib.pyplot as plt +import numpy as np + +import mne +from mne import io +from mne.datasets import sample +from mne.viz import iter_topography + +print(__doc__) + +data_path = sample.data_path() +meg_path = data_path / "MEG" / "sample" +raw_fname = meg_path / "sample_audvis_filt-0-40_raw.fif" + +raw = io.read_raw_fif(raw_fname, preload=True) +raw.filter(1, 20, fir_design="firwin") + +picks = mne.pick_types(raw.info, meg=True, exclude=[]) +tmin, tmax = 0, 120 # use the first 120s of data +fmin, fmax = 2, 20 # look at frequencies between 2 and 20Hz +n_fft = 2048 # the FFT size (n_fft). Ideally a power of 2 +spectrum = raw.compute_psd(picks=picks, tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax) +psds, freqs = spectrum.get_data(exclude=(), return_freqs=True) +psds = 20 * np.log10(psds) # scale to dB + + +def my_callback(ax, ch_idx): + """Handle axes callback. + + This block of code is executed once you click on one of the channel axes + in the plot. To work with the viz internals, this function should only take + two parameters, the axis and the channel or data index. + """ + ax.plot(freqs, psds[ch_idx], color="red") + ax.set_xlabel("Frequency (Hz)") + ax.set_ylabel("Power (dB)") + + +for ax, idx in iter_topography( + raw.info, + fig_facecolor="white", + axis_facecolor="white", + axis_spinecolor="white", + on_pick=my_callback, +): + ax.plot(psds[idx], color="red") + +plt.gcf().suptitle("Power spectral densities") +plt.show() diff --git a/mne-python/source/examples/visualization/xhemi.py b/mne-python/source/examples/visualization/xhemi.py new file mode 100644 index 0000000000000000000000000000000000000000..e0974a30a580decbc8333931e5e1a7890ef06ce9 --- /dev/null +++ b/mne-python/source/examples/visualization/xhemi.py @@ -0,0 +1,50 @@ +""" +.. _ex-xhemi: + +=========================== +Cross-hemisphere comparison +=========================== + +This example illustrates how to visualize the difference between activity in +the left and the right hemisphere. The data from the right hemisphere is +mapped to the left hemisphere, and then the difference is plotted. For more +information see :func:`mne.compute_source_morph`. +""" +# Author: Christian Brodbeck +# +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# %% + +import mne + +data_dir = mne.datasets.sample.data_path() +subjects_dir = data_dir / "subjects" +stc_path = data_dir / "MEG" / "sample" / "sample_audvis-meg-eeg" +stc = mne.read_source_estimate(stc_path, "sample") + +# First, morph the data to fsaverage_sym, for which we have left_right +# registrations: +stc = mne.compute_source_morph( + stc, "sample", "fsaverage_sym", smooth=5, warn=False, subjects_dir=subjects_dir +).apply(stc) + +# Compute a morph-matrix mapping the right to the left hemisphere, +# and vice-versa. +morph = mne.compute_source_morph( + stc, + "fsaverage_sym", + "fsaverage_sym", + spacing=stc.vertices, + warn=False, + subjects_dir=subjects_dir, + xhemi=True, + verbose="error", +) # creating morph map +stc_xhemi = morph.apply(stc) + +# Now we can subtract them and plot the result: +diff = stc - stc_xhemi + +diff.plot(hemi="lh", subjects_dir=subjects_dir, initial_time=0.07, size=(800, 600)) diff --git a/mne-python/source/ignore_words.txt b/mne-python/source/ignore_words.txt new file mode 100644 index 0000000000000000000000000000000000000000..12e1a14ae0e33ec96ea7cf0ec3aaab4aae4e2706 --- /dev/null +++ b/mne-python/source/ignore_words.txt @@ -0,0 +1,45 @@ +ons +fro +ang +als +dur +sinc +wan +reord +iff +numer +uint +# for tempita +nd +cas +thes +ba +bu +ist +od +fo +files' +ser +vas +coo +hist +datas +dof +nwe +sherif +master +nin +trough +recuse +ro +nam +shs +pres +aas +vor +connec +sme +tim +whitelists +gotcha +uner diff --git a/mne-python/source/logo/LICENSE b/mne-python/source/logo/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..c7df3056667a30f8a49b412baba10ba44ddfeeaa --- /dev/null +++ b/mne-python/source/logo/LICENSE @@ -0,0 +1,397 @@ +Attribution 4.0 International + +Copyright © 2022, MNE-Python Contributors + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. diff --git a/mne-python/source/logo/README.md b/mne-python/source/logo/README.md new file mode 100644 index 0000000000000000000000000000000000000000..197987827cfdd958140467c382c3890fd3764e4d --- /dev/null +++ b/mne-python/source/logo/README.md @@ -0,0 +1,15 @@ +# MNE-Python logos + +The following logos used for MNE-Python are made available under a +[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/) +license, see the [LICENSE](./LICENSE) file in this directory: + +- The main MNE-Python logo: [mne_logo.svg](../doc/_static/mne_logo.svg) +- The hexagonal version of the MNE-Python logo: [logo_hex.svg](./logo_hex.svg) +- The small form of the MNE-Python logo: [mne_logo_small.svg](../doc/_static/mne_logo_small.svg) +- The MNE-Python "helmet": [mne_helmet.png](../doc/_static/mne_helmet.png) +- The MNE-Python "helmet" thumbnail: [favicon.ico](../doc/_static/favicon.ico) + +See also the code to create some of these logos: + +- [generate_mne_logos.py](./generate_mne_logos.py) diff --git a/mne-python/source/logo/generate_mne_logos.py b/mne-python/source/logo/generate_mne_logos.py new file mode 100644 index 0000000000000000000000000000000000000000..3dbca9918aad3125d22845daf93d9011e7f3401b --- /dev/null +++ b/mne-python/source/logo/generate_mne_logos.py @@ -0,0 +1,269 @@ +"""Generate the MNE-Python logos.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import pathlib + +import matplotlib.pyplot as plt +import numpy as np +from matplotlib import font_manager, rcParams +from matplotlib.colors import LinearSegmentedColormap +from matplotlib.patches import Ellipse, FancyBboxPatch, PathPatch, Rectangle +from matplotlib.path import Path +from matplotlib.text import TextPath +from scipy.stats import multivariate_normal + +# manually set values +dpi = 300 +center_fudge = np.array([15, 30]) # compensate for font bounding box padding +tagline_scale_fudge = 0.97 # to get justification right +tagline_offset_fudge = np.array([0, -100.0]) + +# font, etc (default to MNE font) +rcp = { + "font.sans-serif": ["Primetime"], + "font.style": "normal", + "font.weight": "black", + "font.variant": "normal", + "figure.dpi": dpi, + "savefig.dpi": dpi, + "contour.negative_linestyle": "solid", +} +plt.rcdefaults() +rcParams.update(rcp) + +# %% +# mne_logo.svg and mne_logo_dark.svg + +# initialize figure (no axes, margins, etc) +fig = plt.figure(1, figsize=(5, 2.25), frameon=False, dpi=dpi) +ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0]) +ax.set_axis_off() +fig.add_axes(ax) + +# fake field data +delta = 0.01 +x = np.arange(-8.0, 8.0, delta) +y = np.arange(-3.0, 3.0, delta) +X, Y = np.meshgrid(x, y) +xy = np.array([X, Y]).transpose(1, 2, 0) +Z1 = multivariate_normal.pdf( + xy, mean=[-5.0, 0.9], cov=np.array([[8.0, 1.0], [1.0, 7.0]]) ** 2 +) +Z2 = multivariate_normal.pdf( + xy, mean=[2.6, -2.5], cov=np.array([[15.0, 2.5], [2.5, 2.5]]) ** 2 +) +Z = Z2 - 0.7 * Z1 + +# color map: field gradient (yellow-red-gray-blue-cyan) +# yrtbc = { +# 'red': ((0, 1, 1), (0.4, 1, 1), (0.5, 0.5, 0.5), (0.6, 0, 0), (1, 0, 0)), +# 'blue': ((0, 0, 0), (0.4, 0, 0), (0.5, 0.5, 0.5), (0.6, 1, 1), (1, 1, 1)), # noqa +# 'green': ((0, 1, 1), (0.4, 0, 0), (0.5, 0.5, 0.5), (0.6, 0, 0), (1, 1, 1)), # noqa +# } +yrtbc = { + "red": ((0.0, 1.0, 1.0), (0.5, 1.0, 0.0), (1.0, 0.0, 0.0)), + "blue": ((0.0, 0.0, 0.0), (0.5, 0.0, 1.0), (1.0, 1.0, 1.0)), + "green": ((0.0, 1.0, 1.0), (0.5, 0.0, 0.0), (1.0, 1.0, 1.0)), + "alpha": ( + (0.0, 1.0, 1.0), + (0.4, 0.8, 0.8), + (0.5, 0.2, 0.2), + (0.6, 0.8, 0.8), + (1.0, 1.0, 1.0), + ), +} +# color map: field lines (red | blue) +redbl = { + "red": ((0.0, 1.0, 1.0), (0.5, 1.0, 0.0), (1.0, 0.0, 0.0)), + "blue": ((0.0, 0.0, 0.0), (0.5, 0.0, 1.0), (1.0, 1.0, 1.0)), + "green": ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)), + "alpha": ((0.0, 0.4, 0.4), (1.0, 0.4, 0.4)), +} +mne_field_grad_cols = LinearSegmentedColormap("mne_grad", yrtbc) +mne_field_line_cols = LinearSegmentedColormap("mne_line", redbl) + +# plot gradient and contour lines +im = ax.imshow(Z, cmap=mne_field_grad_cols, aspect="equal", zorder=1) +cs = ax.contour(Z, 9, cmap=mne_field_line_cols, linewidths=1, zorder=1) +xlim, ylim = ax.get_xbound(), ax.get_ybound() +plot_dims = np.r_[np.diff(xlim), np.diff(ylim)] +rect = Rectangle( + [xlim[0], ylim[0]], plot_dims[0], plot_dims[1], facecolor="w", zorder=0.5 +) + +# create MNE clipping mask +mne_path = TextPath((0, 0), "MNE") +dims = mne_path.vertices.max(0) - mne_path.vertices.min(0) +vert = mne_path.vertices - dims / 2.0 +mult = (plot_dims / dims).min() +mult = [mult, -mult] # y axis is inverted (origin at top left) +offset = plot_dims / 2.0 - center_fudge +mne_clip = Path(offset + vert * mult, mne_path.codes) +ax.add_patch(PathPatch(mne_clip, color="w", zorder=0, linewidth=0)) +# apply clipping mask to field gradient and lines +im.set_clip_path(mne_clip, transform=im.get_transform()) +ax.add_patch(rect) +rect.set_clip_path(mne_clip, transform=im.get_transform()) +cs.set_clip_path(mne_clip, transform=im.get_transform()) +# get final position of clipping mask +mne_corners = mne_clip.get_extents().corners() + +# For this make sure that this gives something like "" +fnt = font_manager.findfont("Cooper Hewitt:style=normal:weight=book") +if "Book" not in fnt or "CooperHewitt" not in fnt: + print( + f"WARNING: Might not use correct Cooper Hewitt, got {fnt} but want " + "CooperHewitt-Book.otf or similar" + ) + +# add tagline +with plt.rc_context({"font.sans-serif": ["Cooper Hewitt"], "font.weight": "book"}): + tag_path = TextPath((0, 0), "MEG + EEG ANALYSIS & VISUALIZATION") +dims = tag_path.vertices.max(0) - tag_path.vertices.min(0) +vert = tag_path.vertices - dims / 2.0 +mult = tagline_scale_fudge * (plot_dims / dims).min() +mult = [mult, -mult] # y axis is inverted +offset = ( + mne_corners[-1] + - np.array([mne_clip.get_extents().size[0] / 2.0, -dims[1]]) + - tagline_offset_fudge +) +tag_clip = Path(offset + vert * mult, tag_path.codes) +tag_patch = PathPatch(tag_clip, facecolor="0.6", edgecolor="none", zorder=10) +ax.add_patch(tag_patch) +yl = ax.get_ylim() +yy = np.max([tag_clip.vertices.max(0)[-1], tag_clip.vertices.min(0)[-1]]) +ax.set_ylim(np.ceil(yy), yl[-1]) + +# only save actual image extent plus a bit of padding +fig.canvas.draw_idle() +static_dir = pathlib.Path(__file__).parents[1] / "doc" / "_static" +assert static_dir.is_dir() +kind_color = dict( + mne_logo_dark=("0.8", "0.5"), + mne_logo_gray=("0.6", "0.75"), + mne_logo=("0.3", "w"), # always last +) +for kind, (tag_color, rect_color) in kind_color.items(): + tag_patch.set_facecolor(tag_color) + rect.set_facecolor(rect_color) + fig.savefig( + static_dir / f"{kind}.svg", + transparent=True, + ) + +# %% +# mne_splash.png + +# modify to make the splash screen +data_dir = pathlib.Path(__file__).parents[1] / "mne" / "icons" +assert data_dir.is_dir() +tag_patch.set_facecolor("0.7") +for coll in list(ax.collections): + coll.remove() +bounds = np.array( + [ + [mne_path.vertices[:, ii].min(), mne_path.vertices[:, ii].max()] + for ii in range(2) + ] +) +bounds *= plot_dims / dims +xy = np.mean(bounds, axis=1) - [100, 0] +r = np.diff(bounds, axis=1).max() * 1.2 +w, h = r, r * (2 / 3) +box_xy = [xy[0] - w * 0.5, xy[1] - h * (2 / 5)] +ax.set( + ylim=(box_xy[1] + h * 1.001, box_xy[1] - h * 0.001), + xlim=(box_xy[0] - w * 0.001, box_xy[0] + w * 1.001), +) +patch = FancyBboxPatch( + box_xy, + w, + h, + clip_on=False, + zorder=-1, + fc="k", + ec="none", + alpha=0.75, + boxstyle="round,rounding_size=200.0", + mutation_aspect=1, +) +ax.add_patch(patch) +fig.set_size_inches((512 / dpi, 512 * (h / w) / dpi)) +fig.savefig( + data_dir / "mne_splash.png", + transparent=True, +) +patch.remove() + +# %% +# mne_default_icon.png + +# modify to make an icon +ax.patches[-1].remove() # no tag line for our icon +patch = Ellipse(xy, r, r, clip_on=False, zorder=-1, fc="k") +ax.add_patch(patch) +ax.set_ylim(xy[1] + r / 1.99, xy[1] - r / 1.99) +fig.set_size_inches((256 / dpi, 256 / dpi)) +# Qt does not support clip paths in SVG rendering so we have to use PNG here +# then use "optipng -o7" on it afterward (14% reduction in file size) +fig.savefig( + data_dir / "mne_default_icon.png", + transparent=True, +) + +# %% +# mne_logo_small.svg + +# 188x45 image +dpi = 96 # for SVG it's different +w_px = 188 +h_px = 45 +center_fudge = np.array([60, 0]) +scale_fudge = 2.1 +x = np.linspace(-1.0, 1.0, w_px // 2) +y = np.linspace(-1.0, 1.0, h_px // 2) +X, Y = np.meshgrid(x, y) +# initialize figure (no axes, margins, etc) +fig = plt.figure( + 2, figsize=(w_px / dpi, h_px / dpi), facecolor="k", frameon=False, dpi=dpi +) +ax = plt.Axes(fig, [0.0, 0.0, 1.0, 1.0]) +ax.set_axis_off() +fig.add_axes(ax) +# plot rainbow +ax.imshow(X, cmap=mne_field_grad_cols, aspect="equal", zorder=1) +ax.imshow(np.ones_like(X) * 0.5, cmap="Greys", aspect="equal", zorder=0, clim=[0, 1]) +plot_dims = np.r_[np.diff(ax.get_xbound()), np.diff(ax.get_ybound())] +# MNE text in white +mne_path = TextPath((0, 0), "MNE") +dims = mne_path.vertices.max(0) - mne_path.vertices.min(0) +vert = mne_path.vertices - dims / 2.0 +mult = scale_fudge * (plot_dims / dims).min() +mult = [mult, -mult] # y axis is inverted (origin at top left) +offset = ( + np.array([scale_fudge, 1.0]) * np.array([-dims[0], plot_dims[-1]]) / 2.0 + - center_fudge +) +mne_clip = Path(offset + vert * mult, mne_path.codes) +mne_patch = PathPatch(mne_clip, facecolor="0.5", edgecolor="none", zorder=10) +ax.add_patch(mne_patch) +# adjust xlim and ylim +mne_corners = mne_clip.get_extents().corners() +xmin, ymin = np.min(mne_corners, axis=0) +xmax, ymax = np.max(mne_corners, axis=0) +xl = ax.get_xlim() +yl = ax.get_ylim() +xpad = np.abs(np.diff([xmin, xl[1]])) / 20.0 +ypad = np.abs(np.diff([ymax, ymin])) / 20.0 +ax.set_xlim(xmin - xpad, xl[1] + xpad) +ax.set_ylim(ymax + ypad, ymin - ypad) +fig.canvas.draw_idle() +fig.savefig( + static_dir / "mne_logo_small.svg", + dpi=dpi, + transparent=True, +) diff --git a/mne-python/source/logo/logo_hex.svg b/mne-python/source/logo/logo_hex.svg new file mode 100644 index 0000000000000000000000000000000000000000..45b144d170ce1cdcfb5af402cb00514df7766fdc --- /dev/null +++ b/mne-python/source/logo/logo_hex.svg @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mne-python/source/mne/__init__.py b/mne-python/source/mne/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6abe2bccb62cb4016e8df87327da7db619be6b13 --- /dev/null +++ b/mne-python/source/mne/__init__.py @@ -0,0 +1,36 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""MNE software for MEG and EEG data analysis.""" +# PEP0440 compatible formatted version, see: +# https://www.python.org/dev/peps/pep-0440/ +# +# Generic release markers: +# X.Y +# X.Y.Z # For bugfix releases +# +# Admissible pre-release markers: +# X.YaN # Alpha release +# X.YbN # Beta release +# X.YrcN # Release Candidate +# X.Y # Final release +# +# Dev branch marker is: 'X.Y.devN' where N is an integer. +# +import lazy_loader as lazy + +try: + from importlib.metadata import version + + __version__ = version("mne") +except Exception: + __version__ = "0.0.0" + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) + +# initialize logging +from .utils import set_log_level, set_log_file + +set_log_level(None, False) +set_log_file() diff --git a/mne-python/source/mne/__init__.pyi b/mne-python/source/mne/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..9c5573e0686b3013f6483da24f50ba8b46a9a502 --- /dev/null +++ b/mne-python/source/mne/__init__.pyi @@ -0,0 +1,434 @@ +__all__ = [ + "AcqParserFIF", + "Annotations", + "BaseEpochs", + "BiHemiLabel", + "Covariance", + "Dipole", + "DipoleFixed", + "Epochs", + "EpochsArray", + "Evoked", + "EvokedArray", + "Forward", + "HEDAnnotations", + "Info", + "Label", + "MixedSourceEstimate", + "MixedVectorSourceEstimate", + "Projection", + "Report", + "SourceEstimate", + "SourceMorph", + "SourceSpaces", + "Transform", + "VectorSourceEstimate", + "VolSourceEstimate", + "VolVectorSourceEstimate", + "add_reference_channels", + "add_source_space_distances", + "annotations_from_events", + "apply_forward", + "apply_forward_raw", + "average_forward_solutions", + "beamformer", + "bem", + "channel_indices_by_type", + "channel_type", + "channels", + "chpi", + "combine_evoked", + "commands", + "compute_covariance", + "compute_proj_epochs", + "compute_proj_evoked", + "compute_proj_raw", + "compute_rank", + "compute_raw_covariance", + "compute_source_morph", + "concatenate_epochs", + "concatenate_events", + "concatenate_raws", + "convert_forward_solution", + "coreg", + "count_annotations", + "count_events", + "create_default_subject", + "create_info", + "cuda", + "datasets", + "decimate_surface", + "decoding", + "defaults", + "dig_mri_distances", + "dipole", + "epochs", + "equalize_channels", + "event", + "events_from_annotations", + "export", + "extract_label_time_course", + "filter", + "find_events", + "find_layout", + "find_stim_steps", + "fit_dipole", + "forward", + "get_config", + "get_config_path", + "get_head_surf", + "get_meg_helmet_surf", + "get_montage_volume_labels", + "get_volume_labels_from_aseg", + "get_volume_labels_from_src", + "grade_to_tris", + "grade_to_vertices", + "grand_average", + "grow_labels", + "gui", + "head_to_mni", + "head_to_mri", + "inverse_sparse", + "io", + "label_sign_flip", + "labels_to_stc", + "make_ad_hoc_cov", + "make_bem_model", + "make_bem_solution", + "make_field_map", + "make_fixed_length_epochs", + "make_fixed_length_events", + "make_forward_dipole", + "make_forward_solution", + "make_sphere_model", + "match_channel_orders", + "merge_events", + "minimum_norm", + "morph_labels", + "morph_source_spaces", + "open_docs", + "open_report", + "parse_config", + "pick_channels", + "pick_channels_cov", + "pick_channels_forward", + "pick_channels_regexp", + "pick_events", + "pick_info", + "pick_types", + "pick_types_forward", + "preprocessing", + "random_parcellation", + "read_annotations", + "read_bem_solution", + "read_bem_surfaces", + "read_cov", + "read_dipole", + "read_epochs", + "read_epochs_eeglab", + "read_epochs_fieldtrip", + "read_epochs_kit", + "read_events", + "read_evoked_besa", + "read_evoked_fieldtrip", + "read_evokeds", + "read_evokeds_mff", + "read_forward_solution", + "read_freesurfer_lut", + "read_label", + "read_labels_from_annot", + "read_lta", + "read_morph_map", + "read_proj", + "read_reject_parameters", + "read_source_estimate", + "read_source_morph", + "read_source_spaces", + "read_surface", + "read_talxfm", + "read_trans", + "read_tri", + "read_vectorview_selection", + "rename_channels", + "report", + "scale_bem", + "scale_labels", + "scale_mri", + "scale_source_space", + "sensitivity_map", + "set_bipolar_reference", + "set_cache_dir", + "set_config", + "set_eeg_reference", + "set_log_file", + "set_log_level", + "set_memmap_min_size", + "setup_source_space", + "setup_volume_source_space", + "simulation", + "source_space", + "spatial_dist_adjacency", + "spatial_inter_hemi_adjacency", + "spatial_src_adjacency", + "spatial_tris_adjacency", + "spatio_temporal_dist_adjacency", + "spatio_temporal_src_adjacency", + "spatio_temporal_tris_adjacency", + "split_label", + "stats", + "stc_near_sensors", + "stc_to_label", + "surface", + "sys_info", + "time_frequency", + "transform_surface_to", + "use_coil_def", + "use_log_level", + "verbose", + "vertex_to_mni", + "viz", + "what", + "whiten_evoked", + "write_bem_solution", + "write_bem_surfaces", + "write_cov", + "write_events", + "write_evokeds", + "write_forward_solution", + "write_head_bem", + "write_label", + "write_labels_to_annot", + "write_proj", + "write_source_spaces", + "write_surface", + "write_trans", +] +from . import ( + beamformer, + bem, + channels, + chpi, + commands, + coreg, + cuda, + datasets, + decoding, + defaults, + dipole, + epochs, + event, + export, + filter, + forward, + gui, + inverse_sparse, + io, + minimum_norm, + preprocessing, + report, + simulation, + source_space, + stats, + surface, + time_frequency, + viz, +) +from ._fiff.meas_info import Info, create_info +from ._fiff.pick import ( + channel_indices_by_type, + channel_type, + pick_channels, + pick_channels_cov, + pick_channels_forward, + pick_channels_regexp, + pick_info, + pick_types, + pick_types_forward, +) +from ._fiff.proj import Projection +from ._fiff.reference import ( + add_reference_channels, + set_bipolar_reference, + set_eeg_reference, +) +from ._fiff.what import what +from ._freesurfer import ( + get_volume_labels_from_aseg, + head_to_mni, + head_to_mri, + read_freesurfer_lut, + read_lta, + read_talxfm, + vertex_to_mni, +) +from .annotations import ( + Annotations, + HEDAnnotations, + annotations_from_events, + count_annotations, + events_from_annotations, + read_annotations, +) +from .bem import ( + make_bem_model, + make_bem_solution, + make_sphere_model, + read_bem_solution, + read_bem_surfaces, + write_bem_solution, + write_bem_surfaces, + write_head_bem, +) +from .channels import ( + equalize_channels, + find_layout, + read_vectorview_selection, + rename_channels, +) +from .coreg import ( + create_default_subject, + scale_bem, + scale_labels, + scale_mri, + scale_source_space, +) +from .cov import ( + Covariance, + compute_covariance, + compute_raw_covariance, + make_ad_hoc_cov, + read_cov, + whiten_evoked, + write_cov, +) +from .dipole import Dipole, DipoleFixed, fit_dipole, read_dipole +from .epochs import ( + BaseEpochs, + Epochs, + EpochsArray, + concatenate_epochs, + make_fixed_length_epochs, + read_epochs, +) +from .event import ( + AcqParserFIF, + concatenate_events, + count_events, + find_events, + find_stim_steps, + make_fixed_length_events, + merge_events, + pick_events, + read_events, + write_events, +) +from .evoked import Evoked, EvokedArray, combine_evoked, read_evokeds, write_evokeds +from .forward import ( + Forward, + apply_forward, + apply_forward_raw, + average_forward_solutions, + convert_forward_solution, + make_field_map, + make_forward_dipole, + make_forward_solution, + read_forward_solution, + use_coil_def, + write_forward_solution, +) +from .io import ( + read_epochs_fieldtrip, + read_evoked_besa, + read_evoked_fieldtrip, + read_evokeds_mff, +) +from .io.base import concatenate_raws, match_channel_orders +from .io.eeglab import read_epochs_eeglab +from .io.kit import read_epochs_kit +from .label import ( + BiHemiLabel, + Label, + grow_labels, + label_sign_flip, + labels_to_stc, + morph_labels, + random_parcellation, + read_label, + read_labels_from_annot, + split_label, + stc_to_label, + write_label, + write_labels_to_annot, +) +from .misc import parse_config, read_reject_parameters +from .morph import ( + SourceMorph, + compute_source_morph, + grade_to_vertices, + read_source_morph, +) +from .morph_map import read_morph_map +from .proj import ( + compute_proj_epochs, + compute_proj_evoked, + compute_proj_raw, + read_proj, + sensitivity_map, + write_proj, +) +from .rank import compute_rank +from .report import Report, open_report +from .source_estimate import ( + MixedSourceEstimate, + MixedVectorSourceEstimate, + SourceEstimate, + VectorSourceEstimate, + VolSourceEstimate, + VolVectorSourceEstimate, + extract_label_time_course, + grade_to_tris, + read_source_estimate, + spatial_dist_adjacency, + spatial_inter_hemi_adjacency, + spatial_src_adjacency, + spatial_tris_adjacency, + spatio_temporal_dist_adjacency, + spatio_temporal_src_adjacency, + spatio_temporal_tris_adjacency, + stc_near_sensors, +) +from .source_space._source_space import ( + SourceSpaces, + add_source_space_distances, + get_volume_labels_from_src, + morph_source_spaces, + read_source_spaces, + setup_source_space, + setup_volume_source_space, + write_source_spaces, +) +from .surface import ( + decimate_surface, + dig_mri_distances, + get_head_surf, + get_meg_helmet_surf, + get_montage_volume_labels, + read_surface, + read_tri, + write_surface, +) +from .transforms import Transform, read_trans, transform_surface_to, write_trans +from .utils import ( + get_config, + get_config_path, + grand_average, + open_docs, + set_cache_dir, + set_config, + set_log_file, + set_log_level, + set_memmap_min_size, + sys_info, + use_log_level, + verbose, +) diff --git a/mne-python/source/mne/__main__.py b/mne-python/source/mne/__main__.py new file mode 100644 index 0000000000000000000000000000000000000000..e0a0dc552d25c24f916c74641dcf8849d43d2082 --- /dev/null +++ b/mne-python/source/mne/__main__.py @@ -0,0 +1,8 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .commands.utils import main + +if __name__ == "__main__": + main() diff --git a/mne-python/source/mne/_edf/open.py b/mne-python/source/mne/_edf/open.py new file mode 100644 index 0000000000000000000000000000000000000000..2fd97833b29be70cbb91a48834a7032e155b6dc7 --- /dev/null +++ b/mne-python/source/mne/_edf/open.py @@ -0,0 +1,23 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# Maybe we can move this one to utils or something like that. +from pathlib import Path + +from mne._fiff.open import _NoCloseRead + +from ..utils import _file_like, _validate_type, logger + + +def _gdf_edf_get_fid(fname, **kwargs): + """Open a EDF/BDF/GDF file with no additional parsing.""" + if _file_like(fname): + logger.debug("Using file-like I/O") + fid = _NoCloseRead(fname) + fid.seek(0) + else: + _validate_type(fname, [Path, str], "fname", extra="or file-like") + logger.debug("Using normal I/O") + fid = open(fname, "rb", **kwargs) # Open in binary mode + return fid diff --git a/mne-python/source/mne/_fiff/__init__.py b/mne-python/source/mne/_fiff/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..48a5871c58b1a51728b59c8df3bc15fbed7f8f44 --- /dev/null +++ b/mne-python/source/mne/_fiff/__init__.py @@ -0,0 +1,8 @@ +"""Private module for FIF basic I/O routines.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# All imports should be done directly to submodules, so we don't import +# anything here or use lazy_loader. diff --git a/mne-python/source/mne/_fiff/_digitization.py b/mne-python/source/mne/_fiff/_digitization.py new file mode 100644 index 0000000000000000000000000000000000000000..9664a4f470ea1270874c6c5e5b181d9fb64eb119 --- /dev/null +++ b/mne-python/source/mne/_fiff/_digitization.py @@ -0,0 +1,609 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import heapq +from collections import Counter + +import numpy as np + +from ..fixes import _reshape_view +from ..utils import Bunch, _check_fname, _validate_type, logger, verbose, warn +from .constants import FIFF, _coord_frame_named +from .tag import read_tag +from .tree import dir_tree_find +from .write import _safe_name_list, start_and_end_file, write_dig_points + +_dig_kind_dict = { + "cardinal": FIFF.FIFFV_POINT_CARDINAL, + "hpi": FIFF.FIFFV_POINT_HPI, + "eeg": FIFF.FIFFV_POINT_EEG, + "extra": FIFF.FIFFV_POINT_EXTRA, +} +_dig_kind_ints = tuple(sorted(_dig_kind_dict.values())) +_dig_kind_proper = { + "cardinal": "Cardinal", + "hpi": "HPI", + "eeg": "EEG", + "extra": "Extra", + "unknown": "Unknown", +} +_dig_kind_rev = {val: key for key, val in _dig_kind_dict.items()} +_cardinal_kind_rev = {1: "LPA", 2: "Nasion", 3: "RPA", 4: "Inion"} + + +def _format_dig_points(dig, enforce_order=False): + """Format the dig points nicely.""" + if enforce_order and dig is not None: + # reorder points based on type: + # Fiducials/HPI, EEG, extra (headshape) + fids_digpoints = [] + hpi_digpoints = [] + eeg_digpoints = [] + extra_digpoints = [] + head_digpoints = [] + + # use a heap to enforce order on FIDS, EEG, Extra + for idx, digpoint in enumerate(dig): + ident = digpoint["ident"] + kind = digpoint["kind"] + + # push onto heap based on 'ident' (for the order) for + # each of the possible DigPoint 'kind's + # keep track of 'idx' in case of any clashes in + # the 'ident' variable, which can occur when + # user passes in DigMontage + DigMontage + if kind == FIFF.FIFFV_POINT_CARDINAL: + heapq.heappush(fids_digpoints, (ident, idx, digpoint)) + elif kind == FIFF.FIFFV_POINT_HPI: + heapq.heappush(hpi_digpoints, (ident, idx, digpoint)) + elif kind == FIFF.FIFFV_POINT_EEG: + heapq.heappush(eeg_digpoints, (ident, idx, digpoint)) + elif kind == FIFF.FIFFV_POINT_EXTRA: + heapq.heappush(extra_digpoints, (ident, idx, digpoint)) + elif kind == FIFF.FIFFV_POINT_HEAD: + heapq.heappush(head_digpoints, (ident, idx, digpoint)) + + # now recreate dig based on sorted order + fids_digpoints.sort(), hpi_digpoints.sort() + eeg_digpoints.sort() + extra_digpoints.sort(), head_digpoints.sort() + new_dig = [] + for idx, d in enumerate( + fids_digpoints + + hpi_digpoints + + extra_digpoints + + eeg_digpoints + + head_digpoints + ): + new_dig.append(d[-1]) + dig = new_dig + + return [DigPoint(d) for d in dig] if dig is not None else dig + + +def _get_dig_eeg(dig): + return [d for d in dig if d["kind"] == FIFF.FIFFV_POINT_EEG] + + +def _count_points_by_type(dig): + """Get the number of points of each type.""" + occurrences = Counter([d["kind"] for d in dig]) + return dict( + fid=occurrences[FIFF.FIFFV_POINT_CARDINAL], + hpi=occurrences[FIFF.FIFFV_POINT_HPI], + eeg=occurrences[FIFF.FIFFV_POINT_EEG], + extra=occurrences[FIFF.FIFFV_POINT_EXTRA], + ) + + +_dig_keys = {"kind", "ident", "r", "coord_frame"} + + +class DigPoint(dict): + """Container for a digitization point. + + This is a simple subclass of the standard dict type designed to provide + a readable string representation. + + Parameters + ---------- + kind : int + The kind of channel, + e.g. ``FIFFV_POINT_EEG``, ``FIFFV_POINT_CARDINAL``. + r : array, shape (3,) + 3D position in m. and coord_frame. + ident : int + Number specifying the identity of the point. + e.g. ``FIFFV_POINT_NASION`` if kind is ``FIFFV_POINT_CARDINAL``, + or 42 if kind is ``FIFFV_POINT_EEG``. + coord_frame : int + The coordinate frame used, e.g. ``FIFFV_COORD_HEAD``. + """ + + def __repr__(self): # noqa: D105 + from ..transforms import _coord_frame_name + + if self["kind"] == FIFF.FIFFV_POINT_CARDINAL: + id_ = _cardinal_kind_rev.get(self["ident"], "Unknown cardinal") + else: + id_ = _dig_kind_proper[_dig_kind_rev.get(self["kind"], "unknown")] + id_ = f"{id_} #{self['ident']}" + id_ = id_.rjust(10) + cf = _coord_frame_name(self["coord_frame"]) + x, y, z = self["r"] + if "voxel" in cf: + pos = (f"({x:0.1f}, {y:0.1f}, {z:0.1f})").ljust(25) + else: + pos = (f"({x * 1e3:0.1f}, {y * 1e3:0.1f}, {z * 1e3:0.1f}) mm").ljust(25) + return f"" + + # speed up info copy by only deep copying the mutable item + def __deepcopy__(self, memodict): + """Make a deepcopy.""" + return DigPoint( + kind=self["kind"], + r=self["r"].copy(), + ident=self["ident"], + coord_frame=self["coord_frame"], + ) + + def __eq__(self, other): # noqa: D105 + """Compare two DigPoints. + + Two digpoints are equal if they are the same kind, share the same + coordinate frame and position. + """ + my_keys = ["kind", "ident", "coord_frame"] + if set(self.keys()) != set(other.keys()): + return False + elif any(self[_] != other[_] for _ in my_keys): + return False + else: + return np.allclose(self["r"], other["r"]) + + +def _read_dig_fif(fid, meas_info, *, return_ch_names=False): + """Read digitizer data from a FIFF file.""" + isotrak = dir_tree_find(meas_info, FIFF.FIFFB_ISOTRAK) + dig = None + ch_names = None + if len(isotrak) == 0: + logger.info("Isotrak not found") + elif len(isotrak) > 1: + warn("Multiple Isotrak found") + else: + isotrak = isotrak[0] + coord_frame = FIFF.FIFFV_COORD_HEAD + dig = [] + for k in range(isotrak["nent"]): + kind = isotrak["directory"][k].kind + pos = isotrak["directory"][k].pos + if kind == FIFF.FIFF_DIG_POINT: + tag = read_tag(fid, pos) + dig.append(tag.data) + elif kind == FIFF.FIFF_DIG_STRING: + tag = read_tag(fid, pos) + dig.extend(tag.data) + elif kind == FIFF.FIFF_MNE_COORD_FRAME: + tag = read_tag(fid, pos) + coord_frame = int(tag.data.item()) + coord_frame = _coord_frame_named.get(coord_frame, coord_frame) + elif kind == FIFF.FIFF_MNE_CH_NAME_LIST: + tag = read_tag(fid, pos) + ch_names = _safe_name_list(tag.data, "read", "ch_names") + for d in dig: + d["coord_frame"] = coord_frame + out = _format_dig_points(dig) + if return_ch_names: + out = (out, ch_names) + return out + + +@verbose +def write_dig( + fname, pts, coord_frame=None, *, ch_names=None, overwrite=False, verbose=None +): + """Write digitization data to a FIF file. + + Parameters + ---------- + fname : path-like + Destination file name. + pts : iterator of dict + Iterator through digitizer points. Each point is a dictionary with + the keys 'kind', 'ident' and 'r'. + coord_frame : int | str | None + If all the points have the same coordinate frame, specify the type + here. Can be None (default) if the points could have varying + coordinate frames. + ch_names : list of str | None + Channel names associated with the digitization points, if available. + + .. versionadded:: 1.9 + %(overwrite)s + + .. versionadded:: 1.0 + %(verbose)s + + .. versionadded:: 1.0 + """ + from ..transforms import _to_const + + fname = _check_fname(fname, overwrite=overwrite) + if coord_frame is not None: + coord_frame = _to_const(coord_frame) + pts_frames = {pt.get("coord_frame", coord_frame) for pt in pts} + bad_frames = pts_frames - {coord_frame} + if len(bad_frames) > 0: + raise ValueError( + "Points have coord_frame entries that are incompatible with " + f"coord_frame={coord_frame}: {tuple(bad_frames)}." + ) + _validate_type(ch_names, (None, list, tuple), "ch_names") + if ch_names is not None: + for ci, ch_name in enumerate(ch_names): + _validate_type(ch_name, str, f"ch_names[{ci}]") + + with start_and_end_file(fname) as fid: + write_dig_points( + fid, pts, block=True, coord_frame=coord_frame, ch_names=ch_names + ) + + +_cardinal_ident_mapping = { + FIFF.FIFFV_POINT_NASION: "nasion", + FIFF.FIFFV_POINT_LPA: "lpa", + FIFF.FIFFV_POINT_RPA: "rpa", +} + + +def _ensure_fiducials_head(dig): + # Ensure that there are all three fiducials in the head coord frame + fids = dict() + for d in dig: + if d["kind"] == FIFF.FIFFV_POINT_CARDINAL: + name = _cardinal_ident_mapping.get(d["ident"], None) + if name is not None: + fids[name] = d + radius = None + mults = dict( + lpa=[-1, 0, 0], + rpa=[1, 0, 0], + nasion=[0, 1, 0], + ) + for ident, name in _cardinal_ident_mapping.items(): + if name not in fids: + if radius is None: + radius = [ + np.linalg.norm(d["r"]) + for d in dig + if d["coord_frame"] == FIFF.FIFFV_COORD_HEAD + and not np.isnan(d["r"]).any() + ] + if not radius: + return # can't complete, no head points + radius = np.mean(radius) + dig.append( + DigPoint( + kind=FIFF.FIFFV_POINT_CARDINAL, + ident=ident, + r=np.array(mults[name], float) * radius, + coord_frame=FIFF.FIFFV_COORD_HEAD, + ) + ) + + +# XXXX: +# This does something really similar to _read_dig_montage_fif but: +# - does not check coord_frame +# - does not do any operation that implies assumptions with the names +def _get_data_as_dict_from_dig(dig, exclude_ref_channel=True): + """Obtain coordinate data from a Dig. + + Parameters + ---------- + dig : list of dicts + A container of DigPoints to be added to the info['dig']. + + Returns + ------- + ch_pos : dict + The container of all relevant channel positions inside dig. + """ + # Split up the dig points by category + hsp, hpi, elp = list(), list(), list() + fids, dig_ch_pos_location = dict(), list() + dig = [] if dig is None else dig + + for d in dig: + if d["kind"] == FIFF.FIFFV_POINT_CARDINAL: + fids[_cardinal_ident_mapping[d["ident"]]] = d["r"] + elif d["kind"] == FIFF.FIFFV_POINT_HPI: + hpi.append(d["r"]) + elp.append(d["r"]) + elif d["kind"] == FIFF.FIFFV_POINT_EXTRA: + hsp.append(d["r"]) + elif d["kind"] == FIFF.FIFFV_POINT_EEG: + if d["ident"] != 0 or not exclude_ref_channel: + dig_ch_pos_location.append(d["r"]) + + dig_coord_frames = set([d["coord_frame"] for d in dig]) + if len(dig_coord_frames) == 0: + dig_coord_frames = set([FIFF.FIFFV_COORD_HEAD]) + if len(dig_coord_frames) != 1: + raise RuntimeError( + f"Only single coordinate frame in dig is supported, got {dig_coord_frames}" + ) + dig_ch_pos_location = np.array(dig_ch_pos_location) + dig_ch_pos_location = _reshape_view(dig_ch_pos_location, (-1, 3)) + return Bunch( + nasion=fids.get("nasion", None), + lpa=fids.get("lpa", None), + rpa=fids.get("rpa", None), + hsp=np.array(hsp) if len(hsp) else None, + hpi=np.array(hpi) if len(hpi) else None, + elp=np.array(elp) if len(elp) else None, + dig_ch_pos_location=dig_ch_pos_location, + coord_frame=dig_coord_frames.pop(), + ) + + +def _get_fid_coords(dig, raise_error=True): + fid_coords = Bunch(nasion=None, lpa=None, rpa=None) + fid_coord_frames = dict() + + for d in dig: + if d["kind"] == FIFF.FIFFV_POINT_CARDINAL: + key = _cardinal_ident_mapping[d["ident"]] + fid_coords[key] = d["r"] + fid_coord_frames[key] = d["coord_frame"] + + if len(fid_coord_frames) > 0 and raise_error: + if set(fid_coord_frames.keys()) != set(["nasion", "lpa", "rpa"]): + raise ValueError( + f"Some fiducial points are missing (got {fid_coord_frames.keys()})." + ) + + if len(set(fid_coord_frames.values())) > 1: + raise ValueError( + "All fiducial points must be in the same coordinate system " + f"(got {len(fid_coord_frames)})" + ) + + coord_frame = fid_coord_frames.popitem()[1] if fid_coord_frames else None + + return fid_coords, coord_frame + + +def _coord_frame_const(coord_frame): + from ..transforms import _str_to_frame + + if not isinstance(coord_frame, str) or coord_frame not in _str_to_frame: + raise ValueError( + f"coord_frame must be one of {sorted(_str_to_frame.keys())}, got " + f"{coord_frame}" + ) + return _str_to_frame[coord_frame] + + +def _make_dig_points( + nasion=None, + lpa=None, + rpa=None, + hpi=None, + extra_points=None, + dig_ch_pos=None, + *, + coord_frame="head", + add_missing_fiducials=False, +): + """Construct digitizer info for the info. + + Parameters + ---------- + nasion : array-like | numpy.ndarray, shape (3,) | None + Point designated as the nasion point. + lpa : array-like | numpy.ndarray, shape (3,) | None + Point designated as the left auricular point. + rpa : array-like | numpy.ndarray, shape (3,) | None + Point designated as the right auricular point. + hpi : array-like | numpy.ndarray, shape (n_points, 3) | None + Points designated as head position indicator points. + extra_points : array-like | numpy.ndarray, shape (n_points, 3) + Points designed as the headshape points. + dig_ch_pos : dict + Dict of EEG channel positions. + coord_frame : str + The coordinate frame of the points. Usually this is "unknown" + for native digitizer space. Defaults to "head". + add_missing_fiducials : bool + If True, add fiducials to the dig points if they are not present. + Requires that coord_frame='head' and that lpa, nasion, and rpa are all + None. + + Returns + ------- + dig : list of dicts + A container of DigPoints to be added to the info['dig']. + """ + coord_frame = _coord_frame_const(coord_frame) + + dig = [] + if lpa is not None: + lpa = np.asarray(lpa) + if lpa.shape != (3,): + raise ValueError(f"LPA should have the shape (3,) instead of {lpa.shape}") + dig.append( + { + "r": lpa, + "ident": FIFF.FIFFV_POINT_LPA, + "kind": FIFF.FIFFV_POINT_CARDINAL, + "coord_frame": coord_frame, + } + ) + if nasion is not None: + nasion = np.asarray(nasion) + if nasion.shape != (3,): + raise ValueError( + f"Nasion should have the shape (3,) instead of {nasion.shape}" + ) + dig.append( + { + "r": nasion, + "ident": FIFF.FIFFV_POINT_NASION, + "kind": FIFF.FIFFV_POINT_CARDINAL, + "coord_frame": coord_frame, + } + ) + if rpa is not None: + rpa = np.asarray(rpa) + if rpa.shape != (3,): + raise ValueError(f"RPA should have the shape (3,) instead of {rpa.shape}") + dig.append( + { + "r": rpa, + "ident": FIFF.FIFFV_POINT_RPA, + "kind": FIFF.FIFFV_POINT_CARDINAL, + "coord_frame": coord_frame, + } + ) + if hpi is not None: + hpi = np.asarray(hpi) + if hpi.ndim != 2 or hpi.shape[1] != 3: + raise ValueError( + f"HPI should have the shape (n_points, 3) instead of {hpi.shape}" + ) + for idx, point in enumerate(hpi): + dig.append( + { + "r": point, + "ident": idx + 1, + "kind": FIFF.FIFFV_POINT_HPI, + "coord_frame": coord_frame, + } + ) + if extra_points is not None: + extra_points = np.asarray(extra_points) + if len(extra_points) and extra_points.shape[1] != 3: + raise ValueError( + "Points should have the shape (n_points, 3) instead of " + f"{extra_points.shape}" + ) + for idx, point in enumerate(extra_points): + dig.append( + { + "r": point, + "ident": idx + 1, + "kind": FIFF.FIFFV_POINT_EXTRA, + "coord_frame": coord_frame, + } + ) + if dig_ch_pos is not None: + idents = [] + use_arange = False + for key, value in dig_ch_pos.items(): + _validate_type(key, str, "dig_ch_pos") + try: + idents.append(int(key[-3:])) + except ValueError: + use_arange = True + _validate_type(value, (np.ndarray, list, tuple), "dig_ch_pos") + value = np.array(value, dtype=float) + dig_ch_pos[key] = value + if value.shape != (3,): + raise RuntimeError( + "The position should be a 1D array of 3 floats. " + f"Provided shape {value.shape}." + ) + if use_arange: + idents = np.arange(1, len(dig_ch_pos) + 1) + for key, ident in zip(dig_ch_pos, idents): + dig.append( + { + "r": dig_ch_pos[key], + "ident": int(ident), + "kind": FIFF.FIFFV_POINT_EEG, + "coord_frame": coord_frame, + } + ) + if add_missing_fiducials: + assert coord_frame == FIFF.FIFFV_COORD_HEAD + # These being none is really an assumption that if you have one you + # should have all three. But we can relax this later if necessary. + assert lpa is None + assert rpa is None + assert nasion is None + _ensure_fiducials_head(dig) + + return _format_dig_points(dig) + + +def _call_make_dig_points(nasion, lpa, rpa, hpi, extra, convert=True): + from ..transforms import ( + Transform, + apply_trans, + get_ras_to_neuromag_trans, + ) + + if convert: + neuromag_trans = get_ras_to_neuromag_trans(nasion, lpa, rpa) + nasion = apply_trans(neuromag_trans, nasion) + lpa = apply_trans(neuromag_trans, lpa) + rpa = apply_trans(neuromag_trans, rpa) + + if hpi is not None: + hpi = apply_trans(neuromag_trans, hpi) + + extra = apply_trans(neuromag_trans, extra).astype(np.float32) + else: + neuromag_trans = None + + ctf_head_t = Transform(fro="ctf_head", to="head", trans=neuromag_trans) + + info_dig = _make_dig_points( + nasion=nasion, lpa=lpa, rpa=rpa, hpi=hpi, extra_points=extra + ) + + return info_dig, ctf_head_t + + +############################################################################## +# From artemis123 (we have modified the function a bit) +def _artemis123_read_pos(nas, lpa, rpa, hpi, extra): + # move into MNE head coords + dig_points, _ = _call_make_dig_points(nas, lpa, rpa, hpi, extra) + return dig_points + + +############################################################################## +# From bti +def _make_bti_dig_points( + nasion, + lpa, + rpa, + hpi, + extra, + convert=False, + use_hpi=False, + bti_dev_t=False, + dev_ctf_t=False, +): + from ..transforms import ( + Transform, + combine_transforms, + invert_transform, + ) + + _hpi = hpi if use_hpi else None + info_dig, ctf_head_t = _call_make_dig_points(nasion, lpa, rpa, _hpi, extra, convert) + + if convert: + t = combine_transforms( + invert_transform(bti_dev_t), dev_ctf_t, "meg", "ctf_head" + ) + dev_head_t = combine_transforms(t, ctf_head_t, "meg", "head") + else: + dev_head_t = Transform("meg", "head", trans=None) + + return info_dig, dev_head_t, ctf_head_t # ctf_head_t should not be needed diff --git a/mne-python/source/mne/_fiff/compensator.py b/mne-python/source/mne/_fiff/compensator.py new file mode 100644 index 0000000000000000000000000000000000000000..914dc1bb82bdd40c9edae969106dd7b2ee8b3e3f --- /dev/null +++ b/mne-python/source/mne/_fiff/compensator.py @@ -0,0 +1,168 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ..utils import fill_doc +from .constants import FIFF + + +def get_current_comp(info): + """Get the current compensation in effect in the data.""" + comp = None + first_comp = -1 + for k, chan in enumerate(info["chs"]): + if chan["kind"] == FIFF.FIFFV_MEG_CH: + comp = int(chan["coil_type"]) >> 16 + if first_comp < 0: + first_comp = comp + elif comp != first_comp: + raise ValueError("Compensation is not set equally on all MEG channels") + return comp + + +def set_current_comp(info, comp): + """Set the current compensation in effect in the data.""" + comp_now = get_current_comp(info) + for k, chan in enumerate(info["chs"]): + if chan["kind"] == FIFF.FIFFV_MEG_CH: + rem = chan["coil_type"] - (comp_now << 16) + chan["coil_type"] = int(rem + (comp << 16)) + + +def _make_compensator(info, grade): + """Auxiliary function for make_compensator.""" + for k in range(len(info["comps"])): + if info["comps"][k]["kind"] == grade: + this_data = info["comps"][k]["data"] + + # Create the preselector + presel = np.zeros((this_data["ncol"], info["nchan"])) + for col, col_name in enumerate(this_data["col_names"]): + ind = [k for k, ch in enumerate(info["ch_names"]) if ch == col_name] + if len(ind) == 0: + raise ValueError(f"Channel {col_name} is not available in data") + elif len(ind) > 1: + raise ValueError(f"Ambiguous channel {col_name}") + presel[col, ind[0]] = 1.0 + + # Create the postselector (zero entries for channels not found) + postsel = np.zeros((info["nchan"], this_data["nrow"])) + for c, ch_name in enumerate(info["ch_names"]): + ind = [ + k for k, ch in enumerate(this_data["row_names"]) if ch == ch_name + ] + if len(ind) > 1: + raise ValueError(f"Ambiguous channel {ch_name}") + elif len(ind) == 1: + postsel[c, ind[0]] = 1.0 + # else, don't use it at all (postsel[c, ?] = 0.0) by allocation + this_comp = np.dot(postsel, np.dot(this_data["data"], presel)) + return this_comp + + raise ValueError(f"Desired compensation matrix (grade = {grade:d}) not found") + + +@fill_doc +def make_compensator(info, from_, to, exclude_comp_chs=False): + """Return compensation matrix eg. for CTF system. + + Create a compensation matrix to bring the data from one compensation + state to another. + + Parameters + ---------- + %(info_not_none)s + from_ : int + Compensation in the input data. + to : int + Desired compensation in the output. + exclude_comp_chs : bool + Exclude compensation channels from the output. + + Returns + ------- + comp : array | None. + The compensation matrix. Might be None if no compensation + is needed (from == to). + """ + if from_ == to: + return None + + # s_orig = s_from + C1*s_from = (I + C1)*s_from + # s_to = s_orig - C2*s_orig = (I - C2)*s_orig + # s_to = (I - C2)*(I + C1)*s_from = (I + C1 - C2 - C2*C1)*s_from + if from_ != 0: + C1 = _make_compensator(info, from_) + comp_from_0 = np.linalg.inv(np.eye(info["nchan"]) - C1) + if to != 0: + C2 = _make_compensator(info, to) + comp_0_to = np.eye(info["nchan"]) - C2 + if from_ != 0: + if to != 0: + # This is mathematically equivalent, but has higher numerical + # error than using the inverse to always go to zero and back + # comp = np.eye(info['nchan']) + C1 - C2 - np.dot(C2, C1) + comp = np.dot(comp_0_to, comp_from_0) + else: + comp = comp_from_0 + else: + # from == 0, to != 0 guaranteed here + comp = comp_0_to + + if exclude_comp_chs: + pick = [ + k for k, c in enumerate(info["chs"]) if c["kind"] != FIFF.FIFFV_REF_MEG_CH + ] + + if len(pick) == 0: + raise ValueError( + "Nothing remains after excluding the compensation channels" + ) + + comp = comp[pick, :] + + return comp + + +# @verbose +# def compensate_to(data, to, verbose=None): +# """ +# % +# % [newdata] = mne_compensate_to(data,to) +# % +# % Apply compensation to the data as desired +# % +# """ +# +# newdata = data.copy() +# now = get_current_comp(newdata['info']) +# +# # Are we there already? +# if now == to: +# logger.info('Data are already compensated as desired') +# +# # Make the compensator and apply it to all data sets +# comp = make_compensator(newdata['info'], now, to) +# for k in range(len(newdata['evoked'])): +# newdata['evoked'][k]['epochs'] = np.dot(comp, +# newdata['evoked'][k]['epochs']) +# +# # Update the compensation info in the channel descriptors +# newdata['info']['chs'] = set_current_comp(newdata['info']['chs'], to) +# return newdata + + +# def set_current_comp(chs, value): +# """Set the current compensation value in the channel info structures +# """ +# new_chs = chs +# +# lower_half = int('FFFF', 16) # hex2dec('FFFF') +# for k in range(len(chs)): +# if chs[k]['kind'] == FIFF.FIFFV_MEG_CH: +# coil_type = float(chs[k]['coil_type']) & lower_half +# new_chs[k]['coil_type'] = int(coil_type | (value << 16)) +# +# return new_chs diff --git a/mne-python/source/mne/_fiff/constants.py b/mne-python/source/mne/_fiff/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..cf604db530c3b001c4a0bf4fdca5dda7d476f883 --- /dev/null +++ b/mne-python/source/mne/_fiff/constants.py @@ -0,0 +1,1230 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ..utils._bunch import BunchConstNamed + +FIFF = BunchConstNamed() + +# +# FIFF version number in use +# +FIFF.FIFFC_MAJOR_VERSION = 1 +FIFF.FIFFC_MINOR_VERSION = 4 +FIFF.FIFFC_VERSION = FIFF.FIFFC_MAJOR_VERSION << 16 | FIFF.FIFFC_MINOR_VERSION + +# +# Blocks +# +FIFF.FIFFB_ROOT = 999 +FIFF.FIFFB_MEAS = 100 +FIFF.FIFFB_MEAS_INFO = 101 +FIFF.FIFFB_RAW_DATA = 102 +FIFF.FIFFB_PROCESSED_DATA = 103 +FIFF.FIFFB_EVOKED = 104 +FIFF.FIFFB_ASPECT = 105 +FIFF.FIFFB_SUBJECT = 106 +FIFF.FIFFB_ISOTRAK = 107 +FIFF.FIFFB_HPI_MEAS = 108 # HPI measurement +FIFF.FIFFB_HPI_RESULT = 109 # Result of a HPI fitting procedure +FIFF.FIFFB_HPI_COIL = 110 # Data acquired from one HPI coil +FIFF.FIFFB_PROJECT = 111 +FIFF.FIFFB_CONTINUOUS_DATA = 112 +FIFF.FIFFB_CH_INFO = 113 # Extra channel information +FIFF.FIFFB_VOID = 114 +FIFF.FIFFB_EVENTS = 115 +FIFF.FIFFB_INDEX = 116 +FIFF.FIFFB_DACQ_PARS = 117 +FIFF.FIFFB_REF = 118 +FIFF.FIFFB_IAS_RAW_DATA = 119 +FIFF.FIFFB_IAS_ASPECT = 120 +FIFF.FIFFB_HPI_SUBSYSTEM = 121 +# FIFF.FIFFB_PHANTOM_SUBSYSTEM = 122 +# FIFF.FIFFB_STATUS_SUBSYSTEM = 123 +FIFF.FIFFB_DEVICE = 124 +FIFF.FIFFB_HELIUM = 125 +FIFF.FIFFB_CHANNEL_INFO = 126 + +FIFF.FIFFB_SPHERE = 300 # Concentric sphere model related +FIFF.FIFFB_BEM = 310 # Boundary-element method +FIFF.FIFFB_BEM_SURF = 311 # Boundary-element method surfaces +FIFF.FIFFB_CONDUCTOR_MODEL = 312 # One conductor model definition +FIFF.FIFFB_PROJ = 313 +FIFF.FIFFB_PROJ_ITEM = 314 +FIFF.FIFFB_MRI = 200 +FIFF.FIFFB_MRI_SET = 201 +FIFF.FIFFB_MRI_SLICE = 202 +FIFF.FIFFB_MRI_SCENERY = 203 # These are for writing unrelated 'slices' +FIFF.FIFFB_MRI_SCENE = 204 # Which are actually 3D scenes... +FIFF.FIFFB_MRI_SEG = 205 # MRI segmentation data +FIFF.FIFFB_MRI_SEG_REGION = 206 # One MRI segmentation region +FIFF.FIFFB_PROCESSING_HISTORY = 900 +FIFF.FIFFB_PROCESSING_RECORD = 901 + +FIFF.FIFFB_DATA_CORRECTION = 500 +FIFF.FIFFB_CHANNEL_DECOUPLER = 501 +FIFF.FIFFB_SSS_INFO = 502 +FIFF.FIFFB_SSS_CAL = 503 +FIFF.FIFFB_SSS_ST_INFO = 504 +FIFF.FIFFB_SSS_BASES = 505 +FIFF.FIFFB_IAS = 510 +# +# Of general interest +# +FIFF.FIFF_FILE_ID = 100 +FIFF.FIFF_DIR_POINTER = 101 +FIFF.FIFF_BLOCK_ID = 103 +FIFF.FIFF_BLOCK_START = 104 +FIFF.FIFF_BLOCK_END = 105 +FIFF.FIFF_FREE_LIST = 106 +FIFF.FIFF_FREE_BLOCK = 107 +FIFF.FIFF_NOP = 108 +FIFF.FIFF_PARENT_FILE_ID = 109 +FIFF.FIFF_PARENT_BLOCK_ID = 110 +FIFF.FIFF_BLOCK_NAME = 111 +FIFF.FIFF_BLOCK_VERSION = 112 +FIFF.FIFF_CREATOR = 113 # Program that created the file (string) +FIFF.FIFF_MODIFIER = 114 # Program that modified the file (string) +FIFF.FIFF_REF_ROLE = 115 +FIFF.FIFF_REF_FILE_ID = 116 +FIFF.FIFF_REF_FILE_NUM = 117 +FIFF.FIFF_REF_FILE_NAME = 118 +# +# Megacq saves the parameters in these tags +# +FIFF.FIFF_DACQ_PARS = 150 +FIFF.FIFF_DACQ_STIM = 151 + +FIFF.FIFF_DEVICE_TYPE = 152 +FIFF.FIFF_DEVICE_MODEL = 153 +FIFF.FIFF_DEVICE_SERIAL = 154 +FIFF.FIFF_DEVICE_SITE = 155 + +FIFF.FIFF_HE_LEVEL_RAW = 156 +FIFF.FIFF_HELIUM_LEVEL = 157 +FIFF.FIFF_ORIG_FILE_GUID = 158 +FIFF.FIFF_UTC_OFFSET = 159 + +FIFF.FIFF_NCHAN = 200 +FIFF.FIFF_SFREQ = 201 +FIFF.FIFF_DATA_PACK = 202 +FIFF.FIFF_CH_INFO = 203 +FIFF.FIFF_MEAS_DATE = 204 +FIFF.FIFF_SUBJECT = 205 +FIFF.FIFF_COMMENT = 206 +FIFF.FIFF_NAVE = 207 +FIFF.FIFF_FIRST_SAMPLE = 208 # The first sample of an epoch +FIFF.FIFF_LAST_SAMPLE = 209 # The last sample of an epoch +FIFF.FIFF_ASPECT_KIND = 210 +FIFF.FIFF_REF_EVENT = 211 +FIFF.FIFF_EXPERIMENTER = 212 +FIFF.FIFF_DIG_POINT = 213 +FIFF.FIFF_CH_POS = 214 +FIFF.FIFF_HPI_SLOPES = 215 # HPI data +FIFF.FIFF_HPI_NCOIL = 216 +FIFF.FIFF_REQ_EVENT = 217 +FIFF.FIFF_REQ_LIMIT = 218 +FIFF.FIFF_LOWPASS = 219 +FIFF.FIFF_BAD_CHS = 220 +FIFF.FIFF_ARTEF_REMOVAL = 221 +FIFF.FIFF_COORD_TRANS = 222 +FIFF.FIFF_HIGHPASS = 223 +FIFF.FIFF_CH_CALS = 224 # This will not occur in new files +FIFF.FIFF_HPI_BAD_CHS = 225 # List of channels considered to be bad in hpi +FIFF.FIFF_HPI_CORR_COEFF = 226 # HPI curve fit correlations +FIFF.FIFF_EVENT_COMMENT = 227 # Comment about the events used in averaging +FIFF.FIFF_NO_SAMPLES = 228 # Number of samples in an epoch +FIFF.FIFF_FIRST_TIME = 229 # Time scale minimum + +FIFF.FIFF_SUBAVE_SIZE = 230 # Size of a subaverage +FIFF.FIFF_SUBAVE_FIRST = 231 # The first epoch # contained in the subaverage +FIFF.FIFF_NAME = 233 # Intended to be a short name. +FIFF.FIFF_DESCRIPTION = FIFF.FIFF_COMMENT # (Textual) Description of an object +FIFF.FIFF_DIG_STRING = 234 # String of digitized points +FIFF.FIFF_LINE_FREQ = 235 # Line frequency +FIFF.FIFF_GANTRY_ANGLE = 282 # Tilt angle of the gantry in degrees. + +# +# HPI fitting program tags +# +FIFF.FIFF_HPI_COIL_FREQ = 236 # HPI coil excitation frequency +FIFF.FIFF_HPI_COIL_MOMENTS = ( + 240 # Estimated moment vectors for the HPI coil magnetic dipoles +) +FIFF.FIFF_HPI_FIT_GOODNESS = 241 # Three floats indicating the goodness of fit +FIFF.FIFF_HPI_FIT_ACCEPT = 242 # Bitmask indicating acceptance (see below) +FIFF.FIFF_HPI_FIT_GOOD_LIMIT = 243 # Limit for the goodness-of-fit +FIFF.FIFF_HPI_FIT_DIST_LIMIT = 244 # Limit for the coil distance difference +FIFF.FIFF_HPI_COIL_NO = 245 # Coil number listed by HPI measurement +FIFF.FIFF_HPI_COILS_USED = ( + 246 # List of coils finally used when the transformation was computed +) +FIFF.FIFF_HPI_DIGITIZATION_ORDER = ( + 247 # Which Isotrak digitization point corresponds to each of the coils energized +) + + +# +# Tags used for storing channel info +# +FIFF.FIFF_CH_SCAN_NO = ( + 250 # Channel scan number. Corresponds to fiffChInfoRec.scanNo field +) +FIFF.FIFF_CH_LOGICAL_NO = ( + 251 # Channel logical number. Corresponds to fiffChInfoRec.logNo field +) +FIFF.FIFF_CH_KIND = 252 # Channel type. Corresponds to fiffChInfoRec.kind field" +FIFF.FIFF_CH_RANGE = ( + 253 # Conversion from recorded number to (possibly virtual) voltage at the output" +) +FIFF.FIFF_CH_CAL = 254 # Calibration coefficient from output voltage to some real units +FIFF.FIFF_CH_LOC = 255 # Channel loc +FIFF.FIFF_CH_UNIT = 256 # Unit of the data +FIFF.FIFF_CH_UNIT_MUL = 257 # Unit multiplier exponent +FIFF.FIFF_CH_DACQ_NAME = 258 # Name of the channel in the data acquisition system. Corresponds to fiffChInfoRec.name. +FIFF.FIFF_CH_COIL_TYPE = 350 # Coil type in coil_def.dat +FIFF.FIFF_CH_COORD_FRAME = 351 # Coordinate frame (integer) + +# +# Pointers +# +FIFF.FIFFV_NEXT_SEQ = 0 +FIFF.FIFFV_NEXT_NONE = -1 +# +# Channel types +# +FIFF.FIFFV_BIO_CH = 102 +FIFF.FIFFV_MEG_CH = 1 +FIFF.FIFFV_REF_MEG_CH = 301 +FIFF.FIFFV_EEG_CH = 2 +FIFF.FIFFV_MCG_CH = 201 +FIFF.FIFFV_STIM_CH = 3 +FIFF.FIFFV_EOG_CH = 202 +FIFF.FIFFV_EMG_CH = 302 +FIFF.FIFFV_ECG_CH = 402 +FIFF.FIFFV_MISC_CH = 502 +FIFF.FIFFV_RESP_CH = 602 # Respiration monitoring +FIFF.FIFFV_SEEG_CH = 802 # stereotactic EEG +FIFF.FIFFV_DBS_CH = 803 # deep brain stimulation +FIFF.FIFFV_SYST_CH = 900 # some system status information (on Triux systems only) +FIFF.FIFFV_ECOG_CH = 902 +FIFF.FIFFV_IAS_CH = 910 # Internal Active Shielding data (maybe on Triux only) +FIFF.FIFFV_EXCI_CH = 920 # flux excitation channel used to be a stimulus channel +FIFF.FIFFV_DIPOLE_WAVE = 1000 # Dipole time curve (xplotter/xfit) +FIFF.FIFFV_GOODNESS_FIT = 1001 # Goodness of fit (xplotter/xfit) +FIFF.FIFFV_FNIRS_CH = 1100 # Functional near-infrared spectroscopy +FIFF.FIFFV_TEMPERATURE_CH = 1200 # Functional near-infrared spectroscopy +FIFF.FIFFV_GALVANIC_CH = 1300 # Galvanic skin response +FIFF.FIFFV_EYETRACK_CH = 1400 # Eye-tracking + +_ch_kind_named = { + key: key + for key in ( + FIFF.FIFFV_BIO_CH, + FIFF.FIFFV_MEG_CH, + FIFF.FIFFV_REF_MEG_CH, + FIFF.FIFFV_EEG_CH, + FIFF.FIFFV_MCG_CH, + FIFF.FIFFV_STIM_CH, + FIFF.FIFFV_EOG_CH, + FIFF.FIFFV_EMG_CH, + FIFF.FIFFV_ECG_CH, + FIFF.FIFFV_MISC_CH, + FIFF.FIFFV_RESP_CH, + FIFF.FIFFV_SEEG_CH, + FIFF.FIFFV_DBS_CH, + FIFF.FIFFV_SYST_CH, + FIFF.FIFFV_ECOG_CH, + FIFF.FIFFV_IAS_CH, + FIFF.FIFFV_EXCI_CH, + FIFF.FIFFV_DIPOLE_WAVE, + FIFF.FIFFV_GOODNESS_FIT, + FIFF.FIFFV_FNIRS_CH, + FIFF.FIFFV_GALVANIC_CH, + FIFF.FIFFV_TEMPERATURE_CH, + FIFF.FIFFV_EYETRACK_CH, + ) +} + +# +# Quaternion channels for head position monitoring +# +FIFF.FIFFV_QUAT_0 = 700 # Quaternion param q0 obsolete for unit quaternion +FIFF.FIFFV_QUAT_1 = 701 # Quaternion param q1 rotation +FIFF.FIFFV_QUAT_2 = 702 # Quaternion param q2 rotation +FIFF.FIFFV_QUAT_3 = 703 # Quaternion param q3 rotation +FIFF.FIFFV_QUAT_4 = 704 # Quaternion param q4 translation +FIFF.FIFFV_QUAT_5 = 705 # Quaternion param q5 translation +FIFF.FIFFV_QUAT_6 = 706 # Quaternion param q6 translation +FIFF.FIFFV_HPI_G = 707 # Goodness-of-fit in continuous hpi +FIFF.FIFFV_HPI_ERR = 708 # Estimation error in continuous hpi +FIFF.FIFFV_HPI_MOV = 709 # Estimated head movement speed in continuous hpi +# +# Coordinate frames +# +FIFF.FIFFV_COORD_UNKNOWN = 0 +FIFF.FIFFV_COORD_DEVICE = 1 +FIFF.FIFFV_COORD_ISOTRAK = 2 +FIFF.FIFFV_COORD_HPI = 3 +FIFF.FIFFV_COORD_HEAD = 4 +FIFF.FIFFV_COORD_MRI = 5 +FIFF.FIFFV_COORD_MRI_SLICE = 6 +FIFF.FIFFV_COORD_MRI_DISPLAY = 7 +FIFF.FIFFV_COORD_DICOM_DEVICE = 8 +FIFF.FIFFV_COORD_IMAGING_DEVICE = 9 +_coord_frame_named = { + key: key + for key in ( + FIFF.FIFFV_COORD_UNKNOWN, + FIFF.FIFFV_COORD_DEVICE, + FIFF.FIFFV_COORD_ISOTRAK, + FIFF.FIFFV_COORD_HPI, + FIFF.FIFFV_COORD_HEAD, + FIFF.FIFFV_COORD_MRI, + # We never use these but could add at some point + # FIFF.FIFFV_COORD_MRI_SLICE, + # FIFF.FIFFV_COORD_MRI_DISPLAY, + # FIFF.FIFFV_COORD_DICOM_DEVICE, + # FIFF.FIFFV_COORD_IMAGING_DEVICE, + ) +} +# +# Needed for raw and evoked-response data +# +FIFF.FIFF_DATA_BUFFER = 300 # Buffer containing measurement data +FIFF.FIFF_DATA_SKIP = 301 # Data skip in buffers +FIFF.FIFF_EPOCH = 302 # Buffer containing one epoch and channel +FIFF.FIFF_DATA_SKIP_SAMP = 303 # Data skip in samples + +# +# Info on subject +# +FIFF.FIFF_SUBJ_ID = 400 # Subject ID +FIFF.FIFF_SUBJ_FIRST_NAME = 401 # First name of the subject +FIFF.FIFF_SUBJ_MIDDLE_NAME = 402 # Middle name of the subject +FIFF.FIFF_SUBJ_LAST_NAME = 403 # Last name of the subject +FIFF.FIFF_SUBJ_BIRTH_DAY = 404 # Birthday of the subject +FIFF.FIFF_SUBJ_SEX = 405 # Sex of the subject +FIFF.FIFF_SUBJ_HAND = 406 # Handedness of the subject +FIFF.FIFF_SUBJ_WEIGHT = 407 # Weight of the subject in kg +FIFF.FIFF_SUBJ_HEIGHT = 408 # Height of the subject in m +FIFF.FIFF_SUBJ_COMMENT = 409 # Comment about the subject +FIFF.FIFF_SUBJ_HIS_ID = 410 # ID used in the Hospital Information System + +FIFF.FIFFV_SUBJ_HAND_RIGHT = 1 # Righthanded +FIFF.FIFFV_SUBJ_HAND_LEFT = 2 # Lefthanded +FIFF.FIFFV_SUBJ_HAND_AMBI = 3 # Ambidextrous + +FIFF.FIFFV_SUBJ_SEX_UNKNOWN = 0 # Unknown gender +FIFF.FIFFV_SUBJ_SEX_MALE = 1 # Male +FIFF.FIFFV_SUBJ_SEX_FEMALE = 2 # Female + +FIFF.FIFF_PROJ_ID = 500 +FIFF.FIFF_PROJ_NAME = 501 +FIFF.FIFF_PROJ_AIM = 502 +FIFF.FIFF_PROJ_PERSONS = 503 +FIFF.FIFF_PROJ_COMMENT = 504 + +FIFF.FIFF_EVENT_CHANNELS = 600 # Event channel numbers +FIFF.FIFF_EVENT_LIST = 601 # List of events (integers: +FIFF.FIFF_EVENT_CHANNEL = 602 # Event channel +FIFF.FIFF_EVENT_BITS = 603 # Event bits array + +# +# Tags used in saving SQUID characteristics etc. +# +FIFF.FIFF_SQUID_BIAS = 701 +FIFF.FIFF_SQUID_OFFSET = 702 +FIFF.FIFF_SQUID_GATE = 703 +# +# Aspect values used to save characteristic curves of SQUIDs. (mjk) +# +FIFF.FIFFV_ASPECT_IFII_LOW = 1100 +FIFF.FIFFV_ASPECT_IFII_HIGH = 1101 +FIFF.FIFFV_ASPECT_GATE = 1102 + +# +# Values for file references +# +FIFF.FIFFV_ROLE_PREV_FILE = 1 +FIFF.FIFFV_ROLE_NEXT_FILE = 2 + +# +# References +# +FIFF.FIFF_REF_PATH = 1101 + +# +# Different aspects of data +# +FIFF.FIFFV_ASPECT_AVERAGE = 100 # Normal average of epochs +FIFF.FIFFV_ASPECT_STD_ERR = 101 # Std. error of mean +FIFF.FIFFV_ASPECT_SINGLE = 102 # Single epoch cut out from the continuous data +FIFF.FIFFV_ASPECT_SUBAVERAGE = 103 # Partial average (subaverage) +FIFF.FIFFV_ASPECT_ALTAVERAGE = 104 # Alternating subaverage +FIFF.FIFFV_ASPECT_SAMPLE = 105 # A sample cut out by graph +FIFF.FIFFV_ASPECT_POWER_DENSITY = 106 # Power density spectrum +FIFF.FIFFV_ASPECT_DIPOLE_WAVE = 200 # Dipole amplitude curve + +# +# BEM surface IDs +# +FIFF.FIFFV_BEM_SURF_ID_UNKNOWN = -1 +FIFF.FIFFV_BEM_SURF_ID_NOT_KNOWN = 0 +FIFF.FIFFV_BEM_SURF_ID_BRAIN = 1 +FIFF.FIFFV_BEM_SURF_ID_CSF = 2 +FIFF.FIFFV_BEM_SURF_ID_SKULL = 3 +FIFF.FIFFV_BEM_SURF_ID_HEAD = 4 + +FIFF.FIFF_SPHERE_ORIGIN = 3001 +FIFF.FIFF_SPHERE_RADIUS = 3002 + +FIFF.FIFF_BEM_SURF_ID = 3101 # int surface number +FIFF.FIFF_BEM_SURF_NAME = 3102 # string surface name +FIFF.FIFF_BEM_SURF_NNODE = 3103 # int number of nodes on a surface +FIFF.FIFF_BEM_SURF_NTRI = 3104 # int number of triangles on a surface +FIFF.FIFF_BEM_SURF_NODES = 3105 # float surface nodes (nnode,3) +FIFF.FIFF_BEM_SURF_TRIANGLES = 3106 # int surface triangles (ntri,3) +FIFF.FIFF_BEM_SURF_NORMALS = 3107 # float surface node normal unit vectors + +FIFF.FIFF_BEM_POT_SOLUTION = 3110 # float ** The solution matrix +FIFF.FIFF_BEM_APPROX = 3111 # int approximation method, see below +FIFF.FIFF_BEM_COORD_FRAME = 3112 # The coordinate frame of the model +FIFF.FIFF_BEM_SIGMA = 3113 # Conductivity of a compartment +FIFF.FIFFV_BEM_APPROX_CONST = 1 # The constant potential approach +FIFF.FIFFV_BEM_APPROX_LINEAR = 2 # The linear potential approach + +# +# More of those defined in MNE +# +FIFF.FIFFV_MNE_SURF_UNKNOWN = -1 +FIFF.FIFFV_MNE_SURF_LEFT_HEMI = 101 +FIFF.FIFFV_MNE_SURF_RIGHT_HEMI = 102 +FIFF.FIFFV_MNE_SURF_MEG_HELMET = 201 # Use this irrespective of the system +# +# These relate to the Isotrak data (enum(point)) +# +FIFF.FIFFV_POINT_CARDINAL = 1 +FIFF.FIFFV_POINT_HPI = 2 +FIFF.FIFFV_POINT_EEG = 3 +FIFF.FIFFV_POINT_ECG = FIFF.FIFFV_POINT_EEG +FIFF.FIFFV_POINT_EXTRA = 4 +FIFF.FIFFV_POINT_HEAD = 5 # Point on the surface of the head +_dig_kind_named = { + key: key + for key in ( + FIFF.FIFFV_POINT_CARDINAL, + FIFF.FIFFV_POINT_HPI, + FIFF.FIFFV_POINT_EEG, + FIFF.FIFFV_POINT_EXTRA, + FIFF.FIFFV_POINT_HEAD, + ) +} +# +# Cardinal point types (enum(cardinal_point)) +# +FIFF.FIFFV_POINT_LPA = 1 +FIFF.FIFFV_POINT_NASION = 2 +FIFF.FIFFV_POINT_RPA = 3 +FIFF.FIFFV_POINT_INION = 4 +_dig_cardinal_named = { + key: key + for key in ( + FIFF.FIFFV_POINT_LPA, + FIFF.FIFFV_POINT_NASION, + FIFF.FIFFV_POINT_RPA, + FIFF.FIFFV_POINT_INION, + ) +} +# +# SSP +# +FIFF.FIFF_PROJ_ITEM_KIND = 3411 +FIFF.FIFF_PROJ_ITEM_TIME = 3412 +FIFF.FIFF_PROJ_ITEM_NVEC = 3414 +FIFF.FIFF_PROJ_ITEM_VECTORS = 3415 +FIFF.FIFF_PROJ_ITEM_DEFINITION = 3416 +FIFF.FIFF_PROJ_ITEM_CH_NAME_LIST = 3417 +# XPlotter +FIFF.FIFF_XPLOTTER_LAYOUT = 3501 # string - "Xplotter layout tag" +# +# MRIs +# +FIFF.FIFF_MRI_SOURCE_PATH = FIFF.FIFF_REF_PATH +FIFF.FIFF_MRI_SOURCE_FORMAT = 2002 +FIFF.FIFF_MRI_PIXEL_ENCODING = 2003 +FIFF.FIFF_MRI_PIXEL_DATA_OFFSET = 2004 +FIFF.FIFF_MRI_PIXEL_SCALE = 2005 +FIFF.FIFF_MRI_PIXEL_DATA = 2006 +FIFF.FIFF_MRI_PIXEL_OVERLAY_ENCODING = 2007 +FIFF.FIFF_MRI_PIXEL_OVERLAY_DATA = 2008 +FIFF.FIFF_MRI_BOUNDING_BOX = 2009 +FIFF.FIFF_MRI_WIDTH = 2010 +FIFF.FIFF_MRI_WIDTH_M = 2011 +FIFF.FIFF_MRI_HEIGHT = 2012 +FIFF.FIFF_MRI_HEIGHT_M = 2013 +FIFF.FIFF_MRI_DEPTH = 2014 +FIFF.FIFF_MRI_DEPTH_M = 2015 +FIFF.FIFF_MRI_THICKNESS = 2016 +FIFF.FIFF_MRI_SCENE_AIM = 2017 +FIFF.FIFF_MRI_ORIG_SOURCE_PATH = 2020 +FIFF.FIFF_MRI_ORIG_SOURCE_FORMAT = 2021 +FIFF.FIFF_MRI_ORIG_PIXEL_ENCODING = 2022 +FIFF.FIFF_MRI_ORIG_PIXEL_DATA_OFFSET = 2023 +FIFF.FIFF_MRI_VOXEL_DATA = 2030 +FIFF.FIFF_MRI_VOXEL_ENCODING = 2031 +FIFF.FIFF_MRI_MRILAB_SETUP = 2100 +FIFF.FIFF_MRI_SEG_REGION_ID = 2200 +# +FIFF.FIFFV_MRI_PIXEL_UNKNOWN = 0 +FIFF.FIFFV_MRI_PIXEL_BYTE = 1 +FIFF.FIFFV_MRI_PIXEL_WORD = 2 +FIFF.FIFFV_MRI_PIXEL_SWAP_WORD = 3 +FIFF.FIFFV_MRI_PIXEL_FLOAT = 4 +FIFF.FIFFV_MRI_PIXEL_BYTE_INDEXED_COLOR = 5 +FIFF.FIFFV_MRI_PIXEL_BYTE_RGB_COLOR = 6 +FIFF.FIFFV_MRI_PIXEL_BYTE_RLE_RGB_COLOR = 7 +FIFF.FIFFV_MRI_PIXEL_BIT_RLE = 8 +# +# These are the MNE fiff definitions (range 350-390 reserved for MNE) +# +FIFF.FIFFB_MNE = 350 +FIFF.FIFFB_MNE_SOURCE_SPACE = 351 +FIFF.FIFFB_MNE_FORWARD_SOLUTION = 352 +FIFF.FIFFB_MNE_PARENT_MRI_FILE = 353 +FIFF.FIFFB_MNE_PARENT_MEAS_FILE = 354 +FIFF.FIFFB_MNE_COV = 355 +FIFF.FIFFB_MNE_INVERSE_SOLUTION = 356 +FIFF.FIFFB_MNE_NAMED_MATRIX = 357 +FIFF.FIFFB_MNE_ENV = 358 +FIFF.FIFFB_MNE_BAD_CHANNELS = 359 +FIFF.FIFFB_MNE_VERTEX_MAP = 360 +FIFF.FIFFB_MNE_EVENTS = 361 +FIFF.FIFFB_MNE_MORPH_MAP = 362 +FIFF.FIFFB_MNE_SURFACE_MAP = 363 +FIFF.FIFFB_MNE_SURFACE_MAP_GROUP = 364 + +# +# CTF compensation data +# +FIFF.FIFFB_MNE_CTF_COMP = 370 +FIFF.FIFFB_MNE_CTF_COMP_DATA = 371 +FIFF.FIFFB_MNE_DERIVATIONS = 372 + +FIFF.FIFFB_MNE_EPOCHS = 373 +FIFF.FIFFB_MNE_ICA = 374 +# +# Fiff tags associated with MNE computations (3500...) +# +# +# 3500... Bookkeeping +# +FIFF.FIFF_MNE_ROW_NAMES = 3502 +FIFF.FIFF_MNE_COL_NAMES = 3503 +FIFF.FIFF_MNE_NROW = 3504 +FIFF.FIFF_MNE_NCOL = 3505 +FIFF.FIFF_MNE_COORD_FRAME = 3506 # Coordinate frame employed. Defaults: +# FIFFB_MNE_SOURCE_SPACE FIFFV_COORD_MRI +# FIFFB_MNE_FORWARD_SOLUTION FIFFV_COORD_HEAD +# FIFFB_MNE_INVERSE_SOLUTION FIFFV_COORD_HEAD +FIFF.FIFF_MNE_CH_NAME_LIST = 3507 +FIFF.FIFF_MNE_FILE_NAME = ( + 3508 # This removes the collision with fiff_file.h (used to be 3501) +) +# +# 3510... 3590... Source space or surface +# +FIFF.FIFF_MNE_SOURCE_SPACE_POINTS = 3510 # The vertices +FIFF.FIFF_MNE_SOURCE_SPACE_NORMALS = 3511 # The vertex normals +FIFF.FIFF_MNE_SOURCE_SPACE_NPOINTS = 3512 # How many vertices +FIFF.FIFF_MNE_SOURCE_SPACE_SELECTION = 3513 # Which are selected to the source space +FIFF.FIFF_MNE_SOURCE_SPACE_NUSE = 3514 # How many are in use +FIFF.FIFF_MNE_SOURCE_SPACE_NEAREST = ( + 3515 # Nearest source space vertex for all vertices +) +FIFF.FIFF_MNE_SOURCE_SPACE_NEAREST_DIST = ( + 3516 # Distance to the Nearest source space vertex for all vertices +) +FIFF.FIFF_MNE_SOURCE_SPACE_ID = 3517 # Identifier +FIFF.FIFF_MNE_SOURCE_SPACE_TYPE = 3518 # Surface or volume +FIFF.FIFF_MNE_SOURCE_SPACE_VERTICES = 3519 # List of vertices (zero based) + +FIFF.FIFF_MNE_SOURCE_SPACE_VOXEL_DIMS = ( + 3596 # Voxel space dimensions in a volume source space +) +FIFF.FIFF_MNE_SOURCE_SPACE_INTERPOLATOR = ( + 3597 # Matrix to interpolate a volume source space into a mri volume +) +FIFF.FIFF_MNE_SOURCE_SPACE_MRI_FILE = 3598 # MRI file used in the interpolation + +FIFF.FIFF_MNE_SOURCE_SPACE_NTRI = 3590 # Number of triangles +FIFF.FIFF_MNE_SOURCE_SPACE_TRIANGLES = 3591 # The triangulation +FIFF.FIFF_MNE_SOURCE_SPACE_NUSE_TRI = ( + 3592 # Number of triangles corresponding to the number of vertices in use +) +FIFF.FIFF_MNE_SOURCE_SPACE_USE_TRIANGLES = ( + 3593 # The triangulation of the used vertices in the source space +) +FIFF.FIFF_MNE_SOURCE_SPACE_NNEIGHBORS = 3594 # Number of neighbors for each source space point (used for volume source spaces) +FIFF.FIFF_MNE_SOURCE_SPACE_NEIGHBORS = ( + 3595 # Neighbors for each source space point (used for volume source spaces) +) + +FIFF.FIFF_MNE_SOURCE_SPACE_DIST = ( + 3599 # Distances between vertices in use (along the surface) +) +FIFF.FIFF_MNE_SOURCE_SPACE_DIST_LIMIT = ( + 3600 # If distance is above this limit (in the volume) it has not been calculated +) + +FIFF.FIFF_MNE_SURFACE_MAP_DATA = 3610 # Surface map data +FIFF.FIFF_MNE_SURFACE_MAP_KIND = 3611 # Type of map + +# +# 3520... Forward solution +# +FIFF.FIFF_MNE_FORWARD_SOLUTION = 3520 +FIFF.FIFF_MNE_SOURCE_ORIENTATION = 3521 # Fixed or free +FIFF.FIFF_MNE_INCLUDED_METHODS = 3522 +FIFF.FIFF_MNE_FORWARD_SOLUTION_GRAD = 3523 +# +# 3530... Covariance matrix +# +FIFF.FIFF_MNE_COV_KIND = 3530 # What kind of a covariance matrix +FIFF.FIFF_MNE_COV_DIM = 3531 # Matrix dimension +FIFF.FIFF_MNE_COV = 3532 # Full matrix in packed representation (lower triangle) +FIFF.FIFF_MNE_COV_DIAG = 3533 # Diagonal matrix +FIFF.FIFF_MNE_COV_EIGENVALUES = 3534 # Eigenvalues and eigenvectors of the above +FIFF.FIFF_MNE_COV_EIGENVECTORS = 3535 +FIFF.FIFF_MNE_COV_NFREE = 3536 # Number of degrees of freedom +FIFF.FIFF_MNE_COV_METHOD = 3537 # The estimator used +FIFF.FIFF_MNE_COV_SCORE = 3538 # Negative log-likelihood + +# +# 3540... Inverse operator +# +# We store the inverse operator as the eigenleads, eigenfields, +# and weights +# +FIFF.FIFF_MNE_INVERSE_LEADS = 3540 # The eigenleads +FIFF.FIFF_MNE_INVERSE_LEADS_WEIGHTED = ( + 3546 # The eigenleads (already weighted with R^0.5) +) +FIFF.FIFF_MNE_INVERSE_FIELDS = 3541 # The eigenfields +FIFF.FIFF_MNE_INVERSE_SING = 3542 # The singular values +FIFF.FIFF_MNE_PRIORS_USED = ( + 3543 # Which kind of priors have been used for the source covariance matrix +) +FIFF.FIFF_MNE_INVERSE_FULL = 3544 # Inverse operator as one matrix +# This matrix includes the whitening operator as well +# The regularization is applied +FIFF.FIFF_MNE_INVERSE_SOURCE_ORIENTATIONS = ( + 3545 # Contains the orientation of one source per row +) +# The source orientations must be expressed in the coordinate system +# given by FIFF_MNE_COORD_FRAME +FIFF.FIFF_MNE_INVERSE_SOURCE_UNIT = 3547 # Are the sources given in Am or Am/m^2 ? +# +# 3550... Saved environment info +# +FIFF.FIFF_MNE_ENV_WORKING_DIR = 3550 # Working directory where the file was created +FIFF.FIFF_MNE_ENV_COMMAND_LINE = 3551 # The command used to create the file +FIFF.FIFF_MNE_EXTERNAL_BIG_ENDIAN = ( + 3552 # Reference to an external binary file (big-endian) */ +) +FIFF.FIFF_MNE_EXTERNAL_LITTLE_ENDIAN = ( + 3553 # Reference to an external binary file (little-endian) */ +) +# +# 3560... Miscellaneous +# +FIFF.FIFF_MNE_PROJ_ITEM_ACTIVE = 3560 # Is this projection item active? +FIFF.FIFF_MNE_EVENT_LIST = 3561 # An event list (for STI101 / STI 014) +FIFF.FIFF_MNE_HEMI = 3562 # Hemisphere association for general purposes +FIFF.FIFF_MNE_DATA_SKIP_NOP = 3563 # A data skip turned off in the raw data +FIFF.FIFF_MNE_ORIG_CH_INFO = 3564 # Channel information before any changes +FIFF.FIFF_MNE_EVENT_TRIGGER_MASK = 3565 # Mask applied to the trigger channel values +FIFF.FIFF_MNE_EVENT_COMMENTS = 3566 # Event comments merged into one long string +FIFF.FIFF_MNE_CUSTOM_REF = 3567 # Whether a custom reference was applied to the data +FIFF.FIFF_MNE_BASELINE_MIN = 3568 # Time of baseline beginning +FIFF.FIFF_MNE_BASELINE_MAX = 3569 # Time of baseline end +# +# 3570... Morphing maps +# +FIFF.FIFF_MNE_MORPH_MAP = 3570 # Mapping of closest vertices on the sphere +FIFF.FIFF_MNE_MORPH_MAP_FROM = 3571 # Which subject is this map from +FIFF.FIFF_MNE_MORPH_MAP_TO = 3572 # Which subject is this map to +# +# 3580... CTF compensation data +# +FIFF.FIFF_MNE_CTF_COMP_KIND = 3580 # What kind of compensation +FIFF.FIFF_MNE_CTF_COMP_DATA = 3581 # The compensation data itself +FIFF.FIFF_MNE_CTF_COMP_CALIBRATED = 3582 # Are the coefficients calibrated? + +FIFF.FIFF_MNE_DERIVATION_DATA = ( + 3585 # Used to store information about EEG and other derivations +) +# +# 3601... values associated with ICA decomposition +# +FIFF.FIFF_MNE_ICA_INTERFACE_PARAMS = 3601 # ICA interface parameters +FIFF.FIFF_MNE_ICA_CHANNEL_NAMES = 3602 # ICA channel names +FIFF.FIFF_MNE_ICA_WHITENER = 3603 # ICA whitener +FIFF.FIFF_MNE_ICA_PCA_COMPONENTS = 3604 # PCA components +FIFF.FIFF_MNE_ICA_PCA_EXPLAINED_VAR = 3605 # PCA explained variance +FIFF.FIFF_MNE_ICA_PCA_MEAN = 3606 # PCA mean +FIFF.FIFF_MNE_ICA_MATRIX = 3607 # ICA unmixing matrix +FIFF.FIFF_MNE_ICA_BADS = 3608 # ICA bad sources +FIFF.FIFF_MNE_ICA_MISC_PARAMS = 3609 # ICA misc params +# +# Miscellaneous +# +FIFF.FIFF_MNE_KIT_SYSTEM_ID = 3612 # Unique ID assigned to KIT systems +# +# Maxfilter tags +# +FIFF.FIFF_SSS_FRAME = 263 +FIFF.FIFF_SSS_JOB = 264 +FIFF.FIFF_SSS_ORIGIN = 265 +FIFF.FIFF_SSS_ORD_IN = 266 +FIFF.FIFF_SSS_ORD_OUT = 267 +FIFF.FIFF_SSS_NMAG = 268 +FIFF.FIFF_SSS_COMPONENTS = 269 +FIFF.FIFF_SSS_CAL_CHANS = 270 +FIFF.FIFF_SSS_CAL_CORRS = 271 +FIFF.FIFF_SSS_ST_CORR = 272 +FIFF.FIFF_SSS_NFREE = 278 +FIFF.FIFF_SSS_ST_LENGTH = 279 +FIFF.FIFF_DECOUPLER_MATRIX = 800 +# +# Fiff values associated with MNE computations +# +FIFF.FIFFV_MNE_UNKNOWN_ORI = 0 +FIFF.FIFFV_MNE_FIXED_ORI = 1 +FIFF.FIFFV_MNE_FREE_ORI = 2 + +FIFF.FIFFV_MNE_MEG = 1 +FIFF.FIFFV_MNE_EEG = 2 +FIFF.FIFFV_MNE_MEG_EEG = 3 + +FIFF.FIFFV_MNE_PRIORS_NONE = 0 +FIFF.FIFFV_MNE_PRIORS_DEPTH = 1 +FIFF.FIFFV_MNE_PRIORS_LORETA = 2 +FIFF.FIFFV_MNE_PRIORS_SULCI = 3 + +FIFF.FIFFV_MNE_UNKNOWN_COV = 0 +FIFF.FIFFV_MNE_SENSOR_COV = 1 +FIFF.FIFFV_MNE_NOISE_COV = 1 # This is what it should have been called +FIFF.FIFFV_MNE_SOURCE_COV = 2 +FIFF.FIFFV_MNE_FMRI_PRIOR_COV = 3 +FIFF.FIFFV_MNE_SIGNAL_COV = 4 # This will be potentially employed in beamformers +FIFF.FIFFV_MNE_DEPTH_PRIOR_COV = 5 # The depth weighting prior +FIFF.FIFFV_MNE_ORIENT_PRIOR_COV = 6 # The orientation prior + +# +# Output map types +# +FIFF.FIFFV_MNE_MAP_UNKNOWN = -1 # Unspecified +FIFF.FIFFV_MNE_MAP_SCALAR_CURRENT = 1 # Scalar current value +FIFF.FIFFV_MNE_MAP_SCALAR_CURRENT_SIZE = 2 # Absolute value of the above +FIFF.FIFFV_MNE_MAP_VECTOR_CURRENT = 3 # Current vector components +FIFF.FIFFV_MNE_MAP_VECTOR_CURRENT_SIZE = 4 # Vector current size +FIFF.FIFFV_MNE_MAP_T_STAT = 5 # Student's t statistic +FIFF.FIFFV_MNE_MAP_F_STAT = 6 # F statistic +FIFF.FIFFV_MNE_MAP_F_STAT_SQRT = 7 # Square root of the F statistic +FIFF.FIFFV_MNE_MAP_CHI2_STAT = 8 # (Approximate) chi^2 statistic +FIFF.FIFFV_MNE_MAP_CHI2_STAT_SQRT = ( + 9 # Square root of the (approximate) chi^2 statistic +) +FIFF.FIFFV_MNE_MAP_SCALAR_CURRENT_NOISE = 10 # Current noise approximation (scalar) +FIFF.FIFFV_MNE_MAP_VECTOR_CURRENT_NOISE = 11 # Current noise approximation (vector) +# +# Source space types (values of FIFF_MNE_SOURCE_SPACE_TYPE) +# +FIFF.FIFFV_MNE_SPACE_UNKNOWN = -1 +FIFF.FIFFV_MNE_SPACE_SURFACE = 1 +FIFF.FIFFV_MNE_SPACE_VOLUME = 2 +FIFF.FIFFV_MNE_SPACE_DISCRETE = 3 +# +# Covariance matrix channel classification +# +FIFF.FIFFV_MNE_COV_CH_UNKNOWN = -1 # No idea +FIFF.FIFFV_MNE_COV_CH_MEG_MAG = 0 # Axial gradiometer or magnetometer [T] +FIFF.FIFFV_MNE_COV_CH_MEG_GRAD = 1 # Planar gradiometer [T/m] +FIFF.FIFFV_MNE_COV_CH_EEG = 2 # EEG [V] +# +# Projection item kinds +# +FIFF.FIFFV_PROJ_ITEM_NONE = 0 +FIFF.FIFFV_PROJ_ITEM_FIELD = 1 +FIFF.FIFFV_PROJ_ITEM_DIP_FIX = 2 +FIFF.FIFFV_PROJ_ITEM_DIP_ROT = 3 +FIFF.FIFFV_PROJ_ITEM_HOMOG_GRAD = 4 +FIFF.FIFFV_PROJ_ITEM_HOMOG_FIELD = 5 +FIFF.FIFFV_PROJ_ITEM_EEG_AVREF = ( + 10 # Linear projection related to EEG average reference +) +FIFF.FIFFV_MNE_PROJ_ITEM_EEG_AVREF = ( + FIFF.FIFFV_PROJ_ITEM_EEG_AVREF +) # backward compat alias +# +# Custom EEG references +# +FIFF.FIFFV_MNE_CUSTOM_REF_OFF = 0 +FIFF.FIFFV_MNE_CUSTOM_REF_ON = 1 +FIFF.FIFFV_MNE_CUSTOM_REF_CSD = 2 +# +# SSS job options +# +FIFF.FIFFV_SSS_JOB_NOTHING = 0 # No SSS, just copy input to output +FIFF.FIFFV_SSS_JOB_CTC = 1 # No SSS, only cross-talk correction +FIFF.FIFFV_SSS_JOB_FILTER = 2 # Spatial maxwell filtering +FIFF.FIFFV_SSS_JOB_VIRT = 3 # Transform data to another sensor array +FIFF.FIFFV_SSS_JOB_HEAD_POS = 4 # Estimate head positions, no SSS +FIFF.FIFFV_SSS_JOB_MOVEC_FIT = 5 # Estimate and compensate head movement +FIFF.FIFFV_SSS_JOB_MOVEC_QUA = ( + 6 # Compensate head movement from previously estimated head positions +) +FIFF.FIFFV_SSS_JOB_REC_ALL = 7 # Reconstruct inside and outside signals +FIFF.FIFFV_SSS_JOB_REC_IN = 8 # Reconstruct inside signals +FIFF.FIFFV_SSS_JOB_REC_OUT = 9 # Reconstruct outside signals +FIFF.FIFFV_SSS_JOB_ST = 10 # Spatio-temporal maxwell filtering +FIFF.FIFFV_SSS_JOB_TPROJ = 11 # Temporal projection, no SSS +FIFF.FIFFV_SSS_JOB_XSSS = 12 # Cross-validation SSS +FIFF.FIFFV_SSS_JOB_XSUB = 13 # Cross-validation subtraction, no SSS +FIFF.FIFFV_SSS_JOB_XWAV = 14 # Cross-validation noise waveforms +FIFF.FIFFV_SSS_JOB_NCOV = 15 # Noise covariance estimation +FIFF.FIFFV_SSS_JOB_SCOV = 16 # SSS sample covariance estimation +# } + +# +# Additional coordinate frames +# +FIFF.FIFFV_MNE_COORD_TUFTS_EEG = 300 # For Tufts EEG data +FIFF.FIFFV_MNE_COORD_CTF_DEVICE = 1001 # CTF device coordinates +FIFF.FIFFV_MNE_COORD_CTF_HEAD = 1004 # CTF head coordinates +FIFF.FIFFV_MNE_COORD_DIGITIZER = ( + FIFF.FIFFV_COORD_ISOTRAK +) # Original (Polhemus) digitizer coordinates +FIFF.FIFFV_MNE_COORD_SURFACE_RAS = FIFF.FIFFV_COORD_MRI # The surface RAS coordinates +FIFF.FIFFV_MNE_COORD_MRI_VOXEL = 2001 # The MRI voxel coordinates +FIFF.FIFFV_MNE_COORD_RAS = 2002 # Surface RAS coordinates with non-zero origin +FIFF.FIFFV_MNE_COORD_MNI_TAL = 2003 # MNI Talairach coordinates +FIFF.FIFFV_MNE_COORD_FS_TAL_GTZ = 2004 # FreeSurfer Talairach coordinates (MNI z > 0) +FIFF.FIFFV_MNE_COORD_FS_TAL_LTZ = 2005 # FreeSurfer Talairach coordinates (MNI z < 0) +FIFF.FIFFV_MNE_COORD_FS_TAL = 2006 # FreeSurfer Talairach coordinates +# +# 4D and KIT use the same head coordinate system definition as CTF +# +FIFF.FIFFV_MNE_COORD_4D_HEAD = FIFF.FIFFV_MNE_COORD_CTF_HEAD +FIFF.FIFFV_MNE_COORD_KIT_HEAD = FIFF.FIFFV_MNE_COORD_CTF_HEAD +_coord_frame_named.update({ + key: key + for key in ( + FIFF.FIFFV_MNE_COORD_CTF_DEVICE, + FIFF.FIFFV_MNE_COORD_MRI_VOXEL, + FIFF.FIFFV_MNE_COORD_RAS, + FIFF.FIFFV_MNE_COORD_MNI_TAL, + FIFF.FIFFV_MNE_COORD_FS_TAL, + FIFF.FIFFV_MNE_COORD_KIT_HEAD, + ) +}) + +# +# FWD Types +# + +FWD = BunchConstNamed() + +FWD.COIL_UNKNOWN = 0 +FWD.COILC_UNKNOWN = 0 +FWD.COILC_EEG = 1000 +FWD.COILC_MAG = 1 +FWD.COILC_AXIAL_GRAD = 2 +FWD.COILC_PLANAR_GRAD = 3 +FWD.COILC_AXIAL_GRAD2 = 4 + +FWD.COIL_ACCURACY_POINT = 0 +FWD.COIL_ACCURACY_NORMAL = 1 +FWD.COIL_ACCURACY_ACCURATE = 2 + +FWD.BEM_IP_APPROACH_LIMIT = 0.1 + +FWD.BEM_LIN_FIELD_SIMPLE = 1 +FWD.BEM_LIN_FIELD_FERGUSON = 2 +FWD.BEM_LIN_FIELD_URANKAR = 3 + +# +# Data types +# +FIFF.FIFFT_VOID = 0 +FIFF.FIFFT_BYTE = 1 +FIFF.FIFFT_SHORT = 2 +FIFF.FIFFT_INT = 3 +FIFF.FIFFT_FLOAT = 4 +FIFF.FIFFT_DOUBLE = 5 +FIFF.FIFFT_JULIAN = 6 +FIFF.FIFFT_USHORT = 7 +FIFF.FIFFT_UINT = 8 +FIFF.FIFFT_ULONG = 9 +FIFF.FIFFT_STRING = 10 +FIFF.FIFFT_LONG = 11 +FIFF.FIFFT_DAU_PACK13 = 13 +FIFF.FIFFT_DAU_PACK14 = 14 +FIFF.FIFFT_DAU_PACK16 = 16 +FIFF.FIFFT_COMPLEX_FLOAT = 20 +FIFF.FIFFT_COMPLEX_DOUBLE = 21 +FIFF.FIFFT_OLD_PACK = 23 +FIFF.FIFFT_CH_INFO_STRUCT = 30 +FIFF.FIFFT_ID_STRUCT = 31 +FIFF.FIFFT_DIR_ENTRY_STRUCT = 32 +FIFF.FIFFT_DIG_POINT_STRUCT = 33 +FIFF.FIFFT_CH_POS_STRUCT = 34 +FIFF.FIFFT_COORD_TRANS_STRUCT = 35 +FIFF.FIFFT_DIG_STRING_STRUCT = 36 +FIFF.FIFFT_STREAM_SEGMENT_STRUCT = 37 +FIFF.FIFFT_MATRIX = 0x40000000 # 1073741824, 1 << 30 +FIFF.FIFFT_SPARSE_CCS_MATRIX = 0x00100000 # 1048576 +FIFF.FIFFT_SPARSE_RCS_MATRIX = 0x00200000 # 2097152 + +# +# Units of measurement +# +FIFF.FIFF_UNIT_NONE = -1 +# +# SI base units +# +FIFF.FIFF_UNIT_UNITLESS = 0 +FIFF.FIFF_UNIT_M = 1 # meter +FIFF.FIFF_UNIT_KG = 2 # kilogram +FIFF.FIFF_UNIT_SEC = 3 # second +FIFF.FIFF_UNIT_A = 4 # ampere +FIFF.FIFF_UNIT_K = 5 # Kelvin +FIFF.FIFF_UNIT_MOL = 6 # mole +# +# SI Supplementary units +# +FIFF.FIFF_UNIT_RAD = 7 # radian +FIFF.FIFF_UNIT_SR = 8 # steradian +# +# SI base candela +# +FIFF.FIFF_UNIT_CD = 9 # candela +# +# SI derived units +# +FIFF.FIFF_UNIT_MOL_M3 = 10 # mol/m^3 +FIFF.FIFF_UNIT_HZ = 101 # hertz +FIFF.FIFF_UNIT_N = 102 # Newton +FIFF.FIFF_UNIT_PA = 103 # pascal +FIFF.FIFF_UNIT_J = 104 # joule +FIFF.FIFF_UNIT_W = 105 # watt +FIFF.FIFF_UNIT_C = 106 # coulomb +FIFF.FIFF_UNIT_V = 107 # volt +FIFF.FIFF_UNIT_F = 108 # farad +FIFF.FIFF_UNIT_OHM = 109 # ohm +FIFF.FIFF_UNIT_S = 110 # Siemens (same as Moh, what fiff-constants calls it) +FIFF.FIFF_UNIT_WB = 111 # weber +FIFF.FIFF_UNIT_T = 112 # tesla +FIFF.FIFF_UNIT_H = 113 # Henry +FIFF.FIFF_UNIT_CEL = 114 # celsius +FIFF.FIFF_UNIT_LM = 115 # lumen +FIFF.FIFF_UNIT_LX = 116 # lux +FIFF.FIFF_UNIT_V_M2 = 117 # V/m^2 +# +# Others we need +# +FIFF.FIFF_UNIT_T_M = 201 # T/m +FIFF.FIFF_UNIT_AM = 202 # Am +FIFF.FIFF_UNIT_AM_M2 = 203 # Am/m^2 +FIFF.FIFF_UNIT_AM_M3 = 204 # Am/m^3 + +FIFF.FIFF_UNIT_PX = 210 # Pixel +_ch_unit_named = { + key: key + for key in ( + FIFF.FIFF_UNIT_NONE, + FIFF.FIFF_UNIT_UNITLESS, + FIFF.FIFF_UNIT_M, + FIFF.FIFF_UNIT_KG, + FIFF.FIFF_UNIT_SEC, + FIFF.FIFF_UNIT_A, + FIFF.FIFF_UNIT_K, + FIFF.FIFF_UNIT_MOL, + FIFF.FIFF_UNIT_RAD, + FIFF.FIFF_UNIT_SR, + FIFF.FIFF_UNIT_CD, + FIFF.FIFF_UNIT_MOL_M3, + FIFF.FIFF_UNIT_HZ, + FIFF.FIFF_UNIT_N, + FIFF.FIFF_UNIT_PA, + FIFF.FIFF_UNIT_J, + FIFF.FIFF_UNIT_W, + FIFF.FIFF_UNIT_C, + FIFF.FIFF_UNIT_V, + FIFF.FIFF_UNIT_F, + FIFF.FIFF_UNIT_OHM, + FIFF.FIFF_UNIT_S, + FIFF.FIFF_UNIT_WB, + FIFF.FIFF_UNIT_T, + FIFF.FIFF_UNIT_H, + FIFF.FIFF_UNIT_CEL, + FIFF.FIFF_UNIT_LM, + FIFF.FIFF_UNIT_LX, + FIFF.FIFF_UNIT_V_M2, + FIFF.FIFF_UNIT_T_M, + FIFF.FIFF_UNIT_AM, + FIFF.FIFF_UNIT_AM_M2, + FIFF.FIFF_UNIT_AM_M3, + FIFF.FIFF_UNIT_PX, + ) +} +# +# Multipliers +# +FIFF.FIFF_UNITM_E = 18 +FIFF.FIFF_UNITM_PET = 15 +FIFF.FIFF_UNITM_T = 12 +FIFF.FIFF_UNITM_GIG = 9 +FIFF.FIFF_UNITM_MEG = 6 +FIFF.FIFF_UNITM_K = 3 +FIFF.FIFF_UNITM_H = 2 +FIFF.FIFF_UNITM_DA = 1 +FIFF.FIFF_UNITM_NONE = 0 +FIFF.FIFF_UNITM_D = -1 +FIFF.FIFF_UNITM_C = -2 +FIFF.FIFF_UNITM_M = -3 +FIFF.FIFF_UNITM_MU = -6 +FIFF.FIFF_UNITM_N = -9 +FIFF.FIFF_UNITM_P = -12 +FIFF.FIFF_UNITM_F = -15 +FIFF.FIFF_UNITM_A = -18 +_ch_unit_mul_named = { + key: key + for key in ( + FIFF.FIFF_UNITM_E, + FIFF.FIFF_UNITM_PET, + FIFF.FIFF_UNITM_T, + FIFF.FIFF_UNITM_GIG, + FIFF.FIFF_UNITM_MEG, + FIFF.FIFF_UNITM_K, + FIFF.FIFF_UNITM_H, + FIFF.FIFF_UNITM_DA, + FIFF.FIFF_UNITM_NONE, + FIFF.FIFF_UNITM_D, + FIFF.FIFF_UNITM_C, + FIFF.FIFF_UNITM_M, + FIFF.FIFF_UNITM_MU, + FIFF.FIFF_UNITM_N, + FIFF.FIFF_UNITM_P, + FIFF.FIFF_UNITM_F, + FIFF.FIFF_UNITM_A, + ) +} + +# +# Coil types +# +FIFF.FIFFV_COIL_NONE = 0 # The location info contains no data +FIFF.FIFFV_COIL_EEG = 1 # EEG electrode position in r0 +FIFF.FIFFV_COIL_NM_122 = 2 # Neuromag 122 coils +FIFF.FIFFV_COIL_NM_24 = 3 # Old 24 channel system in HUT +FIFF.FIFFV_COIL_NM_MCG_AXIAL = 4 # The axial devices in the HUCS MCG system +FIFF.FIFFV_COIL_EEG_BIPOLAR = 5 # Bipolar EEG lead +FIFF.FIFFV_COIL_EEG_CSD = 6 # CSD-transformed EEG lead + +FIFF.FIFFV_COIL_DIPOLE = 200 # Time-varying dipole definition +# The coil info contains dipole location (r0) and +# direction (ex) +FIFF.FIFFV_COIL_FNIRS_HBO = 300 # fNIRS oxyhemoglobin +FIFF.FIFFV_COIL_FNIRS_HBR = 301 # fNIRS deoxyhemoglobin +FIFF.FIFFV_COIL_FNIRS_CW_AMPLITUDE = 302 # fNIRS continuous wave amplitude +FIFF.FIFFV_COIL_FNIRS_OD = 303 # fNIRS optical density +FIFF.FIFFV_COIL_FNIRS_FD_AC_AMPLITUDE = 304 # fNIRS frequency domain AC amplitude +FIFF.FIFFV_COIL_FNIRS_FD_PHASE = 305 # fNIRS frequency domain phase +FIFF.FIFFV_COIL_FNIRS_RAW = FIFF.FIFFV_COIL_FNIRS_CW_AMPLITUDE # old alias +FIFF.FIFFV_COIL_FNIRS_TD_GATED_AMPLITUDE = 306 # fNIRS time-domain gated amplitude +FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_AMPLITUDE = 307 # fNIRS time-domain moments amplitude + +FIFF.FIFFV_COIL_EYETRACK_POS = 400 # Eye-tracking gaze position +FIFF.FIFFV_COIL_EYETRACK_PUPIL = 401 # Eye-tracking pupil size + +FIFF.FIFFV_COIL_MCG_42 = 1000 # For testing the MCG software + +FIFF.FIFFV_COIL_POINT_MAGNETOMETER = 2000 # Simple point magnetometer +FIFF.FIFFV_COIL_AXIAL_GRAD_5CM = 2001 # Generic axial gradiometer + +FIFF.FIFFV_COIL_VV_PLANAR_W = 3011 # VV prototype wirewound planar sensor +FIFF.FIFFV_COIL_VV_PLANAR_T1 = 3012 # Vectorview SQ20483N planar gradiometer +FIFF.FIFFV_COIL_VV_PLANAR_T2 = 3013 # Vectorview SQ20483N-A planar gradiometer +FIFF.FIFFV_COIL_VV_PLANAR_T3 = 3014 # Vectorview SQ20950N planar gradiometer +FIFF.FIFFV_COIL_VV_PLANAR_T4 = 3015 # Vectorview planar gradiometer (MEG-MRI) +FIFF.FIFFV_COIL_VV_MAG_W = 3021 # VV prototype wirewound magnetometer +FIFF.FIFFV_COIL_VV_MAG_T1 = 3022 # Vectorview SQ20483N magnetometer +FIFF.FIFFV_COIL_VV_MAG_T2 = 3023 # Vectorview SQ20483-A magnetometer +FIFF.FIFFV_COIL_VV_MAG_T3 = 3024 # Vectorview SQ20950N magnetometer +FIFF.FIFFV_COIL_VV_MAG_T4 = 3025 # Vectorview magnetometer (MEG-MRI) + +FIFF.FIFFV_COIL_MAGNES_MAG = 4001 # Magnes WH magnetometer +FIFF.FIFFV_COIL_MAGNES_GRAD = 4002 # Magnes WH gradiometer +# +# Magnes reference sensors +# +FIFF.FIFFV_COIL_MAGNES_REF_MAG = 4003 +FIFF.FIFFV_COIL_MAGNES_REF_GRAD = 4004 +FIFF.FIFFV_COIL_MAGNES_OFFDIAG_REF_GRAD = 4005 +FIFF.FIFFV_COIL_MAGNES_R_MAG = FIFF.FIFFV_COIL_MAGNES_REF_MAG +FIFF.FIFFV_COIL_MAGNES_R_GRAD = FIFF.FIFFV_COIL_MAGNES_REF_GRAD +FIFF.FIFFV_COIL_MAGNES_R_GRAD_OFF = FIFF.FIFFV_COIL_MAGNES_OFFDIAG_REF_GRAD + +# +# CTF coil and channel types +# +FIFF.FIFFV_COIL_CTF_GRAD = 5001 +FIFF.FIFFV_COIL_CTF_REF_MAG = 5002 +FIFF.FIFFV_COIL_CTF_REF_GRAD = 5003 +FIFF.FIFFV_COIL_CTF_OFFDIAG_REF_GRAD = 5004 +# +# KIT system coil types +# +FIFF.FIFFV_COIL_KIT_GRAD = 6001 +FIFF.FIFFV_COIL_KIT_REF_MAG = 6002 +# +# BabySQUID sensors +# +FIFF.FIFFV_COIL_BABY_GRAD = 7001 +# +# BabyMEG sensors +# +FIFF.FIFFV_COIL_BABY_MAG = 7002 +FIFF.FIFFV_COIL_BABY_REF_MAG = 7003 +FIFF.FIFFV_COIL_BABY_REF_MAG2 = 7004 +# +# Artemis123 sensors +# +FIFF.FIFFV_COIL_ARTEMIS123_GRAD = 7501 +FIFF.FIFFV_COIL_ARTEMIS123_REF_MAG = 7502 +FIFF.FIFFV_COIL_ARTEMIS123_REF_GRAD = 7503 +# +# QuSpin sensors +# +FIFF.FIFFV_COIL_QUSPIN_ZFOPM_MAG = 8001 +FIFF.FIFFV_COIL_QUSPIN_ZFOPM_MAG2 = 8002 +# +# FieldLine sensors +# +FIFF.FIFFV_COIL_FIELDLINE_OPM_MAG_GEN1 = 8101 +# +# Kernel sensors +# +FIFF.FIFFV_COIL_KERNEL_OPM_MAG_GEN1 = 8201 +# +# KRISS sensors +# +FIFF.FIFFV_COIL_KRISS_GRAD = 9001 +# +# Compumedics adult/pediatric gradiometer +# +FIFF.FIFFV_COIL_COMPUMEDICS_ADULT_GRAD = 9101 +FIFF.FIFFV_COIL_COMPUMEDICS_PEDIATRIC_GRAD = 9102 +_ch_coil_type_named = { + key: key + for key in ( + FIFF.FIFFV_COIL_NONE, + FIFF.FIFFV_COIL_EEG, + FIFF.FIFFV_COIL_NM_122, + FIFF.FIFFV_COIL_NM_24, + FIFF.FIFFV_COIL_NM_MCG_AXIAL, + FIFF.FIFFV_COIL_EEG_BIPOLAR, + FIFF.FIFFV_COIL_EEG_CSD, + FIFF.FIFFV_COIL_DIPOLE, + FIFF.FIFFV_COIL_FNIRS_HBO, + FIFF.FIFFV_COIL_FNIRS_HBR, + FIFF.FIFFV_COIL_FNIRS_RAW, + FIFF.FIFFV_COIL_FNIRS_OD, + FIFF.FIFFV_COIL_FNIRS_FD_AC_AMPLITUDE, + FIFF.FIFFV_COIL_FNIRS_FD_PHASE, + FIFF.FIFFV_COIL_FNIRS_TD_GATED_AMPLITUDE, + FIFF.FIFFV_COIL_FNIRS_TD_MOMENTS_AMPLITUDE, + FIFF.FIFFV_COIL_MCG_42, + FIFF.FIFFV_COIL_EYETRACK_POS, + FIFF.FIFFV_COIL_EYETRACK_PUPIL, + FIFF.FIFFV_COIL_POINT_MAGNETOMETER, + FIFF.FIFFV_COIL_AXIAL_GRAD_5CM, + FIFF.FIFFV_COIL_VV_PLANAR_W, + FIFF.FIFFV_COIL_VV_PLANAR_T1, + FIFF.FIFFV_COIL_VV_PLANAR_T2, + FIFF.FIFFV_COIL_VV_PLANAR_T3, + FIFF.FIFFV_COIL_VV_PLANAR_T4, + FIFF.FIFFV_COIL_VV_MAG_W, + FIFF.FIFFV_COIL_VV_MAG_T1, + FIFF.FIFFV_COIL_VV_MAG_T2, + FIFF.FIFFV_COIL_VV_MAG_T3, + FIFF.FIFFV_COIL_VV_MAG_T4, + FIFF.FIFFV_COIL_MAGNES_MAG, + FIFF.FIFFV_COIL_MAGNES_GRAD, + FIFF.FIFFV_COIL_MAGNES_REF_MAG, + FIFF.FIFFV_COIL_MAGNES_REF_GRAD, + FIFF.FIFFV_COIL_MAGNES_OFFDIAG_REF_GRAD, + FIFF.FIFFV_COIL_CTF_GRAD, + FIFF.FIFFV_COIL_CTF_REF_MAG, + FIFF.FIFFV_COIL_CTF_REF_GRAD, + FIFF.FIFFV_COIL_CTF_OFFDIAG_REF_GRAD, + FIFF.FIFFV_COIL_KIT_GRAD, + FIFF.FIFFV_COIL_KIT_REF_MAG, + FIFF.FIFFV_COIL_BABY_GRAD, + FIFF.FIFFV_COIL_BABY_MAG, + FIFF.FIFFV_COIL_BABY_REF_MAG, + FIFF.FIFFV_COIL_BABY_REF_MAG2, + FIFF.FIFFV_COIL_ARTEMIS123_GRAD, + FIFF.FIFFV_COIL_ARTEMIS123_REF_MAG, + FIFF.FIFFV_COIL_ARTEMIS123_REF_GRAD, + FIFF.FIFFV_COIL_QUSPIN_ZFOPM_MAG, + FIFF.FIFFV_COIL_QUSPIN_ZFOPM_MAG2, + FIFF.FIFFV_COIL_FIELDLINE_OPM_MAG_GEN1, + FIFF.FIFFV_COIL_KERNEL_OPM_MAG_GEN1, + FIFF.FIFFV_COIL_KRISS_GRAD, + FIFF.FIFFV_COIL_COMPUMEDICS_ADULT_GRAD, + FIFF.FIFFV_COIL_COMPUMEDICS_PEDIATRIC_GRAD, + ) +} + +# MNE RealTime +FIFF.FIFF_MNE_RT_COMMAND = 3700 # realtime command +FIFF.FIFF_MNE_RT_CLIENT_ID = 3701 # realtime client + +# MNE epochs bookkeeping +FIFF.FIFF_MNE_EPOCHS_SELECTION = 3800 # the epochs selection +FIFF.FIFF_MNE_EPOCHS_DROP_LOG = 3801 # the drop log +FIFF.FIFF_MNE_EPOCHS_REJECT_FLAT = 3802 # rejection and flat params +FIFF.FIFF_MNE_EPOCHS_RAW_SFREQ = 3803 # original raw sfreq + +# MNE annotations +FIFF.FIFFB_MNE_ANNOTATIONS = 3810 # annotations block + +# MNE Metadata Dataframes +FIFF.FIFFB_MNE_METADATA = 3811 # metadata dataframes block + +# Table to match unrecognized channel location names to their known aliases +CHANNEL_LOC_ALIASES = { + # this set of aliases are published in doi:10.1097/WNP.0000000000000316 and + # doi:10.1016/S1388-2457(00)00527-7. + "Cb1": "POO7", + "Cb2": "POO8", + "CB1": "POO7", + "CB2": "POO8", + "T1": "T9", + "T2": "T10", + "T3": "T7", + "T4": "T8", + "T5": "T9", + "T6": "T10", + "M1": "TP9", + "M2": "TP10", + # EGI ref chan is named VREF/Vertex Ref. + # In the standard montages for EGI, the ref is named Cz + "VREF": "Cz", + "Vertex Reference": "Cz" + # add a comment here (with doi of a published source) above any new + # aliases, as they are added +} diff --git a/mne-python/source/mne/_fiff/ctf_comp.py b/mne-python/source/mne/_fiff/ctf_comp.py new file mode 100644 index 0000000000000000000000000000000000000000..87269badb8efe7e8db1ef577f565438335002130 --- /dev/null +++ b/mne-python/source/mne/_fiff/ctf_comp.py @@ -0,0 +1,189 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from copy import deepcopy + +import numpy as np + +from ..utils import _pl, logger, verbose +from .constants import FIFF +from .matrix import _read_named_matrix, write_named_matrix +from .tag import read_tag +from .tree import dir_tree_find +from .write import end_block, start_block, write_int + + +def _add_kind(one): + """Convert CTF kind to MNE kind.""" + if one["ctfkind"] == int("47314252", 16): + one["kind"] = 1 + elif one["ctfkind"] == int("47324252", 16): + one["kind"] = 2 + elif one["ctfkind"] == int("47334252", 16): + one["kind"] = 3 + else: + one["kind"] = int(one["ctfkind"]) + + +def _calibrate_comp( + comp, chs, row_names, col_names, mult_keys=("range", "cal"), flip=False +): + """Get row and column cals.""" + ch_names = [c["ch_name"] for c in chs] + row_cals = np.zeros(len(row_names)) + col_cals = np.zeros(len(col_names)) + for names, cals, inv in zip( + (row_names, col_names), (row_cals, col_cals), (False, True) + ): + for ii in range(len(cals)): + p = ch_names.count(names[ii]) + if p != 1: + raise RuntimeError( + f"Channel {names[ii]} does not appear exactly once " + f"in data, found {p:d} instance{_pl(p)}" + ) + idx = ch_names.index(names[ii]) + val = chs[idx][mult_keys[0]] * chs[idx][mult_keys[1]] + val = float(1.0 / val) if inv else float(val) + val = 1.0 / val if flip else val + cals[ii] = val + comp["rowcals"] = row_cals + comp["colcals"] = col_cals + comp["data"]["data"] = row_cals[:, None] * comp["data"]["data"] * col_cals[None, :] + + +@verbose +def read_ctf_comp(fid, node, chs, verbose=None): + """Read the CTF software compensation data from the given node. + + Parameters + ---------- + fid : file + The file descriptor. + node : dict + The node in the FIF tree. + chs : list + The list of channels from info['chs'] to match with + compensators that are read. + %(verbose)s + + Returns + ------- + compdata : list + The compensation data + """ + return _read_ctf_comp(fid, node, chs, None) + + +def _read_ctf_comp(fid, node, chs, ch_names_mapping): + """Read the CTF software compensation data from the given node. + + Parameters + ---------- + fid : file + The file descriptor. + node : dict + The node in the FIF tree. + chs : list + The list of channels from info['chs'] to match with + compensators that are read. + ch_names_mapping : dict | None + The channel renaming to use. + %(verbose)s + + Returns + ------- + compdata : list + The compensation data + """ + from .meas_info import _rename_comps + + ch_names_mapping = dict() if ch_names_mapping is None else ch_names_mapping + compdata = [] + comps = dir_tree_find(node, FIFF.FIFFB_MNE_CTF_COMP_DATA) + + for node in comps: + # Read the data we need + mat = _read_named_matrix(fid, node, FIFF.FIFF_MNE_CTF_COMP_DATA) + for p in range(node["nent"]): + kind = node["directory"][p].kind + pos = node["directory"][p].pos + if kind == FIFF.FIFF_MNE_CTF_COMP_KIND: + tag = read_tag(fid, pos) + break + else: + raise Exception("Compensation type not found") + + # Get the compensation kind and map it to a simple number + one = dict(ctfkind=tag.data.item()) + del tag + _add_kind(one) + for p in range(node["nent"]): + kind = node["directory"][p].kind + pos = node["directory"][p].pos + if kind == FIFF.FIFF_MNE_CTF_COMP_CALIBRATED: + tag = read_tag(fid, pos) + calibrated = tag.data + break + else: + calibrated = False + + one["save_calibrated"] = bool(calibrated) + one["data"] = mat + _rename_comps([one], ch_names_mapping) + if not calibrated: + # Calibrate... + _calibrate_comp(one, chs, mat["row_names"], mat["col_names"]) + else: + one["rowcals"] = np.ones(mat["data"].shape[0], dtype=np.float64) + one["colcals"] = np.ones(mat["data"].shape[1], dtype=np.float64) + + compdata.append(one) + + if len(compdata) > 0: + logger.info(f" Read {len(compdata)} compensation matrices") + + return compdata + + +############################################################################### +# Writing + + +def write_ctf_comp(fid, comps): + """Write the CTF compensation data into a fif file. + + Parameters + ---------- + fid : file + The open FIF file descriptor + + comps : list + The compensation data to write + """ + if len(comps) <= 0: + return + + # This is very simple in fact + start_block(fid, FIFF.FIFFB_MNE_CTF_COMP) + for comp in comps: + start_block(fid, FIFF.FIFFB_MNE_CTF_COMP_DATA) + # Write the compensation kind + write_int(fid, FIFF.FIFF_MNE_CTF_COMP_KIND, comp["ctfkind"]) + if comp.get("save_calibrated", False): + write_int(fid, FIFF.FIFF_MNE_CTF_COMP_CALIBRATED, comp["save_calibrated"]) + + if not comp.get("save_calibrated", True): + # Undo calibration + comp = deepcopy(comp) + data = ( + (1.0 / comp["rowcals"][:, None]) + * comp["data"]["data"] + * (1.0 / comp["colcals"][None, :]) + ) + comp["data"]["data"] = data + write_named_matrix(fid, FIFF.FIFF_MNE_CTF_COMP_DATA, comp["data"]) + end_block(fid, FIFF.FIFFB_MNE_CTF_COMP_DATA) + + end_block(fid, FIFF.FIFFB_MNE_CTF_COMP) diff --git a/mne-python/source/mne/_fiff/matrix.py b/mne-python/source/mne/_fiff/matrix.py new file mode 100644 index 0000000000000000000000000000000000000000..f27d86808f66c6b54e8df5e08956ec4f4146b58b --- /dev/null +++ b/mne-python/source/mne/_fiff/matrix.py @@ -0,0 +1,137 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ..utils import logger +from .constants import FIFF +from .tag import find_tag, has_tag +from .write import ( + end_block, + start_block, + write_float_matrix, + write_int, + write_name_list, +) + + +def _transpose_named_matrix(mat): + """Transpose mat inplace (no copy).""" + mat["nrow"], mat["ncol"] = mat["ncol"], mat["nrow"] + mat["row_names"], mat["col_names"] = mat["col_names"], mat["row_names"] + mat["data"] = mat["data"].T + + +def _read_named_matrix(fid, node, matkind, indent=" ", transpose=False): + """Read named matrix from the given node. + + Parameters + ---------- + fid : file + The opened file descriptor. + node : dict + The node in the tree. + matkind : int + The type of matrix. + transpose : bool + If True, transpose the matrix. Default is False. + %(verbose)s + + Returns + ------- + mat: dict + The matrix data + """ + # Descend one level if necessary + if node["block"] != FIFF.FIFFB_MNE_NAMED_MATRIX: + for k in range(node["nchild"]): + if node["children"][k]["block"] == FIFF.FIFFB_MNE_NAMED_MATRIX: + if has_tag(node["children"][k], matkind): + node = node["children"][k] + break + else: + logger.info( + f"{indent}Desired named matrix (kind = {matkind}) not available" + ) + return None + else: + if not has_tag(node, matkind): + logger.info( + f"{indent}Desired named matrix (kind = {matkind}) not available" + ) + return None + + # Read everything we need + tag = find_tag(fid, node, matkind) + if tag is None: + raise ValueError("Matrix data missing") + else: + data = tag.data + + nrow, ncol = data.shape + tag = find_tag(fid, node, FIFF.FIFF_MNE_NROW) + if tag is not None and tag.data != nrow: + raise ValueError( + "Number of rows in matrix data and FIFF_MNE_NROW tag do not match" + ) + + tag = find_tag(fid, node, FIFF.FIFF_MNE_NCOL) + if tag is not None and tag.data != ncol: + raise ValueError( + "Number of columns in matrix data and FIFF_MNE_NCOL tag do not match" + ) + + tag = find_tag(fid, node, FIFF.FIFF_MNE_ROW_NAMES) + row_names = tag.data.split(":") if tag is not None else [] + + tag = find_tag(fid, node, FIFF.FIFF_MNE_COL_NAMES) + col_names = tag.data.split(":") if tag is not None else [] + + mat = dict( + nrow=nrow, ncol=ncol, row_names=row_names, col_names=col_names, data=data + ) + if transpose: + _transpose_named_matrix(mat) + return mat + + +def write_named_matrix(fid, kind, mat): + """Write named matrix from the given node. + + Parameters + ---------- + fid : file + The opened file descriptor. + kind : int + The kind of the matrix. + matkind : int + The type of matrix. + """ + # let's save ourselves from disaster + n_tot = mat["nrow"] * mat["ncol"] + if mat["data"].size != n_tot: + ratio = n_tot / float(mat["data"].size) + if n_tot < mat["data"].size and ratio > 0: + ratio = 1 / ratio + raise ValueError( + f"Cannot write matrix: row ({mat['nrow']}) and column ({mat['ncol']}) " + f"total element ({n_tot}) mismatch with data size ({mat['data'].size}), " + f"appears to be off by a factor of {ratio:g}x" + ) + start_block(fid, FIFF.FIFFB_MNE_NAMED_MATRIX) + write_int(fid, FIFF.FIFF_MNE_NROW, mat["nrow"]) + write_int(fid, FIFF.FIFF_MNE_NCOL, mat["ncol"]) + + if len(mat["row_names"]) > 0: + # let's prevent unintentional stupidity + if len(mat["row_names"]) != mat["nrow"]: + raise ValueError('len(mat["row_names"]) != mat["nrow"]') + write_name_list(fid, FIFF.FIFF_MNE_ROW_NAMES, mat["row_names"]) + + if len(mat["col_names"]) > 0: + # let's prevent unintentional stupidity + if len(mat["col_names"]) != mat["ncol"]: + raise ValueError('len(mat["col_names"]) != mat["ncol"]') + write_name_list(fid, FIFF.FIFF_MNE_COL_NAMES, mat["col_names"]) + + write_float_matrix(fid, kind, mat["data"]) + end_block(fid, FIFF.FIFFB_MNE_NAMED_MATRIX) diff --git a/mne-python/source/mne/_fiff/meas_info.py b/mne-python/source/mne/_fiff/meas_info.py new file mode 100644 index 0000000000000000000000000000000000000000..fbb602caf2f256eafbbc85866138116b3be1d81a --- /dev/null +++ b/mne-python/source/mne/_fiff/meas_info.py @@ -0,0 +1,4026 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import contextlib +import datetime +import operator +import re +import string +from collections import Counter, OrderedDict +from collections.abc import Mapping +from copy import deepcopy +from functools import partial +from io import BytesIO +from textwrap import shorten + +import numpy as np + +from ..defaults import _handle_default +from ..html_templates import _get_html_template +from ..utils import ( + _check_fname, + _check_on_missing, + _check_option, + _dt_to_stamp, + _on_missing, + _pl, + _stamp_to_dt, + _validate_type, + check_fname, + fill_doc, + logger, + object_diff, + repr_html, + verbose, + warn, +) +from ..utils._bunch import NamedFloat, NamedInt +from ._digitization import ( + DigPoint, + _dig_kind_ints, + _dig_kind_proper, + _dig_kind_rev, + _format_dig_points, + _get_data_as_dict_from_dig, + _read_dig_fif, + write_dig, +) +from .compensator import get_current_comp +from .constants import FIFF, _ch_unit_mul_named +from .ctf_comp import _read_ctf_comp, write_ctf_comp +from .open import fiff_open +from .pick import ( + _DATA_CH_TYPES_SPLIT, + _contains_ch_type, + _picks_to_idx, + channel_type, + get_channel_type_constants, + pick_types, +) +from .proc_history import _read_proc_history, _write_proc_history +from .proj import ( + Projection, + _normalize_proj, + _proj_equal, + _read_proj, + _uniquify_projs, + _write_proj, +) +from .tag import ( + _ch_coord_dict, + _float_item, + _int_item, + _rename_list, + _update_ch_info_named, + find_tag, + read_tag, +) +from .tree import dir_tree_find +from .write import ( + DATE_NONE, + _safe_name_list, + end_block, + start_and_end_file, + start_block, + write_ch_info, + write_coord_trans, + write_dig_points, + write_float, + write_float_matrix, + write_id, + write_int, + write_julian, + write_name_list_sanitized, + write_string, +) + +b = bytes # alias + +_SCALAR_CH_KEYS = ( + "scanno", + "logno", + "kind", + "range", + "cal", + "coil_type", + "unit", + "unit_mul", + "coord_frame", +) +_ALL_CH_KEYS_SET = set(_SCALAR_CH_KEYS + ("loc", "ch_name")) +# XXX we need to require these except when doing simplify_info +_MIN_CH_KEYS_SET = set(("kind", "cal", "unit", "loc", "ch_name")) + + +def _get_valid_units(): + """Get valid units according to the International System of Units (SI). + + The International System of Units (SI, :footcite:`WikipediaSI`) is the + default system for describing units in the Brain Imaging Data Structure + (BIDS). For more information, see the BIDS specification + :footcite:`BIDSdocs` and the appendix "Units" therein. + + References + ---------- + .. footbibliography:: + """ + valid_prefix_names = [ + "yocto", + "zepto", + "atto", + "femto", + "pico", + "nano", + "micro", + "milli", + "centi", + "deci", + "deca", + "hecto", + "kilo", + "mega", + "giga", + "tera", + "peta", + "exa", + "zetta", + "yotta", + ] + valid_prefix_symbols = [ + "y", + "z", + "a", + "f", + "p", + "n", + "µ", + "m", + "c", + "d", + "da", + "h", + "k", + "M", + "G", + "T", + "P", + "E", + "Z", + "Y", + ] + valid_unit_names = [ + "metre", + "kilogram", + "second", + "ampere", + "kelvin", + "mole", + "candela", + "radian", + "steradian", + "hertz", + "newton", + "pascal", + "joule", + "watt", + "coulomb", + "volt", + "farad", + "ohm", + "siemens", + "weber", + "tesla", + "henry", + "degree Celsius", + "lumen", + "lux", + "becquerel", + "gray", + "sievert", + "katal", + ] + valid_unit_symbols = [ + "m", + "kg", + "s", + "A", + "K", + "mol", + "cd", + "rad", + "sr", + "Hz", + "N", + "Pa", + "J", + "W", + "C", + "V", + "F", + "Ω", + "S", + "Wb", + "T", + "H", + "°C", + "lm", + "lx", + "Bq", + "Gy", + "Sv", + "kat", + ] + + # Valid units are all possible combinations of either prefix name or prefix + # symbol together with either unit name or unit symbol. E.g., nV for + # nanovolt + valid_units = [] + valid_units += [ + "".join([prefix, unit]) + for prefix in valid_prefix_names + for unit in valid_unit_names + ] + valid_units += [ + "".join([prefix, unit]) + for prefix in valid_prefix_names + for unit in valid_unit_symbols + ] + valid_units += [ + "".join([prefix, unit]) + for prefix in valid_prefix_symbols + for unit in valid_unit_names + ] + valid_units += [ + "".join([prefix, unit]) + for prefix in valid_prefix_symbols + for unit in valid_unit_symbols + ] + + # units are also valid without a prefix + valid_units += valid_unit_names + valid_units += valid_unit_symbols + + # we also accept "n/a" as a unit, which is the default missing value in + # BIDS + valid_units += ["n/a"] + + return tuple(valid_units) + + +@verbose +def _unique_channel_names(ch_names, max_length=None, verbose=None): + """Ensure unique channel names.""" + suffixes = tuple(string.ascii_lowercase) + if max_length is not None: + ch_names[:] = [name[:max_length] for name in ch_names] + unique_ids = np.unique(ch_names, return_index=True)[1] + if len(unique_ids) != len(ch_names): + dups = {ch_names[x] for x in np.setdiff1d(range(len(ch_names)), unique_ids)} + warn( + "Channel names are not unique, found duplicates for: " + f"{dups}. Applying running numbers for duplicates." + ) + for ch_stem in dups: + overlaps = np.where(np.array(ch_names) == ch_stem)[0] + # We need an extra character since we append '-'. + # np.ceil(...) is the maximum number of appended digits. + if max_length is not None: + n_keep = max_length - 1 - int(np.ceil(np.log10(len(overlaps)))) + else: + n_keep = np.inf + n_keep = min(len(ch_stem), n_keep) + ch_stem = ch_stem[:n_keep] + for idx, ch_idx in enumerate(overlaps): + # try idx first, then loop through lower case chars + for suffix in (idx,) + suffixes: + ch_name = ch_stem + f"-{suffix}" + if ch_name not in ch_names: + break + if ch_name not in ch_names: + ch_names[ch_idx] = ch_name + else: + raise ValueError( + "Adding a single alphanumeric for a " + "duplicate resulted in another " + f"duplicate name {ch_name}" + ) + return ch_names + + +# %% Mixin classes + + +class MontageMixin: + """Mixin for Montage getting and setting.""" + + @fill_doc + def get_montage(self): + """Get a DigMontage from instance. + + Returns + ------- + montage : None | DigMontage + A copy of the channel positions, if available, otherwise ``None``. + """ + from ..channels.montage import make_dig_montage + from ..transforms import _frame_to_str + + info = self if isinstance(self, Info) else self.info + if info["dig"] is None: + return None + # obtain coord_frame, and landmark coords + # (nasion, lpa, rpa, hsp, hpi) from DigPoints + montage_bunch = _get_data_as_dict_from_dig(info["dig"]) + coord_frame = _frame_to_str.get(montage_bunch.coord_frame) + + # get the channel names and chs data structure + ch_names, chs = info["ch_names"], info["chs"] + picks = pick_types( + info, + meg=False, + eeg=True, + seeg=True, + ecog=True, + dbs=True, + fnirs=True, + exclude=[], + ) + + # channel positions from dig do not match ch_names one to one, + # so use loc[:3] instead + ch_pos = {ch_names[ii]: chs[ii]["loc"][:3] for ii in picks} + + # fNIRS uses multiple channels for the same sensors, we use + # a private function to format these for dig montage. + fnirs_picks = pick_types(info, fnirs=True, exclude=[]) + if len(ch_pos) == len(fnirs_picks): + ch_pos = _get_fnirs_ch_pos(info) + elif len(fnirs_picks) > 0: + raise ValueError( + "MNE does not support getting the montage " + "for a mix of fNIRS and other data types. " + "Please raise a GitHub issue if you " + "require this feature." + ) + + # create montage + montage = make_dig_montage( + ch_pos=ch_pos, + coord_frame=coord_frame, + nasion=montage_bunch.nasion, + lpa=montage_bunch.lpa, + rpa=montage_bunch.rpa, + hsp=montage_bunch.hsp, + hpi=montage_bunch.hpi, + ) + return montage + + @verbose + def set_montage( + self, + montage, + match_case=True, + match_alias=False, + on_missing="raise", + verbose=None, + ): + """Set %(montage_types)s channel positions and digitization points. + + Parameters + ---------- + %(montage)s + %(match_case)s + %(match_alias)s + %(on_missing_montage)s + %(verbose)s + + Returns + ------- + inst : same type as the input data + The instance, modified in-place. + + See Also + -------- + mne.channels.make_standard_montage + mne.channels.make_dig_montage + mne.channels.read_custom_montage + + Notes + ----- + .. warning:: + Only %(montage_types)s channels can have their positions set using + a montage. Other channel types (e.g., MEG channels) should have + their positions defined properly using their data reading + functions. + .. warning:: + Applying a montage will only set locations of channels that exist + at the time it is applied. This means when + :ref:`re-referencing ` + make sure to apply the montage only after calling + :func:`mne.add_reference_channels` + """ + # How to set up a montage to old named fif file (walk through example) + # https://gist.github.com/massich/f6a9f4799f1fbeb8f5e8f8bc7b07d3df + + from ..channels.montage import _set_montage + + info = self if isinstance(self, Info) else self.info + _set_montage(info, montage, match_case, match_alias, on_missing) + return self + + +channel_type_constants = get_channel_type_constants(include_defaults=True) +_human2fiff = { + k: v.get("kind", FIFF.FIFFV_COIL_NONE) for k, v in channel_type_constants.items() +} +_human2unit = { + k: v.get("unit", FIFF.FIFF_UNIT_NONE) for k, v in channel_type_constants.items() +} +_unit2human = { + FIFF.FIFF_UNIT_V: "V", + FIFF.FIFF_UNIT_T: "T", + FIFF.FIFF_UNIT_T_M: "T/m", + FIFF.FIFF_UNIT_MOL: "M", + FIFF.FIFF_UNIT_NONE: "NA", + FIFF.FIFF_UNIT_CEL: "C", + FIFF.FIFF_UNIT_S: "S", + FIFF.FIFF_UNIT_PX: "px", +} + + +def _check_set(ch, projs, ch_type): + """Ensure type change is compatible with projectors.""" + new_kind = _human2fiff[ch_type] + if ch["kind"] != new_kind: + for proj in projs: + if ch["ch_name"] in proj["data"]["col_names"]: + raise RuntimeError( + f"Cannot change channel type for channel {ch['ch_name']} in " + f'projector "{proj["desc"]}"' + ) + ch["kind"] = new_kind + + +class SetChannelsMixin(MontageMixin): + """Mixin class for Raw, Evoked, Epochs.""" + + def _get_channel_positions(self, picks=None): + """Get channel locations from info. + + Parameters + ---------- + picks : str | list | slice | None + None gets good data indices. + + Notes + ----- + .. versionadded:: 0.9.0 + """ + info = self if isinstance(self, Info) else self.info + picks = _picks_to_idx(info, picks) + chs = info["chs"] + pos = np.array([chs[k]["loc"][:3] for k in picks]) + n_zero = np.sum(np.sum(np.abs(pos), axis=1) == 0) + if n_zero > 1: # XXX some systems have origin (0, 0, 0) + raise ValueError( + f"Could not extract channel positions for {n_zero} channels" + ) + return pos + + def _set_channel_positions(self, pos, names): + """Update channel locations in info. + + Parameters + ---------- + pos : array-like | np.ndarray, shape (n_points, 3) + The channel positions to be set. + names : list of str + The names of the channels to be set. + + Notes + ----- + .. versionadded:: 0.9.0 + """ + info = self if isinstance(self, Info) else self.info + if len(pos) != len(names): + raise ValueError( + "Number of channel positions not equal to the number of names given." + ) + pos = np.asarray(pos, dtype=np.float64) + if pos.shape[-1] != 3 or pos.ndim != 2: + msg = ( + f"Channel positions must have the shape (n_points, 3) not {pos.shape}." + ) + raise ValueError(msg) + for name, p in zip(names, pos): + if name in self.ch_names: + idx = self.ch_names.index(name) + info["chs"][idx]["loc"][:3] = p + else: + msg = f"{name} was not found in the info. Cannot be updated." + raise ValueError(msg) + + @verbose + def set_channel_types(self, mapping, *, on_unit_change="warn", verbose=None): + """Specify the sensor types of channels. + + Parameters + ---------- + mapping : dict + A dictionary mapping channel names to sensor types, e.g., + ``{'EEG061': 'eog'}``. + on_unit_change : ``'raise'`` | ``'warn'`` | ``'ignore'`` + What to do if the measurement unit of a channel is changed + automatically to match the new sensor type. + + .. versionadded:: 1.4 + %(verbose)s + + Returns + ------- + inst : same type as the input data + The instance (modified in place). + + .. versionchanged:: 0.20 + Return the instance. + + Notes + ----- + The following :term:`sensor types` are accepted: + + bio, chpi, csd, dbs, dipole, ecg, ecog, eeg, emg, eog, exci, + eyegaze, fnirs_cw_amplitude, fnirs_fd_ac_amplitude, fnirs_fd_phase, + fnirs_od, gof, gsr, hbo, hbr, ias, misc, pupil, ref_meg, resp, + seeg, stim, syst, temperature. + + When working with eye-tracking data, see + :func:`mne.preprocessing.eyetracking.set_channel_types_eyetrack`. + + .. versionadded:: 0.9.0 + """ + info = self if isinstance(self, Info) else self.info + ch_names = info["ch_names"] + + # first check and assemble clean mappings of index and name + unit_changes = dict() + for ch_name, ch_type in mapping.items(): + if ch_name not in ch_names: + raise ValueError( + f"This channel name ({ch_name}) doesn't exist in info." + ) + + c_ind = ch_names.index(ch_name) + if ch_type not in _human2fiff: + raise ValueError( + f"This function cannot change to this channel type: {ch_type}. " + "Accepted channel types are " + f"{', '.join(sorted(_human2unit.keys()))}." + ) + # Set sensor type + _check_set(info["chs"][c_ind], info["projs"], ch_type) + unit_old = info["chs"][c_ind]["unit"] + unit_new = _human2unit[ch_type] + if unit_old not in _unit2human: + raise ValueError( + f"Channel '{ch_name}' has unknown unit ({unit_old}). Please fix the" + " measurement info of your data." + ) + if unit_old != _human2unit[ch_type]: + this_change = (_unit2human[unit_old], _unit2human[unit_new]) + if this_change not in unit_changes: + unit_changes[this_change] = list() + unit_changes[this_change].append(ch_name) + # reset unit multiplication factor since the unit has now changed + info["chs"][c_ind]["unit_mul"] = _ch_unit_mul_named[0] + info["chs"][c_ind]["unit"] = _human2unit[ch_type] + if ch_type in ["eeg", "seeg", "ecog", "dbs"]: + coil_type = FIFF.FIFFV_COIL_EEG + elif ch_type == "hbo": + coil_type = FIFF.FIFFV_COIL_FNIRS_HBO + elif ch_type == "hbr": + coil_type = FIFF.FIFFV_COIL_FNIRS_HBR + elif ch_type == "fnirs_cw_amplitude": + coil_type = FIFF.FIFFV_COIL_FNIRS_CW_AMPLITUDE + elif ch_type == "fnirs_fd_ac_amplitude": + coil_type = FIFF.FIFFV_COIL_FNIRS_FD_AC_AMPLITUDE + elif ch_type == "fnirs_fd_phase": + coil_type = FIFF.FIFFV_COIL_FNIRS_FD_PHASE + elif ch_type == "fnirs_od": + coil_type = FIFF.FIFFV_COIL_FNIRS_OD + elif ch_type == "eyetrack_pos": + coil_type = FIFF.FIFFV_COIL_EYETRACK_POS + elif ch_type == "eyetrack_pupil": + coil_type = FIFF.FIFFV_COIL_EYETRACK_PUPIL + else: + coil_type = FIFF.FIFFV_COIL_NONE + info["chs"][c_ind]["coil_type"] = coil_type + + msg = "The unit for channel(s) {0} has changed from {1} to {2}." + for this_change, names in unit_changes.items(): + _on_missing( + on_missing=on_unit_change, + msg=msg.format(", ".join(sorted(names)), *this_change), + name="on_unit_change", + ) + + return self + + @verbose + def rename_channels( + self, mapping, allow_duplicates=False, *, on_missing="raise", verbose=None + ): + """Rename channels. + + Parameters + ---------- + %(mapping_rename_channels_duplicates)s + %(on_missing_ch_names)s + + .. versionadded:: 1.11.0 + %(verbose)s + + Returns + ------- + inst : same type as the input data + The instance (modified in place). + + .. versionchanged:: 0.20 + Return the instance. + + Notes + ----- + .. versionadded:: 0.9.0 + """ + from ..channels.channels import rename_channels + from ..io import BaseRaw + + info = self if isinstance(self, Info) else self.info + + ch_names_orig = list(info["ch_names"]) + rename_channels(info, mapping, allow_duplicates, on_missing=on_missing) + + # Update self._orig_units for Raw + if isinstance(self, BaseRaw): + # whatever mapping was provided, now we can just use a dict + mapping = dict(zip(ch_names_orig, info["ch_names"])) + for old_name, new_name in mapping.items(): + if old_name in self._orig_units: + self._orig_units[new_name] = self._orig_units.pop(old_name) + ch_names = self.annotations.ch_names + for ci, ch in enumerate(ch_names): + ch_names[ci] = tuple(mapping.get(name, name) for name in ch) + + return self + + @verbose + def plot_sensors( + self, + kind="topomap", + ch_type=None, + title=None, + show_names=False, + ch_groups=None, + to_sphere=True, + axes=None, + block=False, + show=True, + sphere=None, + *, + verbose=None, + ): + """Plot sensor positions. + + Parameters + ---------- + kind : str + Whether to plot the sensors as 3d, topomap or as an interactive + sensor selection dialog. Available options 'topomap', '3d', + 'select'. If 'select', a set of channels can be selected + interactively by using lasso selector or clicking while holding + control key. The selected channels are returned along with the + figure instance. Defaults to 'topomap'. + ch_type : None | str + The channel type to plot. Available options ``'mag'``, ``'grad'``, + ``'eeg'``, ``'seeg'``, ``'dbs'``, ``'ecog'``, ``'all'``. If ``'all'``, all + the available mag, grad, eeg, seeg, dbs, and ecog channels are plotted. If + None (default), then channels are chosen in the order given above. + title : str | None + Title for the figure. If None (default), equals to ``'Sensor + positions (%%s)' %% ch_type``. + show_names : bool | array of str + Whether to display all channel names. If an array, only the channel + names in the array are shown. Defaults to False. + ch_groups : 'position' | array of shape (n_ch_groups, n_picks) | None + Channel groups for coloring the sensors. If None (default), default + coloring scheme is used. If 'position', the sensors are divided + into 8 regions. See ``order`` kwarg of :func:`mne.viz.plot_raw`. If + array, the channels are divided by picks given in the array. + + .. versionadded:: 0.13.0 + to_sphere : bool + Whether to project the 3d locations to a sphere. When False, the + sensor array appears similar as to looking downwards straight above + the subject's head. Has no effect when kind='3d'. Defaults to True. + + .. versionadded:: 0.14.0 + axes : instance of Axes | instance of Axes3D | None + Axes to draw the sensors to. If ``kind='3d'``, axes must be an + instance of Axes3D. If None (default), a new axes will be created. + + .. versionadded:: 0.13.0 + block : bool + Whether to halt program execution until the figure is closed. + Defaults to False. + + .. versionadded:: 0.13.0 + show : bool + Show figure if True. Defaults to True. + %(sphere_topomap_auto)s + %(verbose)s + + Returns + ------- + fig : instance of Figure + Figure containing the sensor topography. + selection : list + A list of selected channels. Only returned if ``kind=='select'``. + + See Also + -------- + mne.viz.plot_layout + + Notes + ----- + This function plots the sensor locations from the info structure using + matplotlib. For drawing the sensors using PyVista see + :func:`mne.viz.plot_alignment`. + + .. versionadded:: 0.12.0 + """ + from ..viz.utils import plot_sensors + + return plot_sensors( + self if isinstance(self, Info) else self.info, + kind=kind, + ch_type=ch_type, + title=title, + show_names=show_names, + ch_groups=ch_groups, + to_sphere=to_sphere, + axes=axes, + block=block, + show=show, + sphere=sphere, + verbose=verbose, + ) + + @verbose + def anonymize(self, daysback=None, keep_his=False, verbose=None): + """Anonymize measurement information in place. + + Parameters + ---------- + %(daysback_anonymize_info)s + %(keep_his_anonymize_info)s + %(verbose)s + + Returns + ------- + inst : same type as the input data + The modified instance. + + Notes + ----- + %(anonymize_info_notes)s + + .. versionadded:: 0.13.0 + """ + info = self if isinstance(self, Info) else self.info + anonymize_info(info, daysback=daysback, keep_his=keep_his, verbose=verbose) + self.set_meas_date(info["meas_date"]) # unify annot update + return self + + def set_meas_date(self, meas_date): + """Set the measurement start date. + + Parameters + ---------- + meas_date : datetime | float | tuple | None + The new measurement date. + If datetime object, it must be timezone-aware and in UTC. + A tuple of (seconds, microseconds) or float (alias for + ``(meas_date, 0)``) can also be passed and a datetime + object will be automatically created. If None, will remove + the time reference. + + Returns + ------- + inst : same type as the input data + The modified instance. Operates in place. + + See Also + -------- + mne.io.Raw.anonymize + + Notes + ----- + If you want to remove all time references in the file, call + :func:`mne.io.anonymize_info(inst.info) ` + after calling ``inst.set_meas_date(None)``. + + .. versionadded:: 0.20 + """ + from ..annotations import _handle_meas_date + + _validate_type( + meas_date, (datetime.datetime, "numeric", tuple, None), "meas_date" + ) + + info = self if isinstance(self, Info) else self.info + + meas_date = _handle_meas_date(meas_date) + with info._unlock(): + info["meas_date"] = meas_date + + # clear file_id and meas_id if needed + if meas_date is None: + for key in ("file_id", "meas_id"): + value = info.get(key) + if value is not None: + assert "msecs" not in value + value["secs"] = DATE_NONE[0] + value["usecs"] = DATE_NONE[1] + # The following copy is needed for a test CTF dataset + # otherwise value['machid'][:] = 0 would suffice + _tmp = value["machid"].copy() + _tmp[:] = 0 + value["machid"] = _tmp + + if hasattr(self, "annotations"): + self.annotations._orig_time = meas_date + return self + + +class ContainsMixin: + """Mixin class for Raw, Evoked, Epochs and Info.""" + + def __contains__(self, ch_type): + """Check channel type membership. + + Parameters + ---------- + ch_type : str + Channel type to check for. Can be e.g. ``'meg'``, ``'eeg'``, + ``'stim'``, etc. + + Returns + ------- + in : bool + Whether or not the instance contains the given channel type. + + Examples + -------- + Channel type membership can be tested as:: + + >>> 'meg' in inst # doctest: +SKIP + True + >>> 'seeg' in inst # doctest: +SKIP + False + + """ + # this method is not supported by Info object. An Info object inherits from a + # dictionary and the 'key' in Info call is present all across MNE codebase, e.g. + # to check for the presence of a key: + # >>> 'bads' in info + if ch_type == "meg": + has_ch_type = _contains_ch_type(self.info, "mag") or _contains_ch_type( + self.info, "grad" + ) + else: + has_ch_type = _contains_ch_type(self.info, ch_type) + return has_ch_type + + @property + def compensation_grade(self): + """The current gradient compensation grade.""" + info = self if isinstance(self, Info) else self.info + return get_current_comp(info) + + @fill_doc + def get_channel_types(self, picks=None, unique=False, only_data_chs=False): + """Get a list of channel type for each channel. + + Parameters + ---------- + %(picks_all)s + unique : bool + Whether to return only unique channel types. Default is ``False``. + only_data_chs : bool + Whether to ignore non-data channels. Default is ``False``. + + Returns + ------- + channel_types : list + The channel types. + """ + info = self if isinstance(self, Info) else self.info + none = "data" if only_data_chs else "all" + picks = _picks_to_idx(info, picks, none, (), allow_empty=False) + ch_types = [channel_type(info, pick) for pick in picks] + if only_data_chs: + ch_types = [ + ch_type for ch_type in ch_types if ch_type in _DATA_CH_TYPES_SPLIT + ] + if unique: + # set does not preserve order but dict does, so let's just use it + ch_types = list({k: k for k in ch_types}.keys()) + return ch_types + + +# %% ValidatedDict class + + +class ValidatedDict(dict): + _attributes = {} # subclasses should set this to validated attributes + + def __init__(self, *args, **kwargs): + self._unlocked = True + super().__init__(*args, **kwargs) + self._unlocked = False + + def __getstate__(self): + """Get state (for pickling).""" + return {"_unlocked": self._unlocked} + + def __setstate__(self, state): + """Set state (for pickling).""" + self._unlocked = state["_unlocked"] + + def __setitem__(self, key, val): + """Attribute setter.""" + # During unpickling, the _unlocked attribute has not been set, so + # let __setstate__ do it later and act unlocked now + unlocked = getattr(self, "_unlocked", True) + if key in self._attributes: + if isinstance(self._attributes[key], str): + if not unlocked: + raise RuntimeError(self._attributes[key]) + else: + val = self._attributes[key]( + val, info=self + ) # attribute checker function + else: + class_name = self.__class__.__name__ + extra = "" + if "temp" in self._attributes: + var_name = _camel_to_snake(class_name) + extra = ( + f"You can set {var_name}['temp'] to store temporary objects in " + f"{class_name} instances, but these will not survive an I/O " + "round-trip." + ) + raise RuntimeError( + f"{class_name} does not support directly setting the key {repr(key)}. " + + extra + ) + super().__setitem__(key, val) + + def update(self, other=None, **kwargs): + """Update method using __setitem__().""" + iterable = other.items() if isinstance(other, Mapping) else other + if other is not None: + for key, val in iterable: + self[key] = val + for key, val in kwargs.items(): + self[key] = val + + def copy(self): + """Copy the instance. + + Returns + ------- + info : instance of Info + The copied info. + """ + return deepcopy(self) + + def __repr__(self): + """Return a string representation.""" + mapping = ", ".join(f"{key}: {val}" for key, val in self.items()) + return f"<{_camel_to_snake(self.__class__.__name__)} | {mapping}>" + + +# %% Subject info + + +def _check_types(x, *, info, name, types, cast=None): + _validate_type(x, types, name) + if cast is not None and x is not None: + x = cast(x) + return x + + +def _check_bday(birthday_input, *, info): + date = _check_types( + birthday_input, + info=info, + name='subject_info["birthday"]', + types=(datetime.date, None), + ) + # test if we have a pd.Timestamp + if hasattr(date, "date"): + date = date.date() + return date + + +class SubjectInfo(ValidatedDict): + _attributes = { + "id": partial(_check_types, name='subject_info["id"]', types=int), + "his_id": partial(_check_types, name='subject_info["his_id"]', types=str), + "last_name": partial(_check_types, name='subject_info["last_name"]', types=str), + "first_name": partial( + _check_types, name='subject_info["first_name"]', types=str + ), + "middle_name": partial( + _check_types, name='subject_info["middle_name"]', types=str + ), + "birthday": partial(_check_bday), + "sex": partial(_check_types, name='subject_info["sex"]', types=int), + "hand": partial(_check_types, name='subject_info["hand"]', types=int), + "weight": partial( + _check_types, name='subject_info["weight"]', types="numeric", cast=float + ), + "height": partial( + _check_types, name='subject_info["height"]', types="numeric", cast=float + ), + } + + def __init__(self, initial): + _validate_type(initial, dict, "subject_info") + super().__init__() + for key, val in initial.items(): + self[key] = val + + +class HeliumInfo(ValidatedDict): + _attributes = { + "he_level_raw": partial( + _check_types, + name='helium_info["he_level_raw"]', + types="numeric", + cast=float, + ), + "helium_level": partial( + _check_types, + name='helium_info["helium_level"]', + types="numeric", + cast=float, + ), + "orig_file_guid": partial( + _check_types, name='helium_info["orig_file_guid"]', types=str + ), + "meas_date": partial( + _check_types, + name='helium_info["meas_date"]', + types=(datetime.datetime, None), + ), + } + + def __init__(self, initial): + _validate_type(initial, dict, "helium_info") + super().__init__() + for key, val in initial.items(): + self[key] = val + + +# %% Info class and helpers + + +def _format_trans(obj, key): + from ..transforms import Transform + + try: + t = obj[key] + except KeyError: + pass + else: + if t is not None: + obj[key] = Transform(t["from"], t["to"], t["trans"]) + + +def _check_ch_keys(ch, ci, name='info["chs"]', check_min=True): + ch_keys = set(ch) + bad = sorted(ch_keys.difference(_ALL_CH_KEYS_SET)) + if bad: + raise KeyError(f"key{_pl(bad)} errantly present for {name}[{ci}]: {bad}") + if check_min: + bad = sorted(_MIN_CH_KEYS_SET.difference(ch_keys)) + if bad: + raise KeyError( + f"key{_pl(bad)} missing for {name}[{ci}]: {bad}", + ) + + +def _check_bads_info_compat(bads, info): + _validate_type(bads, list, "bads") + if not len(bads): + return # e.g. in empty_info + for bi, bad in enumerate(bads): + _validate_type(bad, str, f"bads[{bi}]") + if "ch_names" not in info: # somewhere in init, or deepcopy, or _empty_info, etc. + return + missing = [bad for bad in bads if bad not in info["ch_names"]] + if len(missing) > 0: + raise ValueError(f"bad channel(s) {missing} marked do not exist in info") + + +class MNEBadsList(list): + """Subclass of bads that checks inplace operations.""" + + def __init__(self, *, bads, info): + _check_bads_info_compat(bads, info) + self._mne_info = info + super().__init__(bads) + + def extend(self, iterable): + if not isinstance(iterable, list): + iterable = list(iterable) + # can happen during pickling + try: + info = self._mne_info + except AttributeError: + pass # can happen during pickling + else: + _check_bads_info_compat(iterable, info) + return super().extend(iterable) + + def append(self, x): + return self.extend([x]) + + def __iadd__(self, x): + self.extend(x) + return self + + +# As options are added here, test_meas_info.py:test_info_bad should be updated +def _check_bads(bads, *, info): + return MNEBadsList(bads=bads, info=info) + + +def _check_dev_head_t(dev_head_t, *, info): + from ..transforms import Transform, _ensure_trans + + _validate_type(dev_head_t, (Transform, None), "info['dev_head_t']") + if dev_head_t is not None: + dev_head_t = _ensure_trans(dev_head_t, "meg", "head") + return dev_head_t + + +def _restore_mne_types(info): + """Restore MNE-specific types after unpickling/deserialization. + + This function handles the restoration of MNE-specific object types + that need to be reconstructed from their serialized representations. + These correspond to the "cast" entries in Info._attributes: bads, + dev_head_t, dig, helium_info, line_freq, proj_id, projs, and + subject_info. However, this function is specifically for types that + need restoration because h5io and other serialization formats cast + them to native Python types (e.g., MNEBadsList -> list, Projection + -> dict, DigPoint -> dict). + + This function should be called in Info.__init__ and Info.__setstate__. + If new MNE-specific types are added to Info._attributes, they + should be handled here if they need type restoration after + deserialization. + + Parameters + ---------- + info : Info + The Info object whose types need to be restored. Modified in-place. + + Notes + ----- + This function restores: + - MNEBadsList for the bads field (see Info._attributes["bads"]) + - DigPoint objects for digitization points (see Info._attributes["dig"]) + - Projection objects for SSP projectors (see Info._attributes["projs"]) + - Transform objects for device/head transformations + - meas_date from tuple to datetime + - helium_info and subject_info with proper casting + - proc_history date field from numpy array to tuple (JSON limitation) + """ + # Restore MNEBadsList (corresponds to Info._attributes["bads"]) + if "bads" in info: + info["bads"] = MNEBadsList(bads=info["bads"], info=info) + + # Format Transform objects + for key in ("dev_head_t", "ctf_head_t", "dev_ctf_t"): + _format_trans(info, key) + for res in info.get("hpi_results", []): + _format_trans(res, "coord_trans") + + # Restore DigPoint objects (corresponds to Info._attributes["dig"]) + if info.get("dig", None) is not None and len(info["dig"]): + if isinstance(info["dig"], dict): # needs to be unpacked + info["dig"] = _dict_unpack(info["dig"], _DIG_CAST) + if not isinstance(info["dig"][0], DigPoint): + info["dig"] = _format_dig_points(info["dig"]) + + # Unpack chs if needed + if isinstance(info.get("chs", None), dict): + info["chs"]["ch_name"] = [ + str(x) for x in np.char.decode(info["chs"]["ch_name"], encoding="utf8") + ] + info["chs"] = _dict_unpack(info["chs"], _CH_CAST) + + # Restore Projection objects (corresponds to Info._attributes["projs"]) + for pi, proj in enumerate(info.get("projs", [])): + if not isinstance(proj, Projection): + info["projs"][pi] = Projection(**proj) + + # Old files could have meas_date as tuple instead of datetime + try: + meas_date = info["meas_date"] + except KeyError: + pass + else: + info["meas_date"] = _ensure_meas_date_none_or_dt(meas_date) + + # with validation and casting + for key in ("helium_info", "subject_info"): + if key in info: + info[key] = info[key] + + # Restore proc_history[*]['date'] as tuple + # JSON converts tuples to lists, so we need to convert back + for entry in info.get("proc_history", []): + if "date" in entry and isinstance(entry["date"], np.ndarray): + # Convert numpy array back to tuple with Python types + entry["date"] = tuple(int(x) for x in entry["date"]) + + +# TODO: Add fNIRS convention to loc +class Info(ValidatedDict, SetChannelsMixin, MontageMixin, ContainsMixin): + """Measurement information. + + This data structure behaves like a dictionary. It contains all metadata + that is available for a recording. However, its keys are restricted to + those provided by the + `FIF format specification `__, + so new entries should not be manually added. + + .. note:: + This class should not be instantiated directly via + ``mne.Info(...)``. Instead, use :func:`mne.create_info` to create + measurement information from scratch. + + .. warning:: + The only entries that should be manually changed by the user are: + ``info['bads']``, ``info['description']``, ``info['device_info']``, + ``info['proj_id']``, ``info['proj_name']``, ``info['dev_head_t']``, + ``info['experimenter']``, ``info['helium_info']``, + ``info['line_freq']``, ``info['temp']``, and ``info['subject_info']``. + + All other entries should be considered read-only, though they can be + modified by various MNE-Python functions or methods (which have + safeguards to ensure all fields remain in sync). + + Parameters + ---------- + *args : list + Arguments. + **kwargs : dict + Keyword arguments. + + Attributes + ---------- + acq_pars : str | None + MEG system acquisition parameters. + See :class:`mne.AcqParserFIF` for details. + acq_stim : str | None + MEG system stimulus parameters. + bads : list of str + List of bad (noisy/broken) channels, by name. These channels will by + default be ignored by many processing steps. + ch_names : list of str + The names of the channels. + chs : list of dict + A list of channel information dictionaries, one per channel. + See Notes for more information. + command_line : str + Contains the command and arguments used to create the source space + (used for source estimation). + comps : list of dict + CTF software gradient compensation data. + See Notes for more information. + ctf_head_t : Transform | None + The transformation from 4D/CTF head coordinates to Neuromag head + coordinates. This is only present in 4D/CTF data. + custom_ref_applied : int + Whether a custom (=other than an average projector) reference has been + applied to the EEG data. This flag is checked by some algorithms that + require an average reference to be set. + description : str | None + String description of the recording. + dev_ctf_t : Transform | None + The transformation from device coordinates to 4D/CTF head coordinates. + This is only present in 4D/CTF data. + dev_head_t : Transform | None + The device to head transformation. + device_info : dict | None + Information about the acquisition device. See Notes for details. + + .. versionadded:: 0.19 + dig : list of dict | None + The Polhemus digitization data in head coordinates. + See Notes for more information. + events : list of dict + Event list, sometimes extracted from the stim channels by Neuromag + systems. In general this should not be used and + :func:`mne.find_events` should be used for event processing. + See Notes for more information. + experimenter : str | None + Name of the person that ran the experiment. + file_id : dict | None + The FIF globally unique ID. See Notes for more information. + gantry_angle : float | None + Tilt angle of the gantry in degrees. + helium_info : dict | None + Information about the device helium. See Notes for details. + + .. versionadded:: 0.19 + highpass : float + Highpass corner frequency in Hertz. Zero indicates a DC recording. + hpi_meas : list of dict + HPI measurements that were taken at the start of the recording + (e.g. coil frequencies). + See Notes for details. + hpi_results : list of dict + Head position indicator (HPI) digitization points and fit information + (e.g., the resulting transform). + See Notes for details. + hpi_subsystem : dict | None + Information about the HPI subsystem that was used (e.g., event + channel used for cHPI measurements). + See Notes for details. + kit_system_id : int + Identifies the KIT system. + line_freq : float | None + Frequency of the power line in Hertz. + lowpass : float + Lowpass corner frequency in Hertz. + It is automatically set to half the sampling rate if there is + otherwise no low-pass applied to the data. + maxshield : bool + True if active shielding (IAS) was active during recording. + meas_date : datetime + The time (UTC) of the recording. + + .. versionchanged:: 0.20 + This is stored as a :class:`~python:datetime.datetime` object + instead of a tuple of seconds/microseconds. + meas_file : str | None + Raw measurement file (used for source estimation). + meas_id : dict | None + The ID assigned to this measurement by the acquisition system or + during file conversion. Follows the same format as ``file_id``. + mri_file : str | None + File containing the MRI to head transformation (used for source + estimation). + mri_head_t : dict | None + Transformation from MRI to head coordinates (used for source + estimation). + mri_id : dict | None + MRI unique ID (used for source estimation). + nchan : int + Number of channels. + proc_history : list of dict + The MaxFilter processing history. + See Notes for details. + proj_id : int | None + ID number of the project the experiment belongs to. + proj_name : str | None + Name of the project the experiment belongs to. + projs : list of Projection + List of SSP operators that operate on the data. + See :class:`mne.Projection` for details. + sfreq : float + Sampling frequency in Hertz. + subject_info : dict | None + Information about the subject. + See Notes for details. + temp : object | None + Can be used to store temporary objects in an Info instance. It will not + survive an I/O roundtrip. + + .. versionadded:: 0.24 + utc_offset : str + "UTC offset of related meas_date (sHH:MM). + + .. versionadded:: 0.19 + working_dir : str + Working directory used when the source space was created (used for + source estimation). + xplotter_layout : str + Layout of the Xplotter (Neuromag system only). + + See Also + -------- + mne.create_info + mne.pick_info + + Notes + ----- + The following parameters have a nested structure. + + * ``chs`` list of dict: + + cal : float + The calibration factor to bring the channels to physical + units. Used in product with ``range`` to scale the data read + from disk. + ch_name : str + The channel name. + coil_type : int + Coil type, e.g. ``FIFFV_COIL_MEG``. + coord_frame : int + The coordinate frame used, e.g. ``FIFFV_COORD_HEAD``. + kind : int + The kind of channel, e.g. ``FIFFV_EEG_CH``. + loc : array, shape (12,) + Channel location information. The first three elements ``[:3]`` always store + the nominal channel position. The remaining 9 elements store different + information based on the channel type: + + MEG + Remaining 9 elements ``[3:]``, contain the EX, EY, and EZ normal + triplets (columns) of the coil rotation/orientation matrix. + EEG + Elements ``[3:6]`` contain the reference channel position. + Eyetrack + Element ``[3]`` contains information about which eye was tracked + (-1 for left, 1 for right), and element ``[4]`` contains information + about the axis of coordinate data (-1 for x-coordinate data, 1 for + y-coordinate data). + Dipole + Elements ``[3:6]`` contain dipole orientation information. + logno : int + Logical channel number, conventions in the usage of this + number vary. + range : float + The hardware-oriented part of the calibration factor. + This should be only applied to the continuous raw data. + Used in product with ``cal`` to scale data read from disk. + scanno : int + Scanning order number, starting from 1. + unit : int + The unit to use, e.g. ``FIFF_UNIT_T_M``. + unit_mul : int + Unit multipliers, most commonly ``FIFF_UNITM_NONE``. + + * ``comps`` list of dict: + + ctfkind : int + CTF compensation grade. + colcals : ndarray + Column calibrations. + mat : dict + A named matrix dictionary (with entries "data", "col_names", etc.) + containing the compensation matrix. + rowcals : ndarray + Row calibrations. + save_calibrated : bool + Were the compensation data saved in calibrated form. + + * ``device_info`` dict: + + type : str + Device type. + model : str + Device model. + serial : str + Device serial. + site : str + Device site. + + * ``dig`` list of dict: + + kind : int + The kind of channel, + e.g. ``FIFFV_POINT_EEG``, ``FIFFV_POINT_CARDINAL``. + r : array, shape (3,) + 3D position in m. and coord_frame. + ident : int + Number specifying the identity of the point. + e.g. ``FIFFV_POINT_NASION`` if kind is ``FIFFV_POINT_CARDINAL``, or + 42 if kind is ``FIFFV_POINT_EEG``. + coord_frame : int + The coordinate frame used, e.g. ``FIFFV_COORD_HEAD``. + + * ``events`` list of dict: + + channels : list of int + Channel indices for the events. + list : ndarray, shape (n_events * 3,) + Events in triplets as number of samples, before, after. + + * ``file_id`` dict: + + version : int + FIF format version, i.e. ``FIFFC_VERSION``. + machid : ndarray, shape (2,) + Unique machine ID, usually derived from the MAC address. + secs : int + Time in seconds. + usecs : int + Time in microseconds. + + * ``helium_info`` dict: + + he_level_raw : float + Helium level (%) before position correction. + helium_level : float + Helium level (%) after position correction. + orig_file_guid : str + Original file GUID. + meas_date : datetime.datetime | None + The helium level meas date. + + .. versionchanged:: 1.8 + This is stored as a :class:`~python:datetime.datetime` object + instead of a tuple of seconds/microseconds. + + * ``hpi_meas`` list of dict: + + creator : str + Program that did the measurement. + sfreq : float + Sample rate. + nchan : int + Number of channels used. + nave : int + Number of averages used. + ncoil : int + Number of coils used. + first_samp : int + First sample used. + last_samp : int + Last sample used. + hpi_coils : list of dict + Coils, containing: + + number: int + Coil number + epoch : ndarray + Buffer containing one epoch and channel. + slopes : ndarray, shape (n_channels,) + HPI data. + corr_coeff : ndarray, shape (n_channels,) + HPI curve fit correlations. + coil_freq : float + HPI coil excitation frequency + + * ``hpi_results`` list of dict: + + dig_points : list + Digitization points (see ``dig`` definition) for the HPI coils. + order : ndarray, shape (ncoil,) + The determined digitization order. + used : ndarray, shape (nused,) + The indices of the used coils. + moments : ndarray, shape (ncoil, 3) + The coil moments. + goodness : ndarray, shape (ncoil,) + The goodness of fits. + good_limit : float + The goodness of fit limit. + dist_limit : float + The distance limit. + accept : int + Whether or not the fit was accepted. + coord_trans : instance of Transform + The resulting MEG<->head transformation. + + * ``hpi_subsystem`` dict: + + ncoil : int + The number of coils. + event_channel : str + The event channel used to encode cHPI status (e.g., STI201). + hpi_coils : list of ndarray + List of length ``ncoil``, each 4-element ndarray contains the + event bits used on the event channel to indicate cHPI status + (using the first element of these arrays is typically + sufficient). + + * ``mri_id`` dict: + + version : int + FIF format version, i.e. ``FIFFC_VERSION``. + machid : ndarray, shape (2,) + Unique machine ID, usually derived from the MAC address. + secs : int + Time in seconds. + usecs : int + Time in microseconds. + + * ``proc_history`` list of dict: + + block_id : dict + See ``id`` above. + date : ndarray, shape (2,) + 2-element tuple of seconds and microseconds. + experimenter : str + Name of the person who ran the program. + creator : str + Program that did the processing. + max_info : dict + Maxwel filtering info, can contain: + + sss_info : dict + SSS processing information. + max_st + tSSS processing information. + sss_ctc : dict + Cross-talk processing information. + sss_cal : dict + Fine-calibration information. + smartshield : dict + MaxShield information. This dictionary is (always?) empty, + but its presence implies that MaxShield was used during + acquisition. + + * ``subject_info`` dict: + + id : int + Integer subject identifier. + his_id : str + String subject identifier. + last_name : str + Last name. + first_name : str + First name. + middle_name : str + Middle name. + birthday : datetime.date + The subject birthday. + + .. versionchanged:: 1.8 + This is stored as a :class:`~python:datetime.date` object + instead of a tuple of seconds/microseconds. + sex : int + Subject sex (0=unknown, 1=male, 2=female). + hand : int + Handedness (1=right, 2=left, 3=ambidextrous). + weight : float + Weight in kilograms. + height : float + Height in meters. + """ + + _attributes = { + "acq_pars": "acq_pars cannot be set directly. " + "See mne.AcqParserFIF() for details.", + "acq_stim": "acq_stim cannot be set directly.", + "bads": _check_bads, + "ch_names": "ch_names cannot be set directly. " + "Please use methods inst.add_channels(), " + "inst.drop_channels(), inst.pick(), " + "inst.rename_channels(), inst.reorder_channels() " + "and inst.set_channel_types() instead.", + "chs": "chs cannot be set directly. " + "Please use methods inst.add_channels(), " + "inst.drop_channels(), inst.pick(), " + "inst.rename_channels(), inst.reorder_channels() " + "and inst.set_channel_types() instead.", + "command_line": "command_line cannot be set directly.", + "comps": "comps cannot be set directly. " + "Please use method Raw.apply_gradient_compensation() " + "instead.", + "ctf_head_t": "ctf_head_t cannot be set directly.", + "custom_ref_applied": "custom_ref_applied cannot be set directly. " + "Please use method inst.set_eeg_reference() " + "instead.", + "description": partial(_check_types, name="description", types=(str, None)), + "dev_ctf_t": "dev_ctf_t cannot be set directly.", + "dev_head_t": _check_dev_head_t, + "device_info": partial(_check_types, name="device_info", types=(dict, None)), + "dig": "dig cannot be set directly. " + "Please use method inst.set_montage() instead.", + "events": "events cannot be set directly.", + "experimenter": partial(_check_types, name="experimenter", types=(str, None)), + "file_id": "file_id cannot be set directly.", + "gantry_angle": "gantry_angle cannot be set directly.", + "helium_info": partial( + _check_types, name="helium_info", types=(dict, None), cast=HeliumInfo + ), + "highpass": "highpass cannot be set directly. " + "Please use method inst.filter() instead.", + "hpi_meas": "hpi_meas can not be set directly.", + "hpi_results": "hpi_results cannot be set directly.", + "hpi_subsystem": "hpi_subsystem cannot be set directly.", + "kit_system_id": "kit_system_id cannot be set directly.", + "line_freq": partial( + _check_types, name="line_freq", types=("numeric", None), cast=float + ), + "lowpass": "lowpass cannot be set directly. " + "Please use method inst.filter() instead.", + "maxshield": "maxshield cannot be set directly.", + "meas_date": "meas_date cannot be set directly. " + "Please use method inst.set_meas_date() instead.", + "meas_file": "meas_file cannot be set directly.", + "meas_id": "meas_id cannot be set directly.", + "mri_file": "mri_file cannot be set directly.", + "mri_head_t": "mri_head_t cannot be set directly.", + "mri_id": "mri_id cannot be set directly.", + "nchan": "nchan cannot be set directly. " + "Please use methods inst.add_channels(), " + "inst.drop_channels(), and inst.pick() instead.", + "proc_history": "proc_history cannot be set directly.", + "proj_id": partial(_check_types, name="proj_id", types=(int, None), cast=int), + "proj_name": partial(_check_types, name="proj_name", types=(str, None)), + "projs": "projs cannot be set directly. " + "Please use methods inst.add_proj() and inst.del_proj() " + "instead.", + "sfreq": "sfreq cannot be set directly. " + "Please use method inst.resample() instead.", + "subject_info": partial( + _check_types, name="subject_info", types=(dict, None), cast=SubjectInfo + ), + "temp": lambda x, info=None: x, + "utc_offset": "utc_offset cannot be set directly.", + "working_dir": "working_dir cannot be set directly.", + "xplotter_layout": "xplotter_layout cannot be set directly.", + } + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + with self._unlock(): + _restore_mne_types(self) + + def __setstate__(self, state): + """Set state (for pickling).""" + super().__setstate__(state) + self["bads"] = MNEBadsList(bads=self["bads"], info=self) + + @contextlib.contextmanager + def _unlock(self, *, update_redundant=False, check_after=False): + """Context manager unlocking access to attributes.""" + # needed for nested _unlock() + state = self._unlocked if hasattr(self, "_unlocked") else False + + self._unlocked = True + try: + yield + except Exception: + raise + else: + if update_redundant: + self._update_redundant() + if check_after: + self._check_consistency() + finally: + self._unlocked = state + + def normalize_proj(self): + """(Re-)Normalize projection vectors after subselection. + + Applying projection after sub-selecting a set of channels that + were originally used to compute the original projection vectors + can be dangerous (e.g., if few channels remain, most power was + in channels that are no longer picked, etc.). By default, mne + will emit a warning when this is done. + + This function will re-normalize projectors to use only the + remaining channels, thus avoiding that warning. Only use this + function if you're confident that the projection vectors still + adequately capture the original signal of interest. + """ + _normalize_proj(self) + + def __repr__(self): + """Summarize info instead of printing all.""" + from ..io.kit.constants import KIT_SYSNAMES + from ..transforms import Transform, _coord_frame_name + + MAX_WIDTH = 68 + strs = [" {frame2} transform" + else: + entr = "" + elif k in ["sfreq", "lowpass", "highpass"]: + entr = f"{v:.1f} Hz" + elif isinstance(v, str): + entr = shorten(v, MAX_WIDTH, placeholder=" ...") + elif k == "chs": + # TODO someday we should refactor with _repr_html_ with + # bad vs good + ch_types = [channel_type(self, idx) for idx in range(len(v))] + ch_counts = Counter(ch_types) + entr = ", ".join( + f"{count} {titles.get(ch_type, ch_type.upper())}" + for ch_type, count in ch_counts.items() + ) + elif k == "custom_ref_applied": + entr = str(bool(v)) + if not v: + non_empty -= 1 # don't count if 0 + elif isinstance(v, ValidatedDict): + entr = repr(v) + else: + try: + this_len = len(v) + except TypeError: + entr = f"{v}" if v is not None else "" + else: + if this_len > 0: + entr = f"{this_len} item{_pl(this_len)} ({type(v).__name__})" + else: + entr = "" + if entr != "": + non_empty += 1 + strs.append(f"{k}: {entr}") + st = "\n ".join(sorted(strs)) + st += "\n>" + st %= non_empty + return st + + def __deepcopy__(self, memodict): + """Make a deepcopy.""" + result = Info.__new__(Info) + result._unlocked = True + for k, v in self.items(): + # chs is roughly half the time but most are immutable + if k == "chs": + # dict shallow copy is fast, so use it then overwrite + result[k] = list() + for ch in v: + ch = ch.copy() # shallow + ch["loc"] = ch["loc"].copy() + result[k].append(ch) + elif k == "ch_names": + # we know it's list of str, shallow okay and saves ~100 µs + result[k] = v.copy() + elif k == "hpi_meas": + hms = list() + for hm in v: + hm = hm.copy() + # the only mutable thing here is some entries in coils + hm["hpi_coils"] = [coil.copy() for coil in hm["hpi_coils"]] + # There is a *tiny* risk here that someone could write + # raw.info['hpi_meas'][0]['hpi_coils'][1]['epoch'] = ... + # and assume that info.copy() will make an actual copy, + # but copying these entries has a 2x slowdown penalty so + # probably not worth it for such a deep corner case: + # for coil in hpi_coils: + # for key in ('epoch', 'slopes', 'corr_coeff'): + # coil[key] = coil[key].copy() + hms.append(hm) + result[k] = hms + else: + result[k] = deepcopy(v, memodict) + result._unlocked = False + return result + + def _check_consistency(self, prepend_error=""): + """Do some self-consistency checks and datatype tweaks.""" + meas_date = self.get("meas_date") + if meas_date is not None: + if ( + not isinstance(self["meas_date"], datetime.datetime) + or self["meas_date"].tzinfo is None + or self["meas_date"].tzinfo is not datetime.timezone.utc + ): + raise RuntimeError( + f'{prepend_error}info["meas_date"] must be a datetime object in UTC' + f" or None, got {repr(self['meas_date'])!r}" + ) + + chs = [ch["ch_name"] for ch in self["chs"]] + if ( + len(self["ch_names"]) != len(chs) + or any(ch_1 != ch_2 for ch_1, ch_2 in zip(self["ch_names"], chs)) + or self["nchan"] != len(chs) + ): + raise RuntimeError( + f"{prepend_error}info channel name inconsistency detected, please " + "notify MNE-Python developers" + ) + + # make sure we have the proper datatypes + with self._unlock(): + for key in ("sfreq", "highpass", "lowpass"): + if self.get(key) is not None: + self[key] = float(self[key]) + + for pi, proj in enumerate(self.get("projs", [])): + _validate_type(proj, Projection, f'info["projs"][{pi}]') + for key in ("kind", "active", "desc", "data", "explained_var"): + if key not in proj: + raise RuntimeError(f"Projection incomplete, missing {key}") + + # Ensure info['chs'] has immutable entries (copies much faster) + for ci, ch in enumerate(self["chs"]): + _check_ch_keys(ch, ci) + ch_name = ch["ch_name"] + _validate_type(ch_name, str, f'info["chs"][{ci}]["ch_name"]') + for key in _SCALAR_CH_KEYS: + val = ch.get(key, 1) + _validate_type(val, "numeric", f'info["chs"][{ci}][{key}]') + loc = ch["loc"] + if not (isinstance(loc, np.ndarray) and loc.shape == (12,)): + raise TypeError( + f'Bad info: info["chs"][{ci}]["loc"] must be ndarray with ' + f"12 elements, got {repr(loc)}" + ) + + # make sure channel names are unique + with self._unlock(): + self["ch_names"] = _unique_channel_names(self["ch_names"]) + for idx, ch_name in enumerate(self["ch_names"]): + self["chs"][idx]["ch_name"] = ch_name + + def _update_redundant(self): + """Update the redundant entries.""" + with self._unlock(): + self["ch_names"] = [ch["ch_name"] for ch in self["chs"]] + self["nchan"] = len(self["chs"]) + + @property + def ch_names(self): + try: + ch_names = self["ch_names"] + except KeyError: + ch_names = [] + + return ch_names + + @property + def _cals(self): + return np.array([ch["range"] * ch["cal"] for ch in self["chs"]], float) + + @repr_html + def _repr_html_(self): + """Summarize info for HTML representation.""" + info_template = _get_html_template("repr", "info.html.jinja") + return info_template.render(info=self) + + @verbose + def save(self, fname, *, overwrite=False, verbose=None): + """Write measurement info in fif file. + + Parameters + ---------- + fname : path-like + The name of the file. Should end by ``'-info.fif'``. + %(overwrite)s + + .. versionadded:: 1.10 + %(verbose)s + + See Also + -------- + mne.io.write_info + """ + write_info(fname, self, overwrite=overwrite) + + def to_json_dict(self) -> dict: + """Convert Info to a JSON-serializable dictionary. + + This method converts the Info object to a standard Python dictionary + containing only JSON-serializable types (dict, list, str, int, float, + bool, None). Numpy arrays are converted to nested lists, and datetime + objects to ISO format strings. + + Returns + ------- + dict + A JSON-serializable dictionary representation of the Info object. + + See Also + -------- + from_json_dict : Reconstruct Info object from dictionary. + + Notes + ----- + This method is useful for serializing Info objects to JSON or other + formats that don't support numpy arrays or custom objects. + + Examples + -------- + >>> info = mne.create_info(['MEG1', 'MEG2'], 1000., ['mag', 'mag']) + >>> info_dict = info.to_json_dict() + >>> import json + >>> json_str = json.dumps(info_dict) # Save to JSON + """ + return _make_serializable(self) + + @classmethod + def from_json_dict(cls, data_dict) -> "Info": + """Reconstruct Info object from a dictionary. + + Parameters + ---------- + data_dict : dict + A dictionary representation of an Info object, typically + created by the :meth:`to_json_dict` method. + + Returns + ------- + Info + The reconstructed Info object. + + See Also + -------- + to_json_dict : Convert Info to dictionary. + + Examples + -------- + >>> info = mne.create_info(['MEG1', 'MEG2'], 1000., ['mag', 'mag']) + >>> info_dict = info.to_json_dict() + >>> info_restored = mne.Info.from_json_dict(info_dict) + """ + data_dict = data_dict.copy() + # Restore all nested objects (Transform, NamedInt, etc.) + restored_dict = _restore_objects(data_dict) + + info = cls() + with info._unlock(): + info.update(restored_dict) + _restore_mne_types(info) + + return info + + +def _make_serializable(obj): + """Recursively convert objects to JSON-serializable types.""" + from ..transforms import Transform + + if obj is None: + return None + elif isinstance(obj, bool): + return obj + elif isinstance(obj, NamedInt): + # Preserve NamedInt with its name + return {"_mne_type": "NamedInt", "value": int(obj), "name": obj._name} + elif isinstance(obj, NamedFloat): + # Preserve NamedFloat with its name + return {"_mne_type": "NamedFloat", "value": float(obj), "name": obj._name} + elif isinstance(obj, (str, int, float)): + return obj + elif isinstance(obj, np.integer): + return int(obj) + elif isinstance(obj, np.floating): + return float(obj) + elif isinstance(obj, np.ndarray): + return obj.tolist() + elif isinstance(obj, datetime.datetime): + # Tag datetime objects for proper reconstruction + return {"_mne_type": "datetime", "value": obj.isoformat()} + elif isinstance(obj, datetime.date): + # Tag date objects for proper reconstruction + return {"_mne_type": "date", "value": obj.isoformat()} + elif isinstance(obj, Transform): + # Tag Transform objects for proper reconstruction + return { + "_mne_type": "Transform", + "from": obj["from"], + "to": obj["to"], + "trans": obj["trans"].tolist(), + } + elif isinstance(obj, (list, tuple)): + return [_make_serializable(item) for item in obj] + elif isinstance(obj, dict): + return {key: _make_serializable(val) for key, val in obj.items()} + else: + # Try to convert to string as fallback + return str(obj) + + +def _restore_objects(obj) -> object: + """Recursively restore objects from JSON-serializable types.""" + if obj is None: + return None + elif isinstance(obj, (bool, int, float)): + return obj + elif isinstance(obj, str): + # Regular strings are returned as-is + return obj + elif isinstance(obj, list): + # Check if all elements are numbers - convert to numpy array + # (JSON doesn't distinguish between tuples and lists, so 1D numeric + # lists that came from numpy arrays should be restored as numpy arrays, + # while tuple fields like proc_history[date] are handled separately) + if len(obj) > 0 and all(isinstance(x, (int, float)) for x in obj): + # 1D numeric arrays should be converted to numpy arrays + return np.array(obj) + elif len(obj) > 0 and all(isinstance(x, list) for x in obj): + # 2D or higher dimensional arrays + return np.array(obj) + else: + # Mixed types - recursively restore elements + return [_restore_objects(item) for item in obj] + elif isinstance(obj, dict): + # Check if this is a tagged MNE type + if "_mne_type" in obj: + if obj["_mne_type"] == "Transform": + # Actually create the Transform object now + from ..transforms import Transform + + return Transform(obj["from"], obj["to"], np.array(obj["trans"])) + elif obj["_mne_type"] == "NamedInt": + return NamedInt(obj["name"], obj["value"]) + elif obj["_mne_type"] == "NamedFloat": + return NamedFloat(obj["name"], obj["value"]) + elif obj["_mne_type"] == "datetime": + # Restore datetime object from ISO format string + return datetime.datetime.fromisoformat(obj["value"]) + elif obj["_mne_type"] == "date": + # Restore date object from ISO format string + return datetime.date.fromisoformat(obj["value"]) + # Add more types here if needed in the future + else: + return {key: _restore_objects(val) for key, val in obj.items()} + else: + return obj + + +def _simplify_info(info, *, keep=()): + """Return a simplified info structure to speed up picking.""" + chs = [ + {key: ch[key] for key in ("ch_name", "kind", "unit", "coil_type", "loc", "cal")} + for ch in info["chs"] + ] + keys = ("bads", "comps", "projs", "custom_ref_applied") + keep + sub_info = Info((key, info[key]) for key in keys if key in info) + with sub_info._unlock(): + sub_info["chs"] = chs + sub_info._update_redundant() + return sub_info + + +@verbose +def read_fiducials(fname, *, verbose=None): + """Read fiducials from a fiff file. + + Parameters + ---------- + fname : path-like + The filename to read. + %(verbose)s + + Returns + ------- + pts : list of dict + List of digitizer points (each point in a dict). + coord_frame : int + The coordinate frame of the points (one of + ``mne.io.constants.FIFF.FIFFV_COORD_...``). + """ + fname = _check_fname(fname=fname, overwrite="read", must_exist=True) + fid, tree, _ = fiff_open(fname) + with fid: + pts = _read_dig_fif(fid, tree) + return pts, pts[0]["coord_frame"] + + +@verbose +def write_fiducials( + fname, pts, coord_frame="unknown", *, overwrite=False, verbose=None +): + """Write fiducials to a fiff file. + + Parameters + ---------- + fname : path-like + Destination file name. + pts : iterator of dict + Iterator through digitizer points. Each point is a dictionary with + the keys 'kind', 'ident' and 'r'. + coord_frame : str | int + The coordinate frame of the points. If a string, must be one of + ``'meg'``, ``'mri'``, ``'mri_voxel'``, ``'head'``, + ``'mri_tal'``, ``'ras'``, ``'fs_tal'``, ``'ctf_head'``, + ``'ctf_meg'``, and ``'unknown'`` + If an integer, must be one of the constants defined as + ``mne.io.constants.FIFF.FIFFV_COORD_...``. + %(overwrite)s + + .. versionadded:: 1.0 + %(verbose)s + """ + write_dig(fname, pts, coord_frame, overwrite=overwrite) + + +@verbose +def read_info(fname, verbose=None): + """Read measurement info from a file. + + Parameters + ---------- + fname : path-like + File name. + %(verbose)s + + Returns + ------- + %(info_not_none)s + """ + check_fname(fname, "Info", (".fif", ".fif.gz")) + fname = _check_fname(fname, must_exist=True, overwrite="read") + f, tree, _ = fiff_open(fname) + with f as fid: + info = read_meas_info(fid, tree)[0] + return info + + +def read_bad_channels(fid, node): + """Read bad channels. + + Parameters + ---------- + fid : file + The file descriptor. + node : dict + The node of the FIF tree that contains info on the bad channels. + + Returns + ------- + bads : list + A list of bad channel's names. + """ + return _read_bad_channels(fid, node) + + +def _read_bad_channels(fid, node, ch_names_mapping): + ch_names_mapping = {} if ch_names_mapping is None else ch_names_mapping + nodes = dir_tree_find(node, FIFF.FIFFB_MNE_BAD_CHANNELS) + + bads = [] + if len(nodes) > 0: + for node in nodes: + tag = find_tag(fid, node, FIFF.FIFF_MNE_CH_NAME_LIST) + if tag is not None and tag.data is not None: + bads = _safe_name_list(tag.data, "read", "bads") + bads[:] = _rename_list(bads, ch_names_mapping) + return bads + + +def _write_bad_channels(fid, bads, ch_names_mapping): + if bads is not None and len(bads) > 0: + ch_names_mapping = {} if ch_names_mapping is None else ch_names_mapping + bads = _rename_list(bads, ch_names_mapping) + start_block(fid, FIFF.FIFFB_MNE_BAD_CHANNELS) + write_name_list_sanitized(fid, FIFF.FIFF_MNE_CH_NAME_LIST, bads, "bads") + end_block(fid, FIFF.FIFFB_MNE_BAD_CHANNELS) + + +@verbose +def read_meas_info(fid, tree, clean_bads=False, verbose=None): + """Read the measurement info. + + Parameters + ---------- + fid : file + Open file descriptor. + tree : tree + FIF tree structure. + clean_bads : bool + If True, clean info['bads'] before running consistency check. + Should only be needed for old files where we did not check bads + before saving. + %(verbose)s + + Returns + ------- + %(info_not_none)s + meas : dict + Node in tree that contains the info. + """ + from ..transforms import Transform, invert_transform + + # Find the desired blocks + meas = dir_tree_find(tree, FIFF.FIFFB_MEAS) + if len(meas) == 0: + raise ValueError("Could not find measurement data") + if len(meas) > 1: + raise ValueError("Cannot read more that 1 measurement data") + meas = meas[0] + + meas_info = dir_tree_find(meas, FIFF.FIFFB_MEAS_INFO) + if len(meas_info) == 0: + raise ValueError("Could not find measurement info") + if len(meas_info) > 1: + raise ValueError("Cannot read more that 1 measurement info") + meas_info = meas_info[0] + + # Read measurement info + dev_head_t = None + ctf_head_t = None + dev_ctf_t = None + meas_date = None + utc_offset = None + highpass = None + lowpass = None + nchan = None + sfreq = None + chs = [] + experimenter = None + description = None + proj_id = None + proj_name = None + line_freq = None + gantry_angle = None + custom_ref_applied = FIFF.FIFFV_MNE_CUSTOM_REF_OFF + xplotter_layout = None + kit_system_id = None + for k in range(meas_info["nent"]): + kind = meas_info["directory"][k].kind + pos = meas_info["directory"][k].pos + if kind == FIFF.FIFF_NCHAN: + tag = read_tag(fid, pos) + nchan = int(tag.data.item()) + elif kind == FIFF.FIFF_SFREQ: + tag = read_tag(fid, pos) + sfreq = float(tag.data.item()) + elif kind == FIFF.FIFF_CH_INFO: + tag = read_tag(fid, pos) + chs.append(tag.data) + elif kind == FIFF.FIFF_LOWPASS: + tag = read_tag(fid, pos) + if not np.isnan(tag.data.item()): + lowpass = float(tag.data.item()) + elif kind == FIFF.FIFF_HIGHPASS: + tag = read_tag(fid, pos) + if not np.isnan(tag.data): + highpass = float(tag.data.item()) + elif kind == FIFF.FIFF_MEAS_DATE: + tag = read_tag(fid, pos) + meas_date = tuple(tag.data) + if len(meas_date) == 1: # can happen from old C conversions + meas_date = (meas_date[0], 0) + elif kind == FIFF.FIFF_UTC_OFFSET: + tag = read_tag(fid, pos) + utc_offset = str(tag.data) + elif kind == FIFF.FIFF_COORD_TRANS: + tag = read_tag(fid, pos) + cand = tag.data + + if ( + cand["from"] == FIFF.FIFFV_COORD_DEVICE + and cand["to"] == FIFF.FIFFV_COORD_HEAD + ): + dev_head_t = cand + elif ( + cand["from"] == FIFF.FIFFV_COORD_HEAD + and cand["to"] == FIFF.FIFFV_COORD_DEVICE + ): + # this reversal can happen with BabyMEG data + dev_head_t = invert_transform(cand) + elif ( + cand["from"] == FIFF.FIFFV_MNE_COORD_CTF_HEAD + and cand["to"] == FIFF.FIFFV_COORD_HEAD + ): + ctf_head_t = cand + elif ( + cand["from"] == FIFF.FIFFV_MNE_COORD_CTF_DEVICE + and cand["to"] == FIFF.FIFFV_MNE_COORD_CTF_HEAD + ): + dev_ctf_t = cand + elif kind == FIFF.FIFF_EXPERIMENTER: + tag = read_tag(fid, pos) + experimenter = tag.data + elif kind == FIFF.FIFF_DESCRIPTION: + tag = read_tag(fid, pos) + description = tag.data + elif kind == FIFF.FIFF_PROJ_ID: + tag = read_tag(fid, pos) + proj_id = int(tag.data.item()) + elif kind == FIFF.FIFF_PROJ_NAME: + tag = read_tag(fid, pos) + proj_name = tag.data + elif kind == FIFF.FIFF_LINE_FREQ: + tag = read_tag(fid, pos) + line_freq = float(tag.data.item()) + elif kind == FIFF.FIFF_GANTRY_ANGLE: + tag = read_tag(fid, pos) + gantry_angle = float(tag.data.item()) + elif kind in [FIFF.FIFF_MNE_CUSTOM_REF, 236]: # 236 used before v0.11 + tag = read_tag(fid, pos) + custom_ref_applied = int(tag.data.item()) + elif kind == FIFF.FIFF_XPLOTTER_LAYOUT: + tag = read_tag(fid, pos) + xplotter_layout = str(tag.data) + elif kind == FIFF.FIFF_MNE_KIT_SYSTEM_ID: + tag = read_tag(fid, pos) + kit_system_id = int(tag.data.item()) + ch_names_mapping = _read_extended_ch_info(chs, meas_info, fid) + + # Check that we have everything we need + if nchan is None: + raise ValueError("Number of channels is not defined") + + if sfreq is None: + raise ValueError("Sampling frequency is not defined") + + if len(chs) == 0: + raise ValueError("Channel information not defined") + + if len(chs) != nchan: + raise ValueError("Incorrect number of channel definitions found") + + if dev_head_t is None or ctf_head_t is None: + hpi_result = dir_tree_find(meas_info, FIFF.FIFFB_HPI_RESULT) + if len(hpi_result) == 1: + hpi_result = hpi_result[0] + for k in range(hpi_result["nent"]): + kind = hpi_result["directory"][k].kind + pos = hpi_result["directory"][k].pos + if kind == FIFF.FIFF_COORD_TRANS: + tag = read_tag(fid, pos) + cand = tag.data + if ( + cand["from"] == FIFF.FIFFV_COORD_DEVICE + and cand["to"] == FIFF.FIFFV_COORD_HEAD + and dev_head_t is None + ): + dev_head_t = cand + elif ( + cand["from"] == FIFF.FIFFV_MNE_COORD_CTF_HEAD + and cand["to"] == FIFF.FIFFV_COORD_HEAD + and ctf_head_t is None + ): + ctf_head_t = cand + + # Locate the Polhemus data + dig = _read_dig_fif(fid, meas_info) + + # Locate the acquisition information + acqpars = dir_tree_find(meas_info, FIFF.FIFFB_DACQ_PARS) + acq_pars = None + acq_stim = None + if len(acqpars) == 1: + acqpars = acqpars[0] + for k in range(acqpars["nent"]): + kind = acqpars["directory"][k].kind + pos = acqpars["directory"][k].pos + if kind == FIFF.FIFF_DACQ_PARS: + tag = read_tag(fid, pos) + acq_pars = tag.data + elif kind == FIFF.FIFF_DACQ_STIM: + tag = read_tag(fid, pos) + acq_stim = tag.data + + # Load the SSP data + projs = _read_proj(fid, meas_info, ch_names_mapping=ch_names_mapping) + + # Load the CTF compensation data + comps = _read_ctf_comp(fid, meas_info, chs, ch_names_mapping=ch_names_mapping) + + # Load the bad channel list + bads = _read_bad_channels(fid, meas_info, ch_names_mapping=ch_names_mapping) + + # + # Put the data together + # + info = Info(file_id=tree["id"]) + info._unlocked = True + + # Locate events list + events = dir_tree_find(meas_info, FIFF.FIFFB_EVENTS) + evs = list() + for event in events: + ev = dict() + for k in range(event["nent"]): + kind = event["directory"][k].kind + pos = event["directory"][k].pos + if kind == FIFF.FIFF_EVENT_CHANNELS: + ev["channels"] = read_tag(fid, pos).data + elif kind == FIFF.FIFF_EVENT_LIST: + ev["list"] = read_tag(fid, pos).data + evs.append(ev) + info["events"] = evs + + # Locate HPI result + hpi_results = dir_tree_find(meas_info, FIFF.FIFFB_HPI_RESULT) + hrs = list() + for hpi_result in hpi_results: + hr = dict() + hr["dig_points"] = [] + for k in range(hpi_result["nent"]): + kind = hpi_result["directory"][k].kind + pos = hpi_result["directory"][k].pos + if kind == FIFF.FIFF_DIG_POINT: + hr["dig_points"].append(read_tag(fid, pos).data) + elif kind == FIFF.FIFF_HPI_DIGITIZATION_ORDER: + hr["order"] = read_tag(fid, pos).data + elif kind == FIFF.FIFF_HPI_COILS_USED: + hr["used"] = read_tag(fid, pos).data + elif kind == FIFF.FIFF_HPI_COIL_MOMENTS: + hr["moments"] = read_tag(fid, pos).data + elif kind == FIFF.FIFF_HPI_FIT_GOODNESS: + hr["goodness"] = read_tag(fid, pos).data + elif kind == FIFF.FIFF_HPI_FIT_GOOD_LIMIT: + hr["good_limit"] = float(read_tag(fid, pos).data.item()) + elif kind == FIFF.FIFF_HPI_FIT_DIST_LIMIT: + hr["dist_limit"] = float(read_tag(fid, pos).data.item()) + elif kind == FIFF.FIFF_HPI_FIT_ACCEPT: + hr["accept"] = int(read_tag(fid, pos).data.item()) + elif kind == FIFF.FIFF_COORD_TRANS: + hr["coord_trans"] = read_tag(fid, pos).data + hrs.append(hr) + info["hpi_results"] = hrs + + # Locate HPI Measurement + hpi_meass = dir_tree_find(meas_info, FIFF.FIFFB_HPI_MEAS) + hms = list() + for hpi_meas in hpi_meass: + hm = dict() + for k in range(hpi_meas["nent"]): + kind = hpi_meas["directory"][k].kind + pos = hpi_meas["directory"][k].pos + if kind == FIFF.FIFF_CREATOR: + hm["creator"] = str(read_tag(fid, pos).data) + elif kind == FIFF.FIFF_SFREQ: + hm["sfreq"] = float(read_tag(fid, pos).data.item()) + elif kind == FIFF.FIFF_NCHAN: + hm["nchan"] = int(read_tag(fid, pos).data.item()) + elif kind == FIFF.FIFF_NAVE: + hm["nave"] = int(read_tag(fid, pos).data.item()) + elif kind == FIFF.FIFF_HPI_NCOIL: + hm["ncoil"] = int(read_tag(fid, pos).data.item()) + elif kind == FIFF.FIFF_FIRST_SAMPLE: + hm["first_samp"] = int(read_tag(fid, pos).data.item()) + elif kind == FIFF.FIFF_LAST_SAMPLE: + hm["last_samp"] = int(read_tag(fid, pos).data.item()) + hpi_coils = dir_tree_find(hpi_meas, FIFF.FIFFB_HPI_COIL) + hcs = [] + for hpi_coil in hpi_coils: + hc = dict() + for k in range(hpi_coil["nent"]): + kind = hpi_coil["directory"][k].kind + pos = hpi_coil["directory"][k].pos + if kind == FIFF.FIFF_HPI_COIL_NO: + hc["number"] = int(read_tag(fid, pos).data.item()) + elif kind == FIFF.FIFF_EPOCH: + hc["epoch"] = read_tag(fid, pos).data + hc["epoch"].flags.writeable = False + elif kind == FIFF.FIFF_HPI_SLOPES: + hc["slopes"] = read_tag(fid, pos).data + hc["slopes"].flags.writeable = False + elif kind == FIFF.FIFF_HPI_CORR_COEFF: + hc["corr_coeff"] = read_tag(fid, pos).data + hc["corr_coeff"].flags.writeable = False + elif kind == FIFF.FIFF_HPI_COIL_FREQ: + hc["coil_freq"] = float(read_tag(fid, pos).data.item()) + hcs.append(hc) + hm["hpi_coils"] = hcs + hms.append(hm) + info["hpi_meas"] = hms + del hms + + subject_info = dir_tree_find(meas_info, FIFF.FIFFB_SUBJECT) + si = None + if len(subject_info) == 1: + subject_info = subject_info[0] + si = dict() + for k in range(subject_info["nent"]): + kind = subject_info["directory"][k].kind + pos = subject_info["directory"][k].pos + if kind == FIFF.FIFF_SUBJ_ID: + tag = read_tag(fid, pos) + si["id"] = int(tag.data.item()) + elif kind == FIFF.FIFF_SUBJ_HIS_ID: + tag = read_tag(fid, pos) + si["his_id"] = str(tag.data) + elif kind == FIFF.FIFF_SUBJ_LAST_NAME: + tag = read_tag(fid, pos) + si["last_name"] = str(tag.data) + elif kind == FIFF.FIFF_SUBJ_FIRST_NAME: + tag = read_tag(fid, pos) + si["first_name"] = str(tag.data) + elif kind == FIFF.FIFF_SUBJ_MIDDLE_NAME: + tag = read_tag(fid, pos) + si["middle_name"] = str(tag.data) + elif kind == FIFF.FIFF_SUBJ_BIRTH_DAY: + try: + tag = read_tag(fid, pos) + except OverflowError: + warn( + "Encountered an error while trying to read the " + "birthday from the input data. No birthday will be " + "set. Please check the integrity of the birthday " + "information in the input data." + ) + continue + si["birthday"] = tag.data + elif kind == FIFF.FIFF_SUBJ_SEX: + tag = read_tag(fid, pos) + si["sex"] = int(tag.data.item()) + elif kind == FIFF.FIFF_SUBJ_HAND: + tag = read_tag(fid, pos) + si["hand"] = int(tag.data.item()) + elif kind == FIFF.FIFF_SUBJ_WEIGHT: + tag = read_tag(fid, pos) + si["weight"] = float(tag.data.item()) + elif kind == FIFF.FIFF_SUBJ_HEIGHT: + tag = read_tag(fid, pos) + si["height"] = float(tag.data.item()) + info["subject_info"] = si + del si + + device_info = dir_tree_find(meas_info, FIFF.FIFFB_DEVICE) + di = None + if len(device_info) == 1: + device_info = device_info[0] + di = dict() + for k in range(device_info["nent"]): + kind = device_info["directory"][k].kind + pos = device_info["directory"][k].pos + if kind == FIFF.FIFF_DEVICE_TYPE: + tag = read_tag(fid, pos) + di["type"] = str(tag.data) + elif kind == FIFF.FIFF_DEVICE_MODEL: + tag = read_tag(fid, pos) + di["model"] = str(tag.data) + elif kind == FIFF.FIFF_DEVICE_SERIAL: + tag = read_tag(fid, pos) + di["serial"] = str(tag.data) + elif kind == FIFF.FIFF_DEVICE_SITE: + tag = read_tag(fid, pos) + di["site"] = str(tag.data) + info["device_info"] = di + del di + + helium_info = dir_tree_find(meas_info, FIFF.FIFFB_HELIUM) + hi = None + if len(helium_info) == 1: + helium_info = helium_info[0] + hi = dict() + for k in range(helium_info["nent"]): + kind = helium_info["directory"][k].kind + pos = helium_info["directory"][k].pos + if kind == FIFF.FIFF_HE_LEVEL_RAW: + tag = read_tag(fid, pos) + hi["he_level_raw"] = float(tag.data.item()) + elif kind == FIFF.FIFF_HELIUM_LEVEL: + tag = read_tag(fid, pos) + hi["helium_level"] = float(tag.data.item()) + elif kind == FIFF.FIFF_ORIG_FILE_GUID: + tag = read_tag(fid, pos) + hi["orig_file_guid"] = str(tag.data) + elif kind == FIFF.FIFF_MEAS_DATE: + tag = read_tag(fid, pos) + hi["meas_date"] = _ensure_meas_date_none_or_dt( + tuple(int(t) for t in tag.data), + ) + if "meas_date" not in hi: + hi["meas_date"] = None + info["helium_info"] = hi + del hi + + hpi_subsystem = dir_tree_find(meas_info, FIFF.FIFFB_HPI_SUBSYSTEM) + hs = None + if len(hpi_subsystem) == 1: + hpi_subsystem = hpi_subsystem[0] + hs = dict() + for k in range(hpi_subsystem["nent"]): + kind = hpi_subsystem["directory"][k].kind + pos = hpi_subsystem["directory"][k].pos + if kind == FIFF.FIFF_HPI_NCOIL: + tag = read_tag(fid, pos) + hs["ncoil"] = int(tag.data.item()) + elif kind == FIFF.FIFF_EVENT_CHANNEL: + tag = read_tag(fid, pos) + hs["event_channel"] = str(tag.data) + hpi_coils = dir_tree_find(hpi_subsystem, FIFF.FIFFB_HPI_COIL) + hc = [] + for coil in hpi_coils: + this_coil = dict() + for j in range(coil["nent"]): + kind = coil["directory"][j].kind + pos = coil["directory"][j].pos + if kind == FIFF.FIFF_EVENT_BITS: + tag = read_tag(fid, pos) + this_coil["event_bits"] = np.array(tag.data) + hc.append(this_coil) + hs["hpi_coils"] = hc + info["hpi_subsystem"] = hs + + # Read processing history + info["proc_history"] = _read_proc_history(fid, tree) + + # Make the most appropriate selection for the measurement id + if meas_info["parent_id"] is None: + if meas_info["id"] is None: + if meas["id"] is None: + if meas["parent_id"] is None: + info["meas_id"] = info["file_id"] + else: + info["meas_id"] = meas["parent_id"] + else: + info["meas_id"] = meas["id"] + else: + info["meas_id"] = meas_info["id"] + else: + info["meas_id"] = meas_info["parent_id"] + info["experimenter"] = experimenter + info["description"] = description + info["proj_id"] = proj_id + info["proj_name"] = proj_name + if meas_date is None: + meas_date = (info["meas_id"]["secs"], info["meas_id"]["usecs"]) + info["meas_date"] = _ensure_meas_date_none_or_dt(meas_date) + info["utc_offset"] = utc_offset + + info["sfreq"] = sfreq + info["highpass"] = highpass if highpass is not None else 0.0 + info["lowpass"] = lowpass if lowpass is not None else info["sfreq"] / 2.0 + info["line_freq"] = line_freq + info["gantry_angle"] = gantry_angle + + # Add the channel information and make a list of channel names + # for convenience + info["chs"] = chs + + # + # Add the coordinate transformations + # + info["dev_head_t"] = dev_head_t + info["ctf_head_t"] = ctf_head_t + info["dev_ctf_t"] = dev_ctf_t + if dev_head_t is not None and ctf_head_t is not None and dev_ctf_t is None: + head_ctf_trans = np.linalg.inv(ctf_head_t["trans"]) + dev_ctf_trans = np.dot(head_ctf_trans, info["dev_head_t"]["trans"]) + info["dev_ctf_t"] = Transform("meg", "ctf_head", dev_ctf_trans) + + # All kinds of auxliary stuff + info["dig"] = _format_dig_points(dig) + info["bads"] = bads + info._update_redundant() + if clean_bads: + info["bads"] = [b for b in bads if b in info["ch_names"]] + info["projs"] = projs + info["comps"] = comps + info["acq_pars"] = acq_pars + info["acq_stim"] = acq_stim + info["custom_ref_applied"] = custom_ref_applied + info["xplotter_layout"] = xplotter_layout + info["kit_system_id"] = kit_system_id + info._check_consistency() + info._unlocked = False + return info, meas + + +def _read_extended_ch_info(chs, parent, fid): + ch_infos = dir_tree_find(parent, FIFF.FIFFB_CH_INFO) + if len(ch_infos) == 0: + return + _check_option("length of channel infos", len(ch_infos), [len(chs)]) + logger.info(" Reading extended channel information") + + # Here we assume that ``remap`` is in the same order as the channels + # themselves, which is hopefully safe enough. + ch_names_mapping = dict() + for new, ch in zip(ch_infos, chs): + for k in range(new["nent"]): + kind = new["directory"][k].kind + try: + key, cast = _CH_READ_MAP[kind] + except KeyError: + # This shouldn't happen if we're up to date with the FIFF + # spec + warn(f"Discarding extra channel information kind {kind}") + continue + assert key in ch + data = read_tag(fid, new["directory"][k].pos).data + if data is not None: + data = cast(data) + if key == "ch_name": + ch_names_mapping[ch[key]] = data + ch[key] = data + _update_ch_info_named(ch) + # we need to return ch_names_mapping so that we can also rename the + # bad channels + return ch_names_mapping + + +def _rename_comps(comps, ch_names_mapping): + if not (comps and ch_names_mapping): + return + for comp in comps: + data = comp["data"] + for key in ("row_names", "col_names"): + data[key][:] = _rename_list(data[key], ch_names_mapping) + + +def _ensure_meas_date_none_or_dt(meas_date): + if meas_date is None or np.array_equal(meas_date, DATE_NONE): + meas_date = None + elif not isinstance(meas_date, datetime.datetime): + meas_date = _stamp_to_dt(meas_date) + return meas_date + + +def _check_dates(info, prepend_error=""): + """Check dates before writing as fif files. + + It's needed because of the limited integer precision + of the fix standard. + """ + for key in ("file_id", "meas_id"): + value = info.get(key) + if value is not None: + assert "msecs" not in value + for key_2 in ("secs", "usecs"): + if ( + value[key_2] < np.iinfo(">i4").min + or value[key_2] > np.iinfo(">i4").max + ): + raise RuntimeError( + f"{prepend_error}info[{key}][{key_2}] must be between " + f'"{np.iinfo(">i4").min!r}" and "{np.iinfo(">i4").max!r}", got ' + f'"{value[key_2]!r}"' + ) + + meas_date = info.get("meas_date") + if meas_date is None: + return + + meas_date_stamp = _dt_to_stamp(meas_date) + if ( + meas_date_stamp[0] < np.iinfo(">i4").min + or meas_date_stamp[0] > np.iinfo(">i4").max + ): + raise RuntimeError( + f'{prepend_error}info["meas_date"] seconds must be between ' + f'"{(np.iinfo(">i4").min, 0)!r}" and "{(np.iinfo(">i4").max, 0)!r}", got ' + f'"{meas_date_stamp[0]!r}"' + ) + + +@fill_doc +def write_meas_info(fid, info, data_type=None, reset_range=True): + """Write measurement info into a file id (from a fif file). + + Parameters + ---------- + fid : file + Open file descriptor. + %(info_not_none)s + data_type : int + The data_type in case it is necessary. Should be 4 (FIFFT_FLOAT), + 5 (FIFFT_DOUBLE), or 16 (FIFFT_DAU_PACK16) for + raw data. + reset_range : bool + If True, info['chs'][k]['range'] will be set to unity. + + Notes + ----- + Tags are written in a particular order for compatibility with maxfilter. + """ + info._check_consistency() + _check_dates(info) + + # Measurement info + start_block(fid, FIFF.FIFFB_MEAS_INFO) + + # Add measurement id + if info["meas_id"] is not None: + write_id(fid, FIFF.FIFF_PARENT_BLOCK_ID, info["meas_id"]) + + for event in info["events"]: + start_block(fid, FIFF.FIFFB_EVENTS) + if event.get("channels") is not None: + write_int(fid, FIFF.FIFF_EVENT_CHANNELS, event["channels"]) + if event.get("list") is not None: + write_int(fid, FIFF.FIFF_EVENT_LIST, event["list"]) + end_block(fid, FIFF.FIFFB_EVENTS) + + # HPI Result + for hpi_result in info["hpi_results"]: + start_block(fid, FIFF.FIFFB_HPI_RESULT) + write_dig_points(fid, hpi_result["dig_points"]) + if "order" in hpi_result: + write_int(fid, FIFF.FIFF_HPI_DIGITIZATION_ORDER, hpi_result["order"]) + if "used" in hpi_result: + write_int(fid, FIFF.FIFF_HPI_COILS_USED, hpi_result["used"]) + if "moments" in hpi_result: + write_float_matrix(fid, FIFF.FIFF_HPI_COIL_MOMENTS, hpi_result["moments"]) + if "goodness" in hpi_result: + write_float(fid, FIFF.FIFF_HPI_FIT_GOODNESS, hpi_result["goodness"]) + if "good_limit" in hpi_result: + write_float(fid, FIFF.FIFF_HPI_FIT_GOOD_LIMIT, hpi_result["good_limit"]) + if "dist_limit" in hpi_result: + write_float(fid, FIFF.FIFF_HPI_FIT_DIST_LIMIT, hpi_result["dist_limit"]) + if "accept" in hpi_result: + write_int(fid, FIFF.FIFF_HPI_FIT_ACCEPT, hpi_result["accept"]) + if "coord_trans" in hpi_result: + write_coord_trans(fid, hpi_result["coord_trans"]) + end_block(fid, FIFF.FIFFB_HPI_RESULT) + + # HPI Measurement + for hpi_meas in info["hpi_meas"]: + start_block(fid, FIFF.FIFFB_HPI_MEAS) + if hpi_meas.get("creator") is not None: + write_string(fid, FIFF.FIFF_CREATOR, hpi_meas["creator"]) + if hpi_meas.get("sfreq") is not None: + write_float(fid, FIFF.FIFF_SFREQ, hpi_meas["sfreq"]) + if hpi_meas.get("nchan") is not None: + write_int(fid, FIFF.FIFF_NCHAN, hpi_meas["nchan"]) + if hpi_meas.get("nave") is not None: + write_int(fid, FIFF.FIFF_NAVE, hpi_meas["nave"]) + if hpi_meas.get("ncoil") is not None: + write_int(fid, FIFF.FIFF_HPI_NCOIL, hpi_meas["ncoil"]) + if hpi_meas.get("first_samp") is not None: + write_int(fid, FIFF.FIFF_FIRST_SAMPLE, hpi_meas["first_samp"]) + if hpi_meas.get("last_samp") is not None: + write_int(fid, FIFF.FIFF_LAST_SAMPLE, hpi_meas["last_samp"]) + for hpi_coil in hpi_meas["hpi_coils"]: + start_block(fid, FIFF.FIFFB_HPI_COIL) + if hpi_coil.get("number") is not None: + write_int(fid, FIFF.FIFF_HPI_COIL_NO, hpi_coil["number"]) + if hpi_coil.get("epoch") is not None: + write_float_matrix(fid, FIFF.FIFF_EPOCH, hpi_coil["epoch"]) + if hpi_coil.get("slopes") is not None: + write_float(fid, FIFF.FIFF_HPI_SLOPES, hpi_coil["slopes"]) + if hpi_coil.get("corr_coeff") is not None: + write_float(fid, FIFF.FIFF_HPI_CORR_COEFF, hpi_coil["corr_coeff"]) + if hpi_coil.get("coil_freq") is not None: + write_float(fid, FIFF.FIFF_HPI_COIL_FREQ, hpi_coil["coil_freq"]) + end_block(fid, FIFF.FIFFB_HPI_COIL) + end_block(fid, FIFF.FIFFB_HPI_MEAS) + + # Polhemus data + write_dig_points(fid, info["dig"], block=True) + + # megacq parameters + if info["acq_pars"] is not None or info["acq_stim"] is not None: + start_block(fid, FIFF.FIFFB_DACQ_PARS) + if info["acq_pars"] is not None: + write_string(fid, FIFF.FIFF_DACQ_PARS, info["acq_pars"]) + + if info["acq_stim"] is not None: + write_string(fid, FIFF.FIFF_DACQ_STIM, info["acq_stim"]) + + end_block(fid, FIFF.FIFFB_DACQ_PARS) + + # Coordinate transformations if the HPI result block was not there + if info["dev_head_t"] is not None: + write_coord_trans(fid, info["dev_head_t"]) + + if info["ctf_head_t"] is not None: + write_coord_trans(fid, info["ctf_head_t"]) + + if info["dev_ctf_t"] is not None: + write_coord_trans(fid, info["dev_ctf_t"]) + + # Projectors + ch_names_mapping = _make_ch_names_mapping(info["chs"]) + _write_proj(fid, info["projs"], ch_names_mapping=ch_names_mapping) + + # Bad channels + _write_bad_channels(fid, info["bads"], ch_names_mapping=ch_names_mapping) + + # General + if info.get("experimenter") is not None: + write_string(fid, FIFF.FIFF_EXPERIMENTER, info["experimenter"]) + if info.get("description") is not None: + write_string(fid, FIFF.FIFF_DESCRIPTION, info["description"]) + if info.get("proj_id") is not None: + write_int(fid, FIFF.FIFF_PROJ_ID, info["proj_id"]) + if info.get("proj_name") is not None: + write_string(fid, FIFF.FIFF_PROJ_NAME, info["proj_name"]) + if info.get("meas_date") is not None: + write_int(fid, FIFF.FIFF_MEAS_DATE, _dt_to_stamp(info["meas_date"])) + if info.get("utc_offset") is not None: + write_string(fid, FIFF.FIFF_UTC_OFFSET, info["utc_offset"]) + write_int(fid, FIFF.FIFF_NCHAN, info["nchan"]) + write_float(fid, FIFF.FIFF_SFREQ, info["sfreq"]) + if info["lowpass"] is not None: + write_float(fid, FIFF.FIFF_LOWPASS, info["lowpass"]) + if info["highpass"] is not None: + write_float(fid, FIFF.FIFF_HIGHPASS, info["highpass"]) + if info.get("line_freq") is not None: + write_float(fid, FIFF.FIFF_LINE_FREQ, info["line_freq"]) + if info.get("gantry_angle") is not None: + write_float(fid, FIFF.FIFF_GANTRY_ANGLE, info["gantry_angle"]) + if data_type is not None: + write_int(fid, FIFF.FIFF_DATA_PACK, data_type) + if info.get("custom_ref_applied"): + write_int(fid, FIFF.FIFF_MNE_CUSTOM_REF, info["custom_ref_applied"]) + if info.get("xplotter_layout"): + write_string(fid, FIFF.FIFF_XPLOTTER_LAYOUT, info["xplotter_layout"]) + + # Channel information + _write_ch_infos(fid, info["chs"], reset_range, ch_names_mapping) + + # Subject information + if info.get("subject_info") is not None: + start_block(fid, FIFF.FIFFB_SUBJECT) + si = info["subject_info"] + if si.get("id") is not None: + write_int(fid, FIFF.FIFF_SUBJ_ID, si["id"]) + if si.get("his_id") is not None: + write_string(fid, FIFF.FIFF_SUBJ_HIS_ID, si["his_id"]) + if si.get("last_name") is not None: + write_string(fid, FIFF.FIFF_SUBJ_LAST_NAME, si["last_name"]) + if si.get("first_name") is not None: + write_string(fid, FIFF.FIFF_SUBJ_FIRST_NAME, si["first_name"]) + if si.get("middle_name") is not None: + write_string(fid, FIFF.FIFF_SUBJ_MIDDLE_NAME, si["middle_name"]) + if si.get("birthday") is not None: + write_julian(fid, FIFF.FIFF_SUBJ_BIRTH_DAY, si["birthday"]) + if si.get("sex") is not None: + write_int(fid, FIFF.FIFF_SUBJ_SEX, si["sex"]) + if si.get("hand") is not None: + write_int(fid, FIFF.FIFF_SUBJ_HAND, si["hand"]) + if si.get("weight") is not None: + write_float(fid, FIFF.FIFF_SUBJ_WEIGHT, si["weight"]) + if si.get("height") is not None: + write_float(fid, FIFF.FIFF_SUBJ_HEIGHT, si["height"]) + end_block(fid, FIFF.FIFFB_SUBJECT) + del si + + if info.get("device_info") is not None: + start_block(fid, FIFF.FIFFB_DEVICE) + di = info["device_info"] + if di.get("type") is not None: + write_string(fid, FIFF.FIFF_DEVICE_TYPE, di["type"]) + for key in ("model", "serial", "site"): + if di.get(key) is not None: + write_string(fid, getattr(FIFF, "FIFF_DEVICE_" + key.upper()), di[key]) + end_block(fid, FIFF.FIFFB_DEVICE) + del di + + if info.get("helium_info") is not None: + start_block(fid, FIFF.FIFFB_HELIUM) + hi = info["helium_info"] + if hi.get("he_level_raw") is not None: + write_float(fid, FIFF.FIFF_HE_LEVEL_RAW, hi["he_level_raw"]) + if hi.get("helium_level") is not None: + write_float(fid, FIFF.FIFF_HELIUM_LEVEL, hi["helium_level"]) + if hi.get("orig_file_guid") is not None: + write_string(fid, FIFF.FIFF_ORIG_FILE_GUID, hi["orig_file_guid"]) + if hi.get("meas_date", None) is not None: + write_int(fid, FIFF.FIFF_MEAS_DATE, _dt_to_stamp(hi["meas_date"])) + end_block(fid, FIFF.FIFFB_HELIUM) + del hi + + if info.get("hpi_subsystem") is not None: + hs = info["hpi_subsystem"] + start_block(fid, FIFF.FIFFB_HPI_SUBSYSTEM) + if hs.get("ncoil") is not None: + write_int(fid, FIFF.FIFF_HPI_NCOIL, hs["ncoil"]) + if hs.get("event_channel") is not None: + write_string(fid, FIFF.FIFF_EVENT_CHANNEL, hs["event_channel"]) + if hs.get("hpi_coils") is not None: + for coil in hs["hpi_coils"]: + start_block(fid, FIFF.FIFFB_HPI_COIL) + if coil.get("event_bits") is not None: + write_int(fid, FIFF.FIFF_EVENT_BITS, coil["event_bits"]) + end_block(fid, FIFF.FIFFB_HPI_COIL) + end_block(fid, FIFF.FIFFB_HPI_SUBSYSTEM) + del hs + + # CTF compensation info + comps = info["comps"] + if ch_names_mapping: + comps = deepcopy(comps) + _rename_comps(comps, ch_names_mapping) + write_ctf_comp(fid, comps) + + # KIT system ID + if info.get("kit_system_id") is not None: + write_int(fid, FIFF.FIFF_MNE_KIT_SYSTEM_ID, info["kit_system_id"]) + + end_block(fid, FIFF.FIFFB_MEAS_INFO) + + # Processing history + _write_proc_history(fid, info) + + +@verbose +def write_info( + fname, info, *, data_type=None, reset_range=True, overwrite=False, verbose=None +): + """Write measurement info in fif file. + + Parameters + ---------- + fname : path-like + The name of the file. Should end by ``-info.fif``. + %(info_not_none)s + data_type : int + The data_type in case it is necessary. Should be 4 (FIFFT_FLOAT), + 5 (FIFFT_DOUBLE), or 16 (FIFFT_DAU_PACK16) for + raw data. + reset_range : bool + If True, info['chs'][k]['range'] will be set to unity. + %(overwrite)s + %(verbose)s + """ + with start_and_end_file(fname, overwrite=overwrite) as fid: + start_block(fid, FIFF.FIFFB_MEAS) + write_meas_info(fid, info, data_type, reset_range) + end_block(fid, FIFF.FIFFB_MEAS) + + +@verbose +def _merge_info_values(infos, key, verbose=None): + """Merge things together. + + Fork for {'dict', 'list', 'array', 'other'} + and consider cases where one or all are of the same type. + + Does special things for "projs", "bads", and "meas_date". + """ + values = [d[key] for d in infos] + msg = ( + f"Don't know how to merge '{key}'. Make sure values are compatible, got types:" + f"\n {[type(v) for v in values]}" + ) + + def _flatten(lists): + return [item for sublist in lists for item in sublist] + + def _check_isinstance(values, kind, func): + return func([isinstance(v, kind) for v in values]) + + def _where_isinstance(values, kind): + """Get indices of instances.""" + return np.where([isinstance(v, type) for v in values])[0] + + # list + if _check_isinstance(values, list, all): + lists = (d[key] for d in infos) + if key == "projs": + return _uniquify_projs(_flatten(lists)) + elif key == "bads": + return sorted(set(_flatten(lists))) + else: + return _flatten(lists) + elif _check_isinstance(values, list, any): + idx = _where_isinstance(values, list) + if len(idx) == 1: + return values[int(idx)] + elif len(idx) > 1: + lists = (d[key] for d in infos if isinstance(d[key], list)) + return _flatten(lists) + # dict + elif _check_isinstance(values, dict, all): + is_qual = all(object_diff(values[0], v) == "" for v in values[1:]) + if is_qual: + return values[0] + else: + RuntimeError(msg) + elif _check_isinstance(values, dict, any): + idx = _where_isinstance(values, dict) + if len(idx) == 1: + return values[int(idx)] + elif len(idx) > 1: + raise RuntimeError(msg) + # ndarray + elif _check_isinstance(values, np.ndarray, all) or _check_isinstance( + values, tuple, all + ): + is_qual = all(np.array_equal(values[0], x) for x in values[1:]) + if is_qual: + return values[0] + elif key == "meas_date": + logger.info(f"Found multiple entries for {key}. Setting value to `None`") + return None + else: + raise RuntimeError(msg) + elif _check_isinstance(values, (np.ndarray, tuple), any): + idx = _where_isinstance(values, np.ndarray) + if len(idx) == 1: + return values[int(idx)] + elif len(idx) > 1: + raise RuntimeError(msg) + # proj_id + elif _check_isinstance(values, (int, type(None)), all) and key == "proj_id": + unique_values = set(values) + if len(unique_values) != 1: + logger.info("Found multiple proj_ids, using the first one.") + return list(unique_values)[0] + + elif key == "experimenter" or key == "proj_name": + if _check_isinstance(values, (str, type(None)), all): + unique_values = set(values) + unique_values.discard(None) + if len(unique_values) == 1: + return list(unique_values)[0] + else: + return None + # other + else: + unique_values = set(values) + if len(unique_values) == 1: + return list(values)[0] + elif isinstance(list(unique_values)[0], BytesIO): + logger.info("Found multiple StringIO instances. Setting value to `None`") + return None + elif isinstance(list(unique_values)[0], str): + logger.info(f"Found multiple {key}. Setting value to `None`") + return None + else: + raise RuntimeError(msg) + + +@verbose +def _merge_info(infos, force_update_to_first=False, verbose=None): + """Merge multiple measurement info dictionaries. + + - Fields that are present in only one info object will be used in the + merged info. + - Fields that are present in multiple info objects and are the same + will be used in the merged info. + - Fields that are present in multiple info objects and are different + will result in a None value in the merged info. + - Channels will be concatenated. If multiple info objects contain + channels with the same name, an exception is raised. + + Parameters + ---------- + infos | list of instance of Info + Info objects to merge into one info object. + force_update_to_first : bool + If True, force the fields for objects in `info` will be updated + to match those in the first item. Use at your own risk, as this + may overwrite important metadata. + %(verbose)s + + Returns + ------- + info : instance of Info + The merged info object. + """ + for info in infos: + info._check_consistency() + if force_update_to_first is True: + infos = deepcopy(infos) + _force_update_info(infos[0], infos[1:]) + info = Info() + info._unlocked = True + info["chs"] = [] + for this_info in infos: + info["chs"].extend(this_info["chs"]) + info._update_redundant() + duplicates = {ch for ch in info["ch_names"] if info["ch_names"].count(ch) > 1} + if len(duplicates) > 0: + msg = ( + "The following channels are present in more than one input " + f"measurement info objects: {list(duplicates)}" + ) + raise ValueError(msg) + + transforms = ["ctf_head_t", "dev_head_t", "dev_ctf_t"] + for trans_name in transforms: + trans = [i[trans_name] for i in infos if i[trans_name]] + if len(trans) == 0: + info[trans_name] = None + elif len(trans) == 1: + info[trans_name] = trans[0] + elif all( + np.all(trans[0]["trans"] == x["trans"]) + and trans[0]["from"] == x["from"] + and trans[0]["to"] == x["to"] + for x in trans[1:] + ): + info[trans_name] = trans[0] + else: + msg = f"Measurement infos provide mutually inconsistent {trans_name}" + raise ValueError(msg) + + # KIT system-IDs + kit_sys_ids = [i["kit_system_id"] for i in infos if i["kit_system_id"]] + if len(kit_sys_ids) == 0: + info["kit_system_id"] = None + elif len(set(kit_sys_ids)) == 1: + info["kit_system_id"] = kit_sys_ids[0] + else: + raise ValueError("Trying to merge channels from different KIT systems") + + # hpi infos and digitization data: + fields = ["hpi_results", "hpi_meas", "dig"] + for k in fields: + values = [i[k] for i in infos if i[k]] + if len(values) == 0: + info[k] = [] + elif len(values) == 1: + info[k] = values[0] + elif all(object_diff(values[0], v) == "" for v in values[1:]): + info[k] = values[0] + else: + msg = f"Measurement infos are inconsistent for {k}" + raise ValueError(msg) + + # other fields + other_fields = [ + "acq_pars", + "acq_stim", + "bads", + "comps", + "custom_ref_applied", + "description", + "experimenter", + "file_id", + "highpass", + "utc_offset", + "hpi_subsystem", + "events", + "device_info", + "helium_info", + "line_freq", + "lowpass", + "meas_id", + "proj_id", + "proj_name", + "projs", + "sfreq", + "gantry_angle", + "subject_info", + "sfreq", + "xplotter_layout", + "proc_history", + ] + + for k in other_fields: + info[k] = _merge_info_values(infos, k) + + info["meas_date"] = infos[0]["meas_date"] + info._unlocked = False + + return info + + +@verbose +def create_info(ch_names, sfreq, ch_types="misc", verbose=None): + """Create a basic Info instance suitable for use with create_raw. + + Parameters + ---------- + ch_names : list of str | int + Channel names. If an int, a list of channel names will be created + from ``range(ch_names)``. + sfreq : float + Sample rate of the data. + ch_types : list of str | str + Channel types, default is ``'misc'`` which is a + :term:`non-data channel `. + Currently supported fields are 'bio', 'chpi', 'csd', 'dbs', 'dipole', + 'ecg', 'ecog', 'eeg', 'emg', 'eog', 'exci', 'eyegaze', + 'fnirs_cw_amplitude', 'fnirs_fd_ac_amplitude', 'fnirs_fd_phase', + 'fnirs_od', 'gof', 'gsr', 'hbo', 'hbr', 'ias', 'misc', 'pupil', + 'ref_meg', 'resp', 'seeg', 'stim', 'syst', 'temperature' (see also + :term:`sensor types`). + If str, then all channels are assumed to be of the same type. + %(verbose)s + + Returns + ------- + %(info_not_none)s + + Notes + ----- + The info dictionary will be sparsely populated to enable functionality + within the rest of the package. Advanced functionality such as source + localization can only be obtained through substantial, proper + modifications of the info structure (not recommended). + + Note that the MEG device-to-head transform ``info['dev_head_t']`` will + be initialized to the identity transform. + + Proper units of measure: + + * V: eeg, eog, seeg, dbs, emg, ecg, bio, ecog, resp, fnirs_fd_ac_amplitude, + fnirs_cw_amplitude, fnirs_od + * T: mag, chpi, ref_meg + * T/m: grad + * M: hbo, hbr + * rad: fnirs_fd_phase + * Am: dipole + * S: gsr + * C: temperature + * V/m²: csd + * GOF: gof + * AU: misc, stim, eyegaze, pupil + """ + try: + ch_names = operator.index(ch_names) # int-like + except TypeError: + pass + else: + ch_names = list(np.arange(ch_names).astype(str)) + _validate_type(ch_names, (list, tuple), "ch_names", ("list, tuple, or int")) + sfreq = float(sfreq) + if sfreq <= 0: + raise ValueError("sfreq must be positive") + nchan = len(ch_names) + if isinstance(ch_types, str): + ch_types = [ch_types] * nchan + ch_types = np.atleast_1d(np.array(ch_types, np.str_)) + if ch_types.ndim != 1 or len(ch_types) != nchan: + raise ValueError( + f"ch_types and ch_names must be the same length ({len(ch_types)} != " + f"{nchan}) for ch_types={ch_types}" + ) + info = _empty_info(sfreq) + ch_types_dict = get_channel_type_constants(include_defaults=True) + for ci, (ch_name, ch_type) in enumerate(zip(ch_names, ch_types)): + _validate_type(ch_name, "str", "each entry in ch_names") + _validate_type(ch_type, "str", "each entry in ch_types") + if ch_type not in ch_types_dict: + raise KeyError(f"kind must be one of {list(ch_types_dict)}, not {ch_type}") + this_ch_dict = ch_types_dict[ch_type] + kind = this_ch_dict["kind"] + # handle chpi, where kind is a *list* of FIFF constants: + kind = kind[0] if isinstance(kind, list | tuple) else kind + # mirror what tag.py does here + coord_frame = _ch_coord_dict.get(kind, FIFF.FIFFV_COORD_UNKNOWN) + coil_type = this_ch_dict.get("coil_type", FIFF.FIFFV_COIL_NONE) + unit = this_ch_dict.get("unit", FIFF.FIFF_UNIT_NONE) + chan_info = dict( + loc=np.full(12, np.nan), + unit_mul=FIFF.FIFF_UNITM_NONE, + range=1.0, + cal=1.0, + kind=kind, + coil_type=coil_type, + unit=unit, + coord_frame=coord_frame, + ch_name=str(ch_name), + scanno=ci + 1, + logno=ci + 1, + ) + info["chs"].append(chan_info) + + info._update_redundant() + info._check_consistency() + info._unlocked = False + return info + + +RAW_INFO_FIELDS = ( + "acq_pars", + "acq_stim", + "bads", + "ch_names", + "chs", + "comps", + "ctf_head_t", + "custom_ref_applied", + "description", + "dev_ctf_t", + "dev_head_t", + "dig", + "experimenter", + "events", + "utc_offset", + "device_info", + "file_id", + "highpass", + "hpi_meas", + "hpi_results", + "helium_info", + "hpi_subsystem", + "kit_system_id", + "line_freq", + "lowpass", + "meas_date", + "meas_id", + "nchan", + "proj_id", + "proj_name", + "projs", + "sfreq", + "subject_info", + "xplotter_layout", + "proc_history", + "gantry_angle", +) + + +def _empty_info(sfreq): + """Create an empty info dictionary.""" + _none_keys = ( + "acq_pars", + "acq_stim", + "ctf_head_t", + "description", + "dev_head_t", + "dev_ctf_t", + "dig", + "experimenter", + "utc_offset", + "device_info", + "file_id", + "highpass", + "hpi_subsystem", + "kit_system_id", + "helium_info", + "line_freq", + "lowpass", + "meas_date", + "meas_id", + "proj_id", + "proj_name", + "subject_info", + "xplotter_layout", + "gantry_angle", + ) + _list_keys = ( + "bads", + "chs", + "comps", + "events", + "hpi_meas", + "hpi_results", + "projs", + "proc_history", + ) + info = Info() + info._unlocked = True + for k in _none_keys: + info[k] = None + for k in _list_keys: + info[k] = list() + info["custom_ref_applied"] = FIFF.FIFFV_MNE_CUSTOM_REF_OFF + info["highpass"] = 0.0 + info["sfreq"] = float(sfreq) + info["lowpass"] = info["sfreq"] / 2.0 + info._update_redundant() + info._check_consistency() + return info + + +def _force_update_info(info_base, info_target): + """Update target info objects with values from info base. + + Note that values in info_target will be overwritten by those in info_base. + This will overwrite all fields except for: 'chs', 'ch_names', 'nchan'. + + Parameters + ---------- + info_base : mne.Info + The Info object you want to use for overwriting values + in target Info objects. + info_target : mne.Info | list of mne.Info + The Info object(s) you wish to overwrite using info_base. These objects + will be modified in-place. + """ + exclude_keys = ["chs", "ch_names", "nchan", "bads"] + info_target = np.atleast_1d(info_target).ravel() + all_infos = np.hstack([info_base, info_target]) + for ii in all_infos: + if not isinstance(ii, Info): + raise ValueError(f"Inputs must be of type Info. Found type {type(ii)}") + for key, val in info_base.items(): + if key in exclude_keys: + continue + for i_targ in info_target: + with i_targ._unlock(): + i_targ[key] = val + + +def _add_timedelta_to_stamp(meas_date_stamp, delta_t): + """Add a timedelta to a meas_date tuple.""" + if meas_date_stamp is not None: + meas_date_stamp = _dt_to_stamp(_stamp_to_dt(meas_date_stamp) + delta_t) + return meas_date_stamp + + +@verbose +def anonymize_info(info, daysback=None, keep_his=False, verbose=None): + """Anonymize measurement information in place. + + .. warning:: If ``info`` is part of an object like + :class:`raw.info `, you should directly use + the method :meth:`raw.anonymize() ` + to ensure that all parts of the data are anonymized and + stay synchronized (e.g., + :class:`raw.annotations `). + + Parameters + ---------- + %(info_not_none)s + %(daysback_anonymize_info)s + %(keep_his_anonymize_info)s + %(verbose)s + + Returns + ------- + info : instance of Info + The anonymized measurement information. + + Notes + ----- + %(anonymize_info_notes)s + """ + _validate_type(info, "info", "self") + + valid_fields = {"his_id", "sex", "hand"} + if isinstance(keep_his, bool): # True means keep all fields, False means keep none + keep_fields = valid_fields if keep_his else set() + elif isinstance(keep_his, str): + _check_option("keep_his", keep_his, valid_fields) + keep_fields = {keep_his} + else: + _validate_type(keep_his, (list, tuple, set), "keep_his") + keep_fields = set(keep_his) + for field in keep_fields: + _check_option("keep_his", field, valid_fields) + + default_anon_dos = datetime.datetime( + 2000, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc + ) + default_str = "mne_anonymize" + default_subject_id = 0 + default_sex = 0 + default_desc = "Anonymized using a time shift to preserve age at acquisition" + + none_meas_date = info["meas_date"] is None + + if none_meas_date: + if daysback is not None: + warn( + 'Input info has "meas_date" set to None. ' + "Removing all information from time/date structures, " + "*NOT* performing any time shifts!" + ) + else: + # compute timeshift delta + if daysback is None: + delta_t = info["meas_date"] - default_anon_dos + else: + delta_t = datetime.timedelta(days=daysback) + with info._unlock(): + info["meas_date"] = info["meas_date"] - delta_t + + # file_id and meas_id + for key in ("file_id", "meas_id"): + value = info.get(key) + if value is not None: + assert "msecs" not in value + if none_meas_date or ((value["secs"], value["usecs"]) == DATE_NONE): + # Don't try to shift backwards in time when no measurement + # date is available or when file_id is already a place holder + tmp = DATE_NONE + else: + tmp = _add_timedelta_to_stamp((value["secs"], value["usecs"]), -delta_t) + value["secs"] = tmp[0] + value["usecs"] = tmp[1] + # The following copy is needed for a test CTF dataset + # otherwise value['machid'][:] = 0 would suffice + _tmp = value["machid"].copy() + _tmp[:] = 0 + value["machid"] = _tmp + + # subject info + subject_info = info.get("subject_info") + if subject_info is not None: + if subject_info.get("id") is not None: + subject_info["id"] = default_subject_id + if keep_fields: + logger.info( + f"Not fully anonymizing info - keeping {', '.join(sorted(keep_fields))}" + " of subject_info" + ) + if "his_id" not in keep_fields: + if subject_info.get("his_id") is not None: + subject_info["his_id"] = str(default_subject_id) + if "sex" not in keep_fields: + if subject_info.get("sex") is not None: + subject_info["sex"] = default_sex + if "hand" not in keep_fields: + subject_info.pop("hand", None) # there's no "unknown" setting + + for key in ("last_name", "first_name", "middle_name"): + if subject_info.get(key) is not None: + subject_info[key] = default_str + + # anonymize the subject birthday + if none_meas_date: + subject_info.pop("birthday", None) + elif subject_info.get("birthday") is not None: + subject_info["birthday"] = subject_info["birthday"] - delta_t + + for key in ("weight", "height"): + if subject_info.get(key) is not None: + subject_info[key] = 0 + + info["experimenter"] = default_str + info["description"] = default_desc + with info._unlock(): + if info["proj_id"] is not None: + info["proj_id"] = 0 + if info["proj_name"] is not None: + info["proj_name"] = default_str + if info["utc_offset"] is not None: + info["utc_offset"] = None + + proc_hist = info.get("proc_history") + if proc_hist is not None: + for record in proc_hist: + record["block_id"]["machid"][:] = 0 + record["experimenter"] = default_str + if none_meas_date: + record["block_id"]["secs"] = DATE_NONE[0] + record["block_id"]["usecs"] = DATE_NONE[1] + record["date"] = DATE_NONE + else: + this_t0 = (record["block_id"]["secs"], record["block_id"]["usecs"]) + this_t1 = _add_timedelta_to_stamp(this_t0, -delta_t) + record["block_id"]["secs"] = this_t1[0] + record["block_id"]["usecs"] = this_t1[1] + record["date"] = _add_timedelta_to_stamp(record["date"], -delta_t) + + hi = info.get("helium_info") + if hi is not None: + if hi.get("orig_file_guid") is not None: + hi["orig_file_guid"] = default_str + if none_meas_date and hi.get("meas_date") is not None: + hi["meas_date"] = _ensure_meas_date_none_or_dt(DATE_NONE) + elif hi.get("meas_date") is not None: + hi["meas_date"] = hi["meas_date"] - delta_t + + di = info.get("device_info") + if di is not None: + for k in ("serial", "site"): + if di.get(k) is not None: + di[k] = default_str + + err_mesg = ( + "anonymize_info generated an inconsistent info object. Underlying Error:\n" + ) + info._check_consistency(prepend_error=err_mesg) + err_mesg = ( + "anonymize_info generated an inconsistent info object. " + "daysback parameter was too large. " + "Underlying Error:\n" + ) + _check_dates(info, prepend_error=err_mesg) + + return info + + +@fill_doc +def _bad_chans_comp(info, ch_names): + """Check if channel names are consistent with current compensation status. + + Parameters + ---------- + %(info_not_none)s + + ch_names : list of str + The channel names to check. + + Returns + ------- + status : bool + True if compensation is *currently* in use but some compensation + channels are not included in picks + + False if compensation is *currently* not being used + or if compensation is being used and all compensation channels + in info and included in picks. + + missing_ch_names: array-like of str, shape (n_missing,) + The names of compensation channels not included in picks. + Returns [] if no channels are missing. + + """ + if "comps" not in info: + # should this be thought of as a bug? + return False, [] + + # only include compensation channels that would affect selected channels + ch_names_s = set(ch_names) + comp_names = [] + for comp in info["comps"]: + if len(ch_names_s.intersection(comp["data"]["row_names"])) > 0: + comp_names.extend(comp["data"]["col_names"]) + comp_names = sorted(set(comp_names)) + + missing_ch_names = sorted(set(comp_names).difference(ch_names)) + + if get_current_comp(info) != 0 and len(missing_ch_names) > 0: + return True, missing_ch_names + + return False, missing_ch_names + + +_DIG_CAST = dict(kind=int, ident=int, r=lambda x: x, coord_frame=int) +# key -> const, cast, write +_CH_INFO_MAP = OrderedDict( + scanno=(FIFF.FIFF_CH_SCAN_NO, _int_item, write_int), + logno=(FIFF.FIFF_CH_LOGICAL_NO, _int_item, write_int), + kind=(FIFF.FIFF_CH_KIND, _int_item, write_int), + range=(FIFF.FIFF_CH_RANGE, _float_item, write_float), + cal=(FIFF.FIFF_CH_CAL, _float_item, write_float), + coil_type=(FIFF.FIFF_CH_COIL_TYPE, _int_item, write_int), + loc=(FIFF.FIFF_CH_LOC, lambda x: x, write_float), + unit=(FIFF.FIFF_CH_UNIT, _int_item, write_int), + unit_mul=(FIFF.FIFF_CH_UNIT_MUL, _int_item, write_int), + ch_name=(FIFF.FIFF_CH_DACQ_NAME, str, write_string), + coord_frame=(FIFF.FIFF_CH_COORD_FRAME, _int_item, write_int), +) +# key -> cast +_CH_CAST = OrderedDict((key, val[1]) for key, val in _CH_INFO_MAP.items()) +# const -> key, cast +_CH_READ_MAP = OrderedDict((val[0], (key, val[1])) for key, val in _CH_INFO_MAP.items()) + + +@contextlib.contextmanager +def _writing_info_hdf5(info): + # Make info writing faster by packing chs and dig into numpy arrays + orig_dig = info.get("dig", None) + orig_chs = info["chs"] + with info._unlock(): + try: + if orig_dig is not None and len(orig_dig) > 0: + info["dig"] = _dict_pack(info["dig"], _DIG_CAST) + info["chs"] = _dict_pack(info["chs"], _CH_CAST) + info["chs"]["ch_name"] = np.char.encode( + info["chs"]["ch_name"], encoding="utf8" + ) + yield + finally: + if orig_dig is not None: + info["dig"] = orig_dig + info["chs"] = orig_chs + + +def _dict_pack(obj, casts): + # pack a list of dict into dict of array + return {key: np.array([o[key] for o in obj]) for key in casts} + + +def _dict_unpack(obj, casts): + # unpack a dict of array into a list of dict + n = len(obj[list(casts)[0]]) + return [{key: cast(obj[key][ii]) for key, cast in casts.items()} for ii in range(n)] + + +def _make_ch_names_mapping(chs): + orig_ch_names = [c["ch_name"] for c in chs] + ch_names = orig_ch_names.copy() + _unique_channel_names(ch_names, max_length=15, verbose="error") + ch_names_mapping = dict() + if orig_ch_names != ch_names: + ch_names_mapping.update(zip(orig_ch_names, ch_names)) + return ch_names_mapping + + +def _write_ch_infos(fid, chs, reset_range, ch_names_mapping): + ch_names_mapping = dict() if ch_names_mapping is None else ch_names_mapping + for k, c in enumerate(chs): + # Scan numbers may have been messed up + c = c.copy() + c["ch_name"] = ch_names_mapping.get(c["ch_name"], c["ch_name"]) + assert len(c["ch_name"]) <= 15 + c["scanno"] = k + 1 + # for float/double, the "range" param is unnecessary + if reset_range: + c["range"] = 1.0 + write_ch_info(fid, c) + # only write new-style channel information if necessary + if len(ch_names_mapping): + logger.info( + " Writing channel names to FIF truncated to 15 characters with remapping" + ) + for ch in chs: + start_block(fid, FIFF.FIFFB_CH_INFO) + assert set(ch) == set(_CH_INFO_MAP) + for key, (const, _, write) in _CH_INFO_MAP.items(): + write(fid, const, ch[key]) + end_block(fid, FIFF.FIFFB_CH_INFO) + + +def _ensure_infos_match(info1, info2, name, *, on_mismatch="raise"): + """Check if infos match. + + Parameters + ---------- + info1, info2 : instance of Info + The infos to compare. + name : str + The name of the object appearing in the error message of the comparison + fails. + on_mismatch : 'raise' | 'warn' | 'ignore' + What to do in case of a mismatch of ``dev_head_t`` between ``info1`` + and ``info2``. + """ + _check_on_missing(on_missing=on_mismatch, name="on_mismatch") + + info1._check_consistency() + info2._check_consistency() + + if info1["nchan"] != info2["nchan"]: + raise ValueError(f"{name}.info['nchan'] must match") + if set(info1["bads"]) != set(info2["bads"]): + raise ValueError(f"{name}.info['bads'] must match") + if info1["sfreq"] != info2["sfreq"]: + raise ValueError(f"{name}.info['sfreq'] must match") + if set(info1["ch_names"]) != set(info2["ch_names"]): + raise ValueError(f"{name}.info['ch_names'] must match") + if info1["ch_names"] != info2["ch_names"]: + msg = ( + f"{name}.info['ch_names']: Channel order must match. Use " + '"mne.match_channel_orders()" to sort channels.' + ) + raise ValueError(msg) + if len(info2["projs"]) != len(info1["projs"]): + raise ValueError(f"SSP projectors in {name} must be the same") + if any(not _proj_equal(p1, p2) for p1, p2 in zip(info2["projs"], info1["projs"])): + raise ValueError(f"SSP projectors in {name} must be the same") + if (info1["dev_head_t"] is None) ^ (info2["dev_head_t"] is None) or ( + info1["dev_head_t"] is not None + and not np.allclose( + info1["dev_head_t"]["trans"], + info2["dev_head_t"]["trans"], + rtol=1e-6, + equal_nan=True, + ) + ): + msg = ( + f"{name}.info['dev_head_t'] differs. The " + f"instances probably come from different runs, and " + f"are therefore associated with different head " + f"positions. Manually change info['dev_head_t'] to " + f"avoid this message but beware that this means the " + f"MEG sensors will not be properly spatially aligned. " + f"See mne.preprocessing.maxwell_filter to realign the " + f"runs to a common head position." + ) + _on_missing(on_missing=on_mismatch, msg=msg, name="on_mismatch") + + +def _get_fnirs_ch_pos(info): + """Return positions of each fNIRS optode. + + fNIRS uses two types of optodes, sources and detectors. + There can be multiple connections between each source + and detector at different wavelengths. This function + returns the location of each source and detector. + """ + from ..preprocessing.nirs import _fnirs_optode_names, _optode_position + + srcs, dets = _fnirs_optode_names(info) + ch_pos = {} + for optode in [*srcs, *dets]: + ch_pos[optode] = _optode_position(info, optode) + return ch_pos + + +def _camel_to_snake(s): + return re.sub(r"(? 0: + dir_tag = read_tag(fid, dirpos) + if dir_tag is None or dir_tag.data is None: + fid.seek(0, 2) # move to end of file + size = fid.tell() + extra = "" if size > dirpos else f" > file size {size}" + warn( + "FIF tag directory missing at the end of the file " + f"(at byte {dirpos}{extra}), possibly corrupted file: {fname}" + ) + else: + directory = dir_tag.data + read_slow = False + if read_slow: + pos = 0 + fid.seek(pos, 0) + directory = list() + while pos is not None: + tag = _read_tag_header(fid, pos) + if tag is None: + break # HACK : to fix file ending with empty tag... + pos = tag.next_pos + directory.append(tag) + + tree, _ = make_dir_tree(fid, directory, indent=1) + + logger.debug("[done]") + + # Back to the beginning + fid.seek(0) + + return fid, tree, directory + + +@verbose +def show_fiff( + fname, + indent=" ", + read_limit=np.inf, + max_str=30, + output=str, + tag=None, + *, + show_bytes=False, + verbose=None, +): + """Show FIFF information. + + This function is similar to mne_show_fiff. + + Parameters + ---------- + fname : path-like + Filename to evaluate. + indent : str + How to indent the lines. + read_limit : int + Max number of bytes of data to read from a tag. Can be np.inf + to always read all data (helps test read completion). + max_str : int + Max number of characters of string representation to print for + each tag's data. + output : type + Either str or list. str is a convenience output for printing. + tag : int | None + Provide information about this tag. If None (default), all information + is shown. + show_bytes : bool + If True (default False), print the byte offsets of each tag. + %(verbose)s + + Returns + ------- + contents : str + The contents of the file. + """ + if output not in [list, str]: + raise ValueError("output must be list or str") + if isinstance(tag, str): # command mne show_fiff passes string + tag = int(tag) + fname = _check_fname(fname, "read", True) + f, tree, _ = fiff_open(fname) + # This gets set to 0 (unknown) by fiff_open, but FIFFB_ROOT probably + # makes more sense for display + tree["block"] = FIFF.FIFFB_ROOT + with f as fid: + out = _show_tree( + fid, + tree, + indent=indent, + level=0, + read_limit=read_limit, + max_str=max_str, + tag_id=tag, + show_bytes=show_bytes, + ) + if output is str: + out = "\n".join(out) + return out + + +def _find_type(value, fmts=("FIFF_",), exclude=("FIFF_UNIT",)): + """Find matching values.""" + value = int(value) + vals = [ + k + for k, v in FIFF.items() + if v == value + and any(fmt in k for fmt in fmts) + and not any(exc in k for exc in exclude) + ] + if len(vals) == 0: + vals = ["???"] + return vals + + +def _show_tree( + fid, + tree, + indent, + level, + read_limit, + max_str, + tag_id, + *, + show_bytes=False, +): + """Show FIFF tree.""" + this_idt = indent * level + next_idt = indent * (level + 1) + # print block-level information + found_types = "/".join(_find_type(tree["block"], fmts=["FIFFB_"])) + out = [f"{this_idt}{str(int(tree['block'])).ljust(4)} = {found_types}"] + tag_found = False + if tag_id is None or out[0].strip().startswith(str(tag_id)): + tag_found = True + + if tree["directory"] is not None: + kinds = [ent.kind for ent in tree["directory"]] + [-1] + types = [ent.type for ent in tree["directory"]] + sizes = [ent.size for ent in tree["directory"]] + poss = [ent.pos for ent in tree["directory"]] + counter = 0 + good = True + for k, kn, size, pos, type_ in zip(kinds[:-1], kinds[1:], sizes, poss, types): + if not tag_found and k != tag_id: + continue + tag = Tag(kind=k, type=type_, size=size, next=FIFF.FIFFV_NEXT_NONE, pos=pos) + if read_limit is None or size <= read_limit: + try: + tag = read_tag(fid, pos) + except Exception: + good = False + + if kn == k: + # don't print if the next item is the same type (count 'em) + counter += 1 + else: + if show_bytes: + at = f" @{pos}" + else: + at = "" + # find the tag type + this_type = _find_type(k, fmts=["FIFF_"]) + # prepend a count if necessary + prepend = "x" + str(counter + 1) + ": " if counter > 0 else "" + postpend = "" + # print tag data nicely + if tag.data is not None: + postpend = " = " + str(tag.data)[:max_str] + if isinstance(tag.data, np.ndarray): + if tag.data.size > 1: + postpend += " ... array size=" + str(tag.data.size) + elif isinstance(tag.data, dict): + postpend += " ... dict len=" + str(len(tag.data)) + elif isinstance(tag.data, str): + postpend += " ... str len=" + str(len(tag.data)) + elif isinstance(tag.data, list | tuple): + postpend += " ... list len=" + str(len(tag.data)) + elif issparse(tag.data): + postpend += ( + f" ... sparse ({tag.data.__class__.__name__}) shape=" + f"{tag.data.shape}" + ) + else: + postpend += " ... type=" + str(type(tag.data)) + postpend = ">" * 20 + f"BAD @{pos}" if not good else postpend + matrix_info = _matrix_info(tag) + if matrix_info is not None: + _, type_, _, _ = matrix_info + type_ = _call_dict_names.get(type_, f"?{type_}?") + this_type = "/".join(this_type) + out += [ + f"{next_idt}{prepend}{str(k).ljust(4)} = " + f"{this_type}{at} ({size}b {type_}) {postpend}" + ] + out[-1] = out[-1].replace("\n", "¶") + counter = 0 + good = True + if tag_id in kinds: + tag_found = True + if not tag_found: + out = [""] + level = -1 # removes extra indent + # deal with children + for branch in tree["children"]: + out += _show_tree( + fid, + branch, + indent, + level + 1, + read_limit, + max_str, + tag_id, + show_bytes=show_bytes, + ) + return out diff --git a/mne-python/source/mne/_fiff/pick.py b/mne-python/source/mne/_fiff/pick.py new file mode 100644 index 0000000000000000000000000000000000000000..e007100dae1dc8f6ce5f7b2a78bc79e8c16c399d --- /dev/null +++ b/mne-python/source/mne/_fiff/pick.py @@ -0,0 +1,1418 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import re +from copy import deepcopy + +import numpy as np + +from ..utils import ( + _check_option, + _ensure_int, + _validate_type, + fill_doc, + logger, + verbose, +) +from .constants import FIFF + + +def get_channel_type_constants(include_defaults=False): + """Return all known channel types, and associated FIFF constants. + + Parameters + ---------- + include_defaults : bool + Whether to include default values for "unit" and "coil_type" for all + entries (see Notes). Defaults are generally based on values normally + present for a VectorView MEG system. Defaults to ``False``. + + Returns + ------- + channel_types : dict + The keys are channel type strings, and the values are dictionaries of + FIFF constants for "kind", and possibly "unit" and "coil_type". + + Notes + ----- + Values which might vary within a channel type across real data + recordings are excluded unless ``include_defaults=True``. For example, + "ref_meg" channels may have coil type + ``FIFFV_COIL_MAGNES_OFFDIAG_REF_GRAD``, ``FIFFV_COIL_VV_MAG_T3``, etc + (depending on the recording system), so no "coil_type" entry is given + for "ref_meg" unless ``include_defaults`` is requested. + """ + base = dict( + grad=dict(kind=FIFF.FIFFV_MEG_CH, unit=FIFF.FIFF_UNIT_T_M), + mag=dict(kind=FIFF.FIFFV_MEG_CH, unit=FIFF.FIFF_UNIT_T), + ref_meg=dict(kind=FIFF.FIFFV_REF_MEG_CH), + eeg=dict( + kind=FIFF.FIFFV_EEG_CH, unit=FIFF.FIFF_UNIT_V, coil_type=FIFF.FIFFV_COIL_EEG + ), + seeg=dict( + kind=FIFF.FIFFV_SEEG_CH, + unit=FIFF.FIFF_UNIT_V, + coil_type=FIFF.FIFFV_COIL_EEG, + ), + dbs=dict( + kind=FIFF.FIFFV_DBS_CH, unit=FIFF.FIFF_UNIT_V, coil_type=FIFF.FIFFV_COIL_EEG + ), + ecog=dict( + kind=FIFF.FIFFV_ECOG_CH, + unit=FIFF.FIFF_UNIT_V, + coil_type=FIFF.FIFFV_COIL_EEG, + ), + eog=dict(kind=FIFF.FIFFV_EOG_CH, unit=FIFF.FIFF_UNIT_V), + emg=dict(kind=FIFF.FIFFV_EMG_CH, unit=FIFF.FIFF_UNIT_V), + ecg=dict(kind=FIFF.FIFFV_ECG_CH, unit=FIFF.FIFF_UNIT_V), + resp=dict(kind=FIFF.FIFFV_RESP_CH, unit=FIFF.FIFF_UNIT_V), + bio=dict(kind=FIFF.FIFFV_BIO_CH, unit=FIFF.FIFF_UNIT_V), + misc=dict(kind=FIFF.FIFFV_MISC_CH, unit=FIFF.FIFF_UNIT_V), + stim=dict(kind=FIFF.FIFFV_STIM_CH), + exci=dict(kind=FIFF.FIFFV_EXCI_CH), + syst=dict(kind=FIFF.FIFFV_SYST_CH), + ias=dict(kind=FIFF.FIFFV_IAS_CH), + gof=dict(kind=FIFF.FIFFV_GOODNESS_FIT), + dipole=dict(kind=FIFF.FIFFV_DIPOLE_WAVE), + chpi=dict( + kind=[ + FIFF.FIFFV_QUAT_0, + FIFF.FIFFV_QUAT_1, + FIFF.FIFFV_QUAT_2, + FIFF.FIFFV_QUAT_3, + FIFF.FIFFV_QUAT_4, + FIFF.FIFFV_QUAT_5, + FIFF.FIFFV_QUAT_6, + FIFF.FIFFV_HPI_G, + FIFF.FIFFV_HPI_ERR, + FIFF.FIFFV_HPI_MOV, + ] + ), + fnirs_cw_amplitude=dict( + kind=FIFF.FIFFV_FNIRS_CH, + unit=FIFF.FIFF_UNIT_V, + coil_type=FIFF.FIFFV_COIL_FNIRS_CW_AMPLITUDE, + ), + fnirs_fd_ac_amplitude=dict( + kind=FIFF.FIFFV_FNIRS_CH, + unit=FIFF.FIFF_UNIT_V, + coil_type=FIFF.FIFFV_COIL_FNIRS_FD_AC_AMPLITUDE, + ), + fnirs_fd_phase=dict( + kind=FIFF.FIFFV_FNIRS_CH, + unit=FIFF.FIFF_UNIT_RAD, + coil_type=FIFF.FIFFV_COIL_FNIRS_FD_PHASE, + ), + fnirs_od=dict(kind=FIFF.FIFFV_FNIRS_CH, coil_type=FIFF.FIFFV_COIL_FNIRS_OD), + hbo=dict( + kind=FIFF.FIFFV_FNIRS_CH, + unit=FIFF.FIFF_UNIT_MOL, + coil_type=FIFF.FIFFV_COIL_FNIRS_HBO, + ), + hbr=dict( + kind=FIFF.FIFFV_FNIRS_CH, + unit=FIFF.FIFF_UNIT_MOL, + coil_type=FIFF.FIFFV_COIL_FNIRS_HBR, + ), + csd=dict( + kind=FIFF.FIFFV_EEG_CH, + unit=FIFF.FIFF_UNIT_V_M2, + coil_type=FIFF.FIFFV_COIL_EEG_CSD, + ), + temperature=dict(kind=FIFF.FIFFV_TEMPERATURE_CH, unit=FIFF.FIFF_UNIT_CEL), + gsr=dict(kind=FIFF.FIFFV_GALVANIC_CH, unit=FIFF.FIFF_UNIT_S), + eyegaze=dict( + kind=FIFF.FIFFV_EYETRACK_CH, coil_type=FIFF.FIFFV_COIL_EYETRACK_POS + ), + pupil=dict( + kind=FIFF.FIFFV_EYETRACK_CH, coil_type=FIFF.FIFFV_COIL_EYETRACK_PUPIL + ), + ) + if include_defaults: + coil_none = dict(coil_type=FIFF.FIFFV_COIL_NONE) + unit_none = dict(unit=FIFF.FIFF_UNIT_NONE) + defaults = dict( + grad=dict(coil_type=FIFF.FIFFV_COIL_VV_PLANAR_T1), + mag=dict(coil_type=FIFF.FIFFV_COIL_VV_MAG_T3), + ref_meg=dict(coil_type=FIFF.FIFFV_COIL_VV_MAG_T3, unit=FIFF.FIFF_UNIT_T), + misc=dict(**coil_none, **unit_none), # NB: overwrites UNIT_V + stim=dict(unit=FIFF.FIFF_UNIT_V, **coil_none), + eog=coil_none, + ecg=coil_none, + emg=coil_none, + bio=coil_none, + fnirs_od=unit_none, + pupil=unit_none, + eyegaze=dict(unit=FIFF.FIFF_UNIT_PX), + ) + for key, value in defaults.items(): + base[key].update(value) + return base + + +_first_rule = { + FIFF.FIFFV_MEG_CH: "meg", + FIFF.FIFFV_REF_MEG_CH: "ref_meg", + FIFF.FIFFV_EEG_CH: "eeg", + FIFF.FIFFV_STIM_CH: "stim", + FIFF.FIFFV_EOG_CH: "eog", + FIFF.FIFFV_EMG_CH: "emg", + FIFF.FIFFV_ECG_CH: "ecg", + FIFF.FIFFV_RESP_CH: "resp", + FIFF.FIFFV_MISC_CH: "misc", + FIFF.FIFFV_EXCI_CH: "exci", + FIFF.FIFFV_IAS_CH: "ias", + FIFF.FIFFV_SYST_CH: "syst", + FIFF.FIFFV_SEEG_CH: "seeg", + FIFF.FIFFV_DBS_CH: "dbs", + FIFF.FIFFV_BIO_CH: "bio", + FIFF.FIFFV_QUAT_0: "chpi", + FIFF.FIFFV_QUAT_1: "chpi", + FIFF.FIFFV_QUAT_2: "chpi", + FIFF.FIFFV_QUAT_3: "chpi", + FIFF.FIFFV_QUAT_4: "chpi", + FIFF.FIFFV_QUAT_5: "chpi", + FIFF.FIFFV_QUAT_6: "chpi", + FIFF.FIFFV_HPI_G: "chpi", + FIFF.FIFFV_HPI_ERR: "chpi", + FIFF.FIFFV_HPI_MOV: "chpi", + FIFF.FIFFV_DIPOLE_WAVE: "dipole", + FIFF.FIFFV_GOODNESS_FIT: "gof", + FIFF.FIFFV_ECOG_CH: "ecog", + FIFF.FIFFV_FNIRS_CH: "fnirs", + FIFF.FIFFV_TEMPERATURE_CH: "temperature", + FIFF.FIFFV_GALVANIC_CH: "gsr", + FIFF.FIFFV_EYETRACK_CH: "eyetrack", +} +# How to reduce our categories in channel_type (originally) +_second_rules = { + "meg": ("unit", {FIFF.FIFF_UNIT_T_M: "grad", FIFF.FIFF_UNIT_T: "mag"}), + "fnirs": ( + "coil_type", + { + FIFF.FIFFV_COIL_FNIRS_HBO: "hbo", + FIFF.FIFFV_COIL_FNIRS_HBR: "hbr", + FIFF.FIFFV_COIL_FNIRS_CW_AMPLITUDE: "fnirs_cw_amplitude", + FIFF.FIFFV_COIL_FNIRS_FD_AC_AMPLITUDE: "fnirs_fd_ac_amplitude", + FIFF.FIFFV_COIL_FNIRS_FD_PHASE: "fnirs_fd_phase", + FIFF.FIFFV_COIL_FNIRS_OD: "fnirs_od", + }, + ), + "eeg": ( + "coil_type", + { + FIFF.FIFFV_COIL_EEG: "eeg", + FIFF.FIFFV_COIL_EEG_BIPOLAR: "eeg", + FIFF.FIFFV_COIL_NONE: "eeg", # MNE-C backward compat + FIFF.FIFFV_COIL_EEG_CSD: "csd", + }, + ), + "eyetrack": ( + "coil_type", + { + FIFF.FIFFV_COIL_EYETRACK_POS: "eyegaze", + FIFF.FIFFV_COIL_EYETRACK_PUPIL: "pupil", + }, + ), +} + + +@fill_doc +def channel_type(info, idx): + """Get channel type. + + Parameters + ---------- + %(info_not_none)s + idx : int + Index of channel. + + Returns + ------- + type : str + Type of channel. Will be one of:: + + {'bio', 'chpi', 'dbs', 'dipole', 'ecg', 'ecog', 'eeg', 'emg', + 'eog', 'exci', 'eyetrack', 'fnirs', 'gof', 'gsr', 'ias', 'misc', + 'meg', 'ref_meg', 'resp', 'seeg', 'stim', 'syst', 'temperature'} + """ + # This is faster than the original _channel_type_old now in test_pick.py + # because it uses (at most!) two dict lookups plus one conditional + # to get the channel type string. + ch = info["chs"][idx] + try: + first_kind = _first_rule[ch["kind"]] + except KeyError: + raise ValueError( + f'Unknown channel type ({ch["kind"]}) for channel "{ch["ch_name"]}"' + ) + if first_kind in _second_rules: + key, second_rule = _second_rules[first_kind] + first_kind = second_rule[ch[key]] + return first_kind + + +@verbose +def pick_channels(ch_names, include, exclude=(), ordered=True, *, verbose=None): + """Pick channels by names. + + Returns the indices of ``ch_names`` in ``include`` but not in ``exclude``. + + Parameters + ---------- + ch_names : list of str + List of channels. + include : list of str + List of channels to include (if empty include all available). + + .. note:: This is to be treated as a set. The order of this list + is not used or maintained in ``sel``. + + exclude : list of str + List of channels to exclude (if empty do not exclude any channel). + Defaults to []. + %(ordered)s + %(verbose)s + + Returns + ------- + sel : array of int + Indices of good channels. + + See Also + -------- + pick_channels_regexp, pick_types + """ + if len(np.unique(ch_names)) != len(ch_names): + raise RuntimeError("ch_names is not a unique list, picking is unsafe") + _validate_type(ordered, bool, "ordered") + _check_excludes_includes(include) + _check_excludes_includes(exclude) + if not isinstance(include, list): + include = list(include) + if len(include) == 0: + include = list(ch_names) + if not isinstance(exclude, list): + exclude = list(exclude) + sel, missing = list(), list() + for name in include: + if name in ch_names: + if name not in exclude: + sel.append(ch_names.index(name)) + else: + missing.append(name) + if len(missing) and ordered: + raise ValueError( + f"Missing channels from ch_names required by include:\n{missing}" + ) + if not ordered: + sel = np.unique(sel) + return np.array(sel, int) + + +def pick_channels_regexp(ch_names, regexp): + """Pick channels using regular expression. + + Returns the indices of the good channels in ch_names. + + Parameters + ---------- + ch_names : list of str + List of channels. + + regexp : str + The regular expression. See python standard module for regular + expressions. + + Returns + ------- + sel : array of int + Indices of good channels. + + See Also + -------- + pick_channels + + Examples + -------- + >>> pick_channels_regexp(['MEG 2331', 'MEG 2332', 'MEG 2333'], 'MEG ...1') + [0] + >>> pick_channels_regexp(['MEG 2331', 'MEG 2332', 'MEG 2333'], 'MEG *') + [0, 1, 2] + """ + r = re.compile(regexp) + return [k for k, name in enumerate(ch_names) if r.match(name)] + + +def _triage_meg_pick(ch, meg): + """Triage an MEG pick type.""" + if meg is True: + return True + elif ch["unit"] == FIFF.FIFF_UNIT_T_M: + if meg == "grad": + return True + elif meg == "planar1" and ch["ch_name"].endswith("2"): + return True + elif meg == "planar2" and ch["ch_name"].endswith("3"): + return True + elif meg == "mag" and ch["unit"] == FIFF.FIFF_UNIT_T: + return True + return False + + +def _triage_fnirs_pick(ch, fnirs, warned): + """Triage an fNIRS pick type.""" + if fnirs is True: + return True + elif ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_HBO and "hbo" in fnirs: + return True + elif ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_HBR and "hbr" in fnirs: + return True + elif ( + ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_CW_AMPLITUDE + and "fnirs_cw_amplitude" in fnirs + ): + return True + elif ( + ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_FD_AC_AMPLITUDE + and "fnirs_fd_ac_amplitude" in fnirs + ): + return True + elif ( + ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_FD_PHASE and "fnirs_fd_phase" in fnirs + ): + return True + elif ch["coil_type"] == FIFF.FIFFV_COIL_FNIRS_OD and "fnirs_od" in fnirs: + return True + return False + + +def _triage_eyetrack_pick(ch, eyetrack): + """Triage an eyetrack pick type.""" + if eyetrack is False: + return False + elif eyetrack is True: + return True + elif ch["coil_type"] == FIFF.FIFFV_COIL_EYETRACK_PUPIL and "pupil" in eyetrack: + return True + elif ch["coil_type"] == FIFF.FIFFV_COIL_EYETRACK_POS and "eyegaze" in eyetrack: + return True + return False + + +def _check_meg_type(meg, allow_auto=False): + """Ensure a valid meg type.""" + if isinstance(meg, str): + allowed_types = ["grad", "mag", "planar1", "planar2"] + allowed_types += ["auto"] if allow_auto else [] + if meg not in allowed_types: + raise ValueError( + f"meg value must be one of {allowed_types} or bool, not {meg}" + ) + + +def _check_info_exclude(info, exclude): + _validate_type(info, "info") + info._check_consistency() + if exclude is None: + raise ValueError('exclude must be a list of strings or "bads"') + elif exclude == "bads": + exclude = info.get("bads", []) + elif not isinstance(exclude, list | tuple): + raise ValueError( + 'exclude must either be "bads" or a list of strings.' + " If only one channel is to be excluded, use " + "[ch_name] instead of passing ch_name." + ) + return exclude + + +@fill_doc +def pick_types( + info, + meg=False, + eeg=False, + stim=False, + eog=False, + ecg=False, + emg=False, + ref_meg="auto", + *, + misc=False, + resp=False, + chpi=False, + exci=False, + ias=False, + syst=False, + seeg=False, + dipole=False, + gof=False, + bio=False, + ecog=False, + fnirs=False, + csd=False, + dbs=False, + temperature=False, + gsr=False, + eyetrack=False, + include=(), + exclude="bads", + selection=None, +): + """Pick channels by type and names. + + Parameters + ---------- + %(info_not_none)s + %(pick_types_params)s + + Returns + ------- + sel : array of int + Indices of good channels. + """ + # NOTE: Changes to this function's signature should also be changed in + # PickChannelsMixin + _validate_type(meg, (bool, str), "meg") + + exclude = _check_info_exclude(info, exclude) + nchan = info["nchan"] + pick = np.zeros(nchan, dtype=bool) + + _check_meg_type(ref_meg, allow_auto=True) + _check_meg_type(meg) + if isinstance(ref_meg, str) and ref_meg == "auto": + ref_meg = ( + "comps" in info + and info["comps"] is not None + and len(info["comps"]) > 0 + and meg is not False + ) + + for param in ( + eeg, + stim, + eog, + ecg, + emg, + misc, + resp, + chpi, + exci, + ias, + syst, + seeg, + dipole, + gof, + bio, + ecog, + csd, + dbs, + temperature, + gsr, + ): + if not isinstance(param, bool): + w = ( + "Parameters for all channel types (with the exception of " + '"meg", "ref_meg", "fnirs", and "eyetrack") must be of type ' + "bool, not {}." + ) + raise ValueError(w.format(type(param))) + + param_dict = dict( + eeg=eeg, + stim=stim, + eog=eog, + ecg=ecg, + emg=emg, + misc=misc, + resp=resp, + chpi=chpi, + exci=exci, + ias=ias, + syst=syst, + seeg=seeg, + dbs=dbs, + dipole=dipole, + gof=gof, + bio=bio, + ecog=ecog, + csd=csd, + temperature=temperature, + gsr=gsr, + eyetrack=eyetrack, + ) + + # avoid triage if possible + if isinstance(meg, bool): + for key in ("grad", "mag"): + param_dict[key] = meg + if isinstance(fnirs, bool): + for key in _FNIRS_CH_TYPES_SPLIT: + param_dict[key] = fnirs + warned = [False] + for k in range(nchan): + ch_type = channel_type(info, k) + try: + pick[k] = param_dict[ch_type] + except KeyError: # not so simple + assert ( + ch_type + in ("grad", "mag", "ref_meg") + + _FNIRS_CH_TYPES_SPLIT + + _EYETRACK_CH_TYPES_SPLIT + ) + if ch_type in ("grad", "mag"): + pick[k] = _triage_meg_pick(info["chs"][k], meg) + elif ch_type == "ref_meg": + pick[k] = _triage_meg_pick(info["chs"][k], ref_meg) + elif ch_type in ("eyegaze", "pupil"): + pick[k] = _triage_eyetrack_pick(info["chs"][k], eyetrack) + else: # ch_type in ('hbo', 'hbr') + pick[k] = _triage_fnirs_pick(info["chs"][k], fnirs, warned) + + # restrict channels to selection if provided + if selection is not None: + # the selection only restricts these types of channels + sel_kind = [FIFF.FIFFV_MEG_CH, FIFF.FIFFV_REF_MEG_CH, FIFF.FIFFV_EEG_CH] + for k in np.where(pick)[0]: + if ( + info["chs"][k]["kind"] in sel_kind + and info["ch_names"][k] not in selection + ): + pick[k] = False + + myinclude = [info["ch_names"][k] for k in range(nchan) if pick[k]] + myinclude += include + + if len(myinclude) == 0: + sel = np.array([], int) + else: + sel = pick_channels(info["ch_names"], myinclude, exclude, ordered=False) + + return sel + + +@verbose +def pick_info(info, sel=(), copy=True, verbose=None): + """Restrict an info structure to a selection of channels. + + Parameters + ---------- + %(info_not_none)s + sel : list of int | None + Indices of channels to include. If None, all channels + are included. + copy : bool + If copy is False, info is modified inplace. + %(verbose)s + + Returns + ------- + res : dict + Info structure restricted to a selection of channels. + """ + # avoid circular imports + from .meas_info import _bad_chans_comp + + info._check_consistency() + info = info.copy() if copy else info + if sel is None: + return info + elif len(sel) == 0: + raise ValueError("No channels match the selection.") + ch_set = set(info["ch_names"][k] for k in sel) + n_unique = len(ch_set) + if n_unique != len(sel): + raise ValueError( + f"Found {n_unique} / {len(sel)} unique names, sel is not unique" + ) + + # make sure required the compensation channels are present + if len(info.get("comps", [])) > 0: + ch_names = [info["ch_names"][idx] for idx in sel] + _, comps_missing = _bad_chans_comp(info, ch_names) + if len(comps_missing) > 0: + logger.info( + f"Removing {len(info['comps'])} compensators from info because " + "not all compensation channels were picked." + ) + with info._unlock(): + info["comps"] = [] + with info._unlock(): + info["chs"] = [info["chs"][k] for k in sel] + info._update_redundant() + info["bads"] = [ch for ch in info["bads"] if ch in info["ch_names"]] + if "comps" in info: + comps = deepcopy(info["comps"]) + for c in comps: + row_idx = [ + k for k, n in enumerate(c["data"]["row_names"]) if n in info["ch_names"] + ] + row_names = [c["data"]["row_names"][i] for i in row_idx] + rowcals = c["rowcals"][row_idx] + c["rowcals"] = rowcals + c["data"]["nrow"] = len(row_names) + c["data"]["row_names"] = row_names + c["data"]["data"] = c["data"]["data"][row_idx] + with info._unlock(): + info["comps"] = comps + if info.get("custom_ref_applied", False) and not _electrode_types(info): + with info._unlock(): + info["custom_ref_applied"] = FIFF.FIFFV_MNE_CUSTOM_REF_OFF + # remove unused projectors + if info.get("projs", False): + projs = list() + for p in info["projs"]: + if any(ch_name in ch_set for ch_name in p["data"]["col_names"]): + projs.append(p) + if len(projs) != len(info["projs"]): + with info._unlock(): + info["projs"] = projs + info._check_consistency() + + return info + + +def _has_kit_refs(info, picks): + """Determine if KIT ref channels are chosen. + + This is currently only used by make_forward_solution, which cannot + run when KIT reference channels are included. + """ + for p in picks: + if info["chs"][p]["coil_type"] == FIFF.FIFFV_COIL_KIT_REF_MAG: + return True + return False + + +@verbose +def pick_channels_forward( + orig, include=(), exclude=(), ordered=True, copy=True, *, verbose=None +): + """Pick channels from forward operator. + + Parameters + ---------- + orig : dict + A forward solution. + include : list of str + List of channels to include (if empty, include all available). + Defaults to []. + exclude : list of str | 'bads' + Channels to exclude (if empty, do not exclude any). Defaults to []. + If 'bads', then exclude bad channels in orig. + %(ordered)s + copy : bool + If True (default), make a copy. + + .. versionadded:: 0.19 + %(verbose)s + + Returns + ------- + res : dict + Forward solution restricted to selected channels. If include and + exclude are empty it returns orig without copy. + """ + orig["info"]._check_consistency() + if len(include) == 0 and len(exclude) == 0: + return orig.copy() if copy else orig + exclude = _check_excludes_includes(exclude, info=orig["info"], allow_bads=True) + + # Allow for possibility of channel ordering in forward solution being + # different from that of the M/EEG file it is based on. + sel_sol = pick_channels( + orig["sol"]["row_names"], include=include, exclude=exclude, ordered=ordered + ) + sel_info = pick_channels( + orig["info"]["ch_names"], include=include, exclude=exclude, ordered=ordered + ) + + fwd = deepcopy(orig) if copy else orig + + # Check that forward solution and original data file agree on #channels + if len(sel_sol) != len(sel_info): + raise ValueError( + "Forward solution and functional data appear to " + "have different channel names, please check." + ) + + # Do we have something? + nuse = len(sel_sol) + if nuse == 0: + raise ValueError("Nothing remains after picking") + + logger.info(f" {nuse:d} out of {fwd['nchan']} channels remain after picking") + + # Pick the correct rows of the forward operator using sel_sol + fwd["sol"]["data"] = fwd["sol"]["data"][sel_sol, :] + fwd["_orig_sol"] = fwd["_orig_sol"][sel_sol, :] + fwd["sol"]["nrow"] = nuse + + ch_names = [fwd["sol"]["row_names"][k] for k in sel_sol] + fwd["nchan"] = nuse + fwd["sol"]["row_names"] = ch_names + + # Pick the appropriate channel names from the info-dict using sel_info + with fwd["info"]._unlock(): + fwd["info"]["chs"] = [fwd["info"]["chs"][k] for k in sel_info] + fwd["info"]._update_redundant() + fwd["info"]["bads"] = [b for b in fwd["info"]["bads"] if b in ch_names] + + if fwd["sol_grad"] is not None: + fwd["sol_grad"]["data"] = fwd["sol_grad"]["data"][sel_sol, :] + fwd["_orig_sol_grad"] = fwd["_orig_sol_grad"][sel_sol, :] + fwd["sol_grad"]["nrow"] = nuse + fwd["sol_grad"]["row_names"] = [ + fwd["sol_grad"]["row_names"][k] for k in sel_sol + ] + + return fwd + + +def pick_types_forward( + orig, + meg=False, + eeg=False, + ref_meg=True, + seeg=False, + ecog=False, + dbs=False, + include=(), + exclude=(), +): + """Pick by channel type and names from a forward operator. + + Parameters + ---------- + orig : dict + A forward solution. + meg : bool | str + If True include MEG channels. If string it can be 'mag', 'grad', + 'planar1' or 'planar2' to select only magnetometers, all gradiometers, + or a specific type of gradiometer. + eeg : bool + If True include EEG channels. + ref_meg : bool + If True include CTF / 4D reference channels. + seeg : bool + If True include stereotactic EEG channels. + ecog : bool + If True include electrocorticography channels. + dbs : bool + If True include deep brain stimulation channels. + include : list of str + List of additional channels to include. If empty do not include any. + exclude : list of str | str + List of channels to exclude. If empty do not exclude any (default). + If 'bads', exclude channels in orig['info']['bads']. + + Returns + ------- + res : dict + Forward solution restricted to selected channel types. + """ + info = orig["info"] + sel = pick_types( + info, + meg, + eeg, + ref_meg=ref_meg, + seeg=seeg, + ecog=ecog, + dbs=dbs, + include=include, + exclude=exclude, + ) + if len(sel) == 0: + raise ValueError("No valid channels found") + include_ch_names = [info["ch_names"][k] for k in sel] + + return pick_channels_forward(orig, include_ch_names) + + +@fill_doc +def channel_indices_by_type(info, picks=None, *, exclude=()): + """Get indices of channels by type. + + Parameters + ---------- + %(info_not_none)s + %(picks_all)s + exclude : list | str + Set of channels to exclude, only used when picking based on + types (e.g., exclude="bads" when picks="meg"). + + .. versionadded:: 1.10.0 + + Returns + ------- + idx_by_type : dict + A dictionary that maps each channel type to a (possibly empty) list of + channel indices. + """ + idx_by_type = { + key: list() + for key in _PICK_TYPES_KEYS + if key not in ("meg", "fnirs", "eyetrack") + } + idx_by_type.update( + mag=list(), + grad=list(), + hbo=list(), + hbr=list(), + fnirs_cw_amplitude=list(), + fnirs_fd_ac_amplitude=list(), + fnirs_fd_phase=list(), + fnirs_od=list(), + eyegaze=list(), + pupil=list(), + ) + picks = _picks_to_idx(info, picks, none="all", exclude=exclude, allow_empty=True) + for k in picks: + ch_type = channel_type(info, k) + for key in idx_by_type.keys(): + if ch_type == key: + idx_by_type[key].append(k) + return idx_by_type + + +@verbose +def pick_channels_cov( + orig, include=(), exclude="bads", ordered=True, copy=True, *, verbose=None +): + """Pick channels from covariance matrix. + + Parameters + ---------- + orig : Covariance + A covariance. + include : list of str, (optional) + List of channels to include (if empty, include all available). + exclude : list of str, (optional) | 'bads' + Channels to exclude (if empty, do not exclude any). Defaults to 'bads'. + %(ordered)s + copy : bool + If True (the default), return a copy of the covariance matrix with the + modified channels. If False, channels are modified in-place. + + .. versionadded:: 0.20.0 + %(verbose)s + + Returns + ------- + res : dict + Covariance solution restricted to selected channels. + """ + if copy: + orig = orig.copy() + # A little peculiarity of the cov objects is that these two fields + # should not be copied over when None. + if "method" in orig and orig["method"] is None: + del orig["method"] + if "loglik" in orig and orig["loglik"] is None: + del orig["loglik"] + + exclude = orig["bads"] if exclude == "bads" else exclude + sel = pick_channels( + orig["names"], include=include, exclude=exclude, ordered=ordered + ) + data = orig["data"][sel][:, sel] if not orig["diag"] else orig["data"][sel] + names = [orig["names"][k] for k in sel] + bads = [name for name in orig["bads"] if name in orig["names"]] + + orig["data"] = data + orig["names"] = names + orig["bads"] = bads + orig["dim"] = len(data) + + return orig + + +def _mag_grad_dependent(info): + """Determine of mag and grad should be dealt with jointly.""" + # right now just uses SSS, could be computed / checked from cov + # but probably overkill + return any( + ph.get("max_info", {}).get("sss_info", {}).get("in_order", 0) + for ph in info.get("proc_history", []) + ) + + +@fill_doc +def _contains_ch_type(info, ch_type): + """Check whether a certain channel type is in an info object. + + Parameters + ---------- + %(info_not_none)s + ch_type : str + the channel type to be checked for + + Returns + ------- + has_ch_type : bool + Whether the channel type is present or not. + """ + _validate_type(ch_type, "str", "ch_type") + + meg_extras = list(_MEG_CH_TYPES_SPLIT) + fnirs_extras = list(_FNIRS_CH_TYPES_SPLIT) + et_extras = list(_EYETRACK_CH_TYPES_SPLIT) + valid_channel_types = sorted( + [key for key in _PICK_TYPES_KEYS if key != "meg"] + + meg_extras + + fnirs_extras + + et_extras + ) + _check_option("ch_type", ch_type, valid_channel_types) + if info is None: + raise ValueError( + f'Cannot check for channels of type "{ch_type}" because info is None' + ) + return any(ch_type == channel_type(info, ii) for ii in range(info["nchan"])) + + +@fill_doc +def _picks_by_type(info, meg_combined=False, ref_meg=False, exclude="bads"): + """Get data channel indices as separate list of tuples. + + Parameters + ---------- + %(info_not_none)s + meg_combined : bool | 'auto' + Whether to return combined picks for grad and mag. + Can be 'auto' to choose based on Maxwell filtering status. + ref_meg : bool + If True include CTF / 4D reference channels + exclude : list of str | str + List of channels to exclude. If 'bads' (default), exclude channels + in info['bads']. + + Returns + ------- + picks_list : list of tuples + The list of tuples of picks and the type string. + """ + _validate_type(ref_meg, bool, "ref_meg") + exclude = _check_info_exclude(info, exclude) + if meg_combined == "auto": + meg_combined = _mag_grad_dependent(info) + + picks_list = {ch_type: list() for ch_type in _DATA_CH_TYPES_SPLIT} + for k in range(info["nchan"]): + if info["chs"][k]["ch_name"] not in exclude: + this_type = channel_type(info, k) + try: + picks_list[this_type].append(k) + except KeyError: + # This annoyance is due to differences in pick_types + # and channel_type behavior + if this_type == "ref_meg": + ch = info["chs"][k] + if _triage_meg_pick(ch, ref_meg): + if ch["unit"] == FIFF.FIFF_UNIT_T: + picks_list["mag"].append(k) + elif ch["unit"] == FIFF.FIFF_UNIT_T_M: + picks_list["grad"].append(k) + else: + pass # not a data channel type + picks_list = [ + (ch_type, np.array(picks_list[ch_type], int)) + for ch_type in _DATA_CH_TYPES_SPLIT + ] + assert _DATA_CH_TYPES_SPLIT[:2] == ("mag", "grad") + if meg_combined and len(picks_list[0][1]) and len(picks_list[1][1]): + picks_list.insert( + 0, + ( + "meg", + np.unique(np.concatenate([picks_list.pop(0)[1], picks_list.pop(0)[1]])), + ), + ) + picks_list = [p for p in picks_list if len(p[1])] + return picks_list + + +def _check_excludes_includes(chs, info=None, allow_bads=False): + """Ensure that inputs to exclude/include are list-like or "bads". + + Parameters + ---------- + chs : any input, should be list, tuple, set, str + The channels passed to include or exclude. + allow_bads : bool + Allow the user to supply "bads" as a string for auto exclusion. + + Returns + ------- + chs : list + Channels to be excluded/excluded. If allow_bads, and chs=="bads", + this will be the bad channels found in 'info'. + """ + from .meas_info import Info + + if not isinstance(chs, list | tuple | set | np.ndarray): + if allow_bads is True: + if not isinstance(info, Info): + raise ValueError("Supply an info object if allow_bads is true") + elif chs != "bads": + raise ValueError('If chs is a string, it must be "bads"') + else: + chs = info["bads"] + else: + raise ValueError( + 'include/exclude must be list, tuple, ndarray, or "bads". You provided ' + f"type {type(chs)}." + ) + return chs + + +_PICK_TYPES_DATA_DICT = dict( + meg=True, + eeg=True, + csd=True, + stim=False, + eog=False, + ecg=False, + emg=False, + misc=False, + resp=False, + chpi=False, + exci=False, + ias=False, + syst=False, + seeg=True, + dipole=False, + gof=False, + bio=False, + ecog=True, + fnirs=True, + dbs=True, + temperature=False, + gsr=False, + eyetrack=False, +) +_PICK_TYPES_KEYS = tuple(list(_PICK_TYPES_DATA_DICT) + ["ref_meg"]) +_MEG_CH_TYPES_SPLIT = ("mag", "grad", "planar1", "planar2") +_FNIRS_CH_TYPES_SPLIT = ( + "hbo", + "hbr", + "fnirs_cw_amplitude", + "fnirs_fd_ac_amplitude", + "fnirs_fd_phase", + "fnirs_od", +) +_EYETRACK_CH_TYPES_SPLIT = ("eyegaze", "pupil") +_DATA_CH_TYPES_ORDER_DEFAULT = ( + ( + "mag", + "grad", + "eeg", + "csd", + "eog", + "ecg", + "resp", + "emg", + "ref_meg", + "misc", + "stim", + "chpi", + "exci", + "ias", + "syst", + "seeg", + "bio", + "ecog", + "dbs", + "temperature", + "gsr", + "gof", + "dipole", + ) + + _FNIRS_CH_TYPES_SPLIT + + _EYETRACK_CH_TYPES_SPLIT + + ("whitened",) +) + +# Valid data types, ordered for consistency, used in viz/evoked. +_VALID_CHANNEL_TYPES = ( + ( + "eeg", + "grad", + "mag", + "seeg", + "eog", + "ecg", + "resp", + "emg", + "dipole", + "gof", + "bio", + "ecog", + "dbs", + ) + + _FNIRS_CH_TYPES_SPLIT + + _EYETRACK_CH_TYPES_SPLIT + + ("misc", "csd") +) +_DATA_CH_TYPES_SPLIT = ( + "mag", + "grad", + "eeg", + "csd", + "seeg", + "ecog", + "dbs", +) + _FNIRS_CH_TYPES_SPLIT +# Electrode types (e.g., can be average-referenced together or separately) +_ELECTRODE_CH_TYPES = ("eeg", "ecog", "seeg", "dbs") + + +def _electrode_types(info, *, exclude="bads"): + return [ + ch_type + for ch_type in _ELECTRODE_CH_TYPES + if len(pick_types(info, exclude=exclude, **{ch_type: True})) + ] + + +def _pick_data_channels(info, exclude="bads", with_ref_meg=True, with_aux=False): + """Pick only data channels.""" + kwargs = _PICK_TYPES_DATA_DICT + if with_aux: + kwargs = kwargs.copy() + kwargs.update(eog=True, ecg=True, emg=True, bio=True) + return pick_types(info, ref_meg=with_ref_meg, exclude=exclude, **kwargs) + + +def _pick_data_or_ica(info, exclude=()): + """Pick only data or ICA channels.""" + if any(ch_name.startswith("ICA") for ch_name in info["ch_names"]): + picks = pick_types(info, exclude=exclude, misc=True) + else: + picks = _pick_data_channels(info, exclude=exclude, with_ref_meg=True) + return picks + + +def _picks_to_idx( + info, + picks, + none="data", + exclude="bads", + allow_empty=False, + with_ref_meg=True, + return_kind=False, + picks_on="channels", +): + """Convert and check pick validity. + + Parameters + ---------- + picks_on : str + 'channels' (default) for error messages about selection of channels. + 'components' for error messages about selection of components. + """ + from .meas_info import Info + + picked_ch_type_or_generic = False + # + # None -> all, data, or data_or_ica (ndarray of int) + # + if isinstance(info, Info): + n_chan = info["nchan"] + else: + info = _ensure_int(info, "info", "an int or Info") + n_chan = info + assert n_chan >= 0 + + orig_picks = picks + # We do some extra_repr gymnastics to avoid calling repr(orig_picks) too + # soon as it can be a performance bottleneck (repr on ndarray is slow) + extra_repr = "" + if picks is None: + if isinstance(info, int): # special wrapper for no real info + picks = np.arange(n_chan) + extra_repr = ", treated as range({n_chan})" + else: + picks = none # let _picks_str_to_idx handle it + extra_repr = f'None, treated as "{none}"' + + # + # slice + # + if isinstance(picks, slice): + picks = np.arange(n_chan)[picks] + + # + # -> ndarray of int (and make a copy) + # + picks = np.atleast_1d(picks) # this works even for picks == 'something' + picks = np.array([], dtype=int) if len(picks) == 0 else picks + if picks.ndim != 1: + raise ValueError(f"picks must be 1D, got {picks.ndim}D") + if picks.dtype.char in ("S", "U"): + picks = _picks_str_to_idx( + info, + picks, + exclude, + with_ref_meg, + return_kind, + extra_repr, + allow_empty, + orig_picks, + ) + if return_kind: + picked_ch_type_or_generic = picks[1] + picks = picks[0] + if picks.dtype.kind not in ["i", "u"]: + extra_ch = " or list of str (names)" if picks_on == "channels" else "" + msg = ( + f"picks must be a list of int (indices){extra_ch}. " + f"The provided data type {picks.dtype} is invalid." + ) + raise TypeError(msg) + del extra_repr + picks = picks.astype(int) + + # + # ensure we have (optionally non-empty) ndarray of valid int + # + if len(picks) == 0 and not allow_empty: + raise ValueError( + f"No appropriate {picks_on} found for the given picks ({orig_picks!r})" + ) + if (picks < -n_chan).any(): + raise IndexError(f"All picks must be >= {-n_chan}, got {repr(orig_picks)}") + if (picks >= n_chan).any(): + raise IndexError( + f"All picks must be < n_{picks_on} ({n_chan}), got {repr(orig_picks)}" + ) + picks %= n_chan # ensure positive + if return_kind: + return picks, picked_ch_type_or_generic + return picks + + +def _picks_str_to_idx( + info, picks, exclude, with_ref_meg, return_kind, extra_repr, allow_empty, orig_picks +): + """Turn a list of str into ndarray of int.""" + # special case for _picks_to_idx w/no info: shouldn't really happen + if isinstance(info, int): + raise ValueError( + "picks as str can only be used when measurement info is available" + ) + + # + # first: check our special cases + # + + picks_generic = list() + if len(picks) == 1: + if picks[0] in ("all", "data", "data_or_ica"): + if picks[0] == "all": + use_exclude = info["bads"] if exclude == "bads" else exclude + picks_generic = pick_channels( + info["ch_names"], info["ch_names"], exclude=use_exclude + ) + elif picks[0] == "data": + picks_generic = _pick_data_channels( + info, exclude=exclude, with_ref_meg=with_ref_meg + ) + elif picks[0] == "data_or_ica": + picks_generic = _pick_data_or_ica(info, exclude=exclude) + if len(picks_generic) == 0 and orig_picks is None and not allow_empty: + raise ValueError( + f"picks ({repr(orig_picks) + extra_repr}) yielded no channels, " + "consider passing picks explicitly" + ) + + # + # second: match all to channel names + # + + bad_names = [] + picks_name = list() + for pick in picks: + try: + picks_name.append(info["ch_names"].index(pick)) + except ValueError: + bad_names.append(pick) + + # + # third: match all to types + # + bad_type = None + picks_type = list() + kwargs = dict(meg=False) + meg, fnirs, eyetrack = set(), set(), set() + for pick in picks: + if pick in _PICK_TYPES_KEYS: + kwargs[pick] = True + elif pick in _MEG_CH_TYPES_SPLIT: + meg |= {pick} + elif pick in _FNIRS_CH_TYPES_SPLIT: + fnirs |= {pick} + elif pick in _EYETRACK_CH_TYPES_SPLIT: + eyetrack |= {pick} + else: + bad_type = pick + break + else: + # bad_type is None but this could still be empty + bad_type = list(picks) + # triage MEG, FNIRS, and eyetrack, which are complicated due to non-bool entries + extra_picks = set() + if "ref_meg" not in picks and not with_ref_meg: + kwargs["ref_meg"] = False + if len(meg) > 0 and not kwargs.get("meg", False): + # easiest just to iterate + for use_meg in meg: + extra_picks |= set( + pick_types(info, meg=use_meg, ref_meg=False, exclude=exclude) + ) + if len(fnirs) and not kwargs.get("fnirs", False): + idx = 0 if len(fnirs) == 1 else slice(None) + kwargs["fnirs"] = list(fnirs)[idx] + if len(eyetrack) and not kwargs.get("eyetrack", False): + idx = 0 if len(eyetrack) == 1 else slice(None) + kwargs["eyetrack"] = list(eyetrack)[idx] # slice(None) is equivalent to all + picks_type = pick_types(info, exclude=exclude, **kwargs) + if len(extra_picks) > 0: + picks_type = sorted(set(picks_type) | set(extra_picks)) + + # + # finally: ensure we have exactly one usable list + # + all_picks = (picks_generic, picks_name, picks_type) + any_found = [len(p) > 0 for p in all_picks] + if sum(any_found) == 0: + if not allow_empty: + raise ValueError( + f"picks ({repr(orig_picks) + extra_repr}) could not be interpreted as " + f'channel names (no channel "{bad_names}"), channel types (no type' + f' "{bad_type}" present), or a generic type (just "all" or "data")' + ) + picks = np.array([], int) + elif sum(any_found) > 1: + raise RuntimeError( + "Some channel names are ambiguously equivalent to " + "channel types, cannot use string-based " + "picks for these" + ) + else: + picks = np.array(all_picks[np.where(any_found)[0][0]]) + + picked_ch_type_or_generic = not len(picks_name) + if len(bad_names) > 0 and not picked_ch_type_or_generic: + raise ValueError( + f"Channel(s) {bad_names} could not be picked, because " + "they are not present in the info instance." + ) + + if return_kind: + return picks, picked_ch_type_or_generic + return picks diff --git a/mne-python/source/mne/_fiff/proc_history.py b/mne-python/source/mne/_fiff/proc_history.py new file mode 100644 index 0000000000000000000000000000000000000000..caa2d3de554fdc58871b59afc3d1a43164055031 --- /dev/null +++ b/mne-python/source/mne/_fiff/proc_history.py @@ -0,0 +1,345 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ..fixes import _csc_array_cast +from ..utils import _check_fname, warn +from .constants import FIFF +from .open import fiff_open, read_tag +from .tag import _float_item, _int_item, find_tag +from .tree import dir_tree_find +from .write import ( + _safe_name_list, + end_block, + start_block, + write_float, + write_float_matrix, + write_float_sparse, + write_id, + write_int, + write_int_matrix, + write_name_list_sanitized, + write_string, +) + +_proc_map = dict( # ID, caster, writer + parent_file_id=( + FIFF.FIFF_PARENT_FILE_ID, + dict, + write_id, + ), + block_id=( + FIFF.FIFF_BLOCK_ID, + dict, + write_id, + ), + parent_block_id=( + FIFF.FIFF_PARENT_BLOCK_ID, + dict, + write_id, + ), + date=( + FIFF.FIFF_MEAS_DATE, + lambda d: tuple(int(dd) for dd in d), + write_int, + ), + experimenter=( + FIFF.FIFF_EXPERIMENTER, + str, + write_string, + ), + creator=( + FIFF.FIFF_CREATOR, + str, + write_string, + ), +) + + +def _read_proc_history(fid, tree): + """Read processing history from fiff file. + + This function reads the SSS info, the CTC correction and the + calibaraions from the SSS processing logs inside af a raw file + (C.f. Maxfilter v2.2 manual (October 2010), page 21):: + + 104 = { 900 = proc. history + 104 = { 901 = proc. record + 103 = block ID + 204 = date + 212 = scientist + 113 = creator program + 104 = { 502 = SSS info + 264 = SSS task + 263 = SSS coord frame + 265 = SSS origin + 266 = SSS ins.order + 267 = SSS outs.order + 268 = SSS nr chnls + 269 = SSS components + 278 = SSS nfree + 243 = HPI g limit 0.98 + 244 = HPI dist limit 0.005 + 105 = } 502 = SSS info + 104 = { 504 = MaxST info + 264 = SSS task + 272 = SSST subspace correlation + 279 = SSST buffer length + 105 = } + 104 = { 501 = CTC correction + 103 = block ID + 204 = date + 113 = creator program + 800 = CTC matrix + 3417 = proj item chs + 105 = } 501 = CTC correction + 104 = { 503 = SSS finecalib. + 270 = SSS cal chnls + 271 = SSS cal coeff + 105 = } 503 = SSS finecalib. + 105 = } 901 = proc. record + 105 = } 900 = proc. history + """ + proc_history = dir_tree_find(tree, FIFF.FIFFB_PROCESSING_HISTORY) + out = list() + if len(proc_history) > 0: + proc_history = proc_history[0] + proc_records = dir_tree_find(proc_history, FIFF.FIFFB_PROCESSING_RECORD) + for proc_record in proc_records: + record = dict() + for i_ent in range(proc_record["nent"]): + kind = proc_record["directory"][i_ent].kind + pos = proc_record["directory"][i_ent].pos + for key, (id_, cast, _) in _proc_map.items(): + if kind == id_: + tag = read_tag(fid, pos) + record[key] = cast(tag.data) + break + else: + warn(f"Unknown processing history item {kind}") + record["max_info"] = _read_maxfilter_record(fid, proc_record) + iass = dir_tree_find(proc_record, FIFF.FIFFB_IAS) + if len(iass) > 0: + # XXX should eventually populate this + ss = [dict() for _ in range(len(iass))] + record["ias"] = ss + if len(record["max_info"]) > 0: + out.append(record) + return out + + +def _write_proc_history(fid, info): + """Write processing history to file.""" + if len(info["proc_history"]) > 0: + start_block(fid, FIFF.FIFFB_PROCESSING_HISTORY) + for record in info["proc_history"]: + start_block(fid, FIFF.FIFFB_PROCESSING_RECORD) + for key, (id_, _, writer) in _proc_map.items(): + if key in record: + writer(fid, id_, record[key]) + _write_maxfilter_record(fid, record["max_info"]) + if "ias" in record: + for _ in record["ias"]: + start_block(fid, FIFF.FIFFB_IAS) + # XXX should eventually populate this + end_block(fid, FIFF.FIFFB_IAS) + end_block(fid, FIFF.FIFFB_PROCESSING_RECORD) + end_block(fid, FIFF.FIFFB_PROCESSING_HISTORY) + + +_sss_info_keys = ( + "job", + "frame", + "origin", + "in_order", + "out_order", + "nchan", + "components", + "nfree", + "hpi_g_limit", + "hpi_dist_limit", +) +_sss_info_ids = ( + FIFF.FIFF_SSS_JOB, + FIFF.FIFF_SSS_FRAME, + FIFF.FIFF_SSS_ORIGIN, + FIFF.FIFF_SSS_ORD_IN, + FIFF.FIFF_SSS_ORD_OUT, + FIFF.FIFF_SSS_NMAG, + FIFF.FIFF_SSS_COMPONENTS, + FIFF.FIFF_SSS_NFREE, + FIFF.FIFF_HPI_FIT_GOOD_LIMIT, + FIFF.FIFF_HPI_FIT_DIST_LIMIT, +) +_sss_info_writers = ( + write_int, + write_int, + write_float, + write_int, + write_int, + write_int, + write_int, + write_int, + write_float, + write_float, +) +_sss_info_casters = ( + _int_item, + _int_item, + np.array, + _int_item, + _int_item, + _int_item, + np.array, + _int_item, + _float_item, + _float_item, +) + +_max_st_keys = ("job", "subspcorr", "buflen") +_max_st_ids = (FIFF.FIFF_SSS_JOB, FIFF.FIFF_SSS_ST_CORR, FIFF.FIFF_SSS_ST_LENGTH) +_max_st_writers = (write_int, write_float, write_float) +_max_st_casters = (_int_item, _float_item, _float_item) + +_sss_ctc_keys = ("block_id", "date", "creator", "decoupler") +_sss_ctc_ids = ( + FIFF.FIFF_BLOCK_ID, + FIFF.FIFF_MEAS_DATE, + FIFF.FIFF_CREATOR, + FIFF.FIFF_DECOUPLER_MATRIX, +) +_sss_ctc_writers = (write_id, write_int, write_string, write_float_sparse) +_sss_ctc_casters = (dict, np.array, str, _csc_array_cast) + +_sss_cal_keys = ("cal_chans", "cal_corrs") +_sss_cal_ids = (FIFF.FIFF_SSS_CAL_CHANS, FIFF.FIFF_SSS_CAL_CORRS) +_sss_cal_writers = (write_int_matrix, write_float_matrix) +_sss_cal_casters = (np.array, np.array) + + +def _read_ctc(fname): + """Read cross-talk correction matrix.""" + fname = _check_fname(fname, overwrite="read", must_exist=True) + f, tree, _ = fiff_open(fname) + with f as fid: + sss_ctc = _read_maxfilter_record(fid, tree)["sss_ctc"] + bad_str = f"Invalid cross-talk FIF: {fname}" + if len(sss_ctc) == 0: + raise ValueError(bad_str) + node = dir_tree_find(tree, FIFF.FIFFB_DATA_CORRECTION)[0] + comment = find_tag(fid, node, FIFF.FIFF_COMMENT).data + if comment != "cross-talk compensation matrix": + raise ValueError(bad_str) + sss_ctc["creator"] = find_tag(fid, node, FIFF.FIFF_CREATOR).data + sss_ctc["date"] = find_tag(fid, node, FIFF.FIFF_MEAS_DATE).data + return sss_ctc + + +def _read_maxfilter_record(fid, tree): + """Read maxfilter processing record from file.""" + sss_info_block = dir_tree_find(tree, FIFF.FIFFB_SSS_INFO) # 502 + sss_info = dict() + if len(sss_info_block) > 0: + sss_info_block = sss_info_block[0] + for i_ent in range(sss_info_block["nent"]): + kind = sss_info_block["directory"][i_ent].kind + pos = sss_info_block["directory"][i_ent].pos + for key, id_, cast in zip(_sss_info_keys, _sss_info_ids, _sss_info_casters): + if kind == id_: + tag = read_tag(fid, pos) + sss_info[key] = cast(tag.data) + break + + max_st_block = dir_tree_find(tree, FIFF.FIFFB_SSS_ST_INFO) # 504 + max_st = dict() + if len(max_st_block) > 0: + max_st_block = max_st_block[0] + for i_ent in range(max_st_block["nent"]): + kind = max_st_block["directory"][i_ent].kind + pos = max_st_block["directory"][i_ent].pos + for key, id_, cast in zip(_max_st_keys, _max_st_ids, _max_st_casters): + if kind == id_: + tag = read_tag(fid, pos) + max_st[key] = cast(tag.data) + break + + sss_ctc_block = dir_tree_find(tree, FIFF.FIFFB_CHANNEL_DECOUPLER) # 501 + sss_ctc = dict() + if len(sss_ctc_block) > 0: + sss_ctc_block = sss_ctc_block[0] + for i_ent in range(sss_ctc_block["nent"]): + kind = sss_ctc_block["directory"][i_ent].kind + pos = sss_ctc_block["directory"][i_ent].pos + for key, id_, cast in zip(_sss_ctc_keys, _sss_ctc_ids, _sss_ctc_casters): + if kind == id_: + tag = read_tag(fid, pos) + sss_ctc[key] = cast(tag.data) + break + else: + if kind == FIFF.FIFF_PROJ_ITEM_CH_NAME_LIST: + tag = read_tag(fid, pos) + chs = _safe_name_list(tag.data, "read", "proj_items_chs") + # This list can null chars in the last entry, e.g.: + # [..., 'MEG2642', 'MEG2643', 'MEG2641\x00 ... \x00'] + chs[-1] = chs[-1].split("\x00")[0] + sss_ctc["proj_items_chs"] = chs + + sss_cal_block = dir_tree_find(tree, FIFF.FIFFB_SSS_CAL) # 503 + sss_cal = dict() + if len(sss_cal_block) > 0: + sss_cal_block = sss_cal_block[0] + for i_ent in range(sss_cal_block["nent"]): + kind = sss_cal_block["directory"][i_ent].kind + pos = sss_cal_block["directory"][i_ent].pos + for key, id_, cast in zip(_sss_cal_keys, _sss_cal_ids, _sss_cal_casters): + if kind == id_: + tag = read_tag(fid, pos) + sss_cal[key] = cast(tag.data) + break + + max_info = dict(sss_info=sss_info, sss_ctc=sss_ctc, sss_cal=sss_cal, max_st=max_st) + return max_info + + +def _write_maxfilter_record(fid, record): + """Write maxfilter processing record to file.""" + sss_info = record["sss_info"] + if len(sss_info) > 0: + start_block(fid, FIFF.FIFFB_SSS_INFO) + for key, id_, writer in zip(_sss_info_keys, _sss_info_ids, _sss_info_writers): + if key in sss_info: + writer(fid, id_, sss_info[key]) + end_block(fid, FIFF.FIFFB_SSS_INFO) + + max_st = record["max_st"] + if len(max_st) > 0: + start_block(fid, FIFF.FIFFB_SSS_ST_INFO) + for key, id_, writer in zip(_max_st_keys, _max_st_ids, _max_st_writers): + if key in max_st: + writer(fid, id_, max_st[key]) + end_block(fid, FIFF.FIFFB_SSS_ST_INFO) + + sss_ctc = record["sss_ctc"] + if len(sss_ctc) > 0: # dict has entries + start_block(fid, FIFF.FIFFB_CHANNEL_DECOUPLER) + for key, id_, writer in zip(_sss_ctc_keys, _sss_ctc_ids, _sss_ctc_writers): + if key in sss_ctc: + writer(fid, id_, sss_ctc[key]) + if "proj_items_chs" in sss_ctc: + write_name_list_sanitized( + fid, + FIFF.FIFF_PROJ_ITEM_CH_NAME_LIST, + sss_ctc["proj_items_chs"], + "proj_items_chs", + ) + end_block(fid, FIFF.FIFFB_CHANNEL_DECOUPLER) + + sss_cal = record["sss_cal"] + if len(sss_cal) > 0: + start_block(fid, FIFF.FIFFB_SSS_CAL) + for key, id_, writer in zip(_sss_cal_keys, _sss_cal_ids, _sss_cal_writers): + if key in sss_cal: + writer(fid, id_, sss_cal[key]) + end_block(fid, FIFF.FIFFB_SSS_CAL) diff --git a/mne-python/source/mne/_fiff/proj.py b/mne-python/source/mne/_fiff/proj.py new file mode 100644 index 0000000000000000000000000000000000000000..65125c45d3d18b8e65385285b4f660398477eb25 --- /dev/null +++ b/mne-python/source/mne/_fiff/proj.py @@ -0,0 +1,1187 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import re +from copy import deepcopy +from itertools import count + +import numpy as np + +from ..defaults import _BORDER_DEFAULT, _EXTRAPOLATE_DEFAULT, _INTERPOLATION_DEFAULT +from ..fixes import _safe_svd +from ..utils import ( + _check_option, + _validate_type, + fill_doc, + logger, + object_diff, + verbose, + warn, +) +from .constants import FIFF +from .pick import _ELECTRODE_CH_TYPES, _electrode_types, pick_info, pick_types +from .tag import _rename_list, find_tag +from .tree import dir_tree_find +from .write import ( + _safe_name_list, + end_block, + start_block, + write_float, + write_float_matrix, + write_int, + write_name_list_sanitized, + write_string, +) + + +class Projection(dict): + """Dictionary-like object holding a projection vector. + + Projection vectors are stored in a list in ``inst.info["projs"]``. Each projection + vector has 5 keys: ``active``, ``data``, ``desc``, ``explained_var``, ``kind``. + + .. warning:: This class is generally not meant to be instantiated + directly, use ``compute_proj_*`` functions instead. + + Parameters + ---------- + data : dict + The data dictionary. + desc : str + The projector description. + kind : int + The projector kind. + active : bool + Whether or not the projector has been applied. + explained_var : float | None + The proportion of explained variance. + """ + + def __init__( + self, + *, + data, + desc="", + kind=FIFF.FIFFV_PROJ_ITEM_FIELD, + active=False, + explained_var=None, + ): + super().__init__( + desc=desc, kind=kind, active=active, data=data, explained_var=explained_var + ) + + def __repr__(self): # noqa: D105 + s = str(self["desc"]) + s += f", active : {self['active']}" + s += f", n_channels : {len(self['data']['col_names'])}" + if self["explained_var"] is not None: + s += f", exp. var : {self['explained_var'] * 100:0.2f}%" + return f"" + + # speed up info copy by taking advantage of mutability + def __deepcopy__(self, memodict): + """Make a deepcopy.""" + cls = self.__class__ + result = cls.__new__(cls) + for k, v in self.items(): + if k == "data": + v = v.copy() + v["data"] = v["data"].copy() + result[k] = v + else: + result[k] = v # kind, active, desc, explained_var immutable + return result + + def __eq__(self, other): + """Equality == method.""" + return True if len(object_diff(self, other)) == 0 else False + + def __ne__(self, other): + """Different != method.""" + return not self.__eq__(other) + + @fill_doc + def plot_topomap( + self, + info, + *, + sensors=True, + show_names=False, + contours=6, + outlines="head", + sphere=None, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + border=_BORDER_DEFAULT, + res=64, + size=1, + cmap=None, + vlim=(None, None), + cnorm=None, + colorbar=False, + cbar_fmt="%3.1f", + units=None, + axes=None, + show=True, + ): + """Plot topographic maps of SSP projections. + + Parameters + ---------- + %(info_not_none)s Used to determine the layout. + %(sensors_topomap)s + %(show_names_topomap)s + + .. versionadded:: 1.2 + %(contours_topomap)s + %(outlines_topomap)s + %(sphere_topomap_auto)s + %(image_interp_topomap)s + %(extrapolate_topomap)s + + .. versionadded:: 1.2 + %(border_topomap)s + + .. versionadded:: 0.20 + %(res_topomap)s + %(size_topomap)s + %(cmap_topomap)s + %(vlim_plot_topomap_proj)s + %(cnorm)s + + .. versionadded:: 1.2 + %(colorbar_topomap)s + %(cbar_fmt_topomap)s + + .. versionadded:: 1.2 + %(units_topomap)s + + .. versionadded:: 1.2 + %(axes_plot_projs_topomap)s + %(show)s + + Returns + ------- + fig : instance of Figure + Figure distributing one image per channel across sensor topography. + + Notes + ----- + .. versionadded:: 0.15.0 + """ # noqa: E501 + from ..viz.topomap import plot_projs_topomap + + return plot_projs_topomap( + self, + info, + sensors=sensors, + show_names=show_names, + contours=contours, + outlines=outlines, + sphere=sphere, + image_interp=image_interp, + extrapolate=extrapolate, + border=border, + res=res, + size=size, + cmap=cmap, + vlim=vlim, + cnorm=cnorm, + colorbar=colorbar, + cbar_fmt=cbar_fmt, + units=units, + axes=axes, + show=show, + ) + + +class ProjMixin: + """Mixin class for Raw, Evoked, Epochs. + + Notes + ----- + This mixin adds a proj attribute as a property to data containers. + It is True if at least one proj is present and all of them are active. + The projs might not be applied yet if data are not preloaded. In + this case it's the _projector attribute that does the job. + If a private _data attribute is present then the projs applied + to it are the ones marked as active. + + A proj parameter passed in constructor of raw or epochs calls + apply_proj and hence after the .proj attribute is True. + + As soon as you've applied the projs it will stay active in the + remaining pipeline. + + The suggested pipeline is proj=True in epochs (it's cheaper than for raw). + + When you use delayed SSP in Epochs, projs are applied when you call + get_data() method. They are not applied to the evoked._data unless you call + apply_proj(). The reason is that you want to reject with projs although + it's not stored in proj mode. + """ + + @property + def proj(self): + """Whether or not projections are active.""" + return len(self.info["projs"]) > 0 and all( + p["active"] for p in self.info["projs"] + ) + + @verbose + def add_proj(self, projs, remove_existing=False, verbose=None): + """Add SSP projection vectors. + + Parameters + ---------- + projs : list + List with projection vectors. + remove_existing : bool + Remove the projection vectors currently in the file. + %(verbose)s + + Returns + ------- + self : same type as the input data + The data container. + """ + if isinstance(projs, Projection): + projs = [projs] + + if not isinstance(projs, list) and not all( + isinstance(p, Projection) for p in projs + ): + raise ValueError("Only projs can be added. You supplied something else.") + + # mark proj as inactive, as they have not been applied + projs = deactivate_proj(projs, copy=True) + if remove_existing: + # we cannot remove the proj if they are active + if any(p["active"] for p in self.info["projs"]): + raise ValueError( + "Cannot remove projectors that have already been applied" + ) + with self.info._unlock(): + self.info["projs"] = projs + else: + self.info["projs"].extend(projs) + # We don't want to add projectors that are activated again. + with self.info._unlock(): + self.info["projs"] = _uniquify_projs( + self.info["projs"], check_active=False, sort=False + ) + return self + + @verbose + def apply_proj(self, verbose=None): + """Apply the signal space projection (SSP) operators to the data. + + Parameters + ---------- + %(verbose)s + + Returns + ------- + self : same type as the input data + The instance. + + Notes + ----- + Once the projectors have been applied, they can no longer be + removed. It is usually not recommended to apply the projectors at + too early stages, as they are applied automatically later on + (e.g. when computing inverse solutions). + Hint: using the copy method individual projection vectors + can be tested without affecting the original data. + With evoked data, consider the following example:: + + projs_a = mne.read_proj('proj_a.fif') + projs_b = mne.read_proj('proj_b.fif') + # add the first, copy, apply and see ... + evoked.add_proj(a).copy().apply_proj().plot() + # add the second, copy, apply and see ... + evoked.add_proj(b).copy().apply_proj().plot() + # drop the first and see again + evoked.copy().del_proj(0).apply_proj().plot() + evoked.apply_proj() # finally keep both + """ + from ..epochs import BaseEpochs + from ..evoked import Evoked + from ..io import BaseRaw + + if self.info["projs"] is None or len(self.info["projs"]) == 0: + logger.info( + "No projector specified for this dataset. " + "Please consider the method self.add_proj." + ) + return self + + # Exit delayed mode if you apply proj + if isinstance(self, BaseEpochs) and self._do_delayed_proj: + logger.info("Leaving delayed SSP mode.") + self._do_delayed_proj = False + + if all(p["active"] for p in self.info["projs"]): + logger.info( + "Projections have already been applied. Setting proj attribute to True." + ) + return self + + _projector, info = setup_proj( + deepcopy(self.info), add_eeg_ref=False, activate=True + ) + # let's not raise a RuntimeError here, otherwise interactive plotting + if _projector is None: # won't be fun. + logger.info("The projections don't apply to these data. Doing nothing.") + return self + self._projector, self.info = _projector, info + if isinstance(self, BaseRaw | Evoked): + if self.preload: + self._data = np.dot(self._projector, self._data) + else: # BaseEpochs + if self.preload: + for ii, e in enumerate(self._data): + self._data[ii] = self._project_epoch(e) + else: + self.load_data() # will automatically apply + logger.info("SSP projectors applied...") + return self + + def del_proj(self, idx="all"): + """Remove SSP projection vector. + + .. note:: The projection vector can only be removed if it is inactive + (has not been applied to the data). + + Parameters + ---------- + idx : int | list of int | str + Index of the projector to remove. Can also be "all" (default) + to remove all projectors. + + Returns + ------- + self : same type as the input data + The instance. + """ + if isinstance(idx, str) and idx == "all": + idx = list(range(len(self.info["projs"]))) + idx = np.atleast_1d(np.array(idx, int)).ravel() + + for ii in idx: + proj = self.info["projs"][ii] + if proj["active"] and set(self.info["ch_names"]) & set( + proj["data"]["col_names"] + ): + msg = ( + f"Cannot remove projector that has already been " + f"applied, unless you first remove all channels it " + f"applies to. The problematic projector is: {proj}" + ) + raise ValueError(msg) + + keep = np.ones(len(self.info["projs"])) + keep[idx] = False # works with negative indexing and does checks + with self.info._unlock(): + self.info["projs"] = [p for p, k in zip(self.info["projs"], keep) if k] + return self + + @fill_doc + def plot_projs_topomap( + self, + ch_type=None, + *, + sensors=True, + show_names=False, + contours=6, + outlines="head", + sphere=None, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + border=_BORDER_DEFAULT, + res=64, + size=1, + cmap=None, + vlim=(None, None), + cnorm=None, + colorbar=False, + cbar_fmt="%3.1f", + units=None, + axes=None, + show=True, + ): + """Plot SSP vector. + + Parameters + ---------- + %(ch_type_topomap_proj)s + %(sensors_topomap)s + %(show_names_topomap)s + + .. versionadded:: 1.2 + %(contours_topomap)s + %(outlines_topomap)s + %(sphere_topomap_auto)s + %(image_interp_topomap)s + %(extrapolate_topomap)s + + .. versionadded:: 0.20 + + .. versionchanged:: 0.21 + + - The default was changed to ``'local'`` for MEG sensors. + - ``'local'`` was changed to use a convex hull mask + - ``'head'`` was changed to extrapolate out to the clipping circle. + %(border_topomap)s + + .. versionadded:: 0.20 + %(res_topomap)s + %(size_topomap)s + Only applies when plotting multiple topomaps at a time. + %(cmap_topomap)s + %(vlim_plot_topomap_proj)s + %(cnorm)s + + .. versionadded:: 1.2 + %(colorbar_topomap)s + %(cbar_fmt_topomap)s + + .. versionadded:: 1.2 + %(units_topomap)s + + .. versionadded:: 1.2 + %(axes_plot_projs_topomap)s + %(show)s + + Returns + ------- + fig : instance of Figure + Figure distributing one image per channel across sensor topography. + """ + _projs = [deepcopy(_proj) for _proj in self.info["projs"]] + if _projs is None or len(_projs) == 0: + raise ValueError("No projectors in Info; nothing to plot.") + if ch_type is not None: + # make sure the requested channel type(s) exist + _validate_type(ch_type, (str, list, tuple), "ch_type") + if isinstance(ch_type, str): + ch_type = [ch_type] + bad_ch_types = [_type not in self for _type in ch_type] + if any(bad_ch_types): + raise ValueError( + f"ch_type {ch_type[bad_ch_types]} not " + f"present in {self.__class__.__name__}." + ) + # remove projs from unrequested channel types. This is a bit + # convoluted because Projection objects don't store channel types, + # only channel names + available_ch_types = np.array(self.get_channel_types()) + for _proj in _projs[::-1]: + idx = np.isin(self.ch_names, _proj["data"]["col_names"]) + proj_ch_type = np.unique(available_ch_types[idx]) + err_msg = "Projector contains multiple channel types" + assert len(proj_ch_type) == 1, err_msg + if proj_ch_type[0] != ch_type: + _projs.remove(_proj) + if len(_projs) == 0: + raise ValueError( + f"Nothing to plot (no projectors for channel type {ch_type})." + ) + # now we have non-empty _projs list with correct channel type(s) + from ..viz.topomap import plot_projs_topomap + + fig = plot_projs_topomap( + _projs, + self.info, + sensors=sensors, + show_names=show_names, + contours=contours, + outlines=outlines, + sphere=sphere, + image_interp=image_interp, + extrapolate=extrapolate, + border=border, + res=res, + size=size, + cmap=cmap, + vlim=vlim, + cnorm=cnorm, + colorbar=colorbar, + cbar_fmt=cbar_fmt, + units=units, + axes=axes, + show=show, + ) + return fig + + def _reconstruct_proj(self, mode="accurate", origin="auto"): + from ..forward import _map_meg_or_eeg_channels + + if len(self.info["projs"]) == 0: + return self + self.apply_proj() + for kind in ("meg", "eeg"): + kwargs = dict(meg=False) + kwargs[kind] = True + picks = pick_types(self.info, **kwargs) + if len(picks) == 0: + continue + info_from = pick_info(self.info, picks) + info_to = info_from.copy() + with info_to._unlock(): + info_to["projs"] = [] + if kind == "eeg" and _has_eeg_average_ref_proj(info_from): + info_to["projs"] = [ + make_eeg_average_ref_proj(info_to, verbose=False) + ] + mapping = _map_meg_or_eeg_channels( + info_from, info_to, mode=mode, origin=origin + ) + self.data[..., picks, :] = np.matmul(mapping, self.data[..., picks, :]) + return self + + +def _proj_equal(a, b, check_active=True): + """Test if two projectors are equal.""" + equal = ( + (a["active"] == b["active"] or not check_active) + and a["kind"] == b["kind"] + and a["desc"] == b["desc"] + and a["data"]["col_names"] == b["data"]["col_names"] + and a["data"]["row_names"] == b["data"]["row_names"] + and a["data"]["ncol"] == b["data"]["ncol"] + and a["data"]["nrow"] == b["data"]["nrow"] + and np.all(a["data"]["data"] == b["data"]["data"]) + ) + return equal + + +@verbose +def _read_proj(fid, node, *, ch_names_mapping=None, verbose=None): + ch_names_mapping = {} if ch_names_mapping is None else ch_names_mapping + projs = list() + + # Locate the projection data + nodes = dir_tree_find(node, FIFF.FIFFB_PROJ) + if len(nodes) == 0: + return projs + + # This might exist but we won't use it: + # global_nchan = None + # tag = find_tag(fid, nodes[0], FIFF.FIFF_NCHAN) + # if tag is not None: + # global_nchan = int(tag.data.item()) + + items = dir_tree_find(nodes[0], FIFF.FIFFB_PROJ_ITEM) + for item in items: + # Find all desired tags in one item + + # This probably also exists but used to be written incorrectly + # sometimes + # tag = find_tag(fid, item, FIFF.FIFF_NCHAN) + # if tag is not None: + # nchan = int(tag.data.item()) + # else: + # nchan = global_nchan + + tag = find_tag(fid, item, FIFF.FIFF_DESCRIPTION) + if tag is not None: + desc = tag.data + else: + tag = find_tag(fid, item, FIFF.FIFF_NAME) + if tag is not None: + desc = tag.data + else: + raise ValueError("Projection item description missing") + + tag = find_tag(fid, item, FIFF.FIFF_PROJ_ITEM_KIND) + if tag is not None: + kind = int(tag.data.item()) + else: + raise ValueError("Projection item kind missing") + + tag = find_tag(fid, item, FIFF.FIFF_PROJ_ITEM_NVEC) + if tag is not None: + nvec = int(tag.data.item()) + else: + raise ValueError("Number of projection vectors not specified") + + tag = find_tag(fid, item, FIFF.FIFF_PROJ_ITEM_CH_NAME_LIST) + if tag is not None: + names = _safe_name_list(tag.data, "read", "names") + else: + raise ValueError("Projection item channel list missing") + + tag = find_tag(fid, item, FIFF.FIFF_PROJ_ITEM_VECTORS) + if tag is not None: + data = tag.data + else: + raise ValueError("Projection item data missing") + + tag = find_tag(fid, item, FIFF.FIFF_MNE_PROJ_ITEM_ACTIVE) + if tag is not None: + active = bool(tag.data.item()) + else: + active = False + + tag = find_tag(fid, item, FIFF.FIFF_MNE_ICA_PCA_EXPLAINED_VAR) + if tag is not None: + explained_var = float(tag.data.item()) + else: + explained_var = None + + # handle the case when data is transposed for some reason + if data.shape[0] == len(names) and data.shape[1] == nvec: + data = data.T + + if data.shape[1] != len(names): + raise ValueError( + "Number of channel names does not match the size of data matrix" + ) + + # just always use this, we used to have bugs with writing the + # number correctly... + nchan = len(names) + names[:] = _rename_list(names, ch_names_mapping) + # Use exactly the same fields in data as in a named matrix + one = Projection( + kind=kind, + active=active, + desc=desc, + data=dict( + nrow=nvec, ncol=nchan, row_names=None, col_names=names, data=data + ), + explained_var=explained_var, + ) + + projs.append(one) + + if len(projs) > 0: + logger.info(f" Read a total of {len(projs)} projection items:") + for proj in projs: + misc = "active" if proj["active"] else " idle" + logger.info( + f" {proj['desc']} " + f"({proj['data']['nrow']} x " + f"{len(proj['data']['col_names'])}) {misc}" + ) + + return projs + + +############################################################################### +# Write + + +def _write_proj(fid, projs, *, ch_names_mapping=None): + """Write a projection operator to a file. + + Parameters + ---------- + fid : file + The file descriptor of the open file. + projs : dict + The projection operator. + """ + if len(projs) == 0: + return + + ch_names_mapping = dict() if ch_names_mapping is None else ch_names_mapping + # validation + _validate_type(projs, (list, tuple), "projs") + for pi, proj in enumerate(projs): + _validate_type(proj, Projection, f"projs[{pi}]") + + start_block(fid, FIFF.FIFFB_PROJ) + + for proj in projs: + start_block(fid, FIFF.FIFFB_PROJ_ITEM) + write_int(fid, FIFF.FIFF_NCHAN, len(proj["data"]["col_names"])) + names = _rename_list(proj["data"]["col_names"], ch_names_mapping) + write_name_list_sanitized( + fid, FIFF.FIFF_PROJ_ITEM_CH_NAME_LIST, names, "col_names" + ) + write_string(fid, FIFF.FIFF_NAME, proj["desc"]) + write_int(fid, FIFF.FIFF_PROJ_ITEM_KIND, proj["kind"]) + if proj["kind"] == FIFF.FIFFV_PROJ_ITEM_FIELD: + write_float(fid, FIFF.FIFF_PROJ_ITEM_TIME, 0.0) + + write_int(fid, FIFF.FIFF_PROJ_ITEM_NVEC, proj["data"]["nrow"]) + write_int(fid, FIFF.FIFF_MNE_PROJ_ITEM_ACTIVE, proj["active"]) + write_float_matrix(fid, FIFF.FIFF_PROJ_ITEM_VECTORS, proj["data"]["data"]) + if proj["explained_var"] is not None: + write_float(fid, FIFF.FIFF_MNE_ICA_PCA_EXPLAINED_VAR, proj["explained_var"]) + end_block(fid, FIFF.FIFFB_PROJ_ITEM) + + end_block(fid, FIFF.FIFFB_PROJ) + + +############################################################################### +# Utils + + +def _check_projs(projs, copy=True): + """Check that projs is a list of Projection.""" + _validate_type(projs, (list, tuple), "projs") + for pi, p in enumerate(projs): + _validate_type(p, Projection, f"projs[{pi}]") + return deepcopy(projs) if copy else projs + + +def make_projector(projs, ch_names, bads=(), include_active=True): + """Create an SSP operator from SSP projection vectors. + + Parameters + ---------- + projs : list + List of projection vectors. + ch_names : list of str + List of channels to include in the projection matrix. + bads : list of str + Some bad channels to exclude. If bad channels were marked + in the raw file when projs were calculated using mne-python, + they should not need to be included here as they will + have been automatically omitted from the projectors. + include_active : bool + Also include projectors that are already active. + + Returns + ------- + proj : array of shape [n_channels, n_channels] + The projection operator to apply to the data. + nproj : int + How many items in the projector. + U : array + The orthogonal basis of the projection vectors. + """ + return _make_projector(projs, ch_names, bads, include_active) + + +def _make_projector(projs, ch_names, bads=(), include_active=True, inplace=False): + """Subselect projs based on ch_names and bads. + + Use inplace=True mode to modify ``projs`` inplace so that no + warning will be raised next time projectors are constructed with + the given inputs. If inplace=True, no meaningful data are returned. + """ + nchan = len(ch_names) + if nchan == 0: + raise ValueError("No channel names specified") + + default_return = (np.eye(nchan, nchan), 0, np.empty((nchan, 0))) + + # Check trivial cases first + if projs is None: + return default_return + + nvec = 0 + nproj = 0 + for p in projs: + if not p["active"] or include_active: + nproj += 1 + nvec += p["data"]["nrow"] + + if nproj == 0: + return default_return + + # Pick the appropriate entries + vecs = np.zeros((nchan, nvec)) + nvec = 0 + nonzero = 0 + bads = set(bads) + for k, p in enumerate(projs): + if not p["active"] or include_active: + if len(p["data"]["col_names"]) != len(np.unique(p["data"]["col_names"])): + raise ValueError( + f"Channel name list in projection item {k} contains duplicate items" + ) + + # Get the two selection vectors to pick correct elements from + # the projection vectors omitting bad channels + sel = [] + vecsel = [] + p_set = set(p["data"]["col_names"]) # faster membership access + for c, name in enumerate(ch_names): + if name not in bads and name in p_set: + sel.append(c) + vecsel.append(p["data"]["col_names"].index(name)) + + # If there is something to pick, pickit + nrow = p["data"]["nrow"] + this_vecs = vecs[:, nvec : nvec + nrow] + if len(sel) > 0: + this_vecs[sel] = p["data"]["data"][:, vecsel].T + + # Rescale for better detection of small singular values + for v in range(p["data"]["nrow"]): + psize = np.linalg.norm(this_vecs[:, v]) + if psize > 0: + orig_n = p["data"]["data"].any(axis=0).sum() + # Average ref still works if channels are removed + # Use relative power to determine if we're in trouble. + # 10% loss is hopefully a reasonable threshold. + if ( + psize < 0.9 + and not inplace + and ( + p["kind"] != FIFF.FIFFV_PROJ_ITEM_EEG_AVREF + or len(vecsel) == 1 + ) + ): + warn( + f"Projection vector {repr(p['desc'])} has been " + f"reduced to {100 * psize:0.2f}% of its " + "original magnitude by subselecting " + f"{len(vecsel)}/{orig_n} of the original " + "channels. If the ignored channels were bad " + "during SSP computation, we recommend " + "recomputing proj (via compute_proj_raw " + "or related functions) with the bad channels " + "properly marked, because computing SSP with bad " + "channels present in the data but unmarked is " + "dangerous (it can bias the PCA used by SSP). " + "On the other hand, if you know that all channels " + "were good during SSP computation, you can safely " + "use info.normalize_proj() to suppress this " + "warning during projection." + ) + this_vecs[:, v] /= psize + nonzero += 1 + # If doing "inplace" mode, "fix" the projectors to only operate + # on this subset of channels. + if inplace: + p["data"]["data"] = this_vecs[sel].T + p["data"]["col_names"] = [p["data"]["col_names"][ii] for ii in vecsel] + p["data"]["ncol"] = len(p["data"]["col_names"]) + nvec += p["data"]["nrow"] + + # Check whether all of the vectors are exactly zero + if nonzero == 0 or inplace: + return default_return + + # Reorthogonalize the vectors + U, S, _ = _safe_svd(vecs[:, :nvec], full_matrices=False) + + # Throw away the linearly dependent guys + nproj = np.sum((S / S[0]) > 1e-2) + U = U[:, :nproj] + + # Here is the celebrated result + proj = np.eye(nchan, nchan) - np.dot(U, U.T) + if nproj >= nchan: # e.g., 3 channels and 3 projectors + raise RuntimeError( + f"Application of {nproj} projectors for {nchan} channels " + "will yield no components." + ) + + return proj, nproj, U + + +def _normalize_proj(info): + """Normalize proj after subselection to avoid warnings. + + This is really only useful for tests, and might not be needed + eventually if we change or improve our handling of projectors + with picks. + """ + # Here we do info.get b/c info can actually be a noise cov + _make_projector( + info["projs"], + info.get("ch_names", info.get("names")), + info["bads"], + include_active=True, + inplace=True, + ) + + +@fill_doc +def make_projector_info(info, include_active=True): + """Make an SSP operator using the measurement info. + + Calls make_projector on good channels. + + Parameters + ---------- + %(info_not_none)s + include_active : bool + Also include projectors that are already active. + + Returns + ------- + proj : array of shape [n_channels, n_channels] + The projection operator to apply to the data. + nproj : int + How many items in the projector. + """ + proj, nproj, _ = make_projector( + info["projs"], info["ch_names"], info["bads"], include_active + ) + return proj, nproj + + +@verbose +def activate_proj(projs, copy=True, verbose=None): + """Set all projections to active. + + Useful before passing them to make_projector. + + Parameters + ---------- + projs : list + The projectors. + copy : bool + Modify projs in place or operate on a copy. + %(verbose)s + + Returns + ------- + projs : list + The projectors. + """ + if copy: + projs = deepcopy(projs) + + # Activate the projection items + for proj in projs: + proj["active"] = True + + logger.info(f"{len(projs)} projection items activated") + + return projs + + +@verbose +def deactivate_proj(projs, copy=True, verbose=None): + """Set all projections to inactive. + + Useful before saving raw data without projectors applied. + + Parameters + ---------- + projs : list + The projectors. + copy : bool + Modify projs in place or operate on a copy. + %(verbose)s + + Returns + ------- + projs : list + The projectors. + """ + if copy: + projs = deepcopy(projs) + + # Deactivate the projection items + for proj in projs: + proj["active"] = False + + logger.info(f"{len(projs)} projection items deactivated") + + return projs + + +# Keep in sync with doc below +_EEG_AVREF_PICK_DICT = {k: True for k in _ELECTRODE_CH_TYPES} + + +@verbose +def make_eeg_average_ref_proj(info, activate=True, *, ch_type="eeg", verbose=None): + """Create an EEG average reference SSP projection vector. + + Parameters + ---------- + %(info_not_none)s + activate : bool + If True projections are activated. + ch_type : str + The channel type to use for reference projection. + Valid types are ``'eeg'``, ``'ecog'``, ``'seeg'`` and ``'dbs'``. + + .. versionadded:: 1.2 + %(verbose)s + + Returns + ------- + proj: instance of Projection + The SSP/PCA projector. + """ + if info.get("custom_ref_applied", False): + raise RuntimeError( + "A custom reference has been applied to the " + "data earlier. Please use the " + "mne.io.set_eeg_reference function to move from " + "one EEG reference to another." + ) + + _validate_type(ch_type, (list, tuple, str), "ch_type") + singleton = False + if isinstance(ch_type, str): + ch_type = [ch_type] + singleton = True + for ci, this_ch_type in enumerate(ch_type): + _check_option( + "ch_type" + ("" if singleton else f"[{ci}]"), + this_ch_type, + list(_EEG_AVREF_PICK_DICT), + ) + + ch_type_name = "/".join(c.upper() for c in ch_type) + logger.info(f"Adding average {ch_type_name} reference projection.") + + ch_dict = {c: True for c in ch_type} + for c in ch_type: + one_picks = pick_types(info, exclude="bads", **{c: True}) + if len(one_picks) == 0: + raise ValueError( + f"Cannot create {ch_type_name} average reference " + f"projector (no {c.upper()} data found)" + ) + del ch_type + ch_sel = pick_types(info, **ch_dict, exclude="bads") + ch_names = info["ch_names"] + ch_names = [ch_names[k] for k in ch_sel] + n_chs = len(ch_sel) + vec = np.ones((1, n_chs)) + vec /= np.sqrt(n_chs) + explained_var = None + proj_data = dict(col_names=ch_names, row_names=None, data=vec, nrow=1, ncol=n_chs) + proj = Projection( + active=activate, + data=proj_data, + explained_var=explained_var, + desc=f"Average {ch_type_name} reference", + kind=FIFF.FIFFV_PROJ_ITEM_EEG_AVREF, + ) + return proj + + +@verbose +def _has_eeg_average_ref_proj( + info, *, projs=None, check_active=False, ch_type=None, verbose=None +): + """Determine if a list of projectors has an average EEG ref. + + Optionally, set check_active=True to additionally check if the CAR + has already been applied. + """ + from .meas_info import Info + + _validate_type(info, Info, "info") + projs = info.get("projs", []) if projs is None else projs + if ch_type is None: + pick_kwargs = _EEG_AVREF_PICK_DICT + else: + ch_type = [ch_type] if isinstance(ch_type, str) else ch_type + pick_kwargs = {ch_type: True for ch_type in ch_type} + ch_type = "/".join(c.upper() for c in pick_kwargs) + want_names = [ + info["ch_names"][pick] + for pick in pick_types(info, exclude="bads", **pick_kwargs) + ] + if not want_names: + return False + found_names = list() + for proj in projs: + if proj["kind"] == FIFF.FIFFV_PROJ_ITEM_EEG_AVREF or re.match( + "^Average .* reference$", proj["desc"] + ): + if not check_active or proj["active"]: + found_names.extend(proj["data"]["col_names"]) + # If some are missing we have a problem (keep order for the message, + # otherwise we could use set logic) + missing = [name for name in want_names if name not in found_names] + if missing: + if found_names: # found some but not all: warn + warn(f"Incomplete {ch_type} projector, missing channel(s) {missing}") + return False + return True + + +def _needs_eeg_average_ref_proj(info): + """Determine if the EEG needs an average EEG reference. + + This returns True if no custom reference has been applied and no average + reference projection is present in the list of projections. + """ + if info["custom_ref_applied"]: + return False + if not _electrode_types(info): + return False + if _has_eeg_average_ref_proj(info): + return False + return True + + +@verbose +def setup_proj( + info, add_eeg_ref=True, activate=True, *, eeg_ref_ch_type="eeg", verbose=None +): + """Set up projection for Raw and Epochs. + + Parameters + ---------- + %(info_not_none)s Warning: will be modified in-place. + add_eeg_ref : bool + If True, an EEG average reference will be added (unless one + already exists). + activate : bool + If True projections are activated. + eeg_ref_ch_type : str + The channel type to use for reference projection. + Valid types are 'eeg', 'ecog', 'seeg' and 'dbs'. + + .. versionadded:: 1.2 + %(verbose)s + + Returns + ------- + projector : array of shape [n_channels, n_channels] + The projection operator to apply to the data. + info : mne.Info + The modified measurement info. + """ + # Add EEG ref reference proj if necessary + if add_eeg_ref and _needs_eeg_average_ref_proj(info): + eeg_proj = make_eeg_average_ref_proj( + info, activate=activate, ch_type=eeg_ref_ch_type + ) + info["projs"].append(eeg_proj) + + # Create the projector + projector, nproj = make_projector_info(info) + if nproj == 0: + if verbose: + logger.info("The projection vectors do not apply to these channels") + projector = None + else: + logger.info(f"Created an SSP operator (subspace dimension = {nproj})") + + # The projection items have been activated + if activate: + with info._unlock(): + info["projs"] = activate_proj(info["projs"], copy=False) + + return projector, info + + +def _uniquify_projs(projs, check_active=True, sort=True): + """Make unique projs.""" + final_projs = [] + for proj in projs: # flatten + if not any(_proj_equal(p, proj, check_active) for p in final_projs): + final_projs.append(proj) + + my_count = count(len(final_projs)) + + def sorter(x): + """Sort in a nice way.""" + digits = [s for s in x["desc"] if s.isdigit()] + if digits: + sort_idx = int(digits[-1]) + else: + sort_idx = next(my_count) + return (sort_idx, x["desc"]) + + return sorted(final_projs, key=sorter) if sort else final_projs diff --git a/mne-python/source/mne/_fiff/reference.py b/mne-python/source/mne/_fiff/reference.py new file mode 100644 index 0000000000000000000000000000000000000000..3b654ee77845096279c0abdbfb09fdc06eaba989 --- /dev/null +++ b/mne-python/source/mne/_fiff/reference.py @@ -0,0 +1,738 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ..defaults import DEFAULTS +from ..utils import ( + _check_option, + _check_preload, + _on_missing, + _validate_type, + fill_doc, + logger, + pinv, + verbose, + warn, +) +from .constants import FIFF +from .meas_info import _check_ch_keys +from .pick import _ELECTRODE_CH_TYPES, pick_channels, pick_channels_forward, pick_types +from .proj import _has_eeg_average_ref_proj, make_eeg_average_ref_proj, setup_proj + + +def _check_before_reference(inst, ref_from, ref_to, ch_type): + """Prepare instance for referencing.""" + # Check to see that data is preloaded + _check_preload(inst, "Applying a reference") + + ch_type = _get_ch_type(inst, ch_type) + ch_dict = {**{type_: True for type_ in ch_type}, "meg": False, "ref_meg": False} + eeg_idx = pick_types(inst.info, **ch_dict) + + if ref_to is None: + ref_to = [inst.ch_names[i] for i in eeg_idx] + extra = "EEG channels found" + else: + extra = "channels supplied" + if len(ref_to) == 0: + raise ValueError(f"No {extra} to apply the reference to") + + _check_ssp(inst, ref_from + ref_to) + + # If the reference touches EEG/ECoG/sEEG/DBS electrodes, note in the + # info that a non-CAR has been applied. + ref_to_channels = pick_channels(inst.ch_names, ref_to, ordered=True) + if len(np.intersect1d(ref_to_channels, eeg_idx)) > 0: + with inst.info._unlock(): + inst.info["custom_ref_applied"] = FIFF.FIFFV_MNE_CUSTOM_REF_ON + + return ref_to + + +def _check_ssp(inst, ref_items): + """Check for SSPs that may block re-referencing.""" + projs_to_remove = [] + for i, proj in enumerate(inst.info["projs"]): + # Remove any average reference projections + if ( + proj["desc"] == "Average EEG reference" + or proj["kind"] == FIFF.FIFFV_PROJ_ITEM_EEG_AVREF + ): + logger.info("Removing existing average EEG reference projection.") + # Don't remove the projection right away, but do this at the end of + # this loop. + projs_to_remove.append(i) + + # Inactive SSPs may block re-referencing + elif ( + not proj["active"] + and len([ch for ch in ref_items if ch in proj["data"]["col_names"]]) > 0 + ): + raise RuntimeError( + "Inactive signal space projection (SSP) operators are " + "present that operate on sensors involved in the desired " + "referencing scheme. These projectors need to be applied " + "using the apply_proj() method function before the desired " + "reference can be set." + ) + + for i in projs_to_remove: + del inst.info["projs"][i] + + # Need to call setup_proj after changing the projs: + inst._projector, _ = setup_proj(inst.info, add_eeg_ref=False, activate=False) + + +def _check_before_dict_reference(inst, ref_dict): + """Prepare instance for dict-based referencing.""" + # Check to see that data is preloaded + _check_preload(inst, "Applying a reference") + + # Promote all values to list-like. This simplifies our logic and also helps catch + # self-referencing cases like `{"Cz": ["Cz"]}` + _refdict = {k: [v] if isinstance(v, str) else list(v) for k, v in ref_dict.items()} + + # Check that keys are strings and values are lists-of-strings + key_types = {type(k) for k in _refdict} + value_types = {type(v) for val in _refdict.values() for v in val} + for elem_name, elem in dict(key=key_types, value=value_types).items(): + if bad_elem := elem - {str}: + raise TypeError( + f"{elem_name.capitalize()}s in the ref_channels dict must be strings. " + f"Your dict has {elem_name}s of type " + f"{', '.join(map(lambda x: x.__name__, bad_elem))}." + ) + + # Check that keys are valid channels and values are lists-of-valid-channels + ch_set = set(inst.ch_names) + bad_ch_set = set(inst.info["bads"]) + keys = set(_refdict) + values = set(sum(_refdict.values(), [])) + for elem_name, elem in dict(key=keys, value=values).items(): + if bad_elem := elem - ch_set: + raise ValueError( + f"ref_channels dict contains invalid {elem_name}(s) " + f"({', '.join(bad_elem)}) " + "that are not names of channels in the instance." + ) + # Check that values are not bad channels + if bad_elem := elem.intersection(bad_ch_set): + warn( + f"ref_channels dict contains {elem_name}(s) " + f"({', '.join(bad_elem)}) " + "that are marked as bad channels." + ) + + _check_ssp(inst, keys.union(values)) + + # Check for self-referencing + self_ref = [[k] == v for k, v in _refdict.items()] + if any(self_ref): + which = np.array(list(_refdict))[np.nonzero(self_ref)] + for ch in which: + warn(f"Channel {ch} is self-referenced, which will nullify the channel.") + + # Check that channel types match. First unpack list-like vals into separate items: + pairs = [(k, v) for k in _refdict for v in _refdict[k]] + ch_type_map = dict(zip(inst.ch_names, inst.get_channel_types())) + mismatch = [ch_type_map[k] != ch_type_map[v] for k, v in pairs] + if any(mismatch): + mismatch_pairs = np.array(pairs)[mismatch] + for k, v in mismatch_pairs: + warn( + f"Channel {k} ({ch_type_map[k]}) is referenced to channel {v} which is " + f"a different channel type ({ch_type_map[v]})." + ) + + # convert channel names to indices + keys_ix = pick_channels(inst.ch_names, list(_refdict), ordered=True) + vals_ix = (pick_channels(inst.ch_names, v, ordered=True) for v in _refdict.values()) + return dict(zip(keys_ix, vals_ix)) + + +def _apply_reference(inst, ref_from, ref_to=None, forward=None, ch_type="auto"): + """Apply a custom EEG referencing scheme.""" + ref_to = _check_before_reference(inst, ref_from, ref_to, ch_type) + + # Compute reference + if len(ref_from) > 0: + # this is guaranteed below, but we should avoid the crazy pick_channels + # behavior that [] gives all. Also use ordered=True just to make sure + # that all supplied channels actually exist. + assert len(ref_to) > 0 + ref_names = ref_from + ref_from = pick_channels(inst.ch_names, ref_from, ordered=True) + ref_to = pick_channels(inst.ch_names, ref_to, ordered=True) + + data = inst._data + ref_data = data[..., ref_from, :].mean(-2, keepdims=True) + data[..., ref_to, :] -= ref_data + ref_data = ref_data[..., 0, :] + + # REST + if forward is not None: + # use ch_sel and the given forward + forward = pick_channels_forward(forward, ref_names, ordered=True) + # 1-3. Compute a forward (G) and avg-ref'ed data (done above) + G = forward["sol"]["data"] + assert G.shape[0] == len(ref_names) + # 4. Compute the forward (G) and average-reference it (Ga): + Ga = G - np.mean(G, axis=0, keepdims=True) + # 5. Compute the Ga_inv by SVD + Ga_inv = pinv(Ga, rtol=1e-6) + # 6. Compute Ra = (G @ Ga_inv) in eq (8) from G and Ga_inv + Ra = G @ Ga_inv + # 7-8. Compute Vp = Ra @ Va; then Vpa=average(Vp) + Vpa = np.mean(Ra @ data[..., ref_from, :], axis=-2, keepdims=True) + data[..., ref_to, :] += Vpa + else: + ref_data = None + + return inst, ref_data + + +def _apply_dict_reference(inst, ref_dict): + """Apply a dict-based custom EEG referencing scheme.""" + # this converts all keys to channel indices and all values to arrays of ch. indices: + ref_dict = _check_before_dict_reference(inst, ref_dict) + + data = inst._data + orig_data = data.copy() + for ref_to, ref_from in ref_dict.items(): + ref_data = orig_data[..., ref_from, :].mean(-2, keepdims=True) + data[..., [ref_to], :] -= ref_data + + with inst.info._unlock(): + inst.info["custom_ref_applied"] = FIFF.FIFFV_MNE_CUSTOM_REF_ON + return inst, None + + +@fill_doc +def add_reference_channels(inst, ref_channels, copy=True): + """Add reference channels to data that consists of all zeros. + + Adds reference channels to data that were not included during recording. + This is useful when you need to re-reference your data to different + channels. These added channels will consist of all zeros. + + Parameters + ---------- + inst : instance of Raw | Epochs | Evoked + Instance of Raw or Epochs with EEG channels and reference channel(s). + %(ref_channels)s + copy : bool + Specifies whether the data will be copied (True) or modified in-place + (False). Defaults to True. + + Returns + ------- + inst : same type as the input data + Data with added EEG reference channels. + + Notes + ----- + .. warning:: + When :ref:`re-referencing `, + make sure to apply the montage using :meth:`mne.io.Raw.set_montage` + only after calling this function. Applying a montage will only set + locations of channels that exist at the time it is applied. + """ + from ..epochs import BaseEpochs + from ..evoked import Evoked + from ..io import BaseRaw + + # Check to see that data is preloaded + _check_preload(inst, "add_reference_channels") + _validate_type(ref_channels, (list, tuple, str), "ref_channels") + if isinstance(ref_channels, str): + ref_channels = [ref_channels] + for ch in ref_channels: + if ch in inst.info["ch_names"]: + raise ValueError(f"Channel {ch} already specified in inst.") + + # Once CAR is applied (active), don't allow adding channels + if _has_eeg_average_ref_proj(inst.info, check_active=True): + raise RuntimeError("Average reference already applied to data.") + + if copy: + inst = inst.copy() + + if isinstance(inst, BaseRaw | Evoked): + data = inst._data + refs = np.zeros((len(ref_channels), data.shape[1])) + data = np.vstack((data, refs)) + inst._data = data + elif isinstance(inst, BaseEpochs): + data = inst._data + x, y, z = data.shape + refs = np.zeros((x * len(ref_channels), z)) + data = np.vstack((data.reshape((x * y, z), order="F"), refs)) + data = data.reshape(x, y + len(ref_channels), z, order="F") + inst._data = data + else: + raise TypeError( + f"inst should be Raw, Epochs, or Evoked instead of {type(inst)}." + ) + nchan = len(inst.info["ch_names"]) + + if inst.info.get("dig", None) is not None: + # A montage has been set. Try to infer location of reference channels. + # "zeroth" EEG electrode dig points is reference + ref_dig_loc = [ + dl + for dl in inst.info["dig"] + if (dl["kind"] == FIFF.FIFFV_POINT_EEG and dl["ident"] == 0) + ] + if len(ref_channels) > 1 or len(ref_dig_loc) != len(ref_channels): + ref_dig_array = np.full(12, np.nan) + warn( + "Location for this channel is unknown or ambiguous; consider calling " + "set_montage() after adding new reference channels if needed. " + "Applying a montage will only set locations of channels that " + "exist at the time it is applied." + ) + else: # n_ref_channels == 1 and a single ref digitization exists + ref_dig_array = np.concatenate( + (ref_dig_loc[0]["r"], ref_dig_loc[0]["r"], np.zeros(6)) + ) + # Replace the (possibly new) Ref location for each channel + for idx in pick_types(inst.info, meg=False, eeg=True, exclude=[]): + inst.info["chs"][idx]["loc"][3:6] = ref_dig_loc[0]["r"] + else: + # If no montage has ever been set, we cannot even try to infer a location. + ref_dig_array = np.full(12, np.nan) + + for ch in ref_channels: + chan_info = { + "ch_name": ch, + "coil_type": FIFF.FIFFV_COIL_EEG, + "kind": FIFF.FIFFV_EEG_CH, + "logno": nchan + 1, + "scanno": nchan + 1, + "cal": 1, + "range": 1.0, + "unit_mul": FIFF.FIFF_UNITM_NONE, + "unit": FIFF.FIFF_UNIT_V, + "coord_frame": FIFF.FIFFV_COORD_HEAD, + "loc": ref_dig_array.copy(), + } + inst.info["chs"].append(chan_info) + inst.info._update_redundant() + range_ = np.arange(1, len(ref_channels) + 1) + if isinstance(inst, BaseRaw): + inst._cals = np.hstack((inst._cals, [1] * len(ref_channels))) + for pi, picks in enumerate(inst._read_picks): + inst._read_picks[pi] = np.concatenate([picks, np.max(picks) + range_]) + elif isinstance(inst, BaseEpochs): + picks = inst.picks + inst.picks = np.concatenate([picks, np.max(picks) + range_]) + inst.info._check_consistency() + set_eeg_reference(inst, ref_channels=ref_channels, copy=False, verbose=False) + return inst + + +_ref_dict = { + FIFF.FIFFV_MNE_CUSTOM_REF_ON: "on", + FIFF.FIFFV_MNE_CUSTOM_REF_OFF: "off", + FIFF.FIFFV_MNE_CUSTOM_REF_CSD: "CSD", +} + + +def _check_can_reref(inst): + from ..epochs import BaseEpochs + from ..evoked import Evoked + from ..io import BaseRaw + + _validate_type(inst, (BaseRaw, BaseEpochs, Evoked), "Instance") + current_custom = inst.info["custom_ref_applied"] + if current_custom not in ( + FIFF.FIFFV_MNE_CUSTOM_REF_ON, + FIFF.FIFFV_MNE_CUSTOM_REF_OFF, + ): + raise RuntimeError( + "Cannot set new reference on data with custom reference type " + f"{_ref_dict[current_custom]!r}" + ) + + +@verbose +def set_eeg_reference( + inst, + ref_channels="average", + copy=True, + projection=False, + ch_type="auto", + forward=None, + *, + joint=False, + verbose=None, +): + """Specify which reference to use for EEG data. + + Use this function to explicitly specify the desired reference for EEG. + This can be either an existing electrode or a new virtual channel. + This function will re-reference the data according to the desired + reference. + + Note that it is also possible to re-reference the signal using a + Laplacian (LAP) "reference-free" transformation using the + :func:`.compute_current_source_density` function. + + Parameters + ---------- + inst : instance of Raw | Epochs | Evoked + Instance of Raw or Epochs with EEG channels and reference channel(s). + %(ref_channels_set_eeg_reference)s + copy : bool + Specifies whether the data will be copied (True) or modified in-place + (False). Defaults to True. + %(projection_set_eeg_reference)s + %(ch_type_set_eeg_reference)s + %(forward_set_eeg_reference)s + %(joint_set_eeg_reference)s + %(verbose)s + + Returns + ------- + inst : same type as the input data + Data with EEG channels re-referenced. If ``ref_channels="average"`` and + ``projection=True`` a projection will be added instead of directly + re-referencing the data. + ref_data : array + Array of reference data subtracted from EEG channels. This will be + ``None`` if ``projection=True``, or if ``ref_channels`` is ``"REST"`` or a + :class:`dict`. + %(set_eeg_reference_see_also_notes)s + """ + from ..forward import Forward + + _check_can_reref(inst) + + if isinstance(ref_channels, dict): + logger.info("Applying a custom dict-based reference.") + return _apply_dict_reference(inst, ref_channels) + + ch_type = _get_ch_type(inst, ch_type) + + if projection: # average reference projector + if ref_channels != "average": + raise ValueError( + 'Setting projection=True is only supported for ref_channels="average", ' + f"got {ref_channels!r}." + ) + # We need verbose='error' here in case we add projs sequentially + if _has_eeg_average_ref_proj(inst.info, ch_type=ch_type, verbose="error"): + warn( + "An average reference projection was already added. The data " + "has been left untouched." + ) + else: + # Creating an average reference may fail. In this case, make + # sure that the custom_ref_applied flag is left untouched. + custom_ref_applied = inst.info["custom_ref_applied"] + + try: + with inst.info._unlock(): + inst.info["custom_ref_applied"] = FIFF.FIFFV_MNE_CUSTOM_REF_OFF + if joint: + inst.add_proj( + make_eeg_average_ref_proj( + inst.info, ch_type=ch_type, activate=False + ) + ) + else: + for this_ch_type in ch_type: + inst.add_proj( + make_eeg_average_ref_proj( + inst.info, ch_type=this_ch_type, activate=False + ) + ) + except Exception: + with inst.info._unlock(): + inst.info["custom_ref_applied"] = custom_ref_applied + raise + # If the data has been preloaded, projections will no + # longer be automatically applied. + if inst.preload: + logger.info( + "Average reference projection was added, " + "but has not been applied yet. Use the " + "apply_proj method to apply it." + ) + return inst, None + del projection # not used anymore + + inst = inst.copy() if copy else inst + ch_dict = {**{type_: True for type_ in ch_type}, "meg": False, "ref_meg": False} + ch_sel = [inst.ch_names[i] for i in pick_types(inst.info, **ch_dict)] + + if ref_channels == "REST": + _validate_type(forward, Forward, 'forward when ref_channels="REST"') + else: + forward = None # signal to _apply_reference not to do REST + + if ref_channels in ("average", "REST"): + logger.info(f"Applying {ref_channels} reference.") + ref_channels = ch_sel + + if ref_channels == []: + logger.info("EEG data marked as already having the desired reference.") + else: + logger.info( + "Applying a custom " + f"{tuple(DEFAULTS['titles'][type_] for type_ in ch_type)} " + "reference." + ) + + return _apply_reference(inst, ref_channels, ch_sel, forward, ch_type=ch_type) + + +def _get_ch_type(inst, ch_type): + _validate_type(ch_type, (str, list, tuple), "ch_type") + valid_ch_types = ("auto",) + _ELECTRODE_CH_TYPES + if isinstance(ch_type, str): + _check_option("ch_type", ch_type, valid_ch_types) + if ch_type != "auto": + ch_type = [ch_type] + elif isinstance(ch_type, list | tuple): + for type_ in ch_type: + _validate_type(type_, str, "ch_type") + _check_option("ch_type", type_, valid_ch_types[1:]) + ch_type = list(ch_type) + + # if ch_type is 'auto', search through list to find first reasonable + # reference-able channel type. + if ch_type == "auto": + for type_ in _ELECTRODE_CH_TYPES: + if type_ in inst: + ch_type = [type_] + logger.info( + f"{DEFAULTS['titles'][type_]} channel type selected for " + "re-referencing" + ) + break + # if auto comes up empty, or the user specifies a bad ch_type. + else: + raise ValueError("No EEG, ECoG, sEEG or DBS channels found to rereference.") + return ch_type + + +@verbose +def set_bipolar_reference( + inst, + anode, + cathode, + ch_name=None, + ch_info=None, + drop_refs=True, + copy=True, + on_bad="warn", + verbose=None, +): + """Re-reference selected channels using a bipolar referencing scheme. + + A bipolar reference takes the difference between two channels (the anode + minus the cathode) and adds it as a new virtual channel. The original + channels will be dropped by default. + + Multiple anodes and cathodes can be specified, in which case multiple + virtual channels will be created. The 1st cathode will be subtracted + from the 1st anode, the 2nd cathode from the 2nd anode, etc. + + By default, the virtual channels will be annotated with channel-info and + -location of the anodes and coil types will be set to EEG_BIPOLAR. + + Parameters + ---------- + inst : instance of Raw | Epochs | Evoked + Data containing the unreferenced channels. + anode : str | list of str + The name(s) of the channel(s) to use as anode in the bipolar reference. + cathode : str | list of str + The name(s) of the channel(s) to use as cathode in the bipolar + reference. + ch_name : str | list of str | None + The channel name(s) for the virtual channel(s) containing the resulting + signal. By default, bipolar channels are named after the anode and + cathode, but it is recommended to supply a more meaningful name. + ch_info : dict | list of dict | None + This parameter can be used to supply a dictionary (or a dictionary for + each bipolar channel) containing channel information to merge in, + overwriting the default values. Defaults to None. + drop_refs : bool + Whether to drop the anode/cathode channels from the instance. + copy : bool + Whether to operate on a copy of the data (True) or modify it in-place + (False). Defaults to True. + on_bad : str + If a bipolar channel is created from a bad anode or a bad cathode, mne + warns if on_bad="warns", raises ValueError if on_bad="raise", and does + nothing if on_bad="ignore". For "warn" and "ignore", the new bipolar + channel will be marked as bad. Defaults to on_bad="warns". + %(verbose)s + + Returns + ------- + inst : same type as the input data + Data with the specified channels re-referenced. + + See Also + -------- + set_eeg_reference : Convenience function for creating an EEG reference. + + Notes + ----- + 1. If the anodes contain any EEG channels, this function removes + any pre-existing average reference projections. + + 2. During source localization, the EEG signal should have an average + reference. + + 3. The data must be preloaded. + + .. versionadded:: 0.9.0 + """ + from ..epochs import BaseEpochs, EpochsArray + from ..evoked import EvokedArray + from ..io import BaseRaw, RawArray + from .meas_info import create_info + + _check_can_reref(inst) + if not isinstance(anode, list): + anode = [anode] + + if not isinstance(cathode, list): + cathode = [cathode] + + if len(anode) != len(cathode): + raise ValueError( + f"Number of anodes (got {len(anode)}) must equal the number " + f"of cathodes (got {len(cathode)})." + ) + + if ch_name is None: + ch_name = [f"{a}-{c}" for (a, c) in zip(anode, cathode)] + elif not isinstance(ch_name, list): + ch_name = [ch_name] + if len(ch_name) != len(anode): + raise ValueError( + "Number of channel names must equal the number of " + f"anodes/cathodes (got {len(ch_name)})." + ) + + # Check for duplicate channel names (it is allowed to give the name of the + # anode or cathode channel, as they will be replaced). + for ch, a, c in zip(ch_name, anode, cathode): + if ch not in [a, c] and ch in inst.ch_names: + raise ValueError( + f'There is already a channel named "{ch}", please ' + "specify a different name for the bipolar " + "channel using the ch_name parameter." + ) + + if ch_info is None: + ch_info = [{} for _ in anode] + elif not isinstance(ch_info, list): + ch_info = [ch_info] + if len(ch_info) != len(anode): + raise ValueError( + "Number of channel info dictionaries must equal the " + "number of anodes/cathodes." + ) + + if copy: + inst = inst.copy() + + anode = _check_before_reference( + inst, ref_from=cathode, ref_to=anode, ch_type="auto" + ) + + # Create bipolar reference channels by multiplying the data + # (channels x time) with a matrix (n_virtual_channels x channels) + # and add them to the instance. + multiplier = np.zeros((len(anode), len(inst.ch_names))) + for idx, (a, c) in enumerate(zip(anode, cathode)): + multiplier[idx, inst.ch_names.index(a)] = 1 + multiplier[idx, inst.ch_names.index(c)] = -1 + + ref_info = create_info( + ch_names=ch_name, + sfreq=inst.info["sfreq"], + ch_types=inst.get_channel_types(picks=anode), + ) + + # Update "chs" in Reference-Info. + for ch_idx, (an, info) in enumerate(zip(anode, ch_info)): + _check_ch_keys(info, ch_idx, name="ch_info", check_min=False) + an_idx = inst.ch_names.index(an) + # Copy everything from anode (except ch_name). + an_chs = {k: v for k, v in inst.info["chs"][an_idx].items() if k != "ch_name"} + ref_info["chs"][ch_idx].update(an_chs) + # Set coil-type to bipolar. + ref_info["chs"][ch_idx]["coil_type"] = FIFF.FIFFV_COIL_EEG_BIPOLAR + # Update with info from ch_info-parameter. + ref_info["chs"][ch_idx].update(info) + + # Set other info-keys from original instance. + pick_info = { + k: v + for k, v in inst.info.items() + if k not in ["chs", "ch_names", "bads", "nchan", "sfreq"] + } + + with ref_info._unlock(): + ref_info.update(pick_info) + + # Rereferencing of data. + ref_data = multiplier @ inst._data + + if isinstance(inst, BaseRaw): + ref_inst = RawArray(ref_data, ref_info, first_samp=inst.first_samp, copy=None) + elif isinstance(inst, BaseEpochs): + ref_inst = EpochsArray( + ref_data, + ref_info, + events=inst.events, + tmin=inst.tmin, + event_id=inst.event_id, + metadata=inst.metadata, + ) + else: + ref_inst = EvokedArray( + ref_data, + ref_info, + tmin=inst.tmin, + comment=inst.comment, + nave=inst.nave, + kind="average", + ) + + # Add referenced instance to original instance. + inst.add_channels([ref_inst], force_update_info=True) + + # Handle bad channels. + bad_bipolar_chs = [] + for ch_idx, (a, c) in enumerate(zip(anode, cathode)): + if a in inst.info["bads"] or c in inst.info["bads"]: + bad_bipolar_chs.append(ch_name[ch_idx]) + + # Add warnings if bad channels are present. + if bad_bipolar_chs: + msg = f"Bipolar channels are based on bad channels: {bad_bipolar_chs}." + _on_missing(on_bad, msg) + inst.info["bads"] += bad_bipolar_chs + + added_channels = ", ".join([name for name in ch_name]) + logger.info(f"Added the following bipolar channels:\n{added_channels}") + + for attr_name in ["picks", "_projector"]: + setattr(inst, attr_name, None) + + # Drop remaining channels. + if drop_refs: + drop_channels = list((set(anode) | set(cathode)) & set(inst.ch_names)) + inst.drop_channels(drop_channels) + + return inst diff --git a/mne-python/source/mne/_fiff/tag.py b/mne-python/source/mne/_fiff/tag.py new file mode 100644 index 0000000000000000000000000000000000000000..391606e7ccabc17f9d39d3657b05e1c8b28f6b68 --- /dev/null +++ b/mne-python/source/mne/_fiff/tag.py @@ -0,0 +1,533 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import html +import re +import struct +from dataclasses import dataclass +from functools import partial +from typing import Any + +import numpy as np +from scipy.sparse import csc_array, csr_array + +from ..fixes import _reshape_view +from ..utils import _check_option, warn +from ..utils.numerics import _julian_to_date +from .constants import ( + FIFF, + _ch_coil_type_named, + _ch_kind_named, + _ch_unit_mul_named, + _ch_unit_named, + _dig_cardinal_named, + _dig_kind_named, +) + +############################################################################## +# HELPERS + + +@dataclass +class Tag: + """Tag in FIF tree structure.""" + + kind: int + type: int + size: int + next: int + pos: int + data: Any = None + + def __eq__(self, tag): # noqa: D105 + return int( + self.kind == tag.kind + and self.type == tag.type + and self.size == tag.size + and self.next == tag.next + and self.pos == tag.pos + and self.data == tag.data + ) + + @property + def next_pos(self): + """The next tag position.""" + if self.next == FIFF.FIFFV_NEXT_SEQ: # 0 + return self.pos + 16 + self.size + elif self.next > 0: + return self.next + else: # self.next should be -1 if we get here + return None # safest to return None so that things like fid.seek die + + +def _frombuffer_rows(fid, tag_size, dtype=None, shape=None, rlims=None): + """Get a range of rows from a large tag.""" + if shape is not None: + item_size = np.dtype(dtype).itemsize + if not len(shape) == 2: + raise ValueError("Only implemented for 2D matrices") + want_shape = np.prod(shape) + have_shape = tag_size // item_size + if want_shape != have_shape: + raise ValueError( + f"Wrong shape specified, requested {want_shape} but got {have_shape}" + ) + if not len(rlims) == 2: + raise ValueError("rlims must have two elements") + n_row_out = rlims[1] - rlims[0] + if n_row_out <= 0: + raise ValueError("rlims must yield at least one output") + row_size = item_size * shape[1] + # # of bytes to skip at the beginning, # to read, where to end + start_skip = int(rlims[0] * row_size) + read_size = int(n_row_out * row_size) + end_pos = int(fid.tell() + tag_size) + # Move the pointer ahead to the read point + fid.seek(start_skip, 1) + # Do the reading + out = np.frombuffer(fid.read(read_size), dtype=dtype) + # Move the pointer ahead to the end of the tag + fid.seek(end_pos) + else: + out = np.frombuffer(fid.read(tag_size), dtype=dtype) + return out + + +def _loc_to_coil_trans(loc): + """Convert loc vector to coil_trans.""" + assert loc.shape[-1] == 12 + coil_trans = np.zeros(loc.shape[:-1] + (4, 4)) + coil_trans[..., :3, 3] = loc[..., :3] + coil_trans[..., :3, :3] = np.reshape( + loc[..., 3:], loc.shape[:-1] + (3, 3) + ).swapaxes(-1, -2) + coil_trans[..., -1, -1] = 1.0 + return coil_trans + + +def _coil_trans_to_loc(coil_trans): + """Convert coil_trans to loc.""" + coil_trans = coil_trans.astype(np.float64) + return np.roll(coil_trans.T[:, :3], 1, 0).flatten() + + +def _loc_to_eeg_loc(loc): + """Convert a loc to an EEG loc.""" + if not np.isfinite(loc[:3]).all(): + raise RuntimeError("Missing EEG channel location") + if np.isfinite(loc[3:6]).all() and (loc[3:6]).any(): + return np.array([loc[0:3], loc[3:6]]).T + else: + return loc[0:3][:, np.newaxis].copy() + + +############################################################################## +# READING FUNCTIONS + +# None of these functions have docstring because it's more compact that way, +# and hopefully it's clear what they do by their names and variable values. +# See ``read_tag`` for variable descriptions. Return values are implied +# by the function names. + + +def _read_tag_header(fid, pos): + """Read only the header of a Tag.""" + fid.seek(pos, 0) + s = fid.read(16) + if len(s) != 16: + where = fid.tell() - len(s) + extra = f" in file {fid.name}" if hasattr(fid, "name") else "" + warn(f"Invalid tag with only {len(s)}/16 bytes at position {where}{extra}") + return None + # struct.unpack faster than np.frombuffer, saves ~10% of time some places + kind, type_, size, next_ = struct.unpack(">iIii", s) + return Tag(kind, type_, size, next_, pos) + + +def _read_matrix(fid, tag, shape, rlims): + """Read a matrix (dense or sparse) tag.""" + # This should be easy to implement (see _frombuffer_rows) + # if we need it, but for now, it's not... + if shape is not None or rlims is not None: + raise ValueError("Row reading not implemented for matrices yet") + + matrix_coding, matrix_type, bit, dtype = _matrix_info(tag) + + pos = tag.pos + 16 + fid.seek(pos + tag.size - 4, 0) + if matrix_coding == "dense": + # Find dimensions and return to the beginning of tag data + ndim = int(np.frombuffer(fid.read(4), dtype=">i4").item()) + fid.seek(-(ndim + 1) * 4, 1) + dims = np.frombuffer(fid.read(4 * ndim), dtype=">i4")[::-1] + # + # Back to where the data start + # + fid.seek(pos, 0) + + if ndim > 3: + raise Exception( + "Only 2 or 3-dimensional matrices are supported at this time" + ) + + data = fid.read(int(bit * dims.prod())) + data = np.frombuffer(data, dtype=dtype) + # Note: we need the non-conjugate transpose here + if matrix_type == FIFF.FIFFT_COMPLEX_FLOAT: + data = data.view(">c8") + elif matrix_type == FIFF.FIFFT_COMPLEX_DOUBLE: + data = data.view(">c16") + data = _reshape_view(data, dims) + else: + # Find dimensions and return to the beginning of tag data + ndim = int(np.frombuffer(fid.read(4), dtype=">i4").item()) + fid.seek(-(ndim + 2) * 4, 1) + dims = np.frombuffer(fid.read(4 * (ndim + 1)), dtype=">i4") + if ndim != 2: + raise Exception("Only two-dimensional matrices are supported at this time") + + # Back to where the data start + fid.seek(pos, 0) + nnz = int(dims[0]) + nrow = int(dims[1]) + ncol = int(dims[2]) + # We need to make a copy so that we can own the data, otherwise we get: + # _sparsetools.csr_sort_indices(len(self.indptr) - 1, self.indptr, + # E ValueError: WRITEBACKIFCOPY base is read-only + data = np.frombuffer(fid.read(bit * nnz), dtype=dtype).astype(np.float32) + shape = (dims[1], dims[2]) + if matrix_coding == "sparse CCS": + tmp_indices = fid.read(4 * nnz) + indices = np.frombuffer(tmp_indices, dtype=">i4") + tmp_ptr = fid.read(4 * (ncol + 1)) + indptr = np.frombuffer(tmp_ptr, dtype=">i4") + swap = nrow + klass = csc_array + else: + assert matrix_coding == "sparse RCS", matrix_coding + tmp_indices = fid.read(4 * nnz) + indices = np.frombuffer(tmp_indices, dtype=">i4") + tmp_ptr = fid.read(4 * (nrow + 1)) + indptr = np.frombuffer(tmp_ptr, dtype=">i4") + swap = ncol + klass = csr_array + if indptr[-1] > len(indices) or np.any(indptr < 0): + # There was a bug in MNE-C that caused some data to be + # stored without byte swapping + indices = np.concatenate( + ( + np.frombuffer(tmp_indices[: 4 * (swap + 1)], dtype=">i4"), + np.frombuffer(tmp_indices[4 * (swap + 1) :], dtype="c8") + return d + + +def _read_complex_double(fid, tag, shape, rlims): + """Read complex double tag.""" + # data gets stored twice as large + if shape is not None: + shape = (shape[0], shape[1] * 2) + d = _frombuffer_rows(fid, tag.size, dtype=">f8", shape=shape, rlims=rlims) + d = d.view(">c16") + return d + + +def _read_id_struct(fid, tag, shape, rlims): + """Read ID struct tag.""" + return dict( + version=int(np.frombuffer(fid.read(4), dtype=">i4").item()), + machid=np.frombuffer(fid.read(8), dtype=">i4"), + secs=int(np.frombuffer(fid.read(4), dtype=">i4").item()), + usecs=int(np.frombuffer(fid.read(4), dtype=">i4").item()), + ) + + +def _read_dig_point_struct(fid, tag, shape, rlims, *, string=False): + """Read dig point struct tag.""" + kind = int(np.frombuffer(fid.read(4), dtype=">i4").item()) + kind = _dig_kind_named.get(kind, kind) + ident = int(np.frombuffer(fid.read(4), dtype=">i4").item()) + if kind == FIFF.FIFFV_POINT_CARDINAL: + ident = _dig_cardinal_named.get(ident, ident) + n = 1 if not string else int(np.frombuffer(fid.read(4), dtype=">i4").item()) + out = [ + dict( + kind=kind, + ident=ident, + r=np.frombuffer(fid.read(12), dtype=">f4"), + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + ) + for _ in range(n) + ] + if not string: + out = out[0] + return out + + +def _read_coord_trans_struct(fid, tag, shape, rlims): + """Read coord trans struct tag.""" + from ..transforms import Transform + + fro = int(np.frombuffer(fid.read(4), dtype=">i4").item()) + to = int(np.frombuffer(fid.read(4), dtype=">i4").item()) + rot = np.frombuffer(fid.read(36), dtype=">f4").reshape(3, 3) + move = np.frombuffer(fid.read(12), dtype=">f4") + trans = np.r_[np.c_[rot, move], np.array([[0], [0], [0], [1]]).T] + data = Transform(fro, to, trans) + fid.seek(48, 1) # Skip over the inverse transformation + return data + + +_ch_coord_dict = { + FIFF.FIFFV_MEG_CH: FIFF.FIFFV_COORD_DEVICE, + FIFF.FIFFV_REF_MEG_CH: FIFF.FIFFV_COORD_DEVICE, + FIFF.FIFFV_EEG_CH: FIFF.FIFFV_COORD_HEAD, + FIFF.FIFFV_ECOG_CH: FIFF.FIFFV_COORD_HEAD, + FIFF.FIFFV_SEEG_CH: FIFF.FIFFV_COORD_HEAD, + FIFF.FIFFV_DBS_CH: FIFF.FIFFV_COORD_HEAD, + FIFF.FIFFV_FNIRS_CH: FIFF.FIFFV_COORD_HEAD, +} + + +def _read_ch_info_struct(fid, tag, shape, rlims): + """Read channel info struct tag.""" + d = dict( + scanno=int(np.frombuffer(fid.read(4), dtype=">i4").item()), + logno=int(np.frombuffer(fid.read(4), dtype=">i4").item()), + kind=int(np.frombuffer(fid.read(4), dtype=">i4").item()), + range=float(np.frombuffer(fid.read(4), dtype=">f4").item()), + cal=float(np.frombuffer(fid.read(4), dtype=">f4").item()), + coil_type=int(np.frombuffer(fid.read(4), dtype=">i4").item()), + # deal with really old OSX Anaconda bug by casting to float64 + loc=np.frombuffer(fid.read(48), dtype=">f4").astype(np.float64), + # unit and exponent + unit=int(np.frombuffer(fid.read(4), dtype=">i4").item()), + unit_mul=int(np.frombuffer(fid.read(4), dtype=">i4").item()), + ) + # channel name + ch_name = np.frombuffer(fid.read(16), dtype=">c") + ch_name = ch_name[: np.argmax(ch_name == b"")].tobytes() + d["ch_name"] = ch_name.decode() + # coil coordinate system definition + _update_ch_info_named(d) + return d + + +def _update_ch_info_named(d): + d["coord_frame"] = _ch_coord_dict.get(d["kind"], FIFF.FIFFV_COORD_UNKNOWN) + d["kind"] = _ch_kind_named.get(d["kind"], d["kind"]) + d["coil_type"] = _ch_coil_type_named.get(d["coil_type"], d["coil_type"]) + d["unit"] = _ch_unit_named.get(d["unit"], d["unit"]) + d["unit_mul"] = _ch_unit_mul_named.get(d["unit_mul"], d["unit_mul"]) + + +def _read_old_pack(fid, tag, shape, rlims): + """Read old pack tag.""" + offset = float(np.frombuffer(fid.read(4), dtype=">f4").item()) + scale = float(np.frombuffer(fid.read(4), dtype=">f4").item()) + data = np.frombuffer(fid.read(tag.size - 8), dtype=">i2") + data = data * scale # to float64 + data += offset + return data + + +def _read_dir_entry_struct(fid, tag, shape, rlims): + """Read dir entry struct tag.""" + pos = tag.pos + 16 + entries = list() + for offset in range(tag.size // 16): + ent = _read_tag_header(fid, pos + offset * 16) + # The position of the real tag on disk is stored in the "next" entry within the + # directory, so we need to overwrite ent.pos. For safety let's also overwrite + # ent.next to point nowhere + ent.pos, ent.next = ent.next, FIFF.FIFFV_NEXT_NONE + entries.append(ent) + return entries + + +def _read_julian(fid, tag, shape, rlims): + """Read julian tag.""" + return _julian_to_date(int(np.frombuffer(fid.read(4), dtype=">i4").item())) + + +# Read types call dict +_call_dict = { + FIFF.FIFFT_STRING: _read_string, + FIFF.FIFFT_COMPLEX_FLOAT: _read_complex_float, + FIFF.FIFFT_COMPLEX_DOUBLE: _read_complex_double, + FIFF.FIFFT_ID_STRUCT: _read_id_struct, + FIFF.FIFFT_DIG_POINT_STRUCT: _read_dig_point_struct, + FIFF.FIFFT_DIG_STRING_STRUCT: partial(_read_dig_point_struct, string=True), + FIFF.FIFFT_COORD_TRANS_STRUCT: _read_coord_trans_struct, + FIFF.FIFFT_CH_INFO_STRUCT: _read_ch_info_struct, + FIFF.FIFFT_OLD_PACK: _read_old_pack, + FIFF.FIFFT_DIR_ENTRY_STRUCT: _read_dir_entry_struct, + FIFF.FIFFT_JULIAN: _read_julian, + FIFF.FIFFT_VOID: lambda fid, tag, shape, rlims: None, +} +_call_dict_names = { + FIFF.FIFFT_STRING: "str", + FIFF.FIFFT_COMPLEX_FLOAT: "c8", + FIFF.FIFFT_COMPLEX_DOUBLE: "c16", + FIFF.FIFFT_ID_STRUCT: "ids", + FIFF.FIFFT_DIG_POINT_STRUCT: "dps", + FIFF.FIFFT_DIG_STRING_STRUCT: "dss", + FIFF.FIFFT_COORD_TRANS_STRUCT: "cts", + FIFF.FIFFT_CH_INFO_STRUCT: "cis", + FIFF.FIFFT_OLD_PACK: "op_", + FIFF.FIFFT_DIR_ENTRY_STRUCT: "dir", + FIFF.FIFFT_JULIAN: "jul", + FIFF.FIFFT_VOID: "nul", # 0 +} + +# Append the simple types +_simple_dict = { + FIFF.FIFFT_BYTE: ">B", + FIFF.FIFFT_SHORT: ">i2", + FIFF.FIFFT_INT: ">i4", + FIFF.FIFFT_USHORT: ">u2", + FIFF.FIFFT_UINT: ">u4", + FIFF.FIFFT_FLOAT: ">f4", + FIFF.FIFFT_DOUBLE: ">f8", + FIFF.FIFFT_DAU_PACK16: ">i2", +} +for key, dtype in _simple_dict.items(): + _call_dict[key] = partial(_read_simple, dtype=dtype) + _call_dict_names[key] = dtype + + +def read_tag(fid, pos, shape=None, rlims=None): + """Read a Tag from a file at a given position. + + Parameters + ---------- + fid : file + The open FIF file descriptor. + pos : int + The position of the Tag in the file. + shape : tuple | None + If tuple, the shape of the stored matrix. Only to be used with + data stored as a vector (not implemented for matrices yet). + rlims : tuple | None + If tuple, the first (inclusive) and last (exclusive) rows to retrieve. + Note that data are assumed to be stored row-major in the file. Only to + be used with data stored as a vector (not implemented for matrices + yet). + + Returns + ------- + tag : Tag + The Tag read. + """ + tag = _read_tag_header(fid, pos) + if tag is None: + return tag + if tag.size > 0: + if _matrix_info(tag) is not None: + tag.data = _read_matrix(fid, tag, shape, rlims) + else: + # All other data types + try: + fun = _call_dict[tag.type] + except KeyError: + raise Exception(f"Unimplemented tag data type {tag.type}") from None + tag.data = fun(fid, tag, shape, rlims) + return tag + + +def find_tag(fid, node, findkind): + """Find Tag in an open FIF file descriptor. + + Parameters + ---------- + fid : file-like + Open file. + node : dict + Node to search. + findkind : int + Tag kind to find. + + Returns + ------- + tag : instance of Tag + The first tag found. + """ + if node["directory"] is not None: + for subnode in node["directory"]: + if subnode.kind == findkind: + return read_tag(fid, subnode.pos) + return None + + +def has_tag(node, kind): + """Check if the node contains a Tag of a given kind.""" + for d in node["directory"]: + if d.kind == kind: + return True + return False + + +def _rename_list(bads, ch_names_mapping): + return [ch_names_mapping.get(bad, bad) for bad in bads] + + +def _int_item(x): + return int(x.item()) + + +def _float_item(x): + return float(x.item()) + + +def _matrix_info(tag): + matrix_coding = tag.type & 0xFFFF0000 + if matrix_coding == 0 or tag.size == 0: + return None + matrix_type = tag.type & 0x0000FFFF + matrix_coding_dict = { + FIFF.FIFFT_MATRIX: "dense", + FIFF.FIFFT_MATRIX | FIFF.FIFFT_SPARSE_CCS_MATRIX: "sparse CCS", + FIFF.FIFFT_MATRIX | FIFF.FIFFT_SPARSE_RCS_MATRIX: "sparse RCS", + } + _check_option("matrix_coding", matrix_coding, list(matrix_coding_dict)) + matrix_coding = matrix_coding_dict[matrix_coding] + matrix_bit_dtype = { + FIFF.FIFFT_INT: (4, ">i4"), + FIFF.FIFFT_JULIAN: (4, ">i4"), + FIFF.FIFFT_FLOAT: (4, ">f4"), + FIFF.FIFFT_DOUBLE: (8, ">f8"), + FIFF.FIFFT_COMPLEX_FLOAT: (8, ">f4"), + FIFF.FIFFT_COMPLEX_DOUBLE: (16, ">f8"), + } + _check_option("matrix_type", matrix_type, list(matrix_bit_dtype)) + bit, dtype = matrix_bit_dtype[matrix_type] + return matrix_coding, matrix_type, bit, dtype diff --git a/mne-python/source/mne/_fiff/tests/__init__.py b/mne-python/source/mne/_fiff/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c45203dcc03058ddea3c2e0c7ff40936a583857c --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op + +data_dir = op.join(op.dirname(__file__), "data") diff --git a/mne-python/source/mne/_fiff/tests/test_compensator.py b/mne-python/source/mne/_fiff/tests/test_compensator.py new file mode 100644 index 0000000000000000000000000000000000000000..4854cc1831c4feacd79c0cb48e7ed6f4eab83270 --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_compensator.py @@ -0,0 +1,118 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose + +from mne import Epochs, pick_types, read_evokeds +from mne._fiff.compensator import get_current_comp, make_compensator +from mne.io import read_raw_fif +from mne.utils import requires_mne, run_subprocess + +base_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +ctf_comp_fname = base_dir / "test_ctf_comp_raw.fif" + + +def test_compensation_identity(): + """Test compensation identity.""" + raw = read_raw_fif(ctf_comp_fname) + assert get_current_comp(raw.info) == 3 + comp1 = make_compensator(raw.info, 3, 1, exclude_comp_chs=False) + assert comp1.shape == (340, 340) + comp2 = make_compensator(raw.info, 3, 1, exclude_comp_chs=True) + assert comp2.shape == (311, 340) + + # round-trip + desired = np.eye(340) + for from_ in range(3): + for to in range(3): + if from_ == to: + continue + comp1 = make_compensator(raw.info, from_, to) + comp2 = make_compensator(raw.info, to, from_) + # To get 1e-12 here (instead of 1e-6) we must use the linalg.inv + # method mentioned in compensator.py + assert_allclose(np.dot(comp1, comp2), desired, atol=1e-12) + assert_allclose(np.dot(comp2, comp1), desired, atol=1e-12) + + +@pytest.mark.parametrize("preload", (True, False)) +@pytest.mark.parametrize("pick", (False, True)) +def test_compensation_apply(tmp_path, preload, pick): + """Test applying compensation.""" + # make sure that changing the comp doesn't modify the original data + raw = read_raw_fif(ctf_comp_fname, preload=preload) + assert raw._comp is None + raw2 = raw.copy() + raw2.apply_gradient_compensation(2) + if pick: + raw2.pick([0] + list(range(2, len(raw.ch_names)))) + raw.pick([0] + list(range(2, len(raw.ch_names)))) + assert get_current_comp(raw2.info) == 2 + if preload: + assert raw2._comp is None + else: + assert raw2._comp.shape == (len(raw2.ch_names),) * 2 + fname = tmp_path / "ctf-raw.fif" + raw2.save(fname) + raw2 = read_raw_fif(fname) + assert raw2.compensation_grade == 2 + raw2.apply_gradient_compensation(3) + assert raw2.compensation_grade == 3 + data, _ = raw[:, :] + data2, _ = raw2[:, :] + # channels have norm ~1e-12 + assert_allclose(data, data2, rtol=1e-9, atol=1e-18) + for ch1, ch2 in zip(raw.info["chs"], raw2.info["chs"]): + assert ch1["coil_type"] == ch2["coil_type"] + + +@requires_mne +def test_compensation_mne(tmp_path): + """Test comensation by comparing with MNE.""" + + def make_evoked(fname, comp): + """Make evoked data.""" + raw = read_raw_fif(fname) + if comp is not None: + raw.apply_gradient_compensation(comp) + picks = pick_types(raw.info, meg=True, ref_meg=True) + events = np.array([[0, 0, 1]], dtype=np.int64) + evoked = Epochs(raw, events, 1, 0, 20e-3, picks=picks, baseline=None).average() + return evoked + + def compensate_mne(fname, comp): + """Compensate using MNE-C.""" + tmp_fname = f"{fname.stem}-{comp}-ave.fif" + cmd = [ + "mne_compensate_data", + "--in", + str(fname), + "--out", + tmp_fname, + "--grad", + str(comp), + ] + run_subprocess(cmd) + return read_evokeds(tmp_fname)[0] + + # save evoked response with default compensation + fname_default = tmp_path / "ctf_default-ave.fif" + make_evoked(ctf_comp_fname, None).save(fname_default) + + for comp in [0, 1, 2, 3]: + evoked_py = make_evoked(ctf_comp_fname, comp) + evoked_c = compensate_mne(fname_default, comp) + picks_py = pick_types(evoked_py.info, meg=True, ref_meg=True) + picks_c = pick_types(evoked_c.info, meg=True, ref_meg=True) + assert_allclose( + evoked_py.data[picks_py], evoked_c.data[picks_c], rtol=1e-3, atol=1e-17 + ) + chs_py = [evoked_py.info["chs"][ii] for ii in picks_py] + chs_c = [evoked_c.info["chs"][ii] for ii in picks_c] + for ch_py, ch_c in zip(chs_py, chs_c): + assert ch_py["coil_type"] == ch_c["coil_type"] diff --git a/mne-python/source/mne/_fiff/tests/test_constants.py b/mne-python/source/mne/_fiff/tests/test_constants.py new file mode 100644 index 0000000000000000000000000000000000000000..43ea22903465bb95b3f167fd7963b5265e91d097 --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_constants.py @@ -0,0 +1,457 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import re +import shutil +import zipfile + +import numpy as np +import pooch +import pytest + +from mne._fiff.constants import ( + FIFF, + FWD, + _ch_coil_type_named, + _ch_kind_named, + _ch_unit_mul_named, + _ch_unit_named, + _coord_frame_named, + _dig_cardinal_named, + _dig_kind_named, +) +from mne.forward._make_forward import _read_coil_defs +from mne.transforms import _frame_to_str, _verbose_frames +from mne.utils import requires_good_network + +# https://github.com/mne-tools/fiff-constants/commits/master +REPO = "mne-tools" +COMMIT = "e27f68cbf74dbfc5193ad429cc77900a59475181" + +# These are oddities that we won't address: +iod_dups = (355, 359) # these are in both MEGIN and MNE files +tag_dups = (3501,) # in both MEGIN and MNE files + +_dir_ignore_names = ( + "clear", + "copy", + "fromkeys", + "get", + "items", + "keys", + "pop", + "popitem", + "setdefault", + "update", + "values", + "has_key", + "iteritems", + "iterkeys", + "itervalues", # Py2 + "viewitems", + "viewkeys", + "viewvalues", # Py2 +) +_tag_ignore_names = () # for fiff-constants pending updates +_ignore_incomplete_enums = ( # XXX eventually we could complete these + "bem_surf_id", + "cardinal_point_cardiac", + "cond_model", + "coord", + "dacq_system", + "diffusion_param", + "gantry_type", + "map_surf", + "mne_lin_proj", + "mne_ori", + "mri_format", + "mri_pixel", + "proj_by", + "tags", + "type", + "iod", + "volume_type", + "vol_type", +) +# not in coil_def.dat but in DictionaryTypes:enum(coil) +_missing_coil_def = ( + 0, # The location info contains no data + 1, # EEG electrode position in r0 + 3, # Old 24 channel system in HUT + 4, # The axial devices in the HUCS MCG system + 5, # Bipolar EEG electrode position + 6, # CSD-transformed EEG electrodes + 200, # Time-varying dipole definition + 300, # fNIRS oxyhemoglobin + 301, # fNIRS deoxyhemoglobin + 302, # fNIRS continuous wave + 303, # fNIRS optical density + 304, # fNIRS frequency domain AC amplitude + 305, # fNIRS frequency domain phase + 306, # fNIRS time domain gated amplitude + 307, # fNIRS time domain moments amplitude + 400, # Eye-tracking gaze position + 401, # Eye-tracking pupil size + 1000, # For testing the MCG software + 2001, # Generic axial gradiometer + 3011, # VV prototype wirewound planar sensor + 3014, # Vectorview SQ20950N planar gradiometer + 3021, # VV prototype wirewound magnetometer +) +# explicit aliases in constants.py +_aliases = dict( + FIFFV_COIL_MAGNES_R_MAG="FIFFV_COIL_MAGNES_REF_MAG", + FIFFV_COIL_MAGNES_R_GRAD="FIFFV_COIL_MAGNES_REF_GRAD", + FIFFV_COIL_MAGNES_R_GRAD_OFF="FIFFV_COIL_MAGNES_OFFDIAG_REF_GRAD", + FIFFV_COIL_FNIRS_RAW="FIFFV_COIL_FNIRS_CW_AMPLITUDE", + FIFFV_MNE_COORD_CTF_HEAD="FIFFV_MNE_COORD_4D_HEAD", + FIFFV_MNE_COORD_KIT_HEAD="FIFFV_MNE_COORD_4D_HEAD", + FIFFV_MNE_COORD_DIGITIZER="FIFFV_COORD_ISOTRAK", + FIFFV_MNE_COORD_SURFACE_RAS="FIFFV_COORD_MRI", + FIFFV_MNE_SENSOR_COV="FIFFV_MNE_NOISE_COV", + FIFFV_POINT_EEG="FIFFV_POINT_ECG", + FIFF_DESCRIPTION="FIFF_COMMENT", + FIFF_REF_PATH="FIFF_MRI_SOURCE_PATH", +) + + +@pytest.mark.flaky +@requires_good_network +@pytest.mark.ultraslowtest # not that slow, just doesn't need to run very often +def test_constants(tmp_path): + """Test compensation.""" + fname = "fiff.zip" + dest = tmp_path / fname + pooch.retrieve( + url=f"https://codeload.github.com/{REPO}/fiff-constants/zip/{COMMIT}", + path=tmp_path, + fname=fname, + known_hash=None, + ) + names = list() + with zipfile.ZipFile(dest, "r") as ff: + for name in ff.namelist(): + if "Dictionary" in name: + ff.extract(name, tmp_path) + names.append(os.path.basename(name)) + shutil.move(tmp_path / name, tmp_path / names[-1]) + names = sorted(names) + assert names == [ + "DictionaryIOD.txt", + "DictionaryIOD_MNE.txt", + "DictionaryStructures.txt", + "DictionaryTags.txt", + "DictionaryTags_MNE.txt", + "DictionaryTypes.txt", + "DictionaryTypes_MNE.txt", + ] + # IOD (MEGIN and MNE) + fif = dict(iod=dict(), tags=dict(), types=dict(), defines=dict()) + con = dict(iod=dict(), tags=dict(), types=dict(), defines=dict()) + fiff_version = None + for name in ["DictionaryIOD.txt", "DictionaryIOD_MNE.txt"]: + with open(tmp_path / name, "rb") as fid: + for line in fid: + line = line.decode("latin1").strip() + if line.startswith("# Packing revision"): + assert fiff_version is None + fiff_version = line.split()[-1] + if line.startswith("#") or line.startswith("alias") or len(line) == 0: + continue + line = line.split('"') + assert len(line) in (1, 2, 3) + desc = "" if len(line) == 1 else line[1] + line = line[0].split() + assert len(line) in (2, 3) + if len(line) == 2: + kind, id_ = line + else: + kind, id_, tagged = line + assert tagged in ("tagged",) + id_ = int(id_) + if id_ not in iod_dups: + assert id_ not in fif["iod"] + fif["iod"][id_] = [kind, desc] + # Tags (MEGIN) + with open(tmp_path / "DictionaryTags.txt", "rb") as fid: + for line in fid: + line = line.decode("ISO-8859-1").strip() + if ( + line.startswith("#") + or line.startswith("alias") + or line.startswith(":") + or len(line) == 0 + ): + continue + line = line.split('"') + assert len(line) in (1, 2, 3), line + desc = "" if len(line) == 1 else line[1] + line = line[0].split() + assert len(line) == 4, line + kind, id_, dtype, unit = line + id_ = int(id_) + val = [kind, dtype, unit] + assert id_ not in fif["tags"], (fif["tags"].get(id_), val) + fif["tags"][id_] = val + # Tags (MNE) + with open(tmp_path / "DictionaryTags_MNE.txt", "rb") as fid: + for li, line in enumerate(fid): + line = line.decode("ISO-8859-1").strip() + # ignore continuation lines (*) + if ( + line.startswith("#") + or line.startswith("alias") + or line.startswith(":") + or line.startswith("*") + or len(line) == 0 + ): + continue + # weird syntax around line 80: + if line in ("/*", '"'): + continue + line = line.split('"') + assert len(line) in (1, 2, 3), line + if len(line) == 3 and len(line[2]) > 0: + l2 = line[2].strip() + assert l2.startswith("/*") and l2.endswith("*/"), l2 + desc = "" if len(line) == 1 else line[1] + line = line[0].split() + assert len(line) == 3, (li + 1, line) + kind, id_, dtype = line + unit = "-" + id_ = int(id_) + val = [kind, dtype, unit] + if id_ not in tag_dups: + assert id_ not in fif["tags"], (fif["tags"].get(id_), val) + fif["tags"][id_] = val + + # Types and enums + in_ = None + re_prim = re.compile(r'^primitive\((.*)\)\s*(\S*)\s*"(.*)"$') + re_enum = re.compile(r'^enum\((\S*)\)\s*".*"$') + re_enum_entry = re.compile(r'\s*(\S*)\s*(\S*)\s*"(.*)"$') + re_deri = re.compile(r"^derived_type\((.*)\)\s*(\S*)\s*$") + re_defi = re.compile(r'#define\s*(\S*)\s*(\S*)\s*"(.*)"$') + used_enums = list() + for extra in ("", "_MNE"): + with open(tmp_path / f"DictionaryTypes{extra}.txt", "rb") as fid: + for li, line in enumerate(fid): + line = line.decode("ISO-8859-1").strip() + if in_ is None: + p = re_prim.match(line) + e = re_enum.match(line) + d = re_defi.match(line) + r = re_deri.match(line) + if p is not None: + t, s, d = p.groups() + s = int(s) + assert s not in fif["types"] + fif["types"][s] = [t, d] + elif e is not None: + # entering an enum + this_enum = e.group(1) + if this_enum not in fif: + used_enums.append(this_enum) + fif[this_enum] = dict() + con[this_enum] = dict() + in_ = fif[this_enum] + elif d is not None: + t, s, d = d.groups() + s = int(s) + fif["defines"][t] = [s, d] + elif r is not None: + t, s = r.groups() + s = int(s, 16) + fif["types"][s] = t + else: + assert not line.startswith("enum(") + assert not line.startswith("derived_type") + else: # in an enum + if line == "{": + continue + elif line == "}": + in_ = None + continue + t, s, d = re_enum_entry.match(line).groups() + s = int(s) + if t != "ecg" and s != 3: # ecg defined the same way + assert s not in in_ + in_[s] = [t, d] + + # + # Assertions + # + + # Version + mne_version = f"{FIFF.FIFFC_MAJOR_VERSION:d}.{FIFF.FIFFC_MINOR_VERSION:d}" + assert fiff_version == mne_version + unknowns = list() + + # Assert that all our constants are in the FIF def + assert "FIFFV_SSS_JOB_NOTHING" in dir(FIFF) + for name in sorted(dir(FIFF)): + if name.startswith("_") or name in _dir_ignore_names: + continue + check = None + val = getattr(FIFF, name) + if name in fif["defines"]: + assert fif["defines"][name][0] == val + elif name.startswith("FIFFC_"): + # Checked above + assert name in ( + "FIFFC_MAJOR_VERSION", + "FIFFC_MINOR_VERSION", + "FIFFC_VERSION", + ) + elif name.startswith("FIFFB_"): + check = "iod" + elif name.startswith("FIFFT_"): + check = "types" + elif name.startswith("FIFFV_"): + if name.startswith("FIFFV_MNE_") and name.endswith("_ORI"): + check = "mne_ori" + elif name.startswith("FIFFV_MNE_") and name.endswith("_COV"): + check = "covariance_type" + elif name.startswith("FIFFV_MNE_COORD"): + check = "coord" # weird wrapper + elif ( + name.endswith("_CH") + or "_QUAT_" in name + or name + in ( + "FIFFV_DIPOLE_WAVE", + "FIFFV_GOODNESS_FIT", + "FIFFV_HPI_ERR", + "FIFFV_HPI_G", + "FIFFV_HPI_MOV", + ) + ): + check = "ch_type" + elif name.startswith("FIFFV_SUBJ_"): + check = name.split("_")[2].lower() + elif name in ( + "FIFFV_POINT_LPA", + "FIFFV_POINT_NASION", + "FIFFV_POINT_RPA", + "FIFFV_POINT_INION", + ): + check = "cardinal_point" + else: + for check in used_enums: + if name.startswith("FIFFV_" + check.upper()): + break + else: + if name not in _tag_ignore_names: + raise RuntimeError(f"Could not find {name}") + assert check in used_enums, name + if "SSS" in check: + raise RuntimeError + elif name.startswith("FIFF_UNIT"): # units and multipliers + check = name.split("_")[1].lower() + elif name.startswith("FIFF_"): + check = "tags" + else: + unknowns.append((name, val)) + if check is not None and name not in _tag_ignore_names: + assert val in fif[check], f"{check}: {val}, {name}" + if val in con[check]: + msg = f"{name}='{con[check][val]}' ?" + assert _aliases.get(name) == con[check][val], msg + else: + con[check][val] = name + unknowns = "\n\t".join(f"{u[0]} ({u[1]})" for u in unknowns) + assert len(unknowns) == 0, f"Unknown types\n\t{unknowns}" + + # Assert that all the FIF defs are in our constants + assert set(fif.keys()) == set(con.keys()) + for key in sorted(set(fif.keys()) - {"defines"}): + this_fif, this_con = fif[key], con[key] + assert len(set(this_fif.keys())) == len(this_fif) + assert len(set(this_con.keys())) == len(this_con) + missing_from_con = sorted(set(this_con.keys()) - set(this_fif.keys())) + assert missing_from_con == [], key + if key not in _ignore_incomplete_enums: + missing_from_fif = sorted(set(this_fif.keys()) - set(this_con.keys())) + assert missing_from_fif == [], key + + # Assert that `coil_def.dat` has accurate descriptions of all enum(coil) + coil_def = _read_coil_defs() + coil_desc = np.array([c["desc"] for c in coil_def]) + coil_def = np.array([(c["coil_type"], c["accuracy"]) for c in coil_def], int) + mask = coil_def[:, 1] == FWD.COIL_ACCURACY_ACCURATE + coil_def = coil_def[mask, 0] + coil_desc = coil_desc[mask] + bad_list = [] + for key in fif["coil"]: + if key not in _missing_coil_def and key not in coil_def: + bad_list.append((f" {key},").ljust(10) + " # " + fif["coil"][key][1]) + assert len(bad_list) == 0, ( + "\nIn fiff-constants, missing from coil_def:\n" + "\n".join(bad_list) + ) + # Assert that enum(coil) has all `coil_def.dat` entries + for key, desc in zip(coil_def, coil_desc): + if key not in fif["coil"]: + bad_list.append((f" {key},").ljust(10) + " # " + desc) + assert len(bad_list) == 0, ( + "In coil_def, missing from fiff-constants:\n" + "\n".join(bad_list) + ) + + +@pytest.mark.parametrize( + "dict_, match, extras", + [ + ({**_dig_kind_named, **_dig_cardinal_named}, "FIFFV_POINT_", ()), + ( + _ch_kind_named, + "^FIFFV_.*_CH$", + (FIFF.FIFFV_DIPOLE_WAVE, FIFF.FIFFV_GOODNESS_FIT), + ), + pytest.param( + _coord_frame_named, + "FIFFV_(MNE_)?COORD_", + (), + marks=pytest.mark.xfail( + reason="Intentional mismatch tested by test_coord_frame_consistency", + ), + ), + (_ch_unit_named, "FIFF_UNIT_", ()), + (_ch_unit_mul_named, "FIFF_UNITM_", ()), + (_ch_coil_type_named, "FIFFV_COIL_", ()), + ], +) +def test_dict_completion(dict_, match, extras): + """Test readable dict completions.""" + regex = re.compile(match) + got = set(FIFF[key] for key in FIFF if regex.search(key) is not None) + for e in extras: + got.add(e) + want = set(dict_) + assert got == want, match + + +def test_coord_frame_consistency(): + """Test consistency between coord frame mappings.""" + all_frames = set( + key for key in dir(FIFF) if key.startswith(("FIFFV_COORD_", "FIFFV_MNE_COORD")) + ) + # ... but there are some frames that we never work in so let's cull those for now + ignore_frames = set( + f"FIFFV_COORD_{name}" + for name in """ + MRI_SLICE MRI_DISPLAY DICOM_DEVICE IMAGING_DEVICE + """.strip().split() + ) + ignore_frames |= set( + f"FIFFV_MNE_COORD_{name}" + for name in """ + DIGITIZER TUFTS_EEG FS_TAL_GTZ FS_TAL_LTZ + """.strip().split() + ) + assert ignore_frames.issubset(all_frames) + all_frames -= ignore_frames + all_ints = set(FIFF[key] for key in all_frames) + assert set(_frame_to_str) == all_ints + assert set(_verbose_frames) == all_ints + assert set(_coord_frame_named) == all_ints diff --git a/mne-python/source/mne/_fiff/tests/test_meas_info.py b/mne-python/source/mne/_fiff/tests/test_meas_info.py new file mode 100644 index 0000000000000000000000000000000000000000..24a6ca04e2617a8fd493890cfa726395d06a76fd --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_meas_info.py @@ -0,0 +1,1508 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import json +import pickle +import string +from datetime import date, datetime, timedelta, timezone +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_equal +from scipy import sparse + +from mne import ( + Annotations, + Epochs, + compute_covariance, + make_forward_solution, + make_sphere_model, + pick_info, + pick_types, + read_cov, + read_epochs, + read_events, + read_evokeds, + read_forward_solution, + setup_volume_source_space, + write_cov, + write_forward_solution, +) +from mne._fiff import meas_info, tag +from mne._fiff._digitization import DigPoint, _make_dig_points +from mne._fiff.constants import FIFF +from mne._fiff.meas_info import ( + RAW_INFO_FIELDS, + Info, + MNEBadsList, + _add_timedelta_to_stamp, + _bad_chans_comp, + _dt_to_stamp, + _force_update_info, + _get_valid_units, + _merge_info, + _read_extended_ch_info, + _stamp_to_dt, + anonymize_info, + create_info, + read_fiducials, + read_info, + write_fiducials, + write_info, +) +from mne._fiff.proj import Projection +from mne._fiff.tag import _coil_trans_to_loc, _loc_to_coil_trans +from mne._fiff.write import DATE_NONE, _generate_meas_id +from mne.channels import ( + equalize_channels, + make_standard_montage, + read_polhemus_fastscan, +) +from mne.datasets import testing +from mne.event import make_fixed_length_events +from mne.io import BaseRaw, RawArray, read_raw_ctf, read_raw_edf, read_raw_fif +from mne.minimum_norm import ( + apply_inverse, + make_inverse_operator, + read_inverse_operator, + write_inverse_operator, +) +from mne.transforms import Transform +from mne.utils import ( + _empty_hash, + _record_warnings, + assert_object_equal, + catch_logging, + object_diff, +) + +root_dir = Path(__file__).parents[2] +fiducials_fname = root_dir / "data" / "fsaverage" / "fsaverage-fiducials.fif" +base_dir = root_dir / "io" / "tests" / "data" +raw_fname = base_dir / "test_raw.fif" +chpi_fname = base_dir / "test_chpi_raw_sss.fif" +event_name = base_dir / "test-eve.fif" + +kit_data_dir = root_dir / "io" / "kit" / "tests" / "data" +hsp_fname = kit_data_dir / "test_hsp.txt" +elp_fname = kit_data_dir / "test_elp.txt" + +data_path = testing.data_path(download=False) +sss_path = data_path / "SSS" +sss_ctc_fname = sss_path / "test_move_anon_crossTalk_raw_sss.fif" +ctf_fname = data_path / "CTF" / "testdata_ctf.ds" +raw_invalid_bday_fname = data_path / "misc" / "sample_invalid_birthday_raw.fif" + + +@pytest.mark.parametrize( + "kwargs, want", + [ + (dict(meg=False, eeg=True), [0]), + (dict(meg=False, fnirs=True), [5]), + (dict(meg=False, fnirs="hbo"), [5]), + (dict(meg=False, fnirs="hbr"), []), + (dict(meg=False, misc=True), [1]), + (dict(meg=True), [2, 3, 4]), + (dict(meg="grad"), [2, 3]), + (dict(meg="planar1"), [2]), + (dict(meg="planar2"), [3]), + (dict(meg="mag"), [4]), + ], +) +def test_create_info_grad(kwargs, want): + """Test create_info behavior with grad coils.""" + info = create_info(6, 256, ["eeg", "misc", "grad", "grad", "mag", "hbo"]) + # Put these in an order such that grads get named "2" and "3", since + # they get picked based first on coil_type then ch_name... + assert [ + ch["ch_name"] + for ch in info["chs"] + if ch["coil_type"] == FIFF.FIFFV_COIL_VV_PLANAR_T1 + ] == ["2", "3"] + picks = pick_types(info, **kwargs) + assert_array_equal(picks, want) + + +def test_get_valid_units(): + """Test the valid units.""" + valid_units = _get_valid_units() + assert isinstance(valid_units, tuple) + assert all(isinstance(unit, str) for unit in valid_units) + assert "n/a" in valid_units + + +def test_coil_trans(): + """Test loc<->coil_trans functions.""" + rng = np.random.RandomState(0) + x = rng.randn(4, 4) + x[3] = [0, 0, 0, 1] + assert_allclose(_loc_to_coil_trans(_coil_trans_to_loc(x)), x) + x = rng.randn(12) + assert_allclose(_coil_trans_to_loc(_loc_to_coil_trans(x)), x) + + +def test_make_info(): + """Test some create_info properties.""" + n_ch = np.longlong(1) + info = create_info(n_ch, 1000.0, "eeg") + assert set(info.keys()) == set(RAW_INFO_FIELDS) + + coil_types = {ch["coil_type"] for ch in info["chs"]} + assert FIFF.FIFFV_COIL_EEG in coil_types + + pytest.raises(TypeError, create_info, ch_names="Test Ch", sfreq=1000) + pytest.raises(ValueError, create_info, ch_names=["Test Ch"], sfreq=-1000) + pytest.raises( + ValueError, + create_info, + ch_names=["Test Ch"], + sfreq=1000, + ch_types=["eeg", "eeg"], + ) + pytest.raises(TypeError, create_info, ch_names=[np.array([1])], sfreq=1000) + pytest.raises( + KeyError, create_info, ch_names=["Test Ch"], sfreq=1000, ch_types=np.array([1]) + ) + pytest.raises( + KeyError, create_info, ch_names=["Test Ch"], sfreq=1000, ch_types="awesome" + ) + pytest.raises( + TypeError, create_info, ["Test Ch"], sfreq=1000, montage=np.array([1]) + ) + m = make_standard_montage("biosemi32") + info = create_info(ch_names=m.ch_names, sfreq=1000.0, ch_types="eeg") + info.set_montage(m) + ch_pos = [ch["loc"][:3] for ch in info["chs"]] + ch_pos_mon = m._get_ch_pos() + ch_pos_mon = np.array([ch_pos_mon[ch_name] for ch_name in info["ch_names"]]) + # transform to head + ch_pos_mon += (0.0, 0.0, 0.04014) + assert_allclose(ch_pos, ch_pos_mon, atol=1e-5) + + +def test_duplicate_name_correction(): + """Test duplicate channel names with running number.""" + # When running number is possible + info = create_info(["A", "A", "A"], 1000.0, verbose="error") + assert info["ch_names"] == ["A-0", "A-1", "A-2"] + + # When running number is not possible but alpha numeric is + info = create_info(["A", "A", "A-0"], 1000.0, verbose="error") + assert info["ch_names"] == ["A-a", "A-1", "A-0"] + + # When a single addition is not sufficient + with pytest.raises(ValueError, match="Adding a single alphanumeric"): + ch_n = ["A", "A"] + # add all options for first duplicate channel (0) + ch_n.extend([f"{ch_n[0]}-{c}" for c in string.ascii_lowercase + "0"]) + create_info(ch_n, 1000.0, verbose="error") + + +def test_fiducials_io(tmp_path): + """Test fiducials i/o.""" + pts, coord_frame = read_fiducials(fiducials_fname) + assert pts[0]["coord_frame"] == FIFF.FIFFV_COORD_MRI + assert pts[0]["ident"] == FIFF.FIFFV_POINT_CARDINAL + + temp_fname = tmp_path / "test.fif" + write_fiducials(temp_fname, pts, coord_frame) + pts_1, coord_frame_1 = read_fiducials(temp_fname) + assert coord_frame == coord_frame_1 + for pt, pt_1 in zip(pts, pts_1): + assert pt["kind"] == pt_1["kind"] + assert pt["ident"] == pt_1["ident"] + assert pt["coord_frame"] == pt_1["coord_frame"] + assert_array_equal(pt["r"], pt_1["r"]) + assert isinstance(pt, DigPoint) + assert isinstance(pt_1, DigPoint) + + # test safeguards + pts[0]["coord_frame"] += 1 + with pytest.raises(ValueError, match="coord_frame entries that are incom"): + write_fiducials(temp_fname, pts, coord_frame, overwrite=True) + + +def test_info(): + """Test info object.""" + raw = read_raw_fif(raw_fname) + event_id, tmin, tmax = 1, -0.2, 0.5 + events = read_events(event_name) + event_id = int(events[0, 2]) + epochs = Epochs(raw, events[:1], event_id, tmin, tmax, picks=None) + + evoked = epochs.average() + + # Test subclassing was successful. + info = Info(a=7, b="aaaaa") + assert "a" in info + assert "b" in info + + # Test info attribute in API objects + for obj in [raw, epochs, evoked]: + assert isinstance(obj.info, Info) + rep = repr(obj.info) + assert "2002-12-03 19:01:10 UTC" in rep, rep + assert "146 items (3 Cardinal, 4 HPI, 61 EEG, 78 Extra)" in rep + dig_rep = repr(obj.info["dig"][0]) + assert "LPA" in dig_rep, dig_rep + assert "(-71.4, 0.0, 0.0) mm" in dig_rep, dig_rep + assert "head frame" in dig_rep, dig_rep + # Test our BunchConstNamed support + for func in (str, repr): + assert "4 (FIFFV_COORD_HEAD)" == func(obj.info["dig"][0]["coord_frame"]) + + # Test read-only fields + info = raw.info.copy() + nchan = len(info["chs"]) + ch_names = [ch["ch_name"] for ch in info["chs"]] + assert info["nchan"] == nchan + assert list(info["ch_names"]) == ch_names + + # Deleting of regular fields should work + info["experimenter"] = "bar" + del info["experimenter"] + + # Test updating of fields + del info["chs"][-1] + info._update_redundant() + assert info["nchan"] == nchan - 1 + assert list(info["ch_names"]) == ch_names[:-1] + + info["chs"][0]["ch_name"] = "foo" + info._update_redundant() + assert info["ch_names"][0] == "foo" + + # Test casting to and from a dict + info_dict = dict(info) + info2 = Info(info_dict) + assert info == info2 + + +def test_read_write_info(tmp_path): + """Test IO of info.""" + info = read_info(raw_fname) + temp_file = tmp_path / "info.fif" + # check for bug `#1198` + info["dev_head_t"]["trans"] = np.eye(4) + t1 = info["dev_head_t"]["trans"] + write_info(temp_file, info) + info2 = read_info(temp_file) + t2 = info2["dev_head_t"]["trans"] + assert len(info["chs"]) == len(info2["chs"]) + assert_array_equal(t1, t2) + # proc_history (e.g., GH#1875) + creator = "é" + info = read_info(chpi_fname) + info["proc_history"][0]["creator"] = creator + info["hpi_meas"][0]["creator"] = creator + info["subject_info"]["his_id"] = creator + info["subject_info"]["weight"] = 11.1 + info["subject_info"]["height"] = 2.3 + + with info._unlock(): + if info["gantry_angle"] is None: # future testing data may include it + info["gantry_angle"] = 0.0 # Elekta supine position + gantry_angle = info["gantry_angle"] + + meas_id = info["meas_id"] + with pytest.raises(FileExistsError, match="Destination file exists"): + write_info(temp_file, info) + write_info(temp_file, info, overwrite=True) + info = read_info(temp_file) + assert info["proc_history"][0]["creator"] == creator + assert info["hpi_meas"][0]["creator"] == creator + assert info["subject_info"]["his_id"] == creator + assert info["gantry_angle"] == gantry_angle + assert_allclose(info["subject_info"]["height"], 2.3) + assert_allclose(info["subject_info"]["weight"], 11.1) + for key in ["secs", "usecs", "version"]: + assert info["meas_id"][key] == meas_id[key] + assert_array_equal(info["meas_id"]["machid"], meas_id["machid"]) + + # Test that writing twice produces the same file + m1 = _empty_hash() + with open(temp_file, "rb") as fid: + m1.update(fid.read()) + m1 = m1.hexdigest() + temp_file_2 = tmp_path / "info2.fif" + assert temp_file_2 != temp_file + write_info(temp_file_2, info) + m2 = _empty_hash() + with open(str(temp_file_2), "rb") as fid: + m2.update(fid.read()) + m2 = m2.hexdigest() + assert m1 == m2 + + info = read_info(raw_fname) + with info._unlock(): + info["meas_date"] = None + anonymize_info(info, verbose="error") + assert info["meas_date"] is None + tmp_fname_3 = tmp_path / "info3.fif" + write_info(tmp_fname_3, info) + assert info["meas_date"] is None + info2 = read_info(tmp_fname_3) + assert info2["meas_date"] is None + + # Check that having a very old date in fine until you try to save it to fif + with info._unlock(check_after=True): + info["meas_date"] = datetime(1800, 1, 1, 0, 0, 0, tzinfo=timezone.utc) + fname = tmp_path / "test.fif" + with pytest.raises(RuntimeError, match="must be between "): + write_info(fname, info, overwrite=True) + + +@testing.requires_testing_data +def test_info_serialization_roundtrip(tmp_path): + """Test Info JSON serialization with real MEG data.""" + # Test with real MEG/FIF file + raw = read_raw_fif(raw_fname, preload=False, verbose=False) + _complete_info(raw.info) + info = raw.info.copy() + + # Save to JSON + json_path = tmp_path / "info.json" + with open(json_path, "w") as f: + json.dump(info.to_json_dict(), f) + + # Read back from JSON + with open(json_path) as f: + info_dict = json.load(f) + info_restored = Info.from_json_dict(info_dict) + + # Verify everything is exactly the same + assert_object_equal(info, info_restored) + + +def test_info_serialization_edf(tmp_path): + """Test Info JSON serialization with EDF data.""" + edf_path = root_dir / "io" / "edf" / "tests" / "data" / "test.edf" + raw = read_raw_edf(edf_path, preload=False, verbose=False) + info = raw.info.copy() + + # Save to JSON + json_path = tmp_path / "info_edf.json" + with open(json_path, "w") as f: + json.dump(info.to_json_dict(), f) + + # Read back from JSON + with open(json_path) as f: + info_dict = json.load(f) + info_restored = Info.from_json_dict(info_dict) + + # Verify everything is exactly the same + assert_object_equal(info, info_restored) + + +def test_info_serialization_special_types(): + """Test that special types (NamedInt, dates, etc.) are preserved correctly.""" + from mne.utils._bunch import NamedInt + + # Create info with various special types + info = create_info(ch_names=["EEG1"], sfreq=1000.0, ch_types="eeg") + + # Test meas_date (datetime) + meas_date = datetime(2023, 11, 13, 10, 30, 0, tzinfo=timezone.utc) + with info._unlock(): + info["meas_date"] = meas_date + + # Test subject_info with birthday (date) + info["subject_info"] = { + "id": 1, + "his_id": "SUBJ001", + "birthday": date(1990, 1, 15), + "sex": 1, + } + + # Roundtrip through JSON + info_dict = info.to_json_dict() + json_str = json.dumps(info_dict) + info_restored = Info.from_json_dict(json.loads(json_str)) + + # Verify special types are preserved + assert isinstance(info_restored["meas_date"], datetime) + assert info_restored["meas_date"] == meas_date + assert isinstance(info_restored["subject_info"]["birthday"], date) + assert info_restored["subject_info"]["birthday"] == date(1990, 1, 15) + assert isinstance(info_restored["custom_ref_applied"], NamedInt) + assert repr(info["custom_ref_applied"]) == repr(info_restored["custom_ref_applied"]) + + +@testing.requires_testing_data +def test_info_serialization_numpy_arrays(tmp_path): + """Test that numpy arrays (e.g., compensation matrices) serialize correctly.""" + # Use CTF data which has compensation matrices + raw = read_raw_ctf(ctf_fname, preload=False, verbose=False) + info = raw.info.copy() + + # Verify we have compensation data with matrices + assert len(info["comps"]) > 0, "CTF data should have compensation matrices" + + # Check the structure of compensation matrices before serialization + for comp in info["comps"]: + assert "data" in comp + assert "data" in comp["data"] + comp_matrix = comp["data"]["data"] + assert isinstance(comp_matrix, np.ndarray), ( + "Compensation matrix should be numpy array" + ) + assert comp_matrix.ndim == 2, "Compensation matrix should be 2D" + assert comp_matrix.shape[0] > 0 and comp_matrix.shape[1] > 0 + + # Save to JSON + json_path = tmp_path / "info_with_comps.json" + with open(json_path, "w") as f: + json.dump(info.to_json_dict(), f) + + # Read back from JSON + with open(json_path) as f: + info_dict = json.load(f) + info_restored = Info.from_json_dict(info_dict) + + # Verify compensation matrices are preserved correctly + assert len(info_restored["comps"]) == len(info["comps"]) + + for orig_comp, rest_comp in zip(info["comps"], info_restored["comps"]): + orig_matrix = orig_comp["data"]["data"] + rest_matrix = rest_comp["data"]["data"] + + # Verify it's a numpy array with correct shape + assert isinstance(rest_matrix, np.ndarray) + assert rest_matrix.shape == orig_matrix.shape + assert rest_matrix.ndim == 2 + + # Verify the actual values are preserved + assert_allclose(rest_matrix, orig_matrix, rtol=1e-10) + + # Verify row and column names are preserved + assert orig_comp["data"]["row_names"] == rest_comp["data"]["row_names"] + assert orig_comp["data"]["col_names"] == rest_comp["data"]["col_names"] + + # Use assert_object_equal for comprehensive check + assert_object_equal(info, info_restored) + + +@testing.requires_testing_data +def test_dir_warning(): + """Test that trying to read a bad filename emits a warning before an error.""" + with ( + pytest.raises(OSError, match="directory"), + pytest.warns(RuntimeWarning, match="does not conform"), + ): + read_info(ctf_fname) + + +def test_io_dig_points(tmp_path): + """Test Writing for dig files.""" + dest = tmp_path / "test.txt" + points2 = np.array([[-106.93, 99.80], [99.80, 68.81]]) + np.savetxt(dest, points2, delimiter="\t", newline="\n") + with pytest.raises(ValueError, match="must be of shape"): + with pytest.warns(RuntimeWarning, match="FastSCAN header"): + read_polhemus_fastscan(dest, on_header_missing="warn") + + +def test_io_coord_frame(tmp_path): + """Test round trip for coordinate frame.""" + fname = tmp_path / "test.fif" + for ch_type in ("eeg", "seeg", "ecog", "dbs", "hbo", "hbr"): + info = create_info(ch_names=["Test Ch"], sfreq=1000.0, ch_types=[ch_type]) + info["chs"][0]["loc"][:3] = [0.05, 0.01, -0.03] + write_info(fname, info, overwrite=True) + info2 = read_info(fname) + assert info2["chs"][0]["coord_frame"] == FIFF.FIFFV_COORD_HEAD + + +def test_make_dig_points(): + """Test application of Polhemus HSP to info.""" + extra_points = read_polhemus_fastscan(hsp_fname, on_header_missing="ignore") + info = create_info(ch_names=["Test Ch"], sfreq=1000.0) + assert info["dig"] is None + + with info._unlock(): + info["dig"] = _make_dig_points(extra_points=extra_points) + assert info["dig"] + assert_allclose(info["dig"][0]["r"], [-0.10693, 0.09980, 0.06881]) + + elp_points = read_polhemus_fastscan(elp_fname, on_header_missing="ignore") + nasion, lpa, rpa = elp_points[:3] + info = create_info(ch_names=["Test Ch"], sfreq=1000.0) + assert info["dig"] is None + + with info._unlock(): + info["dig"] = _make_dig_points(nasion, lpa, rpa, elp_points[3:], None) + assert info["dig"] + idx = [d["ident"] for d in info["dig"]].index(FIFF.FIFFV_POINT_NASION) + assert_allclose(info["dig"][idx]["r"], [0.0013930, 0.0131613, -0.0046967]) + pytest.raises(ValueError, _make_dig_points, nasion[:2]) + pytest.raises(ValueError, _make_dig_points, None, lpa[:2]) + pytest.raises(ValueError, _make_dig_points, None, None, rpa[:2]) + pytest.raises(ValueError, _make_dig_points, None, None, None, elp_points[:, :2]) + pytest.raises( + ValueError, _make_dig_points, None, None, None, None, elp_points[:, :2] + ) + + +def test_redundant(): + """Test some of the redundant properties of info.""" + # Indexing + info = create_info(ch_names=["a", "b", "c"], sfreq=1000.0) + assert info["ch_names"][0] == "a" + assert info["ch_names"][1] == "b" + assert info["ch_names"][2] == "c" + + # Equality + assert info["ch_names"] == info["ch_names"] + assert info["ch_names"] == ["a", "b", "c"] + + # No channels in info + info = create_info(ch_names=[], sfreq=1000.0) + assert info["ch_names"] == [] + + # List should be read-only + info = create_info(ch_names=["a", "b", "c"], sfreq=1000.0) + + +def test_merge_info(): + """Test merging of multiple Info objects.""" + info_a = create_info(ch_names=["a", "b", "c"], sfreq=1000.0) + info_b = create_info(ch_names=["d", "e", "f"], sfreq=1000.0) + info_merged = _merge_info([info_a, info_b]) + assert info_merged["nchan"], 6 + assert info_merged["ch_names"], ["a", "b", "c", "d", "e", "f"] + pytest.raises(ValueError, _merge_info, [info_a, info_a]) + + # Testing for force updates before merging + info_c = create_info(ch_names=["g", "h", "i"], sfreq=500.0) + # This will break because sfreq is not equal + pytest.raises(RuntimeError, _merge_info, [info_a, info_c]) + _force_update_info(info_a, info_c) + assert info_c["sfreq"] == info_a["sfreq"] + assert info_c["ch_names"][0] != info_a["ch_names"][0] + # Make sure it works now + _merge_info([info_a, info_c]) + # Check that you must supply Info + pytest.raises(ValueError, _force_update_info, info_a, dict([("sfreq", 1000.0)])) + # KIT System-ID + info_a._unlocked = info_b._unlocked = True + info_a["kit_system_id"] = 50 + assert _merge_info((info_a, info_b))["kit_system_id"] == 50 + info_b["kit_system_id"] = 50 + assert _merge_info((info_a, info_b))["kit_system_id"] == 50 + info_b["kit_system_id"] = 60 + pytest.raises(ValueError, _merge_info, (info_a, info_b)) + + # hpi infos + info_d = create_info(ch_names=["d", "e", "f"], sfreq=1000.0) + info_merged = _merge_info([info_a, info_d]) + assert not info_merged["hpi_meas"] + assert not info_merged["hpi_results"] + info_a["hpi_meas"] = [{"f1": 3, "f2": 4}] + assert _merge_info([info_a, info_d])["hpi_meas"] == info_a["hpi_meas"] + info_d._unlocked = True + info_d["hpi_meas"] = [{"f1": 3, "f2": 4}] + assert _merge_info([info_a, info_d])["hpi_meas"] == info_d["hpi_meas"] + # This will break because of inconsistency + info_d["hpi_meas"] = [{"f1": 3, "f2": 5}] + pytest.raises(ValueError, _merge_info, [info_a, info_d]) + + info_0 = read_info(raw_fname) + info_0["bads"] = ["MEG 2443", "EEG 053"] + assert len(info_0["chs"]) == 376 + assert len(info_0["dig"]) == 146 + info_1 = create_info(["STI YYY"], info_0["sfreq"], ["stim"]) + assert info_1["bads"] == [] + info_out = _merge_info([info_0, info_1], force_update_to_first=True) + assert len(info_out["chs"]) == 377 + assert len(info_out["bads"]) == 2 + assert len(info_out["dig"]) == 146 + assert len(info_0["chs"]) == 376 + assert len(info_0["bads"]) == 2 + assert len(info_0["dig"]) == 146 + + +def test_check_consistency(): + """Test consistency check of Info objects.""" + info = create_info(ch_names=["a", "b", "c"], sfreq=1000.0) + + # This should pass + info._check_consistency() + + # Info without any channels + info_empty = create_info(ch_names=[], sfreq=1000.0) + info_empty._check_consistency() + + # Bad channels that are not in the info object + info2 = info.copy() + with pytest.raises(ValueError, match="do not exist"): + info2["bads"] = ["b", "foo", "bar"] + + # Bad data types + info2 = info.copy() + with info2._unlock(): + info2["sfreq"] = "foo" + pytest.raises(ValueError, info2._check_consistency) + + info2 = info.copy() + with info2._unlock(): + info2["highpass"] = "foo" + pytest.raises(ValueError, info2._check_consistency) + + info2 = info.copy() + with info2._unlock(): + info2["lowpass"] = "foo" + pytest.raises(ValueError, info2._check_consistency) + + # Silent type conversion to float + info2 = info.copy() + with info2._unlock(check_after=True): + info2["sfreq"] = 1 + info2["highpass"] = 2 + info2["lowpass"] = 2 + assert isinstance(info2["sfreq"], float) + assert isinstance(info2["highpass"], float) + assert isinstance(info2["lowpass"], float) + + # Duplicate channel names + info2 = info.copy() + with info2._unlock(): + info2["chs"][2]["ch_name"] = "b" + pytest.raises(RuntimeError, info2._check_consistency) + + # Duplicates appended with running numbers + with pytest.warns(RuntimeWarning, match="Channel names are not"): + info3 = create_info(ch_names=["a", "b", "b", "c", "b"], sfreq=1000.0) + assert_array_equal(info3["ch_names"], ["a", "b-0", "b-1", "c", "b-2"]) + + # a few bad ones + idx = 0 + ch = info["chs"][idx] + for key, bad, match in ( + ("ch_name", 1.0, "must be an instance"), + ("loc", np.zeros(15), "12 elements"), + ("cal", np.ones(1), "numeric"), + ): + info._check_consistency() # okay + old = ch[key] + ch[key] = bad + if key == "ch_name": + info["ch_names"][idx] = bad + with pytest.raises(TypeError, match=match): + info._check_consistency() + ch[key] = old + if key == "ch_name": + info["ch_names"][idx] = old + + # bad channel entries + info2 = info.copy() + info2["chs"][0]["foo"] = "bar" + with pytest.raises(KeyError, match="key errantly present"): + info2._check_consistency() + info2 = info.copy() + del info2["chs"][0]["loc"] + with pytest.raises(KeyError, match="key missing"): + info2._check_consistency() + + # bad subject_info entries + info2 = info.copy() + with pytest.raises(TypeError, match="must be an instance"): + info2["subject_info"] = "bad" + info2["subject_info"] = dict() + with pytest.raises(TypeError, match="must be an instance"): + info2["subject_info"]["height"] = "bad" + with pytest.raises(TypeError, match="must be an instance"): + info2["subject_info"]["weight"] = [0] + with pytest.raises(TypeError, match=r'subject_info\["height"\] must be an .*'): + info2["subject_info"] = {"height": "bad"} + + +def _test_anonymize_info(base_info, tmp_path): + """Test that sensitive information can be anonymized.""" + pytest.raises(TypeError, anonymize_info, "foo") + assert isinstance(base_info, Info) + base_info = base_info.copy() + + default_anon_dos = datetime(2000, 1, 1, 0, 0, 0, tzinfo=timezone.utc) + default_str = "mne_anonymize" + default_subject_id = 0 + default_desc = "Anonymized using a time shift" + " to preserve age at acquisition" + + # Test no error for incomplete info + bad_info = base_info.copy() + bad_info.pop("file_id") + anonymize_info(bad_info) + del bad_info + + # Fake some additional data + _complete_info(base_info) + meas_date = datetime(2010, 1, 1, 0, 0, 0, tzinfo=timezone.utc) + with base_info._unlock(): + base_info["meas_date"] = meas_date + base_info["subject_info"].update( + birthday=date(1987, 4, 8), + his_id="foobar", + sex=1, + ) + + # generate expected info... + # first expected result with no options. + # will move DOS from 2010/1/1 to 2000/1/1 which is 3653 days. + exp_info = base_info.copy() + exp_info._unlocked = True + exp_info["description"] = default_desc + erase_strs = ( + ("experimenter",), + ("proj_name",), + ("subject_info", "first_name"), + ("subject_info", "middle_name"), + ("subject_info", "last_name"), + ("device_info", "site"), + ("device_info", "serial"), + ("helium_info", "orig_file_guid"), + ("proc_history", 0, "experimenter"), + ) + for tp in erase_strs: + this = exp_info + for lev in tp[:-1]: + this = this[lev] + this[tp[-1]] = default_str + exp_info["proj_id"] = 0 + for key in ("sex", "id", "height", "weight"): + exp_info["subject_info"][key] = 0 + exp_info["subject_info"]["his_id"] = str(default_subject_id) + del exp_info["subject_info"]["hand"] # there's no "unknown" setting + exp_info["utc_offset"] = None + exp_info["proc_history"][0]["block_id"]["machid"][:] = 0 + + # this bday is 3653 days different. the change in day is due to a + # different number of leap days between 1987 and 1977 than between + # 2010 and 2000. + exp_info["subject_info"]["birthday"] = date(1977, 4, 7) + exp_info["meas_date"] = default_anon_dos + exp_info._unlocked = False + + # make copies + exp_info_3 = exp_info.copy() + + # adjust each expected outcome + delta_t = timedelta(days=3653) + + def _adjust_back(e_i, dt): + for key in ("file_id", "meas_id"): + value = e_i.get(key) + if value is not None: + assert "msecs" not in value + tmp = _add_timedelta_to_stamp((value["secs"], value["usecs"]), -dt) + value["secs"] = tmp[0] + value["usecs"] = tmp[1] + value["machid"][:] = 0 + e_i["helium_info"]["meas_date"] -= dt + ds = int(round(dt.total_seconds())) + e_i["proc_history"][0]["date"] = ( + e_i["proc_history"][0]["date"][0] - ds, + e_i["proc_history"][0]["date"][1], + ) + e_i["proc_history"][0]["block_id"]["secs"] -= ds + + _adjust_back(exp_info, delta_t) + + # exp 2 tests the keep_his option + exp_info_2 = exp_info.copy() + with exp_info_2._unlock(): + exp_info_2["subject_info"]["his_id"] = "foobar" + exp_info_2["subject_info"]["sex"] = 1 + exp_info_2["subject_info"]["hand"] = 1 + + # exp 3 tests is a supplied daysback + delta_t_2 = timedelta(days=43) + with exp_info_3._unlock(): + exp_info_3["subject_info"]["birthday"] = date(1987, 2, 24) + exp_info_3["meas_date"] = meas_date - delta_t_2 + _adjust_back(exp_info_3, delta_t_2) + + # exp 4 tests is a supplied daysback + delta_t_3 = timedelta(days=223 + 364 * 500) + + def _check_equiv(got, want, err_msg): + __tracebackhide__ = True + fname_temp = tmp_path / "test.fif" + assert_object_equal(got, want, err_msg=err_msg) + write_info(fname_temp, got, reset_range=False, overwrite=True) + got = read_info(fname_temp) + # this gets changed on write but that's expected + with got._unlock(): + got["file_id"] = want["file_id"] + assert_object_equal(got, want, err_msg=f"{err_msg} (on I/O round trip)") + + new_info = anonymize_info(base_info.copy()) + _check_equiv(new_info, exp_info, err_msg="anon mismatch") + + new_info = anonymize_info(base_info.copy(), keep_his=True) + _check_equiv(new_info, exp_info_2, err_msg="anon keep_his mismatch") + + # keep only his_id + new_info = anonymize_info(base_info.copy(), keep_his="his_id") + assert new_info["subject_info"]["his_id"] == "foobar" + assert new_info["subject_info"]["sex"] == 0 + assert "hand" not in new_info["subject_info"] + + # keep only sex + new_info = anonymize_info(base_info.copy(), keep_his="sex") + assert new_info["subject_info"]["his_id"] == "0" + assert new_info["subject_info"]["sex"] == 1 + assert "hand" not in new_info["subject_info"] + + # keep only hand + new_info = anonymize_info(base_info.copy(), keep_his="hand") + assert new_info["subject_info"]["his_id"] == "0" + assert new_info["subject_info"]["sex"] == 0 + assert new_info["subject_info"]["hand"] == 1 + + # keep his_id and sex + new_info = anonymize_info(base_info.copy(), keep_his=["his_id", "sex"]) + assert new_info["subject_info"]["his_id"] == "foobar" + assert new_info["subject_info"]["sex"] == 1 + assert "hand" not in new_info["subject_info"] + + # keep only hand + new_info = anonymize_info(base_info.copy(), keep_his=["hand"]) + assert new_info["subject_info"]["his_id"] == "0" + assert new_info["subject_info"]["sex"] == 0 + assert new_info["subject_info"]["hand"] == 1 + + # keep his_id and hand + new_info = anonymize_info(base_info.copy(), keep_his=("his_id", "hand")) + assert new_info["subject_info"]["his_id"] == "foobar" + assert new_info["subject_info"]["sex"] == 0 + assert new_info["subject_info"]["hand"] == 1 + + # invalid keep_his values + with pytest.raises(ValueError, match="Invalid value"): + anonymize_info(base_info.copy(), keep_his="invalid_field") + + with pytest.raises(ValueError, match="Invalid value"): + anonymize_info(base_info.copy(), keep_his=["his_id", "invalid"]) + + new_info = anonymize_info(base_info.copy(), daysback=delta_t_2.days) + _check_equiv(new_info, exp_info_3, err_msg="anon daysback mismatch") + + with pytest.raises(RuntimeError, match="anonymize_info generated"): + anonymize_info(base_info.copy(), daysback=delta_t_3.days) + + # test with meas_date = None + with base_info._unlock(): + base_info["meas_date"] = None + with exp_info_3._unlock(): + exp_info_3["meas_date"] = None + exp_info_3["helium_info"]["meas_date"] = None + for var in ( + exp_info_3["file_id"], + exp_info_3["meas_id"], + exp_info_3["proc_history"][0]["block_id"], + ): + var["secs"] = DATE_NONE[0] + var["usecs"] = DATE_NONE[1] + exp_info_3["subject_info"].pop("birthday", None) + exp_info_3["proc_history"][0]["date"] = DATE_NONE + + if base_info["meas_date"] is None: + with pytest.warns(RuntimeWarning, match="all information"): + new_info = anonymize_info(base_info.copy(), daysback=delta_t_2.days) + else: + new_info = anonymize_info(base_info.copy(), daysback=delta_t_2.days) + _check_equiv( + new_info, + exp_info_3, + err_msg="meas_date=None daysback mismatch", + ) + + with _record_warnings(): # meas_date is None + new_info = anonymize_info(base_info.copy()) + _check_equiv(new_info, exp_info_3, err_msg="meas_date=None mismatch") + + +@pytest.mark.parametrize( + "stamp, dt", + [ + [(1346981585, 835782), (2012, 9, 7, 1, 33, 5, 835782)], + # test old dates for BIDS anonymization + [(-1533443343, 24382), (1921, 5, 29, 19, 30, 57, 24382)], + # gh-7116 + [(-908196946, 988669), (1941, 3, 22, 11, 4, 14, 988669)], + ], +) +def test_meas_date_convert(stamp, dt): + """Test conversions of meas_date to datetime objects.""" + meas_datetime = _stamp_to_dt(stamp) + stamp2 = _dt_to_stamp(meas_datetime) + assert stamp == stamp2 + assert meas_datetime == datetime(*dt, tzinfo=timezone.utc) + # smoke test for info __repr__ + info = create_info(1, 1000.0, "eeg") + with info._unlock(): + info["meas_date"] = meas_datetime + assert str(dt[0]) in repr(info) + + +def test_birthday_input(): + """Test that birthday input is handled correctly.""" + pd = pytest.importorskip("pandas") + + # Test valid date + info = create_info(ch_names=["EEG 001"], sfreq=1000.0, ch_types="eeg") + info["subject_info"] = {} + info["subject_info"]["birthday"] = date(2000, 1, 1) + assert info["subject_info"]["birthday"] == date(2000, 1, 1) + + # pandas Timestamp should convert to datetime date + info["subject_info"]["birthday"] = pd.Timestamp("2000-01-01") + assert info["subject_info"]["birthday"] == date(2000, 1, 1) + # Ensure we've converted it during setting + assert not isinstance(info["subject_info"]["birthday"], pd.Timestamp) + + # Test invalid date raises error + with pytest.raises(TypeError, match="must be an instance of date"): + info["subject_info"]["birthday"] = "not a date" + + +def _complete_info(info): + """Complete the meas info fields.""" + for key in ("file_id", "meas_id"): + assert info[key] is not None + info["subject_info"] = dict( + id=1, + sex=1, + hand=1, + first_name="a", + middle_name="b", + last_name="c", + his_id="d", + birthday=date(2000, 1, 1), + weight=1.0, + height=2.0, + ) + info["helium_info"] = dict( + he_level_raw=np.float32(12.34), + helium_level=np.float32(45.67), + meas_date=datetime(2024, 11, 14, 14, 8, 2, tzinfo=timezone.utc), + orig_file_guid="e", + ) + info["experimenter"] = "f" + info["description"] = "g" + with info._unlock(): + info["proj_id"] = 1 + info["proj_name"] = "h" + info["utc_offset"] = "i" + d = (1717707794, 2) + info["proc_history"] = [ + dict( + block_id=dict( + version=4, + machid=np.ones(2, int), + secs=d[0], + usecs=d[1], + ), + experimenter="j", + max_info=dict( + max_st=dict(), + sss_ctc=dict(), + sss_cal=dict(), + sss_info=dict(in_order=8), + ), + date=d, + ), + ] + info["device_info"] = dict(serial="k", site="l") + info._check_consistency() + + +def test_anonymize(tmp_path): + """Test that sensitive information can be anonymized.""" + pytest.raises(TypeError, anonymize_info, "foo") + + # Fake some subject data + raw = read_raw_fif(raw_fname) + _complete_info(raw.info) + raw.set_annotations( + Annotations(onset=[0, 1], duration=[1, 1], description="dummy", orig_time=None) + ) + first_samp = raw.first_samp + expected_onset = np.arange(2) + raw._first_time + assert raw.first_samp == first_samp + assert_allclose(raw.annotations.onset, expected_onset) + + # test mne.anonymize_info() + events = read_events(event_name) + epochs = Epochs(raw, events[:1], 2, 0.0, 0.1, baseline=None) + _test_anonymize_info(raw.info, tmp_path) + _test_anonymize_info(epochs.info, tmp_path) + + # test instance methods & I/O roundtrip + for inst, keep_his in zip((raw, epochs), (True, False)): + inst = inst.copy() + + subject_info = dict(his_id="Volunteer", sex=2, hand=1) + inst.info["subject_info"] = subject_info + inst.anonymize(keep_his=keep_his) + + si = inst.info["subject_info"] + if keep_his: + assert si == subject_info + else: + assert si["his_id"] == "0" + assert si["sex"] == 0 + assert "hand" not in si + + # write to disk & read back + inst_type = "raw" if isinstance(inst, BaseRaw) else "epo" + fname = "tmp_raw.fif" if inst_type == "raw" else "tmp_epo.fif" + out_path = tmp_path / fname + inst.save(out_path, overwrite=True) + if inst_type == "raw": + read_raw_fif(out_path) + else: + read_epochs(out_path) + + # test that annotations are correctly zeroed + raw.anonymize() + assert raw.first_samp == first_samp + assert_allclose(raw.annotations.onset, expected_onset) + assert raw.annotations.orig_time == raw.info["meas_date"] + stamp = _dt_to_stamp(raw.info["meas_date"]) + assert raw.annotations.orig_time == _stamp_to_dt(stamp) + + with raw.info._unlock(): + raw.info["meas_date"] = None + raw.anonymize(daysback=None) + with pytest.warns(RuntimeWarning, match="None"): + raw.anonymize(daysback=123) + assert raw.annotations.orig_time is None + assert raw.first_samp == first_samp + assert_allclose(raw.annotations.onset, expected_onset) + + +@pytest.mark.parametrize("daysback", [None, 28826]) +def test_anonymize_with_io(tmp_path, daysback): + """Test that IO does not break anonymization and all fields.""" + raw = read_raw_fif(raw_fname).crop(0, 1) + _complete_info(raw.info) + temp_path = tmp_path / "tmp_raw.fif" + raw.save(temp_path) + raw2 = read_raw_fif(temp_path).load_data() + raw2.anonymize(daysback=daysback) + raw2.save(temp_path, overwrite=True) + raw3 = read_raw_fif(temp_path) + d = object_diff(raw2.info, raw3.info) + assert d == "['file_id']['machid'] array mismatch\n" + + +@testing.requires_testing_data +def test_csr_csc(tmp_path): + """Test CSR and CSC.""" + info = read_info(sss_ctc_fname) + info = pick_info(info, pick_types(info, meg=True, exclude=[])) + sss_ctc = info["proc_history"][0]["max_info"]["sss_ctc"] + ct = sss_ctc["decoupler"].copy() + # CSC + assert isinstance(ct, sparse.csc_array) + fname = tmp_path / "test.fif" + write_info(fname, info) + info_read = read_info(fname) + ct_read = info_read["proc_history"][0]["max_info"]["sss_ctc"]["decoupler"] + assert isinstance(ct_read, sparse.csc_array) + assert_array_equal(ct_read.toarray(), ct.toarray()) + # Now CSR + csr = ct.tocsr() + assert isinstance(csr, sparse.csr_array) + assert_array_equal(csr.toarray(), ct.toarray()) + info["proc_history"][0]["max_info"]["sss_ctc"]["decoupler"] = csr + fname = tmp_path / "test1.fif" + write_info(fname, info) + info_read = read_info(fname) + ct_read = info_read["proc_history"][0]["max_info"]["sss_ctc"]["decoupler"] + assert isinstance(ct_read, sparse.csc_array) # this gets cast to CSC + assert_array_equal(ct_read.toarray(), ct.toarray()) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_check_compensation_consistency(): + """Test check picks compensation.""" + raw = read_raw_ctf(ctf_fname, preload=False) + events = make_fixed_length_events(raw, 99999) + picks = pick_types(raw.info, meg=True, exclude=[], ref_meg=True) + pick_ch_names = [raw.info["ch_names"][idx] for idx in picks] + for comp, expected_result in zip([0, 1], [False, False]): + raw.apply_gradient_compensation(comp) + ret, missing = _bad_chans_comp(raw.info, pick_ch_names) + assert ret == expected_result + assert len(missing) == 0 + Epochs(raw, events, None, -0.2, 0.2, preload=False, picks=picks) + + picks = pick_types(raw.info, meg=True, exclude=[], ref_meg=False) + pick_ch_names = [raw.info["ch_names"][idx] for idx in picks] + + for comp, expected_result in zip([0, 1], [False, True]): + raw.apply_gradient_compensation(comp) + ret, missing = _bad_chans_comp(raw.info, pick_ch_names) + assert ret == expected_result + assert len(missing) == 17 + with catch_logging() as log: + Epochs( + raw, events, None, -0.2, 0.2, preload=False, picks=picks, verbose=True + ) + assert "Removing 5 compensators" in log.getvalue() + + +def test_field_round_trip(tmp_path): + """Test round-trip for new fields.""" + info = create_info(1, 1000.0, "eeg") + with info._unlock(): + for key in ("file_id", "meas_id"): + info[key] = _generate_meas_id() + info["device_info"] = dict(type="a", model="b", serial="c", site="d") + info["helium_info"] = dict( + he_level_raw=1.0, + helium_level=2.0, + orig_file_guid="e", + meas_date=_stamp_to_dt((1, 2)), + ) + fname = tmp_path / "temp-info.fif" + info.save(fname) + info_read = read_info(fname) + assert_object_equal(info, info_read) + with pytest.raises(TypeError, match="datetime"): + info["helium_info"]["meas_date"] = (1, 2) + # should allow it to be None, though (checking gh-13154) + info["helium_info"]["meas_date"] = None + info.save(fname, overwrite=True) + info_read = read_info(fname) + assert_object_equal(info, info_read) + assert info_read["helium_info"]["meas_date"] is None + # not 100% sure how someone could end up with it deleted, but should still be + # writeable + del info["helium_info"]["meas_date"] + info.save(fname, overwrite=True) + info_read = read_info(fname) + info["helium_info"]["meas_date"] = None # we always set it (which is reasonable) + assert_object_equal(info, info_read) + + +def test_equalize_channels(): + """Test equalization of channels for instances of Info.""" + info1 = create_info(["CH1", "CH2", "CH3"], sfreq=1.0) + info2 = create_info(["CH4", "CH2", "CH1"], sfreq=1.0) + info1, info2 = equalize_channels([info1, info2]) + + assert info1.ch_names == ["CH1", "CH2"] + assert info2.ch_names == ["CH1", "CH2"] + + +def test_repr(): + """Test Info repr.""" + info = create_info(1, 1000, "eeg") + assert "7 non-empty values" in repr(info) + + t = Transform("meg", "head", np.ones((4, 4))) + info["dev_head_t"] = t + assert "dev_head_t: MEG device -> head transform" in repr(info) + + +def test_repr_html(): + """Test Info HTML repr.""" + info = read_info(raw_fname) + assert "Projections" in info._repr_html_() + with info._unlock(): + info["projs"] = [] + assert "Projections" not in info._repr_html_() + info["bads"] = [] + assert "Bad " not in info._repr_html_() + info["bads"] = ["MEG 2443", "EEG 053"] + assert "Bad " in info._repr_html_() # 1 for each channel type + + html = info._repr_html_() + for ch in [ # good channel counts + "203", # grad + "102", # mag + "9", # stim + "59", # eeg + "1", # eog + ]: + assert ch in html + + +@testing.requires_testing_data +def test_invalid_subject_birthday(): + """Test handling of an invalid birthday in the raw file.""" + with pytest.warns(RuntimeWarning, match="No birthday will be set"): + raw = read_raw_fif(raw_invalid_bday_fname) + assert "birthday" not in raw.info["subject_info"] + + +def test_invalid_set_meas_date(): + """Test set_meas_date catches invalid str input.""" + info = create_info(1, 1000, "eeg") + with pytest.raises(TypeError, match=r"meas_date must be an instance of"): + info.set_meas_date("2025-01-01 00:00:00.000000") + + +@pytest.mark.slowtest +@pytest.mark.parametrize( + "fname", + [ + pytest.param(ctf_fname, marks=testing._pytest_mark()), + raw_fname, + ], +) +def test_channel_name_limit(tmp_path, monkeypatch, fname): + """Test that our remapping works properly.""" + # + # raw + # + if fname.suffix == ".fif": + raw = read_raw_fif(fname) + raw.pick(raw.ch_names[:3]) + ref_names = [] + data_names = raw.ch_names + else: + assert fname.suffix == ".ds" + raw = read_raw_ctf(fname) + ref_names = [ + raw.ch_names[pick] for pick in pick_types(raw.info, meg=False, ref_meg=True) + ] + data_names = raw.ch_names[32:35] + proj = dict( + data=np.ones((1, len(data_names))), + col_names=data_names[:2].copy(), + row_names=None, + nrow=1, + ) + proj = Projection(data=proj, active=False, desc="test", kind=0, explained_var=0.0) + raw.add_proj(proj, remove_existing=True) + raw.info.normalize_proj() + raw.pick(data_names + ref_names).crop(0, 2) + long_names = ["123456789abcdefg" + name for name in raw.ch_names] + fname = tmp_path / "test-raw.fif" + with catch_logging() as log: + raw.save(fname) + log = log.getvalue() + assert "truncated" not in log + rename = dict(zip(raw.ch_names, long_names)) + long_data_names = [rename[name] for name in data_names] + long_proj_names = long_data_names[:2] + raw.rename_channels(rename) + for comp in raw.info["comps"]: + for key in ("row_names", "col_names"): + for name in comp["data"][key]: + assert name in raw.ch_names + if raw.info["comps"]: + assert raw.compensation_grade == 0 + raw.apply_gradient_compensation(3) + assert raw.compensation_grade == 3 + assert len(raw.info["projs"]) == 1 + assert raw.info["projs"][0]["data"]["col_names"] == long_proj_names + raw.info["bads"] = bads = long_data_names[2:3] + good_long_data_names = [name for name in long_data_names if name not in bads] + with catch_logging() as log: + raw.save(fname, overwrite=True, verbose=True) + log = log.getvalue() + assert "truncated to 15" in log + for name in raw.ch_names: + assert len(name) > 15 + # first read the full way + with catch_logging() as log: + raw_read = read_raw_fif(fname, verbose=True) + log = log.getvalue() + assert "Reading extended channel information" in log + for ra in (raw, raw_read): + assert ra.ch_names == long_names + assert raw_read.info["projs"][0]["data"]["col_names"] == long_proj_names + del raw_read + # next read as if no longer names could be read + monkeypatch.setattr(meas_info, "_read_extended_ch_info", lambda x, y, z: None) + with catch_logging() as log: + raw_read = read_raw_fif(fname, verbose=True) + log = log.getvalue() + assert "extended" not in log + if raw.info["comps"]: + assert raw_read.compensation_grade == 3 + raw_read.apply_gradient_compensation(0) + assert raw_read.compensation_grade == 0 + monkeypatch.setattr( # restore + meas_info, "_read_extended_ch_info", _read_extended_ch_info + ) + short_proj_names = [ + f"{name[: 13 - bool(len(ref_names))]}-{ni}" + for ni, name in enumerate(long_proj_names) + ] + assert raw_read.info["projs"][0]["data"]["col_names"] == short_proj_names + # + # epochs + # + epochs = Epochs(raw, make_fixed_length_events(raw)) + fname = tmp_path / "test-epo.fif" + epochs.save(fname) + epochs_read = read_epochs(fname) + for ep in (epochs, epochs_read): + assert ep.info["ch_names"] == long_names + assert ep.ch_names == long_names + del raw, epochs_read + # cov + epochs.info["bads"] = [] + cov = compute_covariance(epochs, verbose="error") + fname = tmp_path / "test-cov.fif" + write_cov(fname, cov) + cov_read = read_cov(fname) + for co in (cov, cov_read): + assert co["names"] == long_data_names + assert co["bads"] == [] + del cov_read + + # + # evoked + # + evoked = epochs.average() + evoked.info["bads"] = bads + assert evoked.nave == 1 + fname = tmp_path / "test-ave.fif" + evoked.save(fname) + evoked_read = read_evokeds(fname)[0] + for ev in (evoked, evoked_read): + assert ev.ch_names == long_names + assert ev.info["bads"] == bads + del evoked_read, epochs + + # + # forward + # + with _record_warnings(): # not enough points for CTF + sphere = make_sphere_model("auto", "auto", evoked.info) + src = setup_volume_source_space(pos=dict(rr=[[0, 0, 0.04]], nn=[[0, 1.0, 0.0]])) + fwd = make_forward_solution(evoked.info, None, src, sphere) + fname = tmp_path / "temp-fwd.fif" + write_forward_solution(fname, fwd) + fwd_read = read_forward_solution(fname) + for fw in (fwd, fwd_read): + assert fw["sol"]["row_names"] == long_data_names + assert fw["info"]["ch_names"] == long_data_names + assert fw["info"]["bads"] == bads + del fwd_read + + # + # inv + # + inv = make_inverse_operator(evoked.info, fwd, cov) + fname = tmp_path / "test-inv.fif" + write_inverse_operator(fname, inv) + inv_read = read_inverse_operator(fname) + for iv in (inv, inv_read): + assert iv["info"]["ch_names"] == good_long_data_names + apply_inverse(evoked, inv) # smoke test + + +@pytest.mark.parametrize("protocol", ("highest", "default")) +@pytest.mark.parametrize("fname_info", (raw_fname, "create_info")) +@pytest.mark.parametrize("unlocked", (True, False)) +def test_pickle(fname_info, unlocked, protocol): + """Test that Info can be (un)pickled.""" + if fname_info == "create_info": + info = create_info(3, 1000.0, "eeg") + else: + info = read_info(fname_info) + protocol = getattr(pickle, f"{protocol.upper()}_PROTOCOL") + assert isinstance(info["bads"], MNEBadsList) + info["bads"] = info["ch_names"][:1] + assert not info._unlocked + info._unlocked = unlocked + data = pickle.dumps(info, protocol=protocol) + info_un = pickle.loads(data) # nosec B301 + assert isinstance(info_un, Info) + assert_object_equal(info, info_un) + assert info_un._unlocked == unlocked + assert isinstance(info_un["bads"], MNEBadsList) + assert info_un["bads"]._mne_info is info_un + + +def test_info_bad(): + """Test our info sanity checkers.""" + info = create_info(5, 1000.0, "eeg") + info["description"] = "foo" + info["experimenter"] = "bar" + info["line_freq"] = 50.0 + info["bads"] = info["ch_names"][:1] + info["temp"] = ("whatever", 1.0) + + with pytest.raises(RuntimeError, match=r"info\['temp'\]"): + info["bad_key"] = 1.0 + for key, match in [("sfreq", r"inst\.resample"), ("chs", r"inst\.add_channels")]: + with pytest.raises(RuntimeError, match=match): + info[key] = info[key] + with pytest.raises(ValueError, match="between meg<->head"): + info["dev_head_t"] = Transform("mri", "head", np.eye(4)) + assert isinstance(info["bads"], MNEBadsList) + with pytest.raises(ValueError, match="do not exist in info"): + info["bads"] = ["foo"] + assert isinstance(info["bads"], MNEBadsList) + with pytest.raises(ValueError, match="do not exist in info"): + info["bads"] += ["foo"] + assert isinstance(info["bads"], MNEBadsList) + with pytest.raises(ValueError, match="do not exist in info"): + info["bads"].append("foo") + assert isinstance(info["bads"], MNEBadsList) + with pytest.raises(ValueError, match="do not exist in info"): + info["bads"].extend(["foo"]) + assert isinstance(info["bads"], MNEBadsList) + x = info["bads"] + with pytest.raises(ValueError, match="do not exist in info"): + x.append("foo") + assert info["bads"] == info["ch_names"][:1] # unchonged + x = info["bads"] + info["ch_names"][1:2] + assert x == info["ch_names"][:2] + assert not isinstance(x, MNEBadsList) # plain list + x = info["ch_names"][1:2] + info["bads"] + assert x == info["ch_names"][1::-1] # like [1, 0] in fancy indexing + assert not isinstance(x, MNEBadsList) # plain list + + +def test_get_montage(): + """Test ContainsMixin.get_montage().""" + ch_names = make_standard_montage("standard_1020").ch_names + sfreq = 512 + data = np.zeros((len(ch_names), sfreq * 2)) + raw = RawArray(data, create_info(ch_names, sfreq, "eeg")) + raw.set_montage("standard_1020") + + assert len(raw.get_montage().ch_names) == len(ch_names) + raw.info["bads"] = [ch_names[0]] + assert len(raw.get_montage().ch_names) == len(ch_names) + + # test info + raw = RawArray(data, create_info(ch_names, sfreq, "eeg")) + raw.set_montage("standard_1020") + + assert len(raw.info.get_montage().ch_names) == len(ch_names) + raw.info["bads"] = [ch_names[0]] + assert len(raw.info.get_montage().ch_names) == len(ch_names) + + +def test_tag_consistency(): + """Test that structures for tag reading are consistent.""" + call_set = set(tag._call_dict) + call_names = set(tag._call_dict_names) + assert call_set == call_names, "Mismatch between _call_dict and _call_dict_names" + # TODO: This was inspired by FIFF_DIG_STRING gh-13083, we should ideally add a test + # that those dig points can actually be read in correctly at some point. + + +def test_proj_id_entries(): + """Test that proj_id entries are the right type.""" + info = create_info(5, 1000.0, "eeg") + info["proj_id"] = 123 + # Boolean should be cast into an int + info["proj_id"] = True + with pytest.raises(TypeError, match="must be an instance"): + info["proj_id"] = "bad" + with pytest.raises(TypeError, match="must be an instance"): + info["proj_id"] = np.array([123]) diff --git a/mne-python/source/mne/_fiff/tests/test_pick.py b/mne-python/source/mne/_fiff/tests/test_pick.py new file mode 100644 index 0000000000000000000000000000000000000000..5d1b24247abee845e08901e0321c6727681aaaad --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_pick.py @@ -0,0 +1,764 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from copy import deepcopy +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_array_equal + +from mne import ( + Epochs, + channel_indices_by_type, + channel_type, + create_info, + make_ad_hoc_cov, + pick_channels, + pick_channels_cov, + pick_channels_regexp, + pick_info, + pick_types, + pick_types_forward, + read_forward_solution, + rename_channels, +) +from mne._fiff.constants import FIFF +from mne._fiff.pick import ( + _DATA_CH_TYPES_SPLIT, + _contains_ch_type, + _picks_by_type, + _picks_to_idx, + get_channel_type_constants, +) +from mne.channels import make_standard_montage +from mne.datasets import testing +from mne.io import ( + RawArray, + read_info, + read_raw_bti, + read_raw_fif, + read_raw_kit, +) +from mne.preprocessing import compute_current_source_density +from mne.utils import assert_object_equal, catch_logging + +data_path = testing.data_path(download=False) +fname_meeg = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" +fname_mc = data_path / "SSS" / "test_move_anon_movecomp_raw_sss.fif" + +io_dir = Path(__file__).parents[2] / "io" +ctf_fname = io_dir / "tests" / "data" / "test_ctf_raw.fif" +fif_fname = io_dir / "tests" / "data" / "test_raw.fif" + + +def _picks_by_type_old(info, meg_combined=False, ref_meg=False, exclude="bads"): + """Use the old, slower _picks_by_type code.""" + picks_list = [] + has = [_contains_ch_type(info, k) for k in _DATA_CH_TYPES_SPLIT] + has = dict(zip(_DATA_CH_TYPES_SPLIT, has)) + if has["mag"] and (meg_combined is not True or not has["grad"]): + picks_list.append( + ( + "mag", + pick_types( + info, + meg="mag", + eeg=False, + stim=False, + ref_meg=ref_meg, + exclude=exclude, + ), + ) + ) + if has["grad"] and (meg_combined is not True or not has["mag"]): + picks_list.append( + ( + "grad", + pick_types( + info, + meg="grad", + eeg=False, + stim=False, + ref_meg=ref_meg, + exclude=exclude, + ), + ) + ) + if has["mag"] and has["grad"] and meg_combined is True: + picks_list.append( + ( + "meg", + pick_types( + info, + meg=True, + eeg=False, + stim=False, + ref_meg=ref_meg, + exclude=exclude, + ), + ) + ) + for ch_type in _DATA_CH_TYPES_SPLIT: + if ch_type in ["grad", "mag"]: # exclude just MEG channels + continue + if has[ch_type]: + picks_list.append( + ( + ch_type, + pick_types( + info, + meg=False, + stim=False, + ref_meg=ref_meg, + exclude=exclude, + **{ch_type: True}, + ), + ) + ) + return picks_list + + +def _channel_type_old(info, idx): + """Get channel type using old, slower scheme.""" + ch = info["chs"][idx] + + # iterate through all defined channel types until we find a match with ch + # go in order from most specific (most rules entries) to least specific + channel_types = sorted( + get_channel_type_constants().items(), key=lambda x: len(x[1]), reverse=True + ) + for t, rules in channel_types: + for key, vals in rules.items(): # all keys must match the values + if ch.get(key, None) not in np.array(vals): + break # not channel type t, go to next iteration + else: + return t + + raise ValueError(f"Unknown channel type for {ch['ch_name']}") + + +def _assert_channel_types(info): + for k in range(info["nchan"]): + a, b = channel_type(info, k), _channel_type_old(info, k) + assert a == b + + +def test_pick_refs(): + """Test picking of reference sensors.""" + infos = list() + # KIT + kit_dir = io_dir / "kit" / "tests" / "data" + sqd_path = kit_dir / "test.sqd" + mrk_path = kit_dir / "test_mrk.sqd" + elp_path = kit_dir / "test_elp.txt" + hsp_path = kit_dir / "test_hsp.txt" + raw_kit = read_raw_kit(sqd_path, str(mrk_path), str(elp_path), str(hsp_path)) + infos.append(raw_kit.info) + # BTi + bti_dir = io_dir / "bti" / "tests" / "data" + bti_pdf = bti_dir / "test_pdf_linux" + bti_config = bti_dir / "test_config_linux" + bti_hs = bti_dir / "test_hs_linux" + raw_bti = read_raw_bti(bti_pdf, bti_config, bti_hs, preload=False) + infos.append(raw_bti.info) + # CTF + fname_ctf_raw = io_dir / "tests" / "data" / "test_ctf_comp_raw.fif" + raw_ctf = read_raw_fif(fname_ctf_raw) + raw_ctf.apply_gradient_compensation(2) + for info in infos: + info["bads"] = [] + _assert_channel_types(info) + with pytest.raises(ValueError, match="'planar2'] or bool, not foo"): + pick_types(info, meg="foo") + with pytest.raises(ValueError, match="'planar2', 'auto'] or bool,"): + pick_types(info, ref_meg="foo") + picks_meg_ref = pick_types(info, meg=True, ref_meg=True) + picks_meg = pick_types(info, meg=True, ref_meg=False) + picks_ref = pick_types(info, meg=False, ref_meg=True) + assert_array_equal( + picks_meg_ref, np.sort(np.concatenate([picks_meg, picks_ref])) + ) + picks_grad = pick_types(info, meg="grad", ref_meg=False) + picks_ref_grad = pick_types(info, meg=False, ref_meg="grad") + picks_meg_ref_grad = pick_types(info, meg="grad", ref_meg="grad") + assert_array_equal( + picks_meg_ref_grad, np.sort(np.concatenate([picks_grad, picks_ref_grad])) + ) + picks_mag = pick_types(info, meg="mag", ref_meg=False) + picks_ref_mag = pick_types(info, meg=False, ref_meg="mag") + picks_meg_ref_mag = pick_types(info, meg="mag", ref_meg="mag") + assert_array_equal( + picks_meg_ref_mag, np.sort(np.concatenate([picks_mag, picks_ref_mag])) + ) + assert_array_equal(picks_meg, np.sort(np.concatenate([picks_mag, picks_grad]))) + assert_array_equal( + picks_ref, np.sort(np.concatenate([picks_ref_mag, picks_ref_grad])) + ) + assert_array_equal( + picks_meg_ref, + np.sort( + np.concatenate([picks_grad, picks_mag, picks_ref_grad, picks_ref_mag]) + ), + ) + + for pick in ( + picks_meg_ref, + picks_meg, + picks_ref, + picks_grad, + picks_ref_grad, + picks_meg_ref_grad, + picks_mag, + picks_ref_mag, + picks_meg_ref_mag, + ): + if len(pick) > 0: + pick_info(info, pick) + + # test CTF expected failures directly + info = raw_ctf.info + info["bads"] = [] + picks_meg_ref = pick_types(info, meg=True, ref_meg=True) + picks_meg = pick_types(info, meg=True, ref_meg=False) + picks_ref = pick_types(info, meg=False, ref_meg=True) + picks_mag = pick_types(info, meg="mag", ref_meg=False) + picks_ref_mag = pick_types(info, meg=False, ref_meg="mag") + picks_meg_ref_mag = pick_types(info, meg="mag", ref_meg="mag") + for pick in (picks_meg_ref, picks_ref, picks_ref_mag, picks_meg_ref_mag): + if len(pick) > 0: + pick_info(info, pick) + + for pick in (picks_meg, picks_mag): + if len(pick) > 0: + with catch_logging() as log: + pick_info(info, pick, verbose=True) + assert ( + "Removing {} compensators".format(len(info["comps"])) in log.getvalue() + ) + picks_ref_grad = pick_types(info, meg=False, ref_meg="grad") + assert set(picks_ref_mag) == set(picks_ref) + assert len(picks_ref_grad) == 0 + all_meg = np.arange(3, 306) + assert_array_equal(np.concatenate([picks_ref, picks_meg]), all_meg) + assert_array_equal(picks_meg_ref_mag, all_meg) + + +def test_pick_channels_regexp(): + """Test pick with regular expression.""" + ch_names = ["MEG 2331", "MEG 2332", "MEG 2333"] + assert_array_equal(pick_channels_regexp(ch_names, "MEG ...1"), [0]) + assert_array_equal(pick_channels_regexp(ch_names, "MEG ...[2-3]"), [1, 2]) + assert_array_equal(pick_channels_regexp(ch_names, "MEG *"), [0, 1, 2]) + + +def assert_indexing(info, picks_by_type, ref_meg=False, all_data=True): + """Assert our indexing functions work properly.""" + # First that our old and new channel typing functions are equivalent + _assert_channel_types(info) + # Next that channel_indices_by_type works + if not ref_meg: + idx = channel_indices_by_type(info) + for key in idx: + for p in picks_by_type: + if key == p[0]: + assert_array_equal(idx[key], p[1]) + break + else: + assert len(idx[key]) == 0 + # Finally, picks_by_type (if relevant) + if not all_data: + picks_by_type = [p for p in picks_by_type if p[0] in _DATA_CH_TYPES_SPLIT] + picks_by_type = [(p[0], np.array(p[1], int)) for p in picks_by_type] + actual = _picks_by_type(info, ref_meg=ref_meg) + assert_object_equal(actual, picks_by_type) + if not ref_meg and idx["hbo"]: # our old code had a bug + with pytest.raises(TypeError, match="unexpected keyword argument"): + _picks_by_type_old(info, ref_meg=ref_meg) + else: + old = _picks_by_type_old(info, ref_meg=ref_meg) + assert_object_equal(old, picks_by_type) + # test bads + info = info.copy() + info["bads"] = [info["chs"][picks_by_type[0][1][0]]["ch_name"]] + picks_by_type = deepcopy(picks_by_type) + picks_by_type[0] = (picks_by_type[0][0], picks_by_type[0][1][1:]) + actual = _picks_by_type(info, ref_meg=ref_meg) + assert_object_equal(actual, picks_by_type) + + +def test_pick_seeg_ecog(): + """Test picking with sEEG and ECoG.""" + names = "A1 A2 Fz O OTp1 OTp2 E1 OTp3 E2 E3".split() + types = "mag mag eeg eeg seeg seeg ecog seeg ecog ecog".split() + info = create_info(names, 1024.0, types) + picks_by_type = [ + ("mag", [0, 1]), + ("eeg", [2, 3]), + ("seeg", [4, 5, 7]), + ("ecog", [6, 8, 9]), + ] + assert_indexing(info, picks_by_type) + assert_array_equal(pick_types(info, meg=False, seeg=True), [4, 5, 7]) + for i, t in enumerate(types): + assert channel_type(info, i) == types[i] + raw = RawArray(np.zeros((len(names), 10)), info) + events = np.array([[1, 0, 0], [2, 0, 0]]) + epochs = Epochs( + raw, + events=events, + event_id={"event": 0}, + tmin=-1e-5, + tmax=1e-5, + baseline=(0, 0), + ) # only one sample + evoked = epochs.average(pick_types(epochs.info, meg=True, seeg=True)) + e_seeg = evoked.copy().pick(picks="seeg") + for lt, rt in zip(e_seeg.ch_names, [names[4], names[5], names[7]]): + assert lt == rt + # Deal with constant debacle + raw = read_raw_fif(io_dir / "tests" / "data" / "test_chpi_raw_sss.fif") + assert len(pick_types(raw.info, meg=False, seeg=True, ecog=True)) == 0 + + +def test_pick_dbs(): + """Test picking with DBS.""" + # gh-8739 + names = "A1 A2 Fz O OTp1 OTp2 OTp3".split() + types = "mag mag eeg eeg dbs dbs dbs".split() + info = create_info(names, 1024.0, types) + picks_by_type = [("mag", [0, 1]), ("eeg", [2, 3]), ("dbs", [4, 5, 6])] + assert_indexing(info, picks_by_type) + assert_array_equal(pick_types(info, meg=False, dbs=True), [4, 5, 6]) + for i, t in enumerate(types): + assert channel_type(info, i) == types[i] + raw = RawArray(np.zeros((len(names), 7)), info) + events = np.array([[1, 0, 0], [2, 0, 0]]) + epochs = Epochs( + raw, + events=events, + event_id={"event": 0}, + tmin=-1e-5, + tmax=1e-5, + baseline=(0, 0), + ) # only one sample + evoked = epochs.average(pick_types(epochs.info, meg=True, dbs=True)) + e_dbs = evoked.copy().pick(picks="dbs") + for lt, rt in zip(e_dbs.ch_names, [names[4], names[5], names[6]]): + assert lt == rt + raw = read_raw_fif(io_dir / "tests" / "data" / "test_chpi_raw_sss.fif") + assert len(pick_types(raw.info, meg=False, dbs=True)) == 0 + + +def test_pick_chpi(): + """Test picking cHPI.""" + # Make sure we don't mis-classify cHPI channels + info = read_info(io_dir / "tests" / "data" / "test_chpi_raw_sss.fif") + _assert_channel_types(info) + channel_types = info.get_channel_types() + assert "chpi" in channel_types + assert "seeg" not in channel_types + assert "ecog" not in channel_types + + +def test_pick_csd(): + """Test picking current source density channels.""" + # Make sure we don't mis-classify cHPI channels + names = ["MEG 2331", "MEG 2332", "MEG 2333", "A1", "A2", "Fz"] + types = "mag mag grad csd csd csd".split() + info = create_info(names, 1024.0, types) + picks_by_type = [("mag", [0, 1]), ("grad", [2]), ("csd", [3, 4, 5])] + assert_indexing(info, picks_by_type, all_data=False) + + +def test_pick_bio(): + """Test picking BIO channels.""" + names = "A1 A2 Fz O BIO1 BIO2 BIO3".split() + types = "mag mag eeg eeg bio bio bio".split() + info = create_info(names, 1024.0, types) + picks_by_type = [("mag", [0, 1]), ("eeg", [2, 3]), ("bio", [4, 5, 6])] + assert_indexing(info, picks_by_type, all_data=False) + + +def test_pick_fnirs(): + """Test picking fNIRS channels.""" + names = "A1 A2 Fz O hbo1 hbo2 hbr1 fnirsRaw1 fnirsRaw2 fnirsOD1".split() + types = ( + "mag mag eeg eeg hbo hbo hbr fnirs_cw_" + "amplitude fnirs_cw_amplitude fnirs_od".split() + ) + info = create_info(names, 1024.0, types) + picks_by_type = [ + ("mag", [0, 1]), + ("eeg", [2, 3]), + ("hbo", [4, 5]), + ("hbr", [6]), + ("fnirs_cw_amplitude", [7, 8]), + ("fnirs_od", [9]), + ] + assert_indexing(info, picks_by_type) + + +def test_pick_ref(): + """Test picking ref_meg channels.""" + info = read_info(ctf_fname) + picks_by_type = [ + ("stim", [0]), + ("eog", [306, 307]), + ("ecg", [308]), + ("misc", [1]), + ("mag", np.arange(31, 306)), + ("ref_meg", np.arange(2, 31)), + ] + assert_indexing(info, picks_by_type, all_data=False) + picks_by_type.append( + ("mag", np.concatenate([picks_by_type.pop(-1)[1], picks_by_type.pop(-1)[1]])) + ) + assert_indexing(info, picks_by_type, ref_meg=True, all_data=False) + + +def _check_fwd_n_chan_consistent(fwd, n_expected): + n_ok = len(fwd["info"]["ch_names"]) + n_sol = fwd["sol"]["data"].shape[0] + assert n_expected == n_sol + assert n_expected == n_ok + + +@testing.requires_testing_data +def test_pick_forward_seeg_ecog(): + """Test picking forward with SEEG and ECoG.""" + fwd = read_forward_solution(fname_meeg) + counts = channel_indices_by_type(fwd["info"]) + for key in counts.keys(): + counts[key] = len(counts[key]) + counts["meg"] = counts["mag"] + counts["grad"] + fwd_ = pick_types_forward(fwd, meg=True) + _check_fwd_n_chan_consistent(fwd_, counts["meg"]) + fwd_ = pick_types_forward(fwd, meg=False, eeg=True) + _check_fwd_n_chan_consistent(fwd_, counts["eeg"]) + # should raise exception related to emptiness + pytest.raises(ValueError, pick_types_forward, fwd, meg=False, seeg=True) + pytest.raises(ValueError, pick_types_forward, fwd, meg=False, ecog=True) + # change last chan from EEG to sEEG, second-to-last to ECoG + ecog_name = "E1" + seeg_name = "OTp1" + rename_channels(fwd["info"], {"EEG 059": ecog_name}) + rename_channels(fwd["info"], {"EEG 060": seeg_name}) + for ch in fwd["info"]["chs"]: + if ch["ch_name"] == seeg_name: + ch["kind"] = FIFF.FIFFV_SEEG_CH + ch["coil_type"] = FIFF.FIFFV_COIL_EEG + elif ch["ch_name"] == ecog_name: + ch["kind"] = FIFF.FIFFV_ECOG_CH + ch["coil_type"] = FIFF.FIFFV_COIL_EEG + fwd["sol"]["row_names"][-1] = fwd["info"]["chs"][-1]["ch_name"] + fwd["sol"]["row_names"][-2] = fwd["info"]["chs"][-2]["ch_name"] + counts["eeg"] -= 2 + counts["seeg"] += 1 + counts["ecog"] += 1 + # repick & check + fwd_seeg = pick_types_forward(fwd, meg=False, seeg=True) + assert fwd_seeg["sol"]["row_names"] == [seeg_name] + assert fwd_seeg["info"]["ch_names"] == [seeg_name] + # should work fine + fwd_ = pick_types_forward(fwd, meg=True) + _check_fwd_n_chan_consistent(fwd_, counts["meg"]) + fwd_ = pick_types_forward(fwd, meg=False, eeg=True) + _check_fwd_n_chan_consistent(fwd_, counts["eeg"]) + fwd_ = pick_types_forward(fwd, meg=False, seeg=True) + _check_fwd_n_chan_consistent(fwd_, counts["seeg"]) + fwd_ = pick_types_forward(fwd, meg=False, ecog=True) + _check_fwd_n_chan_consistent(fwd_, counts["ecog"]) + + +def test_picks_by_channels(): + """Test creating pick_lists.""" + rng = np.random.RandomState(909) + + test_data = rng.random_sample((4, 2000)) + ch_names = [f"MEG {i:03d}" for i in [1, 2, 3, 4]] + ch_types = ["grad", "mag", "mag", "eeg"] + sfreq = 250.0 + info = create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types) + _assert_channel_types(info) + raw = RawArray(test_data, info) + + pick_list = _picks_by_type(raw.info) + assert len(pick_list) == 3 + assert pick_list[0][0] == "mag" + pick_list2 = _picks_by_type(raw.info, meg_combined=False) + assert len(pick_list) == len(pick_list2) + assert pick_list2[0][0] == "mag" + + pick_list2 = _picks_by_type(raw.info, meg_combined=True) + assert len(pick_list) == len(pick_list2) + 1 + assert pick_list2[0][0] == "meg" + + test_data = rng.random_sample((4, 2000)) + ch_names = [f"MEG {i:03d}" for i in [1, 2, 3, 4]] + ch_types = ["mag", "mag", "mag", "mag"] + sfreq = 250.0 + info = create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types) + raw = RawArray(test_data, info) + # This acts as a set, not an order + assert_array_equal( + pick_channels(info["ch_names"], ["MEG 002", "MEG 001"], ordered=False), [0, 1] + ) + + # Make sure checks for list input work. + pytest.raises(ValueError, pick_channels, ch_names, "MEG 001") + pytest.raises(ValueError, pick_channels, ch_names, ["MEG 001"], "hi") + + pick_list = _picks_by_type(raw.info) + assert len(pick_list) == 1 + assert pick_list[0][0] == "mag" + pick_list2 = _picks_by_type(raw.info, meg_combined=True) + assert len(pick_list) == len(pick_list2) + assert pick_list2[0][0] == "mag" + + # pick_types type check + with pytest.raises(ValueError, match="must be of type"): + raw.pick_types(eeg="string") + + # duplicate check + names = ["MEG 002", "MEG 002"] + assert len(pick_channels(raw.info["ch_names"], names, ordered=False)) == 1 + assert len(raw.copy().pick_channels(names, ordered=False)[0][0]) == 1 + + # missing ch_name + bad_names = names + ["BAD"] + with pytest.raises(ValueError, match="Missing channels"): + pick_channels(raw.info["ch_names"], bad_names, ordered=True) + with pytest.raises(ValueError, match="Missing channels"): + raw.copy().pick_channels(bad_names, ordered=True) # legacy method OK here + with pytest.raises(ValueError, match="could not be picked"): + raw.copy().pick(bad_names) + + +def test_clean_info_bads(): + """Test cleaning info['bads'] when bad_channels are excluded.""" + raw_file = io_dir / "tests" / "data" / "test_raw.fif" + raw = read_raw_fif(raw_file) + _assert_channel_types(raw.info) + + # select eeg channels + picks_eeg = pick_types(raw.info, meg=False, eeg=True) + + # select 3 eeg channels as bads + idx_eeg_bad_ch = picks_eeg[[1, 5, 14]] + eeg_bad_ch = [raw.info["ch_names"][k] for k in idx_eeg_bad_ch] + + # select meg channels + picks_meg = pick_types(raw.info, meg=True, eeg=False) + + # select randomly 3 meg channels as bads + idx_meg_bad_ch = picks_meg[[0, 15, 34]] + meg_bad_ch = [raw.info["ch_names"][k] for k in idx_meg_bad_ch] + + # simulate the bad channels + raw.info["bads"] = eeg_bad_ch + meg_bad_ch + + assert len(raw.info["projs"]) == 3 + raw.set_eeg_reference(projection=True) + assert len(raw.info["projs"]) == 4 + + # simulate the call to pick_info excluding the bad eeg channels + info_eeg = pick_info(raw.info, picks_eeg) + assert len(info_eeg["projs"]) == 1 + + # simulate the call to pick_info excluding the bad meg channels + info_meg = pick_info(raw.info, picks_meg) + assert len(info_meg["projs"]) == 3 + + assert info_eeg["bads"] == eeg_bad_ch + assert info_meg["bads"] == meg_bad_ch + + info = pick_info(raw.info, picks_meg) + info._check_consistency() + with pytest.raises(ValueError, match="do not exist"): + info["bads"] += ["EEG 053"] + with pytest.raises(ValueError, match="unique"): + pick_info(raw.info, [0, 0]) + + +@testing.requires_testing_data +def test_picks_to_idx(): + """Test checking type integrity checks of picks.""" + info = create_info(12, 1000.0, "eeg") + _assert_channel_types(info) + picks = np.arange(info["nchan"]) + # Array and list + assert_array_equal(picks, _picks_to_idx(info, picks)) + assert_array_equal(picks, _picks_to_idx(info, list(picks))) + with pytest.raises(TypeError, match="data type float64 is invalid"): + _picks_to_idx(info, 1.0) + # None + assert_array_equal(picks, _picks_to_idx(info, None)) + # Type indexing + assert_array_equal(picks, _picks_to_idx(info, "eeg")) + assert_array_equal(picks, _picks_to_idx(info, ["eeg"])) + # Negative indexing + assert_array_equal([len(picks) - 1], _picks_to_idx(info, len(picks) - 1)) + assert_array_equal([len(picks) - 1], _picks_to_idx(info, -1)) + assert_array_equal([len(picks) - 1], _picks_to_idx(info, [-1])) + # Name indexing + assert_array_equal([2], _picks_to_idx(info, info["ch_names"][2])) + assert_array_equal(np.arange(5, 9), _picks_to_idx(info, info["ch_names"][5:9])) + with pytest.raises(IndexError, match="must be >= "): + _picks_to_idx(info, -len(picks) - 1) + with pytest.raises(IndexError, match="must be < "): + _picks_to_idx(info, len(picks)) + with pytest.raises(ValueError, match="could not be interpreted"): + _picks_to_idx(info, ["a", "b"]) + with pytest.raises(ValueError, match="could not be interpreted"): + _picks_to_idx(info, "b") + # bads behavior + info["bads"] = info["ch_names"][1:2] + picks_good = np.array([0] + list(range(2, 12))) + assert_array_equal(picks_good, _picks_to_idx(info, None)) + assert_array_equal(picks_good, _picks_to_idx(info, None, exclude=info["bads"])) + assert_array_equal(picks, _picks_to_idx(info, None, exclude=())) + with pytest.raises(ValueError, match=" 1D, got"): + _picks_to_idx(info, [[1]]) + # MEG types + info = read_info(fname_mc) + meg_picks = np.arange(306) + mag_picks = np.arange(2, 306, 3) + grad_picks = np.setdiff1d(meg_picks, mag_picks) + assert_array_equal(meg_picks, _picks_to_idx(info, "meg")) + assert_array_equal(meg_picks, _picks_to_idx(info, ("mag", "grad"))) + assert_array_equal(mag_picks, _picks_to_idx(info, "mag")) + assert_array_equal(grad_picks, _picks_to_idx(info, "grad")) + + info = create_info(["eeg", "foo"], 1000.0, "eeg") + with pytest.raises(RuntimeError, match="equivalent to channel types"): + _picks_to_idx(info, "eeg") + with pytest.raises(ValueError, match="same length"): + create_info(["a", "b"], 1000.0, dict(hbo=["a"], hbr=["b"])) + info = create_info(["a", "b"], 1000.0, ["hbo", "hbr"]) + assert_array_equal(np.arange(2), _picks_to_idx(info, "fnirs")) + assert_array_equal([0], _picks_to_idx(info, "hbo")) + assert_array_equal([1], _picks_to_idx(info, "hbr")) + info = create_info(["a", "b"], 1000.0, ["hbo", "misc"]) + assert_array_equal(np.arange(len(info["ch_names"])), _picks_to_idx(info, "all")) + assert_array_equal([0], _picks_to_idx(info, "data")) + info = create_info(["a", "b"], 1000.0, ["fnirs_cw_amplitude", "fnirs_od"]) + assert_array_equal(np.arange(2), _picks_to_idx(info, "fnirs")) + assert_array_equal([0], _picks_to_idx(info, "fnirs_cw_amplitude")) + assert_array_equal([1], _picks_to_idx(info, "fnirs_od")) + info = create_info(["a", "b"], 1000.0, ["fnirs_cw_amplitude", "misc"]) + assert_array_equal(np.arange(len(info["ch_names"])), _picks_to_idx(info, "all")) + assert_array_equal([0], _picks_to_idx(info, "data")) + info = create_info(["a", "b"], 1000.0, ["fnirs_od", "misc"]) + assert_array_equal(np.arange(len(info["ch_names"])), _picks_to_idx(info, "all")) + assert_array_equal([0], _picks_to_idx(info, "data")) + # MEG reference sensors + info_ref = read_info(ctf_fname) + picks_meg = pick_types(info_ref, meg=True, ref_meg=False) + assert len(picks_meg) == 275 + picks_ref = pick_types(info_ref, meg=False, ref_meg=True) + assert len(picks_ref) == 29 + picks_meg_ref = np.sort(np.concatenate([picks_meg, picks_ref])) + assert len(picks_meg_ref) == 275 + 29 + assert_array_equal(picks_meg_ref, pick_types(info_ref, meg=True, ref_meg=True)) + assert_array_equal(picks_meg, _picks_to_idx(info_ref, "meg", with_ref_meg=False)) + assert_array_equal( # explicit trumps implicit + picks_ref, _picks_to_idx(info_ref, "ref_meg", with_ref_meg=False) + ) + assert_array_equal(picks_meg_ref, _picks_to_idx(info_ref, "meg", with_ref_meg=True)) + # Eyetrack + info = create_info(["a", "b"], 1000.0, ["eyegaze", "pupil"]) + assert_array_equal(np.arange(2), _picks_to_idx(info, "eyetrack")) + assert_array_equal([0], _picks_to_idx(info, "eyegaze")) + assert_array_equal([1], _picks_to_idx(info, "pupil")) + + +def test_pick_channels_cov(): + """Test picking channels from a Covariance object.""" + info = create_info(["CH1", "CH2", "CH3"], 1.0, ch_types="eeg") + cov = make_ad_hoc_cov(info) + cov["data"] = np.array([1.0, 2.0, 3.0]) + + cov_copy = pick_channels_cov(cov, ["CH2", "CH1"], ordered=False, copy=True) + assert cov_copy.ch_names == ["CH1", "CH2"] + assert_array_equal(cov_copy["data"], [1.0, 2.0]) + + # Test re-ordering channels + cov_copy = pick_channels_cov(cov, ["CH2", "CH1"], ordered=True, copy=True) + assert cov_copy.ch_names == ["CH2", "CH1"] + assert_array_equal(cov_copy["data"], [2.0, 1.0]) + + # Test picking in-place + pick_channels_cov(cov, ["CH2", "CH1"], copy=False, ordered=False) + assert cov.ch_names == ["CH1", "CH2"] + assert_array_equal(cov["data"], [1.0, 2.0]) + + # Test whether `method` and `loglik` are dropped when None + cov["method"] = None + cov["loglik"] = None + cov_copy = pick_channels_cov(cov, ["CH1", "CH2"], copy=True) + assert "method" not in cov_copy + assert "loglik" not in cov_copy + + +def test_pick_types_meg(): + """Test pick_types(meg=True).""" + # info with MEG channels at indices 1, 2, and 4 + info1 = create_info(6, 256, ["eeg", "mag", "grad", "misc", "grad", "hbo"]) + + assert list(pick_types(info1, meg=True)) == [1, 2, 4] + assert list(pick_types(info1, meg=True, eeg=True)) == [0, 1, 2, 4] + + assert list(pick_types(info1, meg=True)) == [1, 2, 4] + assert not list(pick_types(info1, meg=False)) # empty + assert list(pick_types(info1, meg="planar1")) == [2] + assert not list(pick_types(info1, meg="planar2")) # empty + + # info without any MEG channels + info2 = create_info(6, 256, ["eeg", "eeg", "eog", "misc", "stim", "hbo"]) + + assert not list(pick_types(info2)) # empty + assert list(pick_types(info2, eeg=True)) == [0, 1] + + +def test_pick_types_csd(): + """Test pick_types(csd=True).""" + # info with laplacian/CSD channels at indices 1, 2 + names = ["F1", "F2", "C1", "C2", "A1", "A2", "misc1", "CSD1"] + info1 = create_info( + names, 256, ["eeg", "eeg", "eeg", "eeg", "mag", "mag", "misc", "csd"] + ) + raw = RawArray(np.zeros((8, 512)), info1) + raw.set_montage(make_standard_montage("standard_1020"), verbose="error") + raw_csd = compute_current_source_density(raw, verbose="error") + + assert_array_equal(pick_types(info1, csd=True), [7]) + + # pick from the raw object + assert raw_csd.copy().pick("csd").ch_names == [ + "F1", + "F2", + "C1", + "C2", + "CSD1", + ] + + +@pytest.mark.parametrize("meg", [True, False, "grad", "mag"]) +@pytest.mark.parametrize("eeg", [True, False]) +@pytest.mark.parametrize("ordered", [True, False]) +def test_get_channel_types_equiv(meg, eeg, ordered): + """Test equivalence of get_channel_types.""" + raw = read_raw_fif(fif_fname) + pick_types(raw.info, meg=meg, eeg=eeg) + picks = pick_types(raw.info, meg=meg, eeg=eeg) + if not ordered: + picks = np.random.RandomState(0).permutation(picks) + if not meg and not eeg: + with pytest.raises(ValueError, match="No appropriate channels"): + raw.get_channel_types(picks=picks) + return + types = np.array(raw.get_channel_types(picks=picks)) + types_iter = np.array([channel_type(raw.info, idx) for idx in picks]) + assert_array_equal(types, types_iter) diff --git a/mne-python/source/mne/_fiff/tests/test_proc_history.py b/mne-python/source/mne/_fiff/tests/test_proc_history.py new file mode 100644 index 0000000000000000000000000000000000000000..82f2d6262bedd4c1063c6435c4b851bf1b7cbd47 --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_proc_history.py @@ -0,0 +1,42 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import numpy as np +from numpy.testing import assert_array_equal + +from mne._fiff.constants import FIFF +from mne.io import read_info + +base_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = base_dir / "test_chpi_raw_sss.fif" + + +def test_maxfilter_io(): + """Test maxfilter io.""" + info = read_info(raw_fname) + mf = info["proc_history"][1]["max_info"] + + assert mf["sss_info"]["frame"] == FIFF.FIFFV_COORD_HEAD + # based on manual 2.0, rev. 5.0 page 23 + assert 5 <= mf["sss_info"]["in_order"] <= 11 + assert mf["sss_info"]["out_order"] <= 5 + assert mf["sss_info"]["nchan"] > len(mf["sss_info"]["components"]) + + assert ( + info["ch_names"][: mf["sss_info"]["nchan"]] == mf["sss_ctc"]["proj_items_chs"] + ) + assert mf["sss_ctc"]["decoupler"].shape == ( + mf["sss_info"]["nchan"], + mf["sss_info"]["nchan"], + ) + assert_array_equal( + np.unique(np.diag(mf["sss_ctc"]["decoupler"].toarray())), + np.array([1.0], dtype=np.float32), + ) + assert mf["sss_cal"]["cal_corrs"].shape == (306, 14) + assert mf["sss_cal"]["cal_chans"].shape == (306, 2) + vv_coils = [v for k, v in FIFF.items() if "FIFFV_COIL_VV" in k] + assert all(k in vv_coils for k in set(mf["sss_cal"]["cal_chans"][:, 1])) diff --git a/mne-python/source/mne/_fiff/tests/test_reference.py b/mne-python/source/mne/_fiff/tests/test_reference.py new file mode 100644 index 0000000000000000000000000000000000000000..085f34e1bcba239963647278592d63f5fc96ba4e --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_reference.py @@ -0,0 +1,975 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import itertools +from contextlib import nullcontext +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_equal, assert_equal + +from mne import ( + Epochs, + Projection, + add_reference_channels, + create_info, + find_events, + make_forward_solution, + make_sphere_model, + pick_channels, + pick_channels_forward, + pick_types, + read_events, + read_evokeds, + set_bipolar_reference, + set_eeg_reference, + setup_volume_source_space, +) +from mne._fiff.constants import FIFF +from mne._fiff.proj import _has_eeg_average_ref_proj +from mne._fiff.reference import _apply_reference +from mne.datasets import testing +from mne.epochs import BaseEpochs, make_fixed_length_epochs +from mne.io import RawArray, read_raw_fif +from mne.utils import _record_warnings, catch_logging + +base_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = base_dir / "test_raw.fif" +data_dir = testing.data_path(download=False) / "MEG" / "sample" +fif_fname = data_dir / "sample_audvis_trunc_raw.fif" +eve_fname = data_dir / "sample_audvis_trunc_raw-eve.fif" +ave_fname = data_dir / "sample_audvis-ave.fif" + + +def _test_reference(raw, reref, ref_data, ref_from): + """Test whether a reference has been correctly applied.""" + # Separate EEG channels from other channel types + picks_eeg = pick_types(raw.info, meg=False, eeg=True, exclude="bads") + picks_other = pick_types( + raw.info, meg=True, eeg=False, eog=True, stim=True, exclude="bads" + ) + + # Calculate indices of reference channesl + picks_ref = [raw.ch_names.index(ch) for ch in ref_from] + + # Get data + _data = raw._data + _reref = reref._data + + # Check that the ref has been properly computed + if ref_data is not None: + assert_array_equal(ref_data, _data[..., picks_ref, :].mean(-2)) + + # Get the raw EEG data and other channel data + raw_eeg_data = _data[..., picks_eeg, :] + raw_other_data = _data[..., picks_other, :] + + # Get the rereferenced EEG data + reref_eeg_data = _reref[..., picks_eeg, :] + reref_other_data = _reref[..., picks_other, :] + + # Check that non-EEG channels are untouched + assert_allclose(raw_other_data, reref_other_data, 1e-6, atol=1e-15) + + # Undo rereferencing of EEG channels if possible + if ref_data is not None: + if isinstance(raw, BaseEpochs): + unref_eeg_data = reref_eeg_data + ref_data[:, np.newaxis, :] + else: + unref_eeg_data = reref_eeg_data + ref_data + assert_allclose(raw_eeg_data, unref_eeg_data, 1e-6, atol=1e-15) + + +@testing.requires_testing_data +def test_apply_reference(): + """Test base function for rereferencing.""" + raw = read_raw_fif(fif_fname, preload=True) + + # Rereference raw data by creating a copy of original data + reref, ref_data = _apply_reference(raw.copy(), ref_from=["EEG 001", "EEG 002"]) + assert reref.info["custom_ref_applied"] + _test_reference(raw, reref, ref_data, ["EEG 001", "EEG 002"]) + + # The CAR reference projection should have been removed by the function + assert not _has_eeg_average_ref_proj(reref.info) + + # Test that data is modified in place when copy=False + reref, ref_data = _apply_reference(raw, ["EEG 001", "EEG 002"]) + assert raw is reref + + # Test that disabling the reference does not change anything + reref, ref_data = _apply_reference(raw.copy(), []) + assert_array_equal(raw._data, reref._data) + + # Test re-referencing Epochs object + raw = read_raw_fif(fif_fname, preload=False) + events = read_events(eve_fname) + picks_eeg = pick_types(raw.info, meg=False, eeg=True) + epochs = Epochs( + raw, + events=events, + event_id=1, + tmin=-0.2, + tmax=0.5, + picks=picks_eeg, + preload=True, + ) + reref, ref_data = _apply_reference(epochs.copy(), ref_from=["EEG 001", "EEG 002"]) + assert reref.info["custom_ref_applied"] + _test_reference(epochs, reref, ref_data, ["EEG 001", "EEG 002"]) + + # Test re-referencing Evoked object + evoked = epochs.average() + reref, ref_data = _apply_reference(evoked.copy(), ref_from=["EEG 001", "EEG 002"]) + assert reref.info["custom_ref_applied"] + _test_reference(evoked, reref, ref_data, ["EEG 001", "EEG 002"]) + + # Referencing needs data to be preloaded + raw_np = read_raw_fif(fif_fname, preload=False) + pytest.raises(RuntimeError, _apply_reference, raw_np, ["EEG 001"]) + + # Test having inactive SSP projections that deal with channels involved + # during re-referencing + raw = read_raw_fif(fif_fname, preload=True) + raw.add_proj( + Projection( + active=False, + data=dict( + col_names=["EEG 001", "EEG 002"], + row_names=None, + data=np.array([[1, 1]]), + ncol=2, + nrow=1, + ), + desc="test", + kind=1, + ) + ) + # Projection concerns channels mentioned in projector + with pytest.raises(RuntimeError, match="Inactive signal space"): + _apply_reference(raw, ["EEG 001"]) + + # Projection does not concern channels mentioned in projector, no error + _apply_reference(raw, ["EEG 003"], ["EEG 004"]) + + # CSD cannot be rereferenced + with raw.info._unlock(): + raw.info["custom_ref_applied"] = FIFF.FIFFV_MNE_CUSTOM_REF_CSD + with pytest.raises(RuntimeError, match="Cannot set.* type 'CSD'"): + raw.set_eeg_reference() + + +@testing.requires_testing_data +def test_set_eeg_reference(): + """Test rereference eeg data.""" + raw = read_raw_fif(fif_fname, preload=True) + with raw.info._unlock(): + raw.info["projs"] = [] + + # Test setting an average reference projection + assert not _has_eeg_average_ref_proj(raw.info) + reref, ref_data = set_eeg_reference(raw, projection=True) + assert _has_eeg_average_ref_proj(reref.info) + assert not reref.info["projs"][0]["active"] + assert ref_data is None + reref.apply_proj() + eeg_chans = [raw.ch_names[ch] for ch in pick_types(raw.info, meg=False, eeg=True)] + _test_reference( + raw, reref, ref_data, [ch for ch in eeg_chans if ch not in raw.info["bads"]] + ) + + # Test setting an average reference when one was already present + with pytest.warns(RuntimeWarning, match="untouched"): + reref, ref_data = set_eeg_reference(raw, copy=False, projection=True) + assert ref_data is None + + # Test setting an average reference on non-preloaded data + raw_nopreload = read_raw_fif(fif_fname, preload=False) + with raw_nopreload.info._unlock(): + raw_nopreload.info["projs"] = [] + reref, ref_data = set_eeg_reference(raw_nopreload, projection=True) + assert _has_eeg_average_ref_proj(reref.info) + assert not reref.info["projs"][0]["active"] + + # Rereference raw data by creating a copy of original data + reref, ref_data = set_eeg_reference(raw, ["EEG 001", "EEG 002"], copy=True) + assert reref.info["custom_ref_applied"] + _test_reference(raw, reref, ref_data, ["EEG 001", "EEG 002"]) + + # Test that data is modified in place when copy=False + reref, ref_data = set_eeg_reference(raw, ["EEG 001", "EEG 002"], copy=False) + assert raw is reref + + # Test moving from custom to average reference + reref, ref_data = set_eeg_reference(raw, ["EEG 001", "EEG 002"]) + reref, _ = set_eeg_reference(reref, projection=True) + assert _has_eeg_average_ref_proj(reref.info) + assert not reref.info["custom_ref_applied"] + + # When creating an average reference fails, make sure the + # custom_ref_applied flag remains untouched. + reref = raw.copy() + with reref.info._unlock(): + reref.info["custom_ref_applied"] = FIFF.FIFFV_MNE_CUSTOM_REF_ON + reref.pick(picks="meg") # Cause making average ref fail + # should have turned it off + assert reref.info["custom_ref_applied"] == FIFF.FIFFV_MNE_CUSTOM_REF_OFF + with pytest.raises(ValueError, match="found to rereference"): + set_eeg_reference(reref, projection=True) + + # Test moving from average to custom reference + reref, ref_data = set_eeg_reference(raw, projection=True) + reref, _ = set_eeg_reference(reref, ["EEG 001", "EEG 002"]) + assert not _has_eeg_average_ref_proj(reref.info) + assert len(reref.info["projs"]) == 0 + assert reref.info["custom_ref_applied"] == FIFF.FIFFV_MNE_CUSTOM_REF_ON + + # Test that disabling the reference does not change the data + assert _has_eeg_average_ref_proj(raw.info) + reref, _ = set_eeg_reference(raw, []) + assert_array_equal(raw._data, reref._data) + assert not _has_eeg_average_ref_proj(reref.info) + + # make sure ref_channels=[] removes average reference projectors + assert _has_eeg_average_ref_proj(raw.info) + reref, _ = set_eeg_reference(raw, []) + assert not _has_eeg_average_ref_proj(reref.info) + + # Test that average reference gives identical results when calculated + # via SSP projection (projection=True) or directly (projection=False) + with raw.info._unlock(): + raw.info["projs"] = [] + reref_1, _ = set_eeg_reference(raw.copy(), projection=True) + reref_1.apply_proj() + reref_2, _ = set_eeg_reference(raw.copy(), projection=False) + assert_allclose(reref_1._data, reref_2._data, rtol=1e-6, atol=1e-15) + + # Test average reference without projection + reref, ref_data = set_eeg_reference( + raw.copy(), ref_channels="average", projection=False + ) + _test_reference(raw, reref, ref_data, eeg_chans) + + with pytest.raises(ValueError, match='supported for ref_channels="averag'): + set_eeg_reference(raw, [], True, True) + with pytest.raises(ValueError, match='supported for ref_channels="averag'): + set_eeg_reference(raw, ["EEG 001"], True, True) + + +@pytest.mark.parametrize( + "ch_type, msg", + [ + ("auto", ("ECoG",)), + ("ecog", ("ECoG",)), + ("dbs", ("DBS",)), + (["ecog", "dbs"], ("ECoG", "DBS")), + ], +) +@pytest.mark.parametrize("projection", [False, True]) +def test_set_eeg_reference_ch_type(ch_type, msg, projection): + """Test setting EEG reference for ECoG or DBS.""" + # gh-6454 + # gh-8739 added DBS + ch_names = ["ECOG01", "ECOG02", "DBS01", "DBS02", "MISC"] + rng = np.random.RandomState(0) + data = rng.randn(5, 1000) + raw = RawArray( + data, create_info(ch_names, 1000.0, ["ecog"] * 2 + ["dbs"] * 2 + ["misc"]) + ) + + if ch_type == "auto": + ref_ch = ch_names[:2] + else: + ref_ch = raw.copy().pick(picks=ch_type).ch_names + + with catch_logging() as log: + reref, ref_data = set_eeg_reference( + raw.copy(), ch_type=ch_type, projection=projection, verbose=True + ) + + if not projection: + assert f"Applying a custom {msg}" in log.getvalue() + assert reref.info["custom_ref_applied"] # gh-7350 + _test_reference(raw, reref, ref_data, ref_ch) + match = "no EEG data found" if projection else "No channels supplied" + with pytest.raises(ValueError, match=match): + set_eeg_reference(raw, ch_type="eeg", projection=projection) + # gh-8739 + raw2 = RawArray(data, create_info(5, 1000.0, ["mag"] * 4 + ["misc"])) + with pytest.raises( + ValueError, match="No EEG, ECoG, sEEG or DBS channels found to rereference." + ): + set_eeg_reference(raw2, ch_type="auto", projection=projection) + + +@testing.requires_testing_data +def test_set_eeg_reference_rest(): + """Test setting a REST reference.""" + raw = read_raw_fif(fif_fname).crop(0, 1).pick(picks="eeg").load_data() + raw.info["bads"] = ["EEG 057"] # should be excluded + same = [raw.ch_names.index(raw.info["bads"][0])] + picks = np.setdiff1d(np.arange(len(raw.ch_names)), same) + trans = None + # Use fixed values from old sphere fit to reduce lines changed with fixed algorithm + sphere = make_sphere_model( + [-0.00413508, 0.01598787, 0.05175598], + 0.09100286249131773, + ) + src = setup_volume_source_space(pos=20.0, sphere=sphere, exclude=30.0) + assert src[0]["nuse"] == 223 # low but fast + fwd = make_forward_solution(raw.info, trans, src, sphere) + orig_data = raw.get_data() + avg_data = raw.copy().set_eeg_reference("average").get_data() + assert_array_equal(avg_data[same], orig_data[same]) # not processed + raw.set_eeg_reference("REST", forward=fwd) + rest_data = raw.get_data() + assert_array_equal(rest_data[same], orig_data[same]) + # should be more similar to an avg ref than nose ref + orig_corr = np.corrcoef(rest_data[picks].ravel(), orig_data[picks].ravel())[0, 1] + avg_corr = np.corrcoef(rest_data[picks].ravel(), avg_data[picks].ravel())[0, 1] + assert -0.6 < orig_corr < -0.5 + assert 0.1 < avg_corr < 0.2 + # and applying an avg ref after should work + avg_after = raw.set_eeg_reference("average").get_data() + assert_allclose(avg_after, avg_data, atol=1e-12) + with pytest.raises(TypeError, match='forward when ref_channels="REST"'): + raw.set_eeg_reference("REST") + fwd_bad = pick_channels_forward(fwd, raw.ch_names[:-1]) + with pytest.raises(ValueError, match="Missing channels"): + raw.set_eeg_reference("REST", forward=fwd_bad) + # compare to FieldTrip + evoked = read_evokeds(ave_fname, baseline=(None, 0))[0] + evoked.info["bads"] = [] + evoked.pick(picks="eeg") + assert len(evoked.ch_names) == 60 + # Data obtained from FieldTrip with something like (after evoked.save'ing + # then scipy.io.savemat'ing fwd['sol']['data']): + # dat = ft_read_data('ft-ave.fif'); + # load('leadfield.mat', 'G'); + # dat_ref = ft_preproc_rereference(dat, 'all', 'rest', true, G); + # sprintf('%g ', dat_ref(:, 171)); + data_array = "-3.3265e-05 -3.2419e-05 -3.18758e-05 -3.24079e-05 -3.39801e-05 -3.40573e-05 -3.24163e-05 -3.26896e-05 -3.33814e-05 -3.54734e-05 -3.51289e-05 -3.53229e-05 -3.51532e-05 -3.53149e-05 -3.4505e-05 -3.03462e-05 -2.81848e-05 -3.08895e-05 -3.27158e-05 -3.4605e-05 -3.47728e-05 -3.2459e-05 -3.06552e-05 -2.53255e-05 -2.69671e-05 -2.83425e-05 -3.12836e-05 -3.30965e-05 -3.34099e-05 -3.32766e-05 -3.32256e-05 -3.36385e-05 -3.20796e-05 -2.7108e-05 -2.47054e-05 -2.49589e-05 -2.7382e-05 -3.09774e-05 -3.12003e-05 -3.1246e-05 -3.07572e-05 -2.64942e-05 -2.25505e-05 -2.67194e-05 -2.86e-05 -2.94903e-05 -2.96249e-05 -2.92653e-05 -2.86472e-05 -2.81016e-05 -2.69737e-05 -2.48076e-05 -3.00473e-05 -2.73404e-05 -2.60153e-05 -2.41608e-05 -2.61937e-05 -2.5539e-05 -2.47104e-05 -2.35194e-05" # noqa: E501 + want = np.array(data_array.split(" "), float) + norm = np.linalg.norm(want) + idx = np.argmin(np.abs(evoked.times - 0.083)) + assert idx == 170 + old = evoked.data[:, idx].ravel() + exp_var = 1 - np.linalg.norm(want - old) / norm + assert 0.006 < exp_var < 0.008 + evoked.set_eeg_reference("REST", forward=fwd) + exp_var_old = 1 - np.linalg.norm(evoked.data[:, idx] - old) / norm + assert 0.005 < exp_var_old <= 0.009 + exp_var = 1 - np.linalg.norm(evoked.data[:, idx] - want) / norm + assert 0.995 < exp_var <= 1 + + +@testing.requires_testing_data +@pytest.mark.parametrize("inst_type", ["raw", "epochs"]) +@pytest.mark.parametrize( + "ref_channels, expectation", + [ + ( + {2: "EEG 001"}, + pytest.raises( + TypeError, + match="Keys in the ref_channels dict must be strings. " + "Your dict has keys of type int.", + ), + ), + ( + {"EEG 001": (1, 2)}, + pytest.raises( + TypeError, + match="Values in the ref_channels dict must be strings. " + "Your dict has values of type int.", + ), + ), + ( + {"EEG 001": [1, 2]}, + pytest.raises( + TypeError, + match="Values in the ref_channels dict must be strings. " + "Your dict has values of type int.", + ), + ), + ( + {"EEG 999": "EEG 001"}, + pytest.raises( + ValueError, + match=r"ref_channels dict contains invalid key\(s\) \(EEG 999\) " + "that are not names of channels in the instance.", + ), + ), + ( + {"EEG 001": "EEG 999"}, + pytest.raises( + ValueError, + match=r"ref_channels dict contains invalid value\(s\) \(EEG 999\) " + "that are not names of channels in the instance.", + ), + ), + ( + {"EEG 001": "EEG 057"}, + pytest.warns( + RuntimeWarning, + match=r"ref_channels dict contains value\(s\) \(EEG 057\) " + "that are marked as bad channels.", + ), + ), + ( + {"EEG 001": "STI 001"}, + pytest.warns( + RuntimeWarning, + match=( + r"Channel EEG 001 \(eeg\) is referenced to channel " + r"STI 001 which is a different channel type \(stim\)." + ), + ), + ), + ( + {"EEG 001": "EEG 001"}, + pytest.warns( + RuntimeWarning, + match=( + "Channel EEG 001 is self-referenced, " + "which will nullify the channel." + ), + ), + ), + ( + {"EEG 001": "EEG 002", "EEG 002": "EEG 003", "EEG 003": "EEG 005"}, + nullcontext(), + ), + ( + { + "EEG 001": ["EEG 002", "EEG 003"], + "EEG 002": "EEG 003", + "EEG 003": "EEG 005", + }, + nullcontext(), + ), + ], +) +def test_set_eeg_reference_dict(ref_channels, inst_type, expectation): + """Test setting dict-based reference.""" + if inst_type == "raw": + inst = read_raw_fif(fif_fname).crop(0, 1).pick(picks=["eeg", "stim"]) + # Test re-referencing Epochs object + elif inst_type == "epochs": + raw = read_raw_fif(fif_fname, preload=False) + events = read_events(eve_fname) + inst = Epochs( + raw, + events=events, + event_id=1, + tmin=-0.2, + tmax=0.5, + preload=False, + ) + with pytest.raises( + RuntimeError, + match="By default, MNE does not load data.*Applying a reference requires.*", + ): + inst.set_eeg_reference(ref_channels=ref_channels) + inst.load_data() + inst.info["bads"] = ["EEG 057"] + with expectation: + reref, _ = set_eeg_reference(inst.copy(), ref_channels, copy=False) + + if isinstance(expectation, nullcontext): + # Check that the custom_ref_applied is set correctly: + assert reref.info["custom_ref_applied"] == FIFF.FIFFV_MNE_CUSTOM_REF_ON + + # Get raw data + _data = inst._data + + # Get that channels that were and weren't re-referenced: + ch_raw = pick_channels( + inst.ch_names, + [ch for ch in inst.ch_names if ch not in list(ref_channels.keys())], + ) + ch_reref = pick_channels(inst.ch_names, list(ref_channels.keys()), ordered=True) + + # Check that the non re-reference channels are untouched: + assert_allclose( + _data[..., ch_raw, :], reref._data[..., ch_raw, :], 1e-6, atol=1e-15 + ) + + # Compute the reference data: + ref_data = [] + for val in ref_channels.values(): + if isinstance(val, str): + val = [val] # pick_channels expects a list + ref_data.append( + _data[..., pick_channels(inst.ch_names, val, ordered=True), :].mean( + -2, keepdims=True + ) + ) + if inst_type == "epochs": + ref_data = np.concatenate(ref_data, axis=1) + else: + ref_data = np.squeeze(np.array(ref_data)) + assert_allclose( + _data[..., ch_reref, :], + reref._data[..., ch_reref, :] + ref_data, + 1e-6, + atol=1e-15, + ) + + +@testing.requires_testing_data +@pytest.mark.parametrize("inst_type", ("raw", "epochs", "evoked")) +def test_set_bipolar_reference(inst_type): + """Test bipolar referencing.""" + raw = read_raw_fif(fif_fname, preload=True) + raw.apply_proj() + + if inst_type == "raw": + inst = raw + del raw + elif inst_type in ["epochs", "evoked"]: + events = find_events(raw, stim_channel="STI 014") + epochs = Epochs(raw, events, tmin=-0.3, tmax=0.7, preload=True) + inst = epochs + if inst_type == "evoked": + inst = epochs.average() + del epochs + + ch_info = {"kind": FIFF.FIFFV_EOG_CH, "extra": "some extra value"} + with pytest.raises(KeyError, match="key errantly present"): + set_bipolar_reference(inst, "EEG 001", "EEG 002", "bipolar", ch_info) + ch_info.pop("extra") + reref = set_bipolar_reference(inst, "EEG 001", "EEG 002", "bipolar", ch_info) + assert reref.info["custom_ref_applied"] + + # Compare result to a manual calculation + a = inst.copy().pick(["EEG 001", "EEG 002"]) + a = a._data[..., 0, :] - a._data[..., 1, :] + b = reref.copy().pick(["bipolar"])._data[..., 0, :] + assert_allclose(a, b) + + # Original channels should be replaced by a virtual one + assert "EEG 001" not in reref.ch_names + assert "EEG 002" not in reref.ch_names + assert "bipolar" in reref.ch_names + + # Check channel information + bp_info = reref.info["chs"][reref.ch_names.index("bipolar")] + an_info = inst.info["chs"][inst.ch_names.index("EEG 001")] + for key in bp_info: + if key == "coil_type": + assert bp_info[key] == FIFF.FIFFV_COIL_EEG_BIPOLAR, key + elif key == "kind": + assert bp_info[key] == FIFF.FIFFV_EOG_CH, key + elif key != "ch_name": + assert_equal(bp_info[key], an_info[key], err_msg=key) + + # Minimalist call + reref = set_bipolar_reference(inst, "EEG 001", "EEG 002") + assert "EEG 001-EEG 002" in reref.ch_names + + # Minimalist call with twice the same anode + reref = set_bipolar_reference( + inst, ["EEG 001", "EEG 001", "EEG 002"], ["EEG 002", "EEG 003", "EEG 003"] + ) + assert "EEG 001-EEG 002" in reref.ch_names + assert "EEG 001-EEG 003" in reref.ch_names + + # Set multiple references at once + reref = set_bipolar_reference( + inst, + ["EEG 001", "EEG 003"], + ["EEG 002", "EEG 004"], + ["bipolar1", "bipolar2"], + [{"kind": FIFF.FIFFV_EOG_CH}, {"kind": FIFF.FIFFV_EOG_CH}], + ) + a = inst.copy().pick(["EEG 001", "EEG 002", "EEG 003", "EEG 004"]) + a = np.concatenate( + [ + a._data[..., :1, :] - a._data[..., 1:2, :], + a._data[..., 2:3, :] - a._data[..., 3:4, :], + ], + axis=-2, + ) + b = reref.copy().pick(["bipolar1", "bipolar2"])._data + assert_allclose(a, b) + + # Test creating a bipolar reference that doesn't involve EEG channels: + # it should not set the custom_ref_applied flag + reref = set_bipolar_reference( + inst, + "MEG 0111", + "MEG 0112", + ch_info={"kind": FIFF.FIFFV_MEG_CH}, + verbose="error", + ) + assert not reref.info["custom_ref_applied"] + assert "MEG 0111-MEG 0112" in reref.ch_names + + # Test a battery of invalid inputs + pytest.raises( + ValueError, + set_bipolar_reference, + inst, + "EEG 001", + ["EEG 002", "EEG 003"], + "bipolar", + ) + pytest.raises( + ValueError, + set_bipolar_reference, + inst, + ["EEG 001", "EEG 002"], + "EEG 003", + "bipolar", + ) + pytest.raises( + ValueError, + set_bipolar_reference, + inst, + "EEG 001", + "EEG 002", + ["bipolar1", "bipolar2"], + ) + pytest.raises( + ValueError, + set_bipolar_reference, + inst, + "EEG 001", + "EEG 002", + "bipolar", + ch_info=[{"foo": "bar"}, {"foo": "bar"}], + ) + pytest.raises( + ValueError, set_bipolar_reference, inst, "EEG 001", "EEG 002", ch_name="EEG 003" + ) + + # Test if bad anode/cathode raises error if on_bad="raise" + inst.info["bads"] = ["EEG 001"] + pytest.raises( + ValueError, set_bipolar_reference, inst, "EEG 001", "EEG 002", on_bad="raise" + ) + inst.info["bads"] = ["EEG 002"] + pytest.raises( + ValueError, set_bipolar_reference, inst, "EEG 001", "EEG 002", on_bad="raise" + ) + + # Test if bad anode/cathode raises warning if on_bad="warn" + inst.info["bads"] = ["EEG 001"] + pytest.warns( + RuntimeWarning, set_bipolar_reference, inst, "EEG 001", "EEG 002", on_bad="warn" + ) + inst.info["bads"] = ["EEG 002"] + pytest.warns( + RuntimeWarning, set_bipolar_reference, inst, "EEG 001", "EEG 002", on_bad="warn" + ) + + +def _check_channel_names(inst, ref_names): + """Check channel names.""" + if isinstance(ref_names, str): + ref_names = [ref_names] + + # Test that the names of the reference channels are present in `ch_names` + ref_idx = pick_channels(inst.info["ch_names"], ref_names) + assert len(ref_idx) == len(ref_names) + + # Test that the names of the reference channels are present in the `chs` + # list + inst.info._check_consistency() # Should raise no exceptions + + +@testing.requires_testing_data +def test_add_reference(): + """Test adding a reference.""" + raw = read_raw_fif(fif_fname, preload=True) + picks_eeg = pick_types(raw.info, meg=False, eeg=True) + # check if channel already exists + pytest.raises(ValueError, add_reference_channels, raw, raw.info["ch_names"][0]) + # add reference channel to Raw + raw_ref = add_reference_channels(raw, "Ref", copy=True) + assert_equal(raw_ref._data.shape[0], raw._data.shape[0] + 1) + assert_array_equal(raw._data[picks_eeg, :], raw_ref._data[picks_eeg, :]) + _check_channel_names(raw_ref, "Ref") + + orig_nchan = raw.info["nchan"] + raw = add_reference_channels(raw, "Ref", copy=False) + assert_array_equal(raw._data, raw_ref._data) + assert_equal(raw.info["nchan"], orig_nchan + 1) + _check_channel_names(raw, "Ref") + + # for Neuromag fif's, the reference electrode location is placed in + # elements [3:6] of each "data" electrode location + assert_allclose( + raw.info["chs"][-1]["loc"][:3], raw.info["chs"][picks_eeg[0]]["loc"][3:6], 1e-6 + ) + + ref_idx = raw.ch_names.index("Ref") + ref_data, _ = raw[ref_idx] + assert_array_equal(ref_data, 0) + + # add reference channel to Raw when no digitization points exist + raw = read_raw_fif(fif_fname).crop(0, 1).load_data() + picks_eeg = pick_types(raw.info, meg=False, eeg=True) + del raw.info["dig"] + + raw_ref = add_reference_channels(raw, "Ref", copy=True) + + assert_equal(raw_ref._data.shape[0], raw._data.shape[0] + 1) + assert_array_equal(raw._data[picks_eeg, :], raw_ref._data[picks_eeg, :]) + _check_channel_names(raw_ref, "Ref") + + orig_nchan = raw.info["nchan"] + raw = add_reference_channels(raw, "Ref", copy=False) + assert_array_equal(raw._data, raw_ref._data) + assert_equal(raw.info["nchan"], orig_nchan + 1) + _check_channel_names(raw, "Ref") + + # Test adding an existing channel as reference channel + pytest.raises(ValueError, add_reference_channels, raw, raw.info["ch_names"][0]) + + # add two reference channels to Raw + raw_ref = add_reference_channels(raw, ["M1", "M2"], copy=True) + _check_channel_names(raw_ref, ["M1", "M2"]) + assert_equal(raw_ref._data.shape[0], raw._data.shape[0] + 2) + assert_array_equal(raw._data[picks_eeg, :], raw_ref._data[picks_eeg, :]) + assert_array_equal(raw_ref._data[-2:, :], 0) + + raw = add_reference_channels(raw, ["M1", "M2"], copy=False) + _check_channel_names(raw, ["M1", "M2"]) + ref_idx = raw.ch_names.index("M1") + ref_idy = raw.ch_names.index("M2") + ref_data, _ = raw[[ref_idx, ref_idy]] + assert_array_equal(ref_data, 0) + + loc1 = raw.info["chs"][ref_idx]["loc"] + loc2 = raw.info["chs"][ref_idy]["loc"] + assert loc1 is not loc2 + + # add reference channel to epochs + raw = read_raw_fif(fif_fname, preload=True) + events = read_events(eve_fname) + picks_eeg = pick_types(raw.info, meg=False, eeg=True) + epochs = Epochs( + raw, + events=events, + event_id=1, + tmin=-0.2, + tmax=0.5, + picks=picks_eeg, + preload=True, + ) + # default: proj=True, after which adding a Ref channel is prohibited + pytest.raises(RuntimeError, add_reference_channels, epochs, "Ref") + + # create epochs in delayed mode, allowing removal of CAR when re-reffing + epochs = Epochs( + raw, + events=events, + event_id=1, + tmin=-0.2, + tmax=0.5, + picks=picks_eeg, + preload=True, + proj="delayed", + ) + epochs_ref = add_reference_channels(epochs, "Ref", copy=True) + + assert_equal(epochs_ref._data.shape[1], epochs._data.shape[1] + 1) + _check_channel_names(epochs_ref, "Ref") + ref_idx = epochs_ref.ch_names.index("Ref") + ref_data = epochs_ref.get_data(picks=[ref_idx])[:, 0] + assert_array_equal(ref_data, 0) + picks_eeg = pick_types(epochs.info, meg=False, eeg=True) + assert_array_equal(epochs.get_data(picks_eeg), epochs_ref.get_data(picks_eeg)) + + # add two reference channels to epochs + raw = read_raw_fif(fif_fname, preload=True) + events = read_events(eve_fname) + picks_eeg = pick_types(raw.info, meg=False, eeg=True) + # create epochs in delayed mode, allowing removal of CAR when re-reffing + epochs = Epochs( + raw, + events=events, + event_id=1, + tmin=-0.2, + tmax=0.5, + picks=picks_eeg, + preload=True, + proj="delayed", + ) + with pytest.warns(RuntimeWarning, match="for this channel is unknown or ambiguous"): + epochs_ref = add_reference_channels(epochs, ["M1", "M2"], copy=True) + assert_equal(epochs_ref._data.shape[1], epochs._data.shape[1] + 2) + _check_channel_names(epochs_ref, ["M1", "M2"]) + ref_idx = epochs_ref.ch_names.index("M1") + ref_idy = epochs_ref.ch_names.index("M2") + assert_equal(epochs_ref.info["chs"][ref_idx]["ch_name"], "M1") + assert_equal(epochs_ref.info["chs"][ref_idy]["ch_name"], "M2") + ref_data = epochs_ref.get_data([ref_idx, ref_idy]) + assert_array_equal(ref_data, 0) + picks_eeg = pick_types(epochs.info, meg=False, eeg=True) + assert_array_equal(epochs.get_data(picks_eeg), epochs_ref.get_data(picks_eeg)) + + # add reference channel to evoked + raw = read_raw_fif(fif_fname, preload=True) + events = read_events(eve_fname) + picks_eeg = pick_types(raw.info, meg=False, eeg=True) + # create epochs in delayed mode, allowing removal of CAR when re-reffing + epochs = Epochs( + raw, + events=events, + event_id=1, + tmin=-0.2, + tmax=0.5, + picks=picks_eeg, + preload=True, + proj="delayed", + ) + evoked = epochs.average() + evoked_ref = add_reference_channels(evoked, "Ref", copy=True) + assert_equal(evoked_ref.data.shape[0], evoked.data.shape[0] + 1) + _check_channel_names(evoked_ref, "Ref") + ref_idx = evoked_ref.ch_names.index("Ref") + ref_data = evoked_ref.data[ref_idx, :] + assert_array_equal(ref_data, 0) + picks_eeg = pick_types(evoked.info, meg=False, eeg=True) + assert_array_equal(evoked.data[picks_eeg, :], evoked_ref.data[picks_eeg, :]) + + # add two reference channels to evoked + raw = read_raw_fif(fif_fname, preload=True) + events = read_events(eve_fname) + picks_eeg = pick_types(raw.info, meg=False, eeg=True) + # create epochs in delayed mode, allowing removal of CAR when re-reffing + epochs = Epochs( + raw, + events=events, + event_id=1, + tmin=-0.2, + tmax=0.5, + picks=picks_eeg, + preload=True, + proj="delayed", + ) + evoked = epochs.average() + with pytest.warns(RuntimeWarning, match="for this channel is unknown or ambiguous"): + evoked_ref = add_reference_channels(evoked, ["M1", "M2"], copy=True) + assert_equal(evoked_ref.data.shape[0], evoked.data.shape[0] + 2) + _check_channel_names(evoked_ref, ["M1", "M2"]) + ref_idx = evoked_ref.ch_names.index("M1") + ref_idy = evoked_ref.ch_names.index("M2") + ref_data = evoked_ref.data[[ref_idx, ref_idy], :] + assert_array_equal(ref_data, 0) + picks_eeg = pick_types(evoked.info, meg=False, eeg=True) + assert_array_equal(evoked.data[picks_eeg, :], evoked_ref.data[picks_eeg, :]) + + # Test invalid inputs + raw = read_raw_fif(fif_fname, preload=False) + with pytest.raises(RuntimeError, match="loaded"): + add_reference_channels(raw, ["Ref"]) + raw.load_data() + with pytest.raises(ValueError, match="Channel.*already.*"): + add_reference_channels(raw, raw.ch_names[:1]) + with pytest.raises(TypeError, match="instance of"): + add_reference_channels(raw, 1) + + # gh-10878 + raw = read_raw_fif(raw_fname).crop(0, 1, include_tmax=False).load_data() + data = raw.copy().add_reference_channels(["REF"]).pick(picks="eeg") + data = data.get_data() + epochs = make_fixed_length_epochs(raw).load_data() + data_2 = epochs.copy().add_reference_channels(["REF"]).pick(picks="eeg") + data_2 = data_2.get_data(copy=False)[0] + assert_allclose(data, data_2) + evoked = epochs.average() + data_3 = evoked.copy().add_reference_channels(["REF"]).pick(picks="eeg") + data_3 = data_3.get_data() + assert_allclose(data, data_3) + + +@pytest.mark.parametrize("n_ref", (1, 2)) +def test_add_reorder(n_ref): + """Test that a reference channel can be added and then data reordered.""" + # gh-8300 + raw = read_raw_fif(raw_fname).crop(0, 0.1).del_proj().pick("eeg") + assert len(raw.ch_names) == 60 + chs = [f"EEG {60 + ii:03}" for ii in range(1, n_ref)] + ["EEG 000"] + with pytest.raises(RuntimeError, match="preload"): + with _record_warnings(): # ignore multiple warning + add_reference_channels(raw, chs, copy=False) + raw.load_data() + if n_ref == 1: + ctx = nullcontext() + else: + assert n_ref == 2 + ctx = pytest.warns(RuntimeWarning, match="this channel is unknown or ambiguous") + with ctx: + add_reference_channels(raw, chs, copy=False) + data = raw.get_data() + assert_array_equal(data[-1], 0.0) + assert raw.ch_names[-n_ref:] == chs + raw.reorder_channels(raw.ch_names[-1:] + raw.ch_names[:-1]) + assert raw.ch_names == [f"EEG {ii:03}" for ii in range(60 + n_ref)] + data_new = raw.get_data() + data_new = np.concatenate([data_new[1:], data_new[:1]]) + assert_allclose(data, data_new) + + +def test_bipolar_combinations(): + """Test bipolar channel generation.""" + ch_names = ["CH" + str(ni + 1) for ni in range(10)] + info = create_info( + ch_names=ch_names, sfreq=1000.0, ch_types=["eeg"] * len(ch_names) + ) + raw_data = np.random.randn(len(ch_names), 1000) + raw = RawArray(raw_data, info) + + def _check_bipolar(raw_test, ch_a, ch_b): + picks = [raw_test.ch_names.index(ch_a + "-" + ch_b)] + get_data_res = raw_test.get_data(picks=picks)[0, :] + manual_a = raw_data[ch_names.index(ch_a), :] + manual_b = raw_data[ch_names.index(ch_b), :] + assert_array_equal(get_data_res, manual_a - manual_b) + + # test classic EOG/ECG bipolar reference (only two channels per pair). + raw_test = set_bipolar_reference(raw, ["CH2"], ["CH1"], copy=True) + _check_bipolar(raw_test, "CH2", "CH1") + + # test all combinations. + a_channels, b_channels = zip(*itertools.combinations(ch_names, 2)) + a_channels, b_channels = list(a_channels), list(b_channels) + raw_test = set_bipolar_reference(raw, a_channels, b_channels, copy=True) + for ch_a, ch_b in zip(a_channels, b_channels): + _check_bipolar(raw_test, ch_a, ch_b) + # check if reference channels have been dropped. + assert len(raw_test.ch_names) == len(a_channels) + + raw_test = set_bipolar_reference( + raw, a_channels, b_channels, drop_refs=False, copy=True + ) + # check if reference channels have been kept correctly. + assert len(raw_test.ch_names) == len(a_channels) + len(ch_names) + for idx, ch_label in enumerate(ch_names): + manual_ch = raw_data[np.newaxis, idx] + assert_array_equal(raw_test.get_data(ch_label), manual_ch) + + # test bipolars with a channel in both list (anode & cathode). + raw_test = set_bipolar_reference(raw, ["CH2", "CH1"], ["CH1", "CH2"], copy=True) + _check_bipolar(raw_test, "CH2", "CH1") + _check_bipolar(raw_test, "CH1", "CH2") + + # test if bipolar channel is bad if anode is a bad channel + raw.info["bads"] = ["CH1"] + raw_test = set_bipolar_reference( + raw, ["CH1"], ["CH2"], on_bad="ignore", ch_name="bad_bipolar", copy=True + ) + assert raw_test.info["bads"] == ["bad_bipolar"] + + # test if bipolar channel is bad if cathode is a bad channel + raw.info["bads"] = ["CH2"] + raw_test = set_bipolar_reference( + raw, ["CH1"], ["CH2"], on_bad="ignore", ch_name="bad_bipolar", copy=True + ) + assert raw_test.info["bads"] == ["bad_bipolar"] diff --git a/mne-python/source/mne/_fiff/tests/test_show_fiff.py b/mne-python/source/mne/_fiff/tests/test_show_fiff.py new file mode 100644 index 0000000000000000000000000000000000000000..b771d3bd081774fb43944638d080eb92c99f908c --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_show_fiff.py @@ -0,0 +1,35 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +from mne.io import show_fiff + +base_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +fname_evoked = base_dir / "test-ave.fif" +fname_raw = base_dir / "test_raw.fif" +fname_c_annot = base_dir / "test_raw-annot.fif" + + +def test_show_fiff(): + """Test show_fiff.""" + # this is not exhaustive, but hopefully bugs will be found in use + info = show_fiff(fname_evoked) + assert "BAD" not in info + keys = [ + "FIFF_EPOCH", + "FIFFB_HPI_COIL", + "FIFFB_PROJ_ITEM", + "FIFFB_PROCESSED_DATA", + "FIFFB_EVOKED", + "FIFF_NAVE", + "FIFF_EPOCH", + "COORD_TRANS", + ] + assert all(key in info for key in keys) + info = show_fiff(fname_raw, read_limit=1024) + assert "BAD" not in info + info = show_fiff(fname_c_annot) + assert "BAD" not in info + assert ">B" in info, info diff --git a/mne-python/source/mne/_fiff/tests/test_utils.py b/mne-python/source/mne/_fiff/tests/test_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..ba6748826a393beaa036cb1362a306179e6b0027 --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_utils.py @@ -0,0 +1,18 @@ +"""Run tests for the utilities.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from mne._fiff.utils import _check_orig_units + + +def test_check_orig_units(): + """Test the checking of original units.""" + orig_units = dict(FC1="nV", Hfp3erz="n/a", Pz="uV", greekMu="μV", microSign="µV") + orig_units = _check_orig_units(orig_units) + assert orig_units["FC1"] == "nV" + assert orig_units["Hfp3erz"] == "n/a" + assert orig_units["Pz"] == "µV" + assert orig_units["greekMu"] == "µV" + assert orig_units["microSign"] == "µV" diff --git a/mne-python/source/mne/_fiff/tests/test_what.py b/mne-python/source/mne/_fiff/tests/test_what.py new file mode 100644 index 0000000000000000000000000000000000000000..80bebdceebafbe84ca9f256e8a0efdfaa4a8cf3a --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_what.py @@ -0,0 +1,67 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import glob +from pathlib import Path + +import numpy as np +import pytest + +from mne import create_info, what +from mne.datasets import testing +from mne.io import RawArray +from mne.preprocessing import ICA +from mne.utils import _record_warnings + +data_path = testing.data_path(download=False) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_what(tmp_path, verbose_debug): + """Test mne.what.""" + pytest.importorskip("sklearn") + # ICA + ica = ICA(max_iter=1, random_state=0) + raw = RawArray(np.random.RandomState(0).randn(3, 10), create_info(3, 1000.0, "eeg")) + with _record_warnings(): # convergence sometimes + ica.fit(raw) + fname = tmp_path / "x-ica.fif" + ica.save(fname) + assert what(fname) == "ica" + # test files + fnames = glob.glob(str(data_path / "MEG" / "sample" / "*.fif")) + fnames += glob.glob(str(data_path / "subjects" / "sample" / "bem" / "*.fif")) + fnames += [str(fname)] + fnames = sorted(fnames) + want_dict = dict( + eve="events", + ave="evoked", + cov="cov", + ica="ica", + inv="inverse", + fwd="forward", + trans="transform", + proj="proj", + raw="raw", + sol="bem solution", + bem="bem surfaces", + src="src", + dense="bem surfaces", + head="bem surfaces", + fiducials="fiducials", + ) + got = set() + for fname in fnames: + print(fname) + kind = Path(fname).stem.split("-")[-1] + if len(kind) > 5: + kind = kind.split("_")[-1] + this = what(fname) + assert this == want_dict[kind], fname + print() + got.add(kind) + assert set(want_dict) == got + fname = data_path / "MEG" / "sample" / "sample_audvis-ave_xfit.dip" + assert what(fname) == "unknown" diff --git a/mne-python/source/mne/_fiff/tests/test_write.py b/mne-python/source/mne/_fiff/tests/test_write.py new file mode 100644 index 0000000000000000000000000000000000000000..43087ec0dc8a9086f87179def062ab84d6cdb132 --- /dev/null +++ b/mne-python/source/mne/_fiff/tests/test_write.py @@ -0,0 +1,21 @@ +"""Run tests for writing.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import pytest + +from mne._fiff.constants import FIFF +from mne._fiff.write import start_file, write_int + + +def test_write_int(tmp_path): + """Test that write_int raises an error on bad values.""" + with start_file(tmp_path / "temp.fif") as fid: + write_int(fid, FIFF.FIFF_MNE_EVENT_LIST, [2147483647]) # 2 ** 31 - 1 + write_int(fid, FIFF.FIFF_MNE_EVENT_LIST, []) # 2 ** 31 - 1 + with pytest.raises(TypeError, match=r".*exceeds max.*EVENT_LIST\)"): + write_int(fid, FIFF.FIFF_MNE_EVENT_LIST, [2147483648]) # 2 ** 31 + with pytest.raises(TypeError, match="Cannot safely write"): + write_int(fid, FIFF.FIFF_MNE_EVENT_LIST, [0.0]) # float diff --git a/mne-python/source/mne/_fiff/tree.py b/mne-python/source/mne/_fiff/tree.py new file mode 100644 index 0000000000000000000000000000000000000000..142c40aa5a844ef60138fc146d7a6ee4325decc1 --- /dev/null +++ b/mne-python/source/mne/_fiff/tree.py @@ -0,0 +1,108 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + + +from ..utils import logger, verbose +from .constants import FIFF +from .tag import read_tag + + +def dir_tree_find(tree, kind): + """Find nodes of the given kind from a directory tree structure. + + Parameters + ---------- + tree : dict + Directory tree. + kind : int + Kind to find. + + Returns + ------- + nodes : list + List of matching nodes. + """ + nodes = [] + + if isinstance(tree, list): + for t in tree: + nodes += dir_tree_find(t, kind) + else: + # Am I desirable myself? + if tree["block"] == kind: + nodes.append(tree) + + # Search the subtrees + for child in tree["children"]: + nodes += dir_tree_find(child, kind) + return nodes + + +@verbose +def make_dir_tree(fid, directory, start=0, indent=0, verbose=None): + """Create the directory tree structure.""" + if directory[start].kind == FIFF.FIFF_BLOCK_START: + tag = read_tag(fid, directory[start].pos) + block = tag.data.item() + else: + block = 0 + + start_separate = False + + this = start + + tree = dict() + tree["block"] = block + tree["id"] = None + tree["parent_id"] = None + tree["nent"] = 0 + tree["nchild"] = 0 + tree["directory"] = directory[this] + tree["children"] = [] + + while this < len(directory): + if directory[this].kind == FIFF.FIFF_BLOCK_START: + if this != start: + if not start_separate: + start_separate = True + logger.debug(" " * indent + f"start {{ {block}") + child, this = make_dir_tree(fid, directory, this, indent + 1) + tree["nchild"] += 1 + tree["children"].append(child) + elif directory[this].kind == FIFF.FIFF_BLOCK_END: + tag = read_tag(fid, directory[start].pos) + if tag.data == block: + break + else: + tree["nent"] += 1 + if tree["nent"] == 1: + tree["directory"] = list() + tree["directory"].append(directory[this]) + + # Add the id information if available + if block == 0: + if directory[this].kind == FIFF.FIFF_FILE_ID: + tag = read_tag(fid, directory[this].pos) + tree["id"] = tag.data + else: + if directory[this].kind == FIFF.FIFF_BLOCK_ID: + tag = read_tag(fid, directory[this].pos) + tree["id"] = tag.data + elif directory[this].kind == FIFF.FIFF_PARENT_BLOCK_ID: + tag = read_tag(fid, directory[this].pos) + tree["parent_id"] = tag.data + + this += 1 + + # Eliminate the empty directory + if tree["nent"] == 0: + tree["directory"] = None + + content = f"block = {tree['block']} nent = {tree['nent']} nchild = {tree['nchild']}" + if start_separate: + logger.debug(" " * indent + f"end }} {content}") + else: + logger.debug(" " * indent + content) + last = this + return tree, last diff --git a/mne-python/source/mne/_fiff/utils.py b/mne-python/source/mne/_fiff/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..b158914bb88ba47daaa43ae430038685cf1db151 --- /dev/null +++ b/mne-python/source/mne/_fiff/utils.py @@ -0,0 +1,331 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import os.path as op +from pathlib import Path + +import numpy as np + +from .constants import FIFF +from .meas_info import _get_valid_units + + +def _check_orig_units(orig_units): + """Check original units from a raw file. + + Units that are close to a valid_unit but not equal can be remapped to fit + into the valid_units. All other units that are not valid will be replaced + with "n/a". + + Parameters + ---------- + orig_units : dict + Dictionary mapping channel names to their units as specified in + the header file. Example: {'FC1': 'nV'} + + Returns + ------- + orig_units_remapped : dict + Dictionary mapping channel names to their VALID units as specified in + the header file. Invalid units are now labeled "n/a". + Example: {'FC1': 'nV', 'Hfp3erz': 'n/a'} + """ + if orig_units is None: + return + valid_units = _get_valid_units() + valid_units_lowered = [unit.lower() for unit in valid_units] + orig_units_remapped = dict(orig_units) + for ch_name, unit in orig_units.items(): + # Be lenient: we ignore case for now. + if unit.lower() in valid_units_lowered: + continue + + # Common "invalid units" can be remapped to their valid equivalent + remap_dict = dict() + remap_dict["uv"] = "µV" + remap_dict["μv"] = "µV" # greek letter mu vs micro sign. use micro + remap_dict["\x83\xeav"] = "µV" # for shift-jis mu, use micro + if unit.lower() in remap_dict: + orig_units_remapped[ch_name] = remap_dict[unit.lower()] + continue + + # Some units cannot be saved, they are invalid: assign "n/a" + orig_units_remapped[ch_name] = "n/a" + + return orig_units_remapped + + +def _find_channels(ch_names, ch_type="EOG"): + """Find EOG channel.""" + substrings = (ch_type,) + substrings = [s.upper() for s in substrings] + if ch_type == "EOG": + substrings = ("EOG", "EYE") + eog_idx = [ + idx + for idx, ch in enumerate(ch_names) + if any(substring in ch.upper() for substring in substrings) + ] + return eog_idx + + +def _mult_cal_one(data_view, one, idx, cals, mult): + """Take a chunk of raw data, multiply by mult or cals, and store.""" + one = np.asarray(one, dtype=data_view.dtype) + assert data_view.shape[1] == one.shape[1], ( + data_view.shape[1], + one.shape[1], + ) # noqa: E501 + if mult is not None: + assert mult.ndim == one.ndim == 2 + data_view[:] = mult @ one[idx] + else: + assert cals is not None + if isinstance(idx, slice): + data_view[:] = one[idx] + else: + # faster than doing one = one[idx] + np.take(one, idx, axis=0, out=data_view) + data_view *= cals + + +def _blk_read_lims(start, stop, buf_len): + """Deal with indexing in the middle of a data block. + + Parameters + ---------- + start : int + Starting index. + stop : int + Ending index (exclusive). + buf_len : int + Buffer size in samples. + + Returns + ------- + block_start_idx : int + The first block to start reading from. + r_lims : list + The read limits. + d_lims : list + The write limits. + + Notes + ----- + Consider this example:: + + >>> start, stop, buf_len = 2, 27, 10 + + +---------+---------+--------- + File structure: | buf0 | buf1 | buf2 | + +---------+---------+--------- + File time: 0 10 20 30 + +---------+---------+--------- + Requested time: 2 27 + + | | + blockstart blockstop + | | + start stop + + We need 27 - 2 = 25 samples (per channel) to store our data, and + we need to read from 3 buffers (30 samples) to get all of our data. + + On all reads but the first, the data we read starts at + the first sample of the buffer. On all reads but the last, + the data we read ends on the last sample of the buffer. + + We call ``this_data`` the variable that stores the current buffer's data, + and ``data`` the variable that stores the total output. + + On the first read, we need to do this:: + + >>> data[0:buf_len-2] = this_data[2:buf_len] # doctest: +SKIP + + On the second read, we need to do:: + + >>> data[1*buf_len-2:2*buf_len-2] = this_data[0:buf_len] # doctest: +SKIP + + On the final read, we need to do:: + + >>> data[2*buf_len-2:3*buf_len-2-3] = this_data[0:buf_len-3] # doctest: +SKIP + + This function encapsulates this logic to allow a loop over blocks, where + data is stored using the following limits:: + + >>> data[d_lims[ii, 0]:d_lims[ii, 1]] = this_data[r_lims[ii, 0]:r_lims[ii, 1]] # doctest: +SKIP + + """ # noqa: E501 + # this is used to deal with indexing in the middle of a sampling period + assert all(isinstance(x, int) for x in (start, stop, buf_len)) + block_start_idx = start // buf_len + block_start = block_start_idx * buf_len + last_used_samp = stop - 1 + block_stop = last_used_samp - last_used_samp % buf_len + buf_len + read_size = block_stop - block_start + n_blk = read_size // buf_len + (read_size % buf_len != 0) + start_offset = start - block_start + end_offset = block_stop - stop + d_lims = np.empty((n_blk, 2), int) + r_lims = np.empty((n_blk, 2), int) + for bi in range(n_blk): + # Triage start (sidx) and end (eidx) indices for + # data (d) and read (r) + if bi == 0: + d_sidx = 0 + r_sidx = start_offset + else: + d_sidx = bi * buf_len - start_offset + r_sidx = 0 + if bi == n_blk - 1: + d_eidx = stop - start + r_eidx = buf_len - end_offset + else: + d_eidx = (bi + 1) * buf_len - start_offset + r_eidx = buf_len + d_lims[bi] = [d_sidx, d_eidx] + r_lims[bi] = [r_sidx, r_eidx] + return block_start_idx, r_lims, d_lims + + +def _file_size(fname): + """Get the file size in bytes.""" + with open(fname, "rb") as f: + f.seek(0, os.SEEK_END) + return f.tell() + + +def _read_segments_file( + raw, + data, + idx, + fi, + start, + stop, + cals, + mult, + dtype, + n_channels=None, + offset=0, + trigger_ch=None, +): + """Read a chunk of raw data.""" + if n_channels is None: + n_channels = raw._raw_extras[fi]["orig_nchan"] + + n_bytes = np.dtype(dtype).itemsize + # data_offset and data_left count data samples (channels x time points), + # not bytes. + data_offset = n_channels * start * n_bytes + offset + data_left = (stop - start) * n_channels + + # Read up to 100 MB of data at a time, block_size is in data samples + block_size = ((int(100e6) // n_bytes) // n_channels) * n_channels + block_size = min(data_left, block_size) + with open(raw.filenames[fi], "rb", buffering=0) as fid: + fid.seek(data_offset) + # extract data in chunks + for sample_start in np.arange(0, data_left, block_size) // n_channels: + count = min(block_size, data_left - sample_start * n_channels) + block = np.fromfile(fid, dtype, count) + if block.size != count: + raise RuntimeError( + f"Incorrect number of samples ({block.size} != {count}), please " + "report this error to MNE-Python developers" + ) + block = block.reshape(n_channels, -1, order="F") + n_samples = block.shape[1] # = count // n_channels + sample_stop = sample_start + n_samples + if trigger_ch is not None: + stim_ch = trigger_ch[start:stop][sample_start:sample_stop] + block = np.vstack((block, stim_ch)) + data_view = data[:, sample_start:sample_stop] + _mult_cal_one(data_view, block, idx, cals, mult) + + +def read_str(fid, count=1): + """Read string from a binary file in a python version compatible way.""" + dtype = np.dtype(f">S{count}") + string = fid.read(dtype.itemsize) + data = np.frombuffer(string, dtype=dtype)[0] + bytestr = b"".join([data[0 : data.index(b"\x00") if b"\x00" in data else count]]) + + return str(bytestr.decode("ascii")) # Return native str type for Py2/3 + + +def _create_chs(ch_names, cals, ch_coil, ch_kind, eog, ecg, emg, misc): + """Initialize info['chs'] for eeg channels.""" + chs = list() + for idx, ch_name in enumerate(ch_names): + if ch_name in eog or idx in eog: + coil_type = FIFF.FIFFV_COIL_NONE + kind = FIFF.FIFFV_EOG_CH + elif ch_name in ecg or idx in ecg: + coil_type = FIFF.FIFFV_COIL_NONE + kind = FIFF.FIFFV_ECG_CH + elif ch_name in emg or idx in emg: + coil_type = FIFF.FIFFV_COIL_NONE + kind = FIFF.FIFFV_EMG_CH + elif ch_name in misc or idx in misc: + coil_type = FIFF.FIFFV_COIL_NONE + kind = FIFF.FIFFV_MISC_CH + else: + coil_type = ch_coil + kind = ch_kind + + chan_info = { + "cal": cals[idx], + "logno": idx + 1, + "scanno": idx + 1, + "range": 1.0, + "unit_mul": FIFF.FIFF_UNITM_NONE, + "ch_name": ch_name, + "unit": FIFF.FIFF_UNIT_V, + "coord_frame": FIFF.FIFFV_COORD_HEAD, + "coil_type": coil_type, + "kind": kind, + "loc": np.zeros(12), + } + if coil_type == FIFF.FIFFV_COIL_EEG: + chan_info["loc"][:3] = np.nan + chs.append(chan_info) + return chs + + +def _construct_bids_filename(base, ext, part_idx, validate=True): + """Construct a BIDS compatible filename for split files.""" + # insert index in filename + dirname = op.dirname(base) + base = op.basename(base) + deconstructed_base = base.split("_") + if len(deconstructed_base) < 2 and validate: + raise ValueError( + "Filename base must end with an underscore followed " + f"by the modality (e.g., _eeg or _meg), got {base}" + ) + suffix = deconstructed_base[-1] + base = "_".join(deconstructed_base[:-1]) + use_fname = f"{base}_split-{part_idx + 1:02}_{suffix}{ext}" + if dirname: + use_fname = op.join(dirname, use_fname) + return use_fname + + +def _make_split_fnames(fname, n_splits, split_naming): + """Make a list of split filenames.""" + if n_splits == 1: + fname = Path(fname) + return [fname] + res = [] + base, ext = op.splitext(fname) + for i in range(n_splits): + if split_naming == "neuromag": + path = Path(f"{base}-{i:d}{ext}" if i else fname) + res.append(path) + else: + assert split_naming == "bids" + path = Path(_construct_bids_filename(base, ext, i)) + res.append(path) + return res diff --git a/mne-python/source/mne/_fiff/what.py b/mne-python/source/mne/_fiff/what.py new file mode 100644 index 0000000000000000000000000000000000000000..d91f79da5cf3638d7893d8c09da353b3050dcd2f --- /dev/null +++ b/mne-python/source/mne/_fiff/what.py @@ -0,0 +1,70 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from collections import OrderedDict +from inspect import signature + +from ..utils import _check_fname, logger + + +def what(fname): + """Try to determine the type of the FIF file. + + Parameters + ---------- + fname : path-like + The filename. Should end in ``.fif`` or ``.fif.gz``. + + Returns + ------- + what : str | None + The type of the file. Will be 'unknown' if it could not be determined. + + Notes + ----- + .. versionadded:: 0.19 + """ + from ..bem import read_bem_solution, read_bem_surfaces + from ..cov import read_cov + from ..epochs import read_epochs + from ..event import read_events + from ..evoked import read_evokeds + from ..forward import read_forward_solution + from ..io import read_raw_fif + from ..minimum_norm import read_inverse_operator + from ..preprocessing import read_ica + from ..proj import read_proj + from ..source_space import read_source_spaces + from ..transforms import read_trans + from .meas_info import read_fiducials + + fname = _check_fname(fname, overwrite="read", must_exist=True) + checks = OrderedDict() + checks["raw"] = read_raw_fif + checks["ica"] = read_ica + checks["epochs"] = read_epochs + checks["evoked"] = read_evokeds + checks["forward"] = read_forward_solution + checks["inverse"] = read_inverse_operator + checks["src"] = read_source_spaces + checks["bem solution"] = read_bem_solution + checks["bem surfaces"] = read_bem_surfaces + checks["cov"] = read_cov + checks["transform"] = read_trans + checks["events"] = read_events + checks["fiducials"] = read_fiducials + checks["proj"] = read_proj + for what, func in checks.items(): + args = signature(func).parameters + assert "verbose" in args, func + kwargs = dict(verbose="error") + if "preload" in args: + kwargs["preload"] = False + try: + func(fname, **kwargs) + except Exception as exp: + logger.debug(f"Not {what}: {exp}") + else: + return what + return "unknown" diff --git a/mne-python/source/mne/_fiff/write.py b/mne-python/source/mne/_fiff/write.py new file mode 100644 index 0000000000000000000000000000000000000000..8486ca13121b9cdc3e9c9bfa9d8089ea58d60f91 --- /dev/null +++ b/mne-python/source/mne/_fiff/write.py @@ -0,0 +1,455 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime +import os.path as op +import re +import time +import uuid +from contextlib import contextmanager +from gzip import GzipFile + +import numpy as np +from scipy.sparse import csc_array, csr_array + +from ..utils import _check_fname, _file_like, _validate_type, logger +from ..utils.numerics import _date_to_julian +from .constants import FIFF + +# We choose a "magic" date to store (because meas_date is obligatory) +# to treat as meas_date=None. This one should be impossible for systems +# to write -- the second field is microseconds, so anything >= 1e6 +# should be moved into the first field (seconds). +DATE_NONE = (0, 2**31 - 1) + + +def _write(fid, data, kind, data_size, FIFFT_TYPE, dtype): + """Write data.""" + if isinstance(data, np.ndarray): + data_size *= data.size + + # XXX for string types the data size is used as + # computed in ``write_string``. + + fid.write(np.array(kind, dtype=">i4").tobytes()) + fid.write(np.array(FIFFT_TYPE, dtype=">i4").tobytes()) + fid.write(np.array(data_size, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFV_NEXT_SEQ, dtype=">i4").tobytes()) + fid.write(np.array(data, dtype=dtype).tobytes()) + + +def _get_split_size(split_size): + """Convert human-readable bytes to machine-readable bytes.""" + if isinstance(split_size, str): + exp = dict(MB=20, GB=30).get(split_size[-2:], None) + if exp is None: + raise ValueError('split_size has to end with either "MB" or "GB"') + split_size = int(float(split_size[:-2]) * 2**exp) + + if split_size > 2147483648: + raise ValueError("split_size cannot be larger than 2GB") + return split_size + + +_NEXT_FILE_BUFFER = 1048576 # 2 ** 20 extra cushion for last post-data tags + + +def write_nop(fid, last=False): + """Write a FIFF_NOP.""" + fid.write(np.array(FIFF.FIFF_NOP, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFT_VOID, dtype=">i4").tobytes()) + fid.write(np.array(0, dtype=">i4").tobytes()) + next_ = FIFF.FIFFV_NEXT_NONE if last else FIFF.FIFFV_NEXT_SEQ + fid.write(np.array(next_, dtype=">i4").tobytes()) + + +INT32_MAX = 2147483647 + + +def write_int(fid, kind, data): + """Write a 32-bit integer tag to a fif file.""" + data_size = 4 + data = np.asarray(data) + if data.dtype.kind not in "uib" and data.size > 0: + raise TypeError( + f"Cannot safely write data kind {kind} with dtype {data.dtype} as int", + ) + max_val = data.max() if data.size > 0 else 0 + if max_val > INT32_MAX: + raise TypeError( + f"Value {max_val} exceeds maximum allowed ({INT32_MAX}) for tag {kind}" + ) + data = data.astype(">i4").T + _write(fid, data, kind, data_size, FIFF.FIFFT_INT, ">i4") + + +def write_double(fid, kind, data): + """Write a double-precision floating point tag to a fif file.""" + data_size = 8 + data = np.array(data, dtype=">f8").T + _write(fid, data, kind, data_size, FIFF.FIFFT_DOUBLE, ">f8") + + +def write_float(fid, kind, data): + """Write a single-precision floating point tag to a fif file.""" + data_size = 4 + data = np.array(data, dtype=">f4").T + _write(fid, data, kind, data_size, FIFF.FIFFT_FLOAT, ">f4") + + +def write_dau_pack16(fid, kind, data): + """Write a dau_pack16 tag to a fif file.""" + data_size = 2 + data = np.array(data, dtype=">i2").T + _write(fid, data, kind, data_size, FIFF.FIFFT_DAU_PACK16, ">i2") + + +def write_complex64(fid, kind, data): + """Write a 64 bit complex floating point tag to a fif file.""" + data_size = 8 + data = np.array(data, dtype=">c8").T + _write(fid, data, kind, data_size, FIFF.FIFFT_COMPLEX_FLOAT, ">c8") + + +def write_complex128(fid, kind, data): + """Write a 128 bit complex floating point tag to a fif file.""" + data_size = 16 + data = np.array(data, dtype=">c16").T + _write(fid, data, kind, data_size, FIFF.FIFFT_COMPLEX_FLOAT, ">c16") + + +def write_julian(fid, kind, data): + """Write a Julian-formatted date to a FIF file.""" + assert isinstance(data, datetime.date), type(data) + data_size = 4 + jd = _date_to_julian(data) + data = np.array(jd, dtype=">i4") + _write(fid, data, kind, data_size, FIFF.FIFFT_JULIAN, ">i4") + + +def write_string(fid, kind, data): + """Write a string tag.""" + try: + str_data = str(data).encode("latin1") + except UnicodeEncodeError: + str_data = str(data).encode("latin1", errors="xmlcharrefreplace") + data_size = len(str_data) # therefore compute size here + if data_size > 0: + _write(fid, str_data, kind, data_size, FIFF.FIFFT_STRING, ">S") + + +def write_name_list(fid, kind, data): + """Write a colon-separated list of names. + + Parameters + ---------- + data : list of strings + """ + write_string(fid, kind, ":".join(data)) + + +def write_name_list_sanitized(fid, kind, lst, name): + """Write a sanitized, colon-separated list of names.""" + write_string(fid, kind, _safe_name_list(lst, "write", name)) + + +def _safe_name_list(lst, operation, name): + if operation == "write": + assert isinstance(lst, list | tuple | np.ndarray), type(lst) + if any("{COLON}" in val for val in lst): + raise ValueError(f'The substring "{{COLON}}" in {name} not supported.') + return ":".join(val.replace(":", "{COLON}") for val in lst) + else: + # take a sanitized string and return a list of strings + assert operation == "read" + assert lst is None or isinstance(lst, str) + if not lst: # None or empty string + return [] + return [val.replace("{COLON}", ":") for val in lst.split(":")] + + +def write_float_matrix(fid, kind, mat): + """Write a single-precision floating-point matrix tag.""" + _write_matrix_data(fid, kind, mat, FIFF.FIFFT_FLOAT) + + +def write_double_matrix(fid, kind, mat): + """Write a double-precision floating-point matrix tag.""" + _write_matrix_data(fid, kind, mat, FIFF.FIFFT_DOUBLE) + + +def write_int_matrix(fid, kind, mat): + """Write integer 32 matrix tag.""" + _write_matrix_data(fid, kind, mat, FIFF.FIFFT_INT) + + +def write_complex_float_matrix(fid, kind, mat): + """Write complex 64 matrix tag.""" + _write_matrix_data(fid, kind, mat, FIFF.FIFFT_COMPLEX_FLOAT) + + +def write_complex_double_matrix(fid, kind, mat): + """Write complex 128 matrix tag.""" + _write_matrix_data(fid, kind, mat, FIFF.FIFFT_COMPLEX_DOUBLE) + + +def _write_matrix_data(fid, kind, mat, data_type): + dtype = { + FIFF.FIFFT_FLOAT: ">f4", + FIFF.FIFFT_DOUBLE: ">f8", + FIFF.FIFFT_COMPLEX_FLOAT: ">c8", + FIFF.FIFFT_COMPLEX_DOUBLE: ">c16", + FIFF.FIFFT_INT: ">i4", + }[data_type] + dtype = np.dtype(dtype) + data_size = dtype.itemsize * mat.size + 4 * (mat.ndim + 1) + matrix_type = data_type | FIFF.FIFFT_MATRIX + fid.write(np.array(kind, dtype=">i4").tobytes()) + fid.write(np.array(matrix_type, dtype=">i4").tobytes()) + fid.write(np.array(data_size, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFV_NEXT_SEQ, dtype=">i4").tobytes()) + fid.write(np.array(mat, dtype=dtype).tobytes()) + dims = np.empty(mat.ndim + 1, dtype=np.int32) + dims[: mat.ndim] = mat.shape[::-1] + dims[-1] = mat.ndim + fid.write(np.array(dims, dtype=">i4").tobytes()) + check_fiff_length(fid) + + +def get_machid(): + """Get (mostly) unique machine ID. + + Returns + ------- + ids : array (length 2, int32) + The machine identifier used in MNE. + """ + mac = f"{uuid.getnode():012x}".encode() # byte conversion for Py3 + mac = re.findall(b"..", mac) # split string + mac += [b"00", b"00"] # add two more fields + + # Convert to integer in reverse-order (for some reason) + from codecs import encode + + mac = b"".join([encode(h, "hex_codec") for h in mac[::-1]]) + ids = np.flipud(np.frombuffer(mac, np.int32, count=2)) + return ids + + +def get_new_file_id(): + """Create a new file ID tag.""" + secs, usecs = divmod(time.time(), 1.0) + secs, usecs = int(secs), int(usecs * 1e6) + return { + "machid": get_machid(), + "version": FIFF.FIFFC_VERSION, + "secs": secs, + "usecs": usecs, + } + + +def write_id(fid, kind, id_=None): + """Write fiff id.""" + id_ = _generate_meas_id() if id_ is None else id_ + + data_size = 5 * 4 # The id comprises five integers + fid.write(np.array(kind, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFT_ID_STRUCT, dtype=">i4").tobytes()) + fid.write(np.array(data_size, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFV_NEXT_SEQ, dtype=">i4").tobytes()) + + # Collect the bits together for one write + arr = np.array( + [id_["version"], id_["machid"][0], id_["machid"][1], id_["secs"], id_["usecs"]], + dtype=">i4", + ) + fid.write(arr.tobytes()) + + +def start_block(fid, kind): + """Write a FIFF_BLOCK_START tag.""" + write_int(fid, FIFF.FIFF_BLOCK_START, kind) + + +def end_block(fid, kind): + """Write a FIFF_BLOCK_END tag.""" + write_int(fid, FIFF.FIFF_BLOCK_END, kind) + + +def start_file(fname, id_=None, *, overwrite=True): + """Open a fif file for writing and writes the compulsory header tags. + + Parameters + ---------- + fname : path-like | fid + The name of the file to open. It is recommended + that the name ends with .fif or .fif.gz. Can also be an + already opened file. + id_ : dict | None + ID to use for the FIFF_FILE_ID. + """ + if _file_like(fname): + logger.debug(f"Writing using {type(fname)} I/O") + fid = fname + fid.seek(0) + else: + fname = _check_fname(fname, overwrite=overwrite) + fname = str(fname) + if op.splitext(fname)[1].lower() == ".gz": + logger.debug("Writing using gzip") + # defaults to compression level 9, which is barely smaller but much + # slower. 2 offers a good compromise. + fid = GzipFile(fname, "wb", compresslevel=2) + else: + logger.debug("Writing using normal I/O") + fid = open(fname, "wb") + # Write the compulsory items + write_id(fid, FIFF.FIFF_FILE_ID, id_) + write_int(fid, FIFF.FIFF_DIR_POINTER, -1) + write_int(fid, FIFF.FIFF_FREE_LIST, -1) + return fid + + +@contextmanager +def start_and_end_file(fname, id_=None, *, overwrite=True): + """Start and (if successfully written) close the file.""" + with start_file(fname, id_=id_, overwrite=overwrite) as fid: + yield fid + end_file(fid) # we only hit this line if the yield does not err + + +def check_fiff_length(fid, close=True): + """Ensure our file hasn't grown too large to work properly.""" + if fid.tell() > 2147483648: # 2 ** 31, FIFF uses signed 32-bit locations + if close: + fid.close() + raise OSError( + "FIFF file exceeded 2GB limit, please split file, reduce" + " split_size (if possible), or save to a different " + "format" + ) + + +def end_file(fid): + """Write the closing tags to a fif file and closes the file.""" + write_nop(fid, last=True) + check_fiff_length(fid) + fid.close() + + +def write_coord_trans(fid, trans): + """Write a coordinate transformation structure.""" + data_size = 4 * 2 * 12 + 4 * 2 + fid.write(np.array(FIFF.FIFF_COORD_TRANS, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFT_COORD_TRANS_STRUCT, dtype=">i4").tobytes()) + fid.write(np.array(data_size, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFV_NEXT_SEQ, dtype=">i4").tobytes()) + fid.write(np.array(trans["from"], dtype=">i4").tobytes()) + fid.write(np.array(trans["to"], dtype=">i4").tobytes()) + + # The transform... + rot = trans["trans"][:3, :3] + move = trans["trans"][:3, 3] + fid.write(np.array(rot, dtype=">f4").tobytes()) + fid.write(np.array(move, dtype=">f4").tobytes()) + + # ...and its inverse + trans_inv = np.linalg.inv(trans["trans"]) + rot = trans_inv[:3, :3] + move = trans_inv[:3, 3] + fid.write(np.array(rot, dtype=">f4").tobytes()) + fid.write(np.array(move, dtype=">f4").tobytes()) + + +def write_ch_info(fid, ch): + """Write a channel information record to a fif file.""" + data_size = 4 * 13 + 4 * 7 + 16 + + fid.write(np.array(FIFF.FIFF_CH_INFO, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFT_CH_INFO_STRUCT, dtype=">i4").tobytes()) + fid.write(np.array(data_size, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFV_NEXT_SEQ, dtype=">i4").tobytes()) + + # Start writing fiffChInfoRec + fid.write(np.array(ch["scanno"], dtype=">i4").tobytes()) + fid.write(np.array(ch["logno"], dtype=">i4").tobytes()) + fid.write(np.array(ch["kind"], dtype=">i4").tobytes()) + fid.write(np.array(ch["range"], dtype=">f4").tobytes()) + fid.write(np.array(ch["cal"], dtype=">f4").tobytes()) + fid.write(np.array(ch["coil_type"], dtype=">i4").tobytes()) + fid.write(np.array(ch["loc"], dtype=">f4").tobytes()) # writing 12 values + + # unit and unit multiplier + fid.write(np.array(ch["unit"], dtype=">i4").tobytes()) + fid.write(np.array(ch["unit_mul"], dtype=">i4").tobytes()) + + # Finally channel name + ch_name = ch["ch_name"][:15] + fid.write(np.array(ch_name, dtype=">c").tobytes()) + fid.write(b"\0" * (16 - len(ch_name))) + + +def write_dig_points(fid, dig, block=False, coord_frame=None, *, ch_names=None): + """Write a set of digitizer data points into a fif file.""" + if dig is not None: + data_size = 5 * 4 + if block: + start_block(fid, FIFF.FIFFB_ISOTRAK) + if coord_frame is not None: + write_int(fid, FIFF.FIFF_MNE_COORD_FRAME, coord_frame) + for d in dig: + fid.write(np.array(FIFF.FIFF_DIG_POINT, ">i4").tobytes()) + fid.write(np.array(FIFF.FIFFT_DIG_POINT_STRUCT, ">i4").tobytes()) + fid.write(np.array(data_size, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFV_NEXT_SEQ, ">i4").tobytes()) + # Start writing fiffDigPointRec + fid.write(np.array(d["kind"], ">i4").tobytes()) + fid.write(np.array(d["ident"], ">i4").tobytes()) + fid.write(np.array(d["r"][:3], ">f4").tobytes()) + if ch_names is not None: + write_name_list_sanitized( + fid, FIFF.FIFF_MNE_CH_NAME_LIST, ch_names, "ch_names" + ) + if block: + end_block(fid, FIFF.FIFFB_ISOTRAK) + + +def write_float_sparse_rcs(fid, kind, mat): + """Write a single-precision sparse compressed row matrix tag.""" + return write_float_sparse(fid, kind, mat, fmt="csr") + + +def write_float_sparse(fid, kind, mat, fmt="auto"): + """Write a single-precision floating-point sparse matrix tag.""" + if fmt == "auto": + fmt = "csr" if isinstance(mat, csr_array) else "csc" + need = csr_array if fmt == "csr" else csc_array + matrix_type = getattr(FIFF, f"FIFFT_SPARSE_{fmt[-1].upper()}CS_MATRIX") + _validate_type(mat, need, "sparse") + matrix_type = matrix_type | FIFF.FIFFT_MATRIX | FIFF.FIFFT_FLOAT + nnzm = mat.nnz + nrow = mat.shape[0] + data_size = 4 * nnzm + 4 * nnzm + 4 * (nrow + 1) + 4 * 4 + + fid.write(np.array(kind, dtype=">i4").tobytes()) + fid.write(np.array(matrix_type, dtype=">i4").tobytes()) + fid.write(np.array(data_size, dtype=">i4").tobytes()) + fid.write(np.array(FIFF.FIFFV_NEXT_SEQ, dtype=">i4").tobytes()) + + fid.write(np.array(mat.data, dtype=">f4").tobytes()) + fid.write(np.array(mat.indices, dtype=">i4").tobytes()) + fid.write(np.array(mat.indptr, dtype=">i4").tobytes()) + + dims = [nnzm, mat.shape[0], mat.shape[1], 2] + fid.write(np.array(dims, dtype=">i4").tobytes()) + check_fiff_length(fid) + + +def _generate_meas_id(): + """Generate a new meas_id dict.""" + id_ = dict() + id_["version"] = FIFF.FIFFC_VERSION + id_["machid"] = get_machid() + id_["secs"], id_["usecs"] = DATE_NONE + return id_ diff --git a/mne-python/source/mne/_freesurfer.py b/mne-python/source/mne/_freesurfer.py new file mode 100644 index 0000000000000000000000000000000000000000..9b4ec3d4a742b47c5f8d4bd87be3d0311fc94788 --- /dev/null +++ b/mne-python/source/mne/_freesurfer.py @@ -0,0 +1,854 @@ +"""Freesurfer handling functions.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op +from gzip import GzipFile +from pathlib import Path + +import numpy as np + +from ._fiff.constants import FIFF +from ._fiff.meas_info import read_fiducials +from .surface import _read_mri_surface, read_surface +from .transforms import ( + Transform, + _ensure_trans, + apply_trans, + combine_transforms, + invert_transform, + read_ras_mni_t, +) +from .utils import ( + _check_fname, + _check_option, + _import_nibabel, + _validate_type, + get_subjects_dir, + logger, + verbose, +) + + +def _check_subject_dir(subject, subjects_dir): + """Check that the Freesurfer subject directory is as expected.""" + subjects_dir = Path(get_subjects_dir(subjects_dir, raise_error=True)) + for img_name in ("T1", "brain", "aseg"): + if not (subjects_dir / subject / "mri" / f"{img_name}.mgz").is_file(): + raise ValueError( + "Freesurfer recon-all subject folder " + "is incorrect or improperly formatted, " + f"got {subjects_dir / subject}" + ) + return subjects_dir / subject + + +def _get_aseg(aseg, subject, subjects_dir): + """Check that the anatomical segmentation file exists and load it.""" + nib = _import_nibabel("load aseg") + subjects_dir = Path(get_subjects_dir(subjects_dir, raise_error=True)) + if aseg == "auto": # use aparc+aseg if auto + aseg = _check_fname( + subjects_dir / subject / "mri" / "aparc+aseg.mgz", + overwrite="read", + must_exist=False, + ) + if not aseg: # if doesn't exist use wmparc + aseg = subjects_dir / subject / "mri" / "wmparc.mgz" + else: + aseg = subjects_dir / subject / "mri" / f"{aseg}.mgz" + _check_fname(aseg, overwrite="read", must_exist=True) + aseg = nib.load(aseg) + aseg_data = np.array(aseg.dataobj) + return aseg, aseg_data + + +def _reorient_image(img, axcodes="RAS"): + """Reorient an image to a given orientation. + + Parameters + ---------- + img : instance of SpatialImage + The MRI image. + axcodes : tuple | str + The axis codes specifying the orientation, e.g. "RAS". + See :func:`nibabel.orientations.aff2axcodes`. + + Returns + ------- + img_data : ndarray + The reoriented image data. + vox_ras_t : ndarray + The new transform from the new voxels to surface RAS. + + Notes + ----- + .. versionadded:: 0.24 + """ + nib = _import_nibabel("reorient MRI image") + orig_data = np.array(img.dataobj).astype(np.float32) + # reorient data to RAS + ornt = nib.orientations.axcodes2ornt( + nib.orientations.aff2axcodes(img.affine) + ).astype(int) + ras_ornt = nib.orientations.axcodes2ornt(axcodes) + ornt_trans = nib.orientations.ornt_transform(ornt, ras_ornt) + img_data = nib.orientations.apply_orientation(orig_data, ornt_trans) + orig_mgh = nib.MGHImage(orig_data, img.affine) + aff_trans = nib.orientations.inv_ornt_aff(ornt_trans, img.shape) + vox_ras_t = np.dot(orig_mgh.header.get_vox2ras_tkr(), aff_trans) + return img_data, vox_ras_t + + +def _mri_orientation(orientation): + """Get MRI orientation information from an image. + + Parameters + ---------- + orientation : str + Orientation that you want. Can be "axial", "sagittal", or "coronal". + + Returns + ------- + axis : int + The dimension of the axis to take slices over when plotting. + x : int + The dimension of the x axis. + y : int + The dimension of the y axis. + + Notes + ----- + .. versionadded:: 0.21 + .. versionchanged:: 0.24 + """ + _check_option("orientation", orientation, ("coronal", "axial", "sagittal")) + axis = dict(coronal=1, axial=2, sagittal=0)[orientation] + x, y = sorted(set([0, 1, 2]).difference(set([axis]))) + return axis, x, y + + +def _get_mri_info_data(mri, data): + # Read the segmentation data using nibabel + if data: + _import_nibabel("load MRI atlas data") + out = dict() + _, out["vox_mri_t"], out["mri_ras_t"], dims, _, mgz = _read_mri_info( + mri, return_img=True + ) + out.update( + mri_width=dims[0], mri_height=dims[1], mri_depth=dims[1], mri_volume_name=mri + ) + if data: + assert mgz is not None + out["mri_vox_t"] = invert_transform(out["vox_mri_t"]) + out["data"] = np.asarray(mgz.dataobj) + return out + + +def _get_mgz_header(fname): + """Adapted from nibabel to quickly extract header info.""" + fname = _check_fname(fname, overwrite="read", must_exist=True, name="MRI image") + if fname.suffix != ".mgz": + raise OSError("Filename must end with .mgz") + header_dtd = [ + ("version", ">i4"), + ("dims", ">i4", (4,)), + ("type", ">i4"), + ("dof", ">i4"), + ("goodRASFlag", ">i2"), + ("delta", ">f4", (3,)), + ("Mdc", ">f4", (3, 3)), + ("Pxyz_c", ">f4", (3,)), + ] + header_dtype = np.dtype(header_dtd) + with GzipFile(fname, "rb") as fid: + hdr_str = fid.read(header_dtype.itemsize) + header = np.ndarray(shape=(), dtype=header_dtype, buffer=hdr_str) + # dims + dims = header["dims"].astype(int) + dims = dims[:3] if len(dims) == 4 else dims + # vox2ras_tkr + delta = header["delta"] + ds = np.array(delta, float) + ns = np.array(dims * ds) / 2.0 + v2rtkr = np.array( + [ + [-ds[0], 0, 0, ns[0]], + [0, 0, ds[2], -ns[2]], + [0, -ds[1], 0, ns[1]], + [0, 0, 0, 1], + ], + dtype=np.float32, + ) + # ras2vox + d = np.diag(delta) + pcrs_c = dims / 2.0 + Mdc = header["Mdc"].T + pxyz_0 = header["Pxyz_c"] - np.dot(Mdc, np.dot(d, pcrs_c)) + M = np.eye(4, 4) + M[0:3, 0:3] = np.dot(Mdc, d) + M[0:3, 3] = pxyz_0.T + header = dict(dims=dims, vox2ras_tkr=v2rtkr, vox2ras=M, zooms=header["delta"]) + return header + + +def _get_atlas_values(vol_info, rr): + # Transform MRI coordinates (where our surfaces live) to voxels + rr_vox = apply_trans(vol_info["mri_vox_t"], rr) + good = ( + (rr_vox >= -0.5) & (rr_vox < np.array(vol_info["data"].shape, int) - 0.5) + ).all(-1) + idx = np.round(rr_vox[good].T).astype(np.int64) + values = np.full(rr.shape[0], np.nan) + values[good] = vol_info["data"][tuple(idx)] + return values + + +def get_volume_labels_from_aseg(mgz_fname, return_colors=False, atlas_ids=None): + """Return a list of names and colors of segmented volumes. + + Parameters + ---------- + mgz_fname : path-like + Filename to read. Typically ``aseg.mgz`` or some variant in the + freesurfer pipeline. + return_colors : bool + If True returns also the labels colors. + atlas_ids : dict | None + A lookup table providing a mapping from region names (str) to ID values + (int). Can be None to use the standard Freesurfer LUT. + + .. versionadded:: 0.21.0 + + Returns + ------- + label_names : list of str + The names of segmented volumes included in this mgz file. + label_colors : list of str + The RGB colors of the labels included in this mgz file. + + See Also + -------- + read_freesurfer_lut + + Notes + ----- + .. versionchanged:: 0.21.0 + The label names are now sorted in the same order as their corresponding + values in the MRI file. + + .. versionadded:: 0.9.0 + """ + nib = _import_nibabel("load MRI atlas data") + mgz_fname = _check_fname( + mgz_fname, overwrite="read", must_exist=True, name="mgz_fname" + ) + atlas = nib.load(mgz_fname) + data = np.asarray(atlas.dataobj) # don't need float here + want = np.unique(data) + if atlas_ids is None: + atlas_ids, colors = read_freesurfer_lut() + elif return_colors: + raise ValueError("return_colors must be False if atlas_ids are provided") + # restrict to the ones in the MRI, sorted by label name + keep = np.isin(list(atlas_ids.values()), want) + keys = sorted( + (key for ki, key in enumerate(atlas_ids.keys()) if keep[ki]), + key=lambda x: atlas_ids[x], + ) + if return_colors: + colors = [colors[k] for k in keys] + out = keys, colors + else: + out = keys + return out + + +############################################################################## +# Head to MRI volume conversion + + +@verbose +def head_to_mri( + pos, + subject, + mri_head_t, + subjects_dir=None, + *, + kind="mri", + unscale=False, + verbose=None, +): + """Convert pos from head coordinate system to MRI ones. + + Parameters + ---------- + pos : array, shape (n_pos, 3) + The coordinates (in m) in head coordinate system. + %(subject)s + mri_head_t : instance of Transform + MRI<->Head coordinate transformation. + %(subjects_dir)s + kind : str + The MRI coordinate frame kind, can be ``'mri'`` (default) for + FreeSurfer surface RAS or ``'ras'`` (default in 1.2) to use MRI RAS + (scanner RAS). + + .. versionadded:: 1.2 + unscale : bool + For surrogate MRIs (e.g., scaled using ``mne coreg``), if True + (default False), use the MRI scaling parameters to obtain points in + the original/surrogate subject's MRI space. + + .. versionadded:: 1.2 + %(verbose)s + + Returns + ------- + coordinates : array, shape (n_pos, 3) + The MRI RAS coordinates (in mm) of pos. + + Notes + ----- + This function requires nibabel. + """ + from .coreg import read_mri_cfg + + _validate_type(kind, str, "kind") + _check_option("kind", kind, ("ras", "mri")) + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + t1_fname = subjects_dir / subject / "mri" / "T1.mgz" + head_mri_t = _ensure_trans(mri_head_t, "head", "mri") + if kind == "ras": + _, _, mri_ras_t, _, _ = _read_mri_info(t1_fname) + head_ras_t = combine_transforms(head_mri_t, mri_ras_t, "head", "ras") + head_dest_t = head_ras_t + else: + assert kind == "mri" + head_dest_t = head_mri_t + pos_dest = apply_trans(head_dest_t, pos) + # unscale if requested + if unscale: + params = read_mri_cfg(subject, subjects_dir) + pos_dest /= params["scale"] + pos_dest *= 1e3 # mm + return pos_dest + + +############################################################################## +# Surface to MNI conversion + + +@verbose +def vertex_to_mni(vertices, hemis, subject, subjects_dir=None, verbose=None): + """Convert the array of vertices for a hemisphere to MNI coordinates. + + Parameters + ---------- + vertices : int, or list of int + Vertex number(s) to convert. + hemis : int, or list of int + Hemisphere(s) the vertices belong to. + %(subject)s + subjects_dir : str, or None + Path to ``SUBJECTS_DIR`` if it is not set in the environment. + %(verbose)s + + Returns + ------- + coordinates : array, shape (n_vertices, 3) + The MNI coordinates (in mm) of the vertices. + """ + singleton = False + if not isinstance(vertices, list) and not isinstance(vertices, np.ndarray): + singleton = True + vertices = [vertices] + + if not isinstance(hemis, list) and not isinstance(hemis, np.ndarray): + hemis = [hemis] * len(vertices) + + if not len(hemis) == len(vertices): + raise ValueError("hemi and vertices must match in length") + + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + + surfs = [subjects_dir / subject / "surf" / f"{h}.white" for h in ["lh", "rh"]] + + # read surface locations in MRI space + rr = [read_surface(s)[0] for s in surfs] + + # take point locations in MRI space and convert to MNI coordinates + xfm = read_talxfm(subject, subjects_dir) + xfm["trans"][:3, 3] *= 1000.0 # m->mm + data = np.array([rr[h][v, :] for h, v in zip(hemis, vertices)]) + if singleton: + data = data[0] + return apply_trans(xfm["trans"], data) + + +############################################################################## +# Volume to MNI conversion + + +@verbose +def head_to_mni(pos, subject, mri_head_t, subjects_dir=None, verbose=None): + """Convert pos from head coordinate system to MNI ones. + + Parameters + ---------- + pos : array, shape (n_pos, 3) + The coordinates (in m) in head coordinate system. + %(subject)s + mri_head_t : instance of Transform + MRI<->Head coordinate transformation. + %(subjects_dir)s + %(verbose)s + + Returns + ------- + coordinates : array, shape (n_pos, 3) + The MNI coordinates (in mm) of pos. + + Notes + ----- + This function requires either nibabel. + """ + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + + # before we go from head to MRI (surface RAS) + head_mni_t = combine_transforms( + _ensure_trans(mri_head_t, "head", "mri"), + read_talxfm(subject, subjects_dir), + "head", + "mni_tal", + ) + return apply_trans(head_mni_t, pos) * 1000.0 + + +@verbose +def get_mni_fiducials(subject, subjects_dir=None, verbose=None): + """Estimate fiducials for a subject. + + Parameters + ---------- + %(subject)s + %(subjects_dir)s + %(verbose)s + + Returns + ------- + fids_mri : list + List of estimated fiducials (each point in a dict), in the order + LPA, nasion, RPA. + + Notes + ----- + This takes the ``fsaverage-fiducials.fif`` file included with MNE—which + contain the LPA, nasion, and RPA for the ``fsaverage`` subject—and + transforms them to the given FreeSurfer subject's MRI space. + The MRI of ``fsaverage`` is already in MNI Talairach space, so applying + the inverse of the given subject's MNI Talairach affine transformation + (``$SUBJECTS_DIR/$SUBJECT/mri/transforms/talairach.xfm``) is used + to estimate the subject's fiducial locations. + + For more details about the coordinate systems and transformations involved, + see https://surfer.nmr.mgh.harvard.edu/fswiki/CoordinateSystems and + :ref:`tut-source-alignment`. + """ + # Eventually we might want to allow using the MNI Talairach with-skull + # transformation rather than the standard brain-based MNI Talaranch + # transformation, and/or project the points onto the head surface + # (if available). + fname_fids_fs = ( + Path(__file__).parent / "data" / "fsaverage" / "fsaverage-fiducials.fif" + ) + + # Read fsaverage fiducials file and subject Talairach. + fids, coord_frame = read_fiducials(fname_fids_fs) + assert coord_frame == FIFF.FIFFV_COORD_MRI + if subject == "fsaverage": + return fids # special short-circuit for fsaverage + mni_mri_t = invert_transform(read_talxfm(subject, subjects_dir)) + for f in fids: + f["r"] = apply_trans(mni_mri_t, f["r"]) + return fids + + +@verbose +def estimate_head_mri_t(subject, subjects_dir=None, verbose=None): + """Estimate the head->mri transform from fsaverage fiducials. + + A subject's fiducials can be estimated given a Freesurfer ``recon-all`` + by transforming ``fsaverage`` fiducials using the inverse Talairach + transform, see :func:`mne.coreg.get_mni_fiducials`. + + Parameters + ---------- + %(subject)s + %(subjects_dir)s + %(verbose)s + + Returns + ------- + %(trans_not_none)s + """ + from .channels.montage import compute_native_head_t, make_dig_montage + + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + lpa, nasion, rpa = get_mni_fiducials(subject, subjects_dir) + montage = make_dig_montage( + lpa=lpa["r"], nasion=nasion["r"], rpa=rpa["r"], coord_frame="mri" + ) + return invert_transform(compute_native_head_t(montage)) + + +def _get_affine_from_lta_info(lines): + """Get the vox2ras affine from lta file info.""" + volume_data = np.loadtxt([line.split("=")[1] for line in lines]) + # get the size of the volume (number of voxels), slice resolution. + # the matrix of directional cosines and the ras at the center of the bore + dims, deltas, dir_cos, center_ras = ( + volume_data[0], + volume_data[1], + volume_data[2:5], + volume_data[5], + ) + dir_cos_delta = dir_cos.T * deltas + vol_center = (dir_cos_delta @ dims[:3]) / 2 + affine = np.eye(4) + affine[:3, :3] = dir_cos_delta + affine[:3, 3] = center_ras - vol_center + return affine + + +@verbose +def read_lta(fname, verbose=None): + """Read a Freesurfer linear transform array file. + + Parameters + ---------- + fname : path-like + The transform filename. + %(verbose)s + + Returns + ------- + affine : ndarray + The affine transformation described by the lta file. + """ + _check_fname(fname, "read", must_exist=True) + with open(fname) as fid: + lines = fid.readlines() + # 0 is linear vox2vox, 1 is linear ras2ras + trans_type = int(lines[0].split("=")[1].strip()[0]) + assert trans_type in (0, 1) + affine = np.loadtxt(lines[5:9]) + if trans_type == 1: + return affine + + src_affine = _get_affine_from_lta_info(lines[12:18]) + dst_affine = _get_affine_from_lta_info(lines[21:27]) + + # don't compute if src and dst are already identical + if np.allclose(src_affine, dst_affine): + return affine + + ras2ras = src_affine @ np.linalg.inv(affine) @ np.linalg.inv(dst_affine) + affine = np.linalg.inv(np.linalg.inv(src_affine) @ ras2ras @ src_affine) + return affine + + +@verbose +def read_talxfm(subject, subjects_dir=None, verbose=None): + """Compute MRI-to-MNI transform from FreeSurfer talairach.xfm file. + + Parameters + ---------- + %(subject)s + %(subjects_dir)s + %(verbose)s + + Returns + ------- + mri_mni_t : instance of Transform + The affine transformation from MRI to MNI space for the subject. + """ + # Adapted from freesurfer m-files. Altered to deal with Norig + # and Torig correctly + subjects_dir = get_subjects_dir(subjects_dir) + # Setup the RAS to MNI transform + ras_mni_t = read_ras_mni_t(subject, subjects_dir) + ras_mni_t["trans"][:3, 3] /= 1000.0 # mm->m + + # We want to get from Freesurfer surface RAS ('mri') to MNI ('mni_tal'). + # This file only gives us RAS (non-zero origin) ('ras') to MNI ('mni_tal'). + # Se we need to get the ras->mri transform from the MRI headers. + + # To do this, we get Norig and Torig + # (i.e. vox_ras_t and vox_mri_t, respectively) + path = subjects_dir / subject / "mri" / "orig.mgz" + if not path.is_file(): + path = subjects_dir / subject / "mri" / "T1.mgz" + if not path.is_file(): + raise OSError(f"mri not found: {path}") + _, _, mri_ras_t, _, _ = _read_mri_info(path) + mri_mni_t = combine_transforms(mri_ras_t, ras_mni_t, "mri", "mni_tal") + return mri_mni_t + + +def _check_mri(mri, subject, subjects_dir) -> str: + """Check whether an mri exists in the Freesurfer subject directory.""" + _validate_type(mri, "path-like", mri) + mri = Path(mri) + if mri.is_file() and mri.name != mri: + return str(mri) + elif not mri.is_file(): + if subject is None: + raise FileNotFoundError( + f"MRI file {mri!r} not found and no subject provided." + ) + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + mri = subjects_dir / subject / "mri" / mri + if not mri.is_file(): + raise FileNotFoundError( + f"MRI file {mri!r} not found in the subjects directory " + f"{subjects_dir!r} for subject {subject}." + ) + if mri.name == mri: + raise OSError( + f"Ambiguous filename - found {mri!r} in current folder. " + "If this is correct prefix name with relative or absolute path." + ) + return str(mri) + + +def _read_mri_info(path, units="m", return_img=False, use_nibabel=False): + # This is equivalent but 100x slower, so only use nibabel if we need to + # (later): + if use_nibabel: + nib = _import_nibabel() + hdr = nib.load(path).header + n_orig = hdr.get_vox2ras() + t_orig = hdr.get_vox2ras_tkr() + dims = hdr.get_data_shape() + zooms = hdr.get_zooms()[:3] + else: + hdr = _get_mgz_header(path) + n_orig = hdr["vox2ras"] + t_orig = hdr["vox2ras_tkr"] + dims = hdr["dims"] + zooms = hdr["zooms"] + + # extract the MRI_VOXEL to RAS (non-zero origin) transform + vox_ras_t = Transform("mri_voxel", "ras", n_orig) + + # extract the MRI_VOXEL to MRI transform + vox_mri_t = Transform("mri_voxel", "mri", t_orig) + + # construct the MRI to RAS (non-zero origin) transform + mri_ras_t = combine_transforms(invert_transform(vox_mri_t), vox_ras_t, "mri", "ras") + + assert units in ("m", "mm") + if units == "m": + conv = np.array([[1e-3, 1e-3, 1e-3, 1]]).T + # scaling and translation terms + vox_ras_t["trans"] *= conv + vox_mri_t["trans"] *= conv + # just the translation term + mri_ras_t["trans"][:, 3:4] *= conv + + out = (vox_ras_t, vox_mri_t, mri_ras_t, dims, zooms) + if return_img: + nibabel = _import_nibabel() + out += (nibabel.load(path),) + return out + + +def read_freesurfer_lut(fname=None): + """Read a Freesurfer-formatted LUT. + + Parameters + ---------- + fname : path-like | None + The filename. Can be None to read the standard Freesurfer LUT. + + Returns + ------- + atlas_ids : dict + Mapping from label names to IDs. + colors : dict + Mapping from label names to colors. + """ + lut = _get_lut(fname) + names, ids = lut["name"], lut["id"] + colors = np.array([lut["R"], lut["G"], lut["B"], lut["A"]], float).T + atlas_ids = dict(zip(names, ids)) + colors = dict(zip(names, colors)) + return atlas_ids, colors + + +def _get_lut(fname=None): + """Get a FreeSurfer LUT.""" + if fname is None: + fname = Path(__file__).parent / "data" / "FreeSurferColorLUT.txt" + _check_fname(fname, "read", must_exist=True) + dtype = [ + ("id", " 0 + lut["name"] = [str(name) for name in lut["name"]] + return lut + + +@verbose +def _get_head_surface(surf, subject, subjects_dir, bem=None, verbose=None): + """Get a head surface from the Freesurfer subject directory. + + Parameters + ---------- + surf : str + The name of the surface 'auto', 'head', 'outer_skin', 'head-dense' + or 'seghead'. + %(subject)s + %(subjects_dir)s + bem : mne.bem.ConductorModel | None + The conductor model that stores information about the head surface. + %(verbose)s + + Returns + ------- + head_surf : dict | None + A dictionary with keys 'rr', 'tris', 'ntri', 'use_tris', 'np' + and 'coord_frame' that store information for mesh plotting and other + useful information about the head surface. + + Notes + ----- + .. versionadded: 0.24 + """ + from .bem import _bem_find_surface, read_bem_surfaces + + _check_option("surf", surf, ("auto", "head", "outer_skin", "head-dense", "seghead")) + if surf in ("auto", "head", "outer_skin"): + if bem is not None: + try: + return _bem_find_surface(bem, "head") + except RuntimeError: + logger.info( + "Could not find the surface for " + "head in the provided BEM model, " + "looking in the subject directory." + ) + if subject is None: + if surf == "auto": + return + raise ValueError( + "To plot the head surface, the BEM/sphere" + " model must contain a head surface " + 'or "subject" must be provided (got ' + "None)" + ) + subject_dir = op.join(get_subjects_dir(subjects_dir, raise_error=True), subject) + if surf in ("head-dense", "seghead"): + try_fnames = [ + op.join(subject_dir, "bem", f"{subject}-head-dense.fif"), + op.join(subject_dir, "surf", "lh.seghead"), + ] + else: + try_fnames = [ + op.join(subject_dir, "bem", "outer_skin.surf"), + op.join(subject_dir, "bem", "flash", "outer_skin.surf"), + op.join(subject_dir, "bem", f"{subject}-head-sparse.fif"), + op.join(subject_dir, "bem", f"{subject}-head.fif"), + ] + for fname in try_fnames: + if op.exists(fname): + logger.info(f"Using {op.basename(fname)} for head surface.") + if op.splitext(fname)[-1] == ".fif": + return read_bem_surfaces(fname, on_defects="warn")[0] + else: + return _read_mri_surface(fname) + raise OSError( + "No head surface found for subject " + f"{subject} after trying:\n" + "\n".join(try_fnames) + ) + + +@verbose +def _get_skull_surface(surf, subject, subjects_dir, bem=None, verbose=None): + """Get a skull surface from the Freesurfer subject directory. + + Parameters + ---------- + surf : str + The name of the surface 'outer' or 'inner'. + %(subject)s + %(subjects_dir)s + bem : mne.bem.ConductorModel | None + The conductor model that stores information about the skull surface. + %(verbose)s + + Returns + ------- + skull_surf : dict | None + A dictionary with keys 'rr', 'tris', 'ntri', 'use_tris', 'np' + and 'coord_frame' that store information for mesh plotting and other + useful information about the head surface. + + Notes + ----- + .. versionadded: 0.24 + """ + from .bem import _bem_find_surface + + if bem is not None: + try: + return _bem_find_surface(bem, surf + "_skull") + except RuntimeError: + logger.info( + "Could not find the surface for " + "skull in the provided BEM model, " + "looking in the subject directory." + ) + subjects_dir = Path(get_subjects_dir(subjects_dir, raise_error=True)) + fname = _check_fname( + subjects_dir / subject / "bem" / (surf + "_skull.surf"), + overwrite="read", + must_exist=True, + name=f"{surf} skull surface", + ) + return _read_mri_surface(fname) + + +def _estimate_talxfm_rigid(subject, subjects_dir): + from .coreg import _trans_from_params, fit_matched_points + + xfm = read_talxfm(subject, subjects_dir) + # XYZ+origin + halfway + pts_tal = np.concatenate([np.eye(4)[:, :3], np.eye(3) * 0.5]) + pts_subj = apply_trans(invert_transform(xfm), pts_tal) + # we fit with scaling enabled, but then discard it (we just need + # the rigid-body components) + params = fit_matched_points(pts_subj, pts_tal, scale=3, out="params") + rigid = _trans_from_params((True, True, False), params[:6]) + return rigid diff --git a/mne-python/source/mne/_ola.py b/mne-python/source/mne/_ola.py new file mode 100644 index 0000000000000000000000000000000000000000..939aff396463572e1fb8425efc48a6c2663c592d --- /dev/null +++ b/mne-python/source/mne/_ola.py @@ -0,0 +1,478 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +from scipy.signal import get_window + +from .utils import _ensure_int, _validate_type, logger, verbose + +############################################################################### +# Class for interpolation between adjacent points + + +class _Interp2: + r"""Interpolate between two points. + + Parameters + ---------- + control_points : array, shape (n_changes,) + The control points (indices) to use. + values : callable | array, shape (n_changes, ...) + Callable that takes the control point and returns a list of + arrays that must be interpolated. + interp : str + Can be 'zero', 'linear', 'hann', or 'cos2' (same as hann). + + Notes + ----- + This will process data using overlapping windows of potentially + different sizes to achieve a constant output value using different + 2-point interpolation schemes. For example, for linear interpolation, + and window sizes of 6 and 17, this would look like:: + + 1 _ _ + |\ / '-. .-' + | \ / '-. .-' + | x |-.-| + | / \ .-' '-. + |/ \_.-' '-. + 0 +----|----|----|----|--- + 0 5 10 15 20 25 + + """ + + def __init__(self, control_points, values, interp="hann", *, name="Interp2"): + # set up interpolation + self.control_points = np.array(control_points, int).ravel() + if not np.array_equal(np.unique(self.control_points), self.control_points): + raise ValueError("Control points must be sorted and unique") + if len(self.control_points) == 0: + raise ValueError("Must be at least one control point") + if not (self.control_points >= 0).all(): + raise ValueError( + f"All control points must be positive (got {self.control_points[:3]})" + ) + if isinstance(values, np.ndarray): + values = [values] + if isinstance(values, list | tuple): + for v in values: + if not (v is None or isinstance(v, np.ndarray)): + raise TypeError( + 'All entries in "values" must be ndarray or None, got ' + f"{type(v)}" + ) + if v is not None and v.shape[0] != len(self.control_points): + raise ValueError( + "Values, if provided, must be the same length as the number of " + f"control points ({len(self.control_points)}), got {v.shape[0]}" + ) + use_values = values + + def val(pt): + idx = np.where(control_points == pt)[0][0] + return [v[idx] if v is not None else None for v in use_values] + + values = val + self.values = values + self.n_last = None + self._position = 0 # start at zero + self._left_idx = 0 + self._left = self._right = self._use_interp = None + self.name = name + known_types = ("cos2", "linear", "zero", "hann") + if interp not in known_types: + raise ValueError(f'interp must be one of {known_types}, got "{interp}"') + self._interp = interp + + def feed_generator(self, n_pts): + """Feed data and get interpolators as a generator.""" + self.n_last = 0 + n_pts = _ensure_int(n_pts, "n_pts") + original_position = self._position + stop = self._position + n_pts + logger.debug(f" ~ {self.name} Feed {n_pts} ({self._position}-{stop})") + used = np.zeros(n_pts, bool) + if self._left is None: # first one + logger.debug(f" ~ {self.name} Eval @ 0 ({self.control_points[0]})") + self._left = self.values(self.control_points[0]) + if len(self.control_points) == 1: + self._right = self._left + n_used = 0 + + # Left zero-order hold condition + if self._position < self.control_points[self._left_idx]: + n_use = min(self.control_points[self._left_idx] - self._position, n_pts) + logger.debug(f" ~ {self.name} Left ZOH {n_use}") + this_sl = slice(None, n_use) + assert used[this_sl].size == n_use + assert not used[this_sl].any() + used[this_sl] = True + yield [this_sl, self._left, None, None] + self._position += n_use + n_used += n_use + self.n_last += 1 + + # Standard interpolation condition + stop_right_idx = np.where(self.control_points >= stop)[0] + if len(stop_right_idx) == 0: + stop_right_idx = [len(self.control_points) - 1] + stop_right_idx = stop_right_idx[0] + left_idxs = np.arange(self._left_idx, stop_right_idx) + self.n_last += max(len(left_idxs) - 1, 0) + for bi, left_idx in enumerate(left_idxs): + if left_idx != self._left_idx or self._right is None: + if self._right is not None: + assert left_idx == self._left_idx + 1 + self._left = self._right + self._left_idx += 1 + self._use_interp = None # need to recreate it + eval_pt = self.control_points[self._left_idx + 1] + logger.debug( + f" ~ {self.name} Eval @ {self._left_idx + 1} ({eval_pt})" + ) + self._right = self.values(eval_pt) + assert self._right is not None + left_point = self.control_points[self._left_idx] + right_point = self.control_points[self._left_idx + 1] + if self._use_interp is None: + interp_span = right_point - left_point + if self._interp == "zero": + self._use_interp = None + elif self._interp == "linear": + self._use_interp = np.linspace( + 1.0, 0.0, interp_span, endpoint=False + ) + else: # self._interp in ('cos2', 'hann'): + self._use_interp = np.cos( + np.linspace(0, np.pi / 2.0, interp_span, endpoint=False) + ) + self._use_interp *= self._use_interp + n_use = min(stop, right_point) - self._position + if n_use > 0: + logger.debug( + f" ~ {self.name} Interp {self._interp} {n_use} " + f"({left_point}-{right_point})" + ) + interp_start = self._position - left_point + assert interp_start >= 0 + if self._use_interp is None: + this_interp = None + else: + this_interp = self._use_interp[interp_start : interp_start + n_use] + assert this_interp.size == n_use + this_sl = slice(n_used, n_used + n_use) + assert used[this_sl].size == n_use + assert not used[this_sl].any() + used[this_sl] = True + yield [this_sl, self._left, self._right, this_interp] + self._position += n_use + n_used += n_use + + # Right zero-order hold condition + if self.control_points[self._left_idx] <= self._position: + n_use = stop - self._position + if n_use > 0: + logger.debug(f" ~ {self.name} Right ZOH %s" % n_use) + this_sl = slice(n_pts - n_use, None) + assert not used[this_sl].any() + used[this_sl] = True + assert self._right is not None + yield [this_sl, self._right, None, None] + self._position += n_use + n_used += n_use + self.n_last += 1 + assert self._position == stop + assert n_used == n_pts + assert used.all() + assert self._position == original_position + n_pts + + def feed(self, n_pts): + """Feed data and get interpolated values.""" + # Convenience function for assembly + out_arrays = None + for o in self.feed_generator(n_pts): + if out_arrays is None: + out_arrays = [ + np.empty(v.shape + (n_pts,)) if v is not None else None + for v in o[1] + ] + for ai, arr in enumerate(out_arrays): + if arr is not None: + if o[3] is None: + arr[..., o[0]] = o[1][ai][..., np.newaxis] + else: + arr[..., o[0]] = o[1][ai][..., np.newaxis] * o[3] + o[2][ai][ + ..., np.newaxis + ] * (1.0 - o[3]) + assert out_arrays is not None + return out_arrays + + +############################################################################### +# Constant overlap-add processing class + + +def _check_store(store): + _validate_type(store, (np.ndarray, list, tuple, _Storer), "store") + if isinstance(store, np.ndarray): + store = [store] + if not isinstance(store, _Storer): + if not all(isinstance(s, np.ndarray) for s in store): + raise TypeError("All instances must be ndarrays") + store = _Storer(*store) + return store + + +class _COLA: + r"""Constant overlap-add processing helper. + + Parameters + ---------- + process : callable + A function that takes a chunk of input data with shape + ``(n_channels, n_samples)`` and processes it. + store : ndarray | list of ndarray | _Storer + The output data in which to store the results. + n_total : int + The total number of samples. + n_samples : int + The number of samples per window. + n_overlap : int + The overlap between windows. + window : str + The window to use. Default is "hann". + tol : float + The tolerance for COLA checking. + + Notes + ----- + This will process data using overlapping windows to achieve a constant + output value. For example, for ``n_total=27``, ``n_samples=10``, + ``n_overlap=5`` and ``window='triang'``:: + + 1 _____ _______ + | \ /\ /\ / + | \ / \ / \ / + | x x x + | / \ / \ / \ + | / \/ \/ \ + 0 +----|----|----|----|----|- + 0 5 10 15 20 25 + + This produces four windows: the first three are the requested length + (10 samples) and the last one is longer (12 samples). The first and last + window are asymmetric. + """ + + @verbose + def __init__( + self, + process, + store, + n_total, + n_samples, + n_overlap, + sfreq, + window="hann", + tol=1e-10, + *, + name="COLA", + verbose=None, + ): + n_samples = _ensure_int(n_samples, "n_samples") + n_overlap = _ensure_int(n_overlap, "n_overlap") + n_total = _ensure_int(n_total, "n_total") + if n_samples <= 0: + raise ValueError(f"n_samples must be > 0, got {n_samples}") + if n_overlap < 0: + raise ValueError(f"n_overlap must be >= 0, got {n_overlap}") + if n_total < 0: + raise ValueError(f"n_total must be >= 0, got {n_total}") + self._n_samples = int(n_samples) + self._n_overlap = int(n_overlap) + del n_samples, n_overlap + if n_total < self._n_samples: + raise ValueError( + f"Number of samples per window ({self._n_samples}) must be at " + f"most the total number of samples ({n_total})" + ) + if not callable(process): + raise TypeError(f"process must be callable, got type {type(process)}") + self._process = process + self._step = self._n_samples - self._n_overlap + self._store = _check_store(store) + self._idx = 0 + self._in_buffers = self._out_buffers = None + self.name = name + + # Create our window boundaries + window_name = window if isinstance(window, str) else "custom" + self._window = get_window( + window, self._n_samples, fftbins=bool((self._n_samples - 1) % 2) + ) + self._window /= _check_cola( + self._window, self._n_samples, self._step, window_name, tol=tol + ) + self.starts = np.arange(0, n_total - self._n_samples + 1, self._step) + self.stops = self.starts + self._n_samples + delta = n_total - self.stops[-1] + self.stops[-1] = n_total + sfreq = float(sfreq) + pl = "s" if len(self.starts) != 1 else "" + logger.info( + f" Processing {len(self.starts):4d} data chunk{pl} of (at least) " + f"{self._n_samples / sfreq:0.1f} s with " + f"{self._n_overlap / sfreq:0.1f} s overlap and {window_name} windowing" + ) + del window, window_name + if delta > 0: + logger.info( + f" The final {delta / sfreq} s will be lumped into the final window" + ) + + @property + def _in_offset(self): + """Compute from current processing window start and buffer len.""" + return self.starts[self._idx] + self._in_buffers[0].shape[-1] + + @verbose + def feed(self, *datas, verbose=None, **kwargs): + """Pass in a chunk of data.""" + # Append to our input buffer + if self._in_buffers is None: + self._in_buffers = [None] * len(datas) + if len(datas) != len(self._in_buffers): + raise ValueError( + f"Got {len(datas)} array(s), needed {len(self._in_buffers)}" + ) + current_offset = 0 # should be updated below + for di, data in enumerate(datas): + if not isinstance(data, np.ndarray) or data.ndim < 1: + raise TypeError( + f"data entry {di} must be an 2D ndarray, got {type(data)}" + ) + if self._in_buffers[di] is None: + # In practice, users can give large chunks, so we use + # dynamic allocation of the in buffer. We could save some + # memory allocation by only ever processing max_len at once, + # but this would increase code complexity. + self._in_buffers[di] = np.empty(data.shape[:-1] + (0,), data.dtype) + if ( + data.shape[:-1] != self._in_buffers[di].shape[:-1] + or self._in_buffers[di].dtype != data.dtype + ): + raise TypeError( + f"data must dtype {self._in_buffers[di].dtype} and " + f"shape[:-1]=={self._in_buffers[di].shape[:-1]}, got dtype " + f"{data.dtype} shape[:-1]={data.shape[:-1]}" + ) + # This gets updated on first iteration, so store it before it updates + if di == 0: + current_offset = self._in_offset + logger.debug( + f" + {self.name}[{di}] Appending " + f"{current_offset}:{current_offset + data.shape[-1]}" + ) + self._in_buffers[di] = np.concatenate([self._in_buffers[di], data], -1) + if self._in_offset > self.stops[-1]: + raise ValueError( + f"data (shape {data.shape}) exceeded expected total buffer size (" + f"{self._in_offset} > {self.stops[-1]})" + ) + # Check to see if we can process the next chunk and dump outputs + while self._idx < len(self.starts) and self._in_offset >= self.stops[self._idx]: + start, stop = self.starts[self._idx], self.stops[self._idx] + this_len = stop - start + this_window = self._window.copy() + if self._idx == len(self.starts) - 1: + this_window = np.pad( + self._window, (0, this_len - len(this_window)), "constant" + ) + for offset in range(self._step, len(this_window), self._step): + n_use = len(this_window) - offset + this_window[offset:] += self._window[:n_use] + if self._idx == 0: + for offset in range(self._n_samples - self._step, 0, -self._step): + this_window[:offset] += self._window[-offset:] + this_proc = [in_[..., :this_len].copy() for in_ in self._in_buffers] + logger.debug( + f" * {self.name}[:] Processing {start}:{stop} " + f"(e.g., {this_proc[0].flat[[0, -1]]})" + ) + if not all( + proc.shape[-1] == this_len == this_window.size for proc in this_proc + ): + raise RuntimeError("internal indexing error") + start = self._store.idx + stop = self._store.idx + this_len + outs = self._process(*this_proc, start=start, stop=stop, **kwargs) + if self._out_buffers is None: + max_len = np.max(self.stops - self.starts) + self._out_buffers = [ + np.zeros(o.shape[:-1] + (max_len,), o.dtype) for o in outs + ] + for oi, out in enumerate(outs): + out *= this_window + self._out_buffers[oi][..., : stop - start] += out + self._idx += 1 + if self._idx < len(self.starts): + next_start = self.starts[self._idx] + else: + next_start = self.stops[-1] + delta = next_start - self.starts[self._idx - 1] + logger.debug( + f" + {self.name}[:] Shifting input and output buffers by " + f"{delta} samples (storing {start}:{stop})" + ) + for di in range(len(self._in_buffers)): + self._in_buffers[di] = self._in_buffers[di][..., delta:] + self._store(*[o[..., :delta] for o in self._out_buffers]) + for ob in self._out_buffers: + ob[..., :-delta] = ob[..., delta:] + ob[..., -delta:] = 0.0 + + +def _check_cola(win, nperseg, step, window_name, tol=1e-10): + """Check whether the Constant OverLap Add (COLA) constraint is met.""" + # adapted from SciPy + binsums = np.sum( + [win[ii * step : (ii + 1) * step] for ii in range(nperseg // step)], axis=0 + ) + if nperseg % step != 0: + binsums[: nperseg % step] += win[-(nperseg % step) :] + const = np.median(binsums) + deviation = np.max(np.abs(binsums - const)) + if deviation > tol: + raise ValueError( + f"segment length {nperseg} with step {step} for {window_name} " + "window type does not provide a constant output " + f"({100 * deviation / const:g}% deviation)" + ) + return const + + +class _Storer: + """Store data in chunks.""" + + def __init__(self, *outs, picks=None): + for oi, out in enumerate(outs): + if not isinstance(out, np.ndarray) or out.ndim < 1: + raise TypeError(f"outs[oi] must be >= 1D ndarray, got {out}") + self.outs = outs + self.idx = 0 + self.picks = picks + + def __call__(self, *outs): + if len(outs) != len(self.outs) or not all( + out.shape[-1] == outs[0].shape[-1] for out in outs + ): + raise ValueError("Bad outs") + idx = (Ellipsis,) + if self.picks is not None: + idx += (self.picks,) + stop = self.idx + outs[0].shape[-1] + idx += (slice(self.idx, stop),) + for o1, o2 in zip(self.outs, outs): + o1[idx] = o2 + self.idx = stop diff --git a/mne-python/source/mne/annotations.py b/mne-python/source/mne/annotations.py new file mode 100644 index 0000000000000000000000000000000000000000..13d2edd356b19d6c1e005b3c832d01db539de20c --- /dev/null +++ b/mne-python/source/mne/annotations.py @@ -0,0 +1,2455 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import json +import re +import warnings +from collections import Counter, OrderedDict, UserDict, UserList +from collections.abc import Iterable +from copy import deepcopy +from datetime import datetime, timedelta, timezone +from itertools import takewhile +from textwrap import shorten + +import numpy as np +from scipy.io import loadmat + +from ._fiff.constants import FIFF +from ._fiff.open import fiff_open +from ._fiff.tag import read_tag +from ._fiff.tree import dir_tree_find +from ._fiff.write import ( + _safe_name_list, + end_block, + start_and_end_file, + start_block, + write_double, + write_float, + write_name_list_sanitized, + write_string, +) +from .fixes import _compare_version +from .utils import ( + _check_dict_keys, + _check_dt, + _check_fname, + _check_option, + _check_pandas_installed, + _check_time_format, + _convert_times, + _DefaultEventParser, + _dt_to_stamp, + _is_numeric, + _mask_to_onsets_offsets, + _on_missing, + _pl, + _stamp_to_dt, + _validate_type, + check_fname, + fill_doc, + int_like, + logger, + verbose, + warn, +) +from .utils.check import _soft_import + +# For testing windows_like_datetime, we monkeypatch "datetime" in this module. +# Keep the true datetime object around for _validate_type use. +_datetime = datetime + + +class _AnnotationsExtrasDict(UserDict): + """A dictionary for storing extra fields of annotations. + + The keys of the dictionary are strings, and the values can be + strings, integers, floats, or None. + """ + + def __setitem__(self, key: str, value: str | int | float | None) -> None: + _validate_type(key, str, "key") + if key in ("onset", "duration", "description", "ch_names", "hed_string"): + raise ValueError(f"Key '{key}' is reserved and cannot be used in extras.") + _validate_type( + value, + (str, int, float, None), + "value", + ) + super().__setitem__(key, value) + + +class _AnnotationsExtrasList(UserList): + """A list of dictionaries for storing extra fields of annotations. + + Each dictionary in the list corresponds to an annotation and contains + extra fields. + The keys of the dictionaries are strings, and the values can be + strings, integers, floats, or None. + """ + + def __repr__(self): + return repr(self.data) + + @staticmethod + def _validate_value( + value: dict | _AnnotationsExtrasDict | None, + ) -> _AnnotationsExtrasDict: + _validate_type( + value, + (dict, _AnnotationsExtrasDict, None), + "extras dict value", + "dict or None", + ) + return ( + value + if isinstance(value, _AnnotationsExtrasDict) + else _AnnotationsExtrasDict(value or {}) + ) + + def __init__(self, initlist=None): + if not (isinstance(initlist, _AnnotationsExtrasList) or initlist is None): + initlist = [self._validate_value(v) for v in initlist] + super().__init__(initlist) + + def __setitem__( # type: ignore[override] + self, + key: int | slice, + value, + ) -> None: + _validate_type(key, (int, slice), "key", "int or slice") + if isinstance(key, int): + iterable = False + value = [value] + else: + _validate_type(value, Iterable, "value", "Iterable when key is a slice") + iterable = True + + new_values = [self._validate_value(v) for v in value] + if not iterable: + new_values = new_values[0] + super().__setitem__(key, new_values) + + def __iadd__(self, other): + if not isinstance(other, _AnnotationsExtrasList): + other = _AnnotationsExtrasList(other) + super().__iadd__(other) + + def append(self, item): + super().append(self._validate_value(item)) + + def insert(self, i, item): + super().insert(i, self._validate_value(item)) + + def extend(self, other): + if not isinstance(other, _AnnotationsExtrasList): + other = _AnnotationsExtrasList(other) + super().extend(other) + + +def _validate_extras(extras, length: int): + _validate_type(extras, (None, list, _AnnotationsExtrasList), "extras") + if extras is not None and len(extras) != length: + raise ValueError( + f"extras must be None or a list of length {length}, got {len(extras)}." + ) + if isinstance(extras, _AnnotationsExtrasList): + return extras + return _AnnotationsExtrasList(extras or [None] * length) + + +def _check_o_d_s_c_e(onset, duration, description, ch_names, extras): + onset = np.atleast_1d(np.array(onset, dtype=float)) + if onset.ndim != 1: + raise ValueError( + f"Onset must be a one dimensional array, got {onset.ndim} (shape " + f"{onset.shape})." + ) + duration = np.array(duration, dtype=float) + if duration.ndim == 0 or duration.shape == (1,): + duration = np.repeat(duration, len(onset)) + if duration.ndim != 1: + raise ValueError( + f"Duration must be a one dimensional array, got {duration.ndim}." + ) + + description = np.array(description, dtype=str) + if description.ndim == 0 or description.shape == (1,): + description = np.repeat(description, len(onset)) + if description.ndim != 1: + raise ValueError( + f"Description must be a one dimensional array, got {description.ndim}." + ) + _safe_name_list(description, "write", "description") + + # ch_names: convert to ndarray of tuples + _validate_type(ch_names, (None, tuple, list, np.ndarray), "ch_names") + if ch_names is None: + ch_names = [()] * len(onset) + ch_names = list(ch_names) + for ai, ch in enumerate(ch_names): + _validate_type(ch, (list, tuple, np.ndarray), f"ch_names[{ai}]") + ch_names[ai] = tuple(ch) + for ci, name in enumerate(ch_names[ai]): + _validate_type(name, str, f"ch_names[{ai}][{ci}]") + ch_names = _ndarray_ch_names(ch_names) + + if not (len(onset) == len(duration) == len(description) == len(ch_names)): + raise ValueError( + "Onset, duration, description, and ch_names must be " + f"equal in sizes, got {len(onset)}, {len(duration)}, " + f"{len(description)}, and {len(ch_names)}." + ) + + extras = _validate_extras(extras, len(onset)) + return onset, duration, description, ch_names, extras + + +def _ndarray_ch_names(ch_names): + # np.array(..., dtype=object) if all entries are empty will give + # an empty array of shape (n_entries, 0) which is not helpful. So let's + # force it to give us an array of shape (n_entries,) full of empty + # tuples + out = np.empty(len(ch_names), dtype=object) + out[:] = ch_names + return out + + +@fill_doc +class Annotations: + """Annotation object for annotating segments of raw data. + + .. note:: + To convert events to `~mne.Annotations`, use + `~mne.annotations_from_events`. To convert existing `~mne.Annotations` + to events, use `~mne.events_from_annotations`. + + Parameters + ---------- + onset : array of float, shape (n_annotations,) + The starting time of annotations in seconds after ``orig_time``. + duration : array of float, shape (n_annotations,) | float + Durations of the annotations in seconds. If a float, all the + annotations are given the same duration. + description : array of str, shape (n_annotations,) | str + Array of strings containing description for each annotation. If a + string, all the annotations are given the same description. To reject + epochs, use description starting with keyword 'bad'. See example above. + orig_time : float | str | datetime | tuple of int | None + A POSIX Timestamp, datetime or a tuple containing the timestamp as the + first element and microseconds as the second element. Determines the + starting time of annotation acquisition. If None (default), + starting time is determined from beginning of raw data acquisition. + In general, ``raw.info['meas_date']`` (or None) can be used for syncing + the annotations with raw data if their acquisition is started at the + same time. If it is a string, it should conform to the ISO8601 format. + More precisely to this '%%Y-%%m-%%d %%H:%%M:%%S.%%f' particular case of + the ISO8601 format where the delimiter between date and time is ' ' and at most + microsecond precision (nanoseconds are not supported). + %(ch_names_annot)s + + .. versionadded:: 0.23 + extras : list[dict[str, int | float | str | None] | None] | None + Optional list of dicts containing extra fields for each annotation. + The number of items must match the number of annotations. + + .. versionadded:: 1.10 + + See Also + -------- + mne.annotations_from_events + mne.events_from_annotations + mne.HEDAnnotations + + Notes + ----- + Annotations are added to instance of :class:`mne.io.Raw` as the attribute + :attr:`raw.annotations `. + + To reject bad epochs using annotations, use + annotation description starting with 'bad' keyword. The epochs with + overlapping bad segments are then rejected automatically by default. + + To remove epochs with blinks you can do: + + >>> eog_events = mne.preprocessing.find_eog_events(raw) # doctest: +SKIP + >>> n_blinks = len(eog_events) # doctest: +SKIP + >>> onset = eog_events[:, 0] / raw.info['sfreq'] - 0.25 # doctest: +SKIP + >>> duration = np.repeat(0.5, n_blinks) # doctest: +SKIP + >>> description = ['bad blink'] * n_blinks # doctest: +SKIP + >>> annotations = mne.Annotations(onset, duration, description) # doctest: +SKIP + >>> raw.set_annotations(annotations) # doctest: +SKIP + >>> epochs = mne.Epochs(raw, events, event_id, tmin, tmax) # doctest: +SKIP + + **ch_names** + + Specifying channel names allows the creation of channel-specific + annotations. Once the annotations are assigned to a raw instance with + :meth:`mne.io.Raw.set_annotations`, if channels are renamed by the raw + instance, the annotation channels also get renamed. If channels are dropped + from the raw instance, any channel-specific annotation that has no channels + left in the raw instance will also be removed. + + **orig_time** + + If ``orig_time`` is None, the annotations are synced to the start of the + data (0 seconds). Otherwise the annotations are synced to sample 0 and + ``raw.first_samp`` is taken into account the same way as with events. + + When setting annotations, the following alignments + between ``raw.info['meas_date']`` and ``annotation.orig_time`` take place: + + :: + + ----------- meas_date=XX, orig_time=YY ----------------------------- + + | +------------------+ + |______________| RAW | + | | | + | +------------------+ + meas_date first_samp + . + . | +------+ + . |_________| ANOT | + . | | | + . | +------+ + . orig_time onset[0] + . + | +------+ + |___________________| | + | | | + | +------+ + orig_time onset[0]' + + ----------- meas_date=XX, orig_time=None --------------------------- + + | +------------------+ + |______________| RAW | + | | | + | +------------------+ + . N +------+ + . o_________| ANOT | + . n | | + . e +------+ + . + | +------+ + |________________________| | + | | | + | +------+ + orig_time onset[0]' + + ----------- meas_date=None, orig_time=YY --------------------------- + + N +------------------+ + o______________| RAW | + n | | + e +------------------+ + | +------+ + |_________| ANOT | + | | | + | +------+ + + [[[ CRASH ]]] + + ----------- meas_date=None, orig_time=None ------------------------- + + N +------------------+ + o______________| RAW | + n | | + e +------------------+ + . N +------+ + . o_________| ANOT | + . n | | + . e +------+ + . + N +------+ + o________________________| | + n | | + e +------+ + orig_time onset[0]' + + .. warning:: + This means that when ``raw.info['meas_date'] is None``, doing + ``raw.set_annotations(raw.annotations)`` will not alter ``raw`` if and + only if ``raw.first_samp == 0``. When it's non-zero, + ``raw.set_annotations`` will assume that the "new" annotations refer to + the original data (with ``first_samp==0``), and will be re-referenced to + the new time offset! + + **Specific annotation** + + ``BAD_ACQ_SKIP`` annotation leads to specific reading/writing file + behaviours. See :meth:`mne.io.read_raw_fif` and + :meth:`Raw.save() ` notes for details. + """ # noqa: E501 + + def __init__( + self, + onset, + duration, + description, + orig_time=None, + ch_names=None, + *, + extras=None, + ): + self._orig_time = _handle_meas_date(orig_time) + if isinstance(orig_time, str) and self._orig_time is None: + try: # only warn if `orig_time` is not the default '1970-01-01 00:00:00' + if _handle_meas_date(0) == datetime.strptime( + orig_time, "%Y-%m-%d %H:%M:%S" + ).replace(tzinfo=timezone.utc): + pass + except ValueError: # error if incorrect datetime format AND not the default + warn( + "The format of the `orig_time` string is not recognised. It " + "must conform to the ISO8601 format with at most microsecond " + "precision and where the delimiter between date and time is " + f"' '. Got: {orig_time}. Defaulting `orig_time` to None.", + RuntimeWarning, + ) + self.onset, self.duration, self.description, self.ch_names, self._extras = ( + _check_o_d_s_c_e(onset, duration, description, ch_names, extras) + ) + self._sort() # ensure we're sorted + + @property + def orig_time(self): + """The time base of the Annotations.""" + return self._orig_time + + @property + def extras(self): + """The extras of the Annotations. + + The ``extras`` attribute is a list of dictionaries. + It can easily be converted to a pandas DataFrame using: + ``pd.DataFrame(extras)``. + """ + return self._extras + + @extras.setter + def extras(self, extras): + self._extras = _validate_extras(extras, len(self.onset)) + + @property + def _extras_columns(self) -> set[str]: + """The set containing all the keys in all extras dicts.""" + return {k for d in self.extras for k in d} + + def __eq__(self, other): + """Compare to another Annotations instance.""" + if not isinstance(other, type(self)): + return False + return ( + np.array_equal(self.onset, other.onset) + and np.array_equal(self.duration, other.duration) + and np.array_equal(self.description, other.description) + and np.array_equal(self.ch_names, other.ch_names) + and self.orig_time == other.orig_time + ) + + def __repr__(self): + """Show the representation.""" + counter = Counter(self.description) + kinds = ", ".join(["{} ({})".format(*k) for k in sorted(counter.items())]) + kinds = (": " if len(kinds) > 0 else "") + kinds + ch_specific = ", channel-specific" if self._any_ch_names() else "" + s = ( + f"Annotations | {len(self.onset)} segment" + f"{_pl(len(self.onset))}{ch_specific}{kinds}" + ) + return "<" + shorten(s, width=77, placeholder=" ...") + ">" + + def __len__(self): + """Return the number of annotations. + + Returns + ------- + n_annot : int + The number of annotations. + """ + return len(self.duration) + + def __add__(self, other): + """Add (concatencate) two Annotation objects.""" + out = self.copy() + out += other + return out + + def __iadd__(self, other): + """Add (concatencate) two Annotation objects in-place. + + Both annotations must have the same orig_time + """ + if len(self) == 0: + self._orig_time = other.orig_time + if self.orig_time != other.orig_time: + raise ValueError( + "orig_time should be the same to add/concatenate 2 annotations (got " + f"{self.orig_time} != {other.orig_time})" + ) + return self.append( + other.onset, + other.duration, + other.description, + other.ch_names, + extras=other.extras, + ) + + def __iter__(self): + """Iterate over the annotations.""" + # Figure this out once ahead of time for consistency and speed (for + # thousands of annotations) + with_ch_names = self._any_ch_names() + for idx in range(len(self.onset)): + yield self.__getitem__(idx, with_ch_names=with_ch_names) + + def __getitem__(self, key, *, with_ch_names=None, with_extras=True): + """Propagate indexing and slicing to the underlying numpy structure.""" + if isinstance(key, int_like): + out_keys = ("onset", "duration", "description", "orig_time") + out_vals = ( + self.onset[key], + self.duration[key], + self.description[key], + self.orig_time, + ) + if with_ch_names or (with_ch_names is None and self._any_ch_names()): + out_keys += ("ch_names",) + out_vals += (self.ch_names[key],) + if with_extras: + out_keys += ("extras",) + out_vals += (self.extras[key],) + return OrderedDict(zip(out_keys, out_vals)) + else: + key = list(key) if isinstance(key, tuple) else key + return Annotations( + onset=self.onset[key], + duration=self.duration[key], + description=self.description[key], + orig_time=self.orig_time, + ch_names=self.ch_names[key], + extras=[self.extras[i] for i in np.arange(len(self.extras))[key]], + ) + + @fill_doc + def append(self, onset, duration, description, ch_names=None, *, extras=None): + """Add an annotated segment. Operates inplace. + + Parameters + ---------- + onset : float | array-like + Annotation time onset from the beginning of the recording in + seconds. + duration : float | array-like + Duration of the annotation in seconds. + description : str | array-like + Description for the annotation. To reject epochs, use description + starting with keyword 'bad'. + %(ch_names_annot)s + + .. versionadded:: 0.23 + extras : list[dict[str, int | float | str | None] | None] | None + Optional list of dicts containing extras fields for each annotation. + The number of items must match the number of annotations. + + .. versionadded:: 1.10 + + Returns + ------- + self : mne.Annotations + The modified Annotations object. + + Notes + ----- + The array-like support for arguments allows this to be used similarly + to not only ``list.append``, but also + `list.extend `__. + """ # noqa: E501 + onset, duration, description, ch_names, extras = _check_o_d_s_c_e( + onset, duration, description, ch_names, extras + ) + self.onset = np.append(self.onset, onset) + self.duration = np.append(self.duration, duration) + self.description = np.append(self.description, description) + self.ch_names = np.append(self.ch_names, ch_names) + self.extras.extend(extras) + self._sort() + return self + + def copy(self): + """Return a copy of the Annotations. + + Returns + ------- + inst : instance of Annotations + A copy of the object. + """ + return deepcopy(self) + + def delete(self, idx): + """Remove an annotation. Operates inplace. + + Parameters + ---------- + idx : int | array-like of int + Index of the annotation to remove. Can be array-like to + remove multiple indices. + """ + self.onset = np.delete(self.onset, idx) + self.duration = np.delete(self.duration, idx) + self.description = np.delete(self.description, idx) + self.ch_names = np.delete(self.ch_names, idx) + if isinstance(idx, int_like): + del self.extras[idx] + elif len(idx) > 0: + # convert slice-like idx to ints, and delete list items in reverse order + for i in np.sort(np.arange(len(self.extras))[idx])[::-1]: + del self.extras[i] + + @fill_doc + def to_data_frame(self, time_format="datetime"): + """Export annotations in tabular structure as a pandas DataFrame. + + Parameters + ---------- + %(time_format_df_raw)s + Default is ``datetime``. + + .. versionadded:: 1.7 + + Returns + ------- + result : pandas.DataFrame + Returns a pandas DataFrame with onset, duration, and + description columns. A column named ch_names is added if any + annotations are channel-specific. + """ + pd = _check_pandas_installed(strict=True) + valid_time_formats = ["ms", "timedelta", "datetime"] + dt = _handle_meas_date(self.orig_time) + if dt is None: + dt = _handle_meas_date(0) + time_format = _check_time_format(time_format, valid_time_formats, dt) + dt = dt.replace(tzinfo=None) + times = _convert_times(self.onset, time_format, meas_date=dt, drop_nano=True) + df = dict(onset=times, duration=self.duration, description=self.description) + if self._any_ch_names(): + df.update(ch_names=self.ch_names) + df = pd.DataFrame(df) + extras_df = pd.DataFrame(self.extras) + df = pd.concat([df, extras_df], axis=1) + return df + + def count(self): + """Count annotations. + + Returns + ------- + counts : dict + A dictionary containing unique annotation descriptions as keys with their + counts as values. + """ + return count_annotations(self) + + def _any_ch_names(self): + return any(len(ch) for ch in self.ch_names) + + def _prune_ch_names(self, info, on_missing): + # this prunes channel names and if a given channel-specific annotation + # no longer has any channels left, it gets dropped + keep = set(info["ch_names"]) + ch_names = self.ch_names + warned = False + drop_idx = list() + for ci, ch in enumerate(ch_names): + if len(ch): + names = list() + for name in ch: + if name not in keep: + if not warned: + _on_missing( + on_missing, + "At least one channel name in " + f"annotations missing from info: {name}", + ) + warned = True + else: + names.append(name) + ch_names[ci] = tuple(names) + if not len(ch_names[ci]): + drop_idx.append(ci) + if len(drop_idx): + self.delete(drop_idx) + return self + + @verbose + def save(self, fname, *, overwrite=False, verbose=None): + """Save annotations to FIF, CSV or TXT. + + Typically annotations get saved in the FIF file for raw data + (e.g., as ``raw.annotations``), but this offers the possibility + to also save them to disk separately in different file formats + which are easier to share between packages. + + Parameters + ---------- + fname : path-like + The filename to use. + %(overwrite)s + + .. versionadded:: 0.23 + %(verbose)s + + Notes + ----- + The format of the information stored in the saved annotation objects + depends on the chosen file format. :file:`.csv` files store the onset + as timestamps (e.g., ``2002-12-03 19:01:56.676071``), + whereas :file:`.txt` files store onset as seconds since start of the + recording (e.g., ``45.95597082905339``). + """ + check_fname( + fname, + "annotations", + ( + "-annot.fif", + "-annot.fif.gz", + "_annot.fif", + "_annot.fif.gz", + ".txt", + ".csv", + ), + ) + fname = _check_fname(fname, overwrite=overwrite) + if fname.suffix == ".txt": + _write_annotations_txt(fname, self) + elif fname.suffix == ".csv": + _write_annotations_csv(fname, self) + else: + with start_and_end_file(fname) as fid: + _write_annotations(fid, self) + + def _sort(self): + """Sort in place.""" + # instead of argsort here we use sorted so that it gives us + # the onset-then-duration hierarchy + vals = sorted(zip(self.onset, self.duration, range(len(self)))) + order = list(list(zip(*vals))[-1]) if len(vals) else [] + self.onset = self.onset[order] + self.duration = self.duration[order] + self.description = self.description[order] + self.ch_names = self.ch_names[order] + self.extras = [self.extras[i] for i in order] + return order + + def _get_crop_lims(self, tmin, tmax, use_orig_time): + """Compute absolute crop limits and offset.""" + if not use_orig_time or self.orig_time is None: + offset = _handle_meas_date(0) + else: + offset = self.orig_time + if tmin is None: + tmin = timedelta(seconds=self.onset.min()) + offset + if tmax is None: + tmax = timedelta(seconds=(self.onset + self.duration).max()) + offset + for key, val in [("tmin", tmin), ("tmax", tmax)]: + _validate_type( + val, ("numeric", _datetime), key, "numeric, datetime, or None" + ) + absolute_tmin = _handle_meas_date(tmin) + absolute_tmax = _handle_meas_date(tmax) + if absolute_tmin > absolute_tmax: + raise ValueError( + f"tmax should be greater than or equal to tmin ({absolute_tmin} < " + f"{absolute_tmax})." + ) + return offset, absolute_tmin, absolute_tmax + + @verbose + def crop( + self, tmin=None, tmax=None, emit_warning=False, use_orig_time=True, verbose=None + ): + """Remove all annotations that are outside of [tmin, tmax]. + + The method operates inplace. + + Parameters + ---------- + tmin : float | datetime | None + Start time of selection in seconds. + tmax : float | datetime | None + End time of selection in seconds. + emit_warning : bool + Whether to emit warnings when limiting or omitting annotations. + Defaults to False. + use_orig_time : bool + Whether to use orig_time as an offset. + Defaults to True. + %(verbose)s + + Returns + ------- + self : instance of Annotations + The cropped Annotations object. + """ + if len(self) == 0: + return self # no annotations, nothing to do + offset, absolute_tmin, absolute_tmax = self._get_crop_lims( + tmin, tmax, use_orig_time + ) + del tmin, tmax + logger.debug(f"Cropping annotations {absolute_tmin} - {absolute_tmax}") + + onsets, durations, descriptions, ch_names, extras = [], [], [], [], [] + out_of_bounds, clip_left_elem, clip_right_elem = [], [], [] + for idx, (onset, duration, description, ch, extra) in enumerate( + zip(self.onset, self.duration, self.description, self.ch_names, self.extras) + ): + # if duration is NaN behave like a zero + if np.isnan(duration): + duration = 0.0 + # convert to absolute times + absolute_onset = timedelta(seconds=onset) + offset + absolute_offset = absolute_onset + timedelta(seconds=duration) + out_of_bounds.append( + absolute_onset > absolute_tmax or absolute_offset < absolute_tmin + ) + if out_of_bounds[-1]: + clip_left_elem.append(False) + clip_right_elem.append(False) + logger.debug( + f" [{idx}] Dropping " + f"({absolute_onset} - {absolute_offset}: {description})" + ) + else: + # clip the left side + clip_left_elem.append(absolute_onset < absolute_tmin) + if clip_left_elem[-1]: + absolute_onset = absolute_tmin + clip_right_elem.append(absolute_offset > absolute_tmax) + if clip_right_elem[-1]: + absolute_offset = absolute_tmax + if clip_left_elem[-1] or clip_right_elem[-1]: + durations.append((absolute_offset - absolute_onset).total_seconds()) + else: + durations.append(duration) + onsets.append((absolute_onset - offset).total_seconds()) + logger.debug( + f" [{idx}] Keeping " + f"({absolute_onset} - {absolute_offset} -> " + f"{onset} - {onset + duration})" + ) + descriptions.append(description) + ch_names.append(ch) + extras.append(extra) + logger.debug(f"Cropping complete (kept {len(onsets)})") + self.onset = np.array(onsets, float) + self.duration = np.array(durations, float) + assert (self.duration >= 0).all() + self.description = np.array(descriptions, dtype=str) + self.ch_names = _ndarray_ch_names(ch_names) + self.extras = extras + + if emit_warning: + omitted = np.array(out_of_bounds).sum() + if omitted > 0: + warn(f"Omitted {omitted} annotation(s) that were outside data range.") + limited = (np.array(clip_left_elem) | np.array(clip_right_elem)).sum() + if limited > 0: + warn( + f"Limited {limited} annotation(s) that were expanding outside the" + " data range." + ) + + return self + + @verbose + def set_durations(self, mapping, verbose=None): + """Set annotation duration(s). Operates inplace. + + Parameters + ---------- + mapping : dict | float + A dictionary mapping the annotation description to a duration in + seconds e.g. ``{'ShortStimulus' : 3, 'LongStimulus' : 12}``. + Alternatively, if a number is provided, then all annotations + durations are set to the single provided value. + %(verbose)s + + Returns + ------- + self : mne.Annotations + The modified Annotations object. + + Notes + ----- + .. versionadded:: 0.24.0 + """ + _validate_type(mapping, (int, float, dict)) + + if isinstance(mapping, dict): + _check_dict_keys( + mapping, + self.description, + valid_key_source="data", + key_description="Annotation description(s)", + ) + for stim in mapping: + map_idx = [desc == stim for desc in self.description] + self.duration[map_idx] = mapping[stim] + + elif _is_numeric(mapping): + self.duration = np.ones(self.description.shape) * mapping + + else: + raise ValueError( + "Setting durations requires the mapping of " + "descriptions to times to be provided as a dict. " + f"Instead {type(mapping)} was provided." + ) + + return self + + @verbose + def rename(self, mapping, verbose=None): + """Rename annotation description(s). Operates inplace. + + Parameters + ---------- + mapping : dict + A dictionary mapping the old description to a new description, + e.g. {'1.0' : 'Control', '2.0' : 'Stimulus'}. + %(verbose)s + + Returns + ------- + self : mne.Annotations + The modified Annotations object. + + Notes + ----- + .. versionadded:: 0.24.0 + """ + _validate_type(mapping, dict) + _check_dict_keys( + mapping, + self.description, + valid_key_source="data", + key_description="Annotation description(s)", + ) + self.description = np.array([str(mapping.get(d, d)) for d in self.description]) + return self + + +class _HEDStrings(list): + """Subclass of list that will validate before __setitem__.""" + + def __init__(self, *args, hed_version, **kwargs): + self._hed = _soft_import("hed", "validation of HED tags in annotations") + self._schema = self._hed.load_schema_version(hed_version) + super().__init__(*args, **kwargs) + self._objs = [self._validate_hed_string(item, self._schema) for item in self] + + def __setitem__(self, key, value): + """Validate value first, before assigning.""" + if isinstance(key, slice): + hss = [self._validate_hed_string(v, self._schema) for v in value] + super().__setitem__(key, [hs.get_original_hed_string() for hs in hss]) + self._objs[key] = hss + return + hs = self._validate_hed_string(value, self._schema) + super().__setitem__(key, hs.get_original_hed_string()) + self._objs[key] = hs + + def _validate_hed_string(self, value, schema): + # create HedString object and validate it + hs = self._hed.HedString(value, schema) + # handle any errors + error_handler = self._hed.errors.ErrorHandler(check_for_warnings=False) + issues = hs.validate(allow_placeholders=False, error_handler=error_handler) + error_string = self._hed.get_printable_issue_string(issues) + if len(error_string): + raise ValueError(f"A HED string failed to validate:\n {error_string}") + hs.sort() + return hs + + def append(self, item): + """Append an item to the end of the HEDString list.""" + hs = self._validate_hed_string(item, self._schema) + super().append(hs.get_original_hed_string()) + self._objs.append(hs) + + +@fill_doc +class HEDAnnotations(Annotations): + """Annotations object for annotating segments of raw data with HED tags. + + Parameters + ---------- + onset : array of float, shape (n_annotations,) + The starting time of annotations in seconds after ``orig_time``. + duration : array of float, shape (n_annotations,) | float + Durations of the annotations in seconds. If a float, all the + annotations are given the same duration. + description : array of str, shape (n_annotations,) | str + Array of strings containing description for each annotation. If a + string, all the annotations are given the same description. To reject + epochs, use description starting with keyword 'bad'. See example above. + hed_string : array of str, shape (n_annotations,) | str + Sequence of strings containing a HED tag (or comma-separated list of HED tags) + for each annotation. If a single string is provided, all annotations are + assigned the same HED string. + hed_version : str + The HED schema version against which to validate the HED strings. + orig_time : float | str | datetime | tuple of int | None + A POSIX Timestamp, datetime or a tuple containing the timestamp as the + first element and microseconds as the second element. Determines the + starting time of annotation acquisition. If None (default), + starting time is determined from beginning of raw data acquisition. + In general, ``raw.info['meas_date']`` (or None) can be used for syncing + the annotations with raw data if their acquisition is started at the + same time. If it is a string, it should conform to the ISO8601 format. + More precisely to this '%%Y-%%m-%%d %%H:%%M:%%S.%%f' particular case of + the ISO8601 format where the delimiter between date and time is ' '. + %(ch_names_annot)s + extras : list[dict[str, int | float | str | None] | None] | None + Optional list of dicts containing extra fields for each annotation. + The number of items must match the number of annotations. + + See Also + -------- + mne.Annotations + + Notes + ----- + + .. versionadded:: 1.12 + """ + + def __init__( + self, + onset, + duration, + description, + hed_string, + hed_version="8.3.0", + orig_time=None, + ch_names=None, + *, + extras=None, + ): + onset, duration, description, ch_names, extras = _check_o_d_s_c_e( + onset, duration, description, ch_names, extras + ) + hed_string = self._check_hed_strings(hed_string, len(onset)) + self._hed_version = hed_version + self.hed_string = _HEDStrings(hed_string, hed_version=self._hed_version) + super().__init__( + onset=onset, + duration=duration, + description=description, + orig_time=orig_time, + ch_names=ch_names, + extras=extras, + ) + + @staticmethod + def _check_hed_strings(hed_string, n_annot): + """Check HED string container length and allow scalar broadcast.""" + _validate_type(hed_string, (str, list, tuple, np.ndarray), "hed_string") + if isinstance(hed_string, str): + return [hed_string] * n_annot + hed_string = list(hed_string) + if len(hed_string) != n_annot: + raise ValueError( + "Onset, duration, description, ch_names, hed_string, and extras " + f"must be equal in sizes, got {n_annot} != {len(hed_string)}." + ) + return hed_string + + def __eq__(self, other): + """Compare to another HEDAnnotations instance.""" + if not super().__eq__(other): + return False + _slf = self.hed_string + _oth = other.hed_string + + if _compare_version(self._hed_version, "<", other._hed_version): + _slf = [_slf._validate_hed_string(v, _oth._schema) for v in _slf._objs] + elif _compare_version(self._hed_version, ">", other._hed_version): + _oth = [_oth._validate_hed_string(v, _slf._schema) for v in _oth._objs] + return _slf == _oth + + def __repr__(self): + """Show a textual summary of the object.""" + counter = Counter([hs.get_as_short() for hs in self.hed_string._objs]) + + # textwrap.shorten won't work: we remove all spaces and shouldn't split on `-` + def _shorten(text, width=74, placeholder=" ..."): + parts = text.split(",") + out = parts[0] + for part in parts[1:]: + # +1 for the comma ↓↓↓ + if width < len(out) + 1 + len(part) + len(placeholder): + break + out = f"{out},{part}" + return out + placeholder + + kinds = [ + f"{_shorten(k, width=74):<74} ({v})" for k, v in sorted(counter.items()) + ] + if len(kinds) > 5: + kinds = [*kinds[:5], f"... and {len(kinds) - 5} more"] + kinds = "\n ".join(kinds) + if len(kinds): + kinds = f":\n {kinds}\n" + ch_specific = ", channel-specific" if self._any_ch_names() else "" + s = ( + f"HEDAnnotations | {len(self.onset)} segment" + f"{_pl(len(self.onset))}{ch_specific}{kinds}" + ) + return f"<{s}>" + + def __getitem__(self, key, *, with_ch_names=None, with_extras=True): + """Propagate indexing and slicing to the underlying structure.""" + result = super().__getitem__( + key, with_ch_names=with_ch_names, with_extras=with_extras + ) + if isinstance(result, OrderedDict): + result["hed_string"] = self.hed_string[key] + return result + # result not an odict; must be an Annotations obj + key = np.arange(len(self.hed_string))[key] + hed_string = [self.hed_string[idx] for idx in np.atleast_1d(key)] + return HEDAnnotations( + result.onset, + result.duration, + result.description, + hed_string=hed_string, + hed_version=self._hed_version, + orig_time=self.orig_time, + ch_names=result.ch_names, + extras=result.extras if with_extras else None, + ) + + def __getstate__(self): + """Make serialization work, by removing module reference.""" + return dict( + _orig_time=self._orig_time, + onset=self.onset, + duration=self.duration, + description=self.description, + ch_names=self.ch_names, + _extras=self.extras, + hed_string=list(self.hed_string), + _hed_version=self._hed_version, + ) + + def __setstate__(self, state): + """Unpack from serialized format.""" + self._orig_time = state["_orig_time"] + self.onset = state["onset"] + self.duration = state["duration"] + self.description = state["description"] + self.ch_names = state["ch_names"] + self.extras = state.get("_extras", [None] * len(self.onset)) + self._hed_version = state["_hed_version"] + self.hed_string = _HEDStrings( + state["hed_string"], hed_version=self._hed_version + ) + + @fill_doc + def append( + self, *, onset, duration, description, hed_string, ch_names=None, extras=None + ): + """Add an annotated segment. Operates inplace. + + Parameters + ---------- + onset : float | array-like + Annotation time onset from the beginning of the recording in + seconds. + duration : float | array-like + Duration of the annotation in seconds. + description : str | array-like + Description for the annotation. To reject epochs, use description + starting with keyword 'bad'. + hed_string : array of str, shape (n_annotations,) | str + Sequence of strings containing a HED tag (or comma-separated list of HED + tags) for each annotation. If a single string is provided, all annotations + are assigned the same HED string. + %(ch_names_annot)s + extras : list[dict[str, int | float | str | None] | None] | None + Optional list of dicts containing extras fields for each annotation. + + Returns + ------- + self : mne.HEDAnnotations + The modified HEDAnnotations object. + """ + onset, duration, description, ch_names, extras = _check_o_d_s_c_e( + onset, duration, description, ch_names, extras + ) + hed_string = self._check_hed_strings(hed_string, len(onset)) + hed_objs = [ + self.hed_string._validate_hed_string(v, self.hed_string._schema) + for v in hed_string + ] + self.hed_string.extend([hs.get_original_hed_string() for hs in hed_objs]) + self.hed_string._objs.extend(hed_objs) + super().append( + onset=onset, + duration=duration, + description=description, + ch_names=ch_names, + extras=extras, + ) + return self + + def __iadd__(self, other): + """Add (concatenate) two HEDAnnotations objects in-place.""" + if not isinstance(other, type(self)): + raise TypeError( + f"Cannot concatenate {type(self).__name__} and {type(other).__name__}." + ) + if len(self) == 0: + self._orig_time = other.orig_time + if self.orig_time != other.orig_time: + raise ValueError( + "orig_time should be the same to add/concatenate 2 annotations (got " + f"{self.orig_time} != {other.orig_time})" + ) + return self.append( + onset=other.onset, + duration=other.duration, + description=other.description, + hed_string=list(other.hed_string), + ch_names=other.ch_names, + extras=other.extras, + ) + + def delete(self, idx): + """Remove an annotation. Operates inplace. + + Parameters + ---------- + idx : int | array-like of int + Index of the annotation to remove. Can be array-like to remove multiple + indices. + """ + super().delete(idx) + if isinstance(idx, int_like): + del self.hed_string._objs[idx] + del self.hed_string[idx] + else: + for i in np.sort(np.arange(len(self.hed_string))[idx])[::-1]: + del self.hed_string._objs[i] + del self.hed_string[i] + + def _sort(self): + """Sort in place.""" + order = super()._sort() + self.hed_string._objs = [self.hed_string._objs[i] for i in order] + for i in order: + self.hed_string.__setitem__( + i, self.hed_string._objs[i].get_original_hed_string() + ) + + @verbose + def crop( + self, tmin=None, tmax=None, emit_warning=False, use_orig_time=True, verbose=None + ): + """Remove all annotations that are outside of [tmin, tmax]. + + The method operates inplace. + + Parameters + ---------- + tmin : float | datetime | None + Start time of selection in seconds. + tmax : float | datetime | None + End time of selection in seconds. + emit_warning : bool + Whether to emit warnings when limiting or omitting annotations. + Defaults to False. + use_orig_time : bool + Whether to use orig_time as an offset. + Defaults to True. + %(verbose)s + + Returns + ------- + self : instance of HEDAnnotations + The cropped HEDAnnotations object. + """ + if len(self) == 0: + return self + offset, absolute_tmin, absolute_tmax = self._get_crop_lims( + tmin, tmax, use_orig_time + ) + + keep = [] + hed_strings = list(self.hed_string) + for idx, (onset, duration) in enumerate(zip(self.onset, self.duration)): + if np.isnan(duration): + duration = 0.0 + absolute_onset = timedelta(seconds=onset) + offset + absolute_offset = absolute_onset + timedelta(seconds=duration) + out_of_bounds = ( + absolute_onset > absolute_tmax or absolute_offset < absolute_tmin + ) + if not out_of_bounds: + keep.append(idx) + + super().crop( + tmin=absolute_tmin, + tmax=absolute_tmax, + emit_warning=emit_warning, + use_orig_time=use_orig_time, + verbose=verbose, + ) + self.hed_string = _HEDStrings( + [hed_strings[idx] for idx in keep], hed_version=self._hed_version + ) + return self + + @fill_doc + def to_data_frame(self, time_format="datetime"): + """Export annotations in tabular structure as a pandas DataFrame. + + Parameters + ---------- + %(time_format_df_raw)s + + Returns + ------- + result : pandas.DataFrame + Returns a pandas DataFrame with onset, duration, description, + and hed_string columns. A column named ch_names is added if any + annotations are channel-specific. + """ + df = super().to_data_frame(time_format=time_format) + df["hed_string"] = list(self.hed_string) + return df + + +class EpochAnnotationsMixin: + """Mixin class for Annotations in Epochs.""" + + @property + def annotations(self): # noqa: D102 + return self._annotations + + @verbose + def set_annotations(self, annotations, on_missing="raise", *, verbose=None): + """Setter for Epoch annotations from Raw. + + This method does not handle offsetting the times based + on first_samp or measurement dates, since that is expected + to occur in Raw.set_annotations(). + + Parameters + ---------- + annotations : instance of mne.Annotations | None + Annotations to set. + %(on_missing_ch_names)s + %(verbose)s + + Returns + ------- + self : instance of Epochs + The epochs object with annotations. + + Notes + ----- + Annotation onsets and offsets are stored as time in seconds (not as + sample numbers). + + If you have an ``-epo.fif`` file saved to disk created before 1.0, + annotations can be added correctly only if no decimation or + resampling was performed. We thus suggest to regenerate your + :class:`mne.Epochs` from raw and re-save to disk with 1.0+ if you + want to safely work with :class:`~mne.Annotations` in epochs. + + Since this method does not handle offsetting the times based + on first_samp or measurement dates, the recommended way to add + Annotations is:: + + raw.set_annotations(annotations) + annotations = raw.annotations + epochs.set_annotations(annotations) + + .. versionadded:: 1.0 + """ + _validate_type(annotations, (Annotations, None), "annotations") + if annotations is None: + self._annotations = None + else: + if getattr(self, "_unsafe_annot_add", False): + warn( + "Adding annotations to Epochs created (and saved to disk) before " + "1.0 will yield incorrect results if decimation or resampling was " + "performed on the instance, we recommend regenerating the Epochs " + "and re-saving them to disk." + ) + new_annotations = annotations.copy() + new_annotations._prune_ch_names(self.info, on_missing) + self._annotations = new_annotations + return self + + def get_annotations_per_epoch(self, *, with_extras=False): + """Get a list of annotations that occur during each epoch. + + Parameters + ---------- + with_extras : bool + Whether to include the annotations extra fields in the output, + as an additional last element of the tuple. Default is False. + + .. versionadded:: 1.10 + + Returns + ------- + epoch_annots : list + A list of lists (with length equal to number of epochs) where each + inner list contains any annotations that overlap the corresponding + epoch. Annotations are stored as a :class:`tuple` of onset, + duration, description (not as a :class:`~mne.Annotations` object), + where the onset is now relative to time=0 of the epoch, rather than + time=0 of the original continuous (raw) data. + """ + # create a list of annotations for each epoch + epoch_annot_list = [[] for _ in range(len(self.events))] + + # check if annotations exist + if self.annotations is None: + return epoch_annot_list + + # when each epoch and annotation starts/stops + # no need to account for first_samp here... + epoch_tzeros = self.events[:, 0] / self._raw_sfreq + epoch_starts, epoch_stops = ( + np.atleast_2d(epoch_tzeros) + np.atleast_2d(self.times[[0, -1]]).T + ) + # ... because first_samp isn't accounted for here either + annot_starts = self._annotations.onset + annot_stops = annot_starts + self._annotations.duration + + # the first two cases (annot_straddles_epoch_{start|end}) will both + # (redundantly) capture cases where an annotation fully encompasses + # an epoch (e.g., annot from 1-4s, epoch from 2-3s). The redundancy + # doesn't matter because results are summed and then cast to bool (all + # we care about is presence/absence of overlap). + annot_straddles_epoch_start = np.logical_and( + np.atleast_2d(epoch_starts) >= np.atleast_2d(annot_starts).T, + np.atleast_2d(epoch_starts) < np.atleast_2d(annot_stops).T, + ) + + annot_straddles_epoch_end = np.logical_and( + np.atleast_2d(epoch_stops) > np.atleast_2d(annot_starts).T, + np.atleast_2d(epoch_stops) <= np.atleast_2d(annot_stops).T, + ) + + # this captures the only remaining case we care about: annotations + # fully contained within an epoch (or exactly coextensive with it). + annot_fully_within_epoch = np.logical_and( + np.atleast_2d(epoch_starts) <= np.atleast_2d(annot_starts).T, + np.atleast_2d(epoch_stops) >= np.atleast_2d(annot_stops).T, + ) + + # combine all cases to get array of shape (n_annotations, n_epochs). + # Nonzero entries indicate overlap between the corresponding + # annotation (row index) and epoch (column index). + all_cases = ( + annot_straddles_epoch_start + + annot_straddles_epoch_end + + annot_fully_within_epoch + ) + + # for each Epoch-Annotation overlap occurrence: + for annot_ix, epo_ix in zip(*np.nonzero(all_cases)): + this_annot = self._annotations[annot_ix] + this_tzero = epoch_tzeros[epo_ix] + # adjust annotation onset to be relative to epoch tzero... + annot = ( + this_annot["onset"] - this_tzero, + this_annot["duration"], + this_annot["description"], + ) + if with_extras: + annot += (this_annot["extras"],) + # ...then add it to the correct sublist of `epoch_annot_list` + epoch_annot_list[epo_ix].append(annot) + return epoch_annot_list + + def add_annotations_to_metadata(self, overwrite=False, *, with_extras=True): + """Add raw annotations into the Epochs metadata data frame. + + Adds three columns to the ``metadata`` consisting of a list + in each row: + - ``annot_onset``: the onset of each Annotation within + the Epoch relative to the start time of the Epoch (in seconds). + - ``annot_duration``: the duration of each Annotation + within the Epoch in seconds. + - ``annot_description``: the free-form text description of each + Annotation. + + Parameters + ---------- + overwrite : bool + Whether to overwrite existing columns in metadata or not. + Default is False. + with_extras : bool + Whether to include the annotations extra fields in the output, + as an additional last element of the tuple. Default is True. + + .. versionadded:: 1.10 + + Returns + ------- + self : instance of Epochs + The modified instance (instance is also modified inplace). + + Notes + ----- + .. versionadded:: 1.0 + """ + pd = _check_pandas_installed() + + # check if annotations exist + if self.annotations is None: + warn( + f"There were no Annotations stored in {self}, so " + "metadata was not modified." + ) + return self + + # get existing metadata DataFrame or instantiate an empty one + if self._metadata is not None: + metadata = self._metadata + else: + data = np.empty((len(self.events), 0)) + metadata = pd.DataFrame(data=data) + + if ( + any( + name in metadata.columns + for name in ["annot_onset", "annot_duration", "annot_description"] + ) + and not overwrite + ): + raise RuntimeError( + "Metadata for Epochs already contains columns " + '"annot_onset", "annot_duration", or "annot_description".' + ) + + # get the Epoch annotations, then convert to separate lists for + # onsets, durations, and descriptions + epoch_annot_list = self.get_annotations_per_epoch(with_extras=with_extras) + onset, duration, description = [], [], [] + extras = {k: [] for k in self.annotations._extras_columns} + for epoch_annot in epoch_annot_list: + for ix, annot_prop in enumerate((onset, duration, description)): + entry = [annot[ix] for annot in epoch_annot] + + # round onset and duration to avoid IO round trip mismatch + if ix < 2: + entry = np.round(entry, decimals=12).tolist() + + annot_prop.append(entry) + for k in extras.keys(): + entry = [annot[3].get(k, None) for annot in epoch_annot] + extras[k].append(entry) + + # Create a new Annotations column that is instantiated as an empty + # list per Epoch. + metadata["annot_onset"] = pd.Series(onset) + metadata["annot_duration"] = pd.Series(duration) + metadata["annot_description"] = pd.Series(description) + for k, v in extras.items(): + metadata[f"annot_{k}"] = pd.Series(v) + + # reset the metadata + self.metadata = metadata + return self + + +def _combine_annotations( + one, two, one_n_samples, one_first_samp, two_first_samp, sfreq +): + """Combine a tuple of annotations.""" + assert one is not None + assert two is not None + shift = one_n_samples / sfreq # to the right by the number of samples + shift += one_first_samp / sfreq # to the right by the offset + shift -= two_first_samp / sfreq # undo its offset + onset = np.concatenate([one.onset, two.onset + shift]) + duration = np.concatenate([one.duration, two.duration]) + description = np.concatenate([one.description, two.description]) + ch_names = np.concatenate([one.ch_names, two.ch_names]) + return Annotations(onset, duration, description, one.orig_time, ch_names) + + +def _handle_meas_date(meas_date): + """Convert meas_date to datetime or None. + + If `meas_date` is a string, it should conform to the ISO8601 format. + More precisely to this '%Y-%m-%d %H:%M:%S.%f' particular case of the + ISO8601 format where the delimiter between date and time is ' '. + Note that ISO8601 allows for ' ' or 'T' as delimiters between date and + time. + """ + if isinstance(meas_date, str): + ACCEPTED_ISO8601 = "%Y-%m-%d %H:%M:%S.%f" + try: + meas_date = datetime.strptime(meas_date, ACCEPTED_ISO8601) + except ValueError: + meas_date = None + else: + meas_date = meas_date.replace(tzinfo=timezone.utc) + elif isinstance(meas_date, tuple): + # old way + meas_date = _stamp_to_dt(meas_date) + if meas_date is not None: + if np.isscalar(meas_date): + # It would be nice just to do: + # + # meas_date = datetime.fromtimestamp(meas_date, timezone.utc) + # + # But Windows does not like timestamps < 0. So we'll use + # our specialized wrapper instead: + meas_date = np.array(np.modf(meas_date)[::-1]) + meas_date *= [1, 1e6] + meas_date = _stamp_to_dt(np.round(meas_date)) + _check_dt(meas_date) # run checks + return meas_date + + +def _sync_onset(raw, onset, inverse=False): + """Adjust onsets in relation to raw data.""" + offset = (-1 if inverse else 1) * raw._first_time + assert raw.info["meas_date"] == raw.annotations.orig_time + annot_start = onset - offset + return annot_start + + +def _annotations_starts_stops(raw, kinds, name="skip_by_annotation", invert=False): + """Get starts and stops from given kinds. + + onsets and ends are inclusive. + """ + _validate_type(kinds, (str, list, tuple), name) + if isinstance(kinds, str): + kinds = [kinds] + else: + for kind in kinds: + _validate_type(kind, "str", "All entries") + + if len(raw.annotations) == 0: + onsets, ends = np.array([], int), np.array([], int) + else: + idxs = [ + idx + for idx, desc in enumerate(raw.annotations.description) + if any(desc.upper().startswith(kind.upper()) for kind in kinds) + ] + # onsets are already sorted + onsets = raw.annotations.onset[idxs] + onsets = _sync_onset(raw, onsets) + ends = onsets + raw.annotations.duration[idxs] + onsets = raw.time_as_index(onsets, use_rounding=True) + ends = raw.time_as_index(ends, use_rounding=True) + assert (onsets <= ends).all() # all durations >= 0 + if invert: + # We need to eliminate overlaps here, otherwise wacky things happen, + # so we carefully invert the relationship + mask = np.zeros(len(raw.times), bool) + for onset, end in zip(onsets, ends): + mask[onset:end] = True + mask = ~mask + extras = onsets == ends + extra_onsets, extra_ends = onsets[extras], ends[extras] + onsets, ends = _mask_to_onsets_offsets(mask) + # Keep ones where things were exactly equal + del extras + # we could do this with a np.insert+np.searchsorted, but our + # ordered-ness should get us it for free + onsets = np.sort(np.concatenate([onsets, extra_onsets])) + ends = np.sort(np.concatenate([ends, extra_ends])) + assert (onsets <= ends).all() + return onsets, ends + + +def _write_annotations(fid, annotations): + """Write annotations.""" + start_block(fid, FIFF.FIFFB_MNE_ANNOTATIONS) + write_float(fid, FIFF.FIFF_MNE_BASELINE_MIN, annotations.onset) + write_float( + fid, FIFF.FIFF_MNE_BASELINE_MAX, annotations.duration + annotations.onset + ) + write_name_list_sanitized( + fid, FIFF.FIFF_COMMENT, annotations.description, name="description" + ) + if annotations.orig_time is not None: + write_double(fid, FIFF.FIFF_MEAS_DATE, _dt_to_stamp(annotations.orig_time)) + if annotations._any_ch_names(): + write_string( + fid, FIFF.FIFF_MNE_EPOCHS_DROP_LOG, json.dumps(tuple(annotations.ch_names)) + ) + if any(d is not None for d in annotations.extras): + write_string( + fid, + FIFF.FIFF_FREE_LIST, + json.dumps([extra.data for extra in annotations.extras]), + ) + end_block(fid, FIFF.FIFFB_MNE_ANNOTATIONS) + + +def _write_annotations_csv(fname, annot): + annot = annot.to_data_frame() + if "ch_names" in annot: + annot["ch_names"] = [ + _safe_name_list(ch, "write", name=f'annot["ch_names"][{ci}') + for ci, ch in enumerate(annot["ch_names"]) + ] + extras_columns = set(annot.columns) - { + "onset", + "duration", + "description", + "ch_names", + } + for col in extras_columns: + if len(dtypes := annot[col].apply(type).unique()) > 1: + warn( + f"Extra field '{col}' contains heterogeneous dtypes ({dtypes}). " + "Loading these CSV annotations may not return the original dtypes." + ) + annot.to_csv(fname, index=False) + + +def _write_annotations_txt(fname, annot): + content = "# MNE-Annotations\n" + if annot.orig_time is not None: + # for backward compat, we do not write tzinfo (assumed UTC) + content += f"# orig_time : {annot.orig_time.replace(tzinfo=None)}\n" + content += "# onset, duration, description" + n_cols = 3 + data = [annot.onset, annot.duration, annot.description] + if annot._any_ch_names(): + n_cols += 1 + content += ", ch_names" + data.append( + [ + _safe_name_list(ch, "write", f"annot.ch_names[{ci}]") + for ci, ch in enumerate(annot.ch_names) + ] + ) + if len(extras_columns := annot._extras_columns) > 0: + n_cols += len(extras_columns) + for column in extras_columns: + content += f", {column}" + values = [extra.get(column, None) for extra in annot.extras] + if len(dtypes := set(type(v) for v in values)) > 1: + warn( + f"Extra field '{column}' contains heterogeneous dtypes ({dtypes}). " + "Loading these TXT annotations may not return the original dtypes." + ) + data.append([val if val is not None else "" for val in values]) + content += "\n" + data = np.array(data, dtype=str).T + assert data.ndim == 2 + assert data.shape[0] == len(annot.onset) + assert data.shape[1] == n_cols + with open(fname, "wb") as fid: + fid.write(content.encode()) + np.savetxt(fid, data, delimiter=",", fmt="%s") + + +@fill_doc +def read_annotations( + fname, sfreq="auto", uint16_codec=None, encoding="utf8", ignore_marker_types=False +) -> Annotations: + r"""Read annotations from a file. + + This function reads a ``.fif``, ``.fif.gz``, ``.vmrk``, ``.amrk``, + ``.edf``, ``.bdf``, ``.gdf``, ``.txt``, ``.csv``, ``.cnt``, ``.cef``, or + ``.set`` file and makes an :class:`mne.Annotations` object. + + Parameters + ---------- + fname : path-like + The filename. + sfreq : float | ``'auto'`` + The sampling frequency in the file. This parameter is necessary for + \*.vmrk, \*.amrk, and \*.cef files as Annotations are expressed in + seconds and \*.vmrk/\*.amrk/\*.cef files are in samples. For any other + file format, ``sfreq`` is omitted. If set to 'auto' then the ``sfreq`` + is taken from the respective info file of the same name with according + file extension (\*.vhdr/\*.ahdr for brainvision; \*.dap for Curry 7; + \*.cdt.dpa for Curry 8). So data.vmrk/amrk looks for sfreq in + data.vhdr/ahdr, data.cef looks in data.dap and data.cdt.cef looks in + data.cdt.dpa. + uint16_codec : str | None + This parameter is only used in EEGLAB (\*.set) and omitted otherwise. + If your \*.set file contains non-ascii characters, sometimes reading + it may fail and give rise to error message stating that "buffer is + too small". ``uint16_codec`` allows to specify what codec (for example: + ``'latin1'`` or ``'utf-8'``) should be used when reading character + arrays and can therefore help you solve this problem. + %(encoding_edf)s + Only used when reading EDF annotations. + ignore_marker_types : bool + If ``True``, ignore marker types in BrainVision files (and only use their + descriptions). Defaults to ``False``. + + Returns + ------- + annot : instance of Annotations + The annotations. + + Notes + ----- + The annotations stored in a ``.csv`` require the onset columns to be + timestamps. If you have onsets as floats (in seconds), you should use the + ``.txt`` extension. + """ + from .io.brainvision.brainvision import _read_annotations_brainvision + from .io.cnt.cnt import _read_annotations_cnt + from .io.ctf.markers import _read_annotations_ctf + from .io.curry.curry import _read_annotations_curry + from .io.edf.edf import _read_annotations_edf + from .io.eeglab.eeglab import _read_annotations_eeglab + + fname = _check_fname( + fname, + overwrite="read", + must_exist=True, + need_dir=str(fname).endswith(".ds"), # for CTF + name="fname", + ) + readers = { + ".csv": _read_annotations_csv, + ".cnt": _read_annotations_cnt, + ".ds": _read_annotations_ctf, + ".dat": _read_annotations_curry, + ".cdt": _read_annotations_curry, + ".cef": _read_annotations_curry, + ".set": _read_annotations_eeglab, + ".edf": _read_annotations_edf, + ".bdf": _read_annotations_edf, + ".gdf": _read_annotations_edf, + ".vmrk": _read_annotations_brainvision, + ".amrk": _read_annotations_brainvision, + ".txt": _read_annotations_txt, + } + kwargs = { + ".vmrk": {"sfreq": sfreq, "ignore_marker_types": ignore_marker_types}, + ".amrk": {"sfreq": sfreq, "ignore_marker_types": ignore_marker_types}, + ".dat": {"sfreq": sfreq}, + ".cdt": {"sfreq": sfreq}, + ".cef": {"sfreq": sfreq}, + ".set": {"uint16_codec": uint16_codec}, + ".edf": {"encoding": encoding}, + ".bdf": {"encoding": encoding}, + ".gdf": {"encoding": encoding}, + } + if fname.suffix in readers: + annotations = readers[fname.suffix](fname, **kwargs.get(fname.suffix, {})) + elif fname.name.endswith(("fif", "fif.gz")): + # Read FiF files + ff, tree, _ = fiff_open(fname, preload=False) + with ff as fid: + annotations = _read_annotations_fif(fid, tree) + elif fname.name.startswith("events_") and fname.suffix == ".mat": + annotations = _read_brainstorm_annotations(fname) + else: + raise OSError(f'Unknown annotation file format "{fname}"') + + if annotations is None: + raise OSError(f'No annotation data found in file "{fname}"') + return annotations + + +def _read_annotations_csv(fname): + """Read annotations from csv. + + The dtypes of the extra fields will automatically be inferred + by pandas. If some fields have heterogeneous types on the + different rows, this automatic inference may return unexpected + types. + If you need to save heterogeneous extra dtypes, we recommend + saving to FIF. + + Parameters + ---------- + fname : path-like + The filename. + + Returns + ------- + annot : instance of Annotations + The annotations. + """ + pd = _check_pandas_installed(strict=True) + df = pd.read_csv(fname, keep_default_na=False) + orig_time = df["onset"].values[0] + try: + float(orig_time) + warn( + "It looks like you have provided annotation onsets as floats. " + "These will be interpreted as MILLISECONDS. If that is not what " + "you want, save your CSV as a TXT file; the TXT reader accepts " + "onsets in seconds." + ) + except ValueError: + # remove nanoseconds for ISO8601 (microsecond) compliance + timestamp = pd.Timestamp(orig_time) + timespec = "microseconds" + if timestamp == pd.Timestamp(_handle_meas_date(0)).astimezone(None): + timespec = "auto" # use default timespec for `orig_time=None` + orig_time = timestamp.isoformat(sep=" ", timespec=timespec) + + onset_dt = pd.to_datetime(df["onset"]) + onset = (onset_dt - onset_dt[0]).dt.total_seconds() + duration = df["duration"].values.astype(float) + description = df["description"].values + ch_names = None + if "ch_names" in df.columns: + ch_names = [ + _safe_name_list(val, "read", "annotation channel name") + for val in df["ch_names"].values + ] + extra_columns = list( + df.columns.difference(["onset", "duration", "description", "ch_names"]) + ) + extras = None + if len(extra_columns) > 0: + extras = df[extra_columns].to_dict(orient="records") + return Annotations(onset, duration, description, orig_time, ch_names, extras=extras) + + +def _read_brainstorm_annotations(fname, orig_time=None): + """Read annotations from a Brainstorm events_ file. + + Parameters + ---------- + fname : path-like + The filename + orig_time : float | int | instance of datetime | array of int | None + A POSIX Timestamp, datetime or an array containing the timestamp as the + first element and microseconds as the second element. Determines the + starting time of annotation acquisition. If None (default), + starting time is determined from beginning of raw data acquisition. + In general, ``raw.info['meas_date']`` (or None) can be used for syncing + the annotations with raw data if their acquisition is started at the + same time. + + Returns + ------- + annot : instance of Annotations | None + The annotations. + """ + + def get_duration_from_times(t): + return t[1] - t[0] if t.shape[0] == 2 else np.zeros(len(t[0])) + + annot_data = loadmat(fname) + onsets, durations, descriptions = (list(), list(), list()) + for label, _, _, _, times, _, _ in annot_data["events"][0]: + onsets.append(times[0]) + durations.append(get_duration_from_times(times)) + n_annot = len(times[0]) + descriptions += [str(label[0])] * n_annot + + return Annotations( + onset=np.concatenate(onsets), + duration=np.concatenate(durations), + description=descriptions, + orig_time=orig_time, + ) + + +def _is_iso8601(candidate_str): + ISO8601 = r"^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}:\d{2}\.\d{6}$" + return re.compile(ISO8601).match(candidate_str) is not None + + +def _read_annotations_txt_parse_header(fname): + def is_orig_time(x): + return x.startswith("# orig_time :") + + def is_columns(x): + return x.startswith("# onset, duration, description") + + with open(fname) as fid: + header = list(takewhile(lambda x: x.startswith("#"), fid)) + + orig_values = [h[13:].strip() for h in header if is_orig_time(h)] + orig_values = [_handle_meas_date(orig) for orig in orig_values if _is_iso8601(orig)] + + columns = [[c.strip() for c in h[2:].split(",")] for h in header if is_columns(h)] + + return ( + None if not orig_values else orig_values[0], + (None if not columns else columns[0]), + len(header), + ) + + +def _read_annotations_txt(fname): + with warnings.catch_warnings(record=True): + warnings.simplefilter("ignore") + out = np.loadtxt(fname, delimiter=",", dtype=np.bytes_, unpack=True) + orig_time, columns, n_rows_header = _read_annotations_txt_parse_header(fname) + ch_names = extras = None + if len(out) == 0: + onset, duration, desc = [], [], [] + else: + if columns is None: + # No column names were present in the header + # We assume the first three columns are onset, duration, description + # And eventually a fourth column with ch_names + _check_option("text header", len(out), (3, 4)) + columns = ["onset", "duration", "description"] + ( + ["ch_names"] if len(out) == 4 else [] + ) + col_map = {col: i for i, col in enumerate(columns)} + if len(col_map) != len(columns): + raise ValueError( + "Duplicate column names found in header. Please check the file format." + ) + if missing := {"onset", "duration", "description"} - set(col_map.keys()): + raise ValueError( + f"Column(s) {missing} not found in header. " + "Please check the file format." + ) + _check_option("text header len", len(out), (len(columns),)) + onset = out[col_map["onset"]] + duration = out[col_map["duration"]] + desc = out[col_map["description"]] + if "ch_names" in col_map: + ch_names = out[col_map["ch_names"]] + extra_columns = set(col_map.keys()) - { + "onset", + "duration", + "description", + "ch_names", + } + if extra_columns: + pd = _check_pandas_installed(strict=False) + if pd: + df = pd.read_csv( + fname, + delimiter=",", + names=columns, + usecols=extra_columns, + skiprows=n_rows_header, + header=None, + keep_default_na=False, + ) + extras = df.to_dict(orient="records") + else: + warn( + "Extra fields found in the header but pandas is not installed. " + "Therefore the dtypes of the extra fields can not automatically " + "be inferred so they will be loaded as strings." + ) + extras = [ + { + col_name: out[col_map[col_name]][i].decode("UTF-8") + for col_name in extra_columns + } + for i in range(len(onset)) + ] + + onset = [float(o.decode()) for o in np.atleast_1d(onset)] + duration = [float(d.decode()) for d in np.atleast_1d(duration)] + desc = [str(d.decode()).strip() for d in np.atleast_1d(desc)] + if ch_names is not None: + ch_names = [ + _safe_name_list(ch.decode().strip(), "read", f"ch_names[{ci}]") + for ci, ch in enumerate(ch_names) + ] + + annotations = Annotations( + onset=onset, + duration=duration, + description=desc, + orig_time=orig_time, + ch_names=ch_names, + extras=extras, + ) + + return annotations + + +def _read_annotations_fif(fid, tree): + """Read annotations.""" + annot_data = dir_tree_find(tree, FIFF.FIFFB_MNE_ANNOTATIONS) + if len(annot_data) == 0: + annotations = None + else: + annot_data = annot_data[0] + orig_time = ch_names = extras = None + onset, duration, description = list(), list(), list() + for ent in annot_data["directory"]: + kind = ent.kind + pos = ent.pos + tag = read_tag(fid, pos) + if kind == FIFF.FIFF_MNE_BASELINE_MIN: + onset = tag.data + onset = list() if onset is None else onset + elif kind == FIFF.FIFF_MNE_BASELINE_MAX: + duration = tag.data + duration = list() if duration is None else duration - onset + elif kind == FIFF.FIFF_COMMENT: + description = _safe_name_list(tag.data, "read", "description") + elif kind == FIFF.FIFF_MEAS_DATE: + orig_time = tag.data + try: + orig_time = float(orig_time) # old way + except TypeError: + orig_time = tuple(orig_time) # new way + elif kind == FIFF.FIFF_MNE_EPOCHS_DROP_LOG: + ch_names = tuple(tuple(x) for x in json.loads(tag.data)) + elif kind == FIFF.FIFF_FREE_LIST: + extras = json.loads(tag.data) + assert len(onset) == len(duration) == len(description) + if extras is not None: + assert len(extras) == len(onset) + annotations = Annotations( + onset, duration, description, orig_time, ch_names, extras=extras + ) + return annotations + + +def _select_annotations_based_on_description(descriptions, event_id, regexp): + """Get a collection of descriptions and returns index of selected.""" + regexp_comp = re.compile(".*" if regexp is None else regexp) + + event_id_ = dict() + dropped = [] + # Iterate over the sorted descriptions so that the Counter mapping + # is slightly less arbitrary + for desc in sorted(descriptions): + if desc in event_id_: + continue + + if regexp_comp.match(desc) is None: + continue + + if isinstance(event_id, dict): + if desc in event_id: + event_id_[desc] = event_id[desc] + else: + continue + else: + trigger = event_id(desc) + if trigger is not None: + event_id_[desc] = trigger + else: + dropped.append(desc) + + event_sel = [ii for ii, kk in enumerate(descriptions) if kk in event_id_] + + if len(event_sel) == 0 and regexp is not None: + raise ValueError("Could not find any of the events you specified.") + + return event_sel, event_id_ + + +def _select_events_based_on_id(events, event_desc): + """Get a collection of events and returns index of selected.""" + event_desc_ = dict() + func = event_desc.get if isinstance(event_desc, dict) else event_desc + event_ids = events[np.unique(events[:, 2], return_index=True)[1], 2] + for e in event_ids: + trigger = func(e) + if trigger is not None: + event_desc_[e] = trigger + + event_sel = [ii for ii, e in enumerate(events) if e[2] in event_desc_] + + if len(event_sel) == 0: + raise ValueError("Could not find any of the events you specified.") + + return event_sel, event_desc_ + + +def _check_event_id(event_id, raw): + from .io import Raw, RawArray + from .io.brainvision.brainvision import ( + RawBrainVision, + _BVEventParser, + _check_bv_annot, + ) + + if event_id is None: + return _DefaultEventParser() + elif event_id == "auto": + if isinstance(raw, RawBrainVision): + return _BVEventParser() + elif isinstance(raw, Raw | RawArray) and _check_bv_annot( + raw.annotations.description + ): + logger.info("Non-RawBrainVision raw using branvision markers") + return _BVEventParser() + else: + return _DefaultEventParser() + elif callable(event_id) or isinstance(event_id, dict): + return event_id + else: + raise ValueError( + "Invalid type for event_id (should be None, str, " + f"dict or callable). Got {type(event_id)}." + ) + + +def _check_event_description(event_desc, events): + """Check event_id and convert to default format.""" + if event_desc is None: # convert to int to make typing-checks happy + event_desc = list(np.unique(events[:, 2])) + + if isinstance(event_desc, dict): + for val in event_desc.values(): + _validate_type(val, (str, None), "Event names") + elif isinstance(event_desc, Iterable): + event_desc = np.asarray(event_desc) + if event_desc.ndim != 1: + raise ValueError(f"event_desc must be 1D, got shape {event_desc.shape}") + event_desc = dict(zip(event_desc, map(str, event_desc))) + elif callable(event_desc): + pass + else: + raise ValueError( + "Invalid type for event_desc (should be None, list, " + f"1darray, dict or callable). Got {type(event_desc)}." + ) + + return event_desc + + +@verbose +def events_from_annotations( + raw, + event_id="auto", + regexp=r"^(?![Bb][Aa][Dd]|[Ee][Dd][Gg][Ee]).*$", + use_rounding=True, + chunk_duration=None, + tol=1e-8, + verbose=None, +): + """Get :term:`events` and ``event_id`` from an Annotations object. + + Parameters + ---------- + raw : instance of Raw + The raw data for which Annotations are defined. + event_id : dict | callable | None | ``'auto'`` + Can be: + + - **dict**: map descriptions (keys) to integer event codes (values). + Only the descriptions present will be mapped, others will be ignored. + - **callable**: must take a string input and return an integer event + code, or return ``None`` to ignore the event. + - **None**: Map descriptions to unique integer values based on their + ``sorted`` order. + - **'auto' (default)**: prefer a raw-format-specific parser: + + - Brainvision: map stimulus events to their integer part; response + events to integer part + 1000; optic events to integer part + 2000; + 'SyncStatus/Sync On' to 99998; 'New Segment/' to 99999; + all others like ``None`` with an offset of 10000. + - Other raw formats: Behaves like None. + + .. versionadded:: 0.18 + regexp : str | None + Regular expression used to filter the annotations whose + descriptions is a match. The default ignores descriptions beginning + ``'bad'`` or ``'edge'`` (case-insensitive). + + .. versionchanged:: 0.18 + Default ignores bad and edge descriptions. + use_rounding : bool + If True, use rounding (instead of truncation) when converting + times to indices. This can help avoid non-unique indices. + chunk_duration : float | None + Chunk duration in seconds. If ``chunk_duration`` is set to None + (default), generated events correspond to the annotation onsets. + If not, :func:`mne.events_from_annotations` returns as many events as + they fit within the annotation duration spaced according to + ``chunk_duration``. As a consequence annotations with duration shorter + than ``chunk_duration`` will not contribute events. + tol : float + The tolerance used to check if a chunk fits within an annotation when + ``chunk_duration`` is not ``None``. If the duration from a computed + chunk onset to the end of the annotation is smaller than + ``chunk_duration`` minus ``tol``, the onset will be discarded. + %(verbose)s + + Returns + ------- + %(events)s + event_id : dict + The event_id variable that can be passed to :class:`~mne.Epochs`. + + See Also + -------- + mne.annotations_from_events + + Notes + ----- + For data formats that store integer events as strings (e.g., NeuroScan + ``.cnt`` files), passing the Python built-in function :class:`int` as the + ``event_id`` parameter will do what most users probably want in those + circumstances: return an ``event_id`` dictionary that maps event ``'1'`` to + integer event code ``1``, ``'2'`` to ``2``, etc. + """ + if len(raw.annotations) == 0: + event_id = dict() if not isinstance(event_id, dict) else event_id + return np.empty((0, 3), dtype=int), event_id + + annotations = raw.annotations + + event_id = _check_event_id(event_id, raw) + + event_sel, event_id_ = _select_annotations_based_on_description( + annotations.description, event_id=event_id, regexp=regexp + ) + + if chunk_duration is None: + inds = raw.time_as_index( + annotations.onset, use_rounding=use_rounding, origin=annotations.orig_time + ) + if annotations.orig_time is not None: + inds += raw.first_samp + values = [event_id_[kk] for kk in annotations.description[event_sel]] + inds = inds[event_sel] + else: + inds = values = np.array([]).astype(int) + for annot in annotations[event_sel]: + annot_offset = annot["onset"] + annot["duration"] + _onsets = np.arange(annot["onset"], annot_offset, chunk_duration) + good_events = annot_offset - _onsets >= chunk_duration - tol + if good_events.any(): + _onsets = _onsets[good_events] + _inds = raw.time_as_index( + _onsets, use_rounding=use_rounding, origin=annotations.orig_time + ) + _inds += raw.first_samp + inds = np.append(inds, _inds) + _values = np.full( + shape=len(_inds), + fill_value=event_id_[annot["description"]], + dtype=int, + ) + values = np.append(values, _values) + + events = np.c_[inds, np.zeros(len(inds)), values].astype(int) + + logger.info(f"Used Annotations descriptions: {list(event_id_.keys())}") + + return events, event_id_ + + +@verbose +def annotations_from_events( + events, sfreq, event_desc=None, first_samp=0, orig_time=None, verbose=None +): + """Convert an event array to an Annotations object. + + Parameters + ---------- + events : ndarray, shape (n_events, 3) + The events. + sfreq : float + Sampling frequency. + event_desc : dict | array-like | callable | None + Events description. Can be: + + - **dict**: map integer event codes (keys) to descriptions (values). + Only the descriptions present will be mapped, others will be ignored. + - **array-like**: list, or 1d array of integers event codes to include. + Only the event codes present will be mapped, others will be ignored. + Event codes will be passed as string descriptions. + - **callable**: must take a integer event code as input and return a + string description or None to ignore it. + - **None**: Use integer event codes as descriptions. + first_samp : int + The first data sample (default=0). See :attr:`mne.io.Raw.first_samp` + docstring. + orig_time : float | str | datetime | tuple of int | None + Determines the starting time of annotation acquisition. If None + (default), starting time is determined from beginning of raw data + acquisition. For details, see :meth:`mne.Annotations` docstring. + %(verbose)s + + Returns + ------- + annot : instance of Annotations + The annotations. + + See Also + -------- + mne.events_from_annotations + + Notes + ----- + Annotations returned by this function will all have zero (null) duration. + + Creating events from annotations via the function + `mne.events_from_annotations` takes in event mappings with + key→value pairs as description→ID, whereas `mne.annotations_from_events` + takes in event mappings with key→value pairs as ID→description. + If you need to use these together, you can invert the mapping by doing:: + + event_desc = {v: k for k, v in event_id.items()} + """ + event_desc = _check_event_description(event_desc, events) + event_sel, event_desc_ = _select_events_based_on_id(events, event_desc) + events_sel = events[event_sel] + onsets = (events_sel[:, 0] - first_samp) / sfreq + descriptions = [event_desc_[e[2]] for e in events_sel] + durations = np.zeros(len(events_sel)) # dummy durations + + # Create annotations + annots = Annotations( + onset=onsets, duration=durations, description=descriptions, orig_time=orig_time + ) + + return annots + + +def _adjust_onset_meas_date(annot, raw): + """Adjust the annotation onsets based on raw meas_date.""" + # If there is a non-None meas date, then the onset should take into + # account the first_samp / first_time. + if raw.info["meas_date"] is not None: + annot.onset += raw.first_time + + +def count_annotations(annotations): + """Count annotations. + + Parameters + ---------- + annotations : mne.Annotations + The annotations instance. + + Returns + ------- + counts : dict + A dictionary containing unique annotation descriptions as keys with their + counts as values. + + Examples + -------- + >>> annotations = mne.Annotations([0, 1, 2], [1, 2, 1], ["T0", "T1", "T0"]) + >>> count_annotations(annotations) + {'T0': 2, 'T1': 1} + """ + field = "hed_string" if isinstance(annotations, HEDAnnotations) else "description" + types, counts = np.unique(getattr(annotations, field), return_counts=True) + return {str(t): int(count) for t, count in zip(types, counts)} diff --git a/mne-python/source/mne/baseline.py b/mne-python/source/mne/baseline.py new file mode 100644 index 0000000000000000000000000000000000000000..4e73ed0ce95d13866652ca5ed7331c9810ceb876 --- /dev/null +++ b/mne-python/source/mne/baseline.py @@ -0,0 +1,224 @@ +"""Utility functions to baseline-correct data.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from .utils import _check_option, _validate_type, logger, verbose + + +def _log_rescale(baseline, mode="mean"): + """Log the rescaling method.""" + if baseline is not None: + _check_option( + "mode", + mode, + ["logratio", "ratio", "zscore", "mean", "percent", "zlogratio"], + ) + msg = f"Applying baseline correction (mode: {mode})" + else: + msg = "No baseline correction applied" + return msg + + +@verbose +def rescale(data, times, baseline, mode="mean", copy=True, picks=None, verbose=None): + """Rescale (baseline correct) data. + + Parameters + ---------- + data : array + It can be of any shape. The only constraint is that the last + dimension should be time. + times : 1D array + Time instants is seconds. + %(baseline_rescale)s + mode : 'mean' | 'ratio' | 'logratio' | 'percent' | 'zscore' | 'zlogratio' + Perform baseline correction by + + - subtracting the mean of baseline values ('mean') + - dividing by the mean of baseline values ('ratio') + - dividing by the mean of baseline values and taking the log + ('logratio') + - subtracting the mean of baseline values followed by dividing by + the mean of baseline values ('percent') + - subtracting the mean of baseline values and dividing by the + standard deviation of baseline values ('zscore') + - dividing by the mean of baseline values, taking the log, and + dividing by the standard deviation of log baseline values + ('zlogratio') + + copy : bool + Whether to return a new instance or modify in place. + picks : list of int | None + Data to process along the axis=-2 (None, default, processes all). + %(verbose)s + + Returns + ------- + data_scaled: array + Array of same shape as data after rescaling. + """ + if copy: + data = data.copy() + if verbose is not False: + msg = _log_rescale(baseline, mode) + logger.info(msg) + if baseline is None or data.shape[-1] == 0: + return data + + bmin, bmax = baseline + if bmin is None: + imin = 0 + else: + imin = np.where(times >= bmin)[0] + if len(imin) == 0: + raise ValueError( + f"bmin is too large ({bmin}), it exceeds the largest time value" + ) + imin = int(imin[0]) + if bmax is None: + imax = len(times) + else: + imax = np.where(times <= bmax)[0] + if len(imax) == 0: + raise ValueError( + f"bmax is too small ({bmax}), it is smaller than the smallest time " + "value" + ) + imax = int(imax[-1]) + 1 + if imin >= imax: + raise ValueError( + f"Bad rescaling slice ({imin}:{imax}) from time values {bmin}, {bmax}" + ) + + # technically this is inefficient when `picks` is given, but assuming + # that we generally pick most channels for rescaling, it's not so bad + mean = np.mean(data[..., imin:imax], axis=-1, keepdims=True) + + if mode == "mean": + + def fun(d, m): + d -= m + + elif mode == "ratio": + + def fun(d, m): + d /= m + + elif mode == "logratio": + + def fun(d, m): + d /= m + np.log10(d, out=d) + + elif mode == "percent": + + def fun(d, m): + d -= m + d /= m + + elif mode == "zscore": + + def fun(d, m): + d -= m + d /= np.std(d[..., imin:imax], axis=-1, keepdims=True) + + elif mode == "zlogratio": + + def fun(d, m): + d /= m + np.log10(d, out=d) + d /= np.std(d[..., imin:imax], axis=-1, keepdims=True) + + if picks is None: + fun(data, mean) + else: + for pi in picks: + fun(data[..., pi, :], mean[..., pi, :]) + return data + + +def _check_baseline(baseline, times, sfreq, on_baseline_outside_data="raise"): + """Check if the baseline is valid and adjust it if requested. + + ``None`` values inside ``baseline`` will be replaced with ``times[0]`` and + ``times[-1]``. + + Parameters + ---------- + baseline : array-like, shape (2,) | None + Beginning and end of the baseline period, in seconds. If ``None``, + assume no baseline and return immediately. + times : array + The time points. + sfreq : float + The sampling rate. + on_baseline_outside_data : 'raise' | 'info' | 'adjust' + What to do if the baseline period exceeds the data. + If ``'raise'``, raise an exception (default). + If ``'info'``, log an info message. + If ``'adjust'``, adjust the baseline such that it is within the data range. + + Returns + ------- + (baseline_tmin, baseline_tmax) | None + The baseline with ``None`` values replaced with times, and with adjusted times + if ``on_baseline_outside_data='adjust'``; or ``None``, if ``baseline`` is + ``None``. + """ + if baseline is None: + return None + + _validate_type(baseline, "array-like") + baseline = tuple(baseline) + + if len(baseline) != 2: + raise ValueError( + f"baseline must have exactly two elements (got {len(baseline)})." + ) + + tmin, tmax = times[0], times[-1] + tstep = 1.0 / float(sfreq) + + # check default value of baseline and `tmin=0` + if baseline == (None, 0) and tmin == 0: + raise ValueError( + "Baseline interval is only one sample. Use `baseline=(0, 0)` if this is " + "desired." + ) + + baseline_tmin, baseline_tmax = baseline + + if baseline_tmin is None: + baseline_tmin = tmin + baseline_tmin = float(baseline_tmin) + + if baseline_tmax is None: + baseline_tmax = tmax + baseline_tmax = float(baseline_tmax) + + if baseline_tmin > baseline_tmax: + raise ValueError( + f"Baseline min ({baseline_tmin}) must be less than baseline max (" + f"{baseline_tmax})" + ) + + if (baseline_tmin < tmin - tstep) or (baseline_tmax > tmax + tstep): + msg = ( + f"Baseline interval [{baseline_tmin}, {baseline_tmax}] s is outside of " + f"epochs data [{tmin}, {tmax}] s. Epochs were probably cropped." + ) + if on_baseline_outside_data == "raise": + raise ValueError(msg) + elif on_baseline_outside_data == "info": + logger.info(msg) + elif on_baseline_outside_data == "adjust": + if baseline_tmin < tmin - tstep: + baseline_tmin = tmin + if baseline_tmax > tmax + tstep: + baseline_tmax = tmax + + return baseline_tmin, baseline_tmax diff --git a/mne-python/source/mne/beamformer/__init__.py b/mne-python/source/mne/beamformer/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..16a5b363eb63ee05fa5fb7903d2b87332698e1dc --- /dev/null +++ b/mne-python/source/mne/beamformer/__init__.py @@ -0,0 +1,8 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Beamformers for source localization.""" +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/beamformer/__init__.pyi b/mne-python/source/mne/beamformer/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..f7d6eb9d20315ba588d18c21a3a0b9bd0d154a6a --- /dev/null +++ b/mne-python/source/mne/beamformer/__init__.pyi @@ -0,0 +1,34 @@ +__all__ = [ + "Beamformer", + "apply_dics", + "apply_dics_csd", + "apply_dics_epochs", + "apply_dics_tfr_epochs", + "apply_lcmv", + "apply_lcmv_cov", + "apply_lcmv_epochs", + "apply_lcmv_raw", + "make_dics", + "make_lcmv", + "make_lcmv_resolution_matrix", + "rap_music", + "read_beamformer", + "trap_music", +] +from ._compute_beamformer import Beamformer, read_beamformer +from ._dics import ( + apply_dics, + apply_dics_csd, + apply_dics_epochs, + apply_dics_tfr_epochs, + make_dics, +) +from ._lcmv import ( + apply_lcmv, + apply_lcmv_cov, + apply_lcmv_epochs, + apply_lcmv_raw, + make_lcmv, +) +from ._rap_music import rap_music, trap_music +from .resolution_matrix import make_lcmv_resolution_matrix diff --git a/mne-python/source/mne/beamformer/_compute_beamformer.py b/mne-python/source/mne/beamformer/_compute_beamformer.py new file mode 100644 index 0000000000000000000000000000000000000000..16bedc2c317d861e1a8b9c999350662ae0bd727c --- /dev/null +++ b/mne-python/source/mne/beamformer/_compute_beamformer.py @@ -0,0 +1,603 @@ +"""Functions shared between different beamformer types.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from copy import deepcopy + +import numpy as np + +from .._fiff.proj import Projection, make_projector +from ..cov import Covariance, make_ad_hoc_cov +from ..forward.forward import _restrict_forward_to_src_sel, is_fixed_orient +from ..minimum_norm.inverse import _get_vertno, _prepare_forward +from ..source_space._source_space import label_src_vertno_sel +from ..time_frequency.csd import CrossSpectralDensity +from ..utils import ( + _check_option, + _check_src_normal, + _import_h5io_funcs, + _pl, + _reg_pinv, + _sym_mat_pow, + check_fname, + logger, + verbose, + warn, +) + + +def _check_proj_match(proj, filters): + """Check whether SSP projections in data and spatial filter match.""" + proj_data, _, _ = make_projector(proj, filters["ch_names"]) + if not np.allclose( + proj_data, filters["proj"], atol=np.finfo(float).eps, rtol=1e-13 + ): + raise ValueError( + "The SSP projections present in the data " + "do not match the projections used when " + "calculating the spatial filter." + ) + + +def _check_src_type(filters): + """Check whether src_type is in filters and set custom warning.""" + if "src_type" not in filters: + filters["src_type"] = None + warn_text = ( + "The spatial filter does not contain src_type and a robust " + "guess of src_type is not possible without src. Consider " + "recomputing the filter." + ) + return filters, warn_text + + +def _prepare_beamformer_input( + info, + forward, + label=None, + pick_ori=None, + noise_cov=None, + rank=None, + pca=False, + loose=None, + combine_xyz="fro", + exp=None, + limit=None, + allow_fixed_depth=True, + limit_depth_chs=False, +): + """Input preparation common for LCMV, DICS, and RAP-MUSIC.""" + _check_option("pick_ori", pick_ori, ("normal", "max-power", "vector", None)) + + # Restrict forward solution to selected vertices + if label is not None: + _, src_sel = label_src_vertno_sel(label, forward["src"]) + forward = _restrict_forward_to_src_sel(forward, src_sel) + + if loose is None: + loose = 0.0 if is_fixed_orient(forward) else 1.0 + # TODO: Deduplicate with _check_one_ch_type, should not be necessary + # (DICS hits this code path, LCMV does not) + if noise_cov is None: + noise_cov = make_ad_hoc_cov(info, std=1.0) + ( + forward, + info_picked, + gain, + _, + orient_prior, + _, + trace_GRGT, + noise_cov, + whitener, + ) = _prepare_forward( + forward, + info, + noise_cov, + "auto", + loose, + rank=rank, + pca=pca, + use_cps=True, + exp=exp, + limit_depth_chs=limit_depth_chs, + combine_xyz=combine_xyz, + limit=limit, + allow_fixed_depth=allow_fixed_depth, + ) + is_free_ori = not is_fixed_orient(forward) # could have been changed + nn = forward["source_nn"] + if is_free_ori: # take Z coordinate + nn = nn[2::3] + nn = nn.copy() + vertno = _get_vertno(forward["src"]) + if forward["surf_ori"]: + nn[...] = [0, 0, 1] # align to local +Z coordinate + if pick_ori is not None and not is_free_ori: + raise ValueError( + f"Normal or max-power orientation (got {pick_ori!r}) can only be picked " + "when a forward operator with free orientation is used." + ) + if pick_ori == "normal" and not forward["surf_ori"]: + raise ValueError( + "Normal orientation can only be picked when a forward operator oriented in " + "surface coordinates is used." + ) + _check_src_normal(pick_ori, forward["src"]) + del forward, info + + # Undo the scaling that MNE prefers + scale = np.sqrt((noise_cov["eig"] > 0).sum() / trace_GRGT) + gain /= scale + if orient_prior is not None: + orient_std = np.sqrt(orient_prior) + else: + orient_std = np.ones(gain.shape[1]) + + # Get the projector + proj, _, _ = make_projector(info_picked["projs"], info_picked["ch_names"]) + return (is_free_ori, info_picked, proj, vertno, gain, whitener, nn, orient_std) + + +def _reduce_leadfield_rank(G): + """Reduce the rank of the leadfield.""" + # decompose lead field + u, s, v = np.linalg.svd(G, full_matrices=False) + + # backproject, omitting one direction (equivalent to setting the smallest + # singular value to zero) + G = np.matmul(u[:, :, :-1], s[:, :-1, np.newaxis] * v[:, :-1, :]) + + return G + + +def _sym_inv_sm(x, reduce_rank, inversion, sk): + """Symmetric inversion with single- or matrix-style inversion.""" + if x.shape[1:] == (1, 1): + with np.errstate(divide="ignore", invalid="ignore"): + x_inv = 1.0 / x + x_inv[~np.isfinite(x_inv)] = 1.0 + else: + assert x.shape[1:] == (3, 3) + if inversion == "matrix": + x_inv = _sym_mat_pow(x, -1, reduce_rank=reduce_rank) + # Reapply source covariance after inversion + x_inv *= sk[:, :, np.newaxis] + x_inv *= sk[:, np.newaxis, :] + else: + # Invert for each dipole separately using plain division + diags = np.diagonal(x, axis1=1, axis2=2) + assert not reduce_rank # guaranteed earlier + with np.errstate(divide="ignore"): + diags = 1.0 / diags + # set the diagonal of each 3x3 + x_inv = np.zeros_like(x) + for k in range(x.shape[0]): + this = diags[k] + # Reapply source covariance after inversion + this *= sk[k] * sk[k] + x_inv[k].flat[::4] = this + return x_inv + + +def _compute_beamformer( + G, + Cm, + reg, + n_orient, + weight_norm, + pick_ori, + reduce_rank, + rank, + inversion, + nn, + orient_std, + whitener, +): + """Compute a spatial beamformer filter (LCMV or DICS). + + For more detailed information on the parameters, see the docstrings of + `make_lcmv` and `make_dics`. + + Parameters + ---------- + G : ndarray, shape (n_dipoles, n_channels) + The leadfield. + Cm : ndarray, shape (n_channels, n_channels) + The data covariance matrix. + reg : float + Regularization parameter. + n_orient : int + Number of dipole orientations defined at each source point + weight_norm : None | 'unit-noise-gain' | 'nai' + The weight normalization scheme to use. + pick_ori : None | 'normal' | 'max-power' + The source orientation to compute the beamformer in. + reduce_rank : bool + Whether to reduce the rank by one during computation of the filter. + rank : dict | None | 'full' | 'info' + See compute_rank. + inversion : 'matrix' | 'single' + The inversion scheme to compute the weights. + nn : ndarray, shape (n_dipoles, 3) + The source normals. + orient_std : ndarray, shape (n_dipoles,) + The std of the orientation prior used in weighting the lead fields. + whitener : ndarray, shape (n_channels, n_channels) + The whitener. + + Returns + ------- + W : ndarray, shape (n_dipoles, n_channels) + The beamformer filter weights. + """ + _check_option( + "weight_norm", + weight_norm, + ["unit-noise-gain-invariant", "unit-noise-gain", "nai", None], + ) + + # Whiten the data covariance + Cm = whitener @ Cm @ whitener.T.conj() + # Restore to properly Hermitian as large whitening coefs can have bad + # rounding error + Cm[:] = (Cm + Cm.T.conj()) / 2.0 + + assert Cm.shape == (G.shape[0],) * 2 + s, _ = np.linalg.eigh(Cm) + if not (s >= -s.max() * 1e-7).all(): + # This shouldn't ever happen, but just in case + warn( + "data covariance does not appear to be positive semidefinite, " + "results will likely be incorrect" + ) + # Tikhonov regularization using reg parameter to control for + # trade-off between spatial resolution and noise sensitivity + # eq. 25 in Gross and Ioannides, 1999 Phys. Med. Biol. 44 2081 + Cm_inv, loading_factor, rank = _reg_pinv(Cm, reg, rank) + + assert orient_std.shape == (G.shape[1],) + n_sources = G.shape[1] // n_orient + assert nn.shape == (n_sources, 3) + + logger.info(f"Computing beamformer filters for {n_sources} source{_pl(n_sources)}") + n_channels = G.shape[0] + assert n_orient in (3, 1) + Gk = np.reshape(G.T, (n_sources, n_orient, n_channels)).transpose(0, 2, 1) + assert Gk.shape == (n_sources, n_channels, n_orient) + sk = np.reshape(orient_std, (n_sources, n_orient)) + del G, orient_std + + _check_option("reduce_rank", reduce_rank, (True, False)) + + # inversion of the denominator + _check_option("inversion", inversion, ("matrix", "single")) + if ( + inversion == "single" + and n_orient > 1 + and pick_ori == "vector" + and weight_norm == "unit-noise-gain-invariant" + ): + raise ValueError( + 'Cannot use pick_ori="vector" with inversion="single" and ' + 'weight_norm="unit-noise-gain-invariant"' + ) + if reduce_rank and inversion == "single": + raise ValueError( + 'reduce_rank cannot be used with inversion="single"; ' + 'consider using inversion="matrix" if you have a ' + "rank-deficient forward model (i.e., from a sphere " + "model with MEG channels), otherwise consider using " + "reduce_rank=False" + ) + if n_orient > 1: + _, Gk_s, _ = np.linalg.svd(Gk, full_matrices=False) + assert Gk_s.shape == (n_sources, n_orient) + if not reduce_rank and (Gk_s[:, 0] > 1e6 * Gk_s[:, 2]).any(): + raise ValueError( + "Singular matrix detected when estimating spatial filters. " + "Consider reducing the rank of the forward operator by using " + "reduce_rank=True." + ) + del Gk_s + + # + # 1. Reduce rank of the lead field + # + if reduce_rank: + Gk = _reduce_leadfield_rank(Gk) + + def _compute_bf_terms(Gk, Cm_inv): + bf_numer = np.matmul(Gk.swapaxes(-2, -1).conj(), Cm_inv) + bf_denom = np.matmul(bf_numer, Gk) + return bf_numer, bf_denom + + # + # 2. Reorient lead field in direction of max power or normal + # + if pick_ori == "max-power": + assert n_orient == 3 + _, bf_denom = _compute_bf_terms(Gk, Cm_inv) + if weight_norm is None: + ori_numer = np.eye(n_orient)[np.newaxis] + ori_denom = bf_denom + else: + # compute power, cf Sekihara & Nagarajan 2008, eq. 4.47 + ori_numer = bf_denom + # Cm_inv should be Hermitian so no need for .T.conj() + ori_denom = np.matmul( + np.matmul(Gk.swapaxes(-2, -1).conj(), Cm_inv @ Cm_inv), Gk + ) + ori_denom_inv = _sym_inv_sm(ori_denom, reduce_rank, inversion, sk) + ori_pick = np.matmul(ori_denom_inv, ori_numer) + assert ori_pick.shape == (n_sources, n_orient, n_orient) + + # pick eigenvector that corresponds to maximum eigenvalue: + eig_vals, eig_vecs = np.linalg.eig(ori_pick.real) # not Hermitian! + # sort eigenvectors by eigenvalues for picking: + order = np.argsort(np.abs(eig_vals), axis=-1) + # eig_vals = np.take_along_axis(eig_vals, order, axis=-1) + max_power_ori = eig_vecs[np.arange(len(eig_vecs)), :, order[:, -1]] + assert max_power_ori.shape == (n_sources, n_orient) + + # set the (otherwise arbitrary) sign to match the normal + signs = np.sign(np.sum(max_power_ori * nn, axis=1, keepdims=True)) + signs[signs == 0] = 1.0 + max_power_ori *= signs + + # Compute the lead field for the optimal orientation, + # and adjust numer/denom + Gk = np.matmul(Gk, max_power_ori[..., np.newaxis]) + n_orient = 1 + else: + max_power_ori = None + if pick_ori == "normal": + Gk = Gk[..., 2:3] + n_orient = 1 + + # + # 3. Compute numerator and denominator of beamformer formula (unit-gain) + # + + bf_numer, bf_denom = _compute_bf_terms(Gk, Cm_inv) + assert bf_denom.shape == (n_sources,) + (n_orient,) * 2 + assert bf_numer.shape == (n_sources, n_orient, n_channels) + del Gk # lead field has been adjusted and should not be used anymore + + # + # 4. Invert the denominator + # + + # Here W is W_ug, i.e.: + # G.T @ Cm_inv / (G.T @ Cm_inv @ G) + bf_denom_inv = _sym_inv_sm(bf_denom, reduce_rank, inversion, sk) + assert bf_denom_inv.shape == (n_sources, n_orient, n_orient) + W = np.matmul(bf_denom_inv, bf_numer) + assert W.shape == (n_sources, n_orient, n_channels) + del bf_denom_inv, sk + + # + # 5. Re-scale filter weights according to the selected weight_norm + # + + # Weight normalization is done by computing, for each source:: + # + # W_ung = W_ug / sqrt(W_ug @ W_ug.T) + # + # with W_ung referring to the unit-noise-gain (weight normalized) filter + # and W_ug referring to the above-calculated unit-gain filter stored in W. + + if weight_norm is not None: + # Three different ways to calculate the normalization factors here. + # Only matters when in vector mode, as otherwise n_orient == 1 and + # they are all equivalent. + # + # In MNE < 0.21, we just used the Frobenius matrix norm: + # + # noise_norm = np.linalg.norm(W, axis=(1, 2), keepdims=True) + # assert noise_norm.shape == (n_sources, 1, 1) + # W /= noise_norm + # + # Sekihara 2008 says to use sqrt(diag(W_ug @ W_ug.T)), which is not + # rotation invariant: + if weight_norm in ("unit-noise-gain", "nai"): + noise_norm = np.matmul(W, W.swapaxes(-2, -1).conj()).real + noise_norm = np.reshape( # np.diag operation over last two axes + noise_norm, (n_sources, -1, 1) + )[:, :: n_orient + 1] + np.sqrt(noise_norm, out=noise_norm) + noise_norm[noise_norm == 0] = np.inf + assert noise_norm.shape == (n_sources, n_orient, 1) + W /= noise_norm + else: + assert weight_norm == "unit-noise-gain-invariant" + # Here we use sqrtm. The shortcut: + # + # use = W + # + # ... does not match the direct route (it is rotated!), so we'll + # use the direct one to match FieldTrip: + use = bf_numer + inner = np.matmul(use, use.swapaxes(-2, -1).conj()) + W = np.matmul(_sym_mat_pow(inner, -0.5), use) + noise_norm = 1.0 + + if weight_norm == "nai": + # Estimate noise level based on covariance matrix, taking the + # first eigenvalue that falls outside the signal subspace or the + # loading factor used during regularization, whichever is largest. + if rank > len(Cm): + # Covariance matrix is full rank, no noise subspace! + # Use the loading factor as noise ceiling. + if loading_factor == 0: + raise RuntimeError( + "Cannot compute noise subspace with a full-rank " + "covariance matrix and no regularization. Try " + "manually specifying the rank of the covariance " + "matrix or using regularization." + ) + noise = loading_factor + else: + noise, _ = np.linalg.eigh(Cm) + noise = noise[-rank] + noise = max(noise, loading_factor) + W /= np.sqrt(noise) + + W = W.reshape(n_sources * n_orient, n_channels) + logger.info("Filter computation complete") + return W, max_power_ori + + +def _compute_power(Cm, W, n_orient): + """Use beamformer filters to compute source power. + + Parameters + ---------- + Cm : ndarray, shape (n_channels, n_channels) + Data covariance matrix or CSD matrix. + W : ndarray, shape (nvertices*norient, nchannels) + Beamformer weights. + + Returns + ------- + power : ndarray, shape (nvertices,) + Source power. + """ + n_sources = W.shape[0] // n_orient + + Wk = W.reshape(n_sources, n_orient, W.shape[1]) + source_power = np.trace( + (Wk @ Cm @ Wk.conj().transpose(0, 2, 1)).real, axis1=1, axis2=2 + ) + + return source_power + + +class Beamformer(dict): + """A computed beamformer. + + Notes + ----- + .. versionadded:: 0.17 + """ + + def copy(self): + """Copy the beamformer. + + Returns + ------- + beamformer : instance of Beamformer + A deep copy of the beamformer. + """ + return deepcopy(self) + + def __repr__(self): # noqa: D105 + n_verts = sum(len(v) for v in self["vertices"]) + n_channels = len(self["ch_names"]) + if self["subject"] is None: + subject = "unknown" + else: + subject = f'"{self["subject"]}"' + out = " 1: + logger.info( + " computing DICS spatial filter at " + f"{round(freq, 2)} Hz ({i + 1}/{n_freqs})" + ) + + Cm = csd.get_data(index=i) + + # XXX: Weird that real_filter happens *before* whitening, which could + # make things complex again...? + if real_filter: + Cm = Cm.real + + # compute spatial filter + n_orient = 3 if is_free_ori else 1 + W, max_power_ori = _compute_beamformer( + G, + Cm, + reg, + n_orient, + weight_norm, + pick_ori, + reduce_rank, + rank=csd_int_rank[i], + inversion=inversion, + nn=nn, + orient_std=orient_std, + whitener=whitener, + ) + Ws.append(W) + max_oris.append(max_power_ori) + + Ws = np.array(Ws) + if pick_ori == "max-power": + max_oris = np.array(max_oris) + else: + max_oris = None + + src_type = _get_src_type(forward["src"], vertices) + subject = _subject_from_forward(forward) + is_free_ori = is_free_ori if pick_ori in [None, "vector"] else False + n_sources = np.sum([len(v) for v in vertices]) + + filters = Beamformer( + kind="DICS", + weights=Ws, + csd=csd, + ch_names=ch_names, + proj=proj, + vertices=vertices, + n_sources=n_sources, + subject=subject, + pick_ori=pick_ori, + inversion=inversion, + weight_norm=weight_norm, + src_type=src_type, + source_nn=forward["source_nn"].copy(), + is_free_ori=is_free_ori, + whitener=whitener, + max_power_ori=max_oris, + ) + + return filters + + +def _prepare_noise_csd(csd, noise_csd, real_filter): + if noise_csd is not None: + csd, noise_csd = equalize_channels([csd, noise_csd]) + # Use the same noise CSD for all frequencies + if len(noise_csd.frequencies) > 1: + noise_csd = noise_csd.mean() + noise_csd = noise_csd.get_data(as_cov=True) + if real_filter: + noise_csd["data"] = noise_csd["data"].real + return csd, noise_csd + + +def _apply_dics(data, filters, info, tmin, tfr=False): + """Apply DICS spatial filter to data for source reconstruction.""" + if isinstance(data, np.ndarray) and data.ndim == (2 + tfr): + data = [data] + one_epoch = True + else: + one_epoch = False + + Ws = filters["weights"] + one_freq = len(Ws) == 1 + + subject = filters["subject"] + # compatibility with 0.16, add src_type as None if not present: + filters, warn_text = _check_src_type(filters) + + for i, M in enumerate(data): + if not one_epoch: + logger.info(f"Processing epoch : {i + 1}") + + # Apply SSPs + if not tfr: # save computation, only compute once + M_w = _proj_whiten_data(M, info["projs"], filters) + + stcs = [] + for j, W in enumerate(Ws): + if tfr: # must compute for each frequency + M_w = _proj_whiten_data(M[:, j], info["projs"], filters) + + # project to source space using beamformer weights + sol = np.dot(W, M_w) + + if filters["is_free_ori"] and filters["pick_ori"] != "vector": + logger.info("combining the current components...") + sol = combine_xyz(sol) + + tstep = 1.0 / info["sfreq"] + + stcs.append( + _make_stc( + sol, + vertices=filters["vertices"], + src_type=filters["src_type"], + tmin=tmin, + tstep=tstep, + subject=subject, + vector=(filters["pick_ori"] == "vector"), + source_nn=filters["source_nn"], + warn_text=warn_text, + ) + ) + if one_freq: + yield stcs[0] + else: + yield stcs + + logger.info("[done]") + + +@verbose +def apply_dics(evoked, filters, verbose=None): + """Apply Dynamic Imaging of Coherent Sources (DICS) beamformer weights. + + Apply Dynamic Imaging of Coherent Sources (DICS) beamformer weights + on evoked data. + + .. warning:: The result of this function is meant as an intermediate step + for further processing (such as computing connectivity). If + you are interested in estimating source time courses, use an + LCMV beamformer (:func:`make_lcmv`, :func:`apply_lcmv`) + instead. If you are interested in estimating spectral power at + the source level, use :func:`apply_dics_csd`. + .. warning:: This implementation has not been heavily tested so please + report any issues or suggestions. + + Parameters + ---------- + evoked : Evoked + Evoked data to apply the DICS beamformer weights to. + filters : instance of Beamformer + DICS spatial filter (beamformer weights) + Filter weights returned from :func:`make_dics`. + %(verbose)s + + Returns + ------- + stc : SourceEstimate | VolSourceEstimate | list + Source time courses. If the DICS beamformer has been computed for more + than one frequency, a list is returned containing for each frequency + the corresponding time courses. + + See Also + -------- + apply_dics_epochs + apply_dics_tfr_epochs + apply_dics_csd + """ # noqa: E501 + _check_reference(evoked) + + info = evoked.info + data = evoked.data + tmin = evoked.times[0] + + sel = _check_channels_spatial_filter(evoked.ch_names, filters) + data = data[sel] + + stc = _apply_dics(data=data, filters=filters, info=info, tmin=tmin) + + return next(stc) + + +@verbose +def apply_dics_epochs(epochs, filters, return_generator=False, verbose=None): + """Apply Dynamic Imaging of Coherent Sources (DICS) beamformer weights. + + Apply Dynamic Imaging of Coherent Sources (DICS) beamformer weights + on single trial data. + + .. warning:: The result of this function is meant as an intermediate step + for further processing (such as computing connectivity). If + you are interested in estimating source time courses, use an + LCMV beamformer (:func:`make_lcmv`, :func:`apply_lcmv`) + instead. If you are interested in estimating spectral power at + the source level, use :func:`apply_dics_csd`. + .. warning:: This implementation has not been heavily tested so please + report any issue or suggestions. + + Parameters + ---------- + epochs : Epochs + Single trial epochs. + filters : instance of Beamformer + DICS spatial filter (beamformer weights) + Filter weights returned from :func:`make_dics`. The DICS filters must + have been computed for a single frequency only. + return_generator : bool + Return a generator object instead of a list. This allows iterating + over the stcs without having to keep them all in memory. + %(verbose)s + + Returns + ------- + stc: list | generator of (SourceEstimate | VolSourceEstimate) + The source estimates for all epochs. + + See Also + -------- + apply_dics + apply_dics_tfr_epochs + apply_dics_csd + """ + _check_reference(epochs) + + if len(filters["weights"]) > 1: + raise ValueError( + "This function only works on DICS beamformer weights that have " + "been computed for a single frequency. When calling make_dics(), " + "make sure to use a CSD object with only a single frequency (or " + "frequency-bin) defined." + ) + + info = epochs.info + tmin = epochs.times[0] + + sel = _check_channels_spatial_filter(epochs.ch_names, filters) + data = epochs.get_data(sel) + + stcs = _apply_dics(data=data, filters=filters, info=info, tmin=tmin) + + if not return_generator: + stcs = list(stcs) + + return stcs + + +@verbose +def apply_dics_tfr_epochs(epochs_tfr, filters, return_generator=False, verbose=None): + """Apply Dynamic Imaging of Coherent Sources (DICS) beamformer weights. + + Apply Dynamic Imaging of Coherent Sources (DICS) beamformer weights + on single trial time-frequency data. + + Parameters + ---------- + epochs_tfr : EpochsTFR + Single trial time-frequency epochs. + filters : instance of Beamformer + DICS spatial filter (beamformer weights) + Filter weights returned from :func:`make_dics`. + return_generator : bool + Return a generator object instead of a list. This allows iterating + over the stcs without having to keep them all in memory. + %(verbose)s + + Returns + ------- + stcs : list of list of (SourceEstimate | VectorSourceEstimate | VolSourceEstimate) + The source estimates for all epochs (outside list) and for + all frequencies (inside list). + + See Also + -------- + apply_dics + apply_dics_epochs + apply_dics_csd + """ # noqa E501 + _validate_type(epochs_tfr, EpochsTFR) + _check_tfr_complex(epochs_tfr) + + if filters["pick_ori"] == "vector": + warn( + "Using a vector solution to compute power will lead to " + "inaccurate directions (only in the first quadrent) " + "because power is a strictly positive (squared) metric. " + "Using singular value decomposition (SVD) to determine " + "the direction is not yet supported in MNE." + ) + + sel = _check_channels_spatial_filter(epochs_tfr.ch_names, filters) + data = epochs_tfr.data[:, sel, :, :] + + stcs = _apply_dics(data, filters, epochs_tfr.info, epochs_tfr.tmin, tfr=True) + if not return_generator: + stcs = [[stc for stc in tfr_stcs] for tfr_stcs in stcs] + return stcs + + +@verbose +def apply_dics_csd(csd, filters, verbose=None): + """Apply Dynamic Imaging of Coherent Sources (DICS) beamformer weights. + + Apply a previously computed DICS beamformer to a cross-spectral density + (CSD) object to estimate source power in time and frequency windows + specified in the CSD object :footcite:`GrossEtAl2001`. + + .. note:: Only power can computed from the cross-spectral density, not + complex phase-amplitude, so vector DICS filters will be + converted to scalar source estimates since power is strictly + positive and so 3D directions cannot be combined meaningfully + (the direction would be confined to the positive quadrant). + + Parameters + ---------- + csd : instance of CrossSpectralDensity + The data cross-spectral density (CSD) matrices. A source estimate is + performed for each frequency or frequency-bin defined in the CSD + object. + filters : instance of Beamformer + DICS spatial filter (beamformer weights) + Filter weights returned from `make_dics`. + %(verbose)s + + Returns + ------- + stc : SourceEstimate + Source power with frequency instead of time. + frequencies : list of float + The frequencies for which the source power has been computed. If the + data CSD object defines frequency-bins instead of exact frequencies, + the mean of each bin is returned. + + See Also + -------- + apply_dics + apply_dics_epochs + apply_dics_tfr_epochs + + References + ---------- + .. footbibliography:: + """ # noqa: E501 + ch_names = filters["ch_names"] + vertices = filters["vertices"] + n_orient = 3 if filters["is_free_ori"] else 1 + subject = filters["subject"] + whitener = filters["whitener"] + n_sources = filters["n_sources"] + + # If CSD is summed over multiple frequencies, take the average frequency + frequencies = [np.mean(dfreq) for dfreq in csd.frequencies] + n_freqs = len(frequencies) + + source_power = np.zeros((n_sources, len(csd.frequencies))) + + # Ensure the CSD is in the same order as the weights + csd_picks = [csd.ch_names.index(ch) for ch in ch_names] + + logger.info("Computing DICS source power...") + for i, freq in enumerate(frequencies): + if n_freqs > 1: + logger.info( + " applying DICS spatial filter at " + f"{round(freq, 2)} Hz ({i + 1}/{n_freqs})" + ) + + Cm = csd.get_data(index=i) + Cm = Cm[csd_picks, :][:, csd_picks] + W = filters["weights"][i] + + # Whiten the CSD + Cm = np.dot(whitener, np.dot(Cm, whitener.conj().T)) + + source_power[:, i] = _compute_power(Cm, W, n_orient) + + logger.info("[done]") + + # compatibility with 0.16, add src_type as None if not present: + filters, warn_text = _check_src_type(filters) + + return ( + _make_stc( + source_power, + vertices=vertices, + src_type=filters["src_type"], + tmin=0.0, + tstep=1.0, + subject=subject, + warn_text=warn_text, + ), + frequencies, + ) diff --git a/mne-python/source/mne/beamformer/_lcmv.py b/mne-python/source/mne/beamformer/_lcmv.py new file mode 100644 index 0000000000000000000000000000000000000000..cd3b2910cce9ba0ff291dea5841449786347fc54 --- /dev/null +++ b/mne-python/source/mne/beamformer/_lcmv.py @@ -0,0 +1,503 @@ +"""Compute Linearly constrained minimum variance (LCMV) beamformer.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from .._fiff.meas_info import _simplify_info +from .._fiff.pick import pick_channels_cov, pick_info +from ..forward import _subject_from_forward +from ..minimum_norm.inverse import _check_depth, _check_reference, combine_xyz +from ..rank import compute_rank +from ..source_estimate import _get_src_type, _make_stc +from ..utils import ( + _check_channels_spatial_filter, + _check_info_inv, + _check_one_ch_type, + logger, + verbose, +) +from ._compute_beamformer import ( + Beamformer, + _check_src_type, + _compute_beamformer, + _compute_power, + _prepare_beamformer_input, + _proj_whiten_data, +) + + +@verbose +def make_lcmv( + info, + forward, + data_cov, + reg=0.05, + noise_cov=None, + label=None, + pick_ori=None, + rank="info", + weight_norm="unit-noise-gain-invariant", + reduce_rank=False, + depth=None, + inversion="matrix", + verbose=None, +): + """Compute LCMV spatial filter. + + Parameters + ---------- + %(info_not_none)s + Specifies the channels to include. Bad channels (in ``info['bads']``) + are not used. + forward : instance of Forward + Forward operator. + data_cov : instance of Covariance + The data covariance. + reg : float + The regularization for the whitened data covariance. + noise_cov : instance of Covariance + The noise covariance. If provided, whitening will be done. Providing a + noise covariance is mandatory if you mix sensor types, e.g. + gradiometers with magnetometers or EEG with MEG. + + .. note:: + If ``noise_cov`` is ``None`` and ``weight_norm='unit-noise-gain'``, + the unit noise is assumed to be 1 in SI units, e.g., 1 T for + magnetometers, 1 V for EEG, so resulting amplitudes will be tiny. + Consider using :func:`mne.make_ad_hoc_cov` to provide a + ``noise_cov`` to set noise values that are more reasonable for + neural data or using ``weight_norm='nai'`` for weight-normalized + beamformer output that is scaled by a noise estimate. + label : instance of Label + Restricts the LCMV solution to a given label. + %(pick_ori_bf)s + + - ``'vector'`` + Keeps the currents for each direction separate + %(rank_info)s + %(weight_norm)s + + Defaults to ``'unit-noise-gain-invariant'``. + %(reduce_rank)s + %(depth)s + + .. versionadded:: 0.18 + %(inversion_bf)s + + .. versionadded:: 0.21 + %(verbose)s + + Returns + ------- + filters : instance of Beamformer + Dictionary containing filter weights from LCMV beamformer. + Contains the following keys: + + 'kind' : str + The type of beamformer, in this case 'LCMV'. + 'weights' : array + The filter weights of the beamformer. + 'data_cov' : instance of Covariance + The data covariance matrix used to compute the beamformer. + 'noise_cov' : instance of Covariance | None + The noise covariance matrix used to compute the beamformer. + 'whitener' : None | ndarray, shape (n_channels, n_channels) + Whitening matrix, provided if whitening was applied to the + covariance matrix and leadfield during computation of the + beamformer weights. + 'weight_norm' : str | None + Type of weight normalization used to compute the filter + weights. + 'pick-ori' : None | 'max-power' | 'normal' | 'vector' + The orientation in which the beamformer filters were computed. + 'ch_names' : list of str + Channels used to compute the beamformer. + 'proj' : array + Projections used to compute the beamformer. + 'is_ssp' : bool + If True, projections were applied prior to filter computation. + 'vertices' : list + Vertices for which the filter weights were computed. + 'is_free_ori' : bool + If True, the filter was computed with free source orientation. + 'n_sources' : int + Number of source location for which the filter weight were + computed. + 'src_type' : str + Type of source space. + 'source_nn' : ndarray, shape (n_sources, 3) + For each source location, the surface normal. + 'proj' : ndarray, shape (n_channels, n_channels) + Projections used to compute the beamformer. + 'subject' : str + The subject ID. + 'rank' : int + The rank of the data covariance matrix used to compute the + beamformer weights. + 'max-power-ori' : ndarray, shape (n_sources, 3) | None + When pick_ori='max-power', this fields contains the estimated + direction of maximum power at each source location. + 'inversion' : 'single' | 'matrix' + Whether the spatial filters were computed for each dipole + separately or jointly for all dipoles at each vertex using a + matrix inversion. + + Notes + ----- + The original reference is :footcite:`VanVeenEtAl1997`. + + To obtain the Sekihara unit-noise-gain vector beamformer, you should use + ``weight_norm='unit-noise-gain', pick_ori='vector'`` followed by + :meth:`vec_stc.project('pca', src) `. + + .. versionchanged:: 0.21 + The computations were extensively reworked, and the default for + ``weight_norm`` was set to ``'unit-noise-gain-invariant'``. + + References + ---------- + .. footbibliography:: + """ + # check number of sensor types present in the data and ensure a noise cov + info = _simplify_info(info, keep=("proc_history",)) + noise_cov, _, allow_mismatch = _check_one_ch_type( + "lcmv", info, forward, data_cov, noise_cov + ) + # XXX we need this extra picking step (can't just rely on minimum norm's + # because there can be a mismatch. Should probably add an extra arg to + # _prepare_beamformer_input at some point (later) + picks = _check_info_inv(info, forward, data_cov, noise_cov) + info = pick_info(info, picks) + data_rank = compute_rank(data_cov, rank=rank, info=info) + noise_rank = compute_rank(noise_cov, rank=rank, info=info) + for key in data_rank: + if ( + key not in noise_rank or data_rank[key] != noise_rank[key] + ) and not allow_mismatch: + raise ValueError( + f"{key} data rank ({data_rank[key]}) did not match the noise rank (" + f"{noise_rank.get(key, None)})" + ) + del noise_rank + rank = data_rank + logger.info(f"Making LCMV beamformer with rank {rank}") + del data_rank + depth = _check_depth(depth, "depth_sparse") + if inversion == "single": + depth["combine_xyz"] = False + + ( + is_free_ori, + info, + proj, + vertno, + G, + whitener, + nn, + orient_std, + ) = _prepare_beamformer_input( + info, + forward, + label, + pick_ori, + noise_cov=noise_cov, + rank=rank, + pca=False, + **depth, + ) + ch_names = list(info["ch_names"]) + + data_cov = pick_channels_cov(data_cov, include=ch_names) + Cm = data_cov._get_square() + if "estimator" in data_cov: + del data_cov["estimator"] + rank_int = sum(rank.values()) + del rank + + # compute spatial filter + n_orient = 3 if is_free_ori else 1 + W, max_power_ori = _compute_beamformer( + G, + Cm, + reg, + n_orient, + weight_norm, + pick_ori, + reduce_rank, + rank_int, + inversion=inversion, + nn=nn, + orient_std=orient_std, + whitener=whitener, + ) + + # get src type to store with filters for _make_stc + src_type = _get_src_type(forward["src"], vertno) + + # get subject to store with filters + subject_from = _subject_from_forward(forward) + + # Is the computed beamformer a scalar or vector beamformer? + is_free_ori = is_free_ori if pick_ori in [None, "vector"] else False + is_ssp = bool(info["projs"]) + + filters = Beamformer( + kind="LCMV", + weights=W, + data_cov=data_cov, + noise_cov=noise_cov, + whitener=whitener, + weight_norm=weight_norm, + pick_ori=pick_ori, + ch_names=ch_names, + proj=proj, + is_ssp=is_ssp, + vertices=vertno, + is_free_ori=is_free_ori, + n_sources=forward["nsource"], + src_type=src_type, + source_nn=forward["source_nn"].copy(), + subject=subject_from, + rank=rank_int, + max_power_ori=max_power_ori, + inversion=inversion, + ) + + return filters + + +def _apply_lcmv(data, filters, info, tmin): + """Apply LCMV spatial filter to data for source reconstruction.""" + if isinstance(data, np.ndarray) and data.ndim == 2: + data = [data] + return_single = True + else: + return_single = False + + W = filters["weights"] + + for i, M in enumerate(data): + if len(M) != len(filters["ch_names"]): + raise ValueError("data and picks must have the same length") + + if not return_single: + logger.info(f"Processing epoch : {i + 1}") + + M = _proj_whiten_data(M, info["projs"], filters) + + # project to source space using beamformer weights + vector = False + if filters["is_free_ori"]: + sol = np.dot(W, M) + if filters["pick_ori"] == "vector": + vector = True + else: + logger.info("combining the current components...") + sol = combine_xyz(sol) + else: + # Linear inverse: do computation here or delayed + if M.shape[0] < W.shape[0] and filters["pick_ori"] != "max-power": + sol = (W, M) + else: + sol = np.dot(W, M) + + tstep = 1.0 / info["sfreq"] + + # compatibility with 0.16, add src_type as None if not present: + filters, warn_text = _check_src_type(filters) + + yield _make_stc( + sol, + vertices=filters["vertices"], + tmin=tmin, + tstep=tstep, + subject=filters["subject"], + vector=vector, + source_nn=filters["source_nn"], + src_type=filters["src_type"], + warn_text=warn_text, + ) + + logger.info("[done]") + + +@verbose +def apply_lcmv(evoked, filters, *, verbose=None): + """Apply Linearly Constrained Minimum Variance (LCMV) beamformer weights. + + Apply Linearly Constrained Minimum Variance (LCMV) beamformer weights + on evoked data. + + Parameters + ---------- + evoked : Evoked + Evoked data to invert. + filters : instance of Beamformer + LCMV spatial filter (beamformer weights). + Filter weights returned from :func:`make_lcmv`. + %(verbose)s + + Returns + ------- + stc : SourceEstimate | VolSourceEstimate | VectorSourceEstimate + Source time courses. + + See Also + -------- + make_lcmv, apply_lcmv_raw, apply_lcmv_epochs, apply_lcmv_cov + + Notes + ----- + .. versionadded:: 0.18 + """ + _check_reference(evoked) + + info = evoked.info + data = evoked.data + tmin = evoked.times[0] + + sel = _check_channels_spatial_filter(evoked.ch_names, filters) + data = data[sel] + + stc = _apply_lcmv(data=data, filters=filters, info=info, tmin=tmin) + + return next(stc) + + +@verbose +def apply_lcmv_epochs(epochs, filters, *, return_generator=False, verbose=None): + """Apply Linearly Constrained Minimum Variance (LCMV) beamformer weights. + + Apply Linearly Constrained Minimum Variance (LCMV) beamformer weights + on single trial data. + + Parameters + ---------- + epochs : Epochs + Single trial epochs. + filters : instance of Beamformer + LCMV spatial filter (beamformer weights) + Filter weights returned from :func:`make_lcmv`. + return_generator : bool + Return a generator object instead of a list. This allows iterating + over the stcs without having to keep them all in memory. + %(verbose)s + + Returns + ------- + stc: list | generator of (SourceEstimate | VolSourceEstimate) + The source estimates for all epochs. + + See Also + -------- + make_lcmv, apply_lcmv_raw, apply_lcmv, apply_lcmv_cov + """ + _check_reference(epochs) + + info = epochs.info + tmin = epochs.times[0] + + sel = _check_channels_spatial_filter(epochs.ch_names, filters) + data = epochs.get_data(sel) + stcs = _apply_lcmv(data=data, filters=filters, info=info, tmin=tmin) + + if not return_generator: + stcs = [s for s in stcs] + + return stcs + + +@verbose +def apply_lcmv_raw(raw, filters, start=None, stop=None, *, verbose=None): + """Apply Linearly Constrained Minimum Variance (LCMV) beamformer weights. + + Apply Linearly Constrained Minimum Variance (LCMV) beamformer weights + on raw data. + + Parameters + ---------- + raw : mne.io.Raw + Raw data to invert. + filters : instance of Beamformer + LCMV spatial filter (beamformer weights). + Filter weights returned from :func:`make_lcmv`. + start : int + Index of first time sample (index not time is seconds). + stop : int + Index of first time sample not to include (index not time is seconds). + %(verbose)s + + Returns + ------- + stc : SourceEstimate | VolSourceEstimate + Source time courses. + + See Also + -------- + make_lcmv, apply_lcmv_epochs, apply_lcmv, apply_lcmv_cov + """ + _check_reference(raw) + + info = raw.info + + sel = _check_channels_spatial_filter(raw.ch_names, filters) + data, times = raw[sel, start:stop] + tmin = times[0] + + stc = _apply_lcmv(data=data, filters=filters, info=info, tmin=tmin) + + return next(stc) + + +@verbose +def apply_lcmv_cov(data_cov, filters, verbose=None): + """Apply Linearly Constrained Minimum Variance (LCMV) beamformer weights. + + Apply Linearly Constrained Minimum Variance (LCMV) beamformer weights + to a data covariance matrix to estimate source power. + + Parameters + ---------- + data_cov : instance of Covariance + Data covariance matrix. + filters : instance of Beamformer + LCMV spatial filter (beamformer weights). + Filter weights returned from :func:`make_lcmv`. + %(verbose)s + + Returns + ------- + stc : SourceEstimate | VolSourceEstimate + Source power. + + See Also + -------- + make_lcmv, apply_lcmv, apply_lcmv_epochs, apply_lcmv_raw + """ + sel = _check_channels_spatial_filter(data_cov.ch_names, filters) + sel_names = [data_cov.ch_names[ii] for ii in sel] + data_cov = pick_channels_cov(data_cov, sel_names) + + n_orient = filters["weights"].shape[0] // filters["n_sources"] + # Need to project and whiten along both dimensions + data = _proj_whiten_data(data_cov["data"].T, data_cov["projs"], filters) + data = _proj_whiten_data(data.T, data_cov["projs"], filters) + del data_cov + source_power = _compute_power(data, filters["weights"], n_orient) + + # compatibility with 0.16, add src_type as None if not present: + filters, warn_text = _check_src_type(filters) + + return _make_stc( + source_power, + vertices=filters["vertices"], + src_type=filters["src_type"], + tmin=0.0, + tstep=1.0, + subject=filters["subject"], + source_nn=filters["source_nn"], + warn_text=warn_text, + ) diff --git a/mne-python/source/mne/beamformer/_rap_music.py b/mne-python/source/mne/beamformer/_rap_music.py new file mode 100644 index 0000000000000000000000000000000000000000..901651d89de28d559fd4f0a2d7738ee79335b2e9 --- /dev/null +++ b/mne-python/source/mne/beamformer/_rap_music.py @@ -0,0 +1,315 @@ +"""Compute a Recursively Applied and Projected MUltiple Signal Classification (RAP-MUSIC).""" # noqa + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +from scipy import linalg + +from .._fiff.pick import pick_channels_forward, pick_info +from ..fixes import _reshape_view, _safe_svd +from ..forward import convert_forward_solution, is_fixed_orient +from ..inverse_sparse.mxne_inverse import _make_dipoles_sparse +from ..minimum_norm.inverse import _log_exp_var +from ..utils import _check_info_inv, fill_doc, logger, verbose +from ._compute_beamformer import _prepare_beamformer_input + + +@fill_doc +def _apply_rap_music( + data, info, times, forward, noise_cov, n_dipoles=2, picks=None, use_trap=False +): + """RAP-MUSIC or TRAP-MUSIC for evoked data. + + Parameters + ---------- + data : array, shape (n_channels, n_times) + Evoked data. + %(info_not_none)s + times : array + Times. + forward : instance of Forward + Forward operator. + noise_cov : instance of Covariance + The noise covariance. + n_dipoles : int + The number of dipoles to estimate. The default value is 2. + picks : list of int + Caller ensures this is a list of int. + use_trap : bool + Use the TRAP-MUSIC variant if True (default False). + + Returns + ------- + dipoles : list of instances of Dipole + The dipole fits. + explained_data : array | None + Data explained by the dipoles using a least square fitting with the + selected active dipoles and their estimated orientation. + """ + info = pick_info(info, picks) + del picks + # things are much simpler if we avoid surface orientation + align = forward["source_nn"].copy() + if forward["surf_ori"] and not is_fixed_orient(forward): + forward = convert_forward_solution(forward, surf_ori=False) + is_free_ori, info, _, _, G, whitener, _, _ = _prepare_beamformer_input( + info, forward, noise_cov=noise_cov, rank=None + ) + forward = pick_channels_forward(forward, info["ch_names"], ordered=True) + del info + + # whiten the data (leadfield already whitened) + M = np.dot(whitener, data) + del data + + _, eig_vectors = linalg.eigh(np.dot(M, M.T)) + phi_sig = eig_vectors[:, -n_dipoles:] + + n_orient = 3 if is_free_ori else 1 + G = _reshape_view(G, (G.shape[0], -1, n_orient)) + gain = forward["sol"]["data"].copy() + gain = _reshape_view(gain, G.shape) + n_channels = G.shape[0] + A = np.empty((n_channels, n_dipoles)) + gain_dip = np.empty((n_channels, n_dipoles)) + oris = np.empty((n_dipoles, 3)) + poss = np.empty((n_dipoles, 3)) + + G_proj = G.copy() + phi_sig_proj = phi_sig.copy() + + idxs = list() + for k in range(n_dipoles): + subcorr_max = -1.0 + source_idx, source_ori, source_pos = 0, [0, 0, 0], [0, 0, 0] + for i_source in range(G.shape[1]): + Gk = G_proj[:, i_source] + subcorr, ori = _compute_subcorr(Gk, phi_sig_proj) + if subcorr > subcorr_max: + subcorr_max = subcorr + source_idx = i_source + source_ori = ori + source_pos = forward["source_rr"][i_source] + if n_orient == 3 and align is not None: + surf_normal = forward["source_nn"][3 * i_source + 2] + # make sure ori is aligned to the surface orientation + source_ori *= np.sign(source_ori @ surf_normal) or 1.0 + if n_orient == 1: + source_ori = forward["source_nn"][i_source] + + idxs.append(source_idx) + if n_orient == 3: + Ak = np.dot(G[:, source_idx], source_ori) + else: + Ak = G[:, source_idx, 0] + A[:, k] = Ak + oris[k] = source_ori + poss[k] = source_pos + + logger.info(f"source {k + 1} found: p = {source_idx}") + if n_orient == 3: + logger.info("ori = {} {} {}".format(*tuple(oris[k]))) + + projection = _compute_proj(A[:, : k + 1]) + G_proj = np.einsum("ab,bso->aso", projection, G) + phi_sig_proj = np.dot(projection, phi_sig) + if use_trap: + phi_sig_proj = phi_sig_proj[:, -(n_dipoles - k) :] + del G, G_proj + + sol = linalg.lstsq(A, M)[0] + if n_orient == 3: + X = sol[:, np.newaxis] * oris[:, :, np.newaxis] + X = _reshape_view(X, (-1, len(times))) + else: + X = sol + + gain_active = gain[:, idxs] + if n_orient == 3: + gain_dip = (oris * gain_active).sum(-1) + idxs = np.array(idxs) + active_set = np.array([[3 * idxs, 3 * idxs + 1, 3 * idxs + 2]]).T.ravel() + else: + gain_dip = gain_active[:, :, 0] + active_set = idxs + gain_active = whitener @ gain_active.reshape(gain.shape[0], -1) + assert gain_active.shape == (n_channels, X.shape[0]) + + explained_data = gain_dip @ sol + M_estimate = whitener @ explained_data + _log_exp_var(M, M_estimate) + tstep = np.median(np.diff(times)) if len(times) > 1 else 1.0 + dipoles = _make_dipoles_sparse( + X, active_set, forward, times[0], tstep, M, gain_active, active_is_idx=True + ) + for dipole, ori in zip(dipoles, oris): + signs = np.sign((dipole.ori * ori).sum(-1, keepdims=True)) + dipole._ori *= signs + dipole._amplitude *= signs[:, 0] + logger.info("[done]") + return dipoles, explained_data + + +def _compute_subcorr(G, phi_sig): + """Compute the subspace correlation.""" + Ug, Sg, Vg = _safe_svd(G, full_matrices=False) + # Now we look at the actual rank of the forward fields + # in G and handle the fact that it might be rank defficient + # eg. when using MEG and a sphere model for which the + # radial component will be truly 0. + rank = np.sum(Sg > (Sg[0] * 1e-6)) + if rank == 0: + return 0, np.zeros(len(G)) + rank = max(rank, 2) # rank cannot be 1 + Ug, Sg, Vg = Ug[:, :rank], Sg[:rank], Vg[:rank] + tmp = np.dot(Ug.T.conjugate(), phi_sig) + Uc, Sc, _ = _safe_svd(tmp, full_matrices=False) + X = np.dot(Vg.T / Sg[None, :], Uc[:, 0]) # subcorr + return Sc[0], X / np.linalg.norm(X) + + +def _compute_proj(A): + """Compute the orthogonal projection operation for a manifold vector A.""" + U, _, _ = _safe_svd(A, full_matrices=False) + return np.identity(A.shape[0]) - np.dot(U, U.T.conjugate()) + + +def _rap_music(evoked, forward, noise_cov, n_dipoles, return_residual, use_trap): + """RAP-/TRAP-MUSIC implementation.""" + info = evoked.info + data = evoked.data + times = evoked.times + + picks = _check_info_inv(info, forward, data_cov=None, noise_cov=noise_cov) + + data = data[picks] + + dipoles, explained_data = _apply_rap_music( + data, info, times, forward, noise_cov, n_dipoles, picks, use_trap + ) + + if return_residual: + residual = evoked.copy().pick([info["ch_names"][p] for p in picks]) + residual.data -= explained_data + active_projs = [p for p in residual.info["projs"] if p["active"]] + for p in active_projs: + p["active"] = False + residual.add_proj(active_projs, remove_existing=True) + residual.apply_proj() + return dipoles, residual + else: + return dipoles + + +@verbose +def rap_music( + evoked, + forward, + noise_cov, + n_dipoles=5, + return_residual=False, + *, + verbose=None, +): + """RAP-MUSIC source localization method. + + Compute Recursively Applied and Projected MUltiple SIgnal Classification + (RAP-MUSIC) :footcite:`MosherLeahy1999,MosherLeahy1996` on evoked data. + + .. note:: The goodness of fit (GOF) of all the returned dipoles is the + same and corresponds to the GOF of the full set of dipoles. + + Parameters + ---------- + evoked : instance of Evoked + Evoked data to localize. + forward : instance of Forward + Forward operator. + noise_cov : instance of Covariance + The noise covariance. + n_dipoles : int + The number of dipoles to look for. The default value is 5. + return_residual : bool + If True, the residual is returned as an Evoked instance. + %(verbose)s + + Returns + ------- + dipoles : list of instance of Dipole + The dipole fits. + residual : instance of Evoked + The residual a.k.a. data not explained by the dipoles. + Only returned if return_residual is True. + + See Also + -------- + mne.fit_dipole + mne.beamformer.trap_music + + Notes + ----- + .. versionadded:: 0.9.0 + + References + ---------- + .. footbibliography:: + """ + return _rap_music(evoked, forward, noise_cov, n_dipoles, return_residual, False) + + +@verbose +def trap_music( + evoked, + forward, + noise_cov, + n_dipoles=5, + return_residual=False, + *, + verbose=None, +): + """TRAP-MUSIC source localization method. + + Compute Truncated Recursively Applied and Projected MUltiple SIgnal Classification + (TRAP-MUSIC) :footcite:`Makela2018` on evoked data. + + .. note:: The goodness of fit (GOF) of all the returned dipoles is the + same and corresponds to the GOF of the full set of dipoles. + + Parameters + ---------- + evoked : instance of Evoked + Evoked data to localize. + forward : instance of Forward + Forward operator. + noise_cov : instance of Covariance + The noise covariance. + n_dipoles : int + The number of dipoles to look for. The default value is 5. + return_residual : bool + If True, the residual is returned as an Evoked instance. + %(verbose)s + + Returns + ------- + dipoles : list of instance of Dipole + The dipole fits. + residual : instance of Evoked + The residual a.k.a. data not explained by the dipoles. + Only returned if return_residual is True. + + See Also + -------- + mne.fit_dipole + mne.beamformer.rap_music + + Notes + ----- + .. versionadded:: 1.4 + + References + ---------- + .. footbibliography:: + """ + return _rap_music(evoked, forward, noise_cov, n_dipoles, return_residual, True) diff --git a/mne-python/source/mne/beamformer/resolution_matrix.py b/mne-python/source/mne/beamformer/resolution_matrix.py new file mode 100644 index 0000000000000000000000000000000000000000..e2dd258a2ab21a605adb6a8db796a2f3b777ad1c --- /dev/null +++ b/mne-python/source/mne/beamformer/resolution_matrix.py @@ -0,0 +1,86 @@ +"""Compute resolution matrix for beamformers.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from .._fiff.pick import pick_channels, pick_channels_forward, pick_info +from ..evoked import EvokedArray +from ..utils import fill_doc, logger +from ._lcmv import apply_lcmv + + +@fill_doc +def make_lcmv_resolution_matrix(filters, forward, info): + """Compute resolution matrix for LCMV beamformer. + + Parameters + ---------- + filters : instance of Beamformer + Dictionary containing filter weights from LCMV beamformer + (see mne.beamformer.make_lcmv). + forward : instance of Forward + Forward Solution with leadfield matrix. + %(info_not_none)s Used to compute LCMV filters. + + Returns + ------- + resmat : array, shape (n_dipoles_lcmv, n_dipoles_fwd) + Resolution matrix (filter matrix multiplied to leadfield from + forward solution). Numbers of rows (n_dipoles_lcmv) and columns + (n_dipoles_fwd) may differ by a factor depending on orientation + constraints of filter and forward solution, respectively (e.g. factor 3 + for free dipole orientation versus factor 1 for scalar beamformers). + """ + # don't include bad channels from noise covariance matrix + bads_filt = filters["noise_cov"]["bads"] + ch_names = filters["noise_cov"]["names"] + + # good channels + ch_names = [c for c in ch_names if (c not in bads_filt)] + + # adjust channels in forward solution + forward = pick_channels_forward(forward, ch_names, ordered=True) + + # get leadfield matrix from forward solution + leadfield = forward["sol"]["data"] + + # get the filter weights for beamformer as matrix + filtmat = _get_matrix_from_lcmv(filters, forward, info) + + # compute resolution matrix + resmat = filtmat.dot(leadfield) + + logger.info(f"Dimensions of LCMV resolution matrix: {resmat.shape}.") + + return resmat + + +def _get_matrix_from_lcmv(filters, forward, info, verbose=None): + """Get inverse matrix for LCMV beamformer. + + Returns + ------- + invmat : array, shape (n_dipoles, n_channels) + Inverse matrix associated with LCMV beamformer filters. + """ + # number of channels for identity matrix + info = pick_info(info, pick_channels(info["ch_names"], filters["ch_names"])) + n_chs = len(info["ch_names"]) + + # create identity matrix as input for inverse operator + # set elements to zero for non-selected channels + id_mat = np.eye(n_chs) + + # convert identity matrix to evoked data type (pretending it's an epochs + evo_ident = EvokedArray(id_mat, info=info, tmin=0.0) + + # apply beamformer to identity matrix + stc_lcmv = apply_lcmv(evo_ident, filters, verbose=verbose) + + # turn source estimate into numpsy array + invmat = stc_lcmv.data + + return invmat diff --git a/mne-python/source/mne/beamformer/tests/__init__.py b/mne-python/source/mne/beamformer/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/beamformer/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/beamformer/tests/test_dics.py b/mne-python/source/mne/beamformer/tests/test_dics.py new file mode 100644 index 0000000000000000000000000000000000000000..555eceec51366eeaec93e2429aafc20b5b6d5069 --- /dev/null +++ b/mne-python/source/mne/beamformer/tests/test_dics.py @@ -0,0 +1,977 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import copy as cp + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_equal, assert_array_less + +import mne +from mne import pick_types +from mne._fiff.constants import FIFF +from mne._fiff.pick import pick_info +from mne.beamformer import ( + Beamformer, + apply_dics, + apply_dics_csd, + apply_dics_epochs, + apply_dics_tfr_epochs, + make_dics, + read_beamformer, +) +from mne.beamformer._compute_beamformer import _prepare_beamformer_input +from mne.beamformer._dics import _prepare_noise_csd +from mne.beamformer.tests.test_lcmv import _assert_weight_norm +from mne.datasets import testing +from mne.fixes import _reshape_view +from mne.io import read_info +from mne.proj import compute_proj_evoked, make_projector +from mne.surface import _compute_nearest +from mne.time_frequency import CrossSpectralDensity, EpochsTFRArray, csd_morlet, csd_tfr +from mne.time_frequency.csd import _sym_mat_to_vector +from mne.transforms import apply_trans, invert_transform +from mne.utils import catch_logging, object_diff + +data_path = testing.data_path(download=False) +fname_raw = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw.fif" +fname_fwd = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" +fname_fwd_vol = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-vol-7-fwd.fif" +fname_event = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw-eve.fif" +subjects_dir = data_path / "subjects" + + +@pytest.fixture(scope="module", params=[testing._pytest_param()]) +def _load_forward(): + """Load forward models.""" + fwd_free = mne.read_forward_solution(fname_fwd) + fwd_free = mne.pick_types_forward(fwd_free, meg=True, eeg=False) + fwd_free = mne.convert_forward_solution(fwd_free, surf_ori=False) + fwd_surf = mne.convert_forward_solution(fwd_free, surf_ori=True, use_cps=False) + fwd_fixed = mne.convert_forward_solution(fwd_free, force_fixed=True, use_cps=False) + fwd_vol = mne.read_forward_solution(fname_fwd_vol) + return fwd_free, fwd_surf, fwd_fixed, fwd_vol + + +def _simulate_data(fwd, idx): # Somewhere on the frontal lobe by default + """Simulate an oscillator on the cortex.""" + pytest.importorskip("nibabel") + source_vertno = fwd["src"][0]["vertno"][idx] + + sfreq = 50.0 # Hz. + times = np.arange(10 * sfreq) / sfreq # 10 seconds of data + signal = np.sin(20 * 2 * np.pi * times) # 20 Hz oscillator + signal[: len(times) // 2] *= 2 # Make signal louder at the beginning + signal *= 1e-9 # Scale to be in the ballpark of MEG data + + # Construct a SourceEstimate object that describes the signal at the + # cortical level. + stc = mne.SourceEstimate( + signal[np.newaxis, :], + vertices=[[source_vertno], []], + tmin=0, + tstep=1 / sfreq, + subject="sample", + ) + + # Create an info object that holds information about the sensors + info = mne.create_info(fwd["info"]["ch_names"], sfreq, ch_types="grad") + with info._unlock(): + info.update(fwd["info"]) # Merge in sensor position information + # heavily decimate sensors to make it much faster + info = mne.pick_info(info, np.arange(info["nchan"])[::5]) + fwd = mne.pick_channels_forward(fwd, info["ch_names"]) + + # Run the simulated signal through the forward model, obtaining + # simulated sensor data. + raw = mne.apply_forward_raw(fwd, stc, info) + + # Add a little noise + random = np.random.RandomState(42) + noise = random.randn(*raw._data.shape) * 1e-14 + raw._data += noise + + # Define a single epoch (weird baseline but shouldn't matter) + epochs = mne.Epochs( + raw, + [[0, 0, 1]], + event_id=1, + tmin=0, + tmax=raw.times[-1], + baseline=(0.0, 0.0), + preload=True, + ) + evoked = epochs.average() + + # Compute the cross-spectral density matrix + csd = csd_morlet(epochs, frequencies=[10, 20], n_cycles=[5, 10], decim=5) + + labels = mne.read_labels_from_annot("sample", hemi="lh", subjects_dir=subjects_dir) + label = [label for label in labels if np.isin(source_vertno, label.vertices)] + assert len(label) == 1 + label = label[0] + vertices = np.intersect1d(label.vertices, fwd["src"][0]["vertno"]) + source_ind = vertices.tolist().index(source_vertno) + assert vertices[source_ind] == source_vertno + return epochs, evoked, csd, source_vertno, label, vertices, source_ind + + +idx_param = pytest.mark.parametrize( + "idx", + [ + 0, + pytest.param(100, marks=pytest.mark.slowtest), + 200, + pytest.param(233, marks=pytest.mark.slowtest), + ], +) + + +def _rand_csd(rng, info): + scales = mne.make_ad_hoc_cov(info).data + n = scales.size + # Some random complex correlation structure (with channel scalings) + data = rng.randn(n, n) + 1j * rng.randn(n, n) + data = data @ data.conj().T + data *= scales + data *= scales[:, np.newaxis] + data.flat[:: n + 1] = scales + return data + + +def _make_rand_csd(info, csd): + rng = np.random.RandomState(0) + data = _rand_csd(rng, info) + # now we need to have the same null space as the data csd + s, u = np.linalg.eigh(csd.get_data(csd.frequencies[0])) + mask = np.abs(s) >= s[-1] * 1e-7 + rank = mask.sum() + assert rank == len(data) == len(info["ch_names"]) + noise_csd = CrossSpectralDensity( + _sym_mat_to_vector(data), info["ch_names"], 0.0, csd.n_fft + ) + return noise_csd, rank + + +@pytest.mark.slowtest +@testing.requires_testing_data +@idx_param +@pytest.mark.parametrize( + "whiten", + [ + pytest.param(False, marks=pytest.mark.slowtest), + True, + ], +) +def test_make_dics(tmp_path, _load_forward, idx, whiten): + """Test making DICS beamformer filters.""" + pytest.importorskip("h5io") + # We only test proper handling of parameters here. Testing the results is + # done in test_apply_dics_timeseries and test_apply_dics_csd. + + fwd_free, fwd_surf, fwd_fixed, fwd_vol = _load_forward + epochs, _, csd, _, label, vertices, source_ind = _simulate_data(fwd_fixed, idx) + with pytest.raises(ValueError, match="several sensor types"): + make_dics(epochs.info, fwd_surf, csd, label=label, pick_ori=None) + if whiten: + noise_csd, rank = _make_rand_csd(epochs.info, csd) + assert rank == len(epochs.info["ch_names"]) == 62 + else: + noise_csd = None + epochs.pick(picks="grad") + + with pytest.raises(ValueError, match="Invalid value for the 'pick_ori'"): + make_dics( + epochs.info, fwd_fixed, csd, pick_ori="notexistent", noise_csd=noise_csd + ) + with pytest.raises(ValueError, match="rank, if str"): + make_dics(epochs.info, fwd_fixed, csd, rank="foo", noise_csd=noise_csd) + with pytest.raises(TypeError, match="rank must be"): + make_dics(epochs.info, fwd_fixed, csd, rank=1.0, noise_csd=noise_csd) + + # Test if fixed forward operator is detected when picking normal + # orientation + with pytest.raises(ValueError, match="forward operator with free ori"): + make_dics(epochs.info, fwd_fixed, csd, pick_ori="normal", noise_csd=noise_csd) + + # Test if non-surface oriented forward operator is detected when picking + # normal orientation + with pytest.raises(ValueError, match="oriented in surface coordinates"): + make_dics(epochs.info, fwd_free, csd, pick_ori="normal", noise_csd=noise_csd) + + # Test if volume forward operator is detected when picking normal + # orientation + with pytest.raises(ValueError, match="oriented in surface coordinates"): + make_dics(epochs.info, fwd_vol, csd, pick_ori="normal", noise_csd=noise_csd) + + # Test invalid combinations of parameters + with pytest.raises(ValueError, match="reduce_rank cannot be used with"): + make_dics( + epochs.info, + fwd_free, + csd, + inversion="single", + reduce_rank=True, + noise_csd=noise_csd, + ) + # TODO: Restore this? + # with pytest.raises(ValueError, match='not stable with depth'): + # make_dics(epochs.info, fwd_free, csd, weight_norm='unit-noise-gain', + # inversion='single', depth=None) + + # Sanity checks on the returned filters + n_freq = len(csd.frequencies) + vertices = np.intersect1d(label.vertices, fwd_free["src"][0]["vertno"]) + n_verts = len(vertices) + n_orient = 3 + + n_channels = len(epochs.ch_names) + # Test return values + weight_norm = "unit-noise-gain" + inversion = "single" + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + pick_ori=None, + weight_norm=weight_norm, + depth=None, + real_filter=False, + noise_csd=noise_csd, + inversion=inversion, + ) + assert filters["weights"].shape == (n_freq, n_verts * n_orient, n_channels) + assert np.iscomplexobj(filters["weights"]) + assert filters["csd"].ch_names == epochs.ch_names + assert isinstance(filters["csd"], CrossSpectralDensity) + assert filters["ch_names"] == epochs.ch_names + assert_array_equal(filters["proj"], np.eye(n_channels)) + assert_array_equal(filters["vertices"][0], vertices) + assert_array_equal(filters["vertices"][1], []) # Label was on the LH + assert filters["subject"] == fwd_free["src"]._subject + assert filters["pick_ori"] is None + assert filters["is_free_ori"] + assert filters["inversion"] == inversion + assert filters["weight_norm"] == weight_norm + assert "DICS" in repr(filters) + assert 'subject "sample"' in repr(filters) + assert str(len(vertices)) in repr(filters) + assert str(n_channels) in repr(filters) + assert "rank" not in repr(filters) + _, noise_cov = _prepare_noise_csd(csd, noise_csd, real_filter=False) + _, _, _, _, G, _, _, _ = _prepare_beamformer_input( + epochs.info, + fwd_surf, + label, + "vector", + combine_xyz=False, + exp=None, + noise_cov=noise_cov, + ) + G = _reshape_view(G, (n_channels, n_verts, n_orient)) + G = G.transpose(1, 2, 0).conj() # verts, orient, ch + _assert_weight_norm(filters, G) + + inversion = "matrix" + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + pick_ori=None, + weight_norm=weight_norm, + depth=None, + noise_csd=noise_csd, + inversion=inversion, + ) + _assert_weight_norm(filters, G) + + weight_norm = "unit-noise-gain-invariant" + inversion = "single" + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + pick_ori=None, + weight_norm=weight_norm, + depth=None, + noise_csd=noise_csd, + inversion=inversion, + ) + _assert_weight_norm(filters, G) + + # Test picking orientations. Also test weight norming under these different + # conditions. + weight_norm = "unit-noise-gain" + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + pick_ori="normal", + weight_norm=weight_norm, + depth=None, + noise_csd=noise_csd, + inversion=inversion, + ) + n_orient = 1 + assert filters["weights"].shape == (n_freq, n_verts * n_orient, n_channels) + assert not filters["is_free_ori"] + _assert_weight_norm(filters, G) + + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + pick_ori="max-power", + weight_norm=weight_norm, + depth=None, + noise_csd=noise_csd, + inversion=inversion, + ) + n_orient = 1 + assert filters["weights"].shape == (n_freq, n_verts * n_orient, n_channels) + assert not filters["is_free_ori"] + _assert_weight_norm(filters, G) + + # From here on, only work on a single frequency + csd = csd[0] + + # Test using a real-valued filter + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + pick_ori="normal", + real_filter=True, + noise_csd=noise_csd, + ) + assert not np.iscomplexobj(filters["weights"]) + + # Test forward normalization. When inversion='single', the power of a + # unit-noise CSD should be 1, even without weight normalization. + if not whiten: + csd_noise = csd.copy() + inds = np.triu_indices(csd.n_channels) + # Using [:, :] syntax for in-place broadcasting + csd_noise._data[:, :] = np.eye(csd.n_channels)[inds][:, np.newaxis] + filters = make_dics( + epochs.info, + fwd_surf, + csd_noise, + label=label, + weight_norm=None, + depth=1.0, + noise_csd=noise_csd, + inversion="single", + ) + w = filters["weights"][0][:3] + assert_allclose(np.diag(w.dot(w.conjugate().T)), 1.0, rtol=1e-6, atol=0) + + # Test turning off both forward and weight normalization + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + weight_norm=None, + depth=None, + noise_csd=noise_csd, + ) + w = filters["weights"][0][:3] + assert not np.allclose(np.diag(w.dot(w.conjugate().T)), 1.0, rtol=1e-2, atol=0) + + # Test neural-activity-index weight normalization. It should be a scaled + # version of the unit-noise-gain beamformer. + filters_nai = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + pick_ori="max-power", + weight_norm="nai", + depth=None, + noise_csd=noise_csd, + ) + w_nai = filters_nai["weights"][0] + filters_ung = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + pick_ori="max-power", + weight_norm="unit-noise-gain", + depth=None, + noise_csd=noise_csd, + ) + w_ung = filters_ung["weights"][0] + assert_allclose( + np.corrcoef(np.abs(w_nai).ravel(), np.abs(w_ung).ravel()), 1, atol=1e-7 + ) + + # Test whether spatial filter contains src_type + assert "src_type" in filters + + fname = tmp_path / "filters-dics.h5" + filters.save(fname) + filters_read = read_beamformer(fname) + assert isinstance(filters, Beamformer) + assert isinstance(filters_read, Beamformer) + for key in ["tmin", "tmax"]: # deal with strictness of object_diff + setattr(filters["csd"], key, np.float64(getattr(filters["csd"], key))) + assert object_diff(filters, filters_read) == "" + + +def _fwd_dist(power, fwd, vertices, source_ind, tidx=1): + idx = np.argmax(power.data[:, tidx]) + rr_got = fwd["src"][0]["rr"][vertices[idx]] + rr_want = fwd["src"][0]["rr"][vertices[source_ind]] + return np.linalg.norm(rr_got - rr_want) + + +@idx_param +@pytest.mark.parametrize( + "inversion, weight_norm", + [ + ("single", None), + ("matrix", "unit-noise-gain"), + ], +) +def test_apply_dics_csd(_load_forward, idx, inversion, weight_norm): + """Test applying a DICS beamformer to a CSD matrix.""" + fwd_free, fwd_surf, fwd_fixed, _ = _load_forward + epochs, _, csd, source_vertno, label, vertices, source_ind = _simulate_data( + fwd_fixed, idx + ) + reg = 1 # Lots of regularization for our toy dataset + + with pytest.raises(ValueError, match="several sensor types"): + make_dics(epochs.info, fwd_free, csd) + epochs.pick(picks="grad") + + # Try different types of forward models + assert label.hemi == "lh" + for fwd in [fwd_free, fwd_surf, fwd_fixed]: + filters = make_dics( + epochs.info, + fwd, + csd, + label=label, + reg=reg, + inversion=inversion, + weight_norm=weight_norm, + ) + power, f = apply_dics_csd(csd, filters) + assert f == [10, 20] + + # Did we find the true source at 20 Hz? + dist = _fwd_dist(power, fwd_free, vertices, source_ind) + assert dist == 0.0 + + # Is the signal stronger at 20 Hz than 10? + assert power.data[source_ind, 1] > power.data[source_ind, 0] + + +@pytest.mark.parametrize("pick_ori", [None, "normal", "max-power", "vector"]) +@pytest.mark.parametrize("inversion", ["single", "matrix"]) +@idx_param +def test_apply_dics_ori_inv(_load_forward, pick_ori, inversion, idx): + """Test picking different orientations and inversion modes.""" + fwd_free, fwd_surf, fwd_fixed, fwd_vol = _load_forward + epochs, _, csd, source_vertno, label, vertices, source_ind = _simulate_data( + fwd_fixed, idx + ) + epochs.pick(picks="grad") + + reg_ = 5 if inversion == "matrix" else 1 + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + reg=reg_, + pick_ori=pick_ori, + inversion=inversion, + depth=None, + weight_norm="unit-noise-gain", + ) + power, f = apply_dics_csd(csd, filters) + assert f == [10, 20] + dist = _fwd_dist(power, fwd_surf, vertices, source_ind) + # This is 0. for unit-noise-gain-invariant: + assert dist <= (0.02 if inversion == "matrix" else 0.0) + assert power.data[source_ind, 1] > power.data[source_ind, 0] + + # Test unit-noise-gain weighting + csd_noise = csd.copy() + inds = np.triu_indices(csd.n_channels) + csd_noise._data[...] = np.eye(csd.n_channels)[inds][:, np.newaxis] + noise_power, f = apply_dics_csd(csd_noise, filters) + want_norm = 3 if pick_ori in (None, "vector") else 1 + assert_allclose(noise_power.data, want_norm, atol=1e-7) + + # Test filter with forward normalization instead of weight + # normalization + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + reg=reg_, + pick_ori=pick_ori, + inversion=inversion, + weight_norm=None, + depth=1.0, + ) + power, f = apply_dics_csd(csd, filters) + assert f == [10, 20] + dist = _fwd_dist(power, fwd_surf, vertices, source_ind) + mat_tol = {0: 0.055, 100: 0.20, 200: 0.015, 233: 0.035}[idx] + max_ = mat_tol if inversion == "matrix" else 0.0 + assert 0 <= dist <= max_ + assert power.data[source_ind, 1] > power.data[source_ind, 0] + + +def _nearest_vol_ind(fwd_vol, fwd, vertices, source_ind): + return _compute_nearest( + fwd_vol["source_rr"], fwd["src"][0]["rr"][vertices][source_ind][np.newaxis] + )[0] + + +@idx_param +def test_real(_load_forward, idx): + """Test using a real-valued filter.""" + fwd_free, fwd_surf, fwd_fixed, fwd_vol = _load_forward + epochs, _, csd, source_vertno, label, vertices, source_ind = _simulate_data( + fwd_fixed, idx + ) + epochs.pick(picks="grad") + reg = 1 # Lots of regularization for our toy dataset + filters_real = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + reg=reg, + real_filter=True, + inversion="single", + ) + # Also test here that no warnings are thrown - implemented to check whether + # src should not be None warning occurs: + power, f = apply_dics_csd(csd, filters_real) + + assert f == [10, 20] + dist = _fwd_dist(power, fwd_surf, vertices, source_ind) + assert dist == 0 + assert power.data[source_ind, 1] > power.data[source_ind, 0] + + # Test rank reduction + filters_real = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + reg=5, + pick_ori="max-power", + inversion="matrix", + reduce_rank=True, + ) + power, f = apply_dics_csd(csd, filters_real) + assert f == [10, 20] + dist = _fwd_dist(power, fwd_surf, vertices, source_ind) + assert dist == 0 + assert power.data[source_ind, 1] > power.data[source_ind, 0] + + # Test computing source power on a volume source space + filters_vol = make_dics(epochs.info, fwd_vol, csd, reg=reg, inversion="single") + power, f = apply_dics_csd(csd, filters_vol) + vol_source_ind = _nearest_vol_ind(fwd_vol, fwd_surf, vertices, source_ind) + assert f == [10, 20] + dist = _fwd_dist(power, fwd_vol, fwd_vol["src"][0]["vertno"], vol_source_ind) + vol_tols = {100: 0.008, 200: 0.008} + assert dist <= vol_tols.get(idx, 0.0) + assert power.data[vol_source_ind, 1] > power.data[vol_source_ind, 0] + + # check whether a filters object without src_type throws expected warning + del filters_vol["src_type"] # emulate 0.16 behaviour to cause warning + with pytest.warns(RuntimeWarning, match="spatial filter does not contain src_type"): + apply_dics_csd(csd, filters_vol) + + +@pytest.mark.filterwarnings( + "ignore:The use of several sensor types with the:RuntimeWarning" +) +@idx_param +def test_apply_dics_timeseries(_load_forward, idx): + """Test DICS applied to timeseries data.""" + fwd_free, fwd_surf, fwd_fixed, fwd_vol = _load_forward + epochs, evoked, csd, source_vertno, label, vertices, source_ind = _simulate_data( + fwd_fixed, idx + ) + reg = 5 # Lots of regularization for our toy dataset + + with pytest.raises(ValueError, match="several sensor types"): + make_dics(evoked.info, fwd_surf, csd) + evoked.pick(picks="grad") + + multiple_filters = make_dics(evoked.info, fwd_surf, csd, label=label, reg=reg) + + # Sanity checks on the resulting STC after applying DICS on evoked + stcs = apply_dics(evoked, multiple_filters) + assert isinstance(stcs, list) + assert len(stcs) == len(multiple_filters["weights"]) + assert_array_equal(stcs[0].vertices[0], multiple_filters["vertices"][0]) + assert_array_equal(stcs[0].vertices[1], multiple_filters["vertices"][1]) + assert_allclose(stcs[0].times, evoked.times) + + # Applying filters for multiple frequencies on epoch data should fail + with pytest.raises(ValueError, match="computed for a single frequency"): + apply_dics_epochs(epochs, multiple_filters) + + # From now on, only apply filters with a single frequency (20 Hz). + csd20 = csd.pick_frequency(20) + filters = make_dics( + evoked.info, fwd_surf, csd20, label=label, reg=reg, inversion="single" + ) + + # Sanity checks on the resulting STC after applying DICS on epochs. + # Also test here that no warnings are thrown - implemented to check whether + # src should not be None warning occurs + stcs = apply_dics_epochs(epochs, filters) + + assert isinstance(stcs, list) + assert len(stcs) == 1 + assert_array_equal(stcs[0].vertices[0], filters["vertices"][0]) + assert_array_equal(stcs[0].vertices[1], filters["vertices"][1]) + assert_allclose(stcs[0].times, epochs.times) + + # Did we find the source? + stc = (stcs[0] ** 2).mean() + dist = _fwd_dist(stc, fwd_surf, vertices, source_ind, tidx=0) + assert dist == 0 + + # Apply filters to evoked + stc = apply_dics(evoked, filters) + stc = (stc**2).mean() + dist = _fwd_dist(stc, fwd_surf, vertices, source_ind, tidx=0) + assert dist == 0 + + # Test if wrong channel selection is detected in application of filter + evoked_ch = cp.deepcopy(evoked) + evoked_ch.pick(evoked_ch.ch_names[:-1]) + with pytest.raises(ValueError, match="MEG 2633 which is not present"): + apply_dics(evoked_ch, filters) + + # Test whether projections are applied, by adding a custom projection + filters_noproj = make_dics(evoked.info, fwd_surf, csd20, label=label) + stc_noproj = apply_dics(evoked, filters_noproj) + evoked_proj = evoked.copy() + p = compute_proj_evoked(evoked_proj, n_grad=1, n_mag=0, n_eeg=0) + proj_matrix = make_projector(p, evoked_proj.ch_names)[0] + evoked_proj.add_proj(p) + filters_proj = make_dics(evoked_proj.info, fwd_surf, csd20, label=label) + assert_allclose(filters_proj["proj"], proj_matrix, rtol=1e-7) + stc_proj = apply_dics(evoked_proj, filters_proj) + assert np.any(np.not_equal(stc_noproj.data, stc_proj.data)) + + # Test detecting incompatible projections + filters_proj["proj"] = filters_proj["proj"][:-1, :-1] + with pytest.raises(ValueError, match="operands could not be broadcast"): + apply_dics(evoked_proj, filters_proj) + + # Test returning a generator + stcs = apply_dics_epochs(epochs, filters, return_generator=False) + stcs_gen = apply_dics_epochs(epochs, filters, return_generator=True) + assert_array_equal(stcs[0].data, next(stcs_gen).data) + + # Test computing timecourses on a volume source space + filters_vol = make_dics(evoked.info, fwd_vol, csd20, reg=reg, inversion="single") + stc = apply_dics(evoked, filters_vol) + stc = (stc**2).mean() + assert stc.data.shape[1] == 1 + vol_source_ind = _nearest_vol_ind(fwd_vol, fwd_surf, vertices, source_ind) + dist = _fwd_dist(stc, fwd_vol, fwd_vol["src"][0]["vertno"], vol_source_ind, tidx=0) + vol_tols = {100: 0.008, 200: 0.015} + vol_tol = vol_tols.get(idx, 0.0) + assert dist <= vol_tol + + # check whether a filters object without src_type throws expected warning + del filters_vol["src_type"] # emulate 0.16 behaviour to cause warning + with pytest.warns(RuntimeWarning, match="filter does not contain src_typ"): + apply_dics_epochs(epochs, filters_vol) + + +@pytest.mark.slowtest +@testing.requires_testing_data +@pytest.mark.parametrize("return_generator", (True, False)) +def test_apply_dics_tfr(return_generator): + """Test DICS applied to time-frequency objects.""" + info = read_info(fname_raw) + info = pick_info(info, pick_types(info, meg="grad")) + forward = mne.read_forward_solution(fname_fwd) + rng = np.random.default_rng(11) + + # Construct an EpochsTFR object filled with random data. + n_epochs = 8 + n_chans = len(info.ch_names) + freqs = [8, 9] + n_times = 300 + times = np.arange(n_times) / info["sfreq"] + data = rng.random((n_epochs, n_chans, len(freqs), n_times)) + data *= 1e-6 + data = data + data * 1j # add imag. component to simulate phase + epochs_tfr = EpochsTFRArray(info=info, data=data, times=times, freqs=freqs) + + # Create a DICS beamformer and convert the EpochsTFR to source space. + csd = csd_tfr(epochs_tfr) + filters = make_dics(epochs_tfr.info, forward, csd, reg=0.05) + stcs = apply_dics_tfr_epochs(epochs_tfr, filters, return_generator) + + # Check some basic properties of the returned SourceEstimate objects. + if return_generator: + stcs = list(stcs) + assert_allclose(stcs[0][0].times, times) + assert len(stcs) == len(epochs_tfr) # check same number of epochs + assert all([len(s) == len(freqs) for s in stcs]) # check nested freqs + assert all( + [ + s.data.shape == (forward["nsource"], n_times) + for these_stcs in stcs + for s in these_stcs + ] + ) + + # Compute power from the source space TFR. This should yield the same + # result as the apply_dics_csd function. + source_power = np.zeros((forward["nsource"], len(freqs))) + for stcs_epoch in stcs: + for i, stc_freq in enumerate(stcs_epoch): + power = (stc_freq.data * np.conj(stc_freq.data)).real + power = power.mean(axis=-1) # mean over time + # Scaling by sampling frequency for compatibility with Matlab + power /= epochs_tfr.info["sfreq"] + source_power[:, i] += power.T + source_power /= n_epochs + + ref_source_power, ref_freqs = apply_dics_csd(csd, filters) + assert_allclose(freqs, ref_freqs) + assert_allclose(ref_source_power.data, source_power) + + # Test that real-value only data fails, due to non-linearity of computing + # power, it is recommended to transform to source-space first before + # converting to power. + with pytest.raises(RuntimeError, match="Time-frequency data must be complex"): + epochs_tfr_real = epochs_tfr.copy() + epochs_tfr_real.data = epochs_tfr_real.data.real + stcs = apply_dics_tfr_epochs(epochs_tfr_real, filters) + + filters_vector = filters.copy() + filters_vector["pick_ori"] = "vector" + with pytest.warns(match="vector solution"): + apply_dics_tfr_epochs(epochs_tfr, filters_vector) + + +def _cov_as_csd(cov, info): + rng = np.random.RandomState(0) + assert cov["data"].ndim == 2 + assert len(cov["data"]) == len(cov["names"]) + # we need to make this have at least some complex structure + data = cov["data"] + 1e-1 * _rand_csd(rng, info) + assert data.dtype == np.complex128 + return CrossSpectralDensity(_sym_mat_to_vector(data), cov["names"], 0.0, 16) + + +# Just test free ori here (assume fixed is same as LCMV if these are) +# Changes here should be synced with test_lcmv.py +@pytest.mark.slowtest +@pytest.mark.parametrize( + "reg, pick_ori, weight_norm, use_cov, depth, lower, upper, real_filter", + [ + (0.05, "vector", "unit-noise-gain-invariant", False, None, 26, 28, True), + (0.05, "vector", "unit-noise-gain", False, None, 13, 15, True), + (0.05, "vector", "nai", False, None, 13, 15, True), + (0.05, None, "unit-noise-gain-invariant", False, None, 26, 28, False), + (0.05, None, "unit-noise-gain-invariant", True, None, 40, 42, False), + (0.05, None, "unit-noise-gain-invariant", True, None, 40, 42, True), + (0.05, None, "unit-noise-gain", False, None, 13, 14, False), + (0.05, None, "unit-noise-gain", True, None, 35, 37, False), + (0.05, None, "nai", True, None, 35, 37, False), + (0.05, None, None, True, None, 12, 14, False), + (0.05, None, None, True, 0.8, 39, 43, False), + (0.05, "max-power", "unit-noise-gain-invariant", False, None, 17, 20, False), + (0.05, "max-power", "unit-noise-gain", False, None, 17, 20, False), + (0.05, "max-power", "unit-noise-gain", False, None, 17, 20, True), + (0.05, "max-power", "nai", True, None, 21, 24, False), + (0.05, "max-power", None, True, None, 7, 10, False), + (0.05, "max-power", None, True, 0.8, 15, 18, False), + # skip most no-reg tests, assume others are equal to LCMV if these are + (0.00, None, None, True, None, 21, 32, False), + (0.00, "max-power", None, True, None, 13, 19, False), + ], +) +def test_localization_bias_free( + bias_params_free, + reg, + pick_ori, + weight_norm, + use_cov, + depth, + lower, + upper, + real_filter, +): + """Test localization bias for free-orientation DICS.""" + evoked, fwd, noise_cov, data_cov, want = bias_params_free + noise_csd = _cov_as_csd(noise_cov, evoked.info) + data_csd = _cov_as_csd(data_cov, evoked.info) + del noise_cov, data_cov + if not use_cov: + evoked.pick(picks="grad") + noise_csd = None + filters = make_dics( + evoked.info, + fwd, + data_csd, + reg, + noise_csd, + pick_ori=pick_ori, + weight_norm=weight_norm, + depth=depth, + real_filter=real_filter, + ) + loc = apply_dics(evoked, filters).data + loc = np.linalg.norm(loc, axis=1) if pick_ori == "vector" else np.abs(loc) + # Compute the percentage of sources for which there is no loc bias: + perc = (want == np.argmax(loc, axis=0)).mean() * 100 + assert lower <= perc <= upper + + +@pytest.mark.slowtest +@pytest.mark.parametrize( + "weight_norm, lower, upper, lower_ori, upper_ori, real_filter", + [ + ("unit-noise-gain-invariant", 57, 58, 0.60, 0.61, False), + ("unit-noise-gain", 57, 58, 0.60, 0.61, False), + ("unit-noise-gain", 57, 58, 0.60, 0.61, True), + (None, 27, 28, 0.56, 0.57, False), + ], +) +def test_orientation_max_power( + bias_params_fixed, + bias_params_free, + weight_norm, + lower, + upper, + lower_ori, + upper_ori, + real_filter, +): + """Test orientation selection for bias for max-power DICS.""" + # we simulate data for the fixed orientation forward and beamform using + # the free orientation forward, and check the orientation match at the end + evoked, _, noise_cov, data_cov, want = bias_params_fixed + noise_csd = _cov_as_csd(noise_cov, evoked.info) + data_csd = _cov_as_csd(data_cov, evoked.info) + del data_cov, noise_cov + fwd = bias_params_free[1] + filters = make_dics( + evoked.info, + fwd, + data_csd, + 0.05, + noise_csd, + pick_ori="max-power", + weight_norm=weight_norm, + depth=None, + real_filter=real_filter, + ) + loc = np.abs(apply_dics(evoked, filters).data) + ori = filters["max_power_ori"][0] + assert ori.shape == (246, 3) + loc = np.abs(loc) + # Compute the percentage of sources for which there is no loc bias: + max_idx = np.argmax(loc, axis=0) + mask = want == max_idx # ones that localized properly + perc = mask.mean() * 100 + assert lower <= perc <= upper + # Compute the dot products of our forward normals and + # assert we get some hopefully reasonable agreement + assert fwd["coord_frame"] == FIFF.FIFFV_COORD_HEAD + nn = np.concatenate([s["nn"][v] for s, v in zip(fwd["src"], filters["vertices"])]) + nn = nn[want] + nn = apply_trans(invert_transform(fwd["mri_head_t"]), nn, move=False) + assert_allclose(np.linalg.norm(nn, axis=1), 1, atol=1e-6) + assert_allclose(np.linalg.norm(ori, axis=1), 1, atol=1e-12) + dots = np.abs((nn[mask] * ori[mask]).sum(-1)) + assert_array_less(dots, 1) + assert_array_less(0, dots) + got = np.mean(dots) + assert lower_ori < got < upper_ori + + +@testing.requires_testing_data +@idx_param +@pytest.mark.parametrize("whiten", (False, True)) +def test_make_dics_rank(_load_forward, idx, whiten): + """Test making DICS beamformer filters with rank param.""" + _, fwd_surf, fwd_fixed, _ = _load_forward + epochs, _, csd, _, label, _, _ = _simulate_data(fwd_fixed, idx) + if whiten: + noise_csd, want_rank = _make_rand_csd(epochs.info, csd) + kind = "mag + grad" + else: + noise_csd = None + epochs.pick(picks="grad") + want_rank = len(epochs.ch_names) + assert want_rank == 41 + kind = "grad" + + with catch_logging() as log: + filters = make_dics( + epochs.info, fwd_surf, csd, label=label, noise_csd=noise_csd, verbose=True + ) + log = log.getvalue() + assert f"Estimated rank ({kind}): {want_rank}" in log, log + stc, _ = apply_dics_csd(csd, filters) + other_rank = want_rank - 1 # shouldn't make a huge difference + use_rank = dict(meg=other_rank) + if not whiten: + # XXX it's a bug that our rank functions don't treat "meg" + # properly here... + use_rank["grad"] = use_rank.pop("meg") + with catch_logging() as log: + filters_2 = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + noise_csd=noise_csd, + rank=use_rank, + verbose=True, + ) + log = log.getvalue() + assert f"Computing rank from covariance with rank={use_rank}" in log, log + stc_2, _ = apply_dics_csd(csd, filters_2) + corr = np.corrcoef(stc_2.data.ravel(), stc.data.ravel())[0, 1] + assert 0.8 < corr < 0.999999 + + # degenerate conditions + if whiten: + # make rank deficient + data = noise_csd.get_data(0.0) + data[0] = data[:0] = 0 + noise_csd._data[:, 0] = _sym_mat_to_vector(data) + with pytest.raises(ValueError, match="meg data rank.*the noise rank"): + filters = make_dics( + epochs.info, + fwd_surf, + csd, + label=label, + noise_csd=noise_csd, + verbose=True, + ) diff --git a/mne-python/source/mne/beamformer/tests/test_external.py b/mne-python/source/mne/beamformer/tests/test_external.py new file mode 100644 index 0000000000000000000000000000000000000000..8fcb09e870eea803369b4d88e1821941ff53a564 --- /dev/null +++ b/mne-python/source/mne/beamformer/tests/test_external.py @@ -0,0 +1,117 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_equal +from scipy.io import savemat + +import mne +from mne.beamformer import apply_lcmv, apply_lcmv_cov, make_lcmv +from mne.beamformer.tests.test_lcmv import _get_data +from mne.datasets import testing +from mne.fixes import _reshape_view + +data_path = testing.data_path(download=False) +ft_data_path = data_path / "fieldtrip" / "beamformer" +fname_raw = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw.fif" +fname_cov = data_path / "MEG" / "sample" / "sample_audvis_trunc-cov.fif" +fname_fwd = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" +fname_fwd_vol = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-vol-7-fwd.fif" +fname_event = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw-eve.fif" +fname_label = data_path / "MEG" / "sample" / "labels" / "Aud-lh.label" + +reject = dict(grad=4000e-13, mag=4e-12) + + +@pytest.fixture(scope="function", params=[testing._pytest_param()]) +def _get_bf_data(save_fieldtrip=False): + raw, epochs, evoked, data_cov, _, _, _, _, _, fwd = _get_data(proj=False) + + if save_fieldtrip is True: + # raw needs to be saved with all channels and picked in FieldTrip + raw.save(ft_data_path / "raw.fif", overwrite=True) + + # src (tris are not available in fwd['src'] once imported into MATLAB) + src = fwd["src"].copy() + mne.write_source_spaces( + ft_data_path / "src.fif", src, verbose="error", overwrite=True + ) + + # pick gradiometers only: + epochs.pick(picks="grad") + evoked.pick(picks="grad") + + # compute covariance matrix (ignore false alarm about no baseline) + data_cov = mne.compute_covariance( + epochs, tmin=0.04, tmax=0.145, method="empirical", verbose="error" + ) + + if save_fieldtrip is True: + # if the covariance matrix and epochs need resaving: + # data covariance: + cov_savepath = ft_data_path / "sample_cov.mat" + sample_cov = {"sample_cov": data_cov["data"]} + savemat(cov_savepath, sample_cov) + # evoked data: + ev_savepath = ft_data_path / "sample_evoked.mat" + data_ev = {"sample_evoked": evoked.data} + savemat(ev_savepath, data_ev) + + return evoked, data_cov, fwd + + +# beamformer types to be tested: unit-gain (vector and scalar) and +# unit-noise-gain (time series and power output [apply_lcmv_cov]) +@pytest.mark.parametrize( + "bf_type, weight_norm, pick_ori, pwr", + [ + ["ug_scal", None, "max-power", False], + ["ung", "unit-noise-gain", "max-power", False], + ["ung_pow", "unit-noise-gain", "max-power", True], + ["ug_vec", None, "vector", False], + ["ung_vec", "unit-noise-gain", "vector", False], + ], +) +def test_lcmv_fieldtrip(_get_bf_data, bf_type, weight_norm, pick_ori, pwr): + """Test LCMV vs fieldtrip output.""" + pymatreader = pytest.importorskip("pymatreader") + + evoked, data_cov, fwd = _get_bf_data + + # run the MNE-Python beamformer + filters = make_lcmv( + evoked.info, + fwd, + data_cov=data_cov, + noise_cov=None, + pick_ori=pick_ori, + reg=0.05, + weight_norm=weight_norm, + ) + if pwr: + stc_mne = apply_lcmv_cov(data_cov, filters) + else: + stc_mne = apply_lcmv(evoked, filters) + + # load the FieldTrip output + ft_fname = ft_data_path / ("ft_source_" + bf_type + "-vol.mat") + stc_ft_data = pymatreader.read_mat(ft_fname)["stc"] + if stc_ft_data.ndim == 1: + stc_ft_data = _reshape_view(stc_ft_data, (stc_ft_data.size, 1)) + + if stc_mne.data.ndim == 2: + signs = np.sign((stc_mne.data * stc_ft_data).sum(-1, keepdims=True)) + if pwr: + assert_array_equal(signs, 1.0) + stc_mne.data *= signs + assert stc_ft_data.shape == stc_mne.data.shape + if pick_ori == "vector": + # compare norms first + assert_allclose( + np.linalg.norm(stc_mne.data, axis=1), + np.linalg.norm(stc_ft_data, axis=1), + rtol=1e-6, + ) + assert_allclose(stc_mne.data, stc_ft_data, rtol=1e-6) diff --git a/mne-python/source/mne/beamformer/tests/test_lcmv.py b/mne-python/source/mne/beamformer/tests/test_lcmv.py new file mode 100644 index 0000000000000000000000000000000000000000..1e0443a48f32f6cd7daacc03856b738c2d77a486 --- /dev/null +++ b/mne-python/source/mne/beamformer/tests/test_lcmv.py @@ -0,0 +1,1267 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from contextlib import nullcontext +from copy import deepcopy +from inspect import signature + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_array_less, +) +from scipy import linalg +from scipy.spatial.distance import cdist + +import mne +from mne import ( + EvokedArray, + VolSourceEstimate, + VolVectorSourceEstimate, + compute_rank, + convert_forward_solution, + pick_channels_cov, + read_forward_solution, + read_vectorview_selection, +) +from mne._fiff.compensator import set_current_comp +from mne._fiff.constants import FIFF +from mne.beamformer import ( + Beamformer, + apply_lcmv, + apply_lcmv_cov, + apply_lcmv_epochs, + apply_lcmv_raw, + make_dics, + make_lcmv, + read_beamformer, +) +from mne.beamformer._compute_beamformer import _prepare_beamformer_input +from mne.datasets import testing +from mne.fixes import _reshape_view +from mne.minimum_norm import apply_inverse, make_inverse_operator +from mne.minimum_norm.tests.test_inverse import _assert_free_ori_match +from mne.simulation import simulate_evoked +from mne.transforms import apply_trans, invert_transform +from mne.utils import _record_warnings, catch_logging, object_diff + +data_path = testing.data_path(download=False) +fname_raw = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw.fif" +fname_cov = data_path / "MEG" / "sample" / "sample_audvis_trunc-cov.fif" +fname_fwd = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" +fname_fwd_vol = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-vol-7-fwd.fif" +fname_event = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw-eve.fif" +fname_label = data_path / "MEG" / "sample" / "labels" / "Aud-lh.label" +ctf_fname = data_path / "CTF" / "somMDYO-18av.ds" + +reject = dict(grad=4000e-13, mag=4e-12) + + +def _read_forward_solution_meg(*args, **kwargs): + fwd = read_forward_solution(*args) + fwd = convert_forward_solution(fwd, **kwargs) + return mne.pick_types_forward(fwd, meg=True, eeg=False) + + +def _get_data( + tmin=-0.1, + tmax=0.15, + all_forward=True, + epochs=True, + epochs_preload=True, + data_cov=True, + proj=True, +): + """Read in data used in tests.""" + label = mne.read_label(fname_label) + events = mne.read_events(fname_event) + raw = mne.io.read_raw_fif(fname_raw, preload=True) + forward = mne.read_forward_solution(fname_fwd) + if all_forward: + forward_surf_ori = _read_forward_solution_meg(fname_fwd, surf_ori=True) + forward_fixed = _read_forward_solution_meg( + fname_fwd, force_fixed=True, surf_ori=True, use_cps=False + ) + forward_vol = _read_forward_solution_meg(fname_fwd_vol) + else: + forward_surf_ori = None + forward_fixed = None + forward_vol = None + + event_id, tmin, tmax = 1, tmin, tmax + + # Setup for reading the raw data + raw.info["bads"] = ["MEG 2443", "EEG 053"] # 2 bad channels + # Set up pick list: MEG - bad channels + left_temporal_channels = read_vectorview_selection("Left-temporal") + picks = mne.pick_types(raw.info, meg=True, selection=left_temporal_channels) + picks = picks[::2] # decimate for speed + # add a couple channels we will consider bad + bad_picks = [100, 101] + bads = [raw.ch_names[pick] for pick in bad_picks] + assert not any(pick in picks for pick in bad_picks) + picks = np.concatenate([picks, bad_picks]) + raw.pick([raw.ch_names[ii] for ii in picks]) + del picks + + raw.info["bads"] = bads # add more bads + if proj: + raw.info.normalize_proj() # avoid projection warnings + else: + raw.del_proj() + + if epochs: + # Read epochs + epochs = mne.Epochs( + raw, + events, + event_id, + tmin, + tmax, + proj=True, + baseline=(None, 0), + preload=epochs_preload, + reject=reject, + ) + if epochs_preload: + epochs.resample(200, npad=0) + epochs.crop(0, None) + evoked = epochs.average() + info = evoked.info + else: + epochs = None + evoked = None + info = raw.info + + noise_cov = mne.read_cov(fname_cov) + noise_cov["projs"] = [] # avoid warning + noise_cov = mne.cov.regularize( + noise_cov, info, mag=0.05, grad=0.05, eeg=0.1, proj=True, rank=None + ) + if data_cov: + data_cov = mne.compute_covariance( + epochs, tmin=0.04, tmax=0.145, verbose="error" + ) # baseline warning + else: + data_cov = None + + return ( + raw, + epochs, + evoked, + data_cov, + noise_cov, + label, + forward, + forward_surf_ori, + forward_fixed, + forward_vol, + ) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_lcmv_vector(): + """Test vector LCMV solutions.""" + info = mne.io.read_raw_fif(fname_raw).info + + # For speed and for rank-deficiency calculation simplicity, + # just use grads + info = mne.pick_info(info, mne.pick_types(info, meg="grad", exclude=())) + with info._unlock(): + info.update(bads=[], projs=[]) + + forward = mne.read_forward_solution(fname_fwd) + forward = mne.pick_channels_forward(forward, info["ch_names"]) + vertices = [s["vertno"][::200] for s in forward["src"]] + n_vertices = sum(len(v) for v in vertices) + assert n_vertices == 4 + + amplitude = 100e-9 + stc = mne.SourceEstimate( + amplitude * np.eye(n_vertices), vertices, 0, 1.0 / info["sfreq"] + ) + forward_sim = mne.convert_forward_solution( + forward, force_fixed=True, use_cps=True, copy=True + ) + forward_sim = mne.forward.restrict_forward_to_stc(forward_sim, stc) + noise_cov = mne.make_ad_hoc_cov(info) + noise_cov.update(data=np.diag(noise_cov["data"]), diag=False) + evoked = simulate_evoked(forward_sim, stc, info, noise_cov, nave=1) + source_nn = forward_sim["source_nn"] + source_rr = forward_sim["source_rr"] + + # Figure out our indices + mask = np.concatenate( + [np.isin(s["vertno"], v) for s, v in zip(forward["src"], vertices)] + ) + mapping = np.where(mask)[0] + assert_array_equal(source_rr, forward["source_rr"][mapping]) + + # Don't check NN because we didn't rotate to surf ori + del forward_sim + + # Let's do minimum norm as a sanity check (dipole_fit is slower) + inv = make_inverse_operator(info, forward, noise_cov, loose=1.0) + stc_vector_mne = apply_inverse(evoked, inv, pick_ori="vector") + mne_ori = stc_vector_mne.data[mapping, :, np.arange(n_vertices)] + mne_ori /= np.linalg.norm(mne_ori, axis=-1)[:, np.newaxis] + mne_angles = np.rad2deg(np.arccos(np.sum(mne_ori * source_nn, axis=-1))) + assert np.mean(mne_angles) < 36 + + # Now let's do LCMV + data_cov = mne.make_ad_hoc_cov(info) # just a stub for later + with pytest.raises(ValueError, match="pick_ori"): + make_lcmv(info, forward, data_cov, 0.05, noise_cov, pick_ori="bad") + + lcmv_ori = list() + for ti in range(n_vertices): + this_evoked = evoked.copy().crop(evoked.times[ti], evoked.times[ti]) + data_cov["diag"] = False + data_cov["data"] = ( + np.outer(this_evoked.data, this_evoked.data) + noise_cov["data"] + ) + vals = linalg.svdvals(data_cov["data"]) + assert vals[0] / vals[-1] < 1e5 # not rank deficient + + with catch_logging() as log: + filters = make_lcmv(info, forward, data_cov, 0.05, noise_cov, verbose=True) + log = log.getvalue() + assert "498 sources" in log + with catch_logging() as log: + filters_vector = make_lcmv( + info, + forward, + data_cov, + 0.05, + noise_cov, + pick_ori="vector", + verbose=True, + ) + log = log.getvalue() + assert "498 sources" in log + stc = apply_lcmv(this_evoked, filters) + stc_vector = apply_lcmv(this_evoked, filters_vector) + assert isinstance(stc, mne.SourceEstimate) + assert isinstance(stc_vector, mne.VectorSourceEstimate) + assert_allclose(stc.data, stc_vector.magnitude().data) + + # Check the orientation by pooling across some neighbors, as LCMV can + # have some "holes" at the points of interest + idx = np.where(cdist(forward["source_rr"], source_rr[[ti]]) < 0.02)[0] + lcmv_ori.append(np.mean(stc_vector.data[idx, :, 0], axis=0)) + lcmv_ori[-1] /= np.linalg.norm(lcmv_ori[-1]) + + lcmv_angles = np.rad2deg(np.arccos(np.sum(lcmv_ori * source_nn, axis=-1))) + assert np.mean(lcmv_angles) < 55 + + +@pytest.mark.slowtest +@testing.requires_testing_data +@pytest.mark.parametrize( + "reg, proj, kind", + [ + (0.01, True, "volume"), + (0.0, False, "volume"), + (0.01, False, "surface"), + (0.0, True, "surface"), + ], +) +def test_make_lcmv_bem(tmp_path, reg, proj, kind): + """Test LCMV with evoked data and single trials.""" + pytest.importorskip("h5io") + ( + raw, + epochs, + evoked, + data_cov, + noise_cov, + label, + forward, + forward_surf_ori, + forward_fixed, + forward_vol, + ) = _get_data(proj=proj) + + if kind == "surface": + fwd = forward + else: + fwd = forward_vol + assert kind == "volume" + + filters = make_lcmv(evoked.info, fwd, data_cov, reg=reg, noise_cov=noise_cov) + stc = apply_lcmv(evoked, filters) + stc.crop(0.02, None) + + # Smoke test for label= support for surfaces only + label = mne.read_label(fname_label) + if kind == "volume": + ctx = pytest.raises(ValueError, match="volume source space") + else: + ctx = nullcontext() + with ctx: + make_lcmv(evoked.info, fwd, data_cov, reg=reg, noise_cov=noise_cov, label=label) + + stc_pow = np.sum(np.abs(stc.data), axis=1) + idx = np.argmax(stc_pow) + max_stc = stc.data[idx] + tmax = stc.times[np.argmax(max_stc)] + + assert 0.08 < tmax < 0.15, tmax + assert 0.9 < np.max(max_stc) < 3.5, np.max(max_stc) + + if kind == "surface": + # Test picking normal orientation (surface source space only). + filters = make_lcmv( + evoked.info, + forward_surf_ori, + data_cov, + reg=reg, + noise_cov=noise_cov, + pick_ori="normal", + weight_norm=None, + ) + stc_normal = apply_lcmv(evoked, filters) + stc_normal.crop(0.02, None) + + stc_pow = np.sum(np.abs(stc_normal.data), axis=1) + idx = np.argmax(stc_pow) + max_stc = stc_normal.data[idx] + tmax = stc_normal.times[np.argmax(max_stc)] + + lower = 0.04 if proj else 0.025 + assert lower < tmax < 0.14, tmax + lower = 3e-7 if proj else 2e-7 + assert lower < np.max(max_stc) < 3e-6, np.max(max_stc) + + # No weight normalization was applied, so the amplitude of normal + # orientation results should always be smaller than free + # orientation results. + assert (np.abs(stc_normal.data) <= stc.data).all() + + # Test picking source orientation maximizing output source power + filters = make_lcmv( + evoked.info, fwd, data_cov, reg=reg, noise_cov=noise_cov, pick_ori="max-power" + ) + stc_max_power = apply_lcmv(evoked, filters) + stc_max_power.crop(0.02, None) + stc_pow = np.sum(np.abs(stc_max_power.data), axis=1) + idx = np.argmax(stc_pow) + max_stc = np.abs(stc_max_power.data[idx]) + tmax = stc.times[np.argmax(max_stc)] + + lower = 0.08 if proj else 0.04 + assert lower < tmax < 0.15, tmax + assert 0.8 < np.max(max_stc) < 3.0, np.max(max_stc) + + stc_max_power.data[:, :] = np.abs(stc_max_power.data) + + if kind == "surface": + # Maximum output source power orientation results should be + # similar to free orientation results in areas with channel + # coverage + label = mne.read_label(fname_label) + mean_stc = stc.extract_label_time_course(label, fwd["src"], mode="mean") + mean_stc_max_pow = stc_max_power.extract_label_time_course( + label, fwd["src"], mode="mean" + ) + assert_array_less(np.abs(mean_stc - mean_stc_max_pow), 1.0) + + # Test if spatial filter contains src_type + assert filters["src_type"] == kind + + # __repr__ + assert len(evoked.ch_names) == 22 + assert len(evoked.info["projs"]) == (3 if proj else 0) + assert len(evoked.info["bads"]) == 2 + rank = 17 if proj else 20 + assert "LCMV" in repr(filters) + assert "unknown subject" not in repr(filters) + assert f"{fwd['nsource']} vert" in repr(filters) + assert "20 ch" in repr(filters) + assert f"rank {rank}" in repr(filters) + + # I/O + fname = tmp_path / "filters.h5" + with pytest.warns(RuntimeWarning, match="-lcmv.h5"): + filters.save(fname) + filters_read = read_beamformer(fname) + assert isinstance(filters, Beamformer) + assert isinstance(filters_read, Beamformer) + # deal with object_diff strictness + filters_read["rank"] = int(filters_read["rank"]) + filters["rank"] = int(filters["rank"]) + assert object_diff(filters, filters_read) == "" + + if kind != "surface": + return + + # Test if fixed forward operator is detected when picking normal or + # max-power orientation + pytest.raises( + ValueError, + make_lcmv, + evoked.info, + forward_fixed, + data_cov, + reg=0.01, + noise_cov=noise_cov, + pick_ori="normal", + ) + pytest.raises( + ValueError, + make_lcmv, + evoked.info, + forward_fixed, + data_cov, + reg=0.01, + noise_cov=noise_cov, + pick_ori="max-power", + ) + + # Test if non-surface oriented forward operator is detected when picking + # normal orientation + pytest.raises( + ValueError, + make_lcmv, + evoked.info, + forward, + data_cov, + reg=0.01, + noise_cov=noise_cov, + pick_ori="normal", + ) + + # Test if volume forward operator is detected when picking normal + # orientation + pytest.raises( + ValueError, + make_lcmv, + evoked.info, + forward_vol, + data_cov, + reg=0.01, + noise_cov=noise_cov, + pick_ori="normal", + ) + + # Test if missing of noise covariance matrix is detected when more than + # one channel type is present in the data + pytest.raises( + ValueError, + make_lcmv, + evoked.info, + forward_vol, + data_cov=data_cov, + reg=0.01, + noise_cov=None, + pick_ori="max-power", + ) + + # Test if wrong channel selection is detected in application of filter + evoked_ch = deepcopy(evoked) + evoked_ch.pick(evoked_ch.ch_names[1:]) + filters = make_lcmv( + evoked.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov + ) + + # Test if discrepancies in channel selection of data and fwd model are + # handled correctly in apply_lcmv + # make filter with data where first channel was removed + filters = make_lcmv( + evoked_ch.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov + ) + # applying that filter to the full data set should automatically exclude + # this channel from the data + # also test here that no warnings are thrown - implemented to check whether + # src should not be None warning occurs + stc = apply_lcmv(evoked, filters) + + # the result should be equal to applying this filter to a dataset without + # this channel: + stc_ch = apply_lcmv(evoked_ch, filters) + assert_array_almost_equal(stc.data, stc_ch.data) + + # Test if non-matching SSP projection is detected in application of filter + if proj: + raw_proj = raw.copy().del_proj() + with pytest.raises(ValueError, match="do not match the projections"): + apply_lcmv_raw(raw_proj, filters) + + # Test apply_lcmv_raw + use_raw = raw.copy().crop(0, 1) + stc = apply_lcmv_raw(use_raw, filters) + assert_allclose(stc.times, use_raw.times) + assert_array_equal(stc.vertices[0], forward_vol["src"][0]["vertno"]) + + # Test if spatial filter contains src_type + assert "src_type" in filters + + # check whether a filters object without src_type throws expected warning + del filters["src_type"] # emulate 0.16 behaviour to cause warning + with pytest.warns(RuntimeWarning, match="spatial filter does not contain src_type"): + apply_lcmv(evoked, filters) + + # Now test single trial using fixed orientation forward solution + # so we can compare it to the evoked solution + filters = make_lcmv( + epochs.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov + ) + stcs = apply_lcmv_epochs(epochs, filters) + stcs_ = apply_lcmv_epochs(epochs, filters, return_generator=True) + assert_array_equal(stcs[0].data, next(stcs_).data) + + epochs.drop_bad() + assert len(epochs.events) == len(stcs) + + # average the single trial estimates + stc_avg = np.zeros_like(stcs[0].data) + for this_stc in stcs: + stc_avg += this_stc.data + stc_avg /= len(stcs) + + # compare it to the solution using evoked with fixed orientation + filters = make_lcmv( + evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov + ) + stc_fixed = apply_lcmv(evoked, filters) + assert_array_almost_equal(stc_avg, stc_fixed.data) + + # use a label so we have few source vertices and delayed computation is + # not used + filters = make_lcmv( + epochs.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, label=label + ) + stcs_label = apply_lcmv_epochs(epochs, filters) + + assert_array_almost_equal(stcs_label[0].data, stcs[0].in_label(label).data) + + # Test condition where the filters weights are zero. There should not be + # any divide-by-zero errors + zero_cov = data_cov.copy() + zero_cov["data"][:] = 0 + filters = make_lcmv( + epochs.info, forward_fixed, zero_cov, reg=0.01, noise_cov=noise_cov + ) + assert_array_equal(filters["weights"], 0) + + # Test condition where one channel type is picked + # (avoid "grad data rank (13) did not match the noise rank (None)") + data_cov_grad = pick_channels_cov( + data_cov, + [ + ch_name + for ch_name in epochs.info["ch_names"] + if ch_name.endswith(("2", "3")) + ], + ordered=False, + ) + assert len(data_cov_grad["names"]) > 4 + make_lcmv(epochs.info, forward_fixed, data_cov_grad, reg=0.01, noise_cov=noise_cov) + + +@testing.requires_testing_data +@pytest.mark.slowtest +@pytest.mark.parametrize( + "weight_norm, pick_ori", + [ + ("unit-noise-gain", "max-power"), + ("unit-noise-gain", "vector"), + ("unit-noise-gain", None), + ("nai", "vector"), + (None, "max-power"), + ], +) +def test_make_lcmv_sphere(pick_ori, weight_norm): + """Test LCMV with sphere head model.""" + # unit-noise gain beamformer and orientation + # selection and rank reduction of the leadfield + _, _, evoked, data_cov, noise_cov, _, _, _, _, _ = _get_data(proj=True) + assert "eeg" not in evoked + assert "meg" in evoked + sphere = mne.make_sphere_model(r0=(0.0, 0.0, 0.0), head_radius=0.080) + src = mne.setup_volume_source_space( + pos=25.0, sphere=sphere, mindist=5.0, exclude=2.0 + ) + fwd_sphere = mne.make_forward_solution(evoked.info, None, src, sphere) + + # Test that we get an error if not reducing rank + with ( + pytest.raises(ValueError, match="Singular matrix detected"), + _record_warnings(), + pytest.warns(RuntimeWarning, match="positive semidefinite"), + ): + make_lcmv( + evoked.info, + fwd_sphere, + data_cov, + reg=0.1, + noise_cov=noise_cov, + weight_norm=weight_norm, + pick_ori=pick_ori, + reduce_rank=False, + rank="full", + ) + + # Now let's reduce it + filters = make_lcmv( + evoked.info, + fwd_sphere, + data_cov, + reg=0.1, + noise_cov=noise_cov, + weight_norm=weight_norm, + pick_ori=pick_ori, + reduce_rank=True, + ) + stc_sphere = apply_lcmv(evoked, filters) + if isinstance(stc_sphere, VolVectorSourceEstimate): + stc_sphere = stc_sphere.magnitude() + else: + stc_sphere = abs(stc_sphere) + assert isinstance(stc_sphere, VolSourceEstimate) + stc_sphere.crop(0.02, None) + + stc_pow = np.sum(stc_sphere.data, axis=1) + idx = np.argmax(stc_pow) + max_stc = stc_sphere.data[idx] + tmax = stc_sphere.times[np.argmax(max_stc)] + assert 0.08 < tmax < 0.15, tmax + min_, max_ = 1.0, 4.5 + if weight_norm is None: + min_ *= 2e-7 + max_ *= 2e-7 + assert min_ < np.max(max_stc) < max_, (min_, np.max(max_stc), max_) + + +@testing.requires_testing_data +@pytest.mark.parametrize("weight_norm", (None, "unit-noise-gain")) +@pytest.mark.parametrize("pick_ori", ("max-power", "normal")) +def test_lcmv_cov(weight_norm, pick_ori): + """Test LCMV source power computation.""" + ( + raw, + epochs, + evoked, + data_cov, + noise_cov, + label, + forward, + forward_surf_ori, + forward_fixed, + forward_vol, + ) = _get_data() + convert_forward_solution(forward, surf_ori=True, copy=False) + filters = make_lcmv( + evoked.info, + forward, + data_cov, + noise_cov=noise_cov, + weight_norm=weight_norm, + pick_ori=pick_ori, + ) + for cov in (data_cov, noise_cov): + this_cov = pick_channels_cov(cov, evoked.ch_names, ordered=False) + this_evoked = evoked.copy().pick(this_cov["names"]) + this_cov["projs"] = this_evoked.info["projs"] + assert this_evoked.ch_names == this_cov["names"] + stc = apply_lcmv_cov(this_cov, filters) + assert stc.data.min() > 0 + assert stc.shape == (498, 1) + ev = EvokedArray(this_cov.data, this_evoked.info) + stc_1 = apply_lcmv(ev, filters) + assert stc_1.data.min() < 0 + ev = EvokedArray(stc_1.data.T, this_evoked.info) + stc_2 = apply_lcmv(ev, filters) + assert stc_2.data.shape == (498, 498) + data = np.diag(stc_2.data)[:, np.newaxis] + assert data.min() > 0 + assert_allclose(data, stc.data, rtol=1e-12) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_lcmv_ctf_comp(): + """Test interpolation with compensated CTF data.""" + raw = mne.io.read_raw_ctf(ctf_fname, preload=True) + raw.pick(raw.ch_names[:70]) + + events = mne.make_fixed_length_events(raw, duration=0.2)[:2] + epochs = mne.Epochs(raw, events, tmin=-0.1, tmax=0.2) + evoked = epochs.average() + + data_cov = mne.compute_covariance(epochs) + fwd = mne.make_forward_solution( + evoked.info, + None, + mne.setup_volume_source_space(pos=30.0), + mne.make_sphere_model(), + ) + with pytest.raises(ValueError, match="reduce_rank"): + make_lcmv(evoked.info, fwd, data_cov) + filters = make_lcmv(evoked.info, fwd, data_cov, reduce_rank=True) + assert "weights" in filters + + # test whether different compensations throw error + info_comp = evoked.info.copy() + set_current_comp(info_comp, 1) + with pytest.raises(RuntimeError, match="Compensation grade .* not match"): + make_lcmv(info_comp, fwd, data_cov) + + +@pytest.mark.slowtest +@testing.requires_testing_data +@pytest.mark.parametrize( + "proj, weight_norm", + [ + (True, "unit-noise-gain"), + (False, "unit-noise-gain"), + (True, None), + (True, "nai"), + ], +) +def test_lcmv_reg_proj(proj, weight_norm): + """Test LCMV with and without proj.""" + raw = mne.io.read_raw_fif(fname_raw, preload=True) + events = mne.find_events(raw) + raw.pick(picks="meg", exclude="bads") + assert len(raw.ch_names) == 305 + epochs = mne.Epochs(raw, events, None, preload=True, proj=proj) + with pytest.warns(RuntimeWarning, match="Too few samples"): + noise_cov = mne.compute_covariance(epochs, tmax=0) + data_cov = mne.compute_covariance(epochs, tmin=0.04, tmax=0.15) + forward = mne.read_forward_solution(fname_fwd) + filters = make_lcmv( + epochs.info, + forward, + data_cov, + reg=0.05, + noise_cov=noise_cov, + pick_ori="max-power", + weight_norm="nai", + rank=None, + verbose=True, + ) + want_rank = 302 # 305 good channels - 3 MEG projs + assert filters["rank"] == want_rank + # And also with and without noise_cov + with pytest.raises(ValueError, match="several sensor types"): + make_lcmv(epochs.info, forward, data_cov, reg=0.05, noise_cov=None) + epochs.pick(picks="grad") + kwargs = dict(reg=0.05, pick_ori=None, weight_norm=weight_norm) + filters_cov = make_lcmv( + epochs.info, forward, data_cov, noise_cov=noise_cov, **kwargs + ) + filters_nocov = make_lcmv(epochs.info, forward, data_cov, noise_cov=None, **kwargs) + ad_hoc = mne.make_ad_hoc_cov(epochs.info) + filters_adhoc = make_lcmv( + epochs.info, forward, data_cov, noise_cov=ad_hoc, **kwargs + ) + evoked = epochs.average() + stc_cov = apply_lcmv(evoked, filters_cov) + stc_nocov = apply_lcmv(evoked, filters_nocov) + stc_adhoc = apply_lcmv(evoked, filters_adhoc) + + # Compare adhoc and nocov: scale difference is necessitated by using std=1. + if weight_norm == "unit-noise-gain": + scale = np.sqrt(ad_hoc["data"][0]) + else: + scale = 1.0 + assert_allclose(stc_nocov.data, stc_adhoc.data * scale) + a = np.dot(filters_nocov["weights"], filters_nocov["whitener"]) + b = np.dot(filters_adhoc["weights"], filters_adhoc["whitener"]) * scale + atol = np.mean(np.sqrt(a * a)) * 1e-7 + assert_allclose(a, b, atol=atol, rtol=1e-7) + + # Compare adhoc and cov: locs might not be equivalent, but the same + # general profile should persist, so look at the std and be lenient: + if weight_norm == "unit-noise-gain": + adhoc_scale = 0.12 + else: + adhoc_scale = 1.0 + assert_allclose( + np.linalg.norm(stc_adhoc.data, axis=0) * adhoc_scale, + np.linalg.norm(stc_cov.data, axis=0), + rtol=0.3, + ) + assert_allclose( + np.linalg.norm(stc_nocov.data, axis=0) / scale * adhoc_scale, + np.linalg.norm(stc_cov.data, axis=0), + rtol=0.3, + ) + + if weight_norm == "nai": + # NAI is always normalized by noise-level (based on eigenvalues) + for stc in (stc_nocov, stc_cov): + assert_allclose(stc.data.std(), 0.584, rtol=0.2) + elif weight_norm is None: + # None always represents something not normalized, reflecting channel + # weights + for stc in (stc_nocov, stc_cov): + assert_allclose(stc.data.std(), 2.8e-8, rtol=0.1) + else: + assert weight_norm == "unit-noise-gain" + # Channel scalings depend on presence of noise_cov + assert_allclose(stc_nocov.data.std(), 7.8e-13, rtol=0.1) + assert_allclose(stc_cov.data.std(), 0.187, rtol=0.2) + + +@pytest.mark.slowtest +@pytest.mark.parametrize( + "reg, weight_norm, use_cov, depth, lower, upper", + [ + (0.05, "unit-noise-gain", True, None, 97, 98), + (0.05, "nai", True, None, 96, 98), + (0.05, "nai", True, 0.8, 96, 98), + (0.05, None, True, None, 74, 76), + (0.05, None, True, 0.8, 90, 93), # depth improves weight_norm=None + (0.05, "unit-noise-gain", False, None, 83, 86), + (0.05, "unit-noise-gain", False, 0.8, 83, 86), # depth same for wn != None + # no reg + (0.00, "unit-noise-gain", True, None, 35, 99), # TODO: Still not stable + ], +) +def test_localization_bias_fixed( + bias_params_fixed, reg, weight_norm, use_cov, depth, lower, upper +): + """Test localization bias for fixed-orientation LCMV.""" + evoked, fwd, noise_cov, data_cov, want = bias_params_fixed + if not use_cov: + evoked.pick(picks="grad") + noise_cov = None + assert data_cov["data"].shape[0] == len(data_cov["names"]) + loc = apply_lcmv( + evoked, + make_lcmv( + evoked.info, + fwd, + data_cov, + reg, + noise_cov, + depth=depth, + weight_norm=weight_norm, + ), + ).data + loc = np.abs(loc) + # Compute the percentage of sources for which there is no loc bias: + perc = (want == np.argmax(loc, axis=0)).mean() * 100 + assert lower <= perc <= upper + + +# Changes here should be synced with test_dics.py +@pytest.mark.slowtest +@pytest.mark.parametrize( + "reg, pick_ori, weight_norm, use_cov, depth, lower, upper, lower_ori, upper_ori", + [ + ( + 0.05, + "vector", + "unit-noise-gain-invariant", + False, + None, + 26, + 28, + 0.82, + 0.84, + ), # noqa: E501 + ( + 0.05, + "vector", + "unit-noise-gain-invariant", + True, + None, + 40, + 42, + 0.96, + 0.98, + ), # noqa: E501 + (0.05, "vector", "unit-noise-gain", False, None, 13, 14, 0.79, 0.81), + (0.05, "vector", "unit-noise-gain", True, None, 35, 37, 0.98, 0.99), + (0.05, "vector", "nai", True, None, 35, 37, 0.98, 0.99), + (0.05, "vector", None, True, None, 12, 14, 0.97, 0.98), + (0.05, "vector", None, True, 0.8, 39, 43, 0.97, 0.98), + ( + 0.05, + "max-power", + "unit-noise-gain-invariant", + False, + None, + 17, + 20, + 0, + 0, + ), # noqa: E501 + (0.05, "max-power", "unit-noise-gain", False, None, 17, 20, 0, 0), + (0.05, "max-power", "nai", True, None, 21, 24, 0, 0), + (0.05, "max-power", None, True, None, 7, 10, 0, 0), + (0.05, "max-power", None, True, 0.8, 15, 18, 0, 0), + (0.05, None, None, True, 0.8, 40, 42, 0, 0), + # no reg + (0.00, "vector", None, True, None, 23, 24, 0.96, 0.97), + ( + 0.00, + "vector", + "unit-noise-gain-invariant", + True, + None, + 52, + 54, + 0.95, + 0.96, + ), # noqa: E501 + (0.00, "vector", "unit-noise-gain", True, None, 44, 48, 0.97, 0.99), + (0.00, "vector", "nai", True, None, 44, 48, 0.97, 0.99), + (0.00, "max-power", None, True, None, 14, 15, 0, 0), + ( + 0.00, + "max-power", + "unit-noise-gain-invariant", + True, + None, + 35, + 37, + 0, + 0, + ), # noqa: E501 + (0.00, "max-power", "unit-noise-gain", True, None, 35, 37, 0, 0), + (0.00, "max-power", "nai", True, None, 35, 37, 0, 0), + ], +) +def test_localization_bias_free( + bias_params_free, + reg, + pick_ori, + weight_norm, + use_cov, + depth, + lower, + upper, + lower_ori, + upper_ori, +): + """Test localization bias for free-orientation LCMV.""" + evoked, fwd, noise_cov, data_cov, want = bias_params_free + if not use_cov: + evoked.pick(picks="grad") + noise_cov = None + with _record_warnings(): # rank deficiency of data_cov + filters = make_lcmv( + evoked.info, + fwd, + data_cov, + reg, + noise_cov, + pick_ori=pick_ori, + weight_norm=weight_norm, + depth=depth, + ) + loc = apply_lcmv(evoked, filters).data + if pick_ori == "vector": + ori = loc.copy() / np.linalg.norm(loc, axis=1, keepdims=True) + else: + # doesn't make sense for pooled (None) or max-power (can't be all 3) + ori = None + loc = np.linalg.norm(loc, axis=1) if pick_ori == "vector" else np.abs(loc) + # Compute the percentage of sources for which there is no loc bias: + max_idx = np.argmax(loc, axis=0) + perc = (want == max_idx).mean() * 100 + assert lower <= perc <= upper + _assert_free_ori_match(ori, max_idx, lower_ori, upper_ori) + + +# Changes here should be synced with the ones above, but these have meaningful +# orientation values +@pytest.mark.parametrize( + "reg, weight_norm, use_cov, depth, lower, upper, lower_ori, upper_ori", + [ + (0.05, "unit-noise-gain-invariant", False, None, 38, 40, 0.54, 0.55), + (0.05, "unit-noise-gain", False, None, 38, 40, 0.54, 0.55), + (0.05, "nai", True, None, 56, 57, 0.59, 0.61), + (0.05, None, True, None, 27, 28, 0.56, 0.57), + (0.05, None, True, 0.8, 42, 43, 0.56, 0.57), + # no reg + (0.00, None, True, None, 50, 51, 0.58, 0.59), + (0.00, "unit-noise-gain-invariant", True, None, 73, 75, 0.59, 0.61), + (0.00, "unit-noise-gain", True, None, 73, 75, 0.59, 0.61), + (0.00, "nai", True, None, 73, 75, 0.59, 0.61), + ], +) +def test_orientation_max_power( + bias_params_fixed, + bias_params_free, + reg, + weight_norm, + use_cov, + depth, + lower, + upper, + lower_ori, + upper_ori, +): + """Test orientation selection for bias for max-power LCMV.""" + # we simulate data for the fixed orientation forward and beamform using + # the free orientation forward, and check the orientation match at the end + evoked, _, noise_cov, data_cov, want = bias_params_fixed + fwd = bias_params_free[1] + if not use_cov: + evoked.pick(picks="grad") + noise_cov = None + filters = make_lcmv( + evoked.info, + fwd, + data_cov, + reg, + noise_cov, + pick_ori="max-power", + weight_norm=weight_norm, + depth=depth, + ) + loc = apply_lcmv(evoked, filters).data + ori = filters["max_power_ori"] + assert ori.shape == (246, 3) + loc = np.abs(loc) + # Compute the percentage of sources for which there is no loc bias: + max_idx = np.argmax(loc, axis=0) + mask = want == max_idx # ones that localized properly + perc = mask.mean() * 100 + assert lower <= perc <= upper + # Compute the dot products of our forward normals and + assert fwd["coord_frame"] == FIFF.FIFFV_COORD_HEAD + nn = np.concatenate([s["nn"][v] for s, v in zip(fwd["src"], filters["vertices"])]) + nn = nn[want] + nn = apply_trans(invert_transform(fwd["mri_head_t"]), nn, move=False) + assert_allclose(np.linalg.norm(nn, axis=1), 1, atol=1e-6) + assert_allclose(np.linalg.norm(ori, axis=1), 1, atol=1e-12) + dots = np.abs((nn[mask] * ori[mask]).sum(-1)) + assert_array_less(dots, 1) + assert_array_less(0, dots) + got = np.mean(dots) + assert lower_ori < got < upper_ori + + +@pytest.mark.parametrize( + "weight_norm, pick_ori", + [ + pytest.param("nai", "max-power", marks=pytest.mark.slowtest), + pytest.param("unit-noise-gain", "vector", marks=pytest.mark.slowtest), + ("unit-noise-gain", "max-power"), + pytest.param("unit-noise-gain", None, marks=pytest.mark.slowtest), + ], +) +def test_depth_does_not_matter(bias_params_free, weight_norm, pick_ori): + """Test that depth weighting does not matter for normalized filters.""" + evoked, fwd, noise_cov, data_cov, _ = bias_params_free + data = apply_lcmv( + evoked, + make_lcmv( + evoked.info, + fwd, + data_cov, + 0.05, + noise_cov, + pick_ori=pick_ori, + weight_norm=weight_norm, + depth=0.0, + ), + ).data + data_depth = apply_lcmv( + evoked, + make_lcmv( + evoked.info, + fwd, + data_cov, + 0.05, + noise_cov, + pick_ori=pick_ori, + weight_norm=weight_norm, + depth=1.0, + ), + ).data + assert data.shape == data_depth.shape + for d1, d2 in zip(data, data_depth): + # Sign flips can change when nearly orthogonal to the normal direction + d2 *= np.sign(np.dot(d1.ravel(), d2.ravel())) + atol = np.linalg.norm(d1) * 1e-7 + assert_allclose(d1, d2, atol=atol) + + +@pytest.fixture(scope="session") +def mf_data(): + """Produce Maxwell filtered data for beamforming.""" + raw = mne.io.read_raw_fif(fname_raw).fix_mag_coil_types() + raw_sss = mne.preprocessing.maxwell_filter(raw) + events = mne.find_events(raw_sss) + del raw + raw_sss.pick(picks="mag") + assert len(raw_sss.ch_names) == 102 + epochs = mne.Epochs(raw_sss, events) + data_cov = mne.compute_covariance(epochs, tmin=0) + fwd = mne.read_forward_solution(fname_fwd) + return epochs, data_cov, fwd + + +@testing.requires_testing_data +@pytest.mark.parametrize("use_rank", ("info", "computed", "full", None)) +def test_lcmv_maxfiltered(mf_data, use_rank): + """Test LCMV on maxfiltered data.""" + epochs, data_cov, fwd = mf_data + rank = compute_rank(data_cov, info=epochs.info) + assert rank == {"mag": 71} + ctx = nullcontext() + if use_rank == "computed": + use_rank = rank + elif use_rank is None: + ctx = pytest.warns(RuntimeWarning, match="rank as it exceeds") + with catch_logging() as log, ctx: + make_lcmv(epochs.info, fwd, data_cov, rank=use_rank, verbose=True) + log = log.getvalue() + n = 102 if use_rank == "full" else 71 + assert f"Making LCMV beamformer with rank {{'mag': {n}}}" in log + + +# To reduce test time, only test combinations that should matter rather than +# all of them +@testing.requires_testing_data +@pytest.mark.parametrize( + "pick_ori, weight_norm, reg, inversion", + [ + ("vector", "unit-noise-gain-invariant", 0.05, "matrix"), + ("vector", "unit-noise-gain-invariant", 0.05, "single"), + ("vector", "unit-noise-gain", 0.05, "matrix"), + ("vector", "unit-noise-gain", 0.05, "single"), + ("vector", "unit-noise-gain", 0.0, "matrix"), + ("vector", "unit-noise-gain", 0.0, "single"), + ("vector", "nai", 0.05, "matrix"), + ("max-power", "unit-noise-gain", 0.05, "matrix"), + ("max-power", "unit-noise-gain", 0.0, "single"), + ("max-power", "unit-noise-gain", 0.05, "single"), + ("max-power", "unit-noise-gain-invariant", 0.05, "matrix"), + ("normal", "unit-noise-gain", 0.05, "matrix"), + ("normal", "nai", 0.0, "matrix"), + ], +) +def test_unit_noise_gain_formula(pick_ori, weight_norm, reg, inversion): + """Test unit-noise-gain filter against formula.""" + raw = mne.io.read_raw_fif(fname_raw, preload=True) + events = mne.find_events(raw) + raw.pick(picks="mag") + assert len(raw.ch_names) == 102 + epochs = mne.Epochs(raw, events, None, preload=True) + data_cov = mne.compute_covariance(epochs, tmin=0.04, tmax=0.15) + # for now, avoid whitening to make life easier + noise_cov = mne.make_ad_hoc_cov(epochs.info, std=dict(grad=1.0, mag=1.0)) + forward = mne.read_forward_solution(fname_fwd) + convert_forward_solution(forward, surf_ori=True, copy=False) + rank = None + kwargs = dict( + reg=reg, + noise_cov=noise_cov, + pick_ori=pick_ori, + weight_norm=weight_norm, + rank=rank, + inversion=inversion, + ) + if ( + inversion == "single" + and pick_ori == "vector" + and weight_norm == "unit-noise-gain-invariant" + ): + with pytest.raises(ValueError, match="Cannot use"): + make_lcmv(epochs.info, forward, data_cov, **kwargs) + return + filters = make_lcmv(epochs.info, forward, data_cov, **kwargs) + _, _, _, _, G, _, _, _ = _prepare_beamformer_input( + epochs.info, + forward, + None, + "vector", + noise_cov=noise_cov, + rank=rank, + pca=False, + exp=None, + ) + n_channels, n_sources = G.shape + n_sources //= 3 + G = _reshape_view(G, (n_channels, n_sources, 3)) + G = G.transpose(1, 2, 0) # verts, orient, ch + _assert_weight_norm(filters, G) + + +def _assert_weight_norm(filters, G): + """Check the result of the chosen weight normalization strategy.""" + weights, max_power_ori = filters["weights"], filters["max_power_ori"] + + # Make the dimensions of the weight matrix equal for both DICS (which + # defines weights for multiple frequencies) and LCMV (which does not). + if filters["kind"] == "LCMV": + weights = weights[np.newaxis] + if max_power_ori is not None: + max_power_ori = max_power_ori[np.newaxis] + if max_power_ori is not None: + max_power_ori = max_power_ori[..., np.newaxis] + + weight_norm = filters["weight_norm"] + inversion = filters["inversion"] + n_channels = weights.shape[2] + + if inversion == "matrix": + # Dipoles are grouped in groups with size n_orient + n_sources = filters["n_sources"] + n_orient = 3 if filters["is_free_ori"] else 1 + elif inversion == "single": + # Every dipole is treated as a unique source + n_sources = weights.shape[1] + n_orient = 1 + + for wi, w in enumerate(weights): + w = w.reshape(n_sources, n_orient, n_channels) + + # Compute leadfield in the direction chosen during the computation of + # the beamformer. + if filters["pick_ori"] == "max-power": + use_G = np.sum(G * max_power_ori[wi], axis=1, keepdims=True) + elif filters["pick_ori"] == "normal": + use_G = G[:, -1:] + else: + use_G = G + if inversion == "single": + # Every dipole is treated as a unique source + use_G = use_G.reshape(n_sources, 1, n_channels) + assert w.shape == use_G.shape == (n_sources, n_orient, n_channels) + + # Test weight normalization scheme + got = np.matmul(w, w.conj().swapaxes(-2, -1)) + desired = np.repeat(np.eye(n_orient)[np.newaxis], w.shape[0], axis=0) + if n_orient == 3 and weight_norm in ("unit-noise-gain", "nai"): + # only the diagonal is correct! + assert not np.allclose(got, desired, atol=1e-7) + got = got.reshape(n_sources, -1)[:, :: n_orient + 1] + desired = np.ones_like(got) + if weight_norm == "nai": # additional scale factor, should be fixed + atol = 1e-7 * got.flat[0] + desired *= got.flat[0] + else: + atol = 1e-7 + assert_allclose(got, desired, atol=atol, err_msg="w @ w.conj().T = I") + + # Check that the result here is a diagonal matrix for Sekihara + if n_orient > 1 and weight_norm != "unit-noise-gain-invariant": + got = w @ use_G.swapaxes(-2, -1) + diags = np.diagonal(got, 0, -2, -1) + want = np.apply_along_axis(np.diagflat, 1, diags) + atol = np.mean(diags).real * 1e-12 + assert_allclose(got, want, atol=atol, err_msg="G.T @ w = θI") + + +def test_api(): + """Test LCMV/DICS API equivalence.""" + lcmv_names = list(signature(make_lcmv).parameters) + dics_names = list(signature(make_dics).parameters) + dics_names[dics_names.index("csd")] = "data_cov" + dics_names[dics_names.index("noise_csd")] = "noise_cov" + dics_names.pop(dics_names.index("real_filter")) # not a thing for LCMV + assert lcmv_names == dics_names diff --git a/mne-python/source/mne/beamformer/tests/test_rap_music.py b/mne-python/source/mne/beamformer/tests/test_rap_music.py new file mode 100644 index 0000000000000000000000000000000000000000..594e11bca09a556891f023a7a8eb9dc90b99c8da --- /dev/null +++ b/mne-python/source/mne/beamformer/tests/test_rap_music.py @@ -0,0 +1,222 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import pytest +from numpy.testing import assert_allclose +from scipy import linalg + +import mne +from mne.beamformer import rap_music, trap_music +from mne.cov import regularize +from mne.datasets import testing +from mne.minimum_norm.tests.test_inverse import assert_var_exp_log +from mne.utils import catch_logging + +data_path = testing.data_path(download=False) +fname_ave = data_path / "MEG" / "sample" / "sample_audvis-ave.fif" +fname_cov = data_path / "MEG" / "sample" / "sample_audvis_trunc-cov.fif" +fname_fwd = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" + + +def _get_data(ch_decim=1): + """Read in data used in tests.""" + # Read evoked + evoked = mne.read_evokeds(fname_ave, 0, baseline=(None, 0)) + evoked.info["bads"] = ["MEG 2443"] + with evoked.info._unlock(): + evoked.info["lowpass"] = 16 # fake for decim + evoked.decimate(12) + evoked.crop(0.0, 0.3) + picks = mne.pick_types(evoked.info, meg=True, eeg=False) + picks = picks[::ch_decim] + evoked.pick([evoked.ch_names[pick] for pick in picks]) + evoked.info.normalize_proj() + + noise_cov = mne.read_cov(fname_cov) + noise_cov["projs"] = [] + noise_cov = regularize(noise_cov, evoked.info, rank="full", proj=False) + return evoked, noise_cov + + +def simu_data(evoked, forward, noise_cov, n_dipoles, times, nave=1): + """Simulate an evoked dataset with 2 sources. + + One source is put in each hemisphere. + """ + # Generate the two dipoles data + mu, sigma = 0.1, 0.005 + s1 = ( + 1 / (sigma * np.sqrt(2 * np.pi)) * np.exp(-((times - mu) ** 2) / (2 * sigma**2)) + ) + + mu, sigma = 0.075, 0.008 + s2 = ( + -1 + / (sigma * np.sqrt(2 * np.pi)) + * np.exp(-((times - mu) ** 2) / (2 * sigma**2)) + ) + data = np.array([s1, s2]) * 1e-9 + + src = forward["src"] + rng = np.random.RandomState(42) + + rndi = rng.randint(len(src[0]["vertno"])) + lh_vertno = src[0]["vertno"][[rndi]] + + rndi = rng.randint(len(src[1]["vertno"])) + rh_vertno = src[1]["vertno"][[rndi]] + + vertices = [lh_vertno, rh_vertno] + tmin, tstep = times.min(), 1 / evoked.info["sfreq"] + stc = mne.SourceEstimate(data, vertices=vertices, tmin=tmin, tstep=tstep) + + sim_evoked = mne.simulation.simulate_evoked( + forward, stc, evoked.info, noise_cov, nave=nave, random_state=rng + ) + + return sim_evoked, stc + + +def _check_dipoles(dipoles, fwd, stc, evoked, residual=None): + src = fwd["src"] + pos1 = fwd["source_rr"][np.where(src[0]["vertno"] == stc.vertices[0])] + pos2 = fwd["source_rr"][ + np.where(src[1]["vertno"] == stc.vertices[1])[0] + len(src[0]["vertno"]) + ] + + # Check the position of the two dipoles + assert dipoles[0].pos[0] in np.array([pos1, pos2]) + assert dipoles[1].pos[0] in np.array([pos1, pos2]) + + ori1 = fwd["source_nn"][np.where(src[0]["vertno"] == stc.vertices[0])[0]][0] + ori2 = fwd["source_nn"][ + np.where(src[1]["vertno"] == stc.vertices[1])[0] + len(src[0]["vertno"]) + ][0] + + # Check the orientation of the dipoles + assert np.max(np.abs(np.dot(dipoles[0].ori[0], np.array([ori1, ori2]).T))) > 0.99 + + assert np.max(np.abs(np.dot(dipoles[1].ori[0], np.array([ori1, ori2]).T))) > 0.99 + + if residual is not None: + picks_grad = mne.pick_types(residual.info, meg="grad") + picks_mag = mne.pick_types(residual.info, meg="mag") + rel_tol = 0.02 + for picks in [picks_grad, picks_mag]: + assert linalg.norm(residual.data[picks], ord="fro") < rel_tol * linalg.norm( + evoked.data[picks], ord="fro" + ) + + +@testing.requires_testing_data +def test_rap_music_simulated(): + """Test RAP-MUSIC with simulated evoked.""" + evoked, noise_cov = _get_data(ch_decim=16) + forward = mne.read_forward_solution(fname_fwd) + forward = mne.pick_channels_forward(forward, evoked.ch_names) + forward_surf_ori = mne.convert_forward_solution(forward, surf_ori=True) + forward_fixed = mne.convert_forward_solution( + forward, force_fixed=True, surf_ori=True, use_cps=True + ) + + n_dipoles = 2 + sim_evoked, stc = simu_data( + evoked, forward_fixed, noise_cov, n_dipoles, evoked.times, nave=evoked.nave + ) + # Check dipoles for fixed ori + with catch_logging() as log: + dipoles = rap_music( + sim_evoked, forward_fixed, noise_cov, n_dipoles=n_dipoles, verbose=True + ) + assert_var_exp_log(log.getvalue(), 89, 91) + _check_dipoles(dipoles, forward_fixed, stc, sim_evoked) + assert 97 < dipoles[0].gof.max() < 100 + assert 91 < dipoles[1].gof.max() < 93 + assert dipoles[0].gof.min() >= 0.0 + + nave = 100000 # add a tiny amount of noise to the simulated evokeds + sim_evoked, stc = simu_data( + evoked, forward_fixed, noise_cov, n_dipoles, evoked.times, nave=nave + ) + dipoles, residual = rap_music( + sim_evoked, forward_fixed, noise_cov, n_dipoles=n_dipoles, return_residual=True + ) + _check_dipoles(dipoles, forward_fixed, stc, sim_evoked, residual) + + # Check dipoles for free ori + dipoles, residual = rap_music( + sim_evoked, forward, noise_cov, n_dipoles=n_dipoles, return_residual=True + ) + _check_dipoles(dipoles, forward_fixed, stc, sim_evoked, residual) + + # Check dipoles for free surface ori + dipoles, residual = rap_music( + sim_evoked, + forward_surf_ori, + noise_cov, + n_dipoles=n_dipoles, + return_residual=True, + ) + _check_dipoles(dipoles, forward_fixed, stc, sim_evoked, residual) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_rap_music_sphere(): + """Test RAP-MUSIC with real data, sphere model, MEG only.""" + evoked, noise_cov = _get_data(ch_decim=8) + sphere = mne.make_sphere_model(r0=(0.0, 0.0, 0.04)) + src = mne.setup_volume_source_space( + subject=None, + pos=10.0, + sphere=(0.0, 0.0, 40, 65.0), + mindist=5.0, + exclude=0.0, + sphere_units="mm", + ) + forward = mne.make_forward_solution(evoked.info, trans=None, src=src, bem=sphere) + + with catch_logging() as log: + dipoles = rap_music(evoked, forward, noise_cov, n_dipoles=2, verbose=True) + assert_var_exp_log(log.getvalue(), 47, 49) + # Test that there is one dipole on each hemisphere + pos = np.array([dip.pos[0] for dip in dipoles]) + assert pos.shape == (2, 3) + assert (pos[:, 0] < 0).sum() == 1 + assert (pos[:, 0] > 0).sum() == 1 + # Check the amplitude scale + assert 1e-10 < dipoles[0].amplitude[0] < 1e-7 + # Check the orientation + dip_fit = mne.fit_dipole(evoked, noise_cov, sphere)[0] + assert np.max(np.abs(np.dot(dip_fit.ori, dipoles[0].ori[0]))) > 0.99 + assert np.max(np.abs(np.dot(dip_fit.ori, dipoles[1].ori[0]))) > 0.99 + idx = dip_fit.gof.argmax() + dist = np.linalg.norm(dipoles[0].pos[idx] - dip_fit.pos[idx]) + assert 0.004 <= dist < 0.007 + assert_allclose(dipoles[0].gof[idx], dip_fit.gof[idx], atol=3) + + +@testing.requires_testing_data +def test_rap_music_picks(): + """Test RAP-MUSIC with picking.""" + evoked = mne.read_evokeds(fname_ave, condition="Right Auditory", baseline=(None, 0)) + evoked.crop(tmin=0.05, tmax=0.15) # select N100 + evoked.pick(picks="meg") + forward = mne.read_forward_solution(fname_fwd) + noise_cov = mne.read_cov(fname_cov) + dipoles = rap_music(evoked, forward, noise_cov, n_dipoles=2) + assert len(dipoles) == 2 + + +@testing.requires_testing_data +def test_trap_music(): + """Test TRAP-MUSIC.""" + evoked = mne.read_evokeds(fname_ave, condition="Right Auditory", baseline=(None, 0)) + evoked.crop(tmin=0.05, tmax=0.15) # select N100 + evoked.pick(picks="meg") + forward = mne.read_forward_solution(fname_fwd) + noise_cov = mne.read_cov(fname_cov) + dipoles = trap_music(evoked, forward, noise_cov, n_dipoles=2) + assert len(dipoles) == 2 diff --git a/mne-python/source/mne/beamformer/tests/test_resolution_matrix.py b/mne-python/source/mne/beamformer/tests/test_resolution_matrix.py new file mode 100644 index 0000000000000000000000000000000000000000..a02222a86f215d7075752619d6612077179374a8 --- /dev/null +++ b/mne-python/source/mne/beamformer/tests/test_resolution_matrix.py @@ -0,0 +1,97 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +""" +Test computation of resolution matrix for LCMV beamformers. + +If noise and data covariance are the same, the LCMV beamformer weights should +be the transpose of the leadfield matrix. +""" + +from copy import deepcopy + +import numpy as np +from numpy.testing import assert_allclose + +import mne +from mne.beamformer import make_lcmv, make_lcmv_resolution_matrix +from mne.datasets import testing + +data_path = testing.data_path(download=False) +subjects_dir = data_path / "subjects" +fname_inv = ( + data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-6-meg-inv.fif" +) +fname_evoked = data_path / "MEG" / "sample" / "sample_audvis_trunc-ave.fif" +fname_raw = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw.fif" +fname_fwd = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" +fname_cov = data_path / "MEG" / "sample" / "sample_audvis_trunc-cov.fif" + + +@testing.requires_testing_data +def test_resolution_matrix_lcmv(): + """Test computation of resolution matrix for LCMV beamformers.""" + # read forward solution + forward = mne.read_forward_solution(fname_fwd) + + # remove bad channels + forward = mne.pick_channels_forward(forward, exclude="bads") + + # forward operator with fixed source orientations + forward_fxd = mne.convert_forward_solution(forward, surf_ori=True, force_fixed=True) + + # evoked info + info = mne.io.read_info(fname_evoked) + mne.pick_info(info, mne.pick_types(info, meg=True), copy=False) # good MEG + + # noise covariance matrix + # ad-hoc to avoid discrepancies due to regularisation of real noise + # covariance matrix + noise_cov = mne.make_ad_hoc_cov(info) + + # Resolution matrix for Beamformer + data_cov = noise_cov.copy() # to test a property of LCMV + + # compute beamformer filters + # reg=0. to make sure noise_cov and data_cov are as similar as possible + filters = make_lcmv( + info, + forward_fxd, + data_cov, + reg=0.0, + noise_cov=noise_cov, + pick_ori=None, + rank=None, + weight_norm=None, + reduce_rank=False, + verbose=False, + ) + + # Compute resolution matrix for beamformer + resmat_lcmv = make_lcmv_resolution_matrix(filters, forward_fxd, info) + + # for noise_cov==data_cov and whitening, the filter weights should be the + # transpose of leadfield + + # create filters with transposed whitened leadfield as weights + forward_fxd = mne.pick_channels_forward(forward_fxd, info["ch_names"]) + filters_lfd = deepcopy(filters) + filters_lfd["weights"][:] = forward_fxd["sol"]["data"].T + + # compute resolution matrix for filters with transposed leadfield + resmat_fwd = make_lcmv_resolution_matrix(filters_lfd, forward_fxd, info) + + # pairwise correlation for rows (CTFs) of resolution matrices for whitened + # LCMV beamformer and transposed leadfield should be 1 + # Some rows are off by about 0.1 - not yet clear why + corr = [] + + for f, lf in zip(resmat_fwd, resmat_lcmv): + corr.append(np.corrcoef(f, lf)[0, 1]) + + # all row correlations should at least be above ~0.8 + assert_allclose(corr, 1.0, atol=0.2) + + # Maximum row correlation should at least be close to 1 + assert_allclose(np.max(corr), 1.0, atol=0.01) diff --git a/mne-python/source/mne/bem.py b/mne-python/source/mne/bem.py new file mode 100644 index 0000000000000000000000000000000000000000..bb73544f763c9f797bd6de612a51b67933f47f4e --- /dev/null +++ b/mne-python/source/mne/bem.py @@ -0,0 +1,2576 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# The computations in this code were primarily derived from Matti Hämäläinen's +# C code. + +import glob +import json +import os +import os.path as op +import shutil +from collections import OrderedDict +from copy import deepcopy +from functools import partial +from pathlib import Path + +import numpy as np +from scipy.optimize import fmin_cobyla + +from ._fiff._digitization import _dig_kind_dict, _dig_kind_ints, _dig_kind_rev +from ._fiff.constants import FIFF, FWD +from ._fiff.open import fiff_open +from ._fiff.tag import find_tag +from ._fiff.tree import dir_tree_find +from ._fiff.write import ( + end_block, + start_and_end_file, + start_block, + write_float, + write_float_matrix, + write_int, + write_int_matrix, + write_string, +) +from .fixes import _compare_version, _safe_svd +from .surface import ( + _complete_sphere_surf, + _compute_nearest, + _fast_cross_nd_sum, + _get_ico_surface, + _get_solids, + complete_surface_info, + decimate_surface, + read_surface, + read_tri, + transform_surface_to, + write_surface, +) +from .transforms import Transform, _ensure_trans, apply_trans +from .utils import ( + _check_fname, + _check_freesurfer_home, + _check_head_radius, + _check_option, + _ensure_int, + _import_h5io_funcs, + _import_nibabel, + _on_missing, + _path_like, + _pl, + _TempDir, + _validate_type, + _verbose_safe_false, + get_subjects_dir, + logger, + path_like, + run_subprocess, + verbose, + warn, +) +from .viz.misc import plot_bem + +# ############################################################################ +# Compute BEM solution + +# The following approach is based on: +# +# de Munck JC: "A linear discretization of the volume conductor boundary +# integral equation using analytically integrated elements", +# IEEE Trans Biomed Eng. 1992 39(9) : 986 - 990 +# + + +class ConductorModel(dict): + """BEM or sphere model. + + See :func:`~mne.make_bem_model` and :func:`~mne.make_bem_solution` to create a + :class:`mne.bem.ConductorModel`. + """ + + def __repr__(self): # noqa: D105 + if self["is_sphere"]: + center = ", ".join(f"{x * 1000.0:.1f}" for x in self["r0"]) + rad = self.radius + if rad is None: # no radius / MEG only + extra = f"Sphere (no layers): r0=[{center}] mm" + else: + extra = ( + f"Sphere ({len(self['layers']) - 1} layer{_pl(self['layers'])}): " + f"r0=[{center}] R={rad * 1000.0:1.0f} mm" + ) + else: + extra = f"BEM ({len(self['surfs'])} layer{_pl(self['surfs'])})" + extra += f" solver={self['solver']}" + return f"" + + def copy(self): + """Return copy of ConductorModel instance.""" + return deepcopy(self) + + @property + def radius(self): + """Sphere radius if an EEG sphere model.""" + if not self["is_sphere"]: + raise RuntimeError("radius undefined for BEM") + return None if len(self["layers"]) == 0 else self["layers"][-1]["rad"] + + +def _calc_beta(rk, rk_norm, rk1, rk1_norm): + """Compute coefficients for calculating the magic vector omega.""" + rkk1 = rk1[0] - rk[0] + size = np.linalg.norm(rkk1) + rkk1 /= size + num = rk_norm + np.dot(rk, rkk1) + den = rk1_norm + np.dot(rk1, rkk1) + res = np.log(num / den) / size + return res + + +def _lin_pot_coeff(fros, tri_rr, tri_nn, tri_area): + """Compute the linear potential matrix element computations.""" + omega = np.zeros((len(fros), 3)) + + # we replicate a little bit of the _get_solids code here for speed + # (we need some of the intermediate values later) + v1 = tri_rr[np.newaxis, 0, :] - fros + v2 = tri_rr[np.newaxis, 1, :] - fros + v3 = tri_rr[np.newaxis, 2, :] - fros + triples = _fast_cross_nd_sum(v1, v2, v3) + l1 = np.linalg.norm(v1, axis=1) + l2 = np.linalg.norm(v2, axis=1) + l3 = np.linalg.norm(v3, axis=1) + ss = l1 * l2 * l3 + ss += np.einsum("ij,ij,i->i", v1, v2, l3) + ss += np.einsum("ij,ij,i->i", v1, v3, l2) + ss += np.einsum("ij,ij,i->i", v2, v3, l1) + solids = np.arctan2(triples, ss) + + # We *could* subselect the good points from v1, v2, v3, triples, solids, + # l1, l2, and l3, but there are *very* few bad points. So instead we do + # some unnecessary calculations, and then omit them from the final + # solution. These three lines ensure we don't get invalid values in + # _calc_beta. + bad_mask = np.abs(solids) < np.pi / 1e6 + l1[bad_mask] = 1.0 + l2[bad_mask] = 1.0 + l3[bad_mask] = 1.0 + + # Calculate the magic vector vec_omega + beta = [ + _calc_beta(v1, l1, v2, l2)[:, np.newaxis], + _calc_beta(v2, l2, v3, l3)[:, np.newaxis], + _calc_beta(v3, l3, v1, l1)[:, np.newaxis], + ] + vec_omega = (beta[2] - beta[0]) * v1 + vec_omega += (beta[0] - beta[1]) * v2 + vec_omega += (beta[1] - beta[2]) * v3 + + area2 = 2.0 * tri_area + n2 = 1.0 / (area2 * area2) + # leave omega = 0 otherwise + # Put it all together... + yys = [v1, v2, v3] + idx = [0, 1, 2, 0, 2] + for k in range(3): + diff = yys[idx[k - 1]] - yys[idx[k + 1]] + zdots = _fast_cross_nd_sum(yys[idx[k + 1]], yys[idx[k - 1]], tri_nn) + omega[:, k] = -n2 * ( + area2 * zdots * 2.0 * solids - triples * (diff * vec_omega).sum(axis=-1) + ) + # omit the bad points from the solution + omega[bad_mask] = 0.0 + return omega + + +def _correct_auto_elements(surf, mat): + """Improve auto-element approximation.""" + pi2 = 2.0 * np.pi + tris_flat = surf["tris"].ravel() + misses = pi2 - mat.sum(axis=1) + for j, miss in enumerate(misses): + # How much is missing? + n_memb = len(surf["neighbor_tri"][j]) + assert n_memb > 0 # should be guaranteed by our surface checks + # The node itself receives one half + mat[j, j] = miss / 2.0 + # The rest is divided evenly among the member nodes... + miss /= 4.0 * n_memb + members = np.where(j == tris_flat)[0] + mods = members % 3 + offsets = np.array([[1, 2], [-1, 1], [-1, -2]]) + tri_1 = members + offsets[mods, 0] + tri_2 = members + offsets[mods, 1] + for t1, t2 in zip(tri_1, tri_2): + mat[j, tris_flat[t1]] += miss + mat[j, tris_flat[t2]] += miss + return + + +def _fwd_bem_lin_pot_coeff(surfs): + """Calculate the coefficients for linear collocation approach.""" + # taken from fwd_bem_linear_collocation.c + nps = [surf["np"] for surf in surfs] + np_tot = sum(nps) + coeff = np.zeros((np_tot, np_tot)) + offsets = np.cumsum(np.concatenate(([0], nps))) + for si_1, surf1 in enumerate(surfs): + rr_ord = np.arange(nps[si_1]) + for si_2, surf2 in enumerate(surfs): + logger.info( + f" {_bem_surf_name[surf1['id']]} ({nps[si_1]:d}) -> " + f"{_bem_surf_name[surf2['id']]} ({nps[si_2]}) ..." + ) + tri_rr = surf2["rr"][surf2["tris"]] + tri_nn = surf2["tri_nn"] + tri_area = surf2["tri_area"] + submat = coeff[ + offsets[si_1] : offsets[si_1 + 1], offsets[si_2] : offsets[si_2 + 1] + ] # view + for k in range(surf2["ntri"]): + tri = surf2["tris"][k] + if si_1 == si_2: + skip_idx = ( + (rr_ord == tri[0]) | (rr_ord == tri[1]) | (rr_ord == tri[2]) + ) + else: + skip_idx = list() + # No contribution from a triangle that + # this vertex belongs to + # if sidx1 == sidx2 and (tri == j).any(): + # continue + # Otherwise do the hard job + coeffs = _lin_pot_coeff( + fros=surf1["rr"], + tri_rr=tri_rr[k], + tri_nn=tri_nn[k], + tri_area=tri_area[k], + ) + coeffs[skip_idx] = 0.0 + submat[:, tri] -= coeffs + if si_1 == si_2: + _correct_auto_elements(surf1, submat) + return coeff + + +def _fwd_bem_multi_solution(solids, gamma, nps): + """Do multi surface solution. + + * Invert I - solids/(2*M_PI) + * Take deflation into account + * The matrix is destroyed after inversion + * This is the general multilayer case + """ + pi2 = 1.0 / (2 * np.pi) + n_tot = np.sum(nps) + assert solids.shape == (n_tot, n_tot) + nsurf = len(nps) + defl = 1.0 / n_tot + # Modify the matrix + offsets = np.cumsum(np.concatenate(([0], nps))) + for si_1 in range(nsurf): + for si_2 in range(nsurf): + mult = pi2 if gamma is None else pi2 * gamma[si_1, si_2] + slice_j = slice(offsets[si_1], offsets[si_1 + 1]) + slice_k = slice(offsets[si_2], offsets[si_2 + 1]) + solids[slice_j, slice_k] = defl - solids[slice_j, slice_k] * mult + solids += np.eye(n_tot) + return np.linalg.inv(solids) + + +def _fwd_bem_homog_solution(solids, nps): + """Make a homogeneous solution.""" + return _fwd_bem_multi_solution(solids, gamma=None, nps=nps) + + +def _fwd_bem_ip_modify_solution(solution, ip_solution, ip_mult, n_tri): + """Modify the solution according to the IP approach.""" + n_last = n_tri[-1] + mult = (1.0 + ip_mult) / ip_mult + + logger.info(" Combining...") + offsets = np.cumsum(np.concatenate(([0], n_tri))) + for si in range(len(n_tri)): + # Pick the correct submatrix (right column) and multiply + sub = solution[offsets[si] : offsets[si + 1], np.sum(n_tri[:-1]) :] + # Multiply + sub -= 2 * np.dot(sub, ip_solution) + + # The lower right corner is a special case + sub[-n_last:, -n_last:] += mult * ip_solution + + # Final scaling + logger.info(" Scaling...") + solution *= ip_mult + return + + +def _check_complete_surface(surf, copy=False, incomplete="raise", extra=""): + surf = complete_surface_info(surf, copy=copy, verbose=_verbose_safe_false()) + fewer = np.where([len(t) < 3 for t in surf["neighbor_tri"]])[0] + if len(fewer) > 0: + fewer = list(fewer) + fewer = (fewer[:80] + ["..."]) if len(fewer) > 80 else fewer + fewer = ", ".join(str(f) for f in fewer) + msg = ( + f"Surface {_bem_surf_name[surf['id']]} has topological defects: " + f"{len(fewer)} / {len(surf['rr'])} vertices have fewer than three " + f"neighboring triangles [{fewer}]{extra}" + ) + _on_missing(on_missing=incomplete, msg=msg, name="on_defects") + return surf + + +def _fwd_bem_linear_collocation_solution(bem): + """Compute the linear collocation potential solution.""" + # first, add surface geometries + logger.info("Computing the linear collocation solution...") + logger.info(" Matrix coefficients...") + coeff = _fwd_bem_lin_pot_coeff(bem["surfs"]) + bem["nsol"] = len(coeff) + logger.info(" Inverting the coefficient matrix...") + nps = [surf["np"] for surf in bem["surfs"]] + bem["solution"] = _fwd_bem_multi_solution(coeff, bem["gamma"], nps) + if len(bem["surfs"]) == 3: + ip_mult = bem["sigma"][1] / bem["sigma"][2] + if ip_mult <= FWD.BEM_IP_APPROACH_LIMIT: + logger.info("IP approach required...") + logger.info(" Matrix coefficients (homog)...") + coeff = _fwd_bem_lin_pot_coeff([bem["surfs"][-1]]) + logger.info(" Inverting the coefficient matrix (homog)...") + ip_solution = _fwd_bem_homog_solution(coeff, [bem["surfs"][-1]["np"]]) + logger.info( + " Modify the original solution to incorporate IP approach..." + ) + _fwd_bem_ip_modify_solution(bem["solution"], ip_solution, ip_mult, nps) + bem["bem_method"] = FIFF.FIFFV_BEM_APPROX_LINEAR + bem["solver"] = "mne" + + +def _import_openmeeg(what="compute a BEM solution using OpenMEEG"): + try: + import openmeeg as om + except Exception as exc: + raise ImportError( + f"The OpenMEEG module must be installed to {what}, but " + f'"import openmeeg" resulted in: {exc}' + ) from None + if not _compare_version(om.__version__, ">=", "2.5.6"): + raise ImportError(f"OpenMEEG 2.5.6+ is required, got {om.__version__}") + return om + + +def _make_openmeeg_geometry(bem, mri_head_t=None): + # OpenMEEG + om = _import_openmeeg() + meshes = [] + for surf in bem["surfs"][::-1]: + if mri_head_t is not None: + surf = transform_surface_to(surf, "head", mri_head_t, copy=True) + points, faces = surf["rr"], surf["tris"] + faces = faces[:, [1, 0, 2]] # swap faces + meshes.append((points, faces)) + + conductivity = bem["sigma"][::-1] + return om.make_nested_geometry(meshes, conductivity) + + +def _fwd_bem_openmeeg_solution(bem): + om = _import_openmeeg() + logger.info("Creating BEM solution using OpenMEEG") + logger.info("Computing the openmeeg head matrix solution...") + logger.info(" Matrix coefficients...") + + geom = _make_openmeeg_geometry(bem) + + hm = om.HeadMat(geom) + bem["nsol"] = hm.nlin() + + logger.info(" Inverting the coefficient matrix...") + hm.invert() # invert inplace + bem["solution"] = hm.array_flat() + bem["bem_method"] = FIFF.FIFFV_BEM_APPROX_LINEAR + bem["solver"] = "openmeeg" + + +@verbose +def make_bem_solution(surfs, *, solver="mne", verbose=None): + """Create a BEM solution using the linear collocation approach. + + Parameters + ---------- + surfs : list of dict + The BEM surfaces to use (from :func:`mne.make_bem_model`). + solver : str + Can be ``'mne'`` (default) to use MNE-Python, or ``'openmeeg'`` to use the + `OpenMEEG `__ package. + + .. versionadded:: 1.2 + %(verbose)s + + Returns + ------- + bem : instance of ConductorModel + The BEM solution. + + See Also + -------- + make_bem_model + read_bem_surfaces + write_bem_surfaces + read_bem_solution + write_bem_solution + + Notes + ----- + .. versionadded:: 0.10.0 + """ + _validate_type(solver, str, "solver") + _check_option("method", solver.lower(), ("mne", "openmeeg")) + bem = _ensure_bem_surfaces(surfs) + _add_gamma_multipliers(bem) + if len(bem["surfs"]) == 3: + logger.info("Three-layer model surfaces loaded.") + elif len(bem["surfs"]) == 1: + logger.info("Homogeneous model surface loaded.") + else: + raise RuntimeError("Only 1- or 3-layer BEM computations supported") + _check_bem_size(bem["surfs"]) + for surf in bem["surfs"]: + _check_complete_surface(surf) + if solver.lower() == "openmeeg": + _fwd_bem_openmeeg_solution(bem) + else: + assert solver.lower() == "mne" + _fwd_bem_linear_collocation_solution(bem) + logger.info("Solution ready.") + logger.info("BEM geometry computations complete.") + return bem + + +# ############################################################################ +# Make BEM model + + +def _ico_downsample(surf, dest_grade): + """Downsample the surface if isomorphic to a subdivided icosahedron.""" + n_tri = len(surf["tris"]) + bad_msg = ( + f"Cannot decimate to requested ico grade {dest_grade}. The provided " + f"BEM surface has {n_tri} triangles, which cannot be isomorphic with " + "a subdivided icosahedron. Consider manually decimating the surface to " + "a suitable density and then use ico=None in make_bem_model." + ) + if n_tri % 20 != 0: + raise RuntimeError(bad_msg) + n_tri = n_tri // 20 + found = int(round(np.log(n_tri) / np.log(4))) + if n_tri != 4**found: + raise RuntimeError(bad_msg) + del n_tri + + if dest_grade > found: + raise RuntimeError( + f"For this surface, decimation grade should be {found} or less, " + f"not {dest_grade}." + ) + + source = _get_ico_surface(found) + dest = _get_ico_surface(dest_grade, patch_stats=True) + del dest["tri_cent"] + del dest["tri_nn"] + del dest["neighbor_tri"] + del dest["tri_area"] + if not np.array_equal(source["tris"], surf["tris"]): + raise RuntimeError( + "The source surface has a matching number of " + "triangles but ordering is wrong" + ) + logger.info( + f"Going from {found}th to {dest_grade}th subdivision of an icosahedron " + f"(n_tri: {len(surf['tris'])} -> {len(dest['tris'])})" + ) + # Find the mapping + dest["rr"] = surf["rr"][_get_ico_map(source, dest)] + return dest + + +def _get_ico_map(fro, to): + """Get a mapping between ico surfaces.""" + nearest, dists = _compute_nearest(fro["rr"], to["rr"], return_dists=True) + n_bads = (dists > 5e-3).sum() + if n_bads > 0: + raise RuntimeError(f"No matching vertex for {n_bads} destination vertices") + return nearest + + +def _order_surfaces(surfs): + """Reorder the surfaces.""" + if len(surfs) != 3: + return surfs + # we have three surfaces + surf_order = [ + FIFF.FIFFV_BEM_SURF_ID_HEAD, + FIFF.FIFFV_BEM_SURF_ID_SKULL, + FIFF.FIFFV_BEM_SURF_ID_BRAIN, + ] + ids = np.array([surf["id"] for surf in surfs]) + if set(ids) != set(surf_order): + raise RuntimeError(f"bad surface ids: {ids}") + order = [np.where(ids == id_)[0][0] for id_ in surf_order] + surfs = [surfs[idx] for idx in order] + return surfs + + +def _assert_complete_surface(surf, incomplete="raise"): + """Check the sum of solid angles as seen from inside.""" + # from surface_checks.c + # Center of mass.... + cm = surf["rr"].mean(axis=0) + logger.info( + f"{_bem_surf_name[surf['id']]} CM is " + f"{1000 * cm[0]:6.2f} " + f"{1000 * cm[1]:6.2f} " + f"{1000 * cm[2]:6.2f} mm" + ) + tot_angle = _get_solids(surf["rr"][surf["tris"]], cm[np.newaxis, :])[0] + prop = tot_angle / (2 * np.pi) + if np.abs(prop - 1.0) > 1e-5: + msg = ( + f"Surface {_bem_surf_name[surf['id']]} is not complete (sum of " + f"solid angles yielded {prop}, should be 1.)" + ) + _on_missing(incomplete, msg, name="incomplete", error_klass=RuntimeError) + + +def _assert_inside(fro, to): + """Check one set of points is inside a surface.""" + # this is "is_inside" in surface_checks.c + fro_name = _bem_surf_name[fro["id"]] + to_name = _bem_surf_name[to["id"]] + logger.info(f"Checking that surface {fro_name} is inside surface {to_name} ...") + tot_angle = _get_solids(to["rr"][to["tris"]], fro["rr"]) + if (np.abs(tot_angle / (2 * np.pi) - 1.0) > 1e-5).any(): + raise RuntimeError( + f"Surface {fro_name} is not completely inside surface {to_name}" + ) + + +def _check_surfaces(surfs, incomplete="raise"): + """Check that the surfaces are complete and non-intersecting.""" + for surf in surfs: + _assert_complete_surface(surf, incomplete=incomplete) + # Then check the topology + for surf_1, surf_2 in zip(surfs[:-1], surfs[1:]): + _assert_inside(surf_2, surf_1) + + +def _check_surface_size(surf): + """Check that the coordinate limits are reasonable.""" + sizes = surf["rr"].max(axis=0) - surf["rr"].min(axis=0) + if (sizes < 0.05).any(): + raise RuntimeError( + f"Dimensions of the surface {_bem_surf_name[surf['id']]} seem too " + f"small ({1000 * sizes.min():9.5f}). Maybe the unit of measure" + " is meters instead of mm" + ) + + +def _check_thicknesses(surfs): + """Compute how close we are.""" + for surf_1, surf_2 in zip(surfs[:-1], surfs[1:]): + min_dist = _compute_nearest(surf_1["rr"], surf_2["rr"], return_dists=True)[1] + min_dist = min_dist.min() + fro = _bem_surf_name[surf_1["id"]] + to = _bem_surf_name[surf_2["id"]] + logger.info(f"Checking distance between {fro} and {to} surfaces...") + logger.info( + f"Minimum distance between the {fro} and {to} surfaces is " + f"approximately {1000 * min_dist:6.1f} mm" + ) + + +def _surfaces_to_bem( + surfs, ids, sigmas, ico=None, rescale=True, incomplete="raise", extra="" +): + """Convert surfaces to a BEM.""" + # equivalent of mne_surf2bem + # surfs can be strings (filenames) or surface dicts + if len(surfs) not in (1, 3) or not (len(surfs) == len(ids) == len(sigmas)): + raise ValueError( + "surfs, ids, and sigmas must all have the same number of elements (1 or 3)" + ) + for si, surf in enumerate(surfs): + if isinstance(surf, str | Path | os.PathLike): + surfs[si] = surf = read_surface(surf, return_dict=True)[-1] + # Downsampling if the surface is isomorphic with a subdivided icosahedron + if ico is not None: + for si, surf in enumerate(surfs): + surfs[si] = _ico_downsample(surf, ico) + for surf, id_ in zip(surfs, ids): + # Do topology checks (but don't save data) to fail early + surf["id"] = id_ + _check_complete_surface(surf, copy=True, incomplete=incomplete, extra=extra) + surf["coord_frame"] = surf.get("coord_frame", FIFF.FIFFV_COORD_MRI) + surf.update(np=len(surf["rr"]), ntri=len(surf["tris"])) + if rescale: + surf["rr"] /= 1000.0 # convert to meters + + # Shifting surfaces is not implemented here... + + # Order the surfaces for the benefit of the topology checks + for surf, sigma in zip(surfs, sigmas): + surf["sigma"] = sigma + surfs = _order_surfaces(surfs) + + # Check topology as best we can + _check_surfaces(surfs, incomplete=incomplete) + for surf in surfs: + _check_surface_size(surf) + _check_thicknesses(surfs) + logger.info("Surfaces passed the basic topology checks.") + return surfs + + +@verbose +def make_bem_model( + subject, ico=4, conductivity=(0.3, 0.006, 0.3), subjects_dir=None, verbose=None +): + """Create a BEM model for a subject. + + Use :func:`~mne.make_bem_solution` to turn the returned surfaces into a + :class:`~mne.bem.ConductorModel` suitable for forward calculation. + + .. note:: To get a single layer bem corresponding to the --homog flag in + the command line tool set the ``conductivity`` parameter + to a float (e.g. ``0.3``). + + Parameters + ---------- + %(subject)s + ico : int | None + The surface ico downsampling to use, e.g. ``5=20484``, ``4=5120``, + ``3=1280``. If None, no subsampling is applied. + conductivity : float | array of float of shape (3,) or (1,) + The conductivities to use for each shell. Should be a single element + for a one-layer model, or three elements for a three-layer model. + Defaults to ``[0.3, 0.006, 0.3]``. The MNE-C default for a + single-layer model is ``[0.3]``. + %(subjects_dir)s + %(verbose)s + + Returns + ------- + surfaces : list of dict + The BEM surfaces. Use :func:`~mne.make_bem_solution` to turn these into a + :class:`~mne.bem.ConductorModel` suitable for forward calculation. + + See Also + -------- + make_bem_solution + make_sphere_model + read_bem_surfaces + write_bem_surfaces + + Notes + ----- + .. versionadded:: 0.10.0 + """ + conductivity = np.atleast_1d(conductivity).astype(float) + if conductivity.ndim != 1 or conductivity.size not in (1, 3): + raise ValueError( + "conductivity must be a float or a 1D array-like with 1 or 3 elements" + ) + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + subject_dir = subjects_dir / subject + bem_dir = subject_dir / "bem" + inner_skull = bem_dir / "inner_skull.surf" + outer_skull = bem_dir / "outer_skull.surf" + outer_skin = bem_dir / "outer_skin.surf" + surfaces = [inner_skull, outer_skull, outer_skin] + ids = [ + FIFF.FIFFV_BEM_SURF_ID_BRAIN, + FIFF.FIFFV_BEM_SURF_ID_SKULL, + FIFF.FIFFV_BEM_SURF_ID_HEAD, + ] + logger.info("Creating the BEM geometry...") + if len(conductivity) == 1: + surfaces = surfaces[:1] + ids = ids[:1] + surfaces = _surfaces_to_bem(surfaces, ids, conductivity, ico) + _check_bem_size(surfaces) + logger.info("Complete.\n") + return surfaces + + +# ############################################################################ +# Compute EEG sphere model + + +def _fwd_eeg_get_multi_sphere_model_coeffs(m, n_terms): + """Get the model depended weighting factor for n.""" + nlayer = len(m["layers"]) + if nlayer in (0, 1): + return 1.0 + + # Initialize the arrays + c1 = np.zeros(nlayer - 1) + c2 = np.zeros(nlayer - 1) + cr = np.zeros(nlayer - 1) + cr_mult = np.zeros(nlayer - 1) + for k in range(nlayer - 1): + c1[k] = m["layers"][k]["sigma"] / m["layers"][k + 1]["sigma"] + c2[k] = c1[k] - 1.0 + cr_mult[k] = m["layers"][k]["rel_rad"] + cr[k] = cr_mult[k] + cr_mult[k] *= cr_mult[k] + + coeffs = np.zeros(n_terms - 1) + for n in range(1, n_terms): + # Increment the radius coefficients + for k in range(nlayer - 1): + cr[k] *= cr_mult[k] + + # Multiply the matrices + M = np.eye(2) + n1 = n + 1.0 + for k in range(nlayer - 2, -1, -1): + M = np.dot( + [ + [n + n1 * c1[k], n1 * c2[k] / cr[k]], + [n * c2[k] * cr[k], n1 + n * c1[k]], + ], + M, + ) + num = n * (2.0 * n + 1.0) ** (nlayer - 1) + coeffs[n - 1] = num / (n * M[1, 1] + n1 * M[1, 0]) + return coeffs + + +def _compose_linear_fitting_data(mu, u): + """Get the linear fitting data.""" + k1 = np.arange(1, u["nterms"]) + mu1ns = mu[0] ** k1 + # data to be fitted + y = u["w"][:-1] * (u["fn"][1:] - mu1ns * u["fn"][0]) + # model matrix + M = u["w"][:-1, np.newaxis] * (mu[1:] ** k1[:, np.newaxis] - mu1ns[:, np.newaxis]) + uu, sing, vv = _safe_svd(M, full_matrices=False) + ncomp = u["nfit"] - 1 + uu, sing, vv = uu[:, :ncomp], sing[:ncomp], vv[:ncomp] + return y, uu, sing, vv + + +def _compute_linear_parameters(mu, u): + """Compute the best-fitting linear parameters.""" + y, uu, sing, vv = _compose_linear_fitting_data(mu, u) + + # Compute the residuals + vec = np.dot(y, uu) + resi = y - np.dot(uu, vec) + vec /= sing + + lambda_ = np.zeros(u["nfit"]) + lambda_[1:] = np.dot(vec, vv) + lambda_[0] = u["fn"][0] - np.sum(lambda_[1:]) + rv = np.dot(resi, resi) / np.dot(y, y) + return rv, lambda_ + + +def _one_step(mu, u): + """Evaluate the residual sum of squares fit for one set of mu values.""" + if np.abs(mu).max() >= 1.0: + return 100.0 + + # Compose the data for the linear fitting, compute SVD, then residuals + y, uu, sing, vv = _compose_linear_fitting_data(mu, u) + resi = y - np.dot(uu, np.dot(y, uu)) + return np.dot(resi, resi) + + +def _fwd_eeg_fit_berg_scherg(m, nterms, nfit): + """Fit the Berg-Scherg equivalent spherical model dipole parameters.""" + assert nfit >= 2 + u = dict(nfit=nfit, nterms=nterms) + + # (1) Calculate the coefficients of the true expansion + u["fn"] = _fwd_eeg_get_multi_sphere_model_coeffs(m, nterms + 1) + + # (2) Calculate the weighting + f = min([layer["rad"] for layer in m["layers"]]) / max( + [layer["rad"] for layer in m["layers"]] + ) + + # correct weighting + k = np.arange(1, nterms + 1) + u["w"] = np.sqrt((2.0 * k + 1) * (3.0 * k + 1.0) / k) * np.power(f, (k - 1.0)) + u["w"][-1] = 0 + + # Do the nonlinear minimization, constraining mu to the interval [-1, +1] + mu_0 = np.zeros(3) + fun = partial(_one_step, u=u) + catol = 1e-6 + max_ = 1.0 - 2 * catol + + def cons(x): + return max_ - np.abs(x) + + mu = fmin_cobyla(fun, mu_0, [cons], rhobeg=0.5, rhoend=1e-5, catol=catol) + + # (6) Do the final step: calculation of the linear parameters + rv, lambda_ = _compute_linear_parameters(mu, u) + order = np.argsort(mu)[::-1] + mu, lambda_ = mu[order], lambda_[order] # sort: largest mu first + + m["mu"] = mu + # This division takes into account the actual conductivities + m["lambda"] = lambda_ / m["layers"][-1]["sigma"] + m["nfit"] = nfit + return rv + + +@verbose +def make_sphere_model( + r0=(0.0, 0.0, 0.04), + head_radius=0.09, + info=None, + relative_radii=(0.90, 0.92, 0.97, 1.0), + sigmas=(0.33, 1.0, 0.004, 0.33), + verbose=None, +): + """Create a spherical model for forward solution calculation. + + Parameters + ---------- + r0 : array-like | str + Head center to use (in head coordinates). If 'auto', the head + center will be calculated from the digitization points in info. + head_radius : float | str | None + If float, compute spherical shells for EEG using the given radius. + If ``'auto'``, estimate an appropriate radius from the dig points in the + :class:`~mne.Info` provided by the argument ``info``. + If None, exclude shells (single layer sphere model). + %(info)s Only needed if ``r0`` or ``head_radius`` are ``'auto'``. + relative_radii : array-like + Relative radii for the spherical shells. + sigmas : array-like + Sigma values for the spherical shells. + %(verbose)s + + Returns + ------- + sphere : instance of ConductorModel + The resulting spherical conductor model. + + See Also + -------- + make_bem_model + make_bem_solution + + Notes + ----- + The default model has:: + + relative_radii = (0.90, 0.92, 0.97, 1.0) + sigmas = (0.33, 1.0, 0.004, 0.33) + + These correspond to compartments (with relative radii in ``m`` and + conductivities σ in ``S/m``) for the brain, CSF, skull, and scalp, + respectively. + + .. versionadded:: 0.9.0 + """ + for name in ("r0", "head_radius"): + param = locals()[name] + if isinstance(param, str): + if param != "auto": + raise ValueError(f'{name}, if str, must be "auto" not "{param}"') + relative_radii = np.array(relative_radii, float).ravel() + sigmas = np.array(sigmas, float).ravel() + if len(relative_radii) != len(sigmas): + raise ValueError( + f"relative_radii length ({len(relative_radii)}) must match that of sigmas (" + f"{len(sigmas)})" + ) + if len(sigmas) <= 1 and head_radius is not None: + raise ValueError( + "at least 2 sigmas must be supplied if head_radius is not None, got " + f"{len(sigmas)}" + ) + if (isinstance(r0, str) and r0 == "auto") or ( + isinstance(head_radius, str) and head_radius == "auto" + ): + if info is None: + raise ValueError("Info must not be None for auto mode") + head_radius_fit, r0_fit = fit_sphere_to_headshape(info, units="m")[:2] + if isinstance(r0, str): + r0 = r0_fit + if isinstance(head_radius, str): + head_radius = head_radius_fit + sphere = ConductorModel( + is_sphere=True, r0=np.array(r0), coord_frame=FIFF.FIFFV_COORD_HEAD + ) + sphere["layers"] = list() + if head_radius is not None: + # Eventually these could be configurable... + relative_radii = np.array(relative_radii, float) + sigmas = np.array(sigmas, float) + order = np.argsort(relative_radii) + relative_radii = relative_radii[order] + sigmas = sigmas[order] + for rel_rad, sig in zip(relative_radii, sigmas): + # sort layers by (relative) radius, and scale radii + layer = dict(rad=rel_rad, sigma=sig) + layer["rel_rad"] = layer["rad"] = rel_rad + sphere["layers"].append(layer) + + # scale the radii + R = sphere["layers"][-1]["rad"] + rR = sphere["layers"][-1]["rel_rad"] + for layer in sphere["layers"]: + layer["rad"] /= R + layer["rel_rad"] /= rR + + # + # Setup the EEG sphere model calculations + # + + # Scale the relative radii + for k in range(len(relative_radii)): + sphere["layers"][k]["rad"] = head_radius * sphere["layers"][k]["rel_rad"] + rv = _fwd_eeg_fit_berg_scherg(sphere, 200, 3) + logger.info(f"\nEquiv. model fitting -> RV = {100 * rv:g} %%") + for k in range(3): + s_k = sphere["layers"][-1]["sigma"] * sphere["lambda"][k] + logger.info(f"mu{k + 1} = {sphere['mu'][k]:g} lambda{k + 1} = {s_k:g}") + logger.info( + f"Set up EEG sphere model with scalp radius {1000 * head_radius:7.1f} mm\n" + ) + return sphere + + +# ############################################################################# +# Sphere fitting + + +@verbose +def fit_sphere_to_headshape(info, dig_kinds="auto", units="m", verbose=None): + """Fit a sphere to the headshape points to determine head center. + + Parameters + ---------- + %(info_not_none)s + %(dig_kinds)s + units : str + Can be ``"m"`` (default) or ``"mm"``. + + .. versionadded:: 0.12 + %(verbose)s + + Returns + ------- + radius : float + Sphere radius. + origin_head: ndarray, shape (3,) + Head center in head coordinates. + origin_device: ndarray, shape (3,) + Head center in device coordinates. + + Notes + ----- + This function excludes any points that are low and frontal + (``z < 0 and y > 0``) to improve the fit. + """ + if not isinstance(units, str) or units not in ("m", "mm"): + raise ValueError('units must be a "m" or "mm"') + radius, origin_head, origin_device = _fit_sphere_to_headshape(info, dig_kinds) + if units == "mm": + radius *= 1e3 + origin_head *= 1e3 + origin_device *= 1e3 + return radius, origin_head, origin_device + + +@verbose +def get_fitting_dig(info, dig_kinds="auto", exclude_frontal=True, verbose=None): + """Get digitization points suitable for sphere fitting. + + Parameters + ---------- + %(info_not_none)s + %(dig_kinds)s + %(exclude_frontal)s + Default is True. + + .. versionadded:: 0.19 + %(verbose)s + + Returns + ------- + dig : array, shape (n_pts, 3) + The digitization points (in head coordinates) to use for fitting. + + Notes + ----- + This will exclude digitization locations that have ``z < 0 and y > 0``, + i.e. points on the nose and below the nose on the face. + + .. versionadded:: 0.14 + """ + _validate_type(info, "info") + if info.get("dig", None) is None: # "dig" can be missing for fwd/inv + raise RuntimeError( + 'Cannot fit headshape without digitization, info["dig"] is None' + ) + if isinstance(dig_kinds, str): + if dig_kinds == "auto": + # try "extra" first + try: + return get_fitting_dig(info, "extra") + except ValueError: + pass + return get_fitting_dig(info, ("extra", "eeg")) + else: + dig_kinds = (dig_kinds,) + # convert string args to ints (first make dig_kinds mutable in case tuple) + dig_kinds = list(dig_kinds) + for di, d in enumerate(dig_kinds): + dig_kinds[di] = _dig_kind_dict.get(d, d) + if dig_kinds[di] not in _dig_kind_ints: + raise ValueError( + f"dig_kinds[{di}] ({d}) must be one of {sorted(_dig_kind_dict)}" + ) + + # get head digization points of the specified kind(s) + dig = [p for p in info["dig"] if p["kind"] in dig_kinds] + if len(dig) == 0: + raise ValueError(f"No digitization points found for dig_kinds={dig_kinds}") + if any(p["coord_frame"] != FIFF.FIFFV_COORD_HEAD for p in dig): + raise RuntimeError( + f"Digitization points dig_kinds={dig_kinds} not in head " + "coordinates, contact mne-python developers" + ) + hsp = [p["r"] for p in dig] + del dig + + # exclude some frontal points (nose etc.) + if exclude_frontal: + hsp = [p for p in hsp if not (p[2] < -1e-6 and p[1] > 1e-6)] + hsp = np.array(hsp) + + if len(hsp) <= 10: + kinds_str = ", ".join([f'"{_dig_kind_rev[d]}"' for d in sorted(dig_kinds)]) + msg = ( + f"Only {len(hsp)} head digitization points of the specified " + f"kind{_pl(dig_kinds)} ({kinds_str},)" + ) + if len(hsp) < 4: + raise ValueError(msg + ", at least 4 required") + else: + warn(msg + ", fitting may be inaccurate") + return hsp + + +@verbose +def _fit_sphere_to_headshape(info, dig_kinds, *, verbose=None): + """Fit a sphere to the given head shape.""" + hsp = get_fitting_dig(info, dig_kinds) + radius, origin_head = _fit_sphere(np.array(hsp)) + # compute origin in device coordinates + dev_head_t = info["dev_head_t"] + if dev_head_t is None: + dev_head_t = Transform("meg", "head") + head_to_dev = _ensure_trans(dev_head_t, "head", "meg") + origin_device = apply_trans(head_to_dev, origin_head) + logger.info("Fitted sphere radius:".ljust(30) + f"{radius * 1e3:0.1f} mm") + _check_head_radius(radius) + + # > 2 cm away from head center in X or Y is strange + o_mm = origin_head * 1e3 + o_d = origin_device * 1e3 + if np.linalg.norm(origin_head[:2]) > 0.02: + warn( + f"(X, Y) fit ({o_mm[0]:0.1f}, {o_mm[1]:0.1f}) " + "more than 20 mm from head frame origin" + ) + logger.info( + "Origin head coordinates:".ljust(30) + + f"{o_mm[0]:0.1f} {o_mm[1]:0.1f} {o_mm[2]:0.1f} mm" + ) + logger.info( + "Origin device coordinates:".ljust(30) + + f"{o_d[0]:0.1f} {o_d[1]:0.1f} {o_d[2]:0.1f} mm" + ) + return radius, origin_head, origin_device + + +def _fit_sphere(points): + """Fit a sphere to an arbitrary set of points.""" + # linear least-squares sphere fit, see for example + # https://stackoverflow.com/a/78909044 + # TODO: At some point we should maybe reject outliers first... + A = np.c_[2 * points, np.ones((len(points), 1))] + b = (points**2).sum(axis=1) + x, _, _, _ = np.linalg.lstsq(A, b, rcond=1e-6) + origin = x[:3] + radius = np.sqrt(x[0] ** 2 + x[1] ** 2 + x[2] ** 2 + x[3]) + return radius, origin + + +def _check_origin(origin, info, coord_frame="head", disp=False): + """Check or auto-determine the origin.""" + if isinstance(origin, str): + if origin != "auto": + raise ValueError( + f'origin must be a numerical array, or "auto", not {origin}' + ) + if coord_frame == "head": + R, origin = fit_sphere_to_headshape( + info, verbose=_verbose_safe_false(), units="m" + )[:2] + logger.info(f" Automatic origin fit: head of radius {R * 1000:0.1f} mm") + del R + else: + origin = (0.0, 0.0, 0.0) + origin = np.array(origin, float) + if origin.shape != (3,): + raise ValueError("origin must be a 3-element array") + if disp: + origin_str = ", ".join([f"{o * 1000:0.1f}" for o in origin]) + msg = f" Using origin {origin_str} mm in the {coord_frame} frame" + if coord_frame == "meg" and info["dev_head_t"] is not None: + o_dev = apply_trans(info["dev_head_t"], origin) + origin_str = ", ".join(f"{o * 1000:0.1f}" for o in o_dev) + msg += f" ({origin_str} mm in the head frame)" + logger.info(msg) + return origin + + +# ############################################################################ +# Create BEM surfaces + + +@verbose +def make_watershed_bem( + subject, + subjects_dir=None, + overwrite=False, + volume="T1", + atlas=False, + gcaatlas=False, + preflood=None, + show=False, + copy=True, + T1=None, + brainmask="ws.mgz", + verbose=None, +): + """Create BEM surfaces using the FreeSurfer watershed algorithm. + + See :ref:`bem_watershed_algorithm` for additional information. + + Parameters + ---------- + subject : str + Subject name. + %(subjects_dir)s + %(overwrite)s + volume : str + The name of the MRI volume (without file extension) that + will be used as input to mri_watershed_. The volume is expected to + be full-head (non-skull-stripped), as the watershed algorithm relies on tissue + intensity gradients to estimate the inner skull, outer skull, and + outer skin surfaces. Defaults to ``"T1"``, corresponding to + ``$SUBJECTS_DIR/$SUBJECT/mri/T1.mgz`` in a typical FreeSurfer subject directory. + This volume is typically produced by the recon-all_ pipeline after the intensity + normalization step. + atlas : bool + Specify the ``--atlas option`` for ``mri_watershed``. + gcaatlas : bool + Specify the ``--brain_atlas`` option for ``mri_watershed``. + preflood : int + Change the preflood height. + show : bool + Show surfaces to visually inspect all three BEM surfaces (recommended). + + .. versionadded:: 0.12 + + copy : bool + If True (default), use copies instead of symlinks for surfaces + (if they do not already exist). + + .. versionadded:: 0.18 + .. versionchanged:: 1.1 Use copies instead of symlinks. + T1 : bool | None + If True, pass the ``-T1`` flag. + By default (None), this takes the same value as ``gcaatlas``. + + .. versionadded:: 0.19 + brainmask : str + The filename for the brainmask output file relative to the + ``$SUBJECTS_DIR/$SUBJECT/bem/watershed/`` directory. + Can be for example ``"../../mri/brainmask.mgz"`` to overwrite + the brainmask obtained via ``recon-all -autorecon1``. + + .. versionadded:: 0.19 + %(verbose)s + + See Also + -------- + mne.viz.plot_bem + + Notes + ----- + If your BEM meshes do not look correct when viewed in + :func:`mne.viz.plot_alignment` or :func:`mne.viz.plot_bem`, consider + potential solutions from the :ref:`FAQ `. + + .. versionadded:: 0.10 + """ + env, mri_dir, bem_dir = _prepare_env(subject, subjects_dir) + tempdir = _TempDir() # fsl and Freesurfer create some random junk in CWD + run_subprocess_env = partial(run_subprocess, env=env, cwd=tempdir) + + subjects_dir = env["SUBJECTS_DIR"] # Set by _prepare_env() above. + subject_dir = op.join(subjects_dir, subject) + ws_dir = op.join(bem_dir, "watershed") + T1_dir = op.join(mri_dir, volume) + T1_mgz = T1_dir + if not T1_dir.endswith(".mgz"): + T1_mgz += ".mgz" + + if not op.isdir(bem_dir): + os.makedirs(bem_dir) + _check_fname(T1_mgz, overwrite="read", must_exist=True, name="MRI data") + if op.isdir(ws_dir): + if not overwrite: + raise RuntimeError( + f"{ws_dir} already exists. Use the --overwrite option to recreate it." + ) + else: + shutil.rmtree(ws_dir) + + # put together the command + cmd = ["mri_watershed"] + if preflood: + cmd += ["-h", f"{int(preflood)}"] + + if T1 is None: + T1 = gcaatlas + if T1: + cmd += ["-T1"] + if gcaatlas: + fname = op.join(env["FREESURFER_HOME"], "average", "RB_all_withskull_*.gca") + fname = sorted(glob.glob(fname))[::-1][0] + + # check if FS>8 didn't generate talairach_with_skull.lta + talairach_with_skull_path = os.path.join( + subject_dir, "mri/transforms/talairach_with_skull.lta" + ) + if not os.path.exists(talairach_with_skull_path): + logger.info( + f"{talairach_with_skull_path} does not exist. Running mri_em_register." + ) + em_reg_cmd = [ + "mri_em_register", + "-skull", + subject_dir + "/mri/nu.mgz", + fname, + talairach_with_skull_path, + ] + + run_subprocess_env(em_reg_cmd) + + logger.info(f"Using GCA atlas: {fname}") + cmd += [ + "-atlas", + "-brain_atlas", + fname, + subject_dir + "/mri/transforms/talairach_with_skull.lta", + ] + elif atlas: + cmd += ["-atlas"] + if op.exists(T1_mgz): + cmd += [ + "-useSRAS", + "-surf", + op.join(ws_dir, subject), + T1_mgz, + op.join(ws_dir, brainmask), + ] + else: + cmd += [ + "-useSRAS", + "-surf", + op.join(ws_dir, subject), + T1_dir, + op.join(ws_dir, brainmask), + ] + # report and run + logger.info( + "\nRunning mri_watershed for BEM segmentation with the following parameters:\n" + f"\nResults dir = {ws_dir}\nCommand = {' '.join(cmd)}\n" + ) + os.makedirs(op.join(ws_dir)) + run_subprocess_env(cmd) + del tempdir # clean up directory + if op.isfile(T1_mgz): + new_info = _extract_volume_info(T1_mgz) + if not new_info: + warn( + "nibabel is not available or the volume info is invalid. Volume info " + "not updated in the written surface." + ) + surfs = ["brain", "inner_skull", "outer_skull", "outer_skin"] + for s in surfs: + surf_ws_out = op.join(ws_dir, f"{subject}_{s}_surface") + + rr, tris, volume_info = read_surface(surf_ws_out, read_metadata=True) + # replace volume info, 'head' stays + volume_info.update(new_info) + write_surface( + surf_ws_out, rr, tris, volume_info=volume_info, overwrite=True + ) + + # Create symbolic links + surf_out = op.join(bem_dir, f"{s}.surf") + if not overwrite and op.exists(surf_out): + skip_symlink = True + else: + if op.exists(surf_out): + os.remove(surf_out) + _symlink(surf_ws_out, surf_out, copy) + skip_symlink = False + + if skip_symlink: + logger.info( + "Unable to create all symbolic links to .surf files in bem folder. Use " + "--overwrite option to recreate them." + ) + dest = op.join(bem_dir, "watershed") + else: + logger.info("Symbolic links to .surf files created in bem folder") + dest = bem_dir + + logger.info( + "\nThank you for waiting.\nThe BEM triangulations for this subject are now " + f"available at:\n{dest}." + ) + + # Write a head file for coregistration + fname_head = op.join(bem_dir, subject + "-head.fif") + if op.isfile(fname_head): + os.remove(fname_head) + + surf = _surfaces_to_bem( + [op.join(ws_dir, subject + "_outer_skin_surface")], + [FIFF.FIFFV_BEM_SURF_ID_HEAD], + sigmas=[1], + ) + write_bem_surfaces(fname_head, surf) + + # Show computed BEM surfaces + if show: + plot_bem( + subject=subject, + subjects_dir=subjects_dir, + orientation="coronal", + slices=None, + show=True, + ) + + logger.info(f"Created {fname_head}\n\nComplete.") + + +def _extract_volume_info(mgz): + """Extract volume info from a mgz file.""" + nib = _import_nibabel() + header = nib.load(mgz).header + version = header["version"] + vol_info = dict() + if version == 1: + version = f"{version} # volume info valid" + vol_info["valid"] = version + vol_info["filename"] = mgz + vol_info["volume"] = header["dims"][:3] + vol_info["voxelsize"] = header["delta"] + vol_info["xras"], vol_info["yras"], vol_info["zras"] = header["Mdc"] + vol_info["cras"] = header["Pxyz_c"] + + return vol_info + + +# ############################################################################ +# Read + + +@verbose +def read_bem_surfaces( + fname, patch_stats=False, s_id=None, on_defects="raise", verbose=None +): + """Read the BEM surfaces from a FIF file. + + Parameters + ---------- + fname : path-like + The name of the file containing the surfaces. + patch_stats : bool, optional (default False) + Calculate and add cortical patch statistics to the surfaces. + s_id : int | None + If int, only read and return the surface with the given ``s_id``. + An error will be raised if it doesn't exist. If None, all + surfaces are read and returned. + %(on_defects)s + + .. versionadded:: 0.23 + %(verbose)s + + Returns + ------- + surf: list | dict + A list of dictionaries that each contain a surface. If ``s_id`` + is not None, only the requested surface will be returned. + + See Also + -------- + write_bem_surfaces, write_bem_solution, make_bem_model + """ + # Open the file, create directory + _validate_type(s_id, ("int-like", None), "s_id") + fname = _check_fname(fname, "read", True, "fname") + if fname.suffix == ".h5": + surf = _read_bem_surfaces_h5(fname, s_id) + else: + surf = _read_bem_surfaces_fif(fname, s_id) + if s_id is not None and len(surf) != 1: + raise ValueError(f"surface with id {s_id} not found") + for this in surf: + if patch_stats or this["nn"] is None: + _check_complete_surface(this, incomplete=on_defects) + return surf[0] if s_id is not None else surf + + +def _read_bem_surfaces_h5(fname, s_id): + read_hdf5, _ = _import_h5io_funcs() + bem = read_hdf5(fname) + try: + [s["id"] for s in bem["surfs"]] + except Exception: # not our format + raise ValueError("BEM data not found") + surf = bem["surfs"] + if s_id is not None: + surf = [s for s in surf if s["id"] == s_id] + return surf + + +def _read_bem_surfaces_fif(fname, s_id): + # Default coordinate frame + coord_frame = FIFF.FIFFV_COORD_MRI + f, tree, _ = fiff_open(fname) + with f as fid: + # Find BEM + bem = dir_tree_find(tree, FIFF.FIFFB_BEM) + if bem is None or len(bem) == 0: + raise ValueError("BEM data not found") + + bem = bem[0] + # Locate all surfaces + bemsurf = dir_tree_find(bem, FIFF.FIFFB_BEM_SURF) + if bemsurf is None: + raise ValueError("BEM surface data not found") + + logger.info(f" {len(bemsurf)} BEM surfaces found") + # Coordinate frame possibly at the top level + tag = find_tag(fid, bem, FIFF.FIFF_BEM_COORD_FRAME) + if tag is not None: + coord_frame = tag.data + # Read all surfaces + if s_id is not None: + surf = [ + _read_bem_surface(fid, bsurf, coord_frame, s_id) for bsurf in bemsurf + ] + surf = [s for s in surf if s is not None] + else: + surf = list() + for bsurf in bemsurf: + logger.info(" Reading a surface...") + this = _read_bem_surface(fid, bsurf, coord_frame) + surf.append(this) + logger.info("[done]") + logger.info(f" {len(surf)} BEM surfaces read") + return surf + + +def _read_bem_surface(fid, this, def_coord_frame, s_id=None): + """Read one bem surface.""" + # fid should be open as a context manager here + res = dict() + # Read all the interesting stuff + tag = find_tag(fid, this, FIFF.FIFF_BEM_SURF_ID) + + if tag is None: + res["id"] = FIFF.FIFFV_BEM_SURF_ID_UNKNOWN + else: + res["id"] = int(tag.data.item()) + + if s_id is not None and res["id"] != s_id: + return None + + tag = find_tag(fid, this, FIFF.FIFF_BEM_SIGMA) + res["sigma"] = 1.0 if tag is None else float(tag.data.item()) + + tag = find_tag(fid, this, FIFF.FIFF_BEM_SURF_NNODE) + if tag is None: + raise ValueError("Number of vertices not found") + + res["np"] = int(tag.data.item()) + + tag = find_tag(fid, this, FIFF.FIFF_BEM_SURF_NTRI) + if tag is None: + raise ValueError("Number of triangles not found") + res["ntri"] = int(tag.data.item()) + + tag = find_tag(fid, this, FIFF.FIFF_MNE_COORD_FRAME) + if tag is None: + tag = find_tag(fid, this, FIFF.FIFF_BEM_COORD_FRAME) + if tag is None: + res["coord_frame"] = def_coord_frame + else: + res["coord_frame"] = int(tag.data.item()) + else: + res["coord_frame"] = int(tag.data.item()) + + # Vertices, normals, and triangles + tag = find_tag(fid, this, FIFF.FIFF_BEM_SURF_NODES) + if tag is None: + raise ValueError("Vertex data not found") + + res["rr"] = tag.data.astype(np.float64) + if res["rr"].shape[0] != res["np"]: + raise ValueError("Vertex information is incorrect") + + tag = find_tag(fid, this, FIFF.FIFF_MNE_SOURCE_SPACE_NORMALS) + if tag is None: + tag = find_tag(fid, this, FIFF.FIFF_BEM_SURF_NORMALS) + if tag is None: + res["nn"] = None + else: + res["nn"] = tag.data.astype(np.float64) + if res["nn"].shape[0] != res["np"]: + raise ValueError("Vertex normal information is incorrect") + + tag = find_tag(fid, this, FIFF.FIFF_BEM_SURF_TRIANGLES) + if tag is None: + raise ValueError("Triangulation not found") + + res["tris"] = tag.data - 1 # index start at 0 in Python + if res["tris"].shape[0] != res["ntri"]: + raise ValueError("Triangulation information is incorrect") + + return res + + +@verbose +def read_bem_solution(fname, *, verbose=None): + """Read the BEM solution from a file. + + Parameters + ---------- + fname : path-like + The file containing the BEM solution. + %(verbose)s + + Returns + ------- + bem : instance of ConductorModel + The BEM solution. + + See Also + -------- + read_bem_surfaces + write_bem_surfaces + make_bem_solution + write_bem_solution + """ + fname = _check_fname(fname, "read", True, "fname") + # mirrors fwd_bem_load_surfaces from fwd_bem_model.c + if fname.suffix == ".h5": + read_hdf5, _ = _import_h5io_funcs() + logger.info("Loading surfaces and solution...") + bem = read_hdf5(fname) + if "solver" not in bem: + bem["solver"] = "mne" + else: + bem = _read_bem_solution_fif(fname) + + if len(bem["surfs"]) == 3: + logger.info("Three-layer model surfaces loaded.") + needed = np.array( + [ + FIFF.FIFFV_BEM_SURF_ID_HEAD, + FIFF.FIFFV_BEM_SURF_ID_SKULL, + FIFF.FIFFV_BEM_SURF_ID_BRAIN, + ] + ) + if not all(x["id"] in needed for x in bem["surfs"]): + raise RuntimeError("Could not find necessary BEM surfaces") + # reorder surfaces as necessary (shouldn't need to?) + reorder = [None] * 3 + for x in bem["surfs"]: + reorder[np.where(x["id"] == needed)[0][0]] = x + bem["surfs"] = reorder + elif len(bem["surfs"]) == 1: + if not bem["surfs"][0]["id"] == FIFF.FIFFV_BEM_SURF_ID_BRAIN: + raise RuntimeError("BEM Surfaces not found") + logger.info("Homogeneous model surface loaded.") + + assert set(bem.keys()) == set(("surfs", "solution", "bem_method", "solver")) + bem = ConductorModel(bem) + bem["is_sphere"] = False + # sanity checks and conversions + _check_option( + "BEM approximation method", bem["bem_method"], (FIFF.FIFFV_BEM_APPROX_LINEAR,) + ) # CONSTANT not supported + dim = 0 + solver = bem.get("solver", "mne") + _check_option("BEM solver", solver, ("mne", "openmeeg")) + for si, surf in enumerate(bem["surfs"]): + assert bem["bem_method"] == FIFF.FIFFV_BEM_APPROX_LINEAR + dim += surf["np"] + if solver == "openmeeg" and si != 0: + dim += surf["ntri"] + dims = bem["solution"].shape + if solver == "openmeeg": + sz = (dim * (dim + 1)) // 2 + if len(dims) != 1 or dims[0] != sz: + raise RuntimeError( + "For the given BEM surfaces, OpenMEEG should produce a " + f"solution matrix of shape ({sz},) but got {dims}" + ) + bem["nsol"] = dim + else: + if len(dims) != 2 and solver != "openmeeg": + raise RuntimeError( + "Expected a two-dimensional solution matrix " + f"instead of a {dims[0]} dimensional one" + ) + if dims[0] != dim or dims[1] != dim: + raise RuntimeError( + f"Expected a {dim} x {dim} solution matrix instead of " + f"a {dims[1]} x {dims[0]} one" + ) + bem["nsol"] = bem["solution"].shape[0] + # Gamma factors and multipliers + _add_gamma_multipliers(bem) + extra = f"made by {solver}" if solver != "mne" else "" + logger.info(f"Loaded linear collocation BEM solution{extra} from {fname}") + return bem + + +def _read_bem_solution_fif(fname): + logger.info("Loading surfaces...") + surfs = read_bem_surfaces(fname, patch_stats=True, verbose=_verbose_safe_false()) + + # convert from surfaces to solution + logger.info("\nLoading the solution matrix...\n") + solver = "mne" + f, tree, _ = fiff_open(fname) + with f as fid: + # Find the BEM data + nodes = dir_tree_find(tree, FIFF.FIFFB_BEM) + if len(nodes) == 0: + raise RuntimeError(f"No BEM data in {fname}") + bem_node = nodes[0] + + # Approximation method + tag = find_tag(f, bem_node, FIFF.FIFF_DESCRIPTION) + if tag is not None: + tag = json.loads(tag.data) + solver = tag["solver"] + tag = find_tag(f, bem_node, FIFF.FIFF_BEM_APPROX) + if tag is None: + raise RuntimeError(f"No BEM solution found in {fname}") + method = tag.data[0] + tag = find_tag(fid, bem_node, FIFF.FIFF_BEM_POT_SOLUTION) + sol = tag.data + + return dict(solution=sol, bem_method=method, surfs=surfs, solver=solver) + + +def _add_gamma_multipliers(bem): + """Add gamma and multipliers in-place.""" + bem["sigma"] = np.array([surf["sigma"] for surf in bem["surfs"]]) + # Dirty trick for the zero conductivity outside + sigma = np.r_[0.0, bem["sigma"]] + bem["source_mult"] = 2.0 / (sigma[1:] + sigma[:-1]) + bem["field_mult"] = sigma[1:] - sigma[:-1] + # make sure subsequent "zip"s work correctly + assert len(bem["surfs"]) == len(bem["field_mult"]) + bem["gamma"] = (sigma[1:] - sigma[:-1])[np.newaxis, :] / (sigma[1:] + sigma[:-1])[ + :, np.newaxis + ] + + +# In our BEM code we do not model the CSF so we assign the innermost surface +# the id BRAIN. Our 4-layer sphere we model CSF (at least by default), so when +# searching for and referring to surfaces we need to keep track of this. +_sm_surf_dict = OrderedDict( + [ + ("brain", FIFF.FIFFV_BEM_SURF_ID_BRAIN), + ("inner_skull", FIFF.FIFFV_BEM_SURF_ID_CSF), + ("outer_skull", FIFF.FIFFV_BEM_SURF_ID_SKULL), + ("head", FIFF.FIFFV_BEM_SURF_ID_HEAD), + ] +) +_bem_surf_dict = { + "inner_skull": FIFF.FIFFV_BEM_SURF_ID_BRAIN, + "outer_skull": FIFF.FIFFV_BEM_SURF_ID_SKULL, + "head": FIFF.FIFFV_BEM_SURF_ID_HEAD, +} +_bem_surf_name = { + FIFF.FIFFV_BEM_SURF_ID_BRAIN: "inner skull", + FIFF.FIFFV_BEM_SURF_ID_SKULL: "outer skull", + FIFF.FIFFV_BEM_SURF_ID_HEAD: "outer skin ", + FIFF.FIFFV_BEM_SURF_ID_UNKNOWN: "unknown ", + FIFF.FIFFV_MNE_SURF_MEG_HELMET: "MEG helmet ", +} +_sm_surf_name = { + FIFF.FIFFV_BEM_SURF_ID_BRAIN: "brain", + FIFF.FIFFV_BEM_SURF_ID_CSF: "csf", + FIFF.FIFFV_BEM_SURF_ID_SKULL: "outer skull", + FIFF.FIFFV_BEM_SURF_ID_HEAD: "outer skin ", + FIFF.FIFFV_BEM_SURF_ID_UNKNOWN: "unknown ", + FIFF.FIFFV_MNE_SURF_MEG_HELMET: "helmet", +} + + +def _bem_find_surface(bem, id_): + """Find surface from already-loaded conductor model.""" + if bem["is_sphere"]: + _surf_dict = _sm_surf_dict + _name_dict = _sm_surf_name + kind = "Sphere model" + tri = "boundary" + else: + _surf_dict = _bem_surf_dict + _name_dict = _bem_surf_name + kind = "BEM" + tri = "triangulation" + if isinstance(id_, str): + name = id_ + id_ = _surf_dict[id_] + else: + name = _name_dict[id_] + kind = "Sphere model" if bem["is_sphere"] else "BEM" + idx = np.where(np.array([s["id"] for s in bem["surfs"]]) == id_)[0] + if len(idx) != 1: + raise RuntimeError(f"{kind} does not have the {name} {tri}") + return bem["surfs"][idx[0]] + + +# ############################################################################ +# Write + + +@verbose +def write_bem_surfaces(fname, surfs, overwrite=False, *, verbose=None): + """Write BEM surfaces to a FIF file. + + Parameters + ---------- + fname : path-like + Filename to write. Can end with ``.h5`` to write using HDF5. + surfs : dict | list of dict + The surfaces, or a single surface. + %(overwrite)s + %(verbose)s + """ + if isinstance(surfs, dict): + surfs = [surfs] + fname = _check_fname(fname, overwrite=overwrite, name="fname") + + if fname.suffix == ".h5": + _, write_hdf5 = _import_h5io_funcs() + write_hdf5(fname, dict(surfs=surfs), overwrite=True) + else: + with start_and_end_file(fname) as fid: + start_block(fid, FIFF.FIFFB_BEM) + write_int(fid, FIFF.FIFF_BEM_COORD_FRAME, surfs[0]["coord_frame"]) + _write_bem_surfaces_block(fid, surfs) + end_block(fid, FIFF.FIFFB_BEM) + + +@verbose +def write_head_bem( + fname, rr, tris, on_defects="raise", overwrite=False, *, verbose=None +): + """Write a head surface to a FIF file. + + Parameters + ---------- + fname : path-like + Filename to write. + rr : array, shape (n_vertices, 3) + Coordinate points in the MRI coordinate system. + tris : ndarray of int, shape (n_tris, 3) + Triangulation (each line contains indices for three points which + together form a face). + %(on_defects)s + %(overwrite)s + %(verbose)s + """ + surf = _surfaces_to_bem( + [dict(rr=rr, tris=tris)], + [FIFF.FIFFV_BEM_SURF_ID_HEAD], + [1], + rescale=False, + incomplete=on_defects, + ) + write_bem_surfaces(fname, surf, overwrite=overwrite) + + +def _write_bem_surfaces_block(fid, surfs): + """Write bem surfaces to open file handle.""" + for surf in surfs: + start_block(fid, FIFF.FIFFB_BEM_SURF) + if "sigma" in surf: + write_float(fid, FIFF.FIFF_BEM_SIGMA, surf["sigma"]) + write_int(fid, FIFF.FIFF_BEM_SURF_ID, surf["id"]) + write_int(fid, FIFF.FIFF_MNE_COORD_FRAME, surf["coord_frame"]) + write_int(fid, FIFF.FIFF_BEM_SURF_NNODE, surf["np"]) + write_int(fid, FIFF.FIFF_BEM_SURF_NTRI, surf["ntri"]) + write_float_matrix(fid, FIFF.FIFF_BEM_SURF_NODES, surf["rr"]) + # index start at 0 in Python + write_int_matrix(fid, FIFF.FIFF_BEM_SURF_TRIANGLES, surf["tris"] + 1) + if "nn" in surf and surf["nn"] is not None and len(surf["nn"]) > 0: + write_float_matrix(fid, FIFF.FIFF_BEM_SURF_NORMALS, surf["nn"]) + end_block(fid, FIFF.FIFFB_BEM_SURF) + + +@verbose +def write_bem_solution(fname, bem, overwrite=False, *, verbose=None): + """Write a BEM model with solution. + + Parameters + ---------- + fname : path-like + The filename to use. Can end with ``.h5`` to write using HDF5. + bem : instance of ConductorModel + The BEM model with solution to save. + %(overwrite)s + %(verbose)s + + See Also + -------- + read_bem_solution + """ + fname = _check_fname(fname, overwrite=overwrite, name="fname") + if fname.suffix == ".h5": + _, write_hdf5 = _import_h5io_funcs() + bem = {k: bem[k] for k in ("surfs", "solution", "bem_method")} + write_hdf5(fname, bem, overwrite=True) + else: + _write_bem_solution_fif(fname, bem) + + +def _write_bem_solution_fif(fname, bem): + _check_bem_size(bem["surfs"]) + with start_and_end_file(fname) as fid: + start_block(fid, FIFF.FIFFB_BEM) + # Coordinate frame (mainly for backward compatibility) + write_int(fid, FIFF.FIFF_BEM_COORD_FRAME, bem["surfs"][0]["coord_frame"]) + solver = bem.get("solver", "mne") + if solver != "mne": + write_string(fid, FIFF.FIFF_DESCRIPTION, json.dumps(dict(solver=solver))) + # Surfaces + _write_bem_surfaces_block(fid, bem["surfs"]) + # The potential solution + if "solution" in bem: + _check_option( + "bem_method", bem["bem_method"], (FIFF.FIFFV_BEM_APPROX_LINEAR,) + ) + write_int(fid, FIFF.FIFF_BEM_APPROX, FIFF.FIFFV_BEM_APPROX_LINEAR) + write_float_matrix(fid, FIFF.FIFF_BEM_POT_SOLUTION, bem["solution"]) + end_block(fid, FIFF.FIFFB_BEM) + + +# ############################################################################# +# Create 3-Layers BEM model from Flash MRI images + + +def _prepare_env(subject, subjects_dir): + """Prepare an env object for subprocess calls.""" + env = os.environ.copy() + + fs_home = _check_freesurfer_home() + + _validate_type(subject, "str") + + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + subject_dir = subjects_dir / subject + if not subject_dir.is_dir(): + raise RuntimeError(f'Could not find the subject data directory "{subject_dir}"') + env.update(SUBJECT=subject, SUBJECTS_DIR=str(subjects_dir), FREESURFER_HOME=fs_home) + mri_dir = subject_dir / "mri" + bem_dir = subject_dir / "bem" + return env, mri_dir, bem_dir + + +def _write_echos(mri_dir, flash_echos, angle): + nib = _import_nibabel("write echoes") + from nibabel.spatialimages import SpatialImage + + if _path_like(flash_echos): + flash_echos = nib.load(flash_echos) + if isinstance(flash_echos, SpatialImage): + flash_echo_imgs = [] + data = np.asanyarray(flash_echos.dataobj) + affine = flash_echos.affine + if data.ndim == 3: + data = data[..., np.newaxis] + for echo_idx in range(data.shape[3]): + this_echo_img = flash_echos.__class__( + data[..., echo_idx], affine=affine, header=deepcopy(flash_echos.header) + ) + flash_echo_imgs.append(this_echo_img) + flash_echos = flash_echo_imgs + del flash_echo_imgs + for idx, flash_echo in enumerate(flash_echos, 1): + if _path_like(flash_echo): + flash_echo = nib.load(flash_echo) + nib.save(flash_echo, op.join(mri_dir, "flash", f"mef{angle}_{idx:03d}.mgz")) + + +@verbose +def convert_flash_mris( + subject, flash30=True, unwarp=False, subjects_dir=None, flash5=True, verbose=None +): + """Synthesize the flash 5 files for use with make_flash_bem. + + This function aims to produce a synthesized flash 5 MRI from + multiecho flash (MEF) MRI data. This function can use MEF data + with 5 or 30 flip angles. If flash5 (and flash30) images are not + explicitly provided, it will assume that the different echos are available + in the mri/flash folder of the subject with the following naming + convention "mef_.mgz", e.g. "mef05_001.mgz" + or "mef30_001.mgz". + + Parameters + ---------- + %(subject)s + flash30 : bool | list of SpatialImage or path-like | SpatialImage | path-like + If False do not use 30-degree flip angle data. + The list of flash 5 echos to use. If True it will look for files + named mef30_*.mgz in the subject's mri/flash directory and if not False + the list of flash 5 echos images will be written to the mri/flash + folder with convention mef05_.mgz. If a SpatialImage object + each frame of the image will be interpreted as an echo. + unwarp : bool + Run grad_unwarp with -unwarp option on each of the converted + data sets. It requires FreeSurfer's MATLAB toolbox to be properly + installed. + %(subjects_dir)s + flash5 : list of SpatialImage or path-like | SpatialImage | path-like | True + The list of flash 5 echos to use. If True it will look for files + named mef05_*.mgz in the subject's mri/flash directory and if not None + the list of flash 5 echos images will be written to the mri/flash + folder with convention mef05_.mgz. If a SpatialImage object + each frame of the image will be interpreted as an echo. + %(verbose)s + + Returns + ------- + flash5_img : path-like + The path the synthesized flash 5 MRI. + + Notes + ----- + This function assumes that the Freesurfer segmentation of the subject + has been completed. In particular, the T1.mgz and brain.mgz MRI volumes + should be, as usual, in the subject's mri directory. + """ # noqa: E501 + env, mri_dir = _prepare_env(subject, subjects_dir)[:2] + tempdir = _TempDir() # fsl and Freesurfer create some random junk in CWD + run_subprocess_env = partial(run_subprocess, env=env, cwd=tempdir) + + mri_dir = Path(mri_dir) + # Step 1a : Data conversion to mgz format + flash_dir = mri_dir / "flash" + pm_dir = flash_dir / "parameter_maps" + pm_dir.mkdir(parents=True, exist_ok=True) + echos_done = 0 + + if not isinstance(flash5, bool): + _write_echos(mri_dir, flash5, angle="05") + if not isinstance(flash30, bool): + _write_echos(mri_dir, flash30, angle="30") + + # Step 1b : Run grad_unwarp on converted files + template = op.join(flash_dir, "mef*_*.mgz") + files = sorted(glob.glob(template)) + if len(files) == 0: + raise ValueError(f"No suitable source files found ({template})") + if unwarp: + logger.info("\n---- Unwarp mgz data sets ----") + for infile in files: + outfile = infile.replace(".mgz", "u.mgz") + cmd = ["grad_unwarp", "-i", infile, "-o", outfile, "-unwarp", "true"] + run_subprocess_env(cmd) + # Clear parameter maps if some of the data were reconverted + if echos_done > 0 and pm_dir.exists(): + shutil.rmtree(pm_dir) + logger.info("\nParameter maps directory cleared") + if not pm_dir.exists(): + pm_dir.mkdir(parents=True, exist_ok=True) + # Step 2 : Create the parameter maps + if flash30: + logger.info("\n---- Creating the parameter maps ----") + if unwarp: + files = sorted(glob.glob(op.join(flash_dir, "mef05_*u.mgz"))) + if len(os.listdir(pm_dir)) == 0: + cmd = ["mri_ms_fitparms"] + files + [str(pm_dir)] + run_subprocess_env(cmd) + else: + logger.info("Parameter maps were already computed") + # Step 3 : Synthesize the flash 5 images + logger.info("\n---- Synthesizing flash 5 images ----") + if not (pm_dir / "flash5.mgz").exists(): + cmd = [ + "mri_synthesize", + "20", + "5", + "5", + (pm_dir / "T1.mgz"), + (pm_dir / "PD.mgz"), + (pm_dir / "flash5.mgz"), + ] + run_subprocess_env(cmd) + (pm_dir / "flash5_reg.mgz").unlink(missing_ok=True) + else: + logger.info("Synthesized flash 5 volume is already there") + else: + logger.info("\n---- Averaging flash5 echoes ----") + template = "mef05_*u.mgz" if unwarp else "mef05_*.mgz" + files = sorted(flash_dir.glob(template)) + if len(files) == 0: + raise ValueError(f"No suitable source files found ({template})") + cmd = ["mri_average", "-noconform"] + files + [pm_dir / "flash5.mgz"] + run_subprocess_env(cmd) + (pm_dir / "flash5_reg.mgz").unlink(missing_ok=True) + del tempdir # finally done running subprocesses + assert (pm_dir / "flash5.mgz").exists() + return pm_dir / "flash5.mgz" + + +@verbose +def make_flash_bem( + subject, + overwrite=False, + show=True, + subjects_dir=None, + copy=True, + *, + flash5_img=None, + register=True, + verbose=None, +): + """Create 3-Layer BEM model from prepared flash MRI images. + + See :ref:`bem_flash_algorithm` for additional information. + + Parameters + ---------- + %(subject)s + overwrite : bool + Write over existing .surf files in bem folder. + show : bool + Show surfaces to visually inspect all three BEM surfaces (recommended). + %(subjects_dir)s + copy : bool + If True (default), use copies instead of symlinks for surfaces + (if they do not already exist). + + .. versionadded:: 0.18 + .. versionchanged:: 1.1 Use copies instead of symlinks. + flash5_img : None | path-like | Nifti1Image + The path to the synthesized flash 5 MRI image or the image itself. If + None (default), the path defaults to + ``mri/flash/parameter_maps/flash5.mgz`` within the subject + reconstruction. If not present the image is copied or written to the + default location. + + .. versionadded:: 1.1.0 + register : bool + Register the flash 5 image with T1.mgz file. If False, we assume + that the images are already coregistered. + + .. versionadded:: 1.1.0 + %(verbose)s + + See Also + -------- + convert_flash_mris + + Notes + ----- + This program assumes that FreeSurfer is installed and sourced properly. + + This function extracts the BEM surfaces (outer skull, inner skull, and + outer skin) from a FLASH 5 MRI image synthesized from multiecho FLASH + images acquired with spin angles of 5 and 30 degrees. + """ + env, mri_dir, bem_dir = _prepare_env(subject, subjects_dir) + tempdir = _TempDir() # fsl and Freesurfer create some random junk in CWD + run_subprocess_env = partial(run_subprocess, env=env, cwd=tempdir) + + mri_dir = Path(mri_dir) + bem_dir = Path(bem_dir) + subjects_dir = env["SUBJECTS_DIR"] + flash_path = (mri_dir / "flash" / "parameter_maps").resolve() + flash_path.mkdir(exist_ok=True, parents=True) + + logger.info( + "\nProcessing the flash MRI data to produce BEM meshes with the following " + f"parameters:\nSUBJECTS_DIR = {subjects_dir}\nSUBJECT = {subject}\nResult dir =" + f"{bem_dir / 'flash'}\n" + ) + # Step 4 : Register with MPRAGE + flash5 = flash_path / "flash5.mgz" + + if _path_like(flash5_img): + logger.info(f"Copying flash 5 image {flash5_img} to {flash5}") + cmd = ["mri_convert", Path(flash5_img).resolve(), flash5] + run_subprocess_env(cmd) + elif flash5_img is None: + if not flash5.exists(): + raise ValueError(f"Flash 5 image cannot be found at {flash5}.") + else: + logger.info(f"Writing flash 5 image at {flash5}") + nib = _import_nibabel("write an MRI image") + nib.save(flash5_img, flash5) + + if register: + logger.info("\n---- Registering flash 5 with T1 MPRAGE ----") + flash5_reg = flash_path / "flash5_reg.mgz" + if not flash5_reg.exists(): + if (mri_dir / "T1.mgz").exists(): + ref_volume = mri_dir / "T1.mgz" + else: + ref_volume = mri_dir / "T1" + cmd = [ + "fsl_rigid_register", + "-r", + str(ref_volume), + "-i", + str(flash5), + "-o", + str(flash5_reg), + ] + run_subprocess_env(cmd) + else: + logger.info("Registered flash 5 image is already there") + else: + flash5_reg = flash5 + + # Step 5a : Convert flash5 into COR + logger.info("\n---- Converting flash5 volume into COR format ----") + flash5_dir = mri_dir / "flash5" + shutil.rmtree(flash5_dir, ignore_errors=True) + flash5_dir.mkdir(exist_ok=True, parents=True) + cmd = ["mri_convert", flash5_reg, flash5_dir] + run_subprocess_env(cmd) + # Step 5b and c : Convert the mgz volumes into COR + convert_T1 = False + T1_dir = mri_dir / "T1" + if not T1_dir.is_dir() or len(list(T1_dir.glob("COR*"))) == 0: + convert_T1 = True + convert_brain = False + brain_dir = mri_dir / "brain" + if not brain_dir.is_dir() or len(list(brain_dir.glob("COR*"))) == 0: + convert_brain = True + logger.info("\n---- Converting T1 volume into COR format ----") + if convert_T1: + T1_fname = mri_dir / "T1.mgz" + if not T1_fname.is_file(): + raise RuntimeError("Both T1 mgz and T1 COR volumes missing.") + T1_dir.mkdir(exist_ok=True, parents=True) + cmd = ["mri_convert", T1_fname, T1_dir] + run_subprocess_env(cmd) + else: + logger.info("T1 volume is already in COR format") + logger.info("\n---- Converting brain volume into COR format ----") + if convert_brain: + brain_fname = mri_dir / "brain.mgz" + if not brain_fname.is_file(): + raise RuntimeError("Both brain mgz and brain COR volumes missing.") + brain_dir.mkdir(exist_ok=True, parents=True) + cmd = ["mri_convert", brain_fname, brain_dir] + run_subprocess_env(cmd) + else: + logger.info("Brain volume is already in COR format") + # Finally ready to go + logger.info("\n---- Creating the BEM surfaces ----") + cmd = ["mri_make_bem_surfaces", subject] + run_subprocess_env(cmd) + del tempdir # ran our last subprocess; clean up directory + + logger.info("\n---- Converting the tri files into surf files ----") + flash_bem_dir = bem_dir / "flash" + flash_bem_dir.mkdir(exist_ok=True, parents=True) + surfs = ["inner_skull", "outer_skull", "outer_skin"] + for surf in surfs: + out_fname = flash_bem_dir / (surf + ".tri") + shutil.move(bem_dir / (surf + ".tri"), out_fname) + nodes, tris = read_tri(out_fname, swap=True) + # Do not write volume info here because the tris are already in + # standard Freesurfer coords + write_surface(op.splitext(out_fname)[0] + ".surf", nodes, tris, overwrite=True) + + # Cleanup section + logger.info("\n---- Cleaning up ----") + (bem_dir / "inner_skull_tmp.tri").unlink() + if convert_T1: + shutil.rmtree(T1_dir) + logger.info("Deleted the T1 COR volume") + if convert_brain: + shutil.rmtree(brain_dir) + logger.info("Deleted the brain COR volume") + shutil.rmtree(flash5_dir) + logger.info("Deleted the flash5 COR volume") + # Create symbolic links to the .surf files in the bem folder + logger.info("\n---- Creating symbolic links ----") + # os.chdir(bem_dir) + for surf in surfs: + surf = bem_dir / (surf + ".surf") + if not overwrite and surf.exists(): + skip_symlink = True + else: + if surf.exists(): + surf.unlink() + _symlink(flash_bem_dir / surf.name, surf, copy) + skip_symlink = False + if skip_symlink: + logger.info( + "Unable to create all symbolic links to .surf files " + "in bem folder. Use --overwrite option to recreate them." + ) + dest = bem_dir / "flash" + else: + logger.info("Symbolic links to .surf files created in bem folder") + dest = bem_dir + logger.info( + "\nThank you for waiting.\nThe BEM triangulations for this " + f"subject are now available at:\n{dest}.\nWe hope the BEM meshes " + "created will facilitate your MEG and EEG data analyses." + ) + # Show computed BEM surfaces + if show: + plot_bem( + subject=subject, + subjects_dir=subjects_dir, + orientation="coronal", + slices=None, + show=True, + ) + + +def _check_bem_size(surfs): + """Check bem surface sizes.""" + if len(surfs) > 1 and surfs[0]["np"] > 10000: + warn( + f"The bem surfaces have {surfs[0]['np']} data points. 5120 (ico grade=4) " + "should be enough. Dense 3-layer bems may not save properly." + ) + + +def _symlink(src, dest, copy=False): + """Create a relative symlink (or just copy).""" + if not copy: + src_link = op.relpath(src, op.dirname(dest)) + try: + os.symlink(src_link, dest) + except OSError: + warn( + f"Could not create symbolic link {dest}. Check that your " + "partition handles symbolic links. The file will be copied " + "instead." + ) + copy = True + if copy: + shutil.copy(src, dest) + + +def _ensure_bem_surfaces(bem, extra_allow=(), name="bem"): + # by default only allow path-like and list, but handle None and + # ConductorModel properly if need be. Always return a ConductorModel + # even though it's incomplete (and might have is_sphere=True). + assert all(extra in (None, ConductorModel) for extra in extra_allow) + allowed = ("path-like", list) + extra_allow + _validate_type(bem, allowed, name) + if isinstance(bem, path_like): + # Load the surfaces + logger.info(f"Loading BEM surfaces from {bem}...") + bem = read_bem_surfaces(bem) + bem = ConductorModel(is_sphere=False, surfs=bem) + elif isinstance(bem, list): + for ii, this_surf in enumerate(bem): + _validate_type(this_surf, dict, f"{name}[{ii}]") + if isinstance(bem, list): + bem = ConductorModel(is_sphere=False, surfs=bem) + # add surfaces in the spherical case + if isinstance(bem, ConductorModel) and bem["is_sphere"]: + bem = bem.copy() + bem["surfs"] = [] + if len(bem["layers"]) == 4: + for idx, id_ in enumerate(_sm_surf_dict.values()): + bem["surfs"].append(_complete_sphere_surf(bem, idx, 4, complete=False)) + bem["surfs"][-1]["id"] = id_ + + return bem + + +def _check_file(fname, overwrite): + """Prevent overwrites.""" + if op.isfile(fname) and not overwrite: + raise OSError(f"File {fname} exists, use --overwrite to overwrite it") + + +_tri_levels = dict( + medium=30000, + sparse=2500, +) + + +@verbose +def make_scalp_surfaces( + subject, + subjects_dir=None, + force=True, + overwrite=False, + no_decimate=False, + reuse_seghead=False, + *, + threshold=20, + mri="T1.mgz", + verbose=None, +): + """Create surfaces of the scalp and neck. + + The scalp surfaces are required for using the MNE coregistration GUI, and + allow for a visualization of the alignment between anatomy and channel + locations. + + Parameters + ---------- + %(subject)s + %(subjects_dir)s + force : bool + Force creation of the surface even if it has some topological defects. + Defaults to ``True``. See :ref:`tut-fix-meshes` for ideas on how to + fix problematic meshes. + %(overwrite)s + no_decimate : bool + Disable the "medium" and "sparse" decimations. In this case, only + a "dense" surface will be generated. Defaults to ``False``, i.e., + create surfaces for all three types of decimations. + reuse_seghead : bool + Whether to reuse existing head segmentation files. If ``True``, + the existing files will be used if they exist. If ``False`` + (default), the head segmentation will be recomputed. + + .. versionadded:: 1.12 + threshold : int + The threshold to use with the MRI in the call to ``mkheadsurf``. + The default is ``20``. + + .. versionadded:: 1.1 + mri : str + The MRI to use. Should exist in ``$SUBJECTS_DIR/$SUBJECT/mri``. + + .. versionadded:: 1.1 + %(verbose)s + """ + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + incomplete = "warn" if force else "raise" + subj_path = subjects_dir / subject + if not subj_path.exists(): + raise RuntimeError( + f"{subj_path} does not exist. Please check your subject directory path." + ) + + # Backward compat for old FreeSurfer (?) + _validate_type(mri, str, "mri") + if mri == "T1.mgz": + mri = mri if (subj_path / "mri" / mri).exists() else "T1" + + threshold = _ensure_int(threshold, "threshold") + + # Check for existing files + seghead_mgz_path = subj_path / "mri" / "seghead.mgz" + seghead_surf_path = subj_path / "surf" / "lh.seghead" + smseghead_surf_path = subj_path / "surf" / "lh.smseghead" + + bem_dir = subjects_dir / subject / "bem" + fname_template = bem_dir / (f"{subject}-head-{{}}.fif") + dense_fname = str(fname_template).format("dense") + _check_file(dense_fname, overwrite) + + for level in _tri_levels: + dec_fname = str(fname_template).format(level) + if overwrite: + if os.path.exists(dec_fname): + logger.info(f"Removing previously existing {dec_fname}.") + os.remove(dec_fname) + else: + if no_decimate: + if os.path.exists(dec_fname): + raise OSError( + f"Trying to generate new scalp surfaces" + f"but {dec_fname} already exists." + f"To avoid mixing different scalp surface solutions, " + f"delete this file or use overwrite to automatically delete it." + ) + else: + _check_file(dec_fname, overwrite) + + _check_freesurfer_home() + + if reuse_seghead: + if seghead_surf_path.exists(): + surf = seghead_surf_path + elif smseghead_surf_path.exists(): + surf = smseghead_surf_path + else: + raise ValueError( + "No existing scalp surface found. Please check your subject's surf " + "folder or set reuse_seghead to False to recompute the surfaces." + ) + logger.info(f"1. Using existing scalp tessellation {surf} ...") + else: + _check_file(seghead_mgz_path, overwrite) + _check_file(seghead_surf_path, overwrite) + _check_file(smseghead_surf_path, overwrite) + logger.info("1. Creating a dense scalp tessellation with mkheadsurf...") + this_env = deepcopy(os.environ) + this_env["SUBJECTS_DIR"] = str(subjects_dir) + this_env["SUBJECT"] = subject + this_env["subjdir"] = str(subj_path) + run_subprocess( + [ + "mkheadsurf", + "-subjid", + subject, + "-srcvol", + mri, + "-thresh1", + str(threshold), + "-thresh2", + str(threshold), + ], + env=this_env, + ) + if os.path.exists(seghead_surf_path): + surf = seghead_surf_path + elif os.path.exists(smseghead_surf_path): + surf = smseghead_surf_path + else: + raise ValueError("mkheadsurf did not produce the standard output file.") + + logger.info(f"2. Creating {dense_fname} ...") + bem_dir.mkdir(exist_ok=True) + + # Helpful message if we get a topology error + msg = ( + "\n\nConsider using pymeshfix directly to fix the mesh, or --force " + "to ignore the problem." + ) + surf = _surfaces_to_bem( + [surf], [FIFF.FIFFV_BEM_SURF_ID_HEAD], [1], incomplete=incomplete, extra=msg + )[0] + write_bem_surfaces(dense_fname, surf, overwrite=overwrite) + if os.getenv("_MNE_TESTING_SCALP", "false") == "true": + tris = [len(surf["tris"])] # don't actually decimate + for ii, (level, n_tri) in enumerate(_tri_levels.items(), 3): + if no_decimate: + break + logger.info(f"{ii}. Creating {level} tessellation...") + logger.info( + f"{ii}.1 Decimating the dense tessellation " + f"({len(surf['tris'])} -> {n_tri} triangles)..." + ) + points, tris = decimate_surface( + points=surf["rr"], triangles=surf["tris"], n_triangles=n_tri + ) + dec_fname = str(fname_template).format(level) + logger.info(f"{ii}.2 Creating {dec_fname}") + dec_surf = _surfaces_to_bem( + [dict(rr=points, tris=tris)], + [FIFF.FIFFV_BEM_SURF_ID_HEAD], + [1], + rescale=False, + incomplete=incomplete, + extra=msg, + ) + write_bem_surfaces(dec_fname, dec_surf, overwrite=overwrite) + logger.info("[done]") + + +@verbose +def distance_to_bem(pos, bem, trans=None, verbose=None): + """Calculate the distance of positions to inner skull surface. + + Parameters + ---------- + pos : array, shape (..., 3) + Position(s) in m, in head coordinates. + bem : instance of ConductorModel + Conductor model. + %(trans)s If None (default), assumes bem is in head coordinates. + + .. versionchanged:: 0.19 + Support for 'fsaverage' argument. + %(verbose)s + + Returns + ------- + distances : float | array, shape (...) + The computed distance(s). A float is returned if pos is + an array of shape (3,) corresponding to a single position. + + Notes + ----- + .. versionadded:: 1.1 + """ + ndim = pos.ndim + if ndim == 1: + pos = pos[np.newaxis, :] + + n = pos.shape[0] + distance = np.zeros((n,)) + + logger.info( + "Computing distance to inner skull surface for " + f"{n} position{_pl(n)}..." + ) + + if bem["is_sphere"]: + center = bem["r0"] + + if trans: + center = apply_trans(trans, center, move=True) + radius = bem["layers"][0]["rad"] + + distance = np.abs(radius - np.linalg.norm(pos - center, axis=1)) + + else: # is BEM + surface_points = bem["surfs"][0]["rr"] + + if trans: + surface_points = apply_trans(trans, surface_points, move=True) + + _, distance = _compute_nearest(surface_points, pos, return_dists=True) + + if ndim == 1: + distance = distance[0] # return just a float if one pos is passed + + return distance diff --git a/mne-python/source/mne/channels/__init__.py b/mne-python/source/mne/channels/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..901a237da2492fef44663a30708ed86e4df5021d --- /dev/null +++ b/mne-python/source/mne/channels/__init__.py @@ -0,0 +1,12 @@ +"""Module dedicated to manipulation of channels. + +Can be used for setting of sensor locations used for processing and plotting. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/channels/__init__.pyi b/mne-python/source/mne/channels/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..c7aac715b68bdaea5d17940bae17091e8fbf826a --- /dev/null +++ b/mne-python/source/mne/channels/__init__.pyi @@ -0,0 +1,82 @@ +__all__ = [ + "DigMontage", + "Layout", + "_EEG_SELECTIONS", + "_SELECTIONS", + "_divide_to_regions", + "combine_channels", + "compute_dev_head_t", + "compute_native_head_t", + "equalize_channels", + "find_ch_adjacency", + "find_layout", + "fix_mag_coil_types", + "generate_2d_layout", + "get_builtin_ch_adjacencies", + "get_builtin_montages", + "make_1020_channel_selections", + "make_dig_montage", + "make_eeg_layout", + "make_grid_layout", + "make_standard_montage", + "read_ch_adjacency", + "read_custom_montage", + "read_dig_captrak", + "read_dig_curry", + "read_dig_dat", + "read_dig_egi", + "read_dig_fif", + "read_dig_hpts", + "read_dig_localite", + "read_dig_polhemus_isotrak", + "read_layout", + "read_meg_canonical_info", + "read_polhemus_fastscan", + "read_vectorview_selection", + "rename_channels", + "transform_to_head", + "unify_bad_channels", +] +from .channels import ( + _EEG_SELECTIONS, + _SELECTIONS, + _divide_to_regions, + combine_channels, + equalize_channels, + find_ch_adjacency, + fix_mag_coil_types, + get_builtin_ch_adjacencies, + make_1020_channel_selections, + read_ch_adjacency, + read_vectorview_selection, + rename_channels, + unify_bad_channels, +) +from .layout import ( + Layout, + find_layout, + generate_2d_layout, + make_eeg_layout, + make_grid_layout, + read_layout, +) +from .montage import ( + DigMontage, + compute_dev_head_t, + compute_native_head_t, + get_builtin_montages, + make_dig_montage, + make_standard_montage, + read_custom_montage, + read_dig_captrak, + read_dig_curry, + read_dig_dat, + read_dig_egi, + read_dig_fif, + read_dig_hpts, + read_dig_localite, + read_dig_polhemus_isotrak, + read_meg_canonical_info, + read_polhemus_fastscan, + transform_to_head, +) diff --git a/mne-python/source/mne/channels/_dig_montage_utils.py b/mne-python/source/mne/channels/_dig_montage_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..31bee83648d9d9491b07b27825f120d64ebdf706 --- /dev/null +++ b/mne-python/source/mne/channels/_dig_montage_utils.py @@ -0,0 +1,141 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import re + +import numpy as np + +from ..utils import Bunch, _check_fname, _soft_import, warn + + +def _read_dig_montage_egi( + fname, + _scaling, + _all_data_kwargs_are_none, +): + if not _all_data_kwargs_are_none: + raise ValueError( + "hsp, hpi, elp, point_names, fif must all be None if egi is not None" + ) + _check_fname(fname, overwrite="read", must_exist=True) + defusedxml = _soft_import("defusedxml", "reading EGI montages") + root = defusedxml.ElementTree.parse(fname).getroot() + ns = root.tag[root.tag.index("{") : root.tag.index("}") + 1] + sensors = root.find(f"{ns}sensorLayout/{ns}sensors") + fids = dict() + dig_ch_pos = dict() + + fid_name_map = { + "Nasion": "nasion", + "Right periauricular point": "rpa", + "Left periauricular point": "lpa", + } + + for s in sensors: + name, number, kind = s[0].text, int(s[1].text), int(s[2].text) + coordinates = np.array([float(s[3].text), float(s[4].text), float(s[5].text)]) + + coordinates *= _scaling + + # EEG Channels + if kind == 0: + dig_ch_pos[f"EEG {number:03d}"] = coordinates + # Reference + elif kind == 1: + dig_ch_pos[f"EEG {len(dig_ch_pos) + 1:03d}"] = coordinates + # Fiducials + elif kind == 2: + fid_name = fid_name_map[name] + fids[fid_name] = coordinates + # Unknown + else: + warn( + f"Unknown sensor type {kind} detected. Skipping sensor..." + "Proceed with caution!" + ) + + return Bunch( + # EGI stuff + nasion=fids["nasion"], + lpa=fids["lpa"], + rpa=fids["rpa"], + ch_pos=dig_ch_pos, + coord_frame="unknown", + ) + + +def _parse_brainvision_dig_montage(fname, scale): + FID_NAME_MAP = {"Nasion": "nasion", "RPA": "rpa", "LPA": "lpa"} + defusedxml = _soft_import("defusedxml", "reading BrainVision montages") + root = defusedxml.ElementTree.parse(fname).getroot() + sensors = root.find("CapTrakElectrodeList") + + fids, dig_ch_pos = dict(), dict() + + for s in sensors: + name = s.find("Name").text + + is_fid = name in FID_NAME_MAP + coordinates = scale * np.array( + [float(s.find("X").text), float(s.find("Y").text), float(s.find("Z").text)] + ) + + # Fiducials + if is_fid: + fids[FID_NAME_MAP[name]] = coordinates + # EEG Channels + else: + dig_ch_pos[name] = coordinates + + return dict( + # BVCT stuff + nasion=fids["nasion"], + lpa=fids["lpa"], + rpa=fids["rpa"], + ch_pos=dig_ch_pos, + coord_frame="unknown", + ) + + +def _read_dig_montage_curry(ch_names, ch_types, ch_pos, landmarks, landmarkslabels): + # scale ch_pos to m?! + ch_pos /= 1000.0 + landmarks /= 1000.0 + # channel locations + # what about misc without pos? can they mess things up if unordered? + assert len(ch_pos) >= (ch_types.count("mag") + ch_types.count("eeg")) + assert len(ch_pos) == (ch_types.count("mag") + ch_types.count("eeg")) + ch_pos_eeg = { + ch_names[i]: ch_pos[i, :3] for i, t in enumerate(ch_types) if t == "eeg" + } + # landmarks and headshape + landmark_dict = dict(zip(landmarkslabels, landmarks)) + for k in ["Nas", "RPA", "LPA"]: + if k not in landmark_dict.keys(): + landmark_dict[k] = None + if len(landmarkslabels) > 0: + hpi_pos = landmarks[ + [i for i, n in enumerate(landmarkslabels) if re.match("HPI[1-99]", n)], : + ] + else: + hpi_pos = None + if len(landmarkslabels) > 0: + hsp_pos = landmarks[ + [i for i, n in enumerate(landmarkslabels) if re.match("H[1-99]", n)], : + ] + else: + hsp_pos = None + # compile dig montage positions for eeg + if len(ch_pos_eeg) > 0: + return dict( + ch_pos=ch_pos_eeg, + nasion=landmark_dict["Nas"], + lpa=landmark_dict["LPA"], + rpa=landmark_dict["RPA"], + hsp=hsp_pos, + hpi=hpi_pos, + coord_frame="unknown", + ) + else: # not recorded? + raise ValueError("No eeg sensor locations found in header file.") diff --git a/mne-python/source/mne/channels/_standard_montage_utils.py b/mne-python/source/mne/channels/_standard_montage_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..eb3dc10d10e7c889e3c5b9c776620c913d7aec95 --- /dev/null +++ b/mne-python/source/mne/channels/_standard_montage_utils.py @@ -0,0 +1,421 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import csv +import os.path as op +from collections import OrderedDict +from functools import partial + +import numpy as np + +from .._freesurfer import get_mni_fiducials +from ..transforms import _sph_to_cart +from ..utils import _pl, _soft_import, warn +from . import __file__ as _CHANNELS_INIT_FILE +from .montage import make_dig_montage + +MONTAGE_PATH = op.join(op.dirname(_CHANNELS_INIT_FILE), "data", "montages") + +_str = "U100" + + +# In standard_1020, T9=LPA, T10=RPA, Nasion is the same as Iz with a +# sign-flipped Y value + + +def _egi_256(head_size): + fname = op.join(MONTAGE_PATH, "EGI_256.csd") + montage = _read_csd(fname, head_size) + ch_pos = montage._get_ch_pos() + + # For this cap, the Nasion is the frontmost electrode, + # LPA/RPA we approximate by putting 75% of the way (toward the front) + # between the two electrodes that are halfway down the ear holes + nasion = ch_pos["E31"] + lpa = 0.75 * ch_pos["E67"] + 0.25 * ch_pos["E94"] + rpa = 0.75 * ch_pos["E219"] + 0.25 * ch_pos["E190"] + + fids_montage = make_dig_montage( + coord_frame="unknown", + nasion=nasion, + lpa=lpa, + rpa=rpa, + ) + + montage += fids_montage # add fiducials to montage + + return montage + + +def _easycap(basename, head_size): + fname = op.join(MONTAGE_PATH, basename) + montage = _read_theta_phi_in_degrees(fname, head_size, add_fiducials=True) + return montage + + +def _hydrocel(basename, head_size): + fname = op.join(MONTAGE_PATH, basename) + return _read_sfp(fname, head_size) + + +def _str_names(ch_names): + return [str(ch_name) for ch_name in ch_names] + + +def _safe_np_loadtxt(fname, **kwargs): + out = np.genfromtxt(fname, **kwargs) + ch_names = _str_names(out["f0"]) + others = tuple(out[f"f{ii}"] for ii in range(1, len(out.dtype.fields))) + return (ch_names,) + others + + +def _biosemi(basename, head_size): + fname = op.join(MONTAGE_PATH, basename) + fid_names = ("Nz", "LPA", "RPA") + return _read_theta_phi_in_degrees(fname, head_size, fid_names) + + +def _mgh_or_standard(basename, head_size, coord_frame="unknown"): + fid_names = ("Nz", "LPA", "RPA") + fname = op.join(MONTAGE_PATH, basename) + + ch_names_, pos = [], [] + with open(fname) as fid: + # Ignore units as we will scale later using the norms anyway + for line in fid: + if "Positions\n" in line: + break + pos = [] + for line in fid: + if "Labels\n" in line: + break + pos.append(list(map(float, line.split()))) + for line in fid: + if not line or not set(line) - {" "}: + break + ch_names_.append(line.strip(" ").strip("\n")) + + pos = np.array(pos) / 1000.0 + ch_pos = _check_dupes_odict(ch_names_, pos) + nasion, lpa, rpa = (ch_pos.pop(n) for n in fid_names) + if head_size is None: + scale = 1.0 + else: + scale = head_size / np.median(np.linalg.norm(pos, axis=1)) + for value in ch_pos.values(): + value *= scale + # if we are in MRI/MNI coordinates, we need to replace nasion, LPA, and RPA + # with those of fsaverage for ``trans='fsaverage'`` to work + if coord_frame == "mri": + lpa, nasion, rpa = (x["r"].copy() for x in get_mni_fiducials("fsaverage")) + nasion *= scale + lpa *= scale + rpa *= scale + + return make_dig_montage( + ch_pos=ch_pos, coord_frame=coord_frame, nasion=nasion, lpa=lpa, rpa=rpa + ) + + +standard_montage_look_up_table = { + "EGI_256": _egi_256, + "easycap-M1": partial(_easycap, basename="easycap-M1.txt"), + "easycap-M10": partial(_easycap, basename="easycap-M10.txt"), + "easycap-M43": partial(_easycap, basename="easycap-M43.txt"), + "GSN-HydroCel-128": partial(_hydrocel, basename="GSN-HydroCel-128.sfp"), + "GSN-HydroCel-129": partial(_hydrocel, basename="GSN-HydroCel-129.sfp"), + "GSN-HydroCel-256": partial(_hydrocel, basename="GSN-HydroCel-256.sfp"), + "GSN-HydroCel-257": partial(_hydrocel, basename="GSN-HydroCel-257.sfp"), + "GSN-HydroCel-32": partial(_hydrocel, basename="GSN-HydroCel-32.sfp"), + "GSN-HydroCel-64_1.0": partial(_hydrocel, basename="GSN-HydroCel-64_1.0.sfp"), + "GSN-HydroCel-65_1.0": partial(_hydrocel, basename="GSN-HydroCel-65_1.0.sfp"), + "biosemi128": partial(_biosemi, basename="biosemi128.txt"), + "biosemi16": partial(_biosemi, basename="biosemi16.txt"), + "biosemi160": partial(_biosemi, basename="biosemi160.txt"), + "biosemi256": partial(_biosemi, basename="biosemi256.txt"), + "biosemi32": partial(_biosemi, basename="biosemi32.txt"), + "biosemi64": partial(_biosemi, basename="biosemi64.txt"), + "mgh60": partial(_mgh_or_standard, basename="mgh60.elc", coord_frame="mri"), + "mgh70": partial(_mgh_or_standard, basename="mgh70.elc", coord_frame="mri"), + "standard_1005": partial( + _mgh_or_standard, basename="standard_1005.elc", coord_frame="mri" + ), + "standard_1020": partial( + _mgh_or_standard, basename="standard_1020.elc", coord_frame="mri" + ), + "standard_alphabetic": partial( + _mgh_or_standard, basename="standard_alphabetic.elc", coord_frame="mri" + ), + "standard_postfixed": partial( + _mgh_or_standard, basename="standard_postfixed.elc", coord_frame="mri" + ), + "standard_prefixed": partial( + _mgh_or_standard, basename="standard_prefixed.elc", coord_frame="mri" + ), + "standard_primed": partial( + _mgh_or_standard, basename="standard_primed.elc", coord_frame="mri" + ), + "artinis-octamon": partial( + _mgh_or_standard, coord_frame="mri", basename="artinis-octamon.elc" + ), + "artinis-brite23": partial( + _mgh_or_standard, coord_frame="mri", basename="artinis-brite23.elc" + ), + "brainproducts-RNP-BA-128": partial( + _easycap, basename="brainproducts-RNP-BA-128.txt" + ), +} + + +def _read_sfp(fname, head_size): + """Read .sfp BESA/EGI files.""" + # fname has been already checked + fid_names = ("FidNz", "FidT9", "FidT10") + options = dict(dtype=(_str, "f4", "f4", "f4")) + ch_names, xs, ys, zs = _safe_np_loadtxt(fname, **options) + # deal with "headshape" + mask = np.array([ch_name == "headshape" for ch_name in ch_names], bool) + hsp = np.stack([xs[mask], ys[mask], zs[mask]], axis=-1) + mask = ~mask + pos = np.stack([xs[mask], ys[mask], zs[mask]], axis=-1) + ch_names = [ch_name for ch_name, m in zip(ch_names, mask) if m] + ch_pos = _check_dupes_odict(ch_names, pos) + del xs, ys, zs, ch_names + # no one grants that fid names are there. + nasion, lpa, rpa = (ch_pos.pop(n, None) for n in fid_names) + + if head_size is not None: + scale = head_size / np.median(np.linalg.norm(pos, axis=-1)) + for value in ch_pos.values(): + value *= scale + nasion = nasion * scale if nasion is not None else None + lpa = lpa * scale if lpa is not None else None + rpa = rpa * scale if rpa is not None else None + + return make_dig_montage( + ch_pos=ch_pos, coord_frame="unknown", nasion=nasion, rpa=rpa, lpa=lpa, hsp=hsp + ) + + +def _read_csd(fname, head_size): + # Label, Theta, Phi, Radius, X, Y, Z, off sphere surface + options = dict( + comments="//", dtype=(_str, "f4", "f4", "f4", "f4", "f4", "f4", "f4") + ) + ch_names, _, _, _, xs, ys, zs, _ = _safe_np_loadtxt(fname, **options) + pos = np.stack([xs, ys, zs], axis=-1) + + if head_size is not None: + pos *= head_size / np.median(np.linalg.norm(pos, axis=1)) + + return make_dig_montage(ch_pos=_check_dupes_odict(ch_names, pos)) + + +def _check_dupes_odict(ch_names, pos): + """Warn if there are duplicates, then turn to ordered dict.""" + ch_names = list(ch_names) + dups = OrderedDict((ch_name, ch_names.count(ch_name)) for ch_name in ch_names) + dups = OrderedDict((ch_name, count) for ch_name, count in dups.items() if count > 1) + n = len(dups) + if n: + dups = ", ".join(f"{ch_name} ({count})" for ch_name, count in dups.items()) + warn( + f"Duplicate channel position{_pl(n)} found, the last will be " + f"used for {dups}" + ) + return OrderedDict(zip(ch_names, pos)) + + +def _read_elc(fname, head_size): + """Read .elc files. + + The `.elc` files are so-called "asa electrode files". ASA here stands for + Advances Source Analysis, and is a software package developed and sold by + the ANT Neuro company. They provide a device for sensor digitization, called + 'xensor', which produces the `.elc` files. + + Parameters + ---------- + fname : str + File extension is expected to be '.elc'. + head_size : float | None + The size of the head in [m]. If none, returns the values read from the + file with no modification. + + Returns + ------- + montage : instance of DigMontage + The montage units are [m]. + """ + fid_names = ("Nz", "LPA", "RPA") + + with open(fname) as fid: + # Read units + # _read_elc does require to detect the units. (see _mgh_or_standard) + for line in fid: + if "UnitPosition" in line: + units = line.split()[1] + scale = dict(m=1.0, mm=1e-3)[units] + break + else: + raise RuntimeError(f"Could not detect units in file {fname}") + for line in fid: + if "Positions\n" in line: + break + + # Read positions + new_style = False + pos = [] + for line in fid: + if "Labels\n" in line: + break + if ":" in line: + # Of the 'new' format: `E01 : 5.288 -3.658 119.693` + pos.append(list(map(float, line.split(":")[1].split()))) + new_style = True + else: + # Of the 'old' format: `5.288 -3.658 119.693` + pos.append(list(map(float, line.split()))) + + # Read labels + ch_names_ = [] + for line in fid: + if not line or not set(line) - {" "}: + break + if new_style: + # Not sure how this format would deal with spaces in channel labels, + # but none of my test files had this, so let's wait until it comes up. + parsed = line.strip(" ").strip("\n").split() + else: + parsed = [line.strip(" ").strip("\n")] + ch_names_.extend(parsed) + + pos = np.array(pos) * scale + if head_size is not None: + pos *= head_size / np.median(np.linalg.norm(pos, axis=1)) + + ch_pos = _check_dupes_odict(ch_names_, pos) + nasion, lpa, rpa = (ch_pos.pop(n, None) for n in fid_names) + + return make_dig_montage( + ch_pos=ch_pos, coord_frame="unknown", nasion=nasion, lpa=lpa, rpa=rpa + ) + + +def _read_theta_phi_in_degrees(fname, head_size, fid_names=None, add_fiducials=False): + ch_names, theta, phi = _safe_np_loadtxt( + fname, skip_header=1, dtype=(_str, "i4", "i4") + ) + if add_fiducials: + # Add fiducials based on 10/20 spherical coordinate definitions + # http://chgd.umich.edu/wp-content/uploads/2014/06/ + # 10-20_system_positioning.pdf + # extrapolated from other sensor coordinates in the Easycap layouts + # https://www.easycap.de/wp-content/uploads/2018/02/ + # Easycap-Equidistant-Layouts.pdf + assert fid_names is None + fid_names = ["Nasion", "LPA", "RPA"] + ch_names.extend(fid_names) + theta = np.append(theta, [115, -115, 115]) + phi = np.append(phi, [90, 0, 0]) + + radii = np.full(len(phi), head_size) + pos = _sph_to_cart(np.array([radii, np.deg2rad(phi), np.deg2rad(theta)]).T) + ch_pos = _check_dupes_odict(ch_names, pos) + + nasion, lpa, rpa = None, None, None + if fid_names is not None: + nasion, lpa, rpa = (ch_pos.pop(n, None) for n in fid_names) + + return make_dig_montage( + ch_pos=ch_pos, coord_frame="unknown", nasion=nasion, lpa=lpa, rpa=rpa + ) + + +def _read_elp_besa(fname, head_size): + # This .elp is not the same as polhemus elp. see _read_isotrak_elp_points + dtype = np.dtype("S8, S8, f8, f8, f8") + data = np.loadtxt(fname, dtype=dtype) + + ch_names = data["f1"].astype(str).tolist() + az = data["f2"] + horiz = data["f3"] + radius = np.abs(az / 180.0) + az = np.deg2rad(np.array([h if a >= 0.0 else 180 + h for h, a in zip(horiz, az)])) + pol = radius * np.pi + rad = data["f4"] / 100 + pos = _sph_to_cart(np.array([rad, az, pol]).T) + + if head_size is not None: + pos *= head_size / np.median(np.linalg.norm(pos, axis=1)) + + ch_pos = _check_dupes_odict(ch_names, pos) + + fid_names = ("Nz", "LPA", "RPA") + # No one grants that the fid names actually exist. + nasion, lpa, rpa = (ch_pos.pop(n, None) for n in fid_names) + + return make_dig_montage(ch_pos=ch_pos, nasion=nasion, lpa=lpa, rpa=rpa) + + +def _read_brainvision(fname, head_size): + # 'BrainVision Electrodes File' format + # Based on BrainVision Analyzer coordinate system: Defined between + # standard electrode positions: X-axis from T7 to T8, Y-axis from Oz to + # Fpz, Z-axis orthogonal from XY-plane through Cz, fit to a sphere if + # idealized (when radius=1), specified in millimeters + defusedxml = _soft_import("defusedxml", "reading BrainVision montages") + root = defusedxml.ElementTree.parse(fname).getroot() + ch_names = [s.text for s in root.findall("./Electrode/Name")] + theta = [float(s.text) for s in root.findall("./Electrode/Theta")] + pol = np.deg2rad(np.array(theta)) + phi = [float(s.text) for s in root.findall("./Electrode/Phi")] + az = np.deg2rad(np.array(phi)) + rad = [float(s.text) for s in root.findall("./Electrode/Radius")] + rad = np.array(rad) # specified in mm + pos = _sph_to_cart(np.array([rad, az, pol]).T) + + if head_size is not None: + pos *= head_size / np.median(np.linalg.norm(pos, axis=1)) + + return make_dig_montage(ch_pos=_check_dupes_odict(ch_names, pos)) + + +def _read_xyz(fname): + """Import EEG channel locations from CSV, TSV, or XYZ files. + + CSV and TSV files should have columns 4 columns containing + ch_name, x, y, and z. Each row represents one channel. + XYZ files should have 5 columns containing + count, x, y, z, and ch_name. Each row represents one channel + CSV files should be separated by commas, TSV and XYZ files should be + separated by tabs. + + Parameters + ---------- + fname : str + Name of the file to read channel locations from. + + Returns + ------- + montage : instance of DigMontage + The montage. + """ + ch_names = [] + pos = [] + file_format = op.splitext(fname)[1].lower() + with open(fname) as f: + if file_format != ".xyz": + f.readline() # skip header + delimiter = "," if file_format == ".csv" else "\t" + for row in csv.reader(f, delimiter=delimiter): + if file_format == ".xyz": + _, x, y, z, ch_name, *_ = row + ch_name = ch_name.strip() # deals with variable tab size + else: + ch_name, x, y, z, *_ = row + ch_names.append(ch_name) + pos.append((x, y, z)) + d = _check_dupes_odict(ch_names, np.array(pos, dtype=float)) + return make_dig_montage(ch_pos=d) diff --git a/mne-python/source/mne/channels/channels.py b/mne-python/source/mne/channels/channels.py new file mode 100644 index 0000000000000000000000000000000000000000..fbfb759cf926da2fb10fd114b682c951afdeb208 --- /dev/null +++ b/mne-python/source/mne/channels/channels.py @@ -0,0 +1,2343 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + + +from __future__ import annotations # only needed for Python ≤ 3.9 + +import os.path as op +import string +import sys +from collections import OrderedDict +from copy import deepcopy +from dataclasses import dataclass +from functools import partial +from pathlib import Path + +import numpy as np +from scipy.io import loadmat +from scipy.sparse import csr_array, lil_array +from scipy.spatial import Delaunay +from scipy.stats import zscore + +from .._fiff.constants import FIFF +from .._fiff.meas_info import ( # noqa F401 + Info, + MontageMixin, + _merge_info, + _rename_comps, + _unit2human, # TODO: pybv relies on this, should be made public + create_info, +) +from .._fiff.pick import ( + _check_excludes_includes, + _pick_data_channels, + _picks_by_type, + _picks_to_idx, + _second_rules, + channel_indices_by_type, + channel_type, + pick_channels, + pick_info, + pick_types, +) +from .._fiff.proj import setup_proj +from .._fiff.reference import add_reference_channels, set_eeg_reference +from .._fiff.tag import _rename_list +from ..bem import _check_origin +from ..defaults import HEAD_SIZE_DEFAULT, _handle_default +from ..utils import ( + _check_dict_keys, + _check_fname, + _check_option, + _check_preload, + _get_stim_channel, + _on_missing, + _validate_type, + fill_doc, + legacy, + logger, + verbose, + warn, +) + +_ALLOWED_INTERPOLATION_MODES = ("accurate", "fast") + + +def _get_meg_system(info): + """Educated guess for the helmet type based on channels.""" + have_helmet = True + for ch in info["chs"]: + if ch["kind"] == FIFF.FIFFV_MEG_CH: + # Only take first 16 bits, as higher bits store CTF grad comp order + coil_type = ch["coil_type"] & 0xFFFF + nmag = np.sum([c["kind"] == FIFF.FIFFV_MEG_CH for c in info["chs"]]) + if coil_type == FIFF.FIFFV_COIL_NM_122: + system = "122m" + break + elif coil_type // 1000 == 3: # All Vectorview coils are 30xx + system = "306m" + break + elif ( + coil_type == FIFF.FIFFV_COIL_MAGNES_MAG + or coil_type == FIFF.FIFFV_COIL_MAGNES_GRAD + ): + system = "Magnes_3600wh" if nmag > 150 else "Magnes_2500wh" + break + elif coil_type == FIFF.FIFFV_COIL_CTF_GRAD: + system = "CTF_275" + break + elif coil_type == FIFF.FIFFV_COIL_KIT_GRAD: + system = "KIT" + # Our helmet does not match very well, so let's just create it + have_helmet = False + break + elif coil_type == FIFF.FIFFV_COIL_BABY_GRAD: + system = "BabySQUID" + break + elif coil_type == FIFF.FIFFV_COIL_ARTEMIS123_GRAD: + system = "ARTEMIS123" + have_helmet = False + break + elif coil_type == FIFF.FIFFV_COIL_KERNEL_OPM_MAG_GEN1: + system = "Kernel_Flux" + have_helmet = True + break + else: + system = "unknown" + have_helmet = False + return system, have_helmet + + +@verbose +def equalize_channels(instances, copy=True, verbose=None): + """Equalize channel picks and ordering across multiple MNE-Python objects. + + First, all channels that are not common to each object are dropped. Then, + using the first object in the list as a template, the channels of each + object are re-ordered to match the template. The end result is that all + given objects define the same channels, in the same order. + + Parameters + ---------- + instances : list + A list of MNE-Python objects to equalize the channels for. Objects can + be of type Raw, Epochs, Evoked, Spectrum, AverageTFR, Forward, Covariance, + CrossSpectralDensity or Info. + + .. versionchanged:: 1.11 + Added support for :class:`mne.time_frequency.Spectrum` objects. + copy : bool + When dropping and/or re-ordering channels, an object will be copied + when this parameter is set to ``True``. When set to ``False`` (the + default) the dropping and re-ordering of channels happens in-place. + + .. versionadded:: 0.20.0 + %(verbose)s + + Returns + ------- + equalized_instances : list + A list of MNE-Python objects that have the same channels defined in the + same order. + + See Also + -------- + mne.channels.unify_bad_channels + mne.channels.rename_channels + mne.channels.combine_channels + """ + from ..cov import Covariance + from ..epochs import BaseEpochs + from ..evoked import Evoked + from ..forward import Forward + from ..io import BaseRaw + from ..time_frequency import BaseTFR, CrossSpectralDensity + from ..time_frequency.spectrum import BaseSpectrum + + # Instances need to have a `ch_names` attribute and a `pick_channels` + # method that supports `ordered=True`. + allowed_types = ( + BaseRaw, + BaseEpochs, + Evoked, + BaseSpectrum, + BaseTFR, + Forward, + Covariance, + CrossSpectralDensity, + Info, + ) + allowed_types_str = ( + "Raw, Epochs, Evoked, Spectrum, TFR, Forward, Covariance, CrossSpectralDensity " + "or Info" + ) + for inst in instances: + _validate_type( + inst, allowed_types, "Instances to be modified", allowed_types_str + ) + + chan_template = instances[0].ch_names + logger.info("Identifying common channels ...") + channels = [set(inst.ch_names) for inst in instances] + common_channels = set(chan_template).intersection(*channels) + all_channels = set(chan_template).union(*channels) + dropped = list(set(all_channels - common_channels)) + + # Preserve the order of chan_template + order = np.argsort([chan_template.index(ch) for ch in common_channels]) + common_channels = np.array(list(common_channels))[order].tolist() + + # Update all instances to match the common_channels list + reordered = False + equalized_instances = [] + for inst in instances: + # Only perform picking when needed + if inst.ch_names != common_channels: + if isinstance(inst, Info): + sel = pick_channels( + inst.ch_names, common_channels, exclude=[], ordered=True + ) + inst = pick_info(inst, sel, copy=copy, verbose=False) + else: + if copy: + inst = inst.copy() + # TODO change to .pick() once CSD, Cov, and Fwd have `.pick()` methods + inst.pick_channels(common_channels, ordered=True) + if len(inst.ch_names) == len(common_channels): + reordered = True + equalized_instances.append(inst) + + if dropped: + logger.info(f"Dropped the following channels:\n{dropped}") + elif reordered: + logger.info("Channels have been re-ordered.") + + return equalized_instances + + +def unify_bad_channels(insts): + """Unify bad channels across a list of instances. + + All instances must be of the same type and have matching channel names and channel + order. The ``.info["bads"]`` of each instance will be set to the union of + ``.info["bads"]`` across all instances. + + Parameters + ---------- + insts : list + List of instances (:class:`~mne.io.Raw`, :class:`~mne.Epochs`, + :class:`~mne.Evoked`, :class:`~mne.time_frequency.Spectrum`, + :class:`~mne.time_frequency.EpochsSpectrum`) across which to unify bad channels. + + Returns + ------- + insts : list + List of instances with bad channels unified across instances. + + See Also + -------- + mne.channels.equalize_channels + mne.channels.rename_channels + mne.channels.combine_channels + + Notes + ----- + This function modifies the instances in-place. + + .. versionadded:: 1.6 + """ + from ..epochs import Epochs + from ..evoked import Evoked + from ..io import BaseRaw + from ..time_frequency.spectrum import BaseSpectrum + + # ensure input is list-like + _validate_type(insts, (list, tuple), "insts") + # ensure non-empty + if len(insts) == 0: + raise ValueError("insts must not be empty") + # ensure all insts are MNE objects, and all the same type + inst_type = type(insts[0]) + valid_types = (BaseRaw, Epochs, Evoked, BaseSpectrum) + for inst in insts: + _validate_type(inst, valid_types, "each object in insts") + if type(inst) is not inst_type: + raise ValueError("All insts must be the same type") + + # ensure all insts have the same channels and channel order + ch_names = insts[0].ch_names + for inst in insts[1:]: + dif = set(inst.ch_names) ^ set(ch_names) + if len(dif): + raise ValueError( + "Channels do not match across the objects in insts. Consider calling " + "equalize_channels before calling this function." + ) + elif inst.ch_names != ch_names: + raise ValueError( + "Channel names are sorted differently across instances. Please use " + "mne.channels.equalize_channels." + ) + + # collect bads as dict keys so that insertion order is preserved, then cast to list + all_bads = dict() + for inst in insts: + all_bads.update(dict.fromkeys(inst.info["bads"])) + all_bads = list(all_bads) + + # update bads on all instances + for inst in insts: + inst.info["bads"] = all_bads + + return insts + + +class ReferenceMixin(MontageMixin): + """Mixin class for Raw, Evoked, Epochs.""" + + @verbose + def set_eeg_reference( + self, + ref_channels="average", + projection=False, + ch_type="auto", + forward=None, + *, + joint=False, + verbose=None, + ): + """Specify which reference to use for EEG data. + + Use this function to explicitly specify the desired reference for EEG. + This can be either an existing electrode or a new virtual channel. + This function will re-reference the data according to the desired + reference. + + Parameters + ---------- + %(ref_channels_set_eeg_reference)s + %(projection_set_eeg_reference)s + %(ch_type_set_eeg_reference)s + %(forward_set_eeg_reference)s + %(joint_set_eeg_reference)s + %(verbose)s + + Returns + ------- + inst : same type as the input data + Data with EEG channels re-referenced. If ``ref_channels='average'`` + and ``projection=True`` a projection will be added instead of + directly re-referencing the data. + %(set_eeg_reference_see_also_notes)s + """ + return set_eeg_reference( + self, + ref_channels=ref_channels, + copy=False, + projection=projection, + ch_type=ch_type, + forward=forward, + joint=joint, + )[0] + + +class UpdateChannelsMixin: + """Mixin class for Raw, Evoked, Epochs, Spectrum, AverageTFR.""" + + @verbose + @legacy(alt="inst.pick(...)") + def pick_types( + self, + meg=False, + eeg=False, + stim=False, + eog=False, + ecg=False, + emg=False, + ref_meg="auto", + *, + misc=False, + resp=False, + chpi=False, + exci=False, + ias=False, + syst=False, + seeg=False, + dipole=False, + gof=False, + bio=False, + ecog=False, + fnirs=False, + csd=False, + dbs=False, + temperature=False, + gsr=False, + eyetrack=False, + include=(), + exclude="bads", + selection=None, + verbose=None, + ): + """Pick some channels by type and names. + + Parameters + ---------- + %(pick_types_params)s + %(verbose)s + + Returns + ------- + inst : same type as the input data + The modified instance. + + See Also + -------- + pick_channels + + Notes + ----- + .. versionadded:: 0.9.0 + """ + idx = pick_types( + self.info, + meg=meg, + eeg=eeg, + stim=stim, + eog=eog, + ecg=ecg, + emg=emg, + ref_meg=ref_meg, + misc=misc, + resp=resp, + chpi=chpi, + exci=exci, + ias=ias, + syst=syst, + seeg=seeg, + dipole=dipole, + gof=gof, + bio=bio, + ecog=ecog, + fnirs=fnirs, + csd=csd, + dbs=dbs, + temperature=temperature, + gsr=gsr, + eyetrack=eyetrack, + include=include, + exclude=exclude, + selection=selection, + ) + + self._pick_drop_channels(idx) + + # remove dropped channel types from reject and flat + if getattr(self, "reject", None) is not None: + # use list(self.reject) to avoid RuntimeError for changing dictionary size + # during iteration + for ch_type in list(self.reject): + if ch_type not in self: + del self.reject[ch_type] + + if getattr(self, "flat", None) is not None: + for ch_type in list(self.flat): + if ch_type not in self: + del self.flat[ch_type] + + return self + + @verbose + @legacy(alt="inst.pick(...)") + def pick_channels(self, ch_names, ordered=True, *, verbose=None): + """Pick some channels. + + Parameters + ---------- + ch_names : list + The list of channels to select. + %(ordered)s + %(verbose)s + + .. versionadded:: 1.1 + + Returns + ------- + inst : same type as the input data + The modified instance. + + See Also + -------- + drop_channels + pick_types + reorder_channels + + Notes + ----- + If ``ordered`` is ``False``, the channel names given via ``ch_names`` are + assumed to be a set, that is, their order does not matter. In that case, the + original order of the channels in the data is preserved. Apart from using + ``ordered=True``, you may also use ``reorder_channels`` to set channel order, + if necessary. + + .. versionadded:: 0.9.0 + """ + picks = pick_channels(self.info["ch_names"], ch_names, ordered=ordered) + return self._pick_drop_channels(picks) + + @verbose + def pick(self, picks, exclude=(), *, verbose=None): + """Pick a subset of channels. + + Parameters + ---------- + %(picks_all)s + exclude : list | str + Set of channels to exclude, only used when picking based on + types (e.g., exclude="bads" when picks="meg"). + %(verbose)s + + .. versionadded:: 0.24.0 + + Returns + ------- + inst : same type as the input data + The modified instance. + """ + picks = _picks_to_idx(self.info, picks, "all", exclude, allow_empty=False) + self._pick_drop_channels(picks) + + # remove dropped channel types from reject and flat + if getattr(self, "reject", None) is not None: + # use list(self.reject) to avoid RuntimeError for changing dictionary size + # during iteration + for ch_type in list(self.reject): + if ch_type not in self: + del self.reject[ch_type] + + if getattr(self, "flat", None) is not None: + for ch_type in list(self.flat): + if ch_type not in self: + del self.flat[ch_type] + + return self + + def reorder_channels(self, ch_names): + """Reorder channels. + + Parameters + ---------- + ch_names : list + The desired channel order. + + Returns + ------- + inst : same type as the input data + The modified instance. + + See Also + -------- + drop_channels + pick_types + pick_channels + + Notes + ----- + Channel names must be unique. Channels that are not in ``ch_names`` + are dropped. + + .. versionadded:: 0.16.0 + """ + _check_excludes_includes(ch_names) + idx = list() + for ch_name in ch_names: + ii = self.ch_names.index(ch_name) + if ii in idx: + raise ValueError(f"Channel name repeated: {ch_name}") + idx.append(ii) + return self._pick_drop_channels(idx) + + @fill_doc + def drop_channels(self, ch_names, on_missing="raise"): + """Drop channel(s). + + Parameters + ---------- + ch_names : iterable or str + Iterable (e.g. list) of channel name(s) or channel name to remove. + %(on_missing_ch_names)s + + Returns + ------- + inst : same type as the input data + The modified instance. + + See Also + -------- + reorder_channels + pick_channels + pick_types + + Notes + ----- + .. versionadded:: 0.9.0 + """ + if isinstance(ch_names, str): + ch_names = [ch_names] + + try: + all_str = all([isinstance(ch, str) for ch in ch_names]) + except TypeError: + raise ValueError( + f"'ch_names' must be iterable, got type {type(ch_names)} ({ch_names})." + ) + + if not all_str: + raise ValueError( + "Each element in 'ch_names' must be str, got " + f"{[type(ch) for ch in ch_names]}." + ) + + missing = [ch for ch in ch_names if ch not in self.ch_names] + if len(missing) > 0: + msg = "Channel(s) {0} not found, nothing dropped." + _on_missing(on_missing, msg.format(", ".join(missing))) + + bad_idx = [self.ch_names.index(ch) for ch in ch_names if ch in self.ch_names] + idx = np.setdiff1d(np.arange(len(self.ch_names)), bad_idx) + if len(idx) == 0: + raise ValueError("All channels would be dropped.") + return self._pick_drop_channels(idx) + + @verbose + def _pick_drop_channels(self, idx, *, verbose=None): + # avoid circular imports + from ..io import BaseRaw + + msg = "adding, dropping, or reordering channels" + if isinstance(self, BaseRaw): + if self._projector is not None: + _check_preload(self, f"{msg} after calling .apply_proj()") + else: + _check_preload(self, msg) + + if getattr(self, "picks", None) is not None: + self.picks = self.picks[idx] + + if getattr(self, "_read_picks", None) is not None: + self._read_picks = [r[idx] for r in self._read_picks] + + if hasattr(self, "_cals"): + self._cals = self._cals[idx] + + pick_info(self.info, idx, copy=False) + + for key in ("_comp", "_projector"): + mat = getattr(self, key, None) + if mat is not None: + setattr(self, key, mat[idx][:, idx]) + + if hasattr(self, "_dims"): # Spectrum and "new-style" TFRs + axis = self._dims.index("channel") + else: # All others (Evoked, Epochs, Raw) have chs axis=-2 + axis = -2 + if hasattr(self, "_data"): # skip non-preloaded Raw + self._data = self._data.take(idx, axis=axis) + else: + assert isinstance(self, BaseRaw) and not self.preload + + if isinstance(self, BaseRaw): + self.annotations._prune_ch_names(self.info, on_missing="ignore") + self._orig_units = { + k: v for k, v in self._orig_units.items() if k in self.ch_names + } + + self._pick_projs() + return self + + def _pick_projs(self): + """Keep only projectors which apply to at least 1 data channel.""" + drop_idx = [] + for idx, proj in enumerate(self.info["projs"]): + if not set(self.info["ch_names"]) & set(proj["data"]["col_names"]): + drop_idx.append(idx) + + for idx in drop_idx: + logger.info(f"Removing projector {self.info['projs'][idx]}") + + if drop_idx and hasattr(self, "del_proj"): + self.del_proj(drop_idx) + + return self + + def add_channels(self, add_list, force_update_info=False): + """Append new channels from other MNE objects to the instance. + + Parameters + ---------- + add_list : list + A list of MNE objects to append to the current instance. + The channels contained in the other instances are appended to the + channels of the current instance. Therefore, all other instances + must be of the same type as the current object. + See notes on how to add data coming from an array. + force_update_info : bool + If True, force the info for objects to be appended to match the + values of the current instance. This should generally only be + used when adding stim channels for which important metadata won't + be overwritten. + + .. versionadded:: 0.12 + + Returns + ------- + inst : same type as the input data + The modified instance. + + See Also + -------- + drop_channels + + Notes + ----- + If ``self`` is a Raw instance that has been preloaded into a + :obj:`numpy.memmap` instance, the memmap will be resized. + + This function expects an MNE object to be appended (e.g. :class:`~mne.io.Raw`, + :class:`~mne.Epochs`, :class:`~mne.Evoked`). If you simply want to add a + channel based on values of an np.ndarray, you need to create a + :class:`~mne.io.RawArray`. + See `_ + """ + # avoid circular imports + from ..epochs import BaseEpochs + from ..io import BaseRaw + from ..time_frequency import EpochsTFR + + _validate_type(add_list, (list, tuple), "Input") + + # Object-specific checks + for inst in add_list + [self]: + _check_preload(inst, "adding channels") + if isinstance(self, BaseRaw): + con_axis = 0 + comp_class = BaseRaw + elif isinstance(self, BaseEpochs): + con_axis = 1 + comp_class = BaseEpochs + elif isinstance(self, EpochsTFR): + con_axis = 1 + comp_class = EpochsTFR + else: + con_axis = 0 + comp_class = type(self) + for inst in add_list: + _validate_type(inst, comp_class, "All input") + data = [inst._data for inst in [self] + add_list] + + # Make sure that all dimensions other than channel axis are the same + compare_axes = [i for i in range(data[0].ndim) if i != con_axis] + shapes = np.array([dat.shape for dat in data])[:, compare_axes] + for shape in shapes: + if not ((shapes[0] - shape) == 0).all(): + raise ValueError( + "All data dimensions except channels must match, got " + f"{shapes[0]} != {shape}" + ) + del shapes + + # Create final data / info objects + infos = [self.info] + [inst.info for inst in add_list] + new_info = _merge_info(infos, force_update_to_first=force_update_info) + + # Now update the attributes + if ( + isinstance(self._data, np.memmap) + and con_axis == 0 + and sys.platform != "darwin" + ): # resizing not available--no mremap + # Use a resize and fill in other ones + out_shape = (sum(d.shape[0] for d in data),) + data[0].shape[1:] + n_bytes = np.prod(out_shape) * self._data.dtype.itemsize + self._data.flush() + self._data.base.resize(n_bytes) + self._data = np.memmap( + self._data.filename, mode="r+", dtype=self._data.dtype, shape=out_shape + ) + assert self._data.shape == out_shape + assert self._data.nbytes == n_bytes + offset = len(data[0]) + for d in data[1:]: + this_len = len(d) + self._data[offset : offset + this_len] = d + offset += this_len + else: + self._data = np.concatenate(data, axis=con_axis) + self.info = new_info + if isinstance(self, BaseRaw): + self._cals = np.concatenate( + [getattr(inst, "_cals") for inst in [self] + add_list] + ) + # We should never use these since data are preloaded, let's just + # set it to something large and likely to break (2 ** 31 - 1) + extra_idx = [2147483647] * sum(info["nchan"] for info in infos[1:]) + assert all(len(r) == infos[0]["nchan"] for r in self._read_picks) + self._read_picks = [ + np.concatenate([r, extra_idx]) for r in self._read_picks + ] + assert all(len(r) == self.info["nchan"] for r in self._read_picks) + for other in add_list: + self._orig_units.update(other._orig_units) + elif isinstance(self, BaseEpochs): + self.picks = np.arange(self._data.shape[1]) + if hasattr(self, "_projector"): + activate = False if self._do_delayed_proj else self.proj + self._projector, self.info = setup_proj( + self.info, False, activate=activate + ) + + return self + + @fill_doc + def add_reference_channels(self, ref_channels): + """Add reference channels to data that consists of all zeros. + + Adds reference channels to data that were not included during + recording. This is useful when you need to re-reference your data + to different channels. These added channels will consist of all zeros. + + Parameters + ---------- + %(ref_channels)s + + Returns + ------- + inst : same type as the input data + The modified instance. + """ + return add_reference_channels(self, ref_channels, copy=False) + + +class InterpolationMixin: + """Mixin class for Raw, Evoked, Epochs.""" + + @verbose + def interpolate_bads( + self, + reset_bads=True, + mode="accurate", + origin="auto", + method=None, + exclude=(), + on_bad_position="warn", + verbose=None, + ): + """Interpolate bad MEG and EEG channels. + + Operates in place. + + Parameters + ---------- + reset_bads : bool + If True, remove the bads from info. + mode : str + Either ``'accurate'`` or ``'fast'``, determines the quality of the + Legendre polynomial expansion used for interpolation of channels + using the minimum-norm method. + origin : array-like, shape (3,) | str + Origin of the sphere in the head coordinate frame and in meters. + Can be ``'auto'`` (default), which means a head-digitization-based + origin fit. + + .. versionadded:: 0.17 + method : dict | str | None + Method to use for each channel type. + + - ``"meg"`` channels support ``"MNE"`` (default) and ``"nan"`` + - ``"eeg"`` channels support ``"spline"`` (default), ``"MNE"`` and ``"nan"`` + - ``"fnirs"`` channels support ``"nearest"`` (default) and ``"nan"`` + - ``"ecog"`` channels support ``"spline"`` (default) and ``"nan"`` + - ``"seeg"`` channels support ``"spline"`` (default) and ``"nan"`` + + None is an alias for:: + + method=dict(meg="MNE", eeg="spline", fnirs="nearest") + + If a :class:`str` is provided, the method will be applied to all channel + types supported and available in the instance. The method ``"nan"`` will + replace the channel data with ``np.nan``. + + .. warning:: + Be careful when using ``method="nan"``; the default value + ``reset_bads=True`` may not be what you want. + + .. versionadded:: 0.21 + exclude : list | tuple + The channels to exclude from interpolation. If excluded a bad + channel will stay in bads. + on_bad_position : "raise" | "warn" | "ignore" + What to do when one or more sensor positions are invalid (zero or NaN). + If ``"warn"`` or ``"ignore"``, channels with invalid positions will be + filled with :data:`~numpy.nan`. + + .. versionadded:: 1.12 + %(verbose)s + + Returns + ------- + inst : same type as the input data + The modified instance. + + Notes + ----- + The ``"MNE"`` method uses minimum-norm projection to a sphere and back. + + .. versionadded:: 0.9.0 + """ + from .interpolation import ( + _interpolate_bads_ecog, + _interpolate_bads_eeg, + _interpolate_bads_meeg, + _interpolate_bads_nan, + _interpolate_bads_nirs, + _interpolate_bads_seeg, + ) + + _check_preload(self, "interpolation") + _validate_type(method, (dict, str, None), "method") + + # check for channels with invalid position(s) + invalid_chs = [] + for ch in self.info["bads"]: + loc = self.info["chs"][self.ch_names.index(ch)]["loc"][:3] + if np.allclose(loc, 0.0, rtol=0, atol=1e-16) or np.isnan(loc).any(): + invalid_chs.append(ch) + + if invalid_chs: + if on_bad_position == "raise": + msg = ( + f"Channel(s) {invalid_chs} have invalid sensor position(s). " + "Interpolation cannot proceed correctly. If you want to " + "continue despite missing positions, set " + "on_bad_position='warn' or 'ignore', which outputs all " + "NaN values (np.nan) for the interpolated channel(s)." + ) + else: + msg = ( + f"Channel(s) {invalid_chs} have invalid sensor position(s) " + "and cannot be interpolated. The values of these channels " + "will be all NaN. To ignore this warning, pass " + "on_bad_position='ignore'." + ) + _on_missing(on_bad_position, msg) + + method = _handle_default("interpolation_method", method) + ch_types = self.get_channel_types(unique=True) + # figure out if we have "mag" for "meg", "hbo" for "fnirs", ... to filter the + # "method" dictionary and keep only keys that correspond to existing channels. + for ch_type in ("meg", "fnirs"): + for sub_ch_type in _second_rules[ch_type][1].values(): + if sub_ch_type in ch_types: + ch_types.remove(sub_ch_type) + if ch_type not in ch_types: + ch_types.append(ch_type) + keys2delete = set(method) - set(ch_types) + for key in keys2delete: + del method[key] + valids = { + "eeg": ("spline", "MNE", "nan"), + "meg": ("MNE", "nan"), + "fnirs": ("nearest", "nan"), + "ecog": ("spline", "nan"), + "seeg": ("spline", "nan"), + } + for key in method: + _check_option("method[key]", key, tuple(valids)) + _check_option(f"method['{key}']", method[key], valids[key]) + logger.info("Setting channel interpolation method to %s.", method) + idx = _picks_to_idx(self.info, list(method), exclude=(), allow_empty=True) + if idx.size == 0 or len(pick_info(self.info, idx)["bads"]) == 0: + warn("No bad channels to interpolate. Doing nothing...") + return self + for ch_type in method.copy(): + idx = _picks_to_idx(self.info, ch_type, exclude=(), allow_empty=True) + if len(pick_info(self.info, idx)["bads"]) == 0: + method.pop(ch_type) + logger.info("Interpolating bad channels.") + needs_origin = [key != "seeg" and val != "nan" for key, val in method.items()] + if any(needs_origin): + origin = _check_origin(origin, self.info) + for ch_type, interp in method.items(): + if interp == "nan": + _interpolate_bads_nan(self, ch_type=ch_type, exclude=exclude) + if method.get("eeg", "") == "spline": + _interpolate_bads_eeg(self, origin=origin, exclude=exclude) + meg_mne = method.get("meg", "") == "MNE" + eeg_mne = method.get("eeg", "") == "MNE" + if meg_mne or eeg_mne: + _interpolate_bads_meeg( + self, + mode=mode, + meg=meg_mne, + eeg=eeg_mne, + origin=origin, + exclude=exclude, + method=method, + ) + if method.get("fnirs", "") == "nearest": + _interpolate_bads_nirs(self, exclude=exclude) + if method.get("ecog", "") == "spline": + _interpolate_bads_ecog(self, origin=origin, exclude=exclude) + if method.get("seeg", "") == "spline": + _interpolate_bads_seeg(self, exclude=exclude) + + if reset_bads is True: + if "nan" in method.values(): + warn( + "interpolate_bads was called with method='nan' and " + "reset_bads=True. Consider setting reset_bads=False so that the " + "nan-containing channels can be easily excluded from later " + "computations." + ) + self.info["bads"] = [ch for ch in self.info["bads"] if ch in exclude] + + return self + + def interpolate_to( + self, sensors, origin="auto", method=None, mode="accurate", reg=0.0 + ): + """Interpolate data onto a new sensor configuration. + + This method can interpolate EEG data onto a new montage or transform + MEG data to a different sensor configuration (e.g., Neuromag to CTF). + + Parameters + ---------- + sensors : DigMontage | str + For EEG: A DigMontage object containing target channel positions. + For MEG: A string specifying the target MEG system. Currently + supported: ``'neuromag'``, ``'ctf151'`` or ``'ctf275'``. + origin : array-like, shape (3,) | str + Origin of the sphere in the head coordinate frame and in meters. + Can be ``'auto'`` (default), which means a head-digitization-based + origin fit. Used for both EEG and MEG interpolation. + method : str | None + Interpolation method to use. + For EEG: ``'spline'`` (default, same as None) or ``'MNE'``. + For MEG: ``'MNE'`` (default, same as None). + + .. versionchanged:: 1.10.0 + Added support for MEG interpolation. + mode : str + Either ``'accurate'`` (default) or ``'fast'``, determines the + quality of the Legendre polynomial expansion used for + interpolation of MEG channels using the minimum-norm method. + Only used for MEG interpolation. + reg : float + The regularization parameter for the interpolation method. + Only used when ``method='spline'`` for EEG channels. + + Returns + ------- + inst : same type as the input data + A new instance with interpolated data and updated channel + information. + + Notes + ----- + **For EEG data:** + + This method interpolates EEG channels onto a new montage using + spherical splines or minimum-norm estimation. Non-EEG channels + are preserved without modification. + + **For MEG data:** + + This method transforms MEG data to a different sensor configuration + using field interpolation. + + Common use cases for MEG transformation: + + - Transform Neuromag data to CTF sensor layout for comparison + - Transform CTF data to Neuromag sensor layout + - Simulate what data would look like on a different MEG system + + .. warning:: + MEG field interpolation assumes that the head position relative + to the sensors is similar between systems. Large differences in + head position may affect interpolation accuracy. + + .. versionadded:: 1.10.0 + .. versionchanged:: 1.12.0 + Added support for MEG interpolation to canonical systems. + """ + from .interpolation import _interpolate_to_eeg, _interpolate_to_meg + from .montage import DigMontage + + _check_preload(self, "interpolation") + + # Determine if we're doing EEG or MEG interpolation + _validate_type(sensors, (str, DigMontage), "sensors") + _validate_type(method, (str, None), "method") + is_meg_interpolation = isinstance(sensors, str) + is_eeg_interpolation = isinstance(sensors, DigMontage) + + if is_eeg_interpolation: + valid_methods = ["spline", "MNE"] + func = partial(_interpolate_to_eeg, method=method, reg=reg) + kind = "eeg" + else: + assert is_meg_interpolation + valid_methods = ["MNE"] + _check_option("sensors", sensors, ["neuromag", "ctf151", "ctf275"]) + func = partial(_interpolate_to_meg, mode=mode) + kind = "meg" + + if method is None: + method = _handle_default("interpolation_method")[kind] + _check_option("mode", mode, _ALLOWED_INTERPOLATION_MODES) + extra = f"when doing {kind.upper()} interpolation" + _check_option("method", method, valid_methods, extra=extra) + return func(self, sensors, origin) + + +@verbose +def rename_channels( + info, mapping, allow_duplicates=False, *, on_missing="raise", verbose=None +): + """Rename channels. + + Parameters + ---------- + %(info_not_none)s Note: modified in place. + %(mapping_rename_channels_duplicates)s + %(on_missing_ch_names)s + + .. versionadded:: 1.11.0 + %(verbose)s + + See Also + -------- + mne.channels.equalize_channels + mne.channels.unify_bad_channels + mne.channels.combine_channels + """ + _validate_type(info, Info, "info") + info._check_consistency() + bads = list(info["bads"]) # make our own local copies + ch_names = list(info["ch_names"]) + + # first check and assemble clean mappings of index and name + if isinstance(mapping, dict): + if on_missing in ["warn", "ignore"]: + new_mapping = { + ch_old: ch_new + for ch_old, ch_new in mapping.items() + if ch_old in ch_names + } + else: + new_mapping = mapping + + if new_mapping != mapping and on_missing == "warn": + warn( + "Channel rename map contains keys that are not present in the object " + "to be renamed. These will be ignored." + ) + + _check_dict_keys( + new_mapping, + ch_names, + key_description="channel name(s)", + valid_key_source="info", + ) + new_names = [ + (ch_names.index(ch_name), new_name) + for ch_name, new_name in new_mapping.items() + ] + elif callable(mapping): + new_names = [(ci, mapping(ch_name)) for ci, ch_name in enumerate(ch_names)] + else: + raise ValueError(f"mapping must be callable or dict, not {type(mapping)}") + + # check we got all strings out of the mapping + for new_name in new_names: + _validate_type(new_name[1], "str", "New channel mappings") + + # do the remapping locally + for c_ind, new_name in new_names: + for bi, bad in enumerate(bads): + if bad == ch_names[c_ind]: + bads[bi] = new_name + ch_names[c_ind] = new_name + + # check that all the channel names are unique + if len(ch_names) != len(np.unique(ch_names)) and not allow_duplicates: + raise ValueError("New channel names are not unique, renaming failed") + + # do the remapping in info + info["bads"] = [] + ch_names_mapping = dict() + for ch, ch_name in zip(info["chs"], ch_names): + ch_names_mapping[ch["ch_name"]] = ch_name + ch["ch_name"] = ch_name + # .get b/c fwd info omits it + _rename_comps(info.get("comps", []), ch_names_mapping) + if "projs" in info: # fwd might omit it + for proj in info["projs"]: + proj["data"]["col_names"][:] = _rename_list( + proj["data"]["col_names"], ch_names_mapping + ) + info._update_redundant() + info["bads"] = bads + info._check_consistency() + + +def _recursive_flatten(cell, dtype): + """Unpack mat files in Python.""" + if len(cell) > 0: + while not isinstance(cell[0], dtype): + cell = [c for d in cell for c in d] + return cell + + +@dataclass +class _BuiltinChannelAdjacency: + name: str + description: str + fname: str + source_url: str | None + + +_ft_neighbor_url_t = string.Template( + "https://github.com/fieldtrip/fieldtrip/raw/master/template/neighbours/$fname" +) + +_BUILTIN_CHANNEL_ADJACENCIES = [ + _BuiltinChannelAdjacency( + name="biosemi16", + description="Biosemi 16-electrode cap", + fname="biosemi16_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="biosemi16_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="biosemi32", + description="Biosemi 32-electrode cap", + fname="biosemi32_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="biosemi32_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="biosemi64", + description="Biosemi 64-electrode cap", + fname="biosemi64_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="biosemi64_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="bti148", + description="BTI 148-channel system", + fname="bti148_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="bti148_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="bti248", + description="BTI 248-channel system", + fname="bti248_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="bti248_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="bti248grad", + description="BTI 248 gradiometer system", + fname="bti248grad_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="bti248grad_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="ctf64", + description="CTF 64 axial gradiometer", + fname="ctf64_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="ctf64_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="ctf151", + description="CTF 151 axial gradiometer", + fname="ctf151_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="ctf151_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="ctf275", + description="CTF 275 axial gradiometer", + fname="ctf275_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="ctf275_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="easycap32ch-avg", + description="", + fname="easycap32ch-avg_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="easycap32ch-avg_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="easycap64ch-avg", + description="", + fname="easycap64ch-avg_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="easycap64ch-avg_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="easycap128ch-avg", + description="", + fname="easycap128ch-avg_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="easycap128ch-avg_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="easycapM1", + description="Easycap M1", + fname="easycapM1_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="easycapM1_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="easycapM11", + description="Easycap M11", + fname="easycapM11_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="easycapM11_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="easycapM14", + description="Easycap M14", + fname="easycapM14_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="easycapM14_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="easycapM15", + description="Easycap M15", + fname="easycapM15_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="easycapM15_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="KIT-157", + description="", + fname="KIT-157_neighb.mat", + source_url=None, + ), + _BuiltinChannelAdjacency( + name="KIT-208", + description="", + fname="KIT-208_neighb.mat", + source_url=None, + ), + _BuiltinChannelAdjacency( + name="KIT-NYU-2019", + description="", + fname="KIT-NYU-2019_neighb.mat", + source_url=None, + ), + _BuiltinChannelAdjacency( + name="KIT-UMD-1", + description="", + fname="KIT-UMD-1_neighb.mat", + source_url=None, + ), + _BuiltinChannelAdjacency( + name="KIT-UMD-2", + description="", + fname="KIT-UMD-2_neighb.mat", + source_url=None, + ), + _BuiltinChannelAdjacency( + name="KIT-UMD-3", + description="", + fname="KIT-UMD-3_neighb.mat", + source_url=None, + ), + _BuiltinChannelAdjacency( + name="KIT-UMD-4", + description="", + fname="KIT-UMD-4_neighb.mat", + source_url=None, + ), + _BuiltinChannelAdjacency( + name="neuromag306mag", + description="Neuromag306, only magnetometers", + fname="neuromag306mag_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="neuromag306mag_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="neuromag306planar", + description="Neuromag306, only planar gradiometers", + fname="neuromag306planar_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="neuromag306planar_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="neuromag122cmb", + description="Neuromag122, only combined planar gradiometers", + fname="neuromag122cmb_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="neuromag122cmb_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="neuromag306cmb", + description="Neuromag306, only combined planar gradiometers", + fname="neuromag306cmb_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="neuromag306cmb_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="ecog256", + description="ECOG 256channels, average referenced", + fname="ecog256_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="ecog256_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="ecog256bipolar", + description="ECOG 256channels, bipolar referenced", + fname="ecog256bipolar_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="ecog256bipolar_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="eeg1010_neighb", + description="", + fname="eeg1010_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="eeg1010_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="elec1005", + description="Standard 10-05 system", + fname="elec1005_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="elec1005_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="elec1010", + description="Standard 10-10 system", + fname="elec1010_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="elec1010_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="elec1020", + description="Standard 10-20 system", + fname="elec1020_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="elec1020_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="itab28", + description="ITAB 28-channel system", + fname="itab28_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="itab28_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="itab153", + description="ITAB 153-channel system", + fname="itab153_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="itab153_neighb.mat"), + ), + _BuiltinChannelAdjacency( + name="language29ch-avg", + description="MPI for Psycholinguistic: Averaged 29-channel cap", + fname="language29ch-avg_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="language29ch-avg_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="mpi_59_channels", + description="MPI for Psycholinguistic: 59-channel cap", + fname="mpi_59_channels_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="mpi_59_channels_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="yokogawa160", + description="", + fname="yokogawa160_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="yokogawa160_neighb.mat"), # noqa: E501 + ), + _BuiltinChannelAdjacency( + name="yokogawa440", + description="", + fname="yokogawa440_neighb.mat", + source_url=_ft_neighbor_url_t.substitute(fname="yokogawa440_neighb.mat"), # noqa: E501 + ), +] + + +@fill_doc +def get_builtin_ch_adjacencies(*, descriptions=False): + """Get a list of all FieldTrip neighbor definitions shipping with MNE. + + The names of these neighbor definitions can be passed to + :func:`read_ch_adjacency`. + + Parameters + ---------- + descriptions : bool + Whether to return not only the neighbor definition names, but also + their corresponding descriptions. If ``True``, a list of tuples is + returned, where the first tuple element is the neighbor definition name + and the second is the description. If ``False`` (default), only the + names are returned. + + Returns + ------- + neighbor_name : list of str | list of tuple + If ``descriptions=False``, the names of all builtin FieldTrip neighbor + definitions that can be loaded directly via :func:`read_ch_adjacency`. + + If ``descriptions=True``, a list of tuples ``(name, description)``. + + Notes + ----- + .. versionadded:: 1.1 + """ + if descriptions: + return sorted( + [(m.name, m.description) for m in _BUILTIN_CHANNEL_ADJACENCIES], + key=lambda x: x[0].casefold(), # only sort based on name + ) + else: + return sorted([m.name for m in _BUILTIN_CHANNEL_ADJACENCIES], key=str.casefold) + + +@fill_doc +def read_ch_adjacency(fname, picks=None): + """Read a channel adjacency ("neighbors") file that ships with MNE. + + More information on these neighbor definitions can be found on the related + `FieldTrip documentation pages + `__. + + Parameters + ---------- + fname : path-like | str + The path to the file to load, or the name of a channel adjacency + matrix that ships with MNE-Python. + + .. note:: + You can retrieve the names of all + built-in channel adjacencies via + :func:`mne.channels.get_builtin_ch_adjacencies`. + %(picks_all_notypes)s + + Returns + ------- + ch_adjacency : scipy.sparse.csr_array, shape (n_channels, n_channels) + The adjacency matrix. + ch_names : list + The list of channel names present in adjacency matrix. + + See Also + -------- + get_builtin_ch_adjacencies + mne.viz.plot_ch_adjacency + find_ch_adjacency + mne.stats.combine_adjacency + + Notes + ----- + If the neighbor definition you need is not shipped by MNE-Python, + you may use :func:`find_ch_adjacency` to compute the + adjacency matrix based on your 2D sensor locations. + + Note that depending on your use case, you may need to additionally use + :func:`mne.stats.combine_adjacency` to prepare a final "adjacency" + to pass to the eventual function. + """ + if op.isabs(fname): + fname = str( + _check_fname( + fname=fname, + overwrite="read", + must_exist=True, + ) + ) + else: # built-in FieldTrip neighbors + ch_adj_name = fname + del fname + if ch_adj_name.endswith("_neighb.mat"): # backward-compat + ch_adj_name = ch_adj_name.replace("_neighb.mat", "") + + if ch_adj_name not in get_builtin_ch_adjacencies(): + raise ValueError( + f"No built-in channel adjacency matrix found with name: " + f"{ch_adj_name}. Valid names are: " + f"{', '.join(get_builtin_ch_adjacencies())}" + ) + + ch_adj = [a for a in _BUILTIN_CHANNEL_ADJACENCIES if a.name == ch_adj_name][0] + fname = ch_adj.fname + templates_dir = Path(__file__).resolve().parent / "data" / "neighbors" + fname = str( + _check_fname( # only needed to convert to a string + fname=templates_dir / fname, + overwrite="read", + must_exist=True, + ) + ) + + nb = loadmat(fname)["neighbours"] + ch_names = _recursive_flatten(nb["label"], str) + temp_info = create_info(ch_names, 1.0) + picks = _picks_to_idx(temp_info, picks, none="all") + neighbors = [_recursive_flatten(c, str) for c in nb["neighblabel"].flatten()] + assert len(ch_names) == len(neighbors) + adjacency = _ch_neighbor_adjacency(ch_names, neighbors) + # picking before constructing matrix is buggy + adjacency = adjacency[picks][:, picks] + ch_names = [ch_names[p] for p in picks] + + return adjacency, ch_names + + +def _ch_neighbor_adjacency(ch_names, neighbors): + """Compute sensor adjacency matrix. + + Parameters + ---------- + ch_names : list of str + The channel names. + neighbors : list of list + A list of list of channel names. The neighbors to + which the channels in ch_names are connected with. + Must be of the same length as ch_names. + + Returns + ------- + ch_adjacency : scipy.sparse.spmatrix + The adjacency matrix. + """ + if len(ch_names) != len(neighbors): + raise ValueError("`ch_names` and `neighbors` must have the same length") + set_neighbors = {c for d in neighbors for c in d} + rest = set_neighbors - set(ch_names) + if len(rest) > 0: + raise ValueError( + "Some of your neighbors are not present in the list of channel names" + ) + + for neigh in neighbors: + if not isinstance(neigh, list) and not all(isinstance(c, str) for c in neigh): + raise ValueError("`neighbors` must be a list of lists of str") + + ch_adjacency = np.eye(len(ch_names), dtype=bool) + for ii, neigbs in enumerate(neighbors): + ch_adjacency[ii, [ch_names.index(i) for i in neigbs]] = True + ch_adjacency = csr_array(ch_adjacency) + return ch_adjacency + + +@fill_doc +def find_ch_adjacency(info, ch_type): + """Find the adjacency matrix for the given channels. + + This function tries to infer the appropriate adjacency matrix template + for the given channels. If a template is not found, the adjacency matrix + is computed using Delaunay triangulation based on 2D sensor locations. + + Parameters + ---------- + %(info_not_none)s + ch_type : str | None + The channel type for computing the adjacency matrix. Currently + supports ``'mag'``, ``'grad'``, ``'eeg'`` and ``None``. + If ``None``, the info must contain only one channel type. + + Returns + ------- + ch_adjacency : scipy.sparse.csr_array, shape (n_channels, n_channels) + The adjacency matrix. + ch_names : list + The list of channel names present in adjacency matrix. + + See Also + -------- + mne.viz.plot_ch_adjacency + mne.stats.combine_adjacency + get_builtin_ch_adjacencies + read_ch_adjacency + + Notes + ----- + .. versionadded:: 0.15 + + Automatic detection of an appropriate adjacency matrix template only + works for MEG data at the moment. This means that the adjacency matrix + is always computed for EEG data and never loaded from a template file. If + you want to load a template for a given montage use + :func:`read_ch_adjacency` directly. + + .. warning:: + If Delaunay triangulation is used to calculate the adjacency matrix it + may yield partially unexpected results (e.g., include unwanted edges + between non-adjacent sensors). Therefore, it is recommended to check + (and, if necessary, manually modify) the result by inspecting it + via :func:`mne.viz.plot_ch_adjacency`. + + Note that depending on your use case, you may need to additionally use + :func:`mne.stats.combine_adjacency` to prepare a final "adjacency" + to pass to the eventual function. + """ + from ..io.kit.constants import KIT_NEIGHBORS + + if ch_type is None: + picks = channel_indices_by_type(info) + if sum([len(p) != 0 for p in picks.values()]) != 1: + raise ValueError( + "info must contain only one channel type if ch_type is None." + ) + ch_type = channel_type(info, 0) + else: + _check_option("ch_type", ch_type, ["mag", "grad", "eeg"]) + ( + has_vv_mag, + has_vv_grad, + is_old_vv, + has_4D_mag, + ctf_other_types, + has_CTF_grad, + n_kit_grads, + has_any_meg, + has_eeg_coils, + has_eeg_coils_and_meg, + has_eeg_coils_only, + has_neuromag_122_grad, + has_csd_coils, + ) = _get_ch_info(info) + conn_name = None + if has_vv_mag and ch_type == "mag": + conn_name = "neuromag306mag" + elif has_vv_grad and ch_type == "grad": + conn_name = "neuromag306planar" + elif has_4D_mag: + if "MEG 248" in info["ch_names"]: + idx = info["ch_names"].index("MEG 248") + grad = info["chs"][idx]["coil_type"] == FIFF.FIFFV_COIL_MAGNES_GRAD + mag = info["chs"][idx]["coil_type"] == FIFF.FIFFV_COIL_MAGNES_MAG + if ch_type == "grad" and grad: + conn_name = "bti248grad" + elif ch_type == "mag" and mag: + conn_name = "bti248" + elif "MEG 148" in info["ch_names"] and ch_type == "mag": + idx = info["ch_names"].index("MEG 148") + if info["chs"][idx]["coil_type"] == FIFF.FIFFV_COIL_MAGNES_MAG: + conn_name = "bti148" + elif has_CTF_grad and ch_type == "mag": + if info["nchan"] < 100: + conn_name = "ctf64" + elif info["nchan"] > 200: + conn_name = "ctf275" + else: + conn_name = "ctf151" + elif n_kit_grads > 0: + conn_name = KIT_NEIGHBORS.get(info["kit_system_id"]) + + if conn_name is not None: + logger.info(f"Reading adjacency matrix for {conn_name}.") + adjacency, ch_names = read_ch_adjacency(conn_name) + if conn_name.startswith("neuromag") and info["ch_names"][0].startswith("MEG "): + ch_names = [ch_name.replace("MEG", "MEG ") for ch_name in ch_names] + return adjacency, ch_names + logger.info( + "Could not find a adjacency matrix for the data. " + "Computing adjacency based on Delaunay triangulations." + ) + return _compute_ch_adjacency(info, ch_type) + + +@fill_doc +def _compute_ch_adjacency(info, ch_type): + """Compute channel adjacency matrix using Delaunay triangulations. + + Parameters + ---------- + %(info_not_none)s + ch_type : str + The channel type for computing the adjacency matrix. Currently + supports ``'mag'``, ``'grad'`` and ``'eeg'``. + + Returns + ------- + ch_adjacency : scipy.sparse.csr_array, shape (n_channels, n_channels) + The adjacency matrix. + ch_names : list + The list of channel names present in adjacency matrix. + """ + from ..channels.layout import _find_topomap_coords, _pair_grad_sensors + from ..source_estimate import spatial_tris_adjacency + + combine_grads = ch_type == "grad" and any( + [ + coil_type in [ch["coil_type"] for ch in info["chs"]] + for coil_type in [FIFF.FIFFV_COIL_VV_PLANAR_T1, FIFF.FIFFV_COIL_NM_122] + ] + ) + + picks = dict(_picks_by_type(info, exclude=[]))[ch_type] + ch_names = [info["ch_names"][pick] for pick in picks] + if combine_grads: + pairs = _pair_grad_sensors(info, topomap_coords=False, exclude=[]) + if len(pairs) != len(picks): + raise RuntimeError( + "Cannot find a pair for some of the " + "gradiometers. Cannot compute adjacency " + "matrix." + ) + # only for one of the pair + xy = _find_topomap_coords(info, picks[::2], sphere=HEAD_SIZE_DEFAULT) + else: + xy = _find_topomap_coords(info, picks, sphere=HEAD_SIZE_DEFAULT) + tri = Delaunay(xy) + neighbors = spatial_tris_adjacency(tri.simplices) + + if combine_grads: + ch_adjacency = np.eye(len(picks), dtype=bool) + for idx, neigbs in zip(neighbors.row, neighbors.col): + for ii in range(2): # make sure each pair is included + for jj in range(2): + ch_adjacency[idx * 2 + ii, neigbs * 2 + jj] = True + ch_adjacency[idx * 2 + ii, idx * 2 + jj] = True # pair + ch_adjacency = csr_array(ch_adjacency) + else: + ch_adjacency = lil_array(neighbors) + ch_adjacency.setdiag(np.repeat(1, ch_adjacency.shape[0])) + ch_adjacency = ch_adjacency.tocsr() + + return ch_adjacency, ch_names + + +@fill_doc +def fix_mag_coil_types(info, use_cal=False): + """Fix magnetometer coil types. + + Parameters + ---------- + %(info_not_none)s Corrections are done in-place. + use_cal : bool + If True, further refine the check for old coil types by checking + ``info['chs'][ii]['cal']``. + + Notes + ----- + This function changes magnetometer coil types 3022 (T1: SQ20483N) and + 3023 (T2: SQ20483-A) to 3024 (T3: SQ20950N) in the channel definition + records in the info structure. + + Neuromag Vectorview systems can contain magnetometers with two + different coil sizes (3022 and 3023 vs. 3024). The systems + incorporating coils of type 3024 were introduced last and are used at + the majority of MEG sites. At some sites with 3024 magnetometers, + the data files have still defined the magnetometers to be of type + 3022 to ensure compatibility with older versions of Neuromag software. + In the MNE software as well as in the present version of Neuromag + software coil type 3024 is fully supported. Therefore, it is now safe + to upgrade the data files to use the true coil type. + + .. note:: The effect of the difference between the coil sizes on the + current estimates computed by the MNE software is very small. + Therefore the use of ``fix_mag_coil_types`` is not mandatory. + """ + old_mag_inds = _get_T1T2_mag_inds(info, use_cal) + n_mag = len(pick_types(info, meg="mag", exclude=[])) + for ii in old_mag_inds: + info["chs"][ii]["coil_type"] = FIFF.FIFFV_COIL_VV_MAG_T3 + logger.info(f"{len(old_mag_inds)} of {n_mag} magnetometer types replaced with T3.") + info._check_consistency() + + +def _get_T1T2_mag_inds(info, use_cal=False): + """Find T1/T2 magnetometer coil types.""" + picks = pick_types(info, meg="mag", exclude=[]) + old_mag_inds = [] + # From email exchanges, systems with the larger T2 coil only use the cal + # value of 2.09e-11. Newer T3 magnetometers use 4.13e-11 or 1.33e-10 + # (Triux). So we can use a simple check for > 3e-11. + for ii in picks: + ch = info["chs"][ii] + if ch["coil_type"] in (FIFF.FIFFV_COIL_VV_MAG_T1, FIFF.FIFFV_COIL_VV_MAG_T2): + if use_cal: + if ch["cal"] > 3e-11: + old_mag_inds.append(ii) + else: + old_mag_inds.append(ii) + return old_mag_inds + + +def _get_ch_info(info): + """Get channel info for inferring acquisition device.""" + chs = info["chs"] + # Only take first 16 bits, as higher bits store CTF comp order + coil_types = {ch["coil_type"] & 0xFFFF for ch in chs} + channel_types = {ch["kind"] for ch in chs} + + has_vv_mag = any( + k in coil_types + for k in [ + FIFF.FIFFV_COIL_VV_MAG_T1, + FIFF.FIFFV_COIL_VV_MAG_T2, + FIFF.FIFFV_COIL_VV_MAG_T3, + ] + ) + has_vv_grad = any( + k in coil_types + for k in [ + FIFF.FIFFV_COIL_VV_PLANAR_T1, + FIFF.FIFFV_COIL_VV_PLANAR_T2, + FIFF.FIFFV_COIL_VV_PLANAR_T3, + ] + ) + has_neuromag_122_grad = any(k in coil_types for k in [FIFF.FIFFV_COIL_NM_122]) + + is_old_vv = " " in chs[0]["ch_name"] + + has_4D_mag = FIFF.FIFFV_COIL_MAGNES_MAG in coil_types + ctf_other_types = ( + FIFF.FIFFV_COIL_CTF_REF_MAG, + FIFF.FIFFV_COIL_CTF_REF_GRAD, + FIFF.FIFFV_COIL_CTF_OFFDIAG_REF_GRAD, + ) + has_CTF_grad = FIFF.FIFFV_COIL_CTF_GRAD in coil_types or ( + FIFF.FIFFV_MEG_CH in channel_types + and any(k in ctf_other_types for k in coil_types) + ) + # hack due to MNE-C bug in IO of CTF + # only take first 16 bits, as higher bits store CTF comp order + n_kit_grads = sum( + ch["coil_type"] & 0xFFFF == FIFF.FIFFV_COIL_KIT_GRAD for ch in chs + ) + + has_any_meg = any([has_vv_mag, has_vv_grad, has_4D_mag, has_CTF_grad, n_kit_grads]) + has_eeg_coils = ( + FIFF.FIFFV_COIL_EEG in coil_types and FIFF.FIFFV_EEG_CH in channel_types + ) + has_eeg_coils_and_meg = has_eeg_coils and has_any_meg + has_eeg_coils_only = has_eeg_coils and not has_any_meg + has_csd_coils = ( + FIFF.FIFFV_COIL_EEG_CSD in coil_types and FIFF.FIFFV_EEG_CH in channel_types + ) + + return ( + has_vv_mag, + has_vv_grad, + is_old_vv, + has_4D_mag, + ctf_other_types, + has_CTF_grad, + n_kit_grads, + has_any_meg, + has_eeg_coils, + has_eeg_coils_and_meg, + has_eeg_coils_only, + has_neuromag_122_grad, + has_csd_coils, + ) + + +@fill_doc +def make_1020_channel_selections(info, midline="z", *, return_ch_names=False): + """Map hemisphere names to corresponding EEG channel names or indices. + + This function uses a simple heuristic to separate channel names into three + Region of Interest-based selections: ``Left``, ``Midline`` and ``Right``. + + The heuristic is that any of the channel names ending + with odd numbers are filed under ``Left``; those ending with even numbers + are filed under ``Right``; and those ending with the character(s) specified + in ``midline`` are filed under ``Midline``. Other channels are ignored. + + This is appropriate for 10/20, 10/10, 10/05, …, sensor arrangements, but + not for other naming conventions. + + Parameters + ---------- + %(info_not_none)s If channel locations are present, the channel lists will + be sorted from posterior to anterior; otherwise, the order specified in + ``info["ch_names"]`` will be kept. + midline : str + Names ending in any of these characters are stored under the + ``Midline`` key. Defaults to ``'z'``. Capitalization is ignored. + return_ch_names : bool + Whether to return channel names instead of channel indices. + + .. versionadded:: 1.4.0 + + Returns + ------- + selections : dict + A dictionary mapping from region of interest name to a list of channel + indices (if ``return_ch_names=False``) or to a list of channel names + (if ``return_ch_names=True``). + """ + _validate_type(info, "info") + + try: + from .layout import find_layout + + layout = find_layout(info) + pos = layout.pos + ch_names = layout.names + except RuntimeError: # no channel positions found + ch_names = info["ch_names"] + pos = None + + selections = dict(Left=[], Midline=[], Right=[]) + for pick, channel in enumerate(ch_names): + last_char = channel[-1].lower() # in 10/20, last char codes hemisphere + if last_char in midline: + selection = "Midline" + elif last_char.isdigit(): + selection = "Left" if int(last_char) % 2 else "Right" + else: # ignore the channel + continue + selections[selection].append(pick) + + if pos is not None: + # sort channels from front to center + # (y-coordinate of the position info in the layout) + selections = { + selection: np.array(picks)[pos[picks, 1].argsort()] + for selection, picks in selections.items() + } + + # convert channel indices to names if requested + if return_ch_names: + for selection, ch_indices in selections.items(): + selections[selection] = [info.ch_names[idx] for idx in ch_indices] + + return selections + + +@verbose +def combine_channels( + inst, + groups, + method="mean", + keep_stim=False, + drop_bad=False, + *, + on_missing="raise", + verbose=None, +): + """Combine channels based on specified channel grouping. + + Parameters + ---------- + inst : instance of Raw, Epochs, or Evoked + An MNE-Python object to combine the channels for. The object can be of + type Raw, Epochs, or Evoked. + groups : dict + Specifies which channels are aggregated into a single channel, with + aggregation method determined by the ``method`` parameter. One new + pseudo-channel is made per dict entry; the dict values must be lists of + picks (integer indices of ``ch_names``). For example:: + + groups=dict(Left=[1, 2, 3, 4], Right=[5, 6, 7, 8]) + + Note that within a dict entry all channels must have the same type. + method : str | callable + Which method to use to combine channels. If a :class:`str`, must be one + of 'mean', 'median', or 'std' (standard deviation). If callable, the + callable must accept one positional input (data of shape ``(n_channels, + n_times)``, or ``(n_epochs, n_channels, n_times)``) and return an + :class:`array ` of shape ``(n_times,)``, or ``(n_epochs, + n_times)``. For example with an instance of Raw or Evoked:: + + method = lambda data: np.mean(data, axis=0) + + Another example with an instance of Epochs:: + + method = lambda data: np.median(data, axis=1) + + Defaults to ``'mean'``. + keep_stim : bool + If ``True``, include stimulus channels in the resulting object. + Defaults to ``False``. + drop_bad : bool + If ``True``, drop channels marked as bad before combining. Defaults to + ``False``. + %(on_missing_epochs)s + .. versionadded:: 1.11.0 + %(verbose)s + + Returns + ------- + combined_inst : same type as the input data + An MNE-Python object of the same type as the input ``inst``, containing + one virtual channel for each group in ``groups`` (and, if ``keep_stim`` + is ``True``, also containing stimulus channels). + + See Also + -------- + mne.channels.equalize_channels + mne.channels.rename_channels + mne.channels.unify_bad_channels + """ + from ..epochs import BaseEpochs, EpochsArray + from ..evoked import Evoked, EvokedArray + from ..io import BaseRaw, RawArray + + ch_axis = 1 if isinstance(inst, BaseEpochs) else 0 + ch_idx = list(range(inst.info["nchan"])) + ch_names = inst.info["ch_names"] + ch_types = inst.get_channel_types() + kwargs = dict() + if isinstance(inst, BaseEpochs): + kwargs["copy"] = False + inst_data = inst.get_data(**kwargs) + groups = OrderedDict(deepcopy(groups)) + + # Convert string values of ``method`` into callables + # XXX Possibly de-duplicate with _make_combine_callable of mne/viz/utils.py + if isinstance(method, str): + method_dict = { + key: partial(getattr(np, key), axis=ch_axis) + for key in ("mean", "median", "std") + } + try: + method = method_dict[method] + except KeyError: + raise ValueError( + '"method" must be a callable, or one of "mean", ' + f'"median", or "std"; got "{method}".' + ) + + # Instantiate channel info and data + new_ch_names, new_ch_types, new_data = [], [], [] + if not isinstance(keep_stim, bool): + raise TypeError(f'"keep_stim" must be of type bool, not {type(keep_stim)}.') + if keep_stim: + stim_ch_idx = list(pick_types(inst.info, meg=False, stim=True)) + if stim_ch_idx: + new_ch_names = [ch_names[idx] for idx in stim_ch_idx] + new_ch_types = [ch_types[idx] for idx in stim_ch_idx] + new_data = [np.take(inst_data, idx, axis=ch_axis) for idx in stim_ch_idx] + else: + warn("Could not find stimulus channels.") + + # Get indices of bad channels + ch_idx_bad = [] + if not isinstance(drop_bad, bool): + raise TypeError(f'"drop_bad" must be of type bool, not {type(drop_bad)}.') + if drop_bad and inst.info["bads"]: + ch_idx_bad = pick_channels(ch_names, inst.info["bads"]) + + # Check correctness of combinations + for this_group, this_picks in groups.items(): + # Check if channel indices are out of bounds + if not all(idx in ch_idx for idx in this_picks): + raise ValueError("Some channel indices are out of bounds.") + # Check if heterogeneous sensor type combinations + this_ch_type = np.array(ch_types)[this_picks] + if len(set(this_ch_type)) > 1: + types = ", ".join(set(this_ch_type)) + raise ValueError( + "Cannot combine sensors of different types; " + f'"{this_group}" contains types {types}.' + ) + # Remove bad channels + these_bads = [idx for idx in this_picks if idx in ch_idx_bad] + this_picks = [idx for idx in this_picks if idx not in ch_idx_bad] + if these_bads: + logger.info( + f"Dropped the following channels in group {this_group}: {these_bads}" + ) + # Check if combining less than 2 channel + if len(set(this_picks)) < 2: + warn( + f'Less than 2 channels in group "{this_group}" when ' + f'combining by method "{method}".' + ) + # If all good create more detailed dict without bad channels + groups[this_group] = dict(picks=this_picks, ch_type=this_ch_type[0]) + + # Combine channels and add them to the new instance + for this_group, this_group_dict in groups.items(): + new_ch_names.append(this_group) + new_ch_types.append(this_group_dict["ch_type"]) + this_picks = this_group_dict["picks"] + this_data = np.take(inst_data, this_picks, axis=ch_axis) + new_data.append(method(this_data)) + new_data = np.swapaxes(new_data, 0, ch_axis) + info = create_info( + sfreq=inst.info["sfreq"], ch_names=new_ch_names, ch_types=new_ch_types + ) + # create new instances and make sure to copy important attributes + if isinstance(inst, BaseRaw): + combined_inst = RawArray(new_data, info, first_samp=inst.first_samp) + elif isinstance(inst, BaseEpochs): + combined_inst = EpochsArray( + new_data, + info, + events=inst.events, + event_id=inst.event_id, + tmin=inst.times[0], + baseline=inst.baseline, + on_missing=on_missing, + ) + if inst.metadata is not None: + combined_inst.metadata = inst.metadata.copy() + elif isinstance(inst, Evoked): + combined_inst = EvokedArray( + new_data, info, tmin=inst.times[0], baseline=inst.baseline + ) + + return combined_inst + + +# NeuroMag channel groupings +_SELECTIONS = [ + "Vertex", + "Left-temporal", + "Right-temporal", + "Left-parietal", + "Right-parietal", + "Left-occipital", + "Right-occipital", + "Left-frontal", + "Right-frontal", +] +_EEG_SELECTIONS = ["EEG 1-32", "EEG 33-64", "EEG 65-96", "EEG 97-128"] + + +def _divide_to_regions(info, add_stim=True): + """Divide channels to regions by positions.""" + picks = _pick_data_channels(info, exclude=[]) + chs_in_lobe = len(picks) // 4 + pos = np.array([ch["loc"][:3] for ch in info["chs"]]) + x, y, z = pos.T + + frontal = picks[np.argsort(y[picks])[-chs_in_lobe:]] + picks = np.setdiff1d(picks, frontal) + + occipital = picks[np.argsort(y[picks])[:chs_in_lobe]] + picks = np.setdiff1d(picks, occipital) + + temporal = picks[np.argsort(z[picks])[:chs_in_lobe]] + picks = np.setdiff1d(picks, temporal) + + lt, rt = _divide_side(temporal, x) + lf, rf = _divide_side(frontal, x) + lo, ro = _divide_side(occipital, x) + lp, rp = _divide_side(picks, x) # Parietal lobe from the remaining picks. + + # Because of the way the sides are divided, there may be outliers in the + # temporal lobes. Here we switch the sides for these outliers. For other + # lobes it is not a big problem because of the vicinity of the lobes. + with np.errstate(invalid="ignore"): # invalid division, greater compare + zs = np.abs(zscore(x[rt])) + outliers = np.array(rt)[np.where(zs > 2.0)[0]] + rt = list(np.setdiff1d(rt, outliers)) + + with np.errstate(invalid="ignore"): # invalid division, greater compare + zs = np.abs(zscore(x[lt])) + outliers = np.append(outliers, (np.array(lt)[np.where(zs > 2.0)[0]])) + lt = list(np.setdiff1d(lt, outliers)) + + l_mean = np.mean(x[lt]) + r_mean = np.mean(x[rt]) + for outlier in outliers: + if abs(l_mean - x[outlier]) < abs(r_mean - x[outlier]): + lt.append(outlier) + else: + rt.append(outlier) + + if add_stim: + stim_ch = _get_stim_channel(None, info, raise_error=False) + if len(stim_ch) > 0: + for region in [lf, rf, lo, ro, lp, rp, lt, rt]: + region.append(info["ch_names"].index(stim_ch[0])) + return OrderedDict( + [ + ("Left-frontal", lf), + ("Right-frontal", rf), + ("Left-parietal", lp), + ("Right-parietal", rp), + ("Left-occipital", lo), + ("Right-occipital", ro), + ("Left-temporal", lt), + ("Right-temporal", rt), + ] + ) + + +def _divide_side(lobe, x): + """Make a separation between left and right lobe evenly.""" + lobe = np.asarray(lobe) + median = np.median(x[lobe]) + + left = lobe[np.where(x[lobe] < median)[0]] + right = lobe[np.where(x[lobe] > median)[0]] + medians = np.where(x[lobe] == median)[0] + + left = np.sort(np.concatenate([left, lobe[medians[1::2]]])) + right = np.sort(np.concatenate([right, lobe[medians[::2]]])) + return list(left), list(right) + + +@verbose +def read_vectorview_selection(name, fname=None, info=None, verbose=None): + """Read Neuromag Vector View channel selection from a file. + + Parameters + ---------- + name : str | list of str + Name of the selection. If a list, the selections are combined. + Supported selections are: ``'Vertex'``, ``'Left-temporal'``, + ``'Right-temporal'``, ``'Left-parietal'``, ``'Right-parietal'``, + ``'Left-occipital'``, ``'Right-occipital'``, ``'Left-frontal'`` and + ``'Right-frontal'``. Selections can also be matched and combined by + spcecifying common substrings. For example, ``name='temporal`` will + produce a combination of ``'Left-temporal'`` and ``'Right-temporal'``. + fname : path-like + Filename of the selection file (if ``None``, built-in selections are + used). + %(info)s Used to determine which channel naming convention to use, e.g. + ``'MEG 0111'`` (with space) for old Neuromag systems and ``'MEG0111'`` + (without space) for new ones. + %(verbose)s + + Returns + ------- + sel : list of str + List with channel names in the selection. + """ + # convert name to list of string + if not isinstance(name, list | tuple): + name = [name] + if isinstance(info, Info): + picks = pick_types(info, meg=True, exclude=()) + if len(picks) > 0 and " " not in info["ch_names"][picks[0]]: + spacing = "new" + else: + spacing = "old" + elif info is not None: + raise TypeError(f"info must be an instance of Info or None, not {type(info)}") + else: # info is None + spacing = "old" + + # use built-in selections by default + if fname is None: + fname = op.join(op.dirname(__file__), "..", "data", "mne_analyze.sel") + + fname = str(_check_fname(fname, must_exist=True, overwrite="read")) + + # use this to make sure we find at least one match for each name + name_found = {n: False for n in name} + with open(fname) as fid: + sel = [] + for line in fid: + line = line.strip() + # skip blank lines and comments + if len(line) == 0 or line[0] == "#": + continue + # get the name of the selection in the file + pos = line.find(":") + if pos < 0: + logger.info('":" delimiter not found in selections file, skipping line') + continue + sel_name_file = line[:pos] + # search for substring match with name provided + for n in name: + if sel_name_file.find(n) >= 0: + sel.extend(line[pos + 1 :].split("|")) + name_found[n] = True + break + + # make sure we found at least one match for each name + for n, found in name_found.items(): + if not found: + raise ValueError(f'No match for selection name "{n}" found') + + # make the selection a sorted list with unique elements + sel = list(set(sel)) + sel.sort() + if spacing == "new": # "new" or "old" by now, "old" is default + sel = [s.replace("MEG ", "MEG") for s in sel] + return sel diff --git a/mne-python/source/mne/channels/data/canonical_meg/ctf151.csv b/mne-python/source/mne/channels/data/canonical_meg/ctf151.csv new file mode 100644 index 0000000000000000000000000000000000000000..40c42b0b2e84a12baaeae0892b9635bb07a668b0 --- /dev/null +++ b/mne-python/source/mne/channels/data/canonical_meg/ctf151.csv @@ -0,0 +1,152 @@ +name,coil_type,x,y,z,ex_x,ex_y,ex_z,ey_x,ey_y,ey_z,ez_x,ez_y,ez_z +MLC11-606,5001,-0.014323,0.048909,0.083084,0.728954,0.665674,-0.159696,-0.680884,0.680884,-0.269802,-0.070866,0.305408,0.949581 +MLC12-606,5001,-0.040601,0.042758,0.079940,0.708622,0.705572,-0.004790,-0.644792,0.644792,-0.410470,-0.286528,0.293956,0.911862 +MLC13-606,5001,-0.073375,0.034411,0.064147,0.561962,0.806275,0.184715,-0.516439,0.516439,-0.683068,-0.646135,0.288465,0.706610 +MLC14-606,5001,-0.090027,0.012140,0.050707,0.289690,0.900312,0.324835,-0.425104,0.425104,-0.799107,-0.857535,0.093405,0.505875 +MLC15-606,5001,-0.098328,-0.010274,0.030432,0.013822,0.964761,0.262763,-0.257367,0.257367,-0.931410,-0.966215,-0.054752,0.251855 +MLC21-606,5001,-0.027556,0.020578,0.089149,0.713508,0.699800,-0.034442,-0.680665,0.680665,-0.270906,-0.166137,0.216737,0.961989 +MLC22-606,5001,-0.055319,0.020081,0.080971,0.655910,0.744349,0.125403,-0.632790,0.632790,-0.446268,-0.411533,0.213358,0.886070 +MLC23-606,5001,-0.073206,0.000517,0.073274,0.495265,0.807767,0.319725,-0.581697,0.581697,-0.568556,-0.645245,0.095603,0.757971 +MLC24-606,5001,-0.087053,-0.018549,0.057109,0.227250,0.876284,0.424834,-0.480349,0.480349,-0.733846,-0.847126,-0.037302,0.530081 +MLC31-606,5001,-0.044035,-0.004914,0.090291,0.676633,0.728163,0.109299,-0.670812,0.670812,-0.316264,-0.303611,0.140676,0.942354 +MLC32-606,5001,-0.062550,-0.025444,0.082237,0.521289,0.756356,0.395201,-0.651803,0.651803,-0.387694,-0.550828,-0.055493,0.832772 +MLC33-606,5001,-0.047154,-0.050511,0.086130,0.598858,0.639045,0.482691,-0.705885,0.705885,-0.058770,-0.378281,-0.305530,0.873816 +MLC41-606,5001,-0.014313,-0.003184,0.095809,0.712567,0.699474,-0.054632,-0.697168,0.697168,-0.167077,-0.078778,0.157141,0.984429 +MLC42-606,5001,-0.029421,-0.029321,0.094953,0.682652,0.709901,0.173283,-0.702775,0.702775,-0.110515,-0.200234,-0.046336,0.978652 +MLC43-606,5001,-0.014429,-0.056301,0.092331,0.710556,0.626474,0.320375,-0.695237,0.695237,0.182462,-0.108429,-0.352386,0.929552 +MLF11-606,5001,-0.031508,0.120067,-0.017582,0.011661,-0.037725,0.999220,0.955395,0.295331,0.000000,-0.295101,0.954650,0.039486 +MLF12-606,5001,-0.058710,0.106298,-0.023361,0.028819,-0.039229,0.998815,0.805900,0.592051,0.000000,-0.591349,0.804945,0.048677 +MLF21-606,5001,-0.015126,0.121044,0.010698,0.028849,-0.170200,0.984987,0.985937,0.167115,-0.000000,-0.164606,0.971136,0.172627 +MLF22-606,5001,-0.046050,0.110818,0.008105,0.075339,-0.143170,0.986826,0.884954,0.465679,0.000000,-0.459545,0.873296,0.161782 +MLF23-606,5001,-0.071448,0.092577,-0.000471,0.653149,0.757212,0.005099,-0.048882,0.048882,-0.997608,-0.755650,0.651337,0.068942 +MLF31-606,5001,-0.032269,0.107560,0.035421,0.882115,0.433682,-0.183831,-0.354650,0.354650,-0.865128,-0.309995,0.828338,0.466647 +MLF32-606,5001,-0.061468,0.093424,0.030154,0.751575,0.659104,-0.026780,-0.267996,0.267996,-0.925395,-0.602755,0.702680,0.378057 +MLF33-606,5001,-0.081174,0.072412,0.018828,0.446328,0.892010,0.071482,-0.156415,0.156415,-0.975227,-0.881093,0.424091,0.209336 +MLF34-606,5001,-0.092545,0.048544,0.009927,0.363299,0.931232,0.028655,-0.050327,0.050327,-0.997464,-0.930312,0.360936,0.065150 +MLF41-606,5001,-0.014336,0.095188,0.057546,0.822617,0.461102,-0.332695,-0.560705,0.560705,-0.609278,-0.094395,0.687747,0.719788 +MLF42-606,5001,-0.046064,0.085854,0.054833,0.780887,0.615876,-0.104459,-0.471648,0.471648,-0.745048,-0.409589,0.631067,0.658780 +MLF43-606,5001,-0.073502,0.066873,0.045243,0.547547,0.828097,0.120196,-0.366419,0.366419,-0.855262,-0.752283,0.424254,0.504063 +MLF44-606,5001,-0.088155,0.042438,0.038958,0.432012,0.888804,0.152949,-0.302621,0.302621,-0.903793,-0.849580,0.344164,0.399706 +MLF45-606,5001,-0.099700,0.019934,0.021664,0.142753,0.974410,0.173628,-0.200228,0.200228,-0.959071,-0.969294,0.102145,0.223688 +MLF51-606,5001,-0.029080,0.070584,0.072174,0.757825,0.629770,-0.170562,-0.624551,0.624551,-0.468904,-0.188777,0.461872,0.866624 +MLF52-606,5001,-0.057213,0.059096,0.065923,0.665936,0.742456,0.072720,-0.567299,0.567299,-0.596945,-0.484460,0.356273,0.798980 +MLO11-606,5001,-0.014579,-0.120515,0.009576,0.958382,-0.066309,0.277682,-0.253044,0.253044,0.933776,-0.132184,-0.965180,0.225734 +MLO12-606,5001,-0.049711,-0.108916,0.011668,0.809457,-0.256524,0.528181,-0.405781,0.405781,0.818952,-0.424407,-0.877232,0.224370 +MLO21-606,5001,-0.033745,-0.119879,-0.015197,0.947630,-0.301709,0.104731,-0.083246,0.083246,0.993046,-0.308330,-0.949759,0.053770 +MLO22-606,5001,-0.063545,-0.103479,-0.014767,0.770540,-0.569550,0.286147,-0.204412,0.204412,0.957304,-0.603725,-0.796134,0.041085 +MLO31-606,5001,-0.014547,-0.125460,-0.043946,0.992248,-0.116563,0.043104,-0.038815,0.038815,0.998492,-0.118060,-0.992425,0.033990 +MLO32-606,5001,-0.047892,-0.115062,-0.041666,0.892422,-0.444131,0.079567,-0.059321,0.059321,0.996475,-0.447286,-0.893996,0.026593 +MLO33-606,5001,-0.075684,-0.095584,-0.041835,-0.229186,0.248412,0.941151,-0.665556,0.665556,-0.337744,-0.710288,-0.703795,0.012796 +MLO41-606,5001,-0.032572,-0.122181,-0.069424,0.960593,-0.275112,0.039690,-0.032086,0.032086,0.998970,-0.276102,-0.960877,0.021995 +MLO42-606,5001,-0.062229,-0.107652,-0.070052,0.801034,-0.573468,0.171694,-0.123009,0.123009,0.984752,-0.585844,-0.809940,0.027993 +MLO43-606,5001,-0.084444,-0.083231,-0.070377,-0.563043,0.811016,0.158855,-0.114095,0.114095,-0.986896,-0.818514,-0.573790,0.028293 +MLP11-606,5001,-0.030594,-0.075186,0.078347,0.717860,0.437855,0.541257,-0.664071,0.664071,0.343540,-0.209012,-0.606047,0.767477 +MLP12-606,5001,-0.061450,-0.070554,0.067487,0.459771,0.471086,0.752787,-0.707067,0.707067,-0.010628,-0.537278,-0.527384,0.658178 +MLP13-606,5001,-0.077217,-0.045504,0.065098,0.280552,0.745469,0.604621,-0.621218,0.621218,-0.477679,-0.731696,-0.241587,0.637382 +MLP21-606,5001,-0.014445,-0.097723,0.058354,0.835874,0.241523,0.492931,-0.538083,0.538083,0.648794,-0.108539,-0.807548,0.579729 +MLP22-606,5001,-0.042293,-0.090882,0.057869,0.719606,0.188863,0.668205,-0.616523,0.616523,0.489693,-0.319479,-0.764350,0.560092 +MLP31-606,5001,-0.030865,-0.107955,0.035115,0.846355,-0.008026,0.532559,-0.467588,0.467588,0.750149,-0.255039,-0.883910,0.391992 +MLP32-606,5001,-0.062374,-0.092211,0.037356,0.537619,0.045681,0.841950,-0.653527,0.653527,0.381845,-0.532793,-0.755524,0.381202 +MLP33-606,5001,-0.081127,-0.068351,0.042688,0.010832,0.601494,0.798804,-0.626622,0.626622,-0.463345,-0.779248,-0.495530,0.383697 +MLP34-606,5001,-0.093583,-0.040425,0.037142,-0.054400,0.916107,0.397225,-0.354234,0.354234,-0.865469,-0.933573,-0.187792,0.305246 +MLT11-606,5001,-0.086028,0.069026,-0.012285,0.389936,0.920441,0.027174,-0.051089,0.051089,-0.997386,-0.919423,0.387529,0.066946 +MLT12-606,5001,-0.100116,0.028233,-0.007272,0.218301,0.975644,0.021514,-0.028385,0.028385,-0.999194,-0.975469,0.217514,0.033890 +MLT13-606,5001,-0.107074,-0.002177,0.001477,-0.043390,0.996868,0.066119,-0.063305,0.063305,-0.995984,-0.997051,-0.047402,0.060360 +MLT14-606,5001,-0.103195,-0.031971,0.007985,-0.127076,0.989851,0.063609,-0.056766,0.056766,-0.996772,-0.990267,-0.130276,0.048977 +MLT15-606,5001,-0.093473,-0.061826,0.013108,-0.362604,0.909178,0.204728,-0.156961,0.156961,-0.975052,-0.918630,-0.385693,0.085791 +MLT16-606,5001,-0.076536,-0.088203,0.012276,-0.151314,0.347344,0.925449,-0.660770,0.660770,-0.356042,-0.735178,-0.665383,0.129531 +MLT21-606,5001,-0.078545,0.085099,-0.036714,0.532288,0.846504,0.009988,-0.031754,0.031754,-0.998991,-0.845968,0.531434,0.043782 +MLT22-606,5001,-0.097202,0.049296,-0.030091,0.330196,0.943685,0.020724,-0.033742,0.033742,-0.998861,-0.943309,0.329121,0.042983 +MLT23-606,5001,-0.109608,0.008670,-0.027357,0.015858,0.998524,0.051943,-0.052713,0.052713,-0.997218,-0.998484,0.013076,0.053471 +MLT24-606,5001,-0.110483,-0.021821,-0.021287,-0.089815,0.994777,0.048498,-0.044627,0.044627,-0.998006,-0.994958,-0.091800,0.040385 +MLT25-606,5001,-0.106832,-0.053178,-0.016136,-0.277065,0.958481,0.067448,-0.054428,0.054428,-0.997033,-0.959308,-0.279914,0.037088 +MLT26-606,5001,-0.084868,-0.079047,-0.015189,-0.532950,0.827536,0.176487,-0.127594,0.127594,-0.983585,-0.836471,-0.546721,0.037587 +MLT31-606,5001,-0.089958,0.063191,-0.056011,0.383596,0.923380,0.014916,-0.027612,0.027612,-0.999237,-0.923088,0.382892,0.036088 +MLT32-606,5001,-0.101867,0.027638,-0.050488,0.193105,0.980947,0.021282,-0.026993,0.026993,-0.999271,-0.980807,0.192389,0.031691 +MLT33-606,5001,-0.111481,-0.007075,-0.050441,-0.055374,0.997812,0.036128,-0.034263,0.034263,-0.998825,-0.997878,-0.056547,0.032291 +MLT34-606,5001,-0.111079,-0.039430,-0.045815,-0.166044,0.985424,0.036988,-0.032089,0.032089,-0.998970,-0.985596,-0.167060,0.026293 +MLT35-606,5001,-0.098093,-0.070086,-0.042911,-0.428947,0.901013,0.064653,-0.048498,0.048498,-0.997645,-0.902027,-0.431072,0.022894 +MLT41-606,5001,-0.099426,0.042882,-0.076463,0.315201,0.948888,0.016097,-0.025387,0.025387,-0.999355,-0.948685,0.314589,0.032091 +MLT42-606,5001,-0.111482,0.010406,-0.076485,0.031362,0.998567,0.043361,-0.044741,0.044741,-0.997996,-0.998506,0.029359,0.046080 +MLT43-606,5001,-0.112422,-0.022736,-0.074725,-0.076938,0.996648,0.027794,-0.025871,0.025871,-0.999330,-0.996700,-0.077605,0.023794 +MLT44-606,5001,-0.108073,-0.056083,-0.071817,-0.287555,0.956905,0.040564,-0.032561,0.032561,-0.998939,-0.957211,-0.288571,0.021795 +MRC11-606,5001,0.014682,0.048575,0.082890,-0.729737,0.660819,-0.175506,-0.681330,-0.681330,0.267544,0.057221,0.314814,0.947427 +MRC12-606,5001,0.040925,0.042458,0.079901,-0.712472,0.701485,-0.017397,-0.645653,-0.645653,0.407755,0.274802,0.301746,0.912926 +MRC13-606,5001,0.073555,0.034182,0.064101,-0.568281,0.802818,0.180388,-0.520547,-0.520547,0.676803,0.637250,0.290714,0.713721 +MRC14-606,5001,0.089556,0.011853,0.050762,-0.291672,0.900442,0.322695,-0.424134,-0.424134,0.800138,0.857343,0.096512,0.505616 +MRC15-606,5001,0.097972,-0.010831,0.030825,-0.025831,0.967427,0.251828,-0.250152,-0.250152,0.935333,0.967862,-0.038834,0.248466 +MRC21-606,5001,0.027331,0.020157,0.089367,-0.714220,0.699033,-0.035256,-0.676422,-0.676422,0.291388,0.179842,0.231963,0.955955 +MRC22-606,5001,0.055121,0.019588,0.080528,-0.658844,0.743012,0.117718,-0.631041,-0.631041,0.451193,0.409527,0.222981,0.884628 +MRC23-606,5001,0.073016,0.000199,0.073053,-0.500352,0.806855,0.314058,-0.581980,-0.581980,0.567978,0.641051,0.101413,0.760768 +MRC24-606,5001,0.086971,-0.018806,0.057254,-0.234253,0.876277,0.421029,-0.480830,-0.480830,0.733215,0.844943,-0.030686,0.533976 +MRC31-606,5001,0.044083,-0.004870,0.090137,-0.676983,0.727686,0.110305,-0.672477,-0.672477,0.309111,0.299113,0.135085,0.944607 +MRC32-606,5001,0.062387,-0.025962,0.082456,-0.521312,0.761837,0.384496,-0.646667,-0.646667,0.404529,0.556826,-0.037756,0.829770 +MRC33-606,5001,0.047105,-0.050736,0.086031,-0.600513,0.643687,0.474396,-0.705647,-0.705647,0.064220,0.376094,-0.296192,0.877966 +MRC41-606,5001,0.014224,-0.003157,0.095721,-0.711953,0.700730,-0.045828,-0.696738,-0.696738,0.170620,0.087629,0.153404,0.984271 +MRC42-606,5001,0.029356,-0.029372,0.095017,-0.682059,0.709996,0.175216,-0.702655,-0.702655,0.112032,0.202659,-0.046704,0.978135 +MRC43-606,5001,0.014375,-0.055939,0.092312,-0.712427,0.620820,0.327155,-0.693641,-0.693641,-0.194227,0.106348,-0.365300,0.924795 +MRF11-606,5001,0.031295,0.119838,-0.017083,-0.005277,-0.015945,0.999859,0.949362,-0.314185,0.000000,0.314140,0.949228,0.016796 +MRF12-606,5001,0.059471,0.106357,-0.023353,-0.030079,-0.041770,0.998674,0.811490,-0.584366,0.000000,0.583591,0.810415,0.051474 +MRF21-606,5001,0.014965,0.120821,0.010894,-0.028796,-0.158697,0.986907,0.983933,-0.178536,0.000000,0.176199,0.971051,0.161289 +MRF22-606,5001,0.046292,0.110206,0.008045,-0.074906,-0.145619,0.986501,0.889248,-0.457425,0.000000,0.451251,0.877244,0.163755 +MRF23-606,5001,0.071211,0.091936,0.000076,-0.652438,0.757832,0.003919,-0.037136,-0.037136,0.998620,0.756931,0.651392,0.052372 +MRF31-606,5001,0.032477,0.107175,0.035638,-0.885238,0.427227,-0.183932,-0.349200,-0.349200,0.869551,0.307266,0.833988,0.458313 +MRF32-606,5001,0.061104,0.092617,0.030671,-0.751261,0.659548,-0.024566,-0.250490,-0.250490,0.935152,0.610624,0.708697,0.353394 +MRF33-606,5001,0.081210,0.071003,0.019267,-0.477837,0.876444,0.059312,-0.145609,-0.145609,0.978568,0.866297,0.458959,0.197195 +MRF34-606,5001,0.092886,0.047228,0.009246,-0.403750,0.913940,0.041230,-0.080290,-0.080290,0.993533,0.911339,0.397829,0.105798 +MRF41-606,5001,0.014500,0.095034,0.057578,-0.823580,0.458858,-0.333414,-0.559313,-0.559313,0.611832,0.094262,0.690376,0.717284 +MRF42-606,5001,0.046135,0.085503,0.054527,-0.782403,0.613320,-0.108089,-0.474205,-0.474205,0.741794,0.403701,0.631639,0.661859 +MRF43-606,5001,0.073015,0.066295,0.045421,-0.547976,0.828301,0.116788,-0.358947,-0.358947,0.861577,0.755566,0.430202,0.494010 +MRF44-606,5001,0.087909,0.042293,0.038909,-0.430313,0.889269,0.155018,-0.304778,-0.304778,0.902342,0.849671,0.341044,0.402180 +MRF45-606,5001,0.099093,0.018961,0.022812,-0.158174,0.977289,0.141021,-0.167276,-0.167276,0.971616,0.973139,0.130095,0.189935 +MRF51-606,5001,0.028977,0.070435,0.072073,-0.757366,0.631441,-0.166368,-0.623430,-0.623430,0.471878,0.194244,0.461104,0.865825 +MRF52-606,5001,0.056717,0.058547,0.066019,-0.665059,0.743343,0.071679,-0.559649,-0.559649,0.611217,0.494459,0.366380,0.788211 +MRO11-606,5001,0.014865,-0.120307,0.009613,-0.957321,-0.071920,0.279934,-0.253850,-0.253850,-0.933338,0.138187,-0.964566,0.224760 +MRO12-606,5001,0.049526,-0.108720,0.011989,-0.796167,-0.268123,0.542428,-0.413457,-0.413457,-0.811238,0.441782,-0.870152,0.218324 +MRO21-606,5001,0.033612,-0.119850,-0.015080,-0.937397,-0.326553,0.121033,-0.094891,-0.094891,-0.990955,0.335085,-0.940403,0.057964 +MRO22-606,5001,0.063510,-0.103910,-0.015029,-0.680113,-0.500591,0.535589,-0.381807,-0.381807,-0.841693,0.625836,-0.776937,0.068543 +MRO31-606,5001,0.014742,-0.125103,-0.043821,-0.989020,-0.141663,0.042079,-0.037164,-0.037164,-0.998618,0.143031,-0.989217,0.031491 +MRO32-606,5001,0.047848,-0.114667,-0.041267,-0.881919,-0.466048,0.070838,-0.052407,-0.052407,-0.997250,0.468479,-0.883206,0.021795 +MRO33-606,5001,0.073981,-0.094596,-0.041802,0.559448,0.634024,0.533884,-0.378039,-0.378039,0.845088,0.737635,-0.674611,0.028193 +MRO41-606,5001,0.032275,-0.121977,-0.069288,-0.945453,-0.322225,0.047856,-0.037698,-0.037698,-0.998578,0.323570,-0.945912,0.023494 +MRO42-606,5001,0.062817,-0.108083,-0.069750,-0.781295,-0.580887,0.228358,-0.163120,-0.163120,-0.973028,0.602470,-0.797472,0.032691 +MRO43-606,5001,0.084197,-0.083077,-0.070770,0.517538,0.797735,0.309472,-0.223255,-0.223255,0.948849,0.826021,-0.560157,0.062555 +MRP11-606,5001,0.030292,-0.075111,0.078419,-0.713530,0.434910,0.549297,-0.665590,-0.665590,-0.337607,0.218778,-0.606500,0.764391 +MRP12-606,5001,0.060934,-0.069857,0.066840,-0.466729,0.469603,0.749425,-0.707104,-0.707104,0.002712,0.531195,-0.528655,0.662084 +MRP13-606,5001,0.077116,-0.045416,0.065178,-0.284455,0.742401,0.606570,-0.623784,-0.623784,0.470942,0.727996,-0.244407,0.640536 +MRP21-606,5001,0.014682,-0.097520,0.058357,-0.838087,0.244289,0.487783,-0.535909,-0.535909,-0.652383,0.102037,-0.808161,0.580055 +MRP22-606,5001,0.042445,-0.090945,0.056956,-0.715220,0.232735,0.659011,-0.627948,-0.627948,-0.459743,0.306826,-0.742642,0.595266 +MRP31-606,5001,0.031058,-0.107704,0.034895,-0.841996,0.002768,0.539477,-0.475652,-0.475652,-0.739939,0.254556,-0.879629,0.401813 +MRP32-606,5001,0.062206,-0.092419,0.036878,-0.511716,0.096575,0.853709,-0.668681,-0.668681,-0.325166,0.539456,-0.737251,0.406752 +MRP33-606,5001,0.080804,-0.068567,0.042681,-0.016000,0.618936,0.785278,-0.621428,-0.621428,0.477132,0.783308,-0.480360,0.394567 +MRP34-606,5001,0.093626,-0.040200,0.037848,0.057987,0.912102,0.405841,-0.360057,-0.360057,0.860650,0.931126,-0.196032,0.307530 +MRT11-606,5001,0.085561,0.067503,-0.011649,-0.416525,0.908964,0.017103,-0.034689,-0.034689,0.998796,0.908462,0.415430,0.045980 +MRT12-606,5001,0.100127,0.026934,-0.006759,-0.258168,0.965929,0.018162,-0.025644,-0.025644,0.999342,0.965760,0.257532,0.031391 +MRT13-606,5001,0.101827,-0.002630,0.001174,0.018081,0.996481,0.081841,-0.080147,-0.080147,0.993556,0.996619,-0.024524,0.078416 +MRT14-606,5001,0.103088,-0.032781,0.008131,0.094323,0.992470,0.078149,-0.071538,-0.071538,0.994869,0.992968,-0.099430,0.064252 +MRT15-606,5001,0.092142,-0.062413,0.013139,0.317626,0.923533,0.214944,-0.168209,-0.168209,0.971294,0.933177,-0.344663,0.101919 +MRT16-606,5001,0.076110,-0.088804,0.012007,0.197293,0.454749,0.868492,-0.624553,-0.624553,0.468899,0.755651,-0.634930,0.160795 +MRT21-606,5001,0.078177,0.084312,-0.036018,-0.534911,0.844894,0.005010,-0.016158,-0.016158,0.999739,0.844754,0.534690,0.022294 +MRT22-606,5001,0.094286,0.046966,-0.029698,-0.361791,0.932132,0.015390,-0.026964,-0.026964,0.999273,0.931869,0.361113,0.034889 +MRT23-606,5001,0.108889,0.007464,-0.027353,-0.074933,0.994822,0.068667,-0.074234,-0.074234,0.994474,0.994422,0.069422,0.079413 +MRT24-606,5001,0.111303,-0.022562,-0.020957,0.058289,0.996510,0.059744,-0.056460,-0.056460,0.996807,0.996702,-0.061476,0.052972 +MRT25-606,5001,0.106354,-0.053615,-0.015657,0.243840,0.967477,0.067307,-0.055395,-0.055395,0.996927,0.968232,-0.246819,0.040086 +MRT26-606,5001,0.084681,-0.079252,-0.014384,0.527825,0.842430,0.108222,-0.078492,-0.078492,0.993820,0.845718,-0.533058,0.024694 +MRT31-606,5001,0.089091,0.062395,-0.055441,-0.380845,0.924587,0.009831,-0.018074,-0.018074,0.999673,0.924462,0.380543,0.023594 +MRT32-606,5001,0.108829,0.028646,-0.049875,-0.194608,0.980640,0.021747,-0.027646,-0.027646,0.999235,0.980491,0.193858,0.032491 +MRT33-606,5001,0.113018,-0.007776,-0.050164,0.030879,0.998256,0.050311,-0.048770,-0.048770,0.997619,0.998333,-0.033259,0.047179 +MRT34-606,5001,0.110632,-0.039914,-0.045242,0.138862,0.989889,0.028926,-0.025610,-0.025610,0.999344,0.989981,-0.139512,0.021795 +MRT35-606,5001,0.096346,-0.070322,-0.042136,0.379963,0.924788,0.019872,-0.015227,-0.015227,0.999768,0.924876,-0.380178,0.008296 +MRT41-606,5001,0.097931,0.041083,-0.075988,-0.342296,0.939522,0.011510,-0.019265,-0.019265,0.999629,0.939395,0.341947,0.024694 +MRT42-606,5001,0.110119,0.009375,-0.075807,-0.064434,0.997523,0.028222,-0.030219,-0.030219,0.999086,0.997464,0.063522,0.032091 +MRT43-606,5001,0.111354,-0.023427,-0.074378,0.045698,0.998319,0.035649,-0.034107,-0.034107,0.998836,0.998373,-0.046860,0.032491 +MRT44-606,5001,0.107178,-0.055523,-0.071359,0.306016,0.950704,0.050165,-0.039854,-0.039854,0.998410,0.951192,-0.307529,0.025693 +MZC01-606,5001,-0.000062,0.023051,0.090654,-0.717685,0.676713,-0.164279,-0.696361,-0.696361,0.173676,0.003131,0.239042,0.971004 +MZC02-606,5001,-0.000030,-0.029744,0.098425,0.707372,0.706297,0.027722,-0.706841,0.706841,0.027417,-0.000230,-0.038989,0.999240 +MZF01-606,5001,-0.000178,0.124916,-0.015391,-0.000408,-0.025990,0.999662,0.999877,-0.015697,0.000000,0.015692,0.999539,0.025993 +MZF02-606,5001,0.000137,0.112065,0.037592,0.000324,-0.461776,0.886997,1.000000,0.000702,0.000000,-0.000622,0.886996,0.461776 +MZF03-606,5001,-0.000081,0.073128,0.073333,-0.752757,0.579007,-0.313222,-0.658277,-0.658277,0.365160,0.005243,0.481064,0.876670 +MZO01-606,5001,0.000029,-0.125034,-0.014613,-0.998403,-0.009537,0.055689,-0.055083,-0.055083,-0.996961,0.012575,-0.998436,0.054469 +MZO02-606,5001,0.000351,-0.126749,-0.067270,-0.999733,-0.005495,0.022451,-0.022323,-0.022323,-0.999502,0.005994,-0.999736,0.022195 +MZP01-606,5001,-0.000225,-0.079496,0.079535,-0.795373,0.455576,0.399791,-0.606073,-0.606073,-0.515122,0.007625,-0.652017,0.758166 +MZP02-606,5001,0.000429,-0.111700,0.037570,0.921610,0.150056,0.357936,-0.387887,0.387887,0.836114,-0.013375,-0.909410,0.415685 diff --git a/mne-python/source/mne/channels/data/canonical_meg/ctf275.csv b/mne-python/source/mne/channels/data/canonical_meg/ctf275.csv new file mode 100644 index 0000000000000000000000000000000000000000..303f1fc79fb92564f4fe20a9dbfc37aa0a4887f7 --- /dev/null +++ b/mne-python/source/mne/channels/data/canonical_meg/ctf275.csv @@ -0,0 +1,275 @@ +name,coil_type,x,y,z,ex_x,ex_y,ex_z,ey_x,ey_y,ey_z,ez_x,ez_y,ez_z +MLC11-2908,5001,-0.011208,0.066410,0.077882,0.743336,0.622237,-0.245505,-0.667660,0.667660,-0.329333,-0.041010,0.408719,0.911738 +MLC12-2908,5001,-0.029377,0.055086,0.080087,0.729741,0.677331,-0.093276,-0.657139,0.657139,-0.369237,-0.188801,0.330743,0.924642 +MLC13-2908,5001,-0.048940,0.046761,0.077050,0.688131,0.724149,0.045643,-0.617483,0.617483,-0.487266,-0.381037,0.307119,0.872060 +MLC14-2908,5001,-0.067813,0.034319,0.070854,0.601464,0.782830,0.159432,-0.550976,0.550976,-0.626779,-0.578504,0.289142,0.762712 +MLC15-2908,5001,-0.082364,0.020713,0.063230,0.533681,0.812381,0.234992,-0.541801,0.541801,-0.642575,-0.649335,0.215611,0.729298 +MLC16-2908,5001,-0.092564,0.003996,0.054394,0.403172,0.893518,0.197680,-0.350223,0.350223,-0.868728,-0.845456,0.281015,0.454130 +MLC17-2908,5001,-0.096570,-0.014194,0.040090,-0.003109,0.956971,0.290167,-0.277911,0.277911,-0.919528,-0.960602,-0.083500,0.265088 +MLC21-2908,5001,-0.032417,0.034322,0.086215,0.717531,0.695245,-0.042239,-0.662502,0.662502,-0.349544,-0.215035,0.278792,0.935967 +MLC22-2908,5001,-0.051732,0.026067,0.082439,0.675389,0.733158,0.079556,-0.629033,0.629033,-0.456764,-0.384924,0.258450,0.886023 +MLC23-2908,5001,-0.067840,0.013360,0.076709,0.563376,0.790899,0.238928,-0.586532,0.586532,-0.558534,-0.581883,0.174526,0.794326 +MLC24-2908,5001,-0.079776,-0.002873,0.071151,0.529676,0.819133,0.220146,-0.517863,0.517863,-0.680909,-0.671760,0.246655,0.698498 +MLC25-2908,5001,-0.087963,-0.020582,0.058993,0.174408,0.881685,0.438421,-0.466124,0.466124,-0.751969,-0.867358,-0.073209,0.492270 +MLC31-2908,5001,-0.060904,-0.005749,0.084315,0.578927,0.770524,0.266713,-0.630436,0.630436,-0.452882,-0.517101,0.094040,0.850742 +MLC32-2908,5001,-0.075071,-0.025033,0.075763,0.287543,0.759499,0.583508,-0.613809,0.613809,-0.496464,-0.735226,-0.215408,0.642683 +MLC41-2908,5001,-0.044002,0.007164,0.089787,0.682929,0.726113,0.079799,-0.660409,0.660409,-0.357379,-0.312197,0.191364,0.930544 +MLC42-2908,5001,-0.056644,-0.026691,0.087498,0.557638,0.744418,0.367263,-0.665390,0.665390,-0.338398,-0.496283,-0.055670,0.866374 +MLC51-2908,5001,-0.011435,0.031052,0.090011,0.722355,0.669679,-0.172431,-0.691165,0.691165,-0.211144,-0.022220,0.271699,0.962126 +MLC52-2908,5001,-0.023376,0.013224,0.093206,0.715985,0.695845,-0.056258,-0.685486,0.685486,-0.245396,-0.132194,0.214264,0.967789 +MLC53-2908,5001,-0.040660,-0.013765,0.093858,0.671713,0.726636,0.144226,-0.682786,0.682786,-0.260013,-0.287411,0.076179,0.954773 +MLC54-2908,5001,-0.038874,-0.036784,0.093824,0.646942,0.697631,0.307860,-0.702363,0.702363,-0.115643,-0.296906,-0.141415,0.944378 +MLC55-2908,5001,-0.028816,-0.055651,0.091562,0.682008,0.607198,0.407647,-0.701228,0.701228,0.128686,-0.207716,-0.373618,0.904027 +MLC61-2908,5001,-0.012099,-0.004949,0.098104,0.712023,0.699775,-0.057769,-0.699292,0.699292,-0.148264,-0.063354,0.145965,0.987259 +MLC62-2908,5001,-0.022103,-0.023945,0.098446,0.695601,0.711169,0.101876,-0.703014,0.703014,-0.107431,-0.148022,0.003108,0.988979 +MLC63-2908,5001,-0.011664,-0.043691,0.097812,0.703955,0.676273,0.217030,-0.704248,0.704248,0.089825,-0.092096,-0.216076,0.972023 +MLF11-2908,5001,-0.022705,0.122754,-0.011827,0.008482,-0.037437,0.999263,0.975282,0.220963,0.000000,-0.220800,0.974563,0.038386 +MLF12-2908,5001,-0.044133,0.114956,-0.014163,0.018254,-0.037141,0.999143,0.897468,0.441080,-0.000000,-0.440702,0.896699,0.041384 +MLF13-2908,5001,-0.062963,0.103760,-0.019639,0.021224,-0.026165,0.999432,0.776627,0.629960,0.000000,-0.629603,0.776186,0.033691 +MLF14-2908,5001,-0.077271,0.088796,-0.029188,0.567604,0.823290,0.004394,-0.017179,0.017179,-0.999705,-0.823122,0.567361,0.023895 +MLF21-2908,5001,-0.011130,0.123530,0.008045,0.018101,-0.116223,0.993058,0.988088,0.153888,0.000000,-0.152820,0.981229,0.117624 +MLF22-2908,5001,-0.032287,0.118529,0.007357,0.031005,-0.090696,0.995396,0.946236,0.323477,-0.000000,-0.321987,0.941880,0.095849 +MLF23-2908,5001,-0.051554,0.110706,0.005185,0.042070,-0.092831,0.994793,0.910831,0.412779,0.000000,-0.410629,0.906088,0.101919 +MLF24-2908,5001,-0.069633,0.096620,-0.000027,0.621735,0.783215,0.004415,-0.027322,0.027322,-0.999253,-0.782751,0.621150,0.038386 +MLF25-2908,5001,-0.081194,0.080834,-0.009116,0.484433,0.874771,0.009997,-0.025596,0.025596,-0.999345,-0.874454,0.483860,0.034790 +MLF31-2908,5001,-0.022015,0.116028,0.026819,0.077204,-0.323745,0.942989,0.972723,0.231969,0.000000,-0.218744,0.917268,0.332823 +MLF32-2908,5001,-0.042654,0.110024,0.024991,0.088634,-0.226299,0.970017,0.931128,0.364692,-0.000000,-0.353757,0.903210,0.243038 +MLF33-2908,5001,-0.062415,0.098330,0.021643,0.672218,0.740220,0.014044,-0.198240,0.198240,-0.959897,-0.713319,0.642476,0.280002 +MLF34-2908,5001,-0.077044,0.084038,0.015639,0.527636,0.849052,0.026646,-0.082337,0.082337,-0.993197,-0.845471,0.521853,0.113352 +MLF35-2908,5001,-0.086906,0.067075,0.006730,0.386420,0.922140,0.018355,-0.034221,0.034221,-0.998828,-0.921688,0.385339,0.044781 +MLF41-2908,5001,-0.011232,0.108701,0.044777,0.882204,0.322184,-0.343386,-0.463253,0.463253,-0.755508,-0.084338,0.825587,0.557936 +MLF42-2908,5001,-0.032245,0.104991,0.043754,0.108835,-0.440345,0.891208,0.970788,0.239938,0.000000,-0.213835,0.865174,0.453595 +MLF43-2908,5001,-0.053297,0.095596,0.041187,0.735078,0.677493,-0.025741,-0.377837,0.377837,-0.845268,-0.562938,0.631064,0.533722 +MLF44-2908,5001,-0.069267,0.082604,0.036899,0.677470,0.735190,0.023018,-0.347361,0.347361,-0.871023,-0.648363,0.582096,0.490703 +MLF45-2908,5001,-0.083808,0.067219,0.027785,0.384500,0.922034,0.044859,-0.082879,0.082879,-0.993107,-0.919397,0.378132,0.108284 +MLF46-2908,5001,-0.093823,0.048079,0.015099,0.373401,0.926998,0.035308,-0.063521,0.063521,-0.995957,-0.925493,0.369648,0.082603 +MLF51-2908,5001,-0.018784,0.095732,0.060421,-0.833516,0.408180,-0.372344,-0.550074,-0.550074,0.628360,0.051667,0.728565,0.683025 +MLF52-2908,5001,-0.041118,0.088868,0.057897,0.746778,0.661714,-0.066765,-0.525350,0.525350,-0.669340,-0.407836,0.534923,0.739951 +MLF53-2908,5001,-0.059693,0.077472,0.054734,0.708729,0.705479,-0.001793,-0.434878,0.434878,-0.788519,-0.555504,0.559626,0.615008 +MLF54-2908,5001,-0.075239,0.063624,0.048374,0.554720,0.822700,0.124302,-0.387848,0.387848,-0.836150,-0.736111,0.415619,0.534230 +MLF55-2908,5001,-0.089372,0.047617,0.035964,0.340799,0.933982,0.107398,-0.175395,0.175395,-0.968748,-0.923630,0.311312,0.223590 +MLF56-2908,5001,-0.099481,0.028884,0.022275,0.332558,0.938980,0.087874,-0.141956,0.141956,-0.979641,-0.932338,0.313314,0.180502 +MLF61-2908,5001,-0.028458,0.076933,0.070371,0.761381,0.627656,-0.162314,-0.610989,0.610989,-0.503374,-0.216774,0.482432,0.848687 +MLF62-2908,5001,-0.047469,0.067259,0.069356,0.719648,0.693869,-0.025544,-0.575577,0.575577,-0.580880,-0.388352,0.432732,0.813588 +MLF63-2908,5001,-0.064553,0.054999,0.064702,0.609708,0.781552,0.132032,-0.520299,0.520299,-0.677184,-0.597951,0.344188,0.723871 +MLF64-2908,5001,-0.079979,0.043008,0.055827,0.551510,0.816324,0.171615,-0.477761,0.477761,-0.737218,-0.683799,0.324592,0.653497 +MLF65-2908,5001,-0.092819,0.028530,0.044594,0.295052,0.944563,0.144031,-0.211591,0.211591,-0.954179,-0.931758,0.251057,0.262292 +MLF66-2908,5001,-0.100203,0.011587,0.034519,0.257662,0.960388,0.106137,-0.147704,0.147704,-0.977940,-0.954879,0.236302,0.179911 +MLF67-2908,5001,-0.102216,-0.006903,0.020993,-0.130232,0.979777,0.151911,-0.134362,0.134362,-0.981781,-0.982337,-0.148270,0.114147 +MLO11-2908,5001,-0.024392,-0.119634,0.012453,0.894208,-0.257912,0.365887,-0.289701,0.289701,0.912221,-0.341270,-0.921713,0.184336 +MLO12-2908,5001,-0.045449,-0.111755,0.011273,0.863413,-0.280733,0.419173,-0.325294,0.325294,0.887900,-0.385617,-0.902980,0.189543 +MLO13-2908,5001,-0.064929,-0.100633,0.010431,0.624551,-0.348592,0.698871,-0.503862,0.503862,0.701603,-0.596707,-0.790321,0.139045 +MLO14-2908,5001,-0.081135,-0.084405,0.009359,-0.503581,0.738460,0.448424,-0.321549,0.321549,-0.890625,-0.801881,-0.592692,0.075525 +MLO21-2908,5001,-0.013696,-0.125487,-0.005972,0.948823,-0.273794,0.157388,-0.126649,0.126649,0.983829,-0.289300,-0.953413,0.085492 +MLO22-2908,5001,-0.035130,-0.119321,-0.006366,0.936246,-0.291128,0.196690,-0.156290,0.156290,0.975268,-0.314668,-0.943832,0.100825 +MLO23-2908,5001,-0.055906,-0.109384,-0.007892,0.837361,-0.514661,0.184256,-0.133819,0.133819,0.981929,-0.530018,-0.846886,0.043183 +MLO24-2908,5001,-0.073622,-0.094978,-0.008874,-0.301297,0.350044,0.886955,-0.627545,0.627545,-0.460842,-0.717919,-0.695454,0.030591 +MLO31-2908,5001,-0.024211,-0.123787,-0.025258,0.978605,-0.198976,0.052348,-0.044366,0.044366,0.998030,-0.200906,-0.979000,0.034589 +MLO32-2908,5001,-0.045569,-0.116320,-0.026256,0.902720,-0.420101,0.092797,-0.069808,0.069808,0.995115,-0.424527,-0.904788,0.033691 +MLO33-2908,5001,-0.064939,-0.103990,-0.027053,0.763161,-0.598448,0.243815,-0.173584,0.173584,0.969400,-0.622458,-0.782131,0.028592 +MLO34-2908,5001,-0.081017,-0.087333,-0.027829,-0.596692,0.774572,0.209753,-0.149505,0.149505,-0.977393,-0.788420,-0.614562,0.026594 +MLO41-2908,5001,-0.013079,-0.126450,-0.043905,0.994436,-0.101069,0.029689,-0.027081,0.027081,0.999266,-0.101799,-0.994511,0.024193 +MLO43-2908,5001,-0.055487,-0.111607,-0.045616,0.852694,-0.517132,0.074081,-0.053923,0.053923,0.997088,-0.519620,-0.854206,0.018095 +MLO44-2908,5001,-0.073184,-0.097132,-0.045996,0.017242,0.016832,0.999710,-0.707107,0.707107,0.000290,-0.706897,-0.706906,0.024094 +MLO51-2908,5001,-0.023718,-0.125233,-0.063684,0.979133,-0.200080,0.035593,-0.030156,0.030156,0.999090,-0.200971,-0.979315,0.023493 +MLO52-2908,5001,-0.045502,-0.117991,-0.064595,0.901478,-0.426591,0.073194,-0.054946,0.054946,0.996976,-0.429323,-0.902774,0.026093 +MLO53-2908,5001,-0.064853,-0.105377,-0.064596,0.786142,-0.615930,0.051104,-0.036401,0.036401,0.998674,-0.616973,-0.786960,0.006196 +MLP11-2908,5001,-0.018929,-0.073308,0.084049,0.746148,0.462908,0.478518,-0.652278,0.652278,0.386090,-0.133402,-0.600207,0.788641 +MLP12-2908,5001,-0.049664,-0.053413,0.085509,0.573265,0.617195,0.538923,-0.705935,0.705935,-0.057544,-0.415961,-0.347457,0.840387 +MLP21-2908,5001,-0.011677,-0.089204,0.070955,0.815148,0.330996,0.475369,-0.573795,0.573795,0.584396,-0.079332,-0.749134,0.657651 +MLP22-2908,5001,-0.040547,-0.071975,0.079113,0.670854,0.431023,0.603469,-0.680738,0.680738,0.270540,-0.294195,-0.592297,0.750089 +MLP23-2908,5001,-0.067529,-0.044764,0.076966,0.403520,0.703163,0.585435,-0.664900,0.664900,-0.340316,-0.628553,-0.251932,0.735834 +MLP31-2908,5001,-0.021235,-0.100425,0.054812,0.834719,0.168106,0.524389,-0.525879,0.525879,0.668507,-0.163385,-0.833781,0.527365 +MLP32-2908,5001,-0.037154,-0.088352,0.065204,0.738150,0.249125,0.626954,-0.619174,0.619174,0.482957,-0.267877,-0.744688,0.611295 +MLP33-2908,5001,-0.057757,-0.077809,0.065933,0.624852,0.217816,0.749744,-0.660136,0.660136,0.358388,-0.416870,-0.718872,0.556275 +MLP34-2908,5001,-0.073824,-0.060710,0.064262,0.281260,0.722119,0.632010,-0.634160,0.634160,-0.442360,-0.720232,-0.276377,0.636303 +MLP35-2908,5001,-0.082736,-0.041055,0.062032,0.195971,0.800505,0.566380,-0.564398,0.564398,-0.602419,-0.801904,-0.201607,0.562410 +MLP41-2908,5001,-0.042864,-0.100096,0.046816,0.650636,-0.012914,0.759280,-0.601522,0.601522,0.525683,-0.463512,-0.798752,0.383604 +MLP42-2908,5001,-0.060172,-0.088991,0.047264,0.543324,0.120314,0.830857,-0.665307,0.665307,0.338724,-0.512021,-0.736812,0.441523 +MLP43-2908,5001,-0.076698,-0.075775,0.046621,0.324163,0.160597,0.932270,-0.701727,0.701727,0.123118,-0.634427,-0.694109,0.340169 +MLP44-2908,5001,-0.087500,-0.055436,0.046511,-0.033571,0.800187,0.598811,-0.503879,0.503879,-0.701579,-0.863122,-0.325281,0.386281 +MLP45-2908,5001,-0.093245,-0.035021,0.044109,0.007045,0.920117,0.391581,-0.366690,0.366690,-0.855031,-0.930317,-0.137565,0.339981 +MLP51-2908,5001,-0.011560,-0.113945,0.033368,0.890312,0.200860,0.408657,-0.454247,0.454247,0.766367,-0.031698,-0.867937,0.495662 +MLP52-2908,5001,-0.034393,-0.110633,0.029456,0.827846,-0.155430,0.538992,-0.433228,0.433228,0.790333,-0.356348,-0.887781,0.291310 +MLP53-2908,5001,-0.053985,-0.101907,0.029148,0.734426,-0.147622,0.662439,-0.514826,0.514826,0.685499,-0.442236,-0.844489,0.302102 +MLP54-2908,5001,-0.072027,-0.088976,0.028737,0.231537,0.128805,0.964261,-0.705109,0.705109,0.075123,-0.670233,-0.697303,0.254080 +MLP55-2908,5001,-0.085970,-0.072454,0.027045,-0.235531,0.619080,0.749177,-0.550376,0.550376,-0.627832,-0.801007,-0.560202,0.211096 +MLP56-2908,5001,-0.095507,-0.050760,0.026954,-0.096858,0.941416,0.323038,-0.284781,0.284781,-0.915314,-0.953687,-0.180651,0.240514 +MLP57-2908,5001,-0.099463,-0.029585,0.024461,-0.075580,0.966400,0.245679,-0.223674,0.223674,-0.948652,-0.971729,-0.126651,0.199253 +MLT11-2908,5001,-0.093765,0.051373,-0.006429,0.363348,0.931508,0.016463,-0.028951,0.028951,-0.999161,-0.931203,0.362567,0.037488 +MLT12-2908,5001,-0.100429,0.031577,0.000644,0.261402,0.965043,0.018999,-0.026981,0.026981,-0.999272,-0.964853,0.260699,0.033091 +MLT13-2908,5001,-0.103039,0.011239,0.007787,0.023929,0.999262,0.030047,-0.030777,0.030777,-0.999052,-0.999240,0.022981,0.031491 +MLT14-2908,5001,-0.103141,-0.020282,0.004786,-0.075984,0.996410,0.037319,-0.034757,0.034757,-0.998791,-0.996503,-0.077189,0.031992 +MLT15-2908,5001,-0.103844,-0.043082,0.007283,-0.089198,0.993221,0.074533,-0.068534,0.068534,-0.995292,-0.993653,-0.093886,0.061956 +MLT16-2908,5001,-0.093394,-0.065798,0.008142,-0.489703,0.812834,0.315422,-0.229097,0.229097,-0.946060,-0.841252,-0.535551,0.074028 +MLT21-2908,5001,-0.088960,0.065359,-0.022138,0.387532,0.921746,0.014286,-0.026723,0.026723,-0.999286,-0.921469,0.386873,0.034988 +MLT22-2908,5001,-0.099924,0.036102,-0.020733,0.292346,0.956227,0.012816,-0.019297,0.019297,-0.999628,-0.956118,0.291990,0.024094 +MLT23-2908,5001,-0.105322,0.015303,-0.013509,0.066407,0.997584,0.020397,-0.021894,0.021894,-0.999521,-0.997552,0.065929,0.023295 +MLT24-2908,5001,-0.110085,-0.006969,-0.012004,-0.044357,0.998410,0.034786,-0.033322,0.033322,-0.998889,-0.998460,-0.045467,0.031791 +MLT25-2908,5001,-0.111724,-0.034670,-0.012174,-0.120660,0.991887,0.040009,-0.035915,0.035915,-0.998709,-0.992044,-0.121941,0.031290 +MLT26-2908,5001,-0.105860,-0.057569,-0.011126,-0.295524,0.953721,0.055515,-0.044351,0.044351,-0.998031,-0.954305,-0.297405,0.029192 +MLT27-2908,5001,-0.087454,-0.076305,-0.009869,-0.499893,0.858228,0.116411,-0.085092,0.085092,-0.992733,-0.861897,-0.506166,0.030491 +MLT31-2908,5001,-0.086565,0.072712,-0.042128,0.423763,0.905729,0.008919,-0.018499,0.018499,-0.999658,-0.905584,0.423453,0.024594 +MLT32-2908,5001,-0.095247,0.050313,-0.036547,0.351329,0.936200,0.009858,-0.016850,0.016850,-0.999716,-0.936101,0.351063,0.021694 +MLT33-2908,5001,-0.105574,0.020054,-0.034610,0.109708,0.993823,0.016747,-0.018935,0.018935,-0.999641,-0.993784,0.109351,0.020895 +MLT34-2908,5001,-0.111995,-0.002371,-0.033131,-0.028905,0.999166,0.028835,-0.028026,0.028026,-0.999214,-0.999189,-0.029690,0.027192 +MLT35-2908,5001,-0.112341,-0.024551,-0.031570,-0.084516,0.996032,0.027869,-0.025774,0.025774,-0.999335,-0.996089,-0.085178,0.023493 +MLT36-2908,5001,-0.110440,-0.047362,-0.030314,-0.207341,0.977559,0.037255,-0.031411,0.031411,-0.999013,-0.977764,-0.208306,0.024193 +MLT37-2908,5001,-0.097059,-0.069486,-0.028817,-0.407688,0.910963,0.062749,-0.047479,0.047479,-0.997743,-0.911886,-0.409747,0.023895 +MLT41-2908,5001,-0.093559,0.057201,-0.056780,0.372231,0.928085,0.010089,-0.018145,0.018145,-0.999671,-0.927963,0.371925,0.023595 +MLT42-2908,5001,-0.101203,0.034577,-0.050707,0.255740,0.966707,0.008665,-0.012185,0.012185,-0.999852,-0.966669,0.255596,0.014896 +MLT43-2908,5001,-0.111850,0.007951,-0.052633,0.018857,0.999548,0.023408,-0.023855,0.023855,-0.999431,-0.999538,0.018288,0.024294 +MLT44-2908,5001,-0.112593,-0.014470,-0.051328,-0.051924,0.998296,0.026644,-0.025354,0.025354,-0.999357,-0.998329,-0.052567,0.023994 +MLT45-2908,5001,-0.112651,-0.037243,-0.049600,-0.143028,0.989111,0.034682,-0.030605,0.030605,-0.999063,-0.989245,-0.143956,0.025894 +MLT46-2908,5001,-0.106215,-0.060763,-0.047701,-0.311520,0.949129,0.045921,-0.036378,0.036378,-0.998676,-0.949543,-0.312778,0.023195 +MLT47-2908,5001,-0.087363,-0.078825,-0.046652,-0.522407,0.847056,0.097913,-0.071135,0.071135,-0.994927,-0.849724,-0.526722,0.023094 +MLT51-2908,5001,-0.099783,0.041018,-0.071286,0.318903,0.947708,0.012264,-0.019496,0.019496,-0.999620,-0.947587,0.318543,0.024694 +MLT52-2908,5001,-0.108607,0.019280,-0.071673,0.105856,0.994228,0.017446,-0.019630,0.019630,-0.999615,-0.994188,0.105472,0.021595 +MLT53-2908,5001,-0.114107,-0.004067,-0.070696,-0.030863,0.999242,0.023728,-0.023023,0.023023,-0.999470,-0.999258,-0.031392,0.022295 +MLT54-2908,5001,-0.113958,-0.027438,-0.069073,-0.097438,0.994830,0.028615,-0.026180,0.026180,-0.999314,-0.994897,-0.098120,0.023493 +MLT55-2908,5001,-0.110860,-0.050957,-0.066985,-0.226717,0.972918,0.045067,-0.037514,0.037514,-0.998592,-0.973238,-0.228088,0.027993 +MLT56-2908,5001,-0.095797,-0.071214,-0.065621,-0.462709,0.879551,-0.110864,0.082037,-0.082037,-0.993247,-0.882706,-0.468679,-0.034197 +MLT57-2908,5001,-0.081002,-0.089156,-0.064514,-0.608506,0.760015,0.228249,-0.162331,0.162331,-0.973292,-0.776768,-0.629306,0.024594 +MRC11-2908,5001,0.010341,0.066393,0.077892,-0.742366,0.621248,-0.250887,-0.669191,-0.669191,0.323060,0.032809,0.407720,0.912517 +MRC12-2908,5001,0.028437,0.054951,0.080455,-0.729998,0.676716,-0.095700,-0.657954,-0.657954,0.366322,0.184930,0.330380,0.925554 +MRC13-2908,5001,0.048202,0.046792,0.077412,-0.688917,0.723477,0.044440,-0.619605,-0.619605,0.481850,0.376143,0.304419,0.875126 +MRC14-2908,5001,0.067189,0.034233,0.071486,-0.602577,0.781493,0.161770,-0.557001,-0.557001,0.616036,0.571534,0.281103,0.770928 +MRC15-2908,5001,0.081766,0.020674,0.063810,-0.537650,0.809339,0.236437,-0.548786,-0.548786,0.630609,0.640130,0.209293,0.739209 +MRC16-2908,5001,0.092193,0.004191,0.054676,-0.379259,0.896191,0.230224,-0.376848,-0.376848,0.846151,0.845073,0.234151,0.480651 +MRC17-2908,5001,0.096832,-0.014320,0.040723,-0.007637,0.953382,0.301670,-0.290761,-0.290761,0.911546,0.956765,-0.080752,0.279427 +MRC21-2908,5001,0.031324,0.034254,0.086630,-0.717752,0.694875,-0.044507,-0.664569,-0.664569,0.341607,0.207796,0.274767,0.938789 +MRC22-2908,5001,0.050816,0.025968,0.082959,-0.676836,0.731961,0.078267,-0.632954,-0.632954,0.445800,0.375847,0.252194,0.891704 +MRC23-2908,5001,0.067334,0.013190,0.077412,-0.569053,0.786991,0.238377,-0.593823,-0.593823,0.542908,0.568817,0.167389,0.805250 +MRC24-2908,5001,0.079323,-0.002978,0.071889,-0.517446,0.821227,0.240491,-0.527368,-0.527368,0.666158,0.673894,0.217874,0.705973 +MRC25-2908,5001,0.087806,-0.020786,0.059661,-0.164636,0.873689,0.457779,-0.476781,-0.476781,0.738485,0.863467,-0.096679,0.495054 +MRC31-2908,5001,0.060073,-0.005917,0.084980,-0.584060,0.767833,0.263261,-0.634070,-0.634070,0.442619,0.506783,0.091590,0.857194 +MRC32-2908,5001,0.074618,-0.025370,0.076396,-0.284287,0.756316,0.589209,-0.615248,-0.615248,0.492889,0.735289,-0.222388,0.640229 +MRC41-2908,5001,0.042975,0.007147,0.090296,-0.685764,0.724010,0.074419,-0.664585,-0.664585,0.341545,0.296740,0.184761,0.936915 +MRC42-2908,5001,0.055779,-0.026876,0.088250,-0.563809,0.741895,0.362921,-0.668035,-0.668035,0.327807,0.485642,-0.057623,0.872256 +MRC51-2908,5001,0.010425,0.031116,0.090196,-0.724089,0.672761,-0.151945,-0.687758,-0.687758,0.232329,0.051800,0.272729,0.960695 +MRC52-2908,5001,0.022299,0.013124,0.093501,-0.715646,0.696292,-0.055038,-0.686211,-0.686211,0.241304,0.130250,0.210456,0.968888 +MRC53-2908,5001,0.039471,-0.013776,0.094389,-0.675743,0.724276,0.137101,-0.685944,-0.685944,0.242823,0.269914,0.070042,0.960334 +MRC54-2908,5001,0.037598,-0.037086,0.094298,-0.656835,0.694918,0.292671,-0.704133,-0.704133,0.091623,0.269749,-0.145898,0.951814 +MRC55-2908,5001,0.027395,-0.055851,0.091853,-0.687233,0.603833,0.403852,-0.699686,-0.699686,-0.144492,0.195321,-0.381869,0.903341 +MRC61-2908,5001,0.010853,-0.004882,0.098207,-0.711656,0.700467,-0.053779,-0.699576,-0.699576,0.145553,0.064333,0.141206,0.987888 +MRC62-2908,5001,0.020770,-0.024184,0.098723,-0.696161,0.710738,0.101051,-0.703457,-0.703457,0.101472,0.143205,-0.000444,0.989693 +MRC63-2908,5001,0.010206,-0.043833,0.097924,-0.706192,0.677004,0.207262,-0.703627,-0.703627,-0.099089,0.078751,-0.215811,0.973254 +MRF11-2908,5001,0.022361,0.122623,-0.011720,-0.011000,-0.049774,0.998700,0.976440,-0.215787,-0.000000,0.215506,0.975171,0.050975 +MRF12-2908,5001,0.043653,0.115192,-0.014223,-0.020099,-0.041021,0.998956,0.897998,-0.440000,0.000000,0.439541,0.897060,0.045680 +MRF13-2908,5001,0.062590,0.103666,-0.019576,-0.023721,-0.029285,0.999290,0.777070,-0.629414,-0.000000,0.628967,0.776518,0.037687 +MRF14-2908,5001,0.076701,0.088802,-0.029145,-0.562601,0.826701,0.006827,-0.025832,-0.025832,0.999332,0.826325,0.562049,0.035888 +MRF21-2908,5001,0.010810,0.123556,0.008226,-0.021054,-0.127307,0.991640,0.986599,-0.163166,0.000000,0.161802,0.978351,0.129036 +MRF22-2908,5001,0.031990,0.118700,0.007460,-0.036818,-0.104682,0.993824,0.943354,-0.331787,0.000000,0.329738,0.937528,0.110968 +MRF23-2908,5001,0.051309,0.110756,0.005283,-0.039952,-0.088111,0.995309,0.910751,-0.412957,0.000000,0.411019,0.906478,0.096746 +MRF24-2908,5001,0.069428,0.096874,0.000101,-0.618428,0.785822,0.005511,-0.032886,-0.032886,0.998918,0.785153,0.617577,0.046181 +MRF25-2908,5001,0.080844,0.080975,-0.008995,-0.483733,0.875159,0.009970,-0.025454,-0.025454,0.999352,0.874845,0.483166,0.034589 +MRF31-2908,5001,0.021504,0.116122,0.026968,-0.078272,-0.325913,0.942154,0.972352,-0.233522,-0.000000,0.220013,0.916105,0.335180 +MRF32-2908,5001,0.042166,0.110153,0.025103,-0.092084,-0.229416,0.968963,0.928033,-0.372497,0.000000,0.360936,0.899230,0.247207 +MRF33-2908,5001,0.062165,0.098843,0.021837,-0.683885,0.729525,0.009710,-0.203735,-0.203735,0.957593,0.700567,0.652905,0.287961 +MRF34-2908,5001,0.076819,0.084160,0.015721,-0.533551,0.845322,0.027457,-0.087392,-0.087392,0.992333,0.841241,0.527061,0.120502 +MRF35-2908,5001,0.086639,0.067054,0.006727,-0.389072,0.920912,0.023335,-0.043791,-0.043791,0.998081,0.920166,0.387303,0.057365 +MRF41-2908,5001,0.010516,0.108015,0.044551,-0.881617,0.321469,-0.345555,-0.464856,-0.464856,0.753536,0.081605,0.824964,0.559262 +MRF42-2908,5001,0.031630,0.105015,0.043922,-0.108995,-0.446170,0.888286,0.971433,-0.237313,-0.000000,0.210802,0.862911,0.459290 +MRF43-2908,5001,0.052730,0.095988,0.041538,-0.739909,0.672000,-0.030815,-0.381899,-0.381899,0.841609,0.553793,0.634483,0.539207 +MRF44-2908,5001,0.069194,0.082857,0.037181,-0.670526,0.741384,0.027306,-0.338374,-0.338374,0.878069,0.660226,0.579529,0.477754 +MRF45-2908,5001,0.083560,0.067507,0.027899,-0.383573,0.922004,0.052733,-0.097012,-0.097012,0.990544,0.918401,0.374830,0.126656 +MRF46-2908,5001,0.093603,0.047987,0.015130,-0.377266,0.925324,0.038038,-0.069073,-0.069073,0.995217,0.923526,0.372834,0.089974 +MRF51-2908,5001,0.018120,0.095576,0.060442,0.833956,0.410568,-0.368715,-0.548941,0.548941,-0.630339,-0.056395,0.728078,0.683171 +MRF52-2908,5001,0.040493,0.088920,0.058271,-0.748925,0.658920,-0.070257,-0.524059,-0.524059,0.671360,0.405554,0.539617,0.737794 +MRF53-2908,5001,0.058638,0.077332,0.054447,-0.707805,0.706407,-0.000778,-0.437104,-0.437104,0.786054,0.554934,0.556713,0.618157 +MRF54-2908,5001,0.074815,0.063707,0.048689,-0.550972,0.824352,0.129897,-0.394383,-0.394383,0.830014,0.735453,0.406086,0.542405 +MRF55-2908,5001,0.089444,0.047855,0.036387,-0.341363,0.933137,0.112813,-0.184064,-0.184064,0.965526,0.921733,0.308830,0.234589 +MRF56-2908,5001,0.099400,0.028933,0.022453,-0.315579,0.944364,0.092669,-0.144277,-0.144277,0.978963,0.937867,0.295570,0.181781 +MRF61-2908,5001,0.027803,0.077019,0.070606,-0.765303,0.617204,-0.182675,-0.613453,-0.613453,0.497343,0.194899,0.492681,0.848104 +MRF62-2908,5001,0.046761,0.067348,0.069747,-0.721502,0.691781,-0.029577,-0.576412,-0.576412,0.579222,0.383646,0.434958,0.814633 +MRF63-2908,5001,0.063922,0.054927,0.065149,-0.606574,0.783023,0.137637,-0.523892,-0.523892,0.671621,0.598002,0.335281,0.727998 +MRF64-2908,5001,0.079581,0.043128,0.056455,-0.548354,0.818040,0.173549,-0.475934,-0.475934,0.739577,0.687601,0.322952,0.650313 +MRF65-2908,5001,0.092899,0.028728,0.044949,-0.294748,0.943213,0.153208,-0.224085,-0.224085,0.948458,0.928929,0.245224,0.277409 +MRF66-2908,5001,0.100015,0.011759,0.034785,-0.243516,0.962823,0.116928,-0.158425,-0.158425,0.974578,0.956871,0.218801,0.191114 +MRF67-2908,5001,0.102501,-0.007097,0.021248,0.144927,0.971961,0.185173,-0.161416,-0.161416,0.973596,0.976187,-0.170990,0.133497 +MRO11-2908,5001,0.022607,-0.120268,0.012565,-0.895543,-0.259016,0.361820,-0.286507,-0.286507,-0.914236,0.340466,-0.922402,0.182369 +MRO12-2908,5001,0.044087,-0.112525,0.011531,-0.847096,-0.272360,0.456343,-0.353163,-0.353163,-0.866344,0.397121,-0.895040,0.202975 +MRO13-2908,5001,0.064069,-0.101476,0.010509,-0.597313,-0.326839,0.732389,-0.527617,-0.527617,-0.665764,0.604018,-0.784090,0.142707 +MRO14-2908,5001,0.080754,-0.085332,0.009572,0.478414,0.708160,0.519259,-0.372115,-0.372115,0.850330,0.795393,-0.600034,0.085492 +MRO21-2908,5001,0.012195,-0.125758,-0.006073,-0.945716,-0.280414,0.164286,-0.131645,-0.131645,-0.982517,0.297138,-0.950809,0.087583 +MRO22-2908,5001,0.033645,-0.120049,-0.006316,-0.934204,-0.301335,0.190944,-0.150980,-0.150980,-0.976939,0.323214,-0.941490,0.095550 +MRO23-2908,5001,0.054877,-0.110310,-0.007867,-0.834518,-0.514660,0.196736,-0.142814,-0.142814,-0.979392,0.532150,-0.845417,0.045680 +MRO24-2908,5001,0.073000,-0.095932,-0.008849,0.246224,0.304249,0.920221,-0.651243,-0.651243,0.389571,0.717814,-0.695209,0.037788 +MRO31-2908,5001,0.022453,-0.124210,-0.025280,-0.979236,-0.193995,0.058845,-0.050030,-0.050030,-0.997494,0.196453,-0.979726,0.039286 +MRO32-2908,5001,0.044274,-0.117175,-0.026238,-0.903146,-0.415980,0.106247,-0.080026,-0.080026,-0.993575,0.421810,-0.905846,0.038986 +MRO33-2908,5001,0.063990,-0.104937,-0.027048,-0.758885,-0.585131,0.285859,-0.203676,-0.203676,-0.957618,0.618554,-0.784945,0.035390 +MRO34-2908,5001,0.080499,-0.088481,-0.027855,0.591592,0.765307,0.253623,-0.180707,-0.180707,0.966794,0.785725,-0.617779,0.031392 +MRO41-2908,5001,0.011204,-0.126496,-0.043971,-0.994430,-0.099958,0.033425,-0.030514,-0.030514,-0.999068,0.100885,-0.994524,0.027294 +MRO42-2908,5001,0.033464,-0.122141,-0.045027,-0.949334,-0.310966,0.045456,-0.036021,-0.036021,-0.998702,0.312199,-0.949738,0.022994 +MRO43-2908,5001,0.054273,-0.112590,-0.045630,-0.848144,-0.517719,0.112334,-0.081693,-0.081693,-0.993304,0.523429,-0.851641,0.026993 +MRO44-2908,5001,0.072639,-0.098178,-0.046082,-0.178822,-0.139207,0.973984,-0.688981,-0.688981,-0.224969,0.702373,-0.711285,0.027294 +MRO51-2908,5001,0.021952,-0.125580,-0.063751,-0.979790,-0.196411,0.037865,-0.032159,-0.032159,-0.998965,0.197425,-0.979994,0.025193 +MRO52-2908,5001,0.044042,-0.118577,-0.064627,-0.908337,-0.412038,0.071756,-0.054186,-0.054186,-0.997060,0.414715,-0.909554,0.026892 +MRO53-2908,5001,0.063891,-0.106597,-0.064649,-0.778671,-0.595348,0.198071,-0.141249,-0.141249,-0.979846,0.611326,-0.790955,0.025894 +MRP11-2908,5001,0.017422,-0.073486,0.084082,-0.746219,0.469557,0.471882,-0.653198,-0.653198,-0.382967,0.128408,-0.594010,0.794143 +MRP12-2908,5001,0.048656,-0.053841,0.086068,-0.577640,0.616877,0.534597,-0.706156,-0.706156,0.051828,0.409481,-0.347571,0.843516 +MRP21-2908,5001,0.010095,-0.089358,0.070886,-0.816009,0.335174,0.470944,-0.573309,-0.573309,-0.585349,0.073803,-0.747646,0.659983 +MRP22-2908,5001,0.039207,-0.072332,0.079364,-0.669783,0.433347,0.602993,-0.681401,-0.681401,-0.267180,0.295099,-0.589833,0.751674 +MRP23-2908,5001,0.066684,-0.045145,0.077672,-0.408763,0.700623,0.584842,-0.666809,-0.666809,0.332764,0.623120,-0.253956,0.739749 +MRP31-2908,5001,0.019833,-0.100601,0.054941,-0.835828,0.172178,0.521293,-0.525534,-0.525534,-0.669050,0.158762,-0.833168,0.529742 +MRP32-2908,5001,0.035748,-0.088759,0.065341,-0.748307,0.247528,0.615440,-0.612898,-0.612898,-0.498711,0.253757,-0.750390,0.610346 +MRP33-2908,5001,0.056560,-0.078393,0.066318,-0.656115,0.198466,0.728096,-0.646160,-0.646160,-0.406147,0.389860,-0.736946,0.552196 +MRP34-2908,5001,0.073180,-0.061231,0.064854,-0.289844,0.708016,0.643975,-0.642603,-0.642603,0.417281,0.709262,-0.292874,0.641227 +MRP35-2908,5001,0.082295,-0.041609,0.062619,-0.195696,0.793916,0.575674,-0.569816,-0.569816,0.592132,0.798131,-0.212150,0.563897 +MRP41-2908,5001,0.041437,-0.100806,0.047203,-0.620049,0.003917,0.784553,-0.618187,-0.618187,-0.485480,0.483099,-0.786022,0.385727 +MRP42-2908,5001,0.059202,-0.089614,0.047509,-0.550410,0.122657,0.825836,-0.663974,-0.663974,-0.343914,0.506150,-0.737627,0.446899 +MRP43-2908,5001,0.075677,-0.076720,0.046772,-0.365466,0.119340,0.923143,-0.694866,-0.694866,-0.185264,0.619351,-0.709168,0.336875 +MRP44-2908,5001,0.087006,-0.056097,0.046854,0.008540,0.796493,0.604587,-0.514821,-0.514821,0.685506,0.857255,-0.317108,0.405655 +MRP45-2908,5001,0.093290,-0.035314,0.044604,-0.008890,0.917193,0.398344,-0.372696,-0.372696,0.849821,0.927911,-0.140907,0.345147 +MRP51-2908,5001,0.009879,-0.114009,0.033446,-0.896217,0.186444,0.402534,-0.442413,-0.442413,-0.780091,0.032643,-0.877217,0.478983 +MRP52-2908,5001,0.032924,-0.111348,0.029738,-0.814395,-0.153528,0.559633,-0.447599,-0.447599,-0.774152,0.369345,-0.880957,0.295803 +MRP53-2908,5001,0.052868,-0.102617,0.029524,-0.723935,-0.134835,0.676564,-0.526232,-0.526232,-0.667952,0.446093,-0.839583,0.310003 +MRP54-2908,5001,0.071251,-0.089837,0.029151,-0.236210,0.136945,0.962004,-0.705232,-0.705232,-0.072769,0.668470,-0.695625,0.263161 +MRP55-2908,5001,0.085892,-0.073215,0.027542,0.239289,0.581367,0.777659,-0.566716,-0.566716,0.598051,0.788399,-0.583819,0.193861 +MRP56-2908,5001,0.095389,-0.051200,0.027299,0.095188,0.938628,0.331536,-0.292059,-0.292059,0.910716,0.951652,-0.183518,0.246334 +MRP57-2908,5001,0.099481,-0.029930,0.024778,0.069259,0.965865,0.249615,-0.228238,-0.228238,0.946475,0.971139,-0.122523,0.204640 +MRT11-2908,5001,0.093697,0.051201,-0.006247,-0.364016,0.931167,0.020511,-0.036117,-0.036117,0.998695,0.930692,0.362800,0.046779 +MRT12-2908,5001,0.100341,0.031678,0.000662,-0.253479,0.967053,0.023578,-0.033006,-0.033006,0.998910,0.966777,0.252425,0.040285 +MRT13-2908,5001,0.103049,0.011162,0.007893,-0.030770,0.998869,0.036238,-0.037379,-0.037379,0.998602,0.998827,0.029372,0.038487 +MRT14-2908,5001,0.103725,-0.020577,0.004847,0.079355,0.995798,0.045703,-0.042432,-0.042432,0.998198,0.995943,-0.081152,0.038887 +MRT15-2908,5001,0.104014,-0.043358,0.007366,0.099350,0.991464,0.084432,-0.076943,-0.076943,0.994062,0.992073,-0.105257,0.068642 +MRT16-2908,5001,0.093216,-0.066758,0.008309,0.458501,0.757679,0.464434,-0.336009,-0.336009,0.879884,0.822724,-0.559482,0.100527 +MRT21-2908,5001,0.088878,0.065547,-0.022055,-0.380528,0.924580,0.018732,-0.034389,-0.034389,0.998817,0.924130,0.379433,0.044882 +MRT22-2908,5001,0.099853,0.036241,-0.020650,-0.290848,0.956613,0.017299,-0.025966,-0.025966,0.999326,0.956417,0.290202,0.032391 +MRT23-2908,5001,0.105787,0.015303,-0.013390,-0.062257,0.997606,0.030116,-0.032165,-0.032165,0.998965,0.997542,0.061224,0.034090 +MRT24-2908,5001,0.110722,-0.007219,-0.011816,0.020793,0.997560,0.066646,-0.065167,-0.065167,0.995744,0.997658,-0.025048,0.063653 +MRT25-2908,5001,0.112124,-0.035159,-0.012214,0.121645,0.991465,0.046905,-0.042064,-0.042064,0.998229,0.991682,-0.123403,0.036588 +MRT26-2908,5001,0.105603,-0.058254,-0.011087,0.297389,0.952487,0.065795,-0.052496,-0.052496,0.997240,0.953312,-0.300022,0.034390 +MRT27-2908,5001,0.087372,-0.077299,-0.009832,0.503624,0.852330,0.141055,-0.102919,-0.102919,0.989351,0.857771,-0.512778,0.035888 +MRT31-2908,5001,0.086131,0.072818,-0.042249,-0.420944,0.907001,0.012449,-0.025595,-0.025595,0.999345,0.906725,0.420349,0.033989 +MRT32-2908,5001,0.095241,0.050368,-0.036549,-0.353879,0.935155,0.015971,-0.027454,-0.027454,0.999246,0.934888,0.353173,0.035390 +MRT33-2908,5001,0.106180,0.020182,-0.034620,-0.112777,0.993277,0.026127,-0.029646,-0.029646,0.999121,0.993178,0.111903,0.032791 +MRT34-2908,5001,0.112405,-0.002565,-0.033062,0.037516,0.998673,0.035284,-0.034012,-0.034012,0.998842,0.998717,-0.038672,0.032691 +MRT35-2908,5001,0.112913,-0.024799,-0.031565,0.091382,0.995076,0.038388,-0.035289,-0.035289,0.998754,0.995190,-0.092622,0.031890 +MRT36-2908,5001,0.110678,-0.048020,-0.030294,0.212996,0.975784,0.049787,-0.041808,-0.041808,0.998251,0.976158,-0.214704,0.031890 +MRT37-2908,5001,0.096428,-0.069912,-0.028737,0.409758,0.907816,0.089265,-0.067441,-0.067441,0.995441,0.909698,-0.413910,0.033590 +MRT41-2908,5001,0.093298,0.056969,-0.056958,-0.369983,0.928913,0.015240,-0.027246,-0.027246,0.999257,0.928639,0.369293,0.035390 +MRT42-2908,5001,0.101242,0.034631,-0.050590,-0.263692,0.964431,0.018437,-0.026292,-0.026292,0.999308,0.964248,0.263025,0.032290 +MRT43-2908,5001,0.112325,0.007765,-0.052528,-0.010154,0.999477,0.030690,-0.030992,-0.030992,0.999039,0.999468,0.009193,0.031290 +MRT44-2908,5001,0.113131,-0.014783,-0.051290,0.059794,0.997625,0.034191,-0.032301,-0.032301,0.998956,0.997688,-0.060836,0.030293 +MRT45-2908,5001,0.113167,-0.037757,-0.049622,0.149461,0.987848,0.042644,-0.037443,-0.037443,0.998597,0.988058,-0.150848,0.031392 +MRT46-2908,5001,0.106019,-0.061469,-0.047705,0.315995,0.946626,0.063612,-0.050254,-0.050254,0.997471,0.947429,-0.318392,0.031692 +MRT47-2908,5001,0.087186,-0.079839,-0.046796,0.521903,0.841731,0.138224,-0.100338,-0.100338,0.989881,0.847083,-0.530491,0.032091 +MRT51-2908,5001,0.099809,0.041060,-0.071310,-0.316565,0.948425,0.016640,-0.026316,-0.026316,0.999307,0.948206,0.315908,0.033289 +MRT52-2908,5001,0.108994,0.019259,-0.071481,-0.098627,0.994743,0.027556,-0.030721,-0.030721,0.999056,0.994650,0.097688,0.033590 +MRT53-2908,5001,0.113497,-0.004365,-0.070764,0.021483,0.999347,0.029037,-0.028422,-0.028422,0.999192,0.999365,-0.022291,0.027793 +MRT54-2908,5001,0.114235,-0.027734,-0.069083,0.103700,0.993901,0.037517,-0.034141,-0.034141,0.998834,0.994022,-0.104860,0.030392 +MRT55-2908,5001,0.111026,-0.051512,-0.067041,0.233722,0.970970,0.050895,-0.042172,-0.042172,0.998220,0.971388,-0.235452,0.031092 +MRT56-2908,5001,0.096106,-0.072424,-0.065510,0.432569,0.898347,0.076525,-0.057309,-0.057309,0.996710,0.899778,-0.435531,0.026693 +MRT57-2908,5001,0.080410,-0.090250,-0.064917,0.607188,0.761019,0.228413,-0.162477,-0.162477,0.973243,0.777769,-0.628053,0.024994 +MZC01-2908,5001,-0.000477,0.048986,0.084673,-0.726654,0.649979,-0.222489,-0.687002,-0.687002,0.236760,0.001039,0.324893,0.945750 +MZC02-2908,5001,-0.000568,0.013081,0.095006,-0.715416,0.682435,-0.149871,-0.698698,-0.698698,0.153757,0.000214,0.214715,0.976677 +MZC03-2908,5001,-0.000718,-0.024636,0.100094,0.707113,0.707099,-0.001801,-0.707096,0.707096,-0.005513,-0.002625,0.005172,0.999983 +MZC04-2908,5001,-0.000702,-0.063363,0.091725,0.749012,0.582048,0.316546,-0.662526,0.662526,0.349454,-0.006321,-0.471465,0.881862 +MZF01-2908,5001,-0.000162,0.125714,-0.010739,-0.000094,-0.031391,0.999507,0.999996,-0.002998,0.000000,0.002997,0.999503,0.031392 +MZF02-2908,5001,-0.000213,0.119780,0.027775,0.000038,-0.371102,0.928592,1.000000,0.000101,0.000000,-0.000094,0.928592,0.371102 +MZF03-2908,5001,-0.000373,0.086053,0.067277,-0.774794,0.517412,-0.363290,-0.632211,-0.632211,0.447905,0.002076,0.576710,0.816947 +MZO01-2908,5001,-0.000809,-0.121116,0.015960,-0.942870,0.113995,0.313051,-0.333140,-0.333140,-0.882064,0.003739,-0.935961,0.352083 +MZO02-2908,5001,-0.000849,-0.126414,-0.025369,0.999404,0.000385,0.034504,-0.034497,0.034497,0.998809,-0.000806,-0.999405,0.034490 +MZO03-2908,5001,-0.000964,-0.127646,-0.062156,0.999676,-0.004178,0.025119,-0.025007,0.025007,0.999374,-0.004803,-0.999679,0.024895 +MZP01-2908,5001,-0.000712,-0.105876,0.049989,0.886931,0.235489,0.397365,-0.461873,0.461873,0.757197,-0.005221,-0.855113,0.518415 diff --git a/mne-python/source/mne/channels/data/canonical_meg/neuromag306.csv b/mne-python/source/mne/channels/data/canonical_meg/neuromag306.csv new file mode 100644 index 0000000000000000000000000000000000000000..d1773929e341f6f27210663d4cef31d26501046d --- /dev/null +++ b/mne-python/source/mne/channels/data/canonical_meg/neuromag306.csv @@ -0,0 +1,307 @@ +name,coil_type,x,y,z,ex_x,ex_y,ex_z,ey_x,ey_y,ey_z,ez_x,ez_y,ez_z +MEG 0113,3012,-0.106600,0.046400,-0.060400,-0.012700,0.005700,-0.999903,-0.186801,-0.982403,-0.003300,-0.982327,0.186741,0.013541 +MEG 0112,3012,-0.106600,0.046400,-0.060400,-0.186801,-0.982403,-0.003300,0.012700,-0.005700,0.999903,-0.982327,0.186741,0.013541 +MEG 0111,3024,-0.106600,0.046400,-0.060400,-0.012700,0.005700,-0.999903,-0.186801,-0.982403,-0.003300,-0.982327,0.186741,0.013541 +MEG 0122,3012,-0.102000,0.063100,-0.025600,0.013600,0.001100,-0.999902,-0.282001,-0.959402,-0.004900,-0.959313,0.282039,-0.012738 +MEG 0123,3012,-0.102000,0.063100,-0.025600,-0.282001,-0.959402,-0.004900,-0.013600,-0.001100,0.999902,-0.959313,0.282039,-0.012738 +MEG 0121,3024,-0.102000,0.063100,-0.025600,0.013600,0.001100,-0.999902,-0.282001,-0.959402,-0.004900,-0.959313,0.282039,-0.012738 +MEG 0132,3012,-0.108500,0.030200,-0.026600,0.002600,0.002300,-0.999955,-0.095196,-0.995456,-0.002500,-0.995417,0.095198,-0.002369 +MEG 0133,3012,-0.108500,0.030200,-0.026600,-0.095196,-0.995456,-0.002500,-0.002600,-0.002300,0.999955,-0.995417,0.095198,-0.002369 +MEG 0131,3024,-0.108500,0.030200,-0.026600,0.002600,0.002300,-0.999955,-0.095196,-0.995456,-0.002500,-0.995417,0.095198,-0.002369 +MEG 0143,3012,-0.109900,0.013100,-0.062700,-0.012300,0.001800,-0.999923,-0.021200,-0.999823,-0.001600,-0.999748,0.021179,0.012336 +MEG 0142,3012,-0.109900,0.013100,-0.062700,-0.021200,-0.999823,-0.001600,0.012300,-0.001800,0.999923,-0.999748,0.021179,0.012336 +MEG 0141,3024,-0.109900,0.013100,-0.062700,-0.012300,0.001800,-0.999923,-0.021200,-0.999823,-0.001600,-0.999748,0.021179,0.012336 +MEG 0213,3012,-0.107400,0.032900,0.008000,-0.051198,0.007700,-0.998659,-0.101496,-0.994759,-0.002500,-0.993444,0.101232,0.051711 +MEG 0212,3012,-0.107400,0.032900,0.008000,-0.101496,-0.994759,-0.002500,0.051198,-0.007700,0.998659,-0.993444,0.101232,0.051711 +MEG 0211,3024,-0.107400,0.032900,0.008000,-0.051198,0.007700,-0.998659,-0.101496,-0.994759,-0.002500,-0.993444,0.101232,0.051711 +MEG 0222,3012,-0.098900,0.040300,0.041300,-0.343206,0.059801,-0.937415,-0.161803,-0.986816,-0.003700,-0.925278,0.150406,0.348357 +MEG 0223,3012,-0.098900,0.040300,0.041300,-0.161803,-0.986816,-0.003700,0.343206,-0.059801,0.937415,-0.925278,0.150406,0.348357 +MEG 0221,3024,-0.098900,0.040300,0.041300,-0.343206,0.059801,-0.937415,-0.161803,-0.986816,-0.003700,-0.925278,0.150406,0.348357 +MEG 0232,3012,-0.101100,0.004400,0.040800,-0.352103,0.008700,-0.935908,0.037800,-0.999009,-0.023500,-0.935185,-0.043652,0.351425 +MEG 0233,3012,-0.101100,0.004400,0.040800,0.037800,-0.999009,-0.023500,0.352103,-0.008700,0.935908,-0.935185,-0.043652,0.351425 +MEG 0231,3024,-0.101100,0.004400,0.040800,-0.352103,0.008700,-0.935908,0.037800,-0.999009,-0.023500,-0.935185,-0.043652,0.351425 +MEG 0243,3012,-0.108300,-0.001100,0.007100,-0.067199,-0.010400,-0.997685,0.084999,-0.996386,0.004700,-0.994128,-0.084486,0.067840 +MEG 0242,3012,-0.108300,-0.001100,0.007100,0.084999,-0.996386,0.004700,0.067199,0.010400,0.997685,-0.994128,-0.084486,0.067840 +MEG 0241,3024,-0.108300,-0.001100,0.007100,-0.067199,-0.010400,-0.997685,0.084999,-0.996386,0.004700,-0.994128,-0.084486,0.067840 +MEG 0313,3012,-0.086100,0.098800,0.009000,-0.035199,0.118196,-0.992366,-0.483584,-0.870970,-0.086597,-0.874557,0.476844,0.087815 +MEG 0312,3012,-0.086100,0.098800,0.009000,-0.483584,-0.870970,-0.086597,0.035199,-0.118196,0.992366,-0.874557,0.476844,0.087815 +MEG 0311,3024,-0.086100,0.098800,0.009000,-0.035199,0.118196,-0.992366,-0.483584,-0.870970,-0.086597,-0.874557,0.476844,0.087815 +MEG 0322,3012,-0.088700,0.075700,0.041200,-0.351594,0.118898,-0.928584,-0.370994,-0.928384,0.021600,-0.859515,0.352093,0.370525 +MEG 0323,3012,-0.088700,0.075700,0.041200,-0.370994,-0.928384,0.021600,0.351594,-0.118898,0.928584,-0.859515,0.352093,0.370525 +MEG 0321,3024,-0.088700,0.075700,0.041200,-0.351594,0.118898,-0.928584,-0.370994,-0.928384,0.021600,-0.859515,0.352093,0.370525 +MEG 0333,3012,-0.070200,0.075800,0.070700,-0.594240,0.228816,-0.771052,-0.385726,-0.922363,0.023502,-0.705812,0.311381,0.636365 +MEG 0332,3012,-0.070200,0.075800,0.070700,-0.385726,-0.922363,0.023502,0.594240,-0.228816,0.771052,-0.705812,0.311381,0.636365 +MEG 0331,3024,-0.070200,0.075800,0.070700,-0.594240,0.228816,-0.771052,-0.385726,-0.922363,0.023502,-0.705812,0.311381,0.636365 +MEG 0343,3012,-0.100300,0.065900,0.008100,-0.065802,0.024701,-0.997527,-0.288308,-0.957526,-0.004700,-0.955274,0.287286,0.070128 +MEG 0342,3012,-0.100300,0.065900,0.008100,-0.288308,-0.957526,-0.004700,0.065802,-0.024701,0.997527,-0.955274,0.287286,0.070128 +MEG 0341,3024,-0.100300,0.065900,0.008100,-0.065802,0.024701,-0.997527,-0.288308,-0.957526,-0.004700,-0.955274,0.287286,0.070128 +MEG 0413,3012,-0.080800,0.041300,0.072000,-0.642126,0.049002,-0.765031,-0.135706,-0.989540,0.050502,-0.754555,0.136248,0.642060 +MEG 0412,3012,-0.080800,0.041300,0.072000,-0.135706,-0.989540,0.050502,0.642126,-0.049002,0.765031,-0.754555,0.136248,0.642060 +MEG 0411,3024,-0.080800,0.041300,0.072000,-0.642126,0.049002,-0.765031,-0.135706,-0.989540,0.050502,-0.754555,0.136248,0.642060 +MEG 0422,3012,-0.052600,0.040600,0.095200,-0.874970,-0.019699,-0.483783,-0.054998,-0.988666,0.139695,-0.481052,0.148836,0.863970 +MEG 0423,3012,-0.052600,0.040600,0.095200,-0.054998,-0.988666,0.139695,0.874970,0.019699,0.483783,-0.481052,0.148836,0.863970 +MEG 0421,3024,-0.052600,0.040600,0.095200,-0.874970,-0.019699,-0.483783,-0.054998,-0.988666,0.139695,-0.481052,0.148836,0.863970 +MEG 0432,3012,-0.053700,0.005900,0.096900,-0.870267,-0.017799,-0.492081,0.028999,-0.999462,-0.015299,-0.491545,-0.027584,0.870315 +MEG 0433,3012,-0.053700,0.005900,0.096900,0.028999,-0.999462,-0.015299,0.870267,0.017799,0.492081,-0.491545,-0.027584,0.870315 +MEG 0431,3024,-0.053700,0.005900,0.096900,-0.870267,-0.017799,-0.492081,0.028999,-0.999462,-0.015299,-0.491545,-0.027584,0.870315 +MEG 0443,3012,-0.082900,0.006200,0.072800,-0.647316,0.002100,-0.762219,0.043201,-0.998325,-0.039401,-0.761025,-0.058434,0.646141 +MEG 0442,3012,-0.082900,0.006200,0.072800,0.043201,-0.998325,-0.039401,0.647316,-0.002100,0.762219,-0.761025,-0.058434,0.646141 +MEG 0441,3024,-0.082900,0.006200,0.072800,-0.647316,0.002100,-0.762219,0.043201,-0.998325,-0.039401,-0.761025,-0.058434,0.646141 +MEG 0513,3012,-0.063700,0.125400,0.013600,0.019400,0.216900,-0.976001,-0.783501,-0.603001,-0.149600,-0.620977,0.767600,0.158243 +MEG 0512,3012,-0.063700,0.125400,0.013600,-0.783501,-0.603001,-0.149600,-0.019400,-0.216900,0.976001,-0.620977,0.767600,0.158243 +MEG 0511,3024,-0.063700,0.125400,0.013600,0.019400,0.216900,-0.976001,-0.783501,-0.603001,-0.149600,-0.620977,0.767600,0.158243 +MEG 0523,3012,-0.033200,0.139700,0.017400,0.010600,0.218707,-0.975733,-0.957032,-0.280709,-0.073302,-0.289929,0.934585,0.206334 +MEG 0522,3012,-0.033200,0.139700,0.017400,-0.957032,-0.280709,-0.073302,-0.010600,-0.218707,0.975733,-0.289929,0.934585,0.206334 +MEG 0521,3024,-0.033200,0.139700,0.017400,0.010600,0.218707,-0.975733,-0.957032,-0.280709,-0.073302,-0.289929,0.934585,0.206334 +MEG 0532,3012,-0.033700,0.127400,0.048500,-0.052299,0.470092,-0.881084,-0.962183,-0.259895,-0.081599,-0.267349,0.843497,0.465907 +MEG 0533,3012,-0.033700,0.127400,0.048500,-0.962183,-0.259895,-0.081599,0.052299,-0.470092,0.881084,-0.267349,0.843497,0.465907 +MEG 0531,3024,-0.033700,0.127400,0.048500,-0.052299,0.470092,-0.881084,-0.962183,-0.259895,-0.081599,-0.267349,0.843497,0.465907 +MEG 0542,3012,-0.067200,0.108900,0.044300,-0.171191,0.377780,-0.909852,-0.709963,-0.687664,-0.151892,-0.683055,0.619959,0.385932 +MEG 0543,3012,-0.067200,0.108900,0.044300,-0.709963,-0.687664,-0.151892,0.171191,-0.377780,0.909852,-0.683055,0.619959,0.385932 +MEG 0541,3024,-0.067200,0.108900,0.044300,-0.171191,0.377780,-0.909852,-0.709963,-0.687664,-0.151892,-0.683055,0.619959,0.385932 +MEG 0613,3012,-0.035800,0.104800,0.075000,-0.009500,0.770803,-0.637003,-0.954604,-0.196601,-0.223701,-0.297665,0.605960,0.737679 +MEG 0612,3012,-0.035800,0.104800,0.075000,-0.954604,-0.196601,-0.223701,0.009500,-0.770803,0.637003,-0.297665,0.605960,0.737679 +MEG 0611,3024,-0.035800,0.104800,0.075000,-0.009500,0.770803,-0.637003,-0.954604,-0.196601,-0.223701,-0.297665,0.605960,0.737679 +MEG 0622,3012,0.000100,0.077500,0.096700,0.000200,0.917700,-0.397400,-1.000000,0.000400,0.000200,0.000342,0.397400,0.917700 +MEG 0623,3012,0.000100,0.077500,0.096700,-1.000000,0.000400,0.000200,-0.000200,-0.917700,0.397400,0.000342,0.397400,0.917700 +MEG 0621,3024,0.000100,0.077500,0.096700,0.000200,0.917700,-0.397400,-1.000000,0.000400,0.000200,0.000342,0.397400,0.917700 +MEG 0633,3012,-0.018400,0.044000,0.106300,0.006700,0.983663,-0.179893,-0.990063,-0.018599,-0.139095,-0.140168,0.179038,0.973764 +MEG 0632,3012,-0.018400,0.044000,0.106300,-0.990063,-0.018599,-0.139095,-0.006700,-0.983663,0.179893,-0.140168,0.179038,0.973764 +MEG 0631,3024,-0.018400,0.044000,0.106300,0.006700,0.983663,-0.179893,-0.990063,-0.018599,-0.139095,-0.140168,0.179038,0.973764 +MEG 0642,3012,-0.036800,0.075300,0.092200,-0.025099,0.896459,-0.442380,-0.950857,-0.157993,-0.266288,-0.308609,0.413957,0.856370 +MEG 0643,3012,-0.036800,0.075300,0.092200,-0.950857,-0.157993,-0.266288,0.025099,-0.896459,0.442380,-0.308609,0.413957,0.856370 +MEG 0641,3024,-0.036800,0.075300,0.092200,-0.025099,0.896459,-0.442380,-0.950857,-0.157993,-0.266288,-0.308609,0.413957,0.856370 +MEG 0713,3012,-0.018500,0.010500,0.109600,-0.990008,-0.012000,-0.140501,0.013700,-0.999808,-0.011400,-0.140337,-0.013211,0.989982 +MEG 0712,3012,-0.018500,0.010500,0.109600,0.013700,-0.999808,-0.011400,0.990008,0.012000,0.140501,-0.140337,-0.013211,0.989982 +MEG 0711,3024,-0.018500,0.010500,0.109600,-0.990008,-0.012000,-0.140501,0.013700,-0.999808,-0.011400,-0.140337,-0.013211,0.989982 +MEG 0723,3012,0.018600,0.010500,0.109600,0.988752,-0.007200,-0.149393,0.001100,0.999151,-0.040798,0.149560,0.040175,0.987921 +MEG 0722,3012,0.018600,0.010500,0.109600,0.001100,0.999151,-0.040798,-0.988752,0.007200,0.149393,0.149560,0.040175,0.987921 +MEG 0721,3024,0.018600,0.010500,0.109600,0.988752,-0.007200,-0.149393,0.001100,0.999151,-0.040798,0.149560,0.040175,0.987921 +MEG 0733,3012,0.018600,-0.023300,0.105900,-0.036600,-0.970305,-0.239101,0.987205,0.002100,-0.159701,0.155461,-0.241887,0.957812 +MEG 0732,3012,0.018600,-0.023300,0.105900,0.987205,0.002100,-0.159701,0.036600,0.970305,0.239101,0.155461,-0.241887,0.957812 +MEG 0731,3024,0.018600,-0.023300,0.105900,-0.036600,-0.970305,-0.239101,0.987205,0.002100,-0.159701,0.155461,-0.241887,0.957812 +MEG 0743,3012,-0.018500,-0.023700,0.105800,0.039398,-0.969753,-0.240888,0.992852,0.010799,0.118594,-0.112406,-0.243839,0.963246 +MEG 0742,3012,-0.018500,-0.023700,0.105800,0.992852,0.010799,0.118594,-0.039398,0.969753,0.240888,-0.112406,-0.243839,0.963246 +MEG 0741,3024,-0.018500,-0.023700,0.105800,0.039398,-0.969753,-0.240888,0.992852,0.010799,0.118594,-0.112406,-0.243839,0.963246 +MEG 0813,3012,0.000100,0.144500,0.018700,-0.000300,0.251701,-0.967805,-0.999905,-0.012100,-0.002800,-0.012415,0.967712,0.251681 +MEG 0812,3012,0.000100,0.144500,0.018700,-0.999905,-0.012100,-0.002800,0.000300,-0.251701,0.967805,-0.012415,0.967712,0.251681 +MEG 0811,3024,0.000100,0.144500,0.018700,-0.000300,0.251701,-0.967805,-0.999905,-0.012100,-0.002800,-0.012415,0.967712,0.251681 +MEG 0822,3012,0.000100,0.131600,0.050000,0.000700,0.499200,-0.866500,-1.000000,0.000900,-0.000200,0.000680,0.866500,0.499200 +MEG 0823,3012,0.000100,0.131600,0.050000,-1.000000,0.000900,-0.000200,-0.000700,-0.499200,0.866500,0.000680,0.866500,0.499200 +MEG 0821,3024,0.000100,0.131600,0.050000,0.000700,0.499200,-0.866500,-1.000000,0.000900,-0.000200,0.000680,0.866500,0.499200 +MEG 0913,3012,0.033100,0.139700,0.017300,-0.005300,0.236504,-0.971616,-0.964716,0.254804,0.067301,0.263489,0.937690,0.226809 +MEG 0912,3012,0.033100,0.139700,0.017300,-0.964716,0.254804,0.067301,0.005300,-0.236504,0.971616,0.263489,0.937690,0.226809 +MEG 0911,3024,0.033100,0.139700,0.017300,-0.005300,0.236504,-0.971616,-0.964716,0.254804,0.067301,0.263489,0.937690,0.226809 +MEG 0923,3012,0.063800,0.125300,0.013500,-0.022801,0.216906,-0.975926,-0.792421,0.591316,0.150004,0.609617,0.776765,0.158398 +MEG 0922,3012,0.063800,0.125300,0.013500,-0.792421,0.591316,0.150004,0.022801,-0.216906,0.975926,0.609617,0.776765,0.158398 +MEG 0921,3024,0.063800,0.125300,0.013500,-0.022801,0.216906,-0.975926,-0.792421,0.591316,0.150004,0.609617,0.776765,0.158398 +MEG 0932,3012,0.067100,0.108800,0.044400,0.174311,0.376424,-0.909958,-0.709645,0.688644,0.148909,0.682690,0.619790,0.387165 +MEG 0933,3012,0.067100,0.108800,0.044400,-0.709645,0.688644,0.148909,-0.174311,-0.376424,0.909958,0.682690,0.619790,0.387165 +MEG 0931,3024,0.067100,0.108800,0.044400,0.174311,0.376424,-0.909958,-0.709645,0.688644,0.148909,0.682690,0.619790,0.387165 +MEG 0942,3012,0.033800,0.127300,0.048600,0.055602,0.468914,-0.881527,-0.961529,0.263008,0.079302,0.269035,0.843204,0.465498 +MEG 0943,3012,0.033800,0.127300,0.048600,-0.961529,0.263008,0.079302,-0.055602,-0.468914,0.881527,0.269035,0.843204,0.465498 +MEG 0941,3024,0.033800,0.127300,0.048600,0.055602,0.468914,-0.881527,-0.961529,0.263008,0.079302,0.269035,0.843204,0.465498 +MEG 1013,3012,0.000100,0.109300,0.077100,0.000900,0.759320,-0.650717,-0.999826,-0.013800,-0.017400,-0.022193,0.650620,0.759175 +MEG 1012,3012,0.000100,0.109300,0.077100,-0.999826,-0.013800,-0.017400,-0.000900,-0.759320,0.650717,-0.022193,0.650620,0.759175 +MEG 1011,3024,0.000100,0.109300,0.077100,0.000900,0.759320,-0.650717,-0.999826,-0.013800,-0.017400,-0.022193,0.650620,0.759175 +MEG 1023,3012,0.035800,0.104800,0.075000,0.006800,0.768236,-0.640130,-0.964046,0.175308,0.200109,0.265951,0.615754,0.741807 +MEG 1022,3012,0.035800,0.104800,0.075000,-0.964046,0.175308,0.200109,-0.006800,-0.768236,0.640130,0.265951,0.615754,0.741807 +MEG 1021,3024,0.035800,0.104800,0.075000,0.006800,0.768236,-0.640130,-0.964046,0.175308,0.200109,0.265951,0.615754,0.741807 +MEG 1032,3012,0.036800,0.075200,0.092300,0.029199,0.895982,-0.442991,-0.950980,0.161397,0.263795,0.307852,0.413573,0.856774 +MEG 1033,3012,0.036800,0.075200,0.092300,-0.950980,0.161397,0.263795,-0.029199,-0.895982,0.442991,0.307852,0.413573,0.856774 +MEG 1031,3024,0.036800,0.075200,0.092300,0.029199,0.895982,-0.442991,-0.950980,0.161397,0.263795,0.307852,0.413573,0.856774 +MEG 1043,3012,0.018400,0.044200,0.106200,-0.013699,0.979661,-0.200192,-0.993160,0.009900,0.116395,0.116010,0.200417,0.972825 +MEG 1042,3012,0.018400,0.044200,0.106200,-0.993160,0.009900,0.116395,0.013699,-0.979661,0.200192,0.116010,0.200417,0.972825 +MEG 1041,3024,0.018400,0.044200,0.106200,-0.013699,0.979661,-0.200192,-0.993160,0.009900,0.116395,0.116010,0.200417,0.972825 +MEG 1112,3012,0.052500,0.040600,0.095300,0.875761,-0.017599,-0.482379,-0.056398,0.988756,-0.138494,0.479392,0.148493,0.864922 +MEG 1113,3012,0.052500,0.040600,0.095300,-0.056398,0.988756,-0.138494,-0.875761,0.017599,0.482379,0.479392,0.148493,0.864922 +MEG 1111,3024,0.052500,0.040600,0.095300,0.875761,-0.017599,-0.482379,-0.056398,0.988756,-0.138494,0.479392,0.148493,0.864922 +MEG 1123,3012,0.080900,0.041300,0.072100,0.643867,0.052097,-0.763361,-0.171791,0.981950,-0.077896,0.745525,0.181294,0.641196 +MEG 1122,3012,0.080900,0.041300,0.072100,-0.171791,0.981950,-0.077896,-0.643867,-0.052097,0.763361,0.745525,0.181294,0.641196 +MEG 1121,3024,0.080900,0.041300,0.072100,0.643867,0.052097,-0.763361,-0.171791,0.981950,-0.077896,0.745525,0.181294,0.641196 +MEG 1133,3012,0.082800,0.006100,0.072800,0.645314,0.000600,-0.763917,0.011100,0.999922,0.010200,0.763864,-0.015062,0.645257 +MEG 1132,3012,0.082800,0.006100,0.072800,0.011100,0.999922,0.010200,-0.645314,-0.000600,0.763917,0.763864,-0.015062,0.645257 +MEG 1131,3024,0.082800,0.006100,0.072800,0.645314,0.000600,-0.763917,0.011100,0.999922,0.010200,0.763864,-0.015062,0.645257 +MEG 1142,3012,0.053500,0.006200,0.097000,0.871295,-0.018300,-0.490397,0.028700,0.999494,0.013700,0.489898,-0.026011,0.871379 +MEG 1143,3012,0.053500,0.006200,0.097000,0.028700,0.999494,0.013700,-0.871295,0.018300,0.490397,0.489898,-0.026011,0.871379 +MEG 1141,3024,0.053500,0.006200,0.097000,0.871295,-0.018300,-0.490397,0.028700,0.999494,0.013700,0.489898,-0.026011,0.871379 +MEG 1213,3012,0.086200,0.098600,0.008900,0.046901,0.120402,-0.991617,-0.502008,0.861115,0.080801,0.863624,0.494010,0.100830 +MEG 1212,3012,0.086200,0.098600,0.008900,-0.502008,0.861115,0.080801,-0.046901,-0.120402,0.991617,0.863624,0.494010,0.100830 +MEG 1211,3024,0.086200,0.098600,0.008900,0.046901,0.120402,-0.991617,-0.502008,0.861115,0.080801,0.863624,0.494010,0.100830 +MEG 1223,3012,0.100300,0.066000,0.008200,0.067403,0.027601,-0.997344,-0.315514,0.948942,0.005000,0.946559,0.314339,0.072670 +MEG 1222,3012,0.100300,0.066000,0.008200,-0.315514,0.948942,0.005000,-0.067403,-0.027601,0.997344,0.946559,0.314339,0.072670 +MEG 1221,3024,0.100300,0.066000,0.008200,0.067403,0.027601,-0.997344,-0.315514,0.948942,0.005000,0.946559,0.314339,0.072670 +MEG 1232,3012,0.088700,0.075700,0.041200,0.351800,0.119000,-0.928499,-0.371200,0.928299,-0.021700,0.859343,0.352293,0.370748 +MEG 1233,3012,0.088700,0.075700,0.041200,-0.371200,0.928299,-0.021700,-0.351800,-0.119000,0.928499,0.859343,0.352293,0.370748 +MEG 1231,3024,0.088700,0.075700,0.041200,0.351800,0.119000,-0.928499,-0.371200,0.928299,-0.021700,0.859343,0.352293,0.370748 +MEG 1243,3012,0.069900,0.075800,0.070900,0.612621,0.238208,-0.753626,-0.425815,0.902831,-0.060702,0.665937,0.358092,0.654526 +MEG 1242,3012,0.069900,0.075800,0.070900,-0.425815,0.902831,-0.060702,-0.612621,-0.238208,0.753626,0.665937,0.358092,0.654526 +MEG 1241,3024,0.069900,0.075800,0.070900,0.612621,0.238208,-0.753626,-0.425815,0.902831,-0.060702,0.665937,0.358092,0.654526 +MEG 1312,3012,0.098900,0.040400,0.041300,0.343005,0.060601,-0.937414,-0.162403,0.986715,0.004300,0.925222,0.150764,0.348290 +MEG 1313,3012,0.098900,0.040400,0.041300,-0.162403,0.986715,0.004300,-0.343005,-0.060601,0.937414,0.925222,0.150764,0.348290 +MEG 1311,3024,0.098900,0.040400,0.041300,0.343005,0.060601,-0.937414,-0.162403,0.986715,0.004300,0.925222,0.150764,0.348290 +MEG 1323,3012,0.107400,0.032900,0.008100,0.062598,0.011400,-0.997974,-0.129597,0.991574,0.003200,0.989601,0.129134,0.063548 +MEG 1322,3012,0.107400,0.032900,0.008100,-0.129597,0.991574,0.003200,-0.062598,-0.011400,0.997974,0.989601,0.129134,0.063548 +MEG 1321,3024,0.107400,0.032900,0.008100,0.062598,0.011400,-0.997974,-0.129597,0.991574,0.003200,0.989601,0.129134,0.063548 +MEG 1333,3012,0.108300,-0.001100,0.006800,0.050900,-0.002300,-0.998701,0.060100,0.998201,0.000800,0.996903,-0.060063,0.050947 +MEG 1332,3012,0.108300,-0.001100,0.006800,0.060100,0.998201,0.000800,-0.050900,0.002300,0.998701,0.996903,-0.060063,0.050947 +MEG 1331,3024,0.108300,-0.001100,0.006800,0.050900,-0.002300,-0.998701,0.060100,0.998201,0.000800,0.996903,-0.060063,0.050947 +MEG 1342,3012,0.101000,0.004400,0.041000,0.353004,0.007800,-0.935611,0.038200,0.999012,0.022700,0.934864,-0.043754,0.352358 +MEG 1343,3012,0.101000,0.004400,0.041000,0.038200,0.999012,0.022700,-0.353004,-0.007800,0.935611,0.934864,-0.043754,0.352358 +MEG 1341,3024,0.101000,0.004400,0.041000,0.353004,0.007800,-0.935611,0.038200,0.999012,0.022700,0.934864,-0.043754,0.352358 +MEG 1412,3012,0.102000,0.063000,-0.026000,-0.014301,0.003500,-0.999948,-0.281114,0.959646,0.007400,0.959622,0.281205,-0.012740 +MEG 1413,3012,0.102000,0.063000,-0.026000,-0.281114,0.959646,0.007400,0.014301,-0.003500,0.999948,0.959622,0.281205,-0.012740 +MEG 1411,3024,0.102000,0.063000,-0.026000,-0.014301,0.003500,-0.999948,-0.281114,0.959646,0.007400,0.959622,0.281205,-0.012740 +MEG 1423,3012,0.106500,0.046900,-0.060000,0.012000,0.008300,-0.999894,-0.179699,0.983694,0.006000,0.983639,0.179608,0.013296 +MEG 1422,3012,0.106500,0.046900,-0.060000,-0.179699,0.983694,0.006000,-0.012000,-0.008300,0.999894,0.983639,0.179608,0.013296 +MEG 1421,3024,0.106500,0.046900,-0.060000,0.012000,0.008300,-0.999894,-0.179699,0.983694,0.006000,0.983639,0.179608,0.013296 +MEG 1433,3012,0.109800,0.013100,-0.062200,0.012400,0.004400,-0.999913,-0.012800,0.999913,0.004200,0.999845,0.012747,0.012455 +MEG 1432,3012,0.109800,0.013100,-0.062200,-0.012800,0.999913,0.004200,-0.012400,-0.004400,0.999913,0.999845,0.012747,0.012455 +MEG 1431,3024,0.109800,0.013100,-0.062200,0.012400,0.004400,-0.999913,-0.012800,0.999913,0.004200,0.999845,0.012747,0.012455 +MEG 1442,3012,0.108300,0.030100,-0.026200,-0.009900,0.004100,-0.999888,-0.095799,0.995388,0.005100,0.995297,0.095839,-0.009461 +MEG 1443,3012,0.108300,0.030100,-0.026200,-0.095799,0.995388,0.005100,0.009900,-0.004100,0.999888,0.995297,0.095839,-0.009461 +MEG 1441,3024,0.108300,0.030100,-0.026200,-0.009900,0.004100,-0.999888,-0.095799,0.995388,0.005100,0.995297,0.095839,-0.009461 +MEG 1512,3012,-0.108800,-0.003200,-0.028400,0.020599,0.000800,-0.999771,0.080298,-0.996771,0.000800,-0.996541,-0.080296,-0.020597 +MEG 1513,3012,-0.108800,-0.003200,-0.028400,0.080298,-0.996771,0.000800,-0.020599,-0.000800,0.999771,-0.996541,-0.080296,-0.020597 +MEG 1511,3024,-0.108800,-0.003200,-0.028400,0.020599,0.000800,-0.999771,0.080298,-0.996771,0.000800,-0.996541,-0.080296,-0.020597 +MEG 1522,3012,-0.101700,-0.036000,-0.028100,0.028399,0.002900,-0.999575,0.340892,-0.940077,0.007000,-0.939657,-0.340945,-0.027686 +MEG 1523,3012,-0.101700,-0.036000,-0.028100,0.340892,-0.940077,0.007000,-0.028399,-0.002900,0.999575,-0.939657,-0.340945,-0.027686 +MEG 1521,3024,-0.101700,-0.036000,-0.028100,0.028399,0.002900,-0.999575,0.340892,-0.940077,0.007000,-0.939657,-0.340945,-0.027686 +MEG 1533,3012,-0.095100,-0.052400,-0.062300,-0.014600,0.000600,-0.999893,0.465497,-0.884994,-0.007300,-0.884904,-0.465554,0.012642 +MEG 1532,3012,-0.095100,-0.052400,-0.062300,0.465497,-0.884994,-0.007300,0.014600,-0.000600,0.999893,-0.884904,-0.465554,0.012642 +MEG 1531,3024,-0.095100,-0.052400,-0.062300,-0.014600,0.000600,-0.999893,0.465497,-0.884994,-0.007300,-0.884904,-0.465554,0.012642 +MEG 1543,3012,-0.106800,-0.020500,-0.062500,-0.013500,0.001800,-0.999907,0.201801,-0.979407,-0.004500,-0.979324,-0.201844,0.012859 +MEG 1542,3012,-0.106800,-0.020500,-0.062500,0.201801,-0.979407,-0.004500,0.013500,-0.001800,0.999907,-0.979324,-0.201844,0.012859 +MEG 1541,3024,-0.106800,-0.020500,-0.062500,-0.013500,0.001800,-0.999907,0.201801,-0.979407,-0.004500,-0.979324,-0.201844,0.012859 +MEG 1613,3012,-0.101700,-0.033900,0.005600,-0.068397,-0.031599,-0.997158,0.340386,-0.940260,0.006500,-0.937793,-0.338974,0.075067 +MEG 1612,3012,-0.101700,-0.033900,0.005600,0.340386,-0.940260,0.006500,0.068397,0.031599,0.997158,-0.937793,-0.338974,0.075067 +MEG 1611,3024,-0.101700,-0.033900,0.005600,-0.068397,-0.031599,-0.997158,0.340386,-0.940260,0.006500,-0.937793,-0.338974,0.075067 +MEG 1622,3012,-0.095200,-0.030800,0.039100,-0.325001,-0.058300,-0.943902,0.308901,-0.949902,-0.047600,-0.893840,-0.307042,0.326728 +MEG 1623,3012,-0.095200,-0.030800,0.039100,0.308901,-0.949902,-0.047600,0.325001,0.058300,0.943902,-0.893840,-0.307042,0.326728 +MEG 1621,3024,-0.095200,-0.030800,0.039100,-0.325001,-0.058300,-0.943902,0.308901,-0.949902,-0.047600,-0.893840,-0.307042,0.326728 +MEG 1632,3012,-0.078100,-0.062800,0.039400,-0.261799,-0.201399,-0.943897,0.596898,-0.802297,0.005600,-0.758414,-0.561944,0.330256 +MEG 1633,3012,-0.078100,-0.062800,0.039400,0.596898,-0.802297,0.005600,0.261799,0.201399,0.943897,-0.758414,-0.561944,0.330256 +MEG 1631,3024,-0.078100,-0.062800,0.039400,-0.261799,-0.201399,-0.943897,0.596898,-0.802297,0.005600,-0.758414,-0.561944,0.330256 +MEG 1643,3012,-0.086600,-0.064000,0.005500,-0.060699,-0.048399,-0.996982,0.570290,-0.821385,0.005100,-0.819153,-0.568259,0.077459 +MEG 1642,3012,-0.086600,-0.064000,0.005500,0.570290,-0.821385,0.005100,0.060699,0.048399,0.996982,-0.819153,-0.568259,0.077459 +MEG 1641,3024,-0.086600,-0.064000,0.005500,-0.060699,-0.048399,-0.996982,0.570290,-0.821385,0.005100,-0.819153,-0.568259,0.077459 +MEG 1713,3012,-0.075800,-0.079700,-0.062100,0.000000,-0.015300,-0.999883,0.678188,-0.734787,0.011200,-0.734873,-0.678109,0.010376 +MEG 1712,3012,-0.075800,-0.079700,-0.062100,0.678188,-0.734787,0.011200,0.000000,0.015300,0.999883,-0.734873,-0.678109,0.010376 +MEG 1711,3024,-0.075800,-0.079700,-0.062100,0.000000,-0.015300,-0.999883,0.678188,-0.734787,0.011200,-0.734873,-0.678109,0.010376 +MEG 1722,3012,-0.086100,-0.066000,-0.028200,0.022801,0.009400,-0.999727,0.571015,-0.820922,0.005300,-0.820648,-0.570980,-0.024085 +MEG 1723,3012,-0.086100,-0.066000,-0.028200,0.571015,-0.820922,0.005300,-0.022801,-0.009400,0.999727,-0.820648,-0.570980,-0.024085 +MEG 1721,3024,-0.086100,-0.066000,-0.028200,0.022801,0.009400,-0.999727,0.571015,-0.820922,0.005300,-0.820648,-0.570980,-0.024085 +MEG 1732,3012,-0.063200,-0.090500,-0.027800,0.016000,0.023501,-0.999624,0.807319,-0.590114,-0.000900,-0.589913,-0.807001,-0.028415 +MEG 1733,3012,-0.063200,-0.090500,-0.027800,0.807319,-0.590114,-0.000900,-0.016000,-0.023501,0.999624,-0.589913,-0.807001,-0.028415 +MEG 1731,3024,-0.063200,-0.090500,-0.027800,0.016000,0.023501,-0.999624,0.807319,-0.590114,-0.000900,-0.589913,-0.807001,-0.028415 +MEG 1743,3012,-0.048900,-0.099400,-0.062100,-0.008800,-0.009400,-0.999917,0.895915,-0.444308,-0.003700,-0.444236,-0.895874,0.012332 +MEG 1742,3012,-0.048900,-0.099400,-0.062100,0.895915,-0.444308,-0.003700,0.008800,0.009400,0.999917,-0.444236,-0.895874,0.012332 +MEG 1741,3024,-0.048900,-0.099400,-0.062100,-0.008800,-0.009400,-0.999917,0.895915,-0.444308,-0.003700,-0.444236,-0.895874,0.012332 +MEG 1813,3012,-0.078600,-0.028700,0.069600,-0.617503,-0.040900,-0.785504,0.249001,-0.957505,-0.145901,-0.746157,-0.285686,0.601447 +MEG 1812,3012,-0.078600,-0.028700,0.069600,0.249001,-0.957505,-0.145901,0.617503,0.040900,0.785504,-0.746157,-0.285686,0.601447 +MEG 1811,3024,-0.078600,-0.028700,0.069600,-0.617503,-0.040900,-0.785504,0.249001,-0.957505,-0.145901,-0.746157,-0.285686,0.601447 +MEG 1822,3012,-0.051800,-0.027700,0.092700,-0.859116,0.025300,-0.511209,0.109902,-0.966318,-0.232704,-0.499878,-0.256103,0.827399 +MEG 1823,3012,-0.051800,-0.027700,0.092700,0.109902,-0.966318,-0.232704,0.859116,-0.025300,0.511209,-0.499878,-0.256103,0.827399 +MEG 1821,3024,-0.051800,-0.027700,0.092700,-0.859116,0.025300,-0.511209,0.109902,-0.966318,-0.232704,-0.499878,-0.256103,0.827399 +MEG 1832,3012,-0.018100,-0.054200,0.092300,0.070502,-0.841822,-0.535214,0.989126,-0.010400,0.146704,-0.129065,-0.539737,0.831935 +MEG 1833,3012,-0.018100,-0.054200,0.092300,0.989126,-0.010400,0.146704,-0.070502,0.841822,0.535214,-0.129065,-0.539737,0.831935 +MEG 1831,3024,-0.018100,-0.054200,0.092300,0.070502,-0.841822,-0.535214,0.989126,-0.010400,0.146704,-0.129065,-0.539737,0.831935 +MEG 1843,3012,-0.055200,-0.062700,0.070700,-0.383905,-0.499806,-0.776409,0.785209,-0.619107,0.010300,-0.485829,-0.605689,0.630130 +MEG 1842,3012,-0.055200,-0.062700,0.070700,0.785209,-0.619107,0.010300,0.383905,0.499806,0.776409,-0.485829,-0.605689,0.630130 +MEG 1841,3024,-0.055200,-0.062700,0.070700,-0.383905,-0.499806,-0.776409,0.785209,-0.619107,0.010300,-0.485829,-0.605689,0.630130 +MEG 1912,3012,-0.051300,-0.086100,0.039700,-0.154503,-0.301206,-0.940920,0.880219,-0.474510,0.007400,-0.448705,-0.827072,0.338441 +MEG 1913,3012,-0.051300,-0.086100,0.039700,0.880219,-0.474510,0.007400,0.154503,0.301206,0.940920,-0.448705,-0.827072,0.338441 +MEG 1911,3024,-0.051300,-0.086100,0.039700,-0.154503,-0.301206,-0.940920,0.880219,-0.474510,0.007400,-0.448705,-0.827072,0.338441 +MEG 1923,3012,-0.033500,-0.103300,0.006200,-0.044700,-0.142400,-0.988799,0.959299,-0.282400,-0.002700,-0.278852,-0.948675,0.149227 +MEG 1922,3012,-0.033500,-0.103300,0.006200,0.959299,-0.282400,-0.002700,0.044700,0.142400,0.988799,-0.278852,-0.948675,0.149227 +MEG 1921,3024,-0.033500,-0.103300,0.006200,-0.044700,-0.142400,-0.988799,0.959299,-0.282400,-0.002700,-0.278852,-0.948675,0.149227 +MEG 1932,3012,-0.033100,-0.105100,-0.027800,0.007900,0.022401,-0.999723,0.951222,-0.308507,0.000600,-0.308408,-0.950963,-0.023745 +MEG 1933,3012,-0.033100,-0.105100,-0.027800,0.951222,-0.308507,0.000600,-0.007900,-0.022401,0.999723,-0.308408,-0.950963,-0.023745 +MEG 1931,3024,-0.033100,-0.105100,-0.027800,0.007900,0.022401,-0.999723,0.951222,-0.308507,0.000600,-0.308408,-0.950963,-0.023745 +MEG 1943,3012,-0.063600,-0.088400,0.006000,-0.064102,-0.086003,-0.994231,0.809725,-0.586818,-0.001400,-0.583312,-0.805143,0.107255 +MEG 1942,3012,-0.063600,-0.088400,0.006000,0.809725,-0.586818,-0.001400,0.064102,0.086003,0.994231,-0.583312,-0.805143,0.107255 +MEG 1941,3024,-0.063600,-0.088400,0.006000,-0.064102,-0.086003,-0.994231,0.809725,-0.586818,-0.001400,-0.583312,-0.805143,0.107255 +MEG 2013,3012,-0.018600,-0.080100,0.069000,-0.001300,-0.622289,-0.782786,0.992783,-0.094798,0.073699,-0.120069,-0.777041,0.617921 +MEG 2012,3012,-0.018600,-0.080100,0.069000,0.992783,-0.094798,0.073699,0.001300,0.622289,0.782786,-0.120069,-0.777041,0.617921 +MEG 2011,3024,-0.018600,-0.080100,0.069000,-0.001300,-0.622289,-0.782786,0.992783,-0.094798,0.073699,-0.120069,-0.777041,0.617921 +MEG 2023,3012,0.018600,-0.080200,0.068900,0.000200,-0.620001,-0.784601,0.986601,0.128300,-0.101100,0.163347,-0.774068,0.611719 +MEG 2022,3012,0.018600,-0.080200,0.068900,0.986601,0.128300,-0.101100,-0.000200,0.620001,0.784601,0.163347,-0.774068,0.611719 +MEG 2021,3024,0.018600,-0.080200,0.068900,0.000200,-0.620001,-0.784601,0.986601,0.128300,-0.101100,0.163347,-0.774068,0.611719 +MEG 2032,3012,0.016900,-0.097200,0.039700,-0.000300,-0.372910,-0.927926,0.990028,0.130604,-0.052801,0.140881,-0.918688,0.369152 +MEG 2033,3012,0.016900,-0.097200,0.039700,0.990028,0.130604,-0.052801,0.000300,0.372910,0.927926,0.140881,-0.918688,0.369152 +MEG 2031,3024,0.016900,-0.097200,0.039700,-0.000300,-0.372910,-0.927926,0.990028,0.130604,-0.052801,0.140881,-0.918688,0.369152 +MEG 2042,3012,-0.017000,-0.097200,0.039700,-0.000500,-0.373789,-0.927473,0.989971,-0.131196,0.052398,-0.141267,-0.918145,0.370106 +MEG 2043,3012,-0.017000,-0.097200,0.039700,0.989971,-0.131196,0.052398,0.000500,0.373789,0.927473,-0.141267,-0.918145,0.370106 +MEG 2041,3024,-0.017000,-0.097200,0.039700,-0.000500,-0.373789,-0.927473,0.989971,-0.131196,0.052398,-0.141267,-0.918145,0.370106 +MEG 2113,3012,0.000000,-0.108600,0.007000,-0.000100,-0.168403,-0.985718,0.999819,0.020400,-0.003600,0.020715,-0.985540,0.168371 +MEG 2112,3012,0.000000,-0.108600,0.007000,0.999819,0.020400,-0.003600,0.000100,0.168403,0.985718,0.020715,-0.985540,0.168371 +MEG 2111,3024,0.000000,-0.108600,0.007000,-0.000100,-0.168403,-0.985718,0.999819,0.020400,-0.003600,0.020715,-0.985540,0.168371 +MEG 2122,3012,0.000000,-0.110600,-0.027500,0.000000,0.040700,-0.999200,1.000000,-0.000400,0.000000,-0.000400,-0.999200,-0.040700 +MEG 2123,3012,0.000000,-0.110600,-0.027500,1.000000,-0.000400,0.000000,0.000000,-0.040700,0.999200,-0.000400,-0.999200,-0.040700 +MEG 2121,3024,0.000000,-0.110600,-0.027500,0.000000,0.040700,-0.999200,1.000000,-0.000400,0.000000,-0.000400,-0.999200,-0.040700 +MEG 2133,3012,0.017000,-0.109800,-0.061800,0.009200,-0.010800,-0.999899,0.985499,0.169500,0.007300,0.169404,-0.985467,0.012203 +MEG 2132,3012,0.017000,-0.109800,-0.061800,0.985499,0.169500,0.007300,-0.009200,0.010800,0.999899,0.169404,-0.985467,0.012203 +MEG 2131,3024,0.017000,-0.109800,-0.061800,0.009200,-0.010800,-0.999899,0.985499,0.169500,0.007300,0.169404,-0.985467,0.012203 +MEG 2143,3012,-0.017100,-0.109800,-0.061900,-0.006200,-0.012200,-0.999906,0.982706,-0.185001,-0.003800,-0.184937,-0.982638,0.013136 +MEG 2142,3012,-0.017100,-0.109800,-0.061900,0.982706,-0.185001,-0.003800,0.006200,0.012200,0.999906,-0.184937,-0.982638,0.013136 +MEG 2141,3024,-0.017100,-0.109800,-0.061900,-0.006200,-0.012200,-0.999906,0.982706,-0.185001,-0.003800,-0.184937,-0.982638,0.013136 +MEG 2212,3012,0.051700,-0.027600,0.092800,0.859962,0.026999,-0.509577,0.107595,0.966557,0.232790,0.498820,-0.255018,0.828297 +MEG 2213,3012,0.051700,-0.027600,0.092800,0.107595,0.966557,0.232790,-0.859962,-0.026999,0.509577,0.498820,-0.255018,0.828297 +MEG 2211,3024,0.051700,-0.027600,0.092800,0.859962,0.026999,-0.509577,0.107595,0.966557,0.232790,0.498820,-0.255018,0.828297 +MEG 2223,3012,0.078600,-0.028400,0.069800,0.627473,-0.042698,-0.777467,0.223290,0.966359,0.127195,0.745881,-0.253412,0.615898 +MEG 2222,3012,0.078600,-0.028400,0.069800,0.223290,0.966359,0.127195,-0.627473,0.042698,0.777467,0.745881,-0.253412,0.615898 +MEG 2221,3024,0.078600,-0.028400,0.069800,0.627473,-0.042698,-0.777467,0.223290,0.966359,0.127195,0.745881,-0.253412,0.615898 +MEG 2233,3012,0.055300,-0.062800,0.070600,0.377694,-0.493292,-0.783588,0.759388,0.649190,-0.042699,0.529761,-0.578920,0.619796 +MEG 2232,3012,0.055300,-0.062800,0.070600,0.759388,0.649190,-0.042699,-0.377694,0.493292,0.783588,0.529761,-0.578920,0.619796 +MEG 2231,3024,0.055300,-0.062800,0.070600,0.377694,-0.493292,-0.783588,0.759388,0.649190,-0.042699,0.529761,-0.578920,0.619796 +MEG 2242,3012,0.018200,-0.054200,0.092200,-0.069799,-0.841688,-0.535392,0.989086,0.011400,-0.146898,0.129746,-0.539803,0.831706 +MEG 2243,3012,0.018200,-0.054200,0.092200,0.989086,0.011400,-0.146898,0.069799,0.841688,0.535392,0.129746,-0.539803,0.831706 +MEG 2241,3024,0.018200,-0.054200,0.092200,-0.069799,-0.841688,-0.535392,0.989086,0.011400,-0.146898,0.129746,-0.539803,0.831706 +MEG 2312,3012,0.051300,-0.086100,0.039700,0.153007,-0.302213,-0.940940,0.880738,0.473520,-0.008900,0.448244,-0.827360,0.338622 +MEG 2313,3012,0.051300,-0.086100,0.039700,0.880738,0.473520,-0.008900,-0.153007,0.302213,0.940940,0.448244,-0.827360,0.338622 +MEG 2311,3024,0.051300,-0.086100,0.039700,0.153007,-0.302213,-0.940940,0.880738,0.473520,-0.008900,0.448244,-0.827360,0.338622 +MEG 2323,3012,0.063700,-0.088400,0.006200,0.056398,-0.071297,-0.995860,0.798667,0.601776,0.002200,0.599127,-0.795485,0.090881 +MEG 2322,3012,0.063700,-0.088400,0.006200,0.798667,0.601776,0.002200,-0.056398,0.071297,0.995860,0.599127,-0.795485,0.090881 +MEG 2321,3024,0.063700,-0.088400,0.006200,0.056398,-0.071297,-0.995860,0.798667,0.601776,0.002200,0.599127,-0.795485,0.090881 +MEG 2332,3012,0.033000,-0.105100,-0.027700,-0.004900,0.023300,-0.999715,0.951414,0.307905,0.002500,0.307875,-0.951130,-0.023677 +MEG 2333,3012,0.033000,-0.105100,-0.027700,0.951414,0.307905,0.002500,0.004900,-0.023300,0.999715,0.307875,-0.951130,-0.023677 +MEG 2331,3024,0.033000,-0.105100,-0.027700,-0.004900,0.023300,-0.999715,0.951414,0.307905,0.002500,0.307875,-0.951130,-0.023677 +MEG 2343,3012,0.033300,-0.103400,0.006300,0.041500,-0.123300,-0.991501,0.948001,0.318300,0.000100,0.315583,-0.939949,0.130098 +MEG 2342,3012,0.033300,-0.103400,0.006300,0.948001,0.318300,0.000100,-0.041500,0.123300,0.991501,0.315583,-0.939949,0.130098 +MEG 2341,3024,0.033300,-0.103400,0.006300,0.041500,-0.123300,-0.991501,0.948001,0.318300,0.000100,0.315583,-0.939949,0.130098 +MEG 2412,3012,0.095200,-0.030600,0.039200,0.323999,-0.063600,-0.943897,0.309099,0.950098,0.042100,0.894117,-0.305398,0.327489 +MEG 2413,3012,0.095200,-0.030600,0.039200,0.309099,0.950098,0.042100,-0.323999,0.063600,0.943897,0.894117,-0.305398,0.327489 +MEG 2411,3024,0.095200,-0.030600,0.039200,0.323999,-0.063600,-0.943897,0.309099,0.950098,0.042100,0.894117,-0.305398,0.327489 +MEG 2423,3012,0.101700,-0.033800,0.005800,0.066101,-0.028300,-0.997412,0.314004,0.949411,-0.006100,0.947126,-0.312788,0.071643 +MEG 2422,3012,0.101700,-0.033800,0.005800,0.314004,0.949411,-0.006100,-0.066101,0.028300,0.997412,0.947126,-0.312788,0.071643 +MEG 2421,3024,0.101700,-0.033800,0.005800,0.066101,-0.028300,-0.997412,0.314004,0.949411,-0.006100,0.947126,-0.312788,0.071643 +MEG 2433,3012,0.086600,-0.063900,0.005600,0.060099,-0.044799,-0.997187,0.549293,0.835589,-0.004400,0.833435,-0.547483,0.074826 +MEG 2432,3012,0.086600,-0.063900,0.005600,0.549293,0.835589,-0.004400,-0.060099,0.044799,0.997187,0.833435,-0.547483,0.074826 +MEG 2431,3024,0.086600,-0.063900,0.005600,0.060099,-0.044799,-0.997187,0.549293,0.835589,-0.004400,0.833435,-0.547483,0.074826 +MEG 2442,3012,0.078100,-0.062900,0.039400,0.259507,-0.203505,-0.944125,0.598716,0.800921,-0.008000,0.757798,-0.563187,0.329687 +MEG 2443,3012,0.078100,-0.062900,0.039400,0.598716,0.800921,-0.008000,-0.259507,0.203505,0.944125,0.757798,-0.563187,0.329687 +MEG 2441,3024,0.078100,-0.062900,0.039400,0.259507,-0.203505,-0.944125,0.598716,0.800921,-0.008000,0.757798,-0.563187,0.329687 +MEG 2512,3012,0.063000,-0.090600,-0.027600,-0.013600,0.025200,-0.999598,0.808198,0.588899,0.003800,0.588757,-0.807821,-0.028376 +MEG 2513,3012,0.063000,-0.090600,-0.027600,0.808198,0.588899,0.003800,0.013600,-0.025200,0.999598,0.588757,-0.807821,-0.028376 +MEG 2511,3024,0.063000,-0.090600,-0.027600,-0.013600,0.025200,-0.999598,0.808198,0.588899,0.003800,0.588757,-0.807821,-0.028376 +MEG 2522,3012,0.086100,-0.066100,-0.028000,-0.021299,0.011700,-0.999673,0.571385,0.820678,-0.002600,0.820380,-0.571254,-0.024165 +MEG 2523,3012,0.086100,-0.066100,-0.028000,0.571385,0.820678,-0.002600,0.021299,-0.011700,0.999673,0.820380,-0.571254,-0.024165 +MEG 2521,3024,0.086100,-0.066100,-0.028000,-0.021299,0.011700,-0.999673,0.571385,0.820678,-0.002600,0.820380,-0.571254,-0.024165 +MEG 2533,3012,0.075700,-0.079800,-0.062000,0.014300,-0.000900,-0.999897,0.690798,0.722998,0.009300,0.722916,-0.690860,0.010961 +MEG 2532,3012,0.075700,-0.079800,-0.062000,0.690798,0.722998,0.009300,-0.014300,0.000900,0.999897,0.722916,-0.690860,0.010961 +MEG 2531,3024,0.075700,-0.079800,-0.062000,0.014300,-0.000900,-0.999897,0.690798,0.722998,0.009300,0.722916,-0.690860,0.010961 +MEG 2543,3012,0.048800,-0.099400,-0.062100,0.011000,-0.007000,-0.999915,0.903014,0.429706,0.007000,0.429621,-0.903014,0.011048 +MEG 2542,3012,0.048800,-0.099400,-0.062100,0.903014,0.429706,0.007000,-0.011000,0.007000,0.999915,0.429621,-0.903014,0.011048 +MEG 2541,3024,0.048800,-0.099400,-0.062100,0.011000,-0.007000,-0.999915,0.903014,0.429706,0.007000,0.429621,-0.903014,0.011048 +MEG 2612,3012,0.108700,-0.003300,-0.028000,-0.020500,0.003400,-0.999813,0.081001,0.996713,0.001700,0.996532,-0.080951,-0.020708 +MEG 2613,3012,0.108700,-0.003300,-0.028000,0.081001,0.996713,0.001700,0.020500,-0.003400,0.999813,0.996532,-0.080951,-0.020708 +MEG 2611,3024,0.108700,-0.003300,-0.028000,-0.020500,0.003400,-0.999813,0.081001,0.996713,0.001700,0.996532,-0.080951,-0.020708 +MEG 2623,3012,0.106800,-0.020600,-0.062100,0.013100,0.004500,-0.999904,0.215701,0.976404,0.007200,0.976343,-0.215775,0.011820 +MEG 2622,3012,0.106800,-0.020600,-0.062100,0.215701,0.976404,0.007200,-0.013100,-0.004500,0.999904,0.976343,-0.215775,0.011820 +MEG 2621,3024,0.106800,-0.020600,-0.062100,0.013100,0.004500,-0.999904,0.215701,0.976404,0.007200,0.976343,-0.215775,0.011820 +MEG 2633,3012,0.095100,-0.052400,-0.062000,0.015200,0.003300,-0.999879,0.476590,0.879082,0.010100,0.879009,-0.476686,0.011789 +MEG 2632,3012,0.095100,-0.052400,-0.062000,0.476590,0.879082,0.010100,-0.015200,-0.003300,0.999879,0.879009,-0.476686,0.011789 +MEG 2631,3024,0.095100,-0.052400,-0.062000,0.015200,0.003300,-0.999879,0.476590,0.879082,0.010100,0.879009,-0.476686,0.011789 +MEG 2642,3012,0.101700,-0.036100,-0.027800,-0.027699,0.005300,-0.999573,0.341491,0.939874,-0.004500,0.939449,-0.341469,-0.027844 +MEG 2643,3012,0.101700,-0.036100,-0.027800,0.341491,0.939874,-0.004500,0.027699,-0.005300,0.999573,0.939449,-0.341469,-0.027844 +MEG 2641,3024,0.101700,-0.036100,-0.027800,-0.027699,0.005300,-0.999573,0.341491,0.939874,-0.004500,0.939449,-0.341469,-0.027844 diff --git a/mne-python/source/mne/channels/data/layouts/CTF-275.lout b/mne-python/source/mne/channels/data/layouts/CTF-275.lout new file mode 100644 index 0000000000000000000000000000000000000000..53d924c660c22128b76ed0dcc8568703c7f2c97a --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/CTF-275.lout @@ -0,0 +1,276 @@ + -42.27 42.33 -39.99 31.80 +001 -4.09 10.91 4.00 3.00 MLC11-2622 +002 -7.25 8.87 4.00 3.00 MLC12-2622 +003 -10.79 7.43 4.00 3.00 MLC13-2622 +004 -14.40 5.31 4.00 3.00 MLC14-2622 +005 -17.45 2.88 4.00 3.00 MLC15-2622 +006 -19.94 -0.21 4.00 3.00 MLC16-2622 +007 -22.30 -3.88 4.00 3.00 MLC17-2622 +008 -7.70 5.16 4.00 3.00 MLC21-2622 +009 -11.18 3.69 4.00 3.00 MLC22-2622 +010 -14.17 1.40 4.00 3.00 MLC23-2622 +011 -16.42 -1.52 4.00 3.00 MLC24-2622 +012 -18.64 -4.88 4.00 3.00 MLC25-2622 +013 -12.55 -2.00 4.00 3.00 MLC31-2622 +014 -15.13 -5.41 4.00 3.00 MLC32-2622 +015 -9.57 0.28 4.00 3.00 MLC41-2622 +016 -11.51 -5.56 4.00 3.00 MLC42-2622 +017 -4.04 4.58 4.00 3.00 MLC51-2622 +018 -6.04 1.35 4.00 3.00 MLC52-2622 +019 -8.79 -3.34 4.00 3.00 MLC53-2622 +020 -8.32 -7.10 4.00 3.00 MLC54-2622 +021 -6.60 -10.22 4.00 3.00 MLC55-2622 +022 -4.01 -1.76 4.00 3.00 MLC61-2622 +023 -5.55 -4.97 4.00 3.00 MLC62-2622 +024 -3.74 -8.12 4.00 3.00 MLC63-2622 +025 -7.63 28.14 4.00 3.00 MLF11-2622 +026 -12.92 27.01 4.00 3.00 MLF12-2622 +027 -18.14 25.41 4.00 3.00 MLF13-2622 +028 -23.34 23.65 4.00 3.00 MLF14-2622 +029 -4.64 25.47 4.00 3.00 MLF21-2622 +030 -9.22 24.68 4.00 3.00 MLF22-2622 +031 -13.60 23.41 4.00 3.00 MLF23-2622 +032 -18.31 21.53 4.00 3.00 MLF24-2622 +033 -22.68 19.69 4.00 3.00 MLF25-2622 +034 -6.57 22.14 4.00 3.00 MLF31-2622 +035 -10.75 21.22 4.00 3.00 MLF32-2622 +036 -15.16 19.49 4.00 3.00 MLF33-2622 +037 -19.01 17.57 4.00 3.00 MLF34-2622 +038 -22.93 15.25 4.00 3.00 MLF35-2622 +039 -4.25 19.38 4.00 3.00 MLF41-2622 +040 -8.17 18.80 4.00 3.00 MLF42-2622 +041 -12.29 17.37 4.00 3.00 MLF43-2622 +042 -15.93 15.49 4.00 3.00 MLF44-2622 +043 -19.89 13.39 4.00 3.00 MLF45-2622 +044 -24.12 10.50 4.00 3.00 MLF46-2622 +045 -5.48 16.15 4.00 3.00 MLF51-2622 +046 -9.58 15.10 4.00 3.00 MLF52-2622 +047 -13.17 13.43 4.00 3.00 MLF53-2622 +048 -16.66 11.39 4.00 3.00 MLF54-2622 +049 -20.76 9.06 4.00 3.00 MLF55-2622 +050 -24.71 5.73 4.00 3.00 MLF56-2622 +051 -7.17 12.78 4.00 3.00 MLF61-2622 +052 -10.58 11.08 4.00 3.00 MLF62-2622 +053 -13.93 9.16 4.00 3.00 MLF63-2622 +054 -17.37 7.29 4.00 3.00 MLF64-2622 +055 -20.83 4.87 4.00 3.00 MLF65-2622 +056 -23.40 1.59 4.00 3.00 MLF66-2622 +057 -25.90 -2.51 4.00 3.00 MLF67-2622 +058 -6.96 -27.32 4.00 3.00 MLO11-2622 +059 -11.88 -25.97 4.00 3.00 MLO12-2622 +060 -16.48 -23.69 4.00 3.00 MLO13-2622 +061 -20.64 -20.44 4.00 3.00 MLO14-2622 +062 -4.82 -30.75 4.00 3.00 MLO21-2622 +063 -10.11 -29.77 4.00 3.00 MLO22-2622 +064 -15.52 -27.87 4.00 3.00 MLO23-2622 +065 -20.40 -24.85 4.00 3.00 MLO24-2622 +066 -7.92 -33.45 4.00 3.00 MLO31-2622 +067 -13.84 -31.94 4.00 3.00 MLO32-2622 +068 -19.61 -29.16 4.00 3.00 MLO33-2622 +069 -24.70 -25.44 4.00 3.00 MLO34-2622 +070 -5.16 -36.86 4.00 3.00 MLO41-2622 +071 -11.67 -35.84 4.00 3.00 MLO42-2622 +072 -17.98 -33.55 4.00 3.00 MLO43-2622 +073 -23.91 -30.00 4.00 3.00 MLO44-2622 +074 -8.79 -39.34 4.00 3.00 MLO51-2622 +075 -15.83 -37.54 4.00 3.00 MLO52-2622 +076 -22.47 -34.34 4.00 3.00 MLO53-2622 +077 -4.98 -13.36 4.00 3.00 MLP11-2622 +078 -10.20 -10.01 4.00 3.00 MLP12-2622 +079 -3.80 -16.69 4.00 3.00 MLP21-2622 +080 -8.73 -13.30 4.00 3.00 MLP22-2622 +081 -13.58 -8.80 4.00 3.00 MLP23-2622 +082 -5.66 -19.72 4.00 3.00 MLP31-2622 +083 -8.41 -16.83 4.00 3.00 MLP32-2622 +084 -12.08 -14.80 4.00 3.00 MLP33-2622 +085 -15.13 -11.95 4.00 3.00 MLP34-2622 +086 -17.18 -8.63 4.00 3.00 MLP35-2622 +087 -9.92 -20.16 4.00 3.00 MLP41-2622 +088 -13.37 -18.09 4.00 3.00 MLP42-2622 +089 -16.59 -15.58 4.00 3.00 MLP43-2622 +090 -19.06 -11.87 4.00 3.00 MLP44-2622 +091 -20.87 -8.06 4.00 3.00 MLP45-2622 +092 -4.02 -24.07 4.00 3.00 MLP51-2622 +093 -8.77 -23.79 4.00 3.00 MLP52-2622 +094 -12.92 -22.08 4.00 3.00 MLP53-2622 +095 -16.83 -19.50 4.00 3.00 MLP54-2622 +096 -20.23 -16.32 4.00 3.00 MLP55-2622 +097 -22.76 -11.97 4.00 3.00 MLP56-2622 +098 -24.58 -7.58 4.00 3.00 MLP57-2622 +099 -27.14 12.98 4.00 3.00 MLT11-2622 +100 -28.19 7.51 4.00 3.00 MLT12-2622 +101 -28.08 2.09 4.00 3.00 MLT13-2622 +102 -28.56 -5.98 4.00 3.00 MLT14-2622 +103 -26.96 -11.17 4.00 3.00 MLT15-2622 +104 -24.11 -16.46 4.00 3.00 MLT16-2622 +105 -27.30 17.85 4.00 3.00 MLT21-2622 +106 -31.47 10.04 4.00 3.00 MLT22-2622 +107 -31.85 3.70 4.00 3.00 MLT23-2622 +108 -32.08 -2.62 4.00 3.00 MLT24-2622 +109 -31.09 -9.80 4.00 3.00 MLT25-2622 +110 -28.71 -15.38 4.00 3.00 MLT26-2622 +111 -24.78 -20.78 4.00 3.00 MLT27-2622 +112 -28.61 21.64 4.00 3.00 MLT31-2622 +113 -32.09 15.32 4.00 3.00 MLT32-2622 +114 -35.40 5.79 4.00 3.00 MLT33-2622 +115 -35.85 -1.29 4.00 3.00 MLT34-2622 +116 -34.97 -7.76 4.00 3.00 MLT35-2622 +117 -32.89 -13.91 4.00 3.00 MLT36-2622 +118 -29.32 -20.20 4.00 3.00 MLT37-2622 +119 -33.87 18.93 4.00 3.00 MLT41-2622 +120 -36.68 11.37 4.00 3.00 MLT42-2622 +121 -38.92 2.11 4.00 3.00 MLT43-2622 +122 -38.70 -5.16 4.00 3.00 MLT44-2622 +123 -36.95 -12.13 4.00 3.00 MLT45-2622 +124 -33.72 -18.79 4.00 3.00 MLT46-2622 +125 -29.28 -25.28 4.00 3.00 MLT47-2622 +126 -38.78 14.74 4.00 3.00 MLT51-2622 +127 -41.29 6.62 4.00 3.00 MLT52-2622 +128 -41.87 -1.80 4.00 3.00 MLT53-2622 +129 -40.62 -9.63 4.00 3.00 MLT54-2622 +130 -37.78 -16.89 4.00 3.00 MLT55-2622 +131 -33.73 -24.02 4.00 3.00 MLT56-2622 +132 -28.51 -29.92 4.00 3.00 MLT57-2622 +133 -0.24 10.97 4.00 3.00 MRC11-2622 +134 2.99 8.95 4.00 3.00 MRC12-2622 +135 6.57 7.62 4.00 3.00 MRC13-2622 +136 10.22 5.56 4.00 3.00 MRC14-2622 +137 13.27 3.22 4.00 3.00 MRC15-2622 +138 15.86 0.21 4.00 3.00 MRC16-2622 +139 18.32 -3.45 4.00 3.00 MRC17-2622 +140 3.53 5.28 4.00 3.00 MRC21-2622 +141 7.00 3.85 4.00 3.00 MRC22-2622 +142 10.06 1.68 4.00 3.00 MRC23-2622 +143 12.33 -1.20 4.00 3.00 MRC24-2622 +144 14.73 -4.52 4.00 3.00 MRC25-2622 +145 8.51 -1.76 4.00 3.00 MRC31-2622 +146 11.17 -5.14 4.00 3.00 MRC32-2622 +147 5.51 0.46 4.00 3.00 MRC41-2622 +148 7.56 -5.33 4.00 3.00 MRC42-2622 +149 -0.17 4.62 4.00 3.00 MRC51-2622 +150 1.93 1.46 4.00 3.00 MRC52-2622 +151 4.78 -3.16 4.00 3.00 MRC53-2622 +152 4.39 -6.98 4.00 3.00 MRC54-2622 +153 2.73 -10.10 4.00 3.00 MRC55-2622 +154 -0.07 -1.75 4.00 3.00 MRC61-2622 +155 1.58 -4.86 4.00 3.00 MRC62-2622 +156 -0.15 -8.08 4.00 3.00 MRC63-2622 +157 2.97 28.24 4.00 3.00 MRF11-2622 +158 8.25 27.25 4.00 3.00 MRF12-2622 +159 13.54 25.74 4.00 3.00 MRF13-2622 +160 18.74 24.12 4.00 3.00 MRF14-2622 +161 0.03 25.52 4.00 3.00 MRF21-2622 +162 4.63 24.85 4.00 3.00 MRF22-2622 +163 9.03 23.67 4.00 3.00 MRF23-2622 +164 13.78 21.87 4.00 3.00 MRF24-2622 +165 18.19 20.13 4.00 3.00 MRF25-2622 +166 2.05 22.22 4.00 3.00 MRF31-2622 +167 6.27 21.38 4.00 3.00 MRF32-2622 +168 10.63 19.79 4.00 3.00 MRF33-2622 +169 14.57 17.90 4.00 3.00 MRF34-2622 +170 18.54 15.70 4.00 3.00 MRF35-2622 +171 -0.22 19.42 4.00 3.00 MRF41-2622 +172 3.75 18.84 4.00 3.00 MRF42-2622 +173 7.86 17.57 4.00 3.00 MRF43-2622 +174 11.53 15.78 4.00 3.00 MRF44-2622 +175 15.55 13.76 4.00 3.00 MRF45-2622 +176 19.83 10.96 4.00 3.00 MRF46-2622 +177 1.08 16.23 4.00 3.00 MRF51-2622 +178 5.20 15.33 4.00 3.00 MRF52-2622 +179 8.81 13.68 4.00 3.00 MRF53-2622 +180 12.37 11.71 4.00 3.00 MRF54-2622 +181 16.53 9.44 4.00 3.00 MRF55-2622 +182 20.54 6.21 4.00 3.00 MRF56-2622 +183 2.82 12.87 4.00 3.00 MRF61-2622 +184 6.27 11.29 4.00 3.00 MRF62-2622 +185 9.66 9.43 4.00 3.00 MRF63-2622 +186 13.14 7.59 4.00 3.00 MRF64-2622 +187 16.52 5.22 4.00 3.00 MRF65-2622 +188 19.31 2.05 4.00 3.00 MRF66-2622 +189 21.91 -1.92 4.00 3.00 MRF67-2622 +190 3.46 -27.20 4.00 3.00 MRO11-2622 +191 8.35 -25.76 4.00 3.00 MRO12-2622 +192 12.92 -23.40 4.00 3.00 MRO13-2622 +193 17.02 -20.06 4.00 3.00 MRO14-2622 +194 1.43 -30.69 4.00 3.00 MRO21-2622 +195 6.66 -29.60 4.00 3.00 MRO22-2622 +196 12.02 -27.57 4.00 3.00 MRO23-2622 +197 16.88 -24.46 4.00 3.00 MRO24-2622 +198 4.55 -33.35 4.00 3.00 MRO31-2622 +199 10.46 -31.70 4.00 3.00 MRO32-2622 +200 16.07 -28.88 4.00 3.00 MRO33-2622 +201 21.16 -24.93 4.00 3.00 MRO34-2622 +202 1.88 -36.78 4.00 3.00 MRO41-2622 +203 8.37 -35.64 4.00 3.00 MRO42-2622 +204 14.63 -33.19 4.00 3.00 MRO43-2622 +205 20.45 -29.57 4.00 3.00 MRO44-2622 +206 5.57 -39.20 4.00 3.00 MRO51-2622 +207 12.57 -37.26 4.00 3.00 MRO52-2622 +208 19.11 -33.96 4.00 3.00 MRO53-2622 +209 1.20 -13.27 4.00 3.00 MRP11-2622 +210 6.34 -9.81 4.00 3.00 MRP12-2622 +211 0.06 -16.65 4.00 3.00 MRP21-2622 +212 4.94 -13.15 4.00 3.00 MRP22-2622 +213 9.72 -8.56 4.00 3.00 MRP23-2622 +214 2.03 -19.64 4.00 3.00 MRP31-2622 +215 4.72 -16.72 4.00 3.00 MRP32-2622 +216 8.28 -14.64 4.00 3.00 MRP33-2622 +217 11.32 -11.68 4.00 3.00 MRP34-2622 +218 13.30 -8.29 4.00 3.00 MRP35-2622 +219 6.32 -19.99 4.00 3.00 MRP41-2622 +220 9.66 -17.86 4.00 3.00 MRP42-2622 +221 12.83 -15.29 4.00 3.00 MRP43-2622 +222 15.21 -11.53 4.00 3.00 MRP44-2622 +223 16.99 -7.64 4.00 3.00 MRP45-2622 +224 0.42 -24.03 4.00 3.00 MRP51-2622 +225 5.29 -23.71 4.00 3.00 MRP52-2622 +226 9.32 -21.86 4.00 3.00 MRP53-2622 +227 13.19 -19.21 4.00 3.00 MRP54-2622 +228 16.49 -15.99 4.00 3.00 MRP55-2622 +229 18.98 -11.54 4.00 3.00 MRP56-2622 +230 20.69 -7.11 4.00 3.00 MRP57-2622 +231 22.81 13.51 4.00 3.00 MRT11-2622 +232 23.97 8.09 4.00 3.00 MRT12-2622 +233 23.97 2.65 4.00 3.00 MRT13-2622 +234 24.63 -5.42 4.00 3.00 MRT14-2622 +235 23.16 -10.65 4.00 3.00 MRT15-2622 +236 20.37 -16.02 4.00 3.00 MRT16-2622 +237 22.88 18.38 4.00 3.00 MRT21-2622 +238 27.23 10.62 4.00 3.00 MRT22-2622 +239 27.73 4.35 4.00 3.00 MRT23-2622 +240 28.08 -1.95 4.00 3.00 MRT24-2622 +241 27.24 -9.21 4.00 3.00 MRT25-2622 +242 24.97 -14.84 4.00 3.00 MRT26-2622 +243 21.15 -20.30 4.00 3.00 MRT27-2622 +244 24.07 22.26 4.00 3.00 MRT31-2622 +245 27.72 15.94 4.00 3.00 MRT32-2622 +246 31.24 6.55 4.00 3.00 MRT33-2622 +247 31.84 -0.55 4.00 3.00 MRT34-2622 +248 31.09 -7.10 4.00 3.00 MRT35-2622 +249 29.13 -13.33 4.00 3.00 MRT36-2622 +250 25.63 -19.73 4.00 3.00 MRT37-2622 +251 29.40 19.66 4.00 3.00 MRT41-2622 +252 32.38 12.17 4.00 3.00 MRT42-2622 +253 34.86 2.97 4.00 3.00 MRT43-2622 +254 34.80 -4.39 4.00 3.00 MRT44-2622 +255 33.11 -11.36 4.00 3.00 MRT45-2622 +256 30.03 -18.16 4.00 3.00 MRT46-2622 +257 25.54 -24.88 4.00 3.00 MRT47-2622 +258 34.47 15.52 4.00 3.00 MRT51-2622 +259 37.12 7.54 4.00 3.00 MRT52-2622 +260 37.93 -0.94 4.00 3.00 MRT53-2622 +261 36.82 -8.89 4.00 3.00 MRT54-2622 +262 34.10 -16.25 4.00 3.00 MRT55-2622 +263 30.13 -23.45 4.00 3.00 MRT56-2622 +264 25.07 -29.43 4.00 3.00 MRT57-2622 +265 -2.13 7.84 4.00 3.00 MZC01-2622 +266 -2.05 1.38 4.00 3.00 MZC02-2622 +267 -1.99 -5.04 4.00 3.00 MZC03-2622 +268 -1.93 -11.44 4.00 3.00 MZC04-2622 +269 -2.33 28.50 4.00 3.00 MZF01-2622 +270 -2.28 22.54 4.00 3.00 MZF02-2622 +271 -2.20 14.52 4.00 3.00 MZF03-2622 +272 -1.77 -27.22 4.00 3.00 MZO01-2622 +273 -1.71 -34.04 4.00 3.00 MZO02-2622 +274 -1.66 -39.69 4.00 3.00 MZO03-2622 +275 -1.81 -21.05 4.00 3.00 MZP01-2622 diff --git a/mne-python/source/mne/channels/data/layouts/CTF151.lay b/mne-python/source/mne/channels/data/layouts/CTF151.lay new file mode 100644 index 0000000000000000000000000000000000000000..c9d68f31661a8f4fd2c4a57873302124dc8fd95c --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/CTF151.lay @@ -0,0 +1,153 @@ +1 -0.440000 -4.000000 0.551100 0.351100 MLC11 +2 -1.200000 -4.130000 0.551100 0.351100 MLC12 +3 -2.220000 -4.270000 0.551100 0.351100 MLC13 +4 -2.820000 -4.710000 0.551100 0.351100 MLC14 +5 -3.340000 -5.230000 0.551100 0.351100 MLC15 +6 -0.820000 -4.550000 0.551100 0.351100 MLC21 +7 -1.620000 -4.570000 0.551100 0.351100 MLC22 +8 -2.160000 -4.970000 0.551100 0.351100 MLC23 +9 -2.640000 -5.370000 0.551100 0.351100 MLC24 +10 -1.270000 -5.050000 0.551100 0.351100 MLC31 +11 -1.780000 -5.450000 0.551100 0.351100 MLC32 +12 -1.300000 -5.930000 0.551100 0.351100 MLC33 +13 -0.440000 -5.050000 0.551100 0.351100 MLC41 +14 -0.820000 -5.530000 0.551100 0.351100 MLC42 +15 -0.400000 -6.010000 0.551100 0.351100 MLC43 +16 -1.170000 -2.010000 0.551100 0.351100 MLF11 +17 -2.260000 -2.230000 0.551100 0.351100 MLF12 +18 -0.490000 -2.300000 0.551100 0.351100 MLF21 +19 -1.540000 -2.470000 0.551100 0.351100 MLF22 +20 -2.540000 -2.750000 0.551100 0.351100 MLF23 +21 -1.000000 -2.750000 0.551100 0.351100 MLF31 +22 -1.950000 -2.980000 0.551100 0.351100 MLF32 +23 -2.780000 -3.300000 0.551100 0.351100 MLF33 +24 -3.440000 -3.770000 0.551100 0.351100 MLF34 +25 -0.450000 -3.100000 0.551100 0.351100 MLF41 +26 -1.380000 -3.260000 0.551100 0.351100 MLF42 +27 -2.280000 -3.570000 0.551100 0.351100 MLF43 +28 -2.870000 -4.060000 0.551100 0.351100 MLF44 +29 -3.500000 -4.510000 0.551100 0.351100 MLF45 +30 -0.850000 -3.580000 0.551100 0.351100 MLF51 +31 -1.700000 -3.790000 0.551100 0.351100 MLF52 +32 -0.470000 -7.690000 0.551100 0.351100 MLO11 +33 -1.650000 -7.420000 0.551100 0.351100 MLO12 +34 -1.210000 -7.930000 0.551100 0.351100 MLO21 +35 -2.350000 -7.580000 0.551100 0.351100 MLO22 +36 -0.600000 -8.400000 0.551100 0.351100 MLO31 +37 -1.920000 -8.120000 0.551100 0.351100 MLO32 +38 -3.110000 -7.670000 0.551100 0.351100 MLO33 +39 -1.400000 -8.560000 0.551100 0.351100 MLO41 +40 -2.750000 -8.210000 0.551100 0.351100 MLO42 +41 -3.910000 -7.620000 0.551100 0.351100 MLO43 +42 -0.840000 -6.390000 0.551100 0.351100 MLP11 +43 -1.710000 -6.320000 0.551100 0.351100 MLP12 +44 -2.240000 -5.870000 0.551100 0.351100 MLP13 +45 -0.440000 -6.900000 0.551100 0.351100 MLP21 +46 -1.220000 -6.760000 0.551100 0.351100 MLP22 +47 -0.970000 -7.220000 0.551100 0.351100 MLP31 +48 -1.900000 -6.880000 0.551100 0.351100 MLP32 +49 -2.470000 -6.390000 0.551100 0.351100 MLP33 +50 -2.990000 -5.850000 0.551100 0.351100 MLP34 +51 -3.420000 -3.120000 0.551100 0.351100 MLT11 +52 -4.100000 -4.200000 0.551100 0.351100 MLT12 +53 -4.040000 -5.030000 0.551100 0.351100 MLT13 +54 -3.780000 -5.770000 0.551100 0.351100 MLT14 +55 -3.210000 -6.440000 0.551100 0.351100 MLT15 +56 -2.570000 -7.010000 0.551100 0.351100 MLT16 +57 -3.320000 -2.550000 0.551100 0.351100 MLT21 +58 -4.260000 -3.520000 0.551100 0.351100 MLT22 +59 -4.720000 -4.710000 0.551100 0.351100 MLT23 +60 -4.520000 -5.590000 0.551100 0.351100 MLT24 +61 -4.040000 -6.350000 0.551100 0.351100 MLT25 +62 -3.280000 -7.060000 0.551100 0.351100 MLT26 +63 -4.340000 -2.900000 0.551100 0.351100 MLT31 +64 -5.040000 -4.050000 0.551100 0.351100 MLT32 +65 -5.200000 -5.210000 0.551100 0.351100 MLT33 +66 -4.820000 -6.140000 0.551100 0.351100 MLT34 +67 -4.090000 -7.000000 0.551100 0.351100 MLT35 +68 -5.210000 -3.450000 0.551100 0.351100 MLT41 +69 -5.640000 -4.620000 0.551100 0.351100 MLT42 +70 -5.500000 -5.730000 0.551100 0.351100 MLT43 +71 -4.910000 -6.720000 0.551100 0.351100 MLT44 +72 0.410000 -4.000000 0.551100 0.351100 MRC11 +73 1.170000 -4.130000 0.551100 0.351100 MRC12 +74 2.200000 -4.270000 0.551100 0.351100 MRC13 +75 2.800000 -4.710000 0.551100 0.351100 MRC14 +76 3.320000 -5.230000 0.551100 0.351100 MRC15 +77 0.800000 -4.560000 0.551100 0.351100 MRC21 +78 1.600000 -4.570000 0.551100 0.351100 MRC22 +79 2.140000 -4.970000 0.551100 0.351100 MRC23 +80 2.620000 -5.370000 0.551100 0.351100 MRC24 +81 1.260000 -5.050000 0.551100 0.351100 MRC31 +82 1.760000 -5.450000 0.551100 0.351100 MRC32 +83 1.280000 -5.930000 0.551100 0.351100 MRC33 +84 0.420000 -5.050000 0.551100 0.351100 MRC41 +85 0.810000 -5.540000 0.551100 0.351100 MRC42 +86 0.380000 -6.010000 0.551100 0.351100 MRC43 +87 1.130000 -2.010000 0.551100 0.351100 MRF11 +88 2.240000 -2.230000 0.551100 0.351100 MRF12 +89 0.460000 -2.290000 0.551100 0.351100 MRF21 +90 1.510000 -2.470000 0.551100 0.351100 MRF22 +91 2.520000 -2.740000 0.551100 0.351100 MRF23 +92 0.970000 -2.740000 0.551100 0.351100 MRF31 +93 1.920000 -2.980000 0.551100 0.351100 MRF32 +94 2.760000 -3.300000 0.551100 0.351100 MRF33 +95 3.420000 -3.770000 0.551100 0.351100 MRF34 +96 0.420000 -3.100000 0.551100 0.351100 MRF41 +97 1.360000 -3.260000 0.551100 0.351100 MRF42 +98 2.260000 -3.570000 0.551100 0.351100 MRF43 +99 2.840000 -4.050000 0.551100 0.351100 MRF44 +100 3.480000 -4.510000 0.551100 0.351100 MRF45 +101 0.820000 -3.580000 0.551100 0.351100 MRF51 +102 1.670000 -3.790000 0.551100 0.351100 MRF52 +103 0.470000 -7.690000 0.551100 0.351100 MRO11 +104 1.640000 -7.420000 0.551100 0.351100 MRO12 +105 1.200000 -7.930000 0.551100 0.351100 MRO21 +106 2.350000 -7.580000 0.551100 0.351100 MRO22 +107 0.580000 -8.390000 0.551100 0.351100 MRO31 +108 1.910000 -8.110000 0.551100 0.351100 MRO32 +109 3.110000 -7.670000 0.551100 0.351100 MRO33 +110 1.380000 -8.570000 0.551100 0.351100 MRO41 +111 2.750000 -8.220000 0.551100 0.351100 MRO42 +112 3.900000 -7.610000 0.551100 0.351100 MRO43 +113 0.820000 -6.380000 0.551100 0.351100 MRP11 +114 1.700000 -6.320000 0.551100 0.351100 MRP12 +115 2.220000 -5.870000 0.551100 0.351100 MRP13 +116 0.420000 -6.900000 0.551100 0.351100 MRP21 +117 1.200000 -6.750000 0.551100 0.351100 MRP22 +118 0.960000 -7.220000 0.551100 0.351100 MRP31 +119 1.880000 -6.870000 0.551100 0.351100 MRP32 +120 2.470000 -6.390000 0.551100 0.351100 MRP33 +121 2.990000 -5.850000 0.551100 0.351100 MRP34 +122 3.390000 -3.120000 0.551100 0.351100 MRT11 +123 4.070000 -4.190000 0.551100 0.351100 MRT12 +124 4.020000 -5.030000 0.551100 0.351100 MRT13 +125 3.760000 -5.770000 0.551100 0.351100 MRT14 +126 3.200000 -6.430000 0.551100 0.351100 MRT15 +127 2.570000 -7.010000 0.551100 0.351100 MRT16 +128 3.300000 -2.540000 0.551100 0.351100 MRT21 +129 4.230000 -3.510000 0.551100 0.351100 MRT22 +130 4.700000 -4.710000 0.551100 0.351100 MRT23 +131 4.500000 -5.590000 0.551100 0.351100 MRT24 +132 4.020000 -6.360000 0.551100 0.351100 MRT25 +133 3.260000 -7.060000 0.551100 0.351100 MRT26 +134 4.310000 -2.900000 0.551100 0.351100 MRT31 +135 5.020000 -4.050000 0.551100 0.351100 MRT32 +136 5.180000 -5.210000 0.551100 0.351100 MRT33 +137 4.800000 -6.140000 0.551100 0.351100 MRT34 +138 4.080000 -7.000000 0.551100 0.351100 MRT35 +139 5.200000 -3.450000 0.551100 0.351100 MRT41 +140 5.620000 -4.610000 0.551100 0.351100 MRT42 +141 5.480000 -5.730000 0.551100 0.351100 MRT43 +142 4.900000 -6.710000 0.551100 0.351100 MRT44 +143 0.000000 -4.510000 0.551100 0.351100 MZC01 +144 0.000000 -5.550000 0.551100 0.351100 MZC02 +145 0.000000 -1.930000 0.551100 0.351100 MZF01 +146 0.000000 -2.660000 0.551100 0.351100 MZF02 +147 0.000000 -3.510000 0.551100 0.351100 MZF03 +148 0.000000 -8.050000 0.551100 0.351100 MZO01 +149 0.000000 -8.660000 0.551100 0.351100 MZO02 +150 0.000000 -6.470000 0.551100 0.351100 MZP01 +151 0.000000 -7.290000 0.551100 0.351100 MZP02 +152 5.000000 -2.000000 0.551100 0.351100 SCALE +153 -5.50000 -1.500000 0.551100 0.351100 COMNT diff --git a/mne-python/source/mne/channels/data/layouts/CTF275.lay b/mne-python/source/mne/channels/data/layouts/CTF275.lay new file mode 100644 index 0000000000000000000000000000000000000000..2af28d3557dad8234b50a6a8b2a11a65f1ffa9e8 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/CTF275.lay @@ -0,0 +1,275 @@ +1 -0.029414 0.428191 0.100000 0.040000 MLC11 +2 -0.105398 0.378716 0.100000 0.040000 MLC12 +3 -0.187924 0.341472 0.100000 0.040000 MLC13 +4 -0.268071 0.285079 0.100000 0.040000 MLC14 +5 -0.330692 0.221374 0.100000 0.040000 MLC15 +6 -0.378697 0.144627 0.100000 0.040000 MLC16 +7 -0.411309 0.049716 0.100000 0.040000 MLC17 +8 -0.112105 0.295427 0.100000 0.040000 MLC21 +9 -0.189457 0.259287 0.100000 0.040000 MLC22 +10 -0.254180 0.203140 0.100000 0.040000 MLC23 +11 -0.298355 0.137997 0.100000 0.040000 MLC24 +12 -0.337649 0.050767 0.100000 0.040000 MLC25 +13 -0.213750 0.138862 0.100000 0.040000 MLC31 +14 -0.266243 0.056433 0.100000 0.040000 MLC32 +15 -0.150010 0.191395 0.100000 0.040000 MLC41 +16 -0.188739 0.067511 0.100000 0.040000 MLC42 +17 -0.027405 0.285532 0.100000 0.040000 MLC51 +18 -0.072194 0.217381 0.100000 0.040000 MLC52 +19 -0.130467 0.119358 0.100000 0.040000 MLC53 +20 -0.119656 0.041473 0.100000 0.040000 MLC54 +21 -0.083927 -0.021961 0.100000 0.040000 MLC55 +22 -0.027810 0.155198 0.100000 0.040000 MLC61 +23 -0.062042 0.088583 0.100000 0.040000 MLC62 +24 -0.025587 0.023975 0.100000 0.040000 MLC63 +25 -0.154623 0.879985 0.100000 0.040000 MLF11 +26 -0.322264 0.823233 0.100000 0.040000 MLF12 +27 -0.478342 0.740223 0.100000 0.040000 MLF13 +28 -0.622338 0.633371 0.100000 0.040000 MLF14 +29 -0.052995 0.810917 0.100000 0.040000 MLF21 +30 -0.193258 0.778479 0.100000 0.040000 MLF22 +31 -0.319702 0.726613 0.100000 0.040000 MLF23 +32 -0.447065 0.639878 0.100000 0.040000 MLF24 +33 -0.551024 0.545805 0.100000 0.040000 MLF25 +34 -0.106993 0.717661 0.100000 0.040000 MLF31 +35 -0.227303 0.683510 0.100000 0.040000 MLF32 +36 -0.344973 0.613898 0.100000 0.040000 MLF33 +37 -0.437794 0.535071 0.100000 0.040000 MLF34 +38 -0.516944 0.440135 0.100000 0.040000 MLF35 +39 -0.037498 0.646457 0.100000 0.040000 MLF41 +40 -0.145663 0.629747 0.100000 0.040000 MLF42 +41 -0.257022 0.575998 0.100000 0.040000 MLF43 +42 -0.344741 0.511350 0.100000 0.040000 MLF44 +43 -0.434608 0.430669 0.100000 0.040000 MLF45 +44 -0.512928 0.325699 0.100000 0.040000 MLF46 +45 -0.065241 0.564676 0.100000 0.040000 MLF51 +46 -0.176866 0.530203 0.100000 0.040000 MLF52 +47 -0.264799 0.476609 0.100000 0.040000 MLF53 +48 -0.344149 0.409817 0.100000 0.040000 MLF54 +49 -0.432009 0.328939 0.100000 0.040000 MLF55 +50 -0.502082 0.225317 0.100000 0.040000 MLF56 +51 -0.108196 0.473300 0.100000 0.040000 MLF61 +52 -0.191454 0.428184 0.100000 0.040000 MLF62 +53 -0.268505 0.371569 0.100000 0.040000 MLF63 +54 -0.343162 0.314227 0.100000 0.040000 MLF64 +55 -0.415355 0.241209 0.100000 0.040000 MLF65 +56 -0.459435 0.157639 0.100000 0.040000 MLF66 +57 -0.484998 0.050963 0.100000 0.040000 MLF67 +58 -0.086701 -0.382545 0.100000 0.040000 MLO11 +59 -0.173621 -0.361571 0.100000 0.040000 MLO12 +60 -0.257557 -0.329066 0.100000 0.040000 MLO13 +61 -0.337129 -0.278810 0.100000 0.040000 MLO14 +62 -0.050176 -0.456757 0.100000 0.040000 MLO21 +63 -0.138937 -0.440153 0.100000 0.040000 MLO22 +64 -0.234625 -0.414329 0.100000 0.040000 MLO23 +65 -0.323700 -0.370345 0.100000 0.040000 MLO24 +66 -0.099528 -0.519048 0.100000 0.040000 MLO31 +67 -0.201576 -0.499713 0.100000 0.040000 MLO32 +68 -0.300736 -0.464088 0.100000 0.040000 MLO33 +69 -0.395767 -0.412426 0.100000 0.040000 MLO34 +70 -0.054171 -0.598130 0.100000 0.040000 MLO41 +71 -0.162924 -0.587463 0.100000 0.040000 MLO42 +72 -0.270457 -0.559057 0.100000 0.040000 MLO43 +73 -0.375045 -0.514503 0.100000 0.040000 MLO44 +74 -0.114841 -0.674066 0.100000 0.040000 MLO51 +75 -0.232779 -0.654920 0.100000 0.040000 MLO52 +76 -0.347032 -0.617457 0.100000 0.040000 MLO53 +77 -0.050706 -0.086860 0.100000 0.040000 MLP11 +78 -0.157880 -0.022819 0.100000 0.040000 MLP12 +79 -0.027384 -0.156541 0.100000 0.040000 MLP21 +80 -0.125969 -0.090281 0.100000 0.040000 MLP22 +81 -0.229468 -0.007021 0.100000 0.040000 MLP23 +82 -0.063851 -0.221282 0.100000 0.040000 MLP31 +83 -0.117483 -0.164444 0.100000 0.040000 MLP32 +84 -0.191075 -0.130343 0.100000 0.040000 MLP33 +85 -0.256310 -0.076997 0.100000 0.040000 MLP34 +86 -0.301408 -0.017428 0.100000 0.040000 MLP35 +87 -0.145628 -0.236552 0.100000 0.040000 MLP41 +88 -0.211609 -0.201084 0.100000 0.040000 MLP42 +89 -0.277557 -0.161143 0.100000 0.040000 MLP43 +90 -0.330491 -0.093163 0.100000 0.040000 MLP44 +91 -0.372987 -0.024823 0.100000 0.040000 MLP45 +92 -0.032003 -0.311166 0.100000 0.040000 MLP51 +93 -0.120201 -0.309697 0.100000 0.040000 MLP52 +94 -0.197411 -0.282930 0.100000 0.040000 MLP53 +95 -0.273221 -0.242434 0.100000 0.040000 MLP54 +96 -0.341326 -0.192353 0.100000 0.040000 MLP55 +97 -0.397869 -0.117824 0.100000 0.040000 MLP56 +98 -0.439023 -0.040798 0.100000 0.040000 MLP57 +99 -0.600517 0.341742 0.100000 0.040000 MLT11 +100 -0.583854 0.221014 0.100000 0.040000 MLT12 +101 -0.546672 0.118228 0.100000 0.040000 MLT13 +102 -0.525679 -0.043954 0.100000 0.040000 MLT14 +103 -0.482366 -0.132402 0.100000 0.040000 MLT15 +104 -0.408785 -0.217740 0.100000 0.040000 MLT16 +105 -0.657080 0.441193 0.100000 0.040000 MLT21 +106 -0.681569 0.225254 0.100000 0.040000 MLT22 +107 -0.647357 0.101107 0.100000 0.040000 MLT23 +108 -0.618158 -0.017119 0.100000 0.040000 MLT24 +109 -0.570925 -0.147553 0.100000 0.040000 MLT25 +110 -0.505869 -0.237678 0.100000 0.040000 MLT26 +111 -0.406336 -0.310886 0.100000 0.040000 MLT27 +112 -0.758025 0.508412 0.100000 0.040000 MLT31 +113 -0.761740 0.316423 0.100000 0.040000 MLT32 +114 -0.751268 0.088675 0.100000 0.040000 MLT33 +115 -0.712573 -0.047448 0.100000 0.040000 MLT34 +116 -0.658112 -0.159355 0.100000 0.040000 MLT35 +117 -0.592395 -0.256839 0.100000 0.040000 MLT36 +118 -0.495312 -0.345113 0.100000 0.040000 MLT37 +119 -0.885393 0.353401 0.100000 0.040000 MLT41 +120 -0.847844 0.160648 0.100000 0.040000 MLT42 +121 -0.823787 -0.043736 0.100000 0.040000 MLT43 +122 -0.758805 -0.175411 0.100000 0.040000 MLT44 +123 -0.684634 -0.280647 0.100000 0.040000 MLT45 +124 -0.591783 -0.373867 0.100000 0.040000 MLT46 +125 -0.476572 -0.454666 0.100000 0.040000 MLT47 +126 -0.983285 0.161080 0.100000 0.040000 MLT51 +127 -0.944753 -0.028756 0.100000 0.040000 MLT52 +128 -0.872989 -0.188195 0.100000 0.040000 MLT53 +129 -0.785517 -0.310620 0.100000 0.040000 MLT54 +130 -0.688014 -0.407791 0.100000 0.040000 MLT55 +131 -0.571347 -0.497554 0.100000 0.040000 MLT56 +132 -0.457303 -0.565438 0.100000 0.040000 MLT57 +133 0.063389 0.426606 0.100000 0.040000 MRC11 +134 0.137902 0.375428 0.100000 0.040000 MRC12 +135 0.219516 0.336386 0.100000 0.040000 MRC13 +136 0.297688 0.277771 0.100000 0.040000 MRC14 +137 0.355955 0.213304 0.100000 0.040000 MRC15 +138 0.404150 0.135598 0.100000 0.040000 MRC16 +139 0.434870 0.040656 0.100000 0.040000 MRC17 +140 0.142678 0.292126 0.100000 0.040000 MRC21 +141 0.219470 0.254066 0.100000 0.040000 MRC22 +142 0.281922 0.196472 0.100000 0.040000 MRC23 +143 0.325059 0.128269 0.100000 0.040000 MRC24 +144 0.361805 0.044213 0.100000 0.040000 MRC25 +145 0.240157 0.132538 0.100000 0.040000 MRC31 +146 0.290750 0.048681 0.100000 0.040000 MRC32 +147 0.178346 0.187415 0.100000 0.040000 MRC41 +148 0.213493 0.062545 0.100000 0.040000 MRC42 +149 0.058440 0.284194 0.100000 0.040000 MRC51 +150 0.101359 0.215083 0.100000 0.040000 MRC52 +151 0.156968 0.115486 0.100000 0.040000 MRC53 +152 0.144211 0.038238 0.100000 0.040000 MRC54 +153 0.106635 -0.024115 0.100000 0.040000 MRC55 +154 0.055338 0.153928 0.100000 0.040000 MRC61 +155 0.088138 0.086634 0.100000 0.040000 MRC62 +156 0.049557 0.022680 0.100000 0.040000 MRC63 +157 0.197726 0.874477 0.100000 0.040000 MRF11 +158 0.364689 0.811426 0.100000 0.040000 MRF12 +159 0.518245 0.722181 0.100000 0.040000 MRF13 +160 0.658136 0.611411 0.100000 0.040000 MRF14 +161 0.095713 0.807816 0.100000 0.040000 MRF21 +162 0.233999 0.772267 0.100000 0.040000 MRF22 +163 0.358821 0.715911 0.100000 0.040000 MRF23 +164 0.484765 0.623142 0.100000 0.040000 MRF24 +165 0.585405 0.526324 0.100000 0.040000 MRF25 +166 0.147633 0.713396 0.100000 0.040000 MRF31 +167 0.265823 0.676341 0.100000 0.040000 MRF32 +168 0.382256 0.601823 0.100000 0.040000 MRF33 +169 0.473850 0.521768 0.100000 0.040000 MRF34 +170 0.548726 0.424836 0.100000 0.040000 MRF35 +171 0.075451 0.644959 0.100000 0.040000 MRF41 +172 0.182924 0.624842 0.100000 0.040000 MRF42 +173 0.292900 0.568899 0.100000 0.040000 MRF43 +174 0.379529 0.501620 0.100000 0.040000 MRF44 +175 0.465778 0.418231 0.100000 0.040000 MRF45 +176 0.541913 0.311405 0.100000 0.040000 MRF46 +177 0.102375 0.561860 0.100000 0.040000 MRF51 +178 0.212879 0.524802 0.100000 0.040000 MRF52 +179 0.299077 0.468924 0.100000 0.040000 MRF53 +180 0.376186 0.400507 0.100000 0.040000 MRF54 +181 0.461150 0.316311 0.100000 0.040000 MRF55 +182 0.527532 0.213125 0.100000 0.040000 MRF56 +183 0.143360 0.469857 0.100000 0.040000 MRF61 +184 0.224730 0.422291 0.100000 0.040000 MRF62 +185 0.301012 0.364856 0.100000 0.040000 MRF63 +186 0.373056 0.305526 0.100000 0.040000 MRF64 +187 0.443172 0.230008 0.100000 0.040000 MRF65 +188 0.482916 0.144546 0.100000 0.040000 MRF66 +189 0.509363 0.039864 0.100000 0.040000 MRF67 +190 0.101312 -0.384464 0.100000 0.040000 MRO11 +191 0.188777 -0.365285 0.100000 0.040000 MRO12 +192 0.274286 -0.333994 0.100000 0.040000 MRO13 +193 0.354824 -0.285987 0.100000 0.040000 MRO14 +194 0.062633 -0.457476 0.100000 0.040000 MRO21 +195 0.152570 -0.440791 0.100000 0.040000 MRO22 +196 0.248565 -0.418432 0.100000 0.040000 MRO23 +197 0.338845 -0.376241 0.100000 0.040000 MRO24 +198 0.111160 -0.521375 0.100000 0.040000 MRO31 +199 0.212466 -0.502957 0.100000 0.040000 MRO32 +200 0.313063 -0.468465 0.100000 0.040000 MRO33 +201 0.409385 -0.418933 0.100000 0.040000 MRO34 +202 0.063270 -0.599845 0.100000 0.040000 MRO41 +203 0.172480 -0.589865 0.100000 0.040000 MRO42 +204 0.279919 -0.563495 0.100000 0.040000 MRO43 +205 0.386742 -0.520993 0.100000 0.040000 MRO44 +206 0.121969 -0.676100 0.100000 0.040000 MRO51 +207 0.240331 -0.658743 0.100000 0.040000 MRO52 +208 0.356156 -0.623026 0.100000 0.040000 MRO53 +209 0.071855 -0.088269 0.100000 0.040000 MRP11 +210 0.180874 -0.026656 0.100000 0.040000 MRP12 +211 0.047839 -0.157479 0.100000 0.040000 MRP21 +212 0.147221 -0.093053 0.100000 0.040000 MRP22 +213 0.252807 -0.012686 0.100000 0.040000 MRP23 +214 0.082012 -0.222790 0.100000 0.040000 MRP31 +215 0.136825 -0.166819 0.100000 0.040000 MRP32 +216 0.210796 -0.134697 0.100000 0.040000 MRP33 +217 0.277587 -0.083946 0.100000 0.040000 MRP34 +218 0.322867 -0.024718 0.100000 0.040000 MRP35 +219 0.162954 -0.240118 0.100000 0.040000 MRP41 +220 0.230510 -0.205793 0.100000 0.040000 MRP42 +221 0.296283 -0.169213 0.100000 0.040000 MRP43 +222 0.351532 -0.101316 0.100000 0.040000 MRP44 +223 0.395383 -0.032706 0.100000 0.040000 MRP45 +224 0.048690 -0.312307 0.100000 0.040000 MRP51 +225 0.137008 -0.312230 0.100000 0.040000 MRP52 +226 0.214275 -0.287336 0.100000 0.040000 MRP53 +227 0.290637 -0.248388 0.100000 0.040000 MRP54 +228 0.360555 -0.199475 0.100000 0.040000 MRP55 +229 0.419086 -0.126737 0.100000 0.040000 MRP56 +230 0.463976 -0.050387 0.100000 0.040000 MRP57 +231 0.628409 0.323946 0.100000 0.040000 MRT11 +232 0.609835 0.205866 0.100000 0.040000 MRT12 +233 0.571838 0.105198 0.100000 0.040000 MRT13 +234 0.544252 -0.054539 0.100000 0.040000 MRT14 +235 0.500732 -0.143104 0.100000 0.040000 MRT15 +236 0.427582 -0.225716 0.100000 0.040000 MRT16 +237 0.685440 0.421411 0.100000 0.040000 MRT21 +238 0.705800 0.208084 0.100000 0.040000 MRT22 +239 0.667392 0.088109 0.100000 0.040000 MRT23 +240 0.637062 -0.030086 0.100000 0.040000 MRT24 +241 0.588417 -0.159092 0.100000 0.040000 MRT25 +242 0.522350 -0.247039 0.100000 0.040000 MRT26 +243 0.422093 -0.318167 0.100000 0.040000 MRT27 +244 0.789789 0.482334 0.100000 0.040000 MRT31 +245 0.786599 0.293212 0.100000 0.040000 MRT32 +246 0.770320 0.070984 0.100000 0.040000 MRT33 +247 0.731214 -0.061690 0.100000 0.040000 MRT34 +248 0.674802 -0.172109 0.100000 0.040000 MRT35 +249 0.607500 -0.268226 0.100000 0.040000 MRT36 +250 0.510484 -0.353209 0.100000 0.040000 MRT37 +251 0.910695 0.324672 0.100000 0.040000 MRT41 +252 0.867982 0.137317 0.100000 0.040000 MRT42 +253 0.839920 -0.060661 0.100000 0.040000 MRT43 +254 0.773256 -0.189639 0.100000 0.040000 MRT44 +255 0.698444 -0.293384 0.100000 0.040000 MRT45 +256 0.604482 -0.385347 0.100000 0.040000 MRT46 +257 0.489291 -0.462983 0.100000 0.040000 MRT47 +258 1.000000 0.135648 0.100000 0.040000 MRT51 +259 0.959092 -0.049055 0.100000 0.040000 MRT52 +260 0.886964 -0.204289 0.100000 0.040000 MRT53 +261 0.796842 -0.324881 0.100000 0.040000 MRT54 +262 0.698769 -0.420596 0.100000 0.040000 MRT55 +263 0.582500 -0.506810 0.100000 0.040000 MRT56 +264 0.467934 -0.572706 0.100000 0.040000 MRT57 +265 0.016063 0.355556 0.100000 0.040000 MZC01 +266 0.014747 0.217488 0.100000 0.040000 MZC02 +267 0.013199 0.087763 0.100000 0.040000 MZC03 +268 0.011197 -0.046263 0.100000 0.040000 MZC04 +269 0.022267 0.897778 0.100000 0.040000 MZF01 +270 0.019840 0.730557 0.100000 0.040000 MZF02 +271 0.017559 0.517279 0.100000 0.040000 MZF03 +272 0.007392 -0.378522 0.100000 0.040000 MZO01 +273 0.005634 -0.528155 0.100000 0.040000 MZO02 +274 0.003722 -0.675585 0.100000 0.040000 MZO03 +275 0.008864 -0.248776 0.100000 0.040000 MZP01 diff --git a/mne-python/source/mne/channels/data/layouts/EEG1005.lay b/mne-python/source/mne/channels/data/layouts/EEG1005.lay new file mode 100644 index 0000000000000000000000000000000000000000..a600468c79ff4238e41ab684f4057ac20d426a15 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/EEG1005.lay @@ -0,0 +1,337 @@ +1 -0.485328 1.493835 0.069221 0.051916 Fp1 +2 0.000000 1.570696 0.069221 0.051916 Fpz +3 0.485501 1.493884 0.069221 0.051916 Fp2 +4 -1.154207 1.588656 0.069221 0.051916 AF9 +5 -0.923319 1.270781 0.069221 0.051916 AF7 +6 -0.706117 1.226029 0.069221 0.051916 AF5 +7 -0.477022 1.197254 0.069221 0.051916 AF3 +8 -0.240008 1.182594 0.069221 0.051916 AF1 +9 0.000000 1.178022 0.069221 0.051916 AFz +10 0.240008 1.182594 0.069221 0.051916 AF2 +11 0.476904 1.197159 0.069221 0.051916 AF4 +12 0.706117 1.226029 0.069221 0.051916 AF6 +13 0.923319 1.270781 0.069221 0.051916 AF8 +14 1.154207 1.588656 0.069221 0.051916 AF10 +15 -1.588376 1.154294 0.069221 0.051916 F9 +16 -1.270781 0.923319 0.069221 0.051916 F7 +17 -0.968950 0.852434 0.069221 0.051916 F5 +18 -0.652084 0.812357 0.069221 0.051916 F3 +19 -0.327689 0.791876 0.069221 0.051916 F1 +20 0.000000 0.785398 0.069221 0.051916 Fz +21 0.327689 0.791876 0.069221 0.051916 F2 +22 0.652084 0.812357 0.069221 0.051916 F4 +23 0.968950 0.852434 0.069221 0.051916 F6 +24 1.270781 0.923319 0.069221 0.051916 F8 +25 1.588496 1.154168 0.069221 0.051916 F10 +26 -1.867677 0.606883 0.069221 0.051916 FT9 +27 -1.493930 0.485359 0.069221 0.051916 FT7 +28 -1.126134 0.436152 0.069221 0.051916 FC5 +29 -0.752811 0.409634 0.069221 0.051916 FC3 +30 -0.376942 0.396836 0.069221 0.051916 FC1 +31 0.000000 0.392844 0.069221 0.051916 FCz +32 0.376942 0.396836 0.069221 0.051916 FC2 +33 0.752811 0.409634 0.069221 0.051916 FC4 +34 1.126134 0.436152 0.069221 0.051916 FC6 +35 1.493930 0.485359 0.069221 0.051916 FT8 +36 1.867677 0.606883 0.069221 0.051916 FT10 +37 -1.963487 -0.000213 0.069221 0.051916 T9 +38 -1.570796 0.000000 0.069221 0.051916 T7 +39 -1.178106 0.000128 0.069221 0.051916 C5 +40 -0.785398 0.000111 0.069221 0.051916 C3 +41 -0.392736 0.000205 0.069221 0.051916 C1 +42 0.000000 0.000200 0.069221 0.051916 Cz +43 0.392736 0.000103 0.069221 0.051916 C2 +44 0.785398 0.000111 0.069221 0.051916 C4 +45 1.178106 0.000128 0.069221 0.051916 C6 +46 1.570796 -0.000000 0.069221 0.051916 T8 +47 1.963487 -0.000000 0.069221 0.051916 T10 +48 -1.867677 -0.606883 0.069221 0.051916 TP9 +49 -1.494026 -0.485389 0.069221 0.051916 TP7 +50 -1.126048 -0.435839 0.069221 0.051916 CP5 +51 -0.752775 -0.409460 0.069221 0.051916 CP3 +52 -0.376804 -0.396486 0.069221 0.051916 CP1 +53 -0.000000 -0.392551 0.069221 0.051916 CPz +54 0.376804 -0.396486 0.069221 0.051916 CP2 +55 0.752795 -0.409357 0.069221 0.051916 CP4 +56 1.126048 -0.435839 0.069221 0.051916 CP6 +57 1.494026 -0.485389 0.069221 0.051916 TP8 +58 1.867603 -0.607072 0.069221 0.051916 TP10 +59 -1.588496 -1.154168 0.069221 0.051916 P9 +60 -1.270862 -0.923378 0.069221 0.051916 P7 +61 -0.969077 -0.852293 0.069221 0.051916 P5 +62 -0.652231 -0.811998 0.069221 0.051916 P3 +63 -0.327776 -0.791360 0.069221 0.051916 P1 +64 -0.000000 -0.785257 0.069221 0.051916 Pz +65 0.327776 -0.791360 0.069221 0.051916 P2 +66 0.652231 -0.811998 0.069221 0.051916 P4 +67 0.969077 -0.852293 0.069221 0.051916 P6 +68 1.270862 -0.923378 0.069221 0.051916 P8 +69 1.588496 -1.154168 0.069221 0.051916 P10 +70 -1.154207 -1.588656 0.069221 0.051916 PO9 +71 -0.923319 -1.270781 0.069221 0.051916 PO7 +72 -0.706303 -1.225606 0.069221 0.051916 PO5 +73 -0.476710 -1.197888 0.069221 0.051916 PO3 +74 -0.240097 -1.182523 0.069221 0.051916 PO1 +75 -0.000000 -1.178022 0.069221 0.051916 POz +76 0.240223 -1.182505 0.069221 0.051916 PO2 +77 0.476710 -1.197888 0.069221 0.051916 PO4 +78 0.706303 -1.225606 0.069221 0.051916 PO6 +79 0.923319 -1.270781 0.069221 0.051916 PO8 +80 1.154207 -1.588656 0.069221 0.051916 PO10 +81 -0.485359 -1.493930 0.069221 0.051916 O1 +82 -0.000000 -1.570796 0.069221 0.051916 Oz +83 0.485359 -1.493930 0.069221 0.051916 O2 +84 -0.606613 -1.867239 0.069221 0.051916 I1 +85 -0.000000 -1.963478 0.069221 0.051916 Iz +86 0.606613 -1.867239 0.069221 0.051916 I2 +87 -0.802226 1.574520 0.069221 0.051916 AFp9h +88 -0.626475 1.393612 0.069221 0.051916 AFp7h +89 -0.451133 1.382849 0.069221 0.051916 AFp5h +90 -0.271959 1.376738 0.069221 0.051916 AFp3h +91 -0.090887 1.374548 0.069221 0.051916 AFp1h +92 0.090887 1.374548 0.069221 0.051916 AFp2h +93 0.271959 1.376738 0.069221 0.051916 AFp4h +94 0.451133 1.382849 0.069221 0.051916 AFp6h +95 0.626475 1.393612 0.069221 0.051916 AFp8h +96 0.802226 1.574520 0.069221 0.051916 AFp10h +97 -1.249550 1.249550 0.069221 0.051916 AFF9h +98 -0.982948 1.075122 0.069221 0.051916 AFF7h +99 -0.713694 1.024626 0.069221 0.051916 AFF5h +100 -0.432315 0.996167 0.069221 0.051916 AFF3h +101 -0.144727 0.983315 0.069221 0.051916 AFF1h +102 0.144727 0.983315 0.069221 0.051916 AFF2h +103 0.432315 0.996167 0.069221 0.051916 AFF4h +104 0.713694 1.024626 0.069221 0.051916 AFF6h +105 0.982881 1.075049 0.069221 0.051916 AFF8h +106 1.249550 1.249550 0.069221 0.051916 AFF10h +107 -1.574645 0.802293 0.069221 0.051916 FFT9h +108 -1.232019 0.675885 0.069221 0.051916 FFT7h +109 -0.886990 0.627578 0.069221 0.051916 FFC5h +110 -0.534535 0.601827 0.069221 0.051916 FFC3h +111 -0.178478 0.590622 0.069221 0.051916 FFC1h +112 0.178478 0.590622 0.069221 0.051916 FFC2h +113 0.534535 0.601827 0.069221 0.051916 FFC4h +114 0.886990 0.627578 0.069221 0.051916 FFC6h +115 1.232019 0.675885 0.069221 0.051916 FFT8h +116 1.574645 0.802293 0.069221 0.051916 FFT10h +117 -1.745475 0.276484 0.069221 0.051916 FTT9h +118 -1.358553 0.230430 0.069221 0.051916 FTT7h +119 -0.971386 0.211155 0.069221 0.051916 FCC5h +120 -0.583084 0.201295 0.069221 0.051916 FCC3h +121 -0.194460 0.196994 0.069221 0.051916 FCC1h +122 0.194460 0.196994 0.069221 0.051916 FCC2h +123 0.583084 0.201295 0.069221 0.051916 FCC4h +124 0.971386 0.211155 0.069221 0.051916 FCC6h +125 1.358553 0.230430 0.069221 0.051916 FTT8h +126 1.745475 0.276484 0.069221 0.051916 FTT10h +127 -1.745506 -0.276309 0.069221 0.051916 TTP9h +128 -1.358573 -0.230293 0.069221 0.051916 TTP7h +129 -0.971375 -0.211008 0.069221 0.051916 CCP5h +130 -0.583085 -0.200906 0.069221 0.051916 CCP3h +131 -0.194448 -0.196679 0.069221 0.051916 CCP1h +132 0.194448 -0.196679 0.069221 0.051916 CCP2h +133 0.583078 -0.201010 0.069221 0.051916 CCP4h +134 0.971375 -0.211008 0.069221 0.051916 CCP6h +135 1.358573 -0.230293 0.069221 0.051916 TTP8h +136 1.745475 -0.276484 0.069221 0.051916 TTP10h +137 -1.574667 -0.802213 0.069221 0.051916 TPP9h +138 -1.232021 -0.675979 0.069221 0.051916 TPP7h +139 -0.887025 -0.627306 0.069221 0.051916 CPP5h +140 -0.534524 -0.601312 0.069221 0.051916 CPP3h +141 -0.178473 -0.590144 0.069221 0.051916 CPP1h +142 0.178473 -0.590144 0.069221 0.051916 CPP2h +143 0.534524 -0.601312 0.069221 0.051916 CPP4h +144 0.887025 -0.627306 0.069221 0.051916 CPP6h +145 1.231976 -0.676032 0.069221 0.051916 TPP8h +146 1.574586 -0.802352 0.069221 0.051916 TPP10h +147 -1.249639 -1.249639 0.069221 0.051916 PPO9h +148 -0.983137 -1.074700 0.069221 0.051916 PPO7h +149 -0.713821 -1.024109 0.069221 0.051916 PPO5h +150 -0.432363 -0.995909 0.069221 0.051916 PPO3h +151 -0.144761 -0.982953 0.069221 0.051916 PPO1h +152 0.144761 -0.982953 0.069221 0.051916 PPO2h +153 0.432253 -0.995937 0.069221 0.051916 PPO4h +154 0.713967 -1.023998 0.069221 0.051916 PPO6h +155 0.983137 -1.074700 0.069221 0.051916 PPO8h +156 1.249639 -1.249639 0.069221 0.051916 PPO10h +157 -0.802293 -1.574645 0.069221 0.051916 POO9h +158 -0.626849 -1.393237 0.069221 0.051916 POO7h +159 -0.451236 -1.382715 0.069221 0.051916 POO5h +160 -0.271951 -1.377572 0.069221 0.051916 POO3h +161 -0.090910 -1.374606 0.069221 0.051916 POO1h +162 0.090910 -1.374606 0.069221 0.051916 POO2h +163 0.271951 -1.377572 0.069221 0.051916 POO4h +164 0.451236 -1.382715 0.069221 0.051916 POO6h +165 0.626849 -1.393237 0.069221 0.051916 POO8h +166 0.802293 -1.574645 0.069221 0.051916 POO10h +167 -0.276453 -1.745460 0.069221 0.051916 OI1h +168 0.276453 -1.745460 0.069221 0.051916 OI2h +169 -0.245655 1.551367 0.069221 0.051916 Fp1h +170 0.245655 1.551367 0.069221 0.051916 Fp2h +171 -1.038573 1.429729 0.069221 0.051916 AF9h +172 -0.816811 1.245775 0.069221 0.051916 AF7h +173 -0.592502 1.210176 0.069221 0.051916 AF5h +174 -0.359066 1.188527 0.069221 0.051916 AF3h +175 -0.120203 1.179114 0.069221 0.051916 AF1h +176 0.120212 1.179076 0.069221 0.051916 AF2h +177 0.359066 1.188527 0.069221 0.051916 AF4h +178 0.592545 1.210263 0.069221 0.051916 AF6h +179 0.816811 1.245775 0.069221 0.051916 AF8h +180 1.038668 1.429679 0.069221 0.051916 AF10h +181 -1.429588 1.038701 0.069221 0.051916 F9h +182 -1.122287 0.883303 0.069221 0.051916 F7h +183 -0.811863 0.829210 0.069221 0.051916 F5h +184 -0.490601 0.800049 0.069221 0.051916 F3h +185 -0.164017 0.787126 0.069221 0.051916 F1h +186 0.164017 0.787126 0.069221 0.051916 F2h +187 0.490601 0.800049 0.069221 0.051916 F4h +188 0.811863 0.829210 0.069221 0.051916 F6h +189 1.122287 0.883303 0.069221 0.051916 F8h +190 1.429588 1.038701 0.069221 0.051916 F10h +191 -1.680799 0.546075 0.069221 0.051916 FT9h +192 -1.310995 0.457012 0.069221 0.051916 FT7h +193 -0.939857 0.420814 0.069221 0.051916 FC5h +194 -0.565142 0.401905 0.069221 0.051916 FC3h +195 -0.188491 0.393826 0.069221 0.051916 FC1h +196 0.188491 0.393826 0.069221 0.051916 FC2h +197 0.565142 0.401905 0.069221 0.051916 FC4h +198 0.939857 0.420814 0.069221 0.051916 FC6h +199 1.310995 0.457012 0.069221 0.051916 FT8h +200 1.680740 0.546236 0.069221 0.051916 FT10h +201 -1.767191 0.000000 0.069221 0.051916 T9h +202 -1.374500 0.000000 0.069221 0.051916 T7h +203 -0.981850 0.000118 0.069221 0.051916 C5h +204 -0.589058 0.000212 0.069221 0.051916 C3h +205 -0.196395 0.000101 0.069221 0.051916 C1h +206 0.196395 0.000201 0.069221 0.051916 C2h +207 0.589058 0.000212 0.069221 0.051916 C4h +208 0.981850 0.000118 0.069221 0.051916 C6h +209 1.374500 -0.000000 0.069221 0.051916 T8h +210 1.767191 -0.000000 0.069221 0.051916 T10h +211 -1.680646 -0.546088 0.069221 0.051916 TP9h +212 -1.310970 -0.456960 0.069221 0.051916 TP7h +213 -0.939815 -0.420500 0.069221 0.051916 CP5h +214 -0.565062 -0.401491 0.069221 0.051916 CP3h +215 -0.188515 -0.393352 0.069221 0.051916 CP1h +216 0.188515 -0.393352 0.069221 0.051916 CP2h +217 0.565062 -0.401491 0.069221 0.051916 CP4h +218 0.939815 -0.420500 0.069221 0.051916 CP6h +219 1.310970 -0.456960 0.069221 0.051916 TP8h +220 1.680646 -0.546088 0.069221 0.051916 TP10h +221 -1.429668 -1.038758 0.069221 0.051916 P9h +222 -1.122286 -0.883271 0.069221 0.051916 P7h +223 -0.812037 -0.829137 0.069221 0.051916 P5h +224 -0.490726 -0.799336 0.069221 0.051916 P3h +225 -0.164146 -0.786762 0.069221 0.051916 P1h +226 0.164146 -0.786762 0.069221 0.051916 P2h +227 0.490600 -0.799436 0.069221 0.051916 P4h +228 0.812037 -0.829137 0.069221 0.051916 P6h +229 1.122286 -0.883271 0.069221 0.051916 P8h +230 1.429668 -1.038758 0.069221 0.051916 P10h +231 -1.038821 -1.429709 0.069221 0.051916 PO9h +232 -0.816502 -1.246067 0.069221 0.051916 PO7h +233 -0.593079 -1.209372 0.069221 0.051916 PO5h +234 -0.359230 -1.188332 0.069221 0.051916 PO3h +235 -0.120221 -1.179168 0.069221 0.051916 PO1h +236 0.120348 -1.179159 0.069221 0.051916 PO2h +237 0.359230 -1.188332 0.069221 0.051916 PO4h +238 0.593079 -1.209372 0.069221 0.051916 PO6h +239 0.816502 -1.246067 0.069221 0.051916 PO8h +240 1.038710 -1.429804 0.069221 0.051916 PO10h +241 -0.245671 -1.551466 0.069221 0.051916 O1h +242 0.245671 -1.551466 0.069221 0.051916 O2h +243 -0.307129 -1.939338 0.069221 0.051916 I1h +244 0.307129 -1.939338 0.069221 0.051916 I2h +245 -0.891328 1.749684 0.069221 0.051916 AFp9 +246 -0.713143 1.399582 0.069221 0.051916 AFp7 +247 -0.539182 1.387878 0.069221 0.051916 AFp5 +248 -0.361777 1.379743 0.069221 0.051916 AFp3 +249 -0.181624 1.374948 0.069221 0.051916 AFp1 +250 0.000000 1.374461 0.069221 0.051916 AFpz +251 0.181624 1.374948 0.069221 0.051916 AFp2 +252 0.361802 1.379839 0.069221 0.051916 AFp4 +253 0.539182 1.387878 0.069221 0.051916 AFp6 +254 0.713143 1.399582 0.069221 0.051916 AFp8 +255 0.891489 1.749582 0.069221 0.051916 AFp10 +256 -1.388504 1.388504 0.069221 0.051916 AFF9 +257 -1.110721 1.110721 0.069221 0.051916 AFF7 +258 -0.850463 1.046170 0.069221 0.051916 AFF5 +259 -0.574170 1.008058 0.069221 0.051916 AFF3 +260 -0.288981 0.988233 0.069221 0.051916 AFF1 +261 0.000000 0.981739 0.069221 0.051916 AFFz +262 0.288981 0.988233 0.069221 0.051916 AFF2 +263 0.574170 1.008058 0.069221 0.051916 AFF4 +264 0.850463 1.046170 0.069221 0.051916 AFF6 +265 1.110721 1.110721 0.069221 0.051916 AFF8 +266 1.388504 1.388504 0.069221 0.051916 AFF10 +267 -1.749576 0.891591 0.069221 0.051916 FFT9 +268 -1.399582 0.713143 0.069221 0.051916 FFT7 +269 -1.060830 0.648168 0.069221 0.051916 FFC5 +270 -0.711350 0.612390 0.069221 0.051916 FFC3 +271 -0.356750 0.594619 0.069221 0.051916 FFC1 +272 0.000000 0.589085 0.069221 0.051916 FFCz +273 0.356750 0.594619 0.069221 0.051916 FFC2 +274 0.711350 0.612390 0.069221 0.051916 FFC4 +275 1.060749 0.648119 0.069221 0.051916 FFC6 +276 1.399582 0.713143 0.069221 0.051916 FFT8 +277 1.749576 0.891591 0.069221 0.051916 FFT10 +278 -1.939489 0.307119 0.069221 0.051916 FTT9 +279 -1.551442 0.245824 0.069221 0.051916 FTT7 +280 -1.165132 0.219351 0.069221 0.051916 FCC5 +281 -0.777319 0.205363 0.069221 0.051916 FCC3 +282 -0.388766 0.198515 0.069221 0.051916 FCC1 +283 0.000000 0.196434 0.069221 0.051916 FCCz +284 0.388766 0.198515 0.069221 0.051916 FCC2 +285 0.777319 0.205363 0.069221 0.051916 FCC4 +286 1.165132 0.219351 0.069221 0.051916 FCC6 +287 1.551466 0.245671 0.069221 0.051916 FTT8 +288 1.939489 0.307119 0.069221 0.051916 FTT10 +289 -1.939553 -0.307197 0.069221 0.051916 TTP9 +290 -1.551565 -0.245687 0.069221 0.051916 TTP7 +291 -1.165206 -0.219084 0.069221 0.051916 CCP5 +292 -0.777275 -0.205069 0.069221 0.051916 CCP3 +293 -0.388806 -0.198175 0.069221 0.051916 CCP1 +294 -0.000000 -0.196218 0.069221 0.051916 CCPz +295 0.388801 -0.198275 0.069221 0.051916 CCP2 +296 0.777275 -0.205069 0.069221 0.051916 CCP4 +297 1.165206 -0.219084 0.069221 0.051916 CCP6 +298 1.551565 -0.245687 0.069221 0.051916 TTP8 +299 1.939553 -0.307197 0.069221 0.051916 TTP10 +300 -1.749664 -0.891531 0.069221 0.051916 TPP9 +301 -1.399671 -0.713188 0.069221 0.051916 TPP7 +302 -1.060852 -0.647970 0.069221 0.051916 CPP5 +303 -0.711356 -0.612379 0.069221 0.051916 CPP3 +304 -0.356663 -0.594548 0.069221 0.051916 CPP1 +305 -0.000000 -0.588863 0.069221 0.051916 CPPz +306 0.356778 -0.594448 0.069221 0.051916 CPP2 +307 0.711384 -0.612287 0.069221 0.051916 CPP4 +308 1.060852 -0.647970 0.069221 0.051916 CPP6 +309 1.399671 -0.713188 0.069221 0.051916 TPP8 +310 1.749664 -0.891531 0.069221 0.051916 TPP10 +311 -1.388427 -1.388427 0.069221 0.051916 PPO9 +312 -1.110721 -1.110721 0.069221 0.051916 PPO7 +313 -0.850511 -1.046155 0.069221 0.051916 PPO5 +314 -0.574228 -1.007462 0.069221 0.051916 PPO3 +315 -0.289055 -0.987715 0.069221 0.051916 PPO1 +316 -0.000000 -0.981655 0.069221 0.051916 PPOz +317 0.289055 -0.987715 0.069221 0.051916 PPO2 +318 0.574228 -1.007462 0.069221 0.051916 PPO4 +319 0.850454 -1.046223 0.069221 0.051916 PPO6 +320 1.110721 -1.110721 0.069221 0.051916 PPO8 +321 1.388427 -1.388427 0.069221 0.051916 PPO10 +322 -0.891143 -1.749540 0.069221 0.051916 POO9 +323 -0.713143 -1.399582 0.069221 0.051916 POO7 +324 -0.539360 -1.387717 0.069221 0.051916 POO5 +325 -0.362020 -1.379310 0.069221 0.051916 POO3 +326 -0.181486 -1.375484 0.069221 0.051916 POO1 +327 -0.000000 -1.374422 0.069221 0.051916 POOz +328 0.181626 -1.375468 0.069221 0.051916 POO2 +329 0.362020 -1.379310 0.069221 0.051916 POO4 +330 0.539360 -1.387717 0.069221 0.051916 POO6 +331 0.713143 -1.399582 0.069221 0.051916 POO8 +332 0.891143 -1.749540 0.069221 0.051916 POO10 +333 -0.546073 -1.680586 0.069221 0.051916 OI1 +334 -0.000000 -1.767132 0.069221 0.051916 OIz +335 0.546073 -1.680586 0.069221 0.051916 OI2 +336 -1.963487 1.749684 0.069221 0.051916 COMNT +337 1.963487 1.749684 0.069221 0.051916 SCALE diff --git a/mne-python/source/mne/channels/data/layouts/EGI256.lout b/mne-python/source/mne/channels/data/layouts/EGI256.lout new file mode 100644 index 0000000000000000000000000000000000000000..bc9076adba2d1b6e6ed1e993ce46c800476efe8f --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/EGI256.lout @@ -0,0 +1,259 @@ +-42.19 43.52 -41.70 28.71 +001 0.235020883 0.231411875 0.023840595 0.024283894 EEG 001 +002 0.180062322 0.24066255 0.023840595 0.024283894 EEG 002 +003 0.134498312 0.239722125 0.023840595 0.024283894 EEG 003 +004 0.098183698 0.230899463 0.023840595 0.024283894 EEG 004 +005 0.066117291 0.206774428 0.023840595 0.024283894 EEG 005 +006 0.038417416 0.175224454 0.023840595 0.024283894 EEG 006 +007 0.019093339 0.142334211 0.023840595 0.024283894 EEG 007 +008 0 0.106825455 0.023840595 0.024283894 EEG 008 +009 -0.017539353 0.062826857 0.023840595 0.024283894 EEG 009 +010 0.181942866 0.296413546 0.023840595 0.024283894 EEG 010 +011 0.13038807 0.293232492 0.023840595 0.024283894 EEG 011 +012 0.084273706 0.277147412 0.023840595 0.024283894 EEG 012 +013 0.050175359 0.251802841 0.023840595 0.024283894 EEG 013 +014 0.021773201 0.21699757 0.023840595 0.024283894 EEG 014 +015 0 0.180469732 0.023840595 0.024283894 EEG 015 +016 -0.019093339 0.142334211 0.023840595 0.024283894 EEG 016 +017 -0.036255497 0.09269913 0.023840595 0.024283894 EEG 017 +018 0.113098849 0.348229946 0.023840595 0.024283894 EEG 018 +019 0.069000992 0.329792276 0.023840595 0.024283894 EEG 019 +020 0.029776066 0.297506089 0.023840595 0.024283894 EEG 020 +021 0 0.258687873 0.023840595 0.024283894 EEG 021 +022 -0.021773201 0.21699757 0.023840595 0.024283894 EEG 022 +023 -0.038417416 0.175224454 0.023840595 0.024283894 EEG 023 +024 -0.055153266 0.126645408 0.023840595 0.024283894 EEG 024 +025 0.036940443 0.37703699 0.023840595 0.024283894 EEG 025 +026 0 0.343720309 0.023840595 0.024283894 EEG 026 +027 -0.029776066 0.297506089 0.023840595 0.024283894 EEG 027 +028 -0.050175359 0.251802841 0.023840595 0.024283894 EEG 028 +029 -0.066117291 0.206774428 0.023840595 0.024283894 EEG 029 +030 -0.079525249 0.158534511 0.023840595 0.024283894 EEG 030 +031 0 0.415202995 0.023840595 0.024283894 EEG 031 +032 -0.036940443 0.37703699 0.023840595 0.024283894 EEG 032 +033 -0.069000992 0.329792276 0.023840595 0.024283894 EEG 033 +034 -0.084273706 0.277147412 0.023840595 0.024283894 EEG 034 +035 -0.098183698 0.230899463 0.023840595 0.024283894 EEG 035 +036 -0.098479668 0.187945851 0.023840595 0.024283894 EEG 036 +037 -0.113098849 0.348229946 0.023840595 0.024283894 EEG 037 +038 -0.13038807 0.293232492 0.023840595 0.024283894 EEG 038 +039 -0.134498312 0.239722125 0.023840595 0.024283894 EEG 039 +040 -0.130890927 0.191286703 0.023840595 0.024283894 EEG 040 +041 -0.116009122 0.150111634 0.023840595 0.024283894 EEG 041 +042 -0.094840856 0.116834626 0.023840595 0.024283894 EEG 042 +043 -0.076990927 0.086006856 0.023840595 0.024283894 EEG 043 +044 -0.055587556 0.053147386 0.023840595 0.024283894 EEG 044 +045 -0.029699902 0.019405615 0.023840595 0.024283894 EEG 045 +046 -0.181942866 0.296413546 0.023840595 0.024283894 EEG 046 +047 -0.180062322 0.24066255 0.023840595 0.024283894 EEG 047 +048 -0.17285275 0.187572361 0.023840595 0.024283894 EEG 048 +049 -0.156410469 0.141423921 0.023840595 0.024283894 EEG 049 +050 -0.132742164 0.104084677 0.023840595 0.024283894 EEG 050 +051 -0.108362109 0.07207399 0.023840595 0.024283894 EEG 051 +052 -0.087032894 0.041560718 0.023840595 0.024283894 EEG 052 +053 -0.057033727 0.006635523 0.023840595 0.024283894 EEG 053 +054 -0.235020883 0.231411875 0.023840595 0.024283894 EEG 054 +055 -0.21721779 0.1735557 0.023840595 0.024283894 EEG 055 +056 -0.196096643 0.121848964 0.023840595 0.024283894 EEG 056 +057 -0.169122926 0.084563661 0.023840595 0.024283894 EEG 057 +058 -0.142622009 0.056366314 0.023840595 0.024283894 EEG 058 +059 -0.11607512 0.026701856 0.023840595 0.024283894 EEG 059 +060 -0.086703907 -0.006962228 0.023840595 0.024283894 EEG 060 +061 -0.271241865 0.131933691 0.023840595 0.024283894 EEG 061 +062 -0.237546771 0.082946276 0.023840595 0.024283894 EEG 062 +063 -0.20434592 0.049982898 0.023840595 0.024283894 EEG 063 +064 -0.175001011 0.027246728 0.023840595 0.024283894 EEG 064 +065 -0.144183544 0.006552794 0.023840595 0.024283894 EEG 065 +066 -0.117629392 -0.020953359 0.023840595 0.024283894 EEG 066 +067 -0.32017538 0.064356008 0.023840595 0.024283894 EEG 067 +068 -0.277394242 0.035815905 0.023840595 0.024283894 EEG 068 +069 -0.241320281 0.000293927 0.023840595 0.024283894 EEG 069 +070 -0.202988841 -0.017932839 0.023840595 0.024283894 EEG 070 +071 -0.170816713 -0.027588171 0.023840595 0.024283894 EEG 071 +072 -0.142940198 -0.038849379 0.023840595 0.024283894 EEG 072 +073 -0.364333595 -0.009526546 0.023840595 0.024283894 EEG 073 +074 -0.227828247 -0.074709585 0.023840595 0.024283894 EEG 074 +075 -0.186334435 -0.079063391 0.023840595 0.024283894 EEG 075 +076 -0.152612576 -0.080357072 0.023840595 0.024283894 EEG 076 +077 -0.122986168 -0.070147895 0.023840595 0.024283894 EEG 077 +078 -0.092860036 -0.059724481 0.023840595 0.024283894 EEG 078 +079 -0.063373134 -0.044961361 0.023840595 0.024283894 EEG 079 +080 -0.033138055 -0.028518783 0.023840595 0.024283894 EEG 080 +081 0 -0.006448832 0.023840595 0.024283894 EEG 081 +082 -0.384631539 -0.115563191 0.023840595 0.024283894 EEG 082 +083 -0.230231782 -0.157310034 0.023840595 0.024283894 EEG 083 +084 -0.201004697 -0.132397774 0.023840595 0.024283894 EEG 084 +085 -0.158874627 -0.130476761 0.023840595 0.024283894 EEG 085 +086 -0.125435162 -0.117006671 0.023840595 0.024283894 EEG 086 +087 -0.093818787 -0.102184911 0.023840595 0.024283894 EEG 087 +088 -0.063690231 -0.085009427 0.023840595 0.024283894 EEG 088 +089 -0.034226984 -0.069230419 0.023840595 0.024283894 EEG 089 +090 0 -0.043222928 0.023840595 0.024283894 EEG 090 +091 -0.376606255 -0.236283155 0.023840595 0.024283894 EEG 091 +092 -0.320841548 -0.246056831 0.023840595 0.024283894 EEG 092 +093 -0.264511728 -0.247963981 0.023840595 0.024283894 EEG 093 +094 -0.235119884 -0.22133859 0.023840595 0.024283894 EEG 094 +095 -0.200260526 -0.201104991 0.023840595 0.024283894 EEG 095 +096 -0.16089296 -0.182074387 0.023840595 0.024283894 EEG 096 +097 -0.123315473 -0.169463521 0.023840595 0.024283894 EEG 097 +098 -0.093577895 -0.148219199 0.023840595 0.024283894 EEG 098 +099 -0.062757092 -0.127508907 0.023840595 0.024283894 EEG 099 +100 -0.033465994 -0.105718695 0.023840595 0.024283894 EEG 100 +101 0 -0.123212516 0.023840595 0.024283894 EEG 101 +102 -0.309236143 -0.330394078 0.023840595 0.024283894 EEG 102 +103 -0.264402365 -0.317489099 0.023840595 0.024283894 EEG 103 +104 -0.215607267 -0.297916345 0.023840595 0.024283894 EEG 104 +105 -0.194042397 -0.266008675 0.023840595 0.024283894 EEG 105 +106 -0.156365562 -0.241406814 0.023840595 0.024283894 EEG 106 +107 -0.117304936 -0.222733874 0.023840595 0.024283894 EEG 107 +108 -0.08375779 -0.200153314 0.023840595 0.024283894 EEG 108 +109 -0.056791169 -0.173578646 0.023840595 0.024283894 EEG 109 +110 -0.028490371 -0.146436894 0.023840595 0.024283894 EEG 110 +111 -0.235425173 -0.391140875 0.023840595 0.024283894 EEG 111 +112 -0.20031364 -0.367491502 0.023840595 0.024283894 EEG 112 +113 -0.160198907 -0.335751192 0.023840595 0.024283894 EEG 113 +114 -0.148968879 -0.297338854 0.023840595 0.024283894 EEG 114 +115 -0.09913078 -0.279612547 0.023840595 0.024283894 EEG 115 +116 -0.06561825 -0.2506161 0.023840595 0.024283894 EEG 116 +117 -0.036528871 -0.219887692 0.023840595 0.024283894 EEG 117 +118 -0.01914107 -0.187670154 0.023840595 0.024283894 EEG 118 +119 0 -0.159638357 0.023840595 0.024283894 EEG 119 +120 -0.178151028 -0.424680349 0.023840595 0.024283894 EEG 120 +121 -0.142872329 -0.395550026 0.023840595 0.024283894 EEG 121 +122 -0.106134228 -0.360226213 0.023840595 0.024283894 EEG 122 +123 -0.074015552 -0.317797572 0.023840595 0.024283894 EEG 123 +124 -0.049414286 -0.292978277 0.023840595 0.024283894 EEG 124 +125 -0.020856534 -0.260833466 0.023840595 0.024283894 EEG 125 +126 0 -0.223512279 0.023840595 0.024283894 EEG 126 +127 0.01914107 -0.187670154 0.023840595 0.024283894 EEG 127 +128 0.028490371 -0.146436894 0.023840595 0.024283894 EEG 128 +129 0.033465994 -0.105718695 0.023840595 0.024283894 EEG 129 +130 0.034226984 -0.069230419 0.023840595 0.024283894 EEG 130 +131 0.033138055 -0.028518783 0.023840595 0.024283894 EEG 131 +132 0.029699902 0.019405615 0.023840595 0.024283894 EEG 132 +133 -0.11640639 -0.433892117 0.023840595 0.024283894 EEG 133 +134 -0.085226238 -0.411234759 0.023840595 0.024283894 EEG 134 +135 -0.054701526 -0.36252645 0.023840595 0.024283894 EEG 135 +136 -0.02321088 -0.335534555 0.023840595 0.024283894 EEG 136 +137 0 -0.303018075 0.023840595 0.024283894 EEG 137 +138 0.020856534 -0.260833466 0.023840595 0.024283894 EEG 138 +139 0.036528871 -0.219887692 0.023840595 0.024283894 EEG 139 +140 0.056791169 -0.173578646 0.023840595 0.024283894 EEG 140 +141 0.062757092 -0.127508907 0.023840595 0.024283894 EEG 141 +142 0.063690231 -0.085009427 0.023840595 0.024283894 EEG 142 +143 0.063373134 -0.044961361 0.023840595 0.024283894 EEG 143 +144 0.057033727 0.006635523 0.023840595 0.024283894 EEG 144 +145 -0.061719572 -0.45 0.023840595 0.024283894 EEG 145 +146 -0.032116421 -0.419782634 0.023840595 0.024283894 EEG 146 +147 -9.99E-17 -0.379508917 0.023840595 0.024283894 EEG 147 +148 0.02321088 -0.335534555 0.023840595 0.024283894 EEG 148 +149 0.049414286 -0.292978277 0.023840595 0.024283894 EEG 149 +150 0.06561825 -0.2506161 0.023840595 0.024283894 EEG 150 +151 0.08375779 -0.200153314 0.023840595 0.024283894 EEG 151 +152 0.093577895 -0.148219199 0.023840595 0.024283894 EEG 152 +153 0.093818787 -0.102184911 0.023840595 0.024283894 EEG 153 +154 0.092860036 -0.059724481 0.023840595 0.024283894 EEG 154 +155 0.086703907 -0.006962228 0.023840595 0.024283894 EEG 155 +156 0.032116421 -0.419782634 0.023840595 0.024283894 EEG 156 +157 0.054701526 -0.36252645 0.023840595 0.024283894 EEG 157 +158 0.074015552 -0.317797572 0.023840595 0.024283894 EEG 158 +159 0.09913078 -0.279612547 0.023840595 0.024283894 EEG 159 +160 0.117304936 -0.222733874 0.023840595 0.024283894 EEG 160 +161 0.123315473 -0.169463521 0.023840595 0.024283894 EEG 161 +162 0.125435162 -0.117006671 0.023840595 0.024283894 EEG 162 +163 0.122986168 -0.070147895 0.023840595 0.024283894 EEG 163 +164 0.117629392 -0.020953359 0.023840595 0.024283894 EEG 164 +165 0.061719572 -0.45 0.023840595 0.024283894 EEG 165 +166 0.085226238 -0.411234759 0.023840595 0.024283894 EEG 166 +167 0.106134228 -0.360226213 0.023840595 0.024283894 EEG 167 +168 0.148968879 -0.297338854 0.023840595 0.024283894 EEG 168 +169 0.156365562 -0.241406814 0.023840595 0.024283894 EEG 169 +170 0.16089296 -0.182074387 0.023840595 0.024283894 EEG 170 +171 0.158874627 -0.130476761 0.023840595 0.024283894 EEG 171 +172 0.152612576 -0.080357072 0.023840595 0.024283894 EEG 172 +173 0.142940198 -0.038849379 0.023840595 0.024283894 EEG 173 +174 0.11640639 -0.433892117 0.023840595 0.024283894 EEG 174 +175 0.142872329 -0.395550026 0.023840595 0.024283894 EEG 175 +176 0.160198907 -0.335751192 0.023840595 0.024283894 EEG 176 +177 0.194042397 -0.266008675 0.023840595 0.024283894 EEG 177 +178 0.200260526 -0.201104991 0.023840595 0.024283894 EEG 178 +179 0.201004697 -0.132397774 0.023840595 0.024283894 EEG 179 +180 0.186334435 -0.079063391 0.023840595 0.024283894 EEG 180 +181 0.170816713 -0.027588171 0.023840595 0.024283894 EEG 181 +182 0.144183544 0.006552794 0.023840595 0.024283894 EEG 182 +183 0.11607512 0.026701856 0.023840595 0.024283894 EEG 183 +184 0.087032894 0.041560718 0.023840595 0.024283894 EEG 184 +185 0.055587556 0.053147386 0.023840595 0.024283894 EEG 185 +186 0.017539353 0.062826857 0.023840595 0.024283894 EEG 186 +187 0.178151028 -0.424680349 0.023840595 0.024283894 EEG 187 +188 0.20031364 -0.367491502 0.023840595 0.024283894 EEG 188 +189 0.215607267 -0.297916345 0.023840595 0.024283894 EEG 189 +190 0.235119884 -0.22133859 0.023840595 0.024283894 EEG 190 +191 0.230231782 -0.157310034 0.023840595 0.024283894 EEG 191 +192 0.227828247 -0.074709585 0.023840595 0.024283894 EEG 192 +193 0.202988841 -0.017932839 0.023840595 0.024283894 EEG 193 +194 0.175001011 0.027246728 0.023840595 0.024283894 EEG 194 +195 0.142622009 0.056366314 0.023840595 0.024283894 EEG 195 +196 0.108362109 0.07207399 0.023840595 0.024283894 EEG 196 +197 0.076990927 0.086006856 0.023840595 0.024283894 EEG 197 +198 0.036255497 0.09269913 0.023840595 0.024283894 EEG 198 +199 0.235425173 -0.391140875 0.023840595 0.024283894 EEG 199 +200 0.264402365 -0.317489099 0.023840595 0.024283894 EEG 200 +201 0.264511728 -0.247963981 0.023840595 0.024283894 EEG 201 +202 0.241320281 0.000293927 0.023840595 0.024283894 EEG 202 +203 0.20434592 0.049982898 0.023840595 0.024283894 EEG 203 +204 0.169122926 0.084563661 0.023840595 0.024283894 EEG 204 +205 0.132742164 0.104084677 0.023840595 0.024283894 EEG 205 +206 0.094840856 0.116834626 0.023840595 0.024283894 EEG 206 +207 0.055153266 0.126645408 0.023840595 0.024283894 EEG 207 +208 0.309236143 -0.330394078 0.023840595 0.024283894 EEG 208 +209 0.320841548 -0.246056831 0.023840595 0.024283894 EEG 209 +210 0.277394242 0.035815905 0.023840595 0.024283894 EEG 210 +211 0.237546771 0.082946276 0.023840595 0.024283894 EEG 211 +212 0.196096643 0.121848964 0.023840595 0.024283894 EEG 212 +213 0.156410469 0.141423921 0.023840595 0.024283894 EEG 213 +214 0.116009122 0.150111634 0.023840595 0.024283894 EEG 214 +215 0.079525249 0.158534511 0.023840595 0.024283894 EEG 215 +216 0.376606255 -0.236283155 0.023840595 0.024283894 EEG 216 +217 0.384631539 -0.115563191 0.023840595 0.024283894 EEG 217 +218 0.364333595 -0.009526546 0.023840595 0.024283894 EEG 218 +219 0.32017538 0.064356008 0.023840595 0.024283894 EEG 219 +220 0.271241865 0.131933691 0.023840595 0.024283894 EEG 220 +221 0.21721779 0.1735557 0.023840595 0.024283894 EEG 221 +222 0.17285275 0.187572361 0.023840595 0.024283894 EEG 222 +223 0.130890927 0.191286703 0.023840595 0.024283894 EEG 223 +224 0.098479668 0.187945851 0.023840595 0.024283894 EEG 224 +225 0.316289645 0.145736715 0.023840595 0.024283894 EEG 225 +226 0.302702771 0.230332844 0.023840595 0.024283894 EEG 226 +227 0.368412876 0.104246485 0.023840595 0.024283894 EEG 227 +228 0.409165374 0.012374488 0.023840595 0.024283894 EEG 228 +229 0.423731189 -0.12797492 0.023840595 0.024283894 EEG 229 +230 0.298254153 0.303894316 0.023840595 0.024283894 EEG 230 +231 0.362100214 0.20909316 0.023840595 0.024283894 EEG 231 +232 0.410199617 0.143137194 0.023840595 0.024283894 EEG 232 +233 0.447869069 0.013249996 0.023840595 0.024283894 EEG 233 +234 0.269381414 0.382730951 0.023840595 0.024283894 EEG 234 +235 0.342518502 0.308483235 0.023840595 0.024283894 EEG 235 +236 0.395968691 0.254174349 0.023840595 0.024283894 EEG 236 +237 0.45 0.157922288 0.023840595 0.024283894 EEG 237 +238 0.2187115 0.45 0.023840595 0.024283894 EEG 238 +239 0.327880174 0.384827106 0.023840595 0.024283894 EEG 239 +240 0.38583302 0.329449945 0.023840595 0.024283894 EEG 240 +241 -0.2187115 0.45 0.023840595 0.024283894 EEG 241 +242 -0.327880174 0.384827106 0.023840595 0.024283894 EEG 242 +243 -0.38583302 0.329449945 0.023840595 0.024283894 EEG 243 +244 -0.269381414 0.382730951 0.023840595 0.024283894 EEG 244 +245 -0.342518502 0.308483235 0.023840595 0.024283894 EEG 245 +246 -0.395968691 0.254174349 0.023840595 0.024283894 EEG 246 +247 -0.45 0.157922288 0.023840595 0.024283894 EEG 247 +248 -0.298254153 0.303894316 0.023840595 0.024283894 EEG 248 +249 -0.362100214 0.20909316 0.023840595 0.024283894 EEG 249 +250 -0.410199617 0.143137194 0.023840595 0.024283894 EEG 250 +251 -0.447869069 0.013249996 0.023840595 0.024283894 EEG 251 +252 -0.302702771 0.230332844 0.023840595 0.024283894 EEG 252 +253 -0.316289645 0.145736715 0.023840595 0.024283894 EEG 253 +254 -0.368412876 0.104246485 0.023840595 0.024283894 EEG 254 +255 -0.409165374 0.012374488 0.023840595 0.024283894 EEG 255 +256 -0.423731189 -0.12797492 0.023840595 0.024283894 EEG 256 +257 -0.45 -0.45 0.023840595 0.024283894 EEG 257 +258 0.45 -0.45 0.023840595 0.024283894 EEG 258 diff --git a/mne-python/source/mne/channels/data/layouts/GeodesicHeadWeb-130.lout b/mne-python/source/mne/channels/data/layouts/GeodesicHeadWeb-130.lout new file mode 100644 index 0000000000000000000000000000000000000000..32358fea193842f78e204bc66245bc336cfb410f --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/GeodesicHeadWeb-130.lout @@ -0,0 +1,132 @@ + -42.19 43.52 -41.70 28.71 +001 0.50 0.74 0.02 0.02 E1 +002 0.53 0.79 0.02 0.02 E2 +003 0.55 0.73 0.02 0.02 E3 +004 0.50 0.69 0.02 0.02 E4 +005 0.45 0.73 0.02 0.02 E5 +006 0.46 0.79 0.02 0.02 E6 +007 0.50 0.85 0.02 0.02 E7 +008 0.58 0.84 0.02 0.02 E8 +009 0.60 0.77 0.02 0.02 E9 +010 0.60 0.70 0.02 0.02 E10 +011 0.55 0.68 0.02 0.02 E11 +012 0.50 0.64 0.02 0.02 E12 +013 0.45 0.68 0.02 0.02 E13 +014 0.40 0.70 0.02 0.02 E14 +015 0.39 0.77 0.02 0.02 E15 +016 0.41 0.84 0.02 0.02 E16 +017 0.44 0.91 0.02 0.02 E17 +018 0.66 0.79 0.02 0.02 E18 +019 0.60 0.64 0.02 0.02 E19 +020 0.45 0.62 0.02 0.02 E20 +021 0.34 0.72 0.02 0.02 E21 +022 0.73 0.87 0.02 0.02 E22 +023 0.76 0.93 0.02 0.02 E23 +024 0.85 0.83 0.02 0.02 E24 +025 0.86 0.74 0.02 0.02 E25 +026 0.80 0.72 0.02 0.02 E26 +027 0.74 0.81 0.02 0.02 E27 +028 0.65 0.88 0.02 0.02 E28 +029 0.55 0.91 0.02 0.02 E29 +030 0.50 0.96 0.02 0.02 E30 +031 0.63 0.98 0.02 0.02 E31 +032 0.83 0.63 0.02 0.02 E32 +033 0.72 0.73 0.02 0.02 E33 +034 0.67 0.62 0.02 0.02 E34 +035 0.72 0.61 0.02 0.02 E35 +036 0.68 0.56 0.02 0.02 E36 +037 0.62 0.59 0.02 0.02 E37 +038 0.63 0.66 0.02 0.02 E38 +039 0.69 0.67 0.02 0.02 E39 +040 0.76 0.64 0.02 0.02 E40 +041 0.77 0.55 0.02 0.02 E41 +042 0.72 0.51 0.02 0.02 E42 +043 0.67 0.49 0.02 0.02 E43 +044 0.63 0.53 0.02 0.02 E44 +045 0.58 0.58 0.02 0.02 E45 +046 0.66 0.72 0.02 0.02 E46 +047 0.90 0.49 0.02 0.02 E47 +048 0.84 0.51 0.02 0.02 E48 +049 0.88 0.23 0.02 0.02 E49 +050 0.79 0.23 0.02 0.02 E50 +051 0.74 0.29 0.02 0.02 E51 +052 0.72 0.37 0.02 0.02 E52 +053 0.76 0.46 0.02 0.02 E53 +054 0.61 0.39 0.02 0.02 E54 +055 0.61 0.33 0.02 0.02 E55 +056 0.56 0.37 0.02 0.02 E56 +057 0.57 0.43 0.02 0.02 E57 +058 0.64 0.44 0.02 0.02 E58 +059 0.65 0.37 0.02 0.02 E59 +060 0.66 0.30 0.02 0.02 E60 +061 0.58 0.26 0.02 0.02 E61 +062 0.54 0.30 0.02 0.02 E62 +063 0.53 0.41 0.02 0.02 E63 +064 0.55 0.47 0.02 0.02 E64 +065 0.61 0.48 0.02 0.02 E65 +066 0.70 0.44 0.02 0.02 E66 +067 0.50 0.12 0.02 0.02 E67 +068 0.45 0.11 0.02 0.02 E68 +069 0.47 0.18 0.02 0.02 E69 +070 0.53 0.18 0.02 0.02 E70 +071 0.55 0.11 0.02 0.02 E71 +072 0.73 0.08 0.02 0.02 E72 +073 0.50 0.02 0.02 0.02 E73 +074 0.28 0.07 0.02 0.02 E74 +075 0.22 0.22 0.02 0.02 E75 +076 0.35 0.22 0.02 0.02 E76 +077 0.41 0.26 0.02 0.02 E77 +078 0.50 0.25 0.02 0.02 E78 +079 0.65 0.22 0.02 0.02 E79 +080 0.39 0.39 0.02 0.02 E80 +081 0.34 0.36 0.02 0.02 E81 +082 0.36 0.43 0.02 0.02 E82 +083 0.42 0.44 0.02 0.02 E83 +084 0.45 0.37 0.02 0.02 E84 +085 0.40 0.33 0.02 0.02 E85 +086 0.34 0.30 0.02 0.02 E86 +087 0.28 0.37 0.02 0.02 E87 +088 0.30 0.43 0.02 0.02 E88 +089 0.33 0.49 0.02 0.02 E89 +090 0.39 0.48 0.02 0.02 E90 +091 0.45 0.47 0.02 0.02 E91 +092 0.47 0.41 0.02 0.02 E92 +093 0.46 0.30 0.02 0.02 E93 +094 0.47 0.51 0.02 0.02 E94 +095 0.46 0.57 0.02 0.02 E95 +096 0.50 0.60 0.02 0.02 E96 +097 0.54 0.57 0.02 0.02 E97 +098 0.52 0.51 0.02 0.02 E98 +099 0.50 0.46 0.02 0.02 E99 +100 0.42 0.52 0.02 0.02 E100 +101 0.42 0.58 0.02 0.02 E101 +102 0.55 0.62 0.02 0.02 E102 +103 0.58 0.52 0.02 0.02 E103 +104 0.16 0.52 0.02 0.02 E104 +105 0.10 0.49 0.02 0.02 E105 +106 0.09 0.27 0.02 0.02 E106 +107 0.15 0.75 0.02 0.02 E107 +108 0.17 0.63 0.02 0.02 E108 +109 0.22 0.55 0.02 0.02 E109 +110 0.24 0.45 0.02 0.02 E110 +111 0.26 0.29 0.02 0.02 E111 +112 0.33 0.61 0.02 0.02 E112 +113 0.30 0.66 0.02 0.02 E113 +114 0.36 0.66 0.02 0.02 E114 +115 0.37 0.59 0.02 0.02 E115 +116 0.33 0.56 0.02 0.02 E116 +117 0.28 0.60 0.02 0.02 E117 +118 0.24 0.64 0.02 0.02 E118 +119 0.27 0.73 0.02 0.02 E119 +120 0.40 0.64 0.02 0.02 E120 +121 0.37 0.53 0.02 0.02 E121 +122 0.27 0.51 0.02 0.02 E122 +123 0.27 0.88 0.02 0.02 E123 +124 0.26 0.81 0.02 0.02 E124 +125 0.20 0.72 0.02 0.02 E125 +126 0.16 0.83 0.02 0.02 E126 +127 0.25 0.93 0.02 0.02 E127 +128 0.37 0.98 0.02 0.02 E128 +129 0.35 0.88 0.02 0.02 E129 +130 0.33 0.79 0.02 0.02 E130 +131 0.50 0.55 0.02 0.02 E131 diff --git a/mne-python/source/mne/channels/data/layouts/GeodesicHeadWeb-280.lout b/mne-python/source/mne/channels/data/layouts/GeodesicHeadWeb-280.lout new file mode 100644 index 0000000000000000000000000000000000000000..7585787808643cf9798ac17764dec52a36ba3e0e --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/GeodesicHeadWeb-280.lout @@ -0,0 +1,282 @@ + -42.19 43.52 -41.70 28.71 +001 0.49 0.77 0.02 0.02 E1 +002 0.52 0.80 0.02 0.02 E2 +003 0.53 0.76 0.02 0.02 E3 +004 0.49 0.73 0.02 0.02 E4 +005 0.46 0.76 0.02 0.02 E5 +006 0.47 0.80 0.02 0.02 E6 +007 0.49 0.84 0.02 0.02 E7 +008 0.54 0.84 0.02 0.02 E8 +009 0.55 0.80 0.02 0.02 E9 +010 0.57 0.74 0.02 0.02 E10 +011 0.53 0.71 0.02 0.02 E11 +012 0.49 0.68 0.02 0.02 E12 +013 0.46 0.71 0.02 0.02 E13 +014 0.42 0.74 0.02 0.02 E14 +015 0.43 0.79 0.02 0.02 E15 +016 0.45 0.84 0.02 0.02 E16 +017 0.47 0.87 0.02 0.02 E17 +018 0.52 0.87 0.02 0.02 E18 +019 0.57 0.86 0.02 0.02 E19 +020 0.59 0.83 0.02 0.02 E20 +021 0.59 0.79 0.02 0.02 E21 +022 0.60 0.73 0.02 0.02 E22 +023 0.57 0.71 0.02 0.02 E23 +024 0.53 0.67 0.02 0.02 E24 +025 0.49 0.65 0.02 0.02 E25 +026 0.46 0.67 0.02 0.02 E26 +027 0.43 0.70 0.02 0.02 E27 +028 0.39 0.73 0.02 0.02 E28 +029 0.39 0.78 0.02 0.02 E29 +030 0.40 0.83 0.02 0.02 E30 +031 0.41 0.86 0.02 0.02 E31 +032 0.49 0.93 0.02 0.02 E32 +033 0.64 0.81 0.02 0.02 E33 +034 0.56 0.66 0.02 0.02 E34 +035 0.43 0.66 0.02 0.02 E35 +036 0.35 0.80 0.02 0.02 E36 +037 0.73 0.86 0.02 0.02 E37 +038 0.76 0.89 0.02 0.02 E38 +039 0.76 0.84 0.02 0.02 E39 +040 0.72 0.82 0.02 0.02 E40 +041 0.69 0.86 0.02 0.02 E41 +042 0.67 0.99 0.02 0.02 E42 +043 0.79 0.91 0.02 0.02 E43 +044 0.85 0.83 0.02 0.02 E44 +045 0.84 0.77 0.02 0.02 E45 +046 0.82 0.74 0.02 0.02 E46 +047 0.76 0.77 0.02 0.02 E47 +048 0.72 0.76 0.02 0.02 E48 +049 0.68 0.81 0.02 0.02 E49 +050 0.64 0.83 0.02 0.02 E50 +051 0.62 0.85 0.02 0.02 E51 +052 0.58 0.98 0.02 0.02 E52 +053 0.90 0.82 0.02 0.02 E53 +054 0.80 0.70 0.02 0.02 E54 +055 0.76 0.70 0.02 0.02 E55 +056 0.68 0.64 0.02 0.02 E56 +057 0.69 0.68 0.02 0.02 E57 +058 0.71 0.64 0.02 0.02 E58 +059 0.68 0.60 0.02 0.02 E59 +060 0.65 0.62 0.02 0.02 E60 +061 0.65 0.67 0.02 0.02 E61 +062 0.67 0.71 0.02 0.02 E62 +063 0.71 0.72 0.02 0.02 E63 +064 0.73 0.68 0.02 0.02 E64 +065 0.75 0.63 0.02 0.02 E65 +066 0.72 0.59 0.02 0.02 E66 +067 0.69 0.56 0.02 0.02 E67 +068 0.65 0.58 0.02 0.02 E68 +069 0.61 0.60 0.02 0.02 E69 +070 0.61 0.66 0.02 0.02 E70 +071 0.62 0.70 0.02 0.02 E71 +072 0.64 0.76 0.02 0.02 E72 +073 0.69 0.76 0.02 0.02 E73 +074 0.79 0.61 0.02 0.02 E74 +075 0.76 0.57 0.02 0.02 E75 +076 0.73 0.53 0.02 0.02 E76 +077 0.69 0.49 0.02 0.02 E77 +078 0.65 0.53 0.02 0.02 E78 +079 0.62 0.54 0.02 0.02 E79 +080 0.59 0.57 0.02 0.02 E80 +081 0.59 0.63 0.02 0.02 E81 +082 0.60 0.69 0.02 0.02 E82 +083 0.76 0.48 0.02 0.02 E83 +084 0.61 0.50 0.02 0.02 E84 +085 0.90 0.51 0.02 0.02 E85 +086 0.91 0.63 0.02 0.02 E86 +087 0.94 0.58 0.02 0.02 E87 +088 0.97 0.54 0.02 0.02 E88 +089 0.94 0.51 0.02 0.02 E89 +090 0.91 0.46 0.02 0.02 E90 +091 0.87 0.48 0.02 0.02 E91 +092 0.82 0.49 0.02 0.02 E92 +093 0.91 0.73 0.02 0.02 E93 +094 0.97 0.68 0.02 0.02 E94 +095 0.94 0.33 0.02 0.02 E95 +096 0.88 0.31 0.02 0.02 E96 +097 0.77 0.22 0.02 0.02 E97 +098 0.82 0.34 0.02 0.02 E98 +099 0.79 0.37 0.02 0.02 E99 +100 0.77 0.41 0.02 0.02 E100 +101 0.79 0.50 0.02 0.02 E101 +102 0.83 0.17 0.02 0.02 E102 +103 0.74 0.29 0.02 0.02 E103 +104 0.62 0.36 0.02 0.02 E104 +105 0.64 0.39 0.02 0.02 E105 +106 0.66 0.35 0.02 0.02 E106 +107 0.62 0.32 0.02 0.02 E107 +108 0.59 0.35 0.02 0.02 E108 +109 0.60 0.39 0.02 0.02 E109 +110 0.62 0.43 0.02 0.02 E110 +111 0.67 0.43 0.02 0.02 E111 +112 0.68 0.39 0.02 0.02 E112 +113 0.70 0.33 0.02 0.02 E113 +114 0.66 0.31 0.02 0.02 E114 +115 0.62 0.27 0.02 0.02 E115 +116 0.58 0.31 0.02 0.02 E116 +117 0.55 0.34 0.02 0.02 E117 +118 0.56 0.39 0.02 0.02 E118 +119 0.58 0.43 0.02 0.02 E119 +120 0.59 0.46 0.02 0.02 E120 +121 0.65 0.48 0.02 0.02 E121 +122 0.71 0.44 0.02 0.02 E122 +123 0.73 0.40 0.02 0.02 E123 +124 0.73 0.34 0.02 0.02 E124 +125 0.67 0.27 0.02 0.02 E125 +126 0.60 0.23 0.02 0.02 E126 +127 0.56 0.25 0.02 0.02 E127 +128 0.53 0.28 0.02 0.02 E128 +129 0.49 0.31 0.02 0.02 E129 +130 0.52 0.36 0.02 0.02 E130 +131 0.53 0.41 0.02 0.02 E131 +132 0.55 0.45 0.02 0.02 E132 +133 0.49 0.24 0.02 0.02 E133 +134 0.49 0.40 0.02 0.02 E134 +135 0.49 0.13 0.02 0.02 E135 +136 0.51 0.16 0.02 0.02 E136 +137 0.52 0.11 0.02 0.02 E137 +138 0.49 0.08 0.02 0.02 E138 +139 0.46 0.11 0.02 0.02 E139 +140 0.47 0.16 0.02 0.02 E140 +141 0.49 0.19 0.02 0.02 E141 +142 0.54 0.19 0.02 0.02 E142 +143 0.55 0.14 0.02 0.02 E143 +144 0.57 0.09 0.02 0.02 E144 +145 0.53 0.06 0.02 0.02 E145 +146 0.49 0.03 0.02 0.02 E146 +147 0.45 0.06 0.02 0.02 E147 +148 0.42 0.09 0.02 0.02 E148 +149 0.43 0.15 0.02 0.02 E149 +150 0.45 0.19 0.02 0.02 E150 +151 0.47 0.21 0.02 0.02 E151 +152 0.52 0.21 0.02 0.02 E152 +153 0.62 0.21 0.02 0.02 E153 +154 0.68 0.19 0.02 0.02 E154 +155 0.75 0.15 0.02 0.02 E155 +156 0.68 0.06 0.02 0.02 E156 +157 0.49 0.01 0.02 0.02 E157 +158 0.31 0.05 0.02 0.02 E158 +159 0.28 0.12 0.02 0.02 E159 +160 0.21 0.21 0.02 0.02 E160 +161 0.29 0.20 0.02 0.02 E161 +162 0.34 0.21 0.02 0.02 E162 +163 0.38 0.24 0.02 0.02 E163 +164 0.15 0.16 0.02 0.02 E164 +165 0.25 0.28 0.02 0.02 E165 +166 0.47 0.51 0.02 0.02 E166 +167 0.46 0.55 0.02 0.02 E167 +168 0.49 0.58 0.02 0.02 E168 +169 0.52 0.55 0.02 0.02 E169 +170 0.51 0.52 0.02 0.02 E170 +171 0.46 0.48 0.02 0.02 E171 +172 0.44 0.53 0.02 0.02 E172 +173 0.43 0.56 0.02 0.02 E173 +174 0.46 0.59 0.02 0.02 E174 +175 0.49 0.61 0.02 0.02 E175 +176 0.52 0.59 0.02 0.02 E176 +177 0.55 0.56 0.02 0.02 E177 +178 0.54 0.53 0.02 0.02 E178 +179 0.53 0.48 0.02 0.02 E179 +180 0.51 0.44 0.02 0.02 E180 +181 0.47 0.44 0.02 0.02 E181 +182 0.43 0.46 0.02 0.02 E182 +183 0.41 0.49 0.02 0.02 E183 +184 0.40 0.53 0.02 0.02 E184 +185 0.41 0.58 0.02 0.02 E185 +186 0.43 0.61 0.02 0.02 E186 +187 0.46 0.64 0.02 0.02 E187 +188 0.53 0.64 0.02 0.02 E188 +189 0.56 0.61 0.02 0.02 E189 +190 0.59 0.53 0.02 0.02 E190 +191 0.57 0.48 0.02 0.02 E191 +192 0.37 0.50 0.02 0.02 E192 +193 0.36 0.36 0.02 0.02 E193 +194 0.39 0.39 0.02 0.02 E194 +195 0.40 0.35 0.02 0.02 E195 +196 0.36 0.32 0.02 0.02 E196 +197 0.33 0.35 0.02 0.02 E197 +198 0.34 0.39 0.02 0.02 E198 +199 0.36 0.44 0.02 0.02 E199 +200 0.41 0.43 0.02 0.02 E200 +201 0.43 0.38 0.02 0.02 E201 +202 0.44 0.33 0.02 0.02 E202 +203 0.40 0.31 0.02 0.02 E203 +204 0.36 0.28 0.02 0.02 E204 +205 0.33 0.31 0.02 0.02 E205 +206 0.29 0.34 0.02 0.02 E206 +207 0.31 0.39 0.02 0.02 E207 +208 0.32 0.43 0.02 0.02 E208 +209 0.35 0.48 0.02 0.02 E209 +210 0.39 0.46 0.02 0.02 E210 +211 0.45 0.41 0.02 0.02 E211 +212 0.47 0.36 0.02 0.02 E212 +213 0.46 0.28 0.02 0.02 E213 +214 0.42 0.25 0.02 0.02 E214 +215 0.31 0.28 0.02 0.02 E215 +216 0.26 0.34 0.02 0.02 E216 +217 0.22 0.44 0.02 0.02 E217 +218 0.26 0.40 0.02 0.02 E218 +219 0.28 0.45 0.02 0.02 E219 +220 0.30 0.49 0.02 0.02 E220 +221 0.23 0.48 0.02 0.02 E221 +222 0.10 0.51 0.02 0.02 E222 +223 0.18 0.49 0.02 0.02 E223 +224 0.13 0.48 0.02 0.02 E224 +225 0.09 0.46 0.02 0.02 E225 +226 0.06 0.51 0.02 0.02 E226 +227 0.03 0.54 0.02 0.02 E227 +228 0.06 0.58 0.02 0.02 E228 +229 0.09 0.63 0.02 0.02 E229 +230 0.18 0.76 0.02 0.02 E230 +231 0.19 0.71 0.02 0.02 E231 +232 0.21 0.64 0.02 0.02 E232 +233 0.20 0.54 0.02 0.02 E233 +234 0.19 0.39 0.02 0.02 E234 +235 0.17 0.33 0.02 0.02 E235 +236 0.10 0.31 0.02 0.02 E236 +237 0.05 0.33 0.02 0.02 E237 +238 0.03 0.67 0.02 0.02 E238 +239 0.09 0.74 0.02 0.02 E239 +240 0.15 0.79 0.02 0.02 E240 +241 0.23 0.78 0.02 0.02 E241 +242 0.08 0.81 0.02 0.02 E242 +243 0.31 0.64 0.02 0.02 E243 +244 0.34 0.67 0.02 0.02 E244 +245 0.34 0.62 0.02 0.02 E245 +246 0.31 0.60 0.02 0.02 E246 +247 0.27 0.63 0.02 0.02 E247 +248 0.29 0.67 0.02 0.02 E248 +249 0.32 0.71 0.02 0.02 E249 +250 0.37 0.70 0.02 0.02 E250 +251 0.37 0.65 0.02 0.02 E251 +252 0.38 0.60 0.02 0.02 E252 +253 0.34 0.58 0.02 0.02 E253 +254 0.30 0.55 0.02 0.02 E254 +255 0.27 0.58 0.02 0.02 E255 +256 0.23 0.62 0.02 0.02 E256 +257 0.25 0.67 0.02 0.02 E257 +258 0.28 0.72 0.02 0.02 E258 +259 0.30 0.76 0.02 0.02 E259 +260 0.35 0.75 0.02 0.02 E260 +261 0.40 0.68 0.02 0.02 E261 +262 0.40 0.64 0.02 0.02 E262 +263 0.37 0.55 0.02 0.02 E263 +264 0.34 0.52 0.02 0.02 E264 +265 0.26 0.53 0.02 0.02 E265 +266 0.23 0.56 0.02 0.02 E266 +267 0.23 0.70 0.02 0.02 E267 +268 0.28 0.77 0.02 0.02 E268 +269 0.32 0.81 0.02 0.02 E269 +270 0.27 0.87 0.02 0.02 E270 +271 0.23 0.89 0.02 0.02 E271 +272 0.24 0.84 0.02 0.02 E272 +273 0.28 0.83 0.02 0.02 E273 +274 0.30 0.87 0.02 0.02 E274 +275 0.32 0.99 0.02 0.02 E275 +276 0.21 0.91 0.02 0.02 E276 +277 0.16 0.87 0.02 0.02 E277 +278 0.34 0.83 0.02 0.02 E278 +279 0.37 0.84 0.02 0.02 E279 +280 0.41 0.98 0.02 0.02 E280 +281 0.49 0.54 0.02 0.02 E281 diff --git a/mne-python/source/mne/channels/data/layouts/KIT-125.lout b/mne-python/source/mne/channels/data/layouts/KIT-125.lout new file mode 100644 index 0000000000000000000000000000000000000000..5b1e987f38a7cae94dcdaa5c946cd02eb32cee99 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/KIT-125.lout @@ -0,0 +1,126 @@ + -0.50 0.50 -0.50 0.50 +001 0.12 -0.10 0.04 0.03 MEG 001 +002 0.15 -0.06 0.04 0.03 MEG 002 +003 0.03 -0.15 0.04 0.03 MEG 003 +004 -0.22 -0.29 0.04 0.03 MEG 004 +005 -0.28 -0.23 0.04 0.03 MEG 005 +006 -0.33 -0.15 0.04 0.03 MEG 006 +007 -0.07 -0.36 0.04 0.03 MEG 007 +008 0.09 -0.36 0.04 0.03 MEG 008 +009 -0.06 -0.25 0.04 0.03 MEG 009 +010 -0.18 0.18 0.04 0.03 MEG 010 +011 -0.10 0.25 0.04 0.03 MEG 011 +012 -0.15 0.22 0.04 0.03 MEG 012 +013 -0.37 0.13 0.04 0.03 MEG 013 +014 -0.36 -0.06 0.04 0.03 MEG 014 +015 -0.18 -0.41 0.04 0.03 MEG 015 +016 -0.27 -0.35 0.04 0.03 MEG 016 +017 -0.16 -0.19 0.04 0.03 MEG 017 +018 -0.18 -0.10 0.04 0.03 MEG 018 +019 -0.14 -0.14 0.04 0.03 MEG 019 +020 -0.30 -0.04 0.04 0.03 MEG 020 +021 -0.31 0.11 0.04 0.03 MEG 021 +022 -0.37 0.04 0.04 0.03 MEG 022 +023 -0.20 -0.14 0.04 0.03 MEG 023 +024 -0.11 -0.23 0.04 0.03 MEG 024 +025 -0.11 -0.11 0.04 0.03 MEG 025 +026 -0.02 -0.14 0.04 0.03 MEG 026 +027 -0.13 -0.28 0.04 0.03 MEG 027 +028 -0.24 -0.18 0.04 0.03 MEG 028 +029 -0.19 -0.23 0.04 0.03 MEG 029 +030 -0.21 0.01 0.04 0.03 MEG 030 +031 -0.21 0.07 0.04 0.03 MEG 031 +032 -0.20 0.13 0.04 0.03 MEG 032 +033 -0.12 0.08 0.04 0.03 MEG 033 +034 -0.09 -0.07 0.04 0.03 MEG 034 +035 -0.12 0.03 0.04 0.03 MEG 035 +036 -0.25 0.11 0.04 0.03 MEG 036 +037 -0.25 -0.03 0.04 0.03 MEG 037 +038 -0.23 -0.09 0.04 0.03 MEG 038 +039 -0.26 0.04 0.04 0.03 MEG 039 +040 -0.14 -0.06 0.04 0.03 MEG 040 +041 -0.00 0.29 0.04 0.03 MEG 041 +042 0.09 0.26 0.04 0.03 MEG 042 +043 -0.07 -0.00 0.04 0.03 MEG 043 +044 -0.07 0.09 0.04 0.03 MEG 044 +045 -0.34 -0.28 0.04 0.03 MEG 045 +046 -0.43 -0.09 0.04 0.03 MEG 046 +047 -0.45 0.03 0.04 0.03 MEG 047 +048 -0.44 0.14 0.04 0.03 MEG 048 +049 -0.07 0.21 0.04 0.03 MEG 049 +050 -0.15 0.15 0.04 0.03 MEG 050 +051 -0.16 -0.02 0.04 0.03 MEG 051 +052 -0.17 0.04 0.04 0.03 MEG 052 +053 0.07 0.17 0.04 0.03 MEG 053 +054 -0.07 0.17 0.04 0.03 MEG 054 +055 0.00 0.14 0.04 0.03 MEG 055 +056 0.08 0.09 0.04 0.03 MEG 056 +057 0.21 -0.39 0.04 0.03 MEG 057 +058 0.09 -0.06 0.04 0.03 MEG 058 +059 -0.04 -0.09 0.04 0.03 MEG 059 +060 0.05 -0.09 0.04 0.03 MEG 060 +061 0.17 -0.18 0.04 0.03 MEG 061 +062 0.06 -0.19 0.04 0.03 MEG 062 +063 -0.04 -0.19 0.04 0.03 MEG 063 +064 0.01 -0.20 0.04 0.03 MEG 064 +065 0.19 -0.09 0.04 0.03 MEG 065 +066 0.01 -0.31 0.04 0.03 MEG 066 +067 0.14 -0.27 0.04 0.03 MEG 067 +068 0.24 -0.28 0.04 0.03 MEG 068 +069 0.34 -0.13 0.04 0.03 MEG 069 +070 0.29 -0.21 0.04 0.03 MEG 070 +071 0.30 -0.33 0.04 0.03 MEG 071 +072 0.02 -0.45 0.04 0.03 MEG 072 +073 0.21 -0.14 0.04 0.03 MEG 073 +074 0.24 -0.08 0.04 0.03 MEG 074 +075 0.26 0.12 0.04 0.03 MEG 075 +076 0.26 0.05 0.04 0.03 MEG 076 +077 0.07 -0.24 0.04 0.03 MEG 077 +078 0.12 -0.22 0.04 0.03 MEG 078 +079 0.22 0.02 0.04 0.03 MEG 079 +080 0.15 -0.13 0.04 0.03 MEG 080 +081 0.43 0.16 0.04 0.03 MEG 081 +082 0.22 0.09 0.04 0.03 MEG 082 +083 0.18 0.19 0.04 0.03 MEG 083 +084 0.14 0.23 0.04 0.03 MEG 084 +085 0.20 0.14 0.04 0.03 MEG 085 +086 0.36 -0.04 0.04 0.03 MEG 086 +087 0.36 0.15 0.04 0.03 MEG 087 +088 0.26 -0.02 0.04 0.03 MEG 088 +089 0.25 -0.17 0.04 0.03 MEG 089 +090 0.30 0.13 0.04 0.03 MEG 090 +091 0.30 -0.03 0.04 0.03 MEG 091 +092 0.37 0.05 0.04 0.03 MEG 092 +093 0.14 0.15 0.04 0.03 MEG 093 +094 0.17 0.05 0.04 0.03 MEG 094 +095 0.17 -0.01 0.04 0.03 MEG 095 +096 0.45 0.06 0.04 0.03 MEG 096 +097 0.13 0.03 0.04 0.03 MEG 097 +098 -0.04 0.07 0.04 0.03 MEG 098 +099 0.04 0.07 0.04 0.03 MEG 099 +100 -0.04 0.01 0.04 0.03 MEG 100 +101 0.04 0.02 0.04 0.03 MEG 101 +102 0.36 -0.25 0.04 0.03 MEG 102 +103 0.44 -0.05 0.04 0.03 MEG 103 +104 0.20 -0.23 0.04 0.03 MEG 104 +105 0.08 -0.00 0.04 0.03 MEG 105 +106 -0.04 -0.04 0.04 0.03 MEG 106 +107 0.00 -0.05 0.04 0.03 MEG 107 +108 0.05 -0.04 0.04 0.03 MEG 108 +109 0.02 0.23 0.04 0.03 MEG 109 +110 -0.03 0.23 0.04 0.03 MEG 110 +111 0.07 0.22 0.04 0.03 MEG 111 +112 0.13 0.09 0.04 0.03 MEG 112 +113 0.18 -0.33 0.04 0.03 MEG 113 +114 -0.10 0.13 0.04 0.03 MEG 114 +115 0.11 -0.43 0.04 0.03 MEG 115 +116 0.29 -0.10 0.04 0.03 MEG 116 +117 -0.06 -0.30 0.04 0.03 MEG 117 +118 0.11 0.13 0.04 0.03 MEG 118 +119 0.21 -0.03 0.04 0.03 MEG 119 +120 0.08 -0.30 0.04 0.03 MEG 120 +121 -0.20 -0.05 0.04 0.03 MEG 121 +122 -0.08 -0.44 0.04 0.03 MEG 122 +123 -0.15 -0.34 0.04 0.03 MEG 123 +124 0.02 -0.37 0.04 0.03 MEG 124 +125 -0.28 -0.11 0.04 0.03 MEG 125 diff --git a/mne-python/source/mne/channels/data/layouts/KIT-157.lout b/mne-python/source/mne/channels/data/layouts/KIT-157.lout new file mode 100644 index 0000000000000000000000000000000000000000..2cf5637b843877f4f54bd6ce27b132a1f51f3d22 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/KIT-157.lout @@ -0,0 +1,158 @@ +-42.19 43.52 -41.7 28.71 +001 9.78 -14.18 4.00 3.00 MEG 001 +002 3.31 -16.56 4.00 3.00 MEG 002 +003 12.02 -19.42 4.00 3.00 MEG 003 +004 8.08 -21.05 4.00 3.00 MEG 004 +005 4.12 -22.01 4.00 3.00 MEG 005 +006 15.80 -16.63 4.00 3.00 MEG 006 +007 10.21 -12.01 4.00 3.00 MEG 007 +008 7.23 -13.67 4.00 3.00 MEG 008 +009 -22.12 -3.07 4.00 3.00 MEG 009 +010 -13.99 -13.09 4.00 3.00 MEG 010 +011 -21.05 -7.51 4.00 3.00 MEG 011 +012 -18.85 -12.06 4.00 3.00 MEG 012 +013 -0.14 -16.77 4.00 3.00 MEG 013 +014 -6.69 -15.41 4.00 3.00 MEG 014 +015 -10.69 -15.56 4.00 3.00 MEG 015 +016 -3.91 -10.00 4.00 3.00 MEG 016 +017 0.80 -6.66 4.00 3.00 MEG 017 +018 3.74 -20.66 4.00 3.00 MEG 018 +019 15.01 -15.63 4.00 3.00 MEG 019 +020 4.16 -14.75 4.00 3.00 MEG 020 +021 16.72 -0.60 4.00 3.00 MEG 021 +022 14.31 -7.30 4.00 3.00 MEG 022 +023 1.27 -13.23 4.00 3.00 MEG 023 +024 9.63 -10.10 4.00 3.00 MEG 024 +025 -1.74 -14.94 4.00 3.00 MEG 025 +026 -4.68 -14.12 4.00 3.00 MEG 026 +027 -1.65 -8.33 4.00 3.00 MEG 027 +028 -6.53 -8.53 4.00 3.00 MEG 028 +029 -8.52 -6.61 4.00 3.00 MEG 029 +030 -10.18 -4.27 4.00 3.00 MEG 030 +031 -11.14 -1.21 4.00 3.00 MEG 031 +032 -4.02 -18.39 4.00 3.00 MEG 032 +033 19.69 0.13 4.00 3.00 MEG 033 +034 4.03 -8.21 4.00 3.00 MEG 034 +035 3.56 0.14 4.00 3.00 MEG 035 +036 4.19 -12.79 4.00 3.00 MEG 036 +037 19.43 -3.03 4.00 3.00 MEG 037 +038 20.99 -9.54 4.00 3.00 MEG 038 +039 15.93 -11.27 4.00 3.00 MEG 039 +040 22.46 -5.52 4.00 3.00 MEG 040 +041 -9.37 -8.82 4.00 3.00 MEG 041 +042 -6.93 -10.92 4.00 3.00 MEG 042 +043 -1.56 -13.07 4.00 3.00 MEG 043 +044 -7.75 -20.89 4.00 3.00 MEG 044 +045 -11.74 -19.07 4.00 3.00 MEG 045 +046 0.31 -22.23 4.00 3.00 MEG 046 +047 -3.75 -21.89 4.00 3.00 MEG 047 +048 -3.89 -5.28 4.00 3.00 MEG 048 +049 23.23 -0.95 4.00 3.00 MEG 049 +050 13.94 -14.13 4.00 3.00 MEG 050 +051 7.41 -17.72 4.00 3.00 MEG 051 +052 19.50 -8.59 4.00 3.00 MEG 052 +053 18.26 -7.47 4.00 3.00 MEG 053 +054 18.19 -2.34 4.00 3.00 MEG 054 +055 14.76 -9.91 4.00 3.00 MEG 055 +056 21.32 -0.18 4.00 3.00 MEG 056 +057 -1.88 -3.98 4.00 3.00 MEG 057 +058 3.56 -3.73 4.00 3.00 MEG 058 +059 -12.57 -8.25 4.00 3.00 MEG 059 +060 -7.56 -12.70 4.00 3.00 MEG 060 +061 -15.02 -1.73 4.00 3.00 MEG 061 +062 -11.53 -17.47 4.00 3.00 MEG 062 +063 -0.18 -18.90 4.00 3.00 MEG 063 +064 -6.61 -0.05 4.00 3.00 MEG 064 +065 6.73 -9.47 4.00 3.00 MEG 065 +066 1.16 -8.63 4.00 3.00 MEG 066 +067 18.43 8.05 4.00 3.00 MEG 067 +068 16.27 12.00 4.00 3.00 MEG 068 +069 19.53 3.47 4.00 3.00 MEG 069 +070 11.49 5.68 4.00 3.00 MEG 070 +071 12.54 -0.07 4.00 3.00 MEG 071 +072 12.40 3.05 4.00 3.00 MEG 072 +073 -15.98 -9.55 4.00 3.00 MEG 073 +074 -18.65 -1.75 4.00 3.00 MEG 074 +075 -17.81 -5.83 4.00 3.00 MEG 075 +076 -1.09 0.06 4.00 3.00 MEG 076 +077 -1.11 2.07 4.00 3.00 MEG 077 +078 -17.59 -10.78 4.00 3.00 MEG 078 +079 -20.36 -2.47 4.00 3.00 MEG 079 +080 -16.06 10.29 4.00 3.00 MEG 080 +081 10.71 -5.93 4.00 3.00 MEG 081 +082 12.02 -3.35 4.00 3.00 MEG 082 +083 19.99 8.66 4.00 3.00 MEG 083 +084 15.61 15.53 4.00 3.00 MEG 084 +085 5.76 -4.95 4.00 3.00 MEG 085 +086 12.48 13.62 4.00 3.00 MEG 086 +087 18.03 3.69 4.00 3.00 MEG 087 +088 14.69 11.11 4.00 3.00 MEG 088 +089 -19.42 6.89 4.00 3.00 MEG 089 +090 -16.09 14.39 4.00 3.00 MEG 090 +091 -6.70 -5.77 4.00 3.00 MEG 091 +092 -12.37 -11.31 4.00 3.00 MEG 092 +093 -1.72 9.34 4.00 3.00 MEG 093 +094 -4.12 1.65 4.00 3.00 MEG 094 +095 -18.66 2.58 4.00 3.00 MEG 095 +096 -17.76 6.59 4.00 3.00 MEG 096 +097 8.82 -5.11 4.00 3.00 MEG 097 +098 8.79 -7.85 4.00 3.00 MEG 098 +099 15.43 6.10 4.00 3.00 MEG 099 +100 11.93 11.57 4.00 3.00 MEG 100 +101 16.58 7.80 4.00 3.00 MEG 101 +102 8.27 6.69 4.00 3.00 MEG 102 +103 11.62 -8.00 4.00 3.00 MEG 103 +104 13.11 -5.40 4.00 3.00 MEG 104 +105 -13.38 0.11 4.00 3.00 MEG 105 +106 -12.78 -3.22 4.00 3.00 MEG 106 +107 -12.98 3.35 4.00 3.00 MEG 107 +108 -11.84 6.58 4.00 3.00 MEG 108 +109 -10.08 9.11 4.00 3.00 MEG 109 +110 -16.27 -5.03 4.00 3.00 MEG 110 +111 -11.45 -6.21 4.00 3.00 MEG 111 +112 -0.59 5.83 4.00 3.00 MEG 112 +113 14.18 -2.06 4.00 3.00 MEG 113 +114 14.48 1.15 4.00 3.00 MEG 114 +115 12.68 7.37 4.00 3.00 MEG 115 +116 13.93 4.46 4.00 3.00 MEG 116 +117 8.98 11.57 4.00 3.00 MEG 117 +118 6.35 12.95 4.00 3.00 MEG 118 +119 11.01 9.71 4.00 3.00 MEG 119 +120 0.01 16.08 4.00 3.00 MEG 120 +121 -16.87 2.69 4.00 3.00 MEG 121 +122 -16.02 6.38 4.00 3.00 MEG 122 +123 -14.38 9.83 4.00 3.00 MEG 123 +124 -12.23 12.65 4.00 3.00 MEG 124 +125 -10.14 5.19 4.00 3.00 MEG 125 +126 -5.63 12.72 4.00 3.00 MEG 126 +127 -2.90 13.72 4.00 3.00 MEG 127 +128 -7.93 11.11 4.00 3.00 MEG 128 +129 6.83 14.86 4.00 3.00 MEG 129 +130 7.63 3.51 4.00 3.00 MEG 130 +131 8.56 0.40 4.00 3.00 MEG 131 +132 -2.70 7.01 4.00 3.00 MEG 132 +133 3.09 11.73 4.00 3.00 MEG 133 +134 8.14 9.62 4.00 3.00 MEG 134 +135 2.84 2.47 4.00 3.00 MEG 135 +136 4.05 6.89 4.00 3.00 MEG 136 +137 -6.16 14.64 4.00 3.00 MEG 137 +138 -11.02 2.49 4.00 3.00 MEG 138 +139 -6.78 6.65 4.00 3.00 MEG 139 +140 -6.24 3.18 4.00 3.00 MEG 140 +141 -6.83 9.47 4.00 3.00 MEG 141 +142 -2.48 11.64 4.00 3.00 MEG 142 +143 -17.59 14.92 4.00 3.00 MEG 143 +144 -22.23 2.07 4.00 3.00 MEG 144 +145 3.20 13.71 4.00 3.00 MEG 145 +146 2.06 5.84 4.00 3.00 MEG 146 +147 5.76 1.93 4.00 3.00 MEG 147 +148 23.08 3.86 4.00 3.00 MEG 148 +149 21.96 8.34 4.00 3.00 MEG 149 +150 20.00 12.43 4.00 3.00 MEG 150 +151 17.22 16.08 4.00 3.00 MEG 151 +152 3.91 9.37 4.00 3.00 MEG 152 +153 -21.58 6.32 4.00 3.00 MEG 153 +154 -20.17 10.61 4.00 3.00 MEG 154 +155 -11.01 10.95 4.00 3.00 MEG 155 +156 -14.51 5.43 4.00 3.00 MEG 156 +157 1.28 9.74 4.00 3.00 MEG 157 diff --git a/mne-python/source/mne/channels/data/layouts/KIT-160.lay b/mne-python/source/mne/channels/data/layouts/KIT-160.lay new file mode 100644 index 0000000000000000000000000000000000000000..1f5780ff93c1f52c62837503b4996b091f9eba02 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/KIT-160.lay @@ -0,0 +1,162 @@ +001 -0.0758202152 0.3520500341 0.03188472676 0.02713339699 MEG 001 +002 -0.1261117022 0.328933222 0.03188472676 0.02713339699 MEG 002 +003 -0.1696053658 0.2965692769 0.03188472676 0.02713339699 MEG 003 +004 0.1650030446 0.2798950608 0.03188472676 0.02713339699 MEG 004 +005 -0.1114275357 0.2868555816 0.03188472676 0.02713339699 MEG 005 +006 -0.06544380774 0.2622312709 0.03188472676 0.02713339699 MEG 006 +007 -0.1353647314 0.2073255917 0.03188472676 0.02713339699 MEG 007 +008 -0.17422271 0.1205755843 0.03188472676 0.02713339699 MEG 008 +009 -0.01368858767 0.2301473849 0.03188472676 0.02713339699 MEG 009 +010 -0.06470805562 0.2189319658 0.03188472676 0.02713339699 MEG 010 +011 -0.1247701784 0.1499178411 0.03188472676 0.02713339699 MEG 011 +012 -0.03961772545 0.1793694653 0.03188472676 0.02713339699 MEG 012 +013 -0.0711276654 0.1599000923 0.03188472676 0.02713339699 MEG 013 +014 -0.09668684076 0.1249745081 0.03188472676 0.02713339699 MEG 014 +015 -0.1103655395 0.08862749713 0.03188472676 0.02713339699 MEG 015 +016 -0.03953495363 0.1363424548 0.03188472676 0.02713339699 MEG 016 +017 -0.1781804786 0.01931847664 0.03188472676 0.02713339699 MEG 017 +018 -0.142520225 -0.06752066402 0.03188472676 0.02713339699 MEG 018 +019 -0.08088893708 -0.1241365481 0.03188472676 0.02713339699 MEG 019 +020 -0.04456843369 -0.1415706457 0.03188472676 0.02713339699 MEG 020 +021 -0.1426655535 0.05244256024 0.03188472676 0.02713339699 MEG 021 +022 -0.1340581452 0.000388349131 0.03188472676 0.02713339699 MEG 022 +023 -0.08512707038 -0.07696214533 0.03188472676 0.02713339699 MEG 023 +024 -0.04736054836 -0.09618399923 0.03188472676 0.02713339699 MEG 024 +025 -0.114643504 -0.04085422212 0.03188472676 0.02713339699 MEG 025 +026 -0.1103503321 0.03823179105 0.03188472676 0.02713339699 MEG 026 +027 -0.03958310463 -0.05556958642 0.03188472676 0.02713339699 MEG 027 +028 -0.06993629917 0.01943095503 0.03188472676 0.02713339699 MEG 028 +029 -0.04398320652 -0.01300040853 0.03188472676 0.02713339699 MEG 029 +030 -0.004227454924 -0.01962159408 0.03188472676 0.02713339699 MEG 030 +031 -0.01056467818 0.1062293634 0.03188472676 0.02713339699 MEG 031 +032 -0.04021127484 0.08385147042 0.03188472676 0.02713339699 MEG 032 +033 -0.3500780541 0.3978039282 0.03188472676 0.02713339699 MEG 033 +034 -0.400516673 0.3077821901 0.03188472676 0.02713339699 MEG 034 +035 -0.4325895921 0.2136911051 0.03188472676 0.02713339699 MEG 035 +036 -0.45 0.1074214926 0.03188472676 0.02713339699 MEG 036 +037 -0.3046138565 0.3570489454 0.03188472676 0.02713339699 MEG 037 +038 -0.3775870934 0.1989319321 0.03188472676 0.02713339699 MEG 038 +039 -0.3470032996 0.2860012743 0.03188472676 0.02713339699 MEG 039 +040 -0.2596101607 0.2361677074 0.03188472676 0.02713339699 MEG 040 +041 -0.3370312654 0.1080933205 0.03188472676 0.02713339699 MEG 041 +042 -0.2054494635 0.2529931344 0.03188472676 0.02713339699 MEG 042 +043 -0.2819761985 0.1711718789 0.03188472676 0.02713339699 MEG 043 +044 -0.2293126541 0.2020325726 0.03188472676 0.02713339699 MEG 044 +045 -0.253186216 0.08822084019 0.03188472676 0.02713339699 MEG 045 +046 -0.177239753 0.2148932642 0.03188472676 0.02713339699 MEG 046 +047 -0.1982663002 0.1636997157 0.03188472676 0.02713339699 MEG 047 +048 -0.2443663193 0.1429437606 0.03188472676 0.02713339699 MEG 048 +049 -0.3888843678 0.1059383909 0.03188472676 0.02713339699 MEG 049 +050 -0.4270282413 -0.09637491351 0.03188472676 0.02713339699 MEG 050 +051 -0.2842037041 -0.02907823435 0.03188472676 0.02713339699 MEG 051 +052 -0.3447270537 -0.2595887593 0.03188472676 0.02713339699 MEG 052 +053 -0.3909909615 0.01655882049 0.03188472676 0.02713339699 MEG 053 +054 -0.2988307343 -0.1206055812 0.03188472676 0.02713339699 MEG 054 +055 -0.2625165926 -0.18469877 0.03188472676 0.02713339699 MEG 055 +056 -0.3742205763 -0.06701211297 0.03188472676 0.02713339699 MEG 056 +057 -0.3368815045 0.02914339448 0.03188472676 0.02713339699 MEG 057 +058 -0.2614922293 -0.09693316038 0.03188472676 0.02713339699 MEG 058 +059 -0.2296354398 -0.1520887173 0.03188472676 0.02713339699 MEG 059 +060 -0.2424341314 -0.03356215166 0.03188472676 0.02713339699 MEG 060 +061 -0.1876464844 -0.1390883676 0.03188472676 0.02713339699 MEG 061 +062 -0.2141382597 0.06121102293 0.03188472676 0.02713339699 MEG 062 +063 -0.210559287 0.002243140577 0.03188472676 0.02713339699 MEG 063 +064 -0.1972138638 -0.04829819556 0.03188472676 0.02713339699 MEG 064 +065 0.1239897025 0.3184822507 0.03188472676 0.02713339699 MEG 065 +066 0.07602269198 0.346841814 0.03188472676 0.02713339699 MEG 066 +067 0.02730949028 0.3618289046 0.03188472676 0.02713339699 MEG 067 +068 -0.02876209065 0.3665275653 0.03188472676 0.02713339699 MEG 068 +069 0.06023566248 0.305037035 0.03188472676 0.02713339699 MEG 069 +070 0.01553893996 0.3208156125 0.03188472676 0.02713339699 MEG 070 +071 0.1455353008 0.1519564037 0.03188472676 0.02713339699 MEG 071 +072 0.09261086754 0.2300225572 0.03188472676 0.02713339699 MEG 072 +073 0.01800727232 0.2722816956 0.03188472676 0.02713339699 MEG 073 +074 0.09471660492 0.1660243591 0.03188472676 0.02713339699 MEG 074 +075 0.02256442482 0.2241822666 0.03188472676 0.02713339699 MEG 075 +076 0.1172275823 0.121354496 0.03188472676 0.02713339699 MEG 076 +077 0.06434989605 0.1443350384 0.03188472676 0.02713339699 MEG 077 +078 0.03192340214 0.1736460766 0.03188472676 0.02713339699 MEG 078 +079 0.002050178715 0.1879975831 0.03188472676 0.02713339699 MEG 079 +080 0.003697062517 0.143421051 0.03188472676 0.02713339699 MEG 080 +081 -0.003899772644 -0.1490601771 0.03188472676 0.02713339699 MEG 081 +082 0.0711394085 -0.1177609441 0.03188472676 0.02713339699 MEG 082 +083 0.1339233002 -0.04641972764 0.03188472676 0.02713339699 MEG 083 +084 0.1624045334 0.04808542023 0.03188472676 0.02713339699 MEG 084 +085 0.03165333222 -0.09469832945 0.03188472676 0.02713339699 MEG 085 +086 0.07137560881 -0.06228631109 0.03188472676 0.02713339699 MEG 086 +087 0.1185350219 0.01900269558 0.03188472676 0.02713339699 MEG 087 +088 0.1266742656 0.06930579768 0.03188472676 0.02713339699 MEG 088 +089 -0.004420218989 -0.06278528823 0.03188472676 0.02713339699 MEG 089 +090 0.06173501644 -0.0229233209 0.03188472676 0.02713339699 MEG 090 +091 0.08381840152 0.01449327322 0.03188472676 0.02713339699 MEG 091 +092 0.02911019425 -0.004626517545 0.03188472676 0.02713339699 MEG 092 +093 0.05293614742 0.03703628974 0.03188472676 0.02713339699 MEG 093 +094 0.08589158435 0.06075797622 0.03188472676 0.02713339699 MEG 094 +095 -0.007916726978 0.01526702488 0.03188472676 0.02713339699 MEG 095 +096 0.02152774438 0.08873530965 0.03188472676 0.02713339699 MEG 096 +097 0.4428288832 0.1535592899 0.03188472676 0.02713339699 MEG 097 +098 0.4162971034 0.267171892 0.03188472676 0.02713339699 MEG 098 +099 0.3668411201 0.3681231645 0.03188472676 0.02713339699 MEG 099 +100 0.3105057204 0.45 0.03188472676 0.02713339699 MEG 100 +101 0.3522874782 0.2435209125 0.03188472676 0.02713339699 MEG 101 +102 0.2611099363 0.4005591579 0.03188472676 0.02713339699 MEG 102 +103 0.3199035742 0.1404206704 0.03188472676 0.02713339699 MEG 103 +104 0.2620111685 0.2979083124 0.03188472676 0.02713339699 MEG 104 +105 0.2183237036 0.3586832133 0.03188472676 0.02713339699 MEG 105 +106 0.253424964 0.2038387029 0.03188472676 0.02713339699 MEG 106 +107 0.1821371767 0.3235092766 0.03188472676 0.02713339699 MEG 107 +108 0.2320142778 0.1055366971 0.03188472676 0.02713339699 MEG 108 +109 0.1969983757 0.2287392657 0.03188472676 0.02713339699 MEG 109 +110 0.1892169645 0.138858437 0.03188472676 0.02713339699 MEG 110 +111 0.1718069319 0.1949879663 0.03188472676 0.02713339699 MEG 111 +112 0.1412427238 0.2390846129 0.03188472676 0.02713339699 MEG 112 +113 0.3413341674 -0.2749014578 0.03188472676 0.02713339699 MEG 113 +114 0.3957163081 -0.1867381122 0.03188472676 0.02713339699 MEG 114 +115 0.4343284389 -0.0791376981 0.03188472676 0.02713339699 MEG 115 +116 0.45 0.04115848657 0.03188472676 0.02713339699 MEG 116 +117 0.294108122 -0.2248146657 0.03188472676 0.02713339699 MEG 117 +118 0.3408651095 -0.144258791 0.03188472676 0.02713339699 MEG 118 +119 0.3829160873 0.05059902865 0.03188472676 0.02713339699 MEG 119 +120 0.3147171717 -0.02712556599 0.03188472676 0.02713339699 MEG 120 +121 0.2904098027 -0.1079793618 0.03188472676 0.02713339699 MEG 121 +122 0.2489284377 -0.08302604569 0.03188472676 0.02713339699 MEG 122 +123 0.2791450822 0.06065203717 0.03188472676 0.02713339699 MEG 123 +124 0.1699476764 -0.1323891552 0.03188472676 0.02713339699 MEG 124 +125 0.2213406675 -0.02048593019 0.03188472676 0.02713339699 MEG 125 +126 0.1793293141 -0.03692175528 0.03188472676 0.02713339699 MEG 126 +127 0.2340431716 0.04272096725 0.03188472676 0.02713339699 MEG 127 +128 0.1989990214 0.07992534312 0.03188472676 0.02713339699 MEG 128 +129 -0.2893372271 -0.3287872551 0.03188472676 0.02713339699 MEG 129 +130 -0.2271848223 -0.3869397712 0.03188472676 0.02713339699 MEG 130 +131 -0.1541857375 -0.4262216107 0.03188472676 0.02713339699 MEG 131 +132 -0.07352758894 -0.45 0.03188472676 0.02713339699 MEG 132 +133 -0.2537949872 -0.2821367359 0.03188472676 0.02713339699 MEG 133 +134 -0.05789427224 -0.3854591968 0.03188472676 0.02713339699 MEG 134 +135 -0.2180547699 -0.2381599549 0.03188472676 0.02713339699 MEG 135 +136 -0.1654458556 -0.2836078687 0.03188472676 0.02713339699 MEG 136 +137 -0.1282115583 -0.3636295479 0.03188472676 0.02713339699 MEG 137 +138 -0.1869048087 -0.2008317859 0.03188472676 0.02713339699 MEG 138 +139 -0.092414085 -0.2712662931 0.03188472676 0.02713339699 MEG 139 +140 -0.04464737067 -0.3262626614 0.03188472676 0.02713339699 MEG 140 +141 -0.1084802139 -0.2080301215 0.03188472676 0.02713339699 MEG 141 +142 -0.008347885446 -0.2337992621 0.03188472676 0.02713339699 MEG 142 +143 -0.1346335691 -0.1372039628 0.03188472676 0.02713339699 MEG 143 +144 -0.05019800217 -0.1837431338 0.03188472676 0.02713339699 MEG 144 +145 0.08934861049 -0.3726540907 0.03188472676 0.02713339699 MEG 145 +146 0.106172944 -0.4435639299 0.03188472676 0.02713339699 MEG 146 +147 0.2218612721 0.2682623426 0.03188472676 0.02713339699 MEG 147 +148 0.2670027616 -0.3555067924 0.03188472676 0.02713339699 MEG 148 +149 0.01625933145 -0.3877305948 0.03188472676 0.02713339699 MEG 149 +150 0.1626843509 -0.342433819 0.03188472676 0.02713339699 MEG 150 +151 0.07960240502 -0.3134489525 0.03188472676 0.02713339699 MEG 151 +152 0.1456745581 -0.2843789795 0.03188472676 0.02713339699 MEG 152 +153 0.2343957441 -0.2951725192 0.03188472676 0.02713339699 MEG 153 +154 0.01783071962 -0.2738066839 0.03188472676 0.02713339699 MEG 154 +155 0.1274451621 -0.2352949445 0.03188472676 0.02713339699 MEG 155 +156 0.1746647823 -0.1970760538 0.03188472676 0.02713339699 MEG 156 +157 0.0872449245 -0.2076405522 0.03188472676 0.02713339699 MEG 157 +158 0.03888945369 -0.183846741 0.03188472676 0.02713339699 MEG 158 +159 0.08527772847 -0.1590694194 0.03188472676 0.02713339699 MEG 159 +160 0.1230026134 -0.1283845973 0.03188472676 0.02713339699 MEG 160 +161 -0.547000000 -0.5000000000 0.03188472676 0.02713339699 COMNT +162 -0.547000000 -0.5000000000 0.03188472676 0.02713339699 SCALE diff --git a/mne-python/source/mne/channels/data/layouts/KIT-AD.lout b/mne-python/source/mne/channels/data/layouts/KIT-AD.lout new file mode 100644 index 0000000000000000000000000000000000000000..e06356a07c66e024df0c60eaf7d790cd03250fbe --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/KIT-AD.lout @@ -0,0 +1,209 @@ + 0.00 1.00 0.00 1.00 +001 0.61 0.56 0.02 0.04 MEG 001 +002 0.59 0.50 0.02 0.04 MEG 002 +003 0.48 0.42 0.02 0.04 MEG 003 +004 0.52 0.43 0.02 0.04 MEG 004 +005 0.43 0.44 0.02 0.04 MEG 005 +006 0.39 0.48 0.02 0.04 MEG 006 +007 0.52 0.70 0.02 0.04 MEG 007 +008 0.58 0.59 0.02 0.04 MEG 008 +009 0.47 0.71 0.02 0.04 MEG 009 +010 0.53 0.49 0.02 0.04 MEG 010 +011 0.57 0.53 0.02 0.04 MEG 011 +012 0.43 0.50 0.02 0.04 MEG 012 +013 0.40 0.55 0.02 0.04 MEG 013 +014 0.57 0.39 0.02 0.04 MEG 014 +015 0.38 0.41 0.02 0.04 MEG 015 +016 0.48 0.37 0.02 0.04 MEG 016 +017 0.16 0.84 0.02 0.04 MEG 017 +018 0.53 0.63 0.02 0.04 MEG 018 +019 0.48 0.53 0.02 0.04 MEG 019 +020 0.44 0.63 0.02 0.04 MEG 020 +021 0.53 0.56 0.02 0.04 MEG 021 +022 0.44 0.57 0.02 0.04 MEG 022 +023 0.56 0.46 0.02 0.04 MEG 023 +024 0.59 0.68 0.02 0.04 MEG 024 +025 0.34 0.86 0.02 0.04 MEG 025 +026 0.39 0.89 0.02 0.04 MEG 026 +027 0.50 0.91 0.02 0.04 MEG 027 +028 0.61 0.87 0.02 0.04 MEG 028 +029 0.66 0.84 0.02 0.04 MEG 029 +030 0.59 0.76 0.02 0.04 MEG 030 +031 0.39 0.62 0.02 0.04 MEG 031 +032 0.55 0.85 0.02 0.04 MEG 032 +033 0.28 0.39 0.02 0.04 MEG 033 +034 0.37 0.52 0.02 0.04 MEG 034 +035 0.36 0.59 0.02 0.04 MEG 035 +036 0.38 0.70 0.02 0.04 MEG 036 +037 0.07 0.87 0.02 0.04 MEG 037 +038 0.24 0.61 0.02 0.04 MEG 038 +039 0.32 0.68 0.02 0.04 MEG 039 +040 0.30 0.81 0.02 0.04 MEG 040 +041 0.43 0.96 0.02 0.04 MEG 041 +042 0.55 0.95 0.02 0.04 MEG 042 +043 0.42 0.74 0.02 0.04 MEG 043 +044 0.56 0.72 0.02 0.04 MEG 044 +045 0.47 0.76 0.02 0.04 MEG 045 +046 0.52 0.75 0.02 0.04 MEG 046 +047 0.45 0.85 0.02 0.04 MEG 047 +048 0.40 0.79 0.02 0.04 MEG 048 +049 0.24 0.79 0.02 0.04 MEG 049 +050 0.21 0.46 0.02 0.04 MEG 050 +051 0.32 0.76 0.02 0.04 MEG 051 +052 0.20 0.63 0.02 0.04 MEG 052 +053 0.27 0.33 0.02 0.04 MEG 053 +054 0.17 0.74 0.02 0.04 MEG 054 +055 0.05 0.65 0.02 0.04 MEG 055 +056 0.28 0.63 0.02 0.04 MEG 056 +057 0.70 0.62 0.02 0.04 MEG 057 +058 0.94 0.38 0.02 0.04 MEG 058 +059 0.91 0.73 0.02 0.04 MEG 059 +060 0.82 0.93 0.02 0.04 MEG 060 +061 0.93 0.63 0.02 0.04 MEG 061 +062 0.75 0.78 0.02 0.04 MEG 062 +063 0.69 0.78 0.02 0.04 MEG 063 +064 0.43 0.00 0.02 0.04 MEG 064 +065 0.18 0.40 0.02 0.04 MEG 065 +066 0.19 0.29 0.02 0.04 MEG 066 +067 0.15 0.56 0.02 0.04 MEG 067 +068 0.33 0.53 0.02 0.04 MEG 068 +069 0.35 0.47 0.02 0.04 MEG 069 +070 0.25 0.89 0.02 0.04 MEG 070 +071 0.24 0.53 0.02 0.04 MEG 071 +072 0.16 0.95 0.02 0.04 MEG 072 +073 0.67 0.75 0.02 0.04 MEG 073 +074 0.74 0.86 0.02 0.04 MEG 074 +075 0.81 0.71 0.02 0.04 MEG 075 +076 0.78 0.62 0.02 0.04 MEG 076 +077 0.65 0.65 0.02 0.04 MEG 077 +078 0.83 0.81 0.02 0.04 MEG 078 +079 0.82 0.53 0.02 0.04 MEG 079 +080 0.78 0.36 0.02 0.04 MEG 080 +081 0.56 0.65 0.02 0.04 MEG 081 +082 0.35 0.74 0.02 0.04 MEG 082 +083 0.21 0.71 0.02 0.04 MEG 083 +084 0.12 0.75 0.02 0.04 MEG 084 +085 0.11 0.66 0.02 0.04 MEG 085 +086 0.21 0.92 0.02 0.04 MEG 086 +087 0.13 0.96 0.02 0.04 MEG 087 +088 0.03 0.76 0.02 0.04 MEG 088 +089 0.66 0.89 0.02 0.04 MEG 089 +090 0.61 0.93 0.02 0.04 MEG 090 +091 0.63 0.79 0.02 0.04 MEG 091 +092 0.71 0.84 0.02 0.04 MEG 092 +093 0.44 0.91 0.02 0.04 MEG 093 +094 0.56 0.89 0.02 0.04 MEG 094 +095 0.42 0.68 0.02 0.04 MEG 095 +096 0.54 0.79 0.02 0.04 MEG 096 +097 0.11 0.86 0.02 0.04 MEG 097 +098 0.14 0.36 0.02 0.04 MEG 098 +099 0.32 0.60 0.02 0.04 MEG 099 +100 0.25 0.45 0.02 0.04 MEG 100 +101 0.19 0.54 0.02 0.04 MEG 101 +102 0.27 0.85 0.02 0.04 MEG 102 +103 0.27 0.75 0.02 0.04 MEG 103 +104 0.01 0.64 0.02 0.04 MEG 104 +105 0.69 0.68 0.02 0.04 MEG 105 +106 0.88 0.82 0.02 0.04 MEG 106 +107 0.45 0.80 0.02 0.04 MEG 107 +108 0.50 0.86 0.02 0.04 MEG 108 +109 0.36 0.80 0.02 0.04 MEG 109 +110 0.49 0.96 0.02 0.04 MEG 110 +111 0.37 0.93 0.02 0.04 MEG 111 +112 0.32 0.90 0.02 0.04 MEG 112 +113 0.07 0.42 0.02 0.04 MEG 113 +114 0.73 0.72 0.02 0.04 MEG 114 +115 0.19 0.12 0.02 0.04 MEG 115 +116 0.01 0.51 0.02 0.04 MEG 116 +117 0.07 0.29 0.02 0.04 MEG 117 +118 0.16 0.47 0.02 0.04 MEG 118 +119 0.22 0.33 0.02 0.04 MEG 119 +120 0.10 0.54 0.02 0.04 MEG 120 +121 0.78 0.89 0.02 0.04 MEG 121 +122 0.87 0.63 0.02 0.04 MEG 122 +123 0.86 0.72 0.02 0.04 MEG 123 +124 0.77 0.70 0.02 0.04 MEG 124 +125 0.63 0.71 0.02 0.04 MEG 125 +126 0.89 0.27 0.02 0.04 MEG 126 +127 0.97 0.62 0.02 0.04 MEG 127 +128 0.83 0.62 0.02 0.04 MEG 128 +129 0.77 0.11 0.02 0.04 MEG 129 +130 0.86 0.95 0.02 0.04 MEG 130 +131 0.71 0.42 0.02 0.04 MEG 131 +132 0.78 0.53 0.02 0.04 MEG 132 +133 0.65 0.57 0.02 0.04 MEG 133 +134 0.16 0.67 0.02 0.04 MEG 134 +135 0.29 0.71 0.02 0.04 MEG 135 +136 0.16 0.23 0.02 0.04 MEG 136 +137 0.82 0.34 0.02 0.04 MEG 137 +138 0.87 0.52 0.02 0.04 MEG 138 +139 0.81 0.22 0.02 0.04 MEG 139 +140 0.90 0.40 0.02 0.04 MEG 140 +141 0.97 0.49 0.02 0.04 MEG 141 +142 0.74 0.30 0.02 0.04 MEG 142 +143 0.81 0.44 0.02 0.04 MEG 143 +144 0.95 0.75 0.02 0.04 MEG 144 +145 0.13 0.19 0.02 0.04 MEG 145 +146 0.28 0.56 0.02 0.04 MEG 146 +147 0.74 0.15 0.02 0.04 MEG 147 +148 0.10 0.33 0.02 0.04 MEG 148 +149 0.35 0.02 0.02 0.04 MEG 149 +150 0.03 0.39 0.02 0.04 MEG 150 +151 0.27 0.06 0.02 0.04 MEG 151 +152 0.31 0.43 0.02 0.04 MEG 152 +153 0.77 0.26 0.02 0.04 MEG 153 +154 0.67 0.10 0.02 0.04 MEG 154 +155 0.76 0.44 0.02 0.04 MEG 155 +156 0.83 0.18 0.02 0.04 MEG 156 +157 0.61 0.02 0.02 0.04 MEG 157 +158 0.91 0.86 0.02 0.04 MEG 158 +159 0.92 0.51 0.02 0.04 MEG 159 +160 0.86 0.30 0.02 0.04 MEG 160 +161 0.44 0.12 0.02 0.04 MEG 161 +162 0.37 0.30 0.02 0.04 MEG 162 +163 0.30 0.17 0.02 0.04 MEG 163 +164 0.36 0.25 0.02 0.04 MEG 164 +165 0.41 0.22 0.02 0.04 MEG 165 +166 0.31 0.28 0.02 0.04 MEG 166 +167 0.05 0.53 0.02 0.04 MEG 167 +168 0.08 0.76 0.02 0.04 MEG 168 +169 0.69 0.24 0.02 0.04 MEG 169 +170 0.57 0.18 0.02 0.04 MEG 170 +171 0.50 0.17 0.02 0.04 MEG 171 +172 0.64 0.20 0.02 0.04 MEG 172 +173 0.65 0.42 0.02 0.04 MEG 173 +174 0.69 0.53 0.02 0.04 MEG 174 +175 0.61 0.44 0.02 0.04 MEG 175 +176 0.70 0.32 0.02 0.04 MEG 176 +177 0.44 0.17 0.02 0.04 MEG 177 +178 0.38 0.18 0.02 0.04 MEG 178 +179 0.32 0.22 0.02 0.04 MEG 179 +180 0.44 0.06 0.02 0.04 MEG 180 +181 0.22 0.16 0.02 0.04 MEG 181 +182 0.36 0.07 0.02 0.04 MEG 182 +183 0.28 0.11 0.02 0.04 MEG 183 +184 0.42 0.27 0.02 0.04 MEG 184 +185 0.52 0.32 0.02 0.04 MEG 185 +186 0.57 0.33 0.02 0.04 MEG 186 +187 0.47 0.32 0.02 0.04 MEG 187 +188 0.62 0.37 0.02 0.04 MEG 188 +189 0.73 0.49 0.02 0.04 MEG 189 +190 0.67 0.36 0.02 0.04 MEG 190 +191 0.74 0.57 0.02 0.04 MEG 191 +192 0.64 0.49 0.02 0.04 MEG 192 +193 0.59 0.06 0.02 0.04 MEG 193 +194 0.52 -0.00 0.02 0.04 MEG 194 +195 0.58 0.29 0.02 0.04 MEG 195 +196 0.53 0.27 0.02 0.04 MEG 196 +197 0.47 0.26 0.02 0.04 MEG 197 +198 0.34 0.39 0.02 0.04 MEG 198 +199 0.42 0.33 0.02 0.04 MEG 199 +200 0.38 0.35 0.02 0.04 MEG 200 +201 0.53 0.22 0.02 0.04 MEG 201 +202 0.59 0.24 0.02 0.04 MEG 202 +203 0.65 0.27 0.02 0.04 MEG 203 +204 0.27 0.26 0.02 0.04 MEG 204 +205 0.51 0.11 0.02 0.04 MEG 205 +206 0.65 0.15 0.02 0.04 MEG 206 +207 0.51 0.05 0.02 0.04 MEG 207 +208 0.69 0.05 0.02 0.04 MEG 208 diff --git a/mne-python/source/mne/channels/data/layouts/KIT-AS-2008.lout b/mne-python/source/mne/channels/data/layouts/KIT-AS-2008.lout new file mode 100644 index 0000000000000000000000000000000000000000..84b135e998c695bea34b453fdb525a4ab3b4efbc --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/KIT-AS-2008.lout @@ -0,0 +1,158 @@ + 0.00 0.00 0.04 0.02 +000 0.43 0.98 0.10 0.05 MEG 001 +001 0.38 0.96 0.10 0.05 MEG 002 +002 0.32 0.92 0.10 0.05 MEG 003 +003 0.44 0.93 0.10 0.05 MEG 004 +004 0.39 0.91 0.10 0.05 MEG 005 +005 0.45 0.88 0.10 0.05 MEG 006 +006 0.36 0.82 0.10 0.05 MEG 007 +007 0.32 0.78 0.10 0.05 MEG 008 +008 0.33 0.68 0.10 0.05 MEG 009 +009 0.40 0.79 0.10 0.05 MEG 010 +010 0.36 0.74 0.10 0.05 MEG 011 +011 0.48 0.78 0.10 0.05 MEG 012 +012 0.39 0.71 0.10 0.05 MEG 013 +013 0.37 0.66 0.10 0.05 MEG 014 +014 0.48 0.72 0.10 0.05 MEG 015 +015 0.44 0.69 0.10 0.05 MEG 016 +016 0.28 0.57 0.10 0.05 MEG 017 +017 0.29 0.51 0.10 0.05 MEG 018 +018 0.32 0.45 0.10 0.05 MEG 019 +019 0.40 0.36 0.10 0.05 MEG 020 +020 0.46 0.44 0.10 0.05 MEG 021 +021 0.33 0.60 0.10 0.05 MEG 022 +022 0.34 0.53 0.10 0.05 MEG 023 +023 0.41 0.42 0.10 0.05 MEG 024 +024 0.46 0.51 0.10 0.05 MEG 025 +025 0.38 0.59 0.10 0.05 MEG 026 +026 0.50 0.38 0.10 0.05 MEG 027 +027 0.41 0.48 0.10 0.05 MEG 028 +028 0.42 0.56 0.10 0.05 MEG 029 +029 0.51 0.49 0.10 0.05 MEG 030 +030 0.46 0.58 0.10 0.05 MEG 031 +031 0.47 0.64 0.10 0.05 MEG 032 +032 0.12 0.99 0.10 0.05 MEG 033 +033 0.07 0.90 0.10 0.05 MEG 034 +034 0.11 0.88 0.10 0.05 MEG 035 +035 0.13 0.77 0.10 0.05 MEG 036 +036 0.16 0.97 0.10 0.05 MEG 037 +037 0.07 0.78 0.10 0.05 MEG 038 +038 0.20 0.94 0.10 0.05 MEG 039 +039 0.16 0.86 0.10 0.05 MEG 040 +040 0.10 0.67 0.10 0.05 MEG 041 +041 0.25 0.90 0.10 0.05 MEG 042 +042 0.20 0.83 0.10 0.05 MEG 043 +043 0.17 0.76 0.10 0.05 MEG 044 +044 0.24 0.80 0.10 0.05 MEG 045 +045 0.20 0.65 0.10 0.05 MEG 046 +046 0.29 0.82 0.10 0.05 MEG 047 +047 0.25 0.69 0.10 0.05 MEG 048 +048 0.00 0.52 0.10 0.05 MEG 049 +049 0.02 0.40 0.10 0.05 MEG 050 +050 0.07 0.30 0.10 0.05 MEG 051 +051 0.12 0.20 0.10 0.05 MEG 052 +052 0.05 0.53 0.10 0.05 MEG 053 +053 0.07 0.42 0.10 0.05 MEG 054 +054 0.16 0.24 0.10 0.05 MEG 055 +055 0.10 0.56 0.10 0.05 MEG 056 +056 0.15 0.37 0.10 0.05 MEG 057 +057 0.16 0.56 0.10 0.05 MEG 058 +058 0.17 0.48 0.10 0.05 MEG 059 +059 0.20 0.40 0.10 0.05 MEG 060 +060 0.21 0.48 0.10 0.05 MEG 061 +061 0.28 0.34 0.10 0.05 MEG 062 +062 0.24 0.61 0.10 0.05 MEG 063 +063 0.30 0.39 0.10 0.05 MEG 064 +064 0.67 0.93 0.10 0.05 MEG 065 +065 0.62 0.96 0.10 0.05 MEG 066 +066 0.56 0.98 0.10 0.05 MEG 067 +067 0.50 0.99 0.10 0.05 MEG 068 +068 0.60 0.86 0.10 0.05 MEG 069 +069 0.56 0.93 0.10 0.05 MEG 070 +070 0.71 0.72 0.10 0.05 MEG 071 +071 0.65 0.83 0.10 0.05 MEG 072 +072 0.56 0.88 0.10 0.05 MEG 073 +073 0.65 0.76 0.10 0.05 MEG 074 +074 0.56 0.83 0.10 0.05 MEG 075 +075 0.64 0.66 0.10 0.05 MEG 076 +076 0.62 0.71 0.10 0.05 MEG 077 +077 0.53 0.78 0.10 0.05 MEG 078 +078 0.57 0.68 0.10 0.05 MEG 079 +079 0.53 0.72 0.10 0.05 MEG 080 +080 0.50 0.33 0.10 0.05 MEG 081 +081 0.55 0.34 0.10 0.05 MEG 082 +082 0.60 0.36 0.10 0.05 MEG 083 +083 0.69 0.44 0.10 0.05 MEG 084 +084 0.72 0.57 0.10 0.05 MEG 085 +085 0.61 0.42 0.10 0.05 MEG 086 +086 0.67 0.53 0.10 0.05 MEG 087 +087 0.69 0.61 0.10 0.05 MEG 088 +088 0.56 0.45 0.10 0.05 MEG 089 +089 0.60 0.48 0.10 0.05 MEG 090 +090 0.64 0.59 0.10 0.05 MEG 091 +091 0.56 0.51 0.10 0.05 MEG 092 +092 0.59 0.55 0.10 0.05 MEG 093 +093 0.51 0.55 0.10 0.05 MEG 094 +094 0.54 0.58 0.10 0.05 MEG 095 +095 0.54 0.64 0.10 0.05 MEG 096 +096 1.00 0.69 0.10 0.05 MEG 097 +097 0.97 0.81 0.10 0.05 MEG 098 +098 0.93 0.92 0.10 0.05 MEG 099 +099 0.87 1.00 0.10 0.05 MEG 100 +100 0.93 0.80 0.10 0.05 MEG 101 +101 0.83 0.97 0.10 0.05 MEG 102 +102 0.89 0.68 0.10 0.05 MEG 103 +103 0.84 0.87 0.10 0.05 MEG 104 +104 0.79 0.94 0.10 0.05 MEG 105 +105 0.85 0.68 0.10 0.05 MEG 106 +106 0.83 0.76 0.10 0.05 MEG 107 +107 0.76 0.91 0.10 0.05 MEG 108 +108 0.74 0.76 0.10 0.05 MEG 109 +109 0.76 0.81 0.10 0.05 MEG 110 +110 0.76 0.69 0.10 0.05 MEG 111 +111 0.71 0.83 0.10 0.05 MEG 112 +112 0.88 0.22 0.10 0.05 MEG 113 +113 0.94 0.32 0.10 0.05 MEG 114 +114 0.98 0.42 0.10 0.05 MEG 115 +115 1.00 0.54 0.10 0.05 MEG 116 +116 0.84 0.26 0.10 0.05 MEG 117 +117 0.93 0.45 0.10 0.05 MEG 118 +118 0.95 0.56 0.10 0.05 MEG 119 +119 0.81 0.30 0.10 0.05 MEG 120 +120 0.85 0.38 0.10 0.05 MEG 121 +121 0.81 0.41 0.10 0.05 MEG 122 +122 0.83 0.49 0.10 0.05 MEG 123 +123 0.85 0.58 0.10 0.05 MEG 124 +124 0.73 0.35 0.10 0.05 MEG 125 +125 0.79 0.49 0.10 0.05 MEG 126 +126 0.74 0.46 0.10 0.05 MEG 127 +127 0.77 0.61 0.10 0.05 MEG 128 +128 0.20 0.12 0.10 0.05 MEG 129 +129 0.37 0.02 0.10 0.05 MEG 130 +130 0.46 0.00 0.10 0.05 MEG 131 +131 0.30 0.11 0.10 0.05 MEG 132 +132 0.47 0.06 0.10 0.05 MEG 133 +133 0.25 0.21 0.10 0.05 MEG 134 +134 0.32 0.17 0.10 0.05 MEG 135 +135 0.39 0.13 0.10 0.05 MEG 136 +136 0.29 0.26 0.10 0.05 MEG 137 +137 0.41 0.19 0.10 0.05 MEG 138 +138 0.47 0.18 0.10 0.05 MEG 139 +139 0.39 0.26 0.10 0.05 MEG 140 +140 0.50 0.22 0.10 0.05 MEG 141 +141 0.33 0.29 0.10 0.05 MEG 142 +142 0.45 0.29 0.10 0.05 MEG 143 +143 0.50 0.28 0.10 0.05 MEG 144 +144 0.65 0.03 0.10 0.05 MEG 145 +145 0.82 0.13 0.10 0.05 MEG 146 +146 0.55 0.06 0.10 0.05 MEG 147 +147 0.71 0.12 0.10 0.05 MEG 148 +148 0.62 0.14 0.10 0.05 MEG 149 +149 0.69 0.18 0.10 0.05 MEG 150 +150 0.76 0.23 0.10 0.05 MEG 151 +151 0.54 0.18 0.10 0.05 MEG 152 +152 0.61 0.20 0.10 0.05 MEG 153 +153 0.73 0.27 0.10 0.05 MEG 154 +154 0.63 0.25 0.10 0.05 MEG 155 +155 0.56 0.28 0.10 0.05 MEG 156 +156 0.67 0.35 0.10 0.05 MEG 157 diff --git a/mne-python/source/mne/channels/data/layouts/KIT-UMD-3.lout b/mne-python/source/mne/channels/data/layouts/KIT-UMD-3.lout new file mode 100644 index 0000000000000000000000000000000000000000..72cd69f97361bbf6c4ddf6994ebb4913c167f449 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/KIT-UMD-3.lout @@ -0,0 +1,158 @@ + -25.00 28.00 -21.35 23.75 +000 -23.42 20.48 3.20 2.40 MEG 001 +001 -22.32 15.16 3.20 2.40 MEG 002 +002 -24.20 10.24 3.20 2.40 MEG 003 +003 -25.00 5.27 3.20 2.40 MEG 004 +004 -24.75 -0.21 3.20 2.40 MEG 005 +005 -23.41 -5.22 3.20 2.40 MEG 006 +006 -22.35 -11.37 3.20 2.40 MEG 007 +007 -14.06 -15.64 3.20 2.40 MEG 008 +008 -15.12 -18.15 3.20 2.40 MEG 009 +009 -11.26 -20.73 3.20 2.40 MEG 010 +010 -6.28 -20.94 3.20 2.40 MEG 011 +011 -2.04 -21.35 3.20 2.40 MEG 012 +012 2.04 -21.35 3.20 2.40 MEG 013 +013 6.28 -20.94 3.20 2.40 MEG 014 +014 11.26 -20.73 3.20 2.40 MEG 015 +015 15.12 -18.15 3.20 2.40 MEG 016 +016 19.41 -14.06 3.20 2.40 MEG 017 +017 22.35 -11.37 3.20 2.40 MEG 018 +018 24.06 -3.70 3.20 2.40 MEG 019 +019 24.23 1.80 3.20 2.40 MEG 020 +020 24.80 5.19 3.20 2.40 MEG 021 +021 22.03 13.42 3.20 2.40 MEG 022 +022 21.58 16.68 3.20 2.40 MEG 023 +023 23.42 20.48 3.20 2.40 MEG 024 +024 20.15 19.33 3.20 2.40 MEG 025 +025 7.46 -2.58 3.20 2.40 MEG 026 +026 22.86 7.70 3.20 2.40 MEG 027 +027 20.76 2.91 3.20 2.40 MEG 028 +028 19.70 -8.80 3.20 2.40 MEG 029 +029 3.41 -5.91 3.20 2.40 MEG 030 +030 14.06 -15.64 3.20 2.40 MEG 031 +031 0.12 -5.34 3.20 2.40 MEG 032 +032 1.80 -18.87 3.20 2.40 MEG 033 +033 -1.80 -18.87 3.20 2.40 MEG 034 +034 -10.12 -18.16 3.20 2.40 MEG 035 +035 -3.41 -5.91 3.20 2.40 MEG 036 +036 -18.35 -13.97 3.20 2.40 MEG 037 +037 -19.70 -8.80 3.20 2.40 MEG 038 +038 -20.76 2.91 3.20 2.40 MEG 039 +039 -22.86 7.70 3.20 2.40 MEG 040 +040 -7.46 -2.58 3.20 2.40 MEG 041 +041 -20.15 19.33 3.20 2.40 MEG 042 +042 -16.84 18.53 3.20 2.40 MEG 043 +043 -18.55 14.46 3.20 2.40 MEG 044 +044 -20.31 10.64 3.20 2.40 MEG 045 +045 -10.05 0.17 3.20 2.40 MEG 046 +046 -20.62 -2.66 3.20 2.40 MEG 047 +047 -17.20 -6.26 3.20 2.40 MEG 048 +048 -16.21 -11.50 3.20 2.40 MEG 049 +049 -8.92 -15.60 3.20 2.40 MEG 050 +050 -5.79 -18.42 3.20 2.40 MEG 051 +051 -1.62 -16.14 3.20 2.40 MEG 052 +052 -8.25 6.10 3.20 2.40 MEG 053 +053 5.79 -18.42 3.20 2.40 MEG 054 +054 8.92 -15.60 3.20 2.40 MEG 055 +055 16.21 -11.50 3.20 2.40 MEG 056 +056 17.20 -6.26 3.20 2.40 MEG 057 +057 20.62 -2.66 3.20 2.40 MEG 058 +058 -6.11 13.61 3.20 2.40 MEG 059 +059 20.31 10.64 3.20 2.40 MEG 060 +060 17.58 15.92 3.20 2.40 MEG 061 +061 16.84 18.53 3.20 2.40 MEG 062 +062 13.49 18.47 3.20 2.40 MEG 063 +063 15.28 13.32 3.20 2.40 MEG 064 +064 -4.11 11.13 3.20 2.40 MEG 065 +065 19.39 7.54 3.20 2.40 MEG 066 +066 17.50 3.47 3.20 2.40 MEG 067 +067 -6.54 8.57 3.20 2.40 MEG 068 +068 11.44 -8.04 3.20 2.40 MEG 069 +069 12.41 -13.14 3.20 2.40 MEG 070 +070 8.16 -13.13 3.20 2.40 MEG 071 +071 -7.60 2.77 3.20 2.40 MEG 072 +072 1.62 -16.14 3.20 2.40 MEG 073 +073 -6.80 0.14 3.20 2.40 MEG 074 +074 -5.40 -15.93 3.20 2.40 MEG 075 +075 -8.16 -13.13 3.20 2.40 MEG 076 +076 -12.41 -13.14 3.20 2.40 MEG 077 +077 -14.81 -8.97 3.20 2.40 MEG 078 +078 -3.23 -2.94 3.20 2.40 MEG 079 +079 -17.50 3.47 3.20 2.40 MEG 080 +080 -19.39 7.54 3.20 2.40 MEG 081 +081 4.03 -2.84 3.20 2.40 MEG 082 +082 -15.28 13.32 3.20 2.40 MEG 083 +083 -13.49 18.47 3.20 2.40 MEG 084 +084 -12.29 15.99 3.20 2.40 MEG 085 +085 -16.74 10.63 3.20 2.40 MEG 086 +086 6.80 0.14 3.20 2.40 MEG 087 +087 -17.30 -2.88 3.20 2.40 MEG 088 +088 -13.99 -4.86 3.20 2.40 MEG 089 +089 11.58 6.13 3.20 2.40 MEG 090 +090 -11.44 -8.04 3.20 2.40 MEG 091 +091 -3.30 -13.45 3.20 2.40 MEG 092 +092 6.54 8.57 3.20 2.40 MEG 093 +093 -9.52 -10.67 3.20 2.40 MEG 094 +094 9.52 -10.67 3.20 2.40 MEG 095 +095 4.11 11.13 3.20 2.40 MEG 096 +096 13.99 -4.86 3.20 2.40 MEG 097 +097 18.10 -0.17 3.20 2.40 MEG 098 +098 0.74 11.38 3.20 2.40 MEG 099 +099 16.74 10.63 3.20 2.40 MEG 100 +100 12.29 15.99 3.20 2.40 MEG 101 +101 10.11 18.86 3.20 2.40 MEG 102 +102 6.83 19.80 3.20 2.40 MEG 103 +103 3.48 21.35 3.20 2.40 MEG 104 +104 0.00 21.35 3.20 2.40 MEG 105 +105 -3.48 21.35 3.20 2.40 MEG 106 +106 -6.83 19.80 3.20 2.40 MEG 107 +107 -10.11 18.86 3.20 2.40 MEG 108 +108 -12.03 13.52 3.20 2.40 MEG 109 +109 -1.63 8.64 3.20 2.40 MEG 110 +110 -3.36 18.88 3.20 2.40 MEG 111 +111 -0.02 18.88 3.20 2.40 MEG 112 +112 3.36 18.88 3.20 2.40 MEG 113 +113 1.63 8.64 3.20 2.40 MEG 114 +114 9.01 16.34 3.20 2.40 MEG 115 +115 4.97 5.29 3.20 2.40 MEG 116 +116 13.28 10.76 3.20 2.40 MEG 117 +117 15.78 7.58 3.20 2.40 MEG 118 +118 14.24 3.60 3.20 2.40 MEG 119 +119 14.69 -0.31 3.20 2.40 MEG 120 +120 3.37 -0.21 3.20 2.40 MEG 121 +121 8.20 -8.14 3.20 2.40 MEG 122 +122 6.11 -10.67 3.20 2.40 MEG 123 +123 2.77 -10.98 3.20 2.40 MEG 124 +124 0.10 -13.43 3.20 2.40 MEG 125 +125 0.02 -0.57 3.20 2.40 MEG 126 +126 -2.77 -10.98 3.20 2.40 MEG 127 +127 -8.20 -8.14 3.20 2.40 MEG 128 +128 -3.37 -0.21 3.20 2.40 MEG 129 +129 -14.69 -0.31 3.20 2.40 MEG 130 +130 -14.24 3.60 3.20 2.40 MEG 131 +131 -15.78 7.58 3.20 2.40 MEG 132 +132 -13.28 10.76 3.20 2.40 MEG 133 +133 -4.97 5.29 3.20 2.40 MEG 134 +134 -9.46 11.02 3.20 2.40 MEG 135 +135 -12.21 7.84 3.20 2.40 MEG 136 +136 -10.93 3.58 3.20 2.40 MEG 137 +137 -10.71 -3.82 3.20 2.40 MEG 138 +138 -6.89 -5.51 3.20 2.40 MEG 139 +139 -1.66 5.24 3.20 2.40 MEG 140 +140 -2.40 -8.39 3.20 2.40 MEG 141 +141 2.40 -8.39 3.20 2.40 MEG 142 +142 -4.29 2.66 3.20 2.40 MEG 143 +143 6.89 -5.51 3.20 2.40 MEG 144 +144 10.71 -3.82 3.20 2.40 MEG 145 +145 10.93 3.58 3.20 2.40 MEG 146 +146 4.29 2.66 3.20 2.40 MEG 147 +147 9.46 11.02 3.20 2.40 MEG 148 +148 5.70 16.39 3.20 2.40 MEG 149 +149 1.66 5.24 3.20 2.40 MEG 150 +150 -2.37 16.38 3.20 2.40 MEG 151 +151 -5.70 16.39 3.20 2.40 MEG 152 +152 8.25 6.10 3.20 2.40 MEG 153 +153 -0.58 13.96 3.20 2.40 MEG 154 +154 2.81 13.89 3.20 2.40 MEG 155 +155 6.11 13.61 3.20 2.40 MEG 156 +156 2.37 16.38 3.20 2.40 MEG 157 diff --git a/mne-python/source/mne/channels/data/layouts/Neuromag_122.lout b/mne-python/source/mne/channels/data/layouts/Neuromag_122.lout new file mode 100644 index 0000000000000000000000000000000000000000..c97746a7cde306970b234a1546eda7adf78edd01 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/Neuromag_122.lout @@ -0,0 +1,123 @@ +-3 28 -17 15 +1 25.381295 -0.771781 2 1.5 MEG 001 +2 25.381295 0.727697 2 1.5 MEG 002 +3 22.715372 -0.733246 2 1.5 MEG 003 +4 22.715372 0.766753 2 1.5 MEG 004 +5 19.911143 -0.608748 2 1.5 MEG 005 +6 19.911143 0.891252 2 1.5 MEG 006 +7 24.481102 4.347077 2 1.5 MEG 007 +8 24.481102 5.847077 2 1.5 MEG 008 +9 21.9673 3.613717 2 1.5 MEG 009 +10 21.9673 5.113717 2 1.5 MEG 010 +11 19.345958 3.110359 2 1.5 MEG 011 +12 19.345958 4.610058 2 1.5 MEG 012 +13 16.706588 2.875744 2 1.5 MEG 013 +14 16.706588 4.375643 2 1.5 MEG 014 +15 14.09047 2.753697 2 1.5 MEG 015 +16 14.09047 4.253697 2 1.5 MEG 016 +17 19.559995 7.243332 2 1.5 MEG 017 +18 19.559995 8.743163 2 1.5 MEG 018 +19 16.942979 6.237191 2 1.5 MEG 019 +20 16.942979 7.737225 2 1.5 MEG 020 +21 14.204774 5.792745 2 1.5 MEG 021 +22 14.204774 7.292858 2 1.5 MEG 022 +23 11.5 5.70429 2 1.5 MEG 023 +24 11.5 7.204446 2 1.5 MEG 024 +25 16.662514 9.87843 2 1.5 MEG 025 +26 16.662514 11.37843 2 1.5 MEG 026 +27 13.466339 11.859999 2 1.5 MEG 027 +28 13.466339 13.359952 2 1.5 MEG 028 +29 13.450371 8.807222 2 1.5 MEG 029 +30 13.450371 10.307518 2 1.5 MEG 030 +31 9.533661 11.859999 2 1.5 MEG 031 +32 9.533661 13.359952 2 1.5 MEG 032 +33 9.54963 8.807222 2 1.5 MEG 033 +34 9.54963 10.307518 2 1.5 MEG 034 +35 6.3374865 9.87843 2 1.5 MEG 035 +36 6.337486 11.37843 2 1.5 MEG 036 +37 3.440005 7.243332 2 1.5 MEG 037 +38 3.440005 8.743163 2 1.5 MEG 038 +39 6.057021 6.237192 2 1.5 MEG 039 +40 6.057021 7.737225 2 1.5 MEG 040 +41 8.795226 5.792745 2 1.5 MEG 041 +42 8.795226 7.292858 2 1.5 MEG 042 +43 -1.481102 4.347078 2 1.5 MEG 043 +44 -1.481102 5.847078 2 1.5 MEG 044 +45 1.0327 3.613581 2 1.5 MEG 045 +46 1.0327 5.113717 2 1.5 MEG 046 +47 3.654042 3.11036 2 1.5 MEG 047 +48 3.654042 4.610058 2 1.5 MEG 048 +49 6.293412 2.875744 2 1.5 MEG 049 +50 6.293412 4.375643 2 1.5 MEG 050 +51 8.90953 2.753697 2 1.5 MEG 051 +52 8.90953 4.253697 2 1.5 MEG 052 +53 11.5 2.731327 2 1.5 MEG 053 +54 11.5 4.231464 2 1.5 MEG 054 +55 -2.381295 -0.771781 2 1.5 MEG 055 +56 -2.381295 0.727697 2 1.5 MEG 056 +57 0.284628 -0.733246 2 1.5 MEG 057 +58 0.284628 0.766753 2 1.5 MEG 058 +59 3.088857 -0.608748 2 1.5 MEG 059 +60 3.088857 0.891252 2 1.5 MEG 060 +61 5.895393 -0.521429 2 1.5 MEG 061 +62 5.895393 0.978571 2 1.5 MEG 062 +63 8.696664 -0.481488 2 1.5 MEG 063 +64 8.696664 1.018793 2 1.5 MEG 064 +65 11.5 -0.46314 2 1.5 MEG 065 +66 11.5 1.036853 2 1.5 MEG 066 +67 -1.590015 -6.177621 2 1.5 MEG 067 +68 -1.590015 -4.677286 2 1.5 MEG 068 +69 0.893853 -5.313065 2 1.5 MEG 069 +70 0.893853 -3.813065 2 1.5 MEG 070 +71 3.788197 -4.494587 2 1.5 MEG 071 +72 3.788197 -2.994811 2 1.5 MEG 072 +73 6.749538 -3.95458 2 1.5 MEG 073 +74 6.749538 -2.454261 2 1.5 MEG 074 +75 1.096738 -10.894836 2 1.5 MEG 075 +76 1.096738 -9.394836 2 1.5 MEG 076 +77 3.402274 -9.346367 2 1.5 MEG 077 +78 3.402274 -7.846579 2 1.5 MEG 078 +79 6.182132 -8.131419 2 1.5 MEG 079 +80 6.182132 -6.631304 2 1.5 MEG 080 +81 6.102499 -15.409053 2 1.5 MEG 081 +82 6.102499 -13.908834 2 1.5 MEG 082 +83 6.914234 -12.406122 2 1.5 MEG 083 +84 6.914234 -10.906034 2 1.5 MEG 084 +85 9.307503 -10.644013 2 1.5 MEG 085 +86 9.307503 -9.143762 2 1.5 MEG 086 +87 9.660984 -7.199067 2 1.5 MEG 087 +88 9.660984 -5.699067 2 1.5 MEG 088 +89 9.807536 -3.822648 2 1.5 MEG 089 +90 9.807536 -2.322552 2 1.5 MEG 090 +91 11.5 -16.259918 2 1.5 MEG 091 +92 11.5 -14.759918 2 1.5 MEG 092 +93 11.5 -13.097164 2 1.5 MEG 093 +94 11.5 -11.597439 2 1.5 MEG 094 +95 13.692497 -10.644013 2 1.5 MEG 095 +96 13.692497 -9.143762 2 1.5 MEG 096 +97 13.339016 -7.199067 2 1.5 MEG 097 +98 13.339016 -5.699067 2 1.5 MEG 098 +99 13.192464 -3.822648 2 1.5 MEG 099 +100 13.192464 -2.322552 2 1.5 MEG 100 +101 16.897501 -15.409053 2 1.5 MEG 101 +102 16.897501 -13.908834 2 1.5 MEG 102 +103 16.085766 -12.406122 2 1.5 MEG 103 +104 16.085766 -10.906034 2 1.5 MEG 104 +105 21.903262 -10.894836 2 1.5 MEG 105 +106 21.903262 -9.394836 2 1.5 MEG 106 +107 19.597726 -9.346367 2 1.5 MEG 107 +108 19.597726 -7.846579 2 1.5 MEG 108 +109 16.817868 -8.131419 2 1.5 MEG 109 +110 16.817868 -6.631304 2 1.5 MEG 110 +111 24.590015 -6.177621 2 1.5 MEG 111 +112 24.590015 -4.677286 2 1.5 MEG 112 +113 22.106147 -5.313065 2 1.5 MEG 113 +114 22.106147 -3.813065 2 1.5 MEG 114 +115 19.211802 -4.494588 2 1.5 MEG 115 +116 19.211802 -2.994811 2 1.5 MEG 116 +117 16.250462 -3.95458 2 1.5 MEG 117 +118 16.250462 -2.454261 2 1.5 MEG 118 +119 17.104607 -0.521429 2 1.5 MEG 119 +120 17.104607 0.978571 2 1.5 MEG 120 +121 14.303336 -0.481488 2 1.5 MEG 121 +122 14.303336 1.018792 2 1.5 MEG 122 diff --git a/mne-python/source/mne/channels/data/layouts/Vectorview-all.lout b/mne-python/source/mne/channels/data/layouts/Vectorview-all.lout new file mode 100644 index 0000000000000000000000000000000000000000..b6395fb9c00b82da9a5829506b5c8f9d489549ca --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/Vectorview-all.lout @@ -0,0 +1,307 @@ +-85.000000 90.000000 -83.000000 75.000000 +113 -73.416206 33.416687 6.000000 5.000000 MEG 0113 +112 -73.416206 38.416687 6.000000 5.000000 MEG 0112 +111 -67.416206 35.916687 6.000000 5.000000 MEG 0111 +122 -59.602242 38.489067 6.000000 5.000000 MEG 0122 +123 -59.602242 43.489067 6.000000 5.000000 MEG 0123 +121 -53.602242 40.989067 6.000000 5.000000 MEG 0121 +132 -68.018288 18.676970 6.000000 5.000000 MEG 0132 +133 -68.018288 23.676970 6.000000 5.000000 MEG 0133 +131 -62.018288 21.176970 6.000000 5.000000 MEG 0131 +143 -80.582848 8.095787 6.000000 5.000000 MEG 0143 +142 -80.582848 13.095787 6.000000 5.000000 MEG 0142 +141 -74.582848 10.595787 6.000000 5.000000 MEG 0141 +213 -56.595154 17.019251 6.000000 5.000000 MEG 0213 +212 -56.595154 22.019251 6.000000 5.000000 MEG 0212 +211 -50.595154 19.519251 6.000000 5.000000 MEG 0211 +222 -44.599728 17.543873 6.000000 5.000000 MEG 0222 +223 -44.599728 22.543873 6.000000 5.000000 MEG 0223 +221 -38.599728 20.043873 6.000000 5.000000 MEG 0221 +232 -47.416420 -0.216784 6.000000 5.000000 MEG 0232 +233 -47.416420 4.783216 6.000000 5.000000 MEG 0233 +231 -41.416420 2.283216 6.000000 5.000000 MEG 0231 +243 -59.280643 -2.761772 6.000000 5.000000 MEG 0243 +242 -59.280643 2.238228 6.000000 5.000000 MEG 0242 +241 -53.280643 -0.261772 6.000000 5.000000 MEG 0241 +313 -39.790501 47.430138 6.000000 5.000000 MEG 0313 +312 -39.790501 52.430138 6.000000 5.000000 MEG 0312 +311 -33.790501 49.930138 6.000000 5.000000 MEG 0311 +322 -38.014336 32.768585 6.000000 5.000000 MEG 0322 +323 -38.014336 37.768585 6.000000 5.000000 MEG 0323 +321 -32.014336 35.268585 6.000000 5.000000 MEG 0321 +333 -27.679966 28.868065 6.000000 5.000000 MEG 0333 +332 -27.679966 33.868065 6.000000 5.000000 MEG 0332 +331 -21.679966 31.368065 6.000000 5.000000 MEG 0331 +343 -49.684467 34.078434 6.000000 5.000000 MEG 0343 +342 -49.684467 39.078434 6.000000 5.000000 MEG 0342 +341 -43.684467 36.578434 6.000000 5.000000 MEG 0341 +413 -32.997990 15.607347 6.000000 5.000000 MEG 0413 +412 -32.997990 20.607347 6.000000 5.000000 MEG 0412 +411 -26.997990 18.107347 6.000000 5.000000 MEG 0411 +422 -21.084751 13.953575 6.000000 5.000000 MEG 0422 +423 -21.084751 18.953575 6.000000 5.000000 MEG 0423 +421 -15.084751 16.453575 6.000000 5.000000 MEG 0421 +432 -21.930935 -0.085500 6.000000 5.000000 MEG 0432 +433 -21.930935 4.914500 6.000000 5.000000 MEG 0433 +431 -15.930935 2.414500 6.000000 5.000000 MEG 0431 +443 -34.824663 0.362587 6.000000 5.000000 MEG 0443 +442 -34.824663 5.362587 6.000000 5.000000 MEG 0442 +441 -28.824663 2.862587 6.000000 5.000000 MEG 0441 +513 -27.861498 55.439636 6.000000 5.000000 MEG 0513 +512 -27.861498 60.439636 6.000000 5.000000 MEG 0512 +511 -21.861498 57.939636 6.000000 5.000000 MEG 0511 +523 -15.506709 59.619865 6.000000 5.000000 MEG 0523 +522 -15.506709 64.619865 6.000000 5.000000 MEG 0522 +521 -9.506709 62.119865 6.000000 5.000000 MEG 0521 +532 -14.616095 49.308380 6.000000 5.000000 MEG 0532 +533 -14.616095 54.308380 6.000000 5.000000 MEG 0533 +531 -8.616095 51.808380 6.000000 5.000000 MEG 0531 +542 -27.240477 43.863430 6.000000 5.000000 MEG 0542 +543 -27.240477 48.863430 6.000000 5.000000 MEG 0543 +541 -21.240477 46.363430 6.000000 5.000000 MEG 0541 +613 -14.782405 38.147827 6.000000 5.000000 MEG 0613 +612 -14.782405 43.147827 6.000000 5.000000 MEG 0612 +611 -8.782405 40.647827 6.000000 5.000000 MEG 0611 +622 -2.967276 27.260933 6.000000 5.000000 MEG 0622 +623 -2.967276 32.260933 6.000000 5.000000 MEG 0623 +621 3.032724 29.760933 6.000000 5.000000 MEG 0621 +633 -9.094766 14.700909 6.000000 5.000000 MEG 0633 +632 -9.094766 19.700909 6.000000 5.000000 MEG 0632 +631 -3.094766 17.200909 6.000000 5.000000 MEG 0631 +642 -15.199021 26.631405 6.000000 5.000000 MEG 0642 +643 -15.199021 31.631405 6.000000 5.000000 MEG 0643 +641 -9.199021 29.131405 6.000000 5.000000 MEG 0641 +713 -9.246834 1.693846 6.000000 5.000000 MEG 0713 +712 -9.246834 6.693846 6.000000 5.000000 MEG 0712 +711 -3.246834 4.193846 6.000000 5.000000 MEG 0711 +723 3.314525 1.573887 6.000000 5.000000 MEG 0723 +722 3.314525 6.573887 6.000000 5.000000 MEG 0722 +721 9.314525 4.073887 6.000000 5.000000 MEG 0721 +733 3.387173 -10.588106 6.000000 5.000000 MEG 0733 +732 3.387173 -5.588106 6.000000 5.000000 MEG 0732 +731 9.387173 -8.088106 6.000000 5.000000 MEG 0731 +743 -9.422897 -10.519942 6.000000 5.000000 MEG 0743 +742 -9.422897 -5.519942 6.000000 5.000000 MEG 0742 +741 -3.422897 -8.019942 6.000000 5.000000 MEG 0741 +813 -2.962408 61.007698 6.000000 5.000000 MEG 0813 +812 -2.962408 66.007698 6.000000 5.000000 MEG 0812 +811 3.037592 63.507698 6.000000 5.000000 MEG 0811 +822 -2.965545 50.641838 6.000000 5.000000 MEG 0822 +823 -2.965545 55.641838 6.000000 5.000000 MEG 0823 +821 3.034455 53.141838 6.000000 5.000000 MEG 0821 +913 9.504830 59.655254 6.000000 5.000000 MEG 0913 +912 9.504830 64.655254 6.000000 5.000000 MEG 0912 +911 15.504830 62.155254 6.000000 5.000000 MEG 0911 +923 21.967310 55.408710 6.000000 5.000000 MEG 0923 +922 21.967310 60.408710 6.000000 5.000000 MEG 0922 +921 27.967310 57.908710 6.000000 5.000000 MEG 0921 +932 21.254196 43.889683 6.000000 5.000000 MEG 0932 +933 21.254196 48.889683 6.000000 5.000000 MEG 0933 +931 27.254196 46.389683 6.000000 5.000000 MEG 0931 +942 8.661931 49.358044 6.000000 5.000000 MEG 0942 +943 8.661931 54.358044 6.000000 5.000000 MEG 0943 +941 14.661931 51.858044 6.000000 5.000000 MEG 0941 +1013 -2.967087 39.669956 6.000000 5.000000 MEG 1013 +1012 -2.967087 44.669956 6.000000 5.000000 MEG 1012 +1011 3.032913 42.169956 6.000000 5.000000 MEG 1011 +1023 8.751018 38.154079 6.000000 5.000000 MEG 1023 +1022 8.751018 43.154079 6.000000 5.000000 MEG 1022 +1021 14.751018 40.654079 6.000000 5.000000 MEG 1021 +1032 9.123913 26.648697 6.000000 5.000000 MEG 1032 +1033 9.123913 31.648697 6.000000 5.000000 MEG 1033 +1031 15.123913 29.148697 6.000000 5.000000 MEG 1031 +1043 3.200539 14.795620 6.000000 5.000000 MEG 1043 +1042 3.200539 19.795620 6.000000 5.000000 MEG 1042 +1041 9.200539 17.295620 6.000000 5.000000 MEG 1041 +1112 15.014965 13.912239 6.000000 5.000000 MEG 1112 +1113 15.014965 18.912239 6.000000 5.000000 MEG 1113 +1111 21.014965 16.412239 6.000000 5.000000 MEG 1111 +1123 26.958527 15.562130 6.000000 5.000000 MEG 1123 +1122 26.958527 20.562130 6.000000 5.000000 MEG 1122 +1121 32.958527 18.062130 6.000000 5.000000 MEG 1121 +1133 28.757563 0.227141 6.000000 5.000000 MEG 1133 +1132 28.757563 5.227141 6.000000 5.000000 MEG 1132 +1131 34.757563 2.727141 6.000000 5.000000 MEG 1131 +1142 15.882982 0.037700 6.000000 5.000000 MEG 1142 +1143 15.882982 5.037700 6.000000 5.000000 MEG 1143 +1141 21.882982 2.537700 6.000000 5.000000 MEG 1141 +1213 33.958897 47.388790 6.000000 5.000000 MEG 1213 +1212 33.958897 52.388790 6.000000 5.000000 MEG 1212 +1211 39.958897 49.888790 6.000000 5.000000 MEG 1211 +1223 43.923473 33.914738 6.000000 5.000000 MEG 1223 +1222 43.923473 38.914738 6.000000 5.000000 MEG 1222 +1221 49.923473 36.414738 6.000000 5.000000 MEG 1221 +1232 32.014336 32.768585 6.000000 5.000000 MEG 1232 +1233 32.014336 37.768585 6.000000 5.000000 MEG 1233 +1231 38.014336 35.268585 6.000000 5.000000 MEG 1231 +1243 21.600079 28.898149 6.000000 5.000000 MEG 1243 +1242 21.600079 33.898149 6.000000 5.000000 MEG 1242 +1241 27.600079 31.398149 6.000000 5.000000 MEG 1241 +1312 38.599728 17.543867 6.000000 5.000000 MEG 1312 +1313 38.599728 22.543867 6.000000 5.000000 MEG 1313 +1311 44.599728 20.043867 6.000000 5.000000 MEG 1311 +1323 50.558392 16.887651 6.000000 5.000000 MEG 1323 +1322 50.558392 21.887651 6.000000 5.000000 MEG 1322 +1321 56.558392 19.387651 6.000000 5.000000 MEG 1321 +1333 53.420483 -2.919475 6.000000 5.000000 MEG 1333 +1332 53.420483 2.080525 6.000000 5.000000 MEG 1332 +1331 59.420483 -0.419475 6.000000 5.000000 MEG 1331 +1342 41.371586 -0.216817 6.000000 5.000000 MEG 1342 +1343 41.371586 4.783183 6.000000 5.000000 MEG 1343 +1341 47.371586 2.283183 6.000000 5.000000 MEG 1341 +1412 53.704369 38.563030 6.000000 5.000000 MEG 1412 +1413 53.704369 43.563030 6.000000 5.000000 MEG 1413 +1411 59.704369 41.063030 6.000000 5.000000 MEG 1411 +1423 67.119286 33.843739 6.000000 5.000000 MEG 1423 +1422 67.119286 38.843739 6.000000 5.000000 MEG 1422 +1421 73.119286 36.343739 6.000000 5.000000 MEG 1421 +1433 74.438919 8.335863 6.000000 5.000000 MEG 1433 +1432 74.438919 13.335863 6.000000 5.000000 MEG 1432 +1431 80.438919 10.835863 6.000000 5.000000 MEG 1431 +1442 61.883209 18.562304 6.000000 5.000000 MEG 1442 +1443 61.883209 23.562304 6.000000 5.000000 MEG 1443 +1441 67.883209 21.062304 6.000000 5.000000 MEG 1441 +1512 -71.298943 -4.707253 6.000000 5.000000 MEG 1512 +1513 -71.298943 0.292747 6.000000 5.000000 MEG 1513 +1511 -65.298943 -2.207253 6.000000 5.000000 MEG 1511 +1522 -67.281609 -25.407852 6.000000 5.000000 MEG 1522 +1523 -67.281609 -20.407852 6.000000 5.000000 MEG 1523 +1521 -61.281609 -22.907852 6.000000 5.000000 MEG 1521 +1533 -71.702820 -40.152336 6.000000 5.000000 MEG 1533 +1532 -71.702820 -35.152336 6.000000 5.000000 MEG 1532 +1531 -65.702820 -37.652336 6.000000 5.000000 MEG 1531 +1543 -79.907913 -17.418098 6.000000 5.000000 MEG 1543 +1542 -79.907913 -12.418098 6.000000 5.000000 MEG 1542 +1541 -73.907913 -14.918098 6.000000 5.000000 MEG 1541 +1613 -56.916454 -20.312164 6.000000 5.000000 MEG 1613 +1612 -56.916454 -15.312164 6.000000 5.000000 MEG 1612 +1611 -50.916454 -17.812164 6.000000 5.000000 MEG 1611 +1622 -45.631779 -16.320436 6.000000 5.000000 MEG 1622 +1623 -45.631779 -11.320436 6.000000 5.000000 MEG 1623 +1621 -39.631779 -13.820436 6.000000 5.000000 MEG 1621 +1632 -37.896103 -30.578358 6.000000 5.000000 MEG 1632 +1633 -37.896103 -25.578358 6.000000 5.000000 MEG 1633 +1631 -31.896103 -28.078358 6.000000 5.000000 MEG 1631 +1643 -48.859089 -36.176094 6.000000 5.000000 MEG 1643 +1642 -48.859089 -31.176094 6.000000 5.000000 MEG 1642 +1641 -42.859089 -33.676094 6.000000 5.000000 MEG 1641 +1713 -56.796040 -59.082275 6.000000 5.000000 MEG 1713 +1712 -56.796040 -54.082275 6.000000 5.000000 MEG 1712 +1711 -50.796040 -56.582275 6.000000 5.000000 MEG 1711 +1722 -57.188797 -44.057373 6.000000 5.000000 MEG 1722 +1723 -57.188797 -39.057373 6.000000 5.000000 MEG 1723 +1721 -51.188797 -41.557373 6.000000 5.000000 MEG 1721 +1732 -41.902962 -58.279526 6.000000 5.000000 MEG 1732 +1733 -41.902962 -53.279526 6.000000 5.000000 MEG 1733 +1731 -35.902962 -55.779526 6.000000 5.000000 MEG 1731 +1743 -37.408134 -72.449036 6.000000 5.000000 MEG 1743 +1742 -37.408134 -67.449036 6.000000 5.000000 MEG 1742 +1741 -31.408134 -69.949036 6.000000 5.000000 MEG 1741 +1813 -33.801163 -13.768716 6.000000 5.000000 MEG 1813 +1812 -33.801163 -8.768716 6.000000 5.000000 MEG 1812 +1811 -27.801163 -11.268716 6.000000 5.000000 MEG 1811 +1822 -21.685101 -12.619589 6.000000 5.000000 MEG 1822 +1823 -21.685101 -7.619589 6.000000 5.000000 MEG 1823 +1821 -15.685101 -10.119589 6.000000 5.000000 MEG 1821 +1832 -9.600111 -22.190945 6.000000 5.000000 MEG 1832 +1833 -9.600111 -17.190945 6.000000 5.000000 MEG 1833 +1831 -3.600111 -19.690945 6.000000 5.000000 MEG 1831 +1843 -24.483526 -26.850609 6.000000 5.000000 MEG 1843 +1842 -24.483526 -21.850609 6.000000 5.000000 MEG 1842 +1841 -18.483526 -24.350609 6.000000 5.000000 MEG 1841 +1912 -25.866816 -40.850040 6.000000 5.000000 MEG 1912 +1913 -25.866816 -35.850040 6.000000 5.000000 MEG 1913 +1911 -19.866816 -38.350040 6.000000 5.000000 MEG 1911 +1923 -20.513481 -56.355225 6.000000 5.000000 MEG 1923 +1922 -20.513481 -51.355225 6.000000 5.000000 MEG 1922 +1921 -14.513481 -53.855225 6.000000 5.000000 MEG 1921 +1932 -23.428471 -67.375893 6.000000 5.000000 MEG 1932 +1933 -23.428471 -62.375893 6.000000 5.000000 MEG 1933 +1931 -17.428471 -64.875893 6.000000 5.000000 MEG 1931 +1943 -36.237587 -48.444530 6.000000 5.000000 MEG 1943 +1942 -36.237587 -43.444530 6.000000 5.000000 MEG 1942 +1941 -30.237587 -45.944530 6.000000 5.000000 MEG 1941 +2013 -10.441930 -34.308243 6.000000 5.000000 MEG 2013 +2012 -10.441930 -29.308243 6.000000 5.000000 MEG 2012 +2011 -4.441930 -31.808243 6.000000 5.000000 MEG 2011 +2023 4.357624 -34.289736 6.000000 5.000000 MEG 2023 +2022 4.357624 -29.289736 6.000000 5.000000 MEG 2022 +2021 10.357624 -31.789736 6.000000 5.000000 MEG 2021 +2032 4.645295 -46.290749 6.000000 5.000000 MEG 2032 +2033 4.645295 -41.290749 6.000000 5.000000 MEG 2033 +2031 10.645295 -43.790749 6.000000 5.000000 MEG 2031 +2042 -10.645079 -46.244335 6.000000 5.000000 MEG 2042 +2043 -10.645079 -41.244335 6.000000 5.000000 MEG 2043 +2041 -4.645079 -43.744335 6.000000 5.000000 MEG 2041 +2113 -3.052351 -58.889515 6.000000 5.000000 MEG 2113 +2112 -3.052351 -53.889515 6.000000 5.000000 MEG 2112 +2111 2.947649 -56.389515 6.000000 5.000000 MEG 2111 +2122 -2.999999 -70.362061 6.000000 5.000000 MEG 2122 +2123 -2.999999 -65.362061 6.000000 5.000000 MEG 2123 +2121 3.000001 -67.862061 6.000000 5.000000 MEG 2121 +2133 8.918572 -79.441826 6.000000 5.000000 MEG 2133 +2132 8.918572 -74.441826 6.000000 5.000000 MEG 2132 +2131 14.918572 -76.941826 6.000000 5.000000 MEG 2131 +2143 -14.987089 -79.428932 6.000000 5.000000 MEG 2143 +2142 -14.987089 -74.428932 6.000000 5.000000 MEG 2142 +2141 -8.987089 -76.928932 6.000000 5.000000 MEG 2141 +2212 15.641460 -12.579389 6.000000 5.000000 MEG 2212 +2213 15.641460 -7.579389 6.000000 5.000000 MEG 2213 +2211 21.641460 -10.079389 6.000000 5.000000 MEG 2211 +2223 27.786499 -13.669980 6.000000 5.000000 MEG 2223 +2222 27.786499 -8.669980 6.000000 5.000000 MEG 2222 +2221 33.786499 -11.169980 6.000000 5.000000 MEG 2221 +2233 18.501518 -26.949615 6.000000 5.000000 MEG 2233 +2232 18.501518 -21.949615 6.000000 5.000000 MEG 2232 +2231 24.501518 -24.449615 6.000000 5.000000 MEG 2231 +2242 3.641699 -22.206125 6.000000 5.000000 MEG 2242 +2243 3.641699 -17.206125 6.000000 5.000000 MEG 2243 +2241 9.641699 -19.706125 6.000000 5.000000 MEG 2241 +2312 19.852789 -40.871220 6.000000 5.000000 MEG 2312 +2313 19.852789 -35.871220 6.000000 5.000000 MEG 2313 +2311 25.852789 -38.371220 6.000000 5.000000 MEG 2311 +2323 30.078903 -48.474960 6.000000 5.000000 MEG 2323 +2322 30.078903 -43.474960 6.000000 5.000000 MEG 2322 +2321 36.078903 -45.974960 6.000000 5.000000 MEG 2321 +2332 17.363274 -67.365387 6.000000 5.000000 MEG 2332 +2333 17.363274 -62.365387 6.000000 5.000000 MEG 2333 +2331 23.363274 -64.865387 6.000000 5.000000 MEG 2331 +2343 14.329920 -56.380260 6.000000 5.000000 MEG 2343 +2342 14.329920 -51.380260 6.000000 5.000000 MEG 2342 +2341 20.329920 -53.880260 6.000000 5.000000 MEG 2341 +2412 39.644810 -16.175139 6.000000 5.000000 MEG 2412 +2413 39.644810 -11.175139 6.000000 5.000000 MEG 2413 +2411 45.644810 -13.675139 6.000000 5.000000 MEG 2411 +2423 50.812263 -20.401899 6.000000 5.000000 MEG 2423 +2422 50.812263 -15.401899 6.000000 5.000000 MEG 2422 +2421 56.812263 -17.901899 6.000000 5.000000 MEG 2421 +2433 42.694180 -36.278580 6.000000 5.000000 MEG 2433 +2432 42.694180 -31.278580 6.000000 5.000000 MEG 2432 +2431 48.694180 -33.778580 6.000000 5.000000 MEG 2431 +2442 31.896111 -30.578348 6.000000 5.000000 MEG 2442 +2443 31.896111 -25.578348 6.000000 5.000000 MEG 2443 +2441 37.896111 -28.078348 6.000000 5.000000 MEG 2441 +2512 35.812634 -58.300888 6.000000 5.000000 MEG 2512 +2513 35.812634 -53.300888 6.000000 5.000000 MEG 2513 +2511 41.812634 -55.800888 6.000000 5.000000 MEG 2511 +2522 51.171906 -43.981274 6.000000 5.000000 MEG 2522 +2523 51.171906 -38.981274 6.000000 5.000000 MEG 2523 +2521 57.171906 -41.481274 6.000000 5.000000 MEG 2521 +2533 50.704624 -59.132656 6.000000 5.000000 MEG 2533 +2532 50.704624 -54.132656 6.000000 5.000000 MEG 2532 +2531 56.704624 -56.632656 6.000000 5.000000 MEG 2531 +2543 31.320171 -72.484848 6.000000 5.000000 MEG 2543 +2542 31.320171 -67.484848 6.000000 5.000000 MEG 2542 +2541 37.320171 -69.984848 6.000000 5.000000 MEG 2541 +2612 65.137360 -4.702045 6.000000 5.000000 MEG 2612 +2613 65.137360 0.297955 6.000000 5.000000 MEG 2613 +2611 71.137360 -2.202045 6.000000 5.000000 MEG 2611 +2623 73.822243 -17.329140 6.000000 5.000000 MEG 2623 +2622 73.822243 -12.329140 6.000000 5.000000 MEG 2622 +2621 79.822243 -14.829140 6.000000 5.000000 MEG 2621 +2633 65.490112 -40.332645 6.000000 5.000000 MEG 2633 +2632 65.490112 -35.332645 6.000000 5.000000 MEG 2632 +2631 71.490112 -37.832645 6.000000 5.000000 MEG 2631 +2642 61.220192 -25.385981 6.000000 5.000000 MEG 2642 +2643 61.220192 -20.385981 6.000000 5.000000 MEG 2643 +2641 67.220192 -22.885981 6.000000 5.000000 MEG 2641 diff --git a/mne-python/source/mne/channels/data/layouts/Vectorview-grad.lout b/mne-python/source/mne/channels/data/layouts/Vectorview-grad.lout new file mode 100644 index 0000000000000000000000000000000000000000..1f133a185914a8a2ff285d24e0bfe7e650121967 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/Vectorview-grad.lout @@ -0,0 +1,205 @@ +-55.000000 55.000000 -65.000000 60.000000 +113 -48.186871 26.886379 6.000000 5.000000 MEG 0113 +112 -48.186871 31.886379 6.000000 5.000000 MEG 0112 +122 -39.322296 31.036510 6.000000 5.000000 MEG 0122 +123 -39.322296 36.036510 6.000000 5.000000 MEG 0123 +132 -44.722965 14.826612 6.000000 5.000000 MEG 0132 +133 -44.722965 19.826612 6.000000 5.000000 MEG 0133 +143 -52.785782 6.169280 6.000000 5.000000 MEG 0143 +142 -52.785782 11.169280 6.000000 5.000000 MEG 0142 +213 -37.392612 13.470296 6.000000 5.000000 MEG 0213 +212 -37.392612 18.470296 6.000000 5.000000 MEG 0212 +222 -29.695013 13.899532 6.000000 5.000000 MEG 0222 +223 -29.695013 18.899532 6.000000 5.000000 MEG 0223 +232 -31.502516 -0.631914 6.000000 5.000000 MEG 0232 +233 -31.502516 4.368086 6.000000 5.000000 MEG 0233 +243 -39.115921 -2.709978 6.000000 5.000000 MEG 0243 +242 -39.115921 2.290022 6.000000 5.000000 MEG 0242 +313 -26.608879 38.351933 6.000000 5.000000 MEG 0313 +312 -26.608879 43.351933 6.000000 5.000000 MEG 0312 +322 -25.469093 26.356115 6.000000 5.000000 MEG 0322 +323 -25.469093 31.356115 6.000000 5.000000 MEG 0323 +333 -18.837411 23.164780 6.000000 5.000000 MEG 0333 +332 -18.837411 28.164780 6.000000 5.000000 MEG 0332 +343 -32.957949 27.427811 6.000000 5.000000 MEG 0343 +342 -32.957949 32.427811 6.000000 5.000000 MEG 0342 +413 -22.250046 12.315103 6.000000 5.000000 MEG 0413 +412 -22.250046 17.315103 6.000000 5.000000 MEG 0412 +422 -14.605187 10.962016 6.000000 5.000000 MEG 0422 +423 -14.605187 15.962016 6.000000 5.000000 MEG 0423 +432 -15.148193 -0.524500 6.000000 5.000000 MEG 0432 +433 -15.148193 4.475500 6.000000 5.000000 MEG 0433 +443 -23.422245 -0.157884 6.000000 5.000000 MEG 0443 +442 -23.422245 4.842116 6.000000 5.000000 MEG 0442 +513 -18.953902 44.905155 6.000000 5.000000 MEG 0513 +512 -18.953902 49.905155 6.000000 5.000000 MEG 0512 +523 -11.025696 48.325344 6.000000 5.000000 MEG 0523 +522 -11.025696 53.325344 6.000000 5.000000 MEG 0522 +532 -10.454178 39.888676 6.000000 5.000000 MEG 0532 +533 -10.454178 44.888676 6.000000 5.000000 MEG 0533 +542 -18.555386 35.433716 6.000000 5.000000 MEG 0542 +543 -18.555386 40.433716 6.000000 5.000000 MEG 0543 +613 -10.560901 30.757313 6.000000 5.000000 MEG 0613 +612 -10.560901 35.757313 6.000000 5.000000 MEG 0612 +622 -2.979000 21.849854 6.000000 5.000000 MEG 0622 +623 -2.979000 26.849854 6.000000 5.000000 MEG 0623 +633 -6.911079 11.573471 6.000000 5.000000 MEG 0633 +632 -6.911079 16.573471 6.000000 5.000000 MEG 0632 +642 -10.828249 21.334785 6.000000 5.000000 MEG 0642 +643 -10.828249 26.334785 6.000000 5.000000 MEG 0643 +713 -7.008664 0.931329 6.000000 5.000000 MEG 0713 +712 -7.008664 5.931329 6.000000 5.000000 MEG 0712 +723 1.052102 0.833180 6.000000 5.000000 MEG 0723 +722 1.052102 5.833180 6.000000 5.000000 MEG 0722 +733 1.098721 -8.987786 6.000000 5.000000 MEG 0733 +732 1.098721 -3.987786 6.000000 5.000000 MEG 0732 +743 -7.121645 -8.933109 6.000000 5.000000 MEG 0743 +742 -7.121645 -3.933109 6.000000 5.000000 MEG 0742 +813 -2.975877 49.460842 6.000000 5.000000 MEG 0813 +812 -2.975877 54.460842 6.000000 5.000000 MEG 0812 +822 -2.977890 40.979687 6.000000 5.000000 MEG 0822 +823 -2.977890 45.979687 6.000000 5.000000 MEG 0823 +913 5.024490 48.354298 6.000000 5.000000 MEG 0913 +912 5.024490 53.354298 6.000000 5.000000 MEG 0912 +923 13.021803 44.879852 6.000000 5.000000 MEG 0923 +922 13.021803 49.879852 6.000000 5.000000 MEG 0922 +932 12.564190 35.455193 6.000000 5.000000 MEG 0932 +933 12.564190 40.455193 6.000000 5.000000 MEG 0933 +942 4.483593 39.929310 6.000000 5.000000 MEG 0942 +943 4.483593 44.929310 6.000000 5.000000 MEG 0943 +1013 -2.978879 32.002693 6.000000 5.000000 MEG 1013 +1012 -2.978879 37.002693 6.000000 5.000000 MEG 1012 +1023 4.540760 30.762428 6.000000 5.000000 MEG 1023 +1022 4.540760 35.762428 6.000000 5.000000 MEG 1022 +1032 4.780051 21.348934 6.000000 5.000000 MEG 1032 +1033 4.780051 26.348934 6.000000 5.000000 MEG 1033 +1043 0.978956 11.650963 6.000000 5.000000 MEG 1043 +1042 0.978956 16.650963 6.000000 5.000000 MEG 1042 +1112 8.560405 10.928195 6.000000 5.000000 MEG 1112 +1113 8.560405 15.928195 6.000000 5.000000 MEG 1113 +1123 16.224724 12.278107 6.000000 5.000000 MEG 1123 +1122 16.224724 17.278107 6.000000 5.000000 MEG 1122 +1133 17.379185 -0.268703 6.000000 5.000000 MEG 1133 +1132 17.379185 4.731297 6.000000 5.000000 MEG 1132 +1142 9.117422 -0.423700 6.000000 5.000000 MEG 1142 +1143 9.117422 4.576300 6.000000 5.000000 MEG 1143 +1213 20.716938 38.318100 6.000000 5.000000 MEG 1213 +1212 20.716938 43.318100 6.000000 5.000000 MEG 1212 +1223 27.111319 27.293877 6.000000 5.000000 MEG 1223 +1222 27.111319 32.293877 6.000000 5.000000 MEG 1222 +1232 19.469093 26.356115 6.000000 5.000000 MEG 1232 +1233 19.469093 31.356115 6.000000 5.000000 MEG 1233 +1243 12.786146 23.189396 6.000000 5.000000 MEG 1243 +1242 12.786146 28.189396 6.000000 5.000000 MEG 1242 +1312 23.695013 13.899529 6.000000 5.000000 MEG 1312 +1313 23.695013 18.899529 6.000000 5.000000 MEG 1313 +1323 31.369019 13.362624 6.000000 5.000000 MEG 1323 +1322 31.369019 18.362624 6.000000 5.000000 MEG 1322 +1333 33.205658 -2.836478 6.000000 5.000000 MEG 1333 +1332 33.205658 2.163522 6.000000 5.000000 MEG 1332 +1342 25.473745 -0.631941 6.000000 5.000000 MEG 1342 +1343 25.473745 4.368059 6.000000 5.000000 MEG 1343 +1412 33.387833 31.097027 6.000000 5.000000 MEG 1412 +1413 33.387833 36.097027 6.000000 5.000000 MEG 1413 +1423 41.996334 27.235786 6.000000 5.000000 MEG 1423 +1422 41.996334 32.235786 6.000000 5.000000 MEG 1422 +1433 46.693424 6.365705 6.000000 5.000000 MEG 1433 +1432 46.693424 11.365705 6.000000 5.000000 MEG 1432 +1442 38.636284 14.732794 6.000000 5.000000 MEG 1442 +1443 38.636284 19.732794 6.000000 5.000000 MEG 1443 +1512 -46.828197 -4.270524 6.000000 5.000000 MEG 1512 +1513 -46.828197 0.729476 6.000000 5.000000 MEG 1513 +1522 -44.250233 -20.875282 6.000000 5.000000 MEG 1522 +1523 -44.250233 -15.875282 6.000000 5.000000 MEG 1523 +1533 -47.087372 -32.702410 6.000000 5.000000 MEG 1533 +1532 -47.087372 -27.702410 6.000000 5.000000 MEG 1532 +1543 -52.352669 -14.466389 6.000000 5.000000 MEG 1543 +1542 -52.352669 -9.466389 6.000000 5.000000 MEG 1542 +1613 -37.598797 -16.787832 6.000000 5.000000 MEG 1613 +1612 -37.598797 -11.787832 6.000000 5.000000 MEG 1612 +1622 -30.357292 -13.585911 6.000000 5.000000 MEG 1622 +1623 -30.357292 -8.585911 6.000000 5.000000 MEG 1623 +1632 -25.393221 -25.022747 6.000000 5.000000 MEG 1632 +1633 -25.393221 -20.022747 6.000000 5.000000 MEG 1633 +1643 -32.428291 -29.512911 6.000000 5.000000 MEG 1643 +1642 -32.428291 -24.512911 6.000000 5.000000 MEG 1642 +1713 -37.521523 -47.886852 6.000000 5.000000 MEG 1713 +1712 -37.521523 -42.886852 6.000000 5.000000 MEG 1712 +1722 -37.773560 -35.834789 6.000000 5.000000 MEG 1722 +1723 -37.773560 -30.834789 6.000000 5.000000 MEG 1723 +1732 -27.964468 -47.242935 6.000000 5.000000 MEG 1732 +1733 -27.964468 -42.242935 6.000000 5.000000 MEG 1733 +1743 -25.080088 -58.608849 6.000000 5.000000 MEG 1743 +1742 -25.080088 -53.608849 6.000000 5.000000 MEG 1742 +1813 -22.765453 -11.539077 6.000000 5.000000 MEG 1813 +1812 -22.765453 -6.539077 6.000000 5.000000 MEG 1812 +1822 -14.990439 -10.617317 6.000000 5.000000 MEG 1822 +1823 -14.990439 -5.617317 6.000000 5.000000 MEG 1823 +1832 -7.235366 -18.294876 6.000000 5.000000 MEG 1832 +1833 -7.235366 -13.294876 6.000000 5.000000 MEG 1833 +1843 -16.786220 -22.032574 6.000000 5.000000 MEG 1843 +1842 -16.786220 -17.032574 6.000000 5.000000 MEG 1842 +1912 -17.673892 -33.262066 6.000000 5.000000 MEG 1912 +1913 -17.673892 -28.262066 6.000000 5.000000 MEG 1913 +1923 -14.238597 -45.699379 6.000000 5.000000 MEG 1923 +1922 -14.238597 -40.699379 6.000000 5.000000 MEG 1922 +1932 -16.109179 -54.539486 6.000000 5.000000 MEG 1932 +1933 -16.109179 -49.539486 6.000000 5.000000 MEG 1933 +1943 -24.328934 -39.353901 6.000000 5.000000 MEG 1943 +1942 -24.328934 -34.353901 6.000000 5.000000 MEG 1942 +2013 -7.775570 -28.014633 6.000000 5.000000 MEG 2013 +2012 -7.775570 -23.014633 6.000000 5.000000 MEG 2012 +2023 1.721470 -27.999788 6.000000 5.000000 MEG 2023 +2022 1.721470 -22.999788 6.000000 5.000000 MEG 2022 +2032 1.906072 -37.626270 6.000000 5.000000 MEG 2032 +2033 1.906072 -32.626270 6.000000 5.000000 MEG 2033 +2042 -7.905933 -37.589039 6.000000 5.000000 MEG 2042 +2043 -7.905933 -32.589039 6.000000 5.000000 MEG 2043 +2113 -3.033595 -47.732231 6.000000 5.000000 MEG 2113 +2112 -3.033595 -42.732231 6.000000 5.000000 MEG 2112 +2122 -2.999999 -56.934807 6.000000 5.000000 MEG 2122 +2123 -2.999999 -51.934807 6.000000 5.000000 MEG 2123 +2133 4.648282 -64.218044 6.000000 5.000000 MEG 2133 +2132 4.648282 -59.218044 6.000000 5.000000 MEG 2132 +2143 -10.692250 -64.207703 6.000000 5.000000 MEG 2143 +2142 -10.692250 -59.207703 6.000000 5.000000 MEG 2142 +2212 8.962435 -10.585071 6.000000 5.000000 MEG 2212 +2213 8.962435 -5.585071 6.000000 5.000000 MEG 2213 +2223 16.756042 -11.459877 6.000000 5.000000 MEG 2223 +2222 16.756042 -6.459877 6.000000 5.000000 MEG 2222 +2233 10.797766 -22.111992 6.000000 5.000000 MEG 2233 +2232 10.797766 -17.111992 6.000000 5.000000 MEG 2232 +2242 1.262053 -18.307052 6.000000 5.000000 MEG 2242 +2243 1.262053 -13.307052 6.000000 5.000000 MEG 2243 +2312 11.664891 -33.279053 6.000000 5.000000 MEG 2312 +2313 11.664891 -28.279053 6.000000 5.000000 MEG 2313 +2323 18.227104 -39.378311 6.000000 5.000000 MEG 2323 +2322 18.227104 -34.378311 6.000000 5.000000 MEG 2322 +2332 10.067341 -54.531059 6.000000 5.000000 MEG 2332 +2333 10.067341 -49.531059 6.000000 5.000000 MEG 2333 +2343 8.120804 -45.719460 6.000000 5.000000 MEG 2343 +2342 8.120804 -40.719460 6.000000 5.000000 MEG 2342 +2412 24.365654 -13.469363 6.000000 5.000000 MEG 2412 +2413 24.365654 -8.469363 6.000000 5.000000 MEG 2413 +2423 31.531933 -16.859812 6.000000 5.000000 MEG 2423 +2422 31.531933 -11.859812 6.000000 5.000000 MEG 2422 +2433 26.322470 -29.595119 6.000000 5.000000 MEG 2433 +2432 26.322470 -24.595119 6.000000 5.000000 MEG 2432 +2442 19.393225 -25.022739 6.000000 5.000000 MEG 2442 +2443 19.393225 -20.022739 6.000000 5.000000 MEG 2443 +2512 21.906504 -47.260071 6.000000 5.000000 MEG 2512 +2513 21.906504 -42.260071 6.000000 5.000000 MEG 2513 +2522 31.762718 -35.773750 6.000000 5.000000 MEG 2522 +2523 31.762718 -30.773750 6.000000 5.000000 MEG 2523 +2533 31.462860 -47.927265 6.000000 5.000000 MEG 2533 +2532 31.462860 -42.927265 6.000000 5.000000 MEG 2532 +2543 19.023640 -58.637577 6.000000 5.000000 MEG 2543 +2542 19.023640 -53.637577 6.000000 5.000000 MEG 2542 +2612 40.724506 -4.266347 6.000000 5.000000 MEG 2612 +2613 40.724506 0.733653 6.000000 5.000000 MEG 2613 +2623 46.297695 -14.395032 6.000000 5.000000 MEG 2623 +2622 46.297695 -9.395032 6.000000 5.000000 MEG 2622 +2633 40.950874 -32.847042 6.000000 5.000000 MEG 2633 +2632 40.950874 -27.847042 6.000000 5.000000 MEG 2632 +2642 38.210819 -20.857738 6.000000 5.000000 MEG 2642 +2643 38.210819 -15.857738 6.000000 5.000000 MEG 2643 diff --git a/mne-python/source/mne/channels/data/layouts/Vectorview-grad_norm.lout b/mne-python/source/mne/channels/data/layouts/Vectorview-grad_norm.lout new file mode 100644 index 0000000000000000000000000000000000000000..d06ce01c2f2321630bbb2298005486b780376910 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/Vectorview-grad_norm.lout @@ -0,0 +1,103 @@ +-50.000000 50.000000 -50.000000 38.000000 +11 -41.408840 17.090919 6.000000 5.000000 MEG 011X +12 -33.873951 19.857674 6.000000 5.000000 MEG 012X +13 -38.464523 9.051075 6.000000 5.000000 MEG 013X +14 -45.317917 3.279520 6.000000 5.000000 MEG 014X +21 -32.233719 8.146864 6.000000 5.000000 MEG 021X +22 -25.690760 8.433022 6.000000 5.000000 MEG 022X +23 -27.227139 -1.254610 6.000000 5.000000 MEG 023X +24 -33.698534 -2.642785 6.000000 5.000000 MEG 024X +31 -23.067547 24.734621 6.000000 5.000000 MEG 031X +32 -22.098728 16.737410 6.000000 5.000000 MEG 032X +33 -16.461800 14.609854 6.000000 5.000000 MEG 033X +34 -28.464256 17.451874 6.000000 5.000000 MEG 034X +41 -19.362539 7.376735 6.000000 5.000000 MEG 041X +42 -12.864409 6.474677 6.000000 5.000000 MEG 042X +43 -13.325964 -1.183000 6.000000 5.000000 MEG 043X +44 -20.358908 -0.938589 6.000000 5.000000 MEG 044X +51 -16.560817 29.103437 6.000000 5.000000 MEG 051X +52 -9.821842 31.383564 6.000000 5.000000 MEG 052X +53 -9.336051 25.759117 6.000000 5.000000 MEG 053X +54 -16.222077 22.789145 6.000000 5.000000 MEG 054X +61 -9.426766 19.671541 6.000000 5.000000 MEG 061X +62 -2.982150 13.733236 6.000000 5.000000 MEG 062X +63 -6.324418 6.882314 6.000000 5.000000 MEG 063X +64 -9.654012 13.389857 6.000000 5.000000 MEG 064X +71 -6.407364 -0.212448 6.000000 5.000000 MEG 071X +72 0.444286 -0.277880 6.000000 5.000000 MEG 072X +73 0.483912 -6.911695 6.000000 5.000000 MEG 073X +74 -6.503398 -6.874514 6.000000 5.000000 MEG 074X +81 -2.979496 32.140564 6.000000 5.000000 MEG 081X +82 -2.981206 26.486458 6.000000 5.000000 MEG 082X +91 3.820817 31.402866 6.000000 5.000000 MEG 091X +92 10.618533 29.086569 6.000000 5.000000 MEG 092X +93 10.229562 22.803463 6.000000 5.000000 MEG 093X +94 3.361053 25.786205 6.000000 5.000000 MEG 094X +101 -2.982047 20.501795 6.000000 5.000000 MEG 101X +102 3.409646 19.674952 6.000000 5.000000 MEG 102X +103 3.613043 13.399289 6.000000 5.000000 MEG 103X +104 0.382112 6.933975 6.000000 5.000000 MEG 104X +111 6.826344 6.452130 6.000000 5.000000 MEG 111X +112 13.341015 7.352071 6.000000 5.000000 MEG 112X +113 14.322306 -1.012468 6.000000 5.000000 MEG 113X +114 7.299809 -1.115800 6.000000 5.000000 MEG 114X +121 17.159397 24.712067 6.000000 5.000000 MEG 121X +122 22.594622 17.362583 6.000000 5.000000 MEG 122X +123 16.098728 16.737411 6.000000 5.000000 MEG 123X +124 10.418224 14.626265 6.000000 5.000000 MEG 124X +131 19.690762 8.433019 6.000000 5.000000 MEG 131X +132 26.213667 8.075083 6.000000 5.000000 MEG 132X +133 27.774809 -2.728805 6.000000 5.000000 MEG 133X +134 21.202684 -1.254627 6.000000 5.000000 MEG 134X +141 27.929657 19.898018 6.000000 5.000000 MEG 141X +142 35.246883 17.323858 6.000000 5.000000 MEG 142X +143 39.239410 3.410470 6.000000 5.000000 MEG 143X +144 32.390839 8.988529 6.000000 5.000000 MEG 144X +151 -40.253967 -3.703956 6.000000 5.000000 MEG 151X +152 -38.062698 -14.995193 6.000000 5.000000 MEG 152X +153 -40.474266 -23.037640 6.000000 5.000000 MEG 153X +154 -44.949768 -10.637144 6.000000 5.000000 MEG 154X +161 -32.408976 -12.215726 6.000000 5.000000 MEG 161X +162 -26.253698 -10.038419 6.000000 5.000000 MEG 162X +163 -22.034237 -17.815468 6.000000 5.000000 MEG 163X +164 -28.014048 -20.868780 6.000000 5.000000 MEG 164X +171 -32.343294 -33.363060 6.000000 5.000000 MEG 171X +172 -32.557526 -25.167658 6.000000 5.000000 MEG 172X +173 -24.219797 -32.925196 6.000000 5.000000 MEG 173X +174 -21.768074 -40.654018 6.000000 5.000000 MEG 174X +181 -19.800634 -8.646573 6.000000 5.000000 MEG 181X +182 -13.191874 -8.019776 6.000000 5.000000 MEG 182X +183 -6.600061 -13.240516 6.000000 5.000000 MEG 183X +184 -14.718287 -15.782150 6.000000 5.000000 MEG 184X +191 -15.472808 -23.418205 6.000000 5.000000 MEG 191X +192 -12.552808 -31.875578 6.000000 5.000000 MEG 192X +193 -14.142802 -37.886852 6.000000 5.000000 MEG 193X +194 -21.129593 -27.560652 6.000000 5.000000 MEG 194X +201 -7.059234 -19.849951 6.000000 5.000000 MEG 201X +202 1.013249 -19.839857 6.000000 5.000000 MEG 202X +203 1.170161 -26.385864 6.000000 5.000000 MEG 203X +204 -7.170043 -26.360546 6.000000 5.000000 MEG 204X +211 -3.028555 -33.257917 6.000000 5.000000 MEG 211X +212 -3.000000 -39.515667 6.000000 5.000000 MEG 212X +213 3.501040 -44.468269 6.000000 5.000000 MEG 213X +214 -9.538412 -44.461239 6.000000 5.000000 MEG 214X +221 7.168070 -7.997848 6.000000 5.000000 MEG 221X +222 13.792637 -8.592716 6.000000 5.000000 MEG 222X +223 8.728101 -15.836154 6.000000 5.000000 MEG 223X +224 0.622745 -13.248796 6.000000 5.000000 MEG 224X +231 9.465158 -23.429756 6.000000 5.000000 MEG 231X +232 15.043037 -27.577251 6.000000 5.000000 MEG 232X +233 8.107240 -37.881119 6.000000 5.000000 MEG 233X +234 6.452683 -31.889233 6.000000 5.000000 MEG 234X +241 20.260805 -9.959167 6.000000 5.000000 MEG 241X +242 26.352144 -12.264672 6.000000 5.000000 MEG 242X +243 21.924099 -20.924681 6.000000 5.000000 MEG 243X +244 16.034241 -17.815463 6.000000 5.000000 MEG 244X +251 18.170528 -32.936850 6.000000 5.000000 MEG 251X +252 26.548311 -25.126150 6.000000 5.000000 MEG 252X +253 26.293430 -33.390539 6.000000 5.000000 MEG 253X +254 15.720093 -40.673553 6.000000 5.000000 MEG 254X +261 34.165833 -3.701116 6.000000 5.000000 MEG 261X +262 38.903042 -10.588621 6.000000 5.000000 MEG 262X +263 34.358242 -23.135988 6.000000 5.000000 MEG 263X +264 32.029198 -14.983262 6.000000 5.000000 MEG 264X diff --git a/mne-python/source/mne/channels/data/layouts/Vectorview-mag.lout b/mne-python/source/mne/channels/data/layouts/Vectorview-mag.lout new file mode 100644 index 0000000000000000000000000000000000000000..c5f4c60dea049bae7c021b3cffefb13df1432474 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/Vectorview-mag.lout @@ -0,0 +1,103 @@ +-50.000000 50.000000 -50.000000 38.000000 +111 -41.408840 17.090919 6.000000 5.000000 MEG 0111 +121 -33.873951 19.857674 6.000000 5.000000 MEG 0121 +131 -38.464523 9.051075 6.000000 5.000000 MEG 0131 +141 -45.317917 3.279520 6.000000 5.000000 MEG 0141 +211 -32.233719 8.146864 6.000000 5.000000 MEG 0211 +221 -25.690760 8.433022 6.000000 5.000000 MEG 0221 +231 -27.227139 -1.254610 6.000000 5.000000 MEG 0231 +241 -33.698534 -2.642785 6.000000 5.000000 MEG 0241 +311 -23.067547 24.734621 6.000000 5.000000 MEG 0311 +321 -22.098728 16.737410 6.000000 5.000000 MEG 0321 +331 -16.461800 14.609854 6.000000 5.000000 MEG 0331 +341 -28.464256 17.451874 6.000000 5.000000 MEG 0341 +411 -19.362539 7.376735 6.000000 5.000000 MEG 0411 +421 -12.864409 6.474677 6.000000 5.000000 MEG 0421 +431 -13.325964 -1.183000 6.000000 5.000000 MEG 0431 +441 -20.358908 -0.938589 6.000000 5.000000 MEG 0441 +511 -16.560817 29.103437 6.000000 5.000000 MEG 0511 +521 -9.821842 31.383564 6.000000 5.000000 MEG 0521 +531 -9.336051 25.759117 6.000000 5.000000 MEG 0531 +541 -16.222077 22.789145 6.000000 5.000000 MEG 0541 +611 -9.426766 19.671541 6.000000 5.000000 MEG 0611 +621 -2.982150 13.733236 6.000000 5.000000 MEG 0621 +631 -6.324418 6.882314 6.000000 5.000000 MEG 0631 +641 -9.654012 13.389857 6.000000 5.000000 MEG 0641 +711 -6.407364 -0.212448 6.000000 5.000000 MEG 0711 +721 0.444286 -0.277880 6.000000 5.000000 MEG 0721 +731 0.483912 -6.911695 6.000000 5.000000 MEG 0731 +741 -6.503398 -6.874514 6.000000 5.000000 MEG 0741 +811 -2.979496 32.140564 6.000000 5.000000 MEG 0811 +821 -2.981206 26.486458 6.000000 5.000000 MEG 0821 +911 3.820817 31.402866 6.000000 5.000000 MEG 0911 +921 10.618533 29.086569 6.000000 5.000000 MEG 0921 +931 10.229562 22.803463 6.000000 5.000000 MEG 0931 +941 3.361053 25.786205 6.000000 5.000000 MEG 0941 +1011 -2.982047 20.501795 6.000000 5.000000 MEG 1011 +1021 3.409646 19.674952 6.000000 5.000000 MEG 1021 +1031 3.613043 13.399289 6.000000 5.000000 MEG 1031 +1041 0.382112 6.933975 6.000000 5.000000 MEG 1041 +1111 6.826344 6.452130 6.000000 5.000000 MEG 1111 +1121 13.341015 7.352071 6.000000 5.000000 MEG 1121 +1131 14.322306 -1.012468 6.000000 5.000000 MEG 1131 +1141 7.299809 -1.115800 6.000000 5.000000 MEG 1141 +1211 17.159397 24.712067 6.000000 5.000000 MEG 1211 +1221 22.594622 17.362583 6.000000 5.000000 MEG 1221 +1231 16.098728 16.737411 6.000000 5.000000 MEG 1231 +1241 10.418224 14.626265 6.000000 5.000000 MEG 1241 +1311 19.690762 8.433019 6.000000 5.000000 MEG 1311 +1321 26.213667 8.075083 6.000000 5.000000 MEG 1321 +1331 27.774809 -2.728805 6.000000 5.000000 MEG 1331 +1341 21.202684 -1.254627 6.000000 5.000000 MEG 1341 +1411 27.929657 19.898018 6.000000 5.000000 MEG 1411 +1421 35.246883 17.323858 6.000000 5.000000 MEG 1421 +1431 39.239410 3.410470 6.000000 5.000000 MEG 1431 +1441 32.390839 8.988529 6.000000 5.000000 MEG 1441 +1511 -40.253967 -3.703956 6.000000 5.000000 MEG 1511 +1521 -38.062698 -14.995193 6.000000 5.000000 MEG 1521 +1531 -40.474266 -23.037640 6.000000 5.000000 MEG 1531 +1541 -44.949768 -10.637144 6.000000 5.000000 MEG 1541 +1611 -32.408976 -12.215726 6.000000 5.000000 MEG 1611 +1621 -26.253698 -10.038419 6.000000 5.000000 MEG 1621 +1631 -22.034237 -17.815468 6.000000 5.000000 MEG 1631 +1641 -28.014048 -20.868780 6.000000 5.000000 MEG 1641 +1711 -32.343294 -33.363060 6.000000 5.000000 MEG 1711 +1721 -32.557526 -25.167658 6.000000 5.000000 MEG 1721 +1731 -24.219797 -32.925196 6.000000 5.000000 MEG 1731 +1741 -21.768074 -40.654018 6.000000 5.000000 MEG 1741 +1811 -19.800634 -8.646573 6.000000 5.000000 MEG 1811 +1821 -13.191874 -8.019776 6.000000 5.000000 MEG 1821 +1831 -6.600061 -13.240516 6.000000 5.000000 MEG 1831 +1841 -14.718287 -15.782150 6.000000 5.000000 MEG 1841 +1911 -15.472808 -23.418205 6.000000 5.000000 MEG 1911 +1921 -12.552808 -31.875578 6.000000 5.000000 MEG 1921 +1931 -14.142802 -37.886852 6.000000 5.000000 MEG 1931 +1941 -21.129593 -27.560652 6.000000 5.000000 MEG 1941 +2011 -7.059234 -19.849951 6.000000 5.000000 MEG 2011 +2021 1.013249 -19.839857 6.000000 5.000000 MEG 2021 +2031 1.170161 -26.385864 6.000000 5.000000 MEG 2031 +2041 -7.170043 -26.360546 6.000000 5.000000 MEG 2041 +2111 -3.028555 -33.257917 6.000000 5.000000 MEG 2111 +2121 -3.000000 -39.515667 6.000000 5.000000 MEG 2121 +2131 3.501040 -44.468269 6.000000 5.000000 MEG 2131 +2141 -9.538412 -44.461239 6.000000 5.000000 MEG 2141 +2211 7.168070 -7.997848 6.000000 5.000000 MEG 2211 +2221 13.792637 -8.592716 6.000000 5.000000 MEG 2221 +2231 8.728101 -15.836154 6.000000 5.000000 MEG 2231 +2241 0.622745 -13.248796 6.000000 5.000000 MEG 2241 +2311 9.465158 -23.429756 6.000000 5.000000 MEG 2311 +2321 15.043037 -27.577251 6.000000 5.000000 MEG 2321 +2331 8.107240 -37.881119 6.000000 5.000000 MEG 2331 +2341 6.452683 -31.889233 6.000000 5.000000 MEG 2341 +2411 20.260805 -9.959167 6.000000 5.000000 MEG 2411 +2421 26.352144 -12.264672 6.000000 5.000000 MEG 2421 +2431 21.924099 -20.924681 6.000000 5.000000 MEG 2431 +2441 16.034241 -17.815463 6.000000 5.000000 MEG 2441 +2511 18.170528 -32.936850 6.000000 5.000000 MEG 2511 +2521 26.548311 -25.126150 6.000000 5.000000 MEG 2521 +2531 26.293430 -33.390539 6.000000 5.000000 MEG 2531 +2541 15.720093 -40.673553 6.000000 5.000000 MEG 2541 +2611 34.165833 -3.701116 6.000000 5.000000 MEG 2611 +2621 38.903042 -10.588621 6.000000 5.000000 MEG 2621 +2631 34.358242 -23.135988 6.000000 5.000000 MEG 2631 +2641 32.029198 -14.983262 6.000000 5.000000 MEG 2641 diff --git a/mne-python/source/mne/channels/data/layouts/biosemi.lay b/mne-python/source/mne/channels/data/layouts/biosemi.lay new file mode 100644 index 0000000000000000000000000000000000000000..ca748166aec9bbd72426ec6497da214db90d08c1 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/biosemi.lay @@ -0,0 +1,64 @@ +1 -0.496189 1.527114 0.290000 0.230000 Fp1 +2 -0.943808 1.299041 0.290000 0.230000 AF7 +3 -0.545830 1.170536 0.290000 0.230000 AF3 +4 -0.326906 0.809121 0.290000 0.230000 F1 +5 -0.659023 0.813825 0.290000 0.230000 F3 +6 -0.987913 0.858779 0.290000 0.230000 F5 +7 -1.299041 0.943808 0.290000 0.230000 F7 +8 -1.527114 0.496189 0.290000 0.230000 FT7 +9 -1.173172 0.450338 0.290000 0.230000 FC5 +10 -0.770517 0.409691 0.290000 0.230000 FC3 +11 -0.394923 0.394923 0.290000 0.230000 FC1 +12 -0.401426 -0.000000 0.290000 0.230000 C1 +13 -0.802851 -0.000000 0.290000 0.230000 C3 +14 -1.204277 -0.000000 0.290000 0.230000 C5 +15 -1.605703 -0.000000 0.290000 0.230000 T7 +16 -1.527114 -0.496189 0.290000 0.230000 TP7 +17 -1.173172 -0.450338 0.290000 0.230000 CP5 +18 -0.770517 -0.409691 0.290000 0.230000 CP3 +19 -0.394923 -0.394923 0.290000 0.230000 CP1 +20 -0.326906 -0.809121 0.290000 0.230000 P1 +21 -0.659023 -0.813825 0.290000 0.230000 P3 +22 -0.987913 -0.858779 0.290000 0.230000 P5 +23 -1.299041 -0.943808 0.290000 0.230000 P7 +24 -1.537550 -1.290157 0.290000 0.230000 P9 +25 -0.943808 -1.299041 0.290000 0.230000 PO7 +26 -0.545830 -1.170536 0.290000 0.230000 PO3 +27 -0.496189 -1.527114 0.290000 0.230000 O1 +28 0.000000 -2.007129 0.290000 0.230000 Iz +29 0.000000 -1.605703 0.290000 0.230000 Oz +30 0.000000 -1.204277 0.290000 0.230000 POz +31 0.000000 -0.802851 0.290000 0.230000 Pz +32 0.000000 -0.401426 0.290000 0.230000 CPz +33 0.000000 1.605703 0.290000 0.230000 Fpz +34 0.496189 1.527114 0.290000 0.230000 Fp2 +35 0.943808 1.299041 0.290000 0.230000 AF8 +36 0.545830 1.170536 0.290000 0.230000 AF4 +37 0.000000 1.204277 0.290000 0.230000 AFz +38 0.000000 0.802851 0.290000 0.230000 Fz +39 0.326906 0.809121 0.290000 0.230000 F2 +40 0.659023 0.813825 0.290000 0.230000 F4 +41 0.987913 0.858779 0.290000 0.230000 F6 +42 1.299041 0.943808 0.290000 0.230000 F8 +43 1.527114 0.496189 0.290000 0.230000 FT8 +44 1.173172 0.450338 0.290000 0.230000 FC6 +45 0.770517 0.409691 0.290000 0.230000 FC4 +46 0.394923 0.394923 0.290000 0.230000 FC2 +47 0.000000 0.401426 0.290000 0.230000 FCz +48 0.000000 0.000000 0.290000 0.230000 Cz +49 0.401426 0.000000 0.290000 0.230000 C2 +50 0.802851 0.000000 0.290000 0.230000 C4 +51 1.204277 0.000000 0.290000 0.230000 C6 +52 1.605703 0.000000 0.290000 0.230000 T8 +53 1.527114 -0.496189 0.290000 0.230000 TP8 +54 1.173172 -0.450338 0.290000 0.230000 CP6 +55 0.770517 -0.409691 0.290000 0.230000 CP4 +56 0.394923 -0.394923 0.290000 0.230000 CP2 +57 0.326906 -0.809121 0.290000 0.230000 P2 +58 0.659023 -0.813825 0.290000 0.230000 P4 +59 0.987913 -0.858779 0.290000 0.230000 P6 +60 1.299041 -0.943808 0.290000 0.230000 P8 +61 1.537550 -1.290157 0.290000 0.230000 P10 +62 0.943808 -1.299041 0.290000 0.230000 PO8 +63 0.545830 -1.170536 0.290000 0.230000 PO4 +64 0.496189 -1.527114 0.290000 0.230000 O2 \ No newline at end of file diff --git a/mne-python/source/mne/channels/data/layouts/magnesWH3600.lout b/mne-python/source/mne/channels/data/layouts/magnesWH3600.lout new file mode 100644 index 0000000000000000000000000000000000000000..577e9537986420cb55e6ae08ba2bebfb8c7f8d22 --- /dev/null +++ b/mne-python/source/mne/channels/data/layouts/magnesWH3600.lout @@ -0,0 +1,249 @@ + -42.19 43.52 -41.70 28.71 +001 -1.28 -5.13 4.00 3.00 MEG 001 +002 -1.22 -1.43 4.00 3.00 MEG 002 +003 -1.37 2.53 4.00 3.00 MEG 003 +004 -1.36 5.90 4.00 3.00 MEG 004 +005 -1.45 9.27 4.00 3.00 MEG 005 +006 -4.89 9.36 4.00 3.00 MEG 006 +007 -5.20 5.86 4.00 3.00 MEG 007 +008 -5.26 2.40 4.00 3.00 MEG 008 +009 -5.34 -1.29 4.00 3.00 MEG 009 +010 -5.12 -5.08 4.00 3.00 MEG 010 +011 -4.73 -8.47 4.00 3.00 MEG 011 +012 -1.31 -8.81 4.00 3.00 MEG 012 +013 2.04 -8.49 4.00 3.00 MEG 013 +014 2.54 -5.16 4.00 3.00 MEG 014 +015 2.69 -1.43 4.00 3.00 MEG 015 +016 2.62 2.56 4.00 3.00 MEG 016 +017 2.50 5.89 4.00 3.00 MEG 017 +018 2.10 9.34 4.00 3.00 MEG 018 +019 -1.45 12.55 4.00 3.00 MEG 019 +020 -5.76 12.42 4.00 3.00 MEG 020 +021 -8.30 9.98 4.00 3.00 MEG 021 +022 -9.16 5.97 4.00 3.00 MEG 022 +023 -9.32 2.49 4.00 3.00 MEG 023 +024 -9.42 -1.32 4.00 3.00 MEG 024 +025 -9.13 -5.11 4.00 3.00 MEG 025 +026 -8.43 -9.18 4.00 3.00 MEG 026 +027 -5.45 -12.10 4.00 3.00 MEG 027 +028 -1.40 -12.51 4.00 3.00 MEG 028 +029 2.64 -12.08 4.00 3.00 MEG 029 +030 5.77 -9.29 4.00 3.00 MEG 030 +031 6.50 -5.19 4.00 3.00 MEG 031 +032 6.85 -1.37 4.00 3.00 MEG 032 +033 6.70 2.65 4.00 3.00 MEG 033 +034 6.46 6.18 4.00 3.00 MEG 034 +035 5.61 10.08 4.00 3.00 MEG 035 +036 2.95 12.49 4.00 3.00 MEG 036 +037 -1.47 15.77 4.00 3.00 MEG 037 +038 -5.48 15.52 4.00 3.00 MEG 038 +039 -8.97 13.31 4.00 3.00 MEG 039 +040 -11.91 10.42 4.00 3.00 MEG 040 +041 -12.96 6.84 4.00 3.00 MEG 041 +042 -13.39 3.21 4.00 3.00 MEG 042 +043 -13.58 -0.70 4.00 3.00 MEG 043 +044 -13.08 -4.42 4.00 3.00 MEG 044 +045 -12.52 -8.05 4.00 3.00 MEG 045 +046 -11.13 -11.34 4.00 3.00 MEG 046 +047 -8.45 -14.21 4.00 3.00 MEG 047 +048 -5.08 -15.56 4.00 3.00 MEG 048 +049 -1.60 -16.17 4.00 3.00 MEG 049 +050 2.22 -15.61 4.00 3.00 MEG 050 +051 5.63 -14.28 4.00 3.00 MEG 051 +052 8.38 -11.70 4.00 3.00 MEG 052 +053 9.89 -8.24 4.00 3.00 MEG 053 +054 10.43 -4.42 4.00 3.00 MEG 054 +055 10.94 -0.62 4.00 3.00 MEG 055 +056 10.72 3.35 4.00 3.00 MEG 056 +057 10.22 7.01 4.00 3.00 MEG 057 +058 9.04 10.61 4.00 3.00 MEG 058 +059 6.20 13.42 4.00 3.00 MEG 059 +060 2.52 15.65 4.00 3.00 MEG 060 +061 -1.53 18.91 4.00 3.00 MEG 061 +062 -5.68 18.61 4.00 3.00 MEG 062 +063 -9.46 16.89 4.00 3.00 MEG 063 +064 -12.95 14.48 4.00 3.00 MEG 064 +065 -15.67 11.24 4.00 3.00 MEG 065 +066 -17.06 7.05 4.00 3.00 MEG 066 +067 -17.65 3.16 4.00 3.00 MEG 067 +068 -17.98 -1.20 4.00 3.00 MEG 068 +069 -17.13 -5.53 4.00 3.00 MEG 069 +070 -16.60 -9.33 4.00 3.00 MEG 070 +071 -14.32 -12.91 4.00 3.00 MEG 071 +072 -11.85 -15.75 4.00 3.00 MEG 072 +073 -8.78 -17.93 4.00 3.00 MEG 073 +074 -5.30 -19.40 4.00 3.00 MEG 074 +075 -1.58 -19.85 4.00 3.00 MEG 075 +076 2.41 -19.42 4.00 3.00 MEG 076 +077 5.94 -18.13 4.00 3.00 MEG 077 +078 9.16 -15.98 4.00 3.00 MEG 078 +079 11.79 -13.08 4.00 3.00 MEG 079 +080 13.62 -9.59 4.00 3.00 MEG 080 +081 14.57 -5.64 4.00 3.00 MEG 081 +082 15.42 -1.35 4.00 3.00 MEG 082 +083 15.05 3.30 4.00 3.00 MEG 083 +084 14.29 7.20 4.00 3.00 MEG 084 +085 12.81 11.43 4.00 3.00 MEG 085 +086 9.96 14.67 4.00 3.00 MEG 086 +087 6.46 17.06 4.00 3.00 MEG 087 +088 2.60 18.73 4.00 3.00 MEG 088 +089 -1.60 22.21 4.00 3.00 MEG 089 +090 -5.83 21.82 4.00 3.00 MEG 090 +091 -9.75 20.43 4.00 3.00 MEG 091 +092 -13.45 18.45 4.00 3.00 MEG 092 +093 -16.67 15.62 4.00 3.00 MEG 093 +094 -19.33 12.13 4.00 3.00 MEG 094 +095 -20.94 7.82 4.00 3.00 MEG 095 +096 -21.81 3.65 4.00 3.00 MEG 096 +097 -22.23 -1.27 4.00 3.00 MEG 097 +098 -21.14 -5.87 4.00 3.00 MEG 098 +099 -20.30 -9.97 4.00 3.00 MEG 099 +100 -18.46 -13.84 4.00 3.00 MEG 100 +101 -16.07 -17.08 4.00 3.00 MEG 101 +102 -12.88 -19.71 4.00 3.00 MEG 102 +103 -9.34 -21.89 4.00 3.00 MEG 103 +104 -5.64 -23.02 4.00 3.00 MEG 104 +105 -1.72 -23.54 4.00 3.00 MEG 105 +106 2.48 -23.24 4.00 3.00 MEG 106 +107 6.42 -22.00 4.00 3.00 MEG 107 +108 9.86 -20.19 4.00 3.00 MEG 108 +109 13.22 -17.32 4.00 3.00 MEG 109 +110 15.75 -14.15 4.00 3.00 MEG 110 +111 17.67 -10.19 4.00 3.00 MEG 111 +112 18.65 -6.08 4.00 3.00 MEG 112 +113 19.69 -1.27 4.00 3.00 MEG 113 +114 19.27 3.70 4.00 3.00 MEG 114 +115 18.30 8.05 4.00 3.00 MEG 115 +116 16.46 12.48 4.00 3.00 MEG 116 +117 13.74 15.93 4.00 3.00 MEG 117 +118 10.41 18.72 4.00 3.00 MEG 118 +119 6.64 20.69 4.00 3.00 MEG 119 +120 2.67 22.02 4.00 3.00 MEG 120 +121 -1.74 25.41 4.00 3.00 MEG 121 +122 -6.59 24.84 4.00 3.00 MEG 122 +123 -11.16 23.37 4.00 3.00 MEG 123 +124 -15.46 21.07 4.00 3.00 MEG 124 +125 -19.25 17.84 4.00 3.00 MEG 125 +126 -22.45 13.89 4.00 3.00 MEG 126 +127 -24.89 8.96 4.00 3.00 MEG 127 +128 -26.13 4.36 4.00 3.00 MEG 128 +129 -26.65 -1.22 4.00 3.00 MEG 129 +130 -25.30 -6.36 4.00 3.00 MEG 130 +131 -24.16 -11.45 4.00 3.00 MEG 131 +132 -21.98 -15.88 4.00 3.00 MEG 132 +133 -18.81 -19.82 4.00 3.00 MEG 133 +134 -15.20 -22.99 4.00 3.00 MEG 134 +135 -11.11 -25.29 4.00 3.00 MEG 135 +136 -6.51 -26.74 4.00 3.00 MEG 136 +137 -1.86 -27.28 4.00 3.00 MEG 137 +138 3.17 -26.90 4.00 3.00 MEG 138 +139 7.79 -25.55 4.00 3.00 MEG 139 +140 12.07 -23.15 4.00 3.00 MEG 140 +141 15.93 -20.09 4.00 3.00 MEG 141 +142 19.04 -16.25 4.00 3.00 MEG 142 +143 21.39 -11.67 4.00 3.00 MEG 143 +144 22.75 -6.58 4.00 3.00 MEG 144 +145 23.99 -1.23 4.00 3.00 MEG 145 +146 23.36 4.49 4.00 3.00 MEG 146 +147 22.02 9.37 4.00 3.00 MEG 147 +148 19.51 14.31 4.00 3.00 MEG 148 +149 16.20 18.23 4.00 3.00 MEG 149 +150 12.16 21.54 4.00 3.00 MEG 150 +151 7.85 23.69 4.00 3.00 MEG 151 +152 3.16 25.01 4.00 3.00 MEG 152 +153 -23.01 18.82 4.00 3.00 MEG 153 +154 -26.06 15.31 4.00 3.00 MEG 154 +155 -28.76 10.18 4.00 3.00 MEG 155 +156 -31.71 3.39 4.00 3.00 MEG 156 +157 -32.05 -2.89 4.00 3.00 MEG 157 +158 -31.42 -8.67 4.00 3.00 MEG 158 +159 -26.22 -15.24 4.00 3.00 MEG 159 +160 -23.31 -19.72 4.00 3.00 MEG 160 +161 -19.33 -23.66 4.00 3.00 MEG 161 +162 -14.75 -26.73 4.00 3.00 MEG 162 +163 -9.92 -28.91 4.00 3.00 MEG 163 +164 -4.52 -30.10 4.00 3.00 MEG 164 +165 1.25 -30.15 4.00 3.00 MEG 165 +166 6.17 -29.40 4.00 3.00 MEG 166 +167 11.43 -27.39 4.00 3.00 MEG 167 +168 16.20 -24.37 4.00 3.00 MEG 168 +169 20.37 -20.27 4.00 3.00 MEG 169 +170 23.54 -15.56 4.00 3.00 MEG 170 +171 28.66 -8.94 4.00 3.00 MEG 171 +172 29.46 -3.00 4.00 3.00 MEG 172 +173 29.04 3.51 4.00 3.00 MEG 173 +174 25.94 10.77 4.00 3.00 MEG 174 +175 23.08 15.80 4.00 3.00 MEG 175 +176 19.78 19.54 4.00 3.00 MEG 176 +177 -26.70 20.52 4.00 3.00 MEG 177 +178 -29.66 16.81 4.00 3.00 MEG 178 +179 -32.55 11.68 4.00 3.00 MEG 179 +180 -32.47 -13.23 4.00 3.00 MEG 180 +181 -27.63 -19.12 4.00 3.00 MEG 181 +182 -23.75 -23.89 4.00 3.00 MEG 182 +183 -18.94 -27.77 4.00 3.00 MEG 183 +184 -13.64 -30.59 4.00 3.00 MEG 184 +185 -7.93 -32.70 4.00 3.00 MEG 185 +186 -2.12 -33.31 4.00 3.00 MEG 186 +187 4.06 -32.74 4.00 3.00 MEG 187 +188 10.04 -31.14 4.00 3.00 MEG 188 +189 15.57 -28.41 4.00 3.00 MEG 189 +190 20.44 -24.69 4.00 3.00 MEG 190 +191 24.62 -19.81 4.00 3.00 MEG 191 +192 29.49 -13.87 4.00 3.00 MEG 192 +193 29.48 12.54 4.00 3.00 MEG 193 +194 26.49 17.54 4.00 3.00 MEG 194 +195 23.28 21.40 4.00 3.00 MEG 195 +196 -36.84 4.15 4.00 3.00 MEG 196 +197 -37.22 -3.16 4.00 3.00 MEG 197 +198 -36.14 -9.68 4.00 3.00 MEG 198 +199 -28.42 -23.63 4.00 3.00 MEG 199 +200 -23.68 -28.05 4.00 3.00 MEG 200 +201 -18.03 -31.89 4.00 3.00 MEG 201 +202 -11.97 -34.42 4.00 3.00 MEG 202 +203 -5.32 -35.88 4.00 3.00 MEG 203 +204 1.03 -36.08 4.00 3.00 MEG 204 +205 7.92 -35.00 4.00 3.00 MEG 205 +206 13.99 -32.64 4.00 3.00 MEG 206 +207 19.78 -29.06 4.00 3.00 MEG 207 +208 24.79 -24.52 4.00 3.00 MEG 208 +209 33.39 -10.13 4.00 3.00 MEG 209 +210 34.62 -3.11 4.00 3.00 MEG 210 +211 34.23 4.57 4.00 3.00 MEG 211 +212 -32.38 19.14 4.00 3.00 MEG 212 +213 -35.90 13.21 4.00 3.00 MEG 213 +214 -36.70 -14.70 4.00 3.00 MEG 214 +215 -32.93 -22.44 4.00 3.00 MEG 215 +216 -28.17 -28.07 4.00 3.00 MEG 216 +217 -22.65 -32.41 4.00 3.00 MEG 217 +218 -16.53 -35.71 4.00 3.00 MEG 218 +219 -9.52 -37.92 4.00 3.00 MEG 219 +220 -2.58 -38.82 4.00 3.00 MEG 220 +221 4.65 -38.54 4.00 3.00 MEG 221 +222 11.78 -36.65 4.00 3.00 MEG 222 +223 18.43 -33.60 4.00 3.00 MEG 223 +224 24.26 -29.21 4.00 3.00 MEG 224 +225 29.52 -23.44 4.00 3.00 MEG 225 +226 33.73 -15.36 4.00 3.00 MEG 226 +227 33.02 14.20 4.00 3.00 MEG 227 +228 29.24 19.93 4.00 3.00 MEG 228 +229 -36.80 18.24 4.00 3.00 MEG 229 +230 -40.03 12.76 4.00 3.00 MEG 230 +231 -41.35 5.03 4.00 3.00 MEG 231 +232 -41.79 -3.17 4.00 3.00 MEG 232 +233 -40.48 -10.59 4.00 3.00 MEG 233 +234 -32.92 -26.79 4.00 3.00 MEG 234 +235 -27.40 -32.12 4.00 3.00 MEG 235 +236 -20.92 -36.72 4.00 3.00 MEG 236 +237 -14.11 -39.49 4.00 3.00 MEG 237 +238 -6.76 -41.18 4.00 3.00 MEG 238 +239 1.45 -41.40 4.00 3.00 MEG 239 +240 8.96 -40.25 4.00 3.00 MEG 240 +241 16.27 -37.84 4.00 3.00 MEG 241 +242 22.75 -33.68 4.00 3.00 MEG 242 +243 29.08 -28.20 4.00 3.00 MEG 243 +244 37.59 -11.05 4.00 3.00 MEG 244 +245 39.12 -3.16 4.00 3.00 MEG 245 +246 38.59 5.47 4.00 3.00 MEG 246 +247 37.16 13.60 4.00 3.00 MEG 247 +248 33.62 18.93 4.00 3.00 MEG 248 diff --git a/mne-python/source/mne/channels/data/montages/EGI_256.csd b/mne-python/source/mne/channels/data/montages/EGI_256.csd new file mode 100644 index 0000000000000000000000000000000000000000..3da8637bff86dc14cb31a8f467c0586ef96dafcb --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/EGI_256.csd @@ -0,0 +1,258 @@ +// MatLab Sphere coordinates [degrees] Cartesian coordinates +// Label Theta Phi Radius X Y Z off sphere surface + E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011 + E2 44.600 -0.880 1.000 0.7119 0.7021 -0.0154 0.00000000000000000 + E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000 + E4 58.200 21.800 1.000 0.4893 0.7891 0.3714 -0.00000000000000011 + E5 64.200 33.600 1.000 0.3625 0.7499 0.5534 0.00000000000000000 + E6 70.800 45.500 1.000 0.2305 0.6619 0.7133 -0.00000000000000022 + E7 77.200 56.700 1.000 0.1216 0.5354 0.8358 0.00000000000000000 + E8 90.000 67.700 1.000 0.0000 0.3795 0.9252 0.00000000000000000 + E9 127.300 78.300 1.000 -0.1229 0.1613 0.9792 0.00000000000000000 + E10 51.200 -9.080 1.000 0.6188 0.7696 -0.1578 0.00000000000000000 + E11 58.800 2.370 1.000 0.5176 0.8546 0.0414 0.00000000000000000 + E12 66.800 14.300 1.000 0.3817 0.8907 0.2470 -0.00000000000000011 + E13 73.800 25.200 1.000 0.2524 0.8689 0.4258 0.00000000000000022 + E14 81.360 36.400 1.000 0.1209 0.7958 0.5934 0.00000000000000022 + E15 90.000 46.900 1.000 0.0000 0.6833 0.7302 0.00000000000000000 + E16 102.800 56.700 1.000 -0.1216 0.5354 0.8358 0.00000000000000000 + E17 128.200 66.600 1.000 -0.2456 0.3121 0.9178 -0.00000000000000011 + E18 66.600 -4.970 1.000 0.3957 0.9143 -0.0866 -0.00000000000000011 + E19 74.000 4.680 1.000 0.2747 0.9581 0.0816 -0.00000000000000011 + E20 81.960 15.700 1.000 0.1346 0.9532 0.2706 0.00000000000000022 + E21 90.000 26.400 1.000 0.0000 0.8957 0.4446 0.00000000000000000 + E22 98.640 36.400 1.000 -0.1209 0.7958 0.5934 0.00000000000000022 + E23 109.200 45.500 1.000 -0.2305 0.6619 0.7133 0.00000000000000000 + E24 127.200 54.200 1.000 -0.3537 0.4659 0.8111 0.00000000000000000 + E25 82.540 -3.260 1.000 0.1296 0.9899 -0.0569 0.00000000000000000 + E26 90.000 5.370 1.000 0.0000 0.9956 0.0936 0.00000000000000000 + E27 98.040 15.700 1.000 -0.1346 0.9532 0.2706 0.00000000000000022 + E28 106.200 25.200 1.000 -0.2524 0.8689 0.4258 0.00000000000000022 + E29 115.800 33.600 1.000 -0.3625 0.7499 0.5534 0.00000000000000000 + E30 128.800 41.200 1.000 -0.4715 0.5864 0.6587 0.00000000000000000 + E31 90.000 -11.000 1.000 0.0000 0.9816 -0.1908 0.00000000000000000 + E32 97.460 -3.260 1.000 -0.1296 0.9899 -0.0569 0.00000000000000000 + E33 106.000 4.680 1.000 -0.2747 0.9581 0.0816 -0.00000000000000011 + E34 113.200 14.300 1.000 -0.3817 0.8907 0.2470 -0.00000000000000022 + E35 121.800 21.800 1.000 -0.4893 0.7891 0.3714 -0.00000000000000011 + E36 128.500 30.200 1.000 -0.5380 0.6764 0.5030 0.00000000000000022 + E37 113.400 -4.970 1.000 -0.3957 0.9143 -0.0866 0.00000000000000000 + E38 121.200 2.370 1.000 -0.5176 0.8546 0.0414 0.00000000000000000 + E39 128.300 11.000 1.000 -0.6084 0.7704 0.1908 0.00000000000000000 + E40 135.300 20.800 1.000 -0.6645 0.6576 0.3551 0.00000000000000000 + E41 140.600 32.000 1.000 -0.6553 0.5383 0.5299 0.00000000000000000 + E42 144.500 44.000 1.000 -0.5856 0.4177 0.6947 0.00000000000000000 + E43 151.000 54.800 1.000 -0.5042 0.2795 0.8171 0.00000000000000000 + E44 163.200 66.400 1.000 -0.3833 0.1157 0.9164 0.00000000000000000 + E45 197.000 77.300 1.000 -0.2102 -0.0643 0.9755 0.00000000000000000 + E46 128.800 -9.080 1.000 -0.6188 0.7696 -0.1578 0.00000000000000000 + E47 135.400 -0.880 1.000 -0.7119 0.7021 -0.0154 -0.00000000000000011 + E48 142.500 8.460 1.000 -0.7847 0.6021 0.1471 0.00000000000000000 + E49 149.200 19.400 1.000 -0.8102 0.4830 0.3322 0.00000000000000000 + E50 155.300 32.200 1.000 -0.7688 0.3536 0.5329 0.00000000000000000 + E51 162.400 44.200 1.000 -0.6834 0.2168 0.6972 0.00000000000000000 + E52 173.500 54.500 1.000 -0.5770 0.0657 0.8141 0.00000000000000000 + E53 197.000 65.600 1.000 -0.3951 -0.1208 0.9107 0.00000000000000000 + E54 142.300 -14.000 1.000 -0.7677 0.5934 -0.2419 0.00000000000000000 + E55 149.100 -4.100 1.000 -0.8559 0.5122 -0.0715 0.00000000000000000 + E56 156.700 7.130 1.000 -0.9113 0.3925 0.1241 0.00000000000000022 + E57 163.200 19.500 1.000 -0.9024 0.2725 0.3338 0.00000000000000000 + E58 169.700 31.600 1.000 -0.8380 0.1523 0.5240 0.00000000000000000 + E59 179.500 43.000 1.000 -0.7313 0.0064 0.6820 0.00000000000000000 + E60 197.000 53.000 1.000 -0.5755 -0.1760 0.7986 0.00000000000000000 + E61 158.000 -17.200 1.000 -0.8857 0.3579 -0.2957 -0.00000000000000022 + E62 165.100 -5.730 1.000 -0.9615 0.2558 -0.0998 0.00000000000000022 + E63 171.400 6.890 1.000 -0.9816 0.1485 0.1200 0.00000000000000022 + E64 177.200 19.000 1.000 -0.9444 0.0462 0.3256 0.00000000000000000 + E65 184.300 31.100 1.000 -0.8539 -0.0642 0.5165 0.00000000000000000 + E66 196.000 39.900 1.000 -0.7374 -0.2115 0.6414 0.00000000000000000 + E67 167.300 -27.900 1.000 -0.8621 0.1943 -0.4679 0.00000000000000000 + E68 172.300 -17.500 1.000 -0.9451 0.1278 -0.3007 0.00000000000000000 + E69 179.500 -6.970 1.000 -0.9926 0.0087 -0.1213 0.00000000000000000 + E70 185.400 5.990 1.000 -0.9901 -0.0936 0.1044 0.00000000000000022 + E71 191.000 18.700 1.000 -0.9298 -0.1807 0.3206 0.00000000000000000 + E72 197.000 28.500 1.000 -0.8404 -0.2569 0.4772 0.00000000000000000 + E73 174.500 -38.200 1.000 -0.7822 0.0753 -0.6184 0.00000000000000022 + E74 193.000 -6.630 1.000 -0.9679 -0.2234 -0.1155 0.00000000000000000 + E75 199.000 7.590 1.000 -0.9372 -0.3227 0.1321 0.00000000000000000 + E76 205.000 19.800 1.000 -0.8527 -0.3976 0.3387 -0.00000000000000011 + E77 209.000 31.900 1.000 -0.7425 -0.4116 0.5284 0.00000000000000000 + E78 214.000 43.600 1.000 -0.6004 -0.4050 0.6896 0.00000000000000000 + E79 221.000 55.600 1.000 -0.4264 -0.3707 0.8251 -0.00000000000000011 + E80 233.000 67.400 1.000 -0.2313 -0.3069 0.9232 0.00000000000000000 + E81 -90.000 78.400 1.000 0.0000 -0.2011 0.9796 -0.00000000000000011 + E82 183.900 -45.800 1.000 -0.6956 -0.0474 -0.7169 0.00000000000000000 + E83 205.000 -15.000 1.000 -0.8754 -0.4082 -0.2588 0.00000000000000000 + E84 206.000 -3.510 1.000 -0.8971 -0.4375 -0.0612 -0.00000000000000022 + E85 213.000 10.000 1.000 -0.8259 -0.5364 0.1736 -0.00000000000000011 + E86 218.000 22.700 1.000 -0.7270 -0.5680 0.3859 0.00000000000000000 + E87 225.000 35.300 1.000 -0.5771 -0.5771 0.5779 0.00000000000000000 + E88 232.000 46.800 1.000 -0.4214 -0.5394 0.7290 -0.00000000000000011 + E89 245.000 56.900 1.000 -0.2308 -0.4949 0.8377 -0.00000000000000011 + E90 -90.000 67.500 1.000 0.0000 -0.3827 0.9239 0.00000000000000000 + E91 195.000 -50.900 1.000 -0.6092 -0.1632 -0.7760 0.00000000000000000 + E92 203.000 -42.700 1.000 -0.6765 -0.2872 -0.6782 -0.00000000000000022 + E93 211.000 -32.500 1.000 -0.7229 -0.4344 -0.5373 0.00000000000000000 + E94 212.000 -23.100 1.000 -0.7801 -0.4874 -0.3923 0.00000000000000000 + E95 216.000 -12.400 1.000 -0.7901 -0.5741 -0.2147 0.00000000000000000 + E96 221.000 0.666 1.000 -0.7547 -0.6560 0.0116 0.00000000000000000 + E97 228.000 12.900 1.000 -0.6522 -0.7244 0.2233 0.00000000000000022 + E98 233.000 24.900 1.000 -0.5459 -0.7244 0.4210 0.00000000000000000 + E99 241.000 36.400 1.000 -0.3902 -0.7040 0.5934 0.00000000000000000 + E100 251.000 46.900 1.000 -0.2225 -0.6460 0.7302 0.00000000000000000 + E101 -90.000 44.200 1.000 0.0000 -0.7169 0.6972 0.00000000000000000 + E102 211.000 -47.800 1.000 -0.5758 -0.3460 -0.7408 0.00000000000000000 + E103 217.000 -39.900 1.000 -0.6127 -0.4617 -0.6414 0.00000000000000000 + E104 223.000 -29.500 1.000 -0.6365 -0.5936 -0.4924 0.00000000000000000 + E105 224.000 -20.500 1.000 -0.6738 -0.6507 -0.3502 0.00000000000000000 + E106 228.000 -8.840 1.000 -0.6612 -0.7343 -0.1537 0.00000000000000022 + E107 235.000 2.900 1.000 -0.5728 -0.8181 0.0506 0.00000000000000000 + E108 242.000 14.600 1.000 -0.4543 -0.8544 0.2521 0.00000000000000000 + E109 248.000 25.700 1.000 -0.3375 -0.8355 0.4337 -0.00000000000000011 + E110 257.000 36.000 1.000 -0.1820 -0.7883 0.5878 0.00000000000000000 + E111 226.000 -43.800 1.000 -0.5014 -0.5192 -0.6921 0.00000000000000000 + E112 230.000 -36.300 1.000 -0.5180 -0.6174 -0.5920 0.00000000000000000 + E113 235.000 -25.900 1.000 -0.5160 -0.7369 -0.4368 -0.00000000000000022 + E114 235.000 -17.500 1.000 -0.5470 -0.7812 -0.3007 0.00000000000000000 + E115 244.000 -6.240 1.000 -0.4358 -0.8935 -0.1087 0.00000000000000000 + E116 251.000 4.850 1.000 -0.3244 -0.9421 0.0845 0.00000000000000000 + E117 258.000 15.500 1.000 -0.2004 -0.9426 0.2672 0.00000000000000000 + E118 263.000 25.200 1.000 -0.1103 -0.8981 0.4258 0.00000000000000000 + E119 -90.000 33.400 1.000 0.0000 -0.8348 0.5505 -0.00000000000000011 + E120 237.000 -41.100 1.000 -0.4104 -0.6320 -0.6574 0.00000000000000022 + E121 242.000 -33.400 1.000 -0.3919 -0.7371 -0.5505 -0.00000000000000022 + E122 247.000 -23.400 1.000 -0.3586 -0.8448 -0.3971 0.00000000000000000 + E123 252.000 -11.200 1.000 -0.3031 -0.9329 -0.1942 0.00000000000000000 + E124 257.000 -3.660 1.000 -0.2245 -0.9724 -0.0638 0.00000000000000022 + E125 264.000 5.580 1.000 -0.1040 -0.9898 0.0972 0.00000000000000000 + E126 -90.000 15.400 1.000 0.0000 -0.9641 0.2656 0.00000000000000000 + E127 -83.000 25.200 1.000 0.1103 -0.8981 0.4258 0.00000000000000000 + E128 -77.000 36.000 1.000 0.1820 -0.7883 0.5878 0.00000000000000000 + E129 -71.000 46.900 1.000 0.2225 -0.6460 0.7302 0.00000000000000000 + E130 -65.000 56.900 1.000 0.2308 -0.4949 0.8377 -0.00000000000000011 + E131 -53.000 67.400 1.000 0.2313 -0.3069 0.9232 0.00000000000000000 + E132 -17.000 77.300 1.000 0.2102 -0.0643 0.9755 0.00000000000000000 + E133 248.000 -36.400 1.000 -0.3015 -0.7463 -0.5934 0.00000000000000022 + E134 253.000 -30.700 1.000 -0.2514 -0.8223 -0.5105 -0.00000000000000011 + E135 258.000 -19.400 1.000 -0.1961 -0.9226 -0.3322 -0.00000000000000011 + E136 265.000 -12.900 1.000 -0.0850 -0.9711 -0.2233 0.00000000000000000 + E137 -90.000 -5.280 1.000 0.0000 -0.9958 -0.0920 0.00000000000000000 + E138 -84.000 5.580 1.000 0.1040 -0.9898 0.0972 -0.00000000000000022 + E139 -78.000 15.500 1.000 0.2004 -0.9426 0.2672 -0.00000000000000011 + E140 -68.000 25.700 1.000 0.3375 -0.8355 0.4337 -0.00000000000000011 + E141 -61.000 36.400 1.000 0.3902 -0.7040 0.5934 0.00000000000000000 + E142 -52.000 46.800 1.000 0.4214 -0.5394 0.7290 0.00000000000000000 + E143 -41.000 55.600 1.000 0.4264 -0.3707 0.8251 0.00000000000000000 + E144 -17.000 65.600 1.000 0.3951 -0.1208 0.9107 0.00000000000000000 + E145 258.000 -35.800 1.000 -0.1686 -0.7933 -0.5850 0.00000000000000000 + E146 264.000 -29.600 1.000 -0.0909 -0.8647 -0.4939 0.00000000000000000 + E147 -90.000 -22.100 1.000 0.0000 -0.9265 -0.3762 0.00000000000000000 + E148 -85.000 -12.900 1.000 0.0850 -0.9711 -0.2233 0.00000000000000000 + E149 -77.000 -3.660 1.000 0.2245 -0.9724 -0.0638 0.00000000000000022 + E150 -71.000 4.850 1.000 0.3244 -0.9421 0.0845 -0.00000000000000022 + E151 -62.000 14.600 1.000 0.4543 -0.8544 0.2521 0.00000000000000000 + E152 -53.000 24.900 1.000 0.5459 -0.7244 0.4210 0.00000000000000000 + E153 -45.000 35.300 1.000 0.5771 -0.5771 0.5779 0.00000000000000000 + E154 -34.000 43.600 1.000 0.6004 -0.4050 0.6896 0.00000000000000000 + E155 -17.000 53.000 1.000 0.5755 -0.1760 0.7986 0.00000000000000000 + E156 -84.000 -29.600 1.000 0.0909 -0.8647 -0.4939 -0.00000000000000011 + E157 -78.000 -19.400 1.000 0.1961 -0.9226 -0.3322 -0.00000000000000022 + E158 -72.000 -11.200 1.000 0.3031 -0.9329 -0.1942 0.00000000000000000 + E159 -64.000 -6.240 1.000 0.4358 -0.8935 -0.1087 0.00000000000000022 + E160 -55.000 2.900 1.000 0.5728 -0.8181 0.0506 0.00000000000000022 + E161 -48.000 12.900 1.000 0.6522 -0.7244 0.2233 0.00000000000000000 + E162 -38.000 22.700 1.000 0.7270 -0.5680 0.3859 0.00000000000000000 + E163 -29.000 31.900 1.000 0.7425 -0.4116 0.5284 0.00000000000000000 + E164 -16.000 39.900 1.000 0.7374 -0.2115 0.6414 0.00000000000000000 + E165 -78.000 -35.800 1.000 0.1686 -0.7933 -0.5850 0.00000000000000000 + E166 -73.000 -30.700 1.000 0.2514 -0.8223 -0.5105 0.00000000000000000 + E167 -67.000 -23.400 1.000 0.3586 -0.8448 -0.3971 0.00000000000000000 + E168 -55.000 -17.500 1.000 0.5470 -0.7812 -0.3007 0.00000000000000000 + E169 -48.000 -8.840 1.000 0.6612 -0.7343 -0.1537 0.00000000000000022 + E170 -41.000 0.666 1.000 0.7547 -0.6560 0.0116 0.00000000000000000 + E171 -33.000 10.000 1.000 0.8259 -0.5364 0.1736 -0.00000000000000011 + E172 -25.000 19.800 1.000 0.8527 -0.3976 0.3387 -0.00000000000000022 + E173 -17.000 28.500 1.000 0.8404 -0.2569 0.4772 0.00000000000000000 + E174 -68.000 -36.400 1.000 0.3015 -0.7463 -0.5934 0.00000000000000000 + E175 -62.000 -33.400 1.000 0.3919 -0.7371 -0.5505 -0.00000000000000011 + E176 -55.000 -25.900 1.000 0.5160 -0.7369 -0.4368 -0.00000000000000022 + E177 -44.000 -20.500 1.000 0.6738 -0.6507 -0.3502 0.00000000000000000 + E178 -36.000 -12.400 1.000 0.7901 -0.5741 -0.2147 0.00000000000000000 + E179 -26.000 -3.510 1.000 0.8971 -0.4375 -0.0612 -0.00000000000000011 + E180 -19.000 7.590 1.000 0.9372 -0.3227 0.1321 0.00000000000000022 + E181 -11.000 18.700 1.000 0.9298 -0.1807 0.3206 0.00000000000000022 + E182 -4.300 31.100 1.000 0.8539 -0.0642 0.5165 0.00000000000000000 + E183 0.500 43.000 1.000 0.7313 0.0064 0.6820 0.00000000000000000 + E184 6.500 54.500 1.000 0.5770 0.0657 0.8141 0.00000000000000000 + E185 16.800 66.400 1.000 0.3833 0.1157 0.9164 0.00000000000000000 + E186 52.700 78.300 1.000 0.1229 0.1613 0.9792 0.00000000000000000 + E187 -57.000 -41.100 1.000 0.4104 -0.6320 -0.6574 0.00000000000000022 + E188 -50.000 -36.300 1.000 0.5180 -0.6174 -0.5920 -0.00000000000000022 + E189 -43.000 -29.500 1.000 0.6365 -0.5936 -0.4924 0.00000000000000000 + E190 -32.000 -23.100 1.000 0.7801 -0.4874 -0.3923 0.00000000000000000 + E191 -25.000 -15.000 1.000 0.8754 -0.4082 -0.2588 0.00000000000000000 + E192 -13.000 -6.630 1.000 0.9679 -0.2234 -0.1155 0.00000000000000000 + E193 -5.400 5.990 1.000 0.9901 -0.0936 0.1044 0.00000000000000022 + E194 2.800 19.000 1.000 0.9444 0.0462 0.3256 0.00000000000000022 + E195 10.300 31.600 1.000 0.8380 0.1523 0.5240 0.00000000000000000 + E196 17.600 44.200 1.000 0.6834 0.2168 0.6972 0.00000000000000000 + E197 29.000 54.800 1.000 0.5042 0.2795 0.8171 0.00000000000000000 + E198 51.800 66.600 1.000 0.2456 0.3121 0.9178 0.00000000000000000 + E199 -46.000 -43.800 1.000 0.5014 -0.5192 -0.6921 0.00000000000000000 + E200 -37.000 -39.900 1.000 0.6127 -0.4617 -0.6414 0.00000000000000000 + E201 -31.000 -32.500 1.000 0.7229 -0.4344 -0.5373 0.00000000000000000 + E202 0.500 -6.970 1.000 0.9926 0.0087 -0.1213 0.00000000000000000 + E203 8.600 6.890 1.000 0.9816 0.1485 0.1200 0.00000000000000044 + E204 16.800 19.500 1.000 0.9024 0.2725 0.3338 0.00000000000000000 + E205 24.700 32.200 1.000 0.7688 0.3536 0.5329 0.00000000000000000 + E206 35.500 44.000 1.000 0.5856 0.4177 0.6947 0.00000000000000000 + E207 52.800 54.200 1.000 0.3537 0.4659 0.8111 0.00000000000000000 + E208 -31.000 -47.800 1.000 0.5758 -0.3460 -0.7408 0.00000000000000000 + E209 -23.000 -42.700 1.000 0.6765 -0.2872 -0.6782 0.00000000000000000 + E210 7.700 -17.500 1.000 0.9451 0.1278 -0.3007 0.00000000000000000 + E211 14.900 -5.730 1.000 0.9615 0.2558 -0.0998 -0.00000000000000011 + E212 23.300 7.130 1.000 0.9113 0.3925 0.1241 0.00000000000000022 + E213 30.800 19.400 1.000 0.8102 0.4830 0.3322 0.00000000000000000 + E214 39.400 32.000 1.000 0.6553 0.5383 0.5299 0.00000000000000000 + E215 51.200 41.200 1.000 0.4715 0.5864 0.6587 0.00000000000000000 + E216 -15.000 -50.900 1.000 0.6092 -0.1632 -0.7760 0.00000000000000000 + E217 -3.900 -45.800 1.000 0.6956 -0.0474 -0.7169 0.00000000000000000 + E218 5.500 -38.200 1.000 0.7822 0.0753 -0.6184 0.00000000000000022 + E219 12.700 -27.900 1.000 0.8621 0.1943 -0.4679 0.00000000000000000 + E220 22.000 -17.200 1.000 0.8857 0.3579 -0.2957 -0.00000000000000022 + E221 30.900 -4.100 1.000 0.8559 0.5122 -0.0715 0.00000000000000000 + E222 37.500 8.460 1.000 0.7847 0.6021 0.1471 0.00000000000000000 + E223 44.700 20.800 1.000 0.6645 0.6576 0.3551 0.00000000000000000 + E224 51.500 30.200 1.000 0.5380 0.6764 0.5030 0.00000000000000000 + E225 23.100 -28.000 1.000 0.8122 0.3464 -0.4695 0.00000000000000000 + E226 33.500 -28.800 1.000 0.7307 0.4837 -0.4818 0.00000000000000000 + E227 18.500 -38.200 1.000 0.7452 0.2494 -0.6184 0.00000000000000000 + E228 10.400 -46.300 1.000 0.6795 0.1247 -0.7230 0.00000000000000000 + E229 -1.200 -53.100 1.000 0.6003 -0.0126 -0.7997 0.00000000000000000 + E230 41.600 -32.900 1.000 0.6279 0.5574 -0.5432 0.00000000000000000 + E231 29.900 -39.600 1.000 0.6680 0.3841 -0.6374 0.00000000000000000 + E232 23.600 -46.600 1.000 0.6296 0.2751 -0.7266 0.00000000000000000 + E233 13.200 -53.300 1.000 0.5818 0.1365 -0.8018 0.00000000000000022 + E234 50.800 -35.100 1.000 0.5171 0.6340 -0.5750 -0.00000000000000011 + E235 40.300 -41.300 1.000 0.5730 0.4859 -0.6600 0.00000000000000022 + E236 34.400 -47.800 1.000 0.5542 0.3795 -0.7408 0.00000000000000000 + E237 26.900 -54.600 1.000 0.5166 0.2621 -0.8151 0.00000000000000000 + E238 60.300 -35.600 1.000 0.4029 0.7063 -0.5821 0.00000000000000022 + E239 47.800 -45.000 1.000 0.4750 0.5238 -0.7071 -0.00000000000000011 + E240 41.600 -50.500 1.000 0.4757 0.4223 -0.7716 0.00000000000000000 + E241 119.700 -35.600 1.000 -0.4029 0.7063 -0.5821 0.00000000000000000 + E242 132.200 -45.000 1.000 -0.4750 0.5238 -0.7071 -0.00000000000000011 + E243 138.400 -50.500 1.000 -0.4757 0.4223 -0.7716 0.00000000000000000 + E244 129.200 -35.100 1.000 -0.5171 0.6340 -0.5750 -0.00000000000000011 + E245 139.700 -41.300 1.000 -0.5730 0.4859 -0.6600 0.00000000000000000 + E246 145.600 -47.800 1.000 -0.5542 0.3795 -0.7408 -0.00000000000000011 + E247 153.100 -54.600 1.000 -0.5166 0.2621 -0.8151 0.00000000000000000 + E248 138.400 -32.900 1.000 -0.6279 0.5574 -0.5432 -0.00000000000000022 + E249 150.100 -39.600 1.000 -0.6680 0.3841 -0.6374 0.00000000000000000 + E250 156.400 -46.600 1.000 -0.6296 0.2751 -0.7266 -0.00000000000000011 + E251 166.800 -53.300 1.000 -0.5818 0.1365 -0.8018 0.00000000000000022 + E252 146.500 -28.800 1.000 -0.7307 0.4837 -0.4818 0.00000000000000000 + E253 156.900 -28.000 1.000 -0.8122 0.3464 -0.4695 0.00000000000000000 + E254 161.500 -38.200 1.000 -0.7452 0.2494 -0.6184 0.00000000000000000 + E255 169.600 -46.300 1.000 -0.6795 0.1247 -0.7230 0.00000000000000000 + E256 181.200 -53.100 1.000 -0.6003 -0.0126 -0.7997 0.00000000000000000 diff --git a/mne-python/source/mne/channels/data/montages/GSN-HydroCel-128.sfp b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-128.sfp new file mode 100644 index 0000000000000000000000000000000000000000..56c94f8f4a987536385bba60f86aeeaf435644a7 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-128.sfp @@ -0,0 +1,131 @@ +FidNz 0 9.071585155 -2.359754454 +FidT9 -6.711765 0.040402876 -3.251600355 +FidT10 6.711765 0.040402876 -3.251600355 +E1 5.787677636 5.520863216 -2.577468644 +E2 5.291804727 6.709097557 0.307434896 +E3 3.864122447 7.63424051 3.067770143 +E4 2.868837559 7.145708546 4.989564557 +E5 1.479340453 5.68662139 6.812878187 +E6 0 3.806770224 7.891304964 +E7 -1.223800252 1.558864431 8.44043914 +E8 4.221901505 7.998817387 -1.354789681 +E9 2.695405558 8.884820317 1.088308144 +E10 1.830882336 8.708839134 3.18709115 +E11 0 7.96264703 5.044718001 +E12 -1.479340453 5.68662139 6.812878187 +E13 -2.435870762 3.254307219 7.608766206 +E14 1.270447661 9.479016328 -0.947183306 +E15 0 9.087440894 1.333345013 +E16 0 9.076490798 3.105438474 +E17 0 9.271139705 -2.211516434 +E18 -1.830882336 8.708839134 3.18709115 +E19 -2.868837559 7.145708546 4.989564557 +E20 -3.825797111 5.121648995 5.942844877 +E21 -1.270447661 9.479016328 -0.947183306 +E22 -2.695405558 8.884820317 1.088308144 +E23 -3.864122447 7.63424051 3.067770143 +E24 -4.459387187 6.021159964 4.365321482 +E25 -4.221901505 7.998817387 -1.354789681 +E26 -5.291804727 6.709097557 0.307434896 +E27 -5.682547954 5.453384344 2.836565436 +E28 -5.546670402 4.157847823 4.627615703 +E29 -4.762196763 2.697832099 6.297663028 +E30 -3.695490968 0.960411022 7.627828134 +E31 -1.955187826 -0.684381878 8.564858511 +E32 -5.787677636 5.520863216 -2.577468644 +E33 -6.399087198 4.127248875 -0.356852241 +E34 -6.823959684 2.968422112 2.430080351 +E35 -6.414469893 1.490027747 4.741794544 +E36 -5.47913021 0.284948655 6.38332782 +E37 -3.909902609 -1.519049882 7.764134929 +E38 -6.550732888 3.611543152 -3.353155926 +E39 -7.191620108 0.850096251 -0.882936903 +E40 -7.391919265 0.032151584 2.143634599 +E41 -6.905051715 -0.800953972 4.600056501 +E42 -5.956055073 -2.338984312 6.00361353 +E43 -6.518995129 2.417299399 -5.253637073 +E44 -6.840717711 1.278489412 -3.5553823 +E45 -7.304625099 -1.866238006 -0.629182006 +E46 -7.312517928 -2.298574078 2.385298838 +E47 -6.737313764 -3.011819533 4.178390203 +E48 -5.934584124 2.22697797 -7.934360742 +E49 -6.298127313 0.41663451 -6.069156425 +E50 -6.78248072 -4.023512045 -0.232191092 +E51 -6.558030032 -4.667036048 2.749989597 +E52 -5.831241498 -4.494821698 4.955347697 +E53 -4.193518856 -4.037020083 6.982920038 +E54 -2.270752074 -3.414835627 8.204556551 +E55 0 -2.138343513 8.791875902 +E56 -6.174969392 -2.458138877 -5.637380998 +E57 -6.580438308 -3.739554155 -2.991084431 +E58 -6.034746843 -5.755782196 0.051843011 +E59 -5.204501802 -6.437833018 2.984444293 +E60 -4.116929504 -6.061561438 5.365757296 +E61 -2.344914884 -5.481057427 7.057748614 +E62 0 -6.676694032 6.465208258 +E63 -5.333266171 -4.302240169 -5.613509789 +E64 -5.404091392 -5.870302681 -2.891640039 +E65 -4.645302298 -7.280552408 0.130139701 +E66 -3.608293164 -7.665487704 3.129931648 +E67 -1.844644417 -7.354417376 5.224001733 +E68 -3.784983913 -6.401014415 -5.260040689 +E69 -3.528848027 -7.603010836 -2.818037873 +E70 -2.738838019 -8.607966849 0.239368223 +E71 -1.404967401 -8.437486994 3.277284901 +E72 0 -7.829896826 4.687622229 +E73 -1.929652202 -7.497197868 -5.136777648 +E74 -1.125731192 -8.455208629 -2.632832329 +E75 0 -8.996686498 0.487952047 +E76 1.404967401 -8.437486994 3.277284901 +E77 1.844644417 -7.354417376 5.224001733 +E78 2.344914884 -5.481057427 7.057748614 +E79 2.270752074 -3.414835627 8.204556551 +E80 1.955187826 -0.684381878 8.564858511 +E81 0 -7.85891896 -4.945387489 +E82 1.125731192 -8.455208629 -2.632832329 +E83 2.738838019 -8.607966849 0.239368223 +E84 3.608293164 -7.665487704 3.129931648 +E85 4.116929504 -6.061561438 5.365757296 +E86 4.193518856 -4.037020083 6.982920038 +E87 3.909902609 -1.519049882 7.764134929 +E88 1.929652202 -7.497197868 -5.136777648 +E89 3.528848027 -7.603010836 -2.818037873 +E90 4.645302298 -7.280552408 0.130139701 +E91 5.204501802 -6.437833018 2.984444293 +E92 5.831241498 -4.494821698 4.955347697 +E93 5.956055073 -2.338984312 6.00361353 +E94 3.784983913 -6.401014415 -5.260040689 +E95 5.404091392 -5.870302681 -2.891640039 +E96 6.034746843 -5.755782196 0.051843011 +E97 6.558030032 -4.667036048 2.749989597 +E98 6.737313764 -3.011819533 4.178390203 +E99 5.333266171 -4.302240169 -5.613509789 +E100 6.580438308 -3.739554155 -2.991084431 +E101 6.78248072 -4.023512045 -0.232191092 +E102 7.312517928 -2.298574078 2.385298838 +E103 6.905051715 -0.800953972 4.600056501 +E104 5.47913021 0.284948655 6.38332782 +E105 3.695490968 0.960411022 7.627828134 +E106 1.223800252 1.558864431 8.44043914 +E107 6.174969392 -2.458138877 -5.637380998 +E108 7.304625099 -1.866238006 -0.629182006 +E109 7.391919265 0.032151584 2.143634599 +E110 6.414469893 1.490027747 4.741794544 +E111 4.762196763 2.697832099 6.297663028 +E112 2.435870762 3.254307219 7.608766206 +E113 6.298127313 0.41663451 -6.069156425 +E114 6.840717711 1.278489412 -3.5553823 +E115 7.191620108 0.850096251 -0.882936903 +E116 6.823959684 2.968422112 2.430080351 +E117 5.546670402 4.157847823 4.627615703 +E118 3.825797111 5.121648995 5.942844877 +E119 5.934584124 2.22697797 -7.934360742 +E120 6.518995129 2.417299399 -5.253637073 +E121 6.550732888 3.611543152 -3.353155926 +E122 6.399087198 4.127248875 -0.356852241 +E123 5.682547954 5.453384344 2.836565436 +E124 4.459387187 6.021159964 4.365321482 +E125 6.118458137 4.523870113 -4.409174427 +E126 3.743504949 6.649204911 -6.530243068 +E127 -3.743504949 6.649204911 -6.530243068 +E128 -6.118458137 4.523870113 -4.409174427 diff --git a/mne-python/source/mne/channels/data/montages/GSN-HydroCel-129.sfp b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-129.sfp new file mode 100644 index 0000000000000000000000000000000000000000..fb222db909df440d3077166e332529d3e16de86d --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-129.sfp @@ -0,0 +1,132 @@ +FidNz 0 9.071585155 -2.359754454 +FidT9 -6.711765 0.040402876 -3.251600355 +FidT10 6.711765 0.040402876 -3.251600355 +E1 5.787677636 5.520863216 -2.577468644 +E2 5.291804727 6.709097557 0.307434896 +E3 3.864122447 7.63424051 3.067770143 +E4 2.868837559 7.145708546 4.989564557 +E5 1.479340453 5.68662139 6.812878187 +E6 0 3.806770224 7.891304964 +E7 -1.223800252 1.558864431 8.44043914 +E8 4.221901505 7.998817387 -1.354789681 +E9 2.695405558 8.884820317 1.088308144 +E10 1.830882336 8.708839134 3.18709115 +E11 0 7.96264703 5.044718001 +E12 -1.479340453 5.68662139 6.812878187 +E13 -2.435870762 3.254307219 7.608766206 +E14 1.270447661 9.479016328 -0.947183306 +E15 0 9.087440894 1.333345013 +E16 0 9.076490798 3.105438474 +E17 0 9.271139705 -2.211516434 +E18 -1.830882336 8.708839134 3.18709115 +E19 -2.868837559 7.145708546 4.989564557 +E20 -3.825797111 5.121648995 5.942844877 +E21 -1.270447661 9.479016328 -0.947183306 +E22 -2.695405558 8.884820317 1.088308144 +E23 -3.864122447 7.63424051 3.067770143 +E24 -4.459387187 6.021159964 4.365321482 +E25 -4.221901505 7.998817387 -1.354789681 +E26 -5.291804727 6.709097557 0.307434896 +E27 -5.682547954 5.453384344 2.836565436 +E28 -5.546670402 4.157847823 4.627615703 +E29 -4.762196763 2.697832099 6.297663028 +E30 -3.695490968 0.960411022 7.627828134 +E31 -1.955187826 -0.684381878 8.564858511 +E32 -5.787677636 5.520863216 -2.577468644 +E33 -6.399087198 4.127248875 -0.356852241 +E34 -6.823959684 2.968422112 2.430080351 +E35 -6.414469893 1.490027747 4.741794544 +E36 -5.47913021 0.284948655 6.38332782 +E37 -3.909902609 -1.519049882 7.764134929 +E38 -6.550732888 3.611543152 -3.353155926 +E39 -7.191620108 0.850096251 -0.882936903 +E40 -7.391919265 0.032151584 2.143634599 +E41 -6.905051715 -0.800953972 4.600056501 +E42 -5.956055073 -2.338984312 6.00361353 +E43 -6.518995129 2.417299399 -5.253637073 +E44 -6.840717711 1.278489412 -3.5553823 +E45 -7.304625099 -1.866238006 -0.629182006 +E46 -7.312517928 -2.298574078 2.385298838 +E47 -6.737313764 -3.011819533 4.178390203 +E48 -5.934584124 2.22697797 -7.934360742 +E49 -6.298127313 0.41663451 -6.069156425 +E50 -6.78248072 -4.023512045 -0.232191092 +E51 -6.558030032 -4.667036048 2.749989597 +E52 -5.831241498 -4.494821698 4.955347697 +E53 -4.193518856 -4.037020083 6.982920038 +E54 -2.270752074 -3.414835627 8.204556551 +E55 0 -2.138343513 8.791875902 +E56 -6.174969392 -2.458138877 -5.637380998 +E57 -6.580438308 -3.739554155 -2.991084431 +E58 -6.034746843 -5.755782196 0.051843011 +E59 -5.204501802 -6.437833018 2.984444293 +E60 -4.116929504 -6.061561438 5.365757296 +E61 -2.344914884 -5.481057427 7.057748614 +E62 0 -6.676694032 6.465208258 +E63 -5.333266171 -4.302240169 -5.613509789 +E64 -5.404091392 -5.870302681 -2.891640039 +E65 -4.645302298 -7.280552408 0.130139701 +E66 -3.608293164 -7.665487704 3.129931648 +E67 -1.844644417 -7.354417376 5.224001733 +E68 -3.784983913 -6.401014415 -5.260040689 +E69 -3.528848027 -7.603010836 -2.818037873 +E70 -2.738838019 -8.607966849 0.239368223 +E71 -1.404967401 -8.437486994 3.277284901 +E72 0 -7.829896826 4.687622229 +E73 -1.929652202 -7.497197868 -5.136777648 +E74 -1.125731192 -8.455208629 -2.632832329 +E75 0 -8.996686498 0.487952047 +E76 1.404967401 -8.437486994 3.277284901 +E77 1.844644417 -7.354417376 5.224001733 +E78 2.344914884 -5.481057427 7.057748614 +E79 2.270752074 -3.414835627 8.204556551 +E80 1.955187826 -0.684381878 8.564858511 +E81 0 -7.85891896 -4.945387489 +E82 1.125731192 -8.455208629 -2.632832329 +E83 2.738838019 -8.607966849 0.239368223 +E84 3.608293164 -7.665487704 3.129931648 +E85 4.116929504 -6.061561438 5.365757296 +E86 4.193518856 -4.037020083 6.982920038 +E87 3.909902609 -1.519049882 7.764134929 +E88 1.929652202 -7.497197868 -5.136777648 +E89 3.528848027 -7.603010836 -2.818037873 +E90 4.645302298 -7.280552408 0.130139701 +E91 5.204501802 -6.437833018 2.984444293 +E92 5.831241498 -4.494821698 4.955347697 +E93 5.956055073 -2.338984312 6.00361353 +E94 3.784983913 -6.401014415 -5.260040689 +E95 5.404091392 -5.870302681 -2.891640039 +E96 6.034746843 -5.755782196 0.051843011 +E97 6.558030032 -4.667036048 2.749989597 +E98 6.737313764 -3.011819533 4.178390203 +E99 5.333266171 -4.302240169 -5.613509789 +E100 6.580438308 -3.739554155 -2.991084431 +E101 6.78248072 -4.023512045 -0.232191092 +E102 7.312517928 -2.298574078 2.385298838 +E103 6.905051715 -0.800953972 4.600056501 +E104 5.47913021 0.284948655 6.38332782 +E105 3.695490968 0.960411022 7.627828134 +E106 1.223800252 1.558864431 8.44043914 +E107 6.174969392 -2.458138877 -5.637380998 +E108 7.304625099 -1.866238006 -0.629182006 +E109 7.391919265 0.032151584 2.143634599 +E110 6.414469893 1.490027747 4.741794544 +E111 4.762196763 2.697832099 6.297663028 +E112 2.435870762 3.254307219 7.608766206 +E113 6.298127313 0.41663451 -6.069156425 +E114 6.840717711 1.278489412 -3.5553823 +E115 7.191620108 0.850096251 -0.882936903 +E116 6.823959684 2.968422112 2.430080351 +E117 5.546670402 4.157847823 4.627615703 +E118 3.825797111 5.121648995 5.942844877 +E119 5.934584124 2.22697797 -7.934360742 +E120 6.518995129 2.417299399 -5.253637073 +E121 6.550732888 3.611543152 -3.353155926 +E122 6.399087198 4.127248875 -0.356852241 +E123 5.682547954 5.453384344 2.836565436 +E124 4.459387187 6.021159964 4.365321482 +E125 6.118458137 4.523870113 -4.409174427 +E126 3.743504949 6.649204911 -6.530243068 +E127 -3.743504949 6.649204911 -6.530243068 +E128 -6.118458137 4.523870113 -4.409174427 +Cz 0 0 8.899186843 diff --git a/mne-python/source/mne/channels/data/montages/GSN-HydroCel-256.sfp b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-256.sfp new file mode 100644 index 0000000000000000000000000000000000000000..2464e89a0c510aa6e9c67ae71b7c36fe7cf0bb71 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-256.sfp @@ -0,0 +1,259 @@ +FidNz 0.00000 10.56381 -2.05108 +FidT9 -7.82694 0.45386 -3.76056 +FidT10 7.82694 0.45386 -3.76056 +E1 6.96223 5.38242 -2.19061 +E2 6.48414 6.40424 -0.14004 +E3 5.69945 7.20796 1.79088 +E4 4.81093 7.77321 3.65006 +E5 3.61962 7.47782 5.50947 +E6 2.25278 6.46157 6.96317 +E7 1.18879 5.21755 8.13378 +E8 0.00000 3.59608 8.75111 +E9 -1.15339 1.51369 9.19904 +E10 5.94022 7.38337 -1.51513 +E11 5.07624 8.37264 0.40595 +E12 3.87946 9.03611 2.51559 +E13 2.60756 8.97868 4.39107 +E14 1.23344 8.11574 6.06161 +E15 0.00000 6.81181 7.28186 +E16 -1.18879 5.21755 8.13378 +E17 -2.29559 2.91372 8.55810 +E18 4.06489 9.40559 -0.89098 +E19 2.86784 10.01456 0.85212 +E20 1.42153 10.06322 2.84803 +E21 0.00000 9.40339 4.65829 +E22 -1.23344 8.11574 6.06161 +E23 -2.25278 6.46157 6.96317 +E24 -3.34467 4.40891 7.67253 +E25 1.39547 10.65281 -0.61138 +E26 0.00000 10.68996 1.00542 +E27 -1.42153 10.06322 2.84803 +E28 -2.60756 8.97868 4.39107 +E29 -3.61962 7.47782 5.50947 +E30 -4.49828 5.59395 6.28801 +E31 0.00000 10.56381 -2.05108 +E32 -1.39547 10.65281 -0.61138 +E33 -2.86784 10.01456 0.85212 +E34 -3.87946 9.03611 2.51559 +E35 -4.81093 7.77321 3.65006 +E36 -5.10466 6.41586 4.77815 +E37 -4.06489 9.40559 -0.89098 +E38 -5.07624 8.37264 0.40595 +E39 -5.69945 7.20796 1.79088 +E40 -6.16984 6.11292 3.29612 +E41 -6.01447 4.93908 4.85771 +E42 -5.33943 3.80220 6.32664 +E43 -4.64127 2.57224 7.50868 +E44 -3.53746 1.07133 8.47419 +E45 -1.99458 -0.60998 9.28870 +E46 -5.94022 7.38337 -1.51513 +E47 -6.48414 6.40424 -0.14004 +E48 -6.97545 5.35131 1.30741 +E49 -7.10064 4.23342 2.91874 +E50 -6.86564 3.16240 4.76800 +E51 -6.11380 1.94213 6.23844 +E52 -5.31389 0.60081 7.48811 +E53 -3.72368 -1.14573 8.58697 +E54 -6.96223 5.38242 -2.19061 +E55 -7.31613 4.37155 -0.61128 +E56 -7.66385 3.29619 1.04415 +E57 -7.62423 2.30205 2.81799 +E58 -7.36570 1.34368 4.60382 +E59 -6.70292 0.06004 6.23992 +E60 -5.40372 -1.61247 7.47343 +E61 -7.54098 3.05323 -2.51935 +E62 -7.77059 2.06323 -0.80729 +E63 -7.96921 1.20744 0.97332 +E64 -8.06621 0.40109 2.78565 +E65 -7.60767 -0.56840 4.59939 +E66 -6.81554 -1.94522 5.93053 +E67 -7.69315 1.74041 -4.18153 +E68 -7.74468 1.05291 -2.47059 +E69 -7.93758 0.07220 -0.96992 +E70 -7.98893 -0.75212 0.84194 +E71 -8.05947 -1.50296 2.76753 +E72 -7.56445 -2.31141 4.30327 +E73 -7.52646 0.73096 -5.96025 +E74 -7.76752 -1.84131 -0.92719 +E75 -7.79279 -2.73175 1.10033 +E76 -7.46191 -3.49308 2.95937 +E77 -6.86934 -3.79448 4.89401 +E78 -5.65276 -3.84604 6.52108 +E79 -4.12465 -3.54800 7.95405 +E80 -2.23647 -2.95809 8.92461 +E81 0.00000 -1.93834 9.45867 +E82 -7.12806 -0.49186 -7.34929 +E83 -7.37920 -3.49709 -2.18347 +E84 -7.52183 -3.70044 -0.51432 +E85 -7.15214 -4.71132 1.51762 +E86 -6.48817 -5.15829 3.47294 +E87 -5.53051 -5.46184 5.50189 +E88 -4.03809 -5.23807 7.04455 +E89 -2.29514 -4.87829 8.27223 +E90 0.00000 -3.74195 9.02791 +E91 -6.82585 -1.86426 -8.69399 +E92 -6.74047 -2.84840 -6.74712 +E93 -6.78379 -4.01784 -5.01755 +E94 -7.03346 -4.45090 -3.54895 +E95 -6.99052 -5.01694 -1.88810 +E96 -6.67571 -5.73608 0.10234 +E97 -5.96851 -6.52864 2.03293 +E98 -5.10822 -6.74936 3.92134 +E99 -3.75216 -6.67734 5.63719 +E100 -2.14874 -6.29190 7.11453 +E101 0.00000 -7.15042 6.95434 +E102 -6.36989 -3.82470 -8.20622 +E103 -6.24349 -4.62250 -6.49623 +E104 -6.09726 -5.61090 -4.67894 +E105 -6.31441 -6.01299 -3.25921 +E106 -5.98418 -6.74733 -1.40314 +E107 -5.23709 -7.57398 0.46627 +E108 -4.29098 -8.11323 2.38442 +E109 -3.24277 -8.15293 4.22025 +E110 -1.73181 -7.63850 5.69360 +E111 -5.63580 -5.80367 -7.74857 +E112 -5.38718 -6.45180 -6.16689 +E113 -5.08285 -7.32643 -4.32109 +E114 -5.27282 -7.46584 -2.87485 +E115 -4.13620 -8.61230 -1.04503 +E116 -3.13323 -9.13629 0.81878 +E117 -1.94503 -9.23415 2.62135 +E118 -1.09312 -8.74110 4.13810 +E119 0.00000 -8.09146 5.34087 +E120 -4.70608 -7.21970 -7.52955 +E121 -4.20415 -7.81153 -5.84368 +E122 -3.62234 -8.59338 -4.04243 +E123 -3.02717 -9.45363 -1.95941 +E124 -2.20152 -9.70916 -0.63755 +E125 -1.01682 -9.71656 0.95467 +E126 0.00000 -9.23206 2.54671 +E127 1.09312 -8.74110 4.13810 +E128 1.73181 -7.63850 5.69360 +E129 2.14874 -6.29190 7.11453 +E130 2.29514 -4.87829 8.27223 +E131 2.23647 -2.95809 8.92461 +E132 1.99458 -0.60998 9.28870 +E133 -3.45625 -8.57317 -6.82654 +E134 -2.71528 -8.94646 -5.55376 +E135 -2.03205 -9.56166 -3.44989 +E136 -0.91885 -9.62744 -2.21054 +E137 0.00000 -9.58535 -0.88629 +E138 1.01682 -9.71656 0.95467 +E139 1.94503 -9.23415 2.62135 +E140 3.24277 -8.15293 4.22025 +E141 3.75216 -6.67734 5.63719 +E142 4.03809 -5.23807 7.04455 +E143 4.12465 -3.54800 7.95405 +E144 3.72368 -1.14573 8.58697 +E145 -1.88533 -9.22031 -6.79889 +E146 -1.06111 -9.53369 -5.45325 +E147 0.00000 -9.48329 -3.84204 +E148 0.91885 -9.62744 -2.21054 +E149 2.20152 -9.70916 -0.63755 +E150 3.13323 -9.13629 0.81878 +E151 4.29098 -8.11323 2.38442 +E152 5.10822 -6.74936 3.92134 +E153 5.53051 -5.46184 5.50189 +E154 5.65276 -3.84604 6.52108 +E155 5.40372 -1.61247 7.47343 +E156 1.06111 -9.53369 -5.45325 +E157 2.03205 -9.56166 -3.44989 +E158 3.02717 -9.45363 -1.95941 +E159 4.13620 -8.61230 -1.04503 +E160 5.23709 -7.57398 0.46627 +E161 5.96851 -6.52864 2.03293 +E162 6.48817 -5.15829 3.47294 +E163 6.86934 -3.79448 4.89401 +E164 6.81554 -1.94522 5.93053 +E165 1.88533 -9.22031 -6.79889 +E166 2.71528 -8.94646 -5.55376 +E167 3.62234 -8.59338 -4.04243 +E168 5.27282 -7.46584 -2.87485 +E169 5.98418 -6.74733 -1.40314 +E170 6.67571 -5.73608 0.10234 +E171 7.15214 -4.71132 1.51762 +E172 7.46191 -3.49308 2.95937 +E173 7.56445 -2.31141 4.30327 +E174 3.45625 -8.57317 -6.82654 +E175 4.20415 -7.81153 -5.84368 +E176 5.08285 -7.32643 -4.32109 +E177 6.31441 -6.01299 -3.25921 +E178 6.99052 -5.01694 -1.88810 +E179 7.52183 -3.70044 -0.51432 +E180 7.79279 -2.73175 1.10033 +E181 8.05947 -1.50296 2.76753 +E182 7.60767 -0.56840 4.59939 +E183 6.70292 0.06004 6.23992 +E184 5.31389 0.60081 7.48811 +E185 3.53746 1.07133 8.47419 +E186 1.15339 1.51369 9.19904 +E187 4.70608 -7.21970 -7.52955 +E188 5.38718 -6.45180 -6.16689 +E189 6.09726 -5.61090 -4.67894 +E190 7.03346 -4.45090 -3.54895 +E191 7.37920 -3.49709 -2.18347 +E192 7.76752 -1.84131 -0.92719 +E193 7.98893 -0.75212 0.84194 +E194 8.06621 0.40109 2.78565 +E195 7.36570 1.34368 4.60382 +E196 6.11380 1.94213 6.23844 +E197 4.64127 2.57224 7.50868 +E198 2.29559 2.91372 8.55810 +E199 5.63580 -5.80367 -7.74857 +E200 6.24349 -4.62250 -6.49623 +E201 6.78379 -4.01784 -5.01755 +E202 7.93758 0.07220 -0.96992 +E203 7.96921 1.20744 0.97332 +E204 7.62423 2.30205 2.81799 +E205 6.86564 3.16240 4.76800 +E206 5.33943 3.80220 6.32664 +E207 3.34467 4.40891 7.67253 +E208 6.36989 -3.82470 -8.20622 +E209 6.74047 -2.84840 -6.74712 +E210 7.74468 1.05291 -2.47059 +E211 7.77059 2.06323 -0.80729 +E212 7.66385 3.29619 1.04415 +E213 7.10064 4.23342 2.91874 +E214 6.01447 4.93908 4.85771 +E215 4.49828 5.59395 6.28801 +E216 6.82585 -1.86426 -8.69399 +E217 7.12806 -0.49186 -7.34929 +E218 7.52646 0.73096 -5.96025 +E219 7.69315 1.74041 -4.18153 +E220 7.54098 3.05323 -2.51935 +E221 7.31613 4.37155 -0.61128 +E222 6.97545 5.35131 1.30741 +E223 6.16984 6.11292 3.29612 +E224 5.10466 6.41586 4.77815 +E225 7.62652 3.24782 -4.40493 +E226 7.24346 4.80120 -4.77214 +E227 7.55603 2.52648 -6.26962 +E228 7.38028 1.35743 -7.84943 +E229 6.86103 -0.14155 -9.14913 +E230 6.74159 5.99080 -5.83258 +E231 7.22458 4.14855 -6.88918 +E232 7.31422 3.19647 -8.44268 +E233 7.09051 1.66694 -9.77213 +E234 5.88750 7.22674 -6.54736 +E235 6.65934 5.64059 -7.65729 +E236 6.75138 4.62427 -9.03070 +E237 6.58044 3.33743 -10.39707 +E238 4.69146 8.22723 -6.78260 +E239 5.81346 6.42065 -8.65026 +E240 6.04363 5.37051 -9.81363 +E241 -4.69146 8.22723 -6.78260 +E242 -5.81346 6.42065 -8.65026 +E243 -6.04363 5.37051 -9.81363 +E244 -5.88750 7.22674 -6.54736 +E245 -6.65934 5.64059 -7.65729 +E246 -6.75138 4.62427 -9.03070 +E247 -6.58044 3.33743 -10.39707 +E248 -6.74159 5.99080 -5.83258 +E249 -7.22458 4.14855 -6.88918 +E250 -7.31422 3.19647 -8.44268 +E251 -7.09051 1.66694 -9.77213 +E252 -7.24346 4.80120 -4.77214 +E253 -7.62652 3.24782 -4.40493 +E254 -7.55603 2.52648 -6.26962 +E255 -7.38028 1.35743 -7.84943 +E256 -6.86103 -0.14155 -9.14913 diff --git a/mne-python/source/mne/channels/data/montages/GSN-HydroCel-257.sfp b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-257.sfp new file mode 100644 index 0000000000000000000000000000000000000000..98c6b1adf68f820593fdc05bced165dd536a364e --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-257.sfp @@ -0,0 +1,260 @@ +FidNz 0.00000 10.56381 -2.05108 +FidT9 -7.82694 0.45386 -3.76056 +FidT10 7.82694 0.45386 -3.76056 +E1 6.96223 5.38242 -2.19061 +E2 6.48414 6.40424 -0.14004 +E3 5.69945 7.20796 1.79088 +E4 4.81093 7.77321 3.65006 +E5 3.61962 7.47782 5.50947 +E6 2.25278 6.46157 6.96317 +E7 1.18879 5.21755 8.13378 +E8 0.00000 3.59608 8.75111 +E9 -1.15339 1.51369 9.19904 +E10 5.94022 7.38337 -1.51513 +E11 5.07624 8.37264 0.40595 +E12 3.87946 9.03611 2.51559 +E13 2.60756 8.97868 4.39107 +E14 1.23344 8.11574 6.06161 +E15 0.00000 6.81181 7.28186 +E16 -1.18879 5.21755 8.13378 +E17 -2.29559 2.91372 8.55810 +E18 4.06489 9.40559 -0.89098 +E19 2.86784 10.01456 0.85212 +E20 1.42153 10.06322 2.84803 +E21 0.00000 9.40339 4.65829 +E22 -1.23344 8.11574 6.06161 +E23 -2.25278 6.46157 6.96317 +E24 -3.34467 4.40891 7.67253 +E25 1.39547 10.65281 -0.61138 +E26 0.00000 10.68996 1.00542 +E27 -1.42153 10.06322 2.84803 +E28 -2.60756 8.97868 4.39107 +E29 -3.61962 7.47782 5.50947 +E30 -4.49828 5.59395 6.28801 +E31 0.00000 10.56381 -2.05108 +E32 -1.39547 10.65281 -0.61138 +E33 -2.86784 10.01456 0.85212 +E34 -3.87946 9.03611 2.51559 +E35 -4.81093 7.77321 3.65006 +E36 -5.10466 6.41586 4.77815 +E37 -4.06489 9.40559 -0.89098 +E38 -5.07624 8.37264 0.40595 +E39 -5.69945 7.20796 1.79088 +E40 -6.16984 6.11292 3.29612 +E41 -6.01447 4.93908 4.85771 +E42 -5.33943 3.80220 6.32664 +E43 -4.64127 2.57224 7.50868 +E44 -3.53746 1.07133 8.47419 +E45 -1.99458 -0.60998 9.28870 +E46 -5.94022 7.38337 -1.51513 +E47 -6.48414 6.40424 -0.14004 +E48 -6.97545 5.35131 1.30741 +E49 -7.10064 4.23342 2.91874 +E50 -6.86564 3.16240 4.76800 +E51 -6.11380 1.94213 6.23844 +E52 -5.31389 0.60081 7.48811 +E53 -3.72368 -1.14573 8.58697 +E54 -6.96223 5.38242 -2.19061 +E55 -7.31613 4.37155 -0.61128 +E56 -7.66385 3.29619 1.04415 +E57 -7.62423 2.30205 2.81799 +E58 -7.36570 1.34368 4.60382 +E59 -6.70292 0.06004 6.23992 +E60 -5.40372 -1.61247 7.47343 +E61 -7.54098 3.05323 -2.51935 +E62 -7.77059 2.06323 -0.80729 +E63 -7.96921 1.20744 0.97332 +E64 -8.06621 0.40109 2.78565 +E65 -7.60767 -0.56840 4.59939 +E66 -6.81554 -1.94522 5.93053 +E67 -7.69315 1.74041 -4.18153 +E68 -7.74468 1.05291 -2.47059 +E69 -7.93758 0.07220 -0.96992 +E70 -7.98893 -0.75212 0.84194 +E71 -8.05947 -1.50296 2.76753 +E72 -7.56445 -2.31141 4.30327 +E73 -7.52646 0.73096 -5.96025 +E74 -7.76752 -1.84131 -0.92719 +E75 -7.79279 -2.73175 1.10033 +E76 -7.46191 -3.49308 2.95937 +E77 -6.86934 -3.79448 4.89401 +E78 -5.65276 -3.84604 6.52108 +E79 -4.12465 -3.54800 7.95405 +E80 -2.23647 -2.95809 8.92461 +E81 0.00000 -1.93834 9.45867 +E82 -7.12806 -0.49186 -7.34929 +E83 -7.37920 -3.49709 -2.18347 +E84 -7.52183 -3.70044 -0.51432 +E85 -7.15214 -4.71132 1.51762 +E86 -6.48817 -5.15829 3.47294 +E87 -5.53051 -5.46184 5.50189 +E88 -4.03809 -5.23807 7.04455 +E89 -2.29514 -4.87829 8.27223 +E90 0.00000 -3.74195 9.02791 +E91 -6.82585 -1.86426 -8.69399 +E92 -6.74047 -2.84840 -6.74712 +E93 -6.78379 -4.01784 -5.01755 +E94 -7.03346 -4.45090 -3.54895 +E95 -6.99052 -5.01694 -1.88810 +E96 -6.67571 -5.73608 0.10234 +E97 -5.96851 -6.52864 2.03293 +E98 -5.10822 -6.74936 3.92134 +E99 -3.75216 -6.67734 5.63719 +E100 -2.14874 -6.29190 7.11453 +E101 0.00000 -7.15042 6.95434 +E102 -6.36989 -3.82470 -8.20622 +E103 -6.24349 -4.62250 -6.49623 +E104 -6.09726 -5.61090 -4.67894 +E105 -6.31441 -6.01299 -3.25921 +E106 -5.98418 -6.74733 -1.40314 +E107 -5.23709 -7.57398 0.46627 +E108 -4.29098 -8.11323 2.38442 +E109 -3.24277 -8.15293 4.22025 +E110 -1.73181 -7.63850 5.69360 +E111 -5.63580 -5.80367 -7.74857 +E112 -5.38718 -6.45180 -6.16689 +E113 -5.08285 -7.32643 -4.32109 +E114 -5.27282 -7.46584 -2.87485 +E115 -4.13620 -8.61230 -1.04503 +E116 -3.13323 -9.13629 0.81878 +E117 -1.94503 -9.23415 2.62135 +E118 -1.09312 -8.74110 4.13810 +E119 0.00000 -8.09146 5.34087 +E120 -4.70608 -7.21970 -7.52955 +E121 -4.20415 -7.81153 -5.84368 +E122 -3.62234 -8.59338 -4.04243 +E123 -3.02717 -9.45363 -1.95941 +E124 -2.20152 -9.70916 -0.63755 +E125 -1.01682 -9.71656 0.95467 +E126 0.00000 -9.23206 2.54671 +E127 1.09312 -8.74110 4.13810 +E128 1.73181 -7.63850 5.69360 +E129 2.14874 -6.29190 7.11453 +E130 2.29514 -4.87829 8.27223 +E131 2.23647 -2.95809 8.92461 +E132 1.99458 -0.60998 9.28870 +E133 -3.45625 -8.57317 -6.82654 +E134 -2.71528 -8.94646 -5.55376 +E135 -2.03205 -9.56166 -3.44989 +E136 -0.91885 -9.62744 -2.21054 +E137 0.00000 -9.58535 -0.88629 +E138 1.01682 -9.71656 0.95467 +E139 1.94503 -9.23415 2.62135 +E140 3.24277 -8.15293 4.22025 +E141 3.75216 -6.67734 5.63719 +E142 4.03809 -5.23807 7.04455 +E143 4.12465 -3.54800 7.95405 +E144 3.72368 -1.14573 8.58697 +E145 -1.88533 -9.22031 -6.79889 +E146 -1.06111 -9.53369 -5.45325 +E147 0.00000 -9.48329 -3.84204 +E148 0.91885 -9.62744 -2.21054 +E149 2.20152 -9.70916 -0.63755 +E150 3.13323 -9.13629 0.81878 +E151 4.29098 -8.11323 2.38442 +E152 5.10822 -6.74936 3.92134 +E153 5.53051 -5.46184 5.50189 +E154 5.65276 -3.84604 6.52108 +E155 5.40372 -1.61247 7.47343 +E156 1.06111 -9.53369 -5.45325 +E157 2.03205 -9.56166 -3.44989 +E158 3.02717 -9.45363 -1.95941 +E159 4.13620 -8.61230 -1.04503 +E160 5.23709 -7.57398 0.46627 +E161 5.96851 -6.52864 2.03293 +E162 6.48817 -5.15829 3.47294 +E163 6.86934 -3.79448 4.89401 +E164 6.81554 -1.94522 5.93053 +E165 1.88533 -9.22031 -6.79889 +E166 2.71528 -8.94646 -5.55376 +E167 3.62234 -8.59338 -4.04243 +E168 5.27282 -7.46584 -2.87485 +E169 5.98418 -6.74733 -1.40314 +E170 6.67571 -5.73608 0.10234 +E171 7.15214 -4.71132 1.51762 +E172 7.46191 -3.49308 2.95937 +E173 7.56445 -2.31141 4.30327 +E174 3.45625 -8.57317 -6.82654 +E175 4.20415 -7.81153 -5.84368 +E176 5.08285 -7.32643 -4.32109 +E177 6.31441 -6.01299 -3.25921 +E178 6.99052 -5.01694 -1.88810 +E179 7.52183 -3.70044 -0.51432 +E180 7.79279 -2.73175 1.10033 +E181 8.05947 -1.50296 2.76753 +E182 7.60767 -0.56840 4.59939 +E183 6.70292 0.06004 6.23992 +E184 5.31389 0.60081 7.48811 +E185 3.53746 1.07133 8.47419 +E186 1.15339 1.51369 9.19904 +E187 4.70608 -7.21970 -7.52955 +E188 5.38718 -6.45180 -6.16689 +E189 6.09726 -5.61090 -4.67894 +E190 7.03346 -4.45090 -3.54895 +E191 7.37920 -3.49709 -2.18347 +E192 7.76752 -1.84131 -0.92719 +E193 7.98893 -0.75212 0.84194 +E194 8.06621 0.40109 2.78565 +E195 7.36570 1.34368 4.60382 +E196 6.11380 1.94213 6.23844 +E197 4.64127 2.57224 7.50868 +E198 2.29559 2.91372 8.55810 +E199 5.63580 -5.80367 -7.74857 +E200 6.24349 -4.62250 -6.49623 +E201 6.78379 -4.01784 -5.01755 +E202 7.93758 0.07220 -0.96992 +E203 7.96921 1.20744 0.97332 +E204 7.62423 2.30205 2.81799 +E205 6.86564 3.16240 4.76800 +E206 5.33943 3.80220 6.32664 +E207 3.34467 4.40891 7.67253 +E208 6.36989 -3.82470 -8.20622 +E209 6.74047 -2.84840 -6.74712 +E210 7.74468 1.05291 -2.47059 +E211 7.77059 2.06323 -0.80729 +E212 7.66385 3.29619 1.04415 +E213 7.10064 4.23342 2.91874 +E214 6.01447 4.93908 4.85771 +E215 4.49828 5.59395 6.28801 +E216 6.82585 -1.86426 -8.69399 +E217 7.12806 -0.49186 -7.34929 +E218 7.52646 0.73096 -5.96025 +E219 7.69315 1.74041 -4.18153 +E220 7.54098 3.05323 -2.51935 +E221 7.31613 4.37155 -0.61128 +E222 6.97545 5.35131 1.30741 +E223 6.16984 6.11292 3.29612 +E224 5.10466 6.41586 4.77815 +E225 7.62652 3.24782 -4.40493 +E226 7.24346 4.80120 -4.77214 +E227 7.55603 2.52648 -6.26962 +E228 7.38028 1.35743 -7.84943 +E229 6.86103 -0.14155 -9.14913 +E230 6.74159 5.99080 -5.83258 +E231 7.22458 4.14855 -6.88918 +E232 7.31422 3.19647 -8.44268 +E233 7.09051 1.66694 -9.77213 +E234 5.88750 7.22674 -6.54736 +E235 6.65934 5.64059 -7.65729 +E236 6.75138 4.62427 -9.03070 +E237 6.58044 3.33743 -10.39707 +E238 4.69146 8.22723 -6.78260 +E239 5.81346 6.42065 -8.65026 +E240 6.04363 5.37051 -9.81363 +E241 -4.69146 8.22723 -6.78260 +E242 -5.81346 6.42065 -8.65026 +E243 -6.04363 5.37051 -9.81363 +E244 -5.88750 7.22674 -6.54736 +E245 -6.65934 5.64059 -7.65729 +E246 -6.75138 4.62427 -9.03070 +E247 -6.58044 3.33743 -10.39707 +E248 -6.74159 5.99080 -5.83258 +E249 -7.22458 4.14855 -6.88918 +E250 -7.31422 3.19647 -8.44268 +E251 -7.09051 1.66694 -9.77213 +E252 -7.24346 4.80120 -4.77214 +E253 -7.62652 3.24782 -4.40493 +E254 -7.55603 2.52648 -6.26962 +E255 -7.38028 1.35743 -7.84943 +E256 -6.86103 -0.14155 -9.14913 +Cz 0.00000 0.00000 9.68308 diff --git a/mne-python/source/mne/channels/data/montages/GSN-HydroCel-32.sfp b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-32.sfp new file mode 100644 index 0000000000000000000000000000000000000000..214fb1b63e2ad7ea55e8e98f0aa9105fe186ae4d --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-32.sfp @@ -0,0 +1,36 @@ +FidNz 0 9.071585155 -2.359754454 +FidT9 -6.711765 0.040402876 -3.251600355 +FidT10 6.711765 0.040402876 -3.251600355 +E1 -2.695405558 8.884820317 1.088308144 +E2 2.695405558 8.884820317 1.088308144 +E3 -4.459387187 6.021159964 4.365321482 +E4 4.459387187 6.021159964 4.365321482 +E5 -5.47913021 0.284948655 6.38332782 +E6 5.47913021 0.284948655 6.38332782 +E7 -5.831241498 -4.494821698 4.955347697 +E8 5.831241498 -4.494821698 4.955347697 +E9 -2.738838019 -8.607966849 0.239368223 +E10 2.738838019 -8.607966849 0.239368223 +E11 -6.399087198 4.127248875 -0.356852241 +E12 6.399087198 4.127248875 -0.356852241 +E13 -7.304625099 -1.866238006 -0.629182006 +E14 7.304625099 -1.866238006 -0.629182006 +E15 -6.034746843 -5.755782196 0.051843011 +E16 6.034746843 -5.755782196 0.051843011 +E17 0 7.96264703 5.044718001 +E18 0 9.271139705 -2.211516434 +E19 0 -6.676694032 6.465208258 +E20 0 -8.996686498 0.487952047 +E21 -6.518995129 2.417299399 -5.253637073 +E22 6.518995129 2.417299399 -5.253637073 +E23 -6.174969392 -2.458138877 -5.637380998 +E24 6.174969392 -2.458138877 -5.637380998 +E25 -3.784983913 -6.401014415 -5.260040689 +E26 3.784983913 -6.401014415 -5.260040689 +E27 0 9.087440894 1.333345013 +E28 0 3.806770224 7.891304964 +E29 -3.743504949 6.649204911 -6.530243068 +E30 3.743504949 6.649204911 -6.530243068 +E31 -6.118458137 4.523870113 -4.409174427 +E32 6.118458137 4.523870113 -4.409174427 +Cz 0 0 8.899186843 diff --git a/mne-python/source/mne/channels/data/montages/GSN-HydroCel-64_1.0.sfp b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-64_1.0.sfp new file mode 100644 index 0000000000000000000000000000000000000000..004dcb02ca4cffa3462df4d873becb9e32219c62 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-64_1.0.sfp @@ -0,0 +1,67 @@ +FidNz 0.00000 10.3556 -2.69376 +FidT9 -7.18083 0.0461216 -3.71184 +FidT10 6.24270 0.0461216 -3.71184 +E1 6.60688 6.30230 -2.94229 +E2 4.41106 8.71481 3.50199 +E3 3.27490 8.15713 5.69580 +E4 0.00000 4.34559 9.00826 +E5 3.07692 10.1424 1.24235 +E6 0.00000 9.08970 5.75876 +E7 -2.78065 3.71493 8.68573 +E8 0.00000 10.3612 3.54499 +E9 -3.2749 8.15713 5.6958 +E10 -3.07692 10.1424 1.24235 +E11 -4.41106 8.71481 3.50199 +E12 -5.09058 6.87341 4.98320 +E13 -6.48687 6.22527 3.23806 +E14 -6.33176 4.74636 5.28262 +E15 -5.43625 3.07969 7.18905 +E16 -4.21856 1.09635 8.70749 +E17 -6.60688 6.30230 -2.94229 +E18 -7.30483 4.71143 -0.407362 +E19 -7.78984 3.38858 2.77404 +E20 -6.25466 0.325281 7.28684 +E21 -4.46332 -1.73406 8.86309 +E22 -7.88241 -0.914323 5.25116 +E23 -7.80897 1.45945 -4.05862 +E24 -8.33854 -2.13039 -0.718238 +E25 -8.34755 -2.62392 2.72292 +E26 -7.69093 -3.43812 4.76981 +E27 -7.48627 -5.32762 3.13923 +E28 -6.65661 -5.13103 5.65674 +E29 -7.51185 -4.26886 -3.41445 +E30 -6.88892 -6.57047 0.0591810 +E31 -4.69965 -6.91953 6.12524 +E32 -6.16900 -6.70120 -3.30093 +E33 -2.10574 -8.39538 5.96342 +E34 0.00000 -4.98271 9.28085 +E35 -3.12650 -9.82636 0.273249 +E36 0.00000 -8.93816 5.35112 +E37 0.00000 -10.2701 0.557018 +E38 2.10574 -8.39538 5.96342 +E39 3.12650 -9.82636 0.273249 +E40 4.69965 -6.91953 6.12524 +E41 4.46332 -1.73406 8.86309 +E42 6.65661 -5.13103 5.65674 +E43 6.16900 -6.70120 -3.30093 +E44 6.88892 -6.57047 0.0591810 +E45 7.48627 -5.32762 3.13923 +E46 7.69093 -3.43812 4.76981 +E47 7.51185 -4.26886 -3.41445 +E48 8.34755 -2.62392 2.72292 +E49 7.88241 -0.914323 5.25116 +E50 6.25466 0.325281 7.28684 +E51 4.21856 1.09635 8.70749 +E52 8.33854 -2.13039 -0.718238 +E53 5.43625 3.07969 7.18905 +E54 2.78065 3.71493 8.68573 +E55 7.80897 1.45945 -4.05862 +E56 7.78984 3.38858 2.77404 +E57 6.33176 4.74636 5.28262 +E58 7.30483 4.71143 -0.407362 +E59 6.48687 6.22527 3.23806 +E60 5.09058 6.87341 4.98320 +E61 6.98448 5.16419 -5.03326 +E62 4.27337 7.59035 -7.45455 +E63 -4.27337 7.59035 -7.45455 +E64 -6.98448 5.16419 -5.03326 diff --git a/mne-python/source/mne/channels/data/montages/GSN-HydroCel-65_1.0.sfp b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-65_1.0.sfp new file mode 100644 index 0000000000000000000000000000000000000000..c1c455dd03081d807f2b9d5bc5f2d7615ca9960d --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/GSN-HydroCel-65_1.0.sfp @@ -0,0 +1,68 @@ +FidNz 0.00000 10.3556 -2.69376 +FidT9 -7.18083 0.0461216 -3.71184 +FidT10 6.24270 0.0461216 -3.71184 +E1 6.60688 6.30230 -2.94229 +E2 4.41106 8.71481 3.50199 +E3 3.27490 8.15713 5.69580 +E4 0.00000 4.34559 9.00826 +E5 3.07692 10.1424 1.24235 +E6 0.00000 9.08970 5.75876 +E7 -2.78065 3.71493 8.68573 +E8 0.00000 10.3612 3.54499 +E9 -3.2749 8.15713 5.6958 +E10 -3.07692 10.1424 1.24235 +E11 -4.41106 8.71481 3.50199 +E12 -5.09058 6.87341 4.98320 +E13 -6.48687 6.22527 3.23806 +E14 -6.33176 4.74636 5.28262 +E15 -5.43625 3.07969 7.18905 +E16 -4.21856 1.09635 8.70749 +E17 -6.60688 6.30230 -2.94229 +E18 -7.30483 4.71143 -0.407362 +E19 -7.78984 3.38858 2.77404 +E20 -6.25466 0.325281 7.28684 +E21 -4.46332 -1.73406 8.86309 +E22 -7.88241 -0.914323 5.25116 +E23 -7.80897 1.45945 -4.05862 +E24 -8.33854 -2.13039 -0.718238 +E25 -8.34755 -2.62392 2.72292 +E26 -7.69093 -3.43812 4.76981 +E27 -7.48627 -5.32762 3.13923 +E28 -6.65661 -5.13103 5.65674 +E29 -7.51185 -4.26886 -3.41445 +E30 -6.88892 -6.57047 0.0591810 +E31 -4.69965 -6.91953 6.12524 +E32 -6.16900 -6.70120 -3.30093 +E33 -2.10574 -8.39538 5.96342 +E34 0.00000 -4.98271 9.28085 +E35 -3.12650 -9.82636 0.273249 +E36 0.00000 -8.93816 5.35112 +E37 0.00000 -10.2701 0.557018 +E38 2.10574 -8.39538 5.96342 +E39 3.12650 -9.82636 0.273249 +E40 4.69965 -6.91953 6.12524 +E41 4.46332 -1.73406 8.86309 +E42 6.65661 -5.13103 5.65674 +E43 6.16900 -6.70120 -3.30093 +E44 6.88892 -6.57047 0.0591810 +E45 7.48627 -5.32762 3.13923 +E46 7.69093 -3.43812 4.76981 +E47 7.51185 -4.26886 -3.41445 +E48 8.34755 -2.62392 2.72292 +E49 7.88241 -0.914323 5.25116 +E50 6.25466 0.325281 7.28684 +E51 4.21856 1.09635 8.70749 +E52 8.33854 -2.13039 -0.718238 +E53 5.43625 3.07969 7.18905 +E54 2.78065 3.71493 8.68573 +E55 7.80897 1.45945 -4.05862 +E56 7.78984 3.38858 2.77404 +E57 6.33176 4.74636 5.28262 +E58 7.30483 4.71143 -0.407362 +E59 6.48687 6.22527 3.23806 +E60 5.09058 6.87341 4.98320 +E61 6.98448 5.16419 -5.03326 +E62 4.27337 7.59035 -7.45455 +E63 -4.27337 7.59035 -7.45455 +E64 -6.98448 5.16419 -5.03326 +Cz 0.00000 0.00000 10.1588 diff --git a/mne-python/source/mne/channels/data/montages/artinis-brite23.elc b/mne-python/source/mne/channels/data/montages/artinis-brite23.elc new file mode 100644 index 0000000000000000000000000000000000000000..1e14b0a0a2b145c2efaf9fde661fbb1acc991e78 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/artinis-brite23.elc @@ -0,0 +1,48 @@ +# ASA optode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 21 +Positions +-4.62 82.33 -45.74 +79.66 -18.72 -45.89 +-81.41 -17.18 -45.56 +65.18 27.28 35.31 +48.62 59.71 22.68 +18.95 72.41 38.32 +-3.97 79.74 30.28 +-25.96 72.19 35.16 +-52.51 60.53 14.54 +-66.37 32.04 31.08 +76.10 -0.29 31.24 +65.61 -0.26 56.15 +64.93 42.43 8.29 +43.32 46.36 50.77 +21.58 82.45 1.06 +-2.91 59.57 61.59 +-29.62 79.35 2.38 +-48.13 44.76 49.15 +-67.68 43.26 -3.18 +-65.37 4.89 56.36 +-77.24 5.88 27.58 +Labels +Nz +RPA +LPA +D1 +D2 +D3 +D4 +D5 +D6 +D7 +S1 +S2 +S3 +S4 +S5 +S6 +S7 +S8 +S9 +S10 +S11 diff --git a/mne-python/source/mne/channels/data/montages/artinis-octamon.elc b/mne-python/source/mne/channels/data/montages/artinis-octamon.elc new file mode 100644 index 0000000000000000000000000000000000000000..748a19d04e11a796f6b7363d49a88bb853c645c9 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/artinis-octamon.elc @@ -0,0 +1,32 @@ +# ASA optode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 13 +Positions +0.96 83.56 -48.63 +80.25 -19.67 -43.88 +-82.58 -20.09 -43.10 +47.77 65.28 7.28 +-46.45 67.76 8.81 +63.88 34.84 28.34 +64.96 45.02 -10.31 +22.07 74.86 31.03 +17.84 84.96 -10.84 +-10.81 77.96 32.10 +-15.96 85.24 -7.41 +-61.78 40.78 29.92 +-65.28 48.14 -10.73 +Labels +Nz +RPA +LPA +D1 +D2 +S1 +S2 +S3 +S4 +S5 +S6 +S7 +S8 diff --git a/mne-python/source/mne/channels/data/montages/biosemi128.txt b/mne-python/source/mne/channels/data/montages/biosemi128.txt new file mode 100644 index 0000000000000000000000000000000000000000..69739c6fc838f4ffbaa5ced812e7ca2730586f70 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/biosemi128.txt @@ -0,0 +1,132 @@ +Site Theta Phi +A1 0 0 +A2 11.5 -90 +A3 23 -90 +A4 34.5 -90 +A5 -46 67.5 +A6 -46 45 +A7 -57.5 45 +A8 -69 54 +A9 -80.5 54 +A10 -92 54 +A11 -103.5 54 +A12 -115 54 +A13 -115 72 +A14 -103.5 72 +A15 -92 72 +A16 -80.5 72 +A17 -69 72 +A18 -57.5 67.5 +A19 46 -90 +A20 57.5 -90 +A21 69 -90 +A22 80.5 -90 +A23 92 -90 +A24 103.5 -90 +A25 115 -90 +A26 115 -72 +A27 103.5 -72 +A28 92 -72 +A29 80.5 -72 +A30 69 -72 +A31 57.5 -67.5 +A32 46 -67.5 +B1 11.5 -18 +B2 23 -45 +B3 46 -45 +B4 57.5 -45 +B5 69 -54 +B6 80.5 -54 +B7 92 -54 +B8 103.5 -54 +B9 115 -54 +B10 103.5 -36 +B11 92 -36 +B12 80.5 -36 +B13 69 -36 +B14 92 -18 +B15 80.5 -18 +B16 69 -18 +B17 57.5 -22.5 +B18 46 -22.5 +B19 34.5 -30 +B20 23 0 +B21 34.5 0 +B22 46 0 +B23 57.5 0 +B24 69 0 +B25 80.5 0 +B26 92 0 +B27 92 18 +B28 80.5 18 +B29 69 18 +B30 57.5 22.5 +B31 46 22.5 +B32 34.5 30 +C1 11.5 54 +C2 23 45 +C3 46 45 +C4 57.5 45 +C5 69 36 +C6 80.5 36 +C7 92 36 +C8 92 54 +C9 80.5 54 +C10 69 54 +C11 34.5 60 +C12 46 67.5 +C13 57.5 67.5 +C14 69 72 +C15 80.5 72 +C16 92 72 +C17 92 90 +C18 80.5 90 +C19 69 90 +C20 57.5 90 +C21 46 90 +C22 34.5 90 +C23 23 90 +C24 -34.5 -60 +C25 -46 -67.5 +C26 -57.5 -67.5 +C27 -69 -72 +C28 -80.5 -72 +C29 -92 -72 +C30 -92 -54 +C31 -80.5 -54 +C32 -69 -54 +D1 -11.5 -54 +D2 -23 -45 +D3 -46 -45 +D4 -57.5 -45 +D5 -69 -36 +D6 -80.5 -36 +D7 -92 -36 +D8 -92 -18 +D9 -80.5 -18 +D10 -69 -18 +D11 -57.5 -22.5 +D12 -46 -22.5 +D13 -34.5 -30 +D14 -23 0 +D15 -11.5 18 +D16 -23 45 +D17 -34.5 30 +D18 -34.5 0 +D19 -46 0 +D20 -57.5 0 +D21 -69 0 +D22 -80.5 0 +D23 -92 0 +D24 -92 18 +D25 -80.5 18 +D26 -69 18 +D27 -57.5 22.5 +D28 -46 22.5 +D29 -69 36 +D30 -80.5 36 +D31 -92 36 +D32 -103.5 36 +Nz 115 90 +LPA -115 0 +RPA 115 0 diff --git a/mne-python/source/mne/channels/data/montages/biosemi16.txt b/mne-python/source/mne/channels/data/montages/biosemi16.txt new file mode 100644 index 0000000000000000000000000000000000000000..d8a67690a7777c23dcb5975297560b9ce614c25a --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/biosemi16.txt @@ -0,0 +1,20 @@ +Site Theta Phi +Fp1 -92 -72 +Fp2 92 72 +F4 60 51 +Fz 46 90 +F3 -60 -51 +T7 -92 0 +C3 -46 0 +Cz 0 0 +C4 46 0 +T8 92 0 +P4 60 -51 +Pz 46 -90 +P3 -60 51 +O1 -92 72 +Oz 92 -90 +O2 92 -72 +Nz 115 90 +LPA -115 0 +RPA 115 0 diff --git a/mne-python/source/mne/channels/data/montages/biosemi160.txt b/mne-python/source/mne/channels/data/montages/biosemi160.txt new file mode 100644 index 0000000000000000000000000000000000000000..04fefc7513527359d898bb0cdd2f89a91f374d0f --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/biosemi160.txt @@ -0,0 +1,164 @@ +Site Theta Phi +A1 0 0 +A2 11.5 -90 +A3 23 -90 +A4 34.5 -90 +A5 -46 72 +A6 -46 54 +A7 -57.5 54 +A8 -69 60 +A9 -80.5 60 +A10 -92 60 +A11 -103.5 60 +A12 -115 60 +A13 -115 75 +A14 -103.5 75 +A15 -92 75 +A16 -80.5 75 +A17 -69 75 +A18 -57.5 72 +A19 46 -90 +A20 57.5 -90 +A21 69 -90 +A22 80.5 -90 +A23 92 -90 +A24 103.5 -90 +A25 115 -90 +A26 115 -75 +A27 103.5 -75 +A28 92 -75 +A29 80.5 -75 +A30 69 -75 +A31 57.5 -72 +A32 46 -72 +B1 11.5 -18 +B2 23 -60 +B3 46 -54 +B4 57.5 -54 +B5 69 -60 +B6 80.5 -60 +B7 92 -60 +B8 103.5 -60 +B9 115 -60 +B10 115 -45 +B11 103.5 -45 +B12 92 -45 +B13 80.5 -45 +B14 69 -45 +B15 69 -30 +B16 80.5 -30 +B17 92 -30 +B18 103.5 -30 +B19 92 -15 +B20 80.5 -15 +B21 69 -15 +B22 57.5 -36 +B23 46 -36 +B24 34.5 -45 +B25 23 -30 +B26 34.5 -22.5 +B27 46 -18 +B28 57.5 -18 +B29 57.5 0 +B30 69 0 +B31 80.5 0 +B32 92 0 +C1 11.5 54 +C2 23 30 +C3 23 0 +C4 34.5 0 +C5 34.5 22.5 +C6 46 18 +C7 46 0 +C8 57.5 18 +C9 69 15 +C10 80.5 15 +C11 92 15 +C12 92 30 +C13 80.5 30 +C14 69 30 +C15 69 45 +C16 80.5 45 +C17 92 45 +C18 92 60 +C19 80.5 60 +C20 69 60 +C21 57.5 54 +C22 57.5 36 +C23 46 36 +C24 34.5 45 +C25 23 60 +C26 34.5 67.5 +C27 46 54 +C28 46 72 +C29 57.5 72 +C30 69 75 +C31 80.5 75 +C32 92 75 +D1 -11.5 -54 +D2 23 90 +D3 34.5 90 +D4 46 90 +D5 57.5 90 +D6 69 90 +D7 80.5 90 +D8 92 90 +D9 -92 -75 +D10 -80.5 -75 +D11 -69 -75 +D12 -57.5 -72 +D13 -46 -72 +D14 -34.5 -67.5 +D15 -23 -60 +D16 -23 -30 +D17 -34.5 -45 +D18 -46 -54 +D19 -57.5 -54 +D20 -69 -60 +D21 -80.5 -60 +D22 -92 -60 +D23 -92 -45 +D24 -80.5 -45 +D25 -69 -45 +D26 -57.5 -36 +D27 -46 -36 +D28 -34.5 -22.5 +D29 -46 -18 +D30 -69 -30 +D31 -80.5 -30 +D32 -92 -30 +E1 -11.5 18 +E2 -23 0 +E3 -34.5 0 +E4 -46 0 +E5 -57.5 -18 +E6 -69 -15 +E7 -80.5 -15 +E8 -92 -15 +E9 -92 0 +E10 -80.5 0 +E11 -69 0 +E12 -57.5 0 +E13 -57.5 18 +E14 -69 15 +E15 -80.5 15 +E16 -92 15 +E17 -103.5 30 +E18 -92 30 +E19 -80.5 30 +E20 -69 30 +E21 -46 18 +E22 -34.5 22.5 +E23 -23 30 +E24 -23 60 +E25 -34.5 45 +E26 -46 36 +E27 -57.5 36 +E28 -69 45 +E29 -80.5 45 +E30 -92 45 +E31 -103.5 45 +E32 -115 45 +Nz 115 90 +LPA -115 0 +RPA 115 0 diff --git a/mne-python/source/mne/channels/data/montages/biosemi256.txt b/mne-python/source/mne/channels/data/montages/biosemi256.txt new file mode 100644 index 0000000000000000000000000000000000000000..50085a20dc20d1aaeb33b71e3b37db23bdf2ccaf --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/biosemi256.txt @@ -0,0 +1,260 @@ +Site Theta Phi +A1 0 0 +A2 9.2 -90 +A3 18.4 -90 +A4 27.6 -90 +A5 36.8 -90 +A6 46 -90 +A7 -46 75 +A8 -55.2 75 +A9 -64.4 78 +A10 -73.6 78 +A11 -82.8 78.75 +A12 -92 78.75 +A13 -101.2 78.75 +A14 -110.4 78 +A15 -119.6 78 +A16 119.6 -90 +A17 110.4 -90 +A18 101.2 -90 +A19 92 -90 +A20 82.8 -90 +A21 73.6 -90 +A22 64.4 -90 +A23 55.2 -90 +A24 46 -75 +A25 55.2 -75 +A26 64.4 -78 +A27 73.6 -78 +A28 82.8 -78.75 +A29 92 -78.75 +A30 101.2 -78.75 +A31 110.4 -78 +A32 119.6 -78 +B1 18.4 -54 +B2 27.6 -66 +B3 36.8 -54 +B4 46 -60 +B5 55.2 -60 +B6 64.4 -66 +B7 73.6 -66 +B8 82.8 -67.5 +B9 92 -67.5 +B10 101.2 -67.5 +B11 110.4 -66 +B12 119.6 -66 +B13 110.4 -54 +B14 101.2 -56.25 +B15 92 -56.25 +B16 82.8 -56.25 +B17 73.6 -54 +B18 64.4 -54 +B19 55.2 -45 +B20 46 -45 +B21 27.6 -42 +B22 36.8 -36 +B23 46 -30 +B24 55.2 -30 +B25 64.4 -42 +B26 73.6 -42 +B27 82.8 -45 +B28 92 -45 +B29 101.2 -45 +B30 110.4 -42 +B31 110.4 -30 +B32 101.2 -33.75 +C1 9.2 -18 +C2 18.4 -18 +C3 27.6 -18 +C4 36.8 -18 +C5 46 -15 +C6 55.2 -15 +C7 64.4 -18 +C8 64.4 -30 +C9 73.6 -30 +C10 82.8 -33.75 +C11 92 -33.75 +C12 101.2 -22.5 +C13 92 -22.5 +C14 82.8 -22.5 +C15 73.6 -18 +C16 82.8 -11.25 +C17 92 -11.25 +C18 92 0 +C19 82.8 0 +C20 73.6 -6 +C21 64.4 -6 +C22 55.2 0 +C23 46 0 +C24 36.8 0 +C25 27.6 6 +C26 36.8 18 +C27 46 15 +C28 55.2 15 +C29 64.4 6 +C30 73.6 6 +C31 82.8 11.25 +C32 92 11.25 +D1 9.2 54 +D2 18.4 18 +D3 27.6 30 +D4 36.8 36 +D5 46 30 +D6 64.4 18 +D7 73.6 18 +D8 82.8 22.5 +D9 92 22.5 +D10 101.2 22.5 +D11 101.2 33.75 +D12 92 33.75 +D13 82.8 33.75 +D14 73.6 30 +D15 64.4 30 +D16 55.2 30 +D17 46 45 +D18 55.2 45 +D19 64.4 42 +D20 73.6 42 +D21 82.8 45 +D22 92 45 +D23 101.2 45 +D24 92 56.25 +D25 82.8 56.25 +D26 73.6 54 +D27 64.4 54 +D28 55.2 60 +D29 64.4 66 +D30 73.6 66 +D31 82.8 67.5 +D32 92 67.5 +E1 18.4 90 +E2 18.4 54 +E3 27.6 54 +E4 36.8 54 +E5 46 60 +E6 46 75 +E7 55.2 75 +E8 64.4 78 +E9 73.6 78 +E10 82.8 78.75 +E11 92 78.75 +E12 92 90 +E13 82.8 90 +E14 73.6 90 +E15 64.4 90 +E16 55.2 90 +E17 46 90 +E18 36.8 90 +E19 36.8 72 +E20 27.6 78 +E21 -27.6 -78 +E22 -36.8 -72 +E23 -46 -75 +E24 -55.2 -75 +E25 -64.4 -78 +E26 -73.6 -78 +E27 -82.8 -78.75 +E28 -92 -78.75 +E29 -92 -67.5 +E30 -82.8 -67.5 +E31 -73.6 -66 +E32 -64.4 -66 +F1 -9.2 -54 +F2 -18.4 -54 +F3 -27.6 -54 +F4 -36.8 -54 +F5 -46 -60 +F6 -55.2 -60 +F7 -64.4 -54 +F8 -73.6 -54 +F9 -82.8 -56.25 +F10 -92 -56.25 +F11 -101.2 -45 +F12 -92 -45 +F13 -82.8 -45 +F14 -73.6 -42 +F15 -64.4 -42 +F16 -55.2 -45 +F17 -46 -45 +F18 -36.8 -36 +F19 -27.6 -30 +F20 -18.4 -18 +F21 -27.6 -6 +F22 -36.8 -18 +F23 -46 -30 +F24 -55.2 -30 +F25 -64.4 -30 +F26 -73.6 -30 +F27 -82.8 -33.75 +F28 -92 -33.75 +F29 -101.2 -33.75 +F30 -101.2 -22.5 +F31 -92 -22.5 +F32 -82.8 -22.5 +G1 -9.2 18 +G2 -18.4 18 +G3 -27.6 18 +G4 -36.8 0 +G5 -46 -15 +G6 -55.2 -15 +G7 -64.4 -18 +G8 -73.6 -18 +G9 -82.8 -11.25 +G10 -92 -11.25 +G11 -92 0 +G12 -82.8 0 +G13 -73.6 -6 +G14 -64.4 -6 +G15 -55.2 0 +G16 -46 0 +G17 -55.2 15 +G18 -64.4 6 +G19 -73.6 6 +G20 -82.8 11.25 +G21 -92 11.25 +G22 -101.2 22.5 +G23 -92 22.5 +G24 -82.8 22.5 +G25 -73.6 18 +G26 -64.4 18 +G27 -64.4 30 +G28 -73.6 30 +G29 -82.8 33.75 +G30 -92 33.75 +G31 -101.2 33.75 +G32 -110.4 30 +H1 -18.4 54 +H2 -27.6 42 +H3 -36.8 36 +H4 -36.8 18 +H5 -46 15 +H6 -46 30 +H7 -55.2 30 +H8 -64.4 42 +H9 -73.6 42 +H10 -82.8 45 +H11 -92 45 +H12 -101.2 45 +H13 -110.4 42 +H14 -110.4 54 +H15 -101.2 56.25 +H16 -92 56.25 +H17 -82.8 56.25 +H18 -73.6 54 +H19 -64.4 54 +H20 -55.2 45 +H21 -46 45 +H22 -36.8 54 +H23 -27.6 66 +H24 -46 60 +H25 -55.2 60 +H26 -64.4 66 +H27 -73.6 66 +H28 -82.8 67.5 +H29 -92 67.5 +H30 -101.2 67.5 +H31 -110.4 66 +H32 -119.6 66 +Nz 115 90 +LPA -115 0 +RPA 115 0 diff --git a/mne-python/source/mne/channels/data/montages/biosemi32.txt b/mne-python/source/mne/channels/data/montages/biosemi32.txt new file mode 100644 index 0000000000000000000000000000000000000000..d2e0a14ff1c1b397005db8cd847d27fe35cfdb8a --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/biosemi32.txt @@ -0,0 +1,36 @@ +Site Theta Phi +Fp1 -92 -72 +AF3 -74 -65 +F7 -92 -36 +F3 -60 -51 +FC1 -32 -45 +FC5 -72 -21 +T7 -92 0 +C3 -46 0 +CP1 -32 45 +CP5 -72 21 +P7 -92 36 +P3 -60 51 +Pz 46 -90 +PO3 -74 65 +O1 -92 72 +Oz 92 -90 +O2 92 -72 +PO4 74 -65 +P4 60 -51 +P8 92 -36 +CP6 72 -21 +CP2 32 -45 +C4 46 0 +T8 92 0 +FC6 72 21 +FC2 32 45 +F4 60 51 +F8 92 36 +AF4 74 65 +Fp2 92 72 +Fz 46 90 +Cz 0 0 +Nz 115 90 +LPA -115 0 +RPA 115 0 diff --git a/mne-python/source/mne/channels/data/montages/biosemi64.txt b/mne-python/source/mne/channels/data/montages/biosemi64.txt new file mode 100644 index 0000000000000000000000000000000000000000..4071cfb4741d4152d14e5903cd1c9aa1018a7c75 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/biosemi64.txt @@ -0,0 +1,68 @@ +Site Theta Phi +Fp1 -92 -72 +AF7 -92 -54 +AF3 -74 -65 +F1 -50 -68 +F3 -60 -51 +F5 -75 -41 +F7 -92 -36 +FT7 -92 -18 +FC5 -72 -21 +FC3 -50 -28 +FC1 -32 -45 +C1 -23 0 +C3 -46 0 +C5 -69 0 +T7 -92 0 +TP7 -92 18 +CP5 -72 21 +CP3 -50 28 +CP1 -32 45 +P1 -50 68 +P3 -60 51 +P5 -75 41 +P7 -92 36 +P9 -115 36 +PO7 -92 54 +PO3 -74 65 +O1 -92 72 +Iz 115 -90 +Oz 92 -90 +POz 69 -90 +Pz 46 -90 +CPz 23 -90 +Fpz 92 90 +Fp2 92 72 +AF8 92 54 +AF4 74 65 +AFz 69 90 +Fz 46 90 +F2 50 68 +F4 60 51 +F6 75 41 +F8 92 36 +FT8 92 18 +FC6 72 21 +FC4 50 28 +FC2 32 45 +FCz 23 90 +Cz 0 0 +C2 23 0 +C4 46 0 +C6 69 0 +T8 92 0 +TP8 92 -18 +CP6 72 -21 +CP4 50 -28 +CP2 32 -45 +P2 50 -68 +P4 60 -51 +P6 75 -41 +P8 92 -36 +P10 115 -36 +PO8 92 -54 +PO4 74 -65 +O2 92 -72 +Nz 115 90 +LPA -115 0 +RPA 115 0 diff --git a/mne-python/source/mne/channels/data/montages/brainproducts-RNP-BA-128.txt b/mne-python/source/mne/channels/data/montages/brainproducts-RNP-BA-128.txt new file mode 100644 index 0000000000000000000000000000000000000000..907eb5acc305c5f50df1f208a908be0026173132 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/brainproducts-RNP-BA-128.txt @@ -0,0 +1,131 @@ +Name Theta Phi +Fp1 -90 -72 +Fz 45 90 +F3 -60 -51 +F7 -90 -36 +F9 -113 -36 +FC5 -69 -21 +FC1 -31 -46 +C3 -45 0 +T7 -90 0 +CP5 -69 21 +CP1 -31 46 +Pz 45 -90 +P3 -60 51 +P7 -90 36 +P9 -113 36 +O1 -90 72 +Oz 90 -90 +O2 90 -72 +P10 113 -36 +P8 90 -36 +P4 60 -51 +CP2 31 -46 +CP6 69 -21 +T8 90 0 +C4 45 0 +Cz 0 0 +FC2 31 46 +FC6 69 21 +F10 113 36 +F8 90 36 +F4 60 51 +Fp2 90 72 +AF7 -90 -54 +AF3 -74 -68 +AFz 67 90 +F1 -49 -68 +F5 -74 -41 +FT7 -90 -18 +FC3 -49 -29 +C1 -23 0 +C5 -68 0 +TP7 -90 18 +CP3 -49 29 +P1 -49 68 +P5 -74 41 +PO7 -90 54 +PO3 -74 68 +Iz 112 -90 +POz 67 -90 +PO4 74 -68 +PO8 90 -54 +P6 74 -41 +P2 49 -68 +CPz 22 -90 +CP4 49 -29 +TP8 90 -18 +C6 68 0 +C2 23 0 +FC4 49 29 +FT8 90 18 +F6 74 41 +F2 49 68 +AF4 74 68 +AF8 90 54 +AFF3h -62 -67 +FFC1h -35 -73 +FFC5h -62 -35 +FT9 -113 -18 +FTT7h -79 -10 +FCC3h -35 -19 +CCP1h -16 45 +CCP5h -57 12 +TP9 -113 18 +TPP7h -81 29 +CPP3h -46 48 +PPO3h -62 67 +PPO9h -101 45 +POO1 -79 82 +PO9 -113 54 +I1 -112 72 +I2 112 -72 +PO10 113 -54 +POO2 79 -82 +PPO10h 101 -45 +PPO4h 62 -67 +CPP4h 46 -48 +TPP8h 81 -29 +TP10 113 -18 +CCP6h 57 -12 +CCP2h 16 -45 +FCC4h 35 19 +FTT8h 79 10 +FT10 113 18 +FFC6h 62 35 +FFC2h 35 73 +AFF4h 62 67 +AFp1 -79 -82 +AFF1h -57 -82 +AFF5h -72 -55 +FFT7h -81 -29 +FFC3h -46 -48 +FCC1h -16 -45 +FCC5h -57 -12 +TTP7h -79 10 +CCP3h -35 19 +CPP1h -35 73 +CPP5h -62 35 +TPP9h -101 27 +PPO5h -72 55 +PPO1h -57 82 +POO9h -101 63 +OI1h -101 81 +OI2h 101 -81 +POO10h 101 -63 +PPO2h 57 -82 +PPO6h 72 -55 +TPP10h 101 -27 +CPP6h 62 -35 +CPP2h 35 -73 +CCP4h 35 -19 +TTP8h 79 -10 +FCC6h 57 12 +FCC2h 16 45 +FFC4h 46 48 +FFT8h 81 29 +AFF6h 72 55 +AFF2h 57 82 +AFp2 79 82 +FCz 23 90 +Fpz 90 90 diff --git a/mne-python/source/mne/channels/data/montages/easycap-M1.txt b/mne-python/source/mne/channels/data/montages/easycap-M1.txt new file mode 100644 index 0000000000000000000000000000000000000000..271dc0fe79fe67e8fd84543e9c1d13d0429c13ad --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/easycap-M1.txt @@ -0,0 +1,75 @@ +Site Theta Phi +Fp1 -92 -72 +Fp2 92 72 +F3 -60 -51 +F4 60 51 +C3 -46 0 +C4 46 0 +P3 -60 51 +P4 60 -51 +O1 -92 72 +O2 92 -72 +F7 -92 -36 +F8 92 36 +T7 -92 0 +T8 92 0 +P7 -92 36 +P8 92 -36 +Fz 46 90 +Cz 0 0 +Pz 46 -90 +F1 -50 -68 +F2 50 68 +FC1 -32 -45 +FC2 32 45 +C1 -23 0 +C2 23 0 +CP1 -32 45 +CP2 32 -45 +P1 -50 68 +P2 50 -68 +AF3 -74 -65 +AF4 74 65 +FC3 -53 -33 +FC4 53 33 +CP3 -52 33 +CP4 52 -33 +PO3 -74 65 +PO4 74 -65 +F5 -75 -41 +F6 75 41 +FC5 -72 -21 +FC6 72 21 +C5 -69 0 +C6 69 0 +CP5 -72 21 +CP6 72 -21 +P5 -75 41 +P6 75 -41 +AF7 -92 -54 +AF8 92 54 +FT7 -92 -18 +FT8 92 18 +TP7 -92 18 +TP8 92 -18 +PO7 -92 54 +PO8 92 -54 +F9 -115 -36 +F10 115 36 +FT9 -115 -18 +FT10 115 18 +TP9 -115 18 +TP10 115 -18 +P9 -115 36 +P10 115 -36 +PO9 -115 54 +PO10 115 -54 +O9 -115 72 +O10 115 -72 +Fpz 92 90 +AFz 69 90 +FCz 23 90 +CPz 23 -90 +POz 69 -90 +Oz 92 -90 +Iz 115 -90 diff --git a/mne-python/source/mne/channels/data/montages/easycap-M10.txt b/mne-python/source/mne/channels/data/montages/easycap-M10.txt new file mode 100644 index 0000000000000000000000000000000000000000..7019fc692dd0ebdecfc24ea15a1362269b393077 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/easycap-M10.txt @@ -0,0 +1,62 @@ +Site Theta Phi +1 0 0 +2 23 90 +3 23 30 +4 23 -30 +5 23 -90 +6 -23 30 +7 -23 -30 +8 46 90 +9 46 66 +10 46 33 +11 46 0 +12 46 -33 +13 46 -66 +14 46 -90 +15 -46 66 +16 -46 33 +17 -46 0 +18 -46 -33 +19 -46 -66 +20 69 90 +21 69 66 +22 69 42 +23 69 18 +24 69 -6 +25 69 -30 +26 69 -54 +27 69 -78 +28 -69 78 +29 -69 54 +30 -69 30 +31 -69 6 +32 -69 -18 +33 -69 -42 +34 -69 -66 +35 92 90 +36 92 68 +37 92 45 +38 92 22 +39 92 0 +40 92 -22 +41 92 -45 +42 92 -68 +43 92 -90 +44 -92 68 +45 -92 45 +46 -92 22 +47 -92 0 +48 -92 -22 +49 -92 -45 +50 -92 -68 +51 115 35 +52 115 10 +53 115 -15 +54 115 -40 +55 115 -65 +56 115 -90 +57 -115 65 +58 -115 40 +59 -115 15 +60 -115 -10 +61 -115 -35 diff --git a/mne-python/source/mne/channels/data/montages/easycap-M43.txt b/mne-python/source/mne/channels/data/montages/easycap-M43.txt new file mode 100644 index 0000000000000000000000000000000000000000..47bbad785ec9e9a076dfaf6655f04ee1df4e6550 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/easycap-M43.txt @@ -0,0 +1,65 @@ +Site Theta Phi +1 23 90 +2 23 30 +3 23 -30 +4 23 -90 +5 -23 30 +6 -23 -30 +7 46 74 +8 46 41 +9 46 8 +10 46 -25 +11 46 -57 +12 46 -90 +13 -46 57 +14 -46 25 +15 -46 -8 +16 -46 -41 +17 -46 -74 +18 69 76 +19 69 49 +20 69 21 +21 69 -7 +22 69 -35 +23 69 -62 +24 69 -90 +25 -69 62 +26 -69 35 +27 -69 7 +28 -69 -21 +29 -69 -49 +30 -69 -76 +31 92 90 +32 92 62 +33 92 34 +34 92 6 +35 92 -21 +36 92 -49 +37 92 -76 +38 -92 76 +39 -92 49 +40 -92 21 +41 -92 -6 +42 -92 -34 +43 -92 -62 +44 115 35 +45 115 10 +46 115 -15 +47 115 -40 +48 115 -65 +49 115 -90 +50 -115 65 +51 -115 40 +52 -115 15 +53 -115 -10 +54 -115 -35 +55 138 23 +56 138 -15 +57 138 -40 +58 138 -65 +59 138 -90 +60 -138 65 +61 -138 40 +62 -138 15 +63 -138 -23 +Ref 0 0 diff --git a/mne-python/source/mne/channels/data/montages/mgh60.elc b/mne-python/source/mne/channels/data/montages/mgh60.elc new file mode 100644 index 0000000000000000000000000000000000000000..854ab37125c33859980f203d76545ec479ca7adf --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/mgh60.elc @@ -0,0 +1,132 @@ +# ASA electrode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 63 +Positions +-86.0761 -19.9897 -47.9860 +85.7939 -20.0093 -48.0310 +0.0083 86.8110 -39.9830 +-29.4367 83.9171 -6.9900 +0.1123 88.2470 -1.7130 +29.8723 84.8959 -7.0800 +-54.8397 68.5722 -10.5900 +-33.7007 76.8371 21.2270 +35.7123 77.7259 21.9560 +55.7433 69.6568 -10.7550 +-70.2629 42.4743 -11.4200 +-64.4658 48.0353 16.9210 +-50.2438 53.1112 42.1920 +-27.4958 56.9311 60.3420 +0.3122 58.5120 66.4620 +29.5142 57.6019 59.5400 +51.8362 54.3048 40.8140 +67.9142 49.8297 16.3670 +73.0431 44.4217 -12.0000 +-84.0759 14.5673 -50.4290 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-34.0619 26.0111 79.9870 +34.7841 26.4379 78.8080 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +84.1131 14.3647 -50.5380 +-85.8941 -15.8287 -48.2830 +-84.1611 -16.0187 -9.3460 +-80.2801 -13.7597 29.1600 +-65.3581 -11.6317 64.3580 +-36.1580 -9.9839 89.7520 +0.4009 -9.1670 100.2440 +37.6720 -9.6241 88.4120 +67.1179 -10.9003 63.5800 +83.4559 -12.7763 29.2080 +85.0799 -15.0203 -9.4900 +85.5599 -16.3613 -48.2710 +-85.6192 -46.5147 -45.7070 +-84.8302 -46.0217 -7.0560 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +85.5488 -45.5453 -7.1300 +86.1618 -47.0353 -45.8690 +-72.4343 -73.4527 -2.4870 +-67.2723 -76.2907 28.3820 +-53.0073 -78.7878 55.9400 +-28.6203 -80.5249 75.4360 +0.3247 -81.1150 82.6150 +31.9197 -80.4871 76.7160 +55.6667 -78.5602 56.5610 +67.8877 -75.9043 28.0910 +73.0557 -73.0683 -2.5400 +-54.8404 -97.5279 2.7920 +-36.5114 -100.8529 37.1670 +36.7816 -100.8491 36.3970 +55.6666 -97.6251 2.7300 +-29.4134 -112.4490 8.8390 +0.1076 -114.8920 14.6570 +29.8426 -112.1560 8.8000 +0.0045 -118.5650 -23.0780 +Labels +LPA +RPA +Nz +EEG001 +EEG002 +EEG003 +EEG004 +EEG005 +EEG006 +EEG007 +EEG008 +EEG009 +EEG010 +EEG011 +EEG012 +EEG013 +EEG014 +EEG015 +EEG016 +EEG017 +EEG018 +EEG019 +EEG020 +EEG021 +EEG022 +EEG023 +EEG024 +EEG025 +EEG026 +EEG027 +EEG028 +EEG029 +EEG030 +EEG031 +EEG032 +EEG033 +EEG034 +EEG035 +EEG036 +EEG037 +EEG038 +EEG039 +EEG040 +EEG041 +EEG042 +EEG043 +EEG044 +EEG045 +EEG046 +EEG047 +EEG048 +EEG049 +EEG050 +EEG051 +EEG052 +EEG053 +EEG054 +EEG055 +EEG056 +EEG057 +EEG058 +EEG059 +EEG060 \ No newline at end of file diff --git a/mne-python/source/mne/channels/data/montages/mgh70.elc b/mne-python/source/mne/channels/data/montages/mgh70.elc new file mode 100644 index 0000000000000000000000000000000000000000..aba48a41cd476cd79ee1022d3e373e0461628b65 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/mgh70.elc @@ -0,0 +1,152 @@ +# ASA electrode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 73 +Positions +-86.0761 -19.9897 -47.9860 +85.7939 -20.0093 -48.0310 +0.0083 86.8110 -39.9830 +-29.4367 83.9171 -6.9900 +0.1123 88.2470 -1.7130 +29.8723 84.8959 -7.0800 +-54.8397 68.5722 -10.5900 +-33.7007 76.8371 21.2270 +0.2313 80.7710 35.4170 +35.7123 77.7259 21.9560 +55.7433 69.6568 -10.7550 +-70.2629 42.4743 -11.4200 +-64.4658 48.0353 16.9210 +-50.2438 53.1112 42.1920 +-27.4958 56.9311 60.3420 +0.3122 58.5120 66.4620 +29.5142 57.6019 59.5400 +51.8362 54.3048 40.8140 +67.9142 49.8297 16.3670 +73.0431 44.4217 -12.0000 +-84.0759 14.5673 -50.4290 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-60.1819 22.7162 55.5440 +-34.0619 26.0111 79.9870 +0.3761 27.3900 88.6680 +34.7841 26.4379 78.8080 +62.2931 23.7228 55.6300 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +84.1131 14.3647 -50.5380 +-85.8941 -15.8287 -48.2830 +-84.1611 -16.0187 -9.3460 +-80.2801 -13.7597 29.1600 +-65.3581 -11.6317 64.3580 +-36.1580 -9.9839 89.7520 +0.4009 -9.1670 100.2440 +37.6720 -9.6241 88.4120 +67.1179 -10.9003 63.5800 +83.4559 -12.7763 29.2080 +85.0799 -15.0203 -9.4900 +85.5599 -16.3613 -48.2710 +-85.6192 -46.5147 -45.7070 +-84.8302 -46.0217 -7.0560 +-79.5922 -46.5507 30.9490 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +0.3858 -47.3180 99.4320 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +83.3218 -46.1013 31.2060 +85.5488 -45.5453 -7.1300 +86.1618 -47.0353 -45.8690 +-73.0093 -73.7657 -40.9980 +-72.4343 -73.4527 -2.4870 +-67.2723 -76.2907 28.3820 +-53.0073 -78.7878 55.9400 +-28.6203 -80.5249 75.4360 +0.3247 -81.1150 82.6150 +31.9197 -80.4871 76.7160 +55.6667 -78.5602 56.5610 +67.8877 -75.9043 28.0910 +73.0557 -73.0683 -2.5400 +73.8947 -74.3903 -41.2200 +-54.8404 -97.5279 2.7920 +-36.5114 -100.8529 37.1670 +0.2156 -102.1780 50.6080 +36.7816 -100.8491 36.3970 +55.6666 -97.6251 2.7300 +-29.4134 -112.4490 8.8390 +0.1076 -114.8920 14.6570 +29.8426 -112.1560 8.8000 +0.0045 -118.5650 -23.0780 +Labels +LPA +RPA +Nz +EEG001 +EEG002 +EEG003 +EEG004 +EEG005 +EEG006 +EEG007 +EEG008 +EEG009 +EEG010 +EEG011 +EEG012 +EEG013 +EEG014 +EEG015 +EEG016 +EEG017 +EEG018 +EEG019 +EEG020 +EEG021 +EEG022 +EEG023 +EEG024 +EEG025 +EEG026 +EEG027 +EEG028 +EEG029 +EEG030 +EEG031 +EEG032 +EEG033 +EEG034 +EEG035 +EEG036 +EEG037 +EEG038 +EEG039 +EEG040 +EEG041 +EEG042 +EEG043 +EEG044 +EEG045 +EEG046 +EEG047 +EEG048 +EEG049 +EEG050 +EEG051 +EEG052 +EEG053 +EEG054 +EEG055 +EEG056 +EEG057 +EEG058 +EEG059 +EEG060 +EEG065 +EEG066 +EEG067 +EEG068 +EEG069 +EEG070 +EEG071 +EEG072 +EEG073 +EEG074 \ No newline at end of file diff --git a/mne-python/source/mne/channels/data/montages/standard_1005.elc b/mne-python/source/mne/channels/data/montages/standard_1005.elc new file mode 100644 index 0000000000000000000000000000000000000000..4e695328b358db671ae94329ccaa42f44b80b773 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/standard_1005.elc @@ -0,0 +1,698 @@ +# ASA electrode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 346 +Positions +-86.0761 -19.9897 -47.9860 +85.7939 -20.0093 -48.0310 +0.0083 86.8110 -39.9830 +-29.4367 83.9171 -6.9900 +0.1123 88.2470 -1.7130 +29.8723 84.8959 -7.0800 +-48.9708 64.0872 -47.6830 +-54.8397 68.5722 -10.5900 +-45.4307 72.8622 5.9780 +-33.7007 76.8371 21.2270 +-18.4717 79.9041 32.7520 +0.2313 80.7710 35.4170 +19.8203 80.3019 32.7640 +35.7123 77.7259 21.9560 +46.5843 73.8078 6.0340 +55.7433 69.6568 -10.7550 +50.4352 63.8698 -48.0050 +-70.1019 41.6523 -49.9520 +-70.2629 42.4743 -11.4200 +-64.4658 48.0353 16.9210 +-50.2438 53.1112 42.1920 +-27.4958 56.9311 60.3420 +0.3122 58.5120 66.4620 +29.5142 57.6019 59.5400 +51.8362 54.3048 40.8140 +67.9142 49.8297 16.3670 +73.0431 44.4217 -12.0000 +72.1141 42.0667 -50.4520 +-84.0759 14.5673 -50.4290 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-60.1819 22.7162 55.5440 +-34.0619 26.0111 79.9870 +0.3761 27.3900 88.6680 +34.7841 26.4379 78.8080 +62.2931 23.7228 55.6300 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +84.1131 14.3647 -50.5380 +-85.8941 -15.8287 -48.2830 +-84.1611 -16.0187 -9.3460 +-80.2801 -13.7597 29.1600 +-65.3581 -11.6317 64.3580 +-36.1580 -9.9839 89.7520 +0.4009 -9.1670 100.2440 +37.6720 -9.6241 88.4120 +67.1179 -10.9003 63.5800 +83.4559 -12.7763 29.2080 +85.0799 -15.0203 -9.4900 +85.5599 -16.3613 -48.2710 +-85.6192 -46.5147 -45.7070 +-84.8302 -46.0217 -7.0560 +-79.5922 -46.5507 30.9490 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +0.3858 -47.3180 99.4320 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +83.3218 -46.1013 31.2060 +85.5488 -45.5453 -7.1300 +86.1618 -47.0353 -45.8690 +-73.0093 -73.7657 -40.9980 +-72.4343 -73.4527 -2.4870 +-67.2723 -76.2907 28.3820 +-53.0073 -78.7878 55.9400 +-28.6203 -80.5249 75.4360 +0.3247 -81.1150 82.6150 +31.9197 -80.4871 76.7160 +55.6667 -78.5602 56.5610 +67.8877 -75.9043 28.0910 +73.0557 -73.0683 -2.5400 +73.8947 -74.3903 -41.2200 +-54.9104 -98.0448 -35.4650 +-54.8404 -97.5279 2.7920 +-48.4244 -99.3408 21.5990 +-36.5114 -100.8529 37.1670 +-18.9724 -101.7680 46.5360 +0.2156 -102.1780 50.6080 +19.8776 -101.7930 46.3930 +36.7816 -100.8491 36.3970 +49.8196 -99.4461 21.7270 +55.6666 -97.6251 2.7300 +54.9876 -98.0911 -35.5410 +-29.4134 -112.4490 8.8390 +0.1076 -114.8920 14.6570 +29.8426 -112.1560 8.8000 +-29.8184 -114.5700 -29.2160 +0.0045 -118.5650 -23.0780 +29.7416 -114.2600 -29.2560 +-43.2897 75.8552 -28.2440 +-38.5517 79.9532 -4.9950 +-27.9857 82.4591 2.7020 +-17.1947 84.8491 10.0270 +-5.9317 86.8780 16.2000 +7.1053 87.0740 16.4690 +18.9233 85.5969 11.4430 +28.6443 82.9759 2.8280 +39.3203 80.6868 -4.7250 +43.8223 76.5418 -28.3070 +-63.2538 53.8573 -30.3160 +-61.3508 58.7992 0.8970 +-50.7998 64.0412 23.0890 +-34.3157 68.3931 41.1880 +-11.4357 70.7561 50.3480 +13.4793 71.2010 51.1750 +36.1833 69.1509 41.2540 +52.3972 65.0708 22.8620 +62.9152 60.0448 0.6300 +64.3342 54.5998 -30.4440 +-79.0669 28.0813 -31.2530 +-74.4999 31.3003 4.8460 +-65.2379 36.4282 36.1440 +-44.4098 40.7622 61.6900 +-15.4238 43.6600 77.6820 +17.5922 44.0540 77.7880 +45.8532 41.6228 60.6470 +67.1281 37.7998 35.2960 +78.0531 32.9817 4.4830 +80.0971 28.5137 -31.3380 +-84.1250 -1.8467 -29.7940 +-82.3550 0.8263 8.5790 +-74.6920 4.3033 45.3070 +-51.0509 7.1772 74.3770 +-18.2190 9.0941 92.5290 +18.7870 9.2479 91.5620 +51.8851 7.7978 73.5070 +77.0020 5.3357 45.3500 +83.8880 1.9457 8.5010 +84.1230 -1.8083 -29.6380 +-86.9731 -32.2157 -27.8480 +-85.5651 -30.6287 11.1530 +-76.4071 -29.7307 49.2170 +-52.9281 -28.9058 80.3040 +-18.3541 -28.3219 98.2200 +20.2199 -28.1481 98.1720 +55.1139 -28.3862 80.4740 +79.0059 -28.9863 49.6280 +85.9999 -29.8203 11.2480 +88.6249 -32.2723 -28.0000 +-78.1602 -60.7567 -23.8240 +-76.6802 -60.8317 12.8800 +-68.1152 -62.9747 47.2520 +-46.9142 -64.6908 75.2960 +-15.8202 -65.5999 91.1640 +19.4198 -65.5950 92.4050 +50.6738 -64.4822 76.1300 +71.0958 -62.6243 47.3280 +78.5198 -60.4323 12.9020 +78.9027 -60.9553 -23.8050 +-64.5973 -87.6558 -19.0140 +-62.9593 -87.5028 12.9520 +-54.0103 -89.8988 37.3320 +-35.8874 -91.6669 55.5040 +-12.0474 -92.6069 65.5080 +13.9226 -92.6940 66.9580 +37.7986 -91.6291 56.7330 +54.6087 -89.6402 37.0350 +63.1117 -87.2282 12.8560 +65.0137 -87.8062 -18.9520 +-42.8624 -108.0730 -13.1510 +-40.1204 -107.1290 12.0610 +-31.9514 -108.2520 23.0470 +-19.8624 -108.9420 29.7600 +-6.9194 -109.2600 32.7100 +6.8036 -109.1630 31.5820 +20.2936 -108.9140 28.9440 +32.1756 -108.2520 22.2550 +41.0976 -107.2450 12.1380 +43.8946 -109.1270 -13.1700 +-14.8504 -117.9870 -6.9200 +15.0946 -118.0180 -6.9330 +-14.8107 87.2351 -4.4770 +15.1623 88.0910 -4.5510 +-54.8298 66.4132 -29.7040 +-51.1757 70.8362 -1.7550 +-39.6407 74.8671 13.6780 +-27.2187 78.7091 28.3750 +-9.1977 80.6051 35.1330 +10.4823 80.8650 35.3590 +28.5803 79.3029 28.4700 +40.9403 75.7399 13.8600 +52.0293 71.8468 -1.9200 +55.7542 67.1698 -29.8240 +-71.5079 41.1193 -30.8540 +-68.5558 45.2843 3.0020 +-58.4878 50.6722 30.1920 +-39.9798 55.2601 52.6000 +-13.3838 57.9021 64.3320 +15.8342 58.4559 64.9920 +41.7942 56.2259 51.4990 +60.0522 52.0858 28.7080 +71.9592 47.1917 2.4750 +72.7981 41.8218 -31.0260 +-82.9559 13.3203 -30.8080 +-80.1139 16.3903 6.8500 +-71.2099 20.8203 41.3240 +-48.5119 24.5292 69.1360 +-17.3439 27.0241 86.9230 +18.4181 27.2709 86.4370 +49.5481 25.2378 68.4300 +73.2191 22.0067 41.2970 +81.5801 17.6837 6.5640 +83.3711 13.5477 -30.7490 +-85.1321 -17.0557 -28.7310 +-82.9461 -14.8827 10.0090 +-75.2941 -12.6397 47.9040 +-51.5811 -10.7548 78.0350 +-18.2790 -9.4319 97.3560 +19.6780 -9.3041 95.7060 +53.8059 -10.1442 77.7300 +78.1249 -11.7353 47.8400 +85.1369 -13.9063 9.8900 +86.0999 -17.0883 -28.7560 +-84.8102 -47.2457 -26.2200 +-82.7042 -46.2977 11.9740 +-73.3012 -46.7917 49.1090 +-51.0492 -47.1758 80.0160 +-17.3542 -47.3419 97.4100 +20.6798 -47.2321 98.0720 +53.9968 -46.8902 80.0770 +76.5498 -46.3733 49.1400 +85.1998 -45.8073 12.1020 +85.4428 -47.2213 -26.1760 +-72.1773 -74.6277 -21.5360 +-70.1133 -74.8677 12.9990 +-61.7283 -77.6238 43.0280 +-41.6733 -79.7528 66.7150 +-13.9613 -81.0029 81.0030 +17.2977 -80.9810 81.6410 +44.7477 -79.6111 67.6550 +63.6267 -77.3022 43.1190 +72.1037 -74.4993 13.0250 +73.2817 -75.0773 -21.5760 +-54.7754 -98.9768 -16.1930 +-51.9284 -98.4438 12.3040 +-43.3424 -100.1629 30.0090 +-28.0074 -101.3610 42.3790 +-9.5034 -102.0600 49.4180 +10.2356 -102.0290 48.9420 +28.6476 -101.3901 42.1380 +44.2206 -100.2191 29.8080 +52.8386 -98.5360 12.2500 +55.8596 -99.8940 -16.2080 +-14.8054 -115.1000 11.8290 +15.1456 -115.1910 11.8330 +-15.1584 -118.2420 -26.0480 +15.1286 -118.1510 -26.0810 +-36.1247 72.3801 -45.8520 +-43.5117 78.5802 -9.2400 +-33.2847 81.2071 -1.1400 +-22.3517 83.5621 6.0710 +-12.2417 86.1941 14.1880 +0.1703 87.3220 17.4420 +13.6223 86.7579 15.3020 +24.1013 84.3769 7.4330 +33.9133 81.8119 -1.0350 +43.9483 79.2958 -9.3000 +37.7123 72.1679 -46.1970 +-59.3398 52.6802 -48.7700 +-63.2618 55.9922 -11.1730 +-55.8198 61.3962 11.8840 +-43.3817 66.3672 32.8110 +-23.5817 69.9171 47.2930 +0.2763 71.2800 52.0920 +25.5583 70.5559 47.8270 +45.1522 67.2748 32.7310 +58.0002 62.5998 11.9000 +64.6732 57.2738 -11.4600 +60.6012 52.2668 -49.0380 +-78.4839 28.7703 -50.5220 +-76.6149 28.6533 -11.5080 +-71.5059 33.9263 20.9930 +-55.9399 38.7162 49.7880 +-30.6548 42.4151 71.0400 +0.3512 44.0740 79.1410 +32.6451 43.1009 70.7950 +57.5042 39.8518 48.8110 +74.2501 35.4997 20.3800 +79.0341 30.3437 -11.9970 +79.9201 28.9417 -50.9140 +-87.3620 -0.5147 -49.8370 +-82.6680 -0.9417 -10.2840 +-80.1330 2.5853 27.3120 +-64.1610 5.8313 60.8850 +-35.7490 8.3091 85.4590 +0.3911 9.5080 95.5600 +36.0700 8.6519 83.8320 +65.1640 6.6198 60.0520 +81.5440 3.6637 27.2010 +83.1680 0.1817 -10.3640 +85.3930 -0.9523 -49.5200 +-86.6321 -31.2377 -47.1780 +-85.9331 -31.0927 -8.4740 +-81.5431 -30.1727 30.2730 +-66.1281 -29.2957 65.8980 +-36.9301 -28.5699 91.7340 +0.3959 -28.1630 101.2690 +38.5399 -28.2251 90.9760 +68.8539 -28.6403 66.4100 +84.5529 -29.3783 30.8780 +85.9999 -30.2803 -8.4350 +86.7619 -31.7313 -47.2530 +-80.7152 -60.6457 -43.5940 +-78.5992 -59.7237 -4.7580 +-73.6642 -61.9227 30.3800 +-59.4112 -63.9248 62.6720 +-32.7283 -65.3199 85.9440 +0.3658 -65.7500 94.0580 +35.8918 -65.1381 85.9800 +62.2558 -63.6152 62.7190 +76.6708 -61.5483 30.5430 +79.3188 -59.3033 -4.8400 +81.5598 -61.2153 -43.8000 +-64.5703 -86.4318 -38.3240 +-64.5833 -86.2218 0.0330 +-58.7123 -88.7048 25.1930 +-46.1603 -90.8878 47.4460 +-24.6483 -92.2919 62.0760 +0.2727 -92.7580 67.3420 +26.4367 -92.2951 63.1990 +47.1437 -90.7122 47.6780 +60.8127 -88.5042 25.6620 +65.1517 -85.9432 -0.0090 +65.0377 -86.7182 -38.4480 +-43.1284 -107.5160 -32.3870 +-42.9764 -106.4930 5.7730 +-36.2344 -107.7160 17.7500 +-25.9844 -108.6160 26.5440 +-13.6644 -109.2660 32.8560 +0.1676 -109.2760 32.7900 +13.6506 -109.1060 30.9360 +26.6636 -108.6680 26.4150 +37.7006 -107.8400 18.0690 +43.6696 -106.5990 5.7260 +43.1766 -107.4440 -32.4630 +-29.3914 -114.5110 -10.0200 +0.0525 -119.3430 -3.9360 +29.5526 -113.6360 -10.0510 +-84.1611 -16.0187 -9.3460 +-72.4343 -73.4527 -2.4870 +85.0799 -15.0203 -9.4900 +73.0557 -73.0683 -2.5400 +-86.0761 -44.9897 -67.9860 + 85.7939 -45.0093 -68.0310 +-86.0761 -24.9897 -67.9860 + 85.7939 -25.0093 -68.0310 +Labels +LPA +RPA +Nz +Fp1 +Fpz +Fp2 +AF9 +AF7 +AF5 +AF3 +AF1 +AFz +AF2 +AF4 +AF6 +AF8 +AF10 +F9 +F7 +F5 +F3 +F1 +Fz +F2 +F4 +F6 +F8 +F10 +FT9 +FT7 +FC5 +FC3 +FC1 +FCz +FC2 +FC4 +FC6 +FT8 +FT10 +T9 +T7 +C5 +C3 +C1 +Cz +C2 +C4 +C6 +T8 +T10 +TP9 +TP7 +CP5 +CP3 +CP1 +CPz +CP2 +CP4 +CP6 +TP8 +TP10 +P9 +P7 +P5 +P3 +P1 +Pz +P2 +P4 +P6 +P8 +P10 +PO9 +PO7 +PO5 +PO3 +PO1 +POz +PO2 +PO4 +PO6 +PO8 +PO10 +O1 +Oz +O2 +I1 +Iz +I2 +AFp9h +AFp7h +AFp5h +AFp3h +AFp1h +AFp2h +AFp4h +AFp6h +AFp8h +AFp10h +AFF9h +AFF7h +AFF5h +AFF3h +AFF1h +AFF2h +AFF4h +AFF6h +AFF8h +AFF10h +FFT9h +FFT7h +FFC5h +FFC3h +FFC1h +FFC2h +FFC4h +FFC6h +FFT8h +FFT10h +FTT9h +FTT7h +FCC5h +FCC3h +FCC1h +FCC2h +FCC4h +FCC6h +FTT8h +FTT10h +TTP9h +TTP7h +CCP5h +CCP3h +CCP1h +CCP2h +CCP4h +CCP6h +TTP8h +TTP10h +TPP9h +TPP7h +CPP5h +CPP3h +CPP1h +CPP2h +CPP4h +CPP6h +TPP8h +TPP10h +PPO9h +PPO7h +PPO5h +PPO3h +PPO1h +PPO2h +PPO4h +PPO6h +PPO8h +PPO10h +POO9h +POO7h +POO5h +POO3h +POO1h +POO2h +POO4h +POO6h +POO8h +POO10h +OI1h +OI2h +Fp1h +Fp2h +AF9h +AF7h +AF5h +AF3h +AF1h +AF2h +AF4h +AF6h +AF8h +AF10h +F9h +F7h +F5h +F3h +F1h +F2h +F4h +F6h +F8h +F10h +FT9h +FT7h +FC5h +FC3h +FC1h +FC2h +FC4h +FC6h +FT8h +FT10h +T9h +T7h +C5h +C3h +C1h +C2h +C4h +C6h +T8h +T10h +TP9h +TP7h +CP5h +CP3h +CP1h +CP2h +CP4h +CP6h +TP8h +TP10h +P9h +P7h +P5h +P3h +P1h +P2h +P4h +P6h +P8h +P10h +PO9h +PO7h +PO5h +PO3h +PO1h +PO2h +PO4h +PO6h +PO8h +PO10h +O1h +O2h +I1h +I2h +AFp9 +AFp7 +AFp5 +AFp3 +AFp1 +AFpz +AFp2 +AFp4 +AFp6 +AFp8 +AFp10 +AFF9 +AFF7 +AFF5 +AFF3 +AFF1 +AFFz +AFF2 +AFF4 +AFF6 +AFF8 +AFF10 +FFT9 +FFT7 +FFC5 +FFC3 +FFC1 +FFCz +FFC2 +FFC4 +FFC6 +FFT8 +FFT10 +FTT9 +FTT7 +FCC5 +FCC3 +FCC1 +FCCz +FCC2 +FCC4 +FCC6 +FTT8 +FTT10 +TTP9 +TTP7 +CCP5 +CCP3 +CCP1 +CCPz +CCP2 +CCP4 +CCP6 +TTP8 +TTP10 +TPP9 +TPP7 +CPP5 +CPP3 +CPP1 +CPPz +CPP2 +CPP4 +CPP6 +TPP8 +TPP10 +PPO9 +PPO7 +PPO5 +PPO3 +PPO1 +PPOz +PPO2 +PPO4 +PPO6 +PPO8 +PPO10 +POO9 +POO7 +POO5 +POO3 +POO1 +POOz +POO2 +POO4 +POO6 +POO8 +POO10 +OI1 +OIz +OI2 +T3 +T5 +T4 +T6 +M1 +M2 +A1 +A2 diff --git a/mne-python/source/mne/channels/data/montages/standard_1020.elc b/mne-python/source/mne/channels/data/montages/standard_1020.elc new file mode 100644 index 0000000000000000000000000000000000000000..2f68b5147ee5deae20525cf9754f7941dda95a75 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/standard_1020.elc @@ -0,0 +1,200 @@ +# ASA electrode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 97 +Positions +-86.0761 -19.9897 -47.9860 +85.7939 -20.0093 -48.0310 +0.0083 86.8110 -39.9830 +-29.4367 83.9171 -6.9900 +0.1123 88.2470 -1.7130 +29.8723 84.8959 -7.0800 +-48.9708 64.0872 -47.6830 +-54.8397 68.5722 -10.5900 +-45.4307 72.8622 5.9780 +-33.7007 76.8371 21.2270 +-18.4717 79.9041 32.7520 +0.2313 80.7710 35.4170 +19.8203 80.3019 32.7640 +35.7123 77.7259 21.9560 +46.5843 73.8078 6.0340 +55.7433 69.6568 -10.7550 +50.4352 63.8698 -48.0050 +-70.1019 41.6523 -49.9520 +-70.2629 42.4743 -11.4200 +-64.4658 48.0353 16.9210 +-50.2438 53.1112 42.1920 +-27.4958 56.9311 60.3420 +0.3122 58.5120 66.4620 +29.5142 57.6019 59.5400 +51.8362 54.3048 40.8140 +67.9142 49.8297 16.3670 +73.0431 44.4217 -12.0000 +72.1141 42.0667 -50.4520 +-84.0759 14.5673 -50.4290 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-60.1819 22.7162 55.5440 +-34.0619 26.0111 79.9870 +0.3761 27.3900 88.6680 +34.7841 26.4379 78.8080 +62.2931 23.7228 55.6300 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +84.1131 14.3647 -50.5380 +-85.8941 -15.8287 -48.2830 +-84.1611 -16.0187 -9.3460 +-80.2801 -13.7597 29.1600 +-65.3581 -11.6317 64.3580 +-36.1580 -9.9839 89.7520 +0.4009 -9.1670 100.2440 +37.6720 -9.6241 88.4120 +67.1179 -10.9003 63.5800 +83.4559 -12.7763 29.2080 +85.0799 -15.0203 -9.4900 +85.5599 -16.3613 -48.2710 +-85.6192 -46.5147 -45.7070 +-84.8302 -46.0217 -7.0560 +-79.5922 -46.5507 30.9490 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +0.3858 -47.3180 99.4320 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +83.3218 -46.1013 31.2060 +85.5488 -45.5453 -7.1300 +86.1618 -47.0353 -45.8690 +-73.0093 -73.7657 -40.9980 +-72.4343 -73.4527 -2.4870 +-67.2723 -76.2907 28.3820 +-53.0073 -78.7878 55.9400 +-28.6203 -80.5249 75.4360 +0.3247 -81.1150 82.6150 +31.9197 -80.4871 76.7160 +55.6667 -78.5602 56.5610 +67.8877 -75.9043 28.0910 +73.0557 -73.0683 -2.5400 +73.8947 -74.3903 -41.2200 +-54.9104 -98.0448 -35.4650 +-54.8404 -97.5279 2.7920 +-48.4244 -99.3408 21.5990 +-36.5114 -100.8529 37.1670 +-18.9724 -101.7680 46.5360 +0.2156 -102.1780 50.6080 +19.8776 -101.7930 46.3930 +36.7816 -100.8491 36.3970 +49.8196 -99.4461 21.7270 +55.6666 -97.6251 2.7300 +54.9876 -98.0911 -35.5410 +-29.4134 -112.4490 8.8390 +0.1076 -114.8920 14.6570 +29.8426 -112.1560 8.8000 +-29.8184 -114.5700 -29.2160 +0.0045 -118.5650 -23.0780 +29.7416 -114.2600 -29.2560 +-84.1611 -16.0187 -9.3460 +-72.4343 -73.4527 -2.4870 +85.0799 -15.0203 -9.4900 +73.0557 -73.0683 -2.5400 +-86.0761 -44.9897 -67.9860 + 85.7939 -45.0093 -68.0310 +-86.0761 -24.9897 -67.9860 + 85.7939 -25.0093 -68.0310 +Labels +LPA +RPA +Nz +Fp1 +Fpz +Fp2 +AF9 +AF7 +AF5 +AF3 +AF1 +AFz +AF2 +AF4 +AF6 +AF8 +AF10 +F9 +F7 +F5 +F3 +F1 +Fz +F2 +F4 +F6 +F8 +F10 +FT9 +FT7 +FC5 +FC3 +FC1 +FCz +FC2 +FC4 +FC6 +FT8 +FT10 +T9 +T7 +C5 +C3 +C1 +Cz +C2 +C4 +C6 +T8 +T10 +TP9 +TP7 +CP5 +CP3 +CP1 +CPz +CP2 +CP4 +CP6 +TP8 +TP10 +P9 +P7 +P5 +P3 +P1 +Pz +P2 +P4 +P6 +P8 +P10 +PO9 +PO7 +PO5 +PO3 +PO1 +POz +PO2 +PO4 +PO6 +PO8 +PO10 +O1 +Oz +O2 +O9 +Iz +O10 +T3 +T5 +T4 +T6 +M1 +M2 +A1 +A2 diff --git a/mne-python/source/mne/channels/data/montages/standard_alphabetic.elc b/mne-python/source/mne/channels/data/montages/standard_alphabetic.elc new file mode 100644 index 0000000000000000000000000000000000000000..55367e427fbb219bc37cb0c18165d91af23ca511 --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/standard_alphabetic.elc @@ -0,0 +1,142 @@ +# ASA electrode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 68 +Positions +-86.0761 -19.9897 -47.9860 +85.7939 -20.0093 -48.0310 +0.0083 86.8110 -39.9830 +-29.4367 83.9171 -6.9900 +0.1123 88.2470 -1.7130 +29.8723 84.8959 -7.0800 +-54.8397 68.5722 -10.5900 +-33.7007 76.8371 21.2270 +0.2313 80.7710 35.4170 +35.7123 77.7259 21.9560 +55.7433 69.6568 -10.7550 +-70.2629 42.4743 -11.4200 +-64.4658 48.0353 16.9210 +-50.2438 53.1112 42.1920 +-27.4958 56.9311 60.3420 +0.3122 58.5120 66.4620 +29.5142 57.6019 59.5400 +51.8362 54.3048 40.8140 +67.9142 49.8297 16.3670 +73.0431 44.4217 -12.0000 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-60.1819 22.7162 55.5440 +-34.0619 26.0111 79.9870 +0.3761 27.3900 88.6680 +34.7841 26.4379 78.8080 +62.2931 23.7228 55.6300 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +-84.1611 -16.0187 -9.3460 +-80.2801 -13.7597 29.1600 +-65.3581 -11.6317 64.3580 +-36.1580 -9.9839 89.7520 +0.4009 -9.1670 100.2440 +37.6720 -9.6241 88.4120 +67.1179 -10.9003 63.5800 +83.4559 -12.7763 29.2080 +85.0799 -15.0203 -9.4900 +-84.8302 -46.0217 -7.0560 +-79.5922 -46.5507 30.9490 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +0.3858 -47.3180 99.4320 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +83.3218 -46.1013 31.2060 +85.5488 -45.5453 -7.1300 +-72.4343 -73.4527 -2.4870 +-67.2723 -76.2907 28.3820 +-53.0073 -78.7878 55.9400 +-28.6203 -80.5249 75.4360 +0.3247 -81.1150 82.6150 +31.9197 -80.4871 76.7160 +55.6667 -78.5602 56.5610 +67.8877 -75.9043 28.0910 +73.0557 -73.0683 -2.5400 +-54.8404 -97.5279 2.7920 +-36.5114 -100.8529 37.1670 +0.2156 -102.1780 50.6080 +36.7816 -100.8491 36.3970 +55.6666 -97.6251 2.7300 +-29.4134 -112.4490 8.8390 +0.1076 -114.8920 14.6570 +29.8426 -112.1560 8.8000 +-86.0761 -44.9897 -67.9860 + 85.7939 -45.0093 -68.0310 +-86.0761 -24.9897 -67.9860 + 85.7939 -25.0093 -68.0310 +Labels +LPA +RPA +Nz +Fp1 +Fpz +Fp2 +B3 +B1 +Bz +B2 +B4 +F7 +F5 +F3 +F1 +Fz +F2 +F4 +F6 +F8 +D7 +D5 +D3 +D1 +Dz +D2 +D4 +D6 +D8 +T3 +C5 +C3 +C1 +Cz +C2 +C4 +C6 +T4 +E7 +E5 +E3 +E1 +Ez +E2 +E4 +E6 +E8 +T5 +P5 +P3 +P1 +Pz +P2 +P4 +P6 +T6 +H3 +H1 +Hz +H2 +H4 +O1 +Oz +O2 +M1 +M2 +A1 +A2 diff --git a/mne-python/source/mne/channels/data/montages/standard_postfixed.elc b/mne-python/source/mne/channels/data/montages/standard_postfixed.elc new file mode 100644 index 0000000000000000000000000000000000000000..3ed4d32f6fba3d2decab006bb6c6d1b4d130fa0c --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/standard_postfixed.elc @@ -0,0 +1,212 @@ +# ASA electrode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 103 +Positions +-86.0761 -19.9897 -47.9860 +85.7939 -20.0093 -48.0310 +0.0083 86.8110 -39.9830 +-29.4367 83.9171 -6.9900 +0.1123 88.2470 -1.7130 +29.8723 84.8959 -7.0800 +-54.8397 68.5722 -10.5900 +-45.4307 72.8622 5.9780 +-33.7007 76.8371 21.2270 +-18.4717 79.9041 32.7520 +0.2313 80.7710 35.4170 +19.8203 80.3019 32.7640 +35.7123 77.7259 21.9560 +46.5843 73.8078 6.0340 +55.7433 69.6568 -10.7550 +-70.2629 42.4743 -11.4200 +-64.4658 48.0353 16.9210 +-50.2438 53.1112 42.1920 +-27.4958 56.9311 60.3420 +0.3122 58.5120 66.4620 +29.5142 57.6019 59.5400 +51.8362 54.3048 40.8140 +67.9142 49.8297 16.3670 +73.0431 44.4217 -12.0000 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-60.1819 22.7162 55.5440 +-34.0619 26.0111 79.9870 +0.3761 27.3900 88.6680 +34.7841 26.4379 78.8080 +62.2931 23.7228 55.6300 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +-84.0759 14.5673 -50.4290 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-60.1819 22.7162 55.5440 +-34.0619 26.0111 79.9870 +0.3761 27.3900 88.6680 +34.7841 26.4379 78.8080 +62.2931 23.7228 55.6300 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +84.1131 14.3647 -50.5380 +-84.1611 -16.0187 -9.3460 +-80.2801 -13.7597 29.1600 +-65.3581 -11.6317 64.3580 +-36.1580 -9.9839 89.7520 +0.4009 -9.1670 100.2440 +37.6720 -9.6241 88.4120 +67.1179 -10.9003 63.5800 +83.4559 -12.7763 29.2080 +85.0799 -15.0203 -9.4900 +-84.8302 -46.0217 -7.0560 +-79.5922 -46.5507 30.9490 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +0.3858 -47.3180 99.4320 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +83.3218 -46.1013 31.2060 +85.5488 -45.5453 -7.1300 +-84.8302 -46.0217 -7.0560 +-79.5922 -46.5507 30.9490 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +0.3858 -47.3180 99.4320 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +83.3218 -46.1013 31.2060 +85.5488 -45.5453 -7.1300 +-73.0093 -73.7657 -40.9980 +-72.4343 -73.4527 -2.4870 +-67.2723 -76.2907 28.3820 +-53.0073 -78.7878 55.9400 +-28.6203 -80.5249 75.4360 +0.3247 -81.1150 82.6150 +31.9197 -80.4871 76.7160 +55.6667 -78.5602 56.5610 +67.8877 -75.9043 28.0910 +73.0557 -73.0683 -2.5400 +73.8947 -74.3903 -41.2200 +-54.9104 -98.0448 -35.4650 +-54.8404 -97.5279 2.7920 +-48.4244 -99.3408 21.5990 +-36.5114 -100.8529 37.1670 +-18.9724 -101.7680 46.5360 +0.2156 -102.1780 50.6080 +19.8776 -101.7930 46.3930 +36.7816 -100.8491 36.3970 +49.8196 -99.4461 21.7270 +55.6666 -97.6251 2.7300 +54.9876 -98.0911 -35.5410 +-29.4134 -112.4490 8.8390 +0.1076 -114.8920 14.6570 +29.8426 -112.1560 8.8000 +-29.8184 -114.5700 -29.2160 +0.0045 -118.5650 -23.0780 +29.7416 -114.2600 -29.2560 +-86.0761 -44.9897 -67.9860 + 85.7939 -45.0093 -68.0310 +-86.0761 -24.9897 -67.9860 + 85.7939 -25.0093 -68.0310 +Labels +LPA +RPA +Nz +Fp1 +Fpz +Fp2 +F7a +F5a +F3a +F1a +Fza +F2a +F4a +F6a +F8a +F7 +F5 +F3 +F1 +Fz +F2 +F4 +F6 +F8 +F7p +F5p +F3p +F1p +Fzp +F2p +F4p +F6p +F8p +T1 +T3a +C5a +C3a +C1a +Cza +C2a +C4a +C6a +T4a +T2 +T3 +C5 +C3 +C1 +Cz +C2 +C4 +C6 +T4 +T3p +C5p +C3p +C1p +Czp +C2p +C4p +C6p +T4p +T5a +P5a +P3a +P1a +Pza +P2a +P4a +P6a +T6a +Cb1a +T5 +P5 +P3 +P1 +Pz +P2 +P4 +P6 +T6 +Cb2a +Cb1 +O1a +P5p +P3p +P1p +Pzp +P2p +P4p +P6p +O2a +Cb2 +O1 +Oz +O2 +Cb1p +Iz +Cb2p +M1 +M2 +A1 +A2 diff --git a/mne-python/source/mne/channels/data/montages/standard_prefixed.elc b/mne-python/source/mne/channels/data/montages/standard_prefixed.elc new file mode 100644 index 0000000000000000000000000000000000000000..67563c00439888ec7a1e7d546a97c58f17cbb19e --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/standard_prefixed.elc @@ -0,0 +1,160 @@ +# ASA electrode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 77 +Positions +-86.0761 -19.9897 -47.9860 +85.7939 -20.0093 -48.0310 +0.0083 86.8110 -39.9830 +-29.4367 83.9171 -6.9900 +0.1123 88.2470 -1.7130 +29.8723 84.8959 -7.0800 +55.7433 69.6568 -10.7550 +-33.7007 76.8371 21.2270 +0.2313 80.7710 35.4170 +35.7123 77.7259 21.9560 +55.7433 69.6568 -10.7550 +-70.2629 42.4743 -11.4200 +-64.4658 48.0353 16.9210 +-50.2438 53.1112 42.1920 +-27.4958 56.9311 60.3420 +0.3122 58.5120 66.4620 +29.5142 57.6019 59.5400 +51.8362 54.3048 40.8140 +67.9142 49.8297 16.3670 +73.0431 44.4217 -12.0000 +-84.0759 14.5673 -50.4290 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-60.1819 22.7162 55.5440 +-34.0619 26.0111 79.9870 +0.3761 27.3900 88.6680 +34.7841 26.4379 78.8080 +62.2931 23.7228 55.6300 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +84.1131 14.3647 -50.5380 +-85.8941 -15.8287 -48.2830 +-84.1611 -16.0187 -9.3460 +-80.2801 -13.7597 29.1600 +-65.3581 -11.6317 64.3580 +-36.1580 -9.9839 89.7520 +0.4009 -9.1670 100.2440 +37.6720 -9.6241 88.4120 +67.1179 -10.9003 63.5800 +83.4559 -12.7763 29.2080 +85.0799 -15.0203 -9.4900 +85.5599 -16.3613 -48.2710 +-84.8302 -46.0217 -7.0560 +-79.5922 -46.5507 30.9490 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +0.3858 -47.3180 99.4320 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +83.3218 -46.1013 31.2060 +85.5488 -45.5453 -7.1300 +-73.0093 -73.7657 -40.9980 +-72.4343 -73.4527 -2.4870 +-67.2723 -76.2907 28.3820 +-53.0073 -78.7878 55.9400 +-28.6203 -80.5249 75.4360 +0.3247 -81.1150 82.6150 +31.9197 -80.4871 76.7160 +55.6667 -78.5602 56.5610 +67.8877 -75.9043 28.0910 +73.0557 -73.0683 -2.5400 +73.8947 -74.3903 -41.2200 +-54.9104 -98.0448 -35.4650 +-54.8404 -97.5279 2.7920 +-36.5114 -100.8529 37.1670 +0.2156 -102.1780 50.6080 +36.7816 -100.8491 36.3970 +55.6666 -97.6251 2.7300 +54.9876 -98.0911 -35.5410 +-29.4134 -112.4490 8.8390 +0.1076 -114.8920 14.6570 +29.8426 -112.1560 8.8000 +0.0045 -118.5650 -23.0780 +-86.0761 -44.9897 -67.9860 + 85.7939 -45.0093 -68.0310 +-86.0761 -24.9897 -67.9860 + 85.7939 -25.0093 -68.0310 +Labels +LPA +RPA +Nz +Fp1 +Fpz +Fp2 +aF3 +aF1 +aFz +aF2 +aF4 +F7 +F5 +F3 +F1 +Fz +F2 +F4 +F6 +F8 +iT1 +T1 +pF5 +pF3 +pF1 +pFz +pF2 +pF4 +pF6 +T2 +iT2 +iT3 +T3 +C5 +C3 +C1 +Cz +C2 +C4 +C6 +T4 +iT4 +T3A +pC5 +pC3 +pC1 +pCz +pC2 +pC4 +pC6 +T4A +iT5 +T5 +P5 +P3 +P1 +Pz +P2 +P4 +P6 +T6 +iT6 +pO5 +pO3 +pO1 +pOz +pO2 +pO4 +pO6 +O1 +Oz +O2 +Iz +M1 +M2 +A1 +A2 diff --git a/mne-python/source/mne/channels/data/montages/standard_primed.elc b/mne-python/source/mne/channels/data/montages/standard_primed.elc new file mode 100644 index 0000000000000000000000000000000000000000..00ec918387d2adf8be79f2d14f20ae440c10e6bb --- /dev/null +++ b/mne-python/source/mne/channels/data/montages/standard_primed.elc @@ -0,0 +1,212 @@ +# ASA electrode file +ReferenceLabel avg +UnitPosition mm +NumberPositions= 103 +Positions +-86.0761 -19.9897 -47.9860 +85.7939 -20.0093 -48.0310 +0.0083 86.8110 -39.9830 +-29.4367 83.9171 -6.9900 +0.1123 88.2470 -1.7130 +29.8723 84.8959 -7.0800 +-54.8397 68.5722 -10.5900 +-45.4307 72.8622 5.9780 +-33.7007 76.8371 21.2270 +-18.4717 79.9041 32.7520 +0.2313 80.7710 35.4170 +19.8203 80.3019 32.7640 +35.7123 77.7259 21.9560 +46.5843 73.8078 6.0340 +55.7433 69.6568 -10.7550 +-70.2629 42.4743 -11.4200 +-64.4658 48.0353 16.9210 +-50.2438 53.1112 42.1920 +-27.4958 56.9311 60.3420 +0.3122 58.5120 66.4620 +29.5142 57.6019 59.5400 +51.8362 54.3048 40.8140 +67.9142 49.8297 16.3670 +73.0431 44.4217 -12.0000 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-60.1819 22.7162 55.5440 +-34.0619 26.0111 79.9870 +0.3761 27.3900 88.6680 +34.7841 26.4379 78.8080 +62.2931 23.7228 55.6300 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +-84.0759 14.5673 -50.4290 +-80.7750 14.1203 -11.1350 +-77.2149 18.6433 24.4600 +-60.1819 22.7162 55.5440 +-34.0619 26.0111 79.9870 +0.3761 27.3900 88.6680 +34.7841 26.4379 78.8080 +62.2931 23.7228 55.6300 +79.5341 19.9357 24.4380 +81.8151 15.4167 -11.3300 +84.1131 14.3647 -50.5380 +-84.1611 -16.0187 -9.3460 +-80.2801 -13.7597 29.1600 +-65.3581 -11.6317 64.3580 +-36.1580 -9.9839 89.7520 +0.4009 -9.1670 100.2440 +37.6720 -9.6241 88.4120 +67.1179 -10.9003 63.5800 +83.4559 -12.7763 29.2080 +85.0799 -15.0203 -9.4900 +-84.8302 -46.0217 -7.0560 +-79.5922 -46.5507 30.9490 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +0.3858 -47.3180 99.4320 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +83.3218 -46.1013 31.2060 +85.5488 -45.5453 -7.1300 +-84.8302 -46.0217 -7.0560 +-79.5922 -46.5507 30.9490 +-63.5562 -47.0088 65.6240 +-35.5131 -47.2919 91.3150 +0.3858 -47.3180 99.4320 +38.3838 -47.0731 90.6950 +66.6118 -46.6372 65.5800 +83.3218 -46.1013 31.2060 +85.5488 -45.5453 -7.1300 +-73.0093 -73.7657 -40.9980 +-72.4343 -73.4527 -2.4870 +-67.2723 -76.2907 28.3820 +-53.0073 -78.7878 55.9400 +-28.6203 -80.5249 75.4360 +0.3247 -81.1150 82.6150 +31.9197 -80.4871 76.7160 +55.6667 -78.5602 56.5610 +67.8877 -75.9043 28.0910 +73.0557 -73.0683 -2.5400 +73.8947 -74.3903 -41.2200 +-54.9104 -98.0448 -35.4650 +-54.8404 -97.5279 2.7920 +-48.4244 -99.3408 21.5990 +-36.5114 -100.8529 37.1670 +-18.9724 -101.7680 46.5360 +0.2156 -102.1780 50.6080 +19.8776 -101.7930 46.3930 +36.7816 -100.8491 36.3970 +49.8196 -99.4461 21.7270 +55.6666 -97.6251 2.7300 +54.9876 -98.0911 -35.5410 +-29.4134 -112.4490 8.8390 +0.1076 -114.8920 14.6570 +29.8426 -112.1560 8.8000 +-29.8184 -114.5700 -29.2160 +0.0045 -118.5650 -23.0780 +29.7416 -114.2600 -29.2560 +-86.0761 -44.9897 -67.9860 + 85.7939 -45.0093 -68.0310 +-86.0761 -24.9897 -67.9860 + 85.7939 -25.0093 -68.0310 +Labels +LPA +RPA +Nz +Fp1 +Fpz +Fp2 +F7' +F5' +F3' +F1' +Fz' +F2' +F4' +F6' +F8' +F7 +F5 +F3 +F1 +Fz +F2 +F4 +F6 +F8 +F7'' +F5'' +F3'' +F1'' +Fz'' +F2'' +F4'' +F6'' +F8'' +T1 +T3' +C5' +C3' +C1' +Cz' +C2' +C4' +C6' +T4' +T2 +T3 +C5 +C3 +C1 +Cz +C2 +C4 +C6 +T4 +T3'' +C5'' +C3'' +C1'' +Cz'' +C2'' +C4'' +C6'' +T4'' +T5' +P5' +P3' +P1' +Pz' +P2' +P4' +P6' +T6' +Cb1' +T5 +P5 +P3 +P1 +Pz +P2 +P4 +P6 +T6 +Cb2' +Cb1 +O1' +P5'' +P3'' +P1'' +Pz'' +P2'' +P4'' +P6'' +O2' +Cb2 +O1 +Oz +O2 +Cb1'' +Iz +Cb2'' +M1 +M2 +A1 +A2 diff --git a/mne-python/source/mne/channels/data/neighbors/KIT-157_neighb.mat b/mne-python/source/mne/channels/data/neighbors/KIT-157_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..1cae3fc30e6c6fc5074fea2ad6a9b97bc69b1b03 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/KIT-157_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/KIT-208_neighb.mat b/mne-python/source/mne/channels/data/neighbors/KIT-208_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..81de8402077da8ee6b706275fb9ad9f3be050cb5 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/KIT-208_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/KIT-NYU-2019_neighb.mat b/mne-python/source/mne/channels/data/neighbors/KIT-NYU-2019_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..700d19306cbbf75b57370f08eff09963a18fb60d Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/KIT-NYU-2019_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/KIT-UMD-1_neighb.mat b/mne-python/source/mne/channels/data/neighbors/KIT-UMD-1_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..f860666455361fc9b866334c0a0277c10cc3b527 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/KIT-UMD-1_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/KIT-UMD-2_neighb.mat b/mne-python/source/mne/channels/data/neighbors/KIT-UMD-2_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..19ad03ca239c673308e20f9ce67e9e43c8153aaa Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/KIT-UMD-2_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/KIT-UMD-3_neighb.mat b/mne-python/source/mne/channels/data/neighbors/KIT-UMD-3_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..c7ded3d0b78ec88f86b94c981ae469e300ed2eec Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/KIT-UMD-3_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/KIT-UMD-4_neighb.mat b/mne-python/source/mne/channels/data/neighbors/KIT-UMD-4_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..55158e7b4da34d8c70de92137b911b15fb8148b4 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/KIT-UMD-4_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/__init__.py b/mne-python/source/mne/channels/data/neighbors/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a07b13441ad1d401b0ee2b9caeebb4996777fa0b --- /dev/null +++ b/mne-python/source/mne/channels/data/neighbors/__init__.py @@ -0,0 +1,13 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Neighbor definitions for clustering permutation analysis.""" +# This is a selection of files from http://fieldtrip.fcdonders.nl/template +# Additional definitions can be obtained through the FieldTrip software. +# For additional information on how these definitions were computed, please +# consider the related fieldtrip documentation: +# http://fieldtrip.fcdonders.nl/template/neighbours. +# +# KIT neighbor files were computed with ft_prepare_neighbours using the +# triangulation method. diff --git a/mne-python/source/mne/channels/data/neighbors/biosemi16_neighb.mat b/mne-python/source/mne/channels/data/neighbors/biosemi16_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..56b7fb649f2603494ecbf2fef4fea7b313463ba9 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/biosemi16_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/biosemi32_neighb.mat b/mne-python/source/mne/channels/data/neighbors/biosemi32_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..1c29040a254f3d1554ea510fc1566a6a776803fa Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/biosemi32_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/biosemi64_neighb.mat b/mne-python/source/mne/channels/data/neighbors/biosemi64_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..4afbf6f05ff499c70e8cd3e0cbc2cdcb47077438 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/biosemi64_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/bti148_neighb.mat b/mne-python/source/mne/channels/data/neighbors/bti148_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..527e43597fd5027a6c47170e3f7e43936eec788b Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/bti148_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/bti248_neighb.mat b/mne-python/source/mne/channels/data/neighbors/bti248_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..9bde76bdbc16b6997815a2bb28e933e1b11c81e2 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/bti248_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/bti248grad_neighb.mat b/mne-python/source/mne/channels/data/neighbors/bti248grad_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..4e5d620d36ceb5e5288c9930abf060bce0a675f2 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/bti248grad_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/ctf151_neighb.mat b/mne-python/source/mne/channels/data/neighbors/ctf151_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..611a0bc875d346911139fb57544a262b04f4d7d9 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/ctf151_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/ctf275_neighb.mat b/mne-python/source/mne/channels/data/neighbors/ctf275_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..91cf84e2c80946a00d4682508f657ac20fa5e41c Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/ctf275_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/ctf64_neighb.mat b/mne-python/source/mne/channels/data/neighbors/ctf64_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..fd001e6ee8b9e12cad66eb7e5e1e659ae9dcd3c5 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/ctf64_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/easycap128ch-avg_neighb.mat b/mne-python/source/mne/channels/data/neighbors/easycap128ch-avg_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..020392d0024c6f405667c8e4f34eb1e51edc6eb1 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/easycap128ch-avg_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/easycap32ch-avg_neighb.mat b/mne-python/source/mne/channels/data/neighbors/easycap32ch-avg_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..62c88f0d03f814632829f3b45d998d9bc5e6c270 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/easycap32ch-avg_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/easycap64ch-avg_neighb.mat b/mne-python/source/mne/channels/data/neighbors/easycap64ch-avg_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..e59536ccfb0e4094682772fc0fe45276c7f20425 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/easycap64ch-avg_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/easycapM11_neighb.mat b/mne-python/source/mne/channels/data/neighbors/easycapM11_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..28131e70b28e09f1622320f0a5a9f3f4147fb744 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/easycapM11_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/easycapM14_neighb.mat b/mne-python/source/mne/channels/data/neighbors/easycapM14_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..be2ad3dfc90d0c1131ffee8e6e219742f48cb666 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/easycapM14_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/easycapM15_neighb.mat b/mne-python/source/mne/channels/data/neighbors/easycapM15_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..7dfa554a914e2314680be9154e23924637d288a9 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/easycapM15_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/easycapM1_neighb.mat b/mne-python/source/mne/channels/data/neighbors/easycapM1_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..010337b2ef41f8529cb90ea8402ca02dd55ad64b Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/easycapM1_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/ecog256_neighb.mat b/mne-python/source/mne/channels/data/neighbors/ecog256_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..a78f40e039c6dc71736bc03885a328dd74b38cec Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/ecog256_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/ecog256bipolar_neighb.mat b/mne-python/source/mne/channels/data/neighbors/ecog256bipolar_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..36de6194e10b176a5013e1c8b9374305687c2fa2 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/ecog256bipolar_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/eeg1010_neighb.mat b/mne-python/source/mne/channels/data/neighbors/eeg1010_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..fa639f43bc8702dc5c299922fe3338619f79d815 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/eeg1010_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/elec1005_neighb.mat b/mne-python/source/mne/channels/data/neighbors/elec1005_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..a035749124460e60b91d6012619319a4f1444aa4 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/elec1005_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/elec1010_neighb.mat b/mne-python/source/mne/channels/data/neighbors/elec1010_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..181a795ef7ff42762f181c92e566eed449a1c12f Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/elec1010_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/elec1020_neighb.mat b/mne-python/source/mne/channels/data/neighbors/elec1020_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..6ed27bcd79a488da94571f076ea7c5e14d51d5db Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/elec1020_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/itab153_neighb.mat b/mne-python/source/mne/channels/data/neighbors/itab153_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..7f92401b0fda2009fd2983eb0fae84d8ed5a998e Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/itab153_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/itab28_neighb.mat b/mne-python/source/mne/channels/data/neighbors/itab28_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..d7608aa717d5e6c4470fa3e710ab022230723d79 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/itab28_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/language29ch-avg_neighb.mat b/mne-python/source/mne/channels/data/neighbors/language29ch-avg_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..69e38e63bc3ddbddde62c40e23fcb1c2981b7322 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/language29ch-avg_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/mpi_59_channels_neighb.mat b/mne-python/source/mne/channels/data/neighbors/mpi_59_channels_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..eb5c22606335f15e66309f485176cfd7c673c88d Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/mpi_59_channels_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/neuromag122cmb_neighb.mat b/mne-python/source/mne/channels/data/neighbors/neuromag122cmb_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..d4ae1a3f89d398122b53a21de6fc2616325d70c5 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/neuromag122cmb_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/neuromag306cmb_neighb.mat b/mne-python/source/mne/channels/data/neighbors/neuromag306cmb_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..f5a1875733a78159bdac16b50ce290a5807817a6 Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/neuromag306cmb_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/neuromag306mag_neighb.mat b/mne-python/source/mne/channels/data/neighbors/neuromag306mag_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..d7ffc9897691d4ae533b6167243ab434e85acfaf Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/neuromag306mag_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/neuromag306planar_neighb.mat b/mne-python/source/mne/channels/data/neighbors/neuromag306planar_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..aa0529e2a31b36dbec0ff9098ca28dc2717372fc Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/neuromag306planar_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/yokogawa160_neighb.mat b/mne-python/source/mne/channels/data/neighbors/yokogawa160_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..ac47eab5dfa30d7a4393c5a5d1374c25a12358ed Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/yokogawa160_neighb.mat differ diff --git a/mne-python/source/mne/channels/data/neighbors/yokogawa440_neighb.mat b/mne-python/source/mne/channels/data/neighbors/yokogawa440_neighb.mat new file mode 100644 index 0000000000000000000000000000000000000000..e40ef5754871b279e0a2a1f9f83cb4fcfcd523db Binary files /dev/null and b/mne-python/source/mne/channels/data/neighbors/yokogawa440_neighb.mat differ diff --git a/mne-python/source/mne/channels/interpolation.py b/mne-python/source/mne/channels/interpolation.py new file mode 100644 index 0000000000000000000000000000000000000000..b27f8d700584f35b9152c17692a927d5c100461a --- /dev/null +++ b/mne-python/source/mne/channels/interpolation.py @@ -0,0 +1,553 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from copy import deepcopy + +import numpy as np +from numpy.polynomial.legendre import legval +from scipy.interpolate import RectBivariateSpline +from scipy.linalg import pinv +from scipy.spatial.distance import pdist, squareform + +from .._fiff.meas_info import _simplify_info, create_info +from .._fiff.pick import pick_channels, pick_info, pick_types +from .._fiff.proj import _has_eeg_average_ref_proj, make_eeg_average_ref_proj +from ..bem import _check_origin +from ..surface import _normalize_vectors +from ..utils import _validate_type, logger, verbose, warn + + +def _calc_h(cosang, stiffness=4, n_legendre_terms=50): + """Calculate spherical spline h function between points on a sphere. + + Parameters + ---------- + cosang : array-like | float + cosine of angles between pairs of points on a spherical surface. This + is equivalent to the dot product of unit vectors. + stiffness : float + stiffnes of the spline. Also referred to as ``m``. + n_legendre_terms : int + number of Legendre terms to evaluate. + """ + factors = [ + (2 * n + 1) / (n ** (stiffness - 1) * (n + 1) ** (stiffness - 1) * 4 * np.pi) + for n in range(1, n_legendre_terms + 1) + ] + return legval(cosang, [0] + factors) + + +def _calc_g(cosang, stiffness=4, n_legendre_terms=50): + """Calculate spherical spline g function between points on a sphere. + + Parameters + ---------- + cosang : array-like of float, shape(n_channels, n_channels) + cosine of angles between pairs of points on a spherical surface. This + is equivalent to the dot product of unit vectors. + stiffness : float + stiffness of the spline. + n_legendre_terms : int + number of Legendre terms to evaluate. + + Returns + ------- + G : np.ndrarray of float, shape(n_channels, n_channels) + The G matrix. + """ + factors = [ + (2 * n + 1) / (n**stiffness * (n + 1) ** stiffness * 4 * np.pi) + for n in range(1, n_legendre_terms + 1) + ] + return legval(cosang, [0] + factors) + + +def _make_interpolation_matrix(pos_from, pos_to, alpha=1e-5): + """Compute interpolation matrix based on spherical splines. + + Implementation based on [1] + + Parameters + ---------- + pos_from : np.ndarray of float, shape(n_good_sensors, 3) + The positions to interpolate from. + pos_to : np.ndarray of float, shape(n_bad_sensors, 3) + The positions to interpolate. + alpha : float + Regularization parameter. Defaults to 1e-5. + + Returns + ------- + interpolation : np.ndarray of float, shape(len(pos_from), len(pos_to)) + The interpolation matrix that maps good signals to the location + of bad signals. + + References + ---------- + [1] Perrin, F., Pernier, J., Bertrand, O. and Echallier, JF. (1989). + Spherical splines for scalp potential and current density mapping. + Electroencephalography Clinical Neurophysiology, Feb; 72(2):184-7. + """ + pos_from = pos_from.copy() + pos_to = pos_to.copy() + n_from = pos_from.shape[0] + n_to = pos_to.shape[0] + + # normalize sensor positions to sphere + _normalize_vectors(pos_from) + _normalize_vectors(pos_to) + + # cosine angles between source positions + cosang_from = pos_from.dot(pos_from.T) + cosang_to_from = pos_to.dot(pos_from.T) + G_from = _calc_g(cosang_from) + G_to_from = _calc_g(cosang_to_from) + assert G_from.shape == (n_from, n_from) + assert G_to_from.shape == (n_to, n_from) + + if alpha is not None: + G_from.flat[:: len(G_from) + 1] += alpha + + C = np.vstack( + [ + np.hstack([G_from, np.ones((n_from, 1))]), + np.hstack([np.ones((1, n_from)), [[0]]]), + ] + ) + C_inv = pinv(C) + + interpolation = np.hstack([G_to_from, np.ones((n_to, 1))]) @ C_inv[:, :-1] + assert interpolation.shape == (n_to, n_from) + return interpolation + + +def _do_interp_dots(inst, interpolation, goods_idx, bads_idx): + """Dot product of channel mapping matrix to channel data.""" + from ..epochs import BaseEpochs + from ..evoked import Evoked + from ..io import BaseRaw + + _validate_type(inst, (BaseRaw, BaseEpochs, Evoked), "inst") + inst._data[..., bads_idx, :] = np.matmul( + interpolation, inst._data[..., goods_idx, :] + ) + + +@verbose +def _interpolate_bads_eeg(inst, origin, exclude=None, ecog=False, verbose=None): + if exclude is None: + exclude = list() + bads_idx = np.zeros(len(inst.ch_names), dtype=bool) + goods_idx = np.zeros(len(inst.ch_names), dtype=bool) + + picks = pick_types(inst.info, meg=False, eeg=not ecog, ecog=ecog, exclude=exclude) + inst.info._check_consistency() + bads_idx[picks] = [inst.ch_names[ch] in inst.info["bads"] for ch in picks] + + if len(picks) == 0 or bads_idx.sum() == 0: + return + + goods_idx[picks] = True + goods_idx[bads_idx] = False + + pos = inst._get_channel_positions(picks) + + # Make sure only EEG are used + bads_idx_pos = bads_idx[picks] + goods_idx_pos = goods_idx[picks] + + # test spherical fit + distance = np.linalg.norm(pos - origin, axis=-1) + distance = np.mean(distance / np.mean(distance)) + if np.abs(1.0 - distance) > 0.1: + warn( + "Your spherical fit is poor, interpolation results are " + "likely to be inaccurate." + ) + + pos_good = pos[goods_idx_pos] - origin + pos_bad = pos[bads_idx_pos] - origin + logger.info(f"Computing interpolation matrix from {len(pos_good)} sensor positions") + interpolation = _make_interpolation_matrix(pos_good, pos_bad) + + logger.info(f"Interpolating {len(pos_bad)} sensors") + _do_interp_dots(inst, interpolation, goods_idx, bads_idx) + + +@verbose +def _interpolate_bads_ecog(inst, *, origin, exclude=None, verbose=None): + _interpolate_bads_eeg(inst, origin, exclude=exclude, ecog=True, verbose=verbose) + + +def _interpolate_bads_meg( + inst, mode="accurate", *, origin, verbose=None, ref_meg=False +): + return _interpolate_bads_meeg( + inst, mode, ref_meg=ref_meg, eeg=False, origin=origin, verbose=verbose + ) + + +@verbose +def _interpolate_bads_nan( + inst, + *, + ch_type, + ref_meg=False, + exclude=(), + verbose=None, +): + info = _simplify_info(inst.info) + picks_type = pick_types(info, ref_meg=ref_meg, exclude=exclude, **{ch_type: True}) + use_ch_names = [inst.info["ch_names"][p] for p in picks_type] + bads_type = [ch for ch in inst.info["bads"] if ch in use_ch_names] + if len(bads_type) == 0 or len(picks_type) == 0: + return + # select the bad channels to be interpolated + picks_bad = pick_channels(inst.info["ch_names"], bads_type, exclude=[]) + inst._data[..., picks_bad, :] = np.nan + + +@verbose +def _interpolate_bads_meeg( + inst, + mode="accurate", + *, + meg=True, + eeg=True, + ref_meg=False, + exclude=(), + origin, + method=None, + verbose=None, +): + from ..forward import _map_meg_or_eeg_channels + + if method is None: + method = {"meg": "MNE", "eeg": "MNE"} + bools = dict(meg=meg, eeg=eeg) + info = _simplify_info(inst.info) + for ch_type, do in bools.items(): + if not do: + continue + kw = dict(meg=False, eeg=False) + kw[ch_type] = True + picks_type = pick_types(info, ref_meg=ref_meg, exclude=exclude, **kw) + picks_good = pick_types(info, ref_meg=ref_meg, exclude="bads", **kw) + use_ch_names = [inst.info["ch_names"][p] for p in picks_type] + bads_type = [ch for ch in inst.info["bads"] if ch in use_ch_names] + if len(bads_type) == 0 or len(picks_type) == 0: + continue + # select the bad channels to be interpolated + picks_bad = pick_channels(inst.info["ch_names"], bads_type, exclude=[]) + + # do MNE based interpolation + if ch_type == "eeg": + picks_to = picks_type + bad_sel = np.isin(picks_type, picks_bad) + else: + picks_to = picks_bad + bad_sel = slice(None) + info_from = pick_info(inst.info, picks_good) + info_to = pick_info(inst.info, picks_to) + mapping = _map_meg_or_eeg_channels(info_from, info_to, mode=mode, origin=origin) + mapping = mapping[bad_sel] + _do_interp_dots(inst, mapping, picks_good, picks_bad) + + +@verbose +def _interpolate_bads_nirs(inst, exclude=(), verbose=None): + from ..preprocessing.nirs import _validate_nirs_info + + if len(pick_types(inst.info, fnirs=True, exclude=())) == 0: + return + + # Returns pick of all nirs and ensures channels are correctly ordered + picks_nirs = _validate_nirs_info(inst.info) + nirs_ch_names = [inst.info["ch_names"][p] for p in picks_nirs] + nirs_ch_names = [ch for ch in nirs_ch_names if ch not in exclude] + bads_nirs = [ch for ch in inst.info["bads"] if ch in nirs_ch_names] + if len(bads_nirs) == 0: + return + picks_bad = pick_channels(inst.info["ch_names"], bads_nirs, exclude=[]) + bads_mask = [p in picks_bad for p in picks_nirs] + + chs = [inst.info["chs"][i] for i in picks_nirs] + locs3d = np.array([ch["loc"][:3] for ch in chs]) + + dist = pdist(locs3d) + dist = squareform(dist) + + for bad in picks_bad: + dists_to_bad = dist[bad] + # Ignore distances to self + dists_to_bad[dists_to_bad == 0] = np.inf + # Ignore distances to other bad channels + dists_to_bad[bads_mask] = np.inf + # Find closest remaining channels for same frequency + closest_idx = np.argmin(dists_to_bad) + (bad % 2) + inst._data[bad] = inst._data[closest_idx] + + # TODO: this seems like a bug because it does not respect reset_bads + inst.info["bads"] = [ch for ch in inst.info["bads"] if ch in exclude] + + return inst + + +def _find_seeg_electrode_shaft(pos, tol_shaft=0.002, tol_spacing=1): + # 1) find nearest neighbor to define the electrode shaft line + # 2) find all contacts on the same line + # 3) remove contacts with large distances + + dist = squareform(pdist(pos)) + np.fill_diagonal(dist, np.inf) + + shafts = list() + shaft_ts = list() + for i, n1 in enumerate(pos): + if any([i in shaft for shaft in shafts]): + continue + n2 = pos[np.argmin(dist[i])] # 1 + # https://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html + shaft_dists = np.linalg.norm( + np.cross((pos - n1), (pos - n2)), axis=1 + ) / np.linalg.norm(n2 - n1) + shaft = np.where(shaft_dists < tol_shaft)[0] # 2 + shaft_prev = None + for _ in range(10): # avoid potential cycles + if np.array_equal(shaft, shaft_prev): + break + shaft_prev = shaft + # compute median shaft line + v = np.median( + [ + pos[i] - pos[j] + for idx, i in enumerate(shaft) + for j in shaft[idx + 1 :] + ], + axis=0, + ) + c = np.median(pos[shaft], axis=0) + # recompute distances + shaft_dists = np.linalg.norm( + np.cross((pos - c), (pos - c + v)), axis=1 + ) / np.linalg.norm(v) + shaft = np.where(shaft_dists < tol_shaft)[0] + ts = np.array([np.dot(c - n0, v) / np.linalg.norm(v) ** 2 for n0 in pos[shaft]]) + shaft_order = np.argsort(ts) + shaft = shaft[shaft_order] + ts = ts[shaft_order] + + # only include the largest group with spacing with the error tolerance + # avoid interpolating across spans between contacts + t_diffs = np.diff(ts) + t_diff_med = np.median(t_diffs) + spacing_errors = (t_diffs - t_diff_med) / t_diff_med + groups = list() + group = [shaft[0]] + for j in range(len(shaft) - 1): + if spacing_errors[j] > tol_spacing: + groups.append(group) + group = [shaft[j + 1]] + else: + group.append(shaft[j + 1]) + groups.append(group) + group = [group for group in groups if i in group][0] + ts = ts[np.isin(shaft, group)] + shaft = np.array(group, dtype=int) + + shafts.append(shaft) + shaft_ts.append(ts) + return shafts, shaft_ts + + +@verbose +def _interpolate_bads_seeg( + inst, exclude=None, tol_shaft=0.002, tol_spacing=1, verbose=None +): + if exclude is None: + exclude = list() + picks = pick_types(inst.info, meg=False, seeg=True, exclude=exclude) + inst.info._check_consistency() + bads_idx = np.isin(np.array(inst.ch_names)[picks], inst.info["bads"]) + + if len(picks) == 0 or bads_idx.sum() == 0: + return + + pos = inst._get_channel_positions(picks) + + # Make sure only sEEG are used + bads_idx_pos = bads_idx[picks] + + shafts, shaft_ts = _find_seeg_electrode_shaft( + pos, tol_shaft=tol_shaft, tol_spacing=tol_spacing + ) + + # interpolate the bad contacts + picks_bad = list(np.where(bads_idx_pos)[0]) + for shaft, ts in zip(shafts, shaft_ts): + bads_shaft = np.array([idx for idx in picks_bad if idx in shaft]) + if bads_shaft.size == 0: + continue + goods_shaft = shaft[np.isin(shaft, bads_shaft, invert=True)] + if goods_shaft.size < 4: # cubic spline requires 3 channels + msg = "No shaft" if shaft.size < 4 else "Not enough good channels" + no_shaft_chs = " and ".join(np.array(inst.ch_names)[bads_shaft]) + raise RuntimeError( + f"{msg} found in a line with {no_shaft_chs} " + "at least 3 good channels on the same line " + f"are required for interpolation, {goods_shaft.size} found. " + f"Dropping {no_shaft_chs} is recommended." + ) + logger.debug( + f"Interpolating {np.array(inst.ch_names)[bads_shaft]} using " + f"data from {np.array(inst.ch_names)[goods_shaft]}" + ) + bads_shaft_idx = np.where(np.isin(shaft, bads_shaft))[0] + goods_shaft_idx = np.where(~np.isin(shaft, bads_shaft))[0] + + z = inst._data[..., goods_shaft, :] + is_epochs = z.ndim == 3 + if is_epochs: + z = z.swapaxes(0, 1) + z = z.reshape(z.shape[0], -1) + y = np.arange(z.shape[-1]) + out = RectBivariateSpline(x=ts[goods_shaft_idx], y=y, z=z)( + x=ts[bads_shaft_idx], y=y + ) + if is_epochs: + out = out.reshape(bads_shaft.size, inst._data.shape[0], -1) + out = out.swapaxes(0, 1) + inst._data[..., bads_shaft, :] = out + + +def _interpolate_to_eeg(inst, sensors, origin, method, reg): + """Interpolate EEG data to a new montage.""" + from ..forward._field_interpolation import _map_meg_or_eeg_channels + + # Get target positions from the montage + ch_pos = sensors.get_positions().get("ch_pos", {}) + target_ch_names = list(ch_pos) + if not target_ch_names: + raise ValueError("The provided sensors configuration has no channel positions.") + + # Identify EEG channel + picks_good_eeg = pick_types(inst.info, eeg=True, exclude="bads") + if len(picks_good_eeg) == 0: + raise ValueError("No good EEG channels available for interpolation.") + + # Create destination info for new EEG channels + # TODO: Maybe copy? This will remove potentially useful metadata... + info_to = create_info(target_ch_names, sfreq=inst.info["sfreq"], ch_types="eeg") + info_to.set_montage(sensors) + + # Compute the interpolation mapping + if method == "spline": + origin_val = _check_origin(origin, inst.info) + pos_from = inst.info._get_channel_positions(picks_good_eeg) - origin_val + pos_to = np.stack(list(ch_pos.values()), axis=0) + + def _check_pos_sphere(pos): + d = np.linalg.norm(pos, axis=-1) + d_norm = np.mean(d / np.mean(d)) + if np.abs(1.0 - d_norm) > 0.1: + warn("Your spherical fit is poor; interpolation may be inaccurate.") + + _check_pos_sphere(pos_from) + _check_pos_sphere(pos_to) + mapping = _make_interpolation_matrix(pos_from, pos_to, alpha=reg) + + else: + assert method == "MNE" + info_eeg = pick_info(inst.info, picks_good_eeg) + # If the original info has an average EEG reference projector but + # the destination info does not, update info_interp via a temporary RawArray. + if _has_eeg_average_ref_proj(inst.info) and not _has_eeg_average_ref_proj( + info_to + ): + # add an average reference projector. + info_to["projs"].append(make_eeg_average_ref_proj(info_to)) + mapping = _map_meg_or_eeg_channels( + info_eeg, info_to, mode="accurate", origin=origin + ) + + return _remap_add(inst, mapping, info_to, ch_type="eeg") + + +def _interpolate_to_meg(inst, sensors, origin, mode): + """Interpolate MEG data to a canonical sensor configuration.""" + from ..forward._field_interpolation import _map_meg_or_eeg_channels + from .montage import read_meg_canonical_info + + # Get MEG channels from source + picks_meg_good = pick_types(inst.info, meg=True, ref_meg=False, exclude="bads") + if len(picks_meg_good) == 0: + raise ValueError("No good MEG channels available for interpolation.") + + # Load target sensor configuration + info_to = read_meg_canonical_info(sensors) + info_to["dev_head_t"] = deepcopy(inst.info["dev_head_t"]) + + # Get source MEG info + info_from = pick_info(inst.info, picks_meg_good) + + # Compute field interpolation mapping + origin_val = _check_origin(origin, inst.info) + mapping = _map_meg_or_eeg_channels(info_from, info_to, mode=mode, origin=origin_val) + return _remap_add(inst, mapping, info_to, ch_type="meg") + + +def _remap_add(inst, mapping, info_to, ch_type): + # Comments here refer to EEG, but in principle it could instead be MEG! + assert ch_type in ("eeg", "meg") + from ..epochs import BaseEpochs, EpochsArray + from ..evoked import Evoked, EvokedArray + from ..io import RawArray + from ..io.base import BaseRaw + + # Get original channel order + orig_names = inst.info["ch_names"] + + # Get the full list of EEG channel indices (including bad channels) + pick_kwargs = {ch_type: True} + picks_interp_all = pick_types(inst.info, exclude=[], **pick_kwargs) + picks_interp_good = pick_types(inst.info, exclude="bads", **pick_kwargs) + interp_names_orig = [orig_names[i] for i in picks_interp_all] + + # Interpolate EEG data + data_interp = mapping @ inst.get_data(picks=picks_interp_good) + + # Create a new instance for the interpolated EEG channels + if isinstance(inst, BaseRaw): + inst_interp = RawArray(data_interp, info_to, first_samp=inst.first_samp) + elif isinstance(inst, BaseEpochs): + inst_interp = EpochsArray(data_interp, info_to, tmin=inst.tmin) + else: + assert isinstance(inst, Evoked) + inst_interp = EvokedArray(data_interp, info_to, tmin=inst.tmin) + + # Identify non-EEG channels in original order + non_interp_names_ordered = [ch for ch in orig_names if ch not in interp_names_orig] + + # Merge only if non-EEG channels exist + if not non_interp_names_ordered: + return inst_interp + + inst_non_interp = inst.copy().pick(non_interp_names_ordered).load_data() + inst_out = inst_non_interp.add_channels([inst_interp], force_update_info=True) + + # Reorder channels + # Insert the entire new EEG block at the position of the first EEG channel. + orig_names_arr = np.array(orig_names) + mask_interp = np.isin(orig_names_arr, interp_names_orig) + if mask_interp.any(): + first_interp_index = np.where(mask_interp)[0][0] + pre = orig_names_arr[:first_interp_index] + new_interp = np.array(info_to["ch_names"]) + post = orig_names_arr[first_interp_index:] + post = post[~np.isin(orig_names_arr[first_interp_index:], interp_names_orig)] + new_order = np.concatenate((pre, new_interp, post)).tolist() + else: + new_order = orig_names + inst_out.reorder_channels(new_order) + return inst_out diff --git a/mne-python/source/mne/channels/layout.py b/mne-python/source/mne/channels/layout.py new file mode 100644 index 0000000000000000000000000000000000000000..85b7913c1c661cc4a183a53c5d834d044eca1961 --- /dev/null +++ b/mne-python/source/mne/channels/layout.py @@ -0,0 +1,1315 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import logging +from collections import defaultdict +from copy import deepcopy +from itertools import combinations +from pathlib import Path + +import numpy as np +from scipy.spatial.distance import pdist, squareform + +from .._fiff.constants import FIFF +from .._fiff.meas_info import Info +from .._fiff.pick import _FNIRS_CH_TYPES_SPLIT, _picks_to_idx, pick_types +from ..transforms import _cart_to_sph, _pol_to_cart +from ..utils import ( + _check_ch_locs, + _check_fname, + _check_option, + _check_sphere, + _clean_names, + _ensure_int, + fill_doc, + logger, + verbose, + warn, +) +from ..viz.topomap import plot_layout +from .channels import _get_ch_info + + +class Layout: + """Sensor layouts. + + Layouts are typically loaded from a file using + :func:`~mne.channels.read_layout`. Only use this class directly if you're + constructing a new layout. + + Parameters + ---------- + box : tuple of length 4 + The box dimension (x_min, x_max, y_min, y_max). + pos : array, shape=(n_channels, 4) + The unit-normalized positions of the channels in 2d + (x, y, width, height). + names : list of str + The channel names. + ids : array-like of int + The channel ids. + kind : str + The type of Layout (e.g. 'Vectorview-all'). + """ + + def __init__(self, box, pos, names, ids, kind): + self.box = box + self.pos = pos + self.names = names + self.ids = np.array(ids) + if self.ids.ndim != 1: + raise ValueError("The channel indices should be a 1D array-like.") + self.kind = kind + + def copy(self): + """Return a copy of the layout. + + Returns + ------- + layout : instance of Layout + A deepcopy of the layout. + + Notes + ----- + .. versionadded:: 1.7 + """ + return deepcopy(self) + + def save(self, fname, overwrite=False): + """Save Layout to disk. + + Parameters + ---------- + fname : path-like + The file name (must end with either ``.lout`` or ``.lay``). + overwrite : bool + If True, overwrites the destination file if it exists. + + See Also + -------- + read_layout + """ + x = self.pos[:, 0] + y = self.pos[:, 1] + width = self.pos[:, 2] + height = self.pos[:, 3] + fname = _check_fname(fname, overwrite=overwrite, name=fname) + if fname.suffix == ".lout": + out_str = "{:8.2f} {:8.2f} {:8.2f} {:8.2f}\n".format(*self.box) + elif fname.suffix == ".lay": + out_str = "" + else: + raise ValueError("Unknown layout type. Should be of type .lout or .lay.") + + for ii in range(x.shape[0]): + out_str += ( + f"{self.ids[ii]:03d} {x[ii]:8.2f} {y[ii]:8.2f} " + f"{width[ii]:8.2f} {height[ii]:8.2f} {self.names[ii]}\n" + ) + + f = open(fname, "w") + f.write(out_str) + f.close() + + def __repr__(self): + """Return the string representation.""" + return "".format( + self.kind, + ", ".join(self.names[:3]), + ) + + @fill_doc + def plot(self, picks=None, show_axes=False, show=True): + """Plot the sensor positions. + + Parameters + ---------- + %(picks_nostr)s + show_axes : bool + Show layout axes if True. Defaults to False. + show : bool + Show figure if True. Defaults to True. + + Returns + ------- + fig : instance of matplotlib.figure.Figure + Figure containing the sensor topography. + + Notes + ----- + .. versionadded:: 0.12.0 + """ + return plot_layout(self, picks=picks, show_axes=show_axes, show=show) + + @verbose + def pick(self, picks=None, exclude=(), *, verbose=None): + """Pick a subset of channels. + + Parameters + ---------- + %(picks_layout)s + exclude : str | int | array-like of str or int + Set of channels to exclude, only used when ``picks`` is set to ``'all'`` or + ``None``. Exclude will not drop channels explicitly provided in ``picks``. + %(verbose)s + + Returns + ------- + layout : instance of Layout + The modified layout. + + Notes + ----- + .. versionadded:: 1.7 + """ + # TODO: all the picking functions operates on an 'info' object which is missing + # for a layout, thus we have to do the extra work here. The logic below can be + # replaced when https://github.com/mne-tools/mne-python/issues/11913 is solved. + if (isinstance(picks, str) and picks == "all") or (picks is None): + picks = deepcopy(self.names) + apply_exclude = True + elif isinstance(picks, str): + picks = [picks] + apply_exclude = False + elif isinstance(picks, slice): + try: + picks = np.arange(len(self.names))[picks] + except TypeError: + raise TypeError( + "If a slice is provided, it must be a slice of integers." + ) + apply_exclude = False + else: + try: + picks = [_ensure_int(picks)] + except TypeError: + picks = ( + list(picks) if isinstance(picks, tuple | set) else deepcopy(picks) + ) + apply_exclude = False + if apply_exclude: + if isinstance(exclude, str): + exclude = [exclude] + else: + try: + exclude = [_ensure_int(exclude)] + except TypeError: + exclude = ( + list(exclude) + if isinstance(exclude, tuple | set) + else deepcopy(exclude) + ) + for var, var_name in ((picks, "picks"), (exclude, "exclude")): + if var_name == "exclude" and not apply_exclude: + continue + if not isinstance(var, list | tuple | set | np.ndarray): + raise TypeError( + f"'{var_name}' must be a list, tuple, set or ndarray. " + f"Got {type(var)} instead." + ) + if isinstance(var, np.ndarray) and var.ndim != 1: + raise ValueError( + f"'{var_name}' must be a 1D array-like. Got {var.ndim}D instead." + ) + for k, elt in enumerate(var): + if isinstance(elt, str) and elt in self.names: + var[k] = self.names.index(elt) + continue + elif isinstance(elt, str): + raise ValueError( + f"The channel name {elt} provided in {var_name} does not match " + "any channels from the layout." + ) + try: + var[k] = _ensure_int(elt) + except TypeError: + raise TypeError( + f"All elements in '{var_name}' must be integers or strings." + ) + if not (0 <= var[k] < len(self.names)): + raise ValueError( + f"The value {elt} provided in {var_name} does not match any " + f"channels from the layout. The layout has {len(self.names)} " + "channels." + ) + if len(var) != len(set(var)): + warn( + f"The provided '{var_name}' has duplicates which will be ignored.", + RuntimeWarning, + ) + picks = picks.astype(int) if isinstance(picks, np.ndarray) else picks + exclude = exclude.astype(int) if isinstance(exclude, np.ndarray) else exclude + if apply_exclude: + picks = np.array(list(set(picks) - set(exclude)), dtype=int) + if len(picks) == 0: + raise RuntimeError( + "The channel selection yielded no remaining channels. Please edit " + "the arguments 'picks' and 'exclude' to include at least one " + "channel." + ) + else: + picks = np.array(list(set(picks)), dtype=int) + self.pos = self.pos[picks] + self.ids = self.ids[picks] + self.names = [self.names[k] for k in picks] + return self + + +def _read_lout(fname): + """Aux function.""" + with open(fname) as f: + box_line = f.readline() # first line contains box dimension + box = tuple(map(float, box_line.split())) + names, pos, ids = [], [], [] + for line in f: + splits = line.split() + if len(splits) == 7: + cid, x, y, dx, dy, chkind, nb = splits + name = chkind + " " + nb + else: + cid, x, y, dx, dy, name = splits + pos.append(np.array([x, y, dx, dy], dtype=np.float64)) + names.append(name) + ids.append(int(cid)) + + pos = np.array(pos) + + return box, pos, names, ids + + +def _read_lay(fname): + """Aux function.""" + with open(fname) as f: + box = None + names, pos, ids = [], [], [] + for line in f: + splits = line.split() + if len(splits) == 7: + cid, x, y, dx, dy, chkind, nb = splits + name = chkind + " " + nb + else: + cid, x, y, dx, dy, name = splits + pos.append(np.array([x, y, dx, dy], dtype=np.float64)) + names.append(name) + ids.append(int(cid)) + + pos = np.array(pos) + + return box, pos, names, ids + + +def read_layout(fname=None, *, scale=True): + """Read layout from a file. + + Parameters + ---------- + fname : path-like | str + Either the path to a ``.lout`` or ``.lay`` file or the name of a + built-in layout. See Notes for a list of the available built-in + layouts. + scale : bool + Apply useful scaling for out the box plotting using ``layout.pos``. + Defaults to True. + + Returns + ------- + layout : instance of Layout + The layout. + + See Also + -------- + Layout.save + + Notes + ----- + Valid ``fname`` arguments are: + + .. table:: + :widths: auto + + +----------------------+ + | Kind | + +======================+ + | biosemi | + +----------------------+ + | CTF151 | + +----------------------+ + | CTF275 | + +----------------------+ + | CTF-275 | + +----------------------+ + | EEG1005 | + +----------------------+ + | EGI256 | + +----------------------+ + | GeodesicHeadWeb-130 | + +----------------------+ + | GeodesicHeadWeb-280 | + +----------------------+ + | KIT-125 | + +----------------------+ + | KIT-157 | + +----------------------+ + | KIT-160 | + +----------------------+ + | KIT-AD | + +----------------------+ + | KIT-AS-2008 | + +----------------------+ + | KIT-UMD-3 | + +----------------------+ + | magnesWH3600 | + +----------------------+ + | Neuromag_122 | + +----------------------+ + | Vectorview-all | + +----------------------+ + | Vectorview-grad | + +----------------------+ + | Vectorview-grad_norm | + +----------------------+ + | Vectorview-mag | + +----------------------+ + """ + readers = {".lout": _read_lout, ".lay": _read_lay} + + if isinstance(fname, str): + # is it a built-in layout? + directory = Path(__file__).parent / "data" / "layouts" + for suffix in ("", ".lout", ".lay"): + _fname = (directory / fname).with_suffix(suffix) + if _fname.exists(): + fname = _fname + break + # if not, it must be a valid path provided as str or Path + fname = _check_fname(fname, "read", must_exist=True, name="layout") + # and it must have a valid extension + _check_option("fname extension", fname.suffix, readers) + kind = fname.stem + box, pos, names, ids = readers[fname.suffix](fname) + + if scale: + pos[:, 0] -= np.min(pos[:, 0]) + pos[:, 1] -= np.min(pos[:, 1]) + scaling = max(np.max(pos[:, 0]), np.max(pos[:, 1])) + pos[0, 2] + pos /= scaling + pos[:, :2] += 0.03 + pos[:, :2] *= 0.97 / 1.03 + pos[:, 2:] *= 0.94 + + return Layout(box=box, pos=pos, names=names, kind=kind, ids=ids) + + +@fill_doc +def make_eeg_layout( + info, radius=0.5, width=None, height=None, exclude="bads", csd=False +): + """Make a Layout object based on EEG electrode digitization. + + Parameters + ---------- + %(info_not_none)s + radius : float + Viewport radius as a fraction of main figure height. Defaults to 0.5. + width : float | None + Width of sensor axes as a fraction of main figure height. By default, + this will be the maximum width possible without axes overlapping. + height : float | None + Height of sensor axes as a fraction of main figure height. By default, + this will be the maximum height possible without axes overlapping. + exclude : list of str | str + List of channels to exclude. If empty do not exclude any. + If 'bads', exclude channels in info['bads'] (default). + csd : bool + Whether the channels contain current-source-density-transformed data. + + Returns + ------- + layout : Layout + The generated Layout. + + See Also + -------- + make_grid_layout, generate_2d_layout + """ + if not (0 <= radius <= 0.5): + raise ValueError("The radius parameter should be between 0 and 0.5.") + if width is not None and not (0 <= width <= 1.0): + raise ValueError("The width parameter should be between 0 and 1.") + if height is not None and not (0 <= height <= 1.0): + raise ValueError("The height parameter should be between 0 and 1.") + + pick_kwargs = dict(meg=False, eeg=True, ref_meg=False, exclude=exclude) + if csd: + pick_kwargs.update(csd=True, eeg=False) + picks = pick_types(info, **pick_kwargs) + loc2d = _find_topomap_coords(info, picks) + names = [info["chs"][i]["ch_name"] for i in picks] + + # Scale [x, y] to be in the range [-0.5, 0.5] + # Don't mess with the origin or aspect ratio + scale = np.maximum(-np.min(loc2d, axis=0), np.max(loc2d, axis=0)).max() * 2 + loc2d /= scale + + # If no width or height specified, calculate the maximum value possible + # without axes overlapping. + if width is None or height is None: + width, height = _box_size(loc2d, width, height, padding=0.1) + + # Scale to viewport radius + loc2d *= 2 * radius + + # Some subplot centers will be at the figure edge. Shrink everything so it + # fits in the figure. + scaling = min(1 / (1.0 + width), 1 / (1.0 + height)) + loc2d *= scaling + width *= scaling + height *= scaling + + # Shift to center + loc2d += 0.5 + + n_channels = loc2d.shape[0] + pos = np.c_[ + loc2d[:, 0] - 0.5 * width, + loc2d[:, 1] - 0.5 * height, + width * np.ones(n_channels), + height * np.ones(n_channels), + ] + + box = (0, 1, 0, 1) + ids = 1 + np.arange(n_channels) + layout = Layout(box=box, pos=pos, names=names, kind="EEG", ids=ids) + return layout + + +@fill_doc +def make_grid_layout(info, picks=None, n_col=None): + """Make a grid Layout object. + + This can be helpful to plot custom data such as ICA sources. + + Parameters + ---------- + %(info_not_none)s + %(picks_base)s all good misc channels. + n_col : int | None + Number of columns to generate. If None, a square grid will be produced. + + Returns + ------- + layout : Layout + The generated layout. + + See Also + -------- + make_eeg_layout, generate_2d_layout + """ + picks = _picks_to_idx(info, picks, "misc") + + names = [info["chs"][k]["ch_name"] for k in picks] + + if not names: + raise ValueError("No misc data channels found.") + + ids = list(range(len(picks))) + size = len(picks) + + if n_col is None: + # prepare square-like layout + n_row = n_col = np.sqrt(size) # try square + if n_col % 1: + # try n * (n-1) rectangle + n_col, n_row = int(n_col + 1), int(n_row) + + if n_col * n_row < size: # jump to the next full square + n_row += 1 + else: + n_row = int(np.ceil(size / float(n_col))) + + # setup position grid + x, y = np.meshgrid(np.linspace(-0.5, 0.5, n_col), np.linspace(-0.5, 0.5, n_row)) + x, y = x.ravel()[:size], y.ravel()[:size] + width, height = _box_size(np.c_[x, y], padding=0.1) + + # Some axes will be at the figure edge. Shrink everything so it fits in the + # figure. Add 0.01 border around everything + border_x, border_y = (0.01, 0.01) + x_scaling = 1 / (1.0 + width + border_x) + y_scaling = 1 / (1.0 + height + border_y) + x = x * x_scaling + y = y * y_scaling + width *= x_scaling + height *= y_scaling + + # Shift to center + x += 0.5 + y += 0.5 + + # calculate pos + pos = np.c_[ + x - 0.5 * width, y - 0.5 * height, width * np.ones(size), height * np.ones(size) + ] + box = (0, 1, 0, 1) + + layout = Layout(box=box, pos=pos, names=names, kind="grid-misc", ids=ids) + return layout + + +@fill_doc +def find_layout(info, ch_type=None, exclude="bads"): + """Choose a layout based on the channels in the info 'chs' field. + + Parameters + ---------- + %(info_not_none)s + ch_type : {'mag', 'grad', 'meg', 'eeg'} | None + The channel type for selecting single channel layouts. + Defaults to None. Note, this argument will only be considered for + VectorView type layout. Use ``'meg'`` to force using the full layout + in situations where the info does only contain one sensor type. + exclude : list of str | str + List of channels to exclude. If empty do not exclude any. + If 'bads', exclude channels in info['bads'] (default). + + Returns + ------- + layout : Layout instance | None + None if layout not found. + """ + _check_option("ch_type", ch_type, [None, "mag", "grad", "meg", "eeg", "csd"]) + + ( + has_vv_mag, + has_vv_grad, + is_old_vv, + has_4D_mag, + ctf_other_types, + has_CTF_grad, + n_kit_grads, + has_any_meg, + has_eeg_coils, + has_eeg_coils_and_meg, + has_eeg_coils_only, + has_neuromag_122_grad, + has_csd_coils, + ) = _get_ch_info(info) + has_vv_meg = has_vv_mag and has_vv_grad + has_vv_only_mag = has_vv_mag and not has_vv_grad + has_vv_only_grad = has_vv_grad and not has_vv_mag + if ch_type == "meg" and not has_any_meg: + raise RuntimeError("No MEG channels present. Cannot find MEG layout.") + + if ch_type == "eeg" and not has_eeg_coils: + raise RuntimeError("No EEG channels present. Cannot find EEG layout.") + + layout_name = None + if (has_vv_meg and ch_type is None) or ( + any([has_vv_mag, has_vv_grad]) and ch_type == "meg" + ): + layout_name = "Vectorview-all" + elif has_vv_only_mag or (has_vv_meg and ch_type == "mag"): + layout_name = "Vectorview-mag" + elif has_vv_only_grad or (has_vv_meg and ch_type == "grad"): + if info["ch_names"][0].endswith("X"): + layout_name = "Vectorview-grad_norm" + else: + layout_name = "Vectorview-grad" + elif has_neuromag_122_grad: + layout_name = "Neuromag_122" + elif (has_eeg_coils_only and ch_type in [None, "eeg"]) or ( + has_eeg_coils_and_meg and ch_type == "eeg" + ): + if not isinstance(info, dict | Info): + raise RuntimeError( + "Cannot make EEG layout, no measurement info " + "was passed to `find_layout`" + ) + return make_eeg_layout(info, exclude=exclude) + elif has_csd_coils and ch_type in [None, "csd"]: + return make_eeg_layout(info, exclude=exclude, csd=True) + elif has_4D_mag: + layout_name = "magnesWH3600" + elif has_CTF_grad: + layout_name = "CTF-275" + elif n_kit_grads > 0: + layout_name = _find_kit_layout(info, n_kit_grads) + + # If no known layout is found, fall back on automatic layout + if layout_name is None: + picks = _picks_to_idx(info, "data", exclude=(), with_ref_meg=False) + ch_names = [info["ch_names"][pick] for pick in picks] + xy = _find_topomap_coords(info, picks=picks, ignore_overlap=True) + return generate_2d_layout(xy, ch_names=ch_names, name="custom", normalize=True) + + layout = read_layout(fname=layout_name) + if not is_old_vv: + layout.names = _clean_names(layout.names, remove_whitespace=True) + if has_CTF_grad: + layout.names = _clean_names(layout.names, before_dash=True) + + # Apply mask for excluded channels. + if exclude == "bads": + exclude = info["bads"] + idx = [ii for ii, name in enumerate(layout.names) if name not in exclude] + layout.names = [layout.names[ii] for ii in idx] + layout.pos = layout.pos[idx] + layout.ids = layout.ids[idx] + + return layout + + +@fill_doc +def _find_kit_layout(info, n_grads): + """Determine the KIT layout. + + Parameters + ---------- + %(info_not_none)s + n_grads : int + Number of KIT-gradiometers in the info. + + Returns + ------- + kit_layout : str | None + String naming the detected KIT layout or ``None`` if layout is missing. + """ + from ..io.kit.constants import KIT_LAYOUT + + if info["kit_system_id"] is not None: + # avoid circular import + return KIT_LAYOUT.get(info["kit_system_id"]) + elif n_grads == 160: + return "KIT-160" + elif n_grads == 125: + return "KIT-125" + elif n_grads > 157: + return "KIT-AD" + + # channels which are on the left hemisphere for NY and right for UMD + test_chs = ( + "MEG 13", + "MEG 14", + "MEG 15", + "MEG 16", + "MEG 25", + "MEG 26", + "MEG 27", + "MEG 28", + "MEG 29", + "MEG 30", + "MEG 31", + "MEG 32", + "MEG 57", + "MEG 60", + "MEG 61", + "MEG 62", + "MEG 63", + "MEG 64", + "MEG 73", + "MEG 90", + "MEG 93", + "MEG 95", + "MEG 96", + "MEG 105", + "MEG 112", + "MEG 120", + "MEG 121", + "MEG 122", + "MEG 123", + "MEG 124", + "MEG 125", + "MEG 126", + "MEG 142", + "MEG 144", + "MEG 153", + "MEG 154", + "MEG 155", + "MEG 156", + ) + x = [ch["loc"][0] < 0 for ch in info["chs"] if ch["ch_name"] in test_chs] + if np.all(x): + return "KIT-157" # KIT-NY + elif np.all(np.invert(x)): + raise NotImplementedError( + "Guessing sensor layout for legacy UMD " + "files is not implemented. Please convert " + "your files using MNE-Python 0.13 or " + "higher." + ) + else: + raise RuntimeError("KIT system could not be determined for data") + + +def _box_size(points, width=None, height=None, padding=0.0): + """Given a series of points, calculate an appropriate box size. + + Parameters + ---------- + points : array, shape (n_points, 2) + The centers of the axes as a list of (x, y) coordinate pairs. Normally + these are points in the range [0, 1] centered at 0.5. + width : float | None + An optional box width to enforce. When set, only the box height will be + calculated by the function. + height : float | None + An optional box height to enforce. When set, only the box width will be + calculated by the function. + padding : float + Portion of the box to reserve for padding. The value can range between + 0.0 (boxes will touch, default) to 1.0 (boxes consist of only padding). + + Returns + ------- + width : float + Width of the box + height : float + Height of the box + """ + + def xdiff(a, b): + return np.abs(a[0] - b[0]) + + def ydiff(a, b): + return np.abs(a[1] - b[1]) + + points = np.asarray(points) + all_combinations = list(combinations(points, 2)) + + if width is None and height is None: + if len(points) <= 1: + # Trivial case first + width = 1.0 + height = 1.0 + else: + # Find the closest two points A and B. + a, b = all_combinations[np.argmin(pdist(points))] + + # The closest points define either the max width or max height. + w, h = xdiff(a, b), ydiff(a, b) + if w > h: + width = w + else: + height = h + + # At this point, either width or height is known, or both are known. + if height is None: + # Find all axes that could potentially overlap horizontally. + hdist = pdist(points, xdiff) + candidates = [all_combinations[i] for i, d in enumerate(hdist) if d < width] + + if len(candidates) == 0: + # No axes overlap, take all the height you want. + height = 1.0 + else: + # Find an appropriate height so all none of the found axes will + # overlap. + height = np.min([ydiff(*c) for c in candidates]) + + elif width is None: + # Find all axes that could potentially overlap vertically. + vdist = pdist(points, ydiff) + candidates = [all_combinations[i] for i, d in enumerate(vdist) if d < height] + + if len(candidates) == 0: + # No axes overlap, take all the width you want. + width = 1.0 + else: + # Find an appropriate width so all none of the found axes will + # overlap. + width = np.min([xdiff(*c) for c in candidates]) + + # Add a bit of padding between boxes + width *= 1 - padding + height *= 1 - padding + + return width, height + + +@fill_doc +def _find_topomap_coords( + info, picks, layout=None, ignore_overlap=False, to_sphere=True, sphere=None +): + """Guess the E/MEG layout and return appropriate topomap coordinates. + + Parameters + ---------- + %(info_not_none)s + picks : str | list | slice | None + None will choose all channels. + layout : None | instance of Layout + Enforce using a specific layout. With None, a new map is generated + and a layout is chosen based on the channels in the picks + parameter. + sphere : array-like | str + Definition of the head sphere. + + Returns + ------- + coords : array, shape = (n_chs, 2) + 2 dimensional coordinates for each sensor for a topomap plot. + """ + picks = _picks_to_idx(info, picks, "all", exclude=(), allow_empty=False) + + if layout is not None: + chs = [info["chs"][i] for i in picks] + pos = [layout.pos[layout.names.index(ch["ch_name"])] for ch in chs] + pos = np.asarray(pos) + else: + pos = _auto_topomap_coords( + info, + picks, + ignore_overlap=ignore_overlap, + to_sphere=to_sphere, + sphere=sphere, + ) + + return pos + + +@fill_doc +def _auto_topomap_coords(info, picks, ignore_overlap, to_sphere, sphere): + """Make a 2 dimensional sensor map from sensor positions in an info dict. + + The default is to use the electrode locations. The fallback option is to + attempt using digitization points of kind FIFFV_POINT_EEG. This only works + with EEG and requires an equal number of digitization points and sensors. + + Parameters + ---------- + %(info_not_none)s + picks : list | str | slice | None + None will pick all channels. + ignore_overlap : bool + Whether to ignore overlapping positions in the layout. If False and + positions overlap, an error is thrown. + to_sphere : bool + If True, the radial distance of spherical coordinates is ignored, in + effect fitting the xyz-coordinates to a sphere. + sphere : array-like | str + The head sphere definition. + + Returns + ------- + locs : array, shape = (n_sensors, 2) + An array of positions of the 2 dimensional map. + """ + sphere = _check_sphere(sphere, info) + logger.debug(f"Generating coords using: {sphere}") + + picks = _picks_to_idx(info, picks, "all", exclude=(), allow_empty=False) + chs = [info["chs"][i] for i in picks] + + # Use channel locations if available + locs3d = np.array([ch["loc"][:3] for ch in chs]) + + # If electrode locations are not available, use digitization points + if not _check_ch_locs(info=info, picks=picks): + logging.warning( + "Did not find any electrode locations (in the info " + "object), will attempt to use digitization points " + "instead. However, if digitization points do not " + "correspond to the EEG electrodes, this will lead to " + "bad results. Please verify that the sensor locations " + "in the plot are accurate." + ) + + # MEG/EOG/ECG sensors don't have digitization points; all requested + # channels must be EEG + for ch in chs: + if ch["kind"] != FIFF.FIFFV_EEG_CH: + raise ValueError( + "Cannot determine location of MEG/EOG/ECG " + "channels using digitization points." + ) + + eeg_ch_names = [ + ch["ch_name"] for ch in info["chs"] if ch["kind"] == FIFF.FIFFV_EEG_CH + ] + + # Get EEG digitization points + if info["dig"] is None or len(info["dig"]) == 0: + raise RuntimeError("No digitization points found.") + + locs3d = np.array( + [ + point["r"] + for point in info["dig"] + if point["kind"] == FIFF.FIFFV_POINT_EEG + ] + ) + + if len(locs3d) == 0: + raise RuntimeError( + "Did not find any digitization points of " + f"kind {FIFF.FIFFV_POINT_EEG} in the info." + ) + + if len(locs3d) != len(eeg_ch_names): + raise ValueError( + f"Number of EEG digitization points ({len(locs3d)}) doesn't match the " + f"number of EEG channels ({len(eeg_ch_names)})" + ) + + # We no longer center digitization points on head origin, as we work + # in head coordinates always + + # Match the digitization points with the requested + # channels. + eeg_ch_locs = dict(zip(eeg_ch_names, locs3d)) + locs3d = np.array([eeg_ch_locs[ch["ch_name"]] for ch in chs]) + + # Sometimes we can get nans + locs3d[~np.isfinite(locs3d)] = 0.0 + + # Duplicate points cause all kinds of trouble during visualization + dist = pdist(locs3d) + if len(locs3d) > 1 and np.min(dist) < 1e-10 and not ignore_overlap: + problematic_electrodes = [ + chs[elec_i]["ch_name"] + for elec_i in squareform(dist < 1e-10).any(axis=0).nonzero()[0] + ] + + raise ValueError( + "The following electrodes have overlapping positions," + " which causes problems during visualization:\n" + + ", ".join(problematic_electrodes) + ) + + if to_sphere: + # translate to sphere origin, transform/flatten Z, translate back + locs3d -= sphere[:3] + # use spherical (theta, pol) as (r, theta) for polar->cartesian + cart_coords = _cart_to_sph(locs3d) + out = _pol_to_cart(cart_coords[:, 1:][:, ::-1]) + # scale from radians to mm + out *= cart_coords[:, [0]] / (np.pi / 2.0) + out += sphere[:2] + else: + out = _pol_to_cart(_cart_to_sph(locs3d)) + return out + + +def _topo_to_sphere(pos, eegs): + """Transform xy-coordinates to sphere. + + Parameters + ---------- + pos : array-like, shape (n_channels, 2) + xy-oordinates to transform. + eegs : list of int + Indices of EEG channels that are included when calculating the sphere. + + Returns + ------- + coords : array, shape (n_channels, 3) + xyz-coordinates. + """ + xs, ys = np.array(pos).T + + sqs = np.max(np.sqrt((xs[eegs] ** 2) + (ys[eegs] ** 2))) + xs /= sqs # Shape to a sphere and normalize + ys /= sqs + + xs += 0.5 - np.mean(xs[eegs]) # Center the points + ys += 0.5 - np.mean(ys[eegs]) + + xs = xs * 2.0 - 1.0 # Values ranging from -1 to 1 + ys = ys * 2.0 - 1.0 + + rs = np.clip(np.sqrt(xs**2 + ys**2), 0.0, 1.0) + alphas = np.arccos(rs) + zs = np.sin(alphas) + return np.column_stack([xs, ys, zs]) + + +@fill_doc +def _pair_grad_sensors( + info, layout=None, topomap_coords=True, exclude="bads", raise_error=True +): + """Find the picks for pairing grad channels. + + Parameters + ---------- + %(info_not_none)s + layout : Layout | None + The layout if available. Defaults to None. + topomap_coords : bool + Return the coordinates for a topomap plot along with the picks. If + False, only picks are returned. Defaults to True. + exclude : list of str | str + List of channels to exclude. If empty, do not exclude any. + If 'bads', exclude channels in info['bads']. Defaults to 'bads'. + raise_error : bool + Whether to raise an error when no pairs are found. If False, raises a + warning. + + Returns + ------- + picks : array of int + Picks for the grad channels, ordered in pairs. + coords : array, shape = (n_grad_channels, 3) + Coordinates for a topomap plot (optional, only returned if + topomap_coords == True). + """ + # find all complete pairs of grad channels + pairs = defaultdict(list) + grad_picks = pick_types(info, meg="grad", ref_meg=False, exclude=exclude) + + _, has_vv_grad, *_, has_neuromag_122_grad, _ = _get_ch_info(info) + + for i in grad_picks: + ch = info["chs"][i] + name = ch["ch_name"] + if has_vv_grad and name.startswith("MEG"): + if name.endswith(("2", "3")): + key = name[-4:-1] + pairs[key].append(ch) + if has_neuromag_122_grad and name.startswith("MEG"): + key = (int(name[-3:]) - 1) // 2 + pairs[key].append(ch) + + pairs = [p for p in pairs.values() if len(p) == 2] + if len(pairs) == 0: + if raise_error: + raise ValueError("No 'grad' channel pairs found.") + else: + warn("No 'grad' channel pairs found.") + return list() + + # find the picks corresponding to the grad channels + grad_chs = sum(pairs, []) + ch_names = info["ch_names"] + picks = [ch_names.index(c["ch_name"]) for c in grad_chs] + + if topomap_coords: + shape = (len(pairs), 2, -1) + coords = _find_topomap_coords(info, picks, layout).reshape(shape).mean(axis=1) + return picks, coords + else: + return picks + + +def _merge_ch_data(data, ch_type, names, method="rms", *, modality="opm"): + """Merge data from channel pairs. + + Parameters + ---------- + data : array, shape = (n_channels, ..., n_times) + Data for channels, ordered in pairs. + ch_type : str + Channel type. + names : list + List of channel names. + method : str + Can be 'rms' or 'mean'. + modality : str + The modality of the data, either 'grad', 'fnirs', or 'opm' + + Returns + ------- + data : array, shape = (n_channels / 2, ..., n_times) + The root mean square or mean for each pair. + names : list + List of channel names. + """ + if ch_type == "grad": + data = _merge_grad_data(data, method) + elif modality == "fnirs" or ch_type in _FNIRS_CH_TYPES_SPLIT: + data, names = _merge_nirs_data(data, names) + elif modality == "opm" and ch_type == "mag": + data, names = _merge_opm_data(data, names) + else: + raise ValueError(f"Unknown modality {modality} for channel type {ch_type}") + + return data, names + + +def _merge_grad_data(data, method="rms"): + """Merge data from channel pairs using the RMS or mean. + + Parameters + ---------- + data : array, shape = (n_channels, ..., n_times) + Data for channels, ordered in pairs. + method : str + Can be 'rms' or 'mean'. + + Returns + ------- + data : array, shape = (n_channels / 2, ..., n_times) + The root mean square or mean for each pair. + """ + data, orig_shape = data.reshape((len(data) // 2, 2, -1)), data.shape + if method == "mean": + data = np.mean(data, axis=1) + elif method == "rms": + data = np.sqrt(np.sum(data**2, axis=1) / 2) + else: + raise ValueError(f'method must be "rms" or "mean", got {method}.') + return data.reshape(data.shape[:1] + orig_shape[1:]) + + +def _merge_nirs_data(data, merged_names): + """Merge data from multiple nirs channel using the mean. + + Channel names that have an x in them will be merged. The first channel in + the name is replaced with the mean of all listed channels. The other + channels are removed. + + Parameters + ---------- + data : array, shape = (n_channels, ..., n_times) + Data for channels. + merged_names : list + List of strings containing the channel names. Channels that are to be + merged contain an x between them. + + Returns + ------- + data : array + Data for channels with requested channels merged. Channels used in the + merge are removed from the array. + """ + to_remove = np.empty(0, dtype=np.int32) + for idx, ch in enumerate(merged_names): + if "x" in ch: + indices = np.empty(0, dtype=np.int32) + channels = ch.split("x") + for sub_ch in channels[1:]: + indices = np.append(indices, merged_names.index(sub_ch)) + data[idx] = np.mean(data[np.append(idx, indices)], axis=0) + to_remove = np.append(to_remove, indices) + to_remove = np.unique(to_remove) + for rem in sorted(to_remove, reverse=True): + del merged_names[rem] + data = np.delete(data, rem, 0) + return data, merged_names + + +def _merge_opm_data(data, merged_names): + """Merge data from multiple opm channel by just using the radial component. + + Channel names that end in "MERGE_REMOVE" (ie non-radial channels) will be + removed. Only the radial channel is kept. + + Parameters + ---------- + data : array, shape = (n_channels, ..., n_times) + Data for channels. + merged_names : list + List of strings containing the channel names. Channels that are to be + removed end in "MERGE_REMOVE". + + Returns + ------- + data : array + Data for channels with requested channels merged. Channels used in the + merge are removed from the array. + """ + to_remove = np.empty(0, dtype=np.int32) + for idx, ch in enumerate(merged_names): + if ch.endswith("MERGE-REMOVE"): + to_remove = np.append(to_remove, idx) + to_remove = np.unique(to_remove) + for rem in sorted(to_remove, reverse=True): + del merged_names[rem] + data = np.delete(data, to_remove, axis=0) + return data, merged_names + + +def generate_2d_layout( + xy, + w=0.07, + h=0.05, + pad=0.02, + ch_names=None, + ch_indices=None, + name="ecog", + bg_image=None, + normalize=True, +): + """Generate a custom 2D layout from xy points. + + Generates a 2-D layout for plotting with plot_topo methods and + functions. XY points will be normalized between 0 and 1, where + normalization extremes will be either the min/max of xy, or + the width/height of bg_image. + + Parameters + ---------- + xy : ndarray, shape (N, 2) + The xy coordinates of sensor locations. + w : float + The width of each sensor's axis (between 0 and 1). + h : float + The height of each sensor's axis (between 0 and 1). + pad : float + Portion of the box to reserve for padding. The value can range between + 0.0 (boxes will touch, default) to 1.0 (boxes consist of only padding). + ch_names : list + The names of each channel. Must be a list of strings, with one + string per channel. + ch_indices : list + Index of each channel - must be a collection of unique integers, + one index per channel. + name : str + The name of this layout type. + bg_image : path-like | ndarray + The image over which sensor axes will be plotted. Either a path to an + image file, or an array that can be plotted with plt.imshow. If + provided, xy points will be normalized by the width/height of this + image. If not, xy points will be normalized by their own min/max. + normalize : bool + Whether to normalize the coordinates to run from 0 to 1. Defaults to + True. + + Returns + ------- + layout : Layout + A Layout object that can be plotted with plot_topo + functions and methods. + + See Also + -------- + make_eeg_layout, make_grid_layout + + Notes + ----- + .. versionadded:: 0.9.0 + """ + import matplotlib.pyplot as plt + + if ch_indices is None: + ch_indices = np.arange(xy.shape[0]) + if ch_names is None: + ch_names = list(map(str, ch_indices)) + + if len(ch_names) != len(ch_indices): + raise ValueError("# channel names and indices must be equal") + if len(ch_names) != len(xy): + raise ValueError("# channel names and xy vals must be equal") + + x, y = xy.copy().astype(float).T + + # Normalize xy to 0-1 + if bg_image is not None: + # Normalize by image dimensions + img = plt.imread(bg_image) if isinstance(bg_image, str) else bg_image + x /= img.shape[1] + y /= img.shape[0] + elif normalize: + # Normalize x and y by their maxes + for i_dim in [x, y]: + i_dim -= i_dim.min(0) + i_dim /= i_dim.max(0) - i_dim.min(0) + + # Create box and pos variable + box = _box_size(np.vstack([x, y]).T, padding=pad) + box = (0, 0, box[0], box[1]) + w, h = (np.array([i] * x.shape[0]) for i in [w, h]) + loc_params = np.vstack([x, y, w, h]).T + + layout = Layout(box, loc_params, ch_names, ch_indices, name) + return layout diff --git a/mne-python/source/mne/channels/montage.py b/mne-python/source/mne/channels/montage.py new file mode 100644 index 0000000000000000000000000000000000000000..2f84b425fc0eeaffd57e7c3316566abb80a77fc7 --- /dev/null +++ b/mne-python/source/mne/channels/montage.py @@ -0,0 +1,2021 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op +import re +from collections import OrderedDict +from copy import deepcopy +from dataclasses import dataclass +from pathlib import Path + +import numpy as np + +from .._fiff._digitization import ( + _coord_frame_const, + _count_points_by_type, + _ensure_fiducials_head, + _format_dig_points, + _get_data_as_dict_from_dig, + _get_dig_eeg, + _get_fid_coords, + _make_dig_points, + _read_dig_fif, + write_dig, +) +from .._fiff.constants import CHANNEL_LOC_ALIASES, FIFF +from .._fiff.meas_info import create_info +from .._fiff.open import fiff_open +from .._fiff.pick import _picks_to_idx, channel_type, pick_types +from .._freesurfer import get_mni_fiducials +from ..defaults import HEAD_SIZE_DEFAULT +from ..fixes import _reshape_view +from ..transforms import ( + Transform, + _ensure_trans, + _fit_matched_points, + _frame_to_str, + _quat_to_affine, + _sph_to_cart, + _topo_to_sph, + _verbose_frames, + apply_trans, + get_ras_to_neuromag_trans, +) +from ..utils import ( + _check_fname, + _check_option, + _on_missing, + _pl, + _validate_type, + check_fname, + copy_function_doc_to_method_doc, + fill_doc, + legacy, + verbose, + warn, +) +from ..utils.docs import docdict +from ..viz import plot_montage +from ._dig_montage_utils import ( + _parse_brainvision_dig_montage, + _read_dig_montage_curry, + _read_dig_montage_egi, +) + + +@dataclass +class _BuiltinStandardMontage: + name: str + description: str + + +_BUILTIN_STANDARD_MONTAGES = [ + _BuiltinStandardMontage( + name="standard_1005", + description="Electrodes are named and positioned according to the " + "international 10-05 system (343+3 locations)", + ), + _BuiltinStandardMontage( + name="standard_1020", + description="Electrodes are named and positioned according to the " + "international 10-20 system (94+3 locations)", + ), + _BuiltinStandardMontage( + name="standard_alphabetic", + description="Electrodes are named with LETTER-NUMBER combinations " + "(A1, B2, F4, …) (65+3 locations)", + ), + _BuiltinStandardMontage( + name="standard_postfixed", + description="Electrodes are named according to the international " + "10-20 system using postfixes for intermediate positions " + "(100+3 locations)", + ), + _BuiltinStandardMontage( + name="standard_prefixed", + description="Electrodes are named according to the international " + "10-20 system using prefixes for intermediate positions " + "(74+3 locations)", + ), + _BuiltinStandardMontage( + name="standard_primed", + description="Electrodes are named according to the international " + "10-20 system using prime marks (' and '') for " + "intermediate positions (100+3 locations)", + ), + _BuiltinStandardMontage( + name="biosemi16", + description="BioSemi cap with 16 electrodes (16+3 locations)", + ), + _BuiltinStandardMontage( + name="biosemi32", + description="BioSemi cap with 32 electrodes (32+3 locations)", + ), + _BuiltinStandardMontage( + name="biosemi64", + description="BioSemi cap with 64 electrodes (64+3 locations)", + ), + _BuiltinStandardMontage( + name="biosemi128", + description="BioSemi cap with 128 electrodes (128+3 locations)", + ), + _BuiltinStandardMontage( + name="biosemi160", + description="BioSemi cap with 160 electrodes (160+3 locations)", + ), + _BuiltinStandardMontage( + name="biosemi256", + description="BioSemi cap with 256 electrodes (256+3 locations)", + ), + _BuiltinStandardMontage( + name="easycap-M1", + description="EasyCap with 10-05 electrode names (74 locations)", + ), + _BuiltinStandardMontage( + name="easycap-M10", + description="EasyCap with numbered electrodes (61 locations)", + ), + _BuiltinStandardMontage( + name="easycap-M43", + description="EasyCap with numbered electrodes (64 locations)", + ), + _BuiltinStandardMontage( + name="EGI_256", + description="Geodesic Sensor Net (256 locations)", + ), + _BuiltinStandardMontage( + name="GSN-HydroCel-32", + description="HydroCel Geodesic Sensor Net and Cz (33+3 locations)", + ), + _BuiltinStandardMontage( + name="GSN-HydroCel-64_1.0", + description="HydroCel Geodesic Sensor Net (64+3 locations)", + ), + _BuiltinStandardMontage( + name="GSN-HydroCel-65_1.0", + description="HydroCel Geodesic Sensor Net and Cz (65+3 locations)", + ), + _BuiltinStandardMontage( + name="GSN-HydroCel-128", + description="HydroCel Geodesic Sensor Net (128+3 locations)", + ), + _BuiltinStandardMontage( + name="GSN-HydroCel-129", + description="HydroCel Geodesic Sensor Net and Cz (129+3 locations)", + ), + _BuiltinStandardMontage( + name="GSN-HydroCel-256", + description="HydroCel Geodesic Sensor Net (256+3 locations)", + ), + _BuiltinStandardMontage( + name="GSN-HydroCel-257", + description="HydroCel Geodesic Sensor Net and Cz (257+3 locations)", + ), + _BuiltinStandardMontage( + name="mgh60", + description="The (older) 60-channel cap used at MGH (60+3 locations)", + ), + _BuiltinStandardMontage( + name="mgh70", + description="The (newer) 70-channel BrainVision cap used at MGH " + "(70+3 locations)", + ), + _BuiltinStandardMontage( + name="artinis-octamon", + description="Artinis OctaMon fNIRS (8 sources, 2 detectors)", + ), + _BuiltinStandardMontage( + name="artinis-brite23", + description="Artinis Brite23 fNIRS (11 sources, 7 detectors)", + ), + _BuiltinStandardMontage( + name="brainproducts-RNP-BA-128", + description="Brain Products with 10-10 electrode names (128 channels)", + ), +] + + +# We could eventually add mne/data/helmets/Kernel_Flux_ch_pos.txt if we added +# the normals and deduplicate... but can wait until someone has a use case! +_MEG_CANONICAL_FILES = { + "neuromag": "neuromag306.csv", + "ctf151": "ctf151.csv", + "ctf275": "ctf275.csv", +} + + +def _check_get_coord_frame(dig): + dig_coord_frames = sorted(set(d["coord_frame"] for d in dig)) + if len(dig_coord_frames) != 1: + raise RuntimeError( + "Only a single coordinate frame in dig is supported, got " + f"{dig_coord_frames}" + ) + return _frame_to_str[dig_coord_frames.pop()] if dig_coord_frames else None + + +def get_builtin_montages(*, descriptions=False): + """Get a list of all standard montages shipping with MNE-Python. + + The names of the montages can be passed to :func:`make_standard_montage`. + + Parameters + ---------- + descriptions : bool + Whether to return not only the montage names, but also their + corresponding descriptions. If ``True``, a list of tuples is returned, + where the first tuple element is the montage name and the second is + the montage description. If ``False`` (default), only the names are + returned. + + .. versionadded:: 1.1 + + Returns + ------- + montages : list of str | list of tuple + If ``descriptions=False``, the names of all builtin montages that can + be used by :func:`make_standard_montage`. + + If ``descriptions=True``, a list of tuples ``(name, description)``. + """ + if descriptions: + return [(m.name, m.description) for m in _BUILTIN_STANDARD_MONTAGES] + else: + return [m.name for m in _BUILTIN_STANDARD_MONTAGES] + + +def make_dig_montage( + ch_pos=None, + nasion=None, + lpa=None, + rpa=None, + hsp=None, + hpi=None, + coord_frame="unknown", +): + r"""Make montage from arrays. + + Parameters + ---------- + ch_pos : dict | None + Dictionary of channel positions. Keys are channel names and values + are 3D coordinates - array of shape (3,) - in native digitizer space + in m. + nasion : None | array, shape (3,) + The position of the nasion fiducial point. + This point is assumed to be in the native digitizer space in m. + lpa : None | array, shape (3,) + The position of the left periauricular fiducial point. + This point is assumed to be in the native digitizer space in m. + rpa : None | array, shape (3,) + The position of the right periauricular fiducial point. + This point is assumed to be in the native digitizer space in m. + hsp : None | array, shape (n_points, 3) + This corresponds to an array of positions of the headshape points in + 3d. These points are assumed to be in the native digitizer space in m. + hpi : None | array, shape (n_hpi, 3) + This corresponds to an array of HPI points in the native digitizer + space. They only necessary if computation of a ``compute_dev_head_t`` + is True. + coord_frame : str + The coordinate frame of the points. Usually this is ``'unknown'`` + for native digitizer space. + Other valid values are: ``'head'``, ``'meg'``, ``'mri'``, + ``'mri_voxel'``, ``'mni_tal'``, ``'ras'``, ``'fs_tal'``, + ``'ctf_head'``, and ``'ctf_meg'``. + + .. note:: + For custom montages without fiducials, this parameter must be set + to ``'head'``. + + Returns + ------- + montage : instance of DigMontage + The montage. + + See Also + -------- + DigMontage + read_dig_captrak + read_dig_egi + read_dig_fif + read_dig_localite + read_dig_polhemus_isotrak + """ + _validate_type(ch_pos, (dict, None), "ch_pos") + if ch_pos is None: + ch_names = None + else: + ch_names = list(ch_pos) + dig = _make_dig_points( + nasion=nasion, + lpa=lpa, + rpa=rpa, + hpi=hpi, + extra_points=hsp, + dig_ch_pos=ch_pos, + coord_frame=coord_frame, + ) + + return DigMontage(dig=dig, ch_names=ch_names) + + +class DigMontage: + """Montage for digitized electrode and headshape position data. + + .. warning:: Montages are typically created using one of the helper + functions in the ``See Also`` section below instead of + instantiating this class directly. + + Parameters + ---------- + dig : list of dict + The object containing all the dig points. + ch_names : list of str + The names of the EEG channels. + + See Also + -------- + read_dig_captrak + read_dig_egi + read_dig_fif + read_dig_hpts + read_dig_localite + read_dig_polhemus_isotrak + make_dig_montage + + Notes + ----- + .. versionadded:: 0.9.0 + """ + + def __init__(self, *, dig=None, ch_names=None): + dig = list() if dig is None else dig + _validate_type(item=dig, types=list, item_name="dig") + ch_names = list() if ch_names is None else ch_names + n_eeg = sum([1 for d in dig if d["kind"] == FIFF.FIFFV_POINT_EEG]) + if n_eeg != len(ch_names): + raise ValueError( + f"The number of EEG channels ({n_eeg}) does not match the number" + f" of channel names provided ({len(ch_names)})" + ) + + self.dig = dig + self.ch_names = ch_names + + def __repr__(self): + """Return string representation.""" + n_points = _count_points_by_type(self.dig) + return ( + "" + ).format(**n_points) + + @copy_function_doc_to_method_doc(plot_montage) + def plot( + self, + *, + scale=1.0, + show_names=True, + kind="topomap", + show=True, + sphere=None, + axes=None, + verbose=None, + ): + return plot_montage( + self, + scale=scale, + show_names=show_names, + kind=kind, + show=show, + sphere=sphere, + axes=axes, + ) + + @verbose + def rename_channels( + self, mapping, allow_duplicates=False, *, on_missing="raise", verbose=None + ): + """Rename the channels. + + Parameters + ---------- + %(mapping_rename_channels_duplicates)s + %(on_missing_ch_names)s + + .. versionadded:: 1.11.0 + %(verbose)s + + Returns + ------- + inst : instance of DigMontage + The instance. Operates in-place. + """ + from .channels import rename_channels + + temp_info = create_info(list(self._get_ch_pos()), 1000.0, "eeg") + rename_channels(temp_info, mapping, allow_duplicates, on_missing=on_missing) + self.ch_names = temp_info["ch_names"] + return self + + @verbose + def save(self, fname, *, overwrite=False, verbose=None): + """Save digitization points to FIF. + + Parameters + ---------- + fname : path-like + The filename to use. Should end in ``-dig.fif`` or ``-dig.fif.gz``. + %(overwrite)s + %(verbose)s + + See Also + -------- + mne.channels.read_dig_fif + + Notes + ----- + .. versionchanged:: 1.9 + Added support for saving the associated channel names. + """ + fname = _check_fname(fname, overwrite=overwrite) + check_fname(fname, "montage", ("-dig.fif", "-dig.fif.gz")) + coord_frame = _check_get_coord_frame(self.dig) + write_dig( + fname, self.dig, coord_frame, overwrite=overwrite, ch_names=self.ch_names + ) + + def __iadd__(self, other): + """Add two DigMontages in place. + + Notes + ----- + Two DigMontages can only be added if there are no duplicated ch_names + and if fiducials are present they should share the same coordinate + system and location values. + """ + + def is_fid_defined(fid): + return not (fid.nasion is None and fid.lpa is None and fid.rpa is None) + + # Check for none duplicated ch_names + ch_names_intersection = set(self.ch_names).intersection(other.ch_names) + if ch_names_intersection: + raise RuntimeError( + ( + "Cannot add two DigMontage objects if they contain duplicated" + " channel names. Duplicated channel(s) found: {}." + ).format(", ".join([f"{v!r}" for v in sorted(ch_names_intersection)])) + ) + + # Check for unique matching fiducials + self_fid, self_coord = _get_fid_coords(self.dig) + other_fid, other_coord = _get_fid_coords(other.dig) + + if is_fid_defined(self_fid) and is_fid_defined(other_fid): + if self_coord != other_coord: + raise RuntimeError( + "Cannot add two DigMontage objects if " + "fiducial locations are not in the same " + "coordinate system." + ) + + for kk in self_fid: + if not np.array_equal(self_fid[kk], other_fid[kk]): + raise RuntimeError( + "Cannot add two DigMontage objects if " + "fiducial locations do not match " + f"({kk})" + ) + + # keep self + self.dig = _format_dig_points( + self.dig + + [d for d in other.dig if d["kind"] != FIFF.FIFFV_POINT_CARDINAL] + ) + else: + self.dig = _format_dig_points(self.dig + other.dig) + + self.ch_names += other.ch_names + return self + + def copy(self): + """Copy the DigMontage object. + + Returns + ------- + dig : instance of DigMontage + The copied DigMontage instance. + """ + return deepcopy(self) + + def __add__(self, other): + """Add two DigMontages.""" + out = self.copy() + out += other + return out + + def __eq__(self, other): + """Compare different DigMontage objects for equality. + + Returns + ------- + Boolean output from comparison of .dig + """ + return self.dig == other.dig and self.ch_names == other.ch_names + + def _get_ch_pos(self): + pos = [d["r"] for d in _get_dig_eeg(self.dig)] + assert len(self.ch_names) == len(pos) + return OrderedDict(zip(self.ch_names, pos)) + + def _get_dig_names(self): + NAMED_KIND = (FIFF.FIFFV_POINT_EEG,) + is_eeg = np.array([d["kind"] in NAMED_KIND for d in self.dig]) + assert len(self.ch_names) == is_eeg.sum() + dig_names = [None] * len(self.dig) + for ch_name_idx, dig_idx in enumerate(np.where(is_eeg)[0]): + dig_names[dig_idx] = self.ch_names[ch_name_idx] + + return dig_names + + def get_positions(self): + """Get all channel and fiducial positions. + + Returns + ------- + positions : dict + A dictionary of the positions for channels (``ch_pos``), + coordinate frame (``coord_frame``), nasion (``nasion``), + left preauricular point (``lpa``), + right preauricular point (``rpa``), + Head Shape Polhemus (``hsp``), and + Head Position Indicator(``hpi``). + E.g.:: + + { + 'ch_pos': {'EEG061': [0, 0, 0]}, + 'nasion': [0, 0, 1], + 'coord_frame': 'mni_tal', + 'lpa': [0, 1, 0], + 'rpa': [1, 0, 0], + 'hsp': None, + 'hpi': None + } + """ + # get channel positions as dict + ch_pos = self._get_ch_pos() + + # get coordframe and fiducial coordinates + montage_bunch = _get_data_as_dict_from_dig(self.dig) + coord_frame = _frame_to_str.get(montage_bunch.coord_frame) + + # return dictionary + positions = dict( + ch_pos=ch_pos, + coord_frame=coord_frame, + nasion=montage_bunch.nasion, + lpa=montage_bunch.lpa, + rpa=montage_bunch.rpa, + hsp=montage_bunch.hsp, + hpi=montage_bunch.hpi, + ) + return positions + + @verbose + def apply_trans(self, trans, verbose=None): + """Apply a transformation matrix to the montage. + + Parameters + ---------- + trans : instance of mne.transforms.Transform + The transformation matrix to be applied. + %(verbose)s + """ + _validate_type(trans, Transform, "trans") + coord_frame = self.get_positions()["coord_frame"] + trans = _ensure_trans(trans, fro=coord_frame, to=trans["to"]) + for d in self.dig: + d["r"] = apply_trans(trans, d["r"]) + d["coord_frame"] = trans["to"] + + @verbose + def add_estimated_fiducials(self, subject, subjects_dir=None, verbose=None): + """Estimate fiducials based on FreeSurfer ``fsaverage`` subject. + + This takes a montage with the ``mri`` coordinate frame, + corresponding to the FreeSurfer RAS (xyz in the volume) T1w + image of the specific subject. It will call + :func:`mne.coreg.get_mni_fiducials` to estimate LPA, RPA and + Nasion fiducial points. + + Parameters + ---------- + %(subject)s + %(subjects_dir)s + %(verbose)s + + Returns + ------- + inst : instance of DigMontage + The instance, modified in-place. + + See Also + -------- + :ref:`tut-source-alignment` + + Notes + ----- + Since MNE uses the FIF data structure, it relies on the ``head`` + coordinate frame. Any coordinate frame can be transformed + to ``head`` if the fiducials (i.e. LPA, RPA and Nasion) are + defined. One can use this function to estimate those fiducials + and then use ``mne.channels.compute_native_head_t(montage)`` + to get the head <-> MRI transform. + """ + # get coordframe and fiducial coordinates + montage_bunch = _get_data_as_dict_from_dig(self.dig) + + # get the coordinate frame and check that it's MRI + if montage_bunch.coord_frame != FIFF.FIFFV_COORD_MRI: + raise RuntimeError( + f'Montage should be in the "mri" coordinate frame ' + f"to use `add_estimated_fiducials`. The current coordinate " + f"frame is {montage_bunch.coord_frame}" + ) + + # estimate LPA, nasion, RPA from FreeSurfer fsaverage + fids_mri = list(get_mni_fiducials(subject, subjects_dir)) + + # add those digpoints to front of montage + self.dig = fids_mri + self.dig + return self + + @verbose + def add_mni_fiducials(self, subjects_dir=None, verbose=None): + """Add fiducials to a montage in MNI space. + + Parameters + ---------- + %(subjects_dir)s + %(verbose)s + + Returns + ------- + inst : instance of DigMontage + The instance, modified in-place. + + Notes + ----- + ``fsaverage`` is in MNI space and so its fiducials can be + added to a montage in "mni_tal". MNI is an ACPC-aligned + coordinate system (the posterior commissure is the origin) + so since BIDS requires channel locations for ECoG, sEEG and + DBS to be in ACPC space, this function can be used to allow + those coordinate to be transformed to "head" space (origin + between LPA and RPA). + """ + montage_bunch = _get_data_as_dict_from_dig(self.dig) + + # get the coordinate frame and check that it's MNI TAL + if montage_bunch.coord_frame != FIFF.FIFFV_MNE_COORD_MNI_TAL: + raise RuntimeError( + f'Montage should be in the "mni_tal" coordinate frame ' + f"to use `add_estimated_fiducials`. The current coordinate " + f"frame is {montage_bunch.coord_frame}" + ) + + fids_mni = get_mni_fiducials("fsaverage", subjects_dir) + for fid in fids_mni: + # "mri" and "mni_tal" are equivalent for fsaverage + assert fid["coord_frame"] == FIFF.FIFFV_COORD_MRI + fid["coord_frame"] = FIFF.FIFFV_MNE_COORD_MNI_TAL + self.dig = fids_mni + self.dig + return self + + @verbose + def remove_fiducials(self, verbose=None): + """Remove the fiducial points from a montage. + + Parameters + ---------- + %(verbose)s + + Returns + ------- + inst : instance of DigMontage + The instance, modified in-place. + + Notes + ----- + MNE will transform a montage to the internal "head" coordinate + frame if the fiducials are present. Under most circumstances, this + is ideal as it standardizes the coordinate frame for things like + plotting. However, in some circumstances, such as saving a ``raw`` + with intracranial data to BIDS format, the coordinate frame + should not be changed by removing fiducials. + """ + for d in self.dig.copy(): + if d["kind"] == FIFF.FIFFV_POINT_CARDINAL: + self.dig.remove(d) + return self + + +VALID_SCALES = dict(mm=1e-3, cm=1e-2, m=1) + + +def _check_unit_and_get_scaling(unit): + _check_option("unit", unit, sorted(VALID_SCALES.keys())) + return VALID_SCALES[unit] + + +def transform_to_head(montage): + """Transform a DigMontage object into head coordinate. + + Parameters + ---------- + montage : instance of DigMontage + The montage. + + Returns + ------- + montage : instance of DigMontage + A copy of the montage after transforming the points to head + coordinate system. + + Notes + ----- + This function requires that the LPA, RPA and Nasion fiducial + points are available. If they are not, they will be added based by + projecting the fiducials onto a sphere with radius equal to the average + distance of each point to the origin (in the given coordinate frame). + + This function assumes that all fiducial points are in the same coordinate + frame (e.g. 'unknown') and it will convert all the point in this coordinate + system to Neuromag head coordinate system. + + .. versionchanged:: 1.2 + Fiducial points will be added automatically if the montage does not + have them. + """ + # Get fiducial points and their coord_frame + native_head_t = compute_native_head_t(montage) + montage = montage.copy() # to avoid inplace modification + if native_head_t["from"] != FIFF.FIFFV_COORD_HEAD: + for d in montage.dig: + if d["coord_frame"] == native_head_t["from"]: + d["r"] = apply_trans(native_head_t, d["r"]) + d["coord_frame"] = FIFF.FIFFV_COORD_HEAD + _ensure_fiducials_head(montage.dig) + return montage + + +@legacy(alt="read_dig_curry()") +def read_dig_dat(fname): + r"""Read electrode positions from a ``*.dat`` file. + + .. Warning:: + This function was implemented based on ``*.dat`` files available from + `Compumedics `__ and might not work + as expected with novel files. If it does not read your files correctly + please contact the MNE-Python developers. + + Parameters + ---------- + fname : path-like + File from which to read electrode locations. + + Returns + ------- + montage : DigMontage + The montage. + + See Also + -------- + read_dig_captrak + read_dig_curry + read_dig_egi + read_dig_fif + read_dig_hpts + read_dig_localite + read_dig_polhemus_isotrak + make_dig_montage + + Notes + ----- + ``*.dat`` files are plain text files and can be inspected and amended with + a plain text editor. + """ + from ._standard_montage_utils import _check_dupes_odict + + fname = _check_fname(fname, overwrite="read", must_exist=True) + + with open(fname) as fid: + lines = fid.readlines() + + ch_names, poss = list(), list() + nasion = lpa = rpa = None + for i, line in enumerate(lines): + items = line.split() + if not items: + continue + elif len(items) != 5: + raise ValueError( + f"Error reading {fname}, line {i} has unexpected number of entries:\n" + f"{line.rstrip()}" + ) + num = items[1] + if num == "67": + continue # centroid + pos = np.array([float(item) for item in items[2:]]) + if num == "78": + nasion = pos + elif num == "76": + lpa = pos + elif num == "82": + rpa = pos + else: + ch_names.append(items[0]) + poss.append(pos) + electrodes = _check_dupes_odict(ch_names, poss) + return make_dig_montage(electrodes, nasion, lpa, rpa) + + +@verbose +def read_dig_fif(fname, *, verbose=None): + r"""Read digitized points from a .fif file. + + Parameters + ---------- + fname : path-like + FIF file from which to read digitization locations. + %(verbose)s + + Returns + ------- + montage : instance of DigMontage + The montage. + + See Also + -------- + DigMontage + read_dig_egi + read_dig_captrak + read_dig_curry + read_dig_polhemus_isotrak + read_dig_hpts + read_dig_localite + make_dig_montage + + Notes + ----- + .. versionchanged:: 1.9 + Added support for reading the associated channel names, if present. + + In some files, electrode names are not present (e.g., in older files). + For those files, the channel names are defined with the convention from + VectorView systems (EEG001, EEG002, etc.). + """ + check_fname(fname, "montage", ("-dig.fif", "-dig.fif.gz")) + fname = _check_fname(fname=fname, must_exist=True, overwrite="read") + # Load the dig data + f, tree = fiff_open(fname)[:2] + with f as fid: + dig, ch_names = _read_dig_fif(fid, tree, return_ch_names=True) + + if ch_names is None: # backward compat from when we didn't save the names + ch_names = [] + for d in dig: + if d["kind"] == FIFF.FIFFV_POINT_EEG: + ch_names.append(f"EEG{d['ident']:03d}") + + montage = DigMontage(dig=dig, ch_names=ch_names) + return montage + + +def read_dig_hpts(fname, unit="mm"): + """Read historical ``.hpts`` MNE-C files. + + Parameters + ---------- + fname : path-like + The filepath of .hpts file. + unit : ``'m'`` | ``'cm'`` | ``'mm'`` + Unit of the positions. Defaults to ``'mm'``. + + Returns + ------- + montage : instance of DigMontage + The montage. + + See Also + -------- + DigMontage + read_dig_captrak + read_dig_curry + read_dig_egi + read_dig_fif + read_dig_localite + read_dig_polhemus_isotrak + make_dig_montage + + Notes + ----- + The hpts format digitzer data file may contain comment lines starting + with the pound sign (#) and data lines of the form:: + + <*category*> <*identifier*> <*x/mm*> <*y/mm*> <*z/mm*> + + where: + + ``<*category*>`` + defines the type of points. Allowed categories are: ``hpi``, + ``cardinal`` (fiducial), ``eeg``, and ``extra`` corresponding to + head-position indicator coil locations, cardinal landmarks, EEG + electrode locations, and additional head surface points, + respectively. + + ``<*identifier*>`` + identifies the point. The identifiers are usually sequential + numbers. For cardinal landmarks, 1 = left auricular point, + 2 = nasion, and 3 = right auricular point. For EEG electrodes, + identifier = 0 signifies the reference electrode. + + ``<*x/mm*> , <*y/mm*> , <*z/mm*>`` + Location of the point, usually in the head coordinate system + in millimeters. If your points are in [m] then unit parameter can + be changed. + + For example:: + + cardinal 2 -5.6729 -12.3873 -30.3671 + cardinal 1 -37.6782 -10.4957 91.5228 + cardinal 3 -131.3127 9.3976 -22.2363 + hpi 1 -30.4493 -11.8450 83.3601 + hpi 2 -122.5353 9.2232 -28.6828 + hpi 3 -6.8518 -47.0697 -37.0829 + hpi 4 7.3744 -50.6297 -12.1376 + hpi 5 -33.4264 -43.7352 -57.7756 + eeg FP1 3.8676 -77.0439 -13.0212 + eeg FP2 -31.9297 -70.6852 -57.4881 + eeg F7 -6.1042 -68.2969 45.4939 + ... + """ + from ._standard_montage_utils import _str, _str_names + + fname = _check_fname(fname, overwrite="read", must_exist=True) + _scale = _check_unit_and_get_scaling(unit) + + out = np.genfromtxt(fname, comments="#", dtype=(_str, _str, "f8", "f8", "f8")) + kind, label = _str_names(out["f0"]), _str_names(out["f1"]) + kind = [k.lower() for k in kind] + xyz = np.array([out[f"f{ii}"] for ii in range(2, 5)]).T + xyz *= _scale + del _scale + fid_idx_to_label = {"1": "lpa", "2": "nasion", "3": "rpa"} + fid = { + fid_idx_to_label[label[ii]]: this_xyz + for ii, this_xyz in enumerate(xyz) + if kind[ii] == "cardinal" + } + ch_pos = { + label[ii]: this_xyz for ii, this_xyz in enumerate(xyz) if kind[ii] == "eeg" + } + hpi = np.array([this_xyz for ii, this_xyz in enumerate(xyz) if kind[ii] == "hpi"]) + hpi = _reshape_view(hpi, (-1, 3)) # in case it's empty + hsp = np.array([this_xyz for ii, this_xyz in enumerate(xyz) if kind[ii] == "extra"]) + hsp = _reshape_view(hsp, (-1, 3)) # in case it's empty + return make_dig_montage(ch_pos=ch_pos, **fid, hpi=hpi, hsp=hsp) + + +def read_dig_egi(fname): + """Read electrode locations from EGI system. + + Parameters + ---------- + fname : path-like + EGI MFF XML coordinates file from which to read digitization locations. + + Returns + ------- + montage : instance of DigMontage + The montage. + + See Also + -------- + DigMontage + read_dig_captrak + read_dig_curry + read_dig_fif + read_dig_hpts + read_dig_localite + read_dig_polhemus_isotrak + make_dig_montage + """ + _check_fname(fname, overwrite="read", must_exist=True) + + data = _read_dig_montage_egi( + fname=fname, _scaling=1.0, _all_data_kwargs_are_none=True + ) + return make_dig_montage(**data) + + +def read_dig_captrak(fname): + """Read electrode locations from CapTrak Brain Products system. + + Parameters + ---------- + fname : path-like + BrainVision CapTrak coordinates file from which to read EEG electrode + locations. This is typically in XML format with the .bvct extension. + + Returns + ------- + montage : instance of DigMontage + The montage. + + See Also + -------- + DigMontage + read_dig_curry + read_dig_egi + read_dig_fif + read_dig_hpts + read_dig_localite + read_dig_polhemus_isotrak + make_dig_montage + """ + _check_fname(fname, overwrite="read", must_exist=True) + data = _parse_brainvision_dig_montage(fname, scale=1e-3) + + return make_dig_montage(**data) + + +def read_dig_curry(fname): + """Read electrode locations from Neuroscan Curry files. + + Parameters + ---------- + fname : path-like + A valid Curry file. + + Returns + ------- + montage : instance of DigMontage | None + The montage. + + See Also + -------- + DigMontage + read_dig_captrak + read_dig_egi + read_dig_fif + read_dig_hpts + read_dig_localite + read_dig_polhemus_isotrak + make_dig_montage + + Notes + ----- + .. versionadded:: 1.11 + """ + from ..io.curry.curry import ( + _check_curry_filename, + _extract_curry_info, + ) + + # TODO - REVIEW NEEDED + fname = _check_curry_filename(fname) + (_, _, ch_names, ch_types, ch_pos, landmarks, landmarkslabels, _, _, _, _, _, _) = ( + _extract_curry_info(fname) + ) + data = _read_dig_montage_curry( + ch_names, ch_types, ch_pos, landmarks, landmarkslabels + ) + mont = make_dig_montage(**data) if data else None + return mont + + +def read_dig_localite(fname, nasion=None, lpa=None, rpa=None): + """Read Localite .csv file. + + Parameters + ---------- + fname : path-like + File name. + nasion : str | None + Name of nasion fiducial point. + lpa : str | None + Name of left preauricular fiducial point. + rpa : str | None + Name of right preauricular fiducial point. + + Returns + ------- + montage : instance of DigMontage + The montage. + + See Also + -------- + DigMontage + read_dig_captrak + read_dig_curry + read_dig_egi + read_dig_fif + read_dig_hpts + read_dig_polhemus_isotrak + make_dig_montage + """ + ch_pos = {} + with open(fname) as f: + f.readline() # skip first row + for row in f: + _, name, x, y, z = row.split(",") + ch_pos[name] = np.array((float(x), float(y), float(z))) / 1000 + + if nasion is not None: + nasion = ch_pos.pop(nasion) + if lpa is not None: + lpa = ch_pos.pop(lpa) + if rpa is not None: + rpa = ch_pos.pop(rpa) + + return make_dig_montage(ch_pos, nasion, lpa, rpa) + + +def _get_montage_in_head(montage): + coords = set([d["coord_frame"] for d in montage.dig]) + montage = montage.copy() + if len(coords) == 1 and coords.pop() == FIFF.FIFFV_COORD_HEAD: + _ensure_fiducials_head(montage.dig) + return montage + else: + return transform_to_head(montage) + + +def _set_montage_fnirs(info, montage): + """Set the montage for fNIRS data. + + This needs to be different to electrodes as each channel has three + coordinates that need to be set. For each channel there is a source optode + location, a detector optode location, and a channel midpoint that must be + stored. This function modifies info['chs'][#]['loc'] and info['dig'] in + place. + """ + from ..preprocessing.nirs import _validate_nirs_info + + # Validate that the fNIRS info is correctly formatted + picks = _validate_nirs_info(info) + + # Modify info['chs'][#]['loc'] in place + num_ficiduals = len(montage.dig) - len(montage.ch_names) + for ch_idx in picks: + ch = info["chs"][ch_idx]["ch_name"] + source, detector = ch.split(" ")[0].split("_") + source_pos = montage.dig[montage.ch_names.index(source) + num_ficiduals]["r"] + detector_pos = montage.dig[montage.ch_names.index(detector) + num_ficiduals][ + "r" + ] + + info["chs"][ch_idx]["loc"][3:6] = source_pos + info["chs"][ch_idx]["loc"][6:9] = detector_pos + midpoint = (source_pos + detector_pos) / 2 + info["chs"][ch_idx]["loc"][:3] = midpoint + info["chs"][ch_idx]["coord_frame"] = FIFF.FIFFV_COORD_HEAD + + # Modify info['dig'] in place + with info._unlock(): + info["dig"] = montage.dig + + +@fill_doc +def _set_montage(info, montage, match_case=True, match_alias=False, on_missing="raise"): + """Apply montage to data. + + With a DigMontage, this function will replace the digitizer info with + the values specified for the particular montage. + + Usually, a montage is expected to contain the positions of all EEG + electrodes and a warning is raised when this is not the case. + + Parameters + ---------- + %(info_not_none)s + %(montage)s + %(match_case)s + %(match_alias)s + %(on_missing_montage)s + + Notes + ----- + This function will change the info variable in place. + """ + _validate_type(montage, (DigMontage, None, str), "montage") + if montage is None: + # Next line modifies info['dig'] in place + with info._unlock(): + info["dig"] = None + for ch in info["chs"]: + # Next line modifies info['chs'][#]['loc'] in place + ch["loc"] = np.full(12, np.nan) + return + if isinstance(montage, str): # load builtin montage + _check_option( + parameter="montage", + value=montage, + allowed_values=[m.name for m in _BUILTIN_STANDARD_MONTAGES], + ) + montage = make_standard_montage(montage) + + mnt_head = _get_montage_in_head(montage) + del montage + + def _backcompat_value(pos, ref_pos): + if any(np.isnan(pos)): + return np.full(6, np.nan) + else: + return np.concatenate((pos, ref_pos)) + + # get the channels in the montage in head + ch_pos = mnt_head._get_ch_pos() + + # only get the eeg, seeg, dbs, ecog channels + picks = pick_types( + info, meg=False, eeg=True, seeg=True, dbs=True, ecog=True, exclude=() + ) + non_picks = np.setdiff1d(np.arange(info["nchan"]), picks) + + # get the reference position from the loc[3:6] + chs = [info["chs"][ii] for ii in picks] + non_names = [info["chs"][ii]["ch_name"] for ii in non_picks] + del picks + ref_pos = np.array([ch["loc"][3:6] for ch in chs]) + + # keep reference location from EEG-like channels if they + # already exist and are all the same. + # Note: ref position is an empty list for fieldtrip data + if len(ref_pos) and ref_pos[0].any() and (ref_pos[0] == ref_pos).all(): + eeg_ref_pos = ref_pos[0] + # since we have an EEG reference position, we have + # to add it into the info['dig'] as EEG000 + custom_eeg_ref_dig = True + else: + refs = set(ch_pos) & {"EEG000", "REF"} + assert len(refs) <= 1 + eeg_ref_pos = np.zeros(3) if not refs else ch_pos.pop(refs.pop()) + custom_eeg_ref_dig = False + del ref_pos + + # This raises based on info being subset/superset of montage + info_names = [ch["ch_name"] for ch in chs] + dig_names = mnt_head._get_dig_names() + ref_names = [None, "EEG000", "REF"] + + if match_case: + info_names_use = info_names + dig_names_use = dig_names + non_names_use = non_names + else: + ch_pos_use = OrderedDict((name.lower(), pos) for name, pos in ch_pos.items()) + info_names_use = [name.lower() for name in info_names] + dig_names_use = [ + name.lower() if name is not None else name for name in dig_names + ] + non_names_use = [name.lower() for name in non_names] + ref_names = [name.lower() if name is not None else name for name in ref_names] + n_dup = len(ch_pos) - len(ch_pos_use) + if n_dup: + raise ValueError( + f"Cannot use match_case=False as {n_dup} montage " + "name(s) require case sensitivity" + ) + n_dup = len(info_names_use) - len(set(info_names_use)) + if n_dup: + raise ValueError( + f"Cannot use match_case=False as {n_dup} channel " + "name(s) require case sensitivity" + ) + ch_pos = ch_pos_use + del ch_pos_use + del dig_names + + # use lookup table to match unrecognized channel names to known aliases + if match_alias: + alias_dict = ( + match_alias if isinstance(match_alias, dict) else CHANNEL_LOC_ALIASES + ) + if not match_case: + alias_dict = { + ch_name.lower(): ch_alias.lower() + for ch_name, ch_alias in alias_dict.items() + } + + # excluded ch_alias not in info, to prevent unnecessary mapping and + # warning messages based on aliases. + alias_dict = {ch_name: ch_alias for ch_name, ch_alias in alias_dict.items()} + info_names_use = [ + alias_dict.get(ch_name, ch_name) for ch_name in info_names_use + ] + non_names_use = [alias_dict.get(ch_name, ch_name) for ch_name in non_names_use] + + # warn user if there is not a full overlap of montage with info_chs + missing = np.where([use not in ch_pos for use in info_names_use])[0] + if len(missing): # DigMontage is subset of info + missing_names = [info_names[ii] for ii in missing] + pl = _pl(missing) + are_is = "are" if pl else "is" + missing_coord_msg = ( + f"DigMontage is only a subset of info. There {are_is} " + f"{len(missing)} channel position{pl} not present in the " + f"DigMontage. The channel{pl} missing from the montage {are_is}:" + f"\n\n{missing_names}.\n\nConsider using inst.rename_channels to " + "match the montage nomenclature, or inst.set_channel_types if " + f"{'these' if pl else 'this'} {are_is} not {'' if pl else 'an '}" + f"EEG channel{pl}, or use the on_missing parameter if the channel " + f"position{pl} {are_is} allowed to be unknown in your analyses." + ) + _on_missing(on_missing, missing_coord_msg) + + # set ch coordinates and names from digmontage or nan coords + for ii in missing: + ch_pos[info_names_use[ii]] = [np.nan] * 3 + del info_names + + assert len(non_names_use) == len(non_names) + # There are no issues here with fNIRS being in non_names_use because + # these names are like "D1_S1_760" and the ch_pos for a fNIRS montage + # will have entries "D1" and "S1". + extra = np.where([non in ch_pos for non in non_names_use])[0] + if len(extra): + types = "/".join(sorted(set(channel_type(info, non_picks[ii]) for ii in extra))) + names = [non_names[ii] for ii in extra] + warn( + f"Not setting position{_pl(extra)} of {len(extra)} {types} " + f"channel{_pl(extra)} found in montage:\n{names}\n" + "Consider setting the channel types to be of " + f"{docdict['montage_types']} " + "using inst.set_channel_types before calling inst.set_montage, " + "or omit these channels when creating your montage." + ) + + for ch, use in zip(chs, info_names_use): + # Next line modifies info['chs'][#]['loc'] in place + if use in ch_pos: + ch["loc"][:6] = _backcompat_value(ch_pos[use], eeg_ref_pos) + ch["coord_frame"] = FIFF.FIFFV_COORD_HEAD + del ch_pos + + # XXX this is probably wrong as it uses the order from the montage + # rather than the order of our info['ch_names'] ... + digpoints = [ + mnt_head.dig[ii] + for ii, name in enumerate(dig_names_use) + if name in (info_names_use + ref_names) + ] + + # get a copy of the old dig + if info["dig"] is not None: + old_dig = info["dig"].copy() + else: + old_dig = [] + + # determine if needed to add an extra EEG REF DigPoint + if custom_eeg_ref_dig: + # ref_name = 'EEG000' if match_case else 'eeg000' + ref_dig_dict = { + "kind": FIFF.FIFFV_POINT_EEG, + "r": eeg_ref_pos, + "ident": 0, + "coord_frame": info["dig"].pop()["coord_frame"], + } + ref_dig_point = _format_dig_points([ref_dig_dict])[0] + # only append the reference dig point if it was already + # in the old dig + if ref_dig_point in old_dig: + digpoints.append(ref_dig_point) + # Next line modifies info['dig'] in place + with info._unlock(): + info["dig"] = _format_dig_points(digpoints, enforce_order=True) + del digpoints + + # TODO: Ideally we would have a check like this, but read_raw_bids for ECoG + # allows for a montage to be set without any fiducials, then silently the + # info['dig'] can end up in the MNI_TAL frame... only because in our + # conversion code, UNKNOWN is treated differently from any other frame + # (e.g., MNI_TAL). We should clean this up at some point... + # missing_fids = sum( + # d['kind'] == FIFF.FIFFV_POINT_CARDINAL for d in info['dig'][:3]) != 3 + # if missing_fids: + # raise RuntimeError( + # 'Could not find all three fiducials in the montage, this should ' + # 'not happen. Please contact MNE-Python developers.') + + # Handle fNIRS with source, detector and channel + fnirs_picks = _picks_to_idx(info, "fnirs", allow_empty=True) + if len(fnirs_picks) > 0: + _set_montage_fnirs(info, mnt_head) + + +def _read_isotrak_elp_points(fname): + """Read Polhemus Isotrak digitizer data from a ``.elp`` file. + + Parameters + ---------- + fname : path-like + The filepath of .elp Polhemus Isotrak file. + + Returns + ------- + out : dict of arrays + The dictionary containing locations for 'nasion', 'lpa', 'rpa' + and 'points'. + """ + value_pattern = r"\-?\d+\.?\d*e?\-?\d*" + coord_pattern = rf"({value_pattern})\s+({value_pattern})\s+({value_pattern})\s*$" + + with open(fname) as fid: + file_str = fid.read() + + points_str = [ + m.groups() for m in re.finditer(coord_pattern, file_str, re.MULTILINE) + ] + points = np.array(points_str, dtype=float) + + return { + "nasion": points[0], + "lpa": points[1], + "rpa": points[2], + "points": points[3:], + } + + +def _read_isotrak_hsp_points(fname): + """Read Polhemus Isotrak digitizer data from a ``.hsp`` file. + + Parameters + ---------- + fname : path-like + The filepath of .hsp Polhemus Isotrak file. + + Returns + ------- + out : dict of arrays + The dictionary containing locations for 'nasion', 'lpa', 'rpa' + and 'points'. + """ + + def get_hsp_fiducial(line): + return np.fromstring(line.replace("%F", ""), dtype=float, sep="\t") + + with open(fname) as ff: + for line in ff: + if "position of fiducials" in line.lower(): + break + + nasion = get_hsp_fiducial(ff.readline()) + lpa = get_hsp_fiducial(ff.readline()) + rpa = get_hsp_fiducial(ff.readline()) + + _ = ff.readline() + line = ff.readline() + if line: + n_points, n_cols = np.fromstring(line, dtype=int, sep="\t") + points = np.fromstring( + string=ff.read(), + dtype=float, + sep="\t", + ).reshape(-1, n_cols) + assert points.shape[0] == n_points + else: + points = np.empty((0, 3)) + + return {"nasion": nasion, "lpa": lpa, "rpa": rpa, "points": points} + + +def read_dig_polhemus_isotrak(fname, ch_names=None, unit="m"): + """Read Polhemus digitizer data from a file. + + Parameters + ---------- + fname : path-like + The filepath of Polhemus ISOTrak formatted file. + File extension is expected to be ``'.hsp'``, ``'.elp'`` or ``'.eeg'``. + ch_names : None | list of str + The names of the points. This will make the points + considered as EEG channels. If None, channels will be assumed + to be HPI if the extension is ``'.elp'``, and extra headshape + points otherwise. + unit : ``'m'`` | ``'cm'`` | ``'mm'`` + Unit of the digitizer file. Polhemus ISOTrak systems data is usually + exported in meters. Defaults to ``'m'``. + + Returns + ------- + montage : instance of DigMontage + The montage. + + See Also + -------- + DigMontage + make_dig_montage + read_polhemus_fastscan + read_dig_captrak + read_dig_curry + read_dig_egi + read_dig_fif + read_dig_localite + """ + VALID_FILE_EXT = (".hsp", ".elp", ".eeg") + fname = str(_check_fname(fname, overwrite="read", must_exist=True)) + _scale = _check_unit_and_get_scaling(unit) + + _, ext = op.splitext(fname) + _check_option("fname", ext, VALID_FILE_EXT) + + if ext == ".elp": + data = _read_isotrak_elp_points(fname) + else: + # Default case we read points as hsp since is the most likely scenario + data = _read_isotrak_hsp_points(fname) + + if _scale != 1: + data = {key: val * _scale for key, val in data.items()} + else: + pass # noqa + + if ch_names is None: + keyword = "hpi" if ext == ".elp" else "hsp" + data[keyword] = data.pop("points") + + else: + points = data.pop("points") + if points.shape[0] == len(ch_names): + data["ch_pos"] = OrderedDict(zip(ch_names, points)) + else: + raise ValueError( + "Length of ``ch_names`` does not match the number of points in " + f"{fname}. Expected ``ch_names`` length {points.shape[0]}, given " + f"{len(ch_names)}" + ) + + return make_dig_montage(**data) + + +def _is_polhemus_fastscan(fname): + header = "" + with open(fname) as fid: + for line in fid: + if not line.startswith("%"): + break + header += line + + return "FastSCAN" in header + + +@verbose +def read_polhemus_fastscan( + fname, unit="mm", on_header_missing="raise", *, verbose=None +): + """Read Polhemus FastSCAN digitizer data from a ``.txt`` file. + + Parameters + ---------- + fname : path-like + The path of ``.txt`` Polhemus FastSCAN file. + unit : ``'m'`` | ``'cm'`` | ``'mm'`` + Unit of the digitizer file. Polhemus FastSCAN systems data is usually + exported in millimeters. Defaults to ``'mm'``. + %(on_header_missing)s + %(verbose)s + + Returns + ------- + points : array, shape (n_points, 3) + The digitization points in digitizer coordinates. + + See Also + -------- + read_dig_polhemus_isotrak + make_dig_montage + """ + VALID_FILE_EXT = [".txt"] + fname = str(_check_fname(fname, overwrite="read", must_exist=True)) + _scale = _check_unit_and_get_scaling(unit) + + _, ext = op.splitext(fname) + _check_option("fname", ext, VALID_FILE_EXT) + + if not _is_polhemus_fastscan(fname): + msg = f"{fname} does not contain a valid Polhemus FastSCAN header" + _on_missing(on_header_missing, msg) + + points = _scale * np.loadtxt(fname, comments="%", ndmin=2) + _check_dig_shape(points) + return points + + +def _read_eeglab_locations(fname): + ch_names = np.genfromtxt(fname, dtype=str, usecols=3).tolist() + topo = np.loadtxt(fname, dtype=float, usecols=[1, 2]) + sph = _topo_to_sph(topo) + pos = _sph_to_cart(sph) + pos[:, [0, 1]] = pos[:, [1, 0]] * [-1, 1] + + return ch_names, pos + + +@verbose +def read_custom_montage( + fname, head_size=HEAD_SIZE_DEFAULT, coord_frame=None, *, verbose=None +): + """Read a montage from a file. + + Parameters + ---------- + fname : path-like + File extension is expected to be: + ``'.loc'`` or ``'.locs'`` or ``'.eloc'`` (for EEGLAB files), + ``'.sfp'`` (BESA/EGI files), ``'.csd'``, + ``'.elc'``, ``'.txt'``, ``'.csd'``, ``'.elp'`` (BESA spherical), + ``'.bvef'`` (BrainVision files), + ``'.csv'``, ``'.tsv'``, ``'.xyz'`` (XYZ coordinates). + head_size : float | None + The size of the head (radius, in [m]). If ``None``, returns the values + read from the montage file with no modification. Defaults to 0.095m. + coord_frame : str | None + The coordinate frame of the points. Usually this is ``"unknown"`` + for native digitizer space. Defaults to None, which is ``"unknown"`` + for most readers but ``"head"`` for EEGLAB. + + .. versionadded:: 0.20 + %(verbose)s + + Returns + ------- + montage : instance of DigMontage + The montage. + + See Also + -------- + make_dig_montage + make_standard_montage + read_dig_fif + + Notes + ----- + The function is a helper to read electrode positions you may have + in various formats. Most of these format are weakly specified + in terms of units, coordinate systems. It implies that setting + a montage using a DigMontage produced by this function may + be problematic. If you use a standard/template (eg. 10/20, + 10/10 or 10/05) we recommend you use :func:`make_standard_montage`. + If you can have positions in memory you can also use + :func:`make_dig_montage` that takes arrays as input. + """ + from ._standard_montage_utils import ( + _read_brainvision, + _read_csd, + _read_elc, + _read_elp_besa, + _read_sfp, + _read_theta_phi_in_degrees, + _read_xyz, + ) + + SUPPORTED_FILE_EXT = { + "eeglab": ( + ".loc", + ".locs", + ".eloc", + ), + "hydrocel": (".sfp",), + "matlab": (".csd",), + "asa electrode": (".elc",), + "generic (Theta-phi in degrees)": (".txt",), + "standard BESA spherical": (".elp",), # NB: not same as polhemus elp + "brainvision": (".bvef",), + "xyz": (".csv", ".tsv", ".xyz"), + } + + fname = str(_check_fname(fname, overwrite="read", must_exist=True)) + _, ext = op.splitext(fname) + _check_option("fname", ext, list(sum(SUPPORTED_FILE_EXT.values(), ()))) + + if ext in SUPPORTED_FILE_EXT["eeglab"]: + if head_size is None: + raise ValueError(f"``head_size`` cannot be None for '{ext}'") + ch_names, pos = _read_eeglab_locations(fname) + scale = head_size / np.median(np.linalg.norm(pos, axis=-1)) + pos *= scale + + montage = make_dig_montage( + ch_pos=OrderedDict(zip(ch_names, pos)), + coord_frame="head", + ) + + elif ext in SUPPORTED_FILE_EXT["hydrocel"]: + montage = _read_sfp(fname, head_size=head_size) + + elif ext in SUPPORTED_FILE_EXT["matlab"]: + montage = _read_csd(fname, head_size=head_size) + + elif ext in SUPPORTED_FILE_EXT["asa electrode"]: + montage = _read_elc(fname, head_size=head_size) + + elif ext in SUPPORTED_FILE_EXT["generic (Theta-phi in degrees)"]: + if head_size is None: + raise ValueError(f"``head_size`` cannot be None for '{ext}'") + montage = _read_theta_phi_in_degrees( + fname, head_size=head_size, fid_names=("Nz", "LPA", "RPA") + ) + + elif ext in SUPPORTED_FILE_EXT["standard BESA spherical"]: + montage = _read_elp_besa(fname, head_size) + + elif ext in SUPPORTED_FILE_EXT["brainvision"]: + montage = _read_brainvision(fname, head_size) + + elif ext in SUPPORTED_FILE_EXT["xyz"]: + montage = _read_xyz(fname) + + if coord_frame is not None: + coord_frame = _coord_frame_const(coord_frame) + for d in montage.dig: + d["coord_frame"] = coord_frame + + return montage + + +@verbose +def read_meg_canonical_info(system, *, verbose=None): + """Load canonical MEG sensor definitions from CSV files. + + Parameters + ---------- + system : str + The MEG system name. Currently supported: 'neuromag', 'ctf151' or + 'ctf275'. + %(verbose)s + + Returns + ------- + info : Info + An Info object containing the canonical sensor definitions. + + Notes + ----- + This function loads pre-defined canonical sensor positions and + orientations from CSV files stored in mne/channels/data/montages/. + + .. versionadded:: 1.12 + """ + # Validate system input + _check_option("system", system, list(_MEG_CANONICAL_FILES)) + + # Load the CSV file + montage_dir = Path(__file__).parent / "data" / "canonical_meg" + csv_file = montage_dir / _MEG_CANONICAL_FILES[system] + assert csv_file.is_file() # should be guaranteed by packaging + + # Read sensor definitions manually + ch_names = [] + rows = [] + lines = csv_file.read_text("utf-8").splitlines() + # Read header to get column names + header = lines[0].strip().split(",") + # Create a mapping from column name to index + col_idx = {name: i for i, name in enumerate(header)} + + # Read data rows + for line in lines[1:]: + values = line.strip().split(",") + if not values[0]: # skip empty lines + continue + rows.append(values) + ch_names.append(values[col_idx["name"]]) + + # Create base info structure + # Use a dummy sample rate; it won't matter for field interpolation + info = create_info(ch_names=ch_names, sfreq=1000.0, ch_types="mag") + + # Update each channel with full coil information + for idx, row in enumerate(rows): + ch = info["chs"][idx] + + # Set coil type + ch["coil_type"] = int(row[col_idx["coil_type"]]) + + # Set position and orientation in loc field + # loc[0:3] = position + ch["loc"][:3] = [ + float(row[col_idx["x"]]), + float(row[col_idx["y"]]), + float(row[col_idx["z"]]), + ] + + # loc[3:6] = ex (first orientation vector) + ch["loc"][3:6] = [ + float(row[col_idx["ex_x"]]), + float(row[col_idx["ex_y"]]), + float(row[col_idx["ex_z"]]), + ] + + # loc[6:9] = ey (second orientation vector) + ch["loc"][6:9] = [ + float(row[col_idx["ey_x"]]), + float(row[col_idx["ey_y"]]), + float(row[col_idx["ey_z"]]), + ] + + # loc[9:12] = ez (third orientation vector / normal) + ch["loc"][9:12] = [ + float(row[col_idx["ez_x"]]), + float(row[col_idx["ez_y"]]), + float(row[col_idx["ez_z"]]), + ] + + # Set coordinate frame to device coordinates + ch["coord_frame"] = FIFF.FIFFV_COORD_DEVICE + + # Set channel kind to MEG + ch["kind"] = FIFF.FIFFV_MEG_CH + + # Set unit based on coil type + # Neuromag gradiometers (3012) use T/m, magnetometers (3024) use T + # CTF gradiometers (5001) use T + if ch["coil_type"] == 3012: # Neuromag planar gradiometer + ch["unit"] = FIFF.FIFF_UNIT_T_M + else: # Magnetometers and CTF gradiometers + ch["unit"] = FIFF.FIFF_UNIT_T + + # Set device to head transform to identity (canonical positions) + # This will be updated based on the actual data being interpolated + info["dev_head_t"] = Transform("meg", "head", np.eye(4)) + + return info + + +def compute_dev_head_t(montage): + """Compute device to head transform from a DigMontage. + + Parameters + ---------- + montage : DigMontage + The `~mne.channels.DigMontage` must contain the fiducials in head + coordinate system and hpi points in both head and + meg device coordinate system. + + Returns + ------- + dev_head_t : Transform + A Device-to-Head transformation matrix. + """ + _, coord_frame = _get_fid_coords(montage.dig) + if coord_frame != FIFF.FIFFV_COORD_HEAD: + raise ValueError( + "montage should have been set to head coordinate " + "system with transform_to_head function." + ) + + hpi_head = np.array( + [ + d["r"] + for d in montage.dig + if ( + d["kind"] == FIFF.FIFFV_POINT_HPI + and d["coord_frame"] == FIFF.FIFFV_COORD_HEAD + ) + ], + float, + ) + hpi_dev = np.array( + [ + d["r"] + for d in montage.dig + if ( + d["kind"] == FIFF.FIFFV_POINT_HPI + and d["coord_frame"] == FIFF.FIFFV_COORD_DEVICE + ) + ], + float, + ) + + if not (len(hpi_head) == len(hpi_dev) and len(hpi_dev) > 0): + raise ValueError( + "To compute Device-to-Head transformation, the same number of HPI" + f" points in device and head coordinates is required. (Got {len(hpi_dev)}" + f" points in device and {len(hpi_head)} points in head coordinate systems)" + ) + + trans = _quat_to_affine(_fit_matched_points(hpi_dev, hpi_head)[0]) + return Transform(fro="meg", to="head", trans=trans) + + +@verbose +def compute_native_head_t(montage, *, on_missing="warn", verbose=None): + """Compute the native-to-head transformation for a montage. + + This uses the fiducials in the native space to transform to compute the + transform to the head coordinate frame. + + Parameters + ---------- + montage : instance of DigMontage + The montage. + %(on_missing_fiducials)s + + .. versionadded:: 1.2 + %(verbose)s + + Returns + ------- + native_head_t : instance of Transform + A native-to-head transformation matrix. + """ + # Get fiducial points and their coord_frame + fid_coords, coord_frame = _get_fid_coords(montage.dig, raise_error=False) + if coord_frame is None: + coord_frame = FIFF.FIFFV_COORD_UNKNOWN + if coord_frame == FIFF.FIFFV_COORD_HEAD: + native_head_t = np.eye(4) + else: + fid_keys = ("nasion", "lpa", "rpa") + for key in fid_keys: + this_coord = fid_coords[key] + if this_coord is None or np.any(np.isnan(this_coord)): + msg = ( + f"Fiducial point {key} not found, assuming identity " + f"{_verbose_frames[coord_frame]} to head transformation" + ) + _on_missing(on_missing, msg, error_klass=RuntimeError) + native_head_t = np.eye(4) + break + else: + native_head_t = get_ras_to_neuromag_trans( + *[fid_coords[key] for key in fid_keys] + ) + return Transform(coord_frame, "head", native_head_t) + + +def make_standard_montage(kind, head_size="auto"): + """Read a generic (built-in) standard montage that ships with MNE-Python. + + Parameters + ---------- + kind : str + The name of the montage to use. + + .. note:: + You can retrieve the names of all + built-in montages via :func:`mne.channels.get_builtin_montages`. + head_size : float | None | str + The head size (radius, in meters) to use for spherical montages. + Can be None to not scale the read sizes. ``'auto'`` (default) will + use 95mm for all montages except the ``'standard*'``, ``'mgh*'``, and + ``'artinis*'``, which are already in fsaverage's MRI coordinates + (same as MNI). + + Returns + ------- + montage : instance of DigMontage + The montage. + + See Also + -------- + get_builtin_montages + make_dig_montage + read_custom_montage + + Notes + ----- + Individualized (digitized) electrode positions should be read in using + :func:`read_dig_captrak`, :func:`read_dig_curry`, + :func:`read_dig_egi`, :func:`read_dig_fif`, :func:`read_dig_polhemus_isotrak`, + :func:`read_dig_hpts`, or manually made with :func:`make_dig_montage`. + + .. versionadded:: 0.19.0 + """ + from ._standard_montage_utils import standard_montage_look_up_table + + _validate_type(kind, str, "kind") + _check_option( + parameter="kind", + value=kind, + allowed_values=[m.name for m in _BUILTIN_STANDARD_MONTAGES], + ) + _validate_type(head_size, ("numeric", str, None), "head_size") + if isinstance(head_size, str): + _check_option("head_size", head_size, ("auto",), extra="when str") + if kind.startswith(("standard", "mgh", "artinis")): + head_size = None + else: + head_size = HEAD_SIZE_DEFAULT + return standard_montage_look_up_table[kind](head_size=head_size) + + +def _check_dig_shape(pts): + _validate_type(pts, np.ndarray, "points") + if pts.ndim != 2 or pts.shape[-1] != 3: + raise ValueError(f"Points must be of shape (n, 3) instead of {pts.shape}") diff --git a/mne-python/source/mne/channels/tests/__init__.py b/mne-python/source/mne/channels/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/channels/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/channels/tests/test_channels.py b/mne-python/source/mne/channels/tests/test_channels.py new file mode 100644 index 0000000000000000000000000000000000000000..697b49e7943d40f84f860d29f0318a86cf41347d --- /dev/null +++ b/mne-python/source/mne/channels/tests/test_channels.py @@ -0,0 +1,698 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import hashlib +from contextlib import nullcontext +from copy import deepcopy +from functools import partial +from pathlib import Path + +import numpy as np +import pooch +import pytest +from numpy.testing import assert_allclose, assert_array_equal, assert_equal +from scipy.io import savemat + +from mne import ( + Epochs, + EpochsArray, + EvokedArray, + create_info, + make_ad_hoc_cov, + pick_channels, + pick_types, + read_events, +) +from mne._fiff.constants import FIFF, _ch_unit_mul_named +from mne.channels import ( + combine_channels, + equalize_channels, + find_ch_adjacency, + get_builtin_ch_adjacencies, + make_1020_channel_selections, + read_ch_adjacency, + read_custom_montage, + rename_channels, +) +from mne.channels.channels import ( + _BUILTIN_CHANNEL_ADJACENCIES, + _ch_neighbor_adjacency, + _compute_ch_adjacency, +) +from mne.datasets import testing +from mne.io import ( + RawArray, + read_info, + read_raw_bti, + read_raw_ctf, + read_raw_eeglab, + read_raw_fif, + read_raw_kit, +) +from mne.utils import requires_good_network + +io_dir = Path(__file__).parents[2] / "io" +base_dir = io_dir / "tests" / "data" +raw_fname = base_dir / "test_raw.fif" +eve_fname = base_dir / "test-eve.fif" +fname_kit_157 = io_dir / "kit" / "tests" / "data" / "test.sqd" +testing_path = testing.data_path(download=False) + + +@pytest.mark.parametrize("preload", (True, False)) +@pytest.mark.parametrize("proj", (True, False)) +def test_reorder_channels(preload, proj): + """Test reordering of channels.""" + raw = read_raw_fif(raw_fname).crop(0, 0.1).del_proj() + if proj: # a no-op but should test it + raw._projector = np.eye(len(raw.ch_names)) + if preload: + raw.load_data() + # with .reorder_channels + if proj and not preload: + with pytest.raises(RuntimeError, match="load data"): + raw.copy().reorder_channels(raw.ch_names[::-1]) + return + raw_new = raw.copy().reorder_channels(raw.ch_names[::-1]) + assert raw_new.ch_names == raw.ch_names[::-1] + if proj: + assert_allclose(raw_new._projector, raw._projector, atol=1e-12) + else: + assert raw._projector is None + assert raw_new._projector is None + assert_array_equal(raw[:][0], raw_new[:][0][::-1]) + raw_new.reorder_channels(raw_new.ch_names[::-1][1:-1]) + raw.drop_channels(raw.ch_names[:1] + raw.ch_names[-1:]) + assert_array_equal(raw[:][0], raw_new[:][0]) + with pytest.raises(ValueError, match="repeated"): + raw.reorder_channels(raw.ch_names[:1] + raw.ch_names[:1]) + # and with .pick + reord = [1, 0] + list(range(2, len(raw.ch_names))) + rev = np.argsort(reord) + raw_new = raw.copy().pick(reord) + assert_array_equal(raw[:][0], raw_new[rev][0]) + + +def test_rename_channels(): + """Test rename channels.""" + info = read_info(raw_fname) + # Error Tests + # Test channel name exists in ch_names + mapping = {"EEG 160": "EEG060"} + ch_names_orig = info.ch_names[::] + pytest.raises(ValueError, rename_channels, info, mapping) + rename_channels(info, mapping, on_missing="ignore") + assert info.ch_names == ch_names_orig + with pytest.warns(RuntimeWarning, match="Channel rename map contains keys that *"): + rename_channels(info, mapping, on_missing="warn") + # Test improper mapping configuration + mapping = {"MEG 2641": 1.0} + pytest.raises(TypeError, rename_channels, info, mapping) + # Test non-unique mapping configuration + mapping = {"MEG 2641": "MEG 2642"} + pytest.raises(ValueError, rename_channels, info, mapping) + # Test bad input + pytest.raises(ValueError, rename_channels, info, 1.0) + pytest.raises(ValueError, rename_channels, info, 1.0) + + # Test successful changes + # Test ch_name and ch_names are changed + info2 = deepcopy(info) # for consistency at the start of each test + info2["bads"] = ["EEG 060", "EOG 061"] + mapping = {"EEG 060": "EEG060", "EOG 061": "EOG061"} + rename_channels(info2, mapping) + assert info2["chs"][374]["ch_name"] == "EEG060" + assert info2["ch_names"][374] == "EEG060" + assert info2["chs"][375]["ch_name"] == "EOG061" + assert info2["ch_names"][375] == "EOG061" + assert_array_equal(["EEG060", "EOG061"], info2["bads"]) + info2 = deepcopy(info) + rename_channels(info2, lambda x: x.replace(" ", "")) + assert info2["chs"][373]["ch_name"] == "EEG059" + info2 = deepcopy(info) + info2["bads"] = ["EEG 060", "EEG 060"] + rename_channels(info2, mapping) + assert_array_equal(["EEG060", "EEG060"], info2["bads"]) + + # test that keys in Raw._orig_units will be renamed, too + raw = read_raw_fif(raw_fname).crop(0, 0.1) + old, new = "EEG 060", "New" + raw._orig_units = {old: "V"} + + raw.rename_channels({old: new}) + assert old not in raw._orig_units + assert new in raw._orig_units + + +def test_set_channel_types(): + """Test set_channel_types.""" + raw = read_raw_fif(raw_fname) + # Error Tests + # Test channel name exists in ch_names + mapping = {"EEG 160": "EEG060"} + with pytest.raises(ValueError, match=r"name \(EEG 160\) doesn't exist"): + raw.set_channel_types(mapping) + # Test change to illegal channel type + mapping = {"EOG 061": "xxx"} + with pytest.raises(ValueError, match="cannot change to this channel type"): + raw.set_channel_types(mapping) + # Test changing type if in proj + mapping = { + "EEG 057": "dbs", + "EEG 058": "ecog", + "EEG 059": "ecg", + "EEG 060": "eog", + "EOG 061": "seeg", + "MEG 2441": "eeg", + "MEG 2443": "eeg", + "MEG 2442": "hbo", + "EEG 001": "resp", + } + raw2 = read_raw_fif(raw_fname) + raw2.info["bads"] = ["EEG 059", "EEG 060", "EOG 061"] + with pytest.raises(RuntimeError, match='type .* in projector "PCA-v1"'): + raw2.set_channel_types(mapping) # has prj + raw2.add_proj([], remove_existing=True) + + # Should raise + with pytest.raises(ValueError, match="unit for channel.* has changed"): + raw2.copy().set_channel_types(mapping, on_unit_change="raise") + + # Should warn + with pytest.warns(RuntimeWarning, match="unit for channel.* has changed"): + raw2.copy().set_channel_types(mapping) + + # Shouldn't warn + raw2.set_channel_types(mapping, on_unit_change="ignore") + + info = raw2.info + assert info["chs"][371]["ch_name"] == "EEG 057" + assert info["chs"][371]["kind"] == FIFF.FIFFV_DBS_CH + assert info["chs"][371]["unit"] == FIFF.FIFF_UNIT_V + assert info["chs"][371]["coil_type"] == FIFF.FIFFV_COIL_EEG + assert info["chs"][372]["ch_name"] == "EEG 058" + assert info["chs"][372]["kind"] == FIFF.FIFFV_ECOG_CH + assert info["chs"][372]["unit"] == FIFF.FIFF_UNIT_V + assert info["chs"][372]["coil_type"] == FIFF.FIFFV_COIL_EEG + assert info["chs"][373]["ch_name"] == "EEG 059" + assert info["chs"][373]["kind"] == FIFF.FIFFV_ECG_CH + assert info["chs"][373]["unit"] == FIFF.FIFF_UNIT_V + assert info["chs"][373]["coil_type"] == FIFF.FIFFV_COIL_NONE + assert info["chs"][374]["ch_name"] == "EEG 060" + assert info["chs"][374]["kind"] == FIFF.FIFFV_EOG_CH + assert info["chs"][374]["unit"] == FIFF.FIFF_UNIT_V + assert info["chs"][374]["coil_type"] == FIFF.FIFFV_COIL_NONE + assert info["chs"][375]["ch_name"] == "EOG 061" + assert info["chs"][375]["kind"] == FIFF.FIFFV_SEEG_CH + assert info["chs"][375]["unit"] == FIFF.FIFF_UNIT_V + assert info["chs"][375]["coil_type"] == FIFF.FIFFV_COIL_EEG + for idx in pick_channels(raw.ch_names, ["MEG 2441", "MEG 2443"], ordered=False): + assert info["chs"][idx]["kind"] == FIFF.FIFFV_EEG_CH + assert info["chs"][idx]["unit"] == FIFF.FIFF_UNIT_V + assert info["chs"][idx]["coil_type"] == FIFF.FIFFV_COIL_EEG + idx = pick_channels(raw.ch_names, ["MEG 2442"])[0] + assert info["chs"][idx]["kind"] == FIFF.FIFFV_FNIRS_CH + assert info["chs"][idx]["unit"] == FIFF.FIFF_UNIT_MOL + assert info["chs"][idx]["coil_type"] == FIFF.FIFFV_COIL_FNIRS_HBO + + # resp channel type + idx = pick_channels(raw.ch_names, ["EEG 001"])[0] + assert info["chs"][idx]["kind"] == FIFF.FIFFV_RESP_CH + assert info["chs"][idx]["unit"] == FIFF.FIFF_UNIT_V + assert info["chs"][idx]["coil_type"] == FIFF.FIFFV_COIL_NONE + + # Test meaningful error when setting channel type with unknown unit + raw.info["chs"][0]["unit"] = 0.0 + ch_types = {raw.ch_names[0]: "misc"} + pytest.raises(ValueError, raw.set_channel_types, ch_types) + + # test reset of channel units on unit change + idx = raw.ch_names.index("EEG 003") + raw.info["chs"][idx]["unit_mul"] = _ch_unit_mul_named[-6] + assert raw.info["chs"][idx]["unit_mul"] == -6 + raw.set_channel_types({"EEG 003": "misc"}, on_unit_change="ignore") + assert raw.info["chs"][idx]["unit_mul"] == 0 + + +def test_get_builtin_ch_adjacencies(): + """Test retrieving the names of all built-in FieldTrip neighbors.""" + names = get_builtin_ch_adjacencies() + assert names + assert len(names) == len(set(names)) # no duplicates + assert len(names) == len(_BUILTIN_CHANNEL_ADJACENCIES) + + names_and_descriptions = get_builtin_ch_adjacencies(descriptions=True) + for name_and_description in names_and_descriptions: + assert len(name_and_description) == 2 + + +@pytest.mark.parametrize("name", get_builtin_ch_adjacencies()) +@pytest.mark.parametrize("picks", ["pick-slice", "pick-arange", "pick-names"]) +def test_read_builtin_ch_adjacency_picks(name, picks): + """Test picking channel subsets when reading builtin adjacency matrices.""" + ch_adjacency, ch_names = read_ch_adjacency(name) + assert_equal(ch_adjacency.shape[0], len(ch_names)) + subset_names = ch_names[::2] + if picks == "pick-slice": + subset = slice(None, None, 2) + elif picks == "pick-arange": + subset = np.arange(0, len(ch_names), 2) + else: + assert picks == "pick-names" + subset = subset_names + + ch_subset_adjacency, ch_subset_names = read_ch_adjacency(name, subset) + assert_array_equal(ch_subset_names, subset_names) + + +def test_read_ch_adjacency(tmp_path): + """Test reading channel adjacency templates.""" + a = partial(np.array, dtype=" ps + + # are channels in the correct selection? + fz_c3_c4 = [raw.ch_names.index(ch) for ch in ("Fz", "C3", "C4")] + for channel, roi in zip(fz_c3_c4, ("Midline", "Left", "Right")): + assert channel in sels[roi] + + # ensure returning channel names works as expected + sels_names = make_1020_channel_selections(raw.info, return_ch_names=True) + for selection, ch_names in sels_names.items(): + assert ch_names == [raw.ch_names[idx] for idx in sels[selection]] + + +@testing.requires_testing_data +def test_find_ch_adjacency(): + """Test computing the adjacency matrix.""" + raw = read_raw_fif(raw_fname) + sizes = {"mag": 828, "grad": 1700, "eeg": 384} + nchans = {"mag": 102, "grad": 204, "eeg": 60} + for ch_type in ["mag", "grad", "eeg"]: + conn, ch_names = find_ch_adjacency(raw.info, ch_type) + # Silly test for checking the number of neighbors. + assert_equal(conn.astype(bool).sum(), sizes[ch_type]) + assert_equal(len(ch_names), nchans[ch_type]) + kwargs = dict(exclude=()) + if ch_type in ("mag", "grad"): + kwargs["meg"] = ch_type + else: + kwargs[ch_type] = True + want_names = [raw.ch_names[pick] for pick in pick_types(raw.info, **kwargs)] + assert ch_names == want_names + pytest.raises(ValueError, find_ch_adjacency, raw.info, None) + + # Test computing the conn matrix with gradiometers. + conn, ch_names = _compute_ch_adjacency(raw.info, "grad") + assert_equal(conn.astype(bool).sum(), 2680) + + # Test ch_type=None. + raw.pick(picks="mag") + find_ch_adjacency(raw.info, None) + + bti_fname = testing_path / "BTi" / "erm_HFH" / "c,rfDC" + bti_config_name = testing_path / "BTi" / "erm_HFH" / "config" + raw = read_raw_bti(bti_fname, bti_config_name, None) + _, ch_names = find_ch_adjacency(raw.info, "mag") + assert "A1" in ch_names + + ctf_fname = testing_path / "CTF" / "testdata_ctf_short.ds" + raw = read_raw_ctf(ctf_fname) + _, ch_names = find_ch_adjacency(raw.info, "mag") + assert "MLC11" in ch_names + + pytest.raises(ValueError, find_ch_adjacency, raw.info, "eog") + + raw_kit = read_raw_kit(fname_kit_157) + neighb, ch_names = find_ch_adjacency(raw_kit.info, "mag") + assert neighb.data.size == 1329 + assert ch_names[0] == "MEG 001" + + +@testing.requires_testing_data +def test_neuromag122_adjacency(): + """Test computing the adjacency matrix of Neuromag122-Data.""" + nm122_fname = testing_path / "misc" / "neuromag122_test_file-raw.fif" + raw = read_raw_fif(nm122_fname) + conn, ch_names = find_ch_adjacency(raw.info, "grad") + assert conn.astype(bool).sum() == 1564 + assert len(ch_names) == 122 + assert conn.shape == (122, 122) + + +def test_drop_channels(): + """Test if dropping channels works with various arguments.""" + raw = read_raw_fif(raw_fname).crop(0, 0.1) + raw.drop_channels(["MEG 0111"]) # list argument + raw.drop_channels("MEG 0112") # str argument + raw.drop_channels({"MEG 0132", "MEG 0133"}) # set argument + pytest.raises(ValueError, raw.drop_channels, ["MEG 0111", 5]) + pytest.raises(ValueError, raw.drop_channels, 5) # must be list or str + + # by default, drop channels raises a ValueError if a channel can't be found + m_chs = ["MEG 0111", "MEG blahblah"] + with pytest.raises(ValueError, match="not found, nothing dropped"): + raw.drop_channels(m_chs) + # ...but this can be turned to a warning + with pytest.warns(RuntimeWarning, match="not found, nothing dropped"): + raw.drop_channels(m_chs, on_missing="warn") + # ...or ignored altogether + raw.drop_channels(m_chs, on_missing="ignore") + with pytest.raises(ValueError, match="All channels"): + raw.drop_channels(raw.ch_names) + + +def test_pick_channels(): + """Test if picking channels works with various arguments.""" + raw = read_raw_fif(raw_fname).crop(0, 0.1) + + # selected correctly 3 channels + raw.pick(["MEG 0113", "MEG 0112", "MEG 0111"]) + assert len(raw.ch_names) == 3 + + # selected correctly 3 channels and ignored 'meg', and emit warning + with pytest.raises(ValueError, match="not present in the info"): + raw.pick(["MEG 0113", "meg", "MEG 0112", "MEG 0111"]) + + names_len = len(raw.ch_names) + raw.pick(["all"]) # selected correctly all channels + assert len(raw.ch_names) == names_len + raw.pick("all") # selected correctly all channels + assert len(raw.ch_names) == names_len + + +def test_add_reference_channels(): + """Test if there is a new reference channel that consist of all zeros.""" + raw = read_raw_fif(raw_fname, preload=True) + n_raw_original_channels = len(raw.ch_names) + epochs = Epochs(raw, read_events(eve_fname)) + epochs.load_data() + epochs_original_shape = epochs._data.shape[1] + evoked = epochs.average() + n_evoked_original_channels = len(evoked.ch_names) + + # Raw object + raw.add_reference_channels(["REF 123"]) + assert len(raw.ch_names) == n_raw_original_channels + 1 + assert np.all(raw.get_data()[-1] == 0) + + # Epochs object + epochs.add_reference_channels(["REF 123"]) + assert epochs._data.shape[1] == epochs_original_shape + 1 + + # Evoked object + evoked.add_reference_channels(["REF 123"]) + assert len(evoked.ch_names) == n_evoked_original_channels + 1 + assert np.all(evoked._data[-1] == 0) + + +def test_equalize_channels(): + """Test equalizing channels and their ordering.""" + # This function only tests the generic functionality of equalize_channels. + # Additional tests for each instance type are included in the accompanying + # test suite for each type. + pytest.raises( + TypeError, + equalize_channels, + ["foo", "bar"], + match="Instances to be modified must be an instance of", + ) + + raw = RawArray( + [[1.0], [2.0], [3.0], [4.0]], + create_info(["CH1", "CH2", "CH3", "CH4"], sfreq=1.0), + ) + epochs = EpochsArray( + [[[1.0], [2.0], [3.0]]], create_info(["CH5", "CH2", "CH1"], sfreq=1.0) + ) + cov = make_ad_hoc_cov(create_info(["CH2", "CH1", "CH8"], sfreq=1.0, ch_types="eeg")) + cov["bads"] = ["CH1"] + ave = EvokedArray([[1.0], [2.0]], create_info(["CH1", "CH2"], sfreq=1.0)) + + raw2, epochs2, cov2, ave2 = equalize_channels([raw, epochs, cov, ave], copy=True) + + # The Raw object was the first in the list, so should have been used as + # template for the ordering of the channels. No bad channels should have + # been dropped. + assert raw2.ch_names == ["CH1", "CH2"] + assert_array_equal(raw2.get_data(), [[1.0], [2.0]]) + assert epochs2.ch_names == ["CH1", "CH2"] + assert_array_equal(epochs2.get_data(copy=False), [[[3.0], [2.0]]]) + assert cov2.ch_names == ["CH1", "CH2"] + assert cov2["bads"] == cov["bads"] + assert ave2.ch_names == ave.ch_names + assert_array_equal(ave2.data, ave.data) + + # All objects should have been copied, except for the Evoked object which + # did not have to be touched. + assert raw is not raw2 + assert epochs is not epochs2 + assert cov is not cov2 + assert ave is ave2 + + # Test in-place operation + raw2, epochs2 = equalize_channels([raw, epochs], copy=False) + assert raw is raw2 + assert epochs is epochs2 + + +def test_combine_channels(): + """Test channel combination on Raw, Epochs, and Evoked.""" + raw = read_raw_fif(raw_fname, preload=True) + raw_ch_bad = read_raw_fif(raw_fname, preload=True) + raw_ch_bad.info["bads"] = ["MEG 0113", "MEG 0112"] + epochs = Epochs(raw, read_events(eve_fname)) + evoked = epochs.average() + good = dict(foo=[0, 1, 3, 4], bar=[5, 2]) # good grad and mag + + # Test good cases + combine_channels(raw, good) + combined_epochs = combine_channels(epochs, good) + assert_array_equal(combined_epochs.events, epochs.events) + assert epochs.baseline == combined_epochs.baseline + combined_evoked = combine_channels(evoked, good) + assert evoked.baseline == combined_evoked.baseline + combine_channels(raw, good, drop_bad=True) + combine_channels(raw_ch_bad, good, drop_bad=True) + + # Test with stimulus channels + combine_stim = combine_channels(raw, good, keep_stim=True) + target_nchan = len(good) + len(pick_types(raw.info, meg=False, stim=True)) + assert combine_stim.info["nchan"] == target_nchan + + # Test results with one ROI + good_single = dict(foo=[0, 1, 3, 4]) # good grad + combined_mean = combine_channels(raw, good_single, method="mean") + combined_median = combine_channels(raw, good_single, method="median") + combined_std = combine_channels(raw, good_single, method="std") + foo_mean = np.mean(raw.get_data()[good_single["foo"]], axis=0) + foo_median = np.median(raw.get_data()[good_single["foo"]], axis=0) + foo_std = np.std(raw.get_data()[good_single["foo"]], axis=0) + assert_array_equal(combined_mean.get_data(), np.expand_dims(foo_mean, axis=0)) + assert_array_equal(combined_median.get_data(), np.expand_dims(foo_median, axis=0)) + assert_array_equal(combined_std.get_data(), np.expand_dims(foo_std, axis=0)) + + # Test bad cases + bad1 = dict(foo=[0, 376], bar=[5, 2]) # out of bounds + bad2 = dict(foo=[0, 2], bar=[5, 2]) # type mix in same group + with pytest.raises(ValueError, match='"method" must be a callable, or'): + combine_channels(raw, good, method="bad_method") + with pytest.raises(TypeError, match='"keep_stim" must be of type bool'): + combine_channels(raw, good, keep_stim="bad_type") + with pytest.raises(TypeError, match='"drop_bad" must be of type bool'): + combine_channels(raw, good, drop_bad="bad_type") + with pytest.raises(ValueError, match="Some channel indices are out of"): + combine_channels(raw, bad1) + with pytest.raises(ValueError, match="Cannot combine sensors of diff"): + combine_channels(raw, bad2) + + # Test warnings + raw_no_stim = read_raw_fif(raw_fname, preload=True) + raw_no_stim.pick(picks="meg") + warn1 = dict(foo=[375, 375], bar=[5, 2]) # same channel in same group + warn2 = dict(foo=[375], bar=[5, 2]) # one channel (last channel) + warn3 = dict(foo=[0, 4], bar=[5, 2]) # one good channel left + with pytest.warns(RuntimeWarning, match="Could not find stimulus"): + combine_channels(raw_no_stim, good, keep_stim=True) + with pytest.warns(RuntimeWarning, match="Less than 2 channels") as record: + combine_channels(raw, warn1) + combine_channels(raw, warn2) + combine_channels(raw_ch_bad, warn3, drop_bad=True) + assert len(record) == 3 + + # Test on_missing + event_id = [1, 100] # 100 does not exist + epochs1 = Epochs(raw, read_events(eve_fname), event_id, on_missing="ignore") + with pytest.raises(ValueError, match="No matching events found"): + combine_channels(epochs1, groups={"foo": [0, 1]}) + with pytest.warns(RuntimeWarning, match="No matching events found"): + combine_channels(epochs1, groups={"foo": [0, 1]}, on_missing="warn") + with nullcontext(): + combine_channels(epochs1, groups={"foo": [0, 1]}, on_missing="ignore") + + +def test_combine_channels_metadata(): + """Test if metadata is correctly retained in combined object.""" + pd = pytest.importorskip("pandas") + raw = read_raw_fif(raw_fname, preload=True) + epochs = Epochs(raw, read_events(eve_fname), preload=True) + + metadata = pd.DataFrame({"A": np.arange(len(epochs)), "B": np.ones(len(epochs))}) + epochs.metadata = metadata + + good = dict(foo=[0, 1, 3, 4], bar=[5, 2]) # good grad and mag + combined_epochs = combine_channels(epochs, good) + pd.testing.assert_frame_equal(epochs.metadata, combined_epochs.metadata) diff --git a/mne-python/source/mne/channels/tests/test_interpolation.py b/mne-python/source/mne/channels/tests/test_interpolation.py new file mode 100644 index 0000000000000000000000000000000000000000..1c61ede72f292c4a885367497d3d444b45f92e35 --- /dev/null +++ b/mne-python/source/mne/channels/tests/test_interpolation.py @@ -0,0 +1,569 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from itertools import compress +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_equal + +import mne.channels.channels +from mne import Epochs, pick_channels, pick_types, read_events +from mne._fiff.constants import FIFF +from mne._fiff.proj import _has_eeg_average_ref_proj +from mne.channels import make_dig_montage, make_standard_montage +from mne.channels.interpolation import _make_interpolation_matrix +from mne.datasets import testing +from mne.io import RawArray, read_raw_ctf, read_raw_fif, read_raw_nirx +from mne.preprocessing.nirs import ( + beer_lambert_law, + optical_density, + scalp_coupling_index, +) +from mne.utils import _record_warnings + +base_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = base_dir / "test_raw.fif" +event_name = base_dir / "test-eve.fif" +raw_fname_ctf = base_dir / "test_ctf_raw.fif" +testing_path = testing.data_path(download=False) +event_id, tmin, tmax = 1, -0.2, 0.5 +event_id_2 = 2 + + +def _load_data(kind): + """Load data.""" + # It is more memory efficient to load data in a separate + # function so it's loaded on-demand + raw = read_raw_fif(raw_fname) + events = read_events(event_name) + # subselect channels for speed + if kind == "eeg": + picks = pick_types(raw.info, meg=False, eeg=True, exclude=[])[:15] + epochs = Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + preload=True, + reject=dict(eeg=80e-6), + ) + else: + picks = pick_types(raw.info, meg=True, eeg=False, exclude=[])[1:200:2] + assert kind == "meg" + with pytest.warns(RuntimeWarning, match="projection"): + epochs = Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + preload=True, + reject=dict(grad=1000e-12, mag=4e-12), + ) + return raw, epochs + + +@pytest.mark.parametrize("offset", (0.0, 0.1)) +@pytest.mark.parametrize( + "avg_proj, ctol", + [ + (True, (0.86, 0.93)), + (False, (0.97, 0.99)), + ], +) +@pytest.mark.parametrize( + "method, atol", + [ + pytest.param(None, 3e-6, marks=pytest.mark.slowtest), # slow on Azure + (dict(eeg="MNE"), 4e-6), + ], +) +@pytest.mark.filterwarnings("ignore:.*than 20 mm from head frame origin.*") +def test_interpolation_eeg(offset, avg_proj, ctol, atol, method): + """Test interpolation of EEG channels.""" + raw, epochs_eeg = _load_data("eeg") + epochs_eeg = epochs_eeg.copy() + assert not _has_eeg_average_ref_proj(epochs_eeg.info) + # Offsetting the coordinate frame should have no effect on the output + for inst in (raw, epochs_eeg): + for ch in inst.info["chs"]: + if ch["kind"] == FIFF.FIFFV_EEG_CH: + ch["loc"][:3] += offset + ch["loc"][3:6] += offset + for d in inst.info["dig"]: + d["r"] += offset + + # check that interpolation does nothing if no bads are marked + epochs_eeg.info["bads"] = [] + evoked_eeg = epochs_eeg.average() + kw = dict(method=method) + with pytest.warns(RuntimeWarning, match="Doing nothing"): + evoked_eeg.interpolate_bads(**kw) + + # create good and bad channels for EEG + epochs_eeg.info["bads"] = [] + goods_idx = np.ones(len(epochs_eeg.ch_names), dtype=bool) + goods_idx[epochs_eeg.ch_names.index("EEG 012")] = False + bads_idx = ~goods_idx + pos = epochs_eeg._get_channel_positions() + + evoked_eeg = epochs_eeg.average() + if avg_proj: + evoked_eeg.set_eeg_reference(projection=True).apply_proj() + assert_allclose(evoked_eeg.data.mean(0), 0.0, atol=1e-20) + ave_before = evoked_eeg.data[bads_idx] + + # interpolate bad channels for EEG + epochs_eeg.info["bads"] = ["EEG 012"] + evoked_eeg = epochs_eeg.average() + if avg_proj: + evoked_eeg.set_eeg_reference(projection=True).apply_proj() + good_picks = pick_types(evoked_eeg.info, meg=False, eeg=True) + assert_allclose(evoked_eeg.data[good_picks].mean(0), 0.0, atol=1e-20) + evoked_eeg_bad = evoked_eeg.copy() + bads_picks = pick_channels( + epochs_eeg.ch_names, include=epochs_eeg.info["bads"], ordered=True + ) + evoked_eeg_bad.data[bads_picks, :] = 1e10 + + # Test first the exclude parameter + evoked_eeg_2_bads = evoked_eeg_bad.copy() + evoked_eeg_2_bads.info["bads"] = ["EEG 004", "EEG 012"] + evoked_eeg_2_bads.data[ + pick_channels(evoked_eeg_bad.ch_names, ["EEG 004", "EEG 012"]) + ] = 1e10 + evoked_eeg_interp = evoked_eeg_2_bads.interpolate_bads( + origin=(0.0, 0.0, 0.0), exclude=["EEG 004"], **kw + ) + assert evoked_eeg_interp.info["bads"] == ["EEG 004"] + assert np.all(evoked_eeg_interp.get_data("EEG 004") == 1e10) + assert np.all(evoked_eeg_interp.get_data("EEG 012") != 1e10) + + # Now test without exclude parameter + evoked_eeg_bad.info["bads"] = ["EEG 012"] + evoked_eeg_interp = evoked_eeg_bad.copy().interpolate_bads( + origin=(0.0, 0.0, 0.0), **kw + ) + if avg_proj: + assert_allclose(evoked_eeg_interp.data.mean(0), 0.0, atol=1e-6) + interp_zero = evoked_eeg_interp.data[bads_idx] + if method is None: # using + pos_good = pos[goods_idx] + pos_bad = pos[bads_idx] + interpolation = _make_interpolation_matrix(pos_good, pos_bad) + assert interpolation.shape == (1, len(epochs_eeg.ch_names) - 1) + interp_manual = np.dot(interpolation, evoked_eeg_bad.data[goods_idx]) + assert_array_equal(interp_manual, interp_zero) + del interp_manual, interpolation, pos, pos_good, pos_bad + assert_allclose(ave_before, interp_zero, atol=atol) + assert ctol[0] < np.corrcoef(ave_before, interp_zero)[0, 1] < ctol[1] + interp_fit = evoked_eeg_bad.copy().interpolate_bads(**kw).data[bads_idx] + assert_allclose(ave_before, interp_fit, atol=2.5e-6) + assert ctol[1] < np.corrcoef(ave_before, interp_fit)[0, 1] # better + + # check that interpolation fails when preload is False + epochs_eeg.preload = False + with pytest.raises(RuntimeError, match="requires epochs data to be load"): + epochs_eeg.interpolate_bads(**kw) + epochs_eeg.preload = True + + # check that interpolation changes the data in raw + raw_eeg = RawArray(data=epochs_eeg._data[0], info=epochs_eeg.info) + raw_before = raw_eeg._data[bads_idx] + raw_after = raw_eeg.interpolate_bads(**kw)._data[bads_idx] + assert not np.all(raw_before == raw_after) + + # check that interpolation fails when preload is False + for inst in [raw, epochs_eeg]: + assert hasattr(inst, "preload") + inst.preload = False + inst.info["bads"] = [inst.ch_names[1]] + with pytest.raises(RuntimeError, match="requires.*data to be loaded"): + inst.interpolate_bads(**kw) + + # check that interpolation works with few channels + raw_few = raw.copy().crop(0, 0.1).load_data() + raw_few.pick(raw_few.ch_names[:1] + raw_few.ch_names[3:4]) + assert len(raw_few.ch_names) == 2 + raw_few.del_proj() + raw_few.info["bads"] = [raw_few.ch_names[-1]] + orig_data = raw_few[1][0] + with _record_warnings() as w: + raw_few.interpolate_bads(reset_bads=False, **kw) + assert len([ww for ww in w if "more than" not in str(ww.message)]) == 0 + new_data = raw_few[1][0] + assert (new_data == 0).mean() < 0.5 + assert np.corrcoef(new_data, orig_data)[0, 1] > 0.2 + + +@pytest.mark.slowtest +def test_interpolation_meg(): + """Test interpolation of MEG channels.""" + # speed accuracy tradeoff: channel subselection is faster but the + # correlation drops + thresh = 0.68 + + raw, epochs_meg = _load_data("meg") + + # check that interpolation works when non M/EEG channels are present + # before MEG channels + raw.crop(0, 0.1).load_data().pick(epochs_meg.ch_names) + raw.info.normalize_proj() + raw.set_channel_types({raw.ch_names[0]: "stim"}, on_unit_change="ignore") + raw.info["bads"] = [raw.ch_names[1]] + raw.load_data() + raw.interpolate_bads(mode="fast") + del raw + + # check that interpolation works for MEG + epochs_meg.info["bads"] = ["MEG 0141"] + evoked = epochs_meg.average() + pick = pick_channels(epochs_meg.info["ch_names"], epochs_meg.info["bads"]) + + # MEG -- raw + raw_meg = RawArray(data=epochs_meg._data[0], info=epochs_meg.info) + raw_meg.info["bads"] = ["MEG 0141"] + data1 = raw_meg[pick, :][0][0] + + raw_meg.info.normalize_proj() + data2 = raw_meg.interpolate_bads(reset_bads=False, mode="fast")[pick, :][0][0] + assert np.corrcoef(data1, data2)[0, 1] > thresh + # the same number of bads as before + assert len(raw_meg.info["bads"]) == len(raw_meg.info["bads"]) + + # MEG -- epochs + data1 = epochs_meg.get_data(pick).ravel() + epochs_meg.info.normalize_proj() + epochs_meg.interpolate_bads(mode="fast") + data2 = epochs_meg.get_data(pick).ravel() + assert np.corrcoef(data1, data2)[0, 1] > thresh + assert len(epochs_meg.info["bads"]) == 0 + + # MEG -- evoked (plus auto origin) + data1 = evoked.data[pick] + evoked.info.normalize_proj() + data2 = evoked.interpolate_bads(origin="auto").data[pick] + assert np.corrcoef(data1, data2)[0, 1] > thresh + + # MEG -- with exclude + evoked.info["bads"] = ["MEG 0141", "MEG 0121"] + pick = pick_channels(evoked.ch_names, evoked.info["bads"], ordered=True) + evoked.data[pick[-1]] = 1e10 + data1 = evoked.data[pick] + evoked.info.normalize_proj() + data2 = evoked.interpolate_bads(origin="auto", exclude=["MEG 0121"]).data[pick] + assert np.corrcoef(data1[0], data2[0])[0, 1] > thresh + assert np.all(data2[1] == 1e10) + + +def _this_interpol(inst, ref_meg=False): + from mne.channels.interpolation import _interpolate_bads_meg + + _interpolate_bads_meg(inst, ref_meg=ref_meg, mode="fast", origin=(0.0, 0.0, 0.04)) + return inst + + +@pytest.mark.slowtest +def test_interpolate_meg_ctf(): + """Test interpolation of MEG channels from CTF system.""" + thresh = 0.85 + tol = 0.05 # assert the new interpol correlates at least .05 "better" + bad = "MLC22-2622" # select a good channel to test the interpolation + + raw = read_raw_fif(raw_fname_ctf).crop(0, 1.0).load_data() # 3 secs + raw.apply_gradient_compensation(3) + + # Show that we have to exclude ref_meg for interpolating CTF MEG-channels + # (fixed in #5965): + raw.info["bads"] = [bad] + pick_bad = pick_channels(raw.info["ch_names"], raw.info["bads"]) + data_orig = raw[pick_bad, :][0] + # mimic old behavior (the ref_meg-arg in _interpolate_bads_meg only serves + # this purpose): + data_interp_refmeg = _this_interpol(raw, ref_meg=True)[pick_bad, :][0] + # new: + data_interp_no_refmeg = _this_interpol(raw, ref_meg=False)[pick_bad, :][0] + + R = dict() + R["no_refmeg"] = np.corrcoef(data_orig, data_interp_no_refmeg)[0, 1] + R["with_refmeg"] = np.corrcoef(data_orig, data_interp_refmeg)[0, 1] + + print("Corrcoef of interpolated with original channel: ", R) + assert R["no_refmeg"] > R["with_refmeg"] + tol + assert R["no_refmeg"] > thresh + + +@testing.requires_testing_data +def test_interpolation_ctf_comp(): + """Test interpolation with compensated CTF data.""" + raw_fname = testing_path / "CTF" / "somMDYO-18av.ds" + raw = read_raw_ctf(raw_fname, preload=True) + raw.info["bads"] = [raw.ch_names[5], raw.ch_names[-5]] + raw.interpolate_bads(mode="fast", origin=(0.0, 0.0, 0.04)) + assert raw.info["bads"] == [] + + +@testing.requires_testing_data +def test_interpolation_nirs(): + """Test interpolating bad nirs channels.""" + pytest.importorskip("pymatreader") + fname = testing_path / "NIRx" / "nirscout" / "nirx_15_2_recording_w_overlap" + raw_intensity = read_raw_nirx(fname, preload=False) + raw_od = optical_density(raw_intensity) + sci = scalp_coupling_index(raw_od) + raw_od.info["bads"] = list(compress(raw_od.ch_names, sci < 0.5)) + bad_0 = np.where([name == raw_od.info["bads"][0] for name in raw_od.ch_names])[0][0] + bad_0_std_pre_interp = np.std(raw_od._data[bad_0]) + bads_init = list(raw_od.info["bads"]) + raw_od.interpolate_bads(exclude=bads_init[:2]) + assert raw_od.info["bads"] == bads_init[:2] + raw_od.interpolate_bads() + assert raw_od.info["bads"] == [] + assert bad_0_std_pre_interp > np.std(raw_od._data[bad_0]) + raw_haemo = beer_lambert_law(raw_od, ppf=6) + raw_haemo.info["bads"] = raw_haemo.ch_names[2:4] + assert raw_haemo.info["bads"] == ["S1_D2 hbo", "S1_D2 hbr"] + raw_haemo.interpolate_bads() + assert raw_haemo.info["bads"] == [] + + +@testing.requires_testing_data +def test_interpolation_ecog(): + """Test interpolation for ECoG.""" + raw, epochs_eeg = _load_data("eeg") + bads = ["EEG 012"] + bads_mask = np.isin(epochs_eeg.ch_names, bads) + + epochs_ecog = epochs_eeg.set_channel_types( + {ch: "ecog" for ch in epochs_eeg.ch_names} + ) + epochs_ecog.info["bads"] = bads + + # check that interpolation changes the data in raw + raw_ecog = RawArray(data=epochs_ecog._data[0], info=epochs_ecog.info) + raw_before = raw_ecog.copy() + raw_after = raw_ecog.interpolate_bads(method=dict(ecog="spline")) + assert not np.all(raw_before._data[bads_mask] == raw_after._data[bads_mask]) + assert_array_equal(raw_before._data[~bads_mask], raw_after._data[~bads_mask]) + + +@testing.requires_testing_data +def test_interpolation_seeg(): + """Test interpolation for sEEG.""" + raw, epochs_eeg = _load_data("eeg") + bads = ["EEG 012"] + bads_mask = np.isin(epochs_eeg.ch_names, bads) + epochs_seeg = epochs_eeg.set_channel_types( + {ch: "seeg" for ch in epochs_eeg.ch_names} + ) + epochs_seeg.info["bads"] = bads + + # check that interpolation changes the data in raw + raw_seeg = RawArray(data=epochs_seeg._data[0], info=epochs_seeg.info) + raw_before = raw_seeg.copy() + montage = raw_seeg.get_montage() + pos = montage.get_positions() + ch_pos = pos.pop("ch_pos") + n0 = ch_pos[epochs_seeg.ch_names[0]] + n1 = ch_pos[epochs_seeg.ch_names[1]] + for i, ch in enumerate(epochs_seeg.ch_names[2:]): + ch_pos[ch] = n0 + (n1 - n0) * (i + 2) + raw_seeg.set_montage(make_dig_montage(ch_pos, **pos)) + raw_after = raw_seeg.interpolate_bads(method=dict(seeg="spline")) + assert not np.all(raw_before._data[bads_mask] == raw_after._data[bads_mask]) + assert_array_equal(raw_before._data[~bads_mask], raw_after._data[~bads_mask]) + + # check interpolation on epochs + epochs_seeg.set_montage(make_dig_montage(ch_pos, **pos)) + epochs_before = epochs_seeg.copy() + epochs_after = epochs_seeg.interpolate_bads(method=dict(seeg="spline")) + assert not np.all( + epochs_before._data[:, bads_mask] == epochs_after._data[:, bads_mask] + ) + assert_array_equal( + epochs_before._data[:, ~bads_mask], epochs_after._data[:, ~bads_mask] + ) + + # test shaft all bad + epochs_seeg.info["bads"] = epochs_seeg.ch_names + with pytest.raises(RuntimeError, match="Not enough good channels"): + epochs_seeg.interpolate_bads(method=dict(seeg="spline")) + + # test bad not on shaft + ch_pos[bads[0]] = np.array([10, 10, 10]) + epochs_seeg.info["bads"] = bads + epochs_seeg.set_montage(make_dig_montage(ch_pos, **pos)) + with pytest.raises(RuntimeError, match="No shaft found"): + epochs_seeg.interpolate_bads(method=dict(seeg="spline")) + + +def test_nan_interpolation(raw): + """Test 'nan' method for interpolating bads.""" + ch_to_interp = [raw.ch_names[1]] # don't use channel 0 (type is IAS not MEG) + raw.info["bads"] = ch_to_interp + + # test that warning appears for reset_bads = True + with pytest.warns(RuntimeWarning, match="Consider setting reset_bads=False"): + raw.interpolate_bads(method="nan", reset_bads=True) + + # despite warning, interpolation still happened, make sure the channel is NaN + bad_chs = raw.get_data(ch_to_interp) + assert np.isnan(bad_chs).all() + + # make sure reset_bads=False works as expected + raw.info["bads"] = ch_to_interp + raw.interpolate_bads(method="nan", reset_bads=False) + assert raw.info["bads"] == ch_to_interp + + store = raw.info["chs"][1]["loc"] + # for on_bad_position="raise" + raw.info["bads"] = ch_to_interp + raw.info["chs"][1]["loc"] = np.full(12, np.nan) + with pytest.raises(ValueError, match="have invalid sensor position"): + # DOES NOT interpolates at all. So raw.info["bads"] remains as is + raw.interpolate_bads(on_bad_position="raise") + + # for on_bad_position="warn" + with pytest.warns(RuntimeWarning, match="have invalid sensor position"): + # this DOES the interpolation BUT with a warning + # so raw.info["bad"] will be empty again, + # and interpolated channel with be all np.nan + raw.interpolate_bads(on_bad_position="warn") + + # for on_bad_position="ignore" + raw.info["bads"] = ch_to_interp + assert raw.interpolate_bads(on_bad_position="ignore") + assert np.isnan(bad_chs).all, "Interpolated channel should be all NaN" + raw.info["chs"][1]["loc"] = store + + # make sure other channels are untouched + raw.drop_channels(ch_to_interp) + good_chs = raw.get_data() + assert np.isfinite(good_chs).all() + + +@testing.requires_testing_data +def test_method_str(): + """Test method argument types.""" + raw = read_raw_fif( + testing_path / "MEG" / "sample" / "sample_audvis_trunc_raw.fif", + preload=False, + ) + raw.crop(0, 1).pick(("meg", "eeg"), exclude=()).load_data() + raw.copy().interpolate_bads(method="MNE") + with pytest.raises(ValueError, match="Invalid value for the"): + raw.interpolate_bads(method="spline") + raw.pick("eeg", exclude=()) + raw.interpolate_bads(method="spline") + + +@pytest.mark.parametrize("montage_name", ["biosemi16", "standard_1020"]) +@pytest.mark.parametrize("method", ["spline", "MNE"]) +@pytest.mark.parametrize("data_type", ["raw", "epochs", "evoked"]) +def test_interpolate_to_eeg(montage_name, method, data_type): + """Test the interpolate_to method for EEG for raw, epochs, and evoked.""" + # Load EEG data + raw, epochs_eeg = _load_data("eeg") + epochs_eeg = epochs_eeg.copy() + + # Load data for raw + raw.load_data() + + # Create a target montage + montage = make_standard_montage(montage_name) + + # Prepare data to interpolate to + if data_type == "raw": + inst = raw.copy() + elif data_type == "epochs": + inst = epochs_eeg.copy() + elif data_type == "evoked": + inst = epochs_eeg.average() + shape = list(inst._data.shape) + orig_total = len(inst.info["ch_names"]) + n_eeg_orig = len(pick_types(inst.info, eeg=True)) + + # Assert first and last channels are not EEG + if data_type == "raw": + ch_types = inst.get_channel_types() + assert ch_types[0] != "eeg" + assert ch_types[-1] != "eeg" + + # Record the names and data of the first and last channels. + if data_type == "raw": + first_name = inst.info["ch_names"][0] + last_name = inst.info["ch_names"][-1] + data_first = inst._data[..., 0, :].copy() + data_last = inst._data[..., -1, :].copy() + + # Interpolate the EEG channels. + inst_interp = inst.copy().interpolate_to(montage, method=method) + + # Check that the new channel names include the montage channels. + assert set(montage.ch_names).issubset(set(inst_interp.info["ch_names"])) + # Check that the overall channel order is changed. + assert inst.info["ch_names"] != inst_interp.info["ch_names"] + + # Check that the data shape is as expected. + new_nchan_expected = orig_total - n_eeg_orig + len(montage.ch_names) + expected_shape = (new_nchan_expected, shape[-1]) + if len(shape) == 3: + expected_shape = (shape[0],) + expected_shape + assert inst_interp._data.shape == expected_shape + + # Verify that the first and last channels retain their positions. + if data_type == "raw": + assert inst_interp.info["ch_names"][0] == first_name + assert inst_interp.info["ch_names"][-1] == last_name + + # Verify that the data for the first and last channels is unchanged. + if data_type == "raw": + np.testing.assert_allclose( + inst_interp._data[..., 0, :], + data_first, + err_msg="Data for the first non-EEG channel has changed.", + ) + np.testing.assert_allclose( + inst_interp._data[..., -1, :], + data_last, + err_msg="Data for the last non-EEG channel has changed.", + ) + + # Validate that bad channels are carried over. + # Mark the first non eeg channel as bad + all_ch = inst_interp.info["ch_names"] + eeg_ch = [all_ch[i] for i in pick_types(inst_interp.info, eeg=True)] + bads = [ch for ch in all_ch if ch not in eeg_ch][:1] + inst.info["bads"] = bads + inst_interp = inst.copy().interpolate_to(montage, method=method) + assert inst_interp.info["bads"] == bads + + +@pytest.mark.slowtest # ~5s locally +@pytest.mark.filterwarnings("ignore:Projection vector.* reduced .*:RuntimeWarning") +def test_interpolate_to_meg(monkeypatch): + """Test interpolation_to for MEG data.""" + evoked = _load_data("meg")[1].average() + assert len(evoked.ch_names) == 100 + evoked.pick(evoked.ch_names[::4]) # speed up test + assert "MEG 0112" in evoked.ch_names # neuromag data + monkeypatch.setattr( # for speed + mne.channels.channels, "_ALLOWED_INTERPOLATION_MODES", ("point",) + ) + kwargs = dict(mode="point", origin=(0.0, 0.0, 0.04)) + evoked_ctf = evoked.interpolate_to("ctf151", **kwargs) + evoked_ctf.pick(evoked_ctf.ch_names[::4]) + evoked_rt = evoked_ctf.interpolate_to("neuromag", **kwargs).pick(evoked.ch_names) + corrcoef = np.corrcoef(evoked.data.ravel(), evoked_rt.data.ravel())[0, 1] + assert 0.90 < corrcoef < 0.92 + evoked_rt.info["bads"] = evoked_rt.ch_names + with pytest.raises(ValueError, match="No good MEG"): + evoked_rt.interpolate_to("ctf151", **kwargs) + with pytest.raises(ValueError, match="Invalid value"): + evoked_rt.interpolate_to("foo", **kwargs) diff --git a/mne-python/source/mne/channels/tests/test_layout.py b/mne-python/source/mne/channels/tests/test_layout.py new file mode 100644 index 0000000000000000000000000000000000000000..ad44a6873a403e7ab7d94040c3a7403a1889716d --- /dev/null +++ b/mne-python/source/mne/channels/tests/test_layout.py @@ -0,0 +1,506 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import copy +from pathlib import Path + +import matplotlib.pyplot as plt +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_equal, +) + +from mne import pick_info, pick_types +from mne._fiff.constants import FIFF +from mne._fiff.meas_info import _empty_info +from mne.channels import ( + Layout, + find_layout, + make_eeg_layout, + make_grid_layout, + read_layout, +) +from mne.channels.layout import _box_size, _find_topomap_coords, generate_2d_layout +from mne.defaults import HEAD_SIZE_DEFAULT +from mne.io import read_info, read_raw_kit + +io_dir = Path(__file__).parents[2] / "io" +fif_fname = io_dir / "tests" / "data" / "test_raw.fif" +lout_path = io_dir / "tests" / "data" +bti_dir = io_dir / "bti" / "tests" / "data" +fname_ctf_raw = io_dir / "tests" / "data" / "test_ctf_comp_raw.fif" +fname_kit_157 = io_dir / "kit" / "tests" / "data" / "test.sqd" +fname_kit_umd = io_dir / "kit" / "tests" / "data" / "test_umd-raw.sqd" + + +def _get_test_info(): + """Make test info.""" + test_info = _empty_info(1000) + loc = np.array( + [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0], dtype=np.float32 + ) + test_info["chs"] = [ + { + "cal": 1, + "ch_name": "ICA 001", + "coil_type": 0, + "coord_frame": 0, + "kind": 502, + "loc": loc.copy(), + "logno": 1, + "range": 1.0, + "scanno": 1, + "unit": -1, + "unit_mul": 0, + }, + { + "cal": 1, + "ch_name": "ICA 002", + "coil_type": 0, + "coord_frame": 0, + "kind": 502, + "loc": loc.copy(), + "logno": 2, + "range": 1.0, + "scanno": 2, + "unit": -1, + "unit_mul": 0, + }, + { + "cal": 0.002142000012099743, + "ch_name": "EOG 061", + "coil_type": 1, + "coord_frame": 0, + "kind": 202, + "loc": loc.copy(), + "logno": 61, + "range": 1.0, + "scanno": 376, + "unit": 107, + "unit_mul": 0, + }, + ] + test_info._unlocked = False + test_info._update_redundant() + test_info._check_consistency() + return test_info + + +@pytest.fixture(scope="module") +def layout(): + """Get a layout.""" + return Layout( + (0.1, 0.2, 0.1, 1.2), + pos=np.array([[0, 0, 0.1, 0.1], [0.2, 0.2, 0.1, 0.1], [0.4, 0.4, 0.1, 0.1]]), + names=["0", "1", "2"], + ids=[0, 1, 2], + kind="test", + ) + + +def test_io_layout_lout(tmp_path): + """Test IO with .lout files.""" + layout = read_layout(fname="Vectorview-all", scale=False) + layout.save(tmp_path / "foobar.lout", overwrite=True) + layout_read = read_layout( + fname=tmp_path / "foobar.lout", + scale=False, + ) + assert_array_almost_equal(layout.pos, layout_read.pos, decimal=2) + assert layout.names == layout_read.names + assert " 0 # RPA + assert points[0, 0] < 0 # LPA + # Nasion + assert_allclose(points[1, 0], 0.0, atol=1e-6) + assert points[1, 1] > 0 + fname_out = tmp_path / "test-dig.fif" + make_dig_montage( + lpa=fids[0]["r"], nasion=fids[1]["r"], rpa=fids[2]["r"], coord_frame="mri_voxel" + ).save(fname_out, overwrite=True) + fids_2, coord_frame_2 = read_fiducials(fname_out) + assert coord_frame_2 == FIFF.FIFFV_MNE_COORD_MRI_VOXEL + assert_allclose( + [fid["r"] for fid in fids[:3]], + [fid["r"] for fid in fids_2], + rtol=1e-6, + ) + assert coord_frame_2 is not None + + +def test_documented(): + """Test that standard montages are documented.""" + montage_dir = Path(_mne_file).parent / "channels" / "data" / "montages" + montage_files = Path(montage_dir).glob("*") + montage_names = [f.stem for f in montage_files] + + assert len(montage_names) == len(_BUILTIN_STANDARD_MONTAGES) + assert set(montage_names) == set([m.name for m in _BUILTIN_STANDARD_MONTAGES]) + + +@pytest.mark.parametrize( + "reader, file_content, expected_dig, ext, warning", + [ + pytest.param( + partial(read_custom_montage, head_size=None), + ( + "FidNz 0 9.071585155 -2.359754454\n" + "FidT9 -6.711765 0.040402876 -3.251600355\n" + "very_very_very_long_name -5.831241498 -4.494821698 4.955347697\n" + "Cz 0 0 1\n" + "Cz 0 0 8.899186843" + ), + make_dig_montage( + ch_pos={ + "very_very_very_long_name": [ + -5.8312416, + -4.4948215, + 4.9553475, + ], # noqa + "Cz": [0.0, 0.0, 8.899187], + }, + nasion=[0.0, 9.071585, -2.3597546], + lpa=[-6.711765, 0.04040287, -3.2516003], + rpa=None, + ), + "sfp", + (RuntimeWarning, r"Duplicate.*last will be used for Cz \(2\)"), + id="sfp_duplicate", + ), + pytest.param( + partial(read_custom_montage, head_size=None), + ( + "FidNz 0 9.071585155 -2.359754454\n" + "FidT9 -6.711765 0.040402876 -3.251600355\n" + "headshape 1 2 3\n" + "headshape 4 5 6\n" + "Cz 0 0 8.899186843" + ), + make_dig_montage( + hsp=[ + [1, 2, 3], + [4, 5, 6], + ], + ch_pos={ + "Cz": [0.0, 0.0, 8.899187], + }, + nasion=[0.0, 9.071585, -2.3597546], + lpa=[-6.711765, 0.04040287, -3.2516003], + rpa=None, + ), + "sfp", + None, + id="sfp_headshape", + ), + pytest.param( + partial(read_custom_montage, head_size=1), + ( + "1 0 0.50669 FPz\n" + "2 23 0.71 EOG1\n" + "3 -39.947 0.34459 F3\n" + "4 0 0.25338 Fz\n" + ), + make_dig_montage( + ch_pos={ + "EOG1": [0.30873816, 0.72734152, -0.61290705], + "F3": [-0.56705965, 0.67706631, 0.46906776], + "FPz": [0.0, 0.99977915, -0.02101571], + "Fz": [0.0, 0.71457525, 0.69955859], + }, + nasion=None, + lpa=None, + rpa=None, + coord_frame="head", + ), + "loc", + None, + id="EEGLAB", + ), + pytest.param( + partial(read_custom_montage, head_size=None, coord_frame="mri"), + "// MatLab Sphere coordinates [degrees] Cartesian coordinates\n" # noqa: E501 + "// Label Theta Phi Radius X Y Z off sphere surface\n" # noqa: E501 + "E1 37.700 -14.000 1.000 0.7677 0.5934 -0.2419 -0.00000000000000011\n" # noqa: E501 + "E3 51.700 11.000 1.000 0.6084 0.7704 0.1908 0.00000000000000000\n" # noqa: E501 + "E31 90.000 -11.000 1.000 0.0000 0.9816 -0.1908 0.00000000000000000\n" # noqa: E501 + "E61 158.000 -17.200 1.000 -0.8857 0.3579 -0.2957 -0.00000000000000022", # noqa: E501 + make_dig_montage( + ch_pos={ + "E1": [0.7677, 0.5934, -0.2419], + "E3": [0.6084, 0.7704, 0.1908], + "E31": [0.0, 0.9816, -0.1908], + "E61": [-0.8857, 0.3579, -0.2957], + }, + nasion=None, + lpa=None, + rpa=None, + coord_frame="mri", + ), + "csd", + None, + id="matlab", + ), + pytest.param( + partial(read_custom_montage, head_size=None), + ( + "# ASA electrode file\nReferenceLabel avg\nUnitPosition mm\n" + "NumberPositions= 68\n" + "Positions\n" + "-86.0761 -19.9897 -47.9860\n" + "85.7939 -20.0093 -48.0310\n" + "0.0083 86.8110 -39.9830\n" + "-86.0761 -24.9897 -67.9860\n" + "Labels\nLPA\nRPA\nNz\nDummy\n" + ), + make_dig_montage( + ch_pos={ + "Dummy": [-0.0860761, -0.0249897, -0.067986], + }, + nasion=[8.3000e-06, 8.6811e-02, -3.9983e-02], + lpa=[-0.0860761, -0.0199897, -0.047986], + rpa=[0.0857939, -0.0200093, -0.048031], + ), + "elc", + None, + id="old ASA electrode (elc)", + ), + pytest.param( + partial(read_custom_montage, head_size=None), + ( + "NumberPositions= 96\n" + "UnitPosition mm\n" + "Positions\n" + "E01 : 5.288 -3.658 119.693\n" + "E02 : 59.518 -4.031 101.404\n" + "E03 : 29.949 -50.988 98.145\n" + "Labels\n" + "E01 E02 E03\n" + ), + make_dig_montage( + ch_pos={ + "E01": [0.005288, -0.003658, 0.119693], + "E02": [0.059518, -0.004031, 0.101404], + "E03": [0.029949, -0.050988, 0.098145], + }, + ), + "elc", + None, + id="new ASA electrode (elc)", + ), + pytest.param( + partial(read_custom_montage, head_size=None), + ( + "ReferenceLabel\n" + "avg\n" + "UnitPosition mm\n" + "NumberPositions= 6\n" + "Positions\n" + "-69.2574 10.5895 -25.0009\n" + "3.3791 94.6594 32.2592\n" + "77.2856 12.0537 -30.2488\n" + "4.6147 121.8858 8.6370\n" + "-31.3669 54.0269 94.9191\n" + "-8.7495 56.5653 99.6655\n" + "Labels\n" + "LPA\n" + "Nz\n" + "RPA\n" + "EEG 000\n" + "EEG 001\n" + "EEG 002\n" + ), + make_dig_montage( + ch_pos={ + "EEG 000": [0.004615, 0.121886, 0.008637], + "EEG 001": [-0.031367, 0.054027, 0.094919], + "EEG 002": [-0.00875, 0.056565, 0.099665], + }, + nasion=[0.003379, 0.094659, 0.032259], + lpa=[-0.069257, 0.010589, -0.025001], + rpa=[0.077286, 0.012054, -0.030249], + ), + "elc", + None, + id="another old ASA electrode (elc)", + ), + pytest.param( + partial(read_custom_montage, head_size=1), + ( + "Site Theta Phi\n" + "Fp1 -92 -72\n" + "Fp2 92 72\n" + "very_very_very_long_name -92 72\n" + "O2 92 -90\n" + ), + make_dig_montage( + ch_pos={ + "Fp1": [-0.30882875, 0.95047716, -0.0348995], + "Fp2": [0.30882875, 0.95047716, -0.0348995], + "very_very_very_long_name": [ + -0.30882875, + -0.95047716, + -0.0348995, + ], # noqa + "O2": [6.11950389e-17, -9.99390827e-01, -3.48994967e-02], + }, + nasion=None, + lpa=None, + rpa=None, + ), + "txt", + None, + id="generic theta-phi (txt)", + ), + pytest.param( + partial(read_custom_montage, head_size=None), + ( + "FID\t LPA\t -120.03\t 0\t 85\n" + "FID\t RPA\t 120.03\t 0\t 85\n" + "FID\t Nz\t 114.03\t 90\t 85\n" + "EEG\t F3\t -62.027\t -50.053\t 85\n" + "EEG\t Fz\t 45.608\t 90\t 85\n" + "EEG\t F4\t 62.01\t 50.103\t 85\n" + "EEG\t FCz\t 68.01\t 58.103\t 85\n" + ), + make_dig_montage( + ch_pos={ + "F3": [-0.48200427, 0.57551063, 0.39869712], + "Fz": [3.71915931e-17, 6.07384809e-01, 5.94629038e-01], + "F4": [0.48142596, 0.57584026, 0.39891983], + "FCz": [0.41645989, 0.66914889, 0.31827805], + }, + nasion=[4.75366562e-17, 7.76332511e-01, -3.46132681e-01], + lpa=[-7.35898963e-01, 9.01216309e-17, -4.25385374e-01], + rpa=[0.73589896, 0.0, -0.42538537], + ), + "elp", + None, + id="BESA spherical model", + ), + pytest.param( + partial(read_dig_hpts, unit="m"), + ("eeg Fp1 -95.0 -3. -3.\neeg AF7 -1 -1 -3\neeg A3 -2 -2 2\neeg A 0 0 0"), + make_dig_montage( + ch_pos={ + "A": [0.0, 0.0, 0.0], + "A3": [-2.0, -2.0, 2.0], + "AF7": [-1.0, -1.0, -3.0], + "Fp1": [-95.0, -3.0, -3.0], + }, + nasion=None, + lpa=None, + rpa=None, + ), + "hpts", + None, + id="legacy mne-c", + ), + pytest.param( + read_custom_montage, + ( + "ch_name, x, y, z\n" + "Fp1, -95.0, -3., -3.\n" + "AF7, -1, -1, -3\n" + "A3, -2, -2, 2\n" + "A, 0, 0, 0" + ), + make_dig_montage( + ch_pos={ + "A": [0.0, 0.0, 0.0], + "A3": [-2.0, -2.0, 2.0], + "AF7": [-1.0, -1.0, -3.0], + "Fp1": [-95.0, -3.0, -3.0], + }, + nasion=None, + lpa=None, + rpa=None, + ), + "csv", + None, + id="CSV file", + ), + pytest.param( + read_custom_montage, + ( + "1\t-95.0\t-3.\t-3.\tFp1\n" + "2\t-1\t-1\t-3\tAF7\n" + "3\t-2\t-2\t2\tA3\n" + "4\t0\t0\t0\tA" + ), + make_dig_montage( + ch_pos={ + "A": [0.0, 0.0, 0.0], + "A3": [-2.0, -2.0, 2.0], + "AF7": [-1.0, -1.0, -3.0], + "Fp1": [-95.0, -3.0, -3.0], + }, + nasion=None, + lpa=None, + rpa=None, + ), + "xyz", + None, + id="XYZ file", + ), + pytest.param( + read_custom_montage, + ( + "ch_name\tx\ty\tz\n" + "Fp1\t-95.0\t-3.\t-3.\n" + "AF7\t-1\t-1\t-3\n" + "A3\t-2\t-2\t2\n" + "A\t0\t0\t0" + ), + make_dig_montage( + ch_pos={ + "A": [0.0, 0.0, 0.0], + "A3": [-2.0, -2.0, 2.0], + "AF7": [-1.0, -1.0, -3.0], + "Fp1": [-95.0, -3.0, -3.0], + }, + nasion=None, + lpa=None, + rpa=None, + ), + "tsv", + None, + id="TSV file", + ), + pytest.param( + partial(read_custom_montage, head_size=None), + ( + '\n' + "\n" + '\n' + " \n" + " Fp1\n" + " -90\n" + " -72\n" + " 1\n" + " 1\n" + " \n" + " \n" + " Fz\n" + " 45\n" + " 90\n" + " 1\n" + " 2\n" + " \n" + " \n" + " F3\n" + " -60\n" + " -51\n" + " 1\n" + " 3\n" + " \n" + " \n" + " F7\n" + " -90\n" + " -36\n" + " 1\n" + " 4\n" + " \n" + "" + ), + make_dig_montage( + ch_pos={ + "Fp1": [-3.09016994e-01, 9.51056516e-01, 6.12323400e-17], + "Fz": [4.32978028e-17, 7.07106781e-01, 7.07106781e-01], + "F3": [-0.54500745, 0.67302815, 0.5], + "F7": [-8.09016994e-01, 5.87785252e-01, 6.12323400e-17], + }, + nasion=None, + lpa=None, + rpa=None, + ), + "bvef", + None, + id="brainvision", + ), + ], +) +def test_montage_readers(reader, file_content, expected_dig, ext, warning, tmp_path): + """Test that we have an equivalent of read_montage for all file formats.""" + if file_content.startswith("" + ) + + assert set([d["coord_frame"] for d in montage.dig]) == {FIFF.FIFFV_COORD_UNKNOWN} + + EXPECTED_FID_IN_POLHEMUS = { + "nasion": [0.001393, 0.0131613, -0.0046967], + "lpa": [-0.0624997, -0.0737271, 0.07996], + "rpa": [-0.0748957, 0.0873785, 0.0811943], + } + fiducials, fid_coordframe = _get_fid_coords(montage.dig) + assert fid_coordframe == FIFF.FIFFV_COORD_UNKNOWN + for kk, val in fiducials.items(): + assert_allclose(val, EXPECTED_FID_IN_POLHEMUS[kk]) + + +def test_read_dig_montage_using_polhemus_fastscan_error_handling(tmp_path): + """Test reading Polhemus FastSCAN errors.""" + with open(kit_dir / "test_elp.txt") as fid: + content = fid.read().replace("FastSCAN", "XxxxXXXX") + + fname = tmp_path / "faulty_FastSCAN.txt" + with open(fname, "w") as fid: + fid.write(content) + + with pytest.raises(ValueError, match="not contain.*Polhemus FastSCAN"): + _ = read_polhemus_fastscan(fname) + + fname = tmp_path / "faulty_FastSCAN.bar" + with open(fname, "w") as fid: + fid.write(content) + EXPECTED_ERR_MSG = "allowed value is '.txt', but got '.bar' instead" + with pytest.raises(ValueError, match=EXPECTED_ERR_MSG): + _ = read_polhemus_fastscan(fname=fname) + + +def test_read_dig_polhemus_isotrak_hsp(): + """Test reading Polhemus IsoTrak HSP file.""" + EXPECTED_FID_IN_POLHEMUS = { + "nasion": np.array([1.1056e-01, -5.4210e-19, 0]), + "lpa": np.array([-2.1075e-04, 8.0793e-02, -7.5894e-19]), + "rpa": np.array([2.1075e-04, -8.0793e-02, -2.8731e-18]), + } + montage = read_dig_polhemus_isotrak(fname=kit_dir / "test.hsp", ch_names=None) + assert repr(montage) == ( + "" + ) + + fiducials, fid_coordframe = _get_fid_coords(montage.dig) + + assert fid_coordframe == FIFF.FIFFV_COORD_UNKNOWN + for kk, val in fiducials.items(): + assert_array_equal(val, EXPECTED_FID_IN_POLHEMUS[kk]) + + +def test_read_dig_polhemus_isotrak_elp(): + """Test reading Polhemus IsoTrak ELP file.""" + EXPECTED_FID_IN_POLHEMUS = { + "nasion": np.array([1.1056e-01, -5.4210e-19, 0]), + "lpa": np.array([-2.1075e-04, 8.0793e-02, -7.5894e-19]), + "rpa": np.array([2.1075e-04, -8.0793e-02, -2.8731e-18]), + } + montage = read_dig_polhemus_isotrak(fname=kit_dir / "test.elp", ch_names=None) + assert repr(montage) == ( + "" + ) + fiducials, fid_coordframe = _get_fid_coords(montage.dig) + + assert fid_coordframe == FIFF.FIFFV_COORD_UNKNOWN + for kk, val in fiducials.items(): + assert_array_equal(val, EXPECTED_FID_IN_POLHEMUS[kk]) + + +@pytest.fixture(scope="module") +def isotrak_eeg(tmp_path_factory): + """Mock isotrak file with EEG positions.""" + _SEED = 42 + N_ROWS, N_COLS = 5, 3 + content = np.random.RandomState(_SEED).randn(N_ROWS, N_COLS) + + fname = tmp_path_factory.mktemp("data") / "test.eeg" + with open(str(fname), "w") as fid: + fid.write( + "3 200\n" + "//Shape file\n" + "//Minor revision number\n" + "2\n" + "//Subject Name\n" + "%N Name \n" + "////Shape code, number of digitized points\n" + ) + fid.write(f"0 {N_ROWS:d}\n") + fid.write( + "//Position of fiducials X+, Y+, Y- on the subject\n" + "%F 0.11056 -5.421e-19 0 \n" + "%F -0.00021075 0.080793 -7.5894e-19 \n" + "%F 0.00021075 -0.080793 -2.8731e-18 \n" + "//No of rows, no of columns; position of digitized points\n" + ) + fid.write(f"{N_ROWS} {N_COLS}\n") + for row in content: + fid.write("\t".join(f"{cell:0.18e}" for cell in row) + "\n") + + return str(fname) + + +def test_read_dig_polhemus_isotrak_eeg(isotrak_eeg): + """Test reading Polhemus IsoTrak EEG positions.""" + N_CHANNELS = 5 + _SEED = 42 + EXPECTED_FID_IN_POLHEMUS = { + "nasion": np.array([1.1056e-01, -5.4210e-19, 0]), + "lpa": np.array([-2.1075e-04, 8.0793e-02, -7.5894e-19]), + "rpa": np.array([2.1075e-04, -8.0793e-02, -2.8731e-18]), + } + ch_names = [f"eeg {ii:01d}" for ii in range(N_CHANNELS)] + EXPECTED_CH_POS = dict( + zip(ch_names, np.random.RandomState(_SEED).randn(N_CHANNELS, 3)) + ) + + montage = read_dig_polhemus_isotrak(fname=isotrak_eeg, ch_names=ch_names) + assert repr(montage) == ( + "" + ) + + fiducials, fid_coordframe = _get_fid_coords(montage.dig) + + assert fid_coordframe == FIFF.FIFFV_COORD_UNKNOWN + for kk, val in fiducials.items(): + assert_array_equal(val, EXPECTED_FID_IN_POLHEMUS[kk]) + + for kk, dig_point in zip(montage.ch_names, _get_dig_eeg(montage.dig)): + assert_array_equal(dig_point["r"], EXPECTED_CH_POS[kk]) + assert dig_point["coord_frame"] == FIFF.FIFFV_COORD_UNKNOWN + + +def test_read_dig_polhemus_isotrak_error_handling(isotrak_eeg, tmp_path): + """Test errors in reading Polhemus IsoTrak files. + + 1 - matching ch_names and number of points in isotrak file. + 2 - error for unsupported file extensions. + """ + # Check ch_names + N_CHANNELS = 5 + EXPECTED_ERR_MSG = "not match the number of points.*Expected.*5, given 47" + with pytest.raises(ValueError, match=EXPECTED_ERR_MSG): + _ = read_dig_polhemus_isotrak( + fname=isotrak_eeg, + ch_names=[f"eeg {ii:01d}" for ii in range(N_CHANNELS + 42)], + ) + + # Check fname extensions + fname = tmp_path / "test.bar" + shutil.copyfile(isotrak_eeg, fname) + + with pytest.raises( + ValueError, + match="Allowed val.*'.hsp', '.elp', and '.eeg', but got '.bar' instead", + ): + _ = read_dig_polhemus_isotrak(fname=fname, ch_names=None) + + +def test_combining_digmontage_objects(): + """Test combining different DigMontage objects.""" + rng = np.random.RandomState(0) + fiducials = dict(zip(("nasion", "lpa", "rpa"), rng.rand(3, 3))) + + # hsp positions are [1X, 1X, 1X] + hsp1 = make_dig_montage(**fiducials, hsp=np.full((2, 3), 11.0)) + hsp2 = make_dig_montage(**fiducials, hsp=np.full((2, 3), 12.0)) + hsp3 = make_dig_montage(**fiducials, hsp=np.full((2, 3), 13.0)) + + # hpi positions are [2X, 2X, 2X] + hpi1 = make_dig_montage(**fiducials, hpi=np.full((2, 3), 21.0)) + hpi2 = make_dig_montage(**fiducials, hpi=np.full((2, 3), 22.0)) + hpi3 = make_dig_montage(**fiducials, hpi=np.full((2, 3), 23.0)) + + # channels have positions at 40s, 50s, and 60s. + ch_pos1 = make_dig_montage( + **fiducials, ch_pos={"h": [41, 41, 41], "b": [42, 42, 42], "g": [43, 43, 43]} + ) + ch_pos2 = make_dig_montage( + **fiducials, ch_pos={"n": [51, 51, 51], "y": [52, 52, 52], "p": [53, 53, 53]} + ) + ch_pos3 = make_dig_montage( + **fiducials, ch_pos={"v": [61, 61, 61], "a": [62, 62, 62], "l": [63, 63, 63]} + ) + + montage = ( + DigMontage() + + hsp1 + + hsp2 + + hsp3 + + hpi1 + + hpi2 + + hpi3 + + ch_pos1 + + ch_pos2 + + ch_pos3 + ) + assert repr(montage) == ( + "" + ) + + EXPECTED_MONTAGE = make_dig_montage( + **fiducials, + hsp=np.concatenate( + [np.full((2, 3), 11.0), np.full((2, 3), 12.0), np.full((2, 3), 13.0)] + ), + hpi=np.concatenate( + [np.full((2, 3), 21.0), np.full((2, 3), 22.0), np.full((2, 3), 23.0)] + ), + ch_pos={ + "h": [41, 41, 41], + "b": [42, 42, 42], + "g": [43, 43, 43], + "n": [51, 51, 51], + "y": [52, 52, 52], + "p": [53, 53, 53], + "v": [61, 61, 61], + "a": [62, 62, 62], + "l": [63, 63, 63], + }, + ) + + # Do some checks to ensure they are the same DigMontage + assert len(montage.ch_names) == len(EXPECTED_MONTAGE.ch_names) + assert all([c in montage.ch_names for c in EXPECTED_MONTAGE.ch_names]) + actual_occurrences = _count_points_by_type(montage.dig) + expected_occurrences = _count_points_by_type(EXPECTED_MONTAGE.dig) + assert actual_occurrences == expected_occurrences + + +def test_combining_digmontage_forbiden_behaviors(): + """Test combining different DigMontage objects with repeated names.""" + rng = np.random.RandomState(0) + fiducials = dict(zip(("nasion", "lpa", "rpa"), rng.rand(3, 3))) + dig1 = make_dig_montage( + **fiducials, + ch_pos=dict(zip(list("abc"), rng.rand(3, 3))), + ) + dig2 = make_dig_montage( + **fiducials, + ch_pos=dict(zip(list("bcd"), rng.rand(3, 3))), + ) + dig2_wrong_fid = make_dig_montage( + nasion=rng.rand(3), + lpa=rng.rand(3), + rpa=rng.rand(3), + ch_pos=dict(zip(list("ghi"), rng.rand(3, 3))), + ) + dig2_wrong_coordframe = make_dig_montage( + **fiducials, ch_pos=dict(zip(list("ghi"), rng.rand(3, 3))), coord_frame="meg" + ) + + EXPECTED_ERR_MSG = "Cannot.*duplicated channel.*found: 'b', 'c'." + with pytest.raises(RuntimeError, match=EXPECTED_ERR_MSG): + _ = dig1 + dig2 + + with pytest.raises(RuntimeError, match="fiducial locations do not match"): + _ = dig1 + dig2_wrong_fid + + with pytest.raises(RuntimeError, match="not in the same coordinate "): + _ = dig1 + dig2_wrong_coordframe + + +def test_set_dig_montage(): + """Test setting DigMontage with toy understandable points.""" + N_CHANNELS, N_HSP, N_HPI = 3, 2, 1 + ch_names = list(ascii_lowercase[:N_CHANNELS]) + ch_pos = dict( + zip( + ch_names, + np.arange(N_CHANNELS * 3).reshape(N_CHANNELS, 3), + ) + ) + + montage_ch_only = make_dig_montage(ch_pos=ch_pos, coord_frame="head") + + assert repr(montage_ch_only) == ( + "" + ) + info = create_info(ch_names, sfreq=1, ch_types="eeg") + info.set_montage(montage_ch_only) + assert len(info["dig"]) == len(montage_ch_only.dig) + 3 # added fiducials + + assert_allclose( + actual=np.array([ch["loc"][:6] for ch in info["chs"]]), + desired=[ + [0.0, 1.0, 2.0, 0.0, 0.0, 0.0], + [3.0, 4.0, 5.0, 0.0, 0.0, 0.0], + [6.0, 7.0, 8.0, 0.0, 0.0, 0.0], + ], + ) + + montage_full = make_dig_montage( + ch_pos=dict(**ch_pos, EEG000=np.full(3, 42)), # 4 = 3 egg + 1 eeg_ref + nasion=[1, 1, 1], + lpa=[2, 2, 2], + rpa=[3, 3, 3], + hsp=np.full((N_HSP, 3), 4), + hpi=np.full((N_HPI, 3), 4), + coord_frame="head", + ) + + assert repr(montage_full) == ( + "" + ) + + info = create_info(ch_names, sfreq=1, ch_types="eeg") + info.set_montage(montage_full) + EXPECTED_LEN = sum({"hsp": 2, "hpi": 1, "fid": 3, "eeg": 4}.values()) + assert len(info["dig"]) == EXPECTED_LEN + assert_allclose( + actual=np.array([ch["loc"][:6] for ch in info["chs"]]), + desired=[ + [0.0, 1.0, 2.0, 42.0, 42.0, 42.0], + [3.0, 4.0, 5.0, 42.0, 42.0, 42.0], + [6.0, 7.0, 8.0, 42.0, 42.0, 42.0], + ], + ) + + +def test_set_dig_montage_with_nan_positions(): + """Test that fiducials are not NaN. + + Test that setting a montage with some NaN positions does not produce + NaN fiducials. + """ + + def _ensure_fid_not_nan(info, ch_pos): + montage_kwargs = dict(ch_pos=dict(), coord_frame="head") + for ch_idx, ch in enumerate(info.ch_names): + montage_kwargs["ch_pos"][ch] = ch_pos[ch_idx] + + new_montage = make_dig_montage(**montage_kwargs) + info = info.copy() + info.set_montage(new_montage) + + recovered_montage = info.get_montage() + fid_coords, coord_frame = _get_fid_coords( + recovered_montage.dig, raise_error=False + ) + + for fid_coord in fid_coords.values(): + if fid_coord is not None: + assert not np.isnan(fid_coord).any() + + return fid_coords, coord_frame + + channels = list("ABCDEF") + info = create_info(channels, 1000, ch_types="seeg") + + # if all positions are NaN, the fiducials should not be NaN, but None + ch_pos = [info["chs"][ch_idx]["loc"][:3] for ch_idx in range(len(channels))] + fid_coords, coord_frame = _ensure_fid_not_nan(info, ch_pos) + for fid_coord in fid_coords.values(): + assert fid_coord is None + assert coord_frame is None + + # if some positions are not NaN, the fiducials should be a non-NaN array + ch_pos[0] = np.array([1.0, 1.5, 1.0]) + ch_pos[1] = np.array([2.0, 1.5, 1.5]) + ch_pos[2] = np.array([1.25, 1.0, 1.25]) + fid_coords, coord_frame = _ensure_fid_not_nan(info, ch_pos) + for fid_coord in fid_coords.values(): + assert isinstance(fid_coord, np.ndarray) + assert coord_frame == FIFF.FIFFV_COORD_HEAD + + +@testing.requires_testing_data +def test_fif_dig_montage(tmp_path, monkeypatch): + """Test FIF dig montage support.""" + dig_montage = read_dig_fif(fif_dig_montage_fname, verbose="error") + + # test round-trip IO + fname_temp = tmp_path / "test-dig.fif" + _check_roundtrip(dig_montage, fname_temp) + + # Make a BrainVision file like the one the user would have had + raw_bv = read_raw_brainvision(bv_fname, preload=True) + raw_bv_2 = raw_bv.copy() + mapping = dict() + for ii, ch_name in enumerate(raw_bv.ch_names, 1): + mapping[ch_name] = f"EEG{ii:03d}" + raw_bv.rename_channels(mapping) + for ii, ch_name in enumerate(raw_bv_2.ch_names, 33): + mapping[ch_name] = f"EEG{ii:03d}" + raw_bv_2.rename_channels(mapping) + raw_bv.add_channels([raw_bv_2]) + for ch in raw_bv.info["chs"]: + ch["kind"] = FIFF.FIFFV_EEG_CH + + # Set the montage + raw_bv.set_montage(dig_montage) + + # Check the result + evoked = read_evokeds(evoked_fname)[0] + + # check info[chs] matches + assert_equal(len(raw_bv.ch_names), len(evoked.ch_names) - 1) + for ch_py, ch_c in zip(raw_bv.info["chs"], evoked.info["chs"][:-1]): + assert_equal(ch_py["ch_name"], ch_c["ch_name"].replace("EEG ", "EEG")) + # C actually says it's unknown, but it's not (?): + # assert_equal(ch_py['coord_frame'], ch_c['coord_frame']) + assert_equal(ch_py["coord_frame"], FIFF.FIFFV_COORD_HEAD) + c_loc = ch_c["loc"].copy() + c_loc[c_loc == 0] = np.nan + assert_allclose(ch_py["loc"], c_loc, atol=1e-7) + + # check info[dig] + assert_dig_allclose(raw_bv.info, evoked.info) + + # Roundtrip of non-FIF start + montage = make_dig_montage(hsp=read_polhemus_fastscan(hsp), hpi=read_mrk(hpi)) + elp_points = read_polhemus_fastscan(elp) + ch_pos = {f"ECoG{k:03d}": pos for k, pos in enumerate(elp_points[3:], 1)} + assert len(elp_points) == 8 # there are only 8 but pretend the last are ECoG + other = make_dig_montage( + nasion=elp_points[0], lpa=elp_points[1], rpa=elp_points[2], ch_pos=ch_pos + ) + assert other.ch_names[0].startswith("ECoG") + montage += other + assert montage.ch_names[0].startswith("ECoG") + _check_roundtrip(montage, fname_temp, "unknown") + montage = transform_to_head(montage) + _check_roundtrip(montage, fname_temp) + montage.dig[0]["coord_frame"] = FIFF.FIFFV_COORD_UNKNOWN + with pytest.raises(RuntimeError, match="Only a single coordinate"): + montage.save(fname_temp, overwrite=True) + montage.dig[0]["coord_frame"] = FIFF.FIFFV_COORD_HEAD + + # Check that old-style files can be read, too, using EEG001 etc. + def write_dig_no_ch_names(*args, **kwargs): + kwargs["ch_names"] = None + return write_dig(*args, **kwargs) + + monkeypatch.setattr(mne.channels.montage, "write_dig", write_dig_no_ch_names) + montage.save(fname_temp, overwrite=True) + montage_read = read_dig_fif(fname_temp) + default_ch_names = [f"EEG{ii:03d}" for ii in range(1, 6)] + assert montage_read.ch_names == default_ch_names + + +@testing.requires_testing_data +def test_egi_dig_montage(tmp_path): + """Test EGI MFF XML dig montage support.""" + pytest.importorskip("defusedxml") + dig_montage = read_dig_egi(egi_dig_montage_fname) + fid, coord = _get_fid_coords(dig_montage.dig) + + assert coord == FIFF.FIFFV_COORD_UNKNOWN + assert_allclose( + actual=np.array([fid[key] for key in ["nasion", "lpa", "rpa"]]), + desired=[ + [0.0, 10.564, -2.051], # noqa + [-8.592, 0.498, -4.128], # noqa + [8.592, 0.498, -4.128], + ], # noqa + ) + + # Test accuracy and embedding within raw object + raw_egi = read_raw_egi( + egi_raw_fname, + channel_naming="EEG %03d", + events_as_annotations=True, + ) + + raw_egi.set_montage(dig_montage) + test_raw_egi = read_raw_fif(egi_fif_fname) + + assert_equal(len(raw_egi.ch_names), len(test_raw_egi.ch_names)) + for ch_raw, ch_test_raw in zip(raw_egi.info["chs"], test_raw_egi.info["chs"]): + assert_equal(ch_raw["ch_name"], ch_test_raw["ch_name"]) + assert_equal(ch_raw["coord_frame"], FIFF.FIFFV_COORD_HEAD) + assert_allclose(ch_raw["loc"], ch_test_raw["loc"], atol=1e-7) + + assert_dig_allclose(raw_egi.info, test_raw_egi.info) + + dig_montage_in_head = transform_to_head(dig_montage.copy()) + fid, coord = _get_fid_coords(dig_montage_in_head.dig) + assert coord == FIFF.FIFFV_COORD_HEAD + assert_allclose( + actual=np.array([fid[key] for key in ["nasion", "lpa", "rpa"]]), + desired=[[0.0, 10.278, 0.0], [-8.592, 0.0, 0.0], [8.592, 0.0, 0.0]], + atol=1e-4, + ) + + # test round-trip IO (with GZ) + fname_temp = tmp_path / "egi_test-dig.fif.gz" + _check_roundtrip(dig_montage, fname_temp, "unknown") + _check_roundtrip(dig_montage_in_head, fname_temp) + + +@testing.requires_testing_data +def test_read_dig_captrak(tmp_path): + """Test reading a captrak montage file.""" + pytest.importorskip("defusedxml") + EXPECTED_CH_NAMES_OLD = [ + "AF3", + "AF4", + "AF7", + "AF8", + "C1", + "C2", + "C3", + "C4", + "C5", + "C6", + "CP1", + "CP2", + "CP3", + "CP4", + "CP5", + "CP6", + "CPz", + "Cz", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "FC1", + "FC2", + "FC3", + "FC4", + "FC5", + "FC6", + "FT10", + "FT7", + "FT8", + "FT9", + "Fp1", + "Fp2", + "Fz", + "GND", + "O1", + "O2", + "Oz", + "P1", + "P2", + "P3", + "P4", + "P5", + "P6", + "P7", + "P8", + "PO10", + "PO3", + "PO4", + "PO7", + "PO8", + "PO9", + "POz", + "Pz", + "REF", + "T7", + "T8", + "TP10", + "TP7", + "TP8", + "TP9", + ] + EXPECTED_CH_NAMES = [ + "T7", + "FC5", + "F7", + "C5", + "FT7", + "FT9", + "TP7", + "TP9", + "P7", + "CP5", + "PO7", + "C3", + "CP3", + "P5", + "P3", + "PO3", + "PO9", + "O1", + "Oz", + "POz", + "O2", + "PO4", + "P1", + "Pz", + "P2", + "CP2", + "CP1", + "CPz", + "Cz", + "C1", + "FC1", + "FC3", + "REF", + "F3", + "F1", + "Fz", + "F5", + "AF7", + "AF3", + "Fp1", + "GND", + "F2", + "AF4", + "Fp2", + "F4", + "F8", + "F6", + "AF8", + "FC2", + "FC6", + "FC4", + "C2", + "C4", + "P4", + "CP4", + "PO8", + "P8", + "P6", + "CP6", + "PO10", + "TP10", + "TP8", + "FT10", + "T8", + "C6", + "FT8", + ] + assert set(EXPECTED_CH_NAMES) == set(EXPECTED_CH_NAMES_OLD) + montage = read_dig_captrak(fname=data_path / "montage" / "captrak_coords.bvct") + + assert montage.ch_names == EXPECTED_CH_NAMES + assert repr(montage) == ( + "" + ) + + montage = transform_to_head(montage) # transform_to_head has to be tested + _check_roundtrip(montage=montage, fname=tmp_path / "bvct_test-dig.fif") + + fid, _ = _get_fid_coords(montage.dig) + assert_allclose( + actual=np.array([fid.nasion, fid.lpa, fid.rpa]), + desired=[[0, 0.11309, 0], [-0.09189, 0, 0], [0.09240, 0, 0]], + atol=1e-5, + ) + + raw_bv = read_raw_brainvision(bv_raw_fname) + raw_bv.set_channel_types({"HEOG": "eog", "VEOG": "eog", "ECG": "ecg"}) + + raw_bv.set_montage(montage) + + test_raw_bv = read_raw_fif(bv_fif_fname) + + # compare after set_montage using chs loc. + for actual, expected in zip(raw_bv.info["chs"], test_raw_bv.info["chs"]): + assert_allclose(actual["loc"][:3], expected["loc"][:3]) + if actual["kind"] == FIFF.FIFFV_EEG_CH: + assert_allclose( + actual["loc"][3:6], [-0.005103, 0.05395, 0.144622], rtol=1e-04 + ) + + +# https://gist.github.com/larsoner/2264fb5895070d29a8c9aa7c0dc0e8a6 +_MGH60 = ( + "Fp1 Fpz Fp2 " + "AF7 AF3 AF4 AF8 " + "F7 F5 F3 F1 Fz F2 F4 F6 F8 " + "FT9 FT7 FC5 FC1 FC2 FC6 FT8 FT10 " + "T9 T7 C5 C3 C1 Cz C2 C4 C6 T8 T10 " + "TP9 TP7 CP3 CP1 CP2 CP4 TP8 TP10 " + "P7 P5 P3 P1 Pz P2 P4 P6 P8 " + "PO7 PO3 PO4 PO8 " + "O1 Oz O2 " + "Iz" +).split() + + +@pytest.mark.parametrize("rename", ("raw", "montage", "custom")) +def test_set_montage_mgh(rename): + """Test setting 'mgh60' montage to old fif.""" + raw = read_raw_fif(fif_fname) + eeg_picks = pick_types(raw.info, meg=False, eeg=True, exclude=()) + assert list(eeg_picks) == [ + ii for ii, name in enumerate(raw.ch_names) if name.startswith("EEG") + ] + orig_pos = np.array([raw.info["chs"][pick]["loc"][:3] for pick in eeg_picks]) + atol = 1e-6 + mon = None + if rename == "raw": + raw.rename_channels(lambda x: x.replace("EEG ", "EEG")) + raw.set_montage("mgh60") # test loading with string argument + elif rename == "montage": + mon = make_standard_montage("mgh60") + mon.rename_channels(lambda x: x.replace("EEG", "EEG ")) + assert [raw.ch_names[pick] for pick in eeg_picks] == mon.ch_names + raw.set_montage(mon) + else: + atol = 3e-3 # different subsets of channel locations + assert rename == "custom" + assert len(_MGH60) == 60 + mon = make_standard_montage("standard_1020") + assert len(mon._get_ch_pos()) == 94 + + def renamer(x): + try: + return f"EEG {_MGH60.index(x) + 1:03d}" + except ValueError: + return x + + mon = mon.rename_channels(renamer) + raw.set_montage(mon) + + if mon is not None: + # first two are 'Fp1' and 'Fz', take them from standard_1020.elc -- + # they should not be changed on load! + want_pos = [[-29.4367, 83.9171, -6.9900], [0.1123, 88.2470, -1.7130]] + got_pos = [ + mon.get_positions()["ch_pos"][f"EEG {x:03d}"] * 1000 for x in range(1, 3) + ] + assert_allclose(want_pos, got_pos) + assert mon.dig[0]["coord_frame"] == FIFF.FIFFV_COORD_MRI + trans = compute_native_head_t(mon) + trans_2 = _get_trans("fsaverage", "mri", "head")[0] + assert trans["to"] == trans_2["to"] + assert trans["from"] == trans_2["from"] + assert_allclose(trans["trans"], trans_2["trans"], atol=1e-6) + + new_pos = np.array( + [ch["loc"][:3] for ch in raw.info["chs"] if ch["ch_name"].startswith("EEG")] + ) + assert (orig_pos != new_pos).all() + + r0 = _fit_sphere(new_pos)[1] + assert_allclose(r0, [-0.001043, 0.01469, 0.041448], atol=1e-4) + # spot check: Fp1 and Fpz + assert_allclose( + new_pos[:2], + [[-0.030903, 0.114585, 0.027867], [-0.001337, 0.119102, 0.03289]], + atol=atol, + ) + + +@pytest.mark.parametrize( + "fname, montage, n_eeg, n_good, bads", + [ + (fif_fname, "mgh60", 60, 59, ["EEG 053"]), + pytest.param( + mgh70_fname, "mgh70", 70, 64, None, marks=[testing._pytest_mark()] + ), + ], +) +def test_montage_positions_similar(fname, montage, n_eeg, n_good, bads): + """Test that montages give spatially similar positions.""" + # 1. Prepare data: load, set bads (if missing), and filter + raw = read_raw_fif(fname).pick(picks="eeg") + if bads is not None: + assert raw.info["bads"] == [] + raw.info["bads"] = bads + assert len(raw.ch_names) == n_eeg + raw.pick(picks="eeg", exclude="bads").load_data() + raw.apply_function(lambda x: x - x.mean()) # remove DC + raw.filter(None, 40) # remove line noise + assert len(raw.ch_names) == n_good + if montage == "mgh60": + montage = make_standard_montage(montage) + montage.rename_channels(lambda n: f"EEG {n[-3:]}") + raw_mon = raw.copy().set_montage(montage) + # 2. First test: CSDs should be similar (CSD uses 3D positions) + csd = compute_current_source_density(raw).get_data() + csd_mon = compute_current_source_density(raw_mon).get_data() + corr = np.corrcoef(csd.ravel(), csd_mon.ravel())[0, 1] + assert 0.9 < corr < 0.99, corr + # 3. Second test: interpolation of some bads should be similar + bad_picks = np.linspace(0, n_good, 6, endpoint=False).round().astype(int) + bads = [raw.ch_names[idx] for idx in bad_picks] + orig_data = raw.get_data(bad_picks) + assert_allclose(orig_data, raw_mon.get_data(bad_picks)) + raw.info["bads"] = bads + raw_mon.info["bads"] = bads + raw.interpolate_bads() + raw_mon.interpolate_bads() + orig_data = orig_data.ravel() + corr = np.corrcoef(orig_data, raw.get_data(bad_picks).ravel())[0, 1] + assert 0.95 < corr < 0.99, corr + corr = np.corrcoef(orig_data, raw_mon.get_data(bad_picks).ravel())[0, 1] + assert 0.95 < corr < 0.99, corr + # 4. Third test: project each to a sphere, check cosine angles are small + poss = dict() + for kind, this_raw in (("orig", raw), ("mon", raw_mon)): + pos = np.array( + list(this_raw.get_montage().get_positions()["ch_pos"].values()), float + ) + pos -= np.mean(pos, axis=0) + pos /= np.linalg.norm(pos, axis=1, keepdims=True) + poss[kind] = pos + ang = np.rad2deg( # arccos is in [0, pi] + np.arccos(np.minimum(np.sum(poss["orig"] * poss["mon"], axis=1), 1)) + ) + assert_array_less(ang, 20) # less than 20 deg + assert_array_less(0, ang) # but not equal + + +def _check_roundtrip(montage, fname, coord_frame="head"): + """Check roundtrip writing.""" + montage.save(fname, overwrite=True) + montage_read = read_dig_fif(fname=fname) + + assert repr(montage) == repr(montage_read) + assert _check_get_coord_frame(montage_read.dig) == coord_frame + assert_dig_allclose(montage, montage_read) + assert montage.ch_names == montage_read.ch_names + + +def test_digmontage_constructor_errors(): + """Test proper error messaging.""" + with pytest.raises(ValueError, match="does not match the number"): + _ = DigMontage(ch_names=["foo", "bar"], dig=list()) + + +def test_transform_to_head_and_compute_dev_head_t(): + """Test transform_to_head and compute_dev_head_t.""" + EXPECTED_DEV_HEAD_T = [ + [-3.72201691e-02, -9.98212167e-01, -4.67667497e-02, -7.31583414e-04], + [8.98064989e-01, -5.39382685e-02, 4.36543170e-01, 1.60134431e-02], + [-4.38285221e-01, -2.57513699e-02, 8.98466990e-01, 6.13035748e-02], + [0.00000000e00, 0.00000000e00, 0.00000000e00, 1.00000000e00], + ] + + EXPECTED_FID_IN_POLHEMUS = { + "nasion": np.array([0.001393, 0.0131613, -0.0046967]), + "lpa": np.array([-0.0624997, -0.0737271, 0.07996]), + "rpa": np.array([-0.0748957, 0.0873785, 0.0811943]), + } + + EXPECTED_FID_IN_HEAD = { + "nasion": np.array([-8.94466792e-18, 1.10559624e-01, -3.85185989e-34]), + "lpa": np.array([-8.10816716e-02, 6.56321671e-18, 0]), + "rpa": np.array([8.05048781e-02, -6.47441364e-18, 0]), + } + + hpi_dev = np.array( + [ + [2.13951493e-02, 8.47444056e-02, -5.65431188e-02], # noqa + [2.10299433e-02, -8.03141101e-02, -6.34420259e-02], # noqa + [1.05916829e-01, 8.18485672e-05, 1.19928083e-02], # noqa + [9.26595105e-02, 4.64804385e-02, 8.45141253e-03], # noqa + [9.42554419e-02, -4.35206589e-02, 8.78999363e-03], + ] # noqa + ) + + hpi_polhemus = np.array( + [ + [-0.0595004, -0.0704836, 0.075893], # noqa + [-0.0646373, 0.0838228, 0.0762123], # noqa + [-0.0135035, 0.0072522, -0.0268405], # noqa + [-0.0202967, -0.0351498, -0.0129305], # noqa + [-0.0277519, 0.0452628, -0.0222407], + ] # noqa + ) + + montage_polhemus = make_dig_montage( + **EXPECTED_FID_IN_POLHEMUS, hpi=hpi_polhemus, coord_frame="unknown" + ) + + montage_meg = make_dig_montage(hpi=hpi_dev, coord_frame="meg") + + # Test regular workflow to get dev_head_t + montage = montage_polhemus + montage_meg + fids, _ = _get_fid_coords(montage.dig) + for kk in fids: + assert_allclose(fids[kk], EXPECTED_FID_IN_POLHEMUS[kk], atol=1e-5) + + with pytest.raises(ValueError, match="set to head coordinate system"): + _ = compute_dev_head_t(montage) + + montage = transform_to_head(montage) + + fids, _ = _get_fid_coords(montage.dig) + for kk in fids: + assert_allclose(fids[kk], EXPECTED_FID_IN_HEAD[kk], atol=1e-5) + + dev_head_t = compute_dev_head_t(montage) + assert_allclose(dev_head_t["trans"], EXPECTED_DEV_HEAD_T, atol=5e-7) + + # Test errors when number of HPI points do not match + EXPECTED_ERR_MSG = "Device-to-Head .*Got 0 .*device and 5 points in head" + with pytest.raises(ValueError, match=EXPECTED_ERR_MSG): + _ = compute_dev_head_t(transform_to_head(montage_polhemus)) + + EXPECTED_ERR_MSG = "Device-to-Head .*Got 5 .*device and 0 points in head" + with pytest.raises(ValueError, match=EXPECTED_ERR_MSG): + _ = compute_dev_head_t( + transform_to_head( + montage_meg + make_dig_montage(**EXPECTED_FID_IN_POLHEMUS) + ) + ) + + EXPECTED_ERR_MSG = "Device-to-Head .*Got 3 .*device and 5 points in head" + with pytest.raises(ValueError, match=EXPECTED_ERR_MSG): + _ = compute_dev_head_t( + transform_to_head( + DigMontage(dig=_format_dig_points(montage_meg.dig[:3])) + + montage_polhemus + ) + ) + + +def test_set_montage_with_mismatching_ch_names(): + """Test setting a DigMontage with mismatching ch_names.""" + raw = read_raw_fif(fif_fname) + montage = make_standard_montage("mgh60") + + # 'EEG 001' and 'EEG001' won't match + missing_err = "60 channel positions not present" + with pytest.raises(ValueError, match=missing_err): + raw.set_montage(montage) + + montage.ch_names = [ # modify the names in place + name.replace("EEG", "EEG ") for name in montage.ch_names + ] + raw.set_montage(montage) # does not raise + + # Case sensitivity + raw.rename_channels(lambda x: x.lower()) + with pytest.raises(ValueError, match=missing_err): + raw.set_montage(montage) + # should work + raw.set_montage(montage, match_case=False) + raw.rename_channels(lambda x: x.upper()) # restore + assert "EEG 001" in raw.ch_names and "eeg 001" not in raw.ch_names + raw.rename_channels({"EEG 002": "eeg 001"}) + assert "EEG 001" in raw.ch_names and "eeg 001" in raw.ch_names + with pytest.warns(RuntimeWarning, match="changed from V to NA"): + raw.set_channel_types({"eeg 001": "misc"}) + raw.set_montage(montage) + with pytest.warns(RuntimeWarning, match="changed from NA to V"): + raw.set_channel_types({"eeg 001": "eeg"}) + with pytest.raises(ValueError, match="1 channel position not present"): + raw.set_montage(montage) + with pytest.raises(ValueError, match="match_case=False as 1 channel name"): + raw.set_montage(montage, match_case=False) + info = create_info(["EEG 001"], 1000.0, "eeg") + mon = make_dig_montage( + {"EEG 001": np.zeros(3), "eeg 001": np.zeros(3)}, + nasion=[0, 1.0, 0], + rpa=[1.0, 0, 0], + lpa=[-1.0, 0, 0], + ) + info.set_montage(mon) + with pytest.raises(ValueError, match="match_case=False as 1 montage name"): + info.set_montage(mon, match_case=False) + + +def test_set_montage_with_sub_super_set_of_ch_names(): + """Test info and montage ch_names matching criteria.""" + N_CHANNELS = len("abcdef") + montage = _make_toy_dig_montage(N_CHANNELS, coord_frame="head") + + # montage and info match + info = create_info(ch_names=list("abcdef"), sfreq=1, ch_types="eeg") + info.set_montage(montage) + + # montage is a SUPERset of info + info = create_info(list("abc"), sfreq=1, ch_types="eeg") + info.set_montage(montage) + assert len(info["dig"]) == len(list("abc")) + 3 # 3 fiducials + + # montage is a SUBset of info + _MSG = "subset of info. There are 2 .* not present in the DigMontage" + info = create_info(ch_names=list("abcdfgh"), sfreq=1, ch_types="eeg") + with pytest.raises(ValueError, match=_MSG) as exc: + info.set_montage(montage) + # plus suggestions + assert exc.match("set_channel_types") + assert exc.match("on_missing") + + +def test_set_montage_with_known_aliases(): + """Test matching unrecognized channel locations to known aliases.""" + # montage and info match + mock_montage_ch_names = ["POO7", "POO8"] + n_channels = len(mock_montage_ch_names) + + montage = make_dig_montage( + ch_pos=dict( + zip( + mock_montage_ch_names, + np.arange(n_channels * 3).reshape(n_channels, 3), + ) + ), + coord_frame="head", + ) + + mock_info_ch_names = ["Cb1", "Cb2"] + info = create_info(ch_names=mock_info_ch_names, sfreq=1, ch_types="eeg") + info.set_montage(montage, match_alias=True) + + # work with match_case + mock_info_ch_names = ["cb1", "cb2"] + info = create_info(ch_names=mock_info_ch_names, sfreq=1, ch_types="eeg") + info.set_montage(montage, match_case=False, match_alias=True) + + # should warn user T1 instead of its alias T9 + mock_info_ch_names = ["Cb1", "T1"] + info = create_info(ch_names=mock_info_ch_names, sfreq=1, ch_types="eeg") + with pytest.raises(ValueError, match="T1"): + info.set_montage(montage, match_case=False, match_alias=True) + + +def test_heterogeneous_ch_type(): + """Test ch_names matching criteria with heterogeneous ch_type.""" + VALID_MONTAGE_NAMED_CHS = ("eeg", "ecog", "seeg", "dbs") + + montage = _make_toy_dig_montage( + n_channels=len(VALID_MONTAGE_NAMED_CHS), + coord_frame="head", + ) + + # Montage and info match + info = create_info(montage.ch_names, 1.0, list(VALID_MONTAGE_NAMED_CHS)) + RawArray(np.zeros((4, 1)), info, copy=None).set_montage(montage) + + +def test_set_montage_coord_frame_in_head_vs_unknown(): + """Test set montage using head and unknown only.""" + N_CHANNELS, NaN = 3, np.nan + + raw = _make_toy_raw(N_CHANNELS) + montage_in_head = _make_toy_dig_montage(N_CHANNELS, coord_frame="head") + montage_in_unknown = _make_toy_dig_montage(N_CHANNELS, coord_frame="unknown") + montage_in_unknown_with_fid = _make_toy_dig_montage( + N_CHANNELS, + coord_frame="unknown", + nasion=[0, 1, 0], + lpa=[1, 0, 0], + rpa=[-1, 0, 0], + ) + + assert_allclose( + actual=np.array([ch["loc"] for ch in raw.info["chs"]]), + desired=np.full((N_CHANNELS, 12), np.nan), + ) + + raw.set_montage(montage_in_head) + assert_allclose( + actual=np.array([ch["loc"] for ch in raw.info["chs"]]), + desired=[ + [0.0, 1.0, 2.0, 0.0, 0.0, 0.0, NaN, NaN, NaN, NaN, NaN, NaN], + [3.0, 4.0, 5.0, 0.0, 0.0, 0.0, NaN, NaN, NaN, NaN, NaN, NaN], + [6.0, 7.0, 8.0, 0.0, 0.0, 0.0, NaN, NaN, NaN, NaN, NaN, NaN], + ], + ) + + with pytest.warns(RuntimeWarning, match="assuming identity"): + raw.set_montage(montage_in_unknown) + + raw.set_montage(montage_in_unknown_with_fid) + assert_allclose( + actual=np.array([ch["loc"] for ch in raw.info["chs"]]), + desired=[ + [-0.0, 1.0, -2.0, 0.0, 0.0, 0.0, NaN, NaN, NaN, NaN, NaN, NaN], + [-3.0, 4.0, -5.0, 0.0, 0.0, 0.0, NaN, NaN, NaN, NaN, NaN, NaN], + [-6.0, 7.0, -8.0, 0.0, 0.0, 0.0, NaN, NaN, NaN, NaN, NaN, NaN], + ], + ) + + # check no collateral effects from transforming montage + assert _check_get_coord_frame(montage_in_unknown_with_fid.dig) == "unknown" + assert_array_equal( + _get_dig_montage_pos(montage_in_unknown_with_fid), + [[0, 1, 2], [3, 4, 5], [6, 7, 8]], + ) + + +@testing.requires_testing_data +@pytest.mark.parametrize("ch_type", ("eeg", "ecog", "seeg", "dbs")) +def test_montage_head_frame(ch_type): + """Test that head frame is set properly.""" + # gh-9446 + data = np.random.randn(2, 100) + info = create_info(["a", "b"], 512, ch_type) + for ch in info["chs"]: + assert ch["coord_frame"] == FIFF.FIFFV_COORD_HEAD + raw = RawArray(data, info) + ch_pos = dict( + a=[-0.00250136, 0.04913788, 0.05047056], b=[-0.00528394, 0.05066484, 0.05061559] + ) + lpa, nasion, rpa = get_mni_fiducials("fsaverage", subjects_dir=subjects_dir) + lpa, nasion, rpa = lpa["r"], nasion["r"], rpa["r"] + montage = make_dig_montage( + ch_pos, coord_frame="mri", nasion=nasion, lpa=lpa, rpa=rpa + ) + mri_head_t = compute_native_head_t(montage) + raw.set_montage(montage) + pos = apply_trans(mri_head_t, np.array(list(ch_pos.values()))) + for p, ch in zip(pos, raw.info["chs"]): + assert ch["coord_frame"] == FIFF.FIFFV_COORD_HEAD + assert_allclose(p, ch["loc"][:3]) + + # Also test that including channels in the montage that will not have their + # positions set will emit a warning + with pytest.warns(RuntimeWarning, match="changed from V to NA"): + raw.set_channel_types(dict(a="misc")) + with pytest.warns(RuntimeWarning, match="Not setting .*of 1 misc channel"): + raw.set_montage(montage) + + # and with a bunch of bad types + raw = read_raw_fif(fif_fname) + ch_pos = {ch_name: np.zeros(3) for ch_name in raw.ch_names} + mon = make_dig_montage(ch_pos, coord_frame="head") + with pytest.warns(RuntimeWarning, match="316 eog/grad/mag/stim channels"): + raw.set_montage(mon) + + +def test_set_montage_with_missing_coordinates(): + """Test set montage with missing coordinates.""" + N_CHANNELS, NaN = 3, np.nan + + raw = _make_toy_raw(N_CHANNELS) + raw.set_channel_types({ch: "ecog" for ch in raw.ch_names}) + # don't include all the channels + ch_names = raw.ch_names[1:] + n_channels = len(ch_names) + ch_coords = np.arange(n_channels * 3).reshape(n_channels, 3) + montage_in_mri = make_dig_montage( + ch_pos=dict( + zip( + ch_names, + ch_coords, + ) + ), + coord_frame="unknown", + nasion=[0, 1, 0], + lpa=[1, 0, 0], + rpa=[-1, 0, 0], + ) + + with pytest.raises(ValueError, match="DigMontage is only a subset of info"): + raw.set_montage(montage_in_mri) + + with pytest.raises(ValueError, match="Invalid value"): + raw.set_montage(montage_in_mri, on_missing="foo") + + with pytest.raises(TypeError, match="must be an instance"): + raw.set_montage(montage_in_mri, on_missing=True) + + with pytest.warns(RuntimeWarning, match="DigMontage is only a subset of info"): + raw.set_montage(montage_in_mri, on_missing="warn") + + raw.set_montage(montage_in_mri, on_missing="ignore") + assert_allclose( + actual=np.array([ch["loc"] for ch in raw.info["chs"]]), + desired=[ + [NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN, NaN], + [0.0, 1.0, -2.0, 0.0, 0.0, 0.0, NaN, NaN, NaN, NaN, NaN, NaN], + [-3.0, 4.0, -5.0, 0.0, 0.0, 0.0, NaN, NaN, NaN, NaN, NaN, NaN], + ], + ) + + +@testing.requires_testing_data +def test_get_montage(): + """Test get montage from Instance. + + Test with standard montage and then loaded in montage. + """ + # 1. read in testing data and assert montage roundtrip + # for testing dataset: 'test_raw.fif' + raw = read_raw_fif(fif_fname) + raw = raw.rename_channels(lambda name: name.replace("EEG ", "EEG")) + raw2 = raw.copy() + # get montage and then set montage and + # it should be the same + montage = raw.get_montage() + raw.set_montage(montage, on_missing="raise") + test_montage = raw.get_montage() + assert_object_equal(raw.info["chs"], raw2.info["chs"]) + assert_dig_allclose(raw2.info, raw.info) + assert_object_equal(raw2.info["dig"], raw.info["dig"]) + + # the montage does not change + assert_object_equal(montage.dig, test_montage.dig) + + # the montage should fulfill a roundtrip with make_dig_montage + test2_montage = make_dig_montage(**montage.get_positions()) + assert_object_equal(test2_montage.dig, test_montage.dig) + + # 2. now do a standard montage + montage = make_standard_montage("mgh60") + # set the montage; note renaming to make standard montage map + raw.set_montage(montage) + + # get montage back and set it + # the channel locations should be the same + raw2 = raw.copy() + test_montage = raw.get_montage() + raw.set_montage(test_montage, on_missing="ignore") + + # the montage should fulfill a roundtrip with make_dig_montage + test2_montage = make_dig_montage(**test_montage.get_positions()) + assert_object_equal(test2_montage.dig, test_montage.dig) + + # chs should not change + assert_object_equal(raw2.info["chs"], raw.info["chs"]) + # dig order might be different after set_montage + assert montage.ch_names == test_montage.ch_names + # note that test_montage will have different coordinate frame + # compared to standard montage + assert_dig_allclose(raw2.info, raw.info) + assert_object_equal(raw2.info["dig"], raw.info["dig"]) + + # 3. if montage gets set to None + raw.set_montage(None) + assert raw.get_montage() is None + + # 4. read in BV test dataset and make sure montage + # fulfills roundtrip on non-standard montage + dig_montage = read_dig_fif(fif_dig_montage_fname, verbose="error") + + # Make a BrainVision file like the one the user would have had + # with testing dataset 'test.vhdr' + raw_bv = read_raw_brainvision(bv_fname, preload=True) + raw_bv_2 = raw_bv.copy() + + # rename channels to make it have the full set + # of channels + mapping = dict() + for ii, ch_name in enumerate(raw_bv.ch_names, 1): + mapping[ch_name] = f"EEG{ii:03d}" + raw_bv.rename_channels(mapping) + for ii, ch_name in enumerate(raw_bv_2.ch_names, 33): + mapping[ch_name] = f"EEG{ii:03d}" + raw_bv_2.rename_channels(mapping) + raw_bv.add_channels([raw_bv_2]) + for ch in raw_bv.info["chs"]: + ch["kind"] = FIFF.FIFFV_EEG_CH + + # Set the montage and roundtrip + raw_bv.set_montage(dig_montage) + raw_bv2 = raw_bv.copy() + + # reset the montage + test_montage = raw_bv.get_montage() + raw_bv.set_montage(test_montage, on_missing="ignore") + # dig order might be different after set_montage + assert_object_equal(raw_bv2.info["dig"], raw_bv.info["dig"]) + assert_dig_allclose(raw_bv2.info, raw_bv.info) + + # if dig is not set in the info, then montage returns None + with raw.info._unlock(): + raw.info["dig"] = None + assert raw.get_montage() is None + + # the montage should fulfill a roundtrip with make_dig_montage + test2_montage = make_dig_montage(**test_montage.get_positions()) + assert_object_equal(test2_montage.dig, test_montage.dig) + + +def test_read_dig_hpts(): + """Test reading .hpts file (from MNE legacy).""" + fname = io_dir / "brainvision" / "tests" / "data" / "test.hpts" + montage = read_dig_hpts(fname) + assert repr(montage) == ( + "" + ) + + +def test_get_builtin_montages(): + """Test help function to obtain builtin montages.""" + EXPECTED_COUNT = 28 + + montages = get_builtin_montages() + assert len(montages) == EXPECTED_COUNT + + montages_with_descriptions = get_builtin_montages(descriptions=True) + assert len(montages_with_descriptions) == EXPECTED_COUNT + for montage_with_description in montages_with_descriptions: + assert len(montage_with_description) == 2 + + +@testing.requires_testing_data +def test_plot_montage(): + """Test plotting montage.""" + # gh-8025 + pytest.importorskip("defusedxml") + montage = read_dig_captrak(bvct_dig_montage_fname) + montage.plot() + + f, ax = plt.subplots(1, 1) + montage.plot(axes=ax) + + with pytest.raises(TypeError, match="must be an instance of Axes"): + montage.plot(axes=101) + with pytest.raises(TypeError, match="when 'kind' is '3d'"): + montage.plot(axes=ax, kind="3d") + with pytest.raises(TypeError, match="when 'kind' is '3d'"): + montage.plot(axes=101, kind="3d") + + +def test_montage_equality(): + """Test montage equality.""" + rng = np.random.RandomState(0) + fiducials = dict(zip(("nasion", "lpa", "rpa"), rng.rand(3, 3))) + + # hsp positions are [1X, 1X, 1X] + hsp1 = make_dig_montage(**fiducials, hsp=np.full((2, 3), 11.0)) + hsp2 = make_dig_montage(**fiducials, hsp=np.full((2, 3), 12.0)) + hsp2_identical = make_dig_montage(**fiducials, hsp=np.full((2, 3), 12.0)) + + assert hsp1 != hsp2 + assert hsp2 == hsp2_identical + + +@testing.requires_testing_data +def test_montage_add_fiducials(): + """Test montage can add estimated fiducials for rpa, lpa, nas.""" + # get the fiducials from test file + subjects_dir = data_path / "subjects" + subject = "sample" + fid_fname = subjects_dir / subject / "bem" / "sample-fiducials.fif" + test_fids, _ = read_fiducials(fid_fname) + test_fids = np.array([f["r"] for f in test_fids]) + + # create test montage and add estimated fiducials + test_ch_pos = {"A1": [0, 0, 0]} + montage = make_dig_montage(ch_pos=test_ch_pos, coord_frame="mri") + montage.add_estimated_fiducials(subject=subject, subjects_dir=subjects_dir) + + # check that adding MNI fiducials fails because we're in MRI + with pytest.raises( + RuntimeError, match='Montage should be in the "mni_tal" coordinate frame' + ): + montage.add_mni_fiducials(subjects_dir=subjects_dir) + + # check that these fiducials are close to the estimated fiducials + ch_pos = montage.get_positions() + fids_est = [ch_pos["lpa"], ch_pos["nasion"], ch_pos["rpa"]] + + dists = np.linalg.norm(test_fids - fids_est, axis=-1) * 1000.0 # -> mm + assert (dists < 8).all(), dists + + # an error should be raised if the montage is not in `mri` coord_frame + # which is the FreeSurfer RAS + montage = make_dig_montage(ch_pos=test_ch_pos, coord_frame="mni_tal") + with pytest.raises( + RuntimeError, match='Montage should be in the "mri" coordinate frame' + ): + montage.add_estimated_fiducials(subject=subject, subjects_dir=subjects_dir) + + # test that adding MNI fiducials works + montage.add_mni_fiducials(subjects_dir=subjects_dir) + test_fids = get_mni_fiducials("fsaverage", subjects_dir=subjects_dir) + for fid, test_fid in zip(montage.dig[:3], test_fids): + assert_array_equal(fid["r"], test_fid["r"]) + + # test remove fiducials + montage.remove_fiducials() + assert all([d["kind"] != FIFF.FIFFV_POINT_CARDINAL for d in montage.dig]) + + +def test_read_dig_localite(tmp_path): + """Test reading Localite .csv file.""" + contents = """#,id,x,y,z + 1,Nasion,-2.016253511,6.243001715,34.63167712 + 2,LPA,71.96698724,-29.88835576,113.6703679 + 3,RPA,-82.77279316,-22.45928121,116.4005828 + 4,ch01,53.62814378,-91.37837488,29.69071863 + 5,ch02,54.02504821,-59.96228146,23.21714217 + 6,ch03,47.93261613,-29.99373786,24.56468867 + 7,ch04,29.04824633,-86.60006321,13.5073523 + 8,ch05,25.76285783,-58.1658606,3.854848377 + 9,ch06,25.39636794,-27.28186717,9.78490351 + 10,ch07,-5.181242819,-85.52115113,7.201882904 + 11,ch08,-4.995704801,-60.47053977,0.998486757 + 12,ch09,-2.680020493,-31.14357171,6.114621138 + 13,ch10,-33.65019131,-92.34198454,13.2326512 + 14,ch11,-36.22420417,-61.23822776,6.028649571 + 15,ch12,-33.21551039,-31.21772978,8.458854072 + 16,ch13,-61.38400606,-92.67546012,29.5783456 + 17,ch14,-61.16539571,-61.86866187,26.23986153 + 18,ch15,-55.82855386,-34.77319103,25.8083942""" + + fname = tmp_path / "localite.csv" + with open(fname, "w") as f: + for row in contents.split("\n"): + f.write(f"{row.lstrip()}\n") + montage = read_dig_localite(fname, nasion="Nasion", lpa="LPA", rpa="RPA") + s = "" + assert repr(montage) == s + assert montage.ch_names == [f"ch{i:02}" for i in range(1, 16)] + + +def test_make_wrong_dig_montage(): + """Test that a montage with non numeric is not possible.""" + make_dig_montage(ch_pos={"A1": ["0", "0", "0"]}) # converted to floats + with pytest.raises(ValueError, match="could not convert string to float"): + make_dig_montage(ch_pos={"A1": ["a", "b", "c"]}) + with pytest.raises(TypeError, match="instance of ndarray, list, or tuple"): + make_dig_montage(ch_pos={"A1": 5}) + + +@testing.requires_testing_data +def test_fnirs_montage(): + """Ensure fNIRS montages can be get and set.""" + raw = read_raw_nirx(fnirs_dname) + info_orig = raw.copy().info + mtg = raw.get_montage() + + num_sources = np.sum(["S" in optode for optode in mtg.ch_names]) + num_detectors = np.sum(["D" in optode for optode in mtg.ch_names]) + assert num_sources == 5 + assert num_detectors == 13 + + # Make a change to the montage before setting + raw.info["chs"][2]["loc"][:3] = [1.0, 2, 3] + # Set montage back to original + raw.set_montage(mtg) + + for ch in range(len(raw.ch_names)): + assert_array_equal(info_orig["chs"][ch]["loc"], raw.info["chs"][ch]["loc"]) + + # Mixed channel types not supported yet + raw.set_channel_types({ch_name: "eeg" for ch_name in raw.ch_names[-2:]}) + with pytest.raises(ValueError, match="mix of fNIRS"): + raw.get_montage() diff --git a/mne-python/source/mne/channels/tests/test_standard_montage.py b/mne-python/source/mne/channels/tests/test_standard_montage.py new file mode 100644 index 0000000000000000000000000000000000000000..6e9621aa66db3cf8c08acd41875162de1773165c --- /dev/null +++ b/mne-python/source/mne/channels/tests/test_standard_montage.py @@ -0,0 +1,306 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_almost_equal, assert_raises + +from mne import create_info +from mne._fiff._digitization import _get_dig_eeg, _get_fid_coords +from mne._fiff.constants import FIFF +from mne.channels import compute_native_head_t, make_standard_montage +from mne.channels.montage import HEAD_SIZE_DEFAULT, get_builtin_montages +from mne.io import RawArray +from mne.preprocessing.nirs import beer_lambert_law, optical_density +from mne.transforms import _angle_between_quats, _get_trans, rot_to_quat + + +@pytest.mark.parametrize("kind", get_builtin_montages()) +def test_standard_montages_have_fids(kind): + """Test standard montage are all in unknown coord (have fids).""" + montage = make_standard_montage(kind) + fids, coord_frame = _get_fid_coords(montage.dig) + for k, v in fids.items(): + assert v is not None, k + for d in montage.dig: + if kind.startswith(("artinis", "standard", "mgh")): + want = FIFF.FIFFV_COORD_MRI + else: + want = FIFF.FIFFV_COORD_UNKNOWN + assert d["coord_frame"] == want + + +def test_standard_montage_errors(): + """Test error handling for wrong keys.""" + _msg = "Invalid value for the 'kind' parameter..*but got.*not-here" + with pytest.raises(ValueError, match=_msg): + _ = make_standard_montage("not-here") + + +@pytest.mark.parametrize("head_size", (HEAD_SIZE_DEFAULT, 0.05)) +@pytest.mark.parametrize( + "kind, tol", + [ + ["EGI_256", 1e-5], + ["easycap-M1", 1e-8], + ["easycap-M10", 1e-8], + ["biosemi128", 1e-8], + ["biosemi16", 1e-8], + ["biosemi160", 1e-8], + ["biosemi256", 1e-8], + ["biosemi32", 1e-8], + ["biosemi64", 1e-8], + ["brainproducts-RNP-BA-128", 1e-8], + ], +) +def test_standard_montages_on_sphere(kind, tol, head_size): + """Test some standard montage are on sphere.""" + kwargs = dict() + if head_size != HEAD_SIZE_DEFAULT: + kwargs["head_size"] = head_size + montage = make_standard_montage(kind, **kwargs) + eeg_loc = np.array([ch["r"] for ch in _get_dig_eeg(montage.dig)]) + + assert_allclose( + actual=np.linalg.norm(eeg_loc, axis=1), + desired=np.full((eeg_loc.shape[0],), head_size), + atol=tol, + ) + + +def test_standard_superset(): + """Test some properties that should hold for superset montages.""" + # new montages, tweaked to end up at the same size as the others + m_1005 = make_standard_montage("standard_1005", 0.0970) + m_1020 = make_standard_montage("standard_1020", 0.0991) + assert len(set(m_1005.ch_names) - set(m_1020.ch_names)) > 0 + # XXX weird that this is not a proper superset... + assert set(m_1020.ch_names) - set(m_1005.ch_names) == {"O10", "O9"} + c_1005 = m_1005._get_ch_pos() + for key, value in m_1020._get_ch_pos().items(): + if key not in ("O10", "O9"): + assert_allclose(c_1005[key], value, atol=1e-4, err_msg=key) + + +def _simulate_artinis_octamon(): + """Simulate artinis OctaMon channel data from numpy data. + + This is to test data that is imported with missing or incorrect montage + info. This data can then be used to test the set_montage function. + """ + np.random.seed(42) + data = np.absolute(np.random.normal(size=(16, 100))) + ch_names = [ + "S1_D1 760", + "S1_D1 850", + "S2_D1 760", + "S2_D1 850", + "S3_D1 760", + "S3_D1 850", + "S4_D1 760", + "S4_D1 850", + "S5_D2 760", + "S5_D2 850", + "S6_D2 760", + "S6_D2 850", + "S7_D2 760", + "S7_D2 850", + "S8_D2 760", + "S8_D2 850", + ] + ch_types = ["fnirs_cw_amplitude" for _ in ch_names] + sfreq = 10.0 # Hz + info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=sfreq) + for i, ch_name in enumerate(ch_names): + info["chs"][i]["loc"][9] = int(ch_name.split(" ")[1]) + raw = RawArray(data, info) + + return raw + + +def _simulate_artinis_brite23(): + """Simulate artinis Brite23 channel data from numpy data. + + This is to test data that is imported with missing or incorrect montage + info. This data can then be used to test the set_montage function. + """ + np.random.seed(0) + data = np.random.normal(size=(46, 100)) + sd_names = [ + "S1_D1", + "S2_D1", + "S3_D1", + "S4_D1", + "S3_D2", + "S4_D2", + "S5_D2", + "S4_D3", + "S5_D3", + "S6_D3", + "S5_D4", + "S6_D4", + "S7_D4", + "S6_D5", + "S7_D5", + "S8_D5", + "S7_D6", + "S8_D6", + "S9_D6", + "S8_D7", + "S9_D7", + "S10_D7", + "S11_D7", + ] + ch_names = [] + ch_types = [] + for name in sd_names: + ch_names.append(name + " hbo") + ch_types.append("hbo") + ch_names.append(name + " hbr") + ch_types.append("hbr") + sfreq = 10.0 # Hz + info = create_info(ch_names=ch_names, ch_types=ch_types, sfreq=sfreq) + raw = RawArray(data, info) + + return raw + + +@pytest.mark.parametrize("kind", ("octamon", "brite23")) +def test_set_montage_artinis_fsaverage(kind): + """Test that artinis montages match fsaverage's head<->MRI transform.""" + # Compare OctaMon and Brite23 to fsaverage + trans_fs, _ = _get_trans("fsaverage") + montage = make_standard_montage(f"artinis-{kind}") + trans = compute_native_head_t(montage) + assert trans["to"] == trans_fs["to"] + assert trans["from"] == trans_fs["from"] + translation = 1000 * np.linalg.norm( + trans["trans"][:3, 3] - trans_fs["trans"][:3, 3] + ) + assert 0 < translation < 1 # mm + rotation = np.rad2deg( + _angle_between_quats( + rot_to_quat(trans["trans"][:3, :3]), rot_to_quat(trans_fs["trans"][:3, :3]) + ) + ) + assert 0 < rotation < 1 # degrees + + +def test_set_montage_artinis_basic(): + """Test that OctaMon and Brite23 montages are set properly.""" + # Test OctaMon montage + montage_octamon = make_standard_montage("artinis-octamon") + montage_brite23 = make_standard_montage("artinis-brite23") + raw = _simulate_artinis_octamon() + raw_od = optical_density(raw) + old_info = raw.info.copy() + old_info_od = raw_od.info.copy() + raw.set_montage(montage_octamon) + raw_od.set_montage(montage_octamon) + raw_hb = beer_lambert_law(raw_od, ppf=6) # montage needed for BLL + # Check that the montage was actually modified + assert_raises( + AssertionError, + assert_array_almost_equal, + old_info["chs"][0]["loc"][:9], + raw.info["chs"][0]["loc"][:9], + ) + assert_raises( + AssertionError, + assert_array_almost_equal, + old_info_od["chs"][0]["loc"][:9], + raw_od.info["chs"][0]["loc"][:9], + ) + + # Check a known location + assert_array_almost_equal( + raw.info["chs"][0]["loc"][:3], [0.054243, 0.081884, 0.054544] + ) + assert_array_almost_equal( + raw.info["chs"][8]["loc"][:3], [-0.03013, 0.105097, 0.055894] + ) + assert_array_almost_equal( + raw.info["chs"][12]["loc"][:3], [-0.055681, 0.086566, 0.055858] + ) + assert_array_almost_equal( + raw_od.info["chs"][12]["loc"][:3], [-0.055681, 0.086566, 0.055858] + ) + assert_array_almost_equal( + raw_hb.info["chs"][12]["loc"][:3], [-0.055681, 0.086566, 0.055858] + ) + # Check that locations are identical for a pair of channels (all elements + # except the 10th which is the wavelength if not hbo and hbr type) + assert_array_almost_equal( + raw.info["chs"][0]["loc"][:9], raw.info["chs"][1]["loc"][:9] + ) + assert_array_almost_equal( + raw_od.info["chs"][0]["loc"][:9], raw_od.info["chs"][1]["loc"][:9] + ) + assert_array_almost_equal( + raw_hb.info["chs"][0]["loc"][:9], raw_hb.info["chs"][1]["loc"][:9] + ) + + # Test Brite23 montage + raw = _simulate_artinis_brite23() + old_info = raw.info.copy() + raw.set_montage(montage_brite23) + # Check that the montage was actually modified + assert_raises( + AssertionError, + assert_array_almost_equal, + old_info["chs"][0]["loc"][:9], + raw.info["chs"][0]["loc"][:9], + ) + # Check a known location + assert_array_almost_equal( + raw.info["chs"][0]["loc"][:3], [0.068931, 0.046201, 0.072055] + ) + assert_array_almost_equal( + raw.info["chs"][8]["loc"][:3], [0.055196, 0.082757, 0.052165] + ) + assert_array_almost_equal( + raw.info["chs"][12]["loc"][:3], [0.033592, 0.102607, 0.047423] + ) + # Check that locations are identical for a pair of channels (all elements + # except the 10th which is the wavelength if not hbo and hbr type) + assert_array_almost_equal( + raw.info["chs"][0]["loc"][:9], raw.info["chs"][1]["loc"][:9] + ) + + # Test channel variations + raw_old = _simulate_artinis_brite23() + # Raw missing some channels that are in the montage: pass + raw = raw_old.copy() + raw.pick(["S1_D1 hbo", "S1_D1 hbr"]) + raw.set_montage("artinis-brite23") + + # Unconventional channel pair: pass + raw = raw_old.copy() + info_new = create_info( + ["S11_D1 hbo", "S11_D1 hbr"], raw.info["sfreq"], ["hbo", "hbr"] + ) + new = RawArray(np.random.normal(size=(2, len(raw))), info_new) + raw.add_channels([new], force_update_info=True) + raw.set_montage("artinis-brite23") + + # Source not in montage: fail + raw = raw_old.copy() + info_new = create_info( + ["S12_D7 hbo", "S12_D7 hbr"], raw.info["sfreq"], ["hbo", "hbr"] + ) + new = RawArray(np.random.normal(size=(2, len(raw))), info_new) + raw.add_channels([new], force_update_info=True) + with pytest.raises(ValueError, match="not in list"): + raw.set_montage("artinis-brite23") + + # Detector not in montage: fail + raw = raw_old.copy() + info_new = create_info( + ["S11_D8 hbo", "S11_D8 hbr"], raw.info["sfreq"], ["hbo", "hbr"] + ) + new = RawArray(np.random.normal(size=(2, len(raw))), info_new) + raw.add_channels([new], force_update_info=True) + with pytest.raises(ValueError, match="not in list"): + raw.set_montage("artinis-brite23") diff --git a/mne-python/source/mne/channels/tests/test_unify_bads.py b/mne-python/source/mne/channels/tests/test_unify_bads.py new file mode 100644 index 0000000000000000000000000000000000000000..5575b5dce5b0333027251cab05c9e5192a33049e --- /dev/null +++ b/mne-python/source/mne/channels/tests/test_unify_bads.py @@ -0,0 +1,58 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import pytest + +from mne.channels import unify_bad_channels + + +def test_error_raising(raw, epochs): + """Tests input checking.""" + with pytest.raises(TypeError, match=r"must be an instance of list"): + unify_bad_channels("bad input") + with pytest.raises(ValueError, match=r"insts must not be empty"): + unify_bad_channels([]) + with pytest.raises(TypeError, match=r"each object in insts must be an instance of"): + unify_bad_channels(["bad_instance"]) + with pytest.raises(ValueError, match=r"same type"): + unify_bad_channels([raw, epochs]) + with pytest.raises(ValueError, match=r"Channels do not match across"): + raw_alt1 = raw.copy() + raw_alt1.drop_channels(raw.info["ch_names"][-1]) + unify_bad_channels([raw, raw_alt1]) # ch diff preserving order + with pytest.raises(ValueError, match=r"sorted differently"): + raw_alt2 = raw.copy() + new_order = [raw.ch_names[-1]] + raw.ch_names[:-1] + raw_alt2.reorder_channels(new_order) + unify_bad_channels([raw, raw_alt2]) + + +def test_bads_compilation(raw): + """Tests that bads are compiled properly. + + Tests two cases: a) single instance passed to function with an existing + bad, and b) multiple instances passed to function with varying compilation + scenarios including empty bads, unique bads, and partially duplicated bads + listed out-of-order. + + Only the Raw instance type is tested, since bad channel implementation is + controlled across instance types with a MixIn class. + """ + assert raw.info["bads"] == [] + chns = raw.ch_names[:3] + no_bad = raw.copy() + one_bad = raw.copy() + one_bad.info["bads"] = [chns[1]] + three_bad = raw.copy() + three_bad.info["bads"] = chns + # scenario 1: single instance passed with actual bads + s_out = unify_bad_channels([one_bad]) + assert len(s_out) == 1, len(s_out) + assert s_out[0].info["bads"] == [chns[1]], (s_out[0].info["bads"], chns[1]) + # scenario 2: multiple instances passed + m_out = unify_bad_channels([one_bad, no_bad, three_bad]) + assert len(m_out) == 3, len(m_out) + expected_order = [chns[1], chns[0], chns[2]] + for inst in m_out: + assert inst.info["bads"] == expected_order diff --git a/mne-python/source/mne/chpi.py b/mne-python/source/mne/chpi.py new file mode 100644 index 0000000000000000000000000000000000000000..7ea3d1b407d5c72e7b7b7ee9ed5331d6c76a70ae --- /dev/null +++ b/mne-python/source/mne/chpi.py @@ -0,0 +1,1973 @@ +"""Functions for fitting head positions with (c)HPI coils. + +``compute_head_pos`` can be used to: + +1. Drop coils whose GOF are below ``gof_limit``. If fewer than 3 coils + remain, abandon fitting for the chunk. +2. Fit dev_head_t quaternion (using ``_fit_chpi_quat_subset``), + iteratively dropping coils (as long as 3 remain) to find the best GOF + (using ``_fit_chpi_quat``). +3. If fewer than 3 coils meet the ``dist_limit`` criteria following + projection of the fitted device coil locations into the head frame, + abandon fitting for the chunk. + +The function ``filter_chpi`` uses the same linear model to filter cHPI +and (optionally) line frequencies from the data. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import copy +import itertools +from functools import partial + +import numpy as np +from scipy.linalg import orth +from scipy.optimize import fmin_cobyla +from scipy.spatial.distance import cdist + +from ._fiff.constants import FIFF +from ._fiff.meas_info import Info, _simplify_info +from ._fiff.pick import ( + _picks_to_idx, + pick_channels, + pick_channels_regexp, + pick_info, + pick_types, +) +from ._fiff.proj import Projection, setup_proj +from .bem import ConductorModel +from .channels.channels import _get_meg_system +from .cov import compute_whitener, make_ad_hoc_cov +from .dipole import _make_guesses +from .event import find_events +from .fixes import _reshape_view, jit +from .forward import _concatenate_coils, _create_meg_coils, _magnetic_dipole_field_vec +from .io import BaseRaw, RawArray +from .io.ctf.trans import _make_ctf_coord_trans_set +from .io.kit.constants import KIT +from .io.kit.kit import RawKIT as _RawKIT +from .preprocessing.maxwell import ( + _get_mf_picks_fix_mags, + _prep_mf_coils, + _regularize_out, + _sss_basis, +) +from .transforms import ( + Transform, + _angle_between_quats, + _fit_matched_points, + _quat_to_affine, + als_ras_trans, + angle_distance_between_rigid, + apply_trans, + invert_transform, + quat_to_rot, + rot_to_quat, +) +from .utils import ( + ProgressBar, + _check_fname, + _check_option, + _on_missing, + _pl, + _validate_type, + _verbose_safe_false, + logger, + use_log_level, + verbose, + warn, +) + +# Eventually we should add: +# hpicons +# high-passing of data during fits +# parsing cHPI coil information from acq pars, then to PSD if necessary + + +# ############################################################################ +# Reading from text or FIF file + + +def read_head_pos(fname): + """Read MaxFilter-formatted head position parameters. + + Parameters + ---------- + fname : path-like + The filename to read. This can be produced by e.g., + ``maxfilter -headpos .pos``. + + Returns + ------- + quats : array, shape (n_pos, 10) + The position and quaternion parameters from cHPI fitting. + See :func:`mne.chpi.compute_head_pos` for details on the columns. + + See Also + -------- + write_head_pos + head_pos_to_trans_rot_t + + Notes + ----- + .. versionadded:: 0.12 + """ + _check_fname(fname, must_exist=True, overwrite="read") + data = np.loadtxt(fname, skiprows=1) # first line is header, skip it + data = _reshape_view(data, (-1, 10)) # ensure it's the right size even if empty + if np.isnan(data).any(): # make sure we didn't do something dumb + raise RuntimeError(f"positions could not be read properly from {fname}") + return data + + +def write_head_pos(fname, pos): + """Write MaxFilter-formatted head position parameters. + + Parameters + ---------- + fname : path-like + The filename to write. + pos : array, shape (n_pos, 10) + The position and quaternion parameters from cHPI fitting. + See :func:`mne.chpi.compute_head_pos` for details on the columns. + + See Also + -------- + read_head_pos + head_pos_to_trans_rot_t + + Notes + ----- + .. versionadded:: 0.12 + """ + _check_fname(fname, overwrite=True) + pos = np.array(pos, np.float64) + if pos.ndim != 2 or pos.shape[1] != 10: + raise ValueError( + f"pos must be a 2D array of shape (N, 10), got shape {pos.shape}" + ) + with open(fname, "wb") as fid: + fid.write( + " Time q1 q2 q3 q4 q5 " + "q6 g-value error velocity\n".encode("ASCII") + ) + for p in pos: + fmts = ["% 9.3f"] + ["% 8.5f"] * 9 + fid.write(((" " + " ".join(fmts) + "\n") % tuple(p)).encode("ASCII")) + + +def head_pos_to_trans_rot_t(quats): + """Convert Maxfilter-formatted head position quaternions. + + Parameters + ---------- + quats : ndarray, shape (n_pos, 10) + MaxFilter-formatted position and quaternion parameters. + See :func:`mne.chpi.read_head_pos` for details on the columns. + + Returns + ------- + translation : ndarray, shape (n_pos, 3) + Translations at each time point. + rotation : ndarray, shape (n_pos, 3, 3) + Rotations at each time point. + t : ndarray, shape (n_pos,) + The time points. + + See Also + -------- + read_head_pos + write_head_pos + """ + t = quats[..., 0].copy() + rotation = quat_to_rot(quats[..., 1:4]) + translation = quats[..., 4:7].copy() + return translation, rotation, t + + +@verbose +def extract_chpi_locs_ctf(raw, verbose=None): + r"""Extract cHPI locations from CTF data. + + Parameters + ---------- + raw : instance of Raw + Raw data with CTF cHPI information. + %(verbose)s + + Returns + ------- + %(chpi_locs)s + + Notes + ----- + CTF continuous head monitoring stores the x,y,z location (m) of each chpi + coil as separate channels in the dataset: + + - ``HLC001[123]\\*`` - nasion + - ``HLC002[123]\\*`` - lpa + - ``HLC003[123]\\*`` - rpa + + This extracts these positions for use with + :func:`~mne.chpi.compute_head_pos`. + + .. versionadded:: 0.20 + """ + # Pick channels corresponding to the cHPI positions + hpi_picks = pick_channels_regexp(raw.info["ch_names"], "HLC00[123][123].*") + + # make sure we get 9 channels + if len(hpi_picks) != 9: + raise RuntimeError("Could not find all 9 cHPI channels") + + # get indices in alphabetical order + sorted_picks = np.array(sorted(hpi_picks, key=lambda k: raw.info["ch_names"][k])) + + # make picks to match order of dig cardinial ident codes. + # LPA (HPIC002[123]-*), NAS(HPIC001[123]-*), RPA(HPIC003[123]-*) + hpi_picks = sorted_picks[[3, 4, 5, 0, 1, 2, 6, 7, 8]] + del sorted_picks + + # process the entire run + time_sl = slice(0, len(raw.times)) + chpi_data = raw[hpi_picks, time_sl][0] + + # transforms + tmp_trans = _make_ctf_coord_trans_set(None, None) + ctf_dev_dev_t = tmp_trans["t_ctf_dev_dev"] + del tmp_trans + + # find indices where chpi locations change + indices = [0] + indices.extend(np.where(np.any(np.diff(chpi_data, axis=1), axis=0))[0] + 1) + # data in channels are in ctf device coordinates (cm) + rrs = chpi_data[:, indices].T.reshape(len(indices), 3, 3) # m + # map to mne device coords + rrs = apply_trans(ctf_dev_dev_t, rrs) + gofs = np.ones(rrs.shape[:2]) # not encoded, set all good + moments = np.zeros(rrs.shape) # not encoded, set all zero + times = raw.times[indices] + raw._first_time + return dict(rrs=rrs, gofs=gofs, times=times, moments=moments) + + +@verbose +def extract_chpi_locs_kit(raw, stim_channel="MISC 064", *, verbose=None): + """Extract cHPI locations from KIT data. + + Parameters + ---------- + raw : instance of RawKIT + Raw data with KIT cHPI information. + stim_channel : str + The stimulus channel that encodes HPI measurement intervals. + %(verbose)s + + Returns + ------- + %(chpi_locs)s + + Notes + ----- + .. versionadded:: 0.23 + """ + _validate_type(raw, (_RawKIT,), "raw") + stim_chs = [ + raw.info["ch_names"][pick] + for pick in pick_types(raw.info, stim=True, misc=True, ref_meg=False) + ] + _validate_type(stim_channel, str, "stim_channel") + _check_option("stim_channel", stim_channel, stim_chs) + idx = raw.ch_names.index(stim_channel) + safe_false = _verbose_safe_false() + events_on = find_events( + raw, stim_channel=raw.ch_names[idx], output="onset", verbose=safe_false + )[:, 0] + events_off = find_events( + raw, stim_channel=raw.ch_names[idx], output="offset", verbose=safe_false + )[:, 0] + bad = False + if len(events_on) == 0 or len(events_off) == 0: + bad = True + else: + if events_on[-1] > events_off[-1]: + events_on = events_on[:-1] + if events_on.size != events_off.size or not (events_on < events_off).all(): + bad = True + if bad: + raise RuntimeError( + f"Could not find appropriate cHPI intervals from {stim_channel}" + ) + # use the midpoint for times + times = (events_on + events_off) / (2 * raw.info["sfreq"]) + del events_on, events_off + # XXX remove first two rows. It is unknown currently if there is a way to + # determine from the con file the number of initial pulses that + # indicate the start of reading. The number is shown by opening the con + # file in MEG160, but I couldn't find the value in the .con file, so it + # may just always be 2... + times = times[2:] + n_coils = 5 # KIT always has 5 (hard-coded in reader) + header = raw._raw_extras[0]["dirs"][KIT.DIR_INDEX_CHPI_DATA] + dtype = np.dtype([("good", " 0 else None + # grab codes indicating a coil is active + hpi_on = [coil["event_bits"][0] for coil in hpi_sub["hpi_coils"]] + # not all HPI coils will actually be used + hpi_on = np.array([hpi_on[hc["number"] - 1] for hc in hpi_coils]) + # mask for coils that may be active + hpi_mask = np.array([event_bit != 0 for event_bit in hpi_on]) + hpi_on = hpi_on[hpi_mask] + hpi_freqs = hpi_freqs[hpi_mask] + else: + hpi_on = np.zeros(len(hpi_freqs)) + + return hpi_freqs, hpi_pick, hpi_on + + +@verbose +def _get_hpi_initial_fit(info, adjust=False, verbose=None): + """Get HPI fit locations from raw.""" + if info["hpi_results"] is None or len(info["hpi_results"]) == 0: + raise RuntimeError("no initial cHPI head localization performed") + + hpi_result = info["hpi_results"][-1] + hpi_dig = _sorted_hpi_dig(info["dig"]) + CTF_KINDS = (FIFF.FIFFV_POINT_HPI, FIFF.FIFFV_POINT_CARDINAL) + if len(hpi_dig) == 0: + msg = "HPIFIT: No HPI dig points, using hpifit result" + # For CTF data, these can get stored as cardinal points + hpi_dig = _sorted_hpi_dig(hpi_result["dig_points"], kinds=CTF_KINDS) + if all( + d["coord_frame"] in (FIFF.FIFFV_COORD_DEVICE, FIFF.FIFFV_COORD_UNKNOWN) + for d in hpi_dig + ): + # Do not modify in place! + hpi_dig = copy.deepcopy(hpi_dig) + msg += " transformed to head coords" + for dig in hpi_dig: + dig.update( + r=apply_trans(info["dev_head_t"], dig["r"]), + coord_frame=FIFF.FIFFV_COORD_HEAD, + ) + logger.debug(msg) + + # zero-based indexing, dig->info + # CTF does not populate some entries so we use .get here + pos_order = hpi_result.get("order", np.arange(1, len(hpi_dig) + 1)) - 1 + used = hpi_result.get("used", np.arange(len(hpi_dig))) + dist_limit = hpi_result.get("dist_limit", 0.005) + good_limit = hpi_result.get("good_limit", 0.98) + goodness = hpi_result.get("goodness", np.ones(len(hpi_dig))) + + # this shouldn't happen, eventually we could add the transforms + # necessary to put it in head coords + if not all(d["coord_frame"] == FIFF.FIFFV_COORD_HEAD for d in hpi_dig): + raise RuntimeError("cHPI coordinate frame incorrect") + # Give the user some info + logger.info( + f"HPIFIT: {len(pos_order)} coils digitized in order " + f"{' '.join(str(o + 1) for o in pos_order)}" + ) + logger.debug( + f"HPIFIT: {len(used)} coils accepted: {' '.join(str(h) for h in used)}" + ) + hpi_rrs = np.array([d["r"] for d in hpi_dig])[pos_order] + assert len(hpi_rrs) >= 3, len(hpi_rrs) + + # Fitting errors + hpi_rrs_fit = _sorted_hpi_dig( + info["hpi_results"][-1]["dig_points"], + kinds=CTF_KINDS, + ) + hpi_rrs_fit = np.array([d["r"] for d in hpi_rrs_fit]) + # hpi_result['dig_points'] are in FIFFV_COORD_UNKNOWN coords, but this + # is probably a misnomer because it should be FIFFV_COORD_DEVICE for this + # to work + assert hpi_result["coord_trans"]["to"] == FIFF.FIFFV_COORD_HEAD + hpi_rrs_fit = apply_trans(hpi_result["coord_trans"]["trans"], hpi_rrs_fit) + if "moments" in hpi_result: + logger.debug(f"HPI coil moments {hpi_result['moments'].shape[::-1]}:") + for moment in hpi_result["moments"]: + logger.debug(f"{moment[0]:g} {moment[1]:g} {moment[2]:g}") + errors = np.linalg.norm(hpi_rrs - hpi_rrs_fit, axis=1) + logger.debug(f"HPIFIT errors: {', '.join(f'{1000 * e:0.1f}' for e in errors)} mm.") + if errors.sum() < len(errors) * dist_limit: + logger.info("HPI consistency of isotrak and hpifit is OK.") + elif not adjust and (len(used) == len(hpi_dig)): + warn("HPI consistency of isotrak and hpifit is poor.") + else: + # adjust HPI coil locations using the hpifit transformation + for hi, (err, r_fit) in enumerate(zip(errors, hpi_rrs_fit)): + # transform to head frame + d = 1000 * err + if not adjust: + if err >= dist_limit: + warn( + f"Discrepancy of HPI coil {hi + 1} isotrak and hpifit is " + f"{d:.1f} mm!" + ) + elif hi + 1 not in used: + if goodness[hi] >= good_limit: + logger.info( + f"Note: HPI coil {hi + 1} isotrak is adjusted by {d:.1f} mm!" + ) + hpi_rrs[hi] = r_fit + else: + warn( + f"Discrepancy of HPI coil {hi + 1} isotrak and hpifit of " + f"{d:.1f} mm was not adjusted!" + ) + logger.debug( + f"HP fitting limits: err = {1000 * dist_limit:.1f} mm, gval = {good_limit:.3f}." + ) + + return hpi_rrs.astype(float) + + +def _magnetic_dipole_objective( + x, B, B2, coils, whitener, too_close, return_moment=False +): + """Project data onto right eigenvectors of whitened forward.""" + fwd = _magnetic_dipole_field_vec(x[np.newaxis], coils, too_close) + out, u, s, one = _magnetic_dipole_delta(fwd, whitener, B, B2) + if return_moment: + one /= s + Q = np.dot(one, u.T) + out = (out, Q) + return out + + +@jit() +def _magnetic_dipole_delta(fwd, whitener, B, B2): + # Here we use .T to get whitener to Fortran order, which speeds things up + fwd = np.dot(fwd, whitener.T) + u, s, v = np.linalg.svd(fwd, full_matrices=False) + one = np.dot(v, B) + Bm2 = np.dot(one, one) + return B2 - Bm2, u, s, one + + +def _magnetic_dipole_delta_multi(whitened_fwd_svd, B, B2): + # Here we use .T to get whitener to Fortran order, which speeds things up + one = np.matmul(whitened_fwd_svd, B) + Bm2 = np.sum(one * one, axis=1) + return B2 - Bm2 + + +def _fit_magnetic_dipole(B_orig, x0, too_close, whitener, coils, guesses): + """Fit a single bit of data (x0 = pos).""" + B = np.dot(whitener, B_orig) + B2 = np.dot(B, B) + objective = partial( + _magnetic_dipole_objective, + B=B, + B2=B2, + coils=coils, + whitener=whitener, + too_close=too_close, + ) + if guesses is not None: + res0 = objective(x0) + res = _magnetic_dipole_delta_multi(guesses["whitened_fwd_svd"], B, B2) + assert res.shape == (guesses["rr"].shape[0],) + idx = np.argmin(res) + if res[idx] < res0: + x0 = guesses["rr"][idx] + x = fmin_cobyla(objective, x0, (), rhobeg=1e-3, rhoend=1e-5, disp=False) + gof, moment = objective(x, return_moment=True) + gof = 1.0 - gof / B2 + return x, gof, moment + + +@jit() +def _chpi_objective(x, coil_dev_rrs, coil_head_rrs): + """Compute objective function.""" + d = np.dot(coil_dev_rrs, quat_to_rot(x[:3]).T) + d += x[3:] + d -= coil_head_rrs + d *= d + return d.sum() + + +def _fit_chpi_quat(coil_dev_rrs, coil_head_rrs, *, quat=None): + """Fit rotation and translation (quaternion) parameters for cHPI coils.""" + denom = np.linalg.norm(coil_head_rrs - np.mean(coil_head_rrs, axis=0)) + denom *= denom + # We could try to solve it the analytic way: + # TODO someday we could choose to weight these points by their goodness + # of fit somehow, see also https://github.com/mne-tools/mne-python/issues/11330 + if quat is None: + quat = _fit_matched_points(coil_dev_rrs, coil_head_rrs)[0] + gof = 1.0 - _chpi_objective(quat, coil_dev_rrs, coil_head_rrs) / denom + return quat, gof + + +def _fit_coil_order_dev_head_trans( + dev_pnts, head_pnts, *, bias=True, gofs=None, gof_limit=0.98, prefix="" +): + """Compute Device to Head transform allowing for permutiatons of points.""" + n_coils = len(dev_pnts) + id_quat = np.zeros(6) + best_order = np.full(n_coils, -1, dtype=int) + best_g = -999 + best_quat = id_quat + assert dev_pnts.shape == head_pnts.shape == (n_coils, 3) + gofs = np.ones(n_coils) if gofs is None else gofs + use_mask = _gof_use_mask(gofs, gof_limit=gof_limit) + n_use = int(use_mask.sum()) # explicit int cast for itertools.permutations + dev_pnts_tmp = dev_pnts[use_mask] + # First pass: figure out best order using the good dev points + for this_order in itertools.permutations(np.arange(len(head_pnts)), n_use): + head_pnts_tmp = head_pnts[np.array(this_order)] + this_quat, g = _fit_chpi_quat(dev_pnts_tmp, head_pnts_tmp) + assert np.linalg.det(quat_to_rot(this_quat[:3])) > 0.9999 + if bias: + # For symmetrical arrangements, flips can produce roughly + # equivalent g values. To avoid this, heavily penalize + # large rotations. + rotation = _angle_between_quats(this_quat[:3], np.zeros(3)) + check_g = g * max(1.0 - rotation / np.pi, 0) ** 0.25 + else: + check_g = g + if check_g > best_g: + out_g = g + best_g = check_g + best_order[use_mask] = this_order + best_quat = this_quat + del this_order + # Second pass: now fit the remaining (bad) coils using the best order and quat + # from above + missing = np.setdiff1d(np.arange(n_coils), best_order[best_order >= 0]) + best_missing_g = -np.inf + for this_order in itertools.permutations(missing): + full_order = best_order.copy() + full_order[~use_mask] = this_order + assert (full_order >= 0).all() + assert np.array_equal(np.sort(full_order), np.arange(n_coils)) + head_pnts_tmp = head_pnts[np.array(full_order)] + _, g = _fit_chpi_quat(dev_pnts, head_pnts_tmp, quat=best_quat) + if g > best_missing_g: + best_missing_g = g + best_order[:] = full_order + del this_order + assert np.array_equal(np.sort(best_order), np.arange(n_coils)) + + # Convert Quaterion to transform + dev_head_t = _quat_to_affine(best_quat) + ang, dist = angle_distance_between_rigid( + dev_head_t, angle_units="deg", distance_units="mm" + ) + extra = f" using {n_use}/{n_coils} coils" if n_use < n_coils else "" + logger.info( + f"{prefix}Fitted dev_head_t {ang:0.1f}° and {dist:0.1f} mm " + f"from device origin{extra} (GOF: {out_g:.3f})" + ) + return dev_head_t, best_order, out_g + + +@verbose +def _setup_hpi_amplitude_fitting( + info, t_window, remove_aliased=False, ext_order=1, allow_empty=False, verbose=None +): + """Generate HPI structure for HPI localization.""" + # grab basic info. + on_missing = "raise" if not allow_empty else "ignore" + hpi_freqs, hpi_pick, hpi_ons = get_chpi_info(info, on_missing=on_missing) + + # check for maxwell filtering + for ent in info["proc_history"]: + for key in ("sss_info", "max_st"): + if len(ent["max_info"]["sss_info"]) > 0: + warn( + "Fitting cHPI amplitudes after Maxwell filtering may not work, " + "consider fitting on the original data." + ) + break + + _validate_type(t_window, (str, "numeric"), "t_window") + if info["line_freq"] is not None: + line_freqs = np.arange( + info["line_freq"], info["sfreq"] / 3.0, info["line_freq"] + ) + else: + line_freqs = np.zeros([0]) + lfs = " ".join(f"{lf}" for lf in line_freqs) + logger.info(f"Line interference frequencies: {lfs} Hz") + # worry about resampled/filtered data. + # What to do e.g. if Raw has been resampled and some of our + # HPI freqs would now be aliased + highest = info.get("lowpass") + highest = info["sfreq"] / 2.0 if highest is None else highest + keepers = hpi_freqs <= highest + if remove_aliased: + hpi_freqs = hpi_freqs[keepers] + hpi_ons = hpi_ons[keepers] + elif not keepers.all(): + raise RuntimeError( + f"Found HPI frequencies {hpi_freqs[~keepers].tolist()} above the lowpass (" + f"or Nyquist) frequency {highest:0.1f}" + ) + # calculate optimal window length. + if isinstance(t_window, str): + _check_option("t_window", t_window, ("auto",), extra="if a string") + if len(hpi_freqs): + all_freqs = np.concatenate((hpi_freqs, line_freqs)) + delta_freqs = np.diff(np.unique(all_freqs)) + t_window = max(5.0 / all_freqs.min(), 1.0 / delta_freqs.min()) + else: + t_window = 0.2 + t_window = float(t_window) + if t_window <= 0: + raise ValueError(f"t_window ({t_window}) must be > 0") + logger.info(f"Using time window: {1000 * t_window:0.1f} ms") + window_nsamp = np.rint(t_window * info["sfreq"]).astype(int) + model = _setup_hpi_glm(hpi_freqs, line_freqs, info["sfreq"], window_nsamp) + inv_model = np.linalg.pinv(model) + inv_model_reord = _reorder_inv_model(inv_model, len(hpi_freqs)) + proj, proj_op, meg_picks = _setup_ext_proj(info, ext_order) + # include mag and grad picks separately, for SNR computations + mag_subpicks = _picks_to_idx(info, "mag", allow_empty=True) + mag_subpicks = np.searchsorted(meg_picks, mag_subpicks) + grad_subpicks = _picks_to_idx(info, "grad", allow_empty=True) + grad_subpicks = np.searchsorted(meg_picks, grad_subpicks) + # Set up magnetic dipole fits + hpi = dict( + meg_picks=meg_picks, + mag_subpicks=mag_subpicks, + grad_subpicks=grad_subpicks, + hpi_pick=hpi_pick, + model=model, + inv_model=inv_model, + t_window=t_window, + inv_model_reord=inv_model_reord, + on=hpi_ons, + n_window=window_nsamp, + proj=proj, + proj_op=proj_op, + freqs=hpi_freqs, + line_freqs=line_freqs, + ) + return hpi + + +def _setup_hpi_glm(hpi_freqs, line_freqs, sfreq, window_nsamp): + """Initialize a general linear model for HPI amplitude estimation.""" + slope = np.linspace(-0.5, 0.5, window_nsamp)[:, np.newaxis] + radians_per_sec = 2 * np.pi * np.arange(window_nsamp, dtype=float) / sfreq + f_t = hpi_freqs[np.newaxis, :] * radians_per_sec[:, np.newaxis] + l_t = line_freqs[np.newaxis, :] * radians_per_sec[:, np.newaxis] + model = [ + np.sin(f_t), + np.cos(f_t), # hpi freqs + np.sin(l_t), + np.cos(l_t), # line freqs + slope, + np.ones_like(slope), + ] # drift, DC + return np.hstack(model) + + +@jit() +def _reorder_inv_model(inv_model, n_freqs): + # Reorder for faster computation + idx = np.arange(2 * n_freqs).reshape(2, n_freqs).T.ravel() + return inv_model[idx] + + +def _setup_ext_proj(info, ext_order): + meg_picks = pick_types(info, meg=True, eeg=False, exclude="bads") + info = pick_info(_simplify_info(info), meg_picks) # makes a copy + _, _, _, _, mag_or_fine = _get_mf_picks_fix_mags( + info, int_order=0, ext_order=ext_order, ignore_ref=True, verbose="error" + ) + mf_coils = _prep_mf_coils(info, verbose="error") + ext = _sss_basis( + dict(origin=(0.0, 0.0, 0.0), int_order=0, ext_order=ext_order), mf_coils + ).T + out_removes = _regularize_out(0, 1, mag_or_fine, []) + ext = ext[~np.isin(np.arange(len(ext)), out_removes)] + ext = orth(ext.T).T + assert ext.shape[1] == len(meg_picks) + proj = Projection( + kind=FIFF.FIFFV_PROJ_ITEM_HOMOG_FIELD, + desc="SSS", + active=False, + data=dict( + data=ext, ncol=info["nchan"], col_names=info["ch_names"], nrow=len(ext) + ), + ) + with info._unlock(): + info["projs"] = [proj] + proj_op, _ = setup_proj( + info, add_eeg_ref=False, activate=False, verbose=_verbose_safe_false() + ) + # Can be None if ext_order = 0 + if proj_op is None: + proj_op = np.eye(len(meg_picks)) + assert proj_op.shape == (len(meg_picks),) * 2 + return proj, proj_op, meg_picks + + +def _time_prefix(fit_time): + """Format log messages.""" + return (f" t={fit_time:0.3f}:").ljust(17) + + +def _fit_chpi_amplitudes(raw, time_sl, hpi, snr=False): + """Fit amplitudes for each channel from each of the N cHPI sinusoids. + + Returns + ------- + sin_fit : ndarray, shape (n_freqs, n_channels) + The sin amplitudes matching each cHPI frequency. + Will be all nan if this time window should be skipped. + snr : ndarray, shape (n_freqs, 2) + Estimated SNR for this window, separately for mag and grad channels. + """ + # No need to detrend the data because our model has a DC term + with use_log_level(False): + # loads good channels + this_data = raw[hpi["meg_picks"], time_sl][0] + + # which HPI coils to use + if hpi["hpi_pick"] is not None: + with use_log_level(False): + # loads hpi_stim channel + chpi_data = raw[hpi["hpi_pick"], time_sl][0] + + ons = (np.round(chpi_data).astype(np.int64) & hpi["on"][:, np.newaxis]).astype( + bool + ) + n_on = ons.all(axis=-1).sum(axis=0) + if not (n_on >= 3).all(): + return None + if snr: + return _fast_fit_snr( + this_data, + len(hpi["freqs"]), + hpi["model"], + hpi["inv_model"], + hpi["mag_subpicks"], + hpi["grad_subpicks"], + ) + return _fast_fit( + this_data, + hpi["proj_op"], + len(hpi["freqs"]), + hpi["model"], + hpi["inv_model_reord"], + ) + + +@jit() +def _fast_fit(this_data, proj, n_freqs, model, inv_model_reord): + # first or last window + if this_data.shape[1] != model.shape[0]: + model = model[: this_data.shape[1]] + inv_model_reord = _reorder_inv_model(np.linalg.pinv(model), n_freqs) + proj_data = proj @ this_data + X = inv_model_reord @ proj_data.T + + sin_fit = np.zeros((n_freqs, X.shape[1])) + for fi in range(n_freqs): + # use SVD across all sensors to estimate the sinusoid phase + u, s, vt = np.linalg.svd(X[2 * fi : 2 * fi + 2], full_matrices=False) + # the first component holds the predominant phase direction + # (so ignore the second, effectively doing s[1] = 0): + sin_fit[fi] = vt[0] * s[0] + return sin_fit + + +@jit() +def _fast_fit_snr(this_data, n_freqs, model, inv_model, mag_picks, grad_picks): + # first or last window + if this_data.shape[1] != model.shape[0]: + model = model[: this_data.shape[1]] + inv_model = np.linalg.pinv(model) + coefs = np.ascontiguousarray(inv_model) @ np.ascontiguousarray(this_data.T) + # average sin & cos terms (special property of sinusoids: power=A²/2) + hpi_power = (coefs[:n_freqs] ** 2 + coefs[n_freqs : (2 * n_freqs)] ** 2) / 2 + resid = this_data - np.ascontiguousarray((model @ coefs).T) + # can't use np.var(..., axis=1) with Numba, so do it manually: + resid_mean = np.atleast_2d(resid.sum(axis=1) / resid.shape[1]).T + squared_devs = np.abs(resid - resid_mean) ** 2 + resid_var = squared_devs.sum(axis=1) / squared_devs.shape[1] + # output array will be (n_freqs, 3 * n_ch_types). The 3 columns for each + # channel type are the SNR, the mean cHPI power and the residual variance + # (which gets tiled to shape (n_freqs,) because it's a scalar). + snrs = np.empty((n_freqs, 0)) + # average power & compute residual variance separately for each ch type + for _picks in (mag_picks, grad_picks): + if len(_picks): + avg_power = hpi_power[:, _picks].sum(axis=1) / len(_picks) + avg_resid = resid_var[_picks].mean() * np.ones(n_freqs) + snr = 10 * np.log10(avg_power / avg_resid) + snrs = np.hstack((snrs, np.stack((snr, avg_power, avg_resid), 1))) + return snrs + + +def _check_chpi_param(chpi_, name): + if name == "chpi_locs": + want_ndims = dict(times=1, rrs=3, moments=3, gofs=2) + extra_keys = list() + else: + assert name == "chpi_amplitudes" + want_ndims = dict(times=1, slopes=3) + extra_keys = ["proj"] + + _validate_type(chpi_, dict, name) + want_keys = list(want_ndims.keys()) + extra_keys + if set(want_keys).symmetric_difference(chpi_): + raise ValueError( + f"{name} must be a dict with entries {want_keys}, got {sorted(chpi_)}" + ) + n_times = None + for key, want_ndim in want_ndims.items(): + key_str = f"{name}[{key}]" + val = chpi_[key] + _validate_type(val, np.ndarray, key_str) + shape = val.shape + if val.ndim != want_ndim: + raise ValueError(f"{key_str} must have ndim={want_ndim}, got {val.ndim}") + if n_times is None and key != "proj": + n_times = shape[0] + if n_times != shape[0] and key != "proj": + raise ValueError( + f"{name} have inconsistent number of time points in {want_keys}" + ) + if name == "chpi_locs": + n_coils = chpi_["rrs"].shape[1] + for key in ("gofs", "moments"): + val = chpi_[key] + if val.shape[1] != n_coils: + raise ValueError( + f'chpi_locs["rrs"] had values for {n_coils} coils but ' + f'chpi_locs["{key}"] had values for {val.shape[1]} coils' + ) + for key in ("rrs", "moments"): + val = chpi_[key] + if val.shape[2] != 3: + raise ValueError( + f'chpi_locs["{key}"].shape[2] must be 3, got shape {shape}' + ) + else: + assert name == "chpi_amplitudes" + slopes, proj = chpi_["slopes"], chpi_["proj"] + _validate_type(proj, Projection, 'chpi_amplitudes["proj"]') + n_ch = len(proj["data"]["col_names"]) + if slopes.shape[0] != n_times or slopes.shape[2] != n_ch: + raise ValueError( + f"slopes must have shape[0]=={n_times} and shape[2]=={n_ch}, got shape " + f"{slopes.shape}" + ) + + +@verbose +def compute_head_pos( + info, chpi_locs, dist_limit=0.005, gof_limit=0.98, adjust_dig=False, verbose=None +): + """Compute time-varying head positions. + + Parameters + ---------- + %(info_not_none)s + %(chpi_locs)s + Typically obtained by :func:`~mne.chpi.compute_chpi_locs` or + :func:`~mne.chpi.extract_chpi_locs_ctf`. + dist_limit : float + Minimum distance (m) to accept for coil position fitting. + gof_limit : float + Minimum goodness of fit to accept for each coil. + %(adjust_dig_chpi)s + %(verbose)s + + Returns + ------- + quats : ndarray, shape (n_pos, 10) + MaxFilter-formatted head position parameters. The columns correspond to + ``[t, q1, q2, q3, x, y, z, gof, err, v]`` for each time point. + + See Also + -------- + compute_chpi_locs + extract_chpi_locs_ctf + read_head_pos + write_head_pos + + Notes + ----- + .. versionadded:: 0.20 + """ + _check_chpi_param(chpi_locs, "chpi_locs") + _validate_type(info, Info, "info") + hpi_dig_head_rrs = _get_hpi_initial_fit(info, adjust=adjust_dig, verbose="error") + n_coils = len(hpi_dig_head_rrs) + coil_dev_rrs = apply_trans(invert_transform(info["dev_head_t"]), hpi_dig_head_rrs) + dev_head_t = info["dev_head_t"]["trans"] + pos_0 = dev_head_t[:3, 3] + last = dict( + quat_fit_time=-0.1, + coil_dev_rrs=coil_dev_rrs, + quat=np.concatenate([rot_to_quat(dev_head_t[:3, :3]), dev_head_t[:3, 3]]), + ) + del coil_dev_rrs + quats = [] + for fit_time, this_coil_dev_rrs, g_coils in zip( + *(chpi_locs[key] for key in ("times", "rrs", "gofs")) + ): + use_idx = np.where(g_coils >= gof_limit)[0] + + # + # 1. Check number of good ones + # + if len(use_idx) < 3: + gofs = ", ".join(f"{g:0.2f}" for g in g_coils) + warn( + f"{_time_prefix(fit_time)}{len(use_idx)}/{n_coils} " + "good HPI fits, cannot determine the transformation " + f"({gofs} GOF)!" + ) + continue + + # + # 2. Fit the head translation and rotation params (minimize error + # between coil positions and the head coil digitization + # positions) iteratively using different sets of coils. + # + this_quat, g, use_idx = _fit_chpi_quat_subset( + this_coil_dev_rrs, hpi_dig_head_rrs, use_idx + ) + + # + # 3. Stop if < 3 good + # + + # Convert quaterion to transform + this_dev_head_t = _quat_to_affine(this_quat) + est_coil_head_rrs = apply_trans(this_dev_head_t, this_coil_dev_rrs) + errs = np.linalg.norm(hpi_dig_head_rrs - est_coil_head_rrs, axis=1) + n_good = ((g_coils >= gof_limit) & (errs < dist_limit)).sum() + if n_good < 3: + warn_str = ", ".join( + f"{1000 * e:0.1f}::{g:0.2f}" for e, g in zip(errs, g_coils) + ) + warn( + f"{_time_prefix(fit_time)}{n_good}/{n_coils} good HPI fits, cannot " + f"determine the transformation ({warn_str} mm/GOF)!" + ) + continue + + # velocities, in device coords, of HPI coils + dt = fit_time - last["quat_fit_time"] + vs = tuple( + 1000.0 + * np.linalg.norm(last["coil_dev_rrs"] - this_coil_dev_rrs, axis=1) + / dt + ) + logger.info( + _time_prefix(fit_time) + + ( + "%s/%s good HPI fits, movements [mm/s] = " + + " / ".join(["% 8.1f"] * n_coils) + ) + % ((n_good, n_coils) + vs) + ) + + # Log results + # MaxFilter averages over a 200 ms window for display, but we don't + for ii in range(n_coils): + if ii in use_idx: + start, end = " ", "/" + else: + start, end = "(", ")" + log_str = ( + " " + + start + + "{0:6.1f} {1:6.1f} {2:6.1f} / " + + "{3:6.1f} {4:6.1f} {5:6.1f} / " + + "g = {6:0.3f} err = {7:4.1f} " + + end + ) + vals = np.concatenate( + ( + 1000 * hpi_dig_head_rrs[ii], + 1000 * est_coil_head_rrs[ii], + [g_coils[ii], 1000 * errs[ii]], + ) + ) + if len(use_idx) >= 3: + if ii <= 2: + log_str += "{8:6.3f} {9:6.3f} {10:6.3f}" + vals = np.concatenate((vals, this_dev_head_t[ii, :3])) + elif ii == 3: + log_str += "{8:6.1f} {9:6.1f} {10:6.1f}" + vals = np.concatenate((vals, this_dev_head_t[:3, 3] * 1000.0)) + logger.debug(log_str.format(*vals)) + + # resulting errors in head coil positions + d = np.linalg.norm(last["quat"][3:] - this_quat[3:]) # m + r = _angle_between_quats(last["quat"][:3], this_quat[:3]) / dt + v = d / dt # m/s + d = 100 * np.linalg.norm(this_quat[3:] - pos_0) # dis from 1st + logger.debug( + f" #t = {fit_time:0.3f}, #e = {100 * errs.mean():0.2f} cm, #g = {g:0.3f}" + f", #v = {100 * v:0.2f} cm/s, #r = {r:0.2f} rad/s, #d = {d:0.2f} cm" + ) + q_rep = " ".join(f"{qq:8.5f}" for qq in this_quat) + logger.debug(f" #t = {fit_time:0.3f}, #q = {q_rep}") + + quats.append( + np.concatenate(([fit_time], this_quat, [g], [errs[use_idx].mean()], [v])) + ) + last["quat_fit_time"] = fit_time + last["quat"] = this_quat + last["coil_dev_rrs"] = this_coil_dev_rrs + quats = np.array(quats, np.float64) + quats = np.zeros((0, 10)) if quats.size == 0 else quats + return quats + + +def _fit_chpi_quat_subset(coil_dev_rrs, coil_head_rrs, use_idx): + quat, g = _fit_chpi_quat(coil_dev_rrs[use_idx], coil_head_rrs[use_idx]) + out_idx = use_idx.copy() + if len(use_idx) > 3: # try dropping one (recursively) + for di in range(len(use_idx)): + this_use_idx = list(use_idx[:di]) + list(use_idx[di + 1 :]) + this_quat, this_g, this_use_idx = _fit_chpi_quat_subset( + coil_dev_rrs, coil_head_rrs, this_use_idx + ) + if this_g > g: + quat, g, out_idx = this_quat, this_g, this_use_idx + return quat, g, np.array(out_idx, int) + + +@verbose +def compute_chpi_snr( + raw, t_step_min=0.01, t_window="auto", ext_order=1, tmin=0, tmax=None, verbose=None +): + """Compute time-varying estimates of cHPI SNR. + + Parameters + ---------- + raw : instance of Raw + Raw data with cHPI information. + t_step_min : float + Minimum time step to use. + %(t_window_chpi_t)s + %(ext_order_chpi)s + %(tmin_raw)s + %(tmax_raw)s + %(verbose)s + + Returns + ------- + chpi_snrs : dict + The time-varying cHPI SNR estimates, with entries "times", "freqs", + "snr_mag", "power_mag", and "resid_mag" (and/or "snr_grad", + "power_grad", and "resid_grad", depending on which channel types are + present in ``raw``). + + See Also + -------- + mne.chpi.compute_chpi_locs, mne.chpi.compute_chpi_amplitudes + + Notes + ----- + .. versionadded:: 0.24 + """ + return _compute_chpi_amp_or_snr( + raw, t_step_min, t_window, ext_order, tmin, tmax, verbose, snr=True + ) + + +@verbose +def compute_chpi_amplitudes( + raw, t_step_min=0.01, t_window="auto", ext_order=1, tmin=0, tmax=None, verbose=None +): + """Compute time-varying cHPI amplitudes. + + Parameters + ---------- + raw : instance of Raw + Raw data with cHPI information. + t_step_min : float + Minimum time step to use. + %(t_window_chpi_t)s + %(ext_order_chpi)s + %(tmin_raw)s + %(tmax_raw)s + %(verbose)s + + Returns + ------- + %(chpi_amplitudes)s + + See Also + -------- + mne.chpi.compute_chpi_locs, mne.chpi.compute_chpi_snr + + Notes + ----- + This function will: + + 1. Get HPI frequencies, HPI status channel, HPI status bits, + and digitization order using ``_setup_hpi_amplitude_fitting``. + 2. Window data using ``t_window`` (half before and half after ``t``) and + ``t_step_min``. + 3. Use a linear model (DC + linear slope + sin + cos terms) to fit + sinusoidal amplitudes to MEG channels. + It uses SVD to determine the phase/amplitude of the sinusoids. + + In "auto" mode, ``t_window`` will be set to the longer of: + + 1. Five cycles of the lowest HPI or line frequency. + Ensures that the frequency estimate is stable. + 2. The reciprocal of the smallest difference between HPI and line freqs. + Ensures that neighboring frequencies can be disambiguated. + + The output is meant to be used with :func:`~mne.chpi.compute_chpi_locs`. + + .. versionadded:: 0.20 + """ + return _compute_chpi_amp_or_snr( + raw, t_step_min, t_window, ext_order, tmin, tmax, verbose + ) + + +def _compute_chpi_amp_or_snr( + raw, + t_step_min=0.01, + t_window="auto", + ext_order=1, + tmin=0, + tmax=None, + verbose=None, + snr=False, +): + """Compute cHPI amplitude or SNR. + + See compute_chpi_amplitudes for parameter descriptions. One additional + boolean parameter ``snr`` signals whether to return SNR instead of + amplitude. + """ + hpi = _setup_hpi_amplitude_fitting(raw.info, t_window, ext_order=ext_order) + tmin, tmax = raw._tmin_tmax_to_start_stop(tmin, tmax) + tmin = tmin / raw.info["sfreq"] + tmax = tmax / raw.info["sfreq"] + need_win = hpi["t_window"] / 2.0 + fit_idxs = raw.time_as_index( + np.arange(tmin + need_win, tmax, t_step_min), use_rounding=True + ) + logger.info( + f"Fitting {len(hpi['freqs'])} HPI coil locations at up to " + f"{len(fit_idxs)} time points ({tmax - tmin:.1f} s duration)" + ) + del tmin, tmax + sin_fits = dict() + sin_fits["proj"] = hpi["proj"] + sin_fits["times"] = ( + np.round(fit_idxs + raw.first_samp - hpi["n_window"] / 2.0) / raw.info["sfreq"] + ) + n_times = len(sin_fits["times"]) + n_freqs = len(hpi["freqs"]) + n_chans = len(sin_fits["proj"]["data"]["col_names"]) + if snr: + del sin_fits["proj"] + sin_fits["freqs"] = hpi["freqs"] + ch_types = raw.get_channel_types() + grad_offset = 3 if "mag" in ch_types else 0 + for ch_type in ("mag", "grad"): + if ch_type in ch_types: + for key in ("snr", "power", "resid"): + cols = 1 if key == "resid" else n_freqs + sin_fits[f"{ch_type}_{key}"] = np.empty((n_times, cols)) + else: + sin_fits["slopes"] = np.empty((n_times, n_freqs, n_chans)) + message = f"cHPI {'SNRs' if snr else 'amplitudes'}" + for mi, midpt in enumerate(ProgressBar(fit_idxs, mesg=message)): + # + # 0. determine samples to fit. + # + time_sl = midpt - hpi["n_window"] // 2 + time_sl = slice(max(time_sl, 0), min(time_sl + hpi["n_window"], len(raw.times))) + + # + # 1. Fit amplitudes for each channel from each of the N sinusoids + # + amps_or_snrs = _fit_chpi_amplitudes(raw, time_sl, hpi, snr) + if snr: + if amps_or_snrs is None: + amps_or_snrs = np.full((n_freqs, grad_offset + 3), np.nan) + # unpack the SNR estimates. mag & grad are returned in one array + # (because of Numba) so take care with which column is which. + # note that mean residual is a scalar (same for all HPI freqs) but + # is returned as a (tiled) vector (again, because Numba) so that's + # why below we take amps_or_snrs[0, 2] instead of [:, 2] + ch_types = raw.get_channel_types() + if "mag" in ch_types: + sin_fits["mag_snr"][mi] = amps_or_snrs[:, 0] # SNR + sin_fits["mag_power"][mi] = amps_or_snrs[:, 1] # mean power + sin_fits["mag_resid"][mi] = amps_or_snrs[0, 2] # mean resid + if "grad" in ch_types: + sin_fits["grad_snr"][mi] = amps_or_snrs[:, grad_offset] + sin_fits["grad_power"][mi] = amps_or_snrs[:, grad_offset + 1] + sin_fits["grad_resid"][mi] = amps_or_snrs[0, grad_offset + 2] + else: + sin_fits["slopes"][mi] = amps_or_snrs + return sin_fits + + +@verbose +def compute_chpi_locs( + info, + chpi_amplitudes, + t_step_max=1.0, + too_close="raise", + adjust_dig=False, + *, + verbose=None, +): + """Compute locations of each cHPI coils over time. + + Parameters + ---------- + %(info_not_none)s + %(chpi_amplitudes)s + Typically obtained by :func:`mne.chpi.compute_chpi_amplitudes`. + t_step_max : float + Maximum time step to use. + too_close : str + How to handle HPI positions too close to the sensors, + can be ``'raise'`` (default), ``'warning'``, or ``'info'``. + %(adjust_dig_chpi)s + %(verbose)s + + Returns + ------- + %(chpi_locs)s + + See Also + -------- + compute_chpi_amplitudes + compute_head_pos + read_head_pos + write_head_pos + extract_chpi_locs_ctf + + Notes + ----- + This function is designed to take the output of + :func:`mne.chpi.compute_chpi_amplitudes` and: + + 1. Get HPI coil locations (as digitized in ``info['dig']``) in head coords. + 2. If the amplitudes are 98%% correlated with last position + (and Δt < t_step_max), skip fitting. + 3. Fit magnetic dipoles using the amplitudes for each coil frequency. + + The number of fitted points ``n_pos`` will depend on the velocity of head + movements as well as ``t_step_max`` (and ``t_step_min`` from + :func:`mne.chpi.compute_chpi_amplitudes`). + + .. versionadded:: 0.20 + """ + # Set up magnetic dipole fits + _check_option("too_close", too_close, ["raise", "warning", "info"]) + _check_chpi_param(chpi_amplitudes, "chpi_amplitudes") + _validate_type(info, Info, "info") + _validate_type(info["dev_head_t"], Transform, "info['dev_head_t']") + sin_fits = chpi_amplitudes # use the old name below + del chpi_amplitudes + proj = sin_fits["proj"] + meg_picks = pick_channels(info["ch_names"], proj["data"]["col_names"], ordered=True) + info = pick_info(info, meg_picks) # makes a copy + with info._unlock(): + info["projs"] = [proj] + del meg_picks, proj + meg_coils = _concatenate_coils(_create_meg_coils(info["chs"], "accurate")) + + # Set up external model for interference suppression + safe_false = _verbose_safe_false() + cov = make_ad_hoc_cov(info, verbose=safe_false) + whitener, _ = compute_whitener(cov, info, verbose=safe_false) + + # Make some location guesses (1 cm grid) + R = np.linalg.norm(meg_coils[0], axis=1).min() + sphere = ConductorModel(layers=[dict(rad=R)], r0=np.zeros(3), is_sphere=True) + guesses = _make_guesses(sphere, 0.01, 0.0, 0.005, verbose=safe_false)[0]["rr"] + logger.info( + f"Computing {len(guesses)} HPI location guesses " + f"(1 cm grid in a {R * 100:.1f} cm sphere)" + ) + fwd = _magnetic_dipole_field_vec(guesses, meg_coils, too_close) + fwd = np.dot(fwd, whitener.T) + fwd = _reshape_view(fwd, (guesses.shape[0], 3, -1)) + fwd = np.linalg.svd(fwd, full_matrices=False)[2] + guesses = dict(rr=guesses, whitened_fwd_svd=fwd) + del fwd, R + + iter_ = list(zip(sin_fits["times"], sin_fits["slopes"])) + chpi_locs = dict(times=[], rrs=[], gofs=[], moments=[]) + # setup last iteration structure + hpi_dig_dev_rrs = apply_trans( + invert_transform(info["dev_head_t"])["trans"], + _get_hpi_initial_fit(info, adjust=adjust_dig), + ) + last = dict( + sin_fit=None, + coil_fit_time=sin_fits["times"][0] - 1, + coil_dev_rrs=hpi_dig_dev_rrs, + ) + n_hpi = len(hpi_dig_dev_rrs) + del hpi_dig_dev_rrs + for fit_time, sin_fit in ProgressBar(iter_, mesg="cHPI locations "): + # skip this window if bad + if not np.isfinite(sin_fit).all(): + continue + + # check if data has sufficiently changed + if last["sin_fit"] is not None: # first iteration + corrs = np.array( + [np.corrcoef(s, lst)[0, 1] for s, lst in zip(sin_fit, last["sin_fit"])] + ) + corrs *= corrs + # check to see if we need to continue + if ( + fit_time - last["coil_fit_time"] <= t_step_max - 1e-7 + and (corrs > 0.98).sum() >= 3 + ): + # don't need to refit data + continue + + # update 'last' sin_fit *before* inplace sign mult + last["sin_fit"] = sin_fit.copy() + + # + # 2. Fit magnetic dipole for each coil to obtain coil positions + # in device coordinates + # + coil_fits = [ + _fit_magnetic_dipole(f, x0, too_close, whitener, meg_coils, guesses) + for f, x0 in zip(sin_fit, last["coil_dev_rrs"]) + ] + rrs, gofs, moments = zip(*coil_fits) + chpi_locs["times"].append(fit_time) + chpi_locs["rrs"].append(rrs) + chpi_locs["gofs"].append(gofs) + chpi_locs["moments"].append(moments) + last["coil_fit_time"] = fit_time + last["coil_dev_rrs"] = rrs + n_times = len(chpi_locs["times"]) + shapes = dict( + times=(n_times,), + rrs=(n_times, n_hpi, 3), + gofs=(n_times, n_hpi), + moments=(n_times, n_hpi, 3), + ) + for key, val in chpi_locs.items(): + chpi_locs[key] = np.array(val, float).reshape(shapes[key]) + return chpi_locs + + +def _chpi_locs_to_times_dig(chpi_locs): + """Reformat chpi_locs as list of dig (dict).""" + dig = list() + for rrs, gofs in zip(*(chpi_locs[key] for key in ("rrs", "gofs"))): + dig.append( + [ + { + "r": rr, + "ident": idx, + "gof": gof, + "kind": FIFF.FIFFV_POINT_HPI, + "coord_frame": FIFF.FIFFV_COORD_DEVICE, + } + for idx, (rr, gof) in enumerate(zip(rrs, gofs), 1) + ] + ) + return chpi_locs["times"], dig + + +@verbose +def filter_chpi( + raw, + include_line=True, + t_step=0.01, + t_window="auto", + ext_order=1, + allow_line_only=False, + verbose=None, +): + """Remove cHPI and line noise from data. + + .. note:: This function will only work properly if cHPI was on + during the recording. + + Parameters + ---------- + raw : instance of Raw + Raw data with cHPI information. Must be preloaded. Operates in-place. + include_line : bool + If True, also filter line noise. + t_step : float + Time step to use for estimation, default is 0.01 (10 ms). + %(t_window_chpi_t)s + %(ext_order_chpi)s + allow_line_only : bool + If True, allow filtering line noise only. The default is False, + which only allows the function to run when cHPI information is present. + + .. versionadded:: 0.20 + %(verbose)s + + Returns + ------- + raw : instance of Raw + The raw data. + + Notes + ----- + cHPI signals are in general not stationary, because head movements act + like amplitude modulators on cHPI signals. Thus it is recommended to + use this procedure, which uses an iterative fitting method, to + remove cHPI signals, as opposed to notch filtering. + + .. versionadded:: 0.12 + """ + _validate_type(raw, BaseRaw, "raw") + if not raw.preload: + raise RuntimeError("raw data must be preloaded") + t_step = float(t_step) + if t_step <= 0: + raise ValueError(f"t_step ({t_step}) must be > 0") + n_step = int(np.ceil(t_step * raw.info["sfreq"])) + if include_line and raw.info["line_freq"] is None: + raise RuntimeError( + 'include_line=True but raw.info["line_freq"] is ' + "None, consider setting it to the line frequency" + ) + hpi = _setup_hpi_amplitude_fitting( + raw.info, + t_window, + remove_aliased=True, + ext_order=ext_order, + allow_empty=allow_line_only, + verbose=_verbose_safe_false(), + ) + + fit_idxs = np.arange(0, len(raw.times) + hpi["n_window"] // 2, n_step) + n_freqs = len(hpi["freqs"]) + n_remove = 2 * n_freqs + meg_picks = pick_types(raw.info, meg=True, exclude=()) # filter all chs + n_times = len(raw.times) + + msg = f"Removing {n_freqs} cHPI" + if include_line: + n_remove += 2 * len(hpi["line_freqs"]) + msg += f" and {len(hpi['line_freqs'])} line harmonic" + msg += f" frequencies from {len(meg_picks)} MEG channels" + + recon = np.dot(hpi["model"][:, :n_remove], hpi["inv_model"][:n_remove]).T + logger.info(msg) + chunks = list() # the chunks to subtract + last_endpt = 0 + pb = ProgressBar(fit_idxs, mesg="Filtering") + for ii, midpt in enumerate(pb): + left_edge = midpt - hpi["n_window"] // 2 + time_sl = slice( + max(left_edge, 0), min(left_edge + hpi["n_window"], len(raw.times)) + ) + this_len = time_sl.stop - time_sl.start + if this_len == hpi["n_window"]: + this_recon = recon + else: # first or last window + model = hpi["model"][:this_len] + inv_model = np.linalg.pinv(model) + this_recon = np.dot(model[:, :n_remove], inv_model[:n_remove]).T + this_data = raw._data[meg_picks, time_sl] + subt_pt = min(midpt + n_step, n_times) + if last_endpt != subt_pt: + fit_left_edge = left_edge - time_sl.start + hpi["n_window"] // 2 + fit_sl = slice(fit_left_edge, fit_left_edge + (subt_pt - last_endpt)) + chunks.append((subt_pt, np.dot(this_data, this_recon[:, fit_sl]))) + last_endpt = subt_pt + + # Consume (trailing) chunks that are now safe to remove because + # our windows will no longer touch them + if ii < len(fit_idxs) - 1: + next_left_edge = fit_idxs[ii + 1] - hpi["n_window"] // 2 + else: + next_left_edge = np.inf + while len(chunks) > 0 and chunks[0][0] <= next_left_edge: + right_edge, chunk = chunks.pop(0) + raw._data[meg_picks, right_edge - chunk.shape[1] : right_edge] -= chunk + return raw + + +def _compute_good_distances(hpi_coil_dists, new_pos, dist_limit=0.005): + """Compute good coils based on distances.""" + these_dists = cdist(new_pos, new_pos) + these_dists = np.abs(hpi_coil_dists - these_dists) + # there is probably a better algorithm for finding the bad ones... + good = False + use_mask = np.ones(len(hpi_coil_dists), bool) + while not good: + d = these_dists[use_mask][:, use_mask] + d_bad = d > dist_limit + good = not d_bad.any() + if not good: + if use_mask.sum() == 2: + use_mask[:] = False + break # failure + # exclude next worst point + badness = (d * d_bad).sum(axis=0) + exclude_coils = np.where(use_mask)[0][np.argmax(badness)] + use_mask[exclude_coils] = False + return use_mask, these_dists + + +@verbose +def get_active_chpi(raw, *, on_missing="raise", verbose=None): + """Determine how many HPI coils were active for a time point. + + Parameters + ---------- + raw : instance of Raw + Raw data with cHPI information. + %(on_missing_chpi)s + %(verbose)s + + Returns + ------- + n_active : array, shape (n_times) + The number of active cHPIs for every timepoint in raw. + + Notes + ----- + .. versionadded:: 1.2 + """ + # get meg system + system, _ = _get_meg_system(raw.info) + + # check whether we have a neuromag system + if system not in ["122m", "306m"]: + raise NotImplementedError( + "Identifying active HPI channels is not implemented for other systems than " + "neuromag." + ) + # extract hpi info + chpi_info = get_chpi_info(raw.info, on_missing=on_missing) + if (len(chpi_info[2]) == 0) or (chpi_info[1] is None): + return np.zeros_like(raw.times) + + # extract hpi time series and infer which one was on + chpi_ts = raw[chpi_info[1]][0].astype(int) + chpi_active = (chpi_ts & chpi_info[2][:, np.newaxis]).astype(bool) + return chpi_active.sum(axis=0) + + +@verbose +def refit_hpi( + info, + *, + amplitudes=True, + locs=True, + order=True, + ext_order=1, + gof_limit=0.98, + dist_limit=0.005, + use=None, + colinearity_limit=0, + verbose=None, +): + """Refit HPI coil order. + + This operates inplace on ``info``, and will typically be called via + ``refit_hpi(raw.info)`` before further processing. + + Parameters + ---------- + info : instance of Info + The measurement info. + amplitudes : bool + Whether to recompute the HPI amplitudes (slopes) from the raw data obtained + during the original fit using :func:`~mne.chpi.compute_chpi_amplitudes`, + or used the already-computed ones stored in ``info['hpi_meas']``. + If this is True, ``locs`` and ``order`` must also be True. + locs : bool + Whether to recompute the HPI coil locations using + :func:`~mne.chpi.compute_chpi_locs`, or use the already-computed ones stored in + ``info['hpi_results']``. + If this is True, ``order`` must also be True. + order : bool + Whether to refit the coil order by testing all permutations for the best + goodness of fit between digitized coil locations and (rigid-transformed) + fitted coil locations. + %(ext_order_chpi)s + gof_limit : float + The goodness-of-fit limit to use when choosing which coils to use for refitting. + dist_limit : float + The distance limit (in meters) to use when choosing which coils to use for + refitting. + use : int | None + The maximum number of coils to use when testing different coil orderings. + The default for ``hpifit`` in MEGIN software is 3. Default (None) means to + use all coils above ``gof_limit``. Can also be an ndarray of coil indices + (0-indexed!) to use, e.g., ``[1, 2, 4]``. + colinearity_limit : float + The RMS limit (in meters) to use when checking for colinearity of coil + locations. If the RMS difference between the used points and a best-fit linear + approximation is less than this limit, a warning is emitted. + The default (``0``) avoids colinearity warnings altogether. + The appropriate value here is dataset dependent, but for one problematic + dataset the value of 0.03 worked well. + %(verbose)s + + Returns + ------- + info : instance of Info + The modified measurement info (same as input). + + Notes + ----- + This adds additional entries to ``info["hpi_meas"]`` and + ``info["hpi_results"]``, leaving the existing ones intact. + It will always modify ``info["dev_head_t"]`` inplace. + + The algorithm is as follows: + + 1. Optionally recompute HPI amplitudes (sinusoidal fit for each channel) using + :func:`~mne.chpi.compute_chpi_amplitudes`. + 2. Optionally use HPI amplitudes to fit HPI coil locations using + :func:`~mne.chpi.compute_chpi_locs`. + 3. Optionally determine coil digitization order by testing all permutations + for the best goodness of fit between digitized coil locations and + (rigid-transformed) fitted coil locations, choosing the order first based on + those that satisfy ``gof_limit`` then the others. + 4. Subselect coils to use for fitting ``dev_head_t`` based on ``gof_limit``, + ``dist_limit``, and ``use``. + 5. Update info inplace by modifying ``info["dev_head_t"]`` and appending new entries + to ``info["hpi_meas"]`` and ``info["hpi_results"]``. + + .. versionadded:: 1.11 + """ + _validate_type(info, Info, "info") + fit_info = pick_info(info, pick_types(info, meg=True, exclude=())) + # Set bads to empty list here. In theory flux jumps etc. or even flat channels + # shouldn't affect the fit much. At some point we could allow ignoring bads, + # but it would make the API more complex (KISS) and make the info accounting harder + # (e.g., slopes must always have shape[-1] == len(all_meg_chs)). + fit_info["bads"] = [] # for backward compat... maybe shouldn't do this + vf = _verbose_safe_false() + hpi = _setup_hpi_amplitude_fitting(fit_info, 1.0, ext_order=ext_order, verbose=vf) + n_coils = info["hpi_subsystem"]["ncoil"] + if use is not None: + use = np.array(use) + if use.dtype.kind != "i": + raise ValueError( + f"use must be an integer or array-like of integers, got {use.dtype}" + ) + if use.shape == (): + use = int(use.item()) + if use < 3: + raise ValueError(f"max_use must be at least 3, got {use}") + elif ( + use.ndim != 1 + or not np.array_equal(np.sort(use), np.unique(use)) + or not np.isin(use, np.arange(info["hpi_subsystem"]["ncoil"])).all() + ): + raise ValueError( + "use must be a 1D array of unique integers in the range [0, " + f"{n_coils - 1}]" + ) + assert use is None or isinstance(use, int | np.ndarray) # we have this now + _validate_type(amplitudes, bool, "amplitudes") + _validate_type(locs, bool, "locs") + _validate_type(order, bool, "order") + _validate_type(dist_limit, "numeric", "dist_limit") + _validate_type(colinearity_limit, "numeric", "colinearity_limit") + if amplitudes and not locs: + raise ValueError( + "If amplitudes is True, locs must also be True (otherwise " + "recomputing amplitudes has no effect)" + ) + if locs and not order: + raise ValueError( + "If locs is True, order must also be True (otherwise " + "recomputing locations has no effect)" + ) + logger.info(f"Refitting HPI coil order for {n_coils} coils ...") + old_meas = info["hpi_meas"][-1] + old_results = info["hpi_results"][-1] + slopes = np.array([[old_meas["hpi_coils"][ci]["slopes"] for ci in range(n_coils)]]) + + # 1. Compute HPI amplitudes + if amplitudes: + epoch = old_meas["hpi_coils"][0]["epoch"] + cals = info._cals[pick_types(info, meg=True, exclude=()), np.newaxis] + assert cals.shape[0] == epoch.shape[0], "Calibration shape mismatch" + data = epoch * cals + fit_raw = RawArray(data, fit_info) + stop = fit_raw.times[-1] + fit_amps = compute_chpi_amplitudes( + fit_raw, t_step_min=stop, t_window=stop + 1.0 / info["sfreq"] + ) + for ci, slope in enumerate(fit_amps["slopes"][0]): + old_slope = old_meas["hpi_coils"][ci]["slopes"] + corr = np.abs(np.corrcoef(slope, old_slope)[0, 1]) + logger.info(f" Coil {ci + 1}: slope correlation with old = {corr:.3f}") + else: + fit_amps = dict( + times=np.array([old_meas["first_samp"] / info["sfreq"]]), + slopes=slopes, + proj=hpi["proj"], + ) + del amplitudes + + # 2. Compute HPI locations + if locs: + fit_locs = compute_chpi_locs(fit_info, fit_amps) + for ci in range(n_coils): + dist = 1e3 * np.linalg.norm( + fit_locs["rrs"][0][ci] - old_results["dig_points"][ci]["r"] + ) + logger.info( + f" Coil {ci + 1}: location difference with old = {dist:.1f} mm" + ) + else: + fit_locs = dict( + rrs=[np.array([d["r"] for d in old_results["dig_points"]], float)], + gofs=[old_results["goodness"]], + moments=[old_results["moments"]], + ) + del fit_info, locs + + # 3. Determine coil order + hpi_dig = _sorted_hpi_dig(info["dig"]) + assert all(d["coord_frame"] == FIFF.FIFFV_COORD_HEAD for d in hpi_dig) # should be + hpi_head = np.array([d["r"] for d in hpi_dig]).astype(float) + del hpi_dig + hpi_dev = fit_locs["rrs"][0].astype(float) + hpi_gofs = fit_locs["gofs"][0] + gofs_str = " ".join(f"{g:.3f}" for g in hpi_gofs) + logger.info(f" Coil goodness-of-fits: {gofs_str}") + assert len(hpi_head) == len(hpi_dev) == n_coils + if order: + fit_dev_head_t, fit_order, _g = _fit_coil_order_dev_head_trans( + hpi_dev, + hpi_head, + gofs=hpi_gofs, + gof_limit=gof_limit, + prefix=" ", + ) + else: + fit_order = info["hpi_results"][-1]["order"] - 1 # make 0-indexed + fit_dev_head_t = info["dev_head_t"]["trans"] + + # 4. Subselect usable coils and determine final dev_head_t + if isinstance(use, int) or use is None: + use_mask = _gof_use_mask(hpi_gofs, gof_limit=gof_limit) + quat, _g = _fit_chpi_quat(hpi_dev[use_mask], hpi_head[fit_order][use_mask]) + fit_dev_head_t = _quat_to_affine(quat) + hpi_head_got = apply_trans(fit_dev_head_t, hpi_dev) + dists = np.linalg.norm(hpi_head_got - hpi_head[fit_order], axis=1) + dist_str = " ".join(f"{dist * 1e3:.1f}" for dist in dists) + logger.info(f" Coil distances after initial fit: {dist_str} mm") + good_dists_idx = np.where(dists[use_mask] <= dist_limit)[0] + if not len(good_dists_idx) >= 3: + raise RuntimeError( + f"Only {len(good_dists_idx)} coil{_pl(good_dists_idx)} with distance " + f"<= {dist_limit * 1e3:.1f} mm, need at least 3 to refit HPI order " + f"(got distances: {np.round(1e3 * dists, 1)})." + ) + used = np.where(use_mask)[0][good_dists_idx] + if use is not None: + used = np.sort(used[np.argsort(hpi_gofs[used])[-use:]]) + else: + used = use + del use + used_str = " ".join(str(u + 1) for u in used) + logger.info(f" Using coils {used_str} to compute final dev_head_t") + + # Sanity check linearity of points + # The threshold of 3cm was empirically determined by looking at a known problematic + # dataset and seeing when it was fixed. + limit_cm = colinearity_limit * 1e2 + min_kind, min_cm = "", np.inf + for kind, pts in [ + ("digitized", hpi_head[fit_order][used]), + ("fitted", hpi_dev[used]), + ]: + centered = pts - pts.mean(axis=0) + v = np.linalg.svd(centered, full_matrices=False)[2] + resid = pts - (pts @ v[0])[:, np.newaxis] * v[0] + # check if RMS error is less than 5 mm + rms_cm = 1e2 * np.sqrt(np.mean(resid * resid)) + if rms_cm < min_cm: + min_cm = rms_cm + min_kind = kind + if min_cm < limit_cm: + extra = "" + if len(used) < n_coils: + extra += ( + ", consider including more coils by adjusting the gof_limit, " + "dist_limit, amplitudes, locs, or manually setting order" + ) + warn( + f"The {len(used)} {min_kind} coil locations {used_str} are approximately " + f"colinear (RMS error {min_cm:.1f} cm from a linear fit). The fit may be " + f"unstable and be fit as an incorrect rotation about a line{extra}" + ) + quat, _g = _fit_chpi_quat(hpi_dev[used], hpi_head[fit_order][used]) + assert np.linalg.det(quat_to_rot(quat[:3])) > 0.9999 + fit_dev_head_t = _quat_to_affine(quat) + + # 5. Adjust metadata + info["dev_head_t"]["trans"][:] = fit_dev_head_t + results = copy.deepcopy(old_results) + results["coord_trans"]["trans"][:] = fit_dev_head_t + results["accept"] = 1 + results["used"] = used + 1 # make 1-indexed (can be different length from previous) + results["order"][:] = fit_order + 1 # make 1-indexed + results["goodness"][:] = hpi_gofs + results["good_limit"] = gof_limit + results["moments"][:] = fit_locs["moments"][0] # ndarray, shape (n_coils, 3) + results["dist_limit"] = dist_limit + del fit_locs + for ci, loc in enumerate(hpi_dev): + results["dig_points"][ci]["r"][:] = loc.astype(float) + del hpi_dev, fit_dev_head_t, fit_order + meas = copy.deepcopy(old_meas) + meas["used"] = np.arange(1, n_coils + 1) # we use all of them + for ci, slope in enumerate(fit_amps["slopes"][0]): + meas["hpi_coils"][ci]["slopes"][:] = slope + # print out some stats about the refit + to_print = dict(old=old_results, new=results) + for kind, result in to_print.items(): + this_order = result["order"] + msg = f" {kind.capitalize()} order {this_order} errors: " + # errors + this_dev_head_t = result["coord_trans"] + this_hpi_dev = np.array([d["r"] for d in result["dig_points"]]).astype(float) + diffs = apply_trans(this_dev_head_t, this_hpi_dev) - hpi_head[this_order - 1] + dists = 1e3 * np.linalg.norm(diffs, axis=1) + for dist in dists: + msg += f"{dist:5.1f} " + msg += "mm" + logger.info(msg) + # In theory these are lists, but it seems like maxfilter only likes having a single + # entry. At some point we should try recording data where multiple fits are stored + # (maybe there actually aren't any...) + info["hpi_meas"][-1] = meas + info["hpi_results"][-1] = result + return info + + +def _gof_use_mask(hpi_gofs, *, gof_limit): + assert isinstance(hpi_gofs, np.ndarray) and hpi_gofs.ndim == 1 + use_mask = hpi_gofs >= gof_limit + n_use = use_mask.sum() + if n_use < 3: + gofs = ", ".join(f"{g:.3f}" for g in hpi_gofs) + raise RuntimeError( + f"Only {n_use} coil{_pl(n_use)} with goodness of fit >= {gof_limit}" + f", need at least 3 to refit HPI order (got {gofs})." + ) + return use_mask + + +def _sorted_hpi_dig(dig, *, kinds=(FIFF.FIFFV_POINT_HPI,)): + return sorted( + # need .get here because the hpi_result["dig_points"] does not set it + (d for d in dig if d.get("kind", FIFF.FIFFV_POINT_HPI) in kinds), + key=lambda d: d["ident"], + ) diff --git a/mne-python/source/mne/commands/__init__.py b/mne-python/source/mne/commands/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..1c7134ea78ba30e40ccef9fd6a7538488c21e428 --- /dev/null +++ b/mne-python/source/mne/commands/__init__.py @@ -0,0 +1,8 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Command-line utilities.""" +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/commands/__init__.pyi b/mne-python/source/mne/commands/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..c0caf04abbbe6b35ac3261c1bde4466af1479955 --- /dev/null +++ b/mne-python/source/mne/commands/__init__.pyi @@ -0,0 +1,2 @@ +__all__ = ["utils"] +from . import utils diff --git a/mne-python/source/mne/commands/mne_anonymize.py b/mne-python/source/mne/commands/mne_anonymize.py new file mode 100644 index 0000000000000000000000000000000000000000..28fae42c82b922c58f1eb9d0c73056364ef2ba40 --- /dev/null +++ b/mne-python/source/mne/commands/mne_anonymize.py @@ -0,0 +1,127 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Anonymize raw fif file. + +To anonymize other file types call :func:`mne.io.anonymize_info` on their +:class:`~mne.Info` objects and resave to disk. + +Examples +-------- +.. code-block:: console + + $ mne anonymize -f sample_audvis_raw.fif + +""" + +import os.path as op +import sys + +import mne + +ANONYMIZE_FILE_PREFIX = "anon" + + +def mne_anonymize(fif_fname, out_fname, keep_his, daysback, overwrite): + """Call *anonymize_info* on fif file and save. + + Parameters + ---------- + fif_fname : path-like + Raw fif File + out_fname : path-like | None + Output file name + relative paths are saved relative to parent dir of fif_fname + None will save to parent dir of fif_fname with default prefix + daysback : int | None + Number of days to subtract from all dates. + If None will default to move date of service to Jan 1 2000 + keep_his : bool + If True his_id of subject_info will NOT be overwritten. + defaults to False + overwrite : bool + Overwrite output file if it already exists + """ + raw = mne.io.read_raw_fif(fif_fname, allow_maxshield=True) + raw.anonymize(daysback=daysback, keep_his=keep_his) + + # determine out_fname + dir_name = op.split(fif_fname)[0] + if out_fname is None: + fif_bname = op.basename(fif_fname) + out_fname = op.join(dir_name, f"{ANONYMIZE_FILE_PREFIX}-{fif_bname}") + elif not op.isabs(out_fname): + out_fname = op.join(dir_name, out_fname) + + raw.save(out_fname, overwrite=overwrite) + + +def run(): + """Run *mne_anonymize* command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-f", + "--file", + type="string", + dest="file", + help="Name of file to modify.", + metavar="FILE", + default=None, + ) + parser.add_option( + "-o", + "--output", + type="string", + dest="output", + help="Name of anonymized output file." + "`anon-` prefix is added to FILE if not given", + metavar="OUTFILE", + default=None, + ) + parser.add_option( + "--keep_his", + dest="keep_his", + action="store_true", + help="Keep the HIS tag (not advised)", + default=False, + ) + parser.add_option( + "-d", + "--daysback", + type="int", + dest="daysback", + help="Move dates in file backwards by this many days.", + metavar="N_DAYS", + default=None, + ) + parser.add_option( + "--overwrite", + dest="overwrite", + action="store_true", + help="Overwrite input file.", + default=False, + ) + + options, args = parser.parse_args() + if options.file is None: + parser.print_help() + sys.exit(1) + + fname = options.file + out_fname = options.output + keep_his = options.keep_his + daysback = options.daysback + overwrite = options.overwrite + if not fname.endswith(".fif"): + raise ValueError(f"{fname} does not seem to be a .fif file.") + + mne_anonymize(fname, out_fname, keep_his, daysback, overwrite) + + +is_main = __name__ == "__main__" +if is_main: + run() diff --git a/mne-python/source/mne/commands/mne_browse_raw.py b/mne-python/source/mne/commands/mne_browse_raw.py new file mode 100644 index 0000000000000000000000000000000000000000..a6db0e2d6eaab1c1adfbda21a21105b878210b79 --- /dev/null +++ b/mne-python/source/mne/commands/mne_browse_raw.py @@ -0,0 +1,220 @@ +r"""Browse raw data. + +This uses :func:`mne.io.read_raw` so it supports the same formats +(without keyword arguments). + +Examples +-------- +.. code-block:: console + + $ mne browse_raw sample_audvis_raw.fif \ + --proj sample_audvis_ecg-proj.fif \ + --eve sample_audvis_raw-eve.fif +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import sys + +import mne + + +def run(): + """Run command.""" + from mne.commands.utils import _add_verbose_flag, get_optparser + from mne.viz import _RAW_CLIP_DEF + + parser = get_optparser(__file__, usage="usage: %prog raw [options]") + + parser.add_option( + "--raw", + dest="raw_in", + help="Input raw FIF file (can also be specified " + "directly as an argument without the --raw prefix)", + metavar="FILE", + ) + parser.add_option( + "--proj", dest="proj_in", help="Projector file", metavar="FILE", default="" + ) + parser.add_option( + "--projoff", + dest="proj_off", + help="Disable all projectors", + default=False, + action="store_true", + ) + parser.add_option( + "--eve", dest="eve_in", help="Events file", metavar="FILE", default="" + ) + parser.add_option( + "-d", + "--duration", + dest="duration", + type="float", + help="Time window for plotting (s)", + default=10.0, + ) + parser.add_option( + "-t", + "--start", + dest="start", + type="float", + help="Initial start time for plotting", + default=0.0, + ) + parser.add_option( + "-n", + "--n_channels", + dest="n_channels", + type="int", + help="Number of channels to plot at a time", + default=20, + ) + parser.add_option( + "-o", + "--order", + dest="group_by", + help="Order to use for grouping during plotting ('type' or 'original')", + default="type", + ) + parser.add_option( + "-p", + "--preload", + dest="preload", + help="Preload raw data (for faster navigation)", + default=False, + action="store_true", + ) + parser.add_option( + "-s", + "--show_options", + dest="show_options", + help="Show projection options dialog", + default=False, + ) + parser.add_option( + "--allowmaxshield", + dest="maxshield", + help="Allow loading MaxShield processed data", + action="store_true", + ) + parser.add_option( + "--highpass", + dest="highpass", + type="float", + help="Display high-pass filter corner frequency", + default=-1, + ) + parser.add_option( + "--lowpass", + dest="lowpass", + type="float", + help="Display low-pass filter corner frequency", + default=-1, + ) + parser.add_option( + "--filtorder", + dest="filtorder", + type="int", + help="Display filtering IIR order (or 0 to use FIR)", + default=4, + ) + parser.add_option( + "--clipping", + dest="clipping", + help="Enable trace clipping mode. Can be 'clamp', 'transparent', a float, " + "or 'none'.", + default=_RAW_CLIP_DEF, + ) + parser.add_option( + "--filterchpi", + dest="filterchpi", + help="Enable filtering cHPI signals.", + default=None, + action="store_true", + ) + parser.add_option( + "--butterfly", + dest="butterfly", + help="Plot in butterfly mode", + default=False, + action="store_true", + ) + _add_verbose_flag(parser) + options, args = parser.parse_args() + + if len(args): + raw_in = args[0] + else: + raw_in = options.raw_in + duration = options.duration + start = options.start + n_channels = options.n_channels + group_by = options.group_by + preload = options.preload + show_options = options.show_options + proj_in = options.proj_in + proj_off = options.proj_off + eve_in = options.eve_in + maxshield = options.maxshield + highpass = options.highpass + lowpass = options.lowpass + filtorder = options.filtorder + clipping = options.clipping + if isinstance(clipping, str): + if clipping.lower() == "none": + clipping = None + else: + try: + clipping = float(clipping) # allow float and convert it + except ValueError: + pass + filterchpi = options.filterchpi + verbose = options.verbose + butterfly = options.butterfly + + if raw_in is None: + parser.print_help() + sys.exit(1) + + kwargs = dict(preload=preload) + if maxshield: + kwargs.update(allow_maxshield="yes") + raw = mne.io.read_raw(raw_in, **kwargs) + if len(proj_in) > 0: + projs = mne.read_proj(proj_in) + raw.info["projs"] = projs + if len(eve_in) > 0: + events = mne.read_events(eve_in) + else: + events = None + + if filterchpi: + if not preload: + raise RuntimeError("Raw data must be preloaded for chpi, use --preload") + raw = mne.chpi.filter_chpi(raw) + + highpass = None if highpass < 0 or filtorder < 0 else highpass + lowpass = None if lowpass < 0 or filtorder < 0 else lowpass + raw.plot( + duration=duration, + start=start, + n_channels=n_channels, + group_by=group_by, + show_options=show_options, + events=events, + highpass=highpass, + lowpass=lowpass, + filtorder=filtorder, + clipping=clipping, + butterfly=butterfly, + proj=not proj_off, + verbose=verbose, + show=True, + block=True, + ) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_bti2fiff.py b/mne-python/source/mne/commands/mne_bti2fiff.py new file mode 100644 index 0000000000000000000000000000000000000000..8a0606444aac5aac14da35cb40c64a7d0dd71f4c --- /dev/null +++ b/mne-python/source/mne/commands/mne_bti2fiff.py @@ -0,0 +1,122 @@ +"""Import BTi / 4D MagnesWH3600 data to fif file. + +Notes +----- +1. Currently direct inclusion of reference channel weights + is not supported. Please use 'mne_create_comp_data' to include + the weights or use the low level functions from this module to + include them by yourself. +2. The informed guess for the 4D name is E31 for the ECG channel and + E63, E63 for the EOG channels. Please check and adjust if those channels + are present in your dataset but 'ECG 01' and 'EOG 01', 'EOG 02' don't + appear in the channel names of the raw object. + +Examples +-------- +.. code-block:: console + + $ mne bti2fiff --pdf C,rfDC -o my_raw.fif + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import sys + +import mne +from mne.io import read_raw_bti + + +def run(): + """Run command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-p", "--pdf", dest="pdf_fname", help="Input data file name", metavar="FILE" + ) + parser.add_option( + "-c", + "--config", + dest="config_fname", + help="Input config file name", + metavar="FILE", + default="config", + ) + parser.add_option( + "--head_shape", + dest="head_shape_fname", + help="Headshape file name", + metavar="FILE", + default="hs_file", + ) + parser.add_option( + "-o", + "--out_fname", + dest="out_fname", + help="Name of the resulting fiff file", + default="as_data_fname", + ) + parser.add_option( + "-r", + "--rotation_x", + dest="rotation_x", + type="float", + help="Compensatory rotation about Neuromag x axis, deg", + default=2.0, + ) + parser.add_option( + "-T", + "--translation", + dest="translation", + type="str", + help="Default translation, meter", + default=(0.00, 0.02, 0.11), + ) + parser.add_option( + "--ecg_ch", dest="ecg_ch", type="str", help="4D ECG channel name", default="E31" + ) + parser.add_option( + "--eog_ch", + dest="eog_ch", + type="str", + help="4D EOG channel names", + default="E63,E64", + ) + + options, args = parser.parse_args() + + pdf_fname = options.pdf_fname + if pdf_fname is None: + parser.print_help() + sys.exit(1) + + config_fname = options.config_fname + head_shape_fname = options.head_shape_fname + out_fname = options.out_fname + rotation_x = options.rotation_x + translation = options.translation + ecg_ch = options.ecg_ch + eog_ch = options.ecg_ch.split(",") + + if out_fname == "as_data_fname": + out_fname = pdf_fname + "_raw.fif" + + raw = read_raw_bti( + pdf_fname=pdf_fname, + config_fname=config_fname, + head_shape_fname=head_shape_fname, + rotation_x=rotation_x, + translation=translation, + ecg_ch=ecg_ch, + eog_ch=eog_ch, + ) + + raw.save(out_fname) + raw.close() + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_clean_eog_ecg.py b/mne-python/source/mne/commands/mne_clean_eog_ecg.py new file mode 100644 index 0000000000000000000000000000000000000000..add6e3830af911c0865408c49ff9779b90f777f3 --- /dev/null +++ b/mne-python/source/mne/commands/mne_clean_eog_ecg.py @@ -0,0 +1,232 @@ +"""Clean a raw file from EOG and ECG artifacts with PCA (ie SSP). + +Examples +-------- +.. code-block:: console + + $ mne clean_eog_ecg -i in_raw.fif -o clean_raw.fif -e -c + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import sys + +import mne + + +def clean_ecg_eog( + in_fif_fname, + out_fif_fname=None, + eog=True, + ecg=True, + ecg_proj_fname=None, + eog_proj_fname=None, + ecg_event_fname=None, + eog_event_fname=None, + in_path=".", + quiet=False, +): + """Clean ECG from raw fif file. + + Parameters + ---------- + in_fif_fname : path-like + Raw fif File + eog_event_fname : str + name of EOG event file required. + eog : bool + Reject or not EOG artifacts. + ecg : bool + Reject or not ECG artifacts. + ecg_event_fname : str + name of ECG event file required. + in_path : str + Path where all the files are. + """ + if not eog and not ecg: + raise Exception("EOG and ECG cannot be both disabled") + + # Reading fif File + raw_in = mne.io.read_raw_fif(in_fif_fname) + + if in_fif_fname.endswith("_raw.fif") or in_fif_fname.endswith("-raw.fif"): + prefix = in_fif_fname[:-8] + else: + prefix = in_fif_fname[:-4] + + if out_fif_fname is None: + out_fif_fname = prefix + "_clean_ecg_eog_raw.fif" + if ecg_proj_fname is None: + ecg_proj_fname = prefix + "_ecg-proj.fif" + if eog_proj_fname is None: + eog_proj_fname = prefix + "_eog-proj.fif" + if ecg_event_fname is None: + ecg_event_fname = prefix + "_ecg-eve.fif" + if eog_event_fname is None: + eog_event_fname = prefix + "_eog-eve.fif" + + print("Implementing ECG and EOG artifact rejection on data") + + kwargs = dict() if quiet else dict(stdout=None, stderr=None) + if ecg: + ecg_events, _, _ = mne.preprocessing.find_ecg_events( + raw_in, reject_by_annotation=True + ) + print(f"Writing ECG events in {ecg_event_fname}") + mne.write_events(ecg_event_fname, ecg_events) + print("Computing ECG projector") + command = ( + "mne_process_raw", + "--cd", + in_path, + "--raw", + in_fif_fname, + "--events", + ecg_event_fname, + "--makeproj", + "--projtmin", + "-0.08", + "--projtmax", + "0.08", + "--saveprojtag", + "_ecg-proj", + "--projnmag", + "2", + "--projngrad", + "1", + "--projevent", + "999", + "--highpass", + "5", + "--lowpass", + "35", + "--projmagrej", + "4000", + "--projgradrej", + "3000", + ) + mne.utils.run_subprocess(command, **kwargs) + if eog: + eog_events = mne.preprocessing.find_eog_events(raw_in) + print(f"Writing EOG events in {eog_event_fname}") + mne.write_events(eog_event_fname, eog_events) + print("Computing EOG projector") + command = ( + "mne_process_raw", + "--cd", + in_path, + "--raw", + in_fif_fname, + "--events", + eog_event_fname, + "--makeproj", + "--projtmin", + "-0.15", + "--projtmax", + "0.15", + "--saveprojtag", + "_eog-proj", + "--projnmag", + "2", + "--projngrad", + "2", + "--projevent", + "998", + "--lowpass", + "35", + "--projmagrej", + "4000", + "--projgradrej", + "3000", + ) + mne.utils.run_subprocess(command, **kwargs) + + if out_fif_fname is not None: + # Applying the ECG EOG projector + print("Applying ECG EOG projector") + command = ( + "mne_process_raw", + "--cd", + in_path, + "--raw", + in_fif_fname, + "--proj", + in_fif_fname, + "--projoff", + "--save", + out_fif_fname, + "--filteroff", + "--proj", + ecg_proj_fname, + "--proj", + eog_proj_fname, + ) + mne.utils.run_subprocess(command, **kwargs) + print("Done removing artifacts.") + print(f"Cleaned raw data saved in: {out_fif_fname}") + print("IMPORTANT : Please eye-ball the data !!") + else: + print("Projection not applied to raw data.") + + +def run(): + """Run command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-i", "--in", dest="raw_in", help="Input raw FIF file", metavar="FILE" + ) + parser.add_option( + "-o", + "--out", + dest="raw_out", + help="Output raw FIF file", + metavar="FILE", + default=None, + ) + parser.add_option( + "-e", + "--no-eog", + dest="eog", + action="store_false", + help="Remove EOG", + default=True, + ) + parser.add_option( + "-c", + "--no-ecg", + dest="ecg", + action="store_false", + help="Remove ECG", + default=True, + ) + parser.add_option( + "-q", + "--quiet", + dest="quiet", + action="store_true", + help="Suppress mne_process_raw output", + default=False, + ) + + options, args = parser.parse_args() + + if options.raw_in is None: + parser.print_help() + sys.exit(1) + + raw_in = options.raw_in + raw_out = options.raw_out + eog = options.eog + ecg = options.ecg + quiet = options.quiet + + clean_ecg_eog(raw_in, raw_out, eog=eog, ecg=ecg, quiet=quiet) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_compare_fiff.py b/mne-python/source/mne/commands/mne_compare_fiff.py new file mode 100644 index 0000000000000000000000000000000000000000..c619aa57345e39bfff4a6464147601a0e4500ccf --- /dev/null +++ b/mne-python/source/mne/commands/mne_compare_fiff.py @@ -0,0 +1,32 @@ +"""Compare FIFF files. + +Examples +-------- +.. code-block:: console + + $ mne compare_fiff test_raw.fif test_raw_sss.fif + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import sys + +import mne + + +def run(): + """Run command.""" + parser = mne.commands.utils.get_optparser( + __file__, usage="mne compare_fiff " + ) + options, args = parser.parse_args() + if len(args) != 2: + parser.print_help() + sys.exit(1) + mne.viz.compare_fiff(args[0], args[1]) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_compute_proj_ecg.py b/mne-python/source/mne/commands/mne_compute_proj_ecg.py new file mode 100644 index 0000000000000000000000000000000000000000..42038cf1d603e0e2e3f7137a1515b71edd8ed62d --- /dev/null +++ b/mne-python/source/mne/commands/mne_compute_proj_ecg.py @@ -0,0 +1,331 @@ +r"""Compute SSP/PCA projections for ECG artifacts. + +Examples +-------- +.. code-block:: console + + $ mne compute_proj_ecg -i sample_audvis_raw.fif -c "MEG 1531" -a \ + --l-freq 1 --h-freq 100 \ + --rej-grad 3000 --rej-mag 4000 --rej-eeg 100 + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import sys + +import mne + + +def run(): + """Run command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-i", "--in", dest="raw_in", help="Input raw FIF file", metavar="FILE" + ) + parser.add_option( + "--tmin", + dest="tmin", + type="float", + help="Time before event in seconds", + default=-0.2, + ) + parser.add_option( + "--tmax", + dest="tmax", + type="float", + help="Time after event in seconds", + default=0.4, + ) + parser.add_option( + "-g", + "--n-grad", + dest="n_grad", + type="int", + help="Number of SSP vectors for gradiometers", + default=2, + ) + parser.add_option( + "-m", + "--n-mag", + dest="n_mag", + type="int", + help="Number of SSP vectors for magnetometers", + default=2, + ) + parser.add_option( + "-e", + "--n-eeg", + dest="n_eeg", + type="int", + help="Number of SSP vectors for EEG", + default=2, + ) + parser.add_option( + "--l-freq", + dest="l_freq", + type="float", + help="Filter low cut-off frequency in Hz", + default=1, + ) + parser.add_option( + "--h-freq", + dest="h_freq", + type="float", + help="Filter high cut-off frequency in Hz", + default=100, + ) + parser.add_option( + "--ecg-l-freq", + dest="ecg_l_freq", + type="float", + help="Filter low cut-off frequency in Hz used for ECG event detection", + default=5, + ) + parser.add_option( + "--ecg-h-freq", + dest="ecg_h_freq", + type="float", + help="Filter high cut-off frequency in Hz used for ECG event detection", + default=35, + ) + parser.add_option( + "-p", + "--preload", + dest="preload", + help="Temporary file used during computation (to save memory)", + default=True, + ) + parser.add_option( + "-a", + "--average", + dest="average", + action="store_true", + help="Compute SSP after averaging", + default=False, + ) + parser.add_option( + "--proj", dest="proj", help="Use SSP projections from a fif file.", default=None + ) + parser.add_option( + "--filtersize", + dest="filter_length", + type="int", + help="Number of taps to use for filtering", + default=2048, + ) + parser.add_option( + "-j", + "--n-jobs", + dest="n_jobs", + type="int", + help="Number of jobs to run in parallel", + default=1, + ) + parser.add_option( + "-c", + "--channel", + dest="ch_name", + help="Channel to use for ECG detection (Required if no ECG found)", + default=None, + ) + parser.add_option( + "--rej-grad", + dest="rej_grad", + type="float", + help="Gradiometers rejection parameter in fT/cm (peak to peak amplitude)", + default=2000, + ) + parser.add_option( + "--rej-mag", + dest="rej_mag", + type="float", + help="Magnetometers rejection parameter in fT (peak to peak amplitude)", + default=3000, + ) + parser.add_option( + "--rej-eeg", + dest="rej_eeg", + type="float", + help="EEG rejection parameter in µV (peak to peak amplitude)", + default=50, + ) + parser.add_option( + "--rej-eog", + dest="rej_eog", + type="float", + help="EOG rejection parameter in µV (peak to peak amplitude)", + default=250, + ) + parser.add_option( + "--avg-ref", + dest="avg_ref", + action="store_true", + help="Add EEG average reference proj", + default=False, + ) + parser.add_option( + "--no-proj", + dest="no_proj", + action="store_true", + help="Exclude the SSP projectors currently in the fiff file", + default=False, + ) + parser.add_option( + "--bad", + dest="bad_fname", + help="Text file containing bad channels list (one per line)", + default=None, + ) + parser.add_option( + "--event-id", + dest="event_id", + type="int", + help="ID to use for events", + default=999, + ) + parser.add_option( + "--event-raw", + dest="raw_event_fname", + help="raw file to use for event detection", + default=None, + ) + parser.add_option( + "--tstart", + dest="tstart", + type="float", + help="Start artifact detection after tstart seconds", + default=0.0, + ) + parser.add_option( + "--qrsthr", + dest="qrs_threshold", + type="string", + help="QRS detection threshold. Between 0 and 1. Can " + "also be 'auto' for automatic selection", + default="auto", + ) + + options, args = parser.parse_args() + + raw_in = options.raw_in + + if raw_in is None: + parser.print_help() + sys.exit(1) + + tmin = options.tmin + tmax = options.tmax + n_grad = options.n_grad + n_mag = options.n_mag + n_eeg = options.n_eeg + l_freq = options.l_freq + h_freq = options.h_freq + ecg_l_freq = options.ecg_l_freq + ecg_h_freq = options.ecg_h_freq + average = options.average + preload = options.preload + filter_length = options.filter_length + n_jobs = options.n_jobs + ch_name = options.ch_name + reject = dict( + grad=1e-13 * float(options.rej_grad), + mag=1e-15 * float(options.rej_mag), + eeg=1e-6 * float(options.rej_eeg), + eog=1e-6 * float(options.rej_eog), + ) + avg_ref = options.avg_ref + no_proj = options.no_proj + bad_fname = options.bad_fname + event_id = options.event_id + proj_fname = options.proj + raw_event_fname = options.raw_event_fname + tstart = options.tstart + qrs_threshold = options.qrs_threshold + if qrs_threshold != "auto": + try: + qrs_threshold = float(qrs_threshold) + except ValueError: + raise ValueError('qrsthr must be "auto" or a float') + + if bad_fname is not None: + with open(bad_fname) as fid: + bads = [w.rstrip() for w in fid.readlines()] + print(f"Bad channels read : {bads}") + else: + bads = [] + + if raw_in.endswith("_raw.fif") or raw_in.endswith("-raw.fif"): + prefix = raw_in[:-8] + else: + prefix = raw_in[:-4] + + ecg_event_fname = prefix + "_ecg-eve.fif" + + if average: + ecg_proj_fname = prefix + "_ecg_avg-proj.fif" + else: + ecg_proj_fname = prefix + "_ecg-proj.fif" + + raw = mne.io.read_raw_fif(raw_in, preload=preload) + + if raw_event_fname is not None: + raw_event = mne.io.read_raw_fif(raw_event_fname) + else: + raw_event = raw + + flat = None + projs, events = mne.preprocessing.compute_proj_ecg( + raw, + raw_event, + tmin, + tmax, + n_grad, + n_mag, + n_eeg, + l_freq, + h_freq, + average, + filter_length, + n_jobs, + ch_name, + reject, + flat, + bads, + avg_ref, + no_proj, + event_id, + ecg_l_freq, + ecg_h_freq, + tstart, + qrs_threshold, + copy=False, + ) + + raw.close() + + if raw_event_fname is not None: + raw_event.close() + + if proj_fname is not None: + print(f"Including SSP projections from : {proj_fname}") + # append the ecg projs, so they are last in the list + projs = mne.read_proj(proj_fname) + projs + + if isinstance(preload, str) and os.path.exists(preload): + os.remove(preload) + + print(f"Writing ECG projections in {ecg_proj_fname}") + mne.write_proj(ecg_proj_fname, projs) + + print(f"Writing ECG events in {ecg_event_fname}") + mne.write_events(ecg_event_fname, events) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_compute_proj_eog.py b/mne-python/source/mne/commands/mne_compute_proj_eog.py new file mode 100644 index 0000000000000000000000000000000000000000..a1e2679646be6ebf4c94adac994a722384379c89 --- /dev/null +++ b/mne-python/source/mne/commands/mne_compute_proj_eog.py @@ -0,0 +1,329 @@ +r"""Compute SSP/PCA projections for EOG artifacts. + +Examples +-------- +.. code-block:: console + + $ mne compute_proj_eog -i sample_audvis_raw.fif -a \ + --l-freq 1 --h-freq 35 \ + --rej-grad 3000 --rej-mag 4000 --rej-eeg 100 + +or + +.. code-block:: console + + $ mne compute_proj_eog -i sample_audvis_raw.fif -a \ + --l-freq 1 --h-freq 35 \ + --rej-grad 3000 --rej-mag 4000 --rej-eeg 100 \ + --proj sample_audvis_ecg-proj.fif + +to exclude ECG artifacts from projection computation. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import sys + +import mne + + +def run(): + """Run command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-i", "--in", dest="raw_in", help="Input raw FIF file", metavar="FILE" + ) + parser.add_option( + "--tmin", + dest="tmin", + type="float", + help="Time before event in seconds", + default=-0.2, + ) + parser.add_option( + "--tmax", + dest="tmax", + type="float", + help="Time after event in seconds", + default=0.2, + ) + parser.add_option( + "-g", + "--n-grad", + dest="n_grad", + type="int", + help="Number of SSP vectors for gradiometers", + default=2, + ) + parser.add_option( + "-m", + "--n-mag", + dest="n_mag", + type="int", + help="Number of SSP vectors for magnetometers", + default=2, + ) + parser.add_option( + "-e", + "--n-eeg", + dest="n_eeg", + type="int", + help="Number of SSP vectors for EEG", + default=2, + ) + parser.add_option( + "--l-freq", + dest="l_freq", + type="float", + help="Filter low cut-off frequency in Hz", + default=1, + ) + parser.add_option( + "--h-freq", + dest="h_freq", + type="float", + help="Filter high cut-off frequency in Hz", + default=35, + ) + parser.add_option( + "--eog-l-freq", + dest="eog_l_freq", + type="float", + help="Filter low cut-off frequency in Hz used for EOG event detection", + default=1, + ) + parser.add_option( + "--eog-h-freq", + dest="eog_h_freq", + type="float", + help="Filter high cut-off frequency in Hz used for EOG event detection", + default=10, + ) + parser.add_option( + "-p", + "--preload", + dest="preload", + help="Temporary file used during computation (to save memory)", + default=True, + ) + parser.add_option( + "-a", + "--average", + dest="average", + action="store_true", + help="Compute SSP after averaging", + default=False, + ) + parser.add_option( + "--proj", dest="proj", help="Use SSP projections from a fif file.", default=None + ) + parser.add_option( + "--filtersize", + dest="filter_length", + type="int", + help="Number of taps to use for filtering", + default=2048, + ) + parser.add_option( + "-j", + "--n-jobs", + dest="n_jobs", + type="int", + help="Number of jobs to run in parallel", + default=1, + ) + parser.add_option( + "--rej-grad", + dest="rej_grad", + type="float", + help="Gradiometers rejection parameter in fT/cm (peak to peak amplitude)", + default=2000, + ) + parser.add_option( + "--rej-mag", + dest="rej_mag", + type="float", + help="Magnetometers rejection parameter in fT (peak to peak amplitude)", + default=3000, + ) + parser.add_option( + "--rej-eeg", + dest="rej_eeg", + type="float", + help="EEG rejection parameter in µV (peak to peak amplitude)", + default=50, + ) + parser.add_option( + "--rej-eog", + dest="rej_eog", + type="float", + help="EOG rejection parameter in µV (peak to peak amplitude)", + default=1e9, + ) + parser.add_option( + "--avg-ref", + dest="avg_ref", + action="store_true", + help="Add EEG average reference proj", + default=False, + ) + parser.add_option( + "--no-proj", + dest="no_proj", + action="store_true", + help="Exclude the SSP projectors currently in the fiff file", + default=False, + ) + parser.add_option( + "--bad", + dest="bad_fname", + help="Text file containing bad channels list (one per line)", + default=None, + ) + parser.add_option( + "--event-id", + dest="event_id", + type="int", + help="ID to use for events", + default=998, + ) + parser.add_option( + "--event-raw", + dest="raw_event_fname", + help="raw file to use for event detection", + default=None, + ) + parser.add_option( + "--tstart", + dest="tstart", + type="float", + help="Start artifact detection after tstart seconds", + default=0.0, + ) + parser.add_option( + "-c", + "--channel", + dest="ch_name", + type="string", + help="Custom EOG channel(s), comma separated", + default=None, + ) + + options, args = parser.parse_args() + + raw_in = options.raw_in + + if raw_in is None: + parser.print_help() + sys.exit(1) + + tmin = options.tmin + tmax = options.tmax + n_grad = options.n_grad + n_mag = options.n_mag + n_eeg = options.n_eeg + l_freq = options.l_freq + h_freq = options.h_freq + eog_l_freq = options.eog_l_freq + eog_h_freq = options.eog_h_freq + average = options.average + preload = options.preload + filter_length = options.filter_length + n_jobs = options.n_jobs + reject = dict( + grad=1e-13 * float(options.rej_grad), + mag=1e-15 * float(options.rej_mag), + eeg=1e-6 * float(options.rej_eeg), + eog=1e-6 * float(options.rej_eog), + ) + avg_ref = options.avg_ref + no_proj = options.no_proj + bad_fname = options.bad_fname + event_id = options.event_id + proj_fname = options.proj + raw_event_fname = options.raw_event_fname + tstart = options.tstart + ch_name = options.ch_name + + if bad_fname is not None: + with open(bad_fname) as fid: + bads = [w.rstrip() for w in fid.readlines()] + print(f"Bad channels read : {bads}") + else: + bads = [] + + if raw_in.endswith("_raw.fif") or raw_in.endswith("-raw.fif"): + prefix = raw_in[:-8] + else: + prefix = raw_in[:-4] + + eog_event_fname = prefix + "_eog-eve.fif" + + if average: + eog_proj_fname = prefix + "_eog_avg-proj.fif" + else: + eog_proj_fname = prefix + "_eog-proj.fif" + + raw = mne.io.read_raw_fif(raw_in, preload=preload) + + if raw_event_fname is not None: + raw_event = mne.io.read_raw_fif(raw_event_fname) + else: + raw_event = raw + + flat = None + projs, events = mne.preprocessing.compute_proj_eog( + raw=raw, + raw_event=raw_event, + tmin=tmin, + tmax=tmax, + n_grad=n_grad, + n_mag=n_mag, + n_eeg=n_eeg, + l_freq=l_freq, + h_freq=h_freq, + average=average, + filter_length=filter_length, + n_jobs=n_jobs, + reject=reject, + flat=flat, + bads=bads, + avg_ref=avg_ref, + no_proj=no_proj, + event_id=event_id, + eog_l_freq=eog_l_freq, + eog_h_freq=eog_h_freq, + tstart=tstart, + ch_name=ch_name, + copy=False, + ) + + raw.close() + + if raw_event_fname is not None: + raw_event.close() + + if proj_fname is not None: + print(f"Including SSP projections from : {proj_fname}") + # append the eog projs, so they are last in the list + projs = mne.read_proj(proj_fname) + projs + + if isinstance(preload, str) and os.path.exists(preload): + os.remove(preload) + + print(f"Writing EOG projections in {eog_proj_fname}") + mne.write_proj(eog_proj_fname, projs) + + print(f"Writing EOG events in {eog_event_fname}") + mne.write_events(eog_event_fname, events) + + +is_main = __name__ == "__main__" +if is_main: + run() diff --git a/mne-python/source/mne/commands/mne_coreg.py b/mne-python/source/mne/commands/mne_coreg.py new file mode 100644 index 0000000000000000000000000000000000000000..d288c7b53db4c232d8f074ff21e7a103387954a5 --- /dev/null +++ b/mne-python/source/mne/commands/mne_coreg.py @@ -0,0 +1,116 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Open the coregistration GUI. + +Examples +-------- +.. code-block:: console + + $ mne coreg + +""" + +import os.path as op + +import mne + + +def run(): + """Run command.""" + from mne.commands.utils import _add_verbose_flag, get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-d", + "--subjects-dir", + dest="subjects_dir", + default=None, + help="Subjects directory", + ) + parser.add_option( + "-s", "--subject", dest="subject", default=None, help="Subject name" + ) + parser.add_option( + "-f", + "--fiff", + dest="inst", + default=None, + help="FIFF file with digitizer data for coregistration", + ) + parser.add_option( + "--head-opacity", + type=float, + default=None, + dest="head_opacity", + help="The opacity of the head surface, in the range [0, 1].", + ) + parser.add_option( + "--high-res-head", + action="store_true", + default=False, + dest="high_res_head", + help="Use a high-resolution head surface.", + ) + parser.add_option( + "--low-res-head", + action="store_true", + default=False, + dest="low_res_head", + help="Use a low-resolution head surface.", + ) + parser.add_option( + "--trans", + dest="trans", + default=None, + help='Head<->MRI transform FIF file ("-trans.fif")', + ) + parser.add_option( + "--interaction", + type=str, + default=None, + dest="interaction", + help='Interaction style to use, can be "trackball" or "terrain".', + ) + _add_verbose_flag(parser) + + options, args = parser.parse_args() + + if options.low_res_head: + if options.high_res_head: + raise ValueError( + "Can't specify --high-res-head and --low-res-head at the same time." + ) + head_high_res = False + elif options.high_res_head: + head_high_res = True + else: + head_high_res = None + + # expanduser allows ~ for --subjects-dir + subjects_dir = options.subjects_dir + if subjects_dir is not None: + subjects_dir = op.expanduser(subjects_dir) + trans = options.trans + if trans is not None: + trans = op.expanduser(trans) + import faulthandler + + faulthandler.enable() + mne.gui.coregistration( + inst=options.inst, + subject=options.subject, + subjects_dir=subjects_dir, + head_opacity=options.head_opacity, + head_high_res=head_high_res, + trans=trans, + interaction=options.interaction, + show=True, + block=True, + verbose=options.verbose, + ) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_flash_bem.py b/mne-python/source/mne/commands/mne_flash_bem.py new file mode 100644 index 0000000000000000000000000000000000000000..63bcb79d9d8e8917cb8cc4b7b9fe8abb196163f2 --- /dev/null +++ b/mne-python/source/mne/commands/mne_flash_bem.py @@ -0,0 +1,174 @@ +"""Create 3-layer BEM model from Flash MRI images. + +Examples +-------- +.. code-block:: console + + $ mne flash_bem --subject=sample + $ mne flash_bem -s sample -n --registered -5 sample/mri/mef05.mgz -3 sample/mri/mef30.mgz + $ mne flash_bem -s sample -n --registered -5 sample/mri/flash/mef05_*.mgz -3 sample/mri/flash/mef30_*.mgz + +Notes +----- +This program assumes that FreeSurfer and MNE are installed and +sourced properly. + +This function extracts the BEM surfaces (outer skull, inner skull, and +outer skin) from multiecho FLASH MRI data with spin angles of 5 and 30 +degrees. The multiecho FLASH data can be input as .mgz or .nii files. +This function assumes that the Freesurfer segmentation of the subject +has been completed. In particular, the T1.mgz and brain.mgz MRI volumes +should be, as usual, in the subject's mri directory. + +""" # noqa E501 + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import mne +from mne.bem import convert_flash_mris, make_flash_bem + + +def _vararg_callback(option, opt_str, value, parser): + assert value is None + del opt_str # required for input but not used + value = [] + + for arg in parser.rargs: + # stop on --foo like options + if arg[:2] == "--" and len(arg) > 2: + break + if arg[:1] == "-" and len(arg) > 1: + break + value.append(arg) + + del parser.rargs[: len(value)] + setattr(parser.values, option.dest, value) + + +def run(): + """Run command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-s", "--subject", dest="subject", help="Subject name", default=None + ) + parser.add_option( + "-d", + "--subjects-dir", + dest="subjects_dir", + help="Subjects directory", + default=None, + ) + parser.add_option( + "-3", + "--flash30", + "--noflash30", + dest="flash30", + action="callback", + callback=_vararg_callback, + help=( + "The 30-degree flip angle data. If no argument do " + "not use flash30. If arguments are given, them as " + "file names." + ), + ) + parser.add_option( + "-5", + "--flash5", + dest="flash5", + action="callback", + callback=_vararg_callback, + help=("Path to the multiecho flash 5 images. Can be one file or one per echo."), + ) + parser.add_option( + "-r", + "--registered", + dest="registered", + action="store_true", + default=False, + help=( + "Set if the Flash MRI images have already " + "been registered with the T1.mgz file." + ), + ) + parser.add_option( + "-u", + "--unwarp", + dest="unwarp", + action="store_true", + default=False, + help=( + "Run grad_unwarp with -unwarp " + "option on each of the converted data sets" + ), + ) + parser.add_option( + "-o", + "--overwrite", + dest="overwrite", + action="store_true", + default=False, + help="Write over existing .surf files in bem folder", + ) + parser.add_option( + "-v", + "--view", + dest="show", + action="store_true", + help="Show BEM model in 3D for visual inspection", + default=False, + ) + parser.add_option( + "--copy", + dest="copy", + help="Use copies instead of symlinks for surfaces", + action="store_true", + ) + + options, _ = parser.parse_args() + + subject = options.subject + subjects_dir = options.subjects_dir + flash5 = options.flash5 + if flash5 is None or len(flash5) == 0: + flash5 = True + flash30 = options.flash30 + if flash30 is None: + flash30 = True + elif len(flash30) == 0: + flash30 = False + register = not options.registered + unwarp = options.unwarp + overwrite = options.overwrite + show = options.show + copy = options.copy + + if options.subject is None: + parser.print_help() + raise RuntimeError("The subject argument must be set") + + flash5_img = convert_flash_mris( + subject=subject, + subjects_dir=subjects_dir, + flash5=flash5, + flash30=flash30, + unwarp=unwarp, + verbose=True, + ) + make_flash_bem( + subject=subject, + subjects_dir=subjects_dir, + overwrite=overwrite, + show=show, + copy=copy, + register=register, + flash5_img=flash5_img, + verbose=True, + ) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_freeview_bem_surfaces.py b/mne-python/source/mne/commands/mne_freeview_bem_surfaces.py new file mode 100644 index 0000000000000000000000000000000000000000..4edf1465a8a8e3a8bd4cfab11e647c10c231aa19 --- /dev/null +++ b/mne-python/source/mne/commands/mne_freeview_bem_surfaces.py @@ -0,0 +1,114 @@ +"""View the 3-Layers BEM model using Freeview. + +Examples +-------- +.. code-block:: console + + $ mne freeview_bem_surfaces -s sample + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import os.path as op +import sys + +import mne +from mne.utils import get_subjects_dir, run_subprocess + + +def freeview_bem_surfaces(subject, subjects_dir, method=None): + """View 3-Layers BEM model with Freeview. + + Parameters + ---------- + subject : str + Subject name + subjects_dir : path-like + Directory containing subjects data (Freesurfer SUBJECTS_DIR) + method : str | None + Can be ``'flash'`` or ``'watershed'``, or None to use the ``bem/`` directory + files. + """ + subjects_dir = str(get_subjects_dir(subjects_dir, raise_error=True)) + + if subject is None: + raise ValueError("subject argument is None.") + + subject_dir = op.join(subjects_dir, subject) + + if not op.isdir(subject_dir): + raise ValueError( + f"Wrong path: '{subject_dir}'. Check subjects-dir or subject argument." + ) + + env = os.environ.copy() + env["SUBJECT"] = subject + env["SUBJECTS_DIR"] = subjects_dir + + if "FREESURFER_HOME" not in env: + raise RuntimeError("The FreeSurfer environment needs to be set up.") + + mri_dir = op.join(subject_dir, "mri") + bem_dir = op.join(subject_dir, "bem") + mri = op.join(mri_dir, "T1.mgz") + + if method == "watershed": + bem_dir = op.join(bem_dir, "watershed") + outer_skin = op.join(bem_dir, f"{subject}_outer_skin_surface") + outer_skull = op.join(bem_dir, f"{subject}_outer_skull_surface") + inner_skull = op.join(bem_dir, f"{subject}_inner_skull_surface") + else: + if method == "flash": + bem_dir = op.join(bem_dir, "flash") + outer_skin = op.join(bem_dir, "outer_skin.surf") + outer_skull = op.join(bem_dir, "outer_skull.surf") + inner_skull = op.join(bem_dir, "inner_skull.surf") + + # put together the command + cmd = ["freeview"] + cmd += ["--volume", mri] + cmd += ["--surface", f"{inner_skull}:color=red:edgecolor=red"] + cmd += ["--surface", f"{outer_skull}:color=yellow:edgecolor=yellow"] + cmd += ["--surface", f"{outer_skin}:color=255,170,127:edgecolor=255,170,127"] + + run_subprocess(cmd, env=env, stdout=sys.stdout) + print("[done]") + + +def run(): + """Run command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__) + + subject = os.environ.get("SUBJECT") + parser.add_option( + "-s", "--subject", dest="subject", help="Subject name", default=subject + ) + parser.add_option( + "-d", + "--subjects-dir", + dest="subjects_dir", + help="Subjects directory", + ) + parser.add_option( + "-m", + "--method", + dest="method", + help="Method used to generate the BEM model. Can be flash or watershed.", + ) + + options, args = parser.parse_args() + + subject = options.subject + subjects_dir = options.subjects_dir + method = options.method + + freeview_bem_surfaces(subject, subjects_dir, method) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_kit2fiff.py b/mne-python/source/mne/commands/mne_kit2fiff.py new file mode 100644 index 0000000000000000000000000000000000000000..a6874fecf059635156a39760df7aa77bba6285d0 --- /dev/null +++ b/mne-python/source/mne/commands/mne_kit2fiff.py @@ -0,0 +1,114 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Import KIT / NYU data to fif file. + +Examples +-------- +.. code-block:: console + + $ mne kit2fiff --input input.sqd --output output.fif + +Use without arguments to invoke GUI: + +.. code-block:: console + + $ mne kt2fiff + +""" + +import sys + +import mne +from mne.io import read_raw_kit + + +def run(): + """Run command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "--input", dest="input_fname", help="Input data file name", metavar="filename" + ) + parser.add_option( + "--mrk", dest="mrk_fname", help="MEG Marker file name", metavar="filename" + ) + parser.add_option( + "--elp", dest="elp_fname", help="Headshape points file name", metavar="filename" + ) + parser.add_option( + "--hsp", dest="hsp_fname", help="Headshape file name", metavar="filename" + ) + parser.add_option( + "--stim", + dest="stim", + help="Colon Separated Stimulus Trigger Channels", + metavar="chs", + ) + parser.add_option("--slope", dest="slope", help="Slope direction", metavar="slope") + parser.add_option( + "--stimthresh", + dest="stimthresh", + default=1, + help="Threshold value for trigger channels", + metavar="value", + ) + parser.add_option( + "--output", + dest="out_fname", + help="Name of the resulting fiff file", + metavar="filename", + ) + parser.add_option( + "--debug", + dest="debug", + action="store_true", + default=False, + help="Set logging level for terminal output to debug", + ) + + options, args = parser.parse_args() + + if options.debug: + mne.set_log_level("debug") + + input_fname = options.input_fname + if input_fname is None: + try: + from mne_kit_gui import kit2fiff # noqa + except ImportError: + raise ImportError( + "The mne-kit-gui package is required, install it using conda or pip" + ) from None + kit2fiff() + sys.exit(0) + + hsp_fname = options.hsp_fname + elp_fname = options.elp_fname + mrk_fname = options.mrk_fname + stim = options.stim + slope = options.slope + stimthresh = options.stimthresh + out_fname = options.out_fname + + if isinstance(stim, str): + stim = map(int, stim.split(":")) + + raw = read_raw_kit( + input_fname=input_fname, + mrk=mrk_fname, + elp=elp_fname, + hsp=hsp_fname, + stim=stim, + slope=slope, + stimthresh=stimthresh, + ) + + raw.save(out_fname) + raw.close() + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_make_scalp_surfaces.py b/mne-python/source/mne/commands/mne_make_scalp_surfaces.py new file mode 100644 index 0000000000000000000000000000000000000000..5d37b7addc6407776c19d9455dc19f99395dd6aa --- /dev/null +++ b/mne-python/source/mne/commands/mne_make_scalp_surfaces.py @@ -0,0 +1,104 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Create high-resolution head surfaces for coordinate alignment. + +Examples +-------- +.. code-block:: console + + $ mne make_scalp_surfaces --overwrite --subject sample + +""" + +import os +import sys + +import mne +from mne.bem import make_scalp_surfaces + + +def run(): + """Run command.""" + from mne.commands.utils import _add_verbose_flag, get_optparser + + parser = get_optparser(__file__) + subjects_dir = mne.get_config("SUBJECTS_DIR") + + parser.add_option( + "-o", + "--overwrite", + dest="overwrite", + action="store_true", + help="Overwrite previously computed surface", + ) + parser.add_option( + "-s", "--subject", dest="subject", help="The name of the subject", type="str" + ) + parser.add_option( + "-m", + "--mri", + dest="mri", + type="str", + default="T1.mgz", + help="The MRI file to process using mkheadsurf.", + ) + parser.add_option( + "-f", + "--force", + dest="force", + action="store_true", + help="Force creation of the surface even if it has some topological defects.", + ) + parser.add_option( + "-t", + "--threshold", + dest="threshold", + type="int", + default=20, + help="Threshold value to use with the MRI.", + ) + parser.add_option( + "-d", + "--subjects-dir", + dest="subjects_dir", + help="Subjects directory", + default=subjects_dir, + ) + parser.add_option( + "-n", + "--no-decimate", + dest="no_decimate", + help="Disable medium and sparse decimations (dense only)", + action="store_true", + ) + parser.add_option( + "-r", + "--reuse-seghead", + dest="reuse_seghead", + action="store_true", + help="Whether to reuse existing head segmentation files.", + ) + _add_verbose_flag(parser) + options, args = parser.parse_args() + + subject = vars(options).get("subject", os.getenv("SUBJECT")) + subjects_dir = options.subjects_dir + if subject is None or subjects_dir is None: + parser.print_help() + sys.exit(1) + make_scalp_surfaces( + subject=subject, + subjects_dir=subjects_dir, + force=options.force, + overwrite=options.overwrite, + no_decimate=options.no_decimate, + threshold=options.threshold, + mri=options.mri, + reuse_seghead=options.reuse_seghead, + verbose=options.verbose, + ) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_prepare_bem_model.py b/mne-python/source/mne/commands/mne_prepare_bem_model.py new file mode 100644 index 0000000000000000000000000000000000000000..3a830e5ec272b3e390c7819ec4bccef54eb65f69 --- /dev/null +++ b/mne-python/source/mne/commands/mne_prepare_bem_model.py @@ -0,0 +1,66 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Create a BEM solution using the linear collocation approach. + +Examples +-------- +.. code-block:: console + + $ mne prepare_bem_model --bem sample-5120-5120-5120-bem.fif + +""" + +import os +import sys + +import mne + + +def run(): + """Run command.""" + from mne.commands.utils import _add_verbose_flag, get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "--bem", + dest="bem_fname", + help="The name of the file containing the " + "triangulations of the BEM surfaces and the " + "conductivities of the compartments. The standard " + "ending for this file is -bem.fif.", + metavar="FILE", + ) + parser.add_option( + "--sol", + dest="bem_sol_fname", + help="The name of the resulting file containing BEM " + "solution (geometry matrix). It uses the linear " + "collocation approach. The file should end with " + "-bem-sof.fif.", + metavar="FILE", + default=None, + ) + _add_verbose_flag(parser) + + options, args = parser.parse_args() + bem_fname = options.bem_fname + bem_sol_fname = options.bem_sol_fname + verbose = True if options.verbose is not None else False + + if bem_fname is None: + parser.print_help() + sys.exit(1) + + if bem_sol_fname is None: + base, _ = os.path.splitext(bem_fname) + bem_sol_fname = base + "-sol.fif" + + bem_model = mne.read_bem_surfaces(bem_fname, patch_stats=False, verbose=verbose) + bem_solution = mne.make_bem_solution(bem_model, verbose=verbose) + mne.write_bem_solution(bem_sol_fname, bem_solution) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_report.py b/mne-python/source/mne/commands/mne_report.py new file mode 100644 index 0000000000000000000000000000000000000000..eec37c445c744f65063ac38a1e0b79791a89da4b --- /dev/null +++ b/mne-python/source/mne/commands/mne_report.py @@ -0,0 +1,200 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +r"""Create mne report for a folder. + +Examples +-------- +Before getting started with ``mne report``, make sure the files you want to +render follow the filename conventions defined by MNE: + +.. highlight:: console + +.. cssclass:: table-bordered +.. rst-class:: midvalign + +============ ============================================================== +Data object Filename convention (ends with) +============ ============================================================== +raw -raw.fif(.gz), -raw_sss.fif(.gz), -raw_tsss.fif(.gz), + _meg.fif(.gz), _eeg.fif(.gz), _ieeg.fif(.gz) +events -eve.fif(.gz) +epochs -epo.fif(.gz) +evoked -ave.fif(.gz) +covariance -cov.fif(.gz) +trans -trans.fif(.gz) +forward -fwd.fif(.gz) +inverse -inv.fif(.gz) +============ ============================================================== + +To generate a barebones report from all the \*.fif files in the sample +dataset, invoke the following command in a system (e.g., Bash) shell:: + + $ mne report --path MNE-sample-data/ --verbose + +On successful creation of the report, it will open the HTML in a new tab in +the browser. To disable this, use the ``--no-browser`` option. + +TO generate a report for a single subject, give the ``SUBJECT`` name and +the ``SUBJECTS_DIR`` and this will generate the MRI slices (with BEM +contours overlaid on top if available):: + + $ mne report --path MNE-sample-data/ --subject sample --subjects-dir \ + MNE-sample-data/subjects --verbose + +To properly render ``trans`` and ``covariance`` files, add the measurement +information:: + + $ mne report --path MNE-sample-data/ \ + --info MNE-sample-data/MEG/sample/sample_audvis-ave.fif \ + --subject sample --subjects-dir MNE-sample-data/subjects --verbose + +To render whitened ``evoked`` files with baseline correction, add the noise +covariance file:: + + $ mne report --path MNE-sample-data/ \ + --info MNE-sample-data/MEG/sample/sample_audvis-ave.fif \ + --cov MNE-sample-data/MEG/sample/sample_audvis-cov.fif --bmax 0 \ + --subject sample --subjects-dir MNE-sample-data/subjects --verbose + +To generate the report in parallel:: + + $ mne report --path MNE-sample-data/ \ + --info MNE-sample-data/MEG/sample/sample_audvis-ave.fif \ + --subject sample --subjects-dir MNE-sample-data/subjects \ + --verbose --jobs 6 + +For help on all the available options, do:: + + $ mne report --help +""" + +import sys +import time + +import mne +from mne.report import Report +from mne.utils import logger, verbose + + +@verbose +def log_elapsed(t, verbose=None): + """Log elapsed time.""" + logger.info(f"Report complete in {round(t, 1)} seconds") + + +def run(): + """Run command.""" + from mne.commands.utils import _add_verbose_flag, get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-p", + "--path", + dest="path", + help="Path to folder who MNE-Report must be created", + ) + parser.add_option( + "-i", + "--info", + dest="info_fname", + help="File from which info dictionary is to be read", + metavar="FILE", + ) + parser.add_option( + "-c", + "--cov", + dest="cov_fname", + help="File from which noise covariance is to be read", + metavar="FILE", + ) + parser.add_option( + "--bmin", + dest="bmin", + help="Time at which baseline correction starts for evokeds", + default=None, + ) + parser.add_option( + "--bmax", + dest="bmax", + help="Time at which baseline correction stops for evokeds", + default=None, + ) + parser.add_option( + "-d", "--subjects-dir", dest="subjects_dir", help="The subjects directory" + ) + parser.add_option("-s", "--subject", dest="subject", help="The subject name") + parser.add_option( + "--no-browser", + dest="no_browser", + action="store_false", + help="Do not open MNE-Report in browser", + ) + parser.add_option( + "--overwrite", + dest="overwrite", + action="store_false", + help="Overwrite html report if it already exists", + ) + parser.add_option( + "-j", "--jobs", dest="n_jobs", help="Number of jobs to run in parallel" + ) + parser.add_option( + "-m", + "--mri-decim", + type="int", + dest="mri_decim", + default=2, + help="Integer factor used to decimate BEM plots", + ) + parser.add_option( + "--image-format", + type="str", + dest="image_format", + default="png", + help="Image format to use (can be 'png' or 'svg')", + ) + _add_verbose_flag(parser) + + options, args = parser.parse_args() + path = options.path + if path is None: + parser.print_help() + sys.exit(1) + info_fname = options.info_fname + cov_fname = options.cov_fname + subjects_dir = options.subjects_dir + subject = options.subject + image_format = options.image_format + mri_decim = int(options.mri_decim) + verbose = True if options.verbose is not None else False + open_browser = False if options.no_browser is not None else True + overwrite = True if options.overwrite is not None else False + n_jobs = int(options.n_jobs) if options.n_jobs is not None else 1 + + bmin = float(options.bmin) if options.bmin is not None else None + bmax = float(options.bmax) if options.bmax is not None else None + # XXX: this means (None, None) cannot be specified through command line + if bmin is None and bmax is None: + baseline = None + else: + baseline = (bmin, bmax) + + t0 = time.time() + report = Report( + info_fname, + subjects_dir=subjects_dir, + subject=subject, + baseline=baseline, + cov_fname=cov_fname, + verbose=verbose, + image_format=image_format, + ) + report.parse_folder(path, verbose=verbose, n_jobs=n_jobs, mri_decim=mri_decim) + log_elapsed(time.time() - t0, verbose=verbose) + report.save(open_browser=open_browser, overwrite=overwrite) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_setup_forward_model.py b/mne-python/source/mne/commands/mne_setup_forward_model.py new file mode 100644 index 0000000000000000000000000000000000000000..29e8616f5714ad68e11d9e4246d8c83321169902 --- /dev/null +++ b/mne-python/source/mne/commands/mne_setup_forward_model.py @@ -0,0 +1,150 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Create a BEM model for a subject. + +Examples +-------- +.. code-block:: console + + $ mne setup_forward_model -s 'sample' + +""" + +import os +import sys + +import mne +from mne.utils import get_subjects_dir, warn + + +def run(): + """Run command.""" + from mne.commands.utils import _add_verbose_flag, get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-s", "--subject", dest="subject", help="Subject name (required)", default=None + ) + parser.add_option( + "--model", + dest="model", + help="Output file name. Use a name /-bem.fif", + default=None, + type="string", + ) + parser.add_option( + "--ico", + dest="ico", + help="The surface ico downsampling to use, e.g. " + " 5=20484, 4=5120, 3=1280. If None, no subsampling" + " is applied.", + default=None, + type="int", + ) + parser.add_option( + "--brainc", + dest="brainc", + help="Defines the brain compartment conductivity. " + "The default value is 0.3 S/m.", + default=0.3, + type="float", + ) + parser.add_option( + "--skullc", + dest="skullc", + help="Defines the skull compartment conductivity. " + "The default value is 0.006 S/m.", + default=None, + type="float", + ) + parser.add_option( + "--scalpc", + dest="scalpc", + help="Defines the scalp compartment conductivity. " + "The default value is 0.3 S/m.", + default=None, + type="float", + ) + parser.add_option( + "--homog", + dest="homog", + help="Use a single compartment model (brain only) " + "instead a three layer one (scalp, skull, and " + " brain). If this flag is specified, the options " + "--skullc and --scalpc are irrelevant.", + default=None, + action="store_true", + ) + parser.add_option( + "-d", + "--subjects-dir", + dest="subjects_dir", + help="Subjects directory", + default=None, + ) + _add_verbose_flag(parser) + options, args = parser.parse_args() + + if options.subject is None: + parser.print_help() + sys.exit(1) + + subject = options.subject + fname = options.model + subjects_dir = options.subjects_dir + ico = options.ico + brainc = options.brainc + skullc = options.skullc + scalpc = options.scalpc + homog = True if options.homog is not None else False + verbose = True if options.verbose is not None else False + # Parse conductivity option + if homog is True: + if skullc is not None: + warn( + "Trying to set the skull conductivity for a single layer " + "model. To use a 3 layer model, do not set the --homog flag." + ) + if scalpc is not None: + warn( + "Trying to set the scalp conductivity for a single layer " + "model. To use a 3 layer model, do not set the --homog flag." + ) + # Single layer + conductivity = [brainc] + else: + if skullc is None: + skullc = 0.006 + if scalpc is None: + scalpc = 0.3 + conductivity = [brainc, skullc, scalpc] + # Create source space + bem_model = mne.make_bem_model( + subject, + ico=ico, + conductivity=conductivity, + subjects_dir=subjects_dir, + verbose=verbose, + ) + # Generate filename + if fname is None: + n_faces = list(str(len(surface["tris"])) for surface in bem_model) + fname = subject + "-" + "-".join(n_faces) + "-bem.fif" + else: + if not (fname.endswith("-bem.fif") or fname.endswith("_bem.fif")): + fname = fname + "-bem.fif" + # Save to subject's directory + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + fname = subjects_dir / subject / "bem" / fname + # Save source space to file + mne.write_bem_surfaces(fname, bem_model) + # Compute the solution + sol_fname = os.path.splitext(str(fname))[0] + "-sol.fif" + bem_sol = mne.make_bem_solution(bem_model, verbose=verbose) + mne.write_bem_solution(sol_fname, bem_sol) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_setup_source_space.py b/mne-python/source/mne/commands/mne_setup_source_space.py new file mode 100644 index 0000000000000000000000000000000000000000..273e833b31c765f13ca65a8a94059d68f65c910c --- /dev/null +++ b/mne-python/source/mne/commands/mne_setup_source_space.py @@ -0,0 +1,182 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Set up bilateral hemisphere surface-based source space with subsampling. + +Examples +-------- +.. code-block:: console + + $ mne setup_source_space --subject sample + + + .. note : Only one of --ico, --oct or --spacing options can be set at the same + time. Default to oct6. + +""" + +import sys + +import mne +from mne.utils import _check_option + + +def run(): + """Run command.""" + from mne.commands.utils import _add_verbose_flag, get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-s", "--subject", dest="subject", help="Subject name (required)", default=None + ) + parser.add_option( + "--src", + dest="fname", + help="Output file name. Use a name /-src.fif", + metavar="FILE", + default=None, + ) + parser.add_option( + "--morph", + dest="subject_to", + help="morph the source space to this subject", + default=None, + ) + parser.add_option( + "--surf", + dest="surface", + help="The surface to use. (default to white)", + default="white", + type="string", + ) + parser.add_option( + "--spacing", + dest="spacing", + help="Specifies the approximate grid spacing of the " + "source space in mm. (default to 7mm)", + default=None, + type="int", + ) + parser.add_option( + "--ico", + dest="ico", + help="use the recursively subdivided icosahedron to create the source space.", + default=None, + type="int", + ) + parser.add_option( + "--oct", + dest="oct", + help="use the recursively subdivided octahedron to create the source space.", + default=None, + type="int", + ) + parser.add_option( + "-d", + "--subjects-dir", + dest="subjects_dir", + help="Subjects directory", + default=None, + ) + parser.add_option( + "-n", + "--n-jobs", + dest="n_jobs", + help="The number of jobs to run in parallel " + "(default 1). Requires the joblib package. " + "Will use at most 2 jobs" + " (one for each hemisphere).", + default=1, + type="int", + ) + parser.add_option( + "--add-dist", + dest="add_dist", + help='Add distances. Can be "True", "False", or "patch" ' + "to only compute cortical patch statistics (like the --cps option in MNE-C)", + default="True", + ) + parser.add_option( + "-o", + "--overwrite", + dest="overwrite", + help="to write over existing files", + default=None, + action="store_true", + ) + _add_verbose_flag(parser) + + options, args = parser.parse_args() + + if options.subject is None: + parser.print_help() + sys.exit(1) + + subject = options.subject + subject_to = options.subject_to + fname = options.fname + subjects_dir = options.subjects_dir + spacing = options.spacing + ico = options.ico + oct_ = options.oct + surface = options.surface + n_jobs = options.n_jobs + add_dist = options.add_dist + _check_option("add_dist", add_dist, ("True", "False", "patch")) + add_dist = {"True": True, "False": False, "patch": "patch"}[add_dist] + verbose = True if options.verbose is not None else False + overwrite = True if options.overwrite is not None else False + + # Parse source spacing option + spacing_options = [ico, oct_, spacing] + n_options = len([x for x in spacing_options if x is not None]) + use_spacing = "oct6" + if n_options > 1: + raise ValueError("Only one spacing option can be set at the same time") + elif n_options == 0: + # Default to oct6 + pass + elif n_options == 1: + if ico is not None: + use_spacing = "ico" + str(ico) + elif oct_ is not None: + use_spacing = "oct" + str(oct_) + elif spacing is not None: + use_spacing = spacing + del ico, oct_, spacing + # Generate filename + if fname is None: + if subject_to is None: + fname = subject + "-" + str(use_spacing) + "-src.fif" + else: + fname = subject_to + "-" + subject + "-" + str(use_spacing) + "-src.fif" + else: + if not (fname.endswith("_src.fif") or fname.endswith("-src.fif")): + fname = fname + "-src.fif" + # Create source space + src = mne.setup_source_space( + subject=subject, + spacing=use_spacing, + surface=surface, + subjects_dir=subjects_dir, + n_jobs=n_jobs, + add_dist=add_dist, + verbose=verbose, + ) + # Morph source space if --morph is set + if subject_to is not None: + src = mne.morph_source_spaces( + src, + subject_to=subject_to, + subjects_dir=subjects_dir, + surf=surface, + verbose=verbose, + ) + + # Save source space to file + src.save(fname=fname, overwrite=overwrite) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_show_fiff.py b/mne-python/source/mne/commands/mne_show_fiff.py new file mode 100644 index 0000000000000000000000000000000000000000..2f9e73d2dc1bd2a378cd0c56b7b81926b01bf6bd --- /dev/null +++ b/mne-python/source/mne/commands/mne_show_fiff.py @@ -0,0 +1,54 @@ +"""Show the contents of a FIFF file. + +Examples +-------- +.. code-block:: console + + $ mne show_fiff test_raw.fif + + +To see only tag 102: + +.. code-block:: console + + $ mne show_fiff test_raw.fif --tag=102 + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import sys + +import mne + + +def run(): + """Run command.""" + parser = mne.commands.utils.get_optparser(__file__, usage="mne show_fiff ") + parser.add_option( + "-t", + "--tag", + dest="tag", + help="provide information about this tag", + metavar="TAG", + ) + parser.add_option( + "-b", + "--bytes", + dest="show_bytes", + help="show the byte offset of each tag", + action="store_true", + ) + options, args = parser.parse_args() + if len(args) != 1: + parser.print_help() + sys.exit(1) + msg = mne.io.show_fiff( + args[0], tag=options.tag, show_bytes=options.show_bytes + ).strip() + print(msg) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_show_info.py b/mne-python/source/mne/commands/mne_show_info.py new file mode 100644 index 0000000000000000000000000000000000000000..b9448011206f4d38e5d4b6777946986d1b276b29 --- /dev/null +++ b/mne-python/source/mne/commands/mne_show_info.py @@ -0,0 +1,38 @@ +"""Show measurement info from .fif file. + +Examples +-------- +.. code-block:: console + + $ mne show_info sample_audvis_raw.fif + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import sys + +import mne + + +def run(): + """Run command.""" + parser = mne.commands.utils.get_optparser(__file__, usage="mne show_info ") + options, args = parser.parse_args() + if len(args) != 1: + parser.print_help() + sys.exit(1) + + fname = args[0] + + if not fname.endswith(".fif"): + raise ValueError(f"{fname} does not seem to be a .fif file.") + + info = mne.io.read_info(fname) + print(f"File : {fname}") + print(info) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_surf2bem.py b/mne-python/source/mne/commands/mne_surf2bem.py new file mode 100644 index 0000000000000000000000000000000000000000..5d6426986e8030f6da7b39d69791b2ae1e93f2bc --- /dev/null +++ b/mne-python/source/mne/commands/mne_surf2bem.py @@ -0,0 +1,53 @@ +r"""Convert surface to BEM FIF file. + +Examples +-------- +.. code-block:: console + + $ mne surf2bem --surf ${SUBJECTS_DIR}/${SUBJECT}/surf/lh.seghead \ + --fif ${SUBJECTS_DIR}/${SUBJECT}/bem/${SUBJECT}-head.fif \ + --id=4 + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import sys + +import mne + + +def run(): + """Run command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-s", "--surf", dest="surf", help="Surface in Freesurfer format", metavar="FILE" + ) + parser.add_option( + "-f", "--fif", dest="fif", help="FIF file produced", metavar="FILE" + ) + parser.add_option( + "-i", + "--id", + dest="id", + default=4, + help=("Surface Id (e.g. 4 for head surface)"), + ) + + options, args = parser.parse_args() + + if options.surf is None: + parser.print_help() + sys.exit(1) + + print(f"Converting {options.surf} to BEM FIF file.") + surf = mne.bem._surfaces_to_bem([options.surf], [int(options.id)], sigmas=[1]) + mne.write_bem_surfaces(options.fif, surf) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_sys_info.py b/mne-python/source/mne/commands/mne_sys_info.py new file mode 100644 index 0000000000000000000000000000000000000000..70c56e42f3e822d54ff7b98cbdd92f92d15cfdff --- /dev/null +++ b/mne-python/source/mne/commands/mne_sys_info.py @@ -0,0 +1,66 @@ +"""Show system information. + +Examples +-------- +.. code-block:: console + + $ mne sys_info + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import sys + +import mne + + +def run(): + """Run command.""" + parser = mne.commands.utils.get_optparser(__file__, usage="mne sys_info") + parser.add_option( + "-p", + "--show-paths", + dest="show_paths", + help="Show module paths", + action="store_true", + ) + parser.add_option( + "-d", + "--developer", + dest="developer", + help="Show additional developer module information", + action="store_true", + ) + parser.add_option( + "-a", + "--ascii", + dest="unicode", + help="Use ASCII instead of unicode symbols", + action="store_false", + default=True, + ) + parser.add_option( + "--no-check-version", + dest="check_version", + help="Disable MNE-Python remote version checking.", + action="store_false", + default=True, + ) + options, args = parser.parse_args() + dependencies = "developer" if options.developer else "user" + if len(args) != 0: + parser.print_help() + sys.exit(1) + + mne.sys_info( + show_paths=options.show_paths, + dependencies=dependencies, + unicode=options.unicode, + check_version=options.check_version, + ) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_watershed_bem.py b/mne-python/source/mne/commands/mne_watershed_bem.py new file mode 100644 index 0000000000000000000000000000000000000000..4f872b90dacd52e277586d1e36ef8c2483df19fc --- /dev/null +++ b/mne-python/source/mne/commands/mne_watershed_bem.py @@ -0,0 +1,134 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Create BEM surfaces using the watershed algorithm included with FreeSurfer. + +Examples +-------- +.. code-block:: console + + $ mne watershed_bem -s sample + +""" + +import sys + +import mne +from mne.bem import make_watershed_bem +from mne.utils import _check_option + + +def run(): + """Run command.""" + from mne.commands.utils import _add_verbose_flag, get_optparser + + parser = get_optparser(__file__) + + parser.add_option( + "-s", "--subject", dest="subject", help="Subject name (required)", default=None + ) + parser.add_option( + "-d", + "--subjects-dir", + dest="subjects_dir", + help="Subjects directory", + default=None, + ) + parser.add_option( + "-o", + "--overwrite", + dest="overwrite", + help="Write over existing files", + action="store_true", + ) + parser.add_option( + "-v", "--volume", dest="volume", help="Defaults to T1", default="T1" + ) + parser.add_option( + "-a", + "--atlas", + dest="atlas", + help="Specify the --atlas option for mri_watershed", + default=False, + action="store_true", + ) + parser.add_option( + "-g", + "--gcaatlas", + dest="gcaatlas", + help="Specify the --brain_atlas option for mri_watershed", + default=False, + action="store_true", + ) + parser.add_option( + "-p", + "--preflood", + dest="preflood", + help="Change the preflood height", + default=None, + ) + parser.add_option( + "--copy", + dest="copy", + help="Use copies instead of symlinks for surfaces", + action="store_true", + ) + parser.add_option( + "-t", + "--T1", + dest="T1", + help="Whether or not to pass the -T1 flag " + "(can be true, false, 0, or 1). " + "By default it takes the same value as gcaatlas.", + default=None, + ) + parser.add_option( + "-b", + "--brainmask", + dest="brainmask", + help="The filename for the brainmask output file " + "relative to the " + "$SUBJECTS_DIR/$SUBJECT/bem/watershed/ directory.", + default="ws", + ) + _add_verbose_flag(parser) + + options, args = parser.parse_args() + + if options.subject is None: + parser.print_help() + sys.exit(1) + + subject = options.subject + subjects_dir = options.subjects_dir + overwrite = options.overwrite + volume = options.volume + atlas = options.atlas + gcaatlas = options.gcaatlas + preflood = options.preflood + copy = options.copy + brainmask = options.brainmask + T1 = options.T1 + if T1 is not None: + T1 = T1.lower() + _check_option("--T1", T1, ("true", "false", "0", "1")) + T1 = T1 in ("true", "1") + verbose = options.verbose + + make_watershed_bem( + subject=subject, + subjects_dir=subjects_dir, + overwrite=overwrite, + volume=volume, + atlas=atlas, + gcaatlas=gcaatlas, + preflood=preflood, + copy=copy, + T1=T1, + brainmask=brainmask, + verbose=verbose, + ) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/mne_what.py b/mne-python/source/mne/commands/mne_what.py new file mode 100644 index 0000000000000000000000000000000000000000..f6ee1683ba96630619ba85ebfa9d5dc86d322c33 --- /dev/null +++ b/mne-python/source/mne/commands/mne_what.py @@ -0,0 +1,28 @@ +r"""Check type of FIF file. + +Examples +-------- +.. code-block:: console + + $ mne what sample_audvis_raw.fif + raw +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import mne + + +def run(): + """Run command.""" + from mne.commands.utils import get_optparser + + parser = get_optparser(__file__, usage="usage: %prog fname [fname2 ...]") + options, args = parser.parse_args() + for arg in args: + print(mne.what(arg)) + + +mne.utils.run_command_if_main() diff --git a/mne-python/source/mne/commands/tests/__init__.py b/mne-python/source/mne/commands/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/commands/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/commands/tests/test_commands.py b/mne-python/source/mne/commands/tests/test_commands.py new file mode 100644 index 0000000000000000000000000000000000000000..a5d1ef32d7dfaf23f385f89efb9473bc7ab73fea --- /dev/null +++ b/mne-python/source/mne/commands/tests/test_commands.py @@ -0,0 +1,619 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import glob +import os +import platform +import shutil +from os import path as op +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_equal + +import mne +from mne import ( + concatenate_raws, + read_bem_solution, + read_bem_surfaces, + read_source_spaces, + read_surface, +) +from mne.bem import ConductorModel, convert_flash_mris +from mne.commands import ( + mne_anonymize, + mne_browse_raw, + mne_bti2fiff, + mne_clean_eog_ecg, + mne_compare_fiff, + mne_compute_proj_ecg, + mne_compute_proj_eog, + mne_coreg, + mne_flash_bem, + mne_kit2fiff, + mne_make_scalp_surfaces, + mne_prepare_bem_model, + mne_report, + mne_setup_forward_model, + mne_setup_source_space, + mne_show_fiff, + mne_show_info, + mne_surf2bem, + mne_sys_info, + mne_watershed_bem, + mne_what, +) +from mne.datasets import testing +from mne.io import read_info, read_raw_fif, show_fiff +from mne.utils import ( + ArgvSetter, + _record_warnings, + _stamp_to_dt, + requires_freesurfer, + requires_mne, +) + +base_dir = op.join(op.dirname(__file__), "..", "..", "io", "tests", "data") +raw_fname = op.join(base_dir, "test_raw.fif") + +testing_path = testing.data_path(download=False) +subjects_dir = op.join(testing_path, "subjects") +bem_model_fname = op.join( + testing_path, "subjects", "sample", "bem", "sample-320-320-320-bem.fif" +) + + +def check_usage(module, force_help=False): + """Ensure we print usage.""" + args = ("--help",) if force_help else () + with ArgvSetter(args) as out: + try: + module.run() + except SystemExit: + pass + assert "Usage: " in out.stdout.getvalue() + + +@pytest.mark.slowtest +def test_browse_raw(): + """Test mne browse_raw.""" + check_usage(mne_browse_raw) + with ArgvSetter(("--raw", raw_fname)): + with _record_warnings(): # mpl show warning + mne_browse_raw.run() + + +def test_what(): + """Test mne browse_raw.""" + check_usage(mne_browse_raw) + with ArgvSetter((raw_fname,)) as out: + mne_what.run() + assert "raw" == out.stdout.getvalue().strip() + + +def test_bti2fiff(): + """Test mne bti2fiff.""" + check_usage(mne_bti2fiff) + + +def test_compare_fiff(): + """Test mne compare_fiff.""" + check_usage(mne_compare_fiff) + + +# should match ".*valid tag.*" but conda-linux intermittently fails for some reason +@pytest.mark.filterwarnings("ignore:Invalid tag.*:RuntimeWarning") +def test_show_fiff(tmp_path): + """Test mne compare_fiff.""" + if os.getenv("MNE_CI_KIND", "") == "conda" and platform.system() == "Linux": + pytest.skip("Skipping test on conda-linux due to intermittent failures") + check_usage(mne_show_fiff) + with ArgvSetter((raw_fname,)): + mne_show_fiff.run() + with ArgvSetter((raw_fname, "--tag=102")): + mne_show_fiff.run() + bad_fname = tmp_path / "test_bad_raw.fif" + with open(bad_fname, "wb") as fout, open(raw_fname, "rb") as fin: + fout.write(fin.read(100000)) + lines = show_fiff(bad_fname, output=list) + last_line = lines[-1] + assert last_line.endswith(">>>>BAD @9015") + assert "302 = FIFF_EPOCH (734412b >f4)" in last_line + + +@requires_mne +def test_clean_eog_ecg(tmp_path): + """Test mne clean_eog_ecg.""" + check_usage(mne_clean_eog_ecg) + tempdir = str(tmp_path) + raw = concatenate_raws([read_raw_fif(f) for f in [raw_fname, raw_fname, raw_fname]]) + raw.info["bads"] = ["MEG 2443"] + use_fname = op.join(tempdir, op.basename(raw_fname)) + raw.save(use_fname) + with ArgvSetter(("-i", use_fname, "--quiet")): + mne_clean_eog_ecg.run() + for key, count in (("proj", 2), ("-eve", 3)): + fnames = glob.glob(op.join(tempdir, f"*{key}.fif")) + assert len(fnames) == count + + +@pytest.mark.slowtest +@pytest.mark.parametrize("fun", (mne_compute_proj_ecg, mne_compute_proj_eog)) +def test_compute_proj_exg(tmp_path, fun): + """Test mne compute_proj_ecg/eog.""" + check_usage(fun) + tempdir = str(tmp_path) + use_fname = op.join(tempdir, op.basename(raw_fname)) + bad_fname = op.join(tempdir, "bads.txt") + with open(bad_fname, "w") as fid: + fid.write("MEG 2443\n") + shutil.copyfile(raw_fname, use_fname) + with ArgvSetter(("-i", use_fname, "--bad=" + bad_fname, "--rej-eeg", "150")): + with _record_warnings(): # samples, sometimes + fun.run() + fnames = glob.glob(op.join(tempdir, "*proj.fif")) + assert len(fnames) == 1 + fnames = glob.glob(op.join(tempdir, "*-eve.fif")) + assert len(fnames) == 1 + + +def test_coreg(): + """Test mne coreg.""" + assert hasattr(mne_coreg, "run") + + +def test_kit2fiff(): + """Test mne kit2fiff.""" + # Can't check + check_usage(mne_kit2fiff, force_help=True) + + +@pytest.mark.ultraslowtest +@testing.requires_testing_data +@requires_freesurfer("mkheadsurf") +def test_make_scalp_surfaces(tmp_path, monkeypatch): + """Test mne make_scalp_surfaces.""" + pytest.importorskip("nibabel") + pytest.importorskip("pyvista") + check_usage(mne_make_scalp_surfaces) + has = "SUBJECTS_DIR" in os.environ + freesurfer_home = os.environ.get("FREESURFER_HOME") + + monkeypatch.setattr( + mne.bem, + "decimate_surface", + lambda points, triangles, n_triangles: (points, triangles), + ) + + tempdir = str(tmp_path) + t1_path = op.join(subjects_dir, "sample", "mri", "T1.mgz") + t1_path_new = op.join(tempdir, "sample", "mri", "T1.mgz") + + headseg_path = op.join(subjects_dir, "sample", "mri", "seghead.mgz") + headseg_path_new = op.join(tempdir, "sample", "mri", "seghead.mgz") + + surf_path = op.join(subjects_dir, "sample", "surf", "lh.seghead") + surf_path_new = op.join(tempdir, "sample", "surf", "lh.seghead") + + dense_fname = op.join(tempdir, "sample", "bem", "sample-head-dense.fif") + medium_fname = op.join(tempdir, "sample", "bem", "sample-head-medium.fif") + sparse_fname = op.join(tempdir, "sample", "bem", "sample-head-sparse.fif") + + os.makedirs(op.join(tempdir, "sample", "mri"), exist_ok=True) + os.makedirs(op.join(tempdir, "sample", "surf"), exist_ok=True) + + shutil.copy(t1_path, t1_path_new) + shutil.copy(headseg_path, headseg_path_new) + shutil.copy(surf_path, surf_path_new) + + cmd = ( + "-s", + "sample", + "--subjects-dir", + tempdir, + "--no-decimate", + "--reuse-seghead", + ) + with ArgvSetter(cmd, disable_stdout=False, disable_stderr=False): + monkeypatch.delenv("FREESURFER_HOME", raising=False) + with pytest.raises(RuntimeError, match="The FREESURFER_HOME environment"): + mne_make_scalp_surfaces.run() + + monkeypatch.setenv("FREESURFER_HOME", freesurfer_home) + mne_make_scalp_surfaces.run() + + assert op.isfile(headseg_path_new) + assert op.isfile(surf_path_new) + assert op.isfile(dense_fname) + assert not op.isfile(medium_fname) + assert not op.isfile(sparse_fname) + + # actually check the outputs + head_py = read_bem_surfaces(dense_fname) + assert_equal(len(head_py), 1) + head_py = head_py[0] + head_c = read_bem_surfaces( + op.join(subjects_dir, "sample", "bem", "sample-head-dense.fif") + )[0] + assert_allclose(head_py["rr"], head_c["rr"]) + + cmd = ("-s", "sample", "--subjects-dir", tempdir) + with ArgvSetter(cmd, disable_stdout=False, disable_stderr=False): + with pytest.raises(OSError, match="use --overwrite to overwrite it"): + mne_make_scalp_surfaces.run() + + cmd = ("-s", "sample", "--subjects-dir", tempdir, "--overwrite") + with ArgvSetter(cmd, disable_stdout=False, disable_stderr=False): + mne_make_scalp_surfaces.run() + assert op.isfile(headseg_path_new) + assert op.isfile(surf_path_new) + assert op.isfile(dense_fname) + assert op.isfile(medium_fname) + assert op.isfile(sparse_fname) + + os.remove(headseg_path_new) + os.remove(surf_path_new) + os.remove(dense_fname) + cmd = ("-s", "sample", "--subjects-dir", tempdir, "--no-decimate") + with ArgvSetter(cmd, disable_stdout=False, disable_stderr=False): + with pytest.raises(OSError, match="Trying to generate new scalp surfaces"): + mne_make_scalp_surfaces.run() + + os.remove(medium_fname) + os.remove(sparse_fname) + cmd = ( + "-s", + "sample", + "--subjects-dir", + tempdir, + "--no-decimate", + "--reuse-seghead", + ) + with ArgvSetter(cmd, disable_stdout=False, disable_stderr=False): + with pytest.raises(ValueError, match="No existing scalp surface found"): + mne_make_scalp_surfaces.run() + + cmd = ("-s", "sample", "--subjects-dir", tempdir, "--no-decimate", "--overwrite") + with ArgvSetter(cmd, disable_stdout=False, disable_stderr=False): + mne_make_scalp_surfaces.run() + assert op.isfile(headseg_path_new) + assert op.isfile(surf_path_new) + assert op.isfile(dense_fname) + assert not op.isfile(medium_fname) + assert not op.isfile(sparse_fname) + + cmd = ("-s", "sample", "--subjects-dir", tempdir, "--no-decimate", "--overwrite") + with ArgvSetter(cmd, disable_stdout=False, disable_stderr=False): + mne_make_scalp_surfaces.run() + assert op.isfile(headseg_path_new) + assert op.isfile(surf_path_new) + assert op.isfile(dense_fname) + assert not op.isfile(medium_fname) + assert not op.isfile(sparse_fname) + + if not has: + assert "SUBJECTS_DIR" not in os.environ + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_report(tmp_path): + """Test mne report.""" + pytest.importorskip("nibabel") + check_usage(mne_report) + tempdir = str(tmp_path) + use_fname = op.join(tempdir, op.basename(raw_fname)) + shutil.copyfile(raw_fname, use_fname) + with ArgvSetter( + ( + "-p", + tempdir, + "-i", + use_fname, + "-d", + subjects_dir, + "-s", + "sample", + "--no-browser", + "-m", + "30", + ) + ): + with _record_warnings(): # contour levels + mne_report.run() + fnames = glob.glob(op.join(tempdir, "*.html")) + assert len(fnames) == 1 + + +def test_surf2bem(): + """Test mne surf2bem.""" + check_usage(mne_surf2bem) + + +@pytest.mark.timeout(900) # took ~400 s on a local test +@pytest.mark.slowtest +@pytest.mark.ultraslowtest +@requires_freesurfer("mri_watershed") +@testing.requires_testing_data +def test_watershed_bem(tmp_path): + """Test mne watershed bem.""" + pytest.importorskip("nibabel") + check_usage(mne_watershed_bem) + # from T1.mgz + Mdc = np.array([[-1, 0, 0], [0, 0, -1], [0, 1, 0]]) + Pxyz_c = np.array([-5.273613, 9.039085, -27.287964]) + # Copy necessary files to tempdir + tempdir = str(tmp_path) + mridata_path = op.join(subjects_dir, "sample", "mri") + subject_path_new = op.join(tempdir, "sample") + mridata_path_new = op.join(subject_path_new, "mri") + os.makedirs(mridata_path_new) + new_fname = op.join(mridata_path_new, "T1.mgz") + shutil.copyfile(op.join(mridata_path, "T1.mgz"), new_fname) + old_mode = os.stat(new_fname).st_mode + os.chmod(new_fname, 0) + args = ("-d", tempdir, "-s", "sample", "-o") + with pytest.raises(PermissionError, match=r"read permissions.*T1\.mgz"): + with ArgvSetter(args): + mne_watershed_bem.run() + os.chmod(new_fname, old_mode) + for s in ("outer_skin", "outer_skull", "inner_skull"): + assert not op.isfile(op.join(subject_path_new, "bem", f"{s}.surf")) + with ArgvSetter(args): + mne_watershed_bem.run() + + kwargs = dict(rtol=1e-5, atol=1e-5) + for s in ("outer_skin", "outer_skull", "inner_skull"): + rr, tris, vol_info = read_surface( + op.join(subject_path_new, "bem", f"{s}.surf"), read_metadata=True + ) + assert_equal(len(tris), 20480) + assert_equal(tris.min(), 0) + assert_equal(rr.shape[0], tris.max() + 1) + # compare the volume info to the mgz header + assert_allclose(vol_info["xras"], Mdc[0], **kwargs) + assert_allclose(vol_info["yras"], Mdc[1], **kwargs) + assert_allclose(vol_info["zras"], Mdc[2], **kwargs) + assert_allclose(vol_info["cras"], Pxyz_c, **kwargs) + + +@pytest.mark.timeout(180) # took ~70 s locally +@pytest.mark.slowtest +@pytest.mark.ultraslowtest +@requires_freesurfer +@testing.requires_testing_data +def test_flash_bem(tmp_path): + """Test mne flash_bem.""" + pytest.importorskip("nibabel") + check_usage(mne_flash_bem, force_help=True) + # Copy necessary files to tempdir + tempdir = Path(str(tmp_path)) + mridata_path = Path(subjects_dir) / "sample" / "mri" + subject_path_new = tempdir / "sample" + mridata_path_new = subject_path_new / "mri" + flash_path = mridata_path_new / "flash" + flash_path.mkdir(parents=True, exist_ok=True) + bem_path = mridata_path_new / "bem" + bem_path.mkdir(parents=True, exist_ok=True) + shutil.copyfile( + op.join(mridata_path, "T1.mgz"), op.join(mridata_path_new, "T1.mgz") + ) + shutil.copyfile( + op.join(mridata_path, "brain.mgz"), op.join(mridata_path_new, "brain.mgz") + ) + # Copy the available mri/flash/mef*.mgz files from the dataset + for kind in (5, 30): + in_fname = mridata_path / "flash" / f"mef{kind:02d}.mgz" + in_fname_echo = flash_path / f"mef{kind:02d}_001.mgz" + shutil.copyfile(in_fname, flash_path / in_fname_echo.name) + # Test mne flash_bem with --noconvert option + # (since there are no DICOM Flash images in dataset) + for s in ("outer_skin", "outer_skull", "inner_skull"): + assert not op.isfile(subject_path_new / "bem" / f"{s}.surf") + + # First test without flash30 + with ArgvSetter( + ("-d", tempdir, "-s", "sample", "-r", "-3"), + disable_stdout=False, + disable_stderr=False, + ): + mne_flash_bem.run() + for s in ("outer_skin", "outer_skull", "inner_skull"): + surf_path = subject_path_new / "bem" / f"{s}.surf" + assert surf_path.exists() + surf_path.unlink() # cleanup + shutil.rmtree(flash_path / "parameter_maps") # remove old files + + # Test synthesize flash5 with MEF flash5 and flash30 default locations + flash5_img = convert_flash_mris( + subject="sample", subjects_dir=tempdir, unwarp=False + ) + assert flash5_img == (flash_path / "parameter_maps" / "flash5.mgz") + assert flash5_img.exists() + shutil.rmtree(flash_path / "parameter_maps") # remove old files + + # Test with flash5 and flash30 + shutil.rmtree(flash_path) # first remove old files + with ArgvSetter( + ( + "-d", + tempdir, + "-s", + "sample", + "-3", + str(mridata_path / "flash" / "mef30.mgz"), + "-5", + str(mridata_path / "flash" / "mef05.mgz"), + ), + disable_stdout=False, + disable_stderr=False, + ): + mne_flash_bem.run() + + kwargs = dict(rtol=1e-5, atol=1e-5) + for s in ("outer_skin", "outer_skull", "inner_skull"): + rr, tris = read_surface(op.join(subject_path_new, "bem", f"{s}.surf")) + assert_equal(len(tris), 5120) + assert_equal(tris.min(), 0) + assert_equal(rr.shape[0], tris.max() + 1) + # compare to the testing flash surfaces + rr_c, tris_c = read_surface(op.join(subjects_dir, "sample", "bem", f"{s}.surf")) + assert_allclose(rr, rr_c, **kwargs) + assert_allclose(tris, tris_c, **kwargs) + + +@testing.requires_testing_data +def test_setup_source_space(tmp_path): + """Test mne setup_source_space.""" + pytest.importorskip("nibabel") + check_usage(mne_setup_source_space, force_help=True) + # Using the sample dataset + use_fname = op.join(tmp_path, "sources-src.fif") + # Test command + with ArgvSetter( + ( + "--src", + use_fname, + "-d", + subjects_dir, + "-s", + "sample", + "--morph", + "sample", + "--add-dist", + "False", + "--ico", + "3", + "--verbose", + ) + ): + mne_setup_source_space.run() + src = read_source_spaces(use_fname) + assert len(src) == 2 + with pytest.raises(Exception): + with ArgvSetter( + ( + "--src", + use_fname, + "-d", + subjects_dir, + "-s", + "sample", + "--ico", + "3", + "--oct", + "3", + ) + ): + assert mne_setup_source_space.run() + with pytest.raises(Exception): + with ArgvSetter( + ( + "--src", + use_fname, + "-d", + subjects_dir, + "-s", + "sample", + "--ico", + "3", + "--spacing", + "10", + ) + ): + assert mne_setup_source_space.run() + with pytest.raises(Exception): + with ArgvSetter( + ( + "--src", + use_fname, + "-d", + subjects_dir, + "-s", + "sample", + "--ico", + "3", + "--spacing", + "10", + "--oct", + "3", + ) + ): + assert mne_setup_source_space.run() + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_setup_forward_model(tmp_path): + """Test mne setup_forward_model.""" + pytest.importorskip("nibabel") + check_usage(mne_setup_forward_model, force_help=True) + # Using the sample dataset + use_fname = op.join(tmp_path, "model-bem.fif") + # Test command + with ArgvSetter( + ( + "--model", + use_fname, + "-d", + subjects_dir, + "--homog", + "-s", + "sample", + "--ico", + "3", + "--verbose", + ) + ): + mne_setup_forward_model.run() + model = read_bem_surfaces(use_fname) + assert len(model) == 1 + sol_fname = op.splitext(use_fname)[0] + "-sol.fif" + read_bem_solution(sol_fname) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_mne_prepare_bem_model(tmp_path): + """Test mne setup_source_space.""" + check_usage(mne_prepare_bem_model, force_help=True) + # Using the sample dataset + bem_solution_fname = op.join(tmp_path, "bem_solution-bem-sol.fif") + # Test command + with ArgvSetter( + ("--bem", bem_model_fname, "--sol", bem_solution_fname, "--verbose") + ): + mne_prepare_bem_model.run() + bem_solution = read_bem_solution(bem_solution_fname) + assert isinstance(bem_solution, ConductorModel) + + +def test_show_info(): + """Test mne show_info.""" + check_usage(mne_show_info) + with ArgvSetter((raw_fname,)): + mne_show_info.run() + + +def test_sys_info(): + """Test mne show_info.""" + check_usage(mne_sys_info, force_help=True) + with ArgvSetter((raw_fname,)): + with pytest.raises(SystemExit, match="1"): + mne_sys_info.run() + with ArgvSetter(("--no-check-version",)) as out: + mne_sys_info.run() + assert "numpy" in out.stdout.getvalue() + + +def test_anonymize(tmp_path): + """Test mne anonymize.""" + check_usage(mne_anonymize) + out_fname = op.join(tmp_path, "anon_test_raw.fif") + with ArgvSetter(("-f", raw_fname, "-o", out_fname)): + mne_anonymize.run() + info = read_info(out_fname) + assert op.exists(out_fname) + assert info["meas_date"] == _stamp_to_dt((946684800, 0)) diff --git a/mne-python/source/mne/commands/utils.py b/mne-python/source/mne/commands/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..beb3a4e98c4d61c418b00caff9fd20613bc89f44 --- /dev/null +++ b/mne-python/source/mne/commands/utils.py @@ -0,0 +1,109 @@ +"""Some utility functions for commands (e.g., for cmdline handling).""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import glob +import importlib +import os +import os.path as op +import sys +from optparse import OptionParser + +import mne + + +def _add_verbose_flag(parser): + parser.add_option( + "--verbose", + dest="verbose", + help="Enable verbose mode (printing of log messages).", + default=None, + action="store_true", + ) + + +def load_module(name, path): + """Load module from .py/.pyc file. + + Parameters + ---------- + name : str + Name of the module. + path : str + Path to .py/.pyc file. + + Returns + ------- + mod : module + Imported module. + + """ + from importlib.util import module_from_spec, spec_from_file_location + + spec = spec_from_file_location(name, path) + mod = module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + +def get_optparser(cmdpath, usage=None, prog_prefix="mne", version=None): + """Create OptionParser with cmd specific settings (e.g., prog value).""" + # Fetch description + mod = load_module("__temp", cmdpath) + if mod.__doc__: + doc, description, epilog = mod.__doc__, None, None + + doc_lines = doc.split("\n") + description = doc_lines[0] + if len(doc_lines) > 1: + epilog = "\n".join(doc_lines[1:]) + + # Get the name of the command + command = os.path.basename(cmdpath) + command, _ = os.path.splitext(command) + command = command[len(prog_prefix) + 1 :] # +1 is for `_` character + + # Set prog + prog = prog_prefix + f" {command}" + + # Set version + if version is None: + version = mne.__version__ + + # monkey patch OptionParser to not wrap epilog + OptionParser.format_epilog = lambda self, formatter: self.epilog + parser = OptionParser( + prog=prog, version=version, description=description, epilog=epilog, usage=usage + ) + + return parser + + +def main(): + """Entrypoint for mne usage.""" + mne_bin_dir = op.dirname(op.dirname(__file__)) + valid_commands = sorted(glob.glob(op.join(mne_bin_dir, "commands", "mne_*.py"))) + valid_commands = [c.split(op.sep)[-1][4:-3] for c in valid_commands] + + def print_help(): # noqa + print("Usage : mne command options\n") + print("Accepted commands :\n") + for c in valid_commands: + print(f"\t- {c}") + print("\nExample : mne browse_raw --raw sample_audvis_raw.fif") + print("\nGetting help example : mne compute_proj_eog -h") + + if len(sys.argv) == 1 or "help" in sys.argv[1] or "-h" in sys.argv[1]: + print_help() + elif sys.argv[1] == "--version": + print(f"MNE {mne.__version__}") + elif sys.argv[1] not in valid_commands: + print(f'Invalid command: "{sys.argv[1]}"\n') + print_help() + else: + cmd = sys.argv[1] + cmd = importlib.import_module(f".mne_{cmd}", "mne.commands") + sys.argv = sys.argv[1:] + cmd.run() diff --git a/mne-python/source/mne/conftest.py b/mne-python/source/mne/conftest.py new file mode 100644 index 0000000000000000000000000000000000000000..a1e6a21ec48a94dc6f06e1c46e8d52a89b4ca657 --- /dev/null +++ b/mne-python/source/mne/conftest.py @@ -0,0 +1,1337 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import gc +import inspect +import os +import os.path as op +import platform +import re +import shutil +import sys +import warnings +from collections import defaultdict +from contextlib import contextmanager +from pathlib import Path +from textwrap import dedent +from unittest import mock + +import numpy as np +import pytest +from packaging.version import Version +from pytest import StashKey, register_assert_rewrite + +# Any `assert` statements in our testing functions should be verbose versions +register_assert_rewrite("mne.utils._testing") + +# ruff: noqa: E402 +import mne +from mne import Epochs, pick_types, read_events +from mne.channels import read_layout +from mne.coreg import create_default_subject +from mne.datasets import testing +from mne.fixes import _compare_version, has_numba +from mne.io import read_raw_ctf, read_raw_fif, read_raw_nirx, read_raw_snirf +from mne.stats import cluster_level +from mne.utils import ( + Bunch, + _assert_no_instances, + _check_qt_version, + _pl, + _record_warnings, + _TempDir, + check_version, + numerics, +) +from mne.viz._figure import use_browser_backend +from mne.viz.backends._utils import _init_mne_qtapp + +# data from sample dataset +test_path = testing.data_path(download=False) +s_path = op.join(test_path, "MEG", "sample") +fname_evoked = op.join(s_path, "sample_audvis_trunc-ave.fif") +fname_cov = op.join(s_path, "sample_audvis_trunc-cov.fif") +fname_fwd = op.join(s_path, "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif") +fname_fwd_full = op.join(s_path, "sample_audvis_trunc-meg-eeg-oct-6-fwd.fif") +bem_path = op.join(test_path, "subjects", "sample", "bem") +fname_bem = op.join(bem_path, "sample-1280-bem.fif") +fname_aseg = op.join(test_path, "subjects", "sample", "mri", "aseg.mgz") +subjects_dir = op.join(test_path, "subjects") +fname_src = op.join(bem_path, "sample-oct-4-src.fif") +fname_trans = op.join(s_path, "sample_audvis_trunc-trans.fif") + +ctf_dir = op.join(test_path, "CTF") +fname_ctf_continuous = op.join(ctf_dir, "testdata_ctf.ds") + +nirx_path = test_path / "NIRx" +snirf_path = test_path / "SNIRF" +nirsport2 = nirx_path / "nirsport_v2" / "aurora_recording _w_short_and_acc" +nirsport2_snirf = snirf_path / "NIRx" / "NIRSport2" / "1.0.3" / "2021-05-05_001.snirf" +nirsport2_2021_9 = nirx_path / "nirsport_v2" / "aurora_2021_9" +nirsport2_20219_snirf = ( + snirf_path / "NIRx" / "NIRSport2" / "2021.9" / "2021-10-01_002.snirf" +) + +# data from mne.io.tests.data +base_dir = op.join(op.dirname(__file__), "io", "tests", "data") +fname_raw_io = op.join(base_dir, "test_raw.fif") +fname_event_io = op.join(base_dir, "test-eve.fif") +fname_cov_io = op.join(base_dir, "test-cov.fif") +fname_evoked_io = op.join(base_dir, "test-ave.fif") +event_id, tmin, tmax = 1, -0.1, 1.0 +vv_layout = read_layout("Vectorview-all") + +collect_ignore = ["export/_brainvision.py", "export/_eeglab.py", "export/_edf_bdf.py"] + + +def pytest_configure(config: pytest.Config): + """Configure pytest options.""" + # Markers + # can be queried with `pytest --markers` for example + for marker in ( + "slowtest: mark a test as slow", + "ultraslowtest: mark a test as ultraslow or to be run rarely", + "pgtest: mark a test as relevant for mne-qt-browser", + "pvtest: mark a test as relevant for pyvistaqt", + "allow_unclosed: allow unclosed pyvistaqt instances", + ): + config.addinivalue_line("markers", marker) + + # Fixtures + for fixture in ( + "matplotlib_config", + "qt_config", + "protect_config", + ): + config.addinivalue_line("usefixtures", fixture) + + # pytest-qt uses PYTEST_QT_API, but let's make it respect qtpy's QT_API + # if present + if os.getenv("PYTEST_QT_API") is None and os.getenv("QT_API") is not None: + os.environ["PYTEST_QT_API"] = os.environ["QT_API"] + + # suppress: + # Debugger warning: It seems that frozen modules are being used, which may + # make the debugger miss breakpoints. Please pass -Xfrozen_modules=off + # to python to disable frozen modules. + if os.getenv("PYDEVD_DISABLE_FILE_VALIDATION") is None: + os.environ["PYDEVD_DISABLE_FILE_VALIDATION"] = "1" + + # https://numba.readthedocs.io/en/latest/reference/deprecation.html#deprecation-of-old-style-numba-captured-errors # noqa: E501 + if "NUMBA_CAPTURED_ERRORS" not in os.environ: + os.environ["NUMBA_CAPTURED_ERRORS"] = "new_style" + + # Warnings + # - Once SciPy updates not to have non-integer and non-tuple errors (1.2.0) + # we should remove them from here. + # - This list should also be considered alongside reset_warnings in + # doc/conf.py. + if os.getenv("MNE_IGNORE_WARNINGS_IN_TESTS", "") not in ("true", "1"): + first_kind = "error" + else: + first_kind = "always" + warning_lines = f" {first_kind}::" + warning_lines += r""" + # matplotlib->traitlets (notebook) + ignore:Passing unrecognized arguments to super.*:DeprecationWarning + # notebook tests + ignore:There is no current event loop:DeprecationWarning + ignore:unclosed tz + ignore:datetime.datetime.utcfromtimestamp.*:DeprecationWarning + # joblib + ignore:ast\.Num is deprecated.*:DeprecationWarning + ignore:Attribute n is deprecated and will be removed in Python 3\.14.*:DeprecationWarning + # numpydoc + ignore:ast\.NameConstant is deprecated and will be removed in Python 3\.14.*:DeprecationWarning + # pooch + ignore:Python 3\.14 will, by default, filter extracted tar archives.*:DeprecationWarning + # pandas + ignore:\n*Pyarrow will become a required dependency of pandas.*:DeprecationWarning + ignore:np\.find_common_type is deprecated.*:DeprecationWarning + ignore:Python binding for RankQuantileOptions.*: + # pyvista <-> NumPy 2.0 + ignore:__array_wrap__ must accept context and return_scalar arguments.*:DeprecationWarning + # pyvista <-> VTK dev + ignore:Call to deprecated method Get.*:DeprecationWarning + # nibabel <-> NumPy 2.0 + ignore:__array__ implementation doesn't accept a copy.*:DeprecationWarning + # quantities via neo + ignore:The 'copy' argument in Quantity is deprecated.*: + # debugpy uses deprecated matplotlib API + ignore:The (non_)?interactive_bk attribute was deprecated.*: + # SWIG (via OpenMEEG) + ignore:.*builtin type swigvarlink has no.*:DeprecationWarning + # eeglabio + ignore:numpy\.core\.records is deprecated.*:DeprecationWarning + ignore:Starting field name with a underscore.*: + # joblib + ignore:process .* is multi-threaded, use of fork/exec.*:DeprecationWarning + # sklearn + ignore:Python binding for RankQuantileOptions.*:RuntimeWarning + ignore:.*The `disp` and `iprint` options of the L-BFGS-B solver.*:DeprecationWarning + # matplotlib<->nilearn + ignore:[\S\s]*You are using the 'agg' matplotlib backend[\S\s]*:UserWarning + # matplotlib<->pyparsing + ignore:^'.*' argument is deprecated, use '.*'$:DeprecationWarning + ignore:^'.*' deprecated - use '.*'$:DeprecationWarning + # dipy + ignore:'where' used without 'out', expect .*:UserWarning + # VTK <-> NumPy 2.5 (https://gitlab.kitware.com/vtk/vtk/-/merge_requests/12796) + # nitime <-> NumPy 2.5 (https://github.com/nipy/nitime/pull/236) + ignore:Setting the shape on a NumPy array has been deprecated.*:DeprecationWarning + """ # noqa: E501 + for warning_line in warning_lines.split("\n"): + warning_line = warning_line.strip() + if warning_line and not warning_line.startswith("#"): + config.addinivalue_line("filterwarnings", warning_line) + try: + import pandas + except Exception: + pass + else: + if Version(pandas.__version__) >= Version("3.1.0.dev0"): + # TODO VERSION once statsmodels dev has updated for pip-pre + # (failing as of 2026/02/04) + config.addinivalue_line( + "filterwarnings", + "ignore:" + ".+ is deprecated and will be removed in a future version.*:" + "pandas.errors.Pandas4Warning", + ) + + +def pytest_collection_modifyitems(items: list[pytest.Item]): + """Add slowtest marker automatically to anything marked ultraslow.""" + for item in items: + if len(list(item.iter_markers("ultraslowtest"))): + item.add_marker(pytest.mark.slowtest) + + +# Have to be careful with autouse=True, but this is just an int comparison +# so it shouldn't really add appreciable overhead +@pytest.fixture(autouse=True) +def check_verbose(request): + """Set to the default logging level to ensure it's tested properly.""" + starting_level = mne.utils.logger.level + yield + # ensures that no tests break the global state + try: + assert mne.utils.logger.level == starting_level + except AssertionError: + pytest.fail( + ".".join([request.module.__name__, request.function.__name__]) + + " modifies logger.level" + ) + + +@pytest.fixture(autouse=True) +def close_all(): + """Close all matplotlib plots, regardless of test status.""" + # This adds < 1 µS in local testing, and we have ~2500 tests, so ~2 ms max + import matplotlib.pyplot as plt + + yield + plt.close("all") + + +@pytest.fixture(autouse=True) +def add_mne(doctest_namespace): + """Add mne to the namespace.""" + doctest_namespace["mne"] = mne + + +@pytest.fixture(scope="function") +def verbose_debug(): + """Run a test with debug verbosity.""" + with mne.utils.use_log_level("debug"): + yield + + +@pytest.fixture(scope="session") +def qt_config(): + """Configure the Qt backend for viz tests.""" + os.environ["_MNE_BROWSER_NO_BLOCK"] = "true" + if "_MNE_BROWSER_BACK" not in os.environ: + os.environ["_MNE_BROWSER_BACK"] = "true" + + +@pytest.fixture(scope="session") +def matplotlib_config(): + """Configure matplotlib for viz tests.""" + import matplotlib + from matplotlib import cbook + + # Allow for easy interactive debugging with a call like: + # + # $ MNE_MPL_TESTING_BACKEND=Qt5Agg pytest mne/viz/tests/test_raw.py -k annotation -x --pdb # noqa: E501 + # + try: + want = os.environ["MNE_MPL_TESTING_BACKEND"] + except KeyError: + want = "agg" # don't pop up windows + with warnings.catch_warnings(record=True): # ignore warning + warnings.filterwarnings("ignore") + matplotlib.use(want, force=True) + import matplotlib.pyplot as plt + + assert plt.get_backend() == want + # overwrite some params that can horribly slow down tests that + # users might have changed locally (but should not otherwise affect + # functionality) + plt.ioff() + plt.rcParams["figure.dpi"] = 100 + plt.rcParams["figure.raise_window"] = False + + # Make sure that we always reraise exceptions in handlers + orig = cbook.CallbackRegistry + + class CallbackRegistryReraise(orig): + def __init__(self, exception_handler=None, signals=None): + super().__init__(exception_handler) + + cbook.CallbackRegistry = CallbackRegistryReraise + + +@pytest.fixture(scope="session") +def azure_windows(): + """Determine if running on Azure Windows.""" + return ( + os.getenv("AZURE_CI_WINDOWS", "false").lower() == "true" + and platform.system() == "Windows" + ) + + +@pytest.fixture(scope="function") +def raw_orig(): + """Get raw data without any change to it from mne.io.tests.data.""" + raw = read_raw_fif(fname_raw_io, preload=True) + return raw + + +@pytest.fixture(scope="function") +def raw(): + """ + Get raw data and pick channels to reduce load for testing. + + (from mne.io.tests.data) + """ + raw = read_raw_fif(fname_raw_io, preload=True) + # Throws a warning about a changed unit. + with pytest.warns(RuntimeWarning, match="unit"): + raw.set_channel_types({raw.ch_names[0]: "ias"}) + raw.pick(raw.ch_names[:9]) + raw.info.normalize_proj() # Fix projectors after subselection + return raw + + +@pytest.fixture(scope="function") +def raw_ctf(): + """Get ctf raw data from mne.io.tests.data.""" + raw_ctf = read_raw_ctf(fname_ctf_continuous, preload=True) + return raw_ctf + + +@pytest.fixture(scope="function") +def raw_spectrum(raw): + """Get raw with power spectral density computed from mne.io.tests.data.""" + return raw.compute_psd() + + +@pytest.fixture(scope="function") +def events(): + """Get events from mne.io.tests.data.""" + return read_events(fname_event_io) + + +def _get_epochs(stop=5, meg=True, eeg=False, n_chan=20): + """Get epochs.""" + raw = read_raw_fif(fname_raw_io) + events = read_events(fname_event_io) + picks = pick_types( + raw.info, meg=meg, eeg=eeg, stim=False, ecg=False, eog=False, exclude="bads" + ) + # Use a subset of channels for plotting speed + picks = np.round(np.linspace(0, len(picks) + 1, n_chan)).astype(int) + with pytest.warns(RuntimeWarning, match="projection"): + epochs = Epochs( + raw, + events[:stop], + event_id, + tmin, + tmax, + picks=picks, + proj=False, + preload=False, + ) + epochs.info.normalize_proj() # avoid warnings + return epochs + + +@pytest.fixture() +def epochs(): + """ + Get minimal, pre-loaded epochs data suitable for most tests. + + (from mne.io.tests.data) + """ + return _get_epochs().load_data() + + +@pytest.fixture() +def epochs_unloaded(): + """Get minimal, unloaded epochs data from mne.io.tests.data.""" + return _get_epochs() + + +@pytest.fixture() +def epochs_full(): + """Get full, preloaded epochs from mne.io.tests.data.""" + return _get_epochs(None).load_data() + + +@pytest.fixture() +def epochs_spectrum(): + """Get epochs with power spectral density computed from mne.io.tests.data.""" + return _get_epochs().load_data().compute_psd() + + +@pytest.fixture() +def epochs_tfr(): + """Get an EpochsTFR computed from mne.io.tests.data.""" + epochs = _get_epochs().load_data() + return epochs.compute_tfr(method="morlet", freqs=np.linspace(20, 40, num=5)) + + +@pytest.fixture() +def average_tfr(epochs_tfr): + """Get an AverageTFR computed by averaging an EpochsTFR (this is small & fast).""" + return epochs_tfr.average() + + +@pytest.fixture() +def full_average_tfr(full_evoked): + """Get an AverageTFR computed from Evoked. + + This is slower than the `average_tfr` fixture, but a few TFR.plot_* tests need it. + """ + return full_evoked.compute_tfr(method="morlet", freqs=np.linspace(20, 40, num=5)) + + +@pytest.fixture() +def raw_tfr(raw): + """Get a RawTFR computed from mne.io.tests.data.""" + return raw.compute_tfr(method="morlet", freqs=np.linspace(20, 40, num=5)) + + +@pytest.fixture() +def epochs_empty(): + """Get empty epochs from mne.io.tests.data.""" + epochs = _get_epochs(meg=True, eeg=True).load_data() + with pytest.warns(RuntimeWarning, match="were dropped"): + epochs.drop_bad(reject={"mag": 1e-20}) + + return epochs + + +@pytest.fixture(scope="session", params=[testing._pytest_param()]) +def _full_evoked(): + # This is session scoped, so be sure not to modify its return value (use + # `full_evoked` fixture instead) + return mne.read_evokeds(fname_evoked, condition="Left Auditory", baseline=(None, 0)) + + +@pytest.fixture(scope="session", params=[testing._pytest_param()]) +def _evoked(_full_evoked): + # This is session scoped, so be sure not to modify its return value (use `evoked` + # fixture instead) + return _full_evoked.copy().crop(0, 0.2) + + +@pytest.fixture() +def evoked(_evoked): + """Get truncated evoked data.""" + return _evoked.copy() + + +@pytest.fixture() +def full_evoked(_full_evoked): + """Get full-duration evoked data (needed for, e.g., testing TFR).""" + return _full_evoked.copy() + + +@pytest.fixture(scope="function", params=[testing._pytest_param()]) +def noise_cov(): + """Get a noise cov from the testing dataset.""" + return mne.read_cov(fname_cov) + + +@pytest.fixture +def noise_cov_io(): + """Get noise-covariance (from mne.io.tests.data).""" + return mne.read_cov(fname_cov_io) + + +@pytest.fixture(scope="function") +def bias_params_free(evoked, noise_cov): + """Provide inputs for free bias functions.""" + fwd = mne.read_forward_solution(fname_fwd) + return _bias_params(evoked, noise_cov, fwd) + + +@pytest.fixture(scope="function") +def bias_params_fixed(evoked, noise_cov): + """Provide inputs for fixed bias functions.""" + fwd = mne.read_forward_solution(fname_fwd) + mne.convert_forward_solution(fwd, force_fixed=True, surf_ori=True, copy=False) + return _bias_params(evoked, noise_cov, fwd) + + +def _bias_params(evoked, noise_cov, fwd): + evoked.pick(picks=["meg", "eeg"]) + # restrict to limited set of verts (small src here) and one hemi for speed + vertices = [fwd["src"][0]["vertno"].copy(), []] + stc = mne.SourceEstimate( + np.zeros((sum(len(v) for v in vertices), 1)), vertices, 0, 1 + ) + fwd = mne.forward.restrict_forward_to_stc(fwd, stc) + assert fwd["sol"]["row_names"] == noise_cov["names"] + assert noise_cov["names"] == evoked.ch_names + evoked = mne.EvokedArray(fwd["sol"]["data"].copy(), evoked.info) + data_cov = noise_cov.copy() + data = fwd["sol"]["data"] @ fwd["sol"]["data"].T + data *= 1e-14 # 100 nAm at each source, effectively (1e-18 would be 1 nAm) + # This is rank-deficient, so let's make it actually positive semidefinite + # by regularizing a tiny bit + data.flat[:: data.shape[0] + 1] += mne.make_ad_hoc_cov(evoked.info)["data"] + # Do our projection + proj, _, _ = mne._fiff.proj.make_projector(data_cov["projs"], data_cov["names"]) + data = proj @ data @ proj.T + data_cov["data"][:] = data + assert data_cov["data"].shape[0] == len(noise_cov["names"]) + want = np.arange(fwd["sol"]["data"].shape[1]) + if not mne.forward.is_fixed_orient(fwd): + want //= 3 + return evoked, fwd, noise_cov, data_cov, want + + +@pytest.fixture +def garbage_collect(): + """Garbage collect on exit.""" + yield + gc.collect() + + +@pytest.fixture +def mpl_backend(garbage_collect): + """Use for epochs/ica when not implemented with pyqtgraph yet.""" + with use_browser_backend("matplotlib") as backend: + yield backend + backend._close_all() + + +# Skip functions or modules for mne-qt-browser < 0.2.0 +pre_2_0_skip_modules = ["mne.viz.tests.test_epochs", "mne.viz.tests.test_ica"] +pre_2_0_skip_funcs = ["test_plot_raw_white", "test_plot_raw_selection"] + + +def _check_pyqtgraph(request): + # Check Qt + qt_version, api = _check_qt_version(return_api=True) + if (not qt_version) or _compare_version(qt_version, "<", "5.12"): + pytest.skip( + f"Qt API {api} has version {qt_version} but pyqtgraph needs >= 5.12!" + ) + try: + import mne_qt_browser # noqa: F401 + + # Check mne-qt-browser version + lower_2_0 = _compare_version(mne_qt_browser.__version__, "<", "0.2.0") + m_name = request.function.__module__ + f_name = request.function.__name__ + if lower_2_0 and m_name in pre_2_0_skip_modules: + pytest.skip( + f'Test-Module "{m_name}" was skipped for mne-qt-browser < 0.2.0' + ) + elif lower_2_0 and f_name in pre_2_0_skip_funcs: + pytest.skip(f'Test "{f_name}" was skipped for mne-qt-browser < 0.2.0') + except Exception: + pytest.skip("Requires mne_qt_browser") + else: + ver = mne_qt_browser.__version__ + if api != "PyQt5" and _compare_version(ver, "<=", "0.2.6"): + pytest.skip(f"mne_qt_browser {ver} requires PyQt5, API is {api}") + + +@pytest.fixture +def pg_backend(request, garbage_collect): + """Use for pyqtgraph-specific test-functions.""" + _check_pyqtgraph(request) + from mne_qt_browser._pg_figure import MNEQtBrowser + + with use_browser_backend("qt") as backend: + backend._close_all() + yield backend + backend._close_all() + # This shouldn't be necessary, but let's make sure nothing is stale + import mne_qt_browser + + mne_qt_browser._browser_instances.clear() + if not _test_passed(request): + return + _assert_no_instances(MNEQtBrowser, f"Closure of {request.node.name}") + + +@pytest.fixture( + params=[ + "matplotlib", + pytest.param("qt", marks=pytest.mark.pgtest), + ] +) +def browser_backend(request, garbage_collect, monkeypatch): + """Parametrizes the name of the browser backend.""" + backend_name = request.param + if backend_name == "qt": + _check_pyqtgraph(request) + with use_browser_backend(backend_name) as backend: + backend._close_all() + monkeypatch.setenv("MNE_BROWSE_RAW_SIZE", "10,10") + yield backend + backend._close_all() + if backend_name == "qt": + # This shouldn't be necessary, but let's make sure nothing is stale + import mne_qt_browser + + mne_qt_browser._browser_instances.clear() + + +@pytest.fixture(params=[pytest.param("pyvistaqt", marks=pytest.mark.pvtest)]) +def renderer(request, options_3d, garbage_collect): + """Yield the 3D backends.""" + with _use_backend(request.param, interactive=False) as renderer: + yield renderer + + +@pytest.fixture(params=[pytest.param("pyvistaqt", marks=pytest.mark.pvtest)]) +def renderer_pyvistaqt(request, options_3d, garbage_collect): + """Yield the PyVista backend.""" + with _use_backend(request.param, interactive=False) as renderer: + yield renderer + + +@pytest.fixture(params=[pytest.param("notebook", marks=pytest.mark.pvtest)]) +def renderer_notebook(request, options_3d): + """Yield the 3D notebook renderer.""" + with _use_backend(request.param, interactive=False) as renderer: + yield renderer + + +@pytest.fixture(params=[pytest.param("pyvistaqt", marks=pytest.mark.pvtest)]) +def renderer_interactive_pyvistaqt(request, options_3d, qt_windows_closed): + """Yield the interactive PyVista backend.""" + with _use_backend(request.param, interactive=True) as renderer: + yield renderer + + +@pytest.fixture(params=[pytest.param("pyvistaqt", marks=pytest.mark.pvtest)]) +def renderer_interactive(request, options_3d): + """Yield the interactive 3D backends.""" + with _use_backend(request.param, interactive=True) as renderer: + yield renderer + + +@contextmanager +def _use_backend(backend_name, interactive): + from mne.viz.backends.renderer import _use_test_3d_backend + + _check_skip_backend(backend_name) + with _use_test_3d_backend(backend_name, interactive=interactive): + from mne.viz.backends import renderer + + try: + yield renderer + finally: + renderer.backend._close_all() + + +def _check_skip_backend(name): + from mne.viz.backends._utils import _notebook_vtk_works + + pytest.importorskip("pyvista") + pytest.importorskip("imageio_ffmpeg") + if name == "pyvistaqt": + pytest.importorskip("pyvistaqt") + if not _check_qt_version(): + pytest.skip("Test skipped, requires Qt.") + else: + assert name == "notebook", name + pytest.importorskip("jupyter") + pytest.importorskip("ipympl") + pytest.importorskip("ipyevents") + pytest.importorskip("trame") + pytest.importorskip("trame_vtk") + pytest.importorskip("trame_vuetify") + if not _notebook_vtk_works(): + pytest.skip("Test skipped, requires working notebook vtk") + + +@pytest.fixture(scope="session") +def pixel_ratio(): + """Get the pixel ratio.""" + # _check_qt_version will init an app for us, so no need for us to do it + if not check_version("pyvista", "0.32") or not _check_qt_version(): + return 1.0 + from qtpy.QtCore import Qt + from qtpy.QtWidgets import QMainWindow + + app = _init_mne_qtapp() + app.processEvents() + window = QMainWindow() + window.setAttribute(Qt.WA_DeleteOnClose, True) + ratio = float(window.devicePixelRatio()) + window.close() + return ratio + + +@pytest.fixture(scope="function", params=[testing._pytest_param()]) +def subjects_dir_tmp(tmp_path): + """Copy MNE-testing-data subjects_dir to a temp dir for manipulation.""" + for key in ("sample", "fsaverage"): + shutil.copytree(op.join(subjects_dir, key), str(tmp_path / key)) + return str(tmp_path) + + +@pytest.fixture(params=[testing._pytest_param()]) +def subjects_dir_tmp_few(tmp_path): + """Copy fewer files to a tmp_path.""" + subjects_path = tmp_path / "subjects" + os.mkdir(subjects_path) + # add fsaverage + create_default_subject(subjects_dir=subjects_path, fs_home=test_path, verbose=True) + # add sample (with few files) + sample_path = subjects_path / "sample" + os.makedirs(sample_path / "bem") + for dirname in ("mri", "surf"): + shutil.copytree( + test_path / "subjects" / "sample" / dirname, sample_path / dirname + ) + return subjects_path + + +# Scoping these as session will make things faster, but need to make sure +# not to modify them in-place in the tests, so keep them private +@pytest.fixture(scope="session", params=[testing._pytest_param()]) +def _evoked_cov_sphere(_evoked): + """Compute a small evoked/cov/sphere combo for use with forwards.""" + evoked = _evoked.copy().pick(picks="meg") + evoked.pick(evoked.ch_names[::4]) + assert len(evoked.ch_names) == 77 + cov = mne.read_cov(fname_cov) + sphere = mne.make_sphere_model( + (0.0, 0.0, 0.04), 0.1, relative_radii=(0.995, 0.997, 0.998, 1.0) + ) + return evoked, cov, sphere + + +@pytest.fixture(scope="session") +def _fwd_surf(_evoked_cov_sphere): + """Compute a forward for a surface source space.""" + evoked, _, sphere = _evoked_cov_sphere + src_surf = mne.read_source_spaces(fname_src) + return mne.make_forward_solution( + evoked.info, fname_trans, src_surf, sphere, mindist=5.0 + ) + + +@pytest.fixture(scope="session") +def _fwd_subvolume(_evoked_cov_sphere): + """Compute a forward for a surface source space.""" + pytest.importorskip("nibabel") + evoked, _, sphere = _evoked_cov_sphere + volume_labels = ["Left-Cerebellum-Cortex", "right-Cerebellum-Cortex"] + with pytest.raises(ValueError, match=r"Did you mean one of \['Right-Cere"): + mne.setup_volume_source_space( + "sample", pos=20.0, volume_label=volume_labels, subjects_dir=subjects_dir + ) + volume_labels[1] = "R" + volume_labels[1][1:] + src_vol = mne.setup_volume_source_space( + "sample", + pos=20.0, + volume_label=volume_labels, + subjects_dir=subjects_dir, + add_interpolator=False, + ) + fwd = mne.make_forward_solution( + evoked.info, fname_trans, src_vol, sphere, mindist=1.0 + ) + nsrc = sum(s["nuse"] for s in src_vol) + assert fwd["nsource"] == nsrc + return fwd + + +@pytest.fixture +def fwd_volume_small(_fwd_subvolume): + """Provide a small volumetric source space.""" + return _fwd_subvolume.copy() + + +@pytest.fixture(scope="session") +def _all_src_types_fwd(_fwd_surf, _fwd_subvolume): + """Create all three forward types (surf, vol, mixed).""" + fwds = dict(surface=_fwd_surf.copy(), volume=_fwd_subvolume.copy()) + with pytest.raises(RuntimeError, match="Invalid source space with kinds"): + fwds["volume"]["src"] + fwds["surface"]["src"] + + # mixed (4) + fwd = fwds["surface"].copy() + f2 = fwds["volume"].copy() + del _fwd_surf, _fwd_subvolume + for keys, axis in [ + (("source_rr",), 0), + (("source_nn",), 0), + (("sol", "data"), 1), + (("_orig_sol",), 1), + ]: + a, b = fwd, f2 + key = keys[0] + if len(keys) > 1: + a, b = a[key], b[key] + key = keys[1] + a[key] = np.concatenate([a[key], b[key]], axis=axis) + fwd["sol"]["ncol"] = fwd["sol"]["data"].shape[1] + fwd["nsource"] = fwd["sol"]["ncol"] // 3 + fwd["src"] = fwd["src"] + f2["src"] + fwds["mixed"] = fwd + + return fwds + + +@pytest.fixture(scope="session") +def _all_src_types_inv_evoked(_evoked_cov_sphere, _all_src_types_fwd): + """Compute inverses for all source types.""" + evoked, cov, _ = _evoked_cov_sphere + invs = dict() + for kind, fwd in _all_src_types_fwd.items(): + assert fwd["src"].kind == kind + with pytest.warns(RuntimeWarning, match="has been reduced"): + invs[kind] = mne.minimum_norm.make_inverse_operator(evoked.info, fwd, cov) + return invs, evoked + + +@pytest.fixture(scope="function") +def all_src_types_inv_evoked(_all_src_types_inv_evoked): + """All source types of inverses, allowing for possible modification.""" + invs, evoked = _all_src_types_inv_evoked + invs = {key: val.copy() for key, val in invs.items()} + evoked = evoked.copy() + return invs, evoked + + +@pytest.fixture(scope="function") +def mixed_fwd_cov_evoked(_evoked_cov_sphere, _all_src_types_fwd): + """Compute inverses for all source types.""" + evoked, cov, _ = _evoked_cov_sphere + return _all_src_types_fwd["mixed"].copy(), cov.copy(), evoked.copy() + + +@pytest.fixture(scope="session") +def src_volume_labels(): + """Create a 7mm source space with labels.""" + pytest.importorskip("nibabel") + volume_labels = mne.get_volume_labels_from_aseg(fname_aseg) + with ( + _record_warnings(), + pytest.warns(RuntimeWarning, match="Found no usable.*t-vessel.*"), + ): + src = mne.setup_volume_source_space( + "sample", + 7.0, + mri="aseg.mgz", + volume_label=volume_labels, + add_interpolator=False, + bem=fname_bem, + subjects_dir=subjects_dir, + ) + lut, _ = mne.read_freesurfer_lut() + assert len(volume_labels) == 46 + assert volume_labels[0] == "Unknown" + assert lut["Unknown"] == 0 # it will be excluded during label gen + return src, tuple(volume_labels), lut + + +def _fail(*args, **kwargs): + __tracebackhide__ = True + raise AssertionError("Test should not download") + + +@pytest.fixture(scope="function") +def download_is_error(monkeypatch): + """Prevent downloading by raising an error when it's attempted.""" + import pooch + + monkeypatch.setattr(pooch, "retrieve", _fail) + yield + + +@pytest.fixture() +def fake_retrieve(monkeypatch, download_is_error): + """Monkeypatch pooch.retrieve to avoid downloading (just touch files).""" + import pooch + + my_func = _FakeFetch() + monkeypatch.setattr(pooch, "retrieve", my_func) + monkeypatch.setattr(pooch, "create", my_func) + yield my_func + + +class _FakeFetch: + def __init__(self): + self.call_args_list = list() + + @property + def call_count(self): + return len(self.call_args_list) + + # Wrapper for pooch.retrieve(...) and pooch.create(...) + def __call__(self, *args, **kwargs): + assert "path" in kwargs + if "fname" in kwargs: # pooch.retrieve(...) + self.call_args_list.append((args, kwargs)) + path = Path(kwargs["path"], kwargs["fname"]) + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("test") + return path + else: # pooch.create(...) has been called + self.path = kwargs["path"] + return self + + # Wrappers for Pooch instances (e.g., in eegbci we pooch.create) + def fetch(self, fname): + self(path=self.path, fname=fname) + + def load_registry(self, registry): + assert Path(registry).exists(), registry + + +# We can't use monkeypatch because its scope (function-level) conflicts with +# the requests fixture (module-level), so we live with a module-scoped version +# that uses mock +@pytest.fixture(scope="module") +def options_3d(): + """Disable advanced 3d rendering.""" + with mock.patch.dict( + os.environ, + { + "MNE_3D_OPTION_ANTIALIAS": "false", + "MNE_3D_OPTION_DEPTH_PEELING": "false", + "MNE_3D_OPTION_SMOOTH_SHADING": "false", + }, + ): + yield + + +@pytest.fixture(scope="session") +def protect_config(): + """Protect ~/.mne.""" + temp = _TempDir() + with mock.patch.dict(os.environ, {"_MNE_FAKE_HOME_DIR": temp}): + yield + + +def _test_passed(request): + if _phase_report_key not in request.node.stash: + return True + report = request.node.stash[_phase_report_key] + return "call" in report and report["call"].outcome == "passed" + + +@pytest.fixture() +def brain_gc(request): + """Ensure that brain can be properly garbage collected.""" + keys = ( + "renderer_interactive", + "renderer_interactive_pyvistaqt", + "renderer", + "renderer_pyvistaqt", + "renderer_notebook", + ) + assert set(request.fixturenames) & set(keys) != set() + for key in keys: + if key in request.fixturenames: + is_pv = request.getfixturevalue(key)._get_3d_backend() == "pyvistaqt" + close_func = request.getfixturevalue(key).backend._close_all + break + if not is_pv: + yield + return + from mne.viz import Brain + + ignore = set(id(o) for o in gc.get_objects()) + yield + close_func() + if not _test_passed(request): + return + _assert_no_instances(Brain, "after") + # Check VTK + objs = gc.get_objects() + bad = list() + for o in objs: + try: + name = o.__class__.__name__ + except Exception: # old Python, probably + pass + else: + if name.startswith("vtk") and id(o) not in ignore: + bad.append(name) + del o + del objs, ignore, Brain + assert len(bad) == 0, "VTK objects linger:\n" + "\n".join(bad) + + +_files = list() + + +def pytest_sessionfinish(session, exitstatus): + """Handle the end of the session.""" + n = session.config.option.durations + if n is None: + return + print("\n") + # get the number to print + files = defaultdict(lambda: 0.0) + for item in session.items: + if _phase_report_key not in item.stash: + continue + report = item.stash[_phase_report_key] + dur = sum(x.duration for x in report.values()) + parts = Path(item.nodeid.split(":")[0]).parts + # split mne/tests/test_whatever.py into separate categories since these + # are essentially submodule-level tests. Keeping just [:3] works, + # except for mne/viz where we want level-4 granulatity + split_submodules = (("mne", "viz"), ("mne", "preprocessing")) + parts = parts[: 4 if parts[:2] in split_submodules else 3] + if not parts[-1].endswith(".py"): + parts = parts + ("",) + file_key = "/".join(parts) + files[file_key] += dur + files = sorted(list(files.items()), key=lambda x: x[1])[::-1] + # print + _files[:] = files[:n] + + +def pytest_terminal_summary(terminalreporter, exitstatus, config): + """Print the module-level timings.""" + writer = terminalreporter + n = len(_files) + if n: + writer.line("") # newline + writer.write_sep("=", f"slowest {n} test module{_pl(n)}") + names, timings = zip(*_files) + timings = [f"{timing:0.2f}s total" for timing in timings] + rjust = max(len(timing) for timing in timings) + timings = [timing.rjust(rjust) for timing in timings] + for name, timing in zip(names, timings): + writer.line(f"{timing.ljust(15)}{name}") + + +def pytest_report_header(config, startdir=None): + """Add information to the pytest run header.""" + return f"MNE {mne.__version__} -- {Path(mne.__file__).parent}" + + +@pytest.fixture(scope="function", params=("Numba", "NumPy")) +def numba_conditional(monkeypatch, request): + """Test both code paths on machines that have Numba.""" + assert request.param in ("Numba", "NumPy") + if request.param == "NumPy" and has_numba: + monkeypatch.setattr( + cluster_level, "_get_buddies", cluster_level._get_buddies_fallback + ) + monkeypatch.setattr( + cluster_level, "_get_selves", cluster_level._get_selves_fallback + ) + monkeypatch.setattr( + cluster_level, "_where_first", cluster_level._where_first_fallback + ) + monkeypatch.setattr(numerics, "_arange_div", numerics._arange_div_fallback) + if request.param == "Numba" and not has_numba: + pytest.skip("Numba not installed") + yield request.param + + +# Create one nbclient and reuse it +@pytest.fixture(scope="session") +def _nbclient(): + try: + import nbformat + import trame # noqa + from ipywidgets import Button # noqa + from jupyter_client import AsyncKernelManager + from nbclient import NotebookClient + except Exception as exc: + return pytest.skip(f"Skipping Notebook test: {exc}") + km = AsyncKernelManager(config=None) + nb = nbformat.reads( + """ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata":{}, + "outputs": [], + "source":[] + } + ], + "metadata": { + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version":3}, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.5" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}""", + as_version=4, + ) + client = NotebookClient(nb, km=km) + yield client + try: + client._cleanup_kernel() + except Exception: + pass + + +@pytest.fixture(scope="function") +def nbexec(_nbclient): + """Execute Python code in a notebook.""" + # Adapted/simplified from nbclient/client.py (BSD-3-Clause) + from nbclient.exceptions import CellExecutionError + + _nbclient._cleanup_kernel() + + def execute(code, reset=False): + _nbclient.reset_execution_trackers() + with _nbclient.setup_kernel(): + assert _nbclient.kc is not None + cell = Bunch(cell_type="code", metadata={}, source=dedent(code), outputs=[]) + try: + _nbclient.execute_cell(cell, 0, execution_count=0) + except CellExecutionError: # pragma: no cover + for kind in ("stdout", "stderr"): + print( + "\n".join( + o["text"] for o in cell.outputs if o.get("name", "") == kind + ), + file=getattr(sys, kind), + ) + raise + _nbclient.set_widgets_metadata() + + yield execute + + +def pytest_runtest_call(item): + """Run notebook code written in Python.""" + if "nbexec" in getattr(item, "fixturenames", ()): + nbexec = item.funcargs["nbexec"] + code = inspect.getsource(getattr(item.module, item.name.split("[")[0])) + code = code.splitlines() + ci = 0 + for ci, c in enumerate(code): + if c.startswith(" "): # actual content + break + code = "\n".join(code[ci:]) + + def run(nbexec=nbexec, code=code): + nbexec(code) + + item.runtest = run + return + + +@pytest.fixture( + params=( + [nirsport2, nirsport2_snirf, testing._pytest_param()], + [nirsport2_2021_9, nirsport2_20219_snirf, testing._pytest_param()], + ) +) +def nirx_snirf(request): + """Return a (raw_nirx, raw_snirf) matched pair.""" + pytest.importorskip("h5py") + skipper = request.param[2].marks[0].mark + if skipper.args[0]: # will skip + pytest.skip(skipper.kwargs["reason"]) + return ( + read_raw_nirx(request.param[0], preload=True), + read_raw_snirf(request.param[1], preload=True), + ) + + +@pytest.fixture +def qt_windows_closed(request): + """Ensure that no new Qt windows are open after a test.""" + _check_skip_backend("pyvistaqt") + app = _init_mne_qtapp() + + app.processEvents() + gc.collect() + n_before = len(app.topLevelWidgets()) + marks = set(mark.name for mark in request.node.iter_markers()) + yield + app.processEvents() + gc.collect() + if "allow_unclosed" in marks: + return + # Don't check when the test fails + if not _test_passed(request): + return + widgets = app.topLevelWidgets() + n_after = len(widgets) + assert n_before == n_after, widgets[-4:] + + +# https://docs.pytest.org/en/latest/example/simple.html#making-test-result-information-available-in-fixtures # noqa: E501 +_phase_report_key = StashKey() + + +@pytest.hookimpl(tryfirst=True, hookwrapper=True) +def pytest_runtest_makereport(item, call): + """Stash the status of each item and turn unexpected skips into errors.""" + outcome = yield + rep: pytest.TestReport = outcome.get_result() + item.stash.setdefault(_phase_report_key, {})[rep.when] = rep + if rep.outcome == "passed": # only check for skips etc. if otherwise green + _modify_report_skips(rep) + return rep + + +@pytest.hookimpl(tryfirst=True, hookwrapper=True) +def pytest_make_collect_report(collector: pytest.Collector): + """Turn unexpected skips during collection (e.g., module-level) into errors.""" + outcome = yield + rep: pytest.CollectReport = outcome.get_result() + _modify_report_skips(rep) + return rep + + +# Default means "allow all skips". Can use something like "$." to mean +# "never match", i.e., "treat all skips as errors" +_valid_skips_re = re.compile(os.getenv("MNE_TEST_ALLOW_SKIP", ".*")) + + +# To turn unexpected skips into errors, we need to look both at the collection phase +# (for decorated tests) and the call phase (for things like `importorskip` +# within the test body). code adapted from pytest-error-for-skips +def _modify_report_skips(report: pytest.TestReport | pytest.CollectReport): + if not report.skipped: + return + if isinstance(report.longrepr, tuple): + file, lineno, reason = report.longrepr + else: + file, lineno, reason = "", 1, str(report.longrepr) + if _valid_skips_re.match(reason): + return + assert isinstance(report, pytest.TestReport | pytest.CollectReport), type(report) + if file.endswith("doctest.py"): # _python/doctest.py + return + # xfail tests aren't true "skips" but show up as skipped in reports + if getattr(report, "keywords", {}).get("xfail", False): + return + # the above only catches marks, so we need to actually parse the report to catch + # an xfail based on the traceback + if " pytest.xfail( " in reason: + return + if reason.startswith("Skipped: "): + reason = reason[9:] + report.longrepr = f"{file}:{lineno}: UNEXPECTED SKIP: {reason}" + # Make it show up as an error in the report + report.outcome = "error" if isinstance(report, pytest.TestReport) else "failed" + + +@pytest.fixture(scope="function") +def eyetrack_cal(): + """Create a toy calibration instance.""" + screen_size = (0.4, 0.225) # width, height in meters + screen_resolution = (1920, 1080) + screen_distance = 0.7 # meters + onset = 0 + model = "HV9" + eye = "R" + avg_error = 0.5 + max_error = 1.0 + positions = np.zeros((9, 2)) + offsets = np.zeros((9,)) + gaze = np.zeros((9, 2)) + cal = mne.preprocessing.eyetracking.Calibration( + screen_size=screen_size, + screen_distance=screen_distance, + screen_resolution=screen_resolution, + eye=eye, + model=model, + positions=positions, + offsets=offsets, + gaze=gaze, + onset=onset, + avg_error=avg_error, + max_error=max_error, + ) + return cal + + +@pytest.fixture(scope="function") +def eyetrack_raw(): + """Create a toy raw instance with eyetracking channels.""" + # simulate a steady fixation at the center pixel of a 1920x1080 resolution screen + shape = (1, 100) # x or y, time + data = np.vstack([np.full(shape, 960), np.full(shape, 540), np.full(shape, 0)]) + + info = info = mne.create_info( + ch_names=["xpos", "ypos", "pupil"], sfreq=100, ch_types="eyegaze" + ) + more_info = dict( + xpos=("eyegaze", "px", "right", "x"), + ypos=("eyegaze", "px", "right", "y"), + pupil=("pupil", "au", "right"), + ) + raw = mne.io.RawArray(data, info) + raw = mne.preprocessing.eyetracking.set_channel_types_eyetrack(raw, more_info) + return raw diff --git a/mne-python/source/mne/coreg.py b/mne-python/source/mne/coreg.py new file mode 100644 index 0000000000000000000000000000000000000000..fdee5e5a0805fdd3cd682d66ae54ad8921c3c02e --- /dev/null +++ b/mne-python/source/mne/coreg.py @@ -0,0 +1,2305 @@ +"""Coregistration between different coordinate frames.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import configparser +import fnmatch +import os +import os.path as op +import re +import shutil +import stat +import sys +from copy import deepcopy +from functools import reduce +from glob import glob, iglob + +import numpy as np +from scipy.optimize import leastsq +from scipy.spatial.distance import cdist + +from ._fiff._digitization import _get_data_as_dict_from_dig +from ._fiff.constants import FIFF +from ._fiff.meas_info import Info, read_fiducials, read_info, write_fiducials + +# keep get_mni_fiducials for backward compat (no burden to keep in this +# namespace, too) +from ._freesurfer import ( + _read_mri_info, + estimate_head_mri_t, # noqa: F401 + get_mni_fiducials, +) +from .bem import read_bem_surfaces, write_bem_surfaces +from .channels import make_dig_montage +from .label import Label, read_label +from .source_space import ( + add_source_space_distances, + read_source_spaces, # noqa: F401 + write_source_spaces, +) +from .surface import ( + _DistanceQuery, + _normalize_vectors, + complete_surface_info, + decimate_surface, + read_surface, + write_surface, +) +from .transforms import ( + Transform, + _angle_between_quats, + _fit_matched_points, + _quat_to_euler, + _read_fs_xfm, + _write_fs_xfm, + apply_trans, + combine_transforms, + invert_transform, + rot_to_quat, + rotation, + rotation3d, + scaling, + translation, +) +from .utils import ( + _check_option, + _check_subject, + _import_nibabel, + _validate_type, + fill_doc, + get_config, + get_subjects_dir, + logger, + pformat, + verbose, + warn, +) +from .viz._3d import _fiducial_coords + +# some path templates +trans_fname = os.path.join("{raw_dir}", "{subject}-trans.fif") +subject_dirname = os.path.join("{subjects_dir}", "{subject}") +bem_dirname = os.path.join(subject_dirname, "bem") +mri_dirname = os.path.join(subject_dirname, "mri") +mri_transforms_dirname = os.path.join(subject_dirname, "mri", "transforms") +surf_dirname = os.path.join(subject_dirname, "surf") +bem_fname = os.path.join(bem_dirname, "{subject}-{name}.fif") +head_bem_fname = pformat(bem_fname, name="head") +head_sparse_fname = pformat(bem_fname, name="head-sparse") +fid_fname = pformat(bem_fname, name="fiducials") +fid_fname_general = os.path.join(bem_dirname, "{head}-fiducials.fif") +src_fname = os.path.join(bem_dirname, "{subject}-{spacing}-src.fif") +_head_fnames = ( + os.path.join(bem_dirname, "outer_skin.surf"), + head_sparse_fname, + head_bem_fname, +) +_high_res_head_fnames = ( + os.path.join(bem_dirname, "{subject}-head-dense.fif"), + os.path.join(surf_dirname, "lh.seghead"), + os.path.join(surf_dirname, "lh.smseghead"), +) + + +def _map_fid_name_to_idx(name: str) -> int: + """Map a fiducial name to its index in the DigMontage.""" + name = name.lower() + + if name == "lpa": + return 0 + elif name == "nasion": + return 1 + else: + assert name == "rpa" + return 2 + + +def _make_writable(fname): + """Make a file writable.""" + os.chmod(fname, stat.S_IMODE(os.lstat(fname)[stat.ST_MODE]) | 128) # write + + +def _make_writable_recursive(path): + """Recursively set writable.""" + if sys.platform.startswith("win"): + return # can't safely set perms + for root, dirs, files in os.walk(path, topdown=False): + for f in dirs + files: + _make_writable(os.path.join(root, f)) + + +def _find_head_bem(subject, subjects_dir, high_res=False): + """Find a high resolution head.""" + # XXX this should be refactored with mne.surface.get_head_surf ... + fnames = _high_res_head_fnames if high_res else _head_fnames + for fname in fnames: + path = fname.format(subjects_dir=subjects_dir, subject=subject) + if os.path.exists(path): + return path + + +@fill_doc +def coregister_fiducials(info, fiducials, tol=0.01): + """Create a head-MRI transform by aligning 3 fiducial points. + + Parameters + ---------- + %(info_not_none)s + fiducials : path-like | list of dict + Fiducials in MRI coordinate space (either path to a ``*-fiducials.fif`` + file or list of fiducials as returned by :func:`read_fiducials`. + + Returns + ------- + trans : Transform + The device-MRI transform. + + .. note:: The :class:`mne.Info` object fiducials must be in the + head coordinate space. + """ + if isinstance(info, str): + info = read_info(info) + if isinstance(fiducials, str): + fiducials, coord_frame_to = read_fiducials(fiducials) + else: + coord_frame_to = FIFF.FIFFV_COORD_MRI + frames_from = {d["coord_frame"] for d in info["dig"]} + if len(frames_from) > 1: + raise ValueError("info contains fiducials from different coordinate frames") + else: + coord_frame_from = frames_from.pop() + coords_from = _fiducial_coords(info["dig"]) + coords_to = _fiducial_coords(fiducials, coord_frame_to) + trans = fit_matched_points(coords_from, coords_to, tol=tol) + return Transform(coord_frame_from, coord_frame_to, trans) + + +@verbose +def create_default_subject(fs_home=None, update=False, subjects_dir=None, verbose=None): + """Create an average brain subject for subjects without structural MRI. + + Create a copy of fsaverage from the FreeSurfer directory in subjects_dir + and add auxiliary files from the mne package. + + Parameters + ---------- + fs_home : None | str + The FreeSurfer home directory (only needed if ``FREESURFER_HOME`` is + not specified as environment variable). + update : bool + In cases where a copy of the fsaverage brain already exists in the + subjects_dir, this option allows to only copy files that don't already + exist in the fsaverage directory. + subjects_dir : None | path-like + Override the ``SUBJECTS_DIR`` environment variable + (``os.environ['SUBJECTS_DIR']``) as destination for the new subject. + %(verbose)s + + Notes + ----- + When no structural MRI is available for a subject, an average brain can be + substituted. FreeSurfer comes with such an average brain model, and MNE + comes with some auxiliary files which make coregistration easier. + :py:func:`create_default_subject` copies the relevant + files from FreeSurfer into the current subjects_dir, and also adds the + auxiliary files provided by MNE. + """ + subjects_dir = str(get_subjects_dir(subjects_dir, raise_error=True)) + if fs_home is None: + fs_home = get_config("FREESURFER_HOME", fs_home) + if fs_home is None: + raise ValueError( + "FREESURFER_HOME environment variable not found. Please " + "specify the fs_home parameter in your call to " + "create_default_subject()." + ) + + # make sure FreeSurfer files exist + fs_src = os.path.join(fs_home, "subjects", "fsaverage") + if not os.path.exists(fs_src): + raise OSError( + f"fsaverage not found at {fs_src!r}. Is fs_home specified correctly?" + ) + for name in ("label", "mri", "surf"): + dirname = os.path.join(fs_src, name) + if not os.path.isdir(dirname): + raise OSError( + "FreeSurfer fsaverage seems to be incomplete: No directory named " + f"{name} found in {fs_src}" + ) + + # make sure destination does not already exist + dest = os.path.join(subjects_dir, "fsaverage") + if dest == fs_src: + raise OSError( + "Your subjects_dir points to the FreeSurfer subjects_dir " + f"({repr(subjects_dir)}). The default subject can not be created in the " + "FreeSurfer installation directory; please specify a different " + "subjects_dir." + ) + elif (not update) and os.path.exists(dest): + raise OSError( + 'Can not create fsaverage because "fsaverage" already exists in ' + f"subjects_dir {repr(subjects_dir)}. Delete or rename the existing " + "fsaverage subject folder." + ) + + # copy fsaverage from FreeSurfer + logger.info("Copying fsaverage subject from FreeSurfer directory...") + if (not update) or not os.path.exists(dest): + shutil.copytree(fs_src, dest) + _make_writable_recursive(dest) + + # copy files from mne + source_fname = os.path.join( + os.path.dirname(__file__), "data", "fsaverage", "fsaverage-%s.fif" + ) + dest_bem = os.path.join(dest, "bem") + if not os.path.exists(dest_bem): + os.mkdir(dest_bem) + logger.info("Copying auxiliary fsaverage files from mne...") + dest_fname = os.path.join(dest_bem, "fsaverage-%s.fif") + _make_writable_recursive(dest_bem) + for name in ("fiducials", "head", "inner_skull-bem", "trans"): + if not os.path.exists(dest_fname % name): + shutil.copy(source_fname % name, dest_bem) + + +def _decimate_points(pts, res=10): + """Decimate the number of points using a voxel grid. + + Create a voxel grid with a specified resolution and retain at most one + point per voxel. For each voxel, the point closest to its center is + retained. + + Parameters + ---------- + pts : array, shape (n_points, 3) + The points making up the head shape. + res : scalar + The resolution of the voxel space (side length of each voxel). + + Returns + ------- + pts : array, shape = (n_points, 3) + The decimated points. + """ + pts = np.asarray(pts) + + # find the bin edges for the voxel space + xmin, ymin, zmin = pts.min(0) - res / 2.0 + xmax, ymax, zmax = pts.max(0) + res + xax = np.arange(xmin, xmax, res) + yax = np.arange(ymin, ymax, res) + zax = np.arange(zmin, zmax, res) + + # find voxels containing one or more point + H, _ = np.histogramdd(pts, bins=(xax, yax, zax), density=False) + xbins, ybins, zbins = np.nonzero(H) + x = xax[xbins] + y = yax[ybins] + z = zax[zbins] + mids = np.c_[x, y, z] + res / 2.0 + + # each point belongs to at most one voxel center, so figure those out + # (KDTree faster than BallTree for these small problems) + tree = _DistanceQuery(mids, method="KDTree") + _, mid_idx = tree.query(pts) + + # then figure out which to actually use based on proximity + # (take advantage of sorting the mid_idx to get our mapping of + # pts to nearest voxel midpoint) + sort_idx = np.argsort(mid_idx) + bounds = np.cumsum(np.concatenate([[0], np.bincount(mid_idx, minlength=len(mids))])) + assert len(bounds) == len(mids) + 1 + out = list() + for mi, mid in enumerate(mids): + # Now we do this: + # + # use_pts = pts[mid_idx == mi] + # + # But it's faster for many points than making a big boolean indexer + # over and over (esp. since each point can only belong to a single + # voxel). + use_pts = pts[sort_idx[bounds[mi] : bounds[mi + 1]]] + if not len(use_pts): + out.append([np.inf] * 3) + else: + out.append(use_pts[np.argmin(cdist(use_pts, mid[np.newaxis])[:, 0])]) + out = np.array(out, float).reshape(-1, 3) + out = out[np.abs(out - mids).max(axis=1) < res / 2.0] + # """ + + return out + + +def _trans_from_params(param_info, params): + """Convert transformation parameters into a transformation matrix.""" + do_rotate, do_translate, do_scale = param_info + i = 0 + trans = [] + + if do_rotate: + x, y, z = params[:3] + trans.append(rotation(x, y, z)) + i += 3 + + if do_translate: + x, y, z = params[i : i + 3] + trans.insert(0, translation(x, y, z)) + i += 3 + + if do_scale == 1: + s = params[i] + trans.append(scaling(s, s, s)) + elif do_scale == 3: + x, y, z = params[i : i + 3] + trans.append(scaling(x, y, z)) + + trans = reduce(np.dot, trans) + return trans + + +_ALLOW_ANALITICAL = True + + +# XXX this function should be moved out of coreg as used elsewhere +def fit_matched_points( + src_pts, + tgt_pts, + rotate=True, + translate=True, + scale=False, + tol=None, + x0=None, + out="trans", + weights=None, +): + """Find a transform between matched sets of points. + + This minimizes the squared distance between two matching sets of points. + + Uses :func:`scipy.optimize.leastsq` to find a transformation involving + a combination of rotation, translation, and scaling (in that order). + + Parameters + ---------- + src_pts : array, shape = (n, 3) + Points to which the transform should be applied. + tgt_pts : array, shape = (n, 3) + Points to which src_pts should be fitted. Each point in tgt_pts should + correspond to the point in src_pts with the same index. + rotate : bool + Allow rotation of the ``src_pts``. + translate : bool + Allow translation of the ``src_pts``. + scale : bool + Number of scaling parameters. With False, points are not scaled. With + True, points are scaled by the same factor along all axes. + tol : scalar | None + The error tolerance. If the distance between any of the matched points + exceeds this value in the solution, a RuntimeError is raised. With + None, no error check is performed. + x0 : None | tuple + Initial values for the fit parameters. + out : 'params' | 'trans' + In what format to return the estimate: 'params' returns a tuple with + the fit parameters; 'trans' returns a transformation matrix of shape + (4, 4). + + Returns + ------- + trans : array, shape (4, 4) + Transformation that, if applied to src_pts, minimizes the squared + distance to tgt_pts. Only returned if out=='trans'. + params : array, shape (n_params, ) + A single tuple containing the rotation, translation, and scaling + parameters in that order (as applicable). + """ + src_pts = np.atleast_2d(src_pts) + tgt_pts = np.atleast_2d(tgt_pts) + if src_pts.shape != tgt_pts.shape: + raise ValueError( + "src_pts and tgt_pts must have same shape " + f"(got {src_pts.shape}, {tgt_pts.shape})" + ) + if weights is not None: + weights = np.asarray(weights, src_pts.dtype) + if weights.ndim != 1 or weights.size not in (src_pts.shape[0], 1): + raise ValueError( + f"weights (shape={weights.shape}) must be None or have shape " + f"({src_pts.shape[0]},)" + ) + weights = weights[:, np.newaxis] + + param_info = (bool(rotate), bool(translate), int(scale)) + del rotate, translate, scale + + # very common use case, rigid transformation (maybe with one scale factor, + # with or without weighted errors) + if param_info in ((True, True, 0), (True, True, 1)) and _ALLOW_ANALITICAL: + src_pts = np.asarray(src_pts, float) + tgt_pts = np.asarray(tgt_pts, float) + if weights is not None: + weights = np.asarray(weights, float) + x, s = _fit_matched_points(src_pts, tgt_pts, weights, bool(param_info[2])) + x[:3] = _quat_to_euler(x[:3]) + x = np.concatenate((x, [s])) if param_info[2] else x + else: + x = _generic_fit(src_pts, tgt_pts, param_info, weights, x0) + + # re-create the final transformation matrix + if (tol is not None) or (out == "trans"): + trans = _trans_from_params(param_info, x) + + # assess the error of the solution + if tol is not None: + src_pts = np.hstack((src_pts, np.ones((len(src_pts), 1)))) + est_pts = np.dot(src_pts, trans.T)[:, :3] + err = np.sqrt(np.sum((est_pts - tgt_pts) ** 2, axis=1)) + if np.any(err > tol): + raise RuntimeError(f"Error exceeds tolerance. Error = {err!r}") + + if out == "params": + return x + elif out == "trans": + return trans + else: + raise ValueError( + f"Invalid out parameter: {out!r}. Needs to be 'params' or 'trans'." + ) + + +def _generic_fit(src_pts, tgt_pts, param_info, weights, x0): + if param_info[1]: # translate + src_pts = np.hstack((src_pts, np.ones((len(src_pts), 1)))) + + if param_info == (True, False, 0): + + def error(x): + rx, ry, rz = x + trans = rotation3d(rx, ry, rz) + est = np.dot(src_pts, trans.T) + d = tgt_pts - est + if weights is not None: + d *= weights + return d.ravel() + + if x0 is None: + x0 = (0, 0, 0) + elif param_info == (True, True, 0): + + def error(x): + rx, ry, rz, tx, ty, tz = x + trans = np.dot(translation(tx, ty, tz), rotation(rx, ry, rz)) + est = np.dot(src_pts, trans.T)[:, :3] + d = tgt_pts - est + if weights is not None: + d *= weights + return d.ravel() + + if x0 is None: + x0 = (0, 0, 0, 0, 0, 0) + elif param_info == (True, True, 1): + + def error(x): + rx, ry, rz, tx, ty, tz, s = x + trans = reduce( + np.dot, + (translation(tx, ty, tz), rotation(rx, ry, rz), scaling(s, s, s)), + ) + est = np.dot(src_pts, trans.T)[:, :3] + d = tgt_pts - est + if weights is not None: + d *= weights + return d.ravel() + + if x0 is None: + x0 = (0, 0, 0, 0, 0, 0, 1) + elif param_info == (True, True, 3): + + def error(x): + rx, ry, rz, tx, ty, tz, sx, sy, sz = x + trans = reduce( + np.dot, + (translation(tx, ty, tz), rotation(rx, ry, rz), scaling(sx, sy, sz)), + ) + est = np.dot(src_pts, trans.T)[:, :3] + d = tgt_pts - est + if weights is not None: + d *= weights + return d.ravel() + + if x0 is None: + x0 = (0, 0, 0, 0, 0, 0, 1, 1, 1) + else: + raise NotImplementedError( + "The specified parameter combination is not implemented: " + "rotate={!r}, translate={!r}, scale={!r}".format(*param_info) + ) + + x, _, _, _, _ = leastsq(error, x0, full_output=True) + return x + + +def _find_label_paths(subject="fsaverage", pattern=None, subjects_dir=None): + """Find paths to label files in a subject's label directory. + + Parameters + ---------- + subject : str + Name of the mri subject. + pattern : str | None + Pattern for finding the labels relative to the label directory in the + MRI subject directory (e.g., "aparc/*.label" will find all labels + in the "subject/label/aparc" directory). With None, find all labels. + subjects_dir : None | path-like + Override the SUBJECTS_DIR environment variable + (sys.environ['SUBJECTS_DIR']) + + Returns + ------- + paths : list + List of paths relative to the subject's label directory + """ + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + subject_dir = subjects_dir / subject + lbl_dir = subject_dir / "label" + + if pattern is None: + paths = [] + for dirpath, _, filenames in os.walk(lbl_dir): + rel_dir = os.path.relpath(dirpath, lbl_dir) + for filename in fnmatch.filter(filenames, "*.label"): + path = os.path.join(rel_dir, filename) + paths.append(path) + else: + paths = [os.path.relpath(path, lbl_dir) for path in iglob(pattern)] + + return paths + + +def _find_mri_paths(subject, skip_fiducials, subjects_dir): + """Find all files of an mri relevant for source transformation. + + Parameters + ---------- + subject : str + Name of the mri subject. + skip_fiducials : bool + Do not scale the MRI fiducials. If False, an OSError will be raised + if no fiducials file can be found. + subjects_dir : None | path-like + Override the SUBJECTS_DIR environment variable + (sys.environ['SUBJECTS_DIR']) + + Returns + ------- + paths : dict + Dictionary whose keys are relevant file type names (str), and whose + values are lists of paths. + """ + subjects_dir = str(get_subjects_dir(subjects_dir, raise_error=True)) + paths = {} + + # directories to create + paths["dirs"] = [bem_dirname, surf_dirname] + + # surf/ files + paths["surf"] = [] + surf_fname = os.path.join(surf_dirname, "{name}") + surf_names = ( + "inflated", + "white", + "orig", + "orig_avg", + "inflated_avg", + "inflated_pre", + "pial", + "pial_avg", + "smoothwm", + "white_avg", + "seghead", + "smseghead", + ) + if os.getenv("_MNE_FEW_SURFACES", "") == "true": # for testing + surf_names = surf_names[:4] + for surf_name in surf_names: + for hemi in ("lh.", "rh."): + name = hemi + surf_name + path = surf_fname.format( + subjects_dir=subjects_dir, subject=subject, name=name + ) + if os.path.exists(path): + paths["surf"].append(pformat(surf_fname, name=name)) + surf_fname = os.path.join(bem_dirname, "{name}") + surf_names = ("inner_skull.surf", "outer_skull.surf", "outer_skin.surf") + for surf_name in surf_names: + path = surf_fname.format( + subjects_dir=subjects_dir, subject=subject, name=surf_name + ) + if os.path.exists(path): + paths["surf"].append(pformat(surf_fname, name=surf_name)) + del surf_names, surf_name, path, hemi + + # BEM files + paths["bem"] = bem = [] + path = head_bem_fname.format(subjects_dir=subjects_dir, subject=subject) + if os.path.exists(path): + bem.append("head") + bem_pattern = pformat( + bem_fname, subjects_dir=subjects_dir, subject=subject, name="*-bem" + ) + re_pattern = pformat( + bem_fname, subjects_dir=subjects_dir, subject=subject, name="(.+)" + ).replace("\\", "\\\\") + for path in iglob(bem_pattern): + match = re.match(re_pattern, path) + name = match.group(1) + bem.append(name) + del bem, path, bem_pattern, re_pattern + + # fiducials + if skip_fiducials: + paths["fid"] = [] + else: + paths["fid"] = _find_fiducials_files(subject, subjects_dir) + # check that we found at least one + if len(paths["fid"]) == 0: + raise OSError( + f"No fiducials file found for {subject}. The fiducials " + "file should be named " + "{subject}/bem/{subject}-fiducials.fif. In " + "order to scale an MRI without fiducials set " + "skip_fiducials=True." + ) + + # duplicate files (curvature and some surfaces) + paths["duplicate"] = [] + path = os.path.join(surf_dirname, "{name}") + surf_fname = os.path.join(surf_dirname, "{name}") + surf_dup_names = ("curv", "sphere", "sphere.reg", "sphere.reg.avg") + for surf_dup_name in surf_dup_names: + for hemi in ("lh.", "rh."): + name = hemi + surf_dup_name + path = surf_fname.format( + subjects_dir=subjects_dir, subject=subject, name=name + ) + if os.path.exists(path): + paths["duplicate"].append(pformat(surf_fname, name=name)) + del surf_dup_name, name, path, hemi + + # transform files (talairach) + paths["transforms"] = [] + transform_fname = os.path.join(mri_transforms_dirname, "talairach.xfm") + path = transform_fname.format(subjects_dir=subjects_dir, subject=subject) + if os.path.exists(path): + paths["transforms"].append(transform_fname) + del transform_fname, path + + # find source space files + paths["src"] = src = [] + bem_dir = bem_dirname.format(subjects_dir=subjects_dir, subject=subject) + fnames = fnmatch.filter(os.listdir(bem_dir), "*-src.fif") + prefix = subject + "-" + for fname in fnames: + if fname.startswith(prefix): + fname = f"{{subject}}-{fname[len(prefix) :]}" + path = os.path.join(bem_dirname, fname) + src.append(path) + + # find MRIs + mri_dir = mri_dirname.format(subjects_dir=subjects_dir, subject=subject) + fnames = fnmatch.filter(os.listdir(mri_dir), "*.mgz") + paths["mri"] = [os.path.join(mri_dir, f) for f in fnames] + + return paths + + +def _find_fiducials_files(subject, subjects_dir): + """Find fiducial files.""" + fid = [] + # standard fiducials + if os.path.exists(fid_fname.format(subjects_dir=subjects_dir, subject=subject)): + fid.append(fid_fname) + # fiducials with subject name + pattern = pformat( + fid_fname_general, subjects_dir=subjects_dir, subject=subject, head="*" + ) + regex = pformat( + fid_fname_general, subjects_dir=subjects_dir, subject=subject, head="(.+)" + ).replace("\\", "\\\\") + for path in iglob(pattern): + match = re.match(regex, path) + head = match.group(1).replace(subject, "{subject}") + fid.append(pformat(fid_fname_general, head=head)) + return fid + + +def _is_mri_subject(subject, subjects_dir=None): + """Check whether a directory in subjects_dir is an mri subject directory. + + Parameters + ---------- + subject : str + Name of the potential subject/directory. + subjects_dir : None | path-like + Override the SUBJECTS_DIR environment variable. + + Returns + ------- + is_mri_subject : bool + Whether ``subject`` is an mri subject. + """ + subjects_dir = str(get_subjects_dir(subjects_dir, raise_error=True)) + return bool( + _find_head_bem(subject, subjects_dir) + or _find_head_bem(subject, subjects_dir, high_res=True) + ) + + +def _mri_subject_has_bem(subject, subjects_dir=None): + """Check whether an mri subject has a file matching the bem pattern. + + Parameters + ---------- + subject : str + Name of the subject. + subjects_dir : None | path-like + Override the SUBJECTS_DIR environment variable. + + Returns + ------- + has_bem_file : bool + Whether ``subject`` has a bem file. + """ + subjects_dir = str(get_subjects_dir(subjects_dir, raise_error=True)) + pattern = bem_fname.format(subjects_dir=subjects_dir, subject=subject, name="*-bem") + fnames = glob(pattern) + return bool(len(fnames)) + + +def read_mri_cfg(subject, subjects_dir=None): + """Read information from the cfg file of a scaled MRI brain. + + Parameters + ---------- + subject : str + Name of the scaled MRI subject. + subjects_dir : None | path-like + Override the ``SUBJECTS_DIR`` environment variable. + + Returns + ------- + cfg : dict + Dictionary with entries from the MRI's cfg file. + """ + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + fname = subjects_dir / subject / "MRI scaling parameters.cfg" + + if not fname.exists(): + raise OSError( + f"{subject!r} does not seem to be a scaled mri subject: {fname!r} does not" + "exist." + ) + + logger.info(f"Reading MRI cfg file {fname}") + config = configparser.RawConfigParser() + config.read(fname) + n_params = config.getint("MRI Scaling", "n_params") + if n_params == 1: + scale = config.getfloat("MRI Scaling", "scale") + elif n_params == 3: + scale_str = config.get("MRI Scaling", "scale") + scale = np.array([float(s) for s in scale_str.split()]) + else: + raise ValueError(f"Invalid n_params value in MRI cfg: {n_params}") + + out = { + "subject_from": config.get("MRI Scaling", "subject_from"), + "n_params": n_params, + "scale": scale, + } + return out + + +def _write_mri_config(fname, subject_from, subject_to, scale): + """Write the cfg file describing a scaled MRI subject. + + Parameters + ---------- + fname : path-like + Target file. + subject_from : str + Name of the source MRI subject. + subject_to : str + Name of the scaled MRI subject. + scale : float | array_like, shape = (3,) + The scaling parameter. + """ + scale = np.asarray(scale) + if np.isscalar(scale) or scale.shape == (): + n_params = 1 + else: + n_params = 3 + + config = configparser.RawConfigParser() + config.add_section("MRI Scaling") + config.set("MRI Scaling", "subject_from", subject_from) + config.set("MRI Scaling", "subject_to", subject_to) + config.set("MRI Scaling", "n_params", str(n_params)) + if n_params == 1: + config.set("MRI Scaling", "scale", str(scale)) + else: + config.set("MRI Scaling", "scale", " ".join([str(s) for s in scale])) + config.set("MRI Scaling", "version", "1") + with open(fname, "w") as fid: + config.write(fid) + + +def _scale_params(subject_to, subject_from, scale, subjects_dir): + """Assemble parameters for scaling. + + Returns + ------- + subjects_dir : path-like + Subjects directory. + subject_from : str + Name of the source subject. + scale : array + Scaling factor, either shape=() for uniform scaling or shape=(3,) for + non-uniform scaling. + uniform : bool + Whether scaling is uniform. + """ + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + if (subject_from is None) != (scale is None): + raise TypeError( + "Need to provide either both subject_from and scale parameters, or neither." + ) + + if subject_from is None: + cfg = read_mri_cfg(subject_to, subjects_dir) + subject_from = cfg["subject_from"] + n_params = cfg["n_params"] + assert n_params in (1, 3) + scale = cfg["scale"] + scale = np.atleast_1d(scale) + if scale.ndim != 1 or scale.shape[0] not in (1, 3): + raise ValueError( + "Invalid shape for scale parameter. Need scalar or array of length 3. Got " + f"shape {scale.shape}." + ) + n_params = len(scale) + return str(subjects_dir), subject_from, scale, n_params == 1 + + +@verbose +def scale_bem( + subject_to, + bem_name, + subject_from=None, + scale=None, + subjects_dir=None, + *, + on_defects="raise", + verbose=None, +): + """Scale a bem file. + + Parameters + ---------- + subject_to : str + Name of the scaled MRI subject (the destination mri subject). + bem_name : str + Name of the bem file. For example, to scale + ``fsaverage-inner_skull-bem.fif``, the bem_name would be + "inner_skull-bem". + subject_from : None | str + The subject from which to read the source space. If None, subject_from + is read from subject_to's config file. + scale : None | float | array, shape = (3,) + Scaling factor. Has to be specified if subjects_from is specified, + otherwise it is read from subject_to's config file. + subjects_dir : None | str + Override the SUBJECTS_DIR environment variable. + %(on_defects)s + + .. versionadded:: 1.0 + %(verbose)s + """ + subjects_dir, subject_from, scale, uniform = _scale_params( + subject_to, subject_from, scale, subjects_dir + ) + + src = bem_fname.format( + subjects_dir=subjects_dir, subject=subject_from, name=bem_name + ) + dst = bem_fname.format(subjects_dir=subjects_dir, subject=subject_to, name=bem_name) + + if os.path.exists(dst): + raise OSError(f"File already exists: {dst}") + + surfs = read_bem_surfaces(src, on_defects=on_defects) + for surf in surfs: + surf["rr"] *= scale + if not uniform: + assert len(surf["nn"]) > 0 + surf["nn"] /= scale + _normalize_vectors(surf["nn"]) + write_bem_surfaces(dst, surfs) + + +def scale_labels( + subject_to, + pattern=None, + overwrite=False, + subject_from=None, + scale=None, + subjects_dir=None, +): + r"""Scale labels to match a brain that was previously created by scaling. + + Parameters + ---------- + subject_to : str + Name of the scaled MRI subject (the destination brain). + pattern : str | None + Pattern for finding the labels relative to the label directory in the + MRI subject directory (e.g., "lh.BA3a.label" will scale + "fsaverage/label/lh.BA3a.label"; "aparc/\*.label" will find all labels + in the "fsaverage/label/aparc" directory). With None, scale all labels. + overwrite : bool + Overwrite any label file that already exists for subject_to (otherwise + existing labels are skipped). + subject_from : None | str + Name of the original MRI subject (the brain that was scaled to create + subject_to). If None, the value is read from subject_to's cfg file. + scale : None | float | array_like, shape = (3,) + Scaling parameter. If None, the value is read from subject_to's cfg + file. + subjects_dir : None | path-like + Override the ``SUBJECTS_DIR`` environment variable. + """ + subjects_dir, subject_from, scale, _ = _scale_params( + subject_to, subject_from, scale, subjects_dir + ) + + # find labels + paths = _find_label_paths(subject_from, pattern, subjects_dir) + if not paths: + return + + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + src_root = subjects_dir / subject_from / "label" + dst_root = subjects_dir / subject_to / "label" + + # scale labels + for fname in paths: + dst = dst_root / fname + if not overwrite and dst.exists(): + continue + + if not dst.parent.exists(): + os.makedirs(dst.parent) + + src = src_root / fname + l_old = read_label(src) + pos = l_old.pos * scale + l_new = Label( + l_old.vertices, + pos, + l_old.values, + l_old.hemi, + l_old.comment, + subject=subject_to, + ) + l_new.save(dst) + + +@verbose +def scale_mri( + subject_from, + subject_to, + scale, + overwrite=False, + subjects_dir=None, + skip_fiducials=False, + labels=True, + annot=False, + *, + on_defects="raise", + mri_fiducials=None, + verbose=None, +): + """Create a scaled copy of an MRI subject. + + Parameters + ---------- + subject_from : str + Name of the subject providing the MRI. + subject_to : str + New subject name for which to save the scaled MRI. + scale : float | array_like, shape = (3,) + The scaling factor (one or 3 parameters). + overwrite : bool + If an MRI already exists for subject_to, overwrite it. + subjects_dir : None | path-like + Override the ``SUBJECTS_DIR`` environment variable. + skip_fiducials : bool + Do not scale the MRI fiducials. If False (default), an OSError will be + raised if no fiducials file can be found. + labels : bool + Also scale all labels (default True). + annot : bool + Copy ``*.annot`` files to the new location (default False). + %(on_defects)s + + .. versionadded:: 1.0 + mri_fiducials : None | list of dict + If provided, these fiducials will be used as the originals to scale instead + of reading from ``{subject_from}/bem/{subject_from}-fiducials.fif``. + This is useful typically when using ``mne coreg`` or similar and you have + modified the MRI fiducials interactively, but have not saved them to disk. + + .. versionadded:: 1.12 + %(verbose)s + + See Also + -------- + scale_bem : Add a scaled BEM to a scaled MRI. + scale_labels : Add labels to a scaled MRI. + scale_source_space : Add a source space to a scaled MRI. + + Notes + ----- + This function will automatically call :func:`scale_bem`, + :func:`scale_labels`, and :func:`scale_source_space` based on expected + filename patterns in the subject directory. + """ + subjects_dir = str(get_subjects_dir(subjects_dir, raise_error=True)) + paths = _find_mri_paths(subject_from, skip_fiducials, subjects_dir) + scale = np.atleast_1d(scale) + if scale.shape == (3,): + if np.isclose(scale[1], scale[0]) and np.isclose(scale[2], scale[0]): + scale = scale[0] # speed up scaling conditionals using a singleton + elif scale.shape != (1,): + raise ValueError(f"scale must have shape (3,) or (1,), got {scale.shape}") + _validate_type(mri_fiducials, (list, tuple, None), "mri_fiducials") + if mri_fiducials is not None: + _check_option("len(mri_fiducials)", len(mri_fiducials), (3,)) + want_fids = [ + FIFF.FIFFV_POINT_LPA, + FIFF.FIFFV_POINT_NASION, + FIFF.FIFFV_POINT_RPA, + ] + for fi, fid in enumerate(mri_fiducials): + fid_name = f"mri_fiducials[{fi}]" + _validate_type(fid, dict, fid_name) + for key in ("r", "coord_frame", "ident"): + if key not in fid: + raise ValueError(f"{fid_name} is missing the '{key}' key") + if fid["coord_frame"] != FIFF.FIFFV_COORD_MRI: + raise ValueError( + f"{fid_name}['coord_frame'] must be 'mri', got {fid['coord_frame']}" + ) + _check_option( + f"{fid_name}['kind']", fid["kind"], (FIFF.FIFFV_POINT_CARDINAL,) + ) + _check_option(f"{fid_name}['ident']", fid["ident"], (want_fids[fi],)) + + # make sure we have an empty target directory + dest = subject_dirname.format(subject=subject_to, subjects_dir=subjects_dir) + if os.path.exists(dest): + if not overwrite: + raise OSError( + f"Subject directory for {subject_to} already exists: {dest!r}" + ) + shutil.rmtree(dest) + + logger.debug("create empty directory structure") + for dirname in paths["dirs"]: + dir_ = dirname.format(subject=subject_to, subjects_dir=subjects_dir) + os.makedirs(dir_) + + logger.debug("save MRI scaling parameters") + fname = os.path.join(dest, "MRI scaling parameters.cfg") + _write_mri_config(fname, subject_from, subject_to, scale) + + logger.debug("surf files [in mm]") + for fname in paths["surf"]: + src = fname.format(subject=subject_from, subjects_dir=subjects_dir) + src = os.path.realpath(src) + dest = fname.format(subject=subject_to, subjects_dir=subjects_dir) + pts, tri = read_surface(src) + write_surface(dest, pts * scale, tri) + + logger.debug("BEM files [in m]") + for bem_name in paths["bem"]: + scale_bem( + subject_to, + bem_name, + subject_from, + scale, + subjects_dir, + on_defects=on_defects, + verbose=False, + ) + + logger.debug("fiducials [in m]") + for fname in paths["fid"]: + src = fname.format(subject=subject_from, subjects_dir=subjects_dir) + src = os.path.realpath(src) + pts, cframe = read_fiducials(src, verbose=False) + for pt in pts: + pt["r"] = pt["r"] * scale + dest = fname.format(subject=subject_to, subjects_dir=subjects_dir) + write_fiducials(dest, pts, cframe, overwrite=True, verbose=False) + + # It is redundant to put this after the paths["fid"] loop, but it's simple, faster + # enough, and cleaner to just write it here (rather than adding conditionals to find + # the correct file above etc.) + if mri_fiducials is not None: + dest = os.path.join( + bem_dirname.format(subjects_dir=subjects_dir, subject=subject_to), + f"{subject_to}-fiducials.fif", + ) + use_mri_fiducials = deepcopy(mri_fiducials) + for fid in use_mri_fiducials: + fid["r"] = fid["r"] * scale + write_fiducials( + dest, use_mri_fiducials, FIFF.FIFFV_COORD_MRI, overwrite=True, verbose=False + ) + + logger.debug("MRIs [nibabel]") + os.mkdir(mri_dirname.format(subjects_dir=subjects_dir, subject=subject_to)) + for fname in paths["mri"]: + mri_name = os.path.basename(fname) + _scale_mri(subject_to, mri_name, subject_from, scale, subjects_dir) + + logger.debug("Transforms") + for mri_name in paths["mri"]: + if mri_name.endswith("T1.mgz"): + os.mkdir( + mri_transforms_dirname.format( + subjects_dir=subjects_dir, subject=subject_to + ) + ) + for fname in paths["transforms"]: + xfm_name = os.path.basename(fname) + _scale_xfm( + subject_to, xfm_name, mri_name, subject_from, scale, subjects_dir + ) + break + + logger.debug("duplicate files") + for fname in paths["duplicate"]: + src = fname.format(subject=subject_from, subjects_dir=subjects_dir) + dest = fname.format(subject=subject_to, subjects_dir=subjects_dir) + shutil.copyfile(src, dest) + + logger.debug("source spaces") + for fname in paths["src"]: + src_name = os.path.basename(fname) + scale_source_space( + subject_to, src_name, subject_from, scale, subjects_dir, verbose=False + ) + + logger.debug("labels [in m]") + os.mkdir(os.path.join(subjects_dir, subject_to, "label")) + if labels: + scale_labels( + subject_to, + subject_from=subject_from, + scale=scale, + subjects_dir=subjects_dir, + ) + + logger.debug("copy *.annot files") + # they don't contain scale-dependent information + if annot: + src_pattern = os.path.join(subjects_dir, subject_from, "label", "*.annot") + dst_dir = os.path.join(subjects_dir, subject_to, "label") + for src_file in iglob(src_pattern): + shutil.copy(src_file, dst_dir) + + +@verbose +def scale_source_space( + subject_to, + src_name, + subject_from=None, + scale=None, + subjects_dir=None, + n_jobs=None, + verbose=None, +): + """Scale a source space for an mri created with scale_mri(). + + Parameters + ---------- + subject_to : str + Name of the scaled MRI subject (the destination mri subject). + src_name : str + Source space name. Can be a spacing parameter (e.g., ``'7'``, + ``'ico4'``, ``'oct6'``) or a file name of a source space file relative + to the bem directory; if the file name contains the subject name, it + should be indicated as "{subject}" in ``src_name`` (e.g., + ``"{subject}-my_source_space-src.fif"``). + subject_from : None | str + The subject from which to read the source space. If None, subject_from + is read from subject_to's config file. + scale : None | float | array, shape = (3,) + Scaling factor. Has to be specified if subjects_from is specified, + otherwise it is read from subject_to's config file. + subjects_dir : None | str + Override the SUBJECTS_DIR environment variable. + n_jobs : int + Number of jobs to run in parallel if recomputing distances (only + applies if scale is an array of length 3, and will not use more cores + than there are source spaces). + %(verbose)s + + Notes + ----- + When scaling volume source spaces, the source (vertex) locations are + scaled, but the reference to the MRI volume is left unchanged. Transforms + are updated so that source estimates can be plotted on the original MRI + volume. + """ + subjects_dir, subject_from, scale, uniform = _scale_params( + subject_to, subject_from, scale, subjects_dir + ) + # if n_params==1 scale is a scalar; if n_params==3 scale is a (3,) array + + # find the source space file names + if src_name.isdigit(): + spacing = src_name # spacing in mm + src_pattern = src_fname + else: + match = re.match(r"(oct|ico|vol)-?(\d+)$", src_name) + if match: + spacing = "-".join(match.groups()) + src_pattern = src_fname + else: + spacing = None + src_pattern = os.path.join(bem_dirname, src_name) + + src = src_pattern.format( + subjects_dir=subjects_dir, subject=subject_from, spacing=spacing + ) + dst = src_pattern.format( + subjects_dir=subjects_dir, subject=subject_to, spacing=spacing + ) + + # read and scale the source space [in m] + sss = read_source_spaces(src) + logger.info("scaling source space %s: %s -> %s", spacing, subject_from, subject_to) + logger.info("Scale factor: %s", scale) + add_dist = False + for ss in sss: + ss["subject_his_id"] = subject_to + ss["rr"] *= scale + # additional tags for volume source spaces + for key in ("vox_mri_t", "src_mri_t"): + # maintain transform to original MRI volume ss['mri_volume_name'] + if key in ss: + ss[key]["trans"][:3] *= scale[:, np.newaxis] + # distances and patch info + if uniform: + if ss["dist"] is not None: + ss["dist"] *= scale[0] + # Sometimes this is read-only due to how it's read + ss["nearest_dist"] = ss["nearest_dist"] * scale + ss["dist_limit"] = ss["dist_limit"] * scale + else: # non-uniform scaling + ss["nn"] /= scale + _normalize_vectors(ss["nn"]) + if ss["dist"] is not None: + add_dist = True + dist_limit = float(np.abs(sss[0]["dist_limit"])) + elif ss["nearest"] is not None: + add_dist = True + dist_limit = 0 + + if add_dist: + logger.info("Recomputing distances, this might take a while") + add_source_space_distances(sss, dist_limit, n_jobs) + + write_source_spaces(dst, sss) + + +def _scale_mri(subject_to, mri_fname, subject_from, scale, subjects_dir): + """Scale an MRI by setting its affine.""" + subjects_dir, subject_from, scale, _ = _scale_params( + subject_to, subject_from, scale, subjects_dir + ) + nibabel = _import_nibabel("scale an MRI") + fname_from = op.join( + mri_dirname.format(subjects_dir=subjects_dir, subject=subject_from), mri_fname + ) + fname_to = op.join( + mri_dirname.format(subjects_dir=subjects_dir, subject=subject_to), mri_fname + ) + img = nibabel.load(fname_from) + zooms = np.array(img.header.get_zooms()) + zooms[[0, 2, 1]] *= scale + img.header.set_zooms(zooms) + # Hack to fix nibabel problems, see + # https://github.com/nipy/nibabel/issues/619 + img._affine = img.header.get_affine() # or could use None + nibabel.save(img, fname_to) + + +def _scale_xfm(subject_to, xfm_fname, mri_name, subject_from, scale, subjects_dir): + """Scale a transform.""" + subjects_dir, subject_from, scale, _ = _scale_params( + subject_to, subject_from, scale, subjects_dir + ) + + # The nibabel warning should already be there in MRI step, if applicable, + # as we only get here if T1.mgz is present (and thus a scaling was + # attempted) so we can silently return here. + fname_from = os.path.join( + mri_transforms_dirname.format(subjects_dir=subjects_dir, subject=subject_from), + xfm_fname, + ) + fname_to = op.join( + mri_transforms_dirname.format(subjects_dir=subjects_dir, subject=subject_to), + xfm_fname, + ) + assert op.isfile(fname_from), fname_from + assert op.isdir(op.dirname(fname_to)), op.dirname(fname_to) + # The "talairach.xfm" file stores the ras_mni transform. + # + # For "from" subj F, "to" subj T, F->T scaling S, some equivalent vertex + # positions F_x and T_x in MRI (FreeSurfer RAS) coords, knowing that + # we have T_x = S @ F_x, we want to have the same MNI coords computed + # for these vertices: + # + # T_mri_mni @ T_x = F_mri_mni @ F_x + # + # We need to find the correct T_ras_mni (talaraich.xfm file) that yields + # this. So we derive (where † indicates inversion): + # + # T_mri_mni @ S @ F_x = F_mri_mni @ F_x + # T_mri_mni @ S = F_mri_mni + # T_ras_mni @ T_mri_ras @ S = F_ras_mni @ F_mri_ras + # T_ras_mni @ T_mri_ras = F_ras_mni @ F_mri_ras @ S⁻¹ + # T_ras_mni = F_ras_mni @ F_mri_ras @ S⁻¹ @ T_ras_mri + # + + # prepare the scale (S) transform + scale = np.atleast_1d(scale) + scale = np.tile(scale, 3) if len(scale) == 1 else scale + S = Transform("mri", "mri", scaling(*scale)) # F_mri->T_mri + + # + # Get the necessary transforms of the "from" subject + # + xfm, kind = _read_fs_xfm(fname_from) + assert kind == "MNI Transform File", kind + _, _, F_mri_ras, _, _ = _read_mri_info(mri_name, units="mm") + F_ras_mni = Transform("ras", "mni_tal", xfm) + del xfm + + # + # Get the necessary transforms of the "to" subject + # + mri_name = op.join( + mri_dirname.format(subjects_dir=subjects_dir, subject=subject_to), + op.basename(mri_name), + ) + _, _, T_mri_ras, _, _ = _read_mri_info(mri_name, units="mm") + T_ras_mri = invert_transform(T_mri_ras) + del mri_name, T_mri_ras + + # Finally we construct as above: + # + # T_ras_mni = F_ras_mni @ F_mri_ras @ S⁻¹ @ T_ras_mri + # + # By moving right to left through the equation. + T_ras_mni = combine_transforms( + combine_transforms( + combine_transforms(T_ras_mri, invert_transform(S), "ras", "mri"), + F_mri_ras, + "ras", + "ras", + ), + F_ras_mni, + "ras", + "mni_tal", + ) + _write_fs_xfm(fname_to, T_ras_mni["trans"], kind) + + +def _read_surface(filename, *, on_defects): + bem = dict() + if filename is not None and op.exists(filename): + if filename.endswith(".fif"): + bem = read_bem_surfaces(filename, on_defects=on_defects, verbose=False)[0] + else: + try: + bem = read_surface(filename, return_dict=True)[2] + bem["rr"] *= 1e-3 + complete_surface_info(bem, copy=False) + except Exception: + raise ValueError( + f"Error loading surface from {filename} (see Terminal for details)." + ) + return bem + + +@fill_doc +class Coregistration: + """Class for MRI<->head coregistration. + + Parameters + ---------- + info : instance of Info | None + The measurement info. + %(subject)s + %(subjects_dir)s + %(fiducials)s + %(on_defects)s + + .. versionadded:: 1.0 + + Attributes + ---------- + fiducials : instance of DigMontage + A montage containing the MRI fiducials. + trans : instance of Transform + MRI<->Head coordinate transformation. + + See Also + -------- + mne.scale_mri + + Notes + ----- + Internal computation quantities parameters are in the following units: + + - rotation are in radians + - translation are in m + - scale are in scale proportion + + If using a scale mode, the :func:`~mne.scale_mri` should be used + to create a surrogate MRI subject with the proper scale factors. + """ + + def __init__( + self, info, subject, subjects_dir=None, fiducials="auto", *, on_defects="raise" + ): + _validate_type(info, (Info, None), "info") + self._info = info + self._subject = _check_subject(subject, subject) + self._subjects_dir = str(get_subjects_dir(subjects_dir, raise_error=True)) + self._scale_mode = None + self._on_defects = on_defects + + self._default_parameters = np.array( + [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0] + ) + + self._rotation = self._default_parameters[:3] + self._translation = self._default_parameters[3:6] + self._scale = self._default_parameters[6:9] + self._icp_angle = 0.2 + self._icp_distance = 0.2 + self._icp_scale = 0.2 + self._icp_fid_matches = ("nearest", "matched") + self._icp_fid_match = self._icp_fid_matches[0] + self._lpa_weight = 1.0 + self._nasion_weight = 10.0 + self._rpa_weight = 1.0 + self._hsp_weight = 1.0 + self._eeg_weight = 1.0 + self._hpi_weight = 1.0 + self._extra_points_filter = None + + self._setup_digs() + self._setup_bem() + + self._fid_filename = None + self._setup_fiducials(fiducials) + self.reset() + + def _setup_digs(self): + if self._info is None: + self._dig_dict = dict( + hpi=np.zeros((1, 3)), + dig_ch_pos_location=np.zeros((1, 3)), + hsp=np.zeros((1, 3)), + rpa=np.zeros((1, 3)), + nasion=np.zeros((1, 3)), + lpa=np.zeros((1, 3)), + ) + else: + self._dig_dict = _get_data_as_dict_from_dig( + dig=self._info["dig"], exclude_ref_channel=False + ) + # adjustments: + # set weights to 0 for None input + # convert fids to float arrays + for k, w_atr in zip( + ["nasion", "lpa", "rpa", "hsp", "hpi"], + [ + "_nasion_weight", + "_lpa_weight", + "_rpa_weight", + "_hsp_weight", + "_hpi_weight", + ], + ): + if self._dig_dict[k] is None: + self._dig_dict[k] = np.zeros((0, 3)) + setattr(self, w_atr, 0) + elif k in ["rpa", "nasion", "lpa"]: + self._dig_dict[k] = np.array([self._dig_dict[k]], float) + + def _setup_bem(self): + # find high-res head model (if possible) + high_res_path = _find_head_bem(self._subject, self._subjects_dir, high_res=True) + low_res_path = _find_head_bem(self._subject, self._subjects_dir, high_res=False) + if high_res_path is None and low_res_path is None: + raise RuntimeError( + "No standard head model was " + f"found for subject {self._subject} in " + f"{self._subjects_dir}" + ) + if high_res_path is not None: + self._bem_high_res = _read_surface( + high_res_path, on_defects=self._on_defects + ) + logger.info(f"Using high resolution head model in {high_res_path}") + else: + self._bem_high_res = _read_surface( + low_res_path, on_defects=self._on_defects + ) + logger.info(f"Using low resolution head model in {low_res_path}") + if low_res_path is None: + # This should be very rare! + warn( + "No low-resolution head found, decimating high resolution " + f"mesh ({len(self._bem_high_res['rr'])} vertices): {high_res_path}" + ) + # Create one from the high res one, which we know we have + rr, tris = decimate_surface( + self._bem_high_res["rr"], self._bem_high_res["tris"], n_triangles=5120 + ) + # directly set the attributes of bem_low_res + self._bem_low_res = complete_surface_info( + dict(rr=rr, tris=tris), copy=False, verbose=False + ) + else: + self._bem_low_res = _read_surface(low_res_path, on_defects=self._on_defects) + + def _setup_fiducials(self, fids): + _validate_type(fids, (str, dict, list)) + # find fiducials file + fid_accurate = None + if fids == "auto": + fid_files = _find_fiducials_files(self._subject, self._subjects_dir) + if len(fid_files) > 0: + # Read fiducials from disk + fid_filename = fid_files[0].format( + subjects_dir=self._subjects_dir, subject=self._subject + ) + logger.info(f"Using fiducials from: {fid_filename}.") + fids, _ = read_fiducials(fid_filename) + fid_accurate = True + self._fid_filename = fid_filename + else: + fids = "estimated" + + if fids == "estimated": + logger.info("Estimating fiducials from fsaverage.") + fid_accurate = False + fids = get_mni_fiducials(self._subject, self._subjects_dir) + + fid_accurate = True if fid_accurate is None else fid_accurate + if isinstance(fids, list): + fid_coords = _fiducial_coords(fids) + else: + assert isinstance(fids, dict) + fid_coords = np.array( + [fids["lpa"], fids["nasion"], fids["rpa"]], dtype=float + ) + + self._fid_points = fid_coords + self._fid_accurate = fid_accurate + + # does not seem to happen by itself ... so hard code it: + self._reset_fiducials() + + def _reset_fiducials(self): + dig_montage = make_dig_montage( + lpa=self._fid_points[0], + nasion=self._fid_points[1], + rpa=self._fid_points[2], + coord_frame="mri", + ) + self.fiducials = dig_montage + + def _update_params(self, rot=None, tra=None, sca=None, force_update=False): + if force_update and tra is None: + tra = self._translation + rot_changed = False + if rot is not None: + rot_changed = True + self._last_rotation = self._rotation.copy() + self._rotation = rot + tra_changed = False + if rot_changed or tra is not None: + if tra is None: + tra = self._translation + tra_changed = True + self._last_translation = self._translation.copy() + self._translation = tra + self._head_mri_t = rotation(*self._rotation).T + self._head_mri_t[:3, 3] = -np.dot(self._head_mri_t[:3, :3], tra) + self._transformed_dig_hpi = apply_trans( + self._head_mri_t, self._dig_dict["hpi"] + ) + self._transformed_dig_eeg = apply_trans( + self._head_mri_t, self._dig_dict["dig_ch_pos_location"] + ) + self._transformed_dig_extra = apply_trans( + self._head_mri_t, self._filtered_extra_points + ) + self._transformed_orig_dig_extra = apply_trans( + self._head_mri_t, self._dig_dict["hsp"] + ) + self._mri_head_t = rotation(*self._rotation) + self._mri_head_t[:3, 3] = np.array(tra) + if tra_changed or sca is not None: + if sca is None: + sca = self._scale + self._last_scale = self._scale.copy() + self._scale = sca + self._mri_trans = np.eye(4) + self._mri_trans[:, :3] *= sca + self._transformed_high_res_mri_points = apply_trans( + self._mri_trans, self._processed_high_res_mri_points + ) + self._update_nearest_calc() + + if tra_changed: + self._nearest_transformed_high_res_mri_idx_orig_hsp = ( + self._nearest_calc.query(self._transformed_orig_dig_extra)[1] + ) + self._nearest_transformed_high_res_mri_idx_hpi = self._nearest_calc.query( + self._transformed_dig_hpi + )[1] + self._nearest_transformed_high_res_mri_idx_eeg = self._nearest_calc.query( + self._transformed_dig_eeg + )[1] + self._nearest_transformed_high_res_mri_idx_rpa = self._nearest_calc.query( + apply_trans(self._head_mri_t, self._dig_dict["rpa"]) + )[1] + self._nearest_transformed_high_res_mri_idx_nasion = ( + self._nearest_calc.query( + apply_trans(self._head_mri_t, self._dig_dict["nasion"]) + )[1] + ) + self._nearest_transformed_high_res_mri_idx_lpa = self._nearest_calc.query( + apply_trans(self._head_mri_t, self._dig_dict["lpa"]) + )[1] + + def set_scale_mode(self, scale_mode): + """Select how to fit the scale parameters. + + Parameters + ---------- + scale_mode : None | str + The scale mode can be 'uniform', '3-axis' or disabled. + Defaults to None. + + * 'uniform': 1 scale factor is recovered. + * '3-axis': 3 scale factors are recovered. + * None: do not scale the MRI. + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + self._scale_mode = scale_mode + return self + + def set_grow_hair(self, value): + """Compensate for hair on the digitizer head shape. + + Parameters + ---------- + value : float + Move the back of the MRI head outwards by ``value`` (mm). + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + self._grow_hair = value + self._update_params(force_update=True) + return self + + def set_rotation(self, rot): + """Set the rotation parameter. + + Parameters + ---------- + rot : array, shape (3,) + The rotation parameter (in radians). + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + self._update_params(rot=np.array(rot)) + return self + + def set_translation(self, tra): + """Set the translation parameter. + + Parameters + ---------- + tra : array, shape (3,) + The translation parameter (in m.). + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + self._update_params(tra=np.array(tra)) + return self + + def set_scale(self, sca): + """Set the scale parameter. + + Parameters + ---------- + sca : array, shape (3,) + The scale parameter. + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + self._update_params(sca=np.array(sca)) + return self + + def _update_nearest_calc(self): + self._nearest_calc = _DistanceQuery( + self._processed_high_res_mri_points * self._scale + ) + + @property + def _filtered_extra_points(self): + if self._extra_points_filter is None: + return self._dig_dict["hsp"] + else: + return self._dig_dict["hsp"][self._extra_points_filter] + + @property + def _parameters(self): + return np.concatenate((self._rotation, self._translation, self._scale)) + + @property + def _last_parameters(self): + return np.concatenate( + (self._last_rotation, self._last_translation, self._last_scale) + ) + + @property + def _changes(self): + move = np.linalg.norm(self._last_translation - self._translation) * 1e3 + angle = np.rad2deg( + _angle_between_quats( + rot_to_quat(rotation(*self._rotation)[:3, :3]), + rot_to_quat(rotation(*self._last_rotation)[:3, :3]), + ) + ) + percs = 100 * (self._scale - self._last_scale) / self._last_scale + return move, angle, percs + + @property + def _nearest_transformed_high_res_mri_idx_hsp(self): + return self._nearest_calc.query( + apply_trans(self._head_mri_t, self._filtered_extra_points) + )[1] + + @property + def _has_hsp_data(self): + return ( + self._has_mri_data + and len(self._nearest_transformed_high_res_mri_idx_hsp) > 0 + ) + + @property + def _has_hpi_data(self): + return ( + self._has_mri_data + and len(self._nearest_transformed_high_res_mri_idx_hpi) > 0 + ) + + @property + def _has_eeg_data(self): + return ( + self._has_mri_data + and len(self._nearest_transformed_high_res_mri_idx_eeg) > 0 + ) + + @property + def _has_lpa_data(self): + mri_point = self.fiducials.dig[_map_fid_name_to_idx("lpa")] + assert mri_point["ident"] == FIFF.FIFFV_POINT_LPA + has_mri_data = np.any(mri_point["r"]) + has_head_data = np.any(self._dig_dict["lpa"]) + return has_mri_data and has_head_data + + @property + def _has_nasion_data(self): + mri_point = self.fiducials.dig[_map_fid_name_to_idx("nasion")] + assert mri_point["ident"] == FIFF.FIFFV_POINT_NASION + has_mri_data = np.any(mri_point["r"]) + has_head_data = np.any(self._dig_dict["nasion"]) + return has_mri_data and has_head_data + + @property + def _has_rpa_data(self): + mri_point = self.fiducials.dig[_map_fid_name_to_idx("rpa")] + assert mri_point["ident"] == FIFF.FIFFV_POINT_RPA + has_mri_data = np.any(mri_point["r"]) + has_head_data = np.any(self._dig_dict["rpa"]) + return has_mri_data and has_head_data + + @property + def _processed_high_res_mri_points(self): + return self._get_processed_mri_points("high") + + def _get_processed_mri_points(self, res): + bem = self._bem_low_res if res == "low" else self._bem_high_res + points = bem["rr"].copy() + if self._grow_hair: + assert len(bem["nn"]) # should be guaranteed by _read_surface + scaled_hair_dist = 1e-3 * self._grow_hair / np.array(self._scale) + hair = points[:, 2] > points[:, 1] + points[hair] += bem["nn"][hair] * scaled_hair_dist + return points + + @property + def _has_mri_data(self): + return len(self._transformed_high_res_mri_points) > 0 + + @property + def _has_dig_data(self): + return ( + self._has_mri_data + and len(self._nearest_transformed_high_res_mri_idx_hsp) > 0 + ) + + @property + def _orig_hsp_point_distance(self): + mri_points = self._transformed_high_res_mri_points[ + self._nearest_transformed_high_res_mri_idx_orig_hsp + ] + hsp_points = self._transformed_orig_dig_extra + return np.linalg.norm(mri_points - hsp_points, axis=-1) + + def _log_dig_mri_distance(self, prefix): + errs_nearest = self.compute_dig_mri_distances() + logger.info( + f"{prefix} median distance: {np.median(errs_nearest * 1000):6.2f} mm" + ) + + @property + def scale(self): + """Get the current scale factor. + + Returns + ------- + scale : ndarray, shape (3,) + The scale factors. + """ + return self._scale.copy() + + @verbose + def fit_fiducials( + self, lpa_weight=1.0, nasion_weight=10.0, rpa_weight=1.0, verbose=None + ): + """Find rotation and translation to fit all 3 fiducials. + + Parameters + ---------- + lpa_weight : float + Relative weight for LPA. The default value is 1. + nasion_weight : float + Relative weight for nasion. The default value is 10. + rpa_weight : float + Relative weight for RPA. The default value is 1. + %(verbose)s + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + logger.info("Aligning using fiducials") + self._log_dig_mri_distance("Start") + n_scale_params = self._n_scale_params + if n_scale_params == 3: + # enforce 1 even for 3-axis here (3 points is not enough) + logger.info("Enforcing 1 scaling parameter for fit with fiducials.") + n_scale_params = 1 + self._lpa_weight = lpa_weight + self._nasion_weight = nasion_weight + self._rpa_weight = rpa_weight + + head_pts = np.vstack( + (self._dig_dict["lpa"], self._dig_dict["nasion"], self._dig_dict["rpa"]) + ) + mri_pts = np.vstack( + ( + self.fiducials.dig[0]["r"], # LPA + self.fiducials.dig[1]["r"], # Nasion + self.fiducials.dig[2]["r"], + ) # RPA + ) + weights = [lpa_weight, nasion_weight, rpa_weight] + + if n_scale_params == 0: + mri_pts *= self._scale # not done in fit_matched_points + x0 = self._parameters + x0 = x0[: 6 + n_scale_params] + est = fit_matched_points( + mri_pts, + head_pts, + x0=x0, + out="params", + scale=n_scale_params, + weights=weights, + ) + if n_scale_params == 0: + self._update_params(rot=est[:3], tra=est[3:6]) + else: + assert est.size == 7 + est = np.concatenate([est, [est[-1]] * 2]) + assert est.size == 9 + self._update_params(rot=est[:3], tra=est[3:6], sca=est[6:9]) + self._log_dig_mri_distance("End ") + return self + + def _setup_icp(self, n_scale_params): + head_pts = [np.zeros((0, 3))] + mri_pts = [np.zeros((0, 3))] + weights = [np.zeros(0)] + if self._has_dig_data and self._hsp_weight > 0: # should be true + head_pts.append(self._filtered_extra_points) + mri_pts.append( + self._processed_high_res_mri_points[ + self._nearest_transformed_high_res_mri_idx_hsp + ] + ) + weights.append(np.full(len(head_pts[-1]), self._hsp_weight)) + for key in ("lpa", "nasion", "rpa"): + if getattr(self, f"_has_{key}_data"): + head_pts.append(self._dig_dict[key]) + if self._icp_fid_match == "matched": + idx = _map_fid_name_to_idx(name=key) + p = self.fiducials.dig[idx]["r"].reshape(1, -1) + mri_pts.append(p) + else: + assert self._icp_fid_match == "nearest" + mri_pts.append( + self._processed_high_res_mri_points[ + getattr( + self, + f"_nearest_transformed_high_res_mri_idx_{key}", + ) + ] + ) + weights.append( + np.full(len(mri_pts[-1]), getattr(self, f"_{key}_weight")) + ) + if self._has_eeg_data and self._eeg_weight > 0: + head_pts.append(self._dig_dict["dig_ch_pos_location"]) + mri_pts.append( + self._processed_high_res_mri_points[ + self._nearest_transformed_high_res_mri_idx_eeg + ] + ) + weights.append(np.full(len(mri_pts[-1]), self._eeg_weight)) + if self._has_hpi_data and self._hpi_weight > 0: + head_pts.append(self._dig_dict["hpi"]) + mri_pts.append( + self._processed_high_res_mri_points[ + self._nearest_transformed_high_res_mri_idx_hpi + ] + ) + weights.append(np.full(len(mri_pts[-1]), self._hpi_weight)) + head_pts = np.concatenate(head_pts) + mri_pts = np.concatenate(mri_pts) + weights = np.concatenate(weights) + if n_scale_params == 0: + mri_pts *= self._scale # not done in fit_matched_points + return head_pts, mri_pts, weights + + def set_fid_match(self, match): + """Set the strategy for fitting anatomical landmark (fiducial) points. + + Parameters + ---------- + match : 'nearest' | 'matched' + Alignment strategy; ``'nearest'`` aligns anatomical landmarks to + any point on the head surface; ``'matched'`` aligns to the fiducial + points in the MRI. + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + _check_option("match", match, self._icp_fid_matches) + self._icp_fid_match = match + return self + + @verbose + def fit_icp( + self, + n_iterations=20, + lpa_weight=1.0, + nasion_weight=10.0, + rpa_weight=1.0, + hsp_weight=1.0, + eeg_weight=1.0, + hpi_weight=1.0, + callback=None, + verbose=None, + ): + """Find MRI scaling, translation, and rotation to match HSP. + + Parameters + ---------- + n_iterations : int + Maximum number of iterations. + lpa_weight : float + Relative weight for LPA. The default value is 1. + nasion_weight : float + Relative weight for nasion. The default value is 10. + rpa_weight : float + Relative weight for RPA. The default value is 1. + hsp_weight : float + Relative weight for HSP. The default value is 1. + eeg_weight : float + Relative weight for EEG. The default value is 1. + hpi_weight : float + Relative weight for HPI. The default value is 1. + callback : callable | None + A function to call on each iteration. Useful for status message + updates. It will be passed the keyword arguments ``iteration`` + and ``n_iterations``. + %(verbose)s + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + logger.info("Aligning using ICP") + self._log_dig_mri_distance("Start ") + n_scale_params = self._n_scale_params + self._lpa_weight = lpa_weight + self._nasion_weight = nasion_weight + self._rpa_weight = rpa_weight + self._hsp_weight = hsp_weight + self._eeg_weight = eeg_weight + self._hpi_weight = hpi_weight + + # Initial guess (current state) + est = self._parameters + est = est[: [6, 7, None, 9][n_scale_params]] + + # Do the fits, assigning and evaluating at each step + for iteration in range(n_iterations): + head_pts, mri_pts, weights = self._setup_icp(n_scale_params) + est = fit_matched_points( + mri_pts, + head_pts, + scale=n_scale_params, + x0=est, + out="params", + weights=weights, + ) + if n_scale_params == 0: + self._update_params(rot=est[:3], tra=est[3:6]) + elif n_scale_params == 1: + est = np.array(list(est) + [est[-1]] * 2) + self._update_params(rot=est[:3], tra=est[3:6], sca=est[6:9]) + else: + self._update_params(rot=est[:3], tra=est[3:6], sca=est[6:9]) + angle, move, scale = self._changes + self._log_dig_mri_distance(f" ICP {iteration + 1:2d} ") + if callback is not None: + callback(iteration, n_iterations) + if ( + angle <= self._icp_angle + and move <= self._icp_distance + and all(scale <= self._icp_scale) + ): + break + self._log_dig_mri_distance("End ") + return self + + @property + def _n_scale_params(self): + if self._scale_mode is None: + n_scale_params = 0 + elif self._scale_mode == "uniform": + n_scale_params = 1 + else: + n_scale_params = 3 + return n_scale_params + + def omit_head_shape_points(self, distance): + """Exclude head shape points that are far away from the MRI head. + + Parameters + ---------- + distance : float + Exclude all points that are further away from the MRI head than + this distance (in m.). A value of distance <= 0 excludes nothing. + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + distance = float(distance) + if distance <= 0: + return + + # find the new filter + mask = self._orig_hsp_point_distance <= distance + n_excluded = np.sum(~mask) + logger.info( + "Coregistration: Excluding %i head shape points with distance >= %.3f m.", + n_excluded, + distance, + ) + # set the filter + self._extra_points_filter = mask + self._update_params(force_update=True) + return self + + def compute_dig_mri_distances(self): + """Compute distance between head shape points and MRI skin surface. + + Returns + ------- + dist : array, shape (n_points,) + The distance of the head shape points to the MRI skin surface. + + See Also + -------- + mne.dig_mri_distances + """ + # we don't use `dig_mri_distances` here because it should be much + # faster to use our already-determined nearest points + hsp_points, mri_points, _ = self._setup_icp(0) + hsp_points = apply_trans(self._head_mri_t, hsp_points) + return np.linalg.norm(mri_points - hsp_points, axis=-1) + + @property + def trans(self): + """The head->mri :class:`~mne.transforms.Transform`.""" + return Transform("head", "mri", self._head_mri_t) + + def reset(self): + """Reset all the parameters affecting the coregistration. + + Returns + ------- + self : Coregistration + The modified Coregistration object. + """ + self._grow_hair = 0.0 + self.set_rotation(self._default_parameters[:3]) + self.set_translation(self._default_parameters[3:6]) + self.set_scale(self._default_parameters[6:9]) + self._extra_points_filter = None + self._update_nearest_calc() + return self + + def _get_fiducials_distance(self): + distance = dict() + for key in ("lpa", "nasion", "rpa"): + idx = _map_fid_name_to_idx(name=key) + fid = self.fiducials.dig[idx]["r"].reshape(1, -1) + + transformed_mri = apply_trans(self._mri_trans, fid) + transformed_hsp = apply_trans(self._head_mri_t, self._dig_dict[key]) + distance[key] = np.linalg.norm(np.ravel(transformed_mri - transformed_hsp)) + return np.array(list(distance.values())) * 1e3 + + def _get_fiducials_distance_str(self): + dists = self._get_fiducials_distance() + return f"Fiducials: {dists[0]:.1f}, {dists[1]:.1f}, {dists[2]:.1f} mm" + + def _get_point_distance(self): + mri_points = list() + hsp_points = list() + if self._hsp_weight > 0 and self._has_hsp_data: + mri_points.append( + self._transformed_high_res_mri_points[ + self._nearest_transformed_high_res_mri_idx_hsp + ] + ) + hsp_points.append(self._transformed_dig_extra) + assert len(mri_points[-1]) == len(hsp_points[-1]) + if self._eeg_weight > 0 and self._has_eeg_data: + mri_points.append( + self._transformed_high_res_mri_points[ + self._nearest_transformed_high_res_mri_idx_eeg + ] + ) + hsp_points.append(self._transformed_dig_eeg) + assert len(mri_points[-1]) == len(hsp_points[-1]) + if self._hpi_weight > 0 and self._has_hpi_data: + mri_points.append( + self._transformed_high_res_mri_points[ + self._nearest_transformed_high_res_mri_idx_hpi + ] + ) + hsp_points.append(self._transformed_dig_hpi) + assert len(mri_points[-1]) == len(hsp_points[-1]) + if all(len(h) == 0 for h in hsp_points): + return None + mri_points = np.concatenate(mri_points) + hsp_points = np.concatenate(hsp_points) + return np.linalg.norm(mri_points - hsp_points, axis=-1) + + def _get_point_distance_str(self): + point_distance = self._get_point_distance() + if point_distance is None: + return "" + dists = 1e3 * point_distance + av_dist = np.mean(dists) + std_dist = np.std(dists) + kinds = [ + kind + for kind, check in ( + ("HSP", self._hsp_weight > 0 and self._has_hsp_data), + ("EEG", self._eeg_weight > 0 and self._has_eeg_data), + ("HPI", self._hpi_weight > 0 and self._has_hpi_data), + ) + if check + ] + kinds = "+".join(kinds) + return f"{len(dists)} {kinds}: {av_dist:.1f} ± {std_dist:.1f} mm" diff --git a/mne-python/source/mne/cov.py b/mne-python/source/mne/cov.py new file mode 100644 index 0000000000000000000000000000000000000000..07af31476d84fa137e4c3d895f43dd7f5b123bb6 --- /dev/null +++ b/mne-python/source/mne/cov.py @@ -0,0 +1,2573 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import itertools as itt +from copy import deepcopy +from math import log + +import numpy as np +from scipy.sparse import issparse + +from . import viz +from ._fiff.constants import FIFF +from ._fiff.meas_info import _read_bad_channels, _write_bad_channels, create_info +from ._fiff.pick import ( + _DATA_CH_TYPES_SPLIT, + _pick_data_channels, + _picks_by_type, + _picks_to_idx, + pick_channels, + pick_channels_cov, + pick_info, + pick_types, +) +from ._fiff.proj import ( + _check_projs, + _has_eeg_average_ref_proj, + _needs_eeg_average_ref_proj, + _proj_equal, + _read_proj, + _write_proj, +) +from ._fiff.proj import activate_proj as _activate_proj +from ._fiff.proj import make_projector as _make_projector +from ._fiff.tag import find_tag +from ._fiff.tree import dir_tree_find +from .defaults import ( + _BORDER_DEFAULT, + _EXTRAPOLATE_DEFAULT, + _INTERPOLATION_DEFAULT, + DEFAULTS, + _handle_default, +) +from .epochs import Epochs +from .event import make_fixed_length_events +from .evoked import EvokedArray +from .fixes import ( + EmpiricalCovariance, + _EstimatorMixin, + _logdet, + _safe_svd, + empirical_covariance, + log_likelihood, +) +from .rank import _compute_rank +from .utils import ( + _array_repr, + _check_fname, + _check_on_missing, + _check_option, + _on_missing, + _pl, + _scaled_array, + _time_mask, + _undo_scaling_cov, + _validate_type, + _verbose_safe_false, + check_fname, + check_version, + copy_function_doc_to_method_doc, + eigh, + fill_doc, + logger, + verbose, + warn, +) + + +def _check_covs_algebra(cov1, cov2): + if cov1.ch_names != cov2.ch_names: + raise ValueError("Both Covariance do not have the same list of channels.") + projs1 = [str(c) for c in cov1["projs"]] + projs2 = [str(c) for c in cov1["projs"]] + if projs1 != projs2: + raise ValueError( + "Both Covariance do not have the same list of SSP projections." + ) + + +def _get_tslice(epochs, tmin, tmax): + """Get the slice.""" + mask = _time_mask(epochs.times, tmin, tmax, sfreq=epochs.info["sfreq"]) + tstart = np.where(mask)[0][0] if tmin is not None else None + tend = np.where(mask)[0][-1] + 1 if tmax is not None else None + tslice = slice(tstart, tend, None) + return tslice + + +@fill_doc +class Covariance(dict): + """Noise covariance matrix. + + .. note:: + This class should not be instantiated directly via + ``mne.Covariance(...)``. Instead, use one of the functions + listed in the See Also section below. + + Parameters + ---------- + data : array-like + The data. + names : list of str + Channel names. + bads : list of str + Bad channels. + projs : list + Projection vectors. + nfree : int + Degrees of freedom. + eig : array-like | None + Eigenvalues. + eigvec : array-like | None + Eigenvectors. + method : str | None + The method used to compute the covariance. + loglik : float + The log likelihood. + %(verbose)s + + Attributes + ---------- + data : array of shape (n_channels, n_channels) + The covariance. + ch_names : list of str + List of channels' names. + nfree : int + Number of degrees of freedom i.e. number of time points used. + dim : int + The number of channels ``n_channels``. + + See Also + -------- + compute_covariance + compute_raw_covariance + make_ad_hoc_cov + read_cov + """ + + @verbose + def __init__( + self, + data, + names, + bads, + projs, + nfree, + eig=None, + eigvec=None, + method=None, + loglik=None, + *, + verbose=None, + ): + """Init of covariance.""" + diag = data.ndim == 1 + projs = _check_projs(projs) + self.update( + data=data, + dim=len(data), + names=names, + bads=bads, + nfree=nfree, + eig=eig, + eigvec=eigvec, + diag=diag, + projs=projs, + kind=FIFF.FIFFV_MNE_NOISE_COV, + ) + if method is not None: + self["method"] = method + if loglik is not None: + self["loglik"] = loglik + + @property + def data(self): + """Numpy array of Noise covariance matrix.""" + return self["data"] + + @property + def ch_names(self): + """Channel names.""" + return self["names"] + + @property + def nfree(self): + """Number of degrees of freedom.""" + return self["nfree"] + + @verbose + def save(self, fname, *, overwrite=False, verbose=None): + """Save covariance matrix in a FIF file. + + Parameters + ---------- + fname : path-like + Output filename. + %(overwrite)s + + .. versionadded:: 1.0 + %(verbose)s + """ + from ._fiff.write import start_and_end_file + + check_fname( + fname, "covariance", ("-cov.fif", "-cov.fif.gz", "_cov.fif", "_cov.fif.gz") + ) + fname = _check_fname(fname=fname, overwrite=overwrite) + with start_and_end_file(fname) as fid: + _write_cov(fid, self) + + def copy(self): + """Copy the Covariance object. + + Returns + ------- + cov : instance of Covariance + The copied object. + """ + return deepcopy(self) + + def as_diag(self): + """Set covariance to be processed as being diagonal. + + Returns + ------- + cov : dict + The covariance. + + Notes + ----- + This function allows creation of inverse operators + equivalent to using the old "--diagnoise" mne option. + + This function operates in place. + """ + if self["diag"]: + return self + self["diag"] = True + self["data"] = np.diag(self["data"]) + self["eig"] = None + self["eigvec"] = None + return self + + def _as_square(self): + # This is a hack but it works because np.diag() behaves nicely + if self["diag"]: + self["diag"] = False + self.as_diag() + self["diag"] = False + return self + + def _get_square(self): + if self["diag"] != (self.data.ndim == 1): + raise RuntimeError( + "Covariance attributes inconsistent, got data with " + f"dimensionality {self.data.ndim} but diag={self['diag']}" + ) + return np.diag(self.data) if self["diag"] else self.data.copy() + + def __repr__(self): # noqa: D105 + s = "" + return s + + def __add__(self, cov): + """Add Covariance taking into account number of degrees of freedom.""" + _check_covs_algebra(self, cov) + this_cov = cov.copy() + this_cov["data"] = ( + (this_cov["data"] * this_cov["nfree"]) + (self["data"] * self["nfree"]) + ) / (self["nfree"] + this_cov["nfree"]) + this_cov["nfree"] += self["nfree"] + + this_cov["bads"] = list(set(this_cov["bads"]).union(self["bads"])) + + return this_cov + + def __iadd__(self, cov): + """Add Covariance taking into account number of degrees of freedom.""" + _check_covs_algebra(self, cov) + self["data"][:] = ( + (self["data"] * self["nfree"]) + (cov["data"] * cov["nfree"]) + ) / (self["nfree"] + cov["nfree"]) + self["nfree"] += cov["nfree"] + + self["bads"] = list(set(self["bads"]).union(cov["bads"])) + + return self + + @verbose + @copy_function_doc_to_method_doc(viz.plot_cov) + def plot( + self, + info, + exclude=(), + colorbar=True, + proj=False, + show_svd=True, + show=True, + verbose=None, + ): + return viz.plot_cov( + self, info, exclude, colorbar, proj, show_svd, show, verbose + ) + + @verbose + def plot_topomap( + self, + info, + ch_type=None, + *, + scalings=None, + proj=False, + noise_cov=None, + sensors=True, + show_names=False, + mask=None, + mask_params=None, + contours=6, + outlines="head", + sphere=None, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + border=_BORDER_DEFAULT, + res=64, + size=1, + cmap=None, + vlim=(None, None), + cnorm=None, + colorbar=True, + cbar_fmt="%3.1f", + units=None, + axes=None, + show=True, + verbose=None, + ): + """Plot a topomap of the covariance diagonal. + + Parameters + ---------- + %(info_not_none)s + %(ch_type_topomap)s + + .. versionadded:: 0.21 + %(scalings_topomap)s + %(proj_plot)s + noise_cov : instance of Covariance | None + If not None, whiten the instance with ``noise_cov`` before + plotting. + %(sensors_topomap)s + %(show_names_topomap)s + %(mask_topomap)s + %(mask_params_topomap)s + %(contours_topomap)s + %(outlines_topomap)s + %(sphere_topomap_auto)s + %(image_interp_topomap)s + %(extrapolate_topomap)s + + .. versionchanged:: 0.21 + + - The default was changed to ``'local'`` for MEG sensors. + - ``'local'`` was changed to use a convex hull mask + - ``'head'`` was changed to extrapolate out to the clipping circle. + %(border_topomap)s + + .. versionadded:: 0.20 + %(res_topomap)s + %(size_topomap)s + %(cmap_topomap)s + %(vlim_plot_topomap)s + + .. versionadded:: 1.2 + %(cnorm)s + + .. versionadded:: 1.2 + %(colorbar_topomap)s + %(cbar_fmt_topomap)s + %(units_topomap_evoked)s + %(axes_cov_plot_topomap)s + %(show)s + %(verbose)s + + Returns + ------- + fig : instance of Figure + The matplotlib figure. + + Notes + ----- + .. versionadded:: 0.21 + """ + from .viz.misc import _index_info_cov + + info, C, _, _ = _index_info_cov(info, self, exclude=()) + evoked = EvokedArray(np.diag(C)[:, np.newaxis], info) + if noise_cov is not None: + # need to left and right multiply whitener, which for the diagonal + # entries is the same as multiplying twice + evoked = whiten_evoked(whiten_evoked(evoked, noise_cov), noise_cov) + if units is None: + units = "AU" + if scalings is None: + scalings = 1.0 + if units is None: + units = {k: f"({v})²" for k, v in DEFAULTS["units"].items()} + if scalings is None: + scalings = {k: v * v for k, v in DEFAULTS["scalings"].items()} + return evoked.plot_topomap( + times=[0], + ch_type=ch_type, + vlim=vlim, + cmap=cmap, + sensors=sensors, + cnorm=cnorm, + colorbar=colorbar, + scalings=scalings, + units=units, + res=res, + size=size, + cbar_fmt=cbar_fmt, + proj=proj, + show=show, + show_names=show_names, + mask=mask, + mask_params=mask_params, + outlines=outlines, + contours=contours, + image_interp=image_interp, + axes=axes, + extrapolate=extrapolate, + sphere=sphere, + border=border, + time_format="", + ) + + @verbose + def pick_channels(self, ch_names, ordered=True, *, verbose=None): + """Pick channels from this covariance matrix. + + Parameters + ---------- + ch_names : list of str + List of channels to keep. All other channels are dropped. + %(ordered)s + %(verbose)s + + Returns + ------- + cov : instance of Covariance. + The modified covariance matrix. + + Notes + ----- + Operates in-place. + + .. versionadded:: 0.20.0 + """ + return pick_channels_cov( + self, ch_names, exclude=[], ordered=ordered, copy=False + ) + + +############################################################################### +# IO + + +@verbose +def read_cov(fname, verbose=None): + """Read a noise covariance from a FIF file. + + Parameters + ---------- + fname : path-like + The path-like of file containing the covariance matrix. It should end + with ``-cov.fif`` or ``-cov.fif.gz``. + %(verbose)s + + Returns + ------- + cov : Covariance + The noise covariance matrix. + + See Also + -------- + write_cov, compute_covariance, compute_raw_covariance + """ + from ._fiff.open import fiff_open + + check_fname( + fname, "covariance", ("-cov.fif", "-cov.fif.gz", "_cov.fif", "_cov.fif.gz") + ) + fname = _check_fname(fname=fname, must_exist=True, overwrite="read") + f, tree, _ = fiff_open(fname) + with f as fid: + return Covariance( + **_read_cov(fid, tree, FIFF.FIFFV_MNE_NOISE_COV, limited=True) + ) + + +############################################################################### +# Estimate from data + + +@verbose +def make_ad_hoc_cov(info, std=None, *, verbose=None): + """Create an ad hoc noise covariance. + + Parameters + ---------- + %(info_not_none)s + std : dict of float | None + Standard_deviation of the diagonal elements. If dict, keys should be + ``'grad'`` for gradiometers, ``'mag'`` for magnetometers and ``'eeg'`` + for EEG channels. If None, default values will be used (see Notes). + %(verbose)s + + Returns + ------- + cov : instance of Covariance + The ad hoc diagonal noise covariance for the M/EEG data channels. + + Notes + ----- + The default noise values are 5 fT/cm, 20 fT, and 0.2 µV for gradiometers, + magnetometers, and EEG channels respectively. + + .. versionadded:: 0.9.0 + """ + picks = pick_types(info, meg=True, eeg=True, exclude=()) + std = _handle_default("noise_std", std) + + data = np.zeros(len(picks)) + for meg, eeg, val in zip( + ("grad", "mag", False), + (False, False, True), + (std["grad"], std["mag"], std["eeg"]), + ): + these_picks = pick_types(info, meg=meg, eeg=eeg) + data[np.searchsorted(picks, these_picks)] = val * val + ch_names = [info["ch_names"][pick] for pick in picks] + return Covariance(data, ch_names, info["bads"], info["projs"], nfree=0) + + +def _check_n_samples(n_samples, n_chan, on_few_samples="warn"): + """Check to see if there are enough samples for reliable cov calc.""" + n_samples_min = 10 * (n_chan + 1) // 2 + if n_samples <= 0: + raise ValueError("No samples found to compute the covariance matrix") + if n_samples < n_samples_min: + msg = ( + f"Too few samples (required {n_samples_min} but got {n_samples} for " + f"{n_chan} channels), covariance estimate may be unreliable" + ) + _on_missing(on_few_samples, msg, "on_few_samples") + + +@verbose +def compute_raw_covariance( + raw, + tmin=0, + tmax=None, + tstep=0.2, + reject=None, + flat=None, + picks=None, + *, + on_few_samples="warn", + method="empirical", + method_params=None, + cv=3, + scalings=None, + n_jobs=None, + return_estimators=False, + reject_by_annotation=True, + rank=None, + verbose=None, +): + """Estimate noise covariance matrix from a continuous segment of raw data. + + It is typically useful to estimate a noise covariance from empty room + data or time intervals before starting the stimulation. + + .. note:: To estimate the noise covariance from epoched data, use + :func:`mne.compute_covariance` instead. + + Parameters + ---------- + raw : instance of Raw + Raw data. + tmin : float + Beginning of time interval in seconds. Defaults to 0. + tmax : float | None (default None) + End of time interval in seconds. If None (default), use the end of the + recording. + tstep : float (default 0.2) + Length of data chunks for artifact rejection in seconds. + Can also be None to use a single epoch of (tmax - tmin) + duration. This can use a lot of memory for large ``Raw`` + instances. + reject : dict | None (default None) + Rejection parameters based on peak-to-peak amplitude. + Valid keys are 'grad' | 'mag' | 'eeg' | 'eog' | 'ecg'. + If reject is None then no rejection is done. Example:: + + reject = dict(grad=4000e-13, # T / m (gradiometers) + mag=4e-12, # T (magnetometers) + eeg=40e-6, # V (EEG channels) + eog=250e-6 # V (EOG channels) + ) + + flat : dict | None (default None) + Rejection parameters based on flatness of signal. + Valid keys are 'grad' | 'mag' | 'eeg' | 'eog' | 'ecg', and values + are floats that set the minimum acceptable peak-to-peak amplitude. + If flat is None then no rejection is done. + %(picks_good_data_noref)s + on_few_samples : str + Can be 'warn' (default), 'ignore', or 'raise' to control behavior when + there are fewer samples than channels, which can lead to inaccurate + covariance or rank estimates. + + .. versionadded:: 1.11 + method : str | list | None (default 'empirical') + The method used for covariance estimation. + See :func:`mne.compute_covariance`. + + .. versionadded:: 0.12 + method_params : dict | None (default None) + Additional parameters to the estimation procedure. + See :func:`mne.compute_covariance`. + + .. versionadded:: 0.12 + cv : int | sklearn.model_selection object (default 3) + The cross validation method. Defaults to 3, which will + internally trigger by default :class:`sklearn.model_selection.KFold` + with 3 splits. + + .. versionadded:: 0.12 + scalings : dict | None (default None) + Defaults to ``dict(mag=1e15, grad=1e13, eeg=1e6)``. + These defaults will scale magnetometers and gradiometers + at the same unit. + + .. versionadded:: 0.12 + %(n_jobs)s + + .. versionadded:: 0.12 + return_estimators : bool (default False) + Whether to return all estimators or the best. Only considered if + method equals 'auto' or is a list of str. Defaults to False. + + .. versionadded:: 0.12 + %(reject_by_annotation_epochs)s + + .. versionadded:: 0.14 + %(rank_none)s + + .. versionadded:: 0.17 + + .. versionadded:: 0.18 + Support for 'info' mode. + %(verbose)s + + Returns + ------- + cov : instance of Covariance | list + The computed covariance. If method equals 'auto' or is a list of str + and return_estimators equals True, a list of covariance estimators is + returned (sorted by log-likelihood, from high to low, i.e. from best + to worst). + + See Also + -------- + compute_covariance : Estimate noise covariance matrix from epoched data. + + Notes + ----- + This function will: + + 1. Partition the data into evenly spaced, equal-length epochs. + 2. Load them into memory. + 3. Subtract the mean across all time points and epochs for each channel. + 4. Process the :class:`Epochs` by :func:`compute_covariance`. + + This will produce a slightly different result compared to using + :func:`make_fixed_length_events`, :class:`Epochs`, and + :func:`compute_covariance` directly, since that would (with the recommended + baseline correction) subtract the mean across time *for each epoch* + (instead of across epochs) for each channel. + """ + tmin = 0.0 if tmin is None else float(tmin) + dt = 1.0 / raw.info["sfreq"] + tmax = raw.times[-1] + dt if tmax is None else float(tmax) + tstep = tmax - tmin if tstep is None else float(tstep) + tstep_m1 = tstep - dt # inclusive! + events = make_fixed_length_events(raw, 1, tmin, tmax, tstep) + logger.info(f"Using up to {len(events)} segment{_pl(events)}") + + # don't exclude any bad channels, inverses expect all channels present + if picks is None: + # Need to include all good channels e.g. if eog rejection is to be used + picks = np.arange(raw.info["nchan"]) + pick_mask = np.isin(picks, _pick_data_channels(raw.info, with_ref_meg=False)) + else: + pick_mask = slice(None) + picks = _picks_to_idx(raw.info, picks) + epochs = Epochs( + raw, + events, + 1, + 0, + tstep_m1, + baseline=None, + picks=picks, + reject=reject, + flat=flat, + verbose=_verbose_safe_false(), + preload=False, + proj=False, + reject_by_annotation=reject_by_annotation, + ) + if method is None: + method = "empirical" + if isinstance(method, str) and method == "empirical": + # potentially *much* more memory efficient to do it the iterative way + picks = picks[pick_mask] + data = 0 + n_samples = 0 + mu = 0 + # Read data in chunks + for raw_segment in epochs: + raw_segment = raw_segment[pick_mask] + mu += raw_segment.sum(axis=1) + data += np.dot(raw_segment, raw_segment.T) + n_samples += raw_segment.shape[1] + _check_n_samples(n_samples, len(picks), on_few_samples) + data -= mu[:, None] * (mu[None, :] / n_samples) + data /= n_samples - 1.0 + logger.info("Number of samples used : %d", n_samples) + logger.info("[done]") + ch_names = [raw.info["ch_names"][k] for k in picks] + bads = [b for b in raw.info["bads"] if b in ch_names] + return Covariance(data, ch_names, bads, raw.info["projs"], nfree=n_samples - 1) + del picks, pick_mask + + # This makes it equivalent to what we used to do (and do above for + # empirical mode), treating all epochs as if they were a single long one + epochs.load_data() + ch_means = epochs._data.mean(axis=0).mean(axis=1) + epochs._data -= ch_means[np.newaxis, :, np.newaxis] + # fake this value so there are no complaints from compute_covariance + epochs.baseline = (None, None) + return compute_covariance( + epochs, + keep_sample_mean=True, + method=method, + method_params=method_params, + cv=cv, + scalings=scalings, + n_jobs=n_jobs, + return_estimators=return_estimators, + rank=rank, + ) + + +def _check_method_params( + method, + method_params, + keep_sample_mean=True, + name="method", + allow_auto=True, + rank=None, +): + """Check that method and method_params are usable.""" + accepted_methods = ( + "auto", + "empirical", + "diagonal_fixed", + "ledoit_wolf", + "oas", + "shrunk", + "pca", + "factor_analysis", + "shrinkage", + ) + _method_params = { + "empirical": {"store_precision": False, "assume_centered": True}, + "diagonal_fixed": {"store_precision": False, "assume_centered": True}, + "ledoit_wolf": {"store_precision": False, "assume_centered": True}, + "oas": {"store_precision": False, "assume_centered": True}, + "shrinkage": { + "shrinkage": 0.1, + "store_precision": False, + "assume_centered": True, + }, + "shrunk": { + "shrinkage": np.logspace(-4, 0, 30), + "store_precision": False, + "assume_centered": True, + }, + "pca": {"iter_n_components": None}, + "factor_analysis": {"iter_n_components": None}, + } + + for ch_type in _DATA_CH_TYPES_SPLIT: + _method_params["diagonal_fixed"][ch_type] = 0.1 + + if isinstance(method_params, dict): + for key, values in method_params.items(): + if key not in _method_params: + raise ValueError( + 'key ({}) must be "{}"'.format(key, '" or "'.join(_method_params)) + ) + + _method_params[key].update(method_params[key]) + shrinkage = method_params.get("shrinkage", {}).get("shrinkage", 0.1) + if not 0 <= shrinkage <= 1: + raise ValueError(f"shrinkage must be between 0 and 1, got {shrinkage}") + + was_auto = False + if method is None: + method = ["empirical"] + elif method == "auto" and allow_auto: + was_auto = True + method = ["shrunk", "diagonal_fixed", "empirical", "factor_analysis"] + + if not isinstance(method, list | tuple): + method = [method] + + if not all(k in accepted_methods for k in method): + raise ValueError( + f"Invalid {name} ({method}). Accepted values (individually or " + f"in a list) are any of '{accepted_methods}' or None." + ) + if not (isinstance(rank, str) and rank == "full"): + if was_auto: + method.pop(method.index("factor_analysis")) + for method_ in method: + if method_ in ("pca", "factor_analysis"): + raise ValueError( + f'{method_} can so far only be used with rank="full", got rank=' + f"{rank!r}" + ) + if not keep_sample_mean: + if len(method) != 1 or "empirical" not in method: + raise ValueError( + f'`keep_sample_mean=False` is only supported with {name}="empirical"' + ) + for p, v in _method_params.items(): + if v.get("assume_centered", None) is False: + raise ValueError( + "`assume_centered` must be True if `keep_sample_mean` is False" + ) + return method, _method_params + + +@verbose +def compute_covariance( + epochs, + keep_sample_mean=True, + tmin=None, + tmax=None, + projs=None, + *, + on_few_samples="warn", + method="empirical", + method_params=None, + cv=3, + scalings=None, + n_jobs=None, + return_estimators=False, + on_mismatch="raise", + rank=None, + verbose=None, +): + """Estimate noise covariance matrix from epochs. + + The noise covariance is typically estimated on pre-stimulus periods + when the stimulus onset is defined from events. + + If the covariance is computed for multiple event types (events + with different IDs), the following two options can be used and combined: + + 1. either an Epochs object for each event type is created and + a list of Epochs is passed to this function. + 2. an Epochs object is created for multiple events and passed + to this function. + + .. note:: To estimate the noise covariance from non-epoched raw data, such + as an empty-room recording, use + :func:`mne.compute_raw_covariance` instead. + + Parameters + ---------- + epochs : instance of Epochs, or list of Epochs + The epochs. + keep_sample_mean : bool (default True) + If False, the average response over epochs is computed for + each event type and subtracted during the covariance + computation. This is useful if the evoked response from a + previous stimulus extends into the baseline period of the next. + Note. This option is only implemented for method='empirical'. + tmin : float | None (default None) + Start time for baseline. If None start at first sample. + tmax : float | None (default None) + End time for baseline. If None end at last sample. + projs : list of Projection | None (default None) + List of projectors to use in covariance calculation, or None + to indicate that the projectors from the epochs should be + inherited. If None, then projectors from all epochs must match. + on_few_samples : str + Can be 'warn' (default), 'ignore', or 'raise' to control behavior when + there are fewer samples than channels, which can lead to inaccurate + covariance or rank estimates. + + .. versionadded:: 1.11 + method : str | list | None (default 'empirical') + The method used for covariance estimation. If 'empirical' (default), + the sample covariance will be computed. A list can be passed to + perform estimates using multiple methods. + If 'auto' or a list of methods, the best estimator will be determined + based on log-likelihood and cross-validation on unseen data as + described in :footcite:`EngemannGramfort2015`. Valid methods are + 'empirical', 'diagonal_fixed', 'shrunk', 'oas', 'ledoit_wolf', + 'factor_analysis', 'shrinkage', and 'pca' (see Notes). If ``'auto'``, + it expands to:: + + ['shrunk', 'diagonal_fixed', 'empirical', 'factor_analysis'] + + ``'factor_analysis'`` is removed when ``rank`` is not 'full'. + The ``'auto'`` mode is not recommended if there are many + segments of data, since computation can take a long time. + + .. versionadded:: 0.9.0 + method_params : dict | None (default None) + Additional parameters to the estimation procedure. Only considered if + method is not None. Keys must correspond to the value(s) of ``method``. + If None (default), expands to the following (with the addition of + ``{'store_precision': False, 'assume_centered': True} for all methods + except ``'factor_analysis'`` and ``'pca'``):: + + {'diagonal_fixed': {'grad': 0.1, 'mag': 0.1, 'eeg': 0.1, ...}, + 'shrinkage': {'shrinkage': 0.1}, + 'shrunk': {'shrinkage': np.logspace(-4, 0, 30)}, + 'pca': {'iter_n_components': None}, + 'factor_analysis': {'iter_n_components': None}} + + cv : int | sklearn.model_selection object (default 3) + The cross validation method. Defaults to 3, which will + internally trigger by default :class:`sklearn.model_selection.KFold` + with 3 splits. + scalings : dict | None (default None) + Defaults to ``dict(mag=1e15, grad=1e13, eeg=1e6)``. + These defaults will scale data to roughly the same order of + magnitude. + %(n_jobs)s + return_estimators : bool (default False) + Whether to return all estimators or the best. Only considered if + method equals 'auto' or is a list of str. Defaults to False. + on_mismatch : str + What to do when the MEG<->Head transformations do not match between + epochs. If "raise" (default) an error is raised, if "warn" then a + warning is emitted, if "ignore" then nothing is printed. Having + mismatched transforms can in some cases lead to unexpected or + unstable results in covariance calculation, e.g. when data + have been processed with Maxwell filtering but not transformed + to the same head position. + %(rank_none)s + + .. versionadded:: 0.17 + + .. versionadded:: 0.18 + Support for 'info' mode. + %(verbose)s + + Returns + ------- + cov : instance of Covariance | list + The computed covariance. If method equals ``'auto'`` or is a list of str + and ``return_estimators=True``, a list of covariance estimators is + returned (sorted by log-likelihood, from high to low, i.e. from best + to worst). + + See Also + -------- + compute_raw_covariance : Estimate noise covariance from raw data, such as + empty-room recordings. + + Notes + ----- + Baseline correction or sufficient high-passing should be used + when creating the :class:`Epochs` to ensure that the data are zero mean, + otherwise the computed covariance matrix will be inaccurate. + + Valid ``method`` strings are: + + * ``'empirical'`` + The empirical or sample covariance (default) + * ``'diagonal_fixed'`` + A diagonal regularization based on channel types as in + :func:`mne.cov.regularize`. + * ``'shrinkage'`` + Fixed shrinkage. + + .. versionadded:: 0.16 + * ``'ledoit_wolf'`` + The Ledoit-Wolf estimator, which uses an + empirical formula for the optimal shrinkage value :footcite:`LedoitWolf2004`. + * ``'oas'`` + The OAS estimator :footcite:`ChenEtAl2010`, which uses a different + empricial formula for the optimal shrinkage value. + + .. versionadded:: 0.16 + * ``'shrunk'`` + Like 'ledoit_wolf', but with cross-validation for optimal alpha. + * ``'pca'`` + Probabilistic PCA with low rank :footcite:`TippingBishop1999`. + * ``'factor_analysis'`` + Factor analysis with low rank :footcite:`Barber2012`. + + ``'ledoit_wolf'`` and ``'pca'`` are similar to ``'shrunk'`` and + ``'factor_analysis'``, respectively, except that they use + cross validation (which is useful when samples are correlated, which + is often the case for M/EEG data). The former two are not included in + the ``'auto'`` mode to avoid redundancy. + + For multiple event types, it is also possible to create a + single :class:`Epochs` object with events obtained using + :func:`mne.merge_events`. However, the resulting covariance matrix + will only be correct if ``keep_sample_mean is True``. + + The covariance can be unstable if the number of samples is small. + In that case it is common to regularize the covariance estimate. + The ``method`` parameter allows to regularize the covariance in an + automated way. It also allows to select between different alternative + estimation algorithms which themselves achieve regularization. + Details are described in :footcite:t:`EngemannGramfort2015`. + + For more information on the advanced estimation methods, see + :ref:`the sklearn manual `. + + References + ---------- + .. footbibliography:: + """ + # scale to natural unit for best stability with MEG/EEG + scalings = _check_scalings_user(scalings) + method, _method_params = _check_method_params( + method, method_params, keep_sample_mean, rank=rank + ) + del method_params + + # for multi condition support epochs is required to refer to a list of + # epochs objects + + def _unpack_epochs(epochs): + if len(epochs.event_id) > 1: + epochs = [epochs[k] for k in epochs.event_id] + else: + epochs = [epochs] + return epochs + + if not isinstance(epochs, list): + epochs = _unpack_epochs(epochs) + else: + epochs = sum([_unpack_epochs(epoch) for epoch in epochs], []) + + # check for baseline correction + if any( + epochs_t.baseline is None + and epochs_t.info["highpass"] < 0.5 + and keep_sample_mean + for epochs_t in epochs + ): + warn("Epochs are not baseline corrected, covariance matrix may be inaccurate") + + orig = epochs[0].info["dev_head_t"] + _check_on_missing(on_mismatch, "on_mismatch") + for ei, epoch in enumerate(epochs): + epoch.info._check_consistency() + if (orig is None) != (epoch.info["dev_head_t"] is None) or ( + orig is not None + and not np.allclose(orig["trans"], epoch.info["dev_head_t"]["trans"]) + ): + msg = ( + "MEG<->Head transform mismatch between epochs[0]:\n{}\n\n" + "and epochs[{}]:\n{}".format(orig, ei, epoch.info["dev_head_t"]) + ) + _on_missing(on_mismatch, msg, "on_mismatch") + + bads = epochs[0].info["bads"] + if projs is None: + projs = epochs[0].info["projs"] + # make sure Epochs are compatible + for epochs_t in epochs[1:]: + if epochs_t.proj != epochs[0].proj: + raise ValueError("Epochs must agree on the use of projections") + for proj_a, proj_b in zip(epochs_t.info["projs"], projs): + if not _proj_equal(proj_a, proj_b): + raise ValueError("Epochs must have same projectors") + projs = _check_projs(projs) + ch_names = epochs[0].ch_names + + # make sure Epochs are compatible + for epochs_t in epochs[1:]: + if epochs_t.info["bads"] != bads: + raise ValueError("Epochs must have same bad channels") + if epochs_t.ch_names != ch_names: + raise ValueError("Epochs must have same channel names") + picks_list = _picks_by_type(epochs[0].info) + picks_meeg = np.concatenate([b for _, b in picks_list]) + picks_meeg = np.sort(picks_meeg) + ch_names = [epochs[0].ch_names[k] for k in picks_meeg] + info = epochs[0].info # we will overwrite 'epochs' + + if not keep_sample_mean: + # prepare mean covs + n_epoch_types = len(epochs) + data_mean = [0] * n_epoch_types + n_samples = np.zeros(n_epoch_types, dtype=np.int64) + n_epochs = np.zeros(n_epoch_types, dtype=np.int64) + + for ii, epochs_t in enumerate(epochs): + tslice = _get_tslice(epochs_t, tmin, tmax) + for e in epochs_t: + e = e[picks_meeg, tslice] + if not keep_sample_mean: + data_mean[ii] += e + n_samples[ii] += e.shape[1] + n_epochs[ii] += 1 + + n_samples_epoch = n_samples // n_epochs + norm_const = np.sum(n_samples_epoch * (n_epochs - 1)) + data_mean = [ + 1.0 / n_epoch * np.dot(mean, mean.T) + for n_epoch, mean in zip(n_epochs, data_mean) + ] + + info = pick_info(info, picks_meeg) + tslice = _get_tslice(epochs[0], tmin, tmax) + epochs = [ee.get_data(picks=picks_meeg)[..., tslice] for ee in epochs] + picks_meeg = np.arange(len(picks_meeg)) + picks_list = _picks_by_type(info) + + if len(epochs) > 1: + epochs = np.concatenate(epochs, 0) + else: + epochs = epochs[0] + + epochs = np.hstack(epochs) + n_samples_tot = epochs.shape[-1] + _check_n_samples(n_samples_tot, len(picks_meeg), on_few_samples) + + epochs = epochs.T # sklearn | C-order + cov_data = _compute_covariance_auto( + epochs, + method=method, + method_params=_method_params, + info=info, + cv=cv, + n_jobs=n_jobs, + stop_early=True, + picks_list=picks_list, + scalings=scalings, + rank=rank, + on_few_samples=on_few_samples, + ) + + if keep_sample_mean is False: + cov = cov_data["empirical"]["data"] + # undo scaling + cov *= n_samples_tot - 1 + # ... apply pre-computed class-wise normalization + for mean_cov in data_mean: + cov -= mean_cov + cov /= norm_const + + covs = list() + for this_method, data in cov_data.items(): + cov = Covariance( + data.pop("data"), ch_names, info["bads"], projs, nfree=n_samples_tot - 1 + ) + + # add extra info + cov.update(method=this_method, **data) + covs.append(cov) + logger.info("Number of samples used : %d", n_samples_tot) + covs.sort(key=lambda c: c["loglik"], reverse=True) + + if len(covs) > 1: + msg = ["log-likelihood on unseen data (descending order):"] + for c in covs: + msg.append(f"{c['method']}: {c['loglik']:0.3f}") + logger.info("\n ".join(msg)) + if return_estimators: + out = covs + else: + out = covs[0] + logger.info("selecting best estimator: {}".format(out["method"])) + else: + out = covs[0] + logger.info("[done]") + + return out + + +def _check_scalings_user(scalings): + if isinstance(scalings, dict): + for k, v in scalings.items(): + _check_option("the keys in `scalings`", k, ["mag", "grad", "eeg"]) + elif scalings is not None and not isinstance(scalings, np.ndarray): + raise TypeError( + f"scalings must be a dict, ndarray, or None, got {type(scalings)}" + ) + scalings = _handle_default("scalings", scalings) + return scalings + + +def _eigvec_subspace(eig, eigvec, mask): + """Compute the subspace from a subset of eigenvectors.""" + # We do the same thing we do with projectors: + P = np.eye(len(eigvec)) - np.dot(eigvec[~mask].conj().T, eigvec[~mask]) + eig, eigvec = eigh(P) + eigvec = eigvec.conj().T + return eig, eigvec + + +@verbose +def _compute_rank_raw_array( + data, info, rank, scalings, *, log_ch_type=None, on_few_samples="warn", verbose=None +): + from .io import RawArray + + return _compute_rank( + RawArray(data, info, copy="auto", verbose=_verbose_safe_false()), + rank, + scalings, + info, + log_ch_type=log_ch_type, + on_few_samples=on_few_samples, + ) + + +def _compute_covariance_auto( + data, + method, + info, + method_params, + cv, + scalings, + n_jobs, + stop_early, + picks_list, + rank, + *, + cov_kind="", + log_ch_type=None, + log_rank=True, + on_few_samples="warn", +): + """Compute covariance auto mode.""" + # rescale to improve numerical stability + orig_rank = rank + rank = _compute_rank_raw_array( + data.T, + info, + rank=rank, + scalings=scalings, + on_few_samples=on_few_samples, + verbose=_verbose_safe_false(), + ) + with _scaled_array(data.T, picks_list, scalings): + C = np.dot(data.T, data) + _, eigvec, mask = _smart_eigh( + C, + info, + rank, + proj_subspace=True, + do_compute_rank=False, + log_ch_type=log_ch_type, + verbose=None if log_rank else _verbose_safe_false(), + ) + eigvec = eigvec[mask] + data = np.dot(data, eigvec.T) + used = np.where(mask)[0] + sub_picks_list = [ + (key, np.searchsorted(used, picks)) for key, picks in picks_list + ] + sub_info = pick_info(info, used) if len(used) != len(mask) else info + if log_rank: + logger.info(f"Reducing data rank from {len(mask)} -> {eigvec.shape[0]}") + estimator_cov_info = list() + + ok_sklearn = check_version("sklearn") + if not ok_sklearn and (len(method) != 1 or method[0] != "empirical"): + raise ValueError( + 'scikit-learn is not installed, `method` must be "empirical", got ' + f"{repr(method)}" + ) + + for method_ in method: + data_ = data.copy() + name = method_.__name__ if callable(method_) else method_ + logger.info( + f"Estimating {cov_kind + (' ' if cov_kind else '')}" + f"covariance using {name.upper()}" + ) + mp = method_params[method_] + _info = {} + + if method_ == "empirical": + est = EmpiricalCovariance(**mp) + est.fit(data_) + estimator_cov_info.append((est, est.covariance_, _info)) + del est + + elif method_ == "diagonal_fixed": + est = _RegCovariance(info=sub_info, **mp) + est.fit(data_) + estimator_cov_info.append((est, est.covariance_, _info)) + del est + + elif method_ == "ledoit_wolf": + from sklearn.covariance import LedoitWolf + + shrinkages = [] + lw = LedoitWolf(**mp) + + for ch_type, picks in sub_picks_list: + lw.fit(data_[:, picks]) + shrinkages.append((ch_type, lw.shrinkage_, picks)) + sc = _ShrunkCovariance(shrinkage=shrinkages, **mp) + sc.fit(data_) + estimator_cov_info.append((sc, sc.covariance_, _info)) + del lw, sc + + elif method_ == "oas": + from sklearn.covariance import OAS + + shrinkages = [] + oas = OAS(**mp) + + for ch_type, picks in sub_picks_list: + oas.fit(data_[:, picks]) + shrinkages.append((ch_type, oas.shrinkage_, picks)) + sc = _ShrunkCovariance(shrinkage=shrinkages, **mp) + sc.fit(data_) + estimator_cov_info.append((sc, sc.covariance_, _info)) + del oas, sc + + elif method_ == "shrinkage": + sc = _ShrunkCovariance(**mp) + sc.fit(data_) + estimator_cov_info.append((sc, sc.covariance_, _info)) + del sc + + elif method_ == "shrunk": + from sklearn.covariance import ShrunkCovariance + from sklearn.model_selection import GridSearchCV + + shrinkage = mp.pop("shrinkage") + tuned_parameters = [{"shrinkage": shrinkage}] + shrinkages = [] + gs = GridSearchCV(ShrunkCovariance(**mp), tuned_parameters, cv=cv) + for ch_type, picks in sub_picks_list: + gs.fit(data_[:, picks]) + shrinkages.append((ch_type, gs.best_estimator_.shrinkage, picks)) + shrinkages = [c[0] for c in zip(shrinkages)] + sc = _ShrunkCovariance(shrinkage=shrinkages, **mp) + sc.fit(data_) + estimator_cov_info.append((sc, sc.covariance_, _info)) + del shrinkage, sc + + elif method_ == "pca": + assert orig_rank == "full" + pca, _info = _auto_low_rank_model( + data_, + method_, + n_jobs=n_jobs, + method_params=mp, + cv=cv, + stop_early=stop_early, + ) + pca.fit(data_) + estimator_cov_info.append((pca, pca.get_covariance(), _info)) + del pca + + elif method_ == "factor_analysis": + assert orig_rank == "full" + fa, _info = _auto_low_rank_model( + data_, + method_, + n_jobs=n_jobs, + method_params=mp, + cv=cv, + stop_early=stop_early, + ) + fa.fit(data_) + estimator_cov_info.append((fa, fa.get_covariance(), _info)) + del fa + else: + raise ValueError("Oh no! Your estimator does not have a .fit method") + logger.info("Done.") + + if len(method) > 1: + logger.info("Using cross-validation to select the best estimator.") + + out = dict() + for ei, (estimator, cov, runtime_info) in enumerate(estimator_cov_info): + if len(method) > 1: + loglik = _cross_val(data, estimator, cv, n_jobs) + else: + loglik = None + # project back + cov = np.dot(eigvec.T, np.dot(cov, eigvec)) + # undo bias + cov *= data.shape[0] / max(data.shape[0] - 1, 1) + # undo scaling + _undo_scaling_cov(cov, picks_list, scalings) + method_ = method[ei] + name = method_.__name__ if callable(method_) else method_ + out[name] = dict(loglik=loglik, data=cov, estimator=estimator) + out[name].update(runtime_info) + + return out + + +def _gaussian_loglik_scorer(est, X, y=None): + """Compute the Gaussian log likelihood of X under the model in est.""" + # compute empirical covariance of the test set + precision = est.get_precision() + n_samples, n_features = X.shape + log_like = -0.5 * (X * (np.dot(X, precision))).sum(axis=1) + log_like -= 0.5 * (n_features * log(2.0 * np.pi) - _logdet(precision)) + out = np.mean(log_like) + return out + + +def _cross_val(data, est, cv, n_jobs): + """Compute cross validation.""" + from sklearn.model_selection import cross_val_score + + return np.mean( + cross_val_score( + est, data, cv=cv, n_jobs=n_jobs, scoring=_gaussian_loglik_scorer + ) + ) + + +def _auto_low_rank_model( + data, mode, n_jobs, method_params, cv, stop_early=True, verbose=None +): + """Compute latent variable models.""" + method_params = deepcopy(method_params) + iter_n_components = method_params.pop("iter_n_components") + if iter_n_components is None: + iter_n_components = np.arange(5, data.shape[1], 5) + from sklearn.decomposition import PCA, FactorAnalysis + + if mode == "factor_analysis": + est = FactorAnalysis + else: + assert mode == "pca" + est = PCA + est = est(**method_params) + est.n_components = 1 + scores = np.empty_like(iter_n_components, dtype=np.float64) + scores.fill(np.nan) + + # make sure we don't empty the thing if it's a generator + max_n = max(list(deepcopy(iter_n_components))) + if max_n > data.shape[1]: + warn( + f"You are trying to estimate {max_n} components on matrix " + f"with {data.shape[1]} features." + ) + + for ii, n in enumerate(iter_n_components): + est.n_components = n + try: # this may fail depending on rank and split + score = _cross_val(data=data, est=est, cv=cv, n_jobs=n_jobs) + except ValueError: + score = np.inf + if np.isinf(score) or score > 0: + logger.info("... infinite values encountered. stopping estimation") + break + logger.info("... rank: %i - loglik: %0.3f", n, score) + if score != -np.inf: + scores[ii] = score + + if ii >= 3 and np.all(np.diff(scores[ii - 3 : ii]) < 0) and stop_early: + # early stop search when loglik has been going down 3 times + logger.info("early stopping parameter search.") + break + + # happens if rank is too low right form the beginning + if np.isnan(scores).all(): + raise RuntimeError( + "Oh no! Could not estimate covariance because all " + "scores were NaN. Please contact the MNE-Python " + "developers." + ) + + i_score = np.nanargmax(scores) + best = est.n_components = iter_n_components[i_score] + logger.info("... best model at rank = %i", best) + runtime_info = { + "ranks": np.array(iter_n_components), + "scores": scores, + "best": best, + "cv": cv, + } + return est, runtime_info + + +############################################################################### +# Sklearn Estimators + + +class _RegCovariance(_EstimatorMixin): + """Aux class.""" + + def __init__( + self, + info, + grad=0.1, + mag=0.1, + eeg=0.1, + seeg=0.1, + ecog=0.1, + hbo=0.1, + hbr=0.1, + fnirs_cw_amplitude=0.1, + fnirs_fd_ac_amplitude=0.1, + fnirs_fd_phase=0.1, + fnirs_od=0.1, + csd=0.1, + dbs=0.1, + store_precision=False, + assume_centered=False, + ): + self.info = info + # For sklearn compat, these cannot (easily?) be combined into + # a single dictionary + self.grad = grad + self.mag = mag + self.eeg = eeg + self.seeg = seeg + self.dbs = dbs + self.ecog = ecog + self.hbo = hbo + self.hbr = hbr + self.fnirs_cw_amplitude = fnirs_cw_amplitude + self.fnirs_fd_ac_amplitude = fnirs_fd_ac_amplitude + self.fnirs_fd_phase = fnirs_fd_phase + self.fnirs_od = fnirs_od + self.csd = csd + self.store_precision = store_precision + self.assume_centered = assume_centered + + def fit(self, X): + """Fit covariance model with classical diagonal regularization.""" + self.estimator_ = EmpiricalCovariance( + store_precision=self.store_precision, assume_centered=self.assume_centered + ) + + self.covariance_ = self.estimator_.fit(X).covariance_ + self.covariance_ = 0.5 * (self.covariance_ + self.covariance_.T) + cov_ = Covariance( + data=self.covariance_, + names=self.info["ch_names"], + bads=self.info["bads"], + projs=self.info["projs"], + nfree=len(self.covariance_), + ) + cov_ = regularize( + cov_, + self.info, + proj=False, + exclude="bads", + grad=self.grad, + mag=self.mag, + eeg=self.eeg, + ecog=self.ecog, + seeg=self.seeg, + dbs=self.dbs, + hbo=self.hbo, + hbr=self.hbr, + rank="full", + ) + self.estimator_.covariance_ = self.covariance_ = cov_.data + return self + + def score(self, X_test, y=None): + """Delegate call to modified EmpiricalCovariance instance.""" + return self.estimator_.score(X_test, y=y) + + def get_precision(self): + """Delegate call to modified EmpiricalCovariance instance.""" + return self.estimator_.get_precision() + + +class _ShrunkCovariance(_EstimatorMixin): + """Aux class.""" + + def __init__(self, store_precision, assume_centered, shrinkage=0.1): + self.store_precision = store_precision + self.assume_centered = assume_centered + self.shrinkage = shrinkage + + def fit(self, X): + """Fit covariance model with oracle shrinkage regularization.""" + from sklearn.covariance import shrunk_covariance + + self.estimator_ = EmpiricalCovariance( + store_precision=self.store_precision, assume_centered=self.assume_centered + ) + + cov = self.estimator_.fit(X).covariance_ + + if not isinstance(self.shrinkage, list | tuple): + shrinkage = [("all", self.shrinkage, np.arange(len(cov)))] + else: + shrinkage = self.shrinkage + + zero_cross_cov = np.zeros_like(cov, dtype=bool) + for a, b in itt.combinations(shrinkage, 2): + picks_i, picks_j = a[2], b[2] + ch_ = a[0], b[0] + if "eeg" in ch_: + zero_cross_cov[np.ix_(picks_i, picks_j)] = True + zero_cross_cov[np.ix_(picks_j, picks_i)] = True + + self.zero_cross_cov_ = zero_cross_cov + + # Apply shrinkage to blocks + for ch_type, c, picks in shrinkage: + sub_cov = cov[np.ix_(picks, picks)] + cov[np.ix_(picks, picks)] = shrunk_covariance(sub_cov, shrinkage=c) + + # Apply shrinkage to cross-cov + for a, b in itt.combinations(shrinkage, 2): + shrinkage_i, shrinkage_j = a[1], b[1] + picks_i, picks_j = a[2], b[2] + c_ij = np.sqrt((1.0 - shrinkage_i) * (1.0 - shrinkage_j)) + cov[np.ix_(picks_i, picks_j)] *= c_ij + cov[np.ix_(picks_j, picks_i)] *= c_ij + + # Set to zero the necessary cross-cov + if np.any(zero_cross_cov): + cov[zero_cross_cov] = 0.0 + + self.estimator_.covariance_ = self.covariance_ = cov + return self + + def score(self, X_test, y=None): + """Delegate to modified EmpiricalCovariance instance.""" + # compute empirical covariance of the test set + test_cov = empirical_covariance( + X_test - self.estimator_.location_, assume_centered=True + ) + if np.any(self.zero_cross_cov_): + test_cov[self.zero_cross_cov_] = 0.0 + res = log_likelihood(test_cov, self.estimator_.get_precision()) + return res + + def get_precision(self): + """Delegate to modified EmpiricalCovariance instance.""" + return self.estimator_.get_precision() + + +############################################################################### +# Writing + + +@verbose +def write_cov(fname, cov, *, overwrite=False, verbose=None): + """Write a noise covariance matrix. + + Parameters + ---------- + fname : path-like + The name of the file. It should end with ``-cov.fif`` or + ``-cov.fif.gz``. + cov : Covariance + The noise covariance matrix. + %(overwrite)s + + .. versionadded:: 1.0 + %(verbose)s + + See Also + -------- + read_cov + """ + cov.save(fname, overwrite=overwrite, verbose=verbose) + + +############################################################################### +# Prepare for inverse modeling + + +def _unpack_epochs(epochs): + """Aux Function.""" + if len(epochs.event_id) > 1: + epochs = [epochs[k] for k in epochs.event_id] + else: + epochs = [epochs] + + return epochs + + +def _get_ch_whitener(A, pca, ch_type, rank): + """Get whitener params for a set of channels.""" + # whitening operator + eig, eigvec = eigh(A, overwrite_a=True) + eigvec = eigvec.conj().T + mask = np.ones(len(eig), bool) + eig[:-rank] = 0.0 + mask[:-rank] = False + + logger.info( + f" Setting small {ch_type} eigenvalues to zero " + f"({'using' if pca else 'without'} PCA)" + ) + if pca: # No PCA case. + # This line will reduce the actual number of variables in data + # and leadfield to the true rank. + eigvec = eigvec[:-rank].copy() + return eig, eigvec, mask + + +@verbose +def prepare_noise_cov( + noise_cov, + info, + ch_names=None, + rank=None, + scalings=None, + on_rank_mismatch="ignore", + *, + verbose=None, +): + """Prepare noise covariance matrix. + + Parameters + ---------- + noise_cov : instance of Covariance + The noise covariance to process. + %(info_not_none)s (Used to get channel types and bad channels). + ch_names : list | None + The channel names to be considered. Can be None to use + ``info['ch_names']``. + %(rank_none)s + + .. versionadded:: 0.18 + Support for 'info' mode. + scalings : dict | None + Data will be rescaled before rank estimation to improve accuracy. + If dict, it will override the following dict (default if None):: + + dict(mag=1e12, grad=1e11, eeg=1e5) + %(on_rank_mismatch)s + %(verbose)s + + Returns + ------- + cov : instance of Covariance + A copy of the covariance with the good channels subselected + and parameters updated. + """ + # reorder C and info to match ch_names order + noise_cov_idx = list() + missing = list() + ch_names = info["ch_names"] if ch_names is None else ch_names + for c in ch_names: + # this could be try/except ValueError, but it is not the preferred way + if c in noise_cov.ch_names: + noise_cov_idx.append(noise_cov.ch_names.index(c)) + else: + missing.append(c) + if len(missing): + raise RuntimeError(f"Not all channels present in noise covariance:\n{missing}") + C = noise_cov._get_square()[np.ix_(noise_cov_idx, noise_cov_idx)] + info = pick_info(info, pick_channels(info["ch_names"], ch_names, ordered=False)) + projs = info["projs"] + noise_cov["projs"] + noise_cov = Covariance( + data=C, + names=ch_names, + bads=list(noise_cov["bads"]), + projs=deepcopy(noise_cov["projs"]), + nfree=noise_cov["nfree"], + method=noise_cov.get("method", None), + loglik=noise_cov.get("loglik", None), + ) + + eig, eigvec, _ = _smart_eigh( + noise_cov, + info, + rank, + scalings, + projs, + ch_names, + on_rank_mismatch=on_rank_mismatch, + ) + noise_cov.update(eig=eig, eigvec=eigvec) + return noise_cov + + +@verbose +def _smart_eigh( + C, + info, + rank, + scalings=None, + projs=None, + ch_names=None, + proj_subspace=False, + do_compute_rank=True, + on_rank_mismatch="ignore", + *, + log_ch_type=None, + verbose=None, +): + """Compute eigh of C taking into account rank and ch_type scalings.""" + scalings = _handle_default("scalings_cov_rank", scalings) + projs = info["projs"] if projs is None else projs + ch_names = info["ch_names"] if ch_names is None else ch_names + if info["ch_names"] != ch_names: + info = pick_info(info, [info["ch_names"].index(c) for c in ch_names]) + assert info["ch_names"] == ch_names + n_chan = len(ch_names) + + # Create the projection operator + proj, ncomp, _ = _make_projector(projs, ch_names) + + if isinstance(C, Covariance): + C = C["data"] + if ncomp > 0: + logger.info(" Created an SSP operator (subspace dimension = %d)", ncomp) + C = np.dot(proj, np.dot(C, proj.T)) + + noise_cov = Covariance(C, ch_names, [], projs, 0) + if do_compute_rank: # if necessary + rank = _compute_rank( + noise_cov, + rank, + scalings, + info, + on_rank_mismatch=on_rank_mismatch, + log_ch_type=log_ch_type, + ) + assert C.ndim == 2 and C.shape[0] == C.shape[1] + + # time saving short-circuit + if proj_subspace and sum(rank.values()) == C.shape[0]: + return np.ones(n_chan), np.eye(n_chan), np.ones(n_chan, bool) + + dtype = complex if C.dtype == np.complex128 else float + eig = np.zeros(n_chan, dtype) + eigvec = np.zeros((n_chan, n_chan), dtype) + mask = np.zeros(n_chan, bool) + for ch_type, picks in _picks_by_type( + info, meg_combined=True, ref_meg=False, exclude=[] + ): + if len(picks) == 0: + continue + this_C = C[np.ix_(picks, picks)] + + if ch_type not in rank and ch_type in ("mag", "grad"): + this_rank = rank["meg"] # if there is only one or the other + else: + this_rank = rank[ch_type] + + if log_ch_type is not None: + ch_type_ = log_ch_type + else: + ch_type_ = ch_type.upper() + e, ev, m = _get_ch_whitener(this_C, False, ch_type_, this_rank) + if proj_subspace: + # Choose the subspace the same way we do for projections + e, ev = _eigvec_subspace(e, ev, m) + eig[picks], eigvec[np.ix_(picks, picks)], mask[picks] = e, ev, m + largest, smallest = e[-1], e[m][0] + if largest > 1e10 * smallest: + warn( + f"The largest eigenvalue of the {len(picks)}-channel {ch_type} " + f"covariance (rank={this_rank}) is over 10 orders of magnitude " + f"larger than the smallest ({largest:0.3g} > 1e10 * {smallest:0.3g}), " + "the resulting whitener will likely be unstable" + ) + + # XXX : also handle ref for sEEG and ECoG + if ( + ch_type == "eeg" + and _needs_eeg_average_ref_proj(info) + and not _has_eeg_average_ref_proj(info, projs=projs) + ): + warn( + 'No average EEG reference present in info["projs"], ' + "covariance may be adversely affected. Consider recomputing " + "covariance using with an average eeg reference projector " + "added." + ) + return eig, eigvec, mask + + +@verbose +def regularize( + cov, + info, + mag=0.1, + grad=0.1, + eeg=0.1, + exclude="bads", + proj=True, + seeg=0.1, + ecog=0.1, + hbo=0.1, + hbr=0.1, + fnirs_cw_amplitude=0.1, + fnirs_fd_ac_amplitude=0.1, + fnirs_fd_phase=0.1, + fnirs_od=0.1, + csd=0.1, + dbs=0.1, + rank=None, + scalings=None, + verbose=None, +): + """Regularize noise covariance matrix. + + This method works by adding a constant to the diagonal for each + channel type separately. Special care is taken to keep the + rank of the data constant. + + .. note:: This function is kept for reasons of backward-compatibility. + Please consider explicitly using the ``method`` parameter in + :func:`mne.compute_covariance` to directly combine estimation + with regularization in a data-driven fashion. See the + :ref:`FAQ ` for more information. + + Parameters + ---------- + cov : Covariance + The noise covariance matrix. + %(info_not_none)s (Used to get channel types and bad channels). + mag : float (default 0.1) + Regularization factor for MEG magnetometers. + grad : float (default 0.1) + Regularization factor for MEG gradiometers. Must be the same as + ``mag`` if data have been processed with SSS. + eeg : float (default 0.1) + Regularization factor for EEG. + exclude : list | 'bads' (default 'bads') + List of channels to mark as bad. If 'bads', bads channels + are extracted from both info['bads'] and cov['bads']. + proj : bool (default True) + Apply projections to keep rank of data. + seeg : float (default 0.1) + Regularization factor for sEEG signals. + ecog : float (default 0.1) + Regularization factor for ECoG signals. + hbo : float (default 0.1) + Regularization factor for HBO signals. + hbr : float (default 0.1) + Regularization factor for HBR signals. + fnirs_cw_amplitude : float (default 0.1) + Regularization factor for fNIRS CW raw signals. + fnirs_fd_ac_amplitude : float (default 0.1) + Regularization factor for fNIRS FD AC raw signals. + fnirs_fd_phase : float (default 0.1) + Regularization factor for fNIRS raw phase signals. + fnirs_od : float (default 0.1) + Regularization factor for fNIRS optical density signals. + csd : float (default 0.1) + Regularization factor for EEG-CSD signals. + dbs : float (default 0.1) + Regularization factor for DBS signals. + %(rank_none)s + + .. versionadded:: 0.17 + + .. versionadded:: 0.18 + Support for 'info' mode. + scalings : dict | None + Data will be rescaled before rank estimation to improve accuracy. + See :func:`mne.compute_covariance`. + + .. versionadded:: 0.17 + %(verbose)s + + Returns + ------- + reg_cov : Covariance + The regularized covariance matrix. + + See Also + -------- + mne.compute_covariance + """ # noqa: E501 + cov = cov.copy() + info._check_consistency() + scalings = _handle_default("scalings_cov_rank", scalings) + regs = dict( + eeg=eeg, + seeg=seeg, + dbs=dbs, + ecog=ecog, + hbo=hbo, + hbr=hbr, + fnirs_cw_amplitude=fnirs_cw_amplitude, + fnirs_fd_ac_amplitude=fnirs_fd_ac_amplitude, + fnirs_fd_phase=fnirs_fd_phase, + fnirs_od=fnirs_od, + csd=csd, + ) + + if exclude is None: + raise ValueError('exclude must be a list of strings or "bads"') + + if exclude == "bads": + exclude = info["bads"] + cov["bads"] + + picks_dict = {ch_type: [] for ch_type in _DATA_CH_TYPES_SPLIT} + meg_combined = "auto" if rank != "full" else False + picks_dict.update( + dict( + _picks_by_type( + info, meg_combined=meg_combined, exclude=exclude, ref_meg=False + ) + ) + ) + if len(picks_dict.get("meg", [])) > 0 and rank != "full": # combined + if mag != grad: + raise ValueError( + "On data where magnetometers and gradiometers are dependent (e.g., " + f"SSSed data), mag ({mag}) must equal grad ({grad})" + ) + logger.info("Regularizing MEG channels jointly") + regs["meg"] = mag + else: + regs.update(mag=mag, grad=grad) + if rank != "full": + rank = _compute_rank(cov, rank, scalings, info) + + info_ch_names = info["ch_names"] + ch_names_by_type = dict() + for ch_type, picks_type in picks_dict.items(): + ch_names_by_type[ch_type] = [info_ch_names[i] for i in picks_type] + + # This actually removes bad channels from the cov, which is not backward + # compatible, so let's leave all channels in + cov_good = pick_channels_cov( + cov, include=info_ch_names, exclude=exclude, ordered=False + ) + ch_names = cov_good.ch_names + + # Now get the indices for each channel type in the cov + idx_cov = {ch_type: [] for ch_type in ch_names_by_type} + for i, ch in enumerate(ch_names): + for ch_type in ch_names_by_type: + if ch in ch_names_by_type[ch_type]: + idx_cov[ch_type].append(i) + break + else: + raise Exception(f"channel {ch} is unknown type") + + C = cov_good["data"] + + assert len(C) == sum(map(len, idx_cov.values())) + + if proj: + projs = info["projs"] + cov_good["projs"] + projs = _activate_proj(projs) + + for ch_type in idx_cov: + desc = ch_type.upper() + idx = idx_cov[ch_type] + if len(idx) == 0: + continue + reg = regs[ch_type] + if reg == 0.0: + logger.info(f" {desc} regularization : None") + continue + logger.info(f" {desc} regularization : {reg}") + + this_C = C[np.ix_(idx, idx)] + U = np.eye(this_C.shape[0]) + this_ch_names = [ch_names[k] for k in idx] + if rank == "full": + if proj: + P, ncomp, _ = _make_projector(projs, this_ch_names) + if ncomp > 0: + # This adjustment ends up being redundant if rank is None: + U = _safe_svd(P)[0][:, :-ncomp] + logger.info( + f" Created an SSP operator for {desc} (dimension = {ncomp})" + ) + else: + this_picks = pick_channels(info["ch_names"], this_ch_names) + this_info = pick_info(info, this_picks) + # Here we could use proj_subspace=True, but this should not matter + # since this is already in a loop over channel types + _, eigvec, mask = _smart_eigh(this_C, this_info, rank) + U = eigvec[mask].T + this_C = np.dot(U.T, np.dot(this_C, U)) + + sigma = np.mean(np.diag(this_C)) + this_C.flat[:: len(this_C) + 1] += reg * sigma # modify diag inplace + this_C = np.dot(U, np.dot(this_C, U.T)) + C[np.ix_(idx, idx)] = this_C + + # Put data back in correct locations + idx = pick_channels(cov.ch_names, info_ch_names, exclude=exclude, ordered=False) + cov["data"][np.ix_(idx, idx)] = C + + return cov + + +@verbose +def _regularized_covariance( + data, + reg=None, + method_params=None, + info=None, + rank=None, + *, + log_ch_type=None, + log_rank=None, + cov_kind="", + # backward-compat default for decoding (maybe someday we want to expose this but + # it's likely too invasive and since it's usually regularized, unnecessary): + on_few_samples="ignore", + verbose=None, +): + """Compute a regularized covariance from data using sklearn. + + This is a convenience wrapper for mne.decoding functions, which + adopted a slightly different covariance API. + + Returns + ------- + cov : ndarray, shape (n_channels, n_channels) + The covariance matrix. + """ + _validate_type(reg, (str, "numeric", None)) + if reg is None: + reg = "empirical" + elif not isinstance(reg, str): + reg = float(reg) + if method_params is not None: + raise ValueError( + "If reg is a float, method_params must be None (got " + f"{type(method_params)})" + ) + method_params = dict( + shrinkage=dict(shrinkage=reg, assume_centered=True, store_precision=False) + ) + reg = "shrinkage" + method, method_params = _check_method_params( + reg, method_params, name="reg", allow_auto=False, rank=rank + ) + # use mag instead of eeg here to avoid the cov EEG projection warning + info = create_info(data.shape[-2], 1000.0, "mag") if info is None else info + picks_list = _picks_by_type(info) + scalings = _handle_default("scalings_cov_rank", None) + cov = _compute_covariance_auto( + data.T, + method=method, + method_params=method_params, + info=info, + cv=None, + n_jobs=None, + stop_early=True, + picks_list=picks_list, + scalings=scalings, + rank=rank, + cov_kind=cov_kind, + log_ch_type=log_ch_type, + log_rank=log_rank, + on_few_samples=on_few_samples, + )[reg]["data"] + return cov + + +@verbose +def compute_whitener( + noise_cov, + info=None, + picks=None, + rank=None, + scalings=None, + return_rank=False, + pca=False, + return_colorer=False, + on_rank_mismatch="warn", + verbose=None, +): + """Compute whitening matrix. + + Parameters + ---------- + noise_cov : Covariance + The noise covariance. + %(info)s Can be None if ``noise_cov`` has already been + prepared with :func:`prepare_noise_cov`. + %(picks_good_data_noref)s + %(rank_none)s + + .. versionadded:: 0.18 + Support for 'info' mode. + scalings : dict | None + The rescaling method to be applied. See documentation of + ``prepare_noise_cov`` for details. + return_rank : bool + If True, return the rank used to compute the whitener. + + .. versionadded:: 0.15 + pca : bool | str + Space to project the data into. Options: + + :data:`python:True` + Whitener will be shape (n_nonzero, n_channels). + ``'white'`` + Whitener will be shape (n_channels, n_channels), potentially rank + deficient, and have the first ``n_channels - n_nonzero`` rows and + columns set to zero. + :data:`python:False` (default) + Whitener will be shape (n_channels, n_channels), potentially rank + deficient, and rotated back to the space of the original data. + + .. versionadded:: 0.18 + return_colorer : bool + If True, return the colorer as well. + %(on_rank_mismatch)s + %(verbose)s + + Returns + ------- + W : ndarray, shape (n_channels, n_channels) or (n_nonzero, n_channels) + The whitening matrix. + ch_names : list + The channel names. + rank : int + Rank reduction of the whitener. Returned only if return_rank is True. + colorer : ndarray, shape (n_channels, n_channels) or (n_channels, n_nonzero) + The coloring matrix. + """ # noqa: E501 + _validate_type(pca, (str, bool), "space") + _valid_pcas = (True, "white", False) + if pca not in _valid_pcas: + raise ValueError(f"space must be one of {_valid_pcas}, got {pca}") + if info is None: + if "eig" not in noise_cov: + raise ValueError( + "info can only be None if the noise cov has already been prepared with " + "prepare_noise_cov" + ) + ch_names = deepcopy(noise_cov["names"]) + else: + picks = _picks_to_idx(info, picks, with_ref_meg=False) + ch_names = [info["ch_names"][k] for k in picks] + del picks + noise_cov = prepare_noise_cov( + noise_cov, info, ch_names, rank, scalings, on_rank_mismatch=on_rank_mismatch + ) + + n_chan = len(ch_names) + assert n_chan == len(noise_cov["eig"]) + + # Omit the zeroes due to projection + eig = noise_cov["eig"].copy() + nzero = eig > 0 + eig[~nzero] = 0.0 # get rid of numerical noise (negative) ones + + if noise_cov["eigvec"].dtype.kind == "c": + dtype = np.complex128 + else: + dtype = np.float64 + W = np.zeros((n_chan, 1), dtype) + W[nzero, 0] = 1.0 / np.sqrt(eig[nzero]) + # Rows of eigvec are the eigenvectors + W = W * noise_cov["eigvec"] # C ** -0.5 + C = np.sqrt(eig) * noise_cov["eigvec"].conj().T # C ** 0.5 + n_nzero = nzero.sum() + logger.info( + " Created the whitener using a noise covariance matrix " + "with rank %d (%d small eigenvalues omitted)", + n_nzero, + noise_cov["dim"] - n_nzero, + ) + + # Do the requested projection + if pca is True: + W = W[nzero] + C = C[:, nzero] + elif pca is False: + W = np.dot(noise_cov["eigvec"].conj().T, W) + C = np.dot(C, noise_cov["eigvec"]) + + # Triage return + out = W, ch_names + if return_rank: + out += (n_nzero,) + if return_colorer: + out += (C,) + return out + + +@verbose +def whiten_evoked( + evoked, noise_cov, picks=None, diag=None, rank=None, scalings=None, verbose=None +): + """Whiten evoked data using given noise covariance. + + Parameters + ---------- + evoked : instance of Evoked + The evoked data. + noise_cov : instance of Covariance + The noise covariance. + %(picks_good_data)s + diag : bool (default False) + If True, whiten using only the diagonal of the covariance. + %(rank_none)s + + .. versionadded:: 0.18 + Support for 'info' mode. + scalings : dict | None (default None) + To achieve reliable rank estimation on multiple sensors, + sensors have to be rescaled. This parameter controls the + rescaling. If dict, it will override the + following default dict (default if None): + + dict(mag=1e12, grad=1e11, eeg=1e5) + %(verbose)s + + Returns + ------- + evoked_white : instance of Evoked + The whitened evoked data. + """ + evoked = evoked.copy() + picks = _picks_to_idx(evoked.info, picks) + + if diag: + noise_cov = noise_cov.as_diag() + + W, _ = compute_whitener( + noise_cov, evoked.info, picks=picks, rank=rank, scalings=scalings + ) + + evoked.data[picks] = np.sqrt(evoked.nave) * np.dot(W, evoked.data[picks]) + return evoked + + +@verbose +def _read_cov(fid, node, cov_kind, limited=False, verbose=None): + """Read a noise covariance matrix.""" + # Find all covariance matrices + from ._fiff.write import _safe_name_list + + covs = dir_tree_find(node, FIFF.FIFFB_MNE_COV) + if len(covs) == 0: + raise ValueError("No covariance matrices found") + + # Is any of the covariance matrices a noise covariance + for p in range(len(covs)): + tag = find_tag(fid, covs[p], FIFF.FIFF_MNE_COV_KIND) + + if tag is not None and int(tag.data.item()) == cov_kind: + this = covs[p] + + # Find all the necessary data + tag = find_tag(fid, this, FIFF.FIFF_MNE_COV_DIM) + if tag is None: + raise ValueError("Covariance matrix dimension not found") + dim = int(tag.data.item()) + + tag = find_tag(fid, this, FIFF.FIFF_MNE_COV_NFREE) + if tag is None: + nfree = -1 + else: + nfree = int(tag.data.item()) + + tag = find_tag(fid, this, FIFF.FIFF_MNE_COV_METHOD) + if tag is None: + method = None + else: + method = tag.data + + tag = find_tag(fid, this, FIFF.FIFF_MNE_COV_SCORE) + if tag is None: + score = None + else: + score = tag.data[0] + + tag = find_tag(fid, this, FIFF.FIFF_MNE_ROW_NAMES) + if tag is None: + names = [] + else: + names = _safe_name_list(tag.data, "read", "names") + if len(names) != dim: + raise ValueError( + "Number of names does not match covariance matrix dimension" + ) + + tag = find_tag(fid, this, FIFF.FIFF_MNE_COV) + if tag is None: + tag = find_tag(fid, this, FIFF.FIFF_MNE_COV_DIAG) + if tag is None: + raise ValueError("No covariance matrix data found") + else: + # Diagonal is stored + data = tag.data + diag = True + logger.info( + " %d x %d diagonal covariance (kind = %d) found.", + dim, + dim, + cov_kind, + ) + + else: + if not issparse(tag.data): + # Lower diagonal is stored + vals = tag.data + data = np.zeros((dim, dim)) + data[np.tril(np.ones((dim, dim))) > 0] = vals + data = data + data.T + data.flat[:: dim + 1] /= 2.0 + diag = False + logger.info( + " %d x %d full covariance (kind = %d) found.", + dim, + dim, + cov_kind, + ) + else: + diag = False + data = tag.data + logger.info( + " %d x %d sparse covariance (kind = %d) found.", + dim, + dim, + cov_kind, + ) + + # Read the possibly precomputed decomposition + tag1 = find_tag(fid, this, FIFF.FIFF_MNE_COV_EIGENVALUES) + tag2 = find_tag(fid, this, FIFF.FIFF_MNE_COV_EIGENVECTORS) + if tag1 is not None and tag2 is not None: + eig = tag1.data + eigvec = tag2.data + else: + eig = None + eigvec = None + + # Read the projection operator + projs = _read_proj(fid, this) + + # Read the bad channel list + bads = _read_bad_channels(fid, this, None) + + # Put it together + assert dim == len(data) + assert data.ndim == (1 if diag else 2) + cov = dict( + kind=cov_kind, + diag=diag, + dim=dim, + names=names, + data=data, + projs=projs, + bads=bads, + nfree=nfree, + eig=eig, + eigvec=eigvec, + ) + if score is not None: + cov["loglik"] = score + if method is not None: + cov["method"] = method + if limited: + del cov["kind"], cov["dim"], cov["diag"] + + return cov + + logger.info(" Did not find the desired covariance matrix (kind = %d)", cov_kind) + + return None + + +def _write_cov(fid, cov): + """Write a noise covariance matrix.""" + from ._fiff.write import ( + end_block, + start_block, + write_double, + write_float_matrix, + write_int, + write_name_list_sanitized, + write_string, + ) + + start_block(fid, FIFF.FIFFB_MNE_COV) + + # Dimensions etc. + write_int(fid, FIFF.FIFF_MNE_COV_KIND, cov["kind"]) + write_int(fid, FIFF.FIFF_MNE_COV_DIM, cov["dim"]) + if cov["nfree"] > 0: + write_int(fid, FIFF.FIFF_MNE_COV_NFREE, cov["nfree"]) + + # Channel names + if cov["names"] is not None and len(cov["names"]) > 0: + write_name_list_sanitized( + fid, FIFF.FIFF_MNE_ROW_NAMES, cov["names"], 'cov["names"]' + ) + + # Data + if cov["diag"]: + write_double(fid, FIFF.FIFF_MNE_COV_DIAG, cov["data"]) + else: + # Store only lower part of covariance matrix + dim = cov["dim"] + mask = np.tril(np.ones((dim, dim), dtype=bool)) > 0 + vals = cov["data"][mask].ravel() + write_double(fid, FIFF.FIFF_MNE_COV, vals) + + # Eigenvalues and vectors if present + if cov["eig"] is not None and cov["eigvec"] is not None: + write_float_matrix(fid, FIFF.FIFF_MNE_COV_EIGENVECTORS, cov["eigvec"]) + write_double(fid, FIFF.FIFF_MNE_COV_EIGENVALUES, cov["eig"]) + + # Projection operator + if cov["projs"] is not None and len(cov["projs"]) > 0: + _write_proj(fid, cov["projs"]) + + # Bad channels + _write_bad_channels(fid, cov["bads"], None) + + # estimator method + if "method" in cov: + write_string(fid, FIFF.FIFF_MNE_COV_METHOD, cov["method"]) + + # negative log-likelihood score + if "loglik" in cov: + write_double(fid, FIFF.FIFF_MNE_COV_SCORE, np.array(cov["loglik"])) + + # Done! + end_block(fid, FIFF.FIFFB_MNE_COV) + + +@verbose +def _ensure_cov(cov, name="cov", *, verbose=None): + _validate_type(cov, ("path-like", Covariance), name) + logger.info(f"Noise covariance : {cov}") + if not isinstance(cov, Covariance): + cov = read_cov(cov, verbose=_verbose_safe_false()) + return cov diff --git a/mne-python/source/mne/cuda.py b/mne-python/source/mne/cuda.py new file mode 100644 index 0000000000000000000000000000000000000000..ce46207563d87e1230d29af5e4b8fa13793df369 --- /dev/null +++ b/mne-python/source/mne/cuda.py @@ -0,0 +1,393 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +from scipy.fft import irfft, rfft + +from .utils import ( + _check_option, + _explain_exception, + fill_doc, + get_config, + logger, + sizeof_fmt, + verbose, + warn, +) + +_cuda_capable = False + + +def get_cuda_memory(kind="available"): + """Get the amount of free memory for CUDA operations. + + Parameters + ---------- + kind : str + Can be ``"available"`` or ``"total"``. + + Returns + ------- + memory : str + The amount of available or total memory as a human-readable string. + """ + if not _cuda_capable: + warn("CUDA not enabled, returning zero for memory") + mem = 0 + else: + import cupy + + mem = cupy.cuda.runtime.memGetInfo()[dict(available=0, total=1)[kind]] + return sizeof_fmt(mem) + + +@verbose +def init_cuda(ignore_config=False, verbose=None): + """Initialize CUDA functionality. + + This function attempts to load the necessary interfaces + (hardware connectivity) to run CUDA-based filtering. This + function should only need to be run once per session. + + If the config var (set via mne.set_config or in ENV) + MNE_USE_CUDA == 'true', this function will be executed when + the first CUDA setup is performed. If this variable is not + set, this function can be manually executed. + + Parameters + ---------- + ignore_config : bool + If True, ignore the config value MNE_USE_CUDA and force init. + %(verbose)s + """ + global _cuda_capable + if _cuda_capable: + return + if not ignore_config and (get_config("MNE_USE_CUDA", "false").lower() != "true"): + logger.info("CUDA not enabled in config, skipping initialization") + return + # Triage possible errors for informative messaging + _cuda_capable = False + try: + import cupy # noqa + except ImportError: + warn("module cupy not found, CUDA not enabled") + return + device_id = int(get_config("MNE_CUDA_DEVICE", "0")) + try: + # Initialize CUDA + _set_cuda_device(device_id, verbose) + except Exception: + warn( + "so CUDA device could be initialized, likely a hardware error, " + f"CUDA not enabled{_explain_exception()}" + ) + return + + _cuda_capable = True + # Figure out limit for CUDA FFT calculations + logger.info(f"Enabling CUDA with {get_cuda_memory()} available memory") + + +@verbose +def set_cuda_device(device_id, verbose=None): + """Set the CUDA device temporarily for the current session. + + Parameters + ---------- + device_id : int + Numeric ID of the CUDA-capable device you want MNE-Python to use. + %(verbose)s + """ + if _cuda_capable: + _set_cuda_device(device_id, verbose) + elif get_config("MNE_USE_CUDA", "false").lower() == "true": + init_cuda() + _set_cuda_device(device_id, verbose) + else: + warn( + "Could not set CUDA device because CUDA is not enabled; either " + "run mne.cuda.init_cuda() first, or set the MNE_USE_CUDA config " + 'variable to "true".' + ) + + +@verbose +def _set_cuda_device(device_id, verbose=None): + """Set the CUDA device.""" + import cupy + + cupy.cuda.Device(device_id).use() + logger.info(f"Now using CUDA device {device_id}") + + +############################################################################### +# Repeated FFT multiplication + + +def _setup_cuda_fft_multiply_repeated(n_jobs, h, n_fft, kind="FFT FIR filtering"): + """Set up repeated CUDA FFT multiplication with a given filter. + + Parameters + ---------- + n_jobs : int | str + If ``n_jobs='cuda'``, the function will attempt to set up for CUDA + FFT multiplication. + h : array + The filtering function that will be used repeatedly. + n_fft : int + The number of points in the FFT. + kind : str + The kind to report to the user. + + Returns + ------- + n_jobs : int + Sets n_jobs = 1 if n_jobs == 'cuda' was passed in, otherwise + original n_jobs is passed. + cuda_dict : dict + Dictionary with the following CUDA-related variables: + use_cuda : bool + Whether CUDA should be used. + fft_plan : instance of FFTPlan + FFT plan to use in calculating the FFT. + ifft_plan : instance of FFTPlan + FFT plan to use in calculating the IFFT. + x_fft : instance of gpuarray + Empty allocated GPU space for storing the result of the + frequency-domain multiplication. + x : instance of gpuarray + Empty allocated GPU space for the data to filter. + h_fft : array | instance of gpuarray + This will either be a gpuarray (if CUDA enabled) or ndarray. + + Notes + ----- + This function is designed to be used with fft_multiply_repeated(). + """ + cuda_dict = dict(n_fft=n_fft, rfft=rfft, irfft=irfft, h_fft=rfft(h, n=n_fft)) + if isinstance(n_jobs, str): + _check_option("n_jobs", n_jobs, ("cuda",)) + n_jobs = 1 + init_cuda() + if _cuda_capable: + import cupy + + try: + # do the IFFT normalization now so we don't have to later + h_fft = cupy.array(cuda_dict["h_fft"]) + logger.info(f"Using CUDA for {kind}") + except Exception as exp: + logger.info( + "CUDA not used, could not instantiate memory (arrays may be too " + f'large: "{exp}"), falling back to n_jobs=None' + ) + cuda_dict.update(h_fft=h_fft, rfft=_cuda_upload_rfft, irfft=_cuda_irfft_get) + else: + logger.info( + "CUDA not used, CUDA could not be initialized, " + "falling back to n_jobs=None" + ) + return n_jobs, cuda_dict + + +def _fft_multiply_repeated(x, cuda_dict): + """Do FFT multiplication by a filter function (possibly using CUDA). + + Parameters + ---------- + h_fft : 1-d array or gpuarray + The filtering array to apply. + x : 1-d array + The array to filter. + n_fft : int + The number of points in the FFT. + cuda_dict : dict + Dictionary constructed using setup_cuda_multiply_repeated(). + + Returns + ------- + x : 1-d array + Filtered version of x. + """ + # do the fourier-domain operations + x_fft = cuda_dict["rfft"](x, cuda_dict["n_fft"]) + x_fft *= cuda_dict["h_fft"] + x = cuda_dict["irfft"](x_fft, cuda_dict["n_fft"]) + return x + + +############################################################################### +# FFT Resampling + + +def _setup_cuda_fft_resample(n_jobs, W, new_len): + """Set up CUDA FFT resampling. + + Parameters + ---------- + n_jobs : int | str + If n_jobs == 'cuda', the function will attempt to set up for CUDA + FFT resampling. + W : array + The filtering function to be used during resampling. + If n_jobs='cuda', this function will be shortened (since CUDA + assumes FFTs of real signals are half the length of the signal) + and turned into a gpuarray. + new_len : int + The size of the array following resampling. + + Returns + ------- + n_jobs : int + Sets n_jobs = 1 if n_jobs == 'cuda' was passed in, otherwise + original n_jobs is passed. + cuda_dict : dict + Dictionary with the following CUDA-related variables: + use_cuda : bool + Whether CUDA should be used. + fft_plan : instance of FFTPlan + FFT plan to use in calculating the FFT. + ifft_plan : instance of FFTPlan + FFT plan to use in calculating the IFFT. + x_fft : instance of gpuarray + Empty allocated GPU space for storing the result of the + frequency-domain multiplication. + x : instance of gpuarray + Empty allocated GPU space for the data to resample. + + Notes + ----- + This function is designed to be used with fft_resample(). + """ + cuda_dict = dict(use_cuda=False, rfft=rfft, irfft=irfft) + rfft_len_x = len(W) // 2 + 1 + # fold the window onto inself (should be symmetric) and truncate + W = W.copy() + W[1:rfft_len_x] = (W[1:rfft_len_x] + W[::-1][: rfft_len_x - 1]) / 2.0 + W = W[:rfft_len_x] + if isinstance(n_jobs, str): + _check_option("n_jobs", n_jobs, ("cuda",)) + n_jobs = 1 + init_cuda() + if _cuda_capable: + try: + import cupy + + # do the IFFT normalization now so we don't have to later + W = cupy.array(W) + logger.info("Using CUDA for FFT resampling") + except Exception: + logger.info( + "CUDA not used, could not instantiate memory " + "(arrays may be too large), falling back to " + "n_jobs=None" + ) + else: + cuda_dict.update( + use_cuda=True, rfft=_cuda_upload_rfft, irfft=_cuda_irfft_get + ) + else: + logger.info( + "CUDA not used, CUDA could not be initialized, " + "falling back to n_jobs=None" + ) + cuda_dict["W"] = W + return n_jobs, cuda_dict + + +def _cuda_upload_rfft(x, n, axis=-1): + """Upload and compute rfft.""" + import cupy + + return cupy.fft.rfft(cupy.array(x), n=n, axis=axis) + + +def _cuda_irfft_get(x, n, axis=-1): + """Compute irfft and get.""" + import cupy + + return cupy.fft.irfft(x, n=n, axis=axis).get() + + +@fill_doc +def _fft_resample(x, new_len, npads, to_removes, cuda_dict=None, pad="reflect_limited"): + """Do FFT resampling with a filter function (possibly using CUDA). + + Parameters + ---------- + x : 1-d array + The array to resample. Will be converted to float64 if necessary. + new_len : int + The size of the output array (before removing padding). + npads : tuple of int + Amount of padding to apply to the start and end of the + signal before resampling. + to_removes : tuple of int + Number of samples to remove after resampling. + cuda_dict : dict + Dictionary constructed using setup_cuda_multiply_repeated(). + %(pad_resample)s + The default is ``'reflect_limited'``. + + .. versionadded:: 0.15 + + Returns + ------- + x : 1-d array + Filtered version of x. + """ + cuda_dict = dict(use_cuda=False) if cuda_dict is None else cuda_dict + # add some padding at beginning and end to make this work a little cleaner + if x.dtype != np.float64: + x = x.astype(np.float64) + x = _smart_pad(x, npads, pad) + old_len = len(x) + shorter = new_len < old_len + use_len = new_len if shorter else old_len + x_fft = cuda_dict["rfft"](x, None) + if use_len % 2 == 0: + nyq = use_len // 2 + x_fft[nyq : nyq + 1] *= 2 if shorter else 0.5 + x_fft *= cuda_dict["W"] + y = cuda_dict["irfft"](x_fft, new_len) + + # now let's trim it back to the correct size (if there was padding) + if (to_removes > 0).any(): + y = y[to_removes[0] : y.shape[0] - to_removes[1]] + + return y + + +############################################################################### +# Misc + + +# this has to go in mne.cuda instead of mne.filter to avoid import errors +def _smart_pad(x, n_pad, pad="reflect_limited"): + """Pad vector x.""" + n_pad = np.asarray(n_pad) + assert n_pad.shape == (2,) + if (n_pad == 0).all(): + return x + elif (n_pad < 0).any(): + raise RuntimeError("n_pad must be non-negative") + if pad == "reflect_limited": + l_z_pad = np.zeros(max(n_pad[0] - len(x) + 1, 0), dtype=x.dtype) + r_z_pad = np.zeros(max(n_pad[1] - len(x) + 1, 0), dtype=x.dtype) + out = np.concatenate( + [ + l_z_pad, + 2 * x[0] - x[n_pad[0] : 0 : -1], + x, + 2 * x[-1] - x[-2 : -n_pad[1] - 2 : -1], + r_z_pad, + ] + ) + else: + kwargs = dict() + if pad == "reflect": + kwargs["reflect_type"] = "odd" + out = np.pad(x, (tuple(n_pad),), pad, **kwargs) + return out diff --git a/mne-python/source/mne/data/FreeSurferColorLUT.txt b/mne-python/source/mne/data/FreeSurferColorLUT.txt new file mode 100644 index 0000000000000000000000000000000000000000..ca285e937b8f954b2630ea8829910c8eb46c275d --- /dev/null +++ b/mne-python/source/mne/data/FreeSurferColorLUT.txt @@ -0,0 +1,1397 @@ +#$Id: FreeSurferColorLUT.txt,v 1.70.2.7 2012/08/27 17:20:08 nicks Exp $ + +#No. Label Name: R G B A + +0 Unknown 0 0 0 0 +1 Left-Cerebral-Exterior 70 130 180 0 +2 Left-Cerebral-White-Matter 245 245 245 0 +3 Left-Cerebral-Cortex 205 62 78 0 +4 Left-Lateral-Ventricle 120 18 134 0 +5 Left-Inf-Lat-Vent 196 58 250 0 +6 Left-Cerebellum-Exterior 0 148 0 0 +7 Left-Cerebellum-White-Matter 220 248 164 0 +8 Left-Cerebellum-Cortex 230 148 34 0 +9 Left-Thalamus 0 118 14 0 +10 Left-Thalamus-Proper 0 118 14 0 +11 Left-Caudate 122 186 220 0 +12 Left-Putamen 236 13 176 0 +13 Left-Pallidum 12 48 255 0 +14 3rd-Ventricle 204 182 142 0 +15 4th-Ventricle 42 204 164 0 +16 Brain-Stem 119 159 176 0 +17 Left-Hippocampus 220 216 20 0 +18 Left-Amygdala 103 255 255 0 +19 Left-Insula 80 196 98 0 +20 Left-Operculum 60 58 210 0 +21 Line-1 60 58 210 0 +22 Line-2 60 58 210 0 +23 Line-3 60 58 210 0 +24 CSF 60 60 60 0 +25 Left-Lesion 255 165 0 0 +26 Left-Accumbens-area 255 165 0 0 +27 Left-Substancia-Nigra 0 255 127 0 +28 Left-VentralDC 165 42 42 0 +29 Left-undetermined 135 206 235 0 +30 Left-vessel 160 32 240 0 +31 Left-choroid-plexus 0 200 200 0 +32 Left-F3orb 100 50 100 0 +33 Left-lOg 135 50 74 0 +34 Left-aOg 122 135 50 0 +35 Left-mOg 51 50 135 0 +36 Left-pOg 74 155 60 0 +37 Left-Stellate 120 62 43 0 +38 Left-Porg 74 155 60 0 +39 Left-Aorg 122 135 50 0 +40 Right-Cerebral-Exterior 70 130 180 0 +41 Right-Cerebral-White-Matter 0 225 0 0 +42 Right-Cerebral-Cortex 205 62 78 0 +43 Right-Lateral-Ventricle 120 18 134 0 +44 Right-Inf-Lat-Vent 196 58 250 0 +45 Right-Cerebellum-Exterior 0 148 0 0 +46 Right-Cerebellum-White-Matter 220 248 164 0 +47 Right-Cerebellum-Cortex 230 148 34 0 +48 Right-Thalamus 0 118 14 0 +49 Right-Thalamus-Proper 0 118 14 0 +50 Right-Caudate 122 186 220 0 +51 Right-Putamen 236 13 176 0 +52 Right-Pallidum 13 48 255 0 +53 Right-Hippocampus 220 216 20 0 +54 Right-Amygdala 103 255 255 0 +55 Right-Insula 80 196 98 0 +56 Right-Operculum 60 58 210 0 +57 Right-Lesion 255 165 0 0 +58 Right-Accumbens-area 255 165 0 0 +59 Right-Substancia-Nigra 0 255 127 0 +60 Right-VentralDC 165 42 42 0 +61 Right-undetermined 135 206 235 0 +62 Right-vessel 160 32 240 0 +63 Right-choroid-plexus 0 200 221 0 +64 Right-F3orb 100 50 100 0 +65 Right-lOg 135 50 74 0 +66 Right-aOg 122 135 50 0 +67 Right-mOg 51 50 135 0 +68 Right-pOg 74 155 60 0 +69 Right-Stellate 120 62 43 0 +70 Right-Porg 74 155 60 0 +71 Right-Aorg 122 135 50 0 +72 5th-Ventricle 120 190 150 0 +73 Left-Interior 122 135 50 0 +74 Right-Interior 122 135 50 0 +# 75/76 removed. duplicates of 4/43 +77 WM-hypointensities 200 70 255 0 +78 Left-WM-hypointensities 255 148 10 0 +79 Right-WM-hypointensities 255 148 10 0 +80 non-WM-hypointensities 164 108 226 0 +81 Left-non-WM-hypointensities 164 108 226 0 +82 Right-non-WM-hypointensities 164 108 226 0 +83 Left-F1 255 218 185 0 +84 Right-F1 255 218 185 0 +85 Optic-Chiasm 234 169 30 0 +192 Corpus_Callosum 250 255 50 0 + +86 Left_future_WMSA 200 120 255 0 +87 Right_future_WMSA 200 121 255 0 +88 future_WMSA 200 122 255 0 + + +96 Left-Amygdala-Anterior 205 10 125 0 +97 Right-Amygdala-Anterior 205 10 125 0 +98 Dura 160 32 240 0 + +100 Left-wm-intensity-abnormality 124 140 178 0 +101 Left-caudate-intensity-abnormality 125 140 178 0 +102 Left-putamen-intensity-abnormality 126 140 178 0 +103 Left-accumbens-intensity-abnormality 127 140 178 0 +104 Left-pallidum-intensity-abnormality 124 141 178 0 +105 Left-amygdala-intensity-abnormality 124 142 178 0 +106 Left-hippocampus-intensity-abnormality 124 143 178 0 +107 Left-thalamus-intensity-abnormality 124 144 178 0 +108 Left-VDC-intensity-abnormality 124 140 179 0 +109 Right-wm-intensity-abnormality 124 140 178 0 +110 Right-caudate-intensity-abnormality 125 140 178 0 +111 Right-putamen-intensity-abnormality 126 140 178 0 +112 Right-accumbens-intensity-abnormality 127 140 178 0 +113 Right-pallidum-intensity-abnormality 124 141 178 0 +114 Right-amygdala-intensity-abnormality 124 142 178 0 +115 Right-hippocampus-intensity-abnormality 124 143 178 0 +116 Right-thalamus-intensity-abnormality 124 144 178 0 +117 Right-VDC-intensity-abnormality 124 140 179 0 + +118 Epidermis 255 20 147 0 +119 Conn-Tissue 205 179 139 0 +120 SC-Fat-Muscle 238 238 209 0 +121 Cranium 200 200 200 0 +122 CSF-SA 74 255 74 0 +123 Muscle 238 0 0 0 +124 Ear 0 0 139 0 +125 Adipose 173 255 47 0 +126 Spinal-Cord 133 203 229 0 +127 Soft-Tissue 26 237 57 0 +128 Nerve 34 139 34 0 +129 Bone 30 144 255 0 +130 Air 147 19 173 0 +131 Orbital-Fat 238 59 59 0 +132 Tongue 221 39 200 0 +133 Nasal-Structures 238 174 238 0 +134 Globe 255 0 0 0 +135 Teeth 72 61 139 0 +136 Left-Caudate-Putamen 21 39 132 0 +137 Right-Caudate-Putamen 21 39 132 0 +138 Left-Claustrum 65 135 20 0 +139 Right-Claustrum 65 135 20 0 +140 Cornea 134 4 160 0 +142 Diploe 221 226 68 0 +143 Vitreous-Humor 255 255 254 0 +144 Lens 52 209 226 0 +145 Aqueous-Humor 239 160 223 0 +146 Outer-Table 70 130 180 0 +147 Inner-Table 70 130 181 0 +148 Periosteum 139 121 94 0 +149 Endosteum 224 224 224 0 +150 R-C-S 255 0 0 0 +151 Iris 205 205 0 0 +152 SC-Adipose-Muscle 238 238 209 0 +153 SC-Tissue 139 121 94 0 +154 Orbital-Adipose 238 59 59 0 + +155 Left-IntCapsule-Ant 238 59 59 0 +156 Right-IntCapsule-Ant 238 59 59 0 +157 Left-IntCapsule-Pos 62 10 205 0 +158 Right-IntCapsule-Pos 62 10 205 0 + +# These labels are for babies/children +159 Left-Cerebral-WM-unmyelinated 0 118 14 0 +160 Right-Cerebral-WM-unmyelinated 0 118 14 0 +161 Left-Cerebral-WM-myelinated 220 216 21 0 +162 Right-Cerebral-WM-myelinated 220 216 21 0 +163 Left-Subcortical-Gray-Matter 122 186 220 0 +164 Right-Subcortical-Gray-Matter 122 186 220 0 +165 Skull 255 165 0 0 +166 Posterior-fossa 14 48 255 0 +167 Scalp 166 42 42 0 +168 Hematoma 121 18 134 0 +169 Left-Basal-Ganglia 236 13 127 0 +176 Right-Basal-Ganglia 236 13 126 0 + +# Label names and colors for Brainstem constituents +# No. Label Name: R G B A +170 brainstem 119 159 176 0 +171 DCG 119 0 176 0 +172 Vermis 119 100 176 0 +173 Midbrain 119 200 176 0 +174 Pons 119 159 100 0 +175 Medulla 119 159 200 0 + +#176 Right-Basal-Ganglia found in babies/children section above + +180 Left-Cortical-Dysplasia 73 61 139 0 +181 Right-Cortical-Dysplasia 73 62 139 0 + +#192 Corpus_Callosum listed after #85 above +193 Left-hippocampal_fissure 0 196 255 0 +194 Left-CADG-head 255 164 164 0 +195 Left-subiculum 196 196 0 0 +196 Left-fimbria 0 100 255 0 +197 Right-hippocampal_fissure 128 196 164 0 +198 Right-CADG-head 0 126 75 0 +199 Right-subiculum 128 96 64 0 +200 Right-fimbria 0 50 128 0 +201 alveus 255 204 153 0 +202 perforant_pathway 255 128 128 0 +203 parasubiculum 255 255 0 0 +204 presubiculum 64 0 64 0 +205 subiculum 0 0 255 0 +206 CA1 255 0 0 0 +207 CA2 128 128 255 0 +208 CA3 0 128 0 0 +209 CA4 196 160 128 0 +210 GC-ML-DG 32 200 255 0 +211 HATA 128 255 128 0 +212 fimbria 204 153 204 0 +213 lateral_ventricle 121 17 136 0 +214 molecular_layer_HP 128 0 0 0 +215 hippocampal_fissure 128 32 255 0 +216 entorhinal_cortex 255 204 102 0 +217 molecular_layer_subiculum 128 128 128 0 +218 Amygdala 104 255 255 0 +219 Cerebral_White_Matter 0 226 0 0 +220 Cerebral_Cortex 205 63 78 0 +221 Inf_Lat_Vent 197 58 250 0 +222 Perirhinal 33 150 250 0 +223 Cerebral_White_Matter_Edge 226 0 0 0 +224 Background 100 100 100 0 +225 Ectorhinal 197 150 250 0 +226 HP_tail 170 170 255 0 + +250 Fornix 255 0 0 0 +251 CC_Posterior 0 0 64 0 +252 CC_Mid_Posterior 0 0 112 0 +253 CC_Central 0 0 160 0 +254 CC_Mid_Anterior 0 0 208 0 +255 CC_Anterior 0 0 255 0 + +# This is for keeping track of voxel changes +256 Voxel-Unchanged 0 0 0 0 + +# lymph node and vascular labels +331 Aorta 255 0 0 0 +332 Left-Common-IliacA 255 80 0 0 +333 Right-Common-IliacA 255 160 0 0 +334 Left-External-IliacA 255 255 0 0 +335 Right-External-IliacA 0 255 0 0 +336 Left-Internal-IliacA 255 0 160 0 +337 Right-Internal-IliacA 255 0 255 0 +338 Left-Lateral-SacralA 255 50 80 0 +339 Right-Lateral-SacralA 80 255 50 0 +340 Left-ObturatorA 160 255 50 0 +341 Right-ObturatorA 160 200 255 0 +342 Left-Internal-PudendalA 0 255 160 0 +343 Right-Internal-PudendalA 0 0 255 0 +344 Left-UmbilicalA 80 50 255 0 +345 Right-UmbilicalA 160 0 255 0 +346 Left-Inf-RectalA 255 210 0 0 +347 Right-Inf-RectalA 0 160 255 0 +348 Left-Common-IliacV 255 200 80 0 +349 Right-Common-IliacV 255 200 160 0 +350 Left-External-IliacV 255 80 200 0 +351 Right-External-IliacV 255 160 200 0 +352 Left-Internal-IliacV 30 255 80 0 +353 Right-Internal-IliacV 80 200 255 0 +354 Left-ObturatorV 80 255 200 0 +355 Right-ObturatorV 195 255 200 0 +356 Left-Internal-PudendalV 120 200 20 0 +357 Right-Internal-PudendalV 170 10 200 0 +358 Pos-Lymph 20 130 180 0 +359 Neg-Lymph 20 180 130 0 + +400 V1 206 62 78 0 +401 V2 121 18 134 0 +402 BA44 199 58 250 0 +403 BA45 1 148 0 0 +404 BA4a 221 248 164 0 +405 BA4p 231 148 34 0 +406 BA6 1 118 14 0 +407 BA2 120 118 14 0 +408 BA1_old 123 186 221 0 +409 BAun2 238 13 177 0 +410 BA1 123 186 220 0 +411 BA2b 138 13 206 0 +412 BA3a 238 130 176 0 +413 BA3b 218 230 76 0 +414 MT 38 213 176 0 +415 AIPS_AIP_l 1 225 176 0 +416 AIPS_AIP_r 1 225 176 0 +417 AIPS_VIP_l 200 2 100 0 +418 AIPS_VIP_r 200 2 100 0 +419 IPL_PFcm_l 5 200 90 0 +420 IPL_PFcm_r 5 200 90 0 +421 IPL_PF_l 100 5 200 0 +422 IPL_PFm_l 25 255 100 0 +423 IPL_PFm_r 25 255 100 0 +424 IPL_PFop_l 230 7 100 0 +425 IPL_PFop_r 230 7 100 0 +426 IPL_PF_r 100 5 200 0 +427 IPL_PFt_l 150 10 200 0 +428 IPL_PFt_r 150 10 200 0 +429 IPL_PGa_l 175 10 176 0 +430 IPL_PGa_r 175 10 176 0 +431 IPL_PGp_l 10 100 255 0 +432 IPL_PGp_r 10 100 255 0 +433 Visual_V3d_l 150 45 70 0 +434 Visual_V3d_r 150 45 70 0 +435 Visual_V4_l 45 200 15 0 +436 Visual_V4_r 45 200 15 0 +437 Visual_V5_b 227 45 100 0 +438 Visual_VP_l 227 45 100 0 +439 Visual_VP_r 227 45 100 0 + +# wm lesions +498 wmsa 143 188 143 0 +499 other_wmsa 255 248 220 0 + +# HiRes Hippocampus labeling +500 right_CA2_3 17 85 136 0 +501 right_alveus 119 187 102 0 +502 right_CA1 204 68 34 0 +503 right_fimbria 204 0 255 0 +504 right_presubiculum 221 187 17 0 +505 right_hippocampal_fissure 153 221 238 0 +506 right_CA4_DG 51 17 17 0 +507 right_subiculum 0 119 85 0 +508 right_fornix 20 100 200 0 + +550 left_CA2_3 17 85 137 0 +551 left_alveus 119 187 103 0 +552 left_CA1 204 68 35 0 +553 left_fimbria 204 0 254 0 +554 left_presubiculum 221 187 16 0 +555 left_hippocampal_fissure 153 221 239 0 +556 left_CA4_DG 51 17 18 0 +557 left_subiculum 0 119 86 0 +558 left_fornix 20 100 201 0 + +600 Tumor 254 254 254 0 + + +# Cerebellar parcellation labels from SUIT (matches labels in cma.h) +#No. Label Name: R G B A +601 Cbm_Left_I_IV 70 130 180 0 +602 Cbm_Right_I_IV 245 245 245 0 +603 Cbm_Left_V 205 62 78 0 +604 Cbm_Right_V 120 18 134 0 +605 Cbm_Left_VI 196 58 250 0 +606 Cbm_Vermis_VI 0 148 0 0 +607 Cbm_Right_VI 220 248 164 0 +608 Cbm_Left_CrusI 230 148 34 0 +609 Cbm_Vermis_CrusI 0 118 14 0 +610 Cbm_Right_CrusI 0 118 14 0 +611 Cbm_Left_CrusII 122 186 220 0 +612 Cbm_Vermis_CrusII 236 13 176 0 +613 Cbm_Right_CrusII 12 48 255 0 +614 Cbm_Left_VIIb 204 182 142 0 +615 Cbm_Vermis_VIIb 42 204 164 0 +616 Cbm_Right_VIIb 119 159 176 0 +617 Cbm_Left_VIIIa 220 216 20 0 +618 Cbm_Vermis_VIIIa 103 255 255 0 +619 Cbm_Right_VIIIa 80 196 98 0 +620 Cbm_Left_VIIIb 60 58 210 0 +621 Cbm_Vermis_VIIIb 60 58 210 0 +622 Cbm_Right_VIIIb 60 58 210 0 +623 Cbm_Left_IX 60 58 210 0 +624 Cbm_Vermis_IX 60 60 60 0 +625 Cbm_Right_IX 255 165 0 0 +626 Cbm_Left_X 255 165 0 0 +627 Cbm_Vermis_X 0 255 127 0 +628 Cbm_Right_X 165 42 42 0 + +# Cerebellar lobule parcellations +640 Cbm_Right_I_V_med 204 0 0 0 +641 Cbm_Right_I_V_mid 255 0 0 0 +642 Cbm_Right_VI_med 0 0 255 0 +643 Cbm_Right_VI_mid 30 144 255 0 +644 Cbm_Right_VI_lat 100 212 237 0 +645 Cbm_Right_CrusI_med 218 165 32 0 +646 Cbm_Right_CrusI_mid 255 215 0 0 +647 Cbm_Right_CrusI_lat 255 255 166 0 +648 Cbm_Right_CrusII_med 153 0 204 0 +649 Cbm_Right_CrusII_mid 153 141 209 0 +650 Cbm_Right_CrusII_lat 204 204 255 0 +651 Cbm_Right_7med 31 212 194 0 +652 Cbm_Right_7mid 3 255 237 0 +653 Cbm_Right_7lat 204 255 255 0 +654 Cbm_Right_8med 86 74 147 0 +655 Cbm_Right_8mid 114 114 190 0 +656 Cbm_Right_8lat 184 178 255 0 +657 Cbm_Right_PUNs 126 138 37 0 +658 Cbm_Right_TONs 189 197 117 0 +659 Cbm_Right_FLOs 240 230 140 0 +660 Cbm_Left_I_V_med 204 0 0 0 +661 Cbm_Left_I_V_mid 255 0 0 0 +662 Cbm_Left_VI_med 0 0 255 0 +663 Cbm_Left_VI_mid 30 144 255 0 +664 Cbm_Left_VI_lat 100 212 237 0 +665 Cbm_Left_CrusI_med 218 165 32 0 +666 Cbm_Left_CrusI_mid 255 215 0 0 +667 Cbm_Left_CrusI_lat 255 255 166 0 +668 Cbm_Left_CrusII_med 153 0 204 0 +669 Cbm_Left_CrusII_mid 153 141 209 0 +670 Cbm_Left_CrusII_lat 204 204 255 0 +671 Cbm_Left_7med 31 212 194 0 +672 Cbm_Left_7mid 3 255 237 0 +673 Cbm_Left_7lat 204 255 255 0 +674 Cbm_Left_8med 86 74 147 0 +675 Cbm_Left_8mid 114 114 190 0 +676 Cbm_Left_8lat 184 178 255 0 +677 Cbm_Left_PUNs 126 138 37 0 +678 Cbm_Left_TONs 189 197 117 0 +679 Cbm_Left_FLOs 240 230 140 0 + +701 CSF-FSL-FAST 120 18 134 0 +702 GrayMatter-FSL-FAST 205 62 78 0 +703 WhiteMatter-FSL-FAST 0 225 0 0 + +999 SUSPICIOUS 255 100 100 0 + +# Below is the color table for the cortical labels of the seg volume +# created by mri_aparc2aseg in which the aseg cortex label is replaced +# by the labels in the aparc. It also supports wm labels that will +# eventually be created by mri_aparc2aseg. Otherwise, the aseg labels +# do not change from above. The cortical labels are the same as in +# colortable_desikan_killiany.txt, except that left hemisphere has +# 1000 added to the index and the right has 2000 added. The label +# names are also prepended with ctx-lh or ctx-rh. The white matter +# labels are the same as in colortable_desikan_killiany.txt, except +# that left hemisphere has 3000 added to the index and the right has +# 4000 added. The label names are also prepended with wm-lh or wm-rh. +# Centrum semiovale is also labeled with 5001 (left) and 5002 (right). +# Even further below are the color tables for aparc.a2005s and aparc.a2009s. + +#No. Label Name: R G B A +1000 ctx-lh-unknown 25 5 25 0 +1001 ctx-lh-bankssts 25 100 40 0 +1002 ctx-lh-caudalanteriorcingulate 125 100 160 0 +1003 ctx-lh-caudalmiddlefrontal 100 25 0 0 +1004 ctx-lh-corpuscallosum 120 70 50 0 +1005 ctx-lh-cuneus 220 20 100 0 +1006 ctx-lh-entorhinal 220 20 10 0 +1007 ctx-lh-fusiform 180 220 140 0 +1008 ctx-lh-inferiorparietal 220 60 220 0 +1009 ctx-lh-inferiortemporal 180 40 120 0 +1010 ctx-lh-isthmuscingulate 140 20 140 0 +1011 ctx-lh-lateraloccipital 20 30 140 0 +1012 ctx-lh-lateralorbitofrontal 35 75 50 0 +1013 ctx-lh-lingual 225 140 140 0 +1014 ctx-lh-medialorbitofrontal 200 35 75 0 +1015 ctx-lh-middletemporal 160 100 50 0 +1016 ctx-lh-parahippocampal 20 220 60 0 +1017 ctx-lh-paracentral 60 220 60 0 +1018 ctx-lh-parsopercularis 220 180 140 0 +1019 ctx-lh-parsorbitalis 20 100 50 0 +1020 ctx-lh-parstriangularis 220 60 20 0 +1021 ctx-lh-pericalcarine 120 100 60 0 +1022 ctx-lh-postcentral 220 20 20 0 +1023 ctx-lh-posteriorcingulate 220 180 220 0 +1024 ctx-lh-precentral 60 20 220 0 +1025 ctx-lh-precuneus 160 140 180 0 +1026 ctx-lh-rostralanteriorcingulate 80 20 140 0 +1027 ctx-lh-rostralmiddlefrontal 75 50 125 0 +1028 ctx-lh-superiorfrontal 20 220 160 0 +1029 ctx-lh-superiorparietal 20 180 140 0 +1030 ctx-lh-superiortemporal 140 220 220 0 +1031 ctx-lh-supramarginal 80 160 20 0 +1032 ctx-lh-frontalpole 100 0 100 0 +1033 ctx-lh-temporalpole 70 70 70 0 +1034 ctx-lh-transversetemporal 150 150 200 0 +1035 ctx-lh-insula 255 192 32 0 + +2000 ctx-rh-unknown 25 5 25 0 +2001 ctx-rh-bankssts 25 100 40 0 +2002 ctx-rh-caudalanteriorcingulate 125 100 160 0 +2003 ctx-rh-caudalmiddlefrontal 100 25 0 0 +2004 ctx-rh-corpuscallosum 120 70 50 0 +2005 ctx-rh-cuneus 220 20 100 0 +2006 ctx-rh-entorhinal 220 20 10 0 +2007 ctx-rh-fusiform 180 220 140 0 +2008 ctx-rh-inferiorparietal 220 60 220 0 +2009 ctx-rh-inferiortemporal 180 40 120 0 +2010 ctx-rh-isthmuscingulate 140 20 140 0 +2011 ctx-rh-lateraloccipital 20 30 140 0 +2012 ctx-rh-lateralorbitofrontal 35 75 50 0 +2013 ctx-rh-lingual 225 140 140 0 +2014 ctx-rh-medialorbitofrontal 200 35 75 0 +2015 ctx-rh-middletemporal 160 100 50 0 +2016 ctx-rh-parahippocampal 20 220 60 0 +2017 ctx-rh-paracentral 60 220 60 0 +2018 ctx-rh-parsopercularis 220 180 140 0 +2019 ctx-rh-parsorbitalis 20 100 50 0 +2020 ctx-rh-parstriangularis 220 60 20 0 +2021 ctx-rh-pericalcarine 120 100 60 0 +2022 ctx-rh-postcentral 220 20 20 0 +2023 ctx-rh-posteriorcingulate 220 180 220 0 +2024 ctx-rh-precentral 60 20 220 0 +2025 ctx-rh-precuneus 160 140 180 0 +2026 ctx-rh-rostralanteriorcingulate 80 20 140 0 +2027 ctx-rh-rostralmiddlefrontal 75 50 125 0 +2028 ctx-rh-superiorfrontal 20 220 160 0 +2029 ctx-rh-superiorparietal 20 180 140 0 +2030 ctx-rh-superiortemporal 140 220 220 0 +2031 ctx-rh-supramarginal 80 160 20 0 +2032 ctx-rh-frontalpole 100 0 100 0 +2033 ctx-rh-temporalpole 70 70 70 0 +2034 ctx-rh-transversetemporal 150 150 200 0 +2035 ctx-rh-insula 255 192 32 0 + +3000 wm-lh-unknown 230 250 230 0 +3001 wm-lh-bankssts 230 155 215 0 +3002 wm-lh-caudalanteriorcingulate 130 155 95 0 +3003 wm-lh-caudalmiddlefrontal 155 230 255 0 +3004 wm-lh-corpuscallosum 135 185 205 0 +3005 wm-lh-cuneus 35 235 155 0 +3006 wm-lh-entorhinal 35 235 245 0 +3007 wm-lh-fusiform 75 35 115 0 +3008 wm-lh-inferiorparietal 35 195 35 0 +3009 wm-lh-inferiortemporal 75 215 135 0 +3010 wm-lh-isthmuscingulate 115 235 115 0 +3011 wm-lh-lateraloccipital 235 225 115 0 +3012 wm-lh-lateralorbitofrontal 220 180 205 0 +3013 wm-lh-lingual 30 115 115 0 +3014 wm-lh-medialorbitofrontal 55 220 180 0 +3015 wm-lh-middletemporal 95 155 205 0 +3016 wm-lh-parahippocampal 235 35 195 0 +3017 wm-lh-paracentral 195 35 195 0 +3018 wm-lh-parsopercularis 35 75 115 0 +3019 wm-lh-parsorbitalis 235 155 205 0 +3020 wm-lh-parstriangularis 35 195 235 0 +3021 wm-lh-pericalcarine 135 155 195 0 +3022 wm-lh-postcentral 35 235 235 0 +3023 wm-lh-posteriorcingulate 35 75 35 0 +3024 wm-lh-precentral 195 235 35 0 +3025 wm-lh-precuneus 95 115 75 0 +3026 wm-lh-rostralanteriorcingulate 175 235 115 0 +3027 wm-lh-rostralmiddlefrontal 180 205 130 0 +3028 wm-lh-superiorfrontal 235 35 95 0 +3029 wm-lh-superiorparietal 235 75 115 0 +3030 wm-lh-superiortemporal 115 35 35 0 +3031 wm-lh-supramarginal 175 95 235 0 +3032 wm-lh-frontalpole 155 255 155 0 +3033 wm-lh-temporalpole 185 185 185 0 +3034 wm-lh-transversetemporal 105 105 55 0 +3035 wm-lh-insula 254 191 31 0 + +4000 wm-rh-unknown 230 250 230 0 +4001 wm-rh-bankssts 230 155 215 0 +4002 wm-rh-caudalanteriorcingulate 130 155 95 0 +4003 wm-rh-caudalmiddlefrontal 155 230 255 0 +4004 wm-rh-corpuscallosum 135 185 205 0 +4005 wm-rh-cuneus 35 235 155 0 +4006 wm-rh-entorhinal 35 235 245 0 +4007 wm-rh-fusiform 75 35 115 0 +4008 wm-rh-inferiorparietal 35 195 35 0 +4009 wm-rh-inferiortemporal 75 215 135 0 +4010 wm-rh-isthmuscingulate 115 235 115 0 +4011 wm-rh-lateraloccipital 235 225 115 0 +4012 wm-rh-lateralorbitofrontal 220 180 205 0 +4013 wm-rh-lingual 30 115 115 0 +4014 wm-rh-medialorbitofrontal 55 220 180 0 +4015 wm-rh-middletemporal 95 155 205 0 +4016 wm-rh-parahippocampal 235 35 195 0 +4017 wm-rh-paracentral 195 35 195 0 +4018 wm-rh-parsopercularis 35 75 115 0 +4019 wm-rh-parsorbitalis 235 155 205 0 +4020 wm-rh-parstriangularis 35 195 235 0 +4021 wm-rh-pericalcarine 135 155 195 0 +4022 wm-rh-postcentral 35 235 235 0 +4023 wm-rh-posteriorcingulate 35 75 35 0 +4024 wm-rh-precentral 195 235 35 0 +4025 wm-rh-precuneus 95 115 75 0 +4026 wm-rh-rostralanteriorcingulate 175 235 115 0 +4027 wm-rh-rostralmiddlefrontal 180 205 130 0 +4028 wm-rh-superiorfrontal 235 35 95 0 +4029 wm-rh-superiorparietal 235 75 115 0 +4030 wm-rh-superiortemporal 115 35 35 0 +4031 wm-rh-supramarginal 175 95 235 0 +4032 wm-rh-frontalpole 155 255 155 0 +4033 wm-rh-temporalpole 185 185 185 0 +4034 wm-rh-transversetemporal 105 105 55 0 +4035 wm-rh-insula 254 191 31 0 + +# Below is the color table for the cortical labels of the seg volume +# created by mri_aparc2aseg (with --a2005s flag) in which the aseg +# cortex label is replaced by the labels in the aparc.a2005s. The +# cortical labels are the same as in Simple_surface_labels2005.txt, +# except that left hemisphere has 1100 added to the index and the +# right has 2100 added. The label names are also prepended with +# ctx-lh or ctx-rh. The aparc.a2009s labels are further below + +#No. Label Name: R G B A +1100 ctx-lh-Unknown 0 0 0 0 +1101 ctx-lh-Corpus_callosum 50 50 50 0 +1102 ctx-lh-G_and_S_Insula_ONLY_AVERAGE 180 20 30 0 +1103 ctx-lh-G_cingulate-Isthmus 60 25 25 0 +1104 ctx-lh-G_cingulate-Main_part 25 60 60 0 + +1200 ctx-lh-G_cingulate-caudal_ACC 25 60 61 0 +1201 ctx-lh-G_cingulate-rostral_ACC 25 90 60 0 +1202 ctx-lh-G_cingulate-posterior 25 120 60 0 + +1205 ctx-lh-S_cingulate-caudal_ACC 25 150 60 0 +1206 ctx-lh-S_cingulate-rostral_ACC 25 180 60 0 +1207 ctx-lh-S_cingulate-posterior 25 210 60 0 + +1210 ctx-lh-S_pericallosal-caudal 25 150 90 0 +1211 ctx-lh-S_pericallosal-rostral 25 180 90 0 +1212 ctx-lh-S_pericallosal-posterior 25 210 90 0 + +1105 ctx-lh-G_cuneus 180 20 20 0 +1106 ctx-lh-G_frontal_inf-Opercular_part 220 20 100 0 +1107 ctx-lh-G_frontal_inf-Orbital_part 140 60 60 0 +1108 ctx-lh-G_frontal_inf-Triangular_part 180 220 140 0 +1109 ctx-lh-G_frontal_middle 140 100 180 0 +1110 ctx-lh-G_frontal_superior 180 20 140 0 +1111 ctx-lh-G_frontomarginal 140 20 140 0 +1112 ctx-lh-G_insular_long 21 10 10 0 +1113 ctx-lh-G_insular_short 225 140 140 0 +1114 ctx-lh-G_and_S_occipital_inferior 23 60 180 0 +1115 ctx-lh-G_occipital_middle 180 60 180 0 +1116 ctx-lh-G_occipital_superior 20 220 60 0 +1117 ctx-lh-G_occipit-temp_lat-Or_fusiform 60 20 140 0 +1118 ctx-lh-G_occipit-temp_med-Lingual_part 220 180 140 0 +1119 ctx-lh-G_occipit-temp_med-Parahippocampal_part 65 100 20 0 +1120 ctx-lh-G_orbital 220 60 20 0 +1121 ctx-lh-G_paracentral 60 100 60 0 +1122 ctx-lh-G_parietal_inferior-Angular_part 20 60 220 0 +1123 ctx-lh-G_parietal_inferior-Supramarginal_part 100 100 60 0 +1124 ctx-lh-G_parietal_superior 220 180 220 0 +1125 ctx-lh-G_postcentral 20 180 140 0 +1126 ctx-lh-G_precentral 60 140 180 0 +1127 ctx-lh-G_precuneus 25 20 140 0 +1128 ctx-lh-G_rectus 20 60 100 0 +1129 ctx-lh-G_subcallosal 60 220 20 0 +1130 ctx-lh-G_subcentral 60 20 220 0 +1131 ctx-lh-G_temporal_inferior 220 220 100 0 +1132 ctx-lh-G_temporal_middle 180 60 60 0 +1133 ctx-lh-G_temp_sup-G_temp_transv_and_interm_S 60 60 220 0 +1134 ctx-lh-G_temp_sup-Lateral_aspect 220 60 220 0 +1135 ctx-lh-G_temp_sup-Planum_polare 65 220 60 0 +1136 ctx-lh-G_temp_sup-Planum_tempolare 25 140 20 0 +1137 ctx-lh-G_and_S_transverse_frontopolar 13 0 250 0 +1138 ctx-lh-Lat_Fissure-ant_sgt-ramus_horizontal 61 20 220 0 +1139 ctx-lh-Lat_Fissure-ant_sgt-ramus_vertical 61 20 60 0 +1140 ctx-lh-Lat_Fissure-post_sgt 61 60 100 0 +1141 ctx-lh-Medial_wall 25 25 25 0 +1142 ctx-lh-Pole_occipital 140 20 60 0 +1143 ctx-lh-Pole_temporal 220 180 20 0 +1144 ctx-lh-S_calcarine 63 180 180 0 +1145 ctx-lh-S_central 221 20 10 0 +1146 ctx-lh-S_central_insula 21 220 20 0 +1147 ctx-lh-S_cingulate-Main_part_and_Intracingulate 183 100 20 0 +1148 ctx-lh-S_cingulate-Marginalis_part 221 20 100 0 +1149 ctx-lh-S_circular_insula_anterior 221 60 140 0 +1150 ctx-lh-S_circular_insula_inferior 221 20 220 0 +1151 ctx-lh-S_circular_insula_superior 61 220 220 0 +1152 ctx-lh-S_collateral_transverse_ant 100 200 200 0 +1153 ctx-lh-S_collateral_transverse_post 10 200 200 0 +1154 ctx-lh-S_frontal_inferior 221 220 20 0 +1155 ctx-lh-S_frontal_middle 141 20 100 0 +1156 ctx-lh-S_frontal_superior 61 220 100 0 +1157 ctx-lh-S_frontomarginal 21 220 60 0 +1158 ctx-lh-S_intermedius_primus-Jensen 141 60 20 0 +1159 ctx-lh-S_intraparietal-and_Parietal_transverse 143 20 220 0 +1160 ctx-lh-S_occipital_anterior 61 20 180 0 +1161 ctx-lh-S_occipital_middle_and_Lunatus 101 60 220 0 +1162 ctx-lh-S_occipital_superior_and_transversalis 21 20 140 0 +1163 ctx-lh-S_occipito-temporal_lateral 221 140 20 0 +1164 ctx-lh-S_occipito-temporal_medial_and_S_Lingual 141 100 220 0 +1165 ctx-lh-S_orbital-H_shapped 101 20 20 0 +1166 ctx-lh-S_orbital_lateral 221 100 20 0 +1167 ctx-lh-S_orbital_medial-Or_olfactory 181 200 20 0 +1168 ctx-lh-S_paracentral 21 180 140 0 +1169 ctx-lh-S_parieto_occipital 101 100 180 0 +1170 ctx-lh-S_pericallosal 181 220 20 0 +1171 ctx-lh-S_postcentral 21 140 200 0 +1172 ctx-lh-S_precentral-Inferior-part 21 20 240 0 +1173 ctx-lh-S_precentral-Superior-part 21 20 200 0 +1174 ctx-lh-S_subcentral_ant 61 180 60 0 +1175 ctx-lh-S_subcentral_post 61 180 250 0 +1176 ctx-lh-S_suborbital 21 20 60 0 +1177 ctx-lh-S_subparietal 101 60 60 0 +1178 ctx-lh-S_supracingulate 21 220 220 0 +1179 ctx-lh-S_temporal_inferior 21 180 180 0 +1180 ctx-lh-S_temporal_superior 223 220 60 0 +1181 ctx-lh-S_temporal_transverse 221 60 60 0 + +2100 ctx-rh-Unknown 0 0 0 0 +2101 ctx-rh-Corpus_callosum 50 50 50 0 +2102 ctx-rh-G_and_S_Insula_ONLY_AVERAGE 180 20 30 0 +2103 ctx-rh-G_cingulate-Isthmus 60 25 25 0 +2104 ctx-rh-G_cingulate-Main_part 25 60 60 0 + +2105 ctx-rh-G_cuneus 180 20 20 0 +2106 ctx-rh-G_frontal_inf-Opercular_part 220 20 100 0 +2107 ctx-rh-G_frontal_inf-Orbital_part 140 60 60 0 +2108 ctx-rh-G_frontal_inf-Triangular_part 180 220 140 0 +2109 ctx-rh-G_frontal_middle 140 100 180 0 +2110 ctx-rh-G_frontal_superior 180 20 140 0 +2111 ctx-rh-G_frontomarginal 140 20 140 0 +2112 ctx-rh-G_insular_long 21 10 10 0 +2113 ctx-rh-G_insular_short 225 140 140 0 +2114 ctx-rh-G_and_S_occipital_inferior 23 60 180 0 +2115 ctx-rh-G_occipital_middle 180 60 180 0 +2116 ctx-rh-G_occipital_superior 20 220 60 0 +2117 ctx-rh-G_occipit-temp_lat-Or_fusiform 60 20 140 0 +2118 ctx-rh-G_occipit-temp_med-Lingual_part 220 180 140 0 +2119 ctx-rh-G_occipit-temp_med-Parahippocampal_part 65 100 20 0 +2120 ctx-rh-G_orbital 220 60 20 0 +2121 ctx-rh-G_paracentral 60 100 60 0 +2122 ctx-rh-G_parietal_inferior-Angular_part 20 60 220 0 +2123 ctx-rh-G_parietal_inferior-Supramarginal_part 100 100 60 0 +2124 ctx-rh-G_parietal_superior 220 180 220 0 +2125 ctx-rh-G_postcentral 20 180 140 0 +2126 ctx-rh-G_precentral 60 140 180 0 +2127 ctx-rh-G_precuneus 25 20 140 0 +2128 ctx-rh-G_rectus 20 60 100 0 +2129 ctx-rh-G_subcallosal 60 220 20 0 +2130 ctx-rh-G_subcentral 60 20 220 0 +2131 ctx-rh-G_temporal_inferior 220 220 100 0 +2132 ctx-rh-G_temporal_middle 180 60 60 0 +2133 ctx-rh-G_temp_sup-G_temp_transv_and_interm_S 60 60 220 0 +2134 ctx-rh-G_temp_sup-Lateral_aspect 220 60 220 0 +2135 ctx-rh-G_temp_sup-Planum_polare 65 220 60 0 +2136 ctx-rh-G_temp_sup-Planum_tempolare 25 140 20 0 +2137 ctx-rh-G_and_S_transverse_frontopolar 13 0 250 0 +2138 ctx-rh-Lat_Fissure-ant_sgt-ramus_horizontal 61 20 220 0 +2139 ctx-rh-Lat_Fissure-ant_sgt-ramus_vertical 61 20 60 0 +2140 ctx-rh-Lat_Fissure-post_sgt 61 60 100 0 +2141 ctx-rh-Medial_wall 25 25 25 0 +2142 ctx-rh-Pole_occipital 140 20 60 0 +2143 ctx-rh-Pole_temporal 220 180 20 0 +2144 ctx-rh-S_calcarine 63 180 180 0 +2145 ctx-rh-S_central 221 20 10 0 +2146 ctx-rh-S_central_insula 21 220 20 0 +2147 ctx-rh-S_cingulate-Main_part_and_Intracingulate 183 100 20 0 +2148 ctx-rh-S_cingulate-Marginalis_part 221 20 100 0 +2149 ctx-rh-S_circular_insula_anterior 221 60 140 0 +2150 ctx-rh-S_circular_insula_inferior 221 20 220 0 +2151 ctx-rh-S_circular_insula_superior 61 220 220 0 +2152 ctx-rh-S_collateral_transverse_ant 100 200 200 0 +2153 ctx-rh-S_collateral_transverse_post 10 200 200 0 +2154 ctx-rh-S_frontal_inferior 221 220 20 0 +2155 ctx-rh-S_frontal_middle 141 20 100 0 +2156 ctx-rh-S_frontal_superior 61 220 100 0 +2157 ctx-rh-S_frontomarginal 21 220 60 0 +2158 ctx-rh-S_intermedius_primus-Jensen 141 60 20 0 +2159 ctx-rh-S_intraparietal-and_Parietal_transverse 143 20 220 0 +2160 ctx-rh-S_occipital_anterior 61 20 180 0 +2161 ctx-rh-S_occipital_middle_and_Lunatus 101 60 220 0 +2162 ctx-rh-S_occipital_superior_and_transversalis 21 20 140 0 +2163 ctx-rh-S_occipito-temporal_lateral 221 140 20 0 +2164 ctx-rh-S_occipito-temporal_medial_and_S_Lingual 141 100 220 0 +2165 ctx-rh-S_orbital-H_shapped 101 20 20 0 +2166 ctx-rh-S_orbital_lateral 221 100 20 0 +2167 ctx-rh-S_orbital_medial-Or_olfactory 181 200 20 0 +2168 ctx-rh-S_paracentral 21 180 140 0 +2169 ctx-rh-S_parieto_occipital 101 100 180 0 +2170 ctx-rh-S_pericallosal 181 220 20 0 +2171 ctx-rh-S_postcentral 21 140 200 0 +2172 ctx-rh-S_precentral-Inferior-part 21 20 240 0 +2173 ctx-rh-S_precentral-Superior-part 21 20 200 0 +2174 ctx-rh-S_subcentral_ant 61 180 60 0 +2175 ctx-rh-S_subcentral_post 61 180 250 0 +2176 ctx-rh-S_suborbital 21 20 60 0 +2177 ctx-rh-S_subparietal 101 60 60 0 +2178 ctx-rh-S_supracingulate 21 220 220 0 +2179 ctx-rh-S_temporal_inferior 21 180 180 0 +2180 ctx-rh-S_temporal_superior 223 220 60 0 +2181 ctx-rh-S_temporal_transverse 221 60 60 0 + + +2200 ctx-rh-G_cingulate-caudal_ACC 25 60 61 0 +2201 ctx-rh-G_cingulate-rostral_ACC 25 90 60 0 +2202 ctx-rh-G_cingulate-posterior 25 120 60 0 + +2205 ctx-rh-S_cingulate-caudal_ACC 25 150 60 0 +2206 ctx-rh-S_cingulate-rostral_ACC 25 180 60 0 +2207 ctx-rh-S_cingulate-posterior 25 210 60 0 + +2210 ctx-rh-S_pericallosal-caudal 25 150 90 0 +2211 ctx-rh-S_pericallosal-rostral 25 180 90 0 +2212 ctx-rh-S_pericallosal-posterior 25 210 90 0 + +3100 wm-lh-Unknown 0 0 0 0 +3101 wm-lh-Corpus_callosum 50 50 50 0 +3102 wm-lh-G_and_S_Insula_ONLY_AVERAGE 180 20 30 0 +3103 wm-lh-G_cingulate-Isthmus 60 25 25 0 +3104 wm-lh-G_cingulate-Main_part 25 60 60 0 +3105 wm-lh-G_cuneus 180 20 20 0 +3106 wm-lh-G_frontal_inf-Opercular_part 220 20 100 0 +3107 wm-lh-G_frontal_inf-Orbital_part 140 60 60 0 +3108 wm-lh-G_frontal_inf-Triangular_part 180 220 140 0 +3109 wm-lh-G_frontal_middle 140 100 180 0 +3110 wm-lh-G_frontal_superior 180 20 140 0 +3111 wm-lh-G_frontomarginal 140 20 140 0 +3112 wm-lh-G_insular_long 21 10 10 0 +3113 wm-lh-G_insular_short 225 140 140 0 +3114 wm-lh-G_and_S_occipital_inferior 23 60 180 0 +3115 wm-lh-G_occipital_middle 180 60 180 0 +3116 wm-lh-G_occipital_superior 20 220 60 0 +3117 wm-lh-G_occipit-temp_lat-Or_fusiform 60 20 140 0 +3118 wm-lh-G_occipit-temp_med-Lingual_part 220 180 140 0 +3119 wm-lh-G_occipit-temp_med-Parahippocampal_part 65 100 20 0 +3120 wm-lh-G_orbital 220 60 20 0 +3121 wm-lh-G_paracentral 60 100 60 0 +3122 wm-lh-G_parietal_inferior-Angular_part 20 60 220 0 +3123 wm-lh-G_parietal_inferior-Supramarginal_part 100 100 60 0 +3124 wm-lh-G_parietal_superior 220 180 220 0 +3125 wm-lh-G_postcentral 20 180 140 0 +3126 wm-lh-G_precentral 60 140 180 0 +3127 wm-lh-G_precuneus 25 20 140 0 +3128 wm-lh-G_rectus 20 60 100 0 +3129 wm-lh-G_subcallosal 60 220 20 0 +3130 wm-lh-G_subcentral 60 20 220 0 +3131 wm-lh-G_temporal_inferior 220 220 100 0 +3132 wm-lh-G_temporal_middle 180 60 60 0 +3133 wm-lh-G_temp_sup-G_temp_transv_and_interm_S 60 60 220 0 +3134 wm-lh-G_temp_sup-Lateral_aspect 220 60 220 0 +3135 wm-lh-G_temp_sup-Planum_polare 65 220 60 0 +3136 wm-lh-G_temp_sup-Planum_tempolare 25 140 20 0 +3137 wm-lh-G_and_S_transverse_frontopolar 13 0 250 0 +3138 wm-lh-Lat_Fissure-ant_sgt-ramus_horizontal 61 20 220 0 +3139 wm-lh-Lat_Fissure-ant_sgt-ramus_vertical 61 20 60 0 +3140 wm-lh-Lat_Fissure-post_sgt 61 60 100 0 +3141 wm-lh-Medial_wall 25 25 25 0 +3142 wm-lh-Pole_occipital 140 20 60 0 +3143 wm-lh-Pole_temporal 220 180 20 0 +3144 wm-lh-S_calcarine 63 180 180 0 +3145 wm-lh-S_central 221 20 10 0 +3146 wm-lh-S_central_insula 21 220 20 0 +3147 wm-lh-S_cingulate-Main_part_and_Intracingulate 183 100 20 0 +3148 wm-lh-S_cingulate-Marginalis_part 221 20 100 0 +3149 wm-lh-S_circular_insula_anterior 221 60 140 0 +3150 wm-lh-S_circular_insula_inferior 221 20 220 0 +3151 wm-lh-S_circular_insula_superior 61 220 220 0 +3152 wm-lh-S_collateral_transverse_ant 100 200 200 0 +3153 wm-lh-S_collateral_transverse_post 10 200 200 0 +3154 wm-lh-S_frontal_inferior 221 220 20 0 +3155 wm-lh-S_frontal_middle 141 20 100 0 +3156 wm-lh-S_frontal_superior 61 220 100 0 +3157 wm-lh-S_frontomarginal 21 220 60 0 +3158 wm-lh-S_intermedius_primus-Jensen 141 60 20 0 +3159 wm-lh-S_intraparietal-and_Parietal_transverse 143 20 220 0 +3160 wm-lh-S_occipital_anterior 61 20 180 0 +3161 wm-lh-S_occipital_middle_and_Lunatus 101 60 220 0 +3162 wm-lh-S_occipital_superior_and_transversalis 21 20 140 0 +3163 wm-lh-S_occipito-temporal_lateral 221 140 20 0 +3164 wm-lh-S_occipito-temporal_medial_and_S_Lingual 141 100 220 0 +3165 wm-lh-S_orbital-H_shapped 101 20 20 0 +3166 wm-lh-S_orbital_lateral 221 100 20 0 +3167 wm-lh-S_orbital_medial-Or_olfactory 181 200 20 0 +3168 wm-lh-S_paracentral 21 180 140 0 +3169 wm-lh-S_parieto_occipital 101 100 180 0 +3170 wm-lh-S_pericallosal 181 220 20 0 +3171 wm-lh-S_postcentral 21 140 200 0 +3172 wm-lh-S_precentral-Inferior-part 21 20 240 0 +3173 wm-lh-S_precentral-Superior-part 21 20 200 0 +3174 wm-lh-S_subcentral_ant 61 180 60 0 +3175 wm-lh-S_subcentral_post 61 180 250 0 +3176 wm-lh-S_suborbital 21 20 60 0 +3177 wm-lh-S_subparietal 101 60 60 0 +3178 wm-lh-S_supracingulate 21 220 220 0 +3179 wm-lh-S_temporal_inferior 21 180 180 0 +3180 wm-lh-S_temporal_superior 223 220 60 0 +3181 wm-lh-S_temporal_transverse 221 60 60 0 + +4100 wm-rh-Unknown 0 0 0 0 +4101 wm-rh-Corpus_callosum 50 50 50 0 +4102 wm-rh-G_and_S_Insula_ONLY_AVERAGE 180 20 30 0 +4103 wm-rh-G_cingulate-Isthmus 60 25 25 0 +4104 wm-rh-G_cingulate-Main_part 25 60 60 0 +4105 wm-rh-G_cuneus 180 20 20 0 +4106 wm-rh-G_frontal_inf-Opercular_part 220 20 100 0 +4107 wm-rh-G_frontal_inf-Orbital_part 140 60 60 0 +4108 wm-rh-G_frontal_inf-Triangular_part 180 220 140 0 +4109 wm-rh-G_frontal_middle 140 100 180 0 +4110 wm-rh-G_frontal_superior 180 20 140 0 +4111 wm-rh-G_frontomarginal 140 20 140 0 +4112 wm-rh-G_insular_long 21 10 10 0 +4113 wm-rh-G_insular_short 225 140 140 0 +4114 wm-rh-G_and_S_occipital_inferior 23 60 180 0 +4115 wm-rh-G_occipital_middle 180 60 180 0 +4116 wm-rh-G_occipital_superior 20 220 60 0 +4117 wm-rh-G_occipit-temp_lat-Or_fusiform 60 20 140 0 +4118 wm-rh-G_occipit-temp_med-Lingual_part 220 180 140 0 +4119 wm-rh-G_occipit-temp_med-Parahippocampal_part 65 100 20 0 +4120 wm-rh-G_orbital 220 60 20 0 +4121 wm-rh-G_paracentral 60 100 60 0 +4122 wm-rh-G_parietal_inferior-Angular_part 20 60 220 0 +4123 wm-rh-G_parietal_inferior-Supramarginal_part 100 100 60 0 +4124 wm-rh-G_parietal_superior 220 180 220 0 +4125 wm-rh-G_postcentral 20 180 140 0 +4126 wm-rh-G_precentral 60 140 180 0 +4127 wm-rh-G_precuneus 25 20 140 0 +4128 wm-rh-G_rectus 20 60 100 0 +4129 wm-rh-G_subcallosal 60 220 20 0 +4130 wm-rh-G_subcentral 60 20 220 0 +4131 wm-rh-G_temporal_inferior 220 220 100 0 +4132 wm-rh-G_temporal_middle 180 60 60 0 +4133 wm-rh-G_temp_sup-G_temp_transv_and_interm_S 60 60 220 0 +4134 wm-rh-G_temp_sup-Lateral_aspect 220 60 220 0 +4135 wm-rh-G_temp_sup-Planum_polare 65 220 60 0 +4136 wm-rh-G_temp_sup-Planum_tempolare 25 140 20 0 +4137 wm-rh-G_and_S_transverse_frontopolar 13 0 250 0 +4138 wm-rh-Lat_Fissure-ant_sgt-ramus_horizontal 61 20 220 0 +4139 wm-rh-Lat_Fissure-ant_sgt-ramus_vertical 61 20 60 0 +4140 wm-rh-Lat_Fissure-post_sgt 61 60 100 0 +4141 wm-rh-Medial_wall 25 25 25 0 +4142 wm-rh-Pole_occipital 140 20 60 0 +4143 wm-rh-Pole_temporal 220 180 20 0 +4144 wm-rh-S_calcarine 63 180 180 0 +4145 wm-rh-S_central 221 20 10 0 +4146 wm-rh-S_central_insula 21 220 20 0 +4147 wm-rh-S_cingulate-Main_part_and_Intracingulate 183 100 20 0 +4148 wm-rh-S_cingulate-Marginalis_part 221 20 100 0 +4149 wm-rh-S_circular_insula_anterior 221 60 140 0 +4150 wm-rh-S_circular_insula_inferior 221 20 220 0 +4151 wm-rh-S_circular_insula_superior 61 220 220 0 +4152 wm-rh-S_collateral_transverse_ant 100 200 200 0 +4153 wm-rh-S_collateral_transverse_post 10 200 200 0 +4154 wm-rh-S_frontal_inferior 221 220 20 0 +4155 wm-rh-S_frontal_middle 141 20 100 0 +4156 wm-rh-S_frontal_superior 61 220 100 0 +4157 wm-rh-S_frontomarginal 21 220 60 0 +4158 wm-rh-S_intermedius_primus-Jensen 141 60 20 0 +4159 wm-rh-S_intraparietal-and_Parietal_transverse 143 20 220 0 +4160 wm-rh-S_occipital_anterior 61 20 180 0 +4161 wm-rh-S_occipital_middle_and_Lunatus 101 60 220 0 +4162 wm-rh-S_occipital_superior_and_transversalis 21 20 140 0 +4163 wm-rh-S_occipito-temporal_lateral 221 140 20 0 +4164 wm-rh-S_occipito-temporal_medial_and_S_Lingual 141 100 220 0 +4165 wm-rh-S_orbital-H_shapped 101 20 20 0 +4166 wm-rh-S_orbital_lateral 221 100 20 0 +4167 wm-rh-S_orbital_medial-Or_olfactory 181 200 20 0 +4168 wm-rh-S_paracentral 21 180 140 0 +4169 wm-rh-S_parieto_occipital 101 100 180 0 +4170 wm-rh-S_pericallosal 181 220 20 0 +4171 wm-rh-S_postcentral 21 140 200 0 +4172 wm-rh-S_precentral-Inferior-part 21 20 240 0 +4173 wm-rh-S_precentral-Superior-part 21 20 200 0 +4174 wm-rh-S_subcentral_ant 61 180 60 0 +4175 wm-rh-S_subcentral_post 61 180 250 0 +4176 wm-rh-S_suborbital 21 20 60 0 +4177 wm-rh-S_subparietal 101 60 60 0 +4178 wm-rh-S_supracingulate 21 220 220 0 +4179 wm-rh-S_temporal_inferior 21 180 180 0 +4180 wm-rh-S_temporal_superior 223 220 60 0 +4181 wm-rh-S_temporal_transverse 221 60 60 0 + +5001 Left-UnsegmentedWhiteMatter 20 30 40 0 +5002 Right-UnsegmentedWhiteMatter 20 30 40 0 + +# Below is the color table for white-matter pathways produced by dmri_paths + +#No. Label Name: R G B A +# +5100 fmajor 204 102 102 0 +5101 fminor 204 102 102 0 +# +5102 lh.atr 255 255 102 0 +5103 lh.cab 153 204 0 0 +5104 lh.ccg 0 153 153 0 +5105 lh.cst 204 153 255 0 +5106 lh.ilf 255 153 51 0 +5107 lh.slfp 204 204 204 0 +5108 lh.slft 153 255 255 0 +5109 lh.unc 102 153 255 0 +# +5110 rh.atr 255 255 102 0 +5111 rh.cab 153 204 0 0 +5112 rh.ccg 0 153 153 0 +5113 rh.cst 204 153 255 0 +5114 rh.ilf 255 153 51 0 +5115 rh.slfp 204 204 204 0 +5116 rh.slft 153 255 255 0 +5117 rh.unc 102 153 255 0 + +# These are the same tracula labels as above in human-readable form +5200 CC-ForcepsMajor 204 102 102 0 +5201 CC-ForcepsMinor 204 102 102 0 +5202 LAntThalRadiation 255 255 102 0 +5203 LCingulumAngBundle 153 204 0 0 +5204 LCingulumCingGyrus 0 153 153 0 +5205 LCorticospinalTract 204 153 255 0 +5206 LInfLongFas 255 153 51 0 +5207 LSupLongFasParietal 204 204 204 0 +5208 LSupLongFasTemporal 153 255 255 0 +5209 LUncinateFas 102 153 255 0 +5210 RAntThalRadiation 255 255 102 0 +5211 RCingulumAngBundle 153 204 0 0 +5212 RCingulumCingGyrus 0 153 153 0 +5213 RCorticospinalTract 204 153 255 0 +5214 RInfLongFas 255 153 51 0 +5215 RSupLongFasParietal 204 204 204 0 +5216 RSupLongFasTemporal 153 255 255 0 +5217 RUncinateFas 102 153 255 0 + +######################################## + +6000 CST-orig 0 255 0 0 +6001 CST-hammer 255 255 0 0 +6002 CST-CVS 0 255 255 0 +6003 CST-flirt 0 0 255 0 + +6010 Left-SLF1 236 16 231 0 +6020 Right-SLF1 237 18 232 0 + +6030 Left-SLF3 236 13 227 0 +6040 Right-SLF3 236 17 228 0 + +6050 Left-CST 1 255 1 0 +6060 Right-CST 2 255 1 0 + +6070 Left-SLF2 236 14 230 0 +6080 Right-SLF2 237 14 230 0 + +#No. Label Name: R G B A + +7001 Lateral-nucleus 72 132 181 0 +7002 Basolateral-nucleus 243 243 243 0 +7003 Basal-nucleus 207 63 79 0 +7004 Centromedial-nucleus 121 20 135 0 +7005 Central-nucleus 197 60 248 0 +7006 Medial-nucleus 2 149 2 0 +7007 Cortical-nucleus 221 249 166 0 +7008 Accessory-Basal-nucleus 232 146 35 0 +7009 Corticoamygdaloid-transitio 20 60 120 0 +7010 Anterior-amygdaloid-area-AAA 250 250 0 0 +7011 Fusion-amygdala-HP-FAH 122 187 222 0 +7012 Hippocampal-amygdala-transition-HATA 237 12 177 0 +7013 Endopiriform-nucleus 10 49 255 0 +7014 Lateral-nucleus-olfactory-tract 205 184 144 0 +7015 Paralaminar-nucleus 45 205 165 0 +7016 Intercalated-nucleus 117 160 175 0 +7017 Prepiriform-cortex 221 217 21 0 +7018 Periamygdaloid-cortex 20 60 120 0 +7019 Envelope-Amygdala 141 21 100 0 +7020 Extranuclear-Amydala 225 140 141 0 + +7100 Brainstem-inferior-colliculus 42 201 168 0 +7101 Brainstem-cochlear-nucleus 168 104 162 0 + +8001 Thalamus-Anterior 74 130 181 0 +8002 Thalamus-Ventral-anterior 242 241 240 0 +8003 Thalamus-Lateral-dorsal 206 65 78 0 +8004 Thalamus-Lateral-posterior 120 21 133 0 +8005 Thalamus-Ventral-lateral 195 61 246 0 +8006 Thalamus-Ventral-posterior-medial 3 147 6 0 +8007 Thalamus-Ventral-posterior-lateral 220 251 163 0 +8008 Thalamus-intralaminar 232 146 33 0 +8009 Thalamus-centromedian 4 114 14 0 +8010 Thalamus-mediodorsal 121 184 220 0 +8011 Thalamus-medial 235 11 175 0 +8012 Thalamus-pulvinar 12 46 250 0 +8013 Thalamus-lateral-geniculate 203 182 143 0 +8014 Thalamus-medial-geniculate 42 204 167 0 + +# +# Labels for thalamus parcellation using probabilistic tractography. See: +# Functional--Anatomical Validation and Individual Variation of Diffusion +# Tractography-based Segmentation of the Human Thalamus; Cerebral Cortex +# January 2005;15:31--39, doi:10.1093/cercor/bhh105, Advance Access +# publication July 6, 2004 +# + +#No. Label Name: R G B A +9000 ctx-lh-prefrontal 30 5 30 0 +9001 ctx-lh-primary-motor 30 100 45 0 +9002 ctx-lh-premotor 130 100 165 0 +9003 ctx-lh-temporal 105 25 5 0 +9004 ctx-lh-posterior-parietal 125 70 55 0 +9005 ctx-lh-prim-sec-somatosensory 225 20 105 0 +9006 ctx-lh-occipital 225 20 15 0 + +9500 ctx-rh-prefrontal 30 55 30 0 +9501 ctx-rh-primary-motor 30 150 45 0 +9502 ctx-rh-premotor 130 150 165 0 +9503 ctx-rh-temporal 105 75 5 0 +9504 ctx-rh-posterior-parietal 125 120 55 0 +9505 ctx-rh-prim-sec-somatosensory 225 70 105 0 +9506 ctx-rh-occipital 225 70 15 0 + +# Below is the color table for the cortical labels of the seg volume +# created by mri_aparc2aseg (with --a2009s flag) in which the aseg +# cortex label is replaced by the labels in the aparc.a2009s. The +# cortical labels are the same as in Simple_surface_labels2009.txt, +# except that left hemisphere has 11100 added to the index and the +# right has 12100 added. The label names are also prepended with +# ctx_lh_, ctx_rh_, wm_lh_ and wm_rh_ (note usage of _ instead of - +# to differentiate from a2005s labels). + +#No. Label Name: R G B A +11100 ctx_lh_Unknown 0 0 0 0 +11101 ctx_lh_G_and_S_frontomargin 23 220 60 0 +11102 ctx_lh_G_and_S_occipital_inf 23 60 180 0 +11103 ctx_lh_G_and_S_paracentral 63 100 60 0 +11104 ctx_lh_G_and_S_subcentral 63 20 220 0 +11105 ctx_lh_G_and_S_transv_frontopol 13 0 250 0 +11106 ctx_lh_G_and_S_cingul-Ant 26 60 0 0 +11107 ctx_lh_G_and_S_cingul-Mid-Ant 26 60 75 0 +11108 ctx_lh_G_and_S_cingul-Mid-Post 26 60 150 0 +11109 ctx_lh_G_cingul-Post-dorsal 25 60 250 0 +11110 ctx_lh_G_cingul-Post-ventral 60 25 25 0 +11111 ctx_lh_G_cuneus 180 20 20 0 +11112 ctx_lh_G_front_inf-Opercular 220 20 100 0 +11113 ctx_lh_G_front_inf-Orbital 140 60 60 0 +11114 ctx_lh_G_front_inf-Triangul 180 220 140 0 +11115 ctx_lh_G_front_middle 140 100 180 0 +11116 ctx_lh_G_front_sup 180 20 140 0 +11117 ctx_lh_G_Ins_lg_and_S_cent_ins 23 10 10 0 +11118 ctx_lh_G_insular_short 225 140 140 0 +11119 ctx_lh_G_occipital_middle 180 60 180 0 +11120 ctx_lh_G_occipital_sup 20 220 60 0 +11121 ctx_lh_G_oc-temp_lat-fusifor 60 20 140 0 +11122 ctx_lh_G_oc-temp_med-Lingual 220 180 140 0 +11123 ctx_lh_G_oc-temp_med-Parahip 65 100 20 0 +11124 ctx_lh_G_orbital 220 60 20 0 +11125 ctx_lh_G_pariet_inf-Angular 20 60 220 0 +11126 ctx_lh_G_pariet_inf-Supramar 100 100 60 0 +11127 ctx_lh_G_parietal_sup 220 180 220 0 +11128 ctx_lh_G_postcentral 20 180 140 0 +11129 ctx_lh_G_precentral 60 140 180 0 +11130 ctx_lh_G_precuneus 25 20 140 0 +11131 ctx_lh_G_rectus 20 60 100 0 +11132 ctx_lh_G_subcallosal 60 220 20 0 +11133 ctx_lh_G_temp_sup-G_T_transv 60 60 220 0 +11134 ctx_lh_G_temp_sup-Lateral 220 60 220 0 +11135 ctx_lh_G_temp_sup-Plan_polar 65 220 60 0 +11136 ctx_lh_G_temp_sup-Plan_tempo 25 140 20 0 +11137 ctx_lh_G_temporal_inf 220 220 100 0 +11138 ctx_lh_G_temporal_middle 180 60 60 0 +11139 ctx_lh_Lat_Fis-ant-Horizont 61 20 220 0 +11140 ctx_lh_Lat_Fis-ant-Vertical 61 20 60 0 +11141 ctx_lh_Lat_Fis-post 61 60 100 0 +11142 ctx_lh_Medial_wall 25 25 25 0 +11143 ctx_lh_Pole_occipital 140 20 60 0 +11144 ctx_lh_Pole_temporal 220 180 20 0 +11145 ctx_lh_S_calcarine 63 180 180 0 +11146 ctx_lh_S_central 221 20 10 0 +11147 ctx_lh_S_cingul-Marginalis 221 20 100 0 +11148 ctx_lh_S_circular_insula_ant 221 60 140 0 +11149 ctx_lh_S_circular_insula_inf 221 20 220 0 +11150 ctx_lh_S_circular_insula_sup 61 220 220 0 +11151 ctx_lh_S_collat_transv_ant 100 200 200 0 +11152 ctx_lh_S_collat_transv_post 10 200 200 0 +11153 ctx_lh_S_front_inf 221 220 20 0 +11154 ctx_lh_S_front_middle 141 20 100 0 +11155 ctx_lh_S_front_sup 61 220 100 0 +11156 ctx_lh_S_interm_prim-Jensen 141 60 20 0 +11157 ctx_lh_S_intrapariet_and_P_trans 143 20 220 0 +11158 ctx_lh_S_oc_middle_and_Lunatus 101 60 220 0 +11159 ctx_lh_S_oc_sup_and_transversal 21 20 140 0 +11160 ctx_lh_S_occipital_ant 61 20 180 0 +11161 ctx_lh_S_oc-temp_lat 221 140 20 0 +11162 ctx_lh_S_oc-temp_med_and_Lingual 141 100 220 0 +11163 ctx_lh_S_orbital_lateral 221 100 20 0 +11164 ctx_lh_S_orbital_med-olfact 181 200 20 0 +11165 ctx_lh_S_orbital-H_Shaped 101 20 20 0 +11166 ctx_lh_S_parieto_occipital 101 100 180 0 +11167 ctx_lh_S_pericallosal 181 220 20 0 +11168 ctx_lh_S_postcentral 21 140 200 0 +11169 ctx_lh_S_precentral-inf-part 21 20 240 0 +11170 ctx_lh_S_precentral-sup-part 21 20 200 0 +11171 ctx_lh_S_suborbital 21 20 60 0 +11172 ctx_lh_S_subparietal 101 60 60 0 +11173 ctx_lh_S_temporal_inf 21 180 180 0 +11174 ctx_lh_S_temporal_sup 223 220 60 0 +11175 ctx_lh_S_temporal_transverse 221 60 60 0 + +12100 ctx_rh_Unknown 0 0 0 0 +12101 ctx_rh_G_and_S_frontomargin 23 220 60 0 +12102 ctx_rh_G_and_S_occipital_inf 23 60 180 0 +12103 ctx_rh_G_and_S_paracentral 63 100 60 0 +12104 ctx_rh_G_and_S_subcentral 63 20 220 0 +12105 ctx_rh_G_and_S_transv_frontopol 13 0 250 0 +12106 ctx_rh_G_and_S_cingul-Ant 26 60 0 0 +12107 ctx_rh_G_and_S_cingul-Mid-Ant 26 60 75 0 +12108 ctx_rh_G_and_S_cingul-Mid-Post 26 60 150 0 +12109 ctx_rh_G_cingul-Post-dorsal 25 60 250 0 +12110 ctx_rh_G_cingul-Post-ventral 60 25 25 0 +12111 ctx_rh_G_cuneus 180 20 20 0 +12112 ctx_rh_G_front_inf-Opercular 220 20 100 0 +12113 ctx_rh_G_front_inf-Orbital 140 60 60 0 +12114 ctx_rh_G_front_inf-Triangul 180 220 140 0 +12115 ctx_rh_G_front_middle 140 100 180 0 +12116 ctx_rh_G_front_sup 180 20 140 0 +12117 ctx_rh_G_Ins_lg_and_S_cent_ins 23 10 10 0 +12118 ctx_rh_G_insular_short 225 140 140 0 +12119 ctx_rh_G_occipital_middle 180 60 180 0 +12120 ctx_rh_G_occipital_sup 20 220 60 0 +12121 ctx_rh_G_oc-temp_lat-fusifor 60 20 140 0 +12122 ctx_rh_G_oc-temp_med-Lingual 220 180 140 0 +12123 ctx_rh_G_oc-temp_med-Parahip 65 100 20 0 +12124 ctx_rh_G_orbital 220 60 20 0 +12125 ctx_rh_G_pariet_inf-Angular 20 60 220 0 +12126 ctx_rh_G_pariet_inf-Supramar 100 100 60 0 +12127 ctx_rh_G_parietal_sup 220 180 220 0 +12128 ctx_rh_G_postcentral 20 180 140 0 +12129 ctx_rh_G_precentral 60 140 180 0 +12130 ctx_rh_G_precuneus 25 20 140 0 +12131 ctx_rh_G_rectus 20 60 100 0 +12132 ctx_rh_G_subcallosal 60 220 20 0 +12133 ctx_rh_G_temp_sup-G_T_transv 60 60 220 0 +12134 ctx_rh_G_temp_sup-Lateral 220 60 220 0 +12135 ctx_rh_G_temp_sup-Plan_polar 65 220 60 0 +12136 ctx_rh_G_temp_sup-Plan_tempo 25 140 20 0 +12137 ctx_rh_G_temporal_inf 220 220 100 0 +12138 ctx_rh_G_temporal_middle 180 60 60 0 +12139 ctx_rh_Lat_Fis-ant-Horizont 61 20 220 0 +12140 ctx_rh_Lat_Fis-ant-Vertical 61 20 60 0 +12141 ctx_rh_Lat_Fis-post 61 60 100 0 +12142 ctx_rh_Medial_wall 25 25 25 0 +12143 ctx_rh_Pole_occipital 140 20 60 0 +12144 ctx_rh_Pole_temporal 220 180 20 0 +12145 ctx_rh_S_calcarine 63 180 180 0 +12146 ctx_rh_S_central 221 20 10 0 +12147 ctx_rh_S_cingul-Marginalis 221 20 100 0 +12148 ctx_rh_S_circular_insula_ant 221 60 140 0 +12149 ctx_rh_S_circular_insula_inf 221 20 220 0 +12150 ctx_rh_S_circular_insula_sup 61 220 220 0 +12151 ctx_rh_S_collat_transv_ant 100 200 200 0 +12152 ctx_rh_S_collat_transv_post 10 200 200 0 +12153 ctx_rh_S_front_inf 221 220 20 0 +12154 ctx_rh_S_front_middle 141 20 100 0 +12155 ctx_rh_S_front_sup 61 220 100 0 +12156 ctx_rh_S_interm_prim-Jensen 141 60 20 0 +12157 ctx_rh_S_intrapariet_and_P_trans 143 20 220 0 +12158 ctx_rh_S_oc_middle_and_Lunatus 101 60 220 0 +12159 ctx_rh_S_oc_sup_and_transversal 21 20 140 0 +12160 ctx_rh_S_occipital_ant 61 20 180 0 +12161 ctx_rh_S_oc-temp_lat 221 140 20 0 +12162 ctx_rh_S_oc-temp_med_and_Lingual 141 100 220 0 +12163 ctx_rh_S_orbital_lateral 221 100 20 0 +12164 ctx_rh_S_orbital_med-olfact 181 200 20 0 +12165 ctx_rh_S_orbital-H_Shaped 101 20 20 0 +12166 ctx_rh_S_parieto_occipital 101 100 180 0 +12167 ctx_rh_S_pericallosal 181 220 20 0 +12168 ctx_rh_S_postcentral 21 140 200 0 +12169 ctx_rh_S_precentral-inf-part 21 20 240 0 +12170 ctx_rh_S_precentral-sup-part 21 20 200 0 +12171 ctx_rh_S_suborbital 21 20 60 0 +12172 ctx_rh_S_subparietal 101 60 60 0 +12173 ctx_rh_S_temporal_inf 21 180 180 0 +12174 ctx_rh_S_temporal_sup 223 220 60 0 +12175 ctx_rh_S_temporal_transverse 221 60 60 0 + +#No. Label Name: R G B A +13100 wm_lh_Unknown 0 0 0 0 +13101 wm_lh_G_and_S_frontomargin 23 220 60 0 +13102 wm_lh_G_and_S_occipital_inf 23 60 180 0 +13103 wm_lh_G_and_S_paracentral 63 100 60 0 +13104 wm_lh_G_and_S_subcentral 63 20 220 0 +13105 wm_lh_G_and_S_transv_frontopol 13 0 250 0 +13106 wm_lh_G_and_S_cingul-Ant 26 60 0 0 +13107 wm_lh_G_and_S_cingul-Mid-Ant 26 60 75 0 +13108 wm_lh_G_and_S_cingul-Mid-Post 26 60 150 0 +13109 wm_lh_G_cingul-Post-dorsal 25 60 250 0 +13110 wm_lh_G_cingul-Post-ventral 60 25 25 0 +13111 wm_lh_G_cuneus 180 20 20 0 +13112 wm_lh_G_front_inf-Opercular 220 20 100 0 +13113 wm_lh_G_front_inf-Orbital 140 60 60 0 +13114 wm_lh_G_front_inf-Triangul 180 220 140 0 +13115 wm_lh_G_front_middle 140 100 180 0 +13116 wm_lh_G_front_sup 180 20 140 0 +13117 wm_lh_G_Ins_lg_and_S_cent_ins 23 10 10 0 +13118 wm_lh_G_insular_short 225 140 140 0 +13119 wm_lh_G_occipital_middle 180 60 180 0 +13120 wm_lh_G_occipital_sup 20 220 60 0 +13121 wm_lh_G_oc-temp_lat-fusifor 60 20 140 0 +13122 wm_lh_G_oc-temp_med-Lingual 220 180 140 0 +13123 wm_lh_G_oc-temp_med-Parahip 65 100 20 0 +13124 wm_lh_G_orbital 220 60 20 0 +13125 wm_lh_G_pariet_inf-Angular 20 60 220 0 +13126 wm_lh_G_pariet_inf-Supramar 100 100 60 0 +13127 wm_lh_G_parietal_sup 220 180 220 0 +13128 wm_lh_G_postcentral 20 180 140 0 +13129 wm_lh_G_precentral 60 140 180 0 +13130 wm_lh_G_precuneus 25 20 140 0 +13131 wm_lh_G_rectus 20 60 100 0 +13132 wm_lh_G_subcallosal 60 220 20 0 +13133 wm_lh_G_temp_sup-G_T_transv 60 60 220 0 +13134 wm_lh_G_temp_sup-Lateral 220 60 220 0 +13135 wm_lh_G_temp_sup-Plan_polar 65 220 60 0 +13136 wm_lh_G_temp_sup-Plan_tempo 25 140 20 0 +13137 wm_lh_G_temporal_inf 220 220 100 0 +13138 wm_lh_G_temporal_middle 180 60 60 0 +13139 wm_lh_Lat_Fis-ant-Horizont 61 20 220 0 +13140 wm_lh_Lat_Fis-ant-Vertical 61 20 60 0 +13141 wm_lh_Lat_Fis-post 61 60 100 0 +13142 wm_lh_Medial_wall 25 25 25 0 +13143 wm_lh_Pole_occipital 140 20 60 0 +13144 wm_lh_Pole_temporal 220 180 20 0 +13145 wm_lh_S_calcarine 63 180 180 0 +13146 wm_lh_S_central 221 20 10 0 +13147 wm_lh_S_cingul-Marginalis 221 20 100 0 +13148 wm_lh_S_circular_insula_ant 221 60 140 0 +13149 wm_lh_S_circular_insula_inf 221 20 220 0 +13150 wm_lh_S_circular_insula_sup 61 220 220 0 +13151 wm_lh_S_collat_transv_ant 100 200 200 0 +13152 wm_lh_S_collat_transv_post 10 200 200 0 +13153 wm_lh_S_front_inf 221 220 20 0 +13154 wm_lh_S_front_middle 141 20 100 0 +13155 wm_lh_S_front_sup 61 220 100 0 +13156 wm_lh_S_interm_prim-Jensen 141 60 20 0 +13157 wm_lh_S_intrapariet_and_P_trans 143 20 220 0 +13158 wm_lh_S_oc_middle_and_Lunatus 101 60 220 0 +13159 wm_lh_S_oc_sup_and_transversal 21 20 140 0 +13160 wm_lh_S_occipital_ant 61 20 180 0 +13161 wm_lh_S_oc-temp_lat 221 140 20 0 +13162 wm_lh_S_oc-temp_med_and_Lingual 141 100 220 0 +13163 wm_lh_S_orbital_lateral 221 100 20 0 +13164 wm_lh_S_orbital_med-olfact 181 200 20 0 +13165 wm_lh_S_orbital-H_Shaped 101 20 20 0 +13166 wm_lh_S_parieto_occipital 101 100 180 0 +13167 wm_lh_S_pericallosal 181 220 20 0 +13168 wm_lh_S_postcentral 21 140 200 0 +13169 wm_lh_S_precentral-inf-part 21 20 240 0 +13170 wm_lh_S_precentral-sup-part 21 20 200 0 +13171 wm_lh_S_suborbital 21 20 60 0 +13172 wm_lh_S_subparietal 101 60 60 0 +13173 wm_lh_S_temporal_inf 21 180 180 0 +13174 wm_lh_S_temporal_sup 223 220 60 0 +13175 wm_lh_S_temporal_transverse 221 60 60 0 + +14100 wm_rh_Unknown 0 0 0 0 +14101 wm_rh_G_and_S_frontomargin 23 220 60 0 +14102 wm_rh_G_and_S_occipital_inf 23 60 180 0 +14103 wm_rh_G_and_S_paracentral 63 100 60 0 +14104 wm_rh_G_and_S_subcentral 63 20 220 0 +14105 wm_rh_G_and_S_transv_frontopol 13 0 250 0 +14106 wm_rh_G_and_S_cingul-Ant 26 60 0 0 +14107 wm_rh_G_and_S_cingul-Mid-Ant 26 60 75 0 +14108 wm_rh_G_and_S_cingul-Mid-Post 26 60 150 0 +14109 wm_rh_G_cingul-Post-dorsal 25 60 250 0 +14110 wm_rh_G_cingul-Post-ventral 60 25 25 0 +14111 wm_rh_G_cuneus 180 20 20 0 +14112 wm_rh_G_front_inf-Opercular 220 20 100 0 +14113 wm_rh_G_front_inf-Orbital 140 60 60 0 +14114 wm_rh_G_front_inf-Triangul 180 220 140 0 +14115 wm_rh_G_front_middle 140 100 180 0 +14116 wm_rh_G_front_sup 180 20 140 0 +14117 wm_rh_G_Ins_lg_and_S_cent_ins 23 10 10 0 +14118 wm_rh_G_insular_short 225 140 140 0 +14119 wm_rh_G_occipital_middle 180 60 180 0 +14120 wm_rh_G_occipital_sup 20 220 60 0 +14121 wm_rh_G_oc-temp_lat-fusifor 60 20 140 0 +14122 wm_rh_G_oc-temp_med-Lingual 220 180 140 0 +14123 wm_rh_G_oc-temp_med-Parahip 65 100 20 0 +14124 wm_rh_G_orbital 220 60 20 0 +14125 wm_rh_G_pariet_inf-Angular 20 60 220 0 +14126 wm_rh_G_pariet_inf-Supramar 100 100 60 0 +14127 wm_rh_G_parietal_sup 220 180 220 0 +14128 wm_rh_G_postcentral 20 180 140 0 +14129 wm_rh_G_precentral 60 140 180 0 +14130 wm_rh_G_precuneus 25 20 140 0 +14131 wm_rh_G_rectus 20 60 100 0 +14132 wm_rh_G_subcallosal 60 220 20 0 +14133 wm_rh_G_temp_sup-G_T_transv 60 60 220 0 +14134 wm_rh_G_temp_sup-Lateral 220 60 220 0 +14135 wm_rh_G_temp_sup-Plan_polar 65 220 60 0 +14136 wm_rh_G_temp_sup-Plan_tempo 25 140 20 0 +14137 wm_rh_G_temporal_inf 220 220 100 0 +14138 wm_rh_G_temporal_middle 180 60 60 0 +14139 wm_rh_Lat_Fis-ant-Horizont 61 20 220 0 +14140 wm_rh_Lat_Fis-ant-Vertical 61 20 60 0 +14141 wm_rh_Lat_Fis-post 61 60 100 0 +14142 wm_rh_Medial_wall 25 25 25 0 +14143 wm_rh_Pole_occipital 140 20 60 0 +14144 wm_rh_Pole_temporal 220 180 20 0 +14145 wm_rh_S_calcarine 63 180 180 0 +14146 wm_rh_S_central 221 20 10 0 +14147 wm_rh_S_cingul-Marginalis 221 20 100 0 +14148 wm_rh_S_circular_insula_ant 221 60 140 0 +14149 wm_rh_S_circular_insula_inf 221 20 220 0 +14150 wm_rh_S_circular_insula_sup 61 220 220 0 +14151 wm_rh_S_collat_transv_ant 100 200 200 0 +14152 wm_rh_S_collat_transv_post 10 200 200 0 +14153 wm_rh_S_front_inf 221 220 20 0 +14154 wm_rh_S_front_middle 141 20 100 0 +14155 wm_rh_S_front_sup 61 220 100 0 +14156 wm_rh_S_interm_prim-Jensen 141 60 20 0 +14157 wm_rh_S_intrapariet_and_P_trans 143 20 220 0 +14158 wm_rh_S_oc_middle_and_Lunatus 101 60 220 0 +14159 wm_rh_S_oc_sup_and_transversal 21 20 140 0 +14160 wm_rh_S_occipital_ant 61 20 180 0 +14161 wm_rh_S_oc-temp_lat 221 140 20 0 +14162 wm_rh_S_oc-temp_med_and_Lingual 141 100 220 0 +14163 wm_rh_S_orbital_lateral 221 100 20 0 +14164 wm_rh_S_orbital_med-olfact 181 200 20 0 +14165 wm_rh_S_orbital-H_Shaped 101 20 20 0 +14166 wm_rh_S_parieto_occipital 101 100 180 0 +14167 wm_rh_S_pericallosal 181 220 20 0 +14168 wm_rh_S_postcentral 21 140 200 0 +14169 wm_rh_S_precentral-inf-part 21 20 240 0 +14170 wm_rh_S_precentral-sup-part 21 20 200 0 +14171 wm_rh_S_suborbital 21 20 60 0 +14172 wm_rh_S_subparietal 101 60 60 0 +14173 wm_rh_S_temporal_inf 21 180 180 0 +14174 wm_rh_S_temporal_sup 223 220 60 0 +14175 wm_rh_S_temporal_transverse 221 60 60 0 + diff --git a/mne-python/source/mne/data/__init__.py b/mne-python/source/mne/data/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a48c2d637539b3e99680c822172ca5c80254cb5a --- /dev/null +++ b/mne-python/source/mne/data/__init__.py @@ -0,0 +1,5 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""MNE-Python data.""" diff --git a/mne-python/source/mne/data/coil_def.dat b/mne-python/source/mne/data/coil_def.dat new file mode 100644 index 0000000000000000000000000000000000000000..e3f7ebc6243ca189c1d84157c3022b104f4b0564 --- /dev/null +++ b/mne-python/source/mne/data/coil_def.dat @@ -0,0 +1,776 @@ +# +# MEG coil definition file +# +# Copyright 2005 - 2019 +# +# Matti Hamalainen +# Athinoula A. Martinos Center for Biomedical Imaging +# Charlestown, MA, USA +# +# +# "" +# +# struct class id accuracy num_points size baseline description +# format '%d %d %d %d %e %e %s' +# +# +# +# struct w x y z nx ny nz +# format '%f %e %e %e %e %e %e' +# +# .... +# +# +# +# 1 magnetometer +# 2 axial gradiometer +# 3 planar gradiometer +# 4 axial second-order gradiometer +# +# 0 point approximation +# 1 normal +# 2 accurate +# +# Produced with: +# +# mne_list_coil_def version 1.14 compiled at May 15 2021 07:58:54 +# +3 2 0 2 2.789e-02 1.620e-02 "Neuromag-122 planar gradiometer size = 27.89 mm base = 16.20 mm" + 61.7284 8.100e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +-61.7284 -8.100e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +3 2 1 2 2.789e-02 1.620e-02 "Neuromag-122 planar gradiometer size = 27.89 mm base = 16.20 mm" + 61.7284 8.100e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +-61.7284 -8.100e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +3 2 2 8 2.789e-02 1.620e-02 "Neuromag-122 planar gradiometer size = 27.89 mm base = 16.20 mm" + 15.1057 1.111e-02 7.680e-03 0.000e+00 0.000 0.000 1.000 + 15.1057 5.440e-03 7.680e-03 0.000e+00 0.000 0.000 1.000 + 15.1057 5.440e-03 -7.680e-03 0.000e+00 0.000 0.000 1.000 + 15.1057 1.111e-02 -7.680e-03 0.000e+00 0.000 0.000 1.000 +-15.1057 -1.111e-02 7.680e-03 0.000e+00 0.000 0.000 1.000 +-15.1057 -5.440e-03 7.680e-03 0.000e+00 0.000 0.000 1.000 +-15.1057 -5.440e-03 -7.680e-03 0.000e+00 0.000 0.000 1.000 +-15.1057 -1.111e-02 -7.680e-03 0.000e+00 0.000 0.000 1.000 +1 2000 0 1 0.000e+00 0.000e+00 "Point magnetometer" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 2000 1 1 0.000e+00 0.000e+00 "Point magnetometer" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 2000 2 1 0.000e+00 0.000e+00 "Point magnetometer" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +3 3012 0 2 2.639e-02 1.680e-02 "Vectorview planar gradiometer T1 size = 26.39 mm base = 16.80 mm" + 59.5238 8.400e-03 0.000e+00 3.000e-04 0.000 0.000 1.000 +-59.5238 -8.400e-03 0.000e+00 3.000e-04 0.000 0.000 1.000 +3 3012 1 4 2.639e-02 1.680e-02 "Vectorview planar gradiometer T1 size = 26.39 mm base = 16.80 mm" + 29.7619 8.400e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 + 29.7619 8.400e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-29.7619 -8.400e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 +-29.7619 -8.400e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +3 3012 2 8 2.639e-02 1.680e-02 "Vectorview planar gradiometer T1 size = 26.39 mm base = 16.80 mm" + 14.9858 1.079e-02 6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 5.891e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 5.891e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 1.079e-02 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -1.079e-02 6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -5.891e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -5.891e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -1.079e-02 -6.713e-03 3.000e-04 0.000 0.000 1.000 +3 3013 0 2 2.639e-02 1.680e-02 "Vectorview planar gradiometer T2 size = 26.39 mm base = 16.80 mm" + 59.5238 8.400e-03 0.000e+00 3.000e-04 0.000 0.000 1.000 +-59.5238 -8.400e-03 0.000e+00 3.000e-04 0.000 0.000 1.000 +3 3013 1 4 2.639e-02 1.680e-02 "Vectorview planar gradiometer T2 size = 26.39 mm base = 16.80 mm" + 29.7619 8.400e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 + 29.7619 8.400e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-29.7619 -8.400e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 +-29.7619 -8.400e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +3 3013 2 8 2.639e-02 1.680e-02 "Vectorview planar gradiometer T2 size = 26.39 mm base = 16.80 mm" + 14.9858 1.079e-02 6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 5.891e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 5.891e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 1.079e-02 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -1.079e-02 6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -5.891e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -5.891e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -1.079e-02 -6.713e-03 3.000e-04 0.000 0.000 1.000 +3 3014 0 2 2.639e-02 1.680e-02 "Vectorview planar gradiometer T3 size = 26.39 mm base = 16.80 mm" + 59.5238 8.400e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +-59.5238 -8.400e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +3 3014 1 4 2.639e-02 1.680e-02 "Vectorview planar gradiometer T3 size = 26.39 mm base = 16.80 mm" + 29.7619 8.400e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 + 29.7619 8.400e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-29.7619 -8.400e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 +-29.7619 -8.400e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +3 3014 2 8 2.639e-02 1.680e-02 "Vectorview planar gradiometer T3 size = 26.39 mm base = 16.80 mm" + 14.9858 1.079e-02 6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 5.891e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 5.891e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 1.079e-02 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -1.079e-02 6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -5.891e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -5.891e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -1.079e-02 -6.713e-03 3.000e-04 0.000 0.000 1.000 +3 3015 0 2 2.639e-02 1.680e-02 "Vectorview planar gradiometer T4 (MEG-MRI) size = 26.39 mm base = 16.80 mm" + 59.5238 8.400e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +-59.5238 -8.400e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +3 3015 1 4 2.639e-02 1.680e-02 "Vectorview planar gradiometer T4 (MEG-MRI) size = 26.39 mm base = 16.80 mm" + 29.7619 8.400e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 + 29.7619 8.400e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-29.7619 -8.400e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 +-29.7619 -8.400e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +3 3015 2 8 2.639e-02 1.680e-02 "Vectorview planar gradiometer T4 (MEG-MRI) size = 26.39 mm base = 16.80 mm" + 14.9858 1.079e-02 6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 5.891e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 5.891e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 + 14.9858 1.079e-02 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -1.079e-02 6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -5.891e-03 6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -5.891e-03 -6.713e-03 3.000e-04 0.000 0.000 1.000 +-14.9858 -1.079e-02 -6.713e-03 3.000e-04 0.000 0.000 1.000 +1 3022 0 1 2.580e-02 0.000e+00 "Vectorview magnetometer T1 size = 25.80 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 3022 1 4 2.580e-02 0.000e+00 "Vectorview magnetometer T1 size = 25.80 mm" + 0.2500 -6.450e-03 -6.450e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 -6.450e-03 6.450e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 6.450e-03 -6.450e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 6.450e-03 6.450e-03 3.000e-04 0.000 0.000 1.000 +1 3022 2 16 2.580e-02 0.000e+00 "Vectorview magnetometer T1 size = 25.80 mm" + 0.0625 -9.675e-03 -9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -9.675e-03 -3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -9.675e-03 3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -9.675e-03 9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.225e-03 -9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.225e-03 -3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.225e-03 3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.225e-03 9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.225e-03 -9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.225e-03 -3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.225e-03 3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.225e-03 9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 9.675e-03 -9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 9.675e-03 -3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 9.675e-03 3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 9.675e-03 9.675e-03 3.000e-04 0.000 0.000 1.000 +1 3023 0 1 2.580e-02 0.000e+00 "Vectorview magnetometer T2 size = 25.80 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 3023 1 4 2.580e-02 0.000e+00 "Vectorview magnetometer T2 size = 25.80 mm" + 0.2500 -6.450e-03 -6.450e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 -6.450e-03 6.450e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 6.450e-03 -6.450e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 6.450e-03 6.450e-03 3.000e-04 0.000 0.000 1.000 +1 3023 2 16 2.580e-02 0.000e+00 "Vectorview magnetometer T2 size = 25.80 mm" + 0.0625 -9.675e-03 -9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -9.675e-03 -3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -9.675e-03 3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -9.675e-03 9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.225e-03 -9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.225e-03 -3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.225e-03 3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.225e-03 9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.225e-03 -9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.225e-03 -3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.225e-03 3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.225e-03 9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 9.675e-03 -9.675e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 9.675e-03 -3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 9.675e-03 3.225e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 9.675e-03 9.675e-03 3.000e-04 0.000 0.000 1.000 +1 3024 0 1 2.100e-02 0.000e+00 "Vectorview magnetometer T3 size = 21.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 3024 1 4 2.100e-02 0.000e+00 "Vectorview magnetometer T3 size = 21.00 mm" + 0.2500 -5.250e-03 -5.250e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 -5.250e-03 5.250e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 5.250e-03 -5.250e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 5.250e-03 5.250e-03 3.000e-04 0.000 0.000 1.000 +1 3024 2 16 2.100e-02 0.000e+00 "Vectorview magnetometer T3 size = 21.00 mm" + 0.0625 -7.875e-03 -7.875e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -7.875e-03 -2.625e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -7.875e-03 2.625e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -7.875e-03 7.875e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -2.625e-03 -7.875e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -2.625e-03 -2.625e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -2.625e-03 2.625e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -2.625e-03 7.875e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 2.625e-03 -7.875e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 2.625e-03 -2.625e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 2.625e-03 2.625e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 2.625e-03 7.875e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 7.875e-03 -7.875e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 7.875e-03 -2.625e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 7.875e-03 2.625e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 7.875e-03 7.875e-03 3.000e-04 0.000 0.000 1.000 +1 3025 0 1 2.800e-02 0.000e+00 "Vectorview magnetometer T4 (MEG-MRI) size = 28.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 3025 1 4 2.800e-02 0.000e+00 "Vectorview magnetometer T4 (MEG-MRI) size = 28.00 mm" + 0.2500 -7.000e-03 -7.000e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 -7.000e-03 7.000e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 7.000e-03 -7.000e-03 3.000e-04 0.000 0.000 1.000 + 0.2500 7.000e-03 7.000e-03 3.000e-04 0.000 0.000 1.000 +1 3025 2 16 2.800e-02 0.000e+00 "Vectorview magnetometer T4 (MEG-MRI) size = 28.00 mm" + 0.0625 -1.050e-02 -1.050e-02 3.000e-04 0.000 0.000 1.000 + 0.0625 -1.050e-02 -3.500e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -1.050e-02 3.500e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -1.050e-02 1.050e-02 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.500e-03 -1.050e-02 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.500e-03 -3.500e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.500e-03 3.500e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 -3.500e-03 1.050e-02 3.000e-04 0.000 0.000 1.000 + 0.0625 3.500e-03 -1.050e-02 3.000e-04 0.000 0.000 1.000 + 0.0625 3.500e-03 -3.500e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.500e-03 3.500e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 3.500e-03 1.050e-02 3.000e-04 0.000 0.000 1.000 + 0.0625 1.050e-02 -1.050e-02 3.000e-04 0.000 0.000 1.000 + 0.0625 1.050e-02 -3.500e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 1.050e-02 3.500e-03 3.000e-04 0.000 0.000 1.000 + 0.0625 1.050e-02 1.050e-02 3.000e-04 0.000 0.000 1.000 +1 4001 0 1 2.300e-02 0.000e+00 "Magnes WH2500 magnetometer size = 23.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 4001 1 4 2.300e-02 0.000e+00 "Magnes WH2500 magnetometer size = 23.00 mm" + 0.2500 5.750e-03 5.750e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.750e-03 5.750e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.750e-03 -5.750e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 5.750e-03 -5.750e-03 0.000e+00 0.000 0.000 1.000 +1 4001 2 7 2.300e-02 0.000e+00 "Magnes WH2500 magnetometer size = 23.00 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 9.390e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -9.390e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 4.695e-03 8.132e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 4.695e-03 -8.132e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.695e-03 8.132e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.695e-03 -8.132e-03 0.000e+00 0.000 0.000 1.000 +2 4002 0 2 1.800e-02 5.000e-02 "Magnes WH3600 gradiometer size = 18.00 mm base = 50.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 +2 4002 1 8 1.800e-02 5.000e-02 "Magnes WH3600 gradiometer size = 18.00 mm base = 50.00 mm" + 0.2500 4.500e-03 4.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -4.500e-03 4.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -4.500e-03 -4.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 4.500e-03 -4.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 4.500e-03 4.500e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -4.500e-03 4.500e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -4.500e-03 -4.500e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 4.500e-03 -4.500e-03 5.000e-02 0.000 0.000 1.000 +2 4002 2 14 1.800e-02 5.000e-02 "Magnes WH3600 gradiometer size = 18.00 mm base = 50.00 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 7.348e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -7.348e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 3.674e-03 6.364e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 3.674e-03 -6.364e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.674e-03 6.364e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.674e-03 -6.364e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 7.348e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 -7.348e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 3.674e-03 6.364e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 3.674e-03 -6.364e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -3.674e-03 6.364e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -3.674e-03 -6.364e-03 5.000e-02 0.000 0.000 1.000 +1 4003 0 1 3.000e-02 0.000e+00 "Magnes reference magnetometer size = 30.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 4003 1 4 3.000e-02 0.000e+00 "Magnes reference magnetometer size = 30.00 mm" + 0.2500 7.500e-03 7.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -7.500e-03 7.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -7.500e-03 -7.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 7.500e-03 -7.500e-03 0.000e+00 0.000 0.000 1.000 +1 4003 2 4 3.000e-02 0.000e+00 "Magnes reference magnetometer size = 30.00 mm" + 0.2500 7.500e-03 7.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -7.500e-03 7.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -7.500e-03 -7.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 7.500e-03 -7.500e-03 0.000e+00 0.000 0.000 1.000 +2 4004 0 2 8.000e-02 1.350e-01 "Magnes reference gradiometer (diag) size = 80.00 mm base = 135.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 1.350e-01 0.000 0.000 1.000 +2 4004 1 8 8.000e-02 1.350e-01 "Magnes reference gradiometer (diag) size = 80.00 mm base = 135.00 mm" + 0.2500 2.000e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 -2.000e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 -2.000e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 2.000e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 2.000e-02 2.000e-02 1.350e-01 0.000 0.000 1.000 + -0.2500 -2.000e-02 2.000e-02 1.350e-01 0.000 0.000 1.000 + -0.2500 -2.000e-02 -2.000e-02 1.350e-01 0.000 0.000 1.000 + -0.2500 2.000e-02 -2.000e-02 1.350e-01 0.000 0.000 1.000 +2 4004 2 8 8.000e-02 1.350e-01 "Magnes reference gradiometer (diag) size = 80.00 mm base = 135.00 mm" + 0.2500 2.000e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 -2.000e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 -2.000e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 2.000e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 2.000e-02 2.000e-02 1.350e-01 0.000 0.000 1.000 + -0.2500 -2.000e-02 2.000e-02 1.350e-01 0.000 0.000 1.000 + -0.2500 -2.000e-02 -2.000e-02 1.350e-01 0.000 0.000 1.000 + -0.2500 2.000e-02 -2.000e-02 1.350e-01 0.000 0.000 1.000 +2 4005 0 2 8.000e-02 1.350e-01 "Magnes reference gradiometer (offdiag) size = 80.00 mm base = 135.00 mm" + 1.0000 6.750e-02 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 -6.750e-02 0.000e+00 0.000e+00 0.000 0.000 1.000 +2 4005 1 8 8.000e-02 1.350e-01 "Magnes reference gradiometer (offdiag) size = 80.00 mm base = 135.00 mm" + 0.2500 8.750e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 4.750e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 4.750e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 8.750e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 -4.750e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 -8.750e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 -8.750e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 -4.750e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 +2 4005 2 8 8.000e-02 1.350e-01 "Magnes reference gradiometer (offdiag) size = 80.00 mm base = 135.00 mm" + 0.2500 8.750e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 4.750e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 4.750e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + 0.2500 8.750e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 -4.750e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 -8.750e-02 2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 -8.750e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 + -0.2500 -4.750e-02 -2.000e-02 0.000e+00 0.000 0.000 1.000 +2 5001 0 2 1.800e-02 5.000e-02 "CTF axial gradiometer size = 18.00 mm base = 50.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 +2 5001 1 8 1.800e-02 5.000e-02 "CTF axial gradiometer size = 18.00 mm base = 50.00 mm" + 0.2500 4.500e-03 4.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -4.500e-03 4.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -4.500e-03 -4.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 4.500e-03 -4.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 4.500e-03 4.500e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -4.500e-03 4.500e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -4.500e-03 -4.500e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 4.500e-03 -4.500e-03 5.000e-02 0.000 0.000 1.000 +2 5001 2 14 1.800e-02 5.000e-02 "CTF axial gradiometer size = 18.00 mm base = 50.00 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 7.348e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -7.348e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 3.674e-03 6.364e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 3.674e-03 -6.364e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.674e-03 6.364e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.674e-03 -6.364e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 7.348e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 -7.348e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 3.674e-03 6.364e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 3.674e-03 -6.364e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -3.674e-03 6.364e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -3.674e-03 -6.364e-03 5.000e-02 0.000 0.000 1.000 +1 5002 0 1 1.600e-02 0.000e+00 "CTF reference magnetometer size = 16.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 5002 1 4 1.600e-02 0.000e+00 "CTF reference magnetometer size = 16.00 mm" + 0.2500 4.000e-03 4.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -4.000e-03 4.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -4.000e-03 -4.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 4.000e-03 -4.000e-03 0.000e+00 0.000 0.000 1.000 +1 5002 2 4 1.600e-02 0.000e+00 "CTF reference magnetometer size = 16.00 mm" + 0.2500 4.000e-03 4.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -4.000e-03 4.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -4.000e-03 -4.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 4.000e-03 -4.000e-03 0.000e+00 0.000 0.000 1.000 +2 5003 0 2 3.440e-02 7.860e-02 "CTF reference gradiometer (diag) size = 34.40 mm base = 78.60 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 7.860e-02 0.000 0.000 1.000 +2 5003 1 8 3.440e-02 7.860e-02 "CTF reference gradiometer (diag) size = 34.40 mm base = 78.60 mm" + 0.2500 8.600e-03 8.600e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -8.600e-03 8.600e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -8.600e-03 -8.600e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 8.600e-03 -8.600e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 8.600e-03 8.600e-03 7.860e-02 0.000 0.000 1.000 + -0.2500 -8.600e-03 8.600e-03 7.860e-02 0.000 0.000 1.000 + -0.2500 -8.600e-03 -8.600e-03 7.860e-02 0.000 0.000 1.000 + -0.2500 8.600e-03 -8.600e-03 7.860e-02 0.000 0.000 1.000 +2 5003 2 8 3.440e-02 7.860e-02 "CTF reference gradiometer (diag) size = 34.40 mm base = 78.60 mm" + 0.2500 8.600e-03 8.600e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -8.600e-03 8.600e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -8.600e-03 -8.600e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 8.600e-03 -8.600e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 8.600e-03 8.600e-03 7.860e-02 0.000 0.000 1.000 + -0.2500 -8.600e-03 8.600e-03 7.860e-02 0.000 0.000 1.000 + -0.2500 -8.600e-03 -8.600e-03 7.860e-02 0.000 0.000 1.000 + -0.2500 8.600e-03 -8.600e-03 7.860e-02 0.000 0.000 1.000 +2 5004 0 2 3.440e-02 7.860e-02 "CTF reference gradiometer (offdiag) size = 34.40 mm base = 78.60 mm" + 1.0000 3.930e-02 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 -3.930e-02 0.000e+00 0.000e+00 0.000 0.000 1.000 +2 5004 1 8 3.440e-02 7.860e-02 "CTF reference gradiometer (offdiag) size = 34.40 mm base = 78.60 mm" + 0.2500 4.780e-02 8.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.080e-02 8.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.080e-02 -8.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 4.780e-02 -8.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 -3.080e-02 8.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 -4.780e-02 8.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 -4.780e-02 -8.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 -3.080e-02 -8.500e-03 0.000e+00 0.000 0.000 1.000 +2 5004 2 8 3.440e-02 7.860e-02 "CTF reference gradiometer (offdiag) size = 34.40 mm base = 78.60 mm" + 0.2500 4.780e-02 8.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.080e-02 8.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.080e-02 -8.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 4.780e-02 -8.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 -3.080e-02 8.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 -4.780e-02 8.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 -4.780e-02 -8.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 -3.080e-02 -8.500e-03 0.000e+00 0.000 0.000 1.000 +2 6001 0 2 1.550e-02 5.000e-02 "MIT KIT system gradiometer size = 15.50 mm base = 50.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 +2 6001 1 8 1.550e-02 5.000e-02 "MIT KIT system gradiometer size = 15.50 mm base = 50.00 mm" + 0.2500 3.875e-03 3.875e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.875e-03 3.875e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.875e-03 -3.875e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.875e-03 -3.875e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 3.875e-03 3.875e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -3.875e-03 3.875e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -3.875e-03 -3.875e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 3.875e-03 -3.875e-03 5.000e-02 0.000 0.000 1.000 +2 6001 2 14 1.550e-02 5.000e-02 "MIT KIT system gradiometer size = 15.50 mm base = 50.00 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 6.328e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -6.328e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 3.164e-03 5.480e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 3.164e-03 -5.480e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.164e-03 5.480e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.164e-03 -5.480e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 6.328e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 -6.328e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 3.164e-03 5.480e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 3.164e-03 -5.480e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -3.164e-03 5.480e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -3.164e-03 -5.480e-03 5.000e-02 0.000 0.000 1.000 +1 6002 0 1 1.550e-02 0.000e+00 "MIT KIT system reference magnetometer size = 15.50 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 6002 1 4 1.550e-02 0.000e+00 "MIT KIT system reference magnetometer size = 15.50 mm" + 0.2500 3.875e-03 3.875e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.875e-03 3.875e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.875e-03 -3.875e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.875e-03 -3.875e-03 0.000e+00 0.000 0.000 1.000 +1 6002 2 7 1.550e-02 0.000e+00 "MIT KIT system reference magnetometer size = 15.50 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 6.328e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -6.328e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 3.164e-03 5.480e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 3.164e-03 -5.480e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.164e-03 5.480e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.164e-03 -5.480e-03 0.000e+00 0.000 0.000 1.000 +2 7001 0 2 6.000e-03 5.000e-02 "BabySQUID system gradiometer size = 6.00 mm base = 50.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 +2 7001 1 2 6.000e-03 5.000e-02 "BabySQUID system gradiometer size = 6.00 mm base = 50.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 +2 7001 2 8 6.000e-03 5.000e-02 "BabySQUID system gradiometer size = 6.00 mm base = 50.00 mm" + 0.2500 1.500e-03 1.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -1.500e-03 1.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -1.500e-03 -1.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 1.500e-03 -1.500e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 1.500e-03 1.500e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -1.500e-03 1.500e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -1.500e-03 -1.500e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 1.500e-03 -1.500e-03 5.000e-02 0.000 0.000 1.000 +1 7002 0 1 1.000e-02 0.000e+00 "BabyMEG system magnetometer size = 10.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 7002 1 4 1.000e-02 0.000e+00 "BabyMEG system magnetometer size = 10.00 mm" + 0.2500 2.500e-03 2.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -2.500e-03 2.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -2.500e-03 -2.500e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 2.500e-03 -2.500e-03 0.000e+00 0.000 0.000 1.000 +1 7002 2 7 1.000e-02 0.000e+00 "BabyMEG system magnetometer size = 10.00 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 4.082e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.082e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 2.041e-03 3.536e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 2.041e-03 -3.536e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -2.041e-03 3.536e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -2.041e-03 -3.536e-03 0.000e+00 0.000 0.000 1.000 +1 7003 0 1 2.000e-02 0.000e+00 "BabyMEG system compensation magnetometer size = 20.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 7003 1 4 2.000e-02 0.000e+00 "BabyMEG system compensation magnetometer size = 20.00 mm" + 0.2500 5.000e-03 5.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.000e-03 5.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.000e-03 -5.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 5.000e-03 -5.000e-03 0.000e+00 0.000 0.000 1.000 +1 7003 2 7 2.000e-02 0.000e+00 "BabyMEG system compensation magnetometer size = 20.00 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 8.165e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -8.165e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 4.082e-03 7.071e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 4.082e-03 -7.071e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.082e-03 7.071e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.082e-03 -7.071e-03 0.000e+00 0.000 0.000 1.000 +1 7004 0 1 2.000e-02 0.000e+00 "BabyMEG system reference magnetometer size = 20.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 7004 1 4 2.000e-02 0.000e+00 "BabyMEG system reference magnetometer size = 20.00 mm" + 0.2500 5.000e-03 5.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.000e-03 5.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.000e-03 -5.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 5.000e-03 -5.000e-03 0.000e+00 0.000 0.000 1.000 +1 7004 2 7 2.000e-02 0.000e+00 "BabyMEG system reference magnetometer size = 20.00 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 8.165e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -8.165e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 4.082e-03 7.071e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 4.082e-03 -7.071e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.082e-03 7.071e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.082e-03 -7.071e-03 0.000e+00 0.000 0.000 1.000 +2 9001 0 2 2.000e-02 5.000e-02 "KRISS system gradiometer size = 20.00 mm base = 50.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 +2 9001 1 8 2.000e-02 5.000e-02 "KRISS system gradiometer size = 20.00 mm base = 50.00 mm" + 0.2500 5.000e-03 5.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.000e-03 5.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.000e-03 -5.000e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 5.000e-03 -5.000e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 5.000e-03 5.000e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -5.000e-03 5.000e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -5.000e-03 -5.000e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 5.000e-03 -5.000e-03 5.000e-02 0.000 0.000 1.000 +2 9001 2 14 2.000e-02 5.000e-02 "KRISS system gradiometer size = 20.00 mm base = 50.00 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 8.165e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -8.165e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 4.082e-03 7.071e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 4.082e-03 -7.071e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.082e-03 7.071e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.082e-03 -7.071e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 8.165e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 -8.165e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 4.082e-03 7.071e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 4.082e-03 -7.071e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -4.082e-03 7.071e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -4.082e-03 -7.071e-03 5.000e-02 0.000 0.000 1.000 +2 7501 0 2 1.486e-02 5.740e-02 "Artemis system gradiometer size = 14.86 mm base = 57.40 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 5.740e-02 0.000 0.000 1.000 +2 7501 1 8 1.486e-02 5.740e-02 "Artemis system gradiometer size = 14.86 mm base = 57.40 mm" + 0.2500 3.715e-03 3.715e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.715e-03 3.715e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.715e-03 -3.715e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.715e-03 -3.715e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 3.715e-03 3.715e-03 5.740e-02 0.000 0.000 1.000 + -0.2500 -3.715e-03 3.715e-03 5.740e-02 0.000 0.000 1.000 + -0.2500 -3.715e-03 -3.715e-03 5.740e-02 0.000 0.000 1.000 + -0.2500 3.715e-03 -3.715e-03 5.740e-02 0.000 0.000 1.000 +2 7501 2 14 1.486e-02 5.740e-02 "Artemis system gradiometer size = 14.86 mm base = 57.40 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 6.067e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -6.067e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 3.033e-03 5.254e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 3.033e-03 -5.254e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.033e-03 5.254e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -3.033e-03 -5.254e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 0.000e+00 0.000e+00 5.740e-02 0.000 0.000 1.000 + -0.1250 6.067e-03 0.000e+00 5.740e-02 0.000 0.000 1.000 + -0.1250 -6.067e-03 0.000e+00 5.740e-02 0.000 0.000 1.000 + -0.1250 3.033e-03 5.254e-03 5.740e-02 0.000 0.000 1.000 + -0.1250 3.033e-03 -5.254e-03 5.740e-02 0.000 0.000 1.000 + -0.1250 -3.033e-03 5.254e-03 5.740e-02 0.000 0.000 1.000 + -0.1250 -3.033e-03 -5.254e-03 5.740e-02 0.000 0.000 1.000 +1 7502 0 1 1.485e-02 0.000e+00 "Artemis system reference magnetometer size = 14.85 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 7502 1 4 1.485e-02 0.000e+00 "Artemis system reference magnetometer size = 14.85 mm" + 0.2500 3.712e-03 3.712e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.712e-03 3.712e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.712e-03 -3.712e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.712e-03 -3.712e-03 0.000e+00 0.000 0.000 1.000 +1 7502 2 4 1.485e-02 0.000e+00 "Artemis system reference magnetometer size = 14.85 mm" + 0.2500 3.712e-03 3.712e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.712e-03 3.712e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.712e-03 -3.712e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.712e-03 -3.712e-03 0.000e+00 0.000 0.000 1.000 +2 7503 0 2 1.486e-02 3.000e-02 "Artemis system reference gradiometer size = 14.86 mm base = 30.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 3.000e-02 0.000 0.000 1.000 +2 7503 1 8 1.486e-02 3.000e-02 "Artemis system reference gradiometer size = 14.86 mm base = 30.00 mm" + 0.2500 3.715e-03 3.715e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.715e-03 3.715e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.715e-03 -3.715e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.715e-03 -3.715e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 3.715e-03 3.715e-03 3.000e-02 0.000 0.000 1.000 + -0.2500 -3.715e-03 3.715e-03 3.000e-02 0.000 0.000 1.000 + -0.2500 -3.715e-03 -3.715e-03 3.000e-02 0.000 0.000 1.000 + -0.2500 3.715e-03 -3.715e-03 3.000e-02 0.000 0.000 1.000 +2 7503 2 8 1.486e-02 3.000e-02 "Artemis system reference gradiometer size = 14.86 mm base = 30.00 mm" + 0.2500 3.715e-03 3.715e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.715e-03 3.715e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -3.715e-03 -3.715e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 3.715e-03 -3.715e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 3.715e-03 3.715e-03 3.000e-02 0.000 0.000 1.000 + -0.2500 -3.715e-03 3.715e-03 3.000e-02 0.000 0.000 1.000 + -0.2500 -3.715e-03 -3.715e-03 3.000e-02 0.000 0.000 1.000 + -0.2500 3.715e-03 -3.715e-03 3.000e-02 0.000 0.000 1.000 +2 9101 0 2 2.050e-02 5.000e-02 "Compumedics adult gradiometer size = 20.50 mm base = 50.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 +2 9101 1 8 2.050e-02 5.000e-02 "Compumedics adult gradiometer size = 20.50 mm base = 50.00 mm" + 0.2500 5.125e-03 5.125e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.125e-03 5.125e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 -5.125e-03 -5.125e-03 0.000e+00 0.000 0.000 1.000 + 0.2500 5.125e-03 -5.125e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 5.125e-03 5.125e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -5.125e-03 5.125e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 -5.125e-03 -5.125e-03 5.000e-02 0.000 0.000 1.000 + -0.2500 5.125e-03 -5.125e-03 5.000e-02 0.000 0.000 1.000 +2 9101 2 14 2.050e-02 5.000e-02 "Compumedics adult gradiometer size = 20.50 mm base = 50.00 mm" + 0.2500 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 8.369e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 -8.369e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1250 4.185e-03 7.248e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 4.185e-03 -7.248e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.185e-03 7.248e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.185e-03 -7.248e-03 0.000e+00 0.000 0.000 1.000 + -0.2500 0.000e+00 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 8.369e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 -8.369e-03 0.000e+00 5.000e-02 0.000 0.000 1.000 + -0.1250 4.185e-03 7.248e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 4.185e-03 -7.248e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -4.185e-03 7.248e-03 5.000e-02 0.000 0.000 1.000 + -0.1250 -4.185e-03 -7.248e-03 5.000e-02 0.000 0.000 1.000 +2 9102 0 2 1.660e-02 4.700e-02 "Compumedics pediatric gradiometer size = 16.60 mm base = 47.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + -1.0000 0.000e+00 0.000e+00 4.700e-02 0.000 0.000 1.000 +2 9102 1 16 1.660e-02 4.700e-02 "Compumedics pediatric gradiometer size = 16.60 mm base = 47.00 mm" + 0.1250 4.150e-03 4.150e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.150e-03 4.150e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.150e-03 -4.150e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 4.150e-03 -4.150e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 4.150e-03 4.150e-03 1.500e-03 0.000 0.000 1.000 + 0.1250 -4.150e-03 4.150e-03 1.500e-03 0.000 0.000 1.000 + 0.1250 -4.150e-03 -4.150e-03 1.500e-03 0.000 0.000 1.000 + 0.1250 4.150e-03 -4.150e-03 1.500e-03 0.000 0.000 1.000 + -0.1250 4.150e-03 4.150e-03 4.700e-02 0.000 0.000 1.000 + -0.1250 -4.150e-03 4.150e-03 4.700e-02 0.000 0.000 1.000 + -0.1250 -4.150e-03 -4.150e-03 4.700e-02 0.000 0.000 1.000 + -0.1250 4.150e-03 -4.150e-03 4.700e-02 0.000 0.000 1.000 + -0.1250 4.150e-03 4.150e-03 4.850e-02 0.000 0.000 1.000 + -0.1250 -4.150e-03 4.150e-03 4.850e-02 0.000 0.000 1.000 + -0.1250 -4.150e-03 -4.150e-03 4.850e-02 0.000 0.000 1.000 + -0.1250 4.150e-03 -4.150e-03 4.850e-02 0.000 0.000 1.000 +2 9102 2 16 1.660e-02 4.700e-02 "Compumedics pediatric gradiometer size = 16.60 mm base = 47.00 mm" + 0.1250 4.150e-03 4.150e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.150e-03 4.150e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 -4.150e-03 -4.150e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 4.150e-03 -4.150e-03 0.000e+00 0.000 0.000 1.000 + 0.1250 4.150e-03 4.150e-03 1.500e-03 0.000 0.000 1.000 + 0.1250 -4.150e-03 4.150e-03 1.500e-03 0.000 0.000 1.000 + 0.1250 -4.150e-03 -4.150e-03 1.500e-03 0.000 0.000 1.000 + 0.1250 4.150e-03 -4.150e-03 1.500e-03 0.000 0.000 1.000 + -0.1250 4.150e-03 4.150e-03 4.700e-02 0.000 0.000 1.000 + -0.1250 -4.150e-03 4.150e-03 4.700e-02 0.000 0.000 1.000 + -0.1250 -4.150e-03 -4.150e-03 4.700e-02 0.000 0.000 1.000 + -0.1250 4.150e-03 -4.150e-03 4.700e-02 0.000 0.000 1.000 + -0.1250 4.150e-03 4.150e-03 4.850e-02 0.000 0.000 1.000 + -0.1250 -4.150e-03 4.150e-03 4.850e-02 0.000 0.000 1.000 + -0.1250 -4.150e-03 -4.150e-03 4.850e-02 0.000 0.000 1.000 + -0.1250 4.150e-03 -4.150e-03 4.850e-02 0.000 0.000 1.000 +1 8001 0 1 7.000e-04 0.000e+00 "QSpin OPM sensor Gen1 size = 0.70 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 8001 1 6 7.000e-04 0.000e+00 "QSpin OPM sensor Gen1 size = 0.70 mm" + 0.1667 -1.250e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 -7.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 -2.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 2.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 7.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 1.250e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 8001 2 24 7.000e-04 0.000e+00 "QSpin OPM sensor Gen1 size = 0.70 mm" + 0.0417 -1.250e-03 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -1.250e-03 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -1.250e-03 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -1.250e-03 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 1.750e-04 -1.750e-04 0.000 0.000 1.000 +1 8002 0 1 7.000e-04 0.000e+00 "QSpin OPM sensor Gen2 size = 0.70 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 8002 1 6 7.000e-04 0.000e+00 "QSpin OPM sensor Gen2 size = 0.70 mm" + 0.1667 -1.250e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 -7.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 -2.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 2.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 7.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 1.250e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 8002 2 24 7.000e-04 0.000e+00 "QSpin OPM sensor Gen2 size = 0.70 mm" + 0.0417 -1.250e-03 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -1.250e-03 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -1.250e-03 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -1.250e-03 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 -1.750e-04 1.750e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 -1.750e-04 -1.750e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 1.750e-04 -1.750e-04 0.000 0.000 1.000 +1 8101 0 1 2.000e-03 0.000e+00 "FieldLine OPM sensor Gen1 size = 2.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 8101 1 6 2.000e-03 0.000e+00 "FieldLine OPM sensor Gen1 size = 2.00 mm" + 0.1667 -1.250e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 -7.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 -2.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 2.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 7.500e-04 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1667 1.250e-03 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 8101 2 24 2.000e-03 0.000e+00 "FieldLine OPM sensor Gen1 size = 2.00 mm" + 0.0417 -1.250e-03 5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 -1.250e-03 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 -1.250e-03 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 -1.250e-03 5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 -7.500e-04 5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 -2.500e-04 5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 2.500e-04 5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 7.500e-04 5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.0417 1.250e-03 5.000e-04 -5.000e-04 0.000 0.000 1.000 +1 8201 0 1 2.000e-03 0.000e+00 "Kernel OPM sensor Gen1 size = 2.00 mm" + 1.0000 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 +1 8201 1 9 2.000e-03 0.000e+00 "Kernel OPM sensor Gen1 size = 2.00 mm" + 0.1111 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1111 -5.000e-04 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.1111 5.000e-04 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.1111 -5.000e-04 5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.1111 5.000e-04 5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.1111 -5.000e-04 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.1111 5.000e-04 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.1111 -5.000e-04 5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.1111 5.000e-04 5.000e-04 5.000e-04 0.000 0.000 1.000 +1 8201 2 9 2.000e-03 0.000e+00 "Kernel OPM sensor Gen1 size = 2.00 mm" + 0.1111 0.000e+00 0.000e+00 0.000e+00 0.000 0.000 1.000 + 0.1111 -5.000e-04 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.1111 5.000e-04 -5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.1111 -5.000e-04 5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.1111 5.000e-04 5.000e-04 -5.000e-04 0.000 0.000 1.000 + 0.1111 -5.000e-04 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.1111 5.000e-04 -5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.1111 -5.000e-04 5.000e-04 5.000e-04 0.000 0.000 1.000 + 0.1111 5.000e-04 5.000e-04 5.000e-04 0.000 0.000 1.000 diff --git a/mne-python/source/mne/data/coil_def_Elekta.dat b/mne-python/source/mne/data/coil_def_Elekta.dat new file mode 100644 index 0000000000000000000000000000000000000000..4bca22de3f6223d7135945a4b4b16f60a5d627de --- /dev/null +++ b/mne-python/source/mne/data/coil_def_Elekta.dat @@ -0,0 +1,70 @@ +# +# MEG coil definition file for Maxwell Filtering +# +# These coil definitions make use of integration points according to the last +# formula in section 25.4.62 in the "Handbook of Mathematical Functions: +# With Formulas, Graphs, and Mathematical Tables" edited by Abramowitz and Stegun. +# +# These coil definitions were used by Samu Taulu in the Spherical Space +# Separation work, which was subsequently used by Elekta in Maxfilter. The only +# difference is that the local z-coordinate was set to zero in Taulu's original +# formulation. Source of small z-coordinate offset (0.0003m) is due to manufacturing bug. +# +# Issues left to be sorted out. +# 1) Discrepancy between gradiometer base size. 16.69 in Elekta, 16.80 in MNE +# +# "" +# +# struct class id accuracy num_points size baseline description +# format '%d %d %d %d %e %e %s' +# +# +# +# struct w x y z nx ny nz +# format '%f %e %e %e %e %e %e' +# +# .... +# +# +# +# 1 magnetometer +# 2 axial gradiometer +# 3 planar gradiometer +# 4 axial second-order gradiometer +# +# 0 point approximation +# 1 normal +# 2 accurate +# +# +1 2000 2 1 0.000e+00 0.000e+00 "Point magnetometer, z-normal" + 1.0000000000e+00 0.0000000000e+00 0.0000000000e+00 0.0000000000e+00 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +3 3012 2 8 2.639e-02 1.669e-02 "Vectorview planar gradiometer T1 size = 26.39 mm base = 16.69 mm" +1.4979029359e+01 1.0800000000e-02 6.7100000000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.4979029359e+01 5.8900000000e-03 6.7100000000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.4979029359e+01 5.8900000000e-03 -6.7100000000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.4979029359e+01 1.0800000000e-02 -6.7100000000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +-1.4979029359e+01 -1.0800000000e-02 6.7100000000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +-1.4979029359e+01 -5.8900000000e-03 6.7100000000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +-1.4979029359e+01 -5.8900000000e-03 -6.7100000000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +-1.4979029359e+01 -1.0800000000e-02 -6.7100000000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1 3022 2 9 2.580e-02 0.000e+00 "Vectorview magnetometer T1 size = 25.80 mm" +7.7160493800e-02 -9.9922970000e-03 9.9922970000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.2345679010e-01 0.0000000000e+00 9.9922970000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +7.7160493800e-02 9.9922970000e-03 9.9922970000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.2345679010e-01 -9.9922970000e-03 0.0000000000e+00 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.9753086420e-01 0.0000000000e+00 0.0000000000e+00 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.2345679010e-01 9.9922970000e-03 0.0000000000e+00 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +7.7160493800e-02 -9.9922970000e-03 -9.9922970000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.2345679010e-01 0.0000000000e+00 -9.9922970000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +7.7160493800e-02 9.9922970000e-03 -9.9922970000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1 3024 2 9 2.100e-02 0.000e+00 "Vectorview magnetometer T3 size = 21.00 mm" +7.7160493800e-02 -8.1332650000e-03 8.1332650000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.2345679010e-01 0.0000000000e+00 8.1332650000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +7.7160493800e-02 8.1332650000e-03 8.1332650000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.2345679010e-01 -8.1332650000e-03 0.0000000000e+00 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.9753086420e-01 0.0000000000e+00 0.0000000000e+00 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.2345679010e-01 8.1332650000e-03 0.0000000000e+00 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +7.7160493800e-02 -8.1332650000e-03 -8.1332650000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +1.2345679010e-01 0.0000000000e+00 -8.1332650000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 +7.7160493800e-02 8.1332650000e-03 -8.1332650000e-03 3.0000000000e-04 0.0000000000e+00 0.0000000000e+00 1.0000000000e+00 diff --git a/mne-python/source/mne/data/eegbci_checksums.txt b/mne-python/source/mne/data/eegbci_checksums.txt new file mode 100644 index 0000000000000000000000000000000000000000..1702429e6e7328aa1430170a5f785f00d2d11bef --- /dev/null +++ b/mne-python/source/mne/data/eegbci_checksums.txt @@ -0,0 +1,3058 @@ +S008/S008R06.edf.event 149997f77af08c9d6ad150aad5198f91c6c964c07e4d639baa770eac01012cfc +S008/S008R05.edf.event 51f07832e9b1d3d8c667f73dde4aa38f9d3e45cf2a4c2baf8e47ea328c860420 +S008/S008R02.edf dcd82e2a2477c52ca4a3dc784d9c04a55f935f2ed9ff10cfe0ec880d56c60edc +S008/S008R09.edf.event 0db4656c1041f6626ac6fd54117fb1e02890492bb86525e197e9ed116a0fe6c7 +S008/S008R03.edf ab3ea90d829e1e2e10bb6e551e828e66ac6262ec7bc24e2e17db6e1e350088fe +S008/S008R08.edf.event 918e61da68f21c26600383b29f33fec7665f2f3fae232e8413bc9266cc617863 +S008/S008R13.edf.event e1ad9bc40c1368a9f08ea6dd90c3750fa2947ff48bcebe59b7e89441a2db68b8 +S008/S008R03.edf.event 8d9c5bb3c83f5f447b4f8159b1454d55332838299c0e4a8e2dc62f413b08cea6 +S008/S008R05.edf 4a1005e7d877efe17e6ab6849665304f21aae138ef72759e5e2e0b96e444e447 +S008/S008R07.edf 9e05bf83ad067538667ab853081165b854b3d13ee334c4185ee5f40aa6b76a7e +S008/S008R12.edf ddced4ba4dc801313554039823fa1826d0dd52648f87a5ee5ada8e9cdd0678c8 +S008/S008R07.edf.event 017d78426c2e9f2b1807cc35ed07405ab8ff157014df0701b8524f965539b319 +S008/S008R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S008/S008R14.edf 19c943fb32f7749b7e37d8765f84a3bbf76c4ac7ea48ff29fa074322ebcad885 +S008/S008R12.edf.event 82c4504914809d88b1ce13e11caa12c3a659e1a2edfab31c2e894283b14daba8 +S008/S008R09.edf a13ed84381df5a71e3e0049a8cdc33f8f04f5f4e3f3af8881ade8b5c57064713 +S008/S008R11.edf.event 0bddeca4a8cd621dca3130a2d5affe793bfed62c379600613bb61a6e554ec750 +S008/S008R01.edf 678e47541d9903c300ba7811554ad1f8bfbe2bff086407cb4ff489d2d0e507bc +S008/S008R14.edf.event e9aa79af3e48ec970083b6f911002eac68ffb799057d4805cd5fde8f16d76b97 +S008/S008R08.edf 534c25b65a4fa68afe29a5c0272a686ac474e638c86521b177660d888401f374 +S008/S008R10.edf 6a7934c18466078caf899f724cf13b665d98e41fac9d978d9521f89021e0377c +S008/S008R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S008/S008R11.edf ef072b260a1d92c45d5d43a2a38c2affc8db37bc2da3df2d0962c44cdc449131 +S008/S008R04.edf 034a26131e1425e6374a459e5887b1f831f7bfdb101a3658d2cd07620cf2c06b +S008/S008R13.edf 9707099fbc3c9bb8cd9655c9ac491b5c6eb0383ea2a17972602f0e5c68ee6741 +S008/S008R10.edf.event f338197f5dd0ca078ea8eee22145e57e694f7dce6a2bbd55f5f05346ce3b3f17 +S008/S008R04.edf.event dea45ba8a8662cd82aeb9d6c523756ce7079f3020c2ad1b23d6dca2f63b5bf82 +S008/S008R06.edf c2afadf0b5cbc8764825fbe26ae358df677c46ce44c6e8622e4fa3d47d6abb14 +S024/S024R06.edf f4553ab40c7b8334a61f1f880d9cad635af87210fb59de6ab5b84ec79af0c296 +S024/S024R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S024/S024R11.edf.event 6e13e4f708f4b769dde500a1db747206aa87951c3914cdd436fb7f07e9aa5052 +S024/S024R12.edf f6287534159e552ed194cd1e3d44719e5ac162691779fd1a6fa3ae535cc036df +S024/S024R14.edf 774fb0c7d2bd28ab25364a1761d042725081a1ccb77f7dbd80d6b32be18252bd +S024/S024R09.edf 660928b6113112c7aaca4e2ed77188fcb66a12b75577f670202eb070b6fb351c +S024/S024R13.edf bf02f4f15115f6cb760f5f0f37437b930e648a85a43840b0382a83c6aa0e7144 +S024/S024R13.edf.event 472673d75763793097b36d5b0883addc030cb3790ee84a18c36eb33ef80d009b +S024/S024R11.edf 9ff78f7743d2b47590d5ae93f97d1afc5d266d41d086f6706cdc87ec32de31d4 +S024/S024R03.edf add2fbc9ed9bac885c6c192f7dc4cbfee1872da48da7423e2b06955bb200e0da +S024/S024R04.edf.event 3e83abe294ec7b278fb4495c4fbc171e9413e9d805ad8464dc6ea5a4875e7625 +S024/S024R01.edf abd9b141d8e2853e30a126a891929bf99f22661e27f571f02d5f6a415b40841a +S024/S024R07.edf.event 6ca290c8f2ab5d2a3d0c42a123bd24341d790899e901dc5991dd66614dfb1842 +S024/S024R05.edf f0de0cc7eb55154e2378911413c3a2ce353a2b4e68a9d298b2778ac4c0c7e587 +S024/S024R03.edf.event 3e83abe294ec7b278fb4495c4fbc171e9413e9d805ad8464dc6ea5a4875e7625 +S024/S024R08.edf 863899a80ad93a9ed8871be3bb775f8e74bf777dbf7a2c3da50e1433ceb3b50c +S024/S024R04.edf fe32b65b90079a307b05c42602aa66b3c79e09726ce9457e1d95242b102c6ba1 +S024/S024R02.edf 23634177bf16de6e243a1c7f0902043ccef5befca66b0504950cd45e08cc6e6f +S024/S024R12.edf.event 732398d864936092994f6aa5c7a3d554d1c1c35ff4fd7a90dd0c06a61260c68b +S024/S024R06.edf.event 04192a55fa7728d34533e76a1b831fe5c94d79c3bc9f1028f45644c51892a744 +S024/S024R10.edf ef34765f73a46e40ee2c59acc9a15d308765da781da11ce01197ee6e21f41c0f +S024/S024R09.edf.event dea45ba8a8662cd82aeb9d6c523756ce7079f3020c2ad1b23d6dca2f63b5bf82 +S024/S024R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S024/S024R07.edf cbf04619f8a980286067dd7fb943a3c5f1bce9928e27fdf3910ac1715d50f420 +S024/S024R05.edf.event a8ce17ff32c2c3aa820817e047ec3ff9976bd33355d14877f0ff811df5a288a1 +S024/S024R14.edf.event ecb3c28bfbaf7c670aa5547fa414949828cb36fcb3d84e0389aa669e01381627 +S024/S024R08.edf.event b9568e8466c8f90e1fe1f9aab8ddb73ea16c008b7b67cbbe5863f04f2ec408f0 +S024/S024R10.edf.event 9b116dac2d8fff59f5bf4cc8d45636716575c73d6e6b2287709cbfdf0ce5f55e +S076/S076R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S076/S076R09.edf.event 0acfeb483b2cb94304c9eb67c0f7c62d40e5219d810874aa1100d47751846b50 +S076/S076R13.edf 5a1a2283844cf3b493f92ffcbe31f2f3f74f09ecef18181edf644d10bcabd041 +S076/S076R06.edf 77739b23f5c793eddec3f39523c08c0dd1794cbee1886bfe34fc32c94700f557 +S076/S076R09.edf 074de623e475352ea6278d66895b15699bbd7213b561f7ec23791ab3a86e3629 +S076/S076R13.edf.event 26ab1ab393fc9047a9dcc0795bfb1c27444f58002c53a85545ba90395b1b54a2 +S076/S076R10.edf 64735a5159983af2f17f6405284ce59abb176211178e9ffa6bf2142bebd1055a +S076/S076R05.edf.event da9621a04c94f97b7529e748da5c8ea934cf17ff04b8b25167bbefb402b05574 +S076/S076R05.edf 9ad75a6b4e666c5f1db7afadf553b3d6f7f0eb46cbfe9980ef83f2ca4c351bca +S076/S076R03.edf.event 816b9e94c71aa492a890b3ee1209e4e3978a2bc1a055bb8d5b29d2aa438e7519 +S076/S076R07.edf.event 25f3656128a87915adc8cadfaac6dcf8a8c1c6f327617318054f010301d6b6c6 +S076/S076R08.edf.event df69a0d4526ab4c42f8d35b328874aafaeda087bb95ee7310d4f3654498f5746 +S076/S076R02.edf 092bbc018ef8bbfe21ff2ebf10e9587c00a1836a922c391e632b829e38aef05a +S076/S076R14.edf.event 246045b94ade6decbe7fab2d5ffd7ca93aada9d955f2d3ad771d86993cebd407 +S076/S076R10.edf.event f902df8b382a804cc4355668d708d0c1fc4103aa929df7db535c913a6352a463 +S076/S076R08.edf b7177ac5c852f96bc54093baafb7fcf0036cabd1263b8dfc2ab594105df3ead8 +S076/S076R11.edf.event 3cb2bc9973bfc45d63eacff0d4dbc31c925dfbadc12a78a18ff82731d7cdf19e +S076/S076R01.edf 86659701591d9e676b453556fd006a7501530d9f328050f2860060150b9ee75b +S076/S076R04.edf 48efdb5438f403e40a95262b12bcfe0147d581610c57ae33ed71c639068a04e8 +S076/S076R11.edf 2a5e9b3db7c0a2d6e030a25131a20e62bb5c4995cf9c001baf605fd0b7f8f254 +S076/S076R12.edf.event 879d902507387beb62ba2852ca4d85abb3e0bf9ee2913b3a553338a93590fe26 +S076/S076R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S076/S076R04.edf.event 994f60d74757d686b44b6a76e2d8e5946d5c8bec058f00a2264bae2e66ef7f62 +S076/S076R12.edf 6e9353b6b73166048fe7477a7f76b25a768d56bb0490188f5c8186506e96c47a +S076/S076R07.edf f45b4bb5193806594236d25ce2e6d3664d560aba813b92259e688f791a8d3552 +S076/S076R03.edf 413e4c44629550309789e4d0bcb33b6c5d9018731b497fc5189634e077636860 +S076/S076R14.edf 51114d952fde1e67627aa2abe33ffbdaf29653097cdc81c559f16d08226c0aad +S076/S076R06.edf.event 4e2eb91af71f5afce0e8a62b4a4ca68badcc99f5cad95fefc14d81d3b8b942ba +S102/S102R09.edf 507e52473e0378f094eb7622edb4ebc669772dcaf28961055790d17adfe64ea2 +S102/S102R01.edf 8eb9f4a85bd7854b545d00504f59d00ae4ba301011bcf3b562fb8d09ecb37d1d +S102/S102R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S102/S102R04.edf a66ad16f27f36c7fd126e15d47eae464e52c906eb5777c9188f392d0db97169e +S102/S102R07.edf.event 67b710bfbdaea5c65257f5bee9fa64cd171dd8b9c8a41d1686b0a14b0d997c51 +S102/S102R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S102/S102R09.edf.event 2d2b8dff802b702fe4eb03f1ac14632c8e7ac45acf9ff5566d798e576f1458d7 +S102/S102R06.edf 2275d9b0af1689c652d0846747eef993479998941fe7dbd3fc1206e39922b67d +S102/S102R04.edf.event 9fd975ed76b006ff20105ebf0fd1ae6dd127f008e06a75cad4484483eaad568d +S102/S102R05.edf.event f89b8b851132f6a167fb816989ff4c56e00ee3cea0b5a0531d0b31636ad86634 +S102/S102R12.edf bdfca4e013a18c8f43c424fd3acf604c231b1405e12c86dc7dd902b427d235a0 +S102/S102R07.edf f25c51950d872a5bfd169cb79263fda5e7c49d4c14d9cdfede7698b242099bde +S102/S102R10.edf 0dd5cabe19f4a7be3e907a69b752c41d459da617fe1b4110ed4bf8400a912666 +S102/S102R11.edf 8debe5134c1bec5e986ce2c025cd133bf1de8486837c363910b79349ebd6e889 +S102/S102R02.edf dedc3e5421cfd02d5505738c92bfe77ad7afc5478cc5c63f1ee07598a66af255 +S102/S102R14.edf 9c983d89d2df07f4477a73b17c5226166f859498f1f859fa64ca92ea3b144427 +S102/S102R14.edf.event 28f75c7ca5b9a2497e2ac9802a60d98795fd30929d3a9999fdab4252b01f28a3 +S102/S102R11.edf.event 82111548c0e7fdffe9a81852fe0ca1917a0898ce34e4d5af5bec8826a50ae766 +S102/S102R08.edf.event 94aaf9017009cf1af17ca3bf9b16aa30c750bd60048f18af249b106afdde2c63 +S102/S102R03.edf f4e0d946b27185e80ed8326d2b0985a72e8c1b25aba86496ba3c91797fd8a6b3 +S102/S102R10.edf.event 761750058b75b97c1177655c9399a4de55d2f053dd7397c6d95c96c7718ded98 +S102/S102R12.edf.event 8eec54f234ee4835606a193713d02283c66ac6177147ea2d90c6cb07814fb12f +S102/S102R13.edf.event d107d48c57429e3818a39fec732023db2d15060d55e82d27b578baa3875b6025 +S102/S102R05.edf 7d0b0c5d517978af5f1ff0386f14eb81af3f9d3402986bbb02e7afd47a7c98b6 +S102/S102R08.edf 6155ab874f65352641325fa1a308cca891820821572a28cae81a87740a046883 +S102/S102R06.edf.event 2de1f3543fab2d52b1e97e2b52f84bee5719ac28f3e613357cc69f70ce2f1e7b +S102/S102R03.edf.event 6c457793161b0b2dafe7d78bf4d750a570530145b98ce0bb007627422152b0f2 +S102/S102R13.edf 9ba36fa3b8377e35c9e666cfa48715e3f2b07513739f7dbb841c45d541673cef +S105/S105R14.edf cd55636e49e04b863df13ab0aa09bc5294eef100f8bc055cbc528f316c415aa6 +S105/S105R10.edf.event 353c44c45eb89b709590af77f11106666cfa3680e5470b61c607b80304933399 +S105/S105R03.edf b04097ea13899d9139a25b8a109d83b78f45aebdd7145610d1abb74ab1302f4a +S105/S105R11.edf.event d9d89addd8fca4d057ce27c16b349184b9dc3b13193561b7c99ffa9414e86138 +S105/S105R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S105/S105R06.edf.event 61280c9a206447732db06a6480d23654d272250513af280790c631d46fd6de1f +S105/S105R08.edf.event 537ad705e53a339bd1d130f3331df882a0416fb7e95c4f565d283142dcd120f4 +S105/S105R04.edf.event 25af506ba70b68343c97ccca1ad0f235958a8dc9bfdd84c6f7155937e7bc7efa +S105/S105R14.edf.event 3fef219961dd488cd267ad63abdc2bd5db054783d67c836968d1266e4a9f8560 +S105/S105R11.edf 1275ff3237fa4bfc006b5e296d6a77a2d65c9b1045451b1485f2837d5ba189d3 +S105/S105R10.edf 3367bdaef3d66d056ec64c553ecb2fecf7fb19677b0d310e4fa6c7501052b7c5 +S105/S105R05.edf.event fb7055ba8adb05cadd3009cfa9adefacc5298e01d2b7156815f6424ce1d4f3f6 +S105/S105R07.edf.event 26fabc186c9b04bd70469a5964b2648cb7a2115fb0a397d51de147fc640d8d83 +S105/S105R02.edf 8816d8070f58a9ddee89d1d6f9923c9df3d73707a0a204953a128b6c357d237c +S105/S105R09.edf.event 9787b103ae02f348ebe837cf8e545e3e630609a320868cfa229f0f82a0734ddd +S105/S105R09.edf f3b966181f93016d52127e1bcc049bf5c4e866bc0540fc7697f369618f78741a +S105/S105R01.edf 712c423a028c67f2fa328bb427cf140fbbeca2fee90bec6c17fb54ed01ffec85 +S105/S105R04.edf 218e3e8ba2bc171a3c6dd5891e6cd604c8fec4f32fe2d4c274732ef880264180 +S105/S105R03.edf.event 0ff4d5f572885db930cfd469a0c25535d26e1712145e5a489a5e31e8a2020961 +S105/S105R13.edf.event e4c9fdcbbe3469b81dd48d30396ee921a23d45fb900a0dd3b7eb4ceaf04936a6 +S105/S105R12.edf.event bf636aa7d9551082dd6cb4265143a22c283dfa2e23b0fee221d83a0b0a57742c +S105/S105R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S105/S105R13.edf 0942c77de3e2167d8f6d2ef7cc5b62fbfc9248ea92985c0c484726a0b893bb51 +S105/S105R07.edf dd475e1a162d6665cca22cfe293d45874b84a017007ca845300fb205ace24424 +S105/S105R05.edf a50dfac654a6f0e0d730cd2475e086f78122aac22d288792c44756e646ccfed1 +S105/S105R12.edf 926fe3afca0077495884cbd67a09761d0a7cbb956c37dc7c140165798b510891 +S105/S105R06.edf f80b5f1ae34d833fc370e17a8e369609240a43f2dcad050eed9b393a32cc4475 +S105/S105R08.edf 52bca66d6e03db2c45e6cf560f54d13abe113ad3fca5396ac4c6fda7796e36c1 +S090/S090R11.edf.event 9e1cfe676de301ff52ef7ef70ad2cdd8b8c9562c01e98d8eae191a5c8c28aa46 +S090/S090R04.edf.event e3fab15583152a967f41c771dfbae2769f9b7aa683947093588c32e8521f7150 +S090/S090R07.edf 4dcb675b5b73c8d79b7e780e310ef91e5060c5965b6aa7e0bdeeed00862e2621 +S090/S090R08.edf.event 4c374f58a91c1ff71894cacb50bfb798d20cbef67ee65a1ce8a2d5826349e390 +S090/S090R05.edf 0f8919f65642a8abae2baa57f5c4550ebfc3c5320eb97d1c9da11b4fe082a926 +S090/S090R06.edf.event 296bafcd473fd6051b9cf19b1af83d7f0a4ba4eb310f7fbf462aa7ac3ebb8120 +S090/S090R12.edf.event 8a4b5822b251050d46b816bf54fbb47530d91210b6d01cc2e6acbe662193553d +S090/S090R10.edf 53184bb4b5b4785bb80819ee6779f6684b5b17b7bdc0be4bfa1113c2c723adb1 +S090/S090R09.edf.event 9aaec3ff6fcd8c6d47bbf0c154dac87cdccac4bfb099e5995ee69afc7b34257b +S090/S090R04.edf 693e109389bc37367ab66ff558171a2fdbcf74bdcace569303e7da8c0f9f8a58 +S090/S090R03.edf aa2696005ede093289712cbff6c1d9ca7fb72c3f127e8e29593b87c160a2c277 +S090/S090R07.edf.event 132c4ce227ebb4e694982a37f3f7e9289511d75fdc0079dc876ccb6d9cf1a81d +S090/S090R01.edf ef8e84de758cebfad15ee86d49bd134578ac5ff24154ece98e9e853c91356e34 +S090/S090R12.edf 8cc1a80be7f14683b645e7443854c6cd938e31049be92344adc58a9e4c586554 +S090/S090R14.edf.event b9997b11f88beac0859d8b671d263d82a6687a271c7dccc0c874b0cb51d57af4 +S090/S090R14.edf 2b900c0724f97e41416ffabc40ff8de4bc2e3333f808169bd2e5c9b4be5c9f76 +S090/S090R05.edf.event 5bb35bd49434a9630e941b5646d6d89f7907531ef3e44464334b78943d4b0237 +S090/S090R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S090/S090R06.edf 07c41b448f75aa807e63018fe370a017e00f6d82b8d23be59ed8969e4091492a +S090/S090R13.edf.event c2f5111be300abf5d209c1908e46d378a7a94c2f8043fe6acf88665aab8efb02 +S090/S090R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S090/S090R03.edf.event a6b508d78111c06b1a185c7a70db08a6126b40c12b7f09d110a17945d19cfdbf +S090/S090R09.edf 6c3614bce81b0e38d7b41c9bb18c77899f1d71be7fa8d135c1f81b210b71d950 +S090/S090R08.edf 9585057959bbaae8a4b6ef81546a88a3ae1d6e95bbc7dfb1dd6a846d46af0637 +S090/S090R10.edf.event 48bfdaa247bad1b393cff54386a6d30257090bf0e7327f31b2b320921da53270 +S090/S090R11.edf d2bf6493d1968c5e0ad3c90f0a5b807b87e321ba5e516d2184db3c18a54443bb +S090/S090R13.edf 4aab298b8aeb892039c948102e8dec14d8824c876dd27332d147f2da11e64a97 +S090/S090R02.edf 19877620e881df6cf52aa25b6383dd55d9097e4425b16b9451f99d68a67c51f7 +S039/S039R03.edf 966a6c64ac3e79dcd455917fdb1b298b812bd8164b77089f560ab6fe0a93d941 +S039/S039R10.edf 4e1fe26c20c3990f2a197c6f4090613de90eab0699c4606daa9bfca9eaefdd77 +S039/S039R08.edf 4f5f011e61932f4f5998692bd6324c70b2286191dca137e340afbd4f9b7b93ae +S039/S039R11.edf 46dc22efd58d1179f521a3827b62d5ab4081fc333bb65025e940aeccf34e684a +S039/S039R12.edf 19078a959cce7c535e92c6fdc557dbd01c162549784a409af79929d9c4f20e16 +S039/S039R11.edf.event 1f21e6a28cc1b59fdc3667207c5b1029902f6d0018bb978cecbb5905b868cb10 +S039/S039R14.edf.event 0d4308120129d0f92d2b8779374ae232f98d1357e6c6427983fed655d9611af0 +S039/S039R09.edf 1d86d0dd505aa15e6e819feb0d9a36f43f783f25861514aaf703b8f93ed774b1 +S039/S039R09.edf.event e1b29e90b20be6fe74d2526e8f695d3e9dfe8bdd7f08c801c24f523ac253462a +S039/S039R05.edf.event 01b8244e62aea11c106c000350e5b2ebec864736b68aa1525ea371fb86a3b0b2 +S039/S039R05.edf 127aa579b8333abc584461ad7efba5ba8b8b9da701fe111677a812dc5d73d622 +S039/S039R03.edf.event b7ad55e8ce55c5743b2d7e417e77c8d7efdeba7b6cbbddb02fe11361879eb9a4 +S039/S039R02.edf e54936d509c572066383ae4250e28f41e9990bad464c26eaa10e248667464483 +S039/S039R04.edf 57302f5f9cd1714693e52b7785a839666da1560ee88b00779fe7f18f56899324 +S039/S039R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S039/S039R10.edf.event a50926e15d8027e4167d22e5479fe3751780003aa245b90b2eecb0b4f474fde2 +S039/S039R13.edf 9bef82ea3f69eff3f3c9f47779593a278a10c9ea379b35d5741b063a4a22c66f +S039/S039R12.edf.event 61878a566785fc86672b3e061fc0eefd0fb9735a4239d8f13ceb0d08ff22f60d +S039/S039R08.edf.event aaa5cf263ed5e1e7bf38b3d540f4e2d286107c553f7904af5c9cee9bfe715f19 +S039/S039R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S039/S039R14.edf 29a2f92b3a9ddad0d55ff5440eea81b69fcf6b21e62e33c3dbfdb42fc1398190 +S039/S039R04.edf.event 09d9d4cbfb435c34d0498269502687afe1e41cb410faf772b5fd4389e435ad7d +S039/S039R06.edf.event 8fb228960cd397f6100e75cca49e1045159bf62e6184dd5267ea608be1d540b6 +S039/S039R07.edf c0c5867355e92bfcd0da79ac30584aa8a97558aaa9900af35f43f5acdbc82378 +S039/S039R06.edf 8512ad15c7d2f497fd1d48753b10f81d6dfde4a1c27434499cf1f50e4e066b32 +S039/S039R01.edf b1c5ca3e506c3dc0d7dc855f3908b5d4ac3b1839e9fac8e7dd316eaaa50f953e +S039/S039R13.edf.event 25af506ba70b68343c97ccca1ad0f235958a8dc9bfdd84c6f7155937e7bc7efa +S039/S039R07.edf.event e1b29e90b20be6fe74d2526e8f695d3e9dfe8bdd7f08c801c24f523ac253462a +S098/S098R12.edf 7523f3be8c00b0ffaf151c4e5f4b3407a88d499b65aeb8b37e6c37bdbed5bb01 +S098/S098R14.edf.event 9b116dac2d8fff59f5bf4cc8d45636716575c73d6e6b2287709cbfdf0ce5f55e +S098/S098R06.edf d07ce4a4f2d6eab3e8f0b3b45285302c9551a6562cb31a247f160d5d702e6b73 +S098/S098R13.edf.event e129d841c2e51546d5ad32cb6c2a8303e4c0bfcd90dc9e3e821c0c40a9a049bc +S098/S098R07.edf 9e6287b11b514ababb4185c98955086fbc53547c2758e2876e23c63bbd7ff766 +S098/S098R09.edf.event 96cef3a9a9e2cd7f438d53008e256b198c48c6e0d2f0b2d70e0d296180cd58b0 +S098/S098R12.edf.event cdf1a70ff91abbdc6f14a7ca794a7b5932276819e6f7c68ee344c3d21e9b73f0 +S098/S098R10.edf e7f29d50b356234f59f36e3f2e239864e40696bafa7f856f295900064ed8519a +S098/S098R07.edf.event b0c7884218a114ab4fc2b8cb09b2c8f1bd0ddbaf69aac65191618c0a230f65d3 +S098/S098R04.edf 9bae31bf3add196cc4588f279b3a372112331b5b385eec4490f09a23c29a9468 +S098/S098R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S098/S098R05.edf.event 1cecdedf3d7f8b7931b4cd84b48bcd356337c0ee32518d737ce0ee8f0d428d8f +S098/S098R05.edf 0e27c55698a030660f39462f0f948da1b1637b4381c3babb432b3963483b8044 +S098/S098R13.edf 95d6338578f27881bf3cc14b09ee3137a5e5be8e7ce598e5c7f562bc1715d93c +S098/S098R08.edf.event efa5d828429e8df393cf3e5b452a00dc9f05f3ad9eeeeb119ad18eafd1cc4e2a +S098/S098R11.edf 55c06e652ae9e6862e19c9e6e0709add991fda1d314df27982d3dfc13ea93a72 +S098/S098R09.edf d0c14bf014bb521244332d7044a8e01763266175d676323a82a92a0164632430 +S098/S098R01.edf e908b862df484c6ffa822ccbb5658894cd3459fadd6c9d02b26e30bb9c392552 +S098/S098R08.edf e357cf8d5236aa3b63e212bccd663e8f07d8b98952d3ae301eca861a63736c19 +S098/S098R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S098/S098R06.edf.event e8abea1fb06a5ad73e91ea5c97aa84247e1c165ee2bc724e9b9c7ae6f6c017cc +S098/S098R02.edf 2d710c6eac0d9bf911512a5cd3ef10f168592af7b2d4f76aa7378c77a9b83bb5 +S098/S098R14.edf cd8fe3074a59818a00e8749cd0a3b9ada624955b56acf7cc81bc20824a7370bd +S098/S098R03.edf 5f37a275e82a5911f1f467fee237bd97dac7496277db7025864bbeb0e8e52b80 +S098/S098R10.edf.event b1046f2c937e8d05f2c3e45473ca880864a5d33222d740a0bee41b055662ea91 +S098/S098R03.edf.event c4fe35467d7d0b21a1a13fdeae18b7f036dce640d9e06acb7a946289a7fd4f44 +S098/S098R04.edf.event 4e057b134c286502a0bd4e491daa0ebb3c4bfdc21b738b2ba2453c8ffc558218 +S098/S098R11.edf.event a6c871f2eb69757aec91f71c7de20007524b3b628f251799a3dd57bbb181fd84 +S020/S020R05.edf b78e35ca2354a77d8d44af4b50205f09bbf866d8f295d5047cca111f60eae213 +S020/S020R14.edf.event bd6dfaccdd7deb73743f500e0a1fa9d0ff333e94d59c6d153e2e9d2dc8a4795f +S020/S020R09.edf.event 26fabc186c9b04bd70469a5964b2648cb7a2115fb0a397d51de147fc640d8d83 +S020/S020R08.edf 05314b692cd4c103071ed616e36f7dec96116f2b5251e0912a35d65782ae9205 +S020/S020R12.edf 63ef2b1452fe4a93a84c501f10fc35a234d87eece20f0b563b373229b9b8ae7d +S020/S020R11.edf.event a5608231854f8f457c107c9acdfead912cd6d55fc459b7abc2f11d77bb166129 +S020/S020R06.edf 6e127745b2b1031bb274f72063b954a79b584163e17c964aa8e859c878498145 +S020/S020R04.edf 3ff2fd30d246987573897d429b8a6c51cca3f1ea4cfcf8815c49e1f6f6512013 +S020/S020R12.edf.event 611df9f780acf887245656c2987fb77e486d2bc016936d00eea0a55d2f5c3028 +S020/S020R02.edf 0fce787b1715bb3799b110bbdf72198fbb5d46af9b25d1c0f55014f245afdfb7 +S020/S020R14.edf 1d9a26f8c38886fa4d700deb86100e56df958b2507875f45adbac7c98de15ed8 +S020/S020R10.edf.event e2b79b09413cc4065a25ea2956bc7726f4bdedc8730e89a7b86a8617c79876c8 +S020/S020R10.edf aef44481a6fe1a8e732450ef594b3167bca2fbd01bb23a29d7ec79a670f0a658 +S020/S020R09.edf 92c11a238de78b5f58402760ca9e157391ca8501705dfd4a4a172fd7e2a7bf05 +S020/S020R13.edf 8fe70e65b1e8f3a61b748d12a01a3d3844071b32bc591a8996b9a4fe1d824b66 +S020/S020R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S020/S020R05.edf.event feeb9bf47f8f6dd0e083c64236055fd7ca30a06709747978b6a7bbc0b632e21c +S020/S020R07.edf 7e1038d12397731e36039b6ba26504383d9f700d4b2e0252421d072d41cb3ce3 +S020/S020R13.edf.event a5608231854f8f457c107c9acdfead912cd6d55fc459b7abc2f11d77bb166129 +S020/S020R03.edf.event 6ad812d50b44ed49ee87e09d1cf28b68a99855b6d266be8b9017d8056de057b4 +S020/S020R07.edf.event 151aa0e52269f6759e2bed18339cad06a9761f4b713071e665a50681af66afc2 +S020/S020R04.edf.event e2b79b09413cc4065a25ea2956bc7726f4bdedc8730e89a7b86a8617c79876c8 +S020/S020R06.edf.event e7ef0a3d66a5c814c6e917ac8f9bf83d6056810f78dd0c9296b5445289483fa5 +S020/S020R08.edf.event 146180adc42ba38b30989a7a30f8dc33c397aeed2db797d266b9ddc607fbddec +S020/S020R11.edf 80014e2cfda81a19647e9f2a16f66082693a591b78a57aee5d220b3ef2a0241f +S020/S020R03.edf 4660edd9962577ceac6e35db1a5c0756fbdfa954a77f479dc8aa3e3b3819f453 +S020/S020R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S020/S020R01.edf da48b7d4ed805218e12c70c775b47a3a111670901e06e7de843916c579278693 +S042/S042R14.edf.event 212052daaa4c0fbc66f91923236861d93fc52f73403f6b4d988205287f1f9ece +S042/S042R12.edf e327ec08604c1a835bd0082c79c2b4f44ec22c1e0b39d12ca7be6c80d1acc8d9 +S042/S042R10.edf a414c5017fa91f1f099174fa99bd13b3391b68fa1473cb0b6642debf264365f1 +S042/S042R13.edf.event a8ce17ff32c2c3aa820817e047ec3ff9976bd33355d14877f0ff811df5a288a1 +S042/S042R05.edf 423d7daa4453176ed054da2ac90d2951c45c48f4324a49cde4846160af810e52 +S042/S042R05.edf.event 09d9d4cbfb435c34d0498269502687afe1e41cb410faf772b5fd4389e435ad7d +S042/S042R11.edf.event 49dac749bf850e47e5d13a8edef5121c75a7baa7f50917a5c17c1dda52d3013e +S042/S042R09.edf 621acaf37bc58d96395bf0a6d8c242e2784768822aa8515251a3cfa149ca5fcd +S042/S042R03.edf 27158284aabae182fcc060a945e8070bf0e9a40bbe737f43a1c4baba5988d34c +S042/S042R11.edf b9eb76af792f6ea5992359b14ad57ece1d5ac3b3d233cc46ebfc6afd07bfd697 +S042/S042R06.edf.event aaa5cf263ed5e1e7bf38b3d540f4e2d286107c553f7904af5c9cee9bfe715f19 +S042/S042R08.edf b277ee780d7ed612958ca36ea7db2be9797001d5afcaf1dc20cf554dd774d18f +S042/S042R07.edf.event d0677488ead680ce24ed6d8a77105b8da3f0bd8cad38fff43732482c17bc4510 +S042/S042R06.edf d4bcaf4ed157911a326c61770386a2d9c95dd8e60d8b3d035efc8266dea1292b +S042/S042R03.edf.event 39c9864c57efec906759ab97dba0ab26a900fa25ad8fc3c48b0d97ea83c3a893 +S042/S042R08.edf.event e16d907d8f296edaf98d1ab54138ee16bae85a4bd81d90a487ccfece5b611fd7 +S042/S042R04.edf 278f745b79a507e87c4a4fe97542416b7723ee66e6960a459d43995486cf60bf +S042/S042R10.edf.event 11c7903b0dd963937962aeddd4ffb77feeec607958b581d996b712009c71f910 +S042/S042R02.edf 34bdf9da7d2a4845db721022179717d6ab5b9e7acb47e2c8f96be20a4c6fc30f +S042/S042R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S042/S042R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S042/S042R09.edf.event a40b48032f894d3401affa4d6ccfd4defb4c639cf235451c5fbe2296febae7a1 +S042/S042R07.edf bacd80ce7c09dd4442384e04babdb34259e79f708c2b093a613b4478f305c2e9 +S042/S042R13.edf 676232fb801e81ade568c6ea9c5e2f98f262283168c92358a0251c50c6fc0565 +S042/S042R14.edf c5292099a382f2a0279cfc29f3a86322e8b607f5329f2295524faa528b7f23fb +S042/S042R04.edf.event b0dc1155da666ef5240efa8026cec5f4f69b5fb6f1d21226a512de3f6b62002d +S042/S042R12.edf.event a716ed693834141bb2b56720ce6124df46e42e86652ec02bc96746644a79378e +S042/S042R01.edf 34f1adbcb0155953eb68874d9a23cc1a8d7ce57a507bc6ceea9189b410d38439 +S031/S031R11.edf 77ae7fd0a38e2bd23eaab19f8c612d144cece3d581fc0ce6740b9eec4e8dfc49 +S031/S031R06.edf ac5b92e882911bc3d4c5d1410a9baca5282536cbe1d183f6333b8fbf9ce8ab54 +S031/S031R10.edf.event 57636037048fc90c882a690b692342a1f4fd070d9f2a219d527ef6c0f7ea7dc1 +S031/S031R03.edf.event 985f9701733fcf2689c3a35bdb9e4b0058b6137ded5bc0f1a2a3b84431edb435 +S031/S031R06.edf.event 0bddeca4a8cd621dca3130a2d5affe793bfed62c379600613bb61a6e554ec750 +S031/S031R05.edf 92e138d4764bc8709af2170722b28d816655ff80287f418346b2886387f25a67 +S031/S031R10.edf 0967dba784038babf1459f8afb6a1b6ae57e51e591a8d84896d5c81736fd4a18 +S031/S031R07.edf ec5602c9eca8e29c1aa51f225504e97189589a18848d1ad968320dcdbf834daf +S031/S031R11.edf.event a931510ec25c8e6b0352576ca7f98b414a922451f0a6ee6aab03d3409a677c66 +S031/S031R14.edf bf60fcc7c476f9e7b0b23710f0c62edd6ed3364698db305fd76925f052c27f5a +S031/S031R01.edf 55d1e8e8145b8eb6778468b55020662275d152d34f33e18c2893b70605175fa3 +S031/S031R04.edf.event a376b452fa5f7c300d71ec31ce58f97920510a057f4ca6c506f4cef51faa7315 +S031/S031R13.edf.event 2da7955eedd5ec220793d3b4b3224c26256f1427c213729179eecd79fd4321c2 +S031/S031R05.edf.event 596ad948f8aa9dfdc6cd3125a3d02e115d1cd6a505023467bf5cd721125ee7fb +S031/S031R02.edf e1f18d1810f486b34075e9b2ba9f028e303b5f548c2477d1340ed4ce0f578bf6 +S031/S031R12.edf 6bfe914504368ce54822eac53598d9d53b251b39b17e9a7090dd64619fcee982 +S031/S031R14.edf.event 5b8eb2e2184e2816cb3f7104149139af83c25f381a47b42e81c9c6aa1723fb5a +S031/S031R07.edf.event a40b48032f894d3401affa4d6ccfd4defb4c639cf235451c5fbe2296febae7a1 +S031/S031R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S031/S031R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S031/S031R04.edf 514a2b800313549f00e927f8f322eac9a381b715b8728b835f0986fa4f7d5096 +S031/S031R08.edf b4cc77950c0f364cceb1ab55559a40c3ffe7a5b2fd5146a8ffa0243a35897e6a +S031/S031R08.edf.event 927b59b2e19d89df8169362057a329c5b70fd65d1d2d0a77e56546927bc02281 +S031/S031R09.edf 3217f543f6f1db0ef3b8e7b268e87e0e1dd69bfc7fdbd33e0ad8ba295341161e +S031/S031R03.edf f9d75722d2b3412a9b9da296dd28185d54f6b5471082f7952c2cfa51212f6845 +S031/S031R12.edf.event f1d83aaf535b3be7098ef9960def69c712f4dadb4f334e40434e155e9088b299 +S031/S031R09.edf.event 918e61da68f21c26600383b29f33fec7665f2f3fae232e8413bc9266cc617863 +S031/S031R13.edf f0fefd12e9a037ba9d46750508f834c99d1331f75024be889bf05c826e55b2c6 +RECORDS 02d1de9c00511d3b7548a6b59bdf209c819db025518ddcc52b21fd3b2b9de4a8 +S004/S004R05.edf 03d587f2b60f6fc1cb8105ea06219b560345e354f4e6623cb1840cea5d0e7138 +S004/S004R12.edf c44b7be0464d86be4d460ec66432869b7b3e8dcaa2067af02d6e772abf5c11de +S004/S004R10.edf 8f8034251a5bc4bf8dd8ecc1869da6ffd9e61bb9d9f8a4ae0df9003d72d40e9f +S004/S004R12.edf.event 6e9a969133a5a862400b62cb84f763eda38a0967078b1ebbfea1ca2ce8635b48 +S004/S004R14.edf.event cdf1a70ff91abbdc6f14a7ca794a7b5932276819e6f7c68ee344c3d21e9b73f0 +S004/S004R09.edf 2b5b61af7ebad040f57ab761e7b2bfb83bd7488801bfcf35805399c076b5e1d3 +S004/S004R10.edf.event 082acf669cebc89d5f5f4bf29769c743f3b1e14290b8f0f34415e285db553b3a +S004/S004R09.edf.event 9825c80a69d06961cbce2e12cf8d0aa56d063e5f4598312c4e5b78693a0219c1 +S004/S004R07.edf.event 83ec130ac6a664e0d88923e1496dc0806008967b51e6158521a6beb0515b2eb8 +S004/S004R05.edf.event a376b452fa5f7c300d71ec31ce58f97920510a057f4ca6c506f4cef51faa7315 +S004/S004R11.edf.event f45bf8e0fbc90d9616344960adaf0ce8357cfa7171b36030a957f85c93267870 +S004/S004R13.edf.event d0677488ead680ce24ed6d8a77105b8da3f0bd8cad38fff43732482c17bc4510 +S004/S004R06.edf 2d9afd10462b0dc93c07e605ce6dd49ddf42c856c843a18a8236cbf08c9af7fa +S004/S004R03.edf.event a716ed693834141bb2b56720ce6124df46e42e86652ec02bc96746644a79378e +S004/S004R07.edf eb00bf6a816a6ded6f93e0b96d2a1c2ae8f6d13a59e39d475bf94d57fb842643 +S004/S004R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S004/S004R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S004/S004R08.edf.event e2b79b09413cc4065a25ea2956bc7726f4bdedc8730e89a7b86a8617c79876c8 +S004/S004R14.edf 06a3c88276f1db76214f8b1068878add45b22836327fe6b95d0231d415cce752 +S004/S004R04.edf c9ddf0294961f0b877192a2479802b9c6c88403682a17b5ad679fd6485aa6f59 +S004/S004R04.edf.event e14dc31d476c11841d45564cac660be9776fccedd3dec71dcee4c5232f00f25c +S004/S004R02.edf 32134f3ce7056fd6487855552636b8f93ea2d67631ef1da6f6474eda6040162f +S004/S004R13.edf 136e362b79e95407025f6ff390631e301e75c996538435ca5e8fee80b4c08682 +S004/S004R06.edf.event 4e057b134c286502a0bd4e491daa0ebb3c4bfdc21b738b2ba2453c8ffc558218 +S004/S004R01.edf 23e9645f492488d2376ac3a606d177043efc6e5fb00281c2d6648e4b06a6ce62 +S004/S004R11.edf a8b96b32782329f12accdc222331545707be4cd497f97f158de4c06e87235f8c +S004/S004R08.edf 1ab5909b183413283a7ea76e35311a68a4688558f0044b9faab3987291cbdb92 +S004/S004R03.edf b24e3ae9d302935be06c0905d1e925ad68a94b4a5b20dc659cbc63bb8481d503 +S002/S002R11.edf 694bd9fbee1305dbc212ea4eecb8930750f5e08f8cc8ea45e2b94c92ac5f5a7d +S002/S002R14.edf 21e20c72ae3f52cc95f6fd6d4b5b958e28fc85bc0d3886f494de97a82c2aa24d +S002/S002R05.edf.event dea45ba8a8662cd82aeb9d6c523756ce7079f3020c2ad1b23d6dca2f63b5bf82 +S002/S002R07.edf.event 350042ca5c37cad9cabe8c469aead2bd074d996b13c69cafba8d24cd8fd825fb +S002/S002R05.edf 16ad84f17851599da5e199106b9b29086cc5793d78197a46b36efd49602b35e1 +S002/S002R11.edf.event efa5d828429e8df393cf3e5b452a00dc9f05f3ad9eeeeb119ad18eafd1cc4e2a +S002/S002R04.edf fcd37831378c411d50c223d97ffbc00949be2271d093f1d8e56bbe7c02bd1539 +S002/S002R09.edf.event f2f8656ee521f666124ee80cf26440ad4cb3e88315a64306e592a3424ebb8ee5 +S002/S002R06.edf.event 5e6dd7d9983b10c75f267d25fb4f039777b8f17f9d64869cb39446d1e9306505 +S002/S002R04.edf.event ecb3c28bfbaf7c670aa5547fa414949828cb36fcb3d84e0389aa669e01381627 +S002/S002R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S002/S002R13.edf 6c018440a9b52980fa40e4b9b9baeeaec7c94fc6d1c0b88c7fb32f1dae3a5a45 +S002/S002R03.edf.event e7ef0a3d66a5c814c6e917ac8f9bf83d6056810f78dd0c9296b5445289483fa5 +S002/S002R06.edf 08b07a8495a51ddca66a91fcc1275651f2d3e6b0a7a56711f06769b4ecbb8d53 +S002/S002R07.edf cdba64ad60574903248aed651d393c148df3c611eebdc9694717a04e2e2deef3 +S002/S002R13.edf.event 533737c87655572a20223c364be6c8be7a035cd8cf3dc42ed8c418e46e174661 +S002/S002R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S002/S002R12.edf a3d166b23375942a5ccf352924f7766f0ca9cfd1bac7951175e710d978f5239f +S002/S002R14.edf.event 5b005cafab5d6d8968aafc95da4c7b50e36cdf3bf2d71b98cd18431017101fcf +S002/S002R02.edf 666a9299341ece77522df050b1ddd128179a540548d82642ba975a65b4f6d84e +S002/S002R08.edf 02d64941f6bcd1635bc7dd187a9553331b73933e9771f4e7c59249dfc5632c5a +S002/S002R10.edf.event 8e9579e89d1ec6576609e05f5e6215b4322a4c5375265379e3acd7952866ac83 +S002/S002R03.edf cbabe29620b19978454bc429f59976f6ee8f32f6392e4fcdf7e463981248072c +S002/S002R12.edf.event e19fc47bcf5b585ab27ad756884c0c4cd37d239bb04c8bf15e2f33fe9fe05e18 +S002/S002R10.edf 817961f28a7acfebc45c664f1a9e40dcf4a8e1e1e51dc089062d7e3e2cef44e9 +S002/S002R01.edf d542689b31c977838f20b1a2062865b98ecf10a7e9702f56f101000d47f2ec68 +S002/S002R09.edf bc439584841a5b637596485e1979c89d872a90f2270a363a039a31587954ec4b +S002/S002R08.edf.event d45b05b6c6897898bdd688c12fad776011d39250bd1bd8de7e7745d939b60e3e +S093/S093R08.edf.event e129d841c2e51546d5ad32cb6c2a8303e4c0bfcd90dc9e3e821c0c40a9a049bc +S093/S093R13.edf e9e7a6f1676cce8250555d109df575bf434049a2be4919faff324defe427fb54 +S093/S093R06.edf fe0a178f7fcfcb2f60d9981e7d5c57caf1cffbac74b73e248b1f4ddcda8cd07f +S093/S093R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S093/S093R06.edf.event 98da35a4768842863f8f05d63e959a36f12126a205e0370d8519299fc06e56ec +S093/S093R09.edf.event 3593f38db6b9b0b72284e6ea58a9169bb2459a37f75643fd634363b665a636d9 +S093/S093R05.edf 08c4b631fb815382a0ca5a3b76309308d589317888cc78d9254113cc71b9806c +S093/S093R01.edf 2d1bca83825b37f2186af5dbdb0c4d7c48d0a971903761a84c385d7dfeb3f54c +S093/S093R05.edf.event 386c51194ef175e56c4d94b5e327133f39929095caa7c3ac86e89628f6fc0610 +S093/S093R02.edf 35ccae312fc9b7a87d3b485bd8cd0721c579d722a78e5e0802d2ba65f07a2e66 +S093/S093R07.edf.event 818acb17a86d3ee6425a512fab58b363d01b6ccc783417cdad466d1ecddc506f +S093/S093R11.edf d312b4f5b5faa38dbc90b0ce863a4dd8181f4a32fb535487fc049b2cc9a523a7 +S093/S093R10.edf 6f0f8189513bf06f9a0d7e694ad12b7efe948195f4b077a57706936b79dc6e6a +S093/S093R14.edf.event f2f8656ee521f666124ee80cf26440ad4cb3e88315a64306e592a3424ebb8ee5 +S093/S093R07.edf 1c493c8dc14e1e1e01c02e0cbe585d1798be82e1503dfdcfe7066db93387157f +S093/S093R12.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S093/S093R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S093/S093R03.edf 20c0e4a51b3eac6047fe26e1f3aef29b4f74caf5e335db090f682f1f7610afb4 +S093/S093R13.edf.event 2d33f0e6820d6c85c1b096ad02de0f117c60e1202edb58aad42f3ec835f3162b +S093/S093R04.edf.event 2d33f0e6820d6c85c1b096ad02de0f117c60e1202edb58aad42f3ec835f3162b +S093/S093R10.edf.event a376b452fa5f7c300d71ec31ce58f97920510a057f4ca6c506f4cef51faa7315 +S093/S093R14.edf d061f438e28cebbadad78943f0d70cefc79b82b20ffc8d9421239ed5cf912aa5 +S093/S093R09.edf 5cc82efff1b3669dcd61697c00596eb850a7117b55817100ff100849888b5fb6 +S093/S093R12.edf 3fea038b8ee2551bfa67f17a6dd668a30e70817996102b7b30dd7f8d7451bd47 +S093/S093R04.edf cab05a2b51874a488cb968bb6c76afb883a7057e384c0af1b7a766e34f4a1de2 +S093/S093R08.edf 54d9a7c0997e29abaa6ffec4a48e32555fff894d83e778c5e974452665835d4d +S093/S093R03.edf.event 6adfbec29ec794c0e3c78a211cdc8485ffa3b00bd6e1c3dab9a7fe1bab88aa88 +S093/S093R11.edf.event 0724cecedb70811bcaf06ec5a41151edaf5209f968315c4da2e3a25bbf0fb9ec +S006/S006R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S006/S006R09.edf cb3af5f176ea1f5be8e493d80f62eb374adf0a92259beabf254a6b423711cd64 +S006/S006R02.edf f114ee8be3445ff48c78422d4cc7b6b68ab83d79f06cb47634b1710796aeda4f +S006/S006R05.edf.event a38580800381d773ef251e941cbd4e02611c4c4e4efab3c383f14300a3394f1e +S006/S006R01.edf bfe32b925fdd469c90ce6913f7409cf85e4492b40d36c77b83511592d6e4c647 +S006/S006R14.edf 4fb5946ed7a29268af9b1770db80d4c6a3dbeacab4be573b6da9c095b8a5e68b +S006/S006R11.edf ce5ef60e07d2b1db8492739786eec2bcc6bb9e85b05fa0c9f2851e3a0f3e9907 +S006/S006R06.edf fc5e1cc21df8b1de6a63fe1a063db27d14ac882d6105057c9d4f924365730a4d +S006/S006R09.edf.event 825d019e301e14c4cc2a396252dd43ba79dd75489c263fe4af3e18e46c5dab2d +S006/S006R07.edf 56b8c705b9c1406546ce90bee6373172f43ec8bb5437aa9772dc2512405e6a17 +S006/S006R13.edf d4ebe044bd1f71c2a653bd8ada69b343b79fe18d9002a24ba96917533ecabe87 +S006/S006R13.edf.event 537ad705e53a339bd1d130f3331df882a0416fb7e95c4f565d283142dcd120f4 +S006/S006R08.edf.event 88e1ea56ed0459a99b011a3ea2f25f947016dd359b2d4fd683f838ac00d993d5 +S006/S006R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S006/S006R12.edf 296b5cb14549098dc55ee047cc9ff63faccf480e432b94797ff73cc7209b7353 +S006/S006R06.edf.event feeb9bf47f8f6dd0e083c64236055fd7ca30a06709747978b6a7bbc0b632e21c +S006/S006R03.edf 1bedb6634f28af44942c14901aa82f420858bc367fd5830482b4e8cf7a28bbf1 +S006/S006R12.edf.event 2b0cd50273254147215db0f2d93c0e409b2279fe37afd6cc7d86edb7df57486d +S006/S006R14.edf.event 0bddeca4a8cd621dca3130a2d5affe793bfed62c379600613bb61a6e554ec750 +S006/S006R11.edf.event 69bc42ecdda8587b1f3dcaeb49f434eb51439670272d896577812c1a8c0b14aa +S006/S006R04.edf 4bd532bb728e1f2ed2afc0a5c162830a07465b6a4a58e105d1316c6ff1921f3b +S006/S006R10.edf.event 48ad6251760a77acc67b82ce0b201f4244cd1385a6181c8236487af76fe1636b +S006/S006R04.edf.event c6fd76cba5a912b92a280d7d54b9158146ba5522f81d9192baecc014a6c9149c +S006/S006R08.edf 006e55ec16590f5f5b9230ac53a2f8fd0660960fa7b4b512ff61f8f7e2f8714e +S006/S006R10.edf d4a1d432d4c703decce7f7ce0a6d7c05a030fd19f562fe2be52d4c581ca24365 +S006/S006R03.edf.event f500286a76884018ad149ef34cc8871332593723b30ad3d79f8f39236a5cc25f +S006/S006R07.edf.event 190f359cc14939d921985886ad1c9081e5e2059b38ae9d130845e8dad044d790 +S006/S006R05.edf 2b793afa3378f56fb546da8265f3efad685d1201b26bc35ea5b0f660a15d87aa +S096/S096R12.edf a55f541160ec1f29086e8ecc7e54ee60fd5d0ec9edbd40313c30bd4c7695c81d +S096/S096R14.edf ad6c2bb5130d2c4379d08069f45be5bd6e16e2cf52d3d46c480a211ad4fc0c0c +S096/S096R02.edf 2a8c6c0c88ba142d17c19c902dce4befd1a2cc497bd43e112c14bfeee792ee18 +S096/S096R11.edf f4893d08eeb086de8eb889dd3d36ec3fe8ffbc56c93ade7a08ebf1af6c731877 +S096/S096R07.edf 1d4575fea624049f78bd4139006308fb88cea1da31e51690f0aef14c5063cb06 +S096/S096R04.edf c39a9977ef6b916ec4183e678a0eedb12695ce9084e2a43fade39a6038cc907f +S096/S096R13.edf ea7994757aa12872aac2fa8bc6aee5b48fae69f74d69e9c060c3f95bed4fb98a +S096/S096R04.edf.event 3d40baf6066941639ef493e2ee821cfa6bd1a236dff48c0659131c0e88fef481 +S096/S096R03.edf d84c57263849e5980aaa0ce9c4b40590ffa912cc45ddb9231de7f6336b8af234 +S096/S096R12.edf.event 37cc966752b10d3890cb16ee78927420f7facf9e9edaf86af928442f1f9df3b4 +S096/S096R14.edf.event 94d1d7007146c80e4f45e873986a770b4b807a34cfeca23f6a7d9054865154c1 +S096/S096R08.edf 6dfcfa5182fc32ca2aa8bf74722f43cd992b2bce64cb7fc15a4ba13a9533fe10 +S096/S096R03.edf.event cfdc7957f5c28cd1f437cdb649750034f1340084be6ccc484dad902fff9127ed +S096/S096R05.edf.event 1d29aa2dd90032d41f7c1c6386db9b2b26b7c29b87234d56e63f65c958acaa3c +S096/S096R09.edf 77c04af955fa1af9dcacfe325d01bb99da92f48d30a041f68a6f8e9ae3e2358b +S096/S096R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S096/S096R05.edf fa817e1acdefa929755a9e0e5b8dfcf85ebd08369ab5d9be92287ecaf172827b +S096/S096R09.edf.event 37784e11407ce31ee513275216bd40c96a4580f080500f2331a58f58a3ca826b +S096/S096R11.edf.event 2e361d8b420d6db7c1d4372f2f615a9f9290ab6956917406863d12a1fdec8f5f +S096/S096R06.edf f69902e69dc0894d9bbb2aa64a154571cd60d867c885578a35bb312ef6f9b831 +S096/S096R10.edf b5e8594fb191adf76d6f29a1607cde6435b25616b0fab99bc18f24adedb17dc3 +S096/S096R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S096/S096R01.edf 005e6ffa9938042c262035797bcbab224dd6039236872416dbe0ec42cac91e49 +S096/S096R06.edf.event 14a453fc6552b2a6d7b55329ca3533853a89a83368101bee6b522e4a67d37283 +S096/S096R10.edf.event f345df3e4e6ca2a51df43688b6036dc5af9a89117b2005dd4a45a7e3886d6bee +S096/S096R08.edf.event 7bc37a046920a5e8c90ae816bf99bac5ca23a1a0ad7d98c1d3c2c5d698871986 +S096/S096R07.edf.event 3c11674692ca50df8414eed1ec2d7308aec7f8ee62785db4f654ee632e18d29d +S096/S096R13.edf.event 405867bf01702626e40e74e21dcc164b7e87d59de89a4e6fd2c4ce561f2e6c1f +S088/S088R12.edf 930e7f40798227e75d28c35e9d79b6c58c78d742daa1daad95f967f633ee02b3 +S088/S088R12.edf.event ccb7718e9ad0d8edd7de8d12553d98a89bcb191c436a6067b3e688a579d4abc9 +S088/S088R09.edf 06f8ec3746f7fe6f2fd6e80465bc8d94471cedd91bbc7f9ac0f1b8dcc00fe65c +S088/S088R05.edf cecedd6c8a8f4320a038a2b32034acbe54bdfbc9f2ec8ec5e04f00eae4e15ece +S088/S088R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S088/S088R04.edf ce6b97a3e00de1b844694fc889ec0ac568fb5c0129130d8e701761fdf0e2711c +S088/S088R08.edf cc57c5b3d363247feacb04b4ef37a30b930ef7a202449874f3773a24af5332f2 +S088/S088R04.edf.event 01f74ce2c10cdf9ed7fe03895dd7f42bb5a5c5b9b847f0f0d5143ef0f1d2211b +S088/S088R13.edf.event 87602b626ec0e48829f47bf9d0c1e958c80a92ea1d57745168a2630ed1101f98 +S088/S088R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S088/S088R06.edf e4bb1819e8c496f228e80d60335964c5ab8e4e1fd1084bc1238ad573aecf748c +S088/S088R05.edf.event 0930979151ea3e22809e2b68d6fad0bb672dea8e58caeb269c20f5bbed49f1a3 +S088/S088R07.edf e7eed7f6d17a3d7e11ef52de0237ba2d93508990406cfc5fba40c91347b366b6 +S088/S088R13.edf 291d09d8e7c444f9dfa93db24cf69f7c64f6db817c6c7a717871d98edd7f8549 +S088/S088R11.edf a7fa83aedd07dacc07408fa53026d4626aa9680968946930a6f369bfdada8778 +S088/S088R10.edf 1c49b9ba7cc30f59443c4292aeaf85dfe81f37e09e4e24db3cf66c7e45a01d3b +S088/S088R03.edf 95c2618922b253bb9faf4a565dc64bbd3b213347764aaf470661b5ea3755c241 +S088/S088R01.edf d7ec3aea4cb49618ec70a1c223c578afac19338e4142807ce9128e78aea49618 +S088/S088R06.edf.event 01f74ce2c10cdf9ed7fe03895dd7f42bb5a5c5b9b847f0f0d5143ef0f1d2211b +S088/S088R08.edf.event 87602b626ec0e48829f47bf9d0c1e958c80a92ea1d57745168a2630ed1101f98 +S088/S088R02.edf 52a17441943433ca8965ce7a21262166ab3ac6e8609e5bed3c39e2ca12cc049c +S088/S088R14.edf.event e88110dc871719db682717f3a256188ebe916d76e5a1a09b0cea908778ae4424 +S088/S088R07.edf.event 0930979151ea3e22809e2b68d6fad0bb672dea8e58caeb269c20f5bbed49f1a3 +S088/S088R14.edf 8a912f35e39b002fe61206bb8661bd783a7b7ba23338f00b8e14ffa746938d0e +S088/S088R09.edf.event 87602b626ec0e48829f47bf9d0c1e958c80a92ea1d57745168a2630ed1101f98 +S088/S088R11.edf.event 82e7ace9f055649957ab04324ffce9101db68bcfcceac1df6786e304f9de8669 +S088/S088R10.edf.event 682de6811acbabf1882380fe24d80b87fda2ac6a48fbdd6eab47970ea1190440 +S088/S088R03.edf.event a27a31471bf1b8bc6ff9b144eb110e9eb0711b24514aaf47ed1cd94395c10b7e +S029/S029R14.edf de0767217b8a403b9670e09ae75d301bfca1e31c4c08cef8678091a038ed9fc2 +S029/S029R03.edf 8e65ac9c88f3dc61adafbdc6809c1bcb9a46bc9ec911239fc8fd7726416e2b5b +S029/S029R07.edf.event 5207e825d15ed81ce802718b5134141adfbb78f1e5f1ca62f6083c6fc9cdefb9 +S029/S029R05.edf a6b3b806a7e4f79ad706ea4e65aeb1109b37730a87919d46460aa8682433eaf4 +S029/S029R09.edf d3acd3558084062eab5a28643879f51b03b8b6377e1cb31d8d45a93517342262 +S029/S029R11.edf 7c6f7cce142ba49222a0f4dc65f0094a7f1a0b8690ff043b834f043cc4286408 +S029/S029R04.edf 4674f7e44919af804dfd99a38004f6b9ae62b21eacd61ca389df55aa18a00f01 +S029/S029R13.edf.event 5d2f63f6f7525c2a049a2a72e3cce5df4e2f537e88220d558ea3f39afc316bb5 +S029/S029R12.edf.event 8d1471f501a31820d94d776160244282b4f4d8c8faec4fcedc3041360481c5c0 +S029/S029R01.edf 48641d0db6e810c96273d8c26d52510132ae503badf74471558b7c12306265b2 +S029/S029R08.edf.event e79dd10c21416b18d7df92203956af2ed5ee19efd50147912adc49744cc31c00 +S029/S029R08.edf a77d299e99458745c7010d023698208f6b0d56cd5f2a74628688d08a600df781 +S029/S029R06.edf.event 32d42684dec82d19ed241af99bffa1b231a1379487eeab2ca6ecf4e960d72495 +S029/S029R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S029/S029R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S029/S029R04.edf.event 8968db92630d7873955e9e9f9858bc44efed375ca81e0e18966b9e0e060b589c +S029/S029R03.edf.event 064ef0b07a868c81ecd78eaf44c28915f919810c3799f26c5fa5040d9de0a71f +S029/S029R11.edf.event 321c4a867784fc95b428c11912af5a17c303ae8df6cd8f6e4124a31ccbfea8e9 +S029/S029R05.edf.event 9ae43452d01b3a55cbcf82776804cae07420bf106c0e5d7010ce1d987637c83e +S029/S029R13.edf 5c1e9299ec2f5c58455b4f9c42ca729dd5013c898ffcd4b33e9114b7d030509c +S029/S029R09.edf.event 6ca3ff62b8d0191c28d6529edb07636e822a980b4ba1b463fd26b1ad8a09c5d8 +S029/S029R10.edf 86340bf35f707ee4194c4440a5bbdc1938b885f2ae0bb425cd3f37a82d352133 +S029/S029R10.edf.event cb58aa4b6d937e71ea9ca4f60e2e4c78b06334d7bd11091e5a5927fa712064b1 +S029/S029R12.edf 9d01ce9be2230b87a47050e0fcdbbfde4ff10144b9466fd286b618e59a81473a +S029/S029R06.edf 0ca802caa9950b5277730fad8b5e8afb0363b0df99dfebe2a7c8a0229e6d2760 +S029/S029R07.edf b99f383631ea61de2fa1b36d28c490a72009bf5bb192294fc1ebaaea254b070c +S029/S029R02.edf 7eff9783f20f4d3521ae877f26d7b2c87c609a920e16d12e5479072c2cb65671 +S029/S029R14.edf.event 5a42bfc69bfc027aed4436c7be8edf69672b70d1ad5a4354e11a92ebe527fe53 +S047/S047R12.edf.event 020a012ee89a9fe2c7bcf34bf02c0d2d78b688185ed74043d21a3d53053e3882 +S047/S047R04.edf.event 99dc24a5732bc2857f1d3fba3d1a5b942b288ef56950e45354e03fb10183bbe6 +S047/S047R07.edf.event 296bafcd473fd6051b9cf19b1af83d7f0a4ba4eb310f7fbf462aa7ac3ebb8120 +S047/S047R06.edf.event 1a93c91ef79032df8664905730df14e57174a6aab494378ea976c6845e662faa +S047/S047R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S047/S047R10.edf.event 017d78426c2e9f2b1807cc35ed07405ab8ff157014df0701b8524f965539b319 +S047/S047R11.edf.event 7ee6977e5ff9c282ca6370406d7a9871d162328940b104573ac9f1d5151c4b96 +S047/S047R10.edf 65fa985cd59fb7c1d5e2cebea93e23608c59ebce4e4e7f69e4cc23542290dda8 +S047/S047R09.edf.event 96cef3a9a9e2cd7f438d53008e256b198c48c6e0d2f0b2d70e0d296180cd58b0 +S047/S047R13.edf.event a716ed693834141bb2b56720ce6124df46e42e86652ec02bc96746644a79378e +S047/S047R01.edf e9e5061be6fea706fdbf03bbc9d0d8de48476d036553a06ff0117c98b60303c2 +S047/S047R03.edf.event 472673d75763793097b36d5b0883addc030cb3790ee84a18c36eb33ef80d009b +S047/S047R08.edf.event 386c51194ef175e56c4d94b5e327133f39929095caa7c3ac86e89628f6fc0610 +S047/S047R12.edf d457e75b37b82724af1b7024194e5c4858b31402b01f8b2691bc9d4bd6ea112c +S047/S047R11.edf 15b68b4f9959a4239152f3e33f0e9f526cc8e8a5d20195f0910724c3f24170dc +S047/S047R06.edf 49d91dcc440c3579b89a557d2aadf39c3fd80f1ae219e91c6d4fc8c36c880562 +S047/S047R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S047/S047R04.edf 67a0ab9dbf9e0164fbe16036ec578b89056fdfe8efdb1eb4aa441502a23b5a5a +S047/S047R14.edf 225c6e69e9f83c33c7529bc91bbd5a446df75589abb2c9d67b34f6b819561720 +S047/S047R07.edf 19b9ec59b71b23bc0228076fd0250cc3f942a14c39bf8abf3ea756e3727b81d0 +S047/S047R02.edf bf7069f688dd19df47c0f9f9b0fcdd6c01fba48a170d5c0dae8551abec383388 +S047/S047R05.edf.event 8ad7739d7d370e087ebe5db6ceadbc03ee38d96703e78cb5c91f2b714f07a25e +S047/S047R14.edf.event 5b8eb2e2184e2816cb3f7104149139af83c25f381a47b42e81c9c6aa1723fb5a +S047/S047R13.edf 4c8e71039e5368b6e6a9acb68b81a4f3bc3c9bb5911d925f0064eceec6b92a9a +S047/S047R05.edf 04dd463e35a6e7099508e49eb2a92dc4cd9bd2b893f194bf332a705232d2b8e6 +S047/S047R08.edf 4de761cc5ffcb89ae9a1d4e206a0397742e7a6e34e458bdf8e50883a3f7f6328 +S047/S047R03.edf 9f43c92bd5cbbc1eaea5b1decf8e66b8629874ed3b81055551b7a59574dfe28e +S047/S047R09.edf 988d7b5518596909926ef6038fd4d6dea34310e874e3b681331bd7a5c8de2f86 +S070/S070R07.edf.event ed0acb0c9635a838cea852cecffa253bbee6e084a3404ea9ac9900188570c878 +S070/S070R06.edf 94aaeafdd41b40b187a9517590531be5559cd86d21bb729bf797d32d4de584d1 +S070/S070R04.edf ac0f01d6df57bd65645c2c6a5b6685d38b11727bf41927fdca90ef7e2d601482 +S070/S070R01.edf 5dbb88fd5e39ce0aae257321765c2b9fd67ee9248993c55fdcccf79605442f23 +S070/S070R02.edf 26e7f3e389e357fe2070157a1d4fa0f504cb8e9cefbfcbb2f1cc5997e71a0e7c +S070/S070R10.edf a0235c84275a4066a7905b0b3322d604213c00c803d59ed9b55b912d9cdd89b6 +S070/S070R08.edf 8c3737b379124d86fe35ccbe37164773c97926d6c7731007dbf54722848e685f +S070/S070R07.edf cd366575453680fb6b0af26f93bd220b17c5da1d66ef4a594a7c489c0f1d6907 +S070/S070R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S070/S070R04.edf.event 9825c80a69d06961cbce2e12cf8d0aa56d063e5f4598312c4e5b78693a0219c1 +S070/S070R08.edf.event 0028edf9b5fcc76311706f809ca44f884f227acaa02c56031cf87a7937c1d9a5 +S070/S070R05.edf d28e20d96170e384b92c71cd7a1ea6393e7f28f779eaea3c7fb7142f5d90dc83 +S070/S070R09.edf.event 72f39ff0119f687cb1efa8861280ba991bf463a2eeac59557c3bb3ea57e09aab +S070/S070R12.edf.event 951ec5064433ae4ed0e83f00905ef394c5250b33e1122f41b10ea8917d13afd7 +S070/S070R05.edf.event 7ee6977e5ff9c282ca6370406d7a9871d162328940b104573ac9f1d5151c4b96 +S070/S070R14.edf 3661f01ba04678982e2efdd3823c1ac1f9b3bc254b1fbc7982b28c5a7ddeeb4d +S070/S070R11.edf.event 190f359cc14939d921985886ad1c9081e5e2059b38ae9d130845e8dad044d790 +S070/S070R13.edf f724ddf4f4037b8e7beef57d55a76e7641fb9ec8bf98bd0a50ff61e2d9433129 +S070/S070R09.edf 7c69a40d9f5aa95bbe259e4cfd8a2664934a1719cc66a6289fae7d1fddf2aa2f +S070/S070R10.edf.event 8aa5136ec7d40284d8eb37993d435226d73bc8621186eae0d173bf0e65165054 +S070/S070R13.edf.event 1f21e6a28cc1b59fdc3667207c5b1029902f6d0018bb978cecbb5905b868cb10 +S070/S070R03.edf.event 5bca2030ba3ea66c594c376bfc5a701d3f25c2f85ea7d72b8abb2b2bbc5644ba +S070/S070R14.edf.event b50d31cc4a2ec520a336774ea70761d08ebeef4930f053a00ed66803060bddef +S070/S070R06.edf.event fb76d885a6c380c62ce2da054f5ec78c9f0178752694a36e4b78183ec8850830 +S070/S070R11.edf d54f1b715e23bb3a48a6f904ae2eb50d109447fe4c483eadffe7e965339c34de +S070/S070R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S070/S070R12.edf 9519f622bb5de5cd8f24eb6a765888a78a28bd17446fc9a41ec13ba84b75a0db +S070/S070R03.edf 9b04b49209c33999d70119b985f0ed5ea5dbe3fd4363dde555e742872ed7f5c5 +S072/S072R08.edf.event 7234785f889c4885f0b35192d9919da14670dae4f01dc951f9099ca59d5c7bd4 +S072/S072R06.edf 1b615047f9d42fd7e0da4f649348ebf2b1d929c6b81852898189dfbaeac47901 +S072/S072R05.edf 135ea7898b7c7454535a4be865cb286b6196f20f2dbbd4ae7fc8a7919e86d44d +S072/S072R04.edf 854bc325b4913798858d5ad099c953c6a018cbbb73a1dbf465882ea2f965d5f9 +S072/S072R08.edf 94bfc11c4720ca4a52dd683f74dba027c47a3e00a634ec15c816f7ff3801ba8f +S072/S072R10.edf.event daacde82696d6cf6075cf81c698fad407304dd3c18071f700a24850cf39d5427 +S072/S072R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S072/S072R09.edf 5d1653c82bbea3fa795dfd7f97e535bdbf17587bde003ba45cc5ea4101f965cb +S072/S072R12.edf.event 10b6367f469a7259d23674e3f8fc88a24dbdb41460385095daa9a795a3b47010 +S072/S072R12.edf 8d4b7877af0a9f04c281ce539c65085ab41d21cdb97b28282f55ab26f5dd6afc +S072/S072R10.edf 29700aafb0ceb72983447355ff62479f7ac371db4fbee7c35e2b9427412f647a +S072/S072R11.edf.event 2c7eac05570280238d6e75f11c28223cf3c6d9c9bbc4a888e05c2b99df0d8b15 +S072/S072R13.edf.event 90ddccb5a9607fc09dfb6e835c770a03f7ef1f0e65eef2306953bf4894302136 +S072/S072R14.edf 45cf02bea1f4db899aec41ab64a7eae44b4d6e2fc2fbac0109400e84706a6602 +S072/S072R09.edf.event 357bcc1ef517dab5a2c819b99716cb28db0a13240c332e1c37196b27021825a9 +S072/S072R07.edf ad44b64c22a62b119afba8ca57a9dd1e632da8e422abd2dbfe92b9088df96250 +S072/S072R03.edf 65e1b35a0098d9eb6a64f618ff8b106662dc14a6624a392e7c5bcbf675a843fa +S072/S072R07.edf.event 880bc36e6f5d82ca838cf6169f989c0e959e8c2d5970a205282cc1e8b8a7c068 +S072/S072R13.edf 84a5a50facd102fbebd09f7dff4ec4459beeaa0ac2c79d16a165de0aa37fd215 +S072/S072R04.edf.event ebbd9bc0cd84bebd02e71f43989cfd362624adbb968d778a6e759a70c66956a0 +S072/S072R06.edf.event 352673445bcc538539b47f676cd9701d31de8178217f7cf903d3b878f64b294b +S072/S072R14.edf.event b4317c81c19626393ab603e338ee0d39f9b6b23f4bcd2dd8ada827ee5a14093a +S072/S072R03.edf.event bb4d81b1643558abae8dda4829a909d44c1d41b95f317fd8470886f9c19a27da +S072/S072R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S072/S072R02.edf 4d9044d0e5c9c0d71becc31e5f5c1eb5739303905c4523566bf63de7497ff5a4 +S072/S072R01.edf 7742f6c605fd73b04ca4ddb7dbc1db4a11cae8497107d3720cae64bcf1fa32a3 +S072/S072R05.edf.event 76db7f6afb0264b534d087d90c2136b0f5e75f69d744c33be087337e64d4a360 +S072/S072R11.edf 3a2d6e7ba690f2ca53a716cbb6eccbb6bd47d1ad1021a819a60c1e9f68333b45 +S017/S017R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S017/S017R10.edf 1cb81c247ff4d726beca43e0bd37d6ff1aacf0d0c63068c6d389af327a86484b +S017/S017R09.edf.event 8ad7739d7d370e087ebe5db6ceadbc03ee38d96703e78cb5c91f2b714f07a25e +S017/S017R12.edf.event 3ea2fd67495fde74ca6a29f7b4f660c7de2dc5720c3a99a762e365ca4d09ab34 +S017/S017R11.edf.event f1d83aaf535b3be7098ef9960def69c712f4dadb4f334e40434e155e9088b299 +S017/S017R10.edf.event 950cf97301dd495a2a6a7a19a93d67d2ee9ee03b2675e300582e19305f5a9287 +S017/S017R13.edf.event 0487cd7ee2fef7813667623ecbe113ebbdd5400e7dff28fd7f0f7b1e00d585a6 +S017/S017R05.edf 76f7e14a4d6a3fe0914722ba2ffdfd8e67f3b878b530872e1d6c1d6fd0840217 +S017/S017R08.edf 902e30ad95dd3786fa3d3e0532743edf049850536cf773974fb9fbe3f4475da5 +S017/S017R13.edf 11045212225733576e7ca2a908205f0c9780e25d3db13ba9c7b3de8f990aa076 +S017/S017R01.edf 051e38a4601ef46f4e5be488f06e3a6c0cf53263d6166075dd94cbddec38624c +S017/S017R03.edf 19911c4a9a693eaed4addcee0ffd78589dc3fe35724079081079ad29e56c911b +S017/S017R09.edf ecb7b472281ac86ff5ca02240d785c0fe94e910f4983c3beaba7998caaadff46 +S017/S017R14.edf f95cb81454f050fc58c4d2bcb7698526e5a6cef17b157e601ec1d4abb96eb3ea +S017/S017R06.edf.event e14dc31d476c11841d45564cac660be9776fccedd3dec71dcee4c5232f00f25c +S017/S017R06.edf 0e32de926757e1a493c3df6d85955c30e0b45b0caa7f1ddac2a4cb483257891e +S017/S017R04.edf 9d13376473bae5b868c07fefde7d4ec465573b393a4831b0142a26812e5b6bf7 +S017/S017R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S017/S017R05.edf.event b0c7884218a114ab4fc2b8cb09b2c8f1bd0ddbaf69aac65191618c0a230f65d3 +S017/S017R04.edf.event 037c923028aca24716dbc8d307c618e19d4e94bb1e759e5ddb8a9d3b6b205a86 +S017/S017R08.edf.event 48eea52bb9946ed46ef7e1b621c8558d41739ffc9aa7ed8fc25eaebd171ac223 +S017/S017R07.edf 850cbc48702c9a180b6fc2408762554fb21d1ad9a6e57fcc33963055de46b517 +S017/S017R02.edf b0a760d49747671b62f7ec39cc147cdf4a3f1a6a7e2f898cddc4f5a0c8b73c5b +S017/S017R07.edf.event 04192a55fa7728d34533e76a1b831fe5c94d79c3bc9f1028f45644c51892a744 +S017/S017R14.edf.event 2b0cd50273254147215db0f2d93c0e409b2279fe37afd6cc7d86edb7df57486d +S017/S017R11.edf 864a47610ad9fe92a8dfe0b667ef81aff31f65ce988f608642572c4a7d7ee859 +S017/S017R03.edf.event fb7055ba8adb05cadd3009cfa9adefacc5298e01d2b7156815f6424ce1d4f3f6 +S017/S017R12.edf ffb8ee6f01d5b12337052ee1eb9e1caccade52937b6999d34925e90634d5b82e +S103/S103R09.edf.event 3b5e25a187d5d82fb5b851ecbebf095c41a5496c5a40492c7a2c638245bbed51 +S103/S103R06.edf 1f716bfca1542c8a270fa5ec298ac2bc5d2fb47590d2d9ef1209c3ba2cde95bc +S103/S103R10.edf ecc2b6bf5823c8aee52aeb1093804a42139993110ad49cf584a78e87b6c63c93 +S103/S103R13.edf 5ddb5493a032511dc890488bc246ed22260b40d55633b8d26a2005e989100e08 +S103/S103R04.edf.event 8a76f461c0b920a909de21383cb5135f496cf1aa992529755f784ebf12db55c1 +S103/S103R09.edf 4ad22209206ad0dac641f659b404ef1895c6446ea11a82f387d0442fd92cd76a +S103/S103R08.edf 9a594869f6cfff74f5d448abd2268870fa98c57381bdfb3eeb7bf7372daabf2d +S103/S103R03.edf.event f8a465b9ebddc2704252299afc352d87e33c523fa8f80ca82a96fe0b268727cd +S103/S103R12.edf.event a4198dd583f6157a8688c48cddf8a62d6829703a2a057ea11e115214c9cd151a +S103/S103R07.edf.event 0e11701069314a60a51b64f11d88913bbbeadf584e9322f073cea02c7d91cbeb +S103/S103R13.edf.event 8496271f8f27f048601fbb18304e61a0950c33536381baa6e6d211de6443cc67 +S103/S103R01.edf 48dbfa8c73308311e3f7c7137b25cbf4a060775c1a460fb8496c50723b8fb231 +S103/S103R11.edf 0d6426287419f30577f49cd759d77dfb2720c84007f5942b0bc9e0f12367323f +S103/S103R02.edf 62217247b15b987831cddf456d3e45904d06d470926e6df2e4ae8e4c23b1b08e +S103/S103R05.edf.event 5ac7e9c852d23361d66baa9d38cfacc10651dcd9582bc391cc58f08094c06941 +S103/S103R05.edf 65a86688d81296f935a4825fd74a189587f02300b66654ba0a837d294c94ca70 +S103/S103R10.edf.event 14bdd1b94d8b8ccdce55e581601a4a304c1444e030aee15596722a70be24c5c4 +S103/S103R14.edf 0b97a59662e0f0cd76ee688f4080ccf71a93bb5db06d0dadc82c970c4aa62f92 +S103/S103R11.edf.event 9688994b1285c6e0afb366716a7cfc380bd4340c8701275dc9340f0713deee95 +S103/S103R03.edf a4d0c0209751833078eeb3d953e161d0fcaa02c4af5e93e93094d2add8106b65 +S103/S103R12.edf 96ea0eb56fb4470b1be09516ccd0561b857748abed9c6afd5302b24c32430aca +S103/S103R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S103/S103R14.edf.event b77225fdf7eecf463ffe5af19336030526137aef78111785b6605cdf4c15c95b +S103/S103R08.edf.event 30b760c52698fc58e43824eb7302010b60c8374cc35c21494035da15da835fdf +S103/S103R07.edf e40a112d21a463232a84e08c88496fdec8e7cf2e12fde7654c891ded54640cc8 +S103/S103R04.edf a4c707cbd94c08bb37718f9c7d03c7259389e4e43e9418f3887de35acfb1125f +S103/S103R06.edf.event 43583e190556326d49c6693ecacd19aa4b29002fcaba93157b7803fca2f71842 +S103/S103R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S061/S061R08.edf.event dbd0435f98476653a27f53b54a6757c6e4596f6d9318a14067e4dd50bb37a888 +S061/S061R03.edf 27558de88191bea04c87f3f079f778217fcd016362f350e8a2c0eac6a182dc67 +S061/S061R13.edf 194e5626af80b437a223c8f28bb908647d7cef050cde4aee91224dbe3e26bee7 +S061/S061R02.edf e6c090a982e016f10248e16123afd230f8725c5a8bfd56774cb659e94efc3783 +S061/S061R13.edf.event 405867bf01702626e40e74e21dcc164b7e87d59de89a4e6fd2c4ce561f2e6c1f +S061/S061R11.edf 20a555d403226f3ab61a341b768a32f4230d0613b7b7a2edb616bbff67e9f39f +S061/S061R01.edf b0728cf10eb1885b0d5cbb9fadc43dc1625dcd892b043f05f7a55a375ad1a3eb +S061/S061R08.edf 9cd27a3563ba90dd3ca373b0da2be78b64c7e4858cbc9954cf4f503f39809aac +S061/S061R12.edf e16007dff642ce2bd6275e806525a0d66d0829f39b6b7e7a8fe18cb3fcea498a +S061/S061R14.edf 5a6711078c8d3114c4708f012b4ad5a9f60f615ea9fd1e9874f348e5ee4d6926 +S061/S061R10.edf 9502b545c2e86b5403dcfcb98c32f7738c6918d9e21c893b61ee0f5f12a0773a +S061/S061R03.edf.event 7fbc239687b3b3100e651edd3c5804afc9493f15f29a15a7c7c523f9f42b5b1b +S061/S061R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S061/S061R05.edf.event e3378f798c2ae2109571b901374ec3f6e67c17b45e2f63b458ca5b1db30f1ea0 +S061/S061R11.edf.event 109d77619d968e04ce3d80665c461d8412a594700916e31d523f31604e109b24 +S061/S061R06.edf.event e697ba3ef839244357e1c111d7dfa9afb60310a0bd8b7935ea5a426a1711194c +S061/S061R05.edf a559920a213923175fd8d90bbeb55840ddbc0851e4cdf661476b19f1c5d8fa31 +S061/S061R07.edf b7a91ef5bdde5cdc5255ad9d8482d8b6f44d89a402d67041e05441dcdf37fd71 +S061/S061R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S061/S061R07.edf.event 3a98d78e3ff8d947a073981e739716fc7bd37c89605bf37bf0addaa16779530a +S061/S061R14.edf.event c6742adf7ce83d034f6e3cecede733919ea0d2fe7854dc4a86c12cf32c5c5aa2 +S061/S061R04.edf.event ea56fcb5af6dc22a09e6c52c6c50be06f5bf4722cba178188f67732c6ecd0395 +S061/S061R12.edf.event 4b81a244be0ef71bc8b32a5a151ca3746b282903e6c7a28b644879e8bae159b9 +S061/S061R09.edf 93ab6309318f1c2f9866e4b158badd8d1eca684ce936eb8d8d8b5ab80ecf8b33 +S061/S061R09.edf.event 82f0f5ea19a20ed8cc8994d29456053772eff3af83ffacc51907fa043cc0ef48 +S061/S061R10.edf.event 22a6b841d94ebe84eeaabd93fb3e0f00da65ddf3bc8de6d5a79394e3a1394567 +S061/S061R04.edf 788c7f7d524dc1e483e49e81f36920a65c464ae54dece6c96ce48b7d168a22ae +S061/S061R06.edf 24dbe6c1d0465c3bd447413a5b28920ea0dd241c05762fef4f19b5bae3a7cc78 +S057/S057R07.edf b46f328990c5607512f28a229769746f0322d8b50e9bc76eb2499abccd0aae27 +S057/S057R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S057/S057R10.edf c7c581aa6f0b7d21e348034fc4f22c3ce66ca81533a3b30252c6b8be10f0d5e8 +S057/S057R06.edf.event d704e59168ad57b1fa2751e18c013c84b7169c08d874e72c7388b74c93006559 +S057/S057R09.edf b6e2cfa63bf3ee3815fb384bbab18aff1c34254e30c1b0d0d4778f5bbec2e40e +S057/S057R07.edf.event 018a676bc733cbc27dffcbbf3767758e526d1ae08a5dbd0785d28e267132a3aa +S057/S057R12.edf.event bd6d931c82981d9463af509515eeb55f7b6499310a828316c8f4a3ea35ecc7bf +S057/S057R13.edf.event 0513fd04977ef5a66b77e72c59699e4e54ff57c226456d0796b1c58c38fb4d59 +S057/S057R14.edf.event cef39c5c7fed8cace25154d7385aa5c8666f28db51ba7c7224ce1650f9388915 +S057/S057R13.edf fdbbaa81ee07af8968795bd8fcdd52ea0a2b74ff686ab03666db07757e0b63d1 +S057/S057R12.edf a893824591d10cd67a04b1273ed436bff4522e14c1d6b6745f2e75348267d7b1 +S057/S057R05.edf 3c6aa834c303ebe0e89e012a0cb7b541c020dc40d028d54dba51ba16c3537998 +S057/S057R01.edf 0b5b499f95a86f7c04d63cef9489f04a81a335eac0c80ec8897eace504c0205a +S057/S057R08.edf.event e96a6caea4f9685ebdd4b9c4f79dee271ab2ca8fa30cd6fcc49d330a6a0c770c +S057/S057R04.edf 53d8515a722509864bd45b148d02730770f540ef56f44cb1e161fdec6978a0a3 +S057/S057R02.edf e38e0435c54470b41f2c2fde3685d58dddaa127e989474eb30955a5d14009969 +S057/S057R03.edf.event 211c6aa0a079d9cba1e8d336802ff8e126829175da37deb01fb3234c2fd81d9d +S057/S057R11.edf.event 6a0785ec7d7cd8c80087db9605dd320790daf7db8cdc6c9fbe68fad0470ed604 +S057/S057R11.edf f0195299b3289d582c4aa4fe027fb937a1c2339def7afabccd065887e8039220 +S057/S057R09.edf.event dea4ebd6eb695d78f9821d3bfa3d4a325dfc5d7ff6f514c6a3f205dfee689e4a +S057/S057R10.edf.event 8162d74d19617d3dc613cc4d3505a1e143edecd3fb9c7901e255495cf94de0d1 +S057/S057R03.edf c14f828bbab8801708392702b0af3536aa23ce706a18b212ff0599a566375876 +S057/S057R14.edf 0994c41b6b5b114b14d85e8af5c4a4cd9d54cee8dacfb780ec922d8af2c59b25 +S057/S057R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S057/S057R08.edf bb2842570aa4a89021f710397914cd810dac010cac428b75173adcc2fbf30a28 +S057/S057R04.edf.event 837f0145b9da4dcc73e14962769b9c68f3eebad462eebe9d8796bc8b099af925 +S057/S057R05.edf.event 1442094c7e4c8cf80c2b917010d3a5835f895b48a64150371ef6f1f36d5eb9dc +S057/S057R06.edf 4f03601e2259a409efad3ade660609c937960ef4dfa564c70deab294f5700c9b +S083/S083R07.edf.event 1db920b489aacf8fb0632d9e919efb2b41c903f8721a96cda16479fdb668ec36 +S083/S083R03.edf 05e2dd9755eba090bd9445c850a7d7d3ea85f1945f36b84787ee434f25ba9c80 +S083/S083R09.edf 0e3ec56ae46f1497d6b427940d6648257beccbf16c779903eb8f51ba66de16ea +S083/S083R10.edf 8772357764f7bb97617443ab303c47d851e0a1f0ba30c9f485507aaa0e0b48fd +S083/S083R12.edf.event a79f747a01fa0ee3d769d3c8e6d6c47bfd1e464df2bb7748eb057537007ded6c +S083/S083R05.edf eed3d080081210253834894b06568f427a996c40e3e11ee28a7acd7133684050 +S083/S083R05.edf.event c81d77b099878d1d392e93aa7a18a46b936b690bad605aa84a652b2bd9cbff1d +S083/S083R13.edf 02a1be3f1868f8f70c83bf073259c01185cbd2762bf96f488d0d140843ddc5e9 +S083/S083R14.edf.event 15eac883e797e576d72c57d60ca80b477563711c2f4f8dd16cadc5a529d40f03 +S083/S083R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S083/S083R04.edf.event 3048bcb4e0fbb0a4db3d630b323c27c5e88b2f2b6aedecde86b33b1d4f135461 +S083/S083R10.edf.event 3d40baf6066941639ef493e2ee821cfa6bd1a236dff48c0659131c0e88fef481 +S083/S083R07.edf 30da924b540a596f91e0964cc993821f29f3ec4ddea82aea78fd60706c6ac32f +S083/S083R11.edf.event e3378f798c2ae2109571b901374ec3f6e67c17b45e2f63b458ca5b1db30f1ea0 +S083/S083R08.edf.event a8e304ecabaf8d9f1d4997f8bb05c9613cb7743d7dc73f6af7fb82cea10f7792 +S083/S083R01.edf 5f6e11cd2acd6244310fefb52a9754242e5fd67e9d1e9fbc148c40ba6c660815 +S083/S083R08.edf cb1c0b233d3a0e618c4ef16f80cc5c2cfd400162aed06847c6e24b1d6cd2add6 +S083/S083R11.edf 2fbf5cfee173730d5a816355c31442044ed73fb20683f376ed90115786f0f21b +S083/S083R13.edf.event 8e32d162c32c431dc9eedfd3b87e45cd3f4466027dc3ebde41c1840612c6f52a +S083/S083R09.edf.event cf74c26a450e66b1953f1cafaa4b5e1beed2c2e16627f1466e08f1d0e4ca0653 +S083/S083R06.edf.event e8e41113aee5fb4f165be2a6037f6a4368faa2c5f90a63ec9b60f4466a2ba6f7 +S083/S083R06.edf 4a715e03ec3c310eb02d9bf03b2e16f65cf3a892a033956fbd60210c202fe751 +S083/S083R03.edf.event 7bc37a046920a5e8c90ae816bf99bac5ca23a1a0ad7d98c1d3c2c5d698871986 +S083/S083R12.edf 7fa028930f6c461c054e1d22e6026f954688b99817232e88f13892c4d7e2dd91 +S083/S083R04.edf 8e28c29d9d6203a35237b30878a1678b677e762561ee6f55854661284d9b3a21 +S083/S083R14.edf b94a229fa28185fc61737b30c0df46a3b40712d6f16f10bbfa369789b9010cd7 +S083/S083R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S083/S083R02.edf 27108699388b469a3d7c75e75d9156b168715f9cfec764c11ea45d8b188dab1d +S019/S019R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S019/S019R11.edf 0bbc66e7c1fbf22e6e8f43aadc075508d94ad0567809f0257d7b65d2b7c9ac8f +S019/S019R10.edf.event 533737c87655572a20223c364be6c8be7a035cd8cf3dc42ed8c418e46e174661 +S019/S019R09.edf 9640606d791c5eeb183b385ae2da0c187cce28b7491378fe9624c777cf063b47 +S019/S019R12.edf a3c4942a316f2cc431aaa358288b3c8f55fffa7b832ebca26705f68f007983ea +S019/S019R14.edf f1c4268a5d230b83417494012193d3511dd8d4de5930a9ebbb03ad2e26a75dd2 +S019/S019R08.edf ae16abeb147d185bf9bd6e1ceff37d95f73fa2b3d03561225a35447d72cc8020 +S019/S019R07.edf.event 43bc660a507d479ebfc1c782945c8504dc21abb3e55cd48acc2faf4db673e854 +S019/S019R04.edf.event 6e4a2f2b413bd53735575eeda52d35059687bb58d072e4de1626bc16d7a28d24 +S019/S019R05.edf.event a5608231854f8f457c107c9acdfead912cd6d55fc459b7abc2f11d77bb166129 +S019/S019R03.edf.event a38580800381d773ef251e941cbd4e02611c4c4e4efab3c383f14300a3394f1e +S019/S019R08.edf.event a7dd5d461dbdafc68a647202ccb3decd039a172ca33d925065fad2be2efab6ab +S019/S019R02.edf 0e82a0cc44fd65c15b9cfaac7143a9915c1712d6286feb81396911e7d4c06925 +S019/S019R11.edf.event e4d125d65ed410f2e37eb6c7f7075c585662cb4e5931bd8436cbd1b59c474f77 +S019/S019R09.edf.event 0c671e4e4ff7b21e4f75cb8796305c57d6ee3fc48e74337e26c3b9f5d49408ee +S019/S019R06.edf 1b0ad7d85228488fe95410bcb88108d41cd8bc2f9b078cf8c0641ed1e8656f42 +S019/S019R04.edf 97eda5477ba1fa369a3718b332a0d5ce6a71e37b5153d6472d65b430103a3d06 +S019/S019R12.edf.event 9e1cfe676de301ff52ef7ef70ad2cdd8b8c9562c01e98d8eae191a5c8c28aa46 +S019/S019R10.edf 809a866319f3dca5bc549d4ed8bb36a891ba270d4aee23950cb5e85c2819fdbe +S019/S019R07.edf 0a97151bc1c64abd2d943c3de22f64d769cdef62ebc5ba93a502b50f82a26f2f +S019/S019R13.edf.event 212052daaa4c0fbc66f91923236861d93fc52f73403f6b4d988205287f1f9ece +S019/S019R14.edf.event a190f5e706b1ba961aeaf8f8f44e40328c3825ee96b16903b64992c144c93a60 +S019/S019R13.edf 661f5140802887726cee2dd2f53657bc61025610686ba187796a67c58c691be9 +S019/S019R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S019/S019R05.edf ca4f301dbdf4a3a6d2a92e747938e249a0b14636ced35d1049c98165090fb233 +S019/S019R01.edf 2c542b11398dfe863ffdfa3e94aa8ee3fe6414b5ca384c7a242b018dd9e9df12 +S019/S019R06.edf.event f2f8656ee521f666124ee80cf26440ad4cb3e88315a64306e592a3424ebb8ee5 +S019/S019R03.edf 27c074fa068c8e6c8b38479d83f99ae810ca06f2d60ed76339f30c3da111f385 +64_channel_sharbrough.pdf 258b24e77052a735ab66ac99692fc7b815f1c79b6e3adb9c71111ecbb1636cd7 +S027/S027R06.edf ca8bce6ff67b1815190481926ed96c73dbf0dbde4a2cab4f1545be725d04d685 +S027/S027R03.edf.event 57e9107b34629563ac9d22f509b6f40e40ebedb8afaca03c2199613287fc06ad +S027/S027R08.edf.event 8fbb43d322f1567ddece82c464cdf460a9df3070b5684895a7bfa7febb8e9950 +S027/S027R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S027/S027R14.edf 3035250ffd4e397cf1475df74263c66af7e2e9e04bad3319de9f92ebde448745 +S027/S027R07.edf ed97a6b4e01e5d5590da6bda8ab79197ed47a998932d391c2c950518aa8c17b7 +S027/S027R11.edf 9f361a90bac8599e7ff0132bd7524b6e12472d6bbd858ec2b75c70b6c4c70bc9 +S027/S027R09.edf 08e6788c429964dd22318fbbf5375a48047ee8e5b2b7a4fcab369ef3ba7019fa +S027/S027R07.edf.event 74fe6694983b37f44ede4efdbd00b6344db3ee7dfce3f27d06f5ec67ac6fc65e +S027/S027R13.edf 62d5ccdfb702cb9050a3243d3baea6466cf591c47c3544128daaadf33f736809 +S027/S027R05.edf.event 60706e2b67a15786207bcb87a2548eb3631153f455476ae03ec52b135003a858 +S027/S027R12.edf.event 5b005cafab5d6d8968aafc95da4c7b50e36cdf3bf2d71b98cd18431017101fcf +S027/S027R09.edf.event 11c7903b0dd963937962aeddd4ffb77feeec607958b581d996b712009c71f910 +S027/S027R12.edf d782cd20eb82862f4bb6f74f4fbd507ff2610480f581ccbc6ab885a60be94ac6 +S027/S027R08.edf bb50d3febb694639ff3d90cedae79d6f9531f4d6824919ebcc843254acc8cd96 +S027/S027R04.edf.event 710672ce0f425a207ef543d23f608683e1863d7423702d511235d71ccbd289cf +S027/S027R01.edf 16ae12914a9c301b652d64f1d6337e6e31edbc4f64f9c222c3670dd7157ecf21 +S027/S027R05.edf 7fdc9ad49431d5f713f883578426385d776b50787a08bff7e0a3a853952b4d62 +S027/S027R13.edf.event 0ff4d5f572885db930cfd469a0c25535d26e1712145e5a489a5e31e8a2020961 +S027/S027R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S027/S027R14.edf.event 91a58fdc6ac826e1cc60d1f6d7a8f3c395a374bee6c3fedb7e90d360410f8f97 +S027/S027R06.edf.event 37c09b028d07b5b1954199394e59b7c78fd1325c5fada30ce1411ada2513eb23 +S027/S027R10.edf.event 23b6fc268df2ca2b48b0a505a6eed055a62dad293041c180f6f03136d0f4b36e +S027/S027R03.edf 59493f105a7531b67e6cc52c1ace3c2fc248800077015c4dcb417b7c6ca6f3fb +S027/S027R10.edf 9fab75ae533d35878ef06a2e8ec6c623fcad251511a8c2dc81df8c332603b707 +S027/S027R02.edf c0ef16b97e2fff2692e400825728ca3c102b359634ac34a08fd2307f14b05d96 +S027/S027R11.edf.event 09d9d4cbfb435c34d0498269502687afe1e41cb410faf772b5fd4389e435ad7d +S027/S027R04.edf 4089acd89834f5aae1ea194c2d42b469b3dff95700554dbb4f0da68e91d94d48 +S040/S040R01.edf 45423b0cfc992bee8cede102265968d424d3731a6a7f2c8fb4a714f4ba3dfe61 +S040/S040R12.edf.event 27db1e140fad9d7a3cbfb7c99bf32f74d60de45fbaac18d08e05970e1ff5b49f +S040/S040R11.edf 693e9ccc55339199be31a7bc2099a26509855447ba1dd94cc8a32760ae9d67bf +S040/S040R11.edf.event b1046f2c937e8d05f2c3e45473ca880864a5d33222d740a0bee41b055662ea91 +S040/S040R14.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S040/S040R07.edf a9dbe8be9c65ff1bfea01eb7a87c68a8fcc59b0bf3a5e78d8b3361687c0ff0d0 +S040/S040R14.edf e439a81cf9c84fb35c9764ba5e760806fa638bb99fe0c222f9fca85e948cb72c +S040/S040R03.edf 0ad4d13fe0bdf89731358eb2ef45bfd1e3d6ccb5704ec601a5b548a18395beb5 +S040/S040R05.edf d3b0fff7acb44c5c07900ab3c3b86a63c188a86ad4c0506bafaf3303930c1dd1 +S040/S040R02.edf 3f9cb083e7c2677528a1f4d23243a062c3ea3498fde899803ae752fd29f9c2db +S040/S040R05.edf.event 3e83abe294ec7b278fb4495c4fbc171e9413e9d805ad8464dc6ea5a4875e7625 +S040/S040R08.edf.event 57636037048fc90c882a690b692342a1f4fd070d9f2a219d527ef6c0f7ea7dc1 +S040/S040R07.edf.event 212052daaa4c0fbc66f91923236861d93fc52f73403f6b4d988205287f1f9ece +S040/S040R04.edf 7e57eaba05275c3238d5fc60b1e696ffab146d578449abe50113f8b0dc388c12 +S040/S040R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S040/S040R09.edf 6b58a26d5f7914661d5f82c9e4e83fd1453af9b9b9452350d82ce5332f01d0d3 +S040/S040R12.edf 4039c3d1a84f9cf689592549332130bfcd37e6739d8e978046f1427af22b10d5 +S040/S040R04.edf.event ee9a506277766c8d64377864252176694f8cbdaac82a329d5cce5e9c11e2e529 +S040/S040R10.edf.event 037c923028aca24716dbc8d307c618e19d4e94bb1e759e5ddb8a9d3b6b205a86 +S040/S040R10.edf 5d6089202962ef26fa68fec40221916256c07e0fb7017fed0dd63ad9a9fe3fe6 +S040/S040R08.edf 941d55ce92107bf7cab012df55566d5dedb0f7b0f13a408dd0a4feeae2d16da8 +S040/S040R13.edf.event ed0acb0c9635a838cea852cecffa253bbee6e084a3404ea9ac9900188570c878 +S040/S040R13.edf 6bfe46c52dd085d36216c28f1dca46071de404bd33d630687ced49d948d1aa52 +S040/S040R06.edf 82f87f29942e399a8d0f996ee8132b8f0028f159826bf31416e1b98a5676017f +S040/S040R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S040/S040R06.edf.event 25eca6452bd9e487db46059b497ec8df5b6c353e97a2ac76ba8344fcc0797c79 +S040/S040R09.edf.event 07fe70f3f8a3bdbc31f5b573f0a7411d64d34385995e5b88892dc178ef898e16 +S040/S040R03.edf.event 1c886979e539efbac81a65fd3868773f73efb803324a60ebab5a203d75cdb97a +S043/S043R14.edf 60940854f70ceaf6fd2438544df485283deb3e6dbb2037b48a8f981e9d8e0fc8 +S043/S043R07.edf.event 8612fac39dad16048db3bea4e27be45fe67ced9a22781462eb9c6e435fe28d6d +S043/S043R03.edf.event e1c00064d3aa1fb0636aaf0dedd65aa66d02a8afcf3dd70b9a5fa4df4d4ebd47 +S043/S043R10.edf 050765b97761f0943cfd1f95fdb707a2b7cf52b26b8a2899a140bcaf502d3a20 +S043/S043R06.edf d58bdfae3036681d8f041ebd230537fe396023f8c42ed6f54003627b50c0dcd6 +S043/S043R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S043/S043R01.edf 49151f1f618da69d7de8bea138e21c0d1f7f9833bdc8b23a9a98c95dbf0120db +S043/S043R04.edf e841bfd7c22f200ed1999fd56466b9c13b05c5bfaf0c1ee30a2685827a137b85 +S043/S043R05.edf 649d2daf74d6bb33e922dea594322c90b35c8bbd9bcb75963fc170892ee4fdf6 +S043/S043R05.edf.event feeb9bf47f8f6dd0e083c64236055fd7ca30a06709747978b6a7bbc0b632e21c +S043/S043R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S043/S043R04.edf.event 01b8244e62aea11c106c000350e5b2ebec864736b68aa1525ea371fb86a3b0b2 +S043/S043R13.edf f51789ff14d721b809f205eefdca14e6bd57d6d63202a7624e19c1d6793e16aa +S043/S043R12.edf.event 08cefdab90cc2c4f915e80340ff4030bb291ede00b87eaa742fbe6a306942d05 +S043/S043R13.edf.event b9568e8466c8f90e1fe1f9aab8ddb73ea16c008b7b67cbbe5863f04f2ec408f0 +S043/S043R10.edf.event 9aaec3ff6fcd8c6d47bbf0c154dac87cdccac4bfb099e5995ee69afc7b34257b +S043/S043R02.edf 51f6d82c5ce4c53a4bc5477d3fa8decd78cc6e3656209b8324df9be0030f27b2 +S043/S043R07.edf e554299d7a61ac63e3c193c9cf968b0c921b20f644673417c767ade5f254e391 +S043/S043R09.edf 32f3a9cdad8dc71123ba983b7b30905dce563cf330d061374d69187d696d23f0 +S043/S043R09.edf.event 25eca6452bd9e487db46059b497ec8df5b6c353e97a2ac76ba8344fcc0797c79 +S043/S043R14.edf.event 8b26d9be3cec072b0ba8e7e1b1aa9f46dbf8f50992131d413440192fc40ccc5f +S043/S043R06.edf.event a788bd6a825d960534053c6559cb4f24cb7ee7a3164017d99c1dbc55f3b22215 +S043/S043R11.edf.event 43bc660a507d479ebfc1c782945c8504dc21abb3e55cd48acc2faf4db673e854 +S043/S043R03.edf 3bb31e415a5cc1b889c80b16473bd18ee5fb6cc8b03cbc2e57255a55e5564047 +S043/S043R12.edf 514e5dd961671fbc4e1e23f852ac6e82320be1ef8b65383602c368f6de946909 +S043/S043R08.edf 9359ced76df3828782fe5ab696efdef57b54e87be5363f2f3f07f8d4b3ac0adb +S043/S043R08.edf.event ea6f6003ddc3676cda270c185ba40fd7915630a24511085aeb31217c9a1e8852 +S043/S043R11.edf 6a70abdb1e96f21d02777643cd36113b950e99ffcd114ea4fbba8889f1114285 +S048/S048R07.edf.event e1ad9bc40c1368a9f08ea6dd90c3750fa2947ff48bcebe59b7e89441a2db68b8 +S048/S048R12.edf.event 50f12f26efafddcd994732349e4117055595d324e4dcff8fa56160baad5d5533 +S048/S048R13.edf cca277275339fcc530dd047960b75284bfc0c7af32ab695162c79189ee46abb3 +S048/S048R08.edf.event d0677488ead680ce24ed6d8a77105b8da3f0bd8cad38fff43732482c17bc4510 +S048/S048R11.edf.event 00eb5e22d01c3eaeb1626660a99e0c6fbf2f4423eed750224cc549752b7b6761 +S048/S048R11.edf d369c128d89f0d8a8e151eb2e335ff858836fad04c432c51db041807992d9844 +S048/S048R02.edf dba6cfa10d8bf65a0ecf681c3d1f7112bfc96e50eaa9c2782a52dc90fb81ef00 +S048/S048R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S048/S048R10.edf.event 20d3d791a72acbcdd619cb968567a104858a5889afc628a6fae4776c90c0780d +S048/S048R04.edf.event b7fc6043070236adccd2c6d2a291a12804c8a08c7d7b2194d31b1f6996080655 +S048/S048R01.edf c614f7a42eee90e494006d410917f21c7cc14e04f6cf86e0728437c636286171 +S048/S048R12.edf 9dbd643ce614d3b1c9e07190375fb04222e065c057d468f36b1141572e1490b2 +S048/S048R10.edf cb8c1bb4774306aacc0e3211444f9470dd0b89d73f5422b4b5c63450b495063d +S048/S048R05.edf ec79c9a93f997629556f37c47f408941813181d4bb8f02a191f0fe3bdf958afc +S048/S048R13.edf.event a6c871f2eb69757aec91f71c7de20007524b3b628f251799a3dd57bbb181fd84 +S048/S048R09.edf.event 6e9a969133a5a862400b62cb84f763eda38a0967078b1ebbfea1ca2ce8635b48 +S048/S048R05.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S048/S048R14.edf.event 82c4504914809d88b1ce13e11caa12c3a659e1a2edfab31c2e894283b14daba8 +S048/S048R04.edf 0916751e1b738588b93540043b78ea96f033b83ed87141a7cde6351409020d1c +S048/S048R03.edf 9c7ba6a229783276d59f9893fcf26a56d498bd4f231bbbdf1530315782b3775e +S048/S048R03.edf.event 48ad6251760a77acc67b82ce0b201f4244cd1385a6181c8236487af76fe1636b +S048/S048R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S048/S048R06.edf.event d6641564c0a8724abac8f919ad99064213b0fafe2c25f0d37d1cc67d83bda19c +S048/S048R07.edf 4b01ca005dd50ba06f1efe2bea065d30bff04204f5af10f18539747f7025e93a +S048/S048R09.edf 9d0481b4338cbc3d3070e53a9198e5d8d889fb692334ed32f8453d480dc0a3d8 +S048/S048R08.edf 5f519c4a10d3e18c4be0eb840be7be1022471594c46c451c3614712896feb669 +S048/S048R14.edf 234b83adaeb3c24523dc12a3c74a5271887cbc85ebd770095644dd373c27329b +S048/S048R06.edf 195f272f2e56fdd9e6b3151982c59bc5bdac42cbcf26cf75846872378ec317d9 +S028/S028R13.edf 780092ab1c7826d7d1fad8329cf8fcbb39c2b6a078314d018f64abc24b5fe47f +S028/S028R09.edf 27fce7d1a64a75ac16d6717161703a402cfaefe4756d27635df2635620e0cf47 +S028/S028R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S028/S028R08.edf.event 48bfdaa247bad1b393cff54386a6d30257090bf0e7327f31b2b320921da53270 +S028/S028R12.edf ce460f08c9ece9756e66c7e413e565d106676c865bd9a4fe6aa19097ff693bf7 +S028/S028R04.edf deee0e2e89467831f8d6d6ad4b142bbe5ffcf79a1e4dc993e1a52b5face5604a +S028/S028R07.edf c4059eefa097feea4b52bdf3aaa2684b2011c6f207668836ae461cf3ad4ef2d3 +S028/S028R11.edf.event 029131148bb6c782573739be6ec79dc67ade89f0b101169912d9c8201871bcd0 +S028/S028R10.edf d6eca0c406b75892a351c65d108546d27ed2d51fd31c0967427fa6115f6097a1 +S028/S028R05.edf.event c2f5111be300abf5d209c1908e46d378a7a94c2f8043fe6acf88665aab8efb02 +S028/S028R07.edf.event a6c871f2eb69757aec91f71c7de20007524b3b628f251799a3dd57bbb181fd84 +S028/S028R03.edf.event 7ee25d4d164dab7d909181d9ed3898053c69dd75d8affe3f277cb9ceac75184a +S028/S028R12.edf.event 985f9701733fcf2689c3a35bdb9e4b0058b6137ded5bc0f1a2a3b84431edb435 +S028/S028R01.edf 7aefa2fd7d92490654beb7deb417dd5e04c9d7c924716c16a48ee3d73ad6c3ce +S028/S028R09.edf.event 386c51194ef175e56c4d94b5e327133f39929095caa7c3ac86e89628f6fc0610 +S028/S028R10.edf.event 149997f77af08c9d6ad150aad5198f91c6c964c07e4d639baa770eac01012cfc +S028/S028R06.edf 04ad2d3a29a0f76a5f8840940bf87fbdcf6acb5d95c677e5bd69b2d259053d3d +S028/S028R03.edf 2137c12dbba064b5181dc83d7d385047ba7f33874679be51bc17bef2a566bdd6 +S028/S028R06.edf.event c2f5111be300abf5d209c1908e46d378a7a94c2f8043fe6acf88665aab8efb02 +S028/S028R11.edf 15e3a1a2c0f28b5856901f6ee4338cd65f98c3b3870b29ee7b5967d2fdc17e55 +S028/S028R04.edf.event c117ba4c66b5467903fddc4ed77a580e09639381683c611dd1f02cb0d311a4b5 +S028/S028R02.edf 3663ccafe904bbf31e929a7999a03e8c387aa645b5a90c8d11b0a8bf751f3d7d +S028/S028R14.edf.event 82c4504914809d88b1ce13e11caa12c3a659e1a2edfab31c2e894283b14daba8 +S028/S028R14.edf 3a2732e2965c9d8a56c1244bba7640b688177b6d2a13e7da4e3d934d25e00db9 +S028/S028R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S028/S028R08.edf f4faed4d95f419e54b95e5232155fa77af1a1a0a739bdc12b3bdfc6edb5f0a79 +S028/S028R05.edf e784563aaecbb0a085924511ecda4ac320a564f9e0dae2e70ba044dede5f8928 +S028/S028R13.edf.event 611df9f780acf887245656c2987fb77e486d2bc016936d00eea0a55d2f5c3028 +S045/S045R07.edf.event e19fc47bcf5b585ab27ad756884c0c4cd37d239bb04c8bf15e2f33fe9fe05e18 +S045/S045R12.edf.event 533737c87655572a20223c364be6c8be7a035cd8cf3dc42ed8c418e46e174661 +S045/S045R03.edf 14e948d21adce6478e71ef21dd9dea8bc3f1555518cf8927b2c33ac6feef4a13 +S045/S045R13.edf.event 91a58fdc6ac826e1cc60d1f6d7a8f3c395a374bee6c3fedb7e90d360410f8f97 +S045/S045R09.edf.event 732398d864936092994f6aa5c7a3d554d1c1c35ff4fd7a90dd0c06a61260c68b +S045/S045R05.edf.event d229cfdfcd562a5cfb40ea306452dab12d3ca82a70a465289b4c69c299fb0258 +S045/S045R06.edf 0a2348d5e52f55836b1154606d89d530f0fc914885cc334ec430c304f7a0627a +S045/S045R14.edf.event bd6dfaccdd7deb73743f500e0a1fa9d0ff333e94d59c6d153e2e9d2dc8a4795f +S045/S045R14.edf b7cb236b51fc8acf948277e703c2bfb04fe5515e3036a7a1d1c8df5a5333a837 +S045/S045R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S045/S045R08.edf.event 1c886979e539efbac81a65fd3868773f73efb803324a60ebab5a203d75cdb97a +S045/S045R03.edf.event 3764472ec04047763aeff3c1680cbc45cec3a88ed5f483d80cfbb31b50a12ac9 +S045/S045R07.edf c37669371b627ee9f63de41f8f276867f8defeff59489873eab0217a852ddf85 +S045/S045R02.edf 91c60dc17ea3b0c8a636b727f5d2caa9d84d6813bbc2a63b40a80d6186e8b75a +S045/S045R04.edf.event d45b05b6c6897898bdd688c12fad776011d39250bd1bd8de7e7745d939b60e3e +S045/S045R13.edf 5eebb9e7c81bc73766bd32d167005ac7dcb256155052e2bb9ab750f104c6efe2 +S045/S045R04.edf 655d2602c087d8f9efa32722bb32aceed76cab3c72570516df12e41458a25482 +S045/S045R10.edf 309184404b1ef8d649d7e8c6177b48a75fb4eaa655eb49d96a797f92b79d3b67 +S045/S045R10.edf.event a40b48032f894d3401affa4d6ccfd4defb4c639cf235451c5fbe2296febae7a1 +S045/S045R05.edf 3bc2887a902ebfa42449cd0d7bb5488d2f6fe6615072b2059639d119d62d76b8 +S045/S045R01.edf 99ed18a81e6d86970dcef27b3bf1ad6d4adf01477b4560aa5e198673de2992bf +S045/S045R12.edf 171f3487729fbbea555c923c74b8ce1e0f408aab10205cc95d2f498ba3220b2b +S045/S045R09.edf 2c5c79713d5127bf59e824029a0e5cba9a46badeb0ae94b0cd729d8dd1bfa26c +S045/S045R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S045/S045R11.edf 1517b91e4166540a416bd233b4ed77be080f740de5c25df6c52f60d61916b68e +S045/S045R08.edf 8e3ac9f836029bfdca587290743f5b7a190f2470f55fcdccbecf9eb7bb3aa40a +S045/S045R11.edf.event 3e83abe294ec7b278fb4495c4fbc171e9413e9d805ad8464dc6ea5a4875e7625 +S045/S045R06.edf.event a40b48032f894d3401affa4d6ccfd4defb4c639cf235451c5fbe2296febae7a1 +S109/S109R02.edf 006fc0cfb18c2084a453578484b2252b6c1dbe5608d73e20717a39b557a1d429 +S109/S109R03.edf e2adb0517ec78e1ea79e6dbc7aba14f16b56243b8dafe630ad57deec29b79d34 +S109/S109R09.edf.event 8a4b5822b251050d46b816bf54fbb47530d91210b6d01cc2e6acbe662193553d +S109/S109R05.edf 033bd271a8054992c658ccf79575e61d3e25d820188cca4f3bd563f899f05bf4 +S109/S109R06.edf.event c777015bef40a19f68f8ed8c37572f501bc00d9f061933697ce2f238c9ad3f9b +S109/S109R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S109/S109R01.edf 4547299bf4645e4afb08006d03b419e1273d4a3e853b8aa73d569e5a96dce8d0 +S109/S109R04.edf c267b8aa26c70924fc9cb9fc8596b351a83894490bab95325f738d68829aab3e +S109/S109R10.edf.event 85ffa4ceaf93483bfdb010c4404fa88a39a260f5371d86a551e206b015abd33d +S109/S109R12.edf.event a7dd5d461dbdafc68a647202ccb3decd039a172ca33d925065fad2be2efab6ab +S109/S109R07.edf 2dde459f8e061be6d581880e6fdcd6cfc1109ff7151729d82097fa8ad66ca50b +S109/S109R04.edf.event 48bfdaa247bad1b393cff54386a6d30257090bf0e7327f31b2b320921da53270 +S109/S109R12.edf b9f0f477c70ce519595b74c887af790c78c77a7f67279fabc7fba2989ee59782 +S109/S109R05.edf.event 6ca290c8f2ab5d2a3d0c42a123bd24341d790899e901dc5991dd66614dfb1842 +S109/S109R10.edf b147611b45da6fd50f0df50f78be9b4782f85a1d5b43edfc0d428ec519bf5012 +S109/S109R07.edf.event 4c374f58a91c1ff71894cacb50bfb798d20cbef67ee65a1ce8a2d5826349e390 +S109/S109R08.edf 879f8c8cda430e95bcda881f9cb1ede5e0693c9b83849d659e60082dd3e8706d +S109/S109R14.edf.event 1ccc28680a9b24af49105d307967ceb434f5229a29e70fbfde089b2d092db7c3 +S109/S109R13.edf.event e4c9fdcbbe3469b81dd48d30396ee921a23d45fb900a0dd3b7eb4ceaf04936a6 +S109/S109R06.edf 5a685c86cf1e3d85e6c7aa58d7d9eabf048d0e1192951777f30f97dfb675bf3e +S109/S109R09.edf 07fce275dae8835e1c4458ff66dd9e87805593e4169faeb025b60c55fbc637a7 +S109/S109R03.edf.event 6ca290c8f2ab5d2a3d0c42a123bd24341d790899e901dc5991dd66614dfb1842 +S109/S109R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S109/S109R08.edf.event 8e9579e89d1ec6576609e05f5e6215b4322a4c5375265379e3acd7952866ac83 +S109/S109R11.edf 7b5859aece6cd7b8d8a732ba372645d6885af1bf29da24a0a27a366dcc92021b +S109/S109R11.edf.event 0bddeca4a8cd621dca3130a2d5affe793bfed62c379600613bb61a6e554ec750 +S109/S109R14.edf 40ff8875daf98e4614854d1bb6bdf97b85b386b9caddc0dc944414fec0d049fe +S109/S109R13.edf aa94b64cd18a1b106471367ca9f2b3a16ca9c5669e637b8328d620df60a96a0c +S068/S068R11.edf 9993b459a0a3667c0b2810476632a71f9c6601f12516ce94c3e127fc8685687d +S068/S068R14.edf d5cba484c5cb43dc0bf4cdf4cb0ff098803b9d4b1f3fd8dd6c3f79006b58ba9d +S068/S068R14.edf.event 2eb503fa48ef7e13b77098d860c716de2d0eb55a3a0580117eb34aedd472a728 +S068/S068R08.edf d49374089836e11880347909fb5a358d6834303153e074f230be6caf0c66aa16 +S068/S068R10.edf.event e7ef0a3d66a5c814c6e917ac8f9bf83d6056810f78dd0c9296b5445289483fa5 +S068/S068R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S068/S068R07.edf.event 819461ff12613675eb0a26eec47ae680594adb9c6696c5e02f8e4b0d3731d56b +S068/S068R09.edf 171dbab1442c48f774cdab95e154d52e2dc9b8c3a20b01933ccaee264871dbbe +S068/S068R09.edf.event 01b8244e62aea11c106c000350e5b2ebec864736b68aa1525ea371fb86a3b0b2 +S068/S068R01.edf 7f528d62c8d4b342ff2f958ec6571d425f7d3926f0832ece121fa162efccab1c +S068/S068R04.edf.event 1b02f94c97b31c7b11129bd2f0db6eb71ffb209c8dc379625185f7a3726d3aff +S068/S068R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S068/S068R12.edf.event 3a8202a5a33eb8ffe91e329a5cb7a69f0647af677bc441cdc0bd0e11b3631c64 +S068/S068R06.edf 81a71170f71fd313c373612f474c6bc051481d5a831cba3f37e7b06c1d9935f4 +S068/S068R04.edf 7009d509684ab0b13b0253178ebf2b715a7ced2dee2b409969f088c3094f272f +S068/S068R13.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S068/S068R11.edf.event 2553cdc46c8017dc83d793a7cce6a36ddf99a043e777612539831e67f1aebc23 +S068/S068R06.edf.event 2da7955eedd5ec220793d3b4b3224c26256f1427c213729179eecd79fd4321c2 +S068/S068R13.edf bea2097a6ee72e37f7039b38cbd57af051dba76797ee83629d4c333c66a3d934 +S068/S068R05.edf 9f5307cda4c4be652743ce6fca4275d2614ec81c42968c1f9c46a22fdcd8a376 +S068/S068R05.edf.event af9bed6667136366cf88d2cd7f0f5fd9dda3fa51cc4cf73d3afe4d57dc8b7502 +S068/S068R08.edf.event 9825c80a69d06961cbce2e12cf8d0aa56d063e5f4598312c4e5b78693a0219c1 +S068/S068R07.edf bc4403c8c2186589008953fac143b4556e05b294fff29bae1de2151f9a7ad36b +S068/S068R02.edf b8207c54c2f123032ba589c1d69ebe39503cbd4f539e96935da842fdf9dcfd4d +S068/S068R03.edf.event d090cffefb3b3a6b7c514daaeff9edd2dc1c358aaa5ba0a069b62e257f59e09c +S068/S068R03.edf 2ce7f50663087ed5f90aa5a75583994c11b86e6556c2395d8cc327cd04599f4a +S068/S068R12.edf 966c9fe51563d5dd048482211d01eb1005130ebc14b5bc6ac89097b96ba9a5ab +S068/S068R10.edf 12250b352069cdef00d68d872a5c110a1098e5e7be6a77c0658f95ebea52a6a4 +S085/S085R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S085/S085R08.edf.event 8a4b5822b251050d46b816bf54fbb47530d91210b6d01cc2e6acbe662193553d +S085/S085R07.edf 67e6d9307b088dee4ab676419451931e4215372843e55c99f55629375fa1d61d +S085/S085R11.edf d2dbe9fbdf9e0a050f08811c18b25bc69a4a87abbca6c819ef96515b72147fe1 +S085/S085R07.edf.event f686071dd83e0610c6463f51dda1c01de1abacf998f19f9b7d3910c06492fc30 +S085/S085R13.edf 253e4d192802423c11f3d9ddb6ffa35c41a5fec990c71f04fe79d86f362836be +S085/S085R14.edf.event 04192a55fa7728d34533e76a1b831fe5c94d79c3bc9f1028f45644c51892a744 +S085/S085R03.edf 3723d3c37f3fc3b8ca7246de882e8ad2edea370284e4878f8a706d6bef0e2f8b +S085/S085R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S085/S085R12.edf bd78d9b98a9ba10ac7ba51cc213970da2f2c7a7f3238714b362017306d53983f +S085/S085R04.edf.event 74fe6694983b37f44ede4efdbd00b6344db3ee7dfce3f27d06f5ec67ac6fc65e +S085/S085R03.edf.event 0ff4d5f572885db930cfd469a0c25535d26e1712145e5a489a5e31e8a2020961 +S085/S085R09.edf b2f2fc7f0bb5a83d8876b40ff654d495a9882a4c046f4e7c9317a524e55a55c3 +S085/S085R08.edf 7da6a14c5b2722ddfa3962cb0b5580e3a5207c77154a6bac05c73d7f75e4409e +S085/S085R04.edf da0fbebf6dd7074cb3b71769f2a32259249b360e8ff03d832e99a02ae7a55090 +S085/S085R11.edf.event ecb3c28bfbaf7c670aa5547fa414949828cb36fcb3d84e0389aa669e01381627 +S085/S085R01.edf 378774575493af619ad20aa110604dc98be465894a7f82ce8ef815e3e58b51ec +S085/S085R10.edf 9d9fb1173e754a9b1ed6cd430c2f4b5418e52ae89878ad51c7f79d7a10244d60 +S085/S085R09.edf.event d090cffefb3b3a6b7c514daaeff9edd2dc1c358aaa5ba0a069b62e257f59e09c +S085/S085R13.edf.event 88e1ea56ed0459a99b011a3ea2f25f947016dd359b2d4fd683f838ac00d993d5 +S085/S085R05.edf 0caeea47c39fc638c03524b356f2fe749fff9ffad8fb3248c476c47c15766ca7 +S085/S085R12.edf.event 6546377ca20368b45bfd1f06c72e153809df57db54b8731ecceb6c8ec813a774 +S085/S085R10.edf.event 57636037048fc90c882a690b692342a1f4fd070d9f2a219d527ef6c0f7ea7dc1 +S085/S085R06.edf b5a691952339b9159eeda0ff49d33a1a05869254398761e4da70a5aca445e1a3 +S085/S085R02.edf a89c675ea2e6e0211aaea83cc2fe0d154bb1984c1ed836868f283f0f61b6c943 +S085/S085R14.edf 77a596bc1306b966accaf331af8501c3cc6dbdf66b0213993a11b189afc01a9f +S085/S085R06.edf.event 7925ab0749163820c00af5a617adba24f1ce1c711886e12def08eb72594e10cc +S085/S085R05.edf.event 2fa0b9392dbafefb266a1c269022274e4f4638513c85370c47ce925b54b7d5d6 +S050/S050R04.edf.event cfb6d9316552151b2cc7a4fe7b3c98b0ffddca0cea554883679586887149feba +S050/S050R01.edf 8407057efedd6e133b5e7b13caba82c90654d2697288d35b27b7fc33aeb4f522 +S050/S050R14.edf 4a11efcc5be7792041af8429b25cf7344e4c9c0adfa75d86bb06bbf8e870ff01 +S050/S050R08.edf.event b7fc6043070236adccd2c6d2a291a12804c8a08c7d7b2194d31b1f6996080655 +S050/S050R05.edf 59950256e03b968a6686c8d102efa843d7ed824e458597084be1a9a535a7d6d8 +S050/S050R10.edf 72174e570bfa31ece2dae5dad0ac8c242044784755bb9d6481a194a4a2b7e311 +S050/S050R06.edf 4b0d2ba3215359fe1b2a963c8ba0c94e0b10c08f33a0eb1c1da0e3bcb8c2617e +S050/S050R09.edf.event 6e4a2f2b413bd53735575eeda52d35059687bb58d072e4de1626bc16d7a28d24 +S050/S050R11.edf.event 08d1f10d75e3c7f02ed234fdfe64948be5fa14e26fb27441a377ebf76532dc50 +S050/S050R06.edf.event a18bb793691db61833ea9b3b10da118a6687892d063d72ae795055c9209ba8ef +S050/S050R04.edf d2068d794befef727cb907835cf04cbc357e16ef90766ca22917dd4b4649df85 +S050/S050R07.edf.event 08d1f10d75e3c7f02ed234fdfe64948be5fa14e26fb27441a377ebf76532dc50 +S050/S050R02.edf e4d2e4444e5dd830417f8729a549daba168d49e2f2db6467f44aa75ab9554474 +S050/S050R09.edf 15c17c5266b4c46e49e454b455dd4fc9cba0cc2ed670b64f47440c5e96e814d4 +S050/S050R03.edf.event e14dc31d476c11841d45564cac660be9776fccedd3dec71dcee4c5232f00f25c +S050/S050R07.edf 0b0435ff445199521d9d11589e69bb0940f7c4878f6546dcb7d65d0dc52fdfea +S050/S050R05.edf.event efa5d828429e8df393cf3e5b452a00dc9f05f3ad9eeeeb119ad18eafd1cc4e2a +S050/S050R08.edf 211a70a072988cc85fbab6e28b0e0550c18d22225dda82a9471a980447eafcf9 +S050/S050R13.edf 2a586af9a1e31ef0bce58d53c92c55c0c1ad670b301711c669daafa2fc452dfd +S050/S050R14.edf.event 1f581da8e4856c63e25c541381ff8a370d89525260484c85de24ca995a24a984 +S050/S050R13.edf.event 9787b103ae02f348ebe837cf8e545e3e630609a320868cfa229f0f82a0734ddd +S050/S050R03.edf 114ffd39341cdf2375d4762190ee4d8b893c0468e02f4c8a413b183432fd44b5 +S050/S050R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S050/S050R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S050/S050R12.edf.event 2b0cd50273254147215db0f2d93c0e409b2279fe37afd6cc7d86edb7df57486d +S050/S050R12.edf ae1fa0a96ddbcf2f2e55f1df26fb90c4bfe439bf0bacb89c03579c0308ea1180 +S050/S050R11.edf 16d0f476a75c5ce8c0dd1e99bbfc8ac1cd0ad72804b9dd76e6803ccc6b4f3b1c +S050/S050R10.edf.event 7ee25d4d164dab7d909181d9ed3898053c69dd75d8affe3f277cb9ceac75184a +S049/S049R07.edf.event de55d737a8555e174e0cd004746337287c294a01d42348abe972b98f07739b4c +S049/S049R14.edf.event 07fe70f3f8a3bdbc31f5b573f0a7411d64d34385995e5b88892dc178ef898e16 +S049/S049R10.edf.event 6ad812d50b44ed49ee87e09d1cf28b68a99855b6d266be8b9017d8056de057b4 +S049/S049R09.edf.event 6558be2dc3366ecd25198b4561d2d6a49bf257ea06005bb7804aa7c5f9bb7c8b +S049/S049R03.edf faff4a3b9f549956039d5fc56f6a3a69666a722767b52672d10057c3af3bd32c +S049/S049R13.edf.event 43bc660a507d479ebfc1c782945c8504dc21abb3e55cd48acc2faf4db673e854 +S049/S049R06.edf 0d6e568a62a15ada1889fbced43069e0c2d5ca1dbb5fede5484a954af40bd079 +S049/S049R08.edf.event 9a154a517e2cf402786cffa7d164d0656aa7a8bb30af51266fc6403fcd9d3d00 +S049/S049R02.edf 1a717c22907a799d191aa1e34b4702d5429359f0d10419ae64aa3baf6d4a9241 +S049/S049R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S049/S049R11.edf b90f50b60a229cc4426527b09711ce720932165fa23d427cee871f13e3b372bd +S049/S049R13.edf dd9504e0120ce5876437f1fbd0ffc150bb6e713550ac818fa7f1b165571b0b47 +S049/S049R07.edf 7a290ed431af3fc57e9e8dd41e383ec8a734fc59240eeced59872f32ca117723 +S049/S049R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S049/S049R01.edf bdfcb91b7c914a621617d59cd6f132c9f3229f64f22084e57904232e84c2eaf9 +S049/S049R11.edf.event 0d4308120129d0f92d2b8779374ae232f98d1357e6c6427983fed655d9611af0 +S049/S049R14.edf 22d3b7e7e6efeae214e237437447f3928214f5d174413f03a113613bb8840771 +S049/S049R05.edf b6eeb2d843cdaacd5316dbe64a15a8332397ce454a657e887fa9ffeb9c335984 +S049/S049R12.edf.event f45bf8e0fbc90d9616344960adaf0ce8357cfa7171b36030a957f85c93267870 +S049/S049R03.edf.event 596ad948f8aa9dfdc6cd3125a3d02e115d1cd6a505023467bf5cd721125ee7fb +S049/S049R08.edf 449bc4afe04a06d018e6a4385144253bdbea91334af3be4f59165883be2c46a5 +S049/S049R10.edf 901196f4f5fd3d9cfec28a04d581bb0e91b43bd6c1815655f112755f7536efed +S049/S049R04.edf.event cd91d83b7ed2080d3d803a7381c00951232c99bd8107647556298a104a0ce8c0 +S049/S049R04.edf a481efa8e833cdc64e9f0a3a5c082ac1765462d4f134beb46a3439acb40323f8 +S049/S049R12.edf 37ac2679e0f9b35f879dd80255dad13f27fda1950a5182eddcee5cab8dc6e8ef +S049/S049R06.edf.event 533737c87655572a20223c364be6c8be7a035cd8cf3dc42ed8c418e46e174661 +S049/S049R09.edf c21b03a3947c630f19e63796321c31088c9b1fd082a4d43b8de813e2140cfb9c +S049/S049R05.edf.event ee9a506277766c8d64377864252176694f8cbdaac82a329d5cce5e9c11e2e529 +S003/S003R13.edf.event f08aa591d71f3207481623462ebe22d9e72781bd8f6adce3738257c0be7ed7f5 +S003/S003R10.edf 99429f0075f59216a10b75eea4029a7ded7bccec34d17100b08a55770cf1f014 +S003/S003R03.edf ebf184ea51d9aa3178190583f428db02f184e22412ff300a5f224776d1e8dbb4 +S003/S003R03.edf.event c9ceffa934dbf8716d8f84a8ab3a0d227c746d5d4fd50627350da4bfc6029e39 +S003/S003R11.edf 0563c2a26f759d849d6b99b3efb6047d1e1d288f80c0c16f5f07403bd0029271 +S003/S003R07.edf.event 92b3e8a6b67a6846154b1244f9044558257134f17b25840c7f71206ad195584e +S003/S003R09.edf e871d2d855a538f653e1e71c4181f1e2b0b5eba59ef698328908cd8511dfdf58 +S003/S003R13.edf db14ae5f0e58a25593fdf9a71c60a80540e06fac158ecf0c28380c7fe54c02d8 +S003/S003R10.edf.event d192ea57ff85ecd8427faf400415c2002cb41aa1189199e0c6ed62a7ecd048c1 +S003/S003R06.edf.event 1056a6ae091909b3aed4f5a2b6e53c4083bb73cd4929def393a94ea0f5953f0d +S003/S003R12.edf.event cfccf092791e4f541cc50e2a8c3317df4e3eaf04f099301c7f827e7dffd9c354 +S003/S003R02.edf 41044fea497e05650c4b1f4009011b44a50a6cefd55d5afa9e1d1b7988afd6e5 +S003/S003R01.edf 2af68afa8d4f158a7ae7f3903b66f0947925880639b7a8b5b6bb13b0c6c50f96 +S003/S003R06.edf 8d48a46397416bbea19eb6b97474aaade72029364231202295bbda805ed79c97 +S003/S003R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S003/S003R04.edf 7d0732eea963488a53153835524e55c2b68220b0a0c7c5be99e535a9f5367e7f +S003/S003R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S003/S003R05.edf.event f73e764c2a5687f81917e5c4eaa8b964ecb99e4c58ff33aa7e02e5fe1f655a98 +S003/S003R07.edf d8a610bf60a19c1d653a11633f7df40bd7b3eca976bebf2b525eb65017fdf044 +S003/S003R11.edf.event 94d1d7007146c80e4f45e873986a770b4b807a34cfeca23f6a7d9054865154c1 +S003/S003R14.edf c80a7a0fab93074cdead76450b49ba8d27b7183f1baa406daf5207d2c1825194 +S003/S003R08.edf 0f50978bb972e693b8c758a9223a2d9fa35c7f117226391090bcc32a83ce765d +S003/S003R04.edf.event 53726fe905bea0abe513d5e84fd629ed577ff03739fbd56c6a12198e7cca5cc0 +S003/S003R12.edf bbf7137bfa7905724741e95359fa090439d4422c07bdba16c792acb09ebd6421 +S003/S003R08.edf.event a3a021aa3014366fda2210569cdbdc257724ba6d0d11b1e6c924103e837c7294 +S003/S003R05.edf 847632c525a231a97e61cd942fe8f4205b2138764f14cecd62f76621287efacd +S003/S003R14.edf.event 1513629f6e8e700394421b828869afdbd4e2ccdf8bdbed2127f75a42b2db3ff4 +S003/S003R09.edf.event 99a46eb7d9a4fa08a856556abfd134cec7b55f86ee94c1eedc9b0b5214911db9 +S108/S108R13.edf.event c777015bef40a19f68f8ed8c37572f501bc00d9f061933697ce2f238c9ad3f9b +S108/S108R06.edf 79c8e5268af37c118dd3b380918b58ccbd90ef51a44f571d6b718929322be16b +S108/S108R05.edf.event fd77510c7ae392a42ed020605a40066a43ea3dcf80082d17cfd95141d71549ae +S108/S108R07.edf.event de55d737a8555e174e0cd004746337287c294a01d42348abe972b98f07739b4c +S108/S108R12.edf 424aa46e174d38f3395647a591c20aedcecf29989f98a6006a77502af9a2add7 +S108/S108R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S108/S108R08.edf.event 176fd10c94c5d482875b1ae7f0756ac60194f41bba099b0b40e5efd4e95e8df7 +S108/S108R14.edf.event 82c4504914809d88b1ce13e11caa12c3a659e1a2edfab31c2e894283b14daba8 +S108/S108R13.edf 0708199ca4f0fa026eb23ded19eb6de66c62db605db7df8129696f6d4fec1b64 +S108/S108R11.edf 7826876fcdac9aff4bfcc44cd2417a844673aa3d15a3d14bdc16c86eb6c51e26 +S108/S108R04.edf 7c56ee104d1b080834992d79fcfdf9f995965f0a416a66fed454784486d97d40 +S108/S108R01.edf 2115183a713af1edb4ddbda03f35712340a2e1bfdc62f825e2b73f495d421291 +S108/S108R07.edf 53f4d5dcaa3e7acbee5762e68d7d3552954df9f4e46c5cc232c2cbb794c3deb8 +S108/S108R09.edf.event a18bb793691db61833ea9b3b10da118a6687892d063d72ae795055c9209ba8ef +S108/S108R03.edf ebe6c07ca779b1226b3dc11ee2d46877fd5d3a94d1fe9f97fa5c2161f16cbade +S108/S108R04.edf.event a730605f9838282a7ec09530538d4f4dc6f2f5cf73c8f2e85944d5e8297c441e +S108/S108R10.edf da4adc3a144f5699b4a4facd89dc85a4617170ae84828ad0a909d154979751a8 +S108/S108R14.edf c51f9e98fc6c4dab6a73fe3ec7363e3ae2c721cde414a46cf4e1fad1bf9d81ff +S108/S108R03.edf.event f1d7c85c7c4b298aa795662274613ada05d95ec81ad8b21ce4c8ddca5a11ecdc +S108/S108R06.edf.event 4ca96a0e24908b831c877816b86e3dbd1eee397d9d9851bd1e890d67134c57a0 +S108/S108R02.edf 2e117bc915d3720afd714e82f1769b0f8a1f040e39ba735fd1c3d2f0e704301a +S108/S108R08.edf 472179c1c0efd3662cbd47ae8ab1be2aef9ec8db8344c086f79c3ac2cd5b5fd3 +S108/S108R05.edf 5073bba54535642aa061d4cffdca53a981c06069f7c5ebca3a8e18953cde928f +S108/S108R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S108/S108R11.edf.event 082acf669cebc89d5f5f4bf29769c743f3b1e14290b8f0f34415e285db553b3a +S108/S108R09.edf 91bc85098b6ae4e93c859dd7e1f606d48b7d83d9bae3b54eb0db4dc7db876ce9 +S108/S108R12.edf.event efa5d828429e8df393cf3e5b452a00dc9f05f3ad9eeeeb119ad18eafd1cc4e2a +S108/S108R10.edf.event a5608231854f8f457c107c9acdfead912cd6d55fc459b7abc2f11d77bb166129 +S060/S060R10.edf.event f39b724630cf39de64096da55e80ef4acde232132367bdb459b9a4b872fdabb8 +S060/S060R05.edf.event b7ad55e8ce55c5743b2d7e417e77c8d7efdeba7b6cbbddb02fe11361879eb9a4 +S060/S060R07.edf 17a7012187c8be76959586c37b5d8cce35add75d601f254a683a8b805a62e404 +S060/S060R03.edf 7b6a4c4b50ae82d8dda38d58dbf4a63668a6ca241c230b110bdba481088116e5 +S060/S060R03.edf.event af55de06274e9f057a8c2b10bb8a4665c70ab950b43d066ea9e3d1de5f188b79 +S060/S060R12.edf.event 818acb17a86d3ee6425a512fab58b363d01b6ccc783417cdad466d1ecddc506f +S060/S060R14.edf.event 029131148bb6c782573739be6ec79dc67ade89f0b101169912d9c8201871bcd0 +S060/S060R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S060/S060R06.edf 19abfd9e28c5d02166a4ef1753ba504c745faee53d28c4943f53a577c76e5b32 +S060/S060R10.edf 93ba02bbc1b91007849214d6cf0330402d55d993357bb70bfd8dc781f96464a3 +S060/S060R01.edf ae25d2c837966144341798b0bd0cbcba1b0eddd28a6b31502f813a41fd6ad1d5 +S060/S060R08.edf.event 01b8244e62aea11c106c000350e5b2ebec864736b68aa1525ea371fb86a3b0b2 +S060/S060R02.edf 597c676b123c5e834048a91035349ce2f72116eef1b80c64602587def6354ad5 +S060/S060R05.edf dc2b1b2ad165e2edceb0fe2634b2885c9f122afb571bb8830758ed8579192400 +S060/S060R04.edf 9547bdc9013bf74161abaae66f3f30453c159a4a0ad7f030a1d527538250ab59 +S060/S060R04.edf.event 931266ffca879dea17f50ad227bae49a0d891b282f30fa3ee4b13ab8623dc5eb +S060/S060R09.edf 6ad2e283d739177eb6fa17c421b3a40b1b9b65c8645dd39ccc2bc491ac70f7e1 +S060/S060R08.edf 5f6411e04fc1fa14636a78f15a8bb49dfbd765fd5f7d9c3c3357044a9037aaec +S060/S060R11.edf.event e16d907d8f296edaf98d1ab54138ee16bae85a4bd81d90a487ccfece5b611fd7 +S060/S060R11.edf c33e3465474c7640dd8d58f7633c4055b85a13199f324cb77246107cb80690a2 +S060/S060R09.edf.event cfb6d9316552151b2cc7a4fe7b3c98b0ffddca0cea554883679586887149feba +S060/S060R06.edf.event 13968dcd0074afe70c79ea250f7148e28870c5b0140104f078a501fd3b51ed69 +S060/S060R12.edf 8b1954f873ac2e1c741522541e4d02e1ff8beede7434a5ccff36cc356d9b95c0 +S060/S060R13.edf 5faf02a9d111e48f09fc40c4ae2906385c37ecd9e62be423e12399215463e21f +S060/S060R14.edf 546122a56dd778291a7867d913093f1605b85ebbbc63cfcb5bae93cb360a0d96 +S060/S060R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S060/S060R13.edf.event 6e13e4f708f4b769dde500a1db747206aa87951c3914cdd436fb7f07e9aa5052 +S060/S060R07.edf.event 8612fac39dad16048db3bea4e27be45fe67ced9a22781462eb9c6e435fe28d6d +S055/S055R07.edf.event 1c886979e539efbac81a65fd3868773f73efb803324a60ebab5a203d75cdb97a +S055/S055R03.edf 5a700147e53e7659c57d78b15dc2590378d5549edc35631fd7302c7847c5569c +S055/S055R09.edf.event a931510ec25c8e6b0352576ca7f98b414a922451f0a6ee6aab03d3409a677c66 +S055/S055R13.edf 8a1182a5eabd260a4d09929bf2b503bcaa5a24ec18c13b9cf525b06e39d787e7 +S055/S055R12.edf 2e9307c91262be0c77efaebd886f75b7e3c11729a9688cada4b5767e7f7490a1 +S055/S055R12.edf.event 9787b103ae02f348ebe837cf8e545e3e630609a320868cfa229f0f82a0734ddd +S055/S055R11.edf 7715df0df55699795e90e5de10cfb1e1b1d60ae7351b81672ebac9fb566ad33b +S055/S055R06.edf db7897ba36039a65f10d8197a3947c6c64d9ed478b9ba21a1a443440243a06af +S055/S055R10.edf 6ec12775870d4e1a563ea51f7eca8dc75528bb283e10dfdf9817066afded8ecb +S055/S055R04.edf.event 00929d2d58d65a270182e61a69c5c896d7083a039df6ae5b3e35e318a811d1aa +S055/S055R14.edf e96ddb32c6f99774a78634ee17e2f8da83a84ac51eb2a3de02262bfde2549f30 +S055/S055R01.edf 38df022c18db1a69e74261fefd85f397b0b55b457384c4c7208ef00f7f6231c6 +S055/S055R06.edf.event 2553cdc46c8017dc83d793a7cce6a36ddf99a043e777612539831e67f1aebc23 +S055/S055R05.edf.event 01b8244e62aea11c106c000350e5b2ebec864736b68aa1525ea371fb86a3b0b2 +S055/S055R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S055/S055R10.edf.event fb7055ba8adb05cadd3009cfa9adefacc5298e01d2b7156815f6424ce1d4f3f6 +S055/S055R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S055/S055R08.edf 808e0060198a3c0189860aa2b92b768f1764c4441eee72af3a01d6014dd81176 +S055/S055R04.edf 5626401f88b26ca66d9621f300a98c0fd80bba41438380dddba05111c8721d36 +S055/S055R05.edf 8afe70b47200e2163b1d57af89eb7eef854cefd1747a938ab21b90120bfb1f15 +S055/S055R09.edf 0cf04dae0b3ba9d249aeeac77e339a5f48f434eb667b901ca65f08b30dfd6c65 +S055/S055R03.edf.event 037c923028aca24716dbc8d307c618e19d4e94bb1e759e5ddb8a9d3b6b205a86 +S055/S055R08.edf.event 9a16113810c1d4f4c6d4bb0e9fa5ea774628a0b8f3e1764e93d71da831cb206e +S055/S055R11.edf.event 350042ca5c37cad9cabe8c469aead2bd074d996b13c69cafba8d24cd8fd825fb +S055/S055R07.edf fb8ba11d022fb1e8b8df561e6eaa84f745cb51c14872e6fbdc4361c4cc14aa01 +S055/S055R02.edf e872c1d3f02e88cd7c040953e4693c851899a0e3020e85aec1373db26cb1503b +S055/S055R14.edf.event 91a58fdc6ac826e1cc60d1f6d7a8f3c395a374bee6c3fedb7e90d360410f8f97 +S055/S055R13.edf.event 596ad948f8aa9dfdc6cd3125a3d02e115d1cd6a505023467bf5cd721125ee7fb +S037/S037R03.edf b08e4b04625ff65ddacad42cdfc403952e391e976ca1451c6c485f6477f290ab +S037/S037R01.edf 51182f52a9316783ef7d393bc1354efcac916524dfa826b3519b132bf516f7db +S037/S037R10.edf.event a3605df98453cf17b0c003ae26ea3b82e48e5080e12c7d92eaa104fb30571adb +S037/S037R13.edf 14b5137aa15c2ba7ee9d1b441f7207c82ea3456a6051eec3062e0037d31bb1a1 +S037/S037R06.edf.event 6c457793161b0b2dafe7d78bf4d750a570530145b98ce0bb007627422152b0f2 +S037/S037R13.edf.event ed3cf1bb44b1d2c21282c844044e08add0a9e1ba501a19ac91fd1593cb7a0f90 +S037/S037R08.edf.event fa3c7a187a7f8a7aebf8ef9cc11c0a206ae8b7b11512d6753899c156e88d5394 +S037/S037R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S037/S037R09.edf.event 10fe2ea57f3dd20adb3824338de616d484101e5955b8607ce38e43162b4cf53d +S037/S037R08.edf 7b21a0f65631f91e46812aac3a2c3d46b9da9e847b2d0289f618419827973e4d +S037/S037R07.edf 483eff50a97ecc856ad5e5cecf01a630d3e11dd64b454ef61a091d30accf133d +S037/S037R06.edf 7aa020ed64d5fbbacbb5d44fb6aaf1fef2bc6d97c5e55a2827f7620055652b34 +S037/S037R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S037/S037R05.edf.event f751705cb1ac76297342f42e431acdcfbf89711a08d63c261434f3584d3edf77 +S037/S037R04.edf.event 30da64dda979b788f6866a64bdbb871697aea2971b00b19bb12b45eb03c9e13b +S037/S037R12.edf ca053b2a09045e39cd0ecf2d7f50e4c067a515becfaaa7ade1f4dd4a06f91b6a +S037/S037R12.edf.event 20b9488db0142f8af79f3a1f6669aa603fafc46d3617ebab296207f1df9f4c2e +S037/S037R04.edf 058d115743bbd3a114a21aa839415312b7210f4aabba8260ec7b9b471430c17a +S037/S037R05.edf 7ee430473a18c6dc76f1635a6a5d5b439de3f873fc83c07016d0508ec991dde9 +S037/S037R03.edf.event 3ebf8a974399c5878d02e333c8cea9226287a30a0ba2f22d93f03dda6fc523e0 +S037/S037R14.edf a3c62714157519822f6820b551505a2329b01ae4359ba6f1099e99b513418dd5 +S037/S037R09.edf 7979da78867d6d4091a4ef919e82fe0e6c7b03727f7f3d67a3dc7718ae9ef502 +S037/S037R10.edf 89a3de5959e5855294d1b86d14b1648909d4c2657fba6a2da289d00364eafd03 +S037/S037R11.edf 8bb1b09e6bba588a17be875f46d33e86a9fcf37dbeebcca51910d636de6b5df8 +S037/S037R14.edf.event 5bbe935f4d605f380ecfc838403e37a58fa59da73118602632e00558c003c171 +S037/S037R11.edf.event 2b4e8c33ee0adfbf5ea0a5dc317f8f76f92419263cf693730153cd417ff4bcf5 +S037/S037R07.edf.event d0350c9c71f7bf60173004774cb340f2afa23c26f3c0b859574afb0514a062a8 +S037/S037R02.edf 9d4da39ddfef739b7a2b0b4fc6e9a748cce3c227c665f6a05fcc8a7da91feb9f +S058/S058R13.edf.event a18bb793691db61833ea9b3b10da118a6687892d063d72ae795055c9209ba8ef +S058/S058R12.edf ec035945aa497928bca1ae1387f50f06b68f346a992e9525afd3f91f74c081da +S058/S058R12.edf.event 96cef3a9a9e2cd7f438d53008e256b198c48c6e0d2f0b2d70e0d296180cd58b0 +S058/S058R04.edf 4e52357fdd5f23f7acff7de83d870b946d3225885ea77b60f2ef6c2f889221d0 +S058/S058R03.edf.event 49dac749bf850e47e5d13a8edef5121c75a7baa7f50917a5c17c1dda52d3013e +S058/S058R10.edf.event a788bd6a825d960534053c6559cb4f24cb7ee7a3164017d99c1dbc55f3b22215 +S058/S058R14.edf 09de80fabf5bfdbc914150d0bb1af7e53f59be055dd2823534fc9d47f9584764 +S058/S058R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S058/S058R09.edf.event 8fb228960cd397f6100e75cca49e1045159bf62e6184dd5267ea608be1d540b6 +S058/S058R06.edf 299a82dbf807ad746e2adf9ed15fc373f60e9b5770ea8a39c76e1a46e1e41360 +S058/S058R01.edf 6a3d55038d5198b06772b43243f2009436a23c41696e98b57d8d98acd2008df1 +S058/S058R05.edf.event 0c671e4e4ff7b21e4f75cb8796305c57d6ee3fc48e74337e26c3b9f5d49408ee +S058/S058R07.edf.event e7ef0a3d66a5c814c6e917ac8f9bf83d6056810f78dd0c9296b5445289483fa5 +S058/S058R11.edf.event 98da35a4768842863f8f05d63e959a36f12126a205e0370d8519299fc06e56ec +S058/S058R07.edf be2e3cf48c68ab002ca78bac6f055b3bfc8e6597e07033bb868b0393c7a8a0d7 +S058/S058R11.edf 4b079809ac45a8aaae9feb663e7a37501c02c3c67ce1e2399bafd49ff5b9f7d6 +S058/S058R13.edf 2eaac3fa4afade6e1772235fb0a7a8ffb5f1c1c1fa0bfb4a9ed97373a0a59d24 +S058/S058R03.edf d974afce72f8c832de47fb809125fa6f78bf6b32558cc468c62c554078d30d3f +S058/S058R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S058/S058R04.edf.event c6fd76cba5a912b92a280d7d54b9158146ba5522f81d9192baecc014a6c9149c +S058/S058R05.edf a389493fb0ae8a74d30a8e69db8d16045b53d0c8bbebde7902953db44cf012e9 +S058/S058R06.edf.event 2da7955eedd5ec220793d3b4b3224c26256f1427c213729179eecd79fd4321c2 +S058/S058R08.edf.event 5bca2030ba3ea66c594c376bfc5a701d3f25c2f85ea7d72b8abb2b2bbc5644ba +S058/S058R08.edf 156b9fd913d2277dcf4fd553f77b9a842992671d3f0b250e16c485b66c3aebf2 +S058/S058R14.edf.event 820bcb0b8aa75c06572fb3677af8b965e06ca92c0ff5f4eabd0d347c7b141680 +S058/S058R02.edf 1ccaa3ea370002190f9d69c0f799c2e061050388e12ff37acd8d69e09f34d5d8 +S058/S058R10.edf 889d23e02b38dae04ef10f756badfeb26f7675af6481a9a033e6b84913e5999e +S058/S058R09.edf f8e9caa438bcc4daaa18f12f0ce70ab74b200c6361dc5b5d7212d3e4a505f277 +S094/S094R04.edf.event fd77510c7ae392a42ed020605a40066a43ea3dcf80082d17cfd95141d71549ae +S094/S094R06.edf ff3769b67a9d0ef29467c4fe73ab47134557baae366284dff40c4e217cecb006 +S094/S094R13.edf de8815227485510ea171fef9903c358a23467caa82d8adfd8a61c65321c88a2a +S094/S094R05.edf b6a7f75293a4d26c06c33f34726ab89b28010fea614e1b4aa61c5de6e9906be4 +S094/S094R07.edf.event ffbdc0e528335775cb88a14baab7b7f1fff4fa1647a473bcd640feefcbfab5a3 +S094/S094R09.edf 0f51c986bb317505fe7d6c4d1df17ac5ee1cdc4cf5d5f45664c86f9afd825b78 +S094/S094R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S094/S094R13.edf.event 7c83be0506163b52a89548c7af6d4893472403c2bab3a455c7d8c92bf3550ad8 +S094/S094R08.edf.event 176fd10c94c5d482875b1ae7f0756ac60194f41bba099b0b40e5efd4e95e8df7 +S094/S094R07.edf 9aa5ec681860884f534e93a56e10cb276dca8b092435483abdde2b853df35c07 +S094/S094R04.edf 41b63eedefea1796e9289de2ead00b6e03bc6f8319cabe1cd293c981c4cfc406 +S094/S094R03.edf ceed432815df2089c58aff28a7a9bf37b3d5cf7ef61825a717dc0fd414f6a54a +S094/S094R03.edf.event 4e057b134c286502a0bd4e491daa0ebb3c4bfdc21b738b2ba2453c8ffc558218 +S094/S094R11.edf.event 1ccc28680a9b24af49105d307967ceb434f5229a29e70fbfde089b2d092db7c3 +S094/S094R10.edf 187f1af97f51fb5add42e3b511e70ce7ae19d30982f9e7c2901c9ee1aefd15c1 +S094/S094R02.edf 5f08c5aaf8e21015ae6fce4a8f8e6e6e658df662e393ec77fc75689bb0a94c63 +S094/S094R01.edf b11fbdf3f5ecd11daaad702b58bdabaf1f15c82f045b7ed53dfd88855271a5bc +S094/S094R14.edf 4111e5c2b5d385cc8f0e5c7ba9757d8deac4cd9c969e44c4008593e78a5f7c70 +S094/S094R05.edf.event e1b29e90b20be6fe74d2526e8f695d3e9dfe8bdd7f08c801c24f523ac253462a +S094/S094R11.edf d07dc1f9703a53caf60c3eff7de342cd54264a3077e6c7975efa20adff7c52fd +S094/S094R14.edf.event 017d78426c2e9f2b1807cc35ed07405ab8ff157014df0701b8524f965539b319 +S094/S094R10.edf.event 2d33f0e6820d6c85c1b096ad02de0f117c60e1202edb58aad42f3ec835f3162b +S094/S094R12.edf 2f70c608f9e291559ca1e135824ea1c8aa44eccdae35bd18705d5574abc68523 +S094/S094R08.edf a265132a093b20b1366ebdd17e77628a0b4feb3b02cf7c037fb092a03a1f47dd +S094/S094R12.edf.event d45b05b6c6897898bdd688c12fad776011d39250bd1bd8de7e7745d939b60e3e +S094/S094R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S094/S094R06.edf.event e2b79b09413cc4065a25ea2956bc7726f4bdedc8730e89a7b86a8617c79876c8 +S094/S094R09.edf.event d229cfdfcd562a5cfb40ea306452dab12d3ca82a70a465289b4c69c299fb0258 +S053/S053R03.edf.event fd77510c7ae392a42ed020605a40066a43ea3dcf80082d17cfd95141d71549ae +S053/S053R05.edf aa23445a5c64286f876853e2d68046fd2e21e01f0d3c6f12767d7078edc63bdb +S053/S053R10.edf.event 83a13523a9ab3f80c3d6e974582a163a305c3619a795d4e26af679735769b3ed +S053/S053R07.edf.event ee9a506277766c8d64377864252176694f8cbdaac82a329d5cce5e9c11e2e529 +S053/S053R14.edf 6f555682d43d8e95f69dc2805bd305d253147b28b6641ee038956ee667a96233 +S053/S053R06.edf 9151463be662a8961ad6e26b3ac320e1f3fa22792e3a5a48685f1fdea17518e7 +S053/S053R09.edf.event 3593f38db6b9b0b72284e6ea58a9169bb2459a37f75643fd634363b665a636d9 +S053/S053R08.edf.event 8553d29b6f3410b4ee7ebd3f65050ee16a492ed893d0bc9a14cf35cfa904d586 +S053/S053R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S053/S053R12.edf.event efa5d828429e8df393cf3e5b452a00dc9f05f3ad9eeeeb119ad18eafd1cc4e2a +S053/S053R02.edf e9a60f7a8aea15a1093cfbbd58e2f4cedcbd4ca1fab1fdbaf272386cf87b4bbd +S053/S053R04.edf 90703ee0a3f4880dfb4bac085c883ce4b0349e7de9d9d4485fae4fb0f2a8d78a +S053/S053R09.edf 6d0b9439be889c04c476d082117cc895ec0a2b8b10d347328e2561e56bd2281e +S053/S053R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S053/S053R04.edf.event 7c83be0506163b52a89548c7af6d4893472403c2bab3a455c7d8c92bf3550ad8 +S053/S053R13.edf a835beec4d19661978710a3680265dc18968f1bd82c006e80a69fd2a60cd7d4c +S053/S053R11.edf c666e7a5af9453a6d7eb9526304229111cb1dbd9ffbf9f4e8514a60a78bbbe95 +S053/S053R08.edf 21c33cc1ab60d7d392b99f1a00df4d4d8024db6f46d0e3f55f53e6321eaeefb0 +S053/S053R01.edf 72184f7aad1257f85cc97ea9afbe7c6e80b4cc3c202403a1323a648955d2d327 +S053/S053R11.edf.event c6fd76cba5a912b92a280d7d54b9158146ba5522f81d9192baecc014a6c9149c +S053/S053R12.edf d151fcac368e31dbe81495377f734a1c2ed898587696503253e197324c884ed0 +S053/S053R03.edf 8e74f83632eea295b71f82004abb466635b0cdb33d7ad393c130866995924544 +S053/S053R14.edf.event 11c7903b0dd963937962aeddd4ffb77feeec607958b581d996b712009c71f910 +S053/S053R13.edf.event 4c374f58a91c1ff71894cacb50bfb798d20cbef67ee65a1ce8a2d5826349e390 +S053/S053R06.edf.event 0724cecedb70811bcaf06ec5a41151edaf5209f968315c4da2e3a25bbf0fb9ec +S053/S053R10.edf af5fc64c8dddefe50ae7d3f12b2f31f3ef1f4b3e72dd5972399205e5a37035bc +S053/S053R05.edf.event 2d33f0e6820d6c85c1b096ad02de0f117c60e1202edb58aad42f3ec835f3162b +S053/S053R07.edf a3f42b2a8cb0cf59ccf421f5ca2d2a11992085eefa971cd28bc1ab0efb6f734b +64_channel_sharbrough.png 9e2ba68c31f3499b1f558fe02cc20aa44f69179416e5de13a025a3012f91d73e +S077/S077R05.edf 5c5f74f4d83f9fb5a08a7df7f34eb1c488d7e3d5c2d4d0ccf2e799b443f7db57 +S077/S077R09.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S077/S077R02.edf 164a6d74ebbd56ec2f8a4cc182ff49b6e41b01796d76ee0d3f245e03a6d4675f +S077/S077R07.edf 69788b22d85f3fe8f1e6d18ed916c035ceb5bb042830c8d2d62515e4a5ed75b2 +S077/S077R14.edf.event 23b6fc268df2ca2b48b0a505a6eed055a62dad293041c180f6f03136d0f4b36e +S077/S077R09.edf fefae86e28f02f36fd24642b62657c00bdb8a82a4088dee6c0a5e10acaf0634c +S077/S077R03.edf.event 0487cd7ee2fef7813667623ecbe113ebbdd5400e7dff28fd7f0f7b1e00d585a6 +S077/S077R03.edf 07eca0c3b99b709c128c52ff9b8bae2b0dca9b84bdc30845cae16e694a935aee +S077/S077R07.edf.event 9e1cfe676de301ff52ef7ef70ad2cdd8b8c9562c01e98d8eae191a5c8c28aa46 +S077/S077R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S077/S077R04.edf cdccce472114bda440a3eb03fa0a1bf32d9dec5753a105736672389bff46d9d9 +S077/S077R06.edf 002a49d4320ef6dbc9daa93471a6f2e7e4036b49fe87e7cd29927f1803333c35 +S077/S077R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S077/S077R14.edf d02fd15e9745107464dc057d0936bbab18a55e1fec8e652c85b9f17f28171a71 +S077/S077R11.edf e023615579d13a36aff9332b376c5e98e795b77d26827e331b3ac0151742734a +S077/S077R06.edf.event 9825c80a69d06961cbce2e12cf8d0aa56d063e5f4598312c4e5b78693a0219c1 +S077/S077R04.edf.event e8abea1fb06a5ad73e91ea5c97aa84247e1c165ee2bc724e9b9c7ae6f6c017cc +S077/S077R11.edf.event b0c7884218a114ab4fc2b8cb09b2c8f1bd0ddbaf69aac65191618c0a230f65d3 +S077/S077R13.edf 74955924f5ad34205cb1a0cde6904fa9bfe8d80ae1e8ed8e389089eb28fe3471 +S077/S077R05.edf.event a6c871f2eb69757aec91f71c7de20007524b3b628f251799a3dd57bbb181fd84 +S077/S077R13.edf.event 0028edf9b5fcc76311706f809ca44f884f227acaa02c56031cf87a7937c1d9a5 +S077/S077R10.edf.event 69bc42ecdda8587b1f3dcaeb49f434eb51439670272d896577812c1a8c0b14aa +S077/S077R08.edf c0bea153dc620d85e59fd9115459a07da82c137b4e836c1752d1a350cbdedab7 +S077/S077R08.edf.event d9d89addd8fca4d057ce27c16b349184b9dc3b13193561b7c99ffa9414e86138 +S077/S077R12.edf 09e9310ea5e0a9a17a0f0d48e9d2cd3b36bca4c4901c4ef246b2b789d08e1927 +S077/S077R01.edf 1eed03d32fc8cc2cb57cf28fec4b380d56ce3bef548ad82b045d43d7f0ac82b1 +S077/S077R12.edf.event cfb6d9316552151b2cc7a4fe7b3c98b0ffddca0cea554883679586887149feba +S077/S077R10.edf 794f13c06350ac4f14523c20edbe60185d3a464e72ae50fecd9074b9d5bc5352 +S069/S069R01.edf 8da5f1695c8c03bcc530dc1478ff74749380d579a5ca84d6232e1df1815071f4 +S069/S069R09.edf 90f43268da66b9f89b4092fadc9e40e6f68fa86f0f54dfb55e1bb4f00d17af9d +S069/S069R12.edf.event e7ef0a3d66a5c814c6e917ac8f9bf83d6056810f78dd0c9296b5445289483fa5 +S069/S069R05.edf.event 9aaec3ff6fcd8c6d47bbf0c154dac87cdccac4bfb099e5995ee69afc7b34257b +S069/S069R10.edf 6d404692f34d3da6dfadd926d862bba22072377d1b3c38c18928b8f0d0203073 +S069/S069R10.edf.event 2eb503fa48ef7e13b77098d860c716de2d0eb55a3a0580117eb34aedd472a728 +S069/S069R03.edf 1a3ca3653caf83303ac1e7e9cbc965a8a135d04f383dca4170c54264d5368253 +S069/S069R08.edf.event 8a6bbfcfdb8f2653e0bd440f6aa7459e00906a06d68c4df1b718df856267369a +S069/S069R08.edf 72a1bc8c4b7790aa730a92029fb18cc9a9894d3934411d3b02f5bf6806f4c3af +S069/S069R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S069/S069R14.edf 4fcba35e3c96f6083afe2124813a6847893c811fddb7848a640ebbebdc1c60fa +S069/S069R11.edf 83adb3635af06c072ead0677b0f97ea35af309cfc9499e386c6aa5b697e0e016 +S069/S069R07.edf.event d45b05b6c6897898bdd688c12fad776011d39250bd1bd8de7e7745d939b60e3e +S069/S069R09.edf.event a376b452fa5f7c300d71ec31ce58f97920510a057f4ca6c506f4cef51faa7315 +S069/S069R02.edf 10456a512b499a18be5cd9d8e6835ad45ab8666db79e25470b7785b062e43e85 +S069/S069R05.edf 4af85e1eb3da69940edf24de72c7676f30a29b8d52b6cfdfabf6b0cbda20d180 +S069/S069R06.edf.event 1a93c91ef79032df8664905730df14e57174a6aab494378ea976c6845e662faa +S069/S069R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S069/S069R12.edf c47fb991214b23a3e30fcdc62d8bca21f4df7765417bba5ebc89255f5043fb7c +S069/S069R11.edf.event cb2f9b00882e2e0ece44139387a5ab787bf248faadba57d4e5f0e759bd015f4d +S069/S069R03.edf.event a18bb793691db61833ea9b3b10da118a6687892d063d72ae795055c9209ba8ef +S069/S069R14.edf.event 1ccc28680a9b24af49105d307967ceb434f5229a29e70fbfde089b2d092db7c3 +S069/S069R06.edf 670e54ba92e9781c033d2d360f50ebb156723ffc2ab77d1e88f0d68a247cd96c +S069/S069R07.edf 3d465afa0d689bf913f8a5ffa486a3dd9808310d20d7750920f760a010ef158d +S069/S069R04.edf 31d86ad9d97e919e9705503bcd47f391a75e1b89f327bfe4656eb76b41fc628b +S069/S069R13.edf 914947f72ec016f128ff2c071624f1be1311500a8af5d0b673948ef65fbaeb53 +S069/S069R04.edf.event 386c51194ef175e56c4d94b5e327133f39929095caa7c3ac86e89628f6fc0610 +S069/S069R13.edf.event a50926e15d8027e4167d22e5479fe3751780003aa245b90b2eecb0b4f474fde2 +S065/S065R08.edf ec531cbf9279eda222e9b873129c34b8bf33f0fcfcdeb790e1c4b5a1146dfd85 +S065/S065R14.edf.event 86187c2aee7d3ec840b09b5c7d4105dede60c6f6536fcc3d5347079d5ce58666 +S065/S065R12.edf 578268f2055e302e5bc3248f8dbfbbd63c8c60b300f4082b4213add5c03e7a2f +S065/S065R07.edf 7bbc404c049acc05e8d5e380bf62594686c3a265e222f516405254721c6d39da +S065/S065R10.edf.event a8e304ecabaf8d9f1d4997f8bb05c9613cb7743d7dc73f6af7fb82cea10f7792 +S065/S065R11.edf.event aa719b9aea445a02c8c5c6a6de32bcb12238842c8d4ae16493f623bf0d226c1d +S065/S065R01.edf 2f6d0594f0207077831c620c299d84ad49cfa36c12af43a32bdbc129f0d9d703 +S065/S065R05.edf.event a26099d22ad0d99c6db2d456dbd53db1b49b139b9020075cd2d55944c659394f +S065/S065R11.edf 48f2b63b9f9d1274c197bc0fc0a7bf67dc53795d06f01319ace8937b2911da71 +S065/S065R13.edf.event 6a0785ec7d7cd8c80087db9605dd320790daf7db8cdc6c9fbe68fad0470ed604 +S065/S065R14.edf 13f91f949f5ec9e1937a7e3722da005338ea6e00abe879eef6144185bea1858c +S065/S065R06.edf cccc62bb8932916489019988e831812a9e38e48d0045a52d395358790203c3d1 +S065/S065R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S065/S065R03.edf.event ee1750c58b0ffdf35fc0b7841091977647634e837de14a0b9f891ff04dd2f5d9 +S065/S065R13.edf 1ecc6c90f6e2d2199cea20044d6d90f0e7e457b5effd3c186a939419e115933f +S065/S065R04.edf 3fc9b1712f959c02a8b6588a77e879d6d9a89d0ec4e746fafb40c2a469d66fb6 +S065/S065R02.edf 8b33a98df8b418688cc3e5fdcc931c78fc616f6a2f82bf3c166455715b3a9ed1 +S065/S065R07.edf.event b1551573cd91101be666afa2abcfdb421f144c3fa966b0a62b6251bba942a18e +S065/S065R03.edf 484dc9e2aeabd8e8ed55b14364b4848e079070bca661bb42f51a7cab9ca6013f +S065/S065R12.edf.event 0513fd04977ef5a66b77e72c59699e4e54ff57c226456d0796b1c58c38fb4d59 +S065/S065R10.edf 1fab43de441d8fb8266264f03b8a72984d41ace8c1ce1bcc04fc084ae550739b +S065/S065R08.edf.event 194c7017f9fb0a9e8e5ed2d2c50b59fe067aa973a5e75567ca562949327e2edb +S065/S065R06.edf.event 3a98d78e3ff8d947a073981e739716fc7bd37c89605bf37bf0addaa16779530a +S065/S065R09.edf.event 1442094c7e4c8cf80c2b917010d3a5835f895b48a64150371ef6f1f36d5eb9dc +S065/S065R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S065/S065R05.edf 13a29cf406fca98795925cd43b56e202ac098c075a2599fd76294baef8139b96 +S065/S065R04.edf.event f8a465b9ebddc2704252299afc352d87e33c523fa8f80ca82a96fe0b268727cd +S065/S065R09.edf 63e28becfd834edd2d827e2e674e2451af2b5195159bd11bead16d41fe44c817 +S032/S032R05.edf ae793cc1cc052c1680defcb9dde25ec5a7551da1848b9d493f31704e6ef766f8 +S032/S032R12.edf 86ec0265944349a8e801a96924a33cbf8834197e312cca86a576bc4be4057844 +S032/S032R09.edf d415986f87c0465cddc8097b69851f6df6d031366fe4694cf521f1d9c29626c7 +S032/S032R14.edf.event 3746a126df3fdfbe9c0038a3eaaf45fe9135091875ffc4e91bf194bec65bd6f8 +S032/S032R02.edf 2cf498af92415c18090d52e96ca5977a63ba2041368dd87df761f037f41ce526 +S032/S032R08.edf.event a9832f55fb6afe673f34035a0fd1c83d70ffe8552c3a3b9927a0296a70c67809 +S032/S032R10.edf ad4e5d446db449d64f10910c6aeac448fc258859257cc5e7f3948478985518e7 +S032/S032R13.edf 242f6cefc2109136019430327cb2639b024c31a7fec71fb69beaf0e30ba387b0 +S032/S032R06.edf.event 86f35381c7eb24cc6094567ca1b734e53a81bd8184a6364c79b7f00b9a5ece02 +S032/S032R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S032/S032R11.edf 6e8c0532a32664a47a4147dee233d71f28bf0a033cd3343addc6b23df805ded6 +S032/S032R11.edf.event 7e31a2cfbce9a99bc07e9ddbae2cc7459eacaa2ee5661470ec567df0527acb79 +S032/S032R03.edf 5cf58f6d8f7b5771cfaa660754a73759e71d7cb5eb4d207bfaaafa815c3e4729 +S032/S032R14.edf 03dc57e9d57878a08ec8201f903b4c3d7539f3cdce3793088139e6974327f88d +S032/S032R10.edf.event 377caeb601fd91dd56677c88ac2c9264debff52b4cc40eb517657abcc42e6d9a +S032/S032R04.edf ae89d2c1dd10b26c8d382ddda0f6681723ab994168d0e94b4051c43d83bce694 +S032/S032R13.edf.event edb77eab3780127cb1134d7d4b9339cd17e3006b601c1091241521e1671ff407 +S032/S032R01.edf ba99cf38dc94b4408469708227736b388eab4cee0a0fb27ecba353ac4348757e +S032/S032R07.edf f32f55586744578a948a01b2c0ae7528f004c6c8085cbac88b7830ae9e5691b1 +S032/S032R03.edf.event 194c7017f9fb0a9e8e5ed2d2c50b59fe067aa973a5e75567ca562949327e2edb +S032/S032R07.edf.event 22a6b841d94ebe84eeaabd93fb3e0f00da65ddf3bc8de6d5a79394e3a1394567 +S032/S032R08.edf d707e791b0439e6b0c2401af9bcb90085272a857fa138f2b0c7d9bb20cf638a6 +S032/S032R04.edf.event 6f21f5809578073ed2c858eefa6348294beb3ca2936579fcd1c562953dfd18ba +S032/S032R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S032/S032R12.edf.event 7eb3d99d1a46e50d5ec14297be174789c9a514ecb48636ff9ba19d90bf2ed9c3 +S032/S032R06.edf 48b8480f6b38c9130c433d907db9b695198d432da837bddc720eb93099bc1ba5 +S032/S032R09.edf.event 1bc8e1dc23f970d7522827a583fce66cb96923864ede7ce6fb77f885dd7ce6b3 +S032/S032R05.edf.event aa88e9dc85f46564702f7964b37b2058d00e5e0b93d498e32bee49aaf8e7c745 +S084/S084R06.edf.event 79987bce81c997afe211bb1afd5e197582440355efe08dfb5466d616a8f03f7f +S084/S084R10.edf.event 69bc42ecdda8587b1f3dcaeb49f434eb51439670272d896577812c1a8c0b14aa +S084/S084R05.edf.event 985f9701733fcf2689c3a35bdb9e4b0058b6137ded5bc0f1a2a3b84431edb435 +S084/S084R01.edf b8fe107728ed7e3057cc35faf2e66f91602dab9260b0ab2b0a64bfe6a3952434 +S084/S084R13.edf 86889443cdf0605b603b1b6b9a0d61f670e16212730e986b8a0f8e90a85d6a78 +S084/S084R08.edf 4228f23c5c8579ed84d2de2a35d33b90ade7202ff18df9e404aad44395acea75 +S084/S084R03.edf 83318bf6b9b298cd261109537d31ce9a945d29c0064152fa19f04b49a004a0cc +S084/S084R03.edf.event 5bca2030ba3ea66c594c376bfc5a701d3f25c2f85ea7d72b8abb2b2bbc5644ba +S084/S084R08.edf.event 01b8244e62aea11c106c000350e5b2ebec864736b68aa1525ea371fb86a3b0b2 +S084/S084R07.edf.event efd977506cc195b985e542f3333bc334c4793652f9b52580c96ef8a5948f4db9 +S084/S084R12.edf.event 8553d29b6f3410b4ee7ebd3f65050ee16a492ed893d0bc9a14cf35cfa904d586 +S084/S084R04.edf 0b79d12851eb2fc57b8fb94c29fc78d228c2125233a0a4ab36581d83e1136456 +S084/S084R12.edf 7e726571c4a9b7513e9e0afce0546a9fb221f13681e70e2d29a02725e608451b +S084/S084R13.edf.event a788bd6a825d960534053c6559cb4f24cb7ee7a3164017d99c1dbc55f3b22215 +S084/S084R07.edf e9674d16f540f1568073ad21fe40ebe186414813069548bc45c8fe6f0ff44a66 +S084/S084R04.edf.event 43bc660a507d479ebfc1c782945c8504dc21abb3e55cd48acc2faf4db673e854 +S084/S084R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S084/S084R09.edf f01a0af0ad426c6ea59e93584b352091b2448a3bb7e503755fca4b5d74f9c242 +S084/S084R09.edf.event 98da35a4768842863f8f05d63e959a36f12126a205e0370d8519299fc06e56ec +S084/S084R11.edf 2491e3b8b033ae43659c025a9ef62beceeecf202ecedf579f1dfe7e0b06fe8ec +S084/S084R11.edf.event a18bb793691db61833ea9b3b10da118a6687892d063d72ae795055c9209ba8ef +S084/S084R05.edf 8a1c8373b6276d1e755ef71144d2b56e30b4b687d08cc56bdf12d880a099938c +S084/S084R06.edf 361908a101cab206d5cf84f47b813dd6ed436fa773b2a17ea97a3b2206b97cbe +S084/S084R10.edf 6c2096104cb26769e84b982f625ebdccc2de28b5b2f45c3a7c4fa398eb564f3d +S084/S084R02.edf eba216592aa8b26c390fe02a33773d9d007cd7b9cd886b18fc9250b649d7e4fa +S084/S084R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S084/S084R14.edf.event 212052daaa4c0fbc66f91923236861d93fc52f73403f6b4d988205287f1f9ece +S084/S084R14.edf d24540d0dae99f7453bbcf4acb93d299747ad65844ee4f4ef7d846e7ed912309 +ANNOTATORS f5bff1d1558405bb6de5d02821a0f00b4be3671ed3454b19d1d2ee75dc689264 +S097/S097R14.edf 76520698cbd9ae79cfa6ababc8627fc60469dfd0f307eb4acf3ca96b5e67e099 +S097/S097R01.edf 7bf7346caa9bd3effc06b27a1f0c4bd94e21a861047fefbf19e7b60ae76ca02f +S097/S097R13.edf fcbde4d0bbb01757064d48afbacff750cb9fc416c741ceb88a3dba5624b8f23a +S097/S097R02.edf 1b138117c090c2041b27984970a5f0a568b5a95b2235c29cd4189c28365b3d21 +S097/S097R12.edf afab0765b4ee4d03198c1e0a18a0f285c84d6734dbd1cf305886cf0d7464f433 +S097/S097R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S097/S097R09.edf.event 0d4308120129d0f92d2b8779374ae232f98d1357e6c6427983fed655d9611af0 +S097/S097R10.edf 6acfd4c3295829d636f686910d28b41a73fa1b6a26ae4d1a7fe30578f1049e7a +S097/S097R11.edf 6d491c8035377279db2aecf740cb19fccc0b00d92d642595775146adbcbbade0 +S097/S097R04.edf.event 7925ab0749163820c00af5a617adba24f1ce1c711886e12def08eb72594e10cc +S097/S097R08.edf.event 48bfdaa247bad1b393cff54386a6d30257090bf0e7327f31b2b320921da53270 +S097/S097R12.edf.event 9a9f0b49f8c6435ad71289db5003bf298965348ca79b0498dc572d390808b84e +S097/S097R08.edf d36269db5e812dfe12879bdf3ecd1d1f7dc0319d59f897dae352e5e19532cb98 +S097/S097R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S097/S097R13.edf.event 1a93c91ef79032df8664905730df14e57174a6aab494378ea976c6845e662faa +S097/S097R06.edf f75339f76c9fdc59aff27e03ed839898bb9b3dea36ded727ff5287b85c274b79 +S097/S097R05.edf.event 20d3d791a72acbcdd619cb968567a104858a5889afc628a6fae4776c90c0780d +S097/S097R05.edf 42d0339fe1c0632861d54e04e1e4cdbe3dc2da0d00295c8a275b8978b6d176c2 +S097/S097R09.edf 3534c74016c2cee1c9ad49e5a08a31e6634b604a8fb3018b183596c863ea1531 +S097/S097R07.edf 1e895aef79f71d0a04a68f4578ad204733a3631ab9c2852526a4f604b8d9392b +S097/S097R03.edf.event 00eb5e22d01c3eaeb1626660a99e0c6fbf2f4423eed750224cc549752b7b6761 +S097/S097R03.edf c3ff3efe887db00e8fa2900dfa09278abd23dfc090262c231815005e81f0736e +S097/S097R14.edf.event bd6dfaccdd7deb73743f500e0a1fa9d0ff333e94d59c6d153e2e9d2dc8a4795f +S097/S097R04.edf b179e92e1d5ff926d6aa88bf3c748201c8368312fb31b1d2bfb8bdd033c67cce +S097/S097R10.edf.event 0487cd7ee2fef7813667623ecbe113ebbdd5400e7dff28fd7f0f7b1e00d585a6 +S097/S097R07.edf.event 25eca6452bd9e487db46059b497ec8df5b6c353e97a2ac76ba8344fcc0797c79 +S097/S097R06.edf.event e4d125d65ed410f2e37eb6c7f7075c585662cb4e5931bd8436cbd1b59c474f77 +S097/S097R11.edf.event a71674e1fd86a57270a24706f4e05755887534f04ecc35f98e56f000312402a9 +S099/S099R08.edf.event 78e5b5619faf1f99b53251a9e743644a731ec9cc5b6e60533a3695f33fca35fb +S099/S099R13.edf 399bbb5280b215c3451d0e10d317fbcfdac333093adfced081aa2db59c523ad0 +S099/S099R11.edf.event bed28cb624951271916f88bc556ff204ccc63699ebc4523ed8043baa9724625a +S099/S099R11.edf c5e935a60f572f30fd2aa2e9639b02f313cb498af17f9105f644d51636fda4f7 +S099/S099R07.edf.event 3670ed6734a1e3a4a23fe378ef332968f910405646ccd883a62369d2add4b888 +S099/S099R14.edf.event dea45ba8a8662cd82aeb9d6c523756ce7079f3020c2ad1b23d6dca2f63b5bf82 +S099/S099R07.edf e9c2be6c0a2d80d78feaef0d251a18f6b753c7987297ec84e66dee0910397afa +S099/S099R12.edf.event a8ce17ff32c2c3aa820817e047ec3ff9976bd33355d14877f0ff811df5a288a1 +S099/S099R09.edf 9041b94fb5dd2cdf300413c690263a223d506ce38347855ee02ef7d45188aafd +S099/S099R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S099/S099R12.edf 79a4364092c5678b43071c5907afe061974346751bd90a2d8eabdc7ef8808e32 +S099/S099R10.edf d3b233a2403e3d00777830137377c4fd3bb4c9130a137439c6ecdd3e39066fef +S099/S099R10.edf.event 00eb5e22d01c3eaeb1626660a99e0c6fbf2f4423eed750224cc549752b7b6761 +S099/S099R03.edf 9166582d968b024a2ca92b99926c4658d6911bb2d3a2256514be716fe57a165f +S099/S099R05.edf eeba6d292190922beee9af52ee0c83530e9e4a406e2fe2e255094ed0ec681417 +S099/S099R04.edf c463ad89dc08d0d5e6fd9f766b0e1c743b802290d93a3c496a9faf3b8ed6032d +S099/S099R06.edf.event 6546377ca20368b45bfd1f06c72e153809df57db54b8731ecceb6c8ec813a774 +S099/S099R06.edf 02a19ca40ac26693a6763d2ebcdfae9e588dbc32cf6675cc236f0c9c17809899 +S099/S099R01.edf 9bdac81d159f0f6c153e4a48a72bcb1bc53ec0ae77a35df1263524016df3a937 +S099/S099R03.edf.event 950cf97301dd495a2a6a7a19a93d67d2ee9ee03b2675e300582e19305f5a9287 +S099/S099R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S099/S099R14.edf 1a56b53c56685a91872ca0e57ed2cc13f88fd70b0bdfa369f1cc2ae19dd19f34 +S099/S099R05.edf.event 43bc660a507d479ebfc1c782945c8504dc21abb3e55cd48acc2faf4db673e854 +S099/S099R08.edf 6c5630263f0e2a23e2ec4c57c00831ced0469b3fc4c8dc79cee7216bb85a4810 +S099/S099R09.edf.event 98da35a4768842863f8f05d63e959a36f12126a205e0370d8519299fc06e56ec +S099/S099R13.edf.event 537ad705e53a339bd1d130f3331df882a0416fb7e95c4f565d283142dcd120f4 +S099/S099R02.edf ee86fd6058f1996d9535938c1cd6eea923ce7dd06774bad24ec342c0a1c1a2af +S099/S099R04.edf.event e1c00064d3aa1fb0636aaf0dedd65aa66d02a8afcf3dd70b9a5fa4df4d4ebd47 +S089/S089R13.edf.event 5c4801afd1f2da908b7c1f672c345bb1db7d2e1892eaf195db0e1ae6e7a9e84d +S089/S089R14.edf 8693681084d9a31a2373e1206a31a5255a098e377986dae311f40b1945aa14f1 +S089/S089R04.edf.event 5c4801afd1f2da908b7c1f672c345bb1db7d2e1892eaf195db0e1ae6e7a9e84d +S089/S089R10.edf.event 5c4801afd1f2da908b7c1f672c345bb1db7d2e1892eaf195db0e1ae6e7a9e84d +S089/S089R01.edf fa4c6f60949968c607bf5105f9c80ea1a786b5bf6b15737077a9f256af66bfa3 +S089/S089R11.edf.event d8477aec0c4899d8efdae84a2031ad72cfb0d63c48f6c0d509cf23003d2b29ad +S089/S089R02.edf 44c5016ee50908df260c8adb6d195c44824787637b2537ee823efcabbc8cfac6 +S089/S089R04.edf 59b477c2e08b85fd3efe774945f6becc5073d654bf0f5b911d45dcf30b92c8a9 +S089/S089R03.edf.event aa72ec0fb1b9bb4224bd65e15fc8975e31a5647924ae870539169014ee07329e +S089/S089R06.edf 7762f48f45a3b446d508942e05bdc9081c897abbe0b6a57651a494da1dba8c27 +S089/S089R11.edf 7f41dc795cb95835ad59fbb44fc8fd14a191dd9634ccb82b73cf2e9a04eaabd5 +S089/S089R12.edf 2fcf2f10853418d0ca8184e008b29ce2d49a4762c0f5e82aa71298925ab2abf4 +S089/S089R07.edf 93a6e3dba6343f46211d0f57dd81776da03488be2356006dda7023c1c22e1dc3 +S089/S089R14.edf.event 5c4801afd1f2da908b7c1f672c345bb1db7d2e1892eaf195db0e1ae6e7a9e84d +S089/S089R12.edf.event 5c4801afd1f2da908b7c1f672c345bb1db7d2e1892eaf195db0e1ae6e7a9e84d +S089/S089R05.edf a5726d13ea72450e4a367588e79c740daf7f5288a2d950fd4cf4904e10ea6ff1 +S089/S089R05.edf.event d8477aec0c4899d8efdae84a2031ad72cfb0d63c48f6c0d509cf23003d2b29ad +S089/S089R09.edf.event d8477aec0c4899d8efdae84a2031ad72cfb0d63c48f6c0d509cf23003d2b29ad +S089/S089R07.edf.event 5c4801afd1f2da908b7c1f672c345bb1db7d2e1892eaf195db0e1ae6e7a9e84d +S089/S089R06.edf.event 5c4801afd1f2da908b7c1f672c345bb1db7d2e1892eaf195db0e1ae6e7a9e84d +S089/S089R10.edf 4a3dbca5c67c12590dc5b9c1faf95587030bc3029a810ecbc7193d5e07f72a87 +S089/S089R03.edf 0de49011384bfb26129a96a0ad2d4edf64f22eacfb523da12afb9889c324c0af +S089/S089R01.edf.event cc4b6b7e93062a4a93859d69a21eac72c2dd51a7a596f8c3941d89d78073eb06 +S089/S089R13.edf 5f3a32cdde3b650569d7b8925bcbb887ac06f354ec987ab6db15aff9d2948c1e +S089/S089R09.edf c5c002521ae41431dedeb6f07fb283f55fd030024f56956f3d371d542be3a0a4 +S089/S089R08.edf.event 5c4801afd1f2da908b7c1f672c345bb1db7d2e1892eaf195db0e1ae6e7a9e84d +S089/S089R02.edf.event cc4b6b7e93062a4a93859d69a21eac72c2dd51a7a596f8c3941d89d78073eb06 +S089/S089R08.edf ee2d004c55381ccbc5f75062e714da9705c7e8cac1d4193952d646399f3ef7e6 +S100/S100R05.edf f9826ef24c2091bbe26928a23b8cd6e9ea764a55a7489c0a06dfa6d8f0b09368 +S100/S100R08.edf 8371eec06d0b1ff62d10e016124e3bc2db411ab6764fea572fb2d1f25a6afd97 +S100/S100R06.edf.event c78171063f0b6cb3d3f0d6ae265f22d687d1a2136c5a8dc8b39c9f87ecd253c9 +S100/S100R13.edf 0294751068a2a6477dbfdb86bda76199069cf506d9bbfba907945accfab9e1d6 +S100/S100R07.edf b3bb899c1bd819e50b9c7ad5837fd57b70ca7c423e06e3f9bafa885eebc0fa97 +S100/S100R10.edf.event 45d618537012fa72a10d1b7fb27c2662f90c1b7975f1c48a918fb5bafda756de +S100/S100R04.edf 0b8af6ed149b8b8d05a5d25da8896c6b555a199002acc0705dc1c5a01e489ea4 +S100/S100R01.edf f3741fda19dfb05973fb367c6f9663df5a9a1c378324c223e677e59cb4450fa8 +S100/S100R14.edf.event 2679ccb7e833183a26577624b2f4dd83eb2cf8afe48763eb5fda873c412cb7ad +S100/S100R05.edf.event 2679ccb7e833183a26577624b2f4dd83eb2cf8afe48763eb5fda873c412cb7ad +S100/S100R12.edf.event 45d618537012fa72a10d1b7fb27c2662f90c1b7975f1c48a918fb5bafda756de +S100/S100R04.edf.event 8c302e42b971167e26925e79e5ace7653e62a27d70b8c0a53aada8f5f3770a99 +S100/S100R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S100/S100R11.edf.event 2679ccb7e833183a26577624b2f4dd83eb2cf8afe48763eb5fda873c412cb7ad +S100/S100R06.edf e57c7986d7814bd142c3cbd525d9602bf00023d397a5e9a89e4646cfae0a8163 +S100/S100R03.edf 1498da5c347ddbade9c693f68063d3fbe244dddb6fc73bcbbb16331d05a0e9a9 +S100/S100R03.edf.event 8c302e42b971167e26925e79e5ace7653e62a27d70b8c0a53aada8f5f3770a99 +S100/S100R09.edf.event c78171063f0b6cb3d3f0d6ae265f22d687d1a2136c5a8dc8b39c9f87ecd253c9 +S100/S100R09.edf 3e1651550a82aa15acdf0f9639712da2153ba1d00cea5a8c11608a43ee88287e +S100/S100R02.edf 506d0a77e01e0326076136cf41c4dfc5ee6206376f20da6efb858affa1c044e5 +S100/S100R13.edf.event c78171063f0b6cb3d3f0d6ae265f22d687d1a2136c5a8dc8b39c9f87ecd253c9 +S100/S100R07.edf.event c78171063f0b6cb3d3f0d6ae265f22d687d1a2136c5a8dc8b39c9f87ecd253c9 +S100/S100R11.edf 9fca7506be3fde10877ebc06d1f64a10aeebf7a99c1058762da81548d562fd18 +S100/S100R12.edf 6dbc4350c7e26c46b96ece5cd7ae2cdf1a9303d237d7089216e5facbc1d25538 +S100/S100R14.edf e80cc42dc4b5dca4cd37bff1a44d971452d265d825f893cb52a6b71d61922882 +S100/S100R08.edf.event 45d618537012fa72a10d1b7fb27c2662f90c1b7975f1c48a918fb5bafda756de +S100/S100R10.edf e68dbed45e873cf275dc2174c7b56ba2fb2ac2ecf162bc7ba7cff5ed0d789cc6 +S100/S100R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S025/S025R12.edf.event 6e13e4f708f4b769dde500a1db747206aa87951c3914cdd436fb7f07e9aa5052 +S025/S025R06.edf.event 6ca290c8f2ab5d2a3d0c42a123bd24341d790899e901dc5991dd66614dfb1842 +S025/S025R09.edf 3049771d277191a89db3650c36972cd0c41cb947f14674501dab593d68edb66f +S025/S025R14.edf 470766d1886c2c43076606110cc79b995808717abd7c109419ac8cb9924ce6dd +S025/S025R03.edf 19a6350b61d317385b80ffd2b7d7f4a23fa889a9b8a3c978db630f004a88fa3f +S025/S025R04.edf 25ee02ebfe5c2b2a652a295835d7a4da653c5e6b390084b7c78a4daa64336381 +S025/S025R04.edf.event 3e83abe294ec7b278fb4495c4fbc171e9413e9d805ad8464dc6ea5a4875e7625 +S025/S025R11.edf.event 212052daaa4c0fbc66f91923236861d93fc52f73403f6b4d988205287f1f9ece +S025/S025R06.edf f11f802c5ed1087c08cab562ae165fa0eec1c13fce7a203427e210c0940dabab +S025/S025R13.edf 1048a353f1132ba976dc920cff2048dc6d47a35bf1f70eb8ae64e8085fa0eac2 +S025/S025R07.edf feaf0611e4671d07daff067c688af3c74e81b4b5e903529b786bc2240f8079ab +S025/S025R01.edf d630db7ef42ec83068197a587f93bd71e218e3d592e190e79111b414633d7fed +S025/S025R09.edf.event b0dc1155da666ef5240efa8026cec5f4f69b5fb6f1d21226a512de3f6b62002d +S025/S025R13.edf.event 33a34db8c83e4bcf4288f2413aa75b7d7c03a7bccfa172b157568ba29ee42d1a +S025/S025R02.edf a7a4ad734563e92b931f990bcfad62a6d03daaa273c7a4b9f039c3030c1536d7 +S025/S025R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S025/S025R05.edf 1bf20c6a6e9f9d926b581eaf8a771f61efb626930c28a19455c90ae0dea6935c +S025/S025R10.edf 93c2e8893122eae1ea5c83f02f08c54847b6dde32814ef1c7b0d390d3a2d3f0c +S025/S025R12.edf 94a0c6cb21c67381221fdf364c8eadd17ce3b70021c579d0721c22d04c6d2523 +S025/S025R07.edf.event 8fb228960cd397f6100e75cca49e1045159bf62e6184dd5267ea608be1d540b6 +S025/S025R10.edf.event 1b02f94c97b31c7b11129bd2f0db6eb71ffb209c8dc379625185f7a3726d3aff +S025/S025R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S025/S025R08.edf eca94875e6b247b85ee541ccca3118d259132e96212fcd059ccc943f48c2dd56 +S025/S025R11.edf e2b2694aa6f7a47dd5a774c7463eb232af25987580d11e729d23037320272e64 +S025/S025R03.edf.event 39b46b55fa02f8503f1d8726fb4de22eb131c815725552e89309f9db71c825ea +S025/S025R14.edf.event 09d9d4cbfb435c34d0498269502687afe1e41cb410faf772b5fd4389e435ad7d +S025/S025R08.edf.event cdf1a70ff91abbdc6f14a7ca794a7b5932276819e6f7c68ee344c3d21e9b73f0 +S025/S025R05.edf.event 9e1cfe676de301ff52ef7ef70ad2cdd8b8c9562c01e98d8eae191a5c8c28aa46 +S063/S063R05.edf 212f1e4ae284e58d11c14dbb6c1cf5cf0ff59cc4b8b5b777412c54bb626ebf02 +S063/S063R11.edf.event b1046f2c937e8d05f2c3e45473ca880864a5d33222d740a0bee41b055662ea91 +S063/S063R14.edf.event 83ec130ac6a664e0d88923e1496dc0806008967b51e6158521a6beb0515b2eb8 +S063/S063R03.edf 83bb2377058d1ecc7e2ea22d55aef11d131903acf88953323cef68488ad41f04 +S063/S063R11.edf 9b829774c5dbcb1e7c3c5ffa541c9e7c22672cfa964535a8b8ecdba0db447f24 +S063/S063R04.edf b3f74fe891fd3b0da76d7c42b624c8ac2b31c566e2c5d017b779ce5b2b4c8989 +S063/S063R14.edf a32cdf01125535e453c311aef70a400c7483d4a09c00751c38d2b522168f2510 +S063/S063R08.edf.event 082acf669cebc89d5f5f4bf29769c743f3b1e14290b8f0f34415e285db553b3a +S063/S063R12.edf fe724c2eff756b9b2079c0028e719837ed8a2e3cc90341065ba31f073c04ef5e +S063/S063R04.edf.event 3cbb6086e0e7d8748f07bafa5905b530a6f1a43c1ebb1a06c6f846a82247c451 +S063/S063R06.edf.event a716ed693834141bb2b56720ce6124df46e42e86652ec02bc96746644a79378e +S063/S063R10.edf 6ca54d65cfa0768f22e7ddeaed4043860731f8e0fb777b08b78525875b656a26 +S063/S063R12.edf.event 186a60a98ff75df214cbab061e8be8ae3bdc4dfa895704bc1ba0c490018953d5 +S063/S063R09.edf c167ad6b516365c6a9cdebbe8fd49658ad31a882b82416eb7a759544f3c27b03 +S063/S063R13.edf.event 918e61da68f21c26600383b29f33fec7665f2f3fae232e8413bc9266cc617863 +S063/S063R13.edf 63a81fbc94679318c4bfdcf8ed864a3acccdd904e2f7b8b4486d38f5efcf6d79 +S063/S063R05.edf.event 25af506ba70b68343c97ccca1ad0f235958a8dc9bfdd84c6f7155937e7bc7efa +S063/S063R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S063/S063R07.edf.event 818acb17a86d3ee6425a512fab58b363d01b6ccc783417cdad466d1ecddc506f +S063/S063R03.edf.event a50926e15d8027e4167d22e5479fe3751780003aa245b90b2eecb0b4f474fde2 +S063/S063R10.edf.event af55de06274e9f057a8c2b10bb8a4665c70ab950b43d066ea9e3d1de5f188b79 +S063/S063R02.edf 5611a5b628d656e04f3c11c64c3d9da543098757ccff5ee6b41b8b069c3aa682 +S063/S063R07.edf 1ff351b434542537e83eab5e3aef59bc272c42bdb69dc450589a0903b0b5469e +S063/S063R06.edf 75495dff156daef37b3d008791930822aade0ef6b9f8a69ff473d71d8189d7d2 +S063/S063R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S063/S063R09.edf.event 9a154a517e2cf402786cffa7d164d0656aa7a8bb30af51266fc6403fcd9d3d00 +S063/S063R01.edf 19e89fec35b5227c3ddd5a031668a7311264610cde156def93771adc15685af6 +S063/S063R08.edf 76fae5c78ea8a2c05a6f7231b5eb8fb2b46a6001344197916a87306c786ef241 +S073/S073R01.edf be8473cb11d653152f32965bfc62691bae4b3df7fbc1e193840667f5912cfb73 +S073/S073R03.edf f1632361422757358260ab11e6b818e9594be3d85082097a772ba46bbd21f295 +S073/S073R07.edf 012e37d81ab052c3751d06203f4c418341135c71ab4ef6536f4485d02bc11872 +S073/S073R08.edf df5ac3bbcadd037c1698db4e3f36ba4f752c6571775c7780c3ec5a778025f909 +S073/S073R08.edf.event 10fe2ea57f3dd20adb3824338de616d484101e5955b8607ce38e43162b4cf53d +S073/S073R13.edf f7dfa58f68f7863670f91abc8c252f2df4875c52ec69dc2246d792b2c7a5eed3 +S073/S073R09.edf b27f1e82d1e744fe40538fa8c700eab5373def323d6df8108a6808bd7f6376d0 +S073/S073R05.edf.event 1fd941c7969069964d579a646ecff980c4713b69568dc624c832f58c5c7df8a4 +S073/S073R10.edf 9a02aad8afcdb74ac200b42b662cb1cd524aad7a6352992339486ca67644f606 +S073/S073R05.edf 0ad69cf05c39f8641d4b319f0ee822237a551c4ecf1214a906ade02c827739b8 +S073/S073R06.edf.event f4c34ff99deadcec51112b9cb6b5db7a903fc19968b9ca14feb0a67ba8795ae5 +S073/S073R13.edf.event ed3cf1bb44b1d2c21282c844044e08add0a9e1ba501a19ac91fd1593cb7a0f90 +S073/S073R09.edf.event 132d7c78fc024e2a331d21e4a954e9dade78d9bc7c55ab44b306fe6ef20a13dd +S073/S073R06.edf 22b272fcefe3337a277ec3b3becf14b2cf78409e878c8e5bd73e44e803b75eed +S073/S073R03.edf.event 0c68a34fc7c7f42962c230acd4f90579e920c83f2d32cd504111843c5f7ae410 +S073/S073R04.edf b7545db1ffdc782d1012419b18a823c35d6f6fa96e3f7c836f08e3d799aff5f4 +S073/S073R14.edf 0d2d955cd5175eff84083b78808f28dfc2a808f6d1f3870f2de5edd21d479f80 +S073/S073R02.edf 843e65b4b436dbd13649e680c90c807d033bb15de8e80e167dcec74335c5db60 +S073/S073R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S073/S073R14.edf.event 726af5b965cd68175880075d714ab5c49b3b1681512af02ff7658e9ba0edbfb5 +S073/S073R07.edf.event ed7531e033fd753faf42520203638d4de33208e84160d44677c41467cb0c16b4 +S073/S073R11.edf a2b965a59a34f3f872756d5d891bd268d5b041ec60f8c0010847d17dbbff6256 +S073/S073R12.edf da24f28f7a880c97e25a45e0f9eb86dbe7aeb13b651e6cef0f99afe2aa1f425f +S073/S073R11.edf.event 8eb33e667f4552c335382b3baa23b804d5f1b703c747eabc52d51698bf1cd83a +S073/S073R10.edf.event 16ea690d66c06482dd3120d00dd8a03decfa55bab04dc1c945f99213f9c5753d +S073/S073R04.edf.event e6e3fae8bbcbc00e9d7d959eb1e3c2c0ab93eb9e896a0adc93c685329e429982 +S073/S073R12.edf.event f8969447e196cd3b85aca233f8197d3642b3a82ffb49458332044d86c5df05d7 +S073/S073R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S009/S009R09.edf.event 7ee25d4d164dab7d909181d9ed3898053c69dd75d8affe3f277cb9ceac75184a +S009/S009R11.edf.event a5608231854f8f457c107c9acdfead912cd6d55fc459b7abc2f11d77bb166129 +S009/S009R02.edf ca5a6f0a0fc6fe11696d5505c3db2b965136d85c4c0590f7c03af1b527b97242 +S009/S009R08.edf a8121c688ffca3db1d3b1f61dd53d6636ac91763cd2269b39636c65dfc6e4fe2 +S009/S009R12.edf.event 1a93c91ef79032df8664905730df14e57174a6aab494378ea976c6845e662faa +S009/S009R11.edf 2e1eac06f72f940fe826ff9c6b963bc686c1c7357d2b860e351baa263684f66b +S009/S009R10.edf eeeeb3a1fad45ab52993a7696c8f86b0f4cb7de3aa68a62cb2b1379fe87b4084 +S009/S009R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S009/S009R06.edf.event efa5d828429e8df393cf3e5b452a00dc9f05f3ad9eeeeb119ad18eafd1cc4e2a +S009/S009R04.edf 705f53460954e465e7a6ef45bd1f64e675548c08e9238dfb1f448713f9e559f8 +S009/S009R07.edf 9d737ae61e6b01feee5a8cd22c219cfa84e8c5f67210a04dd08ad08aa61d82ce +S009/S009R05.edf.event b50d31cc4a2ec520a336774ea70761d08ebeef4930f053a00ed66803060bddef +S009/S009R07.edf.event 9aaec3ff6fcd8c6d47bbf0c154dac87cdccac4bfb099e5995ee69afc7b34257b +S009/S009R14.edf.event e8abea1fb06a5ad73e91ea5c97aa84247e1c165ee2bc724e9b9c7ae6f6c017cc +S009/S009R05.edf 6ecfb972c81f97b5bc88a292b9b249b4fbd3c51f1959cac1ce8f83ee480c7689 +S009/S009R01.edf 37f117b69060f2c784d74fe973d6af30b3b978f9c7c127324273f5741749bb2e +S009/S009R13.edf af39afa6d2e9006c7d7a2cc573206febd62b75bd696f7ac5d0d733af6789e455 +S009/S009R03.edf f5718a37aa5ea43c8f52dd01326ce09568a71f52e1b2750e0e8e2145e88b6e4a +S009/S009R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S009/S009R04.edf.event 82c4504914809d88b1ce13e11caa12c3a659e1a2edfab31c2e894283b14daba8 +S009/S009R12.edf 0c3f9700d6bfd8a8dd797803d61b80852688709011e5863f4e13e9ec3948191f +S009/S009R08.edf.event 0028edf9b5fcc76311706f809ca44f884f227acaa02c56031cf87a7937c1d9a5 +S009/S009R09.edf 33060662f7551cba7035f177f88442594250cf4359da7d9c9fc7070d929cd3f5 +S009/S009R03.edf.event 8e9579e89d1ec6576609e05f5e6215b4322a4c5375265379e3acd7952866ac83 +S009/S009R14.edf e9ffb381cf76880a63c95ffe80106e9339a290f1fa9632e7575515b4900a820b +S009/S009R06.edf c6665f0c93288610a0f3cc379edb8064072e7b276722358912a76e899bd6b194 +S009/S009R13.edf.event 8a4b5822b251050d46b816bf54fbb47530d91210b6d01cc2e6acbe662193553d +S009/S009R10.edf.event f338197f5dd0ca078ea8eee22145e57e694f7dce6a2bbd55f5f05346ce3b3f17 +S030/S030R04.edf.event 21ce3656bdb563d0169b7aa05527648a736ad7cd77c301a0c752f4cf76eca3a2 +S030/S030R02.edf 0527816f344412f459589c2e29a24f87f956c5ed63328755ef06151c96d1ea0e +S030/S030R11.edf 2c0ac5cf0e945d5c66c220d1cac70b376ed1808a723c107051a2c9f8fac1a793 +S030/S030R06.edf.event 745873996b96ae5adff4736ed896862f8ea11f4da06821cb2df5927090639fe5 +S030/S030R13.edf.event 76436f363d0b1f03efa79422710ad179cb02fcaf8b3e4d6a724efc92143ee8fc +S030/S030R08.edf 6d4742bae0754084c96a1b14ff6430203b9d71b619fe9b33b420aa3d6fb83d28 +S030/S030R04.edf 41305848c93a818493e0bbfb965d01433bdce1b48e9ea1b355e88e08f5c20f20 +S030/S030R03.edf d4ea66ddb38572d264851ffe4e1468e206593c2789e675ef29d18ef7c2767e5e +S030/S030R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S030/S030R09.edf.event a8d31a5eb87f88035de02464248ec55b948d96d57ac210508ba4d4b320318124 +S030/S030R09.edf 16f4ea9781be4ef8d52499252bc782056e6424ee391370398095f59d34fdd83e +S030/S030R03.edf.event 0dc10cf1c35632cd53bc4336ca89f30d7f590ef366a20b7511c2cbaa031469f4 +S030/S030R01.edf 3b0b3d390a9d15b30f95230729a24d5b8a2a55b22ae6ab9ee0c18653068d22e8 +S030/S030R11.edf.event 5cf15190744627a260c9ee5573dfc68ba2b843205a19877288aa8be1015fed06 +S030/S030R07.edf 412ff959e0ac1b98565fc741205625bb31a7f19a446edb6d1e8070b2c7d2bed9 +S030/S030R05.edf cf385ce00f0b8efb8714af8058678f375d0597e66a079bc152dadfa922440dd4 +S030/S030R12.edf c1e5ffc5f0876254f77021f0a478bb374e1ef3c1388f8e90694e984aa085ac90 +S030/S030R10.edf ebd59f99c05f284e1cae773c3d00622d45b137e388951b566d8dc3d48ccfafa7 +S030/S030R06.edf 15b136ad592e0f6fd705ac06588ad6bc300c1b6adbbf5a1437ff6a6fdb2be046 +S030/S030R07.edf.event 1089930d94c72e3ce9766d907746b5e30bc79325e62cafe09bf378282e3d63d3 +S030/S030R12.edf.event 839324cb15f4c85297a1bab617a363408975197aa26bb5ce4aa6f0238ecdb3db +S030/S030R14.edf 569adaf14287ac5944c1492ed853d934f1b7e44f1bb89297fdacb0071f81e110 +S030/S030R08.edf.event 60ca10a619a64d8ffe05bbe5271b4639be106480c5613e3a767224f993989d2a +S030/S030R13.edf 5bab95b93f88b747aff0c96c055326197e51a2d2887264ceee3a59f799c4aa64 +S030/S030R10.edf.event e9b96219c96a5df8ee769b66c4f57662e192352a69c8192bf391653bbe782df3 +S030/S030R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S030/S030R14.edf.event 92869f74a264158c2c716f02e82ce6bb81d49bd4cea9ee281a8c63768600773b +S030/S030R05.edf.event 4d70c0e1ea5d348919f757429a1fa31b6bdc7087f75c8e925771beb9d5894c32 +S013/S013R12.edf 5a4d97f54f5769fb61a64854d46108b2554f1013f0e664810746911f69ea241d +S013/S013R01.edf 6f41486d61f25ea3c38608b650f4e9a19d5e6782113fa184408049267fd75310 +S013/S013R14.edf.event f1d83aaf535b3be7098ef9960def69c712f4dadb4f334e40434e155e9088b299 +S013/S013R06.edf.event a38580800381d773ef251e941cbd4e02611c4c4e4efab3c383f14300a3394f1e +S013/S013R12.edf.event 68922fc617d2a7f851f538c226fc5491b6f57526417f33c57ada180e97746c59 +S013/S013R09.edf 78796fb0af41599ba7fbd25a1a084226f7dc0e385ea6bbbee21e6cc8afbde3dd +S013/S013R14.edf ebdbc2b8c8d86022a8f285bf4b42674364d91cc46eecc1e1abc04043ef12c17b +S013/S013R05.edf.event 7ee25d4d164dab7d909181d9ed3898053c69dd75d8affe3f277cb9ceac75184a +S013/S013R10.edf 14c0536c6a2bbc572cf7b4b7e128aa2f1bd5b3a65e84a16184fd4b382609459d +S013/S013R13.edf.event 60cee9d6dd15c5919b0d3d4f0618922c82d19e6490ea88b6fcd09fc7631fac71 +S013/S013R05.edf 882aecd05b5b3869c55c483795743af24e2c7ddea43caafbcd07c6ef435fb6cf +S013/S013R10.edf.event 9787b103ae02f348ebe837cf8e545e3e630609a320868cfa229f0f82a0734ddd +S013/S013R07.edf.event f686071dd83e0610c6463f51dda1c01de1abacf998f19f9b7d3910c06492fc30 +S013/S013R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S013/S013R04.edf 796eb8df7d12b32e6ebbfb6756e527217c7b59a282735eb782dd50f5f16c39c8 +S013/S013R13.edf a81924a0668c8af7b92bc554eccd15881f4f7f6e7a1811db5f44e11e5c61717f +S013/S013R02.edf f60098973655243b1ce53e1e1bfda84cabb9862849461aef58d170369f2700f0 +S013/S013R03.edf b3ccfde504fe3bc9377495c2b70feabcc415a2facdbea1ab0d33e4644f7fde66 +S013/S013R06.edf 2e615fe7a657d7047f4fbe789b66968dbde9394c16cdb9d0995f1c0d376a94a6 +S013/S013R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S013/S013R03.edf.event f338197f5dd0ca078ea8eee22145e57e694f7dce6a2bbd55f5f05346ce3b3f17 +S013/S013R11.edf 261e6a4c8f81071cd6f1309ebd6deef79496601c6b77a8fe3bcc8c3b065626a4 +S013/S013R04.edf.event 8e9579e89d1ec6576609e05f5e6215b4322a4c5375265379e3acd7952866ac83 +S013/S013R11.edf.event 1f581da8e4856c63e25c541381ff8a370d89525260484c85de24ca995a24a984 +S013/S013R07.edf 17a4e59d8c4fdd133f19b428ffe4927484814d1dbaad7df7e5623361fff769c5 +S013/S013R09.edf.event 04192a55fa7728d34533e76a1b831fe5c94d79c3bc9f1028f45644c51892a744 +S013/S013R08.edf.event 732398d864936092994f6aa5c7a3d554d1c1c35ff4fd7a90dd0c06a61260c68b +S013/S013R08.edf dac533ea38aaa6c7505565059a5a8e19825702e68f5d27f47edd11cff0035736 +S104/S104R06.edf b32a0d5028810a98f7712b58ec2c6009f135d0727d03abd0debbeb3cc9190277 +S104/S104R04.edf 21f1d57c977b6dd8e9d3e1a5893431cf4bf0a142c850e273cb34f7e0864dedab +S104/S104R02.edf 02b55d7a4f3e38a37ae12acc81cbf1f9c6f40ececb6290fca2a902c19ce6b180 +S104/S104R11.edf.event 78e5b5619faf1f99b53251a9e743644a731ec9cc5b6e60533a3695f33fca35fb +S104/S104R08.edf 505ca2e90c3476a945714776461c10ce6112ad70b5893b2ac80722b56d26693f +S104/S104R09.edf 7bfa4e74dab55b1fadab1c4c3567e9a612bec013a2da6047c855c5dd125fe27e +S104/S104R03.edf.event b50d31cc4a2ec520a336774ea70761d08ebeef4930f053a00ed66803060bddef +S104/S104R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S104/S104R04.edf.event e1b29e90b20be6fe74d2526e8f695d3e9dfe8bdd7f08c801c24f523ac253462a +S104/S104R14.edf.event 2fa0b9392dbafefb266a1c269022274e4f4638513c85370c47ce925b54b7d5d6 +S104/S104R07.edf.event 472673d75763793097b36d5b0883addc030cb3790ee84a18c36eb33ef80d009b +S104/S104R01.edf 359e9f6ee1667782fc85dc9c9c963fd8327fcc78c7c24381c7be139b66f89dab +S104/S104R07.edf ab366eaa999f517e5b23ca8021d7cf28f6ee29d68a165ee4a6e95775663c2ded +S104/S104R06.edf.event e2b79b09413cc4065a25ea2956bc7726f4bdedc8730e89a7b86a8617c79876c8 +S104/S104R05.edf 57c4e11375232ddd10c4b2e4a4212956b4c700a8c855a788b3d187e653ecf2ee +S104/S104R09.edf.event f338197f5dd0ca078ea8eee22145e57e694f7dce6a2bbd55f5f05346ce3b3f17 +S104/S104R12.edf 541340f418003d02928cfd51baeead5dcf82a405bc6dc20499e129d43dd8e8d2 +S104/S104R14.edf f1f07d0e2801a69d6dd1991273efbdef58edb92220425168ca195fabc7373327 +S104/S104R10.edf.event 353c44c45eb89b709590af77f11106666cfa3680e5470b61c607b80304933399 +S104/S104R08.edf.event 803329ff4c524f2f94c14ac888eb15a5670f44ca9e42a101568a0c16cd0c69b3 +S104/S104R03.edf e74ac8759624fad7c5059fd925d458f2952b893513381c86818619027e698ca9 +S104/S104R13.edf.event a4381c73837f1ba112959670ca4c474004b1d78b82daefb4ea220692bfe23c8f +S104/S104R12.edf.event 950cf97301dd495a2a6a7a19a93d67d2ee9ee03b2675e300582e19305f5a9287 +S104/S104R13.edf 907fe8ab003947ee5395c97f6f2425857ae0be24f4e95b32801cb08a5464e074 +S104/S104R10.edf 2fa882510d50bd3492537b204eeaa5f29e646bb81388ec119276aff07d8ddd94 +S104/S104R05.edf.event 440457b385c6d53d2340acbe5512027de7800fb1514858b055b126c10e58b404 +S104/S104R11.edf d0a943d736737361dea98c5585d63a7bc1b1a4d1130fb43fa43255426ba73b96 +S104/S104R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S038/S038R02.edf 7af50c7caa2b873015cabd726bc47ac5dc57de2ae61d151e278dd2613aca3681 +S038/S038R12.edf edb6693591ebc3e273004339ec6d5eb7b11c60604828cca5e61e0d4df8eb22c1 +S038/S038R13.edf aabefe770caa5296de15ad7395dabfb5947a6daa79bec50596dc0eed3b505243 +S038/S038R08.edf.event 6e13e4f708f4b769dde500a1db747206aa87951c3914cdd436fb7f07e9aa5052 +S038/S038R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S038/S038R12.edf.event 3e83abe294ec7b278fb4495c4fbc171e9413e9d805ad8464dc6ea5a4875e7625 +S038/S038R05.edf.event efd977506cc195b985e542f3333bc334c4793652f9b52580c96ef8a5948f4db9 +S038/S038R11.edf 315510579e7c607daa75969532808476c162076335ef7bd981aa7a02c62b894c +S038/S038R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S038/S038R06.edf bded2cfd25b9240d522d3e5858a6325b0ae13d46ed9cb01c5dad5634c6136227 +S038/S038R09.edf.event c777015bef40a19f68f8ed8c37572f501bc00d9f061933697ce2f238c9ad3f9b +S038/S038R06.edf.event e14dc31d476c11841d45564cac660be9776fccedd3dec71dcee4c5232f00f25c +S038/S038R05.edf 34fafe40c0e98874f023c9548e12a139452c8cff9d71836272ae2ca53222cd7d +S038/S038R03.edf 6d703baf9b57dec7da30d953deb26c24f93ce290240ca136d707ed5a273cd442 +S038/S038R14.edf 160da28cda376cf3e4206f7892f9efcf9342cc701bd9136a31d57d71048451f6 +S038/S038R13.edf.event 83f18e3a845e17346dc10fd176b61c6f306078227a59bb51610834234d1454aa +S038/S038R04.edf.event f686071dd83e0610c6463f51dda1c01de1abacf998f19f9b7d3910c06492fc30 +S038/S038R10.edf c358329a87e97ea80a3daf5702e9d7114e954bd98dca5a157702ed096f3b04ac +S038/S038R03.edf.event 350042ca5c37cad9cabe8c469aead2bd074d996b13c69cafba8d24cd8fd825fb +S038/S038R01.edf cf352ddee891d1f3f6c6aa3fb4e947ae0c89b9dcb2edd0cb2c75defa5c5eb2e1 +S038/S038R08.edf 2f5146836f84423a5dc0a274f4d9da645bf7e485a5100d74cf98508bdac29b69 +S038/S038R14.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S038/S038R09.edf 2abf752ee32dbfcf22c85bd8137c6976b39b46169a2f63d13a769eef0243ed60 +S038/S038R07.edf.event 82c4504914809d88b1ce13e11caa12c3a659e1a2edfab31c2e894283b14daba8 +S038/S038R10.edf.event e4d125d65ed410f2e37eb6c7f7075c585662cb4e5931bd8436cbd1b59c474f77 +S038/S038R04.edf 45e64556375b00e2a2541ed5e14f96c79f4b86c18d54fcb1bafb2508c1ef06f2 +S038/S038R11.edf.event f500286a76884018ad149ef34cc8871332593723b30ad3d79f8f39236a5cc25f +S038/S038R07.edf b6c989c93126b209c5e513e3c8cf32521a86b0ce8b89cc811a1a653c18ee86e7 +S078/S078R03.edf 108c6824287a8a48eca4aba572a0a689bf46931e7c35556ebd36957907c16ceb +S078/S078R07.edf 43521ca9ff9b7cab6cf52bbe6313ea2cdbe7772a27f42e8a310cd0aeccb4be34 +S078/S078R14.edf 9bc71363b71480789c601f6d9cb90aa8bc690567a54a2474af2d9f2fd8c6e37c +S078/S078R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S078/S078R04.edf 4448c6889ea396f851dd48708509b0620974421768814d18d1d5b0f6f22c60c4 +S078/S078R05.edf.event 190f359cc14939d921985886ad1c9081e5e2059b38ae9d130845e8dad044d790 +S078/S078R12.edf e4f6f983bf941c4f713b353a79594af49095e7f002b102ec086a93dec3aa37f5 +S078/S078R14.edf.event 0db4656c1041f6626ac6fd54117fb1e02890492bb86525e197e9ed116a0fe6c7 +S078/S078R09.edf.event 5b005cafab5d6d8968aafc95da4c7b50e36cdf3bf2d71b98cd18431017101fcf +S078/S078R12.edf.event 6e4a2f2b413bd53735575eeda52d35059687bb58d072e4de1626bc16d7a28d24 +S078/S078R10.edf 222df3b50cc0eff62d6fbbc2182e3365a74d996997e9b4219f904201310623c5 +S078/S078R13.edf.event b974d964a889e51c36cb932266f84898e1e404062fac116381b220b354f04feb +S078/S078R04.edf.event fb76d885a6c380c62ce2da054f5ec78c9f0178752694a36e4b78183ec8850830 +S078/S078R01.edf 42899f0af33e3bc857c963066f250f261d4e76d73c0c7700d223b09d13ad495c +S078/S078R09.edf 7c12e0c729eeb0e250422ae71f03558dd411c9f56d63a49a5292f13630d9366a +S078/S078R07.edf.event 176fd10c94c5d482875b1ae7f0756ac60194f41bba099b0b40e5efd4e95e8df7 +S078/S078R11.edf.event 8e9579e89d1ec6576609e05f5e6215b4322a4c5375265379e3acd7952866ac83 +S078/S078R02.edf 3201f4cdd5585a66c882504f15b3427187c78effd66d16976e178ec396abd878 +S078/S078R13.edf ab016fc3d05e5277fdd813ffecd387cb5125ba62d3bb997ed7ee4008697a22aa +S078/S078R11.edf cfad033ec2419b92300f61a64be8f0a547ea531ffc20a0d51719721da81f4f1d +S078/S078R06.edf 1623a5be10e9f4ac175476f00e8b0637b7a63a0253fff92eb7ac561bb21be749 +S078/S078R08.edf.event 51f07832e9b1d3d8c667f73dde4aa38f9d3e45cf2a4c2baf8e47ea328c860420 +S078/S078R08.edf a008d9c403db430abd52d91a04955431b675eb283d3fb9db80e75feb08e3fe39 +S078/S078R10.edf.event dea45ba8a8662cd82aeb9d6c523756ce7079f3020c2ad1b23d6dca2f63b5bf82 +S078/S078R03.edf.event e1b29e90b20be6fe74d2526e8f695d3e9dfe8bdd7f08c801c24f523ac253462a +S078/S078R05.edf 77bdcfdbcf477261a4d6dac03c7a7d2278c445f4d659da8b5693a1b5e70852a7 +S078/S078R06.edf.event 6e13e4f708f4b769dde500a1db747206aa87951c3914cdd436fb7f07e9aa5052 +S078/S078R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S034/S034R01.edf 62814a71a5926f51efe322e6f959b0c6a7b18da7603474a4daa3de3cd4ac2718 +S034/S034R14.edf fab8316da4a5398cda818d57bd9db5f016a3c500ae387bac4e65f9c5eedcf1aa +S034/S034R04.edf 16500fe53e24fd3683538d894bc85214a41801e172787e68fd7e1dc5a42bb56c +S034/S034R08.edf 01d92913e2d1f2bd5eba5d16f1ce03a150f6dba999db83a442e4d6a754fd4c44 +S034/S034R11.edf.event cdc1e4d28716284ddcb2f27cd78fa71625a5d0743587c4085cd40553c3d4593f +S034/S034R11.edf 104b08f5f2f728a5e88b75a4ba8037aa6daac2592bc5814580b76dbf1dbb32d5 +S034/S034R05.edf.event e6e3fae8bbcbc00e9d7d959eb1e3c2c0ab93eb9e896a0adc93c685329e429982 +S034/S034R05.edf d81499b1372d6ccf90677a7a75ab740ff8250347e7883cd9e15035687bea1350 +S034/S034R06.edf.event 626f0f4bcd2b8e692655298d20611bd8343efcaaffc9750f9de2d48d12d814bc +S034/S034R10.edf 9f35f25a3894e5438e2c4673605ba0804c5998e4e75ec1fc5662503f50c77293 +S034/S034R08.edf.event 242b32e3360e3746853cdb2b5bc9e3680de1c253901aec55810ebf98a6f228cd +S034/S034R03.edf 5605f6ea99761ffa6ef64072b3f74688b3483656fe60ec711abec72e90a4bad8 +S034/S034R07.edf.event c3b5fa1c4d34c735d2c72afc39bc9de181add93cfe26671d98a67a907d91ae61 +S034/S034R12.edf.event e5ff9b02c6b12b21bf3d43e30b4e2e24dc33e4dc8e4f263b175a6be78cdbecd4 +S034/S034R03.edf.event 6a82f1537b9e346f18c99107c26f471d6dd0e1a1866c60ec0fd81e8ae2d94fd0 +S034/S034R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S034/S034R14.edf.event 4c04256488608599d6bb2976fe1f7764651501c5b36fa6450a25871cccdffb65 +S034/S034R04.edf.event 72ce0e64e6b25c72495c25f11b75df8d02784d1e7645c959e2379fd7b73c8959 +S034/S034R13.edf.event 80df586db524a77e67f11eb275b00d505b0ba9212ee984d6f721958f2b100b4b +S034/S034R10.edf.event 8e39b81d7164017e1d67672dbc17ff18d31922b3f6365e9e1961814c475b2210 +S034/S034R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S034/S034R06.edf c801d9aada4694ed376b3b1804003c1c5bec9dff51797504ff0f2b93f9c6a580 +S034/S034R12.edf e7e7b75d6af726120e7482462e429a9faab0b1509eee0a73e064f972c4ed9779 +S034/S034R09.edf 044914d21373682d7d59fd35aab9f61350e7594f7b8aaaba9e1c3fbf5399e7e0 +S034/S034R07.edf d687daafc901f01b9536129779d8e53ebcbe1ce55820c0e4a433ec27ae2f04a2 +S034/S034R13.edf fbf72ecf8fa58e695e5b3946827190174beac79d6684da47288ac33120c9718d +S034/S034R09.edf.event ebbd9bc0cd84bebd02e71f43989cfd362624adbb968d778a6e759a70c66956a0 +S034/S034R02.edf 5a59bca545dfc4fcafeb49a9c11bace3a0c91029c941c9f2a46fef9904681514 +S026/S026R11.edf.event 6ad812d50b44ed49ee87e09d1cf28b68a99855b6d266be8b9017d8056de057b4 +S026/S026R05.edf.event 96cef3a9a9e2cd7f438d53008e256b198c48c6e0d2f0b2d70e0d296180cd58b0 +S026/S026R01.edf 2c4c52f3afd7dc4742bc1b009744da1172bb9c4f45546acee2fef230931d411b +S026/S026R13.edf f86fd8bc5817c7cb98176b0e58e7c4a3dade5243311676d1e9fd4a227f22e999 +S026/S026R13.edf.event 7c83be0506163b52a89548c7af6d4893472403c2bab3a455c7d8c92bf3550ad8 +S026/S026R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S026/S026R09.edf ea6dea29fff8a84242be061a37dac15b84acacee2a97045e18ca219943c57bc5 +S026/S026R08.edf.event 78e5b5619faf1f99b53251a9e743644a731ec9cc5b6e60533a3695f33fca35fb +S026/S026R12.edf 681a772c11bbdd917acbf081308f8854c972afb4bf8a05d50fdef1b1c86feff2 +S026/S026R09.edf.event efa5d828429e8df393cf3e5b452a00dc9f05f3ad9eeeeb119ad18eafd1cc4e2a +S026/S026R05.edf 4631e05233933160bb1ba8152f03167481004845fce05bd821ee424dcad7610e +S026/S026R07.edf aa551f530d6949a53ddfd0a4ce0371d2ca8db7c97e11309c45fae79a1600824c +S026/S026R04.edf 1e6bb923f94a3b28354244ea4302d213e1656bb309fe3b3ab069e9dc0b2d62ea +S026/S026R11.edf 39666f75b931ce689e7b76bc9286eec8258cb4bd745f7208b16de318237f9382 +S026/S026R04.edf.event 3670ed6734a1e3a4a23fe378ef332968f910405646ccd883a62369d2add4b888 +S026/S026R08.edf 2c035db71fdf3615a23be361328ff9e9017feb97c097b49a4f6c8aff2c36f1d8 +S026/S026R02.edf 462ce4f1335dcfc319fa4d706b6a23467512366055f0e3283a836a0232891cbb +S026/S026R12.edf.event 37b92549c1fe5d740cc394805738f2d228f8fb948bb4c3aa4817c4dd4b04b9e5 +S026/S026R10.edf b8ee20e9711cc6deae83ca355a3665616d61d0114c263db49138230a71189eb3 +S026/S026R03.edf 5ef33f46f67a415ce54210af6ccd112f00a517cba357489f4cb66da7d2e9265f +S026/S026R14.edf 829b319606b77a21a3c7a4a3906e2c6f2301ae1f6b0d1003c6f3d4eb41297f27 +S026/S026R14.edf.event 37c09b028d07b5b1954199394e59b7c78fd1325c5fada30ce1411ada2513eb23 +S026/S026R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S026/S026R06.edf 3866938781e7784301ba3a0f61e753f4fe0b5117a787c61e1f7b5e5c30c0000c +S026/S026R10.edf.event cfb6d9316552151b2cc7a4fe7b3c98b0ffddca0cea554883679586887149feba +S026/S026R06.edf.event 2fa0b9392dbafefb266a1c269022274e4f4638513c85370c47ce925b54b7d5d6 +S026/S026R03.edf.event 212052daaa4c0fbc66f91923236861d93fc52f73403f6b4d988205287f1f9ece +S026/S026R07.edf.event 25af506ba70b68343c97ccca1ad0f235958a8dc9bfdd84c6f7155937e7bc7efa +S007/S007R06.edf.event e318e6bd044ead383499ec22af114e14b3a59def9653470287d411ce26ee7335 +S007/S007R03.edf.event 7c8a0ac57a3537143f6591a8d4f0420a4948e65577e0caca7c08eb06daa4dbaa +S007/S007R10.edf acd9571b0a6b1f864807e556d09d913592d1eff978e7469bb68a9fefed62e172 +S007/S007R07.edf d801688adfc14ce87dd52f4308b0dbf72fffba30fc5d5b66a4c05a4f3b9310d6 +S007/S007R05.edf 6697e3a18c3025727806e28df7c378468b700f73532fd61ecbebaa2960d712dc +S007/S007R14.edf.event 600983ef19711fe2016d742d1857fcdfa4f0ddc7c5b8c88773db0019f92315d1 +S007/S007R12.edf.event 94d1d7007146c80e4f45e873986a770b4b807a34cfeca23f6a7d9054865154c1 +S007/S007R09.edf.event e8da7819eee7d2c77d74fa9e6aec49532a6b299f30b13b3938ad7ce0357cfb02 +S007/S007R01.edf 2ca422c6076860f12bce174799c5d7e85cae46b7b09a8e8519681d0f82168b22 +S007/S007R05.edf.event 54016a6260b12c8b99943951ccdc7d5425efbf9ab503ef1abeb93deafb262790 +S007/S007R14.edf d6245b9bf35efde8522982146138e2f03fc352217579cb0c8f4d83eedd7d8c9c +S007/S007R11.edf a2ec8339ddfd99168bfa0fdb6b94145fcf6e17abd9816f950d3182f888928b76 +S007/S007R04.edf.event 194c7017f9fb0a9e8e5ed2d2c50b59fe067aa973a5e75567ca562949327e2edb +S007/S007R08.edf fa8cfc38727e908be4626cf82b19533f7a761f102319696e53e4ee2d61b1092b +S007/S007R04.edf 3b31e50c4a5ebbb25459b1ebdf802b7ca86010857637580aacd53067350553a6 +S007/S007R12.edf 70cd3287d6b4821661521954206f86dde9f5e62904edd76cc0cf1d03fe112df3 +S007/S007R06.edf 9f6e8d2367dd2965fe71380ad6d42c94e13848d589516fda86fa0eb93481998e +S007/S007R07.edf.event 5c551f31bb279f96e1589e6bd04f5890f6ec5f9b8eba042c3e54359a4cd3a0ee +S007/S007R08.edf.event 73d0d5230c58b2964db8202c6deae200c4a894209cfbcbdcc9b9898f2359f015 +S007/S007R11.edf.event e697ba3ef839244357e1c111d7dfa9afb60310a0bd8b7935ea5a426a1711194c +S007/S007R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S007/S007R13.edf.event e2f45590bae85355ca04a69408a62dab39a883a35597ae39c912ac5923e8579f +S007/S007R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S007/S007R09.edf 47aed2ff57705ed0e534cca0fe5e7cf2571b7709efd50c61c2480be4752e0244 +S007/S007R10.edf.event 582fbf3e4f5bbd51cc3d858954988e7800ce943626d6f081f659cdd9b863fc0a +S007/S007R03.edf af7f2fe4fc8ae5b727a2cee5e41a58ad0aca7907f0da83b67a754ea7e94ff3a9 +S007/S007R02.edf 9afdeee151fbbcf9ab5ab3537f8f647f0303d97f506048cfdcc6a99d8da809a7 +S007/S007R13.edf 89c78f89c4436ac06622d314ed5cc49a825418a7f051f6c0d3675c70f19cc018 +64_channel_sharbrough-old.png 96d50a707bc8841a946682e47dcfa6ded573ed91dc5f1c01b129c281473f0ce1 +S064/S064R14.edf 330c6c6384fb9a7cf686ed9f230d180cb70a863ec824fccf1a55e047b1696aab +S064/S064R13.edf.event 45f5eb2c092354aee3ed9873f05fbb270ea898808952a8e8d89f53a58d171ca5 +S064/S064R07.edf.event 0c18fa49d469703f30b80a748450ef0688aa72103e201d690fb064dd55c7e540 +S064/S064R07.edf 93149a39154aa81119b69e6cf2c849b214541ce7d16f48a09091efc8f54426d3 +S064/S064R04.edf c4fd5e8940ff3c9809023886c770dc3ca374adcfa93b85784d749241918ee5e1 +S064/S064R08.edf.event 25b9b610fa5d47c04ecf80ff5afc8dc8ae41908a3571f3bdc98cd14a55c003e8 +S064/S064R09.edf 28410cf933254c2c1657a0c89e0177d5ddf25512988dd414a2efd303e3f1bde4 +S064/S064R05.edf a6611a3362f3dc1b41205d9fc5270880b3bea097a7b5d820bbb8dd4dbe236e51 +S064/S064R11.edf bde8d57b66d9904d666702e0824f209ba0ebef5a1b3e5d01d03ab7807e901671 +S064/S064R02.edf ba4aac54d62892710166b5038da3485a1158d1e03cca99fa9710922623a35bd6 +S064/S064R12.edf.event 1071a29bc96a7a8302b3670dbd4e05d2ac47cbf397e29b74a32e6f4029d8a52f +S064/S064R05.edf.event ce9aa6f7710315564bedec57181565954b52788105428ed69c693ca407a546a9 +S064/S064R09.edf.event 7c4bd521fbb97676e1187543f70b99a542e6a60682c3ca4455c69b001e97baf2 +S064/S064R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S064/S064R01.edf e208a4c403cb3597ee704d7b59918e86faf195fdaa28587b84efc86708109219 +S064/S064R10.edf.event be8b4e0108640ed6cf994ccaa0ea908d53eeaee5d7d1fe5059a06c982f4b08b1 +S064/S064R08.edf c0abcac7f314a6a8e921f3a3e100feeb7454f3fffaee325a89930660c5f0bb6e +S064/S064R10.edf c1e0330c970bb6b82a6501027da9de5b62ced4fe5b1fb85db11a3d6c3a8a5a41 +S064/S064R03.edf.event 57cbb289c3aecc1dd1481829d7cbb9f0c68e99192017986dc9107d7cad5f6506 +S064/S064R14.edf.event cce8c6ada8b4f46efbe5930fa6779f8d1e0c787058b6dd8c7b3841254bbdaf35 +S064/S064R06.edf 95acb614f05f3ec49fa426fd474ad02bf26b8f093e837584961472559ae1ffd6 +S064/S064R04.edf.event c0e03fc052196f399444ee8e817cb9226c53c8b1d27137831cbcd0d283821560 +S064/S064R11.edf.event 549c8a3be85848123efbb6bdfc0cc6622bf8ab61ed733497407936b0086b9805 +S064/S064R03.edf b3001738030c26d58536d233a18956c35e12640a4b226c663e05a3c674914645 +S064/S064R06.edf.event 45f381c89be373b8eb7565ebc5489e673811cfc334165888408d2e99864e484a +S064/S064R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S064/S064R12.edf d3f5426e082f27bf037e9ad16336a763b95b00578ef426cb1389830cf40058dd +S064/S064R13.edf 466b835133c3edaaabbcbc612e90cb438f3b216d922ced5419d8ef189eb63423 +S005/S005R14.edf.event e19fc47bcf5b585ab27ad756884c0c4cd37d239bb04c8bf15e2f33fe9fe05e18 +S005/S005R08.edf.event 9825c80a69d06961cbce2e12cf8d0aa56d063e5f4598312c4e5b78693a0219c1 +S005/S005R13.edf 2012101a68c9abcf8021eca5587bf3305ef36ac983486b3396a3c012227b3c47 +S005/S005R06.edf.event bed28cb624951271916f88bc556ff204ccc63699ebc4523ed8043baa9724625a +S005/S005R04.edf 956d0857b17b040955fee9b2384f818f85bfb02248c387d9aa7930c42934ca0c +S005/S005R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S005/S005R11.edf.event 710672ce0f425a207ef543d23f608683e1863d7423702d511235d71ccbd289cf +S005/S005R09.edf bdc007224d5b82152476140b18d2e54b9abdadfeb509c06e1a0c18f62bb0a60f +S005/S005R13.edf.event 11c7903b0dd963937962aeddd4ffb77feeec607958b581d996b712009c71f910 +S005/S005R01.edf f84f58d7d96bce1700af8b2c9e333d66e4b2183e34b3ed5634840fff37845af0 +S005/S005R07.edf.event 6e13e4f708f4b769dde500a1db747206aa87951c3914cdd436fb7f07e9aa5052 +S005/S005R08.edf eeed6c328ee256dd2c20d1808e05819bed4ce56b8de1c57914ded00565b6b7bc +S005/S005R05.edf 40ab4f0bff456a6b55cd55f6a80449a1865fc9a63a202f597a5d679b14978380 +S005/S005R06.edf 07260f0bc56394b88fc506823779ebaf9e0b6ab6286608b010900155a4d206dc +S005/S005R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S005/S005R10.edf.event 020a012ee89a9fe2c7bcf34bf02c0d2d78b688185ed74043d21a3d53053e3882 +S005/S005R12.edf.event ea6f6003ddc3676cda270c185ba40fd7915630a24511085aeb31217c9a1e8852 +S005/S005R11.edf a4d4111c206de3c094d23c9fbaf2b3fece74eff7a68a11073f29dad9800653d4 +S005/S005R03.edf.event 48bfdaa247bad1b393cff54386a6d30257090bf0e7327f31b2b320921da53270 +S005/S005R02.edf bdb498c613cd048a889899282e8f5491c23a76731f3c2be11800362b7bbcb836 +S005/S005R05.edf.event 8b26d9be3cec072b0ba8e7e1b1aa9f46dbf8f50992131d413440192fc40ccc5f +S005/S005R07.edf 630fbaf27a7a962a4a8bd61396b6a1c4f56b44e85fa5e9400016ca19085ad1f9 +S005/S005R10.edf a5721f5a8229799b6323e26f5f2fa149c121ff87d4ba73b30fe9280602aee140 +S005/S005R04.edf.event f1d7c85c7c4b298aa795662274613ada05d95ec81ad8b21ce4c8ddca5a11ecdc +S005/S005R03.edf 3bf2695b66661a274bb099dd093c8f2eb4ede8a7068ec4bfd0a1fe9f4bfc0e18 +S005/S005R09.edf.event c843292c2d927d69501ccd581dd6688cd971a162df8d02a7eb20e6a3c1aa2d83 +S005/S005R12.edf dfaf07c8ecc583b07363485596258e66a75fb33169496c62918c6dd0803814ce +S005/S005R14.edf 77d5b9b1f03074e96c0e42234f57363272fa90501661cbe038bd387f3ce922e0 +S015/S015R09.edf.event 20d3d791a72acbcdd619cb968567a104858a5889afc628a6fae4776c90c0780d +S015/S015R08.edf 70e4dcfa5bb501007b4a502fb1ac6975128fb316de67eb825f8eee00cba9377f +S015/S015R11.edf 5403967a07422bcce09d1d96dd78d0eef6f29344d8e0d388975b483b93d47341 +S015/S015R05.edf.event 3764472ec04047763aeff3c1680cbc45cec3a88ed5f483d80cfbb31b50a12ac9 +S015/S015R12.edf.event a7dd5d461dbdafc68a647202ccb3decd039a172ca33d925065fad2be2efab6ab +S015/S015R03.edf.event 2eb503fa48ef7e13b77098d860c716de2d0eb55a3a0580117eb34aedd472a728 +S015/S015R13.edf.event a4381c73837f1ba112959670ca4c474004b1d78b82daefb4ea220692bfe23c8f +S015/S015R05.edf 9119fdc1ff6ac9f67eb34d14803c8d1279a1d4c013a77f05b99abe2e334dd55a +S015/S015R08.edf.event a7dd5d461dbdafc68a647202ccb3decd039a172ca33d925065fad2be2efab6ab +S015/S015R06.edf 705c63ec04c0f9096cc6b4f32eec0bcea9a0bfa8d01aed7494b67a487e014afe +S015/S015R14.edf.event 0ff4d5f572885db930cfd469a0c25535d26e1712145e5a489a5e31e8a2020961 +S015/S015R04.edf.event 4ca96a0e24908b831c877816b86e3dbd1eee397d9d9851bd1e890d67134c57a0 +S015/S015R12.edf a5e56adba75340447849c46eb049b39799ee98d68133357741c6980f8f60c54a +S015/S015R02.edf a4aae371744dcfe5febf36d2605ede4d704524f9971f5501c4316a077d91562a +S015/S015R14.edf 3f57b464e13807f30aacbfc2f6780bc02bf8faecea883725683177416503c875 +S015/S015R03.edf 9de915e373fc372b372cbe9c59692c7c961dc9d2ff12cbffcdc99190a1bac99d +S015/S015R07.edf 914f9c987bf66fdbc3183531bbc5ca97ba8afaabd8864811c438d8ddb38dfc3a +S015/S015R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S015/S015R13.edf e154f143697251a1b3401fa5792fe47c7d9891a2cf63edd1cc67234752b428e3 +S015/S015R06.edf.event 23b6fc268df2ca2b48b0a505a6eed055a62dad293041c180f6f03136d0f4b36e +S015/S015R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S015/S015R10.edf 67233630176aa19faa4133355be20476cc8f571d9327943b9d35a73ecb96f519 +S015/S015R09.edf 628b83cdf791ab95545606d1b879edd13449da7e143627f931a35680de2b312c +S015/S015R10.edf.event 48ad6251760a77acc67b82ce0b201f4244cd1385a6181c8236487af76fe1636b +S015/S015R01.edf 79564c46036cd6c3d1371811f2cc426c9ac14d09d7da3dcf935a65d1a633c9c6 +S015/S015R11.edf.event 950cf97301dd495a2a6a7a19a93d67d2ee9ee03b2675e300582e19305f5a9287 +S015/S015R04.edf 1721d4a066e0c28221877d0f9e7da2402bdd924a532f5f19261c429def061273 +S015/S015R07.edf.event feeb9bf47f8f6dd0e083c64236055fd7ca30a06709747978b6a7bbc0b632e21c +S081/S081R04.edf.event a8ce17ff32c2c3aa820817e047ec3ff9976bd33355d14877f0ff811df5a288a1 +S081/S081R14.edf.event 0ff4d5f572885db930cfd469a0c25535d26e1712145e5a489a5e31e8a2020961 +S081/S081R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S081/S081R10.edf a8cf1995bc0c09a2a50bf889759ab4c1076735bf6a6144bd73a9ff3e845d885a +S081/S081R06.edf 726507264648754d688db166ebec9836b7be70025eebcbb8ede1ca9e47f74e53 +S081/S081R03.edf.event fb7055ba8adb05cadd3009cfa9adefacc5298e01d2b7156815f6424ce1d4f3f6 +S081/S081R12.edf 48e0a4562e2355a3737b412fc54259c7174269f5e6012448fed56253854950a8 +S081/S081R09.edf.event b1046f2c937e8d05f2c3e45473ca880864a5d33222d740a0bee41b055662ea91 +S081/S081R11.edf.event 48bfdaa247bad1b393cff54386a6d30257090bf0e7327f31b2b320921da53270 +S081/S081R09.edf 2662fbeb19e4154447cdce6f73b767e972cc5abddc9c7c19b1a65acd24166847 +S081/S081R10.edf.event 7925ab0749163820c00af5a617adba24f1ce1c711886e12def08eb72594e10cc +S081/S081R08.edf 7faa1f739438962a64487e2132aabdc5c9528430a5f8e374f4b5a9106cc70fa6 +S081/S081R01.edf e5aa41fe4d8447c05d0e3efb752f1312210db47de6a670da2c7c57b3cdb1bad8 +S081/S081R05.edf 9f5bc4ef1c7fcfee0211319ca64aa04ff7a3b2c01c0c5dc460eaa3d17d3b24ff +S081/S081R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S081/S081R08.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S081/S081R12.edf.event 472673d75763793097b36d5b0883addc030cb3790ee84a18c36eb33ef80d009b +S081/S081R05.edf.event 1cecdedf3d7f8b7931b4cd84b48bcd356337c0ee32518d737ce0ee8f0d428d8f +S081/S081R07.edf.event cdf1a70ff91abbdc6f14a7ca794a7b5932276819e6f7c68ee344c3d21e9b73f0 +S081/S081R02.edf feca30506294768d8b87d959f757ea1c95e17dd5749627a6d7cb4488b314e230 +S081/S081R06.edf.event 931266ffca879dea17f50ad227bae49a0d891b282f30fa3ee4b13ab8623dc5eb +S081/S081R07.edf 3eebdead7b378306bf45d32035f06493de11b6e0f6e7d127ea1f6281371efce7 +S081/S081R13.edf.event 0aaac0e6493abaa7abc2bbcabb2ba2ab9cf91a665d7b07e95e181cb6e7a7d207 +S081/S081R13.edf 163ad2dab963d61eeb59a57e4df45b33c7183bde1209396ccdf3bb74a9c2008a +S081/S081R04.edf abb5db7c9c42a09fe10644c0a071d8511b1a31b0014258e0b076cd9195b0ed2f +S081/S081R14.edf 1ff930fd50f5b1710395ee4e4680ba050f01c776b3d6605609cf2446793159fd +S081/S081R11.edf 98120ee5954f8e394f6405ec853f66cdf656c24c456b6fc004b66e2117135c98 +S081/S081R03.edf c493f4eca660b386bcac76cec638928f5b98cc88eea16ff97b67993b6405ea5c +S018/S018R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S018/S018R10.edf.event 3cbb6086e0e7d8748f07bafa5905b530a6f1a43c1ebb1a06c6f846a82247c451 +S018/S018R08.edf.event a40b48032f894d3401affa4d6ccfd4defb4c639cf235451c5fbe2296febae7a1 +S018/S018R10.edf de1322a24dc7d95c29d64d91488cb1cf3ea30aa5953c7fbc80b1fa42d4ab44f2 +S018/S018R12.edf.event d090cffefb3b3a6b7c514daaeff9edd2dc1c358aaa5ba0a069b62e257f59e09c +S018/S018R06.edf.event 0487cd7ee2fef7813667623ecbe113ebbdd5400e7dff28fd7f0f7b1e00d585a6 +S018/S018R06.edf c63f23d980060ac721c705567e65603808dffd0af32391c6e2528072bdaf3cec +S018/S018R03.edf 6538d4a1fe7df53296897dc6efb2274e78429346086c6383db9c58af16c46251 +S018/S018R09.edf 75c9cd943edd18b43cc73f8b3702e3c7c2fe58dd35119b147041d4ba40e358cd +S018/S018R13.edf f7886c46a154ad73254422b68b56d81e0b986274ab7d1db177de4ec656c88292 +S018/S018R07.edf 1bfa4c8da5c4f30a71797cb27f2c77cc02c66133d3cb83430918cb2950e3d7d1 +S018/S018R04.edf.event cfb6d9316552151b2cc7a4fe7b3c98b0ffddca0cea554883679586887149feba +S018/S018R07.edf.event 6546377ca20368b45bfd1f06c72e153809df57db54b8731ecceb6c8ec813a774 +S018/S018R05.edf 86d9fbc0881a182960ba9486a456f2f91710e94cf2ad755247dd37d352b40e19 +S018/S018R11.edf.event 61878a566785fc86672b3e061fc0eefd0fb9735a4239d8f13ceb0d08ff22f60d +S018/S018R12.edf 50b4e74957541c9f1f2161ec3665b58b247727b50ed9284f1d173b9b77d1feef +S018/S018R13.edf.event efa5d828429e8df393cf3e5b452a00dc9f05f3ad9eeeeb119ad18eafd1cc4e2a +S018/S018R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S018/S018R03.edf.event ffbdc0e528335775cb88a14baab7b7f1fff4fa1647a473bcd640feefcbfab5a3 +S018/S018R02.edf 61c88fcc56859ba2299afb7b1f72a288062826ca7ececf6898224dc9b52c7a70 +S018/S018R01.edf 664012489cbc59928d2bbd665e4f3d557421e9ecec7a8ff6f46faa64ea9e7028 +S018/S018R08.edf b417c65a63c4b70f7eedc81ad11f8b5c067be5143d343a250d9397050ec5e27e +S018/S018R09.edf.event 9aaec3ff6fcd8c6d47bbf0c154dac87cdccac4bfb099e5995ee69afc7b34257b +S018/S018R04.edf 0b726bfd4ce56c9fa7417f84f52759c40eb7cd326f06a25374034c199f5fd8bf +S018/S018R11.edf a08b1554878eedfad123f7a86e034acd22cd9052992e5967b693e13c94e14fff +S018/S018R14.edf 33e7d70d1b51cb549dbe2785e85414e3c82b039c4dbfb71be40c2bcd48136dcc +S018/S018R14.edf.event 09d9d4cbfb435c34d0498269502687afe1e41cb410faf772b5fd4389e435ad7d +S018/S018R05.edf.event e1ad9bc40c1368a9f08ea6dd90c3750fa2947ff48bcebe59b7e89441a2db68b8 +S056/S056R02.edf 061c293fe7d9d36359e77b59c26693809fdf02a4629fee46e9c857b98aa9ad47 +S056/S056R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S056/S056R01.edf 29f8a7a25c02b872dbbf0cb52475ed55b45fd3b5a90e2fc5025691ff389b04b3 +S056/S056R04.edf.event 6546377ca20368b45bfd1f06c72e153809df57db54b8731ecceb6c8ec813a774 +S056/S056R10.edf 3d4f919505b19d346f4d81a8af960119113de7d69ca04effd0d6756ba7e926bd +S056/S056R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S056/S056R07.edf f404688039c70c11a61caeceff3c9e02c214d83d3a404a78947c1dbdc0e4d41b +S056/S056R09.edf.event e1ad9bc40c1368a9f08ea6dd90c3750fa2947ff48bcebe59b7e89441a2db68b8 +S056/S056R05.edf f0a6de4bfe5925d98cf3c0bfcef21a9e61cfb8165c3caf40fb6228c8a507a29a +S056/S056R06.edf 6ce8cd28af985d32ab874784e311f06ae0c2fbf0b9ef4817bc0c561bc4abbd0b +S056/S056R12.edf c47457c3baec40f4b7205cd1fdd878ab5855cfe0d32fe00655639101efddd69c +S056/S056R11.edf.event 7f2596bafc4dd481e36c47d0e562fb6c5f9b7e91c2a915f19f66844b55b75410 +S056/S056R13.edf d04270980331cd9888307b60cb0241f83cd4f4f6a2f840d0350523275776a3bd +S056/S056R06.edf.event 1ccc28680a9b24af49105d307967ceb434f5229a29e70fbfde089b2d092db7c3 +S056/S056R14.edf.event 1c886979e539efbac81a65fd3868773f73efb803324a60ebab5a203d75cdb97a +S056/S056R10.edf.event 5e6dd7d9983b10c75f267d25fb4f039777b8f17f9d64869cb39446d1e9306505 +S056/S056R07.edf.event 88e1ea56ed0459a99b011a3ea2f25f947016dd359b2d4fd683f838ac00d993d5 +S056/S056R03.edf 5714d4361308d21f12c5fd37fda0f2513fc0a2d4a1ef7520b5f20ee302847705 +S056/S056R09.edf 9df278a8cd6331dbbbaa7c79aaeaa70411906fc23b8fea9f3e44a1fa85cdf62b +S056/S056R12.edf.event 440457b385c6d53d2340acbe5512027de7800fb1514858b055b126c10e58b404 +S056/S056R14.edf 281285940d65a262d8544c4ce035bd24720fc5bac685d5e557654aa0470afe2a +S056/S056R05.edf.event d0280a6531ef96d2b622c2d562c05bf53a0d00439a4819213365b6e52e54abd1 +S056/S056R08.edf 0fa0554aafcc78c38f2e7d65f5941c528d26741194a1eeea8801225c44799db8 +S056/S056R13.edf.event 020a012ee89a9fe2c7bcf34bf02c0d2d78b688185ed74043d21a3d53053e3882 +S056/S056R08.edf.event feeb9bf47f8f6dd0e083c64236055fd7ca30a06709747978b6a7bbc0b632e21c +S056/S056R04.edf a618b25fc7570d8fe836949761a53e9a9a61cad59e99ac53e09bccca78155c14 +S056/S056R11.edf d68892e7f775eee5630a37cef9b0357671546f0d05272cb2b5c272cf1c533765 +S056/S056R03.edf.event 25eca6452bd9e487db46059b497ec8df5b6c353e97a2ac76ba8344fcc0797c79 +S095/S095R08.edf e3a48b8a9582fc7286a014902b73cdfec56c3cb1b4376822b5275178ef7d363d +S095/S095R14.edf e38842403578f1438e2946e72257fa3ba5d8d422cc0303f35b50d3f2471c8aa5 +S095/S095R05.edf 0bf1b8fce6528eea18ab08b0d479ae5ecff4befb1d18f707b0637251197f000d +S095/S095R14.edf.event 60a42ff3c5acecb10ff34635fb3d1ffa125153f262355d4bdd58ab9b9345bcae +S095/S095R12.edf.event 9ff78ae1debf975d7ce67d0ae65ebc35a183ca2e2a87fec3f877fda244e34487 +S095/S095R09.edf 98d149a2f0832ef787ea016d2e215ef57bbe944ce4c7768e3bfc8e4d9a8eb888 +S095/S095R09.edf.event 8f01ffccfcd90b3dc7f8bcf530f915ede4d3a7359039c3d68ac2b897a331031d +S095/S095R12.edf ec1661503c6628bda69ba9aff83004bd9528e282707e83f243dc906bcd64caec +S095/S095R01.edf dfc6a2fa8305ddc93e46704abac01c6c9138bb8cd69fd86ea6b29868940d0466 +S095/S095R07.edf 9dbd5a02ae1fecdb713909528ab6803c5a4fbe027dde1da453b71ed3420a3315 +S095/S095R10.edf.event cae710b11a021b7affcf41c5a3937e4c6bed000e6bdc1690cb997e03ef6db7af +S095/S095R06.edf.event 7309915dfa710afbbadf32d03ef14d92ea4f3831f5edb707fd8ba858d5360684 +S095/S095R10.edf d3456f0afc83bf51ea717fdc7f379df64555397b3cd52951b8f4e0ba8bf3b220 +S095/S095R06.edf 8f6847f949aba7a3aa2b5b2394e847a1ef5473f4dfe426792c7c8e75c13afe1b +S095/S095R13.edf 96ed237df16addebaec9ac6d19ba880e0818866c1e7be4bd00d6d69c7bea608e +S095/S095R13.edf.event 954333c8a5a38083d1d58167e4f7c3abbbf8949bb46067df41825e1156c3b517 +S095/S095R07.edf.event 6ae700f98a136e3a38418f1e7ad1db6ec534a13167c4f31e5d88b04564d47fc2 +S095/S095R11.edf.event 178339a2095d7eaf759407927ba3657ec8e96b153a8e085f8a593674f3697b42 +S095/S095R02.edf 1b71278872c1d079892ce8593c714b5dfe0d8a8f17c0133db8ad0bb4eff7cadf +S095/S095R11.edf 677157a867afe196b3c9eed6e156da65323055506f3bee130034ea7381ccf14a +S095/S095R05.edf.event ea56fcb5af6dc22a09e6c52c6c50be06f5bf4722cba178188f67732c6ecd0395 +S095/S095R03.edf fc0385bf90bb072c71c20602106599dfc212cd92c7675697d857db811e3ec2bc +S095/S095R04.edf d6e647c36b24df0524c32d896328b876a079ae75be41aa665c5fb0871ace1430 +S095/S095R03.edf.event cef39c5c7fed8cace25154d7385aa5c8666f28db51ba7c7224ce1650f9388915 +S095/S095R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S095/S095R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S095/S095R04.edf.event 8d0bdc46ca76b86f6ed45d1ca23522221fb5a9e165c0de588616c0b9c11a6077 +S095/S095R08.edf.event c6742adf7ce83d034f6e3cecede733919ea0d2fe7854dc4a86c12cf32c5c5aa2 +S091/S091R11.edf 1fdc4fa050d6249b5daa14099225882eae6c48a99b7993016b536b34ba51fd2e +S091/S091R03.edf.event 0487cd7ee2fef7813667623ecbe113ebbdd5400e7dff28fd7f0f7b1e00d585a6 +S091/S091R01.edf 98db88036017237d6b096d1307927fcbb21aedd5412a55ec641912a9a8dc1cf4 +S091/S091R06.edf b7d61422c998c20a1321c1dc8a1c4f8f33e47b31f8021f4f396ee3fce010f672 +S091/S091R05.edf 7425b2930d298ad1040c2e1ad27d85413fda9de0aa4a09482007be2ef5736cef +S091/S091R11.edf.event fbeefca3ec1354b1a7a1326279d804c2c564c4b25f2475ccda7b8e94ba4cd68d +S091/S091R14.edf 1182c440b3bbee1cec62695b426e6d6021e86f2b40902c9579e2385bd9c6d53d +S091/S091R07.edf 1f4f23a9a08c83685a165f25386bfc5aefd90ba5031337bf0775d790f7fd8e9f +S091/S091R08.edf d38c2dff0d43f699c7c2bde4387d52745f5073a827c2d41200e0aef9371015af +S091/S091R09.edf df600737e8cd8e20fabd7d2e1cab7f1814e555483a254bbdce0c8c5da1857152 +S091/S091R12.edf.event 9825c80a69d06961cbce2e12cf8d0aa56d063e5f4598312c4e5b78693a0219c1 +S091/S091R05.edf.event 82c4504914809d88b1ce13e11caa12c3a659e1a2edfab31c2e894283b14daba8 +S091/S091R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S091/S091R12.edf 3c17be3adc32ebdf36b4addb89fb78b0b0d0aed352497795aedd8f17cea30b4e +S091/S091R08.edf.event 082acf669cebc89d5f5f4bf29769c743f3b1e14290b8f0f34415e285db553b3a +S091/S091R09.edf.event 1cfd45342f8ef617862da12ca0e446e681027d6001054fe41ac2728751d3b2d1 +S091/S091R14.edf.event 132c4ce227ebb4e694982a37f3f7e9289511d75fdc0079dc876ccb6d9cf1a81d +S091/S091R06.edf.event 4e057b134c286502a0bd4e491daa0ebb3c4bfdc21b738b2ba2453c8ffc558218 +S091/S091R02.edf a7a4ae35661c7ca877f353762e1717f6441dea1fa345fc8e4908381197cd25aa +S091/S091R13.edf.event 985f9701733fcf2689c3a35bdb9e4b0058b6137ded5bc0f1a2a3b84431edb435 +S091/S091R10.edf.event b0dc1155da666ef5240efa8026cec5f4f69b5fb6f1d21226a512de3f6b62002d +S091/S091R04.edf.event 710672ce0f425a207ef543d23f608683e1863d7423702d511235d71ccbd289cf +S091/S091R07.edf.event 9b116dac2d8fff59f5bf4cc8d45636716575c73d6e6b2287709cbfdf0ce5f55e +S091/S091R03.edf 0bed1c3dded92a145b61d90c8df087b5502f72b54e5f027855297253944a1f82 +S091/S091R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S091/S091R13.edf 0dce3749db17c971b2d67c7aa1f0cf6db9745714d596f28808fb4595caa8855d +S091/S091R04.edf 285b7884315a91e2d565aa74f208b1c13a9386af477cc7c6dc8253efcd5d1f25 +S091/S091R10.edf 1acf6fe5f95741ceb0db5a4bb741bdd8dd45e99530dd2e159c11ace48707a703 +wfdbcal 76c15f6af371fd682ba78553d974a8c2d5f12c2f84f0bbc3f98d02f9757d426e +S036/S036R07.edf.event f39b724630cf39de64096da55e80ef4acde232132367bdb459b9a4b872fdabb8 +S036/S036R10.edf 7a675ef450988c75998d3ddca96f3773e611ba79d6aee5c09d51dc63e9a1a246 +S036/S036R14.edf.event 0028edf9b5fcc76311706f809ca44f884f227acaa02c56031cf87a7937c1d9a5 +S036/S036R11.edf 3cb485b341bacf8ade8226b2d2bc25ae42ff3d5dddfe7b500c558f3d6febd6b4 +S036/S036R05.edf f43f1de6a8790fd42aeda8cc107dcbae9577598842da1a7f46f2b6020c6d713d +S036/S036R01.edf dbdda796236e1262d7dd1758d7b4c80762b1865047b8bd2b28d59d273fc4f789 +S036/S036R04.edf c4646d8128095e80fbebfd03dd6c77ebb3491fad49f9824c74f3e4861d9a9d04 +S036/S036R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S036/S036R09.edf.event 132c4ce227ebb4e694982a37f3f7e9289511d75fdc0079dc876ccb6d9cf1a81d +S036/S036R14.edf 84c2ffe0f52ec16ab7b188b2713173b635a3a8beeecf575d77b118b795e6738d +S036/S036R08.edf.event 5bb35bd49434a9630e941b5646d6d89f7907531ef3e44464334b78943d4b0237 +S036/S036R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S036/S036R06.edf.event a4381c73837f1ba112959670ca4c474004b1d78b82daefb4ea220692bfe23c8f +S036/S036R11.edf.event d229cfdfcd562a5cfb40ea306452dab12d3ca82a70a465289b4c69c299fb0258 +S036/S036R05.edf.event ea6f6003ddc3676cda270c185ba40fd7915630a24511085aeb31217c9a1e8852 +S036/S036R04.edf.event a18bb793691db61833ea9b3b10da118a6687892d063d72ae795055c9209ba8ef +S036/S036R10.edf.event a71674e1fd86a57270a24706f4e05755887534f04ecc35f98e56f000312402a9 +S036/S036R09.edf c0db65c2fbaf526b62270a476cacc1200f437060fdebcc2528bc85891575e090 +S036/S036R06.edf 116ffdcab798c901b6fb13763417dba611275d4f22c405248f84144cebd33b43 +S036/S036R12.edf.event e19fc47bcf5b585ab27ad756884c0c4cd37d239bb04c8bf15e2f33fe9fe05e18 +S036/S036R02.edf 0dcc07f8b1362772a26db20e0e8ce9426c463973741bf6ef0079f897771ded0c +S036/S036R12.edf ce79efbd62a81e00a6b7e98bbb80e2d8c0c4bf5c23ab1c1a036884044d5978df +S036/S036R03.edf.event 48eea52bb9946ed46ef7e1b621c8558d41739ffc9aa7ed8fc25eaebd171ac223 +S036/S036R13.edf 6b2c188626213b2dbb06c07d9906be0f982fda71c9149821532cffa3855fd782 +S036/S036R08.edf 60ab89e8d0ecba687a40908643caaa4c7f4bf6ef92abb8d5c3c31201315eab2b +S036/S036R13.edf.event e7ef0a3d66a5c814c6e917ac8f9bf83d6056810f78dd0c9296b5445289483fa5 +S036/S036R07.edf 1b978c2ef1ed07eb355b270c32d59e9170e16280d6247578ec806886da798d0f +S036/S036R03.edf e9ec8c8a0fba4c7bf9de6db237bb6bd1ac4a3d5d6d273f9e37a0253ff4d431a7 +S106/S106R12.edf 1ea2b9ed0d8f02557b21bee5b70514b641e68321b3363cc3325b942832005a99 +S106/S106R08.edf e75bafd408f19d7c04d86479a414c0cc29be39150f20b9e676dfb40843f34792 +S106/S106R10.edf 42a957d437ba3b040aba7f84da7d0d30989268f5dffd9e9824436ac99eead107 +S106/S106R11.edf b3819655e3af2c063091ee1df642fef4205268cbe1692d64f91a37393a8e6e56 +S106/S106R07.edf 4cf953b4b5eff90f64667556cf5bf5c7185bb9c013cc8f00a0222fbab852faa8 +S106/S106R04.edf.event b1fa69a82433c5887997fcbcc3cd7d906b4b49e77e25114de9d45087c9b126dd +S106/S106R13.edf 7137ab5a7fb1fa9ae84d4172a80338ab124824d219b52725490854192d5a8596 +S106/S106R09.edf.event 4b81a244be0ef71bc8b32a5a151ca3746b282903e6c7a28b644879e8bae159b9 +S106/S106R03.edf.event e318e6bd044ead383499ec22af114e14b3a59def9653470287d411ce26ee7335 +S106/S106R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S106/S106R11.edf.event 6ae700f98a136e3a38418f1e7ad1db6ec534a13167c4f31e5d88b04564d47fc2 +S106/S106R07.edf.event 6004c1ac954f2a17e948f3273c849a0e322cb8bd539c483c363378dc50ae2099 +S106/S106R06.edf.event ee1750c58b0ffdf35fc0b7841091977647634e837de14a0b9f891ff04dd2f5d9 +S106/S106R12.edf.event ccca38b5a6381c8bccf9729b6a2e1d1cef2d3880619313ab656bd58ab7a0df0d +S106/S106R09.edf b7b4983a788dcd3e801873d215a4d9279ad10166da96e0f47fdf5844ad58c8b9 +S106/S106R06.edf d36e4c2a47438a8c4bd92caae50c73825e7927b4011f44bef010a43982a99022 +S106/S106R05.edf 85fb5d6ca6f88320f8245627bf418b098cdfeb00bcb2f909dc68c7d813aef14b +S106/S106R10.edf.event bd6d931c82981d9463af509515eeb55f7b6499310a828316c8f4a3ea35ecc7bf +S106/S106R05.edf.event e580516304935711e290073cc13e75cf23b577826c9814c6b0676828f9976222 +S106/S106R01.edf 605ac5d4ea9ca2170fa10ff85119297a77a7ccb7054b107294a903b911788c37 +S106/S106R08.edf.event 30b760c52698fc58e43824eb7302010b60c8374cc35c21494035da15da835fdf +S106/S106R14.edf.event ac9692706f0387f2683b9a9fd24b4d8ed371ffd2c916c2e3049ee3f63a0c5c9d +S106/S106R04.edf 7d7599596aacb4635049041a26635e1e14b6b96437a3304701a2a3d7f7cc8c05 +S106/S106R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S106/S106R14.edf 27e090ed4774109e03a7b986ebf7f8f617eef959906987a8f98e4599e285b653 +S106/S106R02.edf fec905ea2aa23a83ee57ec8cfa2dc7babdb169a3ddc3d71623f350ff4a54b340 +S106/S106R13.edf.event 59a87fb5bdf07fa6133a8304b27cefbaef11d6edf13e912fe47b9c6752721e60 +S106/S106R03.edf 603e54496f1e7f21a673e23dc91e304320f7d49d31139369f1232892c4c2ea89 +S079/S079R06.edf.event 15eac883e797e576d72c57d60ca80b477563711c2f4f8dd16cadc5a529d40f03 +S079/S079R10.edf.event 3b5e25a187d5d82fb5b851ecbebf095c41a5496c5a40492c7a2c638245bbed51 +S079/S079R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S079/S079R03.edf.event 220ce5d60602a369af8dd5bc9c722c30b74d0950101a84f6dcc0ab8dcb0c2025 +S079/S079R05.edf a66c18316867709634bcdbfea16f81c3612758d26f0bd252c088242e56281845 +S079/S079R01.edf 5dbffbbbeb71b073533cd280510875199ac7b00e5c6225f95c1b88dcf2fbed1a +S079/S079R11.edf.event 8c5f1f6af23dab21ca4abe1e798a979ad9ab71892604c84a00379c39bd269aed +S079/S079R02.edf 1a43e3f707804eaeec05bda7513e811ada8701131b93650de93131e2e1befb88 +S079/S079R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S079/S079R04.edf.event b1fa69a82433c5887997fcbcc3cd7d906b4b49e77e25114de9d45087c9b126dd +S079/S079R08.edf.event a6cacf979bad39813ad2028620db2781eea6e16e029b8bf69686928d2958fede +S079/S079R14.edf.event 86e7714efe0f24263f2567d7a273935782e2b0153d9e1db329e96ab5cb995a8e +S079/S079R14.edf f3f3119d4f31164076e5d6668b931ddf1730961a7a9f7e198106ed0232adc217 +S079/S079R13.edf.event cfccf092791e4f541cc50e2a8c3317df4e3eaf04f099301c7f827e7dffd9c354 +S079/S079R06.edf 1d7a8f7c0bb7f17ddb08cfac1bd77bbe79acd1973cd920dd34fcfdb684cdd6a6 +S079/S079R05.edf.event 4b408c3796f7bf8dcd27259a0ae6508128a2f1069560a5cff7d3eba4508a6768 +S079/S079R03.edf 72bc07225a4c4cf79335f39e6dc62690bd4bce2789064e53d61af13029ae1416 +S079/S079R09.edf 9e224ee24274de2211dbc80327460af713fd708ca65242eae9119d860299b914 +S079/S079R12.edf 0350def02e230173edb8d69c7e66fb22155d00530fb7ce9e945921e0ab6abf95 +S079/S079R13.edf bf4a8cc1b524063cbcf3e4a7dffc1085be8c02a44e9f8fc5568b63a9d6d45c4e +S079/S079R07.edf.event 86f35381c7eb24cc6094567ca1b734e53a81bd8184a6364c79b7f00b9a5ece02 +S079/S079R04.edf 5538f0fbeb647ea7577e448856433edd3c3884516ef6bc5bf10d601cc62824ac +S079/S079R07.edf 74184070e26635730190095b4e81558916e897b97a0b09326facfbf3412ac6c9 +S079/S079R09.edf.event 4720e082121115ddaf3c9fdf14c4fdd2b2cd4b97a259d705f45872624ca24718 +S079/S079R11.edf 446fea2a6a8885b3230d3fea22cfa4aaaf2ea3f8ff43a413ddbb4e532b41aa70 +S079/S079R12.edf.event ee1750c58b0ffdf35fc0b7841091977647634e837de14a0b9f891ff04dd2f5d9 +S079/S079R10.edf 51ab713a7c33dd19f805f91cc03c62525d0d4c4b746cedaa3a26f2ea67f49471 +S079/S079R08.edf e65556abef6b586d84ebbb2e0a42caeb493f58af9c3d62ee4d41dbf43ceff973 +S023/S023R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S023/S023R03.edf.event 2553cdc46c8017dc83d793a7cce6a36ddf99a043e777612539831e67f1aebc23 +S023/S023R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S023/S023R10.edf 402074b10f0e8689441f60a53e8439a80c43ba456f0cfe245a84d1fc27c3fe1f +S023/S023R11.edf e5be72fc22fb3420b4a4936c87ec9c003fe377c6c5f7bd6fa39242496a0ba2d7 +S023/S023R07.edf 10d59b860cead78e224b2f6633a9cf54a5b735804157f5c8f820e7c560e05f42 +S023/S023R09.edf a787f36a42c2c1b1aaca4c71bfc26b1e0ce60fa90089763e86e4de36a6f476d2 +S023/S023R01.edf 3dc49252e5969854b3c0b9126058e3a9f28efcddd61a6f570702ee3043fec0fb +S023/S023R08.edf.event dea45ba8a8662cd82aeb9d6c523756ce7079f3020c2ad1b23d6dca2f63b5bf82 +S023/S023R05.edf 37405690b9dcb16205a9877bce43f81dc50efaa85422a29493e7a521a8e997d0 +S023/S023R04.edf 16ebfe43b2510115dbf1b15a00a429cfbd6b3a1443c2bed08e6755282e06f3c2 +S023/S023R13.edf.event f686071dd83e0610c6463f51dda1c01de1abacf998f19f9b7d3910c06492fc30 +S023/S023R04.edf.event 43bc660a507d479ebfc1c782945c8504dc21abb3e55cd48acc2faf4db673e854 +S023/S023R11.edf.event 9b116dac2d8fff59f5bf4cc8d45636716575c73d6e6b2287709cbfdf0ce5f55e +S023/S023R03.edf a2f2a6ed190a2381db55e49223fda8526bd0a603bc339f862046604352cceefb +S023/S023R12.edf 366faf95b5e6142e8c6cd9b55da2005533b199983ef0599d73d1535179e7ca5b +S023/S023R12.edf.event 7c83be0506163b52a89548c7af6d4893472403c2bab3a455c7d8c92bf3550ad8 +S023/S023R13.edf b316cc43e36336e6b535f0c8c065db474d057de54b42a95471b2d5ee342860fb +S023/S023R07.edf.event 1cecdedf3d7f8b7931b4cd84b48bcd356337c0ee32518d737ce0ee8f0d428d8f +S023/S023R09.edf.event af9bed6667136366cf88d2cd7f0f5fd9dda3fa51cc4cf73d3afe4d57dc8b7502 +S023/S023R05.edf.event 33a34db8c83e4bcf4288f2413aa75b7d7c03a7bccfa172b157568ba29ee42d1a +S023/S023R14.edf.event e14dc31d476c11841d45564cac660be9776fccedd3dec71dcee4c5232f00f25c +S023/S023R08.edf 70f7e8d4af5500e2114eea7db8c50d7c4b822fbd7c92c8907018e3aa094f4ffc +S023/S023R06.edf 2b903a9f5bd0ce741321e887274e5114d81a4138fd61a7baabacd83b630b4dd6 +S023/S023R06.edf.event a8ce17ff32c2c3aa820817e047ec3ff9976bd33355d14877f0ff811df5a288a1 +S023/S023R02.edf e75a898d302ec8aae307d84835922dae6c298607e9a09a95fbaa9d90452831ec +S023/S023R10.edf.event 99dc24a5732bc2857f1d3fba3d1a5b942b288ef56950e45354e03fb10183bbe6 +S023/S023R14.edf 6d8ac157a1c9559c29aaefdead7748e0853a3eacc54e7b855b97e17653a4c53c +S052/S052R13.edf 1997e7d693fa8a6f2f1f344ba3b57e1ff1ef2aeb330b44afb3151b05ac5dcd69 +S052/S052R02.edf 2ca319811ed895cb132183e3fdcbae6e493bad2759c806833a234c0e7d65fb7e +S052/S052R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S052/S052R06.edf b8e9e0add922295c01a91cc2b88c540dbf8c3076f77d97ffe726fa952442db03 +S052/S052R05.edf 8b90b20f8191b826f42192575c888496f7eeaafdb8e58aa5d3e8e523d48fe677 +S052/S052R10.edf.event d0677488ead680ce24ed6d8a77105b8da3f0bd8cad38fff43732482c17bc4510 +S052/S052R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S052/S052R04.edf.event 5e6dd7d9983b10c75f267d25fb4f039777b8f17f9d64869cb39446d1e9306505 +S052/S052R03.edf a81f9ff3a2af1126e4a1c65491ad03805e04c6895f74bb7c4edcbb630f144eaa +S052/S052R12.edf bd07d4c56f8d31a0fef2a31926a98c11104d21e9b127f84b02743cacc9e6eb40 +S052/S052R10.edf 4d8eb059c2fe2823ffde762b986df2ac941d7ad761b8006fff1719fd863dac22 +S052/S052R12.edf.event 48eea52bb9946ed46ef7e1b621c8558d41739ffc9aa7ed8fc25eaebd171ac223 +S052/S052R11.edf f9b1baab5e1efe90df754dbc91f79d6dfcc145947ea1518272caa713f9da2f25 +S052/S052R08.edf.event 6e4a2f2b413bd53735575eeda52d35059687bb58d072e4de1626bc16d7a28d24 +S052/S052R03.edf.event 98da35a4768842863f8f05d63e959a36f12126a205e0370d8519299fc06e56ec +S052/S052R07.edf 04cf399950b747941a2f78f7de5fbe7bc38c57064fa1b70603ac3879c44a4ad6 +S052/S052R01.edf 8346bfe5bae53f3a82438211538a6482d4e1c885b5b70953b862a4d30fc0bc26 +S052/S052R07.edf.event cdf1a70ff91abbdc6f14a7ca794a7b5932276819e6f7c68ee344c3d21e9b73f0 +S052/S052R13.edf.event 78e5b5619faf1f99b53251a9e743644a731ec9cc5b6e60533a3695f33fca35fb +S052/S052R09.edf fe58ed0bef28cb86f78bfa82dcdc94020a0281b05749b2c7828b580dd8eaab39 +S052/S052R05.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S052/S052R04.edf a519ee3e292f1d8317b69f8bf39e3c6ace26dd5084baf5824f8954b42fc2c8c4 +S052/S052R06.edf.event d0280a6531ef96d2b622c2d562c05bf53a0d00439a4819213365b6e52e54abd1 +S052/S052R08.edf b9583eccd78acef6f7bbb65318f6b1d3fec1ca88ab6e470cd5f97722635379e8 +S052/S052R14.edf.event a376b452fa5f7c300d71ec31ce58f97920510a057f4ca6c506f4cef51faa7315 +S052/S052R11.edf.event 13968dcd0074afe70c79ea250f7148e28870c5b0140104f078a501fd3b51ed69 +S052/S052R09.edf.event 0ff4d5f572885db930cfd469a0c25535d26e1712145e5a489a5e31e8a2020961 +S052/S052R14.edf 55a5eec629950b7d895830a3643d3692d47e8509426b2660aaad8798b905a038 +S107/S107R11.edf 8af14cd3527fa03c48ac9093a61310dcc562af7366867b65f4fbd1d75d53d520 +S107/S107R03.edf.event 272aa3698bab2b05544eceafbf5b26dafc58d0eb50a508a47c26572576853ebd +S107/S107R05.edf.event 5d8061cd48a1d74cf68aa1abca145987d71fda1c779f4e067d7120a42e8532ce +S107/S107R11.edf.event a7ffbae85e6a87d36d8a1790de88fe9163b4487f124a5e2cbad1abd1527eb341 +S107/S107R12.edf 1f61ae883dcb0973b8aae174b588eb352e3d55cd32006cd3a083bf019ece19a9 +S107/S107R14.edf 1a9669549bca2d45e36cd14ad90df230987fadb9eba18af366054390599025f9 +S107/S107R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S107/S107R07.edf 1e0c4ce1cc9b901c3478bffa5bfd97010755ab3c61a598e193fe44364de61dd0 +S107/S107R10.edf 447972429a3a7ee6e6bbabd66b2dc3182b2ee8afa60b8dc354dd9b90837cd269 +S107/S107R12.edf.event f94fa47bd56896d1b35682e2e14d8d1fdb308a058c4a48b7360c7276bb8cd922 +S107/S107R03.edf 90826bec34861d168306758314750e1ff80a09684b25f2b15f393840e8558b8c +S107/S107R10.edf.event 018a676bc733cbc27dffcbbf3767758e526d1ae08a5dbd0785d28e267132a3aa +S107/S107R09.edf.event e318e6bd044ead383499ec22af114e14b3a59def9653470287d411ce26ee7335 +S107/S107R13.edf.event 6f21f5809578073ed2c858eefa6348294beb3ca2936579fcd1c562953dfd18ba +S107/S107R04.edf.event c10d573a5a983f2f3315ff36b74aac2bb21199e85afc6827d4bd4acf2a3c46e9 +S107/S107R09.edf 42b7bf6ddeef1eceb30b2e166d401edd2638d0db97b3c3c7561415b83cfc1313 +S107/S107R14.edf.event 1442094c7e4c8cf80c2b917010d3a5835f895b48a64150371ef6f1f36d5eb9dc +S107/S107R13.edf 83524393a1922213c548d24a014cac7ac9db87425a33cc2bab8612409fae5c52 +S107/S107R08.edf.event 53726fe905bea0abe513d5e84fd629ed577ff03739fbd56c6a12198e7cca5cc0 +S107/S107R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S107/S107R04.edf 7a4eb02e295694a920cc1db2b57bce8024b131dbbd1960310f4c5ac78d614371 +S107/S107R06.edf f164b842f5743e05ae7c67e4a190527b6f53cd7c4d6b8e7e34ee8c4f494c137e +S107/S107R06.edf.event 954333c8a5a38083d1d58167e4f7c3abbbf8949bb46067df41825e1156c3b517 +S107/S107R01.edf 08f3946647a37c1a9dff23a2821c23d5fc1421eaed08bd5b1e14291bf9166363 +S107/S107R02.edf ee27e5b4641392d705cb7ebf76cc42355edd23aabff64aa34495e5cbe9436d79 +S107/S107R05.edf 11a0cdbc2881cdc6bb1c8df54f8468eb0ef77dda94df5c1dad3de09fedccca6d +S107/S107R08.edf 0561cb71fa613df859d632d315cd694a686a0d871ee6661d645bc7e9355a6f0b +S107/S107R07.edf.event 6f21f5809578073ed2c858eefa6348294beb3ca2936579fcd1c562953dfd18ba +S041/S041R08.edf.event e1ea33ab1840970a45f9494f5d70cd8cabbc689566eca11d6942253b2395c368 +S041/S041R09.edf 43b6031d29f744456ec1b586735168e6cf08633d1f34d7353528e61059752f97 +S041/S041R06.edf.event df69a0d4526ab4c42f8d35b328874aafaeda087bb95ee7310d4f3654498f5746 +S041/S041R11.edf 29dadfc9c0a7046ad6fca3ff3123a8de9825e6ea46407d0ea0397f0f1243371b +S041/S041R05.edf e3b18470da33e7377931d2f8932bae6b2abdf12bbc5a4715f59b9d331d9ad5af +S041/S041R05.edf.event f8969447e196cd3b85aca233f8197d3642b3a82ffb49458332044d86c5df05d7 +S041/S041R09.edf.event 67b710bfbdaea5c65257f5bee9fa64cd171dd8b9c8a41d1686b0a14b0d997c51 +S041/S041R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S041/S041R14.edf dd94f1e4d2b83ccf6b984922886bcbdb9a2923ae8ea0756699114c50526399e8 +S041/S041R12.edf.event f148c5d5feebd73d0187005d90c8f91681f338bbb40cb34a407743227184144d +S041/S041R10.edf.event f148c5d5feebd73d0187005d90c8f91681f338bbb40cb34a407743227184144d +S041/S041R08.edf daba914c30b37217f9ed61f4f79157f9e23372ed083260c47edcbda4359c97f1 +S041/S041R02.edf 3c67750762b3ccdc5d76f81e13bd10b996a7d7f6b7a3de4f16985a21484d08d0 +S041/S041R07.edf.event 67b710bfbdaea5c65257f5bee9fa64cd171dd8b9c8a41d1686b0a14b0d997c51 +S041/S041R01.edf 5fec76892825c885cb231c16424e497fa7b0bc5d255f15117c2f896da85a27bb +S041/S041R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S041/S041R10.edf 4c75369bddd2fc10cbf7777bbb1c7c289547ab6f10bf05ebe4a9bbd37d9fedc4 +S041/S041R04.edf.event 4583d527bb9a02f3b0e943a0fc2ce2201582f8b83cdbc0f712b57fac2679359c +S041/S041R12.edf 99f13ffe9ca9d9a3d680360b91555e73f190d91948c80ab8415b901b42350bc0 +S041/S041R06.edf 171ccfca39f773142019df61be511b23536720e385ad4e38e92c4c9a24a8870e +S041/S041R11.edf.event 9fd975ed76b006ff20105ebf0fd1ae6dd127f008e06a75cad4484483eaad568d +S041/S041R14.edf.event 1e4f0638e7419908f6581021a41fbbb2b368f8e087db11c71f96241ae6ccb506 +S041/S041R13.edf ec6f193a78c29024ae8e67e69b942ee30171cb36b99d82ef96d776f2fb1b7e4a +S041/S041R13.edf.event 5eab54e7aecee45049c9cf3e99655056d386829d66b77ed83e678bfb70ef0bfe +S041/S041R03.edf.event 89a83f0e623d00fceb1de134620c85fbe897d37c7fbb2b8d4c97de688059a2b0 +S041/S041R07.edf 980f0e64820ab06e8c913511d92c799b2ae1abe1e48bacf9b9f29b12fd2c93b6 +S041/S041R03.edf 568218fd5956a8c3c8e7cdac30a1e8ea0bd5371fa7ebb96dc9b17a120ad566a8 +S041/S041R04.edf d814dd4d8d3d1e3853051e48cd3ac5e4761c3ed33a509d3c06ec946b9394c534 +S101/S101R10.edf e90eeb58bf74f072e1a7382befc414f5f4c6a88cfd0c46e67b59bb59c09e404e +S101/S101R09.edf 265ae1a34c6bf36478bf3646aa3bced1df8d073090656f2d3b15993ba88e7532 +S101/S101R03.edf 6bcc5fc3330b946a93fc50f2d4ffae97612a78c6f592a443b46b9cba7a06df6c +S101/S101R06.edf 1a4573d0f58b9431883c95b5f4d7695d352632f7d0d40698f4cc82081561e23f +S101/S101R13.edf 13779bb09ca42f247f6fc8dffe19f02a70afb3f5baa49f902e2706fdb9671c49 +S101/S101R14.edf.event f804d1f19243344c8d8b505a1f229c8626e7f81cf4397b94650b0e6959d27437 +S101/S101R03.edf.event 1d29aa2dd90032d41f7c1c6386db9b2b26b7c29b87234d56e63f65c958acaa3c +S101/S101R01.edf 111b902998ad14ea66860661023c2e3132c8da06961afe0de02f71ddc4ee383c +S101/S101R05.edf.event 6110dd47d25df5fec4b10a72fb28e306cc9addec318d4703b53d4b40b49f1930 +S101/S101R12.edf 89538acbaec07991b51b64bb1dd2b7e3927a4436f02028410de95d06e85f683c +S101/S101R07.edf.event 3b5e25a187d5d82fb5b851ecbebf095c41a5496c5a40492c7a2c638245bbed51 +S101/S101R13.edf.event 273c4fa451c5781d94b0c8204068736b90665f96073084c33770108605bd302e +S101/S101R10.edf.event 0513fd04977ef5a66b77e72c59699e4e54ff57c226456d0796b1c58c38fb4d59 +S101/S101R08.edf.event a09f7e11a8c8dae371fa8ecbb2a00172679cc16c6776199906f532a7130b3e33 +S101/S101R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S101/S101R04.edf.event 41090322343b92e918aeb527b6dbeed57fa35198578161fe2d243fbc66dcf876 +S101/S101R14.edf ea43cff7ba5813903ce1695cbdac51c5ffecac98e09c974e3e63645dec45f9d1 +S101/S101R12.edf.event 3e0305869314baf38d1ecf15532e8069bab3bec83bfc99e199b9f5c49899ec56 +S101/S101R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S101/S101R06.edf.event bd6d931c82981d9463af509515eeb55f7b6499310a828316c8f4a3ea35ecc7bf +S101/S101R11.edf.event 007c6ac586d5de80642bcf571fae31808a22c5f6b8fff35fdd8f99f1b334f97b +S101/S101R02.edf 0b999b572a22c300088a4d0f7288a9adc7d09c554a8216b1231124a73468dfee +S101/S101R04.edf 6618bca949e60277dc7a6a23e9fcc5e1d582165550fa31b391a132b2b30b2ace +S101/S101R05.edf f09ad4dba652c6cca39cd9f6d2e030990a564413b30ae57ccfb68b770f111d4a +S101/S101R11.edf 0cac663bde79ffa8674e322b8d7590621568306cbd411618c4370843b3eadb6b +S101/S101R07.edf 4159deabe1ee6e896e8b3604c4260f227c93c43284c99d5c39db63fd3928cac0 +S101/S101R09.edf.event 9a1f9c37f0137ac6d7341c2a9dbef1bc161b35fcb6bd9e0db6cb95f8c7096c5b +S101/S101R08.edf 6e3be34d8b83eac9aca9438049e9de0a8026d6d861e1a0cde5a2df3b4c225331 +S067/S067R03.edf.event 82c4504914809d88b1ce13e11caa12c3a659e1a2edfab31c2e894283b14daba8 +S067/S067R02.edf 814eb9ee675c39178536aec7223f88869ce3dc0a02592fc422995bf8c9a8f192 +S067/S067R05.edf 3fbb87ec6c2b0e60be7dab51c5f5dc4078a89d116b292740bc49904ea2c3bcdc +S067/S067R13.edf.event 69bc42ecdda8587b1f3dcaeb49f434eb51439670272d896577812c1a8c0b14aa +S067/S067R09.edf.event d0677488ead680ce24ed6d8a77105b8da3f0bd8cad38fff43732482c17bc4510 +S067/S067R12.edf 88607f444d64af64f30578bfd1019ff837a0139ad7985235a6401b4edcc1f388 +S067/S067R07.edf.event 49dac749bf850e47e5d13a8edef5121c75a7baa7f50917a5c17c1dda52d3013e +S067/S067R10.edf.event f45bf8e0fbc90d9616344960adaf0ce8357cfa7171b36030a957f85c93267870 +S067/S067R04.edf dbdadbd4a88eb8fda3fd90835ac8a0257101c3b58dd08fc272892d707a560fbf +S067/S067R08.edf.event a730605f9838282a7ec09530538d4f4dc6f2f5cf73c8f2e85944d5e8297c441e +S067/S067R11.edf.event 2fa0b9392dbafefb266a1c269022274e4f4638513c85370c47ce925b54b7d5d6 +S067/S067R14.edf 2b5dd5b0a424ebb04c1d89b0f97532cfda4c4af1bc1c4c1c441b9ba05e3f0d15 +S067/S067R01.edf 7a869d87fe690e94b63ae466a2f8a888d8baf3a028c1be35b6d7fc2b80cb5eb9 +S067/S067R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S067/S067R06.edf 88c56ace75081e57c1b66f781831e4c82403aecd472e2883ea2cd696acdde5f7 +S067/S067R08.edf 838faf306afb01abe27febd1a0992f9ee46bf522073aa94bd625eef578f98480 +S067/S067R11.edf 41d47be97d322c350d4869bcc5fe702162f15f5e2ff8640aa87836904208bba2 +S067/S067R07.edf 5a0c99dc1266dfb64219b872d2ce8aa6536e37f3cccadb0a330794e467120477 +S067/S067R09.edf 06fe2f2805cb210ee9120ef76d997788545a71b52d18c53e58fb2550603bff8a +S067/S067R14.edf.event 99dc24a5732bc2857f1d3fba3d1a5b942b288ef56950e45354e03fb10183bbe6 +S067/S067R13.edf 267c23b4048f8214cad4b3903515bdc36f4aeec9f61e74c3be3d0f791df12b63 +S067/S067R06.edf.event 0c671e4e4ff7b21e4f75cb8796305c57d6ee3fc48e74337e26c3b9f5d49408ee +S067/S067R05.edf.event 8fbb43d322f1567ddece82c464cdf460a9df3070b5684895a7bfa7febb8e9950 +S067/S067R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S067/S067R12.edf.event b1046f2c937e8d05f2c3e45473ca880864a5d33222d740a0bee41b055662ea91 +S067/S067R10.edf 6cdfae4ec7f0ff4b034296a7bc15c92cd6eb6db0536bf21dbb83520b604cc9a9 +S067/S067R03.edf b4b57a88b18afa8e2d40a0d05c53f5868879664d1c6363d4ecc0b38c9af8815b +S067/S067R04.edf.event 732398d864936092994f6aa5c7a3d554d1c1c35ff4fd7a90dd0c06a61260c68b +S001/S001R09.edf.event e438579df1a078f089a8a64cd82e2e11cb94abbd724605c4705658e9cc2458fd +S001/S001R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S001/S001R12.edf.event 482ba145b4cf10d7d6dc91bf708cc14230ec2a86592562a3f6c187be5c9f3e9b +S001/S001R08.edf 358fb5189220725141968ae285fbe9e3f36210b834ffba71d940af308e3aca68 +S001/S001R05.edf 8828f4b97931100af136cebf27838248b82f69cf359f7e6c3146a1970a8fb8d9 +S001/S001R03.edf.event ba934fef5794a278b361c657b30c7a254a5c2d10754a37f484373d779d37bf66 +S001/S001R10.edf.event 8162d74d19617d3dc613cc4d3505a1e143edecd3fb9c7901e255495cf94de0d1 +S001/S001R08.edf.event ccd5cf82de626903ece23e339121ff7919b3c3788cf647b575cf08dbb0198ebd +S001/S001R06.edf.event ea56fcb5af6dc22a09e6c52c6c50be06f5bf4722cba178188f67732c6ecd0395 +S001/S001R05.edf.event 53f4af70d71eafab6e0d5fabc2c8e8b73a48b4f21df8be00e2543cc640c12549 +S001/S001R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S001/S001R14.edf.event 7e61f9359aba654d84b2ebabe218ba21c6b3f8c33a13e5b6c9c71df1e91cd112 +S001/S001R13.edf.event 1513629f6e8e700394421b828869afdbd4e2ccdf8bdbed2127f75a42b2db3ff4 +S001/S001R01.edf 4743b736131a7e147c150e8b37711029b6cda5e356c4b3e8261a03cdcaaf8b0c +S001/S001R10.edf 20de1c7746c2349d16bda5e9f1b0ac7b7ad1581102a2e30dd2ac422696f62fb1 +S001/S001R11.edf d5296b9232b0ad88b7022155cbcde618df44d4b0db046ce3bec54f8f8644207a +S001/S001R03.edf 3427c8d01bff1380bc9ab9f27a35ece2af5dfadf3e291bbc05eb66e4dadbfe2e +S001/S001R07.edf 6320a941815eb7a0bc632e32c07c88b6e2281a0e2f177e8f49e2d0a16231145c +S001/S001R04.edf.event c81d77b099878d1d392e93aa7a18a46b936b690bad605aa84a652b2bd9cbff1d +S001/S001R11.edf.event 8162d74d19617d3dc613cc4d3505a1e143edecd3fb9c7901e255495cf94de0d1 +S001/S001R04.edf 3d161f88e1c00632585287d2ce584c2bc0f08862438eb255ea8723e00fac693d +S001/S001R06.edf 5369364f2c4e81ca141679d6dd2ba6ece61c7eb53d7fae31241b308876e1b6b3 +S001/S001R13.edf dde646236a13d846ca68ee71440f1fd38d818bc50a2f4804a29bcf0f773ad167 +S001/S001R12.edf 2b281c9b687b4c4176e83251d74743721f2d6ebd76656a972a3b9c44d9d88cd5 +S001/S001R14.edf 2110c48e3106898e3dbca47e39b330637afd3d3b8bc2da3ba1e44f4ac1118137 +S001/S001R02.edf 31a95e0a880e6c3d89960d9d62c144f24cc4e9f5d7e93c7f864ef61cd49e847e +S001/S001R07.edf.event 92b3e8a6b67a6846154b1244f9044558257134f17b25840c7f71206ad195584e +S001/S001R09.edf 1b642457807be572c31e8bb56a936cbdb554507d66e25e242c9bd1b0c557c53c +S016/S016R07.edf.event 8fbb43d322f1567ddece82c464cdf460a9df3070b5684895a7bfa7febb8e9950 +S016/S016R14.edf.event 6e9a969133a5a862400b62cb84f763eda38a0967078b1ebbfea1ca2ce8635b48 +S016/S016R10.edf dd359a54e0811d4a08e82284cc251e1ce193f365079578f18d006cf7f1e3919c +S016/S016R14.edf 80dafefa87cba873be315c21c9bc805c9f3c57b50cb9d0efa9a5b8b71037b1c7 +S016/S016R03.edf.event a40b48032f894d3401affa4d6ccfd4defb4c639cf235451c5fbe2296febae7a1 +S016/S016R01.edf a0396eaa7765e822a9520e78321044f7296888442e6258f3e33c550228d84576 +S016/S016R08.edf c7d59291f3d037e25c672da1bf0c202f63b7913a0f72401cb73f27deddb5ac24 +S016/S016R09.edf.event 0aaac0e6493abaa7abc2bbcabb2ba2ab9cf91a665d7b07e95e181cb6e7a7d207 +S016/S016R06.edf 8ff4a1d19384bffce8524194507bdb42946fa06da83bdb75518c9a23f9677876 +S016/S016R06.edf.event e1ad9bc40c1368a9f08ea6dd90c3750fa2947ff48bcebe59b7e89441a2db68b8 +S016/S016R10.edf.event 9a16113810c1d4f4c6d4bb0e9fa5ea774628a0b8f3e1764e93d71da831cb206e +S016/S016R13.edf.event f45bf8e0fbc90d9616344960adaf0ce8357cfa7171b36030a957f85c93267870 +S016/S016R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S016/S016R04.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S016/S016R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S016/S016R08.edf.event 820bcb0b8aa75c06572fb3677af8b965e06ca92c0ff5f4eabd0d347c7b141680 +S016/S016R03.edf 976bcc77f002affd1833ecf5adbe73eca86d1d1b9e2ccaa0d8712095498cea4a +S016/S016R02.edf 129dccd14aab4f3c5761f1e301a9f75c9c0e408333fa4736771834dd0eab5d4a +S016/S016R05.edf 67d864417c5739713aa2defaf1dc9a88add841049adb829f61fd4c344c61f089 +S016/S016R05.edf.event b1046f2c937e8d05f2c3e45473ca880864a5d33222d740a0bee41b055662ea91 +S016/S016R11.edf.event 0d4308120129d0f92d2b8779374ae232f98d1357e6c6427983fed655d9611af0 +S016/S016R04.edf 501fdb3cc2fb504d2948e7ce665c81e828612cf1af80a0b964b34a13803a4d6b +S016/S016R12.edf.event a7a73578d2f76bccb3e355d9d1c30ebbb1c7c5f4f6abd7b7289b88c138f56b17 +S016/S016R13.edf fd037b68ef03566fa39b6318b4b768cd0255f9e255b137cc3214a1d1175e952f +S016/S016R09.edf c1e5591ed4ea70ebe7fc300b52614affec8df35279aac42bce0ba79f4ccf6d1b +S016/S016R11.edf 067acc3474bca1ec4e4e59bf5c0e4d8402a9067fe4f1231d5e50808b64b8781f +S016/S016R07.edf 4fcbf7f4b5bae4290078934484ba3bfb2052b3cde700c9e2d0c1fb0654368f55 +S016/S016R12.edf f4e5942da16ca0992db7884a42d0b2a16bad648fc4bbd483f2954a93ca48a931 +S051/S051R05.edf 64036f696368f79d9caf39094a99727e919d33e6e1573236b6fa7f8dfaf15b61 +S051/S051R08.edf.event f15f8724ee430d797697caab42986f25c432c24a06e9476b217deb6aed7450e2 +S051/S051R02.edf e4d456647129cdfb07b277b2c9a2c761d2e6fe92ff273bd6a15456aa5118b4c9 +S051/S051R11.edf 783e75586ce3cf5c00121b3b419215cb20dddd9c8394c22fc02a82becd411b1b +S051/S051R09.edf.event cf1d9fc8033ee0c3ff02b28ba22ccb2f38d4189988404e0aa8611090eca3aba6 +S051/S051R04.edf f1560c8e23d36805035cbd36496630af7fe2a16d7676b91df7ec8f2d039b2cd8 +S051/S051R10.edf 2f1d5ca3ba1b7a9b3d5193db62a36586b29905a2ea42633219befab290cf552a +S051/S051R03.edf a7e916278599c36b9a3a58060b44a3dd0b56c12b546a86918fdcd6711f4201e1 +S051/S051R14.edf.event ad5857b78d92955c6aca208cf731246cfd8288233693e3f4a523f0703f49f73f +S051/S051R12.edf a89b20cfa7435430bd00d59a884e1c9afbd5190636c63ad9d65de5917922d986 +S051/S051R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S051/S051R06.edf.event 478b8ccd4857cac2290deccf56d25d39325800222eebfce18860bdaad7d56c20 +S051/S051R07.edf cd6fbae8dee9aefa9fbbb8fa30cc10d532bd7dcfc021e466759a42e08416a71a +S051/S051R08.edf 548006fe57af6638963b64e36efff127e1581c9f27ac932c7d4f318fcd0008ee +S051/S051R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S051/S051R13.edf f68f9dba7c2141b4fba3d861c23ae7b5e46393a3293fb3f8087ba2efc4c1165f +S051/S051R10.edf.event 23eb3f298cf113a6057c8c3099fb82c94065a1da3246d3720329fb470a09b5d7 +S051/S051R05.edf.event 906c14054fb3c295684bcbdada9fce2c7ee5c3189024361cee275c892fdcd324 +S051/S051R09.edf 501c0bb8594da4fcd1bde7bc864fdf8fd91f8c5e86a269c847b8155e2b979697 +S051/S051R14.edf 1a97ab81c5f3e4ab30c8fc11f6509b81975aa726b214a65f7f17829e25b91b10 +S051/S051R03.edf.event 93831ffc4037fe5777b156102f8c0af39014f5cb1afa9207470c2bf4bb5af867 +S051/S051R06.edf 40860d44894450c46d5dc9fe2afaf7bac8415cc5345532b7d1c121cb6bdd4cd2 +S051/S051R13.edf.event 8e39b81d7164017e1d67672dbc17ff18d31922b3f6365e9e1961814c475b2210 +S051/S051R04.edf.event 910fb8c1ca895e78ccb614a06814156c6ae67b42893086f2694aaacc81a199cb +S051/S051R11.edf.event 80df586db524a77e67f11eb275b00d505b0ba9212ee984d6f721958f2b100b4b +S051/S051R01.edf 47fed7512d9d7d87c2f85deae9f5c8e80c9734b44352ade28655e8a27ba0ecca +S051/S051R07.edf.event 1dc2bc1afb05cb56cadc05fbdf2f7ee0aa7f1bfa84e10e335f6618bbb761763e +S051/S051R12.edf.event c0e03fc052196f399444ee8e817cb9226c53c8b1d27137831cbcd0d283821560 +S066/S066R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S066/S066R04.edf c92f6dbe450f79af5e76a61188c012ce7140899ef23a4adc5ea74ffcd1c36fec +S066/S066R07.edf b35cc97a9bdda9f56f4a85a19d13ca7f3abf1b1dbeb93139a1d26b788643d95f +S066/S066R13.edf f455678ce77fb04fb42c6f4dc40e0abcb0b009f2b2bc9dfe59250d08a0d8ca34 +S066/S066R14.edf 788e35ffccd4ad43f92c6a42465aba7b781109aec6e6a6fbc4851b96e68e929f +S066/S066R09.edf.event 257122cacc7c40238756b11f4e144c0736d7ac0f933a02a368163a2db8e83122 +S066/S066R09.edf 831a2876dfc28239666c53d7aa18f1add6beaa33032fd96f5854a37bd8d30ea7 +S066/S066R12.edf.event ea1eeabac130c6b0553b7253953303c231f74a93e902a501d7882ce6c58f2f2d +S066/S066R01.edf 6511edb550c0b24d34f0fdd8ce50bd61202130524099c1e087aa92e258bdacb9 +S066/S066R03.edf.event a4955229baef6ae4fbf6af78608901c020d3c47fee4b7280c8c617c752a1865e +S066/S066R02.edf 6ac66d3775bf65c163f944648a5a608248071ae401b45acfa7adca1fe98bd23e +S066/S066R08.edf 60bf15a0629829bc2e0c615639c0f288e9b1e963a086293ee95da8a4d70f3b24 +S066/S066R10.edf.event aa88e9dc85f46564702f7964b37b2058d00e5e0b93d498e32bee49aaf8e7c745 +S066/S066R04.edf.event 8a76f461c0b920a909de21383cb5135f496cf1aa992529755f784ebf12db55c1 +S066/S066R13.edf.event 834d050efe55560305b0e19f49629260d26f65d715e477894ee2b099b0f5b1fd +S066/S066R06.edf 545722e46baeb21596eacd15e46e6236a925daf0283c23804950973900a4c22a +S066/S066R14.edf.event 8c03a670d4980d94f17b5f418cb3ae868421643e376bcfc41d654e67cab2a9f6 +S066/S066R11.edf b06a5d3fc3538be7edacf428a6c2080c011c3241996714172a456528daa2b9eb +S066/S066R07.edf.event 2e361d8b420d6db7c1d4372f2f615a9f9290ab6956917406863d12a1fdec8f5f +S066/S066R05.edf de03c1802e5f55b5de86e87dea506fe7c45c643fdfbcd6f5ffd95e7af8c8b463 +S066/S066R03.edf a760e737deaa26ac36f6c330bdcae1ed775eb6d2fc702a729eab4c0d0c7d1b93 +S066/S066R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S066/S066R10.edf 9705bb7c458b9220de25f6ecea44c046c25558c62bc975e7a3acf2b2354bf54c +S066/S066R06.edf.event 3cc4e538745fefccad07dbe59abc1ac855e1b6121abf89d9f5027ac9337e7c8f +S066/S066R08.edf.event b6e7436289258e26595ceb80330f103bbdd26d9f045dd5fe5e5bb46498a69180 +S066/S066R11.edf.event c8694215a3c53fb8dbf9397e9d5cb12ad4bf06f22ed39533939d10b8ebcacab2 +S066/S066R12.edf a3e8b2021df910995ad9792dfc2ec025ce1b858cba8946cab2bcab9899b51e2a +S066/S066R05.edf.event b1551573cd91101be666afa2abcfdb421f144c3fa966b0a62b6251bba942a18e +S044/S044R07.edf.event 2553cdc46c8017dc83d793a7cce6a36ddf99a043e777612539831e67f1aebc23 +S044/S044R09.edf.event a8ce17ff32c2c3aa820817e047ec3ff9976bd33355d14877f0ff811df5a288a1 +S044/S044R10.edf 0d7bf36388fd847667152db2d79177868cd25981779cd66edbccdbb5646d7c58 +S044/S044R06.edf.event af55de06274e9f057a8c2b10bb8a4665c70ab950b43d066ea9e3d1de5f188b79 +S044/S044R08.edf 5f85b54550e4f648712fbd56a6edda9df6d93f0169b057dcd79ffc0a20224988 +S044/S044R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S044/S044R05.edf 85675c31570d00c43ffaa607609f7e699add2f044f0051aac9ee0b1dd88f256c +S044/S044R09.edf 9dd68765db03a4e42839ff923d246b88e53ba314489c553c6c9c0740bed073b2 +S044/S044R10.edf.event 8ad7739d7d370e087ebe5db6ceadbc03ee38d96703e78cb5c91f2b714f07a25e +S044/S044R01.edf ca0199eeca73ce7b30843e2a06baacca5cfcdc4750cd01a1e237af6feec5dccf +S044/S044R13.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S044/S044R13.edf 64219a96357fe674f8926e8042f9fd2f8210dc8e653f038a1f26671cc2c8bd0b +S044/S044R14.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S044/S044R08.edf.event 48ad6251760a77acc67b82ce0b201f4244cd1385a6181c8236487af76fe1636b +S044/S044R05.edf.event 0724cecedb70811bcaf06ec5a41151edaf5209f968315c4da2e3a25bbf0fb9ec +S044/S044R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S044/S044R04.edf 5da0315dd8b4e33769cbaf69b91e88845cd460f406fc0c72b793bc1f6b2229d2 +S044/S044R02.edf 52dd4f7c19b57e0f61aef7db45993dd60678657045b7541e390defb5602724f4 +S044/S044R04.edf.event 51f07832e9b1d3d8c667f73dde4aa38f9d3e45cf2a4c2baf8e47ea328c860420 +S044/S044R12.edf.event a376b452fa5f7c300d71ec31ce58f97920510a057f4ca6c506f4cef51faa7315 +S044/S044R03.edf df43d9106188f5a38d0f518a5809dc454d5c6d66dcc6b3bfa3edc42041edced8 +S044/S044R12.edf 84d09ee270206ab1f93595cb00d28b51af2cee24f4dc44c23a38464db833d463 +S044/S044R06.edf d16e19dd5d5ecb9b871c11ca624ad8471c3088a3500a65314ec04f3056551e44 +S044/S044R11.edf.event 39b46b55fa02f8503f1d8726fb4de22eb131c815725552e89309f9db71c825ea +S044/S044R14.edf 717ec3207574cd4152200d6f57d531bcb9c699b4f321d34754d055407bc0a542 +S044/S044R07.edf 5d0b03dbf8b1973dcd0a77ee284ecc4cf6fa13d7113ec6b3d0f7c1cf6090ca03 +S044/S044R11.edf 9c104974be9015b57253abae61eb0c3e391314cfae8fbc94bae03c1ce0cac4b6 +S044/S044R03.edf.event efa5d828429e8df393cf3e5b452a00dc9f05f3ad9eeeeb119ad18eafd1cc4e2a +S092/S092R14.edf 99b147c5ea0bca55544ed7163d3747174a5a06a6707d057100d124062f1af173 +S092/S092R03.edf 7131a3198f80a3a770ee2396e8792f644fe9ee520edb632edcec921fc9a57c69 +S092/S092R06.edf.event 682de6811acbabf1882380fe24d80b87fda2ac6a48fbdd6eab47970ea1190440 +S092/S092R04.edf 73ca4043e4c8d38722fc6482a0e231a8505ef6b760cb26bbbb8206f481e683c1 +S092/S092R07.edf.event 87602b626ec0e48829f47bf9d0c1e958c80a92ea1d57745168a2630ed1101f98 +S092/S092R11.edf d6952ffae0a847e93296a6a5b66c9ef66d5e685b08fceb730e84fb36793e806a +S092/S092R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S092/S092R02.edf aabf2489637c7c71e664cb697665bfdb134d5d4776b1ed95cce47bb7c02efada +S092/S092R09.edf 9ad876cd642aaa1e8607da4e838331b5254526c21940423742f224bcbcd820cf +S092/S092R06.edf 8d8c4a918a1e4081bde09019c0449531dec960908dadca7ad25ce9beb87d900a +S092/S092R10.edf.event 0930979151ea3e22809e2b68d6fad0bb672dea8e58caeb269c20f5bbed49f1a3 +S092/S092R07.edf 0067ca60ff80f5f27bd234bdc23414e0b99b0adf5cc8a989aa2c34afe6de2204 +S092/S092R12.edf.event ccb7718e9ad0d8edd7de8d12553d98a89bcb191c436a6067b3e688a579d4abc9 +S092/S092R08.edf 38c8c9e7261c6882b4fc0db19c4ccf905e5249611c6fe9d3c34ed7da098c6481 +S092/S092R09.edf.event 87602b626ec0e48829f47bf9d0c1e958c80a92ea1d57745168a2630ed1101f98 +S092/S092R05.edf 777b5e451f9dda96881d311ef5f6c9b913a738aaee0c1ac613347dcc6936e3b4 +S092/S092R14.edf.event 0930979151ea3e22809e2b68d6fad0bb672dea8e58caeb269c20f5bbed49f1a3 +S092/S092R03.edf.event 87602b626ec0e48829f47bf9d0c1e958c80a92ea1d57745168a2630ed1101f98 +S092/S092R01.edf ca68794592fe3ce3f0217fda4729b2ff16cc83a3bb447302236fb0d83052edfb +S092/S092R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S092/S092R12.edf 5e84bc4b49bd530383b8c28c9f0296d7847012e49b276e916278cea2d9b4ff9d +S092/S092R04.edf.event 82e7ace9f055649957ab04324ffce9101db68bcfcceac1df6786e304f9de8669 +S092/S092R10.edf fb3c55539a8144ffcb8318461c5f8c8967ae27e84a56e8aebcfd6fc0a21df933 +S092/S092R08.edf.event a27a31471bf1b8bc6ff9b144eb110e9eb0711b24514aaf47ed1cd94395c10b7e +S092/S092R11.edf.event 682de6811acbabf1882380fe24d80b87fda2ac6a48fbdd6eab47970ea1190440 +S092/S092R05.edf.event 682de6811acbabf1882380fe24d80b87fda2ac6a48fbdd6eab47970ea1190440 +S092/S092R13.edf be01e0d6d7fc971cb579f030389178b37159e6bacf90dfb41422d48bb5ad02c1 +S092/S092R13.edf.event e88110dc871719db682717f3a256188ebe916d76e5a1a09b0cea908778ae4424 +S035/S035R08.edf ef619d2dc6be970660c2a7ecbff9d084633c3fb023627604283b9606ea7fb668 +S035/S035R12.edf.event 96801f1d89a25da6122f3b69f7160e12f563f1b8380dce64f2d4b18d00121dc5 +S035/S035R12.edf 2358c7e90652d3c687fbcda65ae4ad4a0faca39dbd736c06ea1d8e20173671dd +S035/S035R14.edf 4192067f79a42c47fc73338bca078246f2325f88f5627893efb1a1b5550bcffb +S035/S035R06.edf.event a07306d470013adf2a41bea413a8bac37a03938f3358cb519e480a3b753330d9 +S035/S035R09.edf.event 4b408c3796f7bf8dcd27259a0ae6508128a2f1069560a5cff7d3eba4508a6768 +S035/S035R14.edf.event 3048bcb4e0fbb0a4db3d630b323c27c5e88b2f2b6aedecde86b33b1d4f135461 +S035/S035R07.edf d27bdac7d879d570fd9ba141bdb8cc1e9b94a1628b4a0f430e5e1964dbd90941 +S035/S035R03.edf 030e8222c98a22dac34b41a08b60208dd1b314ff3b805d0a7e102b455cd279fa +S035/S035R13.edf.event 14a453fc6552b2a6d7b55329ca3533853a89a83368101bee6b522e4a67d37283 +S035/S035R05.edf 09e053c055aaa3fd01b024aea74f20957498f72215850510184cb3484cfec3fc +S035/S035R10.edf dd4df070d8b01f68173410835b3d932f4f9a8779191c0518c0933c38bbadcc94 +S035/S035R04.edf a8f13980108a70cc3d410ab231588bf76928e51ef9234650be443ae9cb4bfab3 +S035/S035R06.edf 5324d829c96aca9fe7a0662090dff6b541693e00b782fb3bd07136896a3ddb9f +S035/S035R08.edf.event 944e95e6448926cfca766f748af6a71320282fbbea4cc8f227c8d8f4401f5bc4 +S035/S035R03.edf.event 969cbf2f95e5e05eee52395b936c0acb835c1d39af20b3327802965209d3513a +S035/S035R05.edf.event dbd0435f98476653a27f53b54a6757c6e4596f6d9318a14067e4dd50bb37a888 +S035/S035R04.edf.event dea4ebd6eb695d78f9821d3bfa3d4a325dfc5d7ff6f514c6a3f205dfee689e4a +S035/S035R11.edf 1959e6d5a8130d0f13be346a63880029c949526ff68285713d790107389f00c2 +S035/S035R02.edf 877f3cbaee32e10af7a724be0d709a3a9dc4121a4068b7e4ae418300830990c9 +S035/S035R13.edf cbb0c1b7d31129ac29c52e20ed1b01eb9322e8c72591da0bffc3ce51135cd9e9 +S035/S035R09.edf 5f930fdb0975acb9c936448d93c9e454cf3ee73ef3dae7eecc54d1a92662058c +S035/S035R07.edf.event 273c4fa451c5781d94b0c8204068736b90665f96073084c33770108605bd302e +S035/S035R01.edf c3f65f266df7240a795efc209424b75cd86a30823f63795b51a62deb095f4700 +S035/S035R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S035/S035R11.edf.event e9223514a9ad07601113bf25a3c8e05f3728fcbb5a15e7cce3b90c71df93b940 +S035/S035R10.edf.event 21ef6252cae53bae58d9207d35feda75f1e4a419273f78801e618eccfbbfee77 +S035/S035R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S046/S046R12.edf.event 3048bcb4e0fbb0a4db3d630b323c27c5e88b2f2b6aedecde86b33b1d4f135461 +S046/S046R14.edf 1583e16bc35be30f73901d64a976852fdf89fbf11cefb7b71473875497a9110e +S046/S046R11.edf.event 271170f0da25b9bc7523c8eccfc0cb14ca8d86085b0706c07a42357eb742bdb5 +S046/S046R14.edf.event 23fbb5b9f1007e8652ada0247eb06163f5b93eb5899bab7b719341fbeaf1345b +S046/S046R11.edf fd4300ba279b330343ee16ed3e53e09b84123f9df78ddb15726c5dc77d747d42 +S046/S046R01.edf 49b18f6779e3fdb549c80551379d76ab5fa7f9faa429e171bf4cd38f121ae5d7 +S046/S046R06.edf.event 2a8cf80126be415d578e94fa0061ffee1677829d53c6df1ba1aaede8c845f31e +S046/S046R10.edf.event 7eb3d99d1a46e50d5ec14297be174789c9a514ecb48636ff9ba19d90bf2ed9c3 +S046/S046R08.edf 30e3df4eb6380358330a30b9d9906286a110c46a5eae2a991e83ced4a2abe3b4 +S046/S046R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S046/S046R02.edf 73f41c42ba32cc7acb2d2312bd33308378310e3a4be74490589b95e91fb64d45 +S046/S046R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S046/S046R12.edf 3238e8feb6b1faeb6130cc813b0c147eff986e9332cbffe7b0dd9c5a87975c1b +S046/S046R04.edf ed0b219b3b7f3a340b504a801044b8a6c9c33095a59a3dfab535c6a06abd0670 +S046/S046R07.edf 6e18290e6aa7e774e61d3d5f1903b3c59680b56a9afa3807d381d267fc8f8d9a +S046/S046R08.edf.event c8e92376627dec774f2017745ed32f94ddef2c19ff70ce24fa9679133dc0e7d7 +S046/S046R07.edf.event 13687e378e5618583bff478cd8ad8d7c8c39f230597cfb455142d8199d52bd8a +S046/S046R05.edf c7887aeddeedc3aa7a7439bfb778fd8f8028eca8f53375cc99c3b5aefe2f9bf3 +S046/S046R09.edf.event 58db360bc4c16d775b7e2c4797c2215d9f1405c25061a2237ec95b2ac264f964 +S046/S046R03.edf.event e3378f798c2ae2109571b901374ec3f6e67c17b45e2f63b458ca5b1db30f1ea0 +S046/S046R09.edf 49c058fd06ce3f5fb70d637aed9953ca168d6cb2ca0ac698a8061101ba2c3054 +S046/S046R06.edf a7e2bb4b01b80d2a367d92755a106f908a09716da557f527876d6feef610482b +S046/S046R13.edf.event a6cacf979bad39813ad2028620db2781eea6e16e029b8bf69686928d2958fede +S046/S046R03.edf 23321c49c441693d32b7b85b5e77840dc94a90f2cd66c7df24d5d3e6fd01345b +S046/S046R13.edf d17bee540747f86c9a72c8e8ed054d2a85c419cca8c9daa77e6cbe0e312d8c3a +S046/S046R04.edf.event 3048bcb4e0fbb0a4db3d630b323c27c5e88b2f2b6aedecde86b33b1d4f135461 +S046/S046R05.edf.event f642bffc792f9e20fa7a76eaa7a0776154e7b8e8be7138c7683483a28a2ccc74 +S046/S046R10.edf 884de1d68843591d3e82f99a1b9c88e1bd9293ce0dede387c14a66446c6f74bb +S071/S071R11.edf.event c65a4f3a39476047a743af02cee3029310ece7de2dce5aba866f5d620c729555 +S071/S071R12.edf 54ab787be535020ba05284d323656d201776261b78e2d9f903a8b4b573dc6be2 +S071/S071R09.edf b5f606ac18c89c1a9ca45e2541d18dcb0fb0cb337bba89cb91dc36c45c5f45a4 +S071/S071R10.edf 363b6fcf3c4c82b8a7c7e4af8a4a68e4861004c3838f15c7e80b34cf2649ea10 +S071/S071R08.edf 0fe7edfcff87102410fde01bbb9a4770b20ac6359f3bd77dbbc3551cd2ce35cc +S071/S071R04.edf.event 4c61f07321b475d0f07c3a93b262cc94a5bcc7e8c59d05610786071ce45cc544 +S071/S071R08.edf.event f73e764c2a5687f81917e5c4eaa8b964ecb99e4c58ff33aa7e02e5fe1f655a98 +S071/S071R12.edf.event 954333c8a5a38083d1d58167e4f7c3abbbf8949bb46067df41825e1156c3b517 +S071/S071R09.edf.event 14bdd1b94d8b8ccdce55e581601a4a304c1444e030aee15596722a70be24c5c4 +S071/S071R05.edf 751711bc497af9317c44ba30c77fdfa1333a743541b8197f2d7a341536cbe941 +S071/S071R06.edf e3ccdfd753bde27a09107acfd381fe97d3efb253826d211373559051bae81199 +S071/S071R14.edf.event e9223514a9ad07601113bf25a3c8e05f3728fcbb5a15e7cce3b90c71df93b940 +S071/S071R05.edf.event 061a2814f7c0e21b94dd0e714f51ae50ebe28a4f57d1c4761b554a77f13694a3 +S071/S071R14.edf 6e682c11303810dbddbc47aea87f7e5f9c2d800e1cc28147daf7215488251c5f +S071/S071R03.edf.event 178339a2095d7eaf759407927ba3657ec8e96b153a8e085f8a593674f3697b42 +S071/S071R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S071/S071R02.edf d2ba66c8ec637b4fc6304b0562cbce0874ed0faea3464a72221840390717d7d6 +S071/S071R04.edf 746cf8cb98ec73c251059675f4c5b956c9e8db11bd0de7b7785950e53ebb4647 +S071/S071R03.edf 2a196695568ea8b1f977ddcc95e4e8211d55c087e04d539ec64f65537d438e58 +S071/S071R13.edf.event a3a021aa3014366fda2210569cdbdc257724ba6d0d11b1e6c924103e837c7294 +S071/S071R10.edf.event 837f0145b9da4dcc73e14962769b9c68f3eebad462eebe9d8796bc8b099af925 +S071/S071R01.edf 55ee9a28e1496f5b730ccbeaf859063b2dcc9f11039905e6fbe04fd7fbeb38d2 +S071/S071R06.edf.event 582fbf3e4f5bbd51cc3d858954988e7800ce943626d6f081f659cdd9b863fc0a +S071/S071R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S071/S071R13.edf e47c2ff64522b900eb7c950722b3cf31740747543a512b65b11a233282c8938b +S071/S071R07.edf.event e697ba3ef839244357e1c111d7dfa9afb60310a0bd8b7935ea5a426a1711194c +S071/S071R11.edf 6c798e4af0e540fcf6f026ed4f10498ebc2da3075b3d30a564822228d67af808 +S071/S071R07.edf 0e734c92705376f7e26989101d0d6bc4adff69d8eca4a8f98a17b50700cfef27 +S086/S086R08.edf.event d192ea57ff85ecd8427faf400415c2002cb41aa1189199e0c6ed62a7ecd048c1 +S086/S086R09.edf 907868e30923356a1d675361fecd1a60cd4db3e2fa52d308a5da2a10f2079331 +S086/S086R11.edf 54c35f32beb832e3549fd73264eeb3092601b2ba29b2b11c9c7be42a70795e31 +S086/S086R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S086/S086R08.edf 221dca79488392aa00b3462fcfa6a21b185e5814cf6534ca35b24780aa1da799 +S086/S086R05.edf 46d4fc4f3986d58f220d2c5db58475cdaf6c2960eab7c8e811d2206bf576130f +S086/S086R14.edf.event 23fbb5b9f1007e8652ada0247eb06163f5b93eb5899bab7b719341fbeaf1345b +S086/S086R04.edf 606f9e327b219cbd980f4cb5d83497052a07d927415d1769b039bf0ed7eda693 +S086/S086R10.edf.event 3b5e25a187d5d82fb5b851ecbebf095c41a5496c5a40492c7a2c638245bbed51 +S086/S086R11.edf.event 9b428c26e9e449e90bf57c3b9f5322d9c5bc5f4a65f709a1ccc3c22566292dbe +S086/S086R04.edf.event 272aa3698bab2b05544eceafbf5b26dafc58d0eb50a508a47c26572576853ebd +S086/S086R06.edf.event f4b63d6f50dd4c8695c739b04c7adbcdae610db216040f9c2b732bd361dc9121 +S086/S086R09.edf.event 7771fdd0442286733558fade28a9d92e116695d1dfda6da3cf3487c4467925a6 +S086/S086R03.edf b9d675c4eea24f641af5ca3bc5eb08edd0b8441100c6729a4b3652bf0997447c +S086/S086R12.edf.event 9b428c26e9e449e90bf57c3b9f5322d9c5bc5f4a65f709a1ccc3c22566292dbe +S086/S086R10.edf 2ebdf1e349101b21c3e9e9c5a24f8b6546bc7c30691c6f7cb599087554a5fc69 +S086/S086R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S086/S086R13.edf.event 54016a6260b12c8b99943951ccdc7d5425efbf9ab503ef1abeb93deafb262790 +S086/S086R07.edf 012d5e9c8d6e50fed9e25a748a638168b18fd18153a2ef69a4e1b8cf5836250b +S086/S086R02.edf 4a9237d42c10627cb84d023b5b7056000f3575ee82c10918e4cee3960f27e0e8 +S086/S086R03.edf.event 600983ef19711fe2016d742d1857fcdfa4f0ddc7c5b8c88773db0019f92315d1 +S086/S086R06.edf 370494eb367603a1bb5e16ae5a41c0c85f359c2c0d727bed2a2658ed3dd2b612 +S086/S086R14.edf 712b7758f35dbec80272ac5671e567eb1a61a898a8a05c77a47286955c8e6074 +S086/S086R01.edf 32f1b040a3f8bbc6f3393a48b81ed911095fb0cd78859a129e918f675b3c4167 +S086/S086R12.edf 966b7d92a7e7d3981d56dbf0e159fbfb3fbaf2d955e3573e384918b24431284d +S086/S086R13.edf 6fa20a1e6197c689ec1e4092bb26e75de63e5b2f755b434652eeb11a8b49bb11 +S086/S086R05.edf.event c2ef16690608bdb9ca84fdc930f584191923370f4568e2e42e5808557fef6d8e +S086/S086R07.edf.event fa68bd707dddb5ac8734d2427c1812d242ef23f1aa95b9b002fb67ce4bf47ea9 +S012/S012R08.edf.event f39b724630cf39de64096da55e80ef4acde232132367bdb459b9a4b872fdabb8 +S012/S012R10.edf f70b4292ae24574f7f4835ae89e7d5fc6350c26d0d8da86b347ea0bf4956a17a +S012/S012R14.edf e1b65406fcdf9107d1cb5ec813b7dac9a074a212172d1f79fc403304125900ff +S012/S012R13.edf.event ffbdc0e528335775cb88a14baab7b7f1fff4fa1647a473bcd640feefcbfab5a3 +S012/S012R12.edf 2b76c97a6cbc894a85a4f54385997b6aa07d3e9ec040ec1adf61a310b26f5caa +S012/S012R04.edf.event 1ccc28680a9b24af49105d307967ceb434f5229a29e70fbfde089b2d092db7c3 +S012/S012R05.edf.event bed28cb624951271916f88bc556ff204ccc63699ebc4523ed8043baa9724625a +S012/S012R09.edf 4255d6b2a406f8a8e9cded98032950cd00d97d8d40a558ea1eb34993b3a9c7c0 +S012/S012R02.edf b4f7e8b1b083835899b7b6cbb58c582fd8290311135b3e0148c5b6ffee4f6b1a +S012/S012R03.edf.event 25af506ba70b68343c97ccca1ad0f235958a8dc9bfdd84c6f7155937e7bc7efa +S012/S012R11.edf fd7bda82802bb91b4e04848ce1a8a9a3e5bee822a811d0bedcf812ea4acd273e +S012/S012R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S012/S012R10.edf.event 151aa0e52269f6759e2bed18339cad06a9761f4b713071e665a50681af66afc2 +S012/S012R07.edf.event af9bed6667136366cf88d2cd7f0f5fd9dda3fa51cc4cf73d3afe4d57dc8b7502 +S012/S012R13.edf 892c9975b683852675a14d64c24730756c189133c01aa974eeeb41a7291e3d09 +S012/S012R08.edf 5d7d13ad211f615a21db64c3a4dbc8ff4ef10dc3f777b8e6441d8942e8d40336 +S012/S012R06.edf fe617707aa63e902238e4de12cd8ec22c55822d05d09f60bccab9d08ac53055a +S012/S012R09.edf.event e9aa79af3e48ec970083b6f911002eac68ffb799057d4805cd5fde8f16d76b97 +S012/S012R04.edf 974d6c7558c8d8ee48449bf9a1f40cda596febb6365e69e8e65c2d952644017e +S012/S012R14.edf.event 37b92549c1fe5d740cc394805738f2d228f8fb948bb4c3aa4817c4dd4b04b9e5 +S012/S012R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S012/S012R11.edf.event 04192a55fa7728d34533e76a1b831fe5c94d79c3bc9f1028f45644c51892a744 +S012/S012R12.edf.event 151aa0e52269f6759e2bed18339cad06a9761f4b713071e665a50681af66afc2 +S012/S012R07.edf 47e446122ad05c46d8c0e605c84641ab8a93ba2b8647f0eeceb86ee26ee9d9ab +S012/S012R05.edf e216fb3bfd30a0b9e8c94e1a99e2be1eacdca620872e8d152c129f30517bfd25 +S012/S012R01.edf ad02ce8943d45f07bcf6f69714a61005e570f3fd26f0e8e1bac38c7ad80fcc73 +S012/S012R03.edf d2af7bd93c37e741a77f8f0f611abe3b15baf1a3db65eced1bbd1011f3b193aa +S012/S012R06.edf.event de55d737a8555e174e0cd004746337287c294a01d42348abe972b98f07739b4c +S080/S080R03.edf 021c4dbe3656eeb9e95ee4ad422fd0d0acaca6ef06ab3607e373ac1bde810a6f +S080/S080R11.edf.event a18bb793691db61833ea9b3b10da118a6687892d063d72ae795055c9209ba8ef +S080/S080R04.edf.event 49dac749bf850e47e5d13a8edef5121c75a7baa7f50917a5c17c1dda52d3013e +S080/S080R14.edf.event 9a154a517e2cf402786cffa7d164d0656aa7a8bb30af51266fc6403fcd9d3d00 +S080/S080R11.edf 3f143f67b084e6b46bd62ceea2fb3de4b68445b319355239694dd037ae85264f +S080/S080R13.edf 85a42c5f160296eb8c67c85ccc341c70bdee43def24421b69f88aaa8200a317f +S080/S080R04.edf 39a8fcd0b3e2e7f7e33c54e867036d5bf43350e6525278d42c39cf6e3f642796 +S080/S080R08.edf b0f8d997cf95924f44e7a6fe44e525d22f66c4760587cd7589d4430d210c2d0b +S080/S080R07.edf.event 0aaac0e6493abaa7abc2bbcabb2ba2ab9cf91a665d7b07e95e181cb6e7a7d207 +S080/S080R14.edf 3fe341ba3fc26f7646e874235bd651eee3b490546c07a4d06421694d357c6a91 +S080/S080R13.edf.event af55de06274e9f057a8c2b10bb8a4665c70ab950b43d066ea9e3d1de5f188b79 +S080/S080R12.edf.event 88e1ea56ed0459a99b011a3ea2f25f947016dd359b2d4fd683f838ac00d993d5 +S080/S080R02.edf d4bca47e46e37452771dd39b66a98cffaff0bf9235a8c03efbe3c8edac3d3978 +S080/S080R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S080/S080R09.edf 1b3751f1ae69e24ceaaa4eba361b97df0cefef1d2896c36817502585196d37b6 +S080/S080R07.edf 42d1be730e0f57bd2f6974856ada684ded850b1d11e7a58754209892f2e1dc5f +S080/S080R01.edf e02ada53d55ff4abf99928b1a5da1773023170f345d2c223a3a73b0362683d62 +S080/S080R03.edf.event 39c9864c57efec906759ab97dba0ab26a900fa25ad8fc3c48b0d97ea83c3a893 +S080/S080R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S080/S080R12.edf a0b99813248b36ff650076e0fe38f205e84a6f26e18bce0a43c5510a4cd933f7 +S080/S080R05.edf.event 8612fac39dad16048db3bea4e27be45fe67ced9a22781462eb9c6e435fe28d6d +S080/S080R09.edf.event 7f2596bafc4dd481e36c47d0e562fb6c5f9b7e91c2a915f19f66844b55b75410 +S080/S080R08.edf.event ffbdc0e528335775cb88a14baab7b7f1fff4fa1647a473bcd640feefcbfab5a3 +S080/S080R10.edf.event af55de06274e9f057a8c2b10bb8a4665c70ab950b43d066ea9e3d1de5f188b79 +S080/S080R06.edf aa562fdab20e7bb423562f3e5d61c0b821e3912bb29353fbd1032df7d78ac34e +S080/S080R05.edf d97fb389b6a1c7e6d1a6c5e6f41e91d791f963bc798e793b0c494dc452bb809b +S080/S080R10.edf 8171d40610e3f67b030e5e8f99b39e2751e559398acce78a339962bb43fc1801 +S080/S080R06.edf.event e9aa79af3e48ec970083b6f911002eac68ffb799057d4805cd5fde8f16d76b97 +S054/S054R03.edf 342edbf15c5e37d6b788767bff954a2c0c8b4fcde334d733ba67cbe2dfdf3077 +S054/S054R11.edf 0801cbd50fb6bf1a9afee61b5b424a1f0025025f6fd3d8e580c2b5a76bb641f1 +S054/S054R04.edf c2caf79d559efa0dbade6c67290c2840a75d9b9266b242286aab64ea048facfc +S054/S054R05.edf.event 9e1cfe676de301ff52ef7ef70ad2cdd8b8c9562c01e98d8eae191a5c8c28aa46 +S054/S054R14.edf.event 8121b5c61470f12aea6d6cad9727a5b33c741c9f15d24ee389ddc52970df76af +S054/S054R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S054/S054R08.edf 8fccdcfa00d100148b350b772557a39b8252ceec048da5e0da93e1273cdc8c88 +S054/S054R10.edf 17828d840d9f134ad5129aa66f8842e267a5c5945126dde28fe4c621d0b61f87 +S054/S054R11.edf.event b7fc6043070236adccd2c6d2a291a12804c8a08c7d7b2194d31b1f6996080655 +S054/S054R06.edf b2ec60edb8b8c1a6cea288d328a13b5ebedc3a6d3e9df4ca97f9b2d9de0f5fab +S054/S054R14.edf 6c3ea5618b7e8ac1289f042ff45f55cf017f2e76e0512e7fbda0d2c33c3c5e3f +S054/S054R04.edf.event aaa5cf263ed5e1e7bf38b3d540f4e2d286107c553f7904af5c9cee9bfe715f19 +S054/S054R12.edf 2e1807664cfff1512a8a9ef5ff105e3a19a6c7ebf30dcc6a321244a46f943cf8 +S054/S054R06.edf.event d0280a6531ef96d2b622c2d562c05bf53a0d00439a4819213365b6e52e54abd1 +S054/S054R12.edf.event 950cf97301dd495a2a6a7a19a93d67d2ee9ee03b2675e300582e19305f5a9287 +S054/S054R13.edf b7f29036b47a2daa493f819cb3419a348d8281d39e116a06e89342da6c54e4c3 +S054/S054R10.edf.event 48eea52bb9946ed46ef7e1b621c8558d41739ffc9aa7ed8fc25eaebd171ac223 +S054/S054R09.edf ef124916d0134c53ed3dff058aa6ffbfa1275932751b98b977c55c4fc174a2b3 +S054/S054R09.edf.event 8cd8c690df55a4167dd5e136be1c424a77655375599a9d3350d5460cabab539d +S054/S054R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S054/S054R03.edf.event dea45ba8a8662cd82aeb9d6c523756ce7079f3020c2ad1b23d6dca2f63b5bf82 +S054/S054R02.edf 55442382a62972894ca7ffcb353b8aa4048043d805da35fff567ad37b47a85e8 +S054/S054R08.edf.event 7c83be0506163b52a89548c7af6d4893472403c2bab3a455c7d8c92bf3550ad8 +S054/S054R13.edf.event 26fabc186c9b04bd70469a5964b2648cb7a2115fb0a397d51de147fc640d8d83 +S054/S054R07.edf 38ab1a1b03ec75552208467a02ad50c8b29be99e587b31b1f0b21281683861c1 +S054/S054R07.edf.event 68922fc617d2a7f851f538c226fc5491b6f57526417f33c57ada180e97746c59 +S054/S054R05.edf 499cfc020d673829f77de992d6014a5946968fe26a39adbd9efcae257ac580c1 +S054/S054R01.edf 329625cd03103c4162f6de3c409f3664c68481979263f56e50b8dae272e27f7f +S033/S033R13.edf.event 815500806b68247c0c383804bb4774dc90e7f96d61e9e2b246fc5d33fcb5aafa +S033/S033R03.edf 7b062b51f8af082de4aea5b514db3ec97db2dad908166f4781566218458443c4 +S033/S033R08.edf 0ee2a5a00463bbc650852de790943bc5af90547bc325bbc65be19e9b16eaf0a1 +S033/S033R04.edf.event 25af506ba70b68343c97ccca1ad0f235958a8dc9bfdd84c6f7155937e7bc7efa +S033/S033R14.edf eb372e2cb331dbc63087439c5dd18da0610f4309e68c2297949c897c6a0d6a98 +S033/S033R03.edf.event c843292c2d927d69501ccd581dd6688cd971a162df8d02a7eb20e6a3c1aa2d83 +S033/S033R10.edf 3e4a4eea41ce75b89fd2027c06115b30e6ff36ba14906dc6915441faecd4869f +S033/S033R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S033/S033R13.edf 64ef4744b1b276a462b60627dfef69b157b3fe908634eadc17ca157b083a987a +S033/S033R11.edf.event 57636037048fc90c882a690b692342a1f4fd070d9f2a219d527ef6c0f7ea7dc1 +S033/S033R04.edf d4520b8cafbbf03ce8d2159bb727f0f6032c1e9533bbc275f1fa4ddcb9cf135d +S033/S033R06.edf 772144edd7d06ab31cc649a6c460e43125e9eb13801064276529899f4b51cf01 +S033/S033R07.edf 6aeeed7165812bdf3bc7380539f53f0b0712a74392a8f37f38c4747c96260db1 +S033/S033R12.edf a2968d5f651e72700096a652c3dd2fd34f51e9c381bef25c329dad3a3e2b319f +S033/S033R09.edf e0f43954e8632d987be2a52f116febffc93f9d1dc62311d4f3831249427cec9c +S033/S033R10.edf.event 96cef3a9a9e2cd7f438d53008e256b198c48c6e0d2f0b2d70e0d296180cd58b0 +S033/S033R06.edf.event 0aaac0e6493abaa7abc2bbcabb2ba2ab9cf91a665d7b07e95e181cb6e7a7d207 +S033/S033R05.edf.event 83f18e3a845e17346dc10fd176b61c6f306078227a59bb51610834234d1454aa +S033/S033R08.edf.event 440457b385c6d53d2340acbe5512027de7800fb1514858b055b126c10e58b404 +S033/S033R01.edf 5801c97826b681eddd76641707c479385742b0fa35e5fae0935a81fd139fc646 +S033/S033R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S033/S033R12.edf.event 57e9107b34629563ac9d22f509b6f40e40ebedb8afaca03c2199613287fc06ad +S033/S033R07.edf.event 8d9c5bb3c83f5f447b4f8159b1454d55332838299c0e4a8e2dc62f413b08cea6 +S033/S033R11.edf e70abe84015480fac548205192edf6e472ba392086504118425bf80777b80984 +S033/S033R05.edf 962ba5f5aa3fbd2440ba34ef22a9d3852ae01f9f7cd93475cdb13e00782ebbd8 +S033/S033R02.edf 9a4872573c4ba67267f49d8c2d286776792fdbfe76dbd10c696950cdb34f6e90 +S033/S033R09.edf.event cfb6d9316552151b2cc7a4fe7b3c98b0ffddca0cea554883679586887149feba +S033/S033R14.edf.event 9b116dac2d8fff59f5bf4cc8d45636716575c73d6e6b2287709cbfdf0ce5f55e +S062/S062R07.edf.event 596ad948f8aa9dfdc6cd3125a3d02e115d1cd6a505023467bf5cd721125ee7fb +S062/S062R12.edf f95f21cde281182535aac5a41be11bcd12c1939a485535bf551e6da3f3ffe6f3 +S062/S062R03.edf.event 350042ca5c37cad9cabe8c469aead2bd074d996b13c69cafba8d24cd8fd825fb +S062/S062R14.edf.event f500286a76884018ad149ef34cc8871332593723b30ad3d79f8f39236a5cc25f +S062/S062R09.edf a614ede1529dc1cc60dd7ac3af1a4ae2214050ddc6c378eb5e2f8a59edb8ae68 +S062/S062R06.edf bb609b4819f7e10634350762ccb52d9b04df6746baa95b0c73b9d4f36c857a15 +S062/S062R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S062/S062R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S062/S062R05.edf.event 710672ce0f425a207ef543d23f608683e1863d7423702d511235d71ccbd289cf +S062/S062R11.edf.event 950cf97301dd495a2a6a7a19a93d67d2ee9ee03b2675e300582e19305f5a9287 +S062/S062R06.edf.event a18bb793691db61833ea9b3b10da118a6687892d063d72ae795055c9209ba8ef +S062/S062R12.edf.event 8ad7739d7d370e087ebe5db6ceadbc03ee38d96703e78cb5c91f2b714f07a25e +S062/S062R01.edf 3a2d4ed688479495bf9312be25dcd3ffbf393ba786f185700b611e9b95dbd4ef +S062/S062R03.edf 94b594c87e91c1e1a932bbda2022760641d3cab621132f8cbcdada1e919f5cec +S062/S062R14.edf 40d5eeb86b99c22b7fefc5a08d638d9be9bb5b8240b661451a71574b2c6d21ef +S062/S062R07.edf ba192adc3503f736ef9df7d07796f5b15b0413c3a5e05d5e7d3523970474ee11 +S062/S062R02.edf 5ce5b78bebf8a5e7cb5ed88064f0ef25f3c7cea58ffbf791453d5aa2fbdad831 +S062/S062R13.edf feb14f0a8de34b68017e66be8b19f702d3872e7102f63f6dd8fb17b1e4de4a6e +S062/S062R05.edf 2257a462ca24563b2f157d4f6618f5313933ddf7fc66986ffeac5df2de258794 +S062/S062R08.edf.event 8fb228960cd397f6100e75cca49e1045159bf62e6184dd5267ea608be1d540b6 +S062/S062R13.edf.event e7ef0a3d66a5c814c6e917ac8f9bf83d6056810f78dd0c9296b5445289483fa5 +S062/S062R10.edf.event 815500806b68247c0c383804bb4774dc90e7f96d61e9e2b246fc5d33fcb5aafa +S062/S062R09.edf.event de55d737a8555e174e0cd004746337287c294a01d42348abe972b98f07739b4c +S062/S062R04.edf a054c47a0c59c1a375061a59144160ada314be8ad42ad7bb3971c490572c0324 +S062/S062R04.edf.event 918e61da68f21c26600383b29f33fec7665f2f3fae232e8413bc9266cc617863 +S062/S062R08.edf 0653afdbaee66604e8f9f9161e5cfbb24fda28d9dfbd48b8a343a73a544c5e91 +S062/S062R10.edf 1d1f19e928275c373dd8611a5fba6af15fca64768101ff35b443e47cc7df8b6f +S062/S062R11.edf 1b48ec4778eb975463f126ca0d2efd093978b900f6ea0275ee32ff953d6a4339 +S021/S021R02.edf cbb27fbbb61a98a9e7edd1f0aefdc5a94d964eea0ca16fe3b752aba6b38ec399 +S021/S021R05.edf.event 99a46eb7d9a4fa08a856556abfd134cec7b55f86ee94c1eedc9b0b5214911db9 +S021/S021R08.edf.event 8bbb904a2259011a3e81d620c25b30347e4e7839d6d80c3b648c53545b89f24d +S021/S021R12.edf.event f8a465b9ebddc2704252299afc352d87e33c523fa8f80ca82a96fe0b268727cd +S021/S021R03.edf.event 0a0620d55b56f9b27d4ae912d41ca29efc65875b00d662d149ff508493487b74 +S021/S021R10.edf.event 24945e04ff21b52347d9ac969d09c4af21811576baba1bfaf35d81960e94008f +S021/S021R01.edf 983781fb39c3a747051a04f23484164de485b97ba43a7fd63fd8fe3d7f6f6f3c +S021/S021R03.edf 3404a07e58a4054c33bb554133d7988bc19fa5f2dff5ed74e1669862c44869a4 +S021/S021R04.edf.event 4df88ea43362416385ab85f64107559b8c8cae7e4f9feb2b48eb9ae5bbeea3b2 +S021/S021R10.edf 6e5ea8c53bba188385f86ae619dfe3282679deba4e651ca46ee1c91c06b2c9b1 +S021/S021R07.edf 26e5c7f56d59c4e0188f7479c8af38ee973d789f26d38b80a8e421d62b542a4d +S021/S021R13.edf.event 9a1f9c37f0137ac6d7341c2a9dbef1bc161b35fcb6bd9e0db6cb95f8c7096c5b +S021/S021R06.edf 6b27c8a6782a213bc37bd0ef13c156699a8087107b6bb8893f24c526cba684c2 +S021/S021R09.edf.event 9a1f9c37f0137ac6d7341c2a9dbef1bc161b35fcb6bd9e0db6cb95f8c7096c5b +S021/S021R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S021/S021R04.edf 9481518d6a0b086d782ba17e78fe12575500ce3c7f25071f29adc5eae093c863 +S021/S021R05.edf a03d4e4f066acaac766cb935d3a40eb11886254d82e3a38a6b06714f81df9c98 +S021/S021R11.edf.event f804d1f19243344c8d8b505a1f229c8626e7f81cf4397b94650b0e6959d27437 +S021/S021R14.edf.event 30b760c52698fc58e43824eb7302010b60c8374cc35c21494035da15da835fdf +S021/S021R14.edf 76c2f56b68c08ee48dd151faf5d10d432421ecb33a938ca9b440adeed546015d +S021/S021R07.edf.event 574e54bb07934f5ad1177a8834c912e24b6537ad2eb83ff2f84b43af7024211c +S021/S021R13.edf fde2f1b885036d11a81f403bfef81cda7aad4ffd9b81cf9ff9d725cd988a38ee +S021/S021R11.edf 7b4fc08ae9e199aef5e077ae14a912c790a6d2a0fbf8565aa2c80690800aa911 +S021/S021R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S021/S021R09.edf f5b4c7deeb1c581e455c6d5d91e2d5a403233f373c0ea36f34ce3087f92cb3a3 +S021/S021R08.edf 8abd01e9b2a9c563469beac4d632727d9b341438b93aea76258ea180de2ac6e5 +S021/S021R06.edf.event 60e820216cd891875b6597a2a69eefb270be91108dd94e6c6d72fc69bff372f6 +S021/S021R12.edf 326023193bc901b74d1fcd5e7a88f064643a41842fef121fa031d9f628cbf3ea +S022/S022R04.edf.event 1513629f6e8e700394421b828869afdbd4e2ccdf8bdbed2127f75a42b2db3ff4 +S022/S022R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S022/S022R03.edf 2c7f904749e97f1acf45a98079c515ff40f15234d0463917d5f99dfd4763797e +S022/S022R03.edf.event 23fbb5b9f1007e8652ada0247eb06163f5b93eb5899bab7b719341fbeaf1345b +S022/S022R01.edf 496fc1ca74a265ea0f888b9334ac8b16168ab201dfec3eb7d932e68a5348edc5 +S022/S022R14.edf.event ac2e8337cc4fe1a692a1f25efffa62d821b6b3bb37188c793591c0d07fbac0c0 +S022/S022R06.edf 0133a61ecfdfbd3dbb8c0d678076d9f67836b6fa90c34e35369cce7d4854914a +S022/S022R05.edf e76a89c457b5deaef2fcf393d755af60c4b91fdf804ab5c97a0e461d5421f17d +S022/S022R13.edf.event e8da7819eee7d2c77d74fa9e6aec49532a6b299f30b13b3938ad7ce0357cfb02 +S022/S022R07.edf b2b28d8b0db957a13721997f5a4ccb6ebcc7bf770c7acf0fa710a08f13f1421f +S022/S022R13.edf f032660b52f6da0047f057da1a95bb03412014abc61ff1ebdbaa526e668e63ec +S022/S022R10.edf 4162c067a5d3b1bacd9614234baa0af9a75c269926de688c50227c39567ea49e +S022/S022R06.edf.event 58db360bc4c16d775b7e2c4797c2215d9f1405c25061a2237ec95b2ac264f964 +S022/S022R12.edf 46f0835897374fdc2dbc634bc4c16a61cd03a4ca25506cf923b922629b07674d +S022/S022R08.edf.event 007c6ac586d5de80642bcf571fae31808a22c5f6b8fff35fdd8f99f1b334f97b +S022/S022R08.edf 8f890909113d536152b987caff0d70c73468b0332dca478783e665598697367a +S022/S022R09.edf 735e4a3caffbbc78077baf7f0bf0d23ec707c3926e3857995b90acdc04eb8593 +S022/S022R09.edf.event aa719b9aea445a02c8c5c6a6de32bcb12238842c8d4ae16493f623bf0d226c1d +S022/S022R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S022/S022R05.edf.event 71b0870f3a5490c969240bb5653ec1eaf656e40942ab93a71deb32dbff919601 +S022/S022R07.edf.event 22a6b841d94ebe84eeaabd93fb3e0f00da65ddf3bc8de6d5a79394e3a1394567 +S022/S022R02.edf 1e302df13c28a0cf311c54b205a42155198f2c580e2d3d4e00f6ac66dd5436e1 +S022/S022R12.edf.event 93367a70cc359570029f435dd94fb546895eb7fa6c629c6678544071cd4bdc2c +S022/S022R11.edf 514f1cc57f2a93c418ed81fd3ecbb3a1cc4e4c9a3360587dcd2badb019b443b0 +S022/S022R10.edf.event 9a1f9c37f0137ac6d7341c2a9dbef1bc161b35fcb6bd9e0db6cb95f8c7096c5b +S022/S022R11.edf.event f94fa47bd56896d1b35682e2e14d8d1fdb308a058c4a48b7360c7276bb8cd922 +S022/S022R14.edf 115ee66ec70617c149079edb9a5e823b1b218a885f5a80b56f754ad745a632b0 +S022/S022R04.edf d2f48578f30b4edea2e138e74854a09e36887f8833a3e0f48cb2346ead82b201 +S011/S011R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S011/S011R04.edf 072b75496dd935be460bc8ac9c3bf2d1fdcdb62f32ffb552955319abcb24cfe9 +S011/S011R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S011/S011R07.edf ee5542027039bf28eb7fbb95826235f618e32c74b28857ad51df388256e8fda2 +S011/S011R08.edf.event 533737c87655572a20223c364be6c8be7a035cd8cf3dc42ed8c418e46e174661 +S011/S011R04.edf.event e14dc31d476c11841d45564cac660be9776fccedd3dec71dcee4c5232f00f25c +S011/S011R03.edf 369bc902a59bf9a9d480c2bad2a4b165b83716c7cba5760c2ce0e6500f120443 +S011/S011R10.edf.event fd77510c7ae392a42ed020605a40066a43ea3dcf80082d17cfd95141d71549ae +S011/S011R10.edf f3941502e7692576978f24c14c837b07e760fb94cdc65f2358790375d5537d87 +S011/S011R02.edf 3d64573c6da6183ec5b8d230e38609d4d7f365a2aecbcc8a310c94d13c986f7e +S011/S011R12.edf.event 11c7903b0dd963937962aeddd4ffb77feeec607958b581d996b712009c71f910 +S011/S011R09.edf 8e0a6cb4cfcf916fb73ca5d93839ef79131a6d76874b8307081eb03b6947c23a +S011/S011R12.edf 9034d085bc01c1c738d80a48fdc43059f88c13d587b5de1c59d4a85ecd194ccb +S011/S011R14.edf ba4007cd1ab12e9f87fb8a0d158b55e9b236cf29190db21709482290a05adbb9 +S011/S011R14.edf.event 0db4656c1041f6626ac6fd54117fb1e02890492bb86525e197e9ed116a0fe6c7 +S011/S011R05.edf e02118b61831ef02eb7268afa90ebceb136543fee310dbea1279c21bf842c285 +S011/S011R06.edf 05e960ac5207e35af7dc1fe492b78c7f473340aa88a6639a8e9d711d27c80270 +S011/S011R03.edf.event e1c00064d3aa1fb0636aaf0dedd65aa66d02a8afcf3dd70b9a5fa4df4d4ebd47 +S011/S011R11.edf 4a6c375686a70b4d0d09c789f309d8e41b76bc660d4a20f2f136fedaac2ff1a4 +S011/S011R13.edf.event 5b005cafab5d6d8968aafc95da4c7b50e36cdf3bf2d71b98cd18431017101fcf +S011/S011R01.edf 374dfa06c6df18e3bd324f4c8aefa462bacb6bf9dcbfe8d58ae6e84ed2bbc443 +S011/S011R13.edf a1a02f3cddd77bdf2eef2778bb2fe7dd76030d378d1b84850593ab3dfcb8ea3f +S011/S011R08.edf 70b05e696e9faff6566cabda58b9144e1cd8ca3b16e04178309b22ef7bb612b7 +S011/S011R11.edf.event 2553cdc46c8017dc83d793a7cce6a36ddf99a043e777612539831e67f1aebc23 +S011/S011R06.edf.event 296bafcd473fd6051b9cf19b1af83d7f0a4ba4eb310f7fbf462aa7ac3ebb8120 +S011/S011R09.edf.event f39b724630cf39de64096da55e80ef4acde232132367bdb459b9a4b872fdabb8 +S011/S011R07.edf.event c4fe35467d7d0b21a1a13fdeae18b7f036dce640d9e06acb7a946289a7fd4f44 +S011/S011R05.edf.event 017d78426c2e9f2b1807cc35ed07405ab8ff157014df0701b8524f965539b319 +S082/S082R07.edf 2e76d2510e31a569d934e5e0c79d80ad5d5b717210edfef603da9ed469a0ebe0 +S082/S082R04.edf b3e4c74b4cbbf1aaec1af0c3613fc9d2a27d6d96ac62c7907551a87fa9bf0bbd +S082/S082R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S082/S082R10.edf.event 732398d864936092994f6aa5c7a3d554d1c1c35ff4fd7a90dd0c06a61260c68b +S082/S082R06.edf 1fc2e82fe3d7cac5dc6d1b36f7e427f82dd881d8795e7c1ffaaad4309df741f5 +S082/S082R02.edf 5a60133110089cd88b358a949f2e1d584fa14f90ff4c4016554f4e3a827aed5c +S082/S082R13.edf.event c117ba4c66b5467903fddc4ed77a580e09639381683c611dd1f02cb0d311a4b5 +S082/S082R05.edf 9e318d00b9ab3f34936e0f1a63e36996213b48e72b6cef4e22f3835c58411853 +S082/S082R12.edf.event f45bf8e0fbc90d9616344960adaf0ce8357cfa7171b36030a957f85c93267870 +S082/S082R12.edf a389f918554ba206ee4330deaafe1e21750fb44317401628841ee6e2e9b83a8a +S082/S082R03.edf.event 8612fac39dad16048db3bea4e27be45fe67ced9a22781462eb9c6e435fe28d6d +S082/S082R04.edf.event 23b6fc268df2ca2b48b0a505a6eed055a62dad293041c180f6f03136d0f4b36e +S082/S082R05.edf.event af9bed6667136366cf88d2cd7f0f5fd9dda3fa51cc4cf73d3afe4d57dc8b7502 +S082/S082R11.edf 7b7a5f1608517ddeed1dc7e4e349c346f90ef9d1aaabddce3dde87b65efe2120 +S082/S082R01.edf c36d3ce061cef168595ebbf3995891c60fcefa82dc1534f6dbc4fc6312d09ebe +S082/S082R11.edf.event 61878a566785fc86672b3e061fc0eefd0fb9735a4239d8f13ceb0d08ff22f60d +S082/S082R06.edf.event ffbdc0e528335775cb88a14baab7b7f1fff4fa1647a473bcd640feefcbfab5a3 +S082/S082R03.edf 1df043bd8c67a867ffafc493d40cc183b9c15f46b4a45609b27b386a6b056280 +S082/S082R13.edf 4d97f79b10606441620868d7fab83054e1a3961fc2e056f6082f75f636be17a5 +S082/S082R10.edf c7fc55b18d9be4cdc9faa3b16cfb2814139a7d3c8264e9cdb2b6a5ded49298d2 +S082/S082R14.edf 09c317d8cc56eb914443ad400d1167b60c10ab73766894ddf2934223e30e4aee +S082/S082R07.edf.event f45bf8e0fbc90d9616344960adaf0ce8357cfa7171b36030a957f85c93267870 +S082/S082R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S082/S082R09.edf ba6d90669cf26f7346353afa0fd1a496ae333c8f72a5b4d7b35d0da5607b8cb9 +S082/S082R08.edf.event 00eb5e22d01c3eaeb1626660a99e0c6fbf2f4423eed750224cc549752b7b6761 +S082/S082R08.edf 47ba5b30c2427a7dd4117f26ac5491a0bdf9a2e5a619bfc418ee59b3941042c9 +S082/S082R14.edf.event 6e13e4f708f4b769dde500a1db747206aa87951c3914cdd436fb7f07e9aa5052 +S082/S082R09.edf.event af55de06274e9f057a8c2b10bb8a4665c70ab950b43d066ea9e3d1de5f188b79 +S087/S087R11.edf.event 029131148bb6c782573739be6ec79dc67ade89f0b101169912d9c8201871bcd0 +S087/S087R04.edf.event a38580800381d773ef251e941cbd4e02611c4c4e4efab3c383f14300a3394f1e +S087/S087R10.edf 83d8cc5669b446e85209bc1d3cbcfdd915dbbb910634d096122ef2581b2e3d6f +S087/S087R14.edf.event f45bf8e0fbc90d9616344960adaf0ce8357cfa7171b36030a957f85c93267870 +S087/S087R11.edf ef3af1f11e1c90c305bb5caaa47d3ca98076a3b47378c1a81b6a85b3f2eec5ef +S087/S087R02.edf 869950862ef4df60bc0a4dde3316a8db3780262e29e65a1fd4d98ab20c9859f4 +S087/S087R13.edf.event 7f2596bafc4dd481e36c47d0e562fb6c5f9b7e91c2a915f19f66844b55b75410 +S087/S087R01.edf 5876a24fa07f5580ee8df69f00a069aeeeea2a22e08f3c6ba3678a3978f4a73a +S087/S087R05.edf 9acd4c1585c623ccf52ca1d8c5793168a6d736c528af283fb68116c415cecb48 +S087/S087R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S087/S087R07.edf.event 7ee6977e5ff9c282ca6370406d7a9871d162328940b104573ac9f1d5151c4b96 +S087/S087R08.edf.event d0677488ead680ce24ed6d8a77105b8da3f0bd8cad38fff43732482c17bc4510 +S087/S087R09.edf 6797f700e9a9b26efa58d863349724bf7cb330f62d3653e5f87a6e8a2a9d22b8 +S087/S087R03.edf.event 0724cecedb70811bcaf06ec5a41151edaf5209f968315c4da2e3a25bbf0fb9ec +S087/S087R06.edf.event 8612fac39dad16048db3bea4e27be45fe67ced9a22781462eb9c6e435fe28d6d +S087/S087R05.edf.event b0dc1155da666ef5240efa8026cec5f4f69b5fb6f1d21226a512de3f6b62002d +S087/S087R14.edf 203089c991c61a6701bfbb1e413bbd0bbb5e0a103179852422eab0640e232a14 +S087/S087R12.edf 1fc744ced6882cc083447d4228f2868ad8cd3708506491adaf6b949e1e1aefc8 +S087/S087R12.edf.event a716ed693834141bb2b56720ce6124df46e42e86652ec02bc96746644a79378e +S087/S087R04.edf 4f1599825e6aae94add2c0ebcf8bcb23a65bed258cfb89a73a06a6861fc586c3 +S087/S087R13.edf e07def80de0aad137aeb40c1ec6cc9fe1affb9e53fba10ea09a721ddbdec630f +S087/S087R06.edf bce28b9526a4dfbc28502e3b2d2586a133900fa946ae1b2d7e19752a23d08ebe +S087/S087R08.edf 58ec622ce0deaebeb43334c3f255e81b01e612751cb0b13d2471b2ce98fb67bb +S087/S087R07.edf 70be34572544b1dbb96739d53b694fd0d983a91810f9e05addf1eced8b013b3d +S087/S087R10.edf.event 0d4308120129d0f92d2b8779374ae232f98d1357e6c6427983fed655d9611af0 +S087/S087R03.edf dc60f233daf4d2a62453582210f0186514e02e4d3967af1ef8881361cc55da5b +S087/S087R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S087/S087R09.edf.event 8553d29b6f3410b4ee7ebd3f65050ee16a492ed893d0bc9a14cf35cfa904d586 +S014/S014R06.edf.event efd977506cc195b985e542f3333bc334c4793652f9b52580c96ef8a5948f4db9 +S014/S014R07.edf.event de55d737a8555e174e0cd004746337287c294a01d42348abe972b98f07739b4c +S014/S014R02.edf 6294928380c0ad63219a2713b9f5488d570be1c0f1da72662668c1b4f5bc906d +S014/S014R13.edf.event e8abea1fb06a5ad73e91ea5c97aa84247e1c165ee2bc724e9b9c7ae6f6c017cc +S014/S014R13.edf 28ef92f5bad0bcfabde422238a74fc13e58b9e31882cd9c4ea421f806a923af9 +S014/S014R10.edf c0fdc474a78421cc6048a9c8dfc8cafa8424dd4379135b60d68a77c4ee0b2b6a +S014/S014R10.edf.event 8e9579e89d1ec6576609e05f5e6215b4322a4c5375265379e3acd7952866ac83 +S014/S014R09.edf.event b1046f2c937e8d05f2c3e45473ca880864a5d33222d740a0bee41b055662ea91 +S014/S014R01.edf 9ff971d9225e764428182bf4833ce5a60e620b7b157df9798ea6266070442433 +S014/S014R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S014/S014R03.edf.event c4fe35467d7d0b21a1a13fdeae18b7f036dce640d9e06acb7a946289a7fd4f44 +S014/S014R09.edf 3214586a275de7cfaaa94b5b6ff39c4f8fdaf04ecb3adfddde30ae5327d5e8b8 +S014/S014R05.edf b675b2ff333e7661944d6f37edf44d0c104c0fe9d6c04661c96885fbc0c2edfa +S014/S014R11.edf.event 11c7903b0dd963937962aeddd4ffb77feeec607958b581d996b712009c71f910 +S014/S014R04.edf.event 07fe70f3f8a3bdbc31f5b573f0a7411d64d34385995e5b88892dc178ef898e16 +S014/S014R06.edf 2effc21654d198aa9b98432717d66111358ee5795b929bb4c433d5d9ab066e97 +S014/S014R14.edf.event a376b452fa5f7c300d71ec31ce58f97920510a057f4ca6c506f4cef51faa7315 +S014/S014R12.edf e6ef184a364734f2cc0fce314c93ffa545660a89567475f56ddd979a2d0fbc39 +S014/S014R07.edf 4fc8a7f723e8577d5f0a851ee416ccdd7511aed74ae3da6bcc4bd19a2dda0d1c +S014/S014R11.edf d1d6a99dc4439690c820469616b6bc71d80be65340615246741c0d67efde59c4 +S014/S014R04.edf 7e443b4a4bb000506137ffd79eae9fd915a282f4c6c5aac71ad8b8612072227d +S014/S014R03.edf 670c197481bd1761f1393c3f33e7c286f5966f483493cb6d2e05ff23de93c6a9 +S014/S014R08.edf a63bc896da7b0fa302c3c3b0ad53a4c54f1a35fd1f66bebb2cedc81cbabc9320 +S014/S014R08.edf.event a730605f9838282a7ec09530538d4f4dc6f2f5cf73c8f2e85944d5e8297c441e +S014/S014R14.edf dc0139288de0668975cfde05cce9663a186ba1b2ccb3fce71fbd4bbbb206b5ba +S014/S014R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S014/S014R12.edf.event a38580800381d773ef251e941cbd4e02611c4c4e4efab3c383f14300a3394f1e +S014/S014R05.edf.event a5608231854f8f457c107c9acdfead912cd6d55fc459b7abc2f11d77bb166129 +S075/S075R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S075/S075R12.edf.event 818acb17a86d3ee6425a512fab58b363d01b6ccc783417cdad466d1ecddc506f +S075/S075R05.edf.event aaa5cf263ed5e1e7bf38b3d540f4e2d286107c553f7904af5c9cee9bfe715f19 +S075/S075R02.edf 712ea0f0fd69d3b108cde439012068e81b4cae645d170a93d52c1ead4dd45877 +S075/S075R10.edf.event 8553d29b6f3410b4ee7ebd3f65050ee16a492ed893d0bc9a14cf35cfa904d586 +S075/S075R08.edf 12c3c5d354210080fff50cd4bb475cf89df420c18b0a1e675dee817a79b380ba +S075/S075R10.edf 5d683e7fcc9f0d168f8ba02b226ba4bfe0b00bd26216310522e24c139ef71314 +S075/S075R11.edf 8d55cffc5f065f1de6c5007d2f42393f0f4fa2d40a01de17060d03cd515d3b23 +S075/S075R04.edf.event fd77510c7ae392a42ed020605a40066a43ea3dcf80082d17cfd95141d71549ae +S075/S075R14.edf 4805ec2a2ecefc95562a0f2178e2fd3aba647559674d13fd5c46a2f2dc27ef8e +S075/S075R06.edf b07163bf94520e29c548541fd33ab783ae9953009f4357e6aa57dd6f1d81af88 +S075/S075R03.edf.event 3764472ec04047763aeff3c1680cbc45cec3a88ed5f483d80cfbb31b50a12ac9 +S075/S075R07.edf.event f338197f5dd0ca078ea8eee22145e57e694f7dce6a2bbd55f5f05346ce3b3f17 +S075/S075R12.edf 6c33faf3fad9d274e8e7718c6dc2df6e8d54e5478638684530b7f854961b0eec +S075/S075R03.edf 3c7d10331971c041abdc9fc02041ab2c80384e3b84ff3f58d9d54c7572590ca1 +S075/S075R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S075/S075R09.edf.event 61878a566785fc86672b3e061fc0eefd0fb9735a4239d8f13ceb0d08ff22f60d +S075/S075R01.edf 79c65d9990c6606d45d9c3be18ae7226cc97e4757955fd8675f313ff8f91b238 +S075/S075R14.edf.event 8cd8c690df55a4167dd5e136be1c424a77655375599a9d3350d5460cabab539d +S075/S075R04.edf 87714f913602a939c24e3ce672a689ce20f966c5d19d5f699f898a94cca4c086 +S075/S075R08.edf.event dea45ba8a8662cd82aeb9d6c523756ce7079f3020c2ad1b23d6dca2f63b5bf82 +S075/S075R11.edf.event 596ad948f8aa9dfdc6cd3125a3d02e115d1cd6a505023467bf5cd721125ee7fb +S075/S075R13.edf 10e9456acf73b9c355684b37aaf102a2d78389c47fdf0c026c39a32e08c95c71 +S075/S075R07.edf d933c3ead467e6c662fc45bdba943f20177079470d1d06ac4cdc989d6dfadf5a +S075/S075R06.edf.event 734d5da22686d9f9052ce819f7fba86e4f5225f2d3638eb1e3795e9ebd018fe1 +S075/S075R13.edf.event 83ec130ac6a664e0d88923e1496dc0806008967b51e6158521a6beb0515b2eb8 +S075/S075R09.edf b17c615c3a63e91e8e26a4b9299c1c5bcc022c2d50932520a382c713e8f1f708 +S075/S075R05.edf aa220a279d288581e32dcb10fd8e44688aacf89de7f0dece4765f0b3c40a4229 +S010/S010R09.edf 91bcc4d9068115e0d022a6a9ebb1fe05cfcba27cc1bf025beb8a3eebb72b0e7c +S010/S010R09.edf.event a788bd6a825d960534053c6559cb4f24cb7ee7a3164017d99c1dbc55f3b22215 +S010/S010R08.edf b468e77d0c8a73377b4510220c6be95bdefd572f6ed5c4b5f539c9dc0bdef485 +S010/S010R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S010/S010R12.edf.event 820bcb0b8aa75c06572fb3677af8b965e06ca92c0ff5f4eabd0d347c7b141680 +S010/S010R06.edf 5f5c213f1f7db4bdb52d8d54e8074d7f5e73655b1e040d41a7916d3d0a00b666 +S010/S010R14.edf 138893d950405102e1536365290ac15255688eaab181170afbd5178e6714ae2e +S010/S010R14.edf.event 99dc24a5732bc2857f1d3fba3d1a5b942b288ef56950e45354e03fb10183bbe6 +S010/S010R13.edf.event 212052daaa4c0fbc66f91923236861d93fc52f73403f6b4d988205287f1f9ece +S010/S010R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S010/S010R10.edf.event 8a4b5822b251050d46b816bf54fbb47530d91210b6d01cc2e6acbe662193553d +S010/S010R07.edf.event e11c72f75777baaef94ad75881c37d283df8f4f917ca8c1c823cece56a31f215 +S010/S010R05.edf.event 50f12f26efafddcd994732349e4117055595d324e4dcff8fa56160baad5d5533 +S010/S010R13.edf 10e642cfacf5d55a4a90b73f8968e2dc4da6db4b8458388d87641c21e1e00c6a +S010/S010R06.edf.event f39e6f6c43f557d6a85493c1722b39ca7055c4ba399525941217678a10b78568 +S010/S010R03.edf.event 296bafcd473fd6051b9cf19b1af83d7f0a4ba4eb310f7fbf462aa7ac3ebb8120 +S010/S010R01.edf 0d694b503e5ea0f6088a790f09390efb1be2688ad92213f5e82fa2f343cd18c4 +S010/S010R03.edf 49016ed40a1c17164b7b56031d567ee96b00b0b3755fab072c1d78db9ccdab73 +S010/S010R11.edf 4e8a3c50558c9dce96ab060d4883d19fbfe5e859989d7c633bf9f88a6a65d467 +S010/S010R12.edf 0983609a12e6fd9b3ae99fd6968938ec5a3b012948894602233a65b720ac3975 +S010/S010R04.edf 8e68b22936cbcb7f84ed8ff037cb4a99f01064589d181c8056dbef06c1c7159b +S010/S010R02.edf d44f5f6c774771bc2b6cdd6d29c7f558e11ad11e6198cf4603f473edd4b2074a +S010/S010R05.edf e83d0bcd64dc403e430be79f865e92576b62d42ebbc07583fb1bd964238127bc +S010/S010R04.edf.event 3e275ced710e3ac50d345aab942c9fb009e11f5447566d67dfaa0345a0d96840 +S010/S010R10.edf 693b0d9240095c01eb8ec5b2d0b3887cfbb8fbfeb85a04076b79c297b5b7d42c +S010/S010R11.edf.event 710672ce0f425a207ef543d23f608683e1863d7423702d511235d71ccbd289cf +S010/S010R08.edf.event 0028edf9b5fcc76311706f809ca44f884f227acaa02c56031cf87a7937c1d9a5 +S010/S010R07.edf cf59750f6f9576e106875f257673940cbaf2b0d62e1d3b1a45260dbc46c1981b +S074/S074R02.edf 0135aacd143f05dcde96a748fb925d60823187e0b4a910051d81c91a85b72bed +S074/S074R14.edf.event 046534c84c8b0ff5bc1e42577bfd07477507c70bf5fa72787065271450df27e8 +S074/S074R07.edf d51407f00e5f51714f155025b59165e1629a6f77e1205f0f693917400489198a +S074/S074R12.edf.event ef90708131efeff70f834269381bdac1901f295f238b806a3e7faa6295beae60 +S074/S074R04.edf ea84e05235eb45067eb84f19aa09c4c5d429af1e9d865ee5eae1b2aaab46a081 +S074/S074R05.edf.event c2cda6658840270926f0e5923526e91f0b5c3b025e5e480e8128411d202279f7 +S074/S074R04.edf.event 41a37ed42798630028522e1dddfb80e81b973b74f6159b9cfbb856b13dd30d4b +S074/S074R12.edf f6ea6103b34721b8d2d8e1175d305491303cf5f028879791f14443da810d1c7a +S074/S074R06.edf.event 5bbce0aecf4877ae15055ab9b31e4f2c644ddde0790031ab0902e5c6d913e97d +S074/S074R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S074/S074R01.edf 5a9fed173c09eb34df7bfb6e79d6c15b616f2cf95c65bbed6b7b392acfa2ac3a +S074/S074R05.edf 10c0b403ec5d30a1bfdd118218814ad6a3ab807ba2f25c767aea3374b71de285 +S074/S074R13.edf.event 21d57c80128ab83ad495fc6a3f948d954b23ed08be42eabdf2d058a81fa1ebeb +S074/S074R07.edf.event 33d88435be58ca0eaa6dbf2eedec24ab55aec24d6e067979c6aa5f2549ce02bc +S074/S074R08.edf e594ad62e81f3948d52e1bf5b896598543e4c739e06df596160dd379af59b99f +S074/S074R14.edf a6b678a0c9f505a58fe9b6c769276a84a4785743a3866529febf5f489e41d6d9 +S074/S074R11.edf c7ab21c448f8059e8674b21f9bdd96311c83086c6a7faf95aec5d75c319bc01b +S074/S074R11.edf.event e6e3fae8bbcbc00e9d7d959eb1e3c2c0ab93eb9e896a0adc93c685329e429982 +S074/S074R09.edf e8d8787476b0bf24a5caa9fbc450296cc86bb92fbf25c22dfde96f893bf20c4d +S074/S074R03.edf b93be723755be84e63dd7ad2a09e396392d71a4a6c156b085a7577a1ff6fce9d +S074/S074R09.edf.event 413f7dd132c171c2c14d9a7cdebe9c5e6ea047f267c8e9fbd8669a3ad0fda05b +S074/S074R08.edf.event 6a98c81dedf4cfc225c5d5260ce569ed2e2c48b1be5698ab3cba2089b491e545 +S074/S074R03.edf.event 0c18fa49d469703f30b80a748450ef0688aa72103e201d690fb064dd55c7e540 +S074/S074R10.edf 25261ebba19c4f04b7fe9597287a49a97e91268941c9fd3609ec0a7f53fcd5e6 +S074/S074R13.edf a2816222018a1b9b734f200ea774b9e43371a8c835c729649955ec1b6ad2335b +S074/S074R10.edf.event 772fcde48d228db4376dd7486ad68145a7a40f0180612741f47a1886d5be50f4 +S074/S074R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S074/S074R06.edf c7213e39ce5e307c6619762169d0c07823db7fade9cd2eaa6696fa0ac658c008 +S059/S059R05.edf 80b7c06b3187db15ae83e290d7f82af308e44dcdcb6eef1a0162ec2d9760ad4c +S059/S059R04.edf 904e79d95c362eab86e46e0a1addbe3b80ba802b98b372c63b8872537fcd9bbe +S059/S059R05.edf.event d0677488ead680ce24ed6d8a77105b8da3f0bd8cad38fff43732482c17bc4510 +S059/S059R03.edf ceeae042f3be7a4d705c8b13b507e58d901cdb5e7bd4e367b571f85fe5fb6070 +S059/S059R13.edf 72f0530ffb191f575b29f72964e51fa108ae57f495db19dc11de1e7f3c35262f +S059/S059R09.edf 10491ecfa52bcc63056974652c8931ea19a0adb0d3ed331a1a4d58e5bdedb849 +S059/S059R07.edf d425bba7b0f3019f725f3b43c2a63d703b3524f177b6341beaefc1d479c9561b +S059/S059R09.edf.event feeb9bf47f8f6dd0e083c64236055fd7ca30a06709747978b6a7bbc0b632e21c +S059/S059R13.edf.event d6641564c0a8724abac8f919ad99064213b0fafe2c25f0d37d1cc67d83bda19c +S059/S059R06.edf c7ccb0ab2969a4f1d5c522e66299c08d8db2c39c9ad977a9be7613132b4bb46d +S059/S059R08.edf.event e1ad9bc40c1368a9f08ea6dd90c3750fa2947ff48bcebe59b7e89441a2db68b8 +S059/S059R02.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S059/S059R10.edf 20becd179b2aff43d00c5c5a11faf39a820cb59c8d43f2668d9458dddda9ddd8 +S059/S059R06.edf.event 23b6fc268df2ca2b48b0a505a6eed055a62dad293041c180f6f03136d0f4b36e +S059/S059R01.edf b8b6001fbd9853ab9cf3cc7dc2c40fe0547fd8904044d4bb5b654a083d6f1584 +S059/S059R14.edf.event ea6f6003ddc3676cda270c185ba40fd7915630a24511085aeb31217c9a1e8852 +S059/S059R02.edf 0135175166b23559b8ff05f4e3a4fa0ba0fa24a65b411e0bc1e20dfda9d89074 +S059/S059R01.edf.event 98cfbe863896ed90aa76ff95ad4151ed3b02157854cfa6a974121fc123c109c0 +S059/S059R10.edf.event 927b59b2e19d89df8169362057a329c5b70fd65d1d2d0a77e56546927bc02281 +S059/S059R11.edf 6841c44bb69451d341157e05f64d00cc51ddc1d9076bf6903c5aaaff5aeed129 +S059/S059R08.edf 9c96400ddc6cddc13df50bc49a564365e8f3e24fd9fac3b6fa494cb939c9c627 +S059/S059R03.edf.event 60cee9d6dd15c5919b0d3d4f0618922c82d19e6490ea88b6fcd09fc7631fac71 +S059/S059R12.edf ed9b66b031f545783a98ccc77915ee74b1f9b0471a6edb601408b63b7320121f +S059/S059R12.edf.event aaa5cf263ed5e1e7bf38b3d540f4e2d286107c553f7904af5c9cee9bfe715f19 +S059/S059R07.edf.event 037c923028aca24716dbc8d307c618e19d4e94bb1e759e5ddb8a9d3b6b205a86 +S059/S059R11.edf.event b9568e8466c8f90e1fe1f9aab8ddb73ea16c008b7b67cbbe5863f04f2ec408f0 +S059/S059R14.edf 341c60903abc18408b921bef74bfaa5dbed75d886f13c55b25090afa23690c16 +S059/S059R04.edf.event 950cf97301dd495a2a6a7a19a93d67d2ee9ee03b2675e300582e19305f5a9287 \ No newline at end of file diff --git a/mne-python/source/mne/data/extinction_coef.mat b/mne-python/source/mne/data/extinction_coef.mat new file mode 100644 index 0000000000000000000000000000000000000000..0ea91c90d0f3f5638d7541ab3bf37d212208e651 Binary files /dev/null and b/mne-python/source/mne/data/extinction_coef.mat differ diff --git a/mne-python/source/mne/data/fsaverage/fsaverage-fiducials.fif b/mne-python/source/mne/data/fsaverage/fsaverage-fiducials.fif new file mode 100644 index 0000000000000000000000000000000000000000..faaae97671cf8db36527d262fdddcc7f9d935260 Binary files /dev/null and b/mne-python/source/mne/data/fsaverage/fsaverage-fiducials.fif differ diff --git a/mne-python/source/mne/data/fsaverage/fsaverage-head.fif b/mne-python/source/mne/data/fsaverage/fsaverage-head.fif new file mode 100644 index 0000000000000000000000000000000000000000..b66d16a8a16afa6eb0f99882801024cc16e03e7c Binary files /dev/null and b/mne-python/source/mne/data/fsaverage/fsaverage-head.fif differ diff --git a/mne-python/source/mne/data/fsaverage/fsaverage-inner_skull-bem.fif b/mne-python/source/mne/data/fsaverage/fsaverage-inner_skull-bem.fif new file mode 100644 index 0000000000000000000000000000000000000000..394db6ee4aa6530c80bba6d82adaa0e2f30cc0cf --- /dev/null +++ b/mne-python/source/mne/data/fsaverage/fsaverage-inner_skull-bem.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7f9aebfa69248349fb472a863f34bb77b018f1d1330c02262aa2e16774b10f1b +size 491944 diff --git a/mne-python/source/mne/data/fsaverage/fsaverage-trans.fif b/mne-python/source/mne/data/fsaverage/fsaverage-trans.fif new file mode 100644 index 0000000000000000000000000000000000000000..92b55734b1ca90b5712fca8a769c2aa18d8450e5 Binary files /dev/null and b/mne-python/source/mne/data/fsaverage/fsaverage-trans.fif differ diff --git a/mne-python/source/mne/data/helmets/122m.fif.gz b/mne-python/source/mne/data/helmets/122m.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..dd4c34e37e09ff8fcf6bdbbadab4270a26881a54 --- /dev/null +++ b/mne-python/source/mne/data/helmets/122m.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a4d04347cd4a21a84b49bd4f6ab238e878999ada71a5ec586494487ac70ab039 +size 4706 diff --git a/mne-python/source/mne/data/helmets/306m.fif.gz b/mne-python/source/mne/data/helmets/306m.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..90fa90d8bc3899e5421f05759a574f2dc2e0f610 --- /dev/null +++ b/mne-python/source/mne/data/helmets/306m.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:25447e6957007938685d1da780ac0100e1d493a9d255da508996ceb9a5455664 +size 9462 diff --git a/mne-python/source/mne/data/helmets/306m_rt.fif.gz b/mne-python/source/mne/data/helmets/306m_rt.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..eb644287db20cf6671bdf1a4801bab4d30d83943 --- /dev/null +++ b/mne-python/source/mne/data/helmets/306m_rt.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72ff8dba188094020a7c5c88bd0b9db8c39cb68a43f9a7cce398b29520d224fe +size 9443 diff --git a/mne-python/source/mne/data/helmets/BabySQUID.fif.gz b/mne-python/source/mne/data/helmets/BabySQUID.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..bff7c4878ebde5815a10c5dad51fed7a0d18dd2f --- /dev/null +++ b/mne-python/source/mne/data/helmets/BabySQUID.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:54aff561cf0b76247699d745ca9fc7c14e5d9b1b809d74ee67e8f78e8e87ffc2 +size 59505 diff --git a/mne-python/source/mne/data/helmets/CTF_275.fif.gz b/mne-python/source/mne/data/helmets/CTF_275.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..557857ff44eb9100b4ae1bcdedeaacc44316c713 --- /dev/null +++ b/mne-python/source/mne/data/helmets/CTF_275.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7803e232484ecdd1e2f50d17bd64fac9458cf126334345dc9e15b459490b46b9 +size 11157 diff --git a/mne-python/source/mne/data/helmets/KIT.fif.gz b/mne-python/source/mne/data/helmets/KIT.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..59e06cebb8bb3156657c46666a606a23a68407b9 --- /dev/null +++ b/mne-python/source/mne/data/helmets/KIT.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fc94553503d51216502ac872c2561717274a908f1d9c71adf48f827b84e75bad +size 9477 diff --git a/mne-python/source/mne/data/helmets/Kernel_Flux.fif.gz b/mne-python/source/mne/data/helmets/Kernel_Flux.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..1e0f6ec97da17b043a21946537d1cf03980e5fa0 --- /dev/null +++ b/mne-python/source/mne/data/helmets/Kernel_Flux.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ca5e7bea421a8b0c1f7f12ebfad0784431bbba8c07dd6030d0c3a51f858768e +size 493001 diff --git a/mne-python/source/mne/data/helmets/Kernel_Flux_ch_pos.txt b/mne-python/source/mne/data/helmets/Kernel_Flux_ch_pos.txt new file mode 100644 index 0000000000000000000000000000000000000000..8f9807c9e03a9b63b0ba62fa338ecf937173a455 --- /dev/null +++ b/mne-python/source/mne/data/helmets/Kernel_Flux_ch_pos.txt @@ -0,0 +1,202 @@ +{ + "MA1": [ + -0.040249, + 0.092195, + 0.024061 + ], + "MA2": [ + 0.0, + 0.10462, + 0.016906 + ], + "MA3": [ + 0.040249, + 0.092195, + 0.024061 + ], + "MA4": [ + 0.0, + 0.083089, + 0.053953 + ], + "MB1": [ + -0.040251, + 0.063041, + 0.05933 + ], + "MB2": [ + 0.0, + 0.045194, + 0.077115 + ], + "MB3": [ + 0.040251, + 0.063041, + 0.05933 + ], + "MB4": [ + -0.036861, + 0.026016, + 0.076163 + ], + "MB5": [ + 0.036861, + 0.026016, + 0.076163 + ], + "MC1": [ + -0.035716, + -0.017727, + 0.077709 + ], + "MC2": [ + 0.0, + 0.00196, + 0.085517 + ], + "MC3": [ + 0.035716, + -0.017727, + 0.077709 + ], + "MC4": [ + -0.034502, + -0.056871, + 0.064752 + ], + "MC5": [ + 0.0, + -0.037943, + 0.080668 + ], + "MC6": [ + 0.034502, + -0.056871, + 0.064752 + ], + "MD1": [ + -0.036596, + -0.084035, + 0.027244 + ], + "MD2": [ + 0, + -0.082423, + 0.048749 + ], + "MD3": [ + 0.036596, + -0.084035, + 0.027244 + ], + "MD4": [ + 0, + -0.095211, + 0.008834 + ], + "ME1": [ + -0.038329, + -0.084588, + -0.017313 + ], + "ME2": [ + 0.0, + -0.086368, + -0.035705 + ], + "ME3": [ + 0.038329, + -0.084588, + -0.017313 + ], + "ME4": [ + -0.028545, + -0.071814, + -0.06008 + ], + "ME5": [ + 0.028545, + -0.071814, + -0.06008 + ], + "RA1": [ + 0.06916, + 0.059735, + 0.008274 + ], + "RA2": [ + 0.070053, + 0.032925, + 0.039006 + ], + "RB1": [ + 0.069394, + -0.009905, + 0.045791 + ], + "RB2": [ + 0.06596, + -0.048253, + 0.029541 + ], + "RC1": [ + 0.07757, + 0.023536, + -0.014638 + ], + "RC2": [ + 0.077612, + -0.013307, + 0.002181 + ], + "RC3": [ + 0.068927, + -0.049354, + -0.013998 + ], + "RC4": [ + 0.06444, + -0.040455, + -0.053382 + ], + "LA1": [ + -0.06916, + 0.059735, + 0.008274 + ], + "LA2": [ + -0.070053, + 0.032925, + 0.039006 + ], + "LB1": [ + -0.069394, + -0.009905, + 0.045791 + ], + "LB2": [ + -0.06596, + -0.048253, + 0.029541 + ], + "LC1": [ + -0.07757, + 0.023536, + -0.014638 + ], + "LC2": [ + -0.077612, + -0.013307, + 0.002181 + ], + "LC3": [ + -0.068927, + -0.049354, + -0.013998 + ], + "LC4": [ + -0.06444, + -0.040455, + -0.053382 + ] +} \ No newline at end of file diff --git a/mne-python/source/mne/data/helmets/Magnes_2500wh.fif.gz b/mne-python/source/mne/data/helmets/Magnes_2500wh.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..f0411e2c1fdc95da710e7ad0b0ec53abda508f8c --- /dev/null +++ b/mne-python/source/mne/data/helmets/Magnes_2500wh.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e936a1354396aa699d6f508eee4165653a27b5a058ce3c5122b7133932b1a82f +size 9470 diff --git a/mne-python/source/mne/data/helmets/Magnes_3600wh.fif.gz b/mne-python/source/mne/data/helmets/Magnes_3600wh.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..6745f659a2e42fa4e11c72aef83aaecae01ee34c --- /dev/null +++ b/mne-python/source/mne/data/helmets/Magnes_3600wh.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:87b5844e2c9ba161f875bc553ba09d55a8e174d95294a32249d53432939a5ba9 +size 9475 diff --git a/mne-python/source/mne/data/icos.fif.gz b/mne-python/source/mne/data/icos.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..d8faf28669ebd7e7c02940541d5bc6b0db4e748b --- /dev/null +++ b/mne-python/source/mne/data/icos.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2428e29845dc6ed5c48ed301ac6e9bf52f19b3ed1c4c611edb7e25cddc7e1c25 +size 3732551 diff --git a/mne-python/source/mne/data/mne_analyze.sel b/mne-python/source/mne/data/mne_analyze.sel new file mode 100644 index 0000000000000000000000000000000000000000..ae4bf34f898f4aea14c5a0e51cf69e6c2dc25b27 --- /dev/null +++ b/mne-python/source/mne/data/mne_analyze.sel @@ -0,0 +1,19 @@ +# +# All channels +# +Vertex:MEG 0633|MEG 0632|MEG 0423|MEG 0422|MEG 0712|MEG 0713|MEG 0433|MEG 0432|MEG 0742|MEG 0743|MEG 1822|MEG 1823|MEG 1043|MEG 1042|MEG 1112|MEG 1113|MEG 0722|MEG 0723|MEG 1142|MEG 1143|MEG 0732|MEG 0733|MEG 2212|MEG 2213|MEG 0631|MEG 0431|MEG 0711|MEG 0431|MEG 0741|MEG 1821|MEG 1041|MEG 1111|MEG 0721|MEG 1141|MEG 0731|MEG 2211 +Left-temporal:MEG 0223|MEG 0222|MEG 0212|MEG 0213|MEG 0133|MEG 0132|MEG 0112|MEG 0113|MEG 0233|MEG 0232|MEG 0243|MEG 0242|MEG 1512|MEG 1513|MEG 0143|MEG 0142|MEG 1623|MEG 1622|MEG 1613|MEG 1612|MEG 1523|MEG 1522|MEG 1543|MEG 1542|MEG 1533|MEG 1532|MEG 0221|MEG 0211|MEG 0131|MEG 0111|MEG 0231|MEG 0241|MEG 1511|MEG 0141|MEG 1621|MEG 1611|MEG 1521|MEG 1541|MEG 1531 +Right-temporal:MEG 1312|MEG 1313|MEG 1323|MEG 1322|MEG 1442|MEG 1443|MEG 1423|MEG 1422|MEG 1342|MEG 1343|MEG 1333|MEG 1332|MEG 2612|MEG 2613|MEG 1433|MEG 1432|MEG 2413|MEG 2412|MEG 2422|MEG 2423|MEG 2642|MEG 2643|MEG 2623|MEG 2622|MEG 2633|MEG 2632|MEG 1311|MEG 1321|MEG 1441|MEG 1421|MEG 1341|MEG 1331|MEG 2611|MEG 1431|MEG 2411|MEG 2421|MEG 2641|MEG 2621|MEG 2631 +Left-parietal:MEG 0633|MEG 0632|MEG 0423|MEG 0422|MEG 0412|MEG 0413|MEG 0712|MEG 0713|MEG 0433|MEG 0432|MEG 0442|MEG 0443|MEG 0742|MEG 0743|MEG 1822|MEG 1823|MEG 1813|MEG 1812|MEG 1832|MEG 1833|MEG 1843|MEG 1842|MEG 1632|MEG 1633|MEG 2013|MEG 2012|MEG 0631|MEG 0421|MEG 0411|MEG 0711|MEG 0431|MEG 0441|MEG 0741|MEG 1821|MEG 1811|MEG 1831|MEG 1841|MEG 1631|MEG 2011 +Right-parietal:MEG 1043|MEG 1042|MEG 1112|MEG 1113|MEG 1123|MEG 1122|MEG 0722|MEG 0723|MEG 1142|MEG 1143|MEG 1133|MEG 1132|MEG 0732|MEG 0733|MEG 2212|MEG 2213|MEG 2223|MEG 2222|MEG 2242|MEG 2243|MEG 2232|MEG 2233|MEG 2442|MEG 2443|MEG 2023|MEG 2022|MEG 1041|MEG 1111|MEG 1121|MEG 0721|MEG 1141|MEG 1131|MEG 0731|MEG 2211|MEG 2221|MEG 2241|MEG 2231|MEG 2441|MEG 2021 +Left-occipital:MEG 2042|MEG 2043|MEG 1913|MEG 1912|MEG 2113|MEG 2112|MEG 1922|MEG 1923|MEG 1942|MEG 1943|MEG 1642|MEG 1643|MEG 1933|MEG 1932|MEG 1733|MEG 1732|MEG 1723|MEG 1722|MEG 2143|MEG 2142|MEG 1742|MEG 1743|MEG 1712|MEG 1713|MEG 2041|MEG 1911|MEG 2111|MEG 1921|MEG 1941|MEG 1641|MEG 1931|MEG 1731|MEG 1721|MEG 2141|MEG 1741|MEG 1711 +Right-occipital:MEG 2032|MEG 2033|MEG 2313|MEG 2312|MEG 2342|MEG 2343|MEG 2322|MEG 2323|MEG 2433|MEG 2432|MEG 2122|MEG 2123|MEG 2333|MEG 2332|MEG 2513|MEG 2512|MEG 2523|MEG 2522|MEG 2133|MEG 2132|MEG 2542|MEG 2543|MEG 2532|MEG 2533|MEG 2031|MEG 2311|MEG 2341|MEG 2321|MEG 2431|MEG 2121|MEG 2331|MEG 2511|MEG 2521|MEG 2131|MEG 2541|MEG 2531 +Left-frontal:MEG 0522|MEG 0523|MEG 0512|MEG 0513|MEG 0312|MEG 0313|MEG 0342|MEG 0343|MEG 0122|MEG 0123|MEG 0822|MEG 0823|MEG 0533|MEG 0532|MEG 0543|MEG 0542|MEG 0322|MEG 0323|MEG 0612|MEG 0613|MEG 0333|MEG 0332|MEG 0622|MEG 0623|MEG 0643|MEG 0642|MEG 0521|MEG 0511|MEG 0311|MEG 0341|MEG 0121|MEG 0821|MEG 0531|MEG 0541|MEG 0321|MEG 0611|MEG 0331|MEG 0621|MEG 0641 +Right-frontal:MEG 0813|MEG 0812|MEG 0912|MEG 0913|MEG 0922|MEG 0923|MEG 1212|MEG 1213|MEG 1223|MEG 1222|MEG 1412|MEG 1413|MEG 0943|MEG 0942|MEG 0933|MEG 0932|MEG 1232|MEG 1233|MEG 1012|MEG 1013|MEG 1022|MEG 1023|MEG 1243|MEG 1242|MEG 1033|MEG 1032|MEG 0811|MEG 0911|MEG 0921|MEG 1211|MEG 1221|MEG 1411|MEG 0941|MEG 0931|MEG 1231|MEG 1011|MEG 1021|MEG 1241|MEG 1031 +# +# EEG in groups of 32 channels +# +EEG 1-32:EEG 001|EEG 002|EEG 003|EEG 004|EEG 005|EEG 006|EEG 007|EEG 008|EEG 009|EEG 010|EEG 011|EEG 012|EEG 013|EEG 014|EEG 015|EEG 016|EEG 017|EEG 018|EEG 019|EEG 020|EEG 021|EEG 022|EEG 023|EEG 024|EEG 025|EEG 026|EEG 027|EEG 028|EEG 029|EEG 030|EEG 031|EEG 032 +EEG 33-64:EEG 033|EEG 034|EEG 035|EEG 036|EEG 037|EEG 038|EEG 039|EEG 040|EEG 041|EEG 042|EEG 043|EEG 044|EEG 045|EEG 046|EEG 047|EEG 048|EEG 049|EEG 050|EEG 051|EEG 052|EEG 053|EEG 054|EEG 055|EEG 056|EEG 057|EEG 058|EEG 059|EEG 060|EEG 061|EEG 062|EEG 063|EEG 064 +EEG 65-96:EEG 065|EEG 066|EEG 067|EEG 068|EEG 069|EEG 070|EEG 071|EEG 072|EEG 073|EEG 074|EEG 075|EEG 076|EEG 077|EEG 078|EEG 079|EEG 080|EEG 081|EEG 082|EEG 083|EEG 084|EEG 085|EEG 086|EEG 087|EEG 088|EEG 089|EEG 090|EEG 091|EEG 092|EEG 093|EEG 094|EEG 095|EEG 096 +EEG 97-128:EEG 097|EEG 098|EEG 099|EEG 100|EEG 101|EEG 102|EEG 103|EEG 104|EEG 105|EEG 106|EEG 107|EEG 108|EEG 109|EEG 110|EEG 111|EEG 112|EEG 113|EEG 114|EEG 115|EEG 116|EEG 117|EEG 118|EEG 119|EEG 120|EEG 121|EEG 122|EEG 123|EEG 124|EEG 125|EEG 126|EEG 127|EEG 128 \ No newline at end of file diff --git a/mne-python/source/mne/datasets/__init__.py b/mne-python/source/mne/datasets/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..700dab0608e9b80cc071d6ddcbe0717bacf25cf6 --- /dev/null +++ b/mne-python/source/mne/datasets/__init__.py @@ -0,0 +1,12 @@ +"""Functions for fetching remote datasets. + +See :ref:`datasets` for more information. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/datasets/__init__.pyi b/mne-python/source/mne/datasets/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..2f69a1027e51cc6b47b5745e062c74fc96d97169 --- /dev/null +++ b/mne-python/source/mne/datasets/__init__.pyi @@ -0,0 +1,78 @@ +__all__ = [ + "_download_all_example_data", + "_fake", + "brainstorm", + "eegbci", + "epilepsy_ecog", + "erp_core", + "eyelink", + "default_path", + "fetch_aparc_sub_parcellation", + "fetch_dataset", + "fetch_fsaverage", + "fetch_hcp_mmp_parcellation", + "fetch_infant_template", + "fetch_phantom", + "fieldtrip_cmc", + "fnirs_motor", + "has_dataset", + "hf_sef", + "kiloword", + "limo", + "misc", + "mtrf", + "multimodal", + "opm", + "phantom_4dbti", + "phantom_kernel", + "phantom_kit", + "refmeg_noise", + "sample", + "sleep_physionet", + "somato", + "spm_face", + "ssvep", + "testing", + "ucl_opm_auditory", + "visual_92_categories", +] +from . import ( + _fake, + brainstorm, + eegbci, + epilepsy_ecog, + erp_core, + eyelink, + fieldtrip_cmc, + fnirs_motor, + hf_sef, + kiloword, + limo, + misc, + mtrf, + multimodal, + opm, + phantom_4dbti, + phantom_kernel, + phantom_kit, + refmeg_noise, + sample, + sleep_physionet, + somato, + spm_face, + ssvep, + testing, + ucl_opm_auditory, + visual_92_categories, +) +from ._fetch import fetch_dataset +from ._fsaverage.base import fetch_fsaverage +from ._infant import fetch_infant_template +from ._phantom.base import fetch_phantom +from .utils import ( + _download_all_example_data, + default_path, + fetch_aparc_sub_parcellation, + fetch_hcp_mmp_parcellation, + has_dataset, +) diff --git a/mne-python/source/mne/datasets/_fake/__init__.py b/mne-python/source/mne/datasets/_fake/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fb11651003377cfa602862ccc64a2bc0f91b073d --- /dev/null +++ b/mne-python/source/mne/datasets/_fake/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Fake dataset for testing.""" + +from ._fake import data_path, get_version diff --git a/mne-python/source/mne/datasets/_fake/_fake.py b/mne-python/source/mne/datasets/_fake/_fake.py new file mode 100644 index 0000000000000000000000000000000000000000..e983153ef31584d47f89a447609746aa9151e150 --- /dev/null +++ b/mne-python/source/mne/datasets/_fake/_fake.py @@ -0,0 +1,30 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=False, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="fake", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format(name="fake", conf="MNE_DATASETS_FAKE_PATH") + + +def get_version(): # noqa: D103 + return _get_version("fake") + + +get_version.__doc__ = _version_doc.format(name="fake") diff --git a/mne-python/source/mne/datasets/_fetch.py b/mne-python/source/mne/datasets/_fetch.py new file mode 100644 index 0000000000000000000000000000000000000000..0697add22026cc8eeccee8744403e3f495409a00 --- /dev/null +++ b/mne-python/source/mne/datasets/_fetch.py @@ -0,0 +1,310 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from __future__ import annotations # only needed for Python ≤ 3.9 + +import os +import os.path as op +import sys +import time +from pathlib import Path +from shutil import rmtree + +from .. import __version__ as mne_version +from ..fixes import _compare_version +from ..utils import _safe_input, logger, warn +from .config import ( + MISC_VERSIONED, + RELEASES, + TESTING_VERSIONED, + _bst_license_text, +) +from .utils import ( + _dataset_version, + _do_path_update, + _downloader_params, + _get_path, + _log_time_size, + _pl, +) + +_FAKE_VERSION = None # used for monkeypatching while testing versioning + + +def fetch_dataset( + dataset_params, + processor=None, + path=None, + force_update=False, + update_path=True, + download=True, + check_version=False, + return_version=False, + accept=False, + auth=None, + token=None, +) -> Path | tuple[Path, str]: + """Fetch an MNE-compatible dataset using pooch. + + Parameters + ---------- + dataset_params : list of dict | dict + The dataset name(s) and corresponding parameters to download the + dataset(s). The dataset parameters that contains the following keys: + ``archive_name``, ``url``, ``folder_name``, ``hash``, + ``config_key`` (optional). See Notes. + processor : None | "unzip" | "untar" | instance of pooch.Unzip | instance of pooch.Untar + What to do after downloading the file. ``"unzip"`` and ``"untar"`` will + decompress the downloaded file in place; for custom extraction (e.g., + only extracting certain files from the archive) pass an instance of + ``pooch.Unzip`` or ``pooch.Untar``. If ``None`` (the + default), the files are left as-is. + path : None | str + Directory in which to put the dataset. If ``None``, the dataset + location is determined by first checking whether + ``dataset_params['config_key']`` is defined, and if so, whether that + config key exists in the MNE-Python config file. If so, the configured + path is used; if not, the location is set to the value of the + ``MNE_DATA`` config key (if it exists), or ``~/mne_data`` otherwise. + force_update : bool + Force update of the dataset even if a local copy exists. + Default is False. + update_path : bool | None + If True (default), set the mne-python config to the given + path. If None, the user is prompted. + download : bool + If False and the dataset has not been downloaded yet, it will not be + downloaded and the path will be returned as ``''`` (empty string). This + is mostly used for testing purposes and can be safely ignored by most + users. + check_version : bool + Whether to check the version of the dataset or not. Each version + of the dataset is stored in the root with a ``version.txt`` file. + return_version : bool + Whether or not to return the version of the dataset or not. + Defaults to False. + accept : bool + Some MNE-supplied datasets require acceptance of an additional license. + Default is ``False``. + auth : tuple | None + Optional authentication tuple containing the username and + password/token, passed to ``pooch.HTTPDownloader`` (e.g., + ``auth=('foo', 012345)``). + token : str | None + Optional authentication token passed to ``pooch.HTTPDownloader``. + + Returns + ------- + data_path : instance of Path + The path to the fetched dataset. + version : str + Only returned if ``return_version`` is True. + + See Also + -------- + mne.get_config + mne.set_config + mne.datasets.has_dataset + + Notes + ----- + The ``dataset_params`` argument must contain the following keys: + + - ``archive_name``: The name of the (possibly compressed) file to download + - ``url``: URL from which the file can be downloaded + - ``folder_name``: the subfolder within the ``MNE_DATA`` folder in which to + save and uncompress (if needed) the file(s) + - ``hash``: the cryptographic hash type of the file followed by a colon and + then the hash value (examples: "sha256:19uheid...", "md5:upodh2io...") + - ``config_key`` (optional): key passed to :func:`mne.set_config` to store + the on-disk location of the downloaded dataset (e.g., + ``"MNE_DATASETS_EEGBCI_PATH"``). This will only work for the provided + datasets listed :ref:`here `; do not use for user-defined + datasets. + + An example would look like:: + + {'dataset_name': 'sample', + 'archive_name': 'MNE-sample-data-processed.tar.gz', + 'hash': 'md5:e8f30c4516abdc12a0c08e6bae57409c', + 'url': 'https://osf.io/download/86qa2?version=6', + 'folder_name': 'MNE-sample-data', + 'config_key': 'MNE_DATASETS_SAMPLE_PATH'} + + For datasets where a single (possibly compressed) file must be downloaded, + pass a single :class:`dict` as ``dataset_params``. For datasets where + multiple files must be downloaded and (optionally) uncompressed separately, + pass a list of dicts. + """ # noqa E501 + import pooch + + t0 = time.time() + + if auth is not None: + if len(auth) != 2: + raise RuntimeError( + "auth should be a 2-tuple consisting of a username and password/token." + ) + + # processor to uncompress files + if processor == "untar": + processor = pooch.Untar(extract_dir=path) + elif processor == "unzip": + processor = pooch.Unzip(extract_dir=path) + + if isinstance(dataset_params, dict): + dataset_params = [dataset_params] + + # extract configuration parameters + names = [params["dataset_name"] for params in dataset_params] + name = names[0] + dataset_dict = dataset_params[0] + config_key = dataset_dict.get("config_key", None) + folder_name = dataset_dict["folder_name"] + + # get download path for specific dataset + path = _get_path(path=path, key=config_key, name=name) + + # get the actual path to each dataset folder name + final_path = op.join(path, folder_name) + + # handle BrainStorm datasets with nested folders for datasets + if name.startswith("bst_"): + final_path = op.join(final_path, name) + + final_path = Path(final_path) + + # additional condition: check for version.txt and parse it + # check if testing or misc data is outdated; if so, redownload it + want_version = RELEASES.get(name, None) + want_version = _FAKE_VERSION if name == "fake" else want_version + + # get the version of the dataset and then check if the version is outdated + data_version = _dataset_version(final_path, name) + outdated = want_version is not None and _compare_version( + want_version, ">", data_version + ) + + if outdated: + logger.info( + f"Dataset {name} version {data_version} out of date, " + f"latest version is {want_version}" + ) + empty = Path("") + + # return empty string if outdated dataset and we don't want to download + if (not force_update) and outdated and not download: + logger.info( + "Dataset out of date but force_update=False and download=False, " + "returning empty data_path" + ) + return (empty, data_version) if return_version else empty + + # reasons to bail early (hf_sef has separate code for this): + if (not force_update) and (not outdated) and (not name.startswith("hf_sef_")): + # ...if target folder exists (otherwise pooch downloads every + # time because we don't save the archive files after unpacking, so + # pooch can't check its checksum) + if op.isdir(final_path): + if config_key is not None: + _do_path_update(path, update_path, config_key, name) + return (final_path, data_version) if return_version else final_path + # ...if download=False (useful for debugging) + elif not download: + return (empty, data_version) if return_version else empty + # ...if user didn't accept the license + elif name.startswith("bst_"): + if accept or "--accept-brainstorm-license" in sys.argv: + answer = "y" + else: + # If they don't have stdin, just accept the license + # https://github.com/mne-tools/mne-python/issues/8513#issuecomment-726823724 # noqa: E501 + answer = _safe_input(f"{_bst_license_text}Agree (y/[n])? ", use="y") + if answer.lower() != "y": + raise RuntimeError("You must agree to the license to use this dataset") + # downloader & processors + download_params = _downloader_params(auth=auth, token=token) + if name == "fake": + download_params["progressbar"] = False + downloader = pooch.HTTPDownloader(**download_params) + + # make mappings from archive names to urls and to checksums + urls = dict() + registry = dict() + for idx, this_name in enumerate(names): + this_dataset = dataset_params[idx] + archive_name = this_dataset["archive_name"] + dataset_url = this_dataset["url"] + dataset_hash = this_dataset["hash"] + urls[archive_name] = dataset_url + registry[archive_name] = dataset_hash + + # create the download manager + use_path = final_path if processor is None else Path(path) + fetcher = pooch.create( + path=str(use_path), + base_url="", # Full URLs are given in the `urls` dict. + version=None, # Data versioning is decoupled from MNE-Python version. + urls=urls, + registry=registry, + retry_if_failed=2, # 2 retries = 3 total attempts + ) + + # use our logger level for pooch's logger too + pooch.get_logger().setLevel(logger.getEffectiveLevel()) + sz = 0 + logger.info( + "Fetching %s file%s for the %s dataset ...", len(names), _pl(names), name + ) + + for idx in range(len(names)): + # fetch and unpack the data + archive_name = dataset_params[idx]["archive_name"] + try: + fetcher.fetch( + fname=archive_name, downloader=downloader, processor=processor + ) + except ValueError as err: + err = str(err) + if "hash of downloaded file" in str(err): + raise ValueError( + f"{err} Consider using force_update=True to force " + "the dataset to be downloaded again." + ) from None + else: + raise + fname = use_path / archive_name + sz += fname.stat().st_size + # after unpacking, remove the archive file + if processor is not None: + fname.unlink() + + # remove version number from "misc" and "testing" datasets folder names + if name == "misc": + rmtree(final_path, ignore_errors=True) + os.replace(op.join(path, MISC_VERSIONED), final_path) + elif name == "testing": + rmtree(final_path, ignore_errors=True) + os.replace(op.join(path, TESTING_VERSIONED), final_path) + + # maybe update the config + if config_key is not None: + old_name = "brainstorm" if name.startswith("bst_") else name + _do_path_update(path, update_path, config_key, old_name) + + # compare the version of the dataset and mne + data_version = _dataset_version(path, name) + # 0.7 < 0.7.git should be False, therefore strip + if check_version and ( + _compare_version(data_version, "<", mne_version.strip(".git")) + ): + # OK to `nosec` because it's false positive (misidentified as SQL) + warn( + f"The {name} dataset (version {data_version}) is older than " + f"mne-python (version {mne_version}). If the examples fail, " + f"you may need to update the {name} dataset by using " + f"mne.datasets.{name}.data_path(force_update=True)" # nosec B608 + ) + _log_time_size(t0, sz) + return (final_path, data_version) if return_version else final_path diff --git a/mne-python/source/mne/datasets/_fsaverage/__init__.py b/mne-python/source/mne/datasets/_fsaverage/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/datasets/_fsaverage/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/datasets/_fsaverage/base.py b/mne-python/source/mne/datasets/_fsaverage/base.py new file mode 100644 index 0000000000000000000000000000000000000000..5dce5b8fca4996dd3453aa641ce49385b53e920f --- /dev/null +++ b/mne-python/source/mne/datasets/_fsaverage/base.py @@ -0,0 +1,103 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +from ...utils import get_subjects_dir, set_config, verbose +from ..utils import _get_path, _manifest_check_download + +FSAVERAGE_MANIFEST_PATH = Path(__file__).parent + + +@verbose +def fetch_fsaverage(subjects_dir=None, *, verbose=None): + """Fetch and update :ref:`fsaverage `. + + Parameters + ---------- + subjects_dir : str | None + The path to use as the subjects directory in the MNE-Python + config file. None will use the existing config variable (i.e., + will not change anything), and if it does not exist, will use + ``~/mne_data/MNE-fsaverage-data``. + %(verbose)s + + Returns + ------- + fs_dir : Path + The fsaverage directory. + (essentially ``subjects_dir / 'fsaverage'``). + + .. versionchanged:: 1.8 + A :class:`pathlib.Path` object is returned instead of a string. + + Notes + ----- + This function is designed to provide + + 1. All modern (Freesurfer 6) fsaverage subject files + 2. All MNE fsaverage parcellations + 3. fsaverage head surface, fiducials, head<->MRI trans, 1- and 3-layer + BEMs (and surfaces) + + This function will compare the contents of ``subjects_dir/fsaverage`` + to the ones provided in the remote zip file. If any are missing, + the zip file is downloaded and files are updated. No files will + be overwritten. + + .. versionadded:: 0.18 + """ + # Code used to create the BEM (other files taken from MNE-sample-data): + # + # $ mne watershed_bem -s fsaverage -d $PWD --verbose info --copy + # $ python + # >>> bem = mne.make_bem_model('fsaverage', subjects_dir='.', verbose=True) + # >>> mne.write_bem_surfaces( + # ... 'fsaverage/bem/fsaverage-5120-5120-5120-bem.fif', bem) + # >>> sol = mne.make_bem_solution(bem, verbose=True) + # >>> mne.write_bem_solution( + # ... 'fsaverage/bem/fsaverage-5120-5120-5120-bem-sol.fif', sol) + # >>> import os + # >>> import os.path as op + # >>> names = sorted(op.join(r, f) + # ... for r, d, files in os.walk('fsaverage') + # ... for f in files) + # with open('fsaverage.txt', 'w') as fid: + # fid.write('\n'.join(names)) + # + subjects_dir = _set_montage_coreg_path(subjects_dir) + subjects_dir = subjects_dir.expanduser().absolute() + fs_dir = subjects_dir / "fsaverage" + fs_dir.mkdir(parents=True, exist_ok=True) + _manifest_check_download( + manifest_path=FSAVERAGE_MANIFEST_PATH / "root.txt", + destination=subjects_dir, + url="https://osf.io/download/3bxqt?version=2", + hash_="5133fe92b7b8f03ae19219d5f46e4177", + ) + _manifest_check_download( + manifest_path=FSAVERAGE_MANIFEST_PATH / "bem.txt", + destination=subjects_dir / "fsaverage", + url="https://osf.io/download/7ve8g?version=4", + hash_="b31509cdcf7908af6a83dc5ee8f49fb1", + ) + return fs_dir + + +def _get_create_subjects_dir(subjects_dir): + subjects_dir = get_subjects_dir(subjects_dir, raise_error=False) + if subjects_dir is None: + subjects_dir = _get_path(None, "MNE_DATA", "montage coregistration") + subjects_dir = subjects_dir / "MNE-fsaverage-data" + subjects_dir.mkdir(parents=True, exist_ok=True) + return subjects_dir + + +def _set_montage_coreg_path(subjects_dir=None): + """Set a subject directory suitable for montage(-only) coregistration.""" + subjects_dir = _get_create_subjects_dir(subjects_dir) + old_subjects_dir = get_subjects_dir(None, raise_error=False) + if old_subjects_dir is None: + set_config("SUBJECTS_DIR", subjects_dir) + return subjects_dir diff --git a/mne-python/source/mne/datasets/_fsaverage/bem.txt b/mne-python/source/mne/datasets/_fsaverage/bem.txt new file mode 100644 index 0000000000000000000000000000000000000000..0f4ade512f16416a28c0b35fa091eff2884d19cb --- /dev/null +++ b/mne-python/source/mne/datasets/_fsaverage/bem.txt @@ -0,0 +1,12 @@ +bem/fsaverage-fiducials.fif +bem/fsaverage-5120-5120-5120-bem.fif +bem/fsaverage-head.fif +bem/outer_skin.surf +bem/brain.surf +bem/fsaverage-trans.fif +bem/fsaverage-ico-5-src.fif +bem/fsaverage-vol-5-src.fif +bem/outer_skull.surf +bem/inner_skull.surf +bem/fsaverage-5120-5120-5120-bem-sol.fif +bem/fsaverage-inner_skull-bem.fif diff --git a/mne-python/source/mne/datasets/_fsaverage/root.txt b/mne-python/source/mne/datasets/_fsaverage/root.txt new file mode 100644 index 0000000000000000000000000000000000000000..a6d32810cf577ab7125738c10435b98d9f953d62 --- /dev/null +++ b/mne-python/source/mne/datasets/_fsaverage/root.txt @@ -0,0 +1,179 @@ +fsaverage/bem/fsaverage-head-dense.fif +fsaverage/bem/fsaverage-head-medium.fif +fsaverage/bem/fsaverage-head.fif +fsaverage/bem/fsaverage-ico-5-src.fif +fsaverage/label/lh.BA1.label +fsaverage/label/lh.BA2.label +fsaverage/label/lh.BA3a.label +fsaverage/label/lh.BA3b.label +fsaverage/label/lh.BA44.label +fsaverage/label/lh.BA45.label +fsaverage/label/lh.BA4a.label +fsaverage/label/lh.BA4p.label +fsaverage/label/lh.BA6.label +fsaverage/label/lh.HCPMMP1.annot +fsaverage/label/lh.HCPMMP1_combined.annot +fsaverage/label/lh.MT.label +fsaverage/label/lh.Medial_wall.label +fsaverage/label/lh.PALS_B12.labels.gii +fsaverage/label/lh.PALS_B12_Brodmann.annot +fsaverage/label/lh.PALS_B12_Lobes.annot +fsaverage/label/lh.PALS_B12_OrbitoFrontal.annot +fsaverage/label/lh.PALS_B12_Visuotopic.annot +fsaverage/label/lh.V1.label +fsaverage/label/lh.V2.label +fsaverage/label/lh.Yeo2011_17Networks_N1000.annot +fsaverage/label/lh.Yeo2011_7Networks_N1000.annot +fsaverage/label/lh.aparc.a2005s.annot +fsaverage/label/lh.aparc.a2009s.annot +fsaverage/label/lh.aparc.annot +fsaverage/label/lh.aparc.label +fsaverage/label/lh.aparc_sub.annot +fsaverage/label/lh.cortex.label +fsaverage/label/lh.entorhinal.label +fsaverage/label/lh.oasis.chubs.annot +fsaverage/label/rh.BA1.label +fsaverage/label/rh.BA2.label +fsaverage/label/rh.BA3a.label +fsaverage/label/rh.BA3b.label +fsaverage/label/rh.BA44.label +fsaverage/label/rh.BA45.label +fsaverage/label/rh.BA4a.label +fsaverage/label/rh.BA4p.label +fsaverage/label/rh.BA6.label +fsaverage/label/rh.HCPMMP1.annot +fsaverage/label/rh.HCPMMP1_combined.annot +fsaverage/label/rh.MT.label +fsaverage/label/rh.Medial_wall.label +fsaverage/label/rh.PALS_B12.labels.gii +fsaverage/label/rh.PALS_B12_Brodmann.annot +fsaverage/label/rh.PALS_B12_Lobes.annot +fsaverage/label/rh.PALS_B12_OrbitoFrontal.annot +fsaverage/label/rh.PALS_B12_Visuotopic.annot +fsaverage/label/rh.V1.label +fsaverage/label/rh.V2.label +fsaverage/label/rh.Yeo2011_17Networks_N1000.annot +fsaverage/label/rh.Yeo2011_7Networks_N1000.annot +fsaverage/label/rh.aparc.a2005s.annot +fsaverage/label/rh.aparc.a2009s.annot +fsaverage/label/rh.aparc.annot +fsaverage/label/rh.aparc.label +fsaverage/label/rh.aparc_sub.annot +fsaverage/label/rh.cortex.label +fsaverage/label/rh.entorhinal.label +fsaverage/label/rh.oasis.chubs.annot +fsaverage/mri.2mm/README +fsaverage/mri.2mm/T1.mgz +fsaverage/mri.2mm/aseg.mgz +fsaverage/mri.2mm/brain.mgz +fsaverage/mri.2mm/brainmask.mgz +fsaverage/mri.2mm/mni305.cor.mgz +fsaverage/mri.2mm/orig.mgz +fsaverage/mri.2mm/reg.2mm.dat +fsaverage/mri.2mm/reg.2mm.mni152.dat +fsaverage/mri.2mm/subcort.mask.mgz +fsaverage/mri.2mm/subcort.prob.mgz +fsaverage/mri/T1.mgz +fsaverage/mri/aparc+aseg.mgz +fsaverage/mri/aparc.a2005s+aseg.mgz +fsaverage/mri/aparc.a2009s+aseg.mgz +fsaverage/mri/aseg.mgz +fsaverage/mri/brain.mgz +fsaverage/mri/brainmask.mgz +fsaverage/mri/lh.ribbon.mgz +fsaverage/mri/mni305.cor.mgz +fsaverage/mri/orig.mgz +fsaverage/mri/p.aseg.mgz +fsaverage/mri/rh.ribbon.mgz +fsaverage/mri/ribbon.mgz +fsaverage/mri/seghead.mgz +fsaverage/mri/subcort.prob.log +fsaverage/mri/subcort.prob.mgz +fsaverage/mri/transforms/reg.mni152.2mm.dat +fsaverage/mri/transforms/talairach.xfm +fsaverage/scripts/build-stamp.txt +fsaverage/scripts/csurfdir +fsaverage/scripts/make_average_surface.log +fsaverage/scripts/make_average_volume.log +fsaverage/scripts/mkheadsurf.log +fsaverage/scripts/mris_inflate.log +fsaverage/scripts/mris_inflate_lh.log +fsaverage/scripts/mris_inflate_rh.log +fsaverage/scripts/recon-all-status.log +fsaverage/scripts/recon-all.cmd +fsaverage/scripts/recon-all.done +fsaverage/scripts/recon-all.env +fsaverage/scripts/recon-all.env.bak +fsaverage/scripts/recon-all.local-copy +fsaverage/scripts/recon-all.log +fsaverage/surf/lh.area +fsaverage/surf/lh.area.seghead +fsaverage/surf/lh.avg_curv +fsaverage/surf/lh.avg_sulc +fsaverage/surf/lh.avg_thickness +fsaverage/surf/lh.cortex.patch.3d +fsaverage/surf/lh.cortex.patch.flat +fsaverage/surf/lh.curv +fsaverage/surf/lh.curv.seghead +fsaverage/surf/lh.fsaverage_sym.sphere.reg +fsaverage/surf/lh.inflated +fsaverage/surf/lh.inflated.H +fsaverage/surf/lh.inflated.K +fsaverage/surf/lh.inflated_avg +fsaverage/surf/lh.inflated_pre +fsaverage/surf/lh.orig +fsaverage/surf/lh.orig.avg.area.mgh +fsaverage/surf/lh.orig_avg +fsaverage/surf/lh.pial +fsaverage/surf/lh.pial.avg.area.mgh +fsaverage/surf/lh.pial_avg +fsaverage/surf/lh.pial_semi_inflated +fsaverage/surf/lh.seghead +fsaverage/surf/lh.seghead.inflated +fsaverage/surf/lh.smoothwm +fsaverage/surf/lh.sphere +fsaverage/surf/lh.sphere.left_right +fsaverage/surf/lh.sphere.reg +fsaverage/surf/lh.sphere.reg.avg +fsaverage/surf/lh.sulc +fsaverage/surf/lh.sulc.seghead +fsaverage/surf/lh.thickness +fsaverage/surf/lh.white +fsaverage/surf/lh.white.avg.area.mgh +fsaverage/surf/lh.white_avg +fsaverage/surf/lh.white_avg.H +fsaverage/surf/lh.white_avg.K +fsaverage/surf/mris_preproc.surface.lh.log +fsaverage/surf/mris_preproc.surface.rh.log +fsaverage/surf/rh.area +fsaverage/surf/rh.avg_curv +fsaverage/surf/rh.avg_sulc +fsaverage/surf/rh.avg_thickness +fsaverage/surf/rh.cortex.patch.3d +fsaverage/surf/rh.cortex.patch.flat +fsaverage/surf/rh.curv +fsaverage/surf/rh.fsaverage_sym.sphere.reg +fsaverage/surf/rh.inflated +fsaverage/surf/rh.inflated.H +fsaverage/surf/rh.inflated.K +fsaverage/surf/rh.inflated_avg +fsaverage/surf/rh.inflated_pre +fsaverage/surf/rh.orig +fsaverage/surf/rh.orig.avg.area.mgh +fsaverage/surf/rh.orig_avg +fsaverage/surf/rh.pial +fsaverage/surf/rh.pial.avg.area.mgh +fsaverage/surf/rh.pial_avg +fsaverage/surf/rh.pial_semi_inflated +fsaverage/surf/rh.smoothwm +fsaverage/surf/rh.sphere +fsaverage/surf/rh.sphere.left_right +fsaverage/surf/rh.sphere.reg +fsaverage/surf/rh.sphere.reg.avg +fsaverage/surf/rh.sulc +fsaverage/surf/rh.thickness +fsaverage/surf/rh.white +fsaverage/surf/rh.white.avg.area.mgh +fsaverage/surf/rh.white_avg +fsaverage/surf/rh.white_avg.H +fsaverage/surf/rh.white_avg.K diff --git a/mne-python/source/mne/datasets/_infant/ANTS1-0Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS1-0Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..fc77acedae13408137de679bfaa841c407510f60 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS1-0Months3T.txt @@ -0,0 +1,117 @@ +bem/ANTS1-0Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS1-0Months3T-5120-5120-5120-bem.fif +bem/ANTS1-0Months3T-fiducials.fif +bem/ANTS1-0Months3T-head.fif +bem/ANTS1-0Months3T-oct-6-src.fif +bem/ANTS1-0Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS10-5Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS10-5Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..cec0a3e735aeb3bb23c531c0ce2a23bc02748b2c --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS10-5Months3T.txt @@ -0,0 +1,115 @@ +bem/ANTS10-5Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS10-5Months3T-5120-5120-5120-bem.fif +bem/ANTS10-5Months3T-fiducials.fif +bem/ANTS10-5Months3T-head.fif +bem/ANTS10-5Months3T-oct-6-src.fif +bem/ANTS10-5Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS12-0Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS12-0Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..d1fdbbc7bb06274bcefd3ff24b7fab2c549cb858 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS12-0Months3T.txt @@ -0,0 +1,121 @@ +atlases/brain_ANTS_IXI_atlas_head_space.nii.gz +atlases/brain_ANTS_LPBA40_atlas_head_space.nii.gz +atlases/brain_IXI_atlas_head_space.nii.gz +atlases/brain_LPBA40_atlas_head_space.nii.gz +bem/ANTS12-0Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS12-0Months3T-5120-5120-5120-bem.fif +bem/ANTS12-0Months3T-fiducials.fif +bem/ANTS12-0Months3T-head.fif +bem/ANTS12-0Months3T-oct-6-src.fif +bem/ANTS12-0Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS15-0Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS15-0Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..50487c06c736340a6337e6adc3e8325e4c9b37ed --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS15-0Months3T.txt @@ -0,0 +1,121 @@ +atlases/brain_ANTS_IXI_atlas_head_space.nii.gz +atlases/brain_ANTS_LPBA40_atlas_head_space.nii.gz +atlases/brain_IXI_atlas_head_space.nii.gz +atlases/brain_LPBA40_atlas_head_space.nii.gz +bem/ANTS15-0Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS15-0Months3T-5120-5120-5120-bem.fif +bem/ANTS15-0Months3T-fiducials.fif +bem/ANTS15-0Months3T-head.fif +bem/ANTS15-0Months3T-oct-6-src.fif +bem/ANTS15-0Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS18-0Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS18-0Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..8f386c820f2907956673474c1fa1e342b9ec4b1d --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS18-0Months3T.txt @@ -0,0 +1,121 @@ +atlases/brain_ANTS_IXI_atlas_head_space.nii.gz +atlases/brain_ANTS_LPBA40_atlas_head_space.nii.gz +atlases/brain_IXI_atlas_head_space.nii.gz +atlases/brain_LPBA40_atlas_head_space.nii.gz +bem/ANTS18-0Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS18-0Months3T-5120-5120-5120-bem.fif +bem/ANTS18-0Months3T-fiducials.fif +bem/ANTS18-0Months3T-head.fif +bem/ANTS18-0Months3T-oct-6-src.fif +bem/ANTS18-0Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS2-0Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS2-0Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..2a6b9c22c312ccde03681c7e07e3701514782be8 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS2-0Months3T.txt @@ -0,0 +1,117 @@ +bem/ANTS2-0Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS2-0Months3T-5120-5120-5120-bem.fif +bem/ANTS2-0Months3T-fiducials.fif +bem/ANTS2-0Months3T-head.fif +bem/ANTS2-0Months3T-oct-6-src.fif +bem/ANTS2-0Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS2-0Weeks3T.txt b/mne-python/source/mne/datasets/_infant/ANTS2-0Weeks3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..e940f24b1472a52fa46181812cc8604f2be42310 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS2-0Weeks3T.txt @@ -0,0 +1,117 @@ +bem/ANTS2-0Weeks3T-5120-5120-5120-bem-sol.fif +bem/ANTS2-0Weeks3T-5120-5120-5120-bem.fif +bem/ANTS2-0Weeks3T-fiducials.fif +bem/ANTS2-0Weeks3T-head.fif +bem/ANTS2-0Weeks3T-oct-6-src.fif +bem/ANTS2-0Weeks3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS2-0Years3T.txt b/mne-python/source/mne/datasets/_infant/ANTS2-0Years3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..776396919ec11f29073844732403c9d03d71c5c2 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS2-0Years3T.txt @@ -0,0 +1,121 @@ +atlases/brain_ANTS_IXI_atlas_head_space.nii.gz +atlases/brain_ANTS_LPBA40_atlas_head_space.nii.gz +atlases/brain_IXI_atlas_head_space.nii.gz +atlases/brain_LPBA40_atlas_head_space.nii.gz +bem/ANTS2-0Years3T-5120-5120-5120-bem-sol.fif +bem/ANTS2-0Years3T-5120-5120-5120-bem.fif +bem/ANTS2-0Years3T-fiducials.fif +bem/ANTS2-0Years3T-head.fif +bem/ANTS2-0Years3T-oct-6-src.fif +bem/ANTS2-0Years3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS3-0Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS3-0Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..29a7148010b937d393f597dd4b18f8a02b2014dc --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS3-0Months3T.txt @@ -0,0 +1,121 @@ +atlases/brain_ANTS_IXI_atlas_head_space.nii.gz +atlases/brain_ANTS_LPBA40_atlas_head_space.nii.gz +atlases/brain_IXI_atlas_head_space.nii.gz +atlases/brain_LPBA40_atlas_head_space.nii.gz +bem/ANTS3-0Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS3-0Months3T-5120-5120-5120-bem.fif +bem/ANTS3-0Months3T-fiducials.fif +bem/ANTS3-0Months3T-head.fif +bem/ANTS3-0Months3T-oct-6-src.fif +bem/ANTS3-0Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS4-5Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS4-5Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..b9188492d5023e78cb36f92c6a204d5242801712 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS4-5Months3T.txt @@ -0,0 +1,121 @@ +atlases/brain_ANTS_IXI_atlas_head_space.nii.gz +atlases/brain_ANTS_LPBA40_atlas_head_space.nii.gz +atlases/brain_IXI_atlas_head_space.nii.gz +atlases/brain_LPBA40_atlas_head_space.nii.gz +bem/ANTS4-5Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS4-5Months3T-5120-5120-5120-bem.fif +bem/ANTS4-5Months3T-fiducials.fif +bem/ANTS4-5Months3T-head.fif +bem/ANTS4-5Months3T-oct-6-src.fif +bem/ANTS4-5Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS6-0Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS6-0Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..3235de4c576d81835ad39e4465157f870e728161 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS6-0Months3T.txt @@ -0,0 +1,121 @@ +atlases/brain_ANTS_IXI_atlas_head_space.nii.gz +atlases/brain_ANTS_LPBA40_atlas_head_space.nii.gz +atlases/brain_IXI_atlas_head_space.nii.gz +atlases/brain_LPBA40_atlas_head_space.nii.gz +bem/ANTS6-0Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS6-0Months3T-5120-5120-5120-bem.fif +bem/ANTS6-0Months3T-fiducials.fif +bem/ANTS6-0Months3T-head.fif +bem/ANTS6-0Months3T-oct-6-src.fif +bem/ANTS6-0Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS7-5Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS7-5Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b38563c5b16a4da86c0ec6fa5c2ae878cb4ea4f --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS7-5Months3T.txt @@ -0,0 +1,121 @@ +atlases/brain_ANTS_IXI_atlas_head_space.nii.gz +atlases/brain_ANTS_LPBA40_atlas_head_space.nii.gz +atlases/brain_IXI_atlas_head_space.nii.gz +atlases/brain_LPBA40_atlas_head_space.nii.gz +bem/ANTS7-5Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS7-5Months3T-5120-5120-5120-bem.fif +bem/ANTS7-5Months3T-fiducials.fif +bem/ANTS7-5Months3T-head.fif +bem/ANTS7-5Months3T-oct-6-src.fif +bem/ANTS7-5Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/ANTS9-0Months3T.txt b/mne-python/source/mne/datasets/_infant/ANTS9-0Months3T.txt new file mode 100644 index 0000000000000000000000000000000000000000..8d37f25d0ba64e8ad3265e6792e879b123050140 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/ANTS9-0Months3T.txt @@ -0,0 +1,121 @@ +atlases/brain_ANTS_IXI_atlas_head_space.nii.gz +atlases/brain_ANTS_LPBA40_atlas_head_space.nii.gz +atlases/brain_IXI_atlas_head_space.nii.gz +atlases/brain_LPBA40_atlas_head_space.nii.gz +bem/ANTS9-0Months3T-5120-5120-5120-bem-sol.fif +bem/ANTS9-0Months3T-5120-5120-5120-bem.fif +bem/ANTS9-0Months3T-fiducials.fif +bem/ANTS9-0Months3T-head.fif +bem/ANTS9-0Months3T-oct-6-src.fif +bem/ANTS9-0Months3T-vol-5-src.fif +bem/inner_skull.surf +bem/inner_skull_large.surf +bem/outer_skin.surf +bem/outer_skin_large.surf +bem/outer_skull.surf +bem/outer_skull_large.surf +flirt_trans_mat.txt +label/aparc.annot.ctab +label/lh.aparc.a2009s.annot +label/lh.aparc.annot +label/lh.cortex.label +label/rh.aparc.a2009s.annot +label/rh.aparc.annot +label/rh.cortex.label +montages/10-10-montage.fif +montages/10-10_electrodes.tsv +montages/10-20-montage.fif +montages/10-20_electrodes.tsv +montages/10-5-montage.fif +montages/10-5_electrodes.tsv +montages/HGSN128-montage.fif +montages/HGSN128_electrodes.tsv +montages/HGSN129-montage.fif +montages/HGSN129_electrodes.tsv +mprage.nii.gz +mri/T1.mgz +mri/aparc+aseg.mgz +mri/aseg.count.txt +mri/aseg.mgz +mri/aseg.nii.gz +mri/aseg.presurf.mgz +mri/brain.finalsurfs.mgz +mri/brain.mgz +mri/brain.nii.gz +mri/brainmask.mgz +mri/brainmask.nii.gz +mri/filled.mgz +mri/lh.dpial.ribbon.mgz +mri/lh.dwhite.ribbon.mgz +mri/lh.ribbon.mgz +mri/norm.mgz +mri/norm.nii.gz +mri/rh.dpial.ribbon.mgz +mri/rh.dwhite.ribbon.mgz +mri/rh.ribbon.mgz +mri/ribbon.mgz +mri/transforms/niftyreg_affine.lta +mri/transforms/niftyreg_affine.nii.gz +mri/transforms/niftyreg_affine.txt +mri/transforms/niftyreg_affine.xfm +mri/transforms/talairach.auto.xfm +mri/transforms/talairach.xfm +mri/wm.mgz +surf/10-10-montage.obj +surf/10-10-montage.surf +surf/10-20-montage.obj +surf/10-20-montage.surf +surf/10-5-montage.obj +surf/10-5-montage.surf +surf/HGSN128-montage.obj +surf/HGSN128-montage.surf +surf/fiducials.obj +surf/fiducials.surf +surf/lh.area +surf/lh.curv +surf/lh.defects +surf/lh.inflated +surf/lh.inflated.H +surf/lh.inflated.K +surf/lh.input +surf/lh.orig +surf/lh.orig.euler.txt +surf/lh.orig_corrected +surf/lh.pial +surf/lh.qsphere +surf/lh.qsphere.nofix +surf/lh.smoothwm +surf/lh.smoothwm1 +surf/lh.smoothwm2 +surf/lh.smoothwm3 +surf/lh.smoothwm4 +surf/lh.smoothwm5 +surf/lh.sphere +surf/lh.sphere.reg +surf/lh.sulc +surf/lh.thickness +surf/lh.white +surf/rh.area +surf/rh.curv +surf/rh.defects +surf/rh.inflated +surf/rh.inflated.H +surf/rh.inflated.K +surf/rh.input +surf/rh.orig +surf/rh.orig.euler.txt +surf/rh.orig_corrected +surf/rh.pial +surf/rh.qsphere +surf/rh.qsphere.nofix +surf/rh.smoothwm +surf/rh.smoothwm1 +surf/rh.smoothwm2 +surf/rh.smoothwm3 +surf/rh.smoothwm4 +surf/rh.smoothwm5 +surf/rh.sphere +surf/rh.sphere.reg +surf/rh.sulc +surf/rh.thickness +surf/rh.white \ No newline at end of file diff --git a/mne-python/source/mne/datasets/_infant/__init__.py b/mne-python/source/mne/datasets/_infant/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..d787cc635115caa6d0a4b9cd3b80b40421a32019 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/__init__.py @@ -0,0 +1,5 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .base import fetch_infant_template diff --git a/mne-python/source/mne/datasets/_infant/base.py b/mne-python/source/mne/datasets/_infant/base.py new file mode 100644 index 0000000000000000000000000000000000000000..6c4d038aa728bd141b700ffddc841532462c08f7 --- /dev/null +++ b/mne-python/source/mne/datasets/_infant/base.py @@ -0,0 +1,94 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +from ...utils import _check_option, _validate_type, get_subjects_dir, verbose +from ..utils import _manifest_check_download + +_AGES = "2wk 1mo 2mo 3mo 4.5mo 6mo 7.5mo 9mo 10.5mo 12mo 15mo 18mo 2yr" +# https://github.com/christian-oreilly/infant_template_paper/releases +_ORIGINAL_URL = "https://github.com/christian-oreilly/infant_template_paper/releases/download/v0.1-alpha/{subject}.zip" # noqa: E501 +# Formatted the same way as md5sum *.zip on Ubuntu: +_ORIGINAL_HASHES = """ +851737d5f8f246883f2aef9819c6ec29 ANTS10-5Months3T.zip +32ab6d025f4311433a82e81374f1a045 ANTS1-0Months3T.zip +48ef349e7cc542fdf63ff36d7958ab57 ANTS12-0Months3T.zip +bba22c95aa97988c6e8892d6169ed317 ANTS15-0Months3T.zip +e1bfe5e3ef380592822ced446a4008c7 ANTS18-0Months3T.zip +fa7bee6c0985b9cd15ba53820cd72ccd ANTS2-0Months3T.zip +2ad90540cdf42837c09f8ce829458a35 ANTS2-0Weeks3T.zip +73e6a8b2579b7959a96f7d294ffb7393 ANTS2-0Years3T.zip +cb7b9752894e16a4938ddfe220f6286a ANTS3-0Months3T.zip +16b2a6804c7d5443cfba2ad6f7d4ac6a ANTS4-5Months3T.zip +dbdf2a9976121f2b106da96775690da3 ANTS6-0Months3T.zip +75fe37a1bc80ed6793a8abb47681d5ab ANTS7-5Months3T.zip +790f7dba0a264262e6c1c2dfdf216215 ANTS9-0Months3T.zip +""" +_MANIFEST_PATH = Path(__file__).parent + + +@verbose +def fetch_infant_template(age, subjects_dir=None, *, verbose=None): + """Fetch and update an infant MRI template. + + Parameters + ---------- + age : str + Age to download. Can be one of ``{'2wk', '1mo', '2mo', '3mo', '4.5mo', + '6mo', '7.5mo', '9mo', '10.5mo', '12mo', '15mo', '18mo', '2yr'}``. + subjects_dir : str | None + The path to download the template data to. + %(verbose)s + + Returns + ------- + subject : str + The standard subject name, e.g. ``ANTS4-5Month3T``. + + Notes + ----- + If you use these templates in your work, please cite + :footcite:`OReillyEtAl2021` and :footcite:`RichardsEtAl2016`. + + .. versionadded:: 0.23 + + References + ---------- + .. footbibliography:: + """ + # Code used to create the lists: + # + # $ for name in 2-0Weeks 1-0Months 2-0Months 3-0Months 4-5Months 6-0Months 7-5Months 9-0Months 10-5Months 12-0Months 15-0Months 18-0Months 2-0Years; do wget https://github.com/christian-oreilly/infant_template_paper/releases/download/v0.1-alpha/ANTS${name}3T.zip; done # noqa: E501 + # $ md5sum ANTS*.zip + # $ python + # >>> import os.path as op + # >>> import zipfile + # >>> names = [f'ANTS{name}3T' for name in '2-0Weeks 1-0Months 2-0Months 3-0Months 4-5Months 6-0Months 7-5Months 9-0Months 10-5Months 12-0Months 15-0Months 18-0Months 2-0Years'.split()] # noqa: E501 + # >>> for name in names: + # ... with zipfile.ZipFile(f'{name}.zip', 'r') as zip: + # ... names = sorted(name for name in zip.namelist() if not zipfile.Path(zip, name).is_dir()) # noqa: E501 + # ... with open(f'{name}.txt', 'w') as fid: + # ... fid.write('\n'.join(names)) + _validate_type(age, str, "age") + _check_option("age", age, _AGES.split()) + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + unit = dict(wk="Weeks", mo="Months", yr="Years")[age[-2:]] + first = age[:-2].split(".")[0] + dash = "-5" if ".5" in age else "-0" + subject = f"ANTS{first}{dash}{unit}3T" + # Actually get and create the files + subject_dir = subjects_dir / subject + subject_dir.mkdir(parents=True, exist_ok=True) + # .zip -> hash mapping + orig_hashes = dict( + line.strip().split()[::-1] for line in _ORIGINAL_HASHES.strip().splitlines() + ) + _manifest_check_download( + manifest_path=_MANIFEST_PATH / f"{subject}.txt", + destination=subject_dir, + url=_ORIGINAL_URL.format(subject=subject), + hash_=orig_hashes[f"{subject}.zip"], + ) + return subject diff --git a/mne-python/source/mne/datasets/_phantom/__init__.py b/mne-python/source/mne/datasets/_phantom/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/datasets/_phantom/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/datasets/_phantom/base.py b/mne-python/source/mne/datasets/_phantom/base.py new file mode 100644 index 0000000000000000000000000000000000000000..0cd549571924cea246cdb2863155c906cd93e0c3 --- /dev/null +++ b/mne-python/source/mne/datasets/_phantom/base.py @@ -0,0 +1,67 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +from ...utils import _check_option, _validate_type, get_subjects_dir, verbose +from ..utils import _manifest_check_download + +PHANTOM_MANIFEST_PATH = Path(__file__).parent + + +@verbose +def fetch_phantom(kind="otaniemi", subjects_dir=None, *, verbose=None): + """Fetch and update a phantom subject. + + Parameters + ---------- + kind : str + The kind of phantom to fetch. Can only be ``'otaniemi'`` (default). + + .. versionchanged:: 1.12 + The default is now properly set in the signature so it doesn't need to be + provided. + %(subjects_dir)s + %(verbose)s + + Returns + ------- + subject_dir : pathlib.Path + The resulting phantom subject directory. + + See Also + -------- + mne.dipole.get_phantom_dipoles + + Notes + ----- + This function is designed to provide a head surface and T1.mgz for + the 32-dipole Otaniemi phantom. The VectorView/TRIUX phantom has the same + basic outside geometry, but different internal dipole positions. + + Unlike most FreeSurfer subjects, the Otaniemi phantom scan was aligned + to the "head" coordinate frame, so an identity head<->MRI :term:`trans` + is appropriate. + + .. versionadded:: 0.24 + """ + phantoms = dict( + otaniemi=dict( + url="https://osf.io/download/j5czy?version=1", + hash="42d17db5b1db3e30327ffb4cf2649de8", + ), + ) + _validate_type(kind, str, "kind") + _check_option("kind", kind, list(phantoms)) + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + subject = f"phantom_{kind}" + subject_dir = subjects_dir / subject + subject_dir.mkdir(parents=True, exist_ok=True) + _manifest_check_download( + manifest_path=PHANTOM_MANIFEST_PATH / f"{subject}.txt", + destination=subjects_dir, + url=phantoms[kind]["url"], + hash_=phantoms[kind]["hash"], + ) + return subject_dir diff --git a/mne-python/source/mne/datasets/_phantom/phantom_otaniemi.txt b/mne-python/source/mne/datasets/_phantom/phantom_otaniemi.txt new file mode 100644 index 0000000000000000000000000000000000000000..84f830232c0dd2e8aa17aee486383ca32b5f7c6c --- /dev/null +++ b/mne-python/source/mne/datasets/_phantom/phantom_otaniemi.txt @@ -0,0 +1,3 @@ +phantom_otaniemi/bem/phantom_otaniemi-fiducials.fif +phantom_otaniemi/mri/T1.mgz +phantom_otaniemi/surf/lh.seghead diff --git a/mne-python/source/mne/datasets/brainstorm/__init__.py b/mne-python/source/mne/datasets/brainstorm/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..90a0eaa8e3e7481210855e6215b6c8a355100d3e --- /dev/null +++ b/mne-python/source/mne/datasets/brainstorm/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Brainstorm datasets.""" + +from . import bst_raw, bst_resting, bst_auditory, bst_phantom_ctf, bst_phantom_elekta diff --git a/mne-python/source/mne/datasets/brainstorm/bst_auditory.py b/mne-python/source/mne/datasets/brainstorm/bst_auditory.py new file mode 100644 index 0000000000000000000000000000000000000000..230fd6798705e78960e7f111d7a4a7a637dadb71 --- /dev/null +++ b/mne-python/source/mne/datasets/brainstorm/bst_auditory.py @@ -0,0 +1,69 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import ( + _data_path_doc_accept, + _download_mne_dataset, + _get_version, + _version_doc, +) + +_description = """ +URL: http://neuroimage.usc.edu/brainstorm/DatasetAuditory + - One subject, two acquisition runs of 6 minutes each + - Subject stimulated binaurally with intra-aural earphones + (air tubes+transducers) + - Each run contains: + - 200 regular beeps (440Hz) + - 40 easy deviant beeps (554.4Hz, 4 semitones higher) + - Random inter-stimulus interval: between 0.7s and 1.7s seconds, uniformly + distributed + - The subject presses a button when detecting a deviant with the right + index finger + - Auditory stimuli generated with the Matlab Psychophysics toolbox +""" + + +@verbose +def data_path( + path=None, + force_update=False, + update_path=True, + download=True, + accept=False, + *, + verbose=None, +): # noqa: D103 + return _download_mne_dataset( + name="bst_auditory", + processor="nested_untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + accept=accept, + ) + + +_data_path_doc = _data_path_doc_accept.format( + name="brainstorm", conf="MNE_DATASETS_BRAINSTORM_DATA_PATH" +) +_data_path_doc = _data_path_doc.replace( + "brainstorm dataset", "brainstorm (bst_auditory) dataset" +) +data_path.__doc__ = _data_path_doc + + +def get_version(): # noqa: D103 + return _get_version("bst_auditory") + + +get_version.__doc__ = _version_doc.format(name="brainstorm") + + +def description(): + """Get description of brainstorm (bst_auditory) dataset.""" + for desc in _description.splitlines(): + print(desc) diff --git a/mne-python/source/mne/datasets/brainstorm/bst_phantom_ctf.py b/mne-python/source/mne/datasets/brainstorm/bst_phantom_ctf.py new file mode 100644 index 0000000000000000000000000000000000000000..328a7748924488a6a3403e952bdc9315eeea24f5 --- /dev/null +++ b/mne-python/source/mne/datasets/brainstorm/bst_phantom_ctf.py @@ -0,0 +1,58 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import ( + _data_path_doc_accept, + _download_mne_dataset, + _get_version, + _version_doc, +) + +_description = """ +URL: http://neuroimage.usc.edu/brainstorm/Tutorials/PhantomCtf +""" + + +@verbose +def data_path( + path=None, + force_update=False, + update_path=True, + download=True, + accept=False, + *, + verbose=None, +): # noqa: D103 + return _download_mne_dataset( + name="bst_phantom_ctf", + processor="nested_untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + accept=accept, + ) + + +_data_path_doc = _data_path_doc_accept.format( + name="brainstorm", conf="MNE_DATASETS_BRAINSTORM_DATA_PATH" +) +_data_path_doc = _data_path_doc.replace( + "brainstorm dataset", "brainstorm (bst_phantom_ctf) dataset" +) +data_path.__doc__ = _data_path_doc + + +def get_version(): # noqa: D103 + return _get_version("bst_phantom_ctf") + + +get_version.__doc__ = _version_doc.format(name="brainstorm") + + +def description(): + """Get description of brainstorm (bst_phantom_ctf) dataset.""" + for desc in _description.splitlines(): + print(desc) diff --git a/mne-python/source/mne/datasets/brainstorm/bst_phantom_elekta.py b/mne-python/source/mne/datasets/brainstorm/bst_phantom_elekta.py new file mode 100644 index 0000000000000000000000000000000000000000..1a7e3ac1f31fb593c6aeb564f13ccdc6a092df76 --- /dev/null +++ b/mne-python/source/mne/datasets/brainstorm/bst_phantom_elekta.py @@ -0,0 +1,58 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import ( + _data_path_doc_accept, + _download_mne_dataset, + _get_version, + _version_doc, +) + +_description = """ +URL: http://neuroimage.usc.edu/brainstorm/Tutorials/PhantomElekta +""" + + +@verbose +def data_path( + path=None, + force_update=False, + update_path=True, + download=True, + accept=False, + *, + verbose=None, +): # noqa: D103 + return _download_mne_dataset( + name="bst_phantom_elekta", + processor="nested_untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + accept=accept, + ) + + +_data_path_doc = _data_path_doc_accept.format( + name="brainstorm", conf="MNE_DATASETS_BRAINSTORM_DATA_PATH" +) +_data_path_doc = _data_path_doc.replace( + "brainstorm dataset", "brainstorm (bst_phantom_elekta) dataset" +) +data_path.__doc__ = _data_path_doc + + +def get_version(): # noqa: D103 + return _get_version("bst_phantom_elekta") + + +get_version.__doc__ = _version_doc.format(name="brainstorm") + + +def description(): + """Get description of brainstorm (bst_phantom_elekta) dataset.""" + for desc in _description.splitlines(): + print(desc) diff --git a/mne-python/source/mne/datasets/brainstorm/bst_raw.py b/mne-python/source/mne/datasets/brainstorm/bst_raw.py new file mode 100644 index 0000000000000000000000000000000000000000..13a4aa3e5cc5f57e0172e85346b1b485e2e5898b --- /dev/null +++ b/mne-python/source/mne/datasets/brainstorm/bst_raw.py @@ -0,0 +1,88 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from functools import partial + +from ...utils import get_config, verbose +from ..utils import ( + _data_path_doc_accept, + _download_mne_dataset, + _get_version, + _version_doc, + has_dataset, +) + +has_brainstorm_data = partial(has_dataset, name="bst_raw") + +_description = """ +URL: http://neuroimage.usc.edu/brainstorm/DatasetMedianNerveCtf + - One subject, one acquisition run of 6 minutes + - Subject stimulated using Digitimer Constant Current Stimulator + (model DS7A) + - The run contains 200 electric stimulations randomly distributed between + left and right: + - 102 stimulations of the left hand + - 98 stimulations of the right hand + - Inter-stimulus interval: jittered between [1500, 2000]ms + - Stimuli generated using PsychToolBox on Windows PC (TTL pulse generated + with the parallel port connected to the Digitimer via the rear panel BNC) +""" + + +@verbose +def data_path( + path=None, + force_update=False, + update_path=True, + download=True, + accept=False, + *, + verbose=None, +): # noqa: D103 + return _download_mne_dataset( + name="bst_raw", + processor="nested_untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + accept=accept, + ) + + +_data_path_doc = _data_path_doc_accept.format( + name="brainstorm", conf="MNE_DATASETS_BRAINSTORM_DATA_PATH" +) +_data_path_doc = _data_path_doc.replace( + "brainstorm dataset", "brainstorm (bst_raw) dataset" +) +data_path.__doc__ = _data_path_doc + + +def get_version(): # noqa: D103 + return _get_version("bst_raw") + + +get_version.__doc__ = _version_doc.format(name="brainstorm") + + +def description(): # noqa: D103 + """Get description of brainstorm (bst_raw) dataset.""" + for desc in _description.splitlines(): + print(desc) + + +def _skip_bstraw_data(): + skip_testing = get_config("MNE_SKIP_TESTING_DATASET_TESTS", "false") == "true" + skip = skip_testing or not has_brainstorm_data() + return skip + + +def requires_bstraw_data(func): + """Skip testing data test.""" + import pytest + + return pytest.mark.skipif( + _skip_bstraw_data(), reason="Requires brainstorm dataset" + )(func) diff --git a/mne-python/source/mne/datasets/brainstorm/bst_resting.py b/mne-python/source/mne/datasets/brainstorm/bst_resting.py new file mode 100644 index 0000000000000000000000000000000000000000..d740cf1a6bc8ccb18eeae9b3187aaf5d8580db72 --- /dev/null +++ b/mne-python/source/mne/datasets/brainstorm/bst_resting.py @@ -0,0 +1,61 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import ( + _data_path_doc_accept, + _download_mne_dataset, + _get_version, + _version_doc, +) + +_description = """ +URL: http://neuroimage.usc.edu/brainstorm/DatasetResting + - One subject + - Two runs of 10 min of resting state recordings + - Eyes open +""" + + +@verbose +def data_path( + path=None, + force_update=False, + update_path=True, + download=True, + accept=False, + *, + verbose=None, +): # noqa: D103 + return _download_mne_dataset( + name="bst_resting", + processor="nested_untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + accept=accept, + ) + + +_data_path_doc = _data_path_doc_accept.format( + name="brainstorm", conf="MNE_DATASETS_BRAINSTORM_DATA_PATH" +) +_data_path_doc = _data_path_doc.replace( + "brainstorm dataset", "brainstorm (bst_resting) dataset" +) +data_path.__doc__ = _data_path_doc + + +def get_version(): # noqa: D103 + return _get_version("bst_resting") + + +get_version.__doc__ = _version_doc.format(name="brainstorm") + + +def description(): + """Get description of brainstorm (bst_resting) dataset.""" + for desc in _description.splitlines(): + print(desc) diff --git a/mne-python/source/mne/datasets/config.py b/mne-python/source/mne/datasets/config.py new file mode 100644 index 0000000000000000000000000000000000000000..455af7eaa0d1a7f60aa87b343a531bfca866c426 --- /dev/null +++ b/mne-python/source/mne/datasets/config.py @@ -0,0 +1,370 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + + +_bst_license_text = """ +License +------- +This tutorial dataset (EEG and MRI data) remains a property of the MEG Lab, +McConnell Brain Imaging Center, Montreal Neurological Institute, +McGill University, Canada. Its use and transfer outside the Brainstorm +tutorial, e.g. for research purposes, is prohibited without written consent +from the MEG Lab. + +If you reference this dataset in your publications, please: + + 1) acknowledge its authors: Elizabeth Bock, Esther Florin, Francois Tadel + and Sylvain Baillet, and + 2) cite Brainstorm as indicated on the website: + http://neuroimage.usc.edu/brainstorm + +For questions, please contact Francois Tadel (francois.tadel@mcgill.ca). +""" + +_hcp_mmp_license_text = """ +License +------- +I request access to data collected by the Washington University - University +of Minnesota Consortium of the Human Connectome Project (WU-Minn HCP), and +I agree to the following: + +1. I will not attempt to establish the identity of or attempt to contact any + of the included human subjects. + +2. I understand that under no circumstances will the code that would link + these data to Protected Health Information be given to me, nor will any + additional information about individual human subjects be released to me + under these Open Access Data Use Terms. + +3. I will comply with all relevant rules and regulations imposed by my + institution. This may mean that I need my research to be approved or + declared exempt by a committee that oversees research on human subjects, + e.g. my IRB or Ethics Committee. The released HCP data are not considered + de-identified, insofar as certain combinations of HCP Restricted Data + (available through a separate process) might allow identification of + individuals. Different committees operate under different national, state + and local laws and may interpret regulations differently, so it is + important to ask about this. If needed and upon request, the HCP will + provide a certificate stating that you have accepted the HCP Open Access + Data Use Terms. + +4. I may redistribute original WU-Minn HCP Open Access data and any derived + data as long as the data are redistributed under these same Data Use Terms. + +5. I will acknowledge the use of WU-Minn HCP data and data derived from + WU-Minn HCP data when publicly presenting any results or algorithms + that benefitted from their use. + + 1. Papers, book chapters, books, posters, oral presentations, and all + other printed and digital presentations of results derived from HCP + data should contain the following wording in the acknowledgments + section: "Data were provided [in part] by the Human Connectome + Project, WU-Minn Consortium (Principal Investigators: David Van Essen + and Kamil Ugurbil; 1U54MH091657) funded by the 16 NIH Institutes and + Centers that support the NIH Blueprint for Neuroscience Research; and + by the McDonnell Center for Systems Neuroscience at Washington + University." + + 2. Authors of publications or presentations using WU-Minn HCP data + should cite relevant publications describing the methods used by the + HCP to acquire and process the data. The specific publications that + are appropriate to cite in any given study will depend on what HCP + data were used and for what purposes. An annotated and appropriately + up-to-date list of publications that may warrant consideration is + available at http://www.humanconnectome.org/about/acknowledgehcp.html + + 3. The WU-Minn HCP Consortium as a whole should not be included as an + author of publications or presentations if this authorship would be + based solely on the use of WU-Minn HCP data. + +6. Failure to abide by these guidelines will result in termination of my + privileges to access WU-Minn HCP data. +""" + +# To update the `testing` or `misc` datasets, push or merge commits to their +# respective repos, and make a new release of the dataset on GitHub. Then +# update the checksum in the MNE_DATASETS dict below, and change version +# here: ↓↓↓↓↓↓↓↓ +RELEASES = dict( + testing="0.172", + misc="0.27", + phantom_kit="0.2", + ucl_opm_auditory="0.2", +) +TESTING_VERSIONED = f"mne-testing-data-{RELEASES['testing']}" +MISC_VERSIONED = f"mne-misc-data-{RELEASES['misc']}" + +# To update any other dataset besides `testing` or `misc`, upload the new +# version of the data archive itself (e.g., to https://osf.io or wherever) and +# then update the corresponding checksum in the MNE_DATASETS dict entry below. +MNE_DATASETS = dict() + +# MANDATORY KEYS: +# - archive_name : the name of the compressed file that is downloaded +# - hash : the checksum type followed by a colon and then the checksum value +# (examples: "sha256:19uheid...", "md5:upodh2io...") +# - url : URL from which the file can be downloaded +# - folder_name : the subfolder within the MNE data folder in which to save and +# uncompress (if needed) the file(s) +# +# OPTIONAL KEYS: +# - config_key : key to use with `mne.set_config` to store the on-disk location +# of the downloaded dataset (ex: "MNE_DATASETS_EEGBCI_PATH"). + +# Testing and misc are at the top as they're updated most often +MNE_DATASETS["testing"] = dict( + archive_name=f"{TESTING_VERSIONED}.tar.gz", + hash="md5:9d031f1a91d2bd903a9464ca2cd7dc09", + url=( + "https://codeload.github.com/mne-tools/mne-testing-data/" + f"tar.gz/{RELEASES['testing']}" + ), + # In case we ever have to resort to osf.io again... + # archive_name='mne-testing-data.tar.gz', + # hash='md5:c805a5fed8ca46f723e7eec828d90824', + # url='https://osf.io/download/dqfgy?version=1', # 0.136 + folder_name="MNE-testing-data", + config_key="MNE_DATASETS_TESTING_PATH", +) +MNE_DATASETS["misc"] = dict( + archive_name=f"{MISC_VERSIONED}.tar.gz", # 'mne-misc-data', + hash="md5:e343d3a00cb49f8a2f719d14f4758afe", + url=( + f"https://codeload.github.com/mne-tools/mne-misc-data/tar.gz/{RELEASES['misc']}" + ), + folder_name="MNE-misc-data", + config_key="MNE_DATASETS_MISC_PATH", +) + +MNE_DATASETS["fnirs_motor"] = dict( + archive_name="MNE-fNIRS-motor-data.tgz", + hash="md5:c4935d19ddab35422a69f3326a01fef8", + url="https://osf.io/download/dj3eh?version=1", + folder_name="MNE-fNIRS-motor-data", + config_key="MNE_DATASETS_FNIRS_MOTOR_PATH", +) + +MNE_DATASETS["ucl_opm_auditory"] = dict( + archive_name="auditory_OPM_stationary.zip", + hash="md5:b2d69aa2d656b960bd0c18968dc1a14d", + url="https://osf.io/download/tp324?version=1", # original is mwrt3 + folder_name="auditory_OPM_stationary", + config_key="MNE_DATASETS_UCL_OPM_AUDITORY_PATH", +) + +MNE_DATASETS["kiloword"] = dict( + archive_name="MNE-kiloword-data.tar.gz", + hash="md5:3a124170795abbd2e48aae8727e719a8", + url="https://osf.io/download/qkvf9?version=1", + folder_name="MNE-kiloword-data", + config_key="MNE_DATASETS_KILOWORD_PATH", +) + +MNE_DATASETS["multimodal"] = dict( + archive_name="MNE-multimodal-data.tar.gz", + hash="md5:26ec847ae9ab80f58f204d09e2c08367", + url="https://ndownloader.figshare.com/files/5999598", + folder_name="MNE-multimodal-data", + config_key="MNE_DATASETS_MULTIMODAL_PATH", +) + +MNE_DATASETS["opm"] = dict( + archive_name="MNE-OPM-data.tar.gz", + hash="md5:370ad1dcfd5c47e029e692c85358a374", + url="https://osf.io/download/p6ae7?version=2", + folder_name="MNE-OPM-data", + config_key="MNE_DATASETS_OPM_PATH", +) + +MNE_DATASETS["phantom_kit"] = dict( + archive_name="MNE-phantom-KIT-data.tar.gz", + hash="md5:7bfdf40bbeaf17a66c99c695640e0740", + url="https://osf.io/download/fb6ya?version=1", + folder_name="MNE-phantom-KIT-data", + config_key="MNE_DATASETS_PHANTOM_KIT_PATH", +) + +MNE_DATASETS["phantom_4dbti"] = dict( + archive_name="MNE-phantom-4DBTi.zip", + hash="md5:938a601440f3ffa780d20a17bae039ff", + url="https://osf.io/download/v2brw?version=2", + folder_name="MNE-phantom-4DBTi", + config_key="MNE_DATASETS_PHANTOM_4DBTI_PATH", +) + +MNE_DATASETS["phantom_kernel"] = dict( + archive_name="MNE-phantom-kernel.tar.gz", + hash="md5:4e2ad987dac1a20f95bae8ffeb2d41d6", + url="https://osf.io/download/dj7wz?version=1", + folder_name="MNE-phantom-kernel-data", + config_key="MNE_DATASETS_PHANTOM_KERNEL_PATH", +) + +MNE_DATASETS["sample"] = dict( + archive_name="MNE-sample-data-processed.tar.gz", + hash="md5:e8f30c4516abdc12a0c08e6bae57409c", + url="https://osf.io/download/86qa2?version=6", + folder_name="MNE-sample-data", + config_key="MNE_DATASETS_SAMPLE_PATH", +) + +MNE_DATASETS["somato"] = dict( + archive_name="MNE-somato-data.tar.gz", + hash="md5:9a191907b326b9402341ee7a0d1240d8", + url="https://osf.io/download/tp4sg?version=8", + folder_name="MNE-somato-data", + config_key="MNE_DATASETS_SOMATO_PATH", +) + +MNE_DATASETS["spm"] = dict( + archive_name="MNE-spm-face.tar.gz", + hash="md5:9f43f67150e3b694b523a21eb929ea75", + url="https://osf.io/download/je4s8?version=2", + folder_name="MNE-spm-face", + config_key="MNE_DATASETS_SPM_FACE_PATH", +) + +# Visual 92 categories has the dataset split into 2 files. +# We define a dictionary holding the items with the same +# value across both files: folder name and configuration key. +MNE_DATASETS["visual_92_categories"] = dict( + folder_name="MNE-visual_92_categories-data", + config_key="MNE_DATASETS_VISUAL_92_CATEGORIES_PATH", +) +MNE_DATASETS["visual_92_categories_1"] = dict( + archive_name="MNE-visual_92_categories-data-part1.tar.gz", + hash="md5:74f50bbeb65740903eadc229c9fa759f", + url="https://osf.io/download/8ejrs?version=1", + folder_name="MNE-visual_92_categories-data", + config_key="MNE_DATASETS_VISUAL_92_CATEGORIES_PATH", +) +MNE_DATASETS["visual_92_categories_2"] = dict( + archive_name="MNE-visual_92_categories-data-part2.tar.gz", + hash="md5:203410a98afc9df9ae8ba9f933370e20", + url="https://osf.io/download/t4yjp?version=1", + folder_name="MNE-visual_92_categories-data", + config_key="MNE_DATASETS_VISUAL_92_CATEGORIES_PATH", +) + +MNE_DATASETS["mtrf"] = dict( + archive_name="mTRF_1.5.zip", + hash="md5:273a390ebbc48da2c3184b01a82e4636", + url="https://osf.io/download/h85s2?version=1", + folder_name="mTRF_1.5", + config_key="MNE_DATASETS_MTRF_PATH", +) +MNE_DATASETS["refmeg_noise"] = dict( + archive_name="sample_reference_MEG_noise-raw.zip", + hash="md5:779fecd890d98b73a4832e717d7c7c45", + url="https://osf.io/download/drt6v?version=1", + folder_name="MNE-refmeg-noise-data", + config_key="MNE_DATASETS_REFMEG_NOISE_PATH", +) + +MNE_DATASETS["ssvep"] = dict( + archive_name="ssvep_example_data.zip", + hash="md5:af866bbc0f921114ac9d683494fe87d6", + url="https://osf.io/download/z8h6k?version=5", + folder_name="ssvep-example-data", + config_key="MNE_DATASETS_SSVEP_PATH", +) + +MNE_DATASETS["erp_core"] = dict( + archive_name="MNE-ERP-CORE-data.tar.gz", + hash="md5:5866c0d6213bd7ac97f254c776f6c4b1", + url="https://osf.io/download/rzgba?version=1", + folder_name="MNE-ERP-CORE-data", + config_key="MNE_DATASETS_ERP_CORE_PATH", +) + +MNE_DATASETS["epilepsy_ecog"] = dict( + archive_name="MNE-epilepsy-ecog-data.tar.gz", + hash="md5:ffb139174afa0f71ec98adbbb1729dea", + url="https://osf.io/download/z4epq?version=1", + folder_name="MNE-epilepsy-ecog-data", + config_key="MNE_DATASETS_EPILEPSY_ECOG_PATH", +) + +# Fieldtrip CMC dataset +MNE_DATASETS["fieldtrip_cmc"] = dict( + archive_name="SubjectCMC.zip", + hash="md5:6f9fd6520f9a66e20994423808d2528c", + url="https://osf.io/download/j9b6s?version=1", + folder_name="MNE-fieldtrip_cmc-data", + config_key="MNE_DATASETS_FIELDTRIP_CMC_PATH", +) + +# brainstorm datasets: +MNE_DATASETS["bst_auditory"] = dict( + archive_name="bst_auditory.tar.gz", + hash="md5:fa371a889a5688258896bfa29dd1700b", + url="https://osf.io/download/5t9n8?version=1", + folder_name="MNE-brainstorm-data", + config_key="MNE_DATASETS_BRAINSTORM_PATH", +) +MNE_DATASETS["bst_phantom_ctf"] = dict( + archive_name="bst_phantom_ctf.tar.gz", + hash="md5:80819cb7f5b92d1a5289db3fb6acb33c", + url="https://osf.io/download/sxr8y?version=1", + folder_name="MNE-brainstorm-data", + config_key="MNE_DATASETS_BRAINSTORM_PATH", +) +MNE_DATASETS["bst_phantom_elekta"] = dict( + archive_name="bst_phantom_elekta.tar.gz", + hash="md5:1badccbe17998d18cc373526e86a7aaf", + url="https://osf.io/download/dpcku?version=1", + folder_name="MNE-brainstorm-data", + config_key="MNE_DATASETS_BRAINSTORM_PATH", +) +MNE_DATASETS["bst_raw"] = dict( + archive_name="bst_raw.tar.gz", + hash="md5:fa2efaaec3f3d462b319bc24898f440c", + url="https://osf.io/download/9675n?version=2", + folder_name="MNE-brainstorm-data", + config_key="MNE_DATASETS_BRAINSTORM_PATH", +) +MNE_DATASETS["bst_resting"] = dict( + archive_name="bst_resting.tar.gz", + hash="md5:70fc7bf9c3b97c4f2eab6260ee4a0430", + url="https://osf.io/download/m7bd3?version=3", + folder_name="MNE-brainstorm-data", + config_key="MNE_DATASETS_BRAINSTORM_PATH", +) + +# HF-SEF +MNE_DATASETS["hf_sef_raw"] = dict( + archive_name="hf_sef_raw.tar.gz", + hash="md5:33934351e558542bafa9b262ac071168", + url="https://zenodo.org/record/889296/files/hf_sef_raw.tar.gz", + folder_name="hf_sef", + config_key="MNE_DATASETS_HF_SEF_PATH", +) +MNE_DATASETS["hf_sef_evoked"] = dict( + archive_name="hf_sef_evoked.tar.gz", + hash="md5:13d34cb5db584e00868677d8fb0aab2b", + # Zenodo can be slow, so we use the OSF mirror + # url=('https://zenodo.org/record/3523071/files/' + # 'hf_sef_evoked.tar.gz'), + url="https://osf.io/download/25f8d?version=2", + folder_name="hf_sef", + config_key="MNE_DATASETS_HF_SEF_PATH", +) + +# "fake" dataset (for testing) +MNE_DATASETS["fake"] = dict( + archive_name="foo.tgz", + hash="md5:3194e9f7b46039bb050a74f3e1ae9908", + url="https://github.com/mne-tools/mne-testing-data/raw/master/datasets/foo.tgz", + folder_name="foo", + config_key="MNE_DATASETS_FAKE_PATH", +) + +# eyelink dataset +MNE_DATASETS["eyelink"] = dict( + archive_name="MNE-eyelink-data.zip", + hash="md5:68a6323ef17d655f1a659c3290ee1c3f", + url=("https://osf.io/download/xsu4g?version=1"), + folder_name="MNE-eyelink-data", + config_key="MNE_DATASETS_EYELINK_PATH", +) diff --git a/mne-python/source/mne/datasets/eegbci/__init__.py b/mne-python/source/mne/datasets/eegbci/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ac2a7179596f4e989bb81f42500316f8cfee3789 --- /dev/null +++ b/mne-python/source/mne/datasets/eegbci/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""EEG Motor Movement/Imagery Dataset.""" + +from .eegbci import data_path, load_data, standardize diff --git a/mne-python/source/mne/datasets/eegbci/eegbci.py b/mne-python/source/mne/datasets/eegbci/eegbci.py new file mode 100644 index 0000000000000000000000000000000000000000..7b6b3e8bdc8fa42cbf6186fc11291856a7af3552 --- /dev/null +++ b/mne-python/source/mne/datasets/eegbci/eegbci.py @@ -0,0 +1,248 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import re +import time +from importlib.resources import files +from os import path as op +from pathlib import Path + +from ...utils import _url_to_local_path, logger, verbose +from ..utils import _do_path_update, _downloader_params, _get_path, _log_time_size + +EEGMI_URL = "https://physionet.org/files/eegmmidb/1.0.0/" + + +@verbose +def data_path(url, path=None, force_update=False, update_path=None, *, verbose=None): + """Get path to local copy of EEGMMI dataset URL. + + This is a low-level function useful for getting a local copy of a remote EEGBCI + dataset :footcite:`SchalkEtAl2004`, which is also available at PhysioNet + :footcite:`GoldbergerEtAl2000`. Metadata, such as the meaning of event markers + may be obtained from the + `PhysioNet documentation page `_. + + Parameters + ---------- + url : str + The dataset to use. + path : None | path-like + Location of where to look for the EEGBCI data. If ``None``, the environment + variable or config parameter ``MNE_DATASETS_EEGBCI_PATH`` is used. If neither + exists, the ``~/mne_data`` directory is used. If the EEGBCI dataset is not found + under the given path, the data will be automatically downloaded to the specified + folder. + force_update : bool + Force update of the dataset even if a local copy exists. + update_path : bool | None + If ``True``, set ``MNE_DATASETS_EEGBCI_PATH`` in the configuration to the given + path. If ``None``, the user is prompted. + %(verbose)s + + Returns + ------- + path : list of Path + Local path to the given data file. This path is contained inside a list of + length one for compatibility. + + Notes + ----- + For example, one could do: + + >>> from mne.datasets import eegbci + >>> url = "http://www.physionet.org/physiobank/database/eegmmidb/" + >>> eegbci.data_path(url, "~/datasets") # doctest:+SKIP + + This would download the given EEGBCI data file to the ``~/datasets`` folder and + prompt the user to store this path in the config (if it does not already exist). + + References + ---------- + .. footbibliography:: + """ + import pooch + + key = "MNE_DATASETS_EEGBCI_PATH" + name = "EEGBCI" + path = _get_path(path, key, name) + fname = "MNE-eegbci-data" + destination = _url_to_local_path(url, op.join(path, fname)) + destinations = [destination] + + # fetch the file + downloader = pooch.HTTPDownloader(**_downloader_params()) + if not op.isfile(destination) or force_update: + if op.isfile(destination): + os.remove(destination) + if not op.isdir(op.dirname(destination)): + os.makedirs(op.dirname(destination)) + pooch.retrieve( + url=url, + path=destination, + downloader=downloader, + fname=fname, + ) + + # offer to update the path + _do_path_update(path, update_path, key, name) + destinations = [Path(dest) for dest in destinations] + return destinations + + +@verbose +def load_data( + subjects, + runs, + *, + path=None, + force_update=False, + update_path=None, + base_url=EEGMI_URL, + verbose=None, +): # noqa: D301 + """Get paths to local copies of EEGBCI dataset files. + + This will fetch data for the EEGBCI dataset :footcite:`SchalkEtAl2004`, which is + also available at PhysioNet :footcite:`GoldbergerEtAl2000`. Metadata, such as the + meaning of event markers may be obtained from the + `PhysioNet documentation page `_. + + Parameters + ---------- + subjects : int | list of int + The subjects to use. Can be in the range of 1-109 (inclusive). + runs : int | list of int + The runs to use (see Notes for details). + path : None | path-like + Location of where to look for the EEGBCI data. If ``None``, the environment + variable or config parameter ``MNE_DATASETS_EEGBCI_PATH`` is used. If neither + exists, the ``~/mne_data`` directory is used. If the EEGBCI dataset is not found + under the given path, the data will be automatically downloaded to the specified + folder. + force_update : bool + Force update of the dataset even if a local copy exists. + update_path : bool | None + If ``True``, set ``MNE_DATASETS_EEGBCI_PATH`` in the configuration to the given + path. If ``None``, the user is prompted. + base_url : str + The URL root for the data. + %(verbose)s + + Returns + ------- + paths : list + List of local data paths of the given type. + + Notes + ----- + The run numbers correspond to: + + ========= =================================== + run task + ========= =================================== + 1 Baseline, eyes open + 2 Baseline, eyes closed + 3, 7, 11 Motor execution: left vs right hand + 4, 8, 12 Motor imagery: left vs right hand + 5, 9, 13 Motor execution: hands vs feet + 6, 10, 14 Motor imagery: hands vs feet + ========= =================================== + + For example, one could do:: + + >>> from mne.datasets import eegbci + >>> eegbci.load_data([1, 2], [6, 10, 14], "~/datasets") # doctest:+SKIP + + This would download runs 6, 10, and 14 (hand/foot motor imagery) runs from subjects + 1 and 2 in the EEGBCI dataset to "~/datasets" and prompt the user to store this path + in the config (if it does not already exist). + + References + ---------- + .. footbibliography:: + """ + import pooch + + t0 = time.time() + + if not hasattr(subjects, "__iter__"): + subjects = [subjects] + + if not hasattr(runs, "__iter__"): + runs = [runs] + + # get local storage path + config_key = "MNE_DATASETS_EEGBCI_PATH" + folder = "MNE-eegbci-data" + name = "EEGBCI" + path = _get_path(path, config_key, name) + + # extract path parts + pattern = r"(?:https?://.*)(files)/(eegmmidb)/(\d+\.\d+\.\d+)/?" + match = re.compile(pattern).match(base_url) + if match is None: + raise ValueError( + "base_url does not match the expected EEGMI folder " + "structure. Please notify MNE-Python developers." + ) + base_path = op.join(path, folder, *match.groups()) + + # create the download manager + fetcher = pooch.create( + path=base_path, + base_url=base_url, + version=None, # data versioning is decoupled from MNE-Python version + registry=None, # registry is loaded from file (below) + retry_if_failed=2, # 2 retries = 3 total attempts + ) + + # load the checksum registry + registry = files("mne").joinpath("data", "eegbci_checksums.txt") + fetcher.load_registry(registry) + + # fetch the file(s) + data_paths = [] + sz = 0 + for subject in subjects: + for run in runs: + file_part = f"S{subject:03d}/S{subject:03d}R{run:02d}.edf" + destination = Path(base_path, file_part) + data_paths.append(destination) + if destination.exists(): + if force_update: + destination.unlink() + else: + continue + if sz == 0: # log once + logger.info("Downloading EEGBCI data") + fetcher.fetch(file_part) + # update path in config if desired + sz += destination.stat().st_size + + _do_path_update(path, update_path, config_key, name) + if sz > 0: + _log_time_size(t0, sz) + return data_paths + + +def standardize(raw): + """Standardize channel positions and names. + + Parameters + ---------- + raw : instance of Raw + The raw data to standardize. Operates in-place. + """ + rename = dict() + for name in raw.ch_names: + std_name = name.strip(".") + std_name = std_name.upper() + if std_name.endswith("Z"): + std_name = std_name[:-1] + "z" + if std_name.startswith("FP"): + std_name = "Fp" + std_name[2:] + rename[name] = std_name + raw.rename_channels(rename) diff --git a/mne-python/source/mne/datasets/eegbci/tests/test_eegbci.py b/mne-python/source/mne/datasets/eegbci/tests/test_eegbci.py new file mode 100644 index 0000000000000000000000000000000000000000..e9f63fee28828dcdf9a0f0fdc3430dcc22c21d52 --- /dev/null +++ b/mne-python/source/mne/datasets/eegbci/tests/test_eegbci.py @@ -0,0 +1,15 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + + +from mne.datasets import eegbci + + +def test_eegbci_download(tmp_path, fake_retrieve): + """Test Sleep Physionet URL handling.""" + subjects = range(1, 5) + for subj in subjects: + fnames = eegbci.load_data(subj, runs=[3], path=tmp_path, update_path=False) + assert len(fnames) == 1, subj + assert fake_retrieve.call_count == 4 diff --git a/mne-python/source/mne/datasets/epilepsy_ecog/__init__.py b/mne-python/source/mne/datasets/epilepsy_ecog/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6ecb3379302d7e82ea3680a2f0167bffd1cd3848 --- /dev/null +++ b/mne-python/source/mne/datasets/epilepsy_ecog/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Clinical epilepsy datasets.""" + +from ._data import data_path, get_version diff --git a/mne-python/source/mne/datasets/epilepsy_ecog/_data.py b/mne-python/source/mne/datasets/epilepsy_ecog/_data.py new file mode 100644 index 0000000000000000000000000000000000000000..20abb9fd8be970ecd7863d565fb15ce65c862348 --- /dev/null +++ b/mne-python/source/mne/datasets/epilepsy_ecog/_data.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="epilepsy_ecog", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="epilepsy_ecog", conf="MNE_DATASETS_EPILEPSY_ECOG_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("epilepsy_ecog") + + +get_version.__doc__ = _version_doc.format(name="epilepsy_ecog") diff --git a/mne-python/source/mne/datasets/erp_core/__init__.py b/mne-python/source/mne/datasets/erp_core/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b16989af413e39c7e4fd600152e954d3ee8b87af --- /dev/null +++ b/mne-python/source/mne/datasets/erp_core/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""ERP-CORE EEG dataset.""" + +from .erp_core import data_path, get_version diff --git a/mne-python/source/mne/datasets/erp_core/erp_core.py b/mne-python/source/mne/datasets/erp_core/erp_core.py new file mode 100644 index 0000000000000000000000000000000000000000..2771b17dfe3696be7e799eaca055f13320b98263 --- /dev/null +++ b/mne-python/source/mne/datasets/erp_core/erp_core.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="erp_core", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="erp_core", conf="MNE_DATASETS_ERP_CORE_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("erp_core") + + +get_version.__doc__ = _version_doc.format(name="erp_core") diff --git a/mne-python/source/mne/datasets/eyelink/__init__.py b/mne-python/source/mne/datasets/eyelink/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..db3ea545b587ca26af01abd724b6214beeab3ae6 --- /dev/null +++ b/mne-python/source/mne/datasets/eyelink/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Eyelink test dataset.""" + +from .eyelink import data_path, get_version diff --git a/mne-python/source/mne/datasets/eyelink/eyelink.py b/mne-python/source/mne/datasets/eyelink/eyelink.py new file mode 100644 index 0000000000000000000000000000000000000000..918ac86f1e8b856daa1bf7cb443dc0fa8794abb1 --- /dev/null +++ b/mne-python/source/mne/datasets/eyelink/eyelink.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="eyelink", + processor="unzip", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="eyelink", conf="MNE_DATASETS_EYELINK_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("eyelink") + + +get_version.__doc__ = _version_doc.format(name="eyelink") diff --git a/mne-python/source/mne/datasets/fieldtrip_cmc/__init__.py b/mne-python/source/mne/datasets/fieldtrip_cmc/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..0ed74466be8758cb64fcb873522901e4bdc2e85e --- /dev/null +++ b/mne-python/source/mne/datasets/fieldtrip_cmc/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""fieldtrip Cortico-Muscular Coherence (CMC) Dataset.""" + +from .fieldtrip_cmc import data_path, get_version diff --git a/mne-python/source/mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py b/mne-python/source/mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py new file mode 100644 index 0000000000000000000000000000000000000000..b61b1d7d1883e47591151b4948b82365e53f75ed --- /dev/null +++ b/mne-python/source/mne/datasets/fieldtrip_cmc/fieldtrip_cmc.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="fieldtrip_cmc", + processor="nested_unzip", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="fieldtrip_cmc", conf="MNE_DATASETS_FIELDTRIP_CMC_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("fieldtrip_cmc") + + +get_version.__doc__ = _version_doc.format(name="fieldtrip_cmc") diff --git a/mne-python/source/mne/datasets/fnirs_motor/__init__.py b/mne-python/source/mne/datasets/fnirs_motor/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..61808bb9fdf31262013175f7c56aa3d8270c3d06 --- /dev/null +++ b/mne-python/source/mne/datasets/fnirs_motor/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""fNIRS motor dataset.""" + +from .fnirs_motor import data_path, get_version diff --git a/mne-python/source/mne/datasets/fnirs_motor/fnirs_motor.py b/mne-python/source/mne/datasets/fnirs_motor/fnirs_motor.py new file mode 100644 index 0000000000000000000000000000000000000000..43a4ffc9b96fcc185c92fd30d847d6a6dbe06fdd --- /dev/null +++ b/mne-python/source/mne/datasets/fnirs_motor/fnirs_motor.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="fnirs_motor", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="fnirs_motor", conf="MNE_DATASETS_FNIRS_MOTOR_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("fnirs_motor") + + +get_version.__doc__ = _version_doc.format(name="fnirs_motor") diff --git a/mne-python/source/mne/datasets/hf_sef/__init__.py b/mne-python/source/mne/datasets/hf_sef/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3834a1279b1d2d2a24b152c8c73c76b72201dc6c --- /dev/null +++ b/mne-python/source/mne/datasets/hf_sef/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""HF-SEF dataset.""" + +from .hf_sef import data_path diff --git a/mne-python/source/mne/datasets/hf_sef/hf_sef.py b/mne-python/source/mne/datasets/hf_sef/hf_sef.py new file mode 100644 index 0000000000000000000000000000000000000000..aff18315970b9192dfaa3d9ce1885fc282438e84 --- /dev/null +++ b/mne-python/source/mne/datasets/hf_sef/hf_sef.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python2 + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + + +import os +import os.path as op + +from ...utils import _check_option, verbose +from ..config import MNE_DATASETS +from ..utils import _do_path_update, _download_mne_dataset, _get_path + + +@verbose +def data_path( + dataset="evoked", path=None, force_update=False, update_path=True, *, verbose=None +): + """Get path to local copy of the high frequency SEF dataset. + + Gets a local copy of the high frequency SEF MEG dataset + :footcite:`NurminenEtAl2017`. + + Parameters + ---------- + dataset : 'evoked' | 'raw' + Whether to get the main dataset (evoked, structural and the rest) or + the separate dataset containing raw MEG data only. + path : None | str + Where to look for the HF-SEF data storing location. + If None, the environment variable or config parameter + ``MNE_DATASETS_HF_SEF_PATH`` is used. If it doesn't exist, the + "~/mne_data" directory is used. If the HF-SEF dataset + is not found under the given path, the data + will be automatically downloaded to the specified folder. + force_update : bool + Force update of the dataset even if a local copy exists. + update_path : bool | None + If True, set the MNE_DATASETS_HF_SEF_PATH in mne-python + config to the given path. If None, the user is prompted. + %(verbose)s + + Returns + ------- + path : str + Local path to the directory where the HF-SEF data is stored. + + References + ---------- + .. footbibliography:: + """ + _check_option("dataset", dataset, ("evoked", "raw")) + if dataset == "raw": + data_dict = MNE_DATASETS["hf_sef_raw"] + data_dict["dataset_name"] = "hf_sef_raw" + else: + data_dict = MNE_DATASETS["hf_sef_evoked"] + data_dict["dataset_name"] = "hf_sef_evoked" + config_key = data_dict["config_key"] + folder_name = data_dict["folder_name"] + + # get download path for specific dataset + path = _get_path(path=path, key=config_key, name=folder_name) + final_path = op.join(path, folder_name) + megdir = op.join(final_path, "MEG", "subject_a") + has_raw = ( + dataset == "raw" + and op.isdir(megdir) + and any("raw" in filename for filename in os.listdir(megdir)) + ) + has_evoked = dataset == "evoked" and op.isdir(op.join(final_path, "subjects")) + # data not there, or force_update requested: + if has_raw or has_evoked and not force_update: + _do_path_update(path, update_path, config_key, folder_name) + return final_path + + # instantiate processor that unzips file + data_path = _download_mne_dataset( + name=data_dict["dataset_name"], + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=True, + ) + return data_path diff --git a/mne-python/source/mne/datasets/kiloword/__init__.py b/mne-python/source/mne/datasets/kiloword/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..17b54adacf3c3ce5720e2693bd6a62bf412f8412 --- /dev/null +++ b/mne-python/source/mne/datasets/kiloword/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""MNE visual_92_categories dataset.""" + +from .kiloword import data_path, get_version diff --git a/mne-python/source/mne/datasets/kiloword/kiloword.py b/mne-python/source/mne/datasets/kiloword/kiloword.py new file mode 100644 index 0000000000000000000000000000000000000000..37fd3f1ee6d12abf752030a34135690761409aa4 --- /dev/null +++ b/mne-python/source/mne/datasets/kiloword/kiloword.py @@ -0,0 +1,64 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): + """Get path to local copy of the kiloword dataset. + + This is the dataset from :footcite:`DufauEtAl2015`. + + Parameters + ---------- + path : None | str + Location of where to look for the kiloword data storing + location. If None, the environment variable or config parameter + MNE_DATASETS_KILOWORD_PATH is used. If it doesn't exist, + the "mne-python/examples" directory is used. If the + kiloword dataset is not found under the given path (e.g., + as "mne-python/examples/MNE-kiloword-data"), the data + will be automatically downloaded to the specified folder. + force_update : bool + Force update of the dataset even if a local copy exists. + update_path : bool | None + If True, set the MNE_DATASETS_KILOWORD_PATH in mne-python + config to the given path. If None, the user is prompted. + download : bool + If False and the kiloword dataset has not been downloaded yet, + it will not be downloaded and the path will be returned as + '' (empty string). This is mostly used for debugging purposes + and can be safely ignored by most users. + %(verbose)s + + Returns + ------- + path : list of Path + Local path to the given data file. This path is contained inside a list + of length one, for compatibility. + + References + ---------- + .. footbibliography:: + """ + return _download_mne_dataset( + name="kiloword", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +def get_version(): + """Get dataset version.""" + return _get_version("kiloword") + + +get_version.__doc__ = _version_doc.format(name="kiloword") diff --git a/mne-python/source/mne/datasets/limo/__init__.py b/mne-python/source/mne/datasets/limo/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b5622d903025512cac4eae0f7b32714ce4174315 --- /dev/null +++ b/mne-python/source/mne/datasets/limo/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""LIMO Dataset.""" + +from .limo import data_path, load_data diff --git a/mne-python/source/mne/datasets/limo/limo.py b/mne-python/source/mne/datasets/limo/limo.py new file mode 100644 index 0000000000000000000000000000000000000000..f0696a78b1ef1e4c86c9e60db17083a72d0d6e60 --- /dev/null +++ b/mne-python/source/mne/datasets/limo/limo.py @@ -0,0 +1,372 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op +import time +from pathlib import Path + +import numpy as np +from scipy.io import loadmat + +from ..._fiff.meas_info import create_info +from ...channels import make_standard_montage +from ...epochs import EpochsArray +from ...utils import _check_pandas_installed, logger, verbose +from ..utils import _do_path_update, _downloader_params, _get_path, _log_time_size + +# root url for LIMO files +root_url = "https://files.de-1.osf.io/v1/resources/52rea/providers/osfstorage/" + + +@verbose +def data_path( + subject, path=None, force_update=False, update_path=None, *, verbose=None +): + """Get path to local copy of LIMO dataset URL. + + This is a low-level function useful for getting a local copy of the + remote LIMO dataset :footcite:`Rousselet2016`. The complete dataset is + available at datashare.is.ed.ac.uk/. + + Parameters + ---------- + subject : int + Subject to download. Must be of :class:`ìnt` in the range from 1 + to 18 (inclusive). + path : None | str + Location of where to look for the LIMO data storing directory. + If None, the environment variable or config parameter + ``MNE_DATASETS_LIMO_PATH`` is used. If it doesn't exist, the + "~/mne_data" directory is used. If the LIMO dataset + is not found under the given path, the data + will be automatically downloaded to the specified folder. + force_update : bool + Force update of the dataset even if a local copy exists. + update_path : bool | None + If True, set the MNE_DATASETS_LIMO_PATH in mne-python + config to the given path. If None, the user is prompted. + %(verbose)s + + Returns + ------- + path : str + Local path to the given data file. + + Notes + ----- + For example, one could do: + + >>> from mne.datasets import limo + >>> limo.data_path(subject=1, path=os.getenv('HOME') + '/datasets') # doctest:+SKIP + + This would download the LIMO data file to the 'datasets' folder, + and prompt the user to save the 'datasets' path to the mne-python config, + if it isn't there already. + + References + ---------- + .. footbibliography:: + """ # noqa: E501 + import pooch + + t0 = time.time() + + downloader = pooch.HTTPDownloader(**_downloader_params()) + + # local storage patch + config_key = "MNE_DATASETS_LIMO_PATH" + name = "LIMO" + subj = f"S{subject}" + path = _get_path(path, config_key, name) + base_path = op.join(path, "MNE-limo-data") + subject_path = op.join(base_path, subj) + # the remote URLs are in the form of UUIDs: + urls = dict( + S18={ + "Yr.mat": "5cf839833a4d9500178a6ff8", + "LIMO.mat": "5cf83907e650a2001ad592e4", + }, + S17={ + "Yr.mat": "5cf838e83a4d9500168aeb76", + "LIMO.mat": "5cf83867a542b80019c87602", + }, + S16={ + "Yr.mat": "5cf83857e650a20019d5778f", + "LIMO.mat": "5cf837dc3a4d9500188a64fe", + }, + S15={ + "Yr.mat": "5cf837cce650a2001ad591e8", + "LIMO.mat": "5cf83758a542b8001ac7d11d", + }, + S14={ + "Yr.mat": "5cf837493a4d9500198a938f", + "LIMO.mat": "5cf836e4a542b8001bc7cc53", + }, + S13={ + "Yr.mat": "5cf836d23a4d9500178a6df7", + "LIMO.mat": "5cf836543a4d9500168ae7cb", + }, + S12={ + "Yr.mat": "5cf83643d4c7d700193e5954", + "LIMO.mat": "5cf835193a4d9500178a6c92", + }, + S11={ + "Yr.mat": "5cf8356ea542b8001cc81517", + "LIMO.mat": "5cf834f7d4c7d700163daab8", + }, + S10={ + "Yr.mat": "5cf833b0e650a20019d57454", + "LIMO.mat": "5cf83204e650a20018d59eb2", + }, + S9={ + "Yr.mat": "5cf83201a542b8001cc811cf", + "LIMO.mat": "5cf8316c3a4d9500168ae13b", + }, + S8={ + "Yr.mat": "5cf8326ce650a20017d60373", + "LIMO.mat": "5cf8316d3a4d9500198a8dc5", + }, + S7={ + "Yr.mat": "5cf834a03a4d9500168ae59b", + "LIMO.mat": "5cf83069e650a20017d600d7", + }, + S6={ + "Yr.mat": "5cf830e6a542b80019c86a70", + "LIMO.mat": "5cf83057a542b80019c869ca", + }, + S5={ + "Yr.mat": "5cf8115be650a20018d58041", + "LIMO.mat": "5cf80c0bd4c7d700193e213c", + }, + S4={ + "Yr.mat": "5cf810c9a542b80019c8450a", + "LIMO.mat": "5cf80bf83a4d9500198a6eb4", + }, + S3={ + "Yr.mat": "5cf80c55d4c7d700163d8f52", + "LIMO.mat": "5cf80bdea542b80019c83cab", + }, + S2={ + "Yr.mat": "5cde827123fec40019e01300", + "LIMO.mat": "5cde82682a50c4001677c259", + }, + S1={ + "Yr.mat": "5d6d3071536cf5001a8b0c78", + "LIMO.mat": "5d6d305f6f41fc001a3151d8", + }, + ) + # these can't be in the registry file (mne/data/dataset_checksums.txt) + # because of filename duplication + hashes = dict( + S18={ + "Yr.mat": "md5:87f883d442737971a80fc0a35d057e51", + "LIMO.mat": "md5:8b4879646f65d7876fa4adf2e40162c5", + }, + S17={ + "Yr.mat": "md5:7b667ec9eefd7a9996f61ae270e295ee", + "LIMO.mat": "md5:22eaca4e6fad54431fd61b307fc426b8", + }, + S16={ + "Yr.mat": "md5:c877afdb4897426421577e863a45921a", + "LIMO.mat": "md5:86672d7afbea1e8c39305bc3f852c8c2", + }, + S15={ + "Yr.mat": "md5:eea9e0140af598fefc08c886a6f05de5", + "LIMO.mat": "md5:aed5cb71ddbfd27c6a3ac7d3e613d07f", + }, + S14={ + "Yr.mat": "md5:8bd842cfd8588bd5d32e72fdbe70b66e", + "LIMO.mat": "md5:1e07d1f36f2eefad435a77530daf2680", + }, + S13={ + "Yr.mat": "md5:d7925d2af7288b8a5186dfb5dbb63d34", + "LIMO.mat": "md5:ba891015d2f9e447955fffa9833404ca", + }, + S12={ + "Yr.mat": "md5:0e1d05beaa4bf2726e0d0671b78fe41e", + "LIMO.mat": "md5:423fd479d71097995b6614ecb11df9ad", + }, + S11={ + "Yr.mat": "md5:1b0016fb9832e43b71f79c1992fcbbb1", + "LIMO.mat": "md5:1a281348c2a41ee899f42731d30cda70", + }, + S10={ + "Yr.mat": "md5:13c66f60e241b9a9cc576eaf1b55a417", + "LIMO.mat": "md5:3c4b41e221eb352a21bbef1a7e006f06", + }, + S9={ + "Yr.mat": "md5:3ae1d9c3a1d9325deea2f2dddd1ab507", + "LIMO.mat": "md5:5e204e2a4bcfe4f535b4b1af469b37f7", + }, + S8={ + "Yr.mat": "md5:7e9adbca4e03d8d7ce8ea07ccecdc8fd", + "LIMO.mat": "md5:88313c21d34428863590e586b2bc3408", + }, + S7={ + "Yr.mat": "md5:6b5290a6725ecebf1022d5d2789b186d", + "LIMO.mat": "md5:8c769219ebc14ce3f595063e84bfc0a9", + }, + S6={ + "Yr.mat": "md5:420c858a8340bf7c28910b7b0425dc5d", + "LIMO.mat": "md5:9cf4e1a405366d6bd0cc6d996e32fd63", + }, + S5={ + "Yr.mat": "md5:946436cfb474c8debae56ffb1685ecf3", + "LIMO.mat": "md5:241fac95d3a79d2cea081391fb7078bd", + }, + S4={ + "Yr.mat": "md5:c8216af78ac87b739e86e57b345cafdd", + "LIMO.mat": "md5:8e10ef36c2e075edc2f787581ba33459", + }, + S3={ + "Yr.mat": "md5:ff02e885b65b7b807146f259a30b1b5e", + "LIMO.mat": "md5:59b5fb3a9749003133608b5871309e2c", + }, + S2={ + "Yr.mat": "md5:a4329022e57fd07ceceb7d1735fd2718", + "LIMO.mat": "md5:98b284b567f2dd395c936366e404f2c6", + }, + S1={ + "Yr.mat": "md5:076c0ae78fb71d43409c1877707df30e", + "LIMO.mat": "md5:136c8cf89f8f111a11f531bd9fa6ae69", + }, + ) + # create the download manager + fetcher = pooch.create( + path=subject_path, + base_url="", + version=None, # Data versioning is decoupled from MNE-Python version. + registry=hashes[subj], + urls={key: f"{root_url}{uuid}" for key, uuid in urls[subj].items()}, + retry_if_failed=2, # 2 retries = 3 total attempts + ) + # use our logger level for pooch's logger too + pooch.get_logger().setLevel(logger.getEffectiveLevel()) + # fetch the data + sz = 0 + for fname in ("LIMO.mat", "Yr.mat"): + destination = Path(subject_path, fname) + if destination.exists(): + if force_update: + destination.unlink() + else: + continue + if sz == 0: # log once + logger.info("Downloading LIMO data") + # fetch the remote file (if local file missing or has hash mismatch) + fetcher.fetch(fname=fname, downloader=downloader) + sz += destination.stat().st_size + # update path in config if desired + _do_path_update(path, update_path, config_key, name) + if sz > 0: + _log_time_size(t0, sz) + return base_path + + +@verbose +def load_data(subject, path=None, force_update=False, update_path=None, verbose=None): + """Fetch subjects epochs data for the LIMO data set. + + Parameters + ---------- + subject : int + Subject to use. Must be of class ìnt in the range from 1 to 18. + path : str + Location of where to look for the LIMO data. + If None, the environment variable or config parameter + ``MNE_DATASETS_LIMO_PATH`` is used. If it doesn't exist, the + "~/mne_data" directory is used. + force_update : bool + Force update of the dataset even if a local copy exists. + update_path : bool | None + If True, set the MNE_DATASETS_LIMO_PATH in mne-python + config to the given path. If None, the user is prompted. + %(verbose)s + + Returns + ------- + epochs : instance of Epochs + The epochs. + """ # noqa: E501 + pd = _check_pandas_installed() + # subject in question + if isinstance(subject, int) and 1 <= subject <= 18: + subj = f"S{subject}" + else: + raise ValueError("subject must be an int in the range from 1 to 18") + + # set limo path, download and decompress files if not found + limo_path = data_path(subject, path, force_update, update_path) + + # -- 1) import .mat files + # epochs info + fname_info = op.join(limo_path, subj, "LIMO.mat") + data_info = loadmat(fname_info) + # number of epochs per condition + design = data_info["LIMO"]["design"][0][0]["X"][0][0] + data_info = data_info["LIMO"]["data"][0][0][0][0] + # epochs data + fname_eeg = op.join(limo_path, subj, "Yr.mat") + data = loadmat(fname_eeg) + + # -- 2) get epochs information from structure + # sampling rate + sfreq = data_info["sampling_rate"][0][0] + # tmin and tmax + tmin = data_info["start"][0][0] + # create events matrix + sample = np.arange(len(design)) + prev_id = np.zeros(len(design)) + ev_id = design[:, 1] + events = np.array([sample, prev_id, ev_id]).astype(int).T + # event ids, such that Face B == 1 + event_id = {"Face/A": 0, "Face/B": 1} + + # -- 3) extract channel labels from LIMO structure + # get individual labels + labels = data_info["chanlocs"]["labels"] + labels = [label for label, *_ in labels[0]] + # get montage + montage = make_standard_montage("biosemi128") + # add external electrodes (e.g., eogs) + ch_names = montage.ch_names + ["EXG1", "EXG2", "EXG3", "EXG4"] + # match individual labels to labels in montage + found_inds = [ind for ind, name in enumerate(ch_names) if name in labels] + missing_chans = [name for name in ch_names if name not in labels] + assert labels == [ch_names[ind] for ind in found_inds] + + # -- 4) extract data from subjects Yr structure + # data is stored as channels x time points x epochs + # data['Yr'].shape # <-- see here + # transpose to epochs x channels time points + data = np.transpose(data["Yr"], (2, 0, 1)) + # initialize data in expected order + temp_data = np.empty((data.shape[0], len(ch_names), data.shape[2])) + # copy over the non-missing data + for source, target in enumerate(found_inds): + # avoid copy when fancy indexing + temp_data[:, target, :] = data[:, source, :] + # data to V (to match MNE's format) + data = temp_data / 1e6 + # create list containing channel types + types = ["eog" if ch.startswith("EXG") else "eeg" for ch in ch_names] + + # -- 5) Create custom info for mne epochs structure + # create info + info = create_info(ch_names, sfreq, types).set_montage(montage) + # get faces and noise variables from design matrix + event_list = list(events[:, 2]) + faces = ["B" if event else "A" for event in event_list] + noise = list(design[:, 2]) + # create epochs metadata + metadata = {"face": faces, "phase-coherence": noise} + metadata = pd.DataFrame(metadata) + + # -- 6) Create custom epochs array + epochs = EpochsArray( + data, info, events, tmin, event_id, metadata=metadata, verbose=False + ) + epochs.info["bads"] = missing_chans # missing channels are marked as bad. + + return epochs diff --git a/mne-python/source/mne/datasets/misc/__init__.py b/mne-python/source/mne/datasets/misc/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..25377ca9cebe15850f0f751f9f39e1ce51b458ad --- /dev/null +++ b/mne-python/source/mne/datasets/misc/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""MNE misc dataset.""" + +from ._misc import data_path, _pytest_mark diff --git a/mne-python/source/mne/datasets/misc/_misc.py b/mne-python/source/mne/datasets/misc/_misc.py new file mode 100644 index 0000000000000000000000000000000000000000..ba7fd2341b11eb6e88d9bad6a6a8016f12a2193f --- /dev/null +++ b/mne-python/source/mne/datasets/misc/_misc.py @@ -0,0 +1,31 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, has_dataset + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="misc", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +def _pytest_mark(): + import pytest + + return pytest.mark.skipif( + not has_dataset(name="misc"), reason="Requires misc dataset" + ) + + +data_path.__doc__ = _data_path_doc.format(name="misc", conf="MNE_DATASETS_MISC_PATH") diff --git a/mne-python/source/mne/datasets/mtrf/__init__.py b/mne-python/source/mne/datasets/mtrf/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..13828c026a889295aa56007c4aae4adec06588e1 --- /dev/null +++ b/mne-python/source/mne/datasets/mtrf/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""mTRF Dataset.""" + +from .mtrf import data_path, get_version diff --git a/mne-python/source/mne/datasets/mtrf/mtrf.py b/mne-python/source/mne/datasets/mtrf/mtrf.py new file mode 100644 index 0000000000000000000000000000000000000000..78c50027f435b4088722654d7cdf27ef6c8a7c2c --- /dev/null +++ b/mne-python/source/mne/datasets/mtrf/mtrf.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + +data_name = "mtrf" + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name=data_name, + processor="unzip", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format(name=data_name, conf="MNE_DATASETS_MTRF_PATH") + + +def get_version(): # noqa: D103 + return _get_version(data_name) + + +get_version.__doc__ = _version_doc.format(name=data_name) diff --git a/mne-python/source/mne/datasets/multimodal/__init__.py b/mne-python/source/mne/datasets/multimodal/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7bc3e5571a569c17de48e0b4230b0d6953ff827f --- /dev/null +++ b/mne-python/source/mne/datasets/multimodal/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Multimodal dataset.""" + +from .multimodal import data_path, get_version diff --git a/mne-python/source/mne/datasets/multimodal/multimodal.py b/mne-python/source/mne/datasets/multimodal/multimodal.py new file mode 100644 index 0000000000000000000000000000000000000000..60aa7d21bfce5c7ee181db91467af0c784bcb246 --- /dev/null +++ b/mne-python/source/mne/datasets/multimodal/multimodal.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="multimodal", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="multimodal", conf="MNE_DATASETS_MULTIMODAL_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("multimodal") + + +get_version.__doc__ = _version_doc.format(name="multimodal") diff --git a/mne-python/source/mne/datasets/opm/__init__.py b/mne-python/source/mne/datasets/opm/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a587c5f10069e261edbaad4c3f10d1c3a603ba41 --- /dev/null +++ b/mne-python/source/mne/datasets/opm/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""OPM dataset.""" + +from .opm import data_path, get_version diff --git a/mne-python/source/mne/datasets/opm/opm.py b/mne-python/source/mne/datasets/opm/opm.py new file mode 100644 index 0000000000000000000000000000000000000000..a5245ea02d80c9a10f06ab2eec3bea8a6a962c75 --- /dev/null +++ b/mne-python/source/mne/datasets/opm/opm.py @@ -0,0 +1,30 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="opm", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format(name="opm", conf="MNE_DATASETS_OPML_PATH") + + +def get_version(): # noqa: D103 + return _get_version("opm") + + +get_version.__doc__ = _version_doc.format(name="opm") diff --git a/mne-python/source/mne/datasets/phantom_4dbti/__init__.py b/mne-python/source/mne/datasets/phantom_4dbti/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c5426171998f38e30703e5609482804357fe97f2 --- /dev/null +++ b/mne-python/source/mne/datasets/phantom_4dbti/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Multimodal dataset.""" + +from .phantom_4dbti import data_path, get_version diff --git a/mne-python/source/mne/datasets/phantom_4dbti/phantom_4dbti.py b/mne-python/source/mne/datasets/phantom_4dbti/phantom_4dbti.py new file mode 100644 index 0000000000000000000000000000000000000000..59906a9c1107cf316d2e86e2dbc0dc28cc82ecf8 --- /dev/null +++ b/mne-python/source/mne/datasets/phantom_4dbti/phantom_4dbti.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="phantom_4dbti", + processor="unzip", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="phantom_4dbti", conf="MNE_DATASETS_PHANTOM_4DBTI_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("phantom_4dbti") + + +get_version.__doc__ = _version_doc.format(name="phantom_4dbti") diff --git a/mne-python/source/mne/datasets/phantom_kernel/__init__.py b/mne-python/source/mne/datasets/phantom_kernel/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ad4aecf0ff8785a58661ec516cf563d81cca2e02 --- /dev/null +++ b/mne-python/source/mne/datasets/phantom_kernel/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Multimodal dataset.""" + +from .phantom_kernel import data_path, get_version diff --git a/mne-python/source/mne/datasets/phantom_kernel/phantom_kernel.py b/mne-python/source/mne/datasets/phantom_kernel/phantom_kernel.py new file mode 100644 index 0000000000000000000000000000000000000000..ed44a78977b5f4e8689de30c74e5c5ffbf030fa4 --- /dev/null +++ b/mne-python/source/mne/datasets/phantom_kernel/phantom_kernel.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="phantom_kernel", + processor="nested_untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="phantom_kernel", conf="MNE_DATASETS_PHANTOM_KERNEL_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("phantom_kernel") + + +get_version.__doc__ = _version_doc.format(name="phantom_kernel") diff --git a/mne-python/source/mne/datasets/phantom_kit/__init__.py b/mne-python/source/mne/datasets/phantom_kit/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7fcc361e073dc8959fc0d0d8be1db8f8752c5bc8 --- /dev/null +++ b/mne-python/source/mne/datasets/phantom_kit/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""KIT phantom dataset.""" + +from .phantom_kit import data_path, get_version diff --git a/mne-python/source/mne/datasets/phantom_kit/phantom_kit.py b/mne-python/source/mne/datasets/phantom_kit/phantom_kit.py new file mode 100644 index 0000000000000000000000000000000000000000..150e08dc435280a12cc38d7fd7e2a16c79bb0bde --- /dev/null +++ b/mne-python/source/mne/datasets/phantom_kit/phantom_kit.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="phantom_kit", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="phantom_kit", conf="MNE_DATASETS_PHANTOM_KIT_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("phantom_kit") + + +get_version.__doc__ = _version_doc.format(name="phantom_kit") diff --git a/mne-python/source/mne/datasets/refmeg_noise/__init__.py b/mne-python/source/mne/datasets/refmeg_noise/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7437aaad6a34131adb894bce4ef7e6ebedbd52cf --- /dev/null +++ b/mne-python/source/mne/datasets/refmeg_noise/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""MEG reference-noise data set.""" + +from .refmeg_noise import data_path, get_version diff --git a/mne-python/source/mne/datasets/refmeg_noise/refmeg_noise.py b/mne-python/source/mne/datasets/refmeg_noise/refmeg_noise.py new file mode 100644 index 0000000000000000000000000000000000000000..c6c24ff3942303faba649cff89d656b2897233d0 --- /dev/null +++ b/mne-python/source/mne/datasets/refmeg_noise/refmeg_noise.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="refmeg_noise", + processor="unzip", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="refmeg_noise", conf="MNE_DATASETS_REFMEG_NOISE_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("refmeg_noise") + + +get_version.__doc__ = _version_doc.format(name="refmeg_noise") diff --git a/mne-python/source/mne/datasets/sample/__init__.py b/mne-python/source/mne/datasets/sample/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2c465adb13c5bfef328aa622f0ece0f162bee447 --- /dev/null +++ b/mne-python/source/mne/datasets/sample/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""MNE sample dataset.""" + +from .sample import data_path, get_version diff --git a/mne-python/source/mne/datasets/sample/sample.py b/mne-python/source/mne/datasets/sample/sample.py new file mode 100644 index 0000000000000000000000000000000000000000..8dde8c67047754280d5813ce770df048664a8fe5 --- /dev/null +++ b/mne-python/source/mne/datasets/sample/sample.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="sample", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="sample", conf="MNE_DATASETS_SAMPLE_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("sample") + + +get_version.__doc__ = _version_doc.format(name="sample") diff --git a/mne-python/source/mne/datasets/sleep_physionet/SHA1SUMS b/mne-python/source/mne/datasets/sleep_physionet/SHA1SUMS new file mode 100644 index 0000000000000000000000000000000000000000..1edcecce0743d2f07d05fdc335f005a4cee2b28c --- /dev/null +++ b/mne-python/source/mne/datasets/sleep_physionet/SHA1SUMS @@ -0,0 +1,394 @@ +adabd3b01fc7bb75c523a974f38ee3ae4e57b40f SC4001E0-PSG.edf +21c998eadc8b1e3ea6727d3585186b8f76e7e70b SC4001EC-Hypnogram.edf +c6b6d7a8605cc7e7602b6028ee77f6fbf5f7581d SC4002E0-PSG.edf +386230188a3552b1fc90bba0fb7476ceaca174b6 SC4002EC-Hypnogram.edf +4d17451f7847355bcab17584de05e7e1df58c660 SC4011E0-PSG.edf +d582a3cbe2db481a362af890bc5a2f5ca7c878dc SC4011EH-Hypnogram.edf +a47d525f5147904b6890231e2ad338359c7ab94c SC4012E0-PSG.edf +fa99f60d7f54617cdd1128aff4f21c4daed763c7 SC4012EC-Hypnogram.edf +8b135afa7fb93bb5f1998fda50355944777c245e SC4021E0-PSG.edf +91043cfe46695088b17b6a02937b25efd674c3fb SC4021EH-Hypnogram.edf +d739e142b3b328c71b4752149901805dcd6d7e19 SC4022E0-PSG.edf +0c46a03699dd00e8f92a7edff99ebc4642cb3d48 SC4022EJ-Hypnogram.edf +85e58dc1e3303537dade8c5827ab58328239c384 SC4031E0-PSG.edf +6363d8b0fdc48cf396c9abf054bb4a9696d38bdb SC4031EC-Hypnogram.edf +43963d300642b3aa840e8c468f321b8162601772 SC4032E0-PSG.edf +7925514bc8d2ef3f1103130f08f7b3afd2136b88 SC4032EP-Hypnogram.edf +04d2b88d25f2ae4a65ba44cd9145bd12800a0e20 SC4041E0-PSG.edf +f148821669bd3588187b3b430bd79adf569f86d1 SC4041EC-Hypnogram.edf +76253d964d7797540ffd791e6e136023ed67a485 SC4042E0-PSG.edf +9873df429f971f8a4b720a454f6c0472b8a25ebb SC4042EC-Hypnogram.edf +ea073451b65ce8a6f1a02a8cc2b89d1a162ca0ae SC4051E0-PSG.edf +4159ef8a3e119d6dcc1bede806f6fbc017b27a0f SC4051EC-Hypnogram.edf +5a2efbd21be9b745fd534394eb2503caca7dc53f SC4052E0-PSG.edf +0e96482d44762df4da65dc4fdb970b342264d22a SC4052EC-Hypnogram.edf +1736736e585807c14f1ae8bc87a94cae222c5170 SC4061E0-PSG.edf +4bf99622c67c281b25ceccd35e7050328a2946e8 SC4061EC-Hypnogram.edf +763c7ac059f1771a0165e5cb351b176afb1cfe15 SC4062E0-PSG.edf +14f07411cd04d3b4b522d37c129334955287ff5f SC4062EC-Hypnogram.edf +1374b34f6139b6ff7e865d8243eef39ba334ef50 SC4071E0-PSG.edf +608024fd19a140ad233a4680e07c2495a74b69c2 SC4071EC-Hypnogram.edf +1c570644243d79396df612fa2b9bc027b24430e4 SC4072E0-PSG.edf +a8da6c20b9b48189f05ab537886b59dd141374d2 SC4072EH-Hypnogram.edf +0e1cc2c4e1da14ab94515e3e7e75e8ad30ec99cb SC4081E0-PSG.edf +9ec663ffa5c17afcaca59d7829d77b9165102237 SC4081EC-Hypnogram.edf +d57d4aa7cbc5045f611a3a3e342b501e086ea426 SC4082E0-PSG.edf +d43c785dba43063d7baa332671c6bac9c832b5b7 SC4082EP-Hypnogram.edf +b3502e0bd54683e973182c791aa962b804e79633 SC4091E0-PSG.edf +7aa63b408c769a4a983a908b6ba41d87dd743c6e SC4091EC-Hypnogram.edf +246e35852119b33d197db2f7bcfb1b46a5270a03 SC4092E0-PSG.edf +9d85766a83231b1c6076cb293367ccc354c57eeb SC4092EC-Hypnogram.edf +3ae168ff2c9c0c56f51205fdb10f05a4c6b2064e SC4101E0-PSG.edf +60d9c3913881e11b06ad99e9870bd1ca4d93c952 SC4101EC-Hypnogram.edf +86f307190961eaab0214fdc0213f8fe05812c7a5 SC4102E0-PSG.edf +8072e2d52bc6c19b45fbd921550e5243bc5a1de7 SC4102EC-Hypnogram.edf +e490956b4dce01c46ba88a2b847f091bb54ea16e SC4111E0-PSG.edf +12db1920e2f6083c8ab1f2c24fe35dfa03715e4a SC4111EC-Hypnogram.edf +ca24dc464df61144627588b29d35a85fcc7ac984 SC4112E0-PSG.edf +54dbc39015b0a445b51189987a00e08cc27d8f0c SC4112EC-Hypnogram.edf +33c72025a7a215ea5e255f4254cb0f93b1313369 SC4121E0-PSG.edf +daa57ece807cb5325c6d1ce059f0e8a8d1c85391 SC4121EC-Hypnogram.edf +34f5145ab62dcc5a53ba18735519e5bb2b13841a SC4122E0-PSG.edf +b7af1a32d8ca15e8185e4c94213ffc18ad7f6e8a SC4122EV-Hypnogram.edf +42ff97035aae6dd34ca9437857c48ac6f2ab97df SC4131E0-PSG.edf +5beef85170bdbb5cf2eea24a79f0f5c2c3975c4b SC4131EC-Hypnogram.edf +83493e1c32d441c9e5ee3de6a024bfb5e7ab9f5f SC4141E0-PSG.edf +511d398f22b9b2b304de27c40740a41584ff6af2 SC4141EU-Hypnogram.edf +63d13828b7ebe0d2ed7f491d2b5520e928b9b55d SC4142E0-PSG.edf +6f123e6fdc90a01b83e694d9744a6d27f3c87b25 SC4142EU-Hypnogram.edf +5a92d49699d4de369d66d9462e91b0dcb3312649 SC4151E0-PSG.edf +37dcbd339c95322d028b3a5466812697041cc373 SC4151EC-Hypnogram.edf +778626489bc4fe2c9137d2d361876d97dce97e5e SC4152E0-PSG.edf +294cdc47cd3d165031f7041c17f18dd013d216cb SC4152EC-Hypnogram.edf +e56ff3aa366fe9a04a0fdfdd4cd862e77e8ac807 SC4161E0-PSG.edf +56711b1bfed292032491f5cce57494629286a131 SC4161EC-Hypnogram.edf +722692f9940f3a1bccb9b4488c4477edf7fb128f SC4162E0-PSG.edf +c85647fb4bc1f382fe46bf9aaf579dc483115885 SC4162EC-Hypnogram.edf +f1a65522cb7d6c71ac47742535a12c88e2019dad SC4171E0-PSG.edf +dd257c8d922f08c2c8ca5236c9bf54da887c68e5 SC4171EU-Hypnogram.edf +572b81bc24c2c9482e6fc7ba9202a7bf253655e1 SC4172E0-PSG.edf +c9a3b590748d7d6c7ad97c62222bd53d8ebaf630 SC4172EC-Hypnogram.edf +23674d20572853eb6d988d24378c52123f66500c SC4181E0-PSG.edf +51fc3df2df7d4da654f3e18ed1b233d0c60cfa80 SC4181EC-Hypnogram.edf +83e8cbe882ba863da9fd3c11393c95b6fec5b7a5 SC4182E0-PSG.edf +43c487955edddb4ee2f60193a097c68c25c5dd4d SC4182EC-Hypnogram.edf +d6da621dbb20dec3494a38c7d2a0363793ac5ebe SC4191E0-PSG.edf +defc7b9368c2d3c4ab4a294757843825a83cdb5d SC4191EP-Hypnogram.edf +941353118732321d0246a1d58d72e903bd2f0d8f SC4192E0-PSG.edf +97b91b3067c5ecde766042fc2cff9e22f8023371 SC4192EV-Hypnogram.edf +38a0be6e45ddd9b1f17d09964a32e005dc5a6519 SC4201E0-PSG.edf +83822f9970d3959ad2e0613492ae39bd0fae6068 SC4201EC-Hypnogram.edf +aa69f5bd47c2ae03c9d38bfe6d0e58408744b885 SC4202E0-PSG.edf +5c5c63016b43421a523d1efcb34247e90aa6318b SC4202EC-Hypnogram.edf +c106ad072dbc975a3742f7eff151219870f0c794 SC4211E0-PSG.edf +9126937ea8a414d6ae9bc4a4194d841a891fa8a8 SC4211EC-Hypnogram.edf +a06ecb3f0a7b2c306f5ae4dbd83685f877cd945b SC4212E0-PSG.edf +a85f178b69a1cda47d11dd1e5394dfdcb58de1d4 SC4212EC-Hypnogram.edf +8733ea022d3778259a436507156cf3360ad8be06 SC4221E0-PSG.edf +b158eda4f81772095c129be77f8e60ec9d81b884 SC4221EJ-Hypnogram.edf +211410fab6381da0dfaef4134d5a05eec935a4ec SC4222E0-PSG.edf +1488fbfbc149499dafa8dafff4f7504053af429f SC4222EC-Hypnogram.edf +d96f1f35b2f77c7de706036c6e4114139e07b307 SC4231E0-PSG.edf +9f6df70676d6cddcf069ceb7f408a7989af99ce2 SC4231EJ-Hypnogram.edf +6b493fa424c1329ea1c13543d08ba82a9f1e85b6 SC4232E0-PSG.edf +d8ca7d694b3c48ab9d983b9cf67e17744c6b50fb SC4232EV-Hypnogram.edf +58719e53fe18d2fc4cb1776ab5d43306beb1325d SC4241E0-PSG.edf +fb1432e303a8f99a2256ce682db95d88772c479f SC4241EC-Hypnogram.edf +5a6277972c5f03572ed99d9ff63fb637945be778 SC4242E0-PSG.edf +bbbf097f4cc6560fc20c903fba2c7055e1549f85 SC4242EA-Hypnogram.edf +7dbc0289707ff70662d367d65de7bec188484d1b SC4251E0-PSG.edf +e38be8134e4a36eb418ca1f06a1fe02b52d0ebf1 SC4251EP-Hypnogram.edf +cb3922910ea03d06c1fc5c8f15b71339dc26bc9d SC4252E0-PSG.edf +4cb7a383736e09125a82ef7e4f17b41130c7ac00 SC4252EU-Hypnogram.edf +b81c9bd1875b33713b5eb56b58f1e120841b507f SC4261F0-PSG.edf +501eda59557bb99d530d01bdad3579f1e1158991 SC4261FM-Hypnogram.edf +c9f9ad7cd751d5be91396886a2b64a7c1de564ee SC4262F0-PSG.edf +7ccd12803c5fc602ac1929ff3afd914b894b9143 SC4262FC-Hypnogram.edf +20994715d34edb26113180ee330ce287dbf57b60 SC4271F0-PSG.edf +26c5c7f3a5c350d3505af2857835ce81252c5990 SC4271FC-Hypnogram.edf +9e79eb465e34b7eb6fe27ae3ce35d28d6693d44b SC4272F0-PSG.edf +956fe4b45d29a8999faf280a6168e332afab6abc SC4272FM-Hypnogram.edf +51811913d7854f95c319076e670d988687ca667c SC4281G0-PSG.edf +d188150831e912081dbeda2695231177200c39f9 SC4281GC-Hypnogram.edf +e9f080a766a9b7a247f228e44e9c4ec67e571c95 SC4282G0-PSG.edf +12d777787dd1975eef9015329fd774b2bfa1d53a SC4282GC-Hypnogram.edf +f81c7574a5e5829e006d0b705bf5208a3349c9c7 SC4291G0-PSG.edf +577c1345f6d070d975db5016048722f78b1b414e SC4291GA-Hypnogram.edf +7416f44a3b149b4ca1fc3e53d546a093a7333bb5 SC4292G0-PSG.edf +6e111a15160a31609761f742315df800b1311b3b SC4292GC-Hypnogram.edf +7818e5a02afa89e913111d91ecd651aa3e786e5d SC4301E0-PSG.edf +d49df84bfea28bb241c09b922cd2dc64f57c5ae5 SC4301EC-Hypnogram.edf +d52859ba6a7ded3364b0d8ef2b722e1d3edda060 SC4302E0-PSG.edf +b3d6f687831ee32f6df1da59f2d568c13f9c09d0 SC4302EV-Hypnogram.edf +b62f5104bddf452f4700c85997e51bec17f0243b SC4311E0-PSG.edf +812c34844e834b97949019741fa7f835d973725d SC4311EC-Hypnogram.edf +b0a9b4922665734773abbaba06e7aab32010b862 SC4312E0-PSG.edf +fca1935a8974eac27803e3125cea177995deca11 SC4312EM-Hypnogram.edf +335381ae310e9f1f053c37763eeee74d7d873471 SC4321E0-PSG.edf +67ba7d3b97354deb31db095e748ea3a4014fae2c SC4321EC-Hypnogram.edf +c9fdcfcce7e603b3289b7417891987fd67f6d921 SC4322E0-PSG.edf +40cf9a6397a52c7deda693ca596e928cc2b9f4e9 SC4322EC-Hypnogram.edf +f37cb4df27286e38c604cae943169ff29b1473fc SC4331F0-PSG.edf +ca943e2b73c6404f929c372ebd817b7b3b71b4dd SC4331FV-Hypnogram.edf +5bce6ea9b2d6c9bfb41065e92bf9cc05a11b5b75 SC4332F0-PSG.edf +e4595b0313d5320b0bffefa43260485e19977e3c SC4332FC-Hypnogram.edf +17de25c8f023fe632aa403a6d9525c1cde8eaef5 SC4341F0-PSG.edf +81ba3c0d8320c9ee306f678b4bc9e6e266165886 SC4341FA-Hypnogram.edf +b659037447a1871f4ba72bbe496cfbe507330530 SC4342F0-PSG.edf +e8e74c0905e89a59022ce0814ca9a050748ec9ae SC4342FA-Hypnogram.edf +631900bef36d359a0f5807a7e1b202f80b0427ac SC4351F0-PSG.edf +a15cdf3973b77198d8276dc505dbb35cb39a9b4a SC4351FA-Hypnogram.edf +325423a85890dcc921253bde7c7027d66f14033e SC4352F0-PSG.edf +1e0583b2a58432c964506ff44752d597753658c9 SC4352FV-Hypnogram.edf +30b90aaf965938d569ea362f66e2afa0c08c7017 SC4362F0-PSG.edf +fb870d50ce3f4d961d8b061a83d21e5467e4ae6c SC4362FC-Hypnogram.edf +0dc56fce13b6317f197d0b17c04f5be4af1c964f SC4371F0-PSG.edf +c19b6cbfdf3a33169ce9b4a5dc94f93b696a21ba SC4371FA-Hypnogram.edf +c024c491dd836ed0169300e7171c276fd14b1c44 SC4372F0-PSG.edf +97b2915a8a343efc7b785998c0532beaea2fbe91 SC4372FC-Hypnogram.edf +6098d2b501b82ca0ddc8893547c6990e204e8ba6 SC4381F0-PSG.edf +fdbf653a4a675843c97d0a76ef5e4cebf5d2dbcb SC4381FC-Hypnogram.edf +40ce0168d5f546fcd445996ab614f43823a7c2b1 SC4382F0-PSG.edf +796f8507254c2d8d345171c077dbd855e112eb47 SC4382FW-Hypnogram.edf +28fd8ad1aee307847e2eb579763ebca18e56f540 SC4401E0-PSG.edf +65b5671a89871351ee3da7ea800aad276a445b2a SC4401EC-Hypnogram.edf +3d4bafa57933cfb20c342e8cc54c15916a621454 SC4402E0-PSG.edf +037efea0fc8a6dfa8f85fa1f2fa6fd9a19f2c830 SC4402EW-Hypnogram.edf +30a533b67fdb2adac6a4e83088a07fe1bbaddb6c SC4411E0-PSG.edf +5df1bf20d4f29b95a2bdde853b2a157dd9530a8a SC4411EJ-Hypnogram.edf +bc8e6ea829f14da5396a4b250394c1b72d6631c3 SC4412E0-PSG.edf +f46b1dcfe4f4e3c9d4d4c8516dab9759f9c1224e SC4412EM-Hypnogram.edf +e8a5d9e0f160ae7bd0b35d75d77b4c872daa30f8 SC4421E0-PSG.edf +d2e34f9bcaac7af23da4448f742ac6ea3c895ed9 SC4421EA-Hypnogram.edf +80f246adffb92a3785f91368a77b0250aa040462 SC4422E0-PSG.edf +709251cc7ae6556544c153caf9dac7f82bba113b SC4422EA-Hypnogram.edf +194ae942cf80764e81b4cdabeed9e5a57916aab3 SC4431E0-PSG.edf +497ad7e671edab6e7adc9d35a6aa45b7fd9a706b SC4431EM-Hypnogram.edf +c45a66d27ea03bf448903fe30f17838e9a0fa0de SC4432E0-PSG.edf +10fe276e215f9406c0ddedaa48651cf480892476 SC4432EM-Hypnogram.edf +e3a09d832cb79b0095d7a311ef1b6ed7c569b79d SC4441E0-PSG.edf +68d4e44ad54069701972df66d8a81b4ca434bf2f SC4441EC-Hypnogram.edf +fe51d45e9f3e64a61fa8a5e5274b2e4951a9de43 SC4442E0-PSG.edf +efc2b86bb796b0143f61667402612dfbb85cbb78 SC4442EV-Hypnogram.edf +315db0f9d91988ddc2b198f89cc22f96190eff71 SC4451F0-PSG.edf +bc1f755c3367e378091c44481948a72fc7a928e5 SC4451FY-Hypnogram.edf +a06350e1c85b61c30c3d7d5dc640121b416fe30d SC4452F0-PSG.edf +0286d52cdf898ed8e3b17bb26b9c50ef512daf4d SC4452FW-Hypnogram.edf +e4295014c6d4474d8f7f7792c2ea088eb9e43e9f SC4461F0-PSG.edf +8980e770e58e5704bd36124f6b6bd8d5e3506e12 SC4461FA-Hypnogram.edf +53b69cb41339bc69144eaa5a5a42c2937f237fc9 SC4462F0-PSG.edf +0c6d3974e140c1e62ed2cadaed395781575af042 SC4462FJ-Hypnogram.edf +05d71b55de4c86791195391b1cec8b35e447922d SC4471F0-PSG.edf +ee235454dbfe947432f3f813c9a6384f6e42d36a SC4471FA-Hypnogram.edf +7a12c0d6f3005998472b128e06dd645a8619dae7 SC4472F0-PSG.edf +d234d5d6c396bf7ef0a2106a59ee8204429aa3c5 SC4472FA-Hypnogram.edf +c15f6a0e1802dcf74ecec41745677a4932375faf SC4481F0-PSG.edf +50fce6396aceaf35d9d7e16175053a3b78f214d0 SC4481FV-Hypnogram.edf +34d71530fd1da925ba20b4c48a07f7b18153e0c7 SC4482F0-PSG.edf +e3c48563e63eed27b071d4a7b37c45a0f9dc7eef SC4482FJ-Hypnogram.edf +23ea1f5f299c6cd99d434f014d7490621dbbc854 SC4491G0-PSG.edf +36c6c8112524c7bc9553db37601b38984946209b SC4491GJ-Hypnogram.edf +02c975bfc0773928095239b80d00ac5a7ea5880f SC4492G0-PSG.edf +3673eaad8396ef0ec36cb4299541c30653b72e1f SC4492GJ-Hypnogram.edf +1c31fc02412029bc7369979b8c9f5956420748f5 SC4501E0-PSG.edf +eb2621c1670a42eb38dfa86a9bc3326818365f3d SC4501EW-Hypnogram.edf +ff9eae25afa73115e2b184a68e3a72a39efd37e6 SC4502E0-PSG.edf +7605a1893701925ea0fdd047926bbd6c7c043875 SC4502EM-Hypnogram.edf +e12eb259c2894d45b8d0b2f0e75810c2de02237d SC4511E0-PSG.edf +e549275e9182b9e36ade5abb721098e235ecb164 SC4511EJ-Hypnogram.edf +53c5d982139d248736f6dd7ff3f97f635647eacd SC4512E0-PSG.edf +e22966c263f6ae7444704881f5249f6fb5dee0c1 SC4512EW-Hypnogram.edf +af70ffdbd3012615923f6a4901e7c0dd3a0fd8ca SC4522E0-PSG.edf +57af3eaed541229dcb2478c6050f0582e020f878 SC4522EM-Hypnogram.edf +71222ac5b7784ed1d3a79ee3e9036431d6eba9bd SC4531E0-PSG.edf +934dbfeb29f4f4db4b61e36fb8ddab4ddbf4ff94 SC4531EM-Hypnogram.edf +2d472fb64da5d05a546f780da876b90ad26208f9 SC4532E0-PSG.edf +708b43e7d43a6f5719f48c11bd6a81b037aabfc4 SC4532EV-Hypnogram.edf +4d3ec2f85149bb10fed1013831c3aa1f58049229 SC4541F0-PSG.edf +a301385e6fbde02c83f2545f17cdf75d594d37ce SC4541FA-Hypnogram.edf +2909f5b0d3fdb89e19d42b406798e9cbb4615bb6 SC4542F0-PSG.edf +9548ed641fb961fa46706339891a9453b731369f SC4542FW-Hypnogram.edf +0bf97e463cbcefb7df48bca712f29dcc74223330 SC4551F0-PSG.edf +e50b44e6b049baaeb528c31563642b2a2b933834 SC4551FC-Hypnogram.edf +dfa0adaae50110bdd0077483c31d57956020fcb9 SC4552F0-PSG.edf +7380403f8d72fa4c30013cd026cc1dad23ac2b3e SC4552FW-Hypnogram.edf +1a9baf1b072ca9d2784a404292169ff3177ea83f SC4561F0-PSG.edf +b31a2dfe652508df46f6afe03ab904c333f7b818 SC4561FJ-Hypnogram.edf +4c7081edf572cadee51d30174cd65aa6c658f5a9 SC4562F0-PSG.edf +676ab92dbc6532f67d672f80337c71f817fd3a6d SC4562FJ-Hypnogram.edf +e67f3bd381ddfb96d584f6c6d6f6762087d6553d SC4571F0-PSG.edf +08ee39eb94d819968512297ca883f9bca046de9c SC4571FV-Hypnogram.edf +deb2aef7a6a4b502c819345a7151ffc2529d4ba7 SC4572F0-PSG.edf +7a38cbe581167dfec27a15935e6d386b228616fa SC4572FC-Hypnogram.edf +16a1edbd6a089386fd7de72aef802182d0a2959d SC4581G0-PSG.edf +bfc729575cfdf5f409be2de47dad4e00d43195bf SC4581GM-Hypnogram.edf +9da93f4c2459dd4fe2e5ee6a171904d4f604cd6e SC4582G0-PSG.edf +acbade13cfae4fc5fbda2d0766feea83d114aa23 SC4582GP-Hypnogram.edf +017793b040df8a860df0e43e3e0a496e2cb3f9c1 SC4591G0-PSG.edf +f3bb949a7f82acb7fd3d8f35e92efee1402a383f SC4591GY-Hypnogram.edf +1e284bddd7952862327c83092db21805e6ab6c38 SC4592G0-PSG.edf +58d1678e9ec9f49c9c6a15031dee26d802026851 SC4592GY-Hypnogram.edf +ece6d6ce09fac6fc521cf3f1b536f1ea2a8a1778 SC4601E0-PSG.edf +8f77b05fe58f43cdfdcdba7cc3d27abcac7d37f2 SC4601EC-Hypnogram.edf +0e50df304ced29651267f43689ce49e063f808d6 SC4602E0-PSG.edf +1c52de92668fe4c89cd5e270e17017ef47880991 SC4602EJ-Hypnogram.edf +2cc6e418c0b7af472aa34d2bbd5ece85bdb6a879 SC4611E0-PSG.edf +f5715ab48f24221c28c1d5c45508c8bb58c912ec SC4611EG-Hypnogram.edf +6593e1af07101fa4c5bce8984296858be17e7d4f SC4612E0-PSG.edf +cedb61bbe7a273b12f45579963d5a84f2ab21811 SC4612EA-Hypnogram.edf +31cd2cae56977c6b872311f2a6e60827748b973d SC4621E0-PSG.edf +7acc5296b33ca4eee8d6577064c8c651ee96e527 SC4621EV-Hypnogram.edf +7a7e226d47dccd959305e3f633686335c8e66557 SC4622E0-PSG.edf +9957c9c9e0c705aac0f7125f411b2531a722601c SC4622EJ-Hypnogram.edf +6dfb32aa4c94968a52d61b90a38573d178669bfb SC4631E0-PSG.edf +48e28f93fc71ffc539776196f9d9d1365415e0b4 SC4631EM-Hypnogram.edf +3baa8081b30cc3dfece9d550289dfc94812530d5 SC4632E0-PSG.edf +cd2765ebdabc66cb4ac2320d02e3b7ab0340ede4 SC4632EA-Hypnogram.edf +0e5d109a929490cbecf59573577a97df07a05cd0 SC4641E0-PSG.edf +7b896dc5b34d71381d8462001dc3e05b145cf48c SC4641EP-Hypnogram.edf +03169b7ee9de83b2e17e9bd0d6274965e9518b37 SC4642E0-PSG.edf +d8a870d26e468a643eaebe3275e5e2912690c0d8 SC4642EP-Hypnogram.edf +f2134a2ad001bc146f3e2d9d76cb7f00f03bbe52 SC4651E0-PSG.edf +fad4311c7e11a9aa9a73a8e48d6fa966db61e71d SC4651EP-Hypnogram.edf +aa66553cb0132634d7d11ffe7fab80aa5119b3d7 SC4652E0-PSG.edf +6ed9c4f66c03e56f86730ddd8986f3600c040d4a SC4652EG-Hypnogram.edf +c6057505d2acf7b08371e266cf0fca1bfeb1e4e1 SC4661E0-PSG.edf +06474e72126d2a00c1968e70730e1deac060f94e SC4661EJ-Hypnogram.edf +24d278194360dc78ebd0cfe940fb4d5f7f93ccbc SC4662E0-PSG.edf +07ca0fbfb6030289a089f84e50d7bbfd043f31ad SC4662EJ-Hypnogram.edf +4357aa9fedf0b53896d41e5dccd7b525f7212177 SC4671G0-PSG.edf +459889157743c434933194446af5168cb145dfcb SC4671GJ-Hypnogram.edf +fd86b31a5c22176e1887e2fac460edce42bd2fdf SC4672G0-PSG.edf +dedb182b8c063cefabf1763eb19cd26d0608017f SC4672GV-Hypnogram.edf +3f60b5ad5e1092e90c38f2072b3c041bd7313550 SC4701E0-PSG.edf +196a388f60ee4aecfa982f89e2db03ff91e906e7 SC4701EC-Hypnogram.edf +a6853fee26b1541f85be7ddc3f42f06ccfe2fcfc SC4702E0-PSG.edf +464f7382ec11703b5bc6512930fdfbb1ab6d030a SC4702EA-Hypnogram.edf +e97d691bfecf770ca4e47289b846886c16ef19fb SC4711E0-PSG.edf +81ec5d0288f36c4368e5f06f21980f99774bf533 SC4711EC-Hypnogram.edf +9b99be6cb45af22bdbead7ea01f1375631c9b365 SC4712E0-PSG.edf +66b121441a45ae19852b7002fd78c2caf236631a SC4712EA-Hypnogram.edf +5c9caa01cc1f8065f87195c9f2dc2aeebf83c03d SC4721E0-PSG.edf +efe62b1e8bac1ea08dbf12374ca6812a6f271d5e SC4721EC-Hypnogram.edf +a473f32a6075e9ed830a8e9a246129e05959e8b7 SC4722E0-PSG.edf +efb2358de27da4219f64f7bfb37912dc9efb0281 SC4722EM-Hypnogram.edf +b03e4a2df4d086778f3426ed7b6c5bf800cbfe92 SC4731E0-PSG.edf +eb3dc65d7184d676a6678a70b18730d11a414588 SC4731EM-Hypnogram.edf +574ff5c0634137f7d5c51eb5f7626b451f1f9b9d SC4732E0-PSG.edf +77a523ca9ef4698885b681bf4e27d28dc5c58424 SC4732EJ-Hypnogram.edf +e6ff7462f4ce401e9aff9b3d9c93f0710bc37678 SC4741E0-PSG.edf +bda4d1ab190f4160ec7a3f4420e30d718f02369e SC4741EA-Hypnogram.edf +2b09f78a2f276061c8758a55585fae7355b38111 SC4742E0-PSG.edf +d4bb4266859c2f92ae8ba96111d59d8ab467f6a0 SC4742EC-Hypnogram.edf +17c356a283b026e507331209512453573bcfebe5 SC4751E0-PSG.edf +d35737e86979127ea01b95dcecea018dd2e44f45 SC4751EC-Hypnogram.edf +b650a49d6e3bb81971e4689c720ee079404857e6 SC4752E0-PSG.edf +3d1c86d8d7ecb6ff79ee12cb950690e929394161 SC4752EM-Hypnogram.edf +8bde3f0d5ab6a592f229dfd7886341b3f800bdb3 SC4761E0-PSG.edf +3dbf15f28a293ac89dcf458d844a8c6443aaf1e6 SC4761EP-Hypnogram.edf +7bdc8eacf1a6502c8f007b08556b7e8b52180d44 SC4762E0-PSG.edf +f6ae10f082a10ead671bfd5fdc50f62c42b9f10d SC4762EG-Hypnogram.edf +ac8c2be9175cb02e00cccb5d5df2acfaf05971cc SC4771G0-PSG.edf +09e80b973502d89368d7823ad4aec7417b735f6e SC4771GC-Hypnogram.edf +eea8671791936358037e5d096491865069989a85 SC4772G0-PSG.edf +25a3b8859091a70ca0cff9ebb777879aa156689e SC4772GC-Hypnogram.edf +0ce00a144dd9bc1b0e20cd30e6501a3852e4dbef SC4801G0-PSG.edf +f82d2b8e45723f2a69f8c30286cc68486b0792a6 SC4801GC-Hypnogram.edf +8959ada929c07945757bd6c9ef0267e7c9427a66 SC4802G0-PSG.edf +41ff2d1118425f5828342c07aa58b9d346755b1a SC4802GV-Hypnogram.edf +dcae3307af54ccf5349945e2fa493464de0a5da2 SC4811G0-PSG.edf +2406ce37b86fc3c7492a3ebe89ae58d15686b33d SC4811GG-Hypnogram.edf +fd93757cf6bcf45854fca960a067612352e05547 SC4812G0-PSG.edf +244b3bbb4987db0a9cef85950d14899ab9a3aec4 SC4812GV-Hypnogram.edf +9008c6ffc917fb90a3d399e768fe3c563a144a2f SC4821G0-PSG.edf +59534244c603cd5c3c27db26ae2f014983ec6c9b SC4821GC-Hypnogram.edf +84f9a60f6b0e7ac33388d8f6492096bcfa60bc18 SC4822G0-PSG.edf +8d14c371bc290658469729addee4461866bb67e2 SC4822GC-Hypnogram.edf +b9d11484126ebff1884034396d6a20c62c0ef48d ST7011J0-PSG.edf +ff28e5e01296cefed49ae0c27cfb3ebc42e710bf ST7011JP-Hypnogram.edf +b97c67d2ec40721349fd6faea32ea7155a11940a ST7012J0-PSG.edf +7a98a0ebba9e5e8fc4aac9ab82849385570d7789 ST7012JP-Hypnogram.edf +552e579d96e6c4ae083c7e1422e11b945ebcdabd ST7021J0-PSG.edf +635b07240047ade50649ff0f72ccde792f464f09 ST7021JM-Hypnogram.edf +ebabfa224599201d9baf91311f78f6410971810f ST7022J0-PSG.edf +228c608743abcc28f8c4946e8394ecf8e6ada89c ST7022JM-Hypnogram.edf +41f8e344b9872d93c8c2f2da283252231584b08f ST7041J0-PSG.edf +422655bae4525d121bd45fead048207be9b34c4b ST7041JO-Hypnogram.edf +229ee3bb4d060332c219c3dc1153732ab5499d57 ST7042J0-PSG.edf +eff297358a0c9d175109ba692ac3f9f4cd2c08ed ST7042JO-Hypnogram.edf +17b186214e8944667571f52098564e377b32d695 ST7051J0-PSG.edf +d7696bd1b891dd85e96e20ea727dcebe49ab6dfd ST7051JA-Hypnogram.edf +489fcb38c07688192d9c0eae5455d95241028ad8 ST7052J0-PSG.edf +64f2718c004e64ab598979da139b90452febc9bf ST7052JA-Hypnogram.edf +9fb2b4ed47a6d4b2f0b60a354123e491e8738b19 ST7061J0-PSG.edf +fd9214d026453fce71efa2975ea732e1c1458f69 ST7061JR-Hypnogram.edf +afc5599194648da5568dafa1a811818e77df4842 ST7062J0-PSG.edf +c2a4abe15f08f230b734a328494ab0d2ae9dc786 ST7062JR-Hypnogram.edf +010a65ad86b79d19c372a421f0e7c975e56278c8 ST7071J0-PSG.edf +bc08c797bb7aaf92de1c869d46c6dd4590939996 ST7071JA-Hypnogram.edf +15c5aa5591e35d60ba25044cdd4b3d748d3c0cfc ST7072J0-PSG.edf +1a7813b7a2389c0346e3844835590b9cb2f40f56 ST7072JA-Hypnogram.edf +cb66a0493d90d0d1204936e3e7c944ed536265e3 ST7081J0-PSG.edf +8259b52c62203b85268d23b3a2d87605fdcfa2a6 ST7081JW-Hypnogram.edf +b1cb29c7a7321b7e628d04a477338c4f62f0c093 ST7082J0-PSG.edf +bc33c3aba61c0fa937ef56d4ce7b1468c80663b5 ST7082JW-Hypnogram.edf +b046dd63d92339914eca0489d8a4c566b69e7723 ST7091J0-PSG.edf +af845641a8118d004bcfa6b597f23517e3a752e9 ST7091JE-Hypnogram.edf +2986f4d64f5118c5e356a2abe6bf86521ffde339 ST7092J0-PSG.edf +ec89bb908ff70e123ffa94bc2c11bb1ce54bcb6a ST7092JE-Hypnogram.edf +5662b560f095b8397303cced87e43d407a0d18f7 ST7101J0-PSG.edf +5919542c566d882fbf947c66f4858ad17199103a ST7101JE-Hypnogram.edf +f697a140f18d1005107fcbb7c81d85a5e8cb6ec6 ST7102J0-PSG.edf +1f05e92c9ca076350f981d0ec75ad720606bacbc ST7102JE-Hypnogram.edf +e2bf9db482f230a56372603d23fb12f5c56062f7 ST7111J0-PSG.edf +5964553fe07cbca302526b2153a2507f7d02fab8 ST7111JE-Hypnogram.edf +d3c7907b9b1e4f087f31bd655548b8673b6ec735 ST7112J0-PSG.edf +e4d8406eaca361d2c5d9953b3c67ed1098dd5925 ST7112JE-Hypnogram.edf +6e90bac48e48f71e5572944a364009eab6ea818d ST7121J0-PSG.edf +a991ed3d8be6d55ee563545077f3d280466a4989 ST7121JE-Hypnogram.edf +ae7426c464296ec0a839ccaa9763e3f2c57f41f1 ST7122J0-PSG.edf +b6c2c21e3cf17b371b31af78c64f28aa5811e36f ST7122JE-Hypnogram.edf +d0d6c83b76f627b067e0daac3c181e3666f8ab08 ST7131J0-PSG.edf +91ee1bd29b156b33e03cb8c324a8fac15ec06674 ST7131JR-Hypnogram.edf +54a50dcc40e3d6677b80c629b2f908339d9a7c3e ST7132J0-PSG.edf +028a5c4ed911d67a17b45f12966b32c46949d374 ST7132JR-Hypnogram.edf +6bf8feeabc2259d15f1f535abda90caacc8d4a86 ST7141J0-PSG.edf +203e78e02a92a9f85f07790398f64c66f248e5cc ST7141JE-Hypnogram.edf +b42eb28089bbdcbf3244dead53fd01d5f5ac3ddf ST7142J0-PSG.edf +1f7cc3a1923dd6a3504c82d76f820555ad0b6a1b ST7142JE-Hypnogram.edf +c0df1253b6509c4b4ed9e1283f26cf206a8c725c ST7151J0-PSG.edf +cfcb0089e22244bc5047f61e72a39735cbdc36cf ST7151JA-Hypnogram.edf +faefa07a1ca180861d6f26d5f35285c009dca21e ST7152J0-PSG.edf +27e9b4527eea33ded9072db3c6626f94a966da58 ST7152JA-Hypnogram.edf +8a4f1c44a17b5d665cc30f1141d003043274ac2b ST7161J0-PSG.edf +5a1ef1d375b01f83264e84db4af58acded68f15e ST7161JM-Hypnogram.edf +66925c8fa9f6da18f8590dcf2a6174cfe46e912d ST7162J0-PSG.edf +18b3d7eb9685ec8131fc0a8f81ba6205122595dc ST7162JM-Hypnogram.edf +67c47cb92de8806c60303a4baa87ca6cf52a2245 ST7171J0-PSG.edf +13c371fc4384751cc4bdd3044c6a0813ea12816e ST7171JA-Hypnogram.edf +a46118a5ca9cfaa62ca11c6a8b079e82877305ef ST7172J0-PSG.edf +8de0f3f59dd27d07f5f6a74216814ced08f104b5 ST7172JA-Hypnogram.edf +501f2f9d9ebe15e6dfc86fda6e90f9a54a39660a ST7181J0-PSG.edf +483aa0b448393d61043c98c204c93d4c60abb6bd ST7181JR-Hypnogram.edf +0eab40d3687a2cf708e48137eab26c0c43b75773 ST7182J0-PSG.edf +50efc607882659f8229db773703f5b973b471ed4 ST7182JR-Hypnogram.edf +b1b10cd45a7c0f91286c6fc3f755e59af483bac1 ST7191J0-PSG.edf +e7fcb89cf0f1484ab114bf40dcf2bf4cd413696b ST7191JR-Hypnogram.edf +e80de913aa41b987a43d94cf8f0106d61e4e883b ST7192J0-PSG.edf +def09a7d469984005b0c8414b7995ae8e269fd15 ST7192JR-Hypnogram.edf +454233ae9e6a948848030c5f4d9e60dfcb0facde ST7201J0-PSG.edf +17a0e8aebb885a960a74343bace57d2ab0b6296a ST7201JO-Hypnogram.edf +1e97e392968415da67432842c952344b6d3cdc8c ST7202J0-PSG.edf +ed26efdb6b2d9e815f2a725970262cb9c15c7b98 ST7202JO-Hypnogram.edf +c6582cfa8fcf6542a688fa8842011a93d86f2c60 ST7211J0-PSG.edf +b8756397056f623674c3b03db808b2c8c64b0a0a ST7211JJ-Hypnogram.edf +389f3920b39b4b9ad4fba6f91198299b7c6f6676 ST7212J0-PSG.edf +e25e47adf0c0f09df542ef061272ed9569fb80ea ST7212JJ-Hypnogram.edf +58315bec82d381dec56bf96924a94014462bb608 ST7221J0-PSG.edf +7656827835362b7b44b296bad83ff6001e14f489 ST7221JA-Hypnogram.edf +4961a08b87416246b8b8186190eca0e96da6a50d ST7222J0-PSG.edf +da840db60086e43a2429fb1322ede5e5976b3cda ST7222JA-Hypnogram.edf +7a850ce4bc6bd14ea072f3a45b002f8015cf2f14 ST7241J0-PSG.edf +bbaac4f2c2f330f70583eb179d855fcf42b4fbff ST7241JO-Hypnogram.edf +5c8bd182bfc9609929094769718b2835fe1099ad ST7242J0-PSG.edf +f70b3dfce2c14f01221a66a4acb522df1affffdb ST7242JO-Hypnogram.edf diff --git a/mne-python/source/mne/datasets/sleep_physionet/__init__.py b/mne-python/source/mne/datasets/sleep_physionet/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..aff3f92d4407bc238f93b1fe23551214794d9f84 --- /dev/null +++ b/mne-python/source/mne/datasets/sleep_physionet/__init__.py @@ -0,0 +1,5 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from . import age, temazepam, _utils diff --git a/mne-python/source/mne/datasets/sleep_physionet/_utils.py b/mne-python/source/mne/datasets/sleep_physionet/_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..06c9928d1a5349659b9ff64332c4b786d8c26dcf --- /dev/null +++ b/mne-python/source/mne/datasets/sleep_physionet/_utils.py @@ -0,0 +1,245 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import os.path as op + +import numpy as np + +from ...utils import _check_pandas_installed, _on_missing, _TempDir, verbose +from ..utils import _downloader_params, _get_path + +AGE_SLEEP_RECORDS = op.join(op.dirname(__file__), "age_records.csv") +TEMAZEPAM_SLEEP_RECORDS = op.join(op.dirname(__file__), "temazepam_records.csv") + +TEMAZEPAM_RECORDS_URL = ( + "https://physionet.org/physiobank/database/sleep-edfx/ST-subjects.xls" # noqa: E501 +) +TEMAZEPAM_RECORDS_URL_SHA1 = "f52fffe5c18826a2bd4c5d5cb375bb4a9008c885" + +AGE_RECORDS_URL = "https://physionet.org/physiobank/database/sleep-edfx/SC-subjects.xls" +AGE_RECORDS_URL_SHA1 = "0ba6650892c5d33a8e2b3f62ce1cc9f30438c54f" + +sha1sums_fname = op.join(op.dirname(__file__), "SHA1SUMS") + + +def _fetch_one(fname, hashsum, path, force_update, base_url): + import pooch + + # Fetch the file + url = base_url + "/" + fname + destination = op.join(path, fname) + if op.isfile(destination) and not force_update: + return destination, False + if op.isfile(destination): + os.remove(destination) + if not op.isdir(op.dirname(destination)): + os.makedirs(op.dirname(destination)) + downloader = pooch.HTTPDownloader(**_downloader_params()) + pooch.retrieve( + url=url, + known_hash=f"sha1:{hashsum}", + path=path, + downloader=downloader, + fname=fname, + ) + return destination, True + + +@verbose +def _data_path(path=None, verbose=None): + """Get path to local copy of EEG Physionet age Polysomnography dataset URL. + + This is a low-level function useful for getting a local copy of a + remote Polysomnography dataset :footcite:`KempEtAl2000` which is available + at PhysioNet :footcite:`GoldbergerEtAl2000`. + + Parameters + ---------- + path : None | str + Location of where to look for the data storing location. + If None, the environment variable or config parameter + ``PHYSIONET_SLEEP_PATH`` is used. If it doesn't exist, the "~/mne_data" + directory is used. If the dataset is not found under the given path, + the data will be automatically downloaded to the specified folder. + %(verbose)s + + Returns + ------- + path : list of Path + Local path to the given data file. This path is contained inside a list + of length one, for compatibility. + + References + ---------- + .. footbibliography:: + """ # noqa: E501 + key = "PHYSIONET_SLEEP_PATH" + name = "PHYSIONET_SLEEP" + path = _get_path(path, key, name) + return op.join(path, "physionet-sleep-data") + + +def _update_sleep_temazepam_records(fname=TEMAZEPAM_SLEEP_RECORDS): + """Help function to download Physionet's temazepam dataset records.""" + import pooch + + pd = _check_pandas_installed() + tmp = _TempDir() + + # Download subjects info. + subjects_fname = op.join(tmp, "ST-subjects.xls") + downloader = pooch.HTTPDownloader(**_downloader_params()) + pooch.retrieve( + url=TEMAZEPAM_RECORDS_URL, + known_hash=f"sha1:{TEMAZEPAM_RECORDS_URL_SHA1}", + path=tmp, + downloader=downloader, + fname=op.basename(subjects_fname), + ) + + # Load and Massage the checksums. + sha1_df = pd.read_csv( + sha1sums_fname, sep=" ", header=None, names=["sha", "fname"], engine="python" + ) + select_age_records = sha1_df.fname.str.startswith( + "ST" + ) & sha1_df.fname.str.endswith("edf") + sha1_df = sha1_df[select_age_records] + sha1_df["id"] = [name[:6] for name in sha1_df.fname] + + # Load and massage the data. + data = pd.read_excel(subjects_fname, header=[0, 1]) + data = data.set_index(("Subject - age - sex", "Nr")) + data.index.name = "subject" + data.columns.names = [None, None] + data = ( + data.set_index( + [("Subject - age - sex", "Age"), ("Subject - age - sex", "M1/F2")], + append=True, + ) + # TODO VERSION future_stack goes away w/ Pandas 3.0 + .stack(level=0, future_stack=True) + .reset_index() + ) + + data = data.rename( + columns={ + ("Subject - age - sex", "Age"): "age", + ("Subject - age - sex", "M1/F2"): "sex", + "level_3": "drug", + } + ) + data["id"] = [f"ST7{s:02d}{n:1d}" for s, n in zip(data.subject, data["night nr"])] + + data = pd.merge(sha1_df, data, how="outer", on="id") + data["record type"] = ( + data.fname.str.split("-", expand=True)[1] + .str.split(".", expand=True)[0] + .astype("category") + ) + + data = data.set_index( + ["id", "subject", "age", "sex", "drug", "lights off", "night nr", "record type"] + ).unstack() + data.columns = [l1 + "_" + l2 for l1, l2 in data.columns] + data = data.reset_index().drop(columns=["id"]) + + data["sex"] = data.sex.astype("category").cat.rename_categories( + {1: "male", 2: "female"} + ) + + data["drug"] = data["drug"].str.split(expand=True)[0] + data["subject_orig"] = data["subject"] + data["subject"] = data.index // 2 # to make sure index is from 0 to 21 + + # Save the data. + data.to_csv(fname, index=False) + + +def _update_sleep_age_records(fname=AGE_SLEEP_RECORDS): + """Help function to download Physionet's age dataset records.""" + import pooch + + pd = _check_pandas_installed() + tmp = _TempDir() + + # Download subjects info. + subjects_fname = op.join(tmp, "SC-subjects.xls") + downloader = pooch.HTTPDownloader(**_downloader_params()) + pooch.retrieve( + url=AGE_RECORDS_URL, + known_hash=f"sha1:{AGE_RECORDS_URL_SHA1}", + path=tmp, + downloader=downloader, + fname=op.basename(subjects_fname), + ) + + # Load and Massage the checksums. + sha1_df = pd.read_csv( + sha1sums_fname, sep=" ", header=None, names=["sha", "fname"], engine="python" + ) + select_age_records = sha1_df.fname.str.startswith( + "SC" + ) & sha1_df.fname.str.endswith("edf") + sha1_df = sha1_df[select_age_records] + sha1_df["id"] = [name[:6] for name in sha1_df.fname] + + # Load and massage the data. + data = pd.read_excel(subjects_fname) + data = data.rename( + index=str, columns={"sex (F=1)": "sex", "LightsOff": "lights off"} + ) + data["sex"] = data.sex.astype("category").cat.rename_categories( + {1: "female", 2: "male"} + ) + + data["id"] = [f"SC4{s:02d}{n:1d}" for s, n in zip(data.subject, data.night)] + + data = data.set_index("id").join(sha1_df.set_index("id")).dropna() + + data["record type"] = ( + data.fname.str.split("-", expand=True)[1] + .str.split(".", expand=True)[0] + .astype("category") + ) + + data = data.reset_index().drop(columns=["id"]) + data = data[ + ["subject", "night", "record type", "age", "sex", "lights off", "sha", "fname"] + ] + + # Save the data. + data.to_csv(fname, index=False) + + +def _check_subjects(subjects, n_subjects, missing=None, on_missing="raise"): + """Check whether subjects are available. + + Parameters + ---------- + subjects : list + Subject numbers to be checked. + n_subjects : int + Number of subjects available. + missing : list | None + Subject numbers that are missing. + on_missing : 'raise' | 'warn' | 'ignore' + What to do if one or several subjects are not available. Valid keys + are 'raise' | 'warn' | 'ignore'. Default is 'error'. If on_missing + is 'warn' it will proceed but warn, if 'ignore' it will proceed + silently. + """ + valid_subjects = np.arange(n_subjects) + if missing is not None: + valid_subjects = np.setdiff1d(valid_subjects, missing) + unknown_subjects = np.setdiff1d(subjects, valid_subjects) + if unknown_subjects.size > 0: + subjects_list = ", ".join([str(s) for s in unknown_subjects]) + msg = ( + f"This dataset contains subjects 0 to {n_subjects - 1} with " + f"missing subjects {missing}. Unknown subjects: " + f"{subjects_list}." + ) + _on_missing(on_missing, msg) diff --git a/mne-python/source/mne/datasets/sleep_physionet/age.py b/mne-python/source/mne/datasets/sleep_physionet/age.py new file mode 100644 index 0000000000000000000000000000000000000000..b5ea1764946c38e38fd7072252f47ca73b9ad085 --- /dev/null +++ b/mne-python/source/mne/datasets/sleep_physionet/age.py @@ -0,0 +1,150 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import time + +import numpy as np + +from ...utils import verbose +from ..utils import _log_time_size +from ._utils import ( + AGE_SLEEP_RECORDS, + _check_subjects, + _data_path, + _fetch_one, + _on_missing, +) + +data_path = _data_path # expose _data_path(..) as data_path(..) + +BASE_URL = "https://physionet.org/physiobank/database/sleep-edfx/sleep-cassette/" + + +@verbose +def fetch_data( + subjects, + recording=(1, 2), + path=None, + force_update=False, + base_url=BASE_URL, + on_missing="raise", + *, + verbose=None, +): # noqa: D301, E501 + """Get paths to local copies of PhysioNet Polysomnography dataset files. + + This will fetch data from the publicly available subjects from PhysioNet's + study of age effects on sleep in healthy subjects + :footcite:`MourtazaevEtAl1995,GoldbergerEtAl2000`. This + corresponds to a subset of 153 recordings from 37 males and 41 females that + were 25-101 years old at the time of the recordings. There are two night + recordings per subject except for subjects 13, 36 and 52 which have one + record missing each due to missing recording hardware. + + See more details in + `physionet website `_. + + Parameters + ---------- + subjects : list of int + The subjects to use. Can be in the range of 0-82 (inclusive), however + the following subjects are not available: 39, 68, 69, 78 and 79. + recording : list of int + The night recording indices. Valid values are : [1], [2], or [1, 2]. + The following recordings are not available: recording 1 for subject 36 + and 52, and recording 2 for subject 13. + path : None | str + Location of where to look for the PhysioNet data storing location. + If None, the environment variable or config parameter + ``PHYSIONET_SLEEP_PATH`` is used. If it doesn't exist, the "~/mne_data" + directory is used. If the Polysomnography dataset is not found under + the given path, the data will be automatically downloaded to the + specified folder. + force_update : bool + Force update of the dataset even if a local copy exists. + base_url : str + The URL root. + on_missing : 'raise' | 'warn' | 'ignore' + What to do if one or several recordings are not available. Valid keys + are 'raise' | 'warn' | 'ignore'. Default is 'error'. If on_missing + is 'warn' it will proceed but warn, if 'ignore' it will proceed + silently. + %(verbose)s + + Returns + ------- + paths : list + List of local data paths of the given type. + + See Also + -------- + mne.datasets.sleep_physionet.temazepam.fetch_data + + Notes + ----- + For example, one could do: + + >>> from mne.datasets import sleep_physionet + >>> sleep_physionet.age.fetch_data(subjects=[0]) # doctest: +SKIP + + This would download data for subject 0 if it isn't there already. + + References + ---------- + .. footbibliography:: + """ # noqa: E501 + t0 = time.time() + records = np.loadtxt( + AGE_SLEEP_RECORDS, + skiprows=1, + delimiter=",", + usecols=(0, 1, 2, 6, 7), + dtype={ + "names": ("subject", "record", "type", "sha", "fname"), + "formats": (" 0: + _log_time_size(t0, sz) + return fnames diff --git a/mne-python/source/mne/datasets/sleep_physionet/age_records.csv b/mne-python/source/mne/datasets/sleep_physionet/age_records.csv new file mode 100644 index 0000000000000000000000000000000000000000..e172b6baf1431911df5c354b276bf1b354512c26 --- /dev/null +++ b/mne-python/source/mne/datasets/sleep_physionet/age_records.csv @@ -0,0 +1,307 @@ +subject,night,record type,age,sex,lights off,sha,fname +0,1,PSG,33,female,00:38:00,adabd3b01fc7bb75c523a974f38ee3ae4e57b40f,SC4001E0-PSG.edf +0,1,Hypnogram,33,female,00:38:00,21c998eadc8b1e3ea6727d3585186b8f76e7e70b,SC4001EC-Hypnogram.edf +0,2,PSG,33,female,21:57:00,c6b6d7a8605cc7e7602b6028ee77f6fbf5f7581d,SC4002E0-PSG.edf +0,2,Hypnogram,33,female,21:57:00,386230188a3552b1fc90bba0fb7476ceaca174b6,SC4002EC-Hypnogram.edf +1,1,PSG,33,female,22:44:00,4d17451f7847355bcab17584de05e7e1df58c660,SC4011E0-PSG.edf +1,1,Hypnogram,33,female,22:44:00,d582a3cbe2db481a362af890bc5a2f5ca7c878dc,SC4011EH-Hypnogram.edf +1,2,PSG,33,female,22:15:00,a47d525f5147904b6890231e2ad338359c7ab94c,SC4012E0-PSG.edf +1,2,Hypnogram,33,female,22:15:00,fa99f60d7f54617cdd1128aff4f21c4daed763c7,SC4012EC-Hypnogram.edf +2,1,PSG,26,female,22:50:00,8b135afa7fb93bb5f1998fda50355944777c245e,SC4021E0-PSG.edf +2,1,Hypnogram,26,female,22:50:00,91043cfe46695088b17b6a02937b25efd674c3fb,SC4021EH-Hypnogram.edf +2,2,PSG,26,female,22:57:00,d739e142b3b328c71b4752149901805dcd6d7e19,SC4022E0-PSG.edf +2,2,Hypnogram,26,female,22:57:00,0c46a03699dd00e8f92a7edff99ebc4642cb3d48,SC4022EJ-Hypnogram.edf +3,1,PSG,26,female,00:02:00,85e58dc1e3303537dade8c5827ab58328239c384,SC4031E0-PSG.edf +3,1,Hypnogram,26,female,00:02:00,6363d8b0fdc48cf396c9abf054bb4a9696d38bdb,SC4031EC-Hypnogram.edf +3,2,PSG,26,female,00:24:00,43963d300642b3aa840e8c468f321b8162601772,SC4032E0-PSG.edf +3,2,Hypnogram,26,female,00:24:00,7925514bc8d2ef3f1103130f08f7b3afd2136b88,SC4032EP-Hypnogram.edf +4,1,PSG,34,female,23:12:00,04d2b88d25f2ae4a65ba44cd9145bd12800a0e20,SC4041E0-PSG.edf +4,1,Hypnogram,34,female,23:12:00,f148821669bd3588187b3b430bd79adf569f86d1,SC4041EC-Hypnogram.edf +4,2,PSG,34,female,23:35:00,76253d964d7797540ffd791e6e136023ed67a485,SC4042E0-PSG.edf +4,2,Hypnogram,34,female,23:35:00,9873df429f971f8a4b720a454f6c0472b8a25ebb,SC4042EC-Hypnogram.edf +5,1,PSG,28,female,01:22:00,ea073451b65ce8a6f1a02a8cc2b89d1a162ca0ae,SC4051E0-PSG.edf +5,1,Hypnogram,28,female,01:22:00,4159ef8a3e119d6dcc1bede806f6fbc017b27a0f,SC4051EC-Hypnogram.edf +5,2,PSG,28,female,00:35:00,5a2efbd21be9b745fd534394eb2503caca7dc53f,SC4052E0-PSG.edf +5,2,Hypnogram,28,female,00:35:00,0e96482d44762df4da65dc4fdb970b342264d22a,SC4052EC-Hypnogram.edf +6,1,PSG,31,female,00:16:00,1736736e585807c14f1ae8bc87a94cae222c5170,SC4061E0-PSG.edf +6,1,Hypnogram,31,female,00:16:00,4bf99622c67c281b25ceccd35e7050328a2946e8,SC4061EC-Hypnogram.edf +6,2,PSG,31,female,22:44:00,763c7ac059f1771a0165e5cb351b176afb1cfe15,SC4062E0-PSG.edf +6,2,Hypnogram,31,female,22:44:00,14f07411cd04d3b4b522d37c129334955287ff5f,SC4062EC-Hypnogram.edf +7,1,PSG,30,female,00:36:00,1374b34f6139b6ff7e865d8243eef39ba334ef50,SC4071E0-PSG.edf +7,1,Hypnogram,30,female,00:36:00,608024fd19a140ad233a4680e07c2495a74b69c2,SC4071EC-Hypnogram.edf +7,2,PSG,30,female,00:41:00,1c570644243d79396df612fa2b9bc027b24430e4,SC4072E0-PSG.edf +7,2,Hypnogram,30,female,00:41:00,a8da6c20b9b48189f05ab537886b59dd141374d2,SC4072EH-Hypnogram.edf +8,1,PSG,25,female,23:35:00,0e1cc2c4e1da14ab94515e3e7e75e8ad30ec99cb,SC4081E0-PSG.edf +8,1,Hypnogram,25,female,23:35:00,9ec663ffa5c17afcaca59d7829d77b9165102237,SC4081EC-Hypnogram.edf +8,2,PSG,25,female,23:37:00,d57d4aa7cbc5045f611a3a3e342b501e086ea426,SC4082E0-PSG.edf +8,2,Hypnogram,25,female,23:37:00,d43c785dba43063d7baa332671c6bac9c832b5b7,SC4082EP-Hypnogram.edf +9,1,PSG,25,female,23:02:00,b3502e0bd54683e973182c791aa962b804e79633,SC4091E0-PSG.edf +9,1,Hypnogram,25,female,23:02:00,7aa63b408c769a4a983a908b6ba41d87dd743c6e,SC4091EC-Hypnogram.edf +9,2,PSG,25,female,23:01:00,246e35852119b33d197db2f7bcfb1b46a5270a03,SC4092E0-PSG.edf +9,2,Hypnogram,25,female,23:01:00,9d85766a83231b1c6076cb293367ccc354c57eeb,SC4092EC-Hypnogram.edf +10,1,PSG,26,male,22:59:00,3ae168ff2c9c0c56f51205fdb10f05a4c6b2064e,SC4101E0-PSG.edf +10,1,Hypnogram,26,male,22:59:00,60d9c3913881e11b06ad99e9870bd1ca4d93c952,SC4101EC-Hypnogram.edf +10,2,PSG,26,male,23:07:00,86f307190961eaab0214fdc0213f8fe05812c7a5,SC4102E0-PSG.edf +10,2,Hypnogram,26,male,23:07:00,8072e2d52bc6c19b45fbd921550e5243bc5a1de7,SC4102EC-Hypnogram.edf +11,1,PSG,26,male,23:00:00,e490956b4dce01c46ba88a2b847f091bb54ea16e,SC4111E0-PSG.edf +11,1,Hypnogram,26,male,23:00:00,12db1920e2f6083c8ab1f2c24fe35dfa03715e4a,SC4111EC-Hypnogram.edf +11,2,PSG,26,male,01:14:00,ca24dc464df61144627588b29d35a85fcc7ac984,SC4112E0-PSG.edf +11,2,Hypnogram,26,male,01:14:00,54dbc39015b0a445b51189987a00e08cc27d8f0c,SC4112EC-Hypnogram.edf +12,1,PSG,26,male,00:50:00,33c72025a7a215ea5e255f4254cb0f93b1313369,SC4121E0-PSG.edf +12,1,Hypnogram,26,male,00:50:00,daa57ece807cb5325c6d1ce059f0e8a8d1c85391,SC4121EC-Hypnogram.edf +12,2,PSG,26,male,01:03:00,34f5145ab62dcc5a53ba18735519e5bb2b13841a,SC4122E0-PSG.edf +12,2,Hypnogram,26,male,01:03:00,b7af1a32d8ca15e8185e4c94213ffc18ad7f6e8a,SC4122EV-Hypnogram.edf +13,1,PSG,27,male,00:14:00,42ff97035aae6dd34ca9437857c48ac6f2ab97df,SC4131E0-PSG.edf +13,1,Hypnogram,27,male,00:14:00,5beef85170bdbb5cf2eea24a79f0f5c2c3975c4b,SC4131EC-Hypnogram.edf +14,1,PSG,27,male,22:55:00,83493e1c32d441c9e5ee3de6a024bfb5e7ab9f5f,SC4141E0-PSG.edf +14,1,Hypnogram,27,male,22:55:00,511d398f22b9b2b304de27c40740a41584ff6af2,SC4141EU-Hypnogram.edf +14,2,PSG,27,male,23:22:00,63d13828b7ebe0d2ed7f491d2b5520e928b9b55d,SC4142E0-PSG.edf +14,2,Hypnogram,27,male,23:22:00,6f123e6fdc90a01b83e694d9744a6d27f3c87b25,SC4142EU-Hypnogram.edf +15,1,PSG,31,male,23:56:00,5a92d49699d4de369d66d9462e91b0dcb3312649,SC4151E0-PSG.edf +15,1,Hypnogram,31,male,23:56:00,37dcbd339c95322d028b3a5466812697041cc373,SC4151EC-Hypnogram.edf +15,2,PSG,31,male,23:38:00,778626489bc4fe2c9137d2d361876d97dce97e5e,SC4152E0-PSG.edf +15,2,Hypnogram,31,male,23:38:00,294cdc47cd3d165031f7041c17f18dd013d216cb,SC4152EC-Hypnogram.edf +16,1,PSG,32,male,22:16:00,e56ff3aa366fe9a04a0fdfdd4cd862e77e8ac807,SC4161E0-PSG.edf +16,1,Hypnogram,32,male,22:16:00,56711b1bfed292032491f5cce57494629286a131,SC4161EC-Hypnogram.edf +16,2,PSG,32,male,23:16:00,722692f9940f3a1bccb9b4488c4477edf7fb128f,SC4162E0-PSG.edf +16,2,Hypnogram,32,male,23:16:00,c85647fb4bc1f382fe46bf9aaf579dc483115885,SC4162EC-Hypnogram.edf +17,1,PSG,31,male,23:58:00,f1a65522cb7d6c71ac47742535a12c88e2019dad,SC4171E0-PSG.edf +17,1,Hypnogram,31,male,23:58:00,dd257c8d922f08c2c8ca5236c9bf54da887c68e5,SC4171EU-Hypnogram.edf +17,2,PSG,31,male,00:37:00,572b81bc24c2c9482e6fc7ba9202a7bf253655e1,SC4172E0-PSG.edf +17,2,Hypnogram,31,male,00:37:00,c9a3b590748d7d6c7ad97c62222bd53d8ebaf630,SC4172EC-Hypnogram.edf +18,1,PSG,28,male,23:25:00,23674d20572853eb6d988d24378c52123f66500c,SC4181E0-PSG.edf +18,1,Hypnogram,28,male,23:25:00,51fc3df2df7d4da654f3e18ed1b233d0c60cfa80,SC4181EC-Hypnogram.edf +18,2,PSG,28,male,23:45:00,83e8cbe882ba863da9fd3c11393c95b6fec5b7a5,SC4182E0-PSG.edf +18,2,Hypnogram,28,male,23:45:00,43c487955edddb4ee2f60193a097c68c25c5dd4d,SC4182EC-Hypnogram.edf +19,1,PSG,28,male,01:50:00,d6da621dbb20dec3494a38c7d2a0363793ac5ebe,SC4191E0-PSG.edf +19,1,Hypnogram,28,male,01:50:00,defc7b9368c2d3c4ab4a294757843825a83cdb5d,SC4191EP-Hypnogram.edf +19,2,PSG,28,male,00:57:00,941353118732321d0246a1d58d72e903bd2f0d8f,SC4192E0-PSG.edf +19,2,Hypnogram,28,male,00:57:00,97b91b3067c5ecde766042fc2cff9e22f8023371,SC4192EV-Hypnogram.edf +20,1,PSG,51,female,23:10:00,38a0be6e45ddd9b1f17d09964a32e005dc5a6519,SC4201E0-PSG.edf +20,1,Hypnogram,51,female,23:10:00,83822f9970d3959ad2e0613492ae39bd0fae6068,SC4201EC-Hypnogram.edf +20,2,PSG,51,female,23:15:00,aa69f5bd47c2ae03c9d38bfe6d0e58408744b885,SC4202E0-PSG.edf +20,2,Hypnogram,51,female,23:15:00,5c5c63016b43421a523d1efcb34247e90aa6318b,SC4202EC-Hypnogram.edf +21,1,PSG,51,female,23:28:00,c106ad072dbc975a3742f7eff151219870f0c794,SC4211E0-PSG.edf +21,1,Hypnogram,51,female,23:28:00,9126937ea8a414d6ae9bc4a4194d841a891fa8a8,SC4211EC-Hypnogram.edf +21,2,PSG,51,female,23:59:00,a06ecb3f0a7b2c306f5ae4dbd83685f877cd945b,SC4212E0-PSG.edf +21,2,Hypnogram,51,female,23:59:00,a85f178b69a1cda47d11dd1e5394dfdcb58de1d4,SC4212EC-Hypnogram.edf +22,1,PSG,56,female,23:47:00,8733ea022d3778259a436507156cf3360ad8be06,SC4221E0-PSG.edf +22,1,Hypnogram,56,female,23:47:00,b158eda4f81772095c129be77f8e60ec9d81b884,SC4221EJ-Hypnogram.edf +22,2,PSG,56,female,23:14:00,211410fab6381da0dfaef4134d5a05eec935a4ec,SC4222E0-PSG.edf +22,2,Hypnogram,56,female,23:14:00,1488fbfbc149499dafa8dafff4f7504053af429f,SC4222EC-Hypnogram.edf +23,1,PSG,50,female,00:51:00,d96f1f35b2f77c7de706036c6e4114139e07b307,SC4231E0-PSG.edf +23,1,Hypnogram,50,female,00:51:00,9f6df70676d6cddcf069ceb7f408a7989af99ce2,SC4231EJ-Hypnogram.edf +23,2,PSG,50,female,00:32:00,6b493fa424c1329ea1c13543d08ba82a9f1e85b6,SC4232E0-PSG.edf +23,2,Hypnogram,50,female,00:32:00,d8ca7d694b3c48ab9d983b9cf67e17744c6b50fb,SC4232EV-Hypnogram.edf +24,1,PSG,54,female,23:22:00,58719e53fe18d2fc4cb1776ab5d43306beb1325d,SC4241E0-PSG.edf +24,1,Hypnogram,54,female,23:22:00,fb1432e303a8f99a2256ce682db95d88772c479f,SC4241EC-Hypnogram.edf +24,2,PSG,54,female,22:50:00,5a6277972c5f03572ed99d9ff63fb637945be778,SC4242E0-PSG.edf +24,2,Hypnogram,54,female,22:50:00,bbbf097f4cc6560fc20c903fba2c7055e1549f85,SC4242EA-Hypnogram.edf +25,1,PSG,56,female,00:32:00,7dbc0289707ff70662d367d65de7bec188484d1b,SC4251E0-PSG.edf +25,1,Hypnogram,56,female,00:32:00,e38be8134e4a36eb418ca1f06a1fe02b52d0ebf1,SC4251EP-Hypnogram.edf +25,2,PSG,56,female,23:49:00,cb3922910ea03d06c1fc5c8f15b71339dc26bc9d,SC4252E0-PSG.edf +25,2,Hypnogram,56,female,23:49:00,4cb7a383736e09125a82ef7e4f17b41130c7ac00,SC4252EU-Hypnogram.edf +26,1,PSG,51,female,23:39:00,b81c9bd1875b33713b5eb56b58f1e120841b507f,SC4261F0-PSG.edf +26,1,Hypnogram,51,female,23:39:00,501eda59557bb99d530d01bdad3579f1e1158991,SC4261FM-Hypnogram.edf +26,2,PSG,51,female,00:20:00,c9f9ad7cd751d5be91396886a2b64a7c1de564ee,SC4262F0-PSG.edf +26,2,Hypnogram,51,female,00:20:00,7ccd12803c5fc602ac1929ff3afd914b894b9143,SC4262FC-Hypnogram.edf +27,1,PSG,54,female,23:41:00,20994715d34edb26113180ee330ce287dbf57b60,SC4271F0-PSG.edf +27,1,Hypnogram,54,female,23:41:00,26c5c7f3a5c350d3505af2857835ce81252c5990,SC4271FC-Hypnogram.edf +27,2,PSG,54,female,22:58:00,9e79eb465e34b7eb6fe27ae3ce35d28d6693d44b,SC4272F0-PSG.edf +27,2,Hypnogram,54,female,22:58:00,956fe4b45d29a8999faf280a6168e332afab6abc,SC4272FM-Hypnogram.edf +28,1,PSG,56,female,23:55:00,51811913d7854f95c319076e670d988687ca667c,SC4281G0-PSG.edf +28,1,Hypnogram,56,female,23:55:00,d188150831e912081dbeda2695231177200c39f9,SC4281GC-Hypnogram.edf +28,2,PSG,56,female,00:13:00,e9f080a766a9b7a247f228e44e9c4ec67e571c95,SC4282G0-PSG.edf +28,2,Hypnogram,56,female,00:13:00,12d777787dd1975eef9015329fd774b2bfa1d53a,SC4282GC-Hypnogram.edf +29,1,PSG,51,female,22:38:00,f81c7574a5e5829e006d0b705bf5208a3349c9c7,SC4291G0-PSG.edf +29,1,Hypnogram,51,female,22:38:00,577c1345f6d070d975db5016048722f78b1b414e,SC4291GA-Hypnogram.edf +29,2,PSG,51,female,23:04:00,7416f44a3b149b4ca1fc3e53d546a093a7333bb5,SC4292G0-PSG.edf +29,2,Hypnogram,51,female,23:04:00,6e111a15160a31609761f742315df800b1311b3b,SC4292GC-Hypnogram.edf +30,1,PSG,50,male,00:09:00,7818e5a02afa89e913111d91ecd651aa3e786e5d,SC4301E0-PSG.edf +30,1,Hypnogram,50,male,00:09:00,d49df84bfea28bb241c09b922cd2dc64f57c5ae5,SC4301EC-Hypnogram.edf +30,2,PSG,50,male,00:20:00,d52859ba6a7ded3364b0d8ef2b722e1d3edda060,SC4302E0-PSG.edf +30,2,Hypnogram,50,male,00:20:00,b3d6f687831ee32f6df1da59f2d568c13f9c09d0,SC4302EV-Hypnogram.edf +31,1,PSG,54,male,23:44:00,b62f5104bddf452f4700c85997e51bec17f0243b,SC4311E0-PSG.edf +31,1,Hypnogram,54,male,23:44:00,812c34844e834b97949019741fa7f835d973725d,SC4311EC-Hypnogram.edf +31,2,PSG,54,male,23:14:00,b0a9b4922665734773abbaba06e7aab32010b862,SC4312E0-PSG.edf +31,2,Hypnogram,54,male,23:14:00,fca1935a8974eac27803e3125cea177995deca11,SC4312EM-Hypnogram.edf +32,1,PSG,57,male,00:48:00,335381ae310e9f1f053c37763eeee74d7d873471,SC4321E0-PSG.edf +32,1,Hypnogram,57,male,00:48:00,67ba7d3b97354deb31db095e748ea3a4014fae2c,SC4321EC-Hypnogram.edf +32,2,PSG,57,male,00:15:00,c9fdcfcce7e603b3289b7417891987fd67f6d921,SC4322E0-PSG.edf +32,2,Hypnogram,57,male,00:15:00,40cf9a6397a52c7deda693ca596e928cc2b9f4e9,SC4322EC-Hypnogram.edf +33,1,PSG,60,male,22:58:00,f37cb4df27286e38c604cae943169ff29b1473fc,SC4331F0-PSG.edf +33,1,Hypnogram,60,male,22:58:00,ca943e2b73c6404f929c372ebd817b7b3b71b4dd,SC4331FV-Hypnogram.edf +33,2,PSG,60,male,22:55:00,5bce6ea9b2d6c9bfb41065e92bf9cc05a11b5b75,SC4332F0-PSG.edf +33,2,Hypnogram,60,male,22:55:00,e4595b0313d5320b0bffefa43260485e19977e3c,SC4332FC-Hypnogram.edf +34,1,PSG,54,male,23:03:00,17de25c8f023fe632aa403a6d9525c1cde8eaef5,SC4341F0-PSG.edf +34,1,Hypnogram,54,male,23:03:00,81ba3c0d8320c9ee306f678b4bc9e6e266165886,SC4341FA-Hypnogram.edf +34,2,PSG,54,male,22:30:00,b659037447a1871f4ba72bbe496cfbe507330530,SC4342F0-PSG.edf +34,2,Hypnogram,54,male,22:30:00,e8e74c0905e89a59022ce0814ca9a050748ec9ae,SC4342FA-Hypnogram.edf +35,1,PSG,57,male,00:02:00,631900bef36d359a0f5807a7e1b202f80b0427ac,SC4351F0-PSG.edf +35,1,Hypnogram,57,male,00:02:00,a15cdf3973b77198d8276dc505dbb35cb39a9b4a,SC4351FA-Hypnogram.edf +35,2,PSG,57,male,23:30:00,325423a85890dcc921253bde7c7027d66f14033e,SC4352F0-PSG.edf +35,2,Hypnogram,57,male,23:30:00,1e0583b2a58432c964506ff44752d597753658c9,SC4352FV-Hypnogram.edf +36,2,PSG,51,male,23:59:00,30b90aaf965938d569ea362f66e2afa0c08c7017,SC4362F0-PSG.edf +36,2,Hypnogram,51,male,23:59:00,fb870d50ce3f4d961d8b061a83d21e5467e4ae6c,SC4362FC-Hypnogram.edf +37,1,PSG,52,male,23:03:00,0dc56fce13b6317f197d0b17c04f5be4af1c964f,SC4371F0-PSG.edf +37,1,Hypnogram,52,male,23:03:00,c19b6cbfdf3a33169ce9b4a5dc94f93b696a21ba,SC4371FA-Hypnogram.edf +37,2,PSG,52,male,23:05:00,c024c491dd836ed0169300e7171c276fd14b1c44,SC4372F0-PSG.edf +37,2,Hypnogram,52,male,23:05:00,97b2915a8a343efc7b785998c0532beaea2fbe91,SC4372FC-Hypnogram.edf +38,1,PSG,51,male,23:12:00,6098d2b501b82ca0ddc8893547c6990e204e8ba6,SC4381F0-PSG.edf +38,1,Hypnogram,51,male,23:12:00,fdbf653a4a675843c97d0a76ef5e4cebf5d2dbcb,SC4381FC-Hypnogram.edf +38,2,PSG,51,male,23:47:00,40ce0168d5f546fcd445996ab614f43823a7c2b1,SC4382F0-PSG.edf +38,2,Hypnogram,51,male,23:47:00,796f8507254c2d8d345171c077dbd855e112eb47,SC4382FW-Hypnogram.edf +40,1,PSG,67,female,23:30:00,28fd8ad1aee307847e2eb579763ebca18e56f540,SC4401E0-PSG.edf +40,1,Hypnogram,67,female,23:30:00,65b5671a89871351ee3da7ea800aad276a445b2a,SC4401EC-Hypnogram.edf +40,2,PSG,67,female,23:55:00,3d4bafa57933cfb20c342e8cc54c15916a621454,SC4402E0-PSG.edf +40,2,Hypnogram,67,female,23:55:00,037efea0fc8a6dfa8f85fa1f2fa6fd9a19f2c830,SC4402EW-Hypnogram.edf +41,1,PSG,66,female,23:28:00,30a533b67fdb2adac6a4e83088a07fe1bbaddb6c,SC4411E0-PSG.edf +41,1,Hypnogram,66,female,23:28:00,5df1bf20d4f29b95a2bdde853b2a157dd9530a8a,SC4411EJ-Hypnogram.edf +41,2,PSG,66,female,23:30:00,bc8e6ea829f14da5396a4b250394c1b72d6631c3,SC4412E0-PSG.edf +41,2,Hypnogram,66,female,23:30:00,f46b1dcfe4f4e3c9d4d4c8516dab9759f9c1224e,SC4412EM-Hypnogram.edf +42,1,PSG,69,female,01:30:00,e8a5d9e0f160ae7bd0b35d75d77b4c872daa30f8,SC4421E0-PSG.edf +42,1,Hypnogram,69,female,01:30:00,d2e34f9bcaac7af23da4448f742ac6ea3c895ed9,SC4421EA-Hypnogram.edf +42,2,PSG,69,female,00:22:00,80f246adffb92a3785f91368a77b0250aa040462,SC4422E0-PSG.edf +42,2,Hypnogram,69,female,00:22:00,709251cc7ae6556544c153caf9dac7f82bba113b,SC4422EA-Hypnogram.edf +43,1,PSG,73,female,01:30:00,194ae942cf80764e81b4cdabeed9e5a57916aab3,SC4431E0-PSG.edf +43,1,Hypnogram,73,female,01:30:00,497ad7e671edab6e7adc9d35a6aa45b7fd9a706b,SC4431EM-Hypnogram.edf +43,2,PSG,73,female,00:47:00,c45a66d27ea03bf448903fe30f17838e9a0fa0de,SC4432E0-PSG.edf +43,2,Hypnogram,73,female,00:47:00,10fe276e215f9406c0ddedaa48651cf480892476,SC4432EM-Hypnogram.edf +44,1,PSG,74,female,00:18:00,e3a09d832cb79b0095d7a311ef1b6ed7c569b79d,SC4441E0-PSG.edf +44,1,Hypnogram,74,female,00:18:00,68d4e44ad54069701972df66d8a81b4ca434bf2f,SC4441EC-Hypnogram.edf +44,2,PSG,74,female,23:55:00,fe51d45e9f3e64a61fa8a5e5274b2e4951a9de43,SC4442E0-PSG.edf +44,2,Hypnogram,74,female,23:55:00,efc2b86bb796b0143f61667402612dfbb85cbb78,SC4442EV-Hypnogram.edf +45,1,PSG,66,female,00:26:00,315db0f9d91988ddc2b198f89cc22f96190eff71,SC4451F0-PSG.edf +45,1,Hypnogram,66,female,00:26:00,bc1f755c3367e378091c44481948a72fc7a928e5,SC4451FY-Hypnogram.edf +45,2,PSG,66,female,00:34:00,a06350e1c85b61c30c3d7d5dc640121b416fe30d,SC4452F0-PSG.edf +45,2,Hypnogram,66,female,00:34:00,0286d52cdf898ed8e3b17bb26b9c50ef512daf4d,SC4452FW-Hypnogram.edf +46,1,PSG,66,female,00:30:00,e4295014c6d4474d8f7f7792c2ea088eb9e43e9f,SC4461F0-PSG.edf +46,1,Hypnogram,66,female,00:30:00,8980e770e58e5704bd36124f6b6bd8d5e3506e12,SC4461FA-Hypnogram.edf +46,2,PSG,66,female,00:38:00,53b69cb41339bc69144eaa5a5a42c2937f237fc9,SC4462F0-PSG.edf +46,2,Hypnogram,66,female,00:38:00,0c6d3974e140c1e62ed2cadaed395781575af042,SC4462FJ-Hypnogram.edf +47,1,PSG,73,female,22:36:00,05d71b55de4c86791195391b1cec8b35e447922d,SC4471F0-PSG.edf +47,1,Hypnogram,73,female,22:36:00,ee235454dbfe947432f3f813c9a6384f6e42d36a,SC4471FA-Hypnogram.edf +47,2,PSG,73,female,22:25:00,7a12c0d6f3005998472b128e06dd645a8619dae7,SC4472F0-PSG.edf +47,2,Hypnogram,73,female,22:25:00,d234d5d6c396bf7ef0a2106a59ee8204429aa3c5,SC4472FA-Hypnogram.edf +48,1,PSG,67,female,23:04:00,c15f6a0e1802dcf74ecec41745677a4932375faf,SC4481F0-PSG.edf +48,1,Hypnogram,67,female,23:04:00,50fce6396aceaf35d9d7e16175053a3b78f214d0,SC4481FV-Hypnogram.edf +48,2,PSG,67,female,23:57:00,34d71530fd1da925ba20b4c48a07f7b18153e0c7,SC4482F0-PSG.edf +48,2,Hypnogram,67,female,23:57:00,e3c48563e63eed27b071d4a7b37c45a0f9dc7eef,SC4482FJ-Hypnogram.edf +49,1,PSG,67,female,23:26:00,23ea1f5f299c6cd99d434f014d7490621dbbc854,SC4491G0-PSG.edf +49,1,Hypnogram,67,female,23:26:00,36c6c8112524c7bc9553db37601b38984946209b,SC4491GJ-Hypnogram.edf +49,2,PSG,67,female,00:13:00,02c975bfc0773928095239b80d00ac5a7ea5880f,SC4492G0-PSG.edf +49,2,Hypnogram,67,female,00:13:00,3673eaad8396ef0ec36cb4299541c30653b72e1f,SC4492GJ-Hypnogram.edf +50,1,PSG,71,male,22:07:00,1c31fc02412029bc7369979b8c9f5956420748f5,SC4501E0-PSG.edf +50,1,Hypnogram,71,male,22:07:00,eb2621c1670a42eb38dfa86a9bc3326818365f3d,SC4501EW-Hypnogram.edf +50,2,PSG,71,male,23:40:00,ff9eae25afa73115e2b184a68e3a72a39efd37e6,SC4502E0-PSG.edf +50,2,Hypnogram,71,male,23:40:00,7605a1893701925ea0fdd047926bbd6c7c043875,SC4502EM-Hypnogram.edf +51,1,PSG,70,male,23:10:00,e12eb259c2894d45b8d0b2f0e75810c2de02237d,SC4511E0-PSG.edf +51,1,Hypnogram,70,male,23:10:00,e549275e9182b9e36ade5abb721098e235ecb164,SC4511EJ-Hypnogram.edf +51,2,PSG,70,male,00:03:00,53c5d982139d248736f6dd7ff3f97f635647eacd,SC4512E0-PSG.edf +51,2,Hypnogram,70,male,00:03:00,e22966c263f6ae7444704881f5249f6fb5dee0c1,SC4512EW-Hypnogram.edf +52,2,PSG,69,male,23:53:00,af70ffdbd3012615923f6a4901e7c0dd3a0fd8ca,SC4522E0-PSG.edf +52,2,Hypnogram,69,male,23:53:00,57af3eaed541229dcb2478c6050f0582e020f878,SC4522EM-Hypnogram.edf +53,1,PSG,67,male,23:49:00,71222ac5b7784ed1d3a79ee3e9036431d6eba9bd,SC4531E0-PSG.edf +53,1,Hypnogram,67,male,23:49:00,934dbfeb29f4f4db4b61e36fb8ddab4ddbf4ff94,SC4531EM-Hypnogram.edf +53,2,PSG,67,male,23:53:00,2d472fb64da5d05a546f780da876b90ad26208f9,SC4532E0-PSG.edf +53,2,Hypnogram,67,male,23:53:00,708b43e7d43a6f5719f48c11bd6a81b037aabfc4,SC4532EV-Hypnogram.edf +54,1,PSG,73,male,23:00:00,4d3ec2f85149bb10fed1013831c3aa1f58049229,SC4541F0-PSG.edf +54,1,Hypnogram,73,male,23:00:00,a301385e6fbde02c83f2545f17cdf75d594d37ce,SC4541FA-Hypnogram.edf +54,2,PSG,73,male,23:30:00,2909f5b0d3fdb89e19d42b406798e9cbb4615bb6,SC4542F0-PSG.edf +54,2,Hypnogram,73,male,23:30:00,9548ed641fb961fa46706339891a9453b731369f,SC4542FW-Hypnogram.edf +55,1,PSG,71,male,22:40:00,0bf97e463cbcefb7df48bca712f29dcc74223330,SC4551F0-PSG.edf +55,1,Hypnogram,71,male,22:40:00,e50b44e6b049baaeb528c31563642b2a2b933834,SC4551FC-Hypnogram.edf +55,2,PSG,71,male,22:29:00,dfa0adaae50110bdd0077483c31d57956020fcb9,SC4552F0-PSG.edf +55,2,Hypnogram,71,male,22:29:00,7380403f8d72fa4c30013cd026cc1dad23ac2b3e,SC4552FW-Hypnogram.edf +56,1,PSG,72,male,23:14:00,1a9baf1b072ca9d2784a404292169ff3177ea83f,SC4561F0-PSG.edf +56,1,Hypnogram,72,male,23:14:00,b31a2dfe652508df46f6afe03ab904c333f7b818,SC4561FJ-Hypnogram.edf +56,2,PSG,72,male,23:22:00,4c7081edf572cadee51d30174cd65aa6c658f5a9,SC4562F0-PSG.edf +56,2,Hypnogram,72,male,23:22:00,676ab92dbc6532f67d672f80337c71f817fd3a6d,SC4562FJ-Hypnogram.edf +57,1,PSG,66,male,23:02:00,e67f3bd381ddfb96d584f6c6d6f6762087d6553d,SC4571F0-PSG.edf +57,1,Hypnogram,66,male,23:02:00,08ee39eb94d819968512297ca883f9bca046de9c,SC4571FV-Hypnogram.edf +57,2,PSG,66,male,23:51:00,deb2aef7a6a4b502c819345a7151ffc2529d4ba7,SC4572F0-PSG.edf +57,2,Hypnogram,66,male,23:51:00,7a38cbe581167dfec27a15935e6d386b228616fa,SC4572FC-Hypnogram.edf +58,1,PSG,67,male,22:36:00,16a1edbd6a089386fd7de72aef802182d0a2959d,SC4581G0-PSG.edf +58,1,Hypnogram,67,male,22:36:00,bfc729575cfdf5f409be2de47dad4e00d43195bf,SC4581GM-Hypnogram.edf +58,2,PSG,67,male,23:04:00,9da93f4c2459dd4fe2e5ee6a171904d4f604cd6e,SC4582G0-PSG.edf +58,2,Hypnogram,67,male,23:04:00,acbade13cfae4fc5fbda2d0766feea83d114aa23,SC4582GP-Hypnogram.edf +59,1,PSG,67,male,23:25:00,017793b040df8a860df0e43e3e0a496e2cb3f9c1,SC4591G0-PSG.edf +59,1,Hypnogram,67,male,23:25:00,f3bb949a7f82acb7fd3d8f35e92efee1402a383f,SC4591GY-Hypnogram.edf +59,2,PSG,67,male,00:14:00,1e284bddd7952862327c83092db21805e6ab6c38,SC4592G0-PSG.edf +59,2,Hypnogram,67,male,00:14:00,58d1678e9ec9f49c9c6a15031dee26d802026851,SC4592GY-Hypnogram.edf +60,1,PSG,89,female,21:35:00,ece6d6ce09fac6fc521cf3f1b536f1ea2a8a1778,SC4601E0-PSG.edf +60,1,Hypnogram,89,female,21:35:00,8f77b05fe58f43cdfdcdba7cc3d27abcac7d37f2,SC4601EC-Hypnogram.edf +60,2,PSG,89,female,23:00:00,0e50df304ced29651267f43689ce49e063f808d6,SC4602E0-PSG.edf +60,2,Hypnogram,89,female,23:00:00,1c52de92668fe4c89cd5e270e17017ef47880991,SC4602EJ-Hypnogram.edf +61,1,PSG,101,female,00:20:00,2cc6e418c0b7af472aa34d2bbd5ece85bdb6a879,SC4611E0-PSG.edf +61,1,Hypnogram,101,female,00:20:00,f5715ab48f24221c28c1d5c45508c8bb58c912ec,SC4611EG-Hypnogram.edf +61,2,PSG,101,female,01:00:00,6593e1af07101fa4c5bce8984296858be17e7d4f,SC4612E0-PSG.edf +61,2,Hypnogram,101,female,01:00:00,cedb61bbe7a273b12f45579963d5a84f2ab21811,SC4612EA-Hypnogram.edf +62,1,PSG,95,female,21:00:00,31cd2cae56977c6b872311f2a6e60827748b973d,SC4621E0-PSG.edf +62,1,Hypnogram,95,female,21:00:00,7acc5296b33ca4eee8d6577064c8c651ee96e527,SC4621EV-Hypnogram.edf +62,2,PSG,95,female,21:00:00,7a7e226d47dccd959305e3f633686335c8e66557,SC4622E0-PSG.edf +62,2,Hypnogram,95,female,21:00:00,9957c9c9e0c705aac0f7125f411b2531a722601c,SC4622EJ-Hypnogram.edf +63,1,PSG,91,female,00:15:00,6dfb32aa4c94968a52d61b90a38573d178669bfb,SC4631E0-PSG.edf +63,1,Hypnogram,91,female,00:15:00,48e28f93fc71ffc539776196f9d9d1365415e0b4,SC4631EM-Hypnogram.edf +63,2,PSG,91,female,23:39:00,3baa8081b30cc3dfece9d550289dfc94812530d5,SC4632E0-PSG.edf +63,2,Hypnogram,91,female,23:39:00,cd2765ebdabc66cb4ac2320d02e3b7ab0340ede4,SC4632EA-Hypnogram.edf +64,1,PSG,85,female,22:30:00,0e5d109a929490cbecf59573577a97df07a05cd0,SC4641E0-PSG.edf +64,1,Hypnogram,85,female,22:30:00,7b896dc5b34d71381d8462001dc3e05b145cf48c,SC4641EP-Hypnogram.edf +64,2,PSG,85,female,22:17:00,03169b7ee9de83b2e17e9bd0d6274965e9518b37,SC4642E0-PSG.edf +64,2,Hypnogram,85,female,22:17:00,d8a870d26e468a643eaebe3275e5e2912690c0d8,SC4642EP-Hypnogram.edf +65,1,PSG,88,female,23:10:00,f2134a2ad001bc146f3e2d9d76cb7f00f03bbe52,SC4651E0-PSG.edf +65,1,Hypnogram,88,female,23:10:00,fad4311c7e11a9aa9a73a8e48d6fa966db61e71d,SC4651EP-Hypnogram.edf +65,2,PSG,88,female,23:00:00,aa66553cb0132634d7d11ffe7fab80aa5119b3d7,SC4652E0-PSG.edf +65,2,Hypnogram,88,female,23:00:00,6ed9c4f66c03e56f86730ddd8986f3600c040d4a,SC4652EG-Hypnogram.edf +66,1,PSG,88,female,21:52:00,c6057505d2acf7b08371e266cf0fca1bfeb1e4e1,SC4661E0-PSG.edf +66,1,Hypnogram,88,female,21:52:00,06474e72126d2a00c1968e70730e1deac060f94e,SC4661EJ-Hypnogram.edf +66,2,PSG,88,female,21:56:00,24d278194360dc78ebd0cfe940fb4d5f7f93ccbc,SC4662E0-PSG.edf +66,2,Hypnogram,88,female,21:56:00,07ca0fbfb6030289a089f84e50d7bbfd043f31ad,SC4662EJ-Hypnogram.edf +67,1,PSG,87,female,22:49:00,4357aa9fedf0b53896d41e5dccd7b525f7212177,SC4671G0-PSG.edf +67,1,Hypnogram,87,female,22:49:00,459889157743c434933194446af5168cb145dfcb,SC4671GJ-Hypnogram.edf +67,2,PSG,87,female,23:52:00,fd86b31a5c22176e1887e2fac460edce42bd2fdf,SC4672G0-PSG.edf +67,2,Hypnogram,87,female,23:52:00,dedb182b8c063cefabf1763eb19cd26d0608017f,SC4672GV-Hypnogram.edf +70,1,PSG,89,male,21:40:00,3f60b5ad5e1092e90c38f2072b3c041bd7313550,SC4701E0-PSG.edf +70,1,Hypnogram,89,male,21:40:00,196a388f60ee4aecfa982f89e2db03ff91e906e7,SC4701EC-Hypnogram.edf +70,2,PSG,89,male,21:39:00,a6853fee26b1541f85be7ddc3f42f06ccfe2fcfc,SC4702E0-PSG.edf +70,2,Hypnogram,89,male,21:39:00,464f7382ec11703b5bc6512930fdfbb1ab6d030a,SC4702EA-Hypnogram.edf +71,1,PSG,88,male,21:15:00,e97d691bfecf770ca4e47289b846886c16ef19fb,SC4711E0-PSG.edf +71,1,Hypnogram,88,male,21:15:00,81ec5d0288f36c4368e5f06f21980f99774bf533,SC4711EC-Hypnogram.edf +71,2,PSG,88,male,23:18:00,9b99be6cb45af22bdbead7ea01f1375631c9b365,SC4712E0-PSG.edf +71,2,Hypnogram,88,male,23:18:00,66b121441a45ae19852b7002fd78c2caf236631a,SC4712EA-Hypnogram.edf +72,1,PSG,88,male,23:04:00,5c9caa01cc1f8065f87195c9f2dc2aeebf83c03d,SC4721E0-PSG.edf +72,1,Hypnogram,88,male,23:04:00,efe62b1e8bac1ea08dbf12374ca6812a6f271d5e,SC4721EC-Hypnogram.edf +72,2,PSG,88,male,23:09:00,a473f32a6075e9ed830a8e9a246129e05959e8b7,SC4722E0-PSG.edf +72,2,Hypnogram,88,male,23:09:00,efb2358de27da4219f64f7bfb37912dc9efb0281,SC4722EM-Hypnogram.edf +73,1,PSG,97,male,22:30:00,b03e4a2df4d086778f3426ed7b6c5bf800cbfe92,SC4731E0-PSG.edf +73,1,Hypnogram,97,male,22:30:00,eb3dc65d7184d676a6678a70b18730d11a414588,SC4731EM-Hypnogram.edf +73,2,PSG,97,male,22:00:00,574ff5c0634137f7d5c51eb5f7626b451f1f9b9d,SC4732E0-PSG.edf +73,2,Hypnogram,97,male,22:00:00,77a523ca9ef4698885b681bf4e27d28dc5c58424,SC4732EJ-Hypnogram.edf +74,1,PSG,92,male,23:14:00,e6ff7462f4ce401e9aff9b3d9c93f0710bc37678,SC4741E0-PSG.edf +74,1,Hypnogram,92,male,23:14:00,bda4d1ab190f4160ec7a3f4420e30d718f02369e,SC4741EA-Hypnogram.edf +74,2,PSG,92,male,23:06:00,2b09f78a2f276061c8758a55585fae7355b38111,SC4742E0-PSG.edf +74,2,Hypnogram,92,male,23:06:00,d4bb4266859c2f92ae8ba96111d59d8ab467f6a0,SC4742EC-Hypnogram.edf +75,1,PSG,96,male,22:58:00,17c356a283b026e507331209512453573bcfebe5,SC4751E0-PSG.edf +75,1,Hypnogram,96,male,22:58:00,d35737e86979127ea01b95dcecea018dd2e44f45,SC4751EC-Hypnogram.edf +75,2,PSG,96,male,23:00:00,b650a49d6e3bb81971e4689c720ee079404857e6,SC4752E0-PSG.edf +75,2,Hypnogram,96,male,23:00:00,3d1c86d8d7ecb6ff79ee12cb950690e929394161,SC4752EM-Hypnogram.edf +76,1,PSG,90,male,23:28:00,8bde3f0d5ab6a592f229dfd7886341b3f800bdb3,SC4761E0-PSG.edf +76,1,Hypnogram,90,male,23:28:00,3dbf15f28a293ac89dcf458d844a8c6443aaf1e6,SC4761EP-Hypnogram.edf +76,2,PSG,90,male,01:29:00,7bdc8eacf1a6502c8f007b08556b7e8b52180d44,SC4762E0-PSG.edf +76,2,Hypnogram,90,male,01:29:00,f6ae10f082a10ead671bfd5fdc50f62c42b9f10d,SC4762EG-Hypnogram.edf +77,1,PSG,85,male,23:23:00,ac8c2be9175cb02e00cccb5d5df2acfaf05971cc,SC4771G0-PSG.edf +77,1,Hypnogram,85,male,23:23:00,09e80b973502d89368d7823ad4aec7417b735f6e,SC4771GC-Hypnogram.edf +77,2,PSG,85,male,00:10:00,eea8671791936358037e5d096491865069989a85,SC4772G0-PSG.edf +77,2,Hypnogram,85,male,00:10:00,25a3b8859091a70ca0cff9ebb777879aa156689e,SC4772GC-Hypnogram.edf +80,1,PSG,54,female,23:05:00,0ce00a144dd9bc1b0e20cd30e6501a3852e4dbef,SC4801G0-PSG.edf +80,1,Hypnogram,54,female,23:05:00,f82d2b8e45723f2a69f8c30286cc68486b0792a6,SC4801GC-Hypnogram.edf +80,2,PSG,54,female,23:18:00,8959ada929c07945757bd6c9ef0267e7c9427a66,SC4802G0-PSG.edf +80,2,Hypnogram,54,female,23:18:00,41ff2d1118425f5828342c07aa58b9d346755b1a,SC4802GV-Hypnogram.edf +81,1,PSG,57,female,22:00:00,dcae3307af54ccf5349945e2fa493464de0a5da2,SC4811G0-PSG.edf +81,1,Hypnogram,57,female,22:00:00,2406ce37b86fc3c7492a3ebe89ae58d15686b33d,SC4811GG-Hypnogram.edf +81,2,PSG,57,female,21:56:00,fd93757cf6bcf45854fca960a067612352e05547,SC4812G0-PSG.edf +81,2,Hypnogram,57,female,21:56:00,244b3bbb4987db0a9cef85950d14899ab9a3aec4,SC4812GV-Hypnogram.edf +82,1,PSG,56,female,23:59:00,9008c6ffc917fb90a3d399e768fe3c563a144a2f,SC4821G0-PSG.edf +82,1,Hypnogram,56,female,23:59:00,59534244c603cd5c3c27db26ae2f014983ec6c9b,SC4821GC-Hypnogram.edf +82,2,PSG,56,female,00:05:00,84f9a60f6b0e7ac33388d8f6492096bcfa60bc18,SC4822G0-PSG.edf +82,2,Hypnogram,56,female,00:05:00,8d14c371bc290658469729addee4461866bb67e2,SC4822GC-Hypnogram.edf diff --git a/mne-python/source/mne/datasets/sleep_physionet/temazepam.py b/mne-python/source/mne/datasets/sleep_physionet/temazepam.py new file mode 100644 index 0000000000000000000000000000000000000000..443b4057f55d6713dc604b311855af549b0716f2 --- /dev/null +++ b/mne-python/source/mne/datasets/sleep_physionet/temazepam.py @@ -0,0 +1,119 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import time + +import numpy as np + +from ...utils import verbose +from ..utils import _log_time_size +from ._utils import TEMAZEPAM_SLEEP_RECORDS, _check_subjects, _data_path, _fetch_one + +data_path = _data_path # expose _data_path(..) as data_path(..) + +BASE_URL = "https://physionet.org/physiobank/database/sleep-edfx/sleep-telemetry/" # noqa: E501 + + +@verbose +def fetch_data( + subjects, path=None, force_update=False, base_url=BASE_URL, *, verbose=None +): + """Get paths to local copies of PhysioNet Polysomnography dataset files. + + This will fetch data from the publicly available subjects from PhysioNet's + study of Temazepam effects on sleep :footcite:`KempEtAl2000`. This + corresponds to a set of 22 subjects. Subjects had mild difficulty falling + asleep but were otherwise healthy. + + See more details in the `physionet website + `_ + :footcite:`GoldbergerEtAl2000`. + + Parameters + ---------- + subjects : list of int + The subjects to use. Can be in the range of 0-21 (inclusive). + path : None | str + Location of where to look for the PhysioNet data storing location. + If None, the environment variable or config parameter + ``PHYSIONET_SLEEP_PATH`` is used. If it doesn't exist, the "~/mne_data" + directory is used. If the Polysomnography dataset is not found under + the given path, the data will be automatically downloaded to the + specified folder. + force_update : bool + Force update of the dataset even if a local copy exists. + base_url : str + The base URL to download from. + %(verbose)s + + Returns + ------- + paths : list + List of local data paths of the given type. + + See Also + -------- + mne.datasets.sleep_physionet.age.fetch_data + + Notes + ----- + For example, one could do: + + >>> from mne.datasets import sleep_physionet + >>> sleep_physionet.temazepam.fetch_data(subjects=[1]) # doctest: +SKIP + + This would download data for subject 0 if it isn't there already. + + References + ---------- + .. footbibliography:: + """ + t0 = time.time() + records = np.loadtxt( + TEMAZEPAM_SLEEP_RECORDS, + skiprows=1, + delimiter=",", + usecols=(0, 3, 6, 7, 8, 9), + dtype={ + "names": ( + "subject", + "record", + "hyp sha", + "psg sha", + "hyp fname", + "psg fname", + ), + "formats": (" 0: + _log_time_size(t0, sz) + return fnames diff --git a/mne-python/source/mne/datasets/sleep_physionet/temazepam_records.csv b/mne-python/source/mne/datasets/sleep_physionet/temazepam_records.csv new file mode 100644 index 0000000000000000000000000000000000000000..382221964c145783dba2e14be5c9d5bcfdf9d178 --- /dev/null +++ b/mne-python/source/mne/datasets/sleep_physionet/temazepam_records.csv @@ -0,0 +1,45 @@ +subject,age,sex,drug,lights off,night nr,sha_Hypnogram,sha_PSG,fname_Hypnogram,fname_PSG,subject_orig +0,60,male,Placebo,23:01:00,1,ff28e5e01296cefed49ae0c27cfb3ebc42e710bf,b9d11484126ebff1884034396d6a20c62c0ef48d,ST7011JP-Hypnogram.edf,ST7011J0-PSG.edf,1 +0,60,male,Temazepam,23:48:00,2,7a98a0ebba9e5e8fc4aac9ab82849385570d7789,b97c67d2ec40721349fd6faea32ea7155a11940a,ST7012JP-Hypnogram.edf,ST7012J0-PSG.edf,1 +1,35,female,Temazepam,00:00:00,1,635b07240047ade50649ff0f72ccde792f464f09,552e579d96e6c4ae083c7e1422e11b945ebcdabd,ST7021JM-Hypnogram.edf,ST7021J0-PSG.edf,2 +1,35,female,Placebo,23:27:00,2,228c608743abcc28f8c4946e8394ecf8e6ada89c,ebabfa224599201d9baf91311f78f6410971810f,ST7022JM-Hypnogram.edf,ST7022J0-PSG.edf,2 +2,18,female,Placebo,23:53:00,1,422655bae4525d121bd45fead048207be9b34c4b,41f8e344b9872d93c8c2f2da283252231584b08f,ST7041JO-Hypnogram.edf,ST7041J0-PSG.edf,4 +2,18,female,Temazepam,22:37:00,2,eff297358a0c9d175109ba692ac3f9f4cd2c08ed,229ee3bb4d060332c219c3dc1153732ab5499d57,ST7042JO-Hypnogram.edf,ST7042J0-PSG.edf,4 +3,32,female,Temazepam,23:34:00,1,d7696bd1b891dd85e96e20ea727dcebe49ab6dfd,17b186214e8944667571f52098564e377b32d695,ST7051JA-Hypnogram.edf,ST7051J0-PSG.edf,5 +3,32,female,Placebo,23:23:00,2,64f2718c004e64ab598979da139b90452febc9bf,489fcb38c07688192d9c0eae5455d95241028ad8,ST7052JA-Hypnogram.edf,ST7052J0-PSG.edf,5 +4,35,female,Placebo,23:28:00,1,fd9214d026453fce71efa2975ea732e1c1458f69,9fb2b4ed47a6d4b2f0b60a354123e491e8738b19,ST7061JR-Hypnogram.edf,ST7061J0-PSG.edf,6 +4,35,female,Temazepam,23:26:00,2,c2a4abe15f08f230b734a328494ab0d2ae9dc786,afc5599194648da5568dafa1a811818e77df4842,ST7062JR-Hypnogram.edf,ST7062J0-PSG.edf,6 +5,51,female,Placebo,00:02:00,1,bc08c797bb7aaf92de1c869d46c6dd4590939996,010a65ad86b79d19c372a421f0e7c975e56278c8,ST7071JA-Hypnogram.edf,ST7071J0-PSG.edf,7 +5,51,female,Temazepam,23:24:00,2,1a7813b7a2389c0346e3844835590b9cb2f40f56,15c5aa5591e35d60ba25044cdd4b3d748d3c0cfc,ST7072JA-Hypnogram.edf,ST7072J0-PSG.edf,7 +6,66,female,Temazepam,23:53:00,1,8259b52c62203b85268d23b3a2d87605fdcfa2a6,cb66a0493d90d0d1204936e3e7c944ed536265e3,ST7081JW-Hypnogram.edf,ST7081J0-PSG.edf,8 +6,66,female,Placebo,23:20:00,2,bc33c3aba61c0fa937ef56d4ce7b1468c80663b5,b1cb29c7a7321b7e628d04a477338c4f62f0c093,ST7082JW-Hypnogram.edf,ST7082J0-PSG.edf,8 +7,47,male,Temazepam,23:42:00,1,af845641a8118d004bcfa6b597f23517e3a752e9,b046dd63d92339914eca0489d8a4c566b69e7723,ST7091JE-Hypnogram.edf,ST7091J0-PSG.edf,9 +7,47,male,Placebo,00:30:00,2,ec89bb908ff70e123ffa94bc2c11bb1ce54bcb6a,2986f4d64f5118c5e356a2abe6bf86521ffde339,ST7092JE-Hypnogram.edf,ST7092J0-PSG.edf,9 +8,20,female,Placebo,23:21:00,1,5919542c566d882fbf947c66f4858ad17199103a,5662b560f095b8397303cced87e43d407a0d18f7,ST7101JE-Hypnogram.edf,ST7101J0-PSG.edf,10 +8,20,female,Temazepam,23:28:00,2,1f05e92c9ca076350f981d0ec75ad720606bacbc,f697a140f18d1005107fcbb7c81d85a5e8cb6ec6,ST7102JE-Hypnogram.edf,ST7102J0-PSG.edf,10 +9,21,female,Temazepam,23:38:00,1,5964553fe07cbca302526b2153a2507f7d02fab8,e2bf9db482f230a56372603d23fb12f5c56062f7,ST7111JE-Hypnogram.edf,ST7111J0-PSG.edf,11 +9,21,female,Placebo,23:52:00,2,e4d8406eaca361d2c5d9953b3c67ed1098dd5925,d3c7907b9b1e4f087f31bd655548b8673b6ec735,ST7112JE-Hypnogram.edf,ST7112J0-PSG.edf,11 +10,21,male,Placebo,23:46:00,1,a991ed3d8be6d55ee563545077f3d280466a4989,6e90bac48e48f71e5572944a364009eab6ea818d,ST7121JE-Hypnogram.edf,ST7121J0-PSG.edf,12 +10,21,male,Temazepam,23:56:00,2,b6c2c21e3cf17b371b31af78c64f28aa5811e36f,ae7426c464296ec0a839ccaa9763e3f2c57f41f1,ST7122JE-Hypnogram.edf,ST7122J0-PSG.edf,12 +11,22,male,Temazepam,00:38:00,1,91ee1bd29b156b33e03cb8c324a8fac15ec06674,d0d6c83b76f627b067e0daac3c181e3666f8ab08,ST7131JR-Hypnogram.edf,ST7131J0-PSG.edf,13 +11,22,male,Placebo,00:31:00,2,028a5c4ed911d67a17b45f12966b32c46949d374,54a50dcc40e3d6677b80c629b2f908339d9a7c3e,ST7132JR-Hypnogram.edf,ST7132J0-PSG.edf,13 +12,20,male,Placebo,00:40:00,1,203e78e02a92a9f85f07790398f64c66f248e5cc,6bf8feeabc2259d15f1f535abda90caacc8d4a86,ST7141JE-Hypnogram.edf,ST7141J0-PSG.edf,14 +12,20,male,Temazepam,00:53:00,2,1f7cc3a1923dd6a3504c82d76f820555ad0b6a1b,b42eb28089bbdcbf3244dead53fd01d5f5ac3ddf,ST7142JE-Hypnogram.edf,ST7142J0-PSG.edf,14 +13,66,female,Placebo,23:42:00,1,cfcb0089e22244bc5047f61e72a39735cbdc36cf,c0df1253b6509c4b4ed9e1283f26cf206a8c725c,ST7151JA-Hypnogram.edf,ST7151J0-PSG.edf,15 +13,66,female,Temazepam,23:33:00,2,27e9b4527eea33ded9072db3c6626f94a966da58,faefa07a1ca180861d6f26d5f35285c009dca21e,ST7152JA-Hypnogram.edf,ST7152J0-PSG.edf,15 +14,79,female,Temazepam,23:18:00,1,5a1ef1d375b01f83264e84db4af58acded68f15e,8a4f1c44a17b5d665cc30f1141d003043274ac2b,ST7161JM-Hypnogram.edf,ST7161J0-PSG.edf,16 +14,79,female,Placebo,23:21:00,2,18b3d7eb9685ec8131fc0a8f81ba6205122595dc,66925c8fa9f6da18f8590dcf2a6174cfe46e912d,ST7162JM-Hypnogram.edf,ST7162J0-PSG.edf,16 +15,48,female,Placebo,23:40:00,1,13c371fc4384751cc4bdd3044c6a0813ea12816e,67c47cb92de8806c60303a4baa87ca6cf52a2245,ST7171JA-Hypnogram.edf,ST7171J0-PSG.edf,17 +15,48,female,Temazepam,23:48:00,2,8de0f3f59dd27d07f5f6a74216814ced08f104b5,a46118a5ca9cfaa62ca11c6a8b079e82877305ef,ST7172JA-Hypnogram.edf,ST7172J0-PSG.edf,17 +16,53,female,Temazepam,23:24:00,1,483aa0b448393d61043c98c204c93d4c60abb6bd,501f2f9d9ebe15e6dfc86fda6e90f9a54a39660a,ST7181JR-Hypnogram.edf,ST7181J0-PSG.edf,18 +16,53,female,Placebo,23:38:00,2,50efc607882659f8229db773703f5b973b471ed4,0eab40d3687a2cf708e48137eab26c0c43b75773,ST7182JR-Hypnogram.edf,ST7182J0-PSG.edf,18 +17,28,female,Temazepam,23:44:00,1,e7fcb89cf0f1484ab114bf40dcf2bf4cd413696b,b1b10cd45a7c0f91286c6fc3f755e59af483bac1,ST7191JR-Hypnogram.edf,ST7191J0-PSG.edf,19 +17,28,female,Placebo,23:22:00,2,def09a7d469984005b0c8414b7995ae8e269fd15,e80de913aa41b987a43d94cf8f0106d61e4e883b,ST7192JR-Hypnogram.edf,ST7192J0-PSG.edf,19 +18,24,male,Placebo,23:47:00,1,17a0e8aebb885a960a74343bace57d2ab0b6296a,454233ae9e6a948848030c5f4d9e60dfcb0facde,ST7201JO-Hypnogram.edf,ST7201J0-PSG.edf,20 +18,24,male,Temazepam,00:01:00,2,ed26efdb6b2d9e815f2a725970262cb9c15c7b98,1e97e392968415da67432842c952344b6d3cdc8c,ST7202JO-Hypnogram.edf,ST7202J0-PSG.edf,20 +19,34,female,Temazepam,23:10:00,1,b8756397056f623674c3b03db808b2c8c64b0a0a,c6582cfa8fcf6542a688fa8842011a93d86f2c60,ST7211JJ-Hypnogram.edf,ST7211J0-PSG.edf,21 +19,34,female,Placebo,23:44:00,2,e25e47adf0c0f09df542ef061272ed9569fb80ea,389f3920b39b4b9ad4fba6f91198299b7c6f6676,ST7212JJ-Hypnogram.edf,ST7212J0-PSG.edf,21 +20,56,male,Placebo,23:22:00,1,7656827835362b7b44b296bad83ff6001e14f489,58315bec82d381dec56bf96924a94014462bb608,ST7221JA-Hypnogram.edf,ST7221J0-PSG.edf,22 +20,56,male,Temazepam,23:44:00,2,da840db60086e43a2429fb1322ede5e5976b3cda,4961a08b87416246b8b8186190eca0e96da6a50d,ST7222JA-Hypnogram.edf,ST7222J0-PSG.edf,22 +21,48,female,Placebo,23:27:00,1,bbaac4f2c2f330f70583eb179d855fcf42b4fbff,7a850ce4bc6bd14ea072f3a45b002f8015cf2f14,ST7241JO-Hypnogram.edf,ST7241J0-PSG.edf,24 +21,48,female,Temazepam,23:36:00,2,f70b3dfce2c14f01221a66a4acb522df1affffdb,5c8bd182bfc9609929094769718b2835fe1099ad,ST7242JO-Hypnogram.edf,ST7242J0-PSG.edf,24 diff --git a/mne-python/source/mne/datasets/sleep_physionet/tests/test_physionet.py b/mne-python/source/mne/datasets/sleep_physionet/tests/test_physionet.py new file mode 100644 index 0000000000000000000000000000000000000000..5cb315f90643e9e6743d5cb0bdcd31984f81ea09 --- /dev/null +++ b/mne-python/source/mne/datasets/sleep_physionet/tests/test_physionet.py @@ -0,0 +1,214 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import pytest + +from mne.datasets.sleep_physionet import age, temazepam +from mne.datasets.sleep_physionet._utils import ( + AGE_SLEEP_RECORDS, + TEMAZEPAM_SLEEP_RECORDS, + _update_sleep_age_records, + _update_sleep_temazepam_records, +) +from mne.utils import requires_good_network + + +@pytest.fixture(scope="session") +def physionet_tmpdir(tmp_path_factory): + """Fixture exposing a temporary directory for testing.""" + return str(tmp_path_factory.mktemp("physionet_files")) + + +def _keep_basename_only(paths): + return [Path(p).name for p in paths] + + +def _get_expected_url(name): + base = "https://physionet.org/physiobank/database/sleep-edfx/" + middle = "sleep-cassette/" if name.startswith("SC") else "sleep-telemetry/" + return base + middle + "/" + name + + +def _get_expected_path(base, name): + return Path(base, name) + + +def _check_mocked_function_calls(mocked_func, call_fname_hash_pairs, base_path): + # Check mocked_func has been called the right amount of times. + assert mocked_func.call_count == len(call_fname_hash_pairs) + + # Check it has been called with the right parameters in the right + # order. + for idx, current in enumerate(call_fname_hash_pairs): + _, call_kwargs = mocked_func.call_args_list[idx] + hash_type, hash_ = call_kwargs["known_hash"].split(":") + assert call_kwargs["url"] == _get_expected_url(current["name"]), idx + assert Path(call_kwargs["path"], call_kwargs["fname"]) == _get_expected_path( + base_path, current["name"] + ) + assert hash_ == current["hash"] + assert hash_type == "sha1" + + +@pytest.mark.timeout(60) +@pytest.mark.xfail(strict=False) +@requires_good_network +def test_run_update_age_records(tmp_path): + """Test Sleep Physionet URL handling.""" + pd = pytest.importorskip("pandas") + pytest.importorskip("xlrd", "0.9") + + fname = tmp_path / "records.csv" + _update_sleep_age_records(fname) + data = pd.read_csv(fname) + pd.testing.assert_frame_equal(data, pd.read_csv(AGE_SLEEP_RECORDS)) + + +@pytest.mark.parametrize("subject", [39, 68, 69, 78, 79, 83]) +def test_sleep_physionet_age_missing_subjects( + physionet_tmpdir, subject, download_is_error +): + """Test handling of missing subjects in Sleep Physionet age fetcher.""" + with pytest.raises(ValueError, match="This dataset contains subjects 0 to 82"): + age.fetch_data( + subjects=[subject], recording=[1], on_missing="raise", path=physionet_tmpdir + ) + with pytest.warns(RuntimeWarning, match="This dataset contains subjects 0 to 82"): + age.fetch_data( + subjects=[subject], recording=[1], on_missing="warn", path=physionet_tmpdir + ) + paths = age.fetch_data( + subjects=[subject], recording=[1], on_missing="ignore", path=physionet_tmpdir + ) + assert paths == [] + + +@pytest.mark.parametrize("subject,recording", [(13, 2), (36, 1), (52, 1)]) +def test_sleep_physionet_age_missing_recordings( + physionet_tmpdir, subject, recording, download_is_error +): + """Test handling of missing recordings in Sleep Physionet age fetcher.""" + with pytest.raises( + ValueError, match=f"Requested recording {recording} for subject" + ): + age.fetch_data( + subjects=[subject], + recording=[recording], + on_missing="raise", + path=physionet_tmpdir, + ) + with pytest.warns( + RuntimeWarning, match=f"Requested recording {recording} for subject" + ): + age.fetch_data( + subjects=[subject], + recording=[recording], + on_missing="warn", + path=physionet_tmpdir, + ) + paths = age.fetch_data( + subjects=[subject], + recording=[recording], + on_missing="ignore", + path=physionet_tmpdir, + ) + assert paths == [] + + +def test_sleep_physionet_age(physionet_tmpdir, fake_retrieve): + """Test Sleep Physionet URL handling.""" + paths = age.fetch_data(subjects=[0], recording=[1], path=physionet_tmpdir) + assert _keep_basename_only(paths[0]) == [ + "SC4001E0-PSG.edf", + "SC4001EC-Hypnogram.edf", + ] + + paths = age.fetch_data(subjects=[0, 1], recording=[1], path=physionet_tmpdir) + assert _keep_basename_only(paths[0]) == [ + "SC4001E0-PSG.edf", + "SC4001EC-Hypnogram.edf", + ] + assert _keep_basename_only(paths[1]) == [ + "SC4011E0-PSG.edf", + "SC4011EH-Hypnogram.edf", + ] + + paths = age.fetch_data(subjects=[0], recording=[1, 2], path=physionet_tmpdir) + assert _keep_basename_only(paths[0]) == [ + "SC4001E0-PSG.edf", + "SC4001EC-Hypnogram.edf", + ] + assert _keep_basename_only(paths[1]) == [ + "SC4002E0-PSG.edf", + "SC4002EC-Hypnogram.edf", + ] + + EXPECTED_CALLS = ( + { + "name": "SC4001E0-PSG.edf", + "hash": "adabd3b01fc7bb75c523a974f38ee3ae4e57b40f", + }, + { + "name": "SC4001EC-Hypnogram.edf", + "hash": "21c998eadc8b1e3ea6727d3585186b8f76e7e70b", + }, + { + "name": "SC4011E0-PSG.edf", + "hash": "4d17451f7847355bcab17584de05e7e1df58c660", + }, + { + "name": "SC4011EH-Hypnogram.edf", + "hash": "d582a3cbe2db481a362af890bc5a2f5ca7c878dc", + }, + { + "name": "SC4002E0-PSG.edf", + "hash": "c6b6d7a8605cc7e7602b6028ee77f6fbf5f7581d", + }, + { + "name": "SC4002EC-Hypnogram.edf", + "hash": "386230188a3552b1fc90bba0fb7476ceaca174b6", + }, + ) + base_path = age.data_path(path=physionet_tmpdir) + _check_mocked_function_calls(fake_retrieve, EXPECTED_CALLS, base_path) + + +@pytest.mark.xfail(strict=False) +@requires_good_network +def test_run_update_temazepam_records(tmp_path): + """Test Sleep Physionet URL handling.""" + pd = pytest.importorskip("pandas") + pytest.importorskip("xlrd", "0.9") + fname = tmp_path / "records.csv" + _update_sleep_temazepam_records(fname) + data = pd.read_csv(fname) + + pd.testing.assert_frame_equal(data, pd.read_csv(TEMAZEPAM_SLEEP_RECORDS)) + + +def test_sleep_physionet_temazepam(physionet_tmpdir, fake_retrieve): + """Test Sleep Physionet URL handling.""" + paths = temazepam.fetch_data(subjects=[0], path=physionet_tmpdir) + assert _keep_basename_only(paths[0]) == [ + "ST7011J0-PSG.edf", + "ST7011JP-Hypnogram.edf", + ] + + EXPECTED_CALLS = ( + { + "name": "ST7011J0-PSG.edf", + "hash": "b9d11484126ebff1884034396d6a20c62c0ef48d", + }, + { + "name": "ST7011JP-Hypnogram.edf", + "hash": "ff28e5e01296cefed49ae0c27cfb3ebc42e710bf", + }, + ) + base_path = temazepam.data_path(path=physionet_tmpdir) + _check_mocked_function_calls(fake_retrieve, EXPECTED_CALLS, base_path) + + with pytest.raises(ValueError, match="This dataset contains subjects 0 to 21"): + paths = temazepam.fetch_data(subjects=[22], path=physionet_tmpdir) diff --git a/mne-python/source/mne/datasets/somato/__init__.py b/mne-python/source/mne/datasets/somato/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..24ad4524de036ab86c143956675d12b1641eb86a --- /dev/null +++ b/mne-python/source/mne/datasets/somato/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Somatosensory dataset.""" + +from .somato import data_path, get_version diff --git a/mne-python/source/mne/datasets/somato/somato.py b/mne-python/source/mne/datasets/somato/somato.py new file mode 100644 index 0000000000000000000000000000000000000000..177a642fb2ec3f295bf4b0753f7d1186f818daf4 --- /dev/null +++ b/mne-python/source/mne/datasets/somato/somato.py @@ -0,0 +1,32 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="somato", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="somato", conf="MNE_DATASETS_SOMATO_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("somato") + + +get_version.__doc__ = _version_doc.format(name="somato") diff --git a/mne-python/source/mne/datasets/spm_face/__init__.py b/mne-python/source/mne/datasets/spm_face/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a49e3432abe0f9ba2b62f41a5168b487c8ecbf12 --- /dev/null +++ b/mne-python/source/mne/datasets/spm_face/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""SPM face dataset.""" + +from .spm_data import data_path, has_spm_data, get_version, requires_spm_data diff --git a/mne-python/source/mne/datasets/spm_face/spm_data.py b/mne-python/source/mne/datasets/spm_face/spm_data.py new file mode 100644 index 0000000000000000000000000000000000000000..6653796e357dc7a180b4c4a3ad123c9020acd234 --- /dev/null +++ b/mne-python/source/mne/datasets/spm_face/spm_data.py @@ -0,0 +1,53 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from functools import partial + +from ...utils import get_config, verbose +from ..utils import ( + _data_path_doc, + _download_mne_dataset, + _get_version, + _version_doc, + has_dataset, +) + +has_spm_data = partial(has_dataset, name="spm") + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="spm", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format(name="spm", conf="MNE_DATASETS_SPM_DATA_PATH") + + +def get_version(): # noqa: D103 + return _get_version("spm") + + +get_version.__doc__ = _version_doc.format(name="spm") + + +def _skip_spm_data(): + skip_testing = get_config("MNE_SKIP_TESTING_DATASET_TESTS", "false") == "true" + skip = skip_testing or not has_spm_data() + return skip + + +def requires_spm_data(func): + """Skip testing data test.""" + import pytest + + return pytest.mark.skipif(_skip_spm_data(), reason="Requires spm dataset")(func) diff --git a/mne-python/source/mne/datasets/ssvep/__init__.py b/mne-python/source/mne/datasets/ssvep/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..18229cf176c44461621134d154ce6822532d7023 --- /dev/null +++ b/mne-python/source/mne/datasets/ssvep/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""SSVEP dataset.""" + +from .ssvep import data_path, get_version diff --git a/mne-python/source/mne/datasets/ssvep/ssvep.py b/mne-python/source/mne/datasets/ssvep/ssvep.py new file mode 100644 index 0000000000000000000000000000000000000000..9f13ace8789dda1dbaac0ead0df9784425423c84 --- /dev/null +++ b/mne-python/source/mne/datasets/ssvep/ssvep.py @@ -0,0 +1,30 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name="ssvep", + processor="unzip", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format(name="ssvep", conf="MNE_DATASETS_SSVEP_PATH") + + +def get_version(): # noqa: D103 + return _get_version("ssvep") + + +get_version.__doc__ = _version_doc.format(name="ssvep") diff --git a/mne-python/source/mne/datasets/testing/__init__.py b/mne-python/source/mne/datasets/testing/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..07ad87680291b8588c1a1d3a24e15ef10d97e5b6 --- /dev/null +++ b/mne-python/source/mne/datasets/testing/__init__.py @@ -0,0 +1,13 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""MNE testing dataset.""" + +from ._testing import ( + data_path, + requires_testing_data, + get_version, + _pytest_param, + _pytest_mark, +) diff --git a/mne-python/source/mne/datasets/testing/_testing.py b/mne-python/source/mne/datasets/testing/_testing.py new file mode 100644 index 0000000000000000000000000000000000000000..61d454898bef2354b89f181d07eab4906e8c6a10 --- /dev/null +++ b/mne-python/source/mne/datasets/testing/_testing.py @@ -0,0 +1,77 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from functools import partial + +from ...utils import get_config, verbose +from ..utils import ( + _data_path_doc, + _download_mne_dataset, + _get_version, + _version_doc, + has_dataset, +) + +has_testing_data = partial(has_dataset, name="testing") + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + # Make sure we don't do something stupid + if download and get_config("MNE_SKIP_TESTING_DATASET_TESTS", "false") == "true": + raise RuntimeError("Cannot download data if skipping is forced") + + return _download_mne_dataset( + name="testing", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="testing", conf="MNE_DATASETS_TESTING_PATH" +) + + +def get_version(): # noqa: D103 + return _get_version("testing") + + +get_version.__doc__ = _version_doc.format(name="testing") + + +# Allow forcing of testing dataset skip (for Debian tests) using: +# `make test-no-testing-data` +def _skip_testing_data(): + skip_testing = get_config("MNE_SKIP_TESTING_DATASET_TESTS", "false") == "true" + skip = skip_testing or not has_testing_data() + return skip + + +def requires_testing_data(func): + """Skip testing data test.""" + return _pytest_mark()(func) + + +def _pytest_param(*args, **kwargs): + if len(args) == 0: + args = ("testing_data",) + import pytest + + # turn anything that uses testing data into an auto-skipper by + # setting params=[testing._pytest_param()], or by parametrizing functions + # with testing._pytest_param(whatever) + kwargs["marks"] = kwargs.get("marks", list()) + [_pytest_mark()] + return pytest.param(*args, **kwargs) + + +def _pytest_mark(): + import pytest + + return pytest.mark.skipif(_skip_testing_data(), reason="Requires testing dataset") diff --git a/mne-python/source/mne/datasets/tests/__init__.py b/mne-python/source/mne/datasets/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/datasets/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/datasets/tests/test_datasets.py b/mne-python/source/mne/datasets/tests/test_datasets.py new file mode 100644 index 0000000000000000000000000000000000000000..a7f985392e76f3e57f3e44317512886171bc811e --- /dev/null +++ b/mne-python/source/mne/datasets/tests/test_datasets.py @@ -0,0 +1,324 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import re +import shutil +import zipfile +from functools import partial +from pathlib import Path + +import pooch +import pytest + +import mne.datasets._fsaverage.base +from mne import datasets, read_labels_from_annot, write_labels_to_annot +from mne.datasets import fetch_dataset, fetch_infant_template, fetch_phantom, testing +from mne.datasets._fsaverage.base import _set_montage_coreg_path +from mne.datasets._infant import base as infant_base +from mne.datasets._phantom import base as phantom_base +from mne.datasets.utils import _manifest_check_download +from mne.utils import ( + ArgvSetter, + _pl, + catch_logging, + get_subjects_dir, + hashfunc, + requires_good_network, + use_log_level, +) + +subjects_dir = testing.data_path(download=False) / "subjects" + + +def test_datasets_basic(tmp_path, monkeypatch): + """Test simple dataset functions.""" + # XXX 'hf_sef' and 'misc' do not conform to these standards + for dname in ( + "sample", + "somato", + "spm_face", + "testing", + "opm", + "bst_raw", + "bst_auditory", + "bst_resting", + "multimodal", + "bst_phantom_ctf", + "bst_phantom_elekta", + "kiloword", + "mtrf", + "phantom_4dbti", + "visual_92_categories", + "fieldtrip_cmc", + ): + if dname.startswith("bst"): + dataset = getattr(datasets.brainstorm, dname) + else: + dataset = getattr(datasets, dname) + if str(dataset.data_path(download=False)) != ".": + assert isinstance(dataset.get_version(), str) + assert datasets.has_dataset(dname) + else: + assert dataset.get_version() is None + assert not datasets.has_dataset(dname) + print(f"{dname}: {datasets.has_dataset(dname)}") + # Explicitly test one that isn't preset (given the config) + monkeypatch.setenv("MNE_DATASETS_SAMPLE_PATH", str(tmp_path)) + dataset = datasets.sample + assert str(dataset.data_path(download=False)) == "." + assert dataset.get_version() != "" + assert dataset.get_version() is None + # don't let it read from the config file to get the directory, + # force it to look for the default + monkeypatch.setenv("_MNE_FAKE_HOME_DIR", str(tmp_path)) + monkeypatch.delenv("SUBJECTS_DIR", raising=False) + assert datasets.utils._get_path(None, "foo", "bar") == tmp_path / "mne_data" + assert get_subjects_dir(None) is None + _set_montage_coreg_path() + sd = get_subjects_dir() + assert sd.name.endswith("MNE-fsaverage-data") + monkeypatch.setenv("MNE_DATA", str(tmp_path / "foo")) + with pytest.raises(FileNotFoundError, match="as specified by MNE_DAT"): + testing.data_path(download=False) + + def noop(*args, **kwargs): + return + + monkeypatch.setattr(mne.datasets._fsaverage.base, "_manifest_check_download", noop) + sd_2 = datasets.fetch_fsaverage() + assert sd / "fsaverage" == sd_2 + + +@requires_good_network +def test_downloads(tmp_path, monkeypatch, capsys): + """Test dataset URL and version handling.""" + # Try actually downloading a dataset + kwargs = dict(path=tmp_path, verbose=True) + # XXX we shouldn't need to disable capsys here, but there's a pytest bug + # that we're hitting (https://github.com/pytest-dev/pytest/issues/5997) + # now that we use pooch + with capsys.disabled(): + with pytest.raises(RuntimeError, match="Do not download .* in tests"): + path = datasets._fake.data_path(update_path=False, **kwargs) + monkeypatch.setattr( + datasets.utils, "_MODULES_TO_ENSURE_DOWNLOAD_IS_FALSE_IN_TESTS", () + ) + path = datasets._fake.data_path(update_path=False, **kwargs) + assert path.is_dir() + assert (path / "bar").is_file() + assert not datasets.has_dataset("fake") # not in the desired path + assert datasets._fake.get_version() is None + assert datasets.utils._get_version("fake") is None + monkeypatch.setenv("_MNE_FAKE_HOME_DIR", str(tmp_path)) + with pytest.warns(RuntimeWarning, match="non-standard config"): + new_path = datasets._fake.data_path(update_path=True, **kwargs) + assert path == new_path + out, _ = capsys.readouterr() + assert "Downloading" not in out + # No version: shown as existing but unknown version + assert datasets.has_dataset("fake") + # XXX logic bug, should be "unknown" + assert datasets._fake.get_version() == "0.0" + # With a version but no required one: shown as existing and gives version + fname = tmp_path / "foo" / "version.txt" + with open(fname, "w") as fid: + fid.write("0.1") + assert datasets.has_dataset("fake") + assert datasets._fake.get_version() == "0.1" + datasets._fake.data_path(download=False, **kwargs) + out, _ = capsys.readouterr() + assert "out of date" not in out + # With the required version: shown as existing with the required version + monkeypatch.setattr(datasets._fetch, "_FAKE_VERSION", "0.1") + assert datasets.has_dataset("fake") + assert datasets._fake.get_version() == "0.1" + datasets._fake.data_path(download=False, **kwargs) + out, _ = capsys.readouterr() + assert "out of date" not in out + monkeypatch.setattr(datasets._fetch, "_FAKE_VERSION", "0.2") + # With an older version: + # 1. Marked as not actually being present + assert not datasets.has_dataset("fake") + # 2. Will try to update when `data_path` gets called, with logged message + want_msg = "Correctly trying to download newer version" + + def _error_download(self, fname, downloader, processor): + url = self.get_url(fname) + full_path = self.abspath / fname + assert "foo.tgz" in url + assert str(tmp_path) in str(full_path) + raise RuntimeError(want_msg) + + monkeypatch.setattr(pooch.Pooch, "fetch", _error_download) + with pytest.raises(RuntimeError, match=want_msg): + datasets._fake.data_path(**kwargs) + out, _ = capsys.readouterr() + assert re.match(r".* 0\.1 .*out of date.* 0\.2.*", out, re.MULTILINE), out + + # Hash mismatch suggestion + # https://mne.discourse.group/t/fsaverage-hash-value-mismatch/4663/3 + want_msg = "MD5 hash of downloaded file (MNE-sample-data-processed.tar.gz) does not match the known hash: expected md5:e8f30c4516abdc12a0c08e6bae57409c but got a9dfc7e8843fd7f8a928901e12fb3d25. Deleted download for safety. The downloaded file may have been corrupted or the known hash may be outdated." # noqa: E501 + + def _error_download_2(self, fname, downloader, processor): + url = self.get_url(fname) + full_path = self.abspath / fname + assert "foo.tgz" in url + assert str(tmp_path) in str(full_path) + raise ValueError(want_msg) + + shutil.rmtree(tmp_path / "foo") + monkeypatch.setattr(pooch.Pooch, "fetch", _error_download_2) + with pytest.raises(ValueError, match=".*known hash.*force_update=True.*"): + datasets._fake.data_path(download=True, force_update=True, **kwargs) + + +# Okay to xfail this one because CircleCI downloads + uses the parcellations, +# so we'll know if they break +@pytest.mark.xfail(reason="Figshare blocks access from CIs sometimes") +@pytest.mark.ultraslowtest # not really ultraslow, but flakes out a lot +@testing.requires_testing_data +def test_fetch_parcellations(tmp_path): + """Test fetching parcellations.""" + pytest.importorskip("nibabel") + this_subjects_dir = tmp_path + fsaverage_dir = this_subjects_dir / "fsaverage" + (fsaverage_dir / "label").mkdir(parents=True) + (fsaverage_dir / "surf").mkdir() + for hemi in ("lh", "rh"): + shutil.copyfile( + subjects_dir / "fsaverage" / "surf" / f"{hemi}.white", + fsaverage_dir / "surf" / f"{hemi}.white", + ) + # speed up by prenteding we have one of them + with open(fsaverage_dir / "label" / "lh.aparc_sub.annot", "wb"): + pass + datasets.fetch_aparc_sub_parcellation(subjects_dir=this_subjects_dir) + with ArgvSetter(("--accept-hcpmmp-license",)): + datasets.fetch_hcp_mmp_parcellation(subjects_dir=this_subjects_dir) + for hemi in ("lh", "rh"): + assert (fsaverage_dir / "label" / f"{hemi}.aparc_sub.annot").is_file() + # test our annot round-trips here + kwargs = dict( + subject="fsaverage", hemi="both", sort=False, subjects_dir=this_subjects_dir + ) + labels = read_labels_from_annot(parc="HCPMMP1", **kwargs) + write_labels_to_annot( + labels, + parc="HCPMMP1_round", + table_name="./left.fsaverage164.label.gii", + **kwargs, + ) + orig = fsaverage_dir / "label" / "lh.HCPMMP1.annot" + first = hashfunc(orig) + new = str(orig)[:-6] + "_round.annot" + second = hashfunc(new) + assert first == second + + +_zip_fnames = ["foo/foo.txt", "foo/bar.txt", "foo/baz.txt"] + + +def _fake_zip_fetch(url, path, fname, *args, **kwargs): + path = Path(path) + assert isinstance(fname, str) + fname = path / fname + with zipfile.ZipFile(fname, "w") as zipf: + with zipf.open("foo/", "w"): + pass + for fname in _zip_fnames: + with zipf.open(fname, "w"): + pass + + +@pytest.mark.parametrize("n_have", range(len(_zip_fnames))) +def test_manifest_check_download(tmp_path, n_have, monkeypatch): + """Test our manifest downloader.""" + monkeypatch.setattr(pooch, "retrieve", _fake_zip_fetch) + destination = tmp_path / "empty" + manifest_path = tmp_path / "manifest.txt" + with open(manifest_path, "w") as fid: + for fname in _zip_fnames: + fid.write(f"{fname}\n") + assert n_have in range(len(_zip_fnames) + 1) + assert not destination.is_file() + if n_have > 0: + (destination / "foo").mkdir(parents=True) + assert (destination / "foo").is_dir() + for fname in _zip_fnames: + assert not (destination / fname).is_file() + for fname in _zip_fnames[:n_have]: + with open(destination / fname, "w"): + pass + with catch_logging() as log: + with use_log_level(True): + # we mock the pooch.retrieve so these are not used + url = hash_ = "" + _manifest_check_download(manifest_path, destination, url, hash_) + log = log.getvalue() + n_missing = 3 - n_have + assert (f"{n_missing} file{_pl(n_missing)} missing from") in log + for want in ("Extracting missing", "Successfully "): + if n_missing > 0: + assert want in log + else: + assert want not in log + assert (destination).is_dir() + for fname in _zip_fnames: + assert (destination / fname).is_file() + + +def _fake_mcd(manifest_path, destination, url, hash_, name=None, fake_files=False): + if name is None: + name = url.split("/")[-1].split(".")[0] + assert name in url + assert name in str(destination) + assert name in str(manifest_path) + assert len(hash_) == 32 + if fake_files: + with open(manifest_path) as fid: + for path in fid: + path = path.strip() + if not path: + continue + fname = destination / path + fname.parent.mkdir(exist_ok=True) + with open(fname, "wb"): + pass + + +def test_infant(tmp_path, monkeypatch): + """Test fetch_infant_template.""" + monkeypatch.setattr(infant_base, "_manifest_check_download", _fake_mcd) + fetch_infant_template("12mo", subjects_dir=tmp_path) + with pytest.raises(ValueError, match="Invalid value for"): + fetch_infant_template("0mo", subjects_dir=tmp_path) + + +def test_phantom(tmp_path, monkeypatch): + """Test phantom data downloading.""" + # The Otaniemi file is only ~6MB, so in principle maybe we could test + # an actual download here. But it doesn't seem worth it given that + # CircleCI will at least test the VectorView one, and this file should + # not change often. + monkeypatch.setattr( + phantom_base, + "_manifest_check_download", + partial(_fake_mcd, name="phantom_otaniemi", fake_files=True), + ) + fetch_phantom("otaniemi", subjects_dir=tmp_path) + assert (tmp_path / "phantom_otaniemi" / "mri" / "T1.mgz").is_file() + + +@requires_good_network +def test_fetch_uncompressed_file(tmp_path): + """Test downloading an uncompressed file with our fetch function.""" + dataset_dict = dict( + dataset_name="license", + url="https://raw.githubusercontent.com/mne-tools/mne-python/main/LICENSE.txt", + archive_name="LICENSE.foo", + folder_name=tmp_path / "foo", + hash=None, + ) + fetch_dataset(dataset_dict, path=None, force_update=True) + assert (tmp_path / "foo" / "LICENSE.foo").is_file() diff --git a/mne-python/source/mne/datasets/ucl_opm_auditory/__init__.py b/mne-python/source/mne/datasets/ucl_opm_auditory/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..94f389a51db13ef739bc021ad1ff9f089ddb81d3 --- /dev/null +++ b/mne-python/source/mne/datasets/ucl_opm_auditory/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""fNIRS motor dataset.""" + +from .ucl_opm_auditory import data_path, get_version diff --git a/mne-python/source/mne/datasets/ucl_opm_auditory/ucl_opm_auditory.py b/mne-python/source/mne/datasets/ucl_opm_auditory/ucl_opm_auditory.py new file mode 100644 index 0000000000000000000000000000000000000000..a9f6f410af415f43c51d99df0b016a50f114a2cd --- /dev/null +++ b/mne-python/source/mne/datasets/ucl_opm_auditory/ucl_opm_auditory.py @@ -0,0 +1,36 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + +_NAME = "ucl_opm_auditory" +_PROCESSOR = "unzip" + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): # noqa: D103 + return _download_mne_dataset( + name=_NAME, + processor=_PROCESSOR, + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name=_NAME, + conf=f"MNE_DATASETS_{_NAME.upper()}_PATH", +) + + +def get_version(): # noqa: D103 + return _get_version(_NAME) + + +get_version.__doc__ = _version_doc.format(name=_NAME) diff --git a/mne-python/source/mne/datasets/utils.py b/mne-python/source/mne/datasets/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..8e8d4fb0db17de7aedbda2cc8c9aed35d569a114 --- /dev/null +++ b/mne-python/source/mne/datasets/utils.py @@ -0,0 +1,855 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import glob +import importlib +import inspect +import logging +import os +import os.path as op +import sys +import tempfile +import time +import zipfile +from collections import OrderedDict +from pathlib import Path +from typing import cast + +import numpy as np + +from ..label import Label, read_labels_from_annot, write_labels_to_annot +from ..utils import ( + _pl, + _safe_input, + _validate_type, + get_config, + get_subjects_dir, + logger, + set_config, + verbose, +) +from ..utils.docs import _docformat, docdict +from .config import MNE_DATASETS, _hcp_mmp_license_text + +_data_path_doc = """Get path to local copy of {name} dataset. + + Parameters + ---------- + path : None | str + Location of where to look for the {name} dataset. + If None, the environment variable or config parameter + ``{conf}`` is used. If it doesn't exist, the + "~/mne_data" directory is used. If the {name} dataset + is not found under the given path, the data + will be automatically downloaded to the specified folder. + force_update : bool + Force update of the {name} dataset even if a local copy exists. + Default is False. + update_path : bool | None + If True (default), set the ``{conf}`` in mne-python + config to the given path. If None, the user is prompted. + download : bool + If False and the {name} dataset has not been downloaded yet, + it will not be downloaded and the path will be returned as + '' (empty string). This is mostly used for debugging purposes + and can be safely ignored by most users. + %(verbose)s + + Returns + ------- + path : instance of Path + Path to {name} dataset directory. +""" +_data_path_doc_accept = _data_path_doc.split("%(verbose)s") +_data_path_doc_accept[-1] = "%(verbose)s" + _data_path_doc_accept[-1] +_data_path_doc_accept.insert(1, " %(accept)s") +_data_path_doc_accept = "".join(_data_path_doc_accept) +_data_path_doc = _docformat(_data_path_doc, docdict) +_data_path_doc_accept = _docformat(_data_path_doc_accept, docdict) + +_version_doc = """Get version of the local {name} dataset. + + Returns + ------- + version : str | None + Version of the {name} local dataset, or None if the dataset + does not exist locally. +""" + + +def _dataset_version(path, name): + """Get the version of the dataset.""" + ver_fname = op.join(path, "version.txt") + if op.exists(ver_fname): + with open(ver_fname) as fid: + version = fid.readline().strip() # version is on first line + else: + logger.debug(f"Version file missing: {ver_fname}") + # Sample dataset versioning was introduced after 0.3 + # SPM dataset was introduced with 0.7 + versions = dict(sample="0.7", spm="0.3") + version = versions.get(name, "0.0") + return version + + +@verbose +def default_path(*, verbose=None): + """Get the default MNE_DATA path. + + Parameters + ---------- + %(verbose)s + + Returns + ------- + data_path : instance of Path + Path to the default MNE_DATA directory. + """ + return _get_path(None, None, None) + + +def _get_path(path, key, name): + """Get a dataset path.""" + # 1. Input + _validate_type(path, ("path-like", None), path) + if path is not None: + return Path(path).expanduser() + # 2. get_config(key) — unless key is None or "" (special get_config values) + # 3. get_config('MNE_DATA') + path = get_config(key or "MNE_DATA", get_config("MNE_DATA")) + if path is not None: + path = Path(path).expanduser() + if not path.exists(): + msg = ( + f"Download location {path} as specified by MNE_DATA does " + f"not exist. Either create this directory manually and try " + f"again, or set MNE_DATA to an existing directory." + ) + raise FileNotFoundError(msg) + return path + # 4. ~/mne_data (but use a fake home during testing so we don't + # unnecessarily create ~/mne_data) + extra = f" for {name}" if name else "" + logger.info(f"Using default location ~/mne_data{extra}...") + path = Path(os.getenv("_MNE_FAKE_HOME_DIR", "~")).expanduser() / "mne_data" + if not path.is_dir(): + logger.info(f"Creating {path}") + try: + path.mkdir() + except OSError: + raise OSError( + "User does not have write permissions " + f"at '{path}', try giving the path as an " + "argument to data_path() where user has " + "write permissions, for ex:data_path" + "('/home/xyz/me2/')" + ) + return path + + +def _do_path_update(path, update_path, key, name): + """Update path.""" + path = op.abspath(path) + identical = get_config(key, "", use_env=False) == path + if not identical: + if update_path is None: + update_path = True + if "--update-dataset-path" in sys.argv: + answer = "y" + else: + msg = ( + f"Do you want to set the path:\n {path}\nas the default {name} " + "dataset path in the mne-python config [y]/n? " + ) + answer = _safe_input(msg, alt="pass update_path=True") + if answer.lower() == "n": + update_path = False + + if update_path: + set_config(key, str(path), set_env=False) + return path + + +# This is meant to be semi-public: let packages like mne-bids use it to make +# sure they don't accidentally set download=True in their tests, too +_MODULES_TO_ENSURE_DOWNLOAD_IS_FALSE_IN_TESTS = ("mne",) + + +def _check_in_testing_and_raise(name, download): + """Check if we're in an MNE test and raise an error if download!=False.""" + root_dirs = [ + importlib.import_module(ns) + for ns in _MODULES_TO_ENSURE_DOWNLOAD_IS_FALSE_IN_TESTS + ] + root_dirs = [str(Path(ns.__file__).parent) for ns in root_dirs] + check = False + func = None + frame = inspect.currentframe() + try: + # First, traverse out of the data_path() call + while frame: + if frame.f_code.co_name in ("data_path", "load_data"): + func = frame.f_code.co_name + frame = frame.f_back.f_back # out of verbose decorator + break + frame = frame.f_back + # Next, see what the caller was + while frame: + fname = frame.f_code.co_filename + if fname is not None: + fname = Path(fname) + # in mne namespace, and + # (can't use is_relative_to here until 3.9) + if any(str(fname).startswith(rd) for rd in root_dirs) and ( + # in tests/*.py + fname.parent.stem == "tests" + or + # or in a conftest.py + fname.stem == "conftest.py" + ): + check = True + break + frame = frame.f_back + finally: + del frame + if check and download is not False: + raise RuntimeError( + f"Do not download dataset {repr(name)} in tests, pass " + f"{func}(download=False) to prevent accidental downloads" + ) + + +def _download_mne_dataset( + name, processor, path, force_update, update_path, download, accept=False +) -> Path: + """Aux function for downloading internal MNE datasets.""" + import pooch + + from mne.datasets._fetch import fetch_dataset + + _check_in_testing_and_raise(name, download) + + # import pooch library for handling the dataset downloading + dataset_params = MNE_DATASETS[name] + dataset_params["dataset_name"] = name + config_key = MNE_DATASETS[name]["config_key"] + folder_name = MNE_DATASETS[name]["folder_name"] + + # get download path for specific dataset + path = _get_path(path=path, key=config_key, name=name) + + # instantiate processor that unzips file + if processor == "nested_untar": + processor_ = pooch.Untar(extract_dir=op.join(path, folder_name)) + elif processor == "nested_unzip": + processor_ = pooch.Unzip(extract_dir=op.join(path, folder_name)) + else: + processor_ = processor + + # handle case of multiple sub-datasets with different urls + if name == "visual_92_categories": + dataset_params = [] + for name in ["visual_92_categories_1", "visual_92_categories_2"]: + this_dataset = MNE_DATASETS[name] + this_dataset["dataset_name"] = name + dataset_params.append(this_dataset) + + return cast( + Path, + fetch_dataset( + dataset_params=dataset_params, + processor=processor_, + path=path, + force_update=force_update, + update_path=update_path, + download=download, + accept=accept, + ), + ) + + +def _get_version(name): + """Get a dataset version.""" + from mne.datasets._fetch import fetch_dataset + + if not has_dataset(name): + return None + dataset_params = MNE_DATASETS[name] + dataset_params["dataset_name"] = name + config_key = MNE_DATASETS[name]["config_key"] + + # get download path for specific dataset + path = _get_path(path=None, key=config_key, name=name) + + return fetch_dataset(dataset_params, path=path, return_version=True)[1] + + +def has_dataset(name): + """Check for presence of a dataset. + + Parameters + ---------- + name : str | dict + The dataset to check. Strings refer to one of the supported datasets + listed :ref:`here `. A :class:`dict` can be used to check for + user-defined datasets (see the Notes section of :func:`fetch_dataset`), + and must contain keys ``dataset_name``, ``archive_name``, ``url``, + ``folder_name``, ``hash``. + + Returns + ------- + has : bool + True if the dataset is present. + """ + from mne.datasets._fetch import fetch_dataset + + if isinstance(name, dict): + dataset_name = name["dataset_name"] + dataset_params = name + else: + dataset_name = "spm" if name == "spm_face" else name + dataset_params = MNE_DATASETS[dataset_name] + dataset_params["dataset_name"] = dataset_name + + config_key = dataset_params["config_key"] + + # get download path for specific dataset + path = _get_path(path=None, key=config_key, name=dataset_name) + + dp = fetch_dataset(dataset_params, path=path, download=False, check_version=False) + if dataset_name.startswith("bst_"): + check = dataset_name + else: + check = MNE_DATASETS[dataset_name]["folder_name"] + return str(dp).endswith(check) + + +@verbose +def _download_all_example_data(verbose=True): + """Download all datasets used in examples and tutorials.""" + # This function is designed primarily to be used by CircleCI, to: + # + # 1. Streamline data downloading + # 2. Make CircleCI fail early (rather than later) if some necessary data + # cannot be retrieved. + # 3. Avoid download statuses and timing biases in rendered examples. + # + # verbose=True by default so we get nice status messages. + # Consider adding datasets from here to CircleCI for PR-auto-build + import openneuro + + paths = dict() + for kind in ( + "sample testing misc spm_face somato hf_sef multimodal " + "fnirs_motor opm mtrf fieldtrip_cmc kiloword phantom_kit phantom_4dbti " + "refmeg_noise ssvep epilepsy_ecog ucl_opm_auditory eyelink " + "erp_core brainstorm.bst_raw brainstorm.bst_auditory " + "brainstorm.bst_resting brainstorm.bst_phantom_ctf " + "brainstorm.bst_phantom_elekta phantom_kernel" + ).split(): + mod = importlib.import_module(f"mne.datasets.{kind}") + data_path_func = getattr(mod, "data_path") + kwargs = dict() + if "accept" in inspect.getfullargspec(data_path_func).args: + kwargs["accept"] = True + paths[kind] = data_path_func(**kwargs) + logger.info(f"[done {kind}]") + + # Now for the exceptions: + from . import ( + eegbci, + fetch_fsaverage, + fetch_hcp_mmp_parcellation, + fetch_infant_template, + fetch_phantom, + limo, + sleep_physionet, + ) + + eegbci.load_data(subjects=1, runs=[6, 10, 14], update_path=True) + eegbci.load_data(subjects=range(1, 5), runs=[3], update_path=True) + logger.info("[done eegbci]") + + sleep_physionet.age.fetch_data(subjects=[0, 1], recording=[1]) + logger.info("[done sleep_physionet]") + + # If the user has SUBJECTS_DIR, respect it, if not, set it to the EEG one + # (probably on CircleCI, or otherwise advanced user) + fetch_fsaverage(subjects_dir=None) + logger.info("[done fsaverage]") + + # Now also update the sample dataset path, if not already SUBJECTS_DIR + # (some tutorials make use of these files) + fetch_fsaverage(subjects_dir=paths["sample"] / "subjects") + + fetch_infant_template("6mo") + logger.info("[done infant_template]") + + fetch_hcp_mmp_parcellation(subjects_dir=paths["sample"] / "subjects", accept=True) + logger.info("[done hcp_mmp_parcellation]") + + fetch_phantom("otaniemi", subjects_dir=paths["brainstorm.bst_phantom_elekta"]) + logger.info("[done phantom]") + + limo.load_data(subject=1, update_path=True) + logger.info("[done limo]") + + # for ESG + ds = "ds004388" + target_dir = default_path() / ds + run_name = "sub-001/eeg/*median_run-03_eeg*.set" + if not glob.glob(str(target_dir / run_name)): + target_dir.mkdir(exist_ok=True) + openneuro.download(dataset=ds, target_dir=target_dir, include=run_name[:-4]) + + +@verbose +def fetch_aparc_sub_parcellation(subjects_dir=None, verbose=None): + """Fetch the modified subdivided aparc parcellation. + + This will download and install the subdivided aparc parcellation + :footcite:'KhanEtAl2018' files for + FreeSurfer's fsaverage to the specified directory. + + Parameters + ---------- + subjects_dir : path-like | None + The subjects directory to use. The file will be placed in + ``subjects_dir + '/fsaverage/label'``. + %(verbose)s + + References + ---------- + .. footbibliography:: + """ + import pooch + + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + destination = subjects_dir / "fsaverage" / "label" + urls = dict(lh="https://osf.io/download/p92yb", rh="https://osf.io/download/4kxny") + hashes = dict( + lh="9e4d8d6b90242b7e4b0145353436ef77", rh="dd6464db8e7762d969fc1d8087cd211b" + ) + downloader = pooch.HTTPDownloader(**_downloader_params()) + for hemi in ("lh", "rh"): + fname = f"{hemi}.aparc_sub.annot" + fpath = destination / fname + if not fpath.is_file(): + pooch.retrieve( + url=urls[hemi], + known_hash=f"md5:{hashes[hemi]}", + path=destination, + downloader=downloader, + fname=fname, + ) + + +@verbose +def fetch_hcp_mmp_parcellation( + subjects_dir=None, combine=True, *, accept=False, verbose=None +): + """Fetch the HCP-MMP parcellation. + + This will download and install the HCP-MMP parcellation + :footcite:`GlasserEtAl2016` files for FreeSurfer's fsaverage + :footcite:`Mills2016` to the specified directory. + + Parameters + ---------- + subjects_dir : path-like | None + The subjects directory to use. The file will be placed in + ``subjects_dir + '/fsaverage/label'``. + combine : bool + If True, also produce the combined/reduced set of 23 labels per + hemisphere as ``HCPMMP1_combined.annot`` + :footcite:`GlasserEtAl2016supp`. + %(accept)s + %(verbose)s + + Notes + ----- + Use of this parcellation is subject to terms of use on the + `HCP-MMP webpage `_. + + References + ---------- + .. footbibliography:: + """ + import pooch + + subjects_dir = get_subjects_dir(subjects_dir, raise_error=True) + destination = subjects_dir / "fsaverage" / "label" + fnames = [destination / f"{hemi}.HCPMMP1.annot" for hemi in ("lh", "rh")] + urls = dict( + lh="https://ndownloader.figshare.com/files/5528816", + rh="https://ndownloader.figshare.com/files/5528819", + ) + hashes = dict( + lh="46a102b59b2fb1bb4bd62d51bf02e975", rh="75e96b331940227bbcb07c1c791c2463" + ) + if not all(fname.exists() for fname in fnames): + if accept or "--accept-hcpmmp-license" in sys.argv: + answer = "y" + else: + answer = _safe_input(f"{_hcp_mmp_license_text}\nAgree (y/[n])? ") + if answer.lower() != "y": + raise RuntimeError("You must agree to the license to use this dataset") + downloader = pooch.HTTPDownloader(**_downloader_params()) + for hemi, fpath in zip(("lh", "rh"), fnames): + if not op.isfile(fpath): + fname = fpath.name + pooch.retrieve( + url=urls[hemi], + known_hash=f"md5:{hashes[hemi]}", + path=destination, + downloader=downloader, + fname=fname, + ) + + if combine: + fnames = [ + op.join(destination, f"{hemi}.HCPMMP1_combined.annot") + for hemi in ("lh", "rh") + ] + if all(op.isfile(fname) for fname in fnames): + return + # otherwise, let's make them + logger.info("Creating combined labels") + groups = OrderedDict( + [ + ("Primary Visual Cortex (V1)", ("V1",)), + ("Early Visual Cortex", ("V2", "V3", "V4")), + ( + "Dorsal Stream Visual Cortex", + ("V3A", "V3B", "V6", "V6A", "V7", "IPS1"), + ), + ( + "Ventral Stream Visual Cortex", + ("V8", "VVC", "PIT", "FFC", "VMV1", "VMV2", "VMV3"), + ), + ( + "MT+ Complex and Neighboring Visual Areas", + ("V3CD", "LO1", "LO2", "LO3", "V4t", "FST", "MT", "MST", "PH"), + ), + ("Somatosensory and Motor Cortex", ("4", "3a", "3b", "1", "2")), + ( + "Paracentral Lobular and Mid Cingulate Cortex", + ( + "24dd", + "24dv", + "6mp", + "6ma", + "SCEF", + "5m", + "5L", + "5mv", + ), + ), + ("Premotor Cortex", ("55b", "6d", "6a", "FEF", "6v", "6r", "PEF")), + ( + "Posterior Opercular Cortex", + ("43", "FOP1", "OP4", "OP1", "OP2-3", "PFcm"), + ), + ("Early Auditory Cortex", ("A1", "LBelt", "MBelt", "PBelt", "RI")), + ( + "Auditory Association Cortex", + ( + "A4", + "A5", + "STSdp", + "STSda", + "STSvp", + "STSva", + "STGa", + "TA2", + ), + ), + ( + "Insular and Frontal Opercular Cortex", + ( + "52", + "PI", + "Ig", + "PoI1", + "PoI2", + "FOP2", + "FOP3", + "MI", + "AVI", + "AAIC", + "Pir", + "FOP4", + "FOP5", + ), + ), + ( + "Medial Temporal Cortex", + ( + "H", + "PreS", + "EC", + "PeEc", + "PHA1", + "PHA2", + "PHA3", + ), + ), + ( + "Lateral Temporal Cortex", + ( + "PHT", + "TE1p", + "TE1m", + "TE1a", + "TE2p", + "TE2a", + "TGv", + "TGd", + "TF", + ), + ), + ( + "Temporo-Parieto-Occipital Junction", + ( + "TPOJ1", + "TPOJ2", + "TPOJ3", + "STV", + "PSL", + ), + ), + ( + "Superior Parietal Cortex", + ( + "LIPv", + "LIPd", + "VIP", + "AIP", + "MIP", + "7PC", + "7AL", + "7Am", + "7PL", + "7Pm", + ), + ), + ( + "Inferior Parietal Cortex", + ( + "PGp", + "PGs", + "PGi", + "PFm", + "PF", + "PFt", + "PFop", + "IP0", + "IP1", + "IP2", + ), + ), + ( + "Posterior Cingulate Cortex", + ( + "DVT", + "ProS", + "POS1", + "POS2", + "RSC", + "v23ab", + "d23ab", + "31pv", + "31pd", + "31a", + "23d", + "23c", + "PCV", + "7m", + ), + ), + ( + "Anterior Cingulate and Medial Prefrontal Cortex", + ( + "33pr", + "p24pr", + "a24pr", + "p24", + "a24", + "p32pr", + "a32pr", + "d32", + "p32", + "s32", + "8BM", + "9m", + "10v", + "10r", + "25", + ), + ), + ( + "Orbital and Polar Frontal Cortex", + ( + "47s", + "47m", + "a47r", + "11l", + "13l", + "a10p", + "p10p", + "10pp", + "10d", + "OFC", + "pOFC", + ), + ), + ( + "Inferior Frontal Cortex", + ( + "44", + "45", + "IFJp", + "IFJa", + "IFSp", + "IFSa", + "47l", + "p47r", + ), + ), + ( + "DorsoLateral Prefrontal Cortex", + ( + "8C", + "8Av", + "i6-8", + "s6-8", + "SFL", + "8BL", + "9p", + "9a", + "8Ad", + "p9-46v", + "a9-46v", + "46", + "9-46d", + ), + ), + ("???", ("???",)), + ] + ) + assert len(groups) == 23 + labels_out = list() + + for hemi in ("lh", "rh"): + labels = read_labels_from_annot( + "fsaverage", "HCPMMP1", hemi=hemi, subjects_dir=subjects_dir, sort=False + ) + label_names = [ + "???" if label.name.startswith("???") else label.name.split("_")[1] + for label in labels + ] + used = np.zeros(len(labels), bool) + for key, want in groups.items(): + assert "\t" not in key + these_labels = [ + li + for li, label_name in enumerate(label_names) + if label_name in want + ] + assert not used[these_labels].any() + assert len(these_labels) == len(want) + used[these_labels] = True + these_labels = [labels[li] for li in these_labels] + # take a weighted average to get the color + # (here color == task activation) + w = np.array([len(label.vertices) for label in these_labels]) + w = w / float(w.sum()) + color = np.dot(w, [label.color for label in these_labels]) + these_labels = sum( + these_labels, Label([], subject="fsaverage", hemi=hemi) + ) + these_labels.name = key + these_labels.color = color + labels_out.append(these_labels) + assert used.all() + assert len(labels_out) == 46 + for hemi, side in (("lh", "left"), ("rh", "right")): + table_name = f"./{side}.fsaverage164.label.gii" + write_labels_to_annot( + labels_out, + "fsaverage", + "HCPMMP1_combined", + hemi=hemi, + subjects_dir=subjects_dir, + sort=False, + table_name=table_name, + ) + + +def _manifest_check_download(manifest_path, destination, url, hash_): + import pooch + + with open(manifest_path) as fid: + names = [name.strip() for name in fid.readlines()] + need = list() + for name in names: + if not (destination / name).is_file(): + need.append(name) + logger.info( + "%d file%s missing from %s in %s", + len(need), + _pl(need), + manifest_path.name, + destination, + ) + if len(need) > 0: + downloader = pooch.HTTPDownloader(**_downloader_params()) + with tempfile.TemporaryDirectory() as path: + logger.info("Downloading missing files remotely") + + path = Path(path) + fname_path = path / "temp.zip" + pooch.retrieve( + url=url, + known_hash=f"md5:{hash_}", + path=path, + downloader=downloader, + fname=fname_path.name, + ) + + logger.info(f"Extracting missing file{_pl(need)}") + with zipfile.ZipFile(fname_path, "r") as ff: + members = set(f for f in ff.namelist() if not f.endswith("/")) + missing = sorted(members.symmetric_difference(set(names))) + if len(missing): + raise RuntimeError( + "Zip file did not have correct names:\n{'\n'.join(missing)}" + ) + for name in need: + ff.extract(name, path=destination) + logger.info(f"Successfully extracted {len(need)} file{_pl(need)}") + + +def _log_time_size(t0, sz): + t = time.time() - t0 + fmt = "%Ss" + if t > 60: + fmt = f"%Mm{fmt}" + if t > 3600: + fmt = f"%Hh{fmt}" + sz = sz / 1048576 # 1024 ** 2 + t = time.strftime(fmt, time.gmtime(t)) + logger.info(f"Download complete in {t} ({sz:.1f} MB)") + + +def _downloader_params(*, auth=None, token=None): + params = dict(timeout=15) + params["progressbar"] = ( + logger.level <= logging.INFO and get_config("MNE_TQDM", "tqdm.auto") != "off" + ) + if auth is not None: + params["auth"] = auth + if token is not None: + params["headers"] = {"Authorization": f"token {token}"} + return params diff --git a/mne-python/source/mne/datasets/visual_92_categories/__init__.py b/mne-python/source/mne/datasets/visual_92_categories/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..598795bcc9d6492a4008a2d20f701f22603cb249 --- /dev/null +++ b/mne-python/source/mne/datasets/visual_92_categories/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""MNE visual_92_categories dataset.""" + +from .visual_92_categories import data_path, get_version diff --git a/mne-python/source/mne/datasets/visual_92_categories/visual_92_categories.py b/mne-python/source/mne/datasets/visual_92_categories/visual_92_categories.py new file mode 100644 index 0000000000000000000000000000000000000000..b0ec1e6782051aafdf517688338cc933c398ed69 --- /dev/null +++ b/mne-python/source/mne/datasets/visual_92_categories/visual_92_categories.py @@ -0,0 +1,67 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import verbose +from ..utils import _data_path_doc, _download_mne_dataset, _get_version, _version_doc + + +@verbose +def data_path( + path=None, force_update=False, update_path=True, download=True, *, verbose=None +): + """ + Get path to local copy of visual_92_categories dataset. + + .. note:: The dataset contains four fif-files, the trigger files and the T1 + mri image. This dataset is rather big in size (more than 5 GB). + + Parameters + ---------- + path : None | str + Location of where to look for the visual_92_categories data storing + location. If None, the environment variable or config parameter + MNE_DATASETS_VISUAL_92_CATEGORIES_PATH is used. If it doesn't exist, + the "mne-python/examples" directory is used. If the + visual_92_categories dataset is not found under the given path (e.g., + as "mne-python/examples/MNE-visual_92_categories-data"), the data + will be automatically downloaded to the specified folder. + force_update : bool + Force update of the dataset even if a local copy exists. + update_path : bool | None + If True, set the MNE_DATASETS_VISUAL_92_CATEGORIES_PATH in mne-python + config to the given path. If None, the user is prompted. + %(verbose)s + + Returns + ------- + path : instance of Path + Local path to the given data file. + + Notes + ----- + The visual_92_categories dataset is documented in the following publication + Radoslaw M. Cichy, Dimitrios Pantazis, Aude Oliva (2014) Resolving + human object recognition in space and time. doi: 10.1038/NN.3635 + """ + return _download_mne_dataset( + name="visual_92_categories", + processor="untar", + path=path, + force_update=force_update, + update_path=update_path, + download=download, + ) + + +data_path.__doc__ = _data_path_doc.format( + name="visual_92_categories", conf="MNE_DATASETS_VISUAL_92_CATEGORIES_PATH" +) + + +def get_version(): + """Get dataset version.""" + return _get_version("visual_92_categories") + + +get_version.__doc__ = _version_doc.format(name="visual_92_categories") diff --git a/mne-python/source/mne/decoding/__init__.py b/mne-python/source/mne/decoding/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b0dc90e1048df2bc49da9ae0020cb43014001fd7 --- /dev/null +++ b/mne-python/source/mne/decoding/__init__.py @@ -0,0 +1,8 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Decoding and encoding, including machine learning and receptive fields.""" +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/decoding/__init__.pyi b/mne-python/source/mne/decoding/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..1131f1597c56ebdbaa50eb9998a9f038d707422b --- /dev/null +++ b/mne-python/source/mne/decoding/__init__.pyi @@ -0,0 +1,50 @@ +__all__ = [ + "BaseEstimator", + "CSP", + "EMS", + "FilterEstimator", + "GeneralizingEstimator", + "LinearModel", + "PSDEstimator", + "ReceptiveField", + "SPoC", + "SSD", + "Scaler", + "SlidingEstimator", + "SpatialFilter", + "TemporalFilter", + "TimeDelayingRidge", + "TimeFrequency", + "TransformerMixin", + "UnsupervisedSpatialFilter", + "Vectorizer", + "XdawnTransformer", + "compute_ems", + "cross_val_multiscore", + "get_coef", + "get_spatial_filter_from_estimator", +] +from .base import ( + BaseEstimator, + LinearModel, + TransformerMixin, + cross_val_multiscore, + get_coef, +) +from .csp import CSP, SPoC +from .ems import EMS, compute_ems +from .receptive_field import ReceptiveField +from .search_light import GeneralizingEstimator, SlidingEstimator +from .spatial_filter import SpatialFilter, get_spatial_filter_from_estimator +from .ssd import SSD +from .time_delaying_ridge import TimeDelayingRidge +from .time_frequency import TimeFrequency +from .transformer import ( + FilterEstimator, + PSDEstimator, + Scaler, + TemporalFilter, + UnsupervisedSpatialFilter, + Vectorizer, +) +from .xdawn import XdawnTransformer diff --git a/mne-python/source/mne/decoding/_covs_ged.py b/mne-python/source/mne/decoding/_covs_ged.py new file mode 100644 index 0000000000000000000000000000000000000000..8061a343f23b8d24f12f7dad7e294f856eabac49 --- /dev/null +++ b/mne-python/source/mne/decoding/_covs_ged.py @@ -0,0 +1,287 @@ +"""Covariance estimation for GED transformers.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from .._fiff.meas_info import Info, create_info +from .._fiff.pick import _picks_to_idx, pick_info +from ..cov import Covariance, _compute_rank_raw_array, _regularized_covariance +from ..defaults import _handle_default +from ..filter import filter_data +from ..rank import compute_rank +from ..utils import _verbose_safe_false, logger + + +def _concat_cov(x_class, *, cov_kind, log_rank, reg, cov_method_params, info, rank): + """Concatenate epochs before computing the covariance.""" + _, n_channels, _ = x_class.shape + + x_class = x_class.transpose(1, 0, 2).reshape(n_channels, -1) + cov = _regularized_covariance( + x_class, + reg=reg, + method_params=cov_method_params, + rank=rank, + info=info, + cov_kind=cov_kind, + log_rank=log_rank, + log_ch_type="data", + ) + + return cov, n_channels # the weight here is just the number of channels + + +def _epoch_cov(x_class, *, cov_kind, log_rank, reg, cov_method_params, info, rank): + """Mean of per-epoch covariances.""" + name = reg if isinstance(reg, str) else "empirical" + name += " with shrinkage" if isinstance(reg, float) else "" + logger.info( + f"Estimating {cov_kind + (' ' if cov_kind else '')}" + f"covariance (average over epochs; {name.upper()})" + ) + cov = sum( + _regularized_covariance( + this_X, + reg=reg, + method_params=cov_method_params, + rank=rank, + info=info, + cov_kind=cov_kind, + log_rank=log_rank and ii == 0, + log_ch_type="data", + verbose=_verbose_safe_false(), + ) + for ii, this_X in enumerate(x_class) + ) + cov /= len(x_class) + weight = len(x_class) + + return cov, weight + + +def _handle_info_rank(X, info, rank): + if info is None: + # use mag instead of eeg to avoid the cov EEG projection warning + info = create_info(X.shape[1], 1000.0, "mag") + if isinstance(rank, dict): + rank = dict(mag=sum(rank.values())) + + return info, rank + + +def _csp_estimate(X, y, reg, cov_method_params, cov_est, info, rank, norm_trace): + _, n_channels, _ = X.shape + classes_ = np.unique(y) + if cov_est == "concat": + cov_estimator = _concat_cov + elif cov_est == "epoch": + cov_estimator = _epoch_cov + + info, rank = _handle_info_rank(X, info, rank) + if not isinstance(rank, dict): + rank = _compute_rank_raw_array( + np.hstack(X), + info, + rank=rank, + scalings=None, + log_ch_type="data", + on_few_samples="ignore", + ) + + covs = [] + sample_weights = [] + for ci, this_class in enumerate(classes_): + cov, weight = cov_estimator( + X[y == this_class], + cov_kind=f"class={this_class}", + log_rank=ci == 0, + reg=reg, + cov_method_params=cov_method_params, + info=info, + rank=rank, + ) + + if norm_trace: + cov /= np.trace(cov) + + covs.append(cov) + sample_weights.append(weight) + + covs = np.stack(covs) + C_ref = covs.mean(0) + + return covs, C_ref, info, rank, dict(sample_weights=np.array(sample_weights)) + + +def _xdawn_estimate( + X, + y, + reg, + cov_method_params, + R=None, + info=None, + rank="full", +): + classes = np.unique(y) + info, rank = _handle_info_rank(X, info, rank) + + # Retrieve or compute whitening covariance + if R is None: + R = _regularized_covariance( + np.hstack(X), reg, cov_method_params, info, rank=rank + ) + elif isinstance(R, Covariance): + R = R.data + + # Get prototype events + evokeds, toeplitzs = list(), list() + for c in classes: + # Prototyped response for each class + evokeds.append(np.mean(X[y == c, :, :], axis=0)) + toeplitzs.append(1.0) + + covs = [] + for evo, toeplitz in zip(evokeds, toeplitzs): + # Estimate covariance matrix of the prototype response + evo = np.dot(evo, toeplitz) + evo_cov = _regularized_covariance(evo, reg, cov_method_params, info, rank=rank) + covs.append(evo_cov) + + covs.append(R) + C_ref = R + if not isinstance(rank, dict): + rank = _compute_rank_raw_array( + np.hstack(X), + info, + rank=rank, + scalings=None, + log_ch_type="data", + on_few_samples="ignore", + ) + return covs, C_ref, info, rank, dict() + + +def _ssd_estimate( + X, + y, + reg, + cov_method_params, + info, + picks, + n_fft, + filt_params_signal, + filt_params_noise, + rank, + sort_by_spectral_ratio, +): + if isinstance(info, Info): + sfreq = info["sfreq"] + elif isinstance(info, float): # special case, mostly for testing + sfreq = info + info = create_info(X.shape[-2], sfreq, ch_types="eeg") + picks_ = _picks_to_idx(info, picks, none="data", exclude="bads") + X_aux = X[..., picks_, :] + X_signal = filter_data(X_aux, sfreq, **filt_params_signal) + X_noise = filter_data(X_aux, sfreq, **filt_params_noise) + X_noise -= X_signal + if X.ndim == 3: + X_signal = np.hstack(X_signal) + X_noise = np.hstack(X_noise) + + # prevent rank change when computing cov with rank='full' + picked_info = pick_info(info, picks_) + S = _regularized_covariance( + X_signal, + reg=reg, + method_params=cov_method_params, + rank="full", + info=picked_info, + ) + R = _regularized_covariance( + X_noise, + reg=reg, + method_params=cov_method_params, + rank="full", + info=picked_info, + ) + covs = [S, R] + C_ref = S + + all_ranks = list() + for cov in covs: + r = list( + compute_rank( + Covariance( + cov, + picked_info.ch_names, + list(), + list(), + 0, + verbose=_verbose_safe_false(), + ), + rank, + _handle_default("scalings_cov_rank", None), + info, + ).values() + )[0] + all_ranks.append(r) + rank = np.min(all_ranks) + freqs_signal = (filt_params_signal["l_freq"], filt_params_signal["h_freq"]) + freqs_noise = (filt_params_noise["l_freq"], filt_params_noise["h_freq"]) + n_fft = min( + int(n_fft if n_fft is not None else sfreq), + X.shape[-1], + ) + kwargs = dict( + X=X, + picks=picks_, + sfreq=sfreq, + n_fft=n_fft, + freqs_signal=freqs_signal, + freqs_noise=freqs_noise, + sort_by_spectral_ratio=sort_by_spectral_ratio, + ) + rank = dict(eeg=rank) + info = picked_info + return covs, C_ref, info, rank, kwargs + + +def _spoc_estimate(X, y, reg, cov_method_params, info, rank): + info, rank = _handle_info_rank(X, info, rank) + # Normalize target variable + target = y.astype(np.float64) + target -= target.mean() + target /= target.std() + + n_epochs, n_channels = X.shape[:2] + + # Estimate single trial covariance + covs = np.empty((n_epochs, n_channels, n_channels)) + for ii, epoch in enumerate(X): + covs[ii] = _regularized_covariance( + epoch, + reg=reg, + method_params=cov_method_params, + rank=rank, + log_ch_type="data", + log_rank=ii == 0, + ) + + S = np.mean(covs * target[:, np.newaxis, np.newaxis], axis=0) + R = covs.mean(0) + + covs = [S, R] + C_ref = R + if not isinstance(rank, dict): + rank = _compute_rank_raw_array( + np.hstack(X), + info, + rank=rank, + scalings=None, + log_ch_type="data", + on_few_samples="ignore", + ) + return covs, C_ref, info, rank, dict() diff --git a/mne-python/source/mne/decoding/_fixes.py b/mne-python/source/mne/decoding/_fixes.py new file mode 100644 index 0000000000000000000000000000000000000000..0a71721279ec771466f417fa3f00fa155e5ff272 --- /dev/null +++ b/mne-python/source/mne/decoding/_fixes.py @@ -0,0 +1,174 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +try: + # TODO VERSION remove once we require sklearn 1.6+ + from sklearn.utils.validation import validate_data +except ImportError: + from sklearn.utils.validation import check_array, check_X_y + + # Use a limited version pulled from sklearn 1.7 + def validate_data( + _estimator, + /, + X="no_validation", + y="no_validation", + reset=True, + validate_separately=False, + skip_check_array=False, + **check_params, + ): + """Validate input data and set or check feature names and counts of the input. + + This helper function should be used in an estimator that requires input + validation. This mutates the estimator and sets the `n_features_in_` and + `feature_names_in_` attributes if `reset=True`. + + .. versionadded:: 1.6 + + Parameters + ---------- + _estimator : estimator instance + The estimator to validate the input for. + + X : {array-like, sparse matrix, dataframe} of shape \ + (n_samples, n_features), default='no validation' + The input samples. + If `'no_validation'`, no validation is performed on `X`. This is + useful for meta-estimator which can delegate input validation to + their underlying estimator(s). In that case `y` must be passed and + the only accepted `check_params` are `multi_output` and + `y_numeric`. + + y : array-like of shape (n_samples,), default='no_validation' + The targets. + + - If `None`, :func:`~sklearn.utils.check_array` is called on `X`. If + the estimator's `requires_y` tag is True, then an error will be raised. + - If `'no_validation'`, :func:`~sklearn.utils.check_array` is called + on `X` and the estimator's `requires_y` tag is ignored. This is a default + placeholder and is never meant to be explicitly set. In that case `X` must + be passed. + - Otherwise, only `y` with `_check_y` or both `X` and `y` are checked with + either :func:`~sklearn.utils.check_array` or + :func:`~sklearn.utils.check_X_y` depending on `validate_separately`. + + reset : bool, default=True + Whether to reset the `n_features_in_` attribute. + If False, the input will be checked for consistency with data + provided when reset was last True. + + .. note:: + + It is recommended to call `reset=True` in `fit` and in the first + call to `partial_fit`. All other methods that validate `X` + should set `reset=False`. + + validate_separately : False or tuple of dicts, default=False + Only used if `y` is not `None`. + If `False`, call :func:`~sklearn.utils.check_X_y`. Else, it must be a tuple + of kwargs to be used for calling :func:`~sklearn.utils.check_array` on `X` + and `y` respectively. + + `estimator=self` is automatically added to these dicts to generate + more informative error message in case of invalid input data. + + skip_check_array : bool, default=False + If `True`, `X` and `y` are unchanged and only `feature_names_in_` and + `n_features_in_` are checked. Otherwise, :func:`~sklearn.utils.check_array` + is called on `X` and `y`. + + **check_params : kwargs + Parameters passed to :func:`~sklearn.utils.check_array` or + :func:`~sklearn.utils.check_X_y`. Ignored if validate_separately + is not False. + + `estimator=self` is automatically added to these params to generate + more informative error message in case of invalid input data. + + Returns + ------- + out : {ndarray, sparse matrix} or tuple of these + The validated input. A tuple is returned if both `X` and `y` are + validated. + """ + no_val_X = isinstance(X, str) and X == "no_validation" + no_val_y = y is None or (isinstance(y, str) and y == "no_validation") + + if no_val_X and no_val_y: + raise ValueError("Validation should be done on X, y or both.") + + default_check_params = {"estimator": _estimator} + check_params = {**default_check_params, **check_params} + + if skip_check_array: + if not no_val_X and no_val_y: + out = X + elif no_val_X and not no_val_y: + out = y + else: + out = X, y + elif not no_val_X and no_val_y: + out = check_array(X, input_name="X", **check_params) + elif no_val_X and not no_val_y: + out = check_array(y, input_name="y", **check_params) + else: + if validate_separately: + # We need this because some estimators validate X and y + # separately, and in general, separately calling check_array() + # on X and y isn't equivalent to just calling check_X_y() + # :( + check_X_params, check_y_params = validate_separately + if "estimator" not in check_X_params: + check_X_params = {**default_check_params, **check_X_params} + X = check_array(X, input_name="X", **check_X_params) + if "estimator" not in check_y_params: + check_y_params = {**default_check_params, **check_y_params} + y = check_array(y, input_name="y", **check_y_params) + else: + X, y = check_X_y(X, y, **check_params) + out = X, y + + return out + + +def _check_n_features_3d(estimator, X, reset): + """Set the `n_features_in_` attribute, or check against it on an estimator. + + Sklearn takes n_features from X.shape[1], but we need X.shape[-1] + + Parameters + ---------- + estimator : estimator instance + The estimator to validate the input for. + + X : {ndarray, sparse matrix} of shape ([n_epochs], n_samples, n_features) + The input samples. + + reset : bool + If True, the `n_features_in_` attribute is set to `X.shape[1]`. + If False and the attribute exists, then check that it is equal to + `X.shape[1]`. If False and the attribute does *not* exist, then + the check is skipped. + .. note:: + It is recommended to call reset=True in `fit` and in the first + call to `partial_fit`. All other methods that validate `X` + should set `reset=False`. + """ + n_features = X.shape[-1] + if reset: + estimator.n_features_in_ = n_features + return + + if not hasattr(estimator, "n_features_in_"): + # Skip this check if the expected number of expected input features + # was not recorded by calling fit first. This is typically the case + # for stateless transformers. + return + + if n_features != estimator.n_features_in_: + raise ValueError( + f"X has {n_features} features, but {estimator.__class__.__name__} " + f"is expecting {estimator.n_features_in_} features as input." + ) diff --git a/mne-python/source/mne/decoding/_ged.py b/mne-python/source/mne/decoding/_ged.py new file mode 100644 index 0000000000000000000000000000000000000000..ed6915b6674cc7bb36fde8e5ff86fcbd58900f8b --- /dev/null +++ b/mne-python/source/mne/decoding/_ged.py @@ -0,0 +1,148 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import scipy.linalg + +from ..cov import Covariance, _smart_eigh, compute_whitener + + +def _handle_restr_mat(C_ref, restr_type, info, rank): + """Get restricting matrix to C_ref rank-dimensional principal subspace. + + Returns matrix of shape (rank, n_chs) used to restrict or + restrict+rescale (whiten) covariances matrices. + """ + if C_ref is None or restr_type is None: + return None + if restr_type == "whitening": + C_ref_cov = Covariance(C_ref, info.ch_names, info["bads"], info["projs"], 0) + restr_mat = compute_whitener( + C_ref_cov, info, rank=rank, pca=True, verbose="error" + )[0] + elif restr_type == "restricting": + restr_mat = _get_restr_mat(C_ref, info, rank) + else: + raise ValueError( + "restr_type should either be callable or one of " + "('whitening', 'restricting')" + ) + return restr_mat + + +def _smart_ged(S, R, restr_mat=None, R_func=None): + """Perform smart generalized eigenvalue decomposition (GED) of S and R. + + If restr_mat is provided S and R will be restricted to the principal subspace + of a reference matrix with rank r (see _handle_restr_mat), then GED is performed + on the restricted S and R and then generalized eigenvectors are transformed back + to the original space. The g-eigenvectors matrix is of shape (n_chs, r). + If callable R_func is provided the GED will be performed on (S, R_func(S,R)) + """ + if restr_mat is None: + evals, evecs = scipy.linalg.eigh(S, R) + return evals, evecs + + S_restr = restr_mat @ S @ restr_mat.T + R_restr = restr_mat @ R @ restr_mat.T + if R_func is not None: + R_restr = R_func([S_restr, R_restr]) + evals, evecs_restr = scipy.linalg.eigh(S_restr, R_restr) + evecs = restr_mat.T @ evecs_restr + + return evals, evecs + + +def _is_cov_symm(cov, rtol=1e-7, atol=None): + if atol is None: + atol = 1e-7 * np.max(np.abs(cov)) + is_symm = scipy.linalg.issymmetric(cov, rtol=rtol, atol=atol) + return is_symm + + +def _get_cov_def(cov, eval_tol=None): + """Get definiteness of symmetric cov matrix. + + All evals in (-eval_tol, eval_tol) will be considered zero, + while all evals smaller than -eval_tol will be considered + negative. + """ + evals = scipy.linalg.eigvalsh(cov) + if eval_tol is None: + eval_tol = 1e-7 * np.max(np.abs(evals)) + if np.all(evals > eval_tol): + return "pos_def" + elif np.all(evals >= -eval_tol): + return "pos_semidef" + else: + return "indef" + + +def _is_cov_pos_semidef(cov, eval_tol=None): + cov_def = _get_cov_def(cov, eval_tol=eval_tol) + return cov_def in ("pos_def", "pos_semidef") + + +def _is_cov_pos_def(cov, eval_tol=None): + cov_def = _get_cov_def(cov, eval_tol=eval_tol) + return cov_def == "pos_def" + + +def _smart_ajd(covs, restr_mat=None, weights=None): + """Perform smart approximate joint diagonalization. + + If restr_mat is provided all the cov matrices will be restricted to the + principal subspace of a reference matrix with rank r (see _handle_restr_mat), + then GED is performed on the restricted S and R and then generalized eigenvectors + are transformed back to the original space. + The matrix of generalized eigenvectors is of shape (n_chs, r). + """ + from .csp import _ajd_pham + + if restr_mat is None: + are_all_pos_def = all([_is_cov_pos_def(cov) for cov in covs]) + if not are_all_pos_def: + raise ValueError( + "If C_ref is not provided by covariance estimator, " + "all the covs should be positive definite" + ) + evecs, D = _ajd_pham(covs) + return evecs + + else: + are_all_pos_semidef = all([_is_cov_pos_semidef(cov) for cov in covs]) + if not are_all_pos_semidef: + raise ValueError( + "All the covs should be positive semi-definite for " + "approximate joint diagonalization" + ) + covs = np.array([restr_mat @ cov @ restr_mat.T for cov in covs], float) + evecs_restr, D = _ajd_pham(covs) + evecs = _normalize_eigenvectors(evecs_restr.T, covs, weights) + evecs = restr_mat.T @ evecs + return evecs + + +def _get_restr_mat(C, info, rank): + """Get matrix restricting covariance to rank-dimensional principal subspace of C.""" + _, ref_evecs, mask = _smart_eigh( + C, + info, + rank, + proj_subspace=True, + do_compute_rank=False, + log_ch_type="data", + ) + restr_mat = ref_evecs[mask] + return restr_mat + + +def _normalize_eigenvectors(evecs, covs, sample_weights): + # Here we apply an euclidean mean. See pyRiemann for other metrics + mean_cov = np.average(covs, axis=0, weights=sample_weights) + + for ii in range(evecs.shape[1]): + tmp = np.dot(np.dot(evecs[:, ii].T, mean_cov), evecs[:, ii]) + evecs[:, ii] /= np.sqrt(tmp) + return evecs diff --git a/mne-python/source/mne/decoding/_mod_ged.py b/mne-python/source/mne/decoding/_mod_ged.py new file mode 100644 index 0000000000000000000000000000000000000000..df917a78ae3f136a284cafc2fee29311e78d2ad6 --- /dev/null +++ b/mne-python/source/mne/decoding/_mod_ged.py @@ -0,0 +1,132 @@ +"""Eigenvalue eigenvector modifiers for GED transformers.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ..time_frequency import psd_array_welch +from ..utils import _time_mask + + +def _compute_mutual_info(covs, sample_weights, evecs): + class_probas = sample_weights / sample_weights.sum() + + mutual_info = [] + for jj in range(evecs.shape[1]): + aa, bb = 0, 0 + for cov, prob in zip(covs, class_probas): + tmp = np.dot(np.dot(evecs[:, jj].T, cov), evecs[:, jj]) + aa += prob * np.log(np.sqrt(tmp)) + bb += prob * (tmp**2 - 1) + mi = -(aa + (3.0 / 16) * (bb**2)) + mutual_info.append(mi) + + return mutual_info + + +def _csp_mod(evals, evecs, covs, evecs_order, sample_weights): + n_classes = sample_weights.shape[0] + if evecs_order == "mutual_info" and n_classes > 2: + mutual_info = _compute_mutual_info(covs, sample_weights, evecs) + ix = np.argsort(mutual_info)[::-1] + elif evecs_order == "mutual_info" and n_classes == 2: + ix = np.argsort(np.abs(evals - 0.5))[::-1] + elif evecs_order == "alternate" and n_classes == 2: + i = np.argsort(evals) + ix = np.empty_like(i) + ix[1::2] = i[: len(i) // 2] + ix[0::2] = i[len(i) // 2 :][::-1] + if evals is not None: + evals = evals[ix] + evecs = evecs[:, ix] + sorter = ix + return evals, evecs, sorter + + +def _xdawn_mod(evals, evecs, covs=None): + evals, evecs, sorter = _sort_descending(evals, evecs) + evecs /= np.linalg.norm(evecs, axis=0) + return evals, evecs, sorter + + +def _get_spectral_ratio(ssd_sources, sfreq, n_fft, freqs_signal, freqs_noise): + """Get the spectal signal-to-noise ratio for each spatial filter. + + Spectral ratio measure for best n_components selection + See :footcite:`NikulinEtAl2011`, Eq. (24). + + Returns + ------- + spec_ratio : array, shape (n_channels) + Array with the sprectal ratio value for each component. + sorter_spec : array, shape (n_channels) + Array of indices for sorting spec_ratio. + + References + ---------- + .. footbibliography:: + """ + psd, freqs = psd_array_welch(ssd_sources, sfreq=sfreq, n_fft=n_fft) + sig_idx = _time_mask(freqs, *freqs_signal) + noise_idx = _time_mask(freqs, *freqs_noise) + if psd.ndim == 3: + mean_sig = psd[:, :, sig_idx].mean(axis=2).mean(axis=0) + mean_noise = psd[:, :, noise_idx].mean(axis=2).mean(axis=0) + spec_ratio = mean_sig / mean_noise + else: + mean_sig = psd[:, sig_idx].mean(axis=1) + mean_noise = psd[:, noise_idx].mean(axis=1) + spec_ratio = mean_sig / mean_noise + sorter_spec = spec_ratio.argsort()[::-1] + return spec_ratio, sorter_spec + + +def _ssd_mod( + evals, + evecs, + covs, + X, + picks, + sfreq, + n_fft, + freqs_signal, + freqs_noise, + sort_by_spectral_ratio, +): + evals, evecs, sorter = _sort_descending(evals, evecs) + if sort_by_spectral_ratio: + # We assume that ordering by spectral ratio is more important + # than the initial ordering. + filters = evecs.T + ssd_sources = filters @ X[..., picks, :] + _, sorter_spec = _get_spectral_ratio( + ssd_sources, sfreq, n_fft, freqs_signal, freqs_noise + ) + evecs = evecs[:, sorter_spec] + evals = evals[sorter_spec] + sorter = sorter_spec + return evals, evecs, sorter + + +def _spoc_mod(evals, evecs, covs=None): + evals = evals.real + evecs = evecs.real + evals, evecs, sorter = _sort_descending(evals, evecs, by_abs=True) + return evals, evecs, sorter + + +def _sort_descending(evals, evecs, by_abs=False): + if by_abs: + ix = np.argsort(np.abs(evals))[::-1] + else: + ix = np.argsort(evals)[::-1] + evals = evals[ix] + evecs = evecs[:, ix] + sorter = ix + return evals, evecs, sorter + + +def _no_op_mod(evals, evecs, *args, **kwargs): + return evals, evecs, None diff --git a/mne-python/source/mne/decoding/base.py b/mne-python/source/mne/decoding/base.py new file mode 100644 index 0000000000000000000000000000000000000000..3a51a04bed7ab93a8139ed651d3f137fc4d6ce27 --- /dev/null +++ b/mne-python/source/mne/decoding/base.py @@ -0,0 +1,925 @@ +"""Base class copy from sklearn.base.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime as dt +import numbers +from functools import partial +from inspect import Parameter, signature + +import numpy as np +from sklearn import model_selection as models +from sklearn.base import ( # noqa: F401 + BaseEstimator, + MetaEstimatorMixin, + TransformerMixin, + clone, + is_classifier, + is_regressor, +) +from sklearn.linear_model import LogisticRegression +from sklearn.metrics import check_scoring +from sklearn.model_selection import KFold, StratifiedKFold, check_cv +from sklearn.utils import indexable +from sklearn.utils.validation import check_is_fitted + +from ..parallel import parallel_func +from ..utils import ( + _check_option, + _pl, + _validate_type, + logger, + pinv, + verbose, + warn, +) +from ._fixes import validate_data +from ._ged import ( + _handle_restr_mat, + _is_cov_pos_semidef, + _is_cov_symm, + _smart_ajd, + _smart_ged, +) +from ._mod_ged import _no_op_mod +from .transformer import MNETransformerMixin, Vectorizer + + +class _GEDTransformer(MNETransformerMixin, BaseEstimator): + """M/EEG signal decomposition using the generalized eigenvalue decomposition (GED). + + Given two channel covariance matrices S and R, the goal is to find spatial filters + that maximise contrast between S and R. + + Parameters + ---------- + n_components : int | None + The number of spatial filters to decompose M/EEG signals. + If None, all of the components will be used for transformation. + Defaults to None. + cov_callable : callable + Function used to estimate covariances and reference matrix (C_ref) from the + data. The only required arguments should be 'X' and optionally 'y'. The function + should return covs, C_ref, info, rank and additional kwargs passed further + to mod_ged_callable. C_ref, info, rank can be None and kwargs can be empty dict. + mod_ged_callable : callable | None + Function used to modify (e.g. sort or normalize) generalized + eigenvalues and eigenvectors. It should accept as arguments evals, evecs + and also covs and optional kwargs returned by cov_callable. It should return + sorted and/or modified evals and evecs and the list of indices according + to which the first two were sorted. If None, evals and evecs will be + ordered according to :func:`~scipy.linalg.eigh` default. Defaults to None. + dec_type : "single" | "multi" + When "single" and cov_callable returns > 2 covariances, + approximate joint diagonalization based on Pham's algorithm + will be used instead of GED. + When 'multi', GED is performed separately for each class, i.e. each covariance + (except the last) returned by cov_callable is decomposed with the last + covariance. In this case, number of covariances should be number of classes + 1. + Defaults to "single". + restr_type : "restricting" | "whitening" | None + Restricting transformation for covariance matrices before performing GED. + If "restricting" only restriction to the principal subspace of the C_ref + will be performed. + If "whitening", covariance matrices will be additionally rescaled according + to the whitening for the C_ref. + If None, no restriction will be applied. Defaults to None. + R_func : callable | None + If provided, GED will be performed on (S, R_func([S,R])). When dec_type is + "single", R_func applicable only if two covariances returned by cov_callable. + If None, GED is performed on (S, R). Defaults to None. + + Attributes + ---------- + evals_ : ndarray, shape (n_channels) + If fit, generalized eigenvalues used to decompose S and R, else None. + filters_ : ndarray, shape (n_channels or less, n_channels) + If fit, spatial filters (unmixing matrix) used to decompose the data, + else None. + patterns_ : ndarray, shape (n_channels or less, n_channels) + If fit, spatial patterns (mixing matrix) used to restore M/EEG signals, + else None. + + See Also + -------- + CSP + SPoC + SSD + + Notes + ----- + .. versionadded:: 1.11 + """ + + def __init__( + self, + cov_callable=None, + n_components=None, + mod_ged_callable=None, + dec_type="single", + restr_type=None, + R_func=None, + ): + self.n_components = n_components + self.cov_callable = cov_callable + self.mod_ged_callable = mod_ged_callable + self.dec_type = dec_type + self.restr_type = restr_type + self.R_func = R_func + + _is_base_ged = True + + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + cls._is_base_ged = False + + def fit(self, X, y=None): + """...""" + # Let the inheriting transformers check data by themselves + if self._is_base_ged: + X, y = self._check_data( + X, + y=y, + fit=True, + return_y=True, + ) + self._validate_ged_params() + covs, C_ref, info, rank, kwargs = self.cov_callable(X, y) + covs = np.stack(covs) + self._validate_covariances(covs) + if C_ref is not None: + self._validate_covariances([C_ref]) + mod_ged_callable = ( + self.mod_ged_callable if self.mod_ged_callable is not None else _no_op_mod + ) + restr_mat = _handle_restr_mat(C_ref, self.restr_type, info, rank) + + if self.dec_type == "single": + if len(covs) > 2: + weights = kwargs.get("sample_weights", None) + evecs = _smart_ajd(covs, restr_mat, weights=weights) + evals = None + else: + S = covs[0] + R = covs[1] + evals, evecs = _smart_ged(S, R, restr_mat, R_func=self.R_func) + + evals, evecs, self.sorter_ = mod_ged_callable(evals, evecs, covs, **kwargs) + self.evals_ = evals + self.filters_ = evecs.T + self.patterns_ = pinv(evecs) + + elif self.dec_type == "multi": + self.classes_ = np.unique(y) + R = covs[-1] + all_evals, all_evecs = list(), list() + all_patterns, all_sorters = list(), list() + for i in range(len(self.classes_)): + S = covs[i] + + evals, evecs = _smart_ged(S, R, restr_mat, R_func=self.R_func) + + evals, evecs, sorter = mod_ged_callable(evals, evecs, covs, **kwargs) + all_evals.append(evals) + all_evecs.append(evecs.T) + all_patterns.append(pinv(evecs)) + all_sorters.append(sorter) + self.sorter_ = np.array(all_sorters) + self.evals_ = np.array(all_evals) + self.filters_ = np.array(all_evecs) + self.patterns_ = np.array(all_patterns) + + return self + + def transform(self, X): + """...""" + check_is_fitted(self, "filters_") + # Let the inheriting transformers check data by themselves + if self._is_base_ged: + X = self._check_data(X) + if self.dec_type == "single": + pick_filters = self.filters_[: self.n_components] + elif self.dec_type == "multi": + pick_filters = self._subset_multi_components() + X = pick_filters @ X + return X + + def _subset_multi_components(self, name="filters"): + # The shape of stored filters and patterns is + # is (n_classes, n_evecs, n_chs) + # Transform and subset into (n_classes*n_components, n_chs) + if name == "filters": + return self.filters_[:, : self.n_components, :].reshape( + -1, self.filters_.shape[2] + ) + elif name == "patterns": + return self.patterns_[:, : self.n_components, :].reshape( + -1, self.patterns_.shape[2] + ) + return None + + def _validate_required_args(self, func, desired_required_args): + sig = signature(func) + actual_required_args = [ + param.name + for param in sig.parameters.values() + if param.default is Parameter.empty + ] + func_name = func.func.__name__ if isinstance(func, partial) else func.__name__ + if not all(arg in desired_required_args for arg in actual_required_args): + raise ValueError( + f"Invalid required arguments for '{func_name}'. " + f"The only allowed required arguments are {desired_required_args}, " + f"but got {actual_required_args} instead." + ) + + def _validate_ged_params(self): + # Naming is GED-specific so that the validation is still executed + # when child classes run super().fit() + + _validate_type(self.n_components, (int, None), "n_components") + if self.n_components is not None and self.n_components <= 0: + raise ValueError( + "Invalid value for the 'n_components' parameter. " + "Allowed are positive integers or None, " + "but got a non-positive integer instead." + ) + + self._validate_required_args( + self.cov_callable, desired_required_args=["X", "y"] + ) + + _check_option( + "dec_type", + self.dec_type, + ("single", "multi"), + ) + + _check_option( + "restr_type", + self.restr_type, + ("restricting", "whitening", None), + ) + + def _validate_covariances(self, covs): + error_template = ( + "{matrix} is not {prop}, but required to be for {decomp}. " + "Check your cov_callable" + ) + if len(covs) == 1: + C_ref = covs[0] + is_C_ref_symm = _is_cov_symm(C_ref) + if not is_C_ref_symm: + raise ValueError( + error_template.format( + matrix="C_ref covariance", + prop="symmetric", + decomp="decomposition", + ) + ) + elif self.dec_type == "single" and len(covs) > 2: + # make only lenient symmetric check here. + # positive semidefiniteness/definiteness will be + # checked inside _smart_ajd + for ci, cov in enumerate(covs): + if not _is_cov_symm(cov): + raise ValueError( + error_template.format( + matrix=f"cov[{ci}]", + prop="symmetric", + decomp="approximate joint diagonalization", + ) + ) + else: + if len(covs) == 2: + S_covs = [covs[0]] + R = covs[1] + elif self.dec_type == "multi": + S_covs = covs[:-1] + R = covs[-1] + + are_all_S_symm = all([_is_cov_symm(S) for S in S_covs]) + if not are_all_S_symm: + raise ValueError( + error_template.format( + matrix="S covariance", + prop="symmetric", + decomp="generalized eigendecomposition", + ) + ) + if not _is_cov_symm(R): + raise ValueError( + error_template.format( + matrix="R covariance", + prop="symmetric", + decomp="generalized eigendecomposition", + ) + ) + if not _is_cov_pos_semidef(R): + raise ValueError( + error_template.format( + matrix="R covariance", + prop="positive semi-definite", + decomp="generalized eigendecomposition", + ) + ) + + def __sklearn_tags__(self): + """Tag the transformer.""" + tags = super().__sklearn_tags__() + # Can be a transformer where S and R covs are not based on y classes. + tags.target_tags.required = False + tags.target_tags.one_d_labels = True + tags.input_tags.two_d_array = True + tags.input_tags.three_d_array = True + tags.requires_fit = True + return tags + + +class LinearModel(MetaEstimatorMixin, BaseEstimator): + """Compute and store patterns from linear models. + + The linear model coefficients (filters) are used to extract discriminant + neural sources from the measured data. This class computes the + corresponding patterns of these linear filters to make them more + interpretable :footcite:`HaufeEtAl2014`. + + Parameters + ---------- + model : object | None + A linear model from scikit-learn with a fit method + that updates a ``coef_`` attribute. + If None the model will be + :class:`sklearn.linear_model.LogisticRegression`. + + Attributes + ---------- + filters_ : ndarray, shape ([n_targets], n_features) + If fit, the filters used to decompose the data. + patterns_ : ndarray, shape ([n_targets], n_features) + If fit, the patterns used to restore M/EEG signals. + + See Also + -------- + CSP + mne.preprocessing.ICA + mne.preprocessing.Xdawn + + Notes + ----- + .. versionadded:: 0.10 + + References + ---------- + .. footbibliography:: + """ + + _model_attr_wrap = ( + "transform", + "fit_transform", + "predict", + "predict_proba", + "predict_log_proba", + "_estimator_type", # remove after sklearn 1.6 + "decision_function", + "score", + "classes_", + ) + + def __init__(self, model=None): + self.model = model + + def __sklearn_tags__(self): + """Get sklearn tags.""" + tags = super().__sklearn_tags__() + model = self.model if self.model is not None else LogisticRegression() + model_tags = model.__sklearn_tags__() + tags.estimator_type = model_tags.estimator_type + if tags.estimator_type is not None: + model_type_tags = getattr(model_tags, f"{tags.estimator_type}_tags") + setattr(tags, f"{tags.estimator_type}_tags", model_type_tags) + return tags + + def __getattr__(self, attr): + """Wrap to model for some attributes.""" + if attr in LinearModel._model_attr_wrap: + model = self.model_ if "model_" in self.__dict__ else self.model + if attr == "fit_transform" and hasattr(model, "fit_transform"): + return self._fit_transform + else: + return getattr(model, attr) + else: + raise AttributeError( + f"'{type(self).__name__}' object has no attribute '{attr}'" + ) + + def _fit_transform(self, X, y): + return self.fit(X, y).transform(X) + + def _validate_params(self, X): + if self.model is not None: + model = self.model + if isinstance(model, MetaEstimatorMixin): + model = model.estimator + is_predictor = is_regressor(model) or is_classifier(model) + if not is_predictor: + raise ValueError( + "Linear model should be a supervised predictor " + "(classifier or regressor)" + ) + + # For sklearn < 1.6 + try: + self._check_n_features(X, reset=True) + except AttributeError: + pass + + def fit(self, X, y, **fit_params): + """Estimate the coefficients of the linear model. + + Save the coefficients in the attribute ``filters_`` and + computes the attribute ``patterns_``. + + Parameters + ---------- + X : array, shape (n_samples, n_features) + The training input samples to estimate the linear coefficients. + y : array, shape (n_samples, [n_targets]) + The target values. + **fit_params : dict of string -> object + Parameters to pass to the fit method of the estimator. + + Returns + ------- + self : instance of LinearModel + Returns the modified instance. + """ + self._validate_params(X) + X, y = validate_data(self, X, y, multi_output=True) + + # fit the Model + self.model_ = ( + clone(self.model) + if self.model is not None + else LogisticRegression(solver="liblinear") + ) + self.model_.fit(X, y, **fit_params) + + # Computes patterns using Haufe's trick: A = Cov_X . W . Precision_Y + inv_Y = 1.0 + X = X - X.mean(0, keepdims=True) + if y.ndim == 2 and y.shape[1] != 1: + y = y - y.mean(0, keepdims=True) + inv_Y = np.linalg.pinv(np.cov(y.T)) + self.patterns_ = np.cov(X.T).dot(self.filters_.T.dot(inv_Y)).T + + return self + + @property + def filters_(self): + if hasattr(self.model_, "coef_"): + # Standard Linear Model + filters = self.model_.coef_ + elif hasattr(self.model_, "estimators_"): + # Linear model with OneVsRestClassifier + filters = np.vstack([est.coef_ for est in self.model_.estimators_]) + elif hasattr(self.model_, "best_estimator_") and hasattr( + self.model_.best_estimator_, "coef_" + ): + # Linear Model with GridSearchCV + filters = self.model_.best_estimator_.coef_ + else: + raise ValueError("model does not have a `coef_` attribute.") + if filters.ndim == 2 and filters.shape[0] == 1: + filters = filters[0] + return filters + + +def _set_cv(cv, estimator=None, X=None, y=None): + """Set the default CV depending on whether clf is classifier/regressor.""" + # Detect whether classification or regression + + if estimator in ["classifier", "regressor"]: + est_is_classifier = estimator == "classifier" + else: + est_is_classifier = is_classifier(estimator) + # Setup CV + if isinstance(cv, int | np.int64): + XFold = StratifiedKFold if est_is_classifier else KFold + cv = XFold(n_splits=cv) + elif isinstance(cv, str): + if not hasattr(models, cv): + raise ValueError("Unknown cross-validation") + cv = getattr(models, cv) + cv = cv() + cv = check_cv(cv=cv, y=y, classifier=est_is_classifier) + + # Extract train and test set to retrieve them at predict time + cv_splits = [(train, test) for train, test in cv.split(X=np.zeros_like(y), y=y)] + + if not np.all([len(train) for train, _ in cv_splits]): + raise ValueError("Some folds do not have any train epochs.") + + return cv, cv_splits + + +def _check_estimator(estimator, get_params=True): + """Check whether an object has the methods required by sklearn.""" + valid_methods = ("predict", "transform", "predict_proba", "decision_function") + if (not hasattr(estimator, "fit")) or ( + not any(hasattr(estimator, method) for method in valid_methods) + ): + raise ValueError( + "estimator must be a scikit-learn transformer or " + "an estimator with the fit and a predict-like (e.g. " + "predict_proba) or a transform method." + ) + + if get_params and not hasattr(estimator, "get_params"): + raise ValueError( + "estimator must be a scikit-learn transformer or an " + "estimator with the get_params method that allows " + "cloning." + ) + + +def _get_inverse_funcs(estimator, terminal=True): + """Retrieve the inverse functions of an pipeline or an estimator.""" + inverse_func = list() + estimators = list() + if hasattr(estimator, "steps"): + # if pipeline, retrieve all steps by nesting + for _, est in estimator.steps: + inverse_func.extend(_get_inverse_funcs(est, terminal=False)) + estimators.append(est.__class__.__name__) + elif hasattr(estimator, "inverse_transform"): + # if not pipeline attempt to retrieve inverse function + inverse_func.append(estimator.inverse_transform) + estimators.append(estimator.__class__.__name__) + else: + inverse_func.append(False) + estimators.append("Unknown") + + # If terminal node, check that that the last estimator is a classifier, + # and remove it from the transformers. + if terminal: + last_is_estimator = inverse_func[-1] is False + logger.debug(f" Last estimator is an estimator: {last_is_estimator}") + non_invertible = np.where( + [inv_func is False for inv_func in inverse_func[:-1]] + )[0] + if last_is_estimator and len(non_invertible) == 0: + # keep all inverse transformation and remove last estimation + logger.debug(" Removing inverse transformation from inverse list.") + inverse_func = inverse_func[:-1] + else: + if len(non_invertible): + bad = ", ".join(estimators[ni] for ni in non_invertible) + warn( + f"Cannot inverse transform non-invertible " + f"estimator{_pl(non_invertible)}: {bad}." + ) + inverse_func = list() + + return inverse_func + + +def _get_inverse_funcs_before_step(estimator, step_name): + """Get the inverse_transform methods for all steps before a target step.""" + # in case step_name is nested with __ + parts = step_name.split("__") + inverse_funcs = list() + current_pipeline = estimator + for part_name in parts: + all_names = [name for name, _ in current_pipeline.steps] + part_idx = all_names.index(part_name) + # get all preceding steps for the current step + for prec_name, prec_step in current_pipeline.steps[:part_idx]: + if hasattr(prec_step, "inverse_transform"): + inverse_funcs.append(prec_step.inverse_transform) + else: + warn( + f"Preceding step '{prec_name}' is not invertible " + f"and will be skipped." + ) + current_pipeline = current_pipeline.named_steps[part_name] + return inverse_funcs + + +@verbose +def get_coef( + estimator, attr="filters_", inverse_transform=False, *, step_name=None, verbose=None +): + """Retrieve the coefficients of an estimator ending with a Linear Model. + + This is typically useful to retrieve "spatial filters" or "spatial + patterns" of decoding models :footcite:`HaufeEtAl2014`. + + Parameters + ---------- + estimator : object | None + An estimator from scikit-learn. + attr : str + The name of the coefficient attribute to retrieve, typically + ``'filters_'`` (default) or ``'patterns_'``. + inverse_transform : bool + If True, returns the coefficients after inverse transforming them with + the transformer steps of the estimator. + step_name : str | None + Name of the sklearn's pipeline step to get the coef from. + If inverse_transform is True, the inverse transformations + will be applied using transformers before this step. + If None, the last step will be used. Defaults to None. + + .. versionadded:: 1.11 + %(verbose)s + + Returns + ------- + coef : array + The coefficients. + + References + ---------- + .. footbibliography:: + """ + # Get the coefficients of the last estimator in case of nested pipeline + est = estimator + logger.debug(f"Getting coefficients from estimator: {est.__class__.__name__}") + + if step_name is not None: + if not hasattr(estimator, "named_steps"): + raise ValueError("step_name can only be used with a pipeline estimator.") + try: + est = est.get_params(deep=True)[step_name] + except KeyError: + raise ValueError(f"Step '{step_name}' is not part of the pipeline.") + else: + while hasattr(est, "steps"): + est = est.steps[-1][1] + + squeeze_first_dim = False + + # If SlidingEstimator, loop across estimators + if hasattr(est, "estimators_"): + coef = list() + for ei, this_est in enumerate(est.estimators_): + if ei == 0: + logger.debug(" Extracting coefficients from SlidingEstimator.") + coef.append(get_coef(this_est, attr, inverse_transform)) + coef = np.transpose(coef) + coef = coef[np.newaxis] # fake a sample dimension + squeeze_first_dim = True + elif not hasattr(est, attr): + raise ValueError(f"This estimator does not have a {attr} attribute:\n{est}") + else: + coef = getattr(est, attr) + + if coef.ndim == 1: + coef = coef[np.newaxis] + squeeze_first_dim = True + + # inverse pattern e.g. to get back physical units + if inverse_transform: + if not hasattr(estimator, "steps") and not hasattr(est, "estimators_"): + raise ValueError( + "inverse_transform can only be applied onto pipeline estimators." + ) + if step_name is None: + inverse_funcs = _get_inverse_funcs(estimator) + else: + inverse_funcs = _get_inverse_funcs_before_step(estimator, step_name) + + # The inverse_transform parameter will call this method on any + # estimator contained in the pipeline, in reverse order. + for inverse_func in inverse_funcs[::-1]: + logger.debug(f" Applying inverse transformation: {inverse_func}.") + coef = inverse_func(coef) + + if squeeze_first_dim: + logger.debug(" Squeezing first dimension of coefficients.") + coef = coef[0] + + # inverse_transform with Vectorizer returns shape (n_channels, n_components). + # we should transpose to be consistent with how spatial filters + # store filters and patterns: (n_components, n_channels) + if inverse_transform and hasattr(estimator, "steps"): + is_vectorizer = any( + isinstance(param_value, Vectorizer) + for param_value in estimator.get_params(deep=True).values() + ) + if is_vectorizer and coef.ndim == 2: + coef = coef.T + + return coef + + +@verbose +def cross_val_multiscore( + estimator, + X, + y=None, + groups=None, + scoring=None, + cv=None, + n_jobs=None, + verbose=None, + fit_params=None, + pre_dispatch="2*n_jobs", +): + """Evaluate a score by cross-validation. + + Parameters + ---------- + estimator : instance of sklearn.base.BaseEstimator + The object to use to fit the data. + Must implement the 'fit' method. + X : array-like, shape (n_samples, n_dimensional_features,) + The data to fit. Can be, for example a list, or an array at least 2d. + y : array-like, shape (n_samples, n_targets,) + The target variable to try to predict in the case of + supervised learning. + groups : array-like, with shape (n_samples,) + Group labels for the samples used while splitting the dataset into + train/test set. + scoring : str, callable | None + A string (see model evaluation documentation) or + a scorer callable object / function with signature + ``scorer(estimator, X, y)``. + Note that when using an estimator which inherently returns + multidimensional output - in particular, SlidingEstimator + or GeneralizingEstimator - you should set the scorer + there, not here. + cv : int, cross-validation generator | iterable + Determines the cross-validation splitting strategy. + Possible inputs for cv are: + + - None, to use the default 5-fold cross validation, + - integer, to specify the number of folds in a ``(Stratified)KFold``, + - An object to be used as a cross-validation generator. + - An iterable yielding train, test splits. + + For integer/None inputs, if the estimator is a classifier and ``y`` is + either binary or multiclass, + :class:`sklearn.model_selection.StratifiedKFold` is used. In all + other cases, :class:`sklearn.model_selection.KFold` is used. + %(n_jobs)s + %(verbose)s + fit_params : dict, optional + Parameters to pass to the fit method of the estimator. + pre_dispatch : int, or str, optional + Controls the number of jobs that get dispatched during parallel + execution. Reducing this number can be useful to avoid an + explosion of memory consumption when more jobs get dispatched + than CPUs can process. This parameter can be: + + - None, in which case all the jobs are immediately + created and spawned. Use this for lightweight and + fast-running jobs, to avoid delays due to on-demand + spawning of the jobs + - An int, giving the exact number of total jobs that are + spawned + - A string, giving an expression as a function of n_jobs, + as in '2*n_jobs' + + Returns + ------- + scores : array of float, shape (n_splits,) | shape (n_splits, n_scores) + Array of scores of the estimator for each run of the cross validation. + """ + # This code is copied from sklearn + X, y, groups = indexable(X, y, groups) + + cv = check_cv(cv, y, classifier=is_classifier(estimator)) + cv_iter = list(cv.split(X, y, groups)) + scorer = check_scoring(estimator, scoring=scoring) + # We clone the estimator to make sure that all the folds are + # independent, and that it is pickle-able. + # Note: this parallelization is implemented using MNE Parallel + parallel, p_func, n_jobs = parallel_func( + _fit_and_score, n_jobs, pre_dispatch=pre_dispatch + ) + position = hasattr(estimator, "position") + scores = parallel( + p_func( + estimator=clone(estimator), + X=X, + y=y, + scorer=scorer, + train=train, + test=test, + fit_params=fit_params, + verbose=verbose, + parameters=dict(position=ii % n_jobs) if position else None, + ) + for ii, (train, test) in enumerate(cv_iter) + ) + return np.array(scores)[:, 0, ...] # flatten over joblib output. + + +# This verbose is necessary to properly set the verbosity level +# during parallelization +@verbose +def _fit_and_score( + estimator, + X, + y, + scorer, + train, + test, + parameters, + fit_params, + return_train_score=False, + return_parameters=False, + return_n_test_samples=False, + return_times=False, + error_score="raise", + *, + verbose=None, + position=0, +): + """Fit estimator and compute scores for a given dataset split.""" + # This code is adapted from sklearn + from sklearn.model_selection import _validation + from sklearn.utils.metaestimators import _safe_split + from sklearn.utils.validation import _num_samples + + # Adjust length of sample weights + + fit_params = fit_params if fit_params is not None else {} + fit_params = { + k: _validation._index_param_value(X, v, train) for k, v in fit_params.items() + } + + if parameters is not None: + estimator.set_params(**parameters) + + start_time = dt.datetime.now() + + X_train, y_train = _safe_split(estimator, X, y, train) + X_test, y_test = _safe_split(estimator, X, y, test, train) + + try: + if y_train is None: + estimator.fit(X_train, **fit_params) + else: + estimator.fit(X_train, y_train, **fit_params) + + except Exception as e: + # Note fit time as time until error + fit_duration = dt.datetime.now() - start_time + score_duration = dt.timedelta(0) + if error_score == "raise": + raise + elif isinstance(error_score, numbers.Number): + test_score = error_score + if return_train_score: + train_score = error_score + warn( + "Classifier fit failed. The score on this train-test partition for " + f"these parameters will be set to {error_score}. Details: \n{e!r}" + ) + else: + raise ValueError( + "error_score must be the string 'raise' or a numeric value. (Hint: if " + "using 'raise', please make sure that it has been spelled correctly.)" + ) + + else: + fit_duration = dt.datetime.now() - start_time + test_score = _score(estimator, X_test, y_test, scorer) + score_duration = dt.datetime.now() - start_time - fit_duration + if return_train_score: + train_score = _score(estimator, X_train, y_train, scorer) + + ret = [train_score, test_score] if return_train_score else [test_score] + + if return_n_test_samples: + ret.append(_num_samples(X_test)) + if return_times: + ret.extend([fit_duration.total_seconds(), score_duration.total_seconds()]) + if return_parameters: + ret.append(parameters) + return ret + + +def _score(estimator, X_test, y_test, scorer): + """Compute the score of an estimator on a given test set. + + This code is the same as sklearn.model_selection._validation._score + but accepts to output arrays instead of floats. + """ + if y_test is None: + score = scorer(estimator, X_test) + else: + score = scorer(estimator, X_test, y_test) + if hasattr(score, "item"): + try: + # e.g. unwrap memmapped scalars + score = score.item() + except ValueError: + # non-scalar? + pass + return score diff --git a/mne-python/source/mne/decoding/csp.py b/mne-python/source/mne/decoding/csp.py new file mode 100644 index 0000000000000000000000000000000000000000..adf857d11b97d8e93896095d047d47385c0eec05 --- /dev/null +++ b/mne-python/source/mne/decoding/csp.py @@ -0,0 +1,850 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import collections.abc as abc +from functools import partial + +import numpy as np + +from .._fiff.meas_info import Info +from ..defaults import _BORDER_DEFAULT, _EXTRAPOLATE_DEFAULT, _INTERPOLATION_DEFAULT +from ..utils import _check_option, _validate_type, fill_doc, legacy +from ._covs_ged import _csp_estimate, _spoc_estimate +from ._mod_ged import _csp_mod, _spoc_mod +from .base import _GEDTransformer +from .spatial_filter import get_spatial_filter_from_estimator + + +@fill_doc +class CSP(_GEDTransformer): + """M/EEG signal decomposition using the Common Spatial Patterns (CSP). + + This class can be used as a supervised decomposition to estimate spatial + filters for feature extraction. CSP in the context of EEG was first + described in :footcite:`KolesEtAl1990`; a comprehensive tutorial on CSP can + be found in :footcite:`BlankertzEtAl2008`. Multi-class solving is + implemented from :footcite:`Grosse-WentrupBuss2008`. + + Parameters + ---------- + n_components : int (default 4) + The number of components to decompose M/EEG signals. This number should + be set by cross-validation. + reg : float | str | None (default None) + If not None (same as ``'empirical'``, default), allow regularization + for covariance estimation. If float (between 0 and 1), shrinkage is + used. For str values, ``reg`` will be passed as ``method`` to + :func:`mne.compute_covariance`. + log : None | bool (default None) + If ``transform_into`` equals ``'average_power'`` and ``log`` is None or + True, then apply a log transform to standardize features, else features + are z-scored. If ``transform_into`` is ``'csp_space'``, ``log`` must be + None. + cov_est : 'concat' | 'epoch' (default 'concat') + If ``'concat'``, covariance matrices are estimated on concatenated + epochs for each class. If ``'epoch'``, covariance matrices are + estimated on each epoch separately and then averaged over each class. + transform_into : 'average_power' | 'csp_space' (default 'average_power') + If 'average_power' then ``self.transform`` will return the average + power of each spatial filter. If ``'csp_space'``, ``self.transform`` + will return the data in CSP space. + norm_trace : bool (default False) + Normalize class covariance by its trace. Trace normalization is a step + of the original CSP algorithm :footcite:`KolesEtAl1990` to eliminate + magnitude variations in the EEG between individuals. It is not applied + in more recent work :footcite:`BlankertzEtAl2008`, + :footcite:`Grosse-WentrupBuss2008` and can have a negative impact on + pattern order. + cov_method_params : dict | None + Parameters to pass to :func:`mne.compute_covariance`. + + .. versionadded:: 0.16 + + restr_type : "restricting" | "whitening" | None + Restricting transformation for covariance matrices before performing + generalized eigendecomposition. + If "restricting" only restriction to the principal subspace of signal_cov + will be performed. + If "whitening", covariance matrices will be additionally rescaled according + to the whitening for the signal_cov. + If None, no restriction will be applied. Defaults to "restricting". + + .. versionadded:: 1.11 + info : mne.Info | None + The mne.Info object with information about the sensors and methods of + measurement used for covariance estimation and generalized + eigendecomposition. + If None, one channel type and no projections will be assumed and if + rank is dict, it will be sum of ranks per channel type. + Defaults to None. + + .. versionadded:: 1.11 + %(rank_none)s + + .. versionadded:: 0.17 + component_order : 'mutual_info' | 'alternate' (default 'mutual_info') + If ``'mutual_info'`` order components by decreasing mutual information + (in the two-class case this uses a simplification which orders + components by decreasing absolute deviation of the eigenvalues from 0.5 + :footcite:`BarachantEtAl2010`). For the two-class case, ``'alternate'`` + orders components by starting with the largest eigenvalue, followed by + the smallest, the second-to-largest, the second-to-smallest, and so on + :footcite:`BlankertzEtAl2008`. + + .. versionadded:: 0.21 + + Attributes + ---------- + filters_ : ndarray, shape (n_channels, n_channels) + If fit, the CSP components used to decompose the data, else None. + patterns_ : ndarray, shape (n_channels, n_channels) + If fit, the CSP patterns used to restore M/EEG signals, else None. + mean_ : ndarray, shape (n_components,) + If fit, the mean squared power for each component. + std_ : ndarray, shape (n_components,) + If fit, the std squared power for each component. + + See Also + -------- + XdawnTransformer, SPoC, SSD + + References + ---------- + .. footbibliography:: + """ + + def __init__( + self, + n_components=4, + reg=None, + log=None, + cov_est="concat", + transform_into="average_power", + norm_trace=False, + cov_method_params=None, + *, + restr_type="restricting", + info=None, + rank=None, + component_order="mutual_info", + ): + # Init default CSP + self.n_components = n_components + self.info = info + self.rank = rank + self.reg = reg + self.cov_est = cov_est + self.transform_into = transform_into + self.log = log + self.norm_trace = norm_trace + self.cov_method_params = cov_method_params + self.component_order = component_order + self.restr_type = restr_type + + cov_callable = partial( + _csp_estimate, + reg=reg, + cov_method_params=cov_method_params, + cov_est=cov_est, + info=info, + rank=rank, + norm_trace=norm_trace, + ) + mod_ged_callable = partial(_csp_mod, evecs_order=component_order) + super().__init__( + n_components=n_components, + cov_callable=cov_callable, + mod_ged_callable=mod_ged_callable, + restr_type=restr_type, + R_func=sum, + ) + + def __sklearn_tags__(self): + """Tag the transformer.""" + tags = super().__sklearn_tags__() + tags.target_tags.required = True + tags.target_tags.multi_output = True + return tags + + def _validate_params(self, *, y): + _validate_type(self.n_components, int, "n_components") + if hasattr(self, "cov_est"): + _validate_type(self.cov_est, str, "cov_est") + _check_option("cov_est", self.cov_est, ("concat", "epoch")) + if hasattr(self, "norm_trace"): + _validate_type(self.norm_trace, bool, "norm_trace") + _check_option( + "transform_into", self.transform_into, ["average_power", "csp_space"] + ) + if self.transform_into == "average_power": + _validate_type( + self.log, + (bool, None), + "log", + extra="when transform_into is 'average_power'", + ) + else: + _validate_type( + self.log, None, "log", extra="when transform_into is 'csp_space'" + ) + _check_option( + "component_order", self.component_order, ("mutual_info", "alternate") + ) + self.classes_ = np.unique(y) + n_classes = len(self.classes_) + if n_classes < 2: + raise ValueError( + "y should be a 1d array with more than two classes, " + f"but got {n_classes} class from {y}" + ) + elif n_classes > 2 and self.component_order == "alternate": + raise ValueError( + "component_order='alternate' requires two classes, but data contains " + f"{n_classes} classes; use component_order='mutual_info' instead." + ) + _validate_type(self.rank, (dict, None, str), "rank") + _validate_type(self.info, (Info, None), "info") + _validate_type(self.cov_method_params, (abc.Mapping, None), "cov_method_params") + + def fit(self, X, y): + """Estimate the CSP decomposition on epochs. + + Parameters + ---------- + X : ndarray, shape (n_epochs, n_channels, n_times) + The data on which to estimate the CSP. + y : array, shape (n_epochs,) + The class for each epoch. + + Returns + ------- + self : instance of CSP + Returns the modified instance. + """ + X, y = self._check_data(X, y=y, fit=True, return_y=True) + self._validate_params(y=y) + + # Covariance estimation, GED/AJD + # and evecs/evals sorting happen here + super().fit(X, y) + + pick_filters = self.filters_[: self.n_components] + X = np.asarray([np.dot(pick_filters, epoch) for epoch in X]) + + # compute features (mean power) + X = (X**2).mean(axis=2) + + # To standardize features + self.mean_ = X.mean(axis=0) + self.std_ = X.std(axis=0) + + return self + + def transform(self, X): + """Estimate epochs sources given the CSP filters. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_times) + The data. + + Returns + ------- + X : ndarray + If self.transform_into == 'average_power' then returns the power of + CSP features averaged over time and shape (n_epochs, n_components) + If self.transform_into == 'csp_space' then returns the data in CSP + space and shape is (n_epochs, n_components, n_times). + """ + X = self._check_data(X) + X = super().transform(X) + # compute features (mean band power) + if self.transform_into == "average_power": + X = (X**2).mean(axis=2) + log = True if self.log is None else self.log + if log: + X = np.log(X) + else: + X -= self.mean_ + X /= self.std_ + return X + + def inverse_transform(self, X): + """Project CSP features back to sensor space. + + Parameters + ---------- + X : array, shape (n_epochs, n_components) + The data in CSP power space. + + Returns + ------- + X : ndarray + The data in sensor space and shape (n_epochs, n_channels, n_components). + """ + if self.transform_into != "average_power": + raise NotImplementedError( + "Can only inverse transform CSP features when transform_into is " + "'average_power'." + ) + if not (X.ndim == 2 and X.shape[1] == self.n_components): + raise ValueError( + f"X must be 2D with X[1]={self.n_components}, got {X.shape=}" + ) + return X[:, np.newaxis, :] * self.patterns_[: self.n_components].T + + def fit_transform(self, X, y=None, **fit_params): + """Fit CSP to data, then transform it. + + Fits transformer to ``X`` and ``y`` with optional parameters ``fit_params``, and + returns a transformed version of ``X``. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_times) + The data on which to estimate the CSP. + y : array, shape (n_epochs,) + The class for each epoch. + **fit_params : dict + Additional fitting parameters passed to the :meth:`mne.decoding.CSP.fit` + method. Not used for this class. + + Returns + ------- + X_csp : array, shape (n_epochs, n_components[, n_times]) + If ``self.transform_into == 'average_power'`` then returns the power of CSP + features averaged over time and shape is ``(n_epochs, n_components)``. If + ``self.transform_into == 'csp_space'`` then returns the data in CSP space + and shape is ``(n_epochs, n_components, n_times)``. + """ + # use parent TransformerMixin method but with custom docstring + return super().fit_transform(X, y=y, **fit_params) + + @legacy(alt="get_spatial_filter_from_estimator(clf, info=info).plot_patterns()") + @fill_doc + def plot_patterns( + self, + info, + components=None, + *, + ch_type=None, + scalings=None, + sensors=True, + show_names=False, + mask=None, + mask_params=None, + contours=6, + outlines="head", + sphere=None, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + border=_BORDER_DEFAULT, + res=64, + size=1, + cmap="RdBu_r", + vlim=(None, None), + cnorm=None, + colorbar=True, + cbar_fmt="%3.1f", + units=None, + axes=None, + name_format="CSP%01d", + nrows=1, + ncols="auto", + show=True, + ): + """Plot topographic patterns of components. + + The patterns explain how the measured data was generated from the + neural sources (a.k.a. the forward model). + + Parameters + ---------- + %(info_not_none)s Used for fitting. If not available, consider using + :func:`mne.create_info`. + components : float | array of float | None + The patterns to plot. If ``None``, all components will be shown. + %(ch_type_topomap)s + scalings : dict | float | None + The scalings of the channel types to be applied for plotting. + If None, defaults to ``dict(eeg=1e6, grad=1e13, mag=1e15)``. + %(sensors_topomap)s + %(show_names_topomap)s + %(mask_patterns_topomap)s + %(mask_params_topomap)s + %(contours_topomap)s + %(outlines_topomap)s + %(sphere_topomap_auto)s + %(image_interp_topomap)s + %(extrapolate_topomap)s + + .. versionadded:: 1.3 + %(border_topomap)s + + .. versionadded:: 1.3 + %(res_topomap)s + %(size_topomap)s + %(cmap_topomap)s + %(vlim_plot_topomap)s + + .. versionadded:: 1.3 + %(cnorm)s + + .. versionadded:: 1.3 + %(colorbar_topomap)s + %(cbar_fmt_topomap)s + %(units_topomap)s + %(axes_evoked_plot_topomap)s + name_format : str + String format for topomap values. Defaults to "CSP%%01d". + %(nrows_ncols_topomap)s + + .. versionadded:: 1.3 + %(show)s + + Returns + ------- + fig : instance of matplotlib.figure.Figure + The figure. + """ + spf = get_spatial_filter_from_estimator(self, info=info) + return spf.plot_patterns( + components, + ch_type=ch_type, + scalings=scalings, + sensors=sensors, + show_names=show_names, + mask=mask, + mask_params=mask_params, + contours=contours, + outlines=outlines, + sphere=sphere, + image_interp=image_interp, + extrapolate=extrapolate, + border=border, + res=res, + size=size, + cmap=cmap, + vlim=vlim, + cnorm=cnorm, + colorbar=colorbar, + cbar_fmt=cbar_fmt, + units=units, + axes=axes, + name_format=name_format, + nrows=nrows, + ncols=ncols, + show=show, + ) + + @legacy(alt="get_spatial_filter_from_estimator(clf, info=info).plot_filters()") + @fill_doc + def plot_filters( + self, + info, + components=None, + *, + ch_type=None, + scalings=None, + sensors=True, + show_names=False, + mask=None, + mask_params=None, + contours=6, + outlines="head", + sphere=None, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + border=_BORDER_DEFAULT, + res=64, + size=1, + cmap="RdBu_r", + vlim=(None, None), + cnorm=None, + colorbar=True, + cbar_fmt="%3.1f", + units=None, + axes=None, + name_format="CSP%01d", + nrows=1, + ncols="auto", + show=True, + ): + """Plot topographic filters of components. + + The filters are used to extract discriminant neural sources from + the measured data (a.k.a. the backward model). + + Parameters + ---------- + %(info_not_none)s Used for fitting. If not available, consider using + :func:`mne.create_info`. + components : float | array of float | None + The patterns to plot. If ``None``, all components will be shown. + %(ch_type_topomap)s + scalings : dict | float | None + The scalings of the channel types to be applied for plotting. + If None, defaults to ``dict(eeg=1e6, grad=1e13, mag=1e15)``. + %(sensors_topomap)s + %(show_names_topomap)s + %(mask_patterns_topomap)s + %(mask_params_topomap)s + %(contours_topomap)s + %(outlines_topomap)s + %(sphere_topomap_auto)s + %(image_interp_topomap)s + %(extrapolate_topomap)s + + .. versionadded:: 1.3 + %(border_topomap)s + + .. versionadded:: 1.3 + %(res_topomap)s + %(size_topomap)s + %(cmap_topomap)s + %(vlim_plot_topomap_psd)s + + .. versionadded:: 1.3 + %(cnorm)s + + .. versionadded:: 1.3 + %(colorbar_topomap)s + %(cbar_fmt_topomap)s + %(units_topomap)s + %(axes_evoked_plot_topomap)s + name_format : str + String format for topomap values. Defaults to "CSP%%01d". + %(nrows_ncols_topomap)s + + .. versionadded:: 1.3 + %(show)s + + Returns + ------- + fig : instance of matplotlib.figure.Figure + The figure. + """ + spf = get_spatial_filter_from_estimator(self, info=info) + return spf.plot_filters( + components, + ch_type=ch_type, + scalings=scalings, + sensors=sensors, + show_names=show_names, + mask=mask, + mask_params=mask_params, + contours=contours, + outlines=outlines, + sphere=sphere, + image_interp=image_interp, + extrapolate=extrapolate, + border=border, + res=res, + size=size, + cmap=cmap, + vlim=vlim, + cnorm=cnorm, + colorbar=colorbar, + cbar_fmt=cbar_fmt, + units=units, + axes=axes, + name_format=name_format, + nrows=nrows, + ncols=ncols, + show=show, + ) + + +def _ajd_pham(X, eps=1e-6, max_iter=15): + """Approximate joint diagonalization based on Pham's algorithm. + + This is a direct implementation of the PHAM's AJD algorithm [1]. + + Parameters + ---------- + X : ndarray, shape (n_epochs, n_channels, n_channels) + A set of covariance matrices to diagonalize. + eps : float, default 1e-6 + The tolerance for stopping criterion. + max_iter : int, default 1000 + The maximum number of iteration to reach convergence. + + Returns + ------- + V : ndarray, shape (n_channels, n_channels) + The diagonalizer. + D : ndarray, shape (n_epochs, n_channels, n_channels) + The set of quasi diagonal matrices. + + References + ---------- + .. [1] Pham, Dinh Tuan. "Joint approximate diagonalization of positive + definite Hermitian matrices." SIAM Journal on Matrix Analysis and + Applications 22, no. 4 (2001): 1136-1152. + + """ + # Adapted from http://github.com/alexandrebarachant/pyRiemann + n_epochs = X.shape[0] + + # Reshape input matrix + A = np.concatenate(X, axis=0).T + + # Init variables + n_times, n_m = A.shape + V = np.eye(n_times) + epsilon = n_times * (n_times - 1) * eps + + for it in range(max_iter): + decr = 0 + for ii in range(1, n_times): + for jj in range(ii): + Ii = np.arange(ii, n_m, n_times) + Ij = np.arange(jj, n_m, n_times) + + c1 = A[ii, Ii] + c2 = A[jj, Ij] + + g12 = np.mean(A[ii, Ij] / c1) + g21 = np.mean(A[ii, Ij] / c2) + + omega21 = np.mean(c1 / c2) + omega12 = np.mean(c2 / c1) + omega = np.sqrt(omega12 * omega21) + + tmp = np.sqrt(omega21 / omega12) + tmp1 = (tmp * g12 + g21) / (omega + 1) + tmp2 = (tmp * g12 - g21) / max(omega - 1, 1e-9) + + h12 = tmp1 + tmp2 + h21 = np.conj((tmp1 - tmp2) / tmp) + + decr += n_epochs * (g12 * np.conj(h12) + g21 * h21) / 2.0 + + tmp = 1 + 1.0j * 0.5 * np.imag(h12 * h21) + tmp = np.real(tmp + np.sqrt(tmp**2 - h12 * h21)) + tau = np.array([[1, -h12 / tmp], [-h21 / tmp, 1]]) + + A[[ii, jj], :] = np.dot(tau, A[[ii, jj], :]) + tmp = np.c_[A[:, Ii], A[:, Ij]] + tmp = np.reshape(tmp, (n_times * n_epochs, 2), order="F") + tmp = np.dot(tmp, tau.T) + + tmp = np.reshape(tmp, (n_times, n_epochs * 2), order="F") + A[:, Ii] = tmp[:, :n_epochs] + A[:, Ij] = tmp[:, n_epochs:] + V[[ii, jj], :] = np.dot(tau, V[[ii, jj], :]) + if decr < epsilon: + break + D = np.reshape(A, (n_times, -1, n_times)).transpose(1, 0, 2) + return V, D + + +@fill_doc +class SPoC(CSP): + """Implementation of the SPoC spatial filtering. + + Source Power Comodulation (SPoC) :footcite:`DahneEtAl2014` allows to + extract spatial filters and + patterns by using a target (continuous) variable in the decomposition + process in order to give preference to components whose power correlates + with the target variable. + + SPoC can be seen as an extension of the CSP driven by a continuous + variable rather than a discrete variable. Typical applications include + extraction of motor patterns using EMG power or audio patterns using sound + envelope. + + Parameters + ---------- + n_components : int + The number of components to decompose M/EEG signals. + reg : float | str | None (default None) + If not None (same as ``'empirical'``, default), allow + regularization for covariance estimation. + If float, shrinkage is used (0 <= shrinkage <= 1). + For str options, ``reg`` will be passed to ``method`` to + :func:`mne.compute_covariance`. + log : None | bool (default None) + If transform_into == 'average_power' and log is None or True, then + applies a log transform to standardize the features, else the features + are z-scored. If transform_into == 'csp_space', then log must be None. + transform_into : {'average_power', 'csp_space'} + If 'average_power' then self.transform will return the average power of + each spatial filter. If 'csp_space' self.transform will return the data + in CSP space. Defaults to 'average_power'. + cov_method_params : dict | None + Parameters to pass to :func:`mne.compute_covariance`. + + .. versionadded:: 0.16 + restr_type : "restricting" | "whitening" | None + Restricting transformation for covariance matrices before performing + generalized eigendecomposition. + If "restricting" only restriction to the principal subspace of signal_cov + will be performed. + If "whitening", covariance matrices will be additionally rescaled according + to the whitening for the signal_cov. + If None, no restriction will be applied. Defaults to None. + + .. versionadded:: 1.11 + info : mne.Info | None + The mne.Info object with information about the sensors and methods of + measurement used for covariance estimation and generalized + eigendecomposition. + If None, one channel type and no projections will be assumed and if + rank is dict, it will be sum of ranks per channel type. + Defaults to None. + + .. versionadded:: 1.11 + %(rank_none)s + + .. versionadded:: 0.17 + + Attributes + ---------- + filters_ : ndarray, shape (n_channels, n_channels) + If fit, the SPoC spatial filters, else None. + patterns_ : ndarray, shape (n_channels, n_channels) + If fit, the SPoC spatial patterns, else None. + mean_ : ndarray, shape (n_components,) + If fit, the mean squared power for each component. + std_ : ndarray, shape (n_components,) + If fit, the std squared power for each component. + + See Also + -------- + mne.preprocessing.Xdawn, CSP + + References + ---------- + .. footbibliography:: + """ + + def __init__( + self, + n_components=4, + reg=None, + log=None, + transform_into="average_power", + cov_method_params=None, + *, + restr_type=None, + info=None, + rank=None, + ): + """Init of SPoC.""" + super().__init__( + n_components=n_components, + reg=reg, + log=log, + cov_est="epoch", + norm_trace=False, + transform_into=transform_into, + restr_type=restr_type, + info=info, + rank=rank, + cov_method_params=cov_method_params, + ) + + cov_callable = partial( + _spoc_estimate, + reg=reg, + cov_method_params=cov_method_params, + info=info, + rank=rank, + ) + super(CSP, self).__init__( + n_components=n_components, + cov_callable=cov_callable, + mod_ged_callable=_spoc_mod, + restr_type=restr_type, + ) + + # Covariance estimation have to be done on the single epoch level, + # unlike CSP where covariance estimation can also be achieved through + # concatenation of all epochs from the same class. + delattr(self, "cov_est") + delattr(self, "norm_trace") + + def __sklearn_tags__(self): + """Tag the transformer.""" + tags = super().__sklearn_tags__() + tags.target_tags.multi_output = False + return tags + + def fit(self, X, y): + """Estimate the SPoC decomposition on epochs. + + Parameters + ---------- + X : ndarray, shape (n_epochs, n_channels, n_times) + The data on which to estimate the SPoC. + y : array, shape (n_epochs,) + The class for each epoch. + + Returns + ------- + self : instance of SPoC + Returns the modified instance. + """ + X, y = self._check_data(X, y=y, fit=True, return_y=True) + self._validate_params(y=y) + + super(CSP, self).fit(X, y) + + pick_filters = self.filters_[: self.n_components] + X = np.asarray([np.dot(pick_filters, epoch) for epoch in X]) + + # compute features (mean band power) + X = (X**2).mean(axis=-1) + + # To standardize features + self.mean_ = X.mean(axis=0) + self.std_ = X.std(axis=0) + + return self + + def transform(self, X): + """Estimate epochs sources given the SPoC filters. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_times) + The data. + + Returns + ------- + X : ndarray + If self.transform_into == 'average_power' then returns the power of + CSP features averaged over time and shape (n_epochs, n_components) + If self.transform_into == 'csp_space' then returns the data in CSP + space and shape is (n_epochs, n_components, n_times). + """ + return super().transform(X) + + def fit_transform(self, X, y=None, **fit_params): + """Fit SPoC to data, then transform it. + + Fits transformer to ``X`` and ``y`` with optional parameters ``fit_params``, and + returns a transformed version of ``X``. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_times) + The data on which to estimate the SPoC. + y : array, shape (n_epochs,) + The class for each epoch. + **fit_params : dict + Additional fitting parameters passed to the :meth:`mne.decoding.CSP.fit` + method. Not used for this class. + + Returns + ------- + X : array, shape (n_epochs, n_components[, n_times]) + If ``self.transform_into == 'average_power'`` then returns the power of CSP + features averaged over time and shape is ``(n_epochs, n_components)``. If + ``self.transform_into == 'csp_space'`` then returns the data in CSP space + and shape is ``(n_epochs, n_components, n_times)``. + """ + # use parent TransformerMixin method but with custom docstring + return super().fit_transform(X, y=y, **fit_params) diff --git a/mne-python/source/mne/decoding/ems.py b/mne-python/source/mne/decoding/ems.py new file mode 100644 index 0000000000000000000000000000000000000000..5c7557798ef5d9282f331fd0cbd0b95e137b5adc --- /dev/null +++ b/mne-python/source/mne/decoding/ems.py @@ -0,0 +1,234 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from collections import Counter + +import numpy as np +from sklearn.base import BaseEstimator + +from .._fiff.pick import _picks_to_idx, pick_info, pick_types +from ..parallel import parallel_func +from ..utils import logger, verbose +from .base import _set_cv +from .transformer import MNETransformerMixin + + +class EMS(MNETransformerMixin, BaseEstimator): + """Transformer to compute event-matched spatial filters. + + This version of EMS :footcite:`SchurgerEtAl2013` operates on the entire + time course. No time + window needs to be specified. The result is a spatial filter at each + time point and a corresponding time course. Intuitively, the result + gives the similarity between the filter at each time point and the + data vector (sensors) at that time point. + + .. note:: EMS only works for binary classification. + + Attributes + ---------- + filters_ : ndarray, shape (n_channels, n_times) + The set of spatial filters. + classes_ : ndarray, shape (n_classes,) + The target classes. + + References + ---------- + .. footbibliography:: + """ + + def __sklearn_tags__(self): + """Return sklearn tags.""" + from sklearn.utils import ClassifierTags + + tags = super().__sklearn_tags__() + if tags.classifier_tags is None: + tags.classifier_tags = ClassifierTags() + tags.classifier_tags.multi_class = False + return tags + + def __repr__(self): # noqa: D105 + if hasattr(self, "filters_"): + return ( + f"" + ) + else: + return "" + + def fit(self, X, y): + """Fit the spatial filters. + + .. note : EMS is fitted on data normalized by channel type before the + fitting of the spatial filters. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_times) + The training data. + y : array of int, shape (n_epochs) + The target classes. + + Returns + ------- + self : instance of EMS + Returns self. + """ + X, y = self._check_data(X, y=y, fit=True, return_y=True) + classes, y = np.unique(y, return_inverse=True) + if len(classes) > 2: + raise ValueError("EMS only works for binary classification.") + self.classes_ = classes + filters = X[y == 0].mean(0) - X[y == 1].mean(0) + filters /= np.linalg.norm(filters, axis=0)[None, :] + self.filters_ = filters + return self + + def transform(self, X): + """Transform the data by the spatial filters. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_times) + The input data. + + Returns + ------- + X : array, shape (n_epochs, n_times) + The input data transformed by the spatial filters. + """ + X = self._check_data(X) + Xt = np.sum(X * self.filters_, axis=1) + return Xt + + +@verbose +def compute_ems( + epochs, conditions=None, picks=None, n_jobs=None, cv=None, *, verbose=None +): + """Compute event-matched spatial filter on epochs. + + This version of EMS :footcite:`SchurgerEtAl2013` operates on the entire + time course. No time + window needs to be specified. The result is a spatial filter at each + time point and a corresponding time course. Intuitively, the result + gives the similarity between the filter at each time point and the + data vector (sensors) at that time point. + + .. note : EMS only works for binary classification. + + .. note : The present function applies a leave-one-out cross-validation, + following Schurger et al's paper. However, we recommend using + a stratified k-fold cross-validation. Indeed, leave-one-out tends + to overfit and cannot be used to estimate the variance of the + prediction within a given fold. + + .. note : Because of the leave-one-out, this function needs an equal + number of epochs in each of the two conditions. + + Parameters + ---------- + epochs : instance of mne.Epochs + The epochs. + conditions : list of str | None, default None + If a list of strings, strings must match the epochs.event_id's key as + well as the number of conditions supported by the objective_function. + If None keys in epochs.event_id are used. + %(picks_good_data)s + %(n_jobs)s + cv : cross-validation object | str | None, default LeaveOneOut + The cross-validation scheme. + %(verbose)s + + Returns + ------- + surrogate_trials : ndarray, shape (n_trials // 2, n_times) + The trial surrogates. + mean_spatial_filter : ndarray, shape (n_channels, n_times) + The set of spatial filters. + conditions : ndarray, shape (n_classes,) + The conditions used. Values correspond to original event ids. + + References + ---------- + .. footbibliography:: + """ + logger.info("...computing surrogate time series. This can take some time") + + # Default to leave-one-out cv + cv = "LeaveOneOut" if cv is None else cv + picks = _picks_to_idx(epochs.info, picks) + + if not len(set(Counter(epochs.events[:, 2]).values())) == 1: + raise ValueError( + "The same number of epochs is required by " + "this function. Please consider " + "`epochs.equalize_event_counts`" + ) + + if conditions is None: + conditions = epochs.event_id.keys() + epochs = epochs.copy() + else: + epochs = epochs[conditions] + + epochs.drop_bad() + + if len(conditions) != 2: + raise ValueError( + "Currently this function expects exactly 2 " + f"conditions but you gave me {len(conditions)}" + ) + + ev = epochs.events[:, 2] + # Special care to avoid path dependent mappings and orders + conditions = list(sorted(conditions)) + cond_idx = [np.where(ev == epochs.event_id[k])[0] for k in conditions] + + info = pick_info(epochs.info, picks) + data = epochs.get_data(picks=picks) + + # Scale (z-score) the data by channel type + # XXX the z-scoring is applied outside the CV, which is not standard. + for ch_type in ["mag", "grad", "eeg"]: + if ch_type in epochs: + # FIXME should be applied to all sort of data channels + if ch_type == "eeg": + this_picks = pick_types(info, meg=False, eeg=True) + else: + this_picks = pick_types(info, meg=ch_type, eeg=False) + data[:, this_picks] /= np.std(data[:, this_picks]) + + # Setup cross-validation. Need to use _set_cv to deal with sklearn + # changes in cv object handling. + y = epochs.events[:, 2] + _, cv_splits = _set_cv(cv, "classifier", X=y, y=y) + + parallel, p_func, n_jobs = parallel_func(_run_ems, n_jobs=n_jobs) + # FIXME this parallelization should be removed. + # 1) it's numpy computation so it's already efficient, + # 2) it duplicates the data in RAM, + # 3) the computation is already super fast. + out = parallel( + p_func(_ems_diff, data, cond_idx, train, test) for train, test in cv_splits + ) + + surrogate_trials, spatial_filter = zip(*out) + surrogate_trials = np.array(surrogate_trials) + spatial_filter = np.mean(spatial_filter, axis=0) + + return surrogate_trials, spatial_filter, epochs.events[:, 2] + + +def _ems_diff(data0, data1): + """Compute the default diff objective function.""" + return np.mean(data0, axis=0) - np.mean(data1, axis=0) + + +def _run_ems(objective_function, data, cond_idx, train, test): + """Run EMS.""" + d = objective_function(*(data[np.intersect1d(c, train)] for c in cond_idx)) + d /= np.sqrt(np.sum(d**2, axis=0))[None, :] + # compute surrogates + return np.sum(data[test[0]] * d, axis=0), d diff --git a/mne-python/source/mne/decoding/receptive_field.py b/mne-python/source/mne/decoding/receptive_field.py new file mode 100644 index 0000000000000000000000000000000000000000..7b8fb63dfd30565b366c58175dc33c29774fe776 --- /dev/null +++ b/mne-python/source/mne/decoding/receptive_field.py @@ -0,0 +1,570 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numbers + +import numpy as np +from scipy.stats import pearsonr +from sklearn.base import ( + BaseEstimator, + MetaEstimatorMixin, + clone, + is_regressor, +) +from sklearn.exceptions import NotFittedError +from sklearn.metrics import r2_score + +from ..fixes import _reshape_view +from ..utils import _validate_type, fill_doc, pinv +from ._fixes import _check_n_features_3d, validate_data +from .base import _check_estimator, get_coef +from .time_delaying_ridge import TimeDelayingRidge + + +@fill_doc +class ReceptiveField(MetaEstimatorMixin, BaseEstimator): + """Fit a receptive field model. + + This allows you to fit an encoding model (stimulus to brain) or a decoding + model (brain to stimulus) using time-lagged input features (for example, a + spectro- or spatio-temporal receptive field, or STRF) + :footcite:`TheunissenEtAl2001,WillmoreSmyth2003,CrosseEtAl2016,HoldgrafEtAl2016`. + + Parameters + ---------- + tmin : float + The starting lag, in seconds (or samples if ``sfreq`` == 1). + tmax : float + The ending lag, in seconds (or samples if ``sfreq`` == 1). + Must be >= tmin. + sfreq : float + The sampling frequency used to convert times into samples. + feature_names : array, shape (n_features,) | None + Names for input features to the model. If None, feature names will + be auto-generated from the shape of input data after running `fit`. + estimator : instance of sklearn.base.BaseEstimator | float | None + The model used in fitting inputs and outputs. This can be any + scikit-learn-style model that contains a fit and predict method. If a + float is passed, it will be interpreted as the ``alpha`` parameter + to be passed to a Ridge regression model. If `None`, then a Ridge + regression model with an alpha of 0 will be used. + fit_intercept : bool | None + If True (default), the sample mean is removed before fitting. + If ``estimator`` is a :class:`sklearn.base.BaseEstimator`, + this must be None or match ``estimator.fit_intercept``. + scoring : ['r2', 'corrcoef'] + Defines how predictions will be scored. Currently must be one of + 'r2' (coefficient of determination) or 'corrcoef' (the correlation + coefficient). + patterns : bool + If True, inverse coefficients will be computed upon fitting using the + covariance matrix of the inputs, and the cross-covariance of the + inputs/outputs, according to :footcite:`HaufeEtAl2014`. Defaults to + False. + n_jobs : int | str + Number of jobs to run in parallel. Can be 'cuda' if CuPy + is installed properly and ``estimator is None``. + + .. versionadded:: 0.18 + edge_correction : bool + If True (default), correct the autocorrelation coefficients for + non-zero delays for the fact that fewer samples are available. + Disabling this speeds up performance at the cost of accuracy + depending on the relationship between epoch length and model + duration. Only used if ``estimator`` is float or None. + + .. versionadded:: 0.18 + + Attributes + ---------- + coef_ : array, shape ([n_outputs, ]n_features, n_delays) + The coefficients from the model fit, reshaped for easy visualization. + During :meth:`mne.decoding.ReceptiveField.fit`, if ``y`` has one + dimension (time), the ``n_outputs`` dimension here is omitted. + patterns_ : array, shape ([n_outputs, ]n_features, n_delays) + If fit, the inverted coefficients from the model. + delays_ : array, shape (n_delays,), dtype int + The delays used to fit the model, in indices. To return the delays + in seconds, use ``self.delays_ / self.sfreq`` + valid_samples_ : slice + The rows to keep during model fitting after removing rows with + missing values due to time delaying. This can be used to get an + output equivalent to using :func:`numpy.convolve` or + :func:`numpy.correlate` with ``mode='valid'``. + + See Also + -------- + mne.decoding.TimeDelayingRidge + + Notes + ----- + For a causal system, the encoding model will have significant + non-zero values only at positive lags. In other words, lags point + backward in time relative to the input, so positive lags correspond + to previous input time samples, while negative lags correspond to + future input time samples. + + References + ---------- + .. footbibliography:: + """ # noqa E501 + + def __init__( + self, + tmin, + tmax, + sfreq, + feature_names=None, + estimator=None, + fit_intercept=None, + scoring="r2", + patterns=False, + n_jobs=None, + edge_correction=True, + ): + self.tmin = tmin + self.tmax = tmax + self.sfreq = sfreq + self.feature_names = feature_names + self.estimator = estimator + self.fit_intercept = fit_intercept + self.scoring = scoring + self.patterns = patterns + self.n_jobs = n_jobs + self.edge_correction = edge_correction + + def __repr__(self): # noqa: D105 + s = f"tmin, tmax : ({self.tmin:.3f}, {self.tmax:.3f}), " + estimator = self.estimator + if not isinstance(estimator, str): + estimator = type(self.estimator) + s += f"estimator : {estimator}, " + if hasattr(self, "coef_"): + if self.feature_names is not None: + feats = self.feature_names + if len(feats) == 1: + s += f"feature: {feats[0]}, " + else: + s += f"features : [{feats[0]}, ..., {feats[-1]}], " + s += "fit: True" + else: + s += "fit: False" + if hasattr(self, "scores_"): + s += f"scored ({self.scoring})" + return f"" + + def __sklearn_tags__(self): + """...""" + from sklearn.utils import RegressorTags + + tags = super().__sklearn_tags__() + tags.estimator_type = "regressor" + tags.regressor_tags = RegressorTags() + tags.input_tags.three_d_array = True + tags.target_tags.one_d_labels = True + tags.target_tags.multi_output = True + tags.target_tags.required = True + return tags + + def _delay_and_reshape(self, X, y=None): + """Delay and reshape the variables.""" + if not isinstance(self.estimator_, TimeDelayingRidge): + # X is now shape (n_times, n_epochs, n_feats, n_delays) + X = _delay_time_series( + X, + self.tmin, + self.tmax, + self.sfreq_, + fill_mean=self.fit_intercept_, + ) + X = _reshape_for_est(X) + # Concat times + epochs + if y is not None: + y = y.reshape(-1, y.shape[-1], order="F") + return X, y + + def _check_data(self, X, y=None, reset=False): + if reset: + X, y = validate_data( + self, + X=X, + y=y, + reset=reset, + validate_separately=( # to take care of 3D y + dict(allow_nd=True, ensure_2d=False), + dict(allow_nd=True, ensure_2d=False), + ), + ) + else: + X = validate_data(self, X=X, allow_nd=True, ensure_2d=False, reset=reset) + _check_n_features_3d(self, X, reset) + return X, y + + def _validate_params(self, X): + if self.scoring not in _SCORERS.keys(): + raise ValueError( + f"scoring must be one of {sorted(_SCORERS.keys())}, got {self.scoring}" + ) + self.sfreq_ = float(self.sfreq) + if self.tmin > self.tmax: + raise ValueError(f"tmin ({self.tmin}) must be at most tmax ({self.tmax})") + + def fit(self, X, y): + """Fit a receptive field model. + + Parameters + ---------- + X : array, shape (n_times[, n_epochs], n_features) + The input features for the model. + y : array, shape (n_times[, n_epochs][, n_outputs]) + The output features for the model. + + Returns + ------- + self : instance + The instance so you can chain operations. + """ + X, y = self._check_data(X, y, reset=True) + self._validate_params(X) + X, y, _, self._y_dim = self._check_dimensions(X, y) + + # Initialize delays + self.delays_ = _times_to_delays(self.tmin, self.tmax, self.sfreq_) + + # Define the slice that we should use in the middle + self.valid_samples_ = _delays_to_slice(self.delays_) + + if self.estimator is None or isinstance(self.estimator, numbers.Real): + alpha = self.estimator if self.estimator is not None else 0.0 + if self.fit_intercept is None: + self.fit_intercept_ = True + else: + self.fit_intercept_ = self.fit_intercept + estimator = TimeDelayingRidge( + self.tmin, + self.tmax, + self.sfreq_, + alpha=alpha, + fit_intercept=self.fit_intercept_, + n_jobs=self.n_jobs, + edge_correction=self.edge_correction, + ) + elif is_regressor(self.estimator): + estimator = clone(self.estimator) + if ( + self.fit_intercept is not None + and estimator.fit_intercept != self.fit_intercept + ): + raise ValueError( + f"Estimator fit_intercept ({estimator.fit_intercept}) != " + f"initialization fit_intercept ({self.fit_intercept}), initialize " + "ReceptiveField with the same fit_intercept value or use " + "fit_intercept=None" + ) + self.fit_intercept_ = estimator.fit_intercept + else: + raise ValueError( + "`estimator` must be a float or an instance of `BaseEstimator`, got " + f"type {self.estimator}." + ) + self.estimator_ = estimator + del estimator + _check_estimator(self.estimator_) + + # Create input features + n_times, n_epochs, n_feats = X.shape + n_outputs = y.shape[-1] + n_delays = len(self.delays_) + + # Update feature names if we have none + if (self.feature_names is not None) and (len(self.feature_names) != n_feats): + raise ValueError( + f"n_features in X does not match feature names ({n_feats} != " + f"{len(self.feature_names)})" + ) + + # Create input features + X, y = self._delay_and_reshape(X, y) + + self.estimator_.fit(X, y) + coef = get_coef(self.estimator_, "coef_") # (n_targets, n_features) + shape = [n_feats, n_delays] + if self._y_dim > 1: + shape.insert(0, -1) + self.coef_ = coef.reshape(shape) + + # Inverse-transform model weights + if self.patterns: + n_total_samples = n_times * n_epochs + if n_total_samples < 2: + raise ValueError( + "Cannot compute patterns with only one sample; " + f"got n_samples = {n_total_samples}." + ) + if isinstance(self.estimator_, TimeDelayingRidge): + cov_ = self.estimator_.cov_ / float(n_times * n_epochs - 1) + y = y.reshape(-1, y.shape[-1], order="F") + else: + X = X - X.mean(0, keepdims=True) + cov_ = np.cov(X.T) + del X + + # Inverse output covariance + if y.ndim == 2 and y.shape[1] != 1: + y = y - y.mean(0, keepdims=True) + inv_Y = pinv(np.cov(y.T)) + else: + inv_Y = 1.0 / float(n_times * n_epochs - 1) + del y + + # Inverse coef according to Haufe's method + # patterns has shape (n_feats * n_delays, n_outputs) + coef = np.reshape(self.coef_, (n_feats * n_delays, n_outputs)) + patterns = cov_.dot(coef.dot(inv_Y)) + self.patterns_ = patterns.reshape(shape) + + return self + + def predict(self, X): + """Generate predictions with a receptive field. + + Parameters + ---------- + X : array, shape (n_times[, n_epochs], n_channels) + The input features for the model. + + Returns + ------- + y_pred : array, shape (n_times[, n_epochs][, n_outputs]) + The output predictions. "Note that valid samples (those + unaffected by edge artifacts during the time delaying step) can + be obtained using ``y_pred[rf.valid_samples_]``. + """ + if not hasattr(self, "delays_"): + raise NotFittedError("Estimator has not been fit yet.") + + X, _ = self._check_data(X) + X, _, X_dim = self._check_dimensions(X, None, predict=True)[:3] + + del _ + # convert to sklearn and back + pred_shape = X.shape[:-1] + if self._y_dim > 1: + pred_shape = pred_shape + (self.coef_.shape[0],) + X, _ = self._delay_and_reshape(X) + y_pred = self.estimator_.predict(X) + y_pred = y_pred.reshape(pred_shape, order="F") + shape = list(y_pred.shape) + if X_dim <= 2: + shape.pop(1) # epochs + extra = 0 + else: + extra = 1 + shape = shape[: self._y_dim + extra] + y_pred = _reshape_view(y_pred, shape) + return y_pred + + def score(self, X, y): + """Score predictions generated with a receptive field. + + This calls ``self.predict``, then masks the output of this + and ``y` with ``self.valid_samples_``. Finally, it passes + this to a :mod:`sklearn.metrics` scorer. + + Parameters + ---------- + X : array, shape (n_times[, n_epochs], n_channels) + The input features for the model. + y : array, shape (n_times[, n_epochs][, n_outputs]) + Used for scikit-learn compatibility. + + Returns + ------- + scores : list of float, shape (n_outputs,) + The scores estimated by the model for each output (e.g. mean + R2 of ``predict(X)``). + """ + # Create our scoring object + scorer_ = _SCORERS[self.scoring] + + # Generate predictions, then reshape so we can mask time + X, y = self._check_dimensions(X, y, predict=True)[:2] + n_times, n_epochs, n_outputs = y.shape + y_pred = self.predict(X) + y_pred = y_pred[self.valid_samples_] + y = y[self.valid_samples_] + + # Re-vectorize and call scorer + y = y.reshape([-1, n_outputs], order="F") + y_pred = y_pred.reshape([-1, n_outputs], order="F") + assert y.shape == y_pred.shape + scores = scorer_(y, y_pred, multioutput="raw_values") + return scores + + def _check_dimensions(self, X, y, predict=False): + _validate_type(X, "array-like", "X") + _validate_type(y, ("array-like", None), "y") + X_dim = X.ndim + y_dim = y.ndim if y is not None else 0 + if X_dim == 2: + # Ensure we have a 3D input by adding singleton epochs dimension + X = X[:, np.newaxis, :] + if y is not None: + if y_dim == 1: + y = y[:, np.newaxis, np.newaxis] # epochs, outputs + elif y_dim == 2: + y = y[:, np.newaxis, :] # epochs + else: + raise ValueError( + "y must be shape (n_times[, n_epochs][,n_outputs], got " + f"{y.shape}" + ) + elif X.ndim == 3: + if y is not None: + if y.ndim == 2: + y = y[:, :, np.newaxis] # Add an outputs dim + elif y.ndim != 3: + raise ValueError( + "If X has 3 dimensions, y must have 2 or 3 dimensions" + ) + else: + raise ValueError( + "X must be shape (n_times[, n_epochs], n_features), " + f"got {X.shape}. Reshape your data to 2D or 3D " + "(e.g., array.reshape(-1, 1) for a single feature, " + "or array.reshape(1, -1) for a single sample)." + ) + if y is not None: + if X.shape[0] != y.shape[0]: + raise ValueError( + f"X and y do not have the same n_times\n{X.shape[0]} != " + f"{y.shape[0]}" + ) + if X.shape[1] != y.shape[1]: + raise ValueError( + f"X and y do not have the same n_epochs\n{X.shape[1]} != " + f"{y.shape[1]}" + ) + if predict and y.shape[-1] not in (len(self.estimator_.coef_), 1): + raise ValueError( + "Number of outputs does not match estimator coefficients dimensions" + ) + return X, y, X_dim, y_dim + + +def _delay_time_series(X, tmin, tmax, sfreq, fill_mean=False): + """Return a time-lagged input time series. + + Parameters + ---------- + X : array, shape (n_times[, n_epochs], n_features) + The time series to delay. Must be 2D or 3D. + tmin : int | float + The starting lag. + tmax : int | float + The ending lag. + Must be >= tmin. + sfreq : int | float + The sampling frequency of the series. Defaults to 1.0. + fill_mean : bool + If True, the fill value will be the mean along the time dimension + of the feature, and each cropped and delayed segment of data + will be shifted to have the same mean value (ensuring that mean + subtraction works properly). If False, the fill value will be zero. + + Returns + ------- + delayed : array, shape(n_times[, n_epochs][, n_features], n_delays) + The delayed data. It has the same shape as X, with an extra dimension + appended to the end. + + Examples + -------- + >>> tmin, tmax = -0.1, 0.2 + >>> sfreq = 10. + >>> x = np.arange(1, 6) + >>> x_del = _delay_time_series(x, tmin, tmax, sfreq) + >>> print(x_del) # doctest:+SKIP + [[2. 1. 0. 0.] + [3. 2. 1. 0.] + [4. 3. 2. 1.] + [5. 4. 3. 2.] + [0. 5. 4. 3.]] + """ + _check_delayer_params(tmin, tmax, sfreq) + delays = _times_to_delays(tmin, tmax, sfreq) + # Iterate through indices and append + delayed = np.zeros(X.shape + (len(delays),)) + if fill_mean: + mean_value = X.mean(axis=0) + if X.ndim == 3: + mean_value = np.mean(mean_value, axis=0) + delayed[:] = mean_value[:, np.newaxis] + for ii, ix_delay in enumerate(delays): + # Create zeros to populate w/ delays + if ix_delay < 0: + out = delayed[:ix_delay, ..., ii] + use_X = X[-ix_delay:] + elif ix_delay > 0: + out = delayed[ix_delay:, ..., ii] + use_X = X[:-ix_delay] + else: # == 0 + out = delayed[..., ii] + use_X = X + out[:] = use_X + if fill_mean: + out[:] += mean_value - use_X.mean(axis=0) + return delayed + + +def _times_to_delays(tmin, tmax, sfreq): + """Convert a tmin/tmax in seconds to delays.""" + # Convert seconds to samples + delays = np.arange(int(np.round(tmin * sfreq)), int(np.round(tmax * sfreq) + 1)) + return delays + + +def _delays_to_slice(delays): + """Find the slice to be taken in order to remove missing values.""" + # Negative values == cut off rows at the end + min_delay = None if delays[-1] <= 0 else delays[-1] + # Positive values == cut off rows at the end + max_delay = None if delays[0] >= 0 else delays[0] + return slice(min_delay, max_delay) + + +def _check_delayer_params(tmin, tmax, sfreq): + """Check delayer input parameters. For future custom delay support.""" + _validate_type(sfreq, "numeric", "`sfreq`") + + for tlim in (tmin, tmax): + _validate_type(tlim, "numeric", "tmin/tmax") + if not tmin <= tmax: + raise ValueError("tmin must be <= tmax") + + +def _reshape_for_est(X_del): + """Convert X_del to a sklearn-compatible shape.""" + n_times, n_epochs, n_feats, n_delays = X_del.shape + X_del = X_del.reshape(n_times, n_epochs, -1) # concatenate feats + X_del = X_del.reshape(n_times * n_epochs, -1, order="F") + return X_del + + +# Create a correlation scikit-learn-style scorer +def _corr_score(y_true, y, multioutput=None): + assert multioutput == "raw_values" + for this_y in (y_true, y): + if this_y.ndim != 2: + raise ValueError( + f"inputs must be shape (samples, outputs), got {this_y.shape}" + ) + return np.array([pearsonr(y_true[:, ii], y[:, ii])[0] for ii in range(y.shape[-1])]) + + +def _r2_score(y_true, y, multioutput=None): + return r2_score(y_true, y, multioutput=multioutput) + + +_SCORERS = {"r2": _r2_score, "corrcoef": _corr_score} diff --git a/mne-python/source/mne/decoding/search_light.py b/mne-python/source/mne/decoding/search_light.py new file mode 100644 index 0000000000000000000000000000000000000000..81699ecd5baf2b49b43ca38fbd9ceeb9f65b681e --- /dev/null +++ b/mne-python/source/mne/decoding/search_light.py @@ -0,0 +1,796 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import logging + +import numpy as np +from sklearn.base import BaseEstimator, MetaEstimatorMixin, clone +from sklearn.metrics import check_scoring +from sklearn.preprocessing import LabelEncoder +from sklearn.utils.validation import check_is_fitted + +from ..parallel import parallel_func +from ..utils import ( + ProgressBar, + _parse_verbose, + _verbose_safe_false, + array_split_idx, + fill_doc, +) +from .base import _check_estimator +from .transformer import MNETransformerMixin + + +@fill_doc +class SlidingEstimator(MetaEstimatorMixin, MNETransformerMixin, BaseEstimator): + """Search Light. + + Fit, predict and score a series of models to each subset of the dataset + along the last dimension. Each entry in the last dimension is referred + to as a task. + + Parameters + ---------- + %(base_estimator)s + %(scoring)s + %(n_jobs)s + %(position)s + %(allow_2d)s + %(verbose)s + + Attributes + ---------- + estimators_ : array-like, shape (n_tasks,) + List of fitted scikit-learn estimators (one per task). + """ + + def __init__( + self, + base_estimator, + scoring=None, + n_jobs=None, + *, + position=0, + allow_2d=False, + verbose=None, + ): + self.base_estimator = base_estimator + self.n_jobs = n_jobs + self.scoring = scoring + self.position = position + self.allow_2d = allow_2d + self.verbose = verbose + + @property + def _estimator_type(self): + return getattr(self.base_estimator, "_estimator_type", None) + + def __sklearn_tags__(self): + """Get sklearn tags.""" + from sklearn.utils import get_tags + + tags = super().__sklearn_tags__() + sub_tags = get_tags(self.base_estimator) + tags.estimator_type = sub_tags.estimator_type + for kind in ("classifier", "regressor", "transformer"): + if tags.estimator_type == kind: + attr = f"{kind}_tags" + setattr(tags, attr, getattr(sub_tags, attr)) + break + return tags + + def __repr__(self): # noqa: D105 + repr_str = "<" + super().__repr__() + if hasattr(self, "estimators_"): + repr_str = repr_str[:-1] + repr_str += f", fitted with {len(self.estimators_)} estimators" + return repr_str + ">" + + def fit(self, X, y, **fit_params): + """Fit a series of independent estimators to the dataset. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_tasks) + The training input samples. For each data slice, a clone estimator + is fitted independently. The feature dimension can be + multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_tasks). + y : array, shape (n_samples,) | (n_samples, n_targets) + The target values. + **fit_params : dict of string -> object + Parameters to pass to the fit method of the estimator. + + Returns + ------- + self : object + Return self. + """ + _check_estimator(self.base_estimator) + X, _ = self._check_Xy(X, y, fit=True) + parallel, p_func, n_jobs = parallel_func( + _sl_fit, + self.n_jobs, + max_jobs=X.shape[-1], + verbose=_verbose_safe_false(), + ) + self.estimators_ = list() + self.fit_params_ = fit_params + + # For fitting, the parallelization is across estimators. + context = _create_progressbar_context(self, X, "Fitting") + with context as pb: + estimators = parallel( + p_func(self.base_estimator, split, y, pb.subset(pb_idx), **fit_params) + for pb_idx, split in array_split_idx(X, n_jobs, axis=-1) + ) + + # Each parallel job can have a different number of training estimators + # We can't directly concatenate them because of sklearn's Bagging API + # (see scikit-learn #9720) + self.estimators_ = np.empty(X.shape[-1], dtype=object) + idx = 0 + for job_estimators in estimators: + for est in job_estimators: + self.estimators_[idx] = est + idx += 1 + return self + + def fit_transform(self, X, y, **fit_params): + """Fit and transform a series of independent estimators to the dataset. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_tasks) + The training input samples. For each task, a clone estimator + is fitted independently. The feature dimension can be + multidimensional, e.g.:: + + X.shape = (n_samples, n_features_1, n_features_2, n_estimators) + y : array, shape (n_samples,) | (n_samples, n_targets) + The target values. + **fit_params : dict of string -> object + Parameters to pass to the fit method of the estimator. + + Returns + ------- + y_pred : array, shape (n_samples, n_tasks) | (n_samples, n_tasks, n_targets) + The predicted values for each estimator. + """ # noqa: E501 + return self.fit(X, y, **fit_params).transform(X) + + def _transform(self, X, method): + """Aux. function to make parallel predictions/transformation.""" + X, is_nd = self._check_Xy(X) + orig_method = method + check_is_fitted(self) + method = _check_method(self.base_estimator, method) + if X.shape[-1] != len(self.estimators_): + raise ValueError("The number of estimators does not match X.shape[-1]") + # For predictions/transforms the parallelization is across the data and + # not across the estimators to avoid memory load. + parallel, p_func, n_jobs = parallel_func( + _sl_transform, + self.n_jobs, + max_jobs=X.shape[-1], + verbose=_verbose_safe_false(), + ) + + X_splits = np.array_split(X, n_jobs, axis=-1) + idx, est_splits = zip(*array_split_idx(self.estimators_, n_jobs)) + + context = _create_progressbar_context(self, X, "Transforming") + with context as pb: + y_pred = parallel( + p_func(est, x, method, pb.subset(pb_idx)) + for pb_idx, est, x in zip(idx, est_splits, X_splits) + ) + + y_pred = np.concatenate(y_pred, axis=1) + if orig_method == "transform": + y_pred = y_pred.astype(X.dtype) + elif ( + orig_method in ("predict", "predict_proba", "decision_function") + and not is_nd + ): + y_pred = y_pred.squeeze() + return y_pred + + def transform(self, X): + """Transform each data slice/task with a series of independent estimators. + + The number of tasks in X should match the number of tasks/estimators + given at fit time. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_tasks) + The input samples. For each data slice/task, the corresponding + estimator makes a transformation of the data, e.g. + ``[estimators[ii].transform(X[..., ii]) for ii in range(n_estimators)]``. + The feature dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_tasks). + + Returns + ------- + Xt : array, shape (n_samples, n_estimators) + The transformed values generated by each estimator. + """ # noqa: E501 + return self._transform(X, "transform") + + def predict(self, X): + """Predict each data slice/task with a series of independent estimators. + + The number of tasks in X should match the number of tasks/estimators + given at fit time. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_tasks) + The input samples. For each data slice, the corresponding estimator + makes the sample predictions, e.g.: + ``[estimators[ii].predict(X[..., ii]) for ii in range(n_estimators)]``. + The feature dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_tasks). + + Returns + ------- + y_pred : array, shape (n_samples, n_estimators) | (n_samples, n_tasks, n_targets) + Predicted values for each estimator/data slice. + """ # noqa: E501 + return self._transform(X, "predict") + + def predict_proba(self, X): + """Predict each data slice with a series of independent estimators. + + The number of tasks in X should match the number of tasks/estimators + given at fit time. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_tasks) + The input samples. For each data slice, the corresponding estimator + makes the sample probabilistic predictions, e.g.: + ``[estimators[ii].predict_proba(X[..., ii]) for ii in range(n_estimators)]``. + The feature dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_tasks). + + Returns + ------- + y_pred : array, shape (n_samples, n_tasks, n_classes) + Predicted probabilities for each estimator/data slice/task. + """ # noqa: E501 + return self._transform(X, "predict_proba") + + def decision_function(self, X): + """Estimate distances of each data slice to the hyperplanes. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_tasks) + The input samples. For each data slice, the corresponding estimator + outputs the distance to the hyperplane, e.g.: + ``[estimators[ii].decision_function(X[..., ii]) for ii in range(n_estimators)]``. + The feature dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_estimators). + + Returns + ------- + y_pred : array, shape (n_samples, n_estimators, n_classes * (n_classes-1) // 2) + Predicted distances for each estimator/data slice. + + Notes + ----- + This requires base_estimator to have a ``decision_function`` method. + """ # noqa: E501 + return self._transform(X, "decision_function") + + def _check_Xy(self, X, y=None, fit=False): + """Aux. function to check input data.""" + # Once we require sklearn 1.1+ we should do something like: + X = self._check_data(X, y=y, atleast_3d=False, fit=fit) + is_nd = X.ndim >= 3 + if not is_nd: + err = None + if not self.allow_2d: + err = 3 + elif X.ndim < 2: + err = 2 + if err: + raise ValueError(f"X must have at least {err} dimensions.") + X = X[..., np.newaxis] + return X, is_nd + + def score(self, X, y): + """Score each estimator on each task. + + The number of tasks in X should match the number of tasks/estimators + given at fit time, i.e. we need + ``X.shape[-1] == len(self.estimators_)``. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_tasks) + The input samples. For each data slice, the corresponding estimator + scores the prediction, e.g.: + ``[estimators[ii].score(X[..., ii], y) for ii in range(n_estimators)]``. + The feature dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_tasks). + y : array, shape (n_samples,) | (n_samples, n_targets) + The target values. + + Returns + ------- + score : array, shape (n_samples, n_estimators) + Score for each estimator/task. + """ # noqa: E501 + X, _ = self._check_Xy(X, y) + if X.shape[-1] != len(self.estimators_): + raise ValueError("The number of estimators does not match X.shape[-1]") + + scoring = check_scoring(self.base_estimator, self.scoring) + y = _fix_auc(scoring, y) + + # For predictions/transforms the parallelization is across the data and + # not across the estimators to avoid memory load. + parallel, p_func, n_jobs = parallel_func( + _sl_score, + self.n_jobs, + max_jobs=X.shape[-1], + verbose=_verbose_safe_false(), + ) + X_splits = np.array_split(X, n_jobs, axis=-1) + est_splits = np.array_split(self.estimators_, n_jobs) + score = parallel( + p_func(est, scoring, x, y) for (est, x) in zip(est_splits, X_splits) + ) + + score = np.concatenate(score, axis=0) + return score + + @property + def classes_(self): + if not hasattr(self.estimators_[0], "classes_"): + raise AttributeError( + "classes_ attribute available only if base_estimator has it, and " + f"estimator {self.estimators_[0]} does not" + ) + return self.estimators_[0].classes_ + + +@fill_doc +def _sl_fit(estimator, X, y, pb, **fit_params): + """Aux. function to fit SlidingEstimator in parallel. + + Fit a clone estimator to each slice of data. + + Parameters + ---------- + %(base_estimator)s + X : array, shape (n_samples, nd_features, n_estimators) + The target data. The feature dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_estimators) + y : array, shape (n_sample, ) + The target values. + pb : instance of ProgressBar + The progress bar to update. + fit_params : dict | None + Parameters to pass to the fit method of the estimator. + + Returns + ------- + estimators_ : list of estimators + The fitted estimators. + """ + estimators_ = list() + for ii in range(X.shape[-1]): + est = clone(estimator) + est.fit(X[..., ii], y, **fit_params) + estimators_.append(est) + + pb.update(ii + 1) + return estimators_ + + +def _sl_transform(estimators, X, method, pb): + """Aux. function to transform SlidingEstimator in parallel. + + Applies transform/predict/decision_function etc for each slice of data. + + Parameters + ---------- + estimators : list of estimators + The fitted estimators. + X : array, shape (n_samples, nd_features, n_estimators) + The target data. The feature dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_estimators) + method : str + The estimator method to use (e.g. 'predict', 'transform'). + pb : instance of ProgressBar + The progress bar to update. + + Returns + ------- + y_pred : array, shape (n_samples, n_estimators, n_classes * (n_classes-1) // 2) + The transformations for each slice of data. + """ # noqa: E501 + for ii, est in enumerate(estimators): + transform = getattr(est, method) + _y_pred = transform(X[..., ii]) + # Initialize array of predictions on the first transform iteration + if ii == 0: + y_pred = _sl_init_pred(_y_pred, X) + y_pred[:, ii, ...] = _y_pred + + pb.update(ii + 1) + return y_pred + + +def _sl_init_pred(y_pred, X): + """Aux. function to SlidingEstimator to initialize y_pred.""" + n_sample, n_tasks = X.shape[0], X.shape[-1] + y_pred = np.zeros((n_sample, n_tasks) + y_pred.shape[1:], y_pred.dtype) + return y_pred + + +def _sl_score(estimators, scoring, X, y): + """Aux. function to score SlidingEstimator in parallel. + + Predict and score each slice of data. + + Parameters + ---------- + estimators : list, shape (n_tasks,) + The fitted estimators. + X : array, shape (n_samples, nd_features, n_tasks) + The target data. The feature dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_tasks) + scoring : callable, str or None + If scoring is None (default), the predictions are internally + generated by estimator.score(). Else, we must first get the + predictions to pass them to ad-hoc scorer. + y : array, shape (n_samples,) | (n_samples, n_targets) + The target values. + + Returns + ------- + score : array, shape (n_tasks,) + The score for each task / slice of data. + """ + n_tasks = X.shape[-1] + score = np.zeros(n_tasks) + for ii, est in enumerate(estimators): + score[ii] = scoring(est, X[..., ii], y) + return score + + +def _check_method(estimator, method): + """Check that an estimator has the method attribute. + + If method == 'transform' and estimator does not have 'transform', use + 'predict' instead. + """ + if method == "transform" and not hasattr(estimator, "transform"): + method = "predict" + if not hasattr(estimator, method): + ValueError(f"base_estimator does not have `{method}` method.") + return method + + +@fill_doc +class GeneralizingEstimator(SlidingEstimator): + """Generalization Light. + + Fit a search-light along the last dimension and use them to apply a + systematic cross-tasks generalization. + + Parameters + ---------- + %(base_estimator)s + %(scoring)s + %(n_jobs)s + %(position)s + %(allow_2d)s + %(verbose)s + """ + + def __repr__(self): # noqa: D105 + repr_str = super().__repr__() + if hasattr(self, "estimators_"): + repr_str = repr_str[:-1] + repr_str += f", fitted with {len(self.estimators_)} estimators>" + return repr_str + + def _transform(self, X, method): + """Aux. function to make parallel predictions/transformation.""" + X, is_nd = self._check_Xy(X) + check_is_fitted(self) + orig_method = method + method = _check_method(self.base_estimator, method) + + parallel, p_func, n_jobs = parallel_func( + _gl_transform, + self.n_jobs, + max_jobs=X.shape[-1], + verbose=_verbose_safe_false(), + ) + + context = _create_progressbar_context(self, X, "Transforming") + with context as pb: + y_pred = parallel( + p_func(self.estimators_, x_split, method, pb.subset(pb_idx)) + for pb_idx, x_split in array_split_idx( + X, n_jobs, axis=-1, n_per_split=len(self.estimators_) + ) + ) + + y_pred = np.concatenate(y_pred, axis=2) + if orig_method == "transform": + y_pred = y_pred.astype(X.dtype) + if ( + orig_method in ("predict", "predict_proba", "decision_function") + and not is_nd + ): + y_pred = y_pred.squeeze() + return y_pred + + def transform(self, X): + """Transform each data slice with all possible estimators. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_slices) + The input samples. For estimator the corresponding data slice is + used to make a transformation. The feature dimension can be + multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_estimators). + + Returns + ------- + Xt : array, shape (n_samples, n_estimators, n_slices) + The transformed values generated by each estimator. + """ + check_is_fitted(self) + return self._transform(X, "transform") + + def predict(self, X): + """Predict each data slice with all possible estimators. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_slices) + The training input samples. For each data slice, a fitted estimator + predicts each slice of the data independently. The feature + dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_estimators). + + Returns + ------- + y_pred : array, shape (n_samples, n_estimators, n_slices) | (n_samples, n_estimators, n_slices, n_targets) + The predicted values for each estimator. + """ # noqa: E501 + return self._transform(X, "predict") + + def predict_proba(self, X): + """Estimate probabilistic estimates of each data slice with all possible estimators. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_slices) + The training input samples. For each data slice, a fitted estimator + predicts a slice of the data. The feature dimension can be + multidimensional e.g. + ``X.shape = (n_samples, n_features_1, n_features_2, n_estimators)``. + + Returns + ------- + y_pred : array, shape (n_samples, n_estimators, n_slices, n_classes) + The predicted values for each estimator. + + Notes + ----- + This requires ``base_estimator`` to have a ``predict_proba`` method. + """ # noqa: E501 + return self._transform(X, "predict_proba") + + def decision_function(self, X): + """Estimate distances of each data slice to all hyperplanes. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_slices) + The training input samples. Each estimator outputs the distance to + its hyperplane, e.g.: + ``[estimators[ii].decision_function(X[..., ii]) for ii in range(n_estimators)]``. + The feature dimension can be multidimensional e.g. + ``X.shape = (n_samples, n_features_1, n_features_2, n_estimators)``. + + Returns + ------- + y_pred : array, shape (n_samples, n_estimators, n_slices, n_classes * (n_classes-1) // 2) + The predicted values for each estimator. + + Notes + ----- + This requires ``base_estimator`` to have a ``decision_function`` + method. + """ # noqa: E501 + return self._transform(X, "decision_function") + + def score(self, X, y): + """Score each of the estimators on the tested dimensions. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_slices) + The input samples. For each data slice, the corresponding estimator + scores the prediction, e.g.: + ``[estimators[ii].score(X[..., ii], y) for ii in range(n_slices)]``. + The feature dimension can be multidimensional e.g. + ``X.shape = (n_samples, n_features_1, n_features_2, n_estimators)``. + y : array, shape (n_samples,) | (n_samples, n_targets) + The target values. + + Returns + ------- + score : array, shape (n_samples, n_estimators, n_slices) + Score for each estimator / data slice couple. + """ # noqa: E501 + X, _ = self._check_Xy(X, y) + # For predictions/transforms the parallelization is across the data and + # not across the estimators to avoid memory load. + parallel, p_func, n_jobs = parallel_func( + _gl_score, + self.n_jobs, + max_jobs=X.shape[-1], + verbose=_verbose_safe_false(), + ) + scoring = check_scoring(self.base_estimator, self.scoring) + y = _fix_auc(scoring, y) + + context = _create_progressbar_context(self, X, "Scoring") + with context as pb: + score = parallel( + p_func(self.estimators_, scoring, x, y, pb.subset(pb_idx)) + for pb_idx, x in array_split_idx( + X, n_jobs, axis=-1, n_per_split=len(self.estimators_) + ) + ) + + score = np.concatenate(score, axis=1) + return score + + +def _gl_transform(estimators, X, method, pb): + """Transform the dataset. + + This will apply each estimator to all slices of the data. + + Parameters + ---------- + X : array, shape (n_samples, nd_features, n_slices) + The training input samples. For each data slice, a clone estimator + is fitted independently. The feature dimension can be multidimensional + e.g. X.shape = (n_samples, n_features_1, n_features_2, n_estimators) + method : str + The method to call for each estimator. + pb : instance of ProgressBar + The progress bar to update. + + Returns + ------- + Xt : array, shape (n_samples, n_slices) + The transformed values generated by each estimator. + """ + n_sample, n_iter = X.shape[0], X.shape[-1] + for ii, est in enumerate(estimators): + # stack generalized data for faster prediction + X_stack = X.transpose(np.r_[0, X.ndim - 1, range(1, X.ndim - 1)]) + X_stack = X_stack.reshape(np.r_[n_sample * n_iter, X_stack.shape[2:]]) + transform = getattr(est, method) + _y_pred = transform(X_stack) + # unstack generalizations + if _y_pred.ndim == 2: + _y_pred = np.reshape(_y_pred, [n_sample, n_iter, _y_pred.shape[1]]) + else: + shape = np.r_[n_sample, n_iter, _y_pred.shape[1:]].astype(int) + _y_pred = np.reshape(_y_pred, shape) + # Initialize array of predictions on the first transform iteration + if ii == 0: + y_pred = _gl_init_pred(_y_pred, X, len(estimators)) + y_pred[:, ii, ...] = _y_pred + + pb.update((ii + 1) * n_iter) + return y_pred + + +def _gl_init_pred(y_pred, X, n_train): + """Aux. function to GeneralizingEstimator to initialize y_pred.""" + n_sample, n_iter = X.shape[0], X.shape[-1] + if y_pred.ndim == 3: + y_pred = np.zeros((n_sample, n_train, n_iter, y_pred.shape[-1]), y_pred.dtype) + else: + y_pred = np.zeros((n_sample, n_train, n_iter), y_pred.dtype) + return y_pred + + +def _gl_score(estimators, scoring, X, y, pb): + """Score GeneralizingEstimator in parallel. + + Predict and score each slice of data. + + Parameters + ---------- + estimators : list of estimators + The fitted estimators. + scoring : callable, string or None + If scoring is None (default), the predictions are internally + generated by estimator.score(). Else, we must first get the + predictions to pass them to ad-hoc scorer. + X : array, shape (n_samples, nd_features, n_slices) + The target data. The feature dimension can be multidimensional e.g. + X.shape = (n_samples, n_features_1, n_features_2, n_estimators) + y : array, shape (n_samples,) | (n_samples, n_targets) + The target values. + pb : instance of ProgressBar + The progress bar to update. + + Returns + ------- + score : array, shape (n_estimators, n_slices) + The score for each slice of data. + """ + # FIXME: The level parallelization may be a bit high, and might be memory + # consuming. Perhaps need to lower it down to the loop across X slices. + score_shape = [len(estimators), X.shape[-1]] + for jj in range(X.shape[-1]): + for ii, est in enumerate(estimators): + _score = scoring(est, X[..., jj], y) + # Initialize array of predictions on the first score iteration + if (ii == 0) and (jj == 0): + dtype = type(_score) + score = np.zeros(score_shape, dtype) + score[ii, jj, ...] = _score + + pb.update(jj * len(estimators) + ii + 1) + return score + + +def _fix_auc(scoring, y): + # This fixes sklearn's inability to compute roc_auc when y not in [0, 1] + # scikit-learn/scikit-learn#6874 + if scoring is not None: + score_func = getattr(scoring, "_score_func", None) + kwargs = getattr(scoring, "_kwargs", {}) + if ( + getattr(score_func, "__name__", "") == "roc_auc_score" + and kwargs.get("multi_class", "raise") == "raise" + ): + if np.ndim(y) != 1 or len(set(y)) != 2: + raise ValueError( + "roc_auc scoring can only be computed for two-class problems." + ) + y = LabelEncoder().fit_transform(y) + return y + + +def _create_progressbar_context(inst, X, message): + """Create a progress bar taking into account ``inst.verbose``.""" + multiply = len(inst.estimators_) if isinstance(inst, GeneralizingEstimator) else 1 + n_steps = X.shape[-1] * max(1, multiply) + mesg = f"{message} {inst.__class__.__name__}" + + which_tqdm = "off" if not _check_verbose(inst.verbose) else None + context = ProgressBar( + n_steps, mesg=mesg, position=inst.position, which_tqdm=which_tqdm + ) + + return context + + +def _check_verbose(verbose): + """Check if verbose is above or equal 'INFO' level.""" + logging_level = _parse_verbose(verbose) + bool_verbose = logging_level <= logging.INFO + return bool_verbose diff --git a/mne-python/source/mne/decoding/spatial_filter.py b/mne-python/source/mne/decoding/spatial_filter.py new file mode 100644 index 0000000000000000000000000000000000000000..169cca7d005ad210d381c61b08341790ddb4e761 --- /dev/null +++ b/mne-python/source/mne/decoding/spatial_filter.py @@ -0,0 +1,639 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import copy as cp + +import matplotlib.pyplot as plt +import numpy as np + +from ..defaults import _BORDER_DEFAULT, _EXTRAPOLATE_DEFAULT, _INTERPOLATION_DEFAULT +from ..evoked import EvokedArray +from ..utils import _check_option, fill_doc, verbose +from ..viz.utils import plt_show +from .base import LinearModel, _GEDTransformer, get_coef + + +def _plot_model( + model_array, + info, + components=None, + *, + evk_tmin=None, + ch_type=None, + scalings=None, + sensors=True, + show_names=False, + mask=None, + mask_params=None, + contours=6, + outlines="head", + sphere=None, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + border=_BORDER_DEFAULT, + res=64, + size=1, + cmap="RdBu_r", + vlim=(None, None), + cnorm=None, + colorbar=True, + cbar_fmt="%3.1f", + units=None, + axes=None, + name_format=None, + nrows=1, + ncols="auto", + show=True, +): + if components is None: + n_comps = model_array.shape[-2] + components = np.arange(n_comps) + kwargs = dict( + # args set here + times=components, + average=None, + proj=False, + units="AU" if units is None else units, + time_format=name_format, + # args passed from the upstream + ch_type=ch_type, + scalings=scalings, + sensors=sensors, + show_names=show_names, + mask=mask, + mask_params=mask_params, + contours=contours, + outlines=outlines, + sphere=sphere, + image_interp=image_interp, + extrapolate=extrapolate, + border=border, + res=res, + size=size, + cmap=cmap, + vlim=vlim, + cnorm=cnorm, + colorbar=colorbar, + cbar_fmt=cbar_fmt, + nrows=nrows, + ncols=ncols, + show=show, + ) + + # set sampling frequency to have 1 component per time point + + if evk_tmin is None: + info = cp.deepcopy(info) + with info._unlock(): + info["sfreq"] = 1.0 + evk_tmin = 0 + + if model_array.ndim == 3: + n_classes = model_array.shape[0] + figs = list() + for class_idx in range(n_classes): + model_evk = EvokedArray(model_array[class_idx].T, info, tmin=evk_tmin) + fig = model_evk.plot_topomap( + axes=axes[class_idx] if axes else None, **kwargs + ) + figs.append(fig) + return figs + else: + model_evk = EvokedArray(model_array.T, info, tmin=evk_tmin) + fig = model_evk.plot_topomap(axes=axes, **kwargs) + return fig + + +def _plot_scree_per_class(evals, add_cumul_evals, axes): + component_numbers = np.arange(len(evals)) + cumul_evals = np.cumsum(evals) if add_cumul_evals else None + # plot individual eigenvalues + color_line = "cornflowerblue" + axes.set_xlabel("Component Index", fontsize=18) + axes.set_ylabel("Eigenvalue", fontsize=18) + axes.plot( + component_numbers, + evals, + color=color_line, + marker="o", + markersize=8, + ) + axes.tick_params(axis="y", labelsize=16) + axes.tick_params(axis="x", labelsize=16) + + if add_cumul_evals: + # plot cumulative eigenvalues + ax2 = axes.twinx() + ax2.grid(False) + color_line = "firebrick" + ax2.set_ylabel("Cumulative Eigenvalues", fontsize=18) + ax2.plot( + component_numbers, + cumul_evals, + color=color_line, + marker="o", + markersize=6, + ) + ax2.tick_params(axis="y", labelcolor=color_line, labelsize=16) + ax2.set_ylim(0) + + +def _plot_scree( + evals, + title="Scree plot", + add_cumul_evals=True, + axes=None, +): + evals_data = evals if evals.ndim == 2 else [evals] + n_classes = len(evals_data) + axes = [axes] if isinstance(axes, plt.Axes) else axes + if axes is not None and n_classes != len(axes): + raise ValueError(f"Received {len(axes)} axes, but expected {n_classes}") + + orig_axes = axes + figs = list() + for class_idx in range(n_classes): + fig = None + if orig_axes is None: + fig, ax = plt.subplots(figsize=(7, 4), layout="constrained") + else: + ax = axes[class_idx] + _plot_scree_per_class(evals_data[class_idx], add_cumul_evals, ax) + if fig is not None: + fig.suptitle(title, fontsize=22) + figs.append(fig) + + return figs[0] if len(figs) == 1 else figs + + +@verbose +def get_spatial_filter_from_estimator( + estimator, + info, + *, + inverse_transform=False, + step_name=None, + get_coefs=("filters_", "patterns_", "evals_"), + patterns_method=None, + verbose=None, +): + """Instantiate a :class:`mne.decoding.SpatialFilter` object. + + Creates object from the fitted generalized eigendecomposition + transformers or :class:`mne.decoding.LinearModel`. + This object can be used to visualize spatial filters, + patterns, and eigenvalues. + + Parameters + ---------- + estimator : instance of sklearn.base.BaseEstimator + Sklearn-based estimator or meta-estimator from which to initialize + spatial filter. Use ``step_name`` to select relevant transformer + from the pipeline object (works with nested names using ``__`` syntax). + info : instance of mne.Info + The measurement info object for plotting topomaps. + inverse_transform : bool + If True, returns filters and patterns after inverse transforming them with + the transformer steps of the estimator. Defaults to False. + step_name : str | None + Name of the sklearn's pipeline step to get the coefs from. + If inverse_transform is True, the inverse transformations + will be applied using transformers before this step. + If None, the last step will be used. Defaults to None. + get_coefs : tuple + The names of the coefficient attributes to retrieve, can include + ``'filters_'``, ``'patterns_'`` and ``'evals_'``. + If step is GEDTransformer, will use all. + if step is LinearModel will only use ``'filters_'`` and ``'patterns_'``. + Defaults to (``'filters_'``, ``'patterns_'``, ``'evals_'``). + patterns_method : str + The method used to compute the patterns. Can be None, ``'pinv'`` or ``'haufe'``. + It will be set automatically to ``'pinv'`` if step is GEDTransformer, + or to ``'haufe'`` if step is LinearModel. Defaults to None. + %(verbose)s + + Returns + ------- + sp_filter : instance of mne.decoding.SpatialFilter + The spatial filter object. + + See Also + -------- + SpatialFilter, mne.decoding.LinearModel, mne.decoding.CSP, + mne.decoding.SSD, mne.decoding.XdawnTransformer, mne.decoding.SPoC + + Notes + ----- + .. versionadded:: 1.11 + """ + for coef in get_coefs: + if coef not in ("filters_", "patterns_", "evals_"): + raise ValueError( + f"'get_coefs' can only include 'filters_', " + f"'patterns_' and 'evals_', but got {coef}." + ) + if step_name is not None: + model = estimator.get_params()[step_name] + elif hasattr(estimator, "named_steps"): + model = estimator[-1] + else: + model = estimator + if isinstance(model, LinearModel): + patterns_method = "haufe" + get_coefs = ["filters_", "patterns_"] + elif isinstance(model, _GEDTransformer): + patterns_method = "pinv" + get_coefs = ["filters_", "patterns_", "evals_"] + + coefs = { + coef[:-1]: get_coef( + estimator, + coef, + inverse_transform=False if coef == "evals_" else inverse_transform, + step_name=step_name, + verbose=verbose, + ) + for coef in get_coefs + } + + sp_filter = SpatialFilter(info, patterns_method=patterns_method, **coefs) + return sp_filter + + +class SpatialFilter: + r"""Container for spatial filter weights (evecs) and patterns. + + .. warning:: For MNE-Python decoding classes, this container should be + instantiated with `mne.decoding.get_spatial_filter_from_estimator`. + Direct instantiation with external spatial filters is possible + at your own risk. + + This object is obtained either by generalized eigendecomposition (GED) algorithms + such as :class:`mne.decoding.CSP`, :class:`mne.decoding.SPoC`, + :class:`mne.decoding.SSD`, :class:`mne.decoding.XdawnTransformer` or by + :class:`mne.decoding.LinearModel`, wrapping linear models like SVM or Logit. + The object stores the filters that projects sensor data to a reduced component + space, and the corresponding patterns (obtained by pseudoinverse in GED case or + Haufe's trick in case of :class:`mne.decoding.LinearModel`). It can also be directly + initialized using filters from other transformers (e.g. PyRiemann), + but make sure that the dimensions match. + + Parameters + ---------- + info : instance of Info + The measurement info containing channel topography. + filters : ndarray, shape ((n_classes), n_components, n_channels) + The spatial filters (transposed eigenvectors of the decomposition). + evals : ndarray, shape ((n_classes), n_components) | None + The eigenvalues of the decomposition. Defaults to ``None``. + patterns : ndarray, shape ((n_classes), n_components, n_channels) | None + The patterns of the decomposition. If None, they will be computed + from the filters using pseudoinverse. Defaults to ``None``. + patterns_method : str + The method used to compute the patterns. Can be ``'pinv'`` or ``'haufe'``. + If ``patterns`` is None, it will be set to ``'pinv'``. Defaults to ``'pinv'``. + + Attributes + ---------- + info : instance of Info + The measurement info. + filters : ndarray, shape (n_components, n_channels) + The spatial filters (unmixing matrix). Applying these filters to the data + gives the component time series. + patterns : ndarray, shape (n_components, n_channels) + The spatial patterns (mixing matrix/forward model). + These represent the scalp topography of each component. + evals : ndarray, shape (n_components,) + The eigenvalues associated with each component. + patterns_method : str + The method used to compute the patterns from the filters. + + See Also + -------- + get_spatial_filter_from_estimator, mne.decoding.LinearModel, mne.decoding.CSP, + mne.decoding.SSD, mne.decoding.XdawnTransformer, mne.decoding.SPoC + + Notes + ----- + The spatial filters and patterns are stored with shape + ``(n_components, n_channels)``. + + Filters and patterns are related by the following equation: + + .. math:: + \mathbf{A} = \mathbf{W}^{-1} + + where :math:`\mathbf{A}` is the matrix of patterns (the mixing matrix) and + :math:`\mathbf{W}` is the matrix of filters (the unmixing matrix). + + For a detailed discussion on the difference between filters and patterns for GED + see :footcite:`Cohen2022` and for linear models in + general see :footcite:`HaufeEtAl2014`. + + .. versionadded:: 1.11 + + References + ---------- + .. footbibliography:: + """ + + def __init__( + self, + info, + filters, + *, + evals=None, + patterns=None, + patterns_method="pinv", + ): + _check_option( + "patterns_method", + patterns_method, + ("pinv", "haufe"), + ) + self.info = info + self.evals = evals + self.filters = filters + n_comps, n_chs = self.filters.shape[-2:] + if patterns is None: + # XXX Using numpy's pinv here to handle 3D case seamlessly + # Perhaps mne.linalg.pinv can be improved to handle 3D also + # Then it could be changed here to be consistent with + # GEDTransformer + self.patterns = np.linalg.pinv(filters.T) + self.patterns_method = "pinv" + else: + self.patterns = patterns + self.patterns_method = patterns_method + + # In case of multi-target classification in LinearModel + # number of targets can be greater than number of channels. + if patterns_method != "haufe" and n_comps > n_chs: + raise ValueError( + "Number of components can't be greater " + "than number of channels in filters, " + "perhaps the provided matrix is transposed?" + ) + if self.filters.shape != self.patterns.shape: + raise ValueError( + f"Shape mismatch between filters and patterns." + f"Filters are {self.filters.shape}," + f"while patterns are {self.patterns.shape}" + ) + + @fill_doc + def plot_filters( + self, + components=None, + tmin=None, + *, + ch_type=None, + scalings=None, + sensors=True, + show_names=False, + mask=None, + mask_params=None, + contours=6, + outlines="head", + sphere=None, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + border=_BORDER_DEFAULT, + res=64, + size=1, + cmap="RdBu_r", + vlim=(None, None), + cnorm=None, + colorbar=True, + cbar_fmt="%3.1f", + units=None, + axes=None, + name_format="Filter%01d", + nrows=1, + ncols="auto", + show=True, + ): + """Plot topographic maps of model filters. + + Parameters + ---------- + components : float | array of float | 'auto' | None + Indices of filters to plot. If "auto", the number of + ``axes`` determines the amount of filters. + If None, all filters will be plotted. Defaults to None. + tmin : float | None + In case filters are distributed temporally, + this can be used to align them with times + and frequency. Use ``epochs.tmin``, for example. + Defaults to None. + %(ch_type_topomap)s + %(scalings_topomap)s + %(sensors_topomap)s + %(show_names_topomap)s + %(mask_evoked_topomap)s + %(mask_params_topomap)s + %(contours_topomap)s + %(outlines_topomap)s + %(sphere_topomap_auto)s + %(image_interp_topomap)s + %(extrapolate_topomap)s + %(border_topomap)s + %(res_topomap)s + %(size_topomap)s + %(cmap_topomap)s + %(vlim_plot_topomap_psd)s + %(cnorm)s + %(colorbar_topomap)s + %(cbar_fmt_topomap)s + %(units_topomap_evoked)s + %(axes_evoked_plot_topomap)s + name_format : str + String format for topomap values. Defaults to ``'Filter%%01d'``. + %(nrows_ncols_topomap)s + %(show)s + + Returns + ------- + fig : instance of matplotlib.figure.Figure + The figure. + """ + fig = _plot_model( + self.filters, + self.info, + components=components, + evk_tmin=tmin, + ch_type=ch_type, + scalings=scalings, + sensors=sensors, + show_names=show_names, + mask=mask, + mask_params=mask_params, + contours=contours, + outlines=outlines, + sphere=sphere, + image_interp=image_interp, + extrapolate=extrapolate, + border=border, + res=res, + size=size, + cmap=cmap, + vlim=vlim, + cnorm=cnorm, + colorbar=colorbar, + cbar_fmt=cbar_fmt, + units=units, + axes=axes, + name_format=name_format, + nrows=nrows, + ncols=ncols, + show=show, + ) + return fig + + @fill_doc + def plot_patterns( + self, + components=None, + tmin=None, + *, + ch_type=None, + scalings=None, + sensors=True, + show_names=False, + mask=None, + mask_params=None, + contours=6, + outlines="head", + sphere=None, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + border=_BORDER_DEFAULT, + res=64, + size=1, + cmap="RdBu_r", + vlim=(None, None), + cnorm=None, + colorbar=True, + cbar_fmt="%3.1f", + units=None, + axes=None, + name_format="Pattern%01d", + nrows=1, + ncols="auto", + show=True, + ): + """Plot topographic maps of model patterns. + + Parameters + ---------- + components : float | array of float | 'auto' | None + Indices of patterns to plot. If "auto", the number of + ``axes`` determines the amount of patterns. + If None, all patterns will be plotted. Defaults to None. + tmin : float | None + In case patterns are distributed temporally, + this can be used to align them with times + and frequency. Use ``epochs.tmin``, for example. + Defaults to None. + %(ch_type_topomap)s + %(scalings_topomap)s + %(sensors_topomap)s + %(show_names_topomap)s + %(mask_evoked_topomap)s + %(mask_params_topomap)s + %(contours_topomap)s + %(outlines_topomap)s + %(sphere_topomap_auto)s + %(image_interp_topomap)s + %(extrapolate_topomap)s + %(border_topomap)s + %(res_topomap)s + %(size_topomap)s + %(cmap_topomap)s + %(vlim_plot_topomap_psd)s + %(cnorm)s + %(colorbar_topomap)s + %(cbar_fmt_topomap)s + %(units_topomap_evoked)s + %(axes_evoked_plot_topomap)s + name_format : str + String format for topomap values. Defaults to ``'Pattern%%01d'``. + %(nrows_ncols_topomap)s + %(show)s + + Returns + ------- + fig : instance of matplotlib.figure.Figure + The figure. + """ + fig = _plot_model( + self.patterns, + self.info, + components=components, + evk_tmin=tmin, + ch_type=ch_type, + scalings=scalings, + sensors=sensors, + show_names=show_names, + mask=mask, + mask_params=mask_params, + contours=contours, + outlines=outlines, + sphere=sphere, + image_interp=image_interp, + extrapolate=extrapolate, + border=border, + res=res, + size=size, + cmap=cmap, + vlim=vlim, + cnorm=cnorm, + colorbar=colorbar, + cbar_fmt=cbar_fmt, + units=units, + axes=axes, + name_format=name_format, + nrows=nrows, + ncols=ncols, + show=show, + ) + return fig + + @fill_doc + def plot_scree( + self, + title="Scree plot", + add_cumul_evals=False, + axes=None, + show=True, + ): + """Plot scree for GED eigenvalues. + + Parameters + ---------- + title : str + Title for the plot. Defaults to ``'Scree plot'``. + add_cumul_evals : bool + Whether to add second line and y-axis for cumulative eigenvalues. + Defaults to ``True``. + axes : instance of Axes | None + The matplotlib axes to plot to. Defaults to ``None``. + %(show)s + + Returns + ------- + fig : instance of matplotlib.figure.Figure + The figure. + """ + if self.evals is None: + raise AttributeError("Can't plot scree if eigenvalues are not provided.") + + fig = _plot_scree( + self.evals, + title=title, + add_cumul_evals=add_cumul_evals, + axes=axes, + ) + plt_show(show, block=False) + return fig diff --git a/mne-python/source/mne/decoding/ssd.py b/mne-python/source/mne/decoding/ssd.py new file mode 100644 index 0000000000000000000000000000000000000000..41d67ece8c65a475a9513976514ea8f7e729ddb7 --- /dev/null +++ b/mne-python/source/mne/decoding/ssd.py @@ -0,0 +1,352 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import collections.abc as abc +from functools import partial + +import numpy as np + +from .._fiff.meas_info import Info, create_info +from .._fiff.pick import _picks_to_idx +from ..filter import filter_data +from ..utils import ( + _validate_type, + fill_doc, + logger, +) +from ._covs_ged import _ssd_estimate +from ._mod_ged import _get_spectral_ratio, _ssd_mod +from .base import _GEDTransformer + + +@fill_doc +class SSD(_GEDTransformer): + """ + Signal decomposition using the Spatio-Spectral Decomposition (SSD). + + SSD seeks to maximize the power at a frequency band of interest while + simultaneously minimizing it at the flanking (surrounding) frequency bins + (considered noise). It extremizes the covariance matrices associated with + signal and noise :footcite:`NikulinEtAl2011`. + + SSD can either be used as a dimensionality reduction method or a + ‘denoised’ low rank factorization method :footcite:`HaufeEtAl2014b`. + + Parameters + ---------- + %(info_not_none)s Must match the input data. + filt_params_signal : dict + Filtering for the frequencies of interest. + filt_params_noise : dict + Filtering for the frequencies of non-interest. + reg : float | str | None (default) + Which covariance estimator to use. + If not None (same as 'empirical'), allow regularization for covariance + estimation. If float, shrinkage is used (0 <= shrinkage <= 1). For str + options, reg will be passed to method :func:`mne.compute_covariance`. + n_components : int | None (default None) + The number of components to extract from the signal. + If None, the number of components equal to the rank of the data are + returned (see ``rank``). + picks : array of int | None (default None) + The indices of good channels. + sort_by_spectral_ratio : bool (default True) + If set to True, the components are sorted according to the spectral + ratio. + See Eq. (24) in :footcite:`NikulinEtAl2011`. + return_filtered : bool (default False) + If return_filtered is True, data is bandpassed and projected onto the + SSD components. + n_fft : int (default None) + If sort_by_spectral_ratio is set to True, then the SSD sources will be + sorted according to their spectral ratio which is calculated based on + :func:`mne.time_frequency.psd_array_welch`. The n_fft parameter sets the + length of FFT used. The default (None) will use 1 second of data. + See :func:`mne.time_frequency.psd_array_welch` for more information. + cov_method_params : dict | None (default None) + As in :class:`mne.decoding.SPoC` + The default is None. + restr_type : "restricting" | "whitening" | None + Restricting transformation for covariance matrices before performing + generalized eigendecomposition. + If "restricting" only restriction to the principal subspace of signal_cov + will be performed. + If "whitening", covariance matrices will be additionally rescaled according + to the whitening for the signal_cov. + If None, no restriction will be applied. Defaults to "whitening". + + .. versionadded:: 1.11 + rank : None | dict | ‘info’ | ‘full’ + As in :class:`mne.decoding.SPoC` + This controls the rank computation that can be read from the + measurement info or estimated from the data, which determines the + maximum possible number of components. + See Notes of :func:`mne.compute_rank` for details. + We recommend to use 'full' when working with epoched data. + + Attributes + ---------- + filters_ : array, shape (``n_channels or less``, n_channels) + The spatial filters to be multiplied with the signal. + patterns_ : array, shape (``n_channels or less``, n_channels) + The patterns for reconstructing the signal from the filtered data. + + References + ---------- + .. footbibliography:: + """ + + def __init__( + self, + info, + filt_params_signal, + filt_params_noise, + reg=None, + n_components=None, + picks=None, + sort_by_spectral_ratio=True, + return_filtered=False, + n_fft=None, + cov_method_params=None, + *, + restr_type="whitening", + rank=None, + ): + """Initialize instance.""" + self.info = info + self.filt_params_signal = filt_params_signal + self.filt_params_noise = filt_params_noise + self.reg = reg + self.n_components = n_components + self.picks = picks + self.sort_by_spectral_ratio = sort_by_spectral_ratio + self.return_filtered = return_filtered + self.n_fft = n_fft + self.cov_method_params = cov_method_params + self.restr_type = restr_type + self.rank = rank + + cov_callable = partial( + _ssd_estimate, + reg=reg, + cov_method_params=cov_method_params, + info=info, + picks=picks, + n_fft=n_fft, + filt_params_signal=filt_params_signal, + filt_params_noise=filt_params_noise, + rank=rank, + sort_by_spectral_ratio=sort_by_spectral_ratio, + ) + super().__init__( + n_components=n_components, + cov_callable=cov_callable, + mod_ged_callable=_ssd_mod, + restr_type=restr_type, + ) + + def _validate_params(self, X): + if isinstance(self.info, float): # special case, mostly for testing + self.sfreq_ = self.info + else: + _validate_type(self.info, Info, "info") + self.sfreq_ = self.info["sfreq"] + dicts = {"signal": self.filt_params_signal, "noise": self.filt_params_noise} + for param, dd in [("l", 0), ("h", 0), ("l", 1), ("h", 1)]: + key = ("signal", "noise")[dd] + if param + "_freq" not in dicts[key]: + raise ValueError( + f"{param + '_freq'} must be defined in filter parameters for {key}" + ) + val = dicts[key][param + "_freq"] + if not isinstance(val, int | float): + _validate_type(val, ("numeric",), f"{key} {param}_freq") + # check freq bands + if ( + self.filt_params_noise["l_freq"] > self.filt_params_signal["l_freq"] + or self.filt_params_signal["h_freq"] > self.filt_params_noise["h_freq"] + ): + raise ValueError( + "Wrongly specified frequency bands!\n" + "The signal band-pass must be within the noise " + "band-pass!" + ) + self.freqs_signal_ = ( + self.filt_params_signal["l_freq"], + self.filt_params_signal["h_freq"], + ) + self.freqs_noise_ = ( + self.filt_params_noise["l_freq"], + self.filt_params_noise["h_freq"], + ) + _validate_type(self.sort_by_spectral_ratio, (bool,), "sort_by_spectral_ratio") + _validate_type(self.n_fft, ("numeric", None), "n_fft") + self.n_fft_ = min( + int(self.n_fft if self.n_fft is not None else self.sfreq_), + X.shape[-1], + ) + _validate_type(self.return_filtered, (bool,), "return_filtered") + if isinstance(self.info, Info): + ch_types = self.info.get_channel_types(picks=self.picks, unique=True) + if len(ch_types) > 1: + raise ValueError( + "At this point SSD only supports fitting " + f"single channel types. Your info has {len(ch_types)} types." + ) + _validate_type(self.cov_method_params, (abc.Mapping, None), "cov_method_params") + + def _check_X(self, X, *, y=None, fit=False): + """Check input data.""" + X = self._check_data(X, y=y, fit=fit, atleast_3d=False) + n_chan = X.shape[-2] + if isinstance(self.info, Info) and n_chan != self.info["nchan"]: + raise ValueError( + "Info must match the input data." + f"Found {n_chan} channels but expected {self.info['nchan']}." + ) + return X + + def fit(self, X, y=None): + """Estimate the SSD decomposition on raw or epoched data. + + Parameters + ---------- + X : array, shape ([n_epochs, ]n_channels, n_times) + The input data from which to estimate the SSD. Either 2D array + obtained from continuous data or 3D array obtained from epoched + data. + y : None + Ignored; exists for compatibility with scikit-learn pipelines. + + Returns + ------- + self : instance of SSD + Returns the modified instance. + """ + X = self._check_X(X, y=y, fit=True) + self._validate_params(X) + if isinstance(self.info, Info): + info = self.info + else: + info = create_info(X.shape[-2], self.sfreq_, ch_types="eeg") + self.picks_ = _picks_to_idx(info, self.picks, none="data", exclude="bads") + + super().fit(X, y) + + logger.info("Done.") + return self + + def transform(self, X): + """Estimate epochs sources given the SSD filters. + + Parameters + ---------- + X : array, shape ([n_epochs, ]n_channels, n_times) + The input data from which to estimate the SSD. Either 2D array + obtained from continuous data or 3D array obtained from epoched + data. + + Returns + ------- + X_ssd : array, shape ([n_epochs, ]n_components, n_times) + The processed data. + """ + X = self._check_X(X) + # For the case where n_epochs dimension is absent. + if X.ndim == 2: + X = np.expand_dims(X, axis=0) + X_aux = X[..., self.picks_, :] + if self.return_filtered: + X_aux = filter_data(X_aux, self.sfreq_, **self.filt_params_signal) + X_ssd = super().transform(X_aux).squeeze() + + return X_ssd + + def fit_transform(self, X, y=None, **fit_params): + """Fit SSD to data, then transform it. + + Fits transformer to ``X`` and ``y`` with optional parameters ``fit_params``, and + returns a transformed version of ``X``. + + Parameters + ---------- + X : array, shape ([n_epochs, ]n_channels, n_times) + The input data from which to estimate the SSD. Either 2D array obtained from + continuous data or 3D array obtained from epoched data. + y : None + Ignored; exists for compatibility with scikit-learn pipelines. + **fit_params : dict + Additional fitting parameters passed to the :meth:`mne.decoding.SSD.fit` + method. Not used for this class. + + Returns + ------- + X_ssd : array, shape ([n_epochs, ]n_components, n_times) + The processed data. + """ + # use parent TransformerMixin method but with custom docstring + return super().fit_transform(X, y=y, **fit_params) + + def get_spectral_ratio(self, ssd_sources): + """Get the spectal signal-to-noise ratio for each spatial filter. + + Spectral ratio measure for best n_components selection + See :footcite:`NikulinEtAl2011`, Eq. (24). + + Parameters + ---------- + ssd_sources : array + Data projected to SSD space. + + Returns + ------- + spec_ratio : array, shape (n_channels) + Array with the sprectal ratio value for each component. + sorter_spec : array, shape (n_channels) + Array of indices for sorting spec_ratio. + + References + ---------- + .. footbibliography:: + """ + spec_ratio, sorter_spec = _get_spectral_ratio( + ssd_sources=ssd_sources, + sfreq=self.sfreq_, + n_fft=self.n_fft_, + freqs_signal=self.freqs_signal_, + freqs_noise=self.freqs_noise_, + ) + return spec_ratio, sorter_spec + + def inverse_transform(self): + """Not implemented yet.""" + raise NotImplementedError("inverse_transform is not yet available.") + + def apply(self, X): + """Remove selected components from the signal. + + This procedure will reconstruct M/EEG signals from which the dynamics + described by the excluded components is subtracted + (denoised by low-rank factorization). + See :footcite:`HaufeEtAl2014b` for more information. + + .. note:: Unlike in other classes with an apply method, + only NumPy arrays are supported (not instances of MNE objects). + + Parameters + ---------- + X : array, shape ([n_epochs, ]n_channels, n_times) + The input data from which to estimate the SSD. Either 2D array + obtained from continuous data or 3D array obtained from epoched + data. + + Returns + ------- + X : array, shape ([n_epochs, ]n_channels, n_times) + The processed data. + """ + X_ssd = self.transform(X) + pick_patterns = self.patterns_[: self.n_components].T + X = pick_patterns @ X_ssd + return X diff --git a/mne-python/source/mne/decoding/tests/__init__.py b/mne-python/source/mne/decoding/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/decoding/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/decoding/tests/test_base.py b/mne-python/source/mne/decoding/tests/test_base.py new file mode 100644 index 0000000000000000000000000000000000000000..68623876222a784691b4f1e04542ea6a2e622400 --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_base.py @@ -0,0 +1,601 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import platform +from contextlib import nullcontext + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_array_less, + assert_equal, +) + +pytest.importorskip("sklearn") + +from sklearn import svm +from sklearn.base import ( + BaseEstimator as sklearn_BaseEstimator, +) +from sklearn.base import ( + TransformerMixin as sklearn_TransformerMixin, +) +from sklearn.base import ( + is_classifier, + is_regressor, +) +from sklearn.decomposition import PCA +from sklearn.discriminant_analysis import LinearDiscriminantAnalysis +from sklearn.linear_model import LinearRegression, LogisticRegression, Ridge +from sklearn.model_selection import ( + GridSearchCV, + KFold, + StratifiedKFold, + cross_val_score, +) +from sklearn.multiclass import OneVsRestClassifier +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import StandardScaler +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne import EpochsArray, create_info +from mne.decoding import GeneralizingEstimator, Scaler, TransformerMixin, Vectorizer +from mne.decoding.base import ( + BaseEstimator, + LinearModel, + _get_inverse_funcs, + cross_val_multiscore, + get_coef, +) +from mne.decoding.search_light import SlidingEstimator +from mne.utils import check_version + + +def _make_data(n_samples=1000, n_features=5, n_targets=3): + """Generate some testing data. + + Parameters + ---------- + n_samples : int + The number of samples. + n_features : int + The number of features. + n_targets : int + The number of targets. + + Returns + ------- + X : ndarray, shape (n_samples, n_features) + The measured data. + Y : ndarray, shape (n_samples, n_targets) + The latent variables generating the data. + A : ndarray, shape (n_features, n_targets) + The forward model, mapping the latent variables (=Y) to the measured + data (=X). + """ + # Define Y latent factors + np.random.seed(0) + cov_Y = np.eye(n_targets) * 10 + np.random.rand(n_targets, n_targets) + cov_Y = (cov_Y + cov_Y.T) / 2.0 + mean_Y = np.random.rand(n_targets) + Y = np.random.multivariate_normal(mean_Y, cov_Y, size=n_samples) + + # The Forward model + A = np.random.randn(n_features, n_targets) + + X = Y.dot(A.T) + X += np.random.randn(n_samples, n_features) # add noise + X += np.random.rand(n_features) # Put an offset + if n_targets == 1: + Y = Y[:, 0] + + return X, Y, A + + +def test_get_coef(): + """Test getting linear coefficients (filters/patterns) from estimators.""" + lm_classification = LinearModel(LogisticRegression(solver="liblinear")) + assert hasattr(lm_classification, "__sklearn_tags__") + if check_version("sklearn", "1.6"): + print(lm_classification.__sklearn_tags__()) + assert is_classifier(lm_classification.model) + assert is_classifier(lm_classification) + assert not is_regressor(lm_classification.model) + assert not is_regressor(lm_classification) + + lm_regression = LinearModel(Ridge()) + assert is_regressor(lm_regression.model) + assert is_regressor(lm_regression) + assert not is_classifier(lm_regression.model) + assert not is_classifier(lm_regression) + + parameters = {"kernel": ["linear"], "C": [1, 10]} + lm_gs_classification = LinearModel( + GridSearchCV(svm.SVC(), parameters, cv=2, refit=True, n_jobs=None) + ) + assert is_classifier(lm_gs_classification) + + lm_gs_regression = LinearModel( + GridSearchCV(svm.SVR(), parameters, cv=2, refit=True, n_jobs=None) + ) + assert is_regressor(lm_gs_regression) + + # Define a classifier, an invertible transformer and an non-invertible one. + assert BaseEstimator is sklearn_BaseEstimator + assert TransformerMixin is sklearn_TransformerMixin + + class Clf(BaseEstimator): + def fit(self, X, y): + return self + + class NoInv(TransformerMixin): + def fit(self, X, y): + return self + + def transform(self, X): + return X + + class Inv(NoInv): + def inverse_transform(self, X): + return X + + X, y, A = _make_data(n_samples=1000, n_features=3, n_targets=1) + + # I. Test inverse function + + # Check that we retrieve the right number of inverse functions even if + # there are nested pipelines + good_estimators = [ + (1, make_pipeline(Inv(), Clf())), + (2, make_pipeline(Inv(), Inv(), Clf())), + (3, make_pipeline(Inv(), make_pipeline(Inv(), Inv()), Clf())), + ] + + for expected_n, est in good_estimators: + est.fit(X, y) + assert expected_n == len(_get_inverse_funcs(est)) + + bad_estimators = [ + Clf(), # 0: no preprocessing + Inv(), # 1: final estimator isn't classifier + make_pipeline(NoInv(), Clf()), # 2: first step isn't invertible + make_pipeline( + Inv(), make_pipeline(Inv(), NoInv()), Clf() + ), # 3: nested step isn't invertible + ] + # It's the NoInv that triggers the warning, but too hard to context manage just + # the correct part of the bad_estimators loop + for ei, est in enumerate(bad_estimators): + est.fit(X, y) + if ei in (2, 3): # the NoInv indices + ctx = pytest.warns(RuntimeWarning, match="Cannot inverse transform") + else: + ctx = nullcontext() + with ctx: + invs = _get_inverse_funcs(est) + assert_equal(invs, list()) + + # II. Test get coef for classification/regression estimators and pipelines + rng = np.random.RandomState(0) + for clf in ( + lm_regression, + lm_gs_classification, + make_pipeline(StandardScaler(), lm_classification), + make_pipeline(StandardScaler(), lm_gs_regression), + ): + # generate some categorical/continuous data + # according to the type of estimator. + if is_classifier(clf): + n, n_features = 1000, 3 + X = rng.rand(n, n_features) + y = np.arange(n) % 2 + else: + X, y, A = _make_data(n_samples=1000, n_features=3, n_targets=1) + y = np.ravel(y) + + clf.fit(X, y) + + # Retrieve final linear model + filters = get_coef(clf, "filters_", False) + if hasattr(clf, "steps"): + if hasattr(clf.steps[-1][-1].model_, "best_estimator_"): + # Linear Model with GridSearchCV + coefs = clf.steps[-1][-1].model_.best_estimator_.coef_ + else: + # Standard Linear Model + coefs = clf.steps[-1][-1].model_.coef_ + else: + if hasattr(clf.model_, "best_estimator_"): + # Linear Model with GridSearchCV + coefs = clf.model_.best_estimator_.coef_ + else: + # Standard Linear Model + coefs = clf.model_.coef_ + if coefs.ndim == 2 and coefs.shape[0] == 1: + coefs = coefs[0] + assert_array_equal(filters, coefs) + patterns = get_coef(clf, "patterns_", False) + assert filters[0] != patterns[0] + n_chans = X.shape[1] + assert_array_equal(filters.shape, patterns.shape, [n_chans, n_chans]) + + # Inverse transform linear model + filters_inv = get_coef(clf, "filters_", True) + assert filters[0] != filters_inv[0] + patterns_inv = get_coef(clf, "patterns_", True) + assert patterns[0] != patterns_inv[0] + + +class _Noop(BaseEstimator, TransformerMixin): + def fit(self, X, y=None): + return self + + def transform(self, X): + return X.copy() + + inverse_transform = transform + + +@pytest.mark.parametrize("inverse", (True, False)) +@pytest.mark.parametrize( + "clf", + [ + pytest.param( + make_pipeline( + Scaler(info=None, scalings="mean"), + SlidingEstimator(make_pipeline(LinearModel(Ridge()))), + ), + id="Scaler+SlidingEstimator", + ), + pytest.param( + make_pipeline( + _Noop(), + SlidingEstimator(make_pipeline(LinearModel(Ridge()))), + ), + id="Noop+SlidingEstimator", + ), + pytest.param( + SlidingEstimator(make_pipeline(StandardScaler(), LinearModel(Ridge()))), + id="SlidingEstimator+nested StandardScaler", + ), + ], +) +def test_get_coef_inverse_transform(inverse, clf): + """Test get_coef with and without inverse_transform.""" + X, y, A = _make_data(n_samples=1000, n_features=3, n_targets=1) + X = np.transpose([X, -X], [1, 2, 0]) # invert X across 2 time samples + clf.fit(X, y) + patterns = get_coef(clf, "patterns_", inverse) + filters = get_coef(clf, "filters_", inverse) + assert_array_equal(filters.shape, patterns.shape, X.shape[1:]) + # the two time samples get inverted patterns + assert_equal(patterns[0, 0], -patterns[0, 1]) + + for t in [0, 1]: + if hasattr(clf, "named_steps"): + est_t = clf.named_steps["slidingestimator"].estimators_[t] + filters_t = get_coef(est_t, "filters_", inverse) + if inverse: + filters_t = clf[0].inverse_transform(filters_t.reshape(1, -1))[0] + else: + est_t = clf.estimators_[t] + filters_t = get_coef(est_t, "filters_", inverse) + + assert_equal(filters_t, filters[:, t]) + + +def test_get_coef_inverse_step_name(): + """Test get_coef with inverse_transform=True and a specific step_name.""" + X, y, _ = _make_data(n_samples=100, n_features=5, n_targets=1) + + # Test with a simple pipeline + pipe = make_pipeline(StandardScaler(), PCA(n_components=3), LinearModel(Ridge())) + pipe.fit(X, y) + + coef_inv_actual = get_coef( + pipe, attr="patterns_", inverse_transform=True, step_name="linearmodel" + ) + # Reshape your data using array.reshape(1, -1) if it contains a single sample. + coef_raw = pipe.named_steps["linearmodel"].patterns_.reshape(1, -1) + coef_inv_desired = pipe.named_steps["pca"].inverse_transform(coef_raw) + coef_inv_desired = pipe.named_steps["standardscaler"].inverse_transform( + coef_inv_desired + ) + + assert coef_inv_actual.shape == (X.shape[1],) + # Reshape your data using array.reshape(1, -1) if it contains a single sample. + assert_array_almost_equal(coef_inv_actual.reshape(1, -1), coef_inv_desired) + + with pytest.raises(ValueError, match="inverse_transform"): + _ = get_coef( + pipe[-1], # LinearModel + "filters_", + inverse_transform=True, + ) + with pytest.raises(ValueError, match="step_name"): + _ = get_coef( + SlidingEstimator(pipe), + "filters_", + inverse_transform=True, + step_name="slidingestimator__pipeline__linearmodel", + ) + + # Test with a nested pipeline to check __ parsing + inner_pipe = make_pipeline(PCA(n_components=3), LinearModel(Ridge())) + nested_pipe = make_pipeline(StandardScaler(), inner_pipe) + nested_pipe.fit(X, y) + coef_nested_inv_actual = get_coef( + nested_pipe, + attr="patterns_", + inverse_transform=True, + step_name="pipeline__linearmodel", + ) + linearmodel = nested_pipe.named_steps["pipeline"].named_steps["linearmodel"] + pca = nested_pipe.named_steps["pipeline"].named_steps["pca"] + scaler = nested_pipe.named_steps["standardscaler"] + + coef_nested_raw = linearmodel.patterns_.reshape(1, -1) + coef_nested_inv_desired = pca.inverse_transform(coef_nested_raw) + coef_nested_inv_desired = scaler.inverse_transform(coef_nested_inv_desired) + + assert coef_nested_inv_actual.shape == (X.shape[1],) + assert_array_almost_equal( + coef_nested_inv_actual.reshape(1, -1), coef_nested_inv_desired + ) + + with pytest.raises(ValueError, match="i_do_not_exist"): + get_coef( + pipe, attr="patterns_", inverse_transform=True, step_name="i_do_not_exist" + ) + + class NonInvertibleTransformer(BaseEstimator, TransformerMixin): + def fit(self, X, y=None): + return self + + def transform(self, X): + # In a real scenario, this would modify X + return X + + pipe = make_pipeline(NonInvertibleTransformer(), LinearModel(Ridge())) + pipe.fit(X, y) + with pytest.warns(RuntimeWarning, match="not invertible"): + _ = get_coef( + pipe, + "filters_", + inverse_transform=True, + step_name="linearmodel", + ) + + +@pytest.mark.parametrize("n_features", [1, 5]) +@pytest.mark.parametrize("n_targets", [1, 3]) +def test_get_coef_multiclass(n_features, n_targets): + """Test get_coef on multiclass problems.""" + # Check patterns with more than 1 regressor + X, Y, A = _make_data(n_samples=30000, n_features=n_features, n_targets=n_targets) + lm = LinearModel(LinearRegression()) + assert not hasattr(lm, "model_") + lm.fit(X, Y) + assert lm.model is not lm.model_ + assert_array_equal(lm.filters_.shape, lm.patterns_.shape) + if n_targets == 1: + want_shape = (n_features,) + else: + want_shape = (n_targets, n_features) + assert_array_equal(lm.filters_.shape, want_shape) + if n_features > 1 and n_targets > 1: + assert_array_almost_equal(A, lm.patterns_.T, decimal=2) + lm = LinearModel(Ridge(alpha=0)) + clf = make_pipeline(lm) + clf.fit(X, Y) + if n_features > 1 and n_targets > 1: + assert_allclose(A, lm.patterns_.T, atol=2e-2) + coef = get_coef(clf, "patterns_", inverse_transform=True) + assert_allclose(lm.patterns_, coef, atol=1e-5) + + # With epochs, scaler, and vectorizer (typical use case) + X_epo = X.reshape(X.shape + (1,)) + info = create_info(n_features, 1000.0, "eeg") + lm = LinearModel(Ridge(alpha=1)) + clf = make_pipeline( + Scaler(info, scalings=dict(eeg=1.0)), # XXX adding this step breaks + Vectorizer(), + lm, + ) + clf.fit(X_epo, Y) + if n_features > 1 and n_targets > 1: + assert_allclose(A, lm.patterns_.T, atol=2e-2) + coef = get_coef(clf, "patterns_", inverse_transform=True) + + lm_patterns_ = lm.patterns_ + # Expected shape is (n_targets, n_features) + # which is equivalent to (n_components, n_channels) + # in spatial filters + if lm_patterns_.ndim == 1: + lm_patterns_ = lm_patterns_[np.newaxis, :] + else: + lm_patterns_ = lm_patterns_[..., np.newaxis] + assert_allclose(lm_patterns_, coef, atol=1e-5) + + # Check can pass fitting parameters + lm.fit(X, Y, sample_weight=np.ones(len(Y))) + + +@pytest.mark.parametrize( + "n_classes, n_channels, n_times", + [ + (4, 10, 2), + (4, 3, 2), + (3, 2, 1), + (3, 1, 2), + ], +) +def test_get_coef_multiclass_full(n_classes, n_channels, n_times): + """Test a full example with pattern extraction.""" + data = np.zeros((10 * n_classes, n_channels, n_times)) + # Make only the first channel informative + for ii in range(n_classes): + data[ii * 10 : (ii + 1) * 10, 0] = ii + events = np.zeros((len(data), 3), int) + events[:, 0] = np.arange(len(events)) + events[:, 2] = data[:, 0, 0] + info = create_info(n_channels, 1000.0, "eeg") + epochs = EpochsArray(data, info, events, tmin=0) + clf = make_pipeline( + Scaler(epochs.info), + Vectorizer(), + LinearModel(OneVsRestClassifier(LogisticRegression(random_state=0))), + ) + scorer = "roc_auc_ovr_weighted" + time_gen = GeneralizingEstimator(clf, scorer, verbose=True) + X = epochs.get_data(copy=False) + y = epochs.events[:, 2] + n_splits = 3 + cv = StratifiedKFold(n_splits=n_splits) + scores = cross_val_multiscore(time_gen, X, y, cv=cv, verbose=True) + want = (n_splits,) + if n_times > 1: + want += (n_times, n_times) + assert scores.shape == want + # On Windows LBFGS can fail to converge, so we need to be a bit more tol here + limit = 0.7 if platform.system() == "Windows" else 0.8 + assert_array_less(limit, scores) + clf.fit(X, y) + patterns = get_coef(clf, "patterns_", inverse_transform=True) + assert patterns.shape == (n_classes, n_channels, n_times) + assert_allclose(patterns[:, 1:], 0.0, atol=1e-7) # no other channels useful + + +def test_linearmodel(): + """Test LinearModel class for computing filters and patterns.""" + # check categorical target fit in standard linear model + rng = np.random.RandomState(0) + clf = LinearModel() + n, n_features = 20, 3 + X = rng.rand(n, n_features) + y = np.arange(n) % 2 + clf.fit(X, y) + assert_equal(clf.filters_.shape, (n_features,)) + assert_equal(clf.patterns_.shape, (n_features,)) + with pytest.raises(ValueError): + wrong_X = rng.rand(n, n_features, 99) + clf.fit(wrong_X, y) + + # check fit_transform call + clf = LinearModel(LinearDiscriminantAnalysis()) + _ = clf.fit_transform(X, y) + + # check that model has to have coef_, RBF-SVM doesn't + clf = LinearModel(svm.SVC(kernel="rbf")) + with pytest.raises(ValueError, match="does not have a `coef_`"): + clf.fit(X, y) + + # check that model has to be a predictor + clf = LinearModel(StandardScaler()) + with pytest.raises(ValueError, match="classifier or regressor"): + clf.fit(X, y) + + # check categorical target fit in standard linear model with GridSearchCV + parameters = {"kernel": ["linear"], "C": [1, 10]} + clf = LinearModel( + GridSearchCV(svm.SVC(), parameters, cv=2, refit=True, n_jobs=None) + ) + clf.fit(X, y) + assert_equal(clf.filters_.shape, (n_features,)) + assert_equal(clf.patterns_.shape, (n_features,)) + with pytest.raises(ValueError): + wrong_X = rng.rand(n, n_features, 99) + clf.fit(wrong_X, y) + + # check continuous target fit in standard linear model with GridSearchCV + n_targets = 1 + Y = rng.rand(n, n_targets) + clf = LinearModel( + GridSearchCV(svm.SVR(), parameters, cv=2, refit=True, n_jobs=None) + ) + clf.fit(X, y) + assert_equal(clf.filters_.shape, (n_features,)) + assert_equal(clf.patterns_.shape, (n_features,)) + with pytest.raises(ValueError): + wrong_y = rng.rand(n, n_features, 99) + clf.fit(X, wrong_y) + + # check multi-target fit in standard linear model + n_targets = 5 + Y = rng.rand(n, n_targets) + clf = LinearModel(LinearRegression()) + clf.fit(X, Y) + assert_equal(clf.filters_.shape, (n_targets, n_features)) + assert_equal(clf.patterns_.shape, (n_targets, n_features)) + with pytest.raises(ValueError): + wrong_y = rng.rand(n, n_features, 99) + clf.fit(X, wrong_y) + + +def test_cross_val_multiscore(): + """Test cross_val_multiscore for computing scores on decoding over time.""" + logreg = LogisticRegression(solver="liblinear", random_state=0) + + # compare to cross-val-score + X = np.random.rand(20, 3) + y = np.arange(20) % 2 + cv = KFold(2, random_state=0, shuffle=True) + clf = logreg + assert_array_equal( + cross_val_score(clf, X, y, cv=cv), cross_val_multiscore(clf, X, y, cv=cv) + ) + + # Test with search light + X = np.random.rand(20, 4, 3) + y = np.arange(20) % 2 + clf = SlidingEstimator(logreg, scoring="accuracy") + scores_acc = cross_val_multiscore(clf, X, y, cv=cv) + assert_array_equal(np.shape(scores_acc), [2, 3]) + + # check values + scores_acc_manual = list() + for train, test in cv.split(X, y): + clf.fit(X[train], y[train]) + scores_acc_manual.append(clf.score(X[test], y[test])) + assert_array_equal(scores_acc, scores_acc_manual) + + # check scoring metric + # raise an error if scoring is defined at cross-val-score level and + # search light, because search light does not return a 1-dimensional + # prediction. + with pytest.raises(ValueError, match="multi_class must be"): + cross_val_multiscore(clf, X, y, cv=cv, scoring="roc_auc", n_jobs=1) + clf = SlidingEstimator(logreg, scoring="roc_auc") + scores_auc = cross_val_multiscore(clf, X, y, cv=cv, n_jobs=None) + scores_auc_manual = list() + for train, test in cv.split(X, y): + clf.fit(X[train], y[train]) + scores_auc_manual.append(clf.score(X[test], y[test])) + assert_array_equal(scores_auc, scores_auc_manual) + + # indirectly test that cross_val_multiscore rightly detects the type of + # estimator and generates a StratifiedKFold for classiers and a KFold + # otherwise + X = np.random.randn(1000, 3) + y = np.ones(1000, dtype=int) + y[::2] = 0 + clf = logreg + reg = LinearRegression() + for cross_val in (cross_val_score, cross_val_multiscore): + manual = cross_val(clf, X, y, cv=StratifiedKFold(2)) + auto = cross_val(clf, X, y, cv=2) + assert_array_equal(manual, auto) + + manual = cross_val(reg, X, y, cv=KFold(2)) + auto = cross_val(reg, X, y, cv=2) + assert_array_equal(manual, auto) + + +@parametrize_with_checks([LinearModel(LogisticRegression())]) +def test_sklearn_compliance(estimator, check): + """Test LinearModel compliance with sklearn.""" + check(estimator) diff --git a/mne-python/source/mne/decoding/tests/test_csp.py b/mne-python/source/mne/decoding/tests/test_csp.py new file mode 100644 index 0000000000000000000000000000000000000000..f3f5e16cf986e3fd9e78409a54afbdcc29872ed2 --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_csp.py @@ -0,0 +1,499 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_equal, +) + +pytest.importorskip("sklearn") + +from sklearn.linear_model import LogisticRegression +from sklearn.model_selection import StratifiedKFold, cross_val_score +from sklearn.pipeline import Pipeline, make_pipeline +from sklearn.svm import SVC +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne import Epochs, compute_proj_raw, io, pick_types, read_events +from mne.decoding import CSP, LinearModel, Scaler, SPoC, get_coef +from mne.decoding.csp import _ajd_pham +from mne.utils import catch_logging + +data_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = data_dir / "test_raw.fif" +event_name = data_dir / "test-eve.fif" +tmin, tmax = -0.1, 0.2 +event_id = dict(aud_l=1, vis_l=3) +# if stop is too small pca may fail in some cases, but we're okay on this file +start, stop = 0, 8 + + +def simulate_data(target, n_trials=100, n_channels=10, random_state=42): + """Simulate data according to an instantaneous mixin model. + + Data are simulated in the statistical source space, where one source is + modulated according to a target variable, before being mixed with a + random mixing matrix. + """ + rs = np.random.RandomState(random_state) + + # generate a orthogonal mixin matrix + mixing_mat = np.linalg.svd(rs.randn(n_channels, n_channels))[0] + + S = rs.randn(n_trials, n_channels, 50) + S[:, 0] *= np.atleast_2d(np.sqrt(target)).T + S[:, 1:] *= 0.01 # less noise + + X = np.dot(mixing_mat, S).transpose((1, 0, 2)) + + return X, mixing_mat + + +def deterministic_toy_data(classes=("class_a", "class_b")): + """Generate a small deterministic toy data set. + + Four independent sources are modulated by the target class and mixed + into signal space. + """ + sources_a = ( + np.array( + [ + [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], + [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], + [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1], + [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], + ], + dtype=float, + ) + * 2 + - 1 + ) + + sources_b = ( + np.array( + [ + [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1], + [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1], + [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1], + [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], + ], + dtype=float, + ) + * 2 + - 1 + ) + + sources_a[0, :] *= 1 + sources_a[1, :] *= 2 + + sources_b[2, :] *= 3 + sources_b[3, :] *= 4 + + mixing = np.array( + [ + [1.0, 0.8, 0.6, 0.4], + [0.8, 1.0, 0.8, 0.6], + [0.6, 0.8, 1.0, 0.8], + [0.4, 0.6, 0.8, 1.0], + ] + ) + + x_class_a = mixing @ sources_a + x_class_b = mixing @ sources_b + + x = np.stack([x_class_a, x_class_b]) + y = np.array(classes) + + return x, y + + +@pytest.mark.slowtest +def test_csp(): + """Test Common Spatial Patterns algorithm on epochs.""" + raw = io.read_raw_fif(raw_fname, preload=False) + events = read_events(event_name) + picks = pick_types( + raw.info, meg=True, stim=False, ecg=False, eog=False, exclude="bads" + ) + picks = picks[2:12:3] # subselect channels -> disable proj! + raw.add_proj([], remove_existing=True) + epochs = Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + preload=True, + proj=False, + ) + epochs_data = epochs.get_data(copy=False) + n_channels = epochs_data.shape[1] + y = epochs.events[:, -1] + + # Init + csp = CSP(n_components="foo") + with pytest.raises(TypeError, match="must be an instance"): + csp.fit(epochs_data, y) + for reg in ["foo", -0.1, 1.1]: + csp = CSP(reg=reg, norm_trace=False) + pytest.raises(ValueError, csp.fit, epochs_data, epochs.events[:, -1]) + for reg in ["oas", "ledoit_wolf", 0, 0.5, 1.0]: + CSP(reg=reg, norm_trace=False) + csp = CSP(cov_est="foo", norm_trace=False) + with pytest.raises(ValueError, match="Invalid value"): + csp.fit(epochs_data, y) + csp = CSP(norm_trace="foo") + with pytest.raises(TypeError, match="instance of bool"): + csp.fit(epochs_data, y) + for cov_est in ["concat", "epoch"]: + CSP(cov_est=cov_est, norm_trace=False).fit(epochs_data, y) + + n_components = 3 + # Fit + for norm_trace in [True, False]: + csp = CSP(n_components=n_components, norm_trace=norm_trace) + csp.fit(epochs_data, epochs.events[:, -1]) + + assert_equal(len(csp.mean_), n_components) + assert_equal(len(csp.std_), n_components) + + # Transform + X = csp.fit_transform(epochs_data, y) + sources = csp.transform(epochs_data) + assert sources.shape[1] == n_components + assert csp.filters_.shape == (n_channels, n_channels) + assert csp.patterns_.shape == (n_channels, n_channels) + assert_array_almost_equal(sources, X) + + # Test data exception + pytest.raises(ValueError, csp.fit, epochs_data, np.zeros_like(epochs.events)) + pytest.raises(ValueError, csp.fit, "foo", y) + pytest.raises(ValueError, csp.transform, "foo") + + # Test plots + epochs.pick(picks="mag") + cmap = ("RdBu", True) + components = np.arange(n_components) + for plot in (csp.plot_patterns, csp.plot_filters): + plot(epochs.info, components=components, res=12, show=False, cmap=cmap) + + # Test with more than 2 classes + epochs = Epochs( + raw, + events, + tmin=tmin, + tmax=tmax, + picks=picks, + event_id=dict(aud_l=1, aud_r=2, vis_l=3, vis_r=4), + baseline=(None, 0), + proj=False, + preload=True, + ) + epochs_data = epochs.get_data(copy=False) + n_channels = epochs_data.shape[1] + + n_channels = epochs_data.shape[1] + for cov_est in ["concat", "epoch"]: + csp = CSP(n_components=n_components, cov_est=cov_est, norm_trace=False) + csp.fit(epochs_data, epochs.events[:, 2]).transform(epochs_data) + assert_equal(len(csp.classes_), 4) + assert_array_equal(csp.filters_.shape, [n_channels, n_channels]) + assert_array_equal(csp.patterns_.shape, [n_channels, n_channels]) + + # Test average power transform + n_components = 2 + assert csp.transform_into == "average_power" + feature_shape = [len(epochs_data), n_components] + X_trans = dict() + for log in (None, True, False): + csp = CSP(n_components=n_components, log=log, norm_trace=False) + assert csp.log is log + Xt = csp.fit_transform(epochs_data, epochs.events[:, 2]) + assert_array_equal(Xt.shape, feature_shape) + X_trans[str(log)] = Xt + # log=None => log=True + assert_array_almost_equal(X_trans["None"], X_trans["True"]) + # Different normalization return different transform + assert np.sum((X_trans["True"] - X_trans["False"]) ** 2) > 1.0 + # Check wrong inputs + csp = CSP(transform_into="average_power", log="foo") + with pytest.raises(TypeError, match="must be an instance of bool"): + csp.fit(epochs_data, epochs.events[:, 2]) + + # Test csp space transform + csp = CSP(transform_into="csp_space", norm_trace=False) + assert csp.transform_into == "csp_space" + for log in ("foo", True, False): + csp = CSP(transform_into="csp_space", log=log, norm_trace=False) + with pytest.raises(TypeError, match="must be an instance"): + csp.fit(epochs_data, epochs.events[:, 2]) + n_components = 2 + csp = CSP(n_components=n_components, transform_into="csp_space", norm_trace=False) + Xt = csp.fit(epochs_data, epochs.events[:, 2]).transform(epochs_data) + feature_shape = [len(epochs_data), n_components, epochs_data.shape[2]] + assert_array_equal(Xt.shape, feature_shape) + + # Check mixing matrix on simulated data + y = np.array([100] * 50 + [1] * 50) + X, A = simulate_data(y) + + for cov_est in ["concat", "epoch"]: + # fit csp + csp = CSP(n_components=1, cov_est=cov_est, norm_trace=False) + csp.fit(X, y) + + # check the first pattern match the mixing matrix + # the sign might change + corr = np.abs(np.corrcoef(csp.patterns_[0, :].T, A[:, 0])[0, 1]) + assert np.abs(corr) > 0.99 + + # check output + out = csp.transform(X) + corr = np.abs(np.corrcoef(out[:, 0], y)[0, 1]) + assert np.abs(corr) > 0.95 + + +# Even the "reg is None and rank is None" case should pass now thanks to the +# do_compute_rank +@pytest.mark.parametrize("ch_type", ("mag", "eeg", ("mag", "eeg"))) +@pytest.mark.parametrize("rank", (None, "full", "correct")) +@pytest.mark.parametrize("reg", [None, 0.001, "oas"]) +def test_regularized_csp(ch_type, rank, reg): + """Test Common Spatial Patterns algorithm using regularized covariance.""" + raw = io.read_raw_fif(raw_fname).pick(ch_type, exclude="bads").load_data() + n_orig = len(raw.ch_names) + ch_decim = 2 + raw.pick_channels(raw.ch_names[::ch_decim]) + raw.info.normalize_proj() + if "eeg" in ch_type: + raw.set_eeg_reference(projection=True) + # TODO: for some reason we need to add a second EEG projector in order to get + # the non-semidefinite error for EEG data. Hopefully this won't make much + # difference in practice given our default is rank=None and regularization + # is easy to use. + raw.add_proj(compute_proj_raw(raw, n_eeg=1, n_mag=0, n_grad=0, n_jobs=1)) + n_eig = len(raw.ch_names) - len(raw.info["projs"]) + n_ch = n_orig // ch_decim + if ch_type == "eeg": + assert n_eig == n_ch - 2 + elif ch_type == "mag": + assert n_eig == n_ch - 3 + else: + assert n_eig == n_ch - 5 + if rank == "correct": + if isinstance(ch_type, str): + rank = {ch_type: n_eig} + else: + assert ch_type == ("mag", "eeg") + rank = dict( + mag=102 // ch_decim - 3, + eeg=60 // ch_decim - 2, + ) + else: + assert rank is None or rank == "full", rank + if rank == "full": + n_eig = n_ch + raw.filter(2, 40).apply_proj() + events = read_events(event_name) + # map make left and right events the same + events[events[:, 2] == 2, 2] = 1 + events[events[:, 2] == 4, 2] = 3 + epochs = Epochs(raw, events, event_id, tmin, tmax, decim=5, preload=True) + epochs.equalize_event_counts() + assert 25 < len(epochs) < 30 + epochs_data = epochs.get_data(copy=False) + n_channels = epochs_data.shape[1] + assert n_channels == n_ch + n_components = 3 + + sc = Scaler(epochs.info) + epochs_data_orig = epochs_data.copy() + epochs_data = sc.fit_transform(epochs_data) + csp = CSP(n_components=n_components, reg=reg, norm_trace=False, rank=rank) + if rank == "full" and reg is None: + with pytest.raises(np.linalg.LinAlgError, match="leading minor"): + csp.fit(epochs_data, epochs.events[:, -1]) + return + with catch_logging(verbose=True) as log: + X = csp.fit_transform(epochs_data, epochs.events[:, -1]) + log = log.getvalue() + assert "Setting small MAG" not in log + if rank != "full": + assert "Setting small data eigen" in log + else: + assert "Setting small data eigen" not in log + if rank is None: + assert "Computing rank from data" in log + assert " mag: rank" not in log.lower() + assert " data: rank" in log + assert "rank (mag)" not in log.lower() + assert "rank (data)" in log + elif rank != "full": # if rank is passed no computation is done + assert "Computing rank" not in log + assert ": rank" not in log + assert "rank (" not in log + assert "reducing mag" not in log.lower() + assert f"Reducing data rank from {n_channels} " in log + y = epochs.events[:, -1] + assert csp.filters_.shape == (n_eig, n_channels) + assert csp.patterns_.shape == (n_eig, n_channels) + assert_array_almost_equal(csp.fit(epochs_data, y).transform(epochs_data), X) + + # test init exception + pytest.raises(ValueError, csp.fit, epochs_data, np.zeros_like(epochs.events)) + pytest.raises(ValueError, csp.fit, "foo", y) + pytest.raises(ValueError, csp.transform, "foo") + + csp.n_components = n_components + sources = csp.transform(epochs_data) + assert sources.shape[1] == n_components + + cv = StratifiedKFold(5) + clf = make_pipeline( + sc, + csp, + LinearModel(LogisticRegression(solver="liblinear")), + ) + score = cross_val_score(clf, epochs_data_orig, y, cv=cv, scoring="roc_auc").mean() + assert 0.75 <= score <= 1.0 + + # Test get_coef on CSP + clf.fit(epochs_data_orig, y) + coef = csp.patterns_[:n_components] + assert coef.shape == (n_components, n_channels), coef.shape + coef = sc.inverse_transform(coef.T[np.newaxis])[0] + assert coef.shape == (len(epochs.ch_names), n_components), coef.shape + coef_mne = get_coef(clf, "patterns_", inverse_transform=True, verbose="debug") + assert coef.shape == coef_mne.shape + coef_mne /= np.linalg.norm(coef_mne, axis=0) + coef /= np.linalg.norm(coef, axis=0) + coef *= np.sign(np.sum(coef_mne * coef, axis=0)) + assert_allclose(coef_mne, coef) + + +def test_csp_pipeline(): + """Test if CSP works in a pipeline.""" + csp = CSP(reg=1, norm_trace=False) + svc = SVC() + pipe = Pipeline([("CSP", csp), ("SVC", svc)]) + pipe.set_params(CSP__reg=0.2) + assert pipe.get_params()["CSP__reg"] == 0.2 + + +def test_ajd(): + """Test approximate joint diagonalization.""" + # The implementation should obtain the same + # results as the Matlab implementation by Pham Dinh-Tuan. + # Generate a set of cavariances matrices for test purpose + n_times, n_channels = 10, 3 + seed = np.random.RandomState(0) + diags = 2.0 + 0.1 * seed.randn(n_times, n_channels) + A = 2 * seed.rand(n_channels, n_channels) - 1 + A /= np.atleast_2d(np.sqrt(np.sum(A**2, 1))).T + covmats = np.empty((n_times, n_channels, n_channels)) + for i in range(n_times): + covmats[i] = np.dot(np.dot(A, np.diag(diags[i])), A.T) + V, D = _ajd_pham(covmats) + # Results obtained with original matlab implementation + V_matlab = [ + [-3.507280775058041, -5.498189967306344, 7.720624541198574], + [0.694689013234610, 0.775690358505945, -1.162043086446043], + [-0.592603135588066, -0.598996925696260, 1.009550086271192], + ] + assert_array_almost_equal(V, V_matlab) + + +def test_spoc(): + """Test SPoC.""" + X = np.random.randn(10, 10, 20) + y = np.random.randn(10) + + spoc = SPoC(n_components=4) + spoc.fit(X, y) + Xt = spoc.transform(X) + assert_array_equal(Xt.shape, [10, 4]) + spoc = SPoC(n_components=4, transform_into="csp_space") + spoc.fit(X, y) + Xt = spoc.transform(X) + assert_array_equal(Xt.shape, [10, 4, 20]) + assert_array_equal(spoc.filters_.shape, [10, 10]) + assert_array_equal(spoc.patterns_.shape, [10, 10]) + + # check y + pytest.raises(ValueError, spoc.fit, X, y * 0) + + # Check that doesn't take CSP-specific input + pytest.raises(TypeError, SPoC, cov_est="epoch") + + # Check mixing matrix on simulated data + rs = np.random.RandomState(42) + y = rs.rand(100) * 50 + 1 + X, A = simulate_data(y) + + # fit spoc + spoc = SPoC(n_components=1) + spoc.fit(X, y) + + # check the first patterns match the mixing matrix + corr = np.abs(np.corrcoef(spoc.patterns_[0, :].T, A[:, 0])[0, 1]) + assert np.abs(corr) > 0.99 + + # check output + out = spoc.transform(X) + corr = np.abs(np.corrcoef(out[:, 0], y)[0, 1]) + assert np.abs(corr) > 0.85 + + +def test_csp_twoclass_symmetry(): + """Test that CSP is symmetric when swapping classes.""" + x, y = deterministic_toy_data(["class_a", "class_b"]) + csp = CSP(norm_trace=False, transform_into="average_power", log=True) + log_power = csp.fit_transform(x, y) + log_power_ratio_ab = log_power[0] - log_power[1] + + x, y = deterministic_toy_data(["class_b", "class_a"]) + csp = CSP(norm_trace=False, transform_into="average_power", log=True) + log_power = csp.fit_transform(x, y) + log_power_ratio_ba = log_power[0] - log_power[1] + + assert_array_almost_equal(log_power_ratio_ab, log_power_ratio_ba) + + +def test_csp_component_ordering(): + """Test that CSP component ordering works as expected.""" + x, y = deterministic_toy_data(["class_a", "class_b"]) + + csp = CSP(component_order="invalid") + with pytest.raises(ValueError, match="Invalid value"): + csp.fit(x, y) + + # component_order='alternate' only works with two classes + csp = CSP(component_order="alternate") + with pytest.raises(ValueError): + csp.fit(np.zeros((3, 0, 0)), ["a", "b", "c"]) + + p_alt = CSP(component_order="alternate").fit(x, y).patterns_ + p_mut = CSP(component_order="mutual_info").fit(x, y).patterns_ + + # This permutation of p_alt and p_mut is explained by the particular + # eigenvalues of the toy data: [0.06, 0.1, 0.5, 0.8]. + # p_alt arranges them to [0.8, 0.06, 0.5, 0.1] + # p_mut arranges them to [0.06, 0.1, 0.8, 0.5] + assert_array_almost_equal(p_alt, p_mut[[2, 0, 3, 1]]) + + +@pytest.mark.filterwarnings("ignore:.*Only one sample available.*") +@parametrize_with_checks([CSP(), SPoC()]) +def test_sklearn_compliance(estimator, check): + """Test compliance with sklearn.""" + pytest.importorskip("sklearn", minversion="1.5") # TODO VERSION remove on 1.5+ + check(estimator) diff --git a/mne-python/source/mne/decoding/tests/test_ems.py b/mne-python/source/mne/decoding/tests/test_ems.py new file mode 100644 index 0000000000000000000000000000000000000000..6dadf5094c3b0f317f7e9fde46ea69fc5ab583ac --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_ems.py @@ -0,0 +1,101 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_array_almost_equal, assert_equal + +pytest.importorskip("sklearn") + +from sklearn.model_selection import StratifiedKFold +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne import Epochs, io, pick_types, read_events +from mne.decoding import EMS, compute_ems + +data_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = data_dir / "test_raw.fif" +event_name = data_dir / "test-eve.fif" +tmin, tmax = -0.2, 0.5 +event_id = dict(aud_l=1, vis_l=3) + + +def test_ems(): + """Test event-matched spatial filters.""" + raw = io.read_raw_fif(raw_fname, preload=False) + + # create unequal number of events + events = read_events(event_name) + events[-2, 2] = 3 + picks = pick_types( + raw.info, meg=True, stim=False, ecg=False, eog=False, exclude="bads" + ) + picks = picks[1:13:3] + epochs = Epochs( + raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), preload=True + ) + pytest.raises(ValueError, compute_ems, epochs, ["aud_l", "vis_l"]) + epochs.equalize_event_counts(epochs.event_id) + + pytest.raises(KeyError, compute_ems, epochs, ["blah", "hahah"]) + surrogates, filters, conditions = compute_ems(epochs) + assert_equal(list(set(conditions)), [1, 3]) + + events = read_events(event_name) + event_id2 = dict(aud_l=1, aud_r=2, vis_l=3) + epochs = Epochs( + raw, + events, + event_id2, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + preload=True, + ) + epochs.equalize_event_counts(epochs.event_id) + + n_expected = sum([len(epochs[k]) for k in ["aud_l", "vis_l"]]) + + pytest.raises(ValueError, compute_ems, epochs) + surrogates, filters, conditions = compute_ems(epochs, ["aud_r", "vis_l"]) + assert_equal(n_expected, len(surrogates)) + assert_equal(n_expected, len(conditions)) + assert_equal(list(set(conditions)), [2, 3]) + + # test compute_ems cv + epochs = epochs["aud_r", "vis_l"] + epochs.equalize_event_counts(epochs.event_id) + cv = StratifiedKFold(n_splits=3) + compute_ems(epochs, cv=cv) + compute_ems(epochs, cv=2) + pytest.raises(ValueError, compute_ems, epochs, cv="foo") + pytest.raises(ValueError, compute_ems, epochs, cv=len(epochs) + 1) + raw.close() + + # EMS transformer, check that identical to compute_ems + X = epochs.get_data(copy=False) + y = epochs.events[:, 2] + X = X / np.std(X) # X scaled outside cv in compute_ems + Xt, coefs = list(), list() + ems = EMS() + assert_equal(ems.__repr__(), "") + # manual leave-one-out to avoid sklearn version problem + for test in range(len(y)): + train = np.setdiff1d(range(len(y)), np.atleast_1d(test)) + ems.fit(X[train], y[train]) + coefs.append(ems.filters_) + Xt.append(ems.transform(X[[test]])) + assert_equal(ems.__repr__(), "") + assert_array_almost_equal(filters, np.mean(coefs, axis=0)) + assert_array_almost_equal(surrogates, np.vstack(Xt)) + + +@parametrize_with_checks([EMS()]) +def test_sklearn_compliance(estimator, check): + """Test compliance with sklearn.""" + pytest.importorskip("sklearn", minversion="1.6") # TODO VERSION remove on 1.6+ + check(estimator) diff --git a/mne-python/source/mne/decoding/tests/test_ged.py b/mne-python/source/mne/decoding/tests/test_ged.py new file mode 100644 index 0000000000000000000000000000000000000000..1d951dbf0c1dfc3fda5a3371b69bc3f4473f7dbd --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_ged.py @@ -0,0 +1,376 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from functools import partial +from pathlib import Path + +import numpy as np +import pytest + +pytest.importorskip("sklearn") + + +from sklearn.model_selection import ParameterGrid +from sklearn.utils._testing import assert_allclose +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne import Epochs, compute_rank, create_info, pick_types, read_events +from mne._fiff.proj import make_eeg_average_ref_proj +from mne.cov import Covariance, _regularized_covariance +from mne.decoding._ged import ( + _get_cov_def, + _get_restr_mat, + _handle_restr_mat, + _is_cov_symm, + _smart_ajd, + _smart_ged, +) +from mne.decoding._mod_ged import _no_op_mod +from mne.decoding.base import _GEDTransformer +from mne.io import read_raw + +data_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = data_dir / "test_raw.fif" +event_name = data_dir / "test-eve.fif" +tmin, tmax = -0.1, 0.2 +# if stop is too small pca may fail in some cases, but we're okay on this file +start, stop = 0, 8 + + +def _mock_info(n_channels): + info = create_info(n_channels, 1000.0, "eeg") + avg_eeg_projector = make_eeg_average_ref_proj(info=info, activate=False) + info["projs"].append(avg_eeg_projector) + return info + + +def _get_min_rank(covs, info): + min_rank = dict( + eeg=min( + list( + compute_rank( + Covariance( + cov, + info.ch_names, + list(), + list(), + 0, + # verbose=_verbose_safe_false(), + ), + rank=None, + # _handle_default("scalings_cov_rank", None), + info=info, + ).values() + )[0] + for cov in covs + ) + ) + return min_rank + + +def _mock_cov_callable(X, y, cov_method_params=None, compute_C_ref=True): + if cov_method_params is None: + cov_method_params = dict() + n_epochs, n_channels, n_times = X.shape + + # To pass sklearn check: + if n_channels == 1: + n_channels = 2 + X = np.tile(X, (1, n_channels, 1)) + + # To make covariance estimation sensible + if n_times == 1: + n_times = n_channels + X = np.tile(X, (1, 1, n_channels)) + + classes = np.unique(y) + covs, sample_weights = list(), list() + for ci, this_class in enumerate(classes): + class_data = X[y == this_class] + class_data = class_data.transpose(1, 0, 2).reshape(n_channels, -1) + cov = _regularized_covariance(class_data, **cov_method_params) + covs.append(cov) + sample_weights.append(class_data.shape[0]) + + ref_data = X.transpose(1, 0, 2).reshape(n_channels, -1) + if compute_C_ref: + C_ref = _regularized_covariance(ref_data, **cov_method_params) + else: + C_ref = None + info = _mock_info(n_channels) + rank = _get_min_rank(covs, info) + kwargs = dict() + + # To pass sklearn check: + if len(covs) == 1: + covs.append(covs[0]) + + elif len(covs) > 2: + kwargs["sample_weights"] = sample_weights + return covs, C_ref, info, rank, kwargs + + +def _mock_mod_ged_callable(evals, evecs, covs, **kwargs): + sorter = None + if evals is not None: + ix = np.argsort(evals)[::-1] + evals = evals[ix] + evecs = evecs[:, ix] + sorter = ix + return evals, evecs, sorter + + +param_grid = dict( + n_components=[4], + cov_callable=[partial(_mock_cov_callable, cov_method_params=dict(reg="empirical"))], + mod_ged_callable=[_mock_mod_ged_callable], + dec_type=["single", "multi"], + restr_type=["restricting", "whitening"], + R_func=[None, partial(np.sum, axis=0)], +) + +ged_estimators = [_GEDTransformer(**p) for p in ParameterGrid(param_grid)] + + +@pytest.mark.slowtest +@parametrize_with_checks(ged_estimators) +def test_sklearn_compliance(estimator, check): + """Test GEDTransformer compliance with sklearn.""" + check(estimator) + + +def _get_X_y(event_id): + raw = read_raw(raw_fname, preload=False) + events = read_events(event_name) + picks = pick_types( + raw.info, meg=True, stim=False, ecg=False, eog=False, exclude="bads" + ) + picks = picks[2:12:3] # subselect channels -> disable proj! + raw.add_proj([], remove_existing=True) + epochs = Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + preload=True, + proj=False, + ) + X = epochs.get_data(copy=False, units=dict(eeg="uV", grad="fT/cm", mag="fT")) + y = epochs.events[:, -1] + return X, y + + +def test_ged_binary_cov(): + """Test GEDTransformer on audvis dataset with two covariances.""" + event_id = dict(aud_l=1, vis_l=3) + X, y = _get_X_y(event_id) + # Test "single" decomposition + covs, C_ref, info, rank, kwargs = _mock_cov_callable(X, y) + S, R = covs[0], covs[1] + restr_mat = _get_restr_mat(C_ref, info, rank) + evals, evecs = _smart_ged(S, R, restr_mat=restr_mat, R_func=None) + actual_evals, actual_evecs, sorter = _mock_mod_ged_callable( + evals, evecs, [S, R], **kwargs + ) + actual_filters = actual_evecs.T + + ged = _GEDTransformer( + n_components=4, + cov_callable=_mock_cov_callable, + mod_ged_callable=_mock_mod_ged_callable, + restr_type="restricting", + ) + ged.fit(X, y) + desired_evals = ged.evals_ + desired_filters = ged.filters_ + + assert_allclose(actual_evals, desired_evals) + assert_allclose(actual_filters, desired_filters) + + # Test "multi" decomposition (loop), restr_mat can be reused + all_evals, all_evecs = list(), list() + for i in range(len(covs)): + S = covs[i] + evals, evecs = _smart_ged(S, R, restr_mat) + evals, evecs, sorter = _mock_mod_ged_callable(evals, evecs, covs) + all_evals.append(evals) + all_evecs.append(evecs.T) + actual_evals = np.array(all_evals) + actual_filters = np.array(all_evecs) + + ged = _GEDTransformer( + n_components=4, + cov_callable=_mock_cov_callable, + mod_ged_callable=_mock_mod_ged_callable, + dec_type="multi", + restr_type="restricting", + ) + ged.fit(X, y) + desired_evals = ged.evals_ + desired_filters = ged.filters_ + + assert_allclose(actual_evals, desired_evals) + assert_allclose(actual_filters, desired_filters) + + assert ged._subset_multi_components(name="foo") is None + + +def test_ged_multicov(): + """Test GEDTransformer on audvis dataset with multiple covariances.""" + event_id = dict(aud_l=1, aud_r=2, vis_l=3, vis_r=4) + X, y = _get_X_y(event_id) + # Test "single" decomposition for multicov (AJD) with C_ref + covs, C_ref, info, rank, kwargs = _mock_cov_callable(X, y) + restr_mat = _get_restr_mat(C_ref, info, rank) + evecs = _smart_ajd(covs, restr_mat=restr_mat) + evals = None + _, actual_evecs, _ = _mock_mod_ged_callable(evals, evecs, covs, **kwargs) + actual_filters = actual_evecs.T + + ged = _GEDTransformer( + n_components=4, + cov_callable=_mock_cov_callable, + mod_ged_callable=_mock_mod_ged_callable, + restr_type="restricting", + ) + ged.fit(X, y) + desired_filters = ged.filters_ + + assert_allclose(actual_filters, desired_filters) + + # Test "multi" decomposition for multicov (loop) + R = covs[-1] + all_evals, all_evecs = list(), list() + for i in range(len(covs)): + S = covs[i] + evals, evecs = _smart_ged(S, R, restr_mat) + evals, evecs, sorter = _mock_mod_ged_callable(evals, evecs, covs) + all_evals.append(evals) + all_evecs.append(evecs.T) + actual_evals = np.array(all_evals) + actual_filters = np.array(all_evecs) + + ged = _GEDTransformer( + n_components=4, + cov_callable=_mock_cov_callable, + mod_ged_callable=_mock_mod_ged_callable, + dec_type="multi", + restr_type="restricting", + ) + ged.fit(X, y) + desired_evals = ged.evals_ + desired_filters = ged.filters_ + + assert_allclose(actual_evals, desired_evals) + assert_allclose(actual_filters, desired_filters) + + # Test "single" decomposition for multicov (AJD) without C_ref + covs, C_ref, info, rank, kwargs = _mock_cov_callable( + X, y, cov_method_params=dict(reg="oas"), compute_C_ref=False + ) + covs = np.stack(covs) + evecs = _smart_ajd(covs, restr_mat=None) + evals = None + _, actual_evecs, _ = _mock_mod_ged_callable(evals, evecs, covs, **kwargs) + actual_filters = actual_evecs.T + + ged = _GEDTransformer( + n_components=4, + cov_callable=partial( + _mock_cov_callable, cov_method_params=dict(reg="oas"), compute_C_ref=False + ), + mod_ged_callable=_mock_mod_ged_callable, + restr_type="restricting", + ) + ged.fit(X, y) + desired_filters = ged.filters_ + + assert_allclose(actual_filters, desired_filters) + + +def test_ged_validation_raises(): + """Test GEDTransofmer validation raises correct errors.""" + event_id = dict(aud_l=1, vis_l=3) + X, y = _get_X_y(event_id) + + ged = _GEDTransformer( + n_components=-1, + cov_callable=_mock_cov_callable, + mod_ged_callable=_mock_mod_ged_callable, + restr_type="restricting", + ) + with pytest.raises(ValueError): + ged.fit(X, y) + + def _bad_cov_callable(X, y, foo): + return X, y, foo + + ged = _GEDTransformer( + n_components=1, + cov_callable=_bad_cov_callable, + mod_ged_callable=_mock_mod_ged_callable, + restr_type="restricting", + ) + with pytest.raises(ValueError): + ged.fit(X, y) + + +def test_ged_invalid_cov(): + """Test _validate_covariances raises proper errors.""" + ged = _GEDTransformer( + n_components=1, + cov_callable=_mock_cov_callable, + mod_ged_callable=_mock_mod_ged_callable, + ) + asymm_cov = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + with pytest.raises(ValueError, match="not symmetric"): + ged._validate_covariances([asymm_cov, None]) + + +def test__handle_restr_mat_invalid_restr_type(): + """Test _handle_restr_mat raises correct error when wrong restr_type.""" + C_ref = np.eye(3) + with pytest.raises(ValueError, match="restr_type"): + _handle_restr_mat(C_ref, restr_type="blah", info=None, rank=None) + + +def test_cov_validators(): + """Test that covariance validators indeed validate.""" + asymm_indef = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + sing_pos_semidef = np.array([[1, 2, 3], [2, 4, 6], [3, 6, 9]]) + pos_def = np.array([[5, 1, 1], [1, 6, 2], [1, 2, 7]]) + + assert not _is_cov_symm(asymm_indef) + assert _get_cov_def(asymm_indef) == "indef" + assert _get_cov_def(sing_pos_semidef) == "pos_semidef" + assert _get_cov_def(pos_def) == "pos_def" + + +def test__smart_ajd_raises(): + """Test _smart_ajd raises proper ValueErrors.""" + asymm_indef = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) + sing_pos_semidef = np.array([[1, 2, 3], [2, 4, 6], [3, 6, 9]]) + pos_def1 = np.array([[5, 1, 1], [1, 6, 2], [1, 2, 7]]) + pos_def2 = np.array([[10, 1, 2], [1, 12, 3], [2, 3, 15]]) + + bad_covs = np.stack([sing_pos_semidef, asymm_indef, pos_def1]) + with pytest.raises(ValueError, match="positive semi-definite"): + _smart_ajd(bad_covs, restr_mat=pos_def2, weights=None) + + bad_covs = np.stack([sing_pos_semidef, pos_def1, pos_def2]) + with pytest.raises(ValueError, match="positive definite"): + _smart_ajd(bad_covs, restr_mat=None, weights=None) + + +def test__no_op_mod(): + """Test _no_op_mod returns the same evals/evecs objects.""" + evals = np.array([[1, 2], [3, 4]]) + evecs = np.array([0, 1]) + evals_no_op, evecs_no_op, sorter_no_op = _no_op_mod(evals, evecs) + assert evals is evals_no_op + assert evecs is evecs_no_op + assert sorter_no_op is None diff --git a/mne-python/source/mne/decoding/tests/test_receptive_field.py b/mne-python/source/mne/decoding/tests/test_receptive_field.py new file mode 100644 index 0000000000000000000000000000000000000000..e1d6de8166bb33a7f89541e3c916f5d505906616 --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_receptive_field.py @@ -0,0 +1,618 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import numpy as np +import pytest +from numpy import einsum +from numpy.fft import irfft, rfft +from numpy.testing import assert_allclose, assert_array_equal, assert_equal + +pytest.importorskip("sklearn") + +from sklearn.linear_model import Ridge +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne.decoding import ReceptiveField, TimeDelayingRidge +from mne.decoding.receptive_field import ( + _SCORERS, + _delay_time_series, + _delays_to_slice, + _times_to_delays, +) +from mne.decoding.time_delaying_ridge import _compute_corrs, _compute_reg_neighbors +from mne.fixes import _reshape_view + +data_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = data_dir / "test_raw.fif" +event_name = data_dir / "test-eve.fif" + +tmin, tmax = -0.1, 0.5 +event_id = dict(aud_l=1, vis_l=3) + +# Loading raw data +n_jobs_test = (1, "cuda") + + +def test_compute_reg_neighbors(): + """Test fast calculation of laplacian regularizer.""" + for reg_type in ( + ("ridge", "ridge"), + ("ridge", "laplacian"), + ("laplacian", "ridge"), + ("laplacian", "laplacian"), + ): + for n_ch_x, n_delays in ( + (1, 1), + (1, 2), + (2, 1), + (1, 3), + (3, 1), + (1, 4), + (4, 1), + (2, 2), + (2, 3), + (3, 2), + (3, 3), + (2, 4), + (4, 2), + (3, 4), + (4, 3), + (4, 4), + (5, 4), + (4, 5), + (5, 5), + (20, 9), + (9, 20), + ): + for normed in (True, False): + reg_direct = _compute_reg_neighbors( + n_ch_x, n_delays, reg_type, "direct", normed=normed + ) + reg_csgraph = _compute_reg_neighbors( + n_ch_x, n_delays, reg_type, "csgraph", normed=normed + ) + assert_allclose( + reg_direct, + reg_csgraph, + atol=1e-7, + err_msg=f"{reg_type}: {(n_ch_x, n_delays)}", + ) + + +def test_rank_deficiency(): + """Test signals that are rank deficient.""" + # See GH#4253 + N = 256 + fs = 1.0 + tmin, tmax = -50, 100 + reg = 0.1 + rng = np.random.RandomState(0) + eeg = rng.randn(N, 1) + eeg *= 100 + eeg = rfft(eeg, axis=0) + eeg[N // 4 :] = 0 # rank-deficient lowpass + eeg = irfft(eeg, axis=0) + win = np.hanning(N // 8) + win /= win.mean() + y = np.apply_along_axis(np.convolve, 0, eeg, win, mode="same") + y += rng.randn(*y.shape) * 100 + + for est in (Ridge(reg), reg): + rf = ReceptiveField(tmin, tmax, fs, estimator=est, patterns=True) + rf.fit(eeg, y) + pred = rf.predict(eeg) + assert_equal(y.shape, pred.shape) + corr = np.corrcoef(y.ravel(), pred.ravel())[0, 1] + assert corr > 0.995 + + +def test_time_delay(): + """Test that time-delaying w/ times and samples works properly.""" + # Explicit delays + sfreq + X = np.random.RandomState(0).randn(1000, 2) + assert (X == 0).sum() == 0 # need this for later + test_tlims = [ + ((1, 2), 1), + ((1, 1), 1), + ((0, 2), 1), + ((0, 1), 1), + ((0, 0), 1), + ((-1, 2), 1), + ((-1, 1), 1), + ((-1, 0), 1), + ((-1, -1), 1), + ((-2, 2), 1), + ((-2, 1), 1), + ((-2, 0), 1), + ((-2, -1), 1), + ((-2, -1), 1), + ((0, 0.2), 10), + ((-0.1, 0.1), 10), + ] + for (tmin, tmax), isfreq in test_tlims: + # sfreq must be int/float + with pytest.raises(TypeError, match="`sfreq` must be an instance of"): + _delay_time_series(X, tmin, tmax, sfreq=[1]) + # Delays must be int/float + with pytest.raises(TypeError, match=".*complex.*"): + _delay_time_series(X, np.complex128(tmin), tmax, 1) + # Make sure swapaxes works + start, stop = int(round(tmin * isfreq)), int(round(tmax * isfreq)) + 1 + n_delays = stop - start + X_delayed = _delay_time_series(X, tmin, tmax, isfreq) + assert_equal(X_delayed.shape, (1000, 2, n_delays)) + # Make sure delay slice is correct + delays = _times_to_delays(tmin, tmax, isfreq) + assert_array_equal(delays, np.arange(start, stop)) + keep = _delays_to_slice(delays) + expected = np.where((X_delayed != 0).all(-1).all(-1))[0] + got = np.arange(len(X_delayed))[keep] + assert_array_equal(got, expected) + assert X_delayed[keep].shape[-1] > 0 + assert (X_delayed[keep] == 0).sum() == 0 + + del_zero = int(round(-tmin * isfreq)) + for ii in range(-2, 3): + idx = del_zero + ii + err_msg = f"[{tmin},{tmax}] ({isfreq}): {ii} {idx}" + if 0 <= idx < X_delayed.shape[-1]: + if ii == 0: + assert_array_equal(X_delayed[:, :, idx], X, err_msg=err_msg) + elif ii < 0: # negative delay + assert_array_equal( + X_delayed[:ii, :, idx], X[-ii:, :], err_msg=err_msg + ) + assert_array_equal(X_delayed[ii:, :, idx], 0.0) + else: + assert_array_equal( + X_delayed[ii:, :, idx], X[:-ii, :], err_msg=err_msg + ) + assert_array_equal(X_delayed[:ii, :, idx], 0.0) + + +@pytest.mark.slowtest # slow on Azure +@pytest.mark.parametrize("n_jobs", n_jobs_test) +@pytest.mark.filterwarnings("ignore:Estimator .* has no __sklearn_tags__.*") +@pytest.mark.filterwarnings("ignore:The following error was .*__sklearn_tags__.*") +def test_receptive_field_basic(n_jobs): + """Test model prep and fitting.""" + # Make sure estimator pulling works + mod = Ridge() + rng = np.random.RandomState(1337) + + # Test the receptive field model + # Define parameters for the model and simulate inputs + weights + tmin, tmax = -10.0, 0 + n_feats = 3 + rng = np.random.RandomState(0) + X = rng.randn(10000, n_feats) + w = rng.randn(int((tmax - tmin) + 1) * n_feats) + + # Delay inputs and cut off first 4 values since they'll be cut in the fit + X_del = np.concatenate( + _delay_time_series(X, tmin, tmax, 1.0).transpose(2, 0, 1), axis=1 + ) + y = np.dot(X_del, w) + + # Fit the model and test values + feature_names = [f"feature_{ii}" for ii in [0, 1, 2]] + rf = ReceptiveField(tmin, tmax, 1, feature_names, estimator=mod, patterns=True) + rf.fit(X, y) + assert rf.coef_.shape == (3, 11) + assert_array_equal(rf.delays_, np.arange(tmin, tmax + 1)) + + y_pred = rf.predict(X) + assert_allclose(y[rf.valid_samples_], y_pred[rf.valid_samples_], atol=1e-2) + scores = rf.score(X, y) + assert scores > 0.99 + assert_allclose(rf.coef_.T.ravel(), w, atol=1e-3) + # Make sure different input shapes work + rf.fit(X[:, np.newaxis :], y[:, np.newaxis]) + rf.fit(X, y[:, np.newaxis]) + with pytest.raises(ValueError, match="If X has 3 .* y must have 2 or 3"): + rf.fit(X[..., np.newaxis], y) + with pytest.raises(ValueError, match="X must be shape"): + rf.fit(X[:, 0], y) + with pytest.raises(ValueError, match="X and y do not have the same n_epo"): + rf.fit(X[:, np.newaxis], np.tile(y[:, np.newaxis, np.newaxis], [1, 2, 1])) + with pytest.raises(ValueError, match="X and y do not have the same n_tim"): + rf.fit(X, y[:-2]) + with pytest.raises(ValueError, match="n_features in X does not match"): + rf.fit(X[:, :1], y) + # auto-naming features + feature_names = [f"feature_{ii}" for ii in [0, 1, 2]] + rf = ReceptiveField(tmin, tmax, 1, estimator=mod, feature_names=feature_names) + assert_equal(rf.feature_names, feature_names) + rf = ReceptiveField(tmin, tmax, 1, estimator=mod) + rf.fit(X, y) + assert_equal(rf.feature_names, None) + # Float becomes ridge + rf = ReceptiveField(tmin, tmax, 1, ["one", "two", "three"], estimator=0) + str(rf) # repr works before fit + rf.fit(X, y) + assert isinstance(rf.estimator_, TimeDelayingRidge) + str(rf) # repr works after fit + rf = ReceptiveField(tmin, tmax, 1, ["one"], estimator=0) + rf.fit(X[:, [0]], y) + str(rf) # repr with one feature + # Should only accept estimators or floats + with pytest.raises((ValueError, AttributeError)): + ReceptiveField(tmin, tmax, 1, estimator="foo").fit(X, y) + with pytest.raises((ValueError, AttributeError)): + ReceptiveField(tmin, tmax, 1, estimator=np.array([1, 2, 3])).fit(X, y) + with pytest.raises(ValueError, match="tmin .* must be at most tmax"): + ReceptiveField(5, 4, 1).fit(X, y) + # scorers + for key, val in _SCORERS.items(): + rf = ReceptiveField( + tmin, tmax, 1, ["one"], estimator=0, scoring=key, patterns=True + ) + rf.fit(X[:, [0]], y) + y_pred = rf.predict(X[:, [0]]).T.ravel()[:, np.newaxis] + assert_allclose( + val(y[:, np.newaxis], y_pred, multioutput="raw_values"), + rf.score(X[:, [0]], y), + rtol=1e-2, + ) + with pytest.raises(ValueError, match="inputs must be shape"): + _SCORERS["corrcoef"](y.ravel(), y_pred, multioutput="raw_values") + # Need correct scorers + with pytest.raises(ValueError, match="scoring must be one of"): + ReceptiveField(tmin, tmax, 1.0, scoring="foo").fit(X, y) + + +@pytest.mark.parametrize("n_jobs", n_jobs_test) +def test_time_delaying_fast_calc(n_jobs): + """Test time delaying and fast calculations.""" + X = np.array([[1, 2, 3], [5, 7, 11]]).T + # all negative + smin, smax = 1, 2 + X_del = _delay_time_series(X, smin, smax, 1.0) + # (n_times, n_features, n_delays) -> (n_times, n_features * n_delays) + X_del = _reshape_view(X_del, (X.shape[0], -1)) + expected = np.array([[0, 1, 2], [0, 0, 1], [0, 5, 7], [0, 0, 5]]).T + assert_allclose(X_del, expected) + Xt_X = np.dot(X_del.T, X_del) + expected = [[5, 2, 19, 10], [2, 1, 7, 5], [19, 7, 74, 35], [10, 5, 35, 25]] + assert_allclose(Xt_X, expected) + x_xt = _compute_corrs(X, np.zeros((X.shape[0], 1)), smin, smax + 1)[0] + assert_allclose(x_xt, expected) + # all positive + smin, smax = -2, -1 + X_del = _delay_time_series(X, smin, smax, 1.0) + X_del = _reshape_view(X_del, (X.shape[0], -1)) + expected = np.array([[3, 0, 0], [2, 3, 0], [11, 0, 0], [7, 11, 0]]).T + assert_allclose(X_del, expected) + Xt_X = np.dot(X_del.T, X_del) + expected = [[9, 6, 33, 21], [6, 13, 22, 47], [33, 22, 121, 77], [21, 47, 77, 170]] + assert_allclose(Xt_X, expected) + x_xt = _compute_corrs(X, np.zeros((X.shape[0], 1)), smin, smax + 1)[0] + assert_allclose(x_xt, expected) + # both sides + smin, smax = -1, 1 + X_del = _delay_time_series(X, smin, smax, 1.0) + X_del = _reshape_view(X_del, (X.shape[0], -1)) + expected = np.array( + [[2, 3, 0], [1, 2, 3], [0, 1, 2], [7, 11, 0], [5, 7, 11], [0, 5, 7]] + ).T + assert_allclose(X_del, expected) + Xt_X = np.dot(X_del.T, X_del) + expected = [ + [13, 8, 3, 47, 31, 15], + [8, 14, 8, 29, 52, 31], + [3, 8, 5, 11, 29, 19], + [47, 29, 11, 170, 112, 55], + [31, 52, 29, 112, 195, 112], + [15, 31, 19, 55, 112, 74], + ] + assert_allclose(Xt_X, expected) + x_xt = _compute_corrs(X, np.zeros((X.shape[0], 1)), smin, smax + 1)[0] + assert_allclose(x_xt, expected) + + # slightly harder to get the non-Toeplitz correction correct + X = np.array([[1, 2, 3, 5]]).T + smin, smax = 0, 3 + X_del = _delay_time_series(X, smin, smax, 1.0) + X_del = _reshape_view(X_del, (X.shape[0], -1)) + expected = np.array([[1, 2, 3, 5], [0, 1, 2, 3], [0, 0, 1, 2], [0, 0, 0, 1]]).T + assert_allclose(X_del, expected) + Xt_X = np.dot(X_del.T, X_del) + expected = [[39, 23, 13, 5], [23, 14, 8, 3], [13, 8, 5, 2], [5, 3, 2, 1]] + assert_allclose(Xt_X, expected) + x_xt = _compute_corrs(X, np.zeros((X.shape[0], 1)), smin, smax + 1)[0] + assert_allclose(x_xt, expected) + + # even worse + X = np.array([[1, 2, 3], [5, 7, 11]]).T + smin, smax = 0, 2 + X_del = _delay_time_series(X, smin, smax, 1.0) + X_del = _reshape_view(X_del, (X.shape[0], -1)) + expected = np.array( + [[1, 2, 3], [0, 1, 2], [0, 0, 1], [5, 7, 11], [0, 5, 7], [0, 0, 5]] + ).T + assert_allclose(X_del, expected) + Xt_X = np.dot(X_del.T, X_del) + expected = np.array( + [ + [14, 8, 3, 52, 31, 15], + [8, 5, 2, 29, 19, 10], + [3, 2, 1, 11, 7, 5], + [52, 29, 11, 195, 112, 55], + [31, 19, 7, 112, 74, 35], + [15, 10, 5, 55, 35, 25], + ] + ) + assert_allclose(Xt_X, expected) + x_xt = _compute_corrs(X, np.zeros((X.shape[0], 1)), smin, smax + 1)[0] + assert_allclose(x_xt, expected) + + # And a bunch of random ones for good measure + rng = np.random.RandomState(0) + X = rng.randn(25, 3) + y = np.empty((25, 2)) + vals = (0, -1, 1, -2, 2, -11, 11) + for smax in vals: + for smin in vals: + if smin > smax: + continue + for ii in range(X.shape[1]): + kernel = rng.randn(smax - smin + 1) + kernel -= np.mean(kernel) + y[:, ii % y.shape[-1]] = np.convolve(X[:, ii], kernel, "same") + x_xt, x_yt, n_ch_x, _, _ = _compute_corrs(X, y, smin, smax + 1) + X_del = _delay_time_series(X, smin, smax, 1.0, fill_mean=False) + x_yt_true = einsum("tfd,to->ofd", X_del, y) + x_yt_true = np.reshape(x_yt_true, (x_yt_true.shape[0], -1)).T + assert_allclose(x_yt, x_yt_true, atol=1e-7, err_msg=(smin, smax)) + X_del = _reshape_view(X_del, (X.shape[0], -1)) + x_xt_true = np.dot(X_del.T, X_del).T + assert_allclose(x_xt, x_xt_true, atol=1e-7, err_msg=(smin, smax)) + + +@pytest.mark.parametrize("n_jobs", n_jobs_test) +def test_receptive_field_1d(n_jobs): + """Test that the fast solving works like Ridge.""" + rng = np.random.RandomState(0) + x = rng.randn(500, 1) + for delay in range(-2, 3): + y = np.zeros(500) + slims = [(-2, 4)] + if delay == 0: + y[:] = x[:, 0] + elif delay < 0: + y[:delay] = x[-delay:, 0] + slims += [(-4, -1)] + else: + y[delay:] = x[:-delay, 0] + slims += [(1, 2)] + for ndim in (1, 2): + y = _reshape_view(y, (y.shape[0],) + (1,) * (ndim - 1)) + for slim in slims: + smin, smax = slim + lap = TimeDelayingRidge( + smin, + smax, + 1.0, + 0.1, + "laplacian", + fit_intercept=False, + n_jobs=n_jobs, + ) + for estimator in (Ridge(alpha=0.0), Ridge(alpha=0.1), 0.0, 0.1, lap): + for offset in (-100, 0, 100): + model = ReceptiveField( + smin, smax, 1.0, estimator=estimator, n_jobs=n_jobs + ) + use_x = x + offset + model.fit(use_x, y) + if estimator is lap: + continue # these checks are too stringent + assert_allclose(model.estimator_.intercept_, -offset, atol=1e-1) + assert_array_equal(model.delays_, np.arange(smin, smax + 1)) + expected = (model.delays_ == delay).astype(float) + expected = expected[np.newaxis] # features + if y.ndim == 2: + expected = expected[np.newaxis] # outputs + assert_equal(model.coef_.ndim, ndim + 1) + assert_allclose(model.coef_, expected, atol=1e-3) + start = model.valid_samples_.start or 0 + stop = len(use_x) - (model.valid_samples_.stop or 0) + assert stop - start >= 495 + assert_allclose( + model.predict(use_x)[model.valid_samples_], + y[model.valid_samples_], + atol=1e-2, + ) + score = np.mean(model.score(use_x, y)) + assert score > 0.9999 + + +@pytest.mark.parametrize("n_jobs", n_jobs_test) +def test_receptive_field_nd(n_jobs): + """Test multidimensional support.""" + # multidimensional + rng = np.random.RandomState(3) + x = rng.randn(1000, 3) + y = np.zeros((1000, 2)) + smin, smax = 0, 5 + # This is a weird assignment, but it's just a way to distribute some + # unique values at various delays, and "expected" explains how they + # should appear in the resulting RF + for ii in range(1, 5): + y[ii:, ii % 2] += (-1) ** ii * ii * x[:-ii, ii % 3] + y -= np.mean(y, axis=0) + x -= np.mean(x, axis=0) + x_off = x + 1e3 + expected = [ + [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 4, 0], [0, 0, 2, 0, 0, 0]], + [[0, 0, 0, -3, 0, 0], [0, -1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]], + ] + tdr_l = TimeDelayingRidge(smin, smax, 1.0, 0.1, "laplacian", n_jobs=n_jobs) + tdr_nc = TimeDelayingRidge( + smin, smax, 1.0, 0.1, n_jobs=n_jobs, edge_correction=False + ) + for estimator, atol in zip( + (Ridge(alpha=0.0), 0.0, 0.01, tdr_l, tdr_nc), (1e-3, 1e-3, 1e-3, 5e-3, 5e-2) + ): + model = ReceptiveField(smin, smax, 1.0, estimator=estimator) + model.fit(x, y) + assert_array_equal(model.delays_, np.arange(smin, smax + 1)) + assert_allclose(model.coef_, expected, atol=atol) + tdr = TimeDelayingRidge(smin, smax, 1.0, 0.01, reg_type="foo", n_jobs=n_jobs) + model = ReceptiveField(smin, smax, 1.0, estimator=tdr) + with pytest.raises(ValueError, match="reg_type entries must be one of"): + model.fit(x, y) + tdr = TimeDelayingRidge( + smin, smax, 1.0, 0.01, reg_type=["laplacian"], n_jobs=n_jobs + ) + model = ReceptiveField(smin, smax, 1.0, estimator=tdr) + with pytest.raises(ValueError, match="reg_type must have two elements"): + model.fit(x, y) + model = ReceptiveField(smin, smax, 1, estimator=tdr, fit_intercept=False) + with pytest.raises(ValueError, match="fit_intercept"): + model.fit(x, y) + + # Now check the intercept_ + tdr = TimeDelayingRidge(smin, smax, 1.0, 0.0, n_jobs=n_jobs) + tdr_no = TimeDelayingRidge(smin, smax, 1.0, 0.0, fit_intercept=False, n_jobs=n_jobs) + for estimator in ( + Ridge(alpha=0.0), + tdr, + Ridge(alpha=0.0, fit_intercept=False), + tdr_no, + ): + # first with no intercept in the data + model = ReceptiveField(smin, smax, 1.0, estimator=estimator) + model.fit(x, y) + assert_allclose( + model.estimator_.intercept_, 0.0, atol=1e-7, err_msg=repr(estimator) + ) + assert_allclose(model.coef_, expected, atol=1e-3, err_msg=repr(estimator)) + y_pred = model.predict(x) + assert_allclose( + y_pred[model.valid_samples_], + y[model.valid_samples_], + atol=1e-2, + err_msg=repr(estimator), + ) + score = np.mean(model.score(x, y)) + assert score > 0.9999 + + # now with an intercept in the data + model.fit(x_off, y) + if estimator.fit_intercept: + val = [-6000, 4000] + itol = 0.5 + ctol = 5e-4 + else: + val = itol = 0.0 + ctol = 2.0 + assert_allclose( + model.estimator_.intercept_, val, atol=itol, err_msg=repr(estimator) + ) + assert_allclose( + model.coef_, expected, atol=ctol, rtol=ctol, err_msg=repr(estimator) + ) + if estimator.fit_intercept: + ptol = 1e-2 + stol = 0.999999 + else: + ptol = 10 + stol = 0.6 + y_pred = model.predict(x_off)[model.valid_samples_] + assert_allclose( + y_pred, y[model.valid_samples_], atol=ptol, err_msg=repr(estimator) + ) + score = np.mean(model.score(x_off, y)) + assert score > stol, estimator + model = ReceptiveField(smin, smax, 1.0, fit_intercept=False) + model.fit(x_off, y) + assert_allclose(model.estimator_.intercept_, 0.0, atol=1e-7) + score = np.mean(model.score(x_off, y)) + assert score > 0.6 + + +def _make_data(n_feats, n_targets, n_samples, tmin, tmax): + rng = np.random.RandomState(0) + X = rng.randn(n_samples, n_feats) + w = rng.randn(int((tmax - tmin) + 1) * n_feats, n_targets) + # Delay inputs + X_del = np.concatenate( + _delay_time_series(X, tmin, tmax, 1.0).transpose(2, 0, 1), axis=1 + ) + y = np.dot(X_del, w) + return X, y + + +def test_inverse_coef(): + """Test inverse coefficients computation.""" + tmin, tmax = 0.0, 10.0 + n_feats, n_targets, n_samples = 3, 2, 1000 + n_delays = int((tmax - tmin) + 1) + + # Check coefficient dims, for all estimator types + X, y = _make_data(n_feats, n_targets, n_samples, tmin, tmax) + tdr = TimeDelayingRidge(tmin, tmax, 1.0, 0.1, "laplacian") + for estimator in (0.0, 0.01, Ridge(alpha=0.0), tdr): + rf = ReceptiveField(tmin, tmax, 1.0, estimator=estimator, patterns=True) + rf.fit(X, y) + inv_rf = ReceptiveField(tmin, tmax, 1.0, estimator=estimator, patterns=True) + inv_rf.fit(y, X) + + assert_array_equal( + rf.coef_.shape, rf.patterns_.shape, (n_targets, n_feats, n_delays) + ) + assert_array_equal( + inv_rf.coef_.shape, inv_rf.patterns_.shape, (n_feats, n_targets, n_delays) + ) + + # we should have np.dot(patterns.T,coef) ~ np.eye(n) + c0 = rf.coef_.reshape(n_targets, n_feats * n_delays) + c1 = rf.patterns_.reshape(n_targets, n_feats * n_delays) + assert_allclose(np.dot(c0, c1.T), np.eye(c0.shape[0]), atol=0.2) + + +def test_linalg_warning(): + """Test that warnings are issued when no regularization is applied.""" + n_feats, n_targets, n_samples = 5, 60, 50 + X, y = _make_data(n_feats, n_targets, n_samples, tmin, tmax) + for estimator in (0.0, Ridge(alpha=0.0)): + rf = ReceptiveField(tmin, tmax, 1.0, estimator=estimator) + with pytest.warns( + (RuntimeWarning, UserWarning), match="[Singular|scipy.linalg.solve]" + ): + rf.fit(y, X) + + +@parametrize_with_checks([TimeDelayingRidge(0, 10, 1.0, 0.1, "laplacian", n_jobs=1)]) +def test_tdr_sklearn_compliance(estimator, check): + """Test sklearn estimator compliance.""" + pytest.importorskip("sklearn", minversion="1.6") # TODO VERSION remove on 1.6+ + ignores = ( + # TDR convolves and thus its output cannot be invariant when + # shuffled or subsampled. + "check_methods_sample_order_invariance", + "check_methods_subset_invariance", + ) + if any(ignore in str(check) for ignore in ignores): + return + check(estimator) + + +@pytest.mark.filterwarnings("ignore:.*invalid value encountered in subtract.*:") +@parametrize_with_checks([ReceptiveField(-1, 2, 1.0, estimator=Ridge(), patterns=True)]) +def test_rf_sklearn_compliance(estimator, check): + """Test sklearn RF compliance.""" + pytest.importorskip("sklearn", minversion="1.6") # TODO VERSION remove on 1.6+ + ignores = ( + # RF does time-lagging, so its output cannot be invariant when + # shuffled or subsampled. + "check_methods_sample_order_invariance", + "check_methods_subset_invariance", + ) + if any(ignore in str(check) for ignore in ignores): + return + check(estimator) diff --git a/mne-python/source/mne/decoding/tests/test_search_light.py b/mne-python/source/mne/decoding/tests/test_search_light.py new file mode 100644 index 0000000000000000000000000000000000000000..56d239c1bccedb024a692f8f939ba1e00fcd2171 --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_search_light.py @@ -0,0 +1,358 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import platform +from inspect import signature + +import numpy as np +import pytest +from numpy.testing import assert_array_equal, assert_equal + +sklearn = pytest.importorskip("sklearn") + +from sklearn.base import BaseEstimator, clone, is_classifier +from sklearn.discriminant_analysis import LinearDiscriminantAnalysis +from sklearn.ensemble import BaggingClassifier +from sklearn.linear_model import LinearRegression, LogisticRegression, Ridge +from sklearn.metrics import make_scorer, roc_auc_score +from sklearn.model_selection import cross_val_predict +from sklearn.multiclass import OneVsRestClassifier +from sklearn.pipeline import make_pipeline +from sklearn.svm import SVC +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne.decoding.search_light import GeneralizingEstimator, SlidingEstimator +from mne.decoding.transformer import Vectorizer +from mne.utils import check_version, use_log_level + +NEW_MULTICLASS_SAMPLE_WEIGHT = check_version("sklearn", "1.4") + + +def make_data(): + """Make data.""" + n_epochs, n_chan, n_time = 50, 32, 10 + X = np.random.rand(n_epochs, n_chan, n_time) + y = np.arange(n_epochs) % 2 + for ii in range(n_time): + coef = np.random.randn(n_chan) + X[y == 0, :, ii] += coef + X[y == 1, :, ii] -= coef + return X, y + + +def test_search_light_basic(): + """Test SlidingEstimator.""" + # https://github.com/scikit-learn/scikit-learn/issues/27711 + if platform.system() == "Windows" and check_version("numpy", "2.0.0.dev0"): + pytest.skip("sklearn int_t / long long mismatch") + + logreg = OneVsRestClassifier(LogisticRegression(solver="liblinear", random_state=0)) + + X, y = make_data() + n_epochs, _, n_time = X.shape + # init + sl = SlidingEstimator("foo") + with pytest.raises(ValueError, match="must be"): + sl.fit(X, y) + sl = SlidingEstimator(Ridge()) + assert not is_classifier(sl) + sl = SlidingEstimator(LogisticRegression(solver="liblinear")) + assert is_classifier(sl.base_estimator) + assert is_classifier(sl) + # fit + assert_equal(sl.__repr__()[:18], "") + pytest.raises(ValueError, sl.fit, X[1:], y) + pytest.raises(ValueError, sl.fit, X[:, :, 0], y) + sl.fit(X, y, sample_weight=np.ones_like(y)) + + # transforms + pytest.raises(ValueError, sl.predict, X[:, :, :2]) + y_trans = sl.transform(X) + assert X.dtype == float + assert y_trans.dtype == float + y_pred = sl.predict(X) + assert y_pred.dtype == np.dtype(int) + assert_array_equal(y_pred.shape, [n_epochs, n_time]) + y_proba = sl.predict_proba(X) + assert y_proba.dtype == np.dtype(float) + assert_array_equal(y_proba.shape, [n_epochs, n_time, 2]) + + # score + score = sl.score(X, y) + assert_array_equal(score.shape, [n_time]) + assert np.sum(np.abs(score)) != 0 + assert score.dtype == np.dtype(float) + + sl = SlidingEstimator(logreg) + assert_equal(sl.scoring, None) + + # Scoring method + for scoring in ["foo", 999]: + sl = SlidingEstimator(logreg, scoring=scoring) + sl.fit(X, y) + pytest.raises((ValueError, TypeError), sl.score, X, y) + + # Check sklearn's roc_auc fix: scikit-learn/scikit-learn#6874 + # -- 3 class problem + sl = SlidingEstimator(logreg, scoring="roc_auc") + y = np.arange(len(X)) % 3 + sl.fit(X, y) + with pytest.raises(ValueError, match="for two-class"): + sl.score(X, y) + # But check that valid ones should work with new enough sklearn + kwargs = dict() + if check_version("sklearn", "1.4"): + kwargs["response_method"] = "predict_proba" + else: + kwargs["needs_proba"] = True + if "multi_class" in signature(roc_auc_score).parameters: + scoring = make_scorer(roc_auc_score, multi_class="ovo", **kwargs) + sl = SlidingEstimator(logreg, scoring=scoring) + sl.fit(X, y) + sl.score(X, y) # smoke test + + # -- 2 class problem not in [0, 1] + y = np.arange(len(X)) % 2 + 1 + sl.fit(X, y) + score = sl.score(X, y) + assert_array_equal( + score, + [roc_auc_score(y - 1, _y_pred - 1) for _y_pred in sl.decision_function(X).T], + ) + y = np.arange(len(X)) % 2 + + # Cannot pass a metric as a scoring parameter + sl1 = SlidingEstimator(logreg, scoring=roc_auc_score) + sl1.fit(X, y) + pytest.raises(ValueError, sl1.score, X, y) + + # Now use string as scoring + sl1 = SlidingEstimator(logreg, scoring="roc_auc") + sl1.fit(X, y) + rng = np.random.RandomState(0) + X = rng.randn(*X.shape) # randomize X to avoid AUCs in [0, 1] + score_sl = sl1.score(X, y) + assert_array_equal(score_sl.shape, [n_time]) + assert score_sl.dtype == np.dtype(float) + + # Check that scoring was applied adequately + kwargs = dict() + if check_version("sklearn", "1.4"): + kwargs["response_method"] = ("decision_function", "predict_proba") + else: + kwargs["needs_threshold"] = True + scoring = make_scorer(roc_auc_score, **kwargs) + score_manual = [ + scoring(est, x, y) for est, x in zip(sl1.estimators_, X.transpose(2, 0, 1)) + ] + assert_array_equal(score_manual, score_sl) + + # n_jobs + sl = SlidingEstimator(logreg, n_jobs=None, scoring="roc_auc") + score_1job = sl.fit(X, y).score(X, y) + sl.n_jobs = 2 + score_njobs = sl.fit(X, y).score(X, y) + assert_array_equal(score_1job, score_njobs) + sl.predict(X) + + # n_jobs > n_estimators + sl.fit(X[..., [0]], y) + sl.predict(X[..., [0]]) + + # pipeline + class _LogRegTransformer(LogisticRegression): + def transform(self, X): + return super().predict_proba(X)[..., 1] + + logreg_transformer = OneVsRestClassifier(_LogRegTransformer(random_state=0)) + pipe = make_pipeline(SlidingEstimator(logreg_transformer), logreg) + pipe.fit(X, y) + pipe.predict(X) + + # n-dimensional feature space + X = np.random.rand(10, 3, 4, 2) + y = np.arange(10) % 2 + y_preds = list() + for n_jobs in [1, 2]: + pipe = SlidingEstimator(make_pipeline(Vectorizer(), logreg), n_jobs=n_jobs) + y_preds.append(pipe.fit(X, y).predict(X)) + features_shape = pipe.estimators_[0].steps[0][1].features_shape_ + assert_array_equal(features_shape, [3, 4]) + assert_array_equal(y_preds[0], y_preds[1]) + + # Bagging classifiers + X = np.random.rand(10, 3, 4) + for n_jobs in (1, 2): + pipe = SlidingEstimator(BaggingClassifier(None, 2), n_jobs=n_jobs) + pipe.fit(X, y) + pipe.score(X, y) + assert isinstance(pipe.estimators_[0], BaggingClassifier) + + +@pytest.fixture() +def metadata_routing(): + """Temporarily enable metadata routing for new sklearn.""" + if NEW_MULTICLASS_SAMPLE_WEIGHT: + sklearn.set_config(enable_metadata_routing=True) + yield + if NEW_MULTICLASS_SAMPLE_WEIGHT: + sklearn.set_config(enable_metadata_routing=False) + + +def test_generalization_light(metadata_routing): + """Test GeneralizingEstimator.""" + if NEW_MULTICLASS_SAMPLE_WEIGHT: + clf = LogisticRegression(random_state=0) + clf.set_fit_request(sample_weight=True) + logreg = OneVsRestClassifier(clf) + else: + logreg = LogisticRegression( + solver="liblinear", + random_state=0, + multi_class="ovr", + ) + + X, y = make_data() + n_epochs, _, n_time = X.shape + # fit + gl = GeneralizingEstimator(logreg) + assert_equal(repr(gl)[:23], "") + # transforms + y_pred = gl.predict(X) + assert_array_equal(y_pred.shape, [n_epochs, n_time, n_time]) + assert y_pred.dtype == np.dtype(int) + y_proba = gl.predict_proba(X) + assert y_proba.dtype == np.dtype(float) + assert_array_equal(y_proba.shape, [n_epochs, n_time, n_time, 2]) + + # transform to different datasize + y_pred = gl.predict(X[:, :, :2]) + assert_array_equal(y_pred.shape, [n_epochs, n_time, 2]) + + # score + score = gl.score(X[:, :, :3], y) + assert_array_equal(score.shape, [n_time, 3]) + assert np.sum(np.abs(score)) != 0 + assert score.dtype == np.dtype(float) + + gl = GeneralizingEstimator(logreg, scoring="roc_auc") + gl.fit(X, y) + score = gl.score(X, y) + auc = roc_auc_score(y, gl.estimators_[0].predict_proba(X[..., 0])[..., 1]) + assert_equal(score[0, 0], auc) + + for scoring in ["foo", 999]: + gl = GeneralizingEstimator(logreg, scoring=scoring) + gl.fit(X, y) + pytest.raises((ValueError, TypeError), gl.score, X, y) + + # Check sklearn's roc_auc fix: scikit-learn/scikit-learn#6874 + # -- 3 class problem + gl = GeneralizingEstimator(logreg, scoring="roc_auc") + y = np.arange(len(X)) % 3 + gl.fit(X, y) + pytest.raises(ValueError, gl.score, X, y) + # -- 2 class problem not in [0, 1] + y = np.arange(len(X)) % 2 + 1 + gl.fit(X, y) + score = gl.score(X, y) + manual_score = [ + [roc_auc_score(y - 1, _y_pred) for _y_pred in _y_preds] + for _y_preds in gl.decision_function(X).transpose(1, 2, 0) + ] + assert_array_equal(score, manual_score) + + # n_jobs + gl = GeneralizingEstimator(logreg, n_jobs=2) + gl.fit(X, y) + y_pred = gl.predict(X) + assert_array_equal(y_pred.shape, [n_epochs, n_time, n_time]) + score = gl.score(X, y) + assert_array_equal(score.shape, [n_time, n_time]) + + # n_jobs > n_estimators + gl.fit(X[..., [0]], y) + gl.predict(X[..., [0]]) + + # n-dimensional feature space + X = np.random.rand(10, 3, 4, 2) + y = np.arange(10) % 2 + y_preds = list() + for n_jobs in [1, 2]: + pipe = GeneralizingEstimator(make_pipeline(Vectorizer(), logreg), n_jobs=n_jobs) + y_preds.append(pipe.fit(X, y).predict(X)) + features_shape = pipe.estimators_[0].steps[0][1].features_shape_ + assert_array_equal(features_shape, [3, 4]) + assert_array_equal(y_preds[0], y_preds[1]) + + +@pytest.mark.parametrize( + "n_jobs, verbose", [(1, False), (2, False), (1, True), (2, "info")] +) +def test_verbose_arg(capsys, n_jobs, verbose): + """Test controlling output with the ``verbose`` argument.""" + X, y = make_data() + clf = SVC() + + # shows progress bar and prints other messages to the console + with use_log_level(True): + for estimator_object in [SlidingEstimator, GeneralizingEstimator]: + estimator = estimator_object(clf, n_jobs=n_jobs, verbose=verbose) + estimator = estimator.fit(X, y) + estimator.score(X, y) + estimator.predict(X) + + stdout, stderr = capsys.readouterr() + if isinstance(verbose, bool) and not verbose: + assert all(channel == "" for channel in (stdout, stderr)) + else: + assert any(len(channel) > 0 for channel in (stdout, stderr)) + + +def test_cross_val_predict(): + """Test cross_val_predict with predict_proba.""" + rng = np.random.RandomState(42) + X = rng.randn(10, 1, 3) + y = rng.randint(0, 2, 10) + + estimator = SlidingEstimator(LinearRegression()) + cross_val_predict(estimator, X, y, cv=2) + + class Classifier(BaseEstimator): + """Moch class that does not have classes_ attribute.""" + + def __init__(self): + self.base_estimator = LinearDiscriminantAnalysis() + + def fit(self, X, y): + self.estimator_ = clone(self.base_estimator).fit(X, y) + return self + + def predict_proba(self, X): + return self.estimator_.predict_proba(X) + + with pytest.raises(AttributeError, match="classes_ attribute"): + estimator = SlidingEstimator(Classifier()) + cross_val_predict(estimator, X, y, method="predict_proba", cv=2) + + estimator = SlidingEstimator(LinearDiscriminantAnalysis()) + cross_val_predict(estimator, X, y, method="predict_proba", cv=2) + + +@pytest.mark.slowtest +@parametrize_with_checks( + [ + SlidingEstimator(LogisticRegression(), allow_2d=True), + GeneralizingEstimator(LogisticRegression(), allow_2d=True), + ] +) +def test_sklearn_compliance(estimator, check): + """Test searchlights compliance with sklearn.""" + check(estimator) diff --git a/mne-python/source/mne/decoding/tests/test_spatial_filter.py b/mne-python/source/mne/decoding/tests/test_spatial_filter.py new file mode 100644 index 0000000000000000000000000000000000000000..385b73fc0530038068b974d6b365c6e71226e501 --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_spatial_filter.py @@ -0,0 +1,190 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import matplotlib.pyplot as plt +import numpy as np +import pytest +from numpy.testing import assert_array_equal + +pytest.importorskip("sklearn") + +from sklearn.linear_model import LinearRegression +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import StandardScaler + +from mne import Epochs, create_info, io, pick_types, read_events +from mne.decoding import ( + CSP, + LinearModel, + SpatialFilter, + Vectorizer, + XdawnTransformer, + get_spatial_filter_from_estimator, +) + +data_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = data_dir / "test_raw.fif" +event_name = data_dir / "test-eve.fif" +tmin, tmax = -0.1, 0.2 +event_id = dict(aud_l=1, vis_l=3) +start, stop = 0, 8 + + +def _get_X_y(event_id, return_info=False): + raw = io.read_raw(raw_fname, preload=False) + events = read_events(event_name) + picks = pick_types( + raw.info, meg=True, stim=False, ecg=False, eog=False, exclude="bads" + ) + picks = picks[2:12:3] # subselect channels -> disable proj! + raw.add_proj([], remove_existing=True) + epochs = Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + baseline=(None, 0), + preload=True, + proj=False, + ) + X = epochs.get_data(copy=False, units=dict(eeg="uV", grad="fT/cm", mag="fT")) + y = epochs.events[:, -1] + if return_info: + return X, y, epochs.info + return X, y + + +def test_spatial_filter_init(): + """Test the initialization of the SpatialFilter class.""" + # Test initialization and factory function + rng = np.random.RandomState(0) + n, n_features = 20, 3 + X = rng.rand(n, n_features) + n_targets = 5 + y = rng.rand(n, n_targets) + clf = LinearModel(LinearRegression()) + clf.fit(X, y) + + # test get_spatial_filter_from_estimator for LinearModel + info = create_info(n_features, 1000.0, "eeg") + sp_filter = get_spatial_filter_from_estimator(clf, info) + assert sp_filter.patterns_method == "haufe" + assert_array_equal(sp_filter.filters, clf.filters_) + assert_array_equal(sp_filter.patterns, clf.patterns_) + assert sp_filter.evals is None + + with pytest.raises(ValueError, match="can only include"): + _ = get_spatial_filter_from_estimator( + clf, info, get_coefs=("foo", "foo", "foo") + ) + + event_id = dict(aud_l=1, vis_l=3) + X, y, info = _get_X_y(event_id, return_info=True) + estimator = make_pipeline(Vectorizer(), StandardScaler(), CSP(n_components=4)) + estimator.fit(X, y) + csp = estimator[-1] + # test get_spatial_filter_from_estimator for GED + sp_filter = get_spatial_filter_from_estimator(estimator, info, step_name="csp") + assert sp_filter.patterns_method == "pinv" + assert_array_equal(sp_filter.filters, csp.filters_) + assert_array_equal(sp_filter.patterns, csp.patterns_) + assert_array_equal(sp_filter.evals, csp.evals_) + assert sp_filter.info is info + + # test without step_name + sp_filter = get_spatial_filter_from_estimator(estimator, info) + assert_array_equal(sp_filter.filters, csp.filters_) + assert_array_equal(sp_filter.patterns, csp.patterns_) + assert_array_equal(sp_filter.evals, csp.evals_) + + # test basic initialization + sp_filter = SpatialFilter( + info, filters=csp.filters_, patterns=csp.patterns_, evals=csp.evals_ + ) + assert_array_equal(sp_filter.filters, csp.filters_) + assert_array_equal(sp_filter.patterns, csp.patterns_) + assert_array_equal(sp_filter.evals, csp.evals_) + assert sp_filter.info is info + + # test automatic pattern calculation via pinv + sp_filter_pinv = SpatialFilter(info, filters=csp.filters_, evals=csp.evals_) + patterns_pinv = np.linalg.pinv(csp.filters_.T) + assert_array_equal(sp_filter_pinv.patterns, patterns_pinv) + assert sp_filter_pinv.patterns_method == "pinv" + + # test shape mismatch error + with pytest.raises(ValueError, match="Shape mismatch"): + SpatialFilter(info, filters=csp.filters_, patterns=csp.patterns_[:-1]) + + # test invalid patterns_method + with pytest.raises(ValueError, match="patterns_method"): + SpatialFilter(info, filters=csp.filters_, patterns_method="foo") + + # test n_components > n_channels error + bad_filters = np.random.randn(31, 30) # 31 components, 30 channels + with pytest.raises(ValueError, match="Number of components can't be greater"): + SpatialFilter(info, filters=bad_filters) + + +def test_spatial_filter_plotting(): + """Test the plotting methods of SpatialFilter.""" + event_id = dict(aud_l=1, vis_l=3) + X, y, info = _get_X_y(event_id, return_info=True) + csp = CSP(n_components=4) + csp.fit(X, y) + + sp_filter = get_spatial_filter_from_estimator(csp, info) + + # test plot_filters + fig_filters = sp_filter.plot_filters(components=[0, 1], show=False) + assert isinstance(fig_filters, plt.Figure) + plt.close("all") + + # test plot_patterns + fig_patterns = sp_filter.plot_patterns(show=False) + assert isinstance(fig_patterns, plt.Figure) + plt.close("all") + + # test plot_scree + fig_scree = sp_filter.plot_scree(show=False, add_cumul_evals=True) + assert isinstance(fig_scree, plt.Figure) + plt.close("all") + _, axes = plt.subplots(figsize=(12, 7), layout="constrained") + fig_scree = sp_filter.plot_scree(axes=axes, show=False) + assert fig_scree == list() + plt.close("all") + + # test plot_scree raises error if evals is None + sp_filter_no_evals = SpatialFilter(info, filters=csp.filters_, evals=None) + with pytest.raises(AttributeError, match="eigenvalues are not provided"): + sp_filter_no_evals.plot_scree() + + # 3D case ('multi' GED decomposition) + n_classes = 2 + event_id = dict(aud_l=1, vis_l=3) + X, y, info = _get_X_y(event_id, return_info=True) + xdawn = XdawnTransformer(n_components=4) + xdawn.fit(X, y) + sp_filter = get_spatial_filter_from_estimator(xdawn, info) + + fig_patterns = sp_filter.plot_patterns(show=False) + assert len(fig_patterns) == n_classes + plt.close("all") + + fig_scree = sp_filter.plot_scree(show=False) + assert len(fig_scree) == n_classes + plt.close("all") + + with pytest.raises(ValueError, match="but expected"): + _, axes = plt.subplots(figsize=(12, 7), layout="constrained") + _ = sp_filter.plot_scree(axes=axes, show=False) + + _, axes = plt.subplots(n_classes, figsize=(12, 7), layout="constrained") + fig_scree = sp_filter.plot_scree(axes=axes, show=False) + assert fig_scree == list() + plt.close("all") diff --git a/mne-python/source/mne/decoding/tests/test_ssd.py b/mne-python/source/mne/decoding/tests/test_ssd.py new file mode 100644 index 0000000000000000000000000000000000000000..086413b043fcacb9e97013244a7ac85db0c5fa96 --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_ssd.py @@ -0,0 +1,642 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import sys +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_array_almost_equal, assert_array_equal + +pytest.importorskip("sklearn") + +from sklearn.pipeline import Pipeline +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne import Epochs, create_info, io, pick_types, read_events +from mne._fiff.pick import _picks_to_idx +from mne.decoding import CSP +from mne.decoding._mod_ged import _get_spectral_ratio +from mne.decoding.ssd import SSD +from mne.filter import filter_data +from mne.time_frequency import psd_array_welch + +freqs_sig = 9, 12 +freqs_noise = 8, 13 + +data_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = data_dir / "test_raw.fif" +event_name = data_dir / "test-eve.fif" +tmin, tmax = -0.1, 0.2 +event_id = dict(aud_l=1, vis_l=3) +start, stop = 0, 8 + + +def simulate_data( + freqs_sig=(9, 12), + n_trials=100, + n_channels=20, + n_samples=500, + samples_per_second=250, + n_components=5, + SNR=0.05, + random_state=42, +): + """Simulate data according to an instantaneous mixin model. + + Data are simulated in the statistical source space, where n=n_components + sources contain the peak of interest. + """ + rng = np.random.RandomState(random_state) + + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + fir_design="firwin", + ) + + # generate an orthogonal mixin matrix + mixing_mat = np.linalg.svd(rng.randn(n_channels, n_channels))[0] + # define sources + S_s = rng.randn(n_trials * n_samples, n_components) + # filter source in the specific freq. band of interest + S_s = filter_data(S_s.T, samples_per_second, **filt_params_signal).T + S_n = rng.randn(n_trials * n_samples, n_channels - n_components) + S = np.hstack((S_s, S_n)) + # mix data + X_s = np.dot(mixing_mat[:, :n_components], S_s.T).T + X_n = np.dot(mixing_mat[:, n_components:], S_n.T).T + # add noise + X_s = X_s / np.linalg.norm(X_s, "fro") + X_n = X_n / np.linalg.norm(X_n, "fro") + X = SNR * X_s + (1 - SNR) * X_n + X = X.T + S = S.T + return X, mixing_mat, S + + +@pytest.mark.slowtest +def test_ssd(): + """Test Common Spatial Patterns algorithm on raw data.""" + X, A, S = simulate_data() + sf = 250 + n_channels = X.shape[0] + info = create_info(ch_names=n_channels, sfreq=sf, ch_types="eeg") + n_components_true = 5 + + # Init + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + ssd = SSD(info, filt_params_signal, filt_params_noise) + # freq no int + freq = "foo" + filt_params_signal = dict( + l_freq=freq, h_freq=freqs_sig[1], l_trans_bandwidth=1, h_trans_bandwidth=1 + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + ssd = SSD(info, filt_params_signal, filt_params_noise) + with pytest.raises(TypeError, match="must be an instance "): + ssd.fit(X) + + # Wrongly specified noise band + freq = 2 + filt_params_signal = dict( + l_freq=freq, h_freq=freqs_sig[1], l_trans_bandwidth=1, h_trans_bandwidth=1 + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + ssd = SSD(info, filt_params_signal, filt_params_noise) + with pytest.raises(ValueError, match="Wrongly specified "): + ssd.fit(X) + + # filt param no dict + filt_params_signal = freqs_sig + filt_params_noise = freqs_noise + ssd = SSD(info, filt_params_signal, filt_params_noise) + with pytest.raises(ValueError, match="must be defined"): + ssd.fit(X) + + # Data type + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + ssd = SSD(info, filt_params_signal, filt_params_noise) + raw = io.RawArray(X, info) + + with pytest.raises(ValueError): + ssd.fit(raw) + + # check non-boolean return_filtered + ssd = SSD(info, filt_params_signal, filt_params_noise, return_filtered=0) + with pytest.raises(TypeError, match="return_filtered"): + ssd.fit(X) + + # check non-boolean sort_by_spectral_ratio + ssd = SSD(info, filt_params_signal, filt_params_noise, sort_by_spectral_ratio=0) + with pytest.raises(TypeError, match="sort_by_spectral_ratio"): + ssd.fit(X) + + # More than 1 channel type + ch_types = np.reshape([["mag"] * 10, ["eeg"] * 10], n_channels) + info_2 = create_info(ch_names=n_channels, sfreq=sf, ch_types=ch_types) + + ssd = SSD(info_2, filt_params_signal, filt_params_noise) + with pytest.raises(ValueError, match="At this point SSD"): + ssd.fit(X) + + # Number of channels + info_3 = create_info(ch_names=n_channels + 1, sfreq=sf, ch_types="eeg") + ssd = SSD(info_3, filt_params_signal, filt_params_noise) + with pytest.raises(ValueError, match="channels but expected"): + ssd.fit(X) + + # Fit + n_components = 10 + ssd = SSD(info, filt_params_signal, filt_params_noise, n_components=n_components) + + # Call transform before fit + pytest.raises(AttributeError, ssd.transform, X) + + # Check outputs + ssd.fit(X) + + assert ssd.filters_.shape == (n_channels, n_channels) + assert ssd.patterns_.shape == (n_channels, n_channels) + + # Transform + X_ssd = ssd.fit_transform(X) + assert X_ssd.shape[0] == n_components + # back and forward + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + n_components=None, + sort_by_spectral_ratio=False, + ) + ssd.fit(X) + X_denoised = ssd.apply(X) + assert_array_almost_equal(X_denoised, X) + # denoised by low-rank-factorization + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + n_components=n_components, + sort_by_spectral_ratio=True, + ) + ssd.fit(X) + X_denoised = ssd.apply(X) + assert np.linalg.matrix_rank(X_denoised) == n_components + + # Power ratio ordering + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + n_components=None, + sort_by_spectral_ratio=False, + ) + ssd.fit(X) + spec_ratio, sorter_spec = _get_spectral_ratio( + ssd.transform(X), ssd.sfreq_, ssd.n_fft_, ssd.freqs_signal_, ssd.freqs_noise_ + ) + # since we now that the number of true components is 5, the relative + # difference should be low for the first 5 components and then increases + index_diff = np.argmax(-np.diff(spec_ratio)) + assert index_diff == n_components_true - 1 + # Check detected peaks + # fit ssd + n_components = n_components_true + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + n_components=n_components, + sort_by_spectral_ratio=False, + ) + ssd.fit(X) + + out = ssd.transform(X) + psd_out, _ = psd_array_welch(out[0], sfreq=250, n_fft=250) + psd_S, _ = psd_array_welch(S[0], sfreq=250, n_fft=250) + corr = np.abs(np.corrcoef((psd_out, psd_S))[0, 1]) + assert np.abs(corr) > 0.95 + # Check pattern estimation + # Since there is no exact ordering of the recovered patterns + # a pair-wise greedy search will be done + error = list() + for ii in range(n_channels): + corr = np.abs(np.corrcoef(ssd.patterns_[ii, :].T, A[:, 0])[0, 1]) + error.append(1 - corr) + min_err = np.min(error) + assert min_err < 0.3 # threshold taken from SSD original paper + + +def test_ssd_epoched_data(): + """Test Common Spatial Patterns algorithm on epoched data. + + Compare the outputs when raw data is used. + """ + X, A, S = simulate_data(n_trials=100, n_channels=20, n_samples=500) + sf = 250 + n_channels = X.shape[0] + info = create_info(ch_names=n_channels, sfreq=sf, ch_types="eeg") + n_components_true = 5 + + # Build epochs as sliding windows over the continuous raw file + + # Epoch length is 1 second + X_e = np.reshape(X, (100, 20, 500)) + + # Fit + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=4, + h_trans_bandwidth=4, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=4, + h_trans_bandwidth=4, + ) + + # ssd on epochs + ssd_e = SSD(info, filt_params_signal, filt_params_noise) + ssd_e.fit(X_e) + # ssd on raw + ssd = SSD(info, filt_params_signal, filt_params_noise) + ssd.fit(X) + + # Check if the 5 first 5 components are the same for both + _, sorter_spec_e = _get_spectral_ratio( + ssd_e.transform(X_e), + ssd_e.sfreq_, + ssd_e.n_fft_, + ssd_e.freqs_signal_, + ssd_e.freqs_noise_, + ) + _, sorter_spec = _get_spectral_ratio( + ssd.transform(X), ssd.sfreq_, ssd.n_fft_, ssd.freqs_signal_, ssd.freqs_noise_ + ) + assert_array_equal( + sorter_spec_e[:n_components_true], sorter_spec[:n_components_true] + ) + + +def test_ssd_pipeline(): + """Test if SSD works in a pipeline.""" + sf = 250 + X, A, S = simulate_data(n_trials=100, n_channels=20, n_samples=500) + X_e = np.reshape(X, (100, 20, 500)) + # define bynary random output + y = np.random.RandomState(0).randint(2, size=100) + + info = create_info(ch_names=20, sfreq=sf, ch_types="eeg") + + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=4, + h_trans_bandwidth=4, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=4, + h_trans_bandwidth=4, + ) + ssd = SSD(info, filt_params_signal, filt_params_noise) + csp = CSP() + pipe = Pipeline([("SSD", ssd), ("CSP", csp)]) + pipe.set_params(SSD__n_components=5) + pipe.set_params(CSP__n_components=2) + out = pipe.fit_transform(X_e, y) + assert out.shape == (100, 2) + assert pipe.get_params()["SSD__n_components"] == 5 + + +def test_sorting(): + """Test sorting learning during training.""" + X, _, _ = simulate_data(n_trials=100, n_channels=20, n_samples=500) + # Epoch length is 1 second + X = np.reshape(X, (100, 20, 500)) + # split data + Xtr, Xte = X[:80], X[80:] + sf = 250 + n_channels = Xtr.shape[1] + info = create_info(ch_names=n_channels, sfreq=sf, ch_types="eeg") + + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=4, + h_trans_bandwidth=4, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=4, + h_trans_bandwidth=4, + ) + + # check sort_by_spectral_ratio set to False + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + n_components=None, + sort_by_spectral_ratio=False, + ) + ssd.fit(Xtr) + _, sorter_tr = _get_spectral_ratio( + ssd.transform(Xtr), ssd.sfreq_, ssd.n_fft_, ssd.freqs_signal_, ssd.freqs_noise_ + ) + _, sorter_te = _get_spectral_ratio( + ssd.transform(Xte), ssd.sfreq_, ssd.n_fft_, ssd.freqs_signal_, ssd.freqs_noise_ + ) + assert any(sorter_tr != sorter_te) + + # check sort_by_spectral_ratio set to True + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + n_components=None, + sort_by_spectral_ratio=True, + ) + ssd.fit(Xtr) + + # check sorters + sorter_in = ssd.sorter_ + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + n_components=None, + sort_by_spectral_ratio=False, + ) + ssd.fit(Xtr) + _, sorter_out = _get_spectral_ratio( + ssd.transform(Xtr), ssd.sfreq_, ssd.n_fft_, ssd.freqs_signal_, ssd.freqs_noise_ + ) + + assert all(sorter_in == sorter_out) + + +def test_return_filtered(): + """Test return filtered option.""" + # Check return_filtered + # Simulated more noise data and with broader frequency than the desired + X, _, _ = simulate_data(SNR=0.9, freqs_sig=[4, 13]) + sf = 250 + n_channels = X.shape[0] + info = create_info(ch_names=n_channels, sfreq=sf, ch_types="eeg") + + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + + # return filtered to true + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + sort_by_spectral_ratio=False, + return_filtered=True, + ) + ssd.fit(X) + + out = ssd.transform(X) + psd_out, freqs = psd_array_welch(out[0], sfreq=250, n_fft=250) + freqs_up = int(freqs[psd_out > 0.5][0]), int(freqs[psd_out > 0.5][-1]) + assert freqs_up == freqs_sig + + # return filtered to false + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + sort_by_spectral_ratio=False, + return_filtered=False, + ) + ssd.fit(X) + + out = ssd.transform(X) + psd_out, freqs = psd_array_welch(out[0], sfreq=250, n_fft=250) + freqs_up = int(freqs[psd_out > 0.5][0]), int(freqs[psd_out > 0.5][-1]) + assert freqs_up != freqs_sig + + +def test_non_full_rank_data(): + """Test that the method works with non-full rank data.""" + n_channels = 10 + X, _, _ = simulate_data(SNR=0.9, freqs_sig=[4, 13], n_channels=n_channels) + info = create_info(ch_names=n_channels, sfreq=250, ch_types="eeg") + + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + + # Make data non-full rank + rank = 5 + X[rank:] = X[:rank] # an extreme example, but a valid one + assert np.linalg.matrix_rank(X) == rank + + ssd = SSD(info, filt_params_signal, filt_params_noise) + if sys.platform == "darwin": + pytest.xfail("Unknown linalg bug (Accelerate?)") + ssd.fit(X) + + +def test_picks_arg(): + """Test that picks argument works as expected.""" + raw = io.read_raw_fif(raw_fname, preload=False) + events = read_events(event_name) + picks = pick_types( + raw.info, meg=True, eeg=True, stim=False, ecg=False, eog=False, exclude="bads" + ) + raw.add_proj([], remove_existing=True) + epochs = Epochs( + raw, + events, + event_id, + -0.1, + 1, + picks=picks, + baseline=(None, 0), + preload=True, + proj=False, + ) + X = epochs.get_data(copy=False) + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=3, + h_trans_bandwidth=3, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=3, + h_trans_bandwidth=3, + ) + picks = ["eeg"] + info = epochs.info + picks_idx = _picks_to_idx(info, picks) + + # Test when return_filtered is False + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + picks=picks_idx, + return_filtered=False, + ) + ssd.fit(X).transform(X) + + # Test when return_filtered is true + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + picks=picks_idx, + return_filtered=True, + n_fft=64, + ) + ssd.fit(X).transform(X) + + +def test_get_spectral_ratio(): + """Test that method is the same as function in _mod_ged.py.""" + X, _, _ = simulate_data() + sf = 250 + n_channels = X.shape[0] + info = create_info(ch_names=n_channels, sfreq=sf, ch_types="eeg") + + # Init + filt_params_signal = dict( + l_freq=freqs_sig[0], + h_freq=freqs_sig[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + filt_params_noise = dict( + l_freq=freqs_noise[0], + h_freq=freqs_noise[1], + l_trans_bandwidth=1, + h_trans_bandwidth=1, + ) + + ssd = SSD( + info, + filt_params_signal, + filt_params_noise, + n_components=None, + sort_by_spectral_ratio=False, + ) + ssd.fit(X) + ssd_sources = ssd.transform(X) + spec_ratio_ssd, sorter_spec_ssd = ssd.get_spectral_ratio(ssd_sources) + spec_ratio_ged, sorter_spec_ged = _get_spectral_ratio( + ssd_sources, ssd.sfreq_, ssd.n_fft_, ssd.freqs_signal_, ssd.freqs_noise_ + ) + assert_array_equal(spec_ratio_ssd, spec_ratio_ged) + assert_array_equal(sorter_spec_ssd, sorter_spec_ged) + + +@pytest.mark.filterwarnings("ignore:.*invalid value encountered in divide.*") +@pytest.mark.filterwarnings("ignore:.*is longer than.*") +@parametrize_with_checks( + [ + SSD( + 100.0, + dict(l_freq=0.0, h_freq=30.0), + dict(l_freq=0.0, h_freq=40.0), + ) + ] +) +def test_sklearn_compliance(estimator, check): + """Test LinearModel compliance with sklearn.""" + pytest.importorskip("sklearn", minversion="1.6") # TODO VERSION remove on 1.6+ + ignores = ( + # Checks below fail because what sklearn passes as (n_samples, n_features) + # is considered (n_channels, n_times) by SSD and creates problems + # when n_channels change between fit and transform. + # Could potentially be fixed by if X.ndim == 2: X = np.expand_dims(X, axis=2) + # in fit and transform instead of axis=0. + # But this will require to drop support for 2D inputs and expect + # user to provide 3D array even if it's a continuous signal. + "check_methods_sample_order_invariance", # SSD is not time-invariant + "check_fit_idempotent", + "check_methods_subset_invariance", + "check_transformer_general", + "check_transformer_data_not_an_array", + ) + if any(ignore in str(check) for ignore in ignores): + return + + check(estimator) diff --git a/mne-python/source/mne/decoding/tests/test_time_frequency.py b/mne-python/source/mne/decoding/tests/test_time_frequency.py new file mode 100644 index 0000000000000000000000000000000000000000..9765c85533ebada6a5c796bf4d597ff80b0bc082 --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_time_frequency.py @@ -0,0 +1,61 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + + +import numpy as np +import pytest +from numpy.testing import assert_array_equal + +pytest.importorskip("sklearn") + +from sklearn.base import clone +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne.decoding.time_frequency import TimeFrequency + + +def test_timefrequency_basic(): + """Test TimeFrequency.""" + # Init + n_freqs = 3 + freqs = [20, 21, 22] + tf = TimeFrequency(freqs, sfreq=100) + n_epochs, n_chans, n_times = 10, 2, 100 + X = np.random.rand(n_epochs, n_chans, n_times) + for output in ["avg_power", "foo", None]: + tf = TimeFrequency(freqs, output=output) + with pytest.raises(ValueError, match="Invalid value"): + tf.fit(X) + tf = clone(tf) + + # Clone estimator + freqs_array = np.array(np.asarray(freqs)) + tf = TimeFrequency(freqs_array, 100, "morlet", freqs_array / 5.0) + clone(tf) + + # Fit + assert not hasattr(tf, "fitted_") + tf.fit(X, None) + assert tf.fitted_ + + # Transform + tf = TimeFrequency(freqs, sfreq=100) + tf.fit_transform(X, None) + # 3-D X + Xt = tf.transform(X) + assert_array_equal(Xt.shape, [n_epochs, n_chans, n_freqs, n_times]) + # 2-D X + Xt = tf.fit_transform(X[:, 0, :]) + assert_array_equal(Xt.shape, [n_epochs, n_freqs, n_times]) + # 3-D with decim + tf = TimeFrequency(freqs, sfreq=100, decim=2) + Xt = tf.fit_transform(X) + assert_array_equal(Xt.shape, [n_epochs, n_chans, n_freqs, n_times // 2]) + + +@parametrize_with_checks([TimeFrequency([300, 400], 1000.0, n_cycles=0.25)]) +def test_sklearn_compliance(estimator, check): + """Test LinearModel compliance with sklearn.""" + pytest.importorskip("sklearn", minversion="1.6") # TODO VERSION remove on 1.6+ + check(estimator) diff --git a/mne-python/source/mne/decoding/tests/test_transformer.py b/mne-python/source/mne/decoding/tests/test_transformer.py new file mode 100644 index 0000000000000000000000000000000000000000..0660b358c3d71d6eeec597dc2cea0896087b167f --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_transformer.py @@ -0,0 +1,351 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_equal, +) + +pytest.importorskip("sklearn") + +from sklearn.decomposition import PCA +from sklearn.kernel_ridge import KernelRidge +from sklearn.pipeline import make_pipeline +from sklearn.preprocessing import StandardScaler +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne import Epochs, EpochsArray, create_info, io, pick_types, read_events +from mne.decoding import ( + FilterEstimator, + LinearModel, + PSDEstimator, + Scaler, + TemporalFilter, + UnsupervisedSpatialFilter, + Vectorizer, +) +from mne.defaults import DEFAULTS +from mne.utils import use_log_level + +tmin, tmax = -0.2, 0.5 +event_id = dict(aud_l=1, vis_l=3) +start, stop = 0, 8 +data_dir = Path(__file__).parents[2] / "io" / "tests" / "data" +raw_fname = data_dir / "test_raw.fif" +event_name = data_dir / "test-eve.fif" +info = create_info(2, 1000.0, "eeg") + + +@pytest.mark.parametrize( + "info, method", + [ + (True, None), + (True, dict(mag=5, grad=10, eeg=20)), + (False, "mean"), + (False, "median"), + ], +) +def test_scaler(info, method): + """Test methods of Scaler.""" + raw = io.read_raw_fif(raw_fname) + events = read_events(event_name) + picks = pick_types( + raw.info, meg=True, stim=False, ecg=False, eog=False, exclude="bads" + ) + picks = picks[1:13:3] + + epochs = Epochs( + raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), preload=True + ) + epochs_data = epochs.get_data(copy=False) + y = epochs.events[:, -1] + + epochs_data_t = epochs_data.transpose([1, 0, 2]) + + if info: + info = epochs.info + scaler = Scaler(info, method) + X = scaler.fit_transform(epochs_data, y) + assert_equal(X.shape, epochs_data.shape) + if method is None or isinstance(method, dict): + sd = DEFAULTS["scalings"] if method is None else method + stds = np.zeros(len(picks)) + for key in ("mag", "grad"): + stds[pick_types(epochs.info, meg=key)] = 1.0 / sd[key] + stds[pick_types(epochs.info, meg=False, eeg=True)] = 1.0 / sd["eeg"] + means = np.zeros(len(epochs.ch_names)) + elif method == "mean": + stds = np.array([np.std(ch_data) for ch_data in epochs_data_t]) + means = np.array([np.mean(ch_data) for ch_data in epochs_data_t]) + else: # median + percs = np.array( + [np.percentile(ch_data, [25, 50, 75]) for ch_data in epochs_data_t] + ) + stds = percs[:, 2] - percs[:, 0] + means = percs[:, 1] + assert_allclose( + X * stds[:, np.newaxis] + means[:, np.newaxis], + epochs_data, + rtol=1e-12, + atol=1e-20, + err_msg=method, + ) + + X2 = scaler.fit(epochs_data, y).transform(epochs_data) + assert_array_equal(X, X2) + + # inverse_transform + Xi = scaler.inverse_transform(X) + assert_array_almost_equal(epochs_data, Xi) + + # Test init exception + x = Scaler(None, None) + with pytest.raises(ValueError): + x.fit(epochs_data, y) + pytest.raises(ValueError, scaler.fit, "foo", y) + pytest.raises(ValueError, scaler.transform, "foo") + epochs_bad = Epochs( + raw, + events, + event_id, + 0, + 0.01, + baseline=None, + picks=np.arange(len(raw.ch_names)), + ) # non-data chs + scaler = Scaler(epochs_bad.info, None) + pytest.raises(ValueError, scaler.fit, epochs_bad.get_data(copy=False), y) + + +def test_filterestimator(): + """Test methods of FilterEstimator.""" + raw = io.read_raw_fif(raw_fname) + events = read_events(event_name) + picks = pick_types( + raw.info, meg=True, stim=False, ecg=False, eog=False, exclude="bads" + ) + picks = picks[1:13:3] + epochs = Epochs( + raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), preload=True + ) + epochs_data = epochs.get_data(copy=False) + + # Add tests for different combinations of l_freq and h_freq + filt = FilterEstimator(epochs.info, l_freq=40, h_freq=80) + y = epochs.events[:, -1] + X = filt.fit_transform(epochs_data, y) + assert X.shape == epochs_data.shape + assert_array_equal(filt.fit(epochs_data, y).transform(epochs_data), X) + + filt = FilterEstimator( + epochs.info, + l_freq=None, + h_freq=40, + filter_length="auto", + l_trans_bandwidth="auto", + h_trans_bandwidth="auto", + ) + y = epochs.events[:, -1] + X = filt.fit_transform(epochs_data, y) + + filt = FilterEstimator(epochs.info, l_freq=1, h_freq=1) + y = epochs.events[:, -1] + with pytest.warns(RuntimeWarning, match="longer than the signal"): + pytest.raises(ValueError, filt.fit_transform, epochs_data, y) + + filt = FilterEstimator( + epochs.info, + l_freq=40, + h_freq=None, + filter_length="auto", + l_trans_bandwidth="auto", + h_trans_bandwidth="auto", + ) + X = filt.fit_transform(epochs_data, y) + + # Test init exception + pytest.raises(ValueError, filt.fit, "foo", y) + pytest.raises(ValueError, filt.transform, "foo") + + +def test_psdestimator(): + """Test methods of PSDEstimator.""" + raw = io.read_raw_fif(raw_fname) + events = read_events(event_name) + picks = pick_types( + raw.info, meg=True, stim=False, ecg=False, eog=False, exclude="bads" + ) + picks = picks[1:13:3] + epochs = Epochs( + raw, events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), preload=True + ) + epochs_data = epochs.get_data(copy=False) + psd = PSDEstimator(2 * np.pi, 0, np.inf) + y = epochs.events[:, -1] + assert not hasattr(psd, "fitted_") + X = psd.fit_transform(epochs_data, y) + assert psd.fitted_ + + assert X.shape[0] == epochs_data.shape[0] + assert_array_equal(psd.fit(epochs_data, y).transform(epochs_data), X) + + # Test init exception + with pytest.raises(ValueError): + psd.fit("foo", y) + with pytest.raises(ValueError): + psd.transform("foo") + + +def test_vectorizer(): + """Test Vectorizer.""" + data = np.random.rand(150, 18, 6) + vect = Vectorizer() + result = vect.fit_transform(data) + assert_equal(result.ndim, 2) + + # check inverse_trasnform + orig_data = vect.inverse_transform(result) + assert_equal(orig_data.ndim, 3) + assert_array_equal(orig_data, data) + assert_array_equal(vect.inverse_transform(result[1:]), data[1:]) + + # check with different shape + assert_equal(vect.fit_transform(np.random.rand(150, 18, 6, 3)).shape, (150, 324)) + assert_equal(vect.fit_transform(data[1:]).shape, (149, 108)) + + # check if raised errors are working correctly + X = np.random.default_rng(0).standard_normal((105, 12, 3)) + y = np.arange(X.shape[0]) % 2 + pytest.raises(ValueError, vect.transform, X[..., np.newaxis]) + pytest.raises(ValueError, vect.inverse_transform, X[:, :-1]) + + # And that pipelines work properly + X_arr = EpochsArray(X, create_info(12, 1000.0, "eeg")) + vect.fit(X_arr) + clf = make_pipeline(Vectorizer(), StandardScaler(), LinearModel()) + clf.fit(X_arr, y) + + +def test_unsupervised_spatial_filter(): + """Test unsupervised spatial filter.""" + raw = io.read_raw_fif(raw_fname) + events = read_events(event_name) + picks = pick_types( + raw.info, meg=True, stim=False, ecg=False, eog=False, exclude="bads" + ) + picks = picks[1:13:3] + epochs = Epochs( + raw, + events, + event_id, + tmin, + tmax, + picks=picks, + preload=True, + baseline=None, + verbose=False, + ) + + # Test estimator (must be a transformer) + X = epochs.get_data(copy=False) + usf = UnsupervisedSpatialFilter(KernelRidge(2)) + with pytest.raises(ValueError, match="transform"): + usf.fit(X) + + # Test fit + n_components = 4 + usf = UnsupervisedSpatialFilter(PCA(n_components)) + usf.fit(X) + usf1 = UnsupervisedSpatialFilter(PCA(n_components)) + + # test transform + assert_equal(usf.transform(X).ndim, 3) + # test fit_transform + assert_array_almost_equal(usf.transform(X), usf1.fit_transform(X)) + assert_equal(usf.transform(X).shape[1], n_components) + assert_array_almost_equal(usf.inverse_transform(usf.transform(X)), X) + + # Test with average param + usf = UnsupervisedSpatialFilter(PCA(4), average=True) + usf.fit_transform(X) + usf = UnsupervisedSpatialFilter(PCA(4), 2) + with pytest.raises(TypeError, match="average must be"): + usf.fit(X) + + +def test_temporal_filter(): + """Test methods of TemporalFilter.""" + X = np.random.rand(5, 5, 1200) + + # Test init test + values = ( + ("10hz", None, 100.0, "auto"), + (5.0, "10hz", 100.0, "auto"), + (10.0, 20.0, 5.0, "auto"), + (None, None, 100.0, "5hz"), + ) + for low, high, sf, ltrans in values: + filt = TemporalFilter(low, high, sf, ltrans, fir_design="firwin") + pytest.raises(ValueError, filt.fit_transform, X) + + # Add tests for different combinations of l_freq and h_freq + for low, high in ((5.0, 15.0), (None, 15.0), (5.0, None)): + filt = TemporalFilter(low, high, sfreq=100.0, fir_design="firwin") + Xt = filt.fit_transform(X) + assert_array_equal(filt.fit_transform(X), Xt) + assert X.shape == Xt.shape + + # Test fit and transform numpy type check + with pytest.raises(ValueError): + filt.transform("foo") + + # Test with 2 dimensional data array + X = np.random.rand(101, 500) + filt = TemporalFilter( + l_freq=25.0, h_freq=50.0, sfreq=1000.0, filter_length=150, fir_design="firwin2" + ) + with use_log_level("error"): # warning about transition bandwidth + assert_equal(filt.fit_transform(X).shape, X.shape) + + +def test_bad_triage(): + """Test for gh-10924.""" + filt = TemporalFilter(l_freq=8, h_freq=60, sfreq=160.0) + # Used to fail with "ValueError: Effective band-stop frequency (135.0) is + # too high (maximum based on Nyquist is 80.0)" + assert not hasattr(filt, "fitted_") + filt.fit_transform(np.zeros((1, 1, 481))) + assert filt.fitted_ + + +@pytest.mark.filterwarnings("ignore:.*filter_length.*") +@parametrize_with_checks( + [ + FilterEstimator(info, l_freq=1, h_freq=10), + PSDEstimator(), + Scaler(scalings="mean"), + # Not easy to test Scaler(info) b/c number of channels must match + TemporalFilter(), + UnsupervisedSpatialFilter(PCA()), + Vectorizer(), + ] +) +def test_sklearn_compliance(estimator, check): + """Test LinearModel compliance with sklearn.""" + pytest.importorskip("sklearn", minversion="1.6") # TODO VERSION remove on 1.6+ + ignores = [] + if estimator.__class__.__name__ == "FilterEstimator": + ignores += [ + "check_estimators_overwrite_params", # we modify self.info + "check_methods_sample_order_invariance", # Filtering is not time invariant + ] + if any(ignore in str(check) for ignore in ignores): + return + check(estimator) diff --git a/mne-python/source/mne/decoding/tests/test_xdawn.py b/mne-python/source/mne/decoding/tests/test_xdawn.py new file mode 100644 index 0000000000000000000000000000000000000000..a2936686b59b72b2696217f12ee39e661fe4d5ff --- /dev/null +++ b/mne-python/source/mne/decoding/tests/test_xdawn.py @@ -0,0 +1,17 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import pytest + +pytest.importorskip("sklearn") +from sklearn.utils.estimator_checks import parametrize_with_checks + +from mne.decoding import XdawnTransformer + + +@pytest.mark.filterwarnings("ignore:.*Only one sample available.*") +@parametrize_with_checks([XdawnTransformer(reg="oas")]) # oas handles few sample cases +def test_sklearn_compliance(estimator, check): + """Test compliance with sklearn.""" + check(estimator) diff --git a/mne-python/source/mne/decoding/time_delaying_ridge.py b/mne-python/source/mne/decoding/time_delaying_ridge.py new file mode 100644 index 0000000000000000000000000000000000000000..6a754ed361dacdf3f70fc2a7c68366c1ec1e4c81 --- /dev/null +++ b/mne-python/source/mne/decoding/time_delaying_ridge.py @@ -0,0 +1,437 @@ +"""TimeDelayingRidge class.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +from scipy import linalg +from scipy.signal import fftconvolve +from scipy.sparse.csgraph import laplacian +from sklearn.base import BaseEstimator, RegressorMixin +from sklearn.utils.validation import check_is_fitted + +from ..cuda import _setup_cuda_fft_multiply_repeated +from ..filter import next_fast_len +from ..fixes import jit +from ..utils import ProgressBar, _check_option, logger, warn +from ._fixes import _check_n_features_3d, validate_data + + +def _compute_corrs( + X, y, smin, smax, n_jobs=None, fit_intercept=False, edge_correction=True +): + """Compute auto- and cross-correlations.""" + if fit_intercept: + # We could do this in the Fourier domain, too, but it should + # be a bit cleaner numerically to do it here. + X_offset = np.mean(X, axis=0) + y_offset = np.mean(y, axis=0) + if X.ndim == 3: + X_offset = X_offset.mean(axis=0) + y_offset = np.mean(y_offset, axis=0) + X = X - X_offset + y = y - y_offset + else: + X_offset = y_offset = 0.0 + if X.ndim == 2: + assert y.ndim == 2 + X = X[:, np.newaxis, :] + y = y[:, np.newaxis, :] + assert X.shape[:2] == y.shape[:2] + len_trf = smax - smin + len_x, n_epochs, n_ch_x = X.shape + len_y, n_epochs_y, n_ch_y = y.shape + assert len_x == len_y + assert n_epochs == n_epochs_y + + n_fft = next_fast_len(2 * X.shape[0] - 1) + + _, cuda_dict = _setup_cuda_fft_multiply_repeated( + n_jobs, [1.0], n_fft, "correlation calculations" + ) + del n_jobs # only used to set as CUDA + + # create our Toeplitz indexer + ij = np.empty((len_trf, len_trf), int) + for ii in range(len_trf): + ij[ii, ii:] = np.arange(len_trf - ii) + x = np.arange(n_fft - 1, n_fft - len_trf + ii, -1) + ij[ii + 1 :, ii] = x + + x_xt = np.zeros([n_ch_x * len_trf] * 2) + x_y = np.zeros((len_trf, n_ch_x, n_ch_y), order="F") + n = n_epochs * (n_ch_x * (n_ch_x + 1) // 2 + n_ch_x) + logger.info(f"Fitting {n_epochs} epochs, {n_ch_x} channels") + pb = ProgressBar(n, mesg="Sample") + count = 0 + pb.update(count) + for ei in range(n_epochs): + this_X = X[:, ei, :] + # XXX maybe this is what we should parallelize over CPUs at some point + X_fft = cuda_dict["rfft"](this_X, n=n_fft, axis=0) + X_fft_conj = X_fft.conj() + y_fft = cuda_dict["rfft"](y[:, ei, :], n=n_fft, axis=0) + + for ch0 in range(n_ch_x): + for oi, ch1 in enumerate(range(ch0, n_ch_x)): + this_result = cuda_dict["irfft"]( + X_fft[:, ch0] * X_fft_conj[:, ch1], n=n_fft, axis=0 + ) + # Our autocorrelation structure is a Toeplitz matrix, but + # it's faster to create the Toeplitz ourselves than use + # linalg.toeplitz. + this_result = this_result[ij] + # However, we need to adjust for coeffs that are cut off, + # i.e. the non-zero delays should not have the same AC value + # as the zero-delay ones (because they actually have fewer + # coefficients). + # + # These adjustments also follow a Toeplitz structure, so we + # construct a matrix of what has been left off, compute their + # inner products, and remove them. + if edge_correction: + _edge_correct(this_result, this_X, smax, smin, ch0, ch1) + + # Store the results in our output matrix + x_xt[ + ch0 * len_trf : (ch0 + 1) * len_trf, + ch1 * len_trf : (ch1 + 1) * len_trf, + ] += this_result + if ch0 != ch1: + x_xt[ + ch1 * len_trf : (ch1 + 1) * len_trf, + ch0 * len_trf : (ch0 + 1) * len_trf, + ] += this_result.T + count += 1 + pb.update(count) + + # compute the crosscorrelations + cc_temp = cuda_dict["irfft"]( + y_fft * X_fft_conj[:, slice(ch0, ch0 + 1)], n=n_fft, axis=0 + ) + if smin < 0 and smax >= 0: + x_y[:-smin, ch0] += cc_temp[smin:] + x_y[len_trf - smax :, ch0] += cc_temp[:smax] + else: + x_y[:, ch0] += cc_temp[smin:smax] + count += 1 + pb.update(count) + + x_y = np.reshape(x_y, (n_ch_x * len_trf, n_ch_y), order="F") + return x_xt, x_y, n_ch_x, X_offset, y_offset + + +@jit() +def _edge_correct(this_result, this_X, smax, smin, ch0, ch1): + if smax > 0: + tail = _toeplitz_dot(this_X[-1:-smax:-1, ch0], this_X[-1:-smax:-1, ch1]) + if smin > 0: + tail = tail[smin - 1 :, smin - 1 :] + this_result[max(-smin + 1, 0) :, max(-smin + 1, 0) :] -= tail + if smin < 0: + head = _toeplitz_dot(this_X[:-smin, ch0], this_X[:-smin, ch1])[::-1, ::-1] + if smax < 0: + head = head[:smax, :smax] + this_result[:-smin, :-smin] -= head + + +@jit() +def _toeplitz_dot(a, b): + """Create upper triangular Toeplitz matrices & compute the dot product.""" + # This is equivalent to: + # a = linalg.toeplitz(a) + # b = linalg.toeplitz(b) + # a[np.triu_indices(len(a), 1)] = 0 + # b[np.triu_indices(len(a), 1)] = 0 + # out = np.dot(a.T, b) + assert a.shape == b.shape and a.ndim == 1 + out = np.outer(a, b) + for ii in range(1, len(a)): + out[ii, ii:] += out[ii - 1, ii - 1 : -1] + out[ii + 1 :, ii] += out[ii:-1, ii - 1] + return out + + +def _compute_reg_neighbors(n_ch_x, n_delays, reg_type, method="direct", normed=False): + """Compute regularization parameter from neighbors.""" + known_types = ("ridge", "laplacian") + if isinstance(reg_type, str): + reg_type = (reg_type,) * 2 + if len(reg_type) != 2: + raise ValueError(f"reg_type must have two elements, got {len(reg_type)}") + for r in reg_type: + if r not in known_types: + raise ValueError(f"reg_type entries must be one of {known_types}, got {r}") + reg_time = reg_type[0] == "laplacian" and n_delays > 1 + reg_chs = reg_type[1] == "laplacian" and n_ch_x > 1 + if not reg_time and not reg_chs: + return np.eye(n_ch_x * n_delays) + # regularize time + if reg_time: + reg = np.eye(n_delays) + stride = n_delays + 1 + reg.flat[1::stride] += -1 + reg.flat[n_delays::stride] += -1 + reg.flat[n_delays + 1 : -n_delays - 1 : stride] += 1 + args = [reg] * n_ch_x + reg = linalg.block_diag(*args) + else: + reg = np.zeros((n_delays * n_ch_x,) * 2) + + # regularize features + if reg_chs: + block = n_delays * n_delays + row_offset = block * n_ch_x + stride = n_delays * n_ch_x + 1 + reg.flat[n_delays:-row_offset:stride] += -1 + reg.flat[n_delays + row_offset :: stride] += 1 + reg.flat[row_offset:-n_delays:stride] += -1 + reg.flat[: -(n_delays + row_offset) : stride] += 1 + assert np.array_equal(reg[::-1, ::-1], reg) + + if method == "direct": + if normed: + norm = np.sqrt(np.diag(reg)) + reg /= norm + reg /= norm[:, np.newaxis] + return reg + else: + # Use csgraph. Note that our -1's above are really the neighbors! + # If we ever want to allow arbitrary adjacency matrices, this is how + # we'd want to do it. + reg = laplacian(-reg, normed=normed) + return reg + + +def _fit_corrs(x_xt, x_y, n_ch_x, reg_type, alpha, n_ch_in): + """Fit the model using correlation matrices.""" + # do the regularized solving + n_ch_out = x_y.shape[1] + assert x_y.shape[0] % n_ch_x == 0 + n_delays = x_y.shape[0] // n_ch_x + reg = _compute_reg_neighbors(n_ch_x, n_delays, reg_type) + mat = x_xt + alpha * reg + # From sklearn + try: + # Note: we must use overwrite_a=False in order to be able to + # use the fall-back solution below in case a LinAlgError + # is raised + w = linalg.solve(mat, x_y, overwrite_a=False, assume_a="pos") + except np.linalg.LinAlgError: + warn( + "Singular matrix in solving dual problem. Using " + "least-squares solution instead." + ) + w = linalg.lstsq(mat, x_y, lapack_driver="gelsy")[0] + w = w.T.reshape([n_ch_out, n_ch_in, n_delays]) + return w + + +class TimeDelayingRidge(RegressorMixin, BaseEstimator): + """Ridge regression of data with time delays. + + Parameters + ---------- + tmin : int | float + The starting lag, in seconds (or samples if ``sfreq`` == 1). + Negative values correspond to times in the past. + tmax : int | float + The ending lag, in seconds (or samples if ``sfreq`` == 1). + Positive values correspond to times in the future. + Must be >= tmin. + sfreq : float + The sampling frequency used to convert times into samples. + alpha : float + The ridge (or laplacian) regularization factor. + reg_type : str | list + Can be ``"ridge"`` (default) or ``"laplacian"``. + Can also be a 2-element list specifying how to regularize in time + and across adjacent features. + fit_intercept : bool + If True (default), the sample mean is removed before fitting. + n_jobs : int | str + The number of jobs to use. Can be an int (default 1) or ``'cuda'``. + + .. versionadded:: 0.18 + edge_correction : bool + If True (default), correct the autocorrelation coefficients for + non-zero delays for the fact that fewer samples are available. + Disabling this speeds up performance at the cost of accuracy + depending on the relationship between epoch length and model + duration. Only used if ``estimator`` is float or None. + + .. versionadded:: 0.18 + + See Also + -------- + mne.decoding.ReceptiveField + + Notes + ----- + This class is meant to be used with :class:`mne.decoding.ReceptiveField` + by only implicitly doing the time delaying. For reasonable receptive + field and input signal sizes, it should be more CPU and memory + efficient by using frequency-domain methods (FFTs) to compute the + auto- and cross-correlations. + """ + + def __init__( + self, + tmin, + tmax, + sfreq, + alpha=0.0, + reg_type="ridge", + fit_intercept=True, + n_jobs=None, + edge_correction=True, + ): + self.tmin = tmin + self.tmax = tmax + self.sfreq = sfreq + self.alpha = alpha + self.reg_type = reg_type + self.fit_intercept = fit_intercept + self.edge_correction = edge_correction + self.n_jobs = n_jobs + + def __sklearn_tags__(self): + """...""" + tags = super().__sklearn_tags__() + tags.input_tags.three_d_array = True + tags.target_tags.one_d_labels = True + tags.target_tags.two_d_labels = True + tags.target_tags.multi_output = True + return tags + + @property + def _smin(self): + return int(round(self.tmin_ * self.sfreq_)) + + @property + def _smax(self): + return int(round(self.tmax_ * self.sfreq_)) + 1 + + def _check_data(self, X, y=None, reset=False): + if reset: + X, y = validate_data( + self, + X=X, + y=y, + reset=reset, + validate_separately=( # to take care of 3D y + dict(allow_nd=True), + dict(allow_nd=True, ensure_2d=False), + ), + ) + if X.ndim == 3: + assert y.ndim == 3 + assert X.shape[:2] == y.shape[:2] + else: + if y.ndim == 1: + y = y[:, np.newaxis] + assert y.ndim == 2 + _check_option("y.shape[0]", y.shape[0], (X.shape[0],)) + else: + X = validate_data(self, X=X, allow_nd=True, ensure_2d=False, reset=reset) + # Because when ensure_2d=True, sklearn takes n_features from X.shape[1], + # when we need X.shape[-1]. So we ensure 2D and check features ourselves. + if X.ndim == 1: + raise ValueError( + "Reshape your data either using array.reshape(-1, 1) if " + "your data has a single feature or array.reshape(1, -1) " + "if it contains a single sample." + ) + _check_n_features_3d(self, X, reset) + + return X, y + + def _validate_params(self, X): + self.tmin_ = float(self.tmin) + self.tmax_ = float(self.tmax) + self.sfreq_ = float(self.sfreq) + self.alpha_ = float(self.alpha) + if self.tmin_ > self.tmax_: + raise ValueError(f"tmin must be <= tmax, got {self.tmin_} and {self.tmax_}") + n_delays = self._smax - self._smin + min_samples = (n_delays + 1) // 2 + if X.shape[0] < min_samples: + raise ValueError( + f"Got n_samples = {X.shape[0]}, but at least {min_samples} " + f"are required to estimate {n_delays} delays." + ) + + def fit(self, X, y): + """Estimate the coefficients of the linear model. + + Parameters + ---------- + X : array, shape (n_samples[, n_epochs], n_features) + The training input samples to estimate the linear coefficients. + y : array, shape (n_samples[, n_epochs], n_outputs) + The target values. + + Returns + ------- + self : instance of TimeDelayingRidge + Returns the modified instance. + """ + X, y = self._check_data(X, y, reset=True) + self._validate_params(X) + # These are split into two functions because it's possible that we + # might want to allow people to do them separately (e.g., to test + # different regularization parameters). + self.cov_, x_y_, n_ch_x, X_offset, y_offset = _compute_corrs( + X, + y, + self._smin, + self._smax, + self.n_jobs, + self.fit_intercept, + self.edge_correction, + ) + self.coef_ = _fit_corrs( + self.cov_, x_y_, n_ch_x, self.reg_type, self.alpha_, n_ch_x + ) + # This is the sklearn formula from LinearModel (will be 0. for no fit) + if self.fit_intercept: + self.intercept_ = y_offset - np.dot(X_offset, self.coef_.sum(-1).T) + else: + self.intercept_ = 0.0 + return self + + def predict(self, X): + """Predict the output. + + Parameters + ---------- + X : array, shape (n_samples[, n_epochs], n_features) + The data. + + Returns + ------- + X : ndarray + The predicted response. + """ + check_is_fitted(self) + X, _ = self._check_data(X) + if X.ndim == 2: + X = X[:, np.newaxis, :] + singleton = True + else: + singleton = False + out = np.zeros(X.shape[:2] + (self.coef_.shape[0],)) + smin = self._smin + offset = max(smin, 0) + for ei in range(X.shape[1]): + for oi in range(self.coef_.shape[0]): + for fi in range(self.coef_.shape[1]): + temp = fftconvolve(X[:, ei, fi], self.coef_[oi, fi]) + temp = temp[max(-smin, 0) :][: len(out) - offset] + out[offset : len(temp) + offset, ei, oi] += temp + out += self.intercept_ + if singleton: + out = out[:, 0, :] + out = out.squeeze() + return out diff --git a/mne-python/source/mne/decoding/time_frequency.py b/mne-python/source/mne/decoding/time_frequency.py new file mode 100644 index 0000000000000000000000000000000000000000..29232aaeb9fc45ea4260303d716fc6bed754ece3 --- /dev/null +++ b/mne-python/source/mne/decoding/time_frequency.py @@ -0,0 +1,182 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +from sklearn.base import BaseEstimator +from sklearn.utils.validation import check_is_fitted + +from ..time_frequency.tfr import _compute_tfr +from ..utils import _check_option, fill_doc +from .transformer import MNETransformerMixin + + +@fill_doc +class TimeFrequency(MNETransformerMixin, BaseEstimator): + """Time frequency transformer. + + Time-frequency transform of times series along the last axis. + + Parameters + ---------- + freqs : array-like of float, shape (n_freqs,) + The frequencies. + sfreq : float | int, default 1.0 + Sampling frequency of the data. + method : 'multitaper' | 'morlet', default 'morlet' + The time-frequency method. 'morlet' convolves a Morlet wavelet. + 'multitaper' uses Morlet wavelets windowed with multiple DPSS + multitapers. + n_cycles : float | array of float, default 7.0 + Number of cycles in the Morlet wavelet. Fixed number + or one per frequency. + time_bandwidth : float, default None + If None and method=multitaper, will be set to 4.0 (3 tapers). + Time x (Full) Bandwidth product. Only applies if + method == 'multitaper'. The number of good tapers (low-bias) is + chosen automatically based on this to equal floor(time_bandwidth - 1). + use_fft : bool, default True + Use the FFT for convolutions or not. + decim : int | slice, default 1 + To reduce memory usage, decimation factor after time-frequency + decomposition. + If `int`, returns tfr[..., ::decim]. + If `slice`, returns tfr[..., decim]. + + .. note:: Decimation may create aliasing artifacts, yet decimation + is done after the convolutions. + + output : str, default 'complex' + * 'complex' : single trial complex. + * 'power' : single trial power. + * 'phase' : single trial phase. + %(n_jobs)s + The number of epochs to process at the same time. The parallelization + is implemented across channels. + %(verbose)s + + See Also + -------- + mne.time_frequency.tfr_morlet + mne.time_frequency.tfr_multitaper + """ + + def __init__( + self, + freqs, + sfreq=1.0, + method="morlet", + n_cycles=7.0, + time_bandwidth=None, + use_fft=True, + decim=1, + output="complex", + n_jobs=1, + verbose=None, + ): + """Init TimeFrequency transformer.""" + self.freqs = freqs + self.sfreq = sfreq + self.method = method + self.n_cycles = n_cycles + self.time_bandwidth = time_bandwidth + self.use_fft = use_fft + self.decim = decim + # Check that output is not an average metric (e.g. ITC) + self.output = output + self.n_jobs = n_jobs + self.verbose = verbose + + def __sklearn_tags__(self): + """Return sklearn tags.""" + out = super().__sklearn_tags__() + from sklearn.utils import TransformerTags + + if out.transformer_tags is None: + out.transformer_tags = TransformerTags() + out.transformer_tags.preserves_dtype = [] # real->complex + return out + + def fit_transform(self, X, y=None): + """Time-frequency transform of times series along the last axis. + + Parameters + ---------- + X : array, shape (n_samples, n_channels, n_times) + The training data samples. The channel dimension can be zero- or + 1-dimensional. + y : None + For scikit-learn compatibility purposes. + + Returns + ------- + Xt : array, shape (n_samples, n_channels, n_freqs, n_times) + The time-frequency transform of the data, where n_channels can be + zero- or 1-dimensional. + """ + return self.fit(X, y).transform(X) + + def fit(self, X, y=None): # noqa: D401 + """Do nothing (for scikit-learn compatibility purposes). + + Parameters + ---------- + X : array, shape (n_samples, n_channels, n_times) + The training data. + y : array | None + The target values. + + Returns + ------- + self : object + Return self. + """ + # Check non-average output + _check_option("output", self.output, ["complex", "power", "phase"]) + self._check_data(X, y=y, fit=True) + self.fitted_ = True + return self + + def transform(self, X): + """Time-frequency transform of times series along the last axis. + + Parameters + ---------- + X : array, shape (n_samples, [n_channels, ]n_times) + The training data samples. The channel dimension can be zero- or + 1-dimensional. + + Returns + ------- + Xt : array, shape (n_samples, [n_channels, ]n_freqs, n_times) + The time-frequency transform of the data, where n_channels can be + zero- or 1-dimensional. + """ + X = self._check_data(X, atleast_3d=False) + check_is_fitted(self, "fitted_") + # Ensure 3-dimensional X + shape = X.shape[1:-1] + if not shape: + X = X[:, np.newaxis, :] + + # Compute time-frequency + Xt = _compute_tfr( + X, + freqs=self.freqs, + sfreq=self.sfreq, + method=self.method, + n_cycles=self.n_cycles, + zero_mean=True, + time_bandwidth=self.time_bandwidth, + use_fft=self.use_fft, + decim=self.decim, + output=self.output, + n_jobs=self.n_jobs, + verbose=self.verbose, + ) + + # Back to original shape + if not shape: + Xt = Xt[:, 0, :] + + return Xt diff --git a/mne-python/source/mne/decoding/transformer.py b/mne-python/source/mne/decoding/transformer.py new file mode 100644 index 0000000000000000000000000000000000000000..c5b3a5ca704610e8f720efe80863b02ca6916a5f --- /dev/null +++ b/mne-python/source/mne/decoding/transformer.py @@ -0,0 +1,952 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +from sklearn.base import BaseEstimator, TransformerMixin, check_array, clone +from sklearn.preprocessing import RobustScaler, StandardScaler +from sklearn.utils import check_X_y +from sklearn.utils.validation import check_is_fitted + +from .._fiff.pick import ( + _pick_data_channels, + _picks_by_type, + _picks_to_idx, + pick_info, +) +from ..cov import _check_scalings_user +from ..epochs import BaseEpochs +from ..filter import filter_data +from ..fixes import _reshape_view +from ..time_frequency import psd_array_multitaper +from ..utils import _check_option, _validate_type, check_version, fill_doc +from ._fixes import validate_data + + +class MNETransformerMixin(TransformerMixin): + """TransformerMixin plus some helpers.""" + + def _check_data( + self, + epochs_data, + *, + y=None, + atleast_3d=True, + fit=False, + return_y=False, + multi_output=False, + check_n_features=True, + ): + # Sklearn calls asarray under the hood which works, but elsewhere they check for + # __len__ then look at the size of obj[0]... which is an epoch of shape (1, ...) + # rather than what they expect (shape (...)). So we explicitly get the NumPy + # array to make everyone happy. + if isinstance(epochs_data, BaseEpochs): + epochs_data = epochs_data.get_data(copy=False) + kwargs = dict(dtype=np.float64, allow_nd=True, order="C") + if check_version("sklearn", "1.5"): # TODO VERSION sklearn 1.5+ + kwargs["force_writeable"] = True + if hasattr(self, "n_features_in_") and check_n_features: + if y is None: + epochs_data = validate_data( + self, + epochs_data, + **kwargs, + reset=fit, + ) + else: + epochs_data, y = validate_data( + self, + epochs_data, + y, + **kwargs, + reset=fit, + ) + elif y is None: + epochs_data = check_array(epochs_data, **kwargs) + else: + epochs_data, y = check_X_y( + X=epochs_data, y=y, multi_output=multi_output, **kwargs + ) + if fit: + self.n_features_in_ = epochs_data.shape[1] + if atleast_3d: + epochs_data = np.atleast_3d(epochs_data) + return (epochs_data, y) if return_y else epochs_data + + +class _ConstantScaler: + """Scale channel types using constant values.""" + + def __init__(self, info, scalings, do_scaling=True): + self._scalings = scalings + self._info = info + self._do_scaling = do_scaling + + def fit(self, X, y=None): + scalings = _check_scalings_user(self._scalings) + picks_by_type = _picks_by_type( + pick_info(self._info, _pick_data_channels(self._info, exclude=())) + ) + std = np.ones(sum(len(p[1]) for p in picks_by_type)) + if X.shape[1] != len(std): + raise ValueError( + f"info had {len(std)} data channels but X has {len(X)} channels" + ) + if self._do_scaling: # this is silly, but necessary for completeness + for kind, picks in picks_by_type: + std[picks] = 1.0 / scalings[kind] + self.std_ = std + self.mean_ = np.zeros_like(std) + return self + + def transform(self, X): + return X / self.std_ + + def inverse_transform(self, X, y=None): + return X * self.std_ + + def fit_transform(self, X, y=None): + return self.fit(X, y).transform(X) + + +def _sklearn_reshape_apply(func, return_result, X, *args, **kwargs): + """Reshape epochs and apply function.""" + _validate_type(X, np.ndarray, "X") + if X.size == 0: + return X.copy() if return_result else None + orig_shape = X.shape + X = np.reshape(X.transpose(0, 2, 1), (-1, orig_shape[1])) + X = func(X, *args, **kwargs) + if return_result: + X = _reshape_view(X, (orig_shape[0], orig_shape[2], orig_shape[1])) + X = X.transpose(0, 2, 1) + return X + + +@fill_doc +class Scaler(MNETransformerMixin, BaseEstimator): + """Standardize channel data. + + This class scales data for each channel. It differs from scikit-learn + classes (e.g., :class:`sklearn.preprocessing.StandardScaler`) in that + it scales each *channel* by estimating μ and σ using data from all + time points and epochs, as opposed to standardizing each *feature* + (i.e., each time point for each channel) by estimating using μ and σ + using data from all epochs. + + Parameters + ---------- + %(info)s Only necessary if ``scalings`` is a dict or None. + scalings : dict, str, default None + Scaling method to be applied to data channel wise. + + * if scalings is None (default), scales mag by 1e15, grad by 1e13, + and eeg by 1e6. + * if scalings is :class:`dict`, keys are channel types and values + are scale factors. + * if ``scalings=='median'``, + :class:`sklearn.preprocessing.RobustScaler` + is used (requires sklearn version 0.17+). + * if ``scalings=='mean'``, + :class:`sklearn.preprocessing.StandardScaler` + is used. + + with_mean : bool, default True + If True, center the data using mean (or median) before scaling. + Ignored for channel-type scaling. + with_std : bool, default True + If True, scale the data to unit variance (``scalings='mean'``), + quantile range (``scalings='median``), or using channel type + if ``scalings`` is a dict or None). + """ + + def __init__(self, info=None, scalings=None, with_mean=True, with_std=True): + self.info = info + self.with_mean = with_mean + self.with_std = with_std + self.scalings = scalings + + def fit(self, epochs_data, y=None): + """Standardize data across channels. + + Parameters + ---------- + epochs_data : array, shape (n_epochs, n_channels, n_times) + The data to concatenate channels. + y : array, shape (n_epochs,) + The label for each epoch. + + Returns + ------- + self : instance of Scaler + The modified instance. + """ + epochs_data = self._check_data(epochs_data, y=y, fit=True, multi_output=True) + assert epochs_data.ndim == 3, epochs_data.shape + + _validate_type(self.scalings, (dict, str, type(None)), "scalings") + if isinstance(self.scalings, str): + _check_option( + "scalings", self.scalings, ["mean", "median"], extra="when str" + ) + if self.scalings is None or isinstance(self.scalings, dict): + if self.info is None: + raise ValueError( + f'Need to specify "info" if scalings is {type(self.scalings)}' + ) + self.scaler_ = _ConstantScaler(self.info, self.scalings, self.with_std) + elif self.scalings == "mean": + self.scaler_ = StandardScaler( + with_mean=self.with_mean, with_std=self.with_std + ) + else: # scalings == 'median': + self.scaler_ = RobustScaler( + with_centering=self.with_mean, with_scaling=self.with_std + ) + + _sklearn_reshape_apply(self.scaler_.fit, False, epochs_data, y=y) + return self + + def transform(self, epochs_data): + """Standardize data across channels. + + Parameters + ---------- + epochs_data : array, shape (n_epochs, n_channels[, n_times]) + The data. + + Returns + ------- + X : array, shape (n_epochs, n_channels, n_times) + The data concatenated over channels. + + Notes + ----- + This function makes a copy of the data before the operations and the + memory usage may be large with big data. + """ + check_is_fitted(self, "scaler_") + epochs_data = self._check_data(epochs_data, atleast_3d=False) + if epochs_data.ndim == 2: # can happen with SlidingEstimator + if self.info is not None: + assert len(self.info["ch_names"]) == epochs_data.shape[1] + epochs_data = epochs_data[..., np.newaxis] + assert epochs_data.ndim == 3, epochs_data.shape + return _sklearn_reshape_apply(self.scaler_.transform, True, epochs_data) + + def fit_transform(self, epochs_data, y=None): + """Fit to data, then transform it. + + Fits transformer to epochs_data and y and returns a transformed version + of epochs_data. + + Parameters + ---------- + epochs_data : array, shape (n_epochs, n_channels, n_times) + The data. + y : None | array, shape (n_epochs,) + The label for each epoch. + Defaults to None. + + Returns + ------- + X : array, shape (n_epochs, n_channels, n_times) + The data concatenated over channels. + + Notes + ----- + This function makes a copy of the data before the operations and the + memory usage may be large with big data. + """ + return self.fit(epochs_data, y).transform(epochs_data) + + def inverse_transform(self, epochs_data): + """Invert standardization of data across channels. + + Parameters + ---------- + epochs_data : array, shape ([n_epochs, ]n_channels, n_times) + The data. + + Returns + ------- + X : array, shape (n_epochs, n_channels, n_times) + The data concatenated over channels. + + Notes + ----- + This function makes a copy of the data before the operations and the + memory usage may be large with big data. + """ + epochs_data = self._check_data(epochs_data, atleast_3d=False) + squeeze = False + # Can happen with CSP + if epochs_data.ndim == 2: + squeeze = True + epochs_data = epochs_data[..., np.newaxis] + assert epochs_data.ndim == 3, epochs_data.shape + out = _sklearn_reshape_apply(self.scaler_.inverse_transform, True, epochs_data) + if squeeze: + out = out[..., 0] + return out + + +class Vectorizer(MNETransformerMixin, BaseEstimator): + """Transform n-dimensional array into 2D array of n_samples by n_features. + + This class reshapes an n-dimensional array into an n_samples * n_features + array, usable by the estimators and transformers of scikit-learn. + + Attributes + ---------- + features_shape_ : tuple + Stores the original shape of data. + + Examples + -------- + >>> from sklearn.linear_model import LogisticRegression + >>> from sklearn.pipeline import make_pipeline + >>> from sklearn.preprocessing import StandardScaler + >>> clf = make_pipeline(Vectorizer(), StandardScaler(), LogisticRegression()) + """ + + def fit(self, X, y=None): + """Store the shape of the features of X. + + Parameters + ---------- + X : array-like + The data to fit. Can be, for example a list, or an array of at + least 2d. The first dimension must be of length n_samples, where + samples are the independent samples used by the estimator + (e.g. n_epochs for epoched data). + y : None | array, shape (n_samples,) + Used for scikit-learn compatibility. + + Returns + ------- + self : instance of Vectorizer + Return the modified instance. + """ + X = self._check_data(X, y=y, atleast_3d=False, fit=True, check_n_features=False) + self.features_shape_ = X.shape[1:] + return self + + def transform(self, X): + """Convert given array into two dimensions. + + Parameters + ---------- + X : array-like + The data to fit. Can be, for example a list, or an array of at + least 2d. The first dimension must be of length n_samples, where + samples are the independent samples used by the estimator + (e.g. n_epochs for epoched data). + + Returns + ------- + X : array, shape (n_samples, n_features) + The transformed data. + """ + X = self._check_data(X, atleast_3d=False) + if X.shape[1:] != self.features_shape_: + raise ValueError("Shape of X used in fit and transform must be same") + return X.reshape(len(X), -1) + + def fit_transform(self, X, y=None): + """Fit the data, then transform in one step. + + Parameters + ---------- + X : array-like + The data to fit. Can be, for example a list, or an array of at + least 2d. The first dimension must be of length n_samples, where + samples are the independent samples used by the estimator + (e.g. n_epochs for epoched data). + y : None | array, shape (n_samples,) + Used for scikit-learn compatibility. + + Returns + ------- + X : array, shape (n_samples, -1) + The transformed data. + """ + return self.fit(X).transform(X) + + def inverse_transform(self, X): + """Transform 2D data back to its original feature shape. + + Parameters + ---------- + X : array-like, shape (n_samples, n_features) + Data to be transformed back to original shape. + + Returns + ------- + X : array + The data transformed into shape as used in fit. The first + dimension is of length n_samples. + """ + X = self._check_data(X, atleast_3d=False, check_n_features=False) + if X.ndim not in (2, 3): + raise ValueError( + f"X should be of 2 or 3 dimensions but has shape {X.shape}" + ) + return X.reshape(X.shape[:-1] + self.features_shape_) + + +@fill_doc +class PSDEstimator(MNETransformerMixin, BaseEstimator): + """Compute power spectral density (PSD) using a multi-taper method. + + Parameters + ---------- + sfreq : float + The sampling frequency. + fmin : float + The lower frequency of interest. + fmax : float + The upper frequency of interest. + bandwidth : float + The bandwidth of the multi taper windowing function in Hz. + adaptive : bool + Use adaptive weights to combine the tapered spectra into PSD + (slow, use n_jobs >> 1 to speed up computation). + low_bias : bool + Only use tapers with more than 90%% spectral concentration within + bandwidth. + n_jobs : int + Number of parallel jobs to use (only used if adaptive=True). + %(normalization)s + + See Also + -------- + mne.time_frequency.psd_array_multitaper + mne.io.Raw.compute_psd + mne.Epochs.compute_psd + mne.Evoked.compute_psd + """ + + def __init__( + self, + sfreq=2 * np.pi, + fmin=0, + fmax=np.inf, + bandwidth=None, + adaptive=False, + low_bias=True, + n_jobs=None, + normalization="length", + ): + self.sfreq = sfreq + self.fmin = fmin + self.fmax = fmax + self.bandwidth = bandwidth + self.adaptive = adaptive + self.low_bias = low_bias + self.n_jobs = n_jobs + self.normalization = normalization + + def __sklearn_tags__(self): + """...""" + tags = super().__sklearn_tags__() + tags.target_tags.required = False + tags.requires_fit = False + return tags + + def fit(self, epochs_data, y=None): + """Compute power spectral density (PSD) using a multi-taper method. + + Parameters + ---------- + epochs_data : array, shape (n_epochs, n_channels, n_times) + The data. + y : array, shape (n_epochs,) + The label for each epoch. + + Returns + ------- + self : instance of PSDEstimator + The modified instance. + """ + self._check_data(epochs_data, y=y, fit=True) + self.fitted_ = True # sklearn compliance + return self + + def transform(self, epochs_data): + """Compute power spectral density (PSD) using a multi-taper method. + + Parameters + ---------- + epochs_data : array, shape (n_epochs, n_channels, n_times) + The data. + + Returns + ------- + psd : array, shape (n_signals, n_freqs) or (n_freqs,) + The computed PSD. + """ + epochs_data = self._check_data(epochs_data) + psd, _ = psd_array_multitaper( + epochs_data, + sfreq=self.sfreq, + fmin=self.fmin, + fmax=self.fmax, + bandwidth=self.bandwidth, + adaptive=self.adaptive, + low_bias=self.low_bias, + normalization=self.normalization, + n_jobs=self.n_jobs, + ) + return psd + + +@fill_doc +class FilterEstimator(MNETransformerMixin, BaseEstimator): + """Estimator to filter RtEpochs. + + Applies a zero-phase low-pass, high-pass, band-pass, or band-stop + filter to the channels selected by "picks". + + l_freq and h_freq are the frequencies below which and above which, + respectively, to filter out of the data. Thus the uses are: + + - l_freq < h_freq: band-pass filter + - l_freq > h_freq: band-stop filter + - l_freq is not None, h_freq is None: low-pass filter + - l_freq is None, h_freq is not None: high-pass filter + + If n_jobs > 1, more memory is required as "len(picks) * n_times" + additional time points need to be temporarily stored in memory. + + Parameters + ---------- + %(info_not_none)s + %(l_freq)s + %(h_freq)s + %(picks_good_data)s + %(filter_length)s + %(l_trans_bandwidth)s + %(h_trans_bandwidth)s + n_jobs : int | str + Number of jobs to run in parallel. + Can be 'cuda' if ``cupy`` is installed properly and method='fir'. + method : str + 'fir' will use overlap-add FIR filtering, 'iir' will use IIR filtering. + iir_params : dict | None + Dictionary of parameters to use for IIR filtering. + See mne.filter.construct_iir_filter for details. If iir_params + is None and method="iir", 4th order Butterworth will be used. + %(fir_design)s + + See Also + -------- + TemporalFilter + + Notes + ----- + This is primarily meant for use in realtime applications. + In general it is not recommended in a normal processing pipeline as it may result + in edge artifacts. Use with caution. + """ + + def __init__( + self, + info, + l_freq, + h_freq, + picks=None, + filter_length="auto", + l_trans_bandwidth="auto", + h_trans_bandwidth="auto", + n_jobs=None, + method="fir", + iir_params=None, + fir_design="firwin", + ): + self.info = info + self.l_freq = l_freq + self.h_freq = h_freq + self.picks = picks + self.filter_length = filter_length + self.l_trans_bandwidth = l_trans_bandwidth + self.h_trans_bandwidth = h_trans_bandwidth + self.n_jobs = n_jobs + self.method = method + self.iir_params = iir_params + self.fir_design = fir_design + + def fit(self, epochs_data, y): + """Filter data. + + Parameters + ---------- + epochs_data : array, shape (n_epochs, n_channels, n_times) + The data. + y : array, shape (n_epochs,) + The label for each epoch. + + Returns + ------- + self : instance of FilterEstimator + The modified instance. + """ + self.picks_ = _picks_to_idx(self.info, self.picks) + self._check_data(epochs_data, y=y, fit=True) + + if self.l_freq == 0: + self.l_freq = None + + if self.info["lowpass"] is None or ( + self.h_freq is not None + and (self.l_freq is None or self.l_freq < self.h_freq) + and self.h_freq < self.info["lowpass"] + ): + with self.info._unlock(): + self.info["lowpass"] = self.h_freq + + if self.info["highpass"] is None or ( + self.l_freq is not None + and (self.h_freq is None or self.l_freq < self.h_freq) + and self.l_freq > self.info["highpass"] + ): + with self.info._unlock(): + self.info["highpass"] = self.l_freq + + return self + + def transform(self, epochs_data): + """Filter data. + + Parameters + ---------- + epochs_data : array, shape (n_epochs, n_channels, n_times) + The data. + + Returns + ------- + X : array, shape (n_epochs, n_channels, n_times) + The data after filtering. + """ + return filter_data( + self._check_data(epochs_data), + self.info["sfreq"], + self.l_freq, + self.h_freq, + self.picks_, + self.filter_length, + self.l_trans_bandwidth, + self.h_trans_bandwidth, + method=self.method, + iir_params=self.iir_params, + n_jobs=self.n_jobs, + copy=False, + fir_design=self.fir_design, + verbose=False, + ) + + +class UnsupervisedSpatialFilter(MNETransformerMixin, BaseEstimator): + """Use unsupervised spatial filtering across time and samples. + + Parameters + ---------- + estimator : instance of sklearn.base.BaseEstimator + Estimator using some decomposition algorithm. + average : bool, default False + If True, the estimator is fitted on the average across samples + (e.g. epochs). + """ + + def __init__(self, estimator, average=False): + self.estimator = estimator + self.average = average + + def fit(self, X, y=None): + """Fit the spatial filters. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_times) + The data to be filtered. + y : None | array, shape (n_samples,) + Used for scikit-learn compatibility. + + Returns + ------- + self : instance of UnsupervisedSpatialFilter + Return the modified instance. + """ + # sklearn.utils.estimator_checks.check_estimator(self.estimator) is probably + # too strict for us, given that we don't fully adhere yet, so just check attrs + for attr in ("fit", "transform", "fit_transform"): + if not hasattr(self.estimator, attr): + raise ValueError( + "estimator must be a scikit-learn " + f"transformer, missing {attr} method" + ) + _validate_type(self.average, bool, "average") + X = self._check_data(X, y=y, fit=True) + if self.average: + X = np.mean(X, axis=0).T + else: + n_epochs, n_channels, n_times = X.shape + # trial as time samples + X = np.transpose(X, (1, 0, 2)).reshape((n_channels, n_epochs * n_times)).T + + self.estimator_ = clone(self.estimator) + self.estimator_.fit(X) + return self + + def fit_transform(self, X, y=None): + """Transform the data to its filtered components after fitting. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_times) + The data to be filtered. + y : None | array, shape (n_samples,) + Used for scikit-learn compatibility. + + Returns + ------- + X : array, shape (n_epochs, n_channels, n_times) + The transformed data. + """ + return self.fit(X).transform(X) + + def transform(self, X): + """Transform the data to its spatial filters. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_times) + The data to be filtered. + + Returns + ------- + X : array, shape (n_epochs, n_channels, n_times) + The transformed data. + """ + check_is_fitted(self.estimator_) + X = self._check_data(X) + return self._apply_method(X, "transform") + + def inverse_transform(self, X): + """Inverse transform the data to its original space. + + Parameters + ---------- + X : array, shape (n_epochs, n_components, n_times) + The data to be inverted. + + Returns + ------- + X : array, shape (n_epochs, n_channels, n_times) + The transformed data. + """ + return self._apply_method(X, "inverse_transform") + + def _apply_method(self, X, method): + """Vectorize time samples as trials, apply method and reshape back. + + Parameters + ---------- + X : array, shape (n_epochs, n_dims, n_times) + The data to be inverted. + + Returns + ------- + X : array, shape (n_epochs, n_dims, n_times) + The transformed data. + """ + n_epochs, n_channels, n_times = X.shape + # trial as time samples + X = np.transpose(X, [1, 0, 2]) + X = np.reshape(X, [n_channels, n_epochs * n_times]).T + # apply method + method = getattr(self.estimator_, method) + X = method(X) + # put it back to n_epochs, n_dimensions + X = np.reshape(X.T, [-1, n_epochs, n_times]).transpose([1, 0, 2]) + return X + + +@fill_doc +class TemporalFilter(MNETransformerMixin, BaseEstimator): + """Estimator to filter data array along the last dimension. + + Applies a zero-phase low-pass, high-pass, band-pass, or band-stop + filter to the channels. + + l_freq and h_freq are the frequencies below which and above which, + respectively, to filter out of the data. Thus the uses are: + + - l_freq < h_freq: band-pass filter + - l_freq > h_freq: band-stop filter + - l_freq is not None, h_freq is None: low-pass filter + - l_freq is None, h_freq is not None: high-pass filter + + See :func:`mne.filter.filter_data`. + + Parameters + ---------- + l_freq : float | None + Low cut-off frequency in Hz. If None the data are only low-passed. + h_freq : float | None + High cut-off frequency in Hz. If None the data are only + high-passed. + sfreq : float, default 1.0 + Sampling frequency in Hz. + filter_length : str | int, default 'auto' + Length of the FIR filter to use (if applicable): + + * int: specified length in samples. + * 'auto' (default in 0.14): the filter length is chosen based + on the size of the transition regions (7 times the reciprocal + of the shortest transition band). + * str: (default in 0.13 is "10s") a human-readable time in + units of "s" or "ms" (e.g., "10s" or "5500ms") will be + converted to that number of samples if ``phase="zero"``, or + the shortest power-of-two length at least that duration for + ``phase="zero-double"``. + + l_trans_bandwidth : float | str + Width of the transition band at the low cut-off frequency in Hz + (high pass or cutoff 1 in bandpass). Can be "auto" + (default in 0.14) to use a multiple of ``l_freq``:: + + min(max(l_freq * 0.25, 2), l_freq) + + Only used for ``method='fir'``. + h_trans_bandwidth : float | str + Width of the transition band at the high cut-off frequency in Hz + (low pass or cutoff 2 in bandpass). Can be "auto" + (default in 0.14) to use a multiple of ``h_freq``:: + + min(max(h_freq * 0.25, 2.), info['sfreq'] / 2. - h_freq) + + Only used for ``method='fir'``. + n_jobs : int | str, default 1 + Number of jobs to run in parallel. + Can be 'cuda' if ``cupy`` is installed properly and method='fir'. + method : str, default 'fir' + 'fir' will use overlap-add FIR filtering, 'iir' will use IIR + forward-backward filtering (via filtfilt). + iir_params : dict | None, default None + Dictionary of parameters to use for IIR filtering. + See mne.filter.construct_iir_filter for details. If iir_params + is None and method="iir", 4th order Butterworth will be used. + fir_window : str, default 'hamming' + The window to use in FIR design, can be "hamming", "hann", + or "blackman". + fir_design : str + Can be "firwin" (default) to use :func:`scipy.signal.firwin`, + or "firwin2" to use :func:`scipy.signal.firwin2`. "firwin" uses + a time-domain design technique that generally gives improved + attenuation using fewer samples than "firwin2". + + .. versionadded:: 0.15 + + See Also + -------- + FilterEstimator + Vectorizer + mne.filter.filter_data + """ + + def __init__( + self, + l_freq=None, + h_freq=None, + sfreq=1.0, + filter_length="auto", + l_trans_bandwidth="auto", + h_trans_bandwidth="auto", + n_jobs=None, + method="fir", + iir_params=None, + fir_window="hamming", + fir_design="firwin", + ): + self.l_freq = l_freq + self.h_freq = h_freq + self.sfreq = sfreq + self.filter_length = filter_length + self.l_trans_bandwidth = l_trans_bandwidth + self.h_trans_bandwidth = h_trans_bandwidth + self.n_jobs = n_jobs + self.method = method + self.iir_params = iir_params + self.fir_window = fir_window + self.fir_design = fir_design + + def __sklearn_tags__(self): + """...""" + tags = super().__sklearn_tags__() + tags.target_tags.required = False + tags.requires_fit = False + return tags + + def fit(self, X, y=None): + """Do nothing (for scikit-learn compatibility purposes). + + Parameters + ---------- + X : array, shape ([n_epochs, ]n_channels, n_times) + The data to be filtered over the last dimension. The channels + dimension can be zero when passing a 2D array. + y : None + Not used, for scikit-learn compatibility issues. + + Returns + ------- + self : instance of TemporalFilter + The modified instance. + """ + self.fitted_ = True # sklearn compliance + self._check_data(X, y=y, atleast_3d=False, fit=True) + return self + + def transform(self, X): + """Filter data along the last dimension. + + Parameters + ---------- + X : array, shape ([n_epochs, ]n_channels, n_times) + The data to be filtered over the last dimension. The channels + dimension can be zero when passing a 2D array. + + Returns + ------- + X : array + The data after filtering. + """ # noqa: E501 + X = self._check_data(X, atleast_3d=False) + X = np.atleast_2d(X) + + if X.ndim > 3: + raise ValueError( + "Array must be of at max 3 dimensions instead " + f"got {X.ndim} dimensional matrix" + ) + + shape = X.shape + X = X.reshape(-1, shape[-1]) + X = filter_data( + X, + self.sfreq, + self.l_freq, + self.h_freq, + filter_length=self.filter_length, + l_trans_bandwidth=self.l_trans_bandwidth, + h_trans_bandwidth=self.h_trans_bandwidth, + n_jobs=self.n_jobs, + method=self.method, + iir_params=self.iir_params, + copy=False, + fir_window=self.fir_window, + fir_design=self.fir_design, + ) + return X.reshape(shape) diff --git a/mne-python/source/mne/decoding/xdawn.py b/mne-python/source/mne/decoding/xdawn.py new file mode 100644 index 0000000000000000000000000000000000000000..a34d042e30a87b18b48ccb3d01c54b7aef1b0694 --- /dev/null +++ b/mne-python/source/mne/decoding/xdawn.py @@ -0,0 +1,213 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import collections.abc as abc +from functools import partial + +import numpy as np + +from .._fiff.meas_info import Info +from ..cov import Covariance +from ..decoding._covs_ged import _xdawn_estimate +from ..decoding._mod_ged import _xdawn_mod +from ..decoding.base import _GEDTransformer +from ..utils import _validate_type, fill_doc + + +@fill_doc +class XdawnTransformer(_GEDTransformer): + """Implementation of the Xdawn Algorithm compatible with scikit-learn. + + Xdawn is a spatial filtering method designed to improve the signal + to signal + noise ratio (SSNR) of the event related responses. Xdawn was + originally designed for P300 evoked potential by enhancing the target + response with respect to the non-target response. This implementation is a + generalization to any type of event related response. + + .. note:: XdawnTransformer does not correct for epochs overlap. To correct + overlaps see `mne.preprocessing.Xdawn`. + + Parameters + ---------- + n_components : int (default 2) + The number of components to decompose the signals. + reg : float | str | None (default None) + If not None (same as ``'empirical'``, default), allow + regularization for covariance estimation. + If float, shrinkage is used (0 <= shrinkage <= 1). + For str options, ``reg`` will be passed to ``method`` to + :func:`mne.compute_covariance`. + signal_cov : None | Covariance | array, shape (n_channels, n_channels) + The signal covariance used for whitening of the data. + if None, the covariance is estimated from the epochs signal. + cov_method_params : dict | None + Parameters to pass to :func:`mne.compute_covariance`. + + .. versionadded:: 0.16 + restr_type : "restricting" | "whitening" | None + Restricting transformation for covariance matrices before performing + generalized eigendecomposition. + If "restricting" only restriction to the principal subspace of signal_cov + will be performed. + If "whitening", covariance matrices will be additionally rescaled according + to the whitening for the signal_cov. + If None, no restriction will be applied. Defaults to None. + + .. versionadded:: 1.11 + info : mne.Info | None + The mne.Info object with information about the sensors and methods of + measurement used for covariance estimation and generalized + eigendecomposition. + If None, one channel type and no projections will be assumed and if + rank is dict, it will be sum of ranks per channel type. + Defaults to None. + + .. versionadded:: 1.11 + %(rank_full)s + + .. versionadded:: 1.11 + + Attributes + ---------- + classes_ : array, shape (n_classes) + The event indices of the classes. + filters_ : array, shape (n_channels, n_channels) + The Xdawn components used to decompose the data for each event type. + patterns_ : array, shape (n_channels, n_channels) + The Xdawn patterns used to restore the signals for each event type. + + See Also + -------- + CSP, SPoC, SSD + """ + + def __init__( + self, + n_components=2, + reg=None, + signal_cov=None, + cov_method_params=None, + *, + restr_type=None, + info=None, + rank="full", + ): + self.n_components = n_components + self.signal_cov = signal_cov + self.reg = reg + self.cov_method_params = cov_method_params + self.restr_type = restr_type + self.info = info + self.rank = rank + + cov_callable = partial( + _xdawn_estimate, + reg=reg, + cov_method_params=cov_method_params, + R=signal_cov, + info=info, + rank=rank, + ) + super().__init__( + n_components=n_components, + cov_callable=cov_callable, + mod_ged_callable=_xdawn_mod, + dec_type="multi", + restr_type=restr_type, + ) + + def __sklearn_tags__(self): + """Tag the transformer.""" + tags = super().__sklearn_tags__() + tags.target_tags.required = True + return tags + + def _validate_params(self, X): + _validate_type(self.n_components, int, "n_components") + + # reg is validated in _regularized_covariance + + if self.signal_cov is not None: + if isinstance(self.signal_cov, Covariance): + self.signal_cov = self.signal_cov.data + elif not isinstance(self.signal_cov, np.ndarray): + raise ValueError("signal_cov should be mne.Covariance or np.ndarray") + if not np.array_equal(self.signal_cov.shape, np.tile(X.shape[1], 2)): + raise ValueError( + "signal_cov data should be of shape (n_channels, n_channels)" + ) + _validate_type(self.cov_method_params, (abc.Mapping, None), "cov_method_params") + _validate_type(self.info, (Info, None), "info") + + def fit(self, X, y=None): + """Fit Xdawn spatial filters. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_samples) + The target data. + y : array, shape (n_epochs,) | None + The target labels. If None, Xdawn fit on the average evoked. + + Returns + ------- + self : Xdawn instance + The Xdawn instance. + """ + X, y = self._check_data(X, y=y, fit=True, return_y=True) + # For test purposes + if y is None: + y = np.ones(len(X)) + self._validate_params(X) + + super().fit(X, y) + + return self + + def transform(self, X): + """Transform data with spatial filters. + + Parameters + ---------- + X : array, shape (n_epochs, n_channels, n_samples) + The target data. + + Returns + ------- + X : array, shape (n_epochs, n_components * n_classes, n_samples) + The transformed data. + """ + X = self._check_data(X) + X = super().transform(X) + return X + + def inverse_transform(self, X): + """Remove selected components from the signal. + + Given the unmixing matrix, transform data, zero out components, + and inverse transform the data. This procedure will reconstruct + the signals from which the dynamics described by the excluded + components is subtracted. + + Parameters + ---------- + X : array, shape (n_epochs, n_components * n_classes, n_times) + The transformed data. + + Returns + ------- + X : array, shape (n_epochs, n_channels * n_classes, n_times) + The inverse transform data. + """ + # Check size + X = self._check_data(X, check_n_features=False) + n_epochs, n_comp, n_times = X.shape + if n_comp != (self.n_components * len(self.classes_)): + raise ValueError( + f"X must have {self.n_components * len(self.classes_)} components, " + f"got {n_comp} instead." + ) + pick_patterns = self._subset_multi_components(name="patterns") + # Transform + return np.dot(pick_patterns.T, X).transpose(1, 0, 2) diff --git a/mne-python/source/mne/defaults.py b/mne-python/source/mne/defaults.py new file mode 100644 index 0000000000000000000000000000000000000000..ac040f8fcebed9da108808fb81eaf26dae46f948 --- /dev/null +++ b/mne-python/source/mne/defaults.py @@ -0,0 +1,380 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from copy import deepcopy + +DEFAULTS = dict( + color=dict( + mag="darkblue", + grad="b", + eeg="k", + eog="k", + ecg="m", + emg="k", + ref_meg="steelblue", + misc="k", + stim="k", + resp="k", + chpi="k", + exci="k", + ias="k", + syst="k", + seeg="saddlebrown", + dbs="seagreen", + dipole="k", + gof="k", + bio="k", + ecog="k", + hbo="#AA3377", + hbr="b", + fnirs_cw_amplitude="k", + fnirs_fd_ac_amplitude="k", + fnirs_fd_phase="k", + fnirs_od="k", + csd="k", + whitened="k", + gsr="#666633", + temperature="#663333", + eyegaze="k", + pupil="k", + ), + si_units=dict( + mag="T", + grad="T/m", + eeg="V", + eog="V", + ecg="V", + emg="V", + misc="AU", + seeg="V", + dbs="V", + dipole="Am", + gof="GOF", + bio="V", + ecog="V", + hbo="M", + hbr="M", + ref_meg="T", + fnirs_cw_amplitude="V", + fnirs_fd_ac_amplitude="V", + fnirs_fd_phase="rad", + fnirs_od="V", + csd="V/m²", + whitened="Z", + gsr="S", + temperature="C", + eyegaze="rad", + pupil="m", + ), + units=dict( + mag="fT", + grad="fT/cm", + eeg="µV", + eog="µV", + ecg="µV", + emg="µV", + misc="AU", + seeg="mV", + dbs="µV", + dipole="nAm", + gof="GOF", + bio="µV", + ecog="µV", + hbo="µM", + hbr="µM", + ref_meg="fT", + fnirs_cw_amplitude="V", + fnirs_fd_ac_amplitude="V", + fnirs_fd_phase="rad", + fnirs_od="V", + csd="mV/m²", + whitened="Z", + gsr="S", + temperature="C", + eyegaze="rad", + pupil="mm", + ), + # scalings for the units + scalings=dict( + mag=1e15, + grad=1e13, + eeg=1e6, + eog=1e6, + emg=1e6, + ecg=1e6, + misc=1.0, + seeg=1e3, + dbs=1e6, + ecog=1e6, + dipole=1e9, + gof=1.0, + bio=1e6, + hbo=1e6, + hbr=1e6, + ref_meg=1e15, + fnirs_cw_amplitude=1.0, + fnirs_fd_ac_amplitude=1.0, + fnirs_fd_phase=1.0, + fnirs_od=1.0, + csd=1e3, + whitened=1.0, + gsr=1.0, + temperature=1.0, + eyegaze=1.0, + pupil=1e3, + ), + # rough guess for a good plot + scalings_plot_raw=dict( + mag=1e-12, + grad=4e-11, + eeg=20e-6, + eog=150e-6, + ecg=5e-4, + emg=1e-3, + ref_meg=1e-12, + misc="auto", + stim=1, + resp=1, + chpi=1e-4, + exci=1, + ias=1, + syst=1, + seeg=1e-4, + dbs=1e-4, + bio=1e-6, + ecog=1e-4, + hbo=10e-6, + hbr=10e-6, + whitened=10.0, + fnirs_cw_amplitude=2e-2, + fnirs_fd_ac_amplitude=2e-2, + fnirs_fd_phase=2e-1, + fnirs_od=2e-2, + csd=200e-4, + dipole=1e-7, + gof=1e2, + gsr=1.0, + temperature=0.1, + eyegaze=2e-1, + pupil=1e-2, + ), + scalings_cov_rank=dict( + mag=1e12, + grad=1e11, + eeg=1e5, # ~100x scalings + seeg=1e1, + dbs=1e4, + ecog=1e4, + hbo=1e4, + hbr=1e4, + ), + ylim=dict( + mag=(-600.0, 600.0), + grad=(-200.0, 200.0), + eeg=(-200.0, 200.0), + misc=(-5.0, 5.0), + seeg=(-20.0, 20.0), + dbs=(-200.0, 200.0), + dipole=(-100.0, 100.0), + gof=(0.0, 1.0), + bio=(-500.0, 500.0), + ecog=(-200.0, 200.0), + hbo=(0, 20), + hbr=(0, 20), + csd=(-50.0, 50.0), + eyegaze=(-1, 1), + pupil=(-1.0, 1.0), + ), + titles=dict( + mag="Magnetometers", + grad="Gradiometers", + eeg="EEG", + eog="EOG", + ecg="ECG", + emg="EMG", + misc="misc", + seeg="sEEG", + dbs="DBS", + bio="BIO", + dipole="Dipole", + ecog="ECoG", + hbo="Oxyhemoglobin", + ref_meg="Reference Magnetometers", + fnirs_cw_amplitude="fNIRS (CW amplitude)", + fnirs_fd_ac_amplitude="fNIRS (FD AC amplitude)", + fnirs_fd_phase="fNIRS (FD phase)", + fnirs_od="fNIRS (OD)", + hbr="Deoxyhemoglobin", + gof="Goodness of fit", + csd="Current source density", + stim="Stimulus", + gsr="Galvanic skin response", + temperature="Temperature", + eyegaze="Eye-tracking (Gaze position)", + pupil="Eye-tracking (Pupil size)", + resp="Respiration monitoring channel", + chpi="Continuous head position indicator (HPI) coil channels", + exci="Flux excitation channel", + ias="Internal Active Shielding data (Triux systems)", + syst="System status channel information (Triux systems)", + whitened="Whitened data", + ), + mask_params=dict( + marker="o", + markerfacecolor="w", + markeredgecolor="k", + linewidth=0, + markeredgewidth=1, + markersize=4, + ), + coreg=dict( + mri_fid_opacity=1.0, + dig_fid_opacity=1.0, + # go from unit scaling (e.g., unit-radius sphere) to meters + mri_fid_scale=5e-3, + dig_fid_scale=8e-3, + extra_scale=4e-3, + eeg_scale=4e-3, + eegp_scale=20e-3, + eegp_height=0.1, + ecog_scale=2e-3, + seeg_scale=2e-3, + meg_scale=1.0, # sensors are already in SI units + ref_meg_scale=1.0, + dbs_scale=5e-3, + fnirs_scale=5e-3, + source_scale=5e-3, + detector_scale=5e-3, + hpi_scale=4e-3, + head_color=(0.988, 0.89, 0.74), + hpi_color=(1.0, 0.0, 1.0), + extra_color=(1.0, 1.0, 1.0), + meg_color=(0.0, 0.25, 0.5), + ref_meg_color=(0.5, 0.5, 0.5), + helmet_color=(0.0, 0.0, 0.6), + eeg_color=(1.0, 0.596, 0.588), + eegp_color=(0.839, 0.15, 0.16), + ecog_color=(1.0, 1.0, 1.0), + dbs_color=(0.82, 0.455, 0.659), + seeg_color=(1.0, 1.0, 0.3), + fnirs_color=(1.0, 0.647, 0.0), + source_color=(1.0, 0.05, 0.0), + detector_color=(0.3, 0.15, 0.15), + lpa_color=(1.0, 0.0, 0.0), + nasion_color=(0.0, 1.0, 0.0), + rpa_color=(0.0, 0.0, 1.0), + ), + report_coreg=dict(dig=True, meg=("helmet", "sensors"), show_axes=True), + noise_std=dict(grad=5e-13, mag=20e-15, eeg=0.2e-6), + eloreta_options=dict(eps=1e-6, max_iter=20, force_equal=False), + depth_mne=dict( + exp=0.8, + limit=10.0, + limit_depth_chs=True, + combine_xyz="spectral", + allow_fixed_depth=False, + ), + depth_sparse=dict( + exp=0.8, + limit=None, + limit_depth_chs="whiten", + combine_xyz="fro", + allow_fixed_depth=True, + ), + interpolation_method=dict( + eeg="spline", meg="MNE", fnirs="nearest", ecog="spline", seeg="spline" + ), + volume_options=dict( + alpha=None, + resolution=1.0, + surface_alpha=None, + blending="mip", + silhouette_alpha=None, + silhouette_linewidth=2.0, + ), + prefixes={ + "k": 1e-3, + "h": 1e-2, + "": 1e0, + "d": 1e1, + "c": 1e2, + "m": 1e3, + "µ": 1e6, + "u": 1e6, + "n": 1e9, + "p": 1e12, + "f": 1e15, + }, + transform_zooms=dict(translation=None, rigid=None, affine=None, sdr=None), + transform_niter=dict( + translation=(10000, 1000, 100), + rigid=(10000, 1000, 100), + affine=(10000, 1000, 100), + sdr=(10, 10, 5), + ), + volume_label_indices=( + # Left and middle + 4, # Left-Lateral-Ventricle + 5, # Left-Inf-Lat-Vent + 8, # Left-Cerebellum-Cortex + 10, # Left-Thalamus-Proper + 11, # Left-Caudate + 12, # Left-Putamen + 13, # Left-Pallidum + 14, # 3rd-Ventricle + 15, # 4th-Ventricle + 16, # Brain-Stem + 17, # Left-Hippocampus + 18, # Left-Amygdala + 26, # Left-Accumbens-area + 28, # Left-VentralDC + # Right + 43, # Right-Lateral-Ventricle + 44, # Right-Inf-Lat-Vent + 47, # Right-Cerebellum-Cortex + 49, # Right-Thalamus-Proper + 50, # Right-Caudate + 51, # Right-Putamen + 52, # Right-Pallidum + 53, # Right-Hippocampus + 54, # Right-Amygdala + 58, # Right-Accumbens-area + 60, # Right-VentralDC + ), + report_stc_plot_kwargs=dict( + views=("lateral", "medial"), + hemi="split", + backend="pyvistaqt", + time_viewer=False, + show_traces=False, + size=(450, 450), + background="white", + time_label=None, + add_data_kwargs={"colorbar_kwargs": {"label_font_size": 12, "n_labels": 5}}, + ), +) + + +def _handle_default(k, v=None): + """Avoid dicts as default keyword arguments. + + Use this function instead to resolve default dict values. Example usage:: + + scalings = _handle_default('scalings', scalings) + + """ + this_mapping = deepcopy(DEFAULTS[k]) + if v is not None: + if isinstance(v, dict): + this_mapping.update(v) + else: + for key in this_mapping: + this_mapping[key] = v + return this_mapping + + +HEAD_SIZE_DEFAULT = 0.095 # in [m] +_BORDER_DEFAULT = "mean" +_INTERPOLATION_DEFAULT = "cubic" +_EXTRAPOLATE_DEFAULT = "auto" diff --git a/mne-python/source/mne/dipole.py b/mne-python/source/mne/dipole.py new file mode 100644 index 0000000000000000000000000000000000000000..e5a3c2676322fe290d316f0977552cc39ab94c35 --- /dev/null +++ b/mne-python/source/mne/dipole.py @@ -0,0 +1,1996 @@ +"""Single-dipole functions and classes.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import functools +import re +from copy import deepcopy +from functools import partial + +import numpy as np +from scipy.linalg import eigh +from scipy.optimize import fmin_cobyla + +from ._fiff.constants import FIFF +from ._fiff.pick import pick_types +from ._fiff.proj import _needs_eeg_average_ref_proj, make_projector +from ._freesurfer import _get_aseg, head_to_mni, head_to_mri, read_freesurfer_lut +from .bem import ConductorModel, _bem_find_surface, _bem_surf_name, _fit_sphere +from .cov import _ensure_cov, compute_whitener +from .evoked import _aspect_rev, _read_evoked, _write_evokeds +from .fixes import _safe_svd +from .forward._compute_forward import _compute_forwards_meeg, _prep_field_computation +from .forward._make_forward import ( + _get_trans, + _prep_eeg_channels, + _prep_meg_channels, + _setup_bem, +) +from .parallel import parallel_func +from .source_space._source_space import SourceSpaces, _make_volume_source_space +from .surface import _compute_nearest, _points_outside_surface, transform_surface_to +from .transforms import _coord_frame_name, _print_coord_trans, apply_trans +from .utils import ( + ExtendedTimeMixin, + TimeMixin, + _check_fname, + _check_option, + _get_blas_funcs, + _pl, + _repeated_svd, + _svd_lwork, + _time_mask, + _validate_type, + _verbose_safe_false, + check_fname, + copy_function_doc_to_method_doc, + fill_doc, + logger, + pinvh, + verbose, + warn, +) +from .viz import plot_dipole_amplitudes, plot_dipole_locations +from .viz.evoked import _plot_evoked + + +@fill_doc +class Dipole(TimeMixin): + """Dipole class for sequential dipole fits. + + .. note:: + This class should usually not be instantiated directly via + ``mne.Dipole(...)``. Instead, use one of the functions + listed in the See Also section below. + + Used to store positions, orientations, amplitudes, times, goodness of fit + of dipoles, typically obtained with Neuromag/xfit, mne_dipole_fit + or certain inverse solvers. Note that dipole position vectors are given in + the head coordinate frame. + + Parameters + ---------- + times : array, shape (n_dipoles,) + The time instants at which each dipole was fitted (s). + pos : array, shape (n_dipoles, 3) + The dipoles positions (m) in head coordinates. + amplitude : array, shape (n_dipoles,) + The amplitude of the dipoles (Am). + ori : array, shape (n_dipoles, 3) + The dipole orientations (normalized to unit length). + gof : array, shape (n_dipoles,) + The goodness of fit. + name : str | None + Name of the dipole. + conf : dict + Confidence limits in dipole orientation for "vol" in m^3 (volume), + "depth" in m (along the depth axis), "long" in m (longitudinal axis), + "trans" in m (transverse axis), "qlong" in Am, and "qtrans" in Am + (currents). The current confidence limit in the depth direction is + assumed to be zero (although it can be non-zero when a BEM is used). + + .. versionadded:: 0.15 + khi2 : array, shape (n_dipoles,) + The χ^2 values for the fits. + + .. versionadded:: 0.15 + nfree : array, shape (n_dipoles,) + The number of free parameters for each fit. + + .. versionadded:: 0.15 + %(verbose)s + + See Also + -------- + fit_dipole + DipoleFixed + read_dipole + + Notes + ----- + This class is for sequential dipole fits, where the position + changes as a function of time. For fixed dipole fits, where the + position is fixed as a function of time, use :class:`mne.DipoleFixed`. + """ + + @verbose + def __init__( + self, + times, + pos, + amplitude, + ori, + gof, + name=None, + conf=None, + khi2=None, + nfree=None, + *, + verbose=None, + ): + self._set_times(np.array(times)) + self._pos = np.array(pos) + self._amplitude = np.array(amplitude) + self._ori = np.array(ori) + self._gof = np.array(gof) + self._name = name + self._conf = dict() + if conf is not None: + for key, value in conf.items(): + self._conf[key] = np.array(value) + self._khi2 = np.array(khi2) if khi2 is not None else None + self._nfree = np.array(nfree) if nfree is not None else None + + def __repr__(self): # noqa: D105 + s = f"n_times : {len(self.times)}" + s += f", tmin : {np.min(self.times):0.3f}" + s += f", tmax : {np.max(self.times):0.3f}" + return f"" + + @property + def pos(self): + """The dipoles positions (m) in head coordinates.""" + return self._pos + + @property + def amplitude(self): + """The amplitude of the dipoles (Am).""" + return self._amplitude + + @property + def ori(self): + """The dipole orientations (normalized to unit length).""" + return self._ori + + @property + def gof(self): + """The goodness of fit.""" + return self._gof + + @property + def name(self): + """Name of the dipole.""" + return self._name + + @name.setter + def name(self, name): + _validate_type(name, str, "name") + self._name = name + + @property + def conf(self): + """Confidence limits in dipole orientation.""" + return self._conf + + @property + def khi2(self): + """The χ^2 values for the fits.""" + return self._khi2 + + @property + def nfree(self): + """The number of free parameters for each fit.""" + return self._nfree + + @verbose + def save(self, fname, overwrite=False, *, verbose=None): + """Save dipole in a ``.dip`` or ``.bdip`` file. + + The ``.[b]dip`` format is for :class:`mne.Dipole` objects, that is, + fixed-position dipole fits. For these fits, the amplitude, orientation, + and position vary as a function of time. + + Parameters + ---------- + fname : path-like + The name of the ``.dip`` or ``.bdip`` file. + %(overwrite)s + + .. versionadded:: 0.20 + %(verbose)s + + See Also + -------- + read_dipole + + Notes + ----- + .. versionchanged:: 0.20 + Support for writing bdip (Xfit binary) files. + """ + # obligatory fields + fname = _check_fname(fname, overwrite=overwrite) + if fname.suffix == ".bdip": + _write_dipole_bdip(fname, self) + else: + _write_dipole_text(fname, self) + + @verbose + def crop(self, tmin=None, tmax=None, include_tmax=True, verbose=None): + """Crop data to a given time interval. + + Parameters + ---------- + tmin : float | None + Start time of selection in seconds. + tmax : float | None + End time of selection in seconds. + %(include_tmax)s + %(verbose)s + + Returns + ------- + self : instance of Dipole + The cropped instance. + """ + sfreq = None + if len(self.times) > 1: + sfreq = 1.0 / np.median(np.diff(self.times)) + mask = _time_mask( + self.times, tmin, tmax, sfreq=sfreq, include_tmax=include_tmax + ) + self._set_times(self.times[mask]) + for attr in ("_pos", "_gof", "_amplitude", "_ori", "_khi2", "_nfree"): + if getattr(self, attr) is not None: + setattr(self, attr, getattr(self, attr)[mask]) + for key in self.conf.keys(): + self.conf[key] = self.conf[key][mask] + return self + + def copy(self): + """Copy the Dipoles object. + + Returns + ------- + dip : instance of Dipole + The copied dipole instance. + """ + return deepcopy(self) + + @verbose + @copy_function_doc_to_method_doc(plot_dipole_locations) + def plot_locations( + self, + trans, + subject, + subjects_dir=None, + mode="orthoview", + coord_frame="mri", + idx="gof", + show_all=True, + ax=None, + block=False, + show=True, + scale=None, + color=None, + *, + highlight_color="r", + fig=None, + title=None, + head_source="seghead", + surf="pial", + width=None, + verbose=None, + ): + return plot_dipole_locations( + self, + trans, + subject, + subjects_dir, + mode, + coord_frame, + idx, + show_all, + ax, + block, + show, + scale=scale, + color=color, + highlight_color=highlight_color, + fig=fig, + title=title, + head_source=head_source, + surf=surf, + width=width, + ) + + @verbose + def to_mni(self, subject, trans, subjects_dir=None, verbose=None): + """Convert dipole location from head to MNI coordinates. + + Parameters + ---------- + %(subject)s + %(trans_not_none)s + %(subjects_dir)s + %(verbose)s + + Returns + ------- + pos_mni : array, shape (n_pos, 3) + The MNI coordinates (in mm) of pos. + """ + mri_head_t, trans = _get_trans(trans) + return head_to_mni( + self.pos, subject, mri_head_t, subjects_dir=subjects_dir, verbose=verbose + ) + + @verbose + def to_mri(self, subject, trans, subjects_dir=None, verbose=None): + """Convert dipole location from head to MRI surface RAS coordinates. + + Parameters + ---------- + %(subject)s + %(trans_not_none)s + %(subjects_dir)s + %(verbose)s + + Returns + ------- + pos_mri : array, shape (n_pos, 3) + The Freesurfer surface RAS coordinates (in mm) of pos. + """ + mri_head_t, trans = _get_trans(trans) + return head_to_mri( + self.pos, + subject, + mri_head_t, + subjects_dir=subjects_dir, + verbose=verbose, + kind="mri", + ) + + @verbose + def to_volume_labels( + self, + trans, + subject="fsaverage", + aseg="aparc+aseg", + subjects_dir=None, + verbose=None, + ): + """Find an ROI in atlas for the dipole positions. + + Parameters + ---------- + %(trans)s + + .. versionchanged:: 0.19 + Support for 'fsaverage' argument. + %(subject)s + %(aseg)s + %(subjects_dir)s + %(verbose)s + + Returns + ------- + labels : list + List of anatomical region names from anatomical segmentation atlas. + + Notes + ----- + .. versionadded:: 0.24 + """ + aseg_img, aseg_data = _get_aseg(aseg, subject, subjects_dir) + mri_vox_t = np.linalg.inv(aseg_img.header.get_vox2ras_tkr()) + + # Load freesurface atlas LUT + lut_inv = read_freesurfer_lut()[0] + lut = {v: k for k, v in lut_inv.items()} + + # transform to voxel space from head space + pos = self.to_mri(subject, trans, subjects_dir=subjects_dir, verbose=verbose) + pos = apply_trans(mri_vox_t, pos) + pos = np.rint(pos).astype(int) + + # Get voxel value and label from LUT + labels = [lut.get(aseg_data[tuple(coord)], "Unknown") for coord in pos] + return labels + + def plot_amplitudes(self, color="k", show=True): + """Plot the dipole amplitudes as a function of time. + + Parameters + ---------- + color : matplotlib color + Color to use for the trace. + show : bool + Show figure if True. + + Returns + ------- + fig : matplotlib.figure.Figure + The figure object containing the plot. + """ + return plot_dipole_amplitudes([self], [color], show) + + def __getitem__(self, item): + """Get a time slice. + + Parameters + ---------- + item : array-like or slice + The slice of time points to use. + + Returns + ------- + dip : instance of Dipole + The sliced dipole. + """ + if isinstance(item, int): # make sure attributes stay 2d + item = [item] + + selected_times = self.times[item].copy() + selected_pos = self.pos[item, :].copy() + selected_amplitude = self.amplitude[item].copy() + selected_ori = self.ori[item, :].copy() + selected_gof = self.gof[item].copy() + selected_name = self.name + selected_conf = dict() + for key in self.conf.keys(): + selected_conf[key] = self.conf[key][item] + selected_khi2 = self.khi2[item] if self.khi2 is not None else None + selected_nfree = self.nfree[item] if self.nfree is not None else None + return Dipole( + selected_times, + selected_pos, + selected_amplitude, + selected_ori, + selected_gof, + selected_name, + selected_conf, + selected_khi2, + selected_nfree, + ) + + def __len__(self): + """Return the number of dipoles. + + Returns + ------- + len : int + The number of dipoles. + + Examples + -------- + This can be used as:: + + >>> len(dipoles) # doctest: +SKIP + 10 + """ + return self.pos.shape[0] + + +def _read_dipole_fixed(fname): + """Read a fixed dipole FIF file.""" + logger.info(f"Reading {fname} ...") + info, nave, aspect_kind, comment, times, data, _ = _read_evoked(fname) + return DipoleFixed(info, data, times, nave, aspect_kind, comment=comment) + + +@fill_doc +class DipoleFixed(ExtendedTimeMixin): + """Dipole class for fixed-position dipole fits. + + .. note:: + This class should usually not be instantiated directly + via ``mne.DipoleFixed(...)``. Instead, use one of the functions + listed in the See Also section below. + + Parameters + ---------- + %(info_not_none)s + data : array, shape (n_channels, n_times) + The dipole data. + times : array, shape (n_times,) + The time points. + nave : int + Number of averages. + aspect_kind : int + The kind of data. + comment : str + The dipole comment. + %(verbose)s + + See Also + -------- + read_dipole + Dipole + fit_dipole + + Notes + ----- + This class is for fixed-position dipole fits, where the position + (and maybe orientation) is static over time. For sequential dipole fits, + where the position can change a function of time, use :class:`mne.Dipole`. + + .. versionadded:: 0.12 + """ + + @verbose + def __init__( + self, info, data, times, nave, aspect_kind, comment="", *, verbose=None + ): + self.info = info + self.nave = nave + self._aspect_kind = aspect_kind + self.kind = _aspect_rev.get(aspect_kind, "unknown") + self.comment = comment + self._set_times(np.array(times)) + self.data = data + self.preload = True + self._update_first_last() + + def __repr__(self): # noqa: D105 + s = f"n_times : {len(self.times)}" + s += f", tmin : {np.min(self.times)}" + s += f", tmax : {np.max(self.times)}" + return f"" + + def copy(self): + """Copy the DipoleFixed object. + + Returns + ------- + inst : instance of DipoleFixed + The copy. + + Notes + ----- + .. versionadded:: 0.16 + """ + return deepcopy(self) + + @property + def ch_names(self): + """Channel names.""" + return self.info["ch_names"] + + @verbose + def save(self, fname, *, overwrite=False, verbose=None): + """Save fixed dipole in FIF format. + + The ``.fif[.gz]`` format is for :class:`mne.DipoleFixed` objects, that is, + fixed-position and optionally fixed-orientation dipole fits. For these fits, + the amplitude (and optionally orientation) vary as a function of time, + but not the position. + + Parameters + ---------- + fname : path-like + The name of the FIF file. Must end with ``'-dip.fif'`` or + ``'-dip.fif.gz'`` to make it explicit that the file contains + dipole information in FIF format. + %(overwrite)s + + .. versionadded:: 1.10.0 + %(verbose)s + + See Also + -------- + read_dipole + """ + check_fname( + fname, + "DipoleFixed", + ( + "-dip.fif", + "-dip.fif.gz", + "_dip.fif", + "_dip.fif.gz", + ), + (".fif", ".fif.gz"), + ) + _write_evokeds(fname, self, check=False, overwrite=overwrite) + + def plot(self, show=True, time_unit="s"): + """Plot dipole data. + + Parameters + ---------- + show : bool + Call pyplot.show() at the end or not. + time_unit : str + The units for the time axis, can be "ms" or "s" (default). + + .. versionadded:: 0.16 + + Returns + ------- + fig : instance of matplotlib.figure.Figure + The figure containing the time courses. + """ + return _plot_evoked( + self, + picks=None, + exclude=(), + unit=True, + show=show, + ylim=None, + xlim="tight", + proj=False, + hline=None, + units=None, + scalings=None, + titles=None, + axes=None, + gfp=False, + window_title=None, + spatial_colors=False, + plot_type="butterfly", + selectable=False, + time_unit=time_unit, + ) + + +# ############################################################################# +# IO +@verbose +def read_dipole(fname, verbose=None): + """Read a dipole object from a file. + + Non-fixed-position :class:`mne.Dipole` objects are usually saved in ``.[b]dip`` + format. Fixed-position :class:`mne.DipoleFixed` objects are usually saved in + FIF format. + + Parameters + ---------- + fname : path-like + The name of the ``.[b]dip`` or ``.fif[.gz]`` file. + %(verbose)s + + Returns + ------- + %(dipole)s + + See Also + -------- + Dipole + DipoleFixed + fit_dipole + + Notes + ----- + .. versionchanged:: 0.20 + Support for reading bdip (Xfit binary) format. + """ + fname = _check_fname(fname, overwrite="read", must_exist=True) + if fname.suffix == ".fif" or fname.name.endswith(".fif.gz"): + return _read_dipole_fixed(fname) + elif fname.suffix == ".bdip": + return _read_dipole_bdip(fname) + else: + return _read_dipole_text(fname) + + +def _read_dipole_text(fname): + """Read a dipole text file.""" + # Figure out the special fields + need_header = True + def_line = name = None + # There is a bug in older np.loadtxt regarding skipping fields, + # so just read the data ourselves (need to get name and header anyway) + data = list() + with open(fname) as fid: + for line in fid: + if not (line.startswith("%") or line.startswith("#")): + need_header = False + data.append(line.strip().split()) + else: + if need_header: + def_line = line + if line.startswith("##") or line.startswith("%%"): + m = re.search('Name "(.*) dipoles"', line) + if m: + name = m.group(1) + del line + data = np.atleast_2d(np.array(data, float)) + if def_line is None: + raise OSError( + "Dipole text file is missing field definition comment, cannot parse " + f"{fname}" + ) + # actually parse the fields + def_line = def_line.lstrip("%").lstrip("#").strip() + # MNE writes it out differently than Elekta, let's standardize them... + fields = re.sub( + r"([X|Y|Z] )\(mm\)", # "X (mm)", etc. + lambda match: match.group(1).strip() + "/mm", + def_line, + ) + fields = re.sub( + r"\((.*?)\)", + lambda match: "/" + match.group(1), + fields, # "Q(nAm)", etc. + ) + fields = re.sub( + "(begin|end) ", # "begin" and "end" with no units + lambda match: match.group(1) + "/ms", + fields, + ) + fields = fields.lower().split() + required_fields = ( + "begin/ms", + "x/mm", + "y/mm", + "z/mm", + "q/nam", + "qx/nam", + "qy/nam", + "qz/nam", + "g/%", + ) + optional_fields = ( + "khi^2", + "free", # standard ones + # now the confidence fields (up to 5!) + "vol/mm^3", + "depth/mm", + "long/mm", + "trans/mm", + "qlong/nam", + "qtrans/nam", + ) + conf_scales = [1e-9, 1e-3, 1e-3, 1e-3, 1e-9, 1e-9] + missing_fields = sorted(set(required_fields) - set(fields)) + if len(missing_fields) > 0: + raise RuntimeError( + f"Could not find necessary fields in header: {missing_fields}" + ) + handled_fields = set(required_fields) | set(optional_fields) + assert len(handled_fields) == len(required_fields) + len(optional_fields) + ignored_fields = sorted(set(fields) - set(handled_fields) - {"end/ms"}) + if len(ignored_fields) > 0: + warn(f"Ignoring extra fields in dipole file: {ignored_fields}") + if len(fields) != data.shape[1]: + raise OSError( + f"More data fields ({len(fields)}) found than data columns ({data.shape[1]}" + f"): {fields}" + ) + + logger.info(f"{len(data)} dipole(s) found") + + if "end/ms" in fields: + if np.diff( + data[:, [fields.index("begin/ms"), fields.index("end/ms")]], 1, -1 + ).any(): + warn( + "begin and end fields differed, but only begin will be used " + "to store time values" + ) + + # Find the correct column in our data array, then scale to proper units + idx = [fields.index(field) for field in required_fields] + assert len(idx) >= 9 + times = data[:, idx[0]] / 1000.0 + pos = 1e-3 * data[:, idx[1:4]] # put data in meters + amplitude = data[:, idx[4]] + norm = amplitude.copy() + amplitude /= 1e9 + norm[norm == 0] = 1 + ori = data[:, idx[5:8]] / norm[:, np.newaxis] + gof = data[:, idx[8]] + # Deal with optional fields + optional = [None] * 2 + for fi, field in enumerate(optional_fields[:2]): + if field in fields: + optional[fi] = data[:, fields.index(field)] + khi2, nfree = optional + conf = dict() + for field, scale in zip(optional_fields[2:], conf_scales): # confidence + if field in fields: + conf[field.split("/")[0]] = scale * data[:, fields.index(field)] + return Dipole(times, pos, amplitude, ori, gof, name, conf, khi2, nfree) + + +def _write_dipole_text(fname, dip): + fmt = " %7.1f %7.1f %8.2f %8.2f %8.2f %8.3f %8.3f %8.3f %8.3f %6.2f" + header = ( + "# begin end X (mm) Y (mm) Z (mm)" + " Q(nAm) Qx(nAm) Qy(nAm) Qz(nAm) g/%" + ) + t = dip.times[:, np.newaxis] * 1000.0 + gof = dip.gof[:, np.newaxis] + amp = 1e9 * dip.amplitude[:, np.newaxis] + out = (t, t, dip.pos / 1e-3, amp, dip.ori * amp, gof) + + # optional fields + fmts = dict( + khi2=(" khi^2", " %8.1f", 1.0), + nfree=(" free", " %5d", 1), + vol=(" vol/mm^3", " %9.3f", 1e9), + depth=(" depth/mm", " %9.3f", 1e3), + long=(" long/mm", " %8.3f", 1e3), + trans=(" trans/mm", " %9.3f", 1e3), + qlong=(" Qlong/nAm", " %10.3f", 1e9), + qtrans=(" Qtrans/nAm", " %11.3f", 1e9), + ) + for key in ("khi2", "nfree"): + data = getattr(dip, key) + if data is not None: + header += fmts[key][0] + fmt += fmts[key][1] + out += (data[:, np.newaxis] * fmts[key][2],) + for key in ("vol", "depth", "long", "trans", "qlong", "qtrans"): + data = dip.conf.get(key) + if data is not None: + header += fmts[key][0] + fmt += fmts[key][1] + out += (data[:, np.newaxis] * fmts[key][2],) + out = np.concatenate(out, axis=-1) + + # NB CoordinateSystem is hard-coded as Head here + with open(fname, "wb") as fid: + fid.write(b'# CoordinateSystem "Head"\n') + fid.write((header + "\n").encode("utf-8")) + np.savetxt(fid, out, fmt=fmt) + if dip.name is not None: + fid.write((f'## Name "{dip.name} dipoles" Style "Dipoles"').encode()) + + +_BDIP_ERROR_KEYS = ("depth", "long", "trans", "qlong", "qtrans") + + +def _read_dipole_bdip(fname): + name = None + nfree = None + with open(fname, "rb") as fid: + # Which dipole in a multi-dipole set + times = list() + pos = list() + amplitude = list() + ori = list() + gof = list() + conf = dict(vol=list()) + khi2 = list() + has_errors = None + while True: + num = np.frombuffer(fid.read(4), ">i4") + if len(num) == 0: + break + times.append(np.frombuffer(fid.read(4), ">f4")[0]) + fid.read(4) # end + fid.read(12) # r0 + pos.append(np.frombuffer(fid.read(12), ">f4")) + Q = np.frombuffer(fid.read(12), ">f4") + amplitude.append(np.linalg.norm(Q)) + ori.append(Q / amplitude[-1]) + gof.append(100 * np.frombuffer(fid.read(4), ">f4")[0]) + this_has_errors = bool(np.frombuffer(fid.read(4), ">i4")[0]) + if has_errors is None: + has_errors = this_has_errors + for key in _BDIP_ERROR_KEYS: + conf[key] = list() + assert has_errors == this_has_errors + fid.read(4) # Noise level used for error computations + limits = np.frombuffer(fid.read(20), ">f4") # error limits + for key, lim in zip(_BDIP_ERROR_KEYS, limits): + conf[key].append(lim) + fid.read(100) # (5, 5) fully describes the conf. ellipsoid + conf["vol"].append(np.frombuffer(fid.read(4), ">f4")[0]) + khi2.append(np.frombuffer(fid.read(4), ">f4")[0]) + fid.read(4) # prob + fid.read(4) # total noise estimate + return Dipole(times, pos, amplitude, ori, gof, name, conf, khi2, nfree) + + +def _write_dipole_bdip(fname, dip): + with open(fname, "wb+") as fid: + for ti, t in enumerate(dip.times): + fid.write(np.zeros(1, ">i4").tobytes()) # int dipole + fid.write(np.array([t, 0]).astype(">f4").tobytes()) + fid.write(np.zeros(3, ">f4").tobytes()) # r0 + fid.write(dip.pos[ti].astype(">f4").tobytes()) # pos + Q = dip.amplitude[ti] * dip.ori[ti] + fid.write(Q.astype(">f4").tobytes()) + fid.write(np.array(dip.gof[ti] / 100.0, ">f4").tobytes()) + has_errors = int(bool(len(dip.conf))) + fid.write(np.array(has_errors, ">i4").tobytes()) # has_errors + fid.write(np.zeros(1, ">f4").tobytes()) # noise level + for key in _BDIP_ERROR_KEYS: + val = dip.conf[key][ti] if key in dip.conf else 0.0 + assert val.shape == () + fid.write(np.array(val, ">f4").tobytes()) + fid.write(np.zeros(25, ">f4").tobytes()) + conf = dip.conf["vol"][ti] if "vol" in dip.conf else 0.0 + fid.write(np.array(conf, ">f4").tobytes()) + khi2 = dip.khi2[ti] if dip.khi2 is not None else 0 + fid.write(np.array(khi2, ">f4").tobytes()) + fid.write(np.zeros(1, ">f4").tobytes()) # prob + fid.write(np.zeros(1, ">f4").tobytes()) # total noise est + + +# ############################################################################# +# Fitting + + +def _dipole_forwards(*, sensors, fwd_data, whitener, rr, n_jobs=None): + """Compute the forward solution and do other nice stuff.""" + B = _compute_forwards_meeg( + rr, sensors=sensors, fwd_data=fwd_data, n_jobs=n_jobs, silent=True + ) + B = np.concatenate(list(B.values()), axis=1) + assert np.isfinite(B).all() + B_orig = B.copy() + + # Apply projection and whiten (cov has projections already) + _, _, dgemm = _get_ddot_dgemv_dgemm() + B = dgemm(1.0, B, whitener.T) + + # column normalization doesn't affect our fitting, so skip for now + # S = np.sum(B * B, axis=1) # across channels + # scales = np.repeat(3. / np.sqrt(np.sum(np.reshape(S, (len(rr), 3)), + # axis=1)), 3) + # B *= scales[:, np.newaxis] + scales = np.ones(3) + return B, B_orig, scales + + +@verbose +def _make_guesses(surf, grid, exclude, mindist, n_jobs=None, verbose=None): + """Make a guess space inside a sphere or BEM surface.""" + if "rr" in surf: + logger.info( + "Guess surface ({}) is in {} coordinates".format( + _bem_surf_name[surf["id"]], _coord_frame_name(surf["coord_frame"]) + ) + ) + else: + logger.info( + f"Making a spherical guess space with radius {1000 * surf.radius:7.1f} " + "mm..." + ) + logger.info("Filtering (grid = %6.f mm)..." % (1000 * grid)) + src = _make_volume_source_space( + surf, grid, exclude, 1000 * mindist, do_neighbors=False, n_jobs=n_jobs + )[0] + assert "vertno" in src + # simplify the result to make things easier later + src = dict( + rr=src["rr"][src["vertno"]], + nn=src["nn"][src["vertno"]], + nuse=src["nuse"], + coord_frame=src["coord_frame"], + vertno=np.arange(src["nuse"]), + type="discrete", + ) + return SourceSpaces([src]) + + +def _fit_eval(rd, B, B2, *, sensors, fwd_data, whitener, lwork, fwd_svd): + """Calculate the residual sum of squares.""" + if fwd_svd is None: + assert sensors is not None + fwd = _dipole_forwards( + sensors=sensors, fwd_data=fwd_data, whitener=whitener, rr=rd[np.newaxis, :] + )[0] + uu, sing, vv = _repeated_svd(fwd, lwork, overwrite_a=True) + else: + uu, sing, vv = fwd_svd + gof = _dipole_gof(uu, sing, vv, B, B2)[0] + # mne-c uses fitness=B2-Bm2, but ours (1-gof) is just a normalized version + return 1.0 - gof + + +@functools.lru_cache(None) +def _get_ddot_dgemv_dgemm(): + return _get_blas_funcs(np.float64, ("dot", "gemv", "gemm")) + + +def _dipole_gof(uu, sing, vv, B, B2): + """Calculate the goodness of fit from the forward SVD.""" + ddot, dgemv, _ = _get_ddot_dgemv_dgemm() + ncomp = 3 if sing[2] / (sing[0] if sing[0] > 0 else 1.0) > 0.2 else 2 + one = dgemv(1.0, vv[:ncomp], B) # np.dot(vv[:ncomp], B) + Bm2 = ddot(one, one) # np.sum(one * one) + gof = Bm2 / B2 + return gof, one + + +def _fit_Q(*, sensors, fwd_data, whitener, B, B2, B_orig, rd, ori=None): + """Fit the dipole moment once the location is known.""" + if "fwd" in fwd_data: + # should be a single precomputed "guess" (i.e., fixed position) + assert rd is None + fwd = fwd_data["fwd"] + assert fwd.shape[0] == 3 + fwd_orig = fwd_data["fwd_orig"] + assert fwd_orig.shape[0] == 3 + scales = fwd_data["scales"] + assert scales.shape == (3,) + fwd_svd = fwd_data["fwd_svd"][0] + else: + fwd, fwd_orig, scales = _dipole_forwards( + sensors=sensors, fwd_data=fwd_data, whitener=whitener, rr=rd[np.newaxis, :] + ) + fwd_svd = None + if ori is None: + if fwd_svd is None: + fwd_svd = _safe_svd(fwd, full_matrices=False) + uu, sing, vv = fwd_svd + gof, one = _dipole_gof(uu, sing, vv, B, B2) + ncomp = len(one) + one /= sing[:ncomp] + Q = np.dot(one, uu.T[:ncomp]) + else: + fwd = np.dot(ori[np.newaxis], fwd) + sing = np.linalg.norm(fwd) + one = np.dot(fwd / sing, B) + gof = (one * one)[0] / B2 + Q = ori * np.sum(one / sing) + ncomp = 3 + # Counteract the effect of column normalization + Q *= scales[0] + B_residual_noproj = B_orig - np.dot(fwd_orig.T, Q) + return Q, gof, B_residual_noproj, ncomp + + +def _fit_dipoles( + fun, + min_dist_to_inner_skull, + data, + times, + guess_rrs, + guess_data, + *, + sensors, + fwd_data, + whitener, + ori, + n_jobs, + rank, + rhoend, +): + """Fit a single dipole to the given whitened, projected data.""" + parallel, p_fun, n_jobs = parallel_func(fun, n_jobs) + # parallel over time points + res = parallel( + p_fun( + min_dist_to_inner_skull, + B, + t, + guess_rrs, + guess_data, + sensors=sensors, + fwd_data=fwd_data, + whitener=whitener, + fmin_cobyla=fmin_cobyla, + ori=ori, + rank=rank, + rhoend=rhoend, + ) + for B, t in zip(data.T, times) + ) + pos = np.array([r[0] for r in res]) + amp = np.array([r[1] for r in res]) + ori = np.array([r[2] for r in res]) + gof = np.array([r[3] for r in res]) * 100 # convert to percentage + conf = None + if res[0][4] is not None: + conf = np.array([r[4] for r in res]) + keys = ["vol", "depth", "long", "trans", "qlong", "qtrans"] + conf = {key: conf[:, ki] for ki, key in enumerate(keys)} + khi2 = np.array([r[5] for r in res]) + nfree = np.array([r[6] for r in res]) + residual_noproj = np.array([r[7] for r in res]).T + + return pos, amp, ori, gof, conf, khi2, nfree, residual_noproj + + +'''Simplex code in case we ever want/need it for testing + +def _make_tetra_simplex(): + """Make the initial tetrahedron""" + # + # For this definition of a regular tetrahedron, see + # + # http://mathworld.wolfram.com/Tetrahedron.html + # + x = np.sqrt(3.0) / 3.0 + r = np.sqrt(6.0) / 12.0 + R = 3 * r + d = x / 2.0 + simplex = 1e-2 * np.array([[x, 0.0, -r], + [-d, 0.5, -r], + [-d, -0.5, -r], + [0., 0., R]]) + return simplex + + +def try_(p, y, psum, ndim, fun, ihi, neval, fac): + """Helper to try a value""" + ptry = np.empty(ndim) + fac1 = (1.0 - fac) / ndim + fac2 = fac1 - fac + ptry = psum * fac1 - p[ihi] * fac2 + ytry = fun(ptry) + neval += 1 + if ytry < y[ihi]: + y[ihi] = ytry + psum[:] += ptry - p[ihi] + p[ihi] = ptry + return ytry, neval + + +def _simplex_minimize(p, ftol, stol, fun, max_eval=1000): + """Minimization with the simplex algorithm + + Modified from Numerical recipes""" + y = np.array([fun(s) for s in p]) + ndim = p.shape[1] + assert p.shape[0] == ndim + 1 + mpts = ndim + 1 + neval = 0 + psum = p.sum(axis=0) + + loop = 1 + while(True): + ilo = 1 + if y[1] > y[2]: + ihi = 1 + inhi = 2 + else: + ihi = 2 + inhi = 1 + for i in range(mpts): + if y[i] < y[ilo]: + ilo = i + if y[i] > y[ihi]: + inhi = ihi + ihi = i + elif y[i] > y[inhi]: + if i != ihi: + inhi = i + + rtol = 2 * np.abs(y[ihi] - y[ilo]) / (np.abs(y[ihi]) + np.abs(y[ilo])) + if rtol < ftol: + break + if neval >= max_eval: + raise RuntimeError('Maximum number of evaluations exceeded.') + if stol > 0: # Has the simplex collapsed? + dsum = np.sqrt(np.sum((p[ilo] - p[ihi]) ** 2)) + if loop > 5 and dsum < stol: + break + + ytry, neval = try_(p, y, psum, ndim, fun, ihi, neval, -1.) + if ytry <= y[ilo]: + ytry, neval = try_(p, y, psum, ndim, fun, ihi, neval, 2.) + elif ytry >= y[inhi]: + ysave = y[ihi] + ytry, neval = try_(p, y, psum, ndim, fun, ihi, neval, 0.5) + if ytry >= ysave: + for i in range(mpts): + if i != ilo: + psum[:] = 0.5 * (p[i] + p[ilo]) + p[i] = psum + y[i] = fun(psum) + neval += ndim + psum = p.sum(axis=0) + loop += 1 +''' + + +def _fit_confidence(*, rd, Q, ori, whitener, fwd_data, sensors): + # As describedd in the Xfit manual, confidence intervals can be calculated + # by examining a linearization of model at the best-fitting location, + # i.e. taking the Jacobian and using the whitener: + # + # J = [∂b/∂x ∂b/∂y ∂b/∂z ∂b/∂Qx ∂b/∂Qy ∂b/∂Qz] + # C = (J.T C^-1 J)^-1 + # + # And then the confidence interval is the diagonal of C, scaled by 1.96 + # (for 95% confidence). + direction = np.empty((3, 3)) + # The coordinate system has the x axis aligned with the dipole orientation, + direction[0] = ori + # the z axis through the origin of the sphere model + rvec = rd - fwd_data["inner_skull"]["r0"] + direction[2] = rvec - ori * np.dot(ori, rvec) # orthogonalize + direction[2] /= np.linalg.norm(direction[2]) + # and the y axis perpendical with these forming a right-handed system. + direction[1] = np.cross(direction[2], direction[0]) + assert np.allclose(np.dot(direction, direction.T), np.eye(3)) + # Get spatial deltas in dipole coordinate directions + deltas = (-1e-4, 1e-4) + J = np.empty((whitener.shape[0], 6)) + for ii in range(3): + fwds = [] + for delta in deltas: + this_r = rd[np.newaxis] + delta * direction[ii] + fwds.append( + np.dot( + Q, + _dipole_forwards( + sensors=sensors, fwd_data=fwd_data, whitener=whitener, rr=this_r + )[0], + ) + ) + J[:, ii] = np.diff(fwds, axis=0)[0] / np.diff(deltas)[0] + # Get current (Q) deltas in the dipole directions + deltas = np.array([-0.01, 0.01]) * np.linalg.norm(Q) + this_fwd = _dipole_forwards( + sensors=sensors, fwd_data=fwd_data, whitener=whitener, rr=rd[np.newaxis] + )[0] + for ii in range(3): + fwds = [] + for delta in deltas: + fwds.append(np.dot(Q + delta * direction[ii], this_fwd)) + J[:, ii + 3] = np.diff(fwds, axis=0)[0] / np.diff(deltas)[0] + # J is already whitened, so we don't need to do np.dot(whitener, J). + # However, the units in the Jacobian are potentially quite different, + # so we need to do some normalization during inversion, then revert. + direction_norm = np.linalg.norm(J[:, :3]) + Q_norm = np.linalg.norm(J[:, 3:5]) # omit possible zero Z + norm = np.array([direction_norm] * 3 + [Q_norm] * 3) + J /= norm + J = np.dot(J.T, J) + C = pinvh(J, rtol=1e-14) + C /= norm + C /= norm[:, np.newaxis] + conf = 1.96 * np.sqrt(np.diag(C)) + # The confidence volume of the dipole location is obtained from by + # taking the eigenvalues of the upper left submatrix and computing + # v = 4π/3 √(c^3 λ1 λ2 λ3) with c = 7.81, or: + vol_conf = ( + 4 + * np.pi + / 3.0 + * np.sqrt(476.379541 * np.prod(eigh(C[:3, :3], eigvals_only=True))) + ) + conf = np.concatenate([conf, [vol_conf]]) + # Now we reorder and subselect the proper columns: + # vol, depth, long, trans, Qlong, Qtrans (discard Qdepth, assumed zero) + conf = conf[[6, 2, 0, 1, 3, 4]] + return conf + + +def _surface_constraint(rd, surf, min_dist_to_inner_skull): + """Surface fitting constraint.""" + dist = _compute_nearest(surf["rr"], rd[np.newaxis, :], return_dists=True)[1][0] + if _points_outside_surface(rd[np.newaxis, :], surf, 1)[0]: + dist *= -1.0 + # Once we know the dipole is below the inner skull, + # let's check if its distance to the inner skull is at least + # min_dist_to_inner_skull. This can be enforced by adding a + # constrain proportional to its distance. + dist -= min_dist_to_inner_skull + return dist + + +def _sphere_constraint(rd, r0, R_adj): + """Sphere fitting constraint.""" + return R_adj - np.sqrt(np.sum((rd - r0) ** 2)) + + +def _fit_dipole( + min_dist_to_inner_skull, + B_orig, + t, + guess_rrs, + guess_data, + *, + sensors, + fwd_data, + whitener, + fmin_cobyla, + ori, + rank, + rhoend, +): + """Fit a single bit of data.""" + B = np.dot(whitener, B_orig) + + # make constraint function to keep the solver within the inner skull + if "rr" in fwd_data["inner_skull"]: # bem + surf = fwd_data["inner_skull"] + constraint = partial( + _surface_constraint, + surf=surf, + min_dist_to_inner_skull=min_dist_to_inner_skull, + ) + else: # sphere + surf = None + constraint = partial( + _sphere_constraint, + r0=fwd_data["inner_skull"]["r0"], + R_adj=fwd_data["inner_skull"].radius - min_dist_to_inner_skull, + ) + + # Find a good starting point (find_best_guess in C) + B2 = np.dot(B, B) + if B2 == 0: + warn(f"Zero field found for time {t}") + return np.zeros(3), 0, np.zeros(3), 0, B + + idx = np.argmin( + [ + _fit_eval( + guess_rrs[[fi], :], + B, + B2, + fwd_svd=fwd_svd, + fwd_data=None, + sensors=None, + whitener=None, + lwork=None, + ) + for fi, fwd_svd in enumerate(guess_data["fwd_svd"]) + ] + ) + x0 = guess_rrs[idx] + lwork = _svd_lwork((3, B.shape[0])) + fun = partial( + _fit_eval, + B=B, + B2=B2, + fwd_data=fwd_data, + whitener=whitener, + lwork=lwork, + sensors=sensors, + fwd_svd=None, + ) + + # Tested minimizers: + # Simplex, BFGS, CG, COBYLA, L-BFGS-B, Powell, SLSQP, TNC + # Several were similar, but COBYLA won for having a handy constraint + # function we can use to ensure we stay inside the inner skull / + # smallest sphere + rd_final = fmin_cobyla( + fun, x0, (constraint,), consargs=(), rhobeg=5e-2, rhoend=rhoend, disp=False + ) + + # simplex = _make_tetra_simplex() + x0 + # _simplex_minimize(simplex, 1e-4, 2e-4, fun) + # rd_final = simplex[0] + + # Compute the dipole moment at the final point + Q, gof, residual_noproj, n_comp = _fit_Q( + sensors=sensors, + fwd_data=fwd_data, + whitener=whitener, + B=B, + B2=B2, + B_orig=B_orig, + rd=rd_final, + ori=ori, + ) + khi2 = (1 - gof) * B2 + nfree = rank - n_comp + amp = np.sqrt(np.dot(Q, Q)) + norm = 1.0 if amp == 0.0 else amp + ori = Q / norm + + conf = _fit_confidence( + sensors=sensors, rd=rd_final, Q=Q, ori=ori, whitener=whitener, fwd_data=fwd_data + ) + + msg = "---- Fitted : %7.1f ms" % (1000.0 * t) + if surf is not None: + dist_to_inner_skull = _compute_nearest( + surf["rr"], rd_final[np.newaxis, :], return_dists=True + )[1][0] + msg += ", distance to inner skull : %2.4f mm" % (dist_to_inner_skull * 1000.0) + + logger.info(msg) + return rd_final, amp, ori, gof, conf, khi2, nfree, residual_noproj + + +def _fit_dipole_fixed( + min_dist_to_inner_skull, + B_orig, + t, + guess_rrs, + guess_data, + *, + sensors, + fwd_data, + whitener, + fmin_cobyla, + ori, + rank, + rhoend, +): + """Fit a data using a fixed position.""" + B = np.dot(whitener, B_orig) + B2 = np.dot(B, B) + if B2 == 0: + warn(f"Zero field found for time {t}") + return np.zeros(3), 0, np.zeros(3), 0, np.zeros(6) + # Compute the dipole moment + Q, gof, residual_noproj = _fit_Q( + fwd_data=guess_data, + whitener=whitener, + B=B, + B2=B2, + B_orig=B_orig, + sensors=sensors, + rd=None, + ori=ori, + )[:3] + if ori is None: + amp = np.sqrt(np.dot(Q, Q)) + norm = 1.0 if amp == 0.0 else amp + ori = Q / norm + else: + amp = np.dot(Q, ori) + rd_final = guess_rrs[0] + # This will be slow, and we don't use it anyway, so omit it for now: + # conf = _fit_confidence(rd_final, Q, ori, whitener, fwd_data) + conf = khi2 = nfree = None + # No corresponding 'logger' message here because it should go *very* fast + return rd_final, amp, ori, gof, conf, khi2, nfree, residual_noproj + + +@verbose +def fit_dipole( + evoked, + cov, + bem, + trans=None, + min_dist=5.0, + n_jobs=None, + pos=None, + ori=None, + rank=None, + accuracy="normal", + tol=5e-5, + verbose=None, +): + """Fit a dipole. + + Parameters + ---------- + evoked : instance of Evoked + The dataset to fit. + cov : str | instance of Covariance + The noise covariance. + bem : path-like | instance of ConductorModel + The BEM filename (str) or conductor model. + trans : path-like | None + The head<->MRI transform filename. Must be provided unless BEM + is a sphere model. + min_dist : float + Minimum distance (in millimeters) from the dipole to the inner skull. + Must be positive. Note that because this is a constraint passed to + a solver it is not strict but close, i.e. for a ``min_dist=5.`` the + fits could be 4.9 mm from the inner skull. + %(n_jobs)s + It is used in field computation and fitting. + pos : ndarray, shape (3,) | None + Position of the dipole to use. If None (default), sequential + fitting (different position and orientation for each time instance) + is performed. If a position (in head coords) is given as an array, + the position is fixed during fitting. + + .. versionadded:: 0.12 + ori : ndarray, shape (3,) | None + Orientation of the dipole to use. If None (default), the + orientation is free to change as a function of time. If an + orientation (in head coordinates) is given as an array, ``pos`` + must also be provided, and the routine computes the amplitude and + goodness of fit of the dipole at the given position and orientation + for each time instant. + + .. versionadded:: 0.12 + %(rank_none)s + + .. versionadded:: 0.20 + accuracy : str + Can be ``"normal"`` (default) or ``"accurate"``, which gives the most + accurate coil definition but is typically not necessary for real-world + data. + + .. versionadded:: 0.24 + tol : float + Final accuracy of the optimization (see ``rhoend`` argument of + :func:`scipy.optimize.fmin_cobyla`). + + .. versionadded:: 0.24 + %(verbose)s + + Returns + ------- + dip : instance of Dipole or DipoleFixed + The dipole fits. A :class:`mne.DipoleFixed` is returned if + ``pos`` and ``ori`` are both not None, otherwise a + :class:`mne.Dipole` is returned. + residual : instance of Evoked + The M-EEG data channels with the fitted dipolar activity removed. + + See Also + -------- + mne.beamformer.rap_music + Dipole + DipoleFixed + read_dipole + + Notes + ----- + .. versionadded:: 0.9.0 + """ + # This could eventually be adapted to work with other inputs, these + # are what is needed: + + evoked = evoked.copy() + _validate_type(accuracy, str, "accuracy") + _check_option("accuracy", accuracy, ("accurate", "normal")) + + # Determine if a list of projectors has an average EEG ref + if _needs_eeg_average_ref_proj(evoked.info): + raise ValueError("EEG average reference is mandatory for dipole fitting.") + if min_dist < 0: + raise ValueError(f"min_dist should be positive. Got {min_dist}") + if ori is not None and pos is None: + raise ValueError("pos must be provided if ori is not None") + + data = evoked.data + if not np.isfinite(data).all(): + raise ValueError("Evoked data must be finite") + info = evoked.info + times = evoked.times.copy() + comment = evoked.comment + + # Convert the min_dist to meters + min_dist_to_inner_skull = min_dist / 1000.0 + del min_dist + + # Figure out our inputs + neeg = len(pick_types(info, meg=False, eeg=True, ref_meg=False, exclude=[])) + if isinstance(bem, str): + bem_extra = bem + else: + bem_extra = repr(bem) + logger.info(f"BEM : {bem_extra}") + mri_head_t, trans = _get_trans(trans) + logger.info(f"MRI transform : {trans}") + safe_false = _verbose_safe_false() + bem = _setup_bem(bem, bem_extra, neeg, mri_head_t, verbose=safe_false) + if not bem["is_sphere"]: + if trans == "identity": # = trans was passed as None + raise ValueError( + "`trans` is ``None``, but bem model is not spherical. " + "You must pass a valid `trans` in this case." + ) + # Find the best-fitting sphere + inner_skull = _bem_find_surface(bem, "inner_skull") + inner_skull = inner_skull.copy() + R, r0 = _fit_sphere(inner_skull["rr"]) + # r0 back to head frame for logging + r0 = apply_trans(mri_head_t["trans"], r0[np.newaxis, :])[0] + inner_skull["r0"] = r0 + logger.info( + f"Head origin : {1000 * r0[0]:6.1f} {1000 * r0[1]:6.1f} " + f"{1000 * r0[2]:6.1f} mm rad = {1000 * R:6.1f} mm." + ) + del R, r0 + else: + r0 = bem["r0"] + if len(bem.get("layers", [])) > 0: + R = bem["layers"][0]["rad"] + kind = "rad" + else: # MEG-only + # Use the minimum distance to the MEG sensors as the radius then + R = np.dot( + np.linalg.inv(info["dev_head_t"]["trans"]), np.hstack([r0, [1.0]]) + )[:3] # r0 -> device + R = R - [ + info["chs"][pick]["loc"][:3] + for pick in pick_types(info, meg=True, exclude=[]) + ] + if len(R) == 0: + raise RuntimeError( + "No MEG channels found, but MEG-only sphere model used" + ) + R = np.min(np.linalg.norm(R, axis=1)) + kind = "min_rad" + logger.info( + f"Sphere model : origin at ({1000 * r0[0]: 7.2f} {1000 * r0[1]: 7.2f} " + f"{1000 * r0[2]: 7.2f}) mm, {kind} = {R:6.1f} mm" + ) + # NB sphere model defined in head frame + inner_skull = ConductorModel(layers=[dict(rad=R)], r0=r0, is_sphere=True) + del R, r0 + + # Deal with DipoleFixed cases here + if pos is not None: + fixed_position = True + pos = np.array(pos, float) + if pos.shape != (3,): + raise ValueError(f"pos must be None or a 3-element array-like, got {pos}") + logger.info( + "Fixed position : {:6.1f} {:6.1f} {:6.1f} mm".format(*tuple(1000 * pos)) + ) + if ori is not None: + ori = np.array(ori, float) + if ori.shape != (3,): + raise ValueError( + f"oris must be None or a 3-element array-like, got {ori}" + ) + norm = np.sqrt(np.sum(ori * ori)) + if not np.isclose(norm, 1): + raise ValueError(f"ori must be a unit vector, got length {norm}") + logger.info( + "Fixed orientation : {:6.4f} {:6.4f} {:6.4f} mm".format(*tuple(ori)) + ) + else: + logger.info("Free orientation : ") + fit_n_jobs = 1 # only use 1 job to do the guess fitting + else: + fixed_position = False + # Eventually these could be parameters, but they are just used for + # the initial grid anyway + guess_grid = 0.02 # MNE-C uses 0.01, but this is faster w/similar perf + guess_mindist = max(0.005, min_dist_to_inner_skull) + guess_exclude = 0.02 + + logger.info(f"Guess grid : {1000 * guess_grid:6.1f} mm") + if guess_mindist > 0.0: + logger.info(f"Guess mindist : {1000 * guess_mindist:6.1f} mm") + if guess_exclude > 0: + logger.info(f"Guess exclude : {1000 * guess_exclude:6.1f} mm") + logger.info(f"Using {accuracy} MEG coil definitions.") + fit_n_jobs = n_jobs + cov = _ensure_cov(cov) + logger.info("") + + _print_coord_trans(mri_head_t) + if info["dev_head_t"]: + _print_coord_trans(info["dev_head_t"]) + logger.info(f"{len(info['bads'])} bad channels total") + + # Forward model setup (setup_forward_model from setup.c) + ch_types = evoked.get_channel_types() + + sensors = dict() + if "grad" in ch_types or "mag" in ch_types: + sensors["meg"] = _prep_meg_channels( + info, exclude="bads", accuracy=accuracy, verbose=verbose + ) + if "eeg" in ch_types: + sensors["eeg"] = _prep_eeg_channels(info, exclude="bads", verbose=verbose) + + # Ensure that MEG and/or EEG channels are present + if len(sensors) == 0: + raise RuntimeError("No MEG or EEG channels found.") + + # Whitener for the data + logger.info("Decomposing the sensor noise covariance matrix...") + picks = pick_types(info, meg=True, eeg=True, ref_meg=False) + + # In case we want to more closely match MNE-C for debugging: + # from ._fiff.pick import pick_info + # from .cov import prepare_noise_cov + # info_nb = pick_info(info, picks) + # cov = prepare_noise_cov(cov, info_nb, info_nb['ch_names'], verbose=False) + # nzero = (cov['eig'] > 0) + # n_chan = len(info_nb['ch_names']) + # whitener = np.zeros((n_chan, n_chan), dtype=np.float64) + # whitener[nzero, nzero] = 1.0 / np.sqrt(cov['eig'][nzero]) + # whitener = np.dot(whitener, cov['eigvec']) + + whitener, _, rank = compute_whitener( + cov, info, picks=picks, rank=rank, return_rank=True + ) + + # Proceed to computing the fits (make_guess_data) + if fixed_position: + guess_src = dict(nuse=1, rr=pos[np.newaxis], inuse=np.array([True])) + logger.info("Compute forward for dipole location...") + else: + logger.info("\n---- Computing the forward solution for the guesses...") + guess_src = _make_guesses( + inner_skull, guess_grid, guess_exclude, guess_mindist, n_jobs=n_jobs + )[0] + # grid coordinates go from mri to head frame + transform_surface_to(guess_src, "head", mri_head_t) + logger.info("Go through all guess source locations...") + + # inner_skull goes from mri to head frame + if "rr" in inner_skull: + transform_surface_to(inner_skull, "head", mri_head_t) + if fixed_position: + if "rr" in inner_skull: + check = _surface_constraint(pos, inner_skull, min_dist_to_inner_skull) + else: + check = _sphere_constraint( + pos, + inner_skull["r0"], + R_adj=inner_skull.radius - min_dist_to_inner_skull, + ) + if check <= 0: + raise ValueError( + f"fixed position is {-1000 * check:0.1f}mm outside the inner skull " + "boundary" + ) + + # C code computes guesses w/sphere model for speed, don't bother here + fwd_data = _prep_field_computation( + sensors=sensors, bem=bem, n_jobs=n_jobs, verbose=safe_false + ) + fwd_data["inner_skull"] = inner_skull + guess_fwd, guess_fwd_orig, guess_fwd_scales = _dipole_forwards( + sensors=sensors, + fwd_data=fwd_data, + whitener=whitener, + rr=guess_src["rr"], + n_jobs=fit_n_jobs, + ) + # decompose ahead of time + guess_fwd_svd = [ + _safe_svd(fwd, full_matrices=False) + for fwd in np.array_split(guess_fwd, len(guess_src["rr"])) + ] + guess_data = dict( + fwd=guess_fwd, + fwd_svd=guess_fwd_svd, + fwd_orig=guess_fwd_orig, + scales=guess_fwd_scales, + ) + del guess_fwd, guess_fwd_svd, guess_fwd_orig, guess_fwd_scales # destroyed + logger.info("[done %d source%s]", guess_src["nuse"], _pl(guess_src["nuse"])) + + # Do actual fits + data = data[picks] + ch_names = [info["ch_names"][p] for p in picks] + proj_op = make_projector(info["projs"], ch_names, info["bads"])[0] + fun = _fit_dipole_fixed if fixed_position else _fit_dipole + out = _fit_dipoles( + fun, + min_dist_to_inner_skull, + data, + times, + guess_src["rr"], + guess_data, + sensors=sensors, + fwd_data=fwd_data, + whitener=whitener, + ori=ori, + n_jobs=n_jobs, + rank=rank, + rhoend=tol, + ) + assert len(out) == 8 + if fixed_position and ori is not None: + # DipoleFixed + data = np.array([out[1], out[3]]) + out_info = deepcopy(info) + loc = np.concatenate([pos, ori, np.zeros(6)]) + out_info._unlocked = True + out_info["chs"] = [ + dict( + ch_name="dip 01", + loc=loc, + kind=FIFF.FIFFV_DIPOLE_WAVE, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + unit=FIFF.FIFF_UNIT_AM, + coil_type=FIFF.FIFFV_COIL_DIPOLE, + unit_mul=0, + range=1, + cal=1.0, + scanno=1, + logno=1, + ), + dict( + ch_name="goodness", + loc=np.full(12, np.nan), + kind=FIFF.FIFFV_GOODNESS_FIT, + unit=FIFF.FIFF_UNIT_AM, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + coil_type=FIFF.FIFFV_COIL_NONE, + unit_mul=0, + range=1.0, + cal=1.0, + scanno=2, + logno=100, + ), + ] + for key in ["hpi_meas", "hpi_results", "projs"]: + out_info[key] = list() + for key in [ + "acq_pars", + "acq_stim", + "description", + "dig", + "experimenter", + "hpi_subsystem", + "proj_id", + "proj_name", + "subject_info", + ]: + out_info[key] = None + out_info._unlocked = False + out_info["bads"] = [] + out_info._update_redundant() + out_info._check_consistency() + dipoles = DipoleFixed( + out_info, data, times, evoked.nave, evoked._aspect_kind, comment=comment + ) + else: + dipoles = Dipole( + times, out[0], out[1], out[2], out[3], comment, out[4], out[5], out[6] + ) + residual = evoked.copy().apply_proj() # set the projs active + residual.data[picks] = np.dot(proj_op, out[-1]) + logger.info("%d time points fitted", len(dipoles.times)) + return dipoles, residual + + +# Every other row of Table 3 from OyamaEtAl2015 +_OYAMA = """ +0.00 56.29 -27.50 +32.50 56.29 5.00 +0.00 65.00 5.00 +-32.50 56.29 5.00 +0.00 56.29 37.50 +0.00 32.50 61.29 +-56.29 0.00 -27.50 +-56.29 32.50 5.00 +-65.00 0.00 5.00 +-56.29 -32.50 5.00 +-56.29 0.00 37.50 +-32.50 0.00 61.29 +0.00 -56.29 -27.50 +-32.50 -56.29 5.00 +0.00 -65.00 5.00 +32.50 -56.29 5.00 +0.00 -56.29 37.50 +0.00 -32.50 61.29 +56.29 0.00 -27.50 +56.29 -32.50 5.00 +65.00 0.00 5.00 +56.29 32.50 5.00 +56.29 0.00 37.50 +32.50 0.00 61.29 +0.00 0.00 70.00 +""" + + +def get_phantom_dipoles(kind="vectorview"): + """Get standard phantom dipole locations and orientations. + + Parameters + ---------- + kind : str + Get the information for the given system: + + ``vectorview`` (default) + The Neuromag VectorView phantom. + ``otaniemi`` + The older Neuromag phantom used at Otaniemi. + ``oyama`` + The phantom from :footcite:`OyamaEtAl2015`. + + .. versionchanged:: 1.6 + Support added for ``'oyama'``. + + Returns + ------- + pos : ndarray, shape (n_dipoles, 3) + The dipole positions. + ori : ndarray, shape (n_dipoles, 3) + The dipole orientations. + + See Also + -------- + mne.datasets.fetch_phantom + + Notes + ----- + The Elekta phantoms have a radius of 79.5mm, and HPI coil locations + in the XY-plane at the axis extrema (e.g., (79.5, 0), (0, -79.5), ...). + + References + ---------- + .. footbibliography:: + """ + _validate_type(kind, str, "kind") + _check_option("kind", kind, ["vectorview", "otaniemi", "oyama"]) + if kind == "vectorview": + # these values were pulled from a scanned image provided by + # Elekta folks + a = np.array([59.7, 48.6, 35.8, 24.8, 37.2, 27.5, 15.8, 7.9]) + b = np.array([46.1, 41.9, 38.3, 31.5, 13.9, 16.2, 20.0, 19.3]) + x = np.concatenate((a, [0] * 8, -b, [0] * 8)) + y = np.concatenate(([0] * 8, -a, [0] * 8, b)) + c = [22.9, 23.5, 25.5, 23.1, 52.0, 46.4, 41.0, 33.0] + d = [44.4, 34.0, 21.6, 12.7, 62.4, 51.5, 39.1, 27.9] + z = np.concatenate((c, c, d, d)) + signs = ([1, -1] * 4 + [-1, 1] * 4) * 2 + elif kind == "otaniemi": + # these values were pulled from an Neuromag manual + # (NM20456A, 13.7.1999, p.65) + a = np.array([56.3, 47.6, 39.0, 30.3]) + b = np.array([32.5, 27.5, 22.5, 17.5]) + c = np.zeros(4) + x = np.concatenate((a, b, c, c, -a, -b, c, c)) + y = np.concatenate((c, c, -a, -b, c, c, b, a)) + z = np.concatenate((b, a, b, a, b, a, a, b)) + signs = [-1] * 8 + [1] * 16 + [-1] * 8 + else: + assert kind == "oyama" + xyz = np.fromstring(_OYAMA.strip().replace("\n", " "), sep=" ").reshape(25, 3) + xyz = np.repeat(xyz, 2, axis=0) + x, y, z = xyz.T + signs = [1] * 50 + pos = np.vstack((x, y, z)).T / 1000.0 + # For Neuromag-style phantoms, + # Locs are always in XZ or YZ, and so are the oris. The oris are + # also in the same plane and tangential, so it's easy to determine + # the orientation. + # For Oyama, vectors are orthogonal to the position vector and oriented with one + # pointed toward the north pole (except for the topmost points, which are just xy). + ori = list() + for pi, this_pos in enumerate(pos): + this_ori = np.zeros(3) + idx = np.where(this_pos == 0)[0] + # assert len(idx) == 1 + if len(idx) == 0: # oyama + idx = [np.argmin(this_pos)] + idx = np.setdiff1d(np.arange(3), idx[0]) + this_ori[idx] = (this_pos[idx][::-1] / np.linalg.norm(this_pos[idx])) * [1, -1] + if kind == "oyama": + # Ensure it's orthogonal to the position vector + pos_unit = this_pos / np.linalg.norm(this_pos) + this_ori -= pos_unit * np.dot(this_ori, pos_unit) + this_ori /= np.linalg.norm(this_ori) + # This was empirically determined by looking at the dipole fits + if np.abs(this_ori[2]) >= 1e-6: # if it's not in the XY plane + this_ori *= -1 * np.sign(this_ori[2]) # point downward + elif np.abs(this_ori[0]) < 1e-6: # in the XY plane (at the north pole) + this_ori *= -1 * np.sign(this_ori[1]) # point backward + # Odd ones create a RH coordinate system with their ori + if pi % 2: + this_ori = np.cross(pos_unit, this_ori) + else: + this_ori *= signs[pi] + # Now we have this quality, which we could uncomment to + # double-check: + # np.testing.assert_allclose(np.dot(this_ori, this_pos) / + # np.linalg.norm(this_pos), 0, + # atol=1e-15) + ori.append(this_ori) + ori = np.array(ori) + return pos, ori + + +def _concatenate_dipoles(dipoles): + """Concatenate a list of dipoles.""" + times, pos, amplitude, ori, gof = [], [], [], [], [] + for dipole in dipoles: + times.append(dipole.times) + pos.append(dipole.pos) + amplitude.append(dipole.amplitude) + ori.append(dipole.ori) + gof.append(dipole.gof) + + return Dipole( + np.concatenate(times), + np.concatenate(pos), + np.concatenate(amplitude), + np.concatenate(ori), + np.concatenate(gof), + name=None, + ) diff --git a/mne-python/source/mne/epochs.py b/mne-python/source/mne/epochs.py new file mode 100644 index 0000000000000000000000000000000000000000..c9600a0650f381fd69c0e0cc9b3125bd795348fc --- /dev/null +++ b/mne-python/source/mne/epochs.py @@ -0,0 +1,5030 @@ +"""Tools for working with epoched data.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import json +import operator +import os.path as op +from collections import Counter +from copy import deepcopy +from functools import partial +from inspect import getfullargspec +from pathlib import Path + +import numpy as np +from scipy.interpolate import interp1d + +from ._fiff.constants import FIFF +from ._fiff.meas_info import ( + ContainsMixin, + SetChannelsMixin, + _ensure_infos_match, + read_meas_info, + write_meas_info, +) +from ._fiff.open import _get_next_fname, fiff_open +from ._fiff.pick import ( + _DATA_CH_TYPES_SPLIT, + _pick_data_channels, + _picks_to_idx, + channel_indices_by_type, + channel_type, + pick_channels, + pick_info, +) +from ._fiff.proj import ProjMixin, setup_proj +from ._fiff.tag import _read_tag_header, read_tag +from ._fiff.tree import dir_tree_find +from ._fiff.utils import _make_split_fnames +from ._fiff.write import ( + _NEXT_FILE_BUFFER, + INT32_MAX, + _get_split_size, + end_block, + start_and_end_file, + start_block, + write_complex_double_matrix, + write_complex_float_matrix, + write_double_matrix, + write_float, + write_float_matrix, + write_id, + write_int, + write_string, +) +from .annotations import ( + EpochAnnotationsMixin, + _read_annotations_fif, + _write_annotations, + events_from_annotations, +) +from .baseline import _check_baseline, _log_rescale, rescale +from .bem import _check_origin +from .channels.channels import InterpolationMixin, ReferenceMixin, UpdateChannelsMixin +from .event import _read_events_fif, make_fixed_length_events, match_event_names +from .evoked import EvokedArray +from .filter import FilterMixin, _check_fun, detrend +from .fixes import _reshape_view, rng_uniform +from .html_templates import _get_html_template +from .parallel import parallel_func +from .time_frequency.spectrum import EpochsSpectrum, SpectrumMixin, _validate_method +from .time_frequency.tfr import AverageTFR, EpochsTFR +from .utils import ( + ExtendedTimeMixin, + GetEpochsMixin, + SizeMixin, + _build_data_frame, + _check_combine, + _check_event_id, + _check_fname, + _check_option, + _check_pandas_index_arguments, + _check_pandas_installed, + _check_preload, + _check_time_format, + _convert_times, + _ensure_events, + _gen_events, + _on_missing, + _path_like, + _pl, + _prepare_read_metadata, + _prepare_write_metadata, + _scale_dataframe_data, + _validate_type, + check_fname, + check_random_state, + copy_function_doc_to_method_doc, + legacy, + logger, + object_size, + repr_html, + sizeof_fmt, + verbose, + warn, +) +from .utils.docs import fill_doc +from .viz import plot_drop_log, plot_epochs, plot_epochs_image, plot_topo_image_epochs + + +def _pack_reject_params(epochs): + reject_params = dict() + for key in ("reject", "flat", "reject_tmin", "reject_tmax"): + val = getattr(epochs, key, None) + if val is not None: + reject_params[key] = val + return reject_params + + +def _save_split(epochs, split_fnames, part_idx, n_parts, fmt, overwrite): + """Split epochs. + + Anything new added to this function also needs to be added to + BaseEpochs.save to account for new file sizes. + """ + # insert index in filename + this_fname = split_fnames[part_idx] + _check_fname(this_fname, overwrite=overwrite) + + next_fname, next_idx = None, None + if part_idx < n_parts - 1: + next_idx = part_idx + 1 + next_fname = split_fnames[next_idx] + + with start_and_end_file(this_fname) as fid: + _save_part(fid, epochs, fmt, n_parts, next_fname, next_idx) + + +def _save_part(fid, epochs, fmt, n_parts, next_fname, next_idx): + info = epochs.info + meas_id = info["meas_id"] + + start_block(fid, FIFF.FIFFB_MEAS) + write_id(fid, FIFF.FIFF_BLOCK_ID) + if info["meas_id"] is not None: + write_id(fid, FIFF.FIFF_PARENT_BLOCK_ID, info["meas_id"]) + + # Write measurement info + write_meas_info(fid, info) + + # One or more evoked data sets + start_block(fid, FIFF.FIFFB_PROCESSED_DATA) + start_block(fid, FIFF.FIFFB_MNE_EPOCHS) + + # write events out after getting data to ensure bad events are dropped + data = epochs.get_data(copy=False) + + _check_option("fmt", fmt, ["single", "double"]) + + if np.iscomplexobj(data): + if fmt == "single": + write_function = write_complex_float_matrix + elif fmt == "double": + write_function = write_complex_double_matrix + else: + if fmt == "single": + write_function = write_float_matrix + elif fmt == "double": + write_function = write_double_matrix + + # Epoch annotations are written if there are any + annotations = getattr(epochs, "annotations", []) + if annotations is not None and len(annotations): + _write_annotations(fid, annotations) + + # write Epoch event windows + start_block(fid, FIFF.FIFFB_MNE_EVENTS) + write_int(fid, FIFF.FIFF_MNE_EVENT_LIST, epochs.events.T) + write_string(fid, FIFF.FIFF_DESCRIPTION, _event_id_string(epochs.event_id)) + end_block(fid, FIFF.FIFFB_MNE_EVENTS) + + # Metadata + if epochs.metadata is not None: + start_block(fid, FIFF.FIFFB_MNE_METADATA) + metadata = _prepare_write_metadata(epochs.metadata) + write_string(fid, FIFF.FIFF_DESCRIPTION, metadata) + end_block(fid, FIFF.FIFFB_MNE_METADATA) + + # First and last sample + first = int(round(epochs.tmin * info["sfreq"])) # round just to be safe + last = first + len(epochs.times) - 1 + write_int(fid, FIFF.FIFF_FIRST_SAMPLE, first) + write_int(fid, FIFF.FIFF_LAST_SAMPLE, last) + + # write raw original sampling rate + write_float(fid, FIFF.FIFF_MNE_EPOCHS_RAW_SFREQ, epochs._raw_sfreq) + + # save baseline + if epochs.baseline is not None: + bmin, bmax = epochs.baseline + write_float(fid, FIFF.FIFF_MNE_BASELINE_MIN, bmin) + write_float(fid, FIFF.FIFF_MNE_BASELINE_MAX, bmax) + + # The epochs itself + decal = np.empty(info["nchan"]) + for k in range(info["nchan"]): + decal[k] = 1.0 / (info["chs"][k]["cal"] * info["chs"][k].get("scale", 1.0)) + + data *= decal[np.newaxis, :, np.newaxis] + + write_function(fid, FIFF.FIFF_EPOCH, data) + + # undo modifications to data + data /= decal[np.newaxis, :, np.newaxis] + + write_string(fid, FIFF.FIFF_MNE_EPOCHS_DROP_LOG, json.dumps(epochs.drop_log)) + + reject_params = _pack_reject_params(epochs) + if reject_params: + write_string(fid, FIFF.FIFF_MNE_EPOCHS_REJECT_FLAT, json.dumps(reject_params)) + + write_int(fid, FIFF.FIFF_MNE_EPOCHS_SELECTION, epochs.selection) + + # And now write the next file info in case epochs are split on disk + if next_fname is not None and n_parts > 1: + start_block(fid, FIFF.FIFFB_REF) + write_int(fid, FIFF.FIFF_REF_ROLE, FIFF.FIFFV_ROLE_NEXT_FILE) + write_string(fid, FIFF.FIFF_REF_FILE_NAME, op.basename(next_fname)) + if meas_id is not None: + write_id(fid, FIFF.FIFF_REF_FILE_ID, meas_id) + write_int(fid, FIFF.FIFF_REF_FILE_NUM, next_idx) + end_block(fid, FIFF.FIFFB_REF) + + end_block(fid, FIFF.FIFFB_MNE_EPOCHS) + end_block(fid, FIFF.FIFFB_PROCESSED_DATA) + end_block(fid, FIFF.FIFFB_MEAS) + + +def _event_id_string(event_id): + return ";".join([k + ":" + str(v) for k, v in event_id.items()]) + + +def _merge_events(events, event_id, selection): + """Merge repeated events.""" + event_id = event_id.copy() + new_events = events.copy() + event_idxs_to_delete = list() + unique_events, counts = np.unique(events[:, 0], return_counts=True) + for ev in unique_events[counts > 1]: + # indices at which the non-unique events happened + idxs = (events[:, 0] == ev).nonzero()[0] + + # Figure out new value for events[:, 1]. Set to 0, if mixed vals exist + unique_priors = np.unique(events[idxs, 1]) + new_prior = unique_priors[0] if len(unique_priors) == 1 else 0 + + # If duplicate time samples have same event val, "merge" == "drop" + # and no new event_id key will be created + ev_vals = np.unique(events[idxs, 2]) + if len(ev_vals) <= 1: + new_event_val = ev_vals[0] + + # Else, make a new event_id for the merged event + else: + # Find all event_id keys involved in duplicated events. These + # keys will be merged to become a new entry in "event_id" + event_id_keys = list(event_id.keys()) + event_id_vals = list(event_id.values()) + new_key_comps = [ + event_id_keys[event_id_vals.index(value)] for value in ev_vals + ] + + # Check if we already have an entry for merged keys of duplicate + # events ... if yes, reuse it + for key in event_id: + if set(key.split("/")) == set(new_key_comps): + new_event_val = event_id[key] + break + + # Else, find an unused value for the new key and make an entry into + # the event_id dict + else: + ev_vals = np.unique( + np.concatenate( + (list(event_id.values()), events[:, 1:].flatten()), axis=0 + ) + ) + if ev_vals[0] > 1: + new_event_val = 1 + else: + diffs = np.diff(ev_vals) + idx = np.where(diffs > 1)[0] + idx = -1 if len(idx) == 0 else idx[0] + new_event_val = ev_vals[idx] + 1 + + new_event_id_key = "/".join(sorted(new_key_comps)) + event_id[new_event_id_key] = int(new_event_val) + + # Replace duplicate event times with merged event and remember which + # duplicate indices to delete later + new_events[idxs[0], 1] = new_prior + new_events[idxs[0], 2] = new_event_val + event_idxs_to_delete.extend(idxs[1:]) + + # Delete duplicate event idxs + new_events = np.delete(new_events, event_idxs_to_delete, 0) + new_selection = np.delete(selection, event_idxs_to_delete, 0) + + return new_events, event_id, new_selection + + +def _handle_event_repeated(events, event_id, event_repeated, selection, drop_log): + """Handle repeated events. + + Note that drop_log will be modified inplace + """ + assert len(events) == len(selection) + selection = np.asarray(selection) + + unique_events, u_ev_idxs = np.unique(events[:, 0], return_index=True) + + # Return early if no duplicates + if len(unique_events) == len(events): + return events, event_id, selection, drop_log + + # Else, we have duplicates. Triage ... + _check_option("event_repeated", event_repeated, ["error", "drop", "merge"]) + drop_log = list(drop_log) + if event_repeated == "error": + raise RuntimeError( + "Event time samples were not unique. Consider " + 'setting the `event_repeated` parameter."' + ) + + elif event_repeated == "drop": + logger.info( + "Multiple event values for single event times found. " + "Keeping the first occurrence and dropping all others." + ) + new_events = events[u_ev_idxs] + new_selection = selection[u_ev_idxs] + drop_ev_idxs = np.setdiff1d(selection, new_selection) + for idx in drop_ev_idxs: + drop_log[idx] = drop_log[idx] + ("DROP DUPLICATE",) + selection = new_selection + elif event_repeated == "merge": + logger.info( + "Multiple event values for single event times found. " + "Creating new event value to reflect simultaneous events." + ) + new_events, event_id, new_selection = _merge_events(events, event_id, selection) + drop_ev_idxs = np.setdiff1d(selection, new_selection) + for idx in drop_ev_idxs: + drop_log[idx] = drop_log[idx] + ("MERGE DUPLICATE",) + selection = new_selection + drop_log = tuple(drop_log) + + # Remove obsolete kv-pairs from event_id after handling + keys = new_events[:, 1:].flatten() + event_id = {k: v for k, v in event_id.items() if v in keys} + + return new_events, event_id, selection, drop_log + + +@fill_doc +class BaseEpochs( + ProjMixin, + ContainsMixin, + UpdateChannelsMixin, + ReferenceMixin, + SetChannelsMixin, + InterpolationMixin, + FilterMixin, + ExtendedTimeMixin, + SizeMixin, + GetEpochsMixin, + EpochAnnotationsMixin, + SpectrumMixin, +): + """Abstract base class for `~mne.Epochs`-type classes. + + .. note:: + This class should not be instantiated directly via + ``mne.BaseEpochs(...)``. Instead, use one of the functions listed in + the See Also section below. + + Parameters + ---------- + %(info_not_none)s + data : ndarray | None + If ``None``, data will be read from the Raw object. If ndarray, must be + of shape (n_epochs, n_channels, n_times). + %(events_epochs)s + %(event_id)s + %(epochs_tmin_tmax)s + %(baseline_epochs)s + Defaults to ``(None, 0)``, i.e. beginning of the data until + time point zero. + %(raw_epochs)s + %(picks_all)s + %(reject_epochs)s + %(flat)s + %(decim)s + %(epochs_reject_tmin_tmax)s + %(detrend_epochs)s + %(proj_epochs)s + %(on_missing_epochs)s + preload_at_end : bool + %(epochs_preload)s + %(selection)s + + .. versionadded:: 0.16 + %(drop_log)s + filename : Path | None + The filename (if the epochs are read from disk). + %(metadata_epochs)s + + .. versionadded:: 0.16 + %(event_repeated_epochs)s + %(raw_sfreq)s + annotations : instance of mne.Annotations | None + Annotations to set. + %(verbose)s + + See Also + -------- + Epochs + EpochsArray + make_fixed_length_epochs + + Notes + ----- + The ``BaseEpochs`` class is public to allow for stable type-checking in + user code (i.e., ``isinstance(my_epochs, BaseEpochs)``) but should not be + used as a constructor for Epochs objects (use instead :class:`mne.Epochs`). + """ + + @verbose + def __init__( + self, + info, + data, + events, + event_id=None, + tmin=-0.2, + tmax=0.5, + baseline=(None, 0), + raw=None, + picks=None, + reject=None, + flat=None, + decim=1, + reject_tmin=None, + reject_tmax=None, + detrend=None, + proj=True, + on_missing="raise", + preload_at_end=False, + selection=None, + drop_log=None, + filename=None, + metadata=None, + event_repeated="error", + *, + raw_sfreq=None, + annotations=None, + verbose=None, + ): + if events is not None: # RtEpochs can have events=None + events = _ensure_events(events) + # Allow reading empty epochs (ToDo: Maybe not anymore in the future) + if len(events) == 0: + self._allow_empty = True + selection = None + else: + self._allow_empty = False + events_max = events.max() + if events_max > INT32_MAX: + raise ValueError( + f"events array values must not exceed {INT32_MAX}, " + f"got {events_max}" + ) + event_id = _check_event_id(event_id, events) + self.event_id = event_id + del event_id + + if events is not None: # RtEpochs can have events=None + for key, val in self.event_id.items(): + if val not in events[:, 2]: + msg = f"No matching events found for {key} (event id {val})" + _on_missing(on_missing, msg) + + # ensure metadata matches original events size + self.selection = np.arange(len(events)) + self.events = events + + # same as self.metadata = metadata, but suppress log in favor + # of logging below (after setting self.selection) + GetEpochsMixin.metadata.fset(self, metadata, verbose=False) + del events + + values = list(self.event_id.values()) + selected = np.where(np.isin(self.events[:, 2], values))[0] + if selection is None: + selection = selected + else: + selection = np.array(selection, int) + if selection.shape != (len(selected),): + raise ValueError( + f"selection must be shape {selected.shape} got shape " + f"{selection.shape}" + ) + self.selection = selection + if drop_log is None: + self.drop_log = tuple( + () if k in self.selection else ("IGNORED",) + for k in range(max(len(self.events), max(self.selection) + 1)) + ) + else: + self.drop_log = drop_log + + self.events = self.events[selected] + + ( + self.events, + self.event_id, + self.selection, + self.drop_log, + ) = _handle_event_repeated( + self.events, + self.event_id, + event_repeated, + self.selection, + self.drop_log, + ) + + # then subselect + sub = np.where(np.isin(selection, self.selection))[0] + if isinstance(metadata, list): + metadata = [metadata[s] for s in sub] + elif metadata is not None: + metadata = metadata.iloc[sub] + + # Remove temporarily set metadata from above, and set + # again to get the correct log ("adding metadata", instead of + # "replacing existing metadata") + GetEpochsMixin.metadata.fset(self, None, verbose=False) + self.metadata = metadata + del metadata + + n_events = len(self.events) + if n_events > 1: + if np.diff(self.events.astype(np.int64)[:, 0]).min() <= 0: + warn( + "The events passed to the Epochs constructor are not " + "chronologically ordered.", + RuntimeWarning, + ) + + if n_events > 0: + logger.info(f"{n_events} matching events found") + else: + # Allow reading empty epochs (ToDo: Maybe not anymore in the future) + if not self._allow_empty: + raise ValueError("No desired events found.") + else: + self.drop_log = tuple() + self.selection = np.array([], int) + self.metadata = metadata + # do not set self.events here, let subclass do it + + if (detrend not in [None, 0, 1]) or isinstance(detrend, bool): + raise ValueError("detrend must be None, 0, or 1") + self.detrend = detrend + + self._raw = raw + info._check_consistency() + self.picks = _picks_to_idx( + info, picks, none="all", exclude=(), allow_empty=False + ) + self.info = pick_info(info, self.picks) + del info + self._current = 0 + + if data is None: + self.preload = False + self._data = None + self._do_baseline = True + else: + assert decim == 1 + if ( + data.ndim != 3 + or data.shape[2] != round((tmax - tmin) * self.info["sfreq"]) + 1 + ): + raise RuntimeError("bad data shape") + if data.shape[0] != len(self.events): + raise ValueError( + "The number of epochs and the number of events must match" + ) + self.preload = True + self._data = data + self._do_baseline = False + self._offset = None + + if tmin > tmax: + raise ValueError("tmin has to be less than or equal to tmax") + + # Handle times + sfreq = float(self.info["sfreq"]) + start_idx = int(round(tmin * sfreq)) + self._raw_times = np.arange(start_idx, int(round(tmax * sfreq)) + 1) / sfreq + self._set_times(self._raw_times) + + # check reject_tmin and reject_tmax + if reject_tmin is not None: + if np.isclose(reject_tmin, tmin): + # adjust for potential small deviations due to sampling freq + reject_tmin = self.tmin + elif reject_tmin < tmin: + raise ValueError( + f"reject_tmin needs to be None or >= tmin (got {reject_tmin})" + ) + + if reject_tmax is not None: + if np.isclose(reject_tmax, tmax): + # adjust for potential small deviations due to sampling freq + reject_tmax = self.tmax + elif reject_tmax > tmax: + raise ValueError( + f"reject_tmax needs to be None or <= tmax (got {reject_tmax})" + ) + + if (reject_tmin is not None) and (reject_tmax is not None): + if reject_tmin >= reject_tmax: + raise ValueError( + f"reject_tmin ({reject_tmin}) needs to be " + f" < reject_tmax ({reject_tmax})" + ) + + self.reject_tmin = reject_tmin + self.reject_tmax = reject_tmax + + # decimation + self._decim = 1 + self.decimate(decim) + + # baseline correction: replace `None` tuple elements with actual times + self.baseline = _check_baseline( + baseline, times=self.times, sfreq=self.info["sfreq"] + ) + if self.baseline is not None and self.baseline != baseline: + logger.info( + f"Setting baseline interval to " + f"[{self.baseline[0]}, {self.baseline[1]}] s" + ) + + logger.info(_log_rescale(self.baseline)) + + # setup epoch rejection + self.reject = None + self.flat = None + self._reject_setup(reject, flat) + + # do the rest + valid_proj = [True, "delayed", False] + if proj not in valid_proj: + raise ValueError(f'"proj" must be one of {valid_proj}, not {proj}') + if proj == "delayed": + self._do_delayed_proj = True + logger.info("Entering delayed SSP mode.") + else: + self._do_delayed_proj = False + activate = False if self._do_delayed_proj else proj + self._projector, self.info = setup_proj(self.info, False, activate=activate) + if preload_at_end: + assert self._data is None + assert self.preload is False + self.load_data() # this will do the projection + elif proj is True and self._projector is not None and data is not None: + # let's make sure we project if data was provided and proj + # requested + # we could do this with np.einsum, but iteration should be + # more memory safe in most instances + for ii, epoch in enumerate(self._data): + self._data[ii] = np.dot(self._projector, epoch) + self.filename = filename if filename is not None else filename + if raw_sfreq is None: + raw_sfreq = self.info["sfreq"] + self._raw_sfreq = raw_sfreq + self._check_consistency() + self.set_annotations(annotations, on_missing="ignore") + + def _check_consistency(self): + """Check invariants of epochs object.""" + if hasattr(self, "events"): + assert len(self.selection) == len(self.events) + assert len(self.drop_log) >= len(self.events) + assert len(self.selection) == sum(len(dl) == 0 for dl in self.drop_log) + assert hasattr(self, "_times_readonly") + assert not self.times.flags["WRITEABLE"] + assert isinstance(self.drop_log, tuple) + assert all(isinstance(log, tuple) for log in self.drop_log) + assert all(isinstance(s, str) for log in self.drop_log for s in log) + + @legacy(alt="mne.Epochs.reset_index()") + def reset_drop_log_selection(self): + """Reset the drop_log and selection entries. + + This method will simplify ``self.drop_log`` and ``self.selection`` + so that they are meaningless (tuple of empty tuples and increasing + integers, respectively). This can be useful when concatenating + many Epochs instances, as ``drop_log`` can accumulate many entries + which can become problematic when saving. + """ + self.reset_index() + + def reset_index(self): + """Reset the epochs index. + + This resets the epochs indexing and drop log so that ``self.selection`` becomes + a simple increasing sequence starting at zero and ``self.drop_log`` becomes a + tuple of empty tuples of the same length. The operation is in-place and is + useful when creating epochs from a subset of events (using ``event_id``) and the + original event indexes are not relevant anymore. + """ + self.selection = np.arange(len(self.events)) + self.drop_log = (tuple(),) * len(self.events) + self._check_consistency() + + def load_data(self): + """Load the data if not already preloaded. + + Returns + ------- + epochs : instance of Epochs + The epochs object. + + Notes + ----- + This function operates in-place. + + .. versionadded:: 0.10.0 + """ + if self.preload: + return self + self._data = self._get_data() + self.preload = True + self._do_baseline = False + self._decim_slice = slice(None, None, None) + self._decim = 1 + self._raw_times = self.times + assert self._data.shape[-1] == len(self.times) + self._raw = None # shouldn't need it anymore + return self + + @verbose + def apply_baseline(self, baseline=(None, 0), *, verbose=None): + """Baseline correct epochs. + + Parameters + ---------- + %(baseline_epochs)s + Defaults to ``(None, 0)``, i.e. beginning of the data until + time point zero. + %(verbose)s + + Returns + ------- + epochs : instance of Epochs + The baseline-corrected Epochs object. + + Notes + ----- + Baseline correction can be done multiple times, but can never be + reverted once the data has been loaded. + + .. versionadded:: 0.10.0 + """ + baseline = _check_baseline(baseline, times=self.times, sfreq=self.info["sfreq"]) + + if self.preload: + if self.baseline is not None and baseline is None: + raise RuntimeError( + "You cannot remove baseline correction " + "from preloaded data once it has been " + "applied." + ) + self._do_baseline = True + picks = self._detrend_picks + rescale(self._data, self.times, baseline, copy=False, picks=picks) + self._do_baseline = False + else: # logging happens in "rescale" in "if" branch + logger.info(_log_rescale(baseline)) + # For EpochsArray and Epochs, this is already True: + # assert self._do_baseline is True + # ... but for EpochsFIF it's not, so let's set it explicitly + self._do_baseline = True + self.baseline = baseline + return self + + def _reject_setup(self, reject, flat, *, allow_callable=False): + """Set self._reject_time and self._channel_type_idx.""" + idx = channel_indices_by_type(self.info) + reject = deepcopy(reject) if reject is not None else dict() + flat = deepcopy(flat) if flat is not None else dict() + for rej, kind in zip((reject, flat), ("reject", "flat")): + _validate_type(rej, dict, kind) + bads = set(rej.keys()) - set(idx.keys()) + if len(bads) > 0: + raise KeyError(f"Unknown channel types found in {kind}: {bads}") + + for key in idx.keys(): + # don't throw an error if rejection/flat would do nothing + if len(idx[key]) == 0 and ( + np.isfinite(reject.get(key, np.inf)) or flat.get(key, -1) >= 0 + ): + # This is where we could eventually add e.g. + # self.allow_missing_reject_keys check to allow users to + # provide keys that don't exist in data + raise ValueError( + f"No {key.upper()} channel found. Cannot reject based on " + f"{key.upper()}." + ) + + # check for invalid values + for rej, kind in zip((reject, flat), ("Rejection", "Flat")): + for key, val in rej.items(): + name = f"{kind} dict value for {key}" + if callable(val) and allow_callable: + continue + extra_str = "" + if allow_callable: + extra_str = "or callable" + _validate_type(val, "numeric", name, extra=extra_str) + if val is None or val < 0: + raise ValueError( + f"If using numerical {name} criteria, the value " + f"must be >= 0, not {repr(val)}" + ) + + # now check to see if our rejection and flat are getting more + # restrictive + old_reject = self.reject if self.reject is not None else dict() + old_flat = self.flat if self.flat is not None else dict() + bad_msg = ( + '{kind}["{key}"] == {new} {op} {old} (old value), new ' + "{kind} values must be at least as stringent as " + "previous ones" + ) + + # copy thresholds for channel types that were used previously, but not + # passed this time + for key in set(old_reject) - set(reject): + reject[key] = old_reject[key] + # make sure new thresholds are at least as stringent as the old ones + for key in reject: + # Skip this check if old_reject and reject are callables + if callable(reject[key]) and allow_callable: + continue + if key in old_reject and reject[key] > old_reject[key]: + raise ValueError( + bad_msg.format( + kind="reject", + key=key, + new=reject[key], + old=old_reject[key], + op=">", + ) + ) + + # same for flat thresholds + for key in set(old_flat) - set(flat): + flat[key] = old_flat[key] + for key in flat: + if callable(flat[key]) and allow_callable: + continue + if key in old_flat and flat[key] < old_flat[key]: + raise ValueError( + bad_msg.format( + kind="flat", key=key, new=flat[key], old=old_flat[key], op="<" + ) + ) + + # after validation, set parameters + self._bad_dropped = False + self._channel_type_idx = idx + self.reject = reject if len(reject) > 0 else None + self.flat = flat if len(flat) > 0 else None + + if (self.reject_tmin is None) and (self.reject_tmax is None): + self._reject_time = None + else: + if self.reject_tmin is None: + reject_imin = None + else: + idxs = np.nonzero(self.times >= self.reject_tmin)[0] + reject_imin = idxs[0] + if self.reject_tmax is None: + reject_imax = None + else: + idxs = np.nonzero(self.times <= self.reject_tmax)[0] + reject_imax = idxs[-1] + self._reject_time = slice(reject_imin, reject_imax) + + @verbose # verbose is used by mne-realtime + def _is_good_epoch(self, data, verbose=None): + """Determine if epoch is good.""" + if isinstance(data, str): + return False, (data,) + if data is None: + return False, ("NO_DATA",) + n_times = len(self.times) + if data.shape[1] < n_times: + # epoch is too short ie at the end of the data + return False, ("TOO_SHORT",) + if self.reject is None and self.flat is None: + return True, None + else: + if self._reject_time is not None: + data = data[:, self._reject_time] + + return _is_good( + data, + self.ch_names, + self._channel_type_idx, + self.reject, + self.flat, + full_report=True, + ignore_chs=self.info["bads"], + ) + + @verbose + def _detrend_offset_decim(self, epoch, picks, verbose=None): + """Aux Function: detrend, baseline correct, offset, decim. + + Note: operates inplace + """ + if (epoch is None) or isinstance(epoch, str): + return epoch + + # Detrend + if self.detrend is not None: + # We explicitly detrend just data channels (not EMG, ECG, EOG which + # are processed by baseline correction) + use_picks = _pick_data_channels(self.info, exclude=()) + epoch[use_picks] = detrend(epoch[use_picks], self.detrend, axis=1) + + # Baseline correct + if self._do_baseline: + rescale( + epoch, + self._raw_times, + self.baseline, + picks=picks, + copy=False, + verbose=False, + ) + + # Decimate if necessary (i.e., epoch not preloaded) + epoch = epoch[:, self._decim_slice] + + # handle offset + if self._offset is not None: + epoch += self._offset + + return epoch + + def iter_evoked(self, copy=False): + """Iterate over epochs as a sequence of Evoked objects. + + The Evoked objects yielded will each contain a single epoch (i.e., no + averaging is performed). + + This method resets the object iteration state to the first epoch. + + Parameters + ---------- + copy : bool + If False copies of data and measurement info will be omitted + to save time. + """ + self.__iter__() + + while True: + try: + out = self.__next__(True) + except StopIteration: + break + data, event_id = out + tmin = self.times[0] + info = self.info + if copy: + info = deepcopy(self.info) + data = data.copy() + + yield EvokedArray(data, info, tmin, comment=str(event_id)) + + def subtract_evoked(self, evoked=None): + """Subtract an evoked response from each epoch. + + Can be used to exclude the evoked response when analyzing induced + activity, see e.g. [1]_. + + Parameters + ---------- + evoked : instance of Evoked | None + The evoked response to subtract. If None, the evoked response + is computed from Epochs itself. + + Returns + ------- + self : instance of Epochs + The modified instance (instance is also modified inplace). + + References + ---------- + .. [1] David et al. "Mechanisms of evoked and induced responses in + MEG/EEG", NeuroImage, vol. 31, no. 4, pp. 1580-1591, July 2006. + """ + logger.info("Subtracting Evoked from Epochs") + if evoked is None: + picks = _pick_data_channels(self.info, exclude=[]) + evoked = self.average(picks) + + # find the indices of the channels to use + picks = pick_channels(evoked.ch_names, include=self.ch_names, ordered=False) + + # make sure the omitted channels are not data channels + if len(picks) < len(self.ch_names): + sel_ch = [evoked.ch_names[ii] for ii in picks] + diff_ch = list(set(self.ch_names).difference(sel_ch)) + diff_idx = [self.ch_names.index(ch) for ch in diff_ch] + diff_types = [channel_type(self.info, idx) for idx in diff_idx] + bad_idx = [ + diff_types.index(t) for t in diff_types if t in _DATA_CH_TYPES_SPLIT + ] + if len(bad_idx) > 0: + bad_str = ", ".join([diff_ch[ii] for ii in bad_idx]) + raise ValueError( + "The following data channels are missing " + f"in the evoked response: {bad_str}" + ) + logger.info( + " The following channels are not included in the subtraction: " + + ", ".join(diff_ch) + ) + + # make sure the times match + if ( + len(self.times) != len(evoked.times) + or np.max(np.abs(self.times - evoked.times)) >= 1e-7 + ): + raise ValueError( + "Epochs and Evoked object do not contain the same time points." + ) + + # handle SSPs + if not self.proj and evoked.proj: + warn("Evoked has SSP applied while Epochs has not.") + if self.proj and not evoked.proj: + evoked = evoked.copy().apply_proj() + + # find the indices of the channels to use in Epochs + ep_picks = [self.ch_names.index(evoked.ch_names[ii]) for ii in picks] + + # do the subtraction + if self.preload: + self._data[:, ep_picks, :] -= evoked.data[picks][None, :, :] + else: + if self._offset is None: + self._offset = np.zeros( + (len(self.ch_names), len(self.times)), dtype=np.float64 + ) + self._offset[ep_picks] -= evoked.data[picks] + logger.info("[done]") + + return self + + @fill_doc + def average(self, picks=None, method="mean", by_event_type=False): + """Compute an average over epochs. + + Parameters + ---------- + %(picks_all_data)s + method : str | callable + How to combine the data. If "mean"/"median", the mean/median + are returned. + Otherwise, must be a callable which, when passed an array of shape + (n_epochs, n_channels, n_time) returns an array of shape + (n_channels, n_time). + Note that due to file type limitations, the kind for all + these will be "average". + %(by_event_type)s + + Returns + ------- + %(evoked_by_event_type_returns)s + + Notes + ----- + Computes an average of all epochs in the instance, even if + they correspond to different conditions. To average by condition, + do ``epochs[condition].average()`` for each condition separately. + + When picks is None and epochs contain only ICA channels, no channels + are selected, resulting in an error. This is because ICA channels + are not considered data channels (they are of misc type) and only data + channels are selected when picks is None. + + The ``method`` parameter allows e.g. robust averaging. + For example, one could do: + + >>> from scipy.stats import trim_mean # doctest:+SKIP + >>> trim = lambda x: trim_mean(x, 0.1, axis=0) # doctest:+SKIP + >>> epochs.average(method=trim) # doctest:+SKIP + + This would compute the trimmed mean. + """ + self._handle_empty("raise", "average") + if by_event_type: + evokeds = list() + for event_type in self.event_id.keys(): + ev = self[event_type]._compute_aggregate(picks=picks, mode=method) + ev.comment = event_type + evokeds.append(ev) + else: + evokeds = self._compute_aggregate(picks=picks, mode=method) + return evokeds + + @fill_doc + def standard_error(self, picks=None, by_event_type=False): + """Compute standard error over epochs. + + Parameters + ---------- + %(picks_all_data)s + %(by_event_type)s + + Returns + ------- + %(std_err_by_event_type_returns)s + """ + return self.average(picks=picks, method="std", by_event_type=by_event_type) + + def _compute_aggregate(self, picks, mode="mean"): + """Compute the mean, median, or std over epochs and return Evoked.""" + # if instance contains ICA channels they won't be included unless picks + # is specified + if picks is None: + check_ICA = [x.startswith("ICA") for x in self.ch_names] + if np.all(check_ICA): + raise TypeError( + "picks must be specified (i.e. not None) for ICA channel data" + ) + elif np.any(check_ICA): + warn( + "ICA channels will not be included unless explicitly " + "selected in picks" + ) + + n_channels = len(self.ch_names) + n_times = len(self.times) + + if self.preload: + n_events = len(self.events) + fun = _check_combine(mode, valid=("mean", "median", "std")) + data = fun(self._data) + assert len(self.events) == len(self._data) + if data.shape != self._data.shape[1:]: + raise RuntimeError( + f"You passed a function that resulted n data of shape " + f"{data.shape}, but it should be {self._data.shape[1:]}." + ) + else: + if mode not in {"mean", "std"}: + raise ValueError( + "If data are not preloaded, can only compute " + "mean or standard deviation." + ) + data = np.zeros((n_channels, n_times)) + n_events = 0 + for e in self: + if np.iscomplexobj(e): + data = data.astype(np.complex128) + data += e + n_events += 1 + + if n_events > 0: + data /= n_events + else: + data.fill(np.nan) + + # convert to stderr if requested, could do in one pass but do in + # two (slower) in case there are large numbers + if mode == "std": + data_mean = data.copy() + data.fill(0.0) + for e in self: + data += (e - data_mean) ** 2 + data = np.sqrt(data / n_events) + + if mode == "std": + kind = "standard_error" + data /= np.sqrt(n_events) + else: + kind = "average" + + return self._evoked_from_epoch_data( + data, self.info, picks, n_events, kind, self._name + ) + + @property + def _name(self): + """Give a nice string representation based on event ids.""" + return self._get_name() + + def _get_name(self, count="frac", ms="×", sep="+"): + """Generate human-readable name for epochs and evokeds from event_id. + + Parameters + ---------- + count : 'frac' | 'total' + Whether to include the fraction or total number of epochs that each + event type contributes to the number of all epochs. + Ignored if only one event type is present. + ms : str | None + The multiplication sign to use. Pass ``None`` to omit the sign. + Ignored if only one event type is present. + sep : str + How to separate the different events names. Ignored if only one + event type is present. + """ + _check_option("count", value=count, allowed_values=["frac", "total"]) + + if len(self.event_id) == 1: + comment = next(iter(self.event_id.keys())) + else: + counter = Counter(self.events[:, 2]) + comments = list() + + # Take care of padding + if ms is None: + ms = " " + else: + ms = f" {ms} " + + for event_name, event_code in self.event_id.items(): + if count == "frac": + frac = float(counter[event_code]) / len(self.events) + comment = f"{frac:.2f}{ms}{event_name}" + else: # 'total' + comment = f"{counter[event_code]}{ms}{event_name}" + comments.append(comment) + + comment = f" {sep} ".join(comments) + return comment + + def _evoked_from_epoch_data(self, data, info, picks, n_events, kind, comment): + """Create an evoked object from epoch data.""" + info = deepcopy(info) + # don't apply baseline correction; we'll set evoked.baseline manually + evoked = EvokedArray( + data, + info, + tmin=self.times[0], + comment=comment, + nave=n_events, + kind=kind, + baseline=None, + ) + evoked.baseline = self.baseline + + # the above constructor doesn't recreate the times object precisely + # due to numerical precision issues + evoked._set_times(self.times.copy()) + + # pick channels + picks = _picks_to_idx(self.info, picks, "data_or_ica", ()) + ch_names = [evoked.ch_names[p] for p in picks] + evoked.pick(ch_names) + + if len(evoked.info["ch_names"]) == 0: + raise ValueError("No data channel found when averaging.") + + if evoked.nave < 1: + warn("evoked object is empty (based on less than 1 epoch)") + + return evoked + + @property + def ch_names(self): + """Channel names.""" + return self.info["ch_names"] + + @copy_function_doc_to_method_doc(plot_epochs) + def plot( + self, + picks=None, + scalings=None, + n_epochs=20, + n_channels=20, + title=None, + events=False, + event_color=None, + order=None, + show=True, + block=False, + decim="auto", + noise_cov=None, + butterfly=False, + show_scrollbars=True, + show_scalebars=True, + epoch_colors=None, + event_id=None, + group_by="type", + precompute=None, + use_opengl=None, + *, + theme=None, + overview_mode=None, + splash=True, + ): + return plot_epochs( + self, + picks=picks, + scalings=scalings, + n_epochs=n_epochs, + n_channels=n_channels, + title=title, + events=events, + event_color=event_color, + order=order, + show=show, + block=block, + decim=decim, + noise_cov=noise_cov, + butterfly=butterfly, + show_scrollbars=show_scrollbars, + show_scalebars=show_scalebars, + epoch_colors=epoch_colors, + event_id=event_id, + group_by=group_by, + precompute=precompute, + use_opengl=use_opengl, + theme=theme, + overview_mode=overview_mode, + splash=splash, + ) + + @copy_function_doc_to_method_doc(plot_topo_image_epochs) + def plot_topo_image( + self, + layout=None, + sigma=0.0, + vmin=None, + vmax=None, + colorbar=None, + order=None, + cmap="RdBu_r", + layout_scale=0.95, + title=None, + scalings=None, + border="none", + fig_facecolor="k", + fig_background=None, + font_color="w", + select=False, + show=True, + ): + return plot_topo_image_epochs( + self, + layout=layout, + sigma=sigma, + vmin=vmin, + vmax=vmax, + colorbar=colorbar, + order=order, + cmap=cmap, + layout_scale=layout_scale, + title=title, + scalings=scalings, + border=border, + fig_facecolor=fig_facecolor, + fig_background=fig_background, + font_color=font_color, + select=select, + show=show, + ) + + @verbose + def drop_bad(self, reject="existing", flat="existing", verbose=None): + """Drop bad epochs without retaining the epochs data. + + Should be used before slicing operations. + + .. warning:: This operation is slow since all epochs have to be read + from disk. To avoid reading epochs from disk multiple + times, use :meth:`mne.Epochs.load_data()`. + + .. note:: To constrain the time period used for estimation of signal + quality, set ``epochs.reject_tmin`` and + ``epochs.reject_tmax``, respectively. + + Parameters + ---------- + %(reject_drop_bad)s + %(flat_drop_bad)s + %(verbose)s + + Returns + ------- + epochs : instance of Epochs + The epochs with bad epochs dropped. Operates in-place. + + Notes + ----- + Dropping bad epochs can be done multiple times with different + ``reject`` and ``flat`` parameters. However, once an epoch is + dropped, it is dropped forever, so if more lenient thresholds may + subsequently be applied, :meth:`epochs.copy ` should be + used. + """ + if reject == "existing": + if flat == "existing" and self._bad_dropped: + return + reject = self.reject + if flat == "existing": + flat = self.flat + if any(isinstance(rej, str) and rej != "existing" for rej in (reject, flat)): + raise ValueError('reject and flat, if strings, must be "existing"') + self._reject_setup(reject, flat, allow_callable=True) + self._get_data(out=False, verbose=verbose) + return self + + def drop_log_stats(self, ignore=("IGNORED",)): + """Compute the channel stats based on a drop_log from Epochs. + + Parameters + ---------- + ignore : list + The drop reasons to ignore. + + Returns + ------- + perc : float + Total percentage of epochs dropped. + + See Also + -------- + plot_drop_log + """ + return _drop_log_stats(self.drop_log, ignore) + + @copy_function_doc_to_method_doc(plot_drop_log) + def plot_drop_log( + self, + threshold=0, + n_max_plot=20, + subject=None, + color=(0.9, 0.9, 0.9), + width=0.8, + ignore=("IGNORED",), + show=True, + ): + if not self._bad_dropped: + raise ValueError( + "You cannot use plot_drop_log since bad " + "epochs have not yet been dropped. " + "Use epochs.drop_bad()." + ) + return plot_drop_log( + self.drop_log, + threshold, + n_max_plot, + subject, + color=color, + width=width, + ignore=ignore, + show=show, + ) + + @copy_function_doc_to_method_doc(plot_epochs_image) + def plot_image( + self, + picks=None, + sigma=0.0, + vmin=None, + vmax=None, + colorbar=True, + order=None, + show=True, + units=None, + scalings=None, + cmap=None, + fig=None, + axes=None, + overlay_times=None, + combine=None, + group_by=None, + evoked=True, + ts_args=None, + title=None, + clear=False, + ): + return plot_epochs_image( + self, + picks=picks, + sigma=sigma, + vmin=vmin, + vmax=vmax, + colorbar=colorbar, + order=order, + show=show, + units=units, + scalings=scalings, + cmap=cmap, + fig=fig, + axes=axes, + overlay_times=overlay_times, + combine=combine, + group_by=group_by, + evoked=evoked, + ts_args=ts_args, + title=title, + clear=clear, + ) + + @verbose + def drop(self, indices, reason="USER", verbose=None): + """Drop epochs based on indices or boolean mask. + + .. note:: The indices refer to the current set of undropped epochs + rather than the complete set of dropped and undropped epochs. + They are therefore not necessarily consistent with any + external indices (e.g., behavioral logs). To drop epochs + based on external criteria, do not use the ``preload=True`` + flag when constructing an Epochs object, and call this + method before calling the :meth:`mne.Epochs.drop_bad` or + :meth:`mne.Epochs.load_data` methods. + + Parameters + ---------- + indices : array of int or bool + Set epochs to remove by specifying indices to remove or a boolean + mask to apply (where True values get removed). Events are + correspondingly modified. + reason : list | tuple | str + Reason(s) for dropping the epochs ('ECG', 'timeout', 'blink' etc). + Reason(s) are applied to all indices specified. + Default: 'USER'. + %(verbose)s + + Returns + ------- + epochs : instance of Epochs + The epochs with indices dropped. Operates in-place. + + Notes + ----- + This method expects zero-based indices into the currently remaining + epochs, not the original event indices (as found in + the ``selection`` attribute). If some epochs were previously dropped (possibly + automatically, e.g., due to rejection thresholds or being too close to recording + start or end), you may need to convert indices before calling this method:: + + # epochs.selection contains the original indices (which are also shown by + # epochs.plot()) of the remaining epochs + plot_idx = 1 # index shown in epochs.plot() + drop_idx = np.where(epochs.selection == plot_idx)[0] + epochs.drop(drop_idx) + """ + indices = np.atleast_1d(indices) + + if indices.ndim > 1: + raise TypeError("indices must be a scalar or a 1-d array") + # Check if indices and reasons are of the same length + # if using collection to drop epochs + + if indices.dtype == np.dtype(bool): + indices = np.where(indices)[0] + try_idx = np.where(indices < 0, indices + len(self.events), indices) + + out_of_bounds = (try_idx < 0) | (try_idx >= len(self.events)) + if out_of_bounds.any(): + first = indices[out_of_bounds][0] + raise IndexError(f"Epoch index {first} is out of bounds") + keep = np.setdiff1d(np.arange(len(self.events)), try_idx) + self._getitem(keep, reason, copy=False, drop_event_id=False) + count = len(try_idx) + logger.info( + "Dropped %d epoch%s: %s", + count, + _pl(count), + ", ".join(map(str, np.sort(try_idx))), + ) + + return self + + def _get_epoch_from_raw(self, idx, verbose=None): + """Get a given epoch from disk.""" + raise NotImplementedError + + def _project_epoch(self, epoch): + """Process a raw epoch based on the delayed param.""" + # whenever requested, the first epoch is being projected. + if (epoch is None) or isinstance(epoch, str): + # can happen if t < 0 or reject based on annotations + return epoch + proj = self._do_delayed_proj or self.proj + if self._projector is not None and proj is True: + epoch = np.dot(self._projector, epoch) + return epoch + + def _handle_empty(self, on_empty, meth): + if len(self.events) == 0: + msg = ( + f"epochs.{meth}() can't run because this Epochs-object is empty. " + f"You might want to check Epochs.drop_log or Epochs.plot_drop_log()" + f" to see why epochs were dropped." + ) + _on_missing(on_empty, msg, error_klass=RuntimeError) + + @verbose + def _get_data( + self, + out=True, + picks=None, + item=None, + *, + units=None, + tmin=None, + tmax=None, + copy=False, + on_empty="warn", + verbose=None, + ): + """Load all data, dropping bad epochs along the way. + + Parameters + ---------- + out : bool + Return the data. Setting this to False is used to reject bad + epochs without caching all the data, which saves memory. + %(picks_all)s + item : slice | array-like | str | list | None + See docstring of get_data method. + %(units)s + tmin : int | float | None + Start time of data to get in seconds. + tmax : int | float | None + End time of data to get in seconds. + %(verbose)s + """ + from .io.base import _get_ch_factors + + if copy is not None: + _validate_type(copy, bool, "copy") + + # Handle empty epochs + self._handle_empty(on_empty, "_get_data") + # if called with 'out=False', the call came from 'drop_bad()' + # if no reasons to drop, just declare epochs as good and return + if not out: + # make sure first and last epoch not out of bounds of raw + in_bounds = self.preload or ( + self._get_epoch_from_raw(idx=0) is not None + and self._get_epoch_from_raw(idx=-1) is not None + ) + # might be BaseEpochs or Epochs, only the latter has the attribute + reject_by_annotation = getattr(self, "reject_by_annotation", False) + if ( + self.reject is None + and self.flat is None + and in_bounds + and self._reject_time is None + and not reject_by_annotation + ): + logger.debug("_get_data is a noop, returning") + self._bad_dropped = True + return None + start, stop = self._handle_tmin_tmax(tmin, tmax) + + if item is None: + item = slice(None) + elif not self._bad_dropped: + raise ValueError( + "item must be None in epochs.get_data() unless bads have been " + "dropped. Consider using epochs.drop_bad()." + ) + select = self._item_to_select(item) # indices or slice + use_idx = np.arange(len(self.events))[select] + n_events = len(use_idx) + # in case there are no good events + if self.preload: + # we will store our result in our existing array + data = self._data + else: + # we start out with an empty array, allocate only if necessary + data = np.empty((0, len(self.info["ch_names"]), len(self.times))) + msg = ( + f"for {n_events} events and {len(self._raw_times)} original time points" + ) + if self._decim > 1: + msg += " (prior to decimation)" + if getattr(self._raw, "preload", False): + logger.info(f"Using data from preloaded Raw {msg} ...") + else: + logger.info(f"Loading data {msg} ...") + + orig_picks = picks + if orig_picks is None: + picks = _picks_to_idx(self.info, picks, "all", exclude=()) + else: + picks = _picks_to_idx(self.info, picks) + + # handle units param only if we are going to return data (out==True) + if (units is not None) and out: + ch_factors = _get_ch_factors(self, units, picks) + else: + ch_factors = None + + if self._bad_dropped: + if not out: + return + if self.preload: + return self._data_sel_copy_scale( + data, + select=select, + orig_picks=orig_picks, + picks=picks, + ch_factors=ch_factors, + start=start, + stop=stop, + copy=copy, + ) + + # we need to load from disk, drop, and return data + detrend_picks = self._detrend_picks + for ii, idx in enumerate(use_idx): + # faster to pre-allocate memory here + epoch_noproj = self._get_epoch_from_raw(idx) + epoch_noproj = self._detrend_offset_decim(epoch_noproj, detrend_picks) + if self._do_delayed_proj: + epoch_out = epoch_noproj + else: + epoch_out = self._project_epoch(epoch_noproj) + if ii == 0: + data = np.empty( + (n_events, len(self.ch_names), len(self.times)), + dtype=epoch_out.dtype, + ) + data[ii] = epoch_out + else: + # bads need to be dropped, this might occur after a preload + # e.g., when calling drop_bad w/new params + good_idx = [] + n_out = 0 + drop_log = list(self.drop_log) + assert n_events == len(self.selection) + if not self.preload: + detrend_picks = self._detrend_picks + for idx, sel in enumerate(self.selection): + if self.preload: # from memory + if self._do_delayed_proj: + epoch_noproj = self._data[idx] + epoch = self._project_epoch(epoch_noproj) + else: + epoch_noproj = None + epoch = self._data[idx] + else: # from disk + epoch_noproj = self._get_epoch_from_raw(idx) + epoch_noproj = self._detrend_offset_decim( + epoch_noproj, detrend_picks + ) + epoch = self._project_epoch(epoch_noproj) + + epoch_out = epoch_noproj if self._do_delayed_proj else epoch + is_good, bad_tuple = self._is_good_epoch(epoch, verbose=verbose) + if not is_good: + assert isinstance(bad_tuple, tuple) + assert all(isinstance(x, str) for x in bad_tuple) + drop_log[sel] = drop_log[sel] + bad_tuple + continue + good_idx.append(idx) + + # store the epoch if there is a reason to (output or update) + if out or self.preload: + # faster to pre-allocate, then trim as necessary + if n_out == 0 and not self.preload: + data = np.empty( + (n_events, epoch_out.shape[0], epoch_out.shape[1]), + dtype=epoch_out.dtype, + order="C", + ) + data[n_out] = epoch_out + n_out += 1 + self.drop_log = tuple(drop_log) + del drop_log + + self._bad_dropped = True + n_bads_dropped = n_events - len(good_idx) + logger.info(f"{n_bads_dropped} bad epochs dropped") + + if n_bads_dropped == n_events: + warn( + "All epochs were dropped!\n" + "You might need to alter reject/flat-criteria " + "or drop bad channels to avoid this. " + "You can use Epochs.plot_drop_log() to see which " + "channels are responsible for the dropping of epochs." + ) + + # adjust the data size if there is a reason to (output or update) + if out or self.preload: + if data.flags["OWNDATA"] and data.flags["C_CONTIGUOUS"]: + data.resize((n_out,) + data.shape[1:], refcheck=False) + else: + data = data[:n_out] + if self.preload: + self._data = data + + # Now update our properties (excepd data, which is already fixed) + self._getitem( + good_idx, None, copy=False, drop_event_id=False, select_data=False + ) + + if not out: + return + return self._data_sel_copy_scale( + data, + select=slice(None), + orig_picks=orig_picks, + picks=picks, + ch_factors=ch_factors, + start=start, + stop=stop, + copy=copy, + ) + + def _data_sel_copy_scale( + self, data, *, select, orig_picks, picks, ch_factors, start, stop, copy + ): + # data arg starts out as self._data when data is preloaded + data_is_self_data = bool(self.preload) + logger.debug(f"Data is self data: {data_is_self_data}") + # only two types of epoch subselection allowed + assert isinstance(select, slice | np.ndarray), type(select) + if not isinstance(select, slice): + logger.debug(" Copying, fancy indexed epochs") + data_is_self_data = False # copy (fancy indexing) + elif select != slice(None): + logger.debug(" Slicing epochs") + if orig_picks is not None: + logger.debug(" Copying, fancy indexed picks") + assert isinstance(picks, np.ndarray), type(picks) + data_is_self_data = False # copy (fancy indexing) + else: + picks = slice(None) + if not all(isinstance(x, slice) and x == slice(None) for x in (select, picks)): + data = data[select][:, picks] + del picks + if start != 0 or stop != self.times.size: + logger.debug(" Slicing time") + data = data[..., start:stop] # view (slice) + if ch_factors is not None: + if data_is_self_data: + logger.debug(" Copying, scale factors applied") + data = data.copy() + data_is_self_data = False + data *= ch_factors[:, np.newaxis] + if not data_is_self_data: + return data + if copy: + logger.debug(" Copying, copy=True") + data = data.copy() + return data + + @property + def _detrend_picks(self): + if self._do_baseline: + return _pick_data_channels( + self.info, with_ref_meg=True, with_aux=True, exclude=() + ) + else: + return [] + + @verbose + def get_data( + self, + picks=None, + item=None, + units=None, + tmin=None, + tmax=None, + *, + copy=True, + verbose=None, + ): + """Get all epochs as a 3D array. + + Parameters + ---------- + %(picks_all)s + item : slice | array-like | str | list | None + The items to get. See :meth:`mne.Epochs.__getitem__` for + a description of valid options. This can be substantially faster + for obtaining an ndarray than :meth:`~mne.Epochs.__getitem__` + for repeated access on large Epochs objects. + None (default) is an alias for ``slice(None)``. + + .. versionadded:: 0.20 + %(units)s + + .. versionadded:: 0.24 + tmin : int | float | None + Start time of data to get in seconds. + + .. versionadded:: 0.24.0 + tmax : int | float | None + End time of data to get in seconds. + + .. versionadded:: 0.24.0 + copy : bool + Whether to return a copy of the object's data, or (if possible) a view. + See :ref:`the NumPy docs ` for an + explanation. Default is ``False`` in 1.6 but will change to ``True`` in 1.7, + set it explicitly to avoid a warning in some cases. A view is only possible + when ``item is None``, ``picks is None``, ``units is None``, and data are + preloaded. + + .. warning:: + Using ``copy=False`` and then modifying the returned ``data`` will in + turn modify the Epochs object. Use with caution! + + .. versionchanged:: 1.7 + The default changed from ``False`` to ``True``. + + .. versionadded:: 1.6 + %(verbose)s + + Returns + ------- + data : array of shape (n_epochs, n_channels, n_times) + The epochs data. Will be a copy when ``copy=True`` and will be a view + when possible when ``copy=False``. + """ + return self._get_data( + picks=picks, item=item, units=units, tmin=tmin, tmax=tmax, copy=copy + ) + + @verbose + def apply_function( + self, + fun, + picks=None, + dtype=None, + n_jobs=None, + channel_wise=True, + verbose=None, + **kwargs, + ): + """Apply a function to a subset of channels. + + %(applyfun_summary_epochs)s + + Parameters + ---------- + %(fun_applyfun)s + %(picks_all_data_noref)s + %(dtype_applyfun)s + %(n_jobs)s Ignored if ``channel_wise=False`` as the workload + is split across channels. + %(channel_wise_applyfun_epo)s + %(verbose)s + %(kwargs_fun)s + + Returns + ------- + self : instance of Epochs + The epochs object with transformed data. + """ + _check_preload(self, "epochs.apply_function") + picks = _picks_to_idx(self.info, picks, exclude=(), with_ref_meg=False) + + if not callable(fun): + raise ValueError("fun needs to be a function") + + data_in = self._data + if dtype is not None and dtype != self._data.dtype: + self._data = self._data.astype(dtype) + + args = getfullargspec(fun).args + getfullargspec(fun).kwonlyargs + if channel_wise is False: + if ("ch_idx" in args) or ("ch_name" in args): + raise ValueError( + "apply_function cannot access ch_idx or ch_name " + "when channel_wise=False" + ) + if "ch_idx" in args: + logger.info("apply_function requested to access ch_idx") + if "ch_name" in args: + logger.info("apply_function requested to access ch_name") + + if channel_wise: + parallel, p_fun, n_jobs = parallel_func(_check_fun, n_jobs) + if n_jobs == 1: + _fun = partial(_check_fun, fun) + # modify data inplace to save memory + for ch_idx in picks: + if "ch_idx" in args: + kwargs.update(ch_idx=ch_idx) + if "ch_name" in args: + kwargs.update(ch_name=self.info["ch_names"][ch_idx]) + self._data[:, ch_idx, :] = np.apply_along_axis( + _fun, -1, data_in[:, ch_idx, :], **kwargs + ) + else: + # use parallel function + _fun = partial(np.apply_along_axis, fun, -1) + data_picks_new = parallel( + p_fun( + _fun, + data_in[:, ch_idx, :], + **kwargs, + **{ + k: v + for k, v in [ + ("ch_name", self.info["ch_names"][ch_idx]), + ("ch_idx", ch_idx), + ] + if k in args + }, + ) + for ch_idx in picks + ) + for run_idx, ch_idx in enumerate(picks): + self._data[:, ch_idx, :] = data_picks_new[run_idx] + else: + self._data = _check_fun(fun, data_in, **kwargs) + + return self + + @property + def filename(self) -> Path | None: + """The filename if the epochs are loaded from disk. + + :type: :class:`pathlib.Path` | ``None`` + """ + return self._filename + + @filename.setter + def filename(self, value): + if value is not None: + value = _check_fname(value, overwrite="read", must_exist=True) + self._filename = value + + def __repr__(self): + """Build string representation.""" + s = f"{len(self.events)} events " + s += "(all good)" if self._bad_dropped else "(good & bad)" + s += f", {self.tmin:.3f}".rstrip("0").rstrip(".") + s += f" – {self.tmax:.3f}".rstrip("0").rstrip(".") + s += " s (baseline " + if self.baseline is None: + s += "off" + else: + s += f"{self.baseline[0]:.3f}".rstrip("0").rstrip(".") + s += f" – {self.baseline[1]:.3f}".rstrip("0").rstrip(".") + s += " s" + if self.baseline != _check_baseline( + self.baseline, + times=self.times, + sfreq=self.info["sfreq"], + on_baseline_outside_data="adjust", + ): + s += " (baseline period was cropped after baseline correction)" + + s += f"), ~{sizeof_fmt(self._size)}" + s += f", data{'' if self.preload else ' not'} loaded" + s += ", with metadata" if self.metadata is not None else "" + max_events = 10 + counts = [ + f"{k!r}: {sum(self.events[:, 2] == v)}" + for k, v in list(self.event_id.items())[:max_events] + ] + if len(self.event_id) > 0: + s += "," + "\n ".join([""] + counts) + if len(self.event_id) > max_events: + not_shown_events = len(self.event_id) - max_events + s += f"\n and {not_shown_events} more events ..." + class_name = self.__class__.__name__ + class_name = "Epochs" if class_name == "BaseEpochs" else class_name + return f"<{class_name} | {s}>" + + @repr_html + def _repr_html_(self): + if isinstance(self.event_id, dict): + event_strings = [] + for k, v in sorted(self.event_id.items()): + n_events = sum(self.events[:, 2] == v) + event_strings.append(f"{k}: {n_events}") + elif isinstance(self.event_id, list): + event_strings = [] + for k in self.event_id: + n_events = sum(self.events[:, 2] == k) + event_strings.append(f"{k}: {n_events}") + elif isinstance(self.event_id, int): + n_events = len(self.events[:, 2]) + event_strings = [f"{self.event_id}: {n_events}"] + else: + event_strings = None + + t = _get_html_template("repr", "epochs.html.jinja") + t = t.render( + inst=self, + filenames=( + [Path(self.filename).name] + if getattr(self, "filename", None) is not None + else None + ), + event_counts=event_strings, + ) + return t + + @verbose + def crop(self, tmin=None, tmax=None, include_tmax=True, verbose=None): + """Crop a time interval from the epochs. + + Parameters + ---------- + tmin : float | None + Start time of selection in seconds. + tmax : float | None + End time of selection in seconds. + %(include_tmax)s + %(verbose)s + + Returns + ------- + epochs : instance of Epochs + The cropped epochs object, modified in-place. + + Notes + ----- + %(notes_tmax_included_by_default)s + """ + # XXX this could be made to work on non-preloaded data... + _check_preload(self, "Modifying data of epochs") + + super().crop(tmin=tmin, tmax=tmax, include_tmax=include_tmax) + + # Adjust rejection period + if self.reject_tmin is not None and self.reject_tmin < self.tmin: + logger.info( + f"reject_tmin is not in epochs time interval. " + f"Setting reject_tmin to epochs.tmin ({self.tmin} s)" + ) + self.reject_tmin = self.tmin + if self.reject_tmax is not None and self.reject_tmax > self.tmax: + logger.info( + f"reject_tmax is not in epochs time interval. " + f"Setting reject_tmax to epochs.tmax ({self.tmax} s)" + ) + self.reject_tmax = self.tmax + return self + + def copy(self): + """Return copy of Epochs instance. + + Returns + ------- + epochs : instance of Epochs + A copy of the object. + """ + return deepcopy(self) + + def __deepcopy__(self, memodict): + """Make a deepcopy.""" + cls = self.__class__ + result = cls.__new__(cls) + for k, v in self.__dict__.items(): + # drop_log is immutable and _raw is private (and problematic to + # deepcopy) + if k in ("drop_log", "_raw", "_times_readonly"): + memodict[id(v)] = v + else: + v = deepcopy(v, memodict) + result.__dict__[k] = v + return result + + @verbose + def save( + self, + fname, + split_size="2GB", + fmt="single", + overwrite=False, + split_naming="neuromag", + verbose=None, + ): + """Save epochs in a fif file. + + Parameters + ---------- + fname : path-like + The name of the file, which should end with ``-epo.fif`` or + ``-epo.fif.gz``. + split_size : str | int + Large raw files are automatically split into multiple pieces. This + parameter specifies the maximum size of each piece. If the + parameter is an integer, it specifies the size in Bytes. It is + also possible to pass a human-readable string, e.g., 100MB. + Note: Due to FIFF file limitations, the maximum split size is 2GB. + + .. versionadded:: 0.10.0 + fmt : str + Format to save data. Valid options are 'double' or + 'single' for 64- or 32-bit float, or for 128- or + 64-bit complex numbers respectively. Note: Data are processed with + double precision. Choosing single-precision, the saved data + will slightly differ due to the reduction in precision. + + .. versionadded:: 0.17 + %(overwrite)s + To overwrite original file (the same one that was loaded), + data must be preloaded upon reading. This defaults to True in 0.18 + but will change to False in 0.19. + + .. versionadded:: 0.18 + %(split_naming)s + + .. versionadded:: 0.24 + %(verbose)s + + Returns + ------- + fnames : List of path-like + List of path-like objects containing the path to each file split. + + .. versionadded:: 1.9 + + Notes + ----- + Bad epochs will be dropped before saving the epochs to disk. + """ + check_fname( + fname, "epochs", ("-epo.fif", "-epo.fif.gz", "_epo.fif", "_epo.fif.gz") + ) + + # check for file existence and expand `~` if present + fname = str( + _check_fname( + fname=fname, + overwrite=overwrite, + check_bids_split=True, + name="fname", + ) + ) + + split_size_bytes = _get_split_size(split_size) + + _check_option("fmt", fmt, ["single", "double"]) + + # to know the length accurately. The get_data() call would drop + # bad epochs anyway + self.drop_bad() + # total_size tracks sizes that get split + # over_size tracks overhead (tags, things that get written to each) + if len(self) == 0: + warn("Saving epochs with no data") + total_size = 0 + else: + d = self[0].get_data(copy=False) + # this should be guaranteed by subclasses + assert d.dtype in (">f8", "c16", "= 1, n_parts + if n_parts > 1: + logger.info(f"Splitting into {n_parts} parts") + if n_parts > 100: # This must be an error + raise ValueError( + f"Split size {split_size} would result in writing {n_parts} files" + ) + + if len(self.drop_log) > 100000: + warn( + f"epochs.drop_log contains {len(self.drop_log)} entries " + f"which will incur up to a {sizeof_fmt(drop_size)} writing " + f"overhead (per split file), consider using " + f"epochs.reset_drop_log_selection() prior to writing" + ) + + epoch_idxs = np.array_split(np.arange(n_epochs), n_parts) + + _check_option("split_naming", split_naming, ("neuromag", "bids")) + split_fnames = _make_split_fnames(fname, n_parts, split_naming) + for part_idx, epoch_idx in enumerate(epoch_idxs): + this_epochs = self[epoch_idx] if n_parts > 1 else self + # avoid missing event_ids in splits + this_epochs.event_id = self.event_id + + _save_split(this_epochs, split_fnames, part_idx, n_parts, fmt, overwrite) + return split_fnames + + @verbose + def export(self, fname, fmt="auto", *, overwrite=False, verbose=None): + """Export Epochs to external formats. + + %(export_fmt_support_epochs)s + + %(export_warning)s + + Parameters + ---------- + %(fname_export_params)s + %(export_fmt_params_epochs)s + %(overwrite)s + + .. versionadded:: 0.24.1 + %(verbose)s + + Notes + ----- + .. versionadded:: 0.24 + + %(export_warning_note_epochs)s + %(export_eeglab_note)s + """ + from .export import export_epochs + + export_epochs(fname, self, fmt, overwrite=overwrite, verbose=verbose) + + @fill_doc + def equalize_event_counts( + self, event_ids=None, method="mintime", *, random_state=None + ): + """Equalize the number of trials in each condition. + + It tries to make the remaining epochs occurring as close as possible in + time. This method works based on the idea that if there happened to be + some time-varying (like on the scale of minutes) noise characteristics + during a recording, they could be compensated for (to some extent) in + the equalization process. This method thus seeks to reduce any of + those effects by minimizing the differences in the times of the events + within a `~mne.Epochs` instance. For example, if one event type + occurred at time points ``[1, 2, 3, 4, 120, 121]`` and the another one + at ``[3.5, 4.5, 120.5, 121.5]``, this method would remove the events at + times ``[1, 2]`` for the first event type – and not the events at times + ``[120, 121]``. + + Parameters + ---------- + event_ids : None | list | dict + The event types to equalize. + + If ``None`` (default), equalize the counts of **all** event types + present in the `~mne.Epochs` instance. + + If a list, each element can either be a string (event name) or a + list of strings. In the case where one of the entries is a list of + strings, event types in that list will be grouped together before + equalizing trial counts across conditions. + + If a dictionary, the keys are considered as the event names whose + counts to equalize, i.e., passing ``dict(A=1, B=2)`` will have the + same effect as passing ``['A', 'B']``. This is useful if you intend + to pass an ``event_id`` dictionary that was used when creating + `~mne.Epochs`. + + In the case where partial matching is used (using ``/`` in + the event names), the event types will be matched according to the + provided tags, that is, processing works as if the ``event_ids`` + matched by the provided tags had been supplied instead. + The ``event_ids`` must identify non-overlapping subsets of the + epochs. + %(equalize_events_method)s + %(random_state)s Used only if ``method='random'``. + + Returns + ------- + epochs : instance of Epochs + The modified instance. It is modified in-place. + indices : array of int + Indices from the original events list that were dropped. + + Notes + ----- + For example (if ``epochs.event_id`` was ``{'Left': 1, 'Right': 2, + 'Nonspatial':3}``: + + epochs.equalize_event_counts([['Left', 'Right'], 'Nonspatial']) + + would equalize the number of trials in the ``'Nonspatial'`` condition + with the total number of trials in the ``'Left'`` and ``'Right'`` + conditions combined. + + If multiple indices are provided (e.g. ``'Left'`` and ``'Right'`` in + the example above), it is not guaranteed that after equalization the + conditions will contribute equally. E.g., it is possible to end up + with 70 ``'Nonspatial'`` epochs, 69 ``'Left'`` and 1 ``'Right'``. + + .. versionchanged:: 0.23 + Default to equalizing all events in the passed instance if no + event names were specified explicitly. + """ + from collections.abc import Iterable + + _validate_type( + event_ids, + types=(Iterable, None), + item_name="event_ids", + type_name="list-like or None", + ) + if isinstance(event_ids, str): + raise TypeError( + f"event_ids must be list-like or None, but " + f"received a string: {event_ids}" + ) + + if event_ids is None: + event_ids = list(self.event_id) + elif not event_ids: + raise ValueError("event_ids must have at least one element") + + if not self._bad_dropped: + self.drop_bad() + # figure out how to equalize + eq_inds = list() + + # deal with hierarchical tags + ids = self.event_id + orig_ids = list(event_ids) + tagging = False + if "/" in "".join(ids): + # make string inputs a list of length 1 + event_ids = [[x] if isinstance(x, str) else x for x in event_ids] + for ids_ in event_ids: # check if tagging is attempted + if any([id_ not in ids for id_ in ids_]): + tagging = True + # 1. treat everything that's not in event_id as a tag + # 2a. for tags, find all the event_ids matched by the tags + # 2b. for non-tag ids, just pass them directly + # 3. do this for every input + event_ids = [ + ( + [ + k for k in ids if all(tag in k.split("/") for tag in id_) + ] # ids matching all tags + if all(id__ not in ids for id__ in id_) + else id_ + ) # straight pass for non-tag inputs + for id_ in event_ids + ] + for ii, id_ in enumerate(event_ids): + if len(id_) == 0: + raise KeyError( + f"{orig_ids[ii]} not found in the epoch object's event_id." + ) + elif len({sub_id in ids for sub_id in id_}) != 1: + err = ( + "Don't mix hierarchical and regular event_ids" + f" like in '{', '.join(id_)}'." + ) + raise ValueError(err) + + # raise for non-orthogonal tags + if tagging is True: + events_ = [set(self[x].events[:, 0]) for x in event_ids] + doubles = events_[0].intersection(events_[1]) + if len(doubles): + raise ValueError( + "The two sets of epochs are " + "overlapping. Provide an " + "orthogonal selection." + ) + + for eq in event_ids: + eq_inds.append(self._keys_to_idx(eq)) + + sample_nums = [self.events[e, 0] for e in eq_inds] + indices = _get_drop_indices(sample_nums, method, random_state) + # need to re-index indices + indices = np.concatenate([e[idx] for e, idx in zip(eq_inds, indices)]) + self.drop(indices, reason="EQUALIZED_COUNT") + # actually remove the indices + return self, indices + + @verbose + def compute_psd( + self, + method="multitaper", + fmin=0, + fmax=np.inf, + tmin=None, + tmax=None, + picks=None, + proj=False, + remove_dc=True, + exclude=(), + *, + n_jobs=1, + verbose=None, + **method_kw, + ): + """Perform spectral analysis on sensor data. + + Parameters + ---------- + %(method_psd)s + Default is ``'multitaper'``. + %(fmin_fmax_psd)s + %(tmin_tmax_psd)s + %(picks_good_data_noref)s + %(proj_psd)s + %(remove_dc)s + %(exclude_psd)s + %(n_jobs)s + %(verbose)s + %(method_kw_psd)s + + Returns + ------- + spectrum : instance of EpochsSpectrum + The spectral representation of each epoch. + + Notes + ----- + .. versionadded:: 1.2 + + References + ---------- + .. footbibliography:: + """ + method = _validate_method(method, type(self).__name__) + self._set_legacy_nfft_default(tmin, tmax, method, method_kw) + + return EpochsSpectrum( + self, + method=method, + fmin=fmin, + fmax=fmax, + tmin=tmin, + tmax=tmax, + picks=picks, + exclude=exclude, + proj=proj, + remove_dc=remove_dc, + n_jobs=n_jobs, + verbose=verbose, + **method_kw, + ) + + @verbose + def compute_tfr( + self, + method, + freqs, + *, + tmin=None, + tmax=None, + picks=None, + proj=False, + output="power", + average=False, + return_itc=False, + decim=1, + n_jobs=None, + verbose=None, + **method_kw, + ): + """Compute a time-frequency representation of epoched data. + + Parameters + ---------- + %(method_tfr_epochs)s + %(freqs_tfr_epochs)s + %(tmin_tmax_psd)s + %(picks_good_data_noref)s + %(proj_psd)s + %(output_compute_tfr)s + average : bool + Whether to return average power across epochs (instead of single-trial + power). ``average=True`` is not compatible with ``output="complex"`` or + ``output="phase"``. Ignored if ``method="stockwell"`` (Stockwell method + *requires* averaging). Default is ``False``. + return_itc : bool + Whether to return inter-trial coherence (ITC) as well as power estimates. + If ``True`` then must specify ``average=True`` (or ``method="stockwell", + average="auto"``). Default is ``False``. + %(decim_tfr)s + %(n_jobs)s + %(verbose)s + %(method_kw_epochs_tfr)s + + Returns + ------- + tfr : instance of EpochsTFR or AverageTFR + The time-frequency-resolved power estimates. + itc : instance of AverageTFR + The inter-trial coherence (ITC). Only returned if ``return_itc=True``. + + Notes + ----- + If ``average=True`` (or ``method="stockwell", average="auto"``) the result will + be an :class:`~mne.time_frequency.AverageTFR` instead of an + :class:`~mne.time_frequency.EpochsTFR`. + + .. versionadded:: 1.7 + + References + ---------- + .. footbibliography:: + """ + if method == "stockwell" and not average: # stockwell method *must* average + logger.info( + 'Requested `method="stockwell"` so ignoring parameter `average=False`.' + ) + average = True + if average: + # augment `output` value for use by tfr_array_* functions + _check_option("output", output, ("power",), extra=" when average=True") + method_kw["output"] = "avg_power_itc" if return_itc else "avg_power" + else: + msg = ( + "compute_tfr() got incompatible parameters `average=False` and `{}` " + "({} requires averaging over epochs)." + ) + if return_itc: + raise ValueError(msg.format("return_itc=True", "computing ITC")) + if method == "stockwell": + raise ValueError(msg.format('method="stockwell"', "Stockwell method")) + # `average` and `return_itc` both False, so "phase" and "complex" are OK + _check_option("output", output, ("power", "phase", "complex")) + method_kw["output"] = output + + if method == "stockwell": + method_kw["return_itc"] = return_itc + method_kw.pop("output") + if isinstance(freqs, str): + _check_option("freqs", freqs, "auto") + else: + _validate_type(freqs, "array-like") + _check_option( + "freqs", np.array(freqs).shape, ((2,),), extra=" (wrong shape)." + ) + if average: + out = AverageTFR( + inst=self, + method=method, + freqs=freqs, + tmin=tmin, + tmax=tmax, + picks=picks, + proj=proj, + decim=decim, + n_jobs=n_jobs, + verbose=verbose, + **method_kw, + ) + # tfr_array_stockwell always returns ITC (but sometimes it's None) + if hasattr(out, "_itc"): + if out._itc is not None: + state = out.__getstate__() + state["data"] = out._itc + state["data_type"] = "Inter-trial coherence" + itc = AverageTFR(inst=state) + del out._itc + return out, itc + del out._itc + return out + # now handle average=False + return EpochsTFR( + inst=self, + method=method, + freqs=freqs, + tmin=tmin, + tmax=tmax, + picks=picks, + proj=proj, + decim=decim, + n_jobs=n_jobs, + verbose=verbose, + **method_kw, + ) + + @verbose + def plot_psd( + self, + fmin=0, + fmax=np.inf, + tmin=None, + tmax=None, + picks=None, + proj=False, + *, + method="auto", + average=False, + dB=True, + estimate="power", + xscale="linear", + area_mode="std", + area_alpha=0.33, + color="black", + line_alpha=None, + spatial_colors=True, + sphere=None, + exclude="bads", + ax=None, + show=True, + n_jobs=1, + verbose=None, + **method_kw, + ): + """%(plot_psd_doc)s. + + Parameters + ---------- + %(fmin_fmax_psd)s + %(tmin_tmax_psd)s + %(picks_good_data_noref)s + %(proj_psd)s + %(method_plot_psd_auto)s + %(average_plot_psd)s + %(dB_plot_psd)s + %(estimate_plot_psd)s + %(xscale_plot_psd)s + %(area_mode_plot_psd)s + %(area_alpha_plot_psd)s + %(color_plot_psd)s + %(line_alpha_plot_psd)s + %(spatial_colors_psd)s + %(sphere_topomap_auto)s + + .. versionadded:: 0.22.0 + exclude : list of str | 'bads' + Channels names to exclude from being shown. If 'bads', the bad + channels are excluded. Pass an empty list to plot all channels + (including channels marked "bad", if any). + + .. versionadded:: 0.24.0 + %(ax_plot_psd)s + %(show)s + %(n_jobs)s + %(verbose)s + %(method_kw_psd)s + + Returns + ------- + fig : instance of Figure + Figure with frequency spectra of the data channels. + + Notes + ----- + %(notes_plot_psd_meth)s + """ + return super().plot_psd( + fmin=fmin, + fmax=fmax, + tmin=tmin, + tmax=tmax, + picks=picks, + proj=proj, + reject_by_annotation=False, + method=method, + average=average, + dB=dB, + estimate=estimate, + xscale=xscale, + area_mode=area_mode, + area_alpha=area_alpha, + color=color, + line_alpha=line_alpha, + spatial_colors=spatial_colors, + sphere=sphere, + exclude=exclude, + ax=ax, + show=show, + n_jobs=n_jobs, + verbose=verbose, + **method_kw, + ) + + @verbose + def to_data_frame( + self, + picks=None, + index=None, + scalings=None, + copy=True, + long_format=False, + time_format=None, + *, + verbose=None, + ): + """Export data in tabular structure as a pandas DataFrame. + + Channels are converted to columns in the DataFrame. By default, + additional columns "time", "epoch" (epoch number), and "condition" + (epoch event description) are added, unless ``index`` is not ``None`` + (in which case the columns specified in ``index`` will be used to form + the DataFrame's index instead). + + Parameters + ---------- + %(picks_all)s + %(index_df_epo)s + Valid string values are 'time', 'epoch', and 'condition'. + Defaults to ``None``. + %(scalings_df)s + %(copy_df)s + %(long_format_df_epo)s + %(time_format_df)s + + .. versionadded:: 0.20 + %(verbose)s + + Returns + ------- + %(df_return)s + """ + # check pandas once here, instead of in each private utils function + pd = _check_pandas_installed() # noqa + # arg checking + valid_index_args = ["time", "epoch", "condition"] + valid_time_formats = ["ms", "timedelta"] + index = _check_pandas_index_arguments(index, valid_index_args) + time_format = _check_time_format(time_format, valid_time_formats) + # get data + picks = _picks_to_idx(self.info, picks, "all", exclude=()) + data = self._get_data(on_empty="raise")[:, picks, :] + times = self.times + n_epochs, n_picks, n_times = data.shape + data = np.hstack(data).T # (time*epochs) x signals + if copy: + data = data.copy() + data = _scale_dataframe_data(self, data, picks, scalings) + # prepare extra columns / multiindex + mindex = list() + times = np.tile(times, n_epochs) + times = _convert_times(times, time_format, meas_date=self.info["meas_date"]) + mindex.append(("time", times)) + rev_event_id = {v: k for k, v in self.event_id.items()} + conditions = [rev_event_id[k] for k in self.events[:, 2]] + mindex.append(("condition", np.repeat(conditions, n_times))) + mindex.append(("epoch", np.repeat(self.selection, n_times))) + assert all(len(mdx) == len(mindex[0]) for mdx in mindex) + # build DataFrame + df = _build_data_frame( + self, + data, + picks, + long_format, + mindex, + index, + default_index=["condition", "epoch", "time"], + ) + return df + + def as_type(self, ch_type="grad", mode="fast"): + """Compute virtual epochs using interpolated fields. + + .. Warning:: Using virtual epochs to compute inverse can yield + unexpected results. The virtual channels have ``'_v'`` appended + at the end of the names to emphasize that the data contained in + them are interpolated. + + Parameters + ---------- + ch_type : str + The destination channel type. It can be 'mag' or 'grad'. + mode : str + Either ``'accurate'`` or ``'fast'``, determines the quality of the + Legendre polynomial expansion used. ``'fast'`` should be sufficient + for most applications. + + Returns + ------- + epochs : instance of mne.EpochsArray + The transformed epochs object containing only virtual channels. + + Notes + ----- + This method returns a copy and does not modify the data it + operates on. It also returns an EpochsArray instance. + + .. versionadded:: 0.20.0 + """ + from .forward import _as_meg_type_inst + + self._handle_empty("raise", "as_type") + return _as_meg_type_inst(self, ch_type=ch_type, mode=mode) + + +def _drop_log_stats(drop_log, ignore=("IGNORED",)): + """Compute drop log stats. + + Parameters + ---------- + drop_log : list of list + Epoch drop log from Epochs.drop_log. + ignore : list + The drop reasons to ignore. + + Returns + ------- + perc : float + Total percentage of epochs dropped. + """ + if ( + not isinstance(drop_log, tuple) + or not all(isinstance(d, tuple) for d in drop_log) + or not all(isinstance(s, str) for d in drop_log for s in d) + ): + raise TypeError("drop_log must be a tuple of tuple of str") + perc = 100 * np.mean( + [len(d) > 0 for d in drop_log if not any(r in ignore for r in d)] + ) + return perc + + +def make_metadata( + events, + event_id, + tmin, + tmax, + sfreq, + row_events=None, + keep_first=None, + keep_last=None, +): + """Automatically generate metadata for use with `mne.Epochs` from events. + + This function mimics the epoching process (it constructs time windows + around time-locked "events of interest") and collates information about + any other events that occurred within those time windows. The information + is returned as a :class:`pandas.DataFrame`, suitable for use as + `~mne.Epochs` metadata: one row per time-locked event, and columns + indicating presence or absence and latency of each ancillary event type. + + The function will also return a new ``events`` array and ``event_id`` + dictionary that correspond to the generated metadata, which together can then be + readily fed into `~mne.Epochs`. + + Parameters + ---------- + events : array, shape (m, 3) + The :term:`events array `. By default, the returned metadata + :class:`~pandas.DataFrame` will have as many rows as the events array. + To create rows for only a subset of events, pass the ``row_events`` + parameter. + event_id : dict + A mapping from event names (keys) to event IDs (values). The event + names will be incorporated as columns of the returned metadata + :class:`~pandas.DataFrame`. + tmin, tmax : float | str | list of str | None + If float, start and end of the time interval for metadata generation in seconds, + relative to the time-locked event of the respective time window (the "row + events"). + + .. note:: + If you are planning to attach the generated metadata to + `~mne.Epochs` and intend to include only events that fall inside + your epoch's time interval, pass the same ``tmin`` and ``tmax`` + values here as you use for your epochs. + + If ``None``, the time window used for metadata generation is bounded by the + ``row_events``. This is can be particularly practical if trial duration varies + greatly, but each trial starts with a known event (e.g., a visual cue or + fixation). + + .. note:: + If ``tmin=None``, the first time window for metadata generation starts with + the first row event. If ``tmax=None``, the last time window for metadata + generation ends with the last event in ``events``. + + If a string or a list of strings, the events bounding the metadata around each + "row event". For ``tmin``, the events are assumed to occur **before** the row + event, and for ``tmax``, the events are assumed to occur **after** – unless + ``tmin`` or ``tmax`` are equal to a row event, in which case the row event + serves as the bound. + + .. versionchanged:: 1.6.0 + Added support for ``None``. + + .. versionadded:: 1.7.0 + Added support for strings. + sfreq : float + The sampling frequency of the data from which the events array was + extracted. + row_events : list of str | str | None + Event types around which to create the time windows. For each of these + time-locked events, we will create a **row** in the returned metadata + :class:`pandas.DataFrame`. If provided, the string(s) must be keys of + ``event_id``. If ``None`` (default), rows are created for **all** event types + present in ``event_id``. + keep_first : str | list of str | None + Specify subsets of :term:`hierarchical event descriptors` (HEDs, + inspired by :footcite:`BigdelyShamloEtAl2013`) matching events of which + the **first occurrence** within each time window shall be stored in + addition to the original events. + + .. note:: + There is currently no way to retain **all** occurrences of a + repeated event. The ``keep_first`` parameter can be used to specify + subsets of HEDs, effectively creating a new event type that is the + union of all events types described by the matching HED pattern. + Only the very first event of this set will be kept. + + For example, you might have two response events types, + ``response/left`` and ``response/right``; and in trials with both + responses occurring, you want to keep only the first response. In this + case, you can pass ``keep_first='response'``. This will add two new + columns to the metadata: ``response``, indicating at what **time** the + event occurred, relative to the time-locked event; and + ``first_response``, stating which **type** (``'left'`` or ``'right'``) + of event occurred. + To match specific subsets of HEDs describing different sets of events, + pass a list of these subsets, e.g. + ``keep_first=['response', 'stimulus']``. If ``None`` (default), no + event aggregation will take place and no new columns will be created. + + .. note:: + By default, this function will always retain the first instance + of any event in each time window. For example, if a time window + contains two ``'response'`` events, the generated ``response`` + column will automatically refer to the first of the two events. In + this specific case, it is therefore **not** necessary to make use of + the ``keep_first`` parameter – unless you need to differentiate + between two types of responses, like in the example above. + + keep_last : list of str | None + Same as ``keep_first``, but for keeping only the **last** occurrence + of matching events. The column indicating the **type** of an event + ``myevent`` will be named ``last_myevent``. + + Returns + ------- + metadata : pandas.DataFrame + Metadata for each row event, with the following columns: + + - ``event_name``, with strings indicating the name of the time-locked + event ("row event") for that specific time window + + - one column per event type in ``event_id``, with the same name; floats + indicating the latency of the event in seconds, relative to the + time-locked event + + - if applicable, additional columns named after the ``keep_first`` and + ``keep_last`` event types; floats indicating the latency of the + event in seconds, relative to the time-locked event + + - if applicable, additional columns ``first_{event_type}`` and + ``last_{event_type}`` for ``keep_first`` and ``keep_last`` event + types, respetively; the values will be strings indicating which event + types were matched by the provided HED patterns + + events : array, shape (n, 3) + The events corresponding to the generated metadata, i.e. one + time-locked event per row. + event_id : dict + The event dictionary corresponding to the new events array. This will + be identical to the input dictionary unless ``row_events`` is supplied, + in which case it will only contain the events provided there. + + Notes + ----- + The time window used for metadata generation need not correspond to the + time window used to create the `~mne.Epochs`, to which the metadata will + be attached; it may well be much shorter or longer, or not overlap at all, + if desired. This can be useful, for example, to include events that + occurred before or after an epoch, e.g. during the inter-trial interval. + If either ``tmin``, ``tmax``, or both are ``None``, or a string referring e.g. to a + response event, the time window will typically vary, too. + + .. versionadded:: 0.23 + + References + ---------- + .. footbibliography:: + """ + pd = _check_pandas_installed() + + _validate_type(events, types=("array-like",), item_name="events") + _validate_type(event_id, types=(dict,), item_name="event_id") + _validate_type(sfreq, types=("numeric",), item_name="sfreq") + _validate_type(tmin, types=("numeric", str, "array-like", None), item_name="tmin") + _validate_type(tmax, types=("numeric", str, "array-like", None), item_name="tmax") + _validate_type(row_events, types=(None, str, "array-like"), item_name="row_events") + _validate_type(keep_first, types=(None, str, "array-like"), item_name="keep_first") + _validate_type(keep_last, types=(None, str, "array-like"), item_name="keep_last") + + if not event_id: + raise ValueError("event_id dictionary must contain at least one entry") + + def _ensure_list(x): + if x is None: + return [] + elif isinstance(x, str): + return [x] + else: + return list(x) + + row_events = _ensure_list(row_events) + keep_first = _ensure_list(keep_first) + keep_last = _ensure_list(keep_last) + + # Turn tmin, tmax into a list if they're strings or arrays of strings + try: + _validate_type(tmin, types=(str, "array-like"), item_name="tmin") + tmin = _ensure_list(tmin) + except TypeError: + pass + + try: + _validate_type(tmax, types=(str, "array-like"), item_name="tmax") + tmax = _ensure_list(tmax) + except TypeError: + pass + + keep_first_and_last = set(keep_first) & set(keep_last) + if keep_first_and_last: + raise ValueError( + f"The event names in keep_first and keep_last must " + f"be mutually exclusive. Specified in both: " + f"{', '.join(sorted(keep_first_and_last))}" + ) + del keep_first_and_last + + for param_name, values in dict(keep_first=keep_first, keep_last=keep_last).items(): + for first_last_event_name in values: + try: + match_event_names(event_id, [first_last_event_name]) + except KeyError: + raise ValueError( + f'Event "{first_last_event_name}", specified in ' + f"{param_name}, cannot be found in event_id dictionary" + ) + + # If tmin, tmax are strings, ensure these event names are present in event_id + def _diff_input_strings_vs_event_id(input_strings, input_name, event_id): + event_name_diff = sorted(set(input_strings) - set(event_id.keys())) + if event_name_diff: + raise ValueError( + f"Present in {input_name}, but missing from event_id: " + f"{', '.join(event_name_diff)}" + ) + + _diff_input_strings_vs_event_id( + input_strings=row_events, input_name="row_events", event_id=event_id + ) + if isinstance(tmin, list): + _diff_input_strings_vs_event_id( + input_strings=tmin, input_name="tmin", event_id=event_id + ) + if isinstance(tmax, list): + _diff_input_strings_vs_event_id( + input_strings=tmax, input_name="tmax", event_id=event_id + ) + + # First and last sample of each epoch, relative to the time-locked event + # This follows the approach taken in mne.Epochs + # For strings and None, we don't know the start and stop samples in advance as the + # time window can vary. + if isinstance(tmin, type(None) | list): + start_sample = None + else: + start_sample = int(round(tmin * sfreq)) + + if isinstance(tmax, type(None) | list): + stop_sample = None + else: + stop_sample = int(round(tmax * sfreq)) + 1 + + # Make indexing easier + # We create the DataFrame before subsetting the events so we end up with + # indices corresponding to the original event indices. Not used for now, + # but might come in handy sometime later + events_df = pd.DataFrame(events, columns=("sample", "prev_id", "id")) + id_to_name_map = {v: k for k, v in event_id.items()} + + # Only keep events that are of interest + events = events[np.isin(events[:, 2], list(event_id.values()))] + events_df = events_df.loc[events_df["id"].isin(event_id.values()), :] + + # Prepare & condition the metadata DataFrame + + # Avoid column name duplications if the exact same event name appears in + # event_id.keys() and keep_first / keep_last simultaneously + keep_first_cols = [col for col in keep_first if col not in event_id] + keep_last_cols = [col for col in keep_last if col not in event_id] + first_cols = [f"first_{col}" for col in keep_first_cols] + last_cols = [f"last_{col}" for col in keep_last_cols] + + columns = [ + "event_name", + *event_id.keys(), + *keep_first_cols, + *keep_last_cols, + *first_cols, + *last_cols, + ] + + data = np.empty((len(events_df), len(columns)), float) + metadata = pd.DataFrame(data=data, columns=columns, index=events_df.index) + + # Event names + metadata["event_name"] = "" + + # Event times + start_idx = 1 + stop_idx = start_idx + len(event_id.keys()) + len(keep_first_cols + keep_last_cols) + metadata.iloc[:, start_idx:stop_idx] = np.nan + + # keep_first and keep_last names + start_idx = stop_idx + metadata[columns[start_idx:]] = None + + # We're all set, let's iterate over all events and fill in in the + # respective cells in the metadata. We will subset this to include only + # `row_events` later + for row_event in events_df.itertuples(name="RowEvent"): + row_idx = row_event.Index + metadata.loc[row_idx, "event_name"] = id_to_name_map[row_event.id] + + # Determine which events fall into the current time window + if start_sample is None and isinstance(tmin, list): + # Lower bound is the current or the closest previous event with a name + # in "tmin"; if there is no such event (e.g., beginning of the recording is + # being approached), the upper lower becomes the last event in the + # recording. + prev_matching_events = events_df.loc[ + (events_df["sample"] <= row_event.sample) + & (events_df["id"].isin([event_id[name] for name in tmin])), + :, + ] + if prev_matching_events.size == 0: + # No earlier matching event. Use the current one as the beginning of the + # time window. This may occur at the beginning of a recording. + window_start_sample = row_event.sample + else: + # At least one earlier matching event. Use the closest one. + window_start_sample = prev_matching_events.iloc[-1]["sample"] + elif start_sample is None: + # Lower bound is the current event. + window_start_sample = row_event.sample + else: + # Lower bound is determined by tmin. + window_start_sample = row_event.sample + start_sample + + if stop_sample is None and isinstance(tmax, list): + # Upper bound is the current or the closest following event with a name + # in "tmax"; if there is no such event (e.g., end of the recording is being + # approached), the upper bound becomes the last event in the recording. + next_matching_events = events_df.loc[ + (events_df["sample"] >= row_event.sample) + & (events_df["id"].isin([event_id[name] for name in tmax])), + :, + ] + if next_matching_events.size == 0: + # No matching event after the current one; use the end of the recording + # as upper bound. This may occur at the end of a recording. + window_stop_sample = events_df["sample"].iloc[-1] + else: + # At least one matching later event. Use the closest one.. + window_stop_sample = next_matching_events.iloc[0]["sample"] + elif stop_sample is None: + # Upper bound: next event of the same type, or the last event (of + # any type) if no later event of the same type can be found. + next_events = events_df.loc[ + (events_df["sample"] > row_event.sample), + :, + ] + if next_events.size == 0: + # We've reached the last event in the recording. + window_stop_sample = row_event.sample + elif next_events.loc[next_events["id"] == row_event.id, :].size > 0: + # There's still an event of the same type appearing after the + # current event. Stop one sample short, we don't want to include that + # last event here, but in the next iteration. + window_stop_sample = ( + next_events.loc[next_events["id"] == row_event.id, :].iloc[0][ + "sample" + ] + - 1 + ) + else: + # There are still events after the current one, but not of the + # same type. + window_stop_sample = next_events.iloc[-1]["sample"] + else: + # Upper bound is determined by tmax. + window_stop_sample = row_event.sample + stop_sample + + events_in_window = events_df.loc[ + (events_df["sample"] >= window_start_sample) + & (events_df["sample"] <= window_stop_sample), + :, + ] + + assert not events_in_window.empty + + # Store the metadata + for event in events_in_window.itertuples(name="Event"): + event_sample = event.sample - row_event.sample + event_time = event_sample / sfreq + event_time = 0 if np.isclose(event_time, 0) else event_time + event_name = id_to_name_map[event.id] + + if not np.isnan(metadata.loc[row_idx, event_name]): + # Event already exists in current time window! + assert metadata.loc[row_idx, event_name] <= event_time + + if event_name not in keep_last: + continue + + metadata.loc[row_idx, event_name] = event_time + + # Handle keep_first and keep_last event aggregation + for event_group_name in keep_first + keep_last: + if event_name not in match_event_names(event_id, [event_group_name]): + continue + + if event_group_name in keep_first: + first_last_col = f"first_{event_group_name}" + else: + first_last_col = f"last_{event_group_name}" + + old_time = metadata.loc[row_idx, event_group_name] + if not np.isnan(old_time): + if (event_group_name in keep_first and old_time <= event_time) or ( + event_group_name in keep_last and old_time >= event_time + ): + continue + + if event_group_name not in event_id: + # This is an HED. Strip redundant information from the + # event name + name = ( + event_name.replace(event_group_name, "") + .replace("//", "/") + .strip("/") + ) + metadata.loc[row_idx, first_last_col] = name + del name + + metadata.loc[row_idx, event_group_name] = event_time + + # Only keep rows of interest + if row_events: + event_id_timelocked = { + name: val for name, val in event_id.items() if name in row_events + } + events = events[np.isin(events[:, 2], list(event_id_timelocked.values()))] + metadata = metadata.loc[metadata["event_name"].isin(event_id_timelocked)] + assert len(events) == len(metadata) + event_id = event_id_timelocked + + return metadata, events, event_id + + +def _events_from_annotations(raw, events, event_id, annotations, on_missing): + """Generate events and event_ids from annotations.""" + events, event_id_tmp = events_from_annotations(raw) + if events.size == 0: + raise RuntimeError( + "No usable annotations found in the raw object. " + "Either `events` must be provided or the raw " + "object must have annotations to construct epochs" + ) + if any(raw.annotations.duration > 0): + logger.info( + "Ignoring annotation durations and creating fixed-duration epochs " + "around annotation onsets." + ) + if event_id is None: + event_id = event_id_tmp + # if event_id is the names of events, map to events integers + if isinstance(event_id, str): + event_id = [event_id] + if isinstance(event_id, list | tuple | set): + if not set(event_id).issubset(set(event_id_tmp)): + msg = ( + "No matching annotations found for event_id(s) " + f"{set(event_id) - set(event_id_tmp)}" + ) + _on_missing(on_missing, msg) + # remove extras if on_missing not error + event_id = set(event_id) & set(event_id_tmp) + event_id = {my_id: event_id_tmp[my_id] for my_id in event_id} + # remove any non-selected annotations + annotations.delete(~np.isin(raw.annotations.description, list(event_id))) + return events, event_id, annotations + + +@fill_doc +class Epochs(BaseEpochs): + """Epochs extracted from a Raw instance. + + Parameters + ---------- + %(raw_epochs)s + + .. note:: + If ``raw`` contains annotations, ``Epochs`` can be constructed around + ``raw.annotations.onset``, but note that the durations of the annotations + are ignored in this case. + %(events_epochs)s + + .. versionchanged:: 1.7 + Allow ``events=None`` to use ``raw.annotations.onset`` as the source of + epoch times. + %(event_id)s + %(epochs_tmin_tmax)s + %(baseline_epochs)s + Defaults to ``(None, 0)``, i.e. beginning of the data until + time point zero. + %(picks_all)s + preload : bool + %(epochs_preload)s + %(reject_epochs)s + %(flat)s + %(proj_epochs)s + %(decim)s + %(epochs_reject_tmin_tmax)s + %(detrend_epochs)s + %(on_missing_epochs)s + %(reject_by_annotation_epochs)s + %(metadata_epochs)s + + .. versionadded:: 0.16 + %(event_repeated_epochs)s + %(verbose)s + + Attributes + ---------- + %(info_not_none)s + %(event_id_attr)s + ch_names : list of string + List of channel names. + %(selection_attr)s + preload : bool + Indicates whether epochs are in memory. + drop_log : tuple of tuple + A tuple of the same length as the event array used to initialize the + Epochs object. If the i-th original event is still part of the + selection, drop_log[i] will be an empty tuple; otherwise it will be + a tuple of the reasons the event is not longer in the selection, e.g.: + + - 'IGNORED' + If it isn't part of the current subset defined by the user + - 'NO_DATA' or 'TOO_SHORT' + If epoch didn't contain enough data names of channels that exceeded + the amplitude threshold + - 'EQUALIZED_COUNTS' + See :meth:`~mne.Epochs.equalize_event_counts` + - 'USER' + For user-defined reasons (see :meth:`~mne.Epochs.drop`). + + When dropping based on flat or reject parameters the tuple of + reasons contains a tuple of channels that satisfied the rejection + criteria. + filename : str + The filename of the object. + times : ndarray + Time vector in seconds. Goes from ``tmin`` to ``tmax``. Time interval + between consecutive time samples is equal to the inverse of the + sampling frequency. + + See Also + -------- + mne.epochs.combine_event_ids + mne.Epochs.equalize_event_counts + + Notes + ----- + When accessing data, Epochs are detrended, baseline-corrected, and + decimated, then projectors are (optionally) applied. + + For indexing and slicing using ``epochs[...]``, see + :meth:`mne.Epochs.__getitem__`. + + All methods for iteration over objects (using :meth:`mne.Epochs.__iter__`, + :meth:`mne.Epochs.iter_evoked` or :meth:`mne.Epochs.next`) use the same + internal state. + + If ``event_repeated`` is set to ``'merge'``, the coinciding events + (duplicates) will be merged into a single event_id and assigned a new + id_number as:: + + event_id['{event_id_1}/{event_id_2}/...'] = new_id_number + + For example with the event_id ``{'aud': 1, 'vis': 2}`` and the events + ``[[0, 0, 1], [0, 0, 2]]``, the "merge" behavior will update both event_id + and events to be: ``{'aud/vis': 3}`` and ``[[0, 0, 3]]`` respectively. + + There is limited support for :class:`~mne.Annotations` in the + :class:`~mne.Epochs` class. Currently annotations that are present in the + :class:`~mne.io.Raw` object will be preserved in the resulting + :class:`~mne.Epochs` object, but: + + 1. It is not yet possible to add annotations + to the Epochs object programmatically (via code) or interactively + (through the plot window) + 2. Concatenating :class:`~mne.Epochs` objects + that contain annotations is not supported, and any annotations will + be dropped when concatenating. + 3. Annotations will be lost on save. + """ + + @verbose + def __init__( + self, + raw, + events=None, + event_id=None, + tmin=-0.2, + tmax=0.5, + baseline=(None, 0), + picks=None, + preload=False, + reject=None, + flat=None, + proj=True, + decim=1, + reject_tmin=None, + reject_tmax=None, + detrend=None, + on_missing="raise", + reject_by_annotation=True, + metadata=None, + event_repeated="error", + verbose=None, + ): + from .io import BaseRaw + + if not isinstance(raw, BaseRaw): + raise ValueError( + "The first argument to `Epochs` must be an instance of mne.io.BaseRaw" + ) + info = deepcopy(raw.info) + annotations = raw.annotations.copy() + + # proj is on when applied in Raw + proj = proj or raw.proj + + self.reject_by_annotation = reject_by_annotation + + # keep track of original sfreq (needed for annotations) + raw_sfreq = raw.info["sfreq"] + + # get events from annotations if no events given + if events is None: + events, event_id, annotations = _events_from_annotations( + raw, events, event_id, annotations, on_missing + ) + + # add the annotations.extras to the metadata + if not all(len(d) == 0 for d in annotations.extras): + pd = _check_pandas_installed(strict=True) + extras_df = pd.DataFrame(annotations.extras) + if metadata is None: + metadata = extras_df + else: + extras_df.set_index(metadata.index, inplace=True) + metadata = pd.concat( + [metadata, extras_df], axis=1, ignore_index=False + ) + + # call BaseEpochs constructor + super().__init__( + info, + None, + events, + event_id, + tmin, + tmax, + metadata=metadata, + baseline=baseline, + raw=raw, + picks=picks, + reject=reject, + flat=flat, + decim=decim, + reject_tmin=reject_tmin, + reject_tmax=reject_tmax, + detrend=detrend, + proj=proj, + on_missing=on_missing, + preload_at_end=preload, + event_repeated=event_repeated, + verbose=verbose, + raw_sfreq=raw_sfreq, + annotations=annotations, + ) + + @verbose + def _get_epoch_from_raw(self, idx, verbose=None): + """Load one epoch from disk. + + Returns + ------- + data : array | str | None + If string, it's details on rejection reason. + If array, it's the data in the desired range (good segment) + If None, it means no data is available. + """ + if self._raw is None: + # This should never happen, as raw=None only if preload=True + raise ValueError( + "An error has occurred, no valid raw file found. " + "Please report this to the mne-python " + "developers." + ) + sfreq = self._raw.info["sfreq"] + event_samp = self.events[idx, 0] + # Read a data segment from "start" to "stop" in samples + first_samp = self._raw.first_samp + start = int(round(event_samp + self._raw_times[0] * sfreq)) + start -= first_samp + stop = start + len(self._raw_times) + + # reject_tmin, and reject_tmax need to be converted to samples to + # check the reject_by_annotation boundaries: reject_start, reject_stop + reject_tmin = self.reject_tmin + if reject_tmin is None: + reject_tmin = self._raw_times[0] + reject_start = int(round(event_samp + reject_tmin * sfreq)) + reject_start -= first_samp + + reject_tmax = self.reject_tmax + if reject_tmax is None: + reject_tmax = self._raw_times[-1] + diff = int(round((self._raw_times[-1] - reject_tmax) * sfreq)) + reject_stop = stop - diff + + logger.debug(f" Getting epoch for {start}-{stop}") + data = self._raw._check_bad_segment( + start, + stop, + self.picks, + reject_start, + reject_stop, + self.reject_by_annotation, + ) + return data + + +@fill_doc +class EpochsArray(BaseEpochs): + """Epochs object from numpy array. + + Parameters + ---------- + data : array, shape (n_epochs, n_channels, n_times) + The channels' time series for each epoch. See notes for proper units of + measure. + %(info_not_none)s Consider using :func:`mne.create_info` to populate this + structure. + %(events_epochs)s + %(tmin_epochs)s + %(event_id)s + %(reject_epochs)s + %(flat)s + %(epochs_reject_tmin_tmax)s + %(baseline_epochs)s + Defaults to ``None``, i.e. no baseline correction. + %(proj_epochs)s + %(on_missing_epochs)s + %(metadata_epochs)s + + .. versionadded:: 0.16 + %(selection)s + %(drop_log)s + + .. versionadded:: 1.3 + %(raw_sfreq)s + + .. versionadded:: 1.3 + %(verbose)s + + See Also + -------- + create_info + EvokedArray + io.RawArray + + Notes + ----- + Proper units of measure: + + * V: eeg, eog, seeg, dbs, emg, ecg, bio, ecog + * T: mag + * T/m: grad + * M: hbo, hbr + * Am: dipole + * AU: misc + + EpochsArray does not set `Annotations`. If you would like to create + simulated data with Annotations that are then preserved in the Epochs + object, you would use `mne.io.RawArray` first and then create an + `mne.Epochs` object. + """ + + @verbose + def __init__( + self, + data, + info, + events=None, + tmin=0.0, + event_id=None, + reject=None, + flat=None, + reject_tmin=None, + reject_tmax=None, + baseline=None, + proj=True, + on_missing="raise", + metadata=None, + selection=None, + *, + drop_log=None, + raw_sfreq=None, + verbose=None, + ): + dtype = np.complex128 if np.any(np.iscomplex(data)) else np.float64 + data = np.asanyarray(data, dtype=dtype) + if data.ndim != 3: + raise ValueError( + "Data must be a 3D array of shape (n_epochs, n_channels, n_samples)" + ) + + if len(info["ch_names"]) != data.shape[1]: + raise ValueError("Info and data must have same number of channels.") + if events is None: + n_epochs = len(data) + events = _gen_events(n_epochs) + info = info.copy() # do not modify original info + tmax = (data.shape[2] - 1) / info["sfreq"] + tmin + + super().__init__( + info, + data, + events, + event_id, + tmin, + tmax, + baseline, + reject=reject, + flat=flat, + reject_tmin=reject_tmin, + reject_tmax=reject_tmax, + decim=1, + metadata=metadata, + selection=selection, + proj=proj, + on_missing=on_missing, + drop_log=drop_log, + raw_sfreq=raw_sfreq, + verbose=verbose, + ) + if self.baseline is not None: + self._do_baseline = True + if ( + len(events) + != np.isin(self.events[:, 2], list(self.event_id.values())).sum() + ): + raise ValueError("The events must only contain event numbers from event_id") + detrend_picks = self._detrend_picks + for e in self._data: + # This is safe without assignment b/c there is no decim + self._detrend_offset_decim(e, detrend_picks) + self.drop_bad() + + +def combine_event_ids(epochs, old_event_ids, new_event_id, copy=True): + """Collapse event_ids from an epochs instance into a new event_id. + + Parameters + ---------- + epochs : instance of Epochs + The epochs to operate on. + old_event_ids : str, or list + Conditions to collapse together. + new_event_id : dict, or int + A one-element dict (or a single integer) for the new + condition. Note that for safety, this cannot be any + existing id (in epochs.event_id.values()). + copy : bool + Whether to return a new instance or modify in place. + + Returns + ------- + epochs : instance of Epochs + The modified epochs. + + Notes + ----- + This For example (if epochs.event_id was ``{'Left': 1, 'Right': 2}``:: + + combine_event_ids(epochs, ['Left', 'Right'], {'Directional': 12}) + + would create a 'Directional' entry in epochs.event_id replacing + 'Left' and 'Right' (combining their trials). + """ + epochs = epochs.copy() if copy else epochs + old_event_ids = np.asanyarray(old_event_ids) + if isinstance(new_event_id, int): + new_event_id = {str(new_event_id): new_event_id} + else: + if not isinstance(new_event_id, dict): + raise ValueError("new_event_id must be a dict or int") + if not len(list(new_event_id.keys())) == 1: + raise ValueError("new_event_id dict must have one entry") + new_event_num = list(new_event_id.values())[0] + new_event_num = operator.index(new_event_num) + if new_event_num in epochs.event_id.values(): + raise ValueError("new_event_id value must not already exist") + # could use .pop() here, but if a latter one doesn't exist, we're + # in trouble, so run them all here and pop() later + old_event_nums = np.array([epochs.event_id[key] for key in old_event_ids]) + # find the ones to replace + inds = np.any( + epochs.events[:, 2][:, np.newaxis] == old_event_nums[np.newaxis, :], axis=1 + ) + # replace the event numbers in the events list + epochs.events[inds, 2] = new_event_num + # delete old entries + for key in old_event_ids: + epochs.event_id.pop(key) + # add the new entry + epochs.event_id.update(new_event_id) + return epochs + + +@fill_doc +def equalize_epoch_counts(epochs_list, method="mintime", *, random_state=None): + """Equalize the number of trials in multiple Epochs or EpochsTFR instances. + + Parameters + ---------- + epochs_list : list of Epochs instances + The Epochs instances to equalize trial counts for. + %(equalize_events_method)s + %(random_state)s Used only if ``method='random'``. + + Notes + ----- + The method ``'mintime'`` tries to make the remaining epochs occurring as close as + possible in time. This method is motivated by the possibility that if there happened + to be some time-varying (like on the scale of minutes) noise characteristics during + a recording, they could be compensated for (to some extent) in the + equalization process. This method thus seeks to reduce any of those effects + by minimizing the differences in the times of the events in the two sets of + epochs. For example, if one had event times [1, 2, 3, 4, 120, 121] and the + other one had [3.5, 4.5, 120.5, 121.5], it would remove events at times + [1, 2] in the first epochs and not [120, 121]. + + Examples + -------- + >>> equalize_epoch_counts([epochs1, epochs2]) # doctest: +SKIP + """ + if not all(isinstance(epoch, BaseEpochs | EpochsTFR) for epoch in epochs_list): + raise ValueError("All inputs must be Epochs instances") + # make sure bad epochs are dropped + for epoch in epochs_list: + if not epoch._bad_dropped: + epoch.drop_bad() + sample_nums = [epoch.events[:, 0] for epoch in epochs_list] + indices = _get_drop_indices(sample_nums, method, random_state) + for epoch, inds in zip(epochs_list, indices): + epoch.drop(inds, reason="EQUALIZED_COUNT") + + +def _get_drop_indices(sample_nums, method, random_state): + """Get indices to drop from multiple event timing lists.""" + small_idx = np.argmin([e.size for e in sample_nums]) + small_epoch_indices = sample_nums[small_idx] + _check_option("method", method, ["mintime", "truncate", "random"]) + indices = list() + for event in sample_nums: + if method == "mintime": + mask = _minimize_time_diff(small_epoch_indices, event) + elif method == "truncate": + mask = np.ones(event.size, dtype=bool) + mask[small_epoch_indices.size :] = False + elif method == "random": + rng = check_random_state(random_state) + mask = np.zeros(event.size, dtype=bool) + idx = rng.choice( + np.arange(event.size), size=small_epoch_indices.size, replace=False + ) + mask[idx] = True + indices.append(np.where(np.logical_not(mask))[0]) + return indices + + +def _minimize_time_diff(t_shorter, t_longer): + """Find a boolean mask to minimize timing differences.""" + keep = np.ones((len(t_longer)), dtype=bool) + # special case: length zero or one + if len(t_shorter) < 2: # interp1d won't work + keep.fill(False) + if len(t_shorter) == 1: + idx = np.argmin(np.abs(t_longer - t_shorter)) + keep[idx] = True + return keep + scores = np.ones(len(t_longer)) + x1 = np.arange(len(t_shorter)) + # The first set of keep masks to test + kwargs = dict(copy=False, bounds_error=False, assume_sorted=True) + shorter_interp = interp1d(x1, t_shorter, fill_value=t_shorter[-1], **kwargs) + for ii in range(len(t_longer) - len(t_shorter)): + scores.fill(np.inf) + # set up the keep masks to test, eliminating any rows that are already + # gone + keep_mask = ~np.eye(len(t_longer), dtype=bool)[keep] + keep_mask[:, ~keep] = False + # Check every possible removal to see if it minimizes + x2 = np.arange(len(t_longer) - ii - 1) + t_keeps = np.array([t_longer[km] for km in keep_mask]) + longer_interp = interp1d( + x2, t_keeps, axis=1, fill_value=t_keeps[:, -1], **kwargs + ) + d1 = longer_interp(x1) - t_shorter + d2 = shorter_interp(x2) - t_keeps + scores[keep] = np.abs(d1, d1).sum(axis=1) + np.abs(d2, d2).sum(axis=1) + keep[np.argmin(scores)] = False + return keep + + +@verbose +def _is_good( + e, + ch_names, + channel_type_idx, + reject, + flat, + full_report=False, + ignore_chs=(), + verbose=None, +): + """Test if data segment e is good according to reject and flat. + + The reject and flat parameters can accept functions as values. + + If full_report=True, it will give True/False as well as a list of all + offending channels. + """ + bad_tuple = tuple() + has_printed = False + checkable = np.ones(len(ch_names), dtype=bool) + checkable[np.array([c in ignore_chs for c in ch_names], dtype=bool)] = False + + for refl, f, t in zip([reject, flat], [np.greater, np.less], ["", "flat"]): + if refl is not None: + for key, refl in refl.items(): + criterion = refl + idx = channel_type_idx[key] + name = key.upper() + if len(idx) > 0: + e_idx = e[idx] + checkable_idx = checkable[idx] + # Check if criterion is a function and apply it + if callable(criterion): + result = criterion(e_idx) + _validate_type(result, tuple, "reject/flat output") + if len(result) != 2: + raise TypeError( + "Function criterion must return a tuple of length 2" + ) + cri_truth, reasons = result + _validate_type(cri_truth, (bool, np.bool_), cri_truth, "bool") + _validate_type( + reasons, (str, list, tuple), reasons, "str, list, or tuple" + ) + idx_deltas = np.where(np.logical_and(cri_truth, checkable_idx))[ + 0 + ] + else: + deltas = np.max(e_idx, axis=1) - np.min(e_idx, axis=1) + idx_deltas = np.where( + np.logical_and(f(deltas, criterion), checkable_idx) + )[0] + + if len(idx_deltas) > 0: + # Check to verify that refl is a callable that returns + # (bool, reason). Reason must be a str/list/tuple. + # If using tuple + if callable(refl): + if isinstance(reasons, str): + reasons = (reasons,) + for idx, reason in enumerate(reasons): + _validate_type(reason, str, reason) + bad_tuple += tuple(reasons) + else: + bad_names = [ch_names[idx[i]] for i in idx_deltas] + if not has_printed: + logger.info( + f" Rejecting {t} epoch based on {name} : " + f"{bad_names}" + ) + has_printed = True + if not full_report: + return False + else: + bad_tuple += tuple(bad_names) + + if not full_report: + return True + else: + if bad_tuple == (): + return True, None + else: + return False, bad_tuple + + +def _read_one_epoch_file(f, tree, preload): + """Read a single FIF file.""" + with f as fid: + # Read the measurement info + info, meas = read_meas_info(fid, tree, clean_bads=True) + + # read in the Annotations if they exist + annotations = _read_annotations_fif(fid, tree) + try: + events, mappings = _read_events_fif(fid, tree) + except ValueError as e: + # Allow reading empty epochs (ToDo: Maybe not anymore in the future) + if str(e) == "Could not find any events": + events = np.empty((0, 3), dtype=np.int32) + mappings = dict() + else: + raise + # Metadata + metadata = None + metadata_tree = dir_tree_find(tree, FIFF.FIFFB_MNE_METADATA) + if len(metadata_tree) > 0: + for dd in metadata_tree[0]["directory"]: + kind = dd.kind + pos = dd.pos + if kind == FIFF.FIFF_DESCRIPTION: + metadata = read_tag(fid, pos).data + metadata = _prepare_read_metadata(metadata) + break + + # Locate the data of interest + processed = dir_tree_find(meas, FIFF.FIFFB_PROCESSED_DATA) + del meas + if len(processed) == 0: + raise ValueError("Could not find processed data") + + epochs_node = dir_tree_find(tree, FIFF.FIFFB_MNE_EPOCHS) + if len(epochs_node) == 0: + # before version 0.11 we errantly saved with this tag instead of + # an MNE tag + epochs_node = dir_tree_find(tree, FIFF.FIFFB_MNE_EPOCHS) + if len(epochs_node) == 0: + epochs_node = dir_tree_find(tree, 122) # 122 used before v0.11 + if len(epochs_node) == 0: + raise ValueError("Could not find epochs data") + + my_epochs = epochs_node[0] + + # Now find the data in the block + data = None + data_tag = None + bmin, bmax = None, None + baseline = None + selection = None + drop_log = None + raw_sfreq = None + reject_params = {} + for k in range(my_epochs["nent"]): + kind = my_epochs["directory"][k].kind + pos = my_epochs["directory"][k].pos + if kind == FIFF.FIFF_FIRST_SAMPLE: + tag = read_tag(fid, pos) + first = int(tag.data.item()) + elif kind == FIFF.FIFF_LAST_SAMPLE: + tag = read_tag(fid, pos) + last = int(tag.data.item()) + elif kind == FIFF.FIFF_EPOCH: + # delay reading until later + fid.seek(pos, 0) + data_tag = _read_tag_header(fid, pos) + data_tag.type = data_tag.type ^ (1 << 30) + elif kind in [FIFF.FIFF_MNE_BASELINE_MIN, 304]: + # Constant 304 was used before v0.11 + tag = read_tag(fid, pos) + bmin = float(tag.data.item()) + elif kind in [FIFF.FIFF_MNE_BASELINE_MAX, 305]: + # Constant 305 was used before v0.11 + tag = read_tag(fid, pos) + bmax = float(tag.data.item()) + elif kind == FIFF.FIFF_MNE_EPOCHS_SELECTION: + tag = read_tag(fid, pos) + selection = np.array(tag.data) + elif kind == FIFF.FIFF_MNE_EPOCHS_DROP_LOG: + tag = read_tag(fid, pos) + drop_log = tag.data + drop_log = json.loads(drop_log) + drop_log = tuple(tuple(x) for x in drop_log) + elif kind == FIFF.FIFF_MNE_EPOCHS_REJECT_FLAT: + tag = read_tag(fid, pos) + reject_params = json.loads(tag.data) + elif kind == FIFF.FIFF_MNE_EPOCHS_RAW_SFREQ: + tag = read_tag(fid, pos) + raw_sfreq = tag.data + + if bmin is not None or bmax is not None: + baseline = (bmin, bmax) + + n_samp = last - first + 1 + logger.info(" Found the data of interest:") + logger.info( + f" t = {1000 * first / info['sfreq']:10.2f} ... " + f"{1000 * last / info['sfreq']:10.2f} ms" + ) + if info["comps"] is not None: + logger.info( + f" {len(info['comps'])} CTF compensation matrices available" + ) + + # Inspect the data + if data_tag is None: + raise ValueError("Epochs data not found") + epoch_shape = (len(info["ch_names"]), n_samp) + size_expected = len(events) * np.prod(epoch_shape) + # on read double-precision is always used + if data_tag.type == FIFF.FIFFT_FLOAT: + datatype = np.float64 + fmt = ">f4" + elif data_tag.type == FIFF.FIFFT_DOUBLE: + datatype = np.float64 + fmt = ">f8" + elif data_tag.type == FIFF.FIFFT_COMPLEX_FLOAT: + datatype = np.complex128 + fmt = ">c8" + elif data_tag.type == FIFF.FIFFT_COMPLEX_DOUBLE: + datatype = np.complex128 + fmt = ">c16" + fmt_itemsize = np.dtype(fmt).itemsize + assert fmt_itemsize in (4, 8, 16) + size_actual = data_tag.size // fmt_itemsize - 16 // fmt_itemsize + + if not size_actual == size_expected: + raise ValueError( + f"Incorrect number of samples ({size_actual} instead of " + f"{size_expected})." + ) + + # Calibration factors + cals = np.array( + [ + [info["chs"][k]["cal"] * info["chs"][k].get("scale", 1.0)] + for k in range(info["nchan"]) + ], + np.float64, + ) + + # Read the data + if preload: + data = read_tag(fid, data_tag.pos).data.astype(datatype) + data *= cals + + # Put it all together + tmin = first / info["sfreq"] + tmax = last / info["sfreq"] + event_id = ( + {str(e): e for e in np.unique(events[:, 2])} + if mappings is None + else mappings + ) + # In case epochs didn't have a FIFF.FIFF_MNE_EPOCHS_SELECTION tag + # (version < 0.8): + if selection is None: + selection = np.arange(len(events)) + if drop_log is None: + drop_log = ((),) * len(events) + + return ( + info, + data, + data_tag, + events, + event_id, + metadata, + tmin, + tmax, + baseline, + selection, + drop_log, + epoch_shape, + cals, + reject_params, + fmt, + annotations, + raw_sfreq, + ) + + +@verbose +def read_epochs(fname, proj=True, preload=True, verbose=None) -> "EpochsFIF": + """Read epochs from a fif file. + + Parameters + ---------- + %(fname_epochs)s + %(proj_epochs)s + preload : bool + If True, read all epochs from disk immediately. If ``False``, epochs + will be read on demand. + %(verbose)s + + Returns + ------- + epochs : instance of Epochs + The epochs. + """ + return EpochsFIF(fname, proj, preload, verbose) + + +class _RawContainer: + """Helper for a raw data container.""" + + def __init__(self, fid, data_tag, event_samps, epoch_shape, cals, fmt): + self.fid = fid + self.data_tag = data_tag + self.event_samps = event_samps + self.epoch_shape = epoch_shape + self.cals = cals + self.proj = False + self.fmt = fmt + + def __del__(self): # noqa: D105 + self.fid.close() + + +@fill_doc +class EpochsFIF(BaseEpochs): + """Epochs read from disk. + + Parameters + ---------- + %(fname_epochs)s + %(proj_epochs)s + preload : bool + If True, read all epochs from disk immediately. If False, epochs will + be read on demand. + %(verbose)s + + See Also + -------- + mne.Epochs + mne.epochs.combine_event_ids + mne.Epochs.equalize_event_counts + """ + + @verbose + def __init__(self, fname, proj=True, preload=True, verbose=None): + from .io.base import _get_fname_rep + + if _path_like(fname): + check_fname( + fname=fname, + filetype="epochs", + endings=("-epo.fif", "-epo.fif.gz", "_epo.fif", "_epo.fif.gz"), + ) + fname = _check_fname(fname=fname, must_exist=True, overwrite="read") + elif not preload: + raise ValueError("preload must be used with file-like objects") + + fnames = [fname] + fname_rep = _get_fname_rep(fname) + ep_list = list() + raw = list() + for fname in fnames: + logger.info(f"Reading {fname_rep} ...") + fid, tree, _ = fiff_open(fname, preload=preload) + next_fname = _get_next_fname(fid, fname, tree) + ( + info, + data, + data_tag, + events, + event_id, + metadata, + tmin, + tmax, + baseline, + selection, + drop_log, + epoch_shape, + cals, + reject_params, + fmt, + annotations, + raw_sfreq, + ) = _read_one_epoch_file(fid, tree, preload) + + if (events[:, 0] < 0).any(): + events = events.copy() + warn( + "Incorrect events detected on disk, setting event " + "numbers to consecutive increasing integers" + ) + events[:, 0] = np.arange(1, len(events) + 1) + # here we ignore missing events, since users should already be + # aware of missing events if they have saved data that way + # we also retain original baseline without re-applying baseline + # correction (data is being baseline-corrected when written to + # disk) + epoch = BaseEpochs( + info, + data, + events, + event_id, + tmin, + tmax, + baseline=None, + metadata=metadata, + on_missing="ignore", + selection=selection, + drop_log=drop_log, + proj=False, + verbose=False, + raw_sfreq=raw_sfreq, + ) + epoch.baseline = baseline + epoch._do_baseline = False # might be superfluous but won't hurt + ep_list.append(epoch) + + if not preload: + # store everything we need to index back to the original data + raw.append( + _RawContainer( + fiff_open(fname)[0], + data_tag, + events[:, 0].copy(), + epoch_shape, + cals, + fmt, + ) + ) + + if next_fname is not None: + fnames.append(next_fname) + + unsafe_annot_add = raw_sfreq is None + ( + info, + data, + raw_sfreq, + events, + event_id, + tmin, + tmax, + metadata, + baseline, + selection, + drop_log, + ) = _concatenate_epochs( + ep_list, + with_data=preload, + add_offset=False, + on_mismatch="raise", + ) + # we need this uniqueness for non-preloaded data to work properly + if len(np.unique(events[:, 0])) != len(events): + raise RuntimeError("Event time samples were not unique") + + # correct the drop log + assert len(drop_log) % len(fnames) == 0 + step = len(drop_log) // len(fnames) + offsets = np.arange(step, len(drop_log) + 1, step) + drop_log = list(drop_log) + for i1, i2 in zip(offsets[:-1], offsets[1:]): + other_log = drop_log[i1:i2] + for k, (a, b) in enumerate(zip(drop_log, other_log)): + if a == ("IGNORED",) and b != ("IGNORED",): + drop_log[k] = b + drop_log = tuple(drop_log[:step]) + + # call BaseEpochs constructor + # again, ensure we're retaining the baseline period originally loaded + # from disk without trying to re-apply baseline correction + super().__init__( + info, + data, + events, + event_id, + tmin, + tmax, + baseline=None, + raw=raw, + proj=proj, + preload_at_end=False, + on_missing="ignore", + selection=selection, + drop_log=drop_log, + filename=fname_rep, + metadata=metadata, + verbose=verbose, + raw_sfreq=raw_sfreq, + annotations=annotations, + **reject_params, + ) + self.baseline = baseline + self._do_baseline = False + # use the private property instead of drop_bad so that epochs + # are not all read from disk for preload=False + self._bad_dropped = True + # private property to suggest that people re-save epochs if they add + # annotations + self._unsafe_annot_add = unsafe_annot_add + + @verbose + def _get_epoch_from_raw(self, idx, verbose=None): + """Load one epoch from disk.""" + # Find the right file and offset to use + event_samp = self.events[idx, 0] + for raw in self._raw: + idx = np.where(raw.event_samps == event_samp)[0] + if len(idx) == 1: + fmt = raw.fmt + idx = idx[0] + size = np.prod(raw.epoch_shape) * np.dtype(fmt).itemsize + offset = idx * size + 16 # 16 = Tag header + break + else: + # read the correct subset of the data + raise RuntimeError( + "Correct epoch could not be found, please contact mne-python developers" + ) + # the following is equivalent to this, but faster: + # + # >>> data = read_tag(raw.fid, raw.data_tag.pos).data.astype(float) + # >>> data *= raw.cals[np.newaxis, :, :] + # >>> data = data[idx] + # + # Eventually this could be refactored in io/tag.py if other functions + # could make use of it + raw.fid.seek(raw.data_tag.pos + offset, 0) + if fmt == ">c8": + read_fmt = ">f4" + elif fmt == ">c16": + read_fmt = ">f8" + else: + read_fmt = fmt + data = np.frombuffer(raw.fid.read(size), read_fmt) + if read_fmt != fmt: + data = data.view(fmt) + data = data.astype(np.complex128) + else: + data = data.astype(np.float64) + + data = _reshape_view(data, raw.epoch_shape) + data *= raw.cals + return data + + +@fill_doc +def bootstrap(epochs, random_state=None): + """Compute epochs selected by bootstrapping. + + Parameters + ---------- + epochs : Epochs instance + epochs data to be bootstrapped + %(random_state)s + + Returns + ------- + epochs : Epochs instance + The bootstrap samples + """ + if not epochs.preload: + raise RuntimeError( + "Modifying data of epochs is only supported " + "when preloading is used. Use preload=True " + "in the constructor." + ) + + rng = check_random_state(random_state) + epochs_bootstrap = epochs.copy() + n_events = len(epochs_bootstrap.events) + idx = rng_uniform(rng)(0, n_events, n_events) + epochs_bootstrap = epochs_bootstrap[idx] + return epochs_bootstrap + + +def _concatenate_epochs( + epochs_list, *, with_data=True, add_offset=True, on_mismatch="raise" +): + """Auxiliary function for concatenating epochs.""" + if not isinstance(epochs_list, list | tuple): + raise TypeError(f"epochs_list must be a list or tuple, got {type(epochs_list)}") + + # to make warning messages only occur once during concatenation + warned = False + + for ei, epochs in enumerate(epochs_list): + if not isinstance(epochs, BaseEpochs): + raise TypeError( + f"epochs_list[{ei}] must be an instance of Epochs, got {type(epochs)}" + ) + + if ( + getattr(epochs, "annotations", None) is not None + and len(epochs.annotations) > 0 + and not warned + ): + warned = True + warn( + "Concatenation of Annotations within Epochs is not supported yet. All " + "annotations will be dropped." + ) + + # create a copy, so that the Annotations are not modified in place + # from the original object + epochs = epochs.copy() + epochs.set_annotations(None) + out = epochs_list[0] + offsets = [0] + if with_data: + out.drop_bad() + offsets.append(len(out)) + events = [out.events] + metadata = [out.metadata] + baseline, tmin, tmax = out.baseline, out.tmin, out.tmax + raw_sfreq = out._raw_sfreq + info = deepcopy(out.info) + drop_log = out.drop_log + event_id = deepcopy(out.event_id) + selection = out.selection + # offset is the last epoch + tmax + 10 second + shift = np.int64((10 + tmax) * out.info["sfreq"]) + # Allow reading empty epochs (ToDo: Maybe not anymore in the future) + if out._allow_empty: + events_offset = 0 + else: + events_offset = int(np.max(events[0][:, 0])) + shift + events_offset = np.int64(events_offset) + events_overflow = False + warned = False + for ii, epochs in enumerate(epochs_list[1:], 1): + _ensure_infos_match(epochs.info, info, f"epochs[{ii}]", on_mismatch=on_mismatch) + if not np.allclose(epochs.times, epochs_list[0].times): + raise ValueError("Epochs must have same times") + + if epochs.baseline != baseline: + raise ValueError("Baseline must be same for all epochs") + + if epochs._raw_sfreq != raw_sfreq and not warned: + warned = True + warn( + "The original raw sampling rate of the Epochs does not " + "match for all Epochs. Please proceed cautiously." + ) + + # compare event_id + common_keys = list(set(event_id).intersection(set(epochs.event_id))) + for key in common_keys: + if not event_id[key] == epochs.event_id[key]: + msg = ( + "event_id values must be the same for identical keys " + 'for all concatenated epochs. Key "{}" maps to {} in ' + "some epochs and to {} in others." + ) + raise ValueError(msg.format(key, event_id[key], epochs.event_id[key])) + + if with_data: + epochs.drop_bad() + offsets.append(len(epochs)) + evs = epochs.events.copy() + if len(epochs.events) == 0: + warn("One of the Epochs objects to concatenate was empty.") + elif add_offset: + # We need to cast to a native Python int here to detect an + # overflow of a numpy int32 (which is the default on windows) + max_timestamp = int(np.max(evs[:, 0])) + evs[:, 0] += events_offset + events_offset += max_timestamp + shift + if events_offset > INT32_MAX: + warn( + f"Event number greater than {INT32_MAX} created, " + "events[:, 0] will be assigned consecutive increasing " + "integer values" + ) + events_overflow = True + add_offset = False # we no longer need to add offset + events.append(evs) + selection = np.concatenate((selection, epochs.selection)) + drop_log = drop_log + epochs.drop_log + event_id.update(epochs.event_id) + metadata.append(epochs.metadata) + events = np.concatenate(events, axis=0) + # check to see if we exceeded our maximum event offset + if events_overflow: + events[:, 0] = np.arange(1, len(events) + 1) + + # Create metadata object (or make it None) + n_have = sum(this_meta is not None for this_meta in metadata) + if n_have == 0: + metadata = None + elif n_have != len(metadata): + raise ValueError( + f"{n_have} of {len(metadata)} epochs instances have metadata, either " + "all or none must have metadata" + ) + else: + pd = _check_pandas_installed(strict=False) + if pd is not False: + metadata = pd.concat(metadata) + else: # dict of dicts + metadata = sum(metadata, list()) + assert len(offsets) == (len(epochs_list) if with_data else 0) + 1 + data = None + if with_data: + offsets = np.cumsum(offsets) + for start, stop, epochs in zip(offsets[:-1], offsets[1:], epochs_list): + this_data = epochs.get_data(copy=False) + if data is None: + data = np.empty( + (offsets[-1], len(out.ch_names), len(out.times)), + dtype=this_data.dtype, + ) + data[start:stop] = this_data + return ( + info, + data, + raw_sfreq, + events, + event_id, + tmin, + tmax, + metadata, + baseline, + selection, + drop_log, + ) + + +@verbose +def concatenate_epochs( + epochs_list, add_offset=True, *, on_mismatch="raise", verbose=None +): + """Concatenate a list of `~mne.Epochs` into one `~mne.Epochs` object. + + .. note:: Unlike `~mne.concatenate_raws`, this function does **not** + modify any of the input data. + + Parameters + ---------- + epochs_list : list + List of `~mne.Epochs` instances to concatenate (in that order). + add_offset : bool + If True, a fixed offset is added to the event times from different + Epochs sets, such that they are easy to distinguish after the + concatenation. + If False, the event times are unaltered during the concatenation. + %(on_mismatch_info)s + %(verbose)s + + .. versionadded:: 0.24 + + Returns + ------- + epochs : instance of EpochsArray + The result of the concatenation. All data will be loaded into memory. + + Notes + ----- + .. versionadded:: 0.9.0 + """ + ( + info, + data, + raw_sfreq, + events, + event_id, + tmin, + tmax, + metadata, + baseline, + selection, + drop_log, + ) = _concatenate_epochs( + epochs_list, + with_data=True, + add_offset=add_offset, + on_mismatch=on_mismatch, + ) + selection = np.where([len(d) == 0 for d in drop_log])[0] + out = EpochsArray( + data=data, + info=info, + events=events, + event_id=event_id, + tmin=tmin, + baseline=baseline, + selection=selection, + drop_log=drop_log, + proj=False, + on_missing="ignore", + metadata=metadata, + raw_sfreq=raw_sfreq, + ) + out.drop_bad() + return out + + +@verbose +def average_movements( + epochs, + head_pos=None, + orig_sfreq=None, + picks=None, + origin="auto", + weight_all=True, + int_order=8, + ext_order=3, + destination=None, + ignore_ref=False, + return_mapping=False, + mag_scale=100.0, + verbose=None, +): + """Average data using Maxwell filtering, transforming using head positions. + + Parameters + ---------- + epochs : instance of Epochs + The epochs to operate on. + %(head_pos_maxwell)s + orig_sfreq : float | None + The original sample frequency of the data (that matches the + event sample numbers in ``epochs.events``). Can be ``None`` + if data have not been decimated or resampled. + %(picks_all_data)s + %(origin_maxwell)s + weight_all : bool + If True, all channels are weighted by the SSS basis weights. + If False, only MEG channels are weighted, other channels + receive uniform weight per epoch. + %(int_order_maxwell)s + %(ext_order_maxwell)s + %(destination_maxwell_dest)s + %(ignore_ref_maxwell)s + return_mapping : bool + If True, return the mapping matrix. + %(mag_scale_maxwell)s + + .. versionadded:: 0.13 + %(verbose)s + + Returns + ------- + evoked : instance of Evoked + The averaged epochs. + + See Also + -------- + mne.preprocessing.maxwell_filter + mne.chpi.read_head_pos + + Notes + ----- + The Maxwell filtering version of this algorithm is described in [1]_, + in section V.B "Virtual signals and movement correction", equations + 40-44. For additional validation, see [2]_. + + Regularization has not been added because in testing it appears to + decrease dipole localization accuracy relative to using all components. + Fine calibration and cross-talk cancellation, however, could be added + to this algorithm based on user demand. + + .. versionadded:: 0.11 + + References + ---------- + .. [1] Taulu S. and Kajola M. "Presentation of electromagnetic + multichannel data: The signal space separation method," + Journal of Applied Physics, vol. 97, pp. 124905 1-10, 2005. + .. [2] Wehner DT, Hämäläinen MS, Mody M, Ahlfors SP. "Head movements + of children in MEG: Quantification, effects on source + estimation, and compensation. NeuroImage 40:541–550, 2008. + """ # noqa: E501 + from .preprocessing.maxwell import ( + _check_destination, + _check_usable, + _col_norm_pinv, + _get_coil_scale, + _get_mf_picks_fix_mags, + _get_n_moments, + _get_sensor_operator, + _prep_mf_coils, + _remove_meg_projs_comps, + _reset_meg_bads, + _trans_sss_basis, + ) + + if head_pos is None: + raise TypeError("head_pos must be provided and cannot be None") + from .chpi import head_pos_to_trans_rot_t + + if not isinstance(epochs, BaseEpochs): + raise TypeError(f"epochs must be an instance of Epochs, not {type(epochs)}") + orig_sfreq = epochs.info["sfreq"] if orig_sfreq is None else orig_sfreq + orig_sfreq = float(orig_sfreq) + if isinstance(head_pos, np.ndarray): + head_pos = head_pos_to_trans_rot_t(head_pos) + trn, rot, t = head_pos + del head_pos + _check_usable(epochs, ignore_ref) + origin = _check_origin(origin, epochs.info, "head") + recon_trans = _check_destination(destination, epochs.info, "head") + + logger.info(f"Aligning and averaging up to {len(epochs.events)} epochs") + if not np.array_equal(epochs.events[:, 0], np.unique(epochs.events[:, 0])): + raise RuntimeError("Epochs must have monotonically increasing events") + info_to = epochs.info.copy() + meg_picks, mag_picks, grad_picks, good_mask, _ = _get_mf_picks_fix_mags( + info_to, int_order, ext_order, ignore_ref + ) + coil_scale, mag_scale = _get_coil_scale( + meg_picks, mag_picks, grad_picks, mag_scale, info_to + ) + mult = _get_sensor_operator(epochs, meg_picks) + n_channels, n_times = len(epochs.ch_names), len(epochs.times) + other_picks = np.setdiff1d(np.arange(n_channels), meg_picks) + data = np.zeros((n_channels, n_times)) + count = 0 + # keep only MEG w/bad channels marked in "info_from" + info_from = pick_info(info_to, meg_picks[good_mask], copy=True) + all_coils_recon = _prep_mf_coils(info_to, ignore_ref=ignore_ref) + all_coils = _prep_mf_coils(info_from, ignore_ref=ignore_ref) + # remove MEG bads in "to" info + _reset_meg_bads(info_to) + # set up variables + w_sum = 0.0 + n_in, n_out = _get_n_moments([int_order, ext_order]) + S_decomp = 0.0 # this will end up being a weighted average + last_trans = None + decomp_coil_scale = coil_scale[good_mask] + exp = dict(int_order=int_order, ext_order=ext_order, head_frame=True, origin=origin) + n_in = _get_n_moments(int_order) + for ei, epoch in enumerate(epochs): + event_time = epochs.events[epochs._current - 1, 0] / orig_sfreq + use_idx = np.where(t <= event_time)[0] + if len(use_idx) == 0: + trans = info_to["dev_head_t"]["trans"] + else: + use_idx = use_idx[-1] + trans = np.vstack( + [np.hstack([rot[use_idx], trn[[use_idx]].T]), [[0.0, 0.0, 0.0, 1.0]]] + ) + loc_str = ", ".join(f"{tr:0.1f}" for tr in (trans[:3, 3] * 1000)) + if last_trans is None or not np.allclose(last_trans, trans): + logger.info( + f" Processing epoch {ei + 1} (device location: {loc_str} mm)" + ) + reuse = False + last_trans = trans + else: + logger.info(f" Processing epoch {ei + 1} (device location: same)") + reuse = True + epoch = epoch.copy() # because we operate inplace + if not reuse: + S = _trans_sss_basis(exp, all_coils, trans, coil_scale=decomp_coil_scale) + # Get the weight from the un-regularized version (eq. 44) + weight = np.linalg.norm(S[:, :n_in]) + # XXX Eventually we could do cross-talk and fine-cal here + S *= weight + S_decomp += S # eq. 41 + epoch[slice(None) if weight_all else meg_picks] *= weight + data += epoch # eq. 42 + w_sum += weight + count += 1 + del info_from + mapping = None + if count == 0: + data.fill(np.nan) + else: + data[meg_picks] /= w_sum + data[other_picks] /= w_sum if weight_all else count + # Finalize weighted average decomp matrix + S_decomp /= w_sum + # Get recon matrix + # (We would need to include external here for regularization to work) + exp["ext_order"] = 0 + S_recon = _trans_sss_basis(exp, all_coils_recon, recon_trans) + if mult is not None: + S_decomp = mult @ S_decomp + S_recon = mult @ S_recon + exp["ext_order"] = ext_order + # We could determine regularization on basis of destination basis + # matrix, restricted to good channels, as regularizing individual + # matrices within the loop above does not seem to work. But in + # testing this seemed to decrease localization quality in most cases, + # so we do not provide the option here. + S_recon /= coil_scale + # Invert + pS_ave = _col_norm_pinv(S_decomp)[0][:n_in] + pS_ave *= decomp_coil_scale.T + # Get mapping matrix + mapping = np.dot(S_recon, pS_ave) + # Apply mapping + data[meg_picks] = np.dot(mapping, data[meg_picks[good_mask]]) + info_to["dev_head_t"] = recon_trans # set the reconstruction transform + evoked = epochs._evoked_from_epoch_data( + data, info_to, picks, n_events=count, kind="average", comment=epochs._name + ) + _remove_meg_projs_comps(evoked, ignore_ref) + logger.info(f"Created Evoked dataset from {count} epochs") + return (evoked, mapping) if return_mapping else evoked + + +@verbose +def make_fixed_length_epochs( + raw, + duration=1.0, + preload=False, + reject_by_annotation=True, + proj=True, + overlap=0.0, + id=1, # noqa: A002 + verbose=None, +): + """Divide continuous raw data into equal-sized consecutive epochs. + + Parameters + ---------- + raw : instance of Raw + Raw data to divide into segments. + duration : float + Duration of each epoch in seconds. Defaults to 1. + %(preload)s + %(reject_by_annotation_epochs)s + + .. versionadded:: 0.21.0 + %(proj_epochs)s + + .. versionadded:: 0.22.0 + overlap : float + The overlap between epochs, in seconds. Must be + ``0 <= overlap < duration``. Default is 0, i.e., no overlap. + + .. versionadded:: 0.23.0 + id : int + The id to use (default 1). + + .. versionadded:: 0.24.0 + %(verbose)s + + Returns + ------- + epochs : instance of Epochs + Segmented data. + + Notes + ----- + .. versionadded:: 0.20 + """ + events = make_fixed_length_events(raw, id=id, duration=duration, overlap=overlap) + delta = 1.0 / raw.info["sfreq"] + return Epochs( + raw, + events, + event_id=[id], + tmin=0, + tmax=duration - delta, + baseline=None, + preload=preload, + reject_by_annotation=reject_by_annotation, + proj=proj, + verbose=verbose, + ) diff --git a/mne-python/source/mne/event.py b/mne-python/source/mne/event.py new file mode 100644 index 0000000000000000000000000000000000000000..e8eb4f28579b5b5e76782e5b5f6feeb8a56b0673 --- /dev/null +++ b/mne-python/source/mne/event.py @@ -0,0 +1,1693 @@ +"""IO with fif files containing events.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from collections.abc import Sequence +from pathlib import Path + +import numpy as np + +from ._fiff.constants import FIFF +from ._fiff.open import fiff_open +from ._fiff.pick import pick_channels +from ._fiff.tag import read_tag +from ._fiff.tree import dir_tree_find +from ._fiff.write import end_block, start_and_end_file, start_block, write_int +from .fixes import _reshape_view +from .utils import ( + _check_fname, + _check_integer_or_list, + _check_on_missing, + _check_option, + _get_stim_channel, + _on_missing, + _pl, + _validate_type, + check_fname, + fill_doc, + logger, + verbose, + warn, +) + + +@fill_doc +def pick_events(events, include=None, exclude=None, step=False): + """Select some :term:`events`. + + Parameters + ---------- + %(events)s + include : int | list | None + A event id to include or a list of them. + If None all events are included. + exclude : int | list | None + A event id to exclude or a list of them. + If None no event is excluded. If include is not None + the exclude parameter is ignored. + step : bool + If True (default is False), events have a step format according + to the argument output='step' in the function find_events(). + In this case, the two last columns are considered in inclusion/ + exclusion criteria. + + Returns + ------- + events : array, shape (n_events, 3) + The list of events. + """ + if include is not None: + include = _check_integer_or_list(include, "include") + mask = np.zeros(len(events), dtype=bool) + for e in include: + mask = np.logical_or(mask, events[:, 2] == e) + if step: + mask = np.logical_or(mask, events[:, 1] == e) + events = events[mask] + elif exclude is not None: + exclude = _check_integer_or_list(exclude, "exclude") + mask = np.ones(len(events), dtype=bool) + for e in exclude: + mask = np.logical_and(mask, events[:, 2] != e) + if step: + mask = np.logical_and(mask, events[:, 1] != e) + events = events[mask] + else: + events = np.copy(events) + + if len(events) == 0: + raise RuntimeError("No events found") + + return events + + +def define_target_events( + events, reference_id, target_id, sfreq, tmin, tmax, new_id=None, fill_na=None +): + """Define new events by co-occurrence of existing events. + + This function can be used to evaluate events depending on the + temporal lag to another event. For example, this can be used to + analyze evoked responses which were followed by a button press within + a defined time window. + + Parameters + ---------- + events : ndarray + Array as returned by mne.find_events. + reference_id : int + The reference event. The event defining the epoch of interest. + target_id : int + The target event. The event co-occurring in within a certain time + window around the reference event. + sfreq : float + The sampling frequency of the data. + tmin : float + The lower limit in seconds from the target event. + tmax : float + The upper limit border in seconds from the target event. + new_id : int + New ID for the new event. + fill_na : int | None + Fill event to be inserted if target is not available within the time + window specified. If None, the 'null' events will be dropped. + + Returns + ------- + new_events : ndarray + The new defined events. + lag : ndarray + Time lag between reference and target in milliseconds. + """ + if new_id is None: + new_id = reference_id + + tsample = 1e3 / sfreq + imin = int(tmin * sfreq) + imax = int(tmax * sfreq) + + new_events = [] + lag = [] + for event in events.copy().astype(int): + if event[2] == reference_id: + lower = event[0] + imin + upper = event[0] + imax + res = events[ + (events[:, 0] > lower) + & (events[:, 0] < upper) + & (events[:, 2] == target_id) + ] + if res.any(): + lag += [event[0] - res[0][0]] + event[2] = new_id + new_events += [event] + elif fill_na is not None: + event[2] = fill_na + new_events += [event] + lag.append(np.nan) + + new_events = np.array(new_events) + + with np.errstate(invalid="ignore"): # casting nans + lag = np.abs(lag, dtype="f8") + if lag.any(): + lag *= tsample + else: + lag = np.array([]) + + return new_events if new_events.any() else np.array([]), lag + + +def _read_events_fif(fid, tree): + """Aux function.""" + # Find the desired block + events = dir_tree_find(tree, FIFF.FIFFB_MNE_EVENTS) + + if len(events) == 0: + fid.close() + raise ValueError("Could not find event data") + + events = events[0] + event_list = None + event_id = None + for d in events["directory"]: + kind = d.kind + pos = d.pos + if kind == FIFF.FIFF_MNE_EVENT_LIST: + tag = read_tag(fid, pos) + event_list = tag.data + break + if event_list is None: + raise ValueError("Could not find any events") + else: + event_list = _reshape_view(event_list, (-1, 3)) + for d in events["directory"]: + kind = d.kind + pos = d.pos + if kind == FIFF.FIFF_DESCRIPTION: + tag = read_tag(fid, pos) + event_id = tag.data + m_ = [[s[::-1] for s in m[::-1].split(":", 1)] for m in event_id.split(";")] + event_id = {k: int(v) for v, k in m_} + break + elif kind == FIFF.FIFF_MNE_EVENT_COMMENTS: + tag = read_tag(fid, pos) + event_id = tag.data + event_id = event_id.tobytes().decode("latin-1").split("\x00")[:-1] + assert len(event_id) == len(event_list) + event_id = {k: v[2] for k, v in zip(event_id, event_list)} + break + return event_list, event_id + + +@verbose +def read_events( + filename, + include=None, + exclude=None, + mask=None, + mask_type="and", + return_event_id=False, + verbose=None, +): + """Read :term:`events` from fif or text file. + + See :ref:`tut-events-vs-annotations` and :ref:`tut-event-arrays` + for more information about events. + + Parameters + ---------- + filename : path-like + Name of the input file. + If the extension is ``.fif``, events are read assuming + the file is in FIF format, otherwise (e.g., ``.eve``, + ``.lst``, ``.txt``) events are read as coming from text. + Note that new format event files do not contain + the ``"time"`` column (used to be the second column). + include : int | list | None + A event id to include or a list of them. + If None all events are included. + exclude : int | list | None + A event id to exclude or a list of them. + If None no event is excluded. If include is not None + the exclude parameter is ignored. + mask : int | None + The value of the digital mask to apply to the stim channel values. + If None (default), no masking is performed. + mask_type : ``'and'`` | ``'not_and'`` + The type of operation between the mask and the trigger. + Choose 'and' (default) for MNE-C masking behavior. + + .. versionadded:: 0.13 + return_event_id : bool + If True, ``event_id`` will be returned. This is only possible for + ``-annot.fif`` files produced with MNE-C ``mne_browse_raw``. + + .. versionadded:: 0.20 + %(verbose)s + + Returns + ------- + %(events)s + event_id : dict + Dictionary of ``{str: int}`` mappings of event IDs. + + See Also + -------- + find_events, write_events + + Notes + ----- + This function will discard the offset line (i.e., first line with zero + event number) if it is present in a text file. + + For more information on ``mask`` and ``mask_type``, see + :func:`mne.find_events`. + """ + check_fname( + filename, + "events", + ( + ".eve", + "-eve.fif", + "-eve.fif.gz", + "-eve.lst", + "-eve.txt", + "_eve.fif", + "_eve.fif.gz", + "_eve.lst", + "_eve.txt", + "-annot.fif", # MNE-C annot + ), + ) + filename = Path(filename) + if filename.suffix in (".fif", ".gz"): + fid, tree, _ = fiff_open(filename) + with fid as f: + event_list, event_id = _read_events_fif(f, tree) + # hack fix for windows to avoid bincount problems + event_list = event_list.astype(int) + else: + # Have to read this in as float64 then convert because old style + # eve/lst files had a second float column that will raise errors + lines = np.loadtxt(filename, dtype=np.float64).astype(int) + if len(lines) == 0: + raise ValueError("No text lines found") + + if lines.ndim == 1: # Special case for only one event + lines = lines[np.newaxis, :] + + if len(lines[0]) == 4: # Old format eve/lst + goods = [0, 2, 3] # Omit "time" variable + elif len(lines[0]) == 3: + goods = [0, 1, 2] + else: + raise ValueError("Unknown number of columns in event text file") + + event_list = lines[:, goods] + if mask is not None and event_list.shape[0] > 0 and event_list[0, 2] == 0: + event_list = event_list[1:] + warn("first row of event file discarded (zero-valued)") + event_id = None + + event_list = pick_events(event_list, include, exclude) + unmasked_len = event_list.shape[0] + if mask is not None: + event_list = _mask_trigs(event_list, mask, mask_type) + masked_len = event_list.shape[0] + if masked_len < unmasked_len: + warn(f"{unmasked_len - masked_len} of {unmasked_len} events masked") + out = event_list + if return_event_id: + if event_id is None: + raise RuntimeError("No event_id found in the file") + out = (out, event_id) + return out + + +@verbose +def write_events(filename, events, *, overwrite=False, verbose=None): + """Write :term:`events` to file. + + Parameters + ---------- + filename : path-like + Name of the output file. + If the extension is ``.fif``, events are written in + binary FIF format, otherwise (e.g., ``.eve``, + ``.lst``, ``.txt``) events are written as plain text. + Note that new format event files do not contain + the ``"time"`` column (used to be the second column). + %(events)s + %(overwrite)s + %(verbose)s + + See Also + -------- + read_events + """ + filename = _check_fname(filename, overwrite=overwrite) + check_fname( + filename, + "events", + ( + ".eve", + "-eve.fif", + "-eve.fif.gz", + "-eve.lst", + "-eve.txt", + "_eve.fif", + "_eve.fif.gz", + "_eve.lst", + "_eve.txt", + ), + ) + if filename.suffix in (".fif", ".gz"): + # Start writing... + with start_and_end_file(filename) as fid: + start_block(fid, FIFF.FIFFB_MNE_EVENTS) + write_int(fid, FIFF.FIFF_MNE_EVENT_LIST, events.T) + end_block(fid, FIFF.FIFFB_MNE_EVENTS) + else: + with open(filename, "w") as f: + for e in events: + f.write(f"{e[0]:6d} {e[1]:6d} {e[2]:3d}\n") + + +def _find_stim_steps(data, first_samp, pad_start=None, pad_stop=None, merge=0): + changed = np.diff(data, axis=1) != 0 + idx = np.where(np.all(changed, axis=0))[0] + if len(idx) == 0: + return np.empty((0, 3), dtype="int32") + + pre_step = data[0, idx] + idx += 1 + post_step = data[0, idx] + idx += first_samp + steps = np.c_[idx, pre_step, post_step] + + if pad_start is not None: + v = steps[0, 1] + if v != pad_start: + steps = np.insert(steps, 0, [0, pad_start, v], axis=0) + + if pad_stop is not None: + v = steps[-1, 2] + if v != pad_stop: + last_idx = len(data[0]) + first_samp + steps = np.append(steps, [[last_idx, v, pad_stop]], axis=0) + + if merge != 0: + diff = np.diff(steps[:, 0]) + idx = diff <= abs(merge) + if np.any(idx): + where = np.where(idx)[0] + keep = np.logical_not(idx) + if merge > 0: + # drop the earlier event + steps[where + 1, 1] = steps[where, 1] + keep = np.append(keep, True) + else: + # drop the later event + steps[where, 2] = steps[where + 1, 2] + keep = np.insert(keep, 0, True) + + is_step = steps[:, 1] != steps[:, 2] + keep = np.logical_and(keep, is_step) + steps = steps[keep] + + return steps + + +def find_stim_steps(raw, pad_start=None, pad_stop=None, merge=0, stim_channel=None): + """Find all steps in data from a stim channel. + + Parameters + ---------- + raw : Raw object + The raw data. + pad_start : None | int + Values to assume outside of the stim channel (e.g., if pad_start=0 and + the stim channel starts with value 5, an event of [0, 0, 5] will be + inserted at the beginning). With None, no steps will be inserted. + pad_stop : None | int + Values to assume outside of the stim channel, see ``pad_start``. + merge : int + Merge steps occurring in neighboring samples. The integer value + indicates over how many samples events should be merged, and the sign + indicates in which direction they should be merged (negative means + towards the earlier event, positive towards the later event). + stim_channel : None | str | list of str + Name of the stim channel or all the stim channels + affected by the trigger. If None, the config variables + 'MNE_STIM_CHANNEL', 'MNE_STIM_CHANNEL_1', 'MNE_STIM_CHANNEL_2', + etc. are read. If these are not found, it will default to + 'STI101' or 'STI 014', whichever is present. + + Returns + ------- + steps : array, shape = (n_samples, 3) + For each step in the stim channel the values [sample, v_from, v_to]. + The first column contains the event time in samples (the first sample + with the new value). The second column contains the stim channel value + before the step, and the third column contains value after the step. + + See Also + -------- + find_events : More sophisticated options for finding events in a Raw file. + """ + # pull stim channel from config if necessary + stim_channel = _get_stim_channel(stim_channel, raw.info) + + picks = pick_channels(raw.info["ch_names"], include=stim_channel, ordered=False) + if len(picks) == 0: + raise ValueError("No stim channel found to extract event triggers.") + data, _ = raw[picks, :] + if np.any(data < 0): + warn("Trigger channel contains negative values, using absolute value.") + data = np.abs(data) # make sure trig channel is positive + data = data.astype(np.int64) + + return _find_stim_steps( + data, raw.first_samp, pad_start=pad_start, pad_stop=pad_stop, merge=merge + ) + + +@verbose +def _find_events( + data, + first_samp, + *, + verbose=None, + output="onset", + consecutive="increasing", + min_samples=0, + mask=None, + uint_cast=False, + mask_type="and", + initial_event=False, + ch_name=None, +): + """Help find events.""" + assert data.shape[0] == 1 # data should be only a row vector + + if min_samples > 0: + merge = int(min_samples // 1) + if merge == min_samples: + merge -= 1 + else: + merge = 0 + + data = data.astype(np.int64) + if uint_cast: + data = data.astype(np.uint16).astype(np.int64) + if data.min() < 0: + warn( + "Trigger channel contains negative values, using absolute " + "value. If data were acquired on a Neuromag system with " + "STI016 active, consider using uint_cast=True to work around " + "an acquisition bug" + ) + data = np.abs(data) # make sure trig channel is positive + + events = _find_stim_steps(data, first_samp, pad_stop=0, merge=merge) + initial_value = data[0, 0] + if initial_value != 0: + if initial_event: + events = np.insert(events, 0, [first_samp, 0, initial_value], axis=0) + else: + logger.info( + f"Trigger channel {ch_name} has a non-zero initial value of " + f"{initial_value} (consider using initial_event=True to detect this " + "event)" + ) + + events = _mask_trigs(events, mask, mask_type) + + # Determine event onsets and offsets + if consecutive == "increasing": + onsets = events[:, 2] > events[:, 1] + offsets = np.logical_and( + np.logical_or(onsets, (events[:, 2] == 0)), (events[:, 1] > 0) + ) + elif consecutive: + onsets = events[:, 2] > 0 + offsets = events[:, 1] > 0 + else: + onsets = events[:, 1] == 0 + offsets = events[:, 2] == 0 + + onset_idx = np.where(onsets)[0] + offset_idx = np.where(offsets)[0] + + if len(onset_idx) == 0 or len(offset_idx) == 0: + return np.empty((0, 3), dtype="int32") + + # delete orphaned onsets/offsets + if onset_idx[0] > offset_idx[0]: + logger.info("Removing orphaned offset at the beginning of the file.") + offset_idx = np.delete(offset_idx, 0) + + if onset_idx[-1] > offset_idx[-1]: + logger.info("Removing orphaned onset at the end of the file.") + onset_idx = np.delete(onset_idx, -1) + + _check_option("output", output, ("onset", "step", "offset")) + if output == "onset": + events = events[onset_idx] + elif output == "step": + idx = np.union1d(onset_idx, offset_idx) + events = events[idx] + else: + assert output == "offset" + event_id = events[onset_idx, 2] + events = events[offset_idx] + events[:, 1] = events[:, 2] + events[:, 2] = event_id + events[:, 0] -= 1 + + logger.info(f"{len(events)} event{_pl(events)} found on stim channel {ch_name}") + logger.info(f"Event IDs: {np.unique(events[:, 2])}") + + return events + + +def _find_unique_events(events): + """Uniquify events (ie remove duplicated rows.""" + e = np.ascontiguousarray(events).view( + np.dtype((np.void, events.dtype.itemsize * events.shape[1])) + ) + _, idx = np.unique(e, return_index=True) + n_dupes = len(events) - len(idx) + if n_dupes > 0: + warn( + "Some events are duplicated in your different stim channels. " + f"{n_dupes} events were ignored during deduplication." + ) + return events[idx] + + +@verbose +def find_events( + raw, + stim_channel=None, + output="onset", + consecutive="increasing", + min_duration=0, + shortest_event=2, + mask=None, + uint_cast=False, + mask_type="and", + initial_event=False, + verbose=None, +): + """Find :term:`events` from raw file. + + See :ref:`tut-events-vs-annotations` and :ref:`tut-event-arrays` + for more information about events. + + Parameters + ---------- + raw : Raw object + The raw data. + stim_channel : None | str | list of str + Name of the stim channel or all the stim channels + affected by triggers. If None, the config variables + 'MNE_STIM_CHANNEL', 'MNE_STIM_CHANNEL_1', 'MNE_STIM_CHANNEL_2', + etc. are read. If these are not found, it will fall back to + 'STI 014' if present, then fall back to the first channel of type + 'stim', if present. If multiple channels are provided + then the returned events are the union of all the events + extracted from individual stim channels. + output : 'onset' | 'offset' | 'step' + Whether to report when events start, when events end, or both. + consecutive : bool | 'increasing' + If True, consider instances where the value of the events + channel changes without first returning to zero as multiple + events. If False, report only instances where the value of the + events channel changes from/to zero. If 'increasing', report + adjacent events only when the second event code is greater than + the first. + min_duration : float + The minimum duration of a change in the events channel required + to consider it as an event (in seconds). + shortest_event : int + Minimum number of samples an event must last (default is 2). If the + duration is less than this an exception will be raised. + mask : int | None + The value of the digital mask to apply to the stim channel values. + If None (default), no masking is performed. + uint_cast : bool + If True (default False), do a cast to ``uint16`` on the channel + data. This can be used to fix a bug with STI101 and STI014 in + Neuromag acquisition setups that use channel STI016 (channel 16 + turns data into e.g. -32768), similar to ``mne_fix_stim14 --32`` + in MNE-C. + + .. versionadded:: 0.12 + mask_type : 'and' | 'not_and' + The type of operation between the mask and the trigger. + Choose 'and' (default) for MNE-C masking behavior. + + .. versionadded:: 0.13 + initial_event : bool + If True (default False), an event is created if the stim channel has a + value different from 0 as its first sample. This is useful if an event + at t=0s is present. + + .. versionadded:: 0.16 + %(verbose)s + + Returns + ------- + %(events)s + + See Also + -------- + find_stim_steps : Find all the steps in the stim channel. + read_events : Read events from disk. + write_events : Write events to disk. + + Notes + ----- + .. warning:: If you are working with downsampled data, events computed + before decimation are no longer valid. Please recompute + your events after decimation, but note this reduces the + precision of event timing. + + Examples + -------- + Consider data with a stim channel that looks like:: + + [0, 32, 32, 33, 32, 0] + + By default, find_events returns all samples at which the value of the + stim channel increases:: + + >>> print(find_events(raw)) # doctest: +SKIP + [[ 1 0 32] + [ 3 32 33]] + + If consecutive is False, find_events only returns the samples at which + the stim channel changes from zero to a non-zero value:: + + >>> print(find_events(raw, consecutive=False)) # doctest: +SKIP + [[ 1 0 32]] + + If consecutive is True, find_events returns samples at which the + event changes, regardless of whether it first returns to zero:: + + >>> print(find_events(raw, consecutive=True)) # doctest: +SKIP + [[ 1 0 32] + [ 3 32 33] + [ 4 33 32]] + + If output is 'offset', find_events returns the last sample of each event + instead of the first one:: + + >>> print(find_events(raw, consecutive=True, # doctest: +SKIP + ... output='offset')) + [[ 2 33 32] + [ 3 32 33] + [ 4 0 32]] + + If output is 'step', find_events returns the samples at which an event + starts or ends:: + + >>> print(find_events(raw, consecutive=True, # doctest: +SKIP + ... output='step')) + [[ 1 0 32] + [ 3 32 33] + [ 4 33 32] + [ 5 32 0]] + + To ignore spurious events, it is also possible to specify a minimum + event duration. Assuming our events channel has a sample rate of + 1000 Hz:: + + >>> print(find_events(raw, consecutive=True, # doctest: +SKIP + ... min_duration=0.002)) + [[ 1 0 32]] + + For the digital mask, if mask_type is set to 'and' it will take the + binary representation of the digital mask, e.g. 5 -> '00000101', and will + allow the values to pass where mask is one, e.g.:: + + 7 '0000111' <- trigger value + 37 '0100101' <- mask + ---------------- + 5 '0000101' + + For the digital mask, if mask_type is set to 'not_and' it will take the + binary representation of the digital mask, e.g. 5 -> '00000101', and will + block the values where mask is one, e.g.:: + + 7 '0000111' <- trigger value + 37 '0100101' <- mask + ---------------- + 2 '0000010' + """ + min_samples = min_duration * raw.info["sfreq"] + + # pull stim channel from config if necessary + try: + stim_channel = _get_stim_channel(stim_channel, raw.info) + except ValueError: + if len(raw.annotations) > 0: + raise ValueError( + "No stim channels found, but the raw object has " + "annotations. Consider using " + "mne.events_from_annotations to convert these to " + "events." + ) + else: + raise + + picks = pick_channels(raw.info["ch_names"], include=stim_channel) + if len(picks) == 0: + raise ValueError("No stim channel found to extract event triggers.") + logger.info(f"Finding events on: {', '.join(raw.ch_names[pick] for pick in picks)}") + data, _ = raw[picks, :] + + events_list = [] + for d, ch_name in zip(data, stim_channel): + events = _find_events( + d[np.newaxis, :], + raw.first_samp, + verbose=verbose, + output=output, + consecutive=consecutive, + min_samples=min_samples, + mask=mask, + uint_cast=uint_cast, + mask_type=mask_type, + initial_event=initial_event, + ch_name=ch_name, + ) + # add safety check for spurious events (for ex. from neuromag syst.) by + # checking the number of low sample events + n_short_events = np.sum(np.diff(events[:, 0]) < shortest_event) + if n_short_events > 0: + raise ValueError( + f"You have {n_short_events} events shorter than the shortest_event. " + "These are very unusual and you may want to set min_duration to a " + "larger value e.g. x / raw.info['sfreq']. Where x = 1 sample shorter " + "than the shortest event length." + ) + + events_list.append(events) + + events = np.concatenate(events_list, axis=0) + events = _find_unique_events(events) + events = events[np.argsort(events[:, 0])] + return events + + +def _mask_trigs(events, mask, mask_type): + """Mask digital trigger values.""" + _check_option("mask_type", mask_type, ["not_and", "and"]) + if mask is not None: + _validate_type(mask, "int", "mask", "int or None") + n_events = len(events) + if n_events == 0: + return events.copy() + + if mask is not None: + if mask_type == "not_and": + mask = np.bitwise_not(mask) + elif mask_type != "and": + raise ValueError( + "'mask_type' should be either 'and'" + f" or 'not_and', instead of '{mask_type}'" + ) + events[:, 1:] = np.bitwise_and(events[:, 1:], mask) + events = events[events[:, 1] != events[:, 2]] + + return events + + +def merge_events(events, ids, new_id, replace_events=True): + """Merge a set of :term:`events`. + + Parameters + ---------- + events : array, shape (n_events_in, 3) + Events. + ids : array of int + The ids of events to merge. + new_id : int + The new id. + replace_events : bool + If True (default), old event ids are replaced. Otherwise, + new events will be added to the old event list. + + Returns + ------- + new_events : array, shape (n_events_out, 3) + The new events. + + Notes + ----- + Rather than merging events you can use hierarchical event_id + in Epochs. For example, here:: + + >>> event_id = {'auditory/left': 1, 'auditory/right': 2} + + And the condition 'auditory' would correspond to either 1 or 2. + + Examples + -------- + Here is quick example of the behavior:: + + >>> events = [[134, 0, 1], [341, 0, 2], [502, 0, 3]] + >>> merge_events(events, [1, 2], 12, replace_events=True) + array([[134, 0, 12], + [341, 0, 12], + [502, 0, 3]]) + >>> merge_events(events, [1, 2], 12, replace_events=False) + array([[134, 0, 1], + [134, 0, 12], + [341, 0, 2], + [341, 0, 12], + [502, 0, 3]]) + """ + events = np.asarray(events) + events_out = events.copy() + idx_touched = [] # to keep track of the original events we can keep + for col in [1, 2]: + for i in ids: + mask = events[:, col] == i + events_out[mask, col] = new_id + idx_touched.append(np.where(mask)[0]) + if not replace_events: + idx_touched = np.unique(np.concatenate(idx_touched)) + events_out = np.concatenate((events_out, events[idx_touched]), axis=0) + # Now sort in lexical order + events_out = events_out[np.lexsort(events_out.T[::-1])] + return events_out + + +@fill_doc +def shift_time_events(events, ids, tshift, sfreq): + """Shift a set of :term:`events`. + + Parameters + ---------- + %(events)s + ids : ndarray of int | None + The ids of events to shift. + tshift : float + Time-shift event. Use positive value tshift for forward shifting + the event and negative value for backward shift. + sfreq : float + The sampling frequency of the data. + + Returns + ------- + new_events : array of int, shape (n_new_events, 3) + The new events. + """ + events = events.copy() + if ids is None: + mask = slice(None) + else: + mask = np.isin(events[:, 2], ids) + events[mask, 0] += int(tshift * sfreq) + + return events + + +@fill_doc +def make_fixed_length_events( + raw, + id=1, # noqa: A002 + start=0, + stop=None, + duration=1.0, + first_samp=True, + overlap=0.0, +): + """Make a set of :term:`events` separated by a fixed duration. + + Parameters + ---------- + raw : instance of Raw + A raw object to use the data from. + id : int + The id to use (default 1). + start : float + Time of first event (in seconds). + stop : float | None + Maximum time of last event (in seconds). If None, events extend to the + end of the recording. + duration : float + The duration to separate events by (in seconds). + first_samp : bool + If True (default), times will have :term:`first_samp` added to them, as + in :func:`mne.find_events`. This behavior is not desirable if the + returned events will be combined with event times that already + have :term:`first_samp` added to them, e.g. event times that come + from :func:`mne.find_events`. + overlap : float + The overlap between events (in seconds). + Must be ``0 <= overlap < duration``. + + .. versionadded:: 0.18 + + Returns + ------- + %(events)s + """ + from .io import BaseRaw + + _validate_type(raw, BaseRaw, "raw") + _validate_type(id, "int", "id") + _validate_type(duration, "numeric", "duration") + _validate_type(overlap, "numeric", "overlap") + duration, overlap = float(duration), float(overlap) + if not 0 <= overlap < duration: + raise ValueError( + f"overlap must be >=0 but < duration ({duration}), got {overlap}" + ) + + start = raw.time_as_index(start, use_rounding=True)[0] + if stop is not None: + stop = raw.time_as_index(stop, use_rounding=True)[0] + else: + stop = raw.last_samp + 1 + if first_samp: + start = start + raw.first_samp + stop = min([stop + raw.first_samp, raw.last_samp + 1]) + else: + stop = min([stop, len(raw.times)]) + # Make sure we don't go out the end of the file: + stop -= int(np.round(raw.info["sfreq"] * duration)) + # This should be inclusive due to how we generally use start and stop... + ts = np.arange(start, stop + 1, raw.info["sfreq"] * (duration - overlap)).astype( + int + ) + n_events = len(ts) + if n_events == 0: + raise ValueError( + "No events produced, check the values of start, stop, and duration" + ) + events = np.c_[ts, np.zeros(n_events, dtype=int), id * np.ones(n_events, dtype=int)] + return events + + +def concatenate_events(events, first_samps, last_samps): + """Concatenate event lists to be compatible with concatenate_raws. + + This is useful, for example, if you processed and/or changed + events in raw files separately before combining them using + :func:`mne.concatenate_raws`. + + Parameters + ---------- + events : list of array + List of :term:`events` arrays, typically each extracted from a + corresponding raw file that is being concatenated. + first_samps : list or array of int + First sample numbers of the raw files concatenated. + last_samps : list or array of int + Last sample numbers of the raw files concatenated. + + Returns + ------- + events : array + The concatenated events. + + See Also + -------- + mne.concatenate_raws + """ + _validate_type(events, list, "events") + if not (len(events) == len(last_samps) and len(events) == len(first_samps)): + raise ValueError( + "events, first_samps, and last_samps must all have the same lengths" + ) + first_samps = np.array(first_samps) + last_samps = np.array(last_samps) + n_samps = np.cumsum(last_samps - first_samps + 1) + events_out = events[0] + for e, f, n in zip(events[1:], first_samps[1:], n_samps[:-1]): + # remove any skip since it doesn't exist in concatenated files + e2 = e.copy() + e2[:, 0] -= f + # add offset due to previous files, plus original file offset + e2[:, 0] += n + first_samps[0] + events_out = np.concatenate((events_out, e2), axis=0) + + return events_out + + +@fill_doc +class AcqParserFIF: + """Parser for Elekta data acquisition settings. + + This class parses parameters (e.g. events and averaging categories) that + are defined in the Elekta TRIUX/VectorView data acquisition software (DACQ) + and stored in ``info['acq_pars']``. It can be used to reaverage raw data + according to DACQ settings and modify original averaging settings if + necessary. + + Parameters + ---------- + %(info_not_none)s This is where the DACQ parameters will be taken from. + + Attributes + ---------- + categories : list + List of averaging categories marked active in DACQ. + events : list + List of events that are in use (referenced by some averaging category). + reject : dict + Rejection criteria from DACQ that can be used with mne.Epochs. + Note that mne does not support all DACQ rejection criteria + (e.g. spike, slope). + flat : dict + Flatness rejection criteria from DACQ that can be used with mne.Epochs. + acq_dict : dict + All DACQ parameters. + + See Also + -------- + mne.io.Raw.acqparser : Access the parser through a Raw attribute. + + Notes + ----- + Any averaging category (also non-active ones) can be accessed by indexing + as ``acqparserfif['category_name']``. + """ + + # DACQ variables always start with one of these + _acq_var_magic = ["ERF", "DEF", "ACQ", "TCP"] + + # averager related DACQ variable names (without preceding 'ERF') + # old versions (DACQ < 3.4) + _dacq_vars_compat = ( + "megMax", + "megMin", + "megNoise", + "megSlope", + "megSpike", + "eegMax", + "eegMin", + "eegNoise", + "eegSlope", + "eegSpike", + "eogMax", + "ecgMax", + "ncateg", + "nevent", + "stimSource", + "triggerMap", + "update", + "artefIgnore", + "averUpdate", + ) + + _event_vars_compat = ("Comment", "Delay") + + _cat_vars = ( + "Comment", + "Display", + "Start", + "State", + "End", + "Event", + "Nave", + "ReqEvent", + "ReqWhen", + "ReqWithin", + "SubAve", + ) + + # new versions only (DACQ >= 3.4) + _dacq_vars = _dacq_vars_compat + ( + "magMax", + "magMin", + "magNoise", + "magSlope", + "magSpike", + "version", + ) + + _event_vars = _event_vars_compat + ( + "Name", + "Channel", + "NewBits", + "OldBits", + "NewMask", + "OldMask", + ) + + def __init__(self, info): + acq_pars = info["acq_pars"] + if not acq_pars: + raise ValueError("No acquisition parameters") + self.acq_dict = dict(self._acqpars_gen(acq_pars)) + if "ERFversion" in self.acq_dict: + self.compat = False # DACQ ver >= 3.4 + elif "ERFncateg" in self.acq_dict: # probably DACQ < 3.4 + self.compat = True + else: + raise ValueError("Cannot parse acquisition parameters") + dacq_vars = self._dacq_vars_compat if self.compat else self._dacq_vars + # set instance variables + for var in dacq_vars: + val = self.acq_dict["ERF" + var] + if var[:3] in ["mag", "meg", "eeg", "eog", "ecg"]: + val = float(val) + elif var in ["ncateg", "nevent"]: + val = int(val) + setattr(self, var.lower(), val) + self.stimsource = "Internal" if self.stimsource == "1" else "External" + # collect all events and categories + self._events = self._events_from_acq_pars() + self._categories = self._categories_from_acq_pars() + # mark events that are used by a category + for cat in self._categories.values(): + if cat["event"]: + self._events[cat["event"]]["in_use"] = True + if cat["reqevent"]: + self._events[cat["reqevent"]]["in_use"] = True + # make mne rejection dicts based on the averager parameters + self.reject = { + "grad": self.megmax, + "eeg": self.eegmax, + "eog": self.eogmax, + "ecg": self.ecgmax, + } + if not self.compat: + self.reject["mag"] = self.magmax + self.reject = {k: float(v) for k, v in self.reject.items() if float(v) > 0} + self.flat = {"grad": self.megmin, "eeg": self.eegmin} + if not self.compat: + self.flat["mag"] = self.magmin + self.flat = {k: float(v) for k, v in self.flat.items() if float(v) > 0} + + def __repr__(self): # noqa: D105 + s = " bits for old DACQ versions + _compat_event_lookup = { + 1: 1, + 2: 2, + 3: 4, + 4: 8, + 5: 16, + 6: 32, + 7: 3, + 8: 5, + 9: 6, + 10: 7, + 11: 9, + 12: 10, + 13: 11, + 14: 12, + 15: 13, + 16: 14, + 17: 15, + } + events = dict() + for evnum in range(1, self.nevent + 1): + evnum_s = str(evnum).zfill(2) # '01', '02' etc. + evdi = dict() + event_vars = self._event_vars_compat if self.compat else self._event_vars + for var in event_vars: + # name of DACQ variable, e.g. 'ERFeventNewBits01' + acq_key = "ERFevent" + var + evnum_s + # corresponding dict key, e.g. 'newbits' + dict_key = var.lower() + val = self.acq_dict[acq_key] + # type convert numeric values + if dict_key in ["newbits", "oldbits", "newmask", "oldmask"]: + val = int(val) + elif dict_key in ["delay"]: + val = float(val) + evdi[dict_key] = val + evdi["in_use"] = False # __init__() will set this + evdi["index"] = evnum + if self.compat: + evdi["name"] = str(evnum) + evdi["oldmask"] = 63 + evdi["newmask"] = 63 + evdi["oldbits"] = 0 + evdi["newbits"] = _compat_event_lookup[evnum] + events[evnum] = evdi + return events + + def _acqpars_gen(self, acq_pars): + """Yield key/value pairs from ``info['acq_pars'])``.""" + key, val = "", "" + for line in acq_pars.split(): + if any([line.startswith(x) for x in self._acq_var_magic]): + key = line + val = "" + else: + if not key: + raise ValueError("Cannot parse acquisition parameters") + # DACQ splits items with spaces into multiple lines + val += " " + line if val else line + yield key, val + + def _categories_from_acq_pars(self): + """Collect DACQ averaging categories into a dict. + + Categories are keyed by the comment field in DACQ. Each category is + itself represented a dict containing the category parameters. + """ + cats = dict() + for catnum in [str(x).zfill(2) for x in range(1, self.nevent + 1)]: + catdi = dict() + # read all category variables + for var in self._cat_vars: + acq_key = "ERFcat" + var + catnum + class_key = var.lower() + val = self.acq_dict[acq_key] + catdi[class_key] = val + # some type conversions + catdi["display"] = catdi["display"] == "1" + catdi["state"] = catdi["state"] == "1" + for key in ["start", "end", "reqwithin"]: + catdi[key] = float(catdi[key]) + for key in ["nave", "event", "reqevent", "reqwhen", "subave"]: + catdi[key] = int(catdi[key]) + # some convenient extra (non-DACQ) vars + catdi["index"] = int(catnum) # index of category in DACQ list + cats[catdi["comment"]] = catdi + return cats + + def _events_mne_to_dacq(self, mne_events): + """Create list of DACQ events based on mne trigger transitions list. + + mne_events is typically given by mne.find_events (use consecutive=True + to get all transitions). Output consists of rows in the form + [t, 0, event_codes] where t is time in samples and event_codes is all + DACQ events compatible with the transition, bitwise ORed together: + e.g. [t1, 0, 5] means that events 1 and 3 occurred at time t1, + as 2**(1 - 1) + 2**(3 - 1) = 5. + """ + events_ = mne_events.copy() + events_[:, 1:3] = 0 + for n, ev in self._events.items(): + if ev["in_use"]: + pre_ok = ( + np.bitwise_and(ev["oldmask"], mne_events[:, 1]) == ev["oldbits"] + ) + post_ok = ( + np.bitwise_and(ev["newmask"], mne_events[:, 2]) == ev["newbits"] + ) + ok_ind = np.where(pre_ok & post_ok) + events_[ok_ind, 2] |= 1 << (n - 1) + return events_ + + def _mne_events_to_category_t0(self, cat, mne_events, sfreq): + """Translate mne_events to epoch zero times (t0). + + First mne events (trigger transitions) are converted into DACQ events. + Then the zero times for the epochs are obtained by considering the + reference and conditional (required) events and the delay to stimulus. + """ + cat_ev = cat["event"] + cat_reqev = cat["reqevent"] + # first convert mne events to dacq event list + events = self._events_mne_to_dacq(mne_events) + # next, take req. events and delays into account + times = events[:, 0] + # indices of times where ref. event occurs + refEvents_inds = np.where(events[:, 2] & (1 << cat_ev - 1))[0] + refEvents_t = times[refEvents_inds] + if cat_reqev: + # indices of times where req. event occurs + reqEvents_inds = np.where(events[:, 2] & (1 << cat_reqev - 1))[0] + reqEvents_t = times[reqEvents_inds] + # relative (to refevent) time window where req. event + # must occur (e.g. [0 .2]) + twin = [0, (-1) ** (cat["reqwhen"]) * cat["reqwithin"]] + win = np.round(np.array(sorted(twin)) * sfreq) # to samples + refEvents_wins = refEvents_t[:, None] + win + req_acc = np.zeros(refEvents_inds.shape, dtype=bool) + for t in reqEvents_t: + # mark time windows where req. condition is satisfied + reqEvent_in_win = np.logical_and( + t >= refEvents_wins[:, 0], t <= refEvents_wins[:, 1] + ) + req_acc |= reqEvent_in_win + # drop ref. events where req. event condition is not satisfied + refEvents_inds = refEvents_inds[np.where(req_acc)] + refEvents_t = times[refEvents_inds] + # adjust for trigger-stimulus delay by delaying the ref. event + refEvents_t += int(np.round(self._events[cat_ev]["delay"] * sfreq)) + return refEvents_t + + @property + def categories(self): + """Return list of averaging categories ordered by DACQ index. + + Only returns categories marked active in DACQ. + """ + cats = sorted(self._categories_in_use.values(), key=lambda cat: cat["index"]) + return cats + + @property + def events(self): + """Return events ordered by DACQ index. + + Only returns events that are in use (referred to by a category). + """ + evs = sorted(self._events_in_use.values(), key=lambda ev: ev["index"]) + return evs + + @property + def _categories_in_use(self): + return {k: v for k, v in self._categories.items() if v["state"]} + + @property + def _events_in_use(self): + return {k: v for k, v in self._events.items() if v["in_use"]} + + def get_condition( + self, + raw, + condition=None, + stim_channel=None, + mask=None, + uint_cast=None, + mask_type="and", + delayed_lookup=True, + ): + """Get averaging parameters for a condition (averaging category). + + Output is designed to be used with the Epochs class to extract the + corresponding epochs. + + Parameters + ---------- + raw : Raw object + An instance of Raw. + condition : None | str | dict | list of dict + Condition or a list of conditions. Conditions can be strings + (DACQ comment field, e.g. 'Auditory left') or category dicts + (e.g. acqp['Auditory left'], where acqp is an instance of + AcqParserFIF). If None, get all conditions marked active in + DACQ. + stim_channel : None | str | list of str + Name of the stim channel or all the stim channels + affected by the trigger. If None, the config variables + 'MNE_STIM_CHANNEL', 'MNE_STIM_CHANNEL_1', 'MNE_STIM_CHANNEL_2', + etc. are read. If these are not found, it will fall back to + 'STI101' or 'STI 014' if present, then fall back to the first + channel of type 'stim', if present. + mask : int | None + The value of the digital mask to apply to the stim channel values. + If None (default), no masking is performed. + uint_cast : bool + If True (default False), do a cast to ``uint16`` on the channel + data. This can be used to fix a bug with STI101 and STI014 in + Neuromag acquisition setups that use channel STI016 (channel 16 + turns data into e.g. -32768), similar to ``mne_fix_stim14 --32`` + in MNE-C. + mask_type : 'and' | 'not_and' + The type of operation between the mask and the trigger. + Choose 'and' for MNE-C masking behavior. + delayed_lookup : bool + If True, use the 'delayed lookup' procedure implemented in Elekta + software. When a trigger transition occurs, the lookup of + the new trigger value will not happen immediately at the following + sample, but with a 1-sample delay. This allows a slight + asynchrony between trigger onsets, when they are intended to be + synchronous. If you have accurate hardware and want to detect + transitions with a resolution of one sample, use + delayed_lookup=False. + + Returns + ------- + conds_data : dict or list of dict + Each dict has the following keys: + + events : array, shape (n_epochs_out, 3) + List of zero time points (t0) for the epochs matching the + condition. Use as the ``events`` parameter to Epochs. Note + that these are not (necessarily) actual events. + event_id : dict + Name of condition and index compatible with ``events``. + Should be passed as the ``event_id`` parameter to Epochs. + tmin : float + Epoch starting time relative to t0. Use as the ``tmin`` + parameter to Epochs. + tmax : float + Epoch ending time relative to t0. Use as the ``tmax`` + parameter to Epochs. + """ + if condition is None: + condition = self.categories # get all + if not isinstance(condition, list): + condition = [condition] # single cond -> listify + conds_data = list() + for cat in condition: + if isinstance(cat, str): + cat = self[cat] + mne_events = find_events( + raw, + stim_channel=stim_channel, + mask=mask, + mask_type=mask_type, + output="step", + uint_cast=uint_cast, + consecutive=True, + verbose=False, + shortest_event=1, + ) + if delayed_lookup: + ind = np.where(np.diff(mne_events[:, 0]) == 1)[0] + if 1 in np.diff(ind): + raise ValueError( + "There are several subsequent " + "transitions on the trigger channel. " + "This will not work well with " + "delayed_lookup=True. You may want to " + "check your trigger data and " + "set delayed_lookup=False." + ) + mne_events[ind, 2] = mne_events[ind + 1, 2] + mne_events = np.delete(mne_events, ind + 1, axis=0) + sfreq = raw.info["sfreq"] + cat_t0_ = self._mne_events_to_category_t0(cat, mne_events, sfreq) + # make it compatible with the usual events array + cat_t0 = np.c_[ + cat_t0_, np.zeros(cat_t0_.shape), cat["index"] * np.ones(cat_t0_.shape) + ].astype(np.uint32) + cat_id = {cat["comment"]: cat["index"]} + tmin, tmax = cat["start"], cat["end"] + conds_data.append( + dict(events=cat_t0, event_id=cat_id, tmin=tmin, tmax=tmax) + ) + return conds_data[0] if len(conds_data) == 1 else conds_data + + +def match_event_names(event_names, keys, *, on_missing="raise"): + """Search a collection of event names for matching (sub-)groups of events. + + This function is particularly helpful when using grouped event names + (i.e., event names containing forward slashes ``/``). Please see the + Examples section below for a working example. + + Parameters + ---------- + event_names : array-like of str | dict + Either a collection of event names, or the ``event_id`` dictionary + mapping event names to event codes. + keys : array-like of str | str + One or multiple event names or groups to search for in ``event_names``. + on_missing : 'raise' | 'warn' | 'ignore' + How to handle situations when none of the ``keys`` can be found in + ``event_names``. If ``'warn'`` or ``'ignore'``, an empty list will be + returned. + + Returns + ------- + matches : list of str + All event names that match any of the ``keys`` provided. + + Notes + ----- + .. versionadded:: 1.0 + + Examples + -------- + Assuming the following grouped event names in the data, you could easily + query for all ``auditory`` and ``left`` event names:: + + >>> event_names = [ + ... 'auditory/left', + ... 'auditory/right', + ... 'visual/left', + ... 'visual/right' + ... ] + >>> match_event_names( + ... event_names=event_names, + ... keys=['auditory', 'left'] + ... ) + ['auditory/left', 'auditory/right', 'visual/left'] + """ + _check_on_missing(on_missing) + + if isinstance(event_names, dict): + event_names = list(event_names) + + # ensure we have a list of `keys` + if isinstance(keys, Sequence | np.ndarray) and not isinstance(keys, str): + keys = list(keys) + else: + keys = [keys] + + matches = [] + + # form the hierarchical event name mapping + for key in keys: + if not isinstance(key, str): + raise ValueError(f"keys must be strings, got {type(key)} ({key})") + + matches.extend( + name + for name in event_names + if set(key.split("/")).issubset(name.split("/")) + ) + + if not matches: + _on_missing( + on_missing=on_missing, + msg=f'Event name "{key}" could not be found. The following events ' + f"are present in the data: {', '.join(event_names)}", + error_klass=KeyError, + ) + + matches = sorted(set(matches)) # deduplicate if necessary + return matches + + +def count_events(events, ids=None): + """Count events. + + Parameters + ---------- + events : ndarray, shape (N, 3) + The events array (consisting of N events). + ids : array-like of int | None + If ``None``, count all event types present in the input. If array-like + of int, count only those event types given by ``ids``. + + Returns + ------- + counts : dict + A dictionary containing the event types as keys with their counts as + values. + + Examples + -------- + >>> events = np.array([[0, 0, 1], [0, 0, 1], [0, 0, 5]]) + >>> count_events(events) + {1: 2, 5: 1} + >>> count_events(events, ids=[1, 5]) + {1: 2, 5: 1} + >>> count_events(events, ids=[1, 11]) + {1: 2, 11: 0} + """ + counts = np.bincount(events[:, 2]) + counts = {i: int(count) for i, count in enumerate(counts) if count > 0} + if ids is not None: + counts = {id_: counts.get(id_, 0) for id_ in ids} + return counts diff --git a/mne-python/source/mne/evoked.py b/mne-python/source/mne/evoked.py new file mode 100644 index 0000000000000000000000000000000000000000..32475b37818f5e732d7e71a03decf55bab73f48a --- /dev/null +++ b/mne-python/source/mne/evoked.py @@ -0,0 +1,2168 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from __future__ import annotations # only needed for Python ≤ 3.9 + +from copy import deepcopy +from inspect import getfullargspec +from pathlib import Path + +import numpy as np + +from ._fiff.constants import FIFF +from ._fiff.meas_info import ( + ContainsMixin, + SetChannelsMixin, + _ensure_infos_match, + _read_extended_ch_info, + _rename_list, + read_meas_info, + write_meas_info, +) +from ._fiff.open import fiff_open +from ._fiff.pick import _FNIRS_CH_TYPES_SPLIT, _picks_to_idx, pick_types +from ._fiff.proj import ProjMixin +from ._fiff.tag import read_tag +from ._fiff.tree import dir_tree_find +from ._fiff.write import ( + end_block, + start_and_end_file, + start_block, + write_complex_float_matrix, + write_float, + write_float_matrix, + write_id, + write_int, + write_string, +) +from .baseline import _check_baseline, _log_rescale, rescale +from .channels.channels import InterpolationMixin, ReferenceMixin, UpdateChannelsMixin +from .channels.layout import _merge_ch_data, _pair_grad_sensors +from .defaults import _BORDER_DEFAULT, _EXTRAPOLATE_DEFAULT, _INTERPOLATION_DEFAULT +from .filter import FilterMixin, _check_fun, detrend +from .html_templates import _get_html_template +from .parallel import parallel_func +from .time_frequency.spectrum import Spectrum, SpectrumMixin, _validate_method +from .time_frequency.tfr import AverageTFR +from .utils import ( + ExtendedTimeMixin, + SizeMixin, + _build_data_frame, + _check_fname, + _check_option, + _check_pandas_index_arguments, + _check_pandas_installed, + _check_preload, + _check_time_format, + _convert_times, + _scale_dataframe_data, + _validate_type, + check_fname, + copy_function_doc_to_method_doc, + fill_doc, + logger, + repr_html, + sizeof_fmt, + verbose, + warn, +) +from .viz import ( + plot_evoked, + plot_evoked_field, + plot_evoked_image, + plot_evoked_topo, + plot_evoked_topomap, +) +from .viz.evoked import plot_evoked_joint, plot_evoked_white +from .viz.topomap import _topomap_animation + +_aspect_dict = { + "average": FIFF.FIFFV_ASPECT_AVERAGE, + "standard_error": FIFF.FIFFV_ASPECT_STD_ERR, + "single_epoch": FIFF.FIFFV_ASPECT_SINGLE, + "partial_average": FIFF.FIFFV_ASPECT_SUBAVERAGE, + "alternating_subaverage": FIFF.FIFFV_ASPECT_ALTAVERAGE, + "sample_cut_out_by_graph": FIFF.FIFFV_ASPECT_SAMPLE, + "power_density_spectrum": FIFF.FIFFV_ASPECT_POWER_DENSITY, + "dipole_amplitude_cuvre": FIFF.FIFFV_ASPECT_DIPOLE_WAVE, + "squid_modulation_lower_bound": FIFF.FIFFV_ASPECT_IFII_LOW, + "squid_modulation_upper_bound": FIFF.FIFFV_ASPECT_IFII_HIGH, + "squid_gate_setting": FIFF.FIFFV_ASPECT_GATE, +} +_aspect_rev = {val: key for key, val in _aspect_dict.items()} + + +@fill_doc +class Evoked( + ProjMixin, + ContainsMixin, + UpdateChannelsMixin, + ReferenceMixin, + SetChannelsMixin, + InterpolationMixin, + FilterMixin, + ExtendedTimeMixin, + SizeMixin, + SpectrumMixin, +): + """Evoked data. + + Parameters + ---------- + fname : path-like + Name of evoked/average FIF file to load. + If None no data is loaded. + condition : int, or str + Dataset ID number (int) or comment/name (str). Optional if there is + only one data set in file. + proj : bool, optional + Apply SSP projection vectors. + kind : str + Either ``'average'`` or ``'standard_error'``. The type of data to read. + Only used if 'condition' is a str. + allow_maxshield : bool | str (default False) + If True, allow loading of data that has been recorded with internal + active compensation (MaxShield). Data recorded with MaxShield should + generally not be loaded directly, but should first be processed using + SSS/tSSS to remove the compensation signals that may also affect brain + activity. Can also be ``"yes"`` to load without eliciting a warning. + %(verbose)s + + Attributes + ---------- + %(info_not_none)s + ch_names : list of str + List of channels' names. + nave : int + Number of averaged epochs. + kind : str + Type of data, either average or standard_error. + comment : str + Comment on dataset. Can be the condition. + data : array of shape (n_channels, n_times) + Evoked response. + first : int + First time sample. + last : int + Last time sample. + tmin : float + The first time point in seconds. + tmax : float + The last time point in seconds. + times : array + Time vector in seconds. Goes from ``tmin`` to ``tmax``. Time interval + between consecutive time samples is equal to the inverse of the + sampling frequency. + baseline : None | tuple of length 2 + This attribute reflects whether the data has been baseline-corrected + (it will be a ``tuple`` then) or not (it will be ``None``). + + Notes + ----- + Evoked objects can only contain the average of a single set of conditions. + """ + + @verbose + def __init__( + self, + fname, + condition=None, + proj=True, + kind="average", + allow_maxshield=False, + *, + verbose=None, + ): + _validate_type(proj, bool, "'proj'") + # Read the requested data + fname = _check_fname(fname=fname, must_exist=True, overwrite="read") + ( + self.info, + self.nave, + self._aspect_kind, + self.comment, + times, + self.data, + self.baseline, + ) = _read_evoked(fname, condition, kind, allow_maxshield) + self._set_times(times) + self._raw_times = self.times.copy() + self._decim = 1 + + self._update_first_last() + self.preload = True + # project and baseline correct + if proj: + self.apply_proj() + self.filename = fname + + @property + def filename(self) -> Path | None: + """The filename of the evoked object, if it exists. + + :type: :class:`~pathlib.Path` | None + """ + return self._filename + + @filename.setter + def filename(self, value): + self._filename = Path(value) if value is not None else value + + @property + def kind(self): + """The data kind.""" + return _aspect_rev[self._aspect_kind] + + @kind.setter + def kind(self, kind): + _check_option("kind", kind, list(_aspect_dict.keys())) + self._aspect_kind = _aspect_dict[kind] + + @property + def data(self): + """The data matrix.""" + return self._data + + @data.setter + def data(self, data): + """Set the data matrix.""" + self._data = data + + @fill_doc + def get_data(self, picks=None, units=None, tmin=None, tmax=None): + """Get evoked data as 2D array. + + Parameters + ---------- + %(picks_all)s + %(units)s + tmin : float | None + Start time of data to get in seconds. + tmax : float | None + End time of data to get in seconds. + + Returns + ------- + data : ndarray, shape (n_channels, n_times) + A view on evoked data. + + Notes + ----- + .. versionadded:: 0.24 + """ + # Avoid circular import + from .io.base import _get_ch_factors + + picks = _picks_to_idx(self.info, picks, "all", exclude=()) + + start, stop = self._handle_tmin_tmax(tmin, tmax) + + data = self.data[picks, start:stop] + + if units is not None: + ch_factors = _get_ch_factors(self, units, picks) + data *= ch_factors[:, np.newaxis] + + return data + + @verbose + def apply_function( + self, + fun, + picks=None, + dtype=None, + n_jobs=None, + channel_wise=True, + *, + verbose=None, + **kwargs, + ): + """Apply a function to a subset of channels. + + %(applyfun_summary_evoked)s + + Parameters + ---------- + %(fun_applyfun_evoked)s + %(picks_all_data_noref)s + %(dtype_applyfun)s + %(n_jobs)s Ignored if ``channel_wise=False`` as the workload + is split across channels. + %(channel_wise_applyfun)s + + .. versionadded:: 1.6 + %(verbose)s + %(kwargs_fun)s + + Returns + ------- + self : instance of Evoked + The evoked object with transformed data. + """ + _check_preload(self, "evoked.apply_function") + picks = _picks_to_idx(self.info, picks, exclude=(), with_ref_meg=False) + + if not callable(fun): + raise ValueError("fun needs to be a function") + + data_in = self._data + if dtype is not None and dtype != self._data.dtype: + self._data = self._data.astype(dtype) + + args = getfullargspec(fun).args + getfullargspec(fun).kwonlyargs + if channel_wise is False: + if ("ch_idx" in args) or ("ch_name" in args): + raise ValueError( + "apply_function cannot access ch_idx or ch_name " + "when channel_wise=False" + ) + if "ch_idx" in args: + logger.info("apply_function requested to access ch_idx") + if "ch_name" in args: + logger.info("apply_function requested to access ch_name") + + # check the dimension of the incoming evoked data + _check_option("evoked.ndim", self._data.ndim, [2]) + + if channel_wise: + parallel, p_fun, n_jobs = parallel_func(_check_fun, n_jobs) + if n_jobs == 1: + # modify data inplace to save memory + for ch_idx in picks: + if "ch_idx" in args: + kwargs.update(ch_idx=ch_idx) + if "ch_name" in args: + kwargs.update(ch_name=self.info["ch_names"][ch_idx]) + self._data[ch_idx, :] = _check_fun( + fun, data_in[ch_idx, :], **kwargs + ) + else: + # use parallel function + data_picks_new = parallel( + p_fun( + fun, + data_in[ch_idx, :], + **kwargs, + **{ + k: v + for k, v in [ + ("ch_name", self.info["ch_names"][ch_idx]), + ("ch_idx", ch_idx), + ] + if k in args + }, + ) + for ch_idx in picks + ) + for run_idx, ch_idx in enumerate(picks): + self._data[ch_idx, :] = data_picks_new[run_idx] + else: + self._data[picks, :] = _check_fun(fun, data_in[picks, :], **kwargs) + + return self + + @verbose + def apply_baseline(self, baseline=(None, 0), *, verbose=None): + """Baseline correct evoked data. + + Parameters + ---------- + %(baseline_evoked)s + Defaults to ``(None, 0)``, i.e. beginning of the data until + time point zero. + %(verbose)s + + Returns + ------- + evoked : instance of Evoked + The baseline-corrected Evoked object. + + Notes + ----- + Baseline correction can be done multiple times. + + .. versionadded:: 0.13.0 + """ + baseline = _check_baseline(baseline, times=self.times, sfreq=self.info["sfreq"]) + if self.baseline is not None and baseline is None: + raise ValueError( + "The data has already been baseline-corrected. " + "Cannot remove existing baseline correction." + ) + elif baseline is None: + # Do not rescale + logger.info(_log_rescale(None)) + else: + # Actually baseline correct the data. Logging happens in rescale(). + self.data = rescale(self.data, self.times, baseline, copy=False) + self.baseline = baseline + + return self + + @verbose + def save(self, fname, *, overwrite=False, verbose=None): + """Save evoked data to a file. + + Parameters + ---------- + fname : path-like + The name of the file, which should end with ``-ave.fif(.gz)`` or + ``_ave.fif(.gz)``. + %(overwrite)s + %(verbose)s + + Notes + ----- + To write multiple conditions into a single file, use + `mne.write_evokeds`. + + .. versionchanged:: 0.23 + Information on baseline correction will be stored with the data, + and will be restored when reading again via `mne.read_evokeds`. + """ + write_evokeds(fname, self, overwrite=overwrite) + + @verbose + def export(self, fname, fmt="auto", *, overwrite=False, verbose=None): + """Export Evoked to external formats. + + %(export_fmt_support_evoked)s + + %(export_warning)s + + Parameters + ---------- + %(fname_export_params)s + %(export_fmt_params_evoked)s + %(overwrite)s + %(verbose)s + + Notes + ----- + .. versionadded:: 1.1 + + %(export_warning_note_evoked)s + """ + from .export import export_evokeds + + export_evokeds(fname, self, fmt, overwrite=overwrite, verbose=verbose) + + def __repr__(self): # noqa: D105 + max_comment_length = 1000 + if len(self.comment) > max_comment_length: + comment = self.comment[:max_comment_length] + comment += "..." + else: + comment = self.comment + s = f"'{comment}' ({self.kind}, N={self.nave})" + s += f", {self.times[0]:0.5g} – {self.times[-1]:0.5g} s" + s += ", baseline " + if self.baseline is None: + s += "off" + else: + s += f"{self.baseline[0]:g} – {self.baseline[1]:g} s" + if self.baseline != _check_baseline( + self.baseline, + times=self.times, + sfreq=self.info["sfreq"], + on_baseline_outside_data="adjust", + ): + s += " (baseline period was cropped after baseline correction)" + s += f", {self.data.shape[0]} ch" + s += f", ~{sizeof_fmt(self._size)}" + return f"" + + @repr_html + def _repr_html_(self): + t = _get_html_template("repr", "evoked.html.jinja") + t = t.render( + inst=self, + filenames=( + [Path(self.filename).name] + if getattr(self, "filename", None) is not None + else None + ), + ) + return t + + @property + def ch_names(self): + """Channel names.""" + return self.info["ch_names"] + + @copy_function_doc_to_method_doc(plot_evoked) + def plot( + self, + picks=None, + exclude="bads", + unit=True, + show=True, + ylim=None, + xlim="tight", + proj=False, + hline=None, + units=None, + scalings=None, + titles=None, + axes=None, + gfp=False, + window_title=None, + spatial_colors="auto", + zorder="unsorted", + selectable=True, + noise_cov=None, + time_unit="s", + sphere=None, + *, + highlight=None, + verbose=None, + ): + return plot_evoked( + self, + picks=picks, + exclude=exclude, + unit=unit, + show=show, + ylim=ylim, + proj=proj, + xlim=xlim, + hline=hline, + units=units, + scalings=scalings, + titles=titles, + axes=axes, + gfp=gfp, + window_title=window_title, + spatial_colors=spatial_colors, + zorder=zorder, + selectable=selectable, + noise_cov=noise_cov, + time_unit=time_unit, + sphere=sphere, + highlight=highlight, + verbose=verbose, + ) + + @copy_function_doc_to_method_doc(plot_evoked_image) + def plot_image( + self, + picks=None, + exclude="bads", + unit=True, + show=True, + clim=None, + xlim="tight", + proj=False, + units=None, + scalings=None, + titles=None, + axes=None, + cmap="RdBu_r", + colorbar=True, + mask=None, + mask_style=None, + mask_cmap="Greys", + mask_alpha=0.25, + time_unit="s", + show_names=None, + group_by=None, + sphere=None, + ): + return plot_evoked_image( + self, + picks=picks, + exclude=exclude, + unit=unit, + show=show, + clim=clim, + xlim=xlim, + proj=proj, + units=units, + scalings=scalings, + titles=titles, + axes=axes, + cmap=cmap, + colorbar=colorbar, + mask=mask, + mask_style=mask_style, + mask_cmap=mask_cmap, + mask_alpha=mask_alpha, + time_unit=time_unit, + show_names=show_names, + group_by=group_by, + sphere=sphere, + ) + + @copy_function_doc_to_method_doc(plot_evoked_topo) + def plot_topo( + self, + layout=None, + layout_scale=0.945, + color=None, + border="none", + ylim=None, + scalings=None, + title=None, + proj=False, + vline=(0.0,), + fig_background=None, + merge_grads=False, + legend=True, + axes=None, + background_color="w", + noise_cov=None, + exclude="bads", + select=False, + show=True, + ): + """. + + Notes + ----- + .. versionadded:: 0.10.0 + """ + return plot_evoked_topo( + self, + layout=layout, + layout_scale=layout_scale, + color=color, + border=border, + ylim=ylim, + scalings=scalings, + title=title, + proj=proj, + vline=vline, + fig_background=fig_background, + merge_grads=merge_grads, + legend=legend, + axes=axes, + background_color=background_color, + noise_cov=noise_cov, + exclude=exclude, + select=select, + show=show, + ) + + @copy_function_doc_to_method_doc(plot_evoked_topomap) + def plot_topomap( + self, + times="auto", + *, + average=None, + ch_type=None, + scalings=None, + proj=False, + sensors=True, + show_names=False, + mask=None, + mask_params=None, + contours=6, + outlines="head", + sphere=None, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + border=_BORDER_DEFAULT, + res=64, + size=1, + cmap=None, + vlim=(None, None), + cnorm=None, + colorbar=True, + cbar_fmt="%3.1f", + units=None, + axes=None, + time_unit="s", + time_format=None, + nrows=1, + ncols="auto", + show=True, + ): + return plot_evoked_topomap( + self, + times=times, + ch_type=ch_type, + vlim=vlim, + cmap=cmap, + cnorm=cnorm, + sensors=sensors, + colorbar=colorbar, + scalings=scalings, + units=units, + res=res, + size=size, + cbar_fmt=cbar_fmt, + time_unit=time_unit, + time_format=time_format, + proj=proj, + show=show, + show_names=show_names, + mask=mask, + mask_params=mask_params, + outlines=outlines, + contours=contours, + image_interp=image_interp, + average=average, + axes=axes, + extrapolate=extrapolate, + sphere=sphere, + border=border, + nrows=nrows, + ncols=ncols, + ) + + @copy_function_doc_to_method_doc(plot_evoked_field) + def plot_field( + self, + surf_maps, + time=None, + time_label="t = %0.0f ms", + n_jobs=None, + fig=None, + vmax=None, + n_contours=21, + *, + show_density=True, + alpha=None, + interpolation="nearest", + interaction="terrain", + time_viewer="auto", + verbose=None, + ): + return plot_evoked_field( + self, + surf_maps, + time=time, + time_label=time_label, + n_jobs=n_jobs, + fig=fig, + vmax=vmax, + n_contours=n_contours, + show_density=show_density, + alpha=alpha, + interpolation=interpolation, + interaction=interaction, + time_viewer=time_viewer, + verbose=verbose, + ) + + @copy_function_doc_to_method_doc(plot_evoked_white) + def plot_white( + self, + noise_cov, + show=True, + rank=None, + time_unit="s", + sphere=None, + axes=None, + *, + spatial_colors="auto", + verbose=None, + ): + return plot_evoked_white( + self, + noise_cov=noise_cov, + rank=rank, + show=show, + time_unit=time_unit, + sphere=sphere, + axes=axes, + spatial_colors=spatial_colors, + verbose=verbose, + ) + + @copy_function_doc_to_method_doc(plot_evoked_joint) + def plot_joint( + self, + times="peaks", + title="", + picks=None, + exclude="bads", + show=True, + ts_args=None, + topomap_args=None, + ): + return plot_evoked_joint( + self, + times=times, + title=title, + picks=picks, + exclude=exclude, + show=show, + ts_args=ts_args, + topomap_args=topomap_args, + ) + + @fill_doc + def animate_topomap( + self, + ch_type=None, + times=None, + frame_rate=None, + butterfly=False, + blit=True, + show=True, + time_unit="s", + sphere=None, + *, + image_interp=_INTERPOLATION_DEFAULT, + extrapolate=_EXTRAPOLATE_DEFAULT, + vmin=None, + vmax=None, + verbose=None, + ): + """Make animation of evoked data as topomap timeseries. + + The animation can be paused/resumed with left mouse button. + Left and right arrow keys can be used to move backward or forward + in time. + + Parameters + ---------- + ch_type : str | None + Channel type to plot. Accepted data types: 'mag', 'grad', 'eeg', + 'hbo', 'hbr', 'fnirs_cw_amplitude', + 'fnirs_fd_ac_amplitude', 'fnirs_fd_phase', and 'fnirs_od'. + If None, first available channel type from the above list is used. + Defaults to None. + times : array of float | None + The time points to plot. If None, 10 evenly spaced samples are + calculated over the evoked time series. Defaults to None. + frame_rate : int | None + Frame rate for the animation in Hz. If None, + frame rate = sfreq / 10. Defaults to None. + butterfly : bool + Whether to plot the data as butterfly plot under the topomap. + Defaults to False. + blit : bool + Whether to use blit to optimize drawing. In general, it is + recommended to use blit in combination with ``show=True``. If you + intend to save the animation it is better to disable blit. + Defaults to True. + show : bool + Whether to show the animation. Defaults to True. + time_unit : str + The units for the time axis, can be "ms" (default in 0.16) + or "s" (will become the default in 0.17). + + .. versionadded:: 0.16 + %(sphere_topomap_auto)s + %(image_interp_topomap)s + %(extrapolate_topomap)s + + .. versionadded:: 0.22 + %(vmin_vmax_topomap)s + + .. versionadded:: 1.1.0 + %(verbose)s + + Returns + ------- + fig : instance of matplotlib.figure.Figure + The figure. + anim : instance of matplotlib.animation.FuncAnimation + Animation of the topomap. + + Notes + ----- + .. versionadded:: 0.12.0 + """ + return _topomap_animation( + self, + ch_type=ch_type, + times=times, + frame_rate=frame_rate, + butterfly=butterfly, + blit=blit, + show=show, + time_unit=time_unit, + sphere=sphere, + image_interp=image_interp, + extrapolate=extrapolate, + vmin=vmin, + vmax=vmax, + verbose=verbose, + ) + + def as_type(self, ch_type="grad", mode="fast"): + """Compute virtual evoked using interpolated fields. + + .. Warning:: Using virtual evoked to compute inverse can yield + unexpected results. The virtual channels have ``'_v'`` appended + at the end of the names to emphasize that the data contained in + them are interpolated. + + Parameters + ---------- + ch_type : str + The destination channel type. It can be 'mag' or 'grad'. + mode : str + Either ``'accurate'`` or ``'fast'``, determines the quality of the + Legendre polynomial expansion used. ``'fast'`` should be sufficient + for most applications. + + Returns + ------- + evoked : instance of mne.Evoked + The transformed evoked object containing only virtual channels. + + Notes + ----- + This method returns a copy and does not modify the data it + operates on. It also returns an EvokedArray instance. + + .. versionadded:: 0.9.0 + """ + from .forward import _as_meg_type_inst + + return _as_meg_type_inst(self, ch_type=ch_type, mode=mode) + + @fill_doc + def detrend(self, order=1, picks=None): + """Detrend data. + + This function operates in-place. + + Parameters + ---------- + order : int + Either 0 or 1, the order of the detrending. 0 is a constant + (DC) detrend, 1 is a linear detrend. + %(picks_good_data)s + + Returns + ------- + evoked : instance of Evoked + The detrended evoked object. + """ + picks = _picks_to_idx(self.info, picks) + self.data[picks] = detrend(self.data[picks], order, axis=-1) + return self + + def copy(self): + """Copy the instance of evoked. + + Returns + ------- + evoked : instance of Evoked + A copy of the object. + """ + evoked = deepcopy(self) + return evoked + + def __neg__(self): + """Negate channel responses. + + Returns + ------- + evoked_neg : instance of Evoked + The Evoked instance with channel data negated and '-' + prepended to the comment. + """ + out = self.copy() + out.data *= -1 + + if out.comment is not None and " + " in out.comment: + out.comment = f"({out.comment})" # multiple conditions in evoked + out.comment = f"- {out.comment or 'unknown'}" + return out + + def get_peak( + self, + ch_type=None, + tmin=None, + tmax=None, + mode="abs", + time_as_index=False, + merge_grads=False, + return_amplitude=False, + *, + strict=True, + ): + """Get location and latency of peak amplitude. + + Parameters + ---------- + ch_type : str | None + The channel type to use. Defaults to None. If more than one channel + type is present in the data, this value **must** be provided. + tmin : float | None + The minimum point in time to be considered for peak getting. + If None (default), the beginning of the data is used. + tmax : float | None + The maximum point in time to be considered for peak getting. + If None (default), the end of the data is used. + mode : 'pos' | 'neg' | 'abs' + How to deal with the sign of the data. If 'pos' only positive + values will be considered. If 'neg' only negative values will + be considered. If 'abs' absolute values will be considered. + Defaults to 'abs'. + time_as_index : bool + Whether to return the time index instead of the latency in seconds. + merge_grads : bool + If True, compute peak from merged gradiometer data. + return_amplitude : bool + If True, return also the amplitude at the maximum response. + + .. versionadded:: 0.16 + strict : bool + If True, raise an error if values are all positive when detecting + a minimum (mode='neg'), or all negative when detecting a maximum + (mode='pos'). Defaults to True. + + .. versionadded:: 1.7 + + Returns + ------- + ch_name : str + The channel exhibiting the maximum response. + latency : float | int + The time point of the maximum response, either latency in seconds + or index. + amplitude : float + The amplitude of the maximum response. Only returned if + return_amplitude is True. + + .. versionadded:: 0.16 + """ # noqa: E501 + supported = ( + "mag", + "grad", + "eeg", + "seeg", + "dbs", + "ecog", + "misc", + "None", + ) + _FNIRS_CH_TYPES_SPLIT + types_used = self.get_channel_types(unique=True, only_data_chs=True) + + _check_option("ch_type", str(ch_type), supported) + + if ch_type is not None and ch_type not in types_used: + raise ValueError( + f'Channel type "{ch_type}" not found in this evoked object.' + ) + + elif len(types_used) > 1 and ch_type is None: + raise RuntimeError( + 'Multiple data channel types found. Please pass the "ch_type" ' + "parameter." + ) + + if merge_grads: + if ch_type != "grad": + raise ValueError('Channel type must be "grad" for merge_grads') + elif mode == "neg": + raise ValueError( + "Negative mode (mode=neg) does not make sense with merge_grads=True" + ) + + meg = eeg = misc = seeg = dbs = ecog = fnirs = False + picks = None + if ch_type in ("mag", "grad"): + meg = ch_type + elif ch_type == "eeg": + eeg = True + elif ch_type == "misc": + misc = True + elif ch_type == "seeg": + seeg = True + elif ch_type == "dbs": + dbs = True + elif ch_type == "ecog": + ecog = True + elif ch_type in _FNIRS_CH_TYPES_SPLIT: + fnirs = ch_type + + if ch_type is not None: + if merge_grads: + picks = _pair_grad_sensors(self.info, topomap_coords=False) + else: + picks = pick_types( + self.info, + meg=meg, + eeg=eeg, + misc=misc, + seeg=seeg, + ecog=ecog, + ref_meg=False, + fnirs=fnirs, + dbs=dbs, + ) + data = self.data + ch_names = self.ch_names + + if picks is not None: + data = data[picks] + ch_names = [ch_names[k] for k in picks] + + if merge_grads: + data, _ = _merge_ch_data(data, ch_type, []) + ch_names = [ch_name[:-1] + "X" for ch_name in ch_names[::2]] + + ch_idx, time_idx, max_amp = _get_peak( + data, + self.times, + tmin, + tmax, + mode, + strict=strict, + ) + + out = (ch_names[ch_idx], time_idx if time_as_index else self.times[time_idx]) + + if return_amplitude: + out += (max_amp,) + + return out + + @verbose + def compute_psd( + self, + method="multitaper", + fmin=0, + fmax=np.inf, + tmin=None, + tmax=None, + picks=None, + proj=False, + remove_dc=True, + exclude=(), + *, + n_jobs=1, + verbose=None, + **method_kw, + ): + """Perform spectral analysis on sensor data. + + Parameters + ---------- + %(method_psd)s + Default is ``'multitaper'``. + %(fmin_fmax_psd)s + %(tmin_tmax_psd)s + %(picks_good_data_noref)s + %(proj_psd)s + %(remove_dc)s + %(exclude_psd)s + %(n_jobs)s + %(verbose)s + %(method_kw_psd)s + + Returns + ------- + spectrum : instance of Spectrum + The spectral representation of the data. + + Notes + ----- + .. versionadded:: 1.2 + + References + ---------- + .. footbibliography:: + """ + method = _validate_method(method, type(self).__name__) + self._set_legacy_nfft_default(tmin, tmax, method, method_kw) + + return Spectrum( + self, + method=method, + fmin=fmin, + fmax=fmax, + tmin=tmin, + tmax=tmax, + picks=picks, + exclude=exclude, + proj=proj, + remove_dc=remove_dc, + reject_by_annotation=False, + n_jobs=n_jobs, + verbose=verbose, + **method_kw, + ) + + @verbose + def compute_tfr( + self, + method, + freqs, + *, + tmin=None, + tmax=None, + picks=None, + proj=False, + output="power", + decim=1, + n_jobs=None, + verbose=None, + **method_kw, + ): + """Compute a time-frequency representation of evoked data. + + Parameters + ---------- + %(method_tfr)s + %(freqs_tfr)s + %(tmin_tmax_psd)s + %(picks_good_data_noref)s + %(proj_psd)s + %(output_compute_tfr)s + %(decim_tfr)s + %(n_jobs)s + %(verbose)s + %(method_kw_tfr)s + + Returns + ------- + tfr : instance of AverageTFR + The time-frequency-resolved power estimates of the data. + + Notes + ----- + .. versionadded:: 1.7 + + References + ---------- + .. footbibliography:: + """ + _check_option("output", output, ("power", "phase", "complex")) + method_kw["output"] = output + return AverageTFR( + inst=self, + method=method, + freqs=freqs, + tmin=tmin, + tmax=tmax, + picks=picks, + proj=proj, + decim=decim, + n_jobs=n_jobs, + verbose=verbose, + **method_kw, + ) + + @verbose + def plot_psd( + self, + fmin=0, + fmax=np.inf, + tmin=None, + tmax=None, + picks=None, + proj=False, + *, + method="auto", + average=False, + dB=True, + estimate="power", + xscale="linear", + area_mode="std", + area_alpha=0.33, + color="black", + line_alpha=None, + spatial_colors=True, + sphere=None, + exclude="bads", + ax=None, + show=True, + n_jobs=1, + verbose=None, + **method_kw, + ): + """%(plot_psd_doc)s. + + Parameters + ---------- + %(fmin_fmax_psd)s + %(tmin_tmax_psd)s + %(picks_good_data_noref)s + %(proj_psd)s + %(method_plot_psd_auto)s + %(average_plot_psd)s + %(dB_plot_psd)s + %(estimate_plot_psd)s + %(xscale_plot_psd)s + %(area_mode_plot_psd)s + %(area_alpha_plot_psd)s + %(color_plot_psd)s + %(line_alpha_plot_psd)s + %(spatial_colors_psd)s + %(sphere_topomap_auto)s + + .. versionadded:: 0.22.0 + exclude : list of str | 'bads' + Channels names to exclude from being shown. If 'bads', the bad + channels are excluded. Pass an empty list to plot all channels + (including channels marked "bad", if any). + + .. versionadded:: 0.24.0 + %(ax_plot_psd)s + %(show)s + %(n_jobs)s + %(verbose)s + %(method_kw_psd)s + + Returns + ------- + fig : instance of Figure + Figure with frequency spectra of the data channels. + + Notes + ----- + %(notes_plot_psd_meth)s + """ + return super().plot_psd( + fmin=fmin, + fmax=fmax, + tmin=tmin, + tmax=tmax, + picks=picks, + proj=proj, + reject_by_annotation=False, + method=method, + average=average, + dB=dB, + estimate=estimate, + xscale=xscale, + area_mode=area_mode, + area_alpha=area_alpha, + color=color, + line_alpha=line_alpha, + spatial_colors=spatial_colors, + sphere=sphere, + exclude=exclude, + ax=ax, + show=show, + n_jobs=n_jobs, + verbose=verbose, + **method_kw, + ) + + @verbose + def to_data_frame( + self, + picks=None, + index=None, + scalings=None, + copy=True, + long_format=False, + time_format=None, + *, + verbose=None, + ): + """Export data in tabular structure as a pandas DataFrame. + + Channels are converted to columns in the DataFrame. By default, + an additional column "time" is added, unless ``index='time'`` + (in which case time values form the DataFrame's index). + + Parameters + ---------- + %(picks_all)s + %(index_df_evk)s + Defaults to ``None``. + %(scalings_df)s + %(copy_df)s + %(long_format_df_raw)s + %(time_format_df)s + + .. versionadded:: 0.20 + %(verbose)s + + Returns + ------- + %(df_return)s + """ + # check pandas once here, instead of in each private utils function + pd = _check_pandas_installed() # noqa + # arg checking + valid_index_args = ["time"] + valid_time_formats = ["ms", "timedelta"] + index = _check_pandas_index_arguments(index, valid_index_args) + time_format = _check_time_format(time_format, valid_time_formats) + # get data + picks = _picks_to_idx(self.info, picks, "all", exclude=()) + data = self.data[picks, :] + times = self.times + data = data.T + if copy: + data = data.copy() + data = _scale_dataframe_data(self, data, picks, scalings) + # prepare extra columns / multiindex + mindex = list() + times = _convert_times(times, time_format, meas_date=self.info["meas_date"]) + mindex.append(("time", times)) + # build DataFrame + df = _build_data_frame( + self, data, picks, long_format, mindex, index, default_index=["time"] + ) + return df + + +@fill_doc +class EvokedArray(Evoked): + """Evoked object from numpy array. + + Parameters + ---------- + data : array of shape (n_channels, n_times) + The channels' evoked response. See notes for proper units of measure. + %(info_not_none)s Consider using :func:`mne.create_info` to populate this + structure. + tmin : float + Start time before event. Defaults to 0. + comment : str + Comment on dataset. Can be the condition. Defaults to ''. + nave : int + Number of averaged epochs. Defaults to 1. + kind : str + Type of data, either average or standard_error. Defaults to 'average'. + %(baseline_evoked)s + Defaults to ``None``, i.e. no baseline correction. + + .. versionadded:: 0.23 + %(verbose)s + + See Also + -------- + EpochsArray, io.RawArray, create_info + + Notes + ----- + Proper units of measure: + + * V: eeg, eog, seeg, dbs, emg, ecg, bio, ecog + * T: mag + * T/m: grad + * M: hbo, hbr + * Am: dipole + * AU: misc + """ + + @verbose + def __init__( + self, + data, + info, + tmin=0.0, + comment="", + nave=1, + kind="average", + baseline=None, + *, + verbose=None, + ): + dtype = np.complex128 if np.iscomplexobj(data) else np.float64 + data = np.asanyarray(data, dtype=dtype) + + if data.ndim != 2: + raise ValueError( + "Data must be a 2D array of shape (n_channels, n_samples), got shape " + f"{data.shape}" + ) + + if len(info["ch_names"]) != np.shape(data)[0]: + raise ValueError( + f"Info ({len(info['ch_names'])}) and data ({np.shape(data)[0]}) must " + "have same number of channels." + ) + + self.data = data + + self.first = int(round(tmin * info["sfreq"])) + self.last = self.first + np.shape(data)[-1] - 1 + self._set_times( + np.arange(self.first, self.last + 1, dtype=np.float64) / info["sfreq"] + ) + self._raw_times = self.times.copy() + self._decim = 1 + self.info = info.copy() # do not modify original info + self.nave = nave + self.kind = kind + self.comment = comment + self.picks = None + self.preload = True + self._projector = None + _validate_type(self.kind, "str", "kind") + if self.kind not in _aspect_dict: + raise ValueError( + f'unknown kind "{self.kind}", should be "average" or "standard_error"' + ) + self._aspect_kind = _aspect_dict[self.kind] + + self.baseline = baseline + if self.baseline is not None: # omit log msg if not baselining + self.apply_baseline(self.baseline) + self._filename = None + + +def _get_entries(fid, evoked_node, allow_maxshield=False): + """Get all evoked entries.""" + comments = list() + aspect_kinds = list() + for ev in evoked_node: + for k in range(ev["nent"]): + my_kind = ev["directory"][k].kind + pos = ev["directory"][k].pos + if my_kind == FIFF.FIFF_COMMENT: + tag = read_tag(fid, pos) + comments.append(tag.data) + my_aspect = _get_aspect(ev, allow_maxshield)[0] + for k in range(my_aspect["nent"]): + my_kind = my_aspect["directory"][k].kind + pos = my_aspect["directory"][k].pos + if my_kind == FIFF.FIFF_ASPECT_KIND: + tag = read_tag(fid, pos) + aspect_kinds.append(int(tag.data.item())) + comments = np.atleast_1d(comments) + aspect_kinds = np.atleast_1d(aspect_kinds) + if len(comments) != len(aspect_kinds) or len(comments) == 0: + fid.close() + raise ValueError("Dataset names in FIF file could not be found.") + t = [_aspect_rev[a] for a in aspect_kinds] + t = ['"' + c + '" (' + tt + ")" for tt, c in zip(t, comments)] + t = "\n".join(t) + return comments, aspect_kinds, t + + +def _get_aspect(evoked, allow_maxshield): + """Get Evoked data aspect.""" + from .io.base import _check_maxshield + + is_maxshield = False + aspect = dir_tree_find(evoked, FIFF.FIFFB_ASPECT) + if len(aspect) == 0: + _check_maxshield(allow_maxshield) + aspect = dir_tree_find(evoked, FIFF.FIFFB_IAS_ASPECT) + is_maxshield = True + if len(aspect) > 1: + logger.info("Multiple data aspects found. Taking first one.") + return aspect[0], is_maxshield + + +def _get_evoked_node(fname): + """Get info in evoked file.""" + f, tree, _ = fiff_open(fname) + with f as fid: + _, meas = read_meas_info(fid, tree, verbose=False) + evoked_node = dir_tree_find(meas, FIFF.FIFFB_EVOKED) + return evoked_node + + +def _check_evokeds_ch_names_times(all_evoked): + evoked = all_evoked[0] + ch_names = evoked.ch_names + for ii, ev in enumerate(all_evoked[1:]): + if ev.ch_names != ch_names: + if set(ev.ch_names) != set(ch_names): + raise ValueError(f"{evoked} and {ev} do not contain the same channels.") + else: + warn("Order of channels differs, reordering channels ...") + ev = ev.copy() + ev.reorder_channels(ch_names) + all_evoked[ii + 1] = ev + if not np.max(np.abs(ev.times - evoked.times)) < 1e-7: + raise ValueError(f"{evoked} and {ev} do not contain the same time instants") + return all_evoked + + +def combine_evoked(all_evoked, weights): + """Merge evoked data by weighted addition or subtraction. + + Each `~mne.Evoked` in ``all_evoked`` should have the same channels and the + same time instants. Subtraction can be performed by passing + ``weights=[1, -1]``. + + .. Warning:: + Other than cases like simple subtraction mentioned above (where all + weights are ``-1`` or ``1``), if you provide numeric weights instead of using + ``'equal'`` or ``'nave'``, the resulting `~mne.Evoked` object's + ``.nave`` attribute (which is used to scale noise covariance when + applying the inverse operator) may not be suitable for inverse imaging. + + Parameters + ---------- + all_evoked : list of Evoked + The evoked datasets. + weights : list of float | ``'equal'`` | ``'nave'`` + The weights to apply to the data of each evoked instance, or a string + describing the weighting strategy to apply: ``'nave'`` computes + sum-to-one weights proportional to each object's ``nave`` attribute; + ``'equal'`` weights each `~mne.Evoked` by ``1 / len(all_evoked)``. + + Returns + ------- + evoked : Evoked + The new evoked data. + + Notes + ----- + .. versionadded:: 0.9.0 + """ + naves = np.array([evk.nave for evk in all_evoked], float) + if isinstance(weights, str): + _check_option("weights", weights, ["nave", "equal"]) + if weights == "nave": + weights = naves / naves.sum() + else: + weights = np.ones_like(naves) / len(naves) + else: + weights = np.array(weights, float) + + if weights.ndim != 1 or weights.size != len(all_evoked): + raise ValueError("weights must be the same size as all_evoked") + + # cf. https://en.wikipedia.org/wiki/Weighted_arithmetic_mean, section on + # "weighted sample variance". The variance of a weighted sample mean is: + # + # σ² = w₁² σ₁² + w₂² σ₂² + ... + wₙ² σₙ² + # + # We estimate the variance of each evoked instance as 1 / nave to get: + # + # σ² = w₁² / nave₁ + w₂² / nave₂ + ... + wₙ² / naveₙ + # + # And our resulting nave is the reciprocal of this: + new_nave = 1.0 / np.sum(weights**2 / naves) + # This general formula is equivalent to formulae in Matti's manual + # (pp 128-129), where: + # new_nave = sum(naves) when weights='nave' and + # new_nave = 1. / sum(1. / naves) when weights are all 1. + + all_evoked = _check_evokeds_ch_names_times(all_evoked) + evoked = all_evoked[0].copy() + + # use union of bad channels + bads = list(set(b for e in all_evoked for b in e.info["bads"])) + evoked.info["bads"] = bads + evoked.data = sum(w * e.data for w, e in zip(weights, all_evoked)) + evoked.nave = new_nave + + comment = "" + for idx, (w, e) in enumerate(zip(weights, all_evoked)): + # pick sign + sign = "" if w >= 0 else "-" + # format weight + weight = "" if np.isclose(abs(w), 1.0) else f"{abs(w):0.3f}" + # format multiplier + multiplier = " × " if weight else "" + # format comment + if e.comment is not None and " + " in e.comment: # multiple conditions + this_comment = f"({e.comment})" + else: + this_comment = f"{e.comment or 'unknown'}" + # assemble everything + if idx == 0: + comment += f"{sign}{weight}{multiplier}{this_comment}" + else: + comment += f" {sign or '+'} {weight}{multiplier}{this_comment}" + # special-case: combine_evoked([e1, -e2], [1, -1]) + evoked.comment = comment.replace(" - - ", " + ") + return evoked + + +@verbose +def read_evokeds( + fname, + condition=None, + baseline=None, + kind="average", + proj=True, + allow_maxshield=False, + verbose=None, +) -> list[Evoked] | Evoked: + """Read evoked dataset(s). + + Parameters + ---------- + fname : path-like + The filename, which should end with ``-ave.fif`` or ``-ave.fif.gz``. + condition : int or str | list of int or str | None + The index or list of indices of the evoked dataset to read. FIF files + can contain multiple datasets. If None, all datasets are returned as a + list. + %(baseline_evoked)s + If ``None`` (default), do not apply baseline correction. + + .. note:: Note that if the read `~mne.Evoked` objects have already + been baseline-corrected, the data retrieved from disk will + **always** be baseline-corrected (in fact, only the + baseline-corrected version of the data will be saved, so + there is no way to undo this procedure). Only **after** the + data has been loaded, a custom (additional) baseline + correction **may** be optionally applied by passing a tuple + here. Passing ``None`` will **not** remove an existing + baseline correction, but merely omit the optional, additional + baseline correction. + kind : str + Either ``'average'`` or ``'standard_error'``, the type of data to read. + proj : bool + If False, available projectors won't be applied to the data. + allow_maxshield : bool | str (default False) + If True, allow loading of data that has been recorded with internal + active compensation (MaxShield). Data recorded with MaxShield should + generally not be loaded directly, but should first be processed using + SSS/tSSS to remove the compensation signals that may also affect brain + activity. Can also be ``"yes"`` to load without eliciting a warning. + %(verbose)s + + Returns + ------- + evoked : Evoked or list of Evoked + The evoked dataset(s); one `~mne.Evoked` if ``condition`` is an + integer or string; or a list of `~mne.Evoked` if ``condition`` is + ``None`` or a list. + + See Also + -------- + write_evokeds + + Notes + ----- + .. versionchanged:: 0.23 + If the read `~mne.Evoked` objects had been baseline-corrected before + saving, this will be reflected in their ``baseline`` attribute after + reading. + """ + fname = _check_fname(fname, overwrite="read", must_exist=True) + check_fname(fname, "evoked", ("-ave.fif", "-ave.fif.gz", "_ave.fif", "_ave.fif.gz")) + logger.info(f"Reading {fname} ...") + return_list = True + if condition is None: + evoked_node = _get_evoked_node(fname) + condition = range(len(evoked_node)) + elif not isinstance(condition, list): + condition = [condition] + return_list = False + + out = [] + for c in condition: + evoked = Evoked( + fname, + c, + kind=kind, + proj=proj, + allow_maxshield=allow_maxshield, + verbose=verbose, + ) + if baseline is None and evoked.baseline is None: + logger.info(_log_rescale(None)) + elif baseline is None and evoked.baseline is not None: + # Don't touch an existing baseline + bmin, bmax = evoked.baseline + logger.info( + f"Loaded Evoked data is baseline-corrected " + f"(baseline: [{bmin:g}, {bmax:g}] s)" + ) + else: + evoked.apply_baseline(baseline) + out.append(evoked) + + return out if return_list else out[0] + + +def _read_evoked(fname, condition=None, kind="average", allow_maxshield=False): + """Read evoked data from a FIF file.""" + if fname is None: + raise ValueError("No evoked filename specified") + + f, tree, _ = fiff_open(fname) + with f as fid: + # Read the measurement info + info, meas = read_meas_info(fid, tree, clean_bads=True) + + # Locate the data of interest + processed = dir_tree_find(meas, FIFF.FIFFB_PROCESSED_DATA) + if len(processed) == 0: + raise ValueError("Could not find processed data") + + evoked_node = dir_tree_find(meas, FIFF.FIFFB_EVOKED) + if len(evoked_node) == 0: + raise ValueError("Could not find evoked data") + + # find string-based entry + if isinstance(condition, str): + if kind not in _aspect_dict.keys(): + raise ValueError('kind must be "average" or "standard_error"') + + comments, aspect_kinds, t = _get_entries(fid, evoked_node, allow_maxshield) + goods = np.isin(comments, [condition]) & np.isin( + aspect_kinds, [_aspect_dict[kind]] + ) + found_cond = np.where(goods)[0] + if len(found_cond) != 1: + raise ValueError( + f'condition "{condition}" ({kind}) not found, out of found ' + f"datasets:\n{t}" + ) + condition = found_cond[0] + elif condition is None: + if len(evoked_node) > 1: + _, _, conditions = _get_entries(fid, evoked_node, allow_maxshield) + raise TypeError( + "Evoked file has more than one condition, the condition parameters " + f"must be specified from:\n{conditions}" + ) + else: + condition = 0 + + if condition >= len(evoked_node) or condition < 0: + raise ValueError("Data set selector out of range") + + my_evoked = evoked_node[condition] + + # Identify the aspects + with info._unlock(): + my_aspect, info["maxshield"] = _get_aspect(my_evoked, allow_maxshield) + + # Now find the data in the evoked block + nchan = 0 + sfreq = -1 + chs = [] + baseline = bmin = bmax = None + comment = last = first = first_time = nsamp = None + for k in range(my_evoked["nent"]): + my_kind = my_evoked["directory"][k].kind + pos = my_evoked["directory"][k].pos + if my_kind == FIFF.FIFF_COMMENT: + tag = read_tag(fid, pos) + comment = tag.data + elif my_kind == FIFF.FIFF_FIRST_SAMPLE: + tag = read_tag(fid, pos) + first = int(tag.data.item()) + elif my_kind == FIFF.FIFF_LAST_SAMPLE: + tag = read_tag(fid, pos) + last = int(tag.data.item()) + elif my_kind == FIFF.FIFF_NCHAN: + tag = read_tag(fid, pos) + nchan = int(tag.data.item()) + elif my_kind == FIFF.FIFF_SFREQ: + tag = read_tag(fid, pos) + sfreq = float(tag.data.item()) + elif my_kind == FIFF.FIFF_CH_INFO: + tag = read_tag(fid, pos) + chs.append(tag.data) + elif my_kind == FIFF.FIFF_FIRST_TIME: + tag = read_tag(fid, pos) + first_time = float(tag.data.item()) + elif my_kind == FIFF.FIFF_NO_SAMPLES: + tag = read_tag(fid, pos) + nsamp = int(tag.data.item()) + elif my_kind == FIFF.FIFF_MNE_BASELINE_MIN: + tag = read_tag(fid, pos) + bmin = float(tag.data.item()) + elif my_kind == FIFF.FIFF_MNE_BASELINE_MAX: + tag = read_tag(fid, pos) + bmax = float(tag.data.item()) + + if comment is None: + comment = "No comment" + + if bmin is not None or bmax is not None: + # None's should've been replaced with floats + assert bmin is not None and bmax is not None + baseline = (bmin, bmax) + + # Local channel information? + if nchan > 0: + if chs is None: + raise ValueError( + "Local channel information was not found when it was expected." + ) + + if len(chs) != nchan: + raise ValueError( + "Number of channels and number of channel definitions are different" + ) + + ch_names_mapping = _read_extended_ch_info(chs, my_evoked, fid) + info["chs"] = chs + info["bads"][:] = _rename_list(info["bads"], ch_names_mapping) + logger.info( + f" Found channel information in evoked data. nchan = {nchan}" + ) + if sfreq > 0: + info["sfreq"] = sfreq + + # Read the data in the aspect block + nave = 1 + epoch = [] + for k in range(my_aspect["nent"]): + kind = my_aspect["directory"][k].kind + pos = my_aspect["directory"][k].pos + if kind == FIFF.FIFF_COMMENT: + tag = read_tag(fid, pos) + comment = tag.data + elif kind == FIFF.FIFF_ASPECT_KIND: + tag = read_tag(fid, pos) + aspect_kind = int(tag.data.item()) + elif kind == FIFF.FIFF_NAVE: + tag = read_tag(fid, pos) + nave = int(tag.data.item()) + elif kind == FIFF.FIFF_EPOCH: + tag = read_tag(fid, pos) + epoch.append(tag) + + nepoch = len(epoch) + if nepoch != 1 and nepoch != info["nchan"]: + raise ValueError( + "Number of epoch tags is unreasonable " + f"(nepoch = {nepoch} nchan = {info['nchan']})" + ) + + if nepoch == 1: + # Only one epoch + data = epoch[0].data + # May need a transpose if the number of channels is one + if data.shape[1] == 1 and info["nchan"] == 1: + data = data.T + else: + # Put the old style epochs together + data = np.concatenate([e.data[None, :] for e in epoch], axis=0) + if np.isrealobj(data): + data = data.astype(np.float64) + else: + data = data.astype(np.complex128) + + if first_time is not None and nsamp is not None: + times = first_time + np.arange(nsamp) / info["sfreq"] + elif first is not None: + nsamp = last - first + 1 + times = np.arange(first, last + 1) / info["sfreq"] + else: + raise RuntimeError("Could not read time parameters") + del first, last + if nsamp is not None and data.shape[1] != nsamp: + raise ValueError( + f"Incorrect number of samples ({data.shape[1]} instead of {nsamp})" + ) + logger.info(" Found the data of interest:") + logger.info( + f" t = {1000 * times[0]:10.2f} ... {1000 * times[-1]:10.2f} ms (" + f"{comment})" + ) + if info["comps"] is not None: + logger.info( + f" {len(info['comps'])} CTF compensation matrices available" + ) + logger.info(f" nave = {nave} - aspect type = {aspect_kind}") + + # Calibrate + cals = np.array( + [ + info["chs"][k]["cal"] * info["chs"][k].get("scale", 1.0) + for k in range(info["nchan"]) + ] + ) + data *= cals[:, np.newaxis] + + return info, nave, aspect_kind, comment, times, data, baseline + + +@verbose +def write_evokeds(fname, evoked, *, on_mismatch="raise", overwrite=False, verbose=None): + """Write an evoked dataset to a file. + + Parameters + ---------- + fname : path-like + The file name, which should end with ``-ave.fif`` or ``-ave.fif.gz``. + evoked : Evoked instance, or list of Evoked instances + The evoked dataset, or list of evoked datasets, to save in one file. + Note that the measurement info from the first evoked instance is used, + so be sure that information matches. + %(on_mismatch_info)s + %(overwrite)s + + .. versionadded:: 1.0 + %(verbose)s + + .. versionadded:: 0.24 + + See Also + -------- + read_evokeds + + Notes + ----- + .. versionchanged:: 0.23 + Information on baseline correction will be stored with each individual + `~mne.Evoked` object, and will be restored when reading the data again + via `mne.read_evokeds`. + """ + _write_evokeds(fname, evoked, on_mismatch=on_mismatch, overwrite=overwrite) + + +def _write_evokeds(fname, evoked, check=True, *, on_mismatch="raise", overwrite=False): + """Write evoked data.""" + from .dipole import DipoleFixed # avoid circular import + + fname = _check_fname(fname=fname, overwrite=overwrite) + if check: + check_fname( + fname, "evoked", ("-ave.fif", "-ave.fif.gz", "_ave.fif", "_ave.fif.gz") + ) + + if not isinstance(evoked, list | tuple): + evoked = [evoked] + if not len(evoked): + raise ValueError("No evoked data to write") + + warned = False + # Create the file and save the essentials + with start_and_end_file(fname) as fid: + start_block(fid, FIFF.FIFFB_MEAS) + write_id(fid, FIFF.FIFF_BLOCK_ID) + if evoked[0].info["meas_id"] is not None: + write_id(fid, FIFF.FIFF_PARENT_BLOCK_ID, evoked[0].info["meas_id"]) + + # Write measurement info + write_meas_info(fid, evoked[0].info) + + # One or more evoked data sets + start_block(fid, FIFF.FIFFB_PROCESSED_DATA) + for ei, e in enumerate(evoked): + if ei: + _ensure_infos_match( + info1=evoked[0].info, + info2=e.info, + name=f"evoked[{ei}]", + on_mismatch=on_mismatch, + ) + start_block(fid, FIFF.FIFFB_EVOKED) + + # Comment is optional + if e.comment is not None and len(e.comment) > 0: + write_string(fid, FIFF.FIFF_COMMENT, e.comment) + + # First time, num. samples, first and last sample + write_float(fid, FIFF.FIFF_FIRST_TIME, e.times[0]) + write_int(fid, FIFF.FIFF_NO_SAMPLES, len(e.times)) + write_int(fid, FIFF.FIFF_FIRST_SAMPLE, e.first) + write_int(fid, FIFF.FIFF_LAST_SAMPLE, e.last) + + # Baseline + if not isinstance(e, DipoleFixed) and e.baseline is not None: + bmin, bmax = e.baseline + write_float(fid, FIFF.FIFF_MNE_BASELINE_MIN, bmin) + write_float(fid, FIFF.FIFF_MNE_BASELINE_MAX, bmax) + + # The evoked data itself + if e.info.get("maxshield"): + aspect = FIFF.FIFFB_IAS_ASPECT + else: + aspect = FIFF.FIFFB_ASPECT + start_block(fid, aspect) + + write_int(fid, FIFF.FIFF_ASPECT_KIND, e._aspect_kind) + # convert nave to integer to comply with FIFF spec + nave_int = int(round(e.nave)) + if nave_int != e.nave and not warned: + warn( + 'converting "nave" to integer before saving evoked; this ' + "can have a minor effect on the scale of source " + 'estimates that are computed using "nave".' + ) + warned = True + write_int(fid, FIFF.FIFF_NAVE, nave_int) + del nave_int + + decal = np.zeros((e.info["nchan"], 1)) + for k in range(e.info["nchan"]): + decal[k] = 1.0 / ( + e.info["chs"][k]["cal"] * e.info["chs"][k].get("scale", 1.0) + ) + + if np.iscomplexobj(e.data): + write_function = write_complex_float_matrix + else: + write_function = write_float_matrix + + write_function(fid, FIFF.FIFF_EPOCH, decal * e.data) + end_block(fid, aspect) + end_block(fid, FIFF.FIFFB_EVOKED) + + end_block(fid, FIFF.FIFFB_PROCESSED_DATA) + end_block(fid, FIFF.FIFFB_MEAS) + + +def _get_peak(data, times, tmin=None, tmax=None, mode="abs", *, strict=True): + """Get feature-index and time of maximum signal from 2D array. + + Note. This is a 'getter', not a 'finder'. For non-evoked type + data and continuous signals, please use proper peak detection algorithms. + + Parameters + ---------- + data : instance of numpy.ndarray (n_locations, n_times) + The data, either evoked in sensor or source space. + times : instance of numpy.ndarray (n_times) + The times in seconds. + tmin : float | None + The minimum point in time to be considered for peak getting. + tmax : float | None + The maximum point in time to be considered for peak getting. + mode : {'pos', 'neg', 'abs'} + How to deal with the sign of the data. If 'pos' only positive + values will be considered. If 'neg' only negative values will + be considered. If 'abs' absolute values will be considered. + Defaults to 'abs'. + strict : bool + If True, raise an error if values are all positive when detecting + a minimum (mode='neg'), or all negative when detecting a maximum + (mode='pos'). Defaults to True. + + Returns + ------- + max_loc : int + The index of the feature with the maximum value. + max_time : int + The time point of the maximum response, index. + max_amp : float + Amplitude of the maximum response. + """ + _check_option("mode", mode, ["abs", "neg", "pos"]) + + if tmin is None: + tmin = times[0] + if tmax is None: + tmax = times[-1] + + if tmin < times.min() or tmax > times.max(): + if tmin < times.min(): + param_name = "tmin" + param_val = tmin + else: + param_name = "tmax" + param_val = tmax + + raise ValueError( + f"{param_name} ({param_val}) is out of bounds. It must be " + f"between {times.min()} and {times.max()}" + ) + elif tmin > tmax: + raise ValueError(f"tmin ({tmin}) must be <= tmax ({tmax})") + + time_win = (times >= tmin) & (times <= tmax) + mask = np.ones_like(data).astype(bool) + mask[:, time_win] = False + + maxfun = np.argmax + if mode == "pos": + if strict and not np.any(data[~mask] > 0): + raise ValueError( + "No positive values encountered. Cannot operate in pos mode." + ) + elif mode == "neg": + if strict and not np.any(data[~mask] < 0): + raise ValueError( + "No negative values encountered. Cannot operate in neg mode." + ) + maxfun = np.argmin + + masked_index = np.ma.array(np.abs(data) if mode == "abs" else data, mask=mask) + + max_loc, max_time = np.unravel_index(maxfun(masked_index), data.shape) + + return max_loc, max_time, data[max_loc, max_time] diff --git a/mne-python/source/mne/export/__init__.py b/mne-python/source/mne/export/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7a07df656d6dbb8825dc02b58362091029b665b2 --- /dev/null +++ b/mne-python/source/mne/export/__init__.py @@ -0,0 +1,8 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Functions for exporting data to non-FIF formats.""" +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/export/__init__.pyi b/mne-python/source/mne/export/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..6cd2a374ef315c5ddc8c40423707ceeddb2e8a8d --- /dev/null +++ b/mne-python/source/mne/export/__init__.pyi @@ -0,0 +1,3 @@ +__all__ = ["export_epochs", "export_evokeds", "export_evokeds_mff", "export_raw"] +from ._egimff import export_evokeds_mff +from ._export import export_epochs, export_evokeds, export_raw diff --git a/mne-python/source/mne/export/_brainvision.py b/mne-python/source/mne/export/_brainvision.py new file mode 100644 index 0000000000000000000000000000000000000000..6503c540f415c7cbf1205cb7bcf22e5a42e38851 --- /dev/null +++ b/mne-python/source/mne/export/_brainvision.py @@ -0,0 +1,165 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +from pathlib import Path + +import numpy as np + +from mne.channels.channels import _unit2human +from mne.io.constants import FIFF +from mne.utils import _check_pybv_installed, warn + +_check_pybv_installed() +from pybv import write_brainvision # noqa: E402 + + +def _export_mne_raw(*, raw, fname, events=None, overwrite=False): + """Export raw data from MNE-Python. + + Parameters + ---------- + raw : mne.io.Raw + The raw data to export. + fname : str | pathlib.Path + The name of the file where raw data will be exported to. Must end with + ``".vhdr"``, and accompanying *.vmrk* and *.eeg* files will be written inside + the same directory. + events : np.ndarray | None + Events to be written to the marker file (*.vmrk*). If array, must be in + `MNE-Python format `_. If + ``None`` (default), events will be written based on ``raw.annotations``. + overwrite : bool + Whether or not to overwrite existing data. Defaults to ``False``. + + """ + # prepare file location + if not str(fname).endswith(".vhdr"): + raise ValueError("`fname` must have the '.vhdr' extension for BrainVision.") + fname = Path(fname) + folder_out = fname.parents[0] + fname_base = fname.stem + + # prepare data from raw + data = raw.get_data() # gets data starting from raw.first_samp + sfreq = raw.info["sfreq"] # in Hz + meas_date = raw.info["meas_date"] # datetime.datetime + ch_names = raw.ch_names + + # write voltage units as micro-volts and all other units without scaling + # write units that we don't know as n/a + unit = [] + for ch in raw.info["chs"]: + if ch["unit"] == FIFF.FIFF_UNIT_V: + unit.append("µV") + elif ch["unit"] == FIFF.FIFF_UNIT_CEL: + unit.append("°C") + else: + unit.append(_unit2human.get(ch["unit"], "n/a")) + unit = [u if u != "NA" else "n/a" for u in unit] + + # enforce conversion to float32 format + # XXX: Could add a feature that checks data and optimizes `unit`, `resolution`, and + # `format` so that raw.orig_format could be retained if reasonable. + if raw.orig_format != "single": + warn( + f"Encountered data in '{raw.orig_format}' format. Converting to float32.", + RuntimeWarning, + ) + + fmt = "binary_float32" + resolution = 0.1 + + # handle events + # if we got an ndarray, this is in MNE-Python format + msg = "`events` must be None or array in MNE-Python format." + if events is not None: + # subtract raw.first_samp because brainvision marks events starting from the + # first available data point and ignores the raw.first_samp + assert isinstance(events, np.ndarray), msg + assert events.ndim == 2, msg + assert events.shape[-1] == 3, msg + events[:, 0] -= raw.first_samp + events = events[:, [0, 2]] # reorder for pybv required order + else: # else, prepare pybv style events from raw.annotations + events = _mne_annots2pybv_events(raw) + + # no information about reference channels in mne currently + ref_ch_names = None + + # write to BrainVision + write_brainvision( + data=data, + sfreq=sfreq, + ch_names=ch_names, + ref_ch_names=ref_ch_names, + fname_base=fname_base, + folder_out=folder_out, + overwrite=overwrite, + events=events, + resolution=resolution, + unit=unit, + fmt=fmt, + meas_date=meas_date, + ) + + +def _mne_annots2pybv_events(raw): + """Convert mne Annotations to pybv events.""" + # check that raw.annotations.orig_time is the same as raw.info["meas_date"] + # so that onsets are relative to the first sample + # (after further correction for first_time) + if raw.annotations and raw.info["meas_date"] != raw.annotations.orig_time: + raise ValueError( + "Annotations must have the same orig_time as raw.info['meas_date']" + ) + events = [] + for annot in raw.annotations: + # handle onset and duration: seconds to sample, relative to + # raw.first_samp / raw.first_time + onset = annot["onset"] - raw.first_time + onset = raw.time_as_index(onset).astype(int)[0] + duration = int(annot["duration"] * raw.info["sfreq"]) + + # triage type and description + # defaults to type="Comment" and the full description + etype = "Comment" + description = annot["description"] + for start in ["Stimulus/S", "Response/R", "Comment/"]: + if description.startswith(start): + etype = start.split("/")[0] + description = description.replace(start, "") + break + + if etype in ["Stimulus", "Response"] and description.strip().isdigit(): + description = int(description.strip()) + else: + # if cannot convert to int, we must use this as "Comment" + etype = "Comment" + + event_dict = dict( + onset=onset, # in samples + duration=duration, # in samples + description=description, + type=etype, + ) + + if "ch_names" in annot: + # handle channels + channels = list(annot["ch_names"]) + event_dict["channels"] = channels + + # add a "pybv" event + events += [event_dict] + + return events + + +def _export_raw(fname, raw, overwrite): + """Export Raw object to BrainVision via pybv.""" + fname = str(fname) + ext = os.path.splitext(fname)[-1] + if ext != ".vhdr": + fname = fname.replace(ext, ".vhdr") + _export_mne_raw(raw=raw, fname=fname, overwrite=overwrite) diff --git a/mne-python/source/mne/export/_edf_bdf.py b/mne-python/source/mne/export/_edf_bdf.py new file mode 100644 index 0000000000000000000000000000000000000000..fa4f9ebcf641ae4bc7e0b352aecbafa2035f2fe5 --- /dev/null +++ b/mne-python/source/mne/export/_edf_bdf.py @@ -0,0 +1,281 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime as dt +from collections.abc import Callable + +import numpy as np + +from mne.annotations import _sync_onset +from mne.utils import _check_edfio_installed, warn + +_check_edfio_installed() +from edfio import ( # noqa: E402 + Bdf, + BdfSignal, + Edf, + EdfAnnotation, + EdfSignal, + Patient, + Recording, +) + + +# copied from edfio (Apache license) +def _round_float_to_8_characters( + value: float, + round_func: Callable[[float], int], +) -> float: + if isinstance(value, int) or value.is_integer(): + return value + length = 8 + integer_part_length = str(value).find(".") + if integer_part_length == length: + return round_func(value) + factor = 10 ** (length - 1 - integer_part_length) + return round_func(value * factor) / factor + + +def _export_raw_edf_bdf(fname, raw, physical_range, add_ch_type, file_format): + """Export Raw objects to EDF/BDF files. + + Parameters + ---------- + fname : str + Output file name. + raw : instance of Raw + The raw instance to export. + physical_range : str or tuple + Physical range setting. + add_ch_type : bool + Whether to add channel type to signal label. + file_format : str + File format ("EDF" or "BDF"). + + Notes + ----- + TODO: if in future the Info object supports transducer or technician information, + allow writing those here. + """ + units = dict( + eeg="uV", ecog="uV", seeg="uV", eog="uV", ecg="uV", emg="uV", bio="uV", dbs="uV" + ) + + if file_format == "EDF": + digital_min, digital_max = -32767, 32767 # 16-bit + signal_class = EdfSignal + writer_class = Edf + else: # BDF + digital_min, digital_max = -8388607, 8388607 # 24-bit + signal_class = BdfSignal + writer_class = Bdf + + ch_types = np.array(raw.get_channel_types()) + + # load and prepare data + raw.load_data() + data = raw.get_data(units=units) + sfreq = raw.info["sfreq"] + pad_annotations = [] + + # Sampling frequency in EDF/BDF only supports integers, so to allow for float + # sampling rates from Raw, we adjust the output sampling rate for all channels and + # the data record duration. + if float(sfreq).is_integer(): + out_sfreq = int(sfreq) + data_record_duration = None + # make non-integer second durations work + if (pad_width := int(np.ceil(raw.n_times / sfreq) * sfreq - raw.n_times)) > 0: + warn( + f"{file_format} format requires equal-length data blocks, so " + f"{pad_width / sfreq:.3g} seconds of edge values were appended to all " + "channels when writing the final block." + ) + data = np.pad( + data, + ( + (0, 0), + (0, int(pad_width)), + ), + "edge", + ) + + pad_annotations.append( + EdfAnnotation( + raw.times[-1] + 1 / sfreq, pad_width / sfreq, "BAD_ACQ_SKIP" + ) + ) + else: + data_record_duration = _round_float_to_8_characters( + np.floor(sfreq) / sfreq, round + ) + out_sfreq = np.floor(sfreq) / data_record_duration + warn( + f"Data has a non-integer sampling rate of {sfreq}; writing to " + f"{file_format} format may cause a small change to sample times." + ) + + # extract filter information + lowpass = raw.info["lowpass"] + highpass = raw.info["highpass"] + linefreq = raw.info["line_freq"] + filter_str_info = f"HP:{highpass}Hz LP:{lowpass}Hz" + if linefreq is not None: + filter_str_info += f" N:{linefreq}Hz" + + # compute physical range + if physical_range == "auto": + # get max and min for each channel type data + ch_types_phys_max = dict() + ch_types_phys_min = dict() + + for _type in np.unique(ch_types): + _picks = [n for n, t in zip(raw.ch_names, ch_types) if t == _type] + _data = raw.get_data(units=units, picks=_picks) + ch_types_phys_max[_type] = _data.max() + ch_types_phys_min[_type] = _data.min() + elif physical_range == "channelwise": + prange = None + else: + # get the physical min and max of the data in uV + # Physical ranges of the data in uV are usually set by the manufacturer and + # electrode properties. In general, physical min and max should be the clipping + # levels of the ADC input, and they should be the same for all channels. For + # example, Nihon Kohden uses ±3200 uV for all EEG channels (corresponding to the + # actual clipping levels of their input amplifiers & ADC). For a discussion, + # see https://github.com/sccn/eeglab/issues/246 + pmin, pmax = physical_range[0], physical_range[1] + + # check that physical min and max is not exceeded + if data.max() > pmax: + warn( + f"The maximum μV of the data {data.max()} is more than the physical max" + f" passed in {pmax}." + ) + if data.min() < pmin: + warn( + f"The minimum μV of the data {data.min()} is less than the physical min" + f" passed in {pmin}." + ) + data = np.clip(data, pmin, pmax) + prange = pmin, pmax + + # create signals + signals = [] + for idx, ch in enumerate(raw.ch_names): + ch_type = ch_types[idx] + signal_label = f"{ch_type.upper()} {ch}" if add_ch_type else ch + if len(signal_label) > 16: + raise RuntimeError( + f"Signal label for {ch} ({ch_type}) is longer than 16 characters, which" + f" is not supported by the {file_format} standard. Please shorten the " + f"channel name before exporting to {file_format}." + ) + + if physical_range == "auto": # per channel type + pmin = ch_types_phys_min[ch_type] + pmax = ch_types_phys_max[ch_type] + if pmax == pmin: + pmax = pmin + 1 + prange = pmin, pmax + + signals.append( + signal_class( + data[idx], + out_sfreq, + label=signal_label, + transducer_type="", + physical_dimension="" if ch_type == "stim" else "uV", + physical_range=prange, + digital_range=(digital_min, digital_max), + prefiltering=filter_str_info, + ) + ) + + # create patient info + subj_info = raw.info.get("subject_info") + if subj_info is not None: + # get the full name of subject if available + first_name = subj_info.get("first_name", "") + middle_name = subj_info.get("middle_name", "") + last_name = subj_info.get("last_name", "") + name = "_".join(filter(None, [first_name, middle_name, last_name])) + + birthday = subj_info.get("birthday") + hand = subj_info.get("hand") + weight = subj_info.get("weight") + height = subj_info.get("height") + sex = subj_info.get("sex") + + additional_patient_info = [] + for key, value in [("height", height), ("weight", weight), ("hand", hand)]: + if value: + additional_patient_info.append(f"{key}={value}") + + patient = Patient( + code=subj_info.get("his_id") or "X", + sex={0: "X", 1: "M", 2: "F", None: "X"}[sex], + birthdate=birthday, + name=name or "X", + additional=additional_patient_info, + ) + else: + patient = None + + # create recording info + if (meas_date := raw.info["meas_date"]) is not None: + startdate = dt.date(meas_date.year, meas_date.month, meas_date.day) + starttime = dt.time( + meas_date.hour, meas_date.minute, meas_date.second, meas_date.microsecond + ) + else: + startdate = None + starttime = None + + device_info = raw.info.get("device_info") + if device_info is not None: + device_type = device_info.get("type") or "X" + recording = Recording(startdate=startdate, equipment_code=device_type) + else: + recording = Recording(startdate=startdate) + + # create annotations + annotations = [] + for desc, onset, duration, ch_names in zip( + raw.annotations.description, + # subtract raw.first_time because EDF/BDF marks events starting from the first + # available data point and ignores raw.first_time + _sync_onset(raw, raw.annotations.onset, inverse=False), + raw.annotations.duration, + raw.annotations.ch_names, + ): + if ch_names: + for ch_name in ch_names: + annotations.append( + EdfAnnotation(onset, duration, desc + f"@@{ch_name}") + ) + else: + annotations.append(EdfAnnotation(onset, duration, desc)) + + annotations.extend(pad_annotations) + + # write to file + writer_class( + signals=signals, + patient=patient, + recording=recording, + starttime=starttime, + data_record_duration=data_record_duration, + annotations=annotations, + ).write(fname) + + +def _export_raw_edf(fname, raw, physical_range, add_ch_type): + """Export Raw object to EDF.""" + _export_raw_edf_bdf(fname, raw, physical_range, add_ch_type, file_format="EDF") + + +def _export_raw_bdf(fname, raw, physical_range, add_ch_type): + """Export Raw object to BDF.""" + _export_raw_edf_bdf(fname, raw, physical_range, add_ch_type, file_format="BDF") diff --git a/mne-python/source/mne/export/_eeglab.py b/mne-python/source/mne/export/_eeglab.py new file mode 100644 index 0000000000000000000000000000000000000000..c73243b0311cc461272e46e965356421b26cf66d --- /dev/null +++ b/mne-python/source/mne/export/_eeglab.py @@ -0,0 +1,106 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from inspect import getfullargspec + +import numpy as np + +from ..annotations import _sync_onset +from ..utils import _check_eeglabio_installed + +_check_eeglabio_installed() +import eeglabio.epochs # noqa: E402 +import eeglabio.raw # noqa: E402 + + +def _export_raw(fname, raw): + # load data first + raw.load_data() + + # remove extra epoc and STI channels + drop_chs = ["epoc"] + # filenames attribute of RawArray is filled with None + if raw.filenames[0] and raw.filenames[0].suffix != ".fif": + drop_chs.append("STI 014") + + ch_names = [ch for ch in raw.ch_names if ch not in drop_chs] + cart_coords = _get_als_coords_from_chs(raw.info["chs"], drop_chs) + + if raw.annotations: + annotations = [ + raw.annotations.description, + # subtract raw.first_time because EEGLAB marks events starting from + # the first available data point and ignores raw.first_time + _sync_onset(raw, raw.annotations.onset, inverse=False), + raw.annotations.duration, + ] + else: + annotations = None + eeglabio.raw.export_set( + fname, + data=raw.get_data(picks=ch_names), + sfreq=raw.info["sfreq"], + ch_names=ch_names, + ch_locs=cart_coords, + annotations=annotations, + ) + + +def _export_epochs(fname, epochs): + _check_eeglabio_installed() + # load data first + epochs.load_data() + + # remove extra epoc and STI channels + drop_chs = ["epoc", "STI 014"] + ch_names = [ch for ch in epochs.ch_names if ch not in drop_chs] + cart_coords = _get_als_coords_from_chs(epochs.info["chs"], drop_chs) + + if epochs.annotations: + annot = [ + epochs.annotations.description, + epochs.annotations.onset, + epochs.annotations.duration, + ] + else: + annot = None + + # https://github.com/jackz314/eeglabio/pull/18 + kwargs = dict() + if "epoch_indices" in getfullargspec(eeglabio.epochs.export_set).kwonlyargs: + kwargs["epoch_indices"] = epochs.selection + + eeglabio.epochs.export_set( + fname, + data=epochs.get_data(picks=ch_names), + sfreq=epochs.info["sfreq"], + events=epochs.events, + tmin=epochs.tmin, + tmax=epochs.tmax, + ch_names=ch_names, + event_id=epochs.event_id, + ch_locs=cart_coords, + annotations=annot, + **kwargs, + ) + + +def _get_als_coords_from_chs(chs, drop_chs=None): + """Extract channel locations in ALS format (x, y, z) from a chs instance. + + Returns + ------- + None if no valid coordinates are found (all zeros) + """ + if drop_chs is None: + drop_chs = [] + cart_coords = np.array([d["loc"][:3] for d in chs if d["ch_name"] not in drop_chs]) + if cart_coords.any(): # has coordinates + # (-y x z) to (x y z) + cart_coords[:, 0] = -cart_coords[:, 0] # -y to y + # swap x (1) and y (0) + cart_coords[:, [0, 1]] = cart_coords[:, [1, 0]] + else: + cart_coords = None + return cart_coords diff --git a/mne-python/source/mne/export/_egimff.py b/mne-python/source/mne/export/_egimff.py new file mode 100644 index 0000000000000000000000000000000000000000..185afb5f55801c1f8ade72c4b9db383ede5e941d --- /dev/null +++ b/mne-python/source/mne/export/_egimff.py @@ -0,0 +1,176 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime +import os +import os.path as op +import shutil + +import numpy as np + +from .._fiff.pick import pick_channels, pick_types +from ..io.egi.egimff import _import_mffpy +from ..utils import _check_fname, verbose, warn + + +@verbose +def export_evokeds_mff(fname, evoked, history=None, *, overwrite=False, verbose=None): + """Export evoked dataset to MFF. + + %(export_warning)s + + Parameters + ---------- + %(fname_export_params)s + evoked : list of Evoked instances + List of evoked datasets to export to one file. Note that the + measurement info from the first evoked instance is used, so be sure + that information matches. + history : None (default) | list of dict + Optional list of history entries (dictionaries) to be written to + history.xml. This must adhere to the format described in + mffpy.xml_files.History.content. If None, no history.xml will be + written. + %(overwrite)s + + .. versionadded:: 0.24.1 + %(verbose)s + + Notes + ----- + .. versionadded:: 0.24 + + %(export_warning_note_evoked)s + + Only EEG channels are written to the output file. + ``info['device_info']['type']`` must be a valid MFF recording device + (e.g. 'HydroCel GSN 256 1.0'). This field is automatically populated when + using MFF read functions. + """ + mffpy = _import_mffpy("Export evokeds to MFF.") + + info = evoked[0].info + if np.round(info["sfreq"]) != info["sfreq"]: + raise ValueError( + f"Sampling frequency must be a whole number. sfreq: {info['sfreq']}" + ) + sampling_rate = int(info["sfreq"]) + + # check for unapplied projectors + if any(not proj["active"] for proj in evoked[0].info["projs"]): + warn( + "Evoked instance has unapplied projectors. Consider applying " + "them before exporting with evoked.apply_proj()." + ) + + # Initialize writer + # Future changes: conditions based on version or mffpy requirement if + # https://github.com/BEL-Public/mffpy/pull/92 is merged and released. + fname = str(_check_fname(fname, overwrite=overwrite)) + if op.exists(fname): + os.remove(fname) if op.isfile(fname) else shutil.rmtree(fname) + writer = mffpy.Writer(fname) + current_time = datetime.datetime.now(datetime.timezone.utc) + writer.addxml("fileInfo", recordTime=current_time) + try: + device = info["device_info"]["type"] + except (TypeError, KeyError): + raise ValueError("No device type. Cannot determine sensor layout.") + writer.add_coordinates_and_sensor_layout(device) + + # Add EEG data + eeg_channels = pick_types(info, eeg=True, exclude=[]) + eeg_bin = mffpy.bin_writer.BinWriter(sampling_rate) + for ave in evoked: + # Signals are converted to µV + block = (ave.data[eeg_channels] * 1e6).astype(np.float32) + eeg_bin.add_block(block, offset_us=0) + writer.addbin(eeg_bin) + + # Add categories + categories_content = _categories_content_from_evokeds(evoked) + writer.addxml("categories", categories=categories_content) + + # Add history + if history: + writer.addxml("historyEntries", entries=history) + + writer.write() + + +def _categories_content_from_evokeds(evoked): + """Return categories.xml content for evoked dataset.""" + content = dict() + begin_time = 0 + for ave in evoked: + # Times are converted to microseconds + sfreq = ave.info["sfreq"] + duration = np.round(len(ave.times) / sfreq * 1e6).astype(int) + end_time = begin_time + duration + event_time = begin_time - np.round(ave.tmin * 1e6).astype(int) + eeg_bads = _get_bad_eeg_channels(ave.info) + content[ave.comment] = [ + _build_segment_content( + begin_time, + end_time, + event_time, + eeg_bads, + name="Average", + nsegs=ave.nave, + ) + ] + begin_time += duration + return content + + +def _get_bad_eeg_channels(info): + """Return a list of bad EEG channels formatted for categories.xml. + + Given a list of only the EEG channels in file, return the indices of this + list (starting at 1) that correspond to bad channels. + """ + if len(info["bads"]) == 0: + return [] + eeg_channels = pick_types(info, eeg=True, exclude=[]) + bad_channels = pick_channels(info["ch_names"], info["bads"]) + bads_elementwise = np.isin(eeg_channels, bad_channels) + return list(np.flatnonzero(bads_elementwise) + 1) + + +def _build_segment_content( + begin_time, + end_time, + event_time, + eeg_bads, + status="unedited", + name=None, + pns_bads=None, + nsegs=None, +): + """Build content for a single segment in categories.xml. + + Segments are sorted into categories in categories.xml. In a segmented MFF + each category can contain multiple segments, but in an averaged MFF each + category only contains one segment (the average). + """ + channel_status = [ + {"signalBin": 1, "exclusion": "badChannels", "channels": eeg_bads} + ] + if pns_bads: + channel_status.append( + {"signalBin": 2, "exclusion": "badChannels", "channels": pns_bads} + ) + content = { + "status": status, + "beginTime": begin_time, + "endTime": end_time, + "evtBegin": event_time, + "evtEnd": event_time, + "channelStatus": channel_status, + } + if name: + content["name"] = name + if nsegs: + content["keys"] = {"#seg": {"type": "long", "data": nsegs}} + return content diff --git a/mne-python/source/mne/export/_export.py b/mne-python/source/mne/export/_export.py new file mode 100644 index 0000000000000000000000000000000000000000..2842b747f2130bd9a07e4965b5470e874f8bf2f0 --- /dev/null +++ b/mne-python/source/mne/export/_export.py @@ -0,0 +1,235 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os + +from mne.export._egimff import export_evokeds_mff +from mne.utils import _check_fname, _validate_type, logger, verbose, warn + + +@verbose +def export_raw( + fname, + raw, + fmt="auto", + physical_range="auto", + add_ch_type=False, + *, + overwrite=False, + verbose=None, +): + """Export Raw to external formats. + + %(export_fmt_support_raw)s + + %(export_warning)s + + .. warning:: + When exporting ``Raw`` with annotations, ``raw.info["meas_date"]`` must be the + same as ``raw.annotations.orig_time``. This guarantees that the annotations are + in the same reference frame as the samples. When + :attr:`Raw.first_time ` is not zero (e.g., after + cropping), the onsets are automatically corrected so that onsets are always + relative to the first sample. + + Parameters + ---------- + %(fname_export_params)s + raw : instance of Raw + The raw instance to export. + %(export_fmt_params_raw)s + %(physical_range_export_params)s + %(add_ch_type_export_params)s + %(overwrite)s + + .. versionadded:: 0.24.1 + %(verbose)s + + Notes + ----- + .. versionadded:: 0.24 + + %(export_warning_note_raw)s + %(export_eeglab_note)s + %(export_edf_note)s + """ + fname = str(_check_fname(fname, overwrite=overwrite)) + supported_export_formats = { # format : (extensions,) + "bdf": ("bdf",), + "brainvision": ( + "eeg", + "vmrk", + "vhdr", + ), + "edf": ("edf",), + "eeglab": ("set",), + } + fmt = _infer_check_export_fmt(fmt, fname, supported_export_formats) + + # check for unapplied projectors + if any(not proj["active"] for proj in raw.info["projs"]): + warn( + "Raw instance has unapplied projectors. Consider applying " + "them before exporting with raw.apply_proj()." + ) + + match fmt: + case "bdf": + from mne.export._edf_bdf import _export_raw_bdf + + _export_raw_bdf(fname, raw, physical_range, add_ch_type) + case "brainvision": + from mne.export._brainvision import _export_raw + + _export_raw(fname, raw, overwrite) + case "edf": + from mne.export._edf_bdf import _export_raw_edf + + _export_raw_edf(fname, raw, physical_range, add_ch_type) + case "eeglab": + from mne.export._eeglab import _export_raw + + _export_raw(fname, raw) + + +@verbose +def export_epochs(fname, epochs, fmt="auto", *, overwrite=False, verbose=None): + """Export Epochs to external formats. + + %(export_fmt_support_epochs)s + + %(export_warning)s + + Parameters + ---------- + %(fname_export_params)s + epochs : instance of Epochs + The epochs to export. + %(export_fmt_params_epochs)s + %(overwrite)s + + .. versionadded:: 0.24.1 + %(verbose)s + + Notes + ----- + .. versionadded:: 0.24 + + %(export_warning_note_epochs)s + %(export_eeglab_note)s + """ + fname = str(_check_fname(fname, overwrite=overwrite)) + supported_export_formats = { + "eeglab": ("set",), + } + fmt = _infer_check_export_fmt(fmt, fname, supported_export_formats) + + # check for unapplied projectors + if any(not proj["active"] for proj in epochs.info["projs"]): + warn( + "Epochs instance has unapplied projectors. Consider applying " + "them before exporting with epochs.apply_proj()." + ) + + if fmt == "eeglab": + from mne.export._eeglab import _export_epochs + + _export_epochs(fname, epochs) + + +@verbose +def export_evokeds(fname, evoked, fmt="auto", *, overwrite=False, verbose=None): + """Export evoked dataset to external formats. + + This function is a wrapper for format-specific export functions. The export + function is selected based on the inferred file format. For additional + options, use the format-specific functions. + + %(export_fmt_support_evoked)s + + %(export_warning)s + + Parameters + ---------- + %(fname_export_params)s + evoked : Evoked instance, or list of Evoked instances + The evoked dataset, or list of evoked datasets, to export to one file. + Note that the measurement info from the first evoked instance is used, + so be sure that information matches. + %(export_fmt_params_evoked)s + %(overwrite)s + + .. versionadded:: 0.24.1 + %(verbose)s + + See Also + -------- + mne.write_evokeds + mne.export.export_evokeds_mff + + Notes + ----- + .. versionadded:: 0.24 + + %(export_warning_note_evoked)s + """ + fname = str(_check_fname(fname, overwrite=overwrite)) + supported_export_formats = { + "mff": ("mff",), + } + fmt = _infer_check_export_fmt(fmt, fname, supported_export_formats) + + if not isinstance(evoked, list): + evoked = [evoked] + + logger.info(f"Exporting evoked dataset to {fname}...") + + if fmt == "mff": + export_evokeds_mff(fname, evoked, overwrite=overwrite) + + +def _infer_check_export_fmt(fmt, fname, supported_formats): + """Infer export format from filename extension if auto. + + Raises error if fmt is auto and no file extension found, + then checks format against supported formats, raises error if format is not + supported. + + Parameters + ---------- + fmt : str + Format of the export, will only infer the format from filename if fmt + is auto. + fname : str + Name of the target export file, only used when fmt is auto. + supported_formats : dict of str : tuple/list + Dictionary containing supported formats (as keys) and each format's + corresponding file extensions in a tuple (e.g., {'eeglab': ('set',)}) + """ + _validate_type(fmt, str, "fmt") + fmt = fmt.lower() + if fmt == "auto": + fmt = os.path.splitext(fname)[1] + if fmt: + fmt = fmt[1:].lower() + # find fmt in supported formats dict's tuples + fmt = next( + (k for k, v in supported_formats.items() if fmt in v), fmt + ) # default to original fmt for raising error later + else: + raise ValueError( + f"Couldn't infer format from filename {fname} (no extension found)" + ) + + if fmt not in supported_formats: + supported = [] + for supp_format, extensions in supported_formats.items(): + ext_str = ", ".join(f"*.{ext}" for ext in extensions) + supported.append(f"{supp_format} ({ext_str})") + + supported_str = ", ".join(supported) + raise ValueError( + f"Format '{fmt}' is not supported. Supported formats are {supported_str}." + ) + return fmt diff --git a/mne-python/source/mne/export/tests/test_export.py b/mne-python/source/mne/export/tests/test_export.py new file mode 100644 index 0000000000000000000000000000000000000000..4651123d4995fcb6ef29519ff1a557d0a117998e --- /dev/null +++ b/mne-python/source/mne/export/tests/test_export.py @@ -0,0 +1,719 @@ +"""Test exporting functions.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from contextlib import nullcontext +from datetime import date, datetime, timezone +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_almost_equal, assert_array_equal + +from mne import ( + Annotations, + Epochs, + create_info, + read_epochs_eeglab, + read_evokeds, + read_evokeds_mff, +) +from mne.datasets import misc, testing +from mne.export import export_evokeds, export_evokeds_mff +from mne.fixes import _compare_version +from mne.io import ( + RawArray, + read_raw_bdf, + read_raw_brainvision, + read_raw_edf, + read_raw_eeglab, + read_raw_fif, +) +from mne.tests.test_epochs import _get_data +from mne.utils import ( + _check_edfio_installed, + _record_warnings, + _resource_path, + check_version, + object_diff, +) + +fname_evoked = _resource_path("mne.io.tests.data", "test-ave.fif") +fname_raw = _resource_path("mne.io.tests.data", "test_raw.fif") + +data_path = testing.data_path(download=False) +egi_evoked_fname = data_path / "EGI" / "test_egi_evoked.mff" +misc_path = misc.data_path(download=False) + + +@pytest.mark.parametrize( + ["meas_date", "orig_time", "ext"], + [ + [None, None, ".vhdr"], + [datetime(2022, 12, 3, 19, 1, 10, 720100, tzinfo=timezone.utc), None, ".eeg"], + ], +) +def test_export_raw_pybv(tmp_path, meas_date, orig_time, ext): + """Test saving a Raw instance to BrainVision format via pybv.""" + pytest.importorskip("pybv") + raw = read_raw_fif(fname_raw, preload=True) + raw.apply_proj() + + raw.set_meas_date(meas_date) + + # add some annotations + annots = Annotations( + onset=[3, 6, 9, 12, 14], # seconds + duration=[1, 1, 0.5, 0.25, 9], # seconds + description=[ + "Stimulus/S 1", + "Stimulus/S2.50", + "Response/R101", + "Look at this", + "Comment/And at this", + ], + ch_names=[(), (), (), ("EEG 001",), ("EEG 001", "EEG 002")], + orig_time=orig_time, + ) + raw.set_annotations(annots) + + temp_fname = tmp_path / ("test" + ext) + with ( + _record_warnings(), + pytest.warns(RuntimeWarning, match="'short' format. Converting"), + ): + raw.export(temp_fname) + raw_read = read_raw_brainvision(str(temp_fname).replace(".eeg", ".vhdr")) + assert raw.ch_names == raw_read.ch_names + assert_allclose(raw.times, raw_read.times) + assert_allclose(raw.get_data(), raw_read.get_data()) + + +def test_export_raw_eeglab(tmp_path): + """Test saving a Raw instance to EEGLAB's set format.""" + pytest.importorskip("eeglabio") + raw = read_raw_fif(fname_raw, preload=True) + raw.apply_proj() + temp_fname = tmp_path / "test.set" + raw.export(temp_fname) + raw.drop_channels([ch for ch in ["epoc"] if ch in raw.ch_names]) + + with pytest.warns(RuntimeWarning, match="is above the 99th percentile"): + raw_read = read_raw_eeglab(temp_fname, preload=True, montage_units="m") + assert raw.ch_names == raw_read.ch_names + + cart_coords = np.array([d["loc"][:3] for d in raw.info["chs"]]) # just xyz + cart_coords_read = np.array([d["loc"][:3] for d in raw_read.info["chs"]]) + assert_allclose(cart_coords, cart_coords_read) + assert_allclose(raw.times, raw_read.times) + assert_allclose(raw.get_data(), raw_read.get_data()) + + # test overwrite + with pytest.raises(FileExistsError, match="Destination file exists"): + raw.export(temp_fname, overwrite=False) + raw.export(temp_fname, overwrite=True) + + # test pathlib.Path files + raw.export(Path(temp_fname), overwrite=True) + + # test warning with unapplied projectors + raw = read_raw_fif(fname_raw, preload=True) + with pytest.warns(RuntimeWarning, match="Raw instance has unapplied projectors."): + raw.export(temp_fname, overwrite=True) + + +@pytest.mark.parametrize("tmin", (0, 1, 5, 10)) +def test_export_raw_eeglab_annotations(tmp_path, tmin): + """Test annotations in the exported EEGLAB file. + + All annotations should be preserved and onset corrected. + """ + pytest.importorskip("eeglabio") + raw = read_raw_fif(fname_raw, preload=True) + raw.apply_proj() + annotations = Annotations( + onset=[0.01, 0.05, 0.90, 1.05], + duration=[0, 1, 0, 0], + description=["test1", "test2", "test3", "test4"], + ch_names=[["MEG 0113"], ["MEG 0113", "MEG 0132"], [], ["MEG 0143"]], + ) + raw.set_annotations(annotations) + raw.crop(tmin) + + # export + temp_fname = tmp_path / "test.set" + raw.export(temp_fname) + + # read in the file + with pytest.warns(RuntimeWarning, match="is above the 99th percentile"): + raw_read = read_raw_eeglab(temp_fname, preload=True, montage_units="m") + assert raw_read.first_time == 0 # exportation resets first_time + valid_annot = ( + raw.annotations.onset >= tmin + ) # only annotations in the cropped range gets exported + + # compare annotations before and after export + assert_array_almost_equal( + raw.annotations.onset[valid_annot] - raw.first_time, + raw_read.annotations.onset, + ) + assert_array_equal( + raw.annotations.duration[valid_annot], raw_read.annotations.duration + ) + assert_array_equal( + raw.annotations.description[valid_annot], raw_read.annotations.description + ) + + +def _create_raw_for_edf_tests(stim_channel_index=None): + rng = np.random.RandomState(12345) + ch_types = [ + "eeg", + "eeg", + "ecog", + "ecog", + "seeg", + "eog", + "ecg", + "emg", + "dbs", + "bio", + ] + if stim_channel_index is not None: + ch_types.insert(stim_channel_index, "stim") + ch_names = np.arange(len(ch_types)).astype(str).tolist() + info = create_info(ch_names, sfreq=1000, ch_types=ch_types) + data = rng.random(size=(len(ch_names), 2000)) * 1e-5 + return RawArray(data, info) + + +edfio_mark = pytest.mark.skipif( + not _check_edfio_installed(strict=False), reason="requires edfio" +) + + +@edfio_mark() +def test_double_export_edf(tmp_path): + """Test exporting an EDF file multiple times.""" + raw = _create_raw_for_edf_tests(stim_channel_index=2) + raw.info.set_meas_date(datetime(2023, 9, 4, 14, 53, 9, tzinfo=timezone.utc)) + raw.set_annotations(Annotations(onset=[1], duration=[0], description=["test"])) + + # include subject info and measurement date + raw.info["subject_info"] = dict( + his_id="12345", + first_name="mne", + last_name="python", + birthday=date(1992, 1, 20), + sex=1, + weight=78.3, + height=1.75, + hand=3, + ) + + # export once + temp_fname = tmp_path / "test.edf" + raw.export(temp_fname, add_ch_type=True) + raw_read = read_raw_edf(temp_fname, infer_types=True, preload=True) + + # export again + raw_read.export(temp_fname, add_ch_type=True, overwrite=True) + raw_read = read_raw_edf(temp_fname, infer_types=True, preload=True) + + assert raw.ch_names == raw_read.ch_names + assert_array_almost_equal(raw.get_data(), raw_read.get_data(), decimal=10) + assert_array_equal(raw.times, raw_read.times) + + # check info + for key in set(raw.info) - {"chs"}: + assert raw.info[key] == raw_read.info[key] + + orig_ch_types = raw.get_channel_types() + read_ch_types = raw_read.get_channel_types() + assert_array_equal(orig_ch_types, read_ch_types) + + +@edfio_mark() +def test_edf_physical_range(tmp_path): + """Test exporting an EDF file with different physical range settings.""" + ch_types = ["eeg"] * 4 + ch_names = np.arange(len(ch_types)).astype(str).tolist() + fs = 1000 + info = create_info(len(ch_types), sfreq=fs, ch_types=ch_types) + data = np.tile( + np.sin(2 * np.pi * 10 * np.arange(0, 2, 1 / fs)) * 1e-5, (len(ch_names), 1) + ) + data = (data.T + [0.1, 0, 0, -0.1]).T # add offsets + raw = RawArray(data, info) + + # export with physical range per channel type (default) + temp_fname = tmp_path / "test_auto.edf" + raw.export(temp_fname) + raw_read = read_raw_edf(temp_fname, preload=True) + with pytest.raises(AssertionError, match="Arrays are not almost equal"): + assert_array_almost_equal(raw.get_data(), raw_read.get_data(), decimal=10) + + # export with physical range per channel + temp_fname = tmp_path / "test_per_channel.edf" + raw.export(temp_fname, physical_range="channelwise") + raw_read = read_raw_edf(temp_fname, preload=True) + assert_array_almost_equal(raw.get_data(), raw_read.get_data(), decimal=10) + + +@edfio_mark() +@pytest.mark.parametrize("pad_width", (1, 10, 100, 500, 999)) +def test_edf_padding(tmp_path, pad_width): + """Test exporting an EDF file with not-equal-length data blocks.""" + ch_types = ["eeg"] * 4 + ch_names = np.arange(len(ch_types)).astype(str).tolist() + fs = 1000 + info = create_info(len(ch_types), sfreq=fs, ch_types=ch_types) + data = np.tile( + np.sin(2 * np.pi * 10 * np.arange(0, 2, 1 / fs)) * 1e-5, (len(ch_names), 1) + )[:, 0:-pad_width] # remove last pad_width samples + raw = RawArray(data, info) + + # export with physical range per channel type (default) + temp_fname = tmp_path / "test.edf" + with pytest.warns( + RuntimeWarning, + match=( + "EDF format requires equal-length data blocks.*" + f"{pad_width / 1000:.3g} seconds of edge values were appended.*" + ), + ): + raw.export(temp_fname) + + # read in the file + raw_read = read_raw_edf(temp_fname, preload=True) + assert raw.n_times == raw_read.n_times - pad_width + edge_data = raw_read.get_data()[:, -pad_width - 1] + pad_data = raw_read.get_data()[:, -pad_width:] + assert_array_almost_equal( + raw.get_data(), raw_read.get_data()[:, :-pad_width], decimal=10 + ) + assert_array_almost_equal( + pad_data, np.tile(edge_data, (pad_width, 1)).T, decimal=10 + ) + + assert "BAD_ACQ_SKIP" in raw_read.annotations.description + assert_array_almost_equal(raw_read.annotations.onset[0], raw.times[-1] + 1 / fs) + assert_array_almost_equal(raw_read.annotations.duration[0], pad_width / fs) + + +@edfio_mark() +@pytest.mark.parametrize("tmin", (0, 0.005, 0.03, 1)) +def test_export_edf_annotations(tmp_path, tmin): + """Test annotations in the exported EDF file. + + All annotations should be preserved and onset corrected. + """ + raw = _create_raw_for_edf_tests() + annotations = Annotations( + onset=[0.01, 0.05, 0.90, 1.05], + duration=[0, 1, 0, 0], + description=["test1", "test2", "test3", "test4"], + ch_names=[["0"], ["0", "1"], [], ["1"]], + ) + raw.set_annotations(annotations) + raw.crop(tmin) + assert raw.first_time == tmin + + if raw.n_times % raw.info["sfreq"] == 0: + expectation = nullcontext() + else: + expectation = pytest.warns( + RuntimeWarning, match="EDF format requires equal-length data blocks" + ) + + # export + temp_fname = tmp_path / "test.edf" + with expectation: + raw.export(temp_fname) + + # read in the file + raw_read = read_raw_edf(temp_fname, preload=True) + assert raw_read.first_time == 0 # exportation resets first_time + bad_annot = raw_read.annotations.description == "BAD_ACQ_SKIP" + if bad_annot.any(): + raw_read.annotations.delete(bad_annot) + valid_annot = ( + raw.annotations.onset >= tmin + ) # only annotations in the cropped range gets exported + + # compare annotations before and after export + assert_array_almost_equal( + raw.annotations.onset[valid_annot] - raw.first_time, raw_read.annotations.onset + ) + assert_array_equal( + raw.annotations.duration[valid_annot], raw_read.annotations.duration + ) + assert_array_equal( + raw.annotations.description[valid_annot], raw_read.annotations.description + ) + assert_array_equal( + raw.annotations.ch_names[valid_annot], raw_read.annotations.ch_names + ) + + +@edfio_mark() +def test_rawarray_edf(tmp_path): + """Test saving a Raw array with integer sfreq to EDF.""" + raw = _create_raw_for_edf_tests() + + # include subject info and measurement date + raw.info["subject_info"] = dict( + first_name="mne", + last_name="python", + birthday=date(1992, 1, 20), + sex=1, + hand=3, + ) + time_now = datetime.now() + meas_date = datetime( + year=time_now.year, + month=time_now.month, + day=time_now.day, + hour=time_now.hour, + minute=time_now.minute, + second=time_now.second, + tzinfo=timezone.utc, + ) + raw.set_meas_date(meas_date) + temp_fname = tmp_path / "test.edf" + + raw.export(temp_fname, add_ch_type=True) + raw_read = read_raw_edf(temp_fname, infer_types=True, preload=True) + + assert raw.ch_names == raw_read.ch_names + assert_array_almost_equal(raw.get_data(), raw_read.get_data(), decimal=10) + assert_array_equal(raw.times, raw_read.times) + + orig_ch_types = raw.get_channel_types() + read_ch_types = raw_read.get_channel_types() + assert_array_equal(orig_ch_types, read_ch_types) + assert raw.info["meas_date"] == raw_read.info["meas_date"] + + +@edfio_mark() +def test_edf_export_non_voltage_channels(tmp_path): + """Test saving a Raw array containing a non-voltage channel.""" + temp_fname = tmp_path / "test.edf" + + raw = _create_raw_for_edf_tests() + raw.set_channel_types({"9": "hbr"}, on_unit_change="ignore") + raw.export(temp_fname, overwrite=True) + + # data should match up to the non-accepted channel + raw_read = read_raw_edf(temp_fname, preload=True) + assert raw.ch_names == raw_read.ch_names + assert_array_almost_equal(raw.get_data()[:-1], raw_read.get_data()[:-1], decimal=10) + assert_array_almost_equal(raw.get_data()[-1], raw_read.get_data()[-1], decimal=5) + assert_array_equal(raw.times, raw_read.times) + + +@edfio_mark() +def test_channel_label_too_long_for_edf_raises_error(tmp_path): + """Test trying to save an EDF where a channel label is longer than 16 characters.""" + raw = _create_raw_for_edf_tests() + raw.rename_channels({"1": "abcdefghijklmnopqrstuvwxyz"}) + with pytest.raises(RuntimeError, match="Signal label"): + raw.export(tmp_path / "test.edf") + + +@edfio_mark() +def test_measurement_date_outside_range_valid_for_edf(tmp_path): + """Test trying to save an EDF with a measurement date before 1985-01-01.""" + raw = _create_raw_for_edf_tests() + raw.set_meas_date(datetime(year=1984, month=1, day=1, tzinfo=timezone.utc)) + with pytest.raises(ValueError, match="EDF only allows dates from 1985 to 2084"): + raw.export(tmp_path / "test.edf", overwrite=True) + + +@pytest.mark.filterwarnings("ignore:Data has a non-integer:RuntimeWarning") +@pytest.mark.parametrize( + ("physical_range", "exceeded_bound"), + [ + ((-1e6, 0), "maximum"), + ((0, 1e6), "minimum"), + ], +) +@edfio_mark() +def test_export_edf_signal_clipping(tmp_path, physical_range, exceeded_bound): + """Test if exporting data exceeding physical min/max clips and emits a warning.""" + raw = read_raw_fif(fname_raw) + raw.pick(picks=["eeg", "ecog", "seeg"]).load_data() + temp_fname = tmp_path / "test.edf" + with ( + _record_warnings(), + pytest.warns(RuntimeWarning, match=f"The {exceeded_bound}"), + ): + raw.export(temp_fname, physical_range=physical_range) + raw_read = read_raw_edf(temp_fname, preload=True) + assert raw_read.get_data().min() >= physical_range[0] + assert raw_read.get_data().max() <= physical_range[1] + + +@edfio_mark() +def test_export_edf_with_constant_channel(tmp_path): + """Test if exporting to edf works if a channel contains only constant values.""" + temp_fname = tmp_path / "test.edf" + raw = RawArray(np.zeros((1, 10)), info=create_info(1, 1)) + raw.export(temp_fname) + raw_read = read_raw_edf(temp_fname, preload=True) + assert_array_equal(raw_read.get_data(), np.zeros((1, 10))) + + +@edfio_mark() +@pytest.mark.parametrize( + ("input_path", "warning_msg"), + [ + (fname_raw, "Data has a non-integer"), + pytest.param( + misc_path / "ecog" / "sample_ecog_ieeg.fif", + "EDF format requires", + marks=[pytest.mark.slowtest, misc._pytest_mark()], + ), + ], +) +def test_export_raw_edf(tmp_path, input_path, warning_msg): + """Test saving a Raw instance to EDF format.""" + raw = read_raw_fif(input_path) + + # only test with EEG channels + raw.pick(picks=["eeg", "ecog", "seeg"]).load_data() + temp_fname = tmp_path / "test.edf" + + with pytest.warns(RuntimeWarning, match=warning_msg): + raw.export(temp_fname) + + if "epoc" in raw.ch_names: + raw.drop_channels(["epoc"]) + + raw_read = read_raw_edf(temp_fname, preload=True) + assert raw.ch_names == raw_read.ch_names + # only compare the original length, since extra zeros are appended + orig_raw_len = len(raw) + + # assert data and times are not different + # Due to the physical range of the data, reading and writing is + # not lossless. For example, a physical min/max of -/+ 3200 uV + # will result in a resolution of 0.09 uV. This resolution + # though is acceptable for most EEG manufacturers. + assert_array_almost_equal( + raw.get_data(), raw_read.get_data()[:, :orig_raw_len], decimal=8 + ) + + # Due to the data record duration limitations of EDF files, one + # cannot store arbitrary float sampling rate exactly. Usually this + # results in two sampling rates that are off by very low number of + # decimal points. This for practical purposes does not matter + # but will result in an error when say the number of time points + # is very very large. + assert_allclose(raw.times, raw_read.times[:orig_raw_len], rtol=0, atol=1e-5) + + +@edfio_mark() +def test_export_raw_edf_does_not_fail_on_empty_header_fields(tmp_path): + """Test writing a Raw instance with empty header fields to EDF.""" + rng = np.random.RandomState(123456) + + ch_types = ["eeg"] + info = create_info(len(ch_types), sfreq=1000, ch_types=ch_types) + info["subject_info"] = { + "his_id": "", + "first_name": "", + "middle_name": "", + "last_name": "", + } + info["device_info"] = {"type": "123"} + + data = rng.random(size=(len(ch_types), 1000)) * 1e-5 + raw = RawArray(data, info) + + raw.export(tmp_path / "test.edf", add_ch_type=True) + + +@pytest.mark.skipif( + not check_version("eeglabio", "0.1.2"), reason="fixed by eeglabio 0.1.2" +) +@pytest.mark.parametrize("preload", (True, False)) +def test_export_epochs_eeglab(tmp_path, preload): + """Test saving an Epochs instance to EEGLAB's set format.""" + eeglabio = pytest.importorskip("eeglabio") + raw, events = _get_data()[:2] + raw.load_data() + epochs = Epochs(raw, events, preload=preload) + temp_fname = tmp_path / "test.set" + # TODO: eeglabio 0.2 warns about invalid events + if _compare_version(eeglabio.__version__, "==", "0.0.2-1"): + ctx = _record_warnings + else: + ctx = nullcontext + with ctx(): + epochs.export(temp_fname) + epochs.drop_channels([ch for ch in ["epoc", "STI 014"] if ch in epochs.ch_names]) + epochs_read = read_epochs_eeglab(temp_fname, verbose="error") # head radius + assert epochs.ch_names == epochs_read.ch_names + cart_coords = np.array([d["loc"][:3] for d in epochs.info["chs"]]) # just xyz + cart_coords_read = np.array([d["loc"][:3] for d in epochs_read.info["chs"]]) + assert_allclose(cart_coords, cart_coords_read) + assert_array_equal(epochs.events[:, 0], epochs_read.events[:, 0]) # latency + assert epochs.event_id.keys() == epochs_read.event_id.keys() # just keys + assert_allclose(epochs.times, epochs_read.times) + assert_allclose(epochs.get_data(), epochs_read.get_data()) + + # test overwrite + with pytest.raises(FileExistsError, match="Destination file exists"): + epochs.export(temp_fname, overwrite=False) + with ctx(): + epochs.export(temp_fname, overwrite=True) + + # test pathlib.Path files + with ctx(): + epochs.export(Path(temp_fname), overwrite=True) + + # test warning with unapplied projectors + epochs = Epochs(raw, events, preload=preload, proj=False) + with pytest.warns( + RuntimeWarning, match="Epochs instance has unapplied projectors." + ): + epochs.export(Path(temp_fname), overwrite=True) + + +@testing.requires_testing_data +@pytest.mark.parametrize("fmt", ("auto", "mff")) +@pytest.mark.parametrize("do_history", (True, False)) +def test_export_evokeds_to_mff(tmp_path, fmt, do_history): + """Test exporting evoked dataset to MFF.""" + pytest.importorskip("mffpy", "0.5.7") + pytest.importorskip("defusedxml") + evoked = read_evokeds_mff(egi_evoked_fname) + export_fname = tmp_path / "evoked.mff" + history = [ + { + "name": "Test Segmentation", + "method": "Segmentation", + "settings": ["Setting 1", "Setting 2"], + "results": ["Result 1", "Result 2"], + }, + { + "name": "Test Averaging", + "method": "Averaging", + "settings": ["Setting 1", "Setting 2"], + "results": ["Result 1", "Result 2"], + }, + ] + if do_history: + export_evokeds_mff(export_fname, evoked, history=history) + else: + export_evokeds(export_fname, evoked, fmt=fmt) + # Drop non-EEG channels + evoked = [ave.drop_channels(["ECG", "EMG"]) for ave in evoked] + evoked_exported = read_evokeds_mff(export_fname) + assert len(evoked) == len(evoked_exported) + for ave, ave_exported in zip(evoked, evoked_exported): + # Compare infos + assert object_diff(ave_exported.info, ave.info) == "" + # Compare data + assert_allclose(ave_exported.data, ave.data) + # Compare properties + assert ave_exported.nave == ave.nave + assert ave_exported.kind == ave.kind + assert ave_exported.comment == ave.comment + assert_allclose(ave_exported.times, ave.times) + + # test overwrite + with pytest.raises(FileExistsError, match="Destination file exists"): + if do_history: + export_evokeds_mff(export_fname, evoked, history=history, overwrite=False) + else: + export_evokeds(export_fname, evoked, overwrite=False) + + if do_history: + export_evokeds_mff(export_fname, evoked, history=history, overwrite=True) + else: + export_evokeds(export_fname, evoked, overwrite=True) + + # test export from evoked directly + evoked[0].export(export_fname, overwrite=True) + + +@testing.requires_testing_data +def test_export_to_mff_no_device(): + """Test no device type throws ValueError.""" + pytest.importorskip("mffpy", "0.5.7") + pytest.importorskip("defusedxml") + evoked = read_evokeds_mff(egi_evoked_fname, condition="Category 1") + evoked.info["device_info"] = None + with pytest.raises(ValueError, match="No device type."): + export_evokeds("output.mff", evoked) + + +def test_export_to_mff_incompatible_sfreq(): + """Test non-whole number sampling frequency throws ValueError.""" + pytest.importorskip("mffpy", "0.5.7") + evoked = read_evokeds(fname_evoked) + with pytest.raises(ValueError, match=f"sfreq: {evoked[0].info['sfreq']}"): + export_evokeds("output.mff", evoked) + + +@pytest.mark.parametrize( + "fmt,ext", + [("EEGLAB", "set"), ("EDF", "edf"), ("BrainVision", "vhdr"), ("auto", "vhdr")], +) +def test_export_evokeds_unsupported_format(fmt, ext): + """Test exporting evoked dataset to non-supported formats.""" + evoked = read_evokeds(fname_evoked) + errstr = fmt.lower() if fmt != "auto" else "vhdr" + with pytest.raises(ValueError, match=f"Format '{errstr}' is not .*"): + export_evokeds(f"output.{ext}", evoked, fmt=fmt) + + +@edfio_mark() +@pytest.mark.parametrize( + ("input_path", "warning_msg"), + [ + (fname_raw, "Data has a non-integer"), + pytest.param( + misc_path / "ecog" / "sample_ecog_ieeg.fif", + "BDF format requires", + marks=[pytest.mark.slowtest, misc._pytest_mark()], + ), + ], +) +def test_export_raw_bdf(tmp_path, input_path, warning_msg): + """Test saving a Raw instance to BDF format.""" + raw = read_raw_fif(input_path) + + # only test with EEG channels + raw.pick(picks=["eeg", "ecog", "seeg"]).load_data() + temp_fname = tmp_path / "test.bdf" + + with pytest.warns(RuntimeWarning, match=warning_msg): + raw.export(temp_fname) + + if "epoc" in raw.ch_names: + raw.drop_channels(["epoc"]) + + raw_read = read_raw_bdf(temp_fname, preload=True) + assert raw.ch_names == raw_read.ch_names + # only compare the original length, since extra zeros are appended + orig_raw_len = len(raw) + + # assert data and times are not different + # Due to the physical range of the data, reading and writing is not lossless. For + # example, a physical min/max of -/+ 3200 uV will result in a resolution of 0.38 nV. + # This resolution is more than sufficient for EEG. + assert_array_almost_equal( + raw.get_data(), raw_read.get_data()[:, :orig_raw_len], decimal=11 + ) + + # Due to the data record duration limitations of BDF files, one cannot store + # arbitrary float sampling rate exactly. Usually this results in two sampling rates + # that are off by very low number of decimal points. This for practical purposes + # does not matter but will result in an error when say the number of time points is + # very very large. + assert_allclose(raw.times, raw_read.times[:orig_raw_len], rtol=0, atol=1e-5) diff --git a/mne-python/source/mne/filter.py b/mne-python/source/mne/filter.py new file mode 100644 index 0000000000000000000000000000000000000000..f8f4abf6499fe6b052a161e1255cfa0c650bf295 --- /dev/null +++ b/mne-python/source/mne/filter.py @@ -0,0 +1,2956 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""IIR and FIR filtering and resampling functions.""" + +from collections import Counter +from copy import deepcopy +from functools import partial +from math import gcd + +import numpy as np +from scipy import fft, signal +from scipy.stats import f as fstat + +from ._fiff.pick import _picks_to_idx +from ._ola import _COLA +from .cuda import ( + _fft_multiply_repeated, + _fft_resample, + _setup_cuda_fft_multiply_repeated, + _setup_cuda_fft_resample, + _smart_pad, +) +from .fixes import _reshape_view, minimum_phase +from .parallel import parallel_func +from .utils import ( + _check_option, + _check_preload, + _ensure_int, + _pl, + _validate_type, + logger, + sum_squared, + verbose, + warn, +) + +# These values from Ifeachor and Jervis. +_length_factors = dict(hann=3.1, hamming=3.3, blackman=5.0) + + +def next_fast_len(target): + """Find the next fast size of input data to `fft`, for zero-padding, etc. + + SciPy's FFTPACK has efficient functions for radix {2, 3, 4, 5}, so this + returns the next composite of the prime factors 2, 3, and 5 which is + greater than or equal to `target`. (These are also known as 5-smooth + numbers, regular numbers, or Hamming numbers.) + + Parameters + ---------- + target : int + Length to start searching from. Must be a positive integer. + + Returns + ------- + out : int + The first 5-smooth number greater than or equal to `target`. + + Notes + ----- + Copied from SciPy with minor modifications. + """ + from bisect import bisect_left + + hams = ( + 8, + 9, + 10, + 12, + 15, + 16, + 18, + 20, + 24, + 25, + 27, + 30, + 32, + 36, + 40, + 45, + 48, + 50, + 54, + 60, + 64, + 72, + 75, + 80, + 81, + 90, + 96, + 100, + 108, + 120, + 125, + 128, + 135, + 144, + 150, + 160, + 162, + 180, + 192, + 200, + 216, + 225, + 240, + 243, + 250, + 256, + 270, + 288, + 300, + 320, + 324, + 360, + 375, + 384, + 400, + 405, + 432, + 450, + 480, + 486, + 500, + 512, + 540, + 576, + 600, + 625, + 640, + 648, + 675, + 720, + 729, + 750, + 768, + 800, + 810, + 864, + 900, + 960, + 972, + 1000, + 1024, + 1080, + 1125, + 1152, + 1200, + 1215, + 1250, + 1280, + 1296, + 1350, + 1440, + 1458, + 1500, + 1536, + 1600, + 1620, + 1728, + 1800, + 1875, + 1920, + 1944, + 2000, + 2025, + 2048, + 2160, + 2187, + 2250, + 2304, + 2400, + 2430, + 2500, + 2560, + 2592, + 2700, + 2880, + 2916, + 3000, + 3072, + 3125, + 3200, + 3240, + 3375, + 3456, + 3600, + 3645, + 3750, + 3840, + 3888, + 4000, + 4050, + 4096, + 4320, + 4374, + 4500, + 4608, + 4800, + 4860, + 5000, + 5120, + 5184, + 5400, + 5625, + 5760, + 5832, + 6000, + 6075, + 6144, + 6250, + 6400, + 6480, + 6561, + 6750, + 6912, + 7200, + 7290, + 7500, + 7680, + 7776, + 8000, + 8100, + 8192, + 8640, + 8748, + 9000, + 9216, + 9375, + 9600, + 9720, + 10000, + ) + + if target <= 6: + return target + + # Quickly check if it's already a power of 2 + if not (target & (target - 1)): + return target + + # Get result quickly for small sizes, since FFT itself is similarly fast. + if target <= hams[-1]: + return hams[bisect_left(hams, target)] + + match = float("inf") # Anything found will be smaller + p5 = 1 + while p5 < target: + p35 = p5 + while p35 < target: + # Ceiling integer division, avoiding conversion to float + # (quotient = ceil(target / p35)) + quotient = -(-target // p35) + + p2 = 2 ** int(quotient - 1).bit_length() + + N = p2 * p35 + if N == target: + return N + elif N < match: + match = N + p35 *= 3 + if p35 == target: + return p35 + if p35 < match: + match = p35 + p5 *= 5 + if p5 == target: + return p5 + if p5 < match: + match = p5 + return match + + +def _overlap_add_filter( + x, + h, + n_fft=None, + phase="zero", + picks=None, + n_jobs=None, + copy=True, + pad="reflect_limited", +): + """Filter the signal x using h with overlap-add FFTs.""" + # set up array for filtering, reshape to 2D, operate on last axis + x, orig_shape, picks = _prep_for_filtering(x, copy, picks) + # Extend the signal by mirroring the edges to reduce transient filter + # response + _check_zero_phase_length(len(h), phase) + if len(h) == 1: + return x * h**2 if phase == "zero-double" else x * h + n_edge = max(min(len(h), x.shape[1]) - 1, 0) + logger.debug(f"Smart-padding with: {n_edge} samples on each edge") + n_x = x.shape[1] + 2 * n_edge + + if phase == "zero-double": + h = np.convolve(h, h[::-1]) + + # Determine FFT length to use + min_fft = 2 * len(h) - 1 + if n_fft is None: + max_fft = n_x + if max_fft >= min_fft: + # cost function based on number of multiplications + N = 2 ** np.arange( + np.ceil(np.log2(min_fft)), np.ceil(np.log2(max_fft)) + 1, dtype=int + ) + cost = ( + np.ceil(n_x / (N - len(h) + 1).astype(np.float64)) + * N + * (np.log2(N) + 1) + ) + + # add a heuristic term to prevent too-long FFT's which are slow + # (not predicted by mult. cost alone, 4e-5 exp. determined) + cost += 4e-5 * N * n_x + + n_fft = N[np.argmin(cost)] + else: + # Use only a single block + n_fft = next_fast_len(min_fft) + logger.debug(f"FFT block length: {n_fft}") + if n_fft < min_fft: + raise ValueError( + f"n_fft is too short, has to be at least 2 * len(h) - 1 ({min_fft}), got " + f"{n_fft}" + ) + + # Figure out if we should use CUDA + n_jobs, cuda_dict = _setup_cuda_fft_multiply_repeated(n_jobs, h, n_fft) + + # Process each row separately + picks = _picks_to_idx(len(x), picks) + parallel, p_fun, _ = parallel_func(_1d_overlap_filter, n_jobs) + if n_jobs == 1: + for p in picks: + x[p] = _1d_overlap_filter( + x[p], len(h), n_edge, phase, cuda_dict, pad, n_fft + ) + else: + data_new = parallel( + p_fun(x[p], len(h), n_edge, phase, cuda_dict, pad, n_fft) for p in picks + ) + for pp, p in enumerate(picks): + x[p] = data_new[pp] + + x = _reshape_view(x, orig_shape) + return x + + +def _1d_overlap_filter(x, n_h, n_edge, phase, cuda_dict, pad, n_fft): + """Do one-dimensional overlap-add FFT FIR filtering.""" + # pad to reduce ringing + x_ext = _smart_pad(x, (n_edge, n_edge), pad) + n_x = len(x_ext) + x_filtered = np.zeros_like(x_ext) + + n_seg = n_fft - n_h + 1 + n_segments = int(np.ceil(n_x / float(n_seg))) + shift = ((n_h - 1) // 2 if phase.startswith("zero") else 0) + n_edge + + # Now the actual filtering step is identical for zero-phase (filtfilt-like) + # or single-pass + for seg_idx in range(n_segments): + start = seg_idx * n_seg + stop = (seg_idx + 1) * n_seg + seg = x_ext[start:stop] + seg = np.concatenate([seg, np.zeros(n_fft - len(seg))]) + + prod = _fft_multiply_repeated(seg, cuda_dict) + + start_filt = max(0, start - shift) + stop_filt = min(start - shift + n_fft, n_x) + start_prod = max(0, shift - start) + stop_prod = start_prod + stop_filt - start_filt + x_filtered[start_filt:stop_filt] += prod[start_prod:stop_prod] + + # Remove mirrored edges that we added and cast (n_edge can be zero) + x_filtered = x_filtered[: n_x - 2 * n_edge].astype(x.dtype) + return x_filtered + + +def _filter_attenuation(h, freq, gain): + """Compute minimum attenuation at stop frequency.""" + _, filt_resp = signal.freqz(h.ravel(), worN=np.pi * freq) + filt_resp = np.abs(filt_resp) # use amplitude response + filt_resp[np.where(gain == 1)] = 0 + idx = np.argmax(filt_resp) + att_db = -20 * np.log10(np.maximum(filt_resp[idx], 1e-20)) + att_freq = freq[idx] + return att_db, att_freq + + +def _prep_for_filtering(x, copy, picks=None): + """Set up array as 2D for filtering ease.""" + x = _check_filterable(x) + if copy is True: + x = x.copy() + orig_shape = x.shape + x = np.atleast_2d(x) + picks = _picks_to_idx(x.shape[-2], picks) + x = _reshape_view(x, (np.prod(x.shape[:-1]), x.shape[-1])) + if len(orig_shape) == 3: + n_epochs, n_channels, n_times = orig_shape + offset = np.repeat(np.arange(0, n_channels * n_epochs, n_channels), len(picks)) + picks = np.tile(picks, n_epochs) + offset + elif len(orig_shape) > 3: + raise ValueError( + "picks argument is not supported for data with more than three dimensions" + ) + assert all(0 <= pick < x.shape[0] for pick in picks) # guaranteed by above + + return x, orig_shape, picks + + +def _firwin_design(N, freq, gain, window, sfreq): + """Construct a FIR filter using firwin.""" + assert freq[0] == 0 + assert len(freq) > 1 + assert len(freq) == len(gain) + assert N % 2 == 1 + h = np.zeros(N) + prev_freq = freq[-1] + prev_gain = gain[-1] + if gain[-1] == 1: + h[N // 2] = 1 # start with "all up" + assert prev_gain in (0, 1) + for this_freq, this_gain in zip(freq[::-1][1:], gain[::-1][1:]): + assert this_gain in (0, 1) + if this_gain != prev_gain: + # Get the correct N to satisfy the requested transition bandwidth + transition = (prev_freq - this_freq) / 2.0 + this_N = int(round(_length_factors[window] / transition)) + this_N += 1 - this_N % 2 # make it odd + if this_N > N: + raise ValueError( + f"The requested filter length {N} is too short for the requested " + f"{transition * sfreq / 2.0:0.2f} Hz transition band, which " + f"requires {this_N} samples" + ) + # Construct a lowpass + this_h = signal.firwin( + this_N, + (prev_freq + this_freq) / 2.0, + window=window, + pass_zero=True, + fs=freq[-1] * 2, + ) + assert this_h.shape == (this_N,) + offset = (N - this_N) // 2 + if this_gain == 0: + h[offset : N - offset] -= this_h + else: + h[offset : N - offset] += this_h + prev_gain = this_gain + prev_freq = this_freq + return h + + +def _construct_fir_filter( + sfreq, freq, gain, filter_length, phase, fir_window, fir_design +): + """Filter signal using gain control points in the frequency domain. + + The filter impulse response is constructed from a Hann window (window + used in "firwin2" function) to avoid ripples in the frequency response + (windowing is a smoothing in frequency domain). + + If x is multi-dimensional, this operates along the last dimension. + """ + assert freq[0] == 0 + if fir_design == "firwin2": + fir_design = signal.firwin2 + else: + assert fir_design == "firwin" + fir_design = partial(_firwin_design, sfreq=sfreq) + # issue a warning if attenuation is less than this + min_att_db = 12 if phase == "minimum-half" else 20 + + # normalize frequencies + freq = np.array(freq) / (sfreq / 2.0) + if freq[0] != 0 or freq[-1] != 1: + raise ValueError( + f"freq must start at 0 and end an Nyquist ({sfreq / 2.0}), got {freq}" + ) + gain = np.array(gain) + + # Use overlap-add filter with a fixed length + N = _check_zero_phase_length(filter_length, phase, gain[-1]) + # construct symmetric (linear phase) filter + if phase == "minimum-half": + h = fir_design(N * 2 - 1, freq, gain, window=fir_window) + h = minimum_phase(h) + else: + h = fir_design(N, freq, gain, window=fir_window) + if phase == "minimum": + h = minimum_phase(h, half=False) + assert h.size == N + att_db, att_freq = _filter_attenuation(h, freq, gain) + if phase == "zero-double": + att_db += 6 + if att_db < min_att_db: + att_freq *= sfreq / 2.0 + warn( + f"Attenuation at stop frequency {att_freq:0.2f} Hz is only {att_db:0.2f} " + "dB. Increase filter_length for higher attenuation." + ) + return h + + +def _check_zero_phase_length(N, phase, gain_nyq=0): + N = int(N) + if N % 2 == 0: + if phase == "zero": + raise RuntimeError(f'filter_length must be odd if phase="zero", got {N}') + elif phase == "zero-double" and gain_nyq == 1: + N += 1 + return N + + +def _check_coefficients(system): + """Check for filter stability.""" + if isinstance(system, tuple): + z, p, k = signal.tf2zpk(*system) + else: # sos + z, p, k = signal.sos2zpk(system) + if np.any(np.abs(p) > 1.0): + raise RuntimeError( + "Filter poles outside unit circle, filter will be " + "unstable. Consider using different filter " + "coefficients." + ) + + +def _iir_filter(x, iir_params, picks, n_jobs, copy, phase="zero"): + """Call filtfilt or lfilter.""" + # set up array for filtering, reshape to 2D, operate on last axis + x, orig_shape, picks = _prep_for_filtering(x, copy, picks) + if phase in ("zero", "zero-double"): + padlen = min(iir_params["padlen"], x.shape[-1] - 1) + if "sos" in iir_params: + fun = partial( + _iir_pad_apply_unpad, + func=signal.sosfiltfilt, + sos=iir_params["sos"], + padlen=padlen, + padtype="reflect_limited", + ) + _check_coefficients(iir_params["sos"]) + else: + fun = partial( + _iir_pad_apply_unpad, + func=signal.filtfilt, + b=iir_params["b"], + a=iir_params["a"], + padlen=padlen, + padtype="reflect_limited", + ) + _check_coefficients((iir_params["b"], iir_params["a"])) + else: + if "sos" in iir_params: + fun = partial(signal.sosfilt, sos=iir_params["sos"], axis=-1) + _check_coefficients(iir_params["sos"]) + else: + fun = partial(signal.lfilter, b=iir_params["b"], a=iir_params["a"], axis=-1) + _check_coefficients((iir_params["b"], iir_params["a"])) + parallel, p_fun, n_jobs = parallel_func(fun, n_jobs) + if n_jobs == 1: + for p in picks: + x[p] = fun(x=x[p]) + else: + data_new = parallel(p_fun(x=x[p]) for p in picks) + for pp, p in enumerate(picks): + x[p] = data_new[pp] + x = _reshape_view(x, orig_shape) + return x + + +def estimate_ringing_samples(system, max_try=100000): + """Estimate filter ringing. + + Parameters + ---------- + system : tuple | ndarray + A tuple of (b, a) or ndarray of second-order sections coefficients. + max_try : int + Approximate maximum number of samples to try. + This will be changed to a multiple of 1000. + + Returns + ------- + n : int + The approximate ringing. + """ + if isinstance(system, tuple): # TF + kind = "ba" + b, a = system + zi = [0.0] * (len(a) - 1) + else: + kind = "sos" + sos = system + zi = [[0.0] * 2] * len(sos) + n_per_chunk = 1000 + n_chunks_max = int(np.ceil(max_try / float(n_per_chunk))) + x = np.zeros(n_per_chunk) + x[0] = 1 + last_good = n_per_chunk + thresh_val = 0 + for ii in range(n_chunks_max): + if kind == "ba": + h, zi = signal.lfilter(b, a, x, zi=zi) + else: + h, zi = signal.sosfilt(sos, x, zi=zi) + x[0] = 0 # for subsequent iterations we want zero input + h = np.abs(h) + thresh_val = max(0.001 * np.max(h), thresh_val) + idx = np.where(np.abs(h) > thresh_val)[0] + if len(idx) > 0: + last_good = idx[-1] + else: # this iteration had no sufficiently lange values + idx = (ii - 1) * n_per_chunk + last_good + break + else: + warn("Could not properly estimate ringing for the filter") + idx = n_per_chunk * n_chunks_max + return idx + + +_ftype_dict = { + "butter": "Butterworth", + "cheby1": "Chebyshev I", + "cheby2": "Chebyshev II", + "ellip": "Cauer/elliptic", + "bessel": "Bessel/Thomson", +} + + +@verbose +def construct_iir_filter( + iir_params, + f_pass=None, + f_stop=None, + sfreq=None, + btype=None, + return_copy=True, + *, + phase="zero", + verbose=None, +): + """Use IIR parameters to get filtering coefficients. + + This function works like a wrapper for iirdesign and iirfilter in + scipy.signal to make filter coefficients for IIR filtering. It also + estimates the number of padding samples based on the filter ringing. + It creates a new iir_params dict (or updates the one passed to the + function) with the filter coefficients ('b' and 'a') and an estimate + of the padding necessary ('padlen') so IIR filtering can be performed. + + Parameters + ---------- + iir_params : dict + Dictionary of parameters to use for IIR filtering. + + * If ``iir_params['sos']`` exists, it will be used as + second-order sections to perform IIR filtering. + + .. versionadded:: 0.13 + + * Otherwise, if ``iir_params['b']`` and ``iir_params['a']`` + exist, these will be used as coefficients to perform IIR + filtering. + * Otherwise, if ``iir_params['order']`` and + ``iir_params['ftype']`` exist, these will be used with + `scipy.signal.iirfilter` to make a filter. + You should also supply ``iir_params['rs']`` and + ``iir_params['rp']`` if using elliptic or Chebychev filters. + * Otherwise, if ``iir_params['gpass']`` and + ``iir_params['gstop']`` exist, these will be used with + `scipy.signal.iirdesign` to design a filter. + * ``iir_params['padlen']`` defines the number of samples to pad + (and an estimate will be calculated if it is not given). + See Notes for more details. + * ``iir_params['output']`` defines the system output kind when + designing filters, either "sos" or "ba". For 0.13 the + default is 'ba' but will change to 'sos' in 0.14. + + f_pass : float or list of float + Frequency for the pass-band. Low-pass and high-pass filters should + be a float, band-pass should be a 2-element list of float. + f_stop : float or list of float + Stop-band frequency (same size as f_pass). Not used if 'order' is + specified in iir_params. + sfreq : float | None + The sample rate. + btype : str + Type of filter. Should be 'lowpass', 'highpass', or 'bandpass' + (or analogous string representations known to + :func:`scipy.signal.iirfilter`). + return_copy : bool + If False, the 'sos', 'b', 'a', and 'padlen' entries in + ``iir_params`` will be set inplace (if they weren't already). + Otherwise, a new ``iir_params`` instance will be created and + returned with these entries. + phase : str + Phase of the filter. + ``phase='zero'`` (default) or equivalently ``'zero-double'`` constructs and + applies IIR filter twice, once forward, and once backward (making it non-causal) + using :func:`~scipy.signal.filtfilt`; ``phase='forward'`` will apply + the filter once in the forward (causal) direction using + :func:`~scipy.signal.lfilter`. + + .. versionadded:: 0.13 + %(verbose)s + + Returns + ------- + iir_params : dict + Updated iir_params dict, with the entries (set only if they didn't + exist before) for 'sos' (or 'b', 'a'), and 'padlen' for + IIR filtering. + + See Also + -------- + mne.filter.filter_data + mne.io.Raw.filter + + Notes + ----- + This function triages calls to :func:`scipy.signal.iirfilter` and + :func:`scipy.signal.iirdesign` based on the input arguments (see + linked functions for more details). + + .. versionchanged:: 0.14 + Second-order sections are used in filter design by default (replacing + ``output='ba'`` by ``output='sos'``) to help ensure filter stability + and reduce numerical error. + + Examples + -------- + iir_params can have several forms. Consider constructing a low-pass + filter at 40 Hz with 1000 Hz sampling rate. + + In the most basic (2-parameter) form of iir_params, the order of the + filter 'N' and the type of filtering 'ftype' are specified. To get + coefficients for a 4th-order Butterworth filter, this would be: + + >>> iir_params = dict(order=4, ftype='butter', output='sos') # doctest:+SKIP + >>> iir_params = construct_iir_filter(iir_params, 40, None, 1000, 'low', return_copy=False) # doctest:+SKIP + >>> print((2 * len(iir_params['sos']), iir_params['padlen'])) # doctest:+SKIP + (4, 82) + + Filters can also be constructed using filter design methods. To get a + 40 Hz Chebyshev type 1 lowpass with specific gain characteristics in the + pass and stop bands (assuming the desired stop band is at 45 Hz), this + would be a filter with much longer ringing: + + >>> iir_params = dict(ftype='cheby1', gpass=3, gstop=20, output='sos') # doctest:+SKIP + >>> iir_params = construct_iir_filter(iir_params, 40, 50, 1000, 'low') # doctest:+SKIP + >>> print((2 * len(iir_params['sos']), iir_params['padlen'])) # doctest:+SKIP + (6, 439) + + Padding and/or filter coefficients can also be manually specified. For + a 10-sample moving window with no padding during filtering, for example, + one can just do: + + >>> iir_params = dict(b=np.ones((10)), a=[1, 0], padlen=0) # doctest:+SKIP + >>> iir_params = construct_iir_filter(iir_params, return_copy=False) # doctest:+SKIP + >>> print((iir_params['b'], iir_params['a'], iir_params['padlen'])) # doctest:+SKIP + (array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]), [1, 0], 0) + + For more information, see the tutorials + :ref:`disc-filtering` and :ref:`tut-filter-resample`. + """ # noqa: E501 + known_filters = ( + "bessel", + "butter", + "butterworth", + "cauer", + "cheby1", + "cheby2", + "chebyshev1", + "chebyshev2", + "chebyshevi", + "chebyshevii", + "ellip", + "elliptic", + ) + if not isinstance(iir_params, dict): + raise TypeError(f"iir_params must be a dict, got {type(iir_params)}") + # if the filter has been designed, we're good to go + Wp = None + if "sos" in iir_params: + system = iir_params["sos"] + output = "sos" + elif "a" in iir_params and "b" in iir_params: + system = (iir_params["b"], iir_params["a"]) + output = "ba" + else: + output = iir_params.get("output", "sos") + _check_option("output", output, ("ba", "sos")) + # ensure we have a valid ftype + if "ftype" not in iir_params: + raise RuntimeError( + "ftype must be an entry in iir_params if 'b' and 'a' are not specified." + ) + ftype = iir_params["ftype"] + if ftype not in known_filters: + raise RuntimeError( + "ftype must be in filter_dict from scipy.signal (e.g., butter, cheby1, " + f"etc.) not {ftype}" + ) + + # use order-based design + f_pass = np.atleast_1d(f_pass) + if f_pass.ndim > 1: + raise ValueError(f"frequencies must be 1D, got {f_pass.ndim}D") + edge_freqs = ", ".join(f"{f:0.2f}" for f in f_pass) + Wp = f_pass / (float(sfreq) / 2) + # IT will de designed + ftype_nice = _ftype_dict.get(ftype, ftype) + _validate_type(phase, str, "phase") + _check_option("phase", phase, ("zero", "zero-double", "forward")) + if phase in ("zero-double", "zero"): + ptype = "zero-phase (two-pass forward and reverse) non-causal" + else: + ptype = "non-linear phase (one-pass forward) causal" + logger.info("") + logger.info("IIR filter parameters") + logger.info("---------------------") + logger.info(f"{ftype_nice} {btype} {ptype} filter:") + # SciPy designs forward for -3dB, so forward-backward is -6dB + if "order" in iir_params: + singleton = btype in ("low", "lowpass", "high", "highpass") + use_Wp = Wp.item() if singleton else Wp + kwargs = dict( + N=iir_params["order"], + Wn=use_Wp, + btype=btype, + ftype=ftype, + output=output, + ) + for key in ("rp", "rs"): + if key in iir_params: + kwargs[key] = iir_params[key] + system = signal.iirfilter(**kwargs) + if phase in ("zero", "zero-double"): + ptype, pmul = "(effective, after forward-backward)", 2 + else: + ptype, pmul = "(forward)", 1 + logger.info( + "- Filter order %d %s", pmul * iir_params["order"] * len(Wp), ptype + ) + else: + # use gpass / gstop design + Ws = np.asanyarray(f_stop) / (float(sfreq) / 2) + if "gpass" not in iir_params or "gstop" not in iir_params: + raise ValueError( + "iir_params must have at least 'gstop' and 'gpass' (or N) entries." + ) + system = signal.iirdesign( + Wp, + Ws, + iir_params["gpass"], + iir_params["gstop"], + ftype=ftype, + output=output, + ) + + if system is None: + raise RuntimeError("coefficients could not be created from iir_params") + # do some sanity checks + _check_coefficients(system) + + # get the gains at the cutoff frequencies + if Wp is not None: + if output == "sos": + cutoffs = signal.sosfreqz(system, worN=Wp * np.pi)[1] + else: + cutoffs = signal.freqz(system[0], system[1], worN=Wp * np.pi)[1] + cutoffs = 20 * np.log10(np.abs(cutoffs)) + # 2 * 20 here because we do forward-backward filtering + if phase in ("zero", "zero-double"): + cutoffs *= 2 + cutoffs = ", ".join([f"{c:0.2f}" for c in cutoffs]) + logger.info(f"- Cutoff{_pl(f_pass)} at {edge_freqs} Hz: {cutoffs} dB") + # now deal with padding + if "padlen" not in iir_params: + padlen = estimate_ringing_samples(system) + else: + padlen = iir_params["padlen"] + + if return_copy: + iir_params = deepcopy(iir_params) + + iir_params.update(dict(padlen=padlen)) + if output == "sos": + iir_params.update(sos=system) + else: + iir_params.update(b=system[0], a=system[1]) + logger.info("") + return iir_params + + +def _check_method(method, iir_params, extra_types=()): + """Parse method arguments.""" + allowed_types = ["iir", "fir", "fft"] + list(extra_types) + _validate_type(method, "str", "method") + _check_option("method", method, allowed_types) + if method == "fft": + method = "fir" # use the better name + if method == "iir": + if iir_params is None: + iir_params = dict() + if len(iir_params) == 0 or (len(iir_params) == 1 and "output" in iir_params): + iir_params = dict( + order=4, ftype="butter", output=iir_params.get("output", "sos") + ) + elif iir_params is not None: + raise ValueError('iir_params must be None if method != "iir"') + return iir_params, method + + +@verbose +def filter_data( + data, + sfreq, + l_freq, + h_freq, + picks=None, + filter_length="auto", + l_trans_bandwidth="auto", + h_trans_bandwidth="auto", + n_jobs=None, + method="fir", + iir_params=None, + copy=True, + phase="zero", + fir_window="hamming", + fir_design="firwin", + pad="reflect_limited", + *, + verbose=None, +): + """Filter a subset of channels. + + Parameters + ---------- + data : ndarray, shape (..., n_times) + The data to filter. + sfreq : float + The sample frequency in Hz. + %(l_freq)s + %(h_freq)s + %(picks_nostr)s + Currently this is only supported for 2D (n_channels, n_times) and + 3D (n_epochs, n_channels, n_times) arrays. + %(filter_length)s + %(l_trans_bandwidth)s + %(h_trans_bandwidth)s + %(n_jobs_fir)s + %(method_fir)s + %(iir_params)s + copy : bool + If True, a copy of x, filtered, is returned. Otherwise, it operates + on x in place. + %(phase)s + %(fir_window)s + %(fir_design)s + %(pad_fir)s + The default is ``'reflect_limited'``. + + .. versionadded:: 0.15 + %(verbose)s + + Returns + ------- + data : ndarray, shape (..., n_times) + The filtered data. + + See Also + -------- + construct_iir_filter + create_filter + mne.io.Raw.filter + notch_filter + resample + + Notes + ----- + Applies a zero-phase low-pass, high-pass, band-pass, or band-stop + filter to the channels selected by ``picks``. + + ``l_freq`` and ``h_freq`` are the frequencies below which and above + which, respectively, to filter out of the data. Thus the uses are: + + * ``l_freq < h_freq``: band-pass filter + * ``l_freq > h_freq``: band-stop filter + * ``l_freq is not None and h_freq is None``: high-pass filter + * ``l_freq is None and h_freq is not None``: low-pass filter + + .. note:: If n_jobs > 1, more memory is required as + ``len(picks) * n_times`` additional time points need to + be temporarily stored in memory. + + For more information, see the tutorials + :ref:`disc-filtering` and :ref:`tut-filter-resample` and + :func:`mne.filter.create_filter`. + """ + data = _check_filterable(data) + iir_params, method = _check_method(method, iir_params) + filt = create_filter( + data, + sfreq, + l_freq, + h_freq, + filter_length, + l_trans_bandwidth, + h_trans_bandwidth, + method, + iir_params, + phase, + fir_window, + fir_design, + ) + if method in ("fir", "fft"): + data = _overlap_add_filter(data, filt, None, phase, picks, n_jobs, copy, pad) + else: + data = _iir_filter(data, filt, picks, n_jobs, copy, phase) + return data + + +@verbose +def create_filter( + data, + sfreq, + l_freq, + h_freq, + filter_length="auto", + l_trans_bandwidth="auto", + h_trans_bandwidth="auto", + method="fir", + iir_params=None, + phase="zero", + fir_window="hamming", + fir_design="firwin", + verbose=None, +): + r"""Create a FIR or IIR filter. + + ``l_freq`` and ``h_freq`` are the frequencies below which and above + which, respectively, to filter out of the data. Thus the uses are: + + * ``l_freq < h_freq``: band-pass filter + * ``l_freq > h_freq``: band-stop filter + * ``l_freq is not None and h_freq is None``: high-pass filter + * ``l_freq is None and h_freq is not None``: low-pass filter + + Parameters + ---------- + data : ndarray, shape (..., n_times) | None + The data that will be filtered. This is used for sanity checking + only. If None, no sanity checking related to the length of the signal + relative to the filter order will be performed. + sfreq : float + The sample frequency in Hz. + %(l_freq)s + %(h_freq)s + %(filter_length)s + %(l_trans_bandwidth)s + %(h_trans_bandwidth)s + %(method_fir)s + %(iir_params)s + %(phase)s + %(fir_window)s + %(fir_design)s + %(verbose)s + + Returns + ------- + filt : array or dict + Will be an array of FIR coefficients for method='fir', and dict + with IIR parameters for method='iir'. + + See Also + -------- + filter_data + + Notes + ----- + .. note:: For FIR filters, the *cutoff frequency*, i.e. the -6 dB point, + is in the middle of the transition band (when using phase='zero' + and fir_design='firwin'). For IIR filters, the cutoff frequency + is given by ``l_freq`` or ``h_freq`` directly, and + ``l_trans_bandwidth`` and ``h_trans_bandwidth`` are ignored. + + **Band-pass filter** + + The frequency response is (approximately) given by:: + + 1-| ---------- + | /| | \ + |H| | / | | \ + | / | | \ + | / | | \ + 0-|---------- | | -------------- + | | | | | | + 0 Fs1 Fp1 Fp2 Fs2 Nyq + + Where: + + * Fs1 = Fp1 - l_trans_bandwidth in Hz + * Fs2 = Fp2 + h_trans_bandwidth in Hz + + **Band-stop filter** + + The frequency response is (approximately) given by:: + + 1-|--------- ---------- + | \ / + |H| | \ / + | \ / + | \ / + 0-| ----------- + | | | | | | + 0 Fp1 Fs1 Fs2 Fp2 Nyq + + Where ``Fs1 = Fp1 + l_trans_bandwidth`` and + ``Fs2 = Fp2 - h_trans_bandwidth``. + + Multiple stop bands can be specified using arrays. + + **Low-pass filter** + + The frequency response is (approximately) given by:: + + 1-|------------------------ + | \ + |H| | \ + | \ + | \ + 0-| ---------------- + | | | | + 0 Fp Fstop Nyq + + Where ``Fstop = Fp + trans_bandwidth``. + + **High-pass filter** + + The frequency response is (approximately) given by:: + + 1-| ----------------------- + | / + |H| | / + | / + | / + 0-|--------- + | | | | + 0 Fstop Fp Nyq + + Where ``Fstop = Fp - trans_bandwidth``. + + .. versionadded:: 0.14 + """ + sfreq = float(sfreq) + if sfreq < 0: + raise ValueError("sfreq must be positive") + # If no data specified, sanity checking will be skipped + if data is None: + logger.info( + "No data specified. Sanity checks related to the length of the signal " + "relative to the filter order will be skipped." + ) + if h_freq is not None: + h_freq = np.array(h_freq, float).ravel() + if (h_freq > (sfreq / 2.0)).any(): + raise ValueError( + f"h_freq ({h_freq}) must be less than the Nyquist frequency " + f"{sfreq / 2.0}" + ) + if l_freq is not None: + l_freq = np.array(l_freq, float).ravel() + if (l_freq == 0).all(): + l_freq = None + iir_params, method = _check_method(method, iir_params) + if l_freq is None and h_freq is None: + ( + data, + sfreq, + _, + _, + _, + _, + filter_length, + phase, + fir_window, + fir_design, + ) = _triage_filter_params( + data, + sfreq, + None, + None, + None, + None, + filter_length, + method, + phase, + fir_window, + fir_design, + ) + if method == "iir": + out = dict() if iir_params is None else deepcopy(iir_params) + out.update(b=np.array([1.0]), a=np.array([1.0])) + else: + freq = [0, sfreq / 2.0] + gain = [1.0, 1.0] + if l_freq is None and h_freq is not None: + h_freq = h_freq.item() + logger.info(f"Setting up low-pass filter at {h_freq:0.2g} Hz") + ( + data, + sfreq, + _, + f_p, + _, + f_s, + filter_length, + phase, + fir_window, + fir_design, + ) = _triage_filter_params( + data, + sfreq, + None, + h_freq, + None, + h_trans_bandwidth, + filter_length, + method, + phase, + fir_window, + fir_design, + ) + if method == "iir": + out = construct_iir_filter( + iir_params, f_p, f_s, sfreq, "lowpass", phase=phase + ) + else: # 'fir' + freq = [0, f_p, f_s] + gain = [1, 1, 0] + if f_s != sfreq / 2.0: + freq += [sfreq / 2.0] + gain += [0] + elif l_freq is not None and h_freq is None: + l_freq = l_freq.item() + logger.info(f"Setting up high-pass filter at {l_freq:0.2g} Hz") + ( + data, + sfreq, + pass_, + _, + stop, + _, + filter_length, + phase, + fir_window, + fir_design, + ) = _triage_filter_params( + data, + sfreq, + l_freq, + None, + l_trans_bandwidth, + None, + filter_length, + method, + phase, + fir_window, + fir_design, + ) + if method == "iir": + out = construct_iir_filter( + iir_params, pass_, stop, sfreq, "highpass", phase=phase + ) + else: # 'fir' + freq = [stop, pass_, sfreq / 2.0] + gain = [0, 1, 1] + if stop != 0: + freq = [0] + freq + gain = [0] + gain + elif l_freq is not None and h_freq is not None: + if (l_freq < h_freq).any(): + l_freq, h_freq = l_freq.item(), h_freq.item() + logger.info( + f"Setting up band-pass filter from {l_freq:0.2g} - {h_freq:0.2g} Hz" + ) + ( + data, + sfreq, + f_p1, + f_p2, + f_s1, + f_s2, + filter_length, + phase, + fir_window, + fir_design, + ) = _triage_filter_params( + data, + sfreq, + l_freq, + h_freq, + l_trans_bandwidth, + h_trans_bandwidth, + filter_length, + method, + phase, + fir_window, + fir_design, + ) + if method == "iir": + out = construct_iir_filter( + iir_params, + [f_p1, f_p2], + [f_s1, f_s2], + sfreq, + "bandpass", + phase=phase, + ) + else: # 'fir' + freq = [f_s1, f_p1, f_p2, f_s2] + gain = [0, 1, 1, 0] + if f_s2 != sfreq / 2.0: + freq += [sfreq / 2.0] + gain += [0] + if f_s1 != 0: + freq = [0] + freq + gain = [0] + gain + else: + # This could possibly be removed after 0.14 release, but might + # as well leave it in to sanity check notch_filter + if len(l_freq) != len(h_freq): + raise ValueError("l_freq and h_freq must be the same length") + msg = "Setting up band-stop filter" + if len(l_freq) == 1: + l_freq, h_freq = l_freq.item(), h_freq.item() + msg += f" from {h_freq:0.2g} - {l_freq:0.2g} Hz" + logger.info(msg) + # Note: order of outputs is intentionally switched here! + ( + data, + sfreq, + f_s1, + f_s2, + f_p1, + f_p2, + filter_length, + phase, + fir_window, + fir_design, + ) = _triage_filter_params( + data, + sfreq, + h_freq, + l_freq, + h_trans_bandwidth, + l_trans_bandwidth, + filter_length, + method, + phase, + fir_window, + fir_design, + bands="arr", + reverse=True, + ) + if method == "iir": + if len(f_p1) != 1: + raise ValueError( + "Multiple stop-bands can only be used with method='fir' " + "and method='spectrum_fit'" + ) + out = construct_iir_filter( + iir_params, + [f_p1[0], f_p2[0]], + [f_s1[0], f_s2[0]], + sfreq, + "bandstop", + phase=phase, + ) + else: # 'fir' + freq = np.r_[f_p1, f_s1, f_s2, f_p2] + gain = np.r_[ + np.ones_like(f_p1), + np.zeros_like(f_s1), + np.zeros_like(f_s2), + np.ones_like(f_p2), + ] + order = np.argsort(freq) + freq = freq[order] + gain = gain[order] + if freq[0] != 0: + freq = np.r_[[0.0], freq] + gain = np.r_[[1.0], gain] + if freq[-1] != sfreq / 2.0: + freq = np.r_[freq, [sfreq / 2.0]] + gain = np.r_[gain, [1.0]] + if np.any(np.abs(np.diff(gain, 2)) > 1): + raise ValueError("Stop bands are not sufficiently separated.") + if method == "fir": + out = _construct_fir_filter( + sfreq, freq, gain, filter_length, phase, fir_window, fir_design + ) + return out + + +@verbose +def notch_filter( + x, + Fs, + freqs, + filter_length="auto", + notch_widths=None, + trans_bandwidth=1, + method="fir", + iir_params=None, + mt_bandwidth=None, + p_value=0.05, + picks=None, + n_jobs=None, + copy=True, + phase="zero", + fir_window="hamming", + fir_design="firwin", + pad="reflect_limited", + *, + verbose=None, +): + r"""Notch filter for the signal x. + + Applies a zero-phase notch filter to the signal x, operating on the last + dimension. + + Parameters + ---------- + x : array + Signal to filter. + Fs : float + Sampling rate in Hz. + freqs : float | array of float | None + Frequencies to notch filter in Hz, e.g. np.arange(60, 241, 60). + Multiple stop-bands can only be used with method='fir' + and method='spectrum_fit'. None can only be used with the mode + 'spectrum_fit', where an F test is used to find sinusoidal components. + %(filter_length_notch)s + notch_widths : float | array of float | None + Width of the stop band (centred at each freq in freqs) in Hz. + If None, freqs / 200 is used. + trans_bandwidth : float + Width of the transition band in Hz. + Only used for ``method='fir'`` and ``method='iir'``. + %(method_fir)s + 'spectrum_fit' will use multi-taper estimation of sinusoidal + components. If freqs=None and method='spectrum_fit', significant + sinusoidal components are detected using an F test, and noted by + logging. + %(iir_params)s + mt_bandwidth : float | None + The bandwidth of the multitaper windowing function in Hz. + Only used in 'spectrum_fit' mode. + p_value : float + P-value to use in F-test thresholding to determine significant + sinusoidal components to remove when method='spectrum_fit' and + freqs=None. Note that this will be Bonferroni corrected for the + number of frequencies, so large p-values may be justified. + %(picks_nostr)s + Only supported for 2D (n_channels, n_times) and 3D + (n_epochs, n_channels, n_times) data. + %(n_jobs_fir)s + copy : bool + If True, a copy of x, filtered, is returned. Otherwise, it operates + on x in place. + %(phase)s + %(fir_window)s + %(fir_design)s + %(pad_fir)s + The default is ``'reflect_limited'``. + %(verbose)s + + Returns + ------- + xf : array + The x array filtered. + + See Also + -------- + filter_data + resample + + Notes + ----- + The frequency response is (approximately) given by:: + + 1-|---------- ----------- + | \ / + |H| | \ / + | \ / + | \ / + 0-| - + | | | | | + 0 Fp1 freq Fp2 Nyq + + For each freq in freqs, where ``Fp1 = freq - trans_bandwidth / 2`` and + ``Fs2 = freq + trans_bandwidth / 2``. + + References + ---------- + Multi-taper removal is inspired by code from the Chronux toolbox, see + www.chronux.org and the book "Observed Brain Dynamics" by Partha Mitra + & Hemant Bokil, Oxford University Press, New York, 2008. Please + cite this in publications if method 'spectrum_fit' is used. + """ + x = _check_filterable(x, "notch filtered", "notch_filter") + iir_params, method = _check_method(method, iir_params, ["spectrum_fit"]) + + if freqs is not None: + freqs = np.atleast_1d(freqs) + elif method != "spectrum_fit": + raise ValueError("freqs=None can only be used with method spectrum_fit") + + # Only have to deal with notch_widths for non-autodetect + if freqs is not None: + if notch_widths is None: + notch_widths = freqs / 200.0 + elif np.any(notch_widths < 0): + raise ValueError("notch_widths must be >= 0") + else: + notch_widths = np.atleast_1d(notch_widths) + if len(notch_widths) == 1: + notch_widths = notch_widths[0] * np.ones_like(freqs) + elif len(notch_widths) != len(freqs): + raise ValueError( + "notch_widths must be None, scalar, or the same length as freqs" + ) + + if method in ("fir", "iir"): + # Speed this up by computing the fourier coefficients once + tb_2 = trans_bandwidth / 2.0 + lows = [freq - nw / 2.0 - tb_2 for freq, nw in zip(freqs, notch_widths)] + highs = [freq + nw / 2.0 + tb_2 for freq, nw in zip(freqs, notch_widths)] + xf = filter_data( + x, + Fs, + highs, + lows, + picks, + filter_length, + tb_2, + tb_2, + n_jobs, + method, + iir_params, + copy, + phase, + fir_window, + fir_design, + pad=pad, + ) + elif method == "spectrum_fit": + xf = _mt_spectrum_proc( + x, + Fs, + freqs, + notch_widths, + mt_bandwidth, + p_value, + picks, + n_jobs, + copy, + filter_length, + ) + + return xf + + +def _get_window_thresh(n_times, sfreq, mt_bandwidth, p_value): + from .time_frequency.multitaper import _compute_mt_params + + # figure out what tapers to use + window_fun, _, _ = _compute_mt_params( + n_times, sfreq, mt_bandwidth, False, False, verbose=False + ) + + # F-stat of 1-p point + threshold = fstat.ppf(1 - p_value / n_times, 2, 2 * len(window_fun) - 2) + return window_fun, threshold + + +def _mt_spectrum_proc( + x, + sfreq, + line_freqs, + notch_widths, + mt_bandwidth, + p_value, + picks, + n_jobs, + copy, + filter_length, +): + """Call _mt_spectrum_remove.""" + # set up array for filtering, reshape to 2D, operate on last axis + x, orig_shape, picks = _prep_for_filtering(x, copy, picks) + if isinstance(filter_length, str) and filter_length == "auto": + filter_length = "10s" + if filter_length is None: + filter_length = x.shape[-1] + filter_length = min(_to_samples(filter_length, sfreq, "", ""), x.shape[-1]) + get_wt = partial( + _get_window_thresh, sfreq=sfreq, mt_bandwidth=mt_bandwidth, p_value=p_value + ) + window_fun, threshold = get_wt(filter_length) + parallel, p_fun, n_jobs = parallel_func(_mt_spectrum_remove_win, n_jobs) + if n_jobs == 1: + freq_list = list() + for ii, x_ in enumerate(x): + if ii in picks: + x[ii], f = _mt_spectrum_remove_win( + x_, sfreq, line_freqs, notch_widths, window_fun, threshold, get_wt + ) + freq_list.append(f) + else: + data_new = parallel( + p_fun(x_, sfreq, line_freqs, notch_widths, window_fun, threshold, get_wt) + for xi, x_ in enumerate(x) + if xi in picks + ) + freq_list = [d[1] for d in data_new] + data_new = np.array([d[0] for d in data_new]) + x[picks, :] = data_new + + # report found frequencies, but do some sanitizing first by binning into + # 1 Hz bins + counts = Counter( + sum((np.unique(np.round(ff)).tolist() for f in freq_list for ff in f), list()) + ) + kind = "Detected" if line_freqs is None else "Removed" + found_freqs = ( + "\n".join( + f" {freq:6.2f} : {counts[freq]:4d} window{_pl(counts[freq])}" + for freq in sorted(counts) + ) + or " None" + ) + logger.info(f"{kind} notch frequencies (Hz):\n{found_freqs}") + + x = _reshape_view(x, orig_shape) + return x + + +def _mt_spectrum_remove_win( + x, sfreq, line_freqs, notch_widths, window_fun, threshold, get_thresh +): + n_times = x.shape[-1] + n_samples = window_fun.shape[1] + n_overlap = (n_samples + 1) // 2 + x_out = np.zeros_like(x) + rm_freqs = list() + + # Define how to process a chunk of data + def process(x_, *, start, stop): + out = _mt_spectrum_remove( + x_, sfreq, line_freqs, notch_widths, window_fun, threshold, get_thresh + ) + rm_freqs.append(out[1]) + return (out[0],) # must return a tuple + + _COLA(process, x_out, n_times, n_samples, n_overlap, sfreq, verbose=False).feed(x) + return x_out, rm_freqs + + +def _mt_spectrum_remove( + x, sfreq, line_freqs, notch_widths, window_fun, threshold, get_thresh +): + """Use MT-spectrum to remove line frequencies. + + Based on Chronux. If line_freqs is specified, all freqs within notch_width + of each line_freq is set to zero. + """ + from .time_frequency.multitaper import _mt_spectra + + assert x.ndim == 1 + if x.shape[-1] != window_fun.shape[-1]: + window_fun, threshold = get_thresh(x.shape[-1]) + # drop the even tapers + n_tapers = len(window_fun) + tapers_odd = np.arange(0, n_tapers, 2) + tapers_even = np.arange(1, n_tapers, 2) + tapers_use = window_fun[tapers_odd] + + # sum tapers for (used) odd prolates across time (n_tapers, 1) + H0 = np.sum(tapers_use, axis=1) + + # sum of squares across tapers (1, ) + H0_sq = sum_squared(H0) + + # make "time" vector + rads = 2 * np.pi * (np.arange(x.size) / float(sfreq)) + + # compute mt_spectrum (returning n_ch, n_tapers, n_freq) + x_p, freqs = _mt_spectra(x[np.newaxis, :], window_fun, sfreq) + + # sum of the product of x_p and H0 across tapers (1, n_freqs) + x_p_H0 = np.sum(x_p[:, tapers_odd, :] * H0[np.newaxis, :, np.newaxis], axis=1) + + # resulting calculated amplitudes for all freqs + A = x_p_H0 / H0_sq + + if line_freqs is None: + # figure out which freqs to remove using F stat + + # estimated coefficient + x_hat = A * H0[:, np.newaxis] + + # numerator for F-statistic + num = (n_tapers - 1) * (A * A.conj()).real * H0_sq + # denominator for F-statistic + den = np.sum(np.abs(x_p[:, tapers_odd, :] - x_hat) ** 2, 1) + np.sum( + np.abs(x_p[:, tapers_even, :]) ** 2, 1 + ) + den[den == 0] = np.inf + f_stat = num / den + + # find frequencies to remove + indices = np.where(f_stat > threshold)[1] + rm_freqs = freqs[indices] + else: + # specify frequencies + indices_1 = np.unique([np.argmin(np.abs(freqs - lf)) for lf in line_freqs]) + indices_2 = [ + np.logical_and(freqs > lf - nw / 2.0, freqs < lf + nw / 2.0) + for lf, nw in zip(line_freqs, notch_widths) + ] + indices_2 = np.where(np.any(np.array(indices_2), axis=0))[0] + indices = np.unique(np.r_[indices_1, indices_2]) + rm_freqs = freqs[indices] + + fits = list() + for ind in indices: + c = 2 * A[0, ind] + fit = np.abs(c) * np.cos(freqs[ind] * rads + np.angle(c)) + fits.append(fit) + + if len(fits) == 0: + datafit = 0.0 + else: + # fitted sinusoids are summed, and subtracted from data + datafit = np.sum(fits, axis=0) + + return x - datafit, rm_freqs + + +def _check_filterable(x, kind="filtered", alternative="filter"): + # Let's be fairly strict about this -- users can easily coerce to ndarray + # at their end, and we already should do it internally any time we are + # using these low-level functions. At the same time, let's + # help people who might accidentally use low-level functions that they + # shouldn't use by pushing them in the right direction + from .epochs import BaseEpochs + from .evoked import Evoked + from .io import BaseRaw + + if isinstance(x, BaseRaw | BaseEpochs | Evoked): + try: + name = x.__class__.__name__ + except Exception: + pass + else: + raise TypeError( + "This low-level function only operates on np.ndarray instances. To get " + f"a {kind} {name} instance, use a method like `inst_new = inst.copy()." + f"{alternative}(...)` instead." + ) + _validate_type(x, (np.ndarray, list, tuple), f"Data to be {kind}") + x = np.asanyarray(x) + if x.dtype != np.float64: + raise ValueError(f"Data to be {kind} must be real floating, got {x.dtype}") + return x + + +def _resamp_ratio_len(up, down, n): + ratio = float(up) / down + return ratio, max(int(round(ratio * n)), 1) + + +@verbose +def resample( + x, + up=1.0, + down=1.0, + *, + axis=-1, + window="auto", + n_jobs=None, + pad="auto", + npad=100, + method="fft", + verbose=None, +): + """Resample an array. + + Operates along the last dimension of the array. + + Parameters + ---------- + x : ndarray + Signal to resample. + up : float + Factor to upsample by. + down : float + Factor to downsample by. + axis : int + Axis along which to resample (default is the last axis). + %(window_resample)s + %(n_jobs_cuda)s + ``n_jobs='cuda'`` is only supported when ``method="fft"``. + %(pad_resample_auto)s + + .. versionadded:: 0.15 + %(npad_resample)s + %(method_resample)s + + .. versionadded:: 1.7 + %(verbose)s + + Returns + ------- + y : array + The x array resampled. + + Notes + ----- + When using ``method="fft"`` (default), + this uses (hopefully) intelligent edge padding and frequency-domain + windowing improve :func:`scipy.signal.resample`'s resampling method, which + we have adapted for our use here. Choices of npad and window have + important consequences, and the default choices should work well + for most natural signals. + """ + _validate_type(method, str, "method") + _validate_type(pad, str, "pad") + _check_option("method", method, ("fft", "polyphase")) + + # make sure our arithmetic will work + x = _check_filterable(x, "resampled", "resample") + ratio, final_len = _resamp_ratio_len(up, down, x.shape[axis]) + del up, down + if axis < 0: + axis = x.ndim + axis + if x.shape[axis] == 0: + warn(f"x has zero length along axis={axis}, returning a copy of x") + return x.copy() + + # prep for resampling along the last axis (swap axis with last then reshape) + out_shape = list(x.shape) + out_shape.pop(axis) + out_shape.append(final_len) + x = np.atleast_2d(x.swapaxes(axis, -1).reshape((-1, x.shape[axis]))) + + # do the resampling using FFT or polyphase methods + kwargs = dict(pad=pad, window=window, n_jobs=n_jobs) + if method == "fft": + y = _resample_fft(x, npad=npad, ratio=ratio, final_len=final_len, **kwargs) + else: + up, down, kwargs["window"] = _prep_polyphase( + ratio, x.shape[-1], final_len, window + ) + half_len = len(window) // 2 + logger.info( + f"Polyphase resampling neighborhood: ±{half_len} " + f"input sample{_pl(half_len)}" + ) + y = _resample_polyphase(x, up=up, down=down, **kwargs) + assert y.shape[-1] == final_len + + # restore dimensions (reshape then swap axis with last) + y = y.reshape(out_shape).swapaxes(axis, -1) + + return y + + +def _prep_polyphase(ratio, x_len, final_len, window): + if isinstance(window, str) and window == "auto": + window = ("kaiser", 5.0) # SciPy default + up = final_len + down = x_len + g_ = gcd(up, down) + up = up // g_ + down = down // g_ + # Figure out our signal neighborhood and design window (adapted from SciPy) + if not isinstance(window, list | np.ndarray): + # Design a linear-phase low-pass FIR filter + max_rate = max(up, down) + f_c = 1.0 / max_rate # cutoff of FIR filter (rel. to Nyquist) + half_len = 10 * max_rate # reasonable cutoff for sinc-like function + window = signal.firwin(2 * half_len + 1, f_c, window=window) + return up, down, window + + +def _resample_polyphase(x, *, up, down, pad, window, n_jobs): + if pad == "auto": + pad = "reflect" + kwargs = dict(padtype=pad, window=window, up=up, down=down) + _validate_type( + n_jobs, (None, "int-like"), "n_jobs", extra="when method='polyphase'" + ) + parallel, p_fun, n_jobs = parallel_func(signal.resample_poly, n_jobs) + if n_jobs == 1: + y = signal.resample_poly(x, axis=-1, **kwargs) + else: + y = np.array(parallel(p_fun(x_, **kwargs) for x_ in x)) + return y + + +def _resample_fft(x_flat, *, ratio, final_len, pad, window, npad, n_jobs): + x_len = x_flat.shape[-1] + pad = "reflect_limited" if pad == "auto" else pad + if (isinstance(window, str) and window == "auto") or window is None: + window = "boxcar" + if isinstance(npad, str): + _check_option("npad", npad, ("auto",), extra="when a string") + # Figure out reasonable pad that gets us to a power of 2 + min_add = min(x_len // 8, 100) * 2 + npad = 2 ** int(np.ceil(np.log2(x_len + min_add))) - x_len + npad, extra = divmod(npad, 2) + npads = np.array([npad, npad + extra], int) + else: + npad = _ensure_int(npad, "npad", extra="or 'auto'") + npads = np.array([npad, npad], int) + del npad + + # prep for resampling now + orig_len = x_len + npads.sum() # length after padding + new_len = max(int(round(ratio * orig_len)), 1) # length after resampling + to_removes = [int(round(ratio * npads[0]))] + to_removes.append(new_len - final_len - to_removes[0]) + to_removes = np.array(to_removes) + # This should hold: + # assert np.abs(to_removes[1] - to_removes[0]) <= int(np.ceil(ratio)) + + # figure out windowing function + if callable(window): + W = window(fft.fftfreq(orig_len)) + elif isinstance(window, np.ndarray) and window.shape == (orig_len,): + W = window + else: + W = fft.ifftshift(signal.get_window(window, orig_len)) + W *= float(new_len) / float(orig_len) + + # figure out if we should use CUDA + n_jobs, cuda_dict = _setup_cuda_fft_resample(n_jobs, W, new_len) + + # do the resampling using an adaptation of scipy's FFT-based resample() + # use of the 'flat' window is recommended for minimal ringing + parallel, p_fun, n_jobs = parallel_func(_fft_resample, n_jobs) + if n_jobs == 1: + y = np.zeros((len(x_flat), new_len - to_removes.sum()), dtype=x_flat.dtype) + for xi, x_ in enumerate(x_flat): + y[xi] = _fft_resample(x_, new_len, npads, to_removes, cuda_dict, pad) + else: + y = parallel( + p_fun(x_, new_len, npads, to_removes, cuda_dict, pad) for x_ in x_flat + ) + y = np.array(y) + + return y + + +def _resample_stim_channels(stim_data, up, down): + """Resample stim channels, carefully. + + Parameters + ---------- + stim_data : array, shape (n_samples,) or (n_stim_channels, n_samples) + Stim channels to resample. + up : float + Factor to upsample by. + down : float + Factor to downsample by. + + Returns + ------- + stim_resampled : array, shape (n_stim_channels, n_samples_resampled) + The resampled stim channels. + + Note + ---- + The approach taken here is equivalent to the approach in the C-code. + See the decimate_stimch function in MNE/mne_browse_raw/save.c + """ + stim_data = np.atleast_2d(stim_data) + n_stim_channels, n_samples = stim_data.shape + + ratio = float(up) / down + resampled_n_samples = int(round(n_samples * ratio)) + + stim_resampled = np.zeros((n_stim_channels, resampled_n_samples)) + + # Figure out which points in old data to subsample protect against + # out-of-bounds, which can happen (having one sample more than + # expected) due to padding + sample_picks = np.minimum( + (np.arange(resampled_n_samples) / ratio).astype(int), n_samples - 1 + ) + + # Create windows starting from sample_picks[i], ending at sample_picks[i+1] + windows = zip(sample_picks, np.r_[sample_picks[1:], n_samples]) + + # Use the first non-zero value in each window + for window_i, window in enumerate(windows): + for stim_num, stim in enumerate(stim_data): + nonzero = stim[window[0] : window[1]].nonzero()[0] + if len(nonzero) > 0: + val = stim[window[0] + nonzero[0]] + else: + val = stim[window[0]] + stim_resampled[stim_num, window_i] = val + + return stim_resampled + + +def detrend(x, order=1, axis=-1): + """Detrend the array x. + + Parameters + ---------- + x : n-d array + Signal to detrend. + order : int + Fit order. Currently must be '0' or '1'. + axis : int + Axis of the array to operate on. + + Returns + ------- + y : array + The x array detrended. + + Examples + -------- + As in :func:`scipy.signal.detrend`:: + + >>> randgen = np.random.RandomState(9) + >>> npoints = int(1e3) + >>> noise = randgen.randn(npoints) + >>> x = 3 + 2*np.linspace(0, 1, npoints) + noise + >>> bool((detrend(x) - noise).max() < 0.01) + True + """ + if axis > len(x.shape): + raise ValueError(f"x does not have {axis} axes") + if order == 0: + fit = "constant" + elif order == 1: + fit = "linear" + else: + raise ValueError("order must be 0 or 1") + + y = signal.detrend(x, axis=axis, type=fit) + + return y + + +# Taken from Ifeachor and Jervis p. 356. +# Note that here the passband ripple and stopband attenuation are +# rendundant. The scalar passband ripple δp is expressed in dB as +# 20 * log10(1+δp), but the scalar stopband ripple δs is expressed in dB as +# -20 * log10(δs). So if we know that our stopband attenuation is 53 dB +# (Hamming) then δs = 10 ** (53 / -20.), which means that the passband +# deviation should be 20 * np.log10(1 + 10 ** (53 / -20.)) == 0.0194. +_fir_window_dict = { + "hann": dict(name="Hann", ripple=0.0546, attenuation=44), + "hamming": dict(name="Hamming", ripple=0.0194, attenuation=53), + "blackman": dict(name="Blackman", ripple=0.0017, attenuation=74), +} +_known_fir_windows = tuple(sorted(_fir_window_dict.keys())) +_known_phases_fir = ("linear", "zero", "zero-double", "minimum", "minimum-half") +_known_phases_iir = ("zero", "zero-double", "forward") +_known_fir_designs = ("firwin", "firwin2") +_fir_design_dict = { + "firwin": "Windowed time-domain", + "firwin2": "Windowed frequency-domain", +} + + +def _to_samples(filter_length, sfreq, phase, fir_design): + _validate_type(filter_length, (str, "int-like"), "filter_length") + if isinstance(filter_length, str): + filter_length = filter_length.lower() + err_msg = ( + "filter_length, if a string, must be a " + 'human-readable time, e.g. "10s", or "auto", not ' + f'"{filter_length}"' + ) + if filter_length.lower().endswith("ms"): + mult_fact = 1e-3 + filter_length = filter_length[:-2] + elif filter_length[-1].lower() == "s": + mult_fact = 1 + filter_length = filter_length[:-1] + else: + raise ValueError(err_msg) + # now get the number + try: + filter_length = float(filter_length) + except ValueError: + raise ValueError(err_msg) + filter_length = max(int(np.ceil(filter_length * mult_fact * sfreq)), 1) + if fir_design == "firwin": + filter_length += (filter_length - 1) % 2 + filter_length = _ensure_int(filter_length, "filter_length") + return filter_length + + +def _triage_filter_params( + x, + sfreq, + l_freq, + h_freq, + l_trans_bandwidth, + h_trans_bandwidth, + filter_length, + method, + phase, + fir_window, + fir_design, + bands="scalar", + reverse=False, +): + """Validate and automate filter parameter selection.""" + _validate_type(phase, "str", "phase") + if method == "fir": + _check_option("phase", phase, _known_phases_fir, extra="when FIR filtering") + else: + _check_option("phase", phase, _known_phases_iir, extra="when IIR filtering") + _validate_type(fir_window, "str", "fir_window") + _check_option("fir_window", fir_window, _known_fir_windows) + _validate_type(fir_design, "str", "fir_design") + _check_option("fir_design", fir_design, _known_fir_designs) + + # Helpers for reporting + report_phase = "non-linear phase" if phase == "minimum" else "zero-phase" + causality = "causal" if phase == "minimum" else "non-causal" + if phase == "zero-double": + report_pass = "two-pass forward and reverse" + else: + report_pass = "one-pass" + if l_freq is not None: + if h_freq is not None: + kind = "bandstop" if reverse else "bandpass" + else: + kind = "highpass" + assert not reverse + elif h_freq is not None: + kind = "lowpass" + assert not reverse + else: + kind = "allpass" + + def float_array(c): + return np.array(c, float).ravel() + + if bands == "arr": + cast = float_array + else: + cast = float + sfreq = float(sfreq) + if l_freq is not None: + l_freq = cast(l_freq) + if np.any(l_freq <= 0): + raise ValueError(f"highpass frequency {l_freq} must be greater than zero") + if h_freq is not None: + h_freq = cast(h_freq) + if np.any(h_freq >= sfreq / 2.0): + raise ValueError( + f"lowpass frequency {h_freq} must be less than Nyquist ({sfreq / 2.0})" + ) + + dB_cutoff = False # meaning, don't try to compute or report + if bands == "scalar" or (len(h_freq) == 1 and len(l_freq) == 1): + if phase == "zero": + dB_cutoff = "-6 dB" + elif phase == "zero-double": + dB_cutoff = "-12 dB" + + # we go to the next power of two when in FIR and zero-double mode + if method == "iir": + # Ignore these parameters, effectively + l_stop, h_stop = l_freq, h_freq + else: # method == 'fir' + l_stop = h_stop = None + logger.info("") + logger.info("FIR filter parameters") + logger.info("---------------------") + logger.info( + f"Designing a {report_pass}, {report_phase}, {causality} {kind} filter:" + ) + logger.info(f"- {_fir_design_dict[fir_design]} design ({fir_design}) method") + this_dict = _fir_window_dict[fir_window] + if fir_design == "firwin": + logger.info( + "- {name:s} window with {ripple:0.4f} passband ripple " + "and {attenuation:d} dB stopband attenuation".format(**this_dict) + ) + else: + logger.info("- {name:s} window".format(**this_dict)) + + if l_freq is not None: # high-pass component + if isinstance(l_trans_bandwidth, str): + if l_trans_bandwidth != "auto": + raise ValueError( + 'l_trans_bandwidth must be "auto" if string, got "' + f'{l_trans_bandwidth}"' + ) + l_trans_bandwidth = np.minimum(np.maximum(0.25 * l_freq, 2.0), l_freq) + l_trans_rep = np.array(l_trans_bandwidth, float) + if l_trans_rep.size == 1: + l_trans_rep = f"{l_trans_rep.item():0.2f}" + with np.printoptions(precision=2, floatmode="fixed"): + msg = f"- Lower transition bandwidth: {l_trans_rep} Hz" + if dB_cutoff: + l_freq_rep = np.array(l_freq, float) + if l_freq_rep.size == 1: + l_freq_rep = f"{l_freq_rep.item():0.2f}" + cutoff_rep = np.array(l_freq - l_trans_bandwidth / 2.0, float) + if cutoff_rep.size == 1: + cutoff_rep = f"{cutoff_rep.item():0.2f}" + # Could be an array + logger.info(f"- Lower passband edge: {l_freq_rep}") + msg += f" ({dB_cutoff} cutoff frequency: {cutoff_rep} Hz)" + logger.info(msg) + l_trans_bandwidth = cast(l_trans_bandwidth) + if np.any(l_trans_bandwidth <= 0): + raise ValueError( + f"l_trans_bandwidth must be positive, got {l_trans_bandwidth}" + ) + l_stop = l_freq - l_trans_bandwidth + if reverse: # band-stop style + l_stop += l_trans_bandwidth + l_freq += l_trans_bandwidth + if np.any(l_stop < 0): + raise ValueError( + "Filter specification invalid: Lower stop frequency negative (" + f"{l_stop:0.2f} Hz). Increase pass frequency or reduce the " + "transition bandwidth (l_trans_bandwidth)" + ) + if h_freq is not None: # low-pass component + if isinstance(h_trans_bandwidth, str): + if h_trans_bandwidth != "auto": + raise ValueError( + 'h_trans_bandwidth must be "auto" if ' + f'string, got "{h_trans_bandwidth}"' + ) + h_trans_bandwidth = np.minimum( + np.maximum(0.25 * h_freq, 2.0), sfreq / 2.0 - h_freq + ) + h_trans_rep = np.array(h_trans_bandwidth, float) + if h_trans_rep.size == 1: + h_trans_rep = f"{h_trans_rep.item():0.2f}" + with np.printoptions(precision=2, floatmode="fixed"): + msg = f"- Upper transition bandwidth: {h_trans_rep} Hz" + if dB_cutoff: + h_freq_rep = np.array(h_freq, float) + if h_freq_rep.size == 1: + h_freq_rep = f"{h_freq_rep.item():0.2f}" + cutoff_rep = np.array(h_freq + h_trans_bandwidth / 2.0, float) + if cutoff_rep.size == 1: + cutoff_rep = f"{cutoff_rep.item():0.2f}" + logger.info(f"- Upper passband edge: {h_freq_rep} Hz") + msg += f" ({dB_cutoff} cutoff frequency: {cutoff_rep} Hz)" + logger.info(msg) + h_trans_bandwidth = cast(h_trans_bandwidth) + if np.any(h_trans_bandwidth <= 0): + raise ValueError( + f"h_trans_bandwidth must be positive, got {h_trans_bandwidth}" + ) + h_stop = h_freq + h_trans_bandwidth + if reverse: # band-stop style + h_stop -= h_trans_bandwidth + h_freq -= h_trans_bandwidth + if np.any(h_stop > sfreq / 2): + raise ValueError( + f"Effective band-stop frequency ({h_stop}) is too high (maximum " + f"based on Nyquist is {sfreq / 2.0})" + ) + + if isinstance(filter_length, str) and filter_length.lower() == "auto": + filter_length = filter_length.lower() + h_check = l_check = np.inf + if h_freq is not None: + h_check = min(np.atleast_1d(h_trans_bandwidth)) + if l_freq is not None: + l_check = min(np.atleast_1d(l_trans_bandwidth)) + mult_fact = 2.0 if fir_design == "firwin2" else 1.0 + filter_length = f"{_length_factors[fir_window] * mult_fact / float(min(h_check, l_check))}s" # noqa: E501 + next_pow_2 = False # disable old behavior + else: + next_pow_2 = isinstance(filter_length, str) and phase == "zero-double" + + filter_length = _to_samples(filter_length, sfreq, phase, fir_design) + + # use correct type of filter (must be odd length for firwin and for + # zero phase) + if fir_design == "firwin" or phase == "zero": + filter_length += (filter_length - 1) % 2 + + logger.info( + f"- Filter length: {filter_length} samples ({filter_length / sfreq:0.3f} s)" + ) + logger.info("") + + if filter_length <= 0: + raise ValueError(f"filter_length must be positive, got {filter_length}") + + if next_pow_2: + filter_length = 2 ** int(np.ceil(np.log2(filter_length))) + if fir_design == "firwin": + filter_length += (filter_length - 1) % 2 + + # If we have data supplied, do a sanity check + if x is not None: + x = _check_filterable(x) + len_x = x.shape[-1] + if method != "fir": + filter_length = len_x + if filter_length > len_x and not (l_freq is None and h_freq is None): + warn( + f"filter_length ({filter_length}) is longer than the signal ({len_x}), " + "distortion is likely. Reduce filter length or filter a longer signal." + ) + + logger.debug(f"Using filter length: {filter_length}") + return ( + x, + sfreq, + l_freq, + h_freq, + l_stop, + h_stop, + filter_length, + phase, + fir_window, + fir_design, + ) + + +def _check_resamp_noop(sfreq, o_sfreq, rtol=1e-6): + if np.isclose(sfreq, o_sfreq, atol=0, rtol=rtol): + logger.info( + f"Sampling frequency of the instance is already {sfreq}, returning " + "unmodified." + ) + return True + return False + + +class FilterMixin: + """Object for Epoch/Evoked filtering.""" + + @verbose + def savgol_filter(self, h_freq, verbose=None): + """Filter the data using Savitzky-Golay polynomial method. + + Parameters + ---------- + h_freq : float + Approximate high cut-off frequency in Hz. Note that this + is not an exact cutoff, since Savitzky-Golay filtering + :footcite:`SavitzkyGolay1964` is done using polynomial fits + instead of FIR/IIR filtering. This parameter is thus used to + determine the length of the window over which a 5th-order + polynomial smoothing is used. + %(verbose)s + + Returns + ------- + inst : same type as the input data + The object with the filtering applied. + + See Also + -------- + mne.io.Raw.filter + + Notes + ----- + For Savitzky-Golay low-pass approximation, see: + + https://gist.github.com/larsoner/bbac101d50176611136b + + When working on SourceEstimates the sample rate of the original data is inferred from tstep. + + .. versionadded:: 0.9.0 + + References + ---------- + .. footbibliography:: + + Examples + -------- + >>> import mne + >>> from os import path as op + >>> evoked_fname = op.join(mne.datasets.sample.data_path(), 'MEG', 'sample', 'sample_audvis-ave.fif') # doctest:+SKIP + >>> evoked = mne.read_evokeds(evoked_fname, baseline=(None, 0))[0] # doctest:+SKIP + >>> evoked.savgol_filter(10.) # low-pass at around 10 Hz # doctest:+SKIP + >>> evoked.plot() # doctest:+SKIP + """ # noqa: E501 + from .source_estimate import _BaseSourceEstimate + + _check_preload(self, "inst.savgol_filter") + if not isinstance(self, _BaseSourceEstimate): + s_freq = self.info["sfreq"] + else: + s_freq = 1 / self.tstep + h_freq = float(h_freq) + if h_freq >= s_freq / 2.0: + raise ValueError("h_freq must be less than half the sample rate") + + # savitzky-golay filtering + window_length = (int(np.round(s_freq / h_freq)) // 2) * 2 + 1 + logger.info("Using savgol length %d", window_length) + self._data[:] = signal.savgol_filter( + self._data, axis=-1, polyorder=5, window_length=window_length + ) + return self + + @verbose + def filter( + self, + l_freq, + h_freq, + picks=None, + filter_length="auto", + l_trans_bandwidth="auto", + h_trans_bandwidth="auto", + n_jobs=None, + method="fir", + iir_params=None, + phase="zero", + fir_window="hamming", + fir_design="firwin", + skip_by_annotation=("edge", "bad_acq_skip"), + pad="edge", + *, + verbose=None, + ): + """Filter a subset of channels/vertices. + + Parameters + ---------- + %(l_freq)s + %(h_freq)s + %(picks_all_data)s + %(filter_length)s + %(l_trans_bandwidth)s + %(h_trans_bandwidth)s + %(n_jobs_fir)s + %(method_fir)s + %(iir_params)s + %(phase)s + %(fir_window)s + %(fir_design)s + %(skip_by_annotation)s + + .. versionadded:: 0.16. + %(pad_fir)s + %(verbose)s + + Returns + ------- + inst : same type as the input data + The filtered data. + + See Also + -------- + mne.filter.create_filter + mne.Evoked.savgol_filter + mne.io.Raw.notch_filter + mne.io.Raw.resample + mne.filter.create_filter + mne.filter.filter_data + mne.filter.construct_iir_filter + + Notes + ----- + Applies a zero-phase low-pass, high-pass, band-pass, or band-stop + filter to the channels selected by ``picks``. + The data are modified inplace. + + The object has to have the data loaded e.g. with ``preload=True`` + or ``self.load_data()``. + + ``l_freq`` and ``h_freq`` are the frequencies below which and above + which, respectively, to filter out of the data. Thus the uses are: + + * ``l_freq < h_freq``: band-pass filter + * ``l_freq > h_freq``: band-stop filter + * ``l_freq is not None and h_freq is None``: high-pass filter + * ``l_freq is None and h_freq is not None``: low-pass filter + + ``self.info['lowpass']`` and ``self.info['highpass']`` are only + updated with picks=None. + + .. note:: If n_jobs > 1, more memory is required as + ``len(picks) * n_times`` additional time points need to + be temporarily stored in memory. + + When working on SourceEstimates the sample rate of the original + data is inferred from tstep. + + For more information, see the tutorials + :ref:`disc-filtering` and :ref:`tut-filter-resample` and + :func:`mne.filter.create_filter`. + + .. versionadded:: 0.15 + """ + from .annotations import _annotations_starts_stops + from .io import BaseRaw + from .source_estimate import _BaseSourceEstimate + + _check_preload(self, "inst.filter") + if not isinstance(self, _BaseSourceEstimate): + update_info, picks = _filt_check_picks(self.info, picks, l_freq, h_freq) + s_freq = self.info["sfreq"] + else: + s_freq = 1.0 / self.tstep + if pad is None and method != "iir": + pad = "edge" + if isinstance(self, BaseRaw): + # Deal with annotations + onsets, ends = _annotations_starts_stops( + self, skip_by_annotation, invert=True + ) + logger.info( + "Filtering raw data in %d contiguous segment%s", + len(onsets), + _pl(onsets), + ) + else: + onsets, ends = np.array([0]), np.array([self._data.shape[1]]) + max_idx = (ends - onsets).argmax() + for si, (start, stop) in enumerate(zip(onsets, ends)): + # Only output filter params once (for info level), and only warn + # once about the length criterion (longest segment is too short) + use_verbose = verbose if si == max_idx else "error" + filter_data( + self._data[:, start:stop], + s_freq, + l_freq, + h_freq, + picks, + filter_length, + l_trans_bandwidth, + h_trans_bandwidth, + n_jobs, + method, + iir_params, + copy=False, + phase=phase, + fir_window=fir_window, + fir_design=fir_design, + pad=pad, + verbose=use_verbose, + ) + # update info if filter is applied to all data channels/vertices, + # and it's not a band-stop filter + if not isinstance(self, _BaseSourceEstimate): + _filt_update_info(self.info, update_info, l_freq, h_freq) + return self + + @verbose + def resample( + self, + sfreq, + *, + npad="auto", + window="auto", + n_jobs=None, + pad="edge", + method="fft", + verbose=None, + ): + """Resample data. + + If appropriate, an anti-aliasing filter is applied before resampling. + See :ref:`resampling-and-decimating` for more information. + + .. note:: Data must be loaded. + + Parameters + ---------- + sfreq : float + New sample rate to use. + %(npad)s + %(window_resample)s + %(n_jobs_cuda)s + %(pad_resample)s + + .. versionadded:: 0.15 + %(method_resample)s + + .. versionadded:: 1.7 + %(verbose)s + + Returns + ------- + inst : same type as the input data + The resampled object. + + See Also + -------- + mne.io.Raw.resample + + Notes + ----- + For some data, it may be more accurate to use npad=0 to reduce + artifacts. This is dataset dependent -- check your data! + """ + from .epochs import BaseEpochs + from .evoked import Evoked + + # Should be guaranteed by our inheritance, and the fact that + # mne.io.BaseRaw and _BaseSourceEstimate overrides this method + assert isinstance(self, BaseEpochs | Evoked) + + sfreq = float(sfreq) + o_sfreq = self.info["sfreq"] + if _check_resamp_noop(sfreq, o_sfreq): + return self + + _check_preload(self, "inst.resample") + self._data = resample( + self._data, + sfreq, + o_sfreq, + npad=npad, + window=window, + n_jobs=n_jobs, + pad=pad, + method=method, + ) + lowpass = self.info.get("lowpass") + lowpass = np.inf if lowpass is None else lowpass + with self.info._unlock(): + self.info["lowpass"] = min(lowpass, sfreq / 2.0) + self.info["sfreq"] = float(sfreq) + new_times = ( + np.arange(self._data.shape[-1], dtype=np.float64) / sfreq + self.times[0] + ) + # adjust indirectly affected variables + self._set_times(new_times) + self._raw_times = self.times + self._update_first_last() + return self + + @verbose + def apply_hilbert( + self, picks=None, envelope=False, n_jobs=None, n_fft="auto", *, verbose=None + ): + """Compute analytic signal or envelope for a subset of channels/vertices. + + Parameters + ---------- + %(picks_all_data_noref)s + envelope : bool + Compute the envelope signal of each channel/vertex. Default False. + See Notes. + %(n_jobs)s + n_fft : int | None | str + Points to use in the FFT for Hilbert transformation. The signal + will be padded with zeros before computing Hilbert, then cut back + to original length. If None, n == self.n_times. If 'auto', + the next highest fast FFT length will be use. + %(verbose)s + + Returns + ------- + self : instance of Raw, Epochs, Evoked or SourceEstimate + The raw object with transformed data. + + Notes + ----- + **Parameters** + + If ``envelope=False``, the analytic signal for the channels/vertices defined in + ``picks`` is computed and the data of the Raw object is converted to + a complex representation (the analytic signal is complex valued). + + If ``envelope=True``, the absolute value of the analytic signal for the + channels/vertices defined in ``picks`` is computed, resulting in the envelope + signal. + + .. warning: Do not use ``envelope=True`` if you intend to compute + an inverse solution from the raw data. If you want to + compute the envelope in source space, use + ``envelope=False`` and compute the envelope after the + inverse solution has been obtained. + + If envelope=False, more memory is required since the original raw data + as well as the analytic signal have temporarily to be stored in memory. + If n_jobs > 1, more memory is required as ``len(picks) * n_times`` + additional time points need to be temporarily stored in memory. + + Also note that the ``n_fft`` parameter will allow you to pad the signal + with zeros before performing the Hilbert transform. This padding + is cut off, but it may result in a slightly different result + (particularly around the edges). Use at your own risk. + + **Analytic signal** + + The analytic signal "x_a(t)" of "x(t)" is:: + + x_a = F^{-1}(F(x) 2U) = x + i y + + where "F" is the Fourier transform, "U" the unit step function, + and "y" the Hilbert transform of "x". One usage of the analytic + signal is the computation of the envelope signal, which is given by + "e(t) = abs(x_a(t))". Due to the linearity of Hilbert transform and the + MNE inverse solution, the enevlope in source space can be obtained + by computing the analytic signal in sensor space, applying the MNE + inverse, and computing the envelope in source space. + """ + from .source_estimate import _BaseSourceEstimate + + if not isinstance(self, _BaseSourceEstimate): + use_info = self.info + else: + use_info = len(self._data) + _check_preload(self, "inst.apply_hilbert") + picks = _picks_to_idx(use_info, picks, exclude=(), with_ref_meg=False) + + if n_fft is None: + n_fft = len(self.times) + elif isinstance(n_fft, str): + if n_fft != "auto": + raise ValueError( + f"n_fft must be an integer, string, or None, got {type(n_fft)}" + ) + n_fft = next_fast_len(len(self.times)) + n_fft = int(n_fft) + if n_fft < len(self.times): + raise ValueError( + f"n_fft ({n_fft}) must be at least the number of time points (" + f"{len(self.times)})" + ) + dtype = None if envelope else np.complex128 + args, kwargs = (), dict(n_fft=n_fft, envelope=envelope) + + data_in = self._data + if dtype is not None and dtype != self._data.dtype: + self._data = self._data.astype(dtype) + + parallel, p_fun, n_jobs = parallel_func(_check_fun, n_jobs) + if n_jobs == 1: + # modify data inplace to save memory + for idx in picks: + self._data[..., idx, :] = _check_fun( + _my_hilbert, data_in[..., idx, :], *args, **kwargs + ) + else: + # use parallel function + data_picks_new = parallel( + p_fun(_my_hilbert, data_in[..., p, :], *args, **kwargs) for p in picks + ) + for pp, p in enumerate(picks): + self._data[..., p, :] = data_picks_new[pp] + return self + + +def _check_fun(fun, d, *args, **kwargs): + """Check shapes.""" + want_shape = d.shape + d = fun(d, *args, **kwargs) + if not isinstance(d, np.ndarray): + raise TypeError("Return value must be an ndarray") + if d.shape != want_shape: + raise ValueError(f"Return data must have shape {want_shape} not {d.shape}") + return d + + +def _my_hilbert(x, n_fft=None, envelope=False): + """Compute Hilbert transform of signals w/ zero padding. + + Parameters + ---------- + x : array, shape (n_times) + The signal to convert + n_fft : int + Size of the FFT to perform, must be at least ``len(x)``. + The signal will be cut back to original length. + envelope : bool + Whether to compute amplitude of the hilbert transform in order + to return the signal envelope. + + Returns + ------- + out : array, shape (n_times) + The hilbert transform of the signal, or the envelope. + """ + n_x = x.shape[-1] + out = signal.hilbert(x, N=n_fft, axis=-1)[..., :n_x] + if envelope: + out = np.abs(out) + return out + + +@verbose +def design_mne_c_filter( + sfreq, + l_freq=None, + h_freq=40.0, + l_trans_bandwidth=None, + h_trans_bandwidth=5.0, + verbose=None, +): + """Create a FIR filter like that used by MNE-C. + + Parameters + ---------- + sfreq : float + The sample frequency. + l_freq : float | None + The low filter frequency in Hz, default None. + Can be None to avoid high-passing. + h_freq : float + The high filter frequency in Hz, default 40. + Can be None to avoid low-passing. + l_trans_bandwidth : float | None + Low transition bandwidthin Hz. Can be None (default) to use 3 samples. + h_trans_bandwidth : float + High transition bandwidth in Hz. + %(verbose)s + + Returns + ------- + h : ndarray, shape (8193,) + The linear-phase (symmetric) FIR filter coefficients. + + Notes + ----- + This function is provided mostly for reference purposes. + + MNE-C uses a frequency-domain filter design technique by creating a + linear-phase filter of length 8193. In the frequency domain, the + 4197 frequencies are directly constructed, with zeroes in the stop-band + and ones in the passband, with squared cosine ramps in between. + """ + n_freqs = (4096 + 2 * 2048) // 2 + 1 + freq_resp = np.ones(n_freqs) + l_freq = 0 if l_freq is None else float(l_freq) + if l_trans_bandwidth is None: + l_width = 3 + else: + l_width = (int(((n_freqs - 1) * l_trans_bandwidth) / (0.5 * sfreq)) + 1) // 2 + l_start = int(((n_freqs - 1) * l_freq) / (0.5 * sfreq)) + h_freq = sfreq / 2.0 if h_freq is None else float(h_freq) + h_width = (int(((n_freqs - 1) * h_trans_bandwidth) / (0.5 * sfreq)) + 1) // 2 + h_start = int(((n_freqs - 1) * h_freq) / (0.5 * sfreq)) + logger.info( + "filter : %7.3f ... %6.1f Hz bins : %d ... %d of %d hpw : %d lpw : %d", + l_freq, + h_freq, + l_start, + h_start, + n_freqs, + l_width, + h_width, + ) + if l_freq > 0: + start = l_start - l_width + 1 + stop = start + 2 * l_width - 1 + if start < 0 or stop >= n_freqs: + raise RuntimeError("l_freq too low or l_trans_bandwidth too large") + freq_resp[:start] = 0.0 + k = np.arange(-l_width + 1, l_width) / float(l_width) + 3.0 + freq_resp[start:stop] = np.cos(np.pi / 4.0 * k) ** 2 + + if h_freq < sfreq / 2.0: + start = h_start - h_width + 1 + stop = start + 2 * h_width - 1 + if start < 0 or stop >= n_freqs: + raise RuntimeError("h_freq too high or h_trans_bandwidth too large") + k = np.arange(-h_width + 1, h_width) / float(h_width) + 1.0 + freq_resp[start:stop] *= np.cos(np.pi / 4.0 * k) ** 2 + freq_resp[stop:] = 0.0 + # Get the time-domain version of this signal + h = fft.irfft(freq_resp, n=2 * len(freq_resp) - 1) + h = np.roll(h, n_freqs - 1) # center the impulse like a linear-phase filt + return h + + +def _filt_check_picks(info, picks, h_freq, l_freq): + update_info = False + # This will pick *all* data channels + picks = _picks_to_idx(info, picks, "data_or_ica", exclude=()) + if h_freq is not None or l_freq is not None: + data_picks = _picks_to_idx( + info, None, "data_or_ica", exclude=(), allow_empty=True + ) + if len(data_picks) == 0: + logger.info( + "No data channels found. The highpass and " + "lowpass values in the measurement info will not " + "be updated." + ) + elif np.isin(data_picks, picks).all(): + update_info = True + else: + logger.info( + "Filtering a subset of channels. The highpass and " + "lowpass values in the measurement info will not " + "be updated." + ) + return update_info, picks + + +def _filt_update_info(info, update_info, l_freq, h_freq): + if update_info: + if ( + h_freq is not None + and (l_freq is None or l_freq < h_freq) + and (info["lowpass"] is None or h_freq < info["lowpass"]) + ): + with info._unlock(): + info["lowpass"] = float(h_freq) + if ( + l_freq is not None + and (h_freq is None or l_freq < h_freq) + and (info["highpass"] is None or l_freq > info["highpass"]) + ): + with info._unlock(): + info["highpass"] = float(l_freq) + + +def _iir_pad_apply_unpad(x, *, func, padlen, padtype, **kwargs): + x_out = np.reshape(x, (-1, x.shape[-1])).copy() + for this_x in x_out: + x_ext = this_x + if padlen: + x_ext = _smart_pad(x_ext, (padlen, padlen), padtype) + x_ext = func(x=x_ext, axis=-1, padlen=0, **kwargs) + this_x[:] = x_ext[padlen : len(x_ext) - padlen] + x_out = _reshape_view(x_out, x.shape) + return x_out diff --git a/mne-python/source/mne/fixes.py b/mne-python/source/mne/fixes.py new file mode 100644 index 0000000000000000000000000000000000000000..f3a8252c40f04b5a6bdfb11290b5c235f4c10404 --- /dev/null +++ b/mne-python/source/mne/fixes.py @@ -0,0 +1,808 @@ +"""Compatibility fixes for older versions of libraries. + +If you add content to this file, please give the version of the package +at which the fix is no longer needed. + +# originally copied from scikit-learn + +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# NOTE: +# Imports for SciPy submodules need to stay nested in this module +# because this module is imported many places (but not always used)! + +import inspect +import io +import operator as operator_module +import os +import warnings +from math import log + +import numpy as np +import numpy.typing +from packaging.version import parse + +############################################################################### +# distutils LooseVersion removed in Python 3.12 + + +def _compare_version(version_a, operator, version_b): + """Compare two version strings via a user-specified operator. + + Parameters + ---------- + version_a : str + First version string. + operator : '==' | '>' | '<' | '>=' | '<=' + Operator to compare ``version_a`` and ``version_b`` in the form of + ``version_a operator version_b``. + version_b : str + Second version string. + + Returns + ------- + bool + The result of the version comparison. + """ + mapping = {"<": "lt", "<=": "le", "==": "eq", "!=": "ne", ">=": "ge", ">": "gt"} + with warnings.catch_warnings(record=True): + warnings.simplefilter("ignore") + ver_a = parse(version_a) + ver_b = parse(version_b) + return getattr(operator_module, mapping[operator])(ver_a, ver_b) + + +############################################################################### +# NumPy 2.5 deprecates .shape assignment, but .reshape(copy=False) requires 2.1+ + + +def _reshape_view(arr, shape): + """Reshape an array as a view, raising if a copy would be required. + + This function provides compatibility across NumPy versions for reshaping + arrays as views. On NumPy >= 2.1, it uses ``reshape(copy=False)`` which + explicitly fails if a view cannot be created. On older versions, it uses + direct shape assignment which has the same behavior but is deprecated in + NumPy 2.5+. + + Can be removed once NumPy 2.1 is the minimum supported version. + + Parameters + ---------- + arr : ndarray + The array to reshape. + shape : tuple of int + The new shape. + + Returns + ------- + ndarray + A reshaped view of the array. + + Raises + ------ + AttributeError + If a view cannot be created on NumPy < 2.1. + ValueError + If a view cannot be created on NumPy >= 2.1. + """ + if _compare_version(np.__version__, ">=", "2.1"): + return arr.reshape(shape, copy=False) + else: + arr.shape = shape + return arr + + +############################################################################### +# Misc + + +def _median_complex(data, axis): + """Compute marginal median on complex data safely. + + Can be removed when numpy introduces a fix. + See: https://github.com/scipy/scipy/pull/12676/. + """ + # np.median must be passed real arrays for the desired result + if np.iscomplexobj(data): + data = np.median(np.real(data), axis=axis) + 1j * np.median( + np.imag(data), axis=axis + ) + else: + data = np.median(data, axis=axis) + return data + + +def _safe_svd(A, **kwargs): + """Get around the SVD did not converge error of death.""" + # Intel has a bug with their GESVD driver: + # https://software.intel.com/en-us/forums/intel-distribution-for-python/topic/628049 # noqa: E501 + # For SciPy 0.18 and up, we can work around it by using + # lapack_driver='gesvd' instead. + from scipy import linalg + + if kwargs.get("overwrite_a", False): + raise ValueError("Cannot set overwrite_a=True with this function") + try: + return linalg.svd(A, **kwargs) + except np.linalg.LinAlgError as exp: + from .utils import warn + + warn(f"SVD error ({exp}), attempting to use GESVD instead of GESDD") + return linalg.svd(A, lapack_driver="gesvd", **kwargs) + + +def _csc_array_cast(x): + from scipy.sparse import csc_array + + return csc_array(x) + + +# Can be replaced with sparse.eye_array once we depend on SciPy >= 1.12 +def _eye_array(n, *, format="csr"): # noqa: A002 + from scipy import sparse + + return sparse.dia_array((np.ones(n), 0), shape=(n, n)).asformat(format) + + +############################################################################### +# NumPy Generator (NumPy 1.17) + + +def rng_uniform(rng): + """Get the uniform/randint from the rng.""" + # prefer Generator.integers, fall back to RandomState.randint + return getattr(rng, "integers", getattr(rng, "randint", None)) + + +############################################################################### +# Misc utilities + + +# get_fdata() requires knowing the dtype ahead of time, so let's triage on our +# own instead +def _get_img_fdata(img): + data = np.asanyarray(img.dataobj) + dtype = np.complex128 if np.iscomplexobj(data) else np.float64 + return data.astype(dtype) + + +############################################################################### +# Copied from sklearn to simplify code paths + + +def empirical_covariance(X, assume_centered=False): + """Compute the Maximum likelihood covariance estimator. + + Parameters + ---------- + X : ndarray, shape (n_samples, n_features) + Data from which to compute the covariance estimate + + assume_centered : Boolean + If True, data are not centered before computation. + Useful when working with data whose mean is almost, but not exactly + zero. + If False, data are centered before computation. + + Returns + ------- + covariance : 2D ndarray, shape (n_features, n_features) + Empirical covariance (Maximum Likelihood Estimator). + """ + X = np.asarray(X) + if X.ndim == 1: + X = np.reshape(X, (1, -1)) + + if X.shape[0] == 1: + warnings.warn( + "Only one sample available. You may want to reshape your data array" + ) + + if assume_centered: + covariance = np.dot(X.T, X) / X.shape[0] + else: + covariance = np.cov(X.T, bias=1) + + if covariance.ndim == 0: + covariance = np.array([[covariance]]) + return covariance + + +class _EstimatorMixin: + def __sklearn_tags__(self): + # If we get here, we should have sklearn installed + from sklearn.utils import Tags, TargetTags + + return Tags( + estimator_type=None, + target_tags=TargetTags(required=False), + transformer_tags=None, + regressor_tags=None, + classifier_tags=None, + ) + + def _param_names(self): + return inspect.getfullargspec(self.__init__).args[1:] + + def get_params(self, deep=True): + """Get parameters for this estimator. + + Parameters + ---------- + deep : bool, default=True + If True, will return the parameters for this estimator and + contained subobjects that are estimators. + + Returns + ------- + params : dict + Parameter names mapped to their values. + """ + out = dict() + for key in self._param_names(): + out[key] = getattr(self, key) + return out + + def set_params(self, **params): + """Set the parameters of this estimator. + + The method works on simple estimators as well as on nested objects + (such as pipelines). The latter have parameters of the form + ``__`` so that it's possible to update each + component of a nested object. + + Parameters + ---------- + **params : dict + Estimator parameters. + + Returns + ------- + self : object + Estimator instance. + """ + param_names = self._param_names() + for key in params: + if key in param_names: + setattr(self, key, params[key]) + + +class EmpiricalCovariance(_EstimatorMixin): + """Maximum likelihood covariance estimator. + + Read more in the :ref:`User Guide `. + + Parameters + ---------- + store_precision : bool + Specifies if the estimated precision is stored. + + assume_centered : bool + If True, data are not centered before computation. + Useful when working with data whose mean is almost, but not exactly + zero. + If False (default), data are centered before computation. + + Attributes + ---------- + covariance_ : 2D ndarray, shape (n_features, n_features) + Estimated covariance matrix + + precision_ : 2D ndarray, shape (n_features, n_features) + Estimated pseudo-inverse matrix. + (stored only if store_precision is True) + """ + + def __init__(self, store_precision=True, assume_centered=False): + self.store_precision = store_precision + self.assume_centered = assume_centered + + def _set_covariance(self, covariance): + """Save the covariance and precision estimates. + + Storage is done accordingly to `self.store_precision`. + Precision stored only if invertible. + + Parameters + ---------- + covariance : 2D ndarray, shape (n_features, n_features) + Estimated covariance matrix to be stored, and from which precision + is computed. + """ + from scipy import linalg + + # covariance = check_array(covariance) + # set covariance + self.covariance_ = covariance + # set precision + if self.store_precision: + self.precision_ = linalg.pinvh(covariance) + else: + self.precision_ = None + + def get_precision(self): + """Getter for the precision matrix. + + Returns + ------- + precision_ : array-like, + The precision matrix associated to the current covariance object. + + """ + from scipy import linalg + + if self.store_precision: + precision = self.precision_ + else: + precision = linalg.pinvh(self.covariance_) + return precision + + def fit(self, X, y=None): + """Fit the Maximum Likelihood Estimator covariance model. + + Parameters + ---------- + X : array-like, shape = [n_samples, n_features] + Training data, where n_samples is the number of samples and + n_features is the number of features. + y : ndarray | None + Not used, present for API consistency. + + Returns + ------- + self : object + Returns self. + """ # noqa: E501 + # X = check_array(X) + if self.assume_centered: + self.location_ = np.zeros(X.shape[1]) + else: + self.location_ = X.mean(0) + covariance = empirical_covariance(X, assume_centered=self.assume_centered) + self._set_covariance(covariance) + + return self + + def score(self, X_test, y=None): + """Compute the log-likelihood of a Gaussian dataset. + + Uses ``self.covariance_`` as an estimator of its covariance matrix. + + Parameters + ---------- + X_test : array-like, shape = [n_samples, n_features] + Test data of which we compute the likelihood, where n_samples is + the number of samples and n_features is the number of features. + X_test is assumed to be drawn from the same distribution than + the data used in fit (including centering). + y : ndarray | None + Not used, present for API consistency. + + Returns + ------- + res : float + The likelihood of the data set with `self.covariance_` as an + estimator of its covariance matrix. + """ + # compute empirical covariance of the test set + test_cov = empirical_covariance(X_test - self.location_, assume_centered=True) + # compute log likelihood + res = log_likelihood(test_cov, self.get_precision()) + + return res + + def error_norm(self, comp_cov, norm="frobenius", scaling=True, squared=True): + """Compute the Mean Squared Error between two covariance estimators. + + Parameters + ---------- + comp_cov : array-like, shape = [n_features, n_features] + The covariance to compare with. + norm : str + The type of norm used to compute the error. Available error types: + - 'frobenius' (default): sqrt(tr(A^t.A)) + - 'spectral': sqrt(max(eigenvalues(A^t.A)) + where A is the error ``(comp_cov - self.covariance_)``. + scaling : bool + If True (default), the squared error norm is divided by n_features. + If False, the squared error norm is not rescaled. + squared : bool + Whether to compute the squared error norm or the error norm. + If True (default), the squared error norm is returned. + If False, the error norm is returned. + + Returns + ------- + The Mean Squared Error (in the sense of the Frobenius norm) between + `self` and `comp_cov` covariance estimators. + """ + from scipy import linalg + + # compute the error + error = comp_cov - self.covariance_ + # compute the error norm + if norm == "frobenius": + squared_norm = np.sum(error**2) + elif norm == "spectral": + squared_norm = np.amax(linalg.svdvals(np.dot(error.T, error))) + else: + raise NotImplementedError( + "Only spectral and frobenius norms are implemented" + ) + # optionally scale the error norm + if scaling: + squared_norm = squared_norm / error.shape[0] + # finally get either the squared norm or the norm + if squared: + result = squared_norm + else: + result = np.sqrt(squared_norm) + + return result + + def mahalanobis(self, observations): + """Compute the squared Mahalanobis distances of given observations. + + Parameters + ---------- + observations : array-like, shape = [n_observations, n_features] + The observations, the Mahalanobis distances of the which we + compute. Observations are assumed to be drawn from the same + distribution than the data used in fit. + + Returns + ------- + mahalanobis_distance : array, shape = [n_observations,] + Squared Mahalanobis distances of the observations. + """ + precision = self.get_precision() + # compute mahalanobis distances + centered_obs = observations - self.location_ + mahalanobis_dist = np.sum(np.dot(centered_obs, precision) * centered_obs, 1) + + return mahalanobis_dist + + +def log_likelihood(emp_cov, precision): + """Compute the sample mean of the log_likelihood under a covariance model. + + computes the empirical expected log-likelihood (accounting for the + normalization terms and scaling), allowing for universal comparison (beyond + this software package) + + Parameters + ---------- + emp_cov : 2D ndarray (n_features, n_features) + Maximum Likelihood Estimator of covariance + + precision : 2D ndarray (n_features, n_features) + The precision matrix of the covariance model to be tested + + Returns + ------- + sample mean of the log-likelihood + """ + p = precision.shape[0] + log_likelihood_ = -np.sum(emp_cov * precision) + _logdet(precision) + log_likelihood_ -= p * np.log(2 * np.pi) + log_likelihood_ /= 2.0 + return log_likelihood_ + + +# sklearn uses np.linalg for this, but ours is more robust to zero eigenvalues + + +def _logdet(A): + """Compute the log det of a positive semidefinite matrix.""" + from scipy import linalg + + vals = linalg.eigvalsh(A) + # avoid negative (numerical errors) or zero (semi-definite matrix) values + tol = vals.max() * vals.size * np.finfo(np.float64).eps + vals = np.where(vals > tol, vals, tol) + return np.sum(np.log(vals)) + + +def _infer_dimension_(spectrum, n_samples, n_features): + """Infer the dimension of a dataset of shape (n_samples, n_features). + + The dataset is described by its spectrum `spectrum`. + """ + n_spectrum = len(spectrum) + ll = np.empty(n_spectrum) + for rank in range(n_spectrum): + ll[rank] = _assess_dimension_(spectrum, rank, n_samples, n_features) + return ll.argmax() + + +def _assess_dimension_(spectrum, rank, n_samples, n_features): + from scipy.special import gammaln + + if rank > len(spectrum): + raise ValueError("The tested rank cannot exceed the rank of the dataset") + + pu = -rank * log(2.0) + for i in range(rank): + pu += gammaln((n_features - i) / 2.0) - log(np.pi) * (n_features - i) / 2.0 + + pl = np.sum(np.log(spectrum[:rank])) + pl = -pl * n_samples / 2.0 + + if rank == n_features: + pv = 0 + v = 1 + else: + v = np.sum(spectrum[rank:]) / (n_features - rank) + pv = -np.log(v) * n_samples * (n_features - rank) / 2.0 + + m = n_features * rank - rank * (rank + 1.0) / 2.0 + pp = log(2.0 * np.pi) * (m + rank + 1.0) / 2.0 + + pa = 0.0 + spectrum_ = spectrum.copy() + spectrum_[rank:n_features] = v + for i in range(rank): + for j in range(i + 1, len(spectrum)): + pa += log( + (spectrum[i] - spectrum[j]) * (1.0 / spectrum_[j] - 1.0 / spectrum_[i]) + ) + log(n_samples) + + ll = pu + pl + pv + pp - pa / 2.0 - rank * log(n_samples) / 2.0 + + return ll + + +def svd_flip(u, v, u_based_decision=True): # noqa: D103 + if u_based_decision: + # columns of u, rows of v + max_abs_cols = np.argmax(np.abs(u), axis=0) + signs = np.sign(u[max_abs_cols, np.arange(u.shape[1])]) + u *= signs + v *= signs[:, np.newaxis] + else: + # rows of v, columns of u + max_abs_rows = np.argmax(np.abs(v), axis=1) + signs = np.sign(v[np.arange(v.shape[0]), max_abs_rows]) + u *= signs + v *= signs[:, np.newaxis] + return u, v + + +def stable_cumsum(arr, axis=None, rtol=1e-05, atol=1e-08): + """Use high precision for cumsum and check that final value matches sum. + + Parameters + ---------- + arr : array-like + To be cumulatively summed as flat + axis : int, optional + Axis along which the cumulative sum is computed. + The default (None) is to compute the cumsum over the flattened array. + rtol : float + Relative tolerance, see ``np.allclose`` + atol : float + Absolute tolerance, see ``np.allclose`` + """ + out = np.cumsum(arr, axis=axis, dtype=np.float64) + expected = np.sum(arr, axis=axis, dtype=np.float64) + if not np.all( + np.isclose( + out.take(-1, axis=axis), expected, rtol=rtol, atol=atol, equal_nan=True + ) + ): + warnings.warn( + "cumsum was found to be unstable: " + "its last element does not correspond to sum", + RuntimeWarning, + ) + return out + + +############################################################################### +# From nilearn + + +def _crop_colorbar(cbar, cbar_vmin, cbar_vmax): + """Crop a colorbar to show from cbar_vmin to cbar_vmax. + + Used when symmetric_cbar=False is used. + """ + if (cbar_vmin is None) and (cbar_vmax is None): + return + cbar_tick_locs = cbar.locator.locs + if cbar_vmax is None: + cbar_vmax = cbar_tick_locs.max() + if cbar_vmin is None: + cbar_vmin = cbar_tick_locs.min() + new_tick_locs = np.linspace(cbar_vmin, cbar_vmax, len(cbar_tick_locs)) + + cbar.ax.set_ylim(cbar_vmin, cbar_vmax) + X = cbar._mesh()[0] + X = np.array([X[0], X[-1]]) + Y = np.array([[cbar_vmin, cbar_vmin], [cbar_vmax, cbar_vmax]]) + N = X.shape[0] + ii = [0, 1, N - 2, N - 1, 2 * N - 1, 2 * N - 2, N + 1, N, 0] + x = X.T.reshape(-1)[ii] + y = Y.T.reshape(-1)[ii] + xy = ( + np.column_stack([y, x]) + if cbar.orientation == "horizontal" + else np.column_stack([x, y]) + ) + cbar.outline.set_xy(xy) + + cbar.set_ticks(new_tick_locs) + cbar.update_ticks() + + +############################################################################### +# Numba (optional requirement) + +# Here we choose different defaults to speed things up by default +try: + import numba + + if _compare_version(numba.__version__, "<", "0.56.4"): + raise ImportError + prange = numba.prange + + def jit(nopython=True, nogil=True, fastmath=True, cache=True, **kwargs): # noqa + return numba.jit( + nopython=nopython, nogil=nogil, fastmath=fastmath, cache=cache, **kwargs + ) + +except Exception: # could be ImportError, SystemError, etc. + has_numba = False +else: + has_numba = os.getenv("MNE_USE_NUMBA", "true").lower() == "true" + + +if not has_numba: + + def jit(**kwargs): # noqa + def _jit(func): + return func + + return _jit + + prange = range + bincount = np.bincount + +else: + + @jit() + def bincount(x, weights, minlength): # noqa: D103 + out = np.zeros(minlength) + for idx, w in zip(x, weights): + out[idx] += w + return out + + +############################################################################### +# Matplotlib + + +# workaround: plt.close() doesn't spawn close_event on Agg backend +# https://github.com/matplotlib/matplotlib/issues/18609 +def _close_event(fig): + """Force calling of the MPL figure close event.""" + from matplotlib import backend_bases + + from .utils import logger + + try: + fig.canvas.callbacks.process( + "close_event", + backend_bases.CloseEvent(name="close_event", canvas=fig.canvas), + ) + logger.debug(f"Called {fig!r}.canvas.close_event()") + except ValueError: # old mpl with Qt + logger.debug(f"Calling {fig!r}.canvas.close_event() failed") + pass # pragma: no cover + + +############################################################################### +# SciPy 1.14+ minimum_phase half=True option + + +def minimum_phase(h, method="homomorphic", n_fft=None, *, half=True): + """Wrap scipy.signal.minimum_phase with half option.""" + # Can be removed once + from scipy.fft import fft, ifft + from scipy.signal import minimum_phase as sp_minimum_phase + + assert isinstance(method, str) and method == "homomorphic" + + if "half" in inspect.getfullargspec(sp_minimum_phase).kwonlyargs: + return sp_minimum_phase(h, method=method, n_fft=n_fft, half=half) + h = np.asarray(h) + if np.iscomplexobj(h): + raise ValueError("Complex filters not supported") + if h.ndim != 1 or h.size <= 2: + raise ValueError("h must be 1-D and at least 2 samples long") + n_half = len(h) // 2 + if not np.allclose(h[-n_half:][::-1], h[:n_half]): + warnings.warn( + "h does not appear to by symmetric, conversion may fail", + RuntimeWarning, + stacklevel=2, + ) + if n_fft is None: + n_fft = 2 ** int(np.ceil(np.log2(2 * (len(h) - 1) / 0.01))) + n_fft = int(n_fft) + if n_fft < len(h): + raise ValueError(f"n_fft must be at least len(h)=={len(h)}") + + # zero-pad; calculate the DFT + h_temp = np.abs(fft(h, n_fft)) + # take 0.25*log(|H|**2) = 0.5*log(|H|) + h_temp += 1e-7 * h_temp[h_temp > 0].min() # don't let log blow up + np.log(h_temp, out=h_temp) + if half: # halving of magnitude spectrum optional + h_temp *= 0.5 + # IDFT + h_temp = ifft(h_temp).real + # multiply pointwise by the homomorphic filter + # lmin[n] = 2u[n] - d[n] + # i.e., double the positive frequencies and zero out the negative ones; + # Oppenheim+Shafer 3rd ed p991 eq13.42b and p1004 fig13.7 + win = np.zeros(n_fft) + win[0] = 1 + stop = n_fft // 2 + win[1:stop] = 2 + if n_fft % 2: + win[stop] = 1 + h_temp *= win + h_temp = ifft(np.exp(fft(h_temp))) + h_minimum = h_temp.real + + n_out = (n_half + len(h) % 2) if half else len(h) + return h_minimum[:n_out] + + +# SciPy 1.15 deprecates sph_harm for sph_harm_y and using it will trigger a +# DeprecationWarning. This is a backport of the new function for older SciPy versions. +def sph_harm_y(n, m, theta, phi, *, diff_n=0): + """Wrap scipy.special.sph_harm for sph_harm_y.""" + # Can be removed once we no longer support scipy < 1.15.0 + from scipy import special + + if "sph_harm_y" in special.__dict__: + return special.sph_harm_y(n, m, theta, phi, diff_n=diff_n) + else: + return special.sph_harm(m, n, phi, theta) + + +############################################################################### +# workaround: Numpy won't allow to read from file-like objects with numpy.fromfile, +# we try to use numpy.fromfile, if a blob is used we use numpy.frombuffer to read +# from the file-like object. +def read_from_file_or_buffer( + file: str | bytes | os.PathLike | io.IOBase, + dtype: numpy.typing.DTypeLike = float, + count: int = -1, +): + """numpy.fromfile() wrapper, handling io.BytesIO file-like streams. + + Numpy requires open files to be actual files on disk, i.e., must support + file.fileno(), so it fails with file-like streams such as io.BytesIO(). + + If numpy.fromfile() fails due to no file.fileno() support, this wrapper + reads the required bytes from file and redirects the call to + numpy.frombuffer(). + + See https://github.com/numpy/numpy/issues/2230#issuecomment-949795210 + """ + try: + return np.fromfile(file, dtype=dtype, count=count) + except io.UnsupportedOperation as e: + if not (e.args and e.args[0] == "fileno" and isinstance(file, io.IOBase)): + raise # Nothing I can do about it + dtype = np.dtype(dtype) + buffer = file.read(dtype.itemsize * count) + return np.frombuffer(buffer, dtype=dtype, count=count) diff --git a/mne-python/source/mne/forward/__init__.py b/mne-python/source/mne/forward/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3dcafb625de1bbc136dbd3ee9fbbd7fae162a3e4 --- /dev/null +++ b/mne-python/source/mne/forward/__init__.py @@ -0,0 +1,8 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Forward modeling code.""" +import lazy_loader as lazy # for testing purposes + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/forward/__init__.pyi b/mne-python/source/mne/forward/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..dcac0d308813a4ad1b604db11419a44f3b6a5cb0 --- /dev/null +++ b/mne-python/source/mne/forward/__init__.pyi @@ -0,0 +1,86 @@ +__all__ = [ + "Forward", + "_apply_forward", + "_as_meg_type_inst", + "_compute_forwards", + "_concatenate_coils", + "_create_meg_coils", + "_do_forward_solution", + "_fill_measurement_info", + "_lead_dots", + "_magnetic_dipole_field_vec", + "_make_surface_mapping", + "_map_meg_or_eeg_channels", + "_merge_fwds", + "_prep_eeg_channels", + "_prep_meg_channels", + "_prepare_for_forward", + "_read_coil_defs", + "_read_forward_meas_info", + "_select_orient_forward", + "_stc_src_sel", + "_subject_from_forward", + "_to_forward_dict", + "_transform_orig_meg_coils", + "apply_forward", + "apply_forward_raw", + "average_forward_solutions", + "compute_depth_prior", + "compute_orient_prior", + "convert_forward_solution", + "is_fixed_orient", + "make_field_map", + "make_forward_dipole", + "make_forward_solution", + "read_forward_solution", + "restrict_forward_to_label", + "restrict_forward_to_stc", + "use_coil_def", + "write_forward_solution", +] +from . import _lead_dots +from ._compute_forward import ( + _compute_forwards, + _concatenate_coils, + _magnetic_dipole_field_vec, +) +from ._field_interpolation import ( + _as_meg_type_inst, + _make_surface_mapping, + _map_meg_or_eeg_channels, + make_field_map, +) +from ._make_forward import ( + _create_meg_coils, + _prep_eeg_channels, + _prep_meg_channels, + _prepare_for_forward, + _read_coil_defs, + _to_forward_dict, + _transform_orig_meg_coils, + make_forward_dipole, + make_forward_solution, + use_coil_def, +) +from .forward import ( + Forward, + _apply_forward, + _do_forward_solution, + _fill_measurement_info, + _merge_fwds, + _read_forward_meas_info, + _select_orient_forward, + _stc_src_sel, + _subject_from_forward, + apply_forward, + apply_forward_raw, + average_forward_solutions, + compute_depth_prior, + compute_orient_prior, + convert_forward_solution, + is_fixed_orient, + read_forward_solution, + restrict_forward_to_label, + restrict_forward_to_stc, + write_forward_solution, +) diff --git a/mne-python/source/mne/forward/_compute_forward.py b/mne-python/source/mne/forward/_compute_forward.py new file mode 100644 index 0000000000000000000000000000000000000000..6453fdb47e7df3a7689e78fc62781180d073ea14 --- /dev/null +++ b/mne-python/source/mne/forward/_compute_forward.py @@ -0,0 +1,902 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# The computations in this code were primarily derived from Matti Hämäläinen's +# C code. +# +# Many of the idealized equations behind these calculations can be found in: +# 1) Realistic conductivity geometry model of the human head for interpretation +# of neuromagnetic data. Hämäläinen and Sarvas, 1989. Specific to MNE +# 2) EEG and MEG: forward solutions for inverse methods. Mosher, Leahy, and +# Lewis, 1999. Generalized discussion of forward solutions. + +from copy import deepcopy + +import numpy as np + +from .._fiff.constants import FIFF +from ..bem import _import_openmeeg, _make_openmeeg_geometry +from ..fixes import _reshape_view, bincount, jit +from ..parallel import parallel_func +from ..surface import _jit_cross, _project_onto_surface +from ..transforms import apply_trans, invert_transform +from ..utils import _check_option, _pl, fill_doc, logger, verbose, warn + +# ############################################################################# +# COIL SPECIFICATION AND FIELD COMPUTATION MATRIX + + +def _dup_coil_set(coils, coord_frame, t): + """Make a duplicate.""" + if t is not None and coord_frame != t["from"]: + raise RuntimeError("transformation frame does not match the coil set") + coils = deepcopy(coils) + if t is not None: + coord_frame = t["to"] + for coil in coils: + assert isinstance(coil, dict), f"Coil must be a dict, got {type(coil)}" + for key in ("ex", "ey", "ez"): + if key in coil: + coil[key] = apply_trans(t["trans"], coil[key], False) + coil["r0"] = apply_trans(t["trans"], coil["r0"]) + coil["rmag"] = apply_trans(t["trans"], coil["rmag"]) + coil["cosmag"] = apply_trans(t["trans"], coil["cosmag"], False) + coil["coord_frame"] = t["to"] + return coils, coord_frame + + +def _check_coil_frame(coils, coord_frame, bem): + """Check to make sure the coils are in the correct coordinate frame.""" + if coord_frame != FIFF.FIFFV_COORD_MRI: + if coord_frame == FIFF.FIFFV_COORD_HEAD: + # Make a transformed duplicate + coils, coord_frame = _dup_coil_set(coils, coord_frame, bem["head_mri_t"]) + else: + raise RuntimeError(f"Bad coil coordinate frame {coord_frame}") + return coils, coord_frame + + +@fill_doc +def _lin_field_coeff(surf, mult, rmags, cosmags, ws, bins, n_jobs): + """Parallel wrapper for _do_lin_field_coeff to compute linear coefficients. + + Parameters + ---------- + surf : dict + Dict containing information for one surface of the BEM + mult : float + Multiplier for particular BEM surface (Iso Skull Approach discussed in + Mosher et al., 1999 and Hämäläinen and Sarvas, 1989 Section III?) + rmag : ndarray, shape (n_integration_pts, 3) + 3D positions of MEG coil integration points (from coil['rmag']) + cosmag : ndarray, shape (n_integration_pts, 3) + Direction of the MEG coil integration points (from coil['cosmag']) + ws : ndarray, shape (n_integration_pts,) + Weights for MEG coil integration points + bins : ndarray, shape (n_integration_points,) + The sensor assignments for each rmag/cosmag/w. + %(n_jobs)s + + Returns + ------- + coeff : list + Linear coefficients with lead fields for each BEM vertex on each sensor + (?) + """ + parallel, p_fun, n_jobs = parallel_func( + _do_lin_field_coeff, n_jobs, max_jobs=len(surf["tris"]) + ) + nas = np.array_split + coeffs = parallel( + p_fun(surf["rr"], t, tn, ta, rmags, cosmags, ws, bins) + for t, tn, ta in zip( + nas(surf["tris"], n_jobs), + nas(surf["tri_nn"], n_jobs), + nas(surf["tri_area"], n_jobs), + ) + ) + return mult * np.sum(coeffs, axis=0) + + +@jit() +def _do_lin_field_coeff(bem_rr, tris, tn, ta, rmags, cosmags, ws, bins): + """Compute field coefficients (parallel-friendly). + + See section IV of Mosher et al., 1999 (specifically equation 35). + + Parameters + ---------- + bem_rr : ndarray, shape (n_BEM_vertices, 3) + Positions on one BEM surface in 3-space. 2562 BEM vertices for BEM with + 5120 triangles (ico-4) + tris : ndarray, shape (n_BEM_vertices, 3) + Vertex indices for each triangle (referring to bem_rr) + tn : ndarray, shape (n_BEM_vertices, 3) + Triangle unit normal vectors + ta : ndarray, shape (n_BEM_vertices,) + Triangle areas + rmag : ndarray, shape (n_sensor_pts, 3) + 3D positions of MEG coil integration points (from coil['rmag']) + cosmag : ndarray, shape (n_sensor_pts, 3) + Direction of the MEG coil integration points (from coil['cosmag']) + ws : ndarray, shape (n_sensor_pts,) + Weights for MEG coil integration points + bins : ndarray, shape (n_sensor_pts,) + The sensor assignments for each rmag/cosmag/w. + + Returns + ------- + coeff : ndarray, shape (n_MEG_sensors, n_BEM_vertices) + Linear coefficients with effect of each BEM vertex on each sensor (?) + """ + coeff = np.zeros((bins[-1] + 1, len(bem_rr))) + w_cosmags = ws.reshape(-1, 1) * cosmags + diff = rmags.reshape(rmags.shape[0], 1, rmags.shape[1]) - bem_rr + den = np.sum(diff * diff, axis=-1) + den *= np.sqrt(den) + den *= 3 + for ti in range(len(tris)): + tri, tri_nn, tri_area = tris[ti], tn[ti], ta[ti] + # Accumulate the coefficients for each triangle node and add to the + # corresponding coefficient matrix + + # Simple version (bem_lin_field_coeffs_simple) + # The following is equivalent to: + # tri_rr = bem_rr[tri] + # for j, coil in enumerate(coils['coils']): + # x = func(coil['rmag'], coil['cosmag'], + # tri_rr, tri_nn, tri_area) + # res = np.sum(coil['w'][np.newaxis, :] * x, axis=1) + # coeff[j][tri + off] += mult * res + + c = np.empty((diff.shape[0], tri.shape[0], diff.shape[2])) + _jit_cross(c, diff[:, tri], tri_nn) + c *= w_cosmags.reshape(w_cosmags.shape[0], 1, w_cosmags.shape[1]) + for ti in range(3): + x = np.sum(c[:, ti], axis=-1) + x /= den[:, tri[ti]] / tri_area + coeff[:, tri[ti]] += bincount(bins, weights=x, minlength=bins[-1] + 1) + return coeff + + +def _concatenate_coils(coils): + """Concatenate MEG coil parameters.""" + rmags = np.concatenate([coil["rmag"] for coil in coils]) + cosmags = np.concatenate([coil["cosmag"] for coil in coils]) + ws = np.concatenate([coil["w"] for coil in coils]) + n_int = np.array([len(coil["rmag"]) for coil in coils]) + if n_int[-1] == 0: + # We assume each sensor has at least one integration point, + # which should be a safe assumption. But let's check it here, since + # our code elsewhere relies on bins[-1] + 1 being the number of sensors + raise RuntimeError("not supported") + bins = np.repeat(np.arange(len(n_int)), n_int) + return rmags, cosmags, ws, bins + + +@fill_doc +def _bem_specify_coils(bem, coils, coord_frame, mults, n_jobs): + """Set up for computing the solution at a set of MEG coils. + + Parameters + ---------- + bem : instance of ConductorModel + BEM information + coils : list of dict, len(n_MEG_sensors) + MEG sensor information dicts + coord_frame : int + Class constant identifying coordinate frame + mults : ndarray, shape (1, n_BEM_vertices) + Multiplier for every vertex in BEM + %(n_jobs)s + + Returns + ------- + sol: ndarray, shape (n_MEG_sensors, n_BEM_vertices) + MEG solution + """ + # Make sure MEG coils are in MRI coordinate frame to match BEM coords + coils, coord_frame = _check_coil_frame(coils, coord_frame, bem) + + # leaving this in in case we want to easily add in the future + # if method != 'simple': # in ['ferguson', 'urankar']: + # raise NotImplementedError + + # Compute the weighting factors to obtain the magnetic field in the linear + # potential approximation + + # Process each of the surfaces + rmags, cosmags, ws, bins = _triage_coils(coils) + del coils + lens = np.cumsum(np.r_[0, [len(s["rr"]) for s in bem["surfs"]]]) + sol = np.zeros((bins[-1] + 1, bem["solution"].shape[1])) + + lims = np.concatenate([np.arange(0, sol.shape[0], 100), [sol.shape[0]]]) + # Put through the bem (in channel-based chunks to save memory) + for start, stop in zip(lims[:-1], lims[1:]): + mask = np.logical_and(bins >= start, bins < stop) + r, c, w, b = rmags[mask], cosmags[mask], ws[mask], bins[mask] - start + # Compute coeffs for each surface, one at a time + for o1, o2, surf, mult in zip( + lens[:-1], lens[1:], bem["surfs"], bem["field_mult"] + ): + coeff = _lin_field_coeff(surf, mult, r, c, w, b, n_jobs) + sol[start:stop] += np.dot(coeff, bem["solution"][o1:o2]) + sol *= mults + return sol + + +def _bem_specify_els(bem, els, mults): + """Set up for computing the solution at a set of EEG electrodes. + + Parameters + ---------- + bem : instance of ConductorModel + BEM information + els : list of dict, len(n_EEG_sensors) + List of EEG sensor information dicts + mults: ndarray, shape (1, n_BEM_vertices) + Multiplier for every vertex in BEM + + Returns + ------- + sol : ndarray, shape (n_EEG_sensors, n_BEM_vertices) + EEG solution + """ + sol = np.zeros((len(els), bem["solution"].shape[1])) + scalp = bem["surfs"][0] + + # Operate on all integration points for all electrodes (in MRI coords) + rrs = np.concatenate( + [apply_trans(bem["head_mri_t"]["trans"], el["rmag"]) for el in els], axis=0 + ) + ws = np.concatenate([el["w"] for el in els]) + tri_weights, tri_idx = _project_onto_surface(rrs, scalp) + tri_weights *= ws[:, np.newaxis] + weights = np.matmul( + tri_weights[:, np.newaxis], bem["solution"][scalp["tris"][tri_idx]] + )[:, 0] + # there are way more vertices than electrodes generally, so let's iterate + # over the electrodes + edges = np.concatenate([[0], np.cumsum([len(el["w"]) for el in els])]) + for ii, (start, stop) in enumerate(zip(edges[:-1], edges[1:])): + sol[ii] = weights[start:stop].sum(0) + sol *= mults + return sol + + +# ############################################################################# +# BEM COMPUTATION + +_MAG_FACTOR = 1e-7 # μ_0 / (4π) + +# def _bem_inf_pot(rd, Q, rp): +# """The infinite medium potential in one direction. See Eq. (8) in +# Mosher, 1999""" +# NOTE: the (μ_0 / (4π) factor has been moved to _prep_field_communication +# diff = rp - rd # (Observation point position) - (Source position) +# diff2 = np.sum(diff * diff, axis=1) # Squared magnitude of diff +# # (Dipole moment) dot (diff) / (magnitude ^ 3) +# return np.sum(Q * diff, axis=1) / (diff2 * np.sqrt(diff2)) + + +@jit() +def _bem_inf_pots(mri_rr, bem_rr, mri_Q=None): + """Compute the infinite medium potential in all 3 directions. + + Parameters + ---------- + mri_rr : ndarray, shape (n_dipole_vertices, 3) + Chunk of 3D dipole positions in MRI coordinates + bem_rr: ndarray, shape (n_BEM_vertices, 3) + 3D vertex positions for one BEM surface + mri_Q : ndarray, shape (3, 3) + 3x3 head -> MRI transform. I.e., head_mri_t.dot(np.eye(3)) + + Returns + ------- + ndarray : shape(n_dipole_vertices, 3, n_BEM_vertices) + """ + # NOTE: the (μ_0 / (4π) factor has been moved to _prep_field_communication + # Get position difference vector between BEM vertex and dipole + diff = np.empty((len(mri_rr), 3, len(bem_rr))) + for ri in range(mri_rr.shape[0]): + rr = mri_rr[ri] + this_diff = bem_rr - rr + diff_norm = np.sum(this_diff * this_diff, axis=1) + diff_norm *= np.sqrt(diff_norm) + diff_norm[diff_norm == 0] = 1.0 + if mri_Q is not None: + this_diff = np.dot(this_diff, mri_Q.T) + this_diff /= diff_norm.reshape(-1, 1) + diff[ri] = this_diff.T + + return diff + + +# This function has been refactored to process all points simultaneously +# def _bem_inf_field(rd, Q, rp, d): +# """Infinite-medium magnetic field. See (7) in Mosher, 1999""" +# # Get vector from source to sensor integration point +# diff = rp - rd +# diff2 = np.sum(diff * diff, axis=1) # Get magnitude of diff +# +# # Compute cross product between diff and dipole to get magnetic field at +# # integration point +# x = fast_cross_3d(Q[np.newaxis, :], diff) +# +# # Take magnetic field dotted by integration point normal to get magnetic +# # field threading the current loop. Divide by R^3 (equivalently, R^2 * R) +# return np.sum(x * d, axis=1) / (diff2 * np.sqrt(diff2)) + + +@jit() +def _bem_inf_fields(rr, rmag, cosmag): + """Compute infinite-medium magnetic field at one MEG sensor. + + This operates on all dipoles in all 3 basis directions. + + Parameters + ---------- + rr : ndarray, shape (n_source_points, 3) + 3D dipole source positions + rmag : ndarray, shape (n_sensor points, 3) + 3D positions of 1 MEG coil's integration points (from coil['rmag']) + cosmag : ndarray, shape (n_sensor_points, 3) + Direction of 1 MEG coil's integration points (from coil['cosmag']) + + Returns + ------- + ndarray, shape (n_dipoles, 3, n_integration_pts) + Magnetic field from all dipoles at each MEG sensor integration point + """ + # rr, rmag refactored according to Equation (19) in Mosher, 1999 + # Knowing that we're doing all directions, refactor above function: + + # rr, 3, rmag + diff = rmag.T.reshape(1, 3, rmag.shape[0]) - rr.reshape(rr.shape[0], 3, 1) + diff_norm = np.sum(diff * diff, axis=1) # rr, rmag + diff_norm *= np.sqrt(diff_norm) # Get magnitude of distance cubed + diff_norm_ = diff_norm.reshape(-1) + diff_norm_[diff_norm_ == 0] = 1 # avoid nans + + # This is the result of cross-prod calcs with basis vectors, + # as if we had taken (Q=np.eye(3)), then multiplied by cosmags + # factor, and then summed across directions + x = np.empty((rr.shape[0], 3, rmag.shape[0])) + x[:, 0] = diff[:, 1] * cosmag[:, 2] - diff[:, 2] * cosmag[:, 1] + x[:, 1] = diff[:, 2] * cosmag[:, 0] - diff[:, 0] * cosmag[:, 2] + x[:, 2] = diff[:, 0] * cosmag[:, 1] - diff[:, 1] * cosmag[:, 0] + diff_norm = diff_norm_.reshape((rr.shape[0], 1, rmag.shape[0])) + x /= diff_norm + # x.shape == (rr.shape[0], 3, rmag.shape[0]) + return x + + +@fill_doc +def _bem_pot_or_field(rr, mri_rr, mri_Q, coils, solution, bem_rr, n_jobs, coil_type): + """Calculate the magnetic field or electric potential forward solution. + + The code is very similar between EEG and MEG potentials, so combine them. + This does the work of "fwd_comp_field" (which wraps to "fwd_bem_field") + and "fwd_bem_pot_els" in MNE-C. + + Parameters + ---------- + rr : ndarray, shape (n_dipoles, 3) + 3D dipole source positions + mri_rr : ndarray, shape (n_dipoles, 3) + 3D source positions in MRI coordinates + mri_Q : + 3x3 head -> MRI transform. I.e., head_mri_t.dot(np.eye(3)) + coils : list of dict, len(sensors) + List of sensors where each element contains sensor specific information + solution : ndarray, shape (n_sensors, n_BEM_rr) + Comes from _bem_specify_coils + bem_rr : ndarray, shape (n_BEM_vertices, 3) + 3D vertex positions for all surfaces in the BEM + %(n_jobs)s + coil_type : str + 'meg' or 'eeg' + + Returns + ------- + B : ndarray, shape (n_dipoles * 3, n_sensors) + Forward solution for a set of sensors + """ + # Both MEG and EEG have the inifinite-medium potentials + # This could be just vectorized, but eats too much memory, so instead we + # reduce memory by chunking within _do_inf_pots and parallelize, too: + parallel, p_fun, n_jobs = parallel_func(_do_inf_pots, n_jobs, max_jobs=len(rr)) + nas = np.array_split + B = np.sum( + parallel( + p_fun( + mri_rr, sr.copy(), np.ascontiguousarray(mri_Q), np.array(sol) + ) # copy and contig + for sr, sol in zip(nas(bem_rr, n_jobs), nas(solution.T, n_jobs)) + ), + axis=0, + ) + # The copy()s above should make it so the whole objects don't need to be + # pickled... + + # Only MEG coils are sensitive to the primary current distribution. + if coil_type == "meg": + # Primary current contribution (can be calc. in coil/dipole coords) + parallel, p_fun, n_jobs = parallel_func(_do_prim_curr, n_jobs) + pcc = np.concatenate(parallel(p_fun(r, coils) for r in nas(rr, n_jobs)), axis=0) + B += pcc + B *= _MAG_FACTOR + return B + + +def _do_prim_curr(rr, coils): + """Calculate primary currents in a set of MEG coils. + + See Mosher et al., 1999 Section II for discussion of primary vs. volume + currents. + + Parameters + ---------- + rr : ndarray, shape (n_dipoles, 3) + 3D dipole source positions in head coordinates + coils : list of dict + List of MEG coils where each element contains coil specific information + + Returns + ------- + pc : ndarray, shape (n_sources, n_MEG_sensors) + Primary current for set of MEG coils due to all sources + """ + rmags, cosmags, ws, bins = _triage_coils(coils) + n_coils = bins[-1] + 1 + del coils + pc = np.empty((len(rr) * 3, n_coils)) + for start, stop in _rr_bounds(rr, chunk=1): + pp = _bem_inf_fields(rr[start:stop], rmags, cosmags) + pp *= ws + pp = _reshape_view(pp, (3 * (stop - start), -1)) + pc[3 * start : 3 * stop] = [ + bincount(bins, this_pp, bins[-1] + 1) for this_pp in pp + ] + return pc + + +def _rr_bounds(rr, chunk=200): + # chunk data nicely + bounds = np.concatenate([np.arange(0, len(rr), chunk), [len(rr)]]) + return zip(bounds[:-1], bounds[1:]) + + +def _do_inf_pots(mri_rr, bem_rr, mri_Q, sol): + """Calculate infinite potentials for MEG or EEG sensors using chunks. + + Parameters + ---------- + mri_rr : ndarray, shape (n_dipoles, 3) + 3D dipole source positions in MRI coordinates + bem_rr : ndarray, shape (n_BEM_vertices, 3) + 3D vertex positions for all surfaces in the BEM + mri_Q : + 3x3 head -> MRI transform. I.e., head_mri_t.dot(np.eye(3)) + sol : ndarray, shape (n_sensors_subset, n_BEM_vertices_subset) + Comes from _bem_specify_coils + + Returns + ------- + B : ndarray, (n_dipoles * 3, n_sensors) + Forward solution for sensors due to volume currents + """ + # Doing work of 'fwd_bem_pot_calc' in MNE-C + # The following code is equivalent to this, but saves memory + # v0s = _bem_inf_pots(rr, bem_rr, Q) # n_rr x 3 x n_bem_rr + # v0s.shape = (len(rr) * 3, v0s.shape[2]) + # B = np.dot(v0s, sol) + + # We chunk the source mri_rr's in order to save memory + B = np.empty((len(mri_rr) * 3, sol.shape[1])) + for start, stop in _rr_bounds(mri_rr): + # v0 in Hämäläinen et al., 1989 == v_inf in Mosher, et al., 1999 + v0s = _bem_inf_pots(mri_rr[start:stop], bem_rr, mri_Q) + v0s = v0s.reshape(-1, v0s.shape[2]) + B[3 * start : 3 * stop] = np.dot(v0s, sol) + return B + + +# ############################################################################# +# SPHERE COMPUTATION + + +def _sphere_pot_or_field(rr, mri_rr, mri_Q, coils, solution, bem_rr, n_jobs, coil_type): + """Do potential or field for spherical model.""" + fun = _eeg_spherepot_coil if coil_type == "eeg" else _sphere_field + parallel, p_fun, n_jobs = parallel_func(fun, n_jobs, max_jobs=len(rr)) + B = np.concatenate( + parallel(p_fun(r, coils, sphere=solution) for r in np.array_split(rr, n_jobs)) + ) + return B + + +def _sphere_field(rrs, coils, sphere): + """Compute field for spherical model using Jukka Sarvas' field computation. + + Jukka Sarvas, "Basic mathematical and electromagnetic concepts of the + biomagnetic inverse problem", Phys. Med. Biol. 1987, Vol. 32, 1, 11-22. + + The formulas have been manipulated for efficient computation + by Matti Hämäläinen, February 1990 + """ + rmags, cosmags, ws, bins = _triage_coils(coils) + return _do_sphere_field(rrs, rmags, cosmags, ws, bins, sphere["r0"]) + + +@jit() +def _do_sphere_field(rrs, rmags, cosmags, ws, bins, r0): + n_coils = bins[-1] + 1 + # Shift to the sphere model coordinates + rrs = rrs - r0 + B = np.zeros((3 * len(rrs), n_coils)) + for ri in range(len(rrs)): + rr = rrs[ri] + # Check for a dipole at the origin + if np.sqrt(np.dot(rr, rr)) <= 1e-10: + continue + this_poss = rmags - r0 + + # Vector from dipole to the field point + a_vec = this_poss - rr + a = np.sqrt(np.sum(a_vec * a_vec, axis=1)) + r = np.sqrt(np.sum(this_poss * this_poss, axis=1)) + rr0 = np.sum(this_poss * rr, axis=1) + ar = (r * r) - rr0 + ar0 = ar / a + F = a * (r * a + ar) + gr = (a * a) / r + ar0 + 2.0 * (a + r) + g0 = a + 2 * r + ar0 + # Compute the dot products needed + re = np.sum(this_poss * cosmags, axis=1) + r0e = np.sum(rr * cosmags, axis=1) + g = (g0 * r0e - gr * re) / (F * F) + good = (a > 0) | (r > 0) | ((a * r) + 1 > 1e-5) + rr_ = rr.reshape(1, 3) + v1 = np.empty((cosmags.shape[0], 3)) + _jit_cross(v1, rr_, cosmags) + v2 = np.empty((cosmags.shape[0], 3)) + _jit_cross(v2, rr_, this_poss) + xx = (good * ws).reshape(-1, 1) * ( + v1 / F.reshape(-1, 1) + v2 * g.reshape(-1, 1) + ) + for jj in range(3): + zz = bincount(bins, xx[:, jj], n_coils) + B[3 * ri + jj, :] = zz + B *= _MAG_FACTOR + return B + + +def _eeg_spherepot_coil(rrs, coils, sphere): + """Calculate the EEG in the sphere model.""" + rmags, cosmags, ws, bins = _triage_coils(coils) + n_coils = bins[-1] + 1 + del coils + + # Shift to the sphere model coordinates + rrs = rrs - sphere["r0"] + + B = np.zeros((3 * len(rrs), n_coils)) + for ri, rr in enumerate(rrs): + # Only process dipoles inside the innermost sphere + if np.sqrt(np.dot(rr, rr)) >= sphere["layers"][0]["rad"]: + continue + # fwd_eeg_spherepot_vec + vval_one = np.zeros((len(rmags), 3)) + + # Make a weighted sum over the equivalence parameters + for eq in range(sphere["nfit"]): + # Scale the dipole position + rd = sphere["mu"][eq] * rr + rd2 = np.sum(rd * rd) + rd2_inv = 1.0 / rd2 + # Go over all electrodes + this_pos = rmags - sphere["r0"] + + # Scale location onto the surface of the sphere (not used) + # if sphere['scale_pos']: + # pos_len = (sphere['layers'][-1]['rad'] / + # np.sqrt(np.sum(this_pos * this_pos, axis=1))) + # this_pos *= pos_len + + # Vector from dipole to the field point + a_vec = this_pos - rd + + # Compute the dot products needed + a = np.sqrt(np.sum(a_vec * a_vec, axis=1)) + a3 = 2.0 / (a * a * a) + r2 = np.sum(this_pos * this_pos, axis=1) + r = np.sqrt(r2) + rrd = np.sum(this_pos * rd, axis=1) + ra = r2 - rrd + rda = rrd - rd2 + + # The main ingredients + F = a * (r * a + ra) + c1 = a3 * rda + 1.0 / a - 1.0 / r + c2 = a3 + (a + r) / (r * F) + + # Mix them together and scale by lambda/(rd*rd) + m1 = c1 - c2 * rrd + m2 = c2 * rd2 + + vval_one += ( + sphere["lambda"][eq] + * rd2_inv + * (m1[:, np.newaxis] * rd + m2[:, np.newaxis] * this_pos) + ) + + # compute total result + xx = vval_one * ws[:, np.newaxis] + zz = np.array([bincount(bins, x, bins[-1] + 1) for x in xx.T]) + B[3 * ri : 3 * ri + 3, :] = zz + # finishing by scaling by 1/(4*M_PI) + B *= 0.25 / np.pi + return B + + +def _triage_coils(coils): + return coils if isinstance(coils, tuple) else _concatenate_coils(coils) + + +# ############################################################################# +# MAGNETIC DIPOLE (e.g. CHPI) + +_MIN_DIST_LIMIT = 1e-5 + + +def _magnetic_dipole_field_vec(rrs, coils, too_close="raise"): + rmags, cosmags, ws, bins = _triage_coils(coils) + fwd, min_dist = _compute_mdfv(rrs, rmags, cosmags, ws, bins, too_close) + if min_dist < _MIN_DIST_LIMIT: + msg = f"Coil too close (dist = {min_dist * 1000:g} mm)" + if too_close == "raise": + raise RuntimeError(msg) + func = warn if too_close == "warning" else logger.info + func(msg) + return fwd + + +@jit() +def _compute_mdfv(rrs, rmags, cosmags, ws, bins, too_close): + """Compute an MEG forward solution for a set of magnetic dipoles.""" + # The code below is a more efficient version (~30x) of this: + # for ri, rr in enumerate(rrs): + # for k in range(len(coils)): + # this_coil = coils[k] + # # Go through all points + # diff = this_coil['rmag'] - rr + # dist2 = np.sum(diff * diff, axis=1)[:, np.newaxis] + # dist = np.sqrt(dist2) + # if (dist < 1e-5).any(): + # raise RuntimeError('Coil too close') + # dist5 = dist2 * dist2 * dist + # sum_ = (3 * diff * np.sum(diff * this_coil['cosmag'], + # axis=1)[:, np.newaxis] - + # dist2 * this_coil['cosmag']) / dist5 + # fwd[3*ri:3*ri+3, k] = 1e-7 * np.dot(this_coil['w'], sum_) + fwd = np.zeros((3 * len(rrs), bins[-1] + 1)) + min_dist = np.inf + ws2 = ws.reshape(-1, 1) + for ri in range(len(rrs)): + rr = rrs[ri] + diff = rmags - rr + dist2_ = np.sum(diff * diff, axis=1) + dist2 = dist2_.reshape(-1, 1) + dist = np.sqrt(dist2) + min_dist = min(dist.min(), min_dist) + if min_dist < _MIN_DIST_LIMIT and too_close == "raise": + break + t_ = np.sum(diff * cosmags, axis=1) + t = t_.reshape(-1, 1) + sum_ = ws2 * (3 * diff * t - dist2 * cosmags) / (dist2 * dist2 * dist) + for ii in range(3): + fwd[3 * ri + ii] = bincount(bins, sum_[:, ii], bins[-1] + 1) + fwd *= _MAG_FACTOR + return fwd, min_dist + + +# ############################################################################# +# MAIN TRIAGING FUNCTION + + +@verbose +def _prep_field_computation(*, sensors, bem, n_jobs, verbose=None): + """Precompute and store some things that are used for both MEG and EEG. + + Calculation includes multiplication factors, coordinate transforms, + compensations, and forward solutions. All are stored in modified fwd_data. + + Parameters + ---------- + rr : ndarray, shape (n_dipoles, 3) + 3D dipole source positions in head coordinates + bem : instance of ConductorModel + Boundary Element Model information + fwd_data : dict + Dict containing sensor information in the head coordinate frame. + Gets updated here with BEM and sensor information for later forward + calculations. + %(n_jobs)s + %(verbose)s + """ + bem_rr = mults = mri_Q = head_mri_t = None + if not bem["is_sphere"]: + if bem["bem_method"] != FIFF.FIFFV_BEM_APPROX_LINEAR: + raise RuntimeError("only linear collocation supported") + # Store (and apply soon) μ_0/(4π) factor before source computations + mults = np.repeat( + bem["source_mult"] / (4.0 * np.pi), [len(s["rr"]) for s in bem["surfs"]] + )[np.newaxis, :] + # Get positions of BEM points for every surface + bem_rr = np.concatenate([s["rr"] for s in bem["surfs"]]) + + # The dipole location and orientation must be transformed + head_mri_t = bem["head_mri_t"] + mri_Q = bem["head_mri_t"]["trans"][:3, :3].T + + solutions = dict() + for coil_type in sensors: + coils = sensors[coil_type]["defs"] + if not bem["is_sphere"]: + if coil_type == "meg": + # MEG field computation matrices for BEM + start = "Composing the field computation matrix" + logger.info("\n" + start + "...") + cf = FIFF.FIFFV_COORD_HEAD + # multiply solution by "mults" here for simplicity + solution = _bem_specify_coils(bem, coils, cf, mults, n_jobs) + else: + # Compute solution for EEG sensor + logger.info("Setting up for EEG...") + solution = _bem_specify_els(bem, coils, mults) + else: + solution = bem + if coil_type == "eeg": + logger.info( + "Using the equivalent source approach in the " + "homogeneous sphere for EEG" + ) + sensors[coil_type]["defs"] = _triage_coils(coils) + solutions[coil_type] = solution + + # Get appropriate forward physics function depending on sphere or BEM model + fun = _sphere_pot_or_field if bem["is_sphere"] else _bem_pot_or_field + + # Update fwd_data with + # bem_rr (3D BEM vertex positions) + # mri_Q (3x3 Head->MRI coord transformation applied to identity matrix) + # head_mri_t (head->MRI coord transform dict) + # fun (_bem_pot_or_field if not 'sphere'; otherwise _sph_pot_or_field) + # solutions (len 2 list; [ndarray, shape (n_MEG_sens, n BEM vertices), + # ndarray, shape (n_EEG_sens, n BEM vertices)] + fwd_data = dict( + bem_rr=bem_rr, mri_Q=mri_Q, head_mri_t=head_mri_t, fun=fun, solutions=solutions + ) + return fwd_data + + +@fill_doc +def _compute_forwards_meeg(rr, *, sensors, fwd_data, n_jobs, silent=False): + """Compute MEG and EEG forward solutions for all sensor types.""" + Bs = dict() + # The dipole location and orientation must be transformed to mri coords + mri_rr = None + if fwd_data["head_mri_t"] is not None: + mri_rr = np.ascontiguousarray(apply_trans(fwd_data["head_mri_t"]["trans"], rr)) + mri_Q, bem_rr, fun = fwd_data["mri_Q"], fwd_data["bem_rr"], fwd_data["fun"] + solutions = fwd_data["solutions"] + del fwd_data + rr = np.ascontiguousarray(rr) # usually true but not guaranteed, e.g. in dipole.py + for coil_type, sens in sensors.items(): + coils = sens["defs"] + compensator = sens.get("compensator", None) + post_picks = sens.get("post_picks", None) + solution = solutions.get(coil_type, None) + + # Do the actual forward calculation for a list MEG/EEG sensors + if not silent: + logger.info( + f"Computing {coil_type.upper()} at {len(rr)} source location{_pl(rr)} " + "(free orientations)..." + ) + # Calculate forward solution using spherical or BEM model + B = fun( + rr, + mri_rr, + mri_Q, + coils=coils, + solution=solution, + bem_rr=bem_rr, + n_jobs=n_jobs, + coil_type=coil_type, + ) + + # Compensate if needed (only done for MEG systems w/compensation) + if compensator is not None: + B = B @ compensator.T + if post_picks is not None: + B = B[:, post_picks] + Bs[coil_type] = B + return Bs + + +@verbose +def _compute_forwards(rr, *, bem, sensors, n_jobs, verbose=None): + """Compute the MEG and EEG forward solutions.""" + # Split calculation into two steps to save (potentially) a lot of time + # when e.g. dipole fitting + solver = bem.get("solver", "mne") + _check_option("solver", solver, ("mne", "openmeeg")) + if bem["is_sphere"] or solver == "mne": + # This modifies "sensors" in place, so let's copy it in case the calling + # function needs to reuse it (e.g., in simulate_raw.py) + sensors = deepcopy(sensors) + fwd_data = _prep_field_computation(sensors=sensors, bem=bem, n_jobs=n_jobs) + Bs = _compute_forwards_meeg( + rr, sensors=sensors, fwd_data=fwd_data, n_jobs=n_jobs + ) + else: + Bs = _compute_forwards_openmeeg(rr, bem=bem, sensors=sensors) + n_sensors_want = sum(len(s["ch_names"]) for s in sensors.values()) + n_sensors = sum(B.shape[1] for B in Bs.values()) + n_sources = list(Bs.values())[0].shape[0] + assert (n_sources, n_sensors) == (len(rr) * 3, n_sensors_want) + return Bs + + +def _compute_forwards_openmeeg(rr, *, bem, sensors): + """Compute the MEG and EEG forward solutions for OpenMEEG.""" + if len(bem["surfs"]) != 3: + raise RuntimeError("Only 3-layer BEM is supported for OpenMEEG.") + om = _import_openmeeg("compute a forward solution using OpenMEEG") + hminv = om.SymMatrix(bem["solution"]) + geom = _make_openmeeg_geometry(bem, invert_transform(bem["head_mri_t"])) + + # Make dipoles for all XYZ orientations + dipoles = np.c_[ + np.kron(rr.T, np.ones(3)[None, :]).T, + np.kron(np.ones(len(rr))[:, None], np.eye(3)), + ] + dipoles = np.asfortranarray(dipoles) + dipoles = om.Matrix(dipoles) + dsm = om.DipSourceMat(geom, dipoles, "Brain") + Bs = dict() + if "eeg" in sensors: + rmags, _, ws, bins = _concatenate_coils(sensors["eeg"]["defs"]) + rmags = np.asfortranarray(rmags.astype(np.float64)) + eeg_sensors = om.Sensors(om.Matrix(np.asfortranarray(rmags)), geom) + h2em = om.Head2EEGMat(geom, eeg_sensors) + eeg_fwd_full = om.GainEEG(hminv, dsm, h2em).array() + Bs["eeg"] = np.array( + [bincount(bins, ws * x, bins[-1] + 1) for x in eeg_fwd_full.T], float + ) + if "meg" in sensors: + rmags, cosmags, ws, bins = _concatenate_coils(sensors["meg"]["defs"]) + rmags = np.asfortranarray(rmags.astype(np.float64)) + cosmags = np.asfortranarray(cosmags.astype(np.float64)) + labels = [str(ii) for ii in range(len(rmags))] + weights = radii = np.ones(len(labels)) + meg_sensors = om.Sensors(labels, rmags, cosmags, weights, radii) + h2mm = om.Head2MEGMat(geom, meg_sensors) + ds2mm = om.DipSource2MEGMat(dipoles, meg_sensors) + meg_fwd_full = om.GainMEG(hminv, dsm, h2mm, ds2mm).array() + B = np.array( + [bincount(bins, ws * x, bins[-1] + 1) for x in meg_fwd_full.T], float + ) + compensator = sensors["meg"].get("compensator", None) + post_picks = sensors["meg"].get("post_picks", None) + if compensator is not None: + B = B @ compensator.T + if post_picks is not None: + B = B[:, post_picks] + Bs["meg"] = B + return Bs diff --git a/mne-python/source/mne/forward/_field_interpolation.py b/mne-python/source/mne/forward/_field_interpolation.py new file mode 100644 index 0000000000000000000000000000000000000000..369af2ae695e527e461f38aeb810d2a890369afc --- /dev/null +++ b/mne-python/source/mne/forward/_field_interpolation.py @@ -0,0 +1,561 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# The computations in this code were primarily derived from Matti Hämäläinen's +# C code. + +import inspect +from copy import deepcopy + +import numpy as np +from scipy.interpolate import interp1d + +from .._fiff.constants import FIFF +from .._fiff.meas_info import _simplify_info +from .._fiff.pick import pick_info, pick_types +from .._fiff.proj import _has_eeg_average_ref_proj, make_projector +from ..bem import _check_origin +from ..cov import make_ad_hoc_cov +from ..epochs import BaseEpochs, EpochsArray +from ..evoked import Evoked, EvokedArray +from ..fixes import _safe_svd +from ..surface import get_head_surf, get_meg_helmet_surf +from ..transforms import _find_trans, transform_surface_to +from ..utils import _check_fname, _check_option, _pl, _reg_pinv, logger, verbose +from ._lead_dots import ( + _do_cross_dots, + _do_self_dots, + _do_surface_dots, + _get_legen_table, +) +from ._make_forward import _create_eeg_els, _create_meg_coils, _read_coil_defs + + +def _setup_dots(mode, info, coils, ch_type): + """Set up dot products.""" + int_rad = 0.06 + noise = make_ad_hoc_cov(info, dict(mag=20e-15, grad=5e-13, eeg=1e-6)) + n_coeff, interp = (50, "nearest") if mode == "fast" else (100, "linear") + lut, n_fact = _get_legen_table(ch_type, False, n_coeff, verbose=False) + lut_fun = interp1d(np.linspace(-1, 1, lut.shape[0]), lut, interp, axis=0) + return int_rad, noise, lut_fun, n_fact + + +def _compute_mapping_matrix(fmd, info): + """Do the hairy computations.""" + logger.info(" Preparing the mapping matrix...") + # assemble a projector and apply it to the data + ch_names = fmd["ch_names"] + projs = info.get("projs", list()) + proj_op = make_projector(projs, ch_names)[0] + proj_dots = np.dot(proj_op.T, np.dot(fmd["self_dots"], proj_op)) + + noise_cov = fmd["noise"] + # Whiten + if not noise_cov["diag"]: + raise NotImplementedError # this shouldn't happen + whitener = np.diag(1.0 / np.sqrt(noise_cov["data"].ravel())) + whitened_dots = np.dot(whitener.T, np.dot(proj_dots, whitener)) + + # SVD is numerically better than the eigenvalue composition even if + # mat is supposed to be symmetric and positive definite + if fmd.get("pinv_method", "tsvd") == "tsvd": + inv, fmd["nest"] = _pinv_trunc(whitened_dots, fmd["miss"]) + else: + assert fmd["pinv_method"] == "tikhonov", fmd["pinv_method"] + inv, fmd["nest"] = _pinv_tikhonov(whitened_dots, fmd["miss"]) + + # Sandwich with the whitener + inv_whitened = np.dot(whitener.T, np.dot(inv, whitener)) + + # Take into account that the lead fields used to compute + # d->surface_dots were unprojected + inv_whitened_proj = proj_op.T @ inv_whitened + + # Finally sandwich in the selection matrix + # This one picks up the correct lead field projection + mapping_mat = np.dot(fmd["surface_dots"], inv_whitened_proj) + + # Optionally apply the average electrode reference to the final field map + if fmd["kind"] == "eeg" and _has_eeg_average_ref_proj(info): + logger.info( + " The map has an average electrode reference " + f"({mapping_mat.shape[0]} channels)" + ) + mapping_mat -= np.mean(mapping_mat, axis=0) + return mapping_mat + + +def _pinv_trunc(x, miss): + """Compute pseudoinverse, truncating at most "miss" fraction of varexp.""" + u, s, v = _safe_svd(x, full_matrices=False) + + # Eigenvalue truncation + varexp = np.cumsum(s) + varexp /= varexp[-1] + n = np.where(varexp >= (1.0 - miss))[0][0] + 1 + logger.info( + " Truncating at %d/%d components to omit less than %g (%0.2g)", + n, + len(s), + miss, + 1.0 - varexp[n - 1], + ) + s = 1.0 / s[:n] + inv = ((u[:, :n] * s) @ v[:n]).T + return inv, n + + +def _pinv_tikhonov(x, reg): + # _reg_pinv requires square Hermitian, which we have here + inv, _, n = _reg_pinv(x, reg=reg, rank=None) + logger.info( + f" Truncating at {n}/{len(x)} components and regularizing with α={reg:0.1e}" + ) + return inv, n + + +def _map_meg_or_eeg_channels(info_from, info_to, mode, *, origin, miss=None): + """Find mapping from one set of channels to another. + + Parameters + ---------- + info_from : instance of Info + The measurement data to interpolate from. + info_to : instance of Info + The measurement info to interpolate to. + mode : str + Either `'accurate'` or `'fast'`, determines the quality of the + Legendre polynomial expansion used. `'fast'` should be sufficient + for most applications. + origin : array-like, shape (3,) | str + Origin of the sphere in the head coordinate frame and in meters. + Can be ``'auto'``, which means a head-digitization-based origin + fit. + + Returns + ------- + mapping : array, shape (n_to, n_from) + A mapping matrix. + """ + assert origin is not None # should be assured elsewhere + + # no need to apply trans because both from and to coils are in device + # coordinates + info_kinds = set(ch["kind"] for ch in info_to["chs"]) + info_kinds |= set(ch["kind"] for ch in info_from["chs"]) + if FIFF.FIFFV_REF_MEG_CH in info_kinds: # refs same as MEG + info_kinds |= set([FIFF.FIFFV_MEG_CH]) + info_kinds -= set([FIFF.FIFFV_REF_MEG_CH]) + info_kinds = sorted(info_kinds) + # This should be guaranteed by the callers + assert len(info_kinds) == 1 and info_kinds[0] in ( + FIFF.FIFFV_MEG_CH, + FIFF.FIFFV_EEG_CH, + ) + kind = "eeg" if info_kinds[0] == FIFF.FIFFV_EEG_CH else "meg" + + # + # Step 1. Prepare the coil definitions + # + if kind == "meg": + templates = _read_coil_defs(verbose=False) + coils_from = _create_meg_coils( + info_from["chs"], "normal", info_from["dev_head_t"], templates + ) + coils_to = _create_meg_coils( + info_to["chs"], "normal", info_to["dev_head_t"], templates + ) + pinv_method = "tsvd" + miss = 1e-4 + else: + coils_from = _create_eeg_els(info_from["chs"]) + coils_to = _create_eeg_els(info_to["chs"]) + pinv_method = "tikhonov" + miss = 1e-1 + if _has_eeg_average_ref_proj(info_from) and not _has_eeg_average_ref_proj( + info_to + ): + raise RuntimeError( + "info_to must have an average EEG reference projector if " + "info_from has one" + ) + origin = _check_origin(origin, info_from) + # + # Step 2. Calculate the dot products + # + int_rad, noise, lut_fun, n_fact = _setup_dots(mode, info_from, coils_from, kind) + logger.info( + f" Computing dot products for {len(coils_from)} " + f"{kind.upper()} channel{_pl(coils_from)}..." + ) + self_dots = _do_self_dots( + int_rad, False, coils_from, origin, kind, lut_fun, n_fact, n_jobs=None + ) + logger.info( + f" Computing cross products for {len(coils_from)} → " + f"{len(coils_to)} {kind.upper()} channel{_pl(coils_to)}..." + ) + cross_dots = _do_cross_dots( + int_rad, False, coils_from, coils_to, origin, kind, lut_fun, n_fact + ).T + + ch_names = [c["ch_name"] for c in info_from["chs"]] + fmd = dict( + kind=kind, + ch_names=ch_names, + origin=origin, + noise=noise, + self_dots=self_dots, + surface_dots=cross_dots, + int_rad=int_rad, + miss=miss, + pinv_method=pinv_method, + ) + + # + # Step 3. Compute the mapping matrix + # + mapping = _compute_mapping_matrix(fmd, info_from) + return mapping + + +def _as_meg_type_inst(inst, ch_type="grad", mode="fast"): + """Compute virtual evoked using interpolated fields in mag/grad channels. + + Parameters + ---------- + inst : instance of mne.Evoked or mne.Epochs + The evoked or epochs object. + ch_type : str + The destination channel type. It can be 'mag' or 'grad'. + mode : str + Either `'accurate'` or `'fast'`, determines the quality of the + Legendre polynomial expansion used. `'fast'` should be sufficient + for most applications. + + Returns + ------- + inst : instance of mne.EvokedArray or mne.EpochsArray + The transformed evoked object containing only virtual channels. + """ + _check_option("ch_type", ch_type, ["mag", "grad"]) + + # pick the original and destination channels + pick_from = pick_types(inst.info, meg=True, eeg=False, ref_meg=False) + pick_to = pick_types(inst.info, meg=ch_type, eeg=False, ref_meg=False) + + if len(pick_to) == 0: + raise ValueError( + "No channels matching the destination channel type" + " found in info. Please pass an evoked containing" + "both the original and destination channels. Only the" + " locations of the destination channels will be used" + " for interpolation." + ) + + info_from = pick_info(inst.info, pick_from) + info_to = pick_info(inst.info, pick_to) + # XXX someday we should probably expose the origin + mapping = _map_meg_or_eeg_channels( + info_from, info_to, origin=(0.0, 0.0, 0.04), mode=mode + ) + + # compute data by multiplying by the 'gain matrix' from + # original sensors to virtual sensors + if hasattr(inst, "get_data"): + kwargs = dict() + if "copy" in inspect.getfullargspec(inst.get_data).kwonlyargs: + kwargs["copy"] = False + data = inst.get_data(**kwargs) + else: + data = inst.data + + ndim = data.ndim + if ndim == 2: + data = data[np.newaxis, :, :] + + data_ = np.empty((data.shape[0], len(mapping), data.shape[2]), dtype=data.dtype) + for d, d_ in zip(data, data_): + d_[:] = np.dot(mapping, d[pick_from]) + + # keep only the destination channel types + info = pick_info(inst.info, sel=pick_to, copy=True) + + # change channel names to emphasize they contain interpolated data + for ch in info["chs"]: + ch["ch_name"] += "_v" + info._update_redundant() + info._check_consistency() + if isinstance(inst, Evoked): + assert ndim == 2 + data_ = data_[0] # undo new axis + inst_ = EvokedArray( + data_, info, tmin=inst.times[0], comment=inst.comment, nave=inst.nave + ) + else: + assert isinstance(inst, BaseEpochs) + inst_ = EpochsArray( + data_, + info, + tmin=inst.tmin, + events=inst.events, + event_id=inst.event_id, + metadata=inst.metadata, + ) + + return inst_ + + +@verbose +def _make_surface_mapping( + info, + surf, + ch_type="meg", + trans=None, + mode="fast", + n_jobs=None, + *, + origin, + verbose=None, +): + """Re-map M/EEG data to a surface. + + Parameters + ---------- + %(info_not_none)s + surf : dict + The surface to map the data to. The required fields are `'rr'`, + `'nn'`, and `'coord_frame'`. Must be in head coordinates. + ch_type : str + Must be either `'meg'` or `'eeg'`, determines the type of field. + trans : None | dict + If None, no transformation applied. Should be a Head<->MRI + transformation. + mode : str + Either `'accurate'` or `'fast'`, determines the quality of the + Legendre polynomial expansion used. `'fast'` should be sufficient + for most applications. + %(n_jobs)s + origin : array-like, shape (3,) | str + Origin of the sphere in the head coordinate frame and in meters. + %(verbose)s + + Returns + ------- + mapping : array + A n_vertices x n_sensors array that remaps the MEG or EEG data, + as `new_data = np.dot(mapping, data)`. + """ + assert origin is not None # should be assured elsewhere + + if not all(key in surf for key in ["rr", "nn"]): + raise KeyError('surf must have both "rr" and "nn"') + if "coord_frame" not in surf: + raise KeyError( + 'The surface coordinate frame must be specified in surf["coord_frame"]' + ) + _check_option("mode", mode, ["accurate", "fast"]) + + # deal with coordinate frames here -- always go to "head" (easiest) + orig_surf = surf + surf = transform_surface_to(deepcopy(surf), "head", trans) + origin = _check_origin(origin, info) + + # + # Step 1. Prepare the coil definitions + # Do the dot products, assume surf in head coords + # + _check_option("ch_type", ch_type, ["meg", "eeg"]) + if ch_type == "meg": + picks = pick_types(info, meg=True, eeg=False, ref_meg=False) + logger.info("Prepare MEG mapping...") + else: + picks = pick_types(info, meg=False, eeg=True, ref_meg=False) + logger.info("Prepare EEG mapping...") + if len(picks) == 0: + raise RuntimeError("cannot map, no channels found") + # XXX this code does not do any checking for compensation channels, + # but it seems like this must be intentional from the ref_meg=False + # (presumably from the C code) + dev_head_t = info["dev_head_t"] + info = pick_info(_simplify_info(info), picks) + info["dev_head_t"] = dev_head_t + + # create coil defs in head coordinates + if ch_type == "meg": + # Put them in head coordinates + coils = _create_meg_coils(info["chs"], "normal", info["dev_head_t"]) + type_str = "coils" + miss = 1e-4 # Smoothing criterion for MEG + else: # EEG + coils = _create_eeg_els(info["chs"]) + type_str = "electrodes" + miss = 1e-3 # Smoothing criterion for EEG + + # + # Step 2. Calculate the dot products + # + int_rad, noise, lut_fun, n_fact = _setup_dots(mode, info, coils, ch_type) + logger.info("Computing dot products for %i %s...", len(coils), type_str) + self_dots = _do_self_dots( + int_rad, False, coils, origin, ch_type, lut_fun, n_fact, n_jobs + ) + sel = np.arange(len(surf["rr"])) # eventually we should do sub-selection + logger.info("Computing dot products for %i surface locations...", len(sel)) + surface_dots = _do_surface_dots( + int_rad, False, coils, surf, sel, origin, ch_type, lut_fun, n_fact, n_jobs + ) + + # + # Step 4. Return the result + # + fmd = dict( + kind=ch_type, + surf=surf, + ch_names=info["ch_names"], + coils=coils, + origin=origin, + noise=noise, + self_dots=self_dots, + surface_dots=surface_dots, + int_rad=int_rad, + miss=miss, + ) + logger.info("Field mapping data ready") + + fmd["data"] = _compute_mapping_matrix(fmd, info) + # bring the original back, whatever coord frame it was in + fmd["surf"] = orig_surf + + # Remove some unnecessary fields + del fmd["self_dots"] + del fmd["surface_dots"] + del fmd["int_rad"] + del fmd["miss"] + return fmd + + +@verbose +def make_field_map( + evoked, + trans="auto", + subject=None, + subjects_dir=None, + ch_type=None, + *, + mode="fast", + meg_surf="helmet", + origin="auto", + n_jobs=None, + upsampling=1, + head_source=("bem", "head"), + verbose=None, +): + """Compute surface maps used for field display in 3D. + + Parameters + ---------- + evoked : Evoked | Epochs | Raw + The measurement file. Need to have info attribute. + %(trans)s ``"auto"`` (default) will load trans from the FreeSurfer + directory specified by ``subject`` and ``subjects_dir`` parameters. + + .. versionchanged:: 0.19 + Support for ``'fsaverage'`` argument. + subject : str | None + The subject name corresponding to FreeSurfer environment + variable SUBJECT. If None, map for EEG data will not be available. + subjects_dir : path-like + The path to the freesurfer subjects reconstructions. + It corresponds to Freesurfer environment variable SUBJECTS_DIR. + ch_type : None | ``'eeg'`` | ``'meg'`` + If None, a map for each available channel type will be returned. + Else only the specified type will be used. + mode : ``'accurate'`` | ``'fast'`` + Either ``'accurate'`` or ``'fast'``, determines the quality of the + Legendre polynomial expansion used. ``'fast'`` should be sufficient + for most applications. + meg_surf : 'helmet' | 'head' + Should be ``'helmet'`` or ``'head'`` to specify in which surface + to compute the MEG field map. The default value is ``'helmet'``. + origin : array-like, shape (3,) | 'auto' + Origin of the sphere in the head coordinate frame and in meters. + Can be ``'auto'``, which means a head-digitization-based origin + fit. Default is ``(0., 0., 0.04)``. + + .. versionadded:: 0.11 + .. versionchanged:: 1.12 + In 1.12 the default value is "auto". + In 1.11 and prior versions, it is ``(0., 0., 0.04)``. + %(n_jobs)s + %(helmet_upsampling)s + + .. versionadded:: 1.10 + %(head_source)s + + .. versionadded:: 1.1 + %(verbose)s + + Returns + ------- + surf_maps : list + The surface maps to be used for field plots. The list contains + separate ones for MEG and EEG (if both MEG and EEG are present). + """ + info = evoked.info + + if ch_type is None: + types = [t for t in ["eeg", "meg"] if t in evoked] + else: + _check_option("ch_type", ch_type, ["eeg", "meg"]) + types = [ch_type] + + if subjects_dir is not None: + subjects_dir = _check_fname( + subjects_dir, + overwrite="read", + must_exist=True, + name="subjects_dir", + need_dir=True, + ) + + trans, trans_type = _find_trans( + trans=trans, + subject=subject, + subjects_dir=subjects_dir, + ) + + if "eeg" in types and trans_type == "identity": + logger.info("No trans file available. EEG data ignored.") + types.remove("eeg") + + if len(types) == 0: + raise RuntimeError("No data available for mapping.") + + _check_option("meg_surf", meg_surf, ["helmet", "head"]) + + surfs = [] + for this_type in types: + if this_type == "meg" and meg_surf == "helmet": + surf = get_meg_helmet_surf(info, trans, upsampling=upsampling) + else: + surf = get_head_surf(subject, source=head_source, subjects_dir=subjects_dir) + surfs.append(surf) + + surf_maps = list() + + for this_type, this_surf in zip(types, surfs): + this_map = _make_surface_mapping( + evoked.info, + this_surf, + this_type, + trans, + n_jobs=n_jobs, + origin=origin, + mode=mode, + ) + surf_maps.append(this_map) + + return surf_maps diff --git a/mne-python/source/mne/forward/_lead_dots.py b/mne-python/source/mne/forward/_lead_dots.py new file mode 100644 index 0000000000000000000000000000000000000000..9e6176dbc5c68cac51a1ded2fd523b0c47b26e29 --- /dev/null +++ b/mne-python/source/mne/forward/_lead_dots.py @@ -0,0 +1,611 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# The computations in this code were primarily derived from Matti Hämäläinen's +# C code. + +import os +import os.path as op + +import numpy as np +from numpy.polynomial import legendre + +from ..fixes import _reshape_view +from ..parallel import parallel_func +from ..utils import _get_extra_data_path, _open_lock, fill_doc, logger, verbose + +############################################################################## +# FAST LEGENDRE (DERIVATIVE) POLYNOMIALS USING LOOKUP TABLE + + +def _next_legen_der(n, x, p0, p01, p0d, p0dd): + """Compute the next Legendre polynomial and its derivatives.""" + # only good for n > 1 ! + old_p0 = p0 + old_p0d = p0d + p0 = ((2 * n - 1) * x * old_p0 - (n - 1) * p01) / n + p0d = n * old_p0 + x * old_p0d + p0dd = (n + 1) * old_p0d + x * p0dd + return p0, p0d, p0dd + + +def _get_legen(x, n_coeff=100): + """Get Legendre polynomials expanded about x.""" + return legendre.legvander(x, n_coeff - 1) + + +def _get_legen_der(xx, n_coeff=100): + """Get Legendre polynomial derivatives expanded about x.""" + coeffs = np.empty((len(xx), n_coeff, 3)) + for c, x in zip(coeffs, xx): + p0s, p0ds, p0dds = c[:, 0], c[:, 1], c[:, 2] + p0s[:2] = [1.0, x] + p0ds[:2] = [0.0, 1.0] + p0dds[:2] = [0.0, 0.0] + for n in range(2, n_coeff): + p0s[n], p0ds[n], p0dds[n] = _next_legen_der( + n, x, p0s[n - 1], p0s[n - 2], p0ds[n - 1], p0dds[n - 1] + ) + return coeffs + + +@verbose +def _get_legen_table( + ch_type, + volume_integral=False, + n_coeff=100, + n_interp=20000, + force_calc=False, + verbose=None, +): + """Return a (generated) LUT of Legendre (derivative) polynomial coeffs.""" + if n_interp % 2 != 0: + raise RuntimeError("n_interp must be even") + fname = op.join(_get_extra_data_path(), "tables") + if not op.isdir(fname): + # Updated due to API change (GH 1167) + os.makedirs(fname) + if ch_type == "meg": + fname = op.join(fname, f"legder_{n_coeff}_{n_interp}.bin") + leg_fun = _get_legen_der + extra_str = " derivative" + lut_shape = (n_interp + 1, n_coeff, 3) + else: # 'eeg' + fname = op.join(fname, f"legval_{n_coeff}_{n_interp}.bin") + leg_fun = _get_legen + extra_str = "" + lut_shape = (n_interp + 1, n_coeff) + if not op.isfile(fname) or force_calc: + logger.info(f"Generating Legendre{extra_str} table...") + x_interp = np.linspace(-1, 1, n_interp + 1) + lut = leg_fun(x_interp, n_coeff).astype(np.float32) + if not force_calc: + with _open_lock(fname, "wb") as fid: + fid.write(lut.tobytes()) + else: + logger.info(f"Reading Legendre{extra_str} table...") + with _open_lock(fname, "rb", buffering=0) as fid: + lut = np.fromfile(fid, np.float32) + lut = _reshape_view(lut, lut_shape) + + # we need this for the integration step + n_fact = np.arange(1, n_coeff, dtype=float) + if ch_type == "meg": + n_facts = list() # multn, then mult, then multn * (n + 1) + if volume_integral: + n_facts.append(n_fact / ((2.0 * n_fact + 1.0) * (2.0 * n_fact + 3.0))) + else: + n_facts.append(n_fact / (2.0 * n_fact + 1.0)) + n_facts.append(n_facts[0] / (n_fact + 1.0)) + n_facts.append(n_facts[0] * (n_fact + 1.0)) + # skip the first set of coefficients because they are not used + lut = lut[:, 1:, [0, 1, 1, 2]] # for multiplicative convenience later + # reshape this for convenience, too + n_facts = np.array(n_facts)[[2, 0, 1, 1], :].T + n_facts = np.ascontiguousarray(n_facts) + n_fact = n_facts + else: # 'eeg' + n_fact = (2.0 * n_fact + 1.0) * (2.0 * n_fact + 1.0) / n_fact + # skip the first set of coefficients because they are not used + lut = lut[:, 1:].copy() + return lut, n_fact + + +def _comp_sum_eeg(beta, ctheta, lut_fun, n_fact): + """Lead field dot products using Legendre polynomial (P_n) series.""" + # Compute the sum occurring in the evaluation. + # The result is + # sums[:] (2n+1)^2/n beta^n P_n + n_chunk = 50000000 // (8 * max(n_fact.shape) * 2) + lims = np.concatenate([np.arange(0, beta.size, n_chunk), [beta.size]]) + s0 = np.empty(beta.shape) + for start, stop in zip(lims[:-1], lims[1:]): + coeffs = lut_fun(ctheta[start:stop]) + betans = np.tile(beta[start:stop][:, np.newaxis], (1, n_fact.shape[0])) + np.cumprod(betans, axis=1, out=betans) # run inplace + coeffs *= betans + s0[start:stop] = np.dot(coeffs, n_fact) # == weighted sum across cols + return s0 + + +def _comp_sums_meg(beta, ctheta, lut_fun, n_fact, volume_integral): + """Lead field dot products using Legendre polynomial (P_n) series. + + Parameters + ---------- + beta : array, shape (n_points * n_points, 1) + Coefficients of the integration. + ctheta : array, shape (n_points * n_points, 1) + Cosine of the angle between the sensor integration points. + lut_fun : callable + Look-up table for evaluating Legendre polynomials. + n_fact : array + Coefficients in the integration sum. + volume_integral : bool + If True, compute volume integral. + + Returns + ------- + sums : array, shape (4, n_points * n_points) + The results. + """ + # Compute the sums occurring in the evaluation. + # Two point magnetometers on the xz plane are assumed. + # The four sums are: + # * sums[:, 0] n(n+1)/(2n+1) beta^(n+1) P_n + # * sums[:, 1] n/(2n+1) beta^(n+1) P_n' + # * sums[:, 2] n/((2n+1)(n+1)) beta^(n+1) P_n' + # * sums[:, 3] n/((2n+1)(n+1)) beta^(n+1) P_n'' + + # This is equivalent, but slower: + # sums = np.sum(bbeta[:, :, np.newaxis].T * n_fact * coeffs, axis=1) + # sums = np.rollaxis(sums, 2) + # or + # sums = np.einsum('ji,jk,ijk->ki', bbeta, n_fact, lut_fun(ctheta))) + sums = np.empty((n_fact.shape[1], len(beta))) + # beta can be e.g. 3 million elements, which ends up using lots of memory + # so we split up the computations into ~50 MB blocks + n_chunk = 50000000 // (8 * max(n_fact.shape) * 2) + lims = np.concatenate([np.arange(0, beta.size, n_chunk), [beta.size]]) + for start, stop in zip(lims[:-1], lims[1:]): + bbeta = np.tile(beta[start:stop][np.newaxis], (n_fact.shape[0], 1)) + bbeta[0] *= beta[start:stop] + np.cumprod(bbeta, axis=0, out=bbeta) # run inplace + np.einsum( + "ji,jk,ijk->ki", + bbeta, + n_fact, + lut_fun(ctheta[start:stop]), + out=sums[:, start:stop], + ) + return sums + + +############################################################################### +# SPHERE DOTS + +_meg_const = 4e-14 * np.pi # This is \mu_0^2/4\pi +_eeg_const = 1.0 / (4.0 * np.pi) + + +def _fast_sphere_dot_r0( + r, + rr1_orig, + rr2s, + lr1, + lr2s, + cosmags1, + cosmags2s, + w1, + w2s, + volume_integral, + lut, + n_fact, + ch_type, +): + """Lead field dot product computation for M/EEG in the sphere model. + + Parameters + ---------- + r : float + The integration radius. It is used to calculate beta as: + beta = (r * r) / (lr1 * lr2). + rr1 : array, shape (n_points x 3) + Normalized position vectors of integrations points in first sensor. + rr2s : list + Normalized position vector of integration points in second sensor. + lr1 : array, shape (n_points x 1) + Magnitude of position vector of integration points in first sensor. + lr2s : list + Magnitude of position vector of integration points in second sensor. + cosmags1 : array, shape (n_points x 1) + Direction of integration points in first sensor. + cosmags2s : list + Direction of integration points in second sensor. + w1 : array, shape (n_points x 1) | None + Weights of integration points in the first sensor. + w2s : list + Weights of integration points in the second sensor. + volume_integral : bool + If True, compute volume integral. + lut : callable + Look-up table for evaluating Legendre polynomials. + n_fact : array + Coefficients in the integration sum. + ch_type : str + The channel type. It can be 'meg' or 'eeg'. + + Returns + ------- + result : float + The integration sum. + """ + if w1 is None: # operating on surface, treat independently + out_shape = (len(rr2s), len(rr1_orig)) + sum_axis = 1 # operate along second axis only at the end + else: + out_shape = (len(rr2s),) + sum_axis = None # operate on flattened array at the end + out = np.empty(out_shape) + rr2 = np.concatenate(rr2s) + lr2 = np.concatenate(lr2s) + cosmags2 = np.concatenate(cosmags2s) + + # outer product, sum over coords + ct = np.einsum("ik,jk->ij", rr1_orig, rr2) + np.clip(ct, -1, 1, ct) + + # expand axes + rr1 = rr1_orig[:, np.newaxis, :] # (n_rr1, n_rr2, n_coord) e.g. 4x4x3 + rr2 = rr2[np.newaxis, :, :] + lr1lr2 = lr1[:, np.newaxis] * lr2[np.newaxis, :] + + beta = (r * r) / lr1lr2 + if ch_type == "meg": + sums = _comp_sums_meg( + beta.flatten(), ct.flatten(), lut, n_fact, volume_integral + ) + sums = _reshape_view(sums, ((4,) + beta.shape)) + + # Accumulate the result, a little bit streamlined version + # cosmags1 = cosmags1[:, np.newaxis, :] + # cosmags2 = cosmags2[np.newaxis, :, :] + # n1c1 = np.sum(cosmags1 * rr1, axis=2) + # n1c2 = np.sum(cosmags1 * rr2, axis=2) + # n2c1 = np.sum(cosmags2 * rr1, axis=2) + # n2c2 = np.sum(cosmags2 * rr2, axis=2) + # n1n2 = np.sum(cosmags1 * cosmags2, axis=2) + n1c1 = np.einsum("ik,ijk->ij", cosmags1, rr1) + n1c2 = np.einsum("ik,ijk->ij", cosmags1, rr2) + n2c1 = np.einsum("jk,ijk->ij", cosmags2, rr1) + n2c2 = np.einsum("jk,ijk->ij", cosmags2, rr2) + n1n2 = np.einsum("ik,jk->ij", cosmags1, cosmags2) + part1 = ct * n1c1 * n2c2 + part2 = n1c1 * n2c1 + n1c2 * n2c2 + + result = ( + n1c1 * n2c2 * sums[0] + + (2.0 * part1 - part2) * sums[1] + + (n1n2 + part1 - part2) * sums[2] + + (n1c2 - ct * n1c1) * (n2c1 - ct * n2c2) * sums[3] + ) + + # Give it a finishing touch! + result *= _meg_const / lr1lr2 + if volume_integral: + result *= r + else: # 'eeg' + result = _comp_sum_eeg(beta.flatten(), ct.flatten(), lut, n_fact) + result = _reshape_view(result, beta.shape) + # Give it a finishing touch! + result *= _eeg_const + result /= lr1lr2 + # now we add them all up with weights + offset = 0 + result *= np.concatenate(w2s) + if w1 is not None: + result *= w1[:, np.newaxis] + for ii, w2 in enumerate(w2s): + out[ii] = np.sum(result[:, offset : offset + len(w2)], axis=sum_axis) + offset += len(w2) + return out + + +@fill_doc +def _do_self_dots(intrad, volume, coils, r0, ch_type, lut, n_fact, n_jobs): + """Perform the lead field dot product integrations. + + Parameters + ---------- + intrad : float + The integration radius. It is used to calculate beta as: + beta = (intrad * intrad) / (r1 * r2). + volume : bool + If True, perform volume integral. + coils : list of dict + The coils. + r0 : array, shape (3 x 1) + The origin of the sphere. + ch_type : str + The channel type. It can be 'meg' or 'eeg'. + lut : callable + Look-up table for evaluating Legendre polynomials. + n_fact : array + Coefficients in the integration sum. + %(n_jobs)s + + Returns + ------- + products : array, shape (n_coils, n_coils) + The integration products. + """ + if ch_type == "eeg": + intrad = intrad * 0.7 + # convert to normalized distances from expansion center + rmags = [coil["rmag"] - r0[np.newaxis, :] for coil in coils] + rlens = [np.sqrt(np.sum(r * r, axis=1)) for r in rmags] + rmags = [r / rl[:, np.newaxis] for r, rl in zip(rmags, rlens)] + cosmags = [coil["cosmag"] for coil in coils] + ws = [coil["w"] for coil in coils] + parallel, p_fun, n_jobs = parallel_func(_do_self_dots_subset, n_jobs) + prods = parallel( + p_fun(intrad, rmags, rlens, cosmags, ws, volume, lut, n_fact, ch_type, idx) + for idx in np.array_split(np.arange(len(rmags)), n_jobs) + ) + products = np.sum(prods, axis=0) + return products + + +def _do_self_dots_subset( + intrad, rmags, rlens, cosmags, ws, volume, lut, n_fact, ch_type, idx +): + """Parallelize.""" + # all possible combinations of two magnetometers + products = np.zeros((len(rmags), len(rmags))) + for ci1 in idx: + ci2 = ci1 + 1 + res = _fast_sphere_dot_r0( + intrad, + rmags[ci1], + rmags[:ci2], + rlens[ci1], + rlens[:ci2], + cosmags[ci1], + cosmags[:ci2], + ws[ci1], + ws[:ci2], + volume, + lut, + n_fact, + ch_type, + ) + products[ci1, :ci2] = res + products[:ci2, ci1] = res + return products + + +def _do_cross_dots(intrad, volume, coils1, coils2, r0, ch_type, lut, n_fact): + """Compute lead field dot product integrations between two coil sets. + + The code is a direct translation of MNE-C code found in + `mne_map_data/lead_dots.c`. + + Parameters + ---------- + intrad : float + The integration radius. It is used to calculate beta as: + beta = (intrad * intrad) / (r1 * r2). + volume : bool + If True, compute volume integral. + coils1 : list of dict + The original coils. + coils2 : list of dict + The coils to which data is being mapped. + r0 : array, shape (3 x 1). + The origin of the sphere. + ch_type : str + The channel type. It can be 'meg' or 'eeg' + lut : callable + Look-up table for evaluating Legendre polynomials. + n_fact : array + Coefficients in the integration sum. + + Returns + ------- + products : array, shape (n_coils, n_coils) + The integration products. + """ + if ch_type == "eeg": + intrad = intrad * 0.7 + rmags1 = [coil["rmag"] - r0[np.newaxis, :] for coil in coils1] + rmags2 = [coil["rmag"] - r0[np.newaxis, :] for coil in coils2] + + rlens1 = [np.sqrt(np.sum(r * r, axis=1)) for r in rmags1] + rlens2 = [np.sqrt(np.sum(r * r, axis=1)) for r in rmags2] + + rmags1 = [r / rl[:, np.newaxis] for r, rl in zip(rmags1, rlens1)] + rmags2 = [r / rl[:, np.newaxis] for r, rl in zip(rmags2, rlens2)] + + ws1 = [coil["w"] for coil in coils1] + ws2 = [coil["w"] for coil in coils2] + + cosmags1 = [coil["cosmag"] for coil in coils1] + cosmags2 = [coil["cosmag"] for coil in coils2] + + products = np.zeros((len(rmags1), len(rmags2))) + for ci1 in range(len(coils1)): + res = _fast_sphere_dot_r0( + intrad, + rmags1[ci1], + rmags2, + rlens1[ci1], + rlens2, + cosmags1[ci1], + cosmags2, + ws1[ci1], + ws2, + volume, + lut, + n_fact, + ch_type, + ) + products[ci1, :] = res + return products + + +@fill_doc +def _do_surface_dots( + intrad, volume, coils, surf, sel, r0, ch_type, lut, n_fact, n_jobs +): + """Compute the map construction products. + + Parameters + ---------- + intrad : float + The integration radius. It is used to calculate beta as: + beta = (intrad * intrad) / (r1 * r2) + volume : bool + If True, compute a volume integral. + coils : list of dict + The coils. + surf : dict + The surface on which the field is interpolated. + sel : array + Indices of the surface vertices to select. + r0 : array, shape (3 x 1) + The origin of the sphere. + ch_type : str + The channel type. It can be 'meg' or 'eeg'. + lut : callable + Look-up table for Legendre polynomials. + n_fact : array + Coefficients in the integration sum. + %(n_jobs)s + + Returns + ------- + products : array, shape (n_coils, n_coils) + The integration products. + """ + # convert to normalized distances from expansion center + rmags = [coil["rmag"] - r0[np.newaxis, :] for coil in coils] + rlens = [np.sqrt(np.sum(r * r, axis=1)) for r in rmags] + rmags = [r / rl[:, np.newaxis] for r, rl in zip(rmags, rlens)] + cosmags = [coil["cosmag"] for coil in coils] + ws = [coil["w"] for coil in coils] + rref = None + refl = None + # virt_ref = False + if ch_type == "eeg": + intrad = intrad * 0.7 + # The virtual ref code is untested and unused, so it is + # commented out for now + # if virt_ref: + # rref = virt_ref[np.newaxis, :] - r0[np.newaxis, :] + # refl = np.sqrt(np.sum(rref * rref, axis=1)) + # rref /= refl[:, np.newaxis] + + rsurf = surf["rr"][sel] - r0[np.newaxis, :] + lsurf = np.sqrt(np.sum(rsurf * rsurf, axis=1)) + rsurf /= lsurf[:, np.newaxis] + this_nn = surf["nn"][sel] + + # loop over the coils + parallel, p_fun, n_jobs = parallel_func(_do_surface_dots_subset, n_jobs) + prods = parallel( + p_fun( + intrad, + rsurf, + rmags, + rref, + refl, + lsurf, + rlens, + this_nn, + cosmags, + ws, + volume, + lut, + n_fact, + ch_type, + idx, + ) + for idx in np.array_split(np.arange(len(rmags)), n_jobs) + ) + products = np.sum(prods, axis=0) + return products + + +def _do_surface_dots_subset( + intrad, + rsurf, + rmags, + rref, + refl, + lsurf, + rlens, + this_nn, + cosmags, + ws, + volume, + lut, + n_fact, + ch_type, + idx, +): + """Parallelize. + + Parameters + ---------- + refl : array | None + If ch_type is 'eeg', the magnitude of position vector of the + virtual reference (never used). + lsurf : array + Magnitude of position vector of the surface points. + rlens : list of arrays of length n_coils + Magnitude of position vector. + this_nn : array, shape (n_vertices, 3) + Surface normals. + cosmags : list of array. + Direction of the integration points in the coils. + ws : list of array + Integration weights of the coils. + volume : bool + If True, compute volume integral. + lut : callable + Look-up table for evaluating Legendre polynomials. + n_fact : array + Coefficients in the integration sum. + ch_type : str + 'meg' or 'eeg' + idx : array, shape (n_coils x 1) + Index of coil. + + Returns + ------- + products : array, shape (n_coils, n_coils) + The integration products. + """ + products = _fast_sphere_dot_r0( + intrad, + rsurf, + rmags, + lsurf, + rlens, + this_nn, + cosmags, + None, + ws, + volume, + lut, + n_fact, + ch_type, + ).T + if rref is not None: + raise NotImplementedError # we don't ever use this, isn't tested + # vres = _fast_sphere_dot_r0( + # intrad, rref, rmags, refl, rlens, this_nn, cosmags, None, ws, + # volume, lut, n_fact, ch_type) + # products -= vres + return products diff --git a/mne-python/source/mne/forward/_make_forward.py b/mne-python/source/mne/forward/_make_forward.py new file mode 100644 index 0000000000000000000000000000000000000000..9c2f2552cc95c403d20e0f8d6d9255bfb751d380 --- /dev/null +++ b/mne-python/source/mne/forward/_make_forward.py @@ -0,0 +1,1067 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# The computations in this code were primarily derived from Matti Hämäläinen's +# C code. + +import os +import os.path as op +from contextlib import contextmanager +from copy import deepcopy +from pathlib import Path + +import numpy as np + +from .._fiff.compensator import get_current_comp, make_compensator +from .._fiff.constants import FIFF, FWD +from .._fiff.meas_info import Info, read_info +from .._fiff.pick import _has_kit_refs, pick_info, pick_types +from .._fiff.tag import _loc_to_coil_trans, _loc_to_eeg_loc +from ..bem import ConductorModel, _bem_find_surface, read_bem_solution +from ..source_estimate import VolSourceEstimate +from ..source_space._source_space import ( + SourceSpaces, + _complete_vol_src, + _ensure_src, + _filter_source_spaces, + _make_discrete_source_space, +) +from ..surface import _CheckInside, _CheckInsideSphere, _normalize_vectors +from ..transforms import ( + Transform, + _coord_frame_name, + _ensure_trans, + _get_trans, + _print_coord_trans, + apply_trans, + invert_transform, +) +from ..utils import ( + _check_fname, + _on_missing, + _pl, + _validate_type, + logger, + verbose, + warn, +) +from ._compute_forward import ( + _compute_forwards, + _compute_forwards_meeg, + _prep_field_computation, +) +from .forward import _FWD_ORDER, Forward, _merge_fwds, convert_forward_solution + +_accuracy_dict = dict( + point=FWD.COIL_ACCURACY_POINT, + normal=FWD.COIL_ACCURACY_NORMAL, + accurate=FWD.COIL_ACCURACY_ACCURATE, +) +_extra_coil_def_fname = None + + +@verbose +def _read_coil_defs(verbose=None): + """Read a coil definition file. + + Parameters + ---------- + %(verbose)s + + Returns + ------- + res : list of dict + The coils. It is a dictionary with valid keys: + 'cosmag' | 'coil_class' | 'coord_frame' | 'rmag' | 'type' | + 'chname' | 'accuracy'. + cosmag contains the direction of the coils and rmag contains the + position vector. + + Notes + ----- + The global variable "_extra_coil_def_fname" can be used to prepend + additional definitions. These are never added to the registry. + """ + coil_dir = op.join(op.split(__file__)[0], "..", "data") + coils = list() + if _extra_coil_def_fname is not None: + coils += _read_coil_def_file(_extra_coil_def_fname, use_registry=False) + coils += _read_coil_def_file(op.join(coil_dir, "coil_def.dat")) + return coils + + +# Typically we only have 1 or 2 coil def files, but they can end up being +# read a lot. Let's keep a list of them and just reuse them: +_coil_registry = {} + + +def _read_coil_def_file(fname, use_registry=True): + """Read a coil def file.""" + if not use_registry or fname not in _coil_registry: + big_val = 0.5 + coils = list() + with open(fname) as fid: + lines = fid.readlines() + lines = lines[::-1] + while len(lines) > 0: + line = lines.pop().strip() + if line[0] == "#" and len(line) > 0: + continue + desc_start = line.find('"') + desc_end = len(line) - 1 + assert line.strip()[desc_end] == '"' + desc = line[desc_start:desc_end] + vals = np.fromstring(line[:desc_start].strip(), dtype=float, sep=" ") + assert len(vals) == 6 + npts = int(vals[3]) + coil = dict( + coil_type=vals[1], + coil_class=vals[0], + desc=desc, + accuracy=vals[2], + size=vals[4], + base=vals[5], + ) + # get parameters of each component + rmag = list() + cosmag = list() + w = list() + for p in range(npts): + # get next non-comment line + line = lines.pop() + while line[0] == "#": + line = lines.pop() + vals = np.fromstring(line, sep=" ") + if len(vals) != 7: + raise RuntimeError( + f"Could not interpret line {p + 1} as 7 points:\n{line}" + ) + # Read and verify data for each integration point + w.append(vals[0]) + rmag.append(vals[[1, 2, 3]]) + cosmag.append(vals[[4, 5, 6]]) + w = np.array(w) + rmag = np.array(rmag) + cosmag = np.array(cosmag) + size = np.sqrt(np.sum(cosmag**2, axis=1)) + if np.any(np.sqrt(np.sum(rmag**2, axis=1)) > big_val): + raise RuntimeError("Unreasonable integration point") + if np.any(size <= 0): + raise RuntimeError("Unreasonable normal") + cosmag /= size[:, np.newaxis] + coil.update(dict(w=w, cosmag=cosmag, rmag=rmag)) + coils.append(coil) + if use_registry: + _coil_registry[fname] = coils + if use_registry: + coils = deepcopy(_coil_registry[fname]) + logger.info("%d coil definition%s read", len(coils), _pl(coils)) + return coils + + +def _create_meg_coil(coilset, ch, acc, do_es): + """Create a coil definition using templates, transform if necessary.""" + # Also change the coordinate frame if so desired + if ch["kind"] not in [FIFF.FIFFV_MEG_CH, FIFF.FIFFV_REF_MEG_CH]: + raise RuntimeError(f"{ch['ch_name']} is not a MEG channel") + + # Simple linear search from the coil definitions + for coil in coilset: + if coil["coil_type"] == (ch["coil_type"] & 0xFFFF) and coil["accuracy"] == acc: + break + else: + raise RuntimeError( + f"Desired coil definition not found (type = {ch['coil_type']} acc = {acc})" + ) + + # Apply a coordinate transformation if so desired + coil_trans = _loc_to_coil_trans(ch["loc"]) + + # Create the result + res = dict( + chname=ch["ch_name"], + coil_class=coil["coil_class"], + accuracy=coil["accuracy"], + base=coil["base"], + size=coil["size"], + type=ch["coil_type"], + w=coil["w"], + desc=coil["desc"], + coord_frame=FIFF.FIFFV_COORD_DEVICE, + rmag_orig=coil["rmag"], + cosmag_orig=coil["cosmag"], + coil_trans_orig=coil_trans, + r0=coil_trans[:3, 3], + rmag=apply_trans(coil_trans, coil["rmag"]), + cosmag=apply_trans(coil_trans, coil["cosmag"], False), + ) + if do_es: + r0_exey = np.dot(coil["rmag"][:, :2], coil_trans[:3, :2].T) + coil_trans[:3, 3] + res.update( + ex=coil_trans[:3, 0], + ey=coil_trans[:3, 1], + ez=coil_trans[:3, 2], + r0_exey=r0_exey, + ) + return res + + +def _create_eeg_el(ch, t=None): + """Create an electrode definition, transform coords if necessary.""" + if ch["kind"] != FIFF.FIFFV_EEG_CH: + raise RuntimeError( + f"{ch['ch_name']} is not an EEG channel. Cannot create an electrode " + "definition." + ) + if t is None: + t = Transform("head", "head") # identity, no change + if t.from_str != "head": + raise RuntimeError("Inappropriate coordinate transformation") + + r0ex = _loc_to_eeg_loc(ch["loc"]) + if r0ex.shape[1] == 1: # no reference + w = np.array([1.0]) + else: # has reference + w = np.array([1.0, -1.0]) + + # Optional coordinate transformation + r0ex = apply_trans(t["trans"], r0ex.T) + + # The electrode location + cosmag = r0ex.copy() + _normalize_vectors(cosmag) + res = dict( + chname=ch["ch_name"], + coil_class=FWD.COILC_EEG, + w=w, + accuracy=_accuracy_dict["normal"], + type=ch["coil_type"], + coord_frame=t["to"], + rmag=r0ex, + cosmag=cosmag, + ) + return res + + +def _create_meg_coils(chs, acc, t=None, coilset=None, do_es=False): + """Create a set of MEG coils in the head coordinate frame.""" + acc = _accuracy_dict[acc] if isinstance(acc, str) else acc + coilset = _read_coil_defs(verbose=False) if coilset is None else coilset + coils = [_create_meg_coil(coilset, ch, acc, do_es) for ch in chs] + _transform_orig_meg_coils(coils, t, do_es=do_es) + return coils + + +def _transform_orig_meg_coils(coils, t, do_es=True): + """Transform original (device) MEG coil positions.""" + if t is None: + return + for coil in coils: + coil_trans = np.dot(t["trans"], coil["coil_trans_orig"]) + coil.update( + coord_frame=t["to"], + r0=coil_trans[:3, 3], + rmag=apply_trans(coil_trans, coil["rmag_orig"]), + cosmag=apply_trans(coil_trans, coil["cosmag_orig"], False), + ) + if do_es: + r0_exey = ( + np.dot(coil["rmag_orig"][:, :2], coil_trans[:3, :2].T) + + coil_trans[:3, 3] + ) + coil.update( + ex=coil_trans[:3, 0], + ey=coil_trans[:3, 1], + ez=coil_trans[:3, 2], + r0_exey=r0_exey, + ) + + +def _create_eeg_els(chs): + """Create a set of EEG electrodes in the head coordinate frame.""" + return [_create_eeg_el(ch) for ch in chs] + + +@verbose +def _setup_bem(bem, bem_extra, neeg, mri_head_t, allow_none=False, verbose=None): + """Set up a BEM for forward computation, making a copy and modifying.""" + if allow_none and bem is None: + return None + logger.info("") + _validate_type(bem, ("path-like", ConductorModel), bem) + if not isinstance(bem, ConductorModel): + logger.info(f"Setting up the BEM model using {bem_extra}...\n") + bem = read_bem_solution(bem) + else: + bem = bem.copy() + if bem["is_sphere"]: + logger.info("Using the sphere model.\n") + if len(bem["layers"]) == 0 and neeg > 0: + raise RuntimeError( + "Spherical model has zero shells, cannot use with EEG data" + ) + if bem["coord_frame"] != FIFF.FIFFV_COORD_HEAD: + raise RuntimeError("Spherical model is not in head coordinates") + else: + if bem["surfs"][0]["coord_frame"] != FIFF.FIFFV_COORD_MRI: + raise RuntimeError( + f"BEM is in {_coord_frame_name(bem['surfs'][0]['coord_frame'])} " + "coordinates, should be in MRI" + ) + if neeg > 0 and len(bem["surfs"]) == 1: + raise RuntimeError( + "Cannot use a homogeneous (1-layer BEM) model " + "for EEG forward calculations, consider " + "using a 3-layer BEM instead" + ) + logger.info("Employing the head->MRI coordinate transform with the BEM model.") + # fwd_bem_set_head_mri_t: Set the coordinate transformation + bem["head_mri_t"] = _ensure_trans(mri_head_t, "head", "mri") + logger.info(f"BEM model {op.split(bem_extra)[1]} is now set up") + logger.info("") + return bem + + +@verbose +def _prep_meg_channels( + info, + accuracy="accurate", + exclude=(), + *, + ignore_ref=False, + head_frame=True, + do_es=False, + verbose=None, +): + """Prepare MEG coil definitions for forward calculation.""" + # Find MEG channels + ref_meg = True if not ignore_ref else False + picks = pick_types(info, meg=True, ref_meg=ref_meg, exclude=exclude) + + # Make sure MEG coils exist + if len(picks) <= 0: + raise RuntimeError("Could not find any MEG channels") + info_meg = pick_info(info, picks) + del picks + + # Get channel info and names for MEG channels + logger.info(f"Read {len(info_meg['chs'])} MEG channels from info") + + # Get MEG compensation channels + compensator = post_picks = None + ch_names = info_meg["ch_names"] + if not ignore_ref: + ref_picks = pick_types(info, meg=False, ref_meg=True, exclude=exclude) + ncomp = len(ref_picks) + if ncomp > 0: + logger.info(f"Read {ncomp} MEG compensation channels from info") + # We need to check to make sure these are NOT KIT refs + if _has_kit_refs(info, ref_picks): + raise NotImplementedError( + "Cannot create forward solution with KIT reference " + 'channels. Consider using "ignore_ref=True" in ' + "calculation" + ) + logger.info(f"{len(info['comps'])} compensation data sets in info") + # Compose a compensation data set if necessary + # adapted from mne_make_ctf_comp() from mne_ctf_comp.c + logger.info("Setting up compensation data...") + comp_num = get_current_comp(info) + if comp_num is None or comp_num == 0: + logger.info(" No compensation set. Nothing more to do.") + else: + compensator = make_compensator( + info_meg, 0, comp_num, exclude_comp_chs=False + ) + logger.info(f" Desired compensation data ({comp_num}) found.") + logger.info(" All compensation channels found.") + logger.info(" Preselector created.") + logger.info(" Compensation data matrix created.") + logger.info(" Postselector created.") + post_picks = pick_types(info_meg, meg=True, ref_meg=False, exclude=exclude) + ch_names = [ch_names[pick] for pick in post_picks] + + # Create coil descriptions with transformation to head or device frame + templates = _read_coil_defs() + + if head_frame: + _print_coord_trans(info["dev_head_t"]) + transform = info["dev_head_t"] + else: + transform = None + + megcoils = _create_meg_coils( + info_meg["chs"], accuracy, transform, templates, do_es=do_es + ) + + # Check that coordinate frame is correct and log it + if head_frame: + assert megcoils[0]["coord_frame"] == FIFF.FIFFV_COORD_HEAD + logger.info("MEG coil definitions created in head coordinates.") + else: + assert megcoils[0]["coord_frame"] == FIFF.FIFFV_COORD_DEVICE + logger.info("MEG coil definitions created in device coordinate.") + + return dict( + defs=megcoils, + ch_names=ch_names, + compensator=compensator, + info=info_meg, + post_picks=post_picks, + ) + + +@verbose +def _prep_eeg_channels(info, exclude=(), verbose=None): + """Prepare EEG electrode definitions for forward calculation.""" + info_extra = "info" + + # Find EEG electrodes + picks = pick_types(info, meg=False, eeg=True, ref_meg=False, exclude=exclude) + + # Make sure EEG electrodes exist + neeg = len(picks) + if neeg <= 0: + raise RuntimeError("Could not find any EEG channels") + + # Get channel info and names for EEG channels + eegchs = pick_info(info, picks)["chs"] + eegnames = [info["ch_names"][p] for p in picks] + logger.info(f"Read {len(picks):3} EEG channels from {info_extra}") + + # Create EEG electrode descriptions + eegels = _create_eeg_els(eegchs) + logger.info("Head coordinate coil definitions created.") + + return dict(defs=eegels, ch_names=eegnames) + + +@verbose +def _prepare_for_forward( + src, + mri_head_t, + info, + bem, + mindist, + n_jobs, + *, + bem_extra="", + trans="", + info_extra="", + meg=True, + eeg=True, + ignore_ref=False, + allow_bem_none=False, + on_inside="raise", + verbose=None, +): + """Prepare for forward computation. + + The sensors dict contains keys for each sensor type, e.g. 'meg', 'eeg'. + The vale for each of these is a dict that comes from _prep_meg_channels or + _prep_eeg_channels. Each dict contains: + + - defs : a list of dicts (one per channel) with 'rmag', 'cosmag', etc. + - ch_names: a list of str channel names corresponding to the defs + - compensator (optional): the ndarray compensation matrix to apply + - post_picks (optional): the ndarray of indices to pick after applying the + compensator + """ + # Read the source locations + logger.info("") + # let's make a copy in case we modify something + src = _ensure_src(src).copy() + nsource = sum(s["nuse"] for s in src) + if len(src) and nsource == 0: + raise RuntimeError( + "No sources are active in these source spaces. " + '"do_all" option should be used.' + ) + logger.info( + "Read %d source spaces a total of %d active source locations", len(src), nsource + ) + # Delete some keys to clean up the source space: + for key in ["working_dir", "command_line"]: + if key in src.info: + del src.info[key] + + # Read the MRI -> head coordinate transformation + logger.info("") + _print_coord_trans(mri_head_t) + + # make a new dict with the relevant information + arg_list = [info_extra, trans, src, bem_extra, meg, eeg, mindist, n_jobs, verbose] + cmd = f"make_forward_solution({', '.join(str(a) for a in arg_list)})" + mri_id = dict(machid=np.zeros(2, np.int32), version=0, secs=0, usecs=0) + + info_trans = str(trans) if isinstance(trans, Path) else trans + kwargs_fwd_info = dict( + chs=info["chs"], + comps=info["comps"], + # The forward-writing code always wants a dev_head_t, so give an identity one + dev_head_t=info["dev_head_t"] or Transform("meg", "head"), + mri_file=info_trans, + mri_id=mri_id, + meas_file=info_extra, + meas_id=None, + working_dir=os.getcwd(), + command_line=cmd, + bads=info["bads"], + mri_head_t=mri_head_t, + ) + + if "kit_system_id" in info: + kwargs_fwd_info["kit_system_id"] = info["kit_system_id"] + + info = Info(**kwargs_fwd_info) + info._update_redundant() + info._check_consistency() + logger.info("") + + sensors = dict() + if meg and len(pick_types(info, meg=True, ref_meg=False, exclude=[])) > 0: + sensors["meg"] = _prep_meg_channels(info, ignore_ref=ignore_ref) + if eeg and len(pick_types(info, eeg=True, exclude=[])) > 0: + sensors["eeg"] = _prep_eeg_channels(info) + + # Check that some channels were found + if len(sensors) == 0: + raise RuntimeError("No MEG or EEG channels found.") + + # pick out final info + info = pick_info( + info, pick_types(info, meg=meg, eeg=eeg, ref_meg=False, exclude=[]) + ) + + # Transform the source spaces into the appropriate coordinates + # (will either be HEAD or MRI) + src._transform_to("head", mri_head_t) + if len(src): + logger.info( + f"Source spaces are now in {_coord_frame_name(src[0]['coord_frame'])} " + "coordinates." + ) + + # Prepare the BEM model + eegnames = sensors.get("eeg", dict()).get("ch_names", []) + bem = _setup_bem( + bem, bem_extra, len(eegnames), mri_head_t, allow_none=allow_bem_none + ) + del eegnames + + # Circumvent numerical problems by excluding points too close to the skull, + # and check that sensors are not inside any BEM surface + if bem is not None: + kwargs = dict(limit=mindist, mri_head_t=mri_head_t, src=src) + if not bem["is_sphere"]: + check_surface = "inner skull surface" + check_inside_brain = _CheckInside(_bem_find_surface(bem, "inner_skull")) + logger.info("") + if len(bem["surfs"]) == 3: + check_surface = "scalp surface" + check_inside_head = _CheckInside(_bem_find_surface(bem, "head")) + else: + check_inside_head = check_inside_brain + else: + check_surface = "outermost sphere shell" + check_inside_brain = _CheckInsideSphere(bem) + if bem.radius is not None: + check_inside_head = _CheckInsideSphere(bem, check="outer") + else: + + def check_inside_head(x): + return np.zeros(len(x), bool) + + if len(src): + _filter_source_spaces(check_inside_brain, **kwargs) + + if "meg" in sensors: + meg_loc = np.array([coil["r0"] for coil in sensors["meg"]["defs"]]) + if not bem["is_sphere"]: + meg_loc = apply_trans(invert_transform(mri_head_t), meg_loc) + n_inside = check_inside_head(meg_loc).sum() + if n_inside: + msg = ( + f"Found {n_inside} MEG sensor{_pl(n_inside)} inside the " + f"{check_surface}, perhaps coordinate frames and/or " + "coregistration are incorrect" + ) + _on_missing(on_inside, msg, name="on_inside", error_klass=RuntimeError) + + if len(src): + rr = np.concatenate([s["rr"][s["vertno"]] for s in src]) + if len(rr) < 1: + raise RuntimeError( + "No points left in source space after excluding " + "points close to inner skull." + ) + else: + rr = np.zeros((0, 3)) + + # deal with free orientations: + source_nn = np.tile(np.eye(3), (len(rr), 1)) + update_kwargs = dict( + nchan=len(info["ch_names"]), + nsource=len(rr), + info=info, + src=src, + source_nn=source_nn, + source_rr=rr, + surf_ori=False, + mri_head_t=mri_head_t, + ) + return sensors, rr, info, update_kwargs, bem + + +@verbose +def make_forward_solution( + info, + trans, + src, + bem, + meg=True, + eeg=True, + *, + mindist=0.0, + ignore_ref=False, + n_jobs=None, + on_inside="raise", + verbose=None, +): + """Calculate a forward solution for a subject. + + Parameters + ---------- + %(info_str)s + %(trans)s + + .. versionchanged:: 0.19 + Support for ``'fsaverage'`` argument. + src : path-like | instance of SourceSpaces + Either a path to a source space file or a loaded or generated + :class:`~mne.SourceSpaces`. + bem : path-like | ConductorModel + Filename of the BEM (e.g., ``"sample-5120-5120-5120-bem-sol.fif"``) to + use, or a loaded :class:`~mne.bem.ConductorModel`. See + :func:`~mne.make_bem_model` and :func:`~mne.make_bem_solution` to create a + :class:`mne.bem.ConductorModel`. + meg : bool + If True (default), include MEG computations. + eeg : bool + If True (default), include EEG computations. + mindist : float + Minimum distance of sources from inner skull surface (in mm). + ignore_ref : bool + If True, do not include reference channels in compensation. This + option should be True for KIT files, since forward computation + with reference channels is not currently supported. + %(n_jobs)s + on_inside : 'raise' | 'warn' | 'ignore' + What to do if MEG sensors are inside the outer skin surface. If 'raise' + (default), an error is raised. If 'warn' or 'ignore', the forward + solution is computed anyway and a warning is or isn't emitted, + respectively. + + .. versionadded:: 1.10 + %(verbose)s + + Returns + ------- + fwd : instance of Forward + The forward solution. + + See Also + -------- + convert_forward_solution + + Notes + ----- + The ``--grad`` option from MNE-C (to compute gradients) is not implemented + here. + + To create a fixed-orientation forward solution, use this function + followed by :func:`mne.convert_forward_solution`. + + .. note:: + If the BEM solution was computed with `OpenMEEG `__ + in :func:`mne.make_bem_solution`, then OpenMEEG will automatically + be used to compute the forward solution. + + .. versionchanged:: 1.2 + Added support for OpenMEEG-based forward solution calculations. + """ + # Currently not (sup)ported: + # 1. --grad option (gradients of the field, not used much) + # 2. --fixed option (can be computed post-hoc) + # 3. --mricoord option (probably not necessary) + + # read the transformation from MRI to HEAD coordinates + # (could also be HEAD to MRI) + mri_head_t, trans = _get_trans(trans) + if isinstance(bem, ConductorModel): + bem_extra = "instance of ConductorModel" + else: + bem_extra = bem + _validate_type(info, ("path-like", Info), "info") + if not isinstance(info, Info): + info_extra = op.split(info)[1] + info = _check_fname(info, must_exist=True, overwrite="read", name="info") + info = read_info(info, verbose=False) + else: + info_extra = "instance of Info" + + # Report the setup + logger.info(f"Source space : {src}") + logger.info(f"MRI -> head transform : {trans}") + logger.info(f"Measurement data : {info_extra}") + if isinstance(bem, ConductorModel) and bem["is_sphere"]: + logger.info(f"Sphere model : origin at {bem['r0']} mm") + logger.info("Standard field computations") + else: + logger.info(f"Conductor model : {bem_extra}") + logger.info("Accurate field computations") + logger.info( + "Do computations in %s coordinates", _coord_frame_name(FIFF.FIFFV_COORD_HEAD) + ) + logger.info("Free source orientations") + + # Create MEG coils and EEG electrodes in the head coordinate frame + sensors, rr, info, update_kwargs, bem = _prepare_for_forward( + src, + mri_head_t, + info, + bem, + mindist, + n_jobs, + bem_extra=bem_extra, + trans=trans, + info_extra=info_extra, + meg=meg, + eeg=eeg, + ignore_ref=ignore_ref, + on_inside=on_inside, + ) + del (src, mri_head_t, trans, info_extra, bem_extra, mindist, meg, eeg, ignore_ref) + + # Time to do the heavy lifting: MEG first, then EEG + fwds = _compute_forwards(rr, bem=bem, sensors=sensors, n_jobs=n_jobs) + + # merge forwards + fwds = { + key: _to_forward_dict(fwds[key], sensors[key]["ch_names"]) + for key in _FWD_ORDER + if key in fwds + } + fwd = _merge_fwds(fwds, verbose=False) + del fwds + logger.info("") + + # Don't transform the source spaces back into MRI coordinates (which is + # done in the C code) because mne-python assumes forward solution source + # spaces are in head coords. + fwd.update(**update_kwargs) + logger.info("Finished.") + return fwd + + +@verbose +def make_forward_dipole( + dipole, bem, info, trans=None, n_jobs=None, *, on_inside="raise", verbose=None +): + """Convert dipole object to source estimate and calculate forward operator. + + The instance of Dipole is converted to a discrete source space, + which is then combined with a BEM or a sphere model and + the sensor information in info to form a forward operator. + + The source estimate object (with the forward operator) can be projected to + sensor-space using :func:`mne.simulation.simulate_evoked`. + + .. note:: If the (unique) time points of the dipole object are unevenly + spaced, the first output will be a list of single-timepoint + source estimates. + + Parameters + ---------- + %(dipole)s + bem : str | dict + The BEM filename (str) or a loaded sphere model (dict). + info : instance of Info + The measurement information dictionary. It is sensor-information etc., + e.g., from a real data file. + trans : str | None + The head<->MRI transform filename. Must be provided unless BEM + is a sphere model. + %(n_jobs)s + on_inside : 'raise' | 'warn' | 'ignore' + What to do if MEG sensors are inside the outer skin surface. If 'raise' + (default), an error is raised. If 'warn' or 'ignore', the forward + solution is computed anyway and a warning is or isn't emitted, + respectively. + + .. versionadded:: 1.10 + %(verbose)s + + Returns + ------- + fwd : instance of Forward + The forward solution corresponding to the source estimate(s). + stc : instance of VolSourceEstimate | list of VolSourceEstimate + The dipoles converted to a discrete set of points and associated + time courses. If the time points of the dipole are unevenly spaced, + a list of single-timepoint source estimates are returned. + + See Also + -------- + mne.simulation.simulate_evoked + + Notes + ----- + .. versionadded:: 0.12.0 + """ + if isinstance(dipole, list): + from ..dipole import _concatenate_dipoles # To avoid circular import + + dipole = _concatenate_dipoles(dipole) + + # Make copies to avoid mangling original dipole + times = dipole.times.copy() + pos = dipole.pos.copy() + amplitude = dipole.amplitude.copy() + ori = dipole.ori.copy() + + # Convert positions to discrete source space (allows duplicate rr & nn) + # NB information about dipole orientation enters here, then no more + sources = dict(rr=pos, nn=ori) + # Dipole objects must be in the head frame + src = _complete_vol_src([_make_discrete_source_space(sources, coord_frame="head")]) + + # Forward operator created for channels in info (use pick_info to restrict) + # Use defaults for most params, including min_dist + fwd = make_forward_solution( + info, trans, src, bem, n_jobs=n_jobs, on_inside=on_inside, verbose=verbose + ) + # Convert from free orientations to fixed (in-place) + convert_forward_solution( + fwd, surf_ori=False, force_fixed=True, copy=False, use_cps=False, verbose=None + ) + + # Check for omissions due to proximity to inner skull in + # make_forward_solution, which will result in an exception + if fwd["src"][0]["nuse"] != len(pos): + inuse = fwd["src"][0]["inuse"].astype(bool) + head = "The following dipoles are outside the inner skull boundary" + msg = len(head) * "#" + "\n" + head + "\n" + for t, pos in zip(times[np.logical_not(inuse)], pos[np.logical_not(inuse)]): + msg += ( + f" t={t * 1000.0:.0f} ms, pos=({pos[0] * 1000.0:.0f}, " + f"{pos[1] * 1000.0:.0f}, {pos[2] * 1000.0:.0f}) mm\n" + ) + msg += len(head) * "#" + logger.error(msg) + raise ValueError("One or more dipoles outside the inner skull.") + + # multiple dipoles (rr and nn) per time instant allowed + # uneven sampling in time returns list + timepoints = np.unique(times) + if len(timepoints) > 1: + tdiff = np.diff(timepoints) + if not np.allclose(tdiff, tdiff[0]): + warn( + "Unique time points of dipoles unevenly spaced: returned " + "stc will be a list, one for each time point." + ) + tstep = -1.0 + else: + tstep = tdiff[0] + elif len(timepoints) == 1: + tstep = 0.001 + + # Build the data matrix, essentially a block-diagonal with + # n_rows: number of dipoles in total (dipole.amplitudes) + # n_cols: number of unique time points in dipole.times + # amplitude with identical value of times go together in one col (others=0) + data = np.zeros((len(amplitude), len(timepoints))) # (n_d, n_t) + row = 0 + for tpind, tp in enumerate(timepoints): + amp = amplitude[np.isin(times, tp)] + data[row : row + len(amp), tpind] = amp + row += len(amp) + + if tstep > 0: + stc = VolSourceEstimate( + data, + vertices=[fwd["src"][0]["vertno"]], + tmin=timepoints[0], + tstep=tstep, + subject=None, + ) + else: # Must return a list of stc, one for each time point + stc = [] + for col, tp in enumerate(timepoints): + stc += [ + VolSourceEstimate( + data[:, col][:, np.newaxis], + vertices=[fwd["src"][0]["vertno"]], + tmin=tp, + tstep=0.001, + subject=None, + ) + ] + return fwd, stc + + +def _to_forward_dict( + fwd, + names, + fwd_grad=None, + coord_frame=FIFF.FIFFV_COORD_HEAD, + source_ori=FIFF.FIFFV_MNE_FREE_ORI, +): + """Convert forward solution matrices to dicts.""" + assert names is not None + sol = dict( + data=fwd.T, nrow=fwd.shape[1], ncol=fwd.shape[0], row_names=names, col_names=[] + ) + fwd = Forward( + sol=sol, + source_ori=source_ori, + nsource=sol["ncol"], + coord_frame=coord_frame, + sol_grad=None, + nchan=sol["nrow"], + _orig_source_ori=source_ori, + _orig_sol=sol["data"].copy(), + _orig_sol_grad=None, + ) + if fwd_grad is not None: + sol_grad = dict( + data=fwd_grad.T, + nrow=fwd_grad.shape[1], + ncol=fwd_grad.shape[0], + row_names=names, + col_names=[], + ) + fwd.update(dict(sol_grad=sol_grad), _orig_sol_grad=sol_grad["data"].copy()) + return fwd + + +@contextmanager +def use_coil_def(fname): + """Use a custom coil definition file. + + Parameters + ---------- + fname : path-like + The filename of the coil definition file. + + Returns + ------- + context : contextmanager + The context for using the coil definition. + + Notes + ----- + This is meant to be used a context manager such as: + + >>> with use_coil_def(my_fname): # doctest:+SKIP + ... make_forward_solution(...) + + This allows using custom coil definitions with functions that require + forward modeling. + """ + global _extra_coil_def_fname + _extra_coil_def_fname = fname + try: + yield + finally: + _extra_coil_def_fname = None + + +class _ForwardModeler: + """Optimized incremental fitting using the same sensors and BEM.""" + + @verbose + def __init__( + self, + info, + trans, + bem, + *, + mindist=0.0, + n_jobs=1, + verbose=None, + ): + self.mri_head_t, _ = _get_trans(trans) + self.mindist = mindist + self.n_jobs = n_jobs + src = SourceSpaces([]) + self.sensors, _, _, self.update_kwargs, self.bem = _prepare_for_forward( + src, + self.mri_head_t, + info, + bem, + mindist, + n_jobs, + bem_extra="", + trans="", + info_extra="", + meg=True, + eeg=True, + ignore_ref=False, + ) + self.fwd_data = _prep_field_computation( + sensors=self.sensors, + bem=self.bem, + n_jobs=self.n_jobs, + ) + if self.bem["is_sphere"]: + self.check_inside = _CheckInsideSphere(self.bem) + else: + self.check_inside = _CheckInside(_bem_find_surface(self.bem, "inner_skull")) + + def compute(self, src): + src = _ensure_src(src).copy() + src._transform_to("head", self.mri_head_t) + _filter_source_spaces( + self.check_inside, + n_jobs=self.n_jobs, + limit=self.mindist, + mri_head_t=self.mri_head_t, + src=src, + ) + rr = np.concatenate([s["rr"][s["vertno"]] for s in src]) + if len(rr) < 1: + raise RuntimeError( + "No points left in source space after excluding " + "points close to inner skull." + ) + + sensors = deepcopy(self.sensors) + fwd_data = deepcopy(self.fwd_data) + fwds = _compute_forwards_meeg( + rr, + sensors=sensors, + fwd_data=fwd_data, + n_jobs=self.n_jobs, + ) + fwds = { + key: _to_forward_dict(fwds[key], sensors[key]["ch_names"]) + for key in _FWD_ORDER + if key in fwds + } + fwd = _merge_fwds(fwds, verbose=False) + del fwds + + fwd.update(**self.update_kwargs) + # Delete some keys to clean up the source space: + for key in ["working_dir", "command_line"]: + if key in src.info: + del src.info[key] + # our `update_kwargs` set these, but they need to be updated for this src + fwd["src"] = src + fwd["nsource"] = sum(s["nuse"] for s in src) + fwd["source_rr"] = np.vstack([s["rr"][s["inuse"] == 1] for s in src]) + fwd["source_nn"] = np.tile(np.eye(3), (fwd["nsource"], 1)) + return fwd diff --git a/mne-python/source/mne/forward/forward.py b/mne-python/source/mne/forward/forward.py new file mode 100644 index 0000000000000000000000000000000000000000..83aa4b3a9b806b88be574c6f31f467e9a3e968c3 --- /dev/null +++ b/mne-python/source/mne/forward/forward.py @@ -0,0 +1,2183 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# The computations in this code were primarily derived from Matti Hämäläinen's +# C code. + +import os +import re +import shutil +import tempfile +from copy import deepcopy +from os import PathLike +from os import path as op +from pathlib import Path +from time import time + +import numpy as np +from scipy import sparse + +from .._fiff.constants import FIFF +from .._fiff.matrix import ( + _read_named_matrix, + _transpose_named_matrix, + write_named_matrix, +) +from .._fiff.meas_info import ( + Info, + _make_ch_names_mapping, + _read_bad_channels, + _read_extended_ch_info, + _write_bad_channels, + _write_ch_infos, + write_info, +) +from .._fiff.open import fiff_open +from .._fiff.pick import pick_channels, pick_channels_forward, pick_info, pick_types +from .._fiff.tag import find_tag, read_tag +from .._fiff.tree import dir_tree_find +from .._fiff.write import ( + end_block, + start_and_end_file, + start_block, + write_coord_trans, + write_id, + write_int, + write_string, +) +from ..epochs import BaseEpochs +from ..evoked import Evoked, EvokedArray +from ..fixes import _reshape_view +from ..html_templates import _get_html_template +from ..io import BaseRaw, RawArray +from ..label import Label +from ..source_estimate import _BaseSourceEstimate, _BaseVectorSourceEstimate +from ..source_space._source_space import ( + SourceSpaces, + _get_src_nn, + _read_source_spaces_from_tree, + _set_source_space_vertices, + _src_kind_dict, + _write_source_spaces_to_fid, + find_source_space_hemi, +) +from ..surface import _normal_orth +from ..transforms import invert_transform, write_trans +from ..utils import ( + _check_compensation_grade, + _check_fname, + _check_option, + _check_stc_units, + _import_h5io_funcs, + _on_missing, + _stamp_to_dt, + _validate_type, + check_fname, + fill_doc, + get_subjects_dir, + has_mne_c, + logger, + repr_html, + run_subprocess, + verbose, + warn, +) + + +class Forward(dict): + """Forward class to represent info from forward solution. + + Like :class:`mne.Info`, this data structure behaves like a dictionary. + It contains all metadata necessary for a forward solution. + + .. warning:: + This class should not be modified or created by users. + Forward objects should be obtained using + :func:`mne.make_forward_solution` or :func:`mne.read_forward_solution`. + + Attributes + ---------- + ch_names : list of str + A convenience wrapper accessible as ``fwd.ch_names`` which wraps + ``fwd['info']['ch_names']``. + + See Also + -------- + mne.make_forward_solution + mne.read_forward_solution + + Notes + ----- + Forward data is accessible via string keys using standard + :class:`python:dict` access (e.g., ``fwd['nsource'] == 4096``): + + source_ori : int + The source orientation, either ``FIFF.FIFFV_MNE_FIXED_ORI`` or + ``FIFF.FIFFV_MNE_FREE_ORI``. + coord_frame : int + The coordinate frame of the forward solution, usually + ``FIFF.FIFFV_COORD_HEAD``. + nsource : int + The number of source locations. + nchan : int + The number of channels. + sol : dict + The forward solution, with entries: + + ``'data'`` : ndarray, shape (n_channels, nsource * n_ori) + The forward solution data. The shape will be + ``(n_channels, nsource)`` for a fixed-orientation forward and + ``(n_channels, nsource * 3)`` for a free-orientation forward. + ``'row_names'`` : list of str + The channel names. + mri_head_t : instance of Transform + The mri ↔ head transformation that was used. + info : instance of :class:`~mne.Info` + The measurement information (with contents reduced compared to that + of the original data). + src : instance of :class:`~mne.SourceSpaces` + The source space used during forward computation. This can differ + from the original source space as: + + 1. Source points are removed due to proximity to (or existing + outside) + the inner skull surface. + 2. The source space will be converted to the ``coord_frame`` of the + forward solution, which typically means it gets converted from + MRI to head coordinates. + source_rr : ndarray, shape (n_sources, 3) + The source locations. + source_nn : ndarray, shape (n_sources, 3) + The source normals. Will be all +Z (``(0, 0, 1.)``) for volume + source spaces. For surface source spaces, these are normal to the + cortical surface. + surf_ori : int + Whether ``sol`` is surface-oriented with the surface normal in the + Z component (``FIFF.FIFFV_MNE_FIXED_ORI``) or +Z in the given + ``coord_frame`` in the Z component (``FIFF.FIFFV_MNE_FREE_ORI``). + + Forward objects also have some attributes that are accessible via ``.`` + access, like ``fwd.ch_names``. + """ + + def copy(self): + """Copy the Forward instance.""" + return Forward(deepcopy(self)) + + @verbose + def save(self, fname, *, overwrite=False, verbose=None): + """Save the forward solution. + + Parameters + ---------- + %(fname_fwd)s + %(overwrite)s + %(verbose)s + """ + write_forward_solution(fname, self, overwrite=overwrite) + + def _get_src_type_and_ori_for_repr(self): + src_types = np.array([src["type"] for src in self["src"]]) + + if (src_types == "surf").all(): + src_type = f"Surface with {self['nsource']} vertices" + elif (src_types == "vol").all(): + src_type = f"Volume with {self['nsource']} grid points" + elif (src_types == "discrete").all(): + src_type = f"Discrete with {self['nsource']} dipoles" + else: + count_string = "" + if (src_types == "surf").any(): + count_string += f"{(src_types == 'surf').sum()} surface, " + if (src_types == "vol").any(): + count_string += f"{(src_types == 'vol').sum()} volume, " + if (src_types == "discrete").any(): + count_string += f"{(src_types == 'discrete').sum()} discrete, " + count_string = count_string.rstrip(", ") + src_type = f"Mixed ({count_string}) with {self['nsource']} vertices" + + if self["source_ori"] == FIFF.FIFFV_MNE_UNKNOWN_ORI: + src_ori = "Unknown" + elif self["source_ori"] == FIFF.FIFFV_MNE_FIXED_ORI: + src_ori = "Fixed" + elif self["source_ori"] == FIFF.FIFFV_MNE_FREE_ORI: + src_ori = "Free" + + return src_type, src_ori + + def __repr__(self): + """Summarize forward info instead of printing all.""" + entr = " 0: + raise ValueError("Width of matrix must be a multiple of n") + + tmp = np.arange(ma * bdn, dtype=np.int64).reshape(bdn, ma) + tmp = np.tile(tmp, (1, n)) + ii = tmp.ravel() + + jj = np.arange(na, dtype=np.int64)[None, :] + jj = jj * np.ones(ma, dtype=np.int64)[:, None] + jj = jj.T.ravel() # column indices foreach sparse bd + + bd = sparse.coo_array((A.T.ravel(), np.c_[ii, jj].T)).tocsc() + + return bd + + +def _get_tag_int(fid, node, name, id_): + """Check we have an appropriate tag.""" + tag = find_tag(fid, node, id_) + if tag is None: + raise ValueError(name + " tag not found") + return int(tag.data.item()) + + +def _read_one(fid, node): + """Read all interesting stuff for one forward solution.""" + # This function assumes the fid is open as a context manager + if node is None: + return None + + one = Forward() + one["source_ori"] = _get_tag_int( + fid, node, "Source orientation", FIFF.FIFF_MNE_SOURCE_ORIENTATION + ) + one["coord_frame"] = _get_tag_int( + fid, node, "Coordinate frame", FIFF.FIFF_MNE_COORD_FRAME + ) + one["nsource"] = _get_tag_int( + fid, node, "Number of sources", FIFF.FIFF_MNE_SOURCE_SPACE_NPOINTS + ) + one["nchan"] = _get_tag_int(fid, node, "Number of channels", FIFF.FIFF_NCHAN) + try: + one["sol"] = _read_named_matrix( + fid, node, FIFF.FIFF_MNE_FORWARD_SOLUTION, transpose=True + ) + one["_orig_sol"] = one["sol"]["data"].copy() + except Exception: + logger.error("Forward solution data not found") + raise + + try: + fwd_type = FIFF.FIFF_MNE_FORWARD_SOLUTION_GRAD + one["sol_grad"] = _read_named_matrix(fid, node, fwd_type, transpose=True) + one["_orig_sol_grad"] = one["sol_grad"]["data"].copy() + except Exception: + one["sol_grad"] = None + + if one["sol"]["data"].shape[0] != one["nchan"] or ( + one["sol"]["data"].shape[1] != one["nsource"] + and one["sol"]["data"].shape[1] != 3 * one["nsource"] + ): + raise ValueError("Forward solution matrix has wrong dimensions") + + if one["sol_grad"] is not None: + if one["sol_grad"]["data"].shape[0] != one["nchan"] or ( + one["sol_grad"]["data"].shape[1] != 3 * one["nsource"] + and one["sol_grad"]["data"].shape[1] != 3 * 3 * one["nsource"] + ): + raise ValueError("Forward solution gradient matrix has wrong dimensions") + + return one + + +@fill_doc +def _read_forward_meas_info(tree, fid): + """Read light measurement info from forward operator. + + Parameters + ---------- + tree : tree + FIF tree structure. + fid : file id + The file id. + + Returns + ------- + %(info_not_none)s + """ + # This function assumes fid is being used as a context manager + info = Info() + info._unlocked = True + + # Information from the MRI file + parent_mri = dir_tree_find(tree, FIFF.FIFFB_MNE_PARENT_MRI_FILE) + if len(parent_mri) == 0: + raise ValueError("No parent MEG information found in operator") + parent_mri = parent_mri[0] + + tag = find_tag(fid, parent_mri, FIFF.FIFF_MNE_FILE_NAME) + info["mri_file"] = tag.data if tag is not None else None + tag = find_tag(fid, parent_mri, FIFF.FIFF_PARENT_FILE_ID) + info["mri_id"] = tag.data if tag is not None else None + + # Information from the MEG file + parent_meg = dir_tree_find(tree, FIFF.FIFFB_MNE_PARENT_MEAS_FILE) + if len(parent_meg) == 0: + raise ValueError("No parent MEG information found in operator") + parent_meg = parent_meg[0] + + tag = find_tag(fid, parent_meg, FIFF.FIFF_MNE_FILE_NAME) + info["meas_file"] = tag.data if tag is not None else None + tag = find_tag(fid, parent_meg, FIFF.FIFF_PARENT_FILE_ID) + info["meas_id"] = tag.data if tag is not None else None + + # Add channel information + info["chs"] = chs = list() + for k in range(parent_meg["nent"]): + kind = parent_meg["directory"][k].kind + pos = parent_meg["directory"][k].pos + if kind == FIFF.FIFF_CH_INFO: + tag = read_tag(fid, pos) + chs.append(tag.data) + ch_names_mapping = _read_extended_ch_info(chs, parent_meg, fid) + info._update_redundant() + + # Get the MRI <-> head coordinate transformation + tag = find_tag(fid, parent_mri, FIFF.FIFF_COORD_TRANS) + coord_head = FIFF.FIFFV_COORD_HEAD + coord_mri = FIFF.FIFFV_COORD_MRI + coord_device = FIFF.FIFFV_COORD_DEVICE + coord_ctf_head = FIFF.FIFFV_MNE_COORD_CTF_HEAD + if tag is None: + raise ValueError("MRI/head coordinate transformation not found") + cand = tag.data + if cand["from"] == coord_mri and cand["to"] == coord_head: + info["mri_head_t"] = cand + else: + raise ValueError("MRI/head coordinate transformation not found") + + # Get the MEG device <-> head coordinate transformation + tag = find_tag(fid, parent_meg, FIFF.FIFF_COORD_TRANS) + if tag is None: + raise ValueError("MEG/head coordinate transformation not found") + cand = tag.data + if cand["from"] == coord_device and cand["to"] == coord_head: + info["dev_head_t"] = cand + elif cand["from"] == coord_ctf_head and cand["to"] == coord_head: + info["ctf_head_t"] = cand + else: + raise ValueError("MEG/head coordinate transformation not found") + + bads = _read_bad_channels(fid, parent_meg, ch_names_mapping=ch_names_mapping) + # clean up our bad list, old versions could have non-existent bads + info["bads"] = [bad for bad in bads if bad in info["ch_names"]] + + # Check if a custom reference has been applied + tag = find_tag(fid, parent_mri, FIFF.FIFF_MNE_CUSTOM_REF) + if tag is None: + tag = find_tag(fid, parent_mri, 236) # Constant 236 used before v0.11 + + info["custom_ref_applied"] = int(tag.data.item()) if tag is not None else False + info._unlocked = False + return info + + +def _subject_from_forward(forward): + """Get subject id from inverse operator.""" + return forward["src"]._subject + + +# This sets the forward solution order (and gives human-readable names) +_FWD_ORDER = dict( + meg="MEG", + eeg="EEG", +) + + +@verbose +def _merge_fwds(fwds, *, verbose=None): + """Merge loaded forward dicts into one dict.""" + fwd = None + first_key = None + combined = list() + for key in _FWD_ORDER: + if key not in fwds: + continue + if fwd is None: # assign + fwd = fwds[key] + first_key = key + combined.append(_FWD_ORDER[key]) + continue + a = fwd + b = fwds[key] + a_kind, b_kind = _FWD_ORDER[first_key], _FWD_ORDER[key] + combined.append(b_kind) + if ( + a["sol"]["data"].shape[1] != b["sol"]["data"].shape[1] + or a["source_ori"] != b["source_ori"] + or a["nsource"] != b["nsource"] + or a["coord_frame"] != b["coord_frame"] + ): + raise ValueError( + f"The {a_kind} and {b_kind} forward solutions do not match" + ) + for k in ("sol", "sol_grad"): + if a[k] is None: + continue + a[k]["data"] = np.r_[a[k]["data"], b[k]["data"]] + a[f"_orig_{k}"] = np.r_[a[f"_orig_{k}"], b[f"_orig_{k}"]] + a[k]["nrow"] = a[k]["nrow"] + b[k]["nrow"] + a[k]["row_names"] = a[k]["row_names"] + b[k]["row_names"] + a["nchan"] = a["nchan"] + b["nchan"] + if len(fwds) > 1: + logger.info(f" Forward solutions combined: {', '.join(combined)}") + return fwd + + +@verbose +def read_forward_solution(fname, include=(), exclude=(), *, ordered=True, verbose=None): + """Read a forward solution a.k.a. lead field. + + Parameters + ---------- + fname : path-like + The file name, which should end with ``-fwd.fif``, ``-fwd.fif.gz``, + ``_fwd.fif``, ``_fwd.fif.gz``, ``-fwd.h5``, or ``_fwd.h5``. + include : list, optional + List of names of channels to include. If empty all channels + are included. + exclude : list, optional + List of names of channels to exclude. If empty include all channels. + %(ordered)s + %(verbose)s + + Returns + ------- + fwd : instance of Forward + The forward solution. + + See Also + -------- + write_forward_solution, make_forward_solution + + Notes + ----- + Forward solutions, which are derived from an original forward solution with + free orientation, are always stored on disk as forward solution with free + orientation in X/Y/Z RAS coordinates. To apply any transformation to the + forward operator (surface orientation, fixed orientation) please apply + :func:`convert_forward_solution` after reading the forward solution with + :func:`read_forward_solution`. + + Forward solutions, which are derived from an original forward solution with + fixed orientation, are stored on disk as forward solution with fixed + surface-based orientations. Please note that the transformation to + surface-based, fixed orientation cannot be reverted after loading the + forward solution with :func:`read_forward_solution`. + """ + check_fname( + fname, + "forward", + ("-fwd.fif", "-fwd.fif.gz", "_fwd.fif", "_fwd.fif.gz", "-fwd.h5", "_fwd.h5"), + ) + fname = _check_fname(fname=fname, must_exist=True, overwrite="read") + # Open the file, create directory + logger.info(f"Reading forward solution from {fname}...") + if fname.suffix == ".h5": + return _read_forward_hdf5(fname) + f, tree, _ = fiff_open(fname) + with f as fid: + # Find all forward solutions + fwds = dir_tree_find(tree, FIFF.FIFFB_MNE_FORWARD_SOLUTION) + if len(fwds) == 0: + raise ValueError(f"No forward solutions in {fname}") + + # Parent MRI data + parent_mri = dir_tree_find(tree, FIFF.FIFFB_MNE_PARENT_MRI_FILE) + if len(parent_mri) == 0: + raise ValueError(f"No parent MRI information in {fname}") + parent_mri = parent_mri[0] + + src = _read_source_spaces_from_tree(fid, tree, patch_stats=False) + for s in src: + s["id"] = find_source_space_hemi(s) + + fwd = None + + # Locate and read the forward solutions + megnode = None + eegnode = None + for k in range(len(fwds)): + tag = find_tag(fid, fwds[k], FIFF.FIFF_MNE_INCLUDED_METHODS) + if tag is None: + raise ValueError("Methods not listed for one of the forward solutions") + + if tag.data == FIFF.FIFFV_MNE_MEG: + megnode = fwds[k] + elif tag.data == FIFF.FIFFV_MNE_EEG: + eegnode = fwds[k] + + fwds = dict() + megfwd = _read_one(fid, megnode) + if megfwd is not None: + fwds["meg"] = megfwd + if is_fixed_orient(megfwd): + ori = "fixed" + else: + ori = "free" + logger.info( + " Read MEG forward solution (%d sources, " + "%d channels, %s orientations)", + megfwd["nsource"], + megfwd["nchan"], + ori, + ) + del megfwd + + eegfwd = _read_one(fid, eegnode) + if eegfwd is not None: + fwds["eeg"] = eegfwd + if is_fixed_orient(eegfwd): + ori = "fixed" + else: + ori = "free" + logger.info( + " Read EEG forward solution (%d sources, " + "%d channels, %s orientations)", + eegfwd["nsource"], + eegfwd["nchan"], + ori, + ) + del eegfwd + + fwd = _merge_fwds(fwds) + del fwds + + # Get the MRI <-> head coordinate transformation + tag = find_tag(fid, parent_mri, FIFF.FIFF_COORD_TRANS) + if tag is None: + raise ValueError("MRI/head coordinate transformation not found") + mri_head_t = tag.data + if ( + mri_head_t["from"] != FIFF.FIFFV_COORD_MRI + or mri_head_t["to"] != FIFF.FIFFV_COORD_HEAD + ): + mri_head_t = invert_transform(mri_head_t) + if ( + mri_head_t["from"] != FIFF.FIFFV_COORD_MRI + or mri_head_t["to"] != FIFF.FIFFV_COORD_HEAD + ): + raise ValueError("MRI/head coordinate transformation not found") + fwd["mri_head_t"] = mri_head_t + + # + # get parent MEG info + # + fwd["info"] = _read_forward_meas_info(tree, fid) + + # MNE environment + parent_env = dir_tree_find(tree, FIFF.FIFFB_MNE_ENV) + if len(parent_env) > 0: + parent_env = parent_env[0] + tag = find_tag(fid, parent_env, FIFF.FIFF_MNE_ENV_WORKING_DIR) + if tag is not None: + with fwd["info"]._unlock(): + fwd["info"]["working_dir"] = tag.data + tag = find_tag(fid, parent_env, FIFF.FIFF_MNE_ENV_COMMAND_LINE) + if tag is not None: + with fwd["info"]._unlock(): + fwd["info"]["command_line"] = tag.data + + # Transform the source spaces to the correct coordinate frame + # if necessary + + # Make sure forward solution is in either the MRI or HEAD coordinate frame + if fwd["coord_frame"] not in (FIFF.FIFFV_COORD_MRI, FIFF.FIFFV_COORD_HEAD): + raise ValueError( + "Only forward solutions computed in MRI or head coordinates are acceptable" + ) + + # Transform each source space to the HEAD or MRI coordinate frame, + # depending on the coordinate frame of the forward solution + src._transform_to(fwd["coord_frame"], mri_head_t) + nuse = sum(s["nuse"] for s in src) + + # Make sure the number of sources match after transformation + if nuse != fwd["nsource"]: + raise ValueError("Source spaces do not match the forward solution.") + + logger.info( + " Source spaces transformed to the forward solution coordinate frame" + ) + fwd["src"] = src + + # Handle the source locations and orientations + fwd["source_rr"] = np.concatenate([ss["rr"][ss["vertno"], :] for ss in src], axis=0) + + # Store original source orientations + fwd["_orig_source_ori"] = fwd["source_ori"] + + # Deal with include and exclude + pick_channels_forward(fwd, include=include, exclude=exclude, copy=False) + + if is_fixed_orient(fwd, orig=True): + fwd["source_nn"] = np.concatenate( + [_src["nn"][_src["vertno"], :] for _src in fwd["src"]], axis=0 + ) + fwd["source_ori"] = FIFF.FIFFV_MNE_FIXED_ORI + fwd["surf_ori"] = True + else: + fwd["source_nn"] = np.kron(np.ones((fwd["nsource"], 1)), np.eye(3)) + fwd["source_ori"] = FIFF.FIFFV_MNE_FREE_ORI + fwd["surf_ori"] = False + return Forward(fwd) + + +@verbose +def convert_forward_solution( + fwd, surf_ori=False, force_fixed=False, copy=True, use_cps=True, *, verbose=None +): + """Convert forward solution between different source orientations. + + Parameters + ---------- + fwd : Forward + The forward solution to modify. + surf_ori : bool, optional (default False) + Use surface-based source coordinate system? Note that force_fixed=True + implies surf_ori=True. + force_fixed : bool, optional (default False) + If True, force fixed source orientation mode. + copy : bool + Whether to return a new instance or modify in place. + %(use_cps)s + %(verbose)s + + Returns + ------- + fwd : Forward + The modified forward solution. + """ + fwd = fwd.copy() if copy else fwd + + if force_fixed is True: + surf_ori = True + + if any([src["type"] == "vol" for src in fwd["src"]]) and force_fixed: + raise ValueError( + "Forward operator was generated with sources from a " + "volume source space. Conversion to fixed orientation is not " + "possible. Consider using a discrete source space if you have " + "meaningful normal orientations." + ) + + if surf_ori and use_cps: + if any(s.get("patch_inds") is not None for s in fwd["src"]): + logger.info( + " Average patch normals will be employed in " + "the rotation to the local surface coordinates.." + ".." + ) + else: + use_cps = False + logger.info( + " No patch info available. The standard source " + "space normals will be employed in the rotation " + "to the local surface coordinates...." + ) + + # We need to change these entries (only): + # 1. source_nn + # 2. sol['data'] + # 3. sol['ncol'] + # 4. sol_grad['data'] + # 5. sol_grad['ncol'] + # 6. source_ori + + if is_fixed_orient(fwd, orig=True) or (force_fixed and not use_cps): + # Fixed + fwd["source_nn"] = np.concatenate( + [_get_src_nn(s, use_cps) for s in fwd["src"]], axis=0 + ) + if not is_fixed_orient(fwd, orig=True): + logger.info( + " Changing to fixed-orientation forward " + "solution with surface-based source orientations..." + ) + fix_rot = _block_diag(fwd["source_nn"].T, 1) + # newer versions of numpy require explicit casting here, so *= no + # longer works + fwd["sol"]["data"] = (fwd["_orig_sol"] @ fix_rot).astype("float32") + fwd["sol"]["ncol"] = fwd["nsource"] + if fwd["sol_grad"] is not None: + x = sparse.block_diag([fix_rot] * 3) + fwd["sol_grad"]["data"] = fwd["_orig_sol_grad"] @ x + fwd["sol_grad"]["ncol"] = 3 * fwd["nsource"] + fwd["source_ori"] = FIFF.FIFFV_MNE_FIXED_ORI + fwd["surf_ori"] = True + + elif surf_ori: # Free, surf-oriented + # Rotate the local source coordinate systems + fwd["source_nn"] = np.kron(np.ones((fwd["nsource"], 1)), np.eye(3)) + logger.info(" Converting to surface-based source orientations...") + # Actually determine the source orientations + pp = 0 + for s in fwd["src"]: + if s["type"] in ["surf", "discrete"]: + nn = _get_src_nn(s, use_cps) + stop = pp + 3 * s["nuse"] + fwd["source_nn"][pp:stop] = _normal_orth(nn).reshape(-1, 3) + pp = stop + del nn + else: + pp += 3 * s["nuse"] + + # Rotate the solution components as well + if force_fixed: + fwd["source_nn"] = fwd["source_nn"][2::3, :] + fix_rot = _block_diag(fwd["source_nn"].T, 1) + # newer versions of numpy require explicit casting here, so *= no + # longer works + fwd["sol"]["data"] = (fwd["_orig_sol"] @ fix_rot).astype("float32") + fwd["sol"]["ncol"] = fwd["nsource"] + if fwd["sol_grad"] is not None: + x = sparse.block_diag([fix_rot] * 3) + fwd["sol_grad"]["data"] = fwd["_orig_sol_grad"] @ x + fwd["sol_grad"]["ncol"] = 3 * fwd["nsource"] + fwd["source_ori"] = FIFF.FIFFV_MNE_FIXED_ORI + fwd["surf_ori"] = True + else: + surf_rot = _block_diag(fwd["source_nn"].T, 3) + fwd["sol"]["data"] = fwd["_orig_sol"] @ surf_rot + fwd["sol"]["ncol"] = 3 * fwd["nsource"] + if fwd["sol_grad"] is not None: + x = sparse.block_diag([surf_rot] * 3) + fwd["sol_grad"]["data"] = fwd["_orig_sol_grad"] @ x + fwd["sol_grad"]["ncol"] = 9 * fwd["nsource"] + fwd["source_ori"] = FIFF.FIFFV_MNE_FREE_ORI + fwd["surf_ori"] = True + + else: # Free, cartesian + logger.info(" Cartesian source orientations...") + fwd["source_nn"] = np.tile(np.eye(3), (fwd["nsource"], 1)) + fwd["sol"]["data"] = fwd["_orig_sol"].copy() + fwd["sol"]["ncol"] = 3 * fwd["nsource"] + if fwd["sol_grad"] is not None: + fwd["sol_grad"]["data"] = fwd["_orig_sol_grad"].copy() + fwd["sol_grad"]["ncol"] = 9 * fwd["nsource"] + fwd["source_ori"] = FIFF.FIFFV_MNE_FREE_ORI + fwd["surf_ori"] = False + + logger.info(" [done]") + + return fwd + + +@verbose +def write_forward_solution(fname, fwd, overwrite=False, verbose=None): + """Write forward solution to a file. + + Parameters + ---------- + %(fname_fwd)s + fwd : Forward + Forward solution. + %(overwrite)s + %(verbose)s + + See Also + -------- + read_forward_solution + + Notes + ----- + Forward solutions, which are derived from an original forward solution with + free orientation, are always stored on disk as forward solution with free + orientation in X/Y/Z RAS coordinates. Transformations (surface orientation, + fixed orientation) will be reverted. To reapply any transformation to the + forward operator please apply :func:`convert_forward_solution` after + reading the forward solution with :func:`read_forward_solution`. + + Forward solutions, which are derived from an original forward solution with + fixed orientation, are stored on disk as forward solution with fixed + surface-based orientations. Please note that the transformation to + surface-based, fixed orientation cannot be reverted after loading the + forward solution with :func:`read_forward_solution`. + """ + check_fname( + fname, + "forward", + ("-fwd.fif", "-fwd.fif.gz", "_fwd.fif", "_fwd.fif.gz", "-fwd.h5", "_fwd.h5"), + ) + + # check for file existence and expand `~` if present + fname = _check_fname(fname, overwrite) + if fname.suffix == ".h5": + _write_forward_hdf5(fname, fwd) + else: + with start_and_end_file(fname) as fid: + _write_forward_solution(fid, fwd) + + +def _write_forward_hdf5(fname, fwd): + _, write_hdf5 = _import_h5io_funcs() + write_hdf5(fname, dict(fwd=fwd), overwrite=True) + + +def _read_forward_hdf5(fname): + read_hdf5, _ = _import_h5io_funcs() + fwd = Forward(read_hdf5(fname)["fwd"]) + fwd["info"] = Info(fwd["info"]) + fwd["src"] = SourceSpaces(fwd["src"]) + return fwd + + +def _write_forward_solution(fid, fwd): + start_block(fid, FIFF.FIFFB_MNE) + + # + # MNE env + # + start_block(fid, FIFF.FIFFB_MNE_ENV) + write_id(fid, FIFF.FIFF_BLOCK_ID) + data = fwd["info"].get("working_dir", None) + if data is not None: + write_string(fid, FIFF.FIFF_MNE_ENV_WORKING_DIR, data) + data = fwd["info"].get("command_line", None) + if data is not None: + write_string(fid, FIFF.FIFF_MNE_ENV_COMMAND_LINE, data) + end_block(fid, FIFF.FIFFB_MNE_ENV) + + # + # Information from the MRI file + # + start_block(fid, FIFF.FIFFB_MNE_PARENT_MRI_FILE) + write_string(fid, FIFF.FIFF_MNE_FILE_NAME, fwd["info"]["mri_file"]) + if fwd["info"]["mri_id"] is not None: + write_id(fid, FIFF.FIFF_PARENT_FILE_ID, fwd["info"]["mri_id"]) + # store the MRI to HEAD transform in MRI file + write_coord_trans(fid, fwd["info"]["mri_head_t"]) + end_block(fid, FIFF.FIFFB_MNE_PARENT_MRI_FILE) + + # write measurement info + write_forward_meas_info(fid, fwd["info"]) + + # invert our original source space transform + src = fwd["src"].copy() + # returns source space to original coordinate frame, usually MRI + src._transform_to(fwd["mri_head_t"]["from"], fwd["mri_head_t"]) + + # + # Write the source spaces (again) + # + _write_source_spaces_to_fid(fid, src) + n_vert = sum([ss["nuse"] for ss in src]) + if fwd["_orig_source_ori"] == FIFF.FIFFV_MNE_FIXED_ORI: + n_col = n_vert + else: + n_col = 3 * n_vert + + # Undo transformations + sol = fwd["_orig_sol"].copy() + if fwd["sol_grad"] is not None: + sol_grad = fwd["_orig_sol_grad"].copy() + else: + sol_grad = None + + if fwd["surf_ori"] is True: + if fwd["_orig_source_ori"] == FIFF.FIFFV_MNE_FIXED_ORI: + warn( + "The forward solution, which is stored on disk now, is based " + "on a forward solution with fixed orientation. Please note " + "that the transformation to surface-based, fixed orientation " + "cannot be reverted after loading the forward solution with " + "read_forward_solution.", + RuntimeWarning, + ) + else: + warn( + "This forward solution is based on a forward solution with " + "free orientation. The original forward solution is stored " + "on disk in X/Y/Z RAS coordinates. Any transformation " + "(surface orientation or fixed orientation) will be " + "reverted. To reapply any transformation to the forward " + "operator please apply convert_forward_solution after " + "reading the forward solution with read_forward_solution.", + RuntimeWarning, + ) + + # + # MEG forward solution + # + picks_meg = pick_types(fwd["info"], meg=True, eeg=False, ref_meg=False, exclude=[]) + picks_eeg = pick_types(fwd["info"], meg=False, eeg=True, ref_meg=False, exclude=[]) + n_meg = len(picks_meg) + n_eeg = len(picks_eeg) + row_names_meg = [fwd["sol"]["row_names"][p] for p in picks_meg] + row_names_eeg = [fwd["sol"]["row_names"][p] for p in picks_eeg] + + if n_meg > 0: + meg_solution = dict( + data=sol[picks_meg], + nrow=n_meg, + ncol=n_col, + row_names=row_names_meg, + col_names=[], + ) + _transpose_named_matrix(meg_solution) + start_block(fid, FIFF.FIFFB_MNE_FORWARD_SOLUTION) + write_int(fid, FIFF.FIFF_MNE_INCLUDED_METHODS, FIFF.FIFFV_MNE_MEG) + write_int(fid, FIFF.FIFF_MNE_COORD_FRAME, fwd["coord_frame"]) + write_int(fid, FIFF.FIFF_MNE_SOURCE_ORIENTATION, fwd["_orig_source_ori"]) + write_int(fid, FIFF.FIFF_MNE_SOURCE_SPACE_NPOINTS, n_vert) + write_int(fid, FIFF.FIFF_NCHAN, n_meg) + write_named_matrix(fid, FIFF.FIFF_MNE_FORWARD_SOLUTION, meg_solution) + if sol_grad is not None: + meg_solution_grad = dict( + data=sol_grad[picks_meg], + nrow=n_meg, + ncol=n_col * 3, + row_names=row_names_meg, + col_names=[], + ) + _transpose_named_matrix(meg_solution_grad) + write_named_matrix( + fid, FIFF.FIFF_MNE_FORWARD_SOLUTION_GRAD, meg_solution_grad + ) + end_block(fid, FIFF.FIFFB_MNE_FORWARD_SOLUTION) + + # + # EEG forward solution + # + if n_eeg > 0: + eeg_solution = dict( + data=sol[picks_eeg], + nrow=n_eeg, + ncol=n_col, + row_names=row_names_eeg, + col_names=[], + ) + _transpose_named_matrix(eeg_solution) + start_block(fid, FIFF.FIFFB_MNE_FORWARD_SOLUTION) + write_int(fid, FIFF.FIFF_MNE_INCLUDED_METHODS, FIFF.FIFFV_MNE_EEG) + write_int(fid, FIFF.FIFF_MNE_COORD_FRAME, fwd["coord_frame"]) + write_int(fid, FIFF.FIFF_MNE_SOURCE_ORIENTATION, fwd["_orig_source_ori"]) + write_int(fid, FIFF.FIFF_NCHAN, n_eeg) + write_int(fid, FIFF.FIFF_MNE_SOURCE_SPACE_NPOINTS, n_vert) + write_named_matrix(fid, FIFF.FIFF_MNE_FORWARD_SOLUTION, eeg_solution) + if sol_grad is not None: + eeg_solution_grad = dict( + data=sol_grad[picks_eeg], + nrow=n_eeg, + ncol=n_col * 3, + row_names=row_names_eeg, + col_names=[], + ) + _transpose_named_matrix(eeg_solution_grad) + write_named_matrix( + fid, FIFF.FIFF_MNE_FORWARD_SOLUTION_GRAD, eeg_solution_grad + ) + end_block(fid, FIFF.FIFFB_MNE_FORWARD_SOLUTION) + + end_block(fid, FIFF.FIFFB_MNE) + + +def is_fixed_orient(forward, orig=False): + """Check if the forward operator is fixed orientation. + + Parameters + ---------- + forward : instance of Forward + The forward. + orig : bool + If True, consider the original source orientation. + If False (default), consider the current source orientation. + + Returns + ------- + fixed_ori : bool + Whether or not it is fixed orientation. + """ + if orig: # if we want to know about the original version + fixed_ori = forward["_orig_source_ori"] == FIFF.FIFFV_MNE_FIXED_ORI + else: # most of the time we want to know about the current version + fixed_ori = forward["source_ori"] == FIFF.FIFFV_MNE_FIXED_ORI + return fixed_ori + + +@fill_doc +def write_forward_meas_info(fid, info): + """Write measurement info stored in forward solution. + + Parameters + ---------- + fid : file id + The file id + %(info_not_none)s + """ + info._check_consistency() + # + # Information from the MEG file + # + start_block(fid, FIFF.FIFFB_MNE_PARENT_MEAS_FILE) + write_string(fid, FIFF.FIFF_MNE_FILE_NAME, info["meas_file"]) + if info["meas_id"] is not None: + write_id(fid, FIFF.FIFF_PARENT_BLOCK_ID, info["meas_id"]) + # get transformation from CTF and DEVICE to HEAD coordinate frame + meg_head_t = info.get("dev_head_t", info.get("ctf_head_t")) + if meg_head_t is None: + raise ValueError("Head<-->sensor transform not found") + write_coord_trans(fid, meg_head_t) + + ch_names_mapping = dict() + if "chs" in info: + # Channel information + ch_names_mapping = _make_ch_names_mapping(info["chs"]) + write_int(fid, FIFF.FIFF_NCHAN, len(info["chs"])) + _write_ch_infos(fid, info["chs"], False, ch_names_mapping) + if "bads" in info and len(info["bads"]) > 0: + # Bad channels + _write_bad_channels(fid, info["bads"], ch_names_mapping) + + end_block(fid, FIFF.FIFFB_MNE_PARENT_MEAS_FILE) + + +def _select_orient_forward(forward, info, noise_cov=None, copy=True): + """Prepare forward solution for inverse solvers.""" + # fwd['sol']['row_names'] may be different order from fwd['info']['chs'] + fwd_sol_ch_names = forward["sol"]["row_names"] + all_ch_names = set(fwd_sol_ch_names) + all_bads = set(info["bads"]) + if noise_cov is not None: + all_ch_names &= set(noise_cov["names"]) + all_bads |= set(noise_cov["bads"]) + else: + noise_cov = dict(bads=info["bads"]) + ch_names = [ + c["ch_name"] + for c in info["chs"] + if c["ch_name"] not in all_bads and c["ch_name"] in all_ch_names + ] + + if not len(info["bads"]) == len(noise_cov["bads"]) or not all( + b in noise_cov["bads"] for b in info["bads"] + ): + logger.info( + 'info["bads"] and noise_cov["bads"] do not match, ' + "excluding bad channels from both" + ) + + # check the compensation grade + _check_compensation_grade(forward["info"], info, "forward") + + n_chan = len(ch_names) + logger.info("Computing inverse operator with %d channels.", n_chan) + forward = pick_channels_forward(forward, ch_names, ordered=True, copy=copy) + info_idx = [info["ch_names"].index(name) for name in ch_names] + info_picked = pick_info(info, info_idx) + forward["info"]._check_consistency() + info_picked._check_consistency() + return forward, info_picked + + +def _triage_loose(src, loose, fixed="auto"): + _validate_type(loose, (str, dict, "numeric"), "loose") + _validate_type(fixed, (str, bool), "fixed") + orig_loose = loose + if isinstance(loose, str): + _check_option("loose", loose, ("auto",)) + if fixed is True: + loose = 0.0 + else: # False or auto + loose = 0.2 if src.kind == "surface" else 1.0 + src_types = set(_src_kind_dict[s["type"]] for s in src) + if not isinstance(loose, dict): + loose = float(loose) + loose = {key: loose for key in src_types} + loose_keys = set(loose.keys()) + if loose_keys != src_types: + raise ValueError( + f"loose, if dict, must have keys {sorted(src_types)} to match the " + f"source space, got {sorted(loose_keys)}" + ) + # if fixed is auto it can be ignored, if it's False it can be ignored, + # only really need to care about fixed=True + if fixed is True: + if not all(v == 0.0 for v in loose.values()): + raise ValueError( + f'When using fixed=True, loose must be 0. or "auto", got {orig_loose}' + ) + elif fixed is False: + if any(v == 0.0 for v in loose.values()): + raise ValueError( + 'If loose==0., then fixed must be True or "auto", got False' + ) + del fixed + + for key, this_loose in loose.items(): + if key not in ("surface", "discrete") and this_loose != 1: + raise ValueError( + 'loose parameter has to be 1 or "auto" for non-surface/' + f'discrete source spaces, got loose["{key}"] = {this_loose}' + ) + if not 0 <= this_loose <= 1: + raise ValueError(f"loose ({key}) must be between 0 and 1, got {this_loose}") + return loose + + +@verbose +def compute_orient_prior(forward, loose="auto", verbose=None): + """Compute orientation prior. + + Parameters + ---------- + forward : instance of Forward + Forward operator. + %(loose)s + %(verbose)s + + Returns + ------- + orient_prior : ndarray, shape (n_sources,) + Orientation priors. + + See Also + -------- + compute_depth_prior + """ + _validate_type(forward, Forward, "forward") + n_sources = forward["sol"]["data"].shape[1] + + loose = _triage_loose(forward["src"], loose) + orient_prior = np.ones(n_sources, dtype=np.float64) + if is_fixed_orient(forward): + if any(v > 0.0 for v in loose.values()): + raise ValueError( + "loose must be 0. with forward operator " + f"with fixed orientation, got {loose}" + ) + return orient_prior + if all(v == 1.0 for v in loose.values()): + return orient_prior + # We actually need non-unity prior, compute it for each source space + # separately + if not forward["surf_ori"]: + raise ValueError( + "Forward operator is not oriented in surface " + "coordinates. loose parameter should be 1. " + f"not {loose}." + ) + start = 0 + logged = dict() + for s in forward["src"]: + this_type = _src_kind_dict[s["type"]] + use_loose = loose[this_type] + if not logged.get(this_type): + if use_loose == 1.0: + name = "free" + else: + name = "fixed" if use_loose == 0.0 else "loose" + logger.info( + f"Applying {name.ljust(5)} dipole orientations to " + f"{this_type.ljust(7)} source spaces: {use_loose}" + ) + logged[this_type] = True + stop = start + 3 * s["nuse"] + orient_prior[start:stop:3] *= use_loose + orient_prior[start + 1 : stop : 3] *= use_loose + start = stop + return orient_prior + + +def _restrict_gain_matrix(G, info): + """Restrict gain matrix entries for optimal depth weighting.""" + # Figure out which ones have been used + if len(info["chs"]) != G.shape[0]: + raise ValueError( + f'G.shape[0] ({G.shape[0]}) and length of info["chs"] ({len(info["chs"])}) ' + "do not match." + ) + for meg, eeg, kind in ( + ("grad", False, "planar"), + ("mag", False, "magnetometer or axial gradiometer"), + (False, True, "EEG"), + ): + sel = pick_types(info, meg=meg, eeg=eeg, ref_meg=False, exclude=[]) + if len(sel) > 0: + logger.info(" %d %s channels", len(sel), kind) + break + else: + warn("Could not find MEG or EEG channels to limit depth channels") + sel = slice(None) + return G[sel] + + +@verbose +def compute_depth_prior( + forward, + info, + exp=0.8, + limit=10.0, + limit_depth_chs=False, + combine_xyz="spectral", + noise_cov=None, + rank=None, + verbose=None, +): + """Compute depth prior for depth weighting. + + Parameters + ---------- + forward : instance of Forward + The forward solution. + %(info_not_none)s + exp : float + Exponent for the depth weighting, must be between 0 and 1. + limit : float | None + The upper bound on depth weighting. + Can be None to be bounded by the largest finite prior. + limit_depth_chs : bool | 'whiten' + How to deal with multiple channel types in depth weighting. + The default is True, which whitens based on the source sensitivity + of the highest-SNR channel type. See Notes for details. + + .. versionchanged:: 0.18 + Added the "whiten" option. + combine_xyz : 'spectral' | 'fro' + When a loose (or free) orientation is used, how the depth weighting + for each triplet should be calculated. + If 'spectral', use the squared spectral norm of Gk. + If 'fro', use the squared Frobenius norm of Gk. + + .. versionadded:: 0.18 + noise_cov : instance of Covariance | None + The noise covariance to use to whiten the gain matrix when + ``limit_depth_chs='whiten'``. + + .. versionadded:: 0.18 + %(rank_none)s + + .. versionadded:: 0.18 + %(verbose)s + + Returns + ------- + depth_prior : ndarray, shape (n_vertices,) + The depth prior. + + See Also + -------- + compute_orient_prior + + Notes + ----- + The defaults used by the minimum norm code and sparse solvers differ. + In particular, the values for MNE are:: + + compute_depth_prior(..., limit=10., limit_depth_chs=True, + combine_xyz='spectral') + + In sparse solvers and LCMV, the values are:: + + compute_depth_prior(..., limit=None, limit_depth_chs='whiten', + combine_xyz='fro') + + The ``limit_depth_chs`` argument can take the following values: + + * :data:`python:True` (default) + Use only grad channels in depth weighting (equivalent to MNE C + minimum-norm code). If grad channels aren't present, only mag + channels will be used (if no mag, then eeg). This makes the depth + prior dependent only on the sensor geometry (and relationship + to the sources). + * ``'whiten'`` + Compute a whitener and apply it to the gain matrix before computing + the depth prior. In this case ``noise_cov`` must not be None. + Whitening the gain matrix makes the depth prior + depend on both sensor geometry and the data of interest captured + by the noise covariance (e.g., projections, SNR). + + .. versionadded:: 0.18 + * :data:`python:False` + Use all channels. Not recommended since the depth weighting will be + biased toward whichever channel type has the largest values in + SI units (such as EEG being orders of magnitude larger than MEG). + """ + from ..cov import Covariance, compute_whitener + + _validate_type(forward, Forward, "forward") + patch_areas = forward.get("patch_areas", None) + is_fixed_ori = is_fixed_orient(forward) + G = forward["sol"]["data"] + logger.info("Creating the depth weighting matrix...") + _validate_type(noise_cov, (Covariance, None), "noise_cov", "Covariance or None") + _validate_type(limit_depth_chs, (str, bool), "limit_depth_chs") + if isinstance(limit_depth_chs, str): + if limit_depth_chs != "whiten": + raise ValueError( + f'limit_depth_chs, if str, must be "whiten", got {limit_depth_chs}' + ) + if not isinstance(noise_cov, Covariance): + raise ValueError( + 'With limit_depth_chs="whiten", noise_cov must be' + f" a Covariance, got {type(noise_cov)}" + ) + if combine_xyz is not False: # private / expert option + _check_option("combine_xyz", combine_xyz, ("fro", "spectral")) + + # If possible, pick best depth-weighting channels + if limit_depth_chs is True: + G = _restrict_gain_matrix(G, info) + elif limit_depth_chs == "whiten": + whitener, _ = compute_whitener( + noise_cov, info, pca=True, rank=rank, verbose=False + ) + G = np.dot(whitener, G) + + # Compute the gain matrix + if is_fixed_ori or combine_xyz in ("fro", False): + d = np.sum(G**2, axis=0) + if not (is_fixed_ori or combine_xyz is False): + d = d.reshape(-1, 3).sum(axis=1) + # Spherical leadfield can be zero at the center + d[d == 0.0] = np.min(d[d != 0.0]) + else: # 'spectral' + # n_pos = G.shape[1] // 3 + # The following is equivalent to this, but 4-10x faster + # d = np.zeros(n_pos) + # for k in range(n_pos): + # Gk = G[:, 3 * k:3 * (k + 1)] + # x = np.dot(Gk.T, Gk) + # d[k] = linalg.svdvals(x)[0] + G = _reshape_view(G, (G.shape[0], -1, 3)) + d = np.linalg.norm( + np.einsum("svj,svk->vjk", G, G), # vector dot prods + ord=2, # ord=2 spectral (largest s.v.) + axis=(1, 2), + ) + G = _reshape_view(G, (G.shape[0], -1)) + + # XXX Currently the fwd solns never have "patch_areas" defined + if patch_areas is not None: + if not is_fixed_ori and combine_xyz is False: + patch_areas = np.repeat(patch_areas, 3) + d /= patch_areas**2 + logger.info(" Patch areas taken into account in the depth weighting") + + w = 1.0 / d + if limit is not None: + ws = np.sort(w) + weight_limit = limit**2 + if limit_depth_chs is False: + # match old mne-python behavior + # we used to do ind = np.argmin(ws), but this is 0 by sort above + n_limit = 0 + limit = ws[0] * weight_limit + else: + # match C code behavior + limit = ws[-1] + n_limit = len(d) + if ws[-1] > weight_limit * ws[0]: + ind = np.where(ws > weight_limit * ws[0])[0][0] + limit = ws[ind] + n_limit = ind + + logger.info( + " limit = %d/%d = %f", n_limit + 1, len(d), np.sqrt(limit / ws[0]) + ) + scale = 1.0 / limit + logger.info(f" scale = {scale:g} exp = {exp:g}") + w = np.minimum(w / limit, 1) + depth_prior = w**exp + + if not (is_fixed_ori or combine_xyz is False): + depth_prior = np.repeat(depth_prior, 3) + + return depth_prior + + +def _stc_src_sel( + src, stc, on_missing="raise", extra=", likely due to forward calculations" +): + """Select the vertex indices of a source space using a source estimate.""" + if isinstance(stc, list): + vertices = stc + else: + assert isinstance(stc, _BaseSourceEstimate) + vertices = stc.vertices + del stc + if not len(src) == len(vertices): + raise RuntimeError( + f"Mismatch between number of source spaces ({len(src)}) and " + f"STC vertices ({len(vertices)})" + ) + src_sels, stc_sels, out_vertices = [], [], [] + src_offset = stc_offset = 0 + for s, v in zip(src, vertices): + joint_sel = np.intersect1d(s["vertno"], v) + src_sels.append(np.searchsorted(s["vertno"], joint_sel) + src_offset) + src_offset += len(s["vertno"]) + idx = np.searchsorted(v, joint_sel) + stc_sels.append(idx + stc_offset) + stc_offset += len(v) + out_vertices.append(np.array(v)[idx]) + src_sel = np.concatenate(src_sels) + stc_sel = np.concatenate(stc_sels) + assert len(src_sel) == len(stc_sel) == sum(len(v) for v in out_vertices) + + n_stc = sum(len(v) for v in vertices) + n_joint = len(src_sel) + if n_joint != n_stc: + msg = ( + f"Only {n_joint} of {n_stc} SourceEstimate " + f"{'vertex' if n_stc == 1 else 'vertices'} found in source space{extra}" + ) + _on_missing(on_missing, msg) + return src_sel, stc_sel, out_vertices + + +def _fill_measurement_info(info, fwd, sfreq, data): + """Fill the measurement info of a Raw or Evoked object.""" + sel = pick_channels(info["ch_names"], fwd["sol"]["row_names"], ordered=False) + info = pick_info(info, sel) + info["bads"] = [] + + now = time() + sec = np.floor(now) + usec = 1e6 * (now - sec) + + # this is probably correct based on what's done in meas_info.py... + with info._unlock(check_after=True): + info.update( + meas_id=fwd["info"]["meas_id"], + file_id=info["meas_id"], + meas_date=_stamp_to_dt((int(sec), int(usec))), + highpass=0.0, + lowpass=sfreq / 2.0, + sfreq=sfreq, + projs=[], + ) + + # reorder data (which is in fwd order) to match that of info + order = [fwd["sol"]["row_names"].index(name) for name in info["ch_names"]] + data = data[order] + + return info, data + + +@verbose +def _apply_forward( + fwd, stc, start=None, stop=None, on_missing="raise", use_cps=True, verbose=None +): + """Apply forward model and return data, times, ch_names.""" + _validate_type(stc, _BaseSourceEstimate, "stc", "SourceEstimate") + _validate_type(fwd, Forward, "fwd") + if isinstance(stc, _BaseVectorSourceEstimate): + vector = True + fwd = convert_forward_solution(fwd, force_fixed=False, surf_ori=False) + else: + vector = False + if not is_fixed_orient(fwd): + fwd = convert_forward_solution(fwd, force_fixed=True, use_cps=use_cps) + + if np.all(stc.data > 0): + warn( + "Source estimate only contains currents with positive values. " + 'Use pick_ori="normal" when computing the inverse to compute ' + "currents not current magnitudes." + ) + + _check_stc_units(stc) + + src_sel, stc_sel, _ = _stc_src_sel(fwd["src"], stc, on_missing=on_missing) + gain = fwd["sol"]["data"] + stc_sel = slice(None) if len(stc_sel) == len(stc.data) else stc_sel + times = stc.times[start:stop].copy() + stc_data = stc.data[stc_sel, ..., start:stop].reshape(-1, len(times)) + del stc + if vector: + gain = gain.reshape(len(gain), gain.shape[1] // 3, 3) + gain = gain[:, src_sel].reshape(len(gain), -1) + # save some memory if possible + + logger.info("Projecting source estimate to sensor space...") + data = np.dot(gain, stc_data) + logger.info("[done]") + return data, times + + +@verbose +def apply_forward( + fwd, + stc, + info, + start=None, + stop=None, + use_cps=True, + on_missing="raise", + verbose=None, +): + """Project source space currents to sensor space using a forward operator. + + The sensor space data is computed for all channels present in fwd. Use + pick_channels_forward or pick_types_forward to restrict the solution to a + subset of channels. + + The function returns an Evoked object, which is constructed from + evoked_template. The evoked_template should be from the same MEG system on + which the original data was acquired. An exception will be raised if the + forward operator contains channels that are not present in the template. + + Parameters + ---------- + fwd : Forward + Forward operator to use. + stc : SourceEstimate + The source estimate from which the sensor space data is computed. + %(info_not_none)s + start : int, optional + Index of first time sample (index not time is seconds). + stop : int, optional + Index of first time sample not to include (index not time is seconds). + %(use_cps)s + + .. versionadded:: 0.15 + %(on_missing_fwd)s + Default is "raise". + + .. versionadded:: 0.18 + %(verbose)s + + Returns + ------- + evoked : Evoked + Evoked object with computed sensor space data. + + See Also + -------- + apply_forward_raw: Compute sensor space data and return a Raw object. + """ + _validate_type(info, Info, "info") + _validate_type(fwd, Forward, "forward") + info._check_consistency() + + # make sure evoked_template contains all channels in fwd + for ch_name in fwd["sol"]["row_names"]: + if ch_name not in info["ch_names"]: + raise ValueError( + f"Channel {ch_name} of forward operator not present in evoked_template." + ) + + # project the source estimate to the sensor space + data, times = _apply_forward( + fwd, stc, start, stop, on_missing=on_missing, use_cps=use_cps + ) + + # fill the measurement info + sfreq = float(1.0 / stc.tstep) + info, data = _fill_measurement_info(info, fwd, sfreq, data) + + evoked = EvokedArray(data, info, times[0], nave=1) + + evoked._set_times(times) + evoked._update_first_last() + + return evoked + + +@verbose +def apply_forward_raw( + fwd, + stc, + info, + start=None, + stop=None, + on_missing="raise", + use_cps=True, + verbose=None, +): + """Project source space currents to sensor space using a forward operator. + + The sensor space data is computed for all channels present in fwd. Use + pick_channels_forward or pick_types_forward to restrict the solution to a + subset of channels. + + The function returns a Raw object, which is constructed using provided + info. The info object should be from the same MEG system on which the + original data was acquired. An exception will be raised if the forward + operator contains channels that are not present in the info. + + Parameters + ---------- + fwd : Forward + Forward operator to use. + stc : SourceEstimate + The source estimate from which the sensor space data is computed. + %(info_not_none)s + start : int, optional + Index of first time sample (index not time is seconds). + stop : int, optional + Index of first time sample not to include (index not time is seconds). + %(on_missing_fwd)s + Default is "raise". + + .. versionadded:: 0.18 + %(use_cps)s + + .. versionadded:: 0.21 + %(verbose)s + + Returns + ------- + raw : Raw object + Raw object with computed sensor space data. + + See Also + -------- + apply_forward: Compute sensor space data and return an Evoked object. + """ + # make sure info contains all channels in fwd + for ch_name in fwd["sol"]["row_names"]: + if ch_name not in info["ch_names"]: + raise ValueError( + f"Channel {ch_name} of forward operator not present in info." + ) + + # project the source estimate to the sensor space + data, times = _apply_forward( + fwd, stc, start, stop, on_missing=on_missing, use_cps=use_cps + ) + + sfreq = 1.0 / stc.tstep + info, data = _fill_measurement_info(info, fwd, sfreq, data) + with info._unlock(): + info["projs"] = [] + # store sensor data in Raw object using the info + raw = RawArray(data, info, first_samp=int(np.round(times[0] * sfreq))) + raw._projector = None + return raw + + +@fill_doc +def restrict_forward_to_stc(fwd, stc, on_missing="ignore"): + """Restrict forward operator to active sources in a source estimate. + + Parameters + ---------- + fwd : instance of Forward + Forward operator. + stc : instance of SourceEstimate + Source estimate. + %(on_missing_fwd)s + Default is "ignore". + + .. versionadded:: 0.18 + + Returns + ------- + fwd_out : instance of Forward + Restricted forward operator. + + See Also + -------- + restrict_forward_to_label + """ + _validate_type(on_missing, str, "on_missing") + _check_option("on_missing", on_missing, ("ignore", "warn", "raise")) + src_sel, _, _ = _stc_src_sel(fwd["src"], stc, on_missing=on_missing) + del stc + return _restrict_forward_to_src_sel(fwd, src_sel) + + +def _restrict_forward_to_src_sel(fwd, src_sel): + fwd_out = deepcopy(fwd) + # figure out the vertno we are keeping + idx_sel = np.concatenate( + [[[si] * len(s["vertno"]), s["vertno"]] for si, s in enumerate(fwd["src"])], + axis=-1, + ) + assert idx_sel.ndim == 2 and idx_sel.shape[0] == 2 + assert idx_sel.shape[1] == fwd["nsource"] + idx_sel = idx_sel[:, src_sel] + + fwd_out["source_rr"] = fwd["source_rr"][src_sel] + fwd_out["nsource"] = len(src_sel) + + if is_fixed_orient(fwd): + idx = src_sel + if fwd["sol_grad"] is not None: + idx_grad = (3 * src_sel[:, None] + np.arange(3)).ravel() + else: + idx = (3 * src_sel[:, None] + np.arange(3)).ravel() + if fwd["sol_grad"] is not None: + idx_grad = (9 * src_sel[:, None] + np.arange(9)).ravel() + + fwd_out["source_nn"] = fwd["source_nn"][idx] + fwd_out["sol"]["data"] = fwd["sol"]["data"][:, idx] + if fwd["sol_grad"] is not None: + fwd_out["sol_grad"]["data"] = fwd["sol_grad"]["data"][:, idx_grad] + fwd_out["sol"]["ncol"] = len(idx) + + if is_fixed_orient(fwd, orig=True): + idx = src_sel + if fwd["sol_grad"] is not None: + idx_grad = (3 * src_sel[:, None] + np.arange(3)).ravel() + else: + idx = (3 * src_sel[:, None] + np.arange(3)).ravel() + if fwd["sol_grad"] is not None: + idx_grad = (9 * src_sel[:, None] + np.arange(9)).ravel() + + fwd_out["_orig_sol"] = fwd["_orig_sol"][:, idx] + if fwd["sol_grad"] is not None: + fwd_out["_orig_sol_grad"] = fwd["_orig_sol_grad"][:, idx_grad] + + vertices = [idx_sel[1][idx_sel[0] == si] for si in range(len(fwd_out["src"]))] + _set_source_space_vertices(fwd_out["src"], vertices) + + return fwd_out + + +def restrict_forward_to_label(fwd, labels): + """Restrict forward operator to labels. + + Parameters + ---------- + fwd : Forward + Forward operator. + labels : instance of Label | list + Label object or list of label objects. + + Returns + ------- + fwd_out : dict + Restricted forward operator. + + See Also + -------- + restrict_forward_to_stc + """ + vertices = [np.array([], int), np.array([], int)] + + if not isinstance(labels, list): + labels = [labels] + + # Get vertices separately of each hemisphere from all label + for label in labels: + _validate_type(label, Label, "label", "Label or list") + i = 0 if label.hemi == "lh" else 1 + vertices[i] = np.append(vertices[i], label.vertices) + # Remove duplicates and sort + vertices = [np.unique(vert_hemi) for vert_hemi in vertices] + vertices = [ + vert_hemi[np.isin(vert_hemi, s["vertno"])] + for vert_hemi, s in zip(vertices, fwd["src"]) + ] + src_sel, _, _ = _stc_src_sel(fwd["src"], vertices, on_missing="raise") + return _restrict_forward_to_src_sel(fwd, src_sel) + + +def _do_forward_solution( + subject, + meas, + fname=None, + src=None, + spacing=None, + mindist=None, + bem=None, + mri=None, + trans=None, + eeg=True, + meg=True, + fixed=False, + grad=False, + mricoord=False, + overwrite=False, + subjects_dir=None, + verbose=None, +): + """Calculate a forward solution for a subject using MNE-C routines. + + This is kept around for testing purposes. + + This function wraps to mne_do_forward_solution, so the mne + command-line tools must be installed and accessible from Python. + + Parameters + ---------- + subject : str + Name of the subject. + meas : Raw | Epochs | Evoked | str + If Raw or Epochs, a temporary evoked file will be created and + saved to a temporary directory. If str, then it should be a + filename to a file with measurement information the mne + command-line tools can understand (i.e., raw or evoked). + fname : path-like | None + Destination forward solution filename. If None, the solution + will be created in a temporary directory, loaded, and deleted. + src : str | None + Source space name. If None, the MNE default is used. + spacing : str + The spacing to use. Can be ``'#'`` for spacing in mm, ``'ico#'`` for a + recursively subdivided icosahedron, or ``'oct#'`` for a recursively + subdivided octahedron (e.g., ``spacing='ico4'``). Default is 7 mm. + mindist : float | str | None + Minimum distance measof sources from inner skull surface (in mm). + If None, the MNE default value is used. If string, ``'all'`` + indicates to include all points. + bem : str | None + Name of the BEM to use (e.g., ``"sample-5120-5120-5120"``). If None + (Default), the MNE default will be used. + mri : dict | path-like | None + The name of the trans file in FIF format. + If None, ``trans`` must not be None. + trans : dict | path-like | None + File name of the trans file in text format. + If None, ``mri`` must not be None. + eeg : bool + If True (Default), include EEG computations. + meg : bool + If True (Default), include MEG computations. + fixed : bool + If True, make a fixed-orientation forward solution (Default: + False). Note that fixed-orientation inverses can still be + created from free-orientation forward solutions. + grad : bool + If True, compute the gradient of the field with respect to the + dipole coordinates as well (Default: False). + mricoord : bool + If True, calculate in MRI coordinates (Default: False) + %(overwrite)s + %(subjects_dir)s + %(verbose)s + + See Also + -------- + make_forward_solution + + Returns + ------- + fwd : Forward + The generated forward solution. + """ + if not has_mne_c(): + raise RuntimeError("mne command line tools could not be found") + + # check for file existence + temp_dir = Path(tempfile.mkdtemp()) + if fname is None: + fname = temp_dir / "temp-fwd.fif" + _check_fname(fname, overwrite) + _validate_type(subject, "str", "subject") + + # check for meas to exist as string, or try to make evoked + _validate_type(meas, ("path-like", BaseRaw, BaseEpochs, Evoked), "meas") + if isinstance(meas, BaseRaw | BaseEpochs | Evoked): + meas_file = op.join(temp_dir, "info.fif") + write_info(meas_file, meas.info) + meas = meas_file + else: + meas = str(_check_fname(meas, overwrite="read", must_exist=True)) + + # deal with trans/mri + if mri is not None and trans is not None: + raise ValueError("trans and mri cannot both be specified") + if mri is None and trans is None: + # MNE allows this to default to a trans/mri in the subject's dir, + # but let's be safe here and force the user to pass us a trans/mri + raise ValueError("Either trans or mri must be specified") + + if trans is not None: + if isinstance(trans, dict): + trans_data = deepcopy(trans) + trans = temp_dir / "trans-trans.fif" + try: + write_trans(trans, trans_data) + except Exception: + raise OSError( + "trans was a dict, but could not be " + "written to disk as a transform file" + ) + elif isinstance(trans, str | Path | PathLike): + _check_fname(trans, "read", must_exist=True, name="trans") + trans = Path(trans) + else: + raise ValueError("trans must be a path or dict") + if mri is not None: + if isinstance(mri, dict): + mri_data = deepcopy(trans) + mri = temp_dir / "mri-trans.fif" + try: + write_trans(mri, mri_data) + except Exception: + raise OSError( + "mri was a dict, but could not be " + "written to disk as a transform file" + ) + elif isinstance(mri, str | Path | PathLike): + _check_fname(mri, "read", must_exist=True, name="mri") + mri = Path(mri) + else: + raise ValueError("mri must be a path or dict") + + # deal with meg/eeg + if not meg and not eeg: + raise ValueError("meg or eeg (or both) must be True") + + if not fname.suffix == ".fif": + raise ValueError("Forward name does not end with .fif") + path = fname.parent.absolute() + fname = fname.name + + # deal with mindist + if mindist is not None: + if isinstance(mindist, str): + if not mindist.lower() == "all": + raise ValueError('mindist, if string, must be "all"') + mindist = ["--all"] + else: + mindist = ["--mindist", f"{mindist:g}"] + + # src, spacing, bem + for element, name, kind in zip( + (src, spacing, bem), + ("src", "spacing", "bem"), + ("path-like", "str", "path-like"), + ): + if element is not None: + _validate_type(element, kind, name, f"{kind} or None") + + # put together the actual call + cmd = [ + "mne_do_forward_solution", + "--subject", + subject, + "--meas", + meas, + "--fwd", + fname, + "--destdir", + str(path), + ] + if src is not None: + cmd += ["--src", src] + if spacing is not None: + if spacing.isdigit(): + pass # spacing in mm + else: + # allow both "ico4" and "ico-4" style values + match = re.match(r"(oct|ico)-?(\d+)$", spacing) + if match is None: + raise ValueError(f"Invalid spacing parameter: {spacing!r}") + spacing = "-".join(match.groups()) + cmd += ["--spacing", spacing] + if mindist is not None: + cmd += mindist + if bem is not None: + cmd += ["--bem", bem] + if mri is not None: + cmd += ["--mri", f"{mri.absolute()}"] + if trans is not None: + cmd += ["--trans", f"{trans.absolute()}"] + if not meg: + cmd.append("--eegonly") + if not eeg: + cmd.append("--megonly") + if fixed: + cmd.append("--fixed") + if grad: + cmd.append("--grad") + if mricoord: + cmd.append("--mricoord") + if overwrite: + cmd.append("--overwrite") + + env = os.environ.copy() + subjects_dir = str(get_subjects_dir(subjects_dir, raise_error=True)) + env["SUBJECTS_DIR"] = subjects_dir + + try: + logger.info( + "Running forward solution generation command with " + f"subjects_dir {subjects_dir}" + ) + run_subprocess(cmd, env=env) + except Exception: + raise + else: + fwd = read_forward_solution(path / fname, verbose=False) + finally: + shutil.rmtree(temp_dir, ignore_errors=True) + return fwd + + +@verbose +def average_forward_solutions(fwds, weights=None, verbose=None): + """Average forward solutions. + + Parameters + ---------- + fwds : list of Forward + Forward solutions to average. Each entry (dict) should be a + forward solution. + weights : array | None + Weights to apply to each forward solution in averaging. If None, + forward solutions will be equally weighted. Weights must be + non-negative, and will be adjusted to sum to one. + %(verbose)s + + Returns + ------- + fwd : Forward + The averaged forward solution. + """ + # check for fwds being a list + _validate_type(fwds, list, "fwds") + if not len(fwds) > 0: + raise ValueError("fwds must not be empty") + + # check weights + if weights is None: + weights = np.ones(len(fwds)) + weights = np.asanyarray(weights) # in case it's a list, convert it + if not np.all(weights >= 0): + raise ValueError("weights must be non-negative") + if not len(weights) == len(fwds): + raise ValueError("weights must be None or the same length as fwds") + w_sum = np.sum(weights) + if not w_sum > 0: + raise ValueError("weights cannot all be zero") + weights /= w_sum + + # check our forward solutions + for fwd in fwds: + # check to make sure it's a forward solution + _validate_type(fwd, dict, "each entry in fwds", "dict") + # check to make sure the dict is actually a fwd + check_keys = [ + "info", + "sol_grad", + "nchan", + "src", + "source_nn", + "sol", + "source_rr", + "source_ori", + "surf_ori", + "coord_frame", + "mri_head_t", + "nsource", + ] + if not all(key in fwd for key in check_keys): + raise KeyError( + "forward solution dict does not have all standard " + "entries, cannot compute average." + ) + + # check forward solution compatibility + if any( + fwd["sol"][k] != fwds[0]["sol"][k] for fwd in fwds[1:] for k in ["nrow", "ncol"] + ): + raise ValueError("Forward solutions have incompatible dimensions") + if any( + fwd[k] != fwds[0][k] + for fwd in fwds[1:] + for k in ["source_ori", "surf_ori", "coord_frame"] + ): + raise ValueError("Forward solutions have incompatible orientations") + + # actually average them (solutions and gradients) + fwd_ave = deepcopy(fwds[0]) + fwd_ave["sol"]["data"] *= weights[0] + fwd_ave["_orig_sol"] *= weights[0] + for fwd, w in zip(fwds[1:], weights[1:]): + fwd_ave["sol"]["data"] += w * fwd["sol"]["data"] + fwd_ave["_orig_sol"] += w * fwd["_orig_sol"] + if fwd_ave["sol_grad"] is not None: + fwd_ave["sol_grad"]["data"] *= weights[0] + fwd_ave["_orig_sol_grad"] *= weights[0] + for fwd, w in zip(fwds[1:], weights[1:]): + fwd_ave["sol_grad"]["data"] += w * fwd["sol_grad"]["data"] + fwd_ave["_orig_sol_grad"] += w * fwd["_orig_sol_grad"] + return fwd_ave diff --git a/mne-python/source/mne/forward/tests/__init__.py b/mne-python/source/mne/forward/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/forward/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/forward/tests/test_field_interpolation.py b/mne-python/source/mne/forward/tests/test_field_interpolation.py new file mode 100644 index 0000000000000000000000000000000000000000..4c6ecd73fd545ec6457d0fbddf1875a57efbcf4f --- /dev/null +++ b/mne-python/source/mne/forward/tests/test_field_interpolation.py @@ -0,0 +1,352 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from os import path as op +from pathlib import Path + +import numpy as np +import pytest +from numpy.polynomial import legendre +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_equal, +) +from scipy.interpolate import interp1d + +import mne +from mne import Epochs, make_fixed_length_events, pick_types, read_evokeds +from mne.datasets import testing +from mne.fixes import _reshape_view +from mne.forward import _make_surface_mapping, make_field_map +from mne.forward._field_interpolation import _setup_dots +from mne.forward._lead_dots import ( + _comp_sum_eeg, + _comp_sums_meg, + _do_cross_dots, + _get_legen_table, +) +from mne.forward._make_forward import _create_meg_coils +from mne.io import read_raw_fif +from mne.surface import get_head_surf, get_meg_helmet_surf + +base_dir = op.join(op.dirname(__file__), "..", "..", "io", "tests", "data") +raw_fname = op.join(base_dir, "test_raw.fif") +evoked_fname = op.join(base_dir, "test-ave.fif") +raw_ctf_fname = op.join(base_dir, "test_ctf_raw.fif") + +data_path = testing.data_path(download=False) +trans_fname = op.join(data_path, "MEG", "sample", "sample_audvis_trunc-trans.fif") +subjects_dir = op.join(data_path, "subjects") + + +@testing.requires_testing_data +def test_field_map_ctf(): + """Test that field mapping can be done with CTF data.""" + raw = read_raw_fif(raw_ctf_fname).crop(0, 1) + raw.apply_gradient_compensation(3) + events = make_fixed_length_events(raw, duration=0.5) + evoked = Epochs(raw, events).average() + evoked.pick(evoked.ch_names[:50]) # crappy mapping but faster + # smoke test - passing trans_fname as pathlib.Path as additional check + # set origin to "(0.0, 0.0, 0.04)", which was the default until v1.12 + # estimating origin from "auto" impossible due to missing digitization points + make_field_map( + evoked, + trans=Path(trans_fname), + subject="sample", + subjects_dir=subjects_dir, + origin=(0.0, 0.0, 0.04), + ) + + +def test_legendre_val(): + """Test Legendre polynomial (derivative) equivalence.""" + rng = np.random.RandomState(0) + # check table equiv + xs = np.linspace(-1.0, 1.0, 1000) + n_terms = 100 + + # True, numpy + vals_np = legendre.legvander(xs, n_terms - 1) + + # Table approximation + for nc, interp in zip([100, 50], ["nearest", "linear"]): + lut, n_fact = _get_legen_table("eeg", n_coeff=nc, force_calc=True) + lut_fun = interp1d(np.linspace(-1, 1, lut.shape[0]), lut, interp, axis=0) + vals_i = lut_fun(xs) + # Need a "1:" here because we omit the first coefficient in our table! + assert_allclose( + vals_np[:, 1 : vals_i.shape[1] + 1], vals_i, rtol=1e-2, atol=5e-3 + ) + + # Now let's look at our sums + ctheta = rng.rand(20, 30) * 2.0 - 1.0 + beta = rng.rand(20, 30) * 0.8 + c1 = _comp_sum_eeg(beta.flatten(), ctheta.flatten(), lut_fun, n_fact) + c1 = _reshape_view(c1, beta.shape) + + # compare to numpy + n = np.arange(1, n_terms, dtype=float)[:, np.newaxis, np.newaxis] + coeffs = np.zeros((n_terms,) + beta.shape) + coeffs[1:] = ( + np.cumprod([beta] * (n_terms - 1), axis=0) + * (2.0 * n + 1.0) + * (2.0 * n + 1.0) + / n + ) + # can't use tensor=False here b/c it isn't in old numpy + c2 = np.empty((20, 30)) + for ci1 in range(20): + for ci2 in range(30): + c2[ci1, ci2] = legendre.legval(ctheta[ci1, ci2], coeffs[:, ci1, ci2]) + assert_allclose(c1, c2, 1e-2, 1e-3) # close enough... + + # compare fast and slow for MEG + ctheta = rng.rand(20 * 30) * 2.0 - 1.0 + beta = rng.rand(20 * 30) * 0.8 + lut, n_fact = _get_legen_table("meg", n_coeff=10, force_calc=True) + fun = interp1d(np.linspace(-1, 1, lut.shape[0]), lut, "nearest", axis=0) + coeffs = _comp_sums_meg(beta, ctheta, fun, n_fact, False) + lut, n_fact = _get_legen_table("meg", n_coeff=20, force_calc=True) + fun = interp1d(np.linspace(-1, 1, lut.shape[0]), lut, "linear", axis=0) + coeffs = _comp_sums_meg(beta, ctheta, fun, n_fact, False) + + +def test_legendre_table(): + """Test Legendre table calculation.""" + # double-check our table generation + n = 10 + for ch_type in ["eeg", "meg"]: + lut1, n_fact1 = _get_legen_table(ch_type, n_coeff=25, force_calc=True) + lut1 = lut1[:, : n - 1].copy() + n_fact1 = n_fact1[: n - 1].copy() + lut2, n_fact2 = _get_legen_table(ch_type, n_coeff=n, force_calc=True) + assert_allclose(lut1, lut2) + assert_allclose(n_fact1, n_fact2) + + +@testing.requires_testing_data +def test_make_field_map_eeg(): + """Test interpolation of EEG field onto head.""" + evoked = read_evokeds(evoked_fname, condition="Left Auditory") + evoked.info["bads"] = ["MEG 2443", "EEG 053"] # add some bads + surf = get_head_surf("sample", subjects_dir=subjects_dir) + # we must have trans if surface is in MRI coords + pytest.raises( + ValueError, _make_surface_mapping, evoked.info, surf, "eeg", origin="auto" + ) + + evoked.pick(picks="eeg") + fmd = make_field_map( + evoked, trans_fname, subject="sample", subjects_dir=subjects_dir, origin="auto" + ) + + # trans is necessary for EEG only + pytest.raises( + RuntimeError, + make_field_map, + evoked, + None, + subject="sample", + subjects_dir=subjects_dir, + origin="auto", + ) + + fmd = make_field_map( + evoked, trans_fname, subject="sample", subjects_dir=subjects_dir, origin="auto" + ) + assert len(fmd) == 1 + assert_array_equal(fmd[0]["data"].shape, (642, 59)) # maps data onto surf + assert len(fmd[0]["ch_names"]) == 59 + + +@testing.requires_testing_data +@pytest.mark.slowtest +def test_make_field_map_meg(): + """Test interpolation of MEG field onto helmet | head.""" + evoked = read_evokeds(evoked_fname, condition="Left Auditory") + info = evoked.info + surf = get_meg_helmet_surf(info) + # let's reduce the number of channels by a bunch to speed it up + info["bads"] = info["ch_names"][:200] + # bad ch_type + pytest.raises(ValueError, _make_surface_mapping, info, surf, "foo", origin="auto") + # bad mode + pytest.raises( + ValueError, _make_surface_mapping, info, surf, "meg", mode="foo", origin="auto" + ) + # no picks + evoked_eeg = evoked.copy().pick(picks="eeg") + pytest.raises( + RuntimeError, _make_surface_mapping, evoked_eeg.info, surf, "meg", origin="auto" + ) + # bad surface def + nn = surf["nn"] + del surf["nn"] + pytest.raises(KeyError, _make_surface_mapping, info, surf, "meg", origin="auto") + surf["nn"] = nn + cf = surf["coord_frame"] + del surf["coord_frame"] + pytest.raises(KeyError, _make_surface_mapping, info, surf, "meg", origin="auto") + surf["coord_frame"] = cf + + # now do it with make_field_map + evoked.pick(picks="meg") + evoked.info.normalize_proj() # avoid projection warnings + fmd = make_field_map( + evoked, None, subject="sample", subjects_dir=subjects_dir, origin="auto" + ) + assert len(fmd) == 1 + assert_array_equal(fmd[0]["data"].shape, (304, 106)) # maps data onto surf + assert len(fmd[0]["ch_names"]) == 106 + + pytest.raises(ValueError, make_field_map, evoked, ch_type="foobar", origin="auto") + + # now test the make_field_map on head surf for MEG + evoked.pick(picks="meg") + evoked.info.normalize_proj() + fmd = make_field_map( + evoked, + trans_fname, + meg_surf="head", + subject="sample", + subjects_dir=subjects_dir, + origin="auto", + ) + assert len(fmd) == 1 + assert_array_equal(fmd[0]["data"].shape, (642, 106)) # maps data onto surf + assert len(fmd[0]["ch_names"]) == 106 + + pytest.raises( + ValueError, + make_field_map, + evoked, + meg_surf="foobar", + subjects_dir=subjects_dir, + trans=trans_fname, + origin="auto", + ) + + +@testing.requires_testing_data +def test_make_field_map_meeg(): + """Test making a M/EEG field map onto helmet & head.""" + evoked = read_evokeds(evoked_fname, baseline=(-0.2, 0.0))[0] + picks = pick_types(evoked.info, meg=True, eeg=True) + picks = picks[::10] + evoked.pick([evoked.ch_names[p] for p in picks]) + evoked.info.normalize_proj() + # set origin to "(0.0, 0.0, 0.04)", which was the default until v1.12 + # estimated origin from "auto" fails the assertions below + maps = make_field_map( + evoked, + trans_fname, + subject="sample", + subjects_dir=subjects_dir, + verbose="debug", + origin=(0.0, 0.0, 0.04), + ) + assert_equal(maps[0]["data"].shape, (642, 6)) # EEG->Head + assert_equal(maps[1]["data"].shape, (304, 31)) # MEG->Helmet + # reasonable ranges + maxs = (1.2, 2.0) # before #4418, was (1.1, 2.0) + mins = (-0.8, -1.3) # before #4418, was (-0.6, -1.2) + assert_equal(len(maxs), len(maps)) + for map_, max_, min_ in zip(maps, maxs, mins): + assert_allclose(map_["data"].max(), max_, rtol=5e-2) + assert_allclose(map_["data"].min(), min_, rtol=5e-2) + # calculated from correct looking mapping on 2015/12/26 + assert_allclose( + np.sqrt(np.sum(maps[0]["data"] ** 2)), + 19.0903, + atol=1e-3, + rtol=1e-3, + ) + assert_allclose( + np.sqrt(np.sum(maps[1]["data"] ** 2)), + 19.4748, + atol=1e-3, + rtol=1e-3, + ) + + +def _setup_args(info): + """Configure args for test_as_meg_type_evoked.""" + coils = _create_meg_coils(info["chs"], "normal", info["dev_head_t"]) + int_rad, _, lut_fun, n_fact = _setup_dots("fast", info, coils, "meg") + my_origin = np.array([0.0, 0.0, 0.04]) + args_dict = dict( + intrad=int_rad, + volume=False, + coils1=coils, + r0=my_origin, + ch_type="meg", + lut=lut_fun, + n_fact=n_fact, + ) + return args_dict + + +@testing.requires_testing_data +def test_as_meg_type_evoked(): + """Test interpolation of data on to virtual channels.""" + # validation tests + raw = read_raw_fif(raw_fname) + events = mne.find_events(raw) + picks = pick_types( + raw.info, + meg=True, + eeg=True, + stim=True, + ecg=True, + eog=True, + include=["STI 014"], + exclude="bads", + ) + epochs = mne.Epochs(raw, events, picks=picks) + evoked = epochs.average() + + with pytest.raises(ValueError, match="Invalid value for the 'ch_type'"): + evoked.as_type("meg") + with pytest.raises(ValueError, match="Invalid value for the 'ch_type'"): + evoked.copy().pick(picks="grad").as_type("meg") + + # channel names + ch_names = evoked.info["ch_names"] + virt_evoked = evoked.copy().pick(ch_names[:10:1]) + virt_evoked.info.normalize_proj() + virt_evoked = virt_evoked.as_type("mag") + assert all(ch.endswith("_v") for ch in virt_evoked.info["ch_names"]) + + # pick from and to channels + evoked_from = evoked.copy().pick(ch_names[2:10:3]) + evoked_to = evoked.copy().pick(ch_names[0:10:3]) + + info_from, info_to = evoked_from.info, evoked_to.info + + # set up things + args1, args2 = _setup_args(info_from), _setup_args(info_to) + args1.update(coils2=args2["coils1"]) + args2.update(coils2=args1["coils1"]) + + # test cross dots + cross_dots1 = _do_cross_dots(**args1) + cross_dots2 = _do_cross_dots(**args2) + + assert_array_almost_equal(cross_dots1, cross_dots2.T) + + # correlation test + evoked = evoked.pick(ch_names[:10:]).copy() + data1 = evoked.pick("grad").data.ravel() + data2 = evoked.as_type("grad").data.ravel() + assert np.corrcoef(data1, data2)[0, 1] > 0.95 + + # Do it with epochs + virt_epochs = epochs.copy().load_data().pick(ch_names[:10:1]) + virt_epochs.info.normalize_proj() + virt_epochs = virt_epochs.as_type("mag") + assert all(ch.endswith("_v") for ch in virt_epochs.info["ch_names"]) + assert_allclose(virt_epochs.get_data(copy=False).mean(0), virt_evoked.data) diff --git a/mne-python/source/mne/forward/tests/test_forward.py b/mne-python/source/mne/forward/tests/test_forward.py new file mode 100644 index 0000000000000000000000000000000000000000..3918ee37f1816bd64c4da695557be162370c9a5e --- /dev/null +++ b/mne-python/source/mne/forward/tests/test_forward.py @@ -0,0 +1,528 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import gc +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_equal, +) + +from mne import ( + SourceEstimate, + VectorSourceEstimate, + apply_forward, + apply_forward_raw, + average_forward_solutions, + convert_forward_solution, + pick_types_forward, + read_evokeds, + read_forward_solution, + write_forward_solution, +) +from mne._fiff.pick import pick_channels_forward +from mne.channels import equalize_channels +from mne.datasets import testing +from mne.forward import ( + Forward, + compute_depth_prior, + compute_orient_prior, + is_fixed_orient, + restrict_forward_to_label, + restrict_forward_to_stc, +) +from mne.io import read_info +from mne.label import read_label +from mne.utils import _record_warnings, requires_mne, run_subprocess + +data_path = testing.data_path(download=False) +fname_meeg = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" +fname_meeg_grad = ( + data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-2-grad-fwd.fif" +) +fname_evoked = Path(__file__).parents[2] / "io" / "tests" / "data" / "test-ave.fif" +label_path = data_path / "MEG" / "sample" / "labels" + + +def assert_forward_allclose(f1, f2, rtol=1e-7): + """Compare two potentially converted forward solutions.""" + assert_allclose(f1["sol"]["data"], f2["sol"]["data"], rtol=rtol) + assert f1["sol"]["ncol"] == f2["sol"]["ncol"] + assert f1["sol"]["ncol"] == f1["sol"]["data"].shape[1] + assert_allclose(f1["source_nn"], f2["source_nn"], rtol=rtol) + if f1["sol_grad"] is not None: + assert f2["sol_grad"] is not None + assert_allclose(f1["sol_grad"]["data"], f2["sol_grad"]["data"]) + assert f1["sol_grad"]["ncol"] == f2["sol_grad"]["ncol"] + assert f1["sol_grad"]["ncol"] == f1["sol_grad"]["data"].shape[1] + else: + assert f2["sol_grad"] is None + assert f1["source_ori"] == f2["source_ori"] + assert f1["surf_ori"] == f2["surf_ori"] + assert f1["src"][0]["coord_frame"] == f1["src"][0]["coord_frame"] + + +@testing.requires_testing_data +def test_convert_forward(): + """Test converting forward solution between different representations.""" + fwd = read_forward_solution(fname_meeg_grad) + fwd_repr = repr(fwd) + assert "306" in fwd_repr + assert "60" in fwd_repr + assert fwd_repr + assert isinstance(fwd, Forward) + # look at surface orientation + fwd_surf = convert_forward_solution(fwd, surf_ori=True) + # go back + fwd_new = convert_forward_solution(fwd_surf, surf_ori=False) + assert repr(fwd_new) + assert isinstance(fwd_new, Forward) + assert_forward_allclose(fwd, fwd_new) + del fwd_new + gc.collect() + + # now go to fixed + fwd_fixed = convert_forward_solution( + fwd_surf, surf_ori=True, force_fixed=True, use_cps=False + ) + del fwd_surf + gc.collect() + assert repr(fwd_fixed) + assert isinstance(fwd_fixed, Forward) + assert is_fixed_orient(fwd_fixed) + # now go back to cartesian (original condition) + fwd_new = convert_forward_solution(fwd_fixed, surf_ori=False, force_fixed=False) + assert repr(fwd_new) + assert isinstance(fwd_new, Forward) + assert_forward_allclose(fwd, fwd_new) + del fwd, fwd_new, fwd_fixed + gc.collect() + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_io_forward(tmp_path): + """Test IO for forward solutions.""" + # do extensive tests with MEEG + grad + n_channels, n_src = 366, 108 + fwd = read_forward_solution(fname_meeg_grad) + assert isinstance(fwd, Forward) + fwd = read_forward_solution(fname_meeg_grad) + fwd = convert_forward_solution(fwd, surf_ori=True) + leadfield = fwd["sol"]["data"] + assert_equal(leadfield.shape, (n_channels, n_src)) + assert_equal(len(fwd["sol"]["row_names"]), n_channels) + fname_temp = tmp_path / "test-fwd.fif" + with pytest.warns(RuntimeWarning, match="stored on disk"): + write_forward_solution(fname_temp, fwd, overwrite=True) + + fwd = read_forward_solution(fname_meeg_grad) + fwd = convert_forward_solution(fwd, surf_ori=True) + fwd_read = read_forward_solution(fname_temp) + fwd_read = convert_forward_solution(fwd_read, surf_ori=True) + leadfield = fwd_read["sol"]["data"] + assert_equal(leadfield.shape, (n_channels, n_src)) + assert_equal(len(fwd_read["sol"]["row_names"]), n_channels) + assert_equal(len(fwd_read["info"]["chs"]), n_channels) + assert "dev_head_t" in fwd_read["info"] + assert "mri_head_t" in fwd_read + assert_array_almost_equal(fwd["sol"]["data"], fwd_read["sol"]["data"]) + + fwd = read_forward_solution(fname_meeg) + fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=True, use_cps=False) + with pytest.warns(RuntimeWarning, match="stored on disk"): + write_forward_solution(fname_temp, fwd, overwrite=True) + fwd_read = read_forward_solution(fname_temp) + fwd_read = convert_forward_solution( + fwd_read, surf_ori=True, force_fixed=True, use_cps=False + ) + assert repr(fwd_read) + assert isinstance(fwd_read, Forward) + assert is_fixed_orient(fwd_read) + assert_forward_allclose(fwd, fwd_read) + + fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=True, use_cps=True) + leadfield = fwd["sol"]["data"] + assert_equal(leadfield.shape, (n_channels, 1494 / 3)) + assert_equal(len(fwd["sol"]["row_names"]), n_channels) + assert_equal(len(fwd["info"]["chs"]), n_channels) + assert "dev_head_t" in fwd["info"] + assert "mri_head_t" in fwd + assert fwd["surf_ori"] + with pytest.warns(RuntimeWarning, match="stored on disk"): + write_forward_solution(fname_temp, fwd, overwrite=True) + fwd_read = read_forward_solution(fname_temp) + fwd_read = convert_forward_solution( + fwd_read, surf_ori=True, force_fixed=True, use_cps=True + ) + assert repr(fwd_read) + assert isinstance(fwd_read, Forward) + assert is_fixed_orient(fwd_read) + assert_forward_allclose(fwd, fwd_read) + + fwd = read_forward_solution(fname_meeg_grad) + fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=True, use_cps=True) + leadfield = fwd["sol"]["data"] + assert_equal(leadfield.shape, (n_channels, n_src / 3)) + assert_equal(len(fwd["sol"]["row_names"]), n_channels) + assert_equal(len(fwd["info"]["chs"]), n_channels) + assert "dev_head_t" in fwd["info"] + assert "mri_head_t" in fwd + assert fwd["surf_ori"] + with pytest.warns(RuntimeWarning, match="stored on disk"): + write_forward_solution(fname_temp, fwd, overwrite=True) + fwd_read = read_forward_solution(fname_temp) + fwd_read = convert_forward_solution( + fwd_read, surf_ori=True, force_fixed=True, use_cps=True + ) + assert repr(fwd_read) + assert isinstance(fwd_read, Forward) + assert is_fixed_orient(fwd_read) + assert_forward_allclose(fwd, fwd_read) + + # test warnings on bad filenames + fwd = read_forward_solution(fname_meeg_grad) + fwd_badname = tmp_path / "test-bad-name.fif.gz" + with pytest.warns(RuntimeWarning, match="end with"): + write_forward_solution(fwd_badname, fwd) + with pytest.warns(RuntimeWarning, match="end with"): + read_forward_solution(fwd_badname) + + fwd = read_forward_solution(fname_meeg) + write_forward_solution(fname_temp, fwd, overwrite=True) + fwd_read = read_forward_solution(fname_temp) + assert_forward_allclose(fwd, fwd_read) + + h5py = pytest.importorskip("h5py") + pytest.importorskip("h5io") + fname_h5 = fname_temp.with_suffix(".h5") + fwd.save(fname_h5) + with h5py.File(fname_h5, "r"): + pass # just checks for hdf5-ness + fwd_read = read_forward_solution(fname_h5) + assert_forward_allclose(fwd, fwd_read) + + +@testing.requires_testing_data +def test_apply_forward(): + """Test projection of source space data to sensor space.""" + start = 0 + stop = 5 + n_times = stop - start - 1 + sfreq = 10.0 + t_start = 0.123 + + fwd = read_forward_solution(fname_meeg) + fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=True, use_cps=True) + fwd = pick_types_forward(fwd, meg=True) + assert isinstance(fwd, Forward) + + vertno = [fwd["src"][0]["vertno"], fwd["src"][1]["vertno"]] + stc_data = np.ones((len(vertno[0]) + len(vertno[1]), n_times)) + stc = SourceEstimate(stc_data, vertno, tmin=t_start, tstep=1.0 / sfreq) + + gain_sum = np.sum(fwd["sol"]["data"], axis=1) + + # Evoked + evoked = read_evokeds(fname_evoked, condition=0) + evoked.pick(picks="meg") + with ( + _record_warnings(), + pytest.warns(RuntimeWarning, match="only .* positive values"), + ): + evoked = apply_forward(fwd, stc, evoked.info, start=start, stop=stop) + data = evoked.data + times = evoked.times + + # do some tests + assert_array_almost_equal(evoked.info["sfreq"], sfreq) + assert_array_almost_equal(np.sum(data, axis=1), n_times * gain_sum) + assert_array_almost_equal(times[0], t_start) + assert_array_almost_equal(times[-1], t_start + (n_times - 1) / sfreq) + + # vector + stc_vec = VectorSourceEstimate( + fwd["source_nn"][:, :, np.newaxis] * stc.data[:, np.newaxis], + stc.vertices, + stc.tmin, + stc.tstep, + ) + large_ctx = pytest.warns(RuntimeWarning, match="very large") + with large_ctx: + evoked_2 = apply_forward(fwd, stc_vec, evoked.info) + assert np.abs(evoked_2.data).mean() > 1e-5 + assert_allclose(evoked.data, evoked_2.data, atol=1e-10) + + # Raw + with large_ctx, pytest.warns(RuntimeWarning, match="only .* positive values"): + raw_proj = apply_forward_raw(fwd, stc, evoked.info, start=start, stop=stop) + data, times = raw_proj[:, :] + + # do some tests + assert_array_almost_equal(raw_proj.info["sfreq"], sfreq) + assert_array_almost_equal(np.sum(data, axis=1), n_times * gain_sum) + atol = 1.0 / sfreq + assert_allclose(raw_proj.first_samp / sfreq, t_start, atol=atol) + assert_allclose( + raw_proj.last_samp / sfreq, t_start + (n_times - 1) / sfreq, atol=atol + ) + + +@testing.requires_testing_data +def test_restrict_forward_to_stc(tmp_path): + """Test restriction of source space to source SourceEstimate.""" + start = 0 + stop = 5 + n_times = stop - start - 1 + sfreq = 10.0 + t_start = 0.123 + + fwd = read_forward_solution(fname_meeg) + fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=True, use_cps=True) + fwd = pick_types_forward(fwd, meg=True) + + vertno = [fwd["src"][0]["vertno"][0:15], fwd["src"][1]["vertno"][0:5]] + stc_data = np.ones((len(vertno[0]) + len(vertno[1]), n_times)) + stc = SourceEstimate(stc_data, vertno, tmin=t_start, tstep=1.0 / sfreq) + + fwd_out = restrict_forward_to_stc(fwd, stc) + assert isinstance(fwd_out, Forward) + + assert_equal(fwd_out["sol"]["ncol"], 20) + assert_equal(fwd_out["src"][0]["nuse"], 15) + assert_equal(fwd_out["src"][1]["nuse"], 5) + assert_equal(fwd_out["src"][0]["vertno"], fwd["src"][0]["vertno"][0:15]) + assert_equal(fwd_out["src"][1]["vertno"], fwd["src"][1]["vertno"][0:5]) + + fwd = read_forward_solution(fname_meeg) + fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=False) + fwd = pick_types_forward(fwd, meg=True) + + vertno = [fwd["src"][0]["vertno"][0:15], fwd["src"][1]["vertno"][0:5]] + stc_data = np.ones((len(vertno[0]) + len(vertno[1]), n_times)) + stc = SourceEstimate(stc_data, vertno, tmin=t_start, tstep=1.0 / sfreq) + + fwd_out = restrict_forward_to_stc(fwd, stc) + + assert_equal(fwd_out["sol"]["ncol"], 60) + assert_equal(fwd_out["src"][0]["nuse"], 15) + assert_equal(fwd_out["src"][1]["nuse"], 5) + assert_equal(fwd_out["src"][0]["vertno"], fwd["src"][0]["vertno"][0:15]) + assert_equal(fwd_out["src"][1]["vertno"], fwd["src"][1]["vertno"][0:5]) + + # Test saving the restricted forward object. This only works if all fields + # are properly accounted for. + fname_copy = tmp_path / "copy-fwd.fif" + with pytest.warns(RuntimeWarning, match="stored on disk"): + write_forward_solution(fname_copy, fwd_out, overwrite=True) + fwd_out_read = read_forward_solution(fname_copy) + fwd_out_read = convert_forward_solution( + fwd_out_read, surf_ori=True, force_fixed=False + ) + assert_forward_allclose(fwd_out, fwd_out_read) + + +@testing.requires_testing_data +def test_restrict_forward_to_label(tmp_path): + """Test restriction of source space to label.""" + fwd = read_forward_solution(fname_meeg) + fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=True, use_cps=True) + fwd = pick_types_forward(fwd, meg=True) + + labels = ["Aud-lh", "Vis-rh"] + label_lh = read_label(label_path / (labels[0] + ".label")) + label_rh = read_label(label_path / (labels[1] + ".label")) + + fwd_out = restrict_forward_to_label(fwd, [label_lh, label_rh]) + + src_sel_lh = np.intersect1d(fwd["src"][0]["vertno"], label_lh.vertices) + src_sel_lh = np.searchsorted(fwd["src"][0]["vertno"], src_sel_lh) + vertno_lh = fwd["src"][0]["vertno"][src_sel_lh] + + nuse_lh = fwd["src"][0]["nuse"] + src_sel_rh = np.intersect1d(fwd["src"][1]["vertno"], label_rh.vertices) + src_sel_rh = np.searchsorted(fwd["src"][1]["vertno"], src_sel_rh) + vertno_rh = fwd["src"][1]["vertno"][src_sel_rh] + src_sel_rh += nuse_lh + + assert_equal(fwd_out["sol"]["ncol"], len(src_sel_lh) + len(src_sel_rh)) + assert_equal(fwd_out["src"][0]["nuse"], len(src_sel_lh)) + assert_equal(fwd_out["src"][1]["nuse"], len(src_sel_rh)) + assert_equal(fwd_out["src"][0]["vertno"], vertno_lh) + assert_equal(fwd_out["src"][1]["vertno"], vertno_rh) + + fwd = read_forward_solution(fname_meeg) + fwd = pick_types_forward(fwd, meg=True) + + labels = ["Aud-lh", "Vis-rh"] + label_lh = read_label(label_path / (labels[0] + ".label")) + label_rh = read_label(label_path / (labels[1] + ".label")) + + fwd_out = restrict_forward_to_label(fwd, [label_lh, label_rh]) + + src_sel_lh = np.intersect1d(fwd["src"][0]["vertno"], label_lh.vertices) + src_sel_lh = np.searchsorted(fwd["src"][0]["vertno"], src_sel_lh) + vertno_lh = fwd["src"][0]["vertno"][src_sel_lh] + + nuse_lh = fwd["src"][0]["nuse"] + src_sel_rh = np.intersect1d(fwd["src"][1]["vertno"], label_rh.vertices) + src_sel_rh = np.searchsorted(fwd["src"][1]["vertno"], src_sel_rh) + vertno_rh = fwd["src"][1]["vertno"][src_sel_rh] + src_sel_rh += nuse_lh + + assert_equal(fwd_out["sol"]["ncol"], 3 * (len(src_sel_lh) + len(src_sel_rh))) + assert_equal(fwd_out["src"][0]["nuse"], len(src_sel_lh)) + assert_equal(fwd_out["src"][1]["nuse"], len(src_sel_rh)) + assert_equal(fwd_out["src"][0]["vertno"], vertno_lh) + assert_equal(fwd_out["src"][1]["vertno"], vertno_rh) + + # Test saving the restricted forward object. This only works if all fields + # are properly accounted for. + fname_copy = tmp_path / "copy-fwd.fif" + write_forward_solution(fname_copy, fwd_out, overwrite=True) + fwd_out_read = read_forward_solution(fname_copy) + assert_forward_allclose(fwd_out, fwd_out_read) + + +@pytest.mark.parametrize("use_cps", [True, False]) +@testing.requires_testing_data +def test_restrict_forward_to_label_cps(tmp_path, use_cps): + """Test for gh-11689.""" + label_lh = read_label(label_path / "Aud-lh.label") + fwd = read_forward_solution(fname_meeg) + convert_forward_solution( + fwd, surf_ori=True, force_fixed=False, copy=False, use_cps=use_cps + ) + fwd = pick_types_forward(fwd, meg="mag") + fwd_out = restrict_forward_to_label(fwd, label_lh) + vert = fwd_out["src"][0]["vertno"][0] + + assert fwd["surf_ori"] + assert not is_fixed_orient(fwd) + idx = list(fwd["src"][0]["vertno"]).index(vert) + assert idx == 126 + go1 = fwd["_orig_sol"][:, idx * 3 : idx * 3 + 3].copy() + gs1 = fwd["sol"]["data"][:, idx * 3 : idx * 3 + 3].copy() + + assert fwd_out["surf_ori"] + assert not is_fixed_orient(fwd_out) + idx = list(fwd_out["src"][0]["vertno"]).index(vert) + assert idx == 0 + go2 = fwd_out["_orig_sol"][:, idx * 3 : idx * 3 + 3].copy() + gs2 = fwd_out["sol"]["data"][:, idx * 3 : idx * 3 + 3].copy() + assert_allclose(go2, go1) + assert_allclose(gs2, gs1) + + # should be a no-op + convert_forward_solution( + fwd_out, surf_ori=True, force_fixed=False, copy=False, use_cps=use_cps + ) + assert fwd_out["surf_ori"] + assert not is_fixed_orient(fwd_out) + assert list(fwd_out["src"][0]["vertno"]).index(vert) == 0 + go3 = fwd_out["_orig_sol"][:, idx * 3 : idx * 3 + 3].copy() + gs3 = fwd_out["sol"]["data"][:, idx * 3 : idx * 3 + 3].copy() + assert_allclose(go3, go1) + assert_allclose(gs3, gs1) + + +@testing.requires_testing_data +@requires_mne +def test_average_forward_solution(tmp_path): + """Test averaging forward solutions.""" + fwd = read_forward_solution(fname_meeg) + # input not a list + pytest.raises(TypeError, average_forward_solutions, 1) + # list is too short + pytest.raises(ValueError, average_forward_solutions, []) + # negative weights + pytest.raises(ValueError, average_forward_solutions, [fwd, fwd], [-1, 0]) + # all zero weights + pytest.raises(ValueError, average_forward_solutions, [fwd, fwd], [0, 0]) + # weights not same length + pytest.raises(ValueError, average_forward_solutions, [fwd, fwd], [0, 0, 0]) + # list does not only have all dict() + pytest.raises(TypeError, average_forward_solutions, [1, fwd]) + + # try an easy case + fwd_copy = average_forward_solutions([fwd]) + assert isinstance(fwd_copy, Forward) + assert_array_equal(fwd["sol"]["data"], fwd_copy["sol"]["data"]) + + # modify a fwd solution, save it, use MNE to average with old one + fwd_copy["sol"]["data"] *= 0.5 + fname_copy = str(tmp_path / "copy-fwd.fif") + write_forward_solution(fname_copy, fwd_copy, overwrite=True) + cmd = ( + "mne_average_forward_solutions", + "--fwd", + fname_meeg, + "--fwd", + fname_copy, + "--out", + fname_copy, + ) + run_subprocess(cmd) + + # now let's actually do it, with one filename and one fwd + fwd_ave = average_forward_solutions([fwd, fwd_copy]) + assert_array_equal(0.75 * fwd["sol"]["data"], fwd_ave["sol"]["data"]) + # fwd_ave_mne = read_forward_solution(fname_copy) + # assert_array_equal(fwd_ave_mne['sol']['data'], fwd_ave['sol']['data']) + + # with gradient + fwd = read_forward_solution(fname_meeg_grad) + fwd_ave = average_forward_solutions([fwd, fwd]) + assert_forward_allclose(fwd, fwd_ave) + + +@testing.requires_testing_data +def test_priors(): + """Test prior computations.""" + # Depth prior + fwd = read_forward_solution(fname_meeg) + assert not is_fixed_orient(fwd) + n_sources = fwd["nsource"] + info = read_info(fname_evoked) + depth_prior = compute_depth_prior(fwd, info, exp=0.8) + assert depth_prior.shape == (3 * n_sources,) + depth_prior = compute_depth_prior(fwd, info, exp=0.0) + assert_array_equal(depth_prior, 1.0) + with pytest.raises(ValueError, match='must be "whiten"'): + compute_depth_prior(fwd, info, limit_depth_chs="foo") + with pytest.raises(ValueError, match="noise_cov must be a Covariance"): + compute_depth_prior(fwd, info, limit_depth_chs="whiten") + fwd_fixed = convert_forward_solution(fwd, force_fixed=True) + depth_prior = compute_depth_prior(fwd_fixed, info=info) + assert depth_prior.shape == (n_sources,) + # Orientation prior + orient_prior = compute_orient_prior(fwd, 1.0) + assert_array_equal(orient_prior, 1.0) + orient_prior = compute_orient_prior(fwd_fixed, 0.0) + assert_array_equal(orient_prior, 1.0) + with pytest.raises(ValueError, match="oriented in surface coordinates"): + compute_orient_prior(fwd, 0.5) + fwd_surf_ori = convert_forward_solution(fwd, surf_ori=True) + orient_prior = compute_orient_prior(fwd_surf_ori, 0.5) + assert all(np.isin(orient_prior, (0.5, 1.0))) + with pytest.raises(ValueError, match="between 0 and 1"): + compute_orient_prior(fwd_surf_ori, -0.5) + with pytest.raises(ValueError, match="with fixed orientation"): + compute_orient_prior(fwd_fixed, 0.5) + + +@testing.requires_testing_data +def test_equalize_channels(): + """Test equalization of channels for instances of Forward.""" + fwd1 = read_forward_solution(fname_meeg) + pick_channels_forward(fwd1, include=["EEG 001", "EEG 002", "EEG 003"], copy=False) + fwd2 = pick_channels_forward(fwd1, include=["EEG 002", "EEG 001"], ordered=True) + fwd1, fwd2 = equalize_channels([fwd1, fwd2]) + assert fwd1.ch_names == ["EEG 001", "EEG 002"] + assert fwd2.ch_names == ["EEG 001", "EEG 002"] diff --git a/mne-python/source/mne/forward/tests/test_make_forward.py b/mne-python/source/mne/forward/tests/test_make_forward.py new file mode 100644 index 0000000000000000000000000000000000000000..9e94f0cbd442e577d10b0a18f6c33c2d5b432f12 --- /dev/null +++ b/mne-python/source/mne/forward/tests/test_make_forward.py @@ -0,0 +1,946 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from itertools import product +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_equal, assert_array_less + +from mne import ( + convert_forward_solution, + create_info, + get_volume_labels_from_aseg, + make_forward_solution, + make_sphere_model, + pick_info, + pick_types, + pick_types_forward, + read_cov, + read_dipole, + read_evokeds, + read_forward_solution, + read_source_spaces, + setup_volume_source_space, + write_forward_solution, +) +from mne._fiff.constants import FIFF +from mne.bem import make_bem_solution, read_bem_surfaces +from mne.channels import make_standard_montage +from mne.datasets import testing +from mne.dipole import Dipole, fit_dipole +from mne.forward import Forward, _do_forward_solution, use_coil_def +from mne.forward._compute_forward import _magnetic_dipole_field_vec +from mne.forward._make_forward import ( + _create_meg_coils, + _ForwardModeler, + make_forward_dipole, +) +from mne.forward.tests.test_forward import assert_forward_allclose +from mne.io import read_info, read_raw_bti, read_raw_fif, read_raw_kit +from mne.simulation import simulate_evoked +from mne.source_estimate import VolSourceEstimate +from mne.source_space._source_space import ( + _compare_source_spaces, + setup_source_space, + write_source_spaces, +) +from mne.surface import _get_ico_surface +from mne.transforms import Transform, apply_trans, invert_transform +from mne.utils import ( + _record_warnings, + catch_logging, + requires_mne, + requires_mne_mark, + requires_openmeeg_mark, + run_subprocess, +) + +data_path = testing.data_path(download=False) +fname_meeg = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" +fname_raw = Path(__file__).parents[2] / "io" / "tests" / "data" / "test_raw.fif" +fname_evo = data_path / "MEG" / "sample" / "sample_audvis_trunc-ave.fif" +fname_cov = data_path / "MEG" / "sample" / "sample_audvis_trunc-cov.fif" +fname_dip = data_path / "MEG" / "sample" / "sample_audvis_trunc_set1.dip" +fname_trans = data_path / "MEG" / "sample" / "sample_audvis_trunc-trans.fif" +subjects_dir = data_path / "subjects" +fname_src = subjects_dir / "sample" / "bem" / "sample-oct-4-src.fif" +fname_bem = subjects_dir / "sample" / "bem" / "sample-1280-1280-1280-bem-sol.fif" +fname_aseg = subjects_dir / "sample" / "mri" / "aseg.mgz" +fname_bem_meg = subjects_dir / "sample" / "bem" / "sample-1280-bem-sol.fif" + +io_path = Path(__file__).parents[2] / "io" +bti_dir = io_path / "bti" / "tests" / "data" +kit_dir = io_path / "kit" / "tests" / "data" +trans_path = kit_dir / "trans-sample.fif" +fname_ctf_raw = io_path / "tests" / "data" / "test_ctf_comp_raw.fif" + + +def _col_corrs(a, b): + """Compute correlation between paired columns, being careful about 0.""" + a = a - a.mean(0) + b = b - b.mean(0) + num = (a * b).mean(0) + a_std = np.sqrt((a * a).mean(0)) + b_std = np.sqrt((b * b).mean(0)) + all_zero = (a_std == 0) & (b_std == 0) + num[all_zero] = 1.0 + a_std[all_zero] = 1.0 + b_std[all_zero] = 1.0 + return num / (a_std * b_std) + + +def _rdm(a, b): + """Compute the ratio of norms, being careful about 0.""" + a_norm = np.linalg.norm(a, axis=0) + b_norm = np.linalg.norm(b, axis=0) + all_zero = (a_norm == 0) & (b_norm == 0) + a_norm[all_zero] = 1.0 + b_norm[all_zero] = 1.0 + return a_norm / b_norm + + +def _compare_forwards( + fwd, + fwd_py, + n_sensors, + n_src, + meg_rtol=1e-4, + meg_atol=1e-9, + meg_corr_tol=0.99, + meg_rdm_tol=0.01, + eeg_rtol=1e-3, + eeg_atol=1e-3, + eeg_corr_tol=0.99, + eeg_rdm_tol=0.01, +): + """Test forwards.""" + # check source spaces + assert len(fwd["src"]) == len(fwd_py["src"]) + _compare_source_spaces(fwd["src"], fwd_py["src"], mode="approx") + for surf_ori, force_fixed in product([False, True], [False, True]): + # use copy here to leave our originals unmodified + fwd = convert_forward_solution( + fwd, surf_ori, force_fixed, copy=True, use_cps=True + ) + fwd_py = convert_forward_solution( + fwd_py, surf_ori, force_fixed, copy=True, use_cps=True + ) + check_src = n_src // 3 if force_fixed else n_src + + for key in ( + "nchan", + "source_rr", + "source_ori", + "surf_ori", + "coord_frame", + "nsource", + ): + assert_allclose(fwd_py[key], fwd[key], rtol=1e-4, atol=1e-7, err_msg=key) + # In surf_ori=True only Z matters for source_nn + if surf_ori and not force_fixed: + ori_sl = slice(2, None, 3) + else: + ori_sl = slice(None) + assert_allclose( + fwd_py["source_nn"][ori_sl], fwd["source_nn"][ori_sl], rtol=1e-4, atol=1e-6 + ) + assert_allclose( + fwd_py["mri_head_t"]["trans"], + fwd["mri_head_t"]["trans"], + rtol=1e-5, + atol=1e-8, + ) + + assert fwd_py["sol"]["data"].shape == (n_sensors, check_src) + assert len(fwd["sol"]["row_names"]) == n_sensors + assert len(fwd_py["sol"]["row_names"]) == n_sensors + + # check MEG + fwd_meg = fwd["sol"]["data"][:306, ori_sl] + fwd_meg_py = fwd_py["sol"]["data"][:306, ori_sl] + assert_allclose( + fwd_meg, fwd_meg_py, rtol=meg_rtol, atol=meg_atol, err_msg="MEG mismatch" + ) + meg_corrs = _col_corrs(fwd_meg, fwd_meg_py) + assert_array_less(meg_corr_tol, meg_corrs, err_msg="MEG corr/MAG") + meg_rdm = _rdm(fwd_meg, fwd_meg_py) + assert_allclose(meg_rdm, 1, atol=meg_rdm_tol, err_msg="MEG RDM") + # check EEG + if fwd["sol"]["data"].shape[0] > 306: + fwd_eeg = fwd["sol"]["data"][306:, ori_sl] + fwd_eeg_py = fwd["sol"]["data"][306:, ori_sl] + assert_allclose( + fwd_eeg, + fwd_eeg_py, + rtol=eeg_rtol, + atol=eeg_atol, + err_msg="EEG mismatch", + ) + # To test so-called MAG we use correlation (related to cosine + # similarity) and also RDM to test the amplitude mismatch + eeg_corrs = _col_corrs(fwd_eeg, fwd_eeg_py) + assert_array_less(eeg_corr_tol, eeg_corrs, err_msg="EEG corr/MAG") + eeg_rdm = _rdm(fwd_eeg, fwd_eeg_py) + assert_allclose(eeg_rdm, 1, atol=eeg_rdm_tol, err_msg="EEG RDM") + + +def test_magnetic_dipole(): + """Test basic magnetic dipole forward calculation.""" + info = read_info(fname_raw) + picks = pick_types(info, meg=True, eeg=False, exclude=[]) + info = pick_info(info, picks[:12]) + coils = _create_meg_coils(info["chs"], "normal", None) + # magnetic dipole far (meters!) from device origin + r0 = np.array([0.0, 13.0, -6.0]) + for ch, coil in zip(info["chs"], coils): + rr = (ch["loc"][:3] + r0) / 2.0 # get halfway closer + far_fwd = _magnetic_dipole_field_vec(r0[np.newaxis, :], [coil]) + near_fwd = _magnetic_dipole_field_vec(rr[np.newaxis, :], [coil]) + ratio = 8.0 if ch["ch_name"][-1] == "1" else 16.0 # grad vs mag + assert_allclose(np.median(near_fwd / far_fwd), ratio, atol=1e-1) + # degenerate case + r0 = coils[0]["rmag"][[0]] + with pytest.raises(RuntimeError, match="Coil too close"): + _magnetic_dipole_field_vec(r0, coils[:1]) + with _record_warnings(), pytest.warns(RuntimeWarning, match="Coil too close"): + fwd = _magnetic_dipole_field_vec(r0, coils[:1], too_close="warning") + assert not np.isfinite(fwd).any() + with np.errstate(invalid="ignore"): + fwd = _magnetic_dipole_field_vec(r0, coils[:1], too_close="info") + assert not np.isfinite(fwd).any() + + +@pytest.mark.slowtest # slow-ish on Travis OSX +@requires_mne +def test_make_forward_solution_kit(tmp_path, fname_src_small): + """Test making fwd using KIT (compensated) files.""" + sqd_path = kit_dir / "test.sqd" + mrk_path = kit_dir / "test_mrk.sqd" + elp_path = kit_dir / "test_elp.txt" + hsp_path = kit_dir / "test_hsp.txt" + fname_kit_raw = kit_dir / "test_bin_raw.fif" + + # first use mne-C: convert file, make forward solution + fwd = _do_forward_solution( + "sample", + fname_kit_raw, + src=fname_src_small, + bem=fname_bem_meg, + mri=trans_path, + eeg=False, + meg=True, + subjects_dir=subjects_dir, + ) + assert isinstance(fwd, Forward) + + # now let's use python with the same raw file + src = read_source_spaces(fname_src_small) + fwd_py = make_forward_solution( + fname_kit_raw, trans_path, src, fname_bem_meg, eeg=False, meg=True + ) + _compare_forwards(fwd, fwd_py, 157, n_src_small) + assert isinstance(fwd_py, Forward) + + # now let's use mne-python all the way + raw_py = read_raw_kit(sqd_path, mrk_path, elp_path, hsp_path) + # without ignore_ref=True, this should throw an error: + with pytest.raises(NotImplementedError, match="Cannot.*KIT reference"): + make_forward_solution( + raw_py.info, + src=src, + eeg=False, + meg=True, + bem=fname_bem_meg, + trans=trans_path, + ) + + # check that asking for eeg channels (even if they don't exist) is handled + meg_only_info = pick_info(raw_py.info, pick_types(raw_py.info, meg=True, eeg=False)) + fwd_py = make_forward_solution( + meg_only_info, + src=src, + meg=True, + eeg=True, + bem=fname_bem_meg, + trans=trans_path, + ignore_ref=True, + ) + _compare_forwards(fwd, fwd_py, 157, n_src_small, meg_rtol=1e-3, meg_atol=1e-7) + + # NEW TEST: ensure kit_system_id survives the forward-info rewrite + assert "kit_system_id" in fwd_py["info"] + + +@requires_mne +def test_make_forward_solution_bti(fname_src_small): + """Test BTI end-to-end versus C.""" + bti_pdf = bti_dir / "test_pdf_linux" + bti_config = bti_dir / "test_config_linux" + bti_hs = bti_dir / "test_hs_linux" + fname_bti_raw = bti_dir / "exported4D_linux_raw.fif" + raw_py = read_raw_bti(bti_pdf, bti_config, bti_hs, preload=False) + src = read_source_spaces(fname_src_small) + fwd_py = make_forward_solution( + raw_py.info, src=src, eeg=False, meg=True, bem=fname_bem_meg, trans=trans_path + ) + fwd = _do_forward_solution( + "sample", + fname_bti_raw, + src=fname_src_small, + bem=fname_bem_meg, + mri=trans_path, + eeg=False, + meg=True, + subjects_dir=subjects_dir, + ) + _compare_forwards(fwd, fwd_py, 248, n_src_small) + + +@pytest.mark.parametrize( + "other", + [ + pytest.param("MNE-C", marks=requires_mne_mark()), + pytest.param( + "openmeeg", + marks=[requires_openmeeg_mark(), pytest.mark.slowtest], + ), + ], +) +def test_make_forward_solution_ctf(tmp_path, fname_src_small, other): + """Test CTF w/compensation against MNE-C or OpenMEEG.""" + pytest.importorskip("nibabel") + src = read_source_spaces(fname_src_small) + raw = read_raw_fif(fname_ctf_raw) + assert raw.compensation_grade == 3 + if other == "openmeeg": + mindist = 20.0 + n_src_want = 51 + else: + assert other == "MNE-C" + mindist = 0.0 + n_src_want = n_src_small + assert n_src_want == 108 + mindist = 20.0 if other == "openmeeg" else 0.0 + fwd_py = make_forward_solution( + fname_ctf_raw, + fname_trans, + src, + fname_bem_meg, + eeg=False, + mindist=mindist, + verbose=True, + ) + + if other == "openmeeg": + # TODO: This should be a 1-layer, but it's broken + # (some correlations become negative!)... + bem_surfaces = read_bem_surfaces(fname_bem) # fname_bem_meg + bem = make_bem_solution(bem_surfaces, solver="openmeeg") + # TODO: These tolerances are bad + tol_kwargs = dict(meg_atol=1, meg_corr_tol=0.65, meg_rdm_tol=0.6) + fwd = make_forward_solution( + fname_ctf_raw, + fname_trans, + src, + bem, + eeg=False, + mindist=mindist, + verbose=True, + ) + else: + assert other == "MNE-C" + bem = None + tol_kwargs = dict() + fwd = _do_forward_solution( + "sample", + fname_ctf_raw, + mri=fname_trans, + src=fname_src_small, + bem=fname_bem_meg, + eeg=False, + meg=True, + subjects_dir=subjects_dir, + mindist=mindist, + ) + _compare_forwards(fwd, fwd_py, 274, n_src_want, **tol_kwargs) + + # CTF with compensation changed in python + ctf_raw = read_raw_fif(fname_ctf_raw) + ctf_raw.info["bads"] = ["MRO24-2908"] # test that it works with some bads + ctf_raw.apply_gradient_compensation(2) + + fwd_py = make_forward_solution( + ctf_raw.info, + fname_trans, + src, + fname_bem_meg, + eeg=False, + meg=True, + mindist=mindist, + ) + if other == "openmeeg": + assert bem is not None + fwd = make_forward_solution( + ctf_raw.info, + fname_trans, + src, + bem, + eeg=False, + mindist=mindist, + verbose=True, + ) + else: + fwd = _do_forward_solution( + "sample", + ctf_raw, + mri=fname_trans, + src=fname_src_small, + bem=fname_bem_meg, + eeg=False, + meg=True, + subjects_dir=subjects_dir, + mindist=mindist, + ) + _compare_forwards(fwd, fwd_py, 274, n_src_want, **tol_kwargs) + + fname_temp = tmp_path / "test-ctf-fwd.fif" + write_forward_solution(fname_temp, fwd_py) + fwd_py2 = read_forward_solution(fname_temp) + _compare_forwards(fwd_py, fwd_py2, 274, n_src_want, **tol_kwargs) + repr(fwd_py) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_make_forward_solution_basic(): + """Test making M-EEG forward solution from python.""" + with catch_logging() as log: + # make sure everything can be path-like (gh #10872) + fwd_py = make_forward_solution( + Path(fname_raw), + Path(fname_trans), + Path(fname_src), + Path(fname_bem), + mindist=5.0, + verbose=True, + ) + log = log.getvalue() + assert "Total 258/258 points inside the surface" in log + assert isinstance(fwd_py, Forward) + fwd = read_forward_solution(fname_meeg) + assert isinstance(fwd, Forward) + _compare_forwards(fwd, fwd_py, 366, 1494, meg_rtol=1e-3) + # Homogeneous model + with pytest.raises(RuntimeError, match="homogeneous.*1-layer.*EEG"): + make_forward_solution(fname_raw, fname_trans, fname_src, fname_bem_meg) + + +@pytest.mark.slowtest +@requires_openmeeg_mark() +@pytest.mark.parametrize( + "n_layers", + [ + 3, + pytest.param(1, marks=pytest.mark.xfail(raises=RuntimeError)), + ], +) +@testing.requires_testing_data +def test_make_forward_solution_openmeeg(n_layers): + """Test making M-EEG forward solution from OpenMEEG.""" + solver = "openmeeg" + bem_surfaces = read_bem_surfaces(fname_bem) + raw = read_raw_fif(fname_raw) + n_sensors = 366 + ch_types = ["eeg", "meg"] + if n_layers == 1: + ch_types = ["meg"] + bem_surfaces = bem_surfaces[-1:] + assert bem_surfaces[0]["id"] == FIFF.FIFFV_BEM_SURF_ID_BRAIN + n_sensors = 306 + raw.pick(ch_types) + n_sources_kept = 501 // 3 + fwds = dict() + for solver in ["openmeeg", "mne"]: + bem = make_bem_solution(bem_surfaces, solver=solver) + assert bem["solver"] == solver + with catch_logging() as log: + # make sure everything can be path-like (gh #10872) + fwd = make_forward_solution( + raw.info, + Path(fname_trans), + Path(fname_src), + bem, + mindist=20.0, + verbose=True, + ) + log = log.getvalue() + assert "Total 258/258 points inside the surface" in log + assert isinstance(fwd, Forward) + fwds[solver] = fwd + del fwd + _compare_forwards( + fwds["openmeeg"], + fwds["mne"], + n_sensors, + n_sources_kept * 3, + meg_atol=1, + eeg_atol=100, + meg_corr_tol=0.98, + eeg_corr_tol=0.98, + meg_rdm_tol=0.11, + eeg_rdm_tol=0.2, + ) + + +def test_make_forward_solution_discrete(tmp_path, small_surf_src): + """Test making and converting a forward solution with discrete src.""" + # smoke test for depth weighting and discrete source spaces + src = small_surf_src + src = src + setup_volume_source_space( + pos=dict( + rr=src[0]["rr"][src[0]["vertno"][:3]].copy(), + nn=src[0]["nn"][src[0]["vertno"][:3]].copy(), + ) + ) + sphere = make_sphere_model() + fwd = make_forward_solution( + fname_raw, fname_trans, src, sphere, meg=True, eeg=False + ) + convert_forward_solution(fwd, surf_ori=True) + + +n_src_small = 108 # this is the resulting # of verts in fwd + + +@pytest.fixture(scope="module", params=[testing._pytest_param()]) +def small_surf_src(): + """Create a small surface source space.""" + pytest.importorskip("nibabel") + src = setup_source_space( + "sample", "oct2", subjects_dir=subjects_dir, add_dist=False + ) + assert sum(s["nuse"] for s in src) * 3 == n_src_small + return src + + +@pytest.fixture() +def fname_src_small(tmp_path, small_surf_src): + """Create a small source space.""" + fname_src_small = tmp_path / "sample-oct-2-src.fif" + write_source_spaces(fname_src_small, small_surf_src) + return fname_src_small + + +@requires_mne +@pytest.mark.timeout(90) # can take longer than 60 s on Travis +def test_make_forward_solution_sphere(tmp_path, fname_src_small): + """Test making a forward solution with a sphere model.""" + out_name = tmp_path / "tmp-fwd.fif" + run_subprocess( + [ + "mne_forward_solution", + "--meg", + "--eeg", + "--meas", + fname_raw, + "--src", + fname_src_small, + "--mri", + fname_trans, + "--fwd", + out_name, + ] + ) + fwd = read_forward_solution(out_name) + sphere = make_sphere_model( + head_radius=0.1, + relative_radii=(0.95, 0.97, 0.98, 1), + verbose=True, + ) + src = read_source_spaces(fname_src_small) + fwd_py = make_forward_solution( + fname_raw, fname_trans, src, sphere, meg=True, eeg=True, verbose=True + ) + _compare_forwards( + fwd, + fwd_py, + 366, + 108, + meg_rtol=5e-1, + meg_atol=1e-6, + eeg_rtol=5e-1, + eeg_atol=5e-1, + ) + # Since the above is pretty lax, let's check a different way + for meg, eeg in zip([True, False], [False, True]): + fwd_ = pick_types_forward(fwd, meg=meg, eeg=eeg) + fwd_py_ = pick_types_forward(fwd, meg=meg, eeg=eeg) + assert_allclose( + np.corrcoef(fwd_["sol"]["data"].ravel(), fwd_py_["sol"]["data"].ravel())[ + 0, 1 + ], + 1.0, + rtol=1e-3, + ) + + # Number of layers in the sphere model doesn't matter for MEG + # (as long as no sources are omitted due to distance) + assert len(sphere["layers"]) == 4 + fwd = make_forward_solution( + fname_raw, fname_trans, src, sphere, meg=True, eeg=False + ) + sphere_1 = make_sphere_model(head_radius=None) + assert len(sphere_1["layers"]) == 0 + assert_array_equal(sphere["r0"], sphere_1["r0"]) + fwd_1 = make_forward_solution( + fname_raw, fname_trans, src, sphere, meg=True, eeg=False + ) + _compare_forwards(fwd, fwd_1, 306, 108, meg_rtol=1e-12, meg_atol=1e-12) + # Homogeneous model + sphere = make_sphere_model(head_radius=None) + with pytest.raises(RuntimeError, match="zero shells.*EEG"): + make_forward_solution(fname_raw, fname_trans, src, sphere) + + # Since the spherical model is defined in head space, the head->MRI transform should + # not matter for the check that MEG sensors are outside the sphere. + custom_trans = Transform("head", "mri") + custom_trans["trans"][0, 3] = 0.05 # move MEG sensors close to mesh + sphere = make_sphere_model() + fwd = make_forward_solution(fname_raw, custom_trans, src, sphere) + assert fwd["mri_head_t"]["trans"][0, 3] == -0.05 + + +def test_make_forward_sphere_exclude(): + """Test that points are excluded that are outside BEM sphere inner layer.""" + r0 = (0.0, 0.0, 0.04) + inner_radius = 0.08 + head_radius = inner_radius / 0.9 # relative_radii[0] for make_sphere model + bem = make_sphere_model(r0=r0, head_radius=head_radius) + # construct our source space using a sphere the size of the inner (brain) radius, + # with a 1mm exclude zone to avoid numerical issues + src = setup_volume_source_space( + pos=10.0, + sphere=r0 + (inner_radius,), + mindist=1, # use >0 to avoid any numerical issues + exclude=10, + ) + assert src[0]["nuse"] == 2102 # empirically determined + trans = Transform("mri", "head") # identity for simplicity + raw = read_raw_fif(fname_raw) + raw.pick(raw.ch_names[:1]) + fwd = make_forward_solution(raw.info, trans, src, bem, mindist=0) + assert fwd["nsource"] == src[0]["nuse"] + bem_small = make_sphere_model(r0=r0, head_radius=head_radius - 0.01 / 0.9) + fwd_small = make_forward_solution(raw.info, trans, src, bem_small, mindist=0) + assert fwd_small["nsource"] < src[0]["nuse"] + idx = np.searchsorted(fwd["src"][0]["vertno"], fwd_small["src"][0]["vertno"]) + fwd_data = np.reshape(fwd["sol"]["data"], (len(raw.ch_names), -1, 3)) + fwd_small_data = np.reshape(fwd_small["sol"]["data"], (len(raw.ch_names), -1, 3)) + assert_allclose(fwd_data[:, idx], fwd_small_data) + # again to avoid numerical issues, make this close + fwd_small_2 = make_forward_solution(raw.info, trans, src, bem, mindist=9.999) + assert fwd_small_2["nsource"] == fwd_small["nsource"] + fwd_small_2_data = np.reshape( + fwd_small_2["sol"]["data"], (len(raw.ch_names), -1, 3) + ) + assert_allclose(fwd_small_data, fwd_small_2_data) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_forward_mixed_source_space(tmp_path): + """Test making the forward solution for a mixed source space.""" + pytest.importorskip("nibabel") + # get the surface source space + rng = np.random.RandomState(0) + surf = read_source_spaces(fname_src) + + # setup two volume source spaces + label_names = get_volume_labels_from_aseg(fname_aseg) + vol_labels = rng.choice(label_names, 2) + with pytest.warns(RuntimeWarning, match="Found no usable.*CC_Mid_Ant.*"): + vol1 = setup_volume_source_space( + "sample", + pos=20.0, + mri=fname_aseg, + volume_label=vol_labels[0], + add_interpolator=False, + ) + vol2 = setup_volume_source_space( + "sample", + pos=20.0, + mri=fname_aseg, + volume_label=vol_labels[1], + add_interpolator=False, + ) + + # merge surfaces and volume + src = surf + vol1 + vol2 + + # calculate forward solution + fwd = make_forward_solution(fname_raw, fname_trans, src, fname_bem) + assert repr(fwd) + + # extract source spaces + src_from_fwd = fwd["src"] + + # get the coordinate frame of each source space + coord_frames = np.array([s["coord_frame"] for s in src_from_fwd]) + + # assert that all source spaces are in head coordinates + assert (coord_frames == FIFF.FIFFV_COORD_HEAD).all() + + # run tests for SourceSpaces.export_volume + fname_img = tmp_path / "temp-image.mgz" + + # head coordinates and mri_resolution, but trans file + with pytest.raises(ValueError, match="trans containing mri to head"): + src_from_fwd.export_volume(fname_img, mri_resolution=True, trans=None) + + # head coordinates and mri_resolution, but wrong trans file + vox_mri_t = vol1[0]["vox_mri_t"] + with pytest.raises(ValueError, match="head<->mri, got mri_voxel->mri"): + src_from_fwd.export_volume(fname_img, mri_resolution=True, trans=vox_mri_t) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_make_forward_dipole(tmp_path): + """Test forward-projecting dipoles.""" + rng = np.random.RandomState(0) + + evoked = read_evokeds(fname_evo)[0] + cov = read_cov(fname_cov) + cov["projs"] = [] # avoid proj warning + dip_c = read_dipole(fname_dip) + + # Only use magnetometers for speed! + picks = pick_types(evoked.info, meg="mag", eeg=False)[::8] + evoked.pick([evoked.ch_names[p] for p in picks]) + evoked.info.normalize_proj() + info = evoked.info + + # Make new Dipole object with n_test_dipoles picked from the dipoles + # in the test dataset. + n_test_dipoles = 3 # minimum 3 needed to get uneven sampling in time + dipsel = np.sort(rng.permutation(np.arange(len(dip_c)))[:n_test_dipoles]) + dip_test = Dipole( + times=dip_c.times[dipsel], + pos=dip_c.pos[dipsel], + amplitude=dip_c.amplitude[dipsel], + ori=dip_c.ori[dipsel], + gof=dip_c.gof[dipsel], + ) + + sphere = make_sphere_model(head_radius=0.1) + + # Warning emitted due to uneven sampling in time + with pytest.warns(RuntimeWarning, match="unevenly spaced"): + fwd, stc = make_forward_dipole(dip_test, sphere, info, trans=fname_trans) + + # stc is list of VolSourceEstimate's + assert isinstance(stc, list) + for n_dip in range(n_test_dipoles): + assert isinstance(stc[n_dip], VolSourceEstimate) + + # Now simulate evoked responses for each of the test dipoles, + # and fit dipoles to them (sphere model, MEG and EEG) + times, pos, amplitude, ori, gof = [], [], [], [], [] + nave = 400 # add a tiny amount of noise to the simulated evokeds + for s in stc: + evo_test = simulate_evoked(fwd, s, info, cov, nave=nave, random_state=rng) + # evo_test.add_proj(make_eeg_average_ref_proj(evo_test.info)) + dfit, resid = fit_dipole(evo_test, cov, sphere, None) + times += dfit.times.tolist() + pos += dfit.pos.tolist() + amplitude += dfit.amplitude.tolist() + ori += dfit.ori.tolist() + gof += dfit.gof.tolist() + + # Create a new Dipole object with the dipole fits + dip_fit = Dipole(times, pos, amplitude, ori, gof) + + # check that true (test) dipoles and fits are "close" + # cf. mne/tests/test_dipole.py + diff = dip_test.pos - dip_fit.pos + corr = np.corrcoef(dip_test.pos.ravel(), dip_fit.pos.ravel())[0, 1] + dist = np.sqrt(np.mean(np.sum(diff * diff, axis=1))) + gc_dist = ( + 180 / np.pi * np.mean(np.arccos(np.sum(dip_test.ori * dip_fit.ori, axis=1))) + ) + amp_err = np.sqrt(np.mean((dip_test.amplitude - dip_fit.amplitude) ** 2)) + + # Make sure each coordinate is close to reference + # NB tolerance should be set relative to snr of simulated evoked! + assert_allclose( + dip_fit.pos, dip_test.pos, rtol=0, atol=1.5e-2, err_msg="position mismatch" + ) + assert dist < 1e-2 # within 1 cm + assert corr > 0.98 + assert gc_dist < 20 # less than 20 degrees + assert amp_err < 10e-9 # within 10 nAm + + # Make sure rejection works with BEM: one dipole at z=1m + # NB _make_forward.py:_prepare_for_forward will raise a RuntimeError + # if no points are left after min_dist exclusions, hence 2 dips here! + dip_outside = Dipole( + times=[0.0, 0.001], + pos=[[0.0, 0.0, 1.0], [0.0, 0.0, 0.040]], + amplitude=[100e-9, 100e-9], + ori=[[1.0, 0.0, 0.0], [1.0, 0.0, 0.0]], + gof=1, + ) + with pytest.raises(ValueError, match="outside the inner skull"): + make_forward_dipole(dip_outside, fname_bem, info, fname_trans) + # if we get this far, can safely assume the code works with BEMs too + # -> use sphere again below for speed + + # Now make an evenly sampled set of dipoles, some simultaneous, + # should return a VolSourceEstimate regardless + times = [0.0, 0.0, 0.0, 0.001, 0.001, 0.002] + pos = np.random.rand(6, 3) * 0.020 + np.array([0.0, 0.0, 0.040])[np.newaxis, :] + amplitude = np.random.rand(6) * 100e-9 + ori = np.eye(6, 3) + np.eye(6, 3, -3) + gof = np.arange(len(times)) / len(times) # arbitrary + + dip_even_samp = Dipole(times, pos, amplitude, ori, gof) + + # I/O round-trip + fname = str(tmp_path / "test-fwd.fif") + with pytest.warns(RuntimeWarning, match="free orientation"): + write_forward_solution(fname, fwd) + fwd_read = convert_forward_solution(read_forward_solution(fname), force_fixed=True) + assert_forward_allclose(fwd, fwd_read, rtol=1e-6) + + fwd, stc = make_forward_dipole(dip_even_samp, sphere, info, trans=fname_trans) + assert isinstance(stc, VolSourceEstimate) + assert_allclose(stc.times, np.arange(0.0, 0.003, 0.001)) + + # Test passing a list of Dipoles instead of a single Dipole object + fwd2, stc2 = make_forward_dipole( + [dip_even_samp[0], dip_even_samp[1:]], sphere, info, trans=fname_trans + ) + assert_array_equal(fwd["sol"]["data"], fwd2["sol"]["data"]) + assert_array_equal(stc.data, stc2.data) + + +@testing.requires_testing_data +def test_make_forward_no_meg(tmp_path): + """Test that we can make and I/O forward solution with no MEG channels.""" + pos = dict(rr=[[0.05, 0, 0]], nn=[[0, 0, 1.0]]) + src = setup_volume_source_space(pos=pos) + bem = make_sphere_model() + trans = None + montage = make_standard_montage("standard_1020") + info = create_info(["Cz"], 1000.0, "eeg").set_montage(montage) + fwd = make_forward_solution(info, trans, src, bem) + fname = tmp_path / "test-fwd.fif" + write_forward_solution(fname, fwd) + fwd_read = read_forward_solution(fname) + assert_allclose(fwd["sol"]["data"], fwd_read["sol"]["data"]) + + +def test_use_coil_def(tmp_path): + """Test use_coil_def.""" + info = create_info(1, 1000.0, "mag") + info["chs"][0]["coil_type"] = 9999 + info["chs"][0]["loc"][:] = [0, 0, 0.02, 1, 0, 0, 0, 1, 0, 0, 0, 1] + info["dev_head_t"] = Transform("meg", "head") + sphere = make_sphere_model((0.0, 0.0, 0.0), 0.01) + src = setup_volume_source_space(pos=5, sphere=sphere) + trans = Transform("head", "mri", None) + with pytest.raises(RuntimeError, match="coil definition not found"): + make_forward_solution(info, trans, src, sphere) + coil_fname = tmp_path / "coil_def.dat" + with open(coil_fname, "w") as fid: + fid.write( + """# custom cube coil def +1 9999 2 8 3e-03 0.000e+00 "Test" + 0.1250 -0.750e-03 -0.750e-03 -0.750e-03 0.000 0.000""" + ) + with pytest.raises(RuntimeError, match="Could not interpret"): + with use_coil_def(coil_fname): + make_forward_solution(info, trans, src, sphere) + with open(coil_fname, "w") as fid: + fid.write( + """# custom cube coil def +1 9999 2 8 3e-03 0.000e+00 "Test" + 0.1250 -0.750e-03 -0.750e-03 -0.750e-03 0.000 0.000 1.000 + 0.1250 -0.750e-03 0.750e-03 -0.750e-03 0.000 0.000 1.000 + 0.1250 0.750e-03 -0.750e-03 -0.750e-03 0.000 0.000 1.000 + 0.1250 0.750e-03 0.750e-03 -0.750e-03 0.000 0.000 1.000 + 0.1250 -0.750e-03 -0.750e-03 0.750e-03 0.000 0.000 1.000 + 0.1250 -0.750e-03 0.750e-03 0.750e-03 0.000 0.000 1.000 + 0.1250 0.750e-03 -0.750e-03 0.750e-03 0.000 0.000 1.000 + 0.1250 0.750e-03 0.750e-03 0.750e-03 0.000 0.000 1.000""" + ) + with use_coil_def(coil_fname): + make_forward_solution(info, trans, src, sphere) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_sensors_inside_bem(): + """Test that sensors inside the BEM are problematic.""" + rr = _get_ico_surface(1)["rr"] + rr /= np.linalg.norm(rr, axis=1, keepdims=True) + rr *= 0.1 + assert len(rr) == 42 + info = create_info(len(rr), 1000.0, "mag") + info["dev_head_t"] = Transform("meg", "head", np.eye(4)) + for ii, ch in enumerate(info["chs"]): + ch["loc"][:] = np.concatenate((rr[ii], np.eye(3).ravel())) + trans = Transform("head", "mri", np.eye(4)) + trans["trans"][2, 3] = 0.03 + sphere_noshell = make_sphere_model((0.0, 0.0, 0.0), None) + sphere = make_sphere_model((0.0, 0.0, 0.0), 1.01) + with pytest.warns(RuntimeWarning, match=".* 15 MEG.*inside the scalp.*"): + fwd = make_forward_solution(info, trans, fname_src, fname_bem, on_inside="warn") + assert fwd["nsource"] == 516 + assert fwd["nchan"] == 42 + assert np.isfinite(fwd["sol"]["data"]).all() + make_forward_solution(info, trans, fname_src, fname_bem_meg) # okay + make_forward_solution(info, trans, fname_src, sphere_noshell) # okay + with pytest.raises(RuntimeError, match=".* 42 MEG.*outermost sphere sh.*"): + make_forward_solution(info, trans, fname_src, sphere) + sphere = make_sphere_model((0.0, 0.0, 0.0), 1.01) # weird, but okay + with pytest.raises(RuntimeError, match=".* 42 MEG.*the outermost sphere shell.*"): + make_forward_solution(info, trans, fname_src, sphere) + for ch in info["chs"]: + ch["loc"][:3] *= 0.1 + with pytest.raises(RuntimeError, match=".* 42 MEG.*the inner skull.*"): + make_forward_solution(info, trans, fname_src, fname_bem_meg) + + +def test_make_forward_iterative(): + """Test that points are excluded that are outside BEM sphere inner layer.""" + r0 = (0.0, 0.0, 0.04) + head_radius = 0.08 + bem = make_sphere_model(r0=r0, head_radius=head_radius) + src = setup_volume_source_space( + pos=10.0, + sphere=r0 + (head_radius,), + exclude=10, + ) + assert 500 < src[0]["nuse"] < 4000 + trans = Transform("mri", "head") + raw = read_raw_fif(fname_raw) + raw.pick(raw.ch_names[:2]) + fwd = make_forward_solution(raw.info, trans, src, bem, mindist=0, verbose=True) + # check against iterative version + fm = _ForwardModeler(raw.info, trans, bem) + fwd_iterative = fm.compute(src) + _compare_forwards(fwd, fwd_iterative, fwd["nchan"], 3 * fwd["nsource"]) + midpt = fwd["nsource"] // 2 + assert fwd["coord_frame"] == FIFF.FIFFV_COORD_HEAD + fwd_data = list() + rr = apply_trans(invert_transform(fwd["mri_head_t"]), fwd["source_rr"]) + nn = apply_trans(invert_transform(fwd["mri_head_t"]), fwd["source_nn"], move=False) + for sl in (slice(None, midpt), slice(midpt, None)): + ss = setup_volume_source_space(pos=dict(rr=rr[sl], nn=nn[sl])) + fwd_data.append(fm.compute(ss)["sol"]["data"]) + fwd_data = np.concatenate(fwd_data, axis=1) + assert_allclose(fwd_data, fwd["sol"]["data"]) diff --git a/mne-python/source/mne/gui/__init__.py b/mne-python/source/mne/gui/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c06c8dc993931318345da857237f89d9606bfc7a --- /dev/null +++ b/mne-python/source/mne/gui/__init__.py @@ -0,0 +1,8 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Convenience functions for opening GUIs.""" +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/gui/__init__.pyi b/mne-python/source/mne/gui/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..086c51a4904396847b95950c5c6c9b142dcfd37d --- /dev/null +++ b/mne-python/source/mne/gui/__init__.pyi @@ -0,0 +1,2 @@ +__all__ = ["_GUIScraper", "coregistration"] +from ._gui import _GUIScraper, coregistration diff --git a/mne-python/source/mne/gui/_coreg.py b/mne-python/source/mne/gui/_coreg.py new file mode 100644 index 0000000000000000000000000000000000000000..4004b9e6c396aff6c09ee017e33594339100ad76 --- /dev/null +++ b/mne-python/source/mne/gui/_coreg.py @@ -0,0 +1,2086 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import inspect +import os +import os.path as op +import platform +import queue +import re +import threading +import time +import weakref +from contextlib import contextmanager +from functools import partial +from pathlib import Path + +import numpy as np +from traitlets import Bool, Float, HasTraits, Instance, Unicode, observe + +from .._fiff.constants import FIFF +from .._fiff.meas_info import _empty_info, read_fiducials, read_info, write_fiducials +from .._fiff.open import dir_tree_find, fiff_open +from .._fiff.pick import pick_types +from ..bem import make_bem_solution, write_bem_solution +from ..channels import read_dig_fif +from ..coreg import ( + Coregistration, + _find_head_bem, + _is_mri_subject, + _map_fid_name_to_idx, + _mri_subject_has_bem, + bem_fname, + fid_fname, + scale_mri, +) +from ..defaults import DEFAULTS +from ..io._read_raw import _get_supported, read_raw +from ..surface import _CheckInside, _DistanceQuery +from ..transforms import ( + Transform, + _ensure_trans, + _get_trans, + _get_transforms_to_coord_frame, + read_trans, + rotation_angles, + write_trans, +) +from ..utils import ( + _check_fname, + _validate_type, + check_fname, + fill_doc, + get_subjects_dir, + logger, + verbose, +) +from ..viz._3d import ( + _plot_head_fiducials, + _plot_head_shape_points, + _plot_head_surface, + _plot_helmet, + _plot_hpi_coils, + _plot_mri_fiducials, + _plot_sensors_3d, +) +from ..viz.backends._utils import _qt_app_exec, _qt_safe_window +from ..viz.utils import safe_event + + +class _WorkerData: + def __init__(self, name, params=None): + self._name = name + self._params = params + + +def _get_subjects(sdir): + # XXX: would be nice to move this function to util + is_dir = sdir and op.isdir(sdir) + if is_dir: + dir_content = os.listdir(sdir) + subjects = [s for s in dir_content if _is_mri_subject(s, sdir)] + if len(subjects) == 0: + subjects.append("") + else: + subjects = [""] + return sorted(subjects) + + +@fill_doc +class CoregistrationUI(HasTraits): + """Class for coregistration assisted by graphical interface. + + Parameters + ---------- + info_file : None | path-like + The FIFF file with digitizer data for coregistration. + %(subject)s + %(subjects_dir)s + %(fiducials)s + head_resolution : bool + If ``True``, use a high-resolution head surface. Defaults to ``False``. + head_opacity : float + The opacity of the head surface. Defaults to ``0.8``. + hpi_coils : bool + If ``True``, display the HPI coils. Defaults to ``True``. + head_shape_points : bool + If ``True``, display the head shape points. Defaults to ``True``. + eeg_channels : bool + If ``True``, display the EEG channels. Defaults to ``True``. + meg_channels : bool + If ``True``, display the MEG channels. Defaults to ``False``. + fnirs_channels : bool + If ``True``, display the fNIRS channels. Defaults to ``True``. + orient_glyphs : bool + If ``True``, orient the sensors towards the head surface. Default to ``False``. + scale_by_distance : bool + If ``True``, scale the sensors based on their distance to the head surface. + Defaults to ``True``. + mark_inside : bool + If ``True``, mark the head shape points that are inside the head surface + with a different color. Defaults to ``True``. + sensor_opacity : float + The opacity of the sensors between ``0`` and ``1``. Defaults to ``1.``. + trans : path-like | Transform + The Head<->MRI transform or the path to its FIF file (``"-trans.fif"``). + size : tuple + The dimensions (width, height) of the rendering view. The default is + ``(800, 600)``. + bgcolor : tuple of float | str + The background color as a tuple (red, green, blue) of float + values between ``0`` and ``1`` or a valid color name (i.e. ``'white'`` + or ``'w'``). Defaults to ``'grey'``. + show : bool + Display the window as soon as it is ready. Defaults to ``True``. + block : bool + Whether to halt program execution until the GUI has been closed + (``True``) or not (``False``, default). + %(fullscreen)s + The default is ``False``. + + .. versionadded:: 1.1 + %(interaction_scene)s + Defaults to ``'terrain'``. + + .. versionadded:: 1.0 + %(verbose)s + + Attributes + ---------- + coreg : mne.coreg.Coregistration + The coregistration instance used by the graphical interface. + """ + + _subject = Unicode() + _subjects_dir = Unicode() + _lock_fids = Bool() + _current_fiducial = Unicode() + _info_file = Instance(Path, default_value=Path(".")) + _orient_glyphs = Bool() + _scale_by_distance = Bool() + _mark_inside = Bool() + _hpi_coils = Bool() + _head_shape_points = Bool() + _eeg_channels = Bool() + _meg_channels = Bool() + _fnirs_channels = Bool() + _head_resolution = Bool() + _head_opacity = Float() + _helmet = Bool() + _grow_hair = Float() + _subject_to = Unicode() + _scale_mode = Unicode() + _icp_fid_match = Unicode() + + @_qt_safe_window( + splash="_renderer.figure.splash", window="_renderer.figure.plotter" + ) + @verbose + def __init__( + self, + info_file, + *, + subject=None, + subjects_dir=None, + fiducials="auto", + head_resolution=None, + head_opacity=None, + hpi_coils=None, + head_shape_points=None, + eeg_channels=None, + meg_channels=None, + fnirs_channels=None, + orient_glyphs=None, + scale_by_distance=None, + mark_inside=None, + sensor_opacity=None, + trans=None, + size=None, + bgcolor=None, + show=True, + block=False, + fullscreen=False, + interaction="terrain", + verbose=None, + ): + from ..viz.backends.renderer import _get_renderer + + def _get_default(var, val): + return var if var is not None else val + + self._actors = dict() + self._surfaces = dict() + self._widgets = dict() + self._verbose = verbose + self._plot_locked = False + self._params_locked = False + self._refresh_rate_ms = max(int(round(1000.0 / 60.0)), 1) + self._redraws_pending = set() + self._parameter_mutex = threading.Lock() + self._redraw_mutex = threading.Lock() + self._job_queue = queue.Queue() + self._parameter_queue = queue.Queue() + self._head_geo = None + self._check_inside = None + self._nearest = None + self._coord_frame = "mri" + self._mouse_no_mvt = -1 + self._to_cf_t = None + self._omit_hsp_distance = 0.0 + self._fiducials_file = None + self._trans_modified = False + self._mri_fids_modified = False + self._mri_scale_modified = False + self._accept_close_event = True + self._fid_colors = tuple( + DEFAULTS["coreg"][f"{key}_color"] for key in ("lpa", "nasion", "rpa") + ) + self._defaults = dict( + size=_get_default(size, (800, 600)), + bgcolor=_get_default(bgcolor, "grey"), + orient_glyphs=_get_default(orient_glyphs, True), + scale_by_distance=_get_default(scale_by_distance, True), + mark_inside=_get_default(mark_inside, True), + hpi_coils=_get_default(hpi_coils, True), + head_shape_points=_get_default(head_shape_points, True), + eeg_channels=_get_default(eeg_channels, True), + meg_channels=_get_default(meg_channels, False), + fnirs_channels=_get_default(fnirs_channels, True), + head_resolution=_get_default(head_resolution, True), + head_opacity=_get_default(head_opacity, 0.8), + helmet=False, + sensor_opacity=_get_default(sensor_opacity, 1.0), + fiducials=("LPA", "Nasion", "RPA"), + fiducial="LPA", + lock_fids=True, + grow_hair=0.0, + subject_to="", + scale_modes=["None", "uniform", "3-axis"], + scale_mode="None", + icp_fid_matches=("nearest", "matched"), + icp_fid_match="matched", + icp_n_iterations=20, + omit_hsp_distance=10.0, + lock_head_opacity=self._head_opacity < 1.0, + weights=dict( + lpa=1.0, + nasion=10.0, + rpa=1.0, + hsp=1.0, + eeg=1.0, + hpi=1.0, + ), + ) + + # process requirements + info = None + subjects_dir = str( + get_subjects_dir(subjects_dir=subjects_dir, raise_error=True) + ) + subject = _get_default(subject, _get_subjects(subjects_dir)[0]) + + # setup the window + splash = "Initializing coregistration GUI..." if show else False + self._renderer = _get_renderer( + size=self._defaults["size"], + bgcolor=self._defaults["bgcolor"], + splash=splash, + fullscreen=fullscreen, + ) + self._renderer._window_close_connect(self._clean) + self._renderer._window_close_connect(self._close_callback, after=False) + self._renderer.set_interaction(interaction) + + # coregistration model setup + self._picking_targets = list() + self._immediate_redraw = self._renderer._kind != "qt" + self._info = info + self._fiducials = fiducials + self.coreg = Coregistration( + info=self._info, + subject=subject, + subjects_dir=subjects_dir, + fiducials=fiducials, + on_defects="ignore", # safe due to interactive visual inspection + ) + fid_accurate = self.coreg._fid_accurate + for fid in self._defaults["weights"].keys(): + setattr(self, f"_{fid}_weight", self._defaults["weights"][fid]) + + # set main traits + self._set_head_opacity(self._defaults["head_opacity"]) + self._old_head_opacity = self._head_opacity + self._set_subjects_dir(subjects_dir) + self._set_subject(subject) + self._set_info_file(info_file) + self._set_orient_glyphs(self._defaults["orient_glyphs"]) + self._set_scale_by_distance(self._defaults["scale_by_distance"]) + self._set_mark_inside(self._defaults["mark_inside"]) + self._set_hpi_coils(self._defaults["hpi_coils"]) + self._set_head_shape_points(self._defaults["head_shape_points"]) + self._set_eeg_channels(self._defaults["eeg_channels"]) + self._set_meg_channels(self._defaults["meg_channels"]) + self._set_fnirs_channels(self._defaults["fnirs_channels"]) + self._set_head_resolution(self._defaults["head_resolution"]) + self._set_helmet(self._defaults["helmet"]) + self._set_grow_hair(self._defaults["grow_hair"]) + self._set_omit_hsp_distance(self._defaults["omit_hsp_distance"]) + self._set_icp_n_iterations(self._defaults["icp_n_iterations"]) + self._set_icp_fid_match(self._defaults["icp_fid_match"]) + + # configure UI + self._reset_fitting_parameters() + self._configure_dialogs() + self._configure_status_bar() + self._configure_dock() + self._configure_picking() + self._configure_legend() + + # once the docks are initialized + self._set_current_fiducial(self._defaults["fiducial"]) + self._set_scale_mode(self._defaults["scale_mode"]) + self._set_subject_to(self._defaults["subject_to"]) + if trans is not None: + self._load_trans(trans) + self._redraw() # we need the elements to be present now + + if fid_accurate: + assert self.coreg._fid_filename is not None + # _set_fiducials_file() calls _update_fiducials_label() + # internally + self._set_fiducials_file(self.coreg._fid_filename) + else: + self._set_head_resolution("high") + self._forward_widget_command("high_res_head", "set_value", True) + self._set_lock_fids(True) # hack to make the dig disappear + self._update_fiducials_label() + self._update_fiducials() + + self._set_lock_fids(fid_accurate) + + # configure worker + self._configure_worker() + + # must be done last + if show: + self._renderer.show() + # update the view once shown + views = { + True: dict(azimuth=90, elevation=90), # front + False: dict(azimuth=180, elevation=90), + } # left + self._renderer.set_camera(distance="auto", **views[self._lock_fids]) + self._redraw() + # XXX: internal plotter/renderer should not be exposed + if not self._immediate_redraw: + self._renderer.plotter.add_callback(self._redraw, self._refresh_rate_ms) + self._renderer.plotter.show_axes() + # initialization does not count as modification by the user + self._trans_modified = False + self._mri_fids_modified = False + self._mri_scale_modified = False + if block and self._renderer._kind != "notebook": + _qt_app_exec(self._renderer.figure.store["app"]) + + def _set_subjects_dir(self, subjects_dir): + if subjects_dir is None or not subjects_dir: + return + try: + subjects_dir = str( + _check_fname( + subjects_dir, + overwrite="read", + must_exist=True, + need_dir=True, + ) + ) + subjects = _get_subjects(subjects_dir) + low_res_path = _find_head_bem(subjects[0], subjects_dir, high_res=False) + high_res_path = _find_head_bem(subjects[0], subjects_dir, high_res=True) + valid = low_res_path is not None or high_res_path is not None + except Exception: + valid = False + if valid: + style = dict(border="initial") + self._subjects_dir = subjects_dir + else: + style = dict(border="2px solid #ff0000") + self._forward_widget_command("subjects_dir_field", "set_style", style) + + def _set_subject(self, subject): + self._subject = subject + + def _set_lock_fids(self, state): + self._lock_fids = bool(state) + + def _set_fiducials_file(self, fname): + if fname is None: + fids = "auto" + else: + fname = str( + _check_fname( + fname, + overwrite="read", + must_exist=True, + need_dir=False, + ) + ) + fids, _ = read_fiducials(fname) + + self._fiducials_file = fname + self.coreg._setup_fiducials(fids) + self._update_distance_estimation() + self._update_fiducials_label() + self._update_fiducials() + self._reset(keep_trans=True) + + if fname is None: + self._set_lock_fids(False) + self._forward_widget_command("reload_mri_fids", "set_enabled", False) + else: + self._set_lock_fids(True) + self._forward_widget_command("reload_mri_fids", "set_enabled", True) + self._display_message(f"Loading MRI fiducials from {fname}... Done!") + + def _set_current_fiducial(self, fid): + self._current_fiducial = fid.lower() + + def _set_info_file(self, fname): + if fname is None: + return + + # info file can be anything supported by read_raw + supported = _get_supported() + try: + check_fname( + fname, + "info", + tuple(supported), + endings_err=tuple(supported), + ) + fname = Path(fname) + # ctf ds `files` are actually directories + if fname.suffix == ".ds": + info_file = _check_fname( + fname, overwrite="read", must_exist=True, need_dir=True + ) + else: + info_file = _check_fname( + fname, overwrite="read", must_exist=True, need_dir=False + ) + valid = True + except OSError: + valid = False + if valid: + style = dict(border="initial") + self._info_file = info_file + else: + style = dict(border="2px solid #ff0000") + self._forward_widget_command("info_file_field", "set_style", style) + + def _set_omit_hsp_distance(self, distance): + self._omit_hsp_distance = distance + + def _set_orient_glyphs(self, state): + self._orient_glyphs = bool(state) + + def _set_scale_by_distance(self, state): + self._scale_by_distance = bool(state) + + def _set_mark_inside(self, state): + self._mark_inside = bool(state) + + def _set_hpi_coils(self, state): + self._hpi_coils = bool(state) + + def _set_head_shape_points(self, state): + self._head_shape_points = bool(state) + + def _set_eeg_channels(self, state): + self._eeg_channels = bool(state) + + def _set_meg_channels(self, state): + self._meg_channels = bool(state) + + def _set_fnirs_channels(self, state): + self._fnirs_channels = bool(state) + + def _set_head_resolution(self, state): + self._head_resolution = bool(state) + + def _set_head_opacity(self, value): + self._head_opacity = value + + def _set_helmet(self, state): + self._helmet = bool(state) + + def _set_grow_hair(self, value): + self._grow_hair = value + + def _set_subject_to(self, value): + self._subject_to = value + self._forward_widget_command("save_subject", "set_enabled", len(value) > 0) + if self._check_subject_exists(): + style = dict(border="2px solid #ff0000") + else: + style = dict(border="initial") + self._forward_widget_command("subject_to", "set_style", style) + + def _set_scale_mode(self, mode): + self._scale_mode = mode + + def _set_fiducial(self, value, coord): + self._mri_fids_modified = True + fid = self._current_fiducial + fid_idx = _map_fid_name_to_idx(name=fid) + + coords = ["X", "Y", "Z"] + coord_idx = coords.index(coord) + + self.coreg.fiducials.dig[fid_idx]["r"][coord_idx] = value / 1e3 + self._update_plot("mri_fids") + + def _set_parameter(self, value, mode_name, coord, plot_locked=False): + if mode_name == "scale": + self._mri_scale_modified = True + else: + self._trans_modified = True + if self._params_locked: + return + if mode_name == "scale" and self._scale_mode == "uniform": + with self._lock(params=True): + self._forward_widget_command(["sY", "sZ"], "set_value", value) + with self._parameter_mutex: + self._set_parameter_safe(value, mode_name, coord) + if not plot_locked: + self._update_plot("sensors") + + def _set_parameter_safe(self, value, mode_name, coord): + params = dict( + rotation=self.coreg._rotation, + translation=self.coreg._translation, + scale=self.coreg._scale, + ) + idx = ["X", "Y", "Z"].index(coord) + if mode_name == "rotation": + params[mode_name][idx] = np.deg2rad(value) + elif mode_name == "translation": + params[mode_name][idx] = value / 1e3 + else: + assert mode_name == "scale" + if self._scale_mode == "uniform": + params[mode_name][:] = value / 1e2 + else: + params[mode_name][idx] = value / 1e2 + self._update_plot("head") + self.coreg._update_params( + rot=params["rotation"], + tra=params["translation"], + sca=params["scale"], + ) + + def _set_icp_n_iterations(self, n_iterations): + self._icp_n_iterations = n_iterations + + def _set_icp_fid_match(self, method): + self._icp_fid_match = method + + def _set_point_weight(self, weight, point): + funcs = { + "hpi": "_set_hpi_coils", + "hsp": "_set_head_shape_points", + "eeg": "_set_eeg_channels", + "meg": "_set_meg_channels", + "fnirs": "_set_fnirs_channels", + } + if point in funcs.keys(): + getattr(self, funcs[point])(weight > 0) + setattr(self, f"_{point}_weight", weight) + setattr(self.coreg, f"_{point}_weight", weight) + self._update_distance_estimation() + + @observe("_subjects_dir") + def _subjects_dir_changed(self, change=None): + # XXX: add coreg.set_subjects_dir + self.coreg._subjects_dir = self._subjects_dir + subjects = _get_subjects(self._subjects_dir) + + if self._subject not in subjects: # Just pick the first available one + self._subject = subjects[0] + + self._reset() + + @observe("_subject") + def _subject_changed(self, change=None): + # XXX: add coreg.set_subject() + self.coreg._subject = self._subject + self.coreg._setup_bem() + self.coreg._setup_fiducials(self._fiducials) + self._reset() + + default_fid_fname = fid_fname.format( + subjects_dir=self._subjects_dir, subject=self._subject + ) + if Path(default_fid_fname).exists(): + fname = default_fid_fname + else: + fname = None + + self._set_fiducials_file(fname) + self._reset_fiducials() + + @observe("_lock_fids") + def _lock_fids_changed(self, change=None): + locked_widgets = [ + # MRI fiducials + "save_mri_fids", + # View options + "helmet", + "meg", + "head_opacity", + "high_res_head", + # Digitization source + "info_file", + "grow_hair", + "omit_distance", + "omit", + "reset_omit", + # Scaling + "scaling_mode", + "sX", + "sY", + "sZ", + # Transformation + "tX", + "tY", + "tZ", + "rX", + "rY", + "rZ", + # Fitting buttons + "fit_fiducials", + "fit_icp", + # Transformation I/O + "save_trans", + "load_trans", + "reset_trans", + # ICP + "icp_n_iterations", + "icp_fid_match", + "reset_fitting_options", + # Weights + "hsp_weight", + "eeg_weight", + "hpi_weight", + "lpa_weight", + "nasion_weight", + "rpa_weight", + ] + fits_widgets = ["fits_fiducials", "fits_icp"] + fid_widgets = ["fid_X", "fid_Y", "fid_Z", "fids_file", "fids"] + if self._lock_fids: + self._forward_widget_command(locked_widgets, "set_enabled", True) + self._forward_widget_command( + "head_opacity", "set_value", self._old_head_opacity + ) + self._scale_mode_changed() + self._display_message() + self._update_distance_estimation() + else: + self._old_head_opacity = self._head_opacity + self._forward_widget_command("head_opacity", "set_value", 1.0) + self._forward_widget_command(locked_widgets, "set_enabled", False) + self._forward_widget_command(fits_widgets, "set_enabled", False) + self._display_message( + f"Placing MRI fiducials - {self._current_fiducial.upper()}" + ) + + self._set_sensors_visibility(self._lock_fids) + self._forward_widget_command("lock_fids", "set_value", self._lock_fids) + self._forward_widget_command(fid_widgets, "set_enabled", not self._lock_fids) + + @observe("_current_fiducial") + def _current_fiducial_changed(self, change=None): + self._update_fiducials() + self._follow_fiducial_view() + if not self._lock_fids: + self._display_message( + f"Placing MRI fiducials - {self._current_fiducial.upper()}" + ) + + @observe("_info_file") + def _info_file_changed(self, change=None): + if not self._info_file: + return + elif self._info_file.name.endswith((".fif", ".fif.gz")): + fid, tree, _ = fiff_open(self._info_file) + fid.close() + if len(dir_tree_find(tree, FIFF.FIFFB_MEAS_INFO)) > 0: + self._info = read_info(self._info_file, verbose=False) + elif len(dir_tree_find(tree, FIFF.FIFFB_ISOTRAK)) > 0: + self._info = _empty_info(1) + self._info["dig"] = read_dig_fif(fname=self._info_file).dig + self._info._unlocked = False + else: + self._info = read_raw(self._info_file).info + # XXX: add coreg.set_info() + self.coreg._info = self._info + self.coreg._setup_digs() + self._reset() + + @observe("_orient_glyphs") + def _orient_glyphs_changed(self, change=None): + self._update_plot(["hpi", "hsp", "sensors"]) + + @observe("_scale_by_distance") + def _scale_by_distance_changed(self, change=None): + self._update_plot(["hpi", "hsp", "sensors"]) + + @observe("_mark_inside") + def _mark_inside_changed(self, change=None): + self._update_plot("hsp") + + @observe("_hpi_coils") + def _hpi_coils_changed(self, change=None): + self._update_plot("hpi") + + @observe("_head_shape_points") + def _head_shape_point_changed(self, change=None): + self._update_plot("hsp") + + @observe("_eeg_channels") + def _eeg_channels_changed(self, change=None): + self._update_plot("sensors") + + @observe("_meg_channels") + def _meg_channels_changed(self, change=None): + self._update_plot("sensors") + + @observe("_fnirs_channels") + def _fnirs_channels_changed(self, change=None): + self._update_plot("sensors") + + @observe("_head_resolution") + def _head_resolution_changed(self, change=None): + self._update_plot(["head", "hsp"]) + + @observe("_head_opacity") + def _head_opacity_changed(self, change=None): + if "head" in self._actors: + self._actors["head"].GetProperty().SetOpacity(self._head_opacity) + self._renderer._update() + + @observe("_helmet") + def _helmet_changed(self, change=None): + self._update_plot("helmet") + + @observe("_grow_hair") + def _grow_hair_changed(self, change=None): + self.coreg.set_grow_hair(self._grow_hair) + self._update_plot("head") + self._update_plot("hsp") # inside/outside could change + + @observe("_scale_mode") + def _scale_mode_changed(self, change=None): + locked_widgets = ["sX", "sY", "sZ", "fits_icp", "subject_to"] + mode = None if self._scale_mode == "None" else self._scale_mode + self.coreg.set_scale_mode(mode) + if self._lock_fids: + self._forward_widget_command( + locked_widgets, "set_enabled", mode is not None + ) + self._forward_widget_command( + "fits_fiducials", "set_enabled", mode not in (None, "3-axis") + ) + if self._scale_mode == "uniform": + self._forward_widget_command(["sY", "sZ"], "set_enabled", False) + + @observe("_icp_fid_match") + def _icp_fid_match_changed(self, change=None): + self.coreg.set_fid_match(self._icp_fid_match) + + def _run_worker(self, queue, jobs): + while True: + data = queue.get() + func = jobs[data._name] + if data._params is not None: + func(**data._params) + else: + func() + queue.task_done() + + def _configure_dialogs(self): + from ..viz.backends.renderer import MNE_3D_BACKEND_TESTING + + for name, buttons in zip( + ["overwrite_subject", "overwrite_subject_exit"], + [["Yes", "No"], ["Yes", "Discard", "Cancel"]], + ): + self._widgets[name] = self._renderer._dialog_create( + title="CoregistrationUI", + text="The name of the output subject used to " + "save the scaled anatomy already exists.", + info_text="Do you want to overwrite?", + callback=self._overwrite_subject_callback, + buttons=buttons, + modal=not MNE_3D_BACKEND_TESTING, + ) + + def _configure_worker(self): + work_plan = { + "_job_queue": dict(save_subject=self._save_subject), + "_parameter_queue": dict(set_parameter=self._set_parameter), + } + for queue_name, jobs in work_plan.items(): + t = threading.Thread( + target=partial( + self._run_worker, + queue=getattr(self, queue_name), + jobs=jobs, + ) + ) + t.daemon = True + t.start() + + def _configure_picking(self): + self._renderer._update_picking_callback( + self._on_mouse_move, + self._on_button_press, + self._on_button_release, + self._on_pick, + ) + + def _configure_legend(self): + colors = [ + np.array(DEFAULTS["coreg"][f"{fid.lower()}_color"]).astype(float) + for fid in self._defaults["fiducials"] + ] + labels = list(zip(self._defaults["fiducials"], colors)) + mri_fids_legend_actor = self._renderer.legend(labels=labels) + self._update_actor("mri_fids_legend", mri_fids_legend_actor) + + @safe_event + @verbose + def _redraw(self, *, verbose=None): + if not self._redraws_pending: + return + draw_map = dict( + head=self._add_head_surface, + mri_fids=self._add_mri_fiducials, + hsp=self._add_head_shape_points, + hpi=self._add_hpi_coils, + sensors=self._add_channels, + head_fids=self._add_head_fiducials, + helmet=self._add_helmet, + ) + with self._redraw_mutex: + # We need at least "head" before "hsp", because the grow_hair param + # for head sets the rr that are used for inside/outside hsp + redraws_ordered = sorted( + self._redraws_pending, key=lambda key: list(draw_map).index(key) + ) + logger.debug(f"Redrawing {redraws_ordered}") + for ki, key in enumerate(redraws_ordered): + logger.debug(f"{ki}. Drawing {repr(key)}") + draw_map[key]() + self._redraws_pending.clear() + self._renderer._update() + # necessary for MacOS + if platform.system() == "Darwin": + self._renderer._process_events() + + def _on_mouse_move(self, vtk_picker, event): + if self._mouse_no_mvt: + self._mouse_no_mvt -= 1 + + def _on_button_press(self, vtk_picker, event): + self._mouse_no_mvt = 2 + + def _on_button_release(self, vtk_picker, event): + if self._mouse_no_mvt > 0: + x, y = vtk_picker.GetEventPosition() + # XXX: internal plotter/renderer should not be exposed + picker = self._renderer._picker + picked_renderer = self._renderer.figure.plotter.renderer + # trigger the pick + picker.Pick(x, y, 0, picked_renderer) + self._mouse_no_mvt = 0 + + def _on_pick(self, vtk_picker, event): + if self._lock_fids: + return + # XXX: taken from Brain, can be refactored + cell_id = vtk_picker.GetCellId() + mesh = vtk_picker.GetDataSet() + if mesh is None or cell_id == -1 or not self._mouse_no_mvt: + return + if not any(mesh is target() for target in self._picking_targets): + return + pos = np.array(vtk_picker.GetPickPosition()) + fiducials = [s.lower() for s in self._defaults["fiducials"]] + idx = fiducials.index(self._current_fiducial.lower()) + # XXX: add coreg.set_fids + self.coreg._fid_points[idx] = pos + self.coreg._reset_fiducials() + self._update_fiducials() + self._update_plot("mri_fids") + + def _reset_fitting_parameters(self): + self._forward_widget_command( + "icp_n_iterations", "set_value", self._defaults["icp_n_iterations"] + ) + self._forward_widget_command( + "icp_fid_match", "set_value", self._defaults["icp_fid_match"] + ) + weights_widgets = [f"{w}_weight" for w in self._defaults["weights"].keys()] + self._forward_widget_command( + weights_widgets, "set_value", list(self._defaults["weights"].values()) + ) + + def _reset_fiducials(self): + self._set_current_fiducial(self._defaults["fiducial"]) + + def _omit_hsp(self): + self.coreg.omit_head_shape_points(self._omit_hsp_distance / 1e3) + n_omitted = np.sum(~self.coreg._extra_points_filter) + n_remaining = len(self.coreg._dig_dict["hsp"]) - n_omitted + self._update_plot("hsp") + self._update_distance_estimation() + self._display_message( + f"{n_omitted} head shape points omitted, {n_remaining} remaining." + ) + + def _reset_omit_hsp_filter(self): + self.coreg._extra_points_filter = None + self.coreg._update_params(force_update=True) + self._update_plot("hsp") + self._update_distance_estimation() + n_total = len(self.coreg._dig_dict["hsp"]) + self._display_message( + f"No head shape point is omitted, the total is {n_total}." + ) + + @verbose + def _update_plot(self, changes="all", verbose=None): + # Update list of things that need to be updated/plotted (and maybe + # draw them immediately) + try: + fun_name = inspect.currentframe().f_back.f_back.f_code.co_name + except Exception: # just in case one of these attrs is missing + fun_name = "unknown" + logger.debug(f"Updating plots based on {fun_name}: {repr(changes)}") + if self._plot_locked: + return + if self._info is None: + changes = ["head", "mri_fids"] + self._to_cf_t = dict(mri=dict(trans=np.eye(4)), head=None) + else: + self._to_cf_t = _get_transforms_to_coord_frame( + self._info, self.coreg.trans, coord_frame=self._coord_frame + ) + all_keys = ( + "head", + "mri_fids", # MRI first + "hsp", + "hpi", + "sensors", + "head_fids", # then dig + "helmet", + ) + if changes == "all": + changes = list(all_keys) + elif changes == "sensors": + changes = all_keys[2:] # omit MRI ones + elif isinstance(changes, str): + changes = [changes] + changes = set(changes) + # ideally we would maybe have this in: + # with self._redraw_mutex: + # it would reduce "jerkiness" of the updates, but this should at least + # work okay + bad = changes.difference(set(all_keys)) + assert len(bad) == 0, f"Unknown changes: {bad}" + self._redraws_pending.update(changes) + if self._immediate_redraw: + self._redraw() + + @contextmanager + def _lock(self, plot=False, params=False, scale_mode=False, fitting=False): + """Which part of the UI to temporarily disable.""" + if plot: + old_plot_locked = self._plot_locked + self._plot_locked = True + if params: + old_params_locked = self._params_locked + self._params_locked = True + if scale_mode: + old_scale_mode = self.coreg._scale_mode + self.coreg._scale_mode = None + if fitting: + widgets = [ + "sX", + "sY", + "sZ", + "tX", + "tY", + "tZ", + "rX", + "rY", + "rZ", + "fit_icp", + "fit_fiducials", + "fits_icp", + "fits_fiducials", + ] + states = [ + self._forward_widget_command( + w, "is_enabled", None, input_value=False, output_value=True + ) + for w in widgets + ] + self._forward_widget_command(widgets, "set_enabled", False) + try: + yield + finally: + if plot: + self._plot_locked = old_plot_locked + if params: + self._params_locked = old_params_locked + if scale_mode: + self.coreg._scale_mode = old_scale_mode + if fitting: + for idx, w in enumerate(widgets): + self._forward_widget_command(w, "set_enabled", states[idx]) + + def _display_message(self, msg=""): + self._forward_widget_command("status_message", "set_value", msg) + self._forward_widget_command("status_message", "show", None, input_value=False) + self._forward_widget_command( + "status_message", "update", None, input_value=False + ) + if msg: + logger.info(msg) + + def _follow_fiducial_view(self): + fid = self._current_fiducial.lower() + view = dict(lpa="left", rpa="right", nasion="front") + kwargs = dict(front=(90.0, 90.0), left=(180, 90), right=(0.0, 90)) + kwargs = dict(zip(("azimuth", "elevation"), kwargs[view[fid]])) + if not self._lock_fids: + self._renderer.set_camera(distance="auto", **kwargs) + + def _update_fiducials(self): + fid = self._current_fiducial + if not fid: + return + + idx = _map_fid_name_to_idx(name=fid) + val = self.coreg.fiducials.dig[idx]["r"] * 1e3 + + with self._lock(plot=True): + self._forward_widget_command(["fid_X", "fid_Y", "fid_Z"], "set_value", val) + + def _update_distance_estimation(self): + value = ( + self.coreg._get_fiducials_distance_str() + + "\n" + + self.coreg._get_point_distance_str() + ) + dists = self.coreg.compute_dig_mri_distances() * 1e3 + if self._hsp_weight > 0: + if len(dists) == 0: + value += "\nNo head shape points found." + else: + value += ( + "\nHSP <-> MRI (mean/min/max): " + f"{np.mean(dists):.2f} " + f"/ {np.min(dists):.2f} / {np.max(dists):.2f} mm" + ) + self._forward_widget_command("fit_label", "set_value", value) + + def _update_parameters(self): + with self._lock(plot=True, params=True): + # rotation + deg = np.rad2deg(self.coreg._rotation) + logger.debug(f" Rotation: {deg}") + self._forward_widget_command(["rX", "rY", "rZ"], "set_value", deg) + # translation + mm = self.coreg._translation * 1e3 + logger.debug(f" Translation: {mm}") + self._forward_widget_command(["tX", "tY", "tZ"], "set_value", mm) + # scale + sc = self.coreg._scale * 1e2 + logger.debug(f" Scale: {sc}") + self._forward_widget_command(["sX", "sY", "sZ"], "set_value", sc) + + def _reset(self, keep_trans=False): + """Refresh the scene, and optionally reset transformation & scaling. + + Parameters + ---------- + keep_trans : bool + Whether to retain translation, rotation, and scaling; or reset them + to their default values (no translation, no rotation, no scaling). + """ + if not keep_trans: + self.coreg.set_scale(self.coreg._default_parameters[6:9]) + self.coreg.set_rotation(self.coreg._default_parameters[:3]) + self.coreg.set_translation(self.coreg._default_parameters[3:6]) + self._update_plot() + self._update_parameters() + self._update_distance_estimation() + + def _forward_widget_command( + self, names, command, value, input_value=True, output_value=False + ): + """Invoke a method of one or more widgets if the widgets exist. + + Parameters + ---------- + names : str | array-like of str + The widget names to operate on. + command : str + The method to invoke. + value : object | array-like + The value(s) to pass to the method. + input_value : bool + Whether the ``command`` accepts a ``value``. If ``False``, no + ``value`` will be passed to ``command``. + output_value : bool + Whether to return the return value of ``command``. + + Returns + ------- + ret : object | None + ``None`` if ``output_value`` is ``False``, and the return value of + ``command`` otherwise. + """ + _validate_type(item=names, types=(str, list), item_name="names") + if isinstance(names, str): + names = [names] + + if not isinstance(value, str | float | int | dict | type(None)): + value = list(value) + assert len(names) == len(value) + + for idx, name in enumerate(names): + val = value[idx] if isinstance(value, list) else value + if name in self._widgets and self._widgets[name] is not None: + if input_value: + ret = getattr(self._widgets[name], command)(val) + else: + ret = getattr(self._widgets[name], command)() + if output_value: + return ret + + def _set_sensors_visibility(self, state): + sensors = [ + "head_fiducials", + "hpi_coils", + "head_shape_points", + "sensors", + "helmet", + ] + for sensor in sensors: + if sensor in self._actors and self._actors[sensor] is not None: + actors = self._actors[sensor] + actors = actors if isinstance(actors, list) else [actors] + for actor in actors: + if actor is None: + continue + actor.SetVisibility(state) + + self._renderer._update() + + def _update_actor(self, actor_name, actor): + # XXX: internal plotter/renderer should not be exposed + # Work around PyVista sequential update bug with iterable until > 0.42.3 is req + # https://github.com/pyvista/pyvista/pull/5046 + actors = self._actors.get(actor_name) or [] # convert None to list + if not isinstance(actors, list): + actors = [actors] + for this_actor in actors: + self._renderer.plotter.remove_actor(this_actor, render=False) + self._actors[actor_name] = actor + + def _add_mri_fiducials(self): + mri_fids_actors = _plot_mri_fiducials( + self._renderer, + self.coreg._fid_points, + self._subjects_dir, + self._subject, + self._to_cf_t, + self._fid_colors, + ) + # disable picking on the markers + for actor in mri_fids_actors: + actor.SetPickable(False) + self._update_actor("mri_fiducials", mri_fids_actors) + + def _add_head_fiducials(self): + head_fids_actors = _plot_head_fiducials( + self._renderer, self._info, self._to_cf_t, self._fid_colors + ) + self._update_actor("head_fiducials", head_fids_actors) + + def _add_hpi_coils(self): + if self._hpi_coils: + hpi_actors = _plot_hpi_coils( + self._renderer, + self._info, + self._to_cf_t, + opacity=self._defaults["sensor_opacity"], + scale=DEFAULTS["coreg"]["extra_scale"], + orient_glyphs=self._orient_glyphs, + scale_by_distance=self._scale_by_distance, + surf=self._head_geo, + check_inside=self._check_inside, + nearest=self._nearest, + ) + else: + hpi_actors = None + self._update_actor("hpi_coils", hpi_actors) + + def _add_head_shape_points(self): + if self._head_shape_points: + hsp_actors = _plot_head_shape_points( + self._renderer, + self._info, + self._to_cf_t, + opacity=self._defaults["sensor_opacity"], + orient_glyphs=self._orient_glyphs, + scale_by_distance=self._scale_by_distance, + mark_inside=self._mark_inside, + surf=self._head_geo, + mask=self.coreg._extra_points_filter, + check_inside=self._check_inside, + nearest=self._nearest, + ) + else: + hsp_actors = None + self._update_actor("head_shape_points", hsp_actors) + + def _add_channels(self): + plot_types = dict(eeg=False, meg=False, fnirs=False) + if self._eeg_channels: + plot_types["eeg"] = ["original"] + if self._meg_channels: + plot_types["meg"] = ["sensors"] + if self._fnirs_channels: + plot_types["fnirs"] = ["sources", "detectors"] + sensor_alpha = dict( + eeg=self._defaults["sensor_opacity"], + fnirs=self._defaults["sensor_opacity"], + meg=0.25, + ) + picks = pick_types( + self._info, + ref_meg=False, + meg=True, + eeg=True, + fnirs=True, + exclude=(), + ) + these_actors = _plot_sensors_3d( + self._renderer, + self._info, + self._to_cf_t, + picks=picks, + warn_meg=False, + head_surf=self._head_geo, + units="m", + sensor_alpha=sensor_alpha, + orient_glyphs=self._orient_glyphs, + scale_by_distance=self._scale_by_distance, + surf=self._head_geo, + check_inside=self._check_inside, + nearest=self._nearest, + **plot_types, + ) + sens_actors = sum((these_actors or {}).values(), list()) + self._update_actor("sensors", sens_actors) + + def _add_head_surface(self): + bem = None + if self._head_resolution: + surface = "head-dense" + key = "high" + else: + surface = "head" + key = "low" + try: + head_actor, head_surf, _ = _plot_head_surface( + self._renderer, + surface, + self._subject, + self._subjects_dir, + bem, + self._coord_frame, + self._to_cf_t, + alpha=self._head_opacity, + ) + except OSError: + head_actor, head_surf, _ = _plot_head_surface( + self._renderer, + "head", + self._subject, + self._subjects_dir, + bem, + self._coord_frame, + self._to_cf_t, + alpha=self._head_opacity, + ) + key = "low" + self._update_actor("head", head_actor) + # mark head surface mesh to restrict picking + self._picking_targets.append(weakref.ref(head_surf)) + # We need to use _get_processed_mri_points to incorporate grow_hair + rr = self.coreg._get_processed_mri_points(key) * self.coreg._scale.T + head_surf.points = rr + head_surf.compute_normals() + self._surfaces["head"] = head_surf + tris = self._surfaces["head"].faces.reshape(-1, 4)[:, 1:] + assert tris.ndim == 2 and tris.shape[1] == 3, tris.shape + nn = self._surfaces["head"].point_normals + assert nn.shape == (len(rr), 3), nn.shape + self._head_geo = dict(rr=rr, tris=tris, nn=nn) + self._check_inside = _CheckInside(head_surf, mode="pyvista") + self._nearest = _DistanceQuery(rr) + + def _add_helmet(self): + if self._helmet: + logger.debug("Drawing helmet") + head_mri_t = _get_trans(self.coreg.trans, "head", "mri")[0] + helmet_actor, _, _ = _plot_helmet( + self._renderer, self._info, self._to_cf_t, head_mri_t, self._coord_frame + ) + else: + helmet_actor = None + self._update_actor("helmet", helmet_actor) + + def _fit_fiducials(self): + with self._lock(scale_mode=True): + self._fits_fiducials() + + def _fits_fiducials(self): + with self._lock(params=True, fitting=True): + start = time.time() + self.coreg.fit_fiducials( + lpa_weight=self._lpa_weight, + nasion_weight=self._nasion_weight, + rpa_weight=self._rpa_weight, + verbose=self._verbose, + ) + end = time.time() + self._display_message( + f"Fitting fiducials finished in {end - start:.2f} seconds." + ) + self._update_plot("sensors") + self._update_parameters() + self._update_distance_estimation() + + def _fit_icp(self): + with self._lock(scale_mode=True): + self._fit_icp_real(update_head=False) + + def _fits_icp(self): + self._fit_icp_real(update_head=True) + + def _fit_icp_real(self, *, update_head): + with self._lock(params=True, fitting=True): + self._current_icp_iterations = 0 + updates = ["hsp", "hpi", "sensors", "head_fids", "helmet"] + if update_head: + updates.insert(0, "head") + + def callback(iteration, n_iterations): + self._display_message(f"Fitting ICP - iteration {iteration + 1}") + self._update_plot(updates) + self._current_icp_iterations += 1 + self._update_distance_estimation() + self._update_parameters() + self._renderer._process_events() # allow a draw or cancel + + start = time.time() + self.coreg.fit_icp( + n_iterations=self._icp_n_iterations, + lpa_weight=self._lpa_weight, + nasion_weight=self._nasion_weight, + rpa_weight=self._rpa_weight, + callback=callback, + verbose=self._verbose, + ) + end = time.time() + self._display_message() + self._display_message( + f"Fitting ICP finished in {end - start:.2f} seconds and " + f"{self._current_icp_iterations} iterations." + ) + del self._current_icp_iterations + + def _task_save_subject(self): + from ..viz.backends.renderer import MNE_3D_BACKEND_TESTING + + if MNE_3D_BACKEND_TESTING: + self._save_subject() + else: + self._job_queue.put(_WorkerData("save_subject", None)) + + def _task_set_parameter(self, value, mode_name, coord): + from ..viz.backends.renderer import MNE_3D_BACKEND_TESTING + + if MNE_3D_BACKEND_TESTING: + self._set_parameter(value, mode_name, coord, self._plot_locked) + else: + self._parameter_queue.put( + _WorkerData( + "set_parameter", + dict( + value=value, + mode_name=mode_name, + coord=coord, + plot_locked=self._plot_locked, + ), + ) + ) + + def _overwrite_subject_callback(self, button_name): + if button_name == "Yes": + self._save_subject_callback(overwrite=True) + elif button_name == "Cancel": + self._accept_close_event = False + else: + assert button_name == "No" or button_name == "Discard" + + def _check_subject_exists(self): + if not self._subject_to: + return False + subject_dirname = os.path.join("{subjects_dir}", "{subject}") + dest = subject_dirname.format( + subject=self._subject_to, subjects_dir=self._subjects_dir + ) + return os.path.exists(dest) + + def _save_subject(self, exit_mode=False): + dialog = "overwrite_subject_exit" if exit_mode else "overwrite_subject" + if self._check_subject_exists(): + self._forward_widget_command(dialog, "show", True) + else: + self._save_subject_callback() + + def _save_subject_callback(self, overwrite=False): + self._display_message(f"Saving {self._subject_to}...") + default_cursor = self._renderer._window_get_cursor() + self._renderer._window_set_cursor( + self._renderer._window_new_cursor("WaitCursor") + ) + + # prepare bem + bem_names = [] + if self._scale_mode != "None": + can_prepare_bem = _mri_subject_has_bem(self._subject, self._subjects_dir) + else: + can_prepare_bem = False + if can_prepare_bem: + pattern = bem_fname.format( + subjects_dir=self._subjects_dir, subject=self._subject, name="(.+-bem)" + ) + bem_dir, pattern = os.path.split(pattern) + for filename in os.listdir(bem_dir): + match = re.match(pattern, filename) + if match: + bem_names.append(match.group(1)) + + # save the scaled MRI + try: + self._display_message(f"Scaling {self._subject_to}...") + scale_mri( + subject_from=self._subject, + subject_to=self._subject_to, + scale=self.coreg._scale, + overwrite=overwrite, + subjects_dir=self._subjects_dir, + skip_fiducials=True, + labels=True, + annot=True, + on_defects="ignore", + mri_fiducials=self.coreg.fiducials, + ) + except Exception: + logger.error(f"Error scaling {self._subject_to}") + bem_names = [] + else: + self._display_message(f"Scaling {self._subject_to}... Done!") + + # Precompute BEM solutions + for bem_name in bem_names: + try: + self._display_message(f"Computing {bem_name} solution...") + bem_file = bem_fname.format( + subjects_dir=self._subjects_dir, + subject=self._subject_to, + name=bem_name, + ) + bemsol = make_bem_solution(bem_file) + write_bem_solution(bem_file[:-4] + "-sol.fif", bemsol) + except Exception: + logger.error(f"Error computing {bem_name} solution") + else: + self._display_message(f"Computing {bem_name} solution... Done!") + self._display_message(f"Saving {self._subject_to}... Done!") + self._renderer._window_set_cursor(default_cursor) + self._mri_scale_modified = False + + def _save_mri_fiducials(self, fname): + self._display_message(f"Saving {fname}...") + dig_montage = self.coreg.fiducials + write_fiducials( + fname=fname, pts=dig_montage.dig, coord_frame="mri", overwrite=True + ) + self._set_fiducials_file(fname) + self._display_message(f"Saving {fname}... Done!") + self._mri_fids_modified = False + + def _save_trans(self, fname): + write_trans(fname, self.coreg.trans, overwrite=True) + self._display_message(f"{fname} transform file is saved.") + self._trans_modified = False + + def _load_trans(self, trans): + if not isinstance(trans, Transform): + trans = read_trans(trans, return_all=True) + mri_head_t = _ensure_trans(trans, "mri", "head")["trans"] + rot_x, rot_y, rot_z = rotation_angles(mri_head_t) + x, y, z = mri_head_t[:3, 3] + self.coreg._update_params( + rot=np.array([rot_x, rot_y, rot_z]), + tra=np.array([x, y, z]), + ) + self._update_parameters() + self._update_distance_estimation() + self._update_plot() + self._display_message(f"{trans} transform file is loaded.") + + def _update_fiducials_label(self): + if self._fiducials_file is None: + text = ( + "

No custom MRI fiducials loaded!

" + "

MRI fiducials could not be found in the standard " + "location. The displayed initial MRI fiducial locations " + "(diamonds) were derived from fsaverage. Place, lock, and " + "save fiducials to discard this message.

" + ) + else: + assert self._fiducials_file == fid_fname.format( + subjects_dir=self._subjects_dir, subject=self._subject + ) + assert self.coreg._fid_accurate is True + text = ( + f"

MRI fiducials (diamonds) loaded from " + f"standard location:

" + f"

{self._fiducials_file}

" + ) + + self._forward_widget_command("mri_fiducials_label", "set_value", text) + + def _configure_dock(self): + if self._renderer._kind == "notebook": + collapse = True # collapsible and collapsed + else: + collapse = None # not collapsible + self._renderer._dock_initialize(name="Input", area="left", max_width="375px") + mri_subject_layout = self._renderer._dock_add_group_box( + name="MRI Subject", + collapse=collapse, + ) + subjects_dir_layout = self._renderer._dock_add_layout(vertical=False) + self._widgets["subjects_dir_field"] = self._renderer._dock_add_text( + name="subjects_dir_field", + value=self._subjects_dir, + placeholder="Subjects Directory", + callback=self._set_subjects_dir, + layout=subjects_dir_layout, + ) + self._widgets["subjects_dir"] = self._renderer._dock_add_file_button( + name="subjects_dir", + desc="Load", + func=self._set_subjects_dir, + is_directory=True, + icon=True, + tooltip="Load the path to the directory containing the FreeSurfer subjects", + layout=subjects_dir_layout, + ) + self._renderer._layout_add_widget( + layout=mri_subject_layout, + widget=subjects_dir_layout, + ) + self._widgets["subject"] = self._renderer._dock_add_combo_box( + name="Subject", + value=self._subject, + rng=_get_subjects(self._subjects_dir), + callback=self._set_subject, + compact=True, + tooltip="Select the FreeSurfer subject name", + layout=mri_subject_layout, + ) + + mri_fiducials_layout = self._renderer._dock_add_group_box( + name="MRI Fiducials", + collapse=collapse, + ) + # Add MRI fiducials I/O widgets + self._widgets["mri_fiducials_label"] = self._renderer._dock_add_label( + value="", # Will be filled via _update_fiducials_label() + layout=mri_fiducials_layout, + selectable=True, + ) + # Reload & Save buttons go into their own layout widget + mri_fiducials_button_layout = self._renderer._dock_add_layout(vertical=False) + self._renderer._layout_add_widget( + layout=mri_fiducials_layout, widget=mri_fiducials_button_layout + ) + self._widgets["reload_mri_fids"] = self._renderer._dock_add_button( + name="Reload MRI Fid.", + callback=lambda: self._set_fiducials_file(self._fiducials_file), + tooltip="Reload MRI fiducials from the standard location", + layout=mri_fiducials_button_layout, + ) + # Disable reload button until we've actually loaded a fiducial file + # (happens in _set_fiducials_file method) + self._forward_widget_command("reload_mri_fids", "set_enabled", False) + + self._widgets["save_mri_fids"] = self._renderer._dock_add_button( + name="Save MRI Fid.", + callback=lambda: self._save_mri_fiducials( + fid_fname.format(subjects_dir=self._subjects_dir, subject=self._subject) + ), + tooltip="Save MRI fiducials to the standard location. Fiducials " + "must be locked first!", + layout=mri_fiducials_button_layout, + ) + self._widgets["lock_fids"] = self._renderer._dock_add_check_box( + name="Lock fiducials", + value=self._lock_fids, + callback=self._set_lock_fids, + tooltip="Lock/Unlock interactive fiducial editing", + layout=mri_fiducials_layout, + ) + self._widgets["fids"] = self._renderer._dock_add_radio_buttons( + value=self._defaults["fiducial"], + rng=self._defaults["fiducials"], + callback=self._set_current_fiducial, + vertical=False, + layout=mri_fiducials_layout, + ) + fiducial_coords_layout = self._renderer._dock_add_layout() + for coord in ("X", "Y", "Z"): + name = f"fid_{coord}" + self._widgets[name] = self._renderer._dock_add_spin_box( + name=coord, + value=0.0, + rng=[-1e3, 1e3], + callback=partial( + self._set_fiducial, + coord=coord, + ), + compact=True, + double=True, + step=1, + tooltip=f"Set the {coord} fiducial coordinate", + layout=fiducial_coords_layout, + ) + self._renderer._layout_add_widget(mri_fiducials_layout, fiducial_coords_layout) + + dig_source_layout = self._renderer._dock_add_group_box( + name="Info source with digitization", + collapse=collapse, + ) + info_file_layout = self._renderer._dock_add_layout(vertical=False) + self._widgets["info_file_field"] = self._renderer._dock_add_text( + name="info_file_field", + value=self._info_file, + placeholder="Path to info", + callback=self._set_info_file, + layout=info_file_layout, + ) + self._widgets["info_file"] = self._renderer._dock_add_file_button( + name="info_file", + desc="Load", + func=self._set_info_file, + icon=True, + tooltip="Load the FIFF file with digitization data for coregistration", + layout=info_file_layout, + ) + self._renderer._layout_add_widget( + layout=dig_source_layout, + widget=info_file_layout, + ) + self._widgets["grow_hair"] = self._renderer._dock_add_spin_box( + name="Grow Hair (mm)", + value=self._grow_hair, + rng=[0.0, 10.0], + callback=self._set_grow_hair, + tooltip="Compensate for hair on the digitizer head shape", + layout=dig_source_layout, + ) + omit_hsp_layout_1 = self._renderer._dock_add_layout(vertical=False) + omit_hsp_layout_2 = self._renderer._dock_add_layout(vertical=False) + self._widgets["omit_distance"] = self._renderer._dock_add_spin_box( + name="Omit Distance (mm)", + value=self._omit_hsp_distance, + rng=[0.0, 100.0], + callback=self._set_omit_hsp_distance, + tooltip="Set the head shape points exclusion distance", + layout=omit_hsp_layout_1, + ) + self._widgets["omit"] = self._renderer._dock_add_button( + name="Omit", + callback=self._omit_hsp, + tooltip="Exclude the head shape points that are far away from the MRI head", + layout=omit_hsp_layout_2, + ) + self._widgets["reset_omit"] = self._renderer._dock_add_button( + name="Reset", + callback=self._reset_omit_hsp_filter, + tooltip="Reset all excluded head shape points", + layout=omit_hsp_layout_2, + ) + self._renderer._layout_add_widget(dig_source_layout, omit_hsp_layout_1) + self._renderer._layout_add_widget(dig_source_layout, omit_hsp_layout_2) + + view_options_layout = self._renderer._dock_add_group_box( + name="View Options", + collapse=collapse, + ) + self._widgets["helmet"] = self._renderer._dock_add_check_box( + name="Show MEG helmet", + value=self._helmet, + callback=self._set_helmet, + tooltip="Enable/Disable MEG helmet", + layout=view_options_layout, + ) + self._widgets["meg"] = self._renderer._dock_add_check_box( + name="Show MEG sensors", + value=self._meg_channels, + callback=self._set_meg_channels, + tooltip="Enable/Disable MEG sensors", + layout=view_options_layout, + ) + self._widgets["high_res_head"] = self._renderer._dock_add_check_box( + name="Show high-resolution head", + value=self._head_resolution, + callback=self._set_head_resolution, + tooltip="Enable/Disable high resolution head surface", + layout=view_options_layout, + ) + self._widgets["head_opacity"] = self._renderer._dock_add_slider( + name="Head opacity", + value=self._head_opacity, + rng=[0.25, 1.0], + callback=self._set_head_opacity, + compact=True, + double=True, + layout=view_options_layout, + ) + self._renderer._dock_add_stretch() + + self._renderer._dock_initialize( + name="Parameters", area="right", max_width="375px" + ) + mri_scaling_layout = self._renderer._dock_add_group_box( + name="MRI Scaling", + collapse=collapse, + ) + self._widgets["scaling_mode"] = self._renderer._dock_add_combo_box( + name="Scaling Mode", + value=self._defaults["scale_mode"], + rng=self._defaults["scale_modes"], + callback=self._set_scale_mode, + tooltip="Select the scaling mode", + compact=True, + layout=mri_scaling_layout, + ) + scale_params_layout = self._renderer._dock_add_group_box( + name="Scaling Parameters", + layout=mri_scaling_layout, + ) + coords = ["X", "Y", "Z"] + for coord in coords: + name = f"s{coord}" + attr = getattr(self.coreg, "_scale") + self._widgets[name] = self._renderer._dock_add_spin_box( + name=name, + value=attr[coords.index(coord)] * 1e2, + rng=[1.0, 10000.0], # percent + callback=partial( + self._set_parameter, + mode_name="scale", + coord=coord, + ), + compact=True, + double=True, + step=1, + tooltip=f"Set the {coord} scaling parameter (in %)", + layout=scale_params_layout, + ) + + fit_scale_layout = self._renderer._dock_add_layout(vertical=False) + self._widgets["fits_fiducials"] = self._renderer._dock_add_button( + name="Fit fiducials with scaling", + callback=self._fits_fiducials, + tooltip="Find MRI scaling, rotation, and translation to fit all " + "3 fiducials", + layout=fit_scale_layout, + ) + self._widgets["fits_icp"] = self._renderer._dock_add_button( + name="Fit ICP with scaling", + callback=self._fits_icp, + tooltip="Find MRI scaling, rotation, and translation to match the " + "head shape points", + layout=fit_scale_layout, + ) + self._renderer._layout_add_widget(scale_params_layout, fit_scale_layout) + subject_to_layout = self._renderer._dock_add_layout(vertical=False) + self._widgets["subject_to"] = self._renderer._dock_add_text( + name="subject-to", + value=self._subject_to, + placeholder="subject name", + callback=self._set_subject_to, + layout=subject_to_layout, + ) + self._widgets["save_subject"] = self._renderer._dock_add_button( + name="Save scaled anatomy", + callback=self._task_save_subject, + tooltip="Save scaled anatomy", + layout=subject_to_layout, + ) + self._renderer._layout_add_widget(mri_scaling_layout, subject_to_layout) + param_layout = self._renderer._dock_add_group_box( + name="Translation (t) and Rotation (r)", + collapse=collapse, + ) + for coord in coords: + coord_layout = self._renderer._dock_add_layout(vertical=False) + for mode, mode_name in (("t", "Translation"), ("r", "Rotation")): + name = f"{mode}{coord}" + attr = getattr(self.coreg, f"_{mode_name.lower()}") + rng = [-360, 360] if mode_name == "Rotation" else [-100, 100] + unit = "°" if mode_name == "Rotation" else "mm" + self._widgets[name] = self._renderer._dock_add_spin_box( + name=name, + value=attr[coords.index(coord)] * 1e3, + rng=np.array(rng), + callback=partial( + self._task_set_parameter, + mode_name=mode_name.lower(), + coord=coord, + ), + compact=True, + double=True, + step=1, + tooltip=f"Set the {coord} {mode_name.lower()}" + f" parameter (in {unit})", + layout=coord_layout, + ) + self._renderer._layout_add_widget(param_layout, coord_layout) + + fit_layout = self._renderer._dock_add_layout(vertical=False) + self._widgets["fit_fiducials"] = self._renderer._dock_add_button( + name="Fit fiducials", + callback=self._fit_fiducials, + tooltip="Find rotation and translation to fit all 3 fiducials", + layout=fit_layout, + ) + self._widgets["fit_icp"] = self._renderer._dock_add_button( + name="Fit ICP", + callback=self._fit_icp, + tooltip="Find rotation and translation to match the head shape points", + layout=fit_layout, + ) + self._renderer._layout_add_widget(param_layout, fit_layout) + trans_layout = self._renderer._dock_add_group_box( + name="HEAD <> MRI Transform", + collapse=collapse, + ) + save_trans_layout = self._renderer._dock_add_layout(vertical=False) + self._widgets["save_trans"] = self._renderer._dock_add_file_button( + name="save_trans", + desc="Save...", + save=True, + func=self._save_trans, + tooltip="Save the transform file to disk", + layout=save_trans_layout, + filter_="Head->MRI transformation (*-trans.fif *_trans.fif)", + initial_directory=self._info_file.parent, + ) + self._widgets["load_trans"] = self._renderer._dock_add_file_button( + name="load_trans", + desc="Load...", + func=self._load_trans, + tooltip="Load the transform file from disk", + layout=save_trans_layout, + filter_="Head->MRI transformation (*-trans.fif *_trans.fif)", + initial_directory=self._info_file.parent, + ) + self._renderer._layout_add_widget(trans_layout, save_trans_layout) + self._widgets["reset_trans"] = self._renderer._dock_add_button( + name="Reset Parameters", + callback=self._reset, + tooltip="Reset all the parameters affecting the coregistration", + layout=trans_layout, + ) + + fitting_options_layout = self._renderer._dock_add_group_box( + name="Fitting Options", + collapse=collapse, + ) + self._widgets["fit_label"] = self._renderer._dock_add_label( + value="", + layout=fitting_options_layout, + ) + self._widgets["icp_n_iterations"] = self._renderer._dock_add_spin_box( + name="Number Of ICP Iterations", + value=self._defaults["icp_n_iterations"], + rng=[1, 100], + callback=self._set_icp_n_iterations, + compact=True, + double=False, + tooltip="Set the number of ICP iterations", + layout=fitting_options_layout, + ) + self._widgets["icp_fid_match"] = self._renderer._dock_add_combo_box( + name="Fiducial point matching", + value=self._defaults["icp_fid_match"], + rng=self._defaults["icp_fid_matches"], + callback=self._set_icp_fid_match, + compact=True, + tooltip="Select the fiducial point matching method", + layout=fitting_options_layout, + ) + weights_layout = self._renderer._dock_add_group_box( + name="Weights", + layout=fitting_options_layout, + ) + for point, fid in zip(("HSP", "EEG", "HPI"), self._defaults["fiducials"]): + weight_layout = self._renderer._dock_add_layout(vertical=False) + point_lower = point.lower() + name = f"{point_lower}_weight" + self._widgets[name] = self._renderer._dock_add_spin_box( + name=point, + value=getattr(self, f"_{point_lower}_weight"), + rng=[0.0, 100.0], + callback=partial(self._set_point_weight, point=point_lower), + compact=True, + double=True, + tooltip=f"Set the {point} weight", + layout=weight_layout, + ) + + fid_lower = fid.lower() + name = f"{fid_lower}_weight" + self._widgets[name] = self._renderer._dock_add_spin_box( + name=fid, + value=getattr(self, f"_{fid_lower}_weight"), + rng=[0.0, 100.0], + callback=partial(self._set_point_weight, point=fid_lower), + compact=True, + double=True, + tooltip=f"Set the {fid} weight", + layout=weight_layout, + ) + self._renderer._layout_add_widget(weights_layout, weight_layout) + self._widgets["reset_fitting_options"] = self._renderer._dock_add_button( + name="Reset Fitting Options", + callback=self._reset_fitting_parameters, + tooltip="Reset all the fitting parameters to default value", + layout=fitting_options_layout, + ) + self._renderer._dock_add_stretch() + + def _configure_status_bar(self): + self._renderer._status_bar_initialize() + self._widgets["status_message"] = self._renderer._status_bar_add_label( + "", stretch=1 + ) + self._forward_widget_command( + "status_message", "hide", value=None, input_value=False + ) + + def _clean(self): + if not self._accept_close_event: + return + self._renderer = None + self._widgets.clear() + self._actors.clear() + self._surfaces.clear() + self._defaults.clear() + self._head_geo = None + self._check_inside = None + self._nearest = None + self._redraw = None + + @safe_event + def close(self): + """Close interface and cleanup data structure.""" + if self._renderer is not None: + self._renderer.close() + + def _close_dialog_callback(self, button_name): + from ..viz.backends.renderer import MNE_3D_BACKEND_TESTING + + self._accept_close_event = True + if button_name == "Save": + if self._trans_modified: + self._forward_widget_command("save_trans", "set_value", None) + # cancel means _save_trans is not called + if self._trans_modified: + self._accept_close_event = False + if self._mri_fids_modified: + self._forward_widget_command("save_mri_fids", "set_value", None) + if self._mri_scale_modified: + if self._subject_to: + self._save_subject(exit_mode=True) + else: + dialog = self._renderer._dialog_create( + title="CoregistrationUI", + text="The name of the output subject used to " + "save the scaled anatomy is not set.", + info_text="Please set a subject name", + callback=lambda x: None, + buttons=["Ok"], + modal=not MNE_3D_BACKEND_TESTING, + ) + dialog.show() + self._accept_close_event = False + elif button_name == "Cancel": + self._accept_close_event = False + else: + assert button_name == "Discard" + + def _close_callback(self): + if self._trans_modified or self._mri_fids_modified or self._mri_scale_modified: + from ..viz.backends.renderer import MNE_3D_BACKEND_TESTING + + # prepare the dialog's text + text = "The following is/are not saved:" + text += "
    " + if self._trans_modified: + text += "
  • Head<>MRI transform
  • " + if self._mri_fids_modified: + text += "
  • MRI fiducials
  • " + if self._mri_scale_modified: + text += "
  • scaled subject MRI
  • " + text += "
" + self._widgets["close_dialog"] = self._renderer._dialog_create( + title="CoregistrationUI", + text=text, + info_text="Do you want to save?", + callback=self._close_dialog_callback, + buttons=["Save", "Discard", "Cancel"], + # modal=True means that the dialog blocks the application + # when show() is called, until one of the buttons is clicked + modal=not MNE_3D_BACKEND_TESTING, + ) + self._widgets["close_dialog"].show() + return self._accept_close_event diff --git a/mne-python/source/mne/gui/_gui.py b/mne-python/source/mne/gui/_gui.py new file mode 100644 index 0000000000000000000000000000000000000000..b8898d8b7c2e1d62e3699b8e32e999f0dd00a6c8 --- /dev/null +++ b/mne-python/source/mne/gui/_gui.py @@ -0,0 +1,222 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ..utils import get_config, verbose + + +@verbose +def coregistration( + *, + width=None, + height=None, + inst=None, + subject=None, + subjects_dir=None, + head_opacity=None, + head_high_res=None, + trans=None, + orient_to_surface=None, + scale_by_distance=None, + mark_inside=None, + interaction=None, + fullscreen=None, + show=True, + block=False, + verbose=None, +): + """Coregister an MRI with a subject's head shape. + + The GUI can be launched through the command line interface: + + .. code-block:: bash + + $ mne coreg + + or using a python interpreter as shown in :ref:`tut-source-alignment`. + + Parameters + ---------- + width : int | None + Specify the width for window (in logical pixels). + Default is None, which uses ``MNE_COREG_WINDOW_WIDTH`` config value + (which defaults to ``800``). + height : int | None + Specify a height for window (in logical pixels). + Default is None, which uses ``MNE_COREG_WINDOW_WIDTH`` config value + (which defaults to ``400``). + inst : None | path-like + Path to an instance file containing the digitizer data. Compatible for + Raw, Epochs, and Evoked files. + subject : None | str + Name of the mri subject. + %(subjects_dir)s + head_opacity : float | None + The opacity of the head surface in the range ``[0., 1.]``. + Default is None, which uses ``MNE_COREG_HEAD_OPACITY`` config value + (which defaults to ``1.``). + head_high_res : bool | None + Use a high resolution head surface. + Default is None, which uses ``MNE_COREG_HEAD_HIGH_RES`` config value + (which defaults to True). + trans : path-like | Transform | None + The Head<->MRI transform or the path to its FIF file (``"-trans.fif"``). + orient_to_surface : bool | None + If True (default), orient EEG electrode and head shape points to the head + surface. + + .. versionadded:: 0.16 + scale_by_distance : bool | None + If True (default), scale the digitization points by their distance from the + scalp surface. + + .. versionadded:: 0.16 + mark_inside : bool | None + If True (default), mark points inside the head surface in a + different color. + + .. versionadded:: 0.16 + %(interaction_scene_none)s + Defaults to ``'terrain'``. + + .. versionadded:: 0.16 + .. versionchanged:: 1.0 + Default interaction mode if ``None`` and no config setting found + changed from ``'trackball'`` to ``'terrain'``. + %(fullscreen)s + Default is ``None``, which uses ``MNE_COREG_FULLSCREEN`` config value + (which defaults to ``False``). + + .. versionadded:: 1.1 + show : bool + Show the GUI if True. + block : bool + Whether to halt program execution until the figure is closed. + %(verbose)s + + Returns + ------- + frame : instance of CoregistrationUI + The coregistration frame. + + Notes + ----- + Many parameters (e.g., ``head_opacity``) take None as a parameter, + which means that the default will be read from the MNE-Python + configuration file (which gets saved when exiting). + + Step by step instructions for the coregistrations are shown below: + + .. youtube:: ALV5qqMHLlQ + """ + config = get_config() + if head_high_res is None: + head_high_res = config.get("MNE_COREG_HEAD_HIGH_RES", "true") == "true" + if head_opacity is None: + head_opacity = config.get("MNE_COREG_HEAD_OPACITY", 0.8) + if width is None: + width = config.get("MNE_COREG_WINDOW_WIDTH", 800) + if height is None: + height = config.get("MNE_COREG_WINDOW_HEIGHT", 600) + if subjects_dir is None: + if "SUBJECTS_DIR" in config: + subjects_dir = config["SUBJECTS_DIR"] + elif "MNE_COREG_SUBJECTS_DIR" in config: + subjects_dir = config["MNE_COREG_SUBJECTS_DIR"] + false_like = ("false", "0") + if orient_to_surface is None: + orient_to_surface = config.get("MNE_COREG_ORIENT_TO_SURFACE", "true").lower() + orient_to_surface = orient_to_surface not in false_like + if scale_by_distance is None: + scale_by_distance = config.get("MNE_COREG_SCALE_BY_DISTANCE", "true").lower() + scale_by_distance = scale_by_distance not in false_like + if interaction is None: + interaction = config.get("MNE_COREG_INTERACTION", "terrain") + if mark_inside is None: + mark_inside = config.get("MNE_COREG_MARK_INSIDE", "true").lower() + mark_inside = mark_inside not in false_like + if fullscreen is None: + fullscreen = config.get("MNE_COREG_FULLSCREEN", "") == "true" + head_opacity = float(head_opacity) + width = int(width) + height = int(height) + + from ..viz.backends.renderer import MNE_3D_BACKEND_TESTING + from ._coreg import CoregistrationUI + + if MNE_3D_BACKEND_TESTING: + show = block = False + return CoregistrationUI( + info_file=inst, + subject=subject, + subjects_dir=subjects_dir, + head_resolution=head_high_res, + head_opacity=head_opacity, + orient_glyphs=orient_to_surface, + scale_by_distance=scale_by_distance, + mark_inside=mark_inside, + trans=trans, + size=(width, height), + show=show, + block=block, + interaction=interaction, + fullscreen=fullscreen, + verbose=verbose, + ) + + +class _GUIScraper: + """Scrape GUI outputs.""" + + def __repr__(self): + return "" + + def __call__(self, block, block_vars, gallery_conf): + from ._coreg import CoregistrationUI + + gui_classes = (CoregistrationUI,) + try: + from mne_gui_addons._ieeg_locate import IntracranialElectrodeLocator + except Exception: + pass + else: + gui_classes = gui_classes + (IntracranialElectrodeLocator,) + from qtpy import QtGui + from sphinx_gallery.scrapers import figure_rst + + for gui in block_vars["example_globals"].values(): + if ( + isinstance(gui, gui_classes) + and not getattr(gui, "_scraped", False) + and gallery_conf["builder_name"] == "html" + ): + gui._scraped = True # monkey-patch but it's easy enough + img_fname = next(block_vars["image_path_iterator"]) + # TODO fix in window refactor + window = gui if hasattr(gui, "grab") else gui._renderer._window + # window is QWindow + # https://doc.qt.io/qt-5/qwidget.html#grab + pixmap = window.grab() + if hasattr(gui, "_renderer"): # if no renderer, no need + # Now the tricky part: we need to get the 3D renderer, + # extract the image from it, and put it in the correct + # place in the pixmap. The easiest way to do this is + # actually to save the 3D image first, then load it + # using QPixmap and Qt geometry. + plotter = gui._renderer.plotter + plotter.screenshot(img_fname) + sub_pixmap = QtGui.QPixmap(img_fname) + # https://doc.qt.io/qt-5/qwidget.html#mapTo + # https://doc.qt.io/qt-5/qpainter.html#drawPixmap-1 + QtGui.QPainter(pixmap).drawPixmap( + plotter.mapTo(window, plotter.rect().topLeft()), sub_pixmap + ) + # https://doc.qt.io/qt-5/qpixmap.html#save + pixmap.save(img_fname) + try: # for compatibility with both GUIs, will be refactored + gui._renderer.close() # TODO should be triggered by close + except Exception: + pass + gui.close() + return figure_rst([img_fname], gallery_conf["src_dir"], "GUI") + return "" diff --git a/mne-python/source/mne/gui/tests/__init__.py b/mne-python/source/mne/gui/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/gui/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/gui/tests/test_coreg.py b/mne-python/source/mne/gui/tests/test_coreg.py new file mode 100644 index 0000000000000000000000000000000000000000..4800bea29e1a6c960430e6a4e8b668008e955ac2 --- /dev/null +++ b/mne-python/source/mne/gui/tests/test_coreg.py @@ -0,0 +1,384 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +from contextlib import nullcontext +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose + +import mne +from mne._fiff.constants import FIFF +from mne.channels import DigMontage +from mne.coreg import Coregistration +from mne.datasets import testing +from mne.io import read_info +from mne.utils import catch_logging, get_config +from mne.viz import _3d + +data_path = testing.data_path(download=False) +raw_path = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw.fif" +fname_trans = data_path / "MEG" / "sample" / "sample_audvis_trunc-trans.fif" +subjects_dir = data_path / "subjects" +fid_fname = subjects_dir / "sample" / "bem" / "sample-fiducials.fif" +ctf_raw_path = data_path / "CTF" / "catch-alp-good-f.ds" +nirx_15_0_raw_path = ( + data_path / "NIRx" / "nirscout" / "nirx_15_0_recording" / "NIRS-2019-10-27_003.hdr" +) +nirsport2_raw_path = ( + data_path / "NIRx" / "nirsport_v2" / "aurora_2021_9" / "2021-10-01_002_config.hdr" +) +snirf_nirsport2_raw_path = ( + data_path / "SNIRF" / "NIRx" / "NIRSport2" / "1.0.3" / "2021-05-05_001.snirf" +) + + +pytest.importorskip("nibabel") + + +class TstVTKPicker: + """Class to test cell picking.""" + + def __init__(self, mesh, cell_id, event_pos): + self.mesh = mesh + self.cell_id = cell_id + self.event_pos = event_pos + + def GetCellId(self): + """Return the picked cell.""" + return self.cell_id + + def GetDataSet(self): + """Return the picked mesh.""" + return self.mesh + + def GetPickPosition(self): + """Return the picked position.""" + vtk_cell = self.mesh.GetCell(self.cell_id) + return self.mesh.points[vtk_cell.GetPointId(0)] + + def GetEventPosition(self): + """Return event position.""" + return self.event_pos + + +@pytest.mark.slowtest +@testing.requires_testing_data +@pytest.mark.parametrize( + "inst_path", + ( + raw_path, + "gen_montage", + ctf_raw_path, + nirx_15_0_raw_path, + nirsport2_raw_path, + snirf_nirsport2_raw_path, + ), +) +def test_coreg_gui_pyvista_file_support( + inst_path, tmp_path, renderer_interactive_pyvistaqt +): + """Test reading supported files.""" + from mne.gui import coregistration + + if inst_path == "gen_montage": + # generate a montage fig to use as inst. + tmp_info = read_info(raw_path) + eeg_chans = [] + for pt in tmp_info["dig"]: + if pt["kind"] == FIFF.FIFFV_POINT_EEG: + eeg_chans.append(f"EEG {pt['ident']:03d}") + + dig = DigMontage(dig=tmp_info["dig"], ch_names=eeg_chans) + inst_path = tmp_path / "tmp-dig.fif" + dig.save(inst_path) + + if inst_path == ctf_raw_path: + ctx = pytest.warns(RuntimeWarning, match="MEG ref channel RMSP") + elif inst_path == snirf_nirsport2_raw_path: # TODO: This is maybe a bug? + ctx = pytest.warns(RuntimeWarning, match='assuming "head"') + else: + ctx = nullcontext() + with ctx: + coreg = coregistration( + inst=inst_path, subject="sample", subjects_dir=subjects_dir + ) + coreg._accept_close_event = True + coreg.close() + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_coreg_gui_pyvista_basic(tmp_path, monkeypatch, renderer_interactive_pyvistaqt): + """Test that using CoregistrationUI matches mne coreg.""" + from mne.gui import coregistration + + config = get_config() + # the sample subject in testing has MRI fids + assert (subjects_dir / "sample" / "bem" / "sample-fiducials.fif").is_file() + + coreg = coregistration( + subject="sample", subjects_dir=subjects_dir, trans=fname_trans + ) + assert coreg._lock_fids + coreg._reset_fiducials() + coreg.close() + + # make it always log the distances + monkeypatch.setattr(_3d.logger, "info", _3d.logger.warning) + with catch_logging() as log: + coreg = coregistration( + inst=raw_path, + subject="sample", + head_high_res=False, # for speed + subjects_dir=subjects_dir, + verbose="debug", + ) + log = log.getvalue() + assert "Total 16/78 points inside the surface" in log + coreg._set_fiducials_file(fid_fname) + assert coreg._fiducials_file == str(fid_fname) + + # fitting (with scaling) + assert not coreg._mri_scale_modified + coreg._reset() + coreg._reset_fitting_parameters() + coreg._set_scale_mode("uniform") + coreg._fits_fiducials() + assert_allclose( + coreg.coreg._scale, np.array([97.46, 97.46, 97.46]) * 1e-2, atol=1e-3 + ) + shown_scale = [coreg._widgets[f"s{x}"].get_value() for x in "XYZ"] + assert_allclose(shown_scale, coreg.coreg._scale * 100, atol=1e-2) + coreg._set_icp_fid_match("nearest") + coreg._set_scale_mode("3-axis") + coreg._fits_icp() + assert_allclose( + coreg.coreg._scale, np.array([104.43, 101.47, 125.78]) * 1e-2, atol=1e-3 + ) + shown_scale = [coreg._widgets[f"s{x}"].get_value() for x in "XYZ"] + assert_allclose(shown_scale, coreg.coreg._scale * 100, atol=1e-2) + coreg._set_scale_mode("None") + coreg._set_icp_fid_match("matched") + assert coreg._mri_scale_modified + + # unlock fiducials + assert coreg._lock_fids + coreg._set_lock_fids(False) + assert not coreg._lock_fids + + # picking + assert not coreg._mri_fids_modified + vtk_picker = TstVTKPicker(coreg._surfaces["head"], 0, (0, 0)) + coreg._on_mouse_move(vtk_picker, None) + coreg._on_button_press(vtk_picker, None) + coreg._on_pick(vtk_picker, None) + coreg._on_button_release(vtk_picker, None) + coreg._on_pick(vtk_picker, None) # also pick when locked + assert coreg._mri_fids_modified + + # lock fiducials + coreg._set_lock_fids(True) + assert coreg._lock_fids + + # fitting (no scaling) + assert coreg._nasion_weight == 10.0 + coreg._set_point_weight(11.0, "nasion") + assert coreg._nasion_weight == 11.0 + coreg._fit_fiducials() + with catch_logging() as log: + coreg._redraw() # actually emit the log + log = log.getvalue() + assert "Total 6/78 points inside the surface" in log + with catch_logging() as log: + coreg._fit_icp() + coreg._redraw() + log = log.getvalue() + assert "Total 38/78 points inside the surface" in log + assert coreg.coreg._extra_points_filter is None + coreg._omit_hsp() + with catch_logging() as log: + coreg._redraw() + log = log.getvalue() + assert "Total 29/53 points inside the surface" in log + assert coreg.coreg._extra_points_filter is not None + coreg._reset_omit_hsp_filter() + with catch_logging() as log: + coreg._redraw() + log = log.getvalue() + assert "Total 38/78 points inside the surface" in log + assert coreg.coreg._extra_points_filter is None + + assert coreg._grow_hair == 0 + coreg._fit_fiducials() # go back to few inside to start + with catch_logging() as log: + coreg._redraw() + log = log.getvalue() + assert "Total 6/78 points inside the surface" in log + norm = np.linalg.norm(coreg._head_geo["rr"]) # what's used for inside + assert_allclose(norm, 5.949288, atol=1e-3) + coreg._set_grow_hair(20.0) + with catch_logging() as log: + coreg._redraw() + assert coreg._grow_hair == 20.0 + norm = np.linalg.norm(coreg._head_geo["rr"]) + assert_allclose(norm, 6.555220, atol=1e-3) # outward + log = log.getvalue() + assert "Total 8/78 points inside the surface" in log # more outside now + + # visualization + assert not coreg._helmet + assert coreg._actors["helmet"] is None + coreg._set_helmet(True) + assert coreg._eeg_channels + coreg._set_eeg_channels(False) + assert not coreg._eeg_channels + assert coreg._helmet + with catch_logging() as log: + coreg._redraw(verbose="debug") + log = log.getvalue() + assert "Drawing helmet" in log + coreg._set_point_weight(1.0, "nasion") + coreg._fit_fiducials() + with catch_logging() as log: + coreg._redraw(verbose="debug") + log = log.getvalue() + assert "Drawing helmet" in log + assert not coreg._meg_channels + assert coreg._actors["helmet"] is not None + # TODO: Someday test our file dialogs like: + # coreg._widgets["save_trans"].widget.click() + assert len(coreg._actors["sensors"]) == 0 + coreg._set_meg_channels(True) + assert coreg._meg_channels + with catch_logging() as log: + coreg._redraw(verbose="debug") + assert "Drawing meg sensors" in log.getvalue() + assert coreg._actors["helmet"] is not None + assert len(coreg._actors["sensors"]) == 306 + assert coreg._orient_glyphs + assert coreg._scale_by_distance + assert coreg._mark_inside + assert_allclose( + coreg._head_opacity, float(config.get("MNE_COREG_HEAD_OPACITY", "0.8")) + ) + assert coreg._hpi_coils + assert coreg._head_shape_points + assert coreg._scale_mode == "None" + assert coreg._icp_fid_match == "matched" + assert coreg._head_resolution is False + + assert coreg._trans_modified + tmp_trans = tmp_path / "tmp-trans.fif" + coreg._save_trans(tmp_trans) + assert not coreg._trans_modified + assert tmp_trans.is_file() + + # first, disable auto cleanup + coreg._renderer._window_close_disconnect(after=True) + # test _close_callback() + coreg._renderer._process_events() + assert coreg._mri_fids_modified # should prompt + assert coreg._renderer.plotter.app_window.children() is not None + assert "close_dialog" not in coreg._widgets + assert not coreg._renderer.plotter._closed + assert coreg._accept_close_event + # make sure it's ignored (PySide6 causes problems here and doesn't wait) + coreg._accept_close_event = False + coreg.close() + assert not coreg._renderer.plotter._closed + coreg._widgets["close_dialog"].trigger("Discard") # do not save + coreg.close() + assert coreg._renderer.plotter._closed + coreg._clean() # finally, cleanup internal structures + assert coreg._renderer is None + + # Coregistration instance should survive + assert isinstance(coreg.coreg, Coregistration) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_fullscreen(renderer_interactive_pyvistaqt): + """Test fullscreen mode.""" + from mne.gui import coregistration + + # Fullscreen mode + coreg = coregistration(subject="sample", subjects_dir=subjects_dir, fullscreen=True) + coreg._accept_close_event = True + coreg.close() + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_coreg_gui_scraper(tmp_path, renderer_interactive_pyvistaqt): + """Test the scrapper for the coregistration GUI.""" + pytest.importorskip("sphinx_gallery") + from mne.gui import coregistration + + coreg = coregistration( + subject="sample", subjects_dir=subjects_dir, trans=fname_trans + ) + (tmp_path / "_images").mkdir() + image_path = tmp_path / "_images" / "temp.png" + gallery_conf = dict(builder_name="html", src_dir=tmp_path) + block_vars = dict( + example_globals=dict(gui=coreg), image_path_iterator=iter([str(image_path)]) + ) + assert not image_path.is_file() + assert not getattr(coreg, "_scraped", False) + mne.gui._GUIScraper()(None, block_vars, gallery_conf) + assert image_path.is_file() + assert coreg._scraped + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_coreg_gui_notebook(renderer_notebook, nbexec): + """Test the coregistration UI in a notebook.""" + import pytest + + import mne + from mne.datasets import testing + from mne.gui import coregistration + + mne.viz.set_3d_backend("notebook") # set the 3d backend + with pytest.MonkeyPatch().context() as mp: + mp.delenv("_MNE_FAKE_HOME_DIR") + data_path = testing.data_path(download=False) + subjects_dir = data_path / "subjects" + coregistration(subject="sample", subjects_dir=subjects_dir) + + +@pytest.mark.slowtest +def test_no_sparse_head(subjects_dir_tmp, renderer_interactive_pyvistaqt, monkeypatch): + """Test mne.gui.coregistration with no sparse head.""" + from mne.gui import coregistration + + subjects_dir_tmp = Path(subjects_dir_tmp) + subject = "sample" + out_rr, out_tris = mne.read_surface( + subjects_dir_tmp / subject / "bem" / "outer_skin.surf" + ) + for head in ("sample-head.fif", "outer_skin.surf"): + os.remove(subjects_dir_tmp / subject / "bem" / head) + # Avoid actually doing the decimation (it's slow) + monkeypatch.setattr( + mne.coreg, "decimate_surface", lambda rr, tris, n_triangles: (out_rr, out_tris) + ) + with pytest.warns(RuntimeWarning, match="No low-resolution head found"): + coreg = coregistration( + inst=raw_path, subject=subject, subjects_dir=subjects_dir_tmp + ) + coreg.close() + + +def test_splash_closed(tmp_path, renderer_interactive_pyvistaqt): + """Test that the splash closes on error.""" + from mne.gui import coregistration + + with pytest.raises(RuntimeError, match="No standard head model"): + coregistration(subjects_dir=tmp_path, subject="fsaverage") diff --git a/mne-python/source/mne/gui/tests/test_gui_api.py b/mne-python/source/mne/gui/tests/test_gui_api.py new file mode 100644 index 0000000000000000000000000000000000000000..5be82d27af6d1b60f9d5f9becdff43e00331bb3f --- /dev/null +++ b/mne-python/source/mne/gui/tests/test_gui_api.py @@ -0,0 +1,391 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import pytest + +from mne.utils import _check_qt_version + +# These will skip all tests in this scope +pytest.importorskip("nibabel") + + +def test_gui_api(renderer_notebook, nbexec, *, backend="qt"): + """Test GUI API.""" + import contextlib + import warnings + + import mne + + try: + # Function + backend # noqa + except Exception: + # Notebook standalone mode + backend = "notebook" + # nbexec does not expose renderer_notebook so I use a + # temporary variable to synchronize the tests + if backend == "notebook": + mne.viz.set_3d_backend("notebook") + renderer = mne.viz.backends.renderer._get_renderer(size=(300, 300)) + + # theme + with warnings.catch_warnings(record=True) as w: + warnings.simplefilter("always") + renderer._window_set_theme("/does/not/exist") + if backend == "qt": + assert len(w) == 1 + assert "not found" in str(w[0].message), str(w[0].message) + else: + assert len(w) == 0 + with mne.utils._record_warnings() as w: + renderer._window_set_theme("dark") + w = [ww for ww in w if "is not yet supported" in str(ww.message)] + assert len(w) == 0, [ww.message for ww in w] + + # window without 3d plotter + if backend == "qt": + window = renderer._window_create() + widget = renderer._window_create() + central_layout = renderer._layout_create(orientation="grid") + renderer._layout_add_widget(central_layout, widget, row=0, col=0) + renderer._window_initialize(window=window, central_layout=central_layout) + + from unittest.mock import Mock + + mock = Mock() + + @contextlib.contextmanager + def _check_widget_trigger( + widget, mock, before, after, call_count=True, get_value=True + ): + if get_value: + assert widget.get_value() == before + old_call_count = mock.call_count + try: + yield + finally: + if get_value: + assert widget.get_value() == after + if call_count: + assert mock.call_count == old_call_count + 1 + + # --- BEGIN: dock --- + renderer._dock_initialize(name="", area="left") + + # label (not interactive) + widget = renderer._dock_add_label( + value="", + align=False, + selectable=True, + ) + widget = renderer._dock_add_label( + value="", + align=True, + ) + widget.update() + # labels are disabled by default with the notebook backend + widget.set_enabled(False) + assert not widget.is_enabled() + widget.set_enabled(True) + assert widget.is_enabled() + + # ToolButton + widget = renderer._dock_add_button( + name="", + callback=mock, + style="toolbutton", + tooltip="button", + ) + with _check_widget_trigger(widget, mock, None, None, get_value=False): + widget.set_value(True) + + # PushButton + widget = renderer._dock_add_button( + name="", + callback=mock, + ) + with _check_widget_trigger(widget, mock, None, None, get_value=False): + widget.set_value(True) + + # slider + widget = renderer._dock_add_slider( + name="", + value=0, + rng=[0, 10], + callback=mock, + tooltip="slider", + ) + with _check_widget_trigger(widget, mock, 0, 5): + widget.set_value(5) + + # check box + widget = renderer._dock_add_check_box( + name="", + value=False, + callback=mock, + tooltip="check box", + ) + with _check_widget_trigger(widget, mock, False, True): + widget.set_value(True) + + # spin box + renderer._dock_add_spin_box( + name="", + value=0, + rng=[0, 1], + callback=mock, + step=0.1, + tooltip="spin box", + ) + widget = renderer._dock_add_spin_box( + name="", + value=0, + rng=[0, 1], + callback=mock, + step=None, + ) + with _check_widget_trigger(widget, mock, 0, 0.5): + widget.set_value(0.5) + + # combo box + widget = renderer._dock_add_combo_box( + name="", + value="foo", + rng=["foo", "bar"], + callback=mock, + tooltip="combo box", + ) + with _check_widget_trigger(widget, mock, "foo", "bar"): + widget.set_value("bar") + + # radio buttons + widget = renderer._dock_add_radio_buttons( + value="foo", + rng=["foo", "bar"], + callback=mock, + ) + with _check_widget_trigger(widget, mock, None, None, get_value=False): + widget.set_value(1, "bar") + assert widget.get_value(0) == "foo" + assert widget.get_value(1) == "bar" + widget.set_enabled(False) + + # text field + widget = renderer._dock_add_text( + name="", + value="foo", + placeholder="", + callback=mock, + ) + with _check_widget_trigger(widget, mock, "foo", "bar"): + widget.set_value("bar") + widget.set_style(dict(border="2px solid #ff0000")) + + # file button + renderer._dock_add_file_button( + name="", + desc="", + func=mock, + is_directory=True, + tooltip="file button", + ) + + renderer._dock_add_file_button( + name="", + desc="", + func=mock, + initial_directory="", + ) + renderer._dock_add_file_button( + name="", + desc="", + func=mock, + ) + widget = renderer._dock_add_file_button(name="", desc="", func=mock, save=True) + # XXX: the internal file dialogs may hang without signals + widget.set_enabled(False) + + renderer._dock_initialize(name="", area="right") + renderer._dock_named_layout(name="") + for collapse in (None, True, False): + renderer._dock_add_group_box(name="", collapse=collapse) + renderer._dock_add_stretch() + renderer._dock_add_layout() + renderer._dock_finalize() + renderer._dock_hide() + renderer._dock_show() + # --- END: dock --- + + # --- BEGIN: tool bar --- + renderer._tool_bar_initialize( + name="default", + window=None, + ) + + # button + assert "reset" not in renderer.actions + renderer._tool_bar_add_button( + name="reset", + desc="", + func=mock, + icon_name="help", + ) + assert "reset" in renderer.actions + + # icon + renderer._tool_bar_update_button_icon( + name="reset", + icon_name="reset", + ) + + # text + renderer._tool_bar_add_text( + name="", + value="", + placeholder="", + ) + + # spacer + renderer._tool_bar_add_spacer() + + # file button + assert "help" not in renderer.actions + renderer._tool_bar_add_file_button( + name="help", + desc="", + func=mock, + shortcut=None, + ) + renderer.actions["help"].trigger() + if renderer._kind == "qt": + dialog = renderer._window.children()[-1] + assert "FileDialog" in repr(dialog) + dialog.close() + dialog.deleteLater() + + # play button + assert "play" not in renderer.actions + renderer._tool_bar_add_play_button( + name="play", + desc="", + func=mock, + shortcut=None, + ) + assert "play" in renderer.actions + # --- END: tool bar --- + + # --- BEGIN: menu bar --- + renderer._menu_initialize() + + # submenu + renderer._menu_add_submenu(name="foo", desc="foo") + assert "foo" in renderer._menus + assert "foo" in renderer._menu_actions + + # button + renderer._menu_add_button( + menu_name="foo", + name="bar", + desc="bar", + func=mock, + ) + assert "bar" in renderer._menu_actions["foo"] + with _check_widget_trigger(None, mock, "", "", get_value=False): + renderer._menu_actions["foo"]["bar"].trigger() + + # --- END: menu bar --- + + # --- BEGIN: status bar --- + renderer._status_bar_initialize() + renderer._status_bar_update() + + # label + widget = renderer._status_bar_add_label(value="foo", stretch=0) + assert widget.get_value() == "foo" + + # progress bar + widget = renderer._status_bar_add_progress_bar(stretch=0) + # by default, get_value() is -1 for Qt and 0 for Ipywidgets + widget.set_value(0) + assert widget.get_value() == 0 + # --- END: status bar --- + + # --- BEGIN: tooltips --- + widget = renderer._dock_add_button(name="", callback=mock, tooltip="foo") + assert widget.get_tooltip() == "foo" + # Change it … + widget.set_tooltip("bar") + assert widget.get_tooltip() == "bar" + # --- END: tooltips --- + + # --- BEGIN: dialog --- + # dialogs are not supported yet on notebook + if renderer._kind == "qt": + # warning + buttons = ["Save", "Cancel"] + widget = renderer._dialog_create( + title="", + text="", + info_text="", + callback=mock, + buttons=buttons, + modal=False, + ) + widget.show() + for button in buttons: + with _check_widget_trigger(None, mock, "", "", get_value=False): + widget.trigger(button=button) + assert mock.call_args.args == (button,) + assert not widget._widget.isVisible() + + # buttons list empty means OK button (default) + button = "Ok" + widget = renderer._dialog_create( + title="", + text="", + info_text="", + callback=mock, + icon="NoIcon", + modal=False, + ) + widget.show() + with _check_widget_trigger(None, mock, "", "", get_value=False): + widget.trigger(button=button) + assert mock.call_args.args == (button,) + widget.trigger(button="Ok") + + # --- END: dialog --- + + # --- BEGIN: keypress --- + renderer._keypress_initialize() + renderer._keypress_add("a", mock) + # keypress is not supported yet on notebook + if renderer._kind == "qt": + with _check_widget_trigger(None, mock, "", "", get_value=False): + renderer._keypress_trigger("a") + # --- END: keypress --- + + renderer.show() + + renderer._window_close_connect(lambda: mock("first"), after=False) + renderer._window_close_connect(lambda: mock("last")) + old_call_count = mock.call_count + renderer.close() + if renderer._kind == "qt": + assert mock.call_count == old_call_count + 2 + assert mock.call_args_list[-1].args == ("last",) + assert mock.call_args_list[-2].args == ("first",) + assert renderer._window.isVisible() is False + del renderer + + +def test_gui_api_qt(renderer_interactive_pyvistaqt): + """Test GUI API with the Qt backend.""" + _, api = _check_qt_version(return_api=True) + # TODO: After merging https://github.com/mne-tools/mne-python/pull/11567 + # The Qt CI run started failing about 50% of the time, so let's skip this + # for now. + if api == "PySide6": + pytest.skip("PySide6 causes segfaults on CIs sometimes") + test_gui_api(None, None, backend="qt") diff --git a/mne-python/source/mne/html_templates/__init__.py b/mne-python/source/mne/html_templates/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..b8234d27037b4a5db2984ae061b09434aae1af9a --- /dev/null +++ b/mne-python/source/mne/html_templates/__init__.py @@ -0,0 +1,8 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Jinja2 HTML templates.""" +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/html_templates/__init__.pyi b/mne-python/source/mne/html_templates/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..2312227d990ac89c53983d7f6a76b0c0af8f4efb --- /dev/null +++ b/mne-python/source/mne/html_templates/__init__.pyi @@ -0,0 +1,2 @@ +__all__ = ["_get_html_template"] +from ._templates import _get_html_template diff --git a/mne-python/source/mne/html_templates/_templates.py b/mne-python/source/mne/html_templates/_templates.py new file mode 100644 index 0000000000000000000000000000000000000000..1f68303a51e528fbc3b48082d6519d365bd90ea7 --- /dev/null +++ b/mne-python/source/mne/html_templates/_templates.py @@ -0,0 +1,171 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from __future__ import annotations # only needed for Python ≤ 3.9 + +import datetime +import functools +import uuid +from dataclasses import dataclass +from typing import Any, Literal + +from .._fiff.pick import channel_type +from ..defaults import _handle_default + +_COLLAPSED = False # will override in doc build + + +def _format_number(value: int | float) -> str: + """Insert thousand separators.""" + return f"{value:,}" + + +def _append_uuid(string: str, sep: str = "-") -> str: + """Append a UUID to a string.""" + return f"{string}{sep}{uuid.uuid4()}" + + +def _data_type(obj) -> str: + """Return the qualified name of a class.""" + return obj.__class__.__qualname__ + + +def _dt_to_str(dt: datetime.datetime) -> str: + """Convert a datetime object to a human-readable string representation.""" + return dt.strftime("%Y-%m-%d at %H:%M:%S %Z") + + +def _format_baseline(inst) -> str: + """Format the baseline time period.""" + if inst.baseline is None: + baseline = "off" + else: + baseline = ( + f"{round(inst.baseline[0], 3):.3f} – {round(inst.baseline[1], 3):.3f} s" + ) + + return baseline + + +def _format_metadata(inst) -> str: + """Format metadata representation.""" + if inst.metadata is None: + metadata = "No metadata set" + else: + metadata = f"{inst.metadata.shape[0]} rows × {inst.metadata.shape[1]} columns" + + return metadata + + +def _format_time_range(inst) -> str: + """Format evoked and epochs time range.""" + tr = f"{round(inst.tmin, 3):.3f} – {round(inst.tmax, 3):.3f} s" + return tr + + +def _format_projs(info) -> list[str]: + """Format projectors.""" + projs = [f"{p['desc']} ({'on' if p['active'] else 'off'})" for p in info["projs"]] + return projs + + +@dataclass +class _Channel: + """A channel in a recording.""" + + index: int + name_html: str + type: str + type_pretty: str + status: Literal["good", "bad"] + + +def _format_channels(info) -> dict[str, dict[Literal["good", "bad"], list[str]]]: + """Format channel names.""" + ch_types_pretty: dict[str, str] = _handle_default("titles") + channels = [] + + if info.ch_names: + for ch_index, ch_name in enumerate(info.ch_names): + ch_type = channel_type(info, ch_index) + ch_type_pretty = ch_types_pretty.get(ch_type, ch_type.upper()) + ch_status = "bad" if ch_name in info["bads"] else "good" + channel = _Channel( + index=ch_index, + name_html=ch_name.replace(" ", " "), + type=ch_type, + type_pretty=ch_type_pretty, + status=ch_status, + ) + channels.append(channel) + + # Extract unique channel types and put them in the desired order. + ch_types = list(set([c.type_pretty for c in channels])) + ch_types = [c for c in ch_types_pretty.values() if c in ch_types] + + channels_formatted = {} + for ch_type in ch_types: + goods = [c for c in channels if c.type_pretty == ch_type and c.status == "good"] + bads = [c for c in channels if c.type_pretty == ch_type and c.status == "bad"] + if ch_type not in channels_formatted: + channels_formatted[ch_type] = {"good": [], "bad": []} + channels_formatted[ch_type]["good"] = goods + channels_formatted[ch_type]["bad"] = bads + + return channels_formatted + + +def _has_attr(obj: Any, attr: str) -> bool: + """Check if an object has an attribute `obj.attr`. + + This is needed because on dict-like objects, Jinja2's `obj.attr is defined` would + check for `obj["attr"]`, which may not be what we want. + """ + return hasattr(obj, attr) + + +@functools.lru_cache(maxsize=2) +def _get_html_templates_env(kind): + # For _html_repr_() and mne.Report + assert kind in ("repr", "report"), kind + import jinja2 + + templates_env = jinja2.Environment( + loader=jinja2.PackageLoader( + package_name="mne.html_templates", package_path=kind + ), + autoescape=jinja2.select_autoescape(default=True, default_for_string=True), + ) + if kind == "report": + templates_env.filters["zip"] = zip + + templates_env.filters["format_number"] = _format_number + templates_env.filters["append_uuid"] = _append_uuid + templates_env.filters["data_type"] = _data_type + templates_env.filters["dt_to_str"] = _dt_to_str + templates_env.filters["format_baseline"] = _format_baseline + templates_env.filters["format_metadata"] = _format_metadata + templates_env.filters["format_time_range"] = _format_time_range + templates_env.filters["format_projs"] = _format_projs + templates_env.filters["format_channels"] = _format_channels + templates_env.filters["has_attr"] = _has_attr + return templates_env + + +def _get_html_template(kind, name): + return _RenderWrap( + _get_html_templates_env(kind).get_template(name), + collapsed=_COLLAPSED, + ) + + +class _RenderWrap: + """Class that allows functools.partial-like wrapping of jinja2 Template.render().""" + + def __init__(self, template, **kwargs): + self._template = template + self._kwargs = kwargs + + def render(self, *args, **kwargs): + return self._template.render(*args, **kwargs, **self._kwargs) diff --git a/mne-python/source/mne/html_templates/report/bem.html.jinja b/mne-python/source/mne/html_templates/report/bem.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..a04a4c08d8f56d9f61060a0c01632d8f5dda378d --- /dev/null +++ b/mne-python/source/mne/html_templates/report/bem.html.jinja @@ -0,0 +1,8 @@ +{% extends "section.html.jinja" %} +{% block html_content %} +
+ {{ html_slider_axial | safe }} + {{ html_slider_sagittal | safe }} + {{ html_slider_coronal | safe }} +
+{% endblock html_content %} diff --git a/mne-python/source/mne/html_templates/report/code.html.jinja b/mne-python/source/mne/html_templates/report/code.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..63783e4594ecceef4fa85c68b2acb3da5c365e98 --- /dev/null +++ b/mne-python/source/mne/html_templates/report/code.html.jinja @@ -0,0 +1,6 @@ +{% extends "section.html.jinja" %} +{% block html_content %} +
+  {{ code }}
+
+{% endblock html_content %} diff --git a/mne-python/source/mne/html_templates/report/footer.html.jinja b/mne-python/source/mne/html_templates/report/footer.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..9733155d943c95eb7b8889dcc9ef54e154cd1be1 --- /dev/null +++ b/mne-python/source/mne/html_templates/report/footer.html.jinja @@ -0,0 +1,10 @@ + + +
+ +
+ + + diff --git a/mne-python/source/mne/html_templates/report/forward.html.jinja b/mne-python/source/mne/html_templates/report/forward.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..68c8ebecc27aa9794d26f51f96c8538618be7b20 --- /dev/null +++ b/mne-python/source/mne/html_templates/report/forward.html.jinja @@ -0,0 +1,6 @@ +{% extends "section.html.jinja" %} +{% block html_content %} +{{repr | safe}} +{{sensitivity_maps | safe}} +{{source_space | safe}} +{% endblock html_content %} diff --git a/mne-python/source/mne/html_templates/report/header.html.jinja b/mne-python/source/mne/html_templates/report/header.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..692dbab7a7e4dd75c809021dd3455517407e8a87 --- /dev/null +++ b/mne-python/source/mne/html_templates/report/header.html.jinja @@ -0,0 +1,56 @@ + + + + + + {{include | safe }} + + + + + {{ title }} + + + + diff --git a/mne-python/source/mne/html_templates/report/html.html.jinja b/mne-python/source/mne/html_templates/report/html.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..a9b4f881f12a50f4c0754cb953ac8492f7e8ccc7 --- /dev/null +++ b/mne-python/source/mne/html_templates/report/html.html.jinja @@ -0,0 +1,19 @@ +
+
+ +
+
+
+ {{ html | safe }} +
+
+
diff --git a/mne-python/source/mne/html_templates/report/image.html.jinja b/mne-python/source/mne/html_templates/report/image.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..c3f6e42f06fddd0e071ef877767e192cf86c4e30 --- /dev/null +++ b/mne-python/source/mne/html_templates/report/image.html.jinja @@ -0,0 +1,19 @@ +{% if not embedded %} +{% extends "section.html.jinja" %} +{% endif %} +{% block html_content %} +
+ {% if image_format == 'svg' %} +
+ {{ img|safe }} +
+ {% else %} + {{ title }} + {% endif %} + + {% if caption is not none %} +
{{ caption }}
+ {% endif %} +
+{% endblock html_content %} diff --git a/mne-python/source/mne/html_templates/report/inverse.html.jinja b/mne-python/source/mne/html_templates/report/inverse.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..ca03f3c29af8ce72e4f3f925f7157951f74d2110 --- /dev/null +++ b/mne-python/source/mne/html_templates/report/inverse.html.jinja @@ -0,0 +1,5 @@ +{% extends "section.html.jinja" %} +{% block html_content %} +{{repr | safe}} +{{source_space | safe}} +{% endblock html_content %} diff --git a/mne-python/source/mne/html_templates/report/section.html.jinja b/mne-python/source/mne/html_templates/report/section.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..baddf7dd8b6a1d49af2b9312b5e9c60f873c7141 --- /dev/null +++ b/mne-python/source/mne/html_templates/report/section.html.jinja @@ -0,0 +1,23 @@ +
+
+ +
+
+
+ {% block html_content %} + {% for html in htmls %} + {{ html | safe }} + {% endfor %} + {% endblock %} +
+
+
diff --git a/mne-python/source/mne/html_templates/report/slider.html.jinja b/mne-python/source/mne/html_templates/report/slider.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..fab7f56472d449bf3f3613a099d4369da042ac5c --- /dev/null +++ b/mne-python/source/mne/html_templates/report/slider.html.jinja @@ -0,0 +1,49 @@ +
+
+ +
+
+
+
+ + +
+ +
+
+
diff --git a/mne-python/source/mne/html_templates/report/toc.html.jinja b/mne-python/source/mne/html_templates/report/toc.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..0b714632ae535757e485c7170b9c178266b54cff --- /dev/null +++ b/mne-python/source/mne/html_templates/report/toc.html.jinja @@ -0,0 +1,12 @@ +
+
+
+
Table of contents
+ +
+
diff --git a/mne-python/source/mne/html_templates/repr/_acquisition.html.jinja b/mne-python/source/mne/html_templates/repr/_acquisition.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..e1ee4f69dd34abe5052d1ec425a58a6d6717a83c --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/_acquisition.html.jinja @@ -0,0 +1,97 @@ +{% set section = "Acquisition" %} +{% set section_class_name = section | lower | append_uuid %} + +{# Collapse content during documentation build. #} +{% if collapsed %} +{% set collapsed_row_class = "mne-repr-collapsed" %} +{% else %} +{% set collapsed_row_class = "" %} +{% endif %} + +{%include 'static/_section_header_row.html.jinja' %} + +{% if duration %} + + + Duration + {{ duration }} (HH:MM:SS) + +{% endif %} +{% if inst is defined and inst | has_attr("kind") and inst | has_attr("nave") %} + + + Aggregation + {% if inst.kind == "average" %} + average of {{ inst.nave }} epochs + {% elif inst.kind == "standard_error" %} + standard error of {{ inst.nave }} epochs + {% else %} + {{ inst.kind }} ({{ inst.nave }} epochs) + {% endif %} + +{% endif %} +{% if inst is defined and inst | has_attr("comment") %} + + + Condition + {{inst.comment}} + +{% endif %} +{% if inst is defined and inst | has_attr("events") %} + + + Total number of events + {{ inst.events | length }} + +{% endif %} +{% if event_counts is defined %} + + + Events counts + {% if events is not none %} + + {% for e in event_counts %} + {{ e }} + {% if not loop.last %}
{% endif %} + {% endfor %} + + {% else %} + Not available + {% endif %} + +{% endif %} +{% if inst is defined and inst | has_attr("tmin") and inst | has_attr("tmax") %} + + + Time range + {{ inst | format_time_range }} + +{% endif %} +{% if inst is defined and inst | has_attr("baseline") %} + + + Baseline + {{ inst | format_baseline }} + +{% endif %} +{% if info["sfreq"] is defined and info["sfreq"] is not none %} + + + Sampling frequency + {{ "%0.2f" | format(info["sfreq"]) }} Hz + +{% endif %} +{% if inst is defined and inst | has_attr("times") and inst.times is defined %} + + + Time points + {{ inst.times | length | format_number }} + +{% endif %} +{% if inst is defined and inst | has_attr("metadata") %} + + + Metadata + {{ inst | format_metadata }} + +{% endif %} \ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/_channels.html.jinja b/mne-python/source/mne/html_templates/repr/_channels.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..1d057b9688ffccb7ac4b1d1b8b174c41911255f3 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/_channels.html.jinja @@ -0,0 +1,25 @@ +{% set section = "Channels" %} +{% set section_class_name = section | lower | append_uuid %} + +{# Collapse content during documentation build. #} +{% if collapsed %} +{% set collapsed_row_class = "mne-repr-collapsed" %} +{% else %} +{% set collapsed_row_class = "" %} +{% endif %} + +{%include 'static/_section_header_row.html.jinja' %} + +{% for channel_type, channels in (info | format_channels).items() %} + {% include 'static/_channels.html.jinja' %} +{% endfor %} + + + + Head & sensor digitization + {% if info["dig"] is not none %} + {{ info["dig"] | length }} points + {% else %} + Not available + {% endif %} + \ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/_filters.html.jinja b/mne-python/source/mne/html_templates/repr/_filters.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..97ede5157c15ace3b5d93c4ba378af14bbdd6740 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/_filters.html.jinja @@ -0,0 +1,38 @@ +{% set section = "Filters" %} +{% set section_class_name = section | lower | append_uuid %} + +{# Collapse content during documentation build. #} +{% if collapsed %} +{% set collapsed_row_class = "mne-repr-collapsed" %} +{% else %} +{% set collapsed_row_class = "" %} +{% endif %} + +{%include 'static/_section_header_row.html.jinja' %} + +{% if info["highpass"] is defined and info["highpass"] is not none %} + + + Highpass + {{ "%0.2f" | format(info["highpass"]) }} Hz + +{% endif %} +{% if info["lowpass"] is defined and info["lowpass"] is not none %} + + + Lowpass + {{ "%0.2f" | format(info["lowpass"]) }} Hz + +{% endif %} +{% if info.projs is defined and info.projs %} + + + Projections + + {% for p in (info | format_projs) %} + {{ p }} + {% if not loop.last %}
{% endif %} + {% endfor %} + + +{% endif %} \ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/_frequencies.html.jinja b/mne-python/source/mne/html_templates/repr/_frequencies.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..b55b8ddf88322751ba5e396d944ca65c80af375a --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/_frequencies.html.jinja @@ -0,0 +1,62 @@ +{% set section = "Frequencies" %} +{% set section_class_name = section | lower | append_uuid %} + +{# Collapse content during documentation build. #} +{% if collapsed %} +{% set collapsed_row_class = "mne-repr-collapsed" %} +{% else %} +{% set collapsed_row_class = "" %} +{% endif %} + +{%include 'static/_section_header_row.html.jinja' %} + + + + Data type + {{ inst._data_type }} + + + + Computed from + {{ computed_from }} + + + + Estimation method + {{ inst.method }} + + +{% if "taper" in inst._dims %} + + + Number of tapers + {{ inst._mt_weights.size }} + +{% endif %} +{% if inst.freqs is defined %} + + + Frequency range + {{ '%.2f'|format(inst.freqs[0]) }} – {{ '%.2f'|format(inst.freqs[-1]) }} Hz + + + + Number of frequency bins + {{ inst.freqs|length }} + +{%- for unit in units %} + + + {%- if loop.index == 1 %} + Units + {%- endif %} + {{ unit }} + +{%- endfor %} +{% endif %} diff --git a/mne-python/source/mne/html_templates/repr/_general.html.jinja b/mne-python/source/mne/html_templates/repr/_general.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..a57ae40049d6ec78dda8add9b9f510bf9a1a2825 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/_general.html.jinja @@ -0,0 +1,58 @@ +{% set section = "General" %} +{% set section_class_name = section | lower | append_uuid %} + +{# Collapse content during documentation build. #} +{% if collapsed %} +{% set collapsed_row_class = "mne-repr-collapsed" %} +{% else %} +{% set collapsed_row_class = "" %} +{% endif %} + +{%include 'static/_section_header_row.html.jinja' %} + +{% if filenames %} + + + Filename(s) + + {% for f in filenames %} + {{ f }} + {% if not loop.last %}
{% endif %} + {% endfor %} + + +{% endif %} + + + MNE object type + {{ inst | data_type }} + + + + Measurement date + {% if info["meas_date"] is defined and info["meas_date"] is not none %} + {{ info["meas_date"] | dt_to_str }} + {% else %} + Unknown + {% endif %} + + + + Participant + {% if info["subject_info"] is defined and info["subject_info"] is not none %} + {% if info["subject_info"]["his_id"] is defined %} + {{ info["subject_info"]["his_id"] }} + {% endif %} + {% else %} + Unknown + {% endif %} + + + + Experimenter + {% if info["experimenter"] is defined and info["experimenter"] is not none %} + {{ info["experimenter"] }} + {% else %} + Unknown + {% endif %} + \ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/_js_and_css.html.jinja b/mne-python/source/mne/html_templates/repr/_js_and_css.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..f185cfbe00a8eadb10b76ccb0126e2aca7f81a48 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/_js_and_css.html.jinja @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/epochs.html.jinja b/mne-python/source/mne/html_templates/repr/epochs.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..6b33c177e87e17d592d7f1cf511854c4a5122b28 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/epochs.html.jinja @@ -0,0 +1,10 @@ +{%include '_js_and_css.html.jinja' %} + +{% set info = inst.info %} + + + {%include '_general.html.jinja' %} + {%include '_acquisition.html.jinja' %} + {%include '_channels.html.jinja' %} + {%include '_filters.html.jinja' %} +
\ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/evoked.html.jinja b/mne-python/source/mne/html_templates/repr/evoked.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..6b33c177e87e17d592d7f1cf511854c4a5122b28 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/evoked.html.jinja @@ -0,0 +1,10 @@ +{%include '_js_and_css.html.jinja' %} + +{% set info = inst.info %} + + + {%include '_general.html.jinja' %} + {%include '_acquisition.html.jinja' %} + {%include '_channels.html.jinja' %} + {%include '_filters.html.jinja' %} +
\ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/forward.html.jinja b/mne-python/source/mne/html_templates/repr/forward.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..e8bce9649b131204f0e3c586293db62f363442ad --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/forward.html.jinja @@ -0,0 +1,29 @@ +{%include '_js_and_css.html.jinja' %} + +{% set section = "Forward" %} +{% set section_class_name = section | lower | append_uuid %} + +{# Collapse content during documentation build. #} +{% if collapsed %} +{% set collapsed_row_class = "mne-repr-collapsed" %} +{% else %} +{% set collapsed_row_class = "" %} +{% endif %} + + + {%include 'static/_section_header_row.html.jinja' %} + {% for channel_type, channels in (info | format_channels).items() %} + {% include 'static/_channels.html.jinja' %} + {% endfor %} + + + + + + + + + + + +
Source space{{ source_space_descr }}
Source orientation{{ source_orientation }}
\ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/ica.html.jinja b/mne-python/source/mne/html_templates/repr/ica.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..627620983654248fd08ea69cba8b06b4d0c487b0 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/ica.html.jinja @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + {% if fit_on %} + + + + + + + + + + + + + + + + + {% endif %} +
Method{{ method }}
Fit parameters{% if fit_params %}{% for key, value in fit_params.items() %}{{ key }}={{ value }}
{% endfor %}{% else %}—{% endif %}
Fit{% if fit_on %}{{ n_iter }} iterations on {{ fit_on }} ({{ n_samples }} samples){% else %}no{% endif %}
ICA components{{ n_components }}
Available PCA components{{ n_pca_components }}
Channel types{{ ch_types|join(', ') }}
ICA components marked for exclusion{% if excludes %}{{ excludes|join('
' | safe) }}{% else %}—{% endif %}
diff --git a/mne-python/source/mne/html_templates/repr/info.html.jinja b/mne-python/source/mne/html_templates/repr/info.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..644637289796dc959e0dc088e334f421348275ac --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/info.html.jinja @@ -0,0 +1,10 @@ +{%include '_js_and_css.html.jinja' %} + +{%set inst = info %} + + + {%include '_general.html.jinja' %} + {%include '_acquisition.html.jinja' %} + {%include '_channels.html.jinja' %} + {%include '_filters.html.jinja' %} +
\ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/inverse_operator.html.jinja b/mne-python/source/mne/html_templates/repr/inverse_operator.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..63d1ee8cf3b67c597398cc51315396b7164f8098 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/inverse_operator.html.jinja @@ -0,0 +1,14 @@ + + + + + + + + + + + + + +
Channels{{ channels }}
Source space{{ source_space_descr }}
Source orientation{{ source_orientation }}
diff --git a/mne-python/source/mne/html_templates/repr/raw.html.jinja b/mne-python/source/mne/html_templates/repr/raw.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..6b33c177e87e17d592d7f1cf511854c4a5122b28 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/raw.html.jinja @@ -0,0 +1,10 @@ +{%include '_js_and_css.html.jinja' %} + +{% set info = inst.info %} + + + {%include '_general.html.jinja' %} + {%include '_acquisition.html.jinja' %} + {%include '_channels.html.jinja' %} + {%include '_filters.html.jinja' %} +
\ No newline at end of file diff --git a/mne-python/source/mne/html_templates/repr/spectrum.html.jinja b/mne-python/source/mne/html_templates/repr/spectrum.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..40cc2222005fb7fc34f703f33171e3a4c3a522c4 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/spectrum.html.jinja @@ -0,0 +1,11 @@ +{%include '_js_and_css.html.jinja' %} + +{% set info = inst.info %} + + + {%include '_general.html.jinja' %} + {%include '_acquisition.html.jinja' %} + {%include '_channels.html.jinja' %} + {%include '_frequencies.html.jinja' %} + {%include '_filters.html.jinja' %} +
diff --git a/mne-python/source/mne/html_templates/repr/static/_channels.html.jinja b/mne-python/source/mne/html_templates/repr/static/_channels.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..d40f62f5d6b9100ef6864d79ccaf7358a2f175d1 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/static/_channels.html.jinja @@ -0,0 +1,17 @@ +{% set channel_names_good = channels["good"] | map(attribute='name_html') | join(', ') %} + + + {{ channel_type }} + + + + {% if channels["bad"] %} + {% set channel_names_bad = channels["bad"] | map(attribute='name_html') | join(', ') %} + and + {% endif %} + + diff --git a/mne-python/source/mne/html_templates/repr/static/_section_header_row.html.jinja b/mne-python/source/mne/html_templates/repr/static/_section_header_row.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..d8d3da21d3ff37d228c4047c55a614c412f5d904 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/static/_section_header_row.html.jinja @@ -0,0 +1,12 @@ + + + + + + {{ section }} + + diff --git a/mne-python/source/mne/html_templates/repr/static/repr.css b/mne-python/source/mne/html_templates/repr/static/repr.css new file mode 100644 index 0000000000000000000000000000000000000000..589318784307a4076b3574bc5fb8e43b5a2e2db8 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/static/repr.css @@ -0,0 +1,107 @@ +/* +Styles in this section apply both to the sphinx-built website docs and to notebooks +rendered in an IDE or in Jupyter. In our web docs, styles here are complemented by +doc/_static/styles.css and other CSS files (e.g. from the sphinx theme, sphinx-gallery, +or bootstrap). In IDEs/Jupyter, those style files are unavailable, so only the rules in +this file apply (plus whatever default styling the IDE applies). +*/ +.mne-repr-table { + display: inline; /* prevent using full container width */ +} +.mne-repr-table tr.mne-repr-section-header > th { + padding-top: 1rem; + text-align: left; + vertical-align: middle; +} +.mne-repr-section-toggle > button { + all: unset; + display: block; + height: 1rem; + width: 1rem; +} +.mne-repr-section-toggle > button > svg { + height: 60%; +} + +/* transition (rotation) effects on the collapser button */ +.mne-repr-section-toggle > button.collapsed > svg { + transition: 0.1s ease-out; + transform: rotate(-90deg); +} +.mne-repr-section-toggle > button:not(.collapsed) > svg { + transition: 0.1s ease-out; + transform: rotate(0deg); +} + +/* hide collapsed table rows */ +.mne-repr-collapsed { + display: none; +} + + +@layer { + /* + Selectors in a `@layer` will always be lower-precedence than selectors outside the + layer. So even though e.g. `div.output_html` is present in the sphinx-rendered + website docs, the styles here won't take effect there as long as some other rule + somewhere in the page's CSS targets the same element. + + In IDEs or Jupyter notebooks, though, the CSS files from the sphinx theme, + sphinx-gallery, and bootstrap are unavailable, so these styles will apply. + + Notes: + + - the selector `.accordion-body` is for MNE Reports + - the selector `.output_html` is for VSCode's notebook interface + - the selector `.jp-RenderedHTML` is for Jupyter notebook + - variables starting with `--theme-` are VSCode-specific. + - variables starting with `--jp-` are Jupyter styles, *some of which* are also + available in VSCode. Here we try the `--theme-` variable first, then fall back to + the `--jp-` ones. + */ + .mne-repr-table { + --mne-toggle-color: var(--theme-foreground, var(--jp-ui-font-color1)); + --mne-button-bg-color: var(--theme-button-background, var(--jp-info-color0, var(--jp-content-link-color))); + --mne-button-fg-color: var(--theme-button-foreground, var(--jp-ui-inverse-font-color0, var(--jp-editor-background))); + --mne-button-hover-bg-color: var(--theme-button-hover-background, var(--jp-info-color1)); + --mne-button-radius: var(--jp-border-radius, 0.25rem); + } + /* chevron position/alignment; in VSCode it looks ok without adjusting */ + .accordion-body .mne-repr-section-toggle > button, + .jp-RenderedHTML .mne-repr-section-toggle > button { + padding: 0 0 45% 25% !important; + } + /* chevron color; MNE Report doesn't have light/dark mode */ + div.output_html .mne-repr-section-toggle > button > svg > path, + .jp-RenderedHTML .mne-repr-section-toggle > button > svg > path { + fill: var(--mne-toggle-color); + } + .accordion-body .mne-ch-names-btn, + div.output_html .mne-ch-names-btn, + .jp-RenderedHTML .mne-ch-names-btn { + -webkit-border-radius: var(--mne-button-radius); + -moz-border-radius: var(--mne-button-radius); + border-radius: var(--mne-button-radius); + border: none; + background-image: none; + background-color: var(--mne-button-bg-color); + color: var(--mne-button-fg-color); + font-size: inherit; + min-width: 1.5rem; + padding: 0.25rem; + text-align: center; + text-decoration: none; + } + .accordion-body .mne-ch-names-btn:hover, + div.output_html .mne.ch-names-btn:hover, + .jp-RenderedHTML .mne-ch-names-btn:hover { + background-color: var(--mne-button-hover-bg-color); + text-decoration: underline; + } + .accordion-body .mne-ch-names-btn:focus-visible, + div.output_html .mne-ch-names-btn:focus-visible, + .jp-RenderedHTML .mne-ch-names-btn:focus-visible { + outline: 0.1875rem solid var(--mne-button-bg-color) !important; + outline-offset: 0.1875rem !important; + } +} diff --git a/mne-python/source/mne/html_templates/repr/static/repr.js b/mne-python/source/mne/html_templates/repr/static/repr.js new file mode 100644 index 0000000000000000000000000000000000000000..00c9d327d97a1058386b846b62c9c3fa26261c5c --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/static/repr.js @@ -0,0 +1,23 @@ +// must be `var` (not `const`) because this can get embedded multiple times on a page +var toggleVisibility = (className) => { + + const elements = document.querySelectorAll(`.${className}`); + + elements.forEach(element => { + if (element.classList.contains("mne-repr-section-header")) { + return // Don't collapse the section header row + } + element.classList.toggle("mne-repr-collapsed"); + }); + + // trigger caret to rotate + var sel = `.mne-repr-section-header.${className} > th.mne-repr-section-toggle > button`; + const button = document.querySelector(sel); + button.classList.toggle("collapsed"); + + // adjust tooltip + sel = `tr.mne-repr-section-header.${className}`; + const secHeadRow = document.querySelector(sel); + secHeadRow.classList.toggle("collapsed"); + secHeadRow.title = secHeadRow.title === "Hide section" ? "Show section" : "Hide section"; +} diff --git a/mne-python/source/mne/html_templates/repr/tfr.html.jinja b/mne-python/source/mne/html_templates/repr/tfr.html.jinja new file mode 100644 index 0000000000000000000000000000000000000000..d2881a0db5810fab0eddca2a922a5a5c8b098731 --- /dev/null +++ b/mne-python/source/mne/html_templates/repr/tfr.html.jinja @@ -0,0 +1,60 @@ + + + + + + {%- for unit in units %} + + {%- if loop.index == 1 %} + + {%- endif %} + + + {%- endfor %} + + + + + {%- if inst_type == "Epochs" %} + + + + + {% endif -%} + {%- if inst_type == "Evoked" %} + + + + + {% endif -%} + + + + + + + + + {% if "taper" in tfr._dims %} + + + + + {% endif %} + + + + + + + + + + + + + + + + +
Data type{{ tfr._data_type }}
Units{{ unit }}
Data source{{ inst_type }}
Number of epochs{{ tfr.shape[0] }}
Number of averaged trials{{ nave }}
Dims{{ tfr._dims | join(", ") }}
Estimation method{{ tfr.method }}
Number of tapers{{ tfr._mt_weights.size }}
Number of channels{{ tfr.ch_names|length }}
Number of timepoints{{ tfr.times|length }}
Number of frequency bins{{ tfr.freqs|length }}
Frequency range{{ '%.2f'|format(tfr.freqs[0]) }} – {{ '%.2f'|format(tfr.freqs[-1]) }} Hz
diff --git a/mne-python/source/mne/icons/README.rst b/mne-python/source/mne/icons/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..a6de772797bfca4d63dcd43b32d6f918d28800dd --- /dev/null +++ b/mne-python/source/mne/icons/README.rst @@ -0,0 +1,11 @@ +.. -*- mode: rst -*- + + +Documentation +============= + +The icons are used in ``mne/viz/_brain/_brain.py`` for the toolbar. +These Material design icons are provided by Google under the `Apache 2.0`_ license. + + +.. _Apache 2.0: https://github.com/google/material-design-icons/blob/master/LICENSE diff --git a/mne-python/source/mne/icons/dark/actions/clear.svg b/mne-python/source/mne/icons/dark/actions/clear.svg new file mode 100644 index 0000000000000000000000000000000000000000..f28cedd0acd4811b9ce7576a20e0bfc2ad3464cd --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/clear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/folder.svg b/mne-python/source/mne/icons/dark/actions/folder.svg new file mode 100644 index 0000000000000000000000000000000000000000..7fa0de9ee2ea90e58faae2467a4737d9df946c0d --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/help.svg b/mne-python/source/mne/icons/dark/actions/help.svg new file mode 100644 index 0000000000000000000000000000000000000000..3631070687745e9b2c779ab0be0d5d755dc2a178 --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/help.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/movie.svg b/mne-python/source/mne/icons/dark/actions/movie.svg new file mode 100644 index 0000000000000000000000000000000000000000..94a5554cec5b41cfae8e8cb03c31cc6064461c73 --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/movie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/pause.svg b/mne-python/source/mne/icons/dark/actions/pause.svg new file mode 100644 index 0000000000000000000000000000000000000000..af1364ea630d234f60f6c84f1d7ea91e9c46e018 --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/play.svg b/mne-python/source/mne/icons/dark/actions/play.svg new file mode 100644 index 0000000000000000000000000000000000000000..eea3600f94b16718d7bfaebe2e7e454b83473e84 --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/reset.svg b/mne-python/source/mne/icons/dark/actions/reset.svg new file mode 100644 index 0000000000000000000000000000000000000000..43e59a34a3cd72aad4f8956a85efa59e27243b8d --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/reset.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/restore.svg b/mne-python/source/mne/icons/dark/actions/restore.svg new file mode 100644 index 0000000000000000000000000000000000000000..14711217359791d801ed65e36b37ca317aa52f55 --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/restore.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/scale.svg b/mne-python/source/mne/icons/dark/actions/scale.svg new file mode 100644 index 0000000000000000000000000000000000000000..be0df0387ad615e1c047110ec9b725f701fecaa1 --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/scale.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/screenshot.svg b/mne-python/source/mne/icons/dark/actions/screenshot.svg new file mode 100644 index 0000000000000000000000000000000000000000..ad9719d19d4b1c9cba73dc8b3aa1366d794b617b --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/screenshot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/visibility_off.svg b/mne-python/source/mne/icons/dark/actions/visibility_off.svg new file mode 100644 index 0000000000000000000000000000000000000000..9e10c3a44ffe6696fccbbfedcb8f2c561be8b11c --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/visibility_off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/actions/visibility_on.svg b/mne-python/source/mne/icons/dark/actions/visibility_on.svg new file mode 100644 index 0000000000000000000000000000000000000000..9d4b89e1f2c2669277a6e48b74086d90f92e08d6 --- /dev/null +++ b/mne-python/source/mne/icons/dark/actions/visibility_on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/dark/index.theme b/mne-python/source/mne/icons/dark/index.theme new file mode 100644 index 0000000000000000000000000000000000000000..d3e887c33bd275a3255feea7f255a47febcecee1 --- /dev/null +++ b/mne-python/source/mne/icons/dark/index.theme @@ -0,0 +1,11 @@ +[Icon Theme] +Name=dark + +Directories=actions + +[actions] +Size=32 +Context=Actions +MinSize=16 +MaxSize=128 +Type=Scalable diff --git a/mne-python/source/mne/icons/light/actions/clear.svg b/mne-python/source/mne/icons/light/actions/clear.svg new file mode 100644 index 0000000000000000000000000000000000000000..f5193165b5f4cb4cf07ade0b1873b4067111b0fa --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/clear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/folder.svg b/mne-python/source/mne/icons/light/actions/folder.svg new file mode 100644 index 0000000000000000000000000000000000000000..6b444381f6adcc46e550daaac86e76b8cc248ede --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/folder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/help.svg b/mne-python/source/mne/icons/light/actions/help.svg new file mode 100644 index 0000000000000000000000000000000000000000..afa939840cd5ba2ce3510c44afa04ef10c69be0b --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/help.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/movie.svg b/mne-python/source/mne/icons/light/actions/movie.svg new file mode 100644 index 0000000000000000000000000000000000000000..6bb41a1fe8b1263440f207c42a6ea7b28152dc0f --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/movie.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/pause.svg b/mne-python/source/mne/icons/light/actions/pause.svg new file mode 100644 index 0000000000000000000000000000000000000000..05bcc5c79b4f601390bbe4f0b377ef025a1310d3 --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/pause.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/play.svg b/mne-python/source/mne/icons/light/actions/play.svg new file mode 100644 index 0000000000000000000000000000000000000000..23abb1adf3b6173ae7f5ee7aa69b94545944167c --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/play.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/reset.svg b/mne-python/source/mne/icons/light/actions/reset.svg new file mode 100644 index 0000000000000000000000000000000000000000..1aea2e04cb5263135e116fda4a1237f6809fc00f --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/reset.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/restore.svg b/mne-python/source/mne/icons/light/actions/restore.svg new file mode 100644 index 0000000000000000000000000000000000000000..8a4b066f3401d29fa3663a5f8325bbab1aaa3161 --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/restore.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/scale.svg b/mne-python/source/mne/icons/light/actions/scale.svg new file mode 100644 index 0000000000000000000000000000000000000000..85af4802fc76914b1c0a4805c30a89b02ab0cad3 --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/scale.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/screenshot.svg b/mne-python/source/mne/icons/light/actions/screenshot.svg new file mode 100644 index 0000000000000000000000000000000000000000..53d8fe31d4ea616cf47204db6eea1b0e01d8c0f8 --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/screenshot.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/visibility_off.svg b/mne-python/source/mne/icons/light/actions/visibility_off.svg new file mode 100644 index 0000000000000000000000000000000000000000..00e606705dc18bd25a90fe5aac4b7353bf46eee0 --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/visibility_off.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/actions/visibility_on.svg b/mne-python/source/mne/icons/light/actions/visibility_on.svg new file mode 100644 index 0000000000000000000000000000000000000000..617b9a0c8299c086dbbaa30c7a6cf57e0590a4c9 --- /dev/null +++ b/mne-python/source/mne/icons/light/actions/visibility_on.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/mne-python/source/mne/icons/light/index.theme b/mne-python/source/mne/icons/light/index.theme new file mode 100644 index 0000000000000000000000000000000000000000..21766828b2fd260897db748d64e6651eef597d5f --- /dev/null +++ b/mne-python/source/mne/icons/light/index.theme @@ -0,0 +1,11 @@ +[Icon Theme] +Name=light + +Directories=actions + +[actions] +Size=32 +Context=Actions +MinSize=16 +MaxSize=128 +Type=Scalable diff --git a/mne-python/source/mne/icons/mne_bigsur_icon.png b/mne-python/source/mne/icons/mne_bigsur_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9661d779f816ec9199d448516451f11884cf1ac3 Binary files /dev/null and b/mne-python/source/mne/icons/mne_bigsur_icon.png differ diff --git a/mne-python/source/mne/icons/mne_default_icon.png b/mne-python/source/mne/icons/mne_default_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..22a90e2275c0874c5adaf295b9b75754c273a75d Binary files /dev/null and b/mne-python/source/mne/icons/mne_default_icon.png differ diff --git a/mne-python/source/mne/icons/mne_icon-cropped.png b/mne-python/source/mne/icons/mne_icon-cropped.png new file mode 100644 index 0000000000000000000000000000000000000000..9cc2c336d201d349dec14ca6f1f7cd511bd89082 Binary files /dev/null and b/mne-python/source/mne/icons/mne_icon-cropped.png differ diff --git a/mne-python/source/mne/icons/mne_icon.png b/mne-python/source/mne/icons/mne_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c197b62915615acb84f57ea978cc7bb365e27814 Binary files /dev/null and b/mne-python/source/mne/icons/mne_icon.png differ diff --git a/mne-python/source/mne/icons/mne_splash.png b/mne-python/source/mne/icons/mne_splash.png new file mode 100644 index 0000000000000000000000000000000000000000..76aa18ea574d1746138fe83430dc81889e7f2451 Binary files /dev/null and b/mne-python/source/mne/icons/mne_splash.png differ diff --git a/mne-python/source/mne/icons/toolbar_move_horizontal@2x.png b/mne-python/source/mne/icons/toolbar_move_horizontal@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..143b62ec558059e11306c29ed23f2152062492c0 Binary files /dev/null and b/mne-python/source/mne/icons/toolbar_move_horizontal@2x.png differ diff --git a/mne-python/source/mne/icons/toolbar_move_vertical@2x.png b/mne-python/source/mne/icons/toolbar_move_vertical@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..453d7b71f96c0c92de92c13b189e391157495a2d Binary files /dev/null and b/mne-python/source/mne/icons/toolbar_move_vertical@2x.png differ diff --git a/mne-python/source/mne/icons/toolbar_separator_horizontal.png b/mne-python/source/mne/icons/toolbar_separator_horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..ecf2ab7d0cf13b74e90e4f9f263db0f0553c7da3 Binary files /dev/null and b/mne-python/source/mne/icons/toolbar_separator_horizontal.png differ diff --git a/mne-python/source/mne/icons/toolbar_separator_horizontal@2x.png b/mne-python/source/mne/icons/toolbar_separator_horizontal@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ac2b343264624c5a6ce5842ea5c87a4f45abfb7b Binary files /dev/null and b/mne-python/source/mne/icons/toolbar_separator_horizontal@2x.png differ diff --git a/mne-python/source/mne/icons/toolbar_separator_vertical@2x.png b/mne-python/source/mne/icons/toolbar_separator_vertical@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2f66e93d34699edb9b049006704fdfa01db79707 Binary files /dev/null and b/mne-python/source/mne/icons/toolbar_separator_vertical@2x.png differ diff --git a/mne-python/source/mne/inverse_sparse/__init__.py b/mne-python/source/mne/inverse_sparse/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..615c3062bdb798283891d73349718a44cb639eb9 --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/__init__.py @@ -0,0 +1,9 @@ +"""Non-Linear sparse inverse solvers.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/inverse_sparse/__init__.pyi b/mne-python/source/mne/inverse_sparse/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..557921114caf25b2fd2c820dcdb8dca6c791f157 --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/__init__.pyi @@ -0,0 +1,3 @@ +__all__ = ["gamma_map", "make_stc_from_dipoles", "mixed_norm", "tf_mixed_norm"] +from ._gamma_map import gamma_map +from .mxne_inverse import make_stc_from_dipoles, mixed_norm, tf_mixed_norm diff --git a/mne-python/source/mne/inverse_sparse/_gamma_map.py b/mne-python/source/mne/inverse_sparse/_gamma_map.py new file mode 100644 index 0000000000000000000000000000000000000000..e3d077b77e6a90b3ddf679e1f75c53210a1ef21d --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/_gamma_map.py @@ -0,0 +1,341 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ..fixes import _reshape_view, _safe_svd +from ..forward import is_fixed_orient +from ..minimum_norm.inverse import _check_reference, _log_exp_var +from ..utils import logger, verbose, warn +from .mxne_inverse import ( + _check_ori, + _compute_residual, + _make_dipoles_sparse, + _make_sparse_stc, + _prepare_gain, + _reapply_source_weighting, +) + + +@verbose +def _gamma_map_opt( + M, + G, + alpha, + maxit=10000, + tol=1e-6, + update_mode=1, + group_size=1, + gammas=None, + verbose=None, +): + """Hierarchical Bayes (Gamma-MAP). + + Parameters + ---------- + M : array, shape=(n_sensors, n_times) + Observation. + G : array, shape=(n_sensors, n_sources) + Forward operator. + alpha : float + Regularization parameter (noise variance). + maxit : int + Maximum number of iterations. + tol : float + Tolerance parameter for convergence. + group_size : int + Number of consecutive sources which use the same gamma. + update_mode : int + Update mode, 1: MacKay update (default), 3: Modified MacKay update. + gammas : array, shape=(n_sources,) + Initial values for posterior variances (gammas). If None, a + variance of 1.0 is used. + %(verbose)s + + Returns + ------- + X : array, shape=(n_active, n_times) + Estimated source time courses. + active_set : array, shape=(n_active,) + Indices of active sources. + """ + G = G.copy() + M = M.copy() + + if gammas is None: + gammas = np.ones(G.shape[1], dtype=np.float64) + + eps = np.finfo(float).eps + + n_sources = G.shape[1] + n_sensors, n_times = M.shape + + # apply normalization so the numerical values are sane + M_normalize_constant = np.linalg.norm(np.dot(M, M.T), ord="fro") + M /= np.sqrt(M_normalize_constant) + alpha /= M_normalize_constant + G_normalize_constant = np.linalg.norm(G, ord=np.inf) + G /= G_normalize_constant + + if n_sources % group_size != 0: + raise ValueError( + "Number of sources has to be evenly dividable by the group size" + ) + + n_active = n_sources + active_set = np.arange(n_sources) + + gammas_full_old = gammas.copy() + + if update_mode == 2: + denom_fun = np.sqrt + else: + # do nothing + def denom_fun(x): + return x + + last_size = -1 + for itno in range(maxit): + gammas[np.isnan(gammas)] = 0.0 + + gidx = np.abs(gammas) > eps + active_set = active_set[gidx] + gammas = gammas[gidx] + + # update only active gammas (once set to zero it stays at zero) + if n_active > len(active_set): + n_active = active_set.size + G = G[:, gidx] + + CM = np.dot(G * gammas[np.newaxis, :], G.T) + CM.flat[:: n_sensors + 1] += alpha + # Invert CM keeping symmetry + U, S, _ = _safe_svd(CM, full_matrices=False) + S = S[np.newaxis, :] + del CM + CMinv = np.dot(U / (S + eps), U.T) + CMinvG = np.dot(CMinv, G) + A = np.dot(CMinvG.T, M) # mult. w. Diag(gamma) in gamma update + + if update_mode == 1: + # MacKay fixed point update (10) in [1] + numer = gammas**2 * np.mean((A * A.conj()).real, axis=1) + denom = gammas * np.sum(G * CMinvG, axis=0) + elif update_mode == 2: + # modified MacKay fixed point update (11) in [1] + numer = gammas * np.sqrt(np.mean((A * A.conj()).real, axis=1)) + denom = np.sum(G * CMinvG, axis=0) # sqrt is applied below + else: + raise ValueError("Invalid value for update_mode") + + if group_size == 1: + if denom is None: + gammas = numer + else: + gammas = numer / np.maximum(denom_fun(denom), np.finfo("float").eps) + else: + numer_comb = np.sum(numer.reshape(-1, group_size), axis=1) + if denom is None: + gammas_comb = numer_comb + else: + denom_comb = np.sum(denom.reshape(-1, group_size), axis=1) + gammas_comb = numer_comb / denom_fun(denom_comb) + + gammas = np.repeat(gammas_comb / group_size, group_size) + + # compute convergence criterion + gammas_full = np.zeros(n_sources, dtype=np.float64) + gammas_full[active_set] = gammas + + err = np.sum(np.abs(gammas_full - gammas_full_old)) / np.sum( + np.abs(gammas_full_old) + ) + + gammas_full_old = gammas_full + + breaking = err < tol or n_active == 0 + if len(gammas) != last_size or breaking: + logger.info( + f"Iteration: {itno}\t active set size: {len(gammas)}\t convergence: " + f"{err:.3e}" + ) + last_size = len(gammas) + + if breaking: + break + + if itno < maxit - 1: + logger.info("\nConvergence reached !\n") + else: + warn("\nConvergence NOT reached !\n") + + # undo normalization and compute final posterior mean + n_const = np.sqrt(M_normalize_constant) / G_normalize_constant + x_active = n_const * gammas[:, None] * A + + return x_active, active_set + + +@verbose +def gamma_map( + evoked, + forward, + noise_cov, + alpha, + loose="auto", + depth=0.8, + xyz_same_gamma=True, + maxit=10000, + tol=1e-6, + update_mode=1, + gammas=None, + pca=True, + return_residual=False, + return_as_dipoles=False, + rank=None, + pick_ori=None, + verbose=None, +): + """Hierarchical Bayes (Gamma-MAP) sparse source localization method. + + Models each source time course using a zero-mean Gaussian prior with an + unknown variance (gamma) parameter. During estimation, most gammas are + driven to zero, resulting in a sparse source estimate, as in + :footcite:`WipfEtAl2007` and :footcite:`WipfNagarajan2009`. + + For fixed-orientation forward operators, a separate gamma is used for each + source time course, while for free-orientation forward operators, the same + gamma is used for the three source time courses at each source space point + (separate gammas can be used in this case by using xyz_same_gamma=False). + + Parameters + ---------- + evoked : instance of Evoked + Evoked data to invert. + forward : dict + Forward operator. + noise_cov : instance of Covariance + Noise covariance to compute whitener. + alpha : float + Regularization parameter (noise variance). + %(loose)s + %(depth)s + xyz_same_gamma : bool + Use same gamma for xyz current components at each source space point. + Recommended for free-orientation forward solutions. + maxit : int + Maximum number of iterations. + tol : float + Tolerance parameter for convergence. + update_mode : int + Update mode, 1: MacKay update (default), 2: Modified MacKay update. + gammas : array, shape=(n_sources,) + Initial values for posterior variances (gammas). If None, a + variance of 1.0 is used. + pca : bool + If True the rank of the data is reduced to the true dimension. + return_residual : bool + If True, the residual is returned as an Evoked instance. + return_as_dipoles : bool + If True, the sources are returned as a list of Dipole instances. + %(rank_none)s + + .. versionadded:: 0.18 + %(pick_ori)s + %(verbose)s + + Returns + ------- + stc : instance of SourceEstimate + Source time courses. + residual : instance of Evoked + The residual a.k.a. data not explained by the sources. + Only returned if return_residual is True. + + References + ---------- + .. footbibliography:: + """ + _check_reference(evoked) + + forward, gain, gain_info, whitener, source_weighting, mask = _prepare_gain( + forward, evoked.info, noise_cov, pca, depth, loose, rank + ) + _check_ori(pick_ori, forward) + + group_size = 1 if (is_fixed_orient(forward) or not xyz_same_gamma) else 3 + + # get the data + sel = [evoked.ch_names.index(name) for name in gain_info["ch_names"]] + M = evoked.data[sel] + + # whiten the data + logger.info("Whitening data matrix.") + M = np.dot(whitener, M) + + # run the optimization + X, active_set = _gamma_map_opt( + M, + gain, + alpha, + maxit=maxit, + tol=tol, + update_mode=update_mode, + gammas=gammas, + group_size=group_size, + verbose=verbose, + ) + + if len(active_set) == 0: + raise Exception("No active dipoles found. alpha is too big.") + + M_estimate = gain[:, active_set] @ X + + # Reapply weights to have correct unit + X = _reapply_source_weighting(X, source_weighting, active_set) + + if return_residual: + residual = _compute_residual(forward, evoked, X, active_set, gain_info) + + if group_size == 1 and not is_fixed_orient(forward): + # make sure each source has 3 components + idx, offset = divmod(active_set, 3) + active_src = np.unique(idx) + if len(X) < 3 * len(active_src): + X_xyz = np.zeros((len(active_src), 3, X.shape[1]), dtype=X.dtype) + idx = np.searchsorted(active_src, idx) + X_xyz[idx, offset, :] = X + X_xyz = _reshape_view(X_xyz, (len(active_src) * 3, X.shape[1])) + X = X_xyz + active_set = (active_src[:, np.newaxis] * 3 + np.arange(3)).ravel() + source_weighting[source_weighting == 0] = 1 # zeros + gain_active = gain[:, active_set] / source_weighting[active_set] + del source_weighting + + tmin = evoked.times[0] + tstep = 1.0 / evoked.info["sfreq"] + + if return_as_dipoles: + out = _make_dipoles_sparse( + X, active_set, forward, tmin, tstep, M, gain_active, active_is_idx=True + ) + else: + out = _make_sparse_stc( + X, + active_set, + forward, + tmin, + tstep, + active_is_idx=True, + pick_ori=pick_ori, + verbose=verbose, + ) + + _log_exp_var(M, M_estimate, prefix="") + logger.info("[done]") + + if return_residual: + out = out, residual + + return out diff --git a/mne-python/source/mne/inverse_sparse/mxne_debiasing.py b/mne-python/source/mne/inverse_sparse/mxne_debiasing.py new file mode 100644 index 0000000000000000000000000000000000000000..860c67c5f6c5163f80fb895a257d6a439c0abe48 --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/mxne_debiasing.py @@ -0,0 +1,137 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from math import sqrt + +import numpy as np + +from ..utils import check_random_state, fill_doc, logger, verbose + + +@fill_doc +def power_iteration_kron(A, C, max_iter=1000, tol=1e-3, random_state=0): + """Find the largest singular value for the matrix kron(C.T, A). + + It uses power iterations. + + Parameters + ---------- + A : array + An array + C : array + An array + max_iter : int + Maximum number of iterations + %(random_state)s + + Returns + ------- + L : float + largest singular value + + Notes + ----- + http://en.wikipedia.org/wiki/Power_iteration + """ + AS_size = C.shape[0] + rng = check_random_state(random_state) + B = rng.randn(AS_size, AS_size) + B /= np.linalg.norm(B, "fro") + ATA = np.dot(A.T, A) + CCT = np.dot(C, C.T) + L0 = np.inf + for _ in range(max_iter): + Y = np.dot(np.dot(ATA, B), CCT) + L = np.linalg.norm(Y, "fro") + + if abs(L - L0) < tol: + break + + B = Y / L + L0 = L + return L + + +@verbose +def compute_bias(M, G, X, max_iter=1000, tol=1e-6, n_orient=1, verbose=None): + """Compute scaling to correct amplitude bias. + + It solves the following optimization problem using FISTA: + + min 1/2 * (|| M - GDX ||fro)^2 + s.t. D >= 1 and D is a diagonal matrix + + Reference for the FISTA algorithm: + Amir Beck and Marc Teboulle + A Fast Iterative Shrinkage-Thresholding Algorithm for Linear Inverse + Problems, SIAM J. Imaging Sci., 2(1), 183-202. (20 pages) + http://epubs.siam.org/doi/abs/10.1137/080716542 + + Parameters + ---------- + M : array + measurement data. + G : array + leadfield matrix. + X : array + reconstructed time courses with amplitude bias. + max_iter : int + Maximum number of iterations. + tol : float + The tolerance on convergence. + n_orient : int + The number of orientations (1 for fixed and 3 otherwise). + %(verbose)s + + Returns + ------- + D : array + Debiasing weights. + """ + n_sources = X.shape[0] + + lipschitz_constant = 1.1 * power_iteration_kron(G, X) + + # initializations + D = np.ones(n_sources) + Y = np.ones(n_sources) + t = 1.0 + + for i in range(max_iter): + D0 = D + + # gradient step + R = M - np.dot(G * Y, X) + D = Y + np.sum(np.dot(G.T, R) * X, axis=1) / lipschitz_constant + # Equivalent but faster than: + # D = Y + np.diag(np.dot(np.dot(G.T, R), X.T)) / lipschitz_constant + + # prox ie projection on constraint + if n_orient != 1: # take care of orientations + # The scaling has to be the same for all orientations + D = np.mean(D.reshape(-1, n_orient), axis=1) + D = np.tile(D, [n_orient, 1]).T.ravel() + D = np.maximum(D, 1.0) + + t0 = t + t = 0.5 * (1.0 + sqrt(1.0 + 4.0 * t**2)) + Y.fill(0.0) + dt = (t0 - 1.0) / t + Y = D + dt * (D - D0) + + Ddiff = np.linalg.norm(D - D0, np.inf) + + if Ddiff < tol: + logger.info( + f"Debiasing converged after {i} iterations " + f"max(|D - D0| = {Ddiff:e} < {tol:e})" + ) + break + else: + Ddiff = np.linalg.norm(D - D0, np.inf) + logger.info( + f"Debiasing did not converge after {max_iter} iterations! " + f"max(|D - D0| = {Ddiff:e} >= {tol:e})" + ) + return D diff --git a/mne-python/source/mne/inverse_sparse/mxne_inverse.py b/mne-python/source/mne/inverse_sparse/mxne_inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..295f72c49ce98451b83dd9a73f6f3a4b08e25341 --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/mxne_inverse.py @@ -0,0 +1,1094 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from .._fiff.proj import deactivate_proj +from ..dipole import Dipole +from ..fixes import _reshape_view, _safe_svd +from ..forward import is_fixed_orient +from ..minimum_norm.inverse import ( + _check_reference, + _log_exp_var, + _prepare_forward, + combine_xyz, +) +from ..source_estimate import SourceEstimate, _BaseSourceEstimate, _make_stc +from ..utils import ( + _check_depth, + _check_option, + _validate_type, + check_random_state, + logger, + sum_squared, + verbose, + warn, +) +from .mxne_optim import ( + _Phi, + groups_norm2, + iterative_mixed_norm_solver, + iterative_tf_mixed_norm_solver, + mixed_norm_solver, + norm_epsilon_inf, + norm_l2inf, + tf_mixed_norm_solver, +) + + +def _check_ori(pick_ori, forward): + """Check pick_ori.""" + _check_option("pick_ori", pick_ori, [None, "vector"]) + if pick_ori == "vector" and is_fixed_orient(forward): + raise ValueError( + 'pick_ori="vector" cannot be combined with a fixed ' + "orientation forward solution." + ) + + +def _prepare_weights(forward, gain, source_weighting, weights, weights_min): + mask = None + if isinstance(weights, _BaseSourceEstimate): + weights = np.max(np.abs(weights.data), axis=1) + weights_max = np.max(weights) + if weights_min > weights_max: + raise ValueError(f"weights_min > weights_max ({weights_min} > {weights_max})") + weights_min = weights_min / weights_max + weights = weights / weights_max + n_dip_per_pos = 1 if is_fixed_orient(forward) else 3 + weights = np.ravel(np.tile(weights, [n_dip_per_pos, 1]).T) + if len(weights) != gain.shape[1]: + raise ValueError( + "weights do not have the correct dimension " + f" ({len(weights)} != {gain.shape[1]})" + ) + if len(source_weighting.shape) == 1: + source_weighting *= weights + else: + source_weighting *= weights[:, None] + gain *= weights[None, :] + + if weights_min is not None: + mask = weights > weights_min + gain = gain[:, mask] + n_sources = np.sum(mask) // n_dip_per_pos + logger.info(f"Reducing source space to {n_sources} sources") + + return gain, source_weighting, mask + + +def _prepare_gain( + forward, info, noise_cov, pca, depth, loose, rank, weights=None, weights_min=None +): + depth = _check_depth(depth, "depth_sparse") + forward, gain_info, gain, _, _, source_weighting, _, _, whitener = _prepare_forward( + forward, info, noise_cov, "auto", loose, rank, pca, use_cps=True, **depth + ) + + if weights is None: + mask = None + else: + gain, source_weighting, mask = _prepare_weights( + forward, gain, source_weighting, weights, weights_min + ) + + return forward, gain, gain_info, whitener, source_weighting, mask + + +def _reapply_source_weighting(X, source_weighting, active_set): + X *= source_weighting[active_set][:, None] + return X + + +def _compute_residual(forward, evoked, X, active_set, info): + # OK, picking based on row_names is safe + sel = [forward["sol"]["row_names"].index(c) for c in info["ch_names"]] + residual = evoked.copy().pick(info["ch_names"]) + r_tmp = residual.copy() + + r_tmp.data = np.dot(forward["sol"]["data"][sel, :][:, active_set], X) + + # Take care of proj + active_projs = list() + non_active_projs = list() + for p in evoked.info["projs"]: + if p["active"]: + active_projs.append(p) + else: + non_active_projs.append(p) + + if len(active_projs) > 0: + with r_tmp.info._unlock(): + r_tmp.info["projs"] = deactivate_proj( + active_projs, copy=True, verbose=False + ) + r_tmp.apply_proj(verbose=False) + r_tmp.add_proj(non_active_projs, remove_existing=False, verbose=False) + + residual.data -= r_tmp.data + + return residual + + +@verbose +def _make_sparse_stc( + X, + active_set, + forward, + tmin, + tstep, + active_is_idx=False, + pick_ori=None, + verbose=None, +): + source_nn = forward["source_nn"] + vector = False + if not is_fixed_orient(forward): + if pick_ori != "vector": + logger.info("combining the current components...") + X = combine_xyz(X) + else: + vector = True + source_nn = np.reshape(source_nn, (-1, 3, 3)) + + if not active_is_idx: + active_idx = np.where(active_set)[0] + else: + active_idx = active_set + + n_dip_per_pos = 1 if is_fixed_orient(forward) else 3 + if n_dip_per_pos > 1: + active_idx = np.unique(active_idx // n_dip_per_pos) + + src = forward["src"] + vertices = [] + n_points_so_far = 0 + for this_src in src: + this_n_points_so_far = n_points_so_far + len(this_src["vertno"]) + this_active_idx = active_idx[ + (n_points_so_far <= active_idx) & (active_idx < this_n_points_so_far) + ] + this_active_idx -= n_points_so_far + this_vertno = this_src["vertno"][this_active_idx] + n_points_so_far = this_n_points_so_far + vertices.append(this_vertno) + source_nn = source_nn[active_idx] + return _make_stc( + X, + vertices, + src.kind, + tmin, + tstep, + src[0]["subject_his_id"], + vector=vector, + source_nn=source_nn, + ) + + +def _split_gof(M, X, gain): + # parse out the variance explained using an orthogonal basis + # assuming x is estimated using elements of gain, with residual res + # along the first axis + assert M.ndim == X.ndim == gain.ndim == 2, (M.ndim, X.ndim, gain.ndim) + assert gain.shape == (M.shape[0], X.shape[0]) + assert M.shape[1] == X.shape[1] + norm = (M * M.conj()).real.sum(0, keepdims=True) + norm[norm == 0] = np.inf + M_est = gain @ X + assert M.shape == M_est.shape + res = M - M_est + assert gain.shape[0] == M.shape[0], (gain.shape, M.shape) + # find an orthonormal basis for our matrices that spans the actual data + U, s, _ = np.linalg.svd(gain, full_matrices=False) + if U.shape[1] > 0: + U = U[:, s >= s[0] * 1e-6] + # the part that gets explained + fit_orth = U.T @ M + # the part that got over-explained (landed in residual) + res_orth = U.T @ res + # determine the weights by projecting each one onto this basis + w = (U.T @ gain)[:, :, np.newaxis] * X + w_norm = np.linalg.norm(w, axis=1, keepdims=True) + w_norm[w_norm == 0] = 1.0 + w /= w_norm + # our weights are now unit-norm positive (will presrve power) + fit_back = np.linalg.norm(fit_orth[:, np.newaxis] * w, axis=0) ** 2 + res_back = np.linalg.norm(res_orth[:, np.newaxis] * w, axis=0) ** 2 + # and the resulting goodness of fits + gof_back = 100 * (fit_back - res_back) / norm + assert gof_back.shape == X.shape, (gof_back.shape, X.shape) + return gof_back + + +@verbose +def _make_dipoles_sparse( + X, + active_set, + forward, + tmin, + tstep, + M, + gain_active, + active_is_idx=False, + verbose=None, +): + times = tmin + tstep * np.arange(X.shape[1]) + + if not active_is_idx: + active_idx = np.where(active_set)[0] + else: + active_idx = active_set + + # Compute the GOF split amongst the dipoles + assert M.shape == (gain_active.shape[0], len(times)) + assert gain_active.shape[1] == len(active_idx) == X.shape[0] + gof_split = _split_gof(M, X, gain_active) + assert gof_split.shape == (len(active_idx), len(times)) + assert X.shape[0] in (len(active_idx), 3 * len(active_idx)) + + n_dip_per_pos = 1 if is_fixed_orient(forward) else 3 + if n_dip_per_pos > 1: + active_idx = active_idx // n_dip_per_pos + _, keep = np.unique(active_idx, return_index=True) + keep.sort() # maintain old order + active_idx = active_idx[keep] + gof_split = _reshape_view( + gof_split, (len(active_idx), n_dip_per_pos, len(times)) + ) + gof_split = gof_split.sum(1) + assert (gof_split < 100).all() + assert gof_split.shape == (len(active_idx), len(times)) + + dipoles = [] + for k, i_dip in enumerate(active_idx): + i_pos = forward["source_rr"][i_dip][np.newaxis, :] + i_pos = i_pos.repeat(len(times), axis=0) + X_ = X[k * n_dip_per_pos : (k + 1) * n_dip_per_pos] + if n_dip_per_pos == 1: + amplitude = X_[0] + i_ori = forward["source_nn"][i_dip][np.newaxis, :] + i_ori = i_ori.repeat(len(times), axis=0) + else: + if forward["surf_ori"]: + X_ = np.dot( + forward["source_nn"][ + i_dip * n_dip_per_pos : (i_dip + 1) * n_dip_per_pos + ].T, + X_, + ) + amplitude = np.linalg.norm(X_, axis=0) + i_ori = np.zeros((len(times), 3)) + i_ori[amplitude > 0.0] = ( + X_[:, amplitude > 0.0] / amplitude[amplitude > 0.0] + ).T + + dipoles.append(Dipole(times, i_pos, amplitude, i_ori, gof_split[k])) + + return dipoles + + +@verbose +def make_stc_from_dipoles(dipoles, src, verbose=None): + """Convert a list of spatio-temporal dipoles into a SourceEstimate. + + Parameters + ---------- + dipoles : Dipole | list of instances of Dipole + The dipoles to convert. + src : instance of SourceSpaces + The source space used to generate the forward operator. + %(verbose)s + + Returns + ------- + stc : SourceEstimate + The source estimate. + """ + logger.info("Converting dipoles into a SourceEstimate.") + if isinstance(dipoles, Dipole): + dipoles = [dipoles] + if not isinstance(dipoles, list): + raise ValueError( + "Dipoles must be an instance of Dipole or " + "a list of instances of Dipole. " + f"Got {type(dipoles)}!" + ) + tmin = dipoles[0].times[0] + tstep = dipoles[0].times[1] - tmin + X = np.zeros((len(dipoles), len(dipoles[0].times))) + source_rr = np.concatenate([_src["rr"][_src["vertno"], :] for _src in src], axis=0) + n_lh_points = len(src[0]["vertno"]) + lh_vertno = list() + rh_vertno = list() + for i in range(len(dipoles)): + if not np.all(dipoles[i].pos == dipoles[i].pos[0]): + raise ValueError( + "Only dipoles with fixed position over time are supported!" + ) + X[i] = dipoles[i].amplitude + idx = np.all(source_rr == dipoles[i].pos[0], axis=1) + idx = np.where(idx)[0][0] + if idx < n_lh_points: + lh_vertno.append(src[0]["vertno"][idx]) + else: + rh_vertno.append(src[1]["vertno"][idx - n_lh_points]) + vertices = [np.array(lh_vertno).astype(int), np.array(rh_vertno).astype(int)] + stc = SourceEstimate( + X, vertices=vertices, tmin=tmin, tstep=tstep, subject=src._subject + ) + logger.info("[done]") + return stc + + +@verbose +def mixed_norm( + evoked, + forward, + noise_cov, + alpha="sure", + loose="auto", + depth=0.8, + maxit=3000, + tol=1e-4, + active_set_size=10, + debias=True, + time_pca=True, + weights=None, + weights_min=0.0, + solver="auto", + n_mxne_iter=1, + return_residual=False, + return_as_dipoles=False, + dgap_freq=10, + rank=None, + pick_ori=None, + sure_alpha_grid="auto", + random_state=None, + verbose=None, +): + """Mixed-norm estimate (MxNE) and iterative reweighted MxNE (irMxNE). + + Compute L1/L2 mixed-norm solution :footcite:`GramfortEtAl2012` or L0.5/L2 + :footcite:`StrohmeierEtAl2016` mixed-norm solution on evoked data. + + Parameters + ---------- + evoked : instance of Evoked or list of instances of Evoked + Evoked data to invert. + forward : dict + Forward operator. + noise_cov : instance of Covariance + Noise covariance to compute whitener. + alpha : float | str + Regularization parameter. If float it should be in the range [0, 100): + 0 means no regularization, 100 would give 0 active dipole. + If ``'sure'`` (default), the SURE method from + :footcite:`DeledalleEtAl2014` will be used. + + .. versionchanged:: 0.24 + The default was changed to ``'sure'``. + %(loose)s + %(depth)s + maxit : int + Maximum number of iterations. + tol : float + Tolerance parameter. + active_set_size : int | None + Size of active set increment. If None, no active set strategy is used. + debias : bool + Remove coefficient amplitude bias due to L1 penalty. + time_pca : bool or int + If True the rank of the concatenated epochs is reduced to + its true dimension. If is 'int' the rank is limited to this value. + weights : None | array | SourceEstimate + Weight for penalty in mixed_norm. Can be None, a + 1d array with shape (n_sources,), or a SourceEstimate (e.g. obtained + with wMNE, dSPM, or fMRI). + weights_min : float + Do not consider in the estimation sources for which weights + is less than weights_min. + solver : 'cd' | 'bcd' | 'auto' + The algorithm to use for the optimization. 'cd' uses + coordinate descent, and 'bcd' applies block coordinate descent. + 'cd' is only available for fixed orientation. + n_mxne_iter : int + The number of MxNE iterations. If > 1, iterative reweighting + is applied. + return_residual : bool + If True, the residual is returned as an Evoked instance. + return_as_dipoles : bool + If True, the sources are returned as a list of Dipole instances. + dgap_freq : int or np.inf + The duality gap is evaluated every dgap_freq iterations. Ignored if + solver is 'cd'. + %(rank_none)s + + .. versionadded:: 0.18 + %(pick_ori)s + sure_alpha_grid : array | str + If ``'auto'`` (default), the SURE is evaluated along 15 uniformly + distributed alphas between alpha_max and 0.1 * alpha_max. If array, the + grid is directly specified. Ignored if alpha is not "sure". + + .. versionadded:: 0.24 + random_state : int | None + The random state used in a random number generator for delta and + epsilon used for the SURE computation. Defaults to None. + + .. versionadded:: 0.24 + %(verbose)s + + Returns + ------- + stc : SourceEstimate | list of SourceEstimate + Source time courses for each evoked data passed as input. + residual : instance of Evoked + The residual a.k.a. data not explained by the sources. + Only returned if return_residual is True. + + See Also + -------- + tf_mixed_norm + + References + ---------- + .. footbibliography:: + """ + _validate_type(alpha, ("numeric", str), "alpha") + if isinstance(alpha, str): + _check_option("alpha", alpha, ("sure",)) + elif not 0.0 <= alpha < 100: + raise ValueError( + f'If not equal to "sure" alpha must be in [0, 100). Got alpha = {alpha}' + ) + if n_mxne_iter < 1: + raise ValueError( + "MxNE has to be computed at least 1 time. " + f"Requires n_mxne_iter >= 1, got {n_mxne_iter}" + ) + if dgap_freq <= 0.0: + raise ValueError( + f"dgap_freq must be a positive integer. Got dgap_freq = {dgap_freq}" + ) + if not ( + isinstance(sure_alpha_grid, np.ndarray | list) or sure_alpha_grid == "auto" + ): + raise ValueError( + 'If not equal to "auto" sure_alpha_grid must be an ' + f"array. Got {type(sure_alpha_grid)}" + ) + if (isinstance(sure_alpha_grid, str) and sure_alpha_grid != "auto") and ( + isinstance(alpha, str) and alpha != "sure" + ): + raise Exception( + "If sure_alpha_grid is manually specified, alpha must " + f'be "sure". Got {alpha}' + ) + pca = True + if not isinstance(evoked, list): + evoked = [evoked] + + _check_reference(evoked[0]) + + all_ch_names = evoked[0].ch_names + if not all(all_ch_names == evoked[i].ch_names for i in range(1, len(evoked))): + raise Exception("All the datasets must have the same good channels.") + + forward, gain, gain_info, whitener, source_weighting, mask = _prepare_gain( + forward, + evoked[0].info, + noise_cov, + pca, + depth, + loose, + rank, + weights, + weights_min, + ) + _check_ori(pick_ori, forward) + + sel = [all_ch_names.index(name) for name in gain_info["ch_names"]] + M = np.concatenate([e.data[sel] for e in evoked], axis=1) + + # Whiten data + logger.info("Whitening data matrix.") + M = np.dot(whitener, M) + + if time_pca: + U, s, Vh = _safe_svd(M, full_matrices=False) + if not isinstance(time_pca, bool) and isinstance(time_pca, int): + U = U[:, :time_pca] + s = s[:time_pca] + Vh = Vh[:time_pca] + M = U * s + + # Scaling to make setting of tol and alpha easy + tol *= sum_squared(M) + n_dip_per_pos = 1 if is_fixed_orient(forward) else 3 + alpha_max = norm_l2inf(np.dot(gain.T, M), n_dip_per_pos, copy=False) + alpha_max *= 0.01 + gain /= alpha_max + source_weighting /= alpha_max + + # Alpha selected automatically by SURE minimization + if alpha == "sure": + alpha_grid = sure_alpha_grid + if isinstance(sure_alpha_grid, str) and sure_alpha_grid == "auto": + alpha_grid = np.geomspace(100, 10, num=15) + X, active_set, best_alpha_ = _compute_mxne_sure( + M, + gain, + alpha_grid, + sigma=1, + random_state=random_state, + n_mxne_iter=n_mxne_iter, + maxit=maxit, + tol=tol, + n_orient=n_dip_per_pos, + active_set_size=active_set_size, + debias=debias, + solver=solver, + dgap_freq=dgap_freq, + verbose=verbose, + ) + logger.info(f"Selected alpha: {best_alpha_}") + else: + if n_mxne_iter == 1: + X, active_set, E = mixed_norm_solver( + M, + gain, + alpha, + maxit=maxit, + tol=tol, + active_set_size=active_set_size, + n_orient=n_dip_per_pos, + debias=debias, + solver=solver, + dgap_freq=dgap_freq, + verbose=verbose, + ) + else: + X, active_set, E = iterative_mixed_norm_solver( + M, + gain, + alpha, + n_mxne_iter, + maxit=maxit, + tol=tol, + n_orient=n_dip_per_pos, + active_set_size=active_set_size, + debias=debias, + solver=solver, + dgap_freq=dgap_freq, + verbose=verbose, + ) + + if time_pca: + X = np.dot(X, Vh) + M = np.dot(M, Vh) + + gain_active = gain[:, active_set] + if mask is not None: + active_set_tmp = np.zeros(len(mask), dtype=bool) + active_set_tmp[mask] = active_set + active_set = active_set_tmp + del active_set_tmp + + if active_set.sum() == 0: + warn("No active dipoles found. alpha is too big.") + M_estimate = np.zeros_like(M) + else: + # Reapply weights to have correct unit + X = _reapply_source_weighting(X, source_weighting, active_set) + source_weighting[source_weighting == 0] = 1 # zeros + gain_active /= source_weighting[active_set] + del source_weighting + M_estimate = np.dot(gain_active, X) + + outs = list() + residual = list() + cnt = 0 + for e in evoked: + tmin = e.times[0] + tstep = 1.0 / e.info["sfreq"] + Xe = X[:, cnt : (cnt + len(e.times))] + if return_as_dipoles: + out = _make_dipoles_sparse( + Xe, + active_set, + forward, + tmin, + tstep, + M[:, cnt : (cnt + len(e.times))], + gain_active, + ) + else: + out = _make_sparse_stc( + Xe, active_set, forward, tmin, tstep, pick_ori=pick_ori + ) + outs.append(out) + cnt += len(e.times) + + if return_residual: + residual.append(_compute_residual(forward, e, Xe, active_set, gain_info)) + + _log_exp_var(M, M_estimate, prefix="") + logger.info("[done]") + + if len(outs) == 1: + out = outs[0] + if return_residual: + residual = residual[0] + else: + out = outs + + if return_residual: + out = out, residual + + return out + + +def _window_evoked(evoked, size): + """Window evoked (size in seconds).""" + if isinstance(size, float | int): + lsize = rsize = float(size) + else: + lsize, rsize = size + evoked = evoked.copy() + sfreq = float(evoked.info["sfreq"]) + lsize = int(lsize * sfreq) + rsize = int(rsize * sfreq) + lhann = np.hanning(lsize * 2)[:lsize] + rhann = np.hanning(rsize * 2)[-rsize:] + window = np.r_[lhann, np.ones(len(evoked.times) - lsize - rsize), rhann] + evoked.data *= window[None, :] + return evoked + + +@verbose +def tf_mixed_norm( + evoked, + forward, + noise_cov, + loose="auto", + depth=0.8, + maxit=3000, + tol=1e-4, + weights=None, + weights_min=0.0, + pca=True, + debias=True, + wsize=64, + tstep=4, + window=0.02, + return_residual=False, + return_as_dipoles=False, + alpha=None, + l1_ratio=None, + dgap_freq=10, + rank=None, + pick_ori=None, + n_tfmxne_iter=1, + verbose=None, +): + """Time-Frequency Mixed-norm estimate (TF-MxNE). + + Compute L1/L2 + L1 mixed-norm solution on time-frequency + dictionary. Works with evoked data + :footcite:`GramfortEtAl2013b,GramfortEtAl2011`. + + Parameters + ---------- + evoked : instance of Evoked + Evoked data to invert. + forward : dict + Forward operator. + noise_cov : instance of Covariance + Noise covariance to compute whitener. + %(loose)s + %(depth)s + maxit : int + Maximum number of iterations. + tol : float + Tolerance parameter. + weights : None | array | SourceEstimate + Weight for penalty in mixed_norm. Can be None or + 1d array of length n_sources or a SourceEstimate e.g. obtained + with wMNE or dSPM or fMRI. + weights_min : float + Do not consider in the estimation sources for which weights + is less than weights_min. + pca : bool + If True the rank of the data is reduced to true dimension. + debias : bool + Remove coefficient amplitude bias due to L1 penalty. + wsize : int or array-like + Length of the STFT window in samples (must be a multiple of 4). + If an array is passed, multiple TF dictionaries are used (each having + its own wsize and tstep) and each entry of wsize must be a multiple + of 4. See :footcite:`BekhtiEtAl2016`. + tstep : int or array-like + Step between successive windows in samples (must be a multiple of 2, + a divider of wsize and smaller than wsize/2) (default: wsize/2). + If an array is passed, multiple TF dictionaries are used (each having + its own wsize and tstep), and each entry of tstep must be a multiple + of 2 and divide the corresponding entry of wsize. See + :footcite:`BekhtiEtAl2016`. + window : float or (float, float) + Length of time window used to take care of edge artifacts in seconds. + It can be one float or float if the values are different for left + and right window length. + return_residual : bool + If True, the residual is returned as an Evoked instance. + return_as_dipoles : bool + If True, the sources are returned as a list of Dipole instances. + alpha : float in [0, 100) or None + Overall regularization parameter. + If alpha and l1_ratio are not None, alpha_space and alpha_time are + overridden by alpha * alpha_max * (1. - l1_ratio) and alpha * alpha_max + * l1_ratio. 0 means no regularization, 100 would give 0 active dipole. + l1_ratio : float in [0, 1] or None + Proportion of temporal regularization. + If l1_ratio and alpha are not None, alpha_space and alpha_time are + overridden by alpha * alpha_max * (1. - l1_ratio) and alpha * alpha_max + * l1_ratio. 0 means no time regularization a.k.a. MxNE. + dgap_freq : int or np.inf + The duality gap is evaluated every dgap_freq iterations. + %(rank_none)s + + .. versionadded:: 0.18 + %(pick_ori)s + n_tfmxne_iter : int + Number of TF-MxNE iterations. If > 1, iterative reweighting is applied. + %(verbose)s + + Returns + ------- + stc : instance of SourceEstimate + Source time courses. + residual : instance of Evoked + The residual a.k.a. data not explained by the sources. + Only returned if return_residual is True. + + See Also + -------- + mixed_norm + + References + ---------- + .. footbibliography:: + """ + _check_reference(evoked) + + all_ch_names = evoked.ch_names + info = evoked.info + + if not (0.0 <= alpha < 100.0): + raise ValueError(f"alpha must be in [0, 100). Got alpha = {alpha}") + + if not (0.0 <= l1_ratio <= 1.0): + raise ValueError(f"l1_ratio must be in range [0, 1]. Got l1_ratio = {l1_ratio}") + alpha_space = alpha * (1.0 - l1_ratio) + alpha_time = alpha * l1_ratio + + if n_tfmxne_iter < 1: + raise ValueError( + "TF-MxNE has to be computed at least 1 time. " + f"Requires n_tfmxne_iter >= 1, got {n_tfmxne_iter}" + ) + + if dgap_freq <= 0.0: + raise ValueError( + f"dgap_freq must be a positive integer. Got dgap_freq = {dgap_freq}" + ) + + tstep = np.atleast_1d(tstep) + wsize = np.atleast_1d(wsize) + if len(tstep) != len(wsize): + raise ValueError( + "The same number of window sizes and steps must be " + f"passed. Got tstep = {tstep} and wsize = {wsize}" + ) + + forward, gain, gain_info, whitener, source_weighting, mask = _prepare_gain( + forward, evoked.info, noise_cov, pca, depth, loose, rank, weights, weights_min + ) + _check_ori(pick_ori, forward) + + n_dip_per_pos = 1 if is_fixed_orient(forward) else 3 + + if window is not None: + evoked = _window_evoked(evoked, window) + + sel = [all_ch_names.index(name) for name in gain_info["ch_names"]] + M = evoked.data[sel] + + # Whiten data + logger.info("Whitening data matrix.") + M = np.dot(whitener, M) + + n_steps = np.ceil(M.shape[1] / tstep.astype(float)).astype(int) + n_freqs = wsize // 2 + 1 + n_coefs = n_steps * n_freqs + phi = _Phi(wsize, tstep, n_coefs, evoked.data.shape[1]) + + # Scaling to make setting of tol and alpha easy + tol *= sum_squared(M) + alpha_max = norm_epsilon_inf(gain, M, phi, l1_ratio, n_dip_per_pos) + alpha_max *= 0.01 + gain /= alpha_max + source_weighting /= alpha_max + + if n_tfmxne_iter == 1: + X, active_set, E = tf_mixed_norm_solver( + M, + gain, + alpha_space, + alpha_time, + wsize=wsize, + tstep=tstep, + maxit=maxit, + tol=tol, + verbose=verbose, + n_orient=n_dip_per_pos, + dgap_freq=dgap_freq, + debias=debias, + ) + else: + X, active_set, E = iterative_tf_mixed_norm_solver( + M, + gain, + alpha_space, + alpha_time, + wsize=wsize, + tstep=tstep, + n_tfmxne_iter=n_tfmxne_iter, + maxit=maxit, + tol=tol, + verbose=verbose, + n_orient=n_dip_per_pos, + dgap_freq=dgap_freq, + debias=debias, + ) + + if active_set.sum() == 0: + raise Exception("No active dipoles found. alpha_space/alpha_time are too big.") + + # Compute estimated whitened sensor data for each dipole (dip, ch, time) + gain_active = gain[:, active_set] + + if mask is not None: + active_set_tmp = np.zeros(len(mask), dtype=bool) + active_set_tmp[mask] = active_set + active_set = active_set_tmp + del active_set_tmp + + X = _reapply_source_weighting(X, source_weighting, active_set) + gain_active /= source_weighting[active_set] + + if return_residual: + residual = _compute_residual(forward, evoked, X, active_set, gain_info) + + if return_as_dipoles: + out = _make_dipoles_sparse( + X, active_set, forward, evoked.times[0], 1.0 / info["sfreq"], M, gain_active + ) + else: + out = _make_sparse_stc( + X, + active_set, + forward, + evoked.times[0], + 1.0 / info["sfreq"], + pick_ori=pick_ori, + ) + + logger.info("[done]") + + if return_residual: + out = out, residual + + return out + + +@verbose +def _compute_mxne_sure( + M, + gain, + alpha_grid, + sigma, + n_mxne_iter, + maxit, + tol, + n_orient, + active_set_size, + debias, + solver, + dgap_freq, + random_state, + verbose, +): + """Stein Unbiased Risk Estimator (SURE). + + Implements the finite-difference Monte-Carlo approximation + of the SURE for Multi-Task LASSO. + + See reference :footcite:`DeledalleEtAl2014`. + + Parameters + ---------- + M : array, shape (n_sensors, n_times) + The data. + gain : array, shape (n_sensors, n_dipoles) + The gain matrix a.k.a. lead field. + alpha_grid : array, shape (n_alphas,) + The grid of alphas used to evaluate the SURE. + sigma : float + The true or estimated noise level in the data. Usually 1 if the data + has been previously whitened using MNE whitener. + n_mxne_iter : int + The number of MxNE iterations. If > 1, iterative reweighting is + applied. + maxit : int + Maximum number of iterations. + tol : float + Tolerance parameter. + n_orient : int + The number of orientation (1 : fixed or 3 : free or loose). + active_set_size : int + Size of active set increase at each iteration. + debias : bool + Debias source estimates. + solver : 'cd' | 'bcd' | 'auto' + The algorithm to use for the optimization. + dgap_freq : int or np.inf + The duality gap is evaluated every dgap_freq iterations. + random_state : int | None + The random state used in a random number generator for delta and + epsilon used for the SURE computation. + + Returns + ------- + X : array, shape (n_active, n_times) + Coefficient matrix. + active_set : array, shape (n_dipoles,) + Array of indices of non-zero coefficients. + best_alpha_ : float + Alpha that minimizes the SURE. + + References + ---------- + .. footbibliography:: + """ + + def g(w): + return np.sqrt(np.sqrt(groups_norm2(w.copy(), n_orient))) + + def gprime(w): + return 2.0 * np.repeat(g(w), n_orient).ravel() + + def _run_solver(alpha, M, n_mxne_iter, as_init=None, X_init=None, w_init=None): + if n_mxne_iter == 1: + X, active_set, _ = mixed_norm_solver( + M, + gain, + alpha, + maxit=maxit, + tol=tol, + active_set_size=active_set_size, + n_orient=n_orient, + debias=debias, + solver=solver, + dgap_freq=dgap_freq, + active_set_init=as_init, + X_init=X_init, + verbose=False, + ) + else: + X, active_set, _ = iterative_mixed_norm_solver( + M, + gain, + alpha, + n_mxne_iter, + maxit=maxit, + tol=tol, + n_orient=n_orient, + active_set_size=active_set_size, + debias=debias, + solver=solver, + dgap_freq=dgap_freq, + weight_init=w_init, + verbose=False, + ) + return X, active_set + + def _fit_on_grid(gain, M, eps, delta): + coefs_grid_1_0 = np.zeros((len(alpha_grid), gain.shape[1], M.shape[1])) + coefs_grid_2_0 = np.zeros((len(alpha_grid), gain.shape[1], M.shape[1])) + active_sets, active_sets_eps = [], [] + M_eps = M + eps * delta + # warm start - first iteration (leverages convexity) + logger.info("Warm starting...") + for j, alpha in enumerate(alpha_grid): + logger.info(f"alpha: {alpha}") + X, a_set = _run_solver(alpha, M, 1) + X_eps, a_set_eps = _run_solver(alpha, M_eps, 1) + coefs_grid_1_0[j][a_set, :] = X + coefs_grid_2_0[j][a_set_eps, :] = X_eps + active_sets.append(a_set) + active_sets_eps.append(a_set_eps) + # next iterations + if n_mxne_iter == 1: + return coefs_grid_1_0, coefs_grid_2_0, active_sets + else: + coefs_grid_1 = coefs_grid_1_0.copy() + coefs_grid_2 = coefs_grid_2_0.copy() + logger.info("Fitting SURE on grid.") + for j, alpha in enumerate(alpha_grid): + logger.info(f"alpha: {alpha}") + if active_sets[j].sum() > 0: + w = gprime(coefs_grid_1[j]) + X, a_set = _run_solver(alpha, M, n_mxne_iter - 1, w_init=w) + coefs_grid_1[j][a_set, :] = X + active_sets[j] = a_set + if active_sets_eps[j].sum() > 0: + w_eps = gprime(coefs_grid_2[j]) + X_eps, a_set_eps = _run_solver( + alpha, M_eps, n_mxne_iter - 1, w_init=w_eps + ) + coefs_grid_2[j][a_set_eps, :] = X_eps + active_sets_eps[j] = a_set_eps + + return coefs_grid_1, coefs_grid_2, active_sets + + def _compute_sure_val(coef1, coef2, gain, M, sigma, delta, eps): + n_sensors, n_times = gain.shape[0], M.shape[1] + dof = (gain @ (coef2 - coef1) * delta).sum() / eps + df_term = np.linalg.norm(M - gain @ coef1) ** 2 + sure = df_term - n_sensors * n_times * sigma**2 + sure += 2 * dof * sigma**2 + return sure + + sure_path = np.empty(len(alpha_grid)) + + rng = check_random_state(random_state) + # See Deledalle et al. 20214 Sec. 5.1 + eps = 2 * sigma / (M.shape[0] ** 0.3) + delta = rng.randn(*M.shape) + + coefs_grid_1, coefs_grid_2, active_sets = _fit_on_grid(gain, M, eps, delta) + + logger.info("Computing SURE values on grid.") + for i, (coef1, coef2) in enumerate(zip(coefs_grid_1, coefs_grid_2)): + sure_path[i] = _compute_sure_val(coef1, coef2, gain, M, sigma, delta, eps) + if verbose: + logger.info(f"alpha {alpha_grid[i]} :: sure {sure_path[i]}") + best_alpha_ = alpha_grid[np.argmin(sure_path)] + + X = coefs_grid_1[np.argmin(sure_path)] + active_set = active_sets[np.argmin(sure_path)] + + X = X[active_set, :] + + return X, active_set, best_alpha_ diff --git a/mne-python/source/mne/inverse_sparse/mxne_optim.py b/mne-python/source/mne/inverse_sparse/mxne_optim.py new file mode 100644 index 0000000000000000000000000000000000000000..528cc140654220d46b925f33e92add6d667b215e --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/mxne_optim.py @@ -0,0 +1,1687 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import functools +from math import sqrt + +import numpy as np + +from ..time_frequency._stft import istft, stft, stft_norm1, stft_norm2 +from ..utils import ( + _check_option, + _get_blas_funcs, + _validate_type, + logger, + sum_squared, + verbose, + warn, +) +from .mxne_debiasing import compute_bias + + +@functools.lru_cache(None) +def _get_dgemm(): + return _get_blas_funcs(np.float64, "gemm") + + +def groups_norm2(A, n_orient): + """Compute squared L2 norms of groups inplace.""" + n_positions = A.shape[0] // n_orient + return np.sum(np.power(A, 2, A).reshape(n_positions, -1), axis=1) + + +def norm_l2inf(A, n_orient, copy=True): + """L2-inf norm.""" + if A.size == 0: + return 0.0 + if copy: + A = A.copy() + return sqrt(np.max(groups_norm2(A, n_orient))) + + +def norm_l21(A, n_orient, copy=True): + """L21 norm.""" + if A.size == 0: + return 0.0 + if copy: + A = A.copy() + return np.sum(np.sqrt(groups_norm2(A, n_orient))) + + +def _primal_l21(M, G, X, active_set, alpha, n_orient): + """Primal objective for the mixed-norm inverse problem. + + See :footcite:`GramfortEtAl2012`. + + Parameters + ---------- + M : array, shape (n_sensors, n_times) + The data. + G : array, shape (n_sensors, n_active) + The gain matrix a.k.a. lead field. + X : array, shape (n_active, n_times) + Sources. + active_set : array of bool, shape (n_sources,) + Mask of active sources. + alpha : float + The regularization parameter. + n_orient : int + Number of dipoles per locations (typically 1 or 3). + + Returns + ------- + p_obj : float + Primal objective. + R : array, shape (n_sensors, n_times) + Current residual (M - G * X). + nR2 : float + Data-fitting term. + GX : array, shape (n_sensors, n_times) + Forward prediction. + """ + GX = np.dot(G[:, active_set], X) + R = M - GX + penalty = norm_l21(X, n_orient, copy=True) + nR2 = sum_squared(R) + p_obj = 0.5 * nR2 + alpha * penalty + return p_obj, R, nR2, GX + + +def dgap_l21(M, G, X, active_set, alpha, n_orient): + """Duality gap for the mixed norm inverse problem. + + See :footcite:`GramfortEtAl2012`. + + Parameters + ---------- + M : array, shape (n_sensors, n_times) + The data. + G : array, shape (n_sensors, n_active) + The gain matrix a.k.a. lead field. + X : array, shape (n_active, n_times) + Sources. + active_set : array of bool, shape (n_sources, ) + Mask of active sources. + alpha : float + The regularization parameter. + n_orient : int + Number of dipoles per locations (typically 1 or 3). + + Returns + ------- + gap : float + Dual gap. + p_obj : float + Primal objective. + d_obj : float + Dual objective. gap = p_obj - d_obj. + R : array, shape (n_sensors, n_times) + Current residual (M - G * X). + + References + ---------- + .. footbibilography:: + """ + p_obj, R, nR2, GX = _primal_l21(M, G, X, active_set, alpha, n_orient) + dual_norm = norm_l2inf(np.dot(G.T, R), n_orient, copy=False) + scaling = alpha / dual_norm + scaling = min(scaling, 1.0) + d_obj = (scaling - 0.5 * (scaling**2)) * nR2 + scaling * np.sum(R * GX) + + gap = p_obj - d_obj + return gap, p_obj, d_obj, R + + +def _mixed_norm_solver_cd( + M, + G, + alpha, + lipschitz_constant, + maxit=10000, + tol=1e-8, + init=None, + n_orient=1, + dgap_freq=10, +): + """Solve L21 inverse problem with coordinate descent.""" + from sklearn.linear_model import MultiTaskLasso + + assert M.ndim == G.ndim and M.shape[0] == G.shape[0] + + clf = MultiTaskLasso( + alpha=alpha / len(M), + tol=tol / sum_squared(M), + fit_intercept=False, + max_iter=maxit, + warm_start=True, + ) + if init is not None: + clf.coef_ = init.T + else: + clf.coef_ = np.zeros((G.shape[1], M.shape[1])).T + clf.fit(G, M) + + X = clf.coef_.T + active_set = np.any(X, axis=1) + X = X[active_set] + gap, p_obj, d_obj, _ = dgap_l21(M, G, X, active_set, alpha, n_orient) + return X, active_set, p_obj + + +def _mixed_norm_solver_bcd( + M, + G, + alpha, + lipschitz_constant, + maxit=200, + tol=1e-8, + init=None, + n_orient=1, + dgap_freq=10, + use_accel=True, + K=5, +): + """Solve L21 inverse problem with block coordinate descent.""" + _, n_times = M.shape + _, n_sources = G.shape + n_positions = n_sources // n_orient + + if init is None: + X = np.zeros((n_sources, n_times)) + R = M.copy() + else: + X = init + R = M - np.dot(G, X) + + E = [] # track primal objective function + highest_d_obj = -np.inf + active_set = np.zeros(n_sources, dtype=bool) # start with full AS + + alpha_lc = alpha / lipschitz_constant + + if use_accel: + last_K_X = np.empty((K + 1, n_sources, n_times)) + U = np.zeros((K, n_sources * n_times)) + + # First make G fortran for faster access to blocks of columns + G = np.asfortranarray(G) + # Ensure these are correct for dgemm + assert R.dtype == np.float64 + assert G.dtype == np.float64 + one_ovr_lc = 1.0 / lipschitz_constant + + # assert that all the multiplied matrices are fortran contiguous + assert X.T.flags.f_contiguous + assert R.T.flags.f_contiguous + assert G.flags.f_contiguous + # storing list of contiguous arrays + list_G_j_c = [] + for j in range(n_positions): + idx = slice(j * n_orient, (j + 1) * n_orient) + list_G_j_c.append(np.ascontiguousarray(G[:, idx])) + + for i in range(maxit): + _bcd(G, X, R, active_set, one_ovr_lc, n_orient, alpha_lc, list_G_j_c) + + if (i + 1) % dgap_freq == 0: + _, p_obj, d_obj, _ = dgap_l21( + M, G, X[active_set], active_set, alpha, n_orient + ) + highest_d_obj = max(d_obj, highest_d_obj) + gap = p_obj - highest_d_obj + E.append(p_obj) + logger.debug( + "Iteration %d :: p_obj %f :: dgap %f :: n_active %d", + i + 1, + p_obj, + gap, + np.sum(active_set) / n_orient, + ) + + if gap < tol: + logger.debug(f"Convergence reached ! (gap: {gap} < {tol})") + break + + # using Anderson acceleration of the primal variable for faster + # convergence + if use_accel: + last_K_X[i % (K + 1)] = X + + if i % (K + 1) == K: + for k in range(K): + U[k] = last_K_X[k + 1].ravel() - last_K_X[k].ravel() + C = U @ U.T + # at least on ARM64 we can't rely on np.linalg.solve to + # reliably raise LinAlgError here, so use SVD instead + # equivalent to: + # z = np.linalg.solve(C, np.ones(K)) + u, s, _ = np.linalg.svd(C, hermitian=True) + if s[-1] <= 1e-6 * s[0] or not np.isfinite(s).all(): + logger.debug("Iteration %d: LinAlg Error", i + 1) + continue + z = ((u * 1 / s) @ u.T).sum(0) + c = z / z.sum() + X_acc = np.sum(last_K_X[:-1] * c[:, None, None], axis=0) + _grp_norm2_acc = groups_norm2(X_acc, n_orient) + active_set_acc = _grp_norm2_acc != 0 + if n_orient > 1: + active_set_acc = np.kron( + active_set_acc, np.ones(n_orient, dtype=bool) + ) + p_obj = _primal_l21(M, G, X[active_set], active_set, alpha, n_orient)[0] + p_obj_acc = _primal_l21( + M, G, X_acc[active_set_acc], active_set_acc, alpha, n_orient + )[0] + if p_obj_acc < p_obj: + X = X_acc + active_set = active_set_acc + R = M - G[:, active_set] @ X[active_set] + + X = X[active_set] + + return X, active_set, E + + +def _bcd(G, X, R, active_set, one_ovr_lc, n_orient, alpha_lc, list_G_j_c): + """Implement one full pass of BCD. + + BCD stands for Block Coordinate Descent. + This function make use of scipy.linalg.get_blas_funcs to speed reasons. + + Parameters + ---------- + G : array, shape (n_sensors, n_active) + The gain matrix a.k.a. lead field. + X : array, shape (n_sources, n_times) + Sources, modified in place. + R : array, shape (n_sensors, n_times) + The residuals: R = M - G @ X, modified in place. + active_set : array of bool, shape (n_sources, ) + Mask of active sources, modified in place. + one_ovr_lc : array, shape (n_positions, ) + One over the lipschitz constants. + n_orient : int + Number of dipoles per positions (typically 1 or 3). + n_positions : int + Number of source positions. + alpha_lc: array, shape (n_positions, ) + alpha * (Lipschitz constants). + """ + X_j_new = np.zeros_like(X[:n_orient, :], order="C") + dgemm = _get_dgemm() + + for j, G_j_c in enumerate(list_G_j_c): + idx = slice(j * n_orient, (j + 1) * n_orient) + G_j = G[:, idx] + X_j = X[idx] + dgemm( + alpha=one_ovr_lc[j], beta=0.0, a=R.T, b=G_j, c=X_j_new.T, overwrite_c=True + ) + # X_j_new = G_j.T @ R + # Mathurin's trick to avoid checking all the entries + was_non_zero = X_j[0, 0] != 0 + # was_non_zero = np.any(X_j) + if was_non_zero: + dgemm(alpha=1.0, beta=1.0, a=X_j.T, b=G_j_c.T, c=R.T, overwrite_c=True) + # R += np.dot(G_j, X_j) + X_j_new += X_j + block_norm = sqrt(sum_squared(X_j_new)) + if block_norm <= alpha_lc[j]: + X_j.fill(0.0) + active_set[idx] = False + else: + shrink = max(1.0 - alpha_lc[j] / block_norm, 0.0) + X_j_new *= shrink + dgemm(alpha=-1.0, beta=1.0, a=X_j_new.T, b=G_j_c.T, c=R.T, overwrite_c=True) + # R -= np.dot(G_j, X_j_new) + X_j[:] = X_j_new + active_set[idx] = True + + +@verbose +def mixed_norm_solver( + M, + G, + alpha, + maxit=3000, + tol=1e-8, + verbose=None, + active_set_size=50, + debias=True, + n_orient=1, + solver="auto", + return_gap=False, + dgap_freq=10, + active_set_init=None, + X_init=None, +): + """Solve L1/L2 mixed-norm inverse problem with active set strategy. + + See references :footcite:`GramfortEtAl2012,StrohmeierEtAl2016, + BertrandEtAl2020`. + + Parameters + ---------- + M : array, shape (n_sensors, n_times) + The data. + G : array, shape (n_sensors, n_dipoles) + The gain matrix a.k.a. lead field. + alpha : float + The regularization parameter. It should be between 0 and 100. + A value of 100 will lead to an empty active set (no active source). + maxit : int + The number of iterations. + tol : float + Tolerance on dual gap for convergence checking. + %(verbose)s + active_set_size : int + Size of active set increase at each iteration. + debias : bool + Debias source estimates. + n_orient : int + The number of orientation (1 : fixed or 3 : free or loose). + solver : 'cd' | 'bcd' | 'auto' + The algorithm to use for the optimization. Block Coordinate Descent + (BCD) uses Anderson acceleration for faster convergence. + return_gap : bool + Return final duality gap. + dgap_freq : int + The duality gap is computed every dgap_freq iterations of the solver on + the active set. + active_set_init : array, shape (n_dipoles,) or None + The initial active set (boolean array) used at the first iteration. + If None, the usual active set strategy is applied. + X_init : array, shape (n_dipoles, n_times) or None + The initial weight matrix used for warm starting the solver. If None, + the weights are initialized at zero. + + Returns + ------- + X : array, shape (n_active, n_times) + The source estimates. + active_set : array, shape (new_active_set_size,) + The mask of active sources. Note that new_active_set_size is the size + of the active set after convergence of the solver. + E : list + The value of the objective function over the iterations. + gap : float + Final duality gap. Returned only if return_gap is True. + + References + ---------- + .. footbibliography:: + """ + n_dipoles = G.shape[1] + n_positions = n_dipoles // n_orient + _, n_times = M.shape + alpha_max = norm_l2inf(np.dot(G.T, M), n_orient, copy=False) + logger.info(f"-- ALPHA MAX : {alpha_max}") + alpha = float(alpha) + X = np.zeros((n_dipoles, n_times), dtype=G.dtype) + + has_sklearn = True + try: + from sklearn.linear_model import MultiTaskLasso # noqa: F401 + except ImportError: + has_sklearn = False + + _validate_type(solver, str, "solver") + _check_option("solver", solver, ("cd", "bcd", "auto")) + if solver == "auto": + if has_sklearn and (n_orient == 1): + solver = "cd" + else: + solver = "bcd" + + if solver == "cd": + if n_orient == 1 and not has_sklearn: + warn( + "Scikit-learn >= 0.12 cannot be found. Using block coordinate" + " descent instead of coordinate descent." + ) + solver = "bcd" + if n_orient > 1: + warn( + "Coordinate descent is only available for fixed orientation. " + "Using block coordinate descent instead of coordinate " + "descent" + ) + solver = "bcd" + + if solver == "cd": + logger.info("Using coordinate descent") + l21_solver = _mixed_norm_solver_cd + lc = None + else: + assert solver == "bcd" + logger.info("Using block coordinate descent") + l21_solver = _mixed_norm_solver_bcd + G = np.asfortranarray(G) + if n_orient == 1: + lc = np.sum(G * G, axis=0) + else: + lc = np.empty(n_positions) + for j in range(n_positions): + G_tmp = G[:, (j * n_orient) : ((j + 1) * n_orient)] + lc[j] = np.linalg.norm(np.dot(G_tmp.T, G_tmp), ord=2) + + if active_set_size is not None: + E = list() + highest_d_obj = -np.inf + if X_init is not None and X_init.shape != (n_dipoles, n_times): + raise ValueError("Wrong dim for initialized coefficients.") + active_set = ( + active_set_init + if active_set_init is not None + else np.zeros(n_dipoles, dtype=bool) + ) + idx_large_corr = np.argsort(groups_norm2(np.dot(G.T, M), n_orient)) + new_active_idx = idx_large_corr[-active_set_size:] + if n_orient > 1: + new_active_idx = ( + n_orient * new_active_idx[:, None] + np.arange(n_orient)[None, :] + ).ravel() + active_set[new_active_idx] = True + as_size = np.sum(active_set) + gap = np.inf + for k in range(maxit): + if solver == "bcd": + lc_tmp = lc[active_set[::n_orient]] + elif solver == "cd": + lc_tmp = None + else: + lc_tmp = 1.01 * np.linalg.norm(G[:, active_set], ord=2) ** 2 + X, as_, _ = l21_solver( + M, + G[:, active_set], + alpha, + lc_tmp, + maxit=maxit, + tol=tol, + init=X_init, + n_orient=n_orient, + dgap_freq=dgap_freq, + ) + active_set[active_set] = as_.copy() + idx_old_active_set = np.where(active_set)[0] + + _, p_obj, d_obj, R = dgap_l21(M, G, X, active_set, alpha, n_orient) + highest_d_obj = max(d_obj, highest_d_obj) + gap = p_obj - highest_d_obj + E.append(p_obj) + logger.info( + "Iteration %d :: p_obj %f :: dgap %f :: n_active_start %d :: n_active_" + "end %d", + k + 1, + p_obj, + gap, + as_size // n_orient, + np.sum(active_set) // n_orient, + ) + if gap < tol: + logger.info(f"Convergence reached ! (gap: {gap} < {tol})") + break + + # add sources if not last iteration + if k < (maxit - 1): + idx_large_corr = np.argsort(groups_norm2(np.dot(G.T, R), n_orient)) + new_active_idx = idx_large_corr[-active_set_size:] + if n_orient > 1: + new_active_idx = ( + n_orient * new_active_idx[:, None] + + np.arange(n_orient)[None, :] + ) + new_active_idx = new_active_idx.ravel() + active_set[new_active_idx] = True + idx_active_set = np.where(active_set)[0] + as_size = np.sum(active_set) + X_init = np.zeros((as_size, n_times), dtype=X.dtype) + idx = np.searchsorted(idx_active_set, idx_old_active_set) + X_init[idx] = X + else: + warn(f"Did NOT converge ! (gap: {gap} > {tol})") + else: + X, active_set, E = l21_solver( + M, G, alpha, lc, maxit=maxit, tol=tol, n_orient=n_orient, init=None + ) + if return_gap: + gap = dgap_l21(M, G, X, active_set, alpha, n_orient)[0] + + if np.any(active_set) and debias: + bias = compute_bias(M, G[:, active_set], X, n_orient=n_orient) + X *= bias[:, np.newaxis] + + logger.info("Final active set size: %s" % (np.sum(active_set) // n_orient)) + + if return_gap: + return X, active_set, E, gap + else: + return X, active_set, E + + +@verbose +def iterative_mixed_norm_solver( + M, + G, + alpha, + n_mxne_iter, + maxit=3000, + tol=1e-8, + verbose=None, + active_set_size=50, + debias=True, + n_orient=1, + dgap_freq=10, + solver="auto", + weight_init=None, +): + """Solve L0.5/L2 mixed-norm inverse problem with active set strategy. + + See reference :footcite:`StrohmeierEtAl2016`. + + Parameters + ---------- + M : array, shape (n_sensors, n_times) + The data. + G : array, shape (n_sensors, n_dipoles) + The gain matrix a.k.a. lead field. + alpha : float + The regularization parameter. It should be between 0 and 100. + A value of 100 will lead to an empty active set (no active source). + n_mxne_iter : int + The number of MxNE iterations. If > 1, iterative reweighting + is applied. + maxit : int + The number of iterations. + tol : float + Tolerance on dual gap for convergence checking. + %(verbose)s + active_set_size : int + Size of active set increase at each iteration. + debias : bool + Debias source estimates. + n_orient : int + The number of orientation (1 : fixed or 3 : free or loose). + dgap_freq : int or np.inf + The duality gap is evaluated every dgap_freq iterations. + solver : 'cd' | 'bcd' | 'auto' + The algorithm to use for the optimization. + weight_init : array, shape (n_dipoles,) or None + The initial weight used for reweighting the gain matrix. If None, the + weights are initialized with ones. + + Returns + ------- + X : array, shape (n_active, n_times) + The source estimates. + active_set : array + The mask of active sources. + E : list + The value of the objective function over the iterations. + + References + ---------- + .. footbibliography:: + """ + + def g(w): + return np.sqrt(np.sqrt(groups_norm2(w.copy(), n_orient))) + + def gprime(w): + return 2.0 * np.repeat(g(w), n_orient).ravel() + + E = list() + + if weight_init is not None and weight_init.shape != (G.shape[1],): + raise ValueError( + f"Wrong dimension for weight initialization. Got {weight_init.shape}. " + f"Expected {(G.shape[1],)}." + ) + + weights = weight_init if weight_init is not None else np.ones(G.shape[1]) + active_set = weights != 0 + weights = weights[active_set] + X = np.zeros((G.shape[1], M.shape[1])) + + for k in range(n_mxne_iter): + X0 = X.copy() + active_set_0 = active_set.copy() + G_tmp = G[:, active_set] * weights[np.newaxis, :] + + if active_set_size is not None: + if np.sum(active_set) > (active_set_size * n_orient): + X, _active_set, _ = mixed_norm_solver( + M, + G_tmp, + alpha, + debias=False, + n_orient=n_orient, + maxit=maxit, + tol=tol, + active_set_size=active_set_size, + dgap_freq=dgap_freq, + solver=solver, + ) + else: + X, _active_set, _ = mixed_norm_solver( + M, + G_tmp, + alpha, + debias=False, + n_orient=n_orient, + maxit=maxit, + tol=tol, + active_set_size=None, + dgap_freq=dgap_freq, + solver=solver, + ) + else: + X, _active_set, _ = mixed_norm_solver( + M, + G_tmp, + alpha, + debias=False, + n_orient=n_orient, + maxit=maxit, + tol=tol, + active_set_size=None, + dgap_freq=dgap_freq, + solver=solver, + ) + + logger.info("active set size %d", _active_set.sum() / n_orient) + + if _active_set.sum() > 0: + active_set[active_set] = _active_set + # Reapply weights to have correct unit + X *= weights[_active_set][:, np.newaxis] + weights = gprime(X) + p_obj = 0.5 * np.linalg.norm( + M - np.dot(G[:, active_set], X), "fro" + ) ** 2.0 + alpha * np.sum(g(X)) + E.append(p_obj) + + # Check convergence + if ( + (k >= 1) + and np.all(active_set == active_set_0) + and np.all(np.abs(X - X0) < tol) + ): + logger.info("Convergence reached after %d reweightings!", k) + break + else: + active_set = np.zeros_like(active_set) + p_obj = 0.5 * np.linalg.norm(M) ** 2.0 + E.append(p_obj) + break + + if np.any(active_set) and debias: + bias = compute_bias(M, G[:, active_set], X, n_orient=n_orient) + X *= bias[:, np.newaxis] + + return X, active_set, E + + +############################################################################### +# TF-MxNE + + +class _Phi: + """Have phi stft as callable w/o using a lambda that does not pickle.""" + + def __init__(self, wsize, tstep, n_coefs, n_times): + self.wsize = np.atleast_1d(wsize) + self.tstep = np.atleast_1d(tstep) + self.n_coefs = np.atleast_1d(n_coefs) + self.n_dicts = len(tstep) + self.n_freqs = wsize // 2 + 1 + self.n_steps = self.n_coefs // self.n_freqs + self.n_times = n_times + # ravel freq+time here + self.ops = list() + for ws, ts in zip(self.wsize, self.tstep): + self.ops.append( + stft(np.eye(n_times), ws, ts, verbose=False).reshape(n_times, -1) + ) + + def __call__(self, x): # noqa: D105 + if self.n_dicts == 1: + return x @ self.ops[0] + else: + return np.hstack([x @ op for op in self.ops]) / np.sqrt(self.n_dicts) + + def norm(self, z, ord=2): # noqa: A002 + """Squared L2 norm if ord == 2 and L1 norm if order == 1.""" + if ord not in (1, 2): + raise ValueError(f"Only supported norm order are 1 and 2. Got ord = {ord}") + stft_norm = stft_norm1 if ord == 1 else stft_norm2 + norm = 0.0 + if len(self.n_coefs) > 1: + z_ = np.array_split(np.atleast_2d(z), np.cumsum(self.n_coefs)[:-1], axis=1) + else: + z_ = [np.atleast_2d(z)] + for i in range(len(z_)): + norm += stft_norm(z_[i].reshape(-1, self.n_freqs[i], self.n_steps[i])) + return norm + + +class _PhiT: + """Have phi.T istft as callable w/o using a lambda that does not pickle.""" + + def __init__(self, tstep, n_freqs, n_steps, n_times): + self.tstep = tstep + self.n_freqs = n_freqs + self.n_steps = n_steps + self.n_times = n_times + self.n_dicts = len(tstep) if isinstance(tstep, np.ndarray) else 1 + self.n_coefs = list() + self.op_re = list() + self.op_im = list() + for nf, ns, ts in zip(self.n_freqs, self.n_steps, self.tstep): + nc = nf * ns + self.n_coefs.append(nc) + eye = np.eye(nc).reshape(nf, ns, nf, ns) + self.op_re.append(istft(eye, ts, n_times).reshape(nc, n_times)) + self.op_im.append(istft(eye * 1j, ts, n_times).reshape(nc, n_times)) + + def __call__(self, z): # noqa: D105 + if self.n_dicts == 1: + return z.real @ self.op_re[0] + z.imag @ self.op_im[0] + else: + x_out = np.zeros((z.shape[0], self.n_times)) + z_ = np.array_split(z, np.cumsum(self.n_coefs)[:-1], axis=1) + for this_z, op_re, op_im in zip(z_, self.op_re, self.op_im): + x_out += this_z.real @ op_re + this_z.imag @ op_im + return x_out / np.sqrt(self.n_dicts) + + +def norm_l21_tf(Z, phi, n_orient, w_space=None): + """L21 norm for TF.""" + if Z.shape[0]: + l21_norm = np.sqrt(phi.norm(Z, ord=2).reshape(-1, n_orient).sum(axis=1)) + if w_space is not None: + l21_norm *= w_space + l21_norm = l21_norm.sum() + else: + l21_norm = 0.0 + return l21_norm + + +def norm_l1_tf(Z, phi, n_orient, w_time): + """L1 norm for TF.""" + if Z.shape[0]: + n_positions = Z.shape[0] // n_orient + Z_ = np.sqrt( + np.sum((np.abs(Z) ** 2.0).reshape((n_orient, -1), order="F"), axis=0) + ) + Z_ = Z_.reshape((n_positions, -1), order="F") + if w_time is not None: + Z_ *= w_time + l1_norm = phi.norm(Z_, ord=1).sum() + else: + l1_norm = 0.0 + return l1_norm + + +def norm_epsilon(Y, l1_ratio, phi, w_space=1.0, w_time=None): + """Weighted epsilon norm. + + The weighted epsilon norm is the dual norm of:: + + w_{space} * (1. - l1_ratio) * ||Y||_2 + l1_ratio * ||Y||_{1, w_{time}}. + + where `||Y||_{1, w_{time}} = (np.abs(Y) * w_time).sum()` + + Warning: it takes into account the fact that Y only contains coefficients + corresponding to the positive frequencies (see `stft_norm2()`): some + entries will be counted twice. It is also assumed that all entries of both + Y and w_time are non-negative. See + :footcite:`NdiayeEtAl2016,BurdakovMerkulov2001`. + + Parameters + ---------- + Y : array, shape (n_coefs,) + The input data. + l1_ratio : float between 0 and 1 + Tradeoff between L2 and L1 regularization. When it is 0, no temporal + regularization is applied. + phi : instance of _Phi + The TF operator. + w_space : float + Scalar weight of the L2 norm. By default, it is taken equal to 1. + w_time : array, shape (n_coefs, ) | None + Weights of each TF coefficient in the L1 norm. If None, weights equal + to 1 are used. + + + Returns + ------- + nu : float + The value of the dual norm evaluated at Y. + + References + ---------- + .. footbibliography:: + """ + # since the solution is invariant to flipped signs in Y, all entries + # of Y are assumed positive + + # Add negative freqs: count all freqs twice except first and last: + freqs_count = np.full(len(Y), 2) + for i, fc in enumerate(np.array_split(freqs_count, np.cumsum(phi.n_coefs)[:-1])): + fc[: phi.n_steps[i]] = 1 + fc[-phi.n_steps[i] :] = 1 + + # exclude 0 weights: + if w_time is not None: + nonzero_weights = w_time != 0.0 + Y = Y[nonzero_weights] + freqs_count = freqs_count[nonzero_weights] + w_time = w_time[nonzero_weights] + + norm_inf_Y = np.max(Y / w_time) if w_time is not None else np.max(Y) + if l1_ratio == 1.0: + # dual norm of L1 weighted is Linf with inverse weights + return norm_inf_Y + elif l1_ratio == 0.0: + # dual norm of L2 is L2 + return np.sqrt(phi.norm(Y[None, :], ord=2).sum()) + + if norm_inf_Y == 0.0: + return 0.0 + + # ignore some values of Y by lower bound on dual norm: + if w_time is None: + idx = Y > l1_ratio * norm_inf_Y + else: + idx = Y > l1_ratio * np.max( + Y / (w_space * (1.0 - l1_ratio) + l1_ratio * w_time) + ) + + if idx.sum() == 1: + return norm_inf_Y + + # sort both Y / w_time and freqs_count at the same time + if w_time is not None: + idx_sort = np.argsort(Y[idx] / w_time[idx])[::-1] + w_time = w_time[idx][idx_sort] + else: + idx_sort = np.argsort(Y[idx])[::-1] + + Y = Y[idx][idx_sort] + freqs_count = freqs_count[idx][idx_sort] + + Y = np.repeat(Y, freqs_count) + if w_time is not None: + w_time = np.repeat(w_time, freqs_count) + + K = Y.shape[0] + if w_time is None: + p_sum_Y2 = np.cumsum(Y**2) + p_sum_w2 = np.arange(1, K + 1) + p_sum_Yw = np.cumsum(Y) + upper = p_sum_Y2 / Y**2 - 2.0 * p_sum_Yw / Y + p_sum_w2 + else: + p_sum_Y2 = np.cumsum(Y**2) + p_sum_w2 = np.cumsum(w_time**2) + p_sum_Yw = np.cumsum(Y * w_time) + upper = p_sum_Y2 / (Y / w_time) ** 2 - 2.0 * p_sum_Yw / (Y / w_time) + p_sum_w2 + upper_greater = np.where(upper > w_space**2 * (1.0 - l1_ratio) ** 2 / l1_ratio**2)[ + 0 + ] + + i0 = upper_greater[0] - 1 if upper_greater.size else K - 1 + + p_sum_Y2 = p_sum_Y2[i0] + p_sum_w2 = p_sum_w2[i0] + p_sum_Yw = p_sum_Yw[i0] + + denom = l1_ratio**2 * p_sum_w2 - w_space**2 * (1.0 - l1_ratio) ** 2 + if np.abs(denom) < 1e-10: + return p_sum_Y2 / (2.0 * l1_ratio * p_sum_Yw) + else: + delta = (l1_ratio * p_sum_Yw) ** 2 - p_sum_Y2 * denom + return (l1_ratio * p_sum_Yw - np.sqrt(delta)) / denom + + +def norm_epsilon_inf(G, R, phi, l1_ratio, n_orient, w_space=None, w_time=None): + """Weighted epsilon-inf norm of phi(np.dot(G.T, R)). + + Parameters + ---------- + G : array, shape (n_sensors, n_sources) + Gain matrix a.k.a. lead field. + R : array, shape (n_sensors, n_times) + Residual. + phi : instance of _Phi + The TF operator. + l1_ratio : float between 0 and 1 + Parameter controlling the tradeoff between L21 and L1 regularization. + 0 corresponds to an absence of temporal regularization, ie MxNE. + n_orient : int + Number of dipoles per location (typically 1 or 3). + w_space : array, shape (n_positions,) or None. + Weights for the L2 term of the epsilon norm. If None, weights are + all equal to 1. + w_time : array, shape (n_positions, n_coefs) or None + Weights for the L1 term of the epsilon norm. If None, weights are + all equal to 1. + + Returns + ------- + nu : float + The maximum value of the epsilon norms over groups of n_orient dipoles + (consecutive rows of phi(np.dot(G.T, R))). + """ + n_positions = G.shape[1] // n_orient + GTRPhi = np.abs(phi(np.dot(G.T, R))) + # norm over orientations: + GTRPhi = GTRPhi.reshape((n_orient, -1), order="F") + GTRPhi = np.linalg.norm(GTRPhi, axis=0) + GTRPhi = GTRPhi.reshape((n_positions, -1), order="F") + nu = 0.0 + for idx in range(n_positions): + GTRPhi_ = GTRPhi[idx] + w_t = w_time[idx] if w_time is not None else None + w_s = w_space[idx] if w_space is not None else 1.0 + norm_eps = norm_epsilon(GTRPhi_, l1_ratio, phi, w_space=w_s, w_time=w_t) + if norm_eps > nu: + nu = norm_eps + + return nu + + +def dgap_l21l1( + M, + G, + Z, + active_set, + alpha_space, + alpha_time, + phi, + phiT, + n_orient, + highest_d_obj, + w_space=None, + w_time=None, +): + """Duality gap for the time-frequency mixed norm inverse problem. + + See :footcite:`GramfortEtAl2012,NdiayeEtAl2016` + + Parameters + ---------- + M : array, shape (n_sensors, n_times) + The data. + G : array, shape (n_sensors, n_sources) + Gain matrix a.k.a. lead field. + Z : array, shape (n_active, n_coefs) + Sources in TF domain. + active_set : array of bool, shape (n_sources, ) + Mask of active sources. + alpha_space : float + The spatial regularization parameter. + alpha_time : float + The temporal regularization parameter. The higher it is the smoother + will be the estimated time series. + phi : instance of _Phi + The TF operator. + phiT : instance of _PhiT + The transpose of the TF operator. + n_orient : int + Number of dipoles per locations (typically 1 or 3). + highest_d_obj : float + The highest value of the dual objective so far. + w_space : array, shape (n_positions, ) + Array of spatial weights. + w_time : array, shape (n_positions, n_coefs) + Array of TF weights. + + Returns + ------- + gap : float + Dual gap + p_obj : float + Primal objective + d_obj : float + Dual objective. gap = p_obj - d_obj + R : array, shape (n_sensors, n_times) + Current residual (M - G * X) + + References + ---------- + .. footbibliography:: + """ + X = phiT(Z) + GX = np.dot(G[:, active_set], X) + R = M - GX + + # some functions need w_time only on active_set, other need it completely + if w_time is not None: + w_time_as = w_time[active_set[::n_orient]] + else: + w_time_as = None + if w_space is not None: + w_space_as = w_space[active_set[::n_orient]] + else: + w_space_as = None + + penaltyl1 = norm_l1_tf(Z, phi, n_orient, w_time_as) + penaltyl21 = norm_l21_tf(Z, phi, n_orient, w_space_as) + nR2 = sum_squared(R) + p_obj = 0.5 * nR2 + alpha_space * penaltyl21 + alpha_time * penaltyl1 + + l1_ratio = alpha_time / (alpha_space + alpha_time) + dual_norm = norm_epsilon_inf( + G, R, phi, l1_ratio, n_orient, w_space=w_space, w_time=w_time + ) + scaling = min(1.0, (alpha_space + alpha_time) / dual_norm) + + d_obj = (scaling - 0.5 * (scaling**2)) * nR2 + scaling * np.sum(R * GX) + d_obj = max(d_obj, highest_d_obj) + + gap = p_obj - d_obj + return gap, p_obj, d_obj, R + + +def _tf_mixed_norm_solver_bcd_( + M, + G, + Z, + active_set, + candidates, + alpha_space, + alpha_time, + lipschitz_constant, + phi, + phiT, + *, + w_space=None, + w_time=None, + n_orient=1, + maxit=200, + tol=1e-8, + dgap_freq=10, + perc=None, +): + n_sources = G.shape[1] + n_positions = n_sources // n_orient + + # First make G fortran for faster access to blocks of columns + Gd = np.asfortranarray(G) + G = np.ascontiguousarray(Gd.T.reshape(n_positions, n_orient, -1).transpose(0, 2, 1)) + + R = M.copy() # residual + active = np.where(active_set[::n_orient])[0] + for idx in active: + R -= np.dot(G[idx], phiT(Z[idx])) + + E = [] # track primal objective function + + if w_time is None: + alpha_time_lc = alpha_time / lipschitz_constant + else: + alpha_time_lc = alpha_time * w_time / lipschitz_constant[:, None] + if w_space is None: + alpha_space_lc = alpha_space / lipschitz_constant + else: + alpha_space_lc = alpha_space * w_space / lipschitz_constant + + converged = False + d_obj = -np.inf + + for i in range(maxit): + for jj in candidates: + ids = jj * n_orient + ide = ids + n_orient + + G_j = G[jj] + Z_j = Z[jj] + active_set_j = active_set[ids:ide] + + was_active = np.any(active_set_j) + + # gradient step + GTR = np.dot(G_j.T, R) / lipschitz_constant[jj] + X_j_new = GTR.copy() + + if was_active: + X_j = phiT(Z_j) + R += np.dot(G_j, X_j) + X_j_new += X_j + + rows_norm = np.linalg.norm(X_j_new, "fro") + if rows_norm <= alpha_space_lc[jj]: + if was_active: + Z[jj] = 0.0 + active_set_j[:] = False + else: + GTR_phi = phi(GTR) + if was_active: + Z_j_new = Z_j + GTR_phi + else: + Z_j_new = GTR_phi + col_norm = np.linalg.norm(Z_j_new, axis=0) + + if np.all(col_norm <= alpha_time_lc[jj]): + Z[jj] = 0.0 + active_set_j[:] = False + else: + # l1 + shrink = np.maximum( + 1.0 + - alpha_time_lc[jj] / np.maximum(col_norm, alpha_time_lc[jj]), + 0.0, + ) + if w_time is not None: + shrink[w_time[jj] == 0.0] = 0.0 + Z_j_new *= shrink[np.newaxis, :] + + # l21 + shape_init = Z_j_new.shape + row_norm = np.sqrt(phi.norm(Z_j_new, ord=2).sum()) + if row_norm <= alpha_space_lc[jj]: + Z[jj] = 0.0 + active_set_j[:] = False + else: + shrink = np.maximum( + 1.0 + - alpha_space_lc[jj] + / np.maximum(row_norm, alpha_space_lc[jj]), + 0.0, + ) + Z_j_new *= shrink + Z[jj] = Z_j_new.reshape(-1, *shape_init[1:]).copy() + active_set_j[:] = True + Z_j_phi_T = phiT(Z[jj]) + R -= np.dot(G_j, Z_j_phi_T) + + if (i + 1) % dgap_freq == 0: + Zd = np.vstack([Z[pos] for pos in range(n_positions) if np.any(Z[pos])]) + gap, p_obj, d_obj, _ = dgap_l21l1( + M, + Gd, + Zd, + active_set, + alpha_space, + alpha_time, + phi, + phiT, + n_orient, + d_obj, + w_space=w_space, + w_time=w_time, + ) + converged = gap < tol + E.append(p_obj) + logger.info( + "\n Iteration %d :: n_active %d", + i + 1, + np.sum(active_set) / n_orient, + ) + logger.info(f" dgap {gap:.2e} :: p_obj {p_obj} :: d_obj {d_obj}") + + if converged: + break + + if perc is not None: + if np.sum(active_set) / float(n_orient) <= perc * n_positions: + break + + return Z, active_set, E, converged + + +def _tf_mixed_norm_solver_bcd_active_set( + M, + G, + alpha_space, + alpha_time, + lipschitz_constant, + phi, + phiT, + *, + Z_init=None, + w_space=None, + w_time=None, + n_orient=1, + maxit=200, + tol=1e-8, + dgap_freq=10, +): + n_sensors, n_times = M.shape + n_sources = G.shape[1] + n_positions = n_sources // n_orient + + Z = dict.fromkeys(np.arange(n_positions), 0.0) + active_set = np.zeros(n_sources, dtype=bool) + active = [] + if Z_init is not None: + if Z_init.shape != (n_sources, phi.n_coefs.sum()): + raise Exception( + "Z_init must be None or an array with shape (n_sources, n_coefs)." + ) + for ii in range(n_positions): + if np.any(Z_init[ii * n_orient : (ii + 1) * n_orient]): + active_set[ii * n_orient : (ii + 1) * n_orient] = True + active.append(ii) + if len(active): + Z.update(dict(zip(active, np.vsplit(Z_init[active_set], len(active))))) + + E = [] + candidates = range(n_positions) + d_obj = -np.inf + + while True: + # single BCD pass on all positions: + Z_init = dict.fromkeys(np.arange(n_positions), 0.0) + Z_init.update(dict(zip(active, Z.values()))) + Z, active_set, E_tmp, _ = _tf_mixed_norm_solver_bcd_( + M, + G, + Z_init, + active_set, + candidates, + alpha_space, + alpha_time, + lipschitz_constant, + phi, + phiT, + w_space=w_space, + w_time=w_time, + n_orient=n_orient, + maxit=1, + tol=tol, + perc=None, + ) + + E += E_tmp + + # multiple BCD pass on active positions: + active = np.where(active_set[::n_orient])[0] + Z_init = dict(zip(range(len(active)), [Z[idx] for idx in active])) + candidates_ = range(len(active)) + if w_space is not None: + w_space_as = w_space[active_set[::n_orient]] + else: + w_space_as = None + if w_time is not None: + w_time_as = w_time[active_set[::n_orient]] + else: + w_time_as = None + + Z, as_, E_tmp, converged = _tf_mixed_norm_solver_bcd_( + M, + G[:, active_set], + Z_init, + np.ones(len(active) * n_orient, dtype=bool), + candidates_, + alpha_space, + alpha_time, + lipschitz_constant[active_set[::n_orient]], + phi, + phiT, + w_space=w_space_as, + w_time=w_time_as, + n_orient=n_orient, + maxit=maxit, + tol=tol, + dgap_freq=dgap_freq, + perc=0.5, + ) + active = np.where(active_set[::n_orient])[0] + active_set[active_set] = as_.copy() + E += E_tmp + + converged = True + if converged: + Zd = np.vstack([Z[pos] for pos in range(len(Z)) if np.any(Z[pos])]) + gap, p_obj, d_obj, _ = dgap_l21l1( + M, + G, + Zd, + active_set, + alpha_space, + alpha_time, + phi, + phiT, + n_orient, + d_obj, + w_space, + w_time, + ) + logger.info( + "\ndgap %.2e :: p_obj %f :: d_obj %f :: n_active %d", + gap, + p_obj, + d_obj, + np.sum(active_set) / n_orient, + ) + if gap < tol: + logger.info("\nConvergence reached!\n") + break + + if active_set.sum(): + Z = np.vstack([Z[pos] for pos in range(len(Z)) if np.any(Z[pos])]) + X = phiT(Z) + else: + Z = np.zeros((0, phi.n_coefs.sum()), dtype=np.complex128) + X = np.zeros((0, n_times)) + + return X, Z, active_set, E, gap + + +@verbose +def tf_mixed_norm_solver( + M, + G, + alpha_space, + alpha_time, + wsize=64, + tstep=4, + n_orient=1, + maxit=200, + tol=1e-8, + active_set_size=None, + debias=True, + return_gap=False, + dgap_freq=10, + verbose=None, +): + """Solve TF L21+L1 inverse solver with BCD and active set approach. + + See :footcite:`GramfortEtAl2013b,GramfortEtAl2011,BekhtiEtAl2016`. + + Parameters + ---------- + M : array, shape (n_sensors, n_times) + The data. + G : array, shape (n_sensors, n_dipoles) + The gain matrix a.k.a. lead field. + alpha_space : float + The spatial regularization parameter. + alpha_time : float + The temporal regularization parameter. The higher it is the smoother + will be the estimated time series. + wsize: int or array-like + Length of the STFT window in samples (must be a multiple of 4). + If an array is passed, multiple TF dictionaries are used (each having + its own wsize and tstep) and each entry of wsize must be a multiple + of 4. + tstep: int or array-like + Step between successive windows in samples (must be a multiple of 2, + a divider of wsize and smaller than wsize/2) (default: wsize/2). + If an array is passed, multiple TF dictionaries are used (each having + its own wsize and tstep), and each entry of tstep must be a multiple + of 2 and divide the corresponding entry of wsize. + n_orient : int + The number of orientation (1 : fixed or 3 : free or loose). + maxit : int + The number of iterations. + tol : float + If absolute difference between estimates at 2 successive iterations + is lower than tol, the convergence is reached. + debias : bool + Debias source estimates. + return_gap : bool + Return final duality gap. + dgap_freq : int or np.inf + The duality gap is evaluated every dgap_freq iterations. + %(verbose)s + + Returns + ------- + X : array, shape (n_active, n_times) + The source estimates. + active_set : array + The mask of active sources. + E : list + The value of the objective function every dgap_freq iteration. If + log_objective is False or dgap_freq is np.inf, it will be empty. + gap : float + Final duality gap. Returned only if return_gap is True. + + References + ---------- + .. footbibliography:: + """ + n_sensors, n_times = M.shape + n_sensors, n_sources = G.shape + n_positions = n_sources // n_orient + + tstep = np.atleast_1d(tstep) + wsize = np.atleast_1d(wsize) + if len(tstep) != len(wsize): + raise ValueError( + "The same number of window sizes and steps must be " + f"passed. Got tstep = {tstep} and wsize = {wsize}" + ) + + n_steps = np.ceil(M.shape[1] / tstep.astype(float)).astype(int) + n_freqs = wsize // 2 + 1 + n_coefs = n_steps * n_freqs + phi = _Phi(wsize, tstep, n_coefs, n_times) + phiT = _PhiT(tstep, n_freqs, n_steps, n_times) + + if n_orient == 1: + lc = np.sum(G * G, axis=0) + else: + lc = np.empty(n_positions) + for j in range(n_positions): + G_tmp = G[:, (j * n_orient) : ((j + 1) * n_orient)] + lc[j] = np.linalg.norm(np.dot(G_tmp.T, G_tmp), ord=2) + + logger.info("Using block coordinate descent with active set approach") + X, Z, active_set, E, gap = _tf_mixed_norm_solver_bcd_active_set( + M, + G, + alpha_space, + alpha_time, + lc, + phi, + phiT, + Z_init=None, + n_orient=n_orient, + maxit=maxit, + tol=tol, + dgap_freq=dgap_freq, + ) + + if np.any(active_set) and debias: + bias = compute_bias(M, G[:, active_set], X, n_orient=n_orient) + X *= bias[:, np.newaxis] + + if return_gap: + return X, active_set, E, gap + else: + return X, active_set, E + + +def iterative_tf_mixed_norm_solver( + M, + G, + alpha_space, + alpha_time, + n_tfmxne_iter, + wsize=64, + tstep=4, + maxit=3000, + tol=1e-8, + debias=True, + n_orient=1, + dgap_freq=10, + verbose=None, +): + """Solve TF L0.5/L1 + L0.5 inverse problem with BCD + active set approach. + + Parameters + ---------- + M: array, shape (n_sensors, n_times) + The data. + G: array, shape (n_sensors, n_dipoles) + The gain matrix a.k.a. lead field. + alpha_space: float + The spatial regularization parameter. The higher it is the less there + will be active sources. + alpha_time : float + The temporal regularization parameter. The higher it is the smoother + will be the estimated time series. 0 means no temporal regularization, + a.k.a. irMxNE. + n_tfmxne_iter : int + Number of TF-MxNE iterations. If > 1, iterative reweighting is applied. + wsize : int or array-like + Length of the STFT window in samples (must be a multiple of 4). + If an array is passed, multiple TF dictionaries are used (each having + its own wsize and tstep) and each entry of wsize must be a multiple + of 4. + tstep : int or array-like + Step between successive windows in samples (must be a multiple of 2, + a divider of wsize and smaller than wsize/2) (default: wsize/2). + If an array is passed, multiple TF dictionaries are used (each having + its own wsize and tstep), and each entry of tstep must be a multiple + of 2 and divide the corresponding entry of wsize. + maxit : int + The maximum number of iterations for each TF-MxNE problem. + tol : float + If absolute difference between estimates at 2 successive iterations + is lower than tol, the convergence is reached. Also used as criterion + on duality gap for each TF-MxNE problem. + debias : bool + Debias source estimates. + n_orient : int + The number of orientation (1 : fixed or 3 : free or loose). + dgap_freq : int or np.inf + The duality gap is evaluated every dgap_freq iterations. + %(verbose)s + + Returns + ------- + X : array, shape (n_active, n_times) + The source estimates. + active_set : array + The mask of active sources. + E : list + The value of the objective function over iterations. + """ + n_sensors, n_times = M.shape + n_sources = G.shape[1] + n_positions = n_sources // n_orient + + tstep = np.atleast_1d(tstep) + wsize = np.atleast_1d(wsize) + if len(tstep) != len(wsize): + raise ValueError( + "The same number of window sizes and steps must be " + f"passed. Got tstep = {tstep} and wsize = {wsize}" + ) + + n_steps = np.ceil(n_times / tstep.astype(float)).astype(int) + n_freqs = wsize // 2 + 1 + n_coefs = n_steps * n_freqs + phi = _Phi(wsize, tstep, n_coefs, n_times) + phiT = _PhiT(tstep, n_freqs, n_steps, n_times) + + if n_orient == 1: + lc = np.sum(G * G, axis=0) + else: + lc = np.empty(n_positions) + for j in range(n_positions): + G_tmp = G[:, (j * n_orient) : ((j + 1) * n_orient)] + lc[j] = np.linalg.norm(np.dot(G_tmp.T, G_tmp), ord=2) + + # space and time penalties, and inverse of their derivatives: + def g_space(Z): + return np.sqrt(np.sqrt(phi.norm(Z, ord=2).reshape(-1, n_orient).sum(axis=1))) + + def g_space_prime_inv(Z): + return 2.0 * g_space(Z) + + def g_time(Z): + return np.sqrt( + np.sqrt( + np.sum((np.abs(Z) ** 2.0).reshape((n_orient, -1), order="F"), axis=0) + ).reshape((-1, Z.shape[1]), order="F") + ) + + def g_time_prime_inv(Z): + return 2.0 * g_time(Z) + + E = list() + + active_set = np.ones(n_sources, dtype=bool) + Z = np.zeros((n_sources, phi.n_coefs.sum()), dtype=np.complex128) + + for k in range(n_tfmxne_iter): + active_set_0 = active_set.copy() + Z0 = Z.copy() + + if k == 0: + w_space = None + w_time = None + else: + w_space = 1.0 / g_space_prime_inv(Z) + w_time = g_time_prime_inv(Z) + w_time[w_time == 0.0] = -1.0 + w_time = 1.0 / w_time + w_time[w_time < 0.0] = 0.0 + + X, Z, active_set_, _, _ = _tf_mixed_norm_solver_bcd_active_set( + M, + G[:, active_set], + alpha_space, + alpha_time, + lc[active_set[::n_orient]], + phi, + phiT, + Z_init=Z, + w_space=w_space, + w_time=w_time, + n_orient=n_orient, + maxit=maxit, + tol=tol, + dgap_freq=dgap_freq, + ) + + active_set[active_set] = active_set_ + + if active_set.sum() > 0: + l21_penalty = np.sum(g_space(Z.copy())) + l1_penalty = phi.norm(g_time(Z.copy()), ord=1).sum() + + p_obj = ( + 0.5 * np.linalg.norm(M - np.dot(G[:, active_set], X), "fro") ** 2.0 + + alpha_space * l21_penalty + + alpha_time * l1_penalty + ) + E.append(p_obj) + + logger.info( + "Iteration %d: active set size=%d, E=%f", + k + 1, + active_set.sum() / n_orient, + p_obj, + ) + + # Check convergence + if np.array_equal(active_set, active_set_0): + max_diff = np.amax(np.abs(Z - Z0)) + if max_diff < tol: + logger.info("Convergence reached after %d reweightings!", k) + break + else: + p_obj = 0.5 * np.linalg.norm(M) ** 2.0 + E.append(p_obj) + logger.info( + "Iteration %d: as_size=%d, E=%f", + k + 1, + active_set.sum() / n_orient, + p_obj, + ) + break + + if debias: + if active_set.sum() > 0: + bias = compute_bias(M, G[:, active_set], X, n_orient=n_orient) + X *= bias[:, np.newaxis] + + return X, active_set, E diff --git a/mne-python/source/mne/inverse_sparse/tests/__init__.py b/mne-python/source/mne/inverse_sparse/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/inverse_sparse/tests/test_gamma_map.py b/mne-python/source/mne/inverse_sparse/tests/test_gamma_map.py new file mode 100644 index 0000000000000000000000000000000000000000..db4ac5c92604ccc1a88c772bfc2862d3e9cb17ea --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/tests/test_gamma_map.py @@ -0,0 +1,219 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_almost_equal + +import mne +from mne import ( + VectorSourceEstimate, + convert_forward_solution, + pick_types_forward, + read_cov, + read_evokeds, + read_forward_solution, +) +from mne.cov import regularize +from mne.datasets import testing +from mne.dipole import Dipole +from mne.inverse_sparse import gamma_map +from mne.inverse_sparse.mxne_inverse import make_stc_from_dipoles +from mne.minimum_norm.tests.test_inverse import assert_stc_res, assert_var_exp_log +from mne.utils import assert_stcs_equal, catch_logging + +data_path = testing.data_path(download=False) +fname_evoked = data_path / "MEG" / "sample" / "sample_audvis-ave.fif" +fname_cov = data_path / "MEG" / "sample" / "sample_audvis-cov.fif" +fname_fwd = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-6-fwd.fif" +subjects_dir = data_path / "subjects" + + +def _check_stc( + stc, evoked, idx, hemi, fwd, dist_limit=0.0, ratio=50.0, res=None, atol=1e-20 +): + """Check correctness.""" + assert_array_almost_equal(stc.times, evoked.times, 5) + stc_orig = stc + if isinstance(stc, VectorSourceEstimate): + assert stc.data.any(1).any(1).all() # all dipoles should have some + stc = stc.magnitude() + amps = np.sum(stc.data**2, axis=1) + order = np.argsort(amps)[::-1] + amps = amps[order] + verts = np.concatenate(stc.vertices)[order] + hemi_idx = int(order[0] >= len(stc.vertices[1])) + hemis = ["lh", "rh"] + assert hemis[hemi_idx] == hemi + dist = ( + np.linalg.norm(np.diff(fwd["src"][hemi_idx]["rr"][[idx, verts[0]]], axis=0)[0]) + * 1000.0 + ) + assert dist <= dist_limit + assert amps[0] > ratio * amps[1] + if res is not None: + assert_stc_res(evoked, stc_orig, fwd, res, atol=atol) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_gamma_map_standard(): + """Test Gamma MAP inverse.""" + forward = read_forward_solution(fname_fwd) + forward = convert_forward_solution(forward, surf_ori=True) + + forward = pick_types_forward(forward, meg=False, eeg=True) + evoked = read_evokeds(fname_evoked, condition=0, baseline=(None, 0), proj=False) + evoked.resample(50, npad=100) + evoked.crop(tmin=0.1, tmax=0.14) # crop to window around peak + + cov = read_cov(fname_cov) + cov = regularize(cov, evoked.info) + + alpha = 0.5 + with catch_logging() as log: + stc = gamma_map( + evoked, + forward, + cov, + alpha, + tol=1e-4, + xyz_same_gamma=True, + update_mode=1, + verbose=True, + ) + _check_stc(stc, evoked, 68477, "lh", fwd=forward) + assert_var_exp_log(log.getvalue(), 20, 22) + + with catch_logging() as log: + stc_vec, res = gamma_map( + evoked, + forward, + cov, + alpha, + tol=1e-4, + xyz_same_gamma=True, + update_mode=1, + pick_ori="vector", + return_residual=True, + verbose=True, + ) + assert_var_exp_log(log.getvalue(), 20, 22) + assert_stcs_equal(stc_vec.magnitude(), stc) + _check_stc(stc_vec, evoked, 68477, "lh", fwd=forward, res=res) + + stc, res = gamma_map( + evoked, + forward, + cov, + alpha, + tol=1e-4, + xyz_same_gamma=False, + update_mode=1, + pick_ori="vector", + return_residual=True, + ) + _check_stc( + stc, evoked, 82010, "lh", fwd=forward, dist_limit=6.0, ratio=2.0, res=res + ) + + with catch_logging() as log: + dips = gamma_map( + evoked, + forward, + cov, + alpha, + tol=1e-4, + xyz_same_gamma=False, + update_mode=1, + return_as_dipoles=True, + verbose=True, + ) + exp_var = assert_var_exp_log(log.getvalue(), 58, 60) + dip_exp_var = np.mean(sum(dip.gof for dip in dips)) + assert_allclose(exp_var, dip_exp_var, atol=10) # not really equiv, close + assert isinstance(dips[0], Dipole) + stc_dip = make_stc_from_dipoles(dips, forward["src"]) + assert_stcs_equal(stc.magnitude(), stc_dip) + + # force fixed orientation + stc, res = gamma_map( + evoked, + forward, + cov, + alpha, + tol=1e-4, + xyz_same_gamma=False, + update_mode=2, + loose=0, + return_residual=True, + ) + _check_stc(stc, evoked, 85739, "lh", fwd=forward, ratio=20.0, res=res) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_gamma_map_vol_sphere(): + """Gamma MAP with a sphere forward and volumic source space.""" + evoked = read_evokeds(fname_evoked, condition=0, baseline=(None, 0), proj=False) + evoked.resample(50, npad=100) + evoked.crop(tmin=0.1, tmax=0.16) # crop to window around peak + + cov = read_cov(fname_cov) + cov = regularize(cov, evoked.info, rank=dict(eeg=58)) + + info = evoked.info + sphere = mne.make_sphere_model(r0=(0.0, 0.0, 0.0), head_radius=0.080) + src = mne.setup_volume_source_space( + subject=None, + pos=30.0, + mri=None, + sphere=(0.0, 0.0, 0.0, 0.08), + bem=None, + mindist=5.0, + exclude=2.0, + sphere_units="m", + ) + fwd = mne.make_forward_solution( + info, trans=None, src=src, bem=sphere, eeg=False, meg=True + ) + + alpha = 0.5 + stc = gamma_map( + evoked, + fwd, + cov, + alpha, + tol=1e-4, + xyz_same_gamma=False, + update_mode=2, + return_residual=False, + ) + assert_array_almost_equal(stc.times, evoked.times, 5) + + # Computing inverse with restricted orientations should also work, since + # we have a discrete source space. + stc = gamma_map(evoked, fwd, cov, alpha, loose=0.2, return_residual=False) + assert_array_almost_equal(stc.times, evoked.times, 5) + + # Compare orientation obtained using fit_dipole and gamma_map + # for a simulated evoked containing a single dipole + stc = mne.VolSourceEstimate( + 50e-9 * np.random.RandomState(42).randn(1, 4), + vertices=[stc.vertices[0][:1]], + tmin=stc.tmin, + tstep=stc.tstep, + ) + evoked_dip = mne.simulation.simulate_evoked( + fwd, stc, info, cov, nave=1e9, use_cps=True + ) + + dip_gmap = gamma_map(evoked_dip, fwd, cov, 0.1, return_as_dipoles=True) + + amp_max = [np.max(d.amplitude) for d in dip_gmap] + dip_gmap = dip_gmap[np.argmax(amp_max)] + assert dip_gmap[0].pos[0] in src[0]["rr"][stc.vertices[0]] + + dip_fit = mne.fit_dipole(evoked_dip, cov, sphere)[0] + assert np.abs(np.dot(dip_fit.ori[0], dip_gmap.ori[0])) > 0.99 diff --git a/mne-python/source/mne/inverse_sparse/tests/test_mxne_debiasing.py b/mne-python/source/mne/inverse_sparse/tests/test_mxne_debiasing.py new file mode 100644 index 0000000000000000000000000000000000000000..9c32f136eaf36c16957c2e94d44cd18b3d6f7115 --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/tests/test_mxne_debiasing.py @@ -0,0 +1,21 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +from numpy.testing import assert_almost_equal + +from mne.inverse_sparse.mxne_debiasing import compute_bias + + +def test_compute_debiasing(): + """Test source amplitude debiasing.""" + rng = np.random.RandomState(42) + G = rng.randn(10, 4) + X = rng.randn(4, 20) + debias_true = np.arange(1, 5, dtype=np.float64) + M = np.dot(G, X * debias_true[:, np.newaxis]) + debias = compute_bias(M, G, X, max_iter=10000, n_orient=1, tol=1e-7) + assert_almost_equal(debias, debias_true, decimal=5) + debias = compute_bias(M, G, X, max_iter=10000, n_orient=2, tol=1e-5) + assert_almost_equal(debias, [1.8, 1.8, 3.72, 3.72], decimal=2) diff --git a/mne-python/source/mne/inverse_sparse/tests/test_mxne_inverse.py b/mne-python/source/mne/inverse_sparse/tests/test_mxne_inverse.py new file mode 100644 index 0000000000000000000000000000000000000000..4a3a15df0f46bd631af2312a4874a1cb2d6e4c80 --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/tests/test_mxne_inverse.py @@ -0,0 +1,641 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_array_less, +) + +import mne +from mne import convert_forward_solution, read_cov, read_evokeds, read_forward_solution +from mne.datasets import testing +from mne.dipole import Dipole +from mne.inverse_sparse import mixed_norm, tf_mixed_norm +from mne.inverse_sparse.mxne_inverse import ( + _compute_mxne_sure, + _split_gof, + make_stc_from_dipoles, +) +from mne.inverse_sparse.mxne_optim import norm_l2inf +from mne.label import read_label +from mne.minimum_norm import apply_inverse, make_inverse_operator +from mne.minimum_norm.tests.test_inverse import assert_stc_res, assert_var_exp_log +from mne.simulation import simulate_evoked, simulate_sparse_stc +from mne.source_estimate import VolSourceEstimate +from mne.utils import _record_warnings, assert_stcs_equal, catch_logging + +data_path = testing.data_path(download=False) +# NOTE: These use the ave and cov from sample dataset (no _trunc) +fname_data = data_path / "MEG" / "sample" / "sample_audvis-ave.fif" +fname_cov = data_path / "MEG" / "sample" / "sample_audvis-cov.fif" +fname_raw = data_path / "MEG" / "sample" / "sample_audvis_trunc_raw.fif" +fname_fwd = data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-6-fwd.fif" +label = "Aud-rh" +fname_label = data_path / "MEG" / "sample" / "labels" / f"{label}.label" + + +@pytest.fixture(scope="module", params=[testing._pytest_param]) +def forward(): + """Get a forward solution.""" + # module scope it for speed (but don't overwrite in use!) + return read_forward_solution(fname_fwd) + + +@testing.requires_testing_data +@pytest.mark.timeout(150) # ~30 s on Travis Linux +@pytest.mark.slowtest +def test_mxne_inverse_standard(forward): + """Test (TF-)MxNE inverse computation.""" + # Read noise covariance matrix + cov = read_cov(fname_cov) + + # Handling average file + loose = 0.0 + depth = 0.9 + + evoked = read_evokeds(fname_data, condition=0, baseline=(None, 0)) + evoked.crop(tmin=-0.05, tmax=0.2) + + evoked_l21 = evoked.copy() + evoked_l21.crop(tmin=0.081, tmax=0.1) + label = read_label(fname_label) + assert label.hemi == "rh" + + forward = convert_forward_solution(forward, surf_ori=True) + + # Reduce source space to make test computation faster + inverse_operator = make_inverse_operator( + evoked_l21.info, + forward, + cov, + loose=loose, + depth=depth, + fixed=True, + use_cps=True, + ) + stc_dspm = apply_inverse( + evoked_l21, inverse_operator, lambda2=1.0 / 9.0, method="dSPM" + ) + stc_dspm.data[np.abs(stc_dspm.data) < 12] = 0.0 + stc_dspm.data[np.abs(stc_dspm.data) >= 12] = 1.0 + weights_min = 0.5 + + # MxNE tests + alpha = 70 # spatial regularization parameter + + with _record_warnings(): # CD + stc_cd = mixed_norm( + evoked_l21, + forward, + cov, + alpha, + loose=loose, + depth=depth, + maxit=300, + tol=1e-8, + active_set_size=10, + weights=stc_dspm, + weights_min=weights_min, + solver="cd", + ) + stc_bcd = mixed_norm( + evoked_l21, + forward, + cov, + alpha, + loose=loose, + depth=depth, + maxit=300, + tol=1e-8, + active_set_size=10, + weights=stc_dspm, + weights_min=weights_min, + solver="bcd", + ) + assert_array_almost_equal(stc_cd.times, evoked_l21.times, 5) + assert_array_almost_equal(stc_bcd.times, evoked_l21.times, 5) + assert_allclose(stc_cd.data, stc_bcd.data, rtol=1e-3, atol=0.0) + assert stc_cd.vertices[1][0] in label.vertices + assert stc_bcd.vertices[1][0] in label.vertices + + # vector + with _record_warnings(): # no convergence + stc = mixed_norm(evoked_l21, forward, cov, alpha, loose=1, maxit=2) + with _record_warnings(): # no convergence + stc_vec = mixed_norm( + evoked_l21, forward, cov, alpha, loose=1, maxit=2, pick_ori="vector" + ) + assert_stcs_equal(stc_vec.magnitude(), stc) + with _record_warnings(), pytest.raises(ValueError, match="pick_ori="): + mixed_norm(evoked_l21, forward, cov, alpha, loose=0, maxit=2, pick_ori="vector") + + with _record_warnings(), catch_logging() as log: # CD + dips = mixed_norm( + evoked_l21, + forward, + cov, + alpha, + loose=loose, + depth=depth, + maxit=300, + tol=1e-8, + active_set_size=10, + weights=stc_dspm, + weights_min=weights_min, + solver="cd", + return_as_dipoles=True, + verbose=True, + ) + stc_dip = make_stc_from_dipoles(dips, forward["src"]) + assert isinstance(dips[0], Dipole) + assert stc_dip.subject == "sample" + assert_stcs_equal(stc_cd, stc_dip) + assert_var_exp_log(log.getvalue(), 51, 53) # 51.8 + + # Single time point things should match + with _record_warnings(), catch_logging() as log: + dips = mixed_norm( + evoked_l21.copy().crop(0.081, 0.081), + forward, + cov, + alpha, + loose=loose, + depth=depth, + maxit=300, + tol=1e-8, + active_set_size=10, + weights=stc_dspm, + weights_min=weights_min, + solver="cd", + return_as_dipoles=True, + verbose=True, + ) + assert_var_exp_log(log.getvalue(), 37.8, 38.0) # 37.9 + gof = sum(dip.gof[0] for dip in dips) # these are now partial exp vars + assert_allclose(gof, 37.9, atol=0.1) + + with _record_warnings(), catch_logging() as log: + stc, res = mixed_norm( + evoked_l21, + forward, + cov, + alpha, + loose=loose, + depth=depth, + maxit=300, + tol=1e-8, + weights=stc_dspm, # gh-6382 + active_set_size=10, + return_residual=True, + solver="cd", + verbose=True, + ) + assert_array_almost_equal(stc.times, evoked_l21.times, 5) + assert stc.vertices[1][0] in label.vertices + assert_var_exp_log(log.getvalue(), 51, 53) # 51.8 + assert stc.data.min() < -1e-9 # signed + assert_stc_res(evoked_l21, stc, forward, res) + + # irMxNE tests + with _record_warnings(), catch_logging() as log: # CD + stc, residual = mixed_norm( + evoked_l21, + forward, + cov, + alpha, + n_mxne_iter=5, + loose=0.0001, + depth=depth, + maxit=300, + tol=1e-8, + active_set_size=10, + solver="cd", + return_residual=True, + pick_ori="vector", + verbose=True, + ) + assert_array_almost_equal(stc.times, evoked_l21.times, 5) + assert stc.vertices[1][0] in label.vertices + assert stc.vertices == [[63152], [79017]] + assert_var_exp_log(log.getvalue(), 51, 53) # 51.8 + assert_stc_res(evoked_l21, stc, forward, residual) + + # Do with TF-MxNE for test memory savings + alpha = 60.0 # overall regularization parameter + l1_ratio = 0.01 # temporal regularization proportion + + stc, _ = tf_mixed_norm( + evoked, + forward, + cov, + loose=loose, + depth=depth, + maxit=100, + tol=1e-4, + tstep=4, + wsize=16, + window=0.1, + weights=stc_dspm, + weights_min=weights_min, + return_residual=True, + alpha=alpha, + l1_ratio=l1_ratio, + ) + assert_array_almost_equal(stc.times, evoked.times, 5) + assert stc.vertices[1][0] in label.vertices + + # vector + stc_nrm = tf_mixed_norm( + evoked, + forward, + cov, + loose=1, + depth=depth, + maxit=2, + tol=1e-4, + tstep=4, + wsize=16, + window=0.1, + weights=stc_dspm, + weights_min=weights_min, + alpha=alpha, + l1_ratio=l1_ratio, + ) + stc_vec, residual = tf_mixed_norm( + evoked, + forward, + cov, + loose=1, + depth=depth, + maxit=2, + tol=1e-4, + tstep=4, + wsize=16, + window=0.1, + weights=stc_dspm, + weights_min=weights_min, + alpha=alpha, + l1_ratio=l1_ratio, + pick_ori="vector", + return_residual=True, + ) + assert_stcs_equal(stc_vec.magnitude(), stc_nrm) + + pytest.raises( + ValueError, tf_mixed_norm, evoked, forward, cov, alpha=101, l1_ratio=0.03 + ) + pytest.raises( + ValueError, tf_mixed_norm, evoked, forward, cov, alpha=50.0, l1_ratio=1.01 + ) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_mxne_vol_sphere(): + """Test (TF-)MxNE with a sphere forward and volumic source space.""" + evoked = read_evokeds(fname_data, condition=0, baseline=(None, 0)) + evoked.crop(tmin=-0.05, tmax=0.2) + cov = read_cov(fname_cov) + + evoked_l21 = evoked.copy() + evoked_l21.crop(tmin=0.081, tmax=0.1) + + info = evoked.info + sphere = mne.make_sphere_model(r0=(0.0, 0.0, 0.0), head_radius=0.09) + src = mne.setup_volume_source_space( + subject=None, + pos=15.0, + mri=None, + sphere=(0.0, 0.0, 0.0, 0.08), + bem=None, + mindist=5.0, + exclude=2.0, + sphere_units="m", + ) + fwd = mne.make_forward_solution( + info, trans=None, src=src, bem=sphere, eeg=False, meg=True + ) + + alpha = 80.0 + + # Computing inverse with restricted orientations should also work, since + # we have a discrete source space. + stc = mixed_norm( + evoked_l21, + fwd, + cov, + alpha, + loose=0.2, + return_residual=False, + maxit=3, + tol=1e-8, + active_set_size=10, + ) + assert_array_almost_equal(stc.times, evoked_l21.times, 5) + + # irMxNE tests + with catch_logging() as log: + stc = mixed_norm( + evoked_l21, + fwd, + cov, + alpha, + n_mxne_iter=1, + maxit=30, + tol=1e-8, + active_set_size=10, + verbose=True, + ) + assert isinstance(stc, VolSourceEstimate) + assert_array_almost_equal(stc.times, evoked_l21.times, 5) + assert_var_exp_log(log.getvalue(), 9, 11) # 10.2 + + # Compare orientation obtained using fit_dipole and gamma_map + # for a simulated evoked containing a single dipole + stc = mne.VolSourceEstimate( + 50e-9 * np.random.RandomState(42).randn(1, 4), + vertices=[stc.vertices[0][:1]], + tmin=stc.tmin, + tstep=stc.tstep, + ) + evoked_dip = mne.simulation.simulate_evoked( + fwd, + stc, + info, + cov, + nave=1e9, + use_cps=True, + random_state=0, + ) + + dip_mxne = mixed_norm( + evoked_dip, + fwd, + cov, + alpha=80, + n_mxne_iter=1, + maxit=30, + tol=1e-8, + active_set_size=10, + return_as_dipoles=True, + ) + + amp_max = [np.max(d.amplitude) for d in dip_mxne] + dip_mxne = dip_mxne[np.argmax(amp_max)] + assert dip_mxne.pos[0] in src[0]["rr"][stc.vertices[0]] + + dip_fit = mne.fit_dipole(evoked_dip, cov, sphere)[0] + assert np.abs(np.dot(dip_fit.ori[0], dip_mxne.ori[0])) > 0.99 + dist = 1000 * np.linalg.norm(dip_fit.pos[0] - dip_mxne.pos[0]) + assert dist < 4.0 # within 4 mm + + # Do with TF-MxNE for test memory savings + alpha = 60.0 # overall regularization parameter + l1_ratio = 0.01 # temporal regularization proportion + + stc, _ = tf_mixed_norm( + evoked, + fwd, + cov, + maxit=3, + tol=1e-4, + tstep=16, + wsize=32, + window=0.1, + alpha=alpha, + l1_ratio=l1_ratio, + return_residual=True, + ) + assert isinstance(stc, VolSourceEstimate) + assert_array_almost_equal(stc.times, evoked.times, 5) + + +@pytest.mark.parametrize("mod", (None, "mult", "augment", "sign", "zero", "less")) +def test_split_gof_basic(mod): + """Test splitting the goodness of fit.""" + # first a trivial case + gain = np.array([[0.0, 1.0, 1.0], [1.0, 1.0, 0.0]]).T + M = np.ones((3, 1)) + X = np.ones((2, 1)) + M_est = gain @ X + assert_allclose(M_est, np.array([[1.0, 2.0, 1.0]]).T) # a reasonable estimate + if mod == "mult": + gain *= [1.0, -0.5] + X[1] *= -2 + elif mod == "augment": + gain = np.concatenate((gain, np.zeros((3, 1))), axis=1) + X = np.concatenate((X, [[1.0]])) + elif mod == "sign": + gain[1] *= -1 + M[1] *= -1 + M_est[1] *= -1 + elif mod in ("zero", "less"): + gain = np.array([[1, 1.0, 1.0], [1.0, 1.0, 1.0]]).T + if mod == "zero": + X[:, 0] = [1.0, 0.0] + else: + X[:, 0] = [1.0, 0.5] + M_est = gain @ X + else: + assert mod is None + res = M - M_est + gof = 100 * (1.0 - (res * res).sum() / (M * M).sum()) + gof_split = _split_gof(M, X, gain) + assert_allclose(gof_split.sum(), gof) + want = gof_split[[0, 0]] + if mod == "augment": + want = np.concatenate((want, [[0]])) + if mod in ("mult", "less"): + assert_array_less(gof_split[1], gof_split[0]) + elif mod == "zero": + assert_allclose(gof_split[0], gof_split.sum(0)) + assert_allclose(gof_split[1], 0.0, atol=1e-6) + else: + assert_allclose(gof_split, want, atol=1e-12) + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "idx, weights", + [ + # empirically determined approximately orthogonal columns: 0, 15157, 19448 + ([0], [1]), + ([0, 15157], [1, 1]), + ([0, 15157], [1, 3]), + ([0, 15157], [5, -1]), + ([0, 15157, 19448], [1, 1, 1]), + ([0, 15157, 19448], [1e-2, 1, 5]), + ], +) +def test_split_gof_meg(forward, idx, weights): + """Test GOF splitting on MEG data.""" + gain = forward["sol"]["data"][:, idx] + # close to orthogonal + norms = np.linalg.norm(gain, axis=0) + triu = np.triu_indices(len(idx), 1) + prods = np.abs(np.dot(gain.T, gain) / np.outer(norms, norms))[triu] + assert_array_less(prods, 5e-3) # approximately orthogonal + # first, split across time (one dipole per time point) + M = gain * weights + gof_split = _split_gof(M, np.diag(weights), gain) + assert_allclose(gof_split.sum(0), 100.0, atol=1e-5) # all sum to 100 + assert_allclose(gof_split, 100 * np.eye(len(weights)), atol=1) # loc + # next, summed to a single time point (all dipoles active at one time pt) + weights = np.array(weights)[:, np.newaxis] + x = gain @ weights + assert x.shape == (gain.shape[0], 1) + gof_split = _split_gof(x, weights, gain) + want = (norms * weights.T).T ** 2 + want = 100 * want / want.sum() + assert_allclose(gof_split, want, atol=1e-3, rtol=1e-2) + assert_allclose(gof_split.sum(), 100, rtol=1e-5) + + +@pytest.mark.parametrize( + "n_sensors, n_dipoles, n_times", + [ + (10, 15, 7), + (20, 60, 20), + ], +) +@pytest.mark.parametrize("nnz", [2, 4]) +@pytest.mark.parametrize("corr", [0.75]) +@pytest.mark.parametrize("n_orient", [1, 3]) +def test_mxne_inverse_sure_synthetic( + n_sensors, n_dipoles, n_times, nnz, corr, n_orient, snr=4 +): + """Tests SURE criterion for automatic alpha selection on synthetic data.""" + rng = np.random.RandomState(0) + sigma = np.sqrt(1 - corr**2) + U = rng.randn(n_sensors) + # generate gain matrix + G = np.empty([n_sensors, n_dipoles], order="F") + G[:, :n_orient] = np.expand_dims(U, axis=-1) + n_dip_per_pos = n_dipoles // n_orient + for j in range(1, n_dip_per_pos): + U *= corr + U += sigma * rng.randn(n_sensors) + G[:, j * n_orient : (j + 1) * n_orient] = np.expand_dims(U, axis=-1) + # generate coefficient matrix + support = rng.choice(n_dip_per_pos, nnz, replace=False) + X = np.zeros((n_dipoles, n_times)) + for k in support: + X[k * n_orient : (k + 1) * n_orient, :] = rng.normal(size=(n_orient, n_times)) + # generate measurement matrix + M = G @ X + noise = rng.randn(n_sensors, n_times) + sigma = 1 / np.linalg.norm(noise) * np.linalg.norm(M) / snr + M += sigma * noise + # inverse modeling with sure + alpha_max = norm_l2inf(np.dot(G.T, M), n_orient, copy=False) + alpha_grid = np.geomspace(alpha_max, alpha_max / 10, num=15) + _, active_set, _ = _compute_mxne_sure( + M, + G, + alpha_grid, + sigma=sigma, + n_mxne_iter=5, + maxit=3000, + tol=1e-4, + n_orient=n_orient, + active_set_size=10, + debias=True, + solver="auto", + dgap_freq=10, + random_state=0, + verbose=False, + ) + assert np.count_nonzero(active_set, axis=-1) == n_orient * nnz + + +@pytest.mark.slowtest # slow on Azure +@testing.requires_testing_data +def test_mxne_inverse_sure_meg(): + """Tests SURE criterion for automatic alpha selection on MEG data.""" + + def data_fun(times): + data = np.zeros(times.shape) + data[times >= 0] = 50e-9 + return data + + n_dipoles = 2 + raw = mne.io.read_raw_fif(fname_raw).pick_types("grad", exclude="bads") + raw.del_proj() + info = raw.info + del raw + noise_cov = mne.make_ad_hoc_cov(info) + label_names = ["Aud-lh", "Aud-rh"] + labels = [ + mne.read_label(data_path / "MEG" / "sample" / "labels" / f"{ln}.label") + for ln in label_names + ] + fname_fwd = ( + data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" + ) + forward = mne.read_forward_solution(fname_fwd) + forward = mne.pick_channels_forward(forward, info["ch_names"]) + times = np.arange(100, dtype=np.float64) / info["sfreq"] - 0.1 + stc = simulate_sparse_stc( + forward["src"], + n_dipoles=n_dipoles, + times=times, + random_state=1, + labels=labels, + data_fun=data_fun, + ) + assert len(stc.vertices) == 2 + assert_array_equal(stc.vertices[0], [89259]) + assert_array_equal(stc.vertices[1], [70279]) + nave = 30 + evoked = simulate_evoked( + forward, + stc, + info, + noise_cov, + nave=nave, + use_cps=False, + iir_filter=None, + random_state=0, + ) + evoked = evoked.crop(tmin=0, tmax=10e-3) + stc_ = mixed_norm( + evoked, forward, noise_cov, loose=0.9, n_mxne_iter=5, depth=0.9, random_state=1 + ) + assert len(stc_.vertices) == len(stc.vertices) == 2 + for si in range(len(stc_.vertices)): + assert_array_equal(stc_.vertices[si], stc.vertices[si], err_msg=f"{si=}") + + +@pytest.mark.slowtest # slow on Azure +@testing.requires_testing_data +def test_mxne_inverse_empty(): + """Tests solver with too high alpha.""" + evoked = read_evokeds(fname_data, condition=0, baseline=(None, 0)) + evoked.pick("grad", exclude="bads") + fname_fwd = ( + data_path / "MEG" / "sample" / "sample_audvis_trunc-meg-eeg-oct-4-fwd.fif" + ) + forward = mne.read_forward_solution(fname_fwd) + forward = mne.pick_types_forward( + forward, meg="grad", eeg=False, exclude=evoked.info["bads"] + ) + cov = read_cov(fname_cov) + with pytest.warns(RuntimeWarning, match="too big"): + stc, residual = mixed_norm( + evoked, + forward, + cov, + n_mxne_iter=3, + alpha=99, + return_residual=True, + random_state=0, + ) + assert stc.data.size == 0 + assert stc.vertices[0].size == 0 + assert stc.vertices[1].size == 0 + assert_allclose(evoked.data, residual.data) diff --git a/mne-python/source/mne/inverse_sparse/tests/test_mxne_optim.py b/mne-python/source/mne/inverse_sparse/tests/test_mxne_optim.py new file mode 100644 index 0000000000000000000000000000000000000000..464fe274defa0ab55a3a8937f7e1c3ce698d601c --- /dev/null +++ b/mne-python/source/mne/inverse_sparse/tests/test_mxne_optim.py @@ -0,0 +1,516 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_array_less, +) + +from mne.inverse_sparse.mxne_optim import ( + _Phi, + _PhiT, + dgap_l21l1, + iterative_mixed_norm_solver, + iterative_tf_mixed_norm_solver, + mixed_norm_solver, + norm_epsilon, + norm_epsilon_inf, + tf_mixed_norm_solver, +) +from mne.time_frequency._stft import stft_norm2 +from mne.utils import _record_warnings, catch_logging + + +def _generate_tf_data(): + n, p, t = 30, 40, 64 + rng = np.random.RandomState(0) + G = rng.randn(n, p) + G /= np.std(G, axis=0)[None, :] + X = np.zeros((p, t)) + active_set = [0, 4] + times = np.linspace(0, 2 * np.pi, t) + X[0] = np.sin(times) + X[4] = -2 * np.sin(4 * times) + X[4, times <= np.pi / 2] = 0 + X[4, times >= np.pi] = 0 + M = np.dot(G, X) + M += 1 * rng.randn(*M.shape) + return M, G, active_set + + +def test_l21_mxne(): + """Test convergence of MxNE solver.""" + n, p, t, alpha = 30, 40, 20, 1.0 + rng = np.random.RandomState(0) + G = rng.randn(n, p) + G /= np.std(G, axis=0)[None, :] + X = np.zeros((p, t)) + X[0] = 3 + X[4] = -2 + M = np.dot(G, X) + + args = (M, G, alpha, 1000, 1e-8) + with _record_warnings(): # CD + X_hat_cd, active_set, _, gap_cd = mixed_norm_solver( + *args, active_set_size=None, debias=True, solver="cd", return_gap=True + ) + assert_array_less(gap_cd, 1e-8) + assert_array_equal(np.where(active_set)[0], [0, 4]) + with _record_warnings(): # CD + X_hat_bcd, active_set, E, gap_bcd = mixed_norm_solver( + M, + G, + alpha, + maxit=1000, + tol=1e-8, + active_set_size=None, + debias=True, + solver="bcd", + return_gap=True, + ) + assert_array_less(gap_bcd, 9.6e-9) + assert_array_equal(np.where(active_set)[0], [0, 4]) + assert_allclose(X_hat_bcd, X_hat_cd, rtol=1e-2) + + with _record_warnings(): # CD + X_hat_cd, active_set, _ = mixed_norm_solver( + *args, active_set_size=2, debias=True, solver="cd" + ) + assert_array_equal(np.where(active_set)[0], [0, 4]) + with _record_warnings(): # CD + X_hat_bcd, active_set, _ = mixed_norm_solver( + *args, active_set_size=2, debias=True, solver="bcd" + ) + assert_array_equal(np.where(active_set)[0], [0, 4]) + assert_allclose(X_hat_bcd, X_hat_cd, rtol=1e-2) + + with _record_warnings(): # CD + X_hat_bcd, active_set, _ = mixed_norm_solver( + *args, active_set_size=2, debias=True, n_orient=2, solver="bcd" + ) + assert_array_equal(np.where(active_set)[0], [0, 1, 4, 5]) + + # suppress a coordinate-descent warning here + with pytest.warns(RuntimeWarning, match="descent"): + X_hat_cd, active_set, _ = mixed_norm_solver( + *args, active_set_size=2, debias=True, n_orient=2, solver="cd" + ) + assert_array_equal(np.where(active_set)[0], [0, 1, 4, 5]) + assert_allclose(X_hat_bcd, X_hat_cd, rtol=1e-2) + + with _record_warnings(): # CD + X_hat_bcd, active_set, _ = mixed_norm_solver( + *args, active_set_size=2, debias=True, n_orient=5, solver="bcd" + ) + assert_array_equal(np.where(active_set)[0], [0, 1, 2, 3, 4]) + with pytest.warns(RuntimeWarning, match="descent"): + X_hat_cd, active_set, _ = mixed_norm_solver( + *args, active_set_size=2, debias=True, n_orient=5, solver="cd" + ) + + assert_array_equal(np.where(active_set)[0], [0, 1, 2, 3, 4]) + assert_allclose(X_hat_bcd, X_hat_cd) + + +@pytest.mark.slowtest +def test_non_convergence(): + """Test non-convergence of MxNE solver to catch unexpected bugs.""" + n, p, t, alpha = 30, 40, 20, 1.0 + rng = np.random.RandomState(0) + G = rng.randn(n, p) + G /= np.std(G, axis=0)[None, :] + X = np.zeros((p, t)) + X[0] = 3 + X[4] = -2 + M = np.dot(G, X) + + # Impossible to converge with only 1 iteration and tol 1e-12 + # In case of non-convegence, we test that no error is returned. + args = (M, G, alpha, 1, 1e-12) + with catch_logging() as log: + mixed_norm_solver( + *args, active_set_size=None, debias=True, solver="bcd", verbose=True + ) + log = log.getvalue() + assert "Convergence reached" not in log + + +def test_tf_mxne(): + """Test convergence of TF-MxNE solver.""" + alpha_space = 10.0 + alpha_time = 5.0 + + M, G, active_set = _generate_tf_data() + + with _record_warnings(): # CD + X_hat_tf, active_set_hat_tf, E, gap_tfmxne = tf_mixed_norm_solver( + M, + G, + alpha_space, + alpha_time, + maxit=200, + tol=1e-8, + verbose=True, + n_orient=1, + tstep=4, + wsize=32, + return_gap=True, + ) + assert_array_less(gap_tfmxne, 1e-8) + assert_array_equal(np.where(active_set_hat_tf)[0], active_set) + + +def test_norm_epsilon(): + """Test computation of espilon norm on TF coefficients.""" + tstep = np.array([2]) + wsize = np.array([4]) + n_times = 10 + n_steps = np.ceil(n_times / tstep.astype(float)).astype(int) + n_freqs = wsize // 2 + 1 + n_coefs = n_steps * n_freqs + phi = _Phi(wsize, tstep, n_coefs, n_times) + + Y = np.zeros((n_steps * n_freqs).item()) + l1_ratio = 0.03 + assert_allclose(norm_epsilon(Y, l1_ratio, phi), 0.0) + + Y[0] = 2.0 + assert_allclose(norm_epsilon(Y, l1_ratio, phi), np.max(Y)) + + l1_ratio = 1.0 + assert_allclose(norm_epsilon(Y, l1_ratio, phi), np.max(Y)) + # dummy value without random: + Y = np.arange((n_steps * n_freqs).item()) + l1_ratio = 0.0 + assert_allclose( + norm_epsilon(Y, l1_ratio, phi) ** 2, + stft_norm2(Y.reshape(-1, n_freqs[0], n_steps[0])), + ) + + l1_ratio = 0.03 + # test that vanilla epsilon norm = weights equal to 1 + w_time = np.ones(n_coefs[0]) + Y = np.abs(np.random.randn(n_coefs[0])) + assert_allclose( + norm_epsilon(Y, l1_ratio, phi), norm_epsilon(Y, l1_ratio, phi, w_time=w_time) + ) + + # scaling w_time and w_space by the same amount should divide + # epsilon norm by the same amount + Y = np.arange(n_coefs.item()) + 1 + mult = 2.0 + assert_allclose( + norm_epsilon(Y, l1_ratio, phi, w_space=1, w_time=np.ones(n_coefs.item())) + / mult, + norm_epsilon( + Y, l1_ratio, phi, w_space=mult, w_time=mult * np.ones(n_coefs.item()) + ), + ) + + +@pytest.mark.slowtest # slow-ish on Travis OSX +@pytest.mark.timeout(60) # ~30 s on Travis OSX and Linux OpenBLAS +def test_dgapl21l1(): + """Test duality gap for L21 + L1 regularization.""" + n_orient = 2 + M, G, active_set = _generate_tf_data() + n_times = M.shape[1] + n_sources = G.shape[1] + tstep, wsize = np.array([4, 2]), np.array([64, 16]) + n_steps = np.ceil(n_times / tstep.astype(float)).astype(int) + n_freqs = wsize // 2 + 1 + n_coefs = n_steps * n_freqs + phi = _Phi(wsize, tstep, n_coefs, n_times) + phiT = _PhiT(tstep, n_freqs, n_steps, n_times) + + for l1_ratio in [0.05, 0.1]: + alpha_max = norm_epsilon_inf(G, M, phi, l1_ratio, n_orient) + alpha_space = (1.0 - l1_ratio) * alpha_max + alpha_time = l1_ratio * alpha_max + + Z = np.zeros([n_sources, phi.n_coefs.sum()]) + # for alpha = alpha_max, Z = 0 is the solution so the dgap is 0 + gap = dgap_l21l1( + M, + G, + Z, + np.ones(n_sources, dtype=bool), + alpha_space, + alpha_time, + phi, + phiT, + n_orient, + -np.inf, + )[0] + + assert_allclose(0.0, gap) + # check that solution for alpha smaller than alpha_max is non 0: + X_hat_tf, active_set_hat_tf, E, gap = tf_mixed_norm_solver( + M, + G, + alpha_space / 1.01, + alpha_time / 1.01, + maxit=200, + tol=1e-8, + verbose=True, + debias=False, + n_orient=n_orient, + tstep=tstep, + wsize=wsize, + return_gap=True, + ) + # allow possible small numerical errors (negative gap) + assert_array_less(-1e-10, gap) + assert_array_less(gap, 1e-8) + assert_array_less(1, len(active_set_hat_tf)) + + X_hat_tf, active_set_hat_tf, E, gap = tf_mixed_norm_solver( + M, + G, + alpha_space / 5.0, + alpha_time / 5.0, + maxit=200, + tol=1e-8, + verbose=True, + debias=False, + n_orient=n_orient, + tstep=tstep, + wsize=wsize, + return_gap=True, + ) + assert_array_less(-1e-10, gap) + assert_array_less(gap, 1e-8) + assert_array_less(1, len(active_set_hat_tf)) + + +def test_tf_mxne_vs_mxne(): + """Test equivalence of TF-MxNE (with alpha_time=0) and MxNE.""" + alpha_space = 60.0 + alpha_time = 0.0 + + M, G, active_set = _generate_tf_data() + + X_hat_tf, active_set_hat_tf, E = tf_mixed_norm_solver( + M, + G, + alpha_space, + alpha_time, + maxit=200, + tol=1e-8, + verbose=True, + debias=False, + n_orient=1, + tstep=4, + wsize=32, + ) + + # Also run L21 and check that we get the same + X_hat_l21, _, _ = mixed_norm_solver( + M, + G, + alpha_space, + maxit=200, + tol=1e-8, + verbose=False, + n_orient=1, + active_set_size=None, + debias=False, + ) + + assert_allclose(X_hat_tf, X_hat_l21, rtol=1e-1) + + +@pytest.mark.slowtest # slow-ish on Travis OSX +def test_iterative_reweighted_mxne(): + """Test convergence of irMxNE solver.""" + n, p, t, alpha = 30, 40, 20, 1 + rng = np.random.RandomState(0) + G = rng.randn(n, p) + G /= np.std(G, axis=0)[None, :] + X = np.zeros((p, t)) + X[0] = 3 + X[4] = -2 + M = np.dot(G, X) + + with _record_warnings(): # CD + X_hat_l21, _, _ = mixed_norm_solver( + M, + G, + alpha, + maxit=1000, + tol=1e-8, + verbose=False, + n_orient=1, + active_set_size=None, + debias=False, + solver="bcd", + ) + with _record_warnings(): # CD + X_hat_bcd, active_set, _ = iterative_mixed_norm_solver( + M, + G, + alpha, + 1, + maxit=1000, + tol=1e-8, + active_set_size=None, + debias=False, + solver="bcd", + ) + assert_allclose(X_hat_bcd, X_hat_l21, rtol=1e-3) + + with _record_warnings(): # CD + X_hat_bcd, active_set, _ = iterative_mixed_norm_solver( + M, + G, + alpha, + 5, + maxit=1000, + tol=1e-8, + active_set_size=2, + debias=True, + solver="bcd", + ) + assert_array_equal(np.where(active_set)[0], [0, 4]) + with _record_warnings(): # CD + X_hat_cd, active_set, _ = iterative_mixed_norm_solver( + M, + G, + alpha, + 5, + maxit=1000, + tol=1e-8, + active_set_size=None, + debias=True, + solver="cd", + ) + assert_array_equal(np.where(active_set)[0], [0, 4]) + assert_array_almost_equal(X_hat_bcd, X_hat_cd, 5) + + with _record_warnings(): # CD + X_hat_bcd, active_set, _ = iterative_mixed_norm_solver( + M, + G, + alpha, + 5, + maxit=1000, + tol=1e-8, + active_set_size=2, + debias=True, + n_orient=2, + solver="bcd", + ) + assert_array_equal(np.where(active_set)[0], [0, 1, 4, 5]) + # suppress a coordinate-descent warning here + with pytest.warns(RuntimeWarning, match="descent"): + X_hat_cd, active_set, _ = iterative_mixed_norm_solver( + M, + G, + alpha, + 5, + maxit=1000, + tol=1e-8, + active_set_size=2, + debias=True, + n_orient=2, + solver="cd", + ) + assert_array_equal(np.where(active_set)[0], [0, 1, 4, 5]) + assert_allclose(X_hat_bcd, X_hat_cd) + + X_hat_bcd, active_set, _ = iterative_mixed_norm_solver( + M, G, alpha, 5, maxit=1000, tol=1e-8, active_set_size=2, debias=True, n_orient=5 + ) + assert_array_equal(np.where(active_set)[0], [0, 1, 2, 3, 4]) + with pytest.warns(RuntimeWarning, match="descent"): + X_hat_cd, active_set, _ = iterative_mixed_norm_solver( + M, + G, + alpha, + 5, + maxit=1000, + tol=1e-8, + active_set_size=2, + debias=True, + n_orient=5, + solver="cd", + ) + assert_array_equal(np.where(active_set)[0], [0, 1, 2, 3, 4]) + assert_allclose(X_hat_bcd, X_hat_cd) + + +@pytest.mark.slowtest +def test_iterative_reweighted_tfmxne(): + """Test convergence of irTF-MxNE solver.""" + M, G, true_active_set = _generate_tf_data() + alpha_space = 38.0 + alpha_time = 0.5 + tstep, wsize = [4, 2], [64, 16] + + X_hat_tf, _, _ = tf_mixed_norm_solver( + M, + G, + alpha_space, + alpha_time, + maxit=1000, + tol=1e-4, + wsize=wsize, + tstep=tstep, + verbose=False, + n_orient=1, + debias=False, + ) + X_hat_bcd, active_set, _ = iterative_tf_mixed_norm_solver( + M, + G, + alpha_space, + alpha_time, + 1, + wsize=wsize, + tstep=tstep, + maxit=1000, + tol=1e-4, + debias=False, + verbose=False, + ) + assert_allclose(X_hat_tf, X_hat_bcd, rtol=1e-3) + assert_array_equal(np.where(active_set)[0], true_active_set) + + alpha_space = 50.0 + X_hat_bcd, active_set, _ = iterative_tf_mixed_norm_solver( + M, + G, + alpha_space, + alpha_time, + 3, + wsize=wsize, + tstep=tstep, + n_orient=5, + maxit=1000, + tol=1e-4, + debias=False, + verbose=False, + ) + assert_array_equal(np.where(active_set)[0], [0, 1, 2, 3, 4]) + + alpha_space = 40.0 + X_hat_bcd, active_set, _ = iterative_tf_mixed_norm_solver( + M, + G, + alpha_space, + alpha_time, + 2, + wsize=wsize, + tstep=tstep, + n_orient=2, + maxit=1000, + tol=1e-4, + debias=False, + verbose=False, + ) + assert_array_equal(np.where(active_set)[0], [0, 1, 4, 5]) diff --git a/mne-python/source/mne/io/__init__.py b/mne-python/source/mne/io/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..40f385391cd7f39da27f772a24436c69dcd9d1c7 --- /dev/null +++ b/mne-python/source/mne/io/__init__.py @@ -0,0 +1,9 @@ +"""IO module for reading raw data.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import lazy_loader as lazy + +(__getattr__, __dir__, __all__) = lazy.attach_stub(__name__, __file__) diff --git a/mne-python/source/mne/io/__init__.pyi b/mne-python/source/mne/io/__init__.pyi new file mode 100644 index 0000000000000000000000000000000000000000..d7cd5bdfe02d7f664a765ef91b93aa7d40cd10af --- /dev/null +++ b/mne-python/source/mne/io/__init__.pyi @@ -0,0 +1,93 @@ +__all__ = [ + "BaseRaw", + "Raw", + "RawArray", + "anonymize_info", + "concatenate_raws", + "constants", + "get_channel_type_constants", + "match_channel_orders", + "pick", + "read_epochs_eeglab", + "read_epochs_fieldtrip", + "read_epochs_kit", + "read_evoked_besa", + "read_evoked_fieldtrip", + "read_evokeds_mff", + "read_fiducials", + "read_info", + "read_raw", + "read_raw_ant", + "read_raw_artemis123", + "read_raw_bdf", + "read_raw_boxy", + "read_raw_brainvision", + "read_raw_bti", + "read_raw_cnt", + "read_raw_ctf", + "read_raw_curry", + "read_raw_edf", + "read_raw_eeglab", + "read_raw_egi", + "read_raw_eximia", + "read_raw_eyelink", + "read_raw_fieldtrip", + "read_raw_fif", + "read_raw_fil", + "read_raw_gdf", + "read_raw_hitachi", + "read_raw_kit", + "read_raw_mef", + "read_raw_nedf", + "read_raw_neuralynx", + "read_raw_nicolet", + "read_raw_nihon", + "read_raw_nirx", + "read_raw_nsx", + "read_raw_persyst", + "read_raw_snirf", + "show_fiff", + "write_fiducials", + "write_info", +] +from . import constants, pick +from ._fiff_wrap import ( + anonymize_info, + get_channel_type_constants, + read_fiducials, + read_info, + show_fiff, + write_fiducials, + write_info, +) +from ._read_raw import read_raw +from .ant import read_raw_ant +from .array import RawArray +from .artemis123 import read_raw_artemis123 +from .base import BaseRaw, concatenate_raws, match_channel_orders +from .besa import read_evoked_besa +from .boxy import read_raw_boxy +from .brainvision import read_raw_brainvision +from .bti import read_raw_bti +from .cnt import read_raw_cnt +from .ctf import read_raw_ctf +from .curry import read_raw_curry +from .edf import read_raw_bdf, read_raw_edf, read_raw_gdf +from .eeglab import read_epochs_eeglab, read_raw_eeglab +from .egi import read_evokeds_mff, read_raw_egi +from .eximia import read_raw_eximia +from .eyelink import read_raw_eyelink +from .fieldtrip import read_epochs_fieldtrip, read_evoked_fieldtrip, read_raw_fieldtrip +from .fiff import Raw, read_raw_fif +from .fil import read_raw_fil +from .hitachi import read_raw_hitachi +from .kit import read_epochs_kit, read_raw_kit +from .mef import read_raw_mef +from .nedf import read_raw_nedf +from .neuralynx import read_raw_neuralynx +from .nicolet import read_raw_nicolet +from .nihon import read_raw_nihon +from .nirx import read_raw_nirx +from .nsx import read_raw_nsx +from .persyst import read_raw_persyst +from .snirf import read_raw_snirf diff --git a/mne-python/source/mne/io/_fiff_wrap.py b/mne-python/source/mne/io/_fiff_wrap.py new file mode 100644 index 0000000000000000000000000000000000000000..e4566d61a4063721d8c27f613f3f270f382f927d --- /dev/null +++ b/mne-python/source/mne/io/_fiff_wrap.py @@ -0,0 +1,20 @@ +# ruff: noqa: F401 +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# Backward compat since these were in the public API before switching to _fiff +# (and _empty_info is convenient to keep here for tests and is private) +from .._fiff.meas_info import ( + Info as _info, +) +from .._fiff.meas_info import ( + _empty_info, + anonymize_info, + read_fiducials, + read_info, + write_fiducials, + write_info, +) +from .._fiff.open import show_fiff +from .._fiff.pick import get_channel_type_constants # moved up a level diff --git a/mne-python/source/mne/io/_read_raw.py b/mne-python/source/mne/io/_read_raw.py new file mode 100644 index 0000000000000000000000000000000000000000..bf1b4e6fae572d0d9d23567ba7f6fa7f63b17254 --- /dev/null +++ b/mne-python/source/mne/io/_read_raw.py @@ -0,0 +1,196 @@ +"""Generic wrapper function read_raw for specific read_raw_xxx readers.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from functools import partial +from pathlib import Path + +from ..utils import fill_doc +from .base import BaseRaw + + +def _read_unsupported(fname, **kwargs): + ext = "".join(Path(fname).suffixes) + msg = f"Unsupported file type ({ext})." + suggest = kwargs.get("suggest") + if suggest is not None: + msg += f" Try reading a {suggest} file instead." + msg += " Consider using a dedicated reader function for more options." + raise ValueError(msg) + + +# supported read file formats +def _get_supported(): + from . import ( + read_raw_ant, + read_raw_artemis123, + read_raw_bdf, + read_raw_boxy, + read_raw_brainvision, + read_raw_cnt, + read_raw_ctf, + read_raw_curry, + read_raw_edf, + read_raw_eeglab, + read_raw_egi, + read_raw_eximia, + read_raw_eyelink, + read_raw_fieldtrip, + read_raw_fif, + read_raw_fil, + read_raw_gdf, + read_raw_kit, + read_raw_mef, + read_raw_nedf, + read_raw_nicolet, + read_raw_nihon, + read_raw_nirx, + read_raw_nsx, + read_raw_persyst, + read_raw_snirf, + ) + + return { + ".edf": dict(EDF=read_raw_edf), + ".eeg": dict(NihonKoden=read_raw_nihon), + ".bdf": dict(BDF=read_raw_bdf), + ".gdf": dict(GDF=read_raw_gdf), + ".vhdr": dict(brainvision=read_raw_brainvision), + ".ahdr": dict(brainvision=read_raw_brainvision), + ".mefd": dict(MEF=read_raw_mef), + ".fif": dict(FIF=read_raw_fif), + ".fif.gz": dict(FIF=read_raw_fif), + ".set": dict(EEGLAB=read_raw_eeglab), + ".cnt": dict(CNT=read_raw_cnt, ANT=read_raw_ant), + ".mff": dict(EGI=read_raw_egi), + ".nxe": dict(eximia=read_raw_eximia), + ".hdr": dict(NIRx=read_raw_nirx), + ".snirf": dict(SNIRF=read_raw_snirf), + ".mat": dict(fieldtrip=read_raw_fieldtrip), + ".bin": { + "ARTEMIS": read_raw_artemis123, + "UCL FIL OPM": read_raw_fil, + }, + ".data": dict(Nicolet=read_raw_nicolet), + ".sqd": dict(KIT=read_raw_kit), + ".con": dict(KIT=read_raw_kit), + ".ds": dict(CTF=read_raw_ctf), + ".txt": dict(BOXY=read_raw_boxy), + # Curry + ".dat": dict(CURRY=read_raw_curry), + ".dap": dict(CURRY=read_raw_curry), + ".rs3": dict(CURRY=read_raw_curry), + ".cdt": dict(CURRY=read_raw_curry), + ".cdt.dpa": dict(CURRY=read_raw_curry), + ".cdt.cef": dict(CURRY=read_raw_curry), + ".cef": dict(CURRY=read_raw_curry), + # NEDF + ".nedf": dict(NEDF=read_raw_nedf), + # EyeLink + ".asc": dict(EyeLink=read_raw_eyelink), + ".ns3": dict(NSx=read_raw_nsx), + ".lay": dict(Persyst=read_raw_persyst), + } + + +# known but unsupported file formats +_suggested = { + ".vmrk": dict(brainvision=partial(_read_unsupported, suggest=".vhdr")), + ".amrk": dict(brainvision=partial(_read_unsupported, suggest=".ahdr")), +} + + +# all known file formats +def _get_readers(): + return {**_get_supported(), **_suggested} + + +def split_name_ext(fname): + """Return name and supported file extension.""" + maxsuffixes = max(ext.count(".") for ext in _get_supported()) + suffixes = Path(fname).suffixes + for si in range(-maxsuffixes, 0): + ext = "".join(suffixes[si:]).lower() + if ext in _get_readers(): + return Path(fname).name[: -len(ext)], ext + return fname, None # unknown file extension + + +@fill_doc +def read_raw(fname, *, preload=False, verbose=None, **kwargs) -> BaseRaw: + """Read raw file. + + This function is a convenient wrapper for readers defined in `mne.io`. The + correct reader is automatically selected based on the detected file format. + All function arguments are passed to the respective reader. + + The following readers are currently supported: + + * `~mne.io.read_raw_ant` + * `~mne.io.read_raw_artemis123` + * `~mne.io.read_raw_bdf` + * `~mne.io.read_raw_boxy` + * `~mne.io.read_raw_brainvision` + * `~mne.io.read_raw_cnt` + * `~mne.io.read_raw_ctf` + * `~mne.io.read_raw_curry` + * `~mne.io.read_raw_edf` + * `~mne.io.read_raw_eeglab` + * `~mne.io.read_raw_egi` + * `~mne.io.read_raw_eximia` + * `~mne.io.read_raw_eyelink` + * `~mne.io.read_raw_fieldtrip` + * `~mne.io.read_raw_fif` + * `~mne.io.read_raw_fil` + * `~mne.io.read_raw_gdf` + * `~mne.io.read_raw_kit` + * `~mne.io.read_raw_mef` + * `~mne.io.read_raw_nedf` + * `~mne.io.read_raw_nicolet` + * `~mne.io.read_raw_nihon` + * `~mne.io.read_raw_nirx` + * `~mne.io.read_raw_nsx` + * `~mne.io.read_raw_persyst` + * `~mne.io.read_raw_snirf` + + Parameters + ---------- + fname : path-like + Name of the file to read. + %(preload)s + %(verbose)s + **kwargs + Additional keyword arguments to pass to the underlying reader. For + details, see the arguments of the reader for the respective file + format. + + Returns + ------- + raw : mne.io.Raw + Raw object. + """ + _, ext = split_name_ext(fname) + kwargs["verbose"] = verbose + kwargs["preload"] = preload + readers = _get_readers() + if ext not in readers: + _read_unsupported(fname) + these_readers = list(readers[ext].values()) + for reader in these_readers: + try: + return reader(fname, **kwargs) + except Exception: + if len(these_readers) == 1: + raise + else: + choices = "\n".join( + f"mne.io.{func.__name__.ljust(20)} ({kind})" + for kind, func in readers[ext].items() + ) + raise RuntimeError( + "Could not read file using any of the possible readers for " + f"extension {ext}. Consider trying to read the file directly with " + f"one of:\n{choices}" + ) diff --git a/mne-python/source/mne/io/ant/__init__.py b/mne-python/source/mne/io/ant/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..86ae7b38e0de153d87542d9a9d4f489d31649494 --- /dev/null +++ b/mne-python/source/mne/io/ant/__init__.py @@ -0,0 +1,5 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .ant import read_raw_ant diff --git a/mne-python/source/mne/io/ant/ant.py b/mne-python/source/mne/io/ant/ant.py new file mode 100644 index 0000000000000000000000000000000000000000..854406267f44cc0e810a8c97b08a28d43c50adce --- /dev/null +++ b/mne-python/source/mne/io/ant/ant.py @@ -0,0 +1,338 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from __future__ import annotations + +import re +from collections import defaultdict +from typing import TYPE_CHECKING + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import create_info +from ...annotations import Annotations +from ...utils import ( + _check_fname, + _soft_import, + _validate_type, + copy_doc, + fill_doc, + logger, + verbose, + warn, +) +from ..base import BaseRaw + +if TYPE_CHECKING: + from pathlib import Path + + from numpy.typing import NDArray + +_UNITS: dict[str, float] = {"uv": 1e-6, "µv": 1e-6} + + +@fill_doc +class RawANT(BaseRaw): + r"""Reader for Raw ANT files in .cnt format. + + Parameters + ---------- + fname : file-like + Path to the ANT raw file to load. The file should have the extension ``.cnt``. + eog : str | None + Regex pattern to find EOG channel labels. If None, no EOG channels are + automatically detected. + misc : str | None + Regex pattern to find miscellaneous channels. If None, no miscellaneous channels + are automatically detected. The default pattern ``"BIP\d+"`` will mark all + bipolar channels as ``misc``. + + .. note:: + + A bipolar channel might actually contain ECG, EOG or other signal types + which might have a dedicated channel type in MNE-Python. In this case, use + :meth:`mne.io.Raw.set_channel_types` to change the channel type of the + channel. + bipolars : list of str | tuple of str | None + The list of channels to treat as bipolar EEG channels. Each element should be + a string of the form ``'anode-cathode'`` or in ANT terminology as ``'label- + reference'``. If None, all channels are interpreted as ``'eeg'`` channels + referenced to the same reference electrode. Bipolar channels are treated + as EEG channels with a special coil type in MNE-Python, see also + :func:`mne.set_bipolar_reference` + + .. warning:: + + Do not provide auxiliary channels in this argument, provide them in the + ``eog`` and ``misc`` arguments. + impedance_annotation : str + The string to use for impedance annotations. Defaults to ``"impedance"``, + however, the impedance measurement might mark the end of a segment and the + beginning of a new segment, in which case a discontinuity similar to what + :func:`mne.concatenate_raws` produces is present. In this case, it's better to + include a ``BAD_xxx`` annotation to mark the discontinuity. + + .. note:: + + Note that the impedance annotation will likely have a duration of ``0``. + If the measurement marks a discontinuity, the duration should be modified to + cover the discontinuity in its entirety. + encoding : str + Encoding to use for :class:`str` in the CNT file. Defaults to ``'latin-1'``. + %(preload)s + %(verbose)s + """ + + @verbose + def __init__( + self, + fname: str | Path, + eog: str | None, + misc: str | None, + bipolars: list[str] | tuple[str, ...] | None, + impedance_annotation: str, + *, + encoding: str = "latin-1", + preload: bool | NDArray, + verbose=None, + ) -> None: + logger.info("Reading ANT file %s", fname) + _soft_import("antio", "reading ANT files", min_version="0.5.0") + + from antio import read_cnt + from antio.parser import ( + read_device_info, + read_info, + read_meas_date, + read_subject_info, + read_triggers, + ) + + fname = _check_fname(fname, overwrite="read", must_exist=True, name="fname") + _validate_type(eog, (str, None), "eog") + _validate_type(misc, (str, None), "misc") + _validate_type(bipolars, (list, tuple, None), "bipolar") + _validate_type(impedance_annotation, (str,), "impedance_annotation") + if len(impedance_annotation) == 0: + raise ValueError("The impedance annotation cannot be an empty string.") + cnt = read_cnt(fname) + # parse channels, sampling frequency, and create info + ch_names, ch_units, ch_refs, _, _ = read_info(cnt, encoding=encoding) + ch_types = _parse_ch_types(ch_names, eog, misc, ch_refs) + if bipolars is not None: # handle bipolar channels + bipolars_idx = _handle_bipolar_channels(ch_names, ch_refs, bipolars) + for idx, ch in zip(bipolars_idx, bipolars): + if ch_types[idx] != "eeg": + warn( + f"Channel {ch} was not parsed as an EEG channel, changing to " + "EEG channel type since bipolar EEG was requested." + ) + ch_names[idx] = ch + ch_types[idx] = "eeg" + info = create_info( + ch_names, sfreq=cnt.get_sample_frequency(), ch_types=ch_types + ) + info.set_meas_date(read_meas_date(cnt)) + make, model, serial, site = read_device_info(cnt, encoding=encoding) + info["device_info"] = dict(type=make, model=model, serial=serial, site=site) + his_id, name, sex, birthday = read_subject_info(cnt, encoding=encoding) + info["subject_info"] = dict( + his_id=his_id, + first_name=name, + sex=sex, + ) + if birthday is not None: + info["subject_info"]["birthday"] = birthday + if bipolars is not None: + with info._unlock(): + for idx in bipolars_idx: + info["chs"][idx]["coil_type"] = FIFF.FIFFV_COIL_EEG_BIPOLAR + first_samps = np.array((0,)) + last_samps = (cnt.get_sample_count() - 1,) + raw_extras = { + "orig_nchan": cnt.get_channel_count(), + "orig_ch_units": ch_units, + "first_samples": np.array(first_samps), + "last_samples": np.array(last_samps), + } + super().__init__( + info, + preload=preload, + first_samps=first_samps, + last_samps=last_samps, + filenames=[fname], + verbose=verbose, + raw_extras=[raw_extras], + ) + # look for annotations (called trigger by ant) + onsets, durations, descriptions, _, disconnect = read_triggers(cnt) + onsets, durations, descriptions = _prepare_annotations( + onsets, durations, descriptions, disconnect, impedance_annotation + ) + onsets = np.array(onsets) / self.info["sfreq"] + durations = np.array(durations) / self.info["sfreq"] + annotations = Annotations(onsets, duration=durations, description=descriptions) + self.set_annotations(annotations) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + from antio import read_cnt + from antio.parser import read_data + + ch_units = self._raw_extras[0]["orig_ch_units"] + first_samples = self._raw_extras[0]["first_samples"] + n_times = self._raw_extras[0]["last_samples"] + 1 + for first_samp, this_n_times in zip(first_samples, n_times): + i_start = max(start, first_samp) + i_stop = min(stop, this_n_times + first_samp) + # read and scale data array + cnt = read_cnt(self.filenames[fi]) + one = read_data(cnt, i_start, i_stop) + _scale_data(one, ch_units) + data_view = data[:, i_start - start : i_stop - start] + if isinstance(idx, slice): + data_view[:] = one[idx] + else: + # faster than doing one = one[idx] + np.take(one, idx, axis=0, out=data_view) + + +def _handle_bipolar_channels( + ch_names: list[str], ch_refs: list[str], bipolars: list[str] | tuple[str, ...] +) -> list[int]: + """Handle bipolar channels.""" + bipolars_idx = [] + for ch in bipolars: + _validate_type(ch, (str,), "bipolar_channel") + if "-" not in ch: + raise ValueError( + "Bipolar channels should be provided as 'anode-cathode' or " + f"'label-reference'. '{ch}' is not valid." + ) + anode, cathode = ch.split("-") + if anode not in ch_names: + raise ValueError(f"Anode channel {anode} not found in the channels.") + idx = ch_names.index(anode) + if cathode != ch_refs[idx]: + raise ValueError( + f"Reference electrode for {anode} is {ch_refs[idx]}, not {cathode}." + ) + # store idx for later FIFF coil type change + bipolars_idx.append(idx) + return bipolars_idx + + +def _parse_ch_types( + ch_names: list[str], eog: str | None, misc: str | None, ch_refs: list[str] +) -> list[str]: + """Parse the channel types.""" + eog = re.compile(eog) if eog is not None else None + misc = re.compile(misc) if misc is not None else None + ch_types = [] + for ch in ch_names: + if eog is not None and re.fullmatch(eog, ch): + ch_types.append("eog") + elif misc is not None and re.fullmatch(misc, ch): + ch_types.append("misc") + else: + ch_types.append("eeg") + eeg_refs = [ch_refs[k] for k, elt in enumerate(ch_types) if elt == "eeg"] + if len(set(eeg_refs)) == 1: + logger.info( + "All %i EEG channels are referenced to %s.", len(eeg_refs), eeg_refs[0] + ) + else: + warn("All EEG channels are not referenced to the same electrode.") + return ch_types + + +def _prepare_annotations( + onsets: list[int], + durations: list[int], + descriptions: list[str], + disconnect: dict[str, list[int]], + impedance_annotation: str, +) -> tuple[list[int], list[int], list[str]]: + """Parse the ANT triggers into better Annotations.""" + # first, let's replace the description 'impedance' with impedance_annotation + for k, desc in enumerate(descriptions): + if desc.lower() == "impedance": + descriptions[k] = impedance_annotation + # next, let's look for amplifier connection/disconnection and let's try to create + # BAD_disconnection annotations from them. + if ( + len(disconnect["start"]) == len(disconnect["stop"]) + and len(disconnect["start"]) != 0 + and all( + 0 <= stop - start + for start, stop in zip(disconnect["start"], disconnect["stop"]) + ) + ): + for start, stop in zip(disconnect["start"], disconnect["stop"]): + onsets.append(start) + durations.append(stop - start) + descriptions.append("BAD_disconnection") + else: + for elt in disconnect["start"]: + onsets.append(elt) + durations.append(0) + descriptions.append("Amplifier disconnected") + for elt in disconnect["stop"]: + onsets.append(elt) + durations.append(0) + descriptions.append("Amplifier reconnected") + return onsets, durations, descriptions + + +def _scale_data(data: NDArray[np.float64], ch_units: list[str]) -> None: + """Scale the data array based on the human-readable units reported by ANT. + + Operates in-place. + """ + units_index = defaultdict(list) + for idx, unit in enumerate(ch_units): + units_index[unit].append(idx) + for unit, value in units_index.items(): + if unit in _UNITS: + data[np.array(value, dtype=np.int16), :] *= _UNITS[unit] + else: + warn( + f"Unit {unit} not recognized, not scaling. Please report the unit on " + "a github issue on https://github.com/mne-tools/mne-python." + ) + + +@copy_doc(RawANT) +def read_raw_ant( + fname, + eog=None, + misc=r"BIP\d+", + bipolars=None, + impedance_annotation="impedance", + *, + encoding: str = "latin-1", + preload=False, + verbose=None, +) -> RawANT: + """ + Returns + ------- + raw : instance of RawANT + A Raw object containing ANT data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + Notes + ----- + .. versionadded:: 1.9 + """ + return RawANT( + fname, + eog=eog, + misc=misc, + bipolars=bipolars, + impedance_annotation=impedance_annotation, + encoding=encoding, + preload=preload, + verbose=verbose, + ) diff --git a/mne-python/source/mne/io/ant/tests/__init__.py b/mne-python/source/mne/io/ant/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/ant/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/ant/tests/test_ant.py b/mne-python/source/mne/io/ant/tests/test_ant.py new file mode 100644 index 0000000000000000000000000000000000000000..1db1577f9137f55ebaaab03136469fee213b5bf4 --- /dev/null +++ b/mne-python/source/mne/io/ant/tests/test_ant.py @@ -0,0 +1,491 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from __future__ import annotations + +import warnings +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose + +from mne import Annotations +from mne._fiff.constants import FIFF +from mne.datasets import testing +from mne.io import BaseRaw, read_raw, read_raw_ant, read_raw_brainvision +from mne.io.ant.ant import RawANT + +pytest.importorskip("antio", minversion="0.5.0") +data_path = testing.data_path(download=False) / "antio" + + +TypeDataset = dict[ + str, dict[str, Path] | str | int | tuple[str, str, str] | dict[str, str] | None +] + + +def read_raw_bv(fname: Path) -> BaseRaw: + """Read a brainvision file exported from eego. + + For some reason, the first impedance measurement is annotated at sample 0. But since + BrainVision files are 1-indexed, the reader removes '1' to create 0-indexed + annotations. Thus, the first impedance measurement annotation ends up with an onset + 1 sample before the start of the recording. + This is not really an issue as the annotation duration is sufficient to make sure + that MNE does not drop it entirely as 'outside of the data range'. + """ + with warnings.catch_warnings(): + warnings.filterwarnings( + "ignore", + message="Limited .* annotation.*outside the data range.", + category=RuntimeWarning, + ) + raw_bv = read_raw_brainvision(fname) + return raw_bv + + +@pytest.fixture(scope="module") +def ca_208() -> TypeDataset: + """Return the paths to the CA_208 dataset containing 64 channel gel recordings.""" + cnt = { + "short": data_path / "CA_208" / "test_CA_208.cnt", + "amp-dc": data_path / "CA_208" / "test_CA_208_amp_disconnection.cnt", + "start-stop": data_path / "CA_208" / "test_CA_208_start_stop.cnt", + } + bv = {key: value.with_suffix(".vhdr") for key, value in cnt.items()} + return { + "cnt": cnt, + "bv": bv, + "n_eeg": 64, + "n_misc": 24, + "meas_date": "2024-08-14-10-44-47+0000", + "patient_info": { + "name": "antio test", + "his_id": "", + "birthday": "2024-08-14", + "sex": 0, + }, + "machine_info": ("eego", "EE_225", ""), + "hospital": "", + } + + +@pytest.fixture(scope="module") +def ca_208_refs() -> TypeDataset: + """Return the paths and info to the CA_208_refs dataset. + + The following montage was applid on export: + - highpass: 0.3 Hz - lowpass: 30 Hz + - Fp1, Fpz, Fp2 referenced to Fz + - CP3, CP4 referenced to Cz + - others to CPz + """ + cnt = { + "short": data_path / "CA_208_refs" / "test-ref.cnt", + "legacy": data_path / "CA_208_refs" / "test-ref-legacy.cnt", + } + bv = { + "short": cnt["short"].with_suffix(".vhdr"), + } + return { + "cnt": cnt, + "bv": bv, + "n_eeg": 64, + "n_misc": 0, + "meas_date": "2024-09-09-10-57-44+0000", + "patient_info": { + "name": "antio test", + "his_id": "", + "birthday": "2024-08-14", + "sex": 0, + }, + "machine_info": ("eego", "EE_225", ""), + "hospital": "", + } + + +@pytest.fixture(scope="module") +def andy_101() -> TypeDataset: + """Return the path and info to the andy_101 dataset.""" + cnt = { + "short": data_path / "andy_101" / "Andy_101-raw.cnt", + } + bv = {key: value.with_suffix(".vhdr") for key, value in cnt.items()} + return { + "cnt": cnt, + "bv": bv, + "n_eeg": 128, + "n_misc": 0, + "meas_date": "2024-08-19-16-17-07+0000", + "patient_info": { + "name": "Andy test_middle_name EEG_Exam", + "his_id": "test_subject_code", + "birthday": "2024-08-19", + "sex": 2, + }, + "machine_info": ("eego", "EE_226", ""), + "hospital": "", + } + + +@pytest.fixture(scope="module") +def na_271() -> TypeDataset: + """Return the path to a dataset containing 128 channel recording. + + The recording was done with an NA_271 net dipped in saline solution. + """ + cnt = { + "short": data_path / "NA_271" / "test-na-271.cnt", + "legacy": data_path / "NA_271" / "test-na-271-legacy.cnt", + } + bv = { + "short": cnt["short"].with_suffix(".vhdr"), + } + return { + "cnt": cnt, + "bv": bv, + "n_eeg": 128, + "n_misc": 0, + "meas_date": "2024-09-06-10-45-07+0000", + "patient_info": { + "name": "antio test", + "his_id": "", + "birthday": "2024-08-14", + "sex": 0, + }, + "machine_info": ("eego", "EE_226", ""), + "hospital": "", + } + + +@pytest.fixture(scope="module") +def na_271_bips() -> TypeDataset: + """Return the path to a dataset containing 128 channel recording. + + The recording was done with an NA_271 net dipped in saline solution and includes + bipolar channels. + """ + cnt = { + "short": data_path / "NA_271_bips" / "test-na-271.cnt", + "legacy": data_path / "NA_271_bips" / "test-na-271-legacy.cnt", + } + bv = { + "short": cnt["short"].with_suffix(".vhdr"), + } + return { + "cnt": cnt, + "bv": bv, + "n_eeg": 128, + "n_misc": 6, + "meas_date": "2024-09-06-10-37-23+0000", + "patient_info": { + "name": "antio test", + "his_id": "", + "birthday": "2024-08-14", + "sex": 0, + }, + "machine_info": ("eego", "EE_226", ""), + "hospital": "", + } + + +@pytest.fixture(scope="module") +def user_annotations() -> TypeDataset: + """Return the path to a dataset containing user annotations with floating pins.""" + cnt = { + "short": data_path / "user_annotations" / "test-user-annotation.cnt", + "legacy": data_path / "user_annotations" / "test-user-annotation-legacy.cnt", + } + bv = { + "short": cnt["short"].with_suffix(".vhdr"), + } + return { + "cnt": cnt, + "bv": bv, + "n_eeg": 64, + "n_misc": 0, + "meas_date": "2024-08-29-16-15-44+0000", + "patient_info": { + "name": "test test", + "his_id": "", + "birthday": "2024-02-06", + "sex": 0, + }, + "machine_info": ("eego", "EE_225", ""), + "hospital": "", + } + + +@testing.requires_testing_data +@pytest.mark.parametrize("dataset", ["ca_208", "andy_101", "na_271"]) +def test_io_data(dataset, request): + """Test loading of .cnt file.""" + dataset = request.getfixturevalue(dataset) + raw_cnt = read_raw_ant(dataset["cnt"]["short"]) # preload=False + raw_bv = read_raw_bv(dataset["bv"]["short"]) + cnt = raw_cnt.get_data() + bv = raw_bv.get_data() + assert cnt.shape == bv.shape + assert_allclose(cnt, bv, atol=1e-8) + + # check preload=False and preload=False with raw.load_data() + raw_cnt.crop(0.05, 1.05) + raw_cnt2 = read_raw_ant(dataset["cnt"]["short"], preload=False) + raw_cnt2.crop(0.05, 1.05).load_data() + assert_allclose(raw_cnt.get_data(), raw_cnt2.get_data()) + + # check preload=False vs Brainvision file + raw_bv.crop(0.05, 1.05) + assert_allclose(raw_cnt.get_data(), raw_bv.get_data(), atol=1e-8) + + # check preload=False vs BrainVision file after dropping channels + raw_cnt.pick(raw_cnt.ch_names[::2]) + raw_bv.pick(raw_bv.ch_names[::2]) + assert_allclose(raw_cnt.get_data(), raw_bv.get_data(), atol=1e-8) + + # check after raw_cnt.load_data() + raw_cnt.load_data() + assert_allclose(raw_cnt.get_data(), raw_bv.get_data(), atol=1e-8) + + # check preload True vs False + raw_cnt = read_raw_ant(dataset["cnt"]["short"], preload=False) + raw_cnt2 = read_raw_ant(dataset["cnt"]["short"], preload=True) + bads = [raw_cnt.ch_names[idx] for idx in (1, 5, 10)] + assert_allclose( + raw_cnt.drop_channels(bads).get_data(), raw_cnt2.drop_channels(bads).get_data() + ) + raw_bv = read_raw_bv(dataset["bv"]["short"]).drop_channels(bads) + assert_allclose(raw_cnt.get_data(), raw_bv.get_data(), atol=1e-8) + assert_allclose(raw_cnt2.get_data(), raw_bv.get_data(), atol=1e-8) + + +@testing.requires_testing_data +@pytest.mark.parametrize("dataset", ["ca_208", "andy_101", "na_271"]) +def test_io_info(dataset, request): + """Test the ifo loaded from a .cnt file.""" + dataset = request.getfixturevalue(dataset) + raw_cnt = read_raw_ant(dataset["cnt"]["short"]) # preload=False + raw_bv = read_raw_bv(dataset["bv"]["short"]) + assert raw_cnt.ch_names == raw_bv.ch_names + assert raw_cnt.info["sfreq"] == raw_bv.info["sfreq"] + assert ( + raw_cnt.get_channel_types() + == ["eeg"] * dataset["n_eeg"] + ["misc"] * dataset["n_misc"] + ) + assert_allclose( + (raw_bv.info["meas_date"] - raw_cnt.info["meas_date"]).total_seconds(), + 0, + atol=1e-3, + ) + + +@testing.requires_testing_data +def test_io_info_parse_misc(ca_208: TypeDataset): + """Test parsing misc channels from a .cnt file.""" + raw_cnt = read_raw_ant(ca_208["cnt"]["short"]) + with pytest.warns( + RuntimeWarning, + match="All EEG channels are not referenced to the same electrode.", + ): + raw_cnt = read_raw_ant(ca_208["cnt"]["short"], misc=None) + assert len(raw_cnt.ch_names) == ca_208["n_eeg"] + ca_208["n_misc"] + assert raw_cnt.get_channel_types() == ["eeg"] * len(raw_cnt.ch_names) + + +@testing.requires_testing_data +def test_io_info_parse_non_standard_misc(na_271_bips: TypeDataset): + """Test parsing misc channels with modified names from a .cnt file.""" + with pytest.warns( + RuntimeWarning, match="EEG channels are not referenced to the same electrode" + ): + raw = read_raw_ant(na_271_bips["cnt"]["short"], misc=None) + assert raw.get_channel_types() == ["eeg"] * ( + na_271_bips["n_eeg"] + na_271_bips["n_misc"] + ) + raw = read_raw_ant( + na_271_bips["cnt"]["short"], preload=False, misc=r".{0,1}E.{1}G|Aux|Audio" + ) + assert ( + raw.get_channel_types() + == ["eeg"] * na_271_bips["n_eeg"] + ["misc"] * na_271_bips["n_misc"] + ) + + +@testing.requires_testing_data +def test_io_info_parse_eog(ca_208: TypeDataset): + """Test parsing EOG channels from a .cnt file.""" + raw_cnt = read_raw_ant(ca_208["cnt"]["short"], eog="EOG") + assert len(raw_cnt.ch_names) == ca_208["n_eeg"] + ca_208["n_misc"] + idx = raw_cnt.ch_names.index("EOG") + ch_types = ["eeg"] * ca_208["n_eeg"] + ["misc"] * ca_208["n_misc"] + ch_types[idx] = "eog" + assert raw_cnt.get_channel_types() == ch_types + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "dataset", ["andy_101", "ca_208", "na_271", "user_annotations"] +) +def test_subject_info(dataset, request): + """Test reading the subject info.""" + dataset = request.getfixturevalue(dataset) + raw_cnt = read_raw_ant(dataset["cnt"]["short"]) + subject_info = raw_cnt.info["subject_info"] + assert subject_info["his_id"] == dataset["patient_info"]["his_id"] + assert subject_info["first_name"] == dataset["patient_info"]["name"] + assert subject_info["sex"] == dataset["patient_info"]["sex"] + assert ( + subject_info["birthday"].strftime("%Y-%m-%d") + == dataset["patient_info"]["birthday"] + ) + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "dataset", ["andy_101", "ca_208", "na_271", "user_annotations"] +) +def test_machine_info(dataset, request): + """Test reading the machine info.""" + dataset = request.getfixturevalue(dataset) + raw_cnt = read_raw_ant(dataset["cnt"]["short"]) + device_info = raw_cnt.info["device_info"] + make, model, serial = dataset["machine_info"] + assert device_info["type"] == make + assert device_info["model"] == model + assert device_info["serial"] == serial + + +@testing.requires_testing_data +def test_io_amp_disconnection(ca_208: TypeDataset): + """Test loading of .cnt file with amplifier disconnection.""" + raw_cnt = read_raw_ant(ca_208["cnt"]["amp-dc"]) + raw_bv = read_raw_bv(ca_208["bv"]["amp-dc"]) + assert_allclose(raw_cnt.get_data(), raw_bv.get_data(), atol=1e-8) + assert ( + raw_cnt.get_data(reject_by_annotation="omit").shape != raw_bv.get_data().shape + ) + # create annotation on the BV file + idx = [ + k + for k, elt in enumerate(raw_bv.annotations.description) + if any(code in elt for code in ("9001", "9002")) + ] + assert len(idx) == 2 + start = raw_bv.annotations.onset[idx[0]] + stop = raw_bv.annotations.onset[idx[1]] + annotations = Annotations( + onset=start, + duration=stop - start + 1 / raw_bv.info["sfreq"], # estimate is 1 sample short + description="BAD_segment", + ) + raw_bv.set_annotations(annotations) + assert_allclose( + raw_cnt.get_data(reject_by_annotation="omit"), + raw_bv.get_data(reject_by_annotation="omit"), + atol=1e-8, + ) + + +@testing.requires_testing_data +@pytest.mark.parametrize("description", ["impedance", "test"]) +def test_io_impedance(ca_208: TypeDataset, description: str): + """Test loading of impedances from a .cnt file.""" + raw_cnt = read_raw_ant(ca_208["cnt"]["amp-dc"], impedance_annotation=description) + annotations = [ + annot for annot in raw_cnt.annotations if annot["description"] == description + ] + assert len(annotations) != 0 + + +@testing.requires_testing_data +def test_io_segments(ca_208: TypeDataset): + """Test reading a .cnt file with segents (start/stop).""" + raw_cnt = read_raw_ant(ca_208["cnt"]["start-stop"]) + raw_bv = read_raw_bv(ca_208["bv"]["start-stop"]) + assert_allclose(raw_cnt.get_data(), raw_bv.get_data(), atol=1e-8) + + +@testing.requires_testing_data +def test_annotations_and_preload(ca_208: TypeDataset): + """Test annotation loading with preload True/False.""" + raw_cnt_preloaded = read_raw_ant(ca_208["cnt"]["short"], preload=True) + assert len(raw_cnt_preloaded.annotations) == 2 # impedance measurements, start/end + raw_cnt = read_raw_ant(ca_208["cnt"]["short"], preload=False) + assert len(raw_cnt.annotations) == 2 + raw_cnt.crop(2, 3) + assert len(raw_cnt.annotations) == 0 + raw_cnt.load_data() + assert len(raw_cnt.annotations) == 0 + + raw_cnt_preloaded = read_raw_ant(ca_208["cnt"]["amp-dc"], preload=True) + assert len(raw_cnt_preloaded.annotations) == 5 # 4 impedances, 1 disconnection + raw_cnt = read_raw_ant(ca_208["cnt"]["amp-dc"], preload=False) + assert len(raw_cnt.annotations) == 5 + idx = np.where(raw_cnt.annotations.description == "BAD_disconnection")[0] + onset = raw_cnt.annotations.onset[idx][0] + raw_cnt.crop(0, onset - 1) + assert len(raw_cnt.annotations) == 1 # initial impedance measurement + assert raw_cnt.annotations.description[0] == "impedance" + + +@testing.requires_testing_data +def test_read_raw(ca_208: TypeDataset): + """Test loading through read_raw.""" + raw = read_raw(ca_208["cnt"]["short"]) + assert isinstance(raw, RawANT) + + +@testing.requires_testing_data +@pytest.mark.parametrize("preload", [True, False]) +def test_read_raw_with_user_annotations(user_annotations: TypeDataset, preload: bool): + """Test reading raw objects which have user annotations.""" + raw = read_raw_ant(user_annotations["cnt"]["short"], preload=preload) + assert raw.annotations + assert "1000/user-annot" in raw.annotations.description + assert "1000/user-annot-2" in raw.annotations.description + + +@testing.requires_testing_data +@pytest.mark.parametrize("dataset", ["na_271", "user_annotations"]) +def test_read_raw_legacy_format(dataset, request): + """Test reading the legacy CNT format.""" + dataset = request.getfixturevalue(dataset) + raw_cnt = read_raw_ant(dataset["cnt"]["short"]) # preload=False + raw_bv = read_raw_bv(dataset["bv"]["short"]) + assert raw_cnt.ch_names == raw_bv.ch_names + assert raw_cnt.info["sfreq"] == raw_bv.info["sfreq"] + assert ( + raw_cnt.get_channel_types() + == ["eeg"] * dataset["n_eeg"] + ["misc"] * dataset["n_misc"] + ) + assert_allclose( + (raw_bv.info["meas_date"] - raw_cnt.info["meas_date"]).total_seconds(), + 0, + atol=1e-3, + ) + + +@testing.requires_testing_data +def test_read_raw_custom_reference(ca_208_refs: TypeDataset): + """Test reading a CNT file with custom EEG references.""" + with pytest.warns( + RuntimeWarning, match="EEG channels are not referenced to the same electrode" + ): + raw = read_raw_ant(ca_208_refs["cnt"]["short"], preload=False) + for ch in raw.info["chs"]: + assert ch["coil_type"] == FIFF.FIFFV_COIL_EEG + bipolars = ("Fp1-Fz", "Fpz-Fz", "Fp2-Fz", "CP3-Cz", "CP4-Cz") + with pytest.warns( + RuntimeWarning, match="EEG channels are not referenced to the same electrode" + ): + raw = read_raw_ant( + ca_208_refs["cnt"]["short"], preload=False, bipolars=bipolars + ) + assert all(elt in raw.ch_names for elt in bipolars) + for ch in raw.info["chs"]: + if ch["ch_name"] in bipolars: + assert ch["coil_type"] == FIFF.FIFFV_COIL_EEG_BIPOLAR + else: + assert ch["coil_type"] == FIFF.FIFFV_COIL_EEG diff --git a/mne-python/source/mne/io/array/__init__.py b/mne-python/source/mne/io/array/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ad53f7c817fcd9cc300c17d2e5bedf2d83e8e4be --- /dev/null +++ b/mne-python/source/mne/io/array/__init__.py @@ -0,0 +1,7 @@ +"""Module to convert user data to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ._array import RawArray diff --git a/mne-python/source/mne/io/array/_array.py b/mne-python/source/mne/io/array/_array.py new file mode 100644 index 0000000000000000000000000000000000000000..f1c987cb0065914d1cc2cd78df07f695b1af6d3f --- /dev/null +++ b/mne-python/source/mne/io/array/_array.py @@ -0,0 +1,96 @@ +"""Tools for creating Raw objects from numpy arrays.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ...utils import _check_option, _validate_type, fill_doc, logger, verbose +from ..base import BaseRaw + + +@fill_doc +class RawArray(BaseRaw): + """Raw object from numpy array. + + Parameters + ---------- + data : array, shape (n_channels, n_times) + The channels' time series. See notes for proper units of measure. + %(info_not_none)s Consider using :func:`mne.create_info` to populate + this structure. This may be modified in place by the class. + first_samp : int + First sample offset used during recording (default 0). + + .. versionadded:: 0.12 + copy : {'data', 'info', 'both', 'auto', None} + Determines what gets copied on instantiation. "auto" (default) + will copy info, and copy "data" only if necessary to get to + double floating point precision. + + .. versionadded:: 0.18 + %(verbose)s + + See Also + -------- + mne.EpochsArray + mne.EvokedArray + mne.create_info + + Notes + ----- + Proper units of measure: + + * V: eeg, eog, seeg, dbs, emg, ecg, bio, ecog + * T: mag + * T/m: grad + * M: hbo, hbr + * Am: dipole + * AU: misc + """ + + @verbose + def __init__(self, data, info, first_samp=0, copy="auto", verbose=None): + _validate_type(info, "info", "info") + _check_option("copy", copy, ("data", "info", "both", "auto", None)) + dtype = np.complex128 if np.any(np.iscomplex(data)) else np.float64 + orig_data = data + data = np.asanyarray(orig_data, dtype=dtype) + if data.ndim != 2: + raise ValueError( + "Data must be a 2D array of shape (n_channels, n_samples), got shape " + f"{data.shape}" + ) + if len(data) != len(info["ch_names"]): + raise ValueError( + 'len(data) ({}) does not match len(info["ch_names"]) ({})'.format( + len(data), len(info["ch_names"]) + ) + ) + assert len(info["ch_names"]) == info["nchan"] + if copy in ("auto", "info", "both"): + info = info.copy() + if copy in ("data", "both"): + if data is orig_data: + data = data.copy() + elif copy != "auto" and data is not orig_data: + raise ValueError( + f"data copying was not requested by copy={copy!r} but it was required " + "to get to double floating point precision" + ) + logger.info( + f"Creating RawArray with {dtype.__name__} data, " + f"n_channels={data.shape[0]}, n_times={data.shape[1]}" + ) + super().__init__( + info, data, first_samps=(int(first_samp),), dtype=dtype, verbose=verbose + ) + logger.info( + " Range : %d ... %d = %9.3f ... %9.3f secs", + self.first_samp, + self.last_samp, + float(self.first_samp) / info["sfreq"], + float(self.last_samp) / info["sfreq"], + ) + logger.info("Ready.") diff --git a/mne-python/source/mne/io/array/tests/__init__.py b/mne-python/source/mne/io/array/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/array/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/array/tests/test_array.py b/mne-python/source/mne/io/array/tests/test_array.py new file mode 100644 index 0000000000000000000000000000000000000000..edac2923c2da61ed7216d1ac66394263fbb146b6 --- /dev/null +++ b/mne-python/source/mne/io/array/tests/test_array.py @@ -0,0 +1,189 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import matplotlib.pyplot as plt +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_almost_equal, assert_equal + +from mne import Epochs, find_events, pick_types +from mne._fiff.meas_info import create_info +from mne._fiff.pick import get_channel_type_constants +from mne.channels import make_dig_montage +from mne.io import read_raw_fif +from mne.io.array import RawArray +from mne.io.tests.test_raw import _test_raw_reader + +base_dir = Path(__file__).parents[2] / "tests" / "data" +fif_fname = base_dir / "test_raw.fif" + + +def test_long_names(): + """Test long name support.""" + info = create_info(["a" * 15 + "b", "a" * 16], 1000.0, verbose="error") + data = np.zeros((2, 1000)) + raw = RawArray(data, info) + assert raw.ch_names == ["a" * 15 + "b", "a" * 16] + # and a way to get the old behavior + raw.rename_channels( + {k: k[:13] for k in raw.ch_names}, allow_duplicates=True, verbose="error" + ) + assert raw.ch_names == ["a" * 13 + "-0", "a" * 13 + "-1"] + info = create_info(["a" * 16] * 11, 1000.0, verbose="error") + data = np.zeros((11, 1000)) + raw = RawArray(data, info) + assert raw.ch_names == ["a" * 16 + f"-{ii}" for ii in range(11)] + + +def test_array_copy(): + """Test copying during construction.""" + info = create_info(1, 1000.0) + data = np.zeros((1, 1000)) + # 'auto' (default) + raw = RawArray(data, info) + assert raw._data is data + assert raw.info is not info + raw = RawArray(data.astype(np.float32), info) + assert raw._data is not data + assert raw.info is not info + # 'info' (more restrictive) + raw = RawArray(data, info, copy="info") + assert raw._data is data + assert raw.info is not info + with pytest.raises(ValueError, match="data copying was not .* copy='info"): + RawArray(data.astype(np.float32), info, copy="info") + # 'data' + raw = RawArray(data, info, copy="data") + assert raw._data is not data + assert raw.info is info + # 'both' + raw = RawArray(data, info, copy="both") + assert raw._data is not data + assert raw.info is not info + raw = RawArray(data.astype(np.float32), info, copy="both") + assert raw._data is not data + assert raw.info is not info + # None + raw = RawArray(data, info, copy=None) + assert raw._data is data + assert raw.info is info + with pytest.raises(ValueError, match="data copying was not .* copy=None"): + RawArray(data.astype(np.float32), info, copy=None) + + +@pytest.mark.slowtest +def test_array_raw(): + """Test creating raw from array.""" + # creating + raw = read_raw_fif(fif_fname).crop(2, 5) + data, times = raw[:, :] + sfreq = raw.info["sfreq"] + ch_names = [ + (ch[4:] if "STI" not in ch else ch) for ch in raw.info["ch_names"] + ] # change them, why not + types = list() + for ci in range(101): + types.extend(("grad", "grad", "mag")) + types.extend(["ecog", "seeg", "hbo"]) # really 4 meg channels + types.extend(["stim"] * 9) + types.extend(["dbs"]) # really eeg channel + types.extend(["eeg"] * 60) + picks = np.concatenate( + [ + pick_types(raw.info, meg=True)[::20], + pick_types(raw.info, meg=False, stim=True), + pick_types(raw.info, meg=False, eeg=True)[::20], + ] + ) + del raw + data = data[picks] + ch_names = np.array(ch_names)[picks].tolist() + types = np.array(types)[picks].tolist() + types.pop(-1) + # wrong length + pytest.raises(ValueError, create_info, ch_names, sfreq, types) + # bad entry + types.append("foo") + pytest.raises(KeyError, create_info, ch_names, sfreq, types) + types[-1] = "eog" + # default type + info = create_info(ch_names, sfreq) + assert_equal(info["chs"][0]["kind"], get_channel_type_constants()["misc"]["kind"]) + # use real types + info = create_info(ch_names, sfreq, types) + raw2 = _test_raw_reader( + RawArray, + test_preloading=False, + data=data, + info=info, + first_samp=2 * data.shape[1], + ) + data2, times2 = raw2[:, :] + assert_allclose(data, data2) + assert_allclose(times, times2) + assert "RawArray" in repr(raw2) + pytest.raises(TypeError, RawArray, info, data) + + # filtering + picks = pick_types(raw2.info, meg=True, misc=True, exclude="bads")[:4] + assert_equal(len(picks), 4) + raw_lp = raw2.copy() + kwargs = dict(fir_design="firwin", picks=picks) + raw_lp.filter(None, 4.0, h_trans_bandwidth=4.0, **kwargs) + raw_hp = raw2.copy() + raw_hp.filter(16.0, None, l_trans_bandwidth=4.0, **kwargs) + raw_bp = raw2.copy() + raw_bp.filter(8.0, 12.0, l_trans_bandwidth=4.0, h_trans_bandwidth=4.0, **kwargs) + raw_bs = raw2.copy() + raw_bs.filter(16.0, 4.0, l_trans_bandwidth=4.0, h_trans_bandwidth=4.0, **kwargs) + data, _ = raw2[picks, :] + lp_data, _ = raw_lp[picks, :] + hp_data, _ = raw_hp[picks, :] + bp_data, _ = raw_bp[picks, :] + bs_data, _ = raw_bs[picks, :] + sig_dec = 15 + assert_array_almost_equal(data, lp_data + bp_data + hp_data, sig_dec) + assert_array_almost_equal(data, bp_data + bs_data, sig_dec) + + # plotting + raw2.plot() + raw2.compute_psd(tmax=2.0, n_fft=1024).plot( + average=True, amplitude=False, spatial_colors=False + ) + plt.close("all") + + # epoching + events = find_events(raw2, stim_channel="STI 014") + events[:, 2] = 1 + assert len(events) > 2 + epochs = Epochs(raw2, events, 1, -0.2, 0.4, preload=True) + evoked = epochs.average() + assert_equal(evoked.nave, len(events) - 1) + + # complex data + rng = np.random.RandomState(0) + data = rng.randn(1, 100) + 1j * rng.randn(1, 100) + raw = RawArray(data, create_info(1, 1000.0, "eeg")) + assert_allclose(raw._data, data) + + # Using digital montage to give MNI electrode coordinates + n_elec = 10 + ts_size = 10000 + Fs = 512.0 + ch_names = [str(i) for i in range(n_elec)] + ch_pos_loc = np.random.randint(60, size=(n_elec, 3)).tolist() + + data = np.random.rand(n_elec, ts_size) + montage = make_dig_montage( + ch_pos=dict(zip(ch_names, ch_pos_loc)), coord_frame="head" + ) + info = create_info(ch_names, Fs, "ecog") + + raw = RawArray(data, info) + raw.set_montage(montage) + spectrum = raw.compute_psd() + spectrum.plot(average=False, amplitude=False) # looking for nonexistent layout + spectrum.plot_topo() diff --git a/mne-python/source/mne/io/artemis123/__init__.py b/mne-python/source/mne/io/artemis123/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7a51a739098880f4864fd6c1d0af00a23a4672ac --- /dev/null +++ b/mne-python/source/mne/io/artemis123/__init__.py @@ -0,0 +1,7 @@ +"""artemis123 module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .artemis123 import read_raw_artemis123 diff --git a/mne-python/source/mne/io/artemis123/artemis123.py b/mne-python/source/mne/io/artemis123/artemis123.py new file mode 100644 index 0000000000000000000000000000000000000000..177b57c5db7b23a0c0ddf333f4d9bcaf227aaf49 --- /dev/null +++ b/mne-python/source/mne/io/artemis123/artemis123.py @@ -0,0 +1,532 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import calendar +import datetime +import os.path as op + +import numpy as np +from scipy.spatial.distance import cdist + +from ..._fiff._digitization import DigPoint, _make_dig_points +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info +from ..._fiff.utils import _read_segments_file +from ...transforms import Transform, apply_trans, get_ras_to_neuromag_trans +from ...utils import _check_fname, logger, verbose, warn +from ..base import BaseRaw +from .utils import _load_mne_locs, _read_pos + + +@verbose +def read_raw_artemis123( + input_fname, preload=False, verbose=None, pos_fname=None, add_head_trans=True +) -> "RawArtemis123": + """Read Artemis123 data as raw object. + + Parameters + ---------- + input_fname : path-like + Path to the data file (extension ``.bin``). The header file with the + same file name stem and an extension ``.txt`` is expected to be found + in the same directory. + %(preload)s + %(verbose)s + pos_fname : path-like | None + If not None, load digitized head points from this file. + add_head_trans : bool (default True) + If True attempt to perform initial head localization. Compute initial + device to head coordinate transform using HPI coils. If no + HPI coils are in info['dig'] hpi coils are assumed to be in canonical + order of fiducial points (nas, rpa, lpa). + + Returns + ------- + raw : instance of Raw + A Raw object containing the data. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + return RawArtemis123( + input_fname, + preload=preload, + verbose=verbose, + pos_fname=pos_fname, + add_head_trans=add_head_trans, + ) + + +def _get_artemis123_info(fname, pos_fname=None): + """Generate info struct from artemis123 header file.""" + fname = op.splitext(fname)[0] + header = fname + ".txt" + + logger.info("Reading header...") + + # key names for artemis channel info... + chan_keys = [ + "name", + "scaling", + "FLL_Gain", + "FLL_Mode", + "FLL_HighPass", + "FLL_AutoReset", + "FLL_ResetLock", + ] + + header_info = dict() + header_info["filter_hist"] = [] + header_info["comments"] = "" + header_info["channels"] = [] + + with open(header) as fid: + # section flag + # 0 - None + # 1 - main header + # 2 - channel header + # 3 - comments + # 4 - length + # 5 - filtering History + sectionFlag = 0 + for line in fid: + # skip emptylines or header line for channel info + if (not line.strip()) or (sectionFlag == 2 and line.startswith("DAQ Map")): + continue + + # set sectionFlag + if line.startswith(""): + sectionFlag = 1 + elif line.startswith(""): + sectionFlag = 2 + elif line.startswith(""): + sectionFlag = 3 + elif line.startswith(""): + sectionFlag = 4 + elif line.startswith(""): + sectionFlag = 5 + else: + # parse header info lines + # part of main header - lines are name value pairs + if sectionFlag == 1: + values = line.strip().split("\t") + if len(values) == 1: + values.append("") + header_info[values[0]] = values[1] + # part of channel header - lines are Channel Info + elif sectionFlag == 2: + values = line.strip().split("\t") + if len(values) != 7: + raise OSError( + f"Error parsing line \n\t:{line}\nfrom file {header}" + ) + tmp = dict() + for k, v in zip(chan_keys, values): + tmp[k] = v + header_info["channels"].append(tmp) + elif sectionFlag == 3: + header_info["comments"] = f"{header_info['comments']}{line.strip()}" + elif sectionFlag == 4: + header_info["num_samples"] = int(line.strip()) + elif sectionFlag == 5: + header_info["filter_hist"].append(line.strip()) + + for k in [ + "Temporal Filter Active?", + "Decimation Active?", + "Spatial Filter Active?", + ]: + if header_info[k] != "FALSE": + warn(f"{k} - set to but is not supported") + if header_info["filter_hist"]: + warn("Non-Empty Filter history found, BUT is not supported") + + # build mne info struct + info = _empty_info(float(header_info["DAQ Sample Rate"])) + + # Attempt to get time/date from fname + # Artemis123 files saved from the scanner observe the following + # naming convention 'Artemis_Data_YYYY-MM-DD-HHh-MMm_[chosen by user].bin' + try: + date = datetime.datetime.strptime( + op.basename(fname).split("_")[2], "%Y-%m-%d-%Hh-%Mm" + ) + meas_date = (calendar.timegm(date.utctimetuple()), 0) + except Exception: + meas_date = None + + # build subject info must be an integer (as per FIFF) + try: + subject_info = {"id": int(header_info["Subject ID"])} + except ValueError: + subject_info = {"id": 0} + + # build description + desc = "" + for k in ["Purpose", "Notes"]: + desc += f"{k} : {header_info[k]}\n" + desc += f"Comments : {header_info['comments']}" + + info.update( + { + "meas_date": meas_date, + "description": desc, + "subject_info": subject_info, + "proj_name": header_info["Project Name"], + } + ) + + # Channel Names by type + ref_mag_names = ["REF_001", "REF_002", "REF_003", "REF_004", "REF_005", "REF_006"] + + ref_grad_names = ["REF_007", "REF_008", "REF_009", "REF_010", "REF_011", "REF_012"] + + # load mne loc dictionary + loc_dict = _load_mne_locs() + info["chs"] = [] + bads = [] + + for i, chan in enumerate(header_info["channels"]): + # build chs struct + t = { + "cal": float(chan["scaling"]), + "ch_name": chan["name"], + "logno": i + 1, + "scanno": i + 1, + "range": 1.0, + "unit_mul": FIFF.FIFF_UNITM_NONE, + "coord_frame": FIFF.FIFFV_COORD_DEVICE, + } + # REF_018 has a zero cal which can cause problems. Let's set it to + # a value of another ref channel to make writers/readers happy. + if t["cal"] == 0: + t["cal"] = 4.716e-10 + bads.append(t["ch_name"]) + t["loc"] = loc_dict.get(chan["name"], np.zeros(12)) + + if chan["name"].startswith("MEG"): + t["coil_type"] = FIFF.FIFFV_COIL_ARTEMIS123_GRAD + t["kind"] = FIFF.FIFFV_MEG_CH + # While gradiometer units are T/m, the meg sensors referred to as + # gradiometers report the field difference between 2 pick-up coils. + # Therefore the units of the measurements should be T + # *AND* the baseline (difference between pickup coils) + # should not be used in leadfield / forwardfield computations. + t["unit"] = FIFF.FIFF_UNIT_T + t["unit_mul"] = FIFF.FIFF_UNITM_F + + # 3 axis reference magnetometers + elif chan["name"] in ref_mag_names: + t["coil_type"] = FIFF.FIFFV_COIL_ARTEMIS123_REF_MAG + t["kind"] = FIFF.FIFFV_REF_MEG_CH + t["unit"] = FIFF.FIFF_UNIT_T + t["unit_mul"] = FIFF.FIFF_UNITM_F + + # reference gradiometers + elif chan["name"] in ref_grad_names: + t["coil_type"] = FIFF.FIFFV_COIL_ARTEMIS123_REF_GRAD + t["kind"] = FIFF.FIFFV_REF_MEG_CH + # While gradiometer units are T/m, the meg sensors referred to as + # gradiometers report the field difference between 2 pick-up coils. + # Therefore the units of the measurements should be T + # *AND* the baseline (difference between pickup coils) + # should not be used in leadfield / forwardfield computations. + t["unit"] = FIFF.FIFF_UNIT_T + t["unit_mul"] = FIFF.FIFF_UNITM_F + + # other reference channels are unplugged and should be ignored. + elif chan["name"].startswith("REF"): + t["coil_type"] = FIFF.FIFFV_COIL_NONE + t["kind"] = FIFF.FIFFV_MISC_CH + t["unit"] = FIFF.FIFF_UNIT_V + bads.append(t["ch_name"]) + + elif chan["name"].startswith(("AUX", "TRG", "MIO")): + t["coil_type"] = FIFF.FIFFV_COIL_NONE + t["unit"] = FIFF.FIFF_UNIT_V + if chan["name"].startswith("TRG"): + t["kind"] = FIFF.FIFFV_STIM_CH + else: + t["kind"] = FIFF.FIFFV_MISC_CH + else: + raise ValueError( + f'Channel does not match expected channel Types:"{chan["name"]}"' + ) + + # incorporate multiplier (unit_mul) into calibration + t["cal"] *= 10 ** t["unit_mul"] + t["unit_mul"] = FIFF.FIFF_UNITM_NONE + + # append this channel to the info + info["chs"].append(t) + if chan["FLL_ResetLock"] == "TRUE": + bads.append(t["ch_name"]) + + # HPI information + # print header_info.keys() + hpi_sub = dict() + # Don't know what event_channel is don't think we have it HPIs are either + # always on or always off. + # hpi_sub['event_channel'] = ??? + hpi_sub["hpi_coils"] = [dict(), dict(), dict(), dict()] + hpi_coils = [dict(), dict(), dict(), dict()] + drive_channels = ["MIO_001", "MIO_003", "MIO_009", "MIO_011"] + key_base = "Head Tracking %s %d" + + # set default HPI frequencies + if info["sfreq"] == 1000: + default_freqs = [140, 150, 160, 40] + else: + default_freqs = [700, 750, 800, 40] + + for i in range(4): + # build coil structure + hpi_coils[i]["number"] = i + 1 + hpi_coils[i]["drive_chan"] = drive_channels[i] + this_freq = header_info.pop(key_base % ("Frequency", i + 1), default_freqs[i]) + hpi_coils[i]["coil_freq"] = this_freq + + # check if coil is on + if header_info[key_base % ("Channel", i + 1)] == "OFF": + hpi_sub["hpi_coils"][i]["event_bits"] = [0] + else: + hpi_sub["hpi_coils"][i]["event_bits"] = [256] + + info["hpi_subsystem"] = hpi_sub + info["hpi_meas"] = [{"hpi_coils": hpi_coils}] + # read in digitized points if supplied + if pos_fname is not None: + info["dig"] = _read_pos(pos_fname) + else: + info["dig"] = [] + + info._unlocked = False + info._update_redundant() + # reduce info['bads'] to unique set + info["bads"] = list(set(bads)) + del bads + return info, header_info + + +class RawArtemis123(BaseRaw): + """Raw object from Artemis123 file. + + Parameters + ---------- + input_fname : path-like + Path to the Artemis123 data file (ending in ``'.bin'``). + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + @verbose + def __init__( + self, + input_fname, + preload=False, + verbose=None, + pos_fname=None, + add_head_trans=True, + ): + from ...chpi import ( + _fit_coil_order_dev_head_trans, + compute_chpi_amplitudes, + compute_chpi_locs, + ) + + input_fname = str(_check_fname(input_fname, "read", True, "input_fname")) + fname, ext = op.splitext(input_fname) + if ext == ".txt": + input_fname = fname + ".bin" + elif ext != ".bin": + raise RuntimeError( + 'Valid artemis123 files must end in "txt"' + ' or ".bin".' + ) + + if not op.exists(input_fname): + raise RuntimeError(f"{input_fname} - Not Found") + + info, header_info = _get_artemis123_info(input_fname, pos_fname=pos_fname) + + last_samps = [header_info.get("num_samples", 1) - 1] + + super().__init__( + info, + preload, + filenames=[input_fname], + raw_extras=[header_info], + last_samps=last_samps, + orig_format="single", + verbose=verbose, + ) + + if add_head_trans: + n_hpis = 0 + for d in info["hpi_subsystem"]["hpi_coils"]: + if d["event_bits"] == [256]: + n_hpis += 1 + if n_hpis < 3: + warn( + f"{n_hpis:d} HPIs active. At least 3 needed to perform" + "head localization\n *NO* head localization performed" + ) + else: + # Localized HPIs using the 1st 250 milliseconds of data. + with info._unlock(): + info["hpi_results"] = [ + dict( + dig_points=[ + dict( + r=np.zeros(3), + coord_frame=FIFF.FIFFV_COORD_DEVICE, + ident=ii + 1, + ) + for ii in range(n_hpis) + ], + coord_trans=Transform("meg", "head"), + ) + ] + coil_amplitudes = compute_chpi_amplitudes( + self, tmin=0, tmax=0.25, t_window=0.25, t_step_min=0.25 + ) + assert len(coil_amplitudes["times"]) == 1 + # Need an ititial dev_head_t to compute coil locations + self.info["dev_head_t"] = Transform("meg", "head") + coil_locs = compute_chpi_locs(self.info, coil_amplitudes) + with info._unlock(): + info["hpi_results"] = None + hpi_g = coil_locs["gofs"][0] + hpi_dev = coil_locs["rrs"][0] + + # only use HPI coils with localizaton goodness_of_fit > 0.98 + bad_idx = [] + for i, g in enumerate(hpi_g): + msg = f"HPI coil {i + 1} - location goodness of fit ({g:0.3f})" + if g < 0.98: + bad_idx.append(i) + msg += " *Removed from coregistration*" + logger.info(msg) + hpi_dev = np.delete(hpi_dev, bad_idx, axis=0) + hpi_g = np.delete(hpi_g, bad_idx, axis=0) + + if pos_fname is not None: + # Digitized HPI points are needed. + hpi_head = np.array( + [ + d["r"] + for d in self.info.get("dig", []) + if d["kind"] == FIFF.FIFFV_POINT_HPI + ] + ) + + if len(hpi_head) != len(hpi_dev): + raise RuntimeError( + f"number of digitized ({len(hpi_head)}) and active " + f"({len(hpi_dev)}) HPI coils are not the same." + ) + + # compute initial head to dev transform and hpi ordering + dev_head_t, order, trans_g = _fit_coil_order_dev_head_trans( + hpi_dev, hpi_head + ) + + # set the device to head transform + self.info["dev_head_t"] = Transform( + FIFF.FIFFV_COORD_DEVICE, FIFF.FIFFV_COORD_HEAD, dev_head_t + ) + + # add hpi_meg_dev to dig... + for idx, point in enumerate(hpi_dev): + d = { + "r": point, + "ident": idx + 1, + "kind": FIFF.FIFFV_POINT_HPI, + "coord_frame": FIFF.FIFFV_COORD_DEVICE, + } + self.info["dig"].append(DigPoint(d)) + + dig_dists = cdist(hpi_head[order], hpi_head[order]) + dev_dists = cdist(hpi_dev, hpi_dev) + tmp_dists = np.abs(dig_dists - dev_dists) + dist_limit = tmp_dists.max() * 1.1 + + logger.info( + "HPI-Dig corrregsitration\n" + f"\tGOF : {trans_g:0.3f}\n" + f"\tMax Coil Error : {100 * tmp_dists.max():0.3f} cm\n" + ) + + else: + logger.info("Assuming Cardinal HPIs") + nas = hpi_dev[0] + lpa = hpi_dev[2] + rpa = hpi_dev[1] + t = get_ras_to_neuromag_trans(nas, lpa, rpa) + with self.info._unlock(): + self.info["dev_head_t"] = Transform( + FIFF.FIFFV_COORD_DEVICE, FIFF.FIFFV_COORD_HEAD, t + ) + + # transform fiducial points + nas = apply_trans(t, nas) + lpa = apply_trans(t, lpa) + rpa = apply_trans(t, rpa) + + hpi = apply_trans(self.info["dev_head_t"], hpi_dev) + with self.info._unlock(): + self.info["dig"] = _make_dig_points( + nasion=nas, lpa=lpa, rpa=rpa, hpi=hpi + ) + order = np.array([0, 1, 2]) + dist_limit = 0.005 + + # fill in hpi_results + hpi_result = dict() + + # add HPI points in device coords... + dig = [] + for idx, point in enumerate(hpi_dev): + dig.append( + { + "r": point, + "ident": idx + 1, + "kind": FIFF.FIFFV_POINT_HPI, + "coord_frame": FIFF.FIFFV_COORD_DEVICE, + } + ) + hpi_result["dig_points"] = dig + + # attach Transform + hpi_result["coord_trans"] = self.info["dev_head_t"] + + # 1 based indexing + hpi_result["order"] = order + 1 + hpi_result["used"] = np.arange(3) + 1 + hpi_result["dist_limit"] = dist_limit + hpi_result["good_limit"] = 0.98 + + # Warn for large discrepancies between digitized and fit + # cHPI locations + if hpi_result["dist_limit"] > 0.005: + warn( + "Large difference between digitized geometry" + " and HPI geometry. Max coil to coil difference" + f" is {100.0 * tmp_dists.max():0.2f} cm\n" + "beware of *POOR* head localization" + ) + + # store it + with self.info._unlock(): + self.info["hpi_results"] = [hpi_result] + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + _read_segments_file(self, data, idx, fi, start, stop, cals, mult, dtype=">f4") diff --git a/mne-python/source/mne/io/artemis123/resources/Artemis123_ChannelMap.csv b/mne-python/source/mne/io/artemis123/resources/Artemis123_ChannelMap.csv new file mode 100644 index 0000000000000000000000000000000000000000..1ee93253b2e9b6b220e9a99f96fbf5f6d815b3d1 --- /dev/null +++ b/mne-python/source/mne/io/artemis123/resources/Artemis123_ChannelMap.csv @@ -0,0 +1,146 @@ +name,Channel Type,CAD X+ (INCH),CAD Y+ (INCH),CAD Z+ (INCH),CAD X- (INCH),CAD Y- (INCH),CAD Z- (INCH) +Derived from '90-0395 Channel Map for 6th cooldown 2-01-13.xls',,,,,,, +MEG_059,MEG_GRAD,-1.97677,1.56552,2.91489,-4.18768,2.50074,5.40664 +MEG_045,MEG_GRAD,-1.61144,0.93037,3.41137,-3.33479,1.92534,6.24186 +MEG_029,MEG_GRAD,-0.91075,1.72387,3.473,-1.93587,2.72988,6.62081 +MEG_073,MEG_GRAD,-2.38955,0.86972,2.76491,-4.94504,1.79985,4.90406 +MEG_043,MEG_GRAD,-1.59926,2.33243,2.93122,-3.46787,3.39595,5.64209 +MEG_085,MEG_GRAD,-2.78631,1.40783,1.84839,-5.89386,2.21359,3.13893 +REF_013,UNUSED,,,,,, +MEG_071,MEG_GRAD,-2.43321,2.17533,2.12153,-5.27622,3.05529,3.88634 +MEG_032,MEG_GRAD,0.93037,-1.61144,3.41137,1.92534,-3.33479,6.24186 +MEG_048,MEG_GRAD,1.27145,-2.20222,2.76491,2.6312,-4.55737,4.90406 +MEG_018,MEG_GRAD,0.44157,-2.50427,2.76491,0.91381,-5.18245,4.90406 +MEG_006,MEG_GRAD,0,-3.0105,1.94967,0,-6.23006,3.21696 +MEG_005,MEG_GRAD,0,-1.86073,3.41137,0,-3.85068,6.24186 +MEG_049,MEG_GRAD,-1.27145,-2.20222,2.76491,-2.6312,-4.55737,4.90406 +MEG_019,MEG_GRAD,-0.44157,-2.50427,2.76491,-0.91381,-5.18245,4.90406 +MEG_033,MEG_GRAD,-0.93037,-1.61144,3.41137,-1.92534,-3.33479,6.24186 +MEG_021,MEG_GRAD,-0.56074,-3.168,1.10519,-1.13708,-6.39559,2.21066 +MEG_020,MEG_GRAD,0.56022,-3.16809,1.10519,1.13604,-6.39578,2.21066 +MEG_034,MEG_GRAD,1.02965,-2.82894,1.94967,2.13081,-5.85434,3.21696 +MEG_077,MEG_GRAD,-2.47272,-2.0647,1.06346,-5.01426,-4.15829,2.12604 +MEG_035,MEG_GRAD,-1.02965,-2.82894,1.94967,-2.13081,-5.85434,3.21696 +MEG_007,MEG_GRAD,0,-3.27147,0.25764,0,-6.63351,1.0751 +MEG_023,MEG_GRAD,-0.576,-3.27431,-0.5962,-1.16503,-6.58484,0.21931 +MEG_022,MEG_GRAD,0.56022,-3.27709,-0.59609,1.14872,-6.58771,0.21942 +MEG_047,MEG_GRAD,-1.61144,-0.93037,3.41137,-3.33479,-1.92534,6.24186 +MEG_061,MEG_GRAD,-1.86073,0,3.41137,-3.85068,0,6.24186 +MEG_087,MEG_GRAD,-2.5429,0,2.76491,-5.2624,0,4.90406 +MEG_113,MEG_GRAD,-3.22769,0.0086,0.98505,-6.5452,0.046,1.96703 +MEG_101,MEG_GRAD,-2.96476,-0.52277,1.94967,-6.13541,-1.08184,3.21696 +MEG_099,MEG_GRAD,-2.96476,0.52277,1.94967,-6.13541,1.08184,3.21696 +MEG_063,MEG_GRAD,-1.94798,-1.63455,2.76491,-4.03123,-3.38261,4.90406 +MEG_075,MEG_GRAD,-2.38955,-0.86972,2.76491,-4.94504,-1.79985,4.90406 +MEG_089,MEG_GRAD,-2.60717,-1.50525,1.94967,-5.39539,-3.11503,3.21696 +MEG_123,MEG_GRAD,-3.24454,-0.65992,-1.54654,-6.63007,-1.24165,-1.13258 +MEG_103,MEG_GRAD,-3.03312,-1.09456,1.02677,-6.15066,-2.19102,2.05164 +MEG_119,MEG_GRAD,-3.27163,-0.04807,-0.71822,-6.66217,-0.02172,-0.02891 +MEG_121,MEG_GRAD,-3.24454,0.48346,-1.58979,-6.63007,1.0948,-1.22095 +MEG_105,MEG_GRAD,-3.07707,-1.16672,-0.67591,-6.26323,-2.29919,0.05723 +MEG_091,MEG_GRAD,-2.81455,-1.64764,0.19622,-5.75085,-3.31563,0.94961 +MEG_115,MEG_GRAD,-3.20059,-0.58777,0.15614,-6.53962,-1.15004,0.86771 +MEG_037,MEG_GRAD,-1.11155,-3.07561,0.25023,-2.27119,-6.23333,1.05996 +MEG_067,MEG_GRAD,-2.08904,-2.51166,0.2289,-4.26844,-5.08104,1.01638 +MEG_079,MEG_GRAD,-2.51137,-2.1514,-0.63867,-5.10885,-4.30296,0.13301 +MEG_093,MEG_GRAD,-2.8532,-1.73435,-1.50591,-5.7542,-3.37531,-0.57691 +MEG_051,MEG_GRAD,-1.61407,-2.7848,1.0907,-3.27306,-5.61852,2.18127 +MEG_065,MEG_GRAD,-1.93511,-2.30617,1.94967,-4.00461,-4.7725,3.21696 +REF_014,UNUSED,,,,,, +MEG_053,MEG_GRAD,-1.64275,-2.88336,-0.61098,-3.33826,-5.79135,0.1893 +MEG_039,MEG_GRAD,-1.37821,4.03301,0.38766,-2.98972,7.09471,0.3625 +MEG_041,MEG_GRAD,-1.59926,3.67934,1.66789,-3.46787,6.31662,2.90266 +MEG_055,MEG_GRAD,-2.06278,3.53364,0.8475,-4.47296,6.00069,1.12372 +MEG_069,MEG_GRAD,-2.43321,2.88136,1.45931,-5.27622,4.58626,2.45038 +MEG_027,MEG_GRAD,-1.02514,3.32279,2.63742,-2.22293,5.54346,5.00502 +MEG_025,MEG_GRAD,-0.92333,4.17235,1.20548,-2.00217,7.38566,1.89996 +MEG_057,MEG_GRAD,-1.84667,3.00588,2.29955,-4.00435,4.85628,4.27238 +REF_015,UNUSED,,,,,, +MEG_083,MEG_GRAD,-2.81067,2.32514,1.52142,-6.13327,3.15736,2.01067 +MEG_095,MEG_GRAD,-2.85632,2.16654,0.82155,-6.24599,2.85761,0.88605 +MEG_117,MEG_GRAD,-3.14455,0.87829,-0.52294,-6.53422,1.56936,-0.45844 +MEG_109,MEG_GRAD,-3.0226,1.3925,0.37679,-6.41227,2.08357,0.44129 +MEG_107,MEG_GRAD,-2.7791,2.44789,0.19401,-6.01824,3.66345,0.23867 +MEG_111,MEG_GRAD,-3.20059,0.54013,0.11348,-6.53962,1.15454,0.78055 +MEG_097,MEG_GRAD,-3.04326,1.22292,1.10768,-6.3884,1.94226,1.62169 +MEG_081,MEG_GRAD,-2.54021,2.92425,0.68688,-5.5195,4.68347,0.71098 +REF_001,REF_MAG,-2.26079604,3.98626183,5.04439808,-2.20703425,3.92437924,4.93090704 +REF_002,REF_MAG,1.93013445,4.03046866,5.17689263,1.8763992,3.96852956,5.06341985 +REF_004,REF_MAG,1.70031266,4.21202221,5.57217923,1.57144014,4.22797498,5.62449924 +REF_012,REF_GRAD,4.64675,-0.89642,-0.43802,6.03162,-1.01804,-0.22614 +REF_006,REF_MAG,2.07781,3.83073028,5.60154279,2.08802749,3.70619491,5.66468189 +REF_008,REF_GRAD,4.50056,0.78066,1.76423,5.88573,0.92199,1.96135 +REF_010,REF_GRAD,4.31926,2.18698,-0.37055,5.69806,2.46181,-0.34022 +MEG_094,REF_GRAD,2.85632,2.16654,0.82155,6.24599,2.85761,0.88605 +REF_016,UNUSED,,,,,, +REF_003,REF_MAG,-2.73073962,4.07852721,5.1569653,-2.8596759,4.06162797,5.1051015 +REF_017,UNUSED,,,,,, +REF_011,REF_GRAD,-4.64675,-0.89642,-0.43802,-6.03162,-1.01804,-0.22614 +REF_009,REF_GRAD,-4.31926,2.18698,-0.37055,-5.69806,2.46181,-0.34022 +REF_007,REF_GRAD,-4.50056,0.78066,1.76423,-5.88573,0.92199,1.96135 +REF_018,UNUSED,,,,,, +REF_005,REF_MAG,-2.4058382,3.78665997,5.47001894,-2.41506358,3.66222139,5.53350068 +MEG_090,MEG_GRAD,2.81455,-1.64764,0.19622,5.75085,-3.31563,0.94961 +MEG_088,MEG_GRAD,2.60717,-1.50525,1.94967,5.39539,-3.11503,3.21696 +MEG_102,MEG_GRAD,3.03294,-1.09506,1.02679,6.1503,-2.19202,2.05167 +MEG_122,MEG_GRAD,3.24454,-0.65992,-1.54654,6.63007,-1.24165,-1.13258 +MEG_114,MEG_GRAD,3.20059,-0.58777,0.15614,6.53962,-1.15004,0.86771 +MEG_104,MEG_GRAD,3.07159,-1.18176,-0.67534,6.25756,-2.31475,0.05782 +MEG_120,MEG_GRAD,3.24454,0.48346,-1.58979,6.63007,1.0948,-1.22094 +MEG_118,MEG_GRAD,3.27163,-0.06408,-0.71761,6.66217,-0.03828,-0.02828 +MEG_106,MEG_GRAD,2.7791,2.44789,0.19401,6.01824,3.66345,0.23867 +MEG_082,MEG_GRAD,2.81067,2.32514,1.52142,6.13327,3.15736,2.01067 +MEG_110,MEG_GRAD,3.20059,0.54013,0.11348,6.53962,1.15454,0.78055 +MEG_116,MEG_GRAD,3.14455,0.87829,-0.52294,6.53422,1.56936,-0.45844 +MEG_096,MEG_GRAD,3.04326,1.22292,1.10768,6.3884,1.94226,1.62169 +MEG_080,MEG_GRAD,2.54021,2.92425,0.68688,5.5195,4.68347,0.71098 +MEG_108,MEG_GRAD,3.0226,1.3925,0.37679,6.41227,2.08357,0.44129 +REF_019,UNUSED,,,,,, +MEG_009,MEG_GRAD,-0.48824,4.32904,0.13976,-1.05817,7.74156,0.10133 +MEG_003,MEG_GRAD,0,3.44805,2.77097,0,5.81508,5.29461 +MEG_010,MEG_GRAD,0.51257,3.97032,2.03007,1.11147,6.94759,3.68802 +MEG_012,MEG_GRAD,0.51257,2.67525,3.24478,1.11147,4.13933,6.32201 +MEG_004,MEG_GRAD,0,4.3528,1.03622,0,7.77696,1.53295 +MEG_011,MEG_GRAD,-0.51257,3.97032,2.03007,-1.11147,6.94759,3.68802 +MEG_008,MEG_GRAD,0.48824,4.32904,0.13976,1.05817,7.74156,0.10133 +MEG_013,MEG_GRAD,-0.51257,2.67525,3.24478,-1.11147,4.13933,6.32201 +MEG_024,MEG_GRAD,0.92333,4.17235,1.20548,2.00217,7.38566,1.89996 +REF_020,UNUSED,,,,,, +MEG_068,MEG_GRAD,2.43321,2.88136,1.45931,5.27622,4.58626,2.45038 +MEG_026,MEG_GRAD,1.02514,3.32279,2.63742,2.22293,5.54346,5.00502 +MEG_038,MEG_GRAD,1.37821,4.03301,0.38766,2.98972,7.09471,0.3625 +MEG_040,MEG_GRAD,1.59926,3.67934,1.66789,3.46787,6.31662,2.90266 +MEG_054,MEG_GRAD,2.06278,3.53364,0.8475,4.47296,6.00069,1.12372 +MEG_056,MEG_GRAD,1.84667,3.00588,2.29955,4.00435,4.85628,4.27238 +MEG_058,MEG_GRAD,2.00892,1.56358,2.88668,4.25593,2.49543,5.34722 +MEG_042,MEG_GRAD,1.59926,2.33243,2.93122,3.46787,3.39595,5.64209 +MEG_028,MEG_GRAD,0.90968,1.7238,3.47337,1.93358,2.72985,6.62156 +MEG_070,MEG_GRAD,2.43321,2.17533,2.12153,5.27622,3.05529,3.88634 +REF_021,UNUSED,,,,,, +MEG_072,MEG_GRAD,2.38955,0.86972,2.76491,4.94504,1.79985,4.90406 +MEG_044,MEG_GRAD,1.61144,0.93037,3.41137,3.33479,1.92534,6.24186 +MEG_084,MEG_GRAD,2.78632,1.40783,1.84839,5.89386,2.21359,3.13893 +MEG_046,MEG_GRAD,1.61144,-0.93037,3.41137,3.33479,-1.92534,6.24186 +MEG_098,MEG_GRAD,2.96476,0.52277,1.94967,6.13541,1.08184,3.21696 +MEG_060,MEG_GRAD,1.8607,0,3.41137,3.85068,0,6.24186 +MEG_100,MEG_GRAD,2.96476,-0.52277,1.94967,6.13541,-1.08184,3.21696 +MEG_074,MEG_GRAD,2.38955,-0.86972,2.76491,4.94504,-1.79985,4.90406 +MEG_086,MEG_GRAD,2.5429,0,2.76491,5.2624,0,4.90406 +MEG_062,MEG_GRAD,1.94798,-1.63455,2.76491,4.03123,-3.38261,4.90406 +MEG_112,MEG_GRAD,3.22769,0.00807,0.98507,6.5452,0.04494,1.96707 +MEG_016,MEG_GRAD,0.50538,-0.87535,3.83752,0.89368,-1.5479,7.20924 +MEG_031,MEG_GRAD,-1.01076,0,3.83752,-1.78736,0,7.20924 +MEG_015,MEG_GRAD,-0.50538,0.87535,3.83752,-0.89368,1.5479,7.20924 +MEG_001,MEG_GRAD,0,0,4,0,0,7.46 +MEG_002,MEG_GRAD,0,1.80611,3.59215,0,2.82922,6.89743 +MEG_017,MEG_GRAD,-0.50538,-0.87535,3.83752,-0.89368,-1.5479,7.20924 +MEG_014,MEG_GRAD,0.50538,0.87535,3.83752,0.89368,1.5479,7.20924 +MEG_030,MEG_GRAD,1.01076,0,3.83752,1.78736,0,7.20924 +MEG_050,MEG_GRAD,1.61362,-2.78506,1.09071,3.27214,-5.61905,2.18129 +MEG_064,MEG_GRAD,1.93511,-2.30617,1.94967,4.00461,-4.7725,3.21696 +MEG_076,MEG_GRAD,2.47238,-2.0651,1.06348,5.01358,-4.1591,2.12607 +MEG_078,MEG_GRAD,2.50107,-2.16367,-0.6382,5.0982,-4.31565,0.13349 +MEG_066,MEG_GRAD,2.08904,-2.51166,0.2289,4.26844,-5.08104,1.01638 +MEG_036,MEG_GRAD,1.11155,-3.07561,0.25023,2.27119,-6.23333,1.05996 +MEG_052,MEG_GRAD,1.62888,-2.89137,-0.61068,3.32391,-5.79963,0.18962 +MEG_092,MEG_GRAD,2.8532,-1.73435,-1.50591,5.7542,-3.37531,-0.57691 diff --git a/mne-python/source/mne/io/artemis123/resources/Artemis123_mneLoc.csv b/mne-python/source/mne/io/artemis123/resources/Artemis123_mneLoc.csv new file mode 100644 index 0000000000000000000000000000000000000000..cdad771a1c3777e0677681541a06f8a71e2dffb5 --- /dev/null +++ b/mne-python/source/mne/io/artemis123/resources/Artemis123_mneLoc.csv @@ -0,0 +1,144 @@ +MEG_001,0.0,0.0,0.10160000191,1.0,-0.0,-0.0,-0.0,1.0,-0.0,0.0,0.0,1.0 +MEG_002,0.0,0.0458751948625,0.0912406117153,1.0,-0.0,-0.0,-0.0,0.955282042035,-0.295696161906,0.0,0.295696161906,0.955282042035 +MEG_003,0.0,0.0875804716465,0.0703826393232,1.0,-0.0,-0.0,-0.0,0.729376031116,-0.684113006186,0.0,0.684113006186,0.729376031116 +MEG_004,0.0,0.110561122079,0.0263199884948,1.0,-0.0,-0.0,-0.0,0.143563509474,-0.989641106032,0.0,0.989641106032,0.143563509474 +MEG_005,0.0,-0.0472625428885,0.086648799629,1.0,0.0,-0.0,0.0,0.818061560022,0.575130666904,0.0,-0.575130666904,0.818061560022 +MEG_006,0.0,-0.0764667014376,0.049521618931,1.0,0.0,-0.0,0.0,0.366268930876,0.930509038255,0.0,-0.930509038255,0.366268930876 +MEG_007,0.0,-0.0830953395622,0.00654405612303,1.0,0.0,-0.0,0.0,0.236260571358,0.971689735678,0.0,-0.971689735678,0.236260571358 +MEG_008,0.0124012962331,0.109957618067,0.00354990406674,0.972562667953,-0.164284112711,-0.164719723212,-0.164284112711,0.0163303909087,-0.986277875978,0.164719723212,0.986277875978,-0.0111069411385 +MEG_009,-0.0124012962331,0.109957618067,0.00354990406674,0.972562667953,0.164284112711,0.164719723212,0.164284112711,0.0163303909087,-0.986277875978,-0.164719723212,0.986277875978,-0.0111069411385 +MEG_010,0.0130192782448,0.100846129896,0.0515637789694,0.979744824976,-0.100693145673,-0.173092369408,-0.100693145673,0.499431154085,-0.860482081594,0.173092369408,0.860482081594,0.479175979061 +MEG_011,-0.0130192782448,0.100846129896,0.0515637789694,0.979744824976,0.100693145673,0.173092369408,0.100693145673,0.499431154085,-0.860482081594,-0.173092369408,0.860482081594,0.479175979061 +MEG_012,0.0130192782448,0.0679513512775,0.0824174135494,0.984142307767,-0.038765954324,-0.17309280415,-0.038765954324,0.905232161619,-0.423145287527,0.17309280415,0.423145287527,0.889374469386 +MEG_013,-0.0130192782448,0.0679513512775,0.0824174135494,0.984142307767,0.038765954324,0.17309280415,0.038765954324,0.905232161619,-0.423145287527,-0.17309280415,0.423145287527,0.889374469386 +MEG_014,0.0128366522413,0.022233890418,0.0974730098325,0.993621350642,-0.0110480572384,-0.112225451567,-0.0110480572384,0.980864355149,-0.194378643965,0.112225451567,0.194378643965,0.974485705791 +MEG_015,-0.0128366522413,0.022233890418,0.0974730098325,0.993621350642,0.0110480572384,0.112225451567,0.0110480572384,0.980864355149,-0.194378643965,-0.112225451567,0.194378643965,0.974485705791 +MEG_016,0.0128366522413,-0.022233890418,0.0974730098325,0.993621350642,0.0110480572384,-0.112225451567,0.0110480572384,0.980864355149,0.194378643965,0.112225451567,-0.194378643965,0.974485705791 +MEG_017,-0.0128366522413,-0.022233890418,0.0974730098325,0.993621350642,-0.0110480572384,0.112225451567,-0.0110480572384,0.980864355149,0.194378643965,-0.112225451567,-0.194378643965,0.974485705791 +MEG_018,0.0112158782109,-0.0636084591958,0.0702287153203,0.988488638046,0.0652835409099,-0.136485426846,0.0652835409099,0.629762253104,0.774039768908,0.136485426846,-0.774039768908,0.61825089115 +MEG_019,-0.0112158782109,-0.0636084591958,0.0702287153203,0.988488638046,-0.0652835409099,0.136485426846,-0.0652835409099,0.629762253104,0.774039768908,-0.136485426846,-0.774039768908,0.61825089115 +MEG_020,0.0142295882675,-0.0804694875128,0.0280718265278,0.979010049739,0.117656650617,-0.166421858768,0.117656650617,0.340489745704,0.93285778425,0.166421858768,-0.93285778425,0.319499795443 +MEG_021,-0.0142427962678,-0.0804672015128,0.0280718265278,0.978972050612,-0.117759654311,0.166572470526,-0.117759654311,0.340528364062,0.932830690472,-0.166572470526,-0.932830690472,0.319500414673 +MEG_022,0.0142295882675,-0.0832380875649,-0.0151406862846,0.976588506526,0.131701883642,-0.170086750705,0.131701883642,0.259108088321,0.956826845574,0.170086750705,-0.956826845574,0.235696594848 +MEG_023,-0.0146304002751,-0.0831674755635,-0.0151434802847,0.976546368958,-0.131816629327,0.170239729521,-0.131816629327,0.259149948413,0.956799707604,-0.170239729521,-0.956799707604,0.235696317371 +MEG_024,0.0234525824409,0.105977691992,0.0306191925756,0.919030275794,-0.241167202261,-0.311803997292,-0.241167202261,0.281686827798,-0.928703888007,0.311803997292,0.928703888007,0.200717103592 +MEG_025,-0.0234525824409,0.105977691992,0.0306191925756,0.919030275794,0.241167202261,0.311803997292,0.241167202261,0.281686827798,-0.928703888007,-0.311803997292,0.928703888007,0.200717103592 +MEG_026,0.0260385564895,0.0843988675867,0.0669904692594,0.928846648352,-0.131916373824,-0.346181995721,-0.131916373824,0.755430639878,-0.641811980763,0.346181995721,0.641811980763,0.68427728823 +MEG_027,-0.0260385564895,0.0843988675867,0.0669904692594,0.928846648352,0.131916373824,0.346181995721,0.131916373824,0.755430639878,-0.641811980763,-0.346181995721,0.641811980763,0.68427728823 +MEG_028,0.0231058724344,0.0437845208231,0.0882235996586,0.954148215535,-0.0450524345745,-0.295924755521,-0.0450524345745,0.955732979975,-0.290765797726,0.295924755521,0.290765797726,0.90988119551 +MEG_029,-0.0231330504349,0.0437862988232,0.0882142016584,0.954036318954,0.0451068389737,0.296277024411,0.0451068389737,0.955734030088,-0.290753911081,-0.296277024411,0.290753911081,0.909770349043 +MEG_030,0.0256733044827,0.0,0.0974730098325,0.974485414074,-0.0,-0.224450835944,-0.0,1.0,-0.0,0.224450835944,0.0,0.974485414074 +MEG_031,-0.0256733044827,0.0,0.0974730098325,0.974485414074,0.0,0.224450835944,0.0,1.0,-0.0,-0.224450835944,0.0,0.974485414074 +MEG_032,0.0236313984443,-0.0409305767695,0.086648799629,0.954515845737,0.078781387629,-0.287563894118,0.078781387629,0.863545730655,0.498078572146,0.287563894118,-0.498078572146,0.818061576392 +MEG_033,-0.0236313984443,-0.0409305767695,0.086648799629,0.954515845737,-0.078781387629,0.287563894118,-0.078781387629,0.863545730655,0.498078572146,-0.287563894118,-0.498078572146,0.818061576392 +MEG_034,0.0261531104917,-0.0718550773509,0.049521618931,0.925866960833,0.203678027441,-0.318254036858,0.203678027441,0.440401481873,0.874392243734,0.318254036858,-0.874392243734,0.366268442706 +MEG_035,-0.0261531104917,-0.0718550773509,0.049521618931,0.925866960833,-0.203678027441,0.318254036858,-0.203678027441,0.440401481873,0.874392243734,-0.318254036858,-0.874392243734,0.366268442706 +MEG_036,0.0282333705308,-0.0781204954687,0.00635584211949,0.908973236603,0.247867468623,-0.335155744599,0.247867468623,0.325052548187,0.91263495381,0.335155744599,-0.91263495381,0.23402578479 +MEG_037,-0.0282333705308,-0.0781204954687,0.00635584211949,0.908973236603,-0.247867468623,0.335155744599,-0.247867468623,0.325052548187,0.91263495381,-0.335155744599,-0.91263495381,0.23402578479 +MEG_038,0.0350065346581,0.102438455926,0.00984656418512,0.781484001521,-0.415157481208,-0.465754249753,-0.415157481208,0.211244323513,-0.884884230609,0.465754249753,0.884884230609,-0.00727167496558 +MEG_039,-0.0350065346581,0.102438455926,0.00984656418512,0.781484001521,0.415157481208,0.465754249753,0.415157481208,0.211244323513,-0.884884230609,-0.465754249753,0.884884230609,-0.00727167496558 +MEG_040,0.0406212047637,0.093455237757,0.0423644067965,0.785045408535,-0.303378150058,-0.540060556425,-0.303378150058,0.57182444299,-0.762219459517,0.540060556425,0.762219459517,0.356869851524 +MEG_041,-0.0406212047637,0.093455237757,0.0423644067965,0.785045408535,0.303378150058,0.540060556425,0.303378150058,0.57182444299,-0.762219459517,-0.540060556425,0.762219459517,0.356869851524 +MEG_042,0.0406212047637,0.0592437231138,0.0744529893997,0.836463385382,-0.0930769183398,-0.540060822675,-0.0930769183398,0.947025241119,-0.307375795983,0.540060822675,0.307375795983,0.7834886265 +MEG_043,-0.0406212047637,0.0592437231138,0.0744529893997,0.836463385382,0.0930769183398,0.540060822675,0.0930769183398,0.947025241119,-0.307375795983,-0.540060822675,0.307375795983,0.7834886265 +MEG_044,0.0409305767695,0.0236313984443,0.086648799629,0.863545730655,-0.078781387629,-0.498078572146,-0.078781387629,0.954515845737,-0.287563894118,0.498078572146,0.287563894118,0.818061576392 +MEG_045,-0.0409305767695,0.0236313984443,0.086648799629,0.863545730655,0.078781387629,0.498078572146,0.078781387629,0.954515845737,-0.287563894118,-0.498078572146,0.287563894118,0.818061576392 +MEG_046,0.0409305767695,-0.0236313984443,0.086648799629,0.863545730655,0.078781387629,-0.498078572146,0.078781387629,0.954515845737,0.287563894118,0.498078572146,-0.287563894118,0.818061576392 +MEG_047,-0.0409305767695,-0.0236313984443,0.086648799629,0.863545730655,-0.078781387629,0.498078572146,-0.078781387629,0.954515845737,0.287563894118,-0.498078572146,-0.287563894118,0.818061576392 +MEG_048,0.0322948306071,-0.0559363890516,0.0702287153203,0.904562399003,0.165302346745,-0.392991094644,0.165302346745,0.713688676641,0.680678784005,0.392991094644,-0.680678784005,0.618251075645 +MEG_049,-0.0322948306071,-0.0559363890516,0.0702287153203,0.904562399003,-0.165302346745,0.392991094644,-0.165302346745,0.713688676641,0.680678784005,-0.392991094644,-0.680678784005,0.618251075645 +MEG_050,0.0409859487705,-0.0707405253299,0.0277040345208,0.825297111533,0.298522923381,-0.479341988471,0.298522923381,0.489900043633,0.819073874241,0.479341988471,-0.819073874241,0.315197155166 +MEG_051,-0.0409973787708,-0.0707339213298,0.0277037805208,0.825197788666,-0.298579570884,0.479477683976,-0.298579570884,0.489996382374,0.818995595294,-0.479477683976,-0.818995595294,0.31519417104 +MEG_052,0.0413735527778,-0.0734407993807,-0.0155112722916,0.805087785644,0.334422043575,-0.489893411036,0.334422043575,0.426212956438,0.840538168399,0.489893411036,-0.840538168399,0.231300742083 +MEG_053,-0.0417258507844,-0.0732373453769,-0.0155188922918,0.804976833568,-0.334486625117,0.490031626568,-0.334486625117,0.426317886079,0.840459253996,-0.490031626568,-0.840459253996,0.231294719647 +MEG_054,0.052394612985,0.0897544576874,0.0215265004047,0.550644162251,-0.459958724875,-0.696583791076,-0.459958724875,0.529188204946,-0.713020206696,0.696583791076,0.713020206696,0.0798323671971 +MEG_055,-0.052394612985,0.0897544576874,0.0215265004047,0.550644162251,0.459958724875,0.696583791076,0.459958724875,0.529188204946,-0.713020206696,-0.696583791076,0.713020206696,0.0798323671971 +MEG_056,0.0469054188818,0.0763493534354,0.0584085710981,0.752331243475,-0.212397698952,-0.623606380317,-0.212397698952,0.817850328992,-0.534797210957,0.623606380317,0.534797210957,0.570181572467 +MEG_057,-0.0469054188818,0.0763493534354,0.0584085710981,0.752331243475,0.212397698952,0.623606380317,0.212397698952,0.817850328992,-0.534797210957,-0.623606380317,0.534797210957,0.570181572467 +MEG_058,0.0510265689593,0.0397149327466,0.0733216733784,0.75352606525,-0.102214380931,-0.649423351381,-0.102214380931,0.95761101603,-0.269320185484,0.649423351381,0.269320185484,0.71113708128 +MEG_059,-0.0502099589439,0.0397642087476,0.0740382073919,0.762632097113,0.100407167247,0.638991928915,0.100407167247,0.957527538003,-0.27029505125,-0.638991928915,0.27029505125,0.720159635116 +MEG_060,0.0472617808885,0.0,0.086648799629,0.818057480605,-0.0,-0.575136469394,-0.0,1.0,-0.0,0.575136469394,0.0,0.818057480605 +MEG_061,-0.0472625428885,0.0,0.086648799629,0.818061560022,0.0,0.575130666904,0.0,1.0,-0.0,-0.575130666904,0.0,0.818061560022 +MEG_062,0.0494786929302,-0.0415175707805,0.0702287153203,0.775981248219,0.187974664221,-0.602095198473,0.187974664221,0.842270014862,0.505219504448,0.602095198473,-0.505219504448,0.618251263081 +MEG_063,-0.0494786929302,-0.0415175707805,0.0702287153203,0.775981248219,-0.187974664221,0.602095198473,-0.187974664221,0.842270014862,0.505219504448,-0.602095198473,-0.505219504448,0.618251263081 +MEG_064,0.0491517949241,-0.0585767191012,0.049521618931,0.738156783089,0.312052080775,-0.598120441436,0.312052080775,0.628111423833,0.712811011513,0.598120441436,-0.712811011513,0.366268206923 +MEG_065,-0.0491517949241,-0.0585767191012,0.049521618931,0.738156783089,-0.312052080775,0.598120441436,-0.312052080775,0.628111423833,0.712811011513,-0.598120441436,-0.712811011513,0.366268206923 +MEG_066,0.0530616169976,-0.0637961651994,0.0058140601093,0.676804202704,0.381028180993,-0.629883796022,0.381028180993,0.550790957291,0.742594671847,0.629883796022,-0.742594671847,0.227595159994 +MEG_067,-0.0530616169976,-0.0637961651994,0.0058140601093,0.676804202704,-0.381028180993,0.629883796022,-0.381028180993,0.550790957291,0.742594671847,-0.629883796022,-0.742594671847,0.227595159994 +MEG_068,0.0618035351619,0.0731865453759,0.0370664746968,0.475173275464,-0.314728784866,-0.821678860785,-0.314728784866,0.811263025695,-0.492745466865,0.821678860785,0.492745466865,0.286436301159 +MEG_069,-0.0618035351619,0.0731865453759,0.0370664746968,0.475173275464,0.314728784866,0.821678860785,0.314728784866,0.811263025695,-0.492745466865,-0.821678860785,0.492745466865,0.286436301159 +MEG_070,0.0618035351619,0.0552533830388,0.0538868630131,0.552894017073,-0.138386914129,-0.821679540869,-0.138386914129,0.957166893906,-0.254323807789,0.821679540869,0.254323807789,0.510060910979 +MEG_071,-0.0618035351619,0.0552533830388,0.0538868630131,0.552894017073,0.138386914129,0.821679540869,0.138386914129,0.957166893906,-0.254323807789,-0.821679540869,0.254323807789,0.510060910979 +MEG_072,0.0606945711411,0.0220908884153,0.0702287153203,0.662907428432,-0.12269267874,-0.738579885939,-0.12269267874,0.955343146999,-0.268823321284,0.738579885939,0.268823321284,0.61825057543 +MEG_073,-0.0606945711411,0.0220908884153,0.0702287153203,0.662907428432,0.12269267874,0.738579885939,0.12269267874,0.955343146999,-0.268823321284,-0.738579885939,0.268823321284,0.61825057543 +MEG_074,0.0606945711411,-0.0220908884153,0.0702287153203,0.662907428432,0.12269267874,-0.738579885939,0.12269267874,0.955343146999,0.268823321284,0.738579885939,-0.268823321284,0.61825057543 +MEG_075,-0.0606945711411,-0.0220908884153,0.0702287153203,0.662907428432,-0.12269267874,0.738579885939,-0.12269267874,0.955343146999,0.268823321284,-0.738579885939,-0.268823321284,0.61825057543 +MEG_076,0.0627984531806,-0.0524535409861,0.0270123925078,0.587320034467,0.340056606259,-0.73444991773,0.340056606259,0.719786504995,0.605201529878,0.73444991773,-0.605201529878,0.307106539462 +MEG_077,-0.0628070891808,-0.0524433809859,0.0270118845078,0.587208379993,-0.340036516337,0.734548491268,-0.340036516337,0.719895397972,0.605083286446,-0.734548491268,-0.605083286446,0.307103777966 +MEG_078,0.0635271791943,-0.0549572190332,-0.0162102803048,0.539322307512,0.381717195782,-0.750615368258,0.381717195782,0.683709413476,0.621959339803,0.750615368258,-0.621959339803,0.223031720988 +MEG_079,-0.0637887991992,-0.0546455610273,-0.016222218305,0.539196876386,-0.381695169412,0.750716675014,-0.381695169412,0.683831999207,0.621838077403,-0.750716675014,-0.621838077403,0.223028875593 +MEG_080,0.064521335213,0.0742759513964,0.017446752328,0.263693428198,-0.434776489447,-0.861066304154,-0.434776489447,0.743271888347,-0.508444986421,0.861066304154,0.508444986421,0.00696531654525 +MEG_081,-0.064521335213,0.0742759513964,0.017446752328,0.263693428198,0.434776489447,0.861066304154,0.434776489447,0.743271888347,-0.508444986421,-0.861066304154,0.508444986421,0.00696531654525 +MEG_082,0.0713910193422,0.0590585571103,0.0386440687265,0.192087187177,-0.202359959395,-0.960287956478,-0.202359959395,0.949314390716,-0.240525745844,0.960287956478,0.240525745844,0.141401577893 +MEG_083,-0.0713910193422,0.0590585571103,0.0386440687265,0.192087187177,0.202359959395,0.960287956478,0.202359959395,0.949314390716,-0.240525745844,-0.960287956478,0.240525745844,0.141401577893 +MEG_084,0.0707725293305,0.0357588826723,0.0469491068826,0.412488973038,-0.15233685973,-0.89813491653,-0.15233685973,0.960500283795,-0.232879123147,0.89813491653,0.232879123147,0.372989256833 +MEG_085,-0.0707722753305,0.0357588826723,0.0469491068826,0.412487827635,0.152336666507,0.898135475354,0.152336666507,0.960500461005,-0.232878518647,-0.898135475354,0.232878518647,0.37298828864 +MEG_086,0.0645896612143,0.0,0.0702287153203,0.618250335472,-0.0,-0.785981248306,-0.0,1.0,-0.0,0.785981248306,0.0,0.618250335472 +MEG_087,-0.0645896612143,0.0,0.0702287153203,0.618250335472,0.0,0.785981248306,0.0,1.0,-0.0,-0.785981248306,0.0,0.618250335472 +MEG_088,0.066222119245,-0.0382333507188,0.049521618931,0.524701809918,0.274413611706,-0.80584438968,0.274413611706,0.841567184852,0.46525460029,0.80584438968,-0.46525460029,0.36626899477 +MEG_089,-0.066222119245,-0.0382333507188,0.049521618931,0.524701809918,-0.274413611706,0.80584438968,-0.274413611706,0.841567184852,0.46525460029,-0.80584438968,-0.46525460029,0.36626899477 +MEG_090,0.071489571344,-0.0418500567868,0.0049839880937,0.408585986848,0.335957722235,-0.848640029826,0.335957722235,0.809156380101,0.482077132224,0.848640029826,-0.482077132224,0.217742366948 +MEG_091,-0.071489571344,-0.0418500567868,0.0049839880937,0.408585986848,-0.335957722235,0.848640029826,-0.335957722235,0.809156380101,0.482077132224,-0.848640029826,-0.482077132224,0.217742366948 +MEG_092,0.0724712813625,-0.0440524908282,-0.0382501147191,0.445815918958,0.313476011591,-0.83843959625,0.313476011591,0.822681283702,0.474266059932,0.83843959625,-0.474266059932,0.26849720266 +MEG_093,-0.0724712813625,-0.0440524908282,-0.0382501147191,0.445815918958,-0.313476011591,0.83843959625,-0.313476011591,0.822681283702,0.474266059932,-0.83843959625,-0.474266059932,0.26849720266 +MEG_094,0.0725505293639,0.0550301170346,0.0208673703923,0.0578041209796,-0.192090470788,-0.979673381608,-0.192090470788,0.96083749697,-0.199731208002,0.979673381608,0.199731208002,0.0186416179491 +MEG_095,-0.0725505293639,0.0550301170346,0.0208673703923,0.0578041209796,0.192090470788,0.979673381608,0.192090470788,0.96083749697,-0.199731208002,-0.979673381608,0.199731208002,0.0186416179491 +MEG_096,0.0772988054532,0.031062168584,0.0281350725289,0.186190165142,-0.175001933135,-0.966802743999,-0.175001933135,0.962367527045,-0.20790157837,0.966802743999,0.20790157837,0.148557692187 +MEG_097,-0.0772988054532,0.031062168584,0.0281350725289,0.186190165142,0.175001933135,0.966802743999,0.175001933135,0.962367527045,-0.20790157837,-0.966802743999,0.20790157837,0.148557692187 +MEG_098,0.0753049054157,0.0132783582496,0.049521618931,0.385377976058,-0.108374224505,-0.91637265511,-0.108374224505,0.980890739219,-0.1615808936,0.91637265511,0.1615808936,0.366268715277 +MEG_099,-0.0753049054157,0.0132783582496,0.049521618931,0.385377976058,0.108374224505,0.91637265511,0.108374224505,0.980890739219,-0.1615808936,-0.91637265511,0.1615808936,0.366268715277 +MEG_100,0.0753049054157,-0.0132783582496,0.049521618931,0.385377976058,0.108374224505,-0.91637265511,0.108374224505,0.980890739219,0.1615808936,0.91637265511,-0.1615808936,0.366268715277 +MEG_101,-0.0753049054157,-0.0132783582496,0.049521618931,0.385377976058,-0.108374224505,0.91637265511,-0.108374224505,0.980890739219,0.1615808936,-0.91637265511,-0.1615808936,0.366268715277 +MEG_102,0.0770366774483,-0.0278145245229,0.0260804664903,0.373752636547,0.220368615692,-0.900969832953,0.220368615692,0.922455039947,0.31704001718,0.900969832953,-0.31704001718,0.296207676495 +MEG_103,-0.0770412494484,-0.0278018245227,0.0260799584903,0.373679152588,-0.220281297547,0.901021665041,-0.220281297547,0.92252557096,0.31689544155,-0.901021665041,-0.31689544155,0.296204723548 +MEG_104,0.0780183874667,-0.0300167045643,-0.0171536363225,0.300373897506,0.24880001314,-0.920800779299,0.24880001314,0.911522102566,0.327453828799,0.920800779299,-0.327453828799,0.211896000073 +MEG_105,-0.0781575794694,-0.0296346885571,-0.0171681143228,0.300287289279,-0.248701776907,0.920855564169,-0.248701776907,0.911602900892,0.327303494098,-0.920855564169,-0.327303494098,0.211890190171 +MEG_106,0.0705891413271,0.0621764071689,0.00492785409264,0.134758903688,-0.324701145067,-0.936167295022,-0.324701145067,0.878148606143,-0.351317793345,0.936167295022,0.351317793345,0.0129075098315 +MEG_107,-0.0705891413271,0.0621764071689,0.00492785409264,0.134758903688,0.324701145067,0.936167295022,0.324701145067,0.878148606143,-0.351317793345,-0.936167295022,0.351317793345,0.0129075098315 +MEG_108,0.0767740414434,0.0353695006649,0.00957046617992,0.0578041209796,-0.192090470788,-0.979673381608,-0.192090470788,0.96083749697,-0.199731208002,0.979673381608,0.199731208002,0.0186416179491 +MEG_109,-0.0767740414434,0.0353695006649,0.00957046617992,0.0578041209796,0.192090470788,0.979673381608,0.192090470788,0.96083749697,-0.199731208002,-0.979673381608,0.199731208002,0.0186416179491 +MEG_110,0.0812949875283,0.0137193022579,0.00288239205419,0.219230938619,-0.143668166804,-0.965037436268,-0.143668166804,0.973563831901,-0.177575119486,0.965037436268,0.177575119486,0.192794770521 +MEG_111,-0.0812949875283,0.0137193022579,0.00288239205419,0.219230938619,0.143668166804,0.965037436268,0.143668166804,0.973563831901,-0.177575119486,-0.965037436268,0.177575119486,0.192794770521 +MEG_112,0.0819833275413,0.000204978003854,0.0250207784704,0.283903999524,-0.00795851694118,-0.958819681203,-0.00795851694118,0.999911550977,-0.010656088948,0.958819681203,0.010656088948,0.283815550501 +MEG_113,-0.0819833275413,0.000218440004107,0.0250202704704,0.283900779742,0.00807295557139,0.958819677859,0.00807295557139,0.999908989411,-0.0108092683826,-0.958819677859,0.0108092683826,0.283809769153 +MEG_114,0.0812949875283,-0.0149293582807,0.00396595607456,0.227559595527,0.130073723873,-0.965037541675,0.130073723873,0.978096467321,0.162505775197,0.965037541675,-0.162505775197,0.205656062847 +MEG_115,-0.0812949875283,-0.0149293582807,0.00396595607456,0.227559595527,-0.130073723873,0.965037541675,-0.130073723873,0.978096467321,0.162505775197,-0.965037541675,-0.162505775197,0.205656062847 +MEG_116,0.0798715715016,0.0223085664194,-0.0132826762497,0.0578041209796,-0.192090470788,-0.979673381608,-0.192090470788,0.96083749697,-0.199731208002,0.979673381608,0.199731208002,0.0186416179491 +MEG_117,-0.0798715715016,0.0223085664194,-0.0132826762497,0.0578041209796,0.192090470788,0.979673381608,0.192090470788,0.96083749697,-0.199731208002,-0.979673381608,0.199731208002,0.0186416179491 +MEG_118,0.0830994035623,-0.0016276320306,-0.0182272943427,0.199274663362,-0.00609304526277,-0.979924733508,-0.00609304526277,0.999953635537,-0.00745664647062,0.979924733508,0.00745664647062,0.199228298899 +MEG_119,-0.0830994035623,-0.00122097802295,-0.018242788343,0.199270871862,0.00622296522868,0.979924688091,0.00622296522868,0.999951637458,-0.00761560563545,-0.979924688091,0.00761560563545,0.19922250932 +MEG_120,0.0824113175493,0.0122798842309,-0.0403806667592,0.134815219165,-0.156230210311,-0.978476866394,-0.156230210311,0.971788825746,-0.176687859065,0.978476866394,0.176687859065,0.106604044912 +MEG_121,-0.0824113175493,0.0122798842309,-0.0403806667592,0.134812452063,0.156230709979,0.978477167862,0.156230709979,0.971788735519,-0.176687913503,-0.978477167862,0.176687913503,0.106601187582 +MEG_122,0.0824113175493,-0.0167619683151,-0.0392821167385,0.144888827116,0.146932333372,-0.978477448481,0.146932333372,0.974752861061,0.168130155723,0.978477448481,-0.168130155723,0.119641688177 +MEG_123,-0.0824113175493,-0.0167619683151,-0.0392821167385,0.144888827116,-0.146932333372,0.978477448481,-0.146932333372,0.974752861061,0.168130155723,-0.978477448481,-0.168130155723,0.119641688177 +REF_001,-0.0574242204956,0.101251052386,0.128127713641,0.221198761686,0.896440347728,-0.384012774259,0.896440347728,-0.0318490232173,0.442018486814,0.384012774259,-0.442018486814,-0.810650261531 +REF_002,0.0490254159517,0.102373905889,0.131493075274,0.222503034056,-0.896198721013,0.383823204472,-0.896198721013,-0.0330228704748,0.442422131545,-0.383823204472,-0.442422131545,-0.810519836419 +REF_003,-0.069360787652,0.103594593082,0.130986921083,-0.347310972431,-0.17658747001,0.920973373049,-0.17658747001,0.976855280479,0.120708849866,-0.920973373049,-0.120708849866,-0.370455691952 +REF_004,0.0431879423759,0.106985366145,0.141533355103,0.383166262537,0.0763561288473,0.920517982899,0.0763561288473,0.990548087664,-0.113948355026,-0.920517982899,0.113948355026,0.3737143502 +REF_005,-0.0611082914288,0.0961811650462,0.138938483688,0.997012450802,-0.040298218601,0.0658955728709,-0.040298218601,0.456428559123,0.888847019455,-0.0658955728709,-0.888847019455,0.453441009925 +REF_006,0.0527763749922,0.0973005509413,0.142279189541,0.99632914816,0.0447419955488,-0.072982068763,0.0447419955488,0.454664406796,0.889538324653,0.072982068763,-0.889538324653,0.450993554956 +REF_007,-0.114314226149,0.0198287643728,0.0448114428425,0.149033474209,0.0868247934117,0.985012933323,0.0868247934117,0.991141197071,-0.100501655296,-0.985012933323,0.100501655296,0.14017467128 +REF_008,0.114314226149,0.0198287643728,0.0448114428425,0.149033474209,-0.0868247934117,-0.985012933323,-0.0868247934117,0.991141197071,-0.100501655296,0.985012933323,0.100501655296,0.14017467128 +REF_009,-0.109709206063,0.0555492930443,-0.00941197017695,0.0589562738411,0.187574011648,0.98047954998,0.187574011648,0.96261171626,-0.195434576966,-0.98047954998,0.195434576966,0.0215679901007 +REF_010,0.109709206063,0.0555492930443,-0.00941197017695,0.0589562738411,-0.187574011648,-0.98047954998,-0.187574011648,0.96261171626,-0.195434576966,0.98047954998,0.195434576966,0.0215679901007 +REF_011,-0.118027452219,-0.0227690684281,-0.0111257082092,0.157170103306,-0.0740177576494,0.984793851615,-0.0740177576494,0.993499722223,0.0864851056297,-0.984793851615,-0.0864851056297,0.150669825529 +REF_012,0.118027452219,-0.0227690684281,-0.0111257082092,0.157170103306,0.0740177576494,-0.984793851615,0.0740177576494,0.993499722223,0.0864851056297,0.984793851615,-0.0864851056297,0.150669825529 +REF_013,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +REF_014,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +REF_015,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +REF_016,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +REF_017,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +REF_018,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +REF_019,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +REF_020,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 +REF_021,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0 diff --git a/mne-python/source/mne/io/artemis123/tests/__init__.py b/mne-python/source/mne/io/artemis123/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/artemis123/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/artemis123/tests/test_artemis123.py b/mne-python/source/mne/io/artemis123/tests/test_artemis123.py new file mode 100644 index 0000000000000000000000000000000000000000..e40913d0ed9ebbcdb81643aaf3fe749ceafc2353 --- /dev/null +++ b/mne-python/source/mne/io/artemis123/tests/test_artemis123.py @@ -0,0 +1,121 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_equal + +from mne import pick_types +from mne._fiff.constants import FIFF +from mne.datasets import testing +from mne.io import read_raw_artemis123 +from mne.io.artemis123.utils import _generate_mne_locs_file, _load_mne_locs +from mne.io.tests.test_raw import _test_raw_reader +from mne.utils._testing import assert_trans_allclose + +artemis123_dir = testing.data_path(download=False) / "ARTEMIS123" +short_HPI_dip_fname = ( + artemis123_dir / "Artemis_Data_2017-04-04-15h-44m-22s_Motion_Translation-z.bin" +) +dig_fname = artemis123_dir / "Phantom_040417_dig.pos" +short_hpi_1kz_fname = ( + artemis123_dir / "Artemis_Data_2017-04-14-10h-38m-59s_Phantom_1k_HPI_1s.bin" +) + + +# XXX this tol is way too high, but it's not clear which is correct +# (old or new) +def _assert_trans(actual, desired, dist_tol=0.017, angle_tol=5.0): + __tracebackhide__ = True + # To minimize diff, keep this trivial wrapper + assert_trans_allclose(actual, desired, dist_tol=dist_tol, angle_tol=angle_tol) + + +@testing.requires_testing_data +def test_artemis_reader(): + """Test reading raw Artemis123 files.""" + _test_raw_reader( + read_raw_artemis123, + input_fname=short_hpi_1kz_fname, + pos_fname=dig_fname, + add_head_trans=False, + verbose="error", + ) + + +@pytest.mark.timeout(60) +@testing.requires_testing_data +def test_dev_head_t(): + """Test dev_head_t computation for Artemis123.""" + # test a random selected point + raw = read_raw_artemis123(short_hpi_1kz_fname, preload=True, add_head_trans=False) + assert raw.info["dev_head_t"] is None + meg_picks = pick_types(raw.info, meg=True, eeg=False) + + # checked against matlab reader. + assert_allclose(raw[meg_picks[12]][0][0][123], 1.08239606023e-11) + + dev_head_t_1 = np.array( + [ + [9.713e-01, 2.340e-01, -4.164e-02, 1.302e-04], + [-2.371e-01, 9.664e-01, -9.890e-02, 1.977e-03], + [1.710e-02, 1.059e-01, 9.942e-01, -8.159e-03], + [0.0, 0.0, 0.0, 1.0], + ] + ) + + dev_head_t_2 = np.array( + [ + [9.890e-01, 1.475e-01, -8.090e-03, 4.997e-04], + [-1.476e-01, 9.846e-01, -9.389e-02, 1.962e-03], + [-5.888e-03, 9.406e-02, 9.955e-01, -1.610e-02], + [0.0, 0.0, 0.0, 1.0], + ] + ) + + expected_dev_hpi_rr = np.array( + [ + [-0.01579644, 0.06527367, 0.00152648], + [0.06666813, 0.0148956, 0.00545488], + [-0.06699212, -0.01732376, 0.0112027], + ] + ) + # test with head loc no digitization + raw = read_raw_artemis123(short_HPI_dip_fname, add_head_trans=True) + _assert_trans(raw.info["dev_head_t"]["trans"], dev_head_t_1) + assert_equal(raw.info["sfreq"], 5000.0) + + # test with head loc and digitization + with ( + pytest.warns(RuntimeWarning, match="consistency"), + pytest.warns(RuntimeWarning, match="Large difference"), + ): + raw = read_raw_artemis123( + short_HPI_dip_fname, add_head_trans=True, pos_fname=dig_fname + ) + _assert_trans(raw.info["dev_head_t"]["trans"], dev_head_t_1) + + # test cHPI localization.. + dev_hpi_rr = np.array( + [p["r"] for p in raw.info["dig"] if p["coord_frame"] == FIFF.FIFFV_COORD_DEVICE] + ) + # points should be within 0.1 mm (1e-4m) and within 1% + assert_allclose(dev_hpi_rr, expected_dev_hpi_rr, atol=1e-4, rtol=0.01) + + # test 1kz hpi head loc (different freq) + raw = read_raw_artemis123(short_hpi_1kz_fname, add_head_trans=True) + _assert_trans(raw.info["dev_head_t"]["trans"], dev_head_t_2) + assert_equal(raw.info["sfreq"], 1000.0) + + +def test_utils(tmp_path): + """Test artemis123 utils.""" + # make a tempfile + tmp_fname = tmp_path / "test_gen_mne_locs.csv" + _generate_mne_locs_file(tmp_fname) + installed_locs = _load_mne_locs() + generated_locs = _load_mne_locs(tmp_fname) + assert_equal(set(installed_locs.keys()), set(generated_locs.keys())) + for key in installed_locs.keys(): + assert_allclose(installed_locs[key], generated_locs[key], atol=1e-7) diff --git a/mne-python/source/mne/io/artemis123/utils.py b/mne-python/source/mne/io/artemis123/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..90df53ea1aae73eed262f2a5f06d5845d54518fb --- /dev/null +++ b/mne-python/source/mne/io/artemis123/utils.py @@ -0,0 +1,123 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op + +import numpy as np + +from ..._fiff._digitization import _artemis123_read_pos +from ...transforms import rotation3d_align_z_axis +from ...utils import logger + + +def _load_mne_locs(fname=None): + """Load MNE locs structure from file (if exists) or recreate it.""" + if not fname: + # find input file + resource_dir = op.join(op.dirname(op.abspath(__file__)), "resources") + fname = op.join(resource_dir, "Artemis123_mneLoc.csv") + + if not op.exists(fname): + raise OSError(f'MNE locs file "{fname}" does not exist') + + logger.info(f"Loading mne loc file {fname}") + locs = dict() + with open(fname) as fid: + for line in fid: + vals = line.strip().split(",") + locs[vals[0]] = np.array(vals[1::], np.float64) + + return locs + + +def _generate_mne_locs_file(output_fname): + """Generate mne coil locs and save to supplied file.""" + logger.info("Converting Tristan coil file to mne loc file...") + resource_dir = op.join(op.dirname(op.abspath(__file__)), "resources") + chan_fname = op.join(resource_dir, "Artemis123_ChannelMap.csv") + chans = _load_tristan_coil_locs(chan_fname) + + # compute a dict of loc structs + locs = {n: _compute_mne_loc(cinfo) for n, cinfo in chans.items()} + + # write it out to output_fname + with open(output_fname, "w") as fid: + for n in sorted(locs.keys()): + fid.write(f"{n},") + fid.write(",".join(locs[n].astype(str))) + fid.write("\n") + + +def _load_tristan_coil_locs(coil_loc_path): + """Load the Coil locations from Tristan CAD drawings.""" + channel_info = dict() + with open(coil_loc_path) as fid: + # skip 2 Header lines + fid.readline() + fid.readline() + for line in fid: + line = line.strip() + vals = line.split(",") + channel_info[vals[0]] = dict() + if vals[6]: + channel_info[vals[0]]["inner_coil"] = np.array(vals[2:5], np.float64) + channel_info[vals[0]]["outer_coil"] = np.array(vals[5:8], np.float64) + else: # nothing supplied + channel_info[vals[0]]["inner_coil"] = np.zeros(3) + channel_info[vals[0]]["outer_coil"] = np.zeros(3) + return channel_info + + +def _compute_mne_loc(coil_loc): + """Convert a set of coils to an mne Struct. + + Note input coil locations are in inches. + """ + loc = np.zeros(12) + if (np.linalg.norm(coil_loc["inner_coil"]) == 0) and ( + np.linalg.norm(coil_loc["outer_coil"]) == 0 + ): + return loc + + # channel location is inner coil location converted to meters From inches + loc[0:3] = coil_loc["inner_coil"] / 39.370078 + + # figure out rotation + z_axis = coil_loc["outer_coil"] - coil_loc["inner_coil"] + R = rotation3d_align_z_axis(z_axis) + loc[3:13] = R.T.reshape(9) + return loc + + +def _read_pos(fname): + """Read the .pos file and return positions as dig points.""" + nas, lpa, rpa, hpi, extra = None, None, None, None, None + with open(fname) as fid: + for line in fid: + line = line.strip() + if len(line) > 0: + parts = line.split() + # The lines can have 4 or 5 parts. First part is for the id, + # which can be an int or a string. The last three are for xyz + # coordinates. The extra part is for additional info + # (e.g. 'Pz', 'Cz') which is ignored. + if len(parts) not in [4, 5]: + continue + + if parts[0].lower() == "nasion": + nas = np.array([float(p) for p in parts[-3:]]) / 100.0 + elif parts[0].lower() == "left": + lpa = np.array([float(p) for p in parts[-3:]]) / 100.0 + elif parts[0].lower() == "right": + rpa = np.array([float(p) for p in parts[-3:]]) / 100.0 + elif "hpi" in parts[0].lower(): + if hpi is None: + hpi = list() + hpi.append(np.array([float(p) for p in parts[-3:]]) / 100.0) + else: + if extra is None: + extra = list() + extra.append(np.array([float(p) for p in parts[-3:]]) / 100.0) + + return _artemis123_read_pos(nas, lpa, rpa, hpi, extra) diff --git a/mne-python/source/mne/io/base.py b/mne-python/source/mne/io/base.py new file mode 100644 index 0000000000000000000000000000000000000000..b07a45e992734070bcdb87475699c7d9c161e9ec --- /dev/null +++ b/mne-python/source/mne/io/base.py @@ -0,0 +1,3306 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import shutil +from collections import defaultdict +from contextlib import nullcontext +from copy import deepcopy +from dataclasses import dataclass, field +from datetime import timedelta +from inspect import getfullargspec +from pathlib import Path + +import numpy as np + +from .._fiff.compensator import make_compensator, set_current_comp +from .._fiff.constants import FIFF +from .._fiff.meas_info import ( + ContainsMixin, + SetChannelsMixin, + _ensure_infos_match, + _unit2human, + write_meas_info, +) +from .._fiff.pick import ( + _picks_to_idx, + channel_type, + pick_channels, + pick_info, + pick_types, +) +from .._fiff.proj import ProjMixin, _proj_equal, activate_proj, setup_proj +from .._fiff.utils import _check_orig_units, _make_split_fnames +from .._fiff.write import ( + _NEXT_FILE_BUFFER, + _get_split_size, + end_block, + start_and_end_file, + start_block, + write_complex64, + write_complex128, + write_dau_pack16, + write_double, + write_float, + write_id, + write_int, + write_string, +) +from ..annotations import ( + Annotations, + _annotations_starts_stops, + _combine_annotations, + _handle_meas_date, + _sync_onset, + _write_annotations, +) +from ..channels.channels import InterpolationMixin, ReferenceMixin, UpdateChannelsMixin +from ..defaults import _handle_default +from ..event import concatenate_events, find_events +from ..filter import ( + FilterMixin, + _check_fun, + _check_resamp_noop, + _resamp_ratio_len, + _resample_stim_channels, + notch_filter, + resample, +) +from ..html_templates import _get_html_template +from ..parallel import parallel_func +from ..time_frequency.spectrum import Spectrum, SpectrumMixin, _validate_method +from ..time_frequency.tfr import RawTFR +from ..utils import ( + SizeMixin, + TimeMixin, + _arange_div, + _build_data_frame, + _check_fname, + _check_option, + _check_pandas_index_arguments, + _check_pandas_installed, + _check_preload, + _check_time_format, + _convert_times, + _file_like, + _get_argvalues, + _get_stim_channel, + _pl, + _scale_dataframe_data, + _stamp_to_dt, + _time_mask, + _validate_type, + check_fname, + copy_doc, + copy_function_doc_to_method_doc, + fill_doc, + logger, + repr_html, + sizeof_fmt, + verbose, + warn, +) +from ..viz import _RAW_CLIP_DEF, plot_raw + + +@fill_doc +class BaseRaw( + ProjMixin, + ContainsMixin, + UpdateChannelsMixin, + ReferenceMixin, + SetChannelsMixin, + InterpolationMixin, + TimeMixin, + SizeMixin, + FilterMixin, + SpectrumMixin, +): + """Base class for Raw data. + + Parameters + ---------- + %(info_not_none)s + preload : bool | str | ndarray + Preload data into memory for data manipulation and faster indexing. + If True, the data will be preloaded into memory (fast, requires + large amount of memory). If preload is a string, preload is the + file name of a memory-mapped file which is used to store the data + on the hard drive (slower, requires less memory). If preload is an + ndarray, the data are taken from that array. If False, data are not + read until save. + first_samps : iterable + Iterable of the first sample number from each raw file. For unsplit raw + files this should be a length-one list or tuple. + last_samps : iterable | None + Iterable of the last sample number from each raw file. For unsplit raw + files this should be a length-one list or tuple. If None, then preload + must be an ndarray. + filenames : tuple | None + Tuple of length one (for unsplit raw files) or length > 1 (for split + raw files). + raw_extras : list of dict + The data necessary for on-demand reads for the given reader format. + Should be the same length as ``filenames``. Will have the entry + ``raw_extras['orig_nchan']`` added to it for convenience. + orig_format : str + The data format of the original raw file (e.g., ``'double'``). + dtype : dtype | None + The dtype of the raw data. If preload is an ndarray, its dtype must + match what is passed here. + buffer_size_sec : float + The buffer size in seconds that should be written by default using + :meth:`mne.io.Raw.save`. + orig_units : dict | None + Dictionary mapping channel names to their units as specified in + the header file. Example: {'FC1': 'nV'}. + + .. versionadded:: 0.17 + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + + Notes + ----- + This class is public to allow for stable type-checking in user + code (i.e., ``isinstance(my_raw_object, BaseRaw)``) but should not be used + as a constructor for `Raw` objects (use instead one of the subclass + constructors, or one of the ``mne.io.read_raw_*`` functions). + + Subclasses must provide the following methods: + + * _read_segment_file(self, data, idx, fi, start, stop, cals, mult) + (only needed for types that support on-demand disk reads) + """ + + # NOTE: If you add a new attribute to this class and get a Sphinx warning like: + # docstring of mne.io.base.BaseRaw:71: + # WARNING: py:obj reference target not found: duration [ref.obj] + # You need to add the attribute to doc/conf.py nitpick_ignore_regex. You should also + # consider adding it to the Attributes list for Raw in mne/io/fiff/raw.py. + + _extra_attributes = () + + @verbose + def __init__( + self, + info, + preload=False, + first_samps=(0,), + last_samps=None, + filenames=None, + raw_extras=(None,), + orig_format="double", + dtype=np.float64, + buffer_size_sec=1.0, + orig_units=None, + *, + verbose=None, + ): + # wait until the end to preload data, but triage here + if isinstance(preload, np.ndarray): + # some functions (e.g., filtering) only work w/64-bit data + if preload.dtype not in (np.float64, np.complex128): + raise RuntimeError( + f"datatype must be float64 or complex128, not {preload.dtype}" + ) + if preload.dtype != dtype: + raise ValueError("preload and dtype must match") + self._data = preload + self.preload = True + assert len(first_samps) == 1 + last_samps = [first_samps[0] + self._data.shape[1] - 1] + load_from_disk = False + else: + if last_samps is None: + raise ValueError( + "last_samps must be given unless preload is an ndarray" + ) + if not preload: + self.preload = False + load_from_disk = False + else: + load_from_disk = True + self._last_samps = np.array(last_samps) + self._first_samps = np.array(first_samps) + orig_ch_names = info["ch_names"] + with info._unlock(check_after=True): + # be permissive of old code + if isinstance(info["meas_date"], tuple): + info["meas_date"] = _stamp_to_dt(info["meas_date"]) + self.info = info + self.buffer_size_sec = float(buffer_size_sec) + cals = np.empty(info["nchan"]) + for k in range(info["nchan"]): + cals[k] = info["chs"][k]["range"] * info["chs"][k]["cal"] + bad = np.where(cals == 0)[0] + if len(bad) > 0: + raise ValueError( + f"Bad cals for channels {dict((ii, self.ch_names[ii]) for ii in bad)}" + ) + self._cals = cals + if raw_extras is None: + raw_extras = [None] * len(first_samps) + self._raw_extras = list(dict() if r is None else r for r in raw_extras) + for r in self._raw_extras: + r["orig_nchan"] = info["nchan"] + self._read_picks = [np.arange(info["nchan"]) for _ in range(len(raw_extras))] + # deal with compensation (only relevant for CTF data, either CTF + # reader or MNE-C converted CTF->FIF files) + self._read_comp_grade = self.compensation_grade # read property + if self._read_comp_grade is not None and len(info["comps"]): + logger.info("Current compensation grade : %d", self._read_comp_grade) + self._comp = None + if filenames is None: + filenames = [None] * len(first_samps) + self.filenames = list(filenames) + _validate_type(orig_format, str, "orig_format") + _check_option("orig_format", orig_format, ("double", "single", "int", "short")) + self.orig_format = orig_format + # Sanity check and set original units, if provided by the reader: + + if orig_units: + if not isinstance(orig_units, dict): + raise ValueError( + f"orig_units must be of type dict, but got {type(orig_units)}" + ) + + # original units need to be truncated to 15 chars or renamed + # to match MNE conventions (channel name unique and less than + # 15 characters). + orig_units = deepcopy(orig_units) + for old_ch, new_ch in zip(orig_ch_names, info["ch_names"]): + if old_ch in orig_units: + this_unit = orig_units[old_ch] + del orig_units[old_ch] + orig_units[new_ch] = this_unit + + # STI 014 channel is native only to fif ... for all other formats + # this was artificially added by the IO procedure, so remove it + ch_names = list(info["ch_names"]) + if "STI 014" in ch_names and self.filenames[0].suffix != ".fif": + ch_names.remove("STI 014") + + # Each channel in the data must have a corresponding channel in + # the original units. + ch_correspond = [ch in orig_units for ch in ch_names] + if not all(ch_correspond): + ch_without_orig_unit = ch_names[ch_correspond.index(False)] + raise ValueError( + f"Channel {ch_without_orig_unit} has no associated original unit." + ) + + # Final check of orig_units, editing a unit if it is not a valid + # unit + orig_units = _check_orig_units(orig_units) + self._orig_units = orig_units or dict() # always a dict + self._projector = None + self._dtype_ = dtype + self.set_annotations(None) + self._cropped_samp = first_samps[0] + # If we have True or a string, actually do the preloading + if load_from_disk: + self._preload_data(preload) + self._init_kwargs = _get_argvalues() + + @verbose + def apply_gradient_compensation(self, grade, verbose=None): + """Apply CTF gradient compensation. + + .. warning:: The compensation matrices are stored with single + precision, so repeatedly switching between different + of compensation (e.g., 0->1->3->2) can increase + numerical noise, especially if data are saved to + disk in between changing grades. It is thus best to + only use a single gradient compensation level in + final analyses. + + Parameters + ---------- + grade : int + CTF gradient compensation level. + %(verbose)s + + Returns + ------- + raw : instance of Raw + The modified Raw instance. Works in-place. + """ + grade = int(grade) + current_comp = self.compensation_grade + if current_comp != grade: + if self.proj: + raise RuntimeError( + "Cannot change compensation on data where projectors have been " + "applied." + ) + # Figure out what operator to use (varies depending on preload) + from_comp = current_comp if self.preload else self._read_comp_grade + comp = make_compensator(self.info, from_comp, grade) + logger.info( + "Compensator constructed to change %d -> %d", current_comp, grade + ) + set_current_comp(self.info, grade) + # We might need to apply it to our data now + if self.preload: + logger.info("Applying compensator to loaded data") + lims = np.concatenate( + [np.arange(0, len(self.times), 10000), [len(self.times)]] + ) + for start, stop in zip(lims[:-1], lims[1:]): + self._data[:, start:stop] = np.dot(comp, self._data[:, start:stop]) + else: + self._comp = comp # store it for later use + return self + + @property + def _dtype(self): + """Datatype for loading data (property so subclasses can override).""" + # most classes only store real data, they won't need anything special + return self._dtype_ + + @verbose + def _read_segment( + self, start=0, stop=None, sel=None, data_buffer=None, *, verbose=None + ): + """Read a chunk of raw data. + + Parameters + ---------- + start : int, (optional) + first sample to include (first is 0). If omitted, defaults to the + first sample in data. + stop : int, (optional) + First sample to not include. + If omitted, data is included to the end. + sel : array, optional + Indices of channels to select. + data_buffer : array or str, optional + numpy array to fill with data read, must have the correct shape. + If str, a np.memmap with the correct data type will be used + to store the data. + projector : array + SSP operator to apply to the data. + %(verbose)s + + Returns + ------- + data : array, [channels x samples] + the data matrix (channels x samples). + """ + # Initial checks + start = int(start) + stop = self.n_times if stop is None else min([int(stop), self.n_times]) + + if start >= stop: + raise ValueError("No data in this range") + + # Initialize the data and calibration vector + if sel is None: + n_out = self.info["nchan"] + idx = slice(None) + else: + n_out = len(sel) + idx = _convert_slice(sel) + del sel + assert n_out <= self.info["nchan"] + data_shape = (n_out, stop - start) + dtype = self._dtype + if isinstance(data_buffer, np.ndarray): + if data_buffer.shape != data_shape: + raise ValueError( + f"data_buffer has incorrect shape: " + f"{data_buffer.shape} != {data_shape}" + ) + data = data_buffer + else: + data = _allocate_data(data_buffer, data_shape, dtype) + + # deal with having multiple files accessed by the raw object + cumul_lens = np.concatenate(([0], np.array(self._raw_lengths, dtype="int"))) + cumul_lens = np.cumsum(cumul_lens) + files_used = np.logical_and( + np.less(start, cumul_lens[1:]), np.greater_equal(stop - 1, cumul_lens[:-1]) + ) + + # set up cals and mult (cals, compensation, and projector) + n_out = len(np.arange(len(self.ch_names))[idx]) + cals = self._cals.ravel() + projector, comp = self._projector, self._comp + if comp is not None: + mult = comp + if projector is not None: + mult = projector @ mult + else: + mult = projector + del projector, comp + + if mult is None: + cals = cals[idx, np.newaxis] + assert cals.shape == (n_out, 1) + need_idx = idx # sufficient just to read the given channels + else: + mult = mult[idx] * cals + cals = None # shouldn't be used + assert mult.shape == (n_out, len(self.ch_names)) + # read all necessary for proj + need_idx = np.where(np.any(mult, axis=0))[0] + mult = mult[:, need_idx] + logger.debug( + f"Reading {len(need_idx)}/{len(self.ch_names)} channels " + f"due to projection" + ) + assert (mult is None) ^ (cals is None) # xor + + # read from necessary files + offset = 0 + for fi in np.nonzero(files_used)[0]: + start_file = self._first_samps[fi] + # first iteration (only) could start in the middle somewhere + if offset == 0: + start_file += start - cumul_lens[fi] + stop_file = np.min( + [ + stop - cumul_lens[fi] + self._first_samps[fi], + self._last_samps[fi] + 1, + ] + ) + if start_file < self._first_samps[fi] or stop_file < start_file: + raise ValueError("Bad array indexing, could be a bug") + n_read = stop_file - start_file + this_sl = slice(offset, offset + n_read) + # reindex back to original file + orig_idx = _convert_slice(self._read_picks[fi][need_idx]) + _ReadSegmentFileProtector(self)._read_segment_file( + data[:, this_sl], + orig_idx, + fi, + int(start_file), + int(stop_file), + cals, + mult, + ) + offset += n_read + return data + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a segment of data from a file. + + Only needs to be implemented for readers that support + ``preload=False``. Any implementation should only make use of: + + - self._raw_extras[fi] + - self.filenames[fi] + + So be sure to store any information necessary for reading raw data + in self._raw_extras[fi]. Things like ``info`` can be decoupled + from the original data (e.g., different subsets of channels) due + to picking before preload, for example. + + Parameters + ---------- + data : ndarray, shape (n_out, stop - start + 1) + The data array. Should be modified inplace. + idx : ndarray | slice + The requested channel indices. + fi : int + The file index that must be read from. + start : int + The start sample in the given file. + stop : int + The stop sample in the given file (inclusive). + cals : ndarray, shape (len(idx), 1) + Channel calibrations (already sub-indexed). + mult : ndarray, shape (n_out, len(idx) | None + The compensation + projection + cals matrix, if applicable. + """ + raise NotImplementedError + + def _check_bad_segment( + self, start, stop, picks, reject_start, reject_stop, reject_by_annotation=False + ): + """Check if data segment is bad. + + If the slice is good, returns the data in desired range. + If rejected based on annotation, returns description of the + bad segment as a string. + + Parameters + ---------- + start : int + First sample of the slice. + stop : int + End of the slice. + picks : array of int + Channel picks. + reject_start : int + First sample to check for overlaps with bad annotations. + reject_stop : int + Last sample to check for overlaps with bad annotations. + reject_by_annotation : bool + Whether to perform rejection based on annotations. + False by default. + + Returns + ------- + data : array | str + Data in the desired range (good segment) or description of the bad + segment. + """ + if start < 0: + return None + if reject_by_annotation and len(self.annotations) > 0: + annot = self.annotations + sfreq = self.info["sfreq"] + onset = _sync_onset(self, annot.onset) + overlaps = np.where(onset < reject_stop / sfreq) + overlaps = np.where( + onset[overlaps] + annot.duration[overlaps] > reject_start / sfreq + ) + for descr in annot.description[overlaps]: + if descr.lower().startswith("bad"): + return descr + return self._getitem((picks, slice(start, stop)), return_times=False) + + @verbose + def load_data(self, verbose=None): + """Load raw data. + + Parameters + ---------- + %(verbose)s + + Returns + ------- + raw : instance of Raw + The raw object with data. + + Notes + ----- + This function will load raw data if it was not already preloaded. + If data were already preloaded, it will do nothing. + + .. versionadded:: 0.10.0 + """ + if not self.preload: + self._preload_data(True) + return self + + def _preload_data(self, preload): + """Actually preload the data.""" + data_buffer = preload + if isinstance(preload, bool | np.bool_) and not preload: + data_buffer = None + t = self.times + logger.info( + f"Reading 0 ... {len(t) - 1} = {0.0:9.3f} ... {t[-1]:9.3f} secs..." + ) + self._data = self._read_segment(data_buffer=data_buffer) + assert len(self._data) == self.info["nchan"] + self.preload = True + self._comp = None # no longer needed + self.close() + + @property + def _first_time(self): + return self.first_samp / float(self.info["sfreq"]) + + @property + def first_samp(self): + """The first data sample. + + See :term:`first_samp`. + """ + return self._cropped_samp + + @property + def first_time(self): + """The first time point (including first_samp but not meas_date).""" + return self._first_time + + @property + def last_samp(self): + """The last data sample.""" + return self.first_samp + sum(self._raw_lengths) - 1 + + @property + def _last_time(self): + return self.last_samp / float(self.info["sfreq"]) + + def time_as_index(self, times, use_rounding=False, origin=None): + """Convert time to indices. + + Parameters + ---------- + times : list-like | float | int + List of numbers or a number representing points in time. + use_rounding : bool + If True, use rounding (instead of truncation) when converting + times to indices. This can help avoid non-unique indices. + origin : datetime | float | int | None + Time reference for times. If None, ``times`` are assumed to be + relative to :term:`first_samp`. + + .. versionadded:: 0.17.0 + + Returns + ------- + index : ndarray + Indices relative to :term:`first_samp` corresponding to the times + supplied. + """ + origin = _handle_meas_date(origin) + if origin is None: + delta = 0 + elif self.info["meas_date"] is None: + raise ValueError( + f'origin must be None when info["meas_date"] is None, got {origin}' + ) + else: + first_samp_in_abs_time = self.info["meas_date"] + timedelta( + 0, self._first_time + ) + delta = (origin - first_samp_in_abs_time).total_seconds() + times = np.atleast_1d(times) + delta + + return super().time_as_index(times, use_rounding) + + @property + def _raw_lengths(self): + return [ + last - first + 1 for first, last in zip(self._first_samps, self._last_samps) + ] + + @property + def annotations(self): # noqa: D401 + """:class:`~mne.Annotations` for marking segments of data.""" + return self._annotations + + @property + def filenames(self) -> tuple[Path | None, ...]: + """The filenames used. + + :type: :class:`tuple` of :class:`pathlib.Path` | ``None`` + """ + return tuple(self._filenames) + + @filenames.setter + def filenames(self, value): + """The filenames used, cast to list of paths.""" # noqa: D401 + _validate_type(value, (list, tuple), "filenames") + if isinstance(value, tuple): + value = list(value) + for k, elt in enumerate(value): + if elt is not None: + value[k] = _check_fname(elt, overwrite="read", must_exist=False) + if not value[k].exists(): + # check existence separately from _check_fname since some + # fileformats use directories instead of files and '_check_fname' + # does not handle it correctly. + raise FileNotFoundError(f"File {value[k]} not found.") + self._filenames = list(value) + + @verbose + def set_annotations( + self, annotations, emit_warning=True, on_missing="raise", *, verbose=None + ): + """Setter for annotations. + + This setter checks if they are inside the data range. + + Parameters + ---------- + annotations : instance of mne.Annotations | None + Annotations to set. If None, the annotations is defined + but empty. + %(emit_warning)s + The default is True. + %(on_missing_ch_names)s + %(verbose)s + + Returns + ------- + self : instance of Raw + The raw object with annotations. + """ + meas_date = _handle_meas_date(self.info["meas_date"]) + if annotations is None: + self._annotations = Annotations([], [], [], meas_date) + else: + _validate_type(annotations, Annotations, "annotations") + + if meas_date is None and annotations.orig_time is not None: + raise RuntimeError( + "Ambiguous operation. Setting an Annotation object with known " + "``orig_time`` to a raw object which has ``meas_date`` set to None " + "is ambiguous. Please, either set a meaningful ``meas_date`` to " + "the raw object; or set ``orig_time`` to None in which case the " + "annotation onsets would be taken in reference to the first sample " + "of the raw object." + ) + + delta = 1.0 / self.info["sfreq"] + new_annotations = annotations.copy() + new_annotations._prune_ch_names(self.info, on_missing) + if annotations.orig_time is None: + new_annotations.crop( + 0, self.times[-1] + delta, emit_warning=emit_warning + ) + new_annotations.onset += self._first_time + else: + tmin = meas_date + timedelta(0, self._first_time) + tmax = tmin + timedelta(seconds=self.times[-1] + delta) + new_annotations.crop(tmin=tmin, tmax=tmax, emit_warning=emit_warning) + new_annotations.onset -= ( + meas_date - new_annotations.orig_time + ).total_seconds() + new_annotations._orig_time = meas_date + + self._annotations = new_annotations + + return self + + def __del__(self): # noqa: D105 + # remove file for memmap + if hasattr(self, "_data") and getattr(self._data, "filename", None) is not None: + # First, close the file out; happens automatically on del + filename = self._data.filename + del self._data + # Now file can be removed + try: + os.remove(filename) + except OSError: + pass # ignore file that no longer exists + + def __enter__(self): + """Entering with block.""" + return self + + def __exit__(self, exception_type, exception_val, trace): + """Exit with block.""" + try: + self.close() + except Exception: + return exception_type, exception_val, trace + + def _parse_get_set_params(self, item): + """Parse the __getitem__ / __setitem__ tuples.""" + # make sure item is a tuple + if not isinstance(item, tuple): # only channel selection passed + item = (item, slice(None, None, None)) + + if len(item) != 2: # should be channels and time instants + raise RuntimeError( + "Unable to access raw data (need both channels and time)" + ) + + sel = _picks_to_idx(self.info, item[0]) + + if isinstance(item[1], slice): + time_slice = item[1] + start, stop, step = (time_slice.start, time_slice.stop, time_slice.step) + else: + item1 = item[1] + # Let's do automated type conversion to integer here + if np.array(item[1]).dtype.kind == "i": + item1 = int(item1) + if isinstance(item1, int | np.integer): + start, stop, step = item1, item1 + 1, 1 + # Need to special case -1, because -1:0 will be empty + if start == -1: + stop = None + else: + raise ValueError("Must pass int or slice to __getitem__") + + if start is None: + start = 0 + if step is not None and step != 1: + raise ValueError(f"step needs to be 1 : {step} given") + + if isinstance(sel, int | np.integer): + sel = np.array([sel]) + + if sel is not None and len(sel) == 0: + raise ValueError("Empty channel list") + + return sel, start, stop + + def __getitem__(self, item): + """Get raw data and times. + + Parameters + ---------- + item : tuple or array-like + See below for use cases. + + Returns + ------- + data : ndarray, shape (n_channels, n_times) + The raw data. + times : ndarray, shape (n_times,) + The times associated with the data. + + Examples + -------- + Generally raw data is accessed as:: + + >>> data, times = raw[picks, time_slice] # doctest: +SKIP + + To get all data, you can thus do either of:: + + >>> data, times = raw[:] # doctest: +SKIP + + Which will be equivalent to: + + >>> data, times = raw[:, :] # doctest: +SKIP + + To get only the good MEG data from 10-20 seconds, you could do:: + + >>> picks = mne.pick_types(raw.info, meg=True, exclude='bads') # doctest: +SKIP + >>> t_idx = raw.time_as_index([10., 20.]) # doctest: +SKIP + >>> data, times = raw[picks, t_idx[0]:t_idx[1]] # doctest: +SKIP + + """ # noqa: E501 + return self._getitem(item) + + def _getitem(self, item, return_times=True): + sel, start, stop = self._parse_get_set_params(item) + if self.preload: + data = self._data[sel, start:stop] + else: + data = self._read_segment(start=start, stop=stop, sel=sel) + + if return_times: + # Rather than compute the entire thing just compute the subset + # times = self.times[start:stop] + # stop can be None here so don't use it directly + times = np.arange(start, start + data.shape[1], dtype=float) + times /= self.info["sfreq"] + return data, times + else: + return data + + def __setitem__(self, item, value): + """Set raw data content.""" + _check_preload(self, "Modifying data of Raw") + sel, start, stop = self._parse_get_set_params(item) + # set the data + self._data[sel, start:stop] = value + + @verbose + def get_data( + self, + picks=None, + start=0, + stop=None, + reject_by_annotation=None, + return_times=False, + units=None, + *, + tmin=None, + tmax=None, + verbose=None, + ): + """Get data in the given range. + + Parameters + ---------- + %(picks_all)s + start : int + The first sample to include. Defaults to 0. + stop : int | None + End sample (first not to include). If None (default), the end of + the data is used. + reject_by_annotation : None | 'omit' | 'NaN' + Whether to reject by annotation. If None (default), no rejection is + done. If 'omit', segments annotated with description starting with + 'bad' are omitted. If 'NaN', the bad samples are filled with NaNs. + return_times : bool + Whether to return times as well. Defaults to False. + %(units)s + tmin : int | float | None + Start time of data to get in seconds. The ``tmin`` parameter is + ignored if the ``start`` parameter is bigger than 0. + + .. versionadded:: 0.24.0 + tmax : int | float | None + End time of data to get in seconds. The ``tmax`` parameter is + ignored if the ``stop`` parameter is defined. + + .. versionadded:: 0.24.0 + %(verbose)s + + Returns + ------- + data : ndarray, shape (n_channels, n_times) + Copy of the data in the given range. + times : ndarray, shape (n_times,) + Times associated with the data samples. Only returned if + return_times=True. + + Notes + ----- + .. versionadded:: 0.14.0 + """ + # validate types + _validate_type(start, types=("int-like"), item_name="start", type_name="int") + _validate_type( + stop, types=("int-like", None), item_name="stop", type_name="int, None" + ) + + picks = _picks_to_idx(self.info, picks, "all", exclude=()) + + # Get channel factors for conversion into specified unit + # (vector of ones if no conversion needed) + if units is not None: + ch_factors = _get_ch_factors(self, units, picks) + + # convert to ints + picks = np.atleast_1d(np.arange(self.info["nchan"])[picks]) + + # handle start/tmin stop/tmax + tmin_start, tmax_stop = self._handle_tmin_tmax(tmin, tmax) + + # tmin/tmax are ignored if start/stop are defined to + # something other than their defaults + start = tmin_start if start == 0 else start + stop = tmax_stop if stop is None else stop + + # truncate start/stop to the open interval [0, n_times] + start = min(max(0, start), self.n_times) + stop = min(max(0, stop), self.n_times) + + if len(self.annotations) == 0 or reject_by_annotation is None: + getitem = self._getitem( + (picks, slice(start, stop)), return_times=return_times + ) + if return_times: + data, times = getitem + if units is not None: + data *= ch_factors[:, np.newaxis] + return data, times + if units is not None: + getitem *= ch_factors[:, np.newaxis] + return getitem + _check_option( + "reject_by_annotation", reject_by_annotation.lower(), ["omit", "nan"] + ) + onsets, ends = _annotations_starts_stops(self, ["BAD"]) + keep = (onsets < stop) & (ends > start) + onsets = np.maximum(onsets[keep], start) + ends = np.minimum(ends[keep], stop) + if len(onsets) == 0: + data, times = self[picks, start:stop] + if units is not None: + data *= ch_factors[:, np.newaxis] + if return_times: + return data, times + return data + n_samples = stop - start # total number of samples + used = np.ones(n_samples, bool) + for onset, end in zip(onsets, ends): + if onset >= end: + continue + used[onset - start : end - start] = False + used = np.concatenate([[False], used, [False]]) + starts = np.where(~used[:-1] & used[1:])[0] + start + stops = np.where(used[:-1] & ~used[1:])[0] + start + n_kept = (stops - starts).sum() # kept samples + n_rejected = n_samples - n_kept # rejected samples + if n_rejected > 0: + if reject_by_annotation == "omit": + msg = ( + "Omitting {} of {} ({:.2%}) samples, retaining {} ({:.2%}) samples." + ) + logger.info( + msg.format( + n_rejected, + n_samples, + n_rejected / n_samples, + n_kept, + n_kept / n_samples, + ) + ) + data = np.zeros((len(picks), n_kept)) + times = np.zeros(data.shape[1]) + idx = 0 + for start, stop in zip(starts, stops): # get the data + if start == stop: + continue + end = idx + stop - start + data[:, idx:end], times[idx:end] = self[picks, start:stop] + idx = end + else: + msg = ( + "Setting {} of {} ({:.2%}) samples to NaN, retaining {}" + " ({:.2%}) samples." + ) + logger.info( + msg.format( + n_rejected, + n_samples, + n_rejected / n_samples, + n_kept, + n_kept / n_samples, + ) + ) + data, times = self[picks, start:stop] + data[:, ~used[1:-1]] = np.nan + else: + data, times = self[picks, start:stop] + + if units is not None: + data *= ch_factors[:, np.newaxis] + if return_times: + return data, times + return data + + @verbose + def apply_function( + self, + fun, + picks=None, + dtype=None, + n_jobs=None, + channel_wise=True, + verbose=None, + **kwargs, + ): + """Apply a function to a subset of channels. + + %(applyfun_summary_raw)s + + Parameters + ---------- + %(fun_applyfun)s + %(picks_all_data_noref)s + %(dtype_applyfun)s + %(n_jobs)s Ignored if ``channel_wise=False`` as the workload + is split across channels. + %(channel_wise_applyfun)s + + .. versionadded:: 0.18 + %(verbose)s + %(kwargs_fun)s + + Returns + ------- + self : instance of Raw + The raw object with transformed data. + """ + _check_preload(self, "raw.apply_function") + picks = _picks_to_idx(self.info, picks, exclude=(), with_ref_meg=False) + + if not callable(fun): + raise ValueError("fun needs to be a function") + + data_in = self._data + if dtype is not None and dtype != self._data.dtype: + self._data = self._data.astype(dtype) + + args = getfullargspec(fun).args + getfullargspec(fun).kwonlyargs + if channel_wise is False: + if ("ch_idx" in args) or ("ch_name" in args): + raise ValueError( + "apply_function cannot access ch_idx or ch_name " + "when channel_wise=False" + ) + if "ch_idx" in args: + logger.info("apply_function requested to access ch_idx") + if "ch_name" in args: + logger.info("apply_function requested to access ch_name") + + if channel_wise: + parallel, p_fun, n_jobs = parallel_func(_check_fun, n_jobs) + if n_jobs == 1: + # modify data inplace to save memory + for ch_idx in picks: + if "ch_idx" in args: + kwargs.update(ch_idx=ch_idx) + if "ch_name" in args: + kwargs.update(ch_name=self.info["ch_names"][ch_idx]) + self._data[ch_idx, :] = _check_fun( + fun, data_in[ch_idx, :], **kwargs + ) + else: + # use parallel function + data_picks_new = parallel( + p_fun( + fun, + data_in[ch_idx], + **kwargs, + **{ + k: v + for k, v in [ + ("ch_name", self.info["ch_names"][ch_idx]), + ("ch_idx", ch_idx), + ] + if k in args + }, + ) + for ch_idx in picks + ) + for run_idx, ch_idx in enumerate(picks): + self._data[ch_idx, :] = data_picks_new[run_idx] + else: + self._data[picks, :] = _check_fun(fun, data_in[picks, :], **kwargs) + + return self + + # Need a separate method because the default pad is different for raw + @copy_doc(FilterMixin.filter) + def filter( + self, + l_freq, + h_freq, + picks=None, + filter_length="auto", + l_trans_bandwidth="auto", + h_trans_bandwidth="auto", + n_jobs=None, + method="fir", + iir_params=None, + phase="zero", + fir_window="hamming", + fir_design="firwin", + skip_by_annotation=("edge", "bad_acq_skip"), + pad="reflect_limited", + verbose=None, + ): + return super().filter( + l_freq, + h_freq, + picks, + filter_length, + l_trans_bandwidth, + h_trans_bandwidth, + n_jobs=n_jobs, + method=method, + iir_params=iir_params, + phase=phase, + fir_window=fir_window, + fir_design=fir_design, + skip_by_annotation=skip_by_annotation, + pad=pad, + verbose=verbose, + ) + + @verbose + def notch_filter( + self, + freqs, + picks=None, + filter_length="auto", + notch_widths=None, + trans_bandwidth=1.0, + n_jobs=None, + method="fir", + iir_params=None, + mt_bandwidth=None, + p_value=0.05, + phase="zero", + fir_window="hamming", + fir_design="firwin", + pad="reflect_limited", + skip_by_annotation=("edge", "bad_acq_skip"), + verbose=None, + ): + """Notch filter a subset of channels. + + Parameters + ---------- + freqs : float | array of float | None + Specific frequencies to filter out from data, e.g., + ``np.arange(60, 241, 60)`` in the US or ``np.arange(50, 251, 50)`` + in Europe. ``None`` can only be used with the mode + ``'spectrum_fit'``, where an F test is used to find sinusoidal + components. + %(picks_all_data)s + %(filter_length_notch)s + notch_widths : float | array of float | None + Width of each stop band (centred at each freq in freqs) in Hz. + If None, ``freqs / 200`` is used. + trans_bandwidth : float + Width of the transition band in Hz. + Only used for ``method='fir'`` and ``method='iir'``. + %(n_jobs_fir)s + %(method_fir)s + %(iir_params)s + mt_bandwidth : float | None + The bandwidth of the multitaper windowing function in Hz. + Only used in 'spectrum_fit' mode. + p_value : float + P-value to use in F-test thresholding to determine significant + sinusoidal components to remove when ``method='spectrum_fit'`` and + ``freqs=None``. Note that this will be Bonferroni corrected for the + number of frequencies, so large p-values may be justified. + %(phase)s + %(fir_window)s + %(fir_design)s + %(pad_fir)s + The default is ``'reflect_limited'``. + + .. versionadded:: 0.15 + %(skip_by_annotation)s + %(verbose)s + + Returns + ------- + raw : instance of Raw + The raw instance with filtered data. + + See Also + -------- + mne.filter.notch_filter + mne.io.Raw.filter + + Notes + ----- + Applies a zero-phase notch filter to the channels selected by + "picks". By default the data of the Raw object is modified inplace. + + The Raw object has to have the data loaded e.g. with ``preload=True`` + or ``self.load_data()``. + + .. note:: If n_jobs > 1, more memory is required as + ``len(picks) * n_times`` additional time points need to + be temporarily stored in memory. + + For details, see :func:`mne.filter.notch_filter`. + """ + fs = float(self.info["sfreq"]) + picks = _picks_to_idx(self.info, picks, exclude=(), none="data_or_ica") + _check_preload(self, "raw.notch_filter") + onsets, ends = _annotations_starts_stops(self, skip_by_annotation, invert=True) + logger.info( + "Filtering raw data in %d contiguous segment%s", len(onsets), _pl(onsets) + ) + for si, (start, stop) in enumerate(zip(onsets, ends)): + notch_filter( + self._data[:, start:stop], + fs, + freqs, + filter_length=filter_length, + notch_widths=notch_widths, + trans_bandwidth=trans_bandwidth, + method=method, + iir_params=iir_params, + mt_bandwidth=mt_bandwidth, + p_value=p_value, + picks=picks, + n_jobs=n_jobs, + copy=False, + phase=phase, + fir_window=fir_window, + fir_design=fir_design, + pad=pad, + ) + return self + + @verbose + def resample( + self, + sfreq, + *, + npad="auto", + window="auto", + stim_picks=None, + n_jobs=None, + events=None, + pad="auto", + method="fft", + verbose=None, + ): + """Resample all channels. + + If appropriate, an anti-aliasing filter is applied before resampling. + See :ref:`resampling-and-decimating` for more information. + + .. warning:: The intended purpose of this function is primarily to + speed up computations (e.g., projection calculation) when + precise timing of events is not required, as downsampling + raw data effectively jitters trigger timings. It is + generally recommended not to epoch downsampled data, + but instead epoch and then downsample, as epoching + downsampled data jitters triggers. + For more, see + `this illustrative gist + `_. + + If resampling the continuous data is desired, it is + recommended to construct events using the original data. + The event onsets can be jointly resampled with the raw + data using the 'events' parameter (a resampled copy is + returned). + + Parameters + ---------- + sfreq : float + New sample rate to use. + %(npad_resample)s + %(window_resample)s + stim_picks : list of int | None + Stim channels. These channels are simply subsampled or + supersampled (without applying any filtering). This reduces + resampling artifacts in stim channels, but may lead to missing + triggers. If None, stim channels are automatically chosen using + :func:`mne.pick_types`. + %(n_jobs_cuda)s + events : 2D array, shape (n_events, 3) | None + An optional event matrix. When specified, the onsets of the events + are resampled jointly with the data. NB: The input events are not + modified, but a new array is returned with the raw instead. + %(pad_resample_auto)s + + .. versionadded:: 0.15 + %(method_resample)s + + .. versionadded:: 1.7 + %(verbose)s + + Returns + ------- + raw : instance of Raw + The resampled version of the raw object. + events : array, shape (n_events, 3) | None + If events are jointly resampled, these are returned with the raw. + + See Also + -------- + mne.io.Raw.filter + mne.Epochs.resample + + Notes + ----- + For some data, it may be more accurate to use ``npad=0`` to reduce + artifacts. This is dataset dependent -- check your data! + + For optimum performance and to make use of ``n_jobs > 1``, the raw + object has to have the data loaded e.g. with ``preload=True`` or + ``self.load_data()``, but this increases memory requirements. The + resulting raw object will have the data loaded into memory. + """ + sfreq = float(sfreq) + o_sfreq = float(self.info["sfreq"]) + if _check_resamp_noop(sfreq, o_sfreq): + if events is not None: + return self, events.copy() + else: + return self + + # When no event object is supplied, some basic detection of dropped + # events is performed to generate a warning. Finding events can fail + # for a variety of reasons, e.g. if no stim channel is present or it is + # corrupted. This should not stop the resampling from working. The + # warning should simply not be generated in this case. + if events is None: + try: + original_events = find_events(self) + except Exception: + pass + + offsets = np.concatenate(([0], np.cumsum(self._raw_lengths))) + + # set up stim channel processing + if stim_picks is None: + stim_picks = pick_types( + self.info, meg=False, ref_meg=False, stim=True, exclude=[] + ) + else: + stim_picks = _picks_to_idx( + self.info, stim_picks, exclude=(), with_ref_meg=False + ) + + kwargs = dict( + up=sfreq, + down=o_sfreq, + npad=npad, + window=window, + n_jobs=n_jobs, + pad=pad, + method=method, + ) + ratio, n_news = zip( + *( + _resamp_ratio_len(sfreq, o_sfreq, old_len) + for old_len in self._raw_lengths + ) + ) + ratio, n_news = ratio[0], np.array(n_news, int) + new_offsets = np.cumsum([0] + list(n_news)) + if self.preload: + new_data = np.empty((len(self.ch_names), new_offsets[-1]), self._data.dtype) + for ri, (n_orig, n_new) in enumerate(zip(self._raw_lengths, n_news)): + this_sl = slice(new_offsets[ri], new_offsets[ri + 1]) + if self.preload: + data_chunk = self._data[:, offsets[ri] : offsets[ri + 1]] + new_data[:, this_sl] = resample(data_chunk, **kwargs) + # In empirical testing, it was faster to resample all channels + # (above) and then replace the stim channels than it was to + # only resample the proper subset of channels and then use + # np.insert() to restore the stims. + if len(stim_picks) > 0: + new_data[stim_picks, this_sl] = _resample_stim_channels( + data_chunk[stim_picks], n_new, data_chunk.shape[1] + ) + else: # this will not be I/O efficient, but will be mem efficient + for ci in range(len(self.ch_names)): + data_chunk = self.get_data( + ci, offsets[ri], offsets[ri + 1], verbose="error" + )[0] + if ci == 0 and ri == 0: + new_data = np.empty( + (len(self.ch_names), new_offsets[-1]), data_chunk.dtype + ) + if ci in stim_picks: + resamp = _resample_stim_channels( + data_chunk, n_new, data_chunk.shape[-1] + )[0] + else: + resamp = resample(data_chunk, **kwargs) + new_data[ci, this_sl] = resamp + + self._cropped_samp = int(np.round(self._cropped_samp * ratio)) + self._first_samps = np.round(self._first_samps * ratio).astype(int) + self._last_samps = np.array(self._first_samps) + n_news - 1 + self._raw_lengths[ri] = list(n_news) + assert np.array_equal(n_news, self._last_samps - self._first_samps + 1) + self._data = new_data + self.preload = True + lowpass = self.info.get("lowpass") + lowpass = np.inf if lowpass is None else lowpass + with self.info._unlock(): + self.info["lowpass"] = min(lowpass, sfreq / 2.0) + self.info["sfreq"] = sfreq + + # See the comment above why we ignore all errors here. + if events is None: + try: + # Did we loose events? + resampled_events = find_events(self) + if len(resampled_events) != len(original_events): + warn( + "Resampling of the stim channels caused event " + "information to become unreliable. Consider finding " + "events on the original data and passing the event " + "matrix as a parameter." + ) + except Exception: + pass + + return self + else: + # always make a copy of events + events = events.copy() + + events[:, 0] = np.minimum( + np.round(events[:, 0] * ratio).astype(int), + self._data.shape[1] + self.first_samp - 1, + ) + return self, events + + @verbose + def rescale(self, scalings, *, verbose=None): + """Rescale channels. + + .. warning:: + MNE-Python assumes data are stored in SI base units. This function should + typically only be used to fix an incorrect scaling factor in the data to get + it to be in SI base units, otherwise unintended problems (e.g., incorrect + source imaging results) and analysis errors can occur. + + Parameters + ---------- + scalings : int | float | dict + The scaling factor(s) by which to multiply the data. If a float, the same + scaling factor is applied to all channels (this works only if all channels + are of the same type). If a dict, the keys must be valid channel types and + the values the scaling factors to apply to the corresponding channels. + %(verbose)s + + Returns + ------- + raw : Raw + The raw object with rescaled data (modified in-place). + + Examples + -------- + A common use case for EEG data is to convert from µV to V, since many EEG + systems store data in µV, but MNE-Python expects the data to be in V. Therefore, + the data needs to be rescaled by a factor of 1e-6. To rescale all channels from + µV to V, you can do:: + + >>> raw.rescale(1e-6) # doctest: +SKIP + + Note that the previous example only works if all channels are of the same type. + If there are multiple channel types, you can pass a dict with the individual + scaling factors. For example, to rescale only EEG channels, you can do:: + + >>> raw.rescale({"eeg": 1e-6}) # doctest: +SKIP + """ + _validate_type(scalings, (int, float, dict), "scalings") + _check_preload(self, "raw.rescale") + + channel_types = self.get_channel_types(unique=True) + + if isinstance(scalings, int | float): + if len(channel_types) == 1: + self.apply_function(lambda x: x * scalings, channel_wise=False) + else: + raise ValueError( + "If scalings is a scalar, all channels must be of the same type. " + "Consider passing a dict instead." + ) + else: + for ch_type in scalings.keys(): + if ch_type not in channel_types: + raise ValueError( + f'Channel type "{ch_type}" is not present in the Raw file.' + ) + for ch_type, ch_scale in scalings.items(): + self.apply_function( + lambda x: x * ch_scale, picks=ch_type, channel_wise=False + ) + + return self + + @verbose + def crop( + self, + tmin=0.0, + tmax=None, + include_tmax=True, + *, + reset_first_samp=False, + verbose=None, + ): + """Crop raw data file. + + Limit the data from the raw file to go between specific times. Note + that the new ``tmin`` is assumed to be ``t=0`` for all subsequently + called functions (e.g., :meth:`~mne.io.Raw.time_as_index`, or + :class:`~mne.Epochs`). New :term:`first_samp` and :term:`last_samp` + are set accordingly. + + Thus function operates in-place on the instance. + Use :meth:`mne.io.Raw.copy` if operation on a copy is desired. + + Parameters + ---------- + %(tmin_raw)s + %(tmax_raw)s + %(include_tmax)s + reset_first_samp : bool + If True, reset :term:`first_samp` to 0 after cropping, treating + the cropped segment as an independent recording. Note that this + can break things if you extracted events before cropping and try + to use them afterward. Default is False. + + .. versionadded:: 1.12 + %(verbose)s + + Returns + ------- + raw : instance of Raw + The cropped raw object, modified in-place. + + Notes + ----- + After cropping, :term:`first_samp` is updated to reflect the new + start of the data, preserving the original recording timeline. + This means ``raw.times`` will still start at ``0.0``, but + ``raw.first_samp`` will reflect the offset from the original + recording. If you want to treat the cropped segment as an + independent signal with ``first_samp=0``, you can convert it + to a :class:`~mne.io.RawArray`:: + + raw_array = mne.io.RawArray(raw.get_data(), raw.info) + + Examples + -------- + By default, cropping preserves the original recording timeline, + so :term:`first_samp` remains non-zero after cropping:: + + >>> raw = mne.io.read_raw_fif(fname) # doctest: +SKIP + >>> print(raw.first_samp) # doctest: +SKIP + 25800 + >>> raw.crop(tmin=10, tmax=20) # doctest: +SKIP + >>> print(raw.first_samp) # doctest: +SKIP + 27810 + + If you want to treat the cropped segment as an independent + recording, use ``reset_first_samp=True``:: + + >>> raw2 = raw.copy().crop(tmin=10, tmax=20, + ... reset_first_samp=True) # doctest: +SKIP + >>> print(raw2.first_samp) # doctest: +SKIP + 0 + """ + max_time = (self.n_times - 1) / self.info["sfreq"] + if tmax is None: + tmax = max_time + + if tmin > tmax: + raise ValueError(f"tmin ({tmin}) must be less than tmax ({tmax})") + if tmin < 0.0: + raise ValueError(f"tmin ({tmin}) must be >= 0") + elif tmax - int(not include_tmax) / self.info["sfreq"] > max_time: + raise ValueError( + f"tmax ({tmax}) must be less than or equal to the max " + f"time ({max_time:0.4f} s)" + ) + + smin, smax = np.where( + _time_mask( + self.times, + tmin, + tmax, + sfreq=self.info["sfreq"], + include_tmax=include_tmax, + ) + )[0][[0, -1]] + cumul_lens = np.concatenate(([0], np.array(self._raw_lengths, dtype="int"))) + cumul_lens = np.cumsum(cumul_lens) + keepers = np.logical_and( + np.less(smin, cumul_lens[1:]), np.greater_equal(smax, cumul_lens[:-1]) + ) + keepers = np.where(keepers)[0] + # if we drop file(s) from the beginning, we need to keep track of + # how many samples we dropped relative to that one + self._cropped_samp += smin + self._first_samps = np.atleast_1d(self._first_samps[keepers]) + # Adjust first_samp of first used file! + self._first_samps[0] += smin - cumul_lens[keepers[0]] + self._last_samps = np.atleast_1d(self._last_samps[keepers]) + self._last_samps[-1] -= cumul_lens[keepers[-1] + 1] - 1 - smax + self._read_picks = [self._read_picks[ri] for ri in keepers] + assert all(len(r) == len(self._read_picks[0]) for r in self._read_picks) + self._raw_extras = [self._raw_extras[ri] for ri in keepers] + self.filenames = [self.filenames[ri] for ri in keepers] + if self.preload: + # slice and copy to avoid the reference to large array + self._data = self._data[:, smin : smax + 1].copy() + + annotations = self.annotations + # now call setter to filter out annotations outside of interval + if annotations.orig_time is None: + assert self.info["meas_date"] is None + # When self.info['meas_date'] is None (which is guaranteed if + # self.annotations.orig_time is None), when we do the + # self.set_annotations, it's assumed that the annotations onset + # are relative to first_time, so we have to subtract it, then + # set_annotations will put it back. + annotations.onset -= self.first_time + self.set_annotations(annotations, False) + if reset_first_samp: + delta = self._first_samps[0] + self._first_samps -= delta + self._last_samps -= delta + self._cropped_samp -= delta + return self + + @verbose + def crop_by_annotations(self, annotations=None, *, verbose=None): + """Get crops of raw data file for selected annotations. + + Parameters + ---------- + annotations : instance of Annotations | None + The annotations to use for cropping the raw file. If None, + the annotations from the instance are used. + %(verbose)s + + Returns + ------- + raws : list + The cropped raw objects. + """ + if annotations is None: + annotations = self.annotations + + raws = [] + for annot in annotations: + onset = annot["onset"] - self.first_time + # be careful about near-zero errors (crop is very picky about this, + # e.g., -1e-8 is an error) + if -self.info["sfreq"] / 2 < onset < 0: + onset = 0 + raw_crop = self.copy().crop(onset, onset + annot["duration"]) + raws.append(raw_crop) + + return raws + + @verbose + def save( + self, + fname, + picks=None, + tmin=0, + tmax=None, + buffer_size_sec=None, + drop_small_buffer=False, + proj=False, + fmt="single", + overwrite=False, + split_size="2GB", + split_naming="neuromag", + verbose=None, + ): + """Save raw data to file. + + Parameters + ---------- + fname : path-like + File name of the new dataset. This has to be a new filename + unless data have been preloaded. Filenames should end with + ``raw.fif`` (common raw data), ``raw_sss.fif`` + (Maxwell-filtered continuous data), + ``raw_tsss.fif`` (temporally signal-space-separated data), + ``_meg.fif`` (common MEG data), ``_eeg.fif`` (common EEG data), + or ``_ieeg.fif`` (common intracranial EEG data). You may also + append an additional ``.gz`` suffix to enable gzip compression. + %(picks_all)s + %(tmin_raw)s + %(tmax_raw)s + buffer_size_sec : float | None + Size of data chunks in seconds. If None (default), the buffer + size of the original file is used. + drop_small_buffer : bool + Drop or not the last buffer. It is required by maxfilter (SSS) + that only accepts raw files with buffers of the same size. + proj : bool + If True the data is saved with the projections applied (active). + + .. note:: If ``apply_proj()`` was used to apply the projections, + the projectons will be active even if ``proj`` is False. + fmt : 'single' | 'double' | 'int' | 'short' + Format to use to save raw data. Valid options are 'double', + 'single', 'int', and 'short' for 64- or 32-bit float, or 32- or + 16-bit integers, respectively. It is **strongly** recommended to + use 'single', as this is backward-compatible, and is standard for + maintaining precision. Note that using 'short' or 'int' may result + in loss of precision, complex data cannot be saved as 'short', + and neither complex data types nor real data stored as 'double' + can be loaded with the MNE command-line tools. See raw.orig_format + to determine the format the original data were stored in. + %(overwrite)s + To overwrite original file (the same one that was loaded), + data must be preloaded upon reading. + split_size : str | int + Large raw files are automatically split into multiple pieces. This + parameter specifies the maximum size of each piece. If the + parameter is an integer, it specifies the size in Bytes. It is + also possible to pass a human-readable string, e.g., 100MB. + + .. note:: Due to FIFF file limitations, the maximum split + size is 2GB. + %(split_naming)s + + .. versionadded:: 0.17 + %(verbose)s + + Returns + ------- + fnames : List of path-like + List of path-like objects containing the path to each file split. + + .. versionadded:: 1.9 + + Notes + ----- + If Raw is a concatenation of several raw files, **be warned** that + only the measurement information from the first raw file is stored. + This likely means that certain operations with external tools may not + work properly on a saved concatenated file (e.g., probably some + or all forms of SSS). It is recommended not to concatenate and + then save raw files for this reason. + + Samples annotated ``BAD_ACQ_SKIP`` are not stored in order to optimize + memory. Whatever values, they will be loaded as 0s when reading file. + """ + endings = ( + "raw.fif", + "raw_sss.fif", + "raw_tsss.fif", + "_meg.fif", + "_eeg.fif", + "_ieeg.fif", + ) + endings += tuple([f"{e}.gz" for e in endings]) + endings_err = (".fif", ".fif.gz") + + # convert to str, check for overwrite a few lines later + fname = _check_fname( + fname, + overwrite=True, + verbose="error", + check_bids_split=True, + name="fname", + ) + check_fname(fname, "raw", endings, endings_err=endings_err) + + split_size = _get_split_size(split_size) + if not self.preload and fname in self.filenames: + extra = " and overwrite must be True" if not overwrite else "" + raise ValueError( + "In order to save data to the same file, data need to be preloaded" + + extra + ) + + if self.preload: + if np.iscomplexobj(self._data): + warn( + "Saving raw file with complex data. Loading with command-line MNE " + "tools will not work." + ) + + data_test = self[0, 0][0] + if fmt == "short" and np.iscomplexobj(data_test): + raise ValueError( + 'Complex data must be saved as "single" or "double", not "short"' + ) + + # check for file existence and expand `~` if present + fname = _check_fname(fname=fname, overwrite=overwrite, verbose="error") + + if proj: + info = deepcopy(self.info) + projector, info = setup_proj(info) + activate_proj(info["projs"], copy=False) + else: + info = self.info + projector = None + + # + # Set up the reading parameters + # + + # Convert to samples + start, stop = self._tmin_tmax_to_start_stop(tmin, tmax) + buffer_size = self._get_buffer_size(buffer_size_sec) + + # write the raw file + _validate_type(split_naming, str, "split_naming") + _check_option("split_naming", split_naming, ("neuromag", "bids")) + + cfg = _RawFidWriterCfg(buffer_size, split_size, drop_small_buffer, fmt) + raw_fid_writer = _RawFidWriter(self, info, picks, projector, start, stop, cfg) + filenames = _write_raw(raw_fid_writer, fname, split_naming, overwrite) + return filenames + + @verbose + def export( + self, + fname, + fmt="auto", + physical_range="auto", + add_ch_type=False, + *, + overwrite=False, + verbose=None, + ): + """Export Raw to external formats. + + %(export_fmt_support_raw)s + + %(export_warning)s + + Parameters + ---------- + %(fname_export_params)s + %(export_fmt_params_raw)s + %(physical_range_export_params)s + %(add_ch_type_export_params)s + %(overwrite)s + + .. versionadded:: 0.24.1 + %(verbose)s + + Notes + ----- + .. versionadded:: 0.24 + + %(export_warning_note_raw)s + %(export_eeglab_note)s + %(export_edf_note)s + """ + from ..export import export_raw + + export_raw( + fname, + self, + fmt, + physical_range=physical_range, + add_ch_type=add_ch_type, + overwrite=overwrite, + verbose=verbose, + ) + + def _tmin_tmax_to_start_stop(self, tmin, tmax): + start = int(np.floor(tmin * self.info["sfreq"])) + + # "stop" is the first sample *not* to save, so we need +1's here + if tmax is None: + stop = np.inf + else: + stop = self.time_as_index(float(tmax), use_rounding=True)[0] + 1 + stop = min(stop, self.last_samp - self.first_samp + 1) + if stop <= start or stop <= 0: + raise ValueError(f"tmin ({tmin}) and tmax ({tmax}) yielded no samples") + return start, stop + + @copy_function_doc_to_method_doc(plot_raw) + def plot( + self, + events=None, + duration=10.0, + start=0.0, + n_channels=20, + bgcolor="w", + color=None, + bad_color="lightgray", + event_color="cyan", + *, + annotation_regex=".*", + scalings=None, + remove_dc=True, + order=None, + show_options=False, + title=None, + show=True, + block=False, + highpass=None, + lowpass=None, + filtorder=4, + clipping=_RAW_CLIP_DEF, + show_first_samp=False, + proj=True, + group_by="type", + butterfly=False, + decim="auto", + noise_cov=None, + event_id=None, + show_scrollbars=True, + show_scalebars=True, + time_format="float", + precompute=None, + use_opengl=None, + picks=None, + theme=None, + overview_mode=None, + splash=True, + verbose=None, + ): + return plot_raw( + self, + events, + duration, + start, + n_channels, + bgcolor, + color, + bad_color, + event_color, + annotation_regex=annotation_regex, + scalings=scalings, + remove_dc=remove_dc, + order=order, + show_options=show_options, + title=title, + show=show, + block=block, + highpass=highpass, + lowpass=lowpass, + filtorder=filtorder, + clipping=clipping, + show_first_samp=show_first_samp, + proj=proj, + group_by=group_by, + butterfly=butterfly, + decim=decim, + noise_cov=noise_cov, + event_id=event_id, + show_scrollbars=show_scrollbars, + show_scalebars=show_scalebars, + time_format=time_format, + precompute=precompute, + use_opengl=use_opengl, + picks=picks, + theme=theme, + overview_mode=overview_mode, + splash=splash, + verbose=verbose, + ) + + @property + def ch_names(self): + """Channel names.""" + return self.info["ch_names"] + + @property + def times(self): + """Time points.""" + out = _arange_div(self.n_times, float(self.info["sfreq"])) + out.flags["WRITEABLE"] = False + return out + + @property + def n_times(self): + """Number of time points.""" + return self.last_samp - self.first_samp + 1 + + @property + def duration(self): + """Duration of the data in seconds. + + .. versionadded:: 1.9 + """ + return self.n_times / self.info["sfreq"] + + def __len__(self): + """Return the number of time points. + + Returns + ------- + len : int + The number of time points. + + Examples + -------- + This can be used as:: + + >>> len(raw) # doctest: +SKIP + 1000 + """ + return self.n_times + + @verbose + def load_bad_channels(self, bad_file=None, force=False, verbose=None): + """Mark channels as bad from a text file. + + This function operates mostly in the style of the C function + ``mne_mark_bad_channels``. Each line in the text file will be + interpreted as a name of a bad channel. + + Parameters + ---------- + bad_file : path-like | None + File name of the text file containing bad channels. + If ``None`` (default), bad channels are cleared, but this + is more easily done directly with ``raw.info['bads'] = []``. + force : bool + Whether or not to force bad channel marking (of those + that exist) if channels are not found, instead of + raising an error. Defaults to ``False``. + %(verbose)s + """ + prev_bads = self.info["bads"] + new_bads = [] + if bad_file is not None: + # Check to make sure bad channels are there + names = frozenset(self.info["ch_names"]) + with open(bad_file) as fid: + bad_names = [line for line in fid.read().splitlines() if line] + new_bads = [ci for ci in bad_names if ci in names] + count_diff = len(bad_names) - len(new_bads) + + if count_diff > 0: + msg = ( + f"{count_diff} bad channel(s) from:" + f"\n{bad_file}\nnot found in:\n{self.filenames[0]}" + ) + if not force: + raise ValueError(msg) + else: + warn(msg) + + if prev_bads != new_bads: + logger.info(f"Updating bad channels: {prev_bads} -> {new_bads}") + self.info["bads"] = new_bads + else: + logger.info(f"No channels updated. Bads are: {prev_bads}") + + @fill_doc + def append(self, raws, preload=None): + """Concatenate raw instances as if they were continuous. + + .. note:: Boundaries of the raw files are annotated bad. If you wish to + use the data as continuous recording, you can remove the + boundary annotations after concatenation (see + :meth:`mne.Annotations.delete`). + + Parameters + ---------- + raws : list, or Raw instance + List of Raw instances to concatenate to the current instance + (in order), or a single raw instance to concatenate. + %(preload_concatenate)s + """ + if not isinstance(raws, list): + raws = [raws] + + # make sure the raws are compatible + all_raws = [self] + all_raws += raws + _check_raw_compatibility(all_raws) + + # deal with preloading data first (while files are separate) + all_preloaded = self.preload and all(r.preload for r in raws) + if preload is None: + if all_preloaded: + preload = True + else: + preload = False + + if preload is False: + if self.preload: + self._data = None + self.preload = False + else: + # do the concatenation ourselves since preload might be a string + nchan = self.info["nchan"] + c_ns = np.cumsum([rr.n_times for rr in ([self] + raws)]) + nsamp = c_ns[-1] + + if not self.preload: + this_data = self._read_segment() + else: + this_data = self._data + + # allocate the buffer + _data = _allocate_data(preload, (nchan, nsamp), this_data.dtype) + _data[:, 0 : c_ns[0]] = this_data + + for ri in range(len(raws)): + if not raws[ri].preload: + # read the data directly into the buffer + data_buffer = _data[:, c_ns[ri] : c_ns[ri + 1]] + raws[ri]._read_segment(data_buffer=data_buffer) + else: + _data[:, c_ns[ri] : c_ns[ri + 1]] = raws[ri]._data + self._data = _data + self.preload = True + + # now combine information from each raw file to construct new self + annotations = self.annotations + assert annotations.orig_time == self.info["meas_date"] + edge_samps = list() + for ri, r in enumerate(raws): + edge_samps.append(self.last_samp - self.first_samp + 1) + annotations = _combine_annotations( + annotations, + r.annotations, + edge_samps[-1], + self.first_samp, + r.first_samp, + self.info["sfreq"], + ) + self._first_samps = np.r_[self._first_samps, r._first_samps] + self._last_samps = np.r_[self._last_samps, r._last_samps] + self._read_picks += r._read_picks + self._raw_extras += r._raw_extras + self._filenames += r._filenames # use the private attribute to use the list + assert annotations.orig_time == self.info["meas_date"] + # The above _combine_annotations gets everything synchronized to + # first_samp. set_annotations (with no absolute time reference) assumes + # that the annotations being set are relative to first_samp, and will + # add it back on. So here we have to remove it: + if annotations.orig_time is None: + annotations.onset -= self.first_samp / self.info["sfreq"] + self.set_annotations(annotations) + for edge_samp in edge_samps: + onset = _sync_onset(self, edge_samp / self.info["sfreq"], True) + logger.debug( + f"Marking edge at {edge_samp} samples (maps to {onset:0.3f} sec)" + ) + self.annotations.append(onset, 0.0, "BAD boundary") + self.annotations.append(onset, 0.0, "EDGE boundary") + if not ( + len(self._first_samps) + == len(self._last_samps) + == len(self._raw_extras) + == len(self.filenames) + == len(self._read_picks) + ): + raise RuntimeError("Append error") # should never happen + + def close(self): + """Clean up the object. + + Does nothing for objects that close their file descriptors. + Things like Raw will override this method. + """ + pass # noqa + + def copy(self): + """Return copy of the instance. + + Returns + ------- + inst : same type as the input data + A copy of the instance. + """ + return deepcopy(self) + + def __repr__(self): # noqa: D105 + name = self.filenames[0] + name = "" if name is None else Path(name).name + ", " + size_str = str(sizeof_fmt(self._size)) # str in case it fails -> None + size_str += f", data{'' if self.preload else ' not'} loaded" + s = ( + f"{name}{len(self.ch_names)} x {self.n_times} " + f"({self.duration:0.1f} s), ~{size_str}" + ) + return f"<{self.__class__.__name__} | {s}>" + + @repr_html + def _repr_html_(self): + basenames = [f.name for f in self.filenames if f is not None] + + duration = self._get_duration_string() + + raw_template = _get_html_template("repr", "raw.html.jinja") + return raw_template.render( + inst=self, + filenames=basenames, + duration=duration, + ) + + def _get_duration_string(self): + # https://stackoverflow.com/a/10981895 + duration = np.ceil(self.duration) # always take full seconds + hours, remainder = divmod(duration, 3600) + minutes, seconds = divmod(remainder, 60) + return f"{hours:02.0f}:{minutes:02.0f}:{seconds:02.0f}" + + def add_events(self, events, stim_channel=None, replace=False): + """Add events to stim channel. + + Parameters + ---------- + events : ndarray, shape (n_events, 3) + Events to add. The first column specifies the sample number of + each event, the second column is ignored, and the third column + provides the event value. If events already exist in the Raw + instance at the given sample numbers, the event values will be + added together. + stim_channel : str | None + Name of the stim channel to add to. If None, the config variable + 'MNE_STIM_CHANNEL' is used. If this is not found, it will default + to ``'STI 014'``. + replace : bool + If True the old events on the stim channel are removed before + adding the new ones. + + Notes + ----- + Data must be preloaded in order to add events. + """ + _check_preload(self, "Adding events") + events = np.asarray(events) + if events.ndim != 2 or events.shape[1] != 3: + raise ValueError("events must be shape (n_events, 3)") + stim_channel = _get_stim_channel(stim_channel, self.info) + pick = pick_channels(self.ch_names, stim_channel, ordered=False) + if len(pick) == 0: + raise ValueError(f"Channel {stim_channel} not found") + pick = pick[0] + idx = events[:, 0].astype(int) + if np.any(idx < self.first_samp) or np.any(idx > self.last_samp): + raise ValueError( + f"event sample numbers must be between {self.first_samp} " + f"and {self.last_samp}" + ) + if not all(idx == events[:, 0]): + raise ValueError("event sample numbers must be integers") + if replace: + self._data[pick, :] = 0.0 + self._data[pick, idx - self.first_samp] += events[:, 2] + + def _get_buffer_size(self, buffer_size_sec=None): + """Get the buffer size.""" + if buffer_size_sec is None: + buffer_size_sec = self.buffer_size_sec + buffer_size_sec = float(buffer_size_sec) + return int(np.ceil(buffer_size_sec * self.info["sfreq"])) + + @verbose + def compute_psd( + self, + method="welch", + fmin=0, + fmax=np.inf, + tmin=None, + tmax=None, + picks=None, + exclude=(), + proj=False, + remove_dc=True, + reject_by_annotation=True, + *, + n_jobs=1, + verbose=None, + **method_kw, + ): + """Perform spectral analysis on sensor data. + + Parameters + ---------- + %(method_psd)s + Note that ``"multitaper"`` cannot be used if ``reject_by_annotation=True`` + and there are ``"bad_*"`` annotations in the :class:`~mne.io.Raw` data; + in such cases use ``"welch"``. Default is ``'welch'``. + %(fmin_fmax_psd)s + %(tmin_tmax_psd)s + %(picks_good_data_noref)s + %(exclude_psd)s + %(proj_psd)s + %(remove_dc)s + %(reject_by_annotation_psd)s + %(n_jobs)s + %(verbose)s + %(method_kw_psd)s + + Returns + ------- + spectrum : instance of Spectrum + The spectral representation of the data. + + Notes + ----- + .. versionadded:: 1.2 + + References + ---------- + .. footbibliography:: + """ + method = _validate_method(method, type(self).__name__) + self._set_legacy_nfft_default(tmin, tmax, method, method_kw) + + return Spectrum( + self, + method=method, + fmin=fmin, + fmax=fmax, + tmin=tmin, + tmax=tmax, + picks=picks, + exclude=exclude, + proj=proj, + remove_dc=remove_dc, + reject_by_annotation=reject_by_annotation, + n_jobs=n_jobs, + verbose=verbose, + **method_kw, + ) + + @verbose + def compute_tfr( + self, + method, + freqs, + *, + tmin=None, + tmax=None, + picks=None, + proj=False, + output="power", + reject_by_annotation=True, + decim=1, + n_jobs=None, + verbose=None, + **method_kw, + ): + """Compute a time-frequency representation of sensor data. + + Parameters + ---------- + %(method_tfr)s + %(freqs_tfr)s + %(tmin_tmax_psd)s + %(picks_good_data_noref)s + %(proj_psd)s + %(output_compute_tfr)s + %(reject_by_annotation_tfr)s + %(decim_tfr)s + %(n_jobs)s + %(verbose)s + %(method_kw_tfr)s + + Returns + ------- + tfr : instance of RawTFR + The time-frequency-resolved power estimates of the data. + + Notes + ----- + .. versionadded:: 1.7 + + References + ---------- + .. footbibliography:: + """ + _check_option("output", output, ("power", "phase", "complex")) + method_kw["output"] = output + return RawTFR( + self, + method=method, + freqs=freqs, + tmin=tmin, + tmax=tmax, + picks=picks, + proj=proj, + reject_by_annotation=reject_by_annotation, + decim=decim, + n_jobs=n_jobs, + verbose=verbose, + **method_kw, + ) + + @verbose + def to_data_frame( + self, + picks=None, + index=None, + scalings=None, + copy=True, + start=None, + stop=None, + long_format=False, + time_format=None, + *, + verbose=None, + ): + """Export data in tabular structure as a pandas DataFrame. + + Channels are converted to columns in the DataFrame. By default, an + additional column "time" is added, unless ``index`` is not ``None`` + (in which case time values form the DataFrame's index). + + .. attention:: By default, returned data values are scaled from + SI units to a unit more suitable for plotting or statistical modeling. + See the description of the ``scalings`` parameter for details. + + Parameters + ---------- + %(picks_all)s + %(index_df_raw)s + Defaults to ``None``. + %(scalings_df)s + %(copy_df)s + start : int | None + Starting sample index for creating the DataFrame from a temporal + span of the Raw object. ``None`` (the default) uses the first + sample. + stop : int | None + Ending sample index for creating the DataFrame from a temporal span + of the Raw object. ``None`` (the default) uses the last sample. + %(long_format_df_raw)s + %(time_format_df_raw)s + + .. versionadded:: 0.20 + %(verbose)s + + Returns + ------- + %(df_return)s + """ + # check pandas once here, instead of in each private utils function + pd = _check_pandas_installed() # noqa + # arg checking + valid_index_args = ["time"] + valid_time_formats = ["ms", "timedelta", "datetime"] + index = _check_pandas_index_arguments(index, valid_index_args) + time_format = _check_time_format( + time_format, valid_time_formats, self.info["meas_date"] + ) + # get data + picks = _picks_to_idx(self.info, picks, "all", exclude=()) + data, times = self[picks, start:stop] + data = data.T + if copy: + data = data.copy() + data = _scale_dataframe_data(self, data, picks, scalings) + # prepare extra columns / multiindex + mindex = list() + times = _convert_times( + times, + time_format, + meas_date=self.info["meas_date"], + first_time=self.first_time, + ) + mindex.append(("time", times)) + # build DataFrame + df = _build_data_frame( + self, data, picks, long_format, mindex, index, default_index=["time"] + ) + return df + + def describe(self, data_frame=False): + """Describe channels (name, type, descriptive statistics). + + Parameters + ---------- + data_frame : bool + If True, return results in a pandas.DataFrame. If False, only print + results. Columns 'ch', 'type', and 'unit' indicate channel index, + channel type, and unit of the remaining five columns. These columns + are 'min' (minimum), 'Q1' (first quartile or 25% percentile), + 'median', 'Q3' (third quartile or 75% percentile), and 'max' + (maximum). + + Returns + ------- + result : None | pandas.DataFrame + If data_frame=False, returns None. If data_frame=True, returns + results in a pandas.DataFrame (requires pandas). + """ + nchan = self.info["nchan"] + + # describe each channel + cols = defaultdict(list) + cols["name"] = self.ch_names + for i in range(nchan): + ch = self.info["chs"][i] + data = self[i][0] + cols["type"].append(channel_type(self.info, i)) + cols["unit"].append(_unit2human[ch["unit"]]) + cols["min"].append(np.min(data)) + cols["Q1"].append(np.percentile(data, 25)) + cols["median"].append(np.median(data)) + cols["Q3"].append(np.percentile(data, 75)) + cols["max"].append(np.max(data)) + + if data_frame: # return data frame + import pandas as pd + + df = pd.DataFrame(cols) + df.index.name = "ch" + return df + + # convert into commonly used units + scalings = _handle_default("scalings") + units = _handle_default("units") + for i in range(nchan): + unit = units.get(cols["type"][i]) + scaling = scalings.get(cols["type"][i], 1) + if scaling != 1: + cols["unit"][i] = unit + for col in ["min", "Q1", "median", "Q3", "max"]: + cols[col][i] *= scaling + + lens = { + "ch": max(2, len(str(nchan))), + "name": max(4, max([len(n) for n in cols["name"]])), + "type": max(4, max([len(t) for t in cols["type"]])), + "unit": max(4, max([len(u) for u in cols["unit"]])), + } + + # print description, start with header + print(self) + print( + f"{'ch':>{lens['ch']}} " + f"{'name':<{lens['name']}} " + f"{'type':<{lens['type']}} " + f"{'unit':<{lens['unit']}} " + f"{'min':>9} " + f"{'Q1':>9} " + f"{'median':>9} " + f"{'Q3':>9} " + f"{'max':>9}" + ) + # print description for each channel + for i in range(nchan): + msg = ( + f"{i:>{lens['ch']}} " + f"{cols['name'][i]:<{lens['name']}} " + f"{cols['type'][i].upper():<{lens['type']}} " + f"{cols['unit'][i]:<{lens['unit']}} " + ) + for col in ["min", "Q1", "median", "Q3"]: + msg += f"{cols[col][i]:>9.2f} " + msg += f"{cols['max'][i]:>9.2f}" + print(msg) + + +def _allocate_data(preload, shape, dtype): + """Allocate data in memory or in memmap for preloading.""" + if preload in (None, True): # None comes from _read_segment + data = np.zeros(shape, dtype) + else: + _validate_type(preload, "path-like", "preload") + data = np.memmap(str(preload), mode="w+", dtype=dtype, shape=shape) + return data + + +def _convert_slice(sel): + if len(sel) and (np.diff(sel) == 1).all(): + return slice(sel[0], sel[-1] + 1) + else: + return sel + + +def _get_ch_factors(inst, units, picks_idxs): + """Get scaling factors for data, given units. + + Parameters + ---------- + inst : instance of Raw | Epochs | Evoked + The instance. + %(units)s + picks_idxs : ndarray + The picks as provided through _picks_to_idx. + + Returns + ------- + ch_factors : ndarray of floats, shape(len(picks),) + The scaling factors for each channel, ordered according + to picks. + + """ + _validate_type(units, types=(None, str, dict), item_name="units") + ch_factors = np.ones(len(picks_idxs)) + si_units = _handle_default("si_units") + ch_types = inst.get_channel_types(picks=picks_idxs) + # Convert to dict if str units + if isinstance(units, str): + # Check that there is only one channel type + unit_ch_type = list(set(ch_types) & set(si_units.keys())) + if len(unit_ch_type) > 1: + raise ValueError( + '"units" cannot be str if there is more than ' + "one channel type with a unit " + f"{unit_ch_type}." + ) + units = {unit_ch_type[0]: units} # make the str argument a dict + # Loop over the dict to get channel factors + if isinstance(units, dict): + for ch_type, ch_unit in units.items(): + # Get the scaling factors + scaling = _get_scaling(ch_type, ch_unit) + if scaling != 1: + indices = [i_ch for i_ch, ch in enumerate(ch_types) if ch == ch_type] + ch_factors[indices] *= scaling + + return ch_factors + + +def _get_scaling(ch_type, target_unit): + """Return the scaling factor based on the channel type and a target unit. + + Parameters + ---------- + ch_type : str + The channel type. + target_unit : str + The target unit for the provided channel type. + + Returns + ------- + scaling : float + The scaling factor to convert from the si_unit (used by default for MNE + objects) to the target unit. + """ + scaling = 1.0 + si_units = _handle_default("si_units") + si_units_splitted = {key: si_units[key].split("/") for key in si_units} + prefixes = _handle_default("prefixes") + prefix_list = list(prefixes.keys()) + + # Check that the provided unit exists for the ch_type + unit_list = target_unit.split("/") + if ch_type not in si_units.keys(): + raise KeyError( + f"{ch_type} is not a channel type that can be scaled from units." + ) + si_unit_list = si_units_splitted[ch_type] + if len(unit_list) != len(si_unit_list): + raise ValueError( + f"{target_unit} is not a valid unit for {ch_type}, use a " + f"sub-multiple of {si_units[ch_type]} instead." + ) + for i, unit in enumerate(unit_list): + valid = [prefix + si_unit_list[i] for prefix in prefix_list] + if unit not in valid: + raise ValueError( + f"{target_unit} is not a valid unit for {ch_type}, use a " + f"sub-multiple of {si_units[ch_type]} instead." + ) + + # Get the scaling factors + for i, unit in enumerate(unit_list): + has_square = False + # XXX power normally not used as csd cannot get_data() + if unit[-1] == "²": + has_square = True + if unit == "m" or unit == "m²": + factor = 1.0 + elif unit[0] in prefixes.keys(): + factor = prefixes[unit[0]] + else: + factor = 1.0 + if factor != 1: + if has_square: + factor *= factor + if i == 0: + scaling = scaling * factor + elif i == 1: + scaling = scaling / factor + return scaling + + +class _ReadSegmentFileProtector: + """Ensure only _filenames, _raw_extras, and _read_segment_file are used.""" + + def __init__(self, raw): + self.__raw = raw + assert hasattr(raw, "_projector") + self._filenames = raw._filenames + self._raw_extras = raw._raw_extras + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + return self.__raw.__class__._read_segment_file( + self, data, idx, fi, start, stop, cals, mult + ) + + @property + def filenames(self) -> tuple[Path, ...]: + return tuple(self._filenames) + + +class _RawShell: + """Create a temporary raw object.""" + + def __init__(self): + self.first_samp = None + self.last_samp = None + self._first_time = None + self._last_time = None + self._cals = None + self._projector = None + + @property + def n_times(self): # noqa: D102 + return self.last_samp - self.first_samp + 1 + + @property + def annotations(self): # noqa: D102 + return self._annotations + + def set_annotations(self, annotations): + if annotations is None: + annotations = Annotations([], [], [], None) + self._annotations = annotations.copy() + + +############################################################################### +# Writing + +# Assume we never hit more than 100 splits, like for epochs +MAX_N_SPLITS = 100 + + +def _write_raw(raw_fid_writer, fpath, split_naming, overwrite): + """Write raw file with splitting.""" + dir_path = fpath.parent + _check_fname( + dir_path, + overwrite="read", + must_exist=True, + name="parent directory", + need_dir=True, + ) + # We have to create one extra filename here to make the for loop below happy, + # but it will raise an error if it actually gets used + split_fnames = _make_split_fnames( + fpath.name, n_splits=MAX_N_SPLITS + 1, split_naming=split_naming + ) + is_next_split, prev_fname = True, None + output_fnames = [] + for part_idx in range(0, MAX_N_SPLITS): + if not is_next_split: + break + bids_special_behavior = part_idx == 0 and split_naming == "bids" + if bids_special_behavior: + reserved_fname = dir_path / split_fnames[0] + logger.info(f"Reserving possible split file {reserved_fname.name}") + _check_fname(reserved_fname, overwrite) + reserved_ctx = _ReservedFilename(reserved_fname) + use_fpath = fpath + else: + reserved_ctx = nullcontext() + use_fpath = dir_path / split_fnames[part_idx] + next_fname = split_fnames[part_idx + 1] + _check_fname(use_fpath, overwrite) + + logger.info(f"Writing {use_fpath}") + with start_and_end_file(use_fpath) as fid, reserved_ctx: + is_next_split = raw_fid_writer.write(fid, part_idx, prev_fname, next_fname) + logger.info(f"Closing {use_fpath}") + if bids_special_behavior and is_next_split: + logger.info(f"Renaming BIDS split file {fpath.name}") + prev_fname = dir_path / split_fnames[0] + shutil.move(use_fpath, prev_fname) + output_fnames.append(prev_fname) + else: + output_fnames.append(use_fpath) + prev_fname = use_fpath + else: + raise RuntimeError(f"Exceeded maximum number of splits ({MAX_N_SPLITS}).") + + logger.info("[done]") + return output_fnames + + +class _ReservedFilename: + def __init__(self, fname: Path): + self.fname = fname + assert fname.parent.exists(), fname + with open(fname, "w"): + pass + self.remove = True + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_value, traceback): + if self.remove: + self.fname.unlink() + + +@dataclass(frozen=True) +class _RawFidWriterCfg: + buffer_size: int + split_size: int + drop_small_buffer: bool + fmt: str + reset_range: bool = field(init=False) + data_type: int = field(init=False) + + def __post_init__(self): + type_dict = dict( + short=FIFF.FIFFT_DAU_PACK16, + int=FIFF.FIFFT_INT, + single=FIFF.FIFFT_FLOAT, + double=FIFF.FIFFT_DOUBLE, + ) + _check_option("fmt", self.fmt, type_dict.keys()) + reset_dict = dict(short=False, int=False, single=True, double=True) + object.__setattr__(self, "reset_range", reset_dict[self.fmt]) + object.__setattr__(self, "data_type", type_dict[self.fmt]) + + +class _RawFidWriter: + def __init__(self, raw, info, picks, projector, start, stop, cfg): + self.raw = raw + self.picks = _picks_to_idx(info, picks, "all", ()) + self.info = pick_info(info, sel=self.picks, copy=True) + for k in range(self.info["nchan"]): + # Scan numbers may have been messed up + self.info["chs"][k]["scanno"] = k + 1 # scanno starts at 1 in FIF format + if cfg.reset_range: + self.info["chs"][k]["range"] = 1.0 + self.projector = projector + # self.start is the only mutable attribute in this design! + self.start, self.stop = start, stop + self.cfg = cfg + + def write(self, fid, part_idx, prev_fname, next_fname): + self._check_start_stop_within_bounds() + start_block(fid, FIFF.FIFFB_MEAS) + _write_raw_metadata( + fid, + self.info, + self.cfg.data_type, + self.cfg.reset_range, + self.raw.annotations, + ) + self.start = _write_raw_data( + self.raw, + self.info, + self.picks, + fid, + part_idx, + self.start, + self.stop, + self.cfg.buffer_size, + prev_fname, + self.cfg.split_size, + next_fname, + self.projector, + self.cfg.drop_small_buffer, + self.cfg.fmt, + ) + end_block(fid, FIFF.FIFFB_MEAS) + is_next_split = self.start < self.stop + return is_next_split + + def _check_start_stop_within_bounds(self): + # we've done something wrong if we hit this + n_times_max = len(self.raw.times) + error_msg = ( + f"Can't write raw file with no data: {self.start} -> {self.stop} " + f"(max: {n_times_max}) requested" + ) + if self.start >= self.stop or self.stop > n_times_max: + raise RuntimeError(error_msg) + + +def _write_raw_data( + raw, + info, + picks, + fid, + part_idx, + start, + stop, + buffer_size, + prev_fname, + split_size, + next_fname, + projector, + drop_small_buffer, + fmt, +): + # Start the raw data + data_kind = "IAS_" if info.get("maxshield", False) else "" + data_kind = getattr(FIFF, f"FIFFB_{data_kind}RAW_DATA") + start_block(fid, data_kind) + + first_samp = raw.first_samp + start + if first_samp != 0: + write_int(fid, FIFF.FIFF_FIRST_SAMPLE, first_samp) + + # previous file name and id + if part_idx > 0 and prev_fname is not None: + start_block(fid, FIFF.FIFFB_REF) + write_int(fid, FIFF.FIFF_REF_ROLE, FIFF.FIFFV_ROLE_PREV_FILE) + write_string(fid, FIFF.FIFF_REF_FILE_NAME, prev_fname) + if info["meas_id"] is not None: + write_id(fid, FIFF.FIFF_REF_FILE_ID, info["meas_id"]) + write_int(fid, FIFF.FIFF_REF_FILE_NUM, part_idx - 1) + end_block(fid, FIFF.FIFFB_REF) + + pos_prev = fid.tell() + if pos_prev > split_size: + raise ValueError( + 'file is larger than "split_size" after writing ' + "measurement information, you must use a larger " + f"value for split size: {pos_prev} plus enough bytes for " + "the chosen buffer_size" + ) + + # Check to see if this has acquisition skips and, if so, if we can + # write out empty buffers instead of zeroes + firsts = list(range(start, stop, buffer_size)) + lasts = np.array(firsts) + buffer_size + if lasts[-1] > stop: + lasts[-1] = stop + sk_onsets, sk_ends = _annotations_starts_stops(raw, "bad_acq_skip") + do_skips = False + if len(sk_onsets) > 0: + if np.isin(sk_onsets, firsts).all() and np.isin(sk_ends, lasts).all(): + do_skips = True + else: + if part_idx == 0: + warn( + "Acquisition skips detected but did not fit evenly into " + "output buffer_size, will be written as zeroes." + ) + + cals = [ch["cal"] * ch["range"] for ch in info["chs"]] + # Write the blocks + n_current_skip = 0 + new_start = start + for first, last in zip(firsts, lasts): + if do_skips: + if ((first >= sk_onsets) & (last <= sk_ends)).any(): + # Track how many we have + n_current_skip += 1 + continue + elif n_current_skip > 0: + # Write out an empty buffer instead of data + write_int(fid, FIFF.FIFF_DATA_SKIP, n_current_skip) + # These two NOPs appear to be optional (MaxFilter does not do + # it, but some acquisition machines do) so let's not bother. + # write_nop(fid) + # write_nop(fid) + n_current_skip = 0 + data, times = raw[picks, first:last] + assert len(times) == last - first + + if projector is not None: + data = np.dot(projector, data) + + if drop_small_buffer and (first > start) and (len(times) < buffer_size): + logger.info("Skipping data chunk due to small buffer ... [done]") + break + logger.debug(f"Writing FIF {first:6d} ... {last:6d} ...") + _write_raw_buffer(fid, data, cals, fmt) + + pos = fid.tell() + this_buff_size_bytes = pos - pos_prev + overage = pos - split_size + _NEXT_FILE_BUFFER + if overage > 0: + # This should occur on the first buffer write of the file, so + # we should mention the space required for the meas info + raise ValueError( + f"buffer size ({this_buff_size_bytes}) is too large for the " + f"given split size ({split_size}) " + f"by {overage} bytes after writing info ({pos_prev}) and " + "leaving enough space " + f'for end tags ({_NEXT_FILE_BUFFER}): decrease "buffer_size_sec" ' + 'or increase "split_size".' + ) + + new_start = last + # Split files if necessary, leave some space for next file info + # make sure we check to make sure we actually *need* another buffer + # with the "and" check + if ( + pos >= split_size - this_buff_size_bytes - _NEXT_FILE_BUFFER + and first + buffer_size < stop + ): + start_block(fid, FIFF.FIFFB_REF) + write_int(fid, FIFF.FIFF_REF_ROLE, FIFF.FIFFV_ROLE_NEXT_FILE) + write_string(fid, FIFF.FIFF_REF_FILE_NAME, next_fname.name) + if info["meas_id"] is not None: + write_id(fid, FIFF.FIFF_REF_FILE_ID, info["meas_id"]) + write_int(fid, FIFF.FIFF_REF_FILE_NUM, part_idx + 1) + end_block(fid, FIFF.FIFFB_REF) + + break + pos_prev = pos + + end_block(fid, data_kind) + return new_start + + +@fill_doc +def _write_raw_metadata(fid, info, data_type, reset_range, annotations): + """Start write raw data in file. + + Parameters + ---------- + fid : file + The created file. + %(info_not_none)s + data_type : int + The data_type in case it is necessary. Should be 4 (FIFFT_FLOAT), + 5 (FIFFT_DOUBLE), 16 (FIFFT_DAU_PACK16), or 3 (FIFFT_INT) for raw data. + reset_range : bool + If True, the info['chs'][k]['range'] parameter will be set to unity. + annotations : instance of Annotations + The annotations to write. + + """ + # + # Create the file and save the essentials + # + write_id(fid, FIFF.FIFF_BLOCK_ID) + if info["meas_id"] is not None: + write_id(fid, FIFF.FIFF_PARENT_BLOCK_ID, info["meas_id"]) + + write_meas_info(fid, info, data_type=data_type, reset_range=reset_range) + + # + # Annotations + # + if len(annotations) > 0: # don't save empty annot + _write_annotations(fid, annotations) + + +def _write_raw_buffer(fid, buf, cals, fmt): + """Write raw buffer. + + Parameters + ---------- + fid : file descriptor + an open raw data file. + buf : array + The buffer to write. + cals : array + Calibration factors. + fmt : str + 'short', 'int', 'single', or 'double' for 16/32 bit int or 32/64 bit + float for each item. This will be doubled for complex datatypes. Note + that short and int formats cannot be used for complex data. + """ + if buf.shape[0] != len(cals): + raise ValueError("buffer and calibration sizes do not match") + + _check_option("fmt", fmt, ["short", "int", "single", "double"]) + + cast_int = False # allow unsafe cast + if np.isrealobj(buf): + if fmt == "short": + write_function = write_dau_pack16 + cast_int = True + elif fmt == "int": + write_function = write_int + cast_int = True + elif fmt == "single": + write_function = write_float + else: + write_function = write_double + else: + if fmt == "single": + write_function = write_complex64 + elif fmt == "double": + write_function = write_complex128 + else: + raise ValueError( + 'only "single" and "double" supported for writing complex data' + ) + + buf = buf / np.ravel(cals)[:, None] + if cast_int: + buf = buf.astype(np.int32) + write_function(fid, FIFF.FIFF_DATA_BUFFER, buf) + + +def _check_raw_compatibility(raw): + """Ensure all instances of Raw have compatible parameters.""" + for ri in range(1, len(raw)): + if not isinstance(raw[ri], type(raw[0])): + raise ValueError(f"raw[{ri}] type must match") + for key in ("nchan", "sfreq"): + a, b = raw[ri].info[key], raw[0].info[key] + if a != b: + raise ValueError( + f"raw[{ri}].info[{key}] must match:\n{repr(a)} != {repr(b)}" + ) + for kind in ("bads", "ch_names"): + set1 = set(raw[0].info[kind]) + set2 = set(raw[ri].info[kind]) + mismatch = set1.symmetric_difference(set2) + if mismatch: + raise ValueError( + f"raw[{ri}]['info'][{kind}] do not match: {sorted(mismatch)}" + ) + if any(raw[ri]._cals != raw[0]._cals): + raise ValueError(f"raw[{ri}]._cals must match") + if len(raw[0].info["projs"]) != len(raw[ri].info["projs"]): + raise ValueError("SSP projectors in raw files must be the same") + if not all( + _proj_equal(p1, p2) + for p1, p2 in zip(raw[0].info["projs"], raw[ri].info["projs"]) + ): + raise ValueError("SSP projectors in raw files must be the same") + if any(r.orig_format != raw[0].orig_format for r in raw): + warn( + "raw files do not all have the same data format, could result in " + 'precision mismatch. Setting raw.orig_format="unknown"' + ) + raw[0].orig_format = "unknown" + + +@verbose +def concatenate_raws( + raws, preload=None, events_list=None, *, on_mismatch="raise", verbose=None +): + """Concatenate `~mne.io.Raw` instances as if they were continuous. + + .. note:: ``raws[0]`` is modified in-place to achieve the concatenation. + Boundaries of the raw files are annotated bad. If you wish to use + the data as continuous recording, you can remove the boundary + annotations after concatenation (see + :meth:`mne.Annotations.delete`). + + Parameters + ---------- + raws : list + List of `~mne.io.Raw` instances to concatenate (in order). + %(preload_concatenate)s + events_list : None | list + The events to concatenate. Defaults to ``None``. + %(on_mismatch_info)s + %(verbose)s + + Returns + ------- + raw : instance of Raw + The result of the concatenation (first Raw instance passed in). + events : ndarray of int, shape (n_events, 3) + The events. Only returned if ``event_list`` is not None. + """ + for idx, raw in enumerate(raws[1:], start=1): + _ensure_infos_match( + info1=raws[0].info, + info2=raw.info, + name=f"raws[{idx}]", + on_mismatch=on_mismatch, + ) + + if events_list is not None: + if len(events_list) != len(raws): + raise ValueError( + "`raws` and `event_list` are required to be of the same length" + ) + first, last = zip(*[(r.first_samp, r.last_samp) for r in raws]) + events = concatenate_events(events_list, first, last) + raws[0].append(raws[1:], preload) + + if events_list is None: + return raws[0] + else: + return raws[0], events + + +@fill_doc +def match_channel_orders(insts, copy=True): + """Ensure consistent channel order across instances (Raw, Epochs, or Evoked). + + Parameters + ---------- + insts : list + List of :class:`~mne.io.Raw`, :class:`~mne.Epochs`, + or :class:`~mne.Evoked` instances to order. + %(copy_df)s + + Returns + ------- + list of Raw | list of Epochs | list of Evoked + List of instances (Raw, Epochs, or Evoked) with channel orders matched + according to the order they had in the first item in the ``insts`` list. + """ + insts = deepcopy(insts) if copy else insts + ch_order = insts[0].ch_names + for inst in insts[1:]: + inst.reorder_channels(ch_order) + return insts + + +def _check_maxshield(allow_maxshield): + """Warn or error about MaxShield.""" + msg = ( + "This file contains raw Internal Active " + "Shielding data. It may be distorted. Elekta " + "recommends it be run through MaxFilter to " + "produce reliable results. Consider closing " + "the file and running MaxFilter on the data." + ) + if allow_maxshield: + if not (isinstance(allow_maxshield, str) and allow_maxshield == "yes"): + warn(msg) + else: + msg += ( + " Use allow_maxshield=True if you are sure you" + " want to load the data despite this warning." + ) + raise ValueError(msg) + + +def _get_fname_rep(fname): + if not _file_like(fname): + out = str(fname) + else: + out = "file-like" + try: + out += f' "{fname.name}"' + except Exception: + pass + return out diff --git a/mne-python/source/mne/io/besa/__init__.py b/mne-python/source/mne/io/besa/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a91614c31a4180bf27425a4f9b992498bbcdbec3 --- /dev/null +++ b/mne-python/source/mne/io/besa/__init__.py @@ -0,0 +1,7 @@ +"""Support for various BESA file formats.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .besa import read_evoked_besa diff --git a/mne-python/source/mne/io/besa/besa.py b/mne-python/source/mne/io/besa/besa.py new file mode 100644 index 0000000000000000000000000000000000000000..d6d4ee9657c50d99c6788589c95bd135f0bc43d9 --- /dev/null +++ b/mne-python/source/mne/io/besa/besa.py @@ -0,0 +1,274 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from collections import OrderedDict +from pathlib import Path + +import numpy as np + +from ..._fiff.meas_info import create_info +from ...evoked import EvokedArray +from ...utils import fill_doc, logger, verbose + + +@fill_doc +@verbose +def read_evoked_besa(fname, verbose=None): + """Reader function for BESA ``.avr`` or ``.mul`` files. + + When a ``.elp`` sidecar file is present, it will be used to determine + electrode information. + + Parameters + ---------- + fname : path-like + Path to the ``.avr`` or ``.mul`` file. + %(verbose)s + + Returns + ------- + ev : Evoked + The evoked data in the .avr or .mul file. + """ + fname = Path(fname) + if fname.suffix == ".avr": + return _read_evoked_besa_avr(fname, verbose) + elif fname.suffix == ".mul": + return _read_evoked_besa_mul(fname, verbose) + else: + raise ValueError("Filename must end in either .avr or .mul") + + +@verbose +def _read_evoked_besa_avr(fname, verbose): + """Create EvokedArray from a BESA .avr file.""" + with open(fname) as f: + header = f.readline().strip() + + # There are two versions of .avr files. The old style, generated by + # BESA 1, 2 and 3 does not define Nchan and does not have channel names + # in the file. + new_style = "Nchan=" in header + if new_style: + ch_names = f.readline().strip().split() + else: + ch_names = None + + fields = _parse_header(header) + data = np.loadtxt(fname, skiprows=2 if new_style else 1, ndmin=2) + ch_types = _read_elp_sidecar(fname) + + # Consolidate channel names + if new_style: + if len(ch_names) != len(data): + raise RuntimeError( + "Mismatch between the number of channel names defined in " + f"the .avr file ({len(ch_names)}) and the number of rows " + f"in the data matrix ({len(data)})." + ) + else: + # Determine channel names from the .elp sidecar file + if ch_types is not None: + ch_names = list(ch_types.keys()) + if len(ch_names) != len(data): + raise RuntimeError( + "Mismatch between the number of channels " + f"defined in the .avr file ({len(data)}) " + f"and .elp file ({len(ch_names)})." + ) + else: + logger.info( + "No .elp file found and no channel names present in " + "the .avr file. Falling back to generic names. " + ) + ch_names = [f"CH{i + 1:02d}" for i in range(len(data))] + + # Consolidate channel types + if ch_types is None: + logger.info("Marking all channels as EEG.") + ch_types = ["eeg"] * len(ch_names) + else: + ch_types = [ch_types[ch] for ch in ch_names] + + # Go over all the header fields and make sure they are all defined to + # something sensible. + if "Npts" in fields: + fields["Npts"] = int(fields["Npts"]) + if fields["Npts"] != data.shape[1]: + logger.warn( + f"The size of the data matrix ({data.shape}) does not " + f'match the "Npts" field ({fields["Npts"]}).' + ) + if "Nchan" in fields: + fields["Nchan"] = int(fields["Nchan"]) + if fields["Nchan"] != data.shape[0]: + logger.warn( + f"The size of the data matrix ({data.shape}) does not " + f'match the "Nchan" field ({fields["Nchan"]}).' + ) + if "DI" in fields: + fields["DI"] = float(fields["DI"]) + else: + raise RuntimeError( + 'No "DI" field present. Could not determine sampling frequency.' + ) + if "TSB" in fields: + fields["TSB"] = float(fields["TSB"]) + else: + fields["TSB"] = 0 + if "SB" in fields: + fields["SB"] = float(fields["SB"]) + else: + fields["SB"] = 1.0 + if "SegmentName" not in fields: + fields["SegmentName"] = "" + + # Build the Evoked object based on the header fields. + info = create_info(ch_names, sfreq=1000 / fields["DI"], ch_types="eeg") + return EvokedArray( + data / fields["SB"] / 1e6, + info, + tmin=fields["TSB"] / 1000, + comment=fields["SegmentName"], + verbose=verbose, + ) + + +@verbose +def _read_evoked_besa_mul(fname, verbose): + """Create EvokedArray from a BESA .mul file.""" + with open(fname) as f: + header = f.readline().strip() + ch_names = f.readline().strip().split() + + fields = _parse_header(header) + data = np.loadtxt(fname, skiprows=2, ndmin=2) + + if len(ch_names) != data.shape[1]: + raise RuntimeError( + "Mismatch between the number of channel names " + f"defined in the .mul file ({len(ch_names)}) " + "and the number of columns in the data matrix " + f"({data.shape[1]})." + ) + + # Consolidate channel types + ch_types = _read_elp_sidecar(fname) + if ch_types is None: + logger.info("Marking all channels as EEG.") + ch_types = ["eeg"] * len(ch_names) + else: + ch_types = [ch_types[ch] for ch in ch_names] + + # Go over all the header fields and make sure they are all defined to + # something sensible. + if "TimePoints" in fields: + fields["TimePoints"] = int(fields["TimePoints"]) + if fields["TimePoints"] != data.shape[0]: + logger.warn( + f"The size of the data matrix ({data.shape}) does not " + f'match the "TimePoints" field ({fields["TimePoints"]}).' + ) + if "Channels" in fields: + fields["Channels"] = int(fields["Channels"]) + if fields["Channels"] != data.shape[1]: + logger.warn( + f"The size of the data matrix ({data.shape}) does not " + f'match the "Channels" field ({fields["Channels"]}).' + ) + if "SamplingInterval[ms]" in fields: + fields["SamplingInterval[ms]"] = float(fields["SamplingInterval[ms]"]) + else: + raise RuntimeError( + 'No "SamplingInterval[ms]" field present. Could ' + "not determine sampling frequency." + ) + if "BeginSweep[ms]" in fields: + fields["BeginSweep[ms]"] = float(fields["BeginSweep[ms]"]) + else: + fields["BeginSweep[ms]"] = 0.0 + if "Bins/uV" in fields: + fields["Bins/uV"] = float(fields["Bins/uV"]) + else: + fields["Bins/uV"] = 1 + if "SegmentName" not in fields: + fields["SegmentName"] = "" + + # Build the Evoked object based on the header fields. + info = create_info( + ch_names, sfreq=1000 / fields["SamplingInterval[ms]"], ch_types=ch_types + ) + return EvokedArray( + data.T / fields["Bins/uV"] / 1e6, + info, + tmin=fields["BeginSweep[ms]"] / 1000, + comment=fields["SegmentName"], + verbose=verbose, + ) + + +def _parse_header(header): + """Parse an .avr or .mul header string into name/val pairs. + + The header line looks like: + Npts= 256 TSB= 0.000 DI= 4.000000 SB= 1.000 SC= 200.0 Nchan= 27 + No consistent use of separation chars, so parsing this is a bit iffy. + + Parameters + ---------- + header : str + The first line of the file. + + Returns + ------- + fields : dict + The parsed header fields + """ + parts = header.split() # Splits on one or more spaces + name_val_pairs = zip(parts[::2], parts[1::2]) + return dict((name.replace("=", ""), val) for name, val in name_val_pairs) + + +def _read_elp_sidecar(fname): + """Read a possible .elp sidecar file with electrode information. + + The reason we don't use the read_custom_montage for this is that we are + interested in the channel types, which a DigMontage object does not provide + us. + + Parameters + ---------- + fname : Path + The path of the .avr or .mul file. The corresponding .elp file will be + derived from this path. + + Returns + ------- + ch_type : OrderedDict | None + If the sidecar file exists, return a dictionary mapping channel names + to channel types. Otherwise returns ``None``. + """ + fname_elp = fname.parent / (fname.stem + ".elp") + if not fname_elp.exists(): + logger.info(f"No {fname_elp} file present containing electrode information.") + return None + + logger.info(f"Reading electrode names and types from {fname_elp}") + ch_types = OrderedDict() + with open(fname_elp) as f: + lines = f.readlines() + if len(lines[0].split()) > 3: + # Channel types present + for line in lines: + ch_type, ch_name = line.split()[:2] + ch_types[ch_name] = ch_type.lower() + else: + # No channel types present + logger.info( + "No channel types present in .elp file. Marking all channels as EEG." + ) + for line in lines: + ch_name = line.split()[:1] + ch_types[ch_name] = "eeg" + return ch_types diff --git a/mne-python/source/mne/io/besa/tests/data/simulation.avr b/mne-python/source/mne/io/besa/tests/data/simulation.avr new file mode 100644 index 0000000000000000000000000000000000000000..1e9c9bef6888a1734de344cecc070e682c2dc0f7 --- /dev/null +++ b/mne-python/source/mne/io/besa/tests/data/simulation.avr @@ -0,0 +1,35 @@ +Npts= 200 TSB= -100 DI= 5 SB= 1.00 SC= 500.0 Nchan= 33 SegmentName= simulation +Fp1 Fp2 F9 F7 F3 Fz F4 F8 F10 FC5 FC1 FC2 FC6 T9 T7 C3 Cz C4 T8 T10 CP5 CP1 CP2 CP6 P9 P7 P3 Pz P4 P8 P10 O1 O2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000128 0.000503 0.00111 0.00194 0.00296 0.00418 0.00557 0.00712 0.00882 0.0106 0.0126 0.0146 0.0168 0.019 0.0212 0.0235 0.0259 0.0282 0.0306 0.0329 0.0352 0.0375 0.0397 0.0418 0.0439 0.0458 0.0476 0.0493 0.0509 0.0523 0.0535 0.0545 0.0553 0.0559 0.0563 0.0564 0.0563 0.0559 0.0553 0.0545 0.0535 0.0523 0.0509 0.0493 0.0476 0.0458 0.0439 0.0418 0.0397 0.0375 0.0352 0.0329 0.0306 0.0282 0.0259 0.0235 0.0212 0.019 0.0168 0.0146 0.0126 0.0106 0.00882 0.00712 0.00557 0.00418 0.00296 0.00194 0.00111 0.000503 0.000128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00112 0.0044 0.00971 0.0169 0.0259 0.0365 0.0487 0.0623 0.0771 0.0931 0.11 0.128 0.147 0.166 0.186 0.206 0.226 0.247 0.267 0.288 0.308 0.328 0.347 0.365 0.383 0.4 0.416 0.431 0.445 0.457 0.467 0.476 0.484 0.489 0.492 0.493 0.492 0.489 0.484 0.476 0.467 0.457 0.445 0.431 0.416 0.4 0.383 0.365 0.347 0.328 0.308 0.288 0.267 0.247 0.226 0.206 0.186 0.166 0.147 0.128 0.11 0.0931 0.0771 0.0623 0.0487 0.0365 0.0259 0.0169 0.00971 0.0044 0.00112 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000128 0.000503 0.00111 0.00194 0.00296 0.00418 0.00557 0.00712 0.00882 0.0106 0.0126 0.0146 0.0168 0.019 0.0212 0.0235 0.0259 0.0282 0.0306 0.0329 0.0352 0.0375 0.0397 0.0418 0.0439 0.0458 0.0476 0.0493 0.0509 0.0523 0.0535 0.0545 0.0553 0.0559 0.0563 0.0564 0.0563 0.0559 0.0553 0.0545 0.0535 0.0523 0.0509 0.0493 0.0476 0.0458 0.0439 0.0418 0.0397 0.0375 0.0352 0.0329 0.0306 0.0282 0.0259 0.0235 0.0212 0.019 0.0168 0.0146 0.0126 0.0106 0.00882 0.00712 0.00557 0.00418 0.00296 0.00194 0.00111 0.000503 0.000128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.000426 -0.00167 -0.00369 -0.00643 -0.00984 -0.0139 -0.0185 -0.0236 -0.0293 -0.0353 -0.0418 -0.0486 -0.0557 -0.063 -0.0705 -0.0781 -0.0859 -0.0937 -0.101 -0.109 -0.117 -0.124 -0.132 -0.139 -0.146 -0.152 -0.158 -0.164 -0.169 -0.173 -0.178 -0.181 -0.184 -0.186 -0.187 -0.187 -0.187 -0.186 -0.184 -0.181 -0.178 -0.173 -0.169 -0.164 -0.158 -0.152 -0.146 -0.139 -0.132 -0.124 -0.117 -0.109 -0.101 -0.0937 -0.0859 -0.0781 -0.0705 -0.063 -0.0557 -0.0486 -0.0418 -0.0353 -0.0293 -0.0236 -0.0185 -0.0139 -0.00984 -0.00643 -0.00369 -0.00167 -0.000426 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00259 0.0102 0.0225 0.0392 0.06 0.0846 0.113 0.144 0.178 0.215 0.255 0.296 0.339 0.384 0.43 0.476 0.523 0.571 0.619 0.666 0.712 0.758 0.803 0.846 0.887 0.927 0.964 0.998 1.03 1.06 1.08 1.1 1.12 1.13 1.14 1.14 1.14 1.13 1.12 1.1 1.08 1.06 1.03 0.998 0.964 0.927 0.887 0.846 0.803 0.758 0.712 0.666 0.619 0.571 0.523 0.476 0.43 0.384 0.339 0.296 0.255 0.215 0.178 0.144 0.113 0.0846 0.06 0.0392 0.0225 0.0102 0.00259 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00259 0.0102 0.0225 0.0392 0.06 0.0846 0.113 0.144 0.178 0.215 0.255 0.296 0.339 0.384 0.43 0.476 0.523 0.571 0.619 0.666 0.712 0.758 0.803 0.846 0.887 0.927 0.964 0.998 1.03 1.06 1.08 1.1 1.12 1.13 1.14 1.14 1.14 1.13 1.12 1.1 1.08 1.06 1.03 0.998 0.964 0.927 0.887 0.846 0.803 0.758 0.712 0.666 0.619 0.571 0.523 0.476 0.43 0.384 0.339 0.296 0.255 0.215 0.178 0.144 0.113 0.0846 0.06 0.0392 0.0225 0.0102 0.00259 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.000426 -0.00167 -0.00369 -0.00643 -0.00984 -0.0139 -0.0185 -0.0236 -0.0293 -0.0353 -0.0418 -0.0486 -0.0557 -0.063 -0.0705 -0.0781 -0.0859 -0.0937 -0.101 -0.109 -0.117 -0.124 -0.132 -0.139 -0.146 -0.152 -0.158 -0.164 -0.169 -0.173 -0.178 -0.181 -0.184 -0.186 -0.187 -0.187 -0.187 -0.186 -0.184 -0.181 -0.178 -0.173 -0.169 -0.164 -0.158 -0.152 -0.146 -0.139 -0.132 -0.124 -0.117 -0.109 -0.101 -0.0937 -0.0859 -0.0781 -0.0705 -0.063 -0.0557 -0.0486 -0.0418 -0.0353 -0.0293 -0.0236 -0.0185 -0.0139 -0.00984 -0.00643 -0.00369 -0.00167 -0.000426 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00112 0.0044 0.00971 0.0169 0.0259 0.0365 0.0487 0.0623 0.0771 0.0931 0.11 0.128 0.147 0.166 0.186 0.206 0.226 0.247 0.267 0.288 0.308 0.328 0.347 0.365 0.383 0.4 0.416 0.431 0.445 0.457 0.467 0.476 0.484 0.489 0.492 0.493 0.492 0.489 0.484 0.476 0.467 0.457 0.445 0.431 0.416 0.4 0.383 0.365 0.347 0.328 0.308 0.288 0.267 0.247 0.226 0.206 0.186 0.166 0.147 0.128 0.11 0.0931 0.0771 0.0623 0.0487 0.0365 0.0259 0.0169 0.00971 0.0044 0.00112 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00707 0.0277 0.0612 0.107 0.163 0.23 0.307 0.393 0.486 0.587 0.694 0.807 0.924 1.05 1.17 1.3 1.43 1.56 1.68 1.81 1.94 2.07 2.19 2.3 2.42 2.52 2.62 2.72 2.8 2.88 2.95 3 3.05 3.08 3.1 3.11 3.1 3.08 3.05 3 2.95 2.88 2.8 2.72 2.62 2.52 2.42 2.3 2.19 2.07 1.94 1.81 1.68 1.56 1.43 1.3 1.17 1.05 0.924 0.807 0.694 0.587 0.486 0.393 0.307 0.23 0.163 0.107 0.0612 0.0277 0.00707 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00112 0.0044 0.00971 0.0169 0.0259 0.0365 0.0487 0.0623 0.0771 0.0931 0.11 0.128 0.147 0.166 0.186 0.206 0.226 0.247 0.267 0.288 0.308 0.328 0.347 0.365 0.383 0.4 0.416 0.431 0.445 0.457 0.467 0.476 0.484 0.489 0.492 0.493 0.492 0.489 0.484 0.476 0.467 0.457 0.445 0.431 0.416 0.4 0.383 0.365 0.347 0.328 0.308 0.288 0.267 0.247 0.226 0.206 0.186 0.166 0.147 0.128 0.11 0.0931 0.0771 0.0623 0.0487 0.0365 0.0259 0.0169 0.00971 0.0044 0.00112 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.000426 -0.00167 -0.00369 -0.00643 -0.00984 -0.0139 -0.0185 -0.0236 -0.0293 -0.0353 -0.0418 -0.0486 -0.0557 -0.063 -0.0705 -0.0781 -0.0859 -0.0937 -0.101 -0.109 -0.117 -0.124 -0.132 -0.139 -0.146 -0.152 -0.158 -0.164 -0.169 -0.173 -0.178 -0.181 -0.184 -0.186 -0.187 -0.187 -0.187 -0.186 -0.184 -0.181 -0.178 -0.173 -0.169 -0.164 -0.158 -0.152 -0.146 -0.139 -0.132 -0.124 -0.117 -0.109 -0.101 -0.0937 -0.0859 -0.0781 -0.0705 -0.063 -0.0557 -0.0486 -0.0418 -0.0353 -0.0293 -0.0236 -0.0185 -0.0139 -0.00984 -0.00643 -0.00369 -0.00167 -0.000426 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00259 0.0102 0.0225 0.0392 0.06 0.0846 0.113 0.144 0.178 0.215 0.255 0.296 0.339 0.384 0.43 0.476 0.523 0.571 0.619 0.666 0.712 0.758 0.803 0.846 0.887 0.927 0.964 0.998 1.03 1.06 1.08 1.1 1.12 1.13 1.14 1.14 1.14 1.13 1.12 1.1 1.08 1.06 1.03 0.998 0.964 0.927 0.887 0.846 0.803 0.758 0.712 0.666 0.619 0.571 0.523 0.476 0.43 0.384 0.339 0.296 0.255 0.215 0.178 0.144 0.113 0.0846 0.06 0.0392 0.0225 0.0102 0.00259 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00259 0.0102 0.0225 0.0392 0.06 0.0846 0.113 0.144 0.178 0.215 0.255 0.296 0.339 0.384 0.43 0.476 0.523 0.571 0.619 0.666 0.712 0.758 0.803 0.846 0.887 0.927 0.964 0.998 1.03 1.06 1.08 1.1 1.12 1.13 1.14 1.14 1.14 1.13 1.12 1.1 1.08 1.06 1.03 0.998 0.964 0.927 0.887 0.846 0.803 0.758 0.712 0.666 0.619 0.571 0.523 0.476 0.43 0.384 0.339 0.296 0.255 0.215 0.178 0.144 0.113 0.0846 0.06 0.0392 0.0225 0.0102 0.00259 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.000426 -0.00167 -0.00369 -0.00643 -0.00984 -0.0139 -0.0185 -0.0236 -0.0293 -0.0353 -0.0418 -0.0486 -0.0557 -0.063 -0.0705 -0.0781 -0.0859 -0.0937 -0.101 -0.109 -0.117 -0.124 -0.132 -0.139 -0.146 -0.152 -0.158 -0.164 -0.169 -0.173 -0.178 -0.181 -0.184 -0.186 -0.187 -0.187 -0.187 -0.186 -0.184 -0.181 -0.178 -0.173 -0.169 -0.164 -0.158 -0.152 -0.146 -0.139 -0.132 -0.124 -0.117 -0.109 -0.101 -0.0937 -0.0859 -0.0781 -0.0705 -0.063 -0.0557 -0.0486 -0.0418 -0.0353 -0.0293 -0.0236 -0.0185 -0.0139 -0.00984 -0.00643 -0.00369 -0.00167 -0.000426 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000128 0.000503 0.00111 0.00194 0.00296 0.00418 0.00557 0.00712 0.00882 0.0106 0.0126 0.0146 0.0168 0.019 0.0212 0.0235 0.0259 0.0282 0.0306 0.0329 0.0352 0.0375 0.0397 0.0418 0.0439 0.0458 0.0476 0.0493 0.0509 0.0523 0.0535 0.0545 0.0553 0.0559 0.0563 0.0564 0.0563 0.0559 0.0553 0.0545 0.0535 0.0523 0.0509 0.0493 0.0476 0.0458 0.0439 0.0418 0.0397 0.0375 0.0352 0.0329 0.0306 0.0282 0.0259 0.0235 0.0212 0.019 0.0168 0.0146 0.0126 0.0106 0.00882 0.00712 0.00557 0.00418 0.00296 0.00194 0.00111 0.000503 0.000128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00112 0.0044 0.00971 0.0169 0.0259 0.0365 0.0487 0.0623 0.0771 0.0931 0.11 0.128 0.147 0.166 0.186 0.206 0.226 0.247 0.267 0.288 0.308 0.328 0.347 0.365 0.383 0.4 0.416 0.431 0.445 0.457 0.467 0.476 0.484 0.489 0.492 0.493 0.492 0.489 0.484 0.476 0.467 0.457 0.445 0.431 0.416 0.4 0.383 0.365 0.347 0.328 0.308 0.288 0.267 0.247 0.226 0.206 0.186 0.166 0.147 0.128 0.11 0.0931 0.0771 0.0623 0.0487 0.0365 0.0259 0.0169 0.00971 0.0044 0.00112 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000128 0.000503 0.00111 0.00194 0.00296 0.00418 0.00557 0.00712 0.00882 0.0106 0.0126 0.0146 0.0168 0.019 0.0212 0.0235 0.0259 0.0282 0.0306 0.0329 0.0352 0.0375 0.0397 0.0418 0.0439 0.0458 0.0476 0.0493 0.0509 0.0523 0.0535 0.0545 0.0553 0.0559 0.0563 0.0564 0.0563 0.0559 0.0553 0.0545 0.0535 0.0523 0.0509 0.0493 0.0476 0.0458 0.0439 0.0418 0.0397 0.0375 0.0352 0.0329 0.0306 0.0282 0.0259 0.0235 0.0212 0.019 0.0168 0.0146 0.0126 0.0106 0.00882 0.00712 0.00557 0.00418 0.00296 0.00194 0.00111 0.000503 0.000128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/mne-python/source/mne/io/besa/tests/data/simulation.elp b/mne-python/source/mne/io/besa/tests/data/simulation.elp new file mode 100644 index 0000000000000000000000000000000000000000..3a4190f8fd8b3ea110a6619b21ae1b072f74a79b --- /dev/null +++ b/mne-python/source/mne/io/besa/tests/data/simulation.elp @@ -0,0 +1,33 @@ +EEG Fp1 -92 -72 1 +EEG Fp2 92 72 1 +EEG F9 -115 -35 1 +EEG F7 -92 -36 1 +EEG F3 -60 -51 1 +EEG Fz 46 90 1 +EEG F4 60 51 1 +EEG F8 92 36 1 +EEG F10 115 35 1 +EEG FC5 -71 -21 1 +EEG FC1 -32 -45 1 +EEG FC2 32 45 1 +EEG FC6 71 21 1 +EEG T9 -115 0 1 +EEG T7 -92 0 1 +EEG C3 -46 0 1 +EEG Cz 0 0 1 +EEG C4 46 0 1 +EEG T8 92 0 1 +EEG T10 115 0 1 +EEG CP5 -71 21 1 +EEG CP1 -32 45 1 +EEG CP2 32 -45 1 +EEG CP6 71 -21 1 +EEG P9 -115 36 1 +EEG P7 -92 36 1 +EEG P3 -60 51 1 +EEG Pz 46 -90 1 +EEG P4 60 -51 1 +EEG P8 92 -36 1 +EEG P10 115 -36 1 +EEG O1 -92 72 1 +EEG O2 92 -72 1 diff --git a/mne-python/source/mne/io/besa/tests/data/simulation.mul b/mne-python/source/mne/io/besa/tests/data/simulation.mul new file mode 100644 index 0000000000000000000000000000000000000000..f02b85f6fea5a19a98c2da05bc292ebf6c108e74 --- /dev/null +++ b/mne-python/source/mne/io/besa/tests/data/simulation.mul @@ -0,0 +1,202 @@ +TimePoints= 200 Channels= 33 BeginSweep[ms]= -100.00 SamplingInterval[ms]= 5.000 Bins/uV= 1.000 SegmentName= simulation +Fp1 Fp2 F9 F7 F3 Fz F4 F8 F10 FC5 FC1 FC2 FC6 T9 T7 C3 Cz C4 T8 T10 CP5 CP1 CP2 CP6 P9 P7 P3 Pz P4 P8 P10 O1 O2 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +-0.00113 -0.00113 -0.00157 -0.00113 0.00013 0.00112 0.00013 -0.00113 -0.00157 -0.00043 0.00259 0.00259 -0.00043 -0.00157 -0.00113 0.00112 0.00707 0.00112 -0.00113 -0.00157 -0.00043 0.00259 0.00259 -0.00043 -0.00157 -0.00113 0.00013 0.00112 0.00013 -0.00113 -0.00157 -0.00113 -0.00113 +-0.00443 -0.00443 -0.00618 -0.00443 0.00050 0.00440 0.00050 -0.00443 -0.00618 -0.00167 0.01020 0.01020 -0.00167 -0.00618 -0.00443 0.00440 0.02770 0.00440 -0.00443 -0.00618 -0.00167 0.01020 0.01020 -0.00167 -0.00618 -0.00443 0.00050 0.00440 0.00050 -0.00443 -0.00618 -0.00443 -0.00443 +-0.00979 -0.00979 -0.01360 -0.00979 0.00111 0.00971 0.00111 -0.00979 -0.01360 -0.00369 0.02250 0.02250 -0.00369 -0.01360 -0.00979 0.00971 0.06120 0.00971 -0.00979 -0.01360 -0.00369 0.02250 0.02250 -0.00369 -0.01360 -0.00979 0.00111 0.00971 0.00111 -0.00979 -0.01360 -0.00979 -0.00979 +-0.01710 -0.01710 -0.02380 -0.01710 0.00194 0.01690 0.00194 -0.01710 -0.02380 -0.00643 0.03920 0.03920 -0.00643 -0.02380 -0.01710 0.01690 0.10700 0.01690 -0.01710 -0.02380 -0.00643 0.03920 0.03920 -0.00643 -0.02380 -0.01710 0.00194 0.01690 0.00194 -0.01710 -0.02380 -0.01710 -0.01710 +-0.02610 -0.02610 -0.03640 -0.02610 0.00296 0.02590 0.00296 -0.02610 -0.03640 -0.00984 0.06000 0.06000 -0.00984 -0.03640 -0.02610 0.02590 0.16300 0.02590 -0.02610 -0.03640 -0.00984 0.06000 0.06000 -0.00984 -0.03640 -0.02610 0.00296 0.02590 0.00296 -0.02610 -0.03640 -0.02610 -0.02610 +-0.03680 -0.03680 -0.05130 -0.03680 0.00418 0.03650 0.00418 -0.03680 -0.05130 -0.01390 0.08460 0.08460 -0.01390 -0.05130 -0.03680 0.03650 0.23000 0.03650 -0.03680 -0.05130 -0.01390 0.08460 0.08460 -0.01390 -0.05130 -0.03680 0.00418 0.03650 0.00418 -0.03680 -0.05130 -0.03680 -0.03680 +-0.04910 -0.04910 -0.06840 -0.04910 0.00557 0.04870 0.00557 -0.04910 -0.06840 -0.01850 0.11300 0.11300 -0.01850 -0.06840 -0.04910 0.04870 0.30700 0.04870 -0.04910 -0.06840 -0.01850 0.11300 0.11300 -0.01850 -0.06840 -0.04910 0.00557 0.04870 0.00557 -0.04910 -0.06840 -0.04910 -0.04910 +-0.06280 -0.06280 -0.08740 -0.06280 0.00712 0.06230 0.00712 -0.06280 -0.08740 -0.02360 0.14400 0.14400 -0.02360 -0.08740 -0.06280 0.06230 0.39300 0.06230 -0.06280 -0.08740 -0.02360 0.14400 0.14400 -0.02360 -0.08740 -0.06280 0.00712 0.06230 0.00712 -0.06280 -0.08740 -0.06280 -0.06280 +-0.07770 -0.07770 -0.10800 -0.07770 0.00882 0.07710 0.00882 -0.07770 -0.10800 -0.02930 0.17800 0.17800 -0.02930 -0.10800 -0.07770 0.07710 0.48600 0.07710 -0.07770 -0.10800 -0.02930 0.17800 0.17800 -0.02930 -0.10800 -0.07770 0.00882 0.07710 0.00882 -0.07770 -0.10800 -0.07770 -0.07770 +-0.09380 -0.09380 -0.13100 -0.09380 0.01060 0.09310 0.01060 -0.09380 -0.13100 -0.03530 0.21500 0.21500 -0.03530 -0.13100 -0.09380 0.09310 0.58700 0.09310 -0.09380 -0.13100 -0.03530 0.21500 0.21500 -0.03530 -0.13100 -0.09380 0.01060 0.09310 0.01060 -0.09380 -0.13100 -0.09380 -0.09380 +-0.11100 -0.11100 -0.15400 -0.11100 0.01260 0.11000 0.01260 -0.11100 -0.15400 -0.04180 0.25500 0.25500 -0.04180 -0.15400 -0.11100 0.11000 0.69400 0.11000 -0.11100 -0.15400 -0.04180 0.25500 0.25500 -0.04180 -0.15400 -0.11100 0.01260 0.11000 0.01260 -0.11100 -0.15400 -0.11100 -0.11100 +-0.12900 -0.12900 -0.18000 -0.12900 0.01460 0.12800 0.01460 -0.12900 -0.18000 -0.04860 0.29600 0.29600 -0.04860 -0.18000 -0.12900 0.12800 0.80700 0.12800 -0.12900 -0.18000 -0.04860 0.29600 0.29600 -0.04860 -0.18000 -0.12900 0.01460 0.12800 0.01460 -0.12900 -0.18000 -0.12900 -0.12900 +-0.14800 -0.14800 -0.20600 -0.14800 0.01680 0.14700 0.01680 -0.14800 -0.20600 -0.05570 0.33900 0.33900 -0.05570 -0.20600 -0.14800 0.14700 0.92400 0.14700 -0.14800 -0.20600 -0.05570 0.33900 0.33900 -0.05570 -0.20600 -0.14800 0.01680 0.14700 0.01680 -0.14800 -0.20600 -0.14800 -0.14800 +-0.16700 -0.16700 -0.23300 -0.16700 0.01900 0.16600 0.01900 -0.16700 -0.23300 -0.06300 0.38400 0.38400 -0.06300 -0.23300 -0.16700 0.16600 1.05000 0.16600 -0.16700 -0.23300 -0.06300 0.38400 0.38400 -0.06300 -0.23300 -0.16700 0.01900 0.16600 0.01900 -0.16700 -0.23300 -0.16700 -0.16700 +-0.18700 -0.18700 -0.26100 -0.18700 0.02120 0.18600 0.02120 -0.18700 -0.26100 -0.07050 0.43000 0.43000 -0.07050 -0.26100 -0.18700 0.18600 1.17000 0.18600 -0.18700 -0.26100 -0.07050 0.43000 0.43000 -0.07050 -0.26100 -0.18700 0.02120 0.18600 0.02120 -0.18700 -0.26100 -0.18700 -0.18700 +-0.20700 -0.20700 -0.28900 -0.20700 0.02350 0.20600 0.02350 -0.20700 -0.28900 -0.07810 0.47600 0.47600 -0.07810 -0.28900 -0.20700 0.20600 1.30000 0.20600 -0.20700 -0.28900 -0.07810 0.47600 0.47600 -0.07810 -0.28900 -0.20700 0.02350 0.20600 0.02350 -0.20700 -0.28900 -0.20700 -0.20700 +-0.22800 -0.22800 -0.31700 -0.22800 0.02590 0.22600 0.02590 -0.22800 -0.31700 -0.08590 0.52300 0.52300 -0.08590 -0.31700 -0.22800 0.22600 1.43000 0.22600 -0.22800 -0.31700 -0.08590 0.52300 0.52300 -0.08590 -0.31700 -0.22800 0.02590 0.22600 0.02590 -0.22800 -0.31700 -0.22800 -0.22800 +-0.24900 -0.24900 -0.34600 -0.24900 0.02820 0.24700 0.02820 -0.24900 -0.34600 -0.09370 0.57100 0.57100 -0.09370 -0.34600 -0.24900 0.24700 1.56000 0.24700 -0.24900 -0.34600 -0.09370 0.57100 0.57100 -0.09370 -0.34600 -0.24900 0.02820 0.24700 0.02820 -0.24900 -0.34600 -0.24900 -0.24900 +-0.26900 -0.26900 -0.37500 -0.26900 0.03060 0.26700 0.03060 -0.26900 -0.37500 -0.10100 0.61900 0.61900 -0.10100 -0.37500 -0.26900 0.26700 1.68000 0.26700 -0.26900 -0.37500 -0.10100 0.61900 0.61900 -0.10100 -0.37500 -0.26900 0.03060 0.26700 0.03060 -0.26900 -0.37500 -0.26900 -0.26900 +-0.29000 -0.29000 -0.40400 -0.29000 0.03290 0.28800 0.03290 -0.29000 -0.40400 -0.10900 0.66600 0.66600 -0.10900 -0.40400 -0.29000 0.28800 1.81000 0.28800 -0.29000 -0.40400 -0.10900 0.66600 0.66600 -0.10900 -0.40400 -0.29000 0.03290 0.28800 0.03290 -0.29000 -0.40400 -0.29000 -0.29000 +-0.31000 -0.31000 -0.43200 -0.31000 0.03520 0.30800 0.03520 -0.31000 -0.43200 -0.11700 0.71200 0.71200 -0.11700 -0.43200 -0.31000 0.30800 1.94000 0.30800 -0.31000 -0.43200 -0.11700 0.71200 0.71200 -0.11700 -0.43200 -0.31000 0.03520 0.30800 0.03520 -0.31000 -0.43200 -0.31000 -0.31000 +-0.33000 -0.33000 -0.46000 -0.33000 0.03750 0.32800 0.03750 -0.33000 -0.46000 -0.12400 0.75800 0.75800 -0.12400 -0.46000 -0.33000 0.32800 2.07000 0.32800 -0.33000 -0.46000 -0.12400 0.75800 0.75800 -0.12400 -0.46000 -0.33000 0.03750 0.32800 0.03750 -0.33000 -0.46000 -0.33000 -0.33000 +-0.35000 -0.35000 -0.48700 -0.35000 0.03970 0.34700 0.03970 -0.35000 -0.48700 -0.13200 0.80300 0.80300 -0.13200 -0.48700 -0.35000 0.34700 2.19000 0.34700 -0.35000 -0.48700 -0.13200 0.80300 0.80300 -0.13200 -0.48700 -0.35000 0.03970 0.34700 0.03970 -0.35000 -0.48700 -0.35000 -0.35000 +-0.36800 -0.36800 -0.51300 -0.36800 0.04180 0.36500 0.04180 -0.36800 -0.51300 -0.13900 0.84600 0.84600 -0.13900 -0.51300 -0.36800 0.36500 2.30000 0.36500 -0.36800 -0.51300 -0.13900 0.84600 0.84600 -0.13900 -0.51300 -0.36800 0.04180 0.36500 0.04180 -0.36800 -0.51300 -0.36800 -0.36800 +-0.38600 -0.38600 -0.53800 -0.38600 0.04390 0.38300 0.04390 -0.38600 -0.53800 -0.14600 0.88700 0.88700 -0.14600 -0.53800 -0.38600 0.38300 2.42000 0.38300 -0.38600 -0.53800 -0.14600 0.88700 0.88700 -0.14600 -0.53800 -0.38600 0.04390 0.38300 0.04390 -0.38600 -0.53800 -0.38600 -0.38600 +-0.40400 -0.40400 -0.56200 -0.40400 0.04580 0.40000 0.04580 -0.40400 -0.56200 -0.15200 0.92700 0.92700 -0.15200 -0.56200 -0.40400 0.40000 2.52000 0.40000 -0.40400 -0.56200 -0.15200 0.92700 0.92700 -0.15200 -0.56200 -0.40400 0.04580 0.40000 0.04580 -0.40400 -0.56200 -0.40400 -0.40400 +-0.42000 -0.42000 -0.58400 -0.42000 0.04760 0.41600 0.04760 -0.42000 -0.58400 -0.15800 0.96400 0.96400 -0.15800 -0.58400 -0.42000 0.41600 2.62000 0.41600 -0.42000 -0.58400 -0.15800 0.96400 0.96400 -0.15800 -0.58400 -0.42000 0.04760 0.41600 0.04760 -0.42000 -0.58400 -0.42000 -0.42000 +-0.43500 -0.43500 -0.60500 -0.43500 0.04930 0.43100 0.04930 -0.43500 -0.60500 -0.16400 0.99800 0.99800 -0.16400 -0.60500 -0.43500 0.43100 2.72000 0.43100 -0.43500 -0.60500 -0.16400 0.99800 0.99800 -0.16400 -0.60500 -0.43500 0.04930 0.43100 0.04930 -0.43500 -0.60500 -0.43500 -0.43500 +-0.44800 -0.44800 -0.62400 -0.44800 0.05090 0.44500 0.05090 -0.44800 -0.62400 -0.16900 1.03000 1.03000 -0.16900 -0.62400 -0.44800 0.44500 2.80000 0.44500 -0.44800 -0.62400 -0.16900 1.03000 1.03000 -0.16900 -0.62400 -0.44800 0.05090 0.44500 0.05090 -0.44800 -0.62400 -0.44800 -0.44800 +-0.46000 -0.46000 -0.64100 -0.46000 0.05230 0.45700 0.05230 -0.46000 -0.64100 -0.17300 1.06000 1.06000 -0.17300 -0.64100 -0.46000 0.45700 2.88000 0.45700 -0.46000 -0.64100 -0.17300 1.06000 1.06000 -0.17300 -0.64100 -0.46000 0.05230 0.45700 0.05230 -0.46000 -0.64100 -0.46000 -0.46000 +-0.47100 -0.47100 -0.65600 -0.47100 0.05350 0.46700 0.05350 -0.47100 -0.65600 -0.17800 1.08000 1.08000 -0.17800 -0.65600 -0.47100 0.46700 2.95000 0.46700 -0.47100 -0.65600 -0.17800 1.08000 1.08000 -0.17800 -0.65600 -0.47100 0.05350 0.46700 0.05350 -0.47100 -0.65600 -0.47100 -0.47100 +-0.48000 -0.48000 -0.66900 -0.48000 0.05450 0.47600 0.05450 -0.48000 -0.66900 -0.18100 1.10000 1.10000 -0.18100 -0.66900 -0.48000 0.47600 3.00000 0.47600 -0.48000 -0.66900 -0.18100 1.10000 1.10000 -0.18100 -0.66900 -0.48000 0.05450 0.47600 0.05450 -0.48000 -0.66900 -0.48000 -0.48000 +-0.48800 -0.48800 -0.67900 -0.48800 0.05530 0.48400 0.05530 -0.48800 -0.67900 -0.18400 1.12000 1.12000 -0.18400 -0.67900 -0.48800 0.48400 3.05000 0.48400 -0.48800 -0.67900 -0.18400 1.12000 1.12000 -0.18400 -0.67900 -0.48800 0.05530 0.48400 0.05530 -0.48800 -0.67900 -0.48800 -0.48800 +-0.49300 -0.49300 -0.68600 -0.49300 0.05590 0.48900 0.05590 -0.49300 -0.68600 -0.18600 1.13000 1.13000 -0.18600 -0.68600 -0.49300 0.48900 3.08000 0.48900 -0.49300 -0.68600 -0.18600 1.13000 1.13000 -0.18600 -0.68600 -0.49300 0.05590 0.48900 0.05590 -0.49300 -0.68600 -0.49300 -0.49300 +-0.49600 -0.49600 -0.69100 -0.49600 0.05630 0.49200 0.05630 -0.49600 -0.69100 -0.18700 1.14000 1.14000 -0.18700 -0.69100 -0.49600 0.49200 3.10000 0.49200 -0.49600 -0.69100 -0.18700 1.14000 1.14000 -0.18700 -0.69100 -0.49600 0.05630 0.49200 0.05630 -0.49600 -0.69100 -0.49600 -0.49600 +-0.49700 -0.49700 -0.69300 -0.49700 0.05640 0.49300 0.05640 -0.49700 -0.69300 -0.18700 1.14000 1.14000 -0.18700 -0.69300 -0.49700 0.49300 3.11000 0.49300 -0.49700 -0.69300 -0.18700 1.14000 1.14000 -0.18700 -0.69300 -0.49700 0.05640 0.49300 0.05640 -0.49700 -0.69300 -0.49700 -0.49700 +-0.49600 -0.49600 -0.69100 -0.49600 0.05630 0.49200 0.05630 -0.49600 -0.69100 -0.18700 1.14000 1.14000 -0.18700 -0.69100 -0.49600 0.49200 3.10000 0.49200 -0.49600 -0.69100 -0.18700 1.14000 1.14000 -0.18700 -0.69100 -0.49600 0.05630 0.49200 0.05630 -0.49600 -0.69100 -0.49600 -0.49600 +-0.49300 -0.49300 -0.68600 -0.49300 0.05590 0.48900 0.05590 -0.49300 -0.68600 -0.18600 1.13000 1.13000 -0.18600 -0.68600 -0.49300 0.48900 3.08000 0.48900 -0.49300 -0.68600 -0.18600 1.13000 1.13000 -0.18600 -0.68600 -0.49300 0.05590 0.48900 0.05590 -0.49300 -0.68600 -0.49300 -0.49300 +-0.48800 -0.48800 -0.67900 -0.48800 0.05530 0.48400 0.05530 -0.48800 -0.67900 -0.18400 1.12000 1.12000 -0.18400 -0.67900 -0.48800 0.48400 3.05000 0.48400 -0.48800 -0.67900 -0.18400 1.12000 1.12000 -0.18400 -0.67900 -0.48800 0.05530 0.48400 0.05530 -0.48800 -0.67900 -0.48800 -0.48800 +-0.48000 -0.48000 -0.66900 -0.48000 0.05450 0.47600 0.05450 -0.48000 -0.66900 -0.18100 1.10000 1.10000 -0.18100 -0.66900 -0.48000 0.47600 3.00000 0.47600 -0.48000 -0.66900 -0.18100 1.10000 1.10000 -0.18100 -0.66900 -0.48000 0.05450 0.47600 0.05450 -0.48000 -0.66900 -0.48000 -0.48000 +-0.47100 -0.47100 -0.65600 -0.47100 0.05350 0.46700 0.05350 -0.47100 -0.65600 -0.17800 1.08000 1.08000 -0.17800 -0.65600 -0.47100 0.46700 2.95000 0.46700 -0.47100 -0.65600 -0.17800 1.08000 1.08000 -0.17800 -0.65600 -0.47100 0.05350 0.46700 0.05350 -0.47100 -0.65600 -0.47100 -0.47100 +-0.46000 -0.46000 -0.64100 -0.46000 0.05230 0.45700 0.05230 -0.46000 -0.64100 -0.17300 1.06000 1.06000 -0.17300 -0.64100 -0.46000 0.45700 2.88000 0.45700 -0.46000 -0.64100 -0.17300 1.06000 1.06000 -0.17300 -0.64100 -0.46000 0.05230 0.45700 0.05230 -0.46000 -0.64100 -0.46000 -0.46000 +-0.44800 -0.44800 -0.62400 -0.44800 0.05090 0.44500 0.05090 -0.44800 -0.62400 -0.16900 1.03000 1.03000 -0.16900 -0.62400 -0.44800 0.44500 2.80000 0.44500 -0.44800 -0.62400 -0.16900 1.03000 1.03000 -0.16900 -0.62400 -0.44800 0.05090 0.44500 0.05090 -0.44800 -0.62400 -0.44800 -0.44800 +-0.43500 -0.43500 -0.60500 -0.43500 0.04930 0.43100 0.04930 -0.43500 -0.60500 -0.16400 0.99800 0.99800 -0.16400 -0.60500 -0.43500 0.43100 2.72000 0.43100 -0.43500 -0.60500 -0.16400 0.99800 0.99800 -0.16400 -0.60500 -0.43500 0.04930 0.43100 0.04930 -0.43500 -0.60500 -0.43500 -0.43500 +-0.42000 -0.42000 -0.58400 -0.42000 0.04760 0.41600 0.04760 -0.42000 -0.58400 -0.15800 0.96400 0.96400 -0.15800 -0.58400 -0.42000 0.41600 2.62000 0.41600 -0.42000 -0.58400 -0.15800 0.96400 0.96400 -0.15800 -0.58400 -0.42000 0.04760 0.41600 0.04760 -0.42000 -0.58400 -0.42000 -0.42000 +-0.40400 -0.40400 -0.56200 -0.40400 0.04580 0.40000 0.04580 -0.40400 -0.56200 -0.15200 0.92700 0.92700 -0.15200 -0.56200 -0.40400 0.40000 2.52000 0.40000 -0.40400 -0.56200 -0.15200 0.92700 0.92700 -0.15200 -0.56200 -0.40400 0.04580 0.40000 0.04580 -0.40400 -0.56200 -0.40400 -0.40400 +-0.38600 -0.38600 -0.53800 -0.38600 0.04390 0.38300 0.04390 -0.38600 -0.53800 -0.14600 0.88700 0.88700 -0.14600 -0.53800 -0.38600 0.38300 2.42000 0.38300 -0.38600 -0.53800 -0.14600 0.88700 0.88700 -0.14600 -0.53800 -0.38600 0.04390 0.38300 0.04390 -0.38600 -0.53800 -0.38600 -0.38600 +-0.36800 -0.36800 -0.51300 -0.36800 0.04180 0.36500 0.04180 -0.36800 -0.51300 -0.13900 0.84600 0.84600 -0.13900 -0.51300 -0.36800 0.36500 2.30000 0.36500 -0.36800 -0.51300 -0.13900 0.84600 0.84600 -0.13900 -0.51300 -0.36800 0.04180 0.36500 0.04180 -0.36800 -0.51300 -0.36800 -0.36800 +-0.35000 -0.35000 -0.48700 -0.35000 0.03970 0.34700 0.03970 -0.35000 -0.48700 -0.13200 0.80300 0.80300 -0.13200 -0.48700 -0.35000 0.34700 2.19000 0.34700 -0.35000 -0.48700 -0.13200 0.80300 0.80300 -0.13200 -0.48700 -0.35000 0.03970 0.34700 0.03970 -0.35000 -0.48700 -0.35000 -0.35000 +-0.33000 -0.33000 -0.46000 -0.33000 0.03750 0.32800 0.03750 -0.33000 -0.46000 -0.12400 0.75800 0.75800 -0.12400 -0.46000 -0.33000 0.32800 2.07000 0.32800 -0.33000 -0.46000 -0.12400 0.75800 0.75800 -0.12400 -0.46000 -0.33000 0.03750 0.32800 0.03750 -0.33000 -0.46000 -0.33000 -0.33000 +-0.31000 -0.31000 -0.43200 -0.31000 0.03520 0.30800 0.03520 -0.31000 -0.43200 -0.11700 0.71200 0.71200 -0.11700 -0.43200 -0.31000 0.30800 1.94000 0.30800 -0.31000 -0.43200 -0.11700 0.71200 0.71200 -0.11700 -0.43200 -0.31000 0.03520 0.30800 0.03520 -0.31000 -0.43200 -0.31000 -0.31000 +-0.29000 -0.29000 -0.40400 -0.29000 0.03290 0.28800 0.03290 -0.29000 -0.40400 -0.10900 0.66600 0.66600 -0.10900 -0.40400 -0.29000 0.28800 1.81000 0.28800 -0.29000 -0.40400 -0.10900 0.66600 0.66600 -0.10900 -0.40400 -0.29000 0.03290 0.28800 0.03290 -0.29000 -0.40400 -0.29000 -0.29000 +-0.26900 -0.26900 -0.37500 -0.26900 0.03060 0.26700 0.03060 -0.26900 -0.37500 -0.10100 0.61900 0.61900 -0.10100 -0.37500 -0.26900 0.26700 1.68000 0.26700 -0.26900 -0.37500 -0.10100 0.61900 0.61900 -0.10100 -0.37500 -0.26900 0.03060 0.26700 0.03060 -0.26900 -0.37500 -0.26900 -0.26900 +-0.24900 -0.24900 -0.34600 -0.24900 0.02820 0.24700 0.02820 -0.24900 -0.34600 -0.09370 0.57100 0.57100 -0.09370 -0.34600 -0.24900 0.24700 1.56000 0.24700 -0.24900 -0.34600 -0.09370 0.57100 0.57100 -0.09370 -0.34600 -0.24900 0.02820 0.24700 0.02820 -0.24900 -0.34600 -0.24900 -0.24900 +-0.22800 -0.22800 -0.31700 -0.22800 0.02590 0.22600 0.02590 -0.22800 -0.31700 -0.08590 0.52300 0.52300 -0.08590 -0.31700 -0.22800 0.22600 1.43000 0.22600 -0.22800 -0.31700 -0.08590 0.52300 0.52300 -0.08590 -0.31700 -0.22800 0.02590 0.22600 0.02590 -0.22800 -0.31700 -0.22800 -0.22800 +-0.20700 -0.20700 -0.28900 -0.20700 0.02350 0.20600 0.02350 -0.20700 -0.28900 -0.07810 0.47600 0.47600 -0.07810 -0.28900 -0.20700 0.20600 1.30000 0.20600 -0.20700 -0.28900 -0.07810 0.47600 0.47600 -0.07810 -0.28900 -0.20700 0.02350 0.20600 0.02350 -0.20700 -0.28900 -0.20700 -0.20700 +-0.18700 -0.18700 -0.26100 -0.18700 0.02120 0.18600 0.02120 -0.18700 -0.26100 -0.07050 0.43000 0.43000 -0.07050 -0.26100 -0.18700 0.18600 1.17000 0.18600 -0.18700 -0.26100 -0.07050 0.43000 0.43000 -0.07050 -0.26100 -0.18700 0.02120 0.18600 0.02120 -0.18700 -0.26100 -0.18700 -0.18700 +-0.16700 -0.16700 -0.23300 -0.16700 0.01900 0.16600 0.01900 -0.16700 -0.23300 -0.06300 0.38400 0.38400 -0.06300 -0.23300 -0.16700 0.16600 1.05000 0.16600 -0.16700 -0.23300 -0.06300 0.38400 0.38400 -0.06300 -0.23300 -0.16700 0.01900 0.16600 0.01900 -0.16700 -0.23300 -0.16700 -0.16700 +-0.14800 -0.14800 -0.20600 -0.14800 0.01680 0.14700 0.01680 -0.14800 -0.20600 -0.05570 0.33900 0.33900 -0.05570 -0.20600 -0.14800 0.14700 0.92400 0.14700 -0.14800 -0.20600 -0.05570 0.33900 0.33900 -0.05570 -0.20600 -0.14800 0.01680 0.14700 0.01680 -0.14800 -0.20600 -0.14800 -0.14800 +-0.12900 -0.12900 -0.18000 -0.12900 0.01460 0.12800 0.01460 -0.12900 -0.18000 -0.04860 0.29600 0.29600 -0.04860 -0.18000 -0.12900 0.12800 0.80700 0.12800 -0.12900 -0.18000 -0.04860 0.29600 0.29600 -0.04860 -0.18000 -0.12900 0.01460 0.12800 0.01460 -0.12900 -0.18000 -0.12900 -0.12900 +-0.11100 -0.11100 -0.15400 -0.11100 0.01260 0.11000 0.01260 -0.11100 -0.15400 -0.04180 0.25500 0.25500 -0.04180 -0.15400 -0.11100 0.11000 0.69400 0.11000 -0.11100 -0.15400 -0.04180 0.25500 0.25500 -0.04180 -0.15400 -0.11100 0.01260 0.11000 0.01260 -0.11100 -0.15400 -0.11100 -0.11100 +-0.09380 -0.09380 -0.13100 -0.09380 0.01060 0.09310 0.01060 -0.09380 -0.13100 -0.03530 0.21500 0.21500 -0.03530 -0.13100 -0.09380 0.09310 0.58700 0.09310 -0.09380 -0.13100 -0.03530 0.21500 0.21500 -0.03530 -0.13100 -0.09380 0.01060 0.09310 0.01060 -0.09380 -0.13100 -0.09380 -0.09380 +-0.07770 -0.07770 -0.10800 -0.07770 0.00882 0.07710 0.00882 -0.07770 -0.10800 -0.02930 0.17800 0.17800 -0.02930 -0.10800 -0.07770 0.07710 0.48600 0.07710 -0.07770 -0.10800 -0.02930 0.17800 0.17800 -0.02930 -0.10800 -0.07770 0.00882 0.07710 0.00882 -0.07770 -0.10800 -0.07770 -0.07770 +-0.06280 -0.06280 -0.08740 -0.06280 0.00712 0.06230 0.00712 -0.06280 -0.08740 -0.02360 0.14400 0.14400 -0.02360 -0.08740 -0.06280 0.06230 0.39300 0.06230 -0.06280 -0.08740 -0.02360 0.14400 0.14400 -0.02360 -0.08740 -0.06280 0.00712 0.06230 0.00712 -0.06280 -0.08740 -0.06280 -0.06280 +-0.04910 -0.04910 -0.06840 -0.04910 0.00557 0.04870 0.00557 -0.04910 -0.06840 -0.01850 0.11300 0.11300 -0.01850 -0.06840 -0.04910 0.04870 0.30700 0.04870 -0.04910 -0.06840 -0.01850 0.11300 0.11300 -0.01850 -0.06840 -0.04910 0.00557 0.04870 0.00557 -0.04910 -0.06840 -0.04910 -0.04910 +-0.03680 -0.03680 -0.05130 -0.03680 0.00418 0.03650 0.00418 -0.03680 -0.05130 -0.01390 0.08460 0.08460 -0.01390 -0.05130 -0.03680 0.03650 0.23000 0.03650 -0.03680 -0.05130 -0.01390 0.08460 0.08460 -0.01390 -0.05130 -0.03680 0.00418 0.03650 0.00418 -0.03680 -0.05130 -0.03680 -0.03680 +-0.02610 -0.02610 -0.03640 -0.02610 0.00296 0.02590 0.00296 -0.02610 -0.03640 -0.00984 0.06000 0.06000 -0.00984 -0.03640 -0.02610 0.02590 0.16300 0.02590 -0.02610 -0.03640 -0.00984 0.06000 0.06000 -0.00984 -0.03640 -0.02610 0.00296 0.02590 0.00296 -0.02610 -0.03640 -0.02610 -0.02610 +-0.01710 -0.01710 -0.02380 -0.01710 0.00194 0.01690 0.00194 -0.01710 -0.02380 -0.00643 0.03920 0.03920 -0.00643 -0.02380 -0.01710 0.01690 0.10700 0.01690 -0.01710 -0.02380 -0.00643 0.03920 0.03920 -0.00643 -0.02380 -0.01710 0.00194 0.01690 0.00194 -0.01710 -0.02380 -0.01710 -0.01710 +-0.00979 -0.00979 -0.01360 -0.00979 0.00111 0.00971 0.00111 -0.00979 -0.01360 -0.00369 0.02250 0.02250 -0.00369 -0.01360 -0.00979 0.00971 0.06120 0.00971 -0.00979 -0.01360 -0.00369 0.02250 0.02250 -0.00369 -0.01360 -0.00979 0.00111 0.00971 0.00111 -0.00979 -0.01360 -0.00979 -0.00979 +-0.00443 -0.00443 -0.00618 -0.00443 0.00050 0.00440 0.00050 -0.00443 -0.00618 -0.00167 0.01020 0.01020 -0.00167 -0.00618 -0.00443 0.00440 0.02770 0.00440 -0.00443 -0.00618 -0.00167 0.01020 0.01020 -0.00167 -0.00618 -0.00443 0.00050 0.00440 0.00050 -0.00443 -0.00618 -0.00443 -0.00443 +-0.00113 -0.00113 -0.00157 -0.00113 0.00013 0.00112 0.00013 -0.00113 -0.00157 -0.00043 0.00259 0.00259 -0.00043 -0.00157 -0.00113 0.00112 0.00707 0.00112 -0.00113 -0.00157 -0.00043 0.00259 0.00259 -0.00043 -0.00157 -0.00113 0.00013 0.00112 0.00013 -0.00113 -0.00157 -0.00113 -0.00113 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 diff --git a/mne-python/source/mne/io/besa/tests/data/simulation_oldstyle.avr b/mne-python/source/mne/io/besa/tests/data/simulation_oldstyle.avr new file mode 100644 index 0000000000000000000000000000000000000000..d2f502ddab341baf2ed7b9ab63cf41e2db15ffee --- /dev/null +++ b/mne-python/source/mne/io/besa/tests/data/simulation_oldstyle.avr @@ -0,0 +1,34 @@ +Npts= 200 TSB= -100 DI= 5 SB= 1.00 SC= 500.0 SegmentName= simulation +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000128 0.000503 0.00111 0.00194 0.00296 0.00418 0.00557 0.00712 0.00882 0.0106 0.0126 0.0146 0.0168 0.019 0.0212 0.0235 0.0259 0.0282 0.0306 0.0329 0.0352 0.0375 0.0397 0.0418 0.0439 0.0458 0.0476 0.0493 0.0509 0.0523 0.0535 0.0545 0.0553 0.0559 0.0563 0.0564 0.0563 0.0559 0.0553 0.0545 0.0535 0.0523 0.0509 0.0493 0.0476 0.0458 0.0439 0.0418 0.0397 0.0375 0.0352 0.0329 0.0306 0.0282 0.0259 0.0235 0.0212 0.019 0.0168 0.0146 0.0126 0.0106 0.00882 0.00712 0.00557 0.00418 0.00296 0.00194 0.00111 0.000503 0.000128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00112 0.0044 0.00971 0.0169 0.0259 0.0365 0.0487 0.0623 0.0771 0.0931 0.11 0.128 0.147 0.166 0.186 0.206 0.226 0.247 0.267 0.288 0.308 0.328 0.347 0.365 0.383 0.4 0.416 0.431 0.445 0.457 0.467 0.476 0.484 0.489 0.492 0.493 0.492 0.489 0.484 0.476 0.467 0.457 0.445 0.431 0.416 0.4 0.383 0.365 0.347 0.328 0.308 0.288 0.267 0.247 0.226 0.206 0.186 0.166 0.147 0.128 0.11 0.0931 0.0771 0.0623 0.0487 0.0365 0.0259 0.0169 0.00971 0.0044 0.00112 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000128 0.000503 0.00111 0.00194 0.00296 0.00418 0.00557 0.00712 0.00882 0.0106 0.0126 0.0146 0.0168 0.019 0.0212 0.0235 0.0259 0.0282 0.0306 0.0329 0.0352 0.0375 0.0397 0.0418 0.0439 0.0458 0.0476 0.0493 0.0509 0.0523 0.0535 0.0545 0.0553 0.0559 0.0563 0.0564 0.0563 0.0559 0.0553 0.0545 0.0535 0.0523 0.0509 0.0493 0.0476 0.0458 0.0439 0.0418 0.0397 0.0375 0.0352 0.0329 0.0306 0.0282 0.0259 0.0235 0.0212 0.019 0.0168 0.0146 0.0126 0.0106 0.00882 0.00712 0.00557 0.00418 0.00296 0.00194 0.00111 0.000503 0.000128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.000426 -0.00167 -0.00369 -0.00643 -0.00984 -0.0139 -0.0185 -0.0236 -0.0293 -0.0353 -0.0418 -0.0486 -0.0557 -0.063 -0.0705 -0.0781 -0.0859 -0.0937 -0.101 -0.109 -0.117 -0.124 -0.132 -0.139 -0.146 -0.152 -0.158 -0.164 -0.169 -0.173 -0.178 -0.181 -0.184 -0.186 -0.187 -0.187 -0.187 -0.186 -0.184 -0.181 -0.178 -0.173 -0.169 -0.164 -0.158 -0.152 -0.146 -0.139 -0.132 -0.124 -0.117 -0.109 -0.101 -0.0937 -0.0859 -0.0781 -0.0705 -0.063 -0.0557 -0.0486 -0.0418 -0.0353 -0.0293 -0.0236 -0.0185 -0.0139 -0.00984 -0.00643 -0.00369 -0.00167 -0.000426 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00259 0.0102 0.0225 0.0392 0.06 0.0846 0.113 0.144 0.178 0.215 0.255 0.296 0.339 0.384 0.43 0.476 0.523 0.571 0.619 0.666 0.712 0.758 0.803 0.846 0.887 0.927 0.964 0.998 1.03 1.06 1.08 1.1 1.12 1.13 1.14 1.14 1.14 1.13 1.12 1.1 1.08 1.06 1.03 0.998 0.964 0.927 0.887 0.846 0.803 0.758 0.712 0.666 0.619 0.571 0.523 0.476 0.43 0.384 0.339 0.296 0.255 0.215 0.178 0.144 0.113 0.0846 0.06 0.0392 0.0225 0.0102 0.00259 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00259 0.0102 0.0225 0.0392 0.06 0.0846 0.113 0.144 0.178 0.215 0.255 0.296 0.339 0.384 0.43 0.476 0.523 0.571 0.619 0.666 0.712 0.758 0.803 0.846 0.887 0.927 0.964 0.998 1.03 1.06 1.08 1.1 1.12 1.13 1.14 1.14 1.14 1.13 1.12 1.1 1.08 1.06 1.03 0.998 0.964 0.927 0.887 0.846 0.803 0.758 0.712 0.666 0.619 0.571 0.523 0.476 0.43 0.384 0.339 0.296 0.255 0.215 0.178 0.144 0.113 0.0846 0.06 0.0392 0.0225 0.0102 0.00259 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.000426 -0.00167 -0.00369 -0.00643 -0.00984 -0.0139 -0.0185 -0.0236 -0.0293 -0.0353 -0.0418 -0.0486 -0.0557 -0.063 -0.0705 -0.0781 -0.0859 -0.0937 -0.101 -0.109 -0.117 -0.124 -0.132 -0.139 -0.146 -0.152 -0.158 -0.164 -0.169 -0.173 -0.178 -0.181 -0.184 -0.186 -0.187 -0.187 -0.187 -0.186 -0.184 -0.181 -0.178 -0.173 -0.169 -0.164 -0.158 -0.152 -0.146 -0.139 -0.132 -0.124 -0.117 -0.109 -0.101 -0.0937 -0.0859 -0.0781 -0.0705 -0.063 -0.0557 -0.0486 -0.0418 -0.0353 -0.0293 -0.0236 -0.0185 -0.0139 -0.00984 -0.00643 -0.00369 -0.00167 -0.000426 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00112 0.0044 0.00971 0.0169 0.0259 0.0365 0.0487 0.0623 0.0771 0.0931 0.11 0.128 0.147 0.166 0.186 0.206 0.226 0.247 0.267 0.288 0.308 0.328 0.347 0.365 0.383 0.4 0.416 0.431 0.445 0.457 0.467 0.476 0.484 0.489 0.492 0.493 0.492 0.489 0.484 0.476 0.467 0.457 0.445 0.431 0.416 0.4 0.383 0.365 0.347 0.328 0.308 0.288 0.267 0.247 0.226 0.206 0.186 0.166 0.147 0.128 0.11 0.0931 0.0771 0.0623 0.0487 0.0365 0.0259 0.0169 0.00971 0.0044 0.00112 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00707 0.0277 0.0612 0.107 0.163 0.23 0.307 0.393 0.486 0.587 0.694 0.807 0.924 1.05 1.17 1.3 1.43 1.56 1.68 1.81 1.94 2.07 2.19 2.3 2.42 2.52 2.62 2.72 2.8 2.88 2.95 3 3.05 3.08 3.1 3.11 3.1 3.08 3.05 3 2.95 2.88 2.8 2.72 2.62 2.52 2.42 2.3 2.19 2.07 1.94 1.81 1.68 1.56 1.43 1.3 1.17 1.05 0.924 0.807 0.694 0.587 0.486 0.393 0.307 0.23 0.163 0.107 0.0612 0.0277 0.00707 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00112 0.0044 0.00971 0.0169 0.0259 0.0365 0.0487 0.0623 0.0771 0.0931 0.11 0.128 0.147 0.166 0.186 0.206 0.226 0.247 0.267 0.288 0.308 0.328 0.347 0.365 0.383 0.4 0.416 0.431 0.445 0.457 0.467 0.476 0.484 0.489 0.492 0.493 0.492 0.489 0.484 0.476 0.467 0.457 0.445 0.431 0.416 0.4 0.383 0.365 0.347 0.328 0.308 0.288 0.267 0.247 0.226 0.206 0.186 0.166 0.147 0.128 0.11 0.0931 0.0771 0.0623 0.0487 0.0365 0.0259 0.0169 0.00971 0.0044 0.00112 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.000426 -0.00167 -0.00369 -0.00643 -0.00984 -0.0139 -0.0185 -0.0236 -0.0293 -0.0353 -0.0418 -0.0486 -0.0557 -0.063 -0.0705 -0.0781 -0.0859 -0.0937 -0.101 -0.109 -0.117 -0.124 -0.132 -0.139 -0.146 -0.152 -0.158 -0.164 -0.169 -0.173 -0.178 -0.181 -0.184 -0.186 -0.187 -0.187 -0.187 -0.186 -0.184 -0.181 -0.178 -0.173 -0.169 -0.164 -0.158 -0.152 -0.146 -0.139 -0.132 -0.124 -0.117 -0.109 -0.101 -0.0937 -0.0859 -0.0781 -0.0705 -0.063 -0.0557 -0.0486 -0.0418 -0.0353 -0.0293 -0.0236 -0.0185 -0.0139 -0.00984 -0.00643 -0.00369 -0.00167 -0.000426 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00259 0.0102 0.0225 0.0392 0.06 0.0846 0.113 0.144 0.178 0.215 0.255 0.296 0.339 0.384 0.43 0.476 0.523 0.571 0.619 0.666 0.712 0.758 0.803 0.846 0.887 0.927 0.964 0.998 1.03 1.06 1.08 1.1 1.12 1.13 1.14 1.14 1.14 1.13 1.12 1.1 1.08 1.06 1.03 0.998 0.964 0.927 0.887 0.846 0.803 0.758 0.712 0.666 0.619 0.571 0.523 0.476 0.43 0.384 0.339 0.296 0.255 0.215 0.178 0.144 0.113 0.0846 0.06 0.0392 0.0225 0.0102 0.00259 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00259 0.0102 0.0225 0.0392 0.06 0.0846 0.113 0.144 0.178 0.215 0.255 0.296 0.339 0.384 0.43 0.476 0.523 0.571 0.619 0.666 0.712 0.758 0.803 0.846 0.887 0.927 0.964 0.998 1.03 1.06 1.08 1.1 1.12 1.13 1.14 1.14 1.14 1.13 1.12 1.1 1.08 1.06 1.03 0.998 0.964 0.927 0.887 0.846 0.803 0.758 0.712 0.666 0.619 0.571 0.523 0.476 0.43 0.384 0.339 0.296 0.255 0.215 0.178 0.144 0.113 0.0846 0.06 0.0392 0.0225 0.0102 0.00259 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.000426 -0.00167 -0.00369 -0.00643 -0.00984 -0.0139 -0.0185 -0.0236 -0.0293 -0.0353 -0.0418 -0.0486 -0.0557 -0.063 -0.0705 -0.0781 -0.0859 -0.0937 -0.101 -0.109 -0.117 -0.124 -0.132 -0.139 -0.146 -0.152 -0.158 -0.164 -0.169 -0.173 -0.178 -0.181 -0.184 -0.186 -0.187 -0.187 -0.187 -0.186 -0.184 -0.181 -0.178 -0.173 -0.169 -0.164 -0.158 -0.152 -0.146 -0.139 -0.132 -0.124 -0.117 -0.109 -0.101 -0.0937 -0.0859 -0.0781 -0.0705 -0.063 -0.0557 -0.0486 -0.0418 -0.0353 -0.0293 -0.0236 -0.0185 -0.0139 -0.00984 -0.00643 -0.00369 -0.00167 -0.000426 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000128 0.000503 0.00111 0.00194 0.00296 0.00418 0.00557 0.00712 0.00882 0.0106 0.0126 0.0146 0.0168 0.019 0.0212 0.0235 0.0259 0.0282 0.0306 0.0329 0.0352 0.0375 0.0397 0.0418 0.0439 0.0458 0.0476 0.0493 0.0509 0.0523 0.0535 0.0545 0.0553 0.0559 0.0563 0.0564 0.0563 0.0559 0.0553 0.0545 0.0535 0.0523 0.0509 0.0493 0.0476 0.0458 0.0439 0.0418 0.0397 0.0375 0.0352 0.0329 0.0306 0.0282 0.0259 0.0235 0.0212 0.019 0.0168 0.0146 0.0126 0.0106 0.00882 0.00712 0.00557 0.00418 0.00296 0.00194 0.00111 0.000503 0.000128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.00112 0.0044 0.00971 0.0169 0.0259 0.0365 0.0487 0.0623 0.0771 0.0931 0.11 0.128 0.147 0.166 0.186 0.206 0.226 0.247 0.267 0.288 0.308 0.328 0.347 0.365 0.383 0.4 0.416 0.431 0.445 0.457 0.467 0.476 0.484 0.489 0.492 0.493 0.492 0.489 0.484 0.476 0.467 0.457 0.445 0.431 0.416 0.4 0.383 0.365 0.347 0.328 0.308 0.288 0.267 0.247 0.226 0.206 0.186 0.166 0.147 0.128 0.11 0.0931 0.0771 0.0623 0.0487 0.0365 0.0259 0.0169 0.00971 0.0044 0.00112 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.000128 0.000503 0.00111 0.00194 0.00296 0.00418 0.00557 0.00712 0.00882 0.0106 0.0126 0.0146 0.0168 0.019 0.0212 0.0235 0.0259 0.0282 0.0306 0.0329 0.0352 0.0375 0.0397 0.0418 0.0439 0.0458 0.0476 0.0493 0.0509 0.0523 0.0535 0.0545 0.0553 0.0559 0.0563 0.0564 0.0563 0.0559 0.0553 0.0545 0.0535 0.0523 0.0509 0.0493 0.0476 0.0458 0.0439 0.0418 0.0397 0.0375 0.0352 0.0329 0.0306 0.0282 0.0259 0.0235 0.0212 0.019 0.0168 0.0146 0.0126 0.0106 0.00882 0.00712 0.00557 0.00418 0.00296 0.00194 0.00111 0.000503 0.000128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00157 -0.00618 -0.0136 -0.0238 -0.0364 -0.0513 -0.0684 -0.0874 -0.108 -0.131 -0.154 -0.18 -0.206 -0.233 -0.261 -0.289 -0.317 -0.346 -0.375 -0.404 -0.432 -0.46 -0.487 -0.513 -0.538 -0.562 -0.584 -0.605 -0.624 -0.641 -0.656 -0.669 -0.679 -0.686 -0.691 -0.693 -0.691 -0.686 -0.679 -0.669 -0.656 -0.641 -0.624 -0.605 -0.584 -0.562 -0.538 -0.513 -0.487 -0.46 -0.432 -0.404 -0.375 -0.346 -0.317 -0.289 -0.261 -0.233 -0.206 -0.18 -0.154 -0.131 -0.108 -0.0874 -0.0684 -0.0513 -0.0364 -0.0238 -0.0136 -0.00618 -0.00157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -0.00113 -0.00443 -0.00979 -0.0171 -0.0261 -0.0368 -0.0491 -0.0628 -0.0777 -0.0938 -0.111 -0.129 -0.148 -0.167 -0.187 -0.207 -0.228 -0.249 -0.269 -0.29 -0.31 -0.33 -0.35 -0.368 -0.386 -0.404 -0.42 -0.435 -0.448 -0.46 -0.471 -0.48 -0.488 -0.493 -0.496 -0.497 -0.496 -0.493 -0.488 -0.48 -0.471 -0.46 -0.448 -0.435 -0.42 -0.404 -0.386 -0.368 -0.35 -0.33 -0.31 -0.29 -0.269 -0.249 -0.228 -0.207 -0.187 -0.167 -0.148 -0.129 -0.111 -0.0938 -0.0777 -0.0628 -0.0491 -0.0368 -0.0261 -0.0171 -0.00979 -0.00443 -0.00113 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 diff --git a/mne-python/source/mne/io/besa/tests/data/simulation_oldstyle.elp b/mne-python/source/mne/io/besa/tests/data/simulation_oldstyle.elp new file mode 100644 index 0000000000000000000000000000000000000000..3a4190f8fd8b3ea110a6619b21ae1b072f74a79b --- /dev/null +++ b/mne-python/source/mne/io/besa/tests/data/simulation_oldstyle.elp @@ -0,0 +1,33 @@ +EEG Fp1 -92 -72 1 +EEG Fp2 92 72 1 +EEG F9 -115 -35 1 +EEG F7 -92 -36 1 +EEG F3 -60 -51 1 +EEG Fz 46 90 1 +EEG F4 60 51 1 +EEG F8 92 36 1 +EEG F10 115 35 1 +EEG FC5 -71 -21 1 +EEG FC1 -32 -45 1 +EEG FC2 32 45 1 +EEG FC6 71 21 1 +EEG T9 -115 0 1 +EEG T7 -92 0 1 +EEG C3 -46 0 1 +EEG Cz 0 0 1 +EEG C4 46 0 1 +EEG T8 92 0 1 +EEG T10 115 0 1 +EEG CP5 -71 21 1 +EEG CP1 -32 45 1 +EEG CP2 32 -45 1 +EEG CP6 71 -21 1 +EEG P9 -115 36 1 +EEG P7 -92 36 1 +EEG P3 -60 51 1 +EEG Pz 46 -90 1 +EEG P4 60 -51 1 +EEG P8 92 -36 1 +EEG P10 115 -36 1 +EEG O1 -92 72 1 +EEG O2 92 -72 1 diff --git a/mne-python/source/mne/io/besa/tests/test_besa.py b/mne-python/source/mne/io/besa/tests/test_besa.py new file mode 100644 index 0000000000000000000000000000000000000000..60deb1b482023c1798bc50938d269c747066a87a --- /dev/null +++ b/mne-python/source/mne/io/besa/tests/test_besa.py @@ -0,0 +1,79 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Test reading BESA fileformats.""" + +import inspect +from pathlib import Path + +import pytest + +from mne.channels import read_custom_montage +from mne.io import read_evoked_besa + +FILE = Path(inspect.getfile(inspect.currentframe())) +data_dir = FILE.parent / "data" +avr_file = data_dir / "simulation.avr" +avr_file_oldstyle = data_dir / "simulation_oldstyle.avr" +mul_file = data_dir / "simulation.mul" +montage = read_custom_montage(data_dir / "simulation.elp") + + +@pytest.mark.filterwarnings("ignore:Fiducial point nasion not found") +@pytest.mark.parametrize("fname", (avr_file, avr_file_oldstyle, mul_file)) +def test_read_evoked_besa(fname): + """Test reading MESA .avr and .mul files.""" + ev = read_evoked_besa(fname) + assert len(ev.ch_names) == len(ev.data) == 33 + assert ev.info["sfreq"] == 200 + assert ev.tmin == -0.1 + assert len(ev.times) == 200 + assert ev.ch_names == montage.ch_names + assert ev.comment == "simulation" + + +def test_read_evoked_besa_avr_incomplete(tmp_path): + """Test reading incomplete BESA .avr files.""" + # Check old style .avr file without an .elp sidecar + with open(f"{tmp_path}/missing.avr", "w") as f: + f.write("Npts= 1 TSB= 0 SB= 1.00 SC= 500.0 DI= 5\n0\n1\n2\n") + ev = read_evoked_besa(f"{tmp_path}/missing.avr") + assert ev.ch_names == ["CH01", "CH02", "CH03"] + + # Create BESA file with missing header fields and verify things don't break + with open(f"{tmp_path}/missing.avr", "w") as f: + f.write("DI= 5\n0\n") + ev = read_evoked_besa(f"{tmp_path}/missing.avr") + assert len(ev.ch_names) == len(ev.data) == 1 + assert ev.info["sfreq"] == 200 + assert ev.tmin == 0 + assert len(ev.times) == 1 + assert ev.ch_names == ["CH01"] + assert ev.comment == "" + + # The DI field (sample frequency) must exist + with open(f"{tmp_path}/missing.avr", "w") as f: + f.write("Npts= 1 TSB= 0 SB= 1.00 SC= 500.0\n0\n") + with pytest.raises(RuntimeError, match='No "DI" field present'): + ev = read_evoked_besa(f"{tmp_path}/missing.avr") + + +def test_read_evoked_besa_mul_incomplete(tmp_path): + """Test reading incomplete BESA .mul files.""" + # Create BESA file with missing header fields and verify things don't break + with open(f"{tmp_path}/missing.mul", "w") as f: + f.write("SamplingInterval[ms]= 5\nCH1\n0\n") + ev = read_evoked_besa(f"{tmp_path}/missing.mul") + assert len(ev.ch_names) == len(ev.data) == 1 + assert ev.info["sfreq"] == 200 + assert ev.tmin == 0 + assert len(ev.times) == 1 + assert ev.ch_names == ["CH1"] + assert ev.comment == "" + + # The SamplingInterval[ms] field (sample frequency) must exist + with open(f"{tmp_path}/missing.mul", "w") as f: + f.write("TimePoints= 1 Channels= 1\nCH1\n0\n") + with pytest.raises(RuntimeError, match=r'No "SamplingInterval\[ms\]"'): + ev = read_evoked_besa(f"{tmp_path}/missing.mul") diff --git a/mne-python/source/mne/io/boxy/__init__.py b/mne-python/source/mne/io/boxy/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ac47cccffbc3fa7aaa9143c8ed76e586ceb69ebb --- /dev/null +++ b/mne-python/source/mne/io/boxy/__init__.py @@ -0,0 +1,7 @@ +"""fNIRS module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .boxy import read_raw_boxy diff --git a/mne-python/source/mne/io/boxy/boxy.py b/mne-python/source/mne/io/boxy/boxy.py new file mode 100644 index 0000000000000000000000000000000000000000..9a131730a51c3f9c3d5572ac7f71fdbbfbd3a845 --- /dev/null +++ b/mne-python/source/mne/io/boxy/boxy.py @@ -0,0 +1,283 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import re as re + +import numpy as np + +from ..._fiff.meas_info import create_info +from ..._fiff.utils import _mult_cal_one +from ...annotations import Annotations +from ...utils import _check_fname, fill_doc, logger, verbose +from ..base import BaseRaw + + +@fill_doc +def read_raw_boxy(fname, preload=False, verbose=None) -> "RawBOXY": + """Reader for an optical imaging recording. + + This function has been tested using the ISS Imagent I and II systems + and versions 0.40/0.84 of the BOXY recording software. + + Parameters + ---------- + fname : path-like + Path to the BOXY data file. + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawBOXY + A Raw object containing BOXY data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawBOXY. + """ + return RawBOXY(fname, preload, verbose) + + +@fill_doc +class RawBOXY(BaseRaw): + """Raw object from a BOXY optical imaging file. + + Parameters + ---------- + fname : path-like + Path to the BOXY data file. + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + @verbose + def __init__(self, fname, preload=False, verbose=None): + logger.info(f"Loading {fname}") + + # Read header file and grab some info. + start_line = np.inf + col_names = mrk_col = filetype = mrk_data = end_line = None + raw_extras = dict() + raw_extras["offsets"] = list() # keep track of our offsets + sfreq = None + fname = str(_check_fname(fname, "read", True, "fname")) + with open(fname) as fid: + line_num = 0 + i_line = fid.readline() + while i_line: + # most of our lines will be data lines, so check that first + if line_num >= start_line: + assert col_names is not None + assert filetype is not None + if "#DATA ENDS" in i_line: + # Data ends just before this. + end_line = line_num + break + if mrk_col is not None: + if filetype == "non-parsed": + # Non-parsed files have different lines lengths. + crnt_line = i_line.rsplit(" ")[0] + temp_data = re.findall(r"[-+]?\d*\.?\d+", crnt_line) + if len(temp_data) == len(col_names): + mrk_data.append( + float( + re.findall(r"[-+]?\d*\.?\d+", crnt_line)[ + mrk_col + ] + ) + ) + else: + crnt_line = i_line.rsplit(" ")[0] + mrk_data.append( + float(re.findall(r"[-+]?\d*\.?\d+", crnt_line)[mrk_col]) + ) + raw_extras["offsets"].append(fid.tell()) + # now proceed with more standard header parsing + elif "BOXY.EXE:" in i_line: + boxy_ver = re.findall(r"\d*\.\d+", i_line.rsplit(" ")[-1])[0] + # Check that the BOXY version is supported + if boxy_ver not in ["0.40", "0.84"]: + raise RuntimeError( + f"MNE has not been tested with BOXY version ({boxy_ver})" + ) + elif "Detector Channels" in i_line: + raw_extras["detect_num"] = int(i_line.rsplit(" ")[0]) + elif "External MUX Channels" in i_line: + raw_extras["source_num"] = int(i_line.rsplit(" ")[0]) + elif "Update Rate (Hz)" in i_line or "Updata Rate (Hz)" in i_line: + # Version 0.40 of the BOXY recording software + # (and possibly other versions lower than 0.84) contains a + # typo in the raw data file where 'Update Rate' is spelled + # "Updata Rate. This will account for this typo. + sfreq = float(i_line.rsplit(" ")[0]) + elif "#DATA BEGINS" in i_line: + # Data should start a couple lines later. + start_line = line_num + 3 + elif line_num == start_line - 2: + # Grab names for each column of data. + raw_extras["col_names"] = col_names = re.findall( + r"\w+\-\w+|\w+\-\d+|\w+", i_line.rsplit(" ")[0] + ) + if "exmux" in col_names: + # Change filetype based on data organisation. + filetype = "non-parsed" + else: + filetype = "parsed" + if "digaux" in col_names: + mrk_col = col_names.index("digaux") + mrk_data = list() + # raw_extras['offsets'].append(fid.tell()) + elif line_num == start_line - 1: + raw_extras["offsets"].append(fid.tell()) + line_num += 1 + i_line = fid.readline() + assert sfreq is not None + raw_extras.update(filetype=filetype, start_line=start_line, end_line=end_line) + + # Label each channel in our data, for each data type (DC, AC, Ph). + # Data is organised by channels x timepoint, where the first + # 'source_num' rows correspond to the first detector, the next + # 'source_num' rows correspond to the second detector, and so on. + ch_names = list() + ch_types = list() + cals = list() + for det_num in range(raw_extras["detect_num"]): + for src_num in range(raw_extras["source_num"]): + for i_type, ch_type in [ + ("DC", "fnirs_cw_amplitude"), + ("AC", "fnirs_fd_ac_amplitude"), + ("Ph", "fnirs_fd_phase"), + ]: + ch_names.append(f"S{src_num + 1}_D{det_num + 1} {i_type}") + ch_types.append(ch_type) + cals.append(np.pi / 180.0 if i_type == "Ph" else 1.0) + + # Create info structure. + info = create_info(ch_names, sfreq, ch_types) + for ch, cal in zip(info["chs"], cals): + ch["cal"] = cal + + # Determine how long our data is. + delta = end_line - start_line + assert len(raw_extras["offsets"]) == delta + 1 + if filetype == "non-parsed": + delta //= raw_extras["source_num"] + super().__init__( + info, + preload, + filenames=[fname], + first_samps=[0], + last_samps=[delta - 1], + raw_extras=[raw_extras], + verbose=verbose, + ) + + # Now let's grab our markers, if they are present. + if mrk_data is not None: + mrk_data = np.array(mrk_data, float) + # We only want the first instance of each trigger. + prev_mrk = 0 + mrk_idx = list() + duration = list() + tmp_dur = 0 + for i_num, i_mrk in enumerate(mrk_data): + if i_mrk != 0 and i_mrk != prev_mrk: + mrk_idx.append(i_num) + if i_mrk != 0 and i_mrk == prev_mrk: + tmp_dur += 1 + if i_mrk == 0 and i_mrk != prev_mrk: + duration.append((tmp_dur + 1) / sfreq) + tmp_dur = 0 + prev_mrk = i_mrk + onset = np.array(mrk_idx) / sfreq + description = mrk_data[mrk_idx] + annot = Annotations(onset, duration, description) + self.set_annotations(annot) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a segment of data from a file. + + Boxy file organises data in two ways, parsed or un-parsed. + Regardless of type, output has (n_montages x n_sources x n_detectors + + n_marker_channels) rows, and (n_timepoints x n_blocks) columns. + """ + source_num = self._raw_extras[fi]["source_num"] + detect_num = self._raw_extras[fi]["detect_num"] + start_line = self._raw_extras[fi]["start_line"] + end_line = self._raw_extras[fi]["end_line"] + filetype = self._raw_extras[fi]["filetype"] + col_names = self._raw_extras[fi]["col_names"] + offsets = self._raw_extras[fi]["offsets"] + boxy_file = self.filenames[fi] + + # Non-parsed multiplexes sources, so we need source_num times as many + # lines in that case + if filetype == "parsed": + start_read = start_line + start + stop_read = start_read + (stop - start) + else: + assert filetype == "non-parsed" + start_read = start_line + start * source_num + stop_read = start_read + (stop - start) * source_num + assert start_read >= start_line + assert stop_read <= end_line + + # Possible detector names. + detectors = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[:detect_num] + + # Loop through our data. + one = np.zeros((len(col_names), stop_read - start_read)) + with open(boxy_file) as fid: + # Just a more efficient version of this: + # ii = 0 + # for line_num, i_line in enumerate(fid): + # if line_num >= start_read: + # if line_num >= stop_read: + # break + # # Grab actual data. + # i_data = i_line.strip().split() + # one[:len(i_data), ii] = i_data + # ii += 1 + fid.seek(offsets[start_read - start_line], 0) + for oo in one.T: + i_data = fid.readline().strip().split() + oo[: len(i_data)] = i_data + + # in theory we could index in the loop above, but it's painfully slow, + # so let's just take a hopefully minor memory hit + if filetype == "non-parsed": + ch_idxs = [ + col_names.index(f"{det}-{i_type}") + for det in detectors + for i_type in ["DC", "AC", "Ph"] + ] + one = ( + one[ch_idxs] + .reshape( # each "time point" multiplexes srcs + len(detectors), 3, -1, source_num + ) + .transpose( # reorganize into (det, source, DC/AC/Ph, t) order + 0, 3, 1, 2 + ) + .reshape( # reshape the way we store it (det x source x DAP, t) + len(detectors) * source_num * 3, -1 + ) + ) + else: + assert filetype == "parsed" + ch_idxs = [ + col_names.index(f"{det}-{i_type}{si + 1}") + for det in detectors + for si in range(source_num) + for i_type in ["DC", "AC", "Ph"] + ] + one = one[ch_idxs] + + # Place our data into the data object in place. + _mult_cal_one(data, one, idx, cals, mult) diff --git a/mne-python/source/mne/io/boxy/tests/__init__.py b/mne-python/source/mne/io/boxy/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/boxy/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/boxy/tests/test_boxy.py b/mne-python/source/mne/io/boxy/tests/test_boxy.py new file mode 100644 index 0000000000000000000000000000000000000000..58f4671edd06226c7cee6a66033a47bbd374fe11 --- /dev/null +++ b/mne-python/source/mne/io/boxy/tests/test_boxy.py @@ -0,0 +1,219 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import pytest +import scipy.io as spio +from numpy.testing import assert_allclose, assert_array_equal, assert_array_less + +from mne import pick_types +from mne.datasets import testing +from mne.io import read_raw_boxy +from mne.io.tests.test_raw import _test_raw_reader + +data_path = testing.data_path(download=False) +boxy_0_40 = ( + data_path / "BOXY" / "boxy_0_40_recording" / "boxy_0_40_notriggers_unparsed.txt" +) +p_pod_0_40 = ( + data_path + / "BOXY" + / "boxy_0_40_recording" + / "p_pod_10_6_3_loaded_data" + / "p_pod_10_6_3_notriggers_unparsed.mat" +) +boxy_0_84 = ( + data_path + / "BOXY" + / "boxy_0_84_digaux_recording" + / "boxy_0_84_triggers_unparsed.txt" +) +boxy_0_84_parsed = ( + data_path / "BOXY" / "boxy_0_84_digaux_recording" / "boxy_0_84_triggers_parsed.txt" +) +p_pod_0_84 = ( + data_path + / "BOXY" + / "boxy_0_84_digaux_recording" + / "p_pod_10_6_3_loaded_data" + / "p_pod_10_6_3_triggers_unparsed.mat" +) + + +def _assert_ppod(raw, p_pod_file): + have_types = raw.get_channel_types(unique=True) + assert "fnirs_fd_phase" in raw, have_types + assert "fnirs_cw_amplitude" in raw, have_types + assert "fnirs_fd_ac_amplitude" in raw, have_types + ppod_data = spio.loadmat(p_pod_file) + + # Compare MNE loaded data to p_pod loaded data. + map_ = dict( + dc="fnirs_cw_amplitude", ac="fnirs_fd_ac_amplitude", ph="fnirs_fd_phase" + ) + for key, value in map_.items(): + ppod = ppod_data[key].T + m = np.median(np.abs(ppod)) + assert 1e-1 < m < 1e5, key # our atol is meaningful + atol = m * 1e-10 + py = raw.get_data(value) + if key == "ph": # radians + assert_array_less(-np.pi, py) + assert_array_less(py, 3 * np.pi) + py = np.rad2deg(py) + assert_allclose(py, ppod, atol=atol, err_msg=key) + + +@testing.requires_testing_data +def test_boxy_load(): + """Test reading BOXY files.""" + raw = read_raw_boxy(boxy_0_40, verbose=True) + assert raw.info["sfreq"] == 62.5 + _assert_ppod(raw, p_pod_0_40) + + # Grab our different data types. + mne_ph = raw.copy().pick(picks="fnirs_fd_phase") + mne_dc = raw.copy().pick(picks="fnirs_cw_amplitude") + mne_ac = raw.copy().pick(picks="fnirs_fd_ac_amplitude") + + # Check channel names. + first_chans = [ + "S1_D1", + "S2_D1", + "S3_D1", + "S4_D1", + "S5_D1", + "S6_D1", + "S7_D1", + "S8_D1", + "S9_D1", + "S10_D1", + ] + last_chans = [ + "S1_D8", + "S2_D8", + "S3_D8", + "S4_D8", + "S5_D8", + "S6_D8", + "S7_D8", + "S8_D8", + "S9_D8", + "S10_D8", + ] + + assert mne_dc.info["ch_names"][:10] == [ + i_chan + " " + "DC" for i_chan in first_chans + ] + assert mne_ac.info["ch_names"][:10] == [ + i_chan + " " + "AC" for i_chan in first_chans + ] + assert mne_ph.info["ch_names"][:10] == [ + i_chan + " " + "Ph" for i_chan in first_chans + ] + + assert mne_dc.info["ch_names"][70::] == [ + i_chan + " " + "DC" for i_chan in last_chans + ] + assert mne_ac.info["ch_names"][70::] == [ + i_chan + " " + "AC" for i_chan in last_chans + ] + assert mne_ph.info["ch_names"][70::] == [ + i_chan + " " + "Ph" for i_chan in last_chans + ] + + # Since this data set has no 'digaux' for creating trigger annotations, + # let's make sure our Raw object has no annotations. + assert len(raw.annotations) == 0 + + +@testing.requires_testing_data +@pytest.mark.parametrize("fname", (boxy_0_84, boxy_0_84_parsed)) +def test_boxy_filetypes(fname): + """Test reading parsed and unparsed BOXY data files.""" + # BOXY data files can be saved in two formats (parsed and unparsed) which + # mostly determines how the data is organised. + # For parsed files, each row is a single timepoint and all + # source/detector combinations are represented as columns. + # For unparsed files, each row is a source and each group of n rows + # represents a timepoint. For example, if there are ten sources in the raw + # data then the first ten rows represent the ten sources at timepoint 1 + # while the next set of ten rows are the ten sources at timepoint 2. + # Detectors are represented as columns. + + # Since p_pod is designed to only load unparsed files, we will first + # compare MNE and p_pod loaded data from an unparsed data file. If those + # files are comparable, then we will compare the MNE loaded data between + # parsed and unparsed files. + raw = read_raw_boxy(fname, verbose=True) + assert raw.info["sfreq"] == 79.4722 + _assert_ppod(raw, p_pod_0_84) + + # Grab our different data types. + unp_dc = raw.copy().pick("fnirs_cw_amplitude") + unp_ac = raw.copy().pick("fnirs_fd_ac_amplitude") + unp_ph = raw.copy().pick("fnirs_fd_phase") + + # Check channel names. + chans = ["S1_D1", "S2_D1", "S3_D1", "S4_D1", "S5_D1", "S6_D1", "S7_D1", "S8_D1"] + + assert unp_dc.info["ch_names"] == [i_chan + " " + "DC" for i_chan in chans] + assert unp_ac.info["ch_names"] == [i_chan + " " + "AC" for i_chan in chans] + assert unp_ph.info["ch_names"] == [i_chan + " " + "Ph" for i_chan in chans] + + +@testing.requires_testing_data +@pytest.mark.parametrize("fname", (boxy_0_84, boxy_0_84_parsed)) +def test_boxy_digaux(fname): + """Test reading BOXY files and generating annotations from digaux.""" + srate = 79.4722 + raw = read_raw_boxy(fname, verbose=True) + + # Grab our different data types. + picks_dc = pick_types(raw.info, fnirs="fnirs_cw_amplitude") + picks_ac = pick_types(raw.info, fnirs="fnirs_fd_ac_amplitude") + picks_ph = pick_types(raw.info, fnirs="fnirs_fd_phase") + assert_array_equal(picks_dc, np.arange(0, 8) * 3 + 0) + assert_array_equal(picks_ac, np.arange(0, 8) * 3 + 1) + assert_array_equal(picks_ph, np.arange(0, 8) * 3 + 2) + + # Check that our event order matches what we expect. + event_list = ["1.0", "2.0", "3.0", "4.0", "5.0"] + assert_array_equal(raw.annotations.description, event_list) + + # Check that our event timings are what we expect. + event_onset = [i_time * (1.0 / srate) for i_time in [105, 185, 265, 344, 424]] + assert_allclose(raw.annotations.onset, event_onset, atol=1e-6) + + # Now let's compare parsed and unparsed events to p_pod loaded digaux. + # Load our p_pod data. + ppod_data = spio.loadmat(p_pod_0_84) + ppod_digaux = np.transpose(ppod_data["digaux"])[0] + + # Now let's get our triggers from the p_pod digaux. + # We only want the first instance of each trigger. + prev_mrk = 0 + mrk_idx = list() + duration = list() + tmp_dur = 0 + for i_num, i_mrk in enumerate(ppod_digaux): + if i_mrk != 0 and i_mrk != prev_mrk: + mrk_idx.append(i_num) + if i_mrk != 0 and i_mrk == prev_mrk: + tmp_dur += 1 + if i_mrk == 0 and i_mrk != prev_mrk: + duration.append((tmp_dur + 1) * (1.0 / srate)) + tmp_dur = 0 + prev_mrk = i_mrk + onset = np.asarray([i_mrk * (1.0 / srate) for i_mrk in mrk_idx]) + description = np.asarray([str(float(i_mrk)) for i_mrk in ppod_digaux[mrk_idx]]) + assert_array_equal(raw.annotations.description, description) + assert_allclose(raw.annotations.onset, onset, atol=1e-6) + + +@testing.requires_testing_data +@pytest.mark.parametrize("fname", (boxy_0_40, boxy_0_84, boxy_0_84_parsed)) +def test_raw_properties(fname): + """Test raw reader properties.""" + _test_raw_reader(read_raw_boxy, fname=fname, boundary_decimal=1) diff --git a/mne-python/source/mne/io/brainvision/__init__.py b/mne-python/source/mne/io/brainvision/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..860e157c014f345241f96be182bf6e7cf2b0bf43 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/__init__.py @@ -0,0 +1,7 @@ +"""BrainVision module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .brainvision import read_raw_brainvision diff --git a/mne-python/source/mne/io/brainvision/brainvision.py b/mne-python/source/mne/io/brainvision/brainvision.py new file mode 100644 index 0000000000000000000000000000000000000000..f9dfffccd55f6c313374966556e45f717041311e --- /dev/null +++ b/mne-python/source/mne/io/brainvision/brainvision.py @@ -0,0 +1,1144 @@ +"""Conversion tool from BrainVision EEG to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import configparser +import os +import os.path as op +import re +from datetime import datetime, timezone +from io import StringIO + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info +from ..._fiff.utils import _mult_cal_one, _read_segments_file +from ...annotations import Annotations, read_annotations +from ...channels import make_dig_montage +from ...defaults import HEAD_SIZE_DEFAULT +from ...transforms import _sph_to_cart +from ...utils import _DefaultEventParser, fill_doc, logger, verbose, warn +from ..base import BaseRaw + + +@fill_doc +class RawBrainVision(BaseRaw): + """Raw object from Brain Vision EEG file. + + Parameters + ---------- + vhdr_fname : path-like + Path to the EEG header file. + eog : list of (int | str) | tuple of (int | str) + Names of channels or list of indices that should be designated EOG channels. + Values should correspond to the header file. Default is ``('HEOGL', 'HEOGR', + 'VEOGb')``. + misc : list of (int | str) | tuple of (int | str) | ``'auto'`` + Names of channels or list of indices that should be designated MISC channels. + Values should correspond to the electrodes in the header file. If ``'auto'``, + units in header file are used for inferring misc channels. Default is + ``'auto'``. + scale : float + The scaling factor for EEG data. Unless specified otherwise by header file, + units are in microvolts. Default scale factor is 1. + ignore_marker_types : bool + If ``True``, ignore marker types and only use marker descriptions. Default is + ``False``. + + .. versionadded:: 1.8 + %(preload)s + %(verbose)s + + Attributes + ---------- + impedances : dict + A dictionary of all electrodes and their impedances. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + + Notes + ----- + If the BrainVision header file contains impedance measurements, these may be + accessed using ``raw.impedances`` after reading using this function. However, this + attribute will NOT be available after a save and re-load of the data. That is, it is + only available when reading data directly from the BrainVision header file. + + BrainVision markers consist of a type and a description (in addition to other fields + like onset and duration). In contrast, annotations in MNE only have a description. + Therefore, a BrainVision marker of type "Stimulus" and description "S 1" will be + converted to an annotation "Stimulus/S 1" by default. If you want to ignore the + type and instead only use the description, set ``ignore_marker_types=True``, which + will convert the same marker to an annotation "S 1". + + The first marker in a BrainVision file is usually a "New Segment" marker, which + contains the recording time. This time is stored in the ``info['meas_date']`` + attribute of the returned object and is not converted to an annotation. + """ + + _extra_attributes = ("impedances",) + + @verbose + def __init__( + self, + vhdr_fname, + eog=("HEOGL", "HEOGR", "VEOGb"), + misc="auto", + scale=1.0, + ignore_marker_types=False, + preload=False, + verbose=None, + ): # noqa: D107 + # Channel info and events + logger.info(f"Extracting parameters from {vhdr_fname}...") + hdr_fname = op.abspath(vhdr_fname) + ext = op.splitext(hdr_fname)[-1] + ahdr_format = True if ext == ".ahdr" else False + ( + info, + data_fname, + fmt, + order, + n_samples, + mrk_fname, + montage, + orig_units, + ) = _get_hdr_info(hdr_fname, eog, misc, scale) + + with open(data_fname, "rb") as f: + if isinstance(fmt, dict): # ASCII, this will be slow :( + if order == "F": # multiplexed, channels in columns + n_skip = 0 + for _ in range(int(fmt["skiplines"])): + n_skip += len(f.readline()) + offsets = np.cumsum([n_skip] + [len(line) for line in f]) + n_samples = len(offsets) - 1 + elif order == "C": # vectorized, channels, in rows + raise NotImplementedError() + else: + n_data_ch = int(info["nchan"]) + f.seek(0, os.SEEK_END) + n_samples = f.tell() + dtype_bytes = _fmt_byte_dict[fmt] + offsets = None + n_samples = n_samples // (dtype_bytes * n_data_ch) + + orig_format = "single" if isinstance(fmt, dict) else fmt + raw_extras = dict(offsets=offsets, fmt=fmt, order=order, n_samples=n_samples) + super().__init__( + info, + last_samps=[n_samples - 1], + filenames=[data_fname], + orig_format=orig_format, + preload=preload, + verbose=verbose, + raw_extras=[raw_extras], + orig_units=orig_units, + ) + + self.set_montage(montage) + + settings, _, _, _ = _aux_hdr_info(hdr_fname) + split_settings = settings.splitlines() + self.impedances = _parse_impedance(split_settings, self.info["meas_date"]) + + # Get annotations from marker file + annots = read_annotations( + mrk_fname, info["sfreq"], ignore_marker_types=ignore_marker_types + ) + self.set_annotations(annots) + + # Drop the fake ahdr channel if needed + if ahdr_format: + self.drop_channels(_AHDR_CHANNEL_NAME) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + # read data + n_data_ch = self._raw_extras[fi]["orig_nchan"] + fmt = self._raw_extras[fi]["fmt"] + if self._raw_extras[fi]["order"] == "C": + _read_segments_c(self, data, idx, fi, start, stop, cals, mult) + elif isinstance(fmt, str): + dtype = _fmt_dtype_dict[fmt] + _read_segments_file( + self, + data, + idx, + fi, + start, + stop, + cals, + mult, + dtype=dtype, + n_channels=n_data_ch, + ) + else: + offsets = self._raw_extras[fi]["offsets"] + with open(self.filenames[fi], "rb") as fid: + fid.seek(offsets[start]) + block = np.empty((n_data_ch, stop - start)) + for ii in range(stop - start): + line = fid.readline().decode("ASCII") + line = line.strip() + + # Not sure why we special-handle the "," character here, but let's + # just keep this for historical and backward- compat reasons + if ( + isinstance(fmt, dict) + and "decimalsymbol" in fmt + and fmt["decimalsymbol"] != "." + ): + line = line.replace(",", ".") + + if " " in line: + line_data = line.split() + elif "," in line: + # likely exported from BrainVision Analyzer? + line_data = line.split(",") + else: + raise RuntimeError( + "Unknown BrainVision data format encountered. " + "Please contact the MNE-Python developers." + ) + + block[:n_data_ch, ii] = [float(part) for part in line_data] + _mult_cal_one(data, block, idx, cals, mult) + + +def _read_segments_c(raw, data, idx, fi, start, stop, cals, mult): + """Read chunk of vectorized raw data.""" + n_samples = raw._raw_extras[fi]["n_samples"] + fmt = raw._raw_extras[fi]["fmt"] + dtype = _fmt_dtype_dict[fmt] + n_bytes = _fmt_byte_dict[fmt] + n_channels = raw._raw_extras[fi]["orig_nchan"] + block = np.zeros((n_channels, stop - start)) + with open(raw.filenames[fi], "rb", buffering=0) as fid: + ids = np.arange(idx.start, idx.stop) if isinstance(idx, slice) else idx + for ch_id in ids: + fid.seek(start * n_bytes + ch_id * n_bytes * n_samples) + block[ch_id] = np.fromfile(fid, dtype, stop - start) + _mult_cal_one(data, block, idx, cals, mult) + + +def _read_mrk(fname): + """Read annotations from a vmrk/amrk file. + + Parameters + ---------- + fname : str + vmrk/amrk file to be read. + + Returns + ------- + onset : list of float + The onsets in seconds. + duration : list of float + The onsets in seconds. + type_ : list of str + The marker types. + description : list of str + The marker descriptions. + date_str : str + The recording time. Defaults to empty string if no recording time is found. + """ + # read marker file + with open(fname, "rb") as fid: + txt = fid.read() + + # we don't actually need to know the encoding for the header line. the characters in + # it all belong to ASCII and are thus the same in Latin-1 and UTF-8 + header = txt.decode("ascii", "ignore").split("\n")[0].strip() + _check_bv_version(header, "marker") + + # although the markers themselves are guaranteed to be ASCII (they consist of + # numbers and a few reserved words), we should still decode the file properly here + # because other (currently unused) blocks are not guaranteed to be ASCII + + try: + # if there is an explicit codepage set, use it; we pretend like it's ASCII when + # searching for the codepage + cp_setting = re.search( + "Codepage=(.+)", txt.decode("ascii", "ignore"), re.IGNORECASE & re.MULTILINE + ) + codepage = "utf-8" + if cp_setting: + codepage = cp_setting.group(1).strip() + # BrainAmp Recorder also uses ANSI codepage; an ANSI codepage raises a + # LookupError exception; Python recognize ANSI decoding as cp1252 + if codepage == "ANSI": + codepage = "cp1252" + txt = txt.decode(codepage) + except UnicodeDecodeError: + # if UTF-8 (new standard) or explicit codepage setting fails, fallback to + # Latin-1, which is Windows default and implicit standard in older recordings + txt = txt.decode("latin-1") + + # extract Marker Infos block + onset, duration, type_, description = [], [], [], [] + date_str = "" + + m = re.search(r"\[Marker Infos\]", txt, re.IGNORECASE) + if not m: + return onset, duration, type_, description, date_str + + mk_txt = txt[m.end() :] + m = re.search(r"^\[.*\]$", mk_txt) + if m: + mk_txt = mk_txt[: m.start()] + + # extract event information + items = re.findall(r"^Mk\d+=(.*)", mk_txt, re.MULTILINE) + for info in items: + info_data = info.split(",") + mtype, mdesc, this_onset, this_duration = info_data[:4] + # commas in mtype and mdesc are handled as "\1", convert back to comma + mtype = mtype.replace(r"\1", ",") + mdesc = mdesc.replace(r"\1", ",") + if date_str == "" and len(info_data) == 5 and mtype == "New Segment": + # to handle the origin of time and handle the presence of multiple New + # Segment annotations, we only keep the first one that is different from an + # empty string for date_str + date_str = info_data[-1] + + this_duration = int(this_duration) if this_duration.isdigit() else 0 + duration.append(this_duration) + onset.append(int(this_onset) - 1) # BV is 1-indexed, not 0-indexed + type_.append(mtype) + description.append(mdesc) + + return onset, duration, type_, description, date_str + + +def _read_annotations_brainvision(fname, sfreq="auto", ignore_marker_types=False): + """Create Annotations from BrainVision vmrk/amrk. + + This function reads a .vmrk or .amrk file and creates an :class:`mne.Annotations` + object. + + Parameters + ---------- + fname : str | object + The path to the .vmrk/.amrk file. + sfreq : float | 'auto' + The sampling frequency in the file. This is necessary because Annotations are + expressed in seconds and vmrk/amrk files are in samples. If set to 'auto' then + the sfreq is taken from the .vhdr/.ahdr file with the same name (without file + extension). So data.vmrk/amrk looks for sfreq in data.vhdr or, if it does not + exist, in data.ahdr. + ignore_marker_types : bool + If True, ignore marker types and only use marker descriptions. Default is False. + + Returns + ------- + annotations : instance of Annotations + The annotations present in the file. + """ + onset, duration, type_, description, date_str = _read_mrk(fname) + orig_time = _str_to_meas_date(date_str) + + if sfreq == "auto": + hdr_fname = op.splitext(fname)[0] + ".vhdr" + # if vhdr file does not exist assume that the format is ahdr + if not op.exists(hdr_fname): + hdr_fname = op.splitext(fname)[0] + ".ahdr" + logger.info(f"Finding 'sfreq' from header file: {hdr_fname}") + _, _, _, info = _aux_hdr_info(hdr_fname) + sfreq = info["sfreq"] + + # skip the first "New Segment" marker (as it only contains the recording time) + if len(type_) > 0 and type_[0] == "New Segment": + onset = onset[1:] + duration = duration[1:] + type_ = type_[1:] + description = description[1:] + + onset = np.array(onset, dtype=float) / sfreq + duration = np.array(duration, dtype=float) / sfreq + if not ignore_marker_types: + description = [f"{t}/{d}" for t, d in zip(type_, description)] + annotations = Annotations( + onset=onset, duration=duration, description=description, orig_time=orig_time + ) + return annotations + + +def _check_bv_version(header, kind): + """Check the header version.""" + _data_err = ( + "MNE-Python currently only supports %s versions 1.0 and 2.0, got unparsable " + "%r. Contact MNE-Python developers for support." + ) + # optional space, optional Core or V-Amp, optional Exchange, Version/Header, + # optional comma, 1/2 + _data_re = r"Brain ?Vision( Core| V-Amp)? Data( Exchange)? %s File,? Version %s\.0" + + assert kind in ("header", "marker") + + for version in range(1, 3): + this_re = _data_re % (kind.capitalize(), version) + if re.search(this_re, header) is not None: + return version + else: + if header == "": + warn(f"Missing header in {kind} file.") + else: + warn(_data_err % (kind, header)) + + +_orientation_dict = dict(MULTIPLEXED="F", VECTORIZED="C") +_fmt_dict = dict(INT_16="short", INT_32="int", IEEE_FLOAT_32="single") +_fmt_byte_dict = dict(short=2, int=4, single=4) +_fmt_dtype_dict = dict(short=" 0: + misc += to_misc + warn( + f"No coordinate information found for channels {to_misc}. Setting " + "channel types to misc. To avoid this warning, set channel types " + "explicitly." + ) + + if np.isnan(cals).any(): + raise RuntimeError("Missing channel units") + + # Attempts to extract filtering info from header. If not found, both are set to + # zero. + settings = settings.splitlines() + idx = None + + if "Channels" in settings: + idx = settings.index("Channels") + settings = settings[idx + 1 :] + hp_col, lp_col = 4, 5 + for idx, setting in enumerate(settings): + if re.match(r"#\s+Name", setting): + break + else: + idx = None + + # If software filters are active, then they override the hardware setup; we still + # want to be able to double check the channel names for alignment purposes, we keep + # track of the hardware setting idx + idx_amp = idx + filter_list_has_ch_name = True + + if "S o f t w a r e F i l t e r s" in settings: + idx = settings.index("S o f t w a r e F i l t e r s") + for idx, setting in enumerate(settings[idx + 1 :], idx + 1): + if re.match(r"#\s+Low Cutoff", setting): + hp_col, lp_col = 1, 2 + filter_list_has_ch_name = False + warn( + "Online software filter detected. Using software filter settings " + "and ignoring hardware values" + ) + break + else: + idx = idx_amp + + if idx: + lowpass = [] + highpass = [] + + # for newer BV files, the unit is specified for every channel separated by a + # single space, while for older files, the unit is specified in the column + # headers + divider = r"\s+" + if "Resolution / Unit" in settings[idx]: + shift = 1 # shift for unit + else: + shift = 0 + + # Extract filter units and convert from seconds to Hz if necessary. this cannot + # be done as post-processing as the inverse t-f relationship means that the + # min/max comparisons don't make sense unless we know the units. + # + # For reasoning about the s to Hz conversion, see this reference: + # `Ebersole, J. S., & Pedley, T. A. (Eds.). (2003). + # Current practice of clinical electroencephalography. + # Lippincott Williams & Wilkins.`, page 40-41 + header = re.split(r"\s\s+", settings[idx]) + hp_s = "[s]" in header[hp_col] + lp_s = "[s]" in header[lp_col] + + for i, ch in enumerate(ch_names, 1): + if ahdr_format and i == len(ch_names) and ch == _AHDR_CHANNEL_NAME: + break + # double check alignment with channel by using the hw settings + if idx == idx_amp: + line_amp = settings[idx + i] + else: + line_amp = settings[idx_amp + i] + assert line_amp.find(ch) > -1 + + # Correct shift for channel names with spaces + # Header already gives 1 therefore has to be subtracted + if filter_list_has_ch_name: + ch_name_parts = re.split(divider, ch) + real_shift = shift + len(ch_name_parts) - 1 + else: + real_shift = shift + + line = re.split(divider, settings[idx + i]) + highpass.append(line[hp_col + real_shift]) + lowpass.append(line[lp_col + real_shift]) + + if len(highpass) == 0: + pass + elif len(set(highpass)) == 1: + if highpass[0] in ("NaN", "Off"): + pass # Placeholder for future use. Highpass set in _empty_info + elif highpass[0] == "DC": + info["highpass"] = 0.0 + else: + info["highpass"] = float(highpass[0]) + if hp_s: + # filter time constant t [secs] to Hz conversion: 1/2*pi*t + info["highpass"] = 1.0 / (2 * np.pi * info["highpass"]) + + else: + heterogeneous_hp_filter = True + if hp_s: + # We convert channels with disabled filters to having highpass relaxed / + # no filters + highpass = [ + float(filt) if filt not in ("NaN", "Off", "DC") else np.inf + for filt in highpass + ] + info["highpass"] = np.max(np.array(highpass, dtype=np.float64)) + # Conveniently enough 1 / np.inf = 0.0, so this works for DC / no + # highpass filter + # filter time constant t [secs] to Hz conversion: 1/2*pi*t + info["highpass"] = 1.0 / (2 * np.pi * info["highpass"]) + + # not exactly the cleanest use of FP, but this makes us more + # conservative in *not* warning. + if info["highpass"] == 0.0 and len(set(highpass)) == 1: + # not actually heterogeneous in effect + # ... just heterogeneously disabled + heterogeneous_hp_filter = False + else: + highpass = [ + float(filt) if filt not in ("NaN", "Off", "DC") else 0.0 + for filt in highpass + ] + info["highpass"] = np.min(np.array(highpass, dtype=np.float64)) + if info["highpass"] == 0.0 and len(set(highpass)) == 1: + # not actually heterogeneous in effect + # ... just heterogeneously disabled + heterogeneous_hp_filter = False + + if heterogeneous_hp_filter: + warn( + "Channels contain different highpass filters. Lowest (weakest) " + f"filter setting ({info['highpass']:0.2f} Hz) will be stored." + ) + + if len(lowpass) == 0: + pass + elif len(set(lowpass)) == 1: + if lowpass[0] in ("NaN", "Off", "0"): + pass # Placeholder for future use. Lowpass set in _empty_info + else: + info["lowpass"] = float(lowpass[0]) + if lp_s: + # filter time constant t [secs] to Hz conversion: 1/2*pi*t + info["lowpass"] = 1.0 / (2 * np.pi * info["lowpass"]) + + else: + heterogeneous_lp_filter = True + if lp_s: + # We convert channels with disabled filters to having infinitely relaxed + # / no filters + lowpass = [ + float(filt) if filt not in ("NaN", "Off", "0") else 0.0 + for filt in lowpass + ] + info["lowpass"] = np.min(np.array(lowpass, dtype=np.float64)) + try: + # filter time constant t [secs] to Hz conversion: 1/2*pi*t + info["lowpass"] = 1.0 / (2 * np.pi * info["lowpass"]) + + except ZeroDivisionError: + if len(set(lowpass)) == 1: + # No lowpass actually set for the weakest setting so we set + # lowpass to the Nyquist frequency + info["lowpass"] = info["sfreq"] / 2.0 + # not actually heterogeneous in effect + # ... just heterogeneously disabled + heterogeneous_lp_filter = False + else: + # no lowpass filter is the weakest filter, but it wasn't the + # only filter + pass + else: + # We convert channels with disabled filters to having infinitely relaxed + # / no filters + lowpass = [ + float(filt) if filt not in ("NaN", "Off", "0") else np.inf + for filt in lowpass + ] + info["lowpass"] = np.max(np.array(lowpass, dtype=np.float64)) + + if np.isinf(info["lowpass"]): + # No lowpass actually set for the weakest setting so we set lowpass + # to the Nyquist frequency + info["lowpass"] = info["sfreq"] / 2.0 + if len(set(lowpass)) == 1: + # not actually heterogeneous in effect + # ... just heterogeneously disabled + heterogeneous_lp_filter = False + + if heterogeneous_lp_filter: + # this isn't clean FP, but then again, we only want to provide the + # Nyquist hint when the lowpass filter was actually calculated from + # dividing the sampling frequency by 2, so the exact/direct comparison + # (instead of tolerance) makes sense + if info["lowpass"] == info["sfreq"] / 2.0: + nyquist = ", Nyquist limit" + else: + nyquist = "" + warn( + "Channels contain different lowpass filters. " + f"Highest (weakest) filter setting ({info['lowpass']:0.2f} " + f"Hz{nyquist}) will be stored." + ) + + # Creates a list of dicts of eeg channels for raw.info + logger.info("Setting channel info structure...") + info["chs"] = [] + for idx, ch_name in enumerate(ch_names): + if ch_name in eog or idx in eog or idx - nchan in eog: + kind = FIFF.FIFFV_EOG_CH + coil_type = FIFF.FIFFV_COIL_NONE + unit = FIFF.FIFF_UNIT_V + elif ch_name in misc or idx in misc or idx - nchan in misc: + kind = FIFF.FIFFV_MISC_CH + coil_type = FIFF.FIFFV_COIL_NONE + if ch_name in misc_chs: + unit = misc_chs[ch_name] + else: + unit = FIFF.FIFF_UNIT_NONE + elif ch_name == "STI 014": + kind = FIFF.FIFFV_STIM_CH + coil_type = FIFF.FIFFV_COIL_NONE + unit = FIFF.FIFF_UNIT_NONE + else: + kind = FIFF.FIFFV_EEG_CH + coil_type = FIFF.FIFFV_COIL_EEG + unit = FIFF.FIFF_UNIT_V + info["chs"].append( + dict( + ch_name=ch_name, + coil_type=coil_type, + kind=kind, + logno=idx + 1, + scanno=idx + 1, + cal=cals[idx], + range=ranges[idx], + loc=np.full(12, np.nan), + unit=unit, + unit_mul=FIFF.FIFF_UNITM_NONE, + coord_frame=FIFF.FIFFV_COORD_HEAD, + ) + ) + + info._unlocked = False + info._update_redundant() + return (info, data_fname, fmt, order, n_samples, mrk_fname, montage, orig_units) + + +@fill_doc +def read_raw_brainvision( + vhdr_fname, + eog=("HEOGL", "HEOGR", "VEOGb"), + misc="auto", + scale=1.0, + ignore_marker_types=False, + preload=False, + verbose=None, +) -> RawBrainVision: + """Reader for Brain Vision EEG file. + + Parameters + ---------- + vhdr_fname : path-like + Path to the EEG header file. + eog : list of (int | str) | tuple of (int | str) + Names of channels or list of indices that should be designated EOG channels. + Values should correspond to the header file Default is ``('HEOGL', 'HEOGR', + 'VEOGb')``. + misc : list of (int | str) | tuple of (int | str) | ``'auto'`` + Names of channels or list of indices that should be designated MISC channels. + Values should correspond to the electrodes in the header file. If ``'auto'``, + units in header file are used for inferring misc channels. Default is + ``'auto'``. + scale : float + The scaling factor for EEG data. Unless specified otherwise by header file, + units are in microvolts. Default scale factor is 1. + ignore_marker_types : bool + If ``True``, ignore marker types and only use marker descriptions. Default is + ``False``. + + .. versionadded:: 1.8 + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawBrainVision + A Raw object containing BrainVision data. See :class:`mne.io.Raw` for + documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawBrainVision. + + Notes + ----- + If the BrainVision header file contains impedance measurements, these may be + accessed using ``raw.impedances`` after reading using this function. However, this + attribute will NOT be available after a save and re-load of the data. That is, it is + only available when reading data directly from the BrainVision header file. + + BrainVision markers consist of a type and a description (in addition to other fields + like onset and duration). In contrast, annotations in MNE only have a description. + Therefore, a BrainVision marker of type "Stimulus" and description "S 1" will be + converted to an annotation "Stimulus/S 1" by default. If you want to ignore the + type and instead only use the description, set ``ignore_marker_types=True``, which + will convert the same marker to an annotation "S 1". + + The first marker in a BrainVision file is usually a "New Segment" marker, which + contains the recording time. This time is stored in the ``info['meas_date']`` + attribute of the returned object and is not converted to an annotation. + """ + return RawBrainVision( + vhdr_fname=vhdr_fname, + eog=eog, + misc=misc, + scale=scale, + ignore_marker_types=ignore_marker_types, + preload=preload, + verbose=verbose, + ) + + +_BV_EVENT_IO_OFFSETS = { + "Event/": 0, + "Stimulus/S": 0, + "Response/R": 1000, + "Optic/O": 2000, +} +_OTHER_ACCEPTED_MARKERS = {"New Segment/": 99999, "SyncStatus/Sync On": 99998} +_OTHER_OFFSET = 10001 # where to start "unknown" event_ids +_AHDR_CHANNEL_NAME = "AHDR_CHANNEL" + + +class _BVEventParser(_DefaultEventParser): + """Parse standard brainvision events, accounting for non-standard ones.""" + + def __call__(self, description): + """Parse BrainVision event codes (like `Stimulus/S 11`) to ints.""" + offsets = _BV_EVENT_IO_OFFSETS + + maybe_digit = description[-3:].strip() + kind = description[:-3] + if maybe_digit.isdigit() and kind in offsets: + code = int(maybe_digit) + offsets[kind] + elif description in _OTHER_ACCEPTED_MARKERS: + code = _OTHER_ACCEPTED_MARKERS[description] + else: + code = super().__call__(description, offset=_OTHER_OFFSET) + return code + + +def _check_bv_annot(descriptions): + markers_basename = set([dd.rstrip("0123456789 ") for dd in descriptions]) + bv_markers = set(_BV_EVENT_IO_OFFSETS.keys()).union( + set(_OTHER_ACCEPTED_MARKERS.keys()) + ) + return len(markers_basename - bv_markers) == 0 + + +def _parse_impedance(settings, recording_date=None): + """Parse impedances from the header file. + + Parameters + ---------- + settings : list + The header settings lines from the VHDR/AHDR file. + recording_date : datetime.datetime | None + The date of the recording as extracted from the VMRK/AMRK file. + + Returns + ------- + impedances : dict + A dictionary of all electrodes and their impedances. + """ + ranges = _parse_impedance_ranges(settings) + impedance_setting_lines = [ + i for i in settings if i.startswith("Impedance [") and i.endswith(" :") + ] + impedances = dict() + if len(impedance_setting_lines) > 0: + idx = settings.index(impedance_setting_lines[0]) + impedance_setting = impedance_setting_lines[0].split() + impedance_unit = impedance_setting[1].lstrip("[").rstrip("]") + impedance_time = None + + # If we have a recording date, we can update it with the time of impedance + # measurement + if recording_date is not None: + meas_time = [int(i) for i in impedance_setting[3].split(":")] + impedance_time = recording_date.replace( + hour=meas_time[0], + minute=meas_time[1], + second=meas_time[2], + microsecond=0, + ) + for setting in settings[idx + 1 :]: + # Parse channel impedances until we find a line that doesn't start with a + # channel name and optional +/- polarity for passive elecs + match = re.match(r"[ a-zA-Z0-9_+-]+:", setting) + if match: + channel_name = match.group().rstrip(":") + channel_imp_line = setting.split() + imp_as_number = re.findall(r"[-+]?\d*\.\d+|\d+", channel_imp_line[-1]) + channel_impedance = dict( + imp=float(imp_as_number[0]) if imp_as_number else np.nan, + imp_unit=impedance_unit, + ) + if impedance_time is not None: + channel_impedance.update({"imp_meas_time": impedance_time}) + + if channel_name == "Ref" and "Reference" in ranges: + channel_impedance.update(ranges["Reference"]) + elif channel_name == "Gnd" and "Ground" in ranges: + channel_impedance.update(ranges["Ground"]) + elif "Data" in ranges: + channel_impedance.update(ranges["Data"]) + impedances[channel_name] = channel_impedance + else: + break + return impedances + + +def _parse_impedance_ranges(settings): + """Parse the selected electrode impedance ranges from the header. + + Parameters + ---------- + settings : list + The header settings lines from the VHDR/AHDR file. + + Returns + ------- + electrode_imp_ranges : dict + A dictionary of impedance ranges for each type of electrode. + """ + impedance_ranges = [ + item for item in settings if "Selected Impedance Measurement Range" in item + ] + electrode_imp_ranges = dict() + if impedance_ranges: + if len(impedance_ranges) == 1: + img_range = impedance_ranges[0].split() + for electrode_type in ["Data", "Reference", "Ground"]: + electrode_imp_ranges[electrode_type] = { + "imp_lower_bound": float(img_range[-4]), + "imp_upper_bound": float(img_range[-2]), + "imp_range_unit": img_range[-1], + } + else: + for electrode_range in impedance_ranges: + electrode_range = electrode_range.split() + electrode_imp_ranges[electrode_range[0]] = { + "imp_lower_bound": float(electrode_range[6]), + "imp_upper_bound": float(electrode_range[8]), + "imp_range_unit": electrode_range[9], + } + return electrode_imp_ranges diff --git a/mne-python/source/mne/io/brainvision/tests/__init__.py b/mne-python/source/mne/io/brainvision/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/brainvision/tests/data/test.eeg b/mne-python/source/mne/io/brainvision/tests/data/test.eeg new file mode 100644 index 0000000000000000000000000000000000000000..053aae454a9264fac106bd36417ffae63651ebcc --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test.eeg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0023a682b3291e095acb593472eb06d00e630c7abcfabad5ebc3ef46faafe850 +size 505600 diff --git a/mne-python/source/mne/io/brainvision/tests/data/test.hpts b/mne-python/source/mne/io/brainvision/tests/data/test.hpts new file mode 100644 index 0000000000000000000000000000000000000000..ce260245ccb1c4ba285bf03f72ab43cd59f1bf47 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test.hpts @@ -0,0 +1,42 @@ +cardinal 2 -5.6729 -12.3873 -30.3671 +cardinal 1 -37.6782 -10.4957 91.5228 +cardinal 3 -131.3127 9.3976 -22.2363 +hpi 1 -30.4493 -11.8450 83.3601 +hpi 2 -122.5353 9.2232 -28.6828 +hpi 3 -6.8518 -47.0697 -37.0829 +hpi 4 7.3744 -50.6297 -12.1376 +hpi 5 -33.4264 -43.7352 -57.7756 +eeg FP1 3.8676 -77.0439 -13.0212 +eeg FP2 -31.9297 -70.6852 -57.4881 +eeg F7 -6.1042 -68.2969 45.4939 +eeg GND -26.8874 -108.1869 -29.3948 +eeg F8 -93.4960 -57.5314 -59.6307 +eeg FC5 -28.5191 -90.8090 65.3667 +eeg F3 -20.3574 -115.7971 26.8439 +eeg Fz -52.4084 -132.2694 -10.8940 +eeg F4 -79.6612 -109.5778 -50.2500 +eeg FC6 -120.4482 -80.1049 -48.4998 +eeg FC1 -59.5687 -140.7296 28.7939 +eeg FCz -79.2198 -141.0449 8.6352 +eeg FC2 -98.5593 -130.9501 -14.6008 +eeg CP5 -73.7114 -79.5972 108.4127 +eeg C3 -64.2139 -118.9901 81.5907 +eeg Cz -109.4613 -144.7746 38.7691 +eeg C4 -144.6454 -113.6235 -15.1309 +eeg CP6 -172.6252 -72.4156 -5.0970 +eeg CP1 -111.8295 -132.7764 88.6002 +eeg CPz -133.5129 -127.0993 66.4257 +eeg CP2 -155.4911 -128.0503 41.9582 +eeg P7 -87.9713 -42.7048 122.4772 +eeg P3 -125.8923 -88.7830 113.4730 +eeg Pz -159.2922 -104.0640 84.9862 +eeg P4 -188.8384 -81.4090 45.6836 +eeg P8 -179.7623 -35.5428 13.4639 +eeg O1 -134.3199 -7.4196 99.9593 +eeg POz -167.0685 -28.2038 84.3689 +eeg O2 -172.0302 -4.7960 60.4032 +eeg A1 -65.6105 -14.9387 115.0734 +eeg ReRef -163.2992 3.5260 -9.0238 +eeg HL 1.0591 6.2860 4.8814 +eeg HR -51.6423 10.2912 -47.8098 +EEG Vb -61.2542 29.6360 -43.4039 diff --git a/mne-python/source/mne/io/brainvision/tests/data/test.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..30e177a160d85fbb7589344933d436a013e2bb06 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test.vhdr @@ -0,0 +1,142 @@ +Brain Vision Data Exchange Header File Version 1.0 +; Data created by the Vision Recorder + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=test.vmrk +DataFormat=BINARY +; Data orientation: MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +NumberOfChannels=32 +; Sampling interval in microseconds +SamplingInterval=1000 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5, +Ch3=F3,,0.5 +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,BS +Ch28=CP6,,0.5,µS +Ch29=HL,,0.5,ARU +Ch30=HR,,0.5,uS +Ch31=Vb,,0.5,S +Ch32=ReRef,,0.5,C + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [s] High Cutoff [Hz] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 0.5 µV DC 250 Off 0 +2 FP2 2 0.5 µV DC 250 Off 0 +3 F3 3 0.5 µV DC 250 Off 0 +4 F4 4 0.5 µV DC 250 Off 0 +5 C3 5 0.5 µV DC 250 Off 0 +6 C4 6 0.5 µV DC 250 Off 0 +7 P3 7 0.5 µV DC 250 Off 0 +8 P4 8 0.5 µV DC 250 Off 0 +9 O1 9 0.5 µV DC 250 Off 0 +10 O2 10 0.5 µV DC 250 Off 0 +11 F7 11 0.5 µV DC 250 Off 0 +12 F8 12 0.5 µV DC 250 Off 0 +13 P7 13 0.5 µV DC 250 Off 0 +14 P8 14 0.5 µV DC 250 Off 0 +15 Fz 15 0.5 µV DC 250 Off 0 +16 FCz 16 0.5 µV DC 250 Off 0 +17 Cz 17 0.5 µV DC 250 Off 0 +18 CPz 18 0.5 µV DC 250 Off 0 +19 Pz 19 0.5 µV DC 250 Off 0 +20 POz 20 0.5 µV DC 250 Off 0 +21 FC1 21 0.5 µV DC 250 Off 0 +22 FC2 22 0.5 µV DC 250 Off 0 +23 CP1 23 0.5 µV DC 250 Off 0 +24 CP2 24 0.5 µV DC 250 Off 0 +25 FC5 25 0.5 µV DC 250 Off 0 +26 FC6 26 0.5 µV DC 250 Off 0 +27 CP5 27 0.5 BS DC 250 Off 0 +28 CP6 28 0.5 µS DC 250 Off 0 +29 HL 29 0.5 ARU DC 250 Off 0 +30 HR 30 0.5 uS DC 250 Off 0 +31 Vb 31 0.5 S DC 250 Off 0 +32 ReRef 32 0.5 C DC 250 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + + +Data Electrodes Selected Impedance Measurement Range: 0 - 100 kOhm +Ground Electrode Selected Impedance Measurement Range: 0 - 10 kOhm +Reference Electrode Selected Impedance Measurement Range: 0 - 10 kOhm +Impedance [kOhm] at 16:12:27 : +FP1: ??? +FP2: ??? +F3: ??? +F4: ??? +C3: ??? +C4: ??? +P3: ??? +P4: ??? +O1: ??? +O2: ??? +F7: ??? +F8: ??? +P7: ??? +P8: ??? +Fz: ??? +FCz: ??? +Cz: ??? +CPz: ??? +Pz: ??? +POz: ??? +FC1: ??? +FC2: ??? +CP1: ??? +CP2: ??? +FC5: ??? +FC6: ??? +CP5: ??? +CP6: ??? +HL: ??? +HR: ??? +Vb: ??? +ReRef: ??? +Ref: 0 +Gnd: 4 diff --git a/mne-python/source/mne/io/brainvision/tests/data/test.vmrk b/mne-python/source/mne/io/brainvision/tests/data/test.vmrk new file mode 100644 index 0000000000000000000000000000000000000000..11f707aef3dea87b506e851ba326cd5e145a0e1c --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test.vmrk @@ -0,0 +1,25 @@ +Brain Vision Data Exchange Marker File, Version 1.0 + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg + +[Marker Infos] +; Each entry: Mk=,,, +; , +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in type or description text are coded as "\1". +Mk1=New Segment,,1,1,0,20131113161403794232 +Mk2=Stimulus,S253,487,0,0 +Mk3=Stimulus,S255,497,1,0 +Mk4=Event,254,1770,1,0 +Mk5=Stimulus,S255,1780,1,0 +Mk6=Event,254,3253,1,0 +Mk7=Stimulus,S255,3263,1,0 +Mk8=Stimulus,S253,4936,1,0 +Mk9=Stimulus,S255,4946,1,0 +Mk10=Response,R255,6000,1,0 +Mk11=Event,254,6620,1,0 +Mk12=Stimulus,S255,6630,1,0 +Mk13=SyncStatus,Sync On,7630,1,0 +Mk14=Optic,O 1,7700,1,0 diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_bin_raw.fif b/mne-python/source/mne/io/brainvision/tests/data/test_bin_raw.fif new file mode 100644 index 0000000000000000000000000000000000000000..39c9056c1febc048fb2fd85364507acb5db94717 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_bin_raw.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d1b03791c67f161648b283a5dfc0118166478681192bb0135e7dea62deaa8be5 +size 526560 diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_elp.txt b/mne-python/source/mne/io/brainvision/tests/data/test_elp.txt new file mode 100644 index 0000000000000000000000000000000000000000..3754a676422e89c2200c76bc9cec19a70d6d0f59 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_elp.txt @@ -0,0 +1,45 @@ +% Ascii stylus data file created by FastSCAN V4.0.7 on Thu Oct 17 12:30:44 2013 +% raw surface, 86 visible points, bounding box reference +% x y z + -5.6729 -12.3873 -30.3671 + -37.6782 -10.4957 91.5228 + -131.3127 9.3976 -22.2363 + -30.4493 -11.8450 83.3601 + -122.5353 9.2232 -28.6828 + -6.8518 -47.0697 -37.0829 + 7.3744 -50.6297 -12.1376 + -33.4264 -43.7352 -57.7756 + 3.8676 -77.0439 -13.0212 + -31.9297 -70.6852 -57.4881 + -6.1042 -68.2969 45.4939 + -26.8874 -108.1869 -29.3948 + -93.4960 -57.5314 -59.6307 + -28.5191 -90.8090 65.3667 + -20.3574 -115.7971 26.8439 + -52.4084 -132.2694 -10.8940 + -79.6612 -109.5778 -50.2500 + -120.4482 -80.1049 -48.4998 + -59.5687 -140.7296 28.7939 + -79.2198 -141.0449 8.6352 + -98.5593 -130.9501 -14.6008 + -73.7114 -79.5972 108.4127 + -64.2139 -118.9901 81.5907 + -109.4613 -144.7746 38.7691 + -144.6454 -113.6235 -15.1309 + -172.6252 -72.4156 -5.0970 + -111.8295 -132.7764 88.6002 + -133.5129 -127.0993 66.4257 + -155.4911 -128.0503 41.9582 + -87.9713 -42.7048 122.4772 + -125.8923 -88.7830 113.4730 + -159.2922 -104.0640 84.9862 + -188.8384 -81.4090 45.6836 + -179.7623 -35.5428 13.4639 + -134.3199 -7.4196 99.9593 + -167.0685 -28.2038 84.3689 + -172.0302 -4.7960 60.4032 + -65.6105 -14.9387 115.0734 + -163.2992 3.5260 -9.0238 + 1.0591 6.2860 4.8814 + -51.6423 10.2912 -47.8098 + -61.2542 29.6360 -43.4039 diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_highpass.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_highpass.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..c96daa0a9798281fd87e4ec0521133d8cd1f4590 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_highpass.vhdr @@ -0,0 +1,139 @@ +Brain Vision Data Exchange Header File Version 1.0 +; Data created by the Vision Recorder + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=test.vmrk +DataFormat=BINARY +; Data orientation: MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +NumberOfChannels=32 +; Sampling interval in microseconds +SamplingInterval=1000 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5,µV +Ch3=F3,,0.5,µV +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,µV +Ch28=CP6,,0.5,µV +Ch29=HL,,0.5,µV +Ch30=HR,,0.5,µV +Ch31=Vb,,0.5,µV +Ch32=ReRef,,0.5,µV + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [s] High Cutoff [Hz] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 0.5 µV 10 250 Off 0 +2 FP2 2 0.5 µV 10 250 Off 0 +3 F3 3 0.5 µV 10 250 Off 0 +4 F4 4 0.5 µV 10 250 Off 0 +5 C3 5 0.5 µV 10 250 Off 0 +6 C4 6 0.5 µV 10 250 Off 0 +7 P3 7 0.5 µV 10 250 Off 0 +8 P4 8 0.5 µV 10 250 Off 0 +9 O1 9 0.5 µV 10 250 Off 0 +10 O2 10 0.5 µV 10 250 Off 0 +11 F7 11 0.5 µV 10 250 Off 0 +12 F8 12 0.5 µV 10 250 Off 0 +13 P7 13 0.5 µV 10 250 Off 0 +14 P8 14 0.5 µV 10 250 Off 0 +15 Fz 15 0.5 µV 10 250 Off 0 +16 FCz 16 0.5 µV 10 250 Off 0 +17 Cz 17 0.5 µV 10 250 Off 0 +18 CPz 18 0.5 µV 10 250 Off 0 +19 Pz 19 0.5 µV 10 250 Off 0 +20 POz 20 0.5 µV 10 250 Off 0 +21 FC1 21 0.5 µV 10 250 Off 0 +22 FC2 22 0.5 µV 10 250 Off 0 +23 CP1 23 0.5 µV 10 250 Off 0 +24 CP2 24 0.5 µV 10 250 Off 0 +25 FC5 25 0.5 µV 10 250 Off 0 +26 FC6 26 0.5 µV 10 250 Off 0 +27 CP5 27 0.5 µV 10 250 Off 0 +28 CP6 28 0.5 µV 10 250 Off 0 +29 HL 29 0.5 µV 10 250 Off 0 +30 HR 30 0.5 µV 10 250 Off 0 +31 Vb 31 0.5 µV 10 250 Off 0 +32 ReRef 32 0.5 µV 10 250 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + +Data / Ref / Gnd Electrodes Selected Impedance Measurement Range: 0 - 100 kOhm +Impedance [kOhm] at 16:12:27 : +FP1: ??? +FP2: ??? +F3: ??? +F4: ??? +C3: ??? +C4: ??? +P3: ??? +P4: ??? +O1: ??? +O2: ??? +F7: ??? +F8: ??? +P7: ??? +P8: ??? +Fz: ??? +FCz: ??? +Cz: ??? +CPz: ??? +Pz: ??? +POz: ??? +FC1: ??? +FC2: ??? +CP1: ??? +CP2: ??? +FC5: ??? +FC6: ??? +CP5: ??? +CP6: ??? +HL: ??? +HR: ??? +Vb: ??? +ReRef: ??? +Ref: 0 +Gnd: 4 diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_highpass_hz.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_highpass_hz.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..6315b446fbf9ac864d55796e3c2bab5f51381914 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_highpass_hz.vhdr @@ -0,0 +1,103 @@ +Brain Vision Data Exchange Header File Version 1.0 +; Data created by the Vision Recorder + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=test.vmrk +DataFormat=BINARY +; Data orientation: MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +NumberOfChannels=32 +; Sampling interval in microseconds +SamplingInterval=1000 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5,µV +Ch3=F3,,0.5,µV +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,µV +Ch28=CP6,,0.5,µV +Ch29=HL,,0.5,µV +Ch30=HR,,0.5,µV +Ch31=Vb,,0.5,µV +Ch32=ReRef,,0.5,µV + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [Hz] High Cutoff [Hz] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 0.5 µV 10 250 Off 0 +2 FP2 2 0.5 µV 10 250 Off 0 +3 F3 3 0.5 µV 10 250 Off 0 +4 F4 4 0.5 µV 10 250 Off 0 +5 C3 5 0.5 µV 10 250 Off 0 +6 C4 6 0.5 µV 10 250 Off 0 +7 P3 7 0.5 µV 10 250 Off 0 +8 P4 8 0.5 µV 10 250 Off 0 +9 O1 9 0.5 µV 10 250 Off 0 +10 O2 10 0.5 µV 10 250 Off 0 +11 F7 11 0.5 µV 10 250 Off 0 +12 F8 12 0.5 µV 10 250 Off 0 +13 P7 13 0.5 µV 10 250 Off 0 +14 P8 14 0.5 µV 10 250 Off 0 +15 Fz 15 0.5 µV 10 250 Off 0 +16 FCz 16 0.5 µV 10 250 Off 0 +17 Cz 17 0.5 µV 10 250 Off 0 +18 CPz 18 0.5 µV 10 250 Off 0 +19 Pz 19 0.5 µV 10 250 Off 0 +20 POz 20 0.5 µV 10 250 Off 0 +21 FC1 21 0.5 µV 10 250 Off 0 +22 FC2 22 0.5 µV 10 250 Off 0 +23 CP1 23 0.5 µV 10 250 Off 0 +24 CP2 24 0.5 µV 10 250 Off 0 +25 FC5 25 0.5 µV 10 250 Off 0 +26 FC6 26 0.5 µV 10 250 Off 0 +27 CP5 27 0.5 µV 10 250 Off 0 +28 CP6 28 0.5 µV 10 250 Off 0 +29 HL 29 0.5 µV 10 250 Off 0 +30 HR 30 0.5 µV 10 250 Off 0 +31 Vb 31 0.5 µV 10 250 Off 0 +32 ReRef 32 0.5 µV 10 250 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_lowpass_s.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_lowpass_s.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..483e2903b127f710a919ddfb0e7581d86c2911c7 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_lowpass_s.vhdr @@ -0,0 +1,103 @@ +Brain Vision Data Exchange Header File Version 1.0 +; Data created by the Vision Recorder + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=test.vmrk +DataFormat=BINARY +; Data orientation: MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +NumberOfChannels=32 +; Sampling interval in microseconds +SamplingInterval=1000 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5,µV +Ch3=F3,,0.5,µV +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,µV +Ch28=CP6,,0.5,µV +Ch29=HL,,0.5,µV +Ch30=HR,,0.5,µV +Ch31=Vb,,0.5,µV +Ch32=ReRef,,0.5,µV + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [s] High Cutoff [s] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 0.5 µV 10 0.004 Off 0 +2 FP2 2 0.5 µV 10 0.004 Off 0 +3 F3 3 0.5 µV 10 0.004 Off 0 +4 F4 4 0.5 µV 10 0.004 Off 0 +5 C3 5 0.5 µV 10 0.004 Off 0 +6 C4 6 0.5 µV 10 0.004 Off 0 +7 P3 7 0.5 µV 10 0.004 Off 0 +8 P4 8 0.5 µV 10 0.004 Off 0 +9 O1 9 0.5 µV 10 0.004 Off 0 +10 O2 10 0.5 µV 10 0.004 Off 0 +11 F7 11 0.5 µV 10 0.004 Off 0 +12 F8 12 0.5 µV 10 0.004 Off 0 +13 P7 13 0.5 µV 10 0.004 Off 0 +14 P8 14 0.5 µV 10 0.004 Off 0 +15 Fz 15 0.5 µV 10 0.004 Off 0 +16 FCz 16 0.5 µV 10 0.004 Off 0 +17 Cz 17 0.5 µV 10 0.004 Off 0 +18 CPz 18 0.5 µV 10 0.004 Off 0 +19 Pz 19 0.5 µV 10 0.004 Off 0 +20 POz 20 0.5 µV 10 0.004 Off 0 +21 FC1 21 0.5 µV 10 0.004 Off 0 +22 FC2 22 0.5 µV 10 0.004 Off 0 +23 CP1 23 0.5 µV 10 0.004 Off 0 +24 CP2 24 0.5 µV 10 0.004 Off 0 +25 FC5 25 0.5 µV 10 0.004 Off 0 +26 FC6 26 0.5 µV 10 0.004 Off 0 +27 CP5 27 0.5 µV 10 0.004 Off 0 +28 CP6 28 0.5 µV 10 0.004 Off 0 +29 HL 29 0.5 µV 10 0.004 Off 0 +30 HR 30 0.5 µV 10 0.004 Off 0 +31 Vb 31 0.5 µV 10 0.004 Off 0 +32 ReRef 32 0.5 µV 10 0.004 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_mixed_highpass.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_mixed_highpass.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..b9c175c074c907a753f9d2e8d25e41acb8d10505 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_mixed_highpass.vhdr @@ -0,0 +1,103 @@ +Brain Vision Data Exchange Header File Version 1.0 +; Data created by the Vision Recorder + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=test.vmrk +DataFormat=BINARY +; Data orientation: MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +NumberOfChannels=32 +; Sampling interval in microseconds +SamplingInterval=1000 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5,µV +Ch3=F3,,0.5,µV +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,µV +Ch28=CP6,,0.5,µV +Ch29=HL,,0.5,µV +Ch30=HR,,0.5,µV +Ch31=Vb,,0.5,µV +Ch32=ReRef,,0.5,µV + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [s] High Cutoff [Hz] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 0.5 µV 10 250 Off 0 +2 FP2 2 0.5 µV 10 250 Off 0 +3 F3 3 0.5 µV 10 250 Off 0 +4 F4 4 0.5 µV 10 250 Off 0 +5 C3 5 0.5 µV 10 250 Off 0 +6 C4 6 0.5 µV 10 250 Off 0 +7 P3 7 0.5 µV 10 250 Off 0 +8 P4 8 0.5 µV 10 250 Off 0 +9 O1 9 0.5 µV 10 250 Off 0 +10 O2 10 0.5 µV 10 250 Off 0 +11 F7 11 0.5 µV 10 250 Off 0 +12 F8 12 0.5 µV 10 250 Off 0 +13 P7 13 0.5 µV 10 250 Off 0 +14 P8 14 0.5 µV 10 250 Off 0 +15 Fz 15 0.5 µV 10 250 Off 0 +16 FCz 16 0.5 µV 10 250 Off 0 +17 Cz 17 0.5 µV 10 250 Off 0 +18 CPz 18 0.5 µV 10 250 Off 0 +19 Pz 19 0.5 µV 10 250 Off 0 +20 POz 20 0.5 µV 10 250 Off 0 +21 FC1 21 0.5 µV 10 250 Off 0 +22 FC2 22 0.5 µV 10 250 Off 0 +23 CP1 23 0.5 µV 10 250 Off 0 +24 CP2 24 0.5 µV 10 250 Off 0 +25 FC5 25 0.5 µV 10 250 Off 0 +26 FC6 26 0.5 µV 10 250 Off 0 +27 CP5 27 0.5 µV 10 250 Off 0 +28 CP6 28 0.5 µV 10 250 Off 0 +29 HL 29 0.5 µV 10 250 Off 0 +30 HR 30 0.5 µV 10 250 Off 0 +31 Vb 31 0.5 µV 10 250 Off 0 +32 ReRef 32 0.5 µV 5 250 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_mixed_highpass_hz.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_mixed_highpass_hz.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..e1785853c3b53cc2c7e9d5b1b0b73ef9b66762b1 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_mixed_highpass_hz.vhdr @@ -0,0 +1,103 @@ +Brain Vision Data Exchange Header File Version 1.0 +; Data created by the Vision Recorder + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=test.vmrk +DataFormat=BINARY +; Data orientation: MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +NumberOfChannels=32 +; Sampling interval in microseconds +SamplingInterval=1000 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5,µV +Ch3=F3,,0.5,µV +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,µV +Ch28=CP6,,0.5,µV +Ch29=HL,,0.5,µV +Ch30=HR,,0.5,µV +Ch31=Vb,,0.5,µV +Ch32=ReRef,,0.5,µV + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [Hz] High Cutoff [Hz] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 0.5 µV 10 250 Off 0 +2 FP2 2 0.5 µV 10 250 Off 0 +3 F3 3 0.5 µV 10 250 Off 0 +4 F4 4 0.5 µV 10 250 Off 0 +5 C3 5 0.5 µV 10 250 Off 0 +6 C4 6 0.5 µV 10 250 Off 0 +7 P3 7 0.5 µV 10 250 Off 0 +8 P4 8 0.5 µV 10 250 Off 0 +9 O1 9 0.5 µV 10 250 Off 0 +10 O2 10 0.5 µV 10 250 Off 0 +11 F7 11 0.5 µV 10 250 Off 0 +12 F8 12 0.5 µV 10 250 Off 0 +13 P7 13 0.5 µV 10 250 Off 0 +14 P8 14 0.5 µV 10 250 Off 0 +15 Fz 15 0.5 µV 10 250 Off 0 +16 FCz 16 0.5 µV 10 250 Off 0 +17 Cz 17 0.5 µV 10 250 Off 0 +18 CPz 18 0.5 µV 10 250 Off 0 +19 Pz 19 0.5 µV 10 250 Off 0 +20 POz 20 0.5 µV 10 250 Off 0 +21 FC1 21 0.5 µV 10 250 Off 0 +22 FC2 22 0.5 µV 10 250 Off 0 +23 CP1 23 0.5 µV 10 250 Off 0 +24 CP2 24 0.5 µV 10 250 Off 0 +25 FC5 25 0.5 µV 10 250 Off 0 +26 FC6 26 0.5 µV 10 250 Off 0 +27 CP5 27 0.5 µV 10 250 Off 0 +28 CP6 28 0.5 µV 10 250 Off 0 +29 HL 29 0.5 µV 10 250 Off 0 +30 HR 30 0.5 µV 10 250 Off 0 +31 Vb 31 0.5 µV 10 250 Off 0 +32 ReRef 32 0.5 µV 5 250 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_mixed_lowpass.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_mixed_lowpass.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..cc7c86ca9b09f1802c99da65125854a4366a2bdb --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_mixed_lowpass.vhdr @@ -0,0 +1,146 @@ +Brain Vision Data Exchange Header File Version 1.0 +; Data created by the Vision Recorder + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=test.vmrk +DataFormat=BINARY +; Data orientation: MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +NumberOfChannels=32 +; Sampling interval in microseconds +SamplingInterval=1000 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5,µV +Ch3=F3,,0.5,µV +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,µV +Ch28=CP 6,,0.5,µV +Ch29=ECG,,0.5,µV +Ch30=HEOG,,0.5,µV +Ch31=VEOG,,0.5,µV +Ch32=ReRef,,0.5,µV + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [s] High Cutoff [Hz] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 0.5 µV 10 250 Off 0 +2 FP2 2 0.5 µV 10 250 Off 0 +3 F3 3 0.5 µV 10 250 Off 0 +4 F4 4 0.5 µV 10 250 Off 0 +5 C3 5 0.5 µV 10 250 Off 0 +6 C4 6 0.5 µV 10 250 Off 0 +7 P3 7 0.5 µV 10 250 Off 0 +8 P4 8 0.5 µV 10 250 Off 0 +9 O1 9 0.5 µV 10 250 Off 0 +10 O2 10 0.5 µV 10 250 Off 0 +11 F7 11 0.5 µV 10 250 Off 0 +12 F8 12 0.5 µV 10 250 Off 0 +13 P7 13 0.5 µV 10 250 Off 0 +14 P8 14 0.5 µV 10 250 Off 0 +15 Fz 15 0.5 µV 10 250 Off 0 +16 FCz 16 0.5 µV 10 250 Off 0 +17 Cz 17 0.5 µV 10 250 Off 0 +18 CPz 18 0.5 µV 10 250 Off 0 +19 Pz 19 0.5 µV 10 250 Off 0 +20 POz 20 0.5 µV 10 250 Off 0 +21 FC1 21 0.5 µV 10 250 Off 0 +22 FC2 22 0.5 µV 10 250 Off 0 +23 CP1 23 0.5 µV 10 250 Off 0 +24 CP2 24 0.5 µV 10 250 Off 0 +25 FC5 25 0.5 µV 10 250 Off 0 +26 FC6 26 0.5 µV 10 250 Off 0 +27 CP5 27 0.5 µV 10 250 Off 0 +28 CP 6 28 0.5 µV 10 250 Off 0 +29 ECG 29 0.5 µV 10 250 Off 0 +30 HEOG 30 0.5 µV 10 250 Off 0 +31 VEOG 31 0.5 µV 10 250 Off 0 +32 ReRef 32 0.5 µV 10 125 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + + + +Impedances Imported from actiCAP Control Software: +Impedance [kOhm] at 10:17:02 : +FP1: ??? +FP2: ??? +F3: ??? +F4: ??? +C3: ??? +C4: ??? +P3: ??? +P4: ??? +O1: ??? +O2: ??? +F7: ??? +F8: ??? +P7: ??? +P8: ??? +Fz: ??? +FCz: ??? +Cz: ??? +CPz: ??? +Pz: ??? +POz: ??? +FC1: ??? +FC2: ??? +CP1: ??? +CP2: ??? +FC5: ??? +FC6: ??? +CP5: ??? +CP 6: ??? +ECG+: 35 +ECG-: 46 +HEOG+: 6 +HEOG-: 8 +VEOG+: 3 +VEOG-: 4 +ReRef: 0 +Ref: 8 +Gnd: 2.5 + +; this is a comment diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_mixed_lowpass_s.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_mixed_lowpass_s.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..41ddcad312d1f4859874fc43f901ea4ab78a298f --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_mixed_lowpass_s.vhdr @@ -0,0 +1,103 @@ +Brain Vision Data Exchange Header File Version 1.0 +; Data created by the Vision Recorder + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=test.vmrk +DataFormat=BINARY +; Data orientation: MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +NumberOfChannels=32 +; Sampling interval in microseconds +SamplingInterval=1000 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5,µV +Ch3=F3,,0.5,µV +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,µV +Ch28=CP6,,0.5,µV +Ch29=HL,,0.5,µV +Ch30=HR,,0.5,µV +Ch31=Vb,,0.5,µV +Ch32=ReRef,,0.5,µV + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [s] High Cutoff [s] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 0.5 µV 10 0.004 Off 0 +2 FP2 2 0.5 µV 10 0.004 Off 0 +3 F3 3 0.5 µV 10 0.004 Off 0 +4 F4 4 0.5 µV 10 0.004 Off 0 +5 C3 5 0.5 µV 10 0.004 Off 0 +6 C4 6 0.5 µV 10 0.004 Off 0 +7 P3 7 0.5 µV 10 0.004 Off 0 +8 P4 8 0.5 µV 10 0.004 Off 0 +9 O1 9 0.5 µV 10 0.004 Off 0 +10 O2 10 0.5 µV 10 0.004 Off 0 +11 F7 11 0.5 µV 10 0.004 Off 0 +12 F8 12 0.5 µV 10 0.004 Off 0 +13 P7 13 0.5 µV 10 0.004 Off 0 +14 P8 14 0.5 µV 10 0.004 Off 0 +15 Fz 15 0.5 µV 10 0.004 Off 0 +16 FCz 16 0.5 µV 10 0.004 Off 0 +17 Cz 17 0.5 µV 10 0.004 Off 0 +18 CPz 18 0.5 µV 10 0.004 Off 0 +19 Pz 19 0.5 µV 10 0.004 Off 0 +20 POz 20 0.5 µV 10 0.004 Off 0 +21 FC1 21 0.5 µV 10 0.004 Off 0 +22 FC2 22 0.5 µV 10 0.004 Off 0 +23 CP1 23 0.5 µV 10 0.004 Off 0 +24 CP2 24 0.5 µV 10 0.004 Off 0 +25 FC5 25 0.5 µV 10 0.004 Off 0 +26 FC6 26 0.5 µV 10 0.004 Off 0 +27 CP5 27 0.5 µV 10 0.004 Off 0 +28 CP6 28 0.5 µV 10 0.004 Off 0 +29 HL 29 0.5 µV 10 0.004 Off 0 +30 HR 30 0.5 µV 10 0.004 Off 0 +31 Vb 31 0.5 µV 10 0.004 Off 0 +32 ReRef 32 0.5 µV 10 0.008 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.eeg b/mne-python/source/mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.eeg new file mode 100644 index 0000000000000000000000000000000000000000..b1b37102937c19d9a03997f6f05834cbe0fefb91 Binary files /dev/null and b/mne-python/source/mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.eeg differ diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..cdb837f5d61f4dc15acdcbee1278a0df68bfa82e --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter.vhdr @@ -0,0 +1,156 @@ +Brain Vision Data Exchange Header File Version 1.0 +; Data created by the Vision Recorder and modified by hand + +[Common Infos] +DataFile=test_old_layout_latin1_software_filter.eeg +MarkerFile=test_old_layout_latin1_software_filter.vmrk +DataFormat=BINARY +; Data orientation: VECTORIZED=ch1,pt1, ch1,pt2...,MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=VECTORIZED +NumberOfChannels=29 +; Sampling interval in microseconds +SamplingInterval=4000 + +[Binary Infos] +BinaryFormat=IEEE_FLOAT_32 + +[Channel Infos] +; Each entry: Ch=,, +; ,=,,, +; , , +; +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in type or description text are coded as "". +Mk1=New Segment,,1,1,0,20070716122240937454 +Mk2=New Segment,,2,1,0,20070716122240937455 diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter_longname.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter_longname.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..003bebf29537e8236276cd64d7901696d584397d --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_old_layout_latin1_software_filter_longname.vhdr @@ -0,0 +1,156 @@ +Brain Vision Data Exchange Header File Version 1.0 +; copy of test_old_layout_latin1_software_filter.vhdr, sensor F3 manually renamed for name with spaces + +[Common Infos] +DataFile=test_old_layout_latin1_software_filter.eeg +MarkerFile=test_old_layout_latin1_software_filter.vmrk +DataFormat=BINARY +; Data orientation: VECTORIZED=ch1,pt1, ch1,pt2...,MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=VECTORIZED +NumberOfChannels=29 +; Sampling interval in microseconds +SamplingInterval=4000 + +[Binary Infos] +BinaryFormat=IEEE_FLOAT_32 + +[Channel Infos] +; Each entry: Ch=,, +; ,=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5,µV +Ch3=F3,,0.5,µV +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,BS +Ch28=CP6,,0.5,µS +Ch29=HL,,0.5,ARU +Ch30=HR,,0.5,uS +Ch31=Vb,,0.5,S +Ch32=ReRef,,0.5,C + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [s] High Cutoff [Hz] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 0.5 µV DC 250 Off 0 +2 FP2 2 0.5 µV DC 250 Off 0 +3 F3 3 0.5 µV DC 250 Off 0 +4 F4 4 0.5 µV DC 250 Off 0 +5 C3 5 0.5 µV DC 250 Off 0 +6 C4 6 0.5 µV DC 250 Off 0 +7 P3 7 0.5 µV DC 250 Off 0 +8 P4 8 0.5 µV DC 250 Off 0 +9 O1 9 0.5 µV DC 250 Off 0 +10 O2 10 0.5 µV DC 250 Off 0 +11 F7 11 0.5 µV DC 250 Off 0 +12 F8 12 0.5 µV DC 250 Off 0 +13 P7 13 0.5 µV DC 250 Off 0 +14 P8 14 0.5 µV DC 250 Off 0 +15 Fz 15 0.5 µV DC 250 Off 0 +16 FCz 16 0.5 µV DC 250 Off 0 +17 Cz 17 0.5 µV DC 250 Off 0 +18 CPz 18 0.5 µV DC 250 Off 0 +19 Pz 19 0.5 µV DC 250 Off 0 +20 POz 20 0.5 µV DC 250 Off 0 +21 FC1 21 0.5 µV DC 250 Off 0 +22 FC2 22 0.5 µV DC 250 Off 0 +23 CP1 23 0.5 µV DC 250 Off 0 +24 CP2 24 0.5 µV DC 250 Off 0 +25 FC5 25 0.5 µV DC 250 Off 0 +26 FC6 26 0.5 µV DC 250 Off 0 +27 CP5 27 0.5 BS DC 250 Off 0 +28 CP6 28 0.5 µS DC 250 Off 0 +29 HL 29 0.5 ARU DC 250 Off 0 +30 HR 30 0.5 uS DC Off Off 0 +31 Vb 31 0.5 S Off 250 Off 0 +32 ReRef 32 0.5 C 10 250 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + diff --git a/mne-python/source/mne/io/brainvision/tests/data/test_units.vhdr b/mne-python/source/mne/io/brainvision/tests/data/test_units.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..f13f8ef99427fa374f3958a0650f04be0e960ebb --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/test_units.vhdr @@ -0,0 +1,151 @@ +Brain Vision Data Exchange Header File Version 2.0 +; Data created from history path + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=test.vmrk +DataFormat=BINARY +; Data orientation: VECTORIZED=ch1,pt1, ch1,pt2..., MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +DataType=TIMEDOMAIN +NumberOfChannels=32 +; Sampling interval in microseconds if time domain (convert to Hertz: +; 1000000 / SamplingInterval) or in Hertz if frequency domain: +SamplingInterval=1000 + +[User Infos] +; Each entry: Prop=,,,,..., +; Property number must be unique. Types can be int, single, string, bool, byte, double, uint +; or arrays of those, indicated int-array etc +; Array types have more than one value, number of values determines size of array. +; Fields are delimited by commas, commas in strings are written \1 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions... +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,500,nV +Ch2=FP2,,0.0005,mV +Ch3=F3,,0.0000005,V +Ch4=F4,,0.5,uV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,BS +Ch28=CP6,,0.5,µS +Ch29=HL,,0.5,ARU +Ch30=HR,,0.5,uS +Ch31=Vb,,0.5,S +Ch32=ReRef,,0.5,C + +[Comment] + +A m p l i f i e r S e t u p +============================ +Number of channels: 32 +Sampling Rate [Hz]: 1000 +Sampling Interval [µS]: 1000 + +Channels +-------- +# Name Phys. Chn. Resolution / Unit Low Cutoff [s] High Cutoff [Hz] Notch [Hz] Series Res. [kOhm] Gradient Offset +1 FP1 1 500 nV DC 250 Off 0 +2 FP2 2 0.5 µV DC 250 Off 0 +3 F3 3 0.5 µV DC 250 Off 0 +4 F4 4 0.5 µV DC 250 Off 0 +5 C3 5 0.5 µV DC 250 Off 0 +6 C4 6 0.5 µV DC 250 Off 0 +7 P3 7 0.5 µV DC 250 Off 0 +8 P4 8 0.5 µV DC 250 Off 0 +9 O1 9 0.5 µV DC 250 Off 0 +10 O2 10 0.5 µV DC 250 Off 0 +11 F7 11 0.5 µV DC 250 Off 0 +12 F8 12 0.5 µV DC 250 Off 0 +13 P7 13 0.5 µV DC 250 Off 0 +14 P8 14 0.5 µV DC 250 Off 0 +15 Fz 15 0.5 µV DC 250 Off 0 +16 FCz 16 0.5 µV DC 250 Off 0 +17 Cz 17 0.5 µV DC 250 Off 0 +18 CPz 18 0.5 µV DC 250 Off 0 +19 Pz 19 0.5 µV DC 250 Off 0 +20 POz 20 0.5 µV DC 250 Off 0 +21 FC1 21 0.5 µV DC 250 Off 0 +22 FC2 22 0.5 µV DC 250 Off 0 +23 CP1 23 0.5 µV DC 250 Off 0 +24 CP2 24 0.5 µV DC 250 Off 0 +25 FC5 25 0.5 µV DC 250 Off 0 +26 FC6 26 0.5 µV DC 250 Off 0 +27 CP5 27 0.5 BS DC 250 Off 0 +28 CP6 28 0.5 µS DC 250 Off 0 +29 HL 29 0.5 ARU DC 250 Off 0 +30 HR 30 0.5 uS DC 250 Off 0 +31 Vb 31 0.5 S DC 250 Off 0 +32 ReRef 32 0.5 C DC 250 Off 0 + +S o f t w a r e F i l t e r s +============================== +Disabled + + +Data Electrodes Selected Impedance Measurement Range: 0 - 100 kOhm +Ground Electrode Selected Impedance Measurement Range: 0 - 10 kOhm +Reference Electrode Selected Impedance Measurement Range: 0 - 10 kOhm +Impedance [kOhm] at 16:12:27 : +FP1: ??? +FP2: ??? +F3: ??? +F4: ??? +C3: ??? +C4: ??? +P3: ??? +P4: ??? +O1: ??? +O2: ??? +F7: ??? +F8: ??? +P7: ??? +P8: ??? +Fz: ??? +FCz: ??? +Cz: ??? +CPz: ??? +Pz: ??? +POz: ??? +FC1: ??? +FC2: ??? +CP1: ??? +CP2: ??? +FC5: ??? +FC6: ??? +CP5: ??? +CP6: ??? +HL: ??? +HR: ??? +Vb: ??? +ReRef: ??? +Ref: 0 +Gnd: 4 diff --git a/mne-python/source/mne/io/brainvision/tests/data/testv2.vhdr b/mne-python/source/mne/io/brainvision/tests/data/testv2.vhdr new file mode 100644 index 0000000000000000000000000000000000000000..7773b839044d4f5ab75bd8b580b049e1e5d6592e --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/testv2.vhdr @@ -0,0 +1,107 @@ +Brain Vision Data Exchange Header File Version 2.0 +; Data created from history path: test/Raw Data + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg +MarkerFile=testv2.vmrk +DataFormat=BINARY +; Data orientation: VECTORIZED=ch1,pt1, ch1,pt2..., MULTIPLEXED=ch1,pt1, ch2,pt1 ... +DataOrientation=MULTIPLEXED +DataType=TIMEDOMAIN +NumberOfChannels=32 +DataPoints=7900 +; Sampling interval in microseconds if time domain (convert to Hertz: +; 1000000 / SamplingInterval) or in Hertz if frequency domain: +SamplingInterval=1000 + +[User Infos] +; Each entry: Prop=,,,,..., +; Property number must be unique. Types can be int, single, string, bool, byte, double, uint +; or arrays of those, indicated int-array etc +; Array types have more than one value, number of values determines size of array. +; Fields are delimited by commas, commas in strings are written \1 + +[Binary Infos] +BinaryFormat=INT_16 + +[Channel Infos] +; Each entry: Ch=,, +; ,, Future extensions.. +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in channel names are coded as "\1". +Ch1=FP1,,0.5,µV +Ch2=FP2,,0.5,µV +Ch3=F3,,0.5,µV +Ch4=F4,,0.5,µV +Ch5=C3,,0.5,µV +Ch6=C4,,0.5,µV +Ch7=P3,,0.5,µV +Ch8=P4,,0.5,µV +Ch9=O1,,0.5,µV +Ch10=O2,,0.5,µV +Ch11=F7,,0.5,µV +Ch12=F8,,0.5,µV +Ch13=P7,,0.5,µV +Ch14=P8,,0.5,µV +Ch15=Fz,,0.5,µV +Ch16=FCz,,0.5,µV +Ch17=Cz,,0.5,µV +Ch18=CPz,,0.5,µV +Ch19=Pz,,0.5,µV +Ch20=POz,,0.5,µV +Ch21=FC1,,0.5,µV +Ch22=FC2,,0.5,µV +Ch23=CP1,,0.5,µV +Ch24=CP2,,0.5,µV +Ch25=FC5,,0.5,µV +Ch26=FC6,,0.5,µV +Ch27=CP5,,0.5,µV +Ch28=CP6,,0.5,µV +Ch29=HL,,0.5,µV +Ch30=HR,,0.5,µV +Ch31=Vb,,0.5,µV +Ch32=ReRef,,0.5,µV + +[Channel User Infos] +; Each entry: Prop=Ch,,,,,..., +; Property number must be unique. Types can be int, single, string, bool, byte, double, uint +; or arrays of those, indicated int-array etc +; Array types have more than one value, number of values determines size of array. +; Fields are delimited by commas, commas in strings are written \1 +; Properties are assigned to channels using their channel number. + +[Coordinates] +; Each entry: Ch=,, +Ch1=1,-90,-72 +Ch2=1,90,72 +Ch3=1,-60,-51 +Ch4=1,60,51 +Ch5=1,-45,0 +Ch6=1,45,0 +Ch7=1,-60,51 +Ch8=1,60,-51 +Ch9=1,-90,72 +Ch10=1,90,-72 +Ch11=1,-90,-36 +Ch12=1,90,36 +Ch13=1,-90,36 +Ch14=1,90,-36 +Ch15=1,45,90 +Ch16=1,22,90 +Ch17=1,0,0 +Ch18=1,22,-90 +Ch19=1,45,-90 +Ch20=1,67,-90 +Ch21=1,-31,-46 +Ch22=1,31,46 +Ch23=1,-31,46 +Ch24=1,31,-46 +Ch25=1,-69,-21 +Ch26=1,69,21 +Ch27=1,-69,21 +Ch28=1,69,-21 +Ch29=0,0,0 +Ch30=0,0,0 +Ch31=0,0,0 +Ch32=0,0,0 diff --git a/mne-python/source/mne/io/brainvision/tests/data/testv2.vmrk b/mne-python/source/mne/io/brainvision/tests/data/testv2.vmrk new file mode 100644 index 0000000000000000000000000000000000000000..4eee8eab9beb7bc3d82a7db135ef3c086351bfc7 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/data/testv2.vmrk @@ -0,0 +1,45 @@ +Brain Vision Data Exchange Marker File, Version 2.0 +; Data created from history path: test/Raw Data +; The channel numbers are related to the channels in the exported file. + +[Common Infos] +Codepage=UTF-8 +DataFile=test.eeg + +[Marker Infos] +; Each entry: Mk=,,, +; , +; Fields are delimited by commas, some fields might be omitted (empty). +; Commas in type or description text are coded as "\1". +Mk1=New Segment,,1,1,0 +Mk2=Stimulus,S253,487,1,0 +Mk3=Stimulus,S255,497,1,0 +Mk4=Stimulus,S254,1770,1,0 +Mk5=Stimulus,S255,1780,1,0 +Mk6=Stimulus,S254,3253,1,0 +Mk7=Comment,comment using [square] brackets,3254,1,0 +Mk8=Stimulus,S255,3263,1,0 +Mk9=Stimulus,S253,4936,1,0 +Mk10=Stimulus,S255,4946,1,0 +Mk11=Response,R255,6000,1,0 + +;Removing the prefix makes the marker "PyCorder" style +;The removal of the prefix should not change the parsing +Mk12=Stimulus,254,6620,1,0 +Mk13=Stimulus,255,6630,1,0 + +;Do not parse by default if not in shape '###' + optional single char prefix +Mk14=Comment,This will not be parsed by default 13,8010,1,0 +Mk15=Comment,Not parsed by default either S456 ms,8020,1,0 + +;Certain prefixes are blacklisted by BrainVision recorder: [^a-z$%\-@/\\|;,:.\s] +;Will not be parsed by default +Mk16=$User_Spec,$ 18,8030,1,0 + +[Marker User Infos] +; Each entry: Prop=Mk,,,,,..., +; Property number must be unique. Types can be int, single, string, bool, byte, double, uint +; or arrays of those, indicated int-array etc +; Array types have more than one value, number of values determines size of array. +; Fields are delimited by commas, commas in strings are written \1 +; Properties are assigned to markers using their marker number. diff --git a/mne-python/source/mne/io/brainvision/tests/test_brainvision.py b/mne-python/source/mne/io/brainvision/tests/test_brainvision.py new file mode 100644 index 0000000000000000000000000000000000000000..8366f15dc3a38569912e74426e5b96e0f5019132 --- /dev/null +++ b/mne-python/source/mne/io/brainvision/tests/test_brainvision.py @@ -0,0 +1,967 @@ +"""Test reading of BrainVision format.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime +import re +import shutil +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_equal + +from mne import concatenate_raws, pick_types, read_annotations +from mne._fiff.constants import FIFF +from mne.annotations import events_from_annotations +from mne.datasets import testing +from mne.io import read_raw_brainvision, read_raw_fif +from mne.io.tests.test_raw import _test_raw_reader +from mne.utils import _record_warnings, _stamp_to_dt, object_diff + +data_dir = Path(__file__).parent / "data" +vhdr_path = data_dir / "test.vhdr" +vmrk_path = data_dir / "test.vmrk" +eeg_path = data_dir / "test.eeg" + +vhdr_partially_disabled_hw_filter_path = ( + data_dir / "test_partially_disabled_hw_filter.vhdr" +) + +vhdr_old_path = data_dir / "test_old_layout_latin1_software_filter.vhdr" +vhdr_old_longname_path = ( + data_dir / "test_old_layout_latin1_software_filter_longname.vhdr" +) +vhdr_v2_path = data_dir / "testv2.vhdr" + +vhdr_highpass_path = data_dir / "test_highpass.vhdr" +vhdr_mixed_highpass_path = data_dir / "test_mixed_highpass.vhdr" +vhdr_highpass_hz_path = data_dir / "test_highpass_hz.vhdr" +vhdr_mixed_highpass_hz_path = data_dir / "test_mixed_highpass_hz.vhdr" + +# Not a typo: we can reuse the highpass file for the lowpass (Hz) test +vhdr_lowpass_path = data_dir / "test_highpass.vhdr" +vhdr_mixed_lowpass_path = data_dir / "test_mixed_lowpass.vhdr" +vhdr_lowpass_s_path = data_dir / "test_lowpass_s.vhdr" +vhdr_mixed_lowpass_s_path = data_dir / "test_mixed_lowpass_s.vhdr" + +# VHDR exported with neuroone +data_path = testing.data_path(download=False) +neuroone_vhdr = data_path / "Brainvision" / "test_NO.vhdr" + +# AHDR exported with VAmp +data_path = testing.data_path(download=False) +vamp_ahdr = data_path / "Brainvision" / "test_VAmp.ahdr" + +# Test for nanovolts as unit +vhdr_units_path = data_dir / "test_units.vhdr" + +eeg_bin = data_dir / "test_bin_raw.fif" +eog = ["HL", "HR", "Vb"] + +# XXX: BUG we cannot parse test.hpts FastSCAN file to create a DigMontage +# (plus I've removed montage from all the read_raw_brainvision and nothing +# broke, so we were not testing that set_montage in brainvision was +# working) +# This should be amend in its own PR. +montage = data_dir / "test.hpts" + +_no_dig = pytest.warns(RuntimeWarning, match="No info on DataPoints") + + +def test_orig_units(recwarn): + """Test exposure of original channel units.""" + raw = read_raw_brainvision(vhdr_path) + orig_units = raw._orig_units + assert len(orig_units) == 32 + assert orig_units["FP1"] == "µV" + + # no unit specified in the vhdr, ensure we default to µV here + assert orig_units["FP2"] == "µV" + assert orig_units["F3"] == "µV" + + sum([v == "µV" for v in orig_units.values()]) == 26 + + assert orig_units["CP5"] == "n/a" # originally BS, not a valid unit + assert orig_units["CP6"] == "µS" + assert orig_units["HL"] == "n/a" # originally ARU, not a valid unit + assert orig_units["HR"] == "n/a" # originally uS ... + assert orig_units["Vb"] == "S" + assert orig_units["ReRef"] == "C" + + +DATE_TEST_CASES = np.array( + [ + ( + "Mk1=New Segment,,1,1,0,20131113161403794232\n", # content + [1384359243, 794232], # meas_date internal representation + "2013-11-13 16:14:03 UTC", + ), # meas_date representation + ( + ( + "Mk1=New Segment,,1,1,0,20070716122240937454\n" + "Mk2=New Segment,,2,1,0,20070716122240937455\n" + ), + [1184588560, 937454], + "2007-07-16 12:22:40 UTC", + ), + ( + "Mk1=New Segment,,1,1,0,\nMk2=New Segment,,2,1,0,20070716122240937454\n", + [1184588560, 937454], + "2007-07-16 12:22:40 UTC", + ), + ("Mk1=STATUS,,1,1,0\n", None, "unspecified"), + ("Mk1=New Segment,,1,1,0,\n", None, "unspecified"), + ("Mk1=New Segment,,1,1,0\n", None, "unspecified"), + ("Mk1=New Segment,,1,1,0,00000000000304125000", None, "unspecified"), + ], + dtype=np.dtype( + { + "names": ["content", "meas_date", "meas_date_repr"], + "formats": [object, object, "U22"], + } + ), +) + + +@pytest.fixture(scope="session") +def _mocked_meas_date_data(tmp_path_factory): + """Prepare files for mocked_meas_date_file fixture.""" + # Prepare the files + tmp_path = tmp_path_factory.mktemp("brainvision_mocked_meas_date") + vhdr_fname, vmrk_fname, eeg_fname = ( + tmp_path / ff.name for ff in [vhdr_path, vmrk_path, eeg_path] + ) + for orig, dest in zip([vhdr_path, eeg_path], [vhdr_fname, eeg_fname]): + shutil.copyfile(orig, dest) + + # Get the marker information + with open(vmrk_path) as fin: + lines = fin.readlines() + + return vhdr_fname, vmrk_fname, lines + + +@pytest.fixture(scope="session", params=[tt for tt in DATE_TEST_CASES]) +def mocked_meas_date_file(_mocked_meas_date_data, request): + """Prepare a generator for use in test_meas_date.""" + MEAS_DATE_LINE = 11 # see test.vmrk file + vhdr_fname, vmrk_fname, lines = _mocked_meas_date_data + + lines[MEAS_DATE_LINE] = request.param["content"] + with open(vmrk_fname, "w") as fout: + fout.writelines(lines) + meas_date = request.param["meas_date"] + if meas_date is not None: + meas_date = _stamp_to_dt(meas_date) + + yield vhdr_fname, meas_date, request.param["meas_date_repr"] + + +def test_meas_date(mocked_meas_date_file): + """Test successful extraction of measurement date.""" + vhdr_f, expected_meas, expected_meas_repr = mocked_meas_date_file + raw = read_raw_brainvision(vhdr_f) + assert expected_meas_repr in repr(raw.info) + if expected_meas is None: + assert raw.info["meas_date"] is None + else: + assert raw.info["meas_date"] == expected_meas + + +def test_vhdr_codepage_ansi(tmp_path): + """Test BV reading with ANSI codepage.""" + raw_init = read_raw_brainvision(vhdr_path) + data_expected, times_expected = raw_init[:] + ansi_vhdr_path = tmp_path / vhdr_path.name + ansi_vmrk_path = tmp_path / vmrk_path.name + ansi_eeg_path = tmp_path / eeg_path.name + # copy data file + shutil.copy(eeg_path, ansi_eeg_path) + # modify header file + with open(ansi_vhdr_path, "wb") as fout: + with open(vhdr_path, "rb") as fin: + for line in fin: + # Common Infos section + if line.startswith(b"Codepage"): + line = b"Codepage=ANSI\n" + fout.write(line) + # modify marker file + with open(ansi_vmrk_path, "wb") as fout: + with open(vmrk_path, "rb") as fin: + for line in fin: + # Common Infos section + if line.startswith(b"Codepage"): + line = b"Codepage=ANSI\n" + fout.write(line) + + raw = read_raw_brainvision(ansi_vhdr_path) + data_new, times_new = raw[:] + + assert raw_init.ch_names == raw.ch_names + assert_allclose(data_new, data_expected, atol=1e-15) + assert_allclose(times_new, times_expected, atol=1e-15) + + +@pytest.mark.parametrize( + "header", + [ + b"BrainVision Data Exchange %s File Version 1.0\n", + # 2.0, space, core, comma + b"Brain Vision Core Data Exchange %s File, Version 2.0\n", + # unsupported version + b"Brain Vision Core Data Exchange %s File, Version 3.0\n", + # missing header + b"\n", + ], +) +def test_vhdr_versions(tmp_path, header): + """Test BV reading with different header variants.""" + raw_init = read_raw_brainvision(vhdr_path) + data_expected, times_expected = raw_init[:] + use_vhdr_path = tmp_path / vhdr_path.name + use_vmrk_path = tmp_path / vmrk_path.name + use_eeg_path = tmp_path / eeg_path.name + shutil.copy(eeg_path, use_eeg_path) + with open(use_vhdr_path, "wb") as fout: + with open(vhdr_path, "rb") as fin: + for line in fin: + # Common Infos section + if line.startswith(b"Brain"): + if header != b"\n": + line = header % b"Header" + else: + line = header + fout.write(line) + with open(use_vmrk_path, "wb") as fout: + with open(vmrk_path, "rb") as fin: + for line in fin: + # Common Infos section + if line.startswith(b"Brain"): + if header != b"\n": + line = header % b"Marker" + else: + line = header + fout.write(line) + + if b"3.0" in header: # unsupported version + with pytest.warns(RuntimeWarning, match=r"3\.0.*Contact MNE-Python"): + read_raw_brainvision(use_vhdr_path) + return + elif header == b"\n": # no version header + with pytest.warns(RuntimeWarning, match="Missing header"): + read_raw_brainvision(use_vhdr_path) + return + else: + raw = read_raw_brainvision(use_vhdr_path) + data_new, _ = raw[:] + assert_allclose(data_new, data_expected, atol=1e-15) + + +@pytest.mark.parametrize("data_sep", (b" ", b",", b"+")) +def test_ascii(tmp_path, data_sep): + """Test ASCII BV reading.""" + raw = read_raw_brainvision(vhdr_path) + ascii_vhdr_path = tmp_path / vhdr_path.name + # copy marker file + shutil.copy( + vhdr_path.with_suffix(".vmrk"), + ascii_vhdr_path.with_suffix(".vmrk"), + ) + # modify header file + skipping = False + with open(ascii_vhdr_path, "wb") as fout: + with open(vhdr_path, "rb") as fin: + for line in fin: + # Common Infos section + if line.startswith(b"DataFormat"): + line = b"DataFormat=ASCII\n" + elif line.startswith(b"DataFile="): + line = b"DataFile=test.dat\n" + # Replace the "'Binary Infos'" section + elif line.startswith(b"[Binary Infos]"): + skipping = True + fout.write( + b"[ASCII Infos]\nDecimalSymbol=.\nSkipLines=1\n" + b"SkipColumns=0\n\n" + ) + elif skipping and line.startswith(b"["): + skipping = False + if not skipping: + fout.write(line) + # create the .dat file + data, times = raw[:] + with open(ascii_vhdr_path.with_suffix(".dat"), "wb") as fid: + fid.write( + data_sep.join(ch_name.encode("ASCII") for ch_name in raw.ch_names) + b"\n" + ) + fid.write( + b"\n".join(b" ".join(b"%.3f" % dd for dd in d) for d in data.T / raw._cals) + ) + + if data_sep == b";": + with pytest.raises(RuntimeError, match="Unknown.*data format"): + read_raw_brainvision(ascii_vhdr_path) + return + + raw = read_raw_brainvision(ascii_vhdr_path) + assert isinstance(raw.orig_format, str) + data_new, times_new = raw[:] + assert_allclose(data_new, data, atol=1e-15) + assert_allclose(times_new, times) + + +def test_ch_names_comma(tmp_path): + """Test that channel names containing commas are properly read.""" + # commas in BV are encoded as \1 + replace_dict = { + r"^Ch4=F4,": r"Ch4=F4\\1foo,", + r"^4\s\s\s\s\sF4": "4 F4,foo ", + } + + # Copy existing vhdr file to tmp_path and manipulate to contain + # a channel with comma + for src, dest in zip( + (vhdr_path, vmrk_path, eeg_path), ("test.vhdr", "test.vmrk", "test.eeg") + ): + shutil.copyfile(src, tmp_path / dest) + + comma_vhdr = tmp_path / "test.vhdr" + with open(comma_vhdr) as fin: + lines = fin.readlines() + + new_lines = [] + nperformed_replacements = 0 + for line in lines: + for to_replace, replacement in replace_dict.items(): + match = re.search(to_replace, line) + if match is not None: + new = re.sub(to_replace, replacement, line) + new_lines.append(new) + nperformed_replacements += 1 + break + else: + new_lines.append(line) + assert nperformed_replacements == len(replace_dict) + + with open(comma_vhdr, "w") as fout: + fout.writelines(new_lines) + + # Read the line containing a "comma channel name" + raw = read_raw_brainvision(comma_vhdr) + assert "F4,foo" in raw.ch_names + + +@pytest.mark.filterwarnings("ignore:.*different.*:RuntimeWarning") +def test_brainvision_data_highpass_filters(): + """Test reading raw Brain Vision files with amplifier filter settings.""" + # Homogeneous highpass in seconds (default measurement unit) + raw = _test_raw_reader(read_raw_brainvision, vhdr_fname=vhdr_highpass_path, eog=eog) + + assert raw.info["highpass"] == 1.0 / (2 * np.pi * 10) + assert raw.info["lowpass"] == 250.0 + + # Heterogeneous highpass in seconds (default measurement unit) + with pytest.warns(RuntimeWarning, match="different .*pass filters") as w: + raw = _test_raw_reader( + read_raw_brainvision, vhdr_fname=vhdr_mixed_highpass_path, eog=eog + ) + + w = [str(ww.message) for ww in w] + assert not any("different lowpass filters" in ww for ww in w), w + assert any("different highpass filters" in ww for ww in w), w + + assert raw.info["highpass"] == 1.0 / (2 * np.pi * 10) + assert raw.info["lowpass"] == 250.0 + + # Homogeneous highpass in Hertz + raw = _test_raw_reader( + read_raw_brainvision, vhdr_fname=vhdr_highpass_hz_path, eog=eog + ) + + assert raw.info["highpass"] == 10.0 + assert raw.info["lowpass"] == 250.0 + + # Heterogeneous highpass in Hertz + with pytest.warns(RuntimeWarning, match="different .*pass filters") as w: + raw = _test_raw_reader( + read_raw_brainvision, vhdr_fname=vhdr_mixed_highpass_hz_path, eog=eog + ) + + w = [str(ww.message) for ww in w] + assert not any("will be dropped" in ww for ww in w), w + assert not any("different lowpass filters" in ww for ww in w), w + assert any("different highpass filters" in ww for ww in w), w + + assert raw.info["highpass"] == 5.0 + assert raw.info["lowpass"] == 250.0 + + +def test_brainvision_data_lowpass_filters(): + """Test files with amplifier LP filter settings.""" + # Homogeneous lowpass in Hertz (default measurement unit) + raw = _test_raw_reader(read_raw_brainvision, vhdr_fname=vhdr_lowpass_path, eog=eog) + + assert raw.info["highpass"] == 1.0 / (2 * np.pi * 10) + assert raw.info["lowpass"] == 250.0 + + # Heterogeneous lowpass in Hertz (default measurement unit) + with pytest.warns(RuntimeWarning) as w: # event parsing + raw = _test_raw_reader( + read_raw_brainvision, vhdr_fname=vhdr_mixed_lowpass_path, eog=eog + ) + + lowpass_warning = ["different lowpass filters" in str(ww.message) for ww in w] + highpass_warning = ["different highpass filters" in str(ww.message) for ww in w] + + expected_warnings = zip(lowpass_warning, highpass_warning) + + assert any(any([lp, hp]) for lp, hp in expected_warnings) + + assert raw.info["highpass"] == 1.0 / (2 * np.pi * 10) + assert raw.info["lowpass"] == 250.0 + + # Homogeneous lowpass in seconds + raw = _test_raw_reader( + read_raw_brainvision, vhdr_fname=vhdr_lowpass_s_path, eog=eog + ) + + assert raw.info["highpass"] == 1.0 / (2 * np.pi * 10) + assert raw.info["lowpass"] == 1.0 / (2 * np.pi * 0.004) + + # Heterogeneous lowpass in seconds + with pytest.warns(RuntimeWarning) as w: # filter settings + raw = _test_raw_reader( + read_raw_brainvision, vhdr_fname=vhdr_mixed_lowpass_s_path, eog=eog + ) + + lowpass_warning = ["different lowpass filters" in str(ww.message) for ww in w] + highpass_warning = ["different highpass filters" in str(ww.message) for ww in w] + + expected_warnings = zip(lowpass_warning, highpass_warning) + + assert any(any([lp, hp]) for lp, hp in expected_warnings) + + assert raw.info["highpass"] == 1.0 / (2 * np.pi * 10) + assert raw.info["lowpass"] == 1.0 / (2 * np.pi * 0.004) + + +def test_brainvision_data_partially_disabled_hw_filters(): + """Test heterogeneous filter settings including non-numeric values.""" + with pytest.warns(RuntimeWarning) as w: # event parsing + raw = _test_raw_reader( + read_raw_brainvision, + vhdr_fname=vhdr_partially_disabled_hw_filter_path, + eog=eog, + ) + + trigger_warning = ["will be dropped" in str(ww.message) for ww in w] + lowpass_warning = ["different lowpass filters" in str(ww.message) for ww in w] + highpass_warning = ["different highpass filters" in str(ww.message) for ww in w] + + expected_warnings = zip(trigger_warning, lowpass_warning, highpass_warning) + + assert any(any([trg, lp, hp]) for trg, lp, hp in expected_warnings) + + assert raw.info["highpass"] == 0.0 + assert raw.info["lowpass"] == 500.0 + + +def test_brainvision_data_software_filters_latin1_global_units(): + """Test reading raw Brain Vision files.""" + with _no_dig, pytest.warns(RuntimeWarning, match="software filter"): + raw = _test_raw_reader( + read_raw_brainvision, + vhdr_fname=vhdr_old_path, + eog=("VEOGo", "VEOGu", "HEOGli", "HEOGre"), + misc=("A2",), + ) + + assert raw.info["highpass"] == 1.0 / (2 * np.pi * 0.9) + assert raw.info["lowpass"] == 50.0 + + # test sensor name with spaces (#9299) + with _no_dig, pytest.warns(RuntimeWarning, match="software filter"): + raw = _test_raw_reader( + read_raw_brainvision, + vhdr_fname=vhdr_old_longname_path, + eog=("VEOGo", "VEOGu", "HEOGli", "HEOGre"), + misc=("A2",), + ) + + assert raw.info["highpass"] == 1.0 / (2 * np.pi * 0.9) + assert raw.info["lowpass"] == 50.0 + + +def test_brainvision_data(): + """Test reading raw Brain Vision files.""" + pytest.raises(OSError, read_raw_brainvision, vmrk_path) + pytest.raises( + ValueError, read_raw_brainvision, vhdr_path, preload=True, scale="foo" + ) + + raw_py = _test_raw_reader( + read_raw_brainvision, vhdr_fname=vhdr_path, eog=eog, misc="auto" + ) + + assert "RawBrainVision" in repr(raw_py) + + assert raw_py.info["highpass"] == 0.0 + assert raw_py.info["lowpass"] == 250.0 + + picks = pick_types(raw_py.info, meg=False, eeg=True, exclude="bads") + data_py, times_py = raw_py[picks] + + # compare with a file that was generated using MNE-C + raw_bin = read_raw_fif(eeg_bin, preload=True) + picks = pick_types(raw_py.info, meg=False, eeg=True, exclude="bads") + data_bin, times_bin = raw_bin[picks] + + assert_allclose(data_py, data_bin) + assert_allclose(times_py, times_bin) + + # Make sure EOG channels are marked correctly + for ch in raw_py.info["chs"]: + if ch["ch_name"] in eog: + assert ch["kind"] == FIFF.FIFFV_EOG_CH + elif ch["ch_name"] == "STI 014": + assert ch["kind"] == FIFF.FIFFV_STIM_CH + elif ch["ch_name"] in ("CP5", "CP6"): + assert ch["kind"] == FIFF.FIFFV_MISC_CH + assert ch["unit"] == FIFF.FIFF_UNIT_NONE + elif ch["ch_name"] == "ReRef": + assert ch["kind"] == FIFF.FIFFV_MISC_CH + assert ch["unit"] == FIFF.FIFF_UNIT_CEL + else: + assert ch["ch_name"] in raw_py.info["ch_names"], f"Unknown: {ch['ch_name']}" + assert ch["kind"] == FIFF.FIFFV_EEG_CH + assert ch["unit"] == FIFF.FIFF_UNIT_V + + # test loading v2 + read_raw_brainvision(vhdr_v2_path, eog=eog, preload=True, verbose="error") + # test different units with alternative header file + raw_units = _test_raw_reader( + read_raw_brainvision, vhdr_fname=vhdr_units_path, eog=eog, misc="auto" + ) + assert raw_units.info["chs"][0]["ch_name"] == "FP1" + assert raw_units.info["chs"][0]["kind"] == FIFF.FIFFV_EEG_CH + data_units, _ = raw_units[0] + assert_allclose(data_py[0, :], data_units.squeeze()) + + assert raw_units.info["chs"][1]["ch_name"] == "FP2" + assert raw_units.info["chs"][1]["kind"] == FIFF.FIFFV_EEG_CH + data_units, _ = raw_units[1] + assert_allclose(data_py[1, :], data_units.squeeze()) + + assert raw_units.info["chs"][2]["ch_name"] == "F3" + assert raw_units.info["chs"][2]["kind"] == FIFF.FIFFV_EEG_CH + data_units, _ = raw_units[2] + assert_allclose(data_py[2, :], data_units.squeeze()) + + +def test_brainvision_vectorized_data(): + """Test reading BrainVision data files with vectorized data.""" + with _no_dig, pytest.warns(RuntimeWarning, match="software filter"): + raw = read_raw_brainvision(vhdr_old_path, preload=True) + + assert_array_equal(raw._data.shape, (29, 251)) + + first_two_samples_all_chs = np.array( + [ + [+5.22000008e-06, +5.10000000e-06], + [+2.10000000e-06, +2.27000008e-06], + [+1.15000000e-06, +1.33000002e-06], + [+4.00000000e-07, +4.00000000e-07], + [-3.02999992e-06, -2.82000008e-06], + [+2.71000004e-06, +2.45000000e-06], + [+2.41000004e-06, +2.36000004e-06], + [+1.01999998e-06, +1.18000002e-06], + [-1.33999996e-06, -1.25000000e-06], + [-2.60000000e-06, -2.46000004e-06], + [+6.80000019e-07, +8.00000000e-07], + [+1.48000002e-06, +1.48999996e-06], + [+1.61000004e-06, +1.51000004e-06], + [+7.19999981e-07, +8.60000038e-07], + [-3.00000000e-07, -4.00000006e-08], + [-1.20000005e-07, +6.00000024e-08], + [+8.19999981e-07, +9.89999962e-07], + [+1.13000002e-06, +1.28000002e-06], + [+1.08000002e-06, +1.33999996e-06], + [+2.20000005e-07, +5.69999981e-07], + [-4.09999990e-07, +4.00000006e-08], + [+5.19999981e-07, +9.39999962e-07], + [+1.01000004e-06, +1.51999998e-06], + [+1.01000004e-06, +1.55000000e-06], + [-1.43000002e-06, -1.13999996e-06], + [+3.65000000e-06, +3.65999985e-06], + [+4.15999985e-06, +3.79000015e-06], + [+9.26999969e-06, +8.95999985e-06], + [-7.35999985e-06, -7.18000031e-06], + ] + ) + + assert_allclose(raw._data[:, :2], first_two_samples_all_chs) + + +def test_coodinates_extraction(): + """Test reading of [Coordinates] section if present.""" + # vhdr 2 has a Coordinates section + with ( + _record_warnings(), + pytest.warns(RuntimeWarning, match="coordinate information"), + ): + raw = read_raw_brainvision(vhdr_v2_path) + + # Basic check of extracted coordinates + assert raw.info["dig"] is not None + diglist = raw.info["dig"] + coords = np.array([dig["r"] for dig in diglist]) + EXPECTED_SHAPE = ( + # HL, HR, Vb, ReRef are not set in dig + # but LPA, Nasion, RPA are estimated + len(raw.ch_names) - 4 + 3, + 3, + ) + assert coords.shape == EXPECTED_SHAPE + + # Make sure the scaling seems right + # a coordinate more than 20cm away from origin is implausible + assert coords.max() < 0.2 + + # vhdr 1 does not have a Coordinates section + raw2 = read_raw_brainvision(vhdr_path) + assert raw2.info["dig"] is None + + +@testing.requires_testing_data +def test_brainvision_neuroone_export(): + """Test Brainvision file exported with neuroone system.""" + raw = read_raw_brainvision(neuroone_vhdr, verbose="error") + assert raw.info["meas_date"] is None + assert len(raw.info["chs"]) == 65 + assert raw.info["sfreq"] == 5000.0 + + +@testing.requires_testing_data +def test_read_vmrk_annotations(tmp_path): + """Test load brainvision annotations.""" + sfreq = 1000.0 + + # Test vmrk file without annotations + # delete=False is for Windows compatibility + with open(vmrk_path) as myfile: + head = [next(myfile) for x in range(6)] + fname = tmp_path / "temp.vmrk" + with open(str(fname), "w") as temp: + for item in head: + temp.write(item) + read_annotations(fname, sfreq=sfreq) + + +def test_ignore_marker_types(): + """Test ignore marker types.""" + # default behavior (do not ignore marker types) + raw = read_raw_brainvision(vhdr_path) + expected_descriptions = [ + "Stimulus/S253", + "Stimulus/S255", + "Event/254", + "Stimulus/S255", + "Event/254", + "Stimulus/S255", + "Stimulus/S253", + "Stimulus/S255", + "Response/R255", + "Event/254", + "Stimulus/S255", + "SyncStatus/Sync On", + "Optic/O 1", + ] + assert_array_equal(raw.annotations.description, expected_descriptions) + + # ignore marker types + raw = read_raw_brainvision(vhdr_path, ignore_marker_types=True) + expected_descriptions = [ + "S253", + "S255", + "254", + "S255", + "254", + "S255", + "S253", + "S255", + "R255", + "254", + "S255", + "Sync On", + "O 1", + ] + assert_array_equal(raw.annotations.description, expected_descriptions) + + +@testing.requires_testing_data +def test_read_vhdr_annotations_and_events(tmp_path): + """Test load brainvision annotations and parse them to events.""" + # First we add a custom event that contains a comma in its description + for src, dest in zip( + (vhdr_path, vmrk_path, eeg_path), ("test.vhdr", "test.vmrk", "test.eeg") + ): + shutil.copyfile(src, tmp_path / dest) + + # Commas are encoded as "\1" + with open(tmp_path / "test.vmrk", "a") as fout: + fout.write(r"Mk15=Comma\1Type,CommaValue\11,7800,1,0\n") + + sfreq = 1000.0 + expected_orig_time = _stamp_to_dt((1384359243, 794232)) + expected_onset_latency = np.array( + [ + 486.0, + 496.0, + 1769.0, + 1779.0, + 3252.0, + 3262.0, + 4935.0, + 4945.0, + 5999.0, + 6619.0, + 6629.0, + 7629.0, + 7699.0, + 7799.0, + ] + ) + expected_annot_description = [ + "Stimulus/S253", + "Stimulus/S255", + "Event/254", + "Stimulus/S255", + "Event/254", + "Stimulus/S255", + "Stimulus/S253", + "Stimulus/S255", + "Response/R255", + "Event/254", + "Stimulus/S255", + "SyncStatus/Sync On", + "Optic/O 1", + "Comma,Type/CommaValue,1", + ] + expected_events = ( + np.stack( + [ + expected_onset_latency, + np.zeros_like(expected_onset_latency), + [ + 253, + 255, + 254, + 255, + 254, + 255, + 253, + 255, + 1255, + 254, + 255, + 99998, + 2001, + 10001, + ], + ] + ) + .astype("int64") + .T + ) + expected_event_id = { + "Stimulus/S253": 253, + "Stimulus/S255": 255, + "Event/254": 254, + "Response/R255": 1255, + "SyncStatus/Sync On": 99998, + "Optic/O 1": 2001, + "Comma,Type/CommaValue,1": 10001, + } + + raw = read_raw_brainvision(tmp_path / "test.vhdr", eog=eog) + + # validate annotations + assert raw.annotations.orig_time == expected_orig_time + assert_allclose(raw.annotations.onset, expected_onset_latency / sfreq) + assert_array_equal(raw.annotations.description, expected_annot_description) + + # validate event extraction + events, event_id = events_from_annotations(raw) + assert_array_equal(events, expected_events) + assert event_id == expected_event_id + + # validate that None gives us a sorted list + expected_none_event_id = { + desc: idx + 1 for idx, desc in enumerate(sorted(event_id.keys())) + } + events, event_id = events_from_annotations(raw, event_id=None) + assert event_id == expected_none_event_id + + # Add some custom ones, plus a 2-digit one + s_10 = "Stimulus/S 10" + raw.annotations.append([1, 2, 3], 10, ["ZZZ", s_10, "YYY"]) + # others starting at 10001 ... + # we already have "Comma,Type/CommaValue,1" as 10001 + expected_event_id.update(YYY=10002, ZZZ=10003) + expected_event_id[s_10] = 10 + _, event_id = events_from_annotations(raw) + assert event_id == expected_event_id + + # Concatenating two shouldn't change the resulting event_id + # (BAD and EDGE should be ignored) + with pytest.warns(RuntimeWarning, match="expanding outside"): + raw_concat = concatenate_raws([raw.copy(), raw.copy()]) + _, event_id = events_from_annotations(raw_concat) + assert event_id == expected_event_id + + +@testing.requires_testing_data +def test_automatic_vmrk_sfreq_recovery(): + """Test proper sfreq inference by checking the onsets.""" + assert_array_equal( + read_annotations(vmrk_path, sfreq="auto"), + read_annotations(vmrk_path, sfreq=1000.0), + ) + + +@testing.requires_testing_data +def test_event_id_stability_when_save_and_fif_reload(tmp_path): + """Test load events from brainvision annotations when read_raw_fif.""" + fname = tmp_path / "bv-raw.fif" + raw = read_raw_brainvision(vhdr_path, eog=eog) + original_events, original_event_id = events_from_annotations(raw) + + raw.save(fname) + raw = read_raw_fif(fname) + events, event_id = events_from_annotations(raw) + + assert event_id == original_event_id + assert_array_equal(events, original_events) + + +def test_parse_impedance(): + """Test case for parsing the impedances from header.""" + expected_imp_meas_time = datetime.datetime( + 2013, 11, 13, 16, 12, 27, tzinfo=datetime.timezone.utc + ) + expected_imp_unit = "kOhm" + expected_electrodes = [ + "FP1", + "FP2", + "F3", + "F4", + "C3", + "C4", + "P3", + "P4", + "O1", + "O2", + "F7", + "F8", + "P7", + "P8", + "Fz", + "FCz", + "Cz", + "CPz", + "Pz", + "POz", + "FC1", + "FC2", + "CP1", + "CP2", + "FC5", + "FC6", + "CP5", + "CP6", + "HL", + "HR", + "Vb", + "ReRef", + "Ref", + "Gnd", + ] + n_electrodes = len(expected_electrodes) + expected_imps = [np.nan] * (n_electrodes - 2) + [0.0, 4.0] + expected_imp_lower_bound = 0.0 + expected_imp_upper_bound = [100.0] * (n_electrodes - 2) + [10.0, 10.0] + + expected_impedances = { + elec: { + "imp": expected_imps[i], + "imp_unit": expected_imp_unit, + "imp_meas_time": expected_imp_meas_time, + "imp_lower_bound": expected_imp_lower_bound, + "imp_upper_bound": expected_imp_upper_bound[i], + "imp_range_unit": expected_imp_unit, + } + for i, elec in enumerate(expected_electrodes) + } + + raw = read_raw_brainvision(vhdr_path, eog=eog) + assert object_diff(expected_impedances, raw.impedances) == "" + + # Test "Impedances Imported from actiCAP Control Software" + expected_imp_meas_time = expected_imp_meas_time.replace( + hour=10, minute=17, second=2 + ) + tmpidx = expected_electrodes.index("CP6") + expected_electrodes = expected_electrodes[:tmpidx] + [ + "CP 6", + "ECG+", + "ECG-", + "HEOG+", + "HEOG-", + "VEOG+", + "VEOG-", + "ReRef", + "Ref", + "Gnd", + ] + n_electrodes = len(expected_electrodes) + expected_imps = [np.nan] * (n_electrodes - 9) + [ + 35.0, + 46.0, + 6.0, + 8.0, + 3.0, + 4.0, + 0.0, + 8.0, + 2.5, + ] + expected_impedances = { + elec: { + "imp": expected_imps[i], + "imp_unit": expected_imp_unit, + "imp_meas_time": expected_imp_meas_time, + } + for i, elec in enumerate(expected_electrodes) + } + + with pytest.warns(RuntimeWarning, match="different .*pass filters"): + raw = read_raw_brainvision( + vhdr_mixed_lowpass_path, eog=["HEOG", "VEOG"], misc=["ECG"] + ) + assert object_diff(expected_impedances, raw.impedances) == "" + + +@testing.requires_testing_data +def test_ahdr_format(): + """Test case for parsing data in ahdr format.""" + expected_num_channels = 6 + expected_hp = 0.0 + expected_lp = 250.0 + + raw = read_raw_brainvision(vamp_ahdr) + assert raw.info["nchan"] == expected_num_channels + assert raw.info["highpass"] == expected_hp + assert raw.info["lowpass"] == expected_lp diff --git a/mne-python/source/mne/io/bti/__init__.py b/mne-python/source/mne/io/bti/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3a9d58fe44c90ccd5b629793d273b62e1958c315 --- /dev/null +++ b/mne-python/source/mne/io/bti/__init__.py @@ -0,0 +1,7 @@ +"""BTi module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .bti import read_raw_bti diff --git a/mne-python/source/mne/io/bti/bti.py b/mne-python/source/mne/io/bti/bti.py new file mode 100644 index 0000000000000000000000000000000000000000..e811cd61ff0af1e385e16d036289f158f78ac979 --- /dev/null +++ b/mne-python/source/mne/io/bti/bti.py @@ -0,0 +1,1415 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import functools +import os.path as op +from io import BytesIO +from itertools import count + +import numpy as np + +from ..._fiff._digitization import _make_bti_dig_points +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info +from ..._fiff.tag import _coil_trans_to_loc, _loc_to_coil_trans +from ..._fiff.utils import _mult_cal_one, read_str +from ...fixes import _reshape_view +from ...transforms import Transform, combine_transforms, invert_transform +from ...utils import _stamp_to_dt, _validate_type, logger, path_like, verbose +from ..base import BaseRaw +from .constants import BTI +from .read import ( + read_char, + read_dev_header, + read_double, + read_double_matrix, + read_float, + read_float_matrix, + read_int16, + read_int16_matrix, + read_int32, + read_int64, + read_transform, + read_uint16, + read_uint32, +) + +BTI_WH2500_REF_MAG = ("MxA", "MyA", "MzA", "MxaA", "MyaA", "MzaA") +BTI_WH2500_REF_GRAD = ("GxxA", "GyyA", "GyxA", "GzaA", "GzyA") + +dtypes = zip(list(range(1, 5)), (">i2", ">i4", ">f4", ">f8")) +DTYPES = {i: np.dtype(t) for i, t in dtypes} + + +def _instantiate_default_info_chs(): + """Populate entries in info['chs'] with default values.""" + return dict( + loc=np.array([0, 0, 0, 1] * 3, dtype="f4"), + ch_name=None, + unit_mul=FIFF.FIFF_UNITM_NONE, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + coil_type=FIFF.FIFFV_COIL_NONE, + range=1.0, + unit=FIFF.FIFF_UNIT_V, + cal=1.0, + scanno=None, + kind=FIFF.FIFFV_MISC_CH, + logno=None, + ) + + +class _bytes_io_mock_context: + """Make a context for BytesIO.""" + + def __init__(self, target): + self.target = target + + def __enter__(self): # noqa: D105 + return self.target + + def __exit__(self, exception_type, value, tb): # noqa: D105 + pass + + +def _bti_open(fname, *args, **kwargs): + """Handle BytesIO.""" + if isinstance(fname, path_like): + return open(fname, *args, **kwargs) + elif isinstance(fname, BytesIO): + return _bytes_io_mock_context(fname) + else: + raise RuntimeError("Cannot mock this.") + + +def _get_bti_dev_t(adjust=0.0, translation=(0.0, 0.02, 0.11)): + """Get the general Magnes3600WH to Neuromag coordinate transform. + + Parameters + ---------- + adjust : float | None + Degrees to tilt x-axis for sensor frame misalignment. + If None, no adjustment will be applied. + translation : array-like + The translation to place the origin of coordinate system + to the center of the head. + + Returns + ------- + m_nm_t : ndarray + 4 x 4 rotation, translation, scaling matrix. + """ + flip_t = np.array([[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]]) + rad = np.deg2rad(adjust) + adjust_t = np.array( + [ + [1.0, 0.0, 0.0], + [0.0, np.cos(rad), -np.sin(rad)], + [0.0, np.sin(rad), np.cos(rad)], + ] + ) + m_nm_t = np.eye(4) + m_nm_t[:3, :3] = np.dot(flip_t, adjust_t) + m_nm_t[:3, 3] = translation + return m_nm_t + + +def _rename_channels(names, ecg_ch="E31", eog_ch=("E63", "E64")): + """Rename appropriately ordered list of channel names. + + Parameters + ---------- + names : list of str + Lists of 4-D channel names in ascending order + + Returns + ------- + new : list + List of names, channel names in Neuromag style + """ + new = list() + ref_mag, ref_grad, eog, eeg, ext = (count(1) for _ in range(5)) + for i, name in enumerate(names, 1): + if name.startswith("A"): + name = f"MEG {i:03d}" + elif name == "RESPONSE": + name = "STI 013" + elif name == "TRIGGER": + name = "STI 014" + elif any(name == k for k in eog_ch): + name = f"EOG {next(eog):03d}" + elif name == ecg_ch: + name = "ECG 001" + elif name.startswith("E"): + name = f"EEG {next(eeg):03d}" + elif name == "UACurrent": + name = "UTL 001" + elif name.startswith("M"): + name = f"RFM {next(ref_mag):03d}" + elif name.startswith("G"): + name = f"RFG {next(ref_grad):03d}" + elif name.startswith("X"): + name = f"EXT {next(ext):03d}" + + new += [name] + + return new + + +# read the points +def _read_head_shape(fname): + """Read the head shape.""" + with _bti_open(fname, "rb") as fid: + fid.seek(BTI.FILE_HS_N_DIGPOINTS) + _n_dig_points = read_int32(fid) + idx_points = read_double_matrix(fid, BTI.DATA_N_IDX_POINTS, 3) + dig_points = read_double_matrix(fid, _n_dig_points, 3) + + # reorder to lpa, rpa, nasion so = is direct. + nasion, lpa, rpa = (idx_points[_, :] for _ in [2, 0, 1]) + hpi = idx_points[3 : len(idx_points), :] + + return nasion, lpa, rpa, hpi, dig_points + + +def _check_nan_dev_head_t(dev_ctf_t): + """Make sure we deal with nans.""" + has_nan = np.isnan(dev_ctf_t["trans"]) + if np.any(has_nan): + logger.info( + "Missing values BTI dev->head transform. Replacing with identity matrix." + ) + dev_ctf_t["trans"] = np.identity(4) + + +def _convert_coil_trans(coil_trans, dev_ctf_t, bti_dev_t): + """Convert the coil trans.""" + t = combine_transforms(invert_transform(dev_ctf_t), bti_dev_t, "ctf_head", "meg") + t = np.dot(t["trans"], coil_trans) + return t + + +def _correct_offset(fid): + """Align fid pointer.""" + current = fid.tell() + if (current % BTI.FILE_CURPOS) != 0: + offset = current % BTI.FILE_CURPOS + fid.seek(BTI.FILE_CURPOS - (offset), 1) + + +def _read_config(fname): + """Read BTi system config file. + + Parameters + ---------- + fname : str + The absolute path to the config file + + Returns + ------- + cfg : dict + The config blocks found. + """ + with _bti_open(fname, "rb") as fid: + cfg = dict() + cfg["hdr"] = { + "version": read_int16(fid), + "site_name": read_str(fid, 32), + "dap_hostname": read_str(fid, 16), + "sys_type": read_int16(fid), + "sys_options": read_int32(fid), + "supply_freq": read_int16(fid), + "total_chans": read_int16(fid), + "system_fixed_gain": read_float(fid), + "volts_per_bit": read_float(fid), + "total_sensors": read_int16(fid), + "total_user_blocks": read_int16(fid), + "next_der_chan_no": read_int16(fid), + } + + fid.seek(2, 1) + + cfg["checksum"] = read_uint32(fid) + cfg["reserved"] = read_char(fid, 32) + cfg["transforms"] = [ + read_transform(fid) for t in range(cfg["hdr"]["total_sensors"]) + ] + + cfg["user_blocks"] = dict() + for block in range(cfg["hdr"]["total_user_blocks"]): + ub = dict() + + ub["hdr"] = { + "nbytes": read_uint32(fid), + "kind": read_str(fid, 20), + "checksum": read_int32(fid), + "username": read_str(fid, 32), + "timestamp": read_uint32(fid), + "user_space_size": read_uint32(fid), + "reserved": read_char(fid, 32), + } + + _correct_offset(fid) + start_bytes = fid.tell() + kind = ub["hdr"].pop("kind") + if not kind: # make sure reading goes right. Should never be empty + raise RuntimeError( + "Could not read user block. Probably you " + "acquired data using a BTi version " + "currently not supported. Please contact " + "the mne-python developers." + ) + dta, cfg["user_blocks"][kind] = dict(), ub + if kind in [v for k, v in BTI.items() if k[:5] == "UB_B_"]: + if kind == BTI.UB_B_MAG_INFO: + dta["version"] = read_int32(fid) + fid.seek(20, 1) + dta["headers"] = list() + for hdr in range(6): + d = { + "name": read_str(fid, 16), + "transform": read_transform(fid), + "units_per_bit": read_float(fid), + } + dta["headers"] += [d] + fid.seek(20, 1) + + elif kind == BTI.UB_B_COH_POINTS: + dta["n_points"] = read_int32(fid) + dta["status"] = read_int32(fid) + dta["points"] = [ + { + "pos": read_double_matrix(fid, 1, 3), + "direction": read_double_matrix(fid, 1, 3), + "error": read_double(fid), + } + for _ in range(16) + ] + + elif kind == BTI.UB_B_CCP_XFM_BLOCK: + dta["method"] = read_int32(fid) + # handle difference btw/ linux (0) and solaris (4) + size = 0 if ub["hdr"]["user_space_size"] == 132 else 4 + fid.seek(size, 1) + dta["transform"] = read_transform(fid) + + elif kind == BTI.UB_B_EEG_LOCS: + dta["electrodes"] = [] + while True: + d = { + "label": read_str(fid, 16), + "location": read_double_matrix(fid, 1, 3), + } + if not d["label"]: + break + dta["electrodes"] += [d] + + elif kind in [BTI.UB_B_WHC_CHAN_MAP_VER, BTI.UB_B_WHS_SUBSYS_VER]: + dta["version"] = read_int16(fid) + dta["struct_size"] = read_int16(fid) + dta["entries"] = read_int16(fid) + + fid.seek(8, 1) + + elif kind == BTI.UB_B_WHC_CHAN_MAP: + num_channels = None + for name, data in cfg["user_blocks"].items(): + if name == BTI.UB_B_WHC_CHAN_MAP_VER: + num_channels = data["entries"] + break + + if num_channels is None: + raise ValueError( + f"Cannot find block {BTI.UB_B_WHC_CHAN_MAP_VER} to " + "determine number of channels" + ) + + dta["channels"] = list() + for i in range(num_channels): + d = { + "subsys_type": read_int16(fid), + "subsys_num": read_int16(fid), + "card_num": read_int16(fid), + "chan_num": read_int16(fid), + "recdspnum": read_int16(fid), + } + dta["channels"] += [d] + fid.seek(8, 1) + + elif kind == BTI.UB_B_WHS_SUBSYS: + num_subsys = None + for name, data in cfg["user_blocks"].items(): + if name == BTI.UB_B_WHS_SUBSYS_VER: + num_subsys = data["entries"] + break + + if num_subsys is None: + raise ValueError( + f"Cannot find block {BTI.UB_B_WHS_SUBSYS_VER} to determine" + " number of subsystems" + ) + + dta["subsys"] = list() + for _ in range(num_subsys): + d = { + "subsys_type": read_int16(fid), + "subsys_num": read_int16(fid), + "cards_per_sys": read_int16(fid), + "channels_per_card": read_int16(fid), + "card_version": read_int16(fid), + } + + fid.seek(2, 1) + + d.update( + { + "offsetdacgain": read_float(fid), + "squid_type": read_int32(fid), + "timesliceoffset": read_int16(fid), + "padding": read_int16(fid), + "volts_per_bit": read_float(fid), + } + ) + + dta["subsys"] += [d] + + elif kind == BTI.UB_B_CH_LABELS: + dta["version"] = read_int32(fid) + dta["entries"] = read_int32(fid) + fid.seek(16, 1) + + dta["labels"] = list() + for label in range(dta["entries"]): + dta["labels"] += [read_str(fid, 16)] + + elif kind == BTI.UB_B_CALIBRATION: + dta["sensor_no"] = read_int16(fid) + fid.seek(2, 1) + dta["timestamp"] = read_int32(fid) + dta["logdir"] = read_str(fid, 256) + + elif kind == BTI.UB_B_SYS_CONFIG_TIME: + # handle difference btw/ linux (256) and solaris (512) + size = 256 if ub["hdr"]["user_space_size"] == 260 else 512 + dta["sysconfig_name"] = read_str(fid, size) + dta["timestamp"] = read_int32(fid) + + elif kind == BTI.UB_B_DELTA_ENABLED: + dta["delta_enabled"] = read_int16(fid) + + elif kind in [BTI.UB_B_E_TABLE_USED, BTI.UB_B_E_TABLE]: + dta["hdr"] = { + "version": read_int32(fid), + "entry_size": read_int32(fid), + "n_entries": read_int32(fid), + "filtername": read_str(fid, 16), + "n_e_values": read_int32(fid), + "reserved": read_str(fid, 28), + } + + if dta["hdr"]["version"] == 2: + size = 16 + dta["ch_names"] = [ + read_str(fid, size) for ch in range(dta["hdr"]["n_entries"]) + ] + dta["e_ch_names"] = [ + read_str(fid, size) + for ch in range(dta["hdr"]["n_e_values"]) + ] + + rows = dta["hdr"]["n_entries"] + cols = dta["hdr"]["n_e_values"] + dta["etable"] = read_float_matrix(fid, rows, cols) + else: # handle MAGNES2500 naming scheme + dta["ch_names"] = ["WH2500"] * dta["hdr"]["n_e_values"] + dta["hdr"]["n_e_values"] = 6 + dta["e_ch_names"] = BTI_WH2500_REF_MAG + rows = dta["hdr"]["n_entries"] + cols = dta["hdr"]["n_e_values"] + dta["etable"] = read_float_matrix(fid, rows, cols) + + elif any( + [kind == BTI.UB_B_WEIGHTS_USED, kind[:4] == BTI.UB_B_WEIGHT_TABLE] + ): + dta["hdr"] = dict( + version=read_int32(fid), + n_bytes=read_uint32(fid), + n_entries=read_uint32(fid), + name=read_str(fid, 32), + ) + if dta["hdr"]["version"] == 2: + dta["hdr"].update( + description=read_str(fid, 80), + n_anlg=read_uint32(fid), + n_dsp=read_uint32(fid), + reserved=read_str(fid, 72), + ) + dta["ch_names"] = [ + read_str(fid, 16) for ch in range(dta["hdr"]["n_entries"]) + ] + dta["anlg_ch_names"] = [ + read_str(fid, 16) for ch in range(dta["hdr"]["n_anlg"]) + ] + + dta["dsp_ch_names"] = [ + read_str(fid, 16) for ch in range(dta["hdr"]["n_dsp"]) + ] + dta["dsp_wts"] = read_float_matrix( + fid, dta["hdr"]["n_entries"], dta["hdr"]["n_dsp"] + ) + dta["anlg_wts"] = read_int16_matrix( + fid, dta["hdr"]["n_entries"], dta["hdr"]["n_anlg"] + ) + else: # handle MAGNES2500 naming scheme + fid.seek( + start_bytes + + ub["hdr"]["user_space_size"] + - dta["hdr"]["n_bytes"] * dta["hdr"]["n_entries"], + 0, + ) + + dta["hdr"]["n_dsp"] = dta["hdr"]["n_bytes"] // 4 - 2 + assert dta["hdr"]["n_dsp"] == len(BTI_WH2500_REF_MAG) + len( + BTI_WH2500_REF_GRAD + ) + dta["ch_names"] = ["WH2500"] * dta["hdr"]["n_entries"] + dta["hdr"]["n_anlg"] = 3 + # These orders could be wrong, so don't set them + # for now + # dta['anlg_ch_names'] = BTI_WH2500_REF_MAG[:3] + # dta['dsp_ch_names'] = (BTI_WH2500_REF_GRAD + + # BTI_WH2500_REF_MAG) + dta["anlg_wts"] = np.zeros( + (dta["hdr"]["n_entries"], dta["hdr"]["n_anlg"]), dtype="i2" + ) + dta["dsp_wts"] = np.zeros( + (dta["hdr"]["n_entries"], dta["hdr"]["n_dsp"]), dtype="f4" + ) + for n in range(dta["hdr"]["n_entries"]): + dta["anlg_wts"][n] = read_int16_matrix( + fid, 1, dta["hdr"]["n_anlg"] + ) + read_int16(fid) + dta["dsp_wts"][n] = read_float_matrix( + fid, 1, dta["hdr"]["n_dsp"] + ) + + elif kind == BTI.UB_B_TRIG_MASK: + dta["version"] = read_int32(fid) + dta["entries"] = read_int32(fid) + fid.seek(16, 1) + + dta["masks"] = [] + for entry in range(dta["entries"]): + d = { + "name": read_str(fid, 20), + "nbits": read_uint16(fid), + "shift": read_uint16(fid), + "mask": read_uint32(fid), + } + dta["masks"] += [d] + fid.seek(8, 1) + + else: + dta["unknown"] = {"hdr": read_char(fid, ub["hdr"]["user_space_size"])} + + n_read = fid.tell() - start_bytes + if n_read != ub["hdr"]["user_space_size"]: + raise RuntimeError( + f"Internal MNE reading error, read size {n_read} " + f"!= {ub['hdr']['user_space_size']} expected size for kind {kind}." + ) + ub.update(dta) # finally update the userblock data + _correct_offset(fid) # after reading. + + cfg["chs"] = list() + + # prepare reading channels + for channel in range(cfg["hdr"]["total_chans"]): + ch = { + "name": read_str(fid, 16), + "chan_no": read_int16(fid), + "ch_type": read_uint16(fid), + "sensor_no": read_int16(fid), + "data": dict(), + } + + fid.seek(2, 1) + ch.update( + { + "gain": read_float(fid), + "units_per_bit": read_float(fid), + "yaxis_label": read_str(fid, 16), + "aar_val": read_double(fid), + "checksum": read_int32(fid), + "reserved": read_str(fid, 32), + } + ) + + cfg["chs"] += [ch] + _correct_offset(fid) # before and after + dta = dict() + if ch["ch_type"] in [BTI.CHTYPE_MEG, BTI.CHTYPE_REFERENCE]: + dev = { + "device_info": read_dev_header(fid), + "inductance": read_float(fid), + "padding": read_str(fid, 4), + "transform": _correct_trans(read_transform(fid), False), + "xform_flag": read_int16(fid), + "total_loops": read_int16(fid), + } + + fid.seek(4, 1) + dev["reserved"] = read_str(fid, 32) + dta.update({"dev": dev, "loops": []}) + for _ in range(dev["total_loops"]): + d = { + "position": read_double_matrix(fid, 1, 3), + "orientation": read_double_matrix(fid, 1, 3), + "radius": read_double(fid), + "wire_radius": read_double(fid), + "turns": read_int16(fid), + } + fid.seek(2, 1) + d["checksum"] = read_int32(fid) + d["reserved"] = read_str(fid, 32) + dta["loops"] += [d] + + elif ch["ch_type"] == BTI.CHTYPE_EEG: + dta = { + "device_info": read_dev_header(fid), + "impedance": read_float(fid), + "padding": read_str(fid, 4), + "transform": read_transform(fid), + "reserved": read_char(fid, 32), + } + + elif ch["ch_type"] == BTI.CHTYPE_EXTERNAL: + dta = { + "device_info": read_dev_header(fid), + "user_space_size": read_int32(fid), + "reserved": read_str(fid, 32), + } + + elif ch["ch_type"] == BTI.CHTYPE_TRIGGER: + dta = { + "device_info": read_dev_header(fid), + "user_space_size": read_int32(fid), + } + fid.seek(2, 1) + dta["reserved"] = read_str(fid, 32) + + elif ch["ch_type"] in [BTI.CHTYPE_UTILITY, BTI.CHTYPE_DERIVED]: + dta = { + "device_info": read_dev_header(fid), + "user_space_size": read_int32(fid), + "reserved": read_str(fid, 32), + } + + elif ch["ch_type"] == BTI.CHTYPE_SHORTED: + dta = { + "device_info": read_dev_header(fid), + "reserved": read_str(fid, 32), + } + + ch.update(dta) # add data collected + _correct_offset(fid) # after each reading + + return cfg + + +def _read_epoch(fid): + """Read BTi PDF epoch.""" + out = { + "pts_in_epoch": read_int32(fid), + "epoch_duration": read_float(fid), + "expected_iti": read_float(fid), + "actual_iti": read_float(fid), + "total_var_events": read_int32(fid), + "checksum": read_int32(fid), + "epoch_timestamp": read_int32(fid), + } + + fid.seek(28, 1) + + return out + + +def _read_channel(fid): + """Read BTi PDF channel.""" + out = { + "chan_label": read_str(fid, 16), + "chan_no": read_int16(fid), + "attributes": read_int16(fid), + "scale": read_float(fid), + "yaxis_label": read_str(fid, 16), + "valid_min_max": read_int16(fid), + } + + fid.seek(6, 1) + out.update( + { + "ymin": read_double(fid), + "ymax": read_double(fid), + "index": read_int32(fid), + "checksum": read_int32(fid), + "off_flag": read_str(fid, 4), + "offset": read_float(fid), + } + ) + + fid.seek(24, 1) + + return out + + +def _read_event(fid): + """Read BTi PDF event.""" + out = { + "event_name": read_str(fid, 16), + "start_lat": read_float(fid), + "end_lat": read_float(fid), + "step_size": read_float(fid), + "fixed_event": read_int16(fid), + "checksum": read_int32(fid), + } + + fid.seek(32, 1) + _correct_offset(fid) + + return out + + +def _read_process(fid): + """Read BTi PDF process.""" + out = { + "nbytes": read_int32(fid), + "process_type": read_str(fid, 20), + "checksum": read_int32(fid), + "user": read_str(fid, 32), + "timestamp": read_int32(fid), + "filename": read_str(fid, 256), + "total_steps": read_int32(fid), + } + + fid.seek(32, 1) + _correct_offset(fid) + out["processing_steps"] = list() + for step in range(out["total_steps"]): + this_step = { + "nbytes": read_int32(fid), + "process_type": read_str(fid, 20), + "checksum": read_int32(fid), + } + ptype = this_step["process_type"] + if ptype == BTI.PROC_DEFAULTS: + this_step["scale_option"] = read_int32(fid) + + fid.seek(4, 1) + this_step["scale"] = read_double(fid) + this_step["dtype"] = read_int32(fid) + this_step["selected"] = read_int16(fid) + this_step["color_display"] = read_int16(fid) + + fid.seek(32, 1) + elif ptype in BTI.PROC_FILTER: + this_step["freq"] = read_float(fid) + fid.seek(32, 1) + elif ptype in BTI.PROC_BPFILTER: + this_step["high_freq"] = read_float(fid) + this_step["low_freq"] = read_float(fid) + else: + jump = this_step["user_space_size"] = read_int32(fid) + fid.seek(32, 1) + fid.seek(jump, 1) + + out["processing_steps"] += [this_step] + _correct_offset(fid) + + return out + + +def _read_assoc_file(fid): + """Read BTi PDF assocfile.""" + out = {"file_id": read_int16(fid), "length": read_int16(fid)} + + fid.seek(32, 1) + out["checksum"] = read_int32(fid) + + return out + + +def _read_pfid_ed(fid): + """Read PDF ed file.""" + out = {"comment_size": read_int32(fid), "name": read_str(fid, 17)} + + fid.seek(9, 1) + out.update( + { + "pdf_number": read_int16(fid), + "total_events": read_int32(fid), + "timestamp": read_int32(fid), + "flags": read_int32(fid), + "de_process": read_int32(fid), + "checksum": read_int32(fid), + "ed_id": read_int32(fid), + "win_width": read_float(fid), + "win_offset": read_float(fid), + } + ) + + fid.seek(8, 1) + + return out + + +def _read_bti_header_pdf(pdf_fname): + """Read header from pdf file.""" + with _bti_open(pdf_fname, "rb") as fid: + fid.seek(-8, 2) + start = fid.tell() + header_position = read_int64(fid) + check_value = header_position & BTI.FILE_MASK + + if (start + BTI.FILE_CURPOS - check_value) <= BTI.FILE_MASK: + header_position = check_value + + # Check header position for alignment issues + if (header_position % 8) != 0: + header_position += 8 - (header_position % 8) + + fid.seek(header_position, 0) + + # actual header starts here + info = { + "version": read_int16(fid), + "file_type": read_str(fid, 5), + "hdr_size": start - header_position, # add for convenience + "start": start, + } + + fid.seek(1, 1) + + info.update( + { + "data_format": read_int16(fid), + "acq_mode": read_int16(fid), + "total_epochs": read_int32(fid), + "input_epochs": read_int32(fid), + "total_events": read_int32(fid), + "total_fixed_events": read_int32(fid), + "sample_period": read_float(fid), + "xaxis_label": read_str(fid, 16), + "total_processes": read_int32(fid), + "total_chans": read_int16(fid), + } + ) + + fid.seek(2, 1) + info.update( + { + "checksum": read_int32(fid), + "total_ed_classes": read_int32(fid), + "total_associated_files": read_int16(fid), + "last_file_index": read_int16(fid), + "timestamp": read_int32(fid), + } + ) + + fid.seek(20, 1) + _correct_offset(fid) + + # actual header ends here, so dar seems ok. + + info["epochs"] = [_read_epoch(fid) for _ in range(info["total_epochs"])] + + info["chs"] = [_read_channel(fid) for _ in range(info["total_chans"])] + + info["events"] = [_read_event(fid) for _ in range(info["total_events"])] + + info["processes"] = [_read_process(fid) for _ in range(info["total_processes"])] + + info["assocfiles"] = [ + _read_assoc_file(fid) for _ in range(info["total_associated_files"]) + ] + + info["edclasses"] = [ + _read_pfid_ed(fid) for _ in range(info["total_ed_classes"]) + ] + + info["extra_data"] = fid.read(start - fid.tell()) + info["pdf"] = pdf_fname + + info["total_slices"] = sum(e["pts_in_epoch"] for e in info["epochs"]) + + info["dtype"] = DTYPES[info["data_format"]] + bps = info["dtype"].itemsize * info["total_chans"] + info["bytes_per_slice"] = bps + return info + + +def _read_bti_header(pdf_fname, config_fname, sort_by_ch_name=True): + """Read bti PDF header.""" + info = _read_bti_header_pdf(pdf_fname) if pdf_fname is not None else dict() + cfg = _read_config(config_fname) + info["bti_transform"] = cfg["transforms"] + + # augment channel list by according info from config. + # get channels from config present in PDF + chans = info.get("chs", None) + if chans is not None: + chans_cfg = [ + c for c in cfg["chs"] if c["chan_no"] in [c_["chan_no"] for c_ in chans] + ] + + # sort chans_cfg and chans + chans = sorted(chans, key=lambda k: k["chan_no"]) + chans_cfg = sorted(chans_cfg, key=lambda k: k["chan_no"]) + + # check all pdf channels are present in config + match = [c["chan_no"] for c in chans_cfg] == [c["chan_no"] for c in chans] + + if not match: + raise RuntimeError( + "Could not match raw data channels with" + " config channels. Some of the channels" + " found are not described in config." + ) + else: + chans_cfg = cfg["chs"] + chans = [dict() for _ in chans_cfg] + + # transfer channel info from config to channel info + for ch, ch_cfg in zip(chans, chans_cfg): + ch["upb"] = ch_cfg["units_per_bit"] + ch["gain"] = ch_cfg["gain"] + ch["name"] = ch_cfg["name"] + if ch_cfg.get("dev", dict()).get("transform", None) is not None: + ch["loc"] = _coil_trans_to_loc(ch_cfg["dev"]["transform"]) + else: + ch["loc"] = np.full(12, np.nan) + if pdf_fname is not None: + if info["data_format"] <= 2: # see DTYPES, implies integer + ch["cal"] = ch["scale"] * ch["upb"] / float(ch["gain"]) + else: # float + ch["cal"] = ch["scale"] * ch["gain"] + else: # if we are in this mode we don't read data, only channel info. + ch["cal"] = ch["scale"] = 1.0 # so we put a trivial default value + + if sort_by_ch_name: + by_index = [(i, d["index"]) for i, d in enumerate(chans)] + by_index.sort(key=lambda c: c[1]) + by_index = [idx[0] for idx in by_index] + chs = [chans[pos] for pos in by_index] + + sort_by_name_idx = [(i, d["name"]) for i, d in enumerate(chs)] + a_chs = [c for c in sort_by_name_idx if c[1].startswith("A")] + other_chs = [c for c in sort_by_name_idx if not c[1].startswith("A")] + sort_by_name_idx = sorted(a_chs, key=lambda c: int(c[1][1:])) + sorted( + other_chs + ) + + sort_by_name_idx = [idx[0] for idx in sort_by_name_idx] + + info["chs"] = [chans[pos] for pos in sort_by_name_idx] + info["order"] = sort_by_name_idx + else: + info["chs"] = chans + info["order"] = np.arange(len(chans)) + + # finally add some important fields from the config + info["e_table"] = cfg["user_blocks"][BTI.UB_B_E_TABLE_USED] + info["weights"] = cfg["user_blocks"][BTI.UB_B_WEIGHTS_USED] + + return info + + +def _correct_trans(t, check=True): + """Convert to a transformation matrix.""" + t = np.array(t, np.float64) + t[:3, :3] *= t[3, :3][:, np.newaxis] # apply scalings + t[3, :3] = 0.0 # remove them + if check: + assert t[3, 3] == 1.0 + else: + t[3, 3] = 1.0 + return t + + +class RawBTi(BaseRaw): + """Raw object from 4D Neuroimaging MagnesWH3600 data. + + Parameters + ---------- + pdf_fname : path-like + Path to the processed data file (PDF). + config_fname : path-like + Path to system config file. + head_shape_fname : path-like | None + Path to the head shape file. + rotation_x : float + Degrees to tilt x-axis for sensor frame misalignment. Ignored + if convert is True. + translation : array-like, shape (3,) + The translation to place the origin of coordinate system + to the center of the head. Ignored if convert is True. + convert : bool + Convert to Neuromag coordinates or not. + rename_channels : bool + Whether to keep original 4D channel labels or not. Defaults to True. + sort_by_ch_name : bool + Reorder channels according to channel label. 4D channels don't have + monotonically increasing numbers in their labels. Defaults to True. + ecg_ch : str | None + The 4D name of the ECG channel. If None, the channel will be treated + as regular EEG channel. + eog_ch : tuple of str | None + The 4D names of the EOG channels. If None, the channels will be treated + as regular EEG channels. + %(preload)s + + .. versionadded:: 0.11 + + %(verbose)s + """ + + @verbose + def __init__( + self, + pdf_fname, + config_fname="config", + head_shape_fname="hs_file", + rotation_x=0.0, + translation=(0.0, 0.02, 0.11), + convert=True, + rename_channels=True, + sort_by_ch_name=True, + ecg_ch="E31", + eog_ch=("E63", "E64"), + preload=False, + verbose=None, + ): + _validate_type(pdf_fname, ("path-like", BytesIO), "pdf_fname") + info, bti_info = _get_bti_info( + pdf_fname=pdf_fname, + config_fname=config_fname, + head_shape_fname=head_shape_fname, + rotation_x=rotation_x, + translation=translation, + convert=convert, + ecg_ch=ecg_ch, + rename_channels=rename_channels, + sort_by_ch_name=sort_by_ch_name, + eog_ch=eog_ch, + ) + bti_info["bti_ch_labels"] = [c["chan_label"] for c in bti_info["chs"]] + # make Raw repr work if we have a BytesIO as input + filename = bti_info["pdf"] + if isinstance(filename, BytesIO): + filename = None + super().__init__( + info, + preload, + filenames=[filename], + raw_extras=[bti_info], + last_samps=[bti_info["total_slices"] - 1], + verbose=verbose, + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a segment of data from a file.""" + bti_info = self._raw_extras[fi] + fname_or_bytes = bti_info["pdf"] + dtype = bti_info["dtype"] + assert len(bti_info["chs"]) == self._raw_extras[fi]["orig_nchan"] + n_channels = len(bti_info["chs"]) + n_bytes = np.dtype(dtype).itemsize + data_left = (stop - start) * n_channels + read_cals = np.empty((bti_info["total_chans"],)) + for ch in bti_info["chs"]: + read_cals[ch["index"]] = ch["cal"] + + block_size = ((int(100e6) // n_bytes) // n_channels) * n_channels + block_size = min(data_left, block_size) + # extract data in chunks + with _bti_open(fname_or_bytes, "rb") as fid: + fid.seek(bti_info["bytes_per_slice"] * start, 0) + for sample_start in np.arange(0, data_left, block_size) // n_channels: + count = min(block_size, data_left - sample_start * n_channels) + if isinstance(fid, BytesIO): + block = np.frombuffer(fid.getvalue(), dtype, count) + else: + block = np.fromfile(fid, dtype, count) + sample_stop = sample_start + count // n_channels + shape = (sample_stop - sample_start, bti_info["total_chans"]) + block = _reshape_view(block, shape) + data_view = data[:, sample_start:sample_stop] + one = np.empty(block.shape[::-1]) + + for ii, b_i_o in enumerate(bti_info["order"]): + one[ii] = block[:, b_i_o] * read_cals[b_i_o] + _mult_cal_one(data_view, one, idx, cals, mult) + + +@functools.lru_cache(1) +def _1020_names(): + from mne.channels import make_standard_montage + + return set( + ch_name.lower() for ch_name in make_standard_montage("standard_1005").ch_names + ) + + +def _eeg_like(ch_name): + # Some bti recordigs look like "F4-POz", so let's at least mark them + # as EEG + if ch_name.count("-") != 1: + return + ch, ref = ch_name.split("-") + eeg_names = _1020_names() + return ch.lower() in eeg_names and ref.lower() in eeg_names + + +def _make_bti_digitization( + info, head_shape_fname, convert, use_hpi, bti_dev_t, dev_ctf_t +): + with info._unlock(): + if head_shape_fname: + logger.info(f"... Reading digitization points from {head_shape_fname}") + + nasion, lpa, rpa, hpi, dig_points = _read_head_shape(head_shape_fname) + info["dig"], dev_head_t, ctf_head_t = _make_bti_dig_points( + nasion, + lpa, + rpa, + hpi, + dig_points, + convert, + use_hpi, + bti_dev_t, + dev_ctf_t, + ) + else: + logger.info("... no headshape file supplied, doing nothing.") + info["dig"] = None + dev_head_t = Transform("meg", "head", trans=None) + ctf_head_t = Transform("ctf_head", "head", trans=None) + + info.update(dev_head_t=dev_head_t, dev_ctf_t=dev_ctf_t, ctf_head_t=ctf_head_t) + + return info + + +def _get_bti_info( + pdf_fname, + config_fname, + head_shape_fname, + rotation_x, + translation, + convert, + ecg_ch, + eog_ch, + rename_channels=True, + sort_by_ch_name=True, +): + """Read BTI info. + + Note. This helper supports partial construction of infos when `pdf_fname` + is None. Some datasets, such as the HCP, are shipped as a large collection + of zipped files where it can be more efficient to only read the needed + information. In such a situation, some information can neither be accessed + directly nor guessed based on the `config`. + + These fields will thus be set to None: + - 'lowpass' + - 'highpass' + - 'sfreq' + - 'meas_date' + + """ + if pdf_fname is None: + logger.info("No pdf_fname passed, trying to construct partial info from config") + if pdf_fname is not None and not isinstance(pdf_fname, BytesIO): + if not op.isabs(pdf_fname): + pdf_fname = op.abspath(pdf_fname) + + if not isinstance(config_fname, BytesIO): + if not op.isabs(config_fname): + config_tries = [ + op.abspath(config_fname), + op.abspath(op.join(op.dirname(pdf_fname), config_fname)), + ] + for config_try in config_tries: + if op.isfile(config_try): + config_fname = config_try + break + if not op.isfile(config_fname): + raise ValueError( + f"Could not find the config file {config_fname}. Please check" + " whether you are in the right directory " + "or pass the full name" + ) + + if head_shape_fname is not None and not isinstance(head_shape_fname, BytesIO): + orig_name = head_shape_fname + if not op.isfile(head_shape_fname): + head_shape_fname = op.join(op.dirname(pdf_fname), head_shape_fname) + + if not op.isfile(head_shape_fname): + raise ValueError( + f'Could not find the head_shape file "{orig_name}". ' + "You should check whether you are in the " + "right directory, pass the full file name, " + "or pass head_shape_fname=None." + ) + + logger.info(f"Reading 4D PDF file {pdf_fname}...") + bti_info = _read_bti_header( + pdf_fname, config_fname, sort_by_ch_name=sort_by_ch_name + ) + extras = dict( + pdf_fname=pdf_fname, + head_shape_fname=head_shape_fname, + config_fname=config_fname, + ) + for key, val in extras.items(): + bti_info[key] = None if isinstance(val, BytesIO) else val + + dev_ctf_t = Transform( + "ctf_meg", "ctf_head", _correct_trans(bti_info["bti_transform"][0]) + ) + + _check_nan_dev_head_t(dev_ctf_t) + # for old backward compatibility and external processing + rotation_x = 0.0 if rotation_x is None else rotation_x + bti_dev_t = _get_bti_dev_t(rotation_x, translation) if convert else None + bti_dev_t = Transform("ctf_meg", "meg", bti_dev_t) + + use_hpi = False # hard coded, but marked as later option. + logger.info("Creating Neuromag info structure ...") + if "sample_period" in bti_info.keys(): + sfreq = 1.0 / bti_info["sample_period"] + else: + sfreq = None + + if pdf_fname is not None: + info = _empty_info(sfreq) + date = bti_info["processes"][0]["timestamp"] + info["meas_date"] = _stamp_to_dt((date, 0)) + else: # these cannot be guessed from config, see docstring + info = _empty_info(1.0) + info["sfreq"] = None + info["lowpass"] = None + info["highpass"] = None + info["meas_date"] = None + bti_info["processes"] = list() + + # browse processing info for filter specs. + hp, lp = info["highpass"], info["lowpass"] + for proc in bti_info["processes"]: + if "filt" in proc["process_type"]: + for step in proc["processing_steps"]: + if "high_freq" in step: + hp, lp = step["high_freq"], step["low_freq"] + elif "hp" in step["process_type"]: + hp = step["freq"] + elif "lp" in step["process_type"]: + lp = step["freq"] + + info["highpass"] = hp + info["lowpass"] = lp + chs = [] + + # Note that 'name' and 'chan_label' are not the same. + # We want the configured label if out IO parsed it + # except for the MEG channels for which we keep the config name + bti_ch_names = list() + for ch in bti_info["chs"]: + # we have always relied on 'A' as indicator of MEG data channels. + ch_name = ch["name"] + if not ch_name.startswith("A"): + ch_name = ch.get("chan_label", ch_name) + bti_ch_names.append(ch_name) + + neuromag_ch_names = _rename_channels(bti_ch_names, ecg_ch=ecg_ch, eog_ch=eog_ch) + ch_mapping = zip(bti_ch_names, neuromag_ch_names) + + logger.info("... Setting channel info structure.") + for idx, (chan_4d, chan_neuromag) in enumerate(ch_mapping): + chan_info = _instantiate_default_info_chs() + chan_info["ch_name"] = chan_neuromag if rename_channels else chan_4d + chan_info["logno"] = idx + BTI.FIFF_LOGNO + chan_info["scanno"] = idx + 1 + chan_info["cal"] = float(bti_info["chs"][idx]["scale"]) + + if any(chan_4d.startswith(k) for k in ("A", "M", "G")): + loc = bti_info["chs"][idx]["loc"] + if loc is not None: + if convert: + if idx == 0: + logger.info( + "... putting coil transforms in Neuromag coordinates" + ) + t = _loc_to_coil_trans(bti_info["chs"][idx]["loc"]) + t = _convert_coil_trans(t, dev_ctf_t, bti_dev_t) + loc = _coil_trans_to_loc(t) + chan_info["loc"] = loc + + # BTI sensors are natively stored in 4D head coords we believe + meg_frame = FIFF.FIFFV_COORD_DEVICE if convert else FIFF.FIFFV_MNE_COORD_4D_HEAD + eeg_frame = FIFF.FIFFV_COORD_HEAD if convert else FIFF.FIFFV_MNE_COORD_4D_HEAD + if chan_4d.startswith("A"): + chan_info["kind"] = FIFF.FIFFV_MEG_CH + chan_info["coil_type"] = FIFF.FIFFV_COIL_MAGNES_MAG + chan_info["coord_frame"] = meg_frame + chan_info["unit"] = FIFF.FIFF_UNIT_T + + elif chan_4d.startswith("M"): + chan_info["kind"] = FIFF.FIFFV_REF_MEG_CH + chan_info["coil_type"] = FIFF.FIFFV_COIL_MAGNES_REF_MAG + chan_info["coord_frame"] = meg_frame + chan_info["unit"] = FIFF.FIFF_UNIT_T + + elif chan_4d.startswith("G"): + chan_info["kind"] = FIFF.FIFFV_REF_MEG_CH + chan_info["coord_frame"] = meg_frame + chan_info["unit"] = FIFF.FIFF_UNIT_T_M + if chan_4d in ("GxxA", "GyyA"): + chan_info["coil_type"] = FIFF.FIFFV_COIL_MAGNES_REF_GRAD + elif chan_4d in ("GyxA", "GzxA", "GzyA"): + chan_info["coil_type"] = FIFF.FIFFV_COIL_MAGNES_OFFDIAG_REF_GRAD + + elif chan_4d.startswith("EEG") or _eeg_like(chan_4d): + chan_info["kind"] = FIFF.FIFFV_EEG_CH + chan_info["coil_type"] = FIFF.FIFFV_COIL_EEG + chan_info["coord_frame"] = eeg_frame + chan_info["unit"] = FIFF.FIFF_UNIT_V + # TODO: We should use 'electrodes' to fill this in, and make sure + # we turn them into dig as well + chan_info["loc"][:3] = np.nan + + elif chan_4d == "RESPONSE": + chan_info["kind"] = FIFF.FIFFV_STIM_CH + elif chan_4d == "TRIGGER": + chan_info["kind"] = FIFF.FIFFV_STIM_CH + elif ( + chan_4d.startswith("EOG") + or chan_4d[:4] in ("HEOG", "VEOG") + or chan_4d in eog_ch + ): + chan_info["kind"] = FIFF.FIFFV_EOG_CH + elif chan_4d.startswith("EMG"): + chan_info["kind"] = FIFF.FIFFV_EMG_CH + elif chan_4d == ecg_ch or chan_4d.startswith("ECG"): + chan_info["kind"] = FIFF.FIFFV_ECG_CH + # Our default is now misc, but if we ever change that, + # we'll need this: + # elif chan_4d.startswith('X') or chan_4d == 'UACurrent': + # chan_info['kind'] = FIFF.FIFFV_MISC_CH + + chs.append(chan_info) + + info["chs"] = chs + + # ### Dig stuff + info = _make_bti_digitization( + info, head_shape_fname, convert, use_hpi, bti_dev_t, dev_ctf_t + ) + + logger.info( + "Currently direct inclusion of 4D weight tables is not supported." + " For critical use cases please take into account the MNE command" + ' "mne_create_comp_data" to include weights as printed out by ' + 'the 4D "print_table" routine.' + ) + + # check that the info is complete + info._unlocked = False + info._update_redundant() + info._check_consistency() + return info, bti_info + + +@verbose +def read_raw_bti( + pdf_fname, + config_fname="config", + head_shape_fname="hs_file", + rotation_x=0.0, + translation=(0.0, 0.02, 0.11), + convert=True, + rename_channels=True, + sort_by_ch_name=True, + ecg_ch="E31", + eog_ch=("E63", "E64"), + preload=False, + verbose=None, +) -> RawBTi: + """Raw object from 4D Neuroimaging MagnesWH3600 data. + + .. note:: + 1. Currently direct inclusion of reference channel weights + is not supported. Please use ``mne_create_comp_data`` to include + the weights or use the low level functions from this module to + include them by yourself. + 2. The informed guess for the 4D name is E31 for the ECG channel and + E63, E63 for the EOG channels. Please check and adjust if those + channels are present in your dataset but 'ECG 01' and 'EOG 01', + 'EOG 02' don't appear in the channel names of the raw object. + + Parameters + ---------- + pdf_fname : path-like + Path to the processed data file (PDF). + config_fname : path-like + Path to system config file. + head_shape_fname : path-like | None + Path to the head shape file. + rotation_x : float + Degrees to tilt x-axis for sensor frame misalignment. Ignored + if convert is True. + translation : array-like, shape (3,) + The translation to place the origin of coordinate system + to the center of the head. Ignored if convert is True. + convert : bool + Convert to Neuromag coordinates or not. + rename_channels : bool + Whether to keep original 4D channel labels or not. Defaults to True. + sort_by_ch_name : bool + Reorder channels according to channel label. 4D channels don't have + monotonically increasing numbers in their labels. Defaults to True. + ecg_ch : str | None + The 4D name of the ECG channel. If None, the channel will be treated + as regular EEG channel. + eog_ch : tuple of str | None + The 4D names of the EOG channels. If None, the channels will be treated + as regular EEG channels. + %(preload)s + + .. versionadded:: 0.11 + %(verbose)s + + Returns + ------- + raw : instance of RawBTi + A Raw object containing BTI data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawBTi. + """ + return RawBTi( + pdf_fname, + config_fname=config_fname, + head_shape_fname=head_shape_fname, + rotation_x=rotation_x, + translation=translation, + convert=convert, + rename_channels=rename_channels, + sort_by_ch_name=sort_by_ch_name, + ecg_ch=ecg_ch, + eog_ch=eog_ch, + preload=preload, + verbose=verbose, + ) diff --git a/mne-python/source/mne/io/bti/constants.py b/mne-python/source/mne/io/bti/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..d135dae6e601b3e80d83128996f3c5cc5fcd807e --- /dev/null +++ b/mne-python/source/mne/io/bti/constants.py @@ -0,0 +1,99 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import BunchConst + +BTI = BunchConst() + +BTI.ELEC_STATE_NOT_COLLECTED = 0 +BTI.ELEC_STATE_COLLECTED = 1 +BTI.ELEC_STATE_SKIPPED = 2 +BTI.ELEC_STATE_NOT_APPLICABLE = 3 +# +## Byte offesets and data sizes for different files +# +BTI.FILE_MASK = 2147483647 +BTI.FILE_CURPOS = 8 +BTI.FILE_END = -8 + +BTI.FILE_HS_VERSION = 0 +BTI.FILE_HS_TIMESTAMP = 4 +BTI.FILE_HS_CHECKSUM = 8 +BTI.FILE_HS_N_DIGPOINTS = 12 +BTI.FILE_HS_N_INDEXPOINTS = 16 + +BTI.FILE_PDF_H_ENTER = 1 +BTI.FILE_PDF_H_FTYPE = 5 +BTI.FILE_PDF_H_XLABEL = 16 +BTI.FILE_PDF_H_NEXT = 2 +BTI.FILE_PDF_H_EXIT = 20 + +BTI.FILE_PDF_EPOCH_EXIT = 28 + +BTI.FILE_PDF_CH_NEXT = 6 +BTI.FILE_PDF_CH_LABELSIZE = 16 +BTI.FILE_PDF_CH_YLABEL = 16 +BTI.FILE_PDF_CH_OFF_FLAG = 16 +BTI.FILE_PDF_CH_EXIT = 12 + +BTI.FILE_PDF_EVENT_NAME = 16 +BTI.FILE_PDF_EVENT_EXIT = 32 + +BTI.FILE_PDF_PROCESS_BLOCKTYPE = 20 +BTI.FILE_PDF_PROCESS_USER = 32 +BTI.FILE_PDF_PROCESS_FNAME = 256 +BTI.FILE_PDF_PROCESS_EXIT = 32 + +BTI.FILE_PDF_ASSOC_NEXT = 32 + +BTI.FILE_PDFED_NAME = 17 +BTI.FILE_PDFED_NEXT = 9 +BTI.FILE_PDFED_EXIT = 8 + +# +## General data constants +# +BTI.DATA_N_IDX_POINTS = 5 +BTI.DATA_ROT_N_ROW = 3 +BTI.DATA_ROT_N_COL = 3 +BTI.DATA_XFM_N_COL = 4 +BTI.DATA_XFM_N_ROW = 4 +BTI.FIFF_LOGNO = 111 +# +## Channel Types +# +BTI.CHTYPE_MEG = 1 +BTI.CHTYPE_EEG = 2 +BTI.CHTYPE_REFERENCE = 3 +BTI.CHTYPE_EXTERNAL = 4 +BTI.CHTYPE_TRIGGER = 5 +BTI.CHTYPE_UTILITY = 6 +BTI.CHTYPE_DERIVED = 7 +BTI.CHTYPE_SHORTED = 8 +# +## Processes +# +BTI.PROC_DEFAULTS = "BTi_defaults" +BTI.PROC_FILTER = "b_filt_hp,b_filt_lp,b_filt_notch" +BTI.PROC_BPFILTER = "b_filt_b_pass,b_filt_b_reject" +# +## User blocks +# +BTI.UB_B_MAG_INFO = "B_Mag_Info" +BTI.UB_B_COH_POINTS = "B_COH_Points" +BTI.UB_B_CCP_XFM_BLOCK = "b_ccp_xfm_block" +BTI.UB_B_EEG_LOCS = "b_eeg_elec_locs" +BTI.UB_B_WHC_CHAN_MAP_VER = "B_WHChanMapVer" +BTI.UB_B_WHC_CHAN_MAP = "B_WHChanMap" +BTI.UB_B_WHS_SUBSYS_VER = "B_WHSubsysVer" # B_WHSubsysVer +BTI.UB_B_WHS_SUBSYS = "B_WHSubsys" +BTI.UB_B_CH_LABELS = "B_ch_labels" +BTI.UB_B_CALIBRATION = "B_Calibration" +BTI.UB_B_SYS_CONFIG_TIME = "B_SysConfigTime" +BTI.UB_B_DELTA_ENABLED = "B_DELTA_ENABLED" +BTI.UB_B_E_TABLE_USED = "B_E_table_used" +BTI.UB_B_E_TABLE = "B_E_TABLE" +BTI.UB_B_WEIGHTS_USED = "B_weights_used" +BTI.UB_B_TRIG_MASK = "B_trig_mask" +BTI.UB_B_WEIGHT_TABLE = "BWT_" diff --git a/mne-python/source/mne/io/bti/read.py b/mne-python/source/mne/io/bti/read.py new file mode 100644 index 0000000000000000000000000000000000000000..abf4b72cd9ef7c5de2e982b9318e065af5e4b8ae --- /dev/null +++ b/mne-python/source/mne/io/bti/read.py @@ -0,0 +1,98 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ..._fiff.utils import read_str + + +def _unpack_matrix(fid, rows, cols, dtype, out_dtype): + """Unpack matrix.""" + dtype = np.dtype(dtype) + + string = fid.read(int(dtype.itemsize * rows * cols)) + out = np.frombuffer(string, dtype=dtype).reshape(rows, cols).astype(out_dtype) + return out + + +def _unpack_simple(fid, dtype, out_dtype): + """Unpack a NumPy type.""" + dtype = np.dtype(dtype) + string = fid.read(dtype.itemsize) + out = np.frombuffer(string, dtype=dtype).astype(out_dtype) + + if len(out) > 0: + out = out[0] + return out + + +def read_char(fid, count=1): + """Read character from bti file.""" + return _unpack_simple(fid, f">S{count}", "S") + + +def read_uint16(fid): + """Read unsigned 16bit integer from bti file.""" + return _unpack_simple(fid, ">u2", np.uint32) + + +def read_int16(fid): + """Read 16bit integer from bti file.""" + return _unpack_simple(fid, ">i2", np.int32) + + +def read_uint32(fid): + """Read unsigned 32bit integer from bti file.""" + return _unpack_simple(fid, ">u4", np.uint32) + + +def read_int32(fid): + """Read 32bit integer from bti file.""" + return _unpack_simple(fid, ">i4", np.int32) + + +def read_int64(fid): + """Read 64bit integer from bti file.""" + return _unpack_simple(fid, ">u8", np.int64) + + +def read_float(fid): + """Read 32bit float from bti file.""" + return _unpack_simple(fid, ">f4", np.float32) + + +def read_double(fid): + """Read 64bit float from bti file.""" + return _unpack_simple(fid, ">f8", np.float64) + + +def read_int16_matrix(fid, rows, cols): + """Read 16bit integer matrix from bti file.""" + return _unpack_matrix( + fid, + rows, + cols, + dtype=">i2", + out_dtype=np.int32, + ) + + +def read_float_matrix(fid, rows, cols): + """Read 32bit float matrix from bti file.""" + return _unpack_matrix(fid, rows, cols, dtype=">f4", out_dtype=np.float32) + + +def read_double_matrix(fid, rows, cols): + """Read 64bit float matrix from bti file.""" + return _unpack_matrix(fid, rows, cols, dtype=">f8", out_dtype=np.float64) + + +def read_transform(fid): + """Read 64bit float matrix transform from bti file.""" + return read_double_matrix(fid, rows=4, cols=4) + + +def read_dev_header(x): + """Create a dev header.""" + return dict(size=read_int32(x), checksum=read_int32(x), reserved=read_str(x, 32)) diff --git a/mne-python/source/mne/io/bti/tests/__init__.py b/mne-python/source/mne/io/bti/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/bti/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/bti/tests/data/exported4D_linux_raw.fif b/mne-python/source/mne/io/bti/tests/data/exported4D_linux_raw.fif new file mode 100644 index 0000000000000000000000000000000000000000..8e7b5818327b07eef09d60848416cc71fef8139e --- /dev/null +++ b/mne-python/source/mne/io/bti/tests/data/exported4D_linux_raw.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd85e96e049a526e503bfc3cb5e0cf40abe1b24a0922fec2fcf1d72821c79e58 +size 523296 diff --git a/mne-python/source/mne/io/bti/tests/data/exported4D_solaris_raw.fif b/mne-python/source/mne/io/bti/tests/data/exported4D_solaris_raw.fif new file mode 100644 index 0000000000000000000000000000000000000000..b6a50c256fc404eda2c05504ab3517d60c816aff --- /dev/null +++ b/mne-python/source/mne/io/bti/tests/data/exported4D_solaris_raw.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66a178085814e52c8bd4dcec27ccbd059a13587453d492dbbc1e2d5b2eba9731 +size 987548 diff --git a/mne-python/source/mne/io/bti/tests/data/test_config_linux b/mne-python/source/mne/io/bti/tests/data/test_config_linux new file mode 100644 index 0000000000000000000000000000000000000000..533bff1b2474fe7bbb65a8b62fd87d3c2b701ea0 --- /dev/null +++ b/mne-python/source/mne/io/bti/tests/data/test_config_linux @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:60e8c2128cc1ea96b648268b458598ccc965aad847edbc0c8f59dde6fc1006d9 +size 194296 diff --git a/mne-python/source/mne/io/bti/tests/data/test_config_solaris b/mne-python/source/mne/io/bti/tests/data/test_config_solaris new file mode 100644 index 0000000000000000000000000000000000000000..32f4dbb3d5ed86566dbf5ee7a5e6516aed77c4be --- /dev/null +++ b/mne-python/source/mne/io/bti/tests/data/test_config_solaris @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9d6d98d2e77c31e37f29541e97cb9f81fc3810ad22b085f57eb3a5c6009a9539 +size 193616 diff --git a/mne-python/source/mne/io/bti/tests/data/test_hs_linux b/mne-python/source/mne/io/bti/tests/data/test_hs_linux new file mode 100644 index 0000000000000000000000000000000000000000..f59a04cdc45efd5bfaa2465c5b78b54a7256acb4 Binary files /dev/null and b/mne-python/source/mne/io/bti/tests/data/test_hs_linux differ diff --git a/mne-python/source/mne/io/bti/tests/data/test_hs_solaris b/mne-python/source/mne/io/bti/tests/data/test_hs_solaris new file mode 100644 index 0000000000000000000000000000000000000000..21b14e9416fd86c5e92ddf631a056ac199ba2a09 --- /dev/null +++ b/mne-python/source/mne/io/bti/tests/data/test_hs_solaris @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7429d3f9c3b108e6d572a9cabcf40083d6f8df93ef079a3658ac9262c1f5d148 +size 123760 diff --git a/mne-python/source/mne/io/bti/tests/data/test_pdf_linux b/mne-python/source/mne/io/bti/tests/data/test_pdf_linux new file mode 100644 index 0000000000000000000000000000000000000000..4c007548f9aa95e2098c0936a8f8dc70f4cd7be7 --- /dev/null +++ b/mne-python/source/mne/io/bti/tests/data/test_pdf_linux @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:501633131c69d178584bbd83e41a19553a583e42fb8a75b2de16f60995fe8fab +size 201448 diff --git a/mne-python/source/mne/io/bti/tests/data/test_pdf_solaris b/mne-python/source/mne/io/bti/tests/data/test_pdf_solaris new file mode 100644 index 0000000000000000000000000000000000000000..728776fbf9d6eef5b06af441ae83c7164b9f2955 --- /dev/null +++ b/mne-python/source/mne/io/bti/tests/data/test_pdf_solaris @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1e8d90b4e26a583849db88266488e44a0919c5101774e9b14e5f7ce42cd5194 +size 781560 diff --git a/mne-python/source/mne/io/bti/tests/test_bti.py b/mne-python/source/mne/io/bti/tests/test_bti.py new file mode 100644 index 0000000000000000000000000000000000000000..cc595833275ead688b2ccec2c1f93b905e230de0 --- /dev/null +++ b/mne-python/source/mne/io/bti/tests/test_bti.py @@ -0,0 +1,499 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +from collections import Counter +from functools import partial, reduce +from io import BytesIO +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_equal, +) + +import mne +from mne import pick_info, pick_types +from mne._fiff._digitization import _make_bti_dig_points +from mne._fiff.constants import FIFF +from mne.datasets import testing +from mne.io import read_raw_bti, read_raw_fif +from mne.io.bti.bti import ( + _check_nan_dev_head_t, + _convert_coil_trans, + _correct_trans, + _get_bti_dev_t, + _get_bti_info, + _loc_to_coil_trans, + _read_bti_header, + _read_config, + _read_head_shape, + _rename_channels, +) +from mne.io.tests.test_raw import _test_raw_reader +from mne.transforms import Transform, combine_transforms, invert_transform +from mne.utils import assert_dig_allclose + +base_dir = Path(__file__).parent / "data" + +archs = "linux", "solaris" +pdf_fnames = [base_dir / f"test_pdf_{a}" for a in archs] +config_fnames = [base_dir / f"test_config_{a}" for a in archs] +hs_fnames = [base_dir / f"test_hs_{a}" for a in archs] +exported_fnames = [base_dir / f"exported4D_{a}_raw.fif" for a in archs] +pdf_config_hs_exporteds = list( + zip(pdf_fnames, config_fnames, hs_fnames, exported_fnames) +) + +testing_path_bti = testing.data_path(download=False) / "BTi" +fname_2500 = testing_path_bti / "erm_HFH" / "c,rfDC" +fname_sim = testing_path_bti / "4Dsim" / "c,rfDC" +fname_sim_filt = testing_path_bti / "4Dsim" / "c,rfDC,fn50,o" + +# the 4D exporter doesn't export all channels, so we confine our comparison +NCH = 248 + + +@testing.requires_testing_data +def test_read_2500(): + """Test reading data from 2500 system.""" + _test_raw_reader(read_raw_bti, pdf_fname=fname_2500, head_shape_fname=None) + + +def test_no_loc_none(monkeypatch): + """Test that we don't set loc to None when no trans is found.""" + ch_name = "MLzA" + + def _read_config_bad(*args, **kwargs): + cfg = _read_config(*args, **kwargs) + idx = [ch["name"] for ch in cfg["chs"]].index(ch_name) + del cfg["chs"][idx]["dev"]["transform"] + return cfg + + monkeypatch.setattr(mne.io.bti.bti, "_read_config", _read_config_bad) + kwargs = dict( + pdf_fname=pdf_fnames[0], + config_fname=config_fnames[0], + head_shape_fname=hs_fnames[0], + rename_channels=False, + sort_by_ch_name=False, + ) + raw = read_raw_bti(**kwargs) + idx = raw.ch_names.index(ch_name) + assert_allclose(raw.info["chs"][idx]["loc"], np.full(12, np.nan)) + + +def test_read_config(): + """Test read bti config file.""" + # for config in config_fname, config_solaris_fname: + for config in config_fnames: + cfg = _read_config(config) + assert all( + "unknown" not in block.lower() and block != "" + for block in cfg["user_blocks"] + ) + + +def test_crop_append(): + """Test crop and append raw.""" + raw = _test_raw_reader( + read_raw_bti, + pdf_fname=pdf_fnames[0], + config_fname=config_fnames[0], + head_shape_fname=hs_fnames[0], + ) + y, t = raw[:] + t0, t1 = 0.25 * t[-1], 0.75 * t[-1] + mask = (t0 <= t) * (t <= t1) + raw_ = raw.copy().crop(t0, t1) + y_, _ = raw_[:] + assert y_.shape[1] == mask.sum() + assert y_.shape[0] == y.shape[0] + + +@pytest.mark.parametrize("pdf, config, hs, exported", pdf_config_hs_exporteds) +def test_transforms(pdf, config, hs, exported): + """Test transformations.""" + bti_trans = (0.0, 0.02, 0.11) + bti_dev_t = Transform("ctf_meg", "meg", _get_bti_dev_t(0.0, bti_trans)) + raw = read_raw_bti(pdf, config, hs, preload=False) + dev_ctf_t = raw.info["dev_ctf_t"] + dev_head_t_old = raw.info["dev_head_t"] + ctf_head_t = raw.info["ctf_head_t"] + + # 1) get BTI->Neuromag + bti_dev_t = Transform("ctf_meg", "meg", _get_bti_dev_t(0.0, bti_trans)) + + # 2) get Neuromag->BTI head + t = combine_transforms(invert_transform(bti_dev_t), dev_ctf_t, "meg", "ctf_head") + # 3) get Neuromag->head + dev_head_t_new = combine_transforms(t, ctf_head_t, "meg", "head") + + assert_array_equal(dev_head_t_new["trans"], dev_head_t_old["trans"]) + + +@pytest.mark.slowtest +@pytest.mark.parametrize("pdf, config, hs, exported", pdf_config_hs_exporteds) +def test_raw(pdf, config, hs, exported, tmp_path): + """Test bti conversion to Raw object.""" + # rx = 2 if 'linux' in pdf else 0 + pytest.raises(ValueError, read_raw_bti, pdf, "eggs", preload=False) + pytest.raises(ValueError, read_raw_bti, pdf, config, "spam", preload=False) + tmp_raw_fname = tmp_path / "tmp_raw.fif" + ex = read_raw_fif(exported, preload=True) + ra = read_raw_bti(pdf, config, hs, preload=False) + assert "RawBTi" in repr(ra) + assert_equal(ex.ch_names[:NCH], ra.ch_names[:NCH]) + assert_array_almost_equal( + ex.info["dev_head_t"]["trans"], ra.info["dev_head_t"]["trans"], 7 + ) + assert len(ex.info["dig"]) in (3563, 5154) + assert_dig_allclose(ex.info, ra.info, limit=100) + coil1, coil2 = ( + np.concatenate([d["loc"].flatten() for d in r_.info["chs"][:NCH]]) + for r_ in (ra, ex) + ) + assert_array_almost_equal(coil1, coil2, 7) + + loc1, loc2 = ( + np.concatenate([d["loc"].flatten() for d in r_.info["chs"][:NCH]]) + for r_ in (ra, ex) + ) + assert_allclose(loc1, loc2) + + assert_allclose(ra[:NCH][0], ex[:NCH][0]) + assert_array_equal( + [c["range"] for c in ra.info["chs"][:NCH]], + [c["range"] for c in ex.info["chs"][:NCH]], + ) + assert_array_equal( + [c["cal"] for c in ra.info["chs"][:NCH]], + [c["cal"] for c in ex.info["chs"][:NCH]], + ) + assert_array_equal(ra._cals[:NCH], ex._cals[:NCH]) + + # check our transforms + for key in ("dev_head_t", "dev_ctf_t", "ctf_head_t"): + if ex.info[key] is None: + pass + else: + assert ra.info[key] is not None + for ent in ("to", "from", "trans"): + assert_allclose(ex.info[key][ent], ra.info[key][ent]) + + # MNE-BIDS needs these + for key in ("pdf_fname", "config_fname", "head_shape_fname"): + assert os.path.isfile(ra._raw_extras[0][key]) + + ra.save(tmp_raw_fname) + re = read_raw_fif(tmp_raw_fname) + print(re) + for key in ("dev_head_t", "dev_ctf_t", "ctf_head_t"): + assert isinstance(re.info[key], dict) + this_t = re.info[key]["trans"] + assert_equal(this_t.shape, (4, 4)) + # check that matrix by is not identity + assert not np.allclose(this_t, np.eye(4)) + + +@pytest.mark.parametrize("pdf, config, hs, exported", pdf_config_hs_exporteds) +def test_info_no_rename_no_reorder_no_pdf(pdf, config, hs, exported): + """Test private renaming, reordering and partial construction option.""" + info, bti_info = _get_bti_info( + pdf_fname=pdf, + config_fname=config, + head_shape_fname=hs, + rotation_x=0.0, + translation=(0.0, 0.02, 0.11), + convert=False, + ecg_ch="E31", + eog_ch=("E63", "E64"), + rename_channels=False, + sort_by_ch_name=False, + ) + info2, bti_info = _get_bti_info( + pdf_fname=None, + config_fname=config, + head_shape_fname=hs, + rotation_x=0.0, + translation=(0.0, 0.02, 0.11), + convert=False, + ecg_ch="E31", + eog_ch=("E63", "E64"), + rename_channels=False, + sort_by_ch_name=False, + ) + + assert_equal(info["ch_names"], [ch["ch_name"] for ch in info["chs"]]) + assert_equal( + [n for n in info["ch_names"] if n.startswith("A")][:5], + ["A22", "A2", "A104", "A241", "A138"], + ) + assert_equal( + [n for n in info["ch_names"] if n.startswith("A")][-5:], + ["A133", "A158", "A44", "A134", "A216"], + ) + + info = pick_info(info, pick_types(info, meg=True, stim=True, resp=True)) + info2 = pick_info(info2, pick_types(info2, meg=True, stim=True, resp=True)) + + assert info["sfreq"] is not None + assert info["lowpass"] is not None + assert info["highpass"] is not None + assert info["meas_date"] is not None + + assert_equal(info2["sfreq"], None) + assert_equal(info2["lowpass"], None) + assert_equal(info2["highpass"], None) + assert_equal(info2["meas_date"], None) + + assert_equal(info["ch_names"], info2["ch_names"]) + assert_equal(info["ch_names"], info2["ch_names"]) + for key in ["dev_ctf_t", "dev_head_t", "ctf_head_t"]: + assert_array_equal(info[key]["trans"], info2[key]["trans"]) + + assert_array_equal( + np.array([ch["loc"] for ch in info["chs"]]), + np.array([ch["loc"] for ch in info2["chs"]]), + ) + + # just check reading data | corner case + raw1 = read_raw_bti( + pdf_fname=pdf, + config_fname=config, + head_shape_fname=None, + sort_by_ch_name=False, + preload=True, + ) + # just check reading data | corner case + raw2 = read_raw_bti( + pdf_fname=pdf, + config_fname=config, + head_shape_fname=None, + rename_channels=False, + sort_by_ch_name=True, + preload=True, + ) + + bti_ch_labels_1 = raw1._raw_extras[0]["bti_ch_labels"] + bti_ch_labels_2 = raw2._raw_extras[0]["bti_ch_labels"] + sort_idx = [bti_ch_labels_1.index(ch) for ch in bti_ch_labels_2] + raw1._data = raw1._data[sort_idx] + assert_array_equal(raw1._data, raw2._data) + assert_array_equal(bti_ch_labels_2, raw2.ch_names) + + +@pytest.mark.parametrize("pdf, config, hs, exported", pdf_config_hs_exporteds) +def test_no_conversion(pdf, config, hs, exported): + """Test bti no-conversion option.""" + get_info = partial( + _get_bti_info, + rotation_x=0.0, + translation=(0.0, 0.02, 0.11), + convert=False, + ecg_ch="E31", + eog_ch=("E63", "E64"), + rename_channels=False, + sort_by_ch_name=False, + ) + + raw_info, _ = get_info(pdf, config, hs, convert=False) + raw_info_con = read_raw_bti( + pdf_fname=pdf, + config_fname=config, + head_shape_fname=hs, + convert=True, + preload=False, + ).info + + pick_info( + raw_info_con, pick_types(raw_info_con, meg=True, ref_meg=True), copy=False + ) + pick_info(raw_info, pick_types(raw_info, meg=True, ref_meg=True), copy=False) + bti_info = _read_bti_header(pdf, config) + dev_ctf_t = _correct_trans(bti_info["bti_transform"][0]) + assert_array_equal(dev_ctf_t, raw_info["dev_ctf_t"]["trans"]) + assert_array_equal(raw_info["dev_head_t"]["trans"], np.eye(4)) + assert_array_equal(raw_info["ctf_head_t"]["trans"], np.eye(4)) + + nasion, lpa, rpa, hpi, dig_points = _read_head_shape(hs) + dig, t, _ = _make_bti_dig_points( + nasion, lpa, rpa, hpi, dig_points, convert=False, use_hpi=False + ) + + assert_array_equal(t["trans"], np.eye(4)) + + for ii, (old, new, con) in enumerate( + zip(dig, raw_info["dig"], raw_info_con["dig"]) + ): + assert_equal(old["ident"], new["ident"]) + assert_array_equal(old["r"], new["r"]) + assert not np.allclose(old["r"], con["r"]) + + if ii > 10: + break + + ch_map = {ch["chan_label"]: ch["loc"] for ch in bti_info["chs"]} + + for ii, ch_label in enumerate(raw_info["ch_names"]): + if not ch_label.startswith("A"): + continue + t1 = ch_map[ch_label] # correction already performed in bti_info + t2 = raw_info["chs"][ii]["loc"] + t3 = raw_info_con["chs"][ii]["loc"] + assert_allclose(t1, t2, atol=1e-15) + assert not np.allclose(t1, t3) + idx_a = raw_info_con["ch_names"].index("MEG 001") + idx_b = raw_info["ch_names"].index("A22") + assert_equal(raw_info_con["chs"][idx_a]["coord_frame"], FIFF.FIFFV_COORD_DEVICE) + assert_equal( + raw_info["chs"][idx_b]["coord_frame"], FIFF.FIFFV_MNE_COORD_4D_HEAD + ) + + +@pytest.mark.parametrize("pdf, config, hs, exported", pdf_config_hs_exporteds) +def test_bytes_io(pdf, config, hs, exported): + """Test bti bytes-io API.""" + raw = read_raw_bti(pdf, config, hs, convert=True, preload=False) + + with open(pdf, "rb") as fid: + pdf = BytesIO(fid.read()) + with open(config, "rb") as fid: + config = BytesIO(fid.read()) + with open(hs, "rb") as fid: + hs = BytesIO(fid.read()) + + raw2 = read_raw_bti(pdf, config, hs, convert=True, preload=False) + repr(raw2) + assert_array_equal(raw[:][0], raw2[:][0]) + + +@pytest.mark.parametrize("hs", hs_fnames) +def test_setup_headshape(hs): + """Test reading bti headshape.""" + nasion, lpa, rpa, hpi, dig_points = _read_head_shape(hs) + dig, t, _ = _make_bti_dig_points(nasion, lpa, rpa, hpi, dig_points) + + expected = {"kind", "ident", "r"} + found = set(reduce(lambda x, y: list(x) + list(y), [d.keys() for d in dig])) + assert not expected - found + + +@pytest.mark.parametrize("pdf, config, hs, exported", pdf_config_hs_exporteds) +def test_nan_trans(pdf, config, hs, exported): + """Test unlikely case that the device to head transform is empty.""" + bti_info = _read_bti_header(pdf, config, sort_by_ch_name=True) + + dev_ctf_t = Transform( + "ctf_meg", "ctf_head", _correct_trans(bti_info["bti_transform"][0]) + ) + + # reading params + convert = True + rotation_x = 0.0 + translation = (0.0, 0.02, 0.11) + bti_dev_t = _get_bti_dev_t(rotation_x, translation) + bti_dev_t = Transform("ctf_meg", "meg", bti_dev_t) + ecg_ch = "E31" + eog_ch = ("E63", "E64") + + # read parts of info to get trans + bti_ch_names = list() + for ch in bti_info["chs"]: + ch_name = ch["name"] + if not ch_name.startswith("A"): + ch_name = ch.get("chan_label", ch_name) + bti_ch_names.append(ch_name) + + neuromag_ch_names = _rename_channels(bti_ch_names, ecg_ch=ecg_ch, eog_ch=eog_ch) + ch_mapping = zip(bti_ch_names, neuromag_ch_names) + + # add some nan in some locations! + dev_ctf_t["trans"][:, 3] = np.nan + _check_nan_dev_head_t(dev_ctf_t) + for idx, (chan_4d, chan_neuromag) in enumerate(ch_mapping): + loc = bti_info["chs"][idx]["loc"] + if loc is not None: + if convert: + t = _loc_to_coil_trans(bti_info["chs"][idx]["loc"]) + t = _convert_coil_trans(t, dev_ctf_t, bti_dev_t) + + +@testing.requires_testing_data +@pytest.mark.parametrize("fname", (fname_sim, fname_sim_filt)) +@pytest.mark.parametrize("preload", (True, False)) +def test_bti_ch_data(fname, preload): + """Test for gh-6048.""" + read_raw_bti(fname, preload=preload) # used to fail with ascii decode err + + +@testing.requires_testing_data +def test_bti_set_eog(): + """Check that EOG channels can be set (gh-10092).""" + raw = read_raw_bti( + fname_sim, preload=False, eog_ch=("X65", "X67", "X69", "X66", "X68") + ) + assert_equal(len(pick_types(raw.info, eog=True)), 5) + + +@testing.requires_testing_data +def test_bti_ecg_eog_emg(monkeypatch): + """Test that EOG/ECG/EMG are set properly in BTi.""" + kwargs = dict(rename_channels=False, head_shape_fname=None) + raw = read_raw_bti(fname_2500, **kwargs) + ch_types = raw.get_channel_types() + got = Counter(ch_types) + # Before improving the triaging in gh-, these values were: + # want = dict(mag=148, ref_meg=11, ecg=32, stim=2, misc=1) + want = dict(mag=148, ref_meg=11, ecg=1, stim=2, misc=1, eeg=31) + assert set(want) == set(got) + for key in want: + assert want[key] == got[key], key + + # replace channel names with some from HCP (starting from the end) + # not including UACurrent (misc) or TRIGGER/RESPONSE (stim) b/c they + # already exist + got_map = dict(zip(raw.ch_names, ch_types)) + kind_map = dict( + stim=["TRIGGER", "RESPONSE"], + misc=["UACurrent"], + ) + for kind, ch_names in kind_map.items(): + for ch_name in ch_names: + assert got_map[ch_name] == kind + kind_map = dict( + misc=["SA1", "SA2", "SA3"], + ecg=["ECG+", "ECG-"], + eog=["VEOG+", "HEOG+", "VEOG-", "HEOG-"], + emg=["EMG_LF", "EMG_LH", "EMG_RF", "EMG_RH"], + ) + new_names = sum(kind_map.values(), list()) + assert len(new_names) == 13 + assert set(new_names).intersection(set(raw.ch_names)) == set() + + def _read_bti_header_2(*args, **kwargs): + bti_info = _read_bti_header(*args, **kwargs) + for ch_name, ch in zip(new_names, bti_info["chs"][::-1]): + ch["chan_label"] = ch_name + return bti_info + + monkeypatch.setattr(mne.io.bti.bti, "_read_bti_header", _read_bti_header_2) + raw = read_raw_bti(fname_2500, **kwargs) + got_map = dict(zip(raw.ch_names, raw.get_channel_types())) + got = Counter(got_map.values()) + want = dict(mag=148, ref_meg=11, misc=1, stim=2, eeg=19) + for kind, ch_names in kind_map.items(): + want[kind] = want.get(kind, 0) + len(ch_names) + assert set(want) == set(got) + for key in want: + assert want[key] == got[key], key + for kind, ch_names in kind_map.items(): + for ch_name in ch_names: + assert ch_name in raw.ch_names + err_msg = f"{ch_name} type {got_map[ch_name]} !+ {kind}" + assert got_map[ch_name] == kind, err_msg diff --git a/mne-python/source/mne/io/cnt/__init__.py b/mne-python/source/mne/io/cnt/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..10aac79f2f1159761757e270844d9f8d9caeae8d --- /dev/null +++ b/mne-python/source/mne/io/cnt/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""CNT data reader.""" + +from .cnt import read_raw_cnt diff --git a/mne-python/source/mne/io/cnt/_utils.py b/mne-python/source/mne/io/cnt/_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..cf2d45cb1ef6a32b68122ba68094128fe0eeb883 --- /dev/null +++ b/mne-python/source/mne/io/cnt/_utils.py @@ -0,0 +1,150 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from collections import namedtuple +from datetime import datetime +from math import modf +from os import SEEK_END +from struct import Struct + +import numpy as np + +from ...utils import warn + + +def _read_teeg(f, teeg_offset): + """ + Read TEEG structure from an open CNT file. + + # from TEEG structure in http://paulbourke.net/dataformats/eeg/ + typedef struct { + char Teeg; /* Either 1 or 2 */ + long Size; /* Total length of all the events */ + long Offset; /* Hopefully always 0 */ + } TEEG; + """ + # we use a more descriptive names based on TEEG doc comments + Teeg = namedtuple("Teeg", "event_type total_length offset") + teeg_parser = Struct("3 range 0-15 bit coded response pad */ +# /* 4->7 values 0xd=Accept 0xc=Reject */ +# long Offset; /* file offset of event */ +# } EVENT1; + + +CNTEventType2 = namedtuple( + "CNTEventType2", + ( + "StimType KeyBoard KeyPad_Accept Offset Type " + "Code Latency EpochEvent Accept2 Accuracy" + ), +) +# unsigned short StimType; /* range 0-65535 */ +# unsigned char KeyBoard; /* range 0-11 corresponding to fcn keys +1 */ +# char KeyPad_Accept; /* 0->3 range 0-15 bit coded response pad */ +# /* 4->7 values 0xd=Accept 0xc=Reject */ +# long Offset; /* file offset of event */ +# short Type; +# short Code; +# float Latency; +# char EpochEvent; +# char Accept2; +# char Accuracy; + + +# needed for backward compat: EVENT type 3 has the same structure as type 2 +CNTEventType3 = namedtuple( + "CNTEventType3", + ( + "StimType KeyBoard KeyPad_Accept Offset Type " + "Code Latency EpochEvent Accept2 Accuracy" + ), +) + + +def _get_event_parser(event_type): + if event_type == 1: + event_maker = CNTEventType1 + struct_pattern = "> 4 + # Lower nibble (4 bits) keypad button press + keypad = event.KeyPad_Accept[0] & 0x0F + if str(keypad) != "0": + description.append(f"KeyPad Response {keypad}") + elif event.KeyBoard != 0: + description.append(f"Keyboard Response {event.KeyBoard}") + else: + description.append(str(event.StimType)) + + description = np.array(description) + + onset, duration, description = _update_bad_span_onset( + accept_reject, onset / sfreq, duration, description + ) + return Annotations( + onset=onset, duration=duration, description=description, orig_time=None + ) + + +@fill_doc +def read_raw_cnt( + input_fname, + eog=(), + misc=(), + ecg=(), + emg=(), + data_format="auto", + date_format="mm/dd/yy", + *, + header="auto", + preload=False, + verbose=None, +) -> "RawCNT": + """Read CNT data as raw object. + + .. Note:: + 2d spatial coordinates (x, y) for EEG channels are read from the file + header and fit to a sphere to compute corresponding z-coordinates. + If channels assigned as EEG channels have locations + far away from the head (i.e. x and y coordinates don't fit to a + sphere), all the channel locations will be distorted + (all channels that are not assigned with keywords ``eog``, ``ecg``, + ``emg`` and ``misc`` are assigned as EEG channels). If you are not + sure that the channel locations in the header are correct, it is + probably safer to replace them with :meth:`mne.io.Raw.set_montage`. + Montages can be created/imported with: + + - Standard montages with :func:`mne.channels.make_standard_montage` + - Montages for `Compumedics systems + `__ with + :func:`mne.channels.read_dig_curry` + - Other reader functions are listed under *See Also* at + :class:`mne.channels.DigMontage` + + Parameters + ---------- + input_fname : path-like + Path to the data file. + eog : list | tuple | ``'auto'`` | ``'header'`` + Names of channels or list of indices that should be designated + EOG channels. If 'header', VEOG and HEOG channels assigned in the file + header are used. If ``'auto'``, channel names containing ``'EOG'`` are + used. Defaults to empty tuple. + misc : list | tuple + Names of channels or list of indices that should be designated + MISC channels. Defaults to empty tuple. + ecg : list | tuple | ``'auto'`` + Names of channels or list of indices that should be designated + ECG channels. If ``'auto'``, the channel names containing ``'ECG'`` are + used. Defaults to empty tuple. + emg : list | tuple + Names of channels or list of indices that should be designated + EMG channels. If 'auto', the channel names containing 'EMG' are used. + Defaults to empty tuple. + data_format : ``'auto'`` | ``'int16'`` | ``'int32'`` + Defines the data format the data is read in. If ``'auto'``, it is + determined from the file header using ``numsamples`` field. + Defaults to ``'auto'``. + date_format : ``'mm/dd/yy'`` | ``'dd/mm/yy'`` + Format of date in the header. Defaults to ``'mm/dd/yy'``. + header : ``'auto'`` | ``'new'`` | ``'old'`` + Defines the header format. Used to describe how bad channels + are formatted. If auto, reads using old and new header and + if either contain a bad channel make channel bad. + Defaults to ``'auto'``. + + .. versionadded:: 1.6 + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawCNT. + The raw data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawCNT. + + Notes + ----- + .. versionadded:: 0.12 + """ + return RawCNT( + input_fname, + eog=eog, + misc=misc, + ecg=ecg, + emg=emg, + data_format=data_format, + date_format=date_format, + header=header, + preload=preload, + verbose=verbose, + ) + + +def _get_cnt_info(input_fname, eog, ecg, emg, misc, data_format, date_format, header): + """Read the cnt header.""" + data_offset = 900 # Size of the 'SETUP' header. + cnt_info = dict() + # Reading only the fields of interest. Structure of the whole header at + # http://paulbourke.net/dataformats/eeg/ + with open(input_fname, "rb", buffering=0) as fid: + fid.seek(21) + patient_id = read_str(fid, 20) + patient_id = int(patient_id) if patient_id.isdigit() else 0 + fid.seek(121) + patient_name = read_str(fid, 20).split() + last_name = patient_name[0] if len(patient_name) > 0 else "" + first_name = patient_name[-1] if len(patient_name) > 0 else "" + fid.seek(2, 1) + sex = read_str(fid, 1) + if sex == "M": + sex = FIFF.FIFFV_SUBJ_SEX_MALE + elif sex == "F": + sex = FIFF.FIFFV_SUBJ_SEX_FEMALE + else: # can be 'U' + sex = FIFF.FIFFV_SUBJ_SEX_UNKNOWN + hand = read_str(fid, 1) + if hand == "R": + hand = FIFF.FIFFV_SUBJ_HAND_RIGHT + elif hand == "L": + hand = FIFF.FIFFV_SUBJ_HAND_LEFT + else: # can be 'M' for mixed or 'U' + hand = None + fid.seek(205) + session_label = read_str(fid, 20) + + session_date = f"{read_str(fid, 10)} {read_str(fid, 12)}" + meas_date = _session_date_2_meas_date(session_date, date_format) + + fid.seek(370) + n_channels = np.fromfile(fid, dtype="= 0] + fid.seek(438) + lowpass_toggle = np.fromfile(fid, "i1", count=1).item() + highpass_toggle = np.fromfile(fid, "i1", count=1).item() + + # Header has a field for number of samples, but it does not seem to be + # too reliable. That's why we have option for setting n_bytes manually. + fid.seek(864) + n_samples = np.fromfile(fid, dtype=" n_samples: + n_bytes = 4 + n_samples = n_samples_header + warn( + "Annotations are outside data range. " + "Changing data format to 'int32'." + ) + else: + n_bytes = data_size // (n_samples * n_channels) + else: + n_bytes = 2 if data_format == "int16" else 4 + n_samples = data_size // (n_bytes * n_channels) + + # See PR #12393 + if n_samples_header != 0: + n_samples = n_samples_header + # Channel offset refers to the size of blocks per channel in the file. + cnt_info["channel_offset"] = np.fromfile(fid, dtype=" 1: + cnt_info["channel_offset"] //= n_bytes + else: + cnt_info["channel_offset"] = 1 + + ch_names, cals, baselines, chs, pos = (list(), list(), list(), list(), list()) + + bads = list() + _validate_type(header, str, "header") + _check_option("header", header, ("auto", "new", "old")) + for ch_idx in range(n_channels): # ELECTLOC fields + fid.seek(data_offset + 75 * ch_idx) + ch_name = read_str(fid, 10) + ch_names.append(ch_name) + + # Some files have bad channels marked differently in the header. + if header in ("new", "auto"): + fid.seek(data_offset + 75 * ch_idx + 14) + if np.fromfile(fid, dtype="u1", count=1).item(): + bads.append(ch_name) + if header in ("old", "auto"): + fid.seek(data_offset + 75 * ch_idx + 4) + if np.fromfile(fid, dtype="u1", count=1).item(): + bads.append(ch_name) + + fid.seek(data_offset + 75 * ch_idx + 19) + xy = np.fromfile(fid, dtype="f4", count=2) + xy[1] *= -1 # invert y-axis + pos.append(xy) + fid.seek(data_offset + 75 * ch_idx + 47) + # Baselines are subtracted before scaling the data. + baselines.append(np.fromfile(fid, dtype="i2", count=1).item()) + fid.seek(data_offset + 75 * ch_idx + 59) + sensitivity = np.fromfile(fid, dtype="f4", count=1).item() + fid.seek(data_offset + 75 * ch_idx + 71) + cal = np.fromfile(fid, dtype="f4", count=1).item() + cals.append(cal * sensitivity * 1e-6 / 204.8) + + info = _empty_info(sfreq) + if lowpass_toggle == 1: + info["lowpass"] = highcutoff + if highpass_toggle == 1: + info["highpass"] = lowcutoff + subject_info = { + "hand": hand, + "id": patient_id, + "sex": sex, + "first_name": first_name, + "last_name": last_name, + } + subject_info = {key: val for key, val in subject_info.items() if val is not None} + + if eog == "auto": + eog = _find_channels(ch_names, "EOG") + if ecg == "auto": + ecg = _find_channels(ch_names, "ECG") + if emg == "auto": + emg = _find_channels(ch_names, "EMG") + + chs = _create_chs( + ch_names, cals, FIFF.FIFFV_COIL_EEG, FIFF.FIFFV_EEG_CH, eog, ecg, emg, misc + ) + eegs = [idx for idx, ch in enumerate(chs) if ch["coil_type"] == FIFF.FIFFV_COIL_EEG] + coords = _topo_to_sphere(pos, eegs) + locs = np.full((len(chs), 12), np.nan) + locs[:, :3] = coords + dig = _make_dig_points( + dig_ch_pos=dict(zip(ch_names, coords)), + coord_frame="head", + add_missing_fiducials=True, + ) + for ch, loc in zip(chs, locs): + ch.update(loc=loc) + + cnt_info.update(baselines=np.array(baselines), n_samples=n_samples, n_bytes=n_bytes) + + session_label = None if str(session_label) == "" else str(session_label) + info.update( + meas_date=meas_date, + dig=dig, + description=session_label, + subject_info=subject_info, + chs=chs, + ) + info._unlocked = False + info._update_redundant() + info["bads"] = bads + return info, cnt_info + + +@fill_doc +class RawCNT(BaseRaw): + """Raw object from Neuroscan CNT file. + + .. note:: + + The channel positions are read from the file header. Channels that are + not assigned with keywords ``eog``, ``ecg``, ``emg`` and ``misc`` are + assigned as eeg channels. All the eeg channel locations are fit to a + sphere when computing the z-coordinates for the channels. If channels + assigned as eeg channels have locations far away from the head (i.e. + x and y coordinates don't fit to a sphere), all the channel locations + will be distorted. If you are not sure that the channel locations in + the header are correct, it is probably safer to use a (standard) + montage. See :func:`mne.channels.make_standard_montage` + + .. note:: + + A CNT file can also come from the EEG manufacturer ANT Neuro, in which case the + function :func:`mne.io.read_raw_ant` should be used. + + Parameters + ---------- + input_fname : path-like + Path to the Neuroscan CNT file. + eog : list | tuple + Names of channels or list of indices that should be designated + EOG channels. If ``'auto'``, the channel names beginning with + ``EOG`` are used. Defaults to empty tuple. + misc : list | tuple + Names of channels or list of indices that should be designated + MISC channels. Defaults to empty tuple. + ecg : list | tuple + Names of channels or list of indices that should be designated + ECG channels. If ``'auto'``, the channel names beginning with + ``ECG`` are used. Defaults to empty tuple. + emg : list | tuple + Names of channels or list of indices that should be designated + EMG channels. If ``'auto'``, the channel names beginning with + ``EMG`` are used. Defaults to empty tuple. + data_format : ``'auto'`` | ``'int16'`` | ``'int32'`` + Defines the data format the data is read in. If ``'auto'``, it is + determined from the file header using ``numsamples`` field. + Defaults to ``'auto'``. + date_format : ``'mm/dd/yy'`` | ``'dd/mm/yy'`` + Format of date in the header. Defaults to ``'mm/dd/yy'``. + header : ``'auto'`` | ``'new'`` | ``'old'`` + Defines the header format. Used to describe how bad channels + are formatted. If auto, reads using old and new header and + if either contain a bad channel make channel bad. + Defaults to ``'auto'``. + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + def __init__( + self, + input_fname, + eog=(), + misc=(), + ecg=(), + emg=(), + data_format="auto", + date_format="mm/dd/yy", + *, + header="auto", + preload=False, + verbose=None, + ): + _check_option("date_format", date_format, ["mm/dd/yy", "dd/mm/yy"]) + if date_format == "dd/mm/yy": + _date_format = "%d/%m/%y %H:%M:%S" + else: + _date_format = "%m/%d/%y %H:%M:%S" + + input_fname = path.abspath(input_fname) + try: + info, cnt_info = _get_cnt_info( + input_fname, eog, ecg, emg, misc, data_format, _date_format, header + ) + except Exception: + raise RuntimeError( + f"{_explain_exception()}\n" + "WARNING: mne.io.read_raw_cnt " + "supports Neuroscan CNT files only. If this file is an ANT Neuro CNT, " + "please use mne.io.read_raw_ant instead." + ) + last_samps = [cnt_info["n_samples"] - 1] + super().__init__( + info, + preload, + filenames=[input_fname], + raw_extras=[cnt_info], + last_samps=last_samps, + orig_format="int", + verbose=verbose, + ) + + data_format = "int32" if cnt_info["n_bytes"] == 4 else "int16" + self.set_annotations( + _read_annotations_cnt(input_fname, data_format=data_format) + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Take a chunk of raw data, multiply by mult or cals, and store.""" + n_channels = self._raw_extras[fi]["orig_nchan"] + if "stim_channel" in self._raw_extras[fi]: + f_channels = n_channels - 1 # Stim channel already read. + stim_ch = self._raw_extras[fi]["stim_channel"] + else: + f_channels = n_channels + stim_ch = None + + channel_offset = self._raw_extras[fi]["channel_offset"] + baselines = self._raw_extras[fi]["baselines"] + n_bytes = self._raw_extras[fi]["n_bytes"] + n_samples = self._raw_extras[fi]["n_samples"] + dtype = "= (channel_offset / 2): # Extend at the end. + extra_samps += chunk_size + count = n_samps // channel_offset * chunk_size + extra_samps + n_chunks = count // chunk_size + samps = np.fromfile(fid, dtype=dtype, count=count) + samps = samps.reshape((n_chunks, f_channels, channel_offset), order="C") + + # Intermediate shaping to chunk sizes. + block = np.zeros((n_channels, channel_offset * n_chunks)) + for set_idx, row in enumerate(samps): # Final shape. + block_slice = slice( + set_idx * channel_offset, (set_idx + 1) * channel_offset + ) + block[:f_channels, block_slice] = row + if "stim_channel" in self._raw_extras[fi]: + _data_start = start + sample_start + _data_stop = start + sample_stop + block[-1] = stim_ch[_data_start:_data_stop] + one[idx] = block[idx, s_offset : n_samps + s_offset] + + one[idx] -= baselines[idx][:, None] + _mult_cal_one(data[:, sample_start:sample_stop], one, idx, cals, mult) diff --git a/mne-python/source/mne/io/cnt/tests/__init__.py b/mne-python/source/mne/io/cnt/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/cnt/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/cnt/tests/test_cnt.py b/mne-python/source/mne/io/cnt/tests/test_cnt.py new file mode 100644 index 0000000000000000000000000000000000000000..f98253b1317474f5258c4d90a600f7a2a8125710 --- /dev/null +++ b/mne-python/source/mne/io/cnt/tests/test_cnt.py @@ -0,0 +1,112 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import pytest +from numpy.testing import assert_array_equal + +from mne import pick_types +from mne.annotations import read_annotations +from mne.datasets import testing +from mne.io.cnt import read_raw_cnt +from mne.io.tests.test_raw import _test_raw_reader + +data_path = testing.data_path(download=False) +fname = data_path / "CNT" / "scan41_short.cnt" +# Contains bad spans and could not be read properly before PR #12393 +fname_bad_spans = data_path / "CNT" / "test_CNT_events_mne_JWoess_clipped.cnt" + + +_no_parse = pytest.warns(RuntimeWarning, match="Could not parse") + + +@testing.requires_testing_data +def test_old_data(): + """Test reading raw cnt files.""" + with _no_parse, pytest.warns(RuntimeWarning, match="number of bytes"): + raw = _test_raw_reader( + read_raw_cnt, input_fname=fname, eog="auto", misc=["NA1", "LEFT_EAR"] + ) + + # make sure we use annotations event if we synthesized stim + assert len(raw.annotations) == 6 + + eog_chs = pick_types(raw.info, eog=True, exclude=[]) + assert len(eog_chs) == 2 # test eog='auto' + assert raw.info["bads"] == ["LEFT_EAR", "VEOGR"] # test bads + + # the data has "05/10/200 17:35:31" so it is set to None + assert raw.info["meas_date"] is None + + +@testing.requires_testing_data +def test_new_data(): + """Test reading raw cnt files with different header.""" + with pytest.warns(RuntimeWarning): + raw = read_raw_cnt(input_fname=fname_bad_spans, header="new") + + assert raw.info["bads"] == ["F8"] # test bads + + +@testing.requires_testing_data +def test_auto_data(): + """Test reading raw cnt files with automatic header.""" + first = pytest.warns(RuntimeWarning, match="Could not define the number of bytes.*") + second = pytest.warns(RuntimeWarning, match="Annotations are outside") + third = pytest.warns(RuntimeWarning, match="Omitted 6 annot") + with first, second, third: + raw = read_raw_cnt(input_fname=fname_bad_spans) + # Test that responses are read properly + assert "KeyPad Response 1" in raw.annotations.description + assert raw.info["bads"] == ["F8"] + + with _no_parse, pytest.warns(RuntimeWarning, match="number of bytes"): + raw = _test_raw_reader( + read_raw_cnt, input_fname=fname, eog="auto", misc=["NA1", "LEFT_EAR"] + ) + + # make sure we use annotations event if we synthesized stim + assert len(raw.annotations) == 6 + + eog_chs = pick_types(raw.info, eog=True, exclude=[]) + assert len(eog_chs) == 2 # test eog='auto' + assert raw.info["bads"] == ["LEFT_EAR", "VEOGR"] # test bads + + # the data has "05/10/200 17:35:31" so it is set to None + assert raw.info["meas_date"] is None + + +@testing.requires_testing_data +def test_compare_events_and_annotations(): + """Test comparing annotations and events.""" + with _no_parse, pytest.warns(RuntimeWarning, match="Could not define the num"): + raw = read_raw_cnt(fname) + events = np.array( + [[333, 0, 7], [1010, 0, 7], [1664, 0, 109], [2324, 0, 7], [2984, 0, 109]] + ) + + annot = read_annotations(fname) + assert len(annot) == 6 + assert_array_equal(annot.onset[:-1], events[:, 0] / raw.info["sfreq"]) + assert "STI 014" not in raw.info["ch_names"] + + +@testing.requires_testing_data +@pytest.mark.filterwarnings("ignore::RuntimeWarning") +def test_reading_bytes(): + """Test reading raw cnt files with different header.""" + raw_16 = read_raw_cnt(fname, preload=True) + raw_32 = read_raw_cnt(fname_bad_spans, preload=True) + + # Verify that the number of bytes read is correct + assert len(raw_16) == 3070 + assert len(raw_32) == 90000 + + +@testing.requires_testing_data +def test_bad_spans(): + """Test reading raw cnt files with bad spans.""" + annot = read_annotations(fname_bad_spans) + temp = "\t".join(annot.description) + assert "BAD" in temp diff --git a/mne-python/source/mne/io/constants.py b/mne-python/source/mne/io/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..50cf567773139f0dcd07b71f10206e44f3004c3f --- /dev/null +++ b/mne-python/source/mne/io/constants.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .._fiff.constants import FIFF + +__all__ = ["FIFF"] diff --git a/mne-python/source/mne/io/ctf/__init__.py b/mne-python/source/mne/io/ctf/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..538d63f0ac3c18abde377b62f2df07217808ad35 --- /dev/null +++ b/mne-python/source/mne/io/ctf/__init__.py @@ -0,0 +1,7 @@ +"""CTF module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .ctf import read_raw_ctf, RawCTF diff --git a/mne-python/source/mne/io/ctf/constants.py b/mne-python/source/mne/io/ctf/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..a99b627eeeeae98761d855731e6f26c50b5e8498 --- /dev/null +++ b/mne-python/source/mne/io/ctf/constants.py @@ -0,0 +1,38 @@ +"""CTF constants.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ...utils import BunchConst + + +CTF = BunchConst() + +# ctf_types.h +CTF.CTFV_MAX_AVERAGE_BINS = 8 +CTF.CTFV_MAX_COILS = 8 +CTF.CTFV_MAX_BALANCING = 50 +CTF.CTFV_SENSOR_LABEL = 31 + +CTF.CTFV_COIL_LPA = 1 +CTF.CTFV_COIL_RPA = 2 +CTF.CTFV_COIL_NAS = 3 +CTF.CTFV_COIL_SPARE = 4 + +CTF.CTFV_REF_MAG_CH = 0 +CTF.CTFV_REF_GRAD_CH = 1 +CTF.CTFV_MEG_CH = 5 +CTF.CTFV_EEG_CH = 9 +CTF.CTFV_STIM_CH = 11 + +CTF.CTFV_FILTER_LOWPASS = 1 +CTF.CTFV_FILTER_HIGHPASS = 2 + +# read_res4.c +CTF.FUNNY_POS = 1844 + +# read_write_data.c +CTF.HEADER_SIZE = 8 +CTF.BLOCK_SIZE = 2000 +CTF.SYSTEM_CLOCK_CH = "SCLK01-177" diff --git a/mne-python/source/mne/io/ctf/ctf.py b/mne-python/source/mne/io/ctf/ctf.py new file mode 100644 index 0000000000000000000000000000000000000000..d8b2c96e1bd3d641a4766f97c1f118a432ed1331 --- /dev/null +++ b/mne-python/source/mne/io/ctf/ctf.py @@ -0,0 +1,304 @@ +"""Conversion tool from CTF to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os + +import numpy as np + +from ..._fiff._digitization import _format_dig_points +from ..._fiff.utils import _blk_read_lims, _mult_cal_one +from ...fixes import _reshape_view +from ...utils import ( + _check_fname, + _check_option, + _clean_names, + fill_doc, + logger, + verbose, +) +from ..base import BaseRaw +from .constants import CTF +from .eeg import _read_eeg, _read_pos +from .hc import _read_hc +from .info import _annotate_bad_segments, _compose_meas_info, _read_bad_chans +from .markers import _read_annotations_ctf_call +from .res4 import _make_ctf_name, _read_res4 +from .trans import _make_ctf_coord_trans_set + + +@fill_doc +def read_raw_ctf( + directory, system_clock="truncate", preload=False, clean_names=False, verbose=None +) -> "RawCTF": + """Raw object from CTF directory. + + Parameters + ---------- + directory : path-like + Path to the CTF data (ending in ``'.ds'``). + system_clock : str + How to treat the system clock. Use "truncate" (default) to truncate + the data file when the system clock drops to zero, and use "ignore" + to ignore the system clock (e.g., if head positions are measured + multiple times during a recording). + %(preload)s + clean_names : bool, optional + If True main channel names and compensation channel names will + be cleaned from CTF suffixes. The default is False. + %(verbose)s + + Returns + ------- + raw : instance of RawCTF + The raw data. + + Notes + ----- + .. versionadded:: 0.11 + + To read in the Polhemus digitization data (for example, from + a .pos file), include the file in the CTF directory. The + points will then automatically be read into the `mne.io.Raw` + instance via `mne.io.read_raw_ctf`. + """ + return RawCTF( + directory, + system_clock, + preload=preload, + clean_names=clean_names, + verbose=verbose, + ) + + +@fill_doc +class RawCTF(BaseRaw): + """Raw object from CTF directory. + + Parameters + ---------- + directory : path-like + Path to the CTF data (ending in ``'.ds'``). + system_clock : str + How to treat the system clock. Use ``"truncate"`` (default) to truncate + the data file when the system clock drops to zero, and use ``"ignore"`` + to ignore the system clock (e.g., if head positions are measured + multiple times during a recording). + %(preload)s + clean_names : bool, optional + If True main channel names and compensation channel names will + be cleaned from CTF suffixes. The default is False. + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + @verbose + def __init__( + self, + directory, + system_clock="truncate", + preload=False, + verbose=None, + clean_names=False, + ): + # adapted from mne_ctf2fiff.c + directory = str( + _check_fname(directory, "read", True, "directory", need_dir=True) + ) + if not directory.endswith(".ds"): + raise TypeError( + f'directory must be a directory ending with ".ds", got {directory}' + ) + _check_option("system_clock", system_clock, ["ignore", "truncate"]) + logger.info(f"ds directory : {directory}") + res4 = _read_res4(directory) # Read the magical res4 file + coils = _read_hc(directory) # Read the coil locations + eeg = _read_eeg(directory) # Read the EEG electrode loc info + + # Investigate the coil location data to get the coordinate trans + coord_trans = _make_ctf_coord_trans_set(res4, coils) + + digs = _read_pos(directory, coord_trans) + + # Compose a structure which makes fiff writing a piece of cake + info = _compose_meas_info(res4, coils, coord_trans, eeg) + with info._unlock(): + info["dig"] += digs + info["dig"] = _format_dig_points(info["dig"]) + info["bads"] += _read_bad_chans(directory, info) + + # Determine how our data is distributed across files + fnames = list() + last_samps = list() + raw_extras = list() + missing_names = list() + no_samps = list() + while True: + suffix = "meg4" if len(fnames) == 0 else f"{len(fnames)}_meg4" + meg4_name, found = _make_ctf_name(directory, suffix, raise_error=False) + if not found: + missing_names.append(os.path.relpath(meg4_name, directory)) + break + # check how much data is in the file + sample_info = _get_sample_info(meg4_name, res4, system_clock) + if sample_info["n_samp"] == 0: + no_samps.append(os.path.relpath(meg4_name, directory)) + break + if len(fnames) == 0: + buffer_size_sec = sample_info["block_size"] / info["sfreq"] + else: + buffer_size_sec = 1.0 + fnames.append(meg4_name) + last_samps.append(sample_info["n_samp"] - 1) + raw_extras.append(sample_info) + first_samps = [0] * len(last_samps) + if len(fnames) == 0: + raise OSError( + f"Could not find any data, could not find the following " + f"file(s): {missing_names}, and the following file(s) had no " + f"valid samples: {no_samps}" + ) + super().__init__( + info, + preload, + first_samps=first_samps, + last_samps=last_samps, + filenames=fnames, + raw_extras=raw_extras, + orig_format="int", + buffer_size_sec=buffer_size_sec, + verbose=verbose, + ) + + # Add bad segments as Annotations (correct for start time) + start_time = -res4["pre_trig_pts"] / float(info["sfreq"]) + annot = _annotate_bad_segments(directory, start_time, info["meas_date"]) + marker_annot = _read_annotations_ctf_call( + directory=directory, + total_offset=(res4["pre_trig_pts"] / res4["sfreq"]), + trial_duration=(res4["nsamp"] / res4["sfreq"]), + meas_date=info["meas_date"], + ) + annot = marker_annot if annot is None else annot + marker_annot + self.set_annotations(annot) + if clean_names: + _clean_names_inst(self) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + si = self._raw_extras[fi] + offset = 0 + trial_start_idx, r_lims, d_lims = _blk_read_lims( + start, stop, int(si["block_size"]) + ) + with open(self.filenames[fi], "rb") as fid: + for bi in range(len(r_lims)): + samp_offset = (bi + trial_start_idx) * si["res4_nsamp"] + n_read = min(si["n_samp_tot"] - samp_offset, si["block_size"]) + # read the chunk of data + # have to be careful on Windows and make sure we are using + # 64-bit integers here + with np.errstate(over="raise"): + pos = np.int64(CTF.HEADER_SIZE) + pos += np.int64(samp_offset) * si["n_chan"] * 4 + fid.seek(pos, 0) + this_data = np.fromfile(fid, ">i4", count=si["n_chan"] * n_read) + this_data = _reshape_view(this_data, (si["n_chan"], n_read)) + this_data = this_data[:, r_lims[bi, 0] : r_lims[bi, 1]] + data_view = data[:, d_lims[bi, 0] : d_lims[bi, 1]] + _mult_cal_one(data_view, this_data, idx, cals, mult) + offset += n_read + + +def _clean_names_inst(inst): + """Clean up CTF suffixes from channel names.""" + mapping = dict(zip(inst.ch_names, _clean_names(inst.ch_names))) + inst.rename_channels(mapping) + for comp in inst.info["comps"]: + for key in ("row_names", "col_names"): + comp["data"][key] = _clean_names(comp["data"][key]) + + +def _get_sample_info(fname, res4, system_clock): + """Determine the number of valid samples.""" + logger.info(f"Finding samples for {fname}: ") + if CTF.SYSTEM_CLOCK_CH in res4["ch_names"]: + clock_ch = res4["ch_names"].index(CTF.SYSTEM_CLOCK_CH) + else: + clock_ch = None + for k, ch in enumerate(res4["chs"]): + if ch["ch_name"] == CTF.SYSTEM_CLOCK_CH: + clock_ch = k + break + with open(fname, "rb") as fid: + fid.seek(0, os.SEEK_END) + st_size = fid.tell() + fid.seek(0, 0) + if (st_size - CTF.HEADER_SIZE) % (4 * res4["nsamp"] * res4["nchan"]) != 0: + raise RuntimeError( + "The number of samples is not an even multiple of the trial size" + ) + n_samp_tot = (st_size - CTF.HEADER_SIZE) // (4 * res4["nchan"]) + n_trial = n_samp_tot // res4["nsamp"] + n_samp = n_samp_tot + if clock_ch is None: + logger.info( + " System clock channel is not available, assuming " + "all samples to be valid." + ) + elif system_clock == "ignore": + logger.info(" System clock channel is available, but ignored.") + else: # use it + logger.info( + " System clock channel is available, checking " + "which samples are valid." + ) + for t in range(n_trial): + # Skip to the correct trial + samp_offset = t * res4["nsamp"] + offset = ( + CTF.HEADER_SIZE + + (samp_offset * res4["nchan"] + (clock_ch * res4["nsamp"])) * 4 + ) + fid.seek(offset, 0) + this_data = np.fromfile(fid, ">i4", res4["nsamp"]) + if len(this_data) != res4["nsamp"]: + raise RuntimeError(f"Cannot read data for trial {t + 1}.") + end = np.where(this_data == 0)[0] + if len(end) > 0: + n_samp = samp_offset + end[0] + break + if n_samp < res4["nsamp"]: + n_trial = 1 + logger.info( + " %d x %d = %d samples from %d chs", + n_trial, + n_samp, + n_samp, + res4["nchan"], + ) + else: + n_trial = n_samp // res4["nsamp"] + n_omit = n_samp_tot - n_samp + logger.info( + " %d x %d = %d samples from %d chs", + n_trial, + res4["nsamp"], + n_samp, + res4["nchan"], + ) + if n_omit != 0: + logger.info(" %d samples omitted at the end", n_omit) + + return dict( + n_samp=n_samp, + n_samp_tot=n_samp_tot, + block_size=res4["nsamp"], + res4_nsamp=res4["nsamp"], + n_chan=res4["nchan"], + ) diff --git a/mne-python/source/mne/io/ctf/eeg.py b/mne-python/source/mne/io/ctf/eeg.py new file mode 100644 index 0000000000000000000000000000000000000000..cd39bc980e0a5519ce7ce211f43a7e7d65625daf --- /dev/null +++ b/mne-python/source/mne/io/ctf/eeg.py @@ -0,0 +1,108 @@ +"""Read .eeg files.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from os import listdir +from os.path import join + +import numpy as np + +from ..._fiff.constants import FIFF +from ...transforms import apply_trans +from ...utils import logger, warn +from .res4 import _make_ctf_name + +_cardinal_dict = dict( + nasion=FIFF.FIFFV_POINT_NASION, + lpa=FIFF.FIFFV_POINT_LPA, + left=FIFF.FIFFV_POINT_LPA, + rpa=FIFF.FIFFV_POINT_RPA, + right=FIFF.FIFFV_POINT_RPA, +) + + +def _read_eeg(directory): + """Read the .eeg file.""" + # Missing file is ok + fname, found = _make_ctf_name(directory, "eeg", raise_error=False) + if not found: + logger.info(" Separate EEG position data file not present.") + return + eeg = dict( + labels=list(), + kinds=list(), + ids=list(), + rr=list(), + np=0, + assign_to_chs=True, + coord_frame=FIFF.FIFFV_MNE_COORD_CTF_HEAD, + ) + with open(fname, "rb") as fid: + for line in fid: + line = line.strip() + if len(line) > 0: + parts = line.decode("utf-8").split() + if len(parts) != 5: + raise RuntimeError(f"Illegal data in EEG position file: {line}") + r = np.array([float(p) for p in parts[2:]]) / 100.0 + if (r * r).sum() > 1e-4: + label = parts[1] + eeg["labels"].append(label) + eeg["rr"].append(r) + id_ = _cardinal_dict.get(label.lower(), int(parts[0])) + if label.lower() in _cardinal_dict: + kind = FIFF.FIFFV_POINT_CARDINAL + else: + kind = FIFF.FIFFV_POINT_EXTRA + eeg["ids"].append(id_) + eeg["kinds"].append(kind) + eeg["np"] += 1 + logger.info(" Separate EEG position data file read.") + return eeg + + +def _read_pos(directory, transformations): + """Read the .pos file and return eeg positions as dig extra points.""" + fname = [join(directory, f) for f in listdir(directory) if f.endswith(".pos")] + if len(fname) < 1: + return list() + elif len(fname) > 1: + warn(" Found multiple pos files. Extra digitizer points not added.") + return list() + logger.info(f" Reading digitizer points from {fname}...") + if transformations["t_ctf_head_head"] is None: + warn(" No transformation found. Extra digitizer points not added.") + return list() + fname = fname[0] + digs = list() + i = 2000 + with open(fname) as fid: + for line in fid: + line = line.strip() + if len(line) > 0: + parts = line.split() + # The lines can have 4 or 5 parts. First part is for the id, + # which can be an int or a string. The last three are for xyz + # coordinates. The extra part is for additional info + # (e.g. 'Pz', 'Cz') which is ignored. + if len(parts) not in [4, 5]: + continue + try: + ident = int(parts[0]) + 1000 + except ValueError: # if id is not an int + ident = i + i += 1 + dig = dict( + kind=FIFF.FIFFV_POINT_EXTRA, + ident=ident, + r=list(), + coord_frame=FIFF.FIFFV_COORD_HEAD, + ) + r = np.array([float(p) for p in parts[-3:]]) / 100.0 # cm to m + if (r * r).sum() > 1e-4: + r = apply_trans(transformations["t_ctf_head_head"], r) + dig["r"] = r + digs.append(dig) + return digs diff --git a/mne-python/source/mne/io/ctf/hc.py b/mne-python/source/mne/io/ctf/hc.py new file mode 100644 index 0000000000000000000000000000000000000000..22acceda0ca3f08b2e2e4122e5897ad8c9cbd5f6 --- /dev/null +++ b/mne-python/source/mne/io/ctf/hc.py @@ -0,0 +1,89 @@ +"""Read .hc files.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ..._fiff.constants import FIFF +from ...utils import logger +from .constants import CTF +from .res4 import _make_ctf_name + +_kind_dict = { + "nasion": CTF.CTFV_COIL_NAS, + "left ear": CTF.CTFV_COIL_LPA, + "right ear": CTF.CTFV_COIL_RPA, + "spare": CTF.CTFV_COIL_SPARE, +} + +_coord_dict = { + "relative to dewar": FIFF.FIFFV_MNE_COORD_CTF_DEVICE, + "relative to head": FIFF.FIFFV_MNE_COORD_CTF_HEAD, +} + + +def _read_one_coil_point(fid): + """Read coil coordinate information from the hc file.""" + # Descriptor + one = "#" + while len(one) > 0 and one[0] == "#": + one = fid.readline() + if len(one) == 0: + return None + one = one.strip().decode("utf-8") + if "Unable" in one: + raise RuntimeError("HPI information not available") + + # Hopefully this is an unambiguous interpretation + p = dict() + p["valid"] = "measured" in one + for key, val in _coord_dict.items(): + if key in one: + p["coord_frame"] = val + break + else: + p["coord_frame"] = -1 + + for key, val in _kind_dict.items(): + if key in one: + p["kind"] = val + break + else: + p["kind"] = -1 + + # Three coordinates + p["r"] = np.empty(3) + for ii, coord in enumerate("xyz"): + sp = fid.readline().decode("utf-8").strip() + if len(sp) == 0: # blank line + continue + sp = sp.split(" ") + if len(sp) != 3 or sp[0] != coord or sp[1] != "=": + raise RuntimeError(f"Bad line: {one}") + # We do not deal with centimeters + p["r"][ii] = float(sp[2]) / 100.0 + return p + + +def _read_hc(directory): + """Read the hc file to get the HPI info and to prepare for coord trans.""" + fname, found = _make_ctf_name(directory, "hc", raise_error=False) + if not found: + logger.info(" hc data not present") + return None + s = list() + with open(fname, "rb") as fid: + while True: + p = _read_one_coil_point(fid) + if p is None: + # First point bad indicates that the file is empty + if len(s) == 0: + logger.info("hc file empty, no data present") + return None + # Returns None if at EOF + logger.info(" hc data read.") + return s + if p["valid"]: + s.append(p) diff --git a/mne-python/source/mne/io/ctf/info.py b/mne-python/source/mne/io/ctf/info.py new file mode 100644 index 0000000000000000000000000000000000000000..685a20792d3bb1eeaf3c7f65b642f5c74ff0998e --- /dev/null +++ b/mne-python/source/mne/io/ctf/info.py @@ -0,0 +1,560 @@ +"""Populate measurement info.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op +from calendar import timegm +from time import strptime + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.ctf_comp import _add_kind, _calibrate_comp +from ..._fiff.meas_info import _empty_info +from ..._fiff.write import get_new_file_id +from ...annotations import Annotations +from ...transforms import ( + _coord_frame_name, + apply_trans, + combine_transforms, + invert_transform, +) +from ...utils import _clean_names, logger, warn +from .constants import CTF + +_ctf_to_fiff = { + CTF.CTFV_COIL_LPA: FIFF.FIFFV_POINT_LPA, + CTF.CTFV_COIL_RPA: FIFF.FIFFV_POINT_RPA, + CTF.CTFV_COIL_NAS: FIFF.FIFFV_POINT_NASION, +} + + +def _pick_isotrak_and_hpi_coils(res4, coils, t): + """Pick the HPI coil locations given in device coordinates.""" + if coils is None: + return list(), list() + dig = list() + hpi_result = dict(dig_points=list()) + n_coil_dev = 0 + n_coil_head = 0 + for p in coils: + if p["valid"]: + if p["kind"] in [CTF.CTFV_COIL_LPA, CTF.CTFV_COIL_RPA, CTF.CTFV_COIL_NAS]: + kind = FIFF.FIFFV_POINT_CARDINAL + ident = _ctf_to_fiff[p["kind"]] + else: # CTF.CTFV_COIL_SPARE + kind = FIFF.FIFFV_POINT_HPI + ident = p["kind"] + if p["coord_frame"] == FIFF.FIFFV_MNE_COORD_CTF_DEVICE: + if t is None or t["t_ctf_dev_dev"] is None: + raise RuntimeError( + "No coordinate transformation available for HPI coil locations" + ) + d = dict( + kind=kind, + ident=ident, + r=apply_trans(t["t_ctf_dev_dev"], p["r"]), + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + ) + hpi_result["dig_points"].append(d) + n_coil_dev += 1 + elif p["coord_frame"] == FIFF.FIFFV_MNE_COORD_CTF_HEAD: + if t is None or t["t_ctf_head_head"] is None: + raise RuntimeError( + "No coordinate transformation " + "available for (virtual) Polhemus data" + ) + d = dict( + kind=kind, + ident=ident, + r=apply_trans(t["t_ctf_head_head"], p["r"]), + coord_frame=FIFF.FIFFV_COORD_HEAD, + ) + dig.append(d) + n_coil_head += 1 + if n_coil_head > 0: + logger.info(" Polhemus data for %d HPI coils added", n_coil_head) + if n_coil_dev > 0: + logger.info( + " Device coordinate locations for %d HPI coils added", n_coil_dev + ) + return dig, [hpi_result] + + +def _convert_time(date_str, time_str): + """Convert date and time strings to float time.""" + if date_str == time_str == "": + date_str = "01/01/1970" + time_str = "00:00:00" + logger.info( + "No date or time found, setting to the start of the " + "POSIX epoch (1970/01/01 midnight)" + ) + + for fmt in ("%d/%m/%Y", "%d-%b-%Y", "%a, %b %d, %Y", "%Y/%m/%d"): + try: + date = strptime(date_str.strip(), fmt) + except ValueError: + pass + else: + break + else: + raise RuntimeError( + f"Illegal date: {date_str}.\nIf the language of the date does not " + "correspond to your local machine's language try to set the " + "locale to the language of the date string:\n" + 'locale.setlocale(locale.LC_ALL, "en_US")' + ) + + for fmt in ("%H:%M:%S", "%H:%M"): + try: + time = strptime(time_str, fmt) + except ValueError: + pass + else: + break + else: + raise RuntimeError(f"Illegal time: {time_str}") + # MNE-C uses mktime which uses local time, but here we instead decouple + # conversion location from the process, and instead assume that the + # acquisition was in GMT. This will be wrong for most sites, but at least + # the value we obtain here won't depend on the geographical location + # that the file was converted. + res = timegm( + ( + date.tm_year, + date.tm_mon, + date.tm_mday, + time.tm_hour, + time.tm_min, + time.tm_sec, + date.tm_wday, + date.tm_yday, + date.tm_isdst, + ) + ) + return res + + +def _get_plane_vectors(ez): + """Get two orthogonal vectors orthogonal to ez (ez will be modified).""" + assert ez.shape == (3,) + ez_len = np.sqrt(np.sum(ez * ez)) + if ez_len == 0: + raise RuntimeError("Zero length normal. Cannot proceed.") + if np.abs(ez_len - np.abs(ez[2])) < 1e-5: # ez already in z-direction + ex = np.array([1.0, 0.0, 0.0]) + else: + ex = np.zeros(3) + if ez[1] < ez[2]: + ex[0 if ez[0] < ez[1] else 1] = 1.0 + else: + ex[0 if ez[0] < ez[2] else 2] = 1.0 + ez /= ez_len + ex -= np.dot(ez, ex) * ez + ex /= np.sqrt(np.sum(ex * ex)) + ey = np.cross(ez, ex) + return ex, ey + + +def _at_origin(x): + """Determine if a vector is at the origin.""" + return np.sum(x * x) < 1e-8 + + +def _check_comp_ch(cch, kind, desired=None): + if desired is None: + desired = cch["grad_order_no"] + if cch["grad_order_no"] != desired: + raise RuntimeError( + f"{kind} channel with inconsistent compensation " + f"grade {cch['grad_order_no']}, should be {desired}" + ) + return desired + + +def _convert_channel_info(res4, t, use_eeg_pos): + """Convert CTF channel information to fif format.""" + nmeg = neeg = nstim = nmisc = nref = 0 + chs = list() + this_comp = None + for k, cch in enumerate(res4["chs"]): + cal = float(1.0 / (cch["proper_gain"] * cch["qgain"])) + ch = dict( + scanno=k + 1, + range=1.0, + cal=cal, + loc=np.full(12, np.nan), + unit_mul=FIFF.FIFF_UNITM_NONE, + ch_name=cch["ch_name"][:15], + coil_type=FIFF.FIFFV_COIL_NONE, + ) + del k + chs.append(ch) + # Create the channel position information + if cch["sensor_type_index"] in ( + CTF.CTFV_REF_MAG_CH, + CTF.CTFV_REF_GRAD_CH, + CTF.CTFV_MEG_CH, + ): + # Extra check for a valid MEG channel + if ( + np.sum(cch["coil"]["pos"][0] ** 2) < 1e-6 + or np.sum(cch["coil"]["norm"][0] ** 2) < 1e-6 + ): + nmisc += 1 + ch.update( + logno=nmisc, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + kind=FIFF.FIFFV_MISC_CH, + unit=FIFF.FIFF_UNIT_V, + ) + text = "MEG" + if cch["sensor_type_index"] != CTF.CTFV_MEG_CH: + text += " ref" + warn( + f"{text} channel {ch['ch_name']} did not have position " + "assigned, so it was changed to a MISC channel" + ) + continue + ch["unit"] = FIFF.FIFF_UNIT_T + # Set up the local coordinate frame + r0 = cch["coil"]["pos"][0].copy() + ez = cch["coil"]["norm"][0].copy() + # It turns out that positive proper_gain requires swapping + # of the normal direction + if cch["proper_gain"] > 0.0: + ez *= -1 + # Check how the other vectors should be defined + off_diag = False + # Default: ex and ey are arbitrary in the plane normal to ez + if cch["sensor_type_index"] == CTF.CTFV_REF_GRAD_CH: + # The off-diagonal gradiometers are an exception: + # + # We use the same convention for ex as for Neuromag planar + # gradiometers: ex pointing in the positive gradient direction + diff = cch["coil"]["pos"][0] - cch["coil"]["pos"][1] + size = np.sqrt(np.sum(diff * diff)) + if size > 0.0: + diff /= size + # Is ez normal to the line joining the coils? + if np.abs(np.dot(diff, ez)) < 1e-3: + off_diag = True + # Handle the off-diagonal gradiometer coordinate system + r0 -= size * diff / 2.0 + ex = diff + ey = np.cross(ez, ex) + else: + ex, ey = _get_plane_vectors(ez) + else: + ex, ey = _get_plane_vectors(ez) + # Transform into a Neuromag-like device coordinate system + ch["loc"] = np.concatenate( + [ + apply_trans(t["t_ctf_dev_dev"], r0), + apply_trans(t["t_ctf_dev_dev"], ex, move=False), + apply_trans(t["t_ctf_dev_dev"], ey, move=False), + apply_trans(t["t_ctf_dev_dev"], ez, move=False), + ] + ) + del r0, ex, ey, ez + # Set the coil type + if cch["sensor_type_index"] == CTF.CTFV_REF_MAG_CH: + ch["kind"] = FIFF.FIFFV_REF_MEG_CH + ch["coil_type"] = FIFF.FIFFV_COIL_CTF_REF_MAG + nref += 1 + ch["logno"] = nref + elif cch["sensor_type_index"] == CTF.CTFV_REF_GRAD_CH: + ch["kind"] = FIFF.FIFFV_REF_MEG_CH + if off_diag: + ch["coil_type"] = FIFF.FIFFV_COIL_CTF_OFFDIAG_REF_GRAD + else: + ch["coil_type"] = FIFF.FIFFV_COIL_CTF_REF_GRAD + nref += 1 + ch["logno"] = nref + else: + this_comp = _check_comp_ch(cch, "Gradiometer", this_comp) + ch["kind"] = FIFF.FIFFV_MEG_CH + ch["coil_type"] = FIFF.FIFFV_COIL_CTF_GRAD + nmeg += 1 + ch["logno"] = nmeg + # Encode the software gradiometer order + ch["coil_type"] = int(ch["coil_type"] | (cch["grad_order_no"] << 16)) + ch["coord_frame"] = FIFF.FIFFV_COORD_DEVICE + elif cch["sensor_type_index"] == CTF.CTFV_EEG_CH: + coord_frame = FIFF.FIFFV_COORD_HEAD + if use_eeg_pos: + # EEG electrode coordinates may be present but in the + # CTF head frame + ch["loc"][:3] = cch["coil"]["pos"][0] + if not _at_origin(ch["loc"][:3]): + if t["t_ctf_head_head"] is None: + warn( + f"EEG electrode ({ch['ch_name']}) location omitted because " + "of missing HPI information" + ) + ch["loc"].fill(np.nan) + coord_frame = FIFF.FIFFV_MNE_COORD_CTF_HEAD + else: + ch["loc"][:3] = apply_trans(t["t_ctf_head_head"], ch["loc"][:3]) + neeg += 1 + ch.update( + logno=neeg, + kind=FIFF.FIFFV_EEG_CH, + unit=FIFF.FIFF_UNIT_V, + coord_frame=coord_frame, + coil_type=FIFF.FIFFV_COIL_EEG, + ) + elif cch["sensor_type_index"] == CTF.CTFV_STIM_CH: + nstim += 1 + ch.update( + logno=nstim, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + kind=FIFF.FIFFV_STIM_CH, + unit=FIFF.FIFF_UNIT_V, + ) + else: + nmisc += 1 + ch.update( + logno=nmisc, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + kind=FIFF.FIFFV_MISC_CH, + unit=FIFF.FIFF_UNIT_V, + ) + return chs + + +def _comp_sort_keys(c): + """Sort the compensation data.""" + return (int(c["coeff_type"]), int(c["scanno"])) + + +def _check_comp(comp): + """Check that conversion to named matrices is possible.""" + ref_sens = None + kind = -1 + for k, c_k in enumerate(comp): + if c_k["coeff_type"] != kind: + c_ref = c_k + ref_sens = c_ref["sensors"] + kind = c_k["coeff_type"] + elif not c_k["sensors"] == ref_sens: + raise RuntimeError("Cannot use an uneven compensation matrix") + + +def _conv_comp(comp, first, last, chs): + """Add a new converted compensation data item.""" + ch_names = [c["ch_name"] for c in chs] + n_col = comp[first]["ncoeff"] + col_names = comp[first]["sensors"][:n_col] + row_names = [comp[p]["sensor_name"] for p in range(first, last + 1)] + mask = np.isin(col_names, ch_names) # missing channels excluded + col_names = np.array(col_names)[mask].tolist() + n_col = len(col_names) + n_row = len(row_names) + ccomp = dict(ctfkind=comp[first]["coeff_type"], save_calibrated=False) + _add_kind(ccomp) + + data = np.empty((n_row, n_col)) + for ii, coeffs in enumerate(comp[first : last + 1]): + # Pick the elements to the matrix + data[ii, :] = coeffs["coeffs"][mask] + ccomp["data"] = dict( + row_names=row_names, + col_names=col_names, + data=data, + nrow=len(row_names), + ncol=len(col_names), + ) + mk = ("proper_gain", "qgain") + _calibrate_comp(ccomp, chs, row_names, col_names, mult_keys=mk, flip=True) + return ccomp + + +def _convert_comp_data(res4): + """Convert the compensation data into named matrices.""" + if res4["ncomp"] == 0: + return + # Sort the coefficients in our favorite order + res4["comp"] = sorted(res4["comp"], key=_comp_sort_keys) + # Check that all items for a given compensation type have the correct + # number of channels + _check_comp(res4["comp"]) + # Create named matrices + first = 0 + kind = -1 + comps = list() + for k in range(len(res4["comp"])): + if res4["comp"][k]["coeff_type"] != kind: + if k > 0: + comps.append(_conv_comp(res4["comp"], first, k - 1, res4["chs"])) + kind = res4["comp"][k]["coeff_type"] + first = k + comps.append(_conv_comp(res4["comp"], first, k, res4["chs"])) + return comps + + +def _pick_eeg_pos(c): + """Pick EEG positions.""" + eeg = dict( + coord_frame=FIFF.FIFFV_COORD_HEAD, + assign_to_chs=False, + labels=list(), + ids=list(), + rr=list(), + kinds=list(), + np=0, + ) + for ch in c["chs"]: + if ch["kind"] == FIFF.FIFFV_EEG_CH and not _at_origin(ch["loc"][:3]): + eeg["labels"].append(ch["ch_name"]) + eeg["ids"].append(ch["logno"]) + eeg["rr"].append(ch["loc"][:3]) + eeg["kinds"].append(FIFF.FIFFV_POINT_EEG) + eeg["np"] += 1 + if eeg["np"] == 0: + return None + logger.info("Picked positions of %d EEG channels from channel info", eeg["np"]) + return eeg + + +def _add_eeg_pos(eeg, t, c): + """Pick the (virtual) EEG position data.""" + if eeg is None: + return + if t is None or t["t_ctf_head_head"] is None: + raise RuntimeError( + "No coordinate transformation available for EEG position data" + ) + eeg_assigned = 0 + if eeg["assign_to_chs"]: + for k in range(eeg["np"]): + # Look for a channel name match + for ch in c["chs"]: + if ch["ch_name"].lower() == eeg["labels"][k].lower(): + r0 = ch["loc"][:3] + r0[:] = eeg["rr"][k] + if eeg["coord_frame"] == FIFF.FIFFV_MNE_COORD_CTF_HEAD: + r0[:] = apply_trans(t["t_ctf_head_head"], r0) + elif eeg["coord_frame"] != FIFF.FIFFV_COORD_HEAD: + raise RuntimeError( + "Illegal coordinate frame for EEG electrode " + f"positions : {_coord_frame_name(eeg['coord_frame'])}" + ) + # Use the logical channel number as an identifier + eeg["ids"][k] = ch["logno"] + eeg["kinds"][k] = FIFF.FIFFV_POINT_EEG + eeg_assigned += 1 + break + + # Add these to the Polhemus data + fid_count = eeg_count = extra_count = 0 + for k in range(eeg["np"]): + d = dict( + r=eeg["rr"][k].copy(), + kind=eeg["kinds"][k], + ident=eeg["ids"][k], + coord_frame=FIFF.FIFFV_COORD_HEAD, + ) + c["dig"].append(d) + if eeg["coord_frame"] == FIFF.FIFFV_MNE_COORD_CTF_HEAD: + d["r"] = apply_trans(t["t_ctf_head_head"], d["r"]) + elif eeg["coord_frame"] != FIFF.FIFFV_COORD_HEAD: + raise RuntimeError( + "Illegal coordinate frame for EEG electrode positions: " + + _coord_frame_name(eeg["coord_frame"]) + ) + if eeg["kinds"][k] == FIFF.FIFFV_POINT_CARDINAL: + fid_count += 1 + elif eeg["kinds"][k] == FIFF.FIFFV_POINT_EEG: + eeg_count += 1 + else: + extra_count += 1 + if eeg_assigned > 0: + logger.info( + " %d EEG electrode locations assigned to channel info.", eeg_assigned + ) + for count, kind in zip( + (fid_count, eeg_count, extra_count), + ("fiducials", "EEG locations", "extra points"), + ): + if count > 0: + logger.info(" %d %s added to Polhemus data.", count, kind) + + +_filt_map = {CTF.CTFV_FILTER_LOWPASS: "lowpass", CTF.CTFV_FILTER_HIGHPASS: "highpass"} + + +def _compose_meas_info(res4, coils, trans, eeg): + """Create meas info from CTF data.""" + info = _empty_info(res4["sfreq"]) + + # Collect all the necessary data from the structures read + info["meas_id"] = get_new_file_id() + info["meas_id"]["usecs"] = 0 + info["meas_id"]["secs"] = _convert_time(res4["data_date"], res4["data_time"]) + info["meas_date"] = (info["meas_id"]["secs"], info["meas_id"]["usecs"]) + info["experimenter"] = res4["nf_operator"] + info["subject_info"] = dict(his_id=res4["nf_subject_id"]) + for filt in res4["filters"]: + if filt["type"] in _filt_map: + info[_filt_map[filt["type"]]] = filt["freq"] + info["dig"], info["hpi_results"] = _pick_isotrak_and_hpi_coils(res4, coils, trans) + if trans is not None: + if len(info["hpi_results"]) > 0: + info["hpi_results"][0]["coord_trans"] = trans["t_ctf_head_head"] + if trans["t_dev_head"] is not None: + info["dev_head_t"] = trans["t_dev_head"] + info["dev_ctf_t"] = combine_transforms( + trans["t_dev_head"], + invert_transform(trans["t_ctf_head_head"]), + FIFF.FIFFV_COORD_DEVICE, + FIFF.FIFFV_MNE_COORD_CTF_HEAD, + ) + if trans["t_ctf_head_head"] is not None: + info["ctf_head_t"] = trans["t_ctf_head_head"] + info["chs"] = _convert_channel_info(res4, trans, eeg is None) + info["comps"] = _convert_comp_data(res4) + if eeg is None: + # Pick EEG locations from chan info if not read from a separate file + eeg = _pick_eeg_pos(info) + _add_eeg_pos(eeg, trans, info) + logger.info(" Measurement info composed.") + info._unlocked = False + info._update_redundant() + return info + + +def _read_bad_chans(directory, info): + """Read Bad channel list and match to internal names.""" + fname = op.join(directory, "BadChannels") + if not op.exists(fname): + return [] + mapping = dict(zip(_clean_names(info["ch_names"]), info["ch_names"])) + with open(fname) as fid: + bad_chans = [mapping[f.strip()] for f in fid.readlines()] + return bad_chans + + +def _annotate_bad_segments(directory, start_time, meas_date): + fname = op.join(directory, "bad.segments") + if not op.exists(fname): + return None + + # read in bad segment file + onsets = [] + durations = [] + desc = [] + with open(fname) as fid: + for f in fid.readlines(): + tmp = f.strip().split() + desc.append(f"bad_{tmp[0]}") + onsets.append(np.float64(tmp[1]) - start_time) + durations.append(np.float64(tmp[2]) - np.float64(tmp[1])) + # return None if there are no bad segments + if len(onsets) == 0: + return None + + return Annotations(onsets, durations, desc, meas_date) diff --git a/mne-python/source/mne/io/ctf/markers.py b/mne-python/source/mne/io/ctf/markers.py new file mode 100644 index 0000000000000000000000000000000000000000..64360fbc9c3fb84b3e6ac8784125008805b30926 --- /dev/null +++ b/mne-python/source/mne/io/ctf/markers.py @@ -0,0 +1,89 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op +from io import BytesIO + +import numpy as np + +from ...annotations import Annotations +from .info import _convert_time +from .res4 import _read_res4 + + +def _get_markers(fname): + def consume(fid, predicate): # just a consumer to move around conveniently + while predicate(fid.readline()): + pass + + def parse_marker(string): # XXX: there should be a nicer way to do that + data = np.genfromtxt( + BytesIO(string.encode()), dtype=[("trial", int), ("sync", float)] + ) + return int(data["trial"]), float(data["sync"]) + + markers = dict() + with open(fname) as fid: + consume(fid, lambda line: not line.startswith("NUMBER OF MARKERS:")) + num_of_markers = int(fid.readline()) + + for _ in range(num_of_markers): + consume(fid, lambda line: not line.startswith("NAME:")) + label = fid.readline().strip("\n") + + consume(fid, lambda line: not line.startswith("NUMBER OF SAMPLES:")) + n_markers = int(fid.readline()) + + consume(fid, lambda line: not line.startswith("LIST OF SAMPLES:")) + next(fid) # skip the samples header + markers[label] = [parse_marker(next(fid)) for _ in range(n_markers)] + + return markers + + +def _get_res4_info_needed_by_markers(directory): + """Get required information from CTF res4 information file.""" + # we only need a few values from res4. Maybe we can read them directly + # instead of parsing the entire res4 file. + res4 = _read_res4(directory) + + total_offset_duration = res4["pre_trig_pts"] / res4["sfreq"] + trial_duration = res4["nsamp"] / res4["sfreq"] + + meas_date = (_convert_time(res4["data_date"], res4["data_time"]), 0) + return total_offset_duration, trial_duration, meas_date + + +def _read_annotations_ctf(directory): + total_offset, trial_duration, meas_date = _get_res4_info_needed_by_markers( + directory + ) + return _read_annotations_ctf_call( + directory, total_offset, trial_duration, meas_date + ) + + +def _read_annotations_ctf_call(directory, total_offset, trial_duration, meas_date): + fname = op.join(directory, "MarkerFile.mrk") + if not op.exists(fname): + return Annotations(list(), list(), list(), orig_time=meas_date) + else: + markers = _get_markers(fname) + + onset = [ + synctime + (trialnum * trial_duration) + total_offset + for _, m in markers.items() + for (trialnum, synctime) in m + ] + + description = np.concatenate( + [np.repeat(label, len(m)) for label, m in markers.items()] + ) + + return Annotations( + onset=onset, + duration=np.zeros_like(onset), + description=description, + orig_time=meas_date, + ) diff --git a/mne-python/source/mne/io/ctf/res4.py b/mne-python/source/mne/io/ctf/res4.py new file mode 100644 index 0000000000000000000000000000000000000000..b2ecb9dc304ed6450689bebac59696686bc2ff19 --- /dev/null +++ b/mne-python/source/mne/io/ctf/res4.py @@ -0,0 +1,232 @@ +"""Read .res4 files.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op + +import numpy as np + +from ...utils import logger +from .constants import CTF + + +def _make_ctf_name(directory, extra, raise_error=True): + """Make a CTF name.""" + fname = op.join(directory, op.basename(directory)[:-3] + "." + extra) + found = True + if not op.isfile(fname): + if raise_error: + raise OSError(f"Standard file {fname} not found") + found = False + return fname, found + + +def _read_double(fid, n=1): + """Read a double.""" + return np.fromfile(fid, ">f8", n) + + +def _read_string(fid, n_bytes, decode=True): + """Read string.""" + s0 = fid.read(n_bytes) + s = s0.split(b"\x00")[0] + return s.decode("utf-8") if decode else s + + +def _read_ustring(fid, n_bytes): + """Read unsigned character string.""" + return np.fromfile(fid, ">B", n_bytes) + + +def _read_int2(fid): + """Read int from short.""" + return _auto_cast(np.fromfile(fid, ">i2", 1)[0]) + + +def _read_int(fid): + """Read a 32-bit integer.""" + return np.fromfile(fid, ">i4", 1)[0] + + +def _move_to_next(fid, byte=8): + """Move to next byte boundary.""" + now = fid.tell() + if now % byte != 0: + now = now - (now % byte) + byte + fid.seek(now, 0) + + +def _read_filter(fid): + """Read filter information.""" + f = dict() + f["freq"] = _read_double(fid)[0] + f["class"] = _read_int(fid) + f["type"] = _read_int(fid) + f["npar"] = _read_int2(fid) + f["pars"] = _read_double(fid, f["npar"]) + return f + + +def _read_comp_coeff(fid, d): + """Read compensation coefficients.""" + # Read the coefficients and initialize + d["ncomp"] = _read_int2(fid) + d["comp"] = list() + # Read each record + dt = np.dtype( + [ + ("sensor_name", "S32"), + ("coeff_type", ">i4"), + ("d0", ">i4"), + ("ncoeff", ">i2"), + ("sensors", f"S{CTF.CTFV_SENSOR_LABEL}", CTF.CTFV_MAX_BALANCING), + ("coeffs", ">f8", CTF.CTFV_MAX_BALANCING), + ] + ) + comps = np.fromfile(fid, dt, d["ncomp"]) + for k in range(d["ncomp"]): + comp = dict() + d["comp"].append(comp) + comp["sensor_name"] = comps["sensor_name"][k].split(b"\x00")[0].decode("utf-8") + comp["coeff_type"] = comps["coeff_type"][k].item() + comp["ncoeff"] = comps["ncoeff"][k].item() + comp["sensors"] = [ + s.split(b"\x00")[0].decode("utf-8") + for s in comps["sensors"][k][: comp["ncoeff"]] + ] + comp["coeffs"] = comps["coeffs"][k][: comp["ncoeff"]] + comp["scanno"] = d["ch_names"].index(comp["sensor_name"]) + + +def _read_res4(dsdir): + """Read the magical res4 file.""" + # adapted from read_res4.c + name, _ = _make_ctf_name(dsdir, "res4") + res = dict() + with open(name, "rb") as fid: + # Read the fields + res["head"] = _read_string(fid, 8) + res["appname"] = _read_string(fid, 256) + res["origin"] = _read_string(fid, 256) + res["desc"] = _read_string(fid, 256) + res["nave"] = _read_int2(fid) + res["data_time"] = _read_string(fid, 255) + res["data_date"] = _read_string(fid, 255) + # Seems that date and time can be swapped + # (are they entered manually?!) + if "/" in res["data_time"] and ":" in res["data_date"]: + data_date = res["data_date"] + res["data_date"] = res["data_time"] + res["data_time"] = data_date + res["nsamp"] = _read_int(fid) + res["nchan"] = _read_int2(fid) + _move_to_next(fid, 8) + res["sfreq"] = _read_double(fid)[0] + res["epoch_time"] = _read_double(fid)[0] + res["no_trials"] = _read_int2(fid) + _move_to_next(fid, 4) + res["pre_trig_pts"] = _read_int(fid) + res["no_trials_done"] = _read_int2(fid) + res["no_trials_bst_message_windowlay"] = _read_int2(fid) + _move_to_next(fid, 4) + res["save_trials"] = _read_int(fid) + res["primary_trigger"] = fid.read(1) + res["secondary_trigger"] = [ + fid.read(1) for k in range(CTF.CTFV_MAX_AVERAGE_BINS) + ] + res["trigger_polarity_mask"] = fid.read(1) + res["trigger_mode"] = _read_int2(fid) + _move_to_next(fid, 4) + res["accept_reject"] = _read_int(fid) + res["run_time_bst_message_windowlay"] = _read_int2(fid) + _move_to_next(fid, 4) + res["zero_head"] = _read_int(fid) + _move_to_next(fid, 4) + res["artifact_mode"] = _read_int(fid) + _read_int(fid) # padding + res["nf_run_name"] = _read_string(fid, 32) + res["nf_run_title"] = _read_string(fid, 256) + res["nf_instruments"] = _read_string(fid, 32) + res["nf_collect_descriptor"] = _read_string(fid, 32) + res["nf_subject_id"] = _read_string(fid, 32) + res["nf_operator"] = _read_string(fid, 32) + if len(res["nf_operator"]) == 0: + res["nf_operator"] = None + res["nf_sensor_file_name"] = _read_ustring(fid, 60) + _move_to_next(fid, 4) + res["rdlen"] = _read_int(fid) + fid.seek(CTF.FUNNY_POS, 0) + + if res["rdlen"] > 0: + res["run_desc"] = _read_string(fid, res["rdlen"]) + + # Filters + res["nfilt"] = _read_int2(fid) + res["filters"] = list() + for k in range(res["nfilt"]): + res["filters"].append(_read_filter(fid)) + + # Channel information (names, then data) + res["ch_names"] = list() + for k in range(res["nchan"]): + ch_name = _read_string(fid, 32) + res["ch_names"].append(ch_name) + _coil_dt = np.dtype( + [ + ("pos", ">f8", 3), + ("d0", ">f8"), + ("norm", ">f8", 3), + ("d1", ">f8"), + ("turns", ">i2"), + ("d2", ">i4"), + ("d3", ">i2"), + ("area", ">f8"), + ] + ) + _ch_dt = np.dtype( + [ + ("sensor_type_index", ">i2"), + ("original_run_no", ">i2"), + ("coil_type", ">i4"), + ("proper_gain", ">f8"), + ("qgain", ">f8"), + ("io_gain", ">f8"), + ("io_offset", ">f8"), + ("num_coils", ">i2"), + ("grad_order_no", ">i2"), + ("d0", ">i4"), + ("coil", _coil_dt, CTF.CTFV_MAX_COILS), + ("head_coil", _coil_dt, CTF.CTFV_MAX_COILS), + ] + ) + chs = np.fromfile(fid, _ch_dt, res["nchan"]) + for coil in (chs["coil"], chs["head_coil"]): + coil["pos"] /= 100.0 + coil["area"] *= 1e-4 + # convert to dict + chs = [dict(zip(chs.dtype.names, x)) for x in chs] + for ch in chs: + for key, val in ch.items(): + ch[key] = _auto_cast(val) + res["chs"] = chs + for k in range(res["nchan"]): + res["chs"][k]["ch_name"] = res["ch_names"][k] + + # The compensation coefficients + _read_comp_coeff(fid, res) + logger.info(" res4 data read.") + return res + + +def _auto_cast(x): + # Upcast scalars + if isinstance(x, np.ScalarType): + if x.dtype.kind == "i": + if x.dtype != np.int64: + x = x.astype(np.int64) + elif x.dtype.kind == "f": + if x.dtype != np.float64: + x = x.astype(np.float64) + return x diff --git a/mne-python/source/mne/io/ctf/tests/__init__.py b/mne-python/source/mne/io/ctf/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/ctf/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/ctf/tests/test_ctf.py b/mne-python/source/mne/io/ctf/tests/test_ctf.py new file mode 100644 index 0000000000000000000000000000000000000000..448ea90baba5248f7caf5fa4cce5684f3c62c6c7 --- /dev/null +++ b/mne-python/source/mne/io/ctf/tests/test_ctf.py @@ -0,0 +1,736 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import copy +import os +import shutil +from datetime import datetime, timezone +from os import path as op + +import numpy as np +import pytest +from numpy import array_equal +from numpy.testing import assert_allclose, assert_array_equal + +import mne +import mne.io.ctf.info +from mne import ( + create_info, + events_from_annotations, + make_forward_solution, + pick_types, + read_annotations, +) +from mne._fiff.compensator import get_current_comp +from mne._fiff.constants import FIFF +from mne._fiff.pick import _picks_to_idx +from mne.datasets import brainstorm, spm_face, testing +from mne.io import RawArray, read_raw_ctf, read_raw_fif +from mne.io.ctf.constants import CTF +from mne.io.ctf.info import _convert_time +from mne.io.tests.test_raw import _test_raw_reader +from mne.tests.test_annotations import _assert_annotations_equal +from mne.transforms import apply_trans +from mne.utils import _clean_names, _record_warnings, _stamp_to_dt, catch_logging + +ctf_dir = testing.data_path(download=False) / "CTF" +ctf_fname_continuous = "testdata_ctf.ds" +ctf_fname_1_trial = "testdata_ctf_short.ds" +ctf_fname_2_trials = "testdata_ctf_pseudocontinuous.ds" +ctf_fname_discont = "testdata_ctf_short_discontinuous.ds" +ctf_fname_somato = "somMDYO-18av.ds" +ctf_fname_catch = "catch-alp-good-f.ds" +somato_fname = op.join( + brainstorm.bst_raw.data_path(download=False), + "MEG", + "bst_raw", + "subj001_somatosensory_20111109_01_AUX-f.ds", +) +spm_path = spm_face.data_path(download=False) + +block_sizes = { + ctf_fname_continuous: 12000, + ctf_fname_1_trial: 4801, + ctf_fname_2_trials: 12000, + ctf_fname_discont: 1201, + ctf_fname_somato: 313, + ctf_fname_catch: 2500, +} +single_trials = ( + ctf_fname_continuous, + ctf_fname_1_trial, +) + +ctf_fnames = tuple(sorted(block_sizes.keys())) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_read_ctf(tmp_path): + """Test CTF reader.""" + temp_dir = str(tmp_path) + out_fname = op.join(temp_dir, "test_py_raw.fif") + + # Create a dummy .eeg file so we can test our reading/application of it + os.mkdir(op.join(temp_dir, "randpos")) + ctf_eeg_fname = op.join(temp_dir, "randpos", ctf_fname_catch) + shutil.copytree(op.join(ctf_dir, ctf_fname_catch), ctf_eeg_fname) + with pytest.warns(RuntimeWarning, match="RMSP .* changed to a MISC ch"): + raw = _test_raw_reader(read_raw_ctf, directory=ctf_eeg_fname) + picks = pick_types(raw.info, meg=False, eeg=True) + pos = np.random.RandomState(42).randn(len(picks), 3) + fake_eeg_fname = op.join(ctf_eeg_fname, "catch-alp-good-f.eeg") + # Create a bad file + with open(fake_eeg_fname, "wb") as fid: + fid.write("foo\n".encode("ascii")) + pytest.raises(RuntimeError, read_raw_ctf, ctf_eeg_fname) + # Create a good file + with open(fake_eeg_fname, "wb") as fid: + for ii, ch_num in enumerate(picks): + args = ( + str(ch_num + 1), + raw.ch_names[ch_num], + ) + tuple(f"{x:0.5f}" for x in 100 * pos[ii]) # convert to cm + fid.write(("\t".join(args) + "\n").encode("ascii")) + pos_read_old = np.array([raw.info["chs"][p]["loc"][:3] for p in picks]) + with pytest.warns(RuntimeWarning, match="RMSP .* changed to a MISC ch"): + raw = read_raw_ctf(ctf_eeg_fname) # read modified data + pos_read = np.array([raw.info["chs"][p]["loc"][:3] for p in picks]) + assert_allclose( + apply_trans(raw.info["ctf_head_t"], pos), pos_read, rtol=1e-5, atol=1e-5 + ) + assert (pos_read == pos_read_old).mean() < 0.1 + shutil.copy( + op.join(ctf_dir, "catch-alp-good-f.ds_randpos_raw.fif"), + op.join(temp_dir, "randpos", "catch-alp-good-f.ds_raw.fif"), + ) + + # Create a version with no hc, starting out *with* EEG pos (error) + os.mkdir(op.join(temp_dir, "nohc")) + ctf_no_hc_fname = op.join(temp_dir, "no_hc", ctf_fname_catch) + shutil.copytree(ctf_eeg_fname, ctf_no_hc_fname) + remove_base = op.join(ctf_no_hc_fname, op.basename(ctf_fname_catch[:-3])) + os.remove(remove_base + ".hc") + with _record_warnings(), pytest.warns(RuntimeWarning, match="MISC channel"): + pytest.raises(RuntimeError, read_raw_ctf, ctf_no_hc_fname) + os.remove(remove_base + ".eeg") + shutil.copy( + op.join(ctf_dir, "catch-alp-good-f.ds_nohc_raw.fif"), + op.join(temp_dir, "no_hc", "catch-alp-good-f.ds_raw.fif"), + ) + + # All our files + use_fnames = [op.join(ctf_dir, c) for c in ctf_fnames] + for fname in use_fnames: + raw_c = read_raw_fif(fname + "_raw.fif", preload=True) + # sometimes matches "MISC channel" + with _record_warnings(): + raw = read_raw_ctf(fname) + + # check info match + assert_array_equal(raw.ch_names, raw_c.ch_names) + assert_allclose(raw.times, raw_c.times) + assert_allclose(raw._cals, raw_c._cals) + assert raw.info["meas_id"]["version"] == raw_c.info["meas_id"]["version"] + 1 + for t in ("dev_head_t", "dev_ctf_t", "ctf_head_t"): + assert_allclose( + raw.info[t]["trans"], raw_c.info[t]["trans"], rtol=1e-4, atol=1e-7 + ) + # XXX 2019/11/29 : MNC-C FIF conversion files don't have meas_date set. + # Consider adding meas_date to below checks once this is addressed in + # MNE-C + for key in ( + "acq_pars", + "acq_stim", + "bads", + "ch_names", + "custom_ref_applied", + "description", + "events", + "experimenter", + "highpass", + "line_freq", + "lowpass", + "nchan", + "proj_id", + "proj_name", + "projs", + "sfreq", + "subject_info", + ): + assert raw.info[key] == raw_c.info[key], key + if op.basename(fname) not in single_trials: + # We don't force buffer size to be smaller like MNE-C + assert raw.buffer_size_sec == raw_c.buffer_size_sec + assert len(raw.info["comps"]) == len(raw_c.info["comps"]) + for c1, c2 in zip(raw.info["comps"], raw_c.info["comps"]): + for key in ("colcals", "rowcals"): + assert_allclose(c1[key], c2[key]) + assert c1["save_calibrated"] == c2["save_calibrated"] + for key in ("row_names", "col_names", "nrow", "ncol"): + assert_array_equal(c1["data"][key], c2["data"][key]) + assert_allclose( + c1["data"]["data"], c2["data"]["data"], atol=1e-7, rtol=1e-5 + ) + assert_allclose( + raw.info["hpi_results"][0]["coord_trans"]["trans"], + raw_c.info["hpi_results"][0]["coord_trans"]["trans"], + rtol=1e-5, + atol=1e-7, + ) + assert len(raw.info["chs"]) == len(raw_c.info["chs"]) + for ii, (c1, c2) in enumerate(zip(raw.info["chs"], raw_c.info["chs"])): + for key in ( + "kind", + "scanno", + "unit", + "ch_name", + "unit_mul", + "range", + "coord_frame", + "coil_type", + "logno", + ): + if ( + c1["ch_name"] == "RMSP" + and "catch-alp-good-f" in fname + and key in ("kind", "unit", "coord_frame", "coil_type", "logno") + ): + continue # XXX see below... + if key == "coil_type" and c1[key] == FIFF.FIFFV_COIL_EEG: + # XXX MNE-C bug that this is not set + assert c2[key] == FIFF.FIFFV_COIL_NONE + continue + assert c1[key] == c2[key], key + for key in ("cal",): + assert_allclose( + c1[key], + c2[key], + atol=1e-6, + rtol=1e-4, + err_msg=f'raw.info["chs"][{ii}][{key}]', + ) + # XXX 2016/02/24: fixed bug with normal computation that used + # to exist, once mne-C tools are updated we should update our FIF + # conversion files, then the slices can go away (and the check + # can be combined with that for "cal") + for key in ("loc",): + if c1["ch_name"] == "RMSP" and "catch-alp-good-f" in fname: + continue + if (c2[key][:3] == 0.0).all(): + check = [np.nan] * 3 + else: + check = c2[key][:3] + assert_allclose( + c1[key][:3], + check, + atol=1e-6, + rtol=1e-4, + err_msg=f'raw.info["chs"][{ii}][{key}]', + ) + if (c2[key][3:] == 0.0).all(): + check = [np.nan] * 3 + else: + check = c2[key][9:12] + assert_allclose( + c1[key][9:12], + check, + atol=1e-6, + rtol=1e-4, + err_msg=f'raw.info["chs"][{ii}][{key}]', + ) + + # Make sure all digitization points are in the MNE head coord frame + for p in raw.info["dig"]: + assert p["coord_frame"] == FIFF.FIFFV_COORD_HEAD, ( + "dig points must be in FIFF.FIFFV_COORD_HEAD" + ) + + if fname.endswith("catch-alp-good-f.ds"): # omit points from .pos file + with raw.info._unlock(): + raw.info["dig"] = raw.info["dig"][:-10] + + # XXX: Next test would fail because c-tools assign the fiducials from + # CTF data as HPI. Should eventually clarify/unify with Matti. + # assert_dig_allclose(raw.info, raw_c.info) + + # check data match + raw_c.save(out_fname, overwrite=True, buffer_size_sec=1.0) + raw_read = read_raw_fif(out_fname) + + # so let's check tricky cases based on sample boundaries + rng = np.random.RandomState(0) + pick_ch = rng.permutation(np.arange(len(raw.ch_names)))[:10] + bnd = int(round(raw.info["sfreq"] * raw.buffer_size_sec)) + assert bnd == raw._raw_extras[0]["block_size"] + assert bnd == block_sizes[op.basename(fname)] + slices = ( + slice(0, bnd), + slice(bnd - 1, bnd), + slice(3, bnd), + slice(3, 300), + slice(None), + ) + if len(raw.times) >= 2 * bnd: # at least two complete blocks + slices = slices + ( + slice(bnd, 2 * bnd), + slice(bnd, bnd + 1), + slice(0, bnd + 100), + ) + for sl_time in slices: + assert_allclose(raw[pick_ch, sl_time][0], raw_c[pick_ch, sl_time][0]) + assert_allclose(raw_read[pick_ch, sl_time][0], raw_c[pick_ch, sl_time][0]) + # all data / preload + raw.load_data() + assert_allclose(raw[:][0], raw_c[:][0], atol=1e-15) + # test bad segment annotations + if "testdata_ctf_short.ds" in fname: + assert "bad" in raw.annotations.description[0] + assert_allclose(raw.annotations.onset, [2.15]) + assert_allclose(raw.annotations.duration, [0.0225]) + + with pytest.raises(TypeError, match="path-like"): + read_raw_ctf(1) + with pytest.raises(FileNotFoundError, match="does not exist"): + read_raw_ctf(ctf_fname_continuous + "foo.ds") + # test ignoring of system clock + read_raw_ctf(op.join(ctf_dir, ctf_fname_continuous), "ignore") + with pytest.raises(ValueError, match="system_clock"): + read_raw_ctf(op.join(ctf_dir, ctf_fname_continuous), "foo") + + +@testing.requires_testing_data +def test_rawctf_clean_names(): + """Test RawCTF _clean_names method.""" + # read test data + with pytest.warns(RuntimeWarning, match="ref channel RMSP did not"): + raw = read_raw_ctf(op.join(ctf_dir, ctf_fname_catch)) + raw_cleaned = read_raw_ctf(op.join(ctf_dir, ctf_fname_catch), clean_names=True) + test_channel_names = _clean_names(raw.ch_names) + test_info_comps = copy.deepcopy(raw.info["comps"]) + + # channel names should not be cleaned by default + assert raw.ch_names != test_channel_names + + chs_ch_names = [ch["ch_name"] for ch in raw.info["chs"]] + + assert chs_ch_names != test_channel_names + + for test_comp, comp in zip(test_info_comps, raw.info["comps"]): + for key in ("row_names", "col_names"): + assert not array_equal( + _clean_names(test_comp["data"][key]), comp["data"][key] + ) + + # channel names should be cleaned if clean_names=True + assert raw_cleaned.ch_names == test_channel_names + + for ch, test_ch_name in zip(raw_cleaned.info["chs"], test_channel_names): + assert ch["ch_name"] == test_ch_name + + for test_comp, comp in zip(test_info_comps, raw_cleaned.info["comps"]): + for key in ("row_names", "col_names"): + assert _clean_names(test_comp["data"][key]) == comp["data"][key] + + +@spm_face.requires_spm_data +def test_read_spm_ctf(): + """Test CTF reader with omitted samples.""" + raw_fname = op.join(spm_path, "MEG", "spm", "SPM_CTF_MEG_example_faces1_3D.ds") + raw = read_raw_ctf(raw_fname) + extras = raw._raw_extras[0] + assert extras["n_samp"] == raw.n_times + assert extras["n_samp"] != extras["n_samp_tot"] + + # Test that LPA, nasion and RPA are correct. + coord_frames = np.array([d["coord_frame"] for d in raw.info["dig"]]) + assert np.all(coord_frames == FIFF.FIFFV_COORD_HEAD) + cardinals = {d["ident"]: d["r"] for d in raw.info["dig"]} + assert cardinals[1][0] < cardinals[2][0] < cardinals[3][0] # x coord + assert cardinals[1][1] < cardinals[2][1] # y coord + assert cardinals[3][1] < cardinals[2][1] # y coord + for key in cardinals.keys(): + assert_allclose(cardinals[key][2], 0, atol=1e-6) # z coord + + +@testing.requires_testing_data +@pytest.mark.parametrize("comp_grade", [0, 1]) +def test_saving_picked(tmp_path, comp_grade): + """Test saving picked CTF instances.""" + temp_dir = str(tmp_path) + out_fname = op.join(temp_dir, "test_py_raw.fif") + raw = read_raw_ctf(op.join(ctf_dir, ctf_fname_1_trial)) + assert raw.info["meas_date"] == _stamp_to_dt((1367228160, 0)) + raw.crop(0, 1).load_data() + assert raw.compensation_grade == get_current_comp(raw.info) == 0 + assert len(raw.info["comps"]) == 5 + picks = _picks_to_idx(raw.info, "meg", with_ref_meg=False) + + raw.apply_gradient_compensation(comp_grade) + with catch_logging() as log: + raw_pick = raw.copy().pick(picks, verbose=True) + assert len(raw.info["comps"]) == 5 + assert len(raw_pick.info["comps"]) == 0 + log = log.getvalue() + assert "Removing 5 compensators" in log + raw_pick.save(out_fname, overwrite=True) # should work + raw2 = read_raw_fif(out_fname) + assert raw_pick.ch_names == raw2.ch_names + assert_array_equal(raw_pick.times, raw2.times) + assert_allclose( + raw2[0:20][0], raw_pick[0:20][0], rtol=1e-6, atol=1e-20 + ) # atol is very small but > 0 + + raw2 = read_raw_fif(out_fname, preload=True) + assert raw_pick.ch_names == raw2.ch_names + assert_array_equal(raw_pick.times, raw2.times) + assert_allclose( + raw2[0:20][0], raw_pick[0:20][0], rtol=1e-6, atol=1e-20 + ) # atol is very small but > 0 + + +@brainstorm.bst_raw.requires_bstraw_data +def test_read_ctf_annotations(): + """Test reading CTF marker file.""" + EXPECTED_LATENCIES = ( + np.array( + [ + 5640, + 7950, + 9990, + 12253, + 14171, + 16557, + 18896, + 20846, # noqa + 22702, + 24990, + 26830, + 28974, + 30906, + 33077, + 34985, + 36907, # noqa + 38922, + 40760, + 42881, + 45222, + 47457, + 49618, + 51802, + 54227, # noqa + 56171, + 58274, + 60394, + 62375, + 64444, + 66767, + 68827, + 71109, # noqa + 73499, + 75807, + 78146, + 80415, + 82554, + 84508, + 86403, + 88426, # noqa + 90746, + 92893, + 94779, + 96822, + 98996, + 99001, + 100949, + 103325, # noqa + 105322, + 107678, + 109667, + 111844, + 113682, + 115817, + 117691, + 119663, # noqa + 121966, + 123831, + 126110, + 128490, + 130521, + 132808, + 135204, + 137210, # noqa + 139130, + 141390, + 143660, + 145748, + 147889, + 150205, + 152528, + 154646, # noqa + 156897, + 159191, + 161446, + 163722, + 166077, + 168467, + 170624, + 172519, # noqa + 174719, + 176886, + 179062, + 181405, + 183709, + 186034, + 188454, + 190330, # noqa + 192660, + 194682, + 196834, + 199161, + 201035, + 203008, + 204999, + 207409, # noqa + 209661, + 211895, + 213957, + 216005, + 218040, + 220178, + 222137, + 224305, # noqa + 226297, + 228654, + 230755, + 232909, + 235205, + 237373, + 239723, + 241762, # noqa + 243748, + 245762, + 247801, + 250055, + 251886, + 254252, + 256441, + 258354, # noqa + 260680, + 263026, + 265048, + 267073, + 269235, + 271556, + 273927, + 276197, # noqa + 278436, + 280536, + 282691, + 284933, + 287061, + 288936, + 290941, + 293183, # noqa + 295369, + 297729, + 299626, + 301546, + 303449, + 305548, + 307882, + 310124, # noqa + 312374, + 314509, + 316815, + 318789, + 320981, + 322879, + 324878, + 326959, # noqa + 329341, + 331200, + 331201, + 333469, + 335584, + 337984, + 340143, + 342034, # noqa + 344360, + 346309, + 348544, + 350970, + 353052, + 355227, + 357449, + 359603, # noqa + 361725, + 363676, + 365735, + 367799, + 369777, + 371904, + 373856, + 376204, # noqa + 378391, + 380800, + 382859, + 385161, + 387093, + 389434, + 391624, + 393785, # noqa + 396093, + 398214, + 400198, + 402166, + 404104, + 406047, + 408372, + 410686, # noqa + 413029, + 414975, + 416850, + 418797, + 420824, + 422959, + 425026, + 427215, # noqa + 429278, + 431668, # noqa + ] + ) + - 1 + ) # Fieldtrip has 1 sample difference with MNE + + raw = RawArray( + data=np.empty((1, 432000), dtype=np.float64), + info=create_info(ch_names=1, sfreq=1200.0), + ) + raw.set_meas_date(read_raw_ctf(somato_fname).info["meas_date"]) + raw.set_annotations(read_annotations(somato_fname)) + + events, _ = events_from_annotations(raw) + latencies = np.sort(events[:, 0]) + assert_allclose(latencies, EXPECTED_LATENCIES, atol=1e-6) + + +@testing.requires_testing_data +def test_read_ctf_annotations_smoke_test(): + """Test reading CTF marker file. + + `testdata_ctf_mc.ds` has no trials or offsets therefore its a plain reading + of whatever is in the MarkerFile.mrk. + """ + EXPECTED_ONSET = [ + 0.0, + 0.1425, + 0.285, + 0.42833333, + 0.57083333, + 0.71416667, + 0.85666667, + 0.99916667, + 1.1425, + 1.285, + 1.4275, + 1.57083333, + 1.71333333, + 1.85666667, + 1.99916667, + 2.14166667, + 2.285, + 2.4275, + 2.57083333, + 2.71333333, + 2.85583333, + 2.99916667, + 3.14166667, + 3.28416667, + 3.4275, + 3.57, + 3.71333333, + 3.85583333, + 3.99833333, + 4.14166667, + 4.28416667, + 4.42666667, + 4.57, + 4.7125, + 4.85583333, + 4.99833333, + ] + fname = op.join(ctf_dir, "testdata_ctf_mc.ds") + annot = read_annotations(fname) + assert_allclose(annot.onset, EXPECTED_ONSET) + + raw = read_raw_ctf(fname) + _assert_annotations_equal(raw.annotations, annot, 1e-6) + + +def _read_res4_mag_comp(dsdir): + res = mne.io.ctf.res4._read_res4(dsdir) + for ch in res["chs"]: + if ch["sensor_type_index"] == CTF.CTFV_REF_MAG_CH: + ch["grad_order_no"] = 1 + return res + + +def _bad_res4_grad_comp(dsdir): + res = mne.io.ctf.res4._read_res4(dsdir) + for ch in res["chs"]: + if ch["sensor_type_index"] == CTF.CTFV_MEG_CH: + ch["grad_order_no"] = 1 + break + return res + + +@testing.requires_testing_data +def test_missing_res4(tmp_path): + """Test that res4 missing is handled gracefully.""" + use_ds = tmp_path / ctf_fname_continuous + shutil.copytree(ctf_dir / ctf_fname_continuous, tmp_path / ctf_fname_continuous) + read_raw_ctf(use_ds) + os.remove(use_ds / (ctf_fname_continuous[:-2] + "meg4")) + with pytest.raises(OSError, match="could not find the following"): + read_raw_ctf(use_ds) + + +@testing.requires_testing_data +def test_read_ctf_mag_bad_comp(tmp_path, monkeypatch): + """Test CTF reader with mag comps and bad comps.""" + path = op.join(ctf_dir, ctf_fname_continuous) + raw_orig = read_raw_ctf(path) + assert raw_orig.compensation_grade == 0 + monkeypatch.setattr(mne.io.ctf.ctf, "_read_res4", _read_res4_mag_comp) + raw_mag_comp = read_raw_ctf(path) + assert raw_mag_comp.compensation_grade == 0 + sphere = mne.make_sphere_model() + src = mne.setup_volume_source_space(pos=50.0, exclude=5.0, bem=sphere) + assert src[0]["nuse"] == 26 + for grade in (0, 1): + raw_orig.apply_gradient_compensation(grade) + raw_mag_comp.apply_gradient_compensation(grade) + args = (None, src, sphere, True, False) + fwd_orig = make_forward_solution(raw_orig.info, *args) + fwd_mag_comp = make_forward_solution(raw_mag_comp.info, *args) + assert_allclose(fwd_orig["sol"]["data"], fwd_mag_comp["sol"]["data"]) + monkeypatch.setattr(mne.io.ctf.ctf, "_read_res4", _bad_res4_grad_comp) + with pytest.raises(RuntimeError, match="inconsistent compensation grade"): + read_raw_ctf(path) + + +@testing.requires_testing_data +def test_invalid_meas_date(monkeypatch): + """Test handling of invalid meas_date.""" + + def _convert_time_bad(date_str, time_str): + return _convert_time("", "") + + monkeypatch.setattr(mne.io.ctf.info, "_convert_time", _convert_time_bad) + + with catch_logging() as log: + raw = read_raw_ctf(ctf_dir / ctf_fname_continuous, verbose=True) + log = log.getvalue() + assert "No date or time found" in log + assert raw.info["meas_date"] == datetime.fromtimestamp(0, tz=timezone.utc) diff --git a/mne-python/source/mne/io/ctf/trans.py b/mne-python/source/mne/io/ctf/trans.py new file mode 100644 index 0000000000000000000000000000000000000000..3e74063fa40c6f38e9b138c42b9d53fc7ba0673a --- /dev/null +++ b/mne-python/source/mne/io/ctf/trans.py @@ -0,0 +1,132 @@ +"""Create coordinate transforms.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ..._fiff.constants import FIFF +from ...transforms import ( + Transform, + _fit_matched_points, + _quat_to_affine, + apply_trans, + combine_transforms, + get_ras_to_neuromag_trans, + invert_transform, +) +from ...utils import logger +from .constants import CTF + + +def _make_transform_card(fro, to, r_lpa, r_nasion, r_rpa): + """Make a transform from cardinal landmarks.""" + return invert_transform( + Transform(to, fro, get_ras_to_neuromag_trans(r_nasion, r_lpa, r_rpa)) + ) + + +def _quaternion_align(from_frame, to_frame, from_pts, to_pts, diff_tol=1e-4): + """Perform an alignment using the unit quaternions (modifies points).""" + assert from_pts.shape[1] == to_pts.shape[1] == 3 + trans = _quat_to_affine(_fit_matched_points(from_pts, to_pts)[0]) + + # Test the transformation and print the results + logger.info(" Quaternion matching (desired vs. transformed):") + for fro, to in zip(from_pts, to_pts): + rr = apply_trans(trans, fro) + diff = np.linalg.norm(to - rr) + logger.info( + " %7.2f %7.2f %7.2f mm <-> %7.2f %7.2f %7.2f mm " + "(orig : %7.2f %7.2f %7.2f mm) diff = %8.3f mm" + % (tuple(1000 * to) + tuple(1000 * rr) + tuple(1000 * fro) + (1000 * diff,)) + ) + if diff > diff_tol: + raise RuntimeError( + "Something is wrong: quaternion matching did not work (see above)" + ) + return Transform(from_frame, to_frame, trans) + + +def _make_ctf_coord_trans_set(res4, coils): + """Figure out the necessary coordinate transforms.""" + # CTF head > Neuromag head + lpa = rpa = nas = T1 = T2 = T3 = T5 = None + if coils is not None: + for p in coils: + if p["valid"] and (p["coord_frame"] == FIFF.FIFFV_MNE_COORD_CTF_HEAD): + if lpa is None and p["kind"] == CTF.CTFV_COIL_LPA: + lpa = p + elif rpa is None and p["kind"] == CTF.CTFV_COIL_RPA: + rpa = p + elif nas is None and p["kind"] == CTF.CTFV_COIL_NAS: + nas = p + if lpa is None or rpa is None or nas is None: + raise RuntimeError( + "Some of the mandatory HPI device-coordinate info was not there." + ) + t = _make_transform_card("head", "ctf_head", lpa["r"], nas["r"], rpa["r"]) + T3 = invert_transform(t) + + # CTF device -> Neuromag device + # + # Rotate the CTF coordinate frame by 45 degrees and shift by 190 mm + # in z direction to get a coordinate system comparable to the Neuromag one + # + R = np.eye(4) + R[:3, 3] = [0.0, 0.0, 0.19] + val = 0.5 * np.sqrt(2.0) + R[0, 0] = val + R[0, 1] = -val + R[1, 0] = val + R[1, 1] = val + T4 = Transform("ctf_meg", "meg", R) + + # CTF device -> CTF head + # We need to make the implicit transform explicit! + h_pts = dict() + d_pts = dict() + kinds = ( + CTF.CTFV_COIL_LPA, + CTF.CTFV_COIL_RPA, + CTF.CTFV_COIL_NAS, + CTF.CTFV_COIL_SPARE, + ) + if coils is not None: + for p in coils: + if p["valid"]: + if p["coord_frame"] == FIFF.FIFFV_MNE_COORD_CTF_HEAD: + for kind in kinds: + if kind not in h_pts and p["kind"] == kind: + h_pts[kind] = p["r"] + elif p["coord_frame"] == FIFF.FIFFV_MNE_COORD_CTF_DEVICE: + for kind in kinds: + if kind not in d_pts and p["kind"] == kind: + d_pts[kind] = p["r"] + if any(kind not in h_pts for kind in kinds[:-1]): + raise RuntimeError( + "Some of the mandatory HPI device-coordinate info was not there." + ) + if any(kind not in d_pts for kind in kinds[:-1]): + raise RuntimeError( + "Some of the mandatory HPI head-coordinate info was not there." + ) + use_kinds = [kind for kind in kinds if (kind in h_pts and kind in d_pts)] + r_head = np.array([h_pts[kind] for kind in use_kinds]) + r_dev = np.array([d_pts[kind] for kind in use_kinds]) + T2 = _quaternion_align("ctf_meg", "ctf_head", r_dev, r_head) + + # The final missing transform + if T3 is not None and T2 is not None: + T5 = combine_transforms(T2, T3, "ctf_meg", "head") + T1 = combine_transforms(invert_transform(T4), T5, "meg", "head") + s = dict( + t_dev_head=T1, + t_ctf_dev_ctf_head=T2, + t_ctf_head_head=T3, + t_ctf_dev_dev=T4, + t_ctf_dev_head=T5, + ) + logger.info(" Coordinate transformations established.") + return s diff --git a/mne-python/source/mne/io/curry/__init__.py b/mne-python/source/mne/io/curry/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..5b2e89b6798b6ef90be5758e90cd2721abe13fc0 --- /dev/null +++ b/mne-python/source/mne/io/curry/__init__.py @@ -0,0 +1,8 @@ +"""Reader for CURRY data.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .curry import read_raw_curry +from .curry import read_impedances_curry diff --git a/mne-python/source/mne/io/curry/curry.py b/mne-python/source/mne/io/curry/curry.py new file mode 100644 index 0000000000000000000000000000000000000000..c1ffcad96fb5c1f60c96dc729f289d695207821a --- /dev/null +++ b/mne-python/source/mne/io/curry/curry.py @@ -0,0 +1,920 @@ +# +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import re +from datetime import datetime, timezone +from pathlib import Path + +import numpy as np + +from ..._fiff._digitization import _make_dig_points +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import create_info +from ..._fiff.tag import _coil_trans_to_loc +from ..._fiff.utils import _mult_cal_one, _read_segments_file +from ...annotations import annotations_from_events +from ...epochs import Epochs +from ...surface import _normal_orth +from ...transforms import ( + Transform, + _angle_between_quats, + apply_trans, + combine_transforms, + get_ras_to_neuromag_trans, + invert_transform, + rot_to_quat, +) +from ...utils import ( + _on_missing, + _soft_import, + catch_logging, + logger, + verbose, + warn, +) +from ..base import BaseRaw +from ..ctf.trans import _quaternion_align + +CURRY_SUFFIX_DATA = [".cdt", ".dat"] +CURRY_SUFFIX_HDR = [".cdt.dpa", ".cdt.dpo", ".dap"] +CURRY_SUFFIX_LABELS = [".cdt.dpa", ".cdt.dpo", ".rs3"] + + +def _get_curry_version(fname): + """Check out the curry file version.""" + fname_hdr = _check_curry_header_filename(_check_curry_filename(fname)) + content_hdr = fname_hdr.read_text() + return ( + "Curry 7" + if ".dap" in str(fname_hdr) + else "Curry 8" + if re.compile(r"FileVersion\s*=\s*[0-9]+") + .search(content_hdr) + .group(0) + .split()[-1][0] + == "8" + else "Curry 9" + if re.compile(r"FileVersion\s*=\s*[0-9]+") + .search(content_hdr) + .group(0) + .split()[-1][0] + == "9" + else None + ) + + +def _check_curry_filename(fname): + fname_in = Path(fname).expanduser() + fname_out = None + # try suffixes + if fname_in.suffix in CURRY_SUFFIX_DATA: + fname_out = fname_in + elif ( + fname_in.with_suffix("").exists() + and fname_in.with_suffix("").suffix in CURRY_SUFFIX_DATA + ): + fname_out = fname_in.with_suffix("") + else: + for data_suff in CURRY_SUFFIX_DATA: + if fname_in.with_suffix(data_suff).exists(): + fname_out = fname_in.with_suffix(data_suff) + break + # final check + if not fname_out or not fname_out.exists(): + raise FileNotFoundError( + f"no curry data file found (.dat or .cdt), checked {fname_out or fname_in}" + ) + return fname_out + + +def _check_curry_header_filename(fname): + fname_in = Path(fname) + fname_hdr = None + # try suffixes + for hdr_suff in CURRY_SUFFIX_HDR: + if fname_in.with_suffix(hdr_suff).exists(): + fname_hdr = fname_in.with_suffix(hdr_suff) + break + # final check + if not fname_hdr or not fname_in.exists(): + raise FileNotFoundError( + f"no corresponding header file found {CURRY_SUFFIX_HDR}" + ) + return fname_hdr + + +def _check_curry_labels_filename(fname): + fname_in = Path(fname) + fname_labels = None + # try suffixes + for hdr_suff in CURRY_SUFFIX_LABELS: + if fname_in.with_suffix(hdr_suff).exists(): + fname_labels = fname_in.with_suffix(hdr_suff) + break + # final check + if not fname_labels or not fname_in.exists(): + raise FileNotFoundError( + f"no corresponding labels file found {CURRY_SUFFIX_HDR}" + ) + return fname_labels + + +def _check_curry_sfreq_consistency(fname_hdr): + content_hdr = fname_hdr.read_text() + stime = float( + re.compile(r"SampleTimeUsec\s*=\s*.+").search(content_hdr).group(0).split()[-1] + ) + sfreq = float( + re.compile(r"SampleFreqHz\s*=\s*.+").search(content_hdr).group(0).split()[-1] + ) + if stime == 0: + raise ValueError("Header file indicates a sampling interval of 0µs.") + if not np.isclose(1e6 / stime, sfreq): + warn( + f"Sample distance ({stime}µs) and sample frequency ({sfreq}Hz) in header " + "file do not match! sfreq will be derived from sample distance." + ) + + +def _get_curry_meas_info(fname): + # Note that the time zone information is not stored in the Curry info + # file, and it seems the start time info is in the local timezone + # of the acquisition system (which is unknown); therefore, just set + # the timezone to be UTC. If the user knows otherwise, they can + # change it later. (Some Curry files might include StartOffsetUTCMin, + # but its presence is unpredictable, so we won't rely on it.) + fname_hdr = _check_curry_header_filename(fname) + content_hdr = fname_hdr.read_text() + + # read meas_date + meas_date = [ + int(re.compile(rf"{v}\s*=\s*-?\d+").search(content_hdr).group(0).split()[-1]) + for v in [ + "StartYear", + "StartMonth", + "StartDay", + "StartHour", + "StartMin", + "StartSec", + "StartMillisec", + ] + ] + try: + meas_date = datetime( + *meas_date[:-1], + meas_date[-1] * 1000, # -> microseconds + timezone.utc, + ) + except Exception: + meas_date = None + + # read datatype + byteorder = ( + re.compile(r"DataByteOrder\s*=\s*[A-Z]+") + .search(content_hdr) + .group() + .split()[-1] + ) + is_ascii = byteorder == "ASCII" + + # amplifier info + # TODO - PRIVACY + # seems like there can be identifiable information (serial numbers, dates). + # MNE anonymization functions only overwrite "serial" and "site", though + # TODO - FUTURE ENHANCEMENT + # # there can be filter details in AmplifierInfo, too + amp_info = ( + re.compile(r"AmplifierInfo\s*=.*\n") + .search(content_hdr) + .group() + .strip("\n") + .split("= ")[-1] + .strip() + ) + + device_info = ( + dict(serial=amp_info) + if amp_info != "" + else None # model="", serial="", site="" + ) + + return meas_date, is_ascii, device_info + + +def _get_curry_recording_type(fname): + _soft_import("curryreader", "read recording modality") + + import curryreader + + epochinfo = curryreader.read(str(fname), plotdata=0, verbosity=1)["epochinfo"] + if epochinfo.size == 0: + return "raw" + else: + n_average = epochinfo[:, 0] + if (n_average == 1).all(): + return "epochs" + else: + return "evoked" + + +def _get_curry_epoch_info(fname): + _soft_import("curryreader", "read epoch info") + _soft_import("pandas", "dataframe integration") + + import curryreader + import pandas as pd + + # use curry-python-reader + currydata = curryreader.read(str(fname), plotdata=0, verbosity=1) + + # get epoch info + sfreq = currydata["info"]["samplingfreq"] + n_samples = currydata["info"]["samples"] + n_epochs = len(currydata["epochlabels"]) + epochinfo = currydata["epochinfo"] + epochtypes = epochinfo[:, 2].astype(int).tolist() + epochlabels = currydata["epochlabels"] + epochmetainfo = pd.DataFrame( + epochinfo[:, -4:], columns=["accept", "correct", "response", "response time"] + ) + # create mne events + events = np.array( + [[i * n_samples for i in range(n_epochs)], [0] * n_epochs, epochtypes] + ).T + event_id = dict(zip(epochlabels, epochtypes)) + return dict( + events=events, + event_id=event_id, + tmin=0.0, + tmax=(n_samples - 1) / sfreq, + baseline=None, + detrend=None, + verbose=False, + metadata=epochmetainfo, + reject_by_annotation=False, + reject=None, + ) + + +def _get_curry_meg_normals(fname): + fname_lbl = _check_curry_labels_filename(fname) + normals_str = fname_lbl.read_text().split("\n") + # i_start, i_stop = [ + # i + # for i, ll in enumerate(normals_str) + # if ("NORMALS" in ll and "START_LIST" in ll) + # or ("NORMALS" in ll and "END_LIST" in ll) + # ] + # normals_str = [nn.split("\t") for nn in normals_str[i_start + 1 : i_stop]] + i_list = [ + i + for i, ll in enumerate(normals_str) + if ("NORMALS" in ll and "START_LIST" in ll) + or ("NORMALS" in ll and "END_LIST" in ll) + ] + assert len(i_list) % 2 == 0 + i_start_list = i_list[::2] + i_stop_list = i_list[1::2] + normals_str = [ + nn.split("\t") + for i_start, i_stop in zip(i_start_list, i_stop_list) + for nn in normals_str[i_start + 1 : i_stop] + ] + return np.array([[float(nnn.strip()) for nnn in nn] for nn in normals_str]) + + +def _extract_curry_info(fname): + _soft_import("curryreader", "read file header") + + import curryreader + + # check if sfreq values make sense + fname_hdr = _check_curry_header_filename(fname) + _check_curry_sfreq_consistency(fname_hdr) + + # use curry-python-reader + currydata = curryreader.read(str(fname), plotdata=0, verbosity=1) + + # basic info + sfreq = currydata["info"]["samplingfreq"] + n_samples = currydata["info"]["samples"] + if n_samples != currydata["data"].shape[0]: # normal in epoched data + n_samples = currydata["data"].shape[0] + if _get_curry_recording_type(fname) == "raw": + warn( + "sample count from header doesn't match actual data! " + "file corrupted? will use data shape" + ) + + # channel information + n_ch = currydata["info"]["channels"] + ch_names = currydata["labels"] + ch_pos = currydata["sensorpos"] + landmarks = currydata["landmarks"] + if not isinstance(landmarks, np.ndarray): + landmarks = np.array(landmarks) + landmarkslabels = currydata["landmarkslabels"] + hpimatrix = currydata["hpimatrix"] + if isinstance(currydata["hpimatrix"], np.ndarray) and hpimatrix.ndim == 1: + hpimatrix = hpimatrix[np.newaxis, :] + + # data + orig_format = "int" + # curryreader.py always reads float32, but this is probably just numpy. + # legacy MNE code states int. + + # events + events = currydata["events"] + annotations = currydata["annotations"] + assert len(annotations) == len(events) + if len(events) > 0: + event_desc = dict() + for k, v in zip(events[:, 1], annotations): + if int(k) not in event_desc.keys(): + event_desc[int(k)] = v.strip() if (v.strip() != "") else str(int(k)) + else: + event_desc = None + + # impedance measurements + # moved to standalone def; see read_impedances_curry + # impedances = currydata["impedances"] + + # get other essential info not provided by curryreader + # channel types and units + ch_types, units = [], [] + ch_groups = fname_hdr.read_text().split("DEVICE_PARAMETERS")[1::2] + for ch_group in ch_groups: + ch_group = re.compile(r"\s+").sub(" ", ch_group).strip() + groupid = ch_group.split()[0] + unit = ch_group.split("DataUnit = ")[1].split()[0] + n_ch_group = int(ch_group.split("NumChanThisGroup = ")[1].split()[0]) + ch_type = ( + "mag" if ("MAG" in groupid) else "misc" if ("OTHER" in groupid) else "eeg" + ) + # combine info + ch_types += [ch_type] * n_ch_group + units += [unit] * n_ch_group + + # This for Git issue #8391. In some cases, the 'labels' (.rs3 file will + # list channels that are not actually saved in the datafile (such as the + # 'Ref' channel). These channels are denoted in the 'info' (.dap) file + # in the CHAN_IN_FILE section with a '0' as their index. + # + # current curryreader cannot cope with this - loads the list of channels solely + # based on their order, so can be false. fix it here! + if not len(ch_types) == len(units) == len(ch_names) == n_ch: + # read relevant info + fname_lbl = _check_curry_labels_filename(fname) + lbl = fname_lbl.read_text().split("START_LIST") + ch_names_full = [] + for i in range(1, len(lbl)): + if "LABELS" in lbl[i - 1].split()[-1]: + for ll in lbl[i].split("\n")[1:]: + if "LABELS" not in ll: + ch_names_full.append(ll.strip()) + else: + break + hdr = fname_hdr.read_text().split("START_LIST") + chaninfile_full = [] + for i in range(1, len(hdr)): + if "CHAN_IN_FILE" in hdr[i - 1].split()[-1]: + for ll in hdr[i].split("\n")[1:]: + if "CHAN_IN_FILE" not in ll: + chaninfile_full.append(int(ll.strip())) + else: + break + # drop channels with chan_in_file==0, account for order + i_drop = [i for i, ich in enumerate(chaninfile_full) if ich == 0] + ch_names = [ + ch_names_full[i] for i in np.argsort(chaninfile_full) if i not in i_drop + ] + ch_pos = np.array( + [ + ch_pos[i] + for i in np.argsort(chaninfile_full) + if (i not in i_drop) and (i < len(ch_pos)) + ] + ) + ch_types = [ch_types[i] for i in np.argsort(chaninfile_full) if i not in i_drop] + units = [units[i] for i in np.argsort(chaninfile_full) if i not in i_drop] + + assert len(ch_types) == len(units) == len(ch_names) == n_ch + assert len(ch_pos) == ch_types.count("eeg") + ch_types.count("mag") + + # finetune channel types (e.g. stim, eog etc might be identified by name) + # TODO - FUTURE ENHANCEMENT + + # scale data to SI units + orig_units = dict(zip(ch_names, units)) + cals = [ + 1.0 / 1e15 if (u == "fT") else 1.0 / 1e6 if (u == "uV") else 1.0 for u in units + ] + + return ( + sfreq, + n_samples, + ch_names, + ch_types, + ch_pos, + landmarks, + landmarkslabels, + hpimatrix, + events, + event_desc, + orig_format, + orig_units, + cals, + ) + + +def _read_annotations_curry(fname, sfreq="auto"): + r"""Read events from Curry event files. + + Parameters + ---------- + fname : path-like + The filename. + sfreq : float | 'auto' + The sampling frequency in the file. If set to 'auto' then the + ``sfreq`` is taken from the fileheader. + + Returns + ------- + annot : instance of Annotations | None + The annotations. + """ + fname = _check_curry_filename(fname) + + (sfreq_fromfile, _, _, _, _, _, _, _, events, event_desc, _, _, _) = ( + _extract_curry_info(fname) + ) + if sfreq == "auto": + sfreq = sfreq_fromfile + elif np.isreal(sfreq): + if float(sfreq) != float(sfreq_fromfile): + warn( + f"provided sfreq ({sfreq} Hz) does not match freq from fileheader " + "({sfreq_fromfile} Hz)!" + ) + else: + raise ValueError("'sfreq' must be numeric or 'auto'") + + if isinstance(events, np.ndarray): # if there are events + events = events.astype("int") + events = np.insert(events, 1, np.diff(events[:, 2:]).flatten(), axis=1)[:, :3] + return annotations_from_events(events, sfreq, event_desc=event_desc) + else: + warn("no event annotations found") + return None + + +def _set_chanloc_curry( + inst, ch_types, ch_pos, landmarks, landmarkslabels, hpimatrix, on_bad_hpi_match +): + ch_names = inst.info["ch_names"] + + # scale ch_pos to m?! + ch_pos /= 1000.0 + landmarks /= 1000.0 + # channel locations + # what about misc without pos? can they mess things up if unordered? + assert len(ch_pos) >= (ch_types.count("mag") + ch_types.count("eeg")) + assert len(ch_pos) == (ch_types.count("mag") + ch_types.count("eeg")) + ch_pos_meg = { + ch_names[i]: ch_pos[i, :3] for i, t in enumerate(ch_types) if t == "mag" + } + ch_pos_eeg = { + ch_names[i]: ch_pos[i, :3] for i, t in enumerate(ch_types) if t == "eeg" + } + + # landmarks and headshape + # FIX: one of the test files (c,rfDC*.cdt) names landmarks differently: + NAS_NAMES = ["nasion", "nas"] + LPA_NAMES = ["left ear", "lpa"] + RPA_NAMES = ["right ear", "rpa"] + landmarkslabels = [ + "Nas" + if (ll.lower() in NAS_NAMES) + else "LPA" + if (ll.lower() in LPA_NAMES) + else "RPA" + if (ll.lower() in RPA_NAMES) + else ll + for ll in landmarkslabels + ] + landmark_dict = dict(zip(landmarkslabels, landmarks)) + for k in ["Nas", "RPA", "LPA"]: + if k not in landmark_dict.keys(): + landmark_dict[k] = None + if len(landmarkslabels) > 0: + hpi_pos = landmarks[ + [i for i, n in enumerate(landmarkslabels) if re.match("HPI.?[1-99]", n)], + :, + ] + else: + hpi_pos = None + if len(landmarkslabels) > 0: + hsp_pos = landmarks[ + [i for i, n in enumerate(landmarkslabels) if re.match("H.?[1-99]", n)], : + ] + else: + hsp_pos = None + + has_cards = ( + False + if ( + isinstance(landmark_dict["Nas"], type(None)) + and isinstance(landmark_dict["LPA"], type(None)) + and isinstance(landmark_dict["RPA"], type(None)) + ) + else True + ) + has_hpi = True if isinstance(hpi_pos, np.ndarray) else False + + add_missing_fiducials = not has_cards # raises otherwise + dig = _make_dig_points( + nasion=landmark_dict["Nas"], + lpa=landmark_dict["LPA"], + rpa=landmark_dict["RPA"], + hpi=hpi_pos, + extra_points=hsp_pos, + dig_ch_pos=ch_pos_eeg, + coord_frame="head", + add_missing_fiducials=add_missing_fiducials, + ) + with inst.info._unlock(): + inst.info["dig"] = dig + + # loc transformation for meg sensors (taken from previous version) + if len(ch_pos_meg) > 0: + R = np.eye(4) + R[[0, 1], [0, 1]] = -1 # rotate 180 deg + # shift down and back + # (chosen by eyeballing to make the helmet look roughly correct) + R[:3, 3] = [0.0, -0.015, -0.12] + curry_dev_dev_t = Transform("ctf_meg", "meg", R) + + ch_normals_meg = _get_curry_meg_normals(inst.filenames[0]) + assert len(ch_normals_meg) == len(ch_pos_meg) + else: + curry_dev_dev_t, ch_normals_meg = None, None + # fill up chanlocs + assert len(ch_names) == len(ch_types) >= len(ch_pos) + for i, (ch_name, ch_type, ch_loc) in enumerate(zip(ch_names, ch_types, ch_pos)): + assert inst.info["ch_names"][i] == ch_name + ch = inst.info["chs"][i] + if ch_type == "eeg": + with inst.info._unlock(): + ch["loc"][:3] = ch_loc[:3] + ch["coord_frame"] = FIFF.FIFFV_COORD_HEAD + elif ch_type == "mag": + # transform mode + pos = ch_loc[:3] # just the inner coil for MEG + pos = apply_trans(curry_dev_dev_t, pos) + nn = ch_normals_meg[i] + assert np.isclose(np.linalg.norm(nn), 1.0, atol=1e-4) + nn /= np.linalg.norm(nn) + nn = apply_trans(curry_dev_dev_t, nn, move=False) + trans = np.eye(4) + trans[:3, 3] = pos + trans[:3, :3] = _normal_orth(nn).T + with inst.info._unlock(): + ch["loc"] = _coil_trans_to_loc(trans) + # TODO: We should figure out if all files are Compumedics, + # and even then figure out if it's adult or child + ch["coil_type"] = FIFF.FIFFV_COIL_COMPUMEDICS_ADULT_GRAD + ch["coord_frame"] = FIFF.FIFFV_COORD_DEVICE + elif ch_type == "misc": + pass + else: + raise NotImplementedError + + # TODO - REVIEW NEEDED + # do we need further transformations for MEG channel positions? + # the testfiles i got look good to me.. + _make_trans_dig( + inst.info, + curry_dev_dev_t, + landmark_dict, + has_cards, + has_hpi, + hpimatrix, + on_bad_hpi_match, + ) + + +def _make_trans_dig( + info, + curry_dev_dev_t, + landmark_dict, + has_cards, + has_hpi, + chpidata, + on_bad_hpi_match, +): + cards = { + FIFF.FIFFV_POINT_LPA: landmark_dict["LPA"], + FIFF.FIFFV_POINT_NASION: landmark_dict["Nas"], + FIFF.FIFFV_POINT_RPA: landmark_dict["RPA"], + } + + # Coordinate frame transformations and definitions + no_msg = "Leaving device<->head transform as None" + info["dev_head_t"] = None + lm = [v for v in landmark_dict.values() if isinstance(v, np.ndarray)] + if len(lm) == 0: + # no dig + logger.info(no_msg + " (no landmarks found)") + return + + if has_cards and has_hpi: # have all three + logger.info("Composing device<->head transformation from dig points") + hpi_u = np.array( + [d["r"] for d in info["dig"] if d["kind"] == FIFF.FIFFV_POINT_HPI], float + ) + hpi_c = np.ascontiguousarray(chpidata[0][: len(hpi_u), 1:4]) + bad_hpi_match = False + try: + with catch_logging() as log: + unknown_curry_t = _quaternion_align( + "unknown", + "ctf_meg", + hpi_u.astype("float64"), + hpi_c.astype("float64"), + 1e-2, + ) + except RuntimeError: + bad_hpi_match = True + with catch_logging() as log: + unknown_curry_t = _quaternion_align( + "unknown", + "ctf_meg", + hpi_u.astype("float64"), + hpi_c.astype("float64"), + 1e-1, + ) + logger.info(log.getvalue()) + + angle = np.rad2deg( + _angle_between_quats( + np.zeros(3), rot_to_quat(unknown_curry_t["trans"][:3, :3]) + ) + ) + dist = 1000 * np.linalg.norm(unknown_curry_t["trans"][:3, 3]) + logger.info(f" Fit a {angle:0.1f}° rotation, {dist:0.1f} mm translation") + + if bad_hpi_match: + _on_missing( + on_bad_hpi_match, + "Poor HPI matching (see log above)!", + name="on_bad_hpi_match", + ) + + unknown_dev_t = combine_transforms( + unknown_curry_t, curry_dev_dev_t, "unknown", "meg" + ) + unknown_head_t = Transform( + "unknown", + "head", + get_ras_to_neuromag_trans( + *( + cards[key] + for key in ( + FIFF.FIFFV_POINT_NASION, + FIFF.FIFFV_POINT_LPA, + FIFF.FIFFV_POINT_RPA, + ) + ) + ), + ) + with info._unlock(): + info["dev_head_t"] = combine_transforms( + invert_transform(unknown_dev_t), unknown_head_t, "meg", "head" + ) + for d in info["dig"]: + d.update( + coord_frame=FIFF.FIFFV_COORD_HEAD, + r=apply_trans(unknown_head_t, d["r"]), + ) + else: + if has_cards: + no_msg += " (no .hpi file found)" + elif has_hpi: + no_msg += " (not all cardinal points found)" + else: + no_msg += " (neither cardinal points nor .hpi file found)" + logger.info(no_msg) + + +@verbose +def read_raw_curry( + fname, preload=False, on_bad_hpi_match="warn", verbose=None +) -> "RawCurry": + """Read raw data from Curry files. + + .. versionchanged:: 1.11 + This function now requires ``curryreader`` to be installed. + + Parameters + ---------- + fname : path-like + Path to a valid curry file. + %(preload)s + %(on_bad_hpi_match)s + %(verbose)s + + Returns + ------- + raw : instance of RawCurry + A Raw object containing Curry data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawCurry. + """ + fname = _check_curry_filename(fname) + fname_hdr = _check_curry_header_filename(fname) + + _check_curry_sfreq_consistency(fname_hdr) + + rectype = _get_curry_recording_type(fname) + + inst = RawCurry(fname, preload, on_bad_hpi_match, verbose) + if rectype in ["epochs", "evoked"]: + curry_epoch_info = _get_curry_epoch_info(fname) + inst = Epochs(inst, **curry_epoch_info) + if rectype == "evoked": + raise NotImplementedError # not sure this is even supported format + return inst + + +class RawCurry(BaseRaw): + """Raw object from Curry file. + + Parameters + ---------- + fname : path-like + Path to a valid curry file. + %(preload)s + %(on_bad_hpi_match)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + + """ + + @verbose + def __init__(self, fname, preload=False, on_bad_hpi_match="warn", verbose=None): + fname = _check_curry_filename(fname) + + ( + sfreq, + n_samples, + ch_names, + ch_types, + ch_pos, + landmarks, + landmarkslabels, + hpimatrix, + events, + event_desc, + orig_format, + orig_units, + cals, + ) = _extract_curry_info(fname) + + meas_date, is_ascii, device_info = _get_curry_meas_info(fname) + + # construct info + info = create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types) + info["device_info"] = device_info + + # create raw object + last_samps = [n_samples - 1] + raw_extras = dict(is_ascii=is_ascii) + super().__init__( + info, + preload=False, + filenames=[fname], + last_samps=last_samps, + orig_format=orig_format, + raw_extras=[raw_extras], + orig_units=orig_units, + verbose=verbose, + ) + + # set meas_date + self.set_meas_date(meas_date) + + # scale data to SI units + self._cals = np.array(cals) + if isinstance(preload, bool | np.bool_) and preload: + self.load_data() + + # set events / annotations + # format from curryreader: sample, etype, startsample, endsample + if isinstance(events, np.ndarray): # if there are events + events = events.astype("int") + events = np.insert(events, 1, np.diff(events[:, 2:]).flatten(), axis=1)[ + :, :3 + ] + annot = annotations_from_events(events, sfreq, event_desc=event_desc) + self.set_annotations(annot) + + # add HPI data (if present) + # TODO - FUTURE ENHANCEMENT + # from curryreader docstring: + # "HPI-coil measurements matrix (Orion-MEG only) where every row is: + # [measurementsample, dipolefitflag, x, y, z, deviation]" + # + # that's incorrect, though. it ratehr seems to be: + # [sample, dipole_1, x_1,y_1, z_1, dev_1, ..., dipole_n, x_n, ...] + # for all n coils. + # + # Do not implement cHPI reader for now. + # Can be used for dev-head transform, though! + if not isinstance(hpimatrix, list): + # warn("cHPI data found, but reader not implemented.") + hpisamples = hpimatrix[:, 0] + n_coil = int((hpimatrix.shape[1] - 1) / 5) + hpimatrix = hpimatrix[:, 1:].reshape(hpimatrix.shape[0], n_coil, 5) / 1000 + logger.info(f"found {len(hpisamples)} cHPI samples for {n_coil} coils") + + # add sensor locations + # TODO - REVIEW NEEDED + assert len(self.info["ch_names"]) == len(ch_types) >= len(ch_pos) + _set_chanloc_curry( + inst=self, + ch_types=ch_types, + ch_pos=ch_pos, + landmarks=landmarks, + landmarkslabels=landmarkslabels, + hpimatrix=hpimatrix, + on_bad_hpi_match=on_bad_hpi_match, + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + if self._raw_extras[fi]["is_ascii"]: + if isinstance(idx, slice): + idx = np.arange(idx.start, idx.stop) + block = np.loadtxt( + self.filenames[0], skiprows=start, max_rows=stop - start, ndmin=2 + ).T + _mult_cal_one(data, block, idx, cals, mult) + + else: + _read_segments_file( + self, data, idx, fi, start, stop, cals, mult, dtype=" 100 + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname", + [ + pytest.param(curry7_bdf_file, id="curry 7"), + pytest.param(curry8_bdf_file, id="curry 8"), + ], +) +def test_read_events_curry_are_same_as_bdf(fname): + """Test events from curry annotations recovers the right events.""" + EVENT_ID = {str(ii): ii for ii in range(5)} + REF_EVENTS = find_events(read_raw_bdf(bdf_file, preload=True)) + raw = read_raw_curry(fname) + events, _ = events_from_annotations(raw, event_id=EVENT_ID) + assert_allclose(events, REF_EVENTS) + assert not raw.info["dev_head_t"] + + +@testing.requires_testing_data +def test_check_missing_files(): + """Test checking for missing curry files (smoke test).""" + invalid_fname = "/invalid/path/name.xy" + + with pytest.raises(FileNotFoundError, match="no curry data file"): + _check_curry_filename(invalid_fname) + + with pytest.raises(FileNotFoundError, match="no corresponding header"): + _check_curry_header_filename(invalid_fname) + + with pytest.raises(FileNotFoundError, match="no curry data file"): + read_raw_curry(invalid_fname) + + with pytest.raises(FileNotFoundError, match="no curry data file"): + read_impedances_curry(invalid_fname) + + +def _mock_info_file(src, dst, sfreq, time_step): + with open(src) as in_file, open(dst, "w") as out_file: + for line in in_file: + if "SampleFreqHz" in line: + out_file.write(line.replace("500", str(sfreq))) + elif "SampleTimeUsec" in line: + out_file.write(line.replace("2000", str(time_step))) + else: + out_file.write(line) + + +# In the new version based on curryreader package, time_step is always prioritized, i.e. +# sfreq in the header file will be ignored and overridden by sampling interval +@pytest.fixture( + params=[ + pytest.param( + dict(sfreq=500, time_step=1), + id="correct sfreq", + ), + pytest.param(dict(sfreq=0, time_step=2000), id="correct time_step"), + pytest.param(dict(sfreq=500, time_step=2000), id="both correct"), + pytest.param( + dict(sfreq=0, time_step=0), + id="both 0", + ), + pytest.param( + dict(sfreq=500, time_step=42), + id="mismatch", + ), + ] +) +def sfreq_testing_data(tmp_path, request): + """Generate different sfreq, time_step scenarios to be tested.""" + sfreq, time_step = request.param["sfreq"], request.param["time_step"] + + # create dummy empty files for 'dat' and 'rs3' + for fname in ["curry.dat", "curry.rs3"]: + open(tmp_path / fname, "a").close() + + _mock_info_file( + src=curry7_bdf_file.with_suffix(".dap"), + dst=tmp_path / "curry.dap", + sfreq=sfreq, + time_step=time_step, + ) + _mock_info_file( + src=curry7_bdf_file.with_suffix(".rs3"), + dst=tmp_path / "curry.rs3", + sfreq=sfreq, + time_step=time_step, + ) + copyfile(curry7_bdf_file, tmp_path / "curry.dat") + + return tmp_path / "curry.dat", sfreq, time_step + + +@testing.requires_testing_data +def test_sfreq(sfreq_testing_data): + """Test sfreq and time_step.""" + fname, sfreq, time_step = sfreq_testing_data + if time_step == 0: + with pytest.raises(ValueError, match="sampling interval of 0µs."): + read_raw_curry(fname, preload=False) + else: + if sfreq != 1e6 / time_step: + with pytest.warns( + RuntimeWarning, match="sfreq will be derived from sample distance." + ): + raw = read_raw_curry(fname, preload=False) + else: + raw = read_raw_curry(fname, preload=False) + assert raw.info["sfreq"] == 1e6 / time_step + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname", + [ + pytest.param(curry_dir / "test_bdf_stim_channel Curry 7.cef", id="7"), + pytest.param( + curry_dir / "test_bdf_stim_channel Curry 7 ASCII.cef", id="7 ascii" + ), + pytest.param(curry_dir / "test_bdf_stim_channel Curry 8.cdt.cef", id="8"), + pytest.param( + curry_dir / "test_bdf_stim_channel Curry 8 ASCII.cdt.cef", id="8 ascii" + ), + ], +) +def test_read_curry_annotations(fname): + """Test reading for Curry events file.""" + EXPECTED_ONSET = [ + 0.484, + 0.486, + 0.62, + 0.622, + 1.904, + 1.906, + 3.212, + 3.214, + 4.498, + 4.5, + 5.8, + 5.802, + 7.074, + 7.076, + 8.324, + 8.326, + 9.58, + 9.582, + ] + EXPECTED_DURATION = np.zeros_like(EXPECTED_ONSET) + EXPECTED_DESCRIPTION = [ + "4", + "50000", + "2", + "50000", + "1", + "50000", + "1", + "50000", + "1", + "50000", + "1", + "50000", + "1", + "50000", + "1", + "50000", + "1", + "50000", + ] + + annot = read_annotations(fname, sfreq="auto") + + assert annot.orig_time is None + assert_array_equal(annot.onset, EXPECTED_ONSET) + assert_array_equal(annot.duration, EXPECTED_DURATION) + assert_array_equal(annot.description, EXPECTED_DESCRIPTION) + + with pytest.raises(ValueError, match="must be numeric or 'auto'"): + _ = read_annotations(fname, sfreq="nonsense") + with pytest.warns(RuntimeWarning, match="does not match freq from fileheader"): + _ = read_annotations(fname, sfreq=12.0) + + +FILE_EXTENSIONS = { + "Curry 7": { + "info": ".dap", + "data": ".dat", + "labels": ".rs3", + "events_cef": ".cef", + "events_ceo": ".ceo", + "hpi": ".hpi", + }, + "Curry 8": { + "info": ".cdt.dpa", + "data": ".cdt", + "labels": ".cdt.dpa", + "events_cef": ".cdt.cef", + "events_ceo": ".cdt.ceo", + "hpi": ".cdt.hpi", + }, + "Curry 9": { + "info": ".cdt.dpo", + "data": ".cdt", + "labels": ".cdt.dpo", + "events_cef": ".cdt.cef", + "events_ceo": ".cdt.ceo", + "hpi": ".cdt.hpi", + }, +} + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname", + [ + pytest.param(curry7_bdf_file, id="7"), + pytest.param(curry8_bdf_file, id="8"), + pytest.param(curry7_bdf_ascii_file, id="7 (ascii)"), + pytest.param(curry8_bdf_ascii_file, id="8 (ascii)"), + ], +) +def test_incomplete_file_suite(tmp_path, fname): + """Test reading incomplete Curry filesets.""" + original, modified = dict(), dict() + + version = _get_curry_version(fname) + + original["base"] = fname.with_suffix("") + original["event"] = fname.with_suffix(FILE_EXTENSIONS[version]["events_cef"]) + original["info"] = fname.with_suffix(FILE_EXTENSIONS[version]["info"]) + original["data"] = fname.with_suffix(FILE_EXTENSIONS[version]["data"]) + original["labels"] = fname.with_suffix(FILE_EXTENSIONS[version]["labels"]) + + modified["base"] = tmp_path / "curry" + modified["event"] = modified["base"].with_suffix( + FILE_EXTENSIONS[version]["events_cef"] + ) + modified["info"] = modified["base"].with_suffix(FILE_EXTENSIONS[version]["info"]) + modified["data"] = modified["base"].with_suffix(FILE_EXTENSIONS[version]["data"]) + modified["labels"] = modified["base"].with_suffix( + FILE_EXTENSIONS[version]["labels"] + ) + + # only data + copyfile(src=original["data"], dst=modified["data"]) + _msg = rf"does not exist: .*{modified['event'].name}.*" + with pytest.raises(FileNotFoundError, match=_msg): + read_annotations(modified["event"], sfreq="auto") + + # events missing + copyfile(src=original["info"], dst=modified["info"]) + with pytest.raises(FileNotFoundError, match=_msg): + read_annotations(modified["event"], sfreq="auto") + + # all there + copyfile(src=original["event"], dst=modified["event"]) + if not modified["labels"].exists(): + copyfile(src=original["labels"], dst=modified["labels"]) + read_raw_curry(modified["data"]) + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname,expected_channel_list", + [ + pytest.param( + Ref_chan_omitted_file, + ["FP1", "FPZ", "FP2", "VEO", "EKG", "Trigger"], + id="Ref omitted, normal order", + ), + pytest.param( + Ref_chan_omitted_reordered_file, + ["FP2", "FPZ", "FP1", "VEO", "EKG", "Trigger"], + id="Ref omitted, reordered", + ), + ], +) +def test_read_files_missing_channel(fname, expected_channel_list): + """Test reading data files that has an omitted channel.""" + # This for Git issue #8391. In some cases, the 'labels' (.rs3 file will + # list channels that are not actually saved in the datafile (such as the + # 'Ref' channel). These channels are denoted in the 'info' (.dap) file + # in the CHAN_IN_FILE section with a '0' as their index. + # If the CHAN_IN_FILE section is present, the code also assures that the + # channels are sorted in the prescribed order. + # This test makes sure the data load correctly, and that we end up with + # the proper channel list. + raw = read_raw_curry(fname, preload=True) + assert raw.ch_names == expected_channel_list + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname,expected_meas_date", + [ + pytest.param( + Ref_chan_omitted_file, + datetime(2018, 11, 21, 12, 53, 48, 525000, tzinfo=timezone.utc), + id="valid start date", + ), + pytest.param(curry7_rfDC_file, None, id="start date year is 0"), + pytest.param( + curry7_bdf_file, + None, + id="start date seconds invalid", + ), + ], +) +def test_meas_date(fname, expected_meas_date): + """Test reading acquisition start datetime info info['meas_date'].""" + # This for Git issue #8398. The 'info' (.dap) file includes acquisition + # start date & time. Test that this goes into raw.info['meas_date']. + # If the information is not valid, raw.info['meas_date'] should be None + raw = read_raw_curry(fname, preload=False) + assert raw.info["meas_date"] == expected_meas_date + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname, others", + [ + pytest.param(curry7_bdf_file, (".dap", ".rs3"), id="curry7"), + pytest.param(curry8_bdf_file, (".cdt.cef", ".cdt.dpa"), id="curry8"), + ], +) +def test_dot_names(fname, others, tmp_path): + """Test that dots are parsed properly (e.g., in paths).""" + my_path = tmp_path / "dot.dot.dot" + my_path.mkdir() + my_path = my_path / Path(fname).parts[-1] + fname = Path(fname) + copyfile(fname, my_path) + for ext in others: + this_fname = fname.with_suffix(ext) + to_fname = my_path.with_suffix(ext) + copyfile(this_fname, to_fname) + read_raw_curry(my_path) + + +@testing.requires_testing_data +def test_read_device_info(): + """Test extraction of device_info.""" + raw = read_raw_curry(curry7_bdf_file) + assert not raw.info["device_info"] + raw2 = read_raw_curry(Ref_chan_omitted_file) + assert isinstance(raw2.info["device_info"], dict) + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname", + [ + pytest.param(curry7_bdf_file, id="curry 7"), + pytest.param(curry8_bdf_file, id="curry 8"), + pytest.param(curry7_bdf_ascii_file, id="curry 7 ascii"), + pytest.param(curry8_bdf_ascii_file, id="curry 8 ascii"), + ], +) +def test_read_impedances_curry(fname): + """Test reading impedances from CURRY files.""" + _, imp = read_impedances_curry(fname) + actual_imp = np.empty(shape=(0, 3)) # TODO - need better testing data + assert_allclose( + imp, + actual_imp, + ) + + +def _mock_info_noeeg(src, dst): + # artificially remove eeg channels + content_hdr = src.read_text() + if ".dap" in src.name: + # curry 7 + content_hdr_ = content_hdr + elif ".rs3" in src.name: + # curry 7 + content_hdr_ = ( + content_hdr.split("NUMBERS START")[0] + + content_hdr.split("TRANSFORM END_LIST")[-1] + ) + else: + # curry 8 + content_hdr_ = ( + content_hdr.split("LABELS START")[0] + + content_hdr.split("SENSORS END_LIST")[-1] + ) + # both + content_hdr_ = content_hdr_.replace( + "NumChannels = 194", "NumChannels = 163" + ) + content_hdr_ = content_hdr_.replace( + "NumChanThisGroup = 31", "NumChanThisGroup = 0" + ) + content_hdr_ = content_hdr_.replace( + "NumSensorsThisGroup = 31", "NumSensorsThisGroup = 0" + ) + with dst.open("w+") as f: + f.write(content_hdr_) + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname,mont_present", + [ + pytest.param(curry7_bdf_file, True, id="curry 7"), + pytest.param(curry8_bdf_file, True, id="curry 8"), + pytest.param(curry7_bdf_ascii_file, True, id="curry 7 ascii"), + pytest.param(curry8_bdf_ascii_file, True, id="curry 8 ascii"), + pytest.param(curry7_rfDC_file, False, id="no eeg, curry 7"), + pytest.param(curry8_rfDC_file, False, id="no eeg, curry 8"), + pytest.param(curry_hpi_file, True, id="curry 8, w/ HPI data"), + ], +) +def test_read_montage_curry(tmp_path, fname, mont_present): + """Test reading montage from CURRY files.""" + if mont_present: + assert isinstance(read_dig_curry(fname), DigMontage) + else: + # copy files to tmp_path + for ext in (".cdt", ".cdt.hpi", ".cdt.dpa", ".dat", ".dap", ".rs3"): + src = fname.with_suffix(ext) + dst = tmp_path / fname.with_suffix(ext).name + if src.exists(): + if ext in [".cdt.dpa", ".dap", ".rs3"]: + _mock_info_noeeg(src, dst) + else: + copyfile(src, dst) + with pytest.raises(ValueError, match="No eeg sensor locations found"): + read_dig_curry(tmp_path / fname.name) diff --git a/mne-python/source/mne/io/edf/__init__.py b/mne-python/source/mne/io/edf/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..49e41a7ea5b66228b302b7e963998341fabc78ee --- /dev/null +++ b/mne-python/source/mne/io/edf/__init__.py @@ -0,0 +1,7 @@ +"""EDF+,BDF module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .edf import read_raw_edf, read_raw_bdf, read_raw_gdf diff --git a/mne-python/source/mne/io/edf/edf.py b/mne-python/source/mne/io/edf/edf.py new file mode 100644 index 0000000000000000000000000000000000000000..66200f5fcc6ecb1e6c1b7ffe6f86df662f6489c1 --- /dev/null +++ b/mne-python/source/mne/io/edf/edf.py @@ -0,0 +1,2357 @@ +"""Reading tools from EDF, EDF+, BDF, and GDF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import re +from datetime import date, datetime, timedelta, timezone +from enum import Enum +from pathlib import Path + +import numpy as np +from scipy.interpolate import interp1d + +from ..._edf.open import _gdf_edf_get_fid +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info, _unique_channel_names +from ..._fiff.utils import _blk_read_lims, _mult_cal_one +from ...annotations import Annotations +from ...filter import resample +from ...fixes import read_from_file_or_buffer +from ...utils import ( + _check_fname, + _file_like, + _validate_type, + fill_doc, + logger, + verbose, + warn, +) +from ..base import BaseRaw, _get_scaling + + +class FileType(Enum): + """Enumeration to differentiate files when the extension is not known.""" + + GDF = 1 + EDF = 2 + BDF = 3 + + +# common channel type names mapped to internal ch types +CH_TYPE_MAPPING = { + "EEG": FIFF.FIFFV_EEG_CH, + "SEEG": FIFF.FIFFV_SEEG_CH, + "ECOG": FIFF.FIFFV_ECOG_CH, + "DBS": FIFF.FIFFV_DBS_CH, + "EOG": FIFF.FIFFV_EOG_CH, + "ECG": FIFF.FIFFV_ECG_CH, + "EMG": FIFF.FIFFV_EMG_CH, + "BIO": FIFF.FIFFV_BIO_CH, + "RESP": FIFF.FIFFV_RESP_CH, + "TEMP": FIFF.FIFFV_TEMPERATURE_CH, + "MISC": FIFF.FIFFV_MISC_CH, + "SAO2": FIFF.FIFFV_BIO_CH, + "STIM": FIFF.FIFFV_STIM_CH, +} + + +@fill_doc +class RawEDF(BaseRaw): + """Raw object from EDF, EDF+ file. + + Parameters + ---------- + input_fname : path-like | file-like + Path to the EDF, EDF+ file. If a file-like object is provided, + preloading must be used. + + .. versionchanged:: 1.10 + Added support for file-like objects + eog : list or tuple + Names of channels or list of indices that should be designated EOG + channels. Values should correspond to the electrodes in the file. + Default is None. + misc : list or tuple + Names of channels or list of indices that should be designated MISC + channels. Values should correspond to the electrodes in the file. + Default is None. + stim_channel : ``'auto'`` | str | list of str | int | list of int + Defaults to ``'auto'``, which means that channels named ``'status'`` or + ``'trigger'`` (case insensitive) are set to STIM. If str (or list of + str), all channels matching the name(s) are set to STIM. If int (or + list of ints), the channels corresponding to the indices are set to + STIM. + exclude : list of str + Channel names to exclude. This can help when reading data with + different sampling rates to avoid unnecessary resampling. + infer_types : bool + If True, try to infer channel types from channel labels. If a channel + label starts with a known type (such as 'EEG') followed by a space and + a name (such as 'Fp1'), the channel type will be set accordingly, and + the channel will be renamed to the original label without the prefix. + For unknown prefixes, the type will be 'EEG' and the name will not be + modified. If False, do not infer types and assume all channels are of + type 'EEG'. + + .. versionadded:: 0.24.1 + include : list of str | str + Channel names to be included. A str is interpreted as a regular + expression. 'exclude' must be empty if include is assigned. + + .. versionadded:: 1.1 + %(preload)s + %(units_edf_bdf_io)s + %(encoding_edf)s + %(exclude_after_unique)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + mne.io.read_raw_edf : Recommended way to read EDF/EDF+ files. + + Notes + ----- + %(edf_resamp_note)s + + Biosemi devices trigger codes are encoded in 16-bit format, whereas system + codes (CMS in/out-of range, battery low, etc.) are coded in bits 16-23 of + the status channel (see http://www.biosemi.com/faq/trigger_signals.htm). + To retrieve correct event values (bits 1-16), one could do: + + >>> events = mne.find_events(...) # doctest:+SKIP + >>> events[:, 2] &= (2**16 - 1) # doctest:+SKIP + + The above operation can be carried out directly in :func:`mne.find_events` + using the ``mask`` and ``mask_type`` parameters (see + :func:`mne.find_events` for more details). + + It is also possible to retrieve system codes, but no particular effort has + been made to decode these in MNE. In case it is necessary, for instance to + check the CMS bit, the following operation can be carried out: + + >>> cms_bit = 20 # doctest:+SKIP + >>> cms_high = (events[:, 2] & (1 << cms_bit)) != 0 # doctest:+SKIP + + It is worth noting that in some special cases, it may be necessary to shift + event values in order to retrieve correct event triggers. This depends on + the triggering device used to perform the synchronization. For instance, in + some files events need to be shifted by 8 bits: + + >>> events[:, 2] >>= 8 # doctest:+SKIP + + TAL channels called 'EDF Annotations' are parsed and + extracted annotations are stored in raw.annotations. Use + :func:`mne.events_from_annotations` to obtain events from these + annotations. + + If channels named 'status' or 'trigger' are present, they are considered as + STIM channels by default. Use :func:`mne.find_events` to parse events + encoded in such analog stim channels. + """ + + @verbose + def __init__( + self, + input_fname, + eog=None, + misc=None, + stim_channel="auto", + exclude=(), + infer_types=False, + preload=False, + include=None, + units=None, + encoding="utf8", + exclude_after_unique=False, + *, + verbose=None, + ): + if not _file_like(input_fname): + logger.info(f"Extracting EDF parameters from {input_fname}...") + input_fname = os.path.abspath(input_fname) + + info, edf_info, orig_units = _get_info( + input_fname, + stim_channel, + eog, + misc, + exclude, + infer_types, + FileType.EDF, + include, + exclude_after_unique, + ) + logger.info("Creating raw.info structure...") + edf_info["blob"] = input_fname if _file_like(input_fname) else None + + _validate_type(units, (str, None, dict), "units") + if units is None: + units = dict() + elif isinstance(units, str): + units = {ch_name: units for ch_name in info["ch_names"]} + + for k, (this_ch, this_unit) in enumerate(orig_units.items()): + if this_ch not in units: + continue + if this_unit not in ("", units[this_ch]): + raise ValueError( + f"Unit for channel {this_ch} is present in the file as " + f"{repr(this_unit)}, cannot overwrite it with the units " + f"argument {repr(units[this_ch])}." + ) + if this_unit == "": + orig_units[this_ch] = units[this_ch] + ch_type = edf_info["ch_types"][k] + scaling = _get_scaling(ch_type.lower(), orig_units[this_ch]) + edf_info["units"][k] /= scaling + + # Raw attributes + last_samps = [edf_info["nsamples"] - 1] + super().__init__( + info, + preload, + filenames=[_path_from_fname(input_fname)], + raw_extras=[edf_info], + last_samps=last_samps, + orig_format="int", + orig_units=orig_units, + verbose=verbose, + ) + + # Read annotations from file and set it + if len(edf_info["tal_idx"]) > 0: + # Read TAL data exploiting the header info (no regexp) + idx = np.empty(0, int) + tal_data = self._read_segment_file( + np.empty((0, self.n_times)), + idx, + 0, + 0, + int(self.n_times), + np.ones((len(idx), 1)), + None, + ) + annotations = _read_annotations_edf( + tal_data[0], + ch_names=info["ch_names"], + encoding=encoding, + ) + self.set_annotations(annotations, on_missing="warn") + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + return _read_segment_file( + data, + idx, + fi, + start, + stop, + self._raw_extras[fi], + self.filenames[fi] + if self._raw_extras[fi]["blob"] is None + else self._raw_extras[fi]["blob"], + cals, + mult, + ) + + +def _path_from_fname(fname) -> Path | None: + if isinstance(fname, str | Path): + return Path(fname) + + # Try to get a filename from the file-like object + try: + return Path(fname.name) + except Exception: + return None + + +@fill_doc +class RawBDF(BaseRaw): + """Raw object from BDF file. + + Parameters + ---------- + input_fname : path-like | file-like + Path to the BDF file. If a file-like object is provided, + preloading must be used. + + .. versionchanged:: 1.10 + Added support for file-like objects + eog : list or tuple + Names of channels or list of indices that should be designated EOG + channels. Values should correspond to the electrodes in the file. + Default is None. + misc : list or tuple + Names of channels or list of indices that should be designated MISC + channels. Values should correspond to the electrodes in the file. + Default is None. + stim_channel : ``'auto'`` | str | list of str | int | list of int + Defaults to ``'auto'``, which means that channels named ``'status'`` or + ``'trigger'`` (case insensitive) are set to STIM. If str (or list of + str), all channels matching the name(s) are set to STIM. If int (or + list of ints), the channels corresponding to the indices are set to + STIM. + exclude : list of str + Channel names to exclude. This can help when reading data with + different sampling rates to avoid unnecessary resampling. + infer_types : bool + If True, try to infer channel types from channel labels. If a channel + label starts with a known type (such as 'EEG') followed by a space and + a name (such as 'Fp1'), the channel type will be set accordingly, and + the channel will be renamed to the original label without the prefix. + For unknown prefixes, the type will be 'EEG' and the name will not be + modified. If False, do not infer types and assume all channels are of + type 'EEG'. + + .. versionadded:: 0.24.1 + include : list of str | str + Channel names to be included. A str is interpreted as a regular + expression. 'exclude' must be empty if include is assigned. + + .. versionadded:: 1.1 + %(preload)s + %(units_edf_bdf_io)s + %(encoding_edf)s + %(exclude_after_unique)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + mne.io.read_raw_bdf : Recommended way to read BDF files. + + Notes + ----- + %(edf_resamp_note)s + + Biosemi devices trigger codes are encoded in 16-bit format, whereas system + codes (CMS in/out-of range, battery low, etc.) are coded in bits 16-23 of + the status channel (see http://www.biosemi.com/faq/trigger_signals.htm). + To retrieve correct event values (bits 1-16), one could do: + + >>> events = mne.find_events(...) # doctest:+SKIP + >>> events[:, 2] &= (2**16 - 1) # doctest:+SKIP + + The above operation can be carried out directly in :func:`mne.find_events` + using the ``mask`` and ``mask_type`` parameters (see + :func:`mne.find_events` for more details). + + It is also possible to retrieve system codes, but no particular effort has + been made to decode these in MNE. In case it is necessary, for instance to + check the CMS bit, the following operation can be carried out: + + >>> cms_bit = 20 # doctest:+SKIP + >>> cms_high = (events[:, 2] & (1 << cms_bit)) != 0 # doctest:+SKIP + + It is worth noting that in some special cases, it may be necessary to shift + event values in order to retrieve correct event triggers. This depends on + the triggering device used to perform the synchronization. For instance, in + some files events need to be shifted by 8 bits: + + >>> events[:, 2] >>= 8 # doctest:+SKIP + + TAL channels called 'BDF Annotations' are parsed and + extracted annotations are stored in raw.annotations. Use + :func:`mne.events_from_annotations` to obtain events from these + annotations. + + If channels named 'status' or 'trigger' are present, they are considered as + STIM channels by default. Use :func:`mne.find_events` to parse events + encoded in such analog stim channels. + """ + + @verbose + def __init__( + self, + input_fname, + eog=None, + misc=None, + stim_channel="auto", + exclude=(), + infer_types=False, + preload=False, + include=None, + units=None, + encoding="utf8", + exclude_after_unique=False, + *, + verbose=None, + ): + if not _file_like(input_fname): + logger.info(f"Extracting BDF parameters from {input_fname}...") + input_fname = os.path.abspath(input_fname) + + info, edf_info, orig_units = _get_info( + input_fname, + stim_channel, + eog, + misc, + exclude, + infer_types, + FileType.BDF, + include, + exclude_after_unique, + ) + logger.info("Creating raw.info structure...") + edf_info["blob"] = input_fname if _file_like(input_fname) else None + + _validate_type(units, (str, None, dict), "units") + if units is None: + units = dict() + elif isinstance(units, str): + units = {ch_name: units for ch_name in info["ch_names"]} + + for k, (this_ch, this_unit) in enumerate(orig_units.items()): + if this_ch not in units: + continue + if this_unit not in ("", units[this_ch]): + raise ValueError( + f"Unit for channel {this_ch} is present in the file as " + f"{repr(this_unit)}, cannot overwrite it with the units " + f"argument {repr(units[this_ch])}." + ) + if this_unit == "": + orig_units[this_ch] = units[this_ch] + ch_type = edf_info["ch_types"][k] + scaling = _get_scaling(ch_type.lower(), orig_units[this_ch]) + edf_info["units"][k] /= scaling + + # Raw attributes + last_samps = [edf_info["nsamples"] - 1] + super().__init__( + info, + preload, + filenames=[_path_from_fname(input_fname)], + raw_extras=[edf_info], + last_samps=last_samps, + orig_format="int", + orig_units=orig_units, + verbose=verbose, + ) + + # Read annotations from file and set it + if len(edf_info["tal_idx"]) > 0: + # Read TAL data exploiting the header info (no regexp) + idx = np.empty(0, int) + tal_data = self._read_segment_file( + np.empty((0, self.n_times)), + idx, + 0, + 0, + int(self.n_times), + np.ones((len(idx), 1)), + None, + ) + annotations = _read_annotations_edf( + tal_data[0], + ch_names=info["ch_names"], + encoding=encoding, + ) + self.set_annotations(annotations, on_missing="warn") + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + return _read_segment_file( + data, + idx, + fi, + start, + stop, + self._raw_extras[fi], + self.filenames[fi] + if self._raw_extras[fi]["blob"] is None + else self._raw_extras[fi]["blob"], + cals, + mult, + ) + + +@fill_doc +class RawGDF(BaseRaw): + """Raw object from GDF file. + + Parameters + ---------- + input_fname : path-like | file-like + Path to the GDF file. If a file-like object is provided, + preloading must be used. + + .. versionchanged:: 1.10 + Added support for file-like objects + eog : list or tuple + Names of channels or list of indices that should be designated EOG + channels. Values should correspond to the electrodes in the file. + Default is None. + misc : list or tuple + Names of channels or list of indices that should be designated MISC + channels. Values should correspond to the electrodes in the file. + Default is None. + stim_channel : ``'auto'`` | str | list of str | int | list of int + Defaults to 'auto', which means that channels named 'status' or + 'trigger' (case insensitive) are set to STIM. If str (or list of str), + all channels matching the name(s) are set to STIM. If int (or list of + ints), channels corresponding to the indices are set to STIM. + exclude : list of str + Channel names to exclude. This can help when reading data with + different sampling rates to avoid unnecessary resampling. + + .. versionadded:: 0.24.1 + include : list of str | str + Channel names to be included. A str is interpreted as a regular + expression. 'exclude' must be empty if include is assigned. + + .. versionadded:: 1.1 + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + mne.io.read_raw_gdf : Recommended way to read GDF files. + + Notes + ----- + If channels named 'status' or 'trigger' are present, they are considered as + STIM channels by default. Use :func:`mne.find_events` to parse events + encoded in such analog stim channels. + """ + + @verbose + def __init__( + self, + input_fname, + eog=None, + misc=None, + stim_channel="auto", + exclude=(), + preload=False, + include=None, + verbose=None, + ): + if not _file_like(input_fname): + logger.info(f"Extracting GDF parameters from {input_fname}...") + input_fname = os.path.abspath(input_fname) + + info, edf_info, orig_units = _get_info( + input_fname, + stim_channel, + eog, + misc, + exclude, + True, + FileType.GDF, + include, + ) + logger.info("Creating raw.info structure...") + edf_info["blob"] = input_fname if _file_like(input_fname) else None + + # Raw attributes + last_samps = [edf_info["nsamples"] - 1] + super().__init__( + info, + preload, + filenames=[_path_from_fname(input_fname)], + raw_extras=[edf_info], + last_samps=last_samps, + orig_format="int", + orig_units=orig_units, + verbose=verbose, + ) + + # Read annotations from file and set it + onset, duration, desc = _get_annotations_gdf(edf_info, self.info["sfreq"]) + + self.set_annotations( + Annotations( + onset=onset, duration=duration, description=desc, orig_time=None + ) + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + return _read_segment_file( + data, + idx, + fi, + start, + stop, + self._raw_extras[fi], + self.filenames[fi] + if self._raw_extras[fi]["blob"] is None + else self._raw_extras[fi]["blob"], + cals, + mult, + ) + + +def _read_ch(fid, subtype, samp, dtype_byte, dtype=None): + """Read a number of samples for a single channel.""" + # BDF + if subtype == "bdf": + ch_data = read_from_file_or_buffer(fid, dtype=dtype, count=samp * dtype_byte) + ch_data = ch_data.reshape(-1, 3).astype(INT32) + ch_data = (ch_data[:, 0]) + (ch_data[:, 1] << 8) + (ch_data[:, 2] << 16) + # 24th bit determines the sign + ch_data[ch_data >= (1 << 23)] -= 1 << 24 + + # GDF data and EDF data + else: + ch_data = read_from_file_or_buffer(fid, dtype=dtype, count=samp) + + return ch_data + + +def _read_segment_file(data, idx, fi, start, stop, raw_extras, filenames, cals, mult): + """Read a chunk of raw data.""" + n_samps = raw_extras["n_samps"] + buf_len = int(raw_extras["max_samp"]) + dtype = raw_extras["dtype_np"] + dtype_byte = raw_extras["dtype_byte"] + data_offset = raw_extras["data_offset"] + stim_channel_idxs = raw_extras["stim_channel_idxs"] + orig_sel = raw_extras["sel"] + tal_idx = raw_extras.get("tal_idx", np.empty(0, int)) + subtype = raw_extras["subtype"] + cal = raw_extras["cal"] + offsets = raw_extras["offsets"] + gains = raw_extras["units"] + + read_sel = np.concatenate([orig_sel[idx], tal_idx]) + tal_data = [] + + # only try to read the stim channel if it's not None and it's + # actually one of the requested channels + idx_arr = np.arange(idx.start, idx.stop) if isinstance(idx, slice) else idx + + # We could read this one EDF block at a time, which would be this: + ch_offsets = np.cumsum(np.concatenate([[0], n_samps]), dtype=np.int64) + block_start_idx, r_lims, _ = _blk_read_lims(start, stop, buf_len) + # But to speed it up, we really need to read multiple blocks at once, + # Otherwise we can end up with e.g. 18,181 chunks for a 20 MB file! + # Let's do ~10 MB chunks: + n_per = max(10 * 1024 * 1024 // (ch_offsets[-1] * dtype_byte), 1) + + with _gdf_edf_get_fid(filenames, buffering=0) as fid: + # Extract data + start_offset = data_offset + block_start_idx * ch_offsets[-1] * dtype_byte + + # first read everything into the `ones` array. For channels with + # lower sampling frequency, there will be zeros left at the end of the + # row. Ignore TAL/annotations channel and only store `orig_sel` + ones = np.zeros((len(orig_sel), data.shape[-1]), dtype=data.dtype) + # save how many samples have already been read per channel + n_smp_read = [0 for _ in range(len(orig_sel))] + + # read data in chunks + for ai in range(0, len(r_lims), n_per): + block_offset = ai * ch_offsets[-1] * dtype_byte + n_read = min(len(r_lims) - ai, n_per) + fid.seek(start_offset + block_offset, 0) + # Read and reshape to (n_chunks_read, ch0_ch1_ch2_ch3...) + many_chunk = _read_ch( + fid, subtype, ch_offsets[-1] * n_read, dtype_byte, dtype + ).reshape(n_read, -1) + r_sidx = r_lims[ai][0] + r_eidx = buf_len * (n_read - 1) + r_lims[ai + n_read - 1][1] + + # loop over selected channels, ci=channel selection + for ii, ci in enumerate(read_sel): + # This now has size (n_chunks_read, n_samp[ci]) + ch_data = many_chunk[:, ch_offsets[ci] : ch_offsets[ci + 1]].copy() + + # annotation channel has to be treated separately + if ci in tal_idx: + tal_data.append(ch_data) + continue + + orig_idx = idx_arr[ii] + ch_data = ch_data * cal[orig_idx] + ch_data += offsets[orig_idx] + ch_data *= gains[orig_idx] + + assert ci == orig_sel[orig_idx] + + if n_samps[ci] != buf_len: + if orig_idx in stim_channel_idxs: + # Stim channel will be interpolated + old = np.linspace(0, 1, n_samps[ci] + 1, True) + new = np.linspace(0, 1, buf_len, False) + ch_data = np.append(ch_data, np.zeros((len(ch_data), 1)), -1) + ch_data = interp1d(old, ch_data, kind="zero", axis=-1)(new) + elif orig_idx in stim_channel_idxs: + ch_data = np.bitwise_and(ch_data.astype(int), 2**17 - 1) + + one_i = ch_data.ravel()[r_sidx:r_eidx] + + # note how many samples have been read + smp_read = n_smp_read[orig_idx] + ones[orig_idx, smp_read : smp_read + len(one_i)] = one_i + n_smp_read[orig_idx] += len(one_i) + + # resample channels with lower sample frequency + # skip if no data was requested, ie. only annotations were read + if any(n_smp_read) > 0: + # expected number of samples, equals maximum sfreq + smp_exp = data.shape[-1] + + # resample data after loading all chunks to prevent edge artifacts + resampled = False + + for i, smp_read in enumerate(n_smp_read): + # nothing read, nothing to resample + if smp_read == 0: + continue + # upsample if n_samples is lower than from highest sfreq + if smp_read != smp_exp: + # sanity check that we read exactly how much we expected + assert (ones[i, smp_read:] == 0).all() + + ones[i, :] = resample( + ones[i, :smp_read].astype(np.float64), + smp_exp, + smp_read, + npad=0, + axis=-1, + ) + resampled = True + + # give warning if we resampled a subselection + if resampled and raw_extras["nsamples"] != (stop - start): + warn( + "Loading an EDF with mixed sampling frequencies and " + "preload=False will result in edge artifacts. " + "It is recommended to use preload=True." + "See also https://github.com/mne-tools/mne-python/issues/10635" + ) + + _mult_cal_one(data[:, :], ones, idx, cals, mult) + + if len(tal_data) > 1: + tal_data = np.concatenate([tal.ravel() for tal in tal_data]) + tal_data = tal_data[np.newaxis, :] + return tal_data + + +@fill_doc +def _read_header( + fname, + exclude, + infer_types, + file_type, + include=None, + exclude_after_unique=False, +): + """Unify EDF, BDF and GDF _read_header call. + + Parameters + ---------- + fname : str + Path to the EDF+, BDF, or GDF file or file-like object. + exclude : list of str | str + Channel names to exclude. This can help when reading data with + different sampling rates to avoid unnecessary resampling. A str is + interpreted as a regular expression. + infer_types : bool + If True, try to infer channel types from channel labels. If a channel + label starts with a known type (such as 'EEG') followed by a space and + a name (such as 'Fp1'), the channel type will be set accordingly, and + the channel will be renamed to the original label without the prefix. + For unknown prefixes, the type will be 'EEG' and the name will not be + modified. If False, do not infer types and assume all channels are of + type 'EEG'. + include : list of str | str + Channel names to be included. A str is interpreted as a regular + expression. 'exclude' must be empty if include is assigned. + %(exclude_after_unique)s + + Returns + ------- + (edf_info, orig_units) : tuple + """ + if file_type in (FileType.BDF, FileType.EDF): + return _read_edf_header( + fname, + exclude, + infer_types, + file_type, + include, + exclude_after_unique, + ) + elif file_type == FileType.GDF: + return _read_gdf_header(fname, exclude, include), None + else: + raise NotImplementedError("Only GDF, EDF, and BDF files are supported.") + + +def _get_info( + fname, + stim_channel, + eog, + misc, + exclude, + infer_types, + file_type, + include=None, + exclude_after_unique=False, +): + """Extract information from EDF+, BDF or GDF file.""" + eog = eog if eog is not None else [] + misc = misc if misc is not None else [] + + edf_info, orig_units = _read_header( + fname, exclude, infer_types, file_type, include, exclude_after_unique + ) + + # XXX: `tal_ch_names` to pass to `_check_stim_channel` should be computed + # from `edf_info['ch_names']` and `edf_info['tal_idx']` but 'tal_idx' + # contains stim channels that are not TAL. + stim_channel_idxs, _ = _check_stim_channel(stim_channel, edf_info["ch_names"]) + + sel = edf_info["sel"] # selection of channels not excluded + ch_names = edf_info["ch_names"] # of length len(sel) + if "ch_types" in edf_info: + ch_types = edf_info["ch_types"] # of length len(sel) + else: + ch_types = [None] * len(sel) + if len(sel) == 0: # only want stim channels + n_samps = edf_info["n_samps"][[0]] + else: + n_samps = edf_info["n_samps"][sel] + nchan = edf_info["nchan"] + physical_ranges = edf_info["physical_max"] - edf_info["physical_min"] + cals = edf_info["digital_max"] - edf_info["digital_min"] + bad_idx = np.where((~np.isfinite(cals)) | (cals == 0))[0] + if len(bad_idx) > 0: + warn( + "Scaling factor is not defined in following channels:\n" + + ", ".join(ch_names[i] for i in bad_idx) + ) + cals[bad_idx] = 1 + bad_idx = np.where(physical_ranges == 0)[0] + if len(bad_idx) > 0: + warn( + "Physical range is not defined in following channels:\n" + + ", ".join(ch_names[i] for i in bad_idx) + ) + physical_ranges[bad_idx] = 1 + + # Creates a list of dicts of eeg channels for raw.info + logger.info("Setting channel info structure...") + chs = list() + pick_mask = np.ones(len(ch_names)) + + chs_without_types = list() + + for idx, ch_name in enumerate(ch_names): + chan_info = {} + chan_info["cal"] = 1.0 + chan_info["logno"] = idx + 1 + chan_info["scanno"] = idx + 1 + chan_info["range"] = 1.0 + chan_info["unit_mul"] = FIFF.FIFF_UNITM_NONE + chan_info["ch_name"] = ch_name + chan_info["unit"] = FIFF.FIFF_UNIT_V + chan_info["coord_frame"] = FIFF.FIFFV_COORD_HEAD + chan_info["coil_type"] = FIFF.FIFFV_COIL_EEG + chan_info["kind"] = FIFF.FIFFV_EEG_CH + # montage can't be stored in EDF so channel locs are unknown: + chan_info["loc"] = np.full(12, np.nan) + + # if the edf info contained channel type information + # set it now + ch_type = ch_types[idx] + if ch_type is not None and ch_type in CH_TYPE_MAPPING: + chan_info["kind"] = CH_TYPE_MAPPING.get(ch_type) + if ch_type not in ["EEG", "ECOG", "SEEG", "DBS"]: + chan_info["coil_type"] = FIFF.FIFFV_COIL_NONE + pick_mask[idx] = False + # if user passes in explicit mapping for eog, misc and stim + # channels set them here + if ch_name in eog or idx in eog or idx - nchan in eog: + chan_info["coil_type"] = FIFF.FIFFV_COIL_NONE + chan_info["kind"] = FIFF.FIFFV_EOG_CH + pick_mask[idx] = False + elif ch_name in misc or idx in misc or idx - nchan in misc: + chan_info["coil_type"] = FIFF.FIFFV_COIL_NONE + chan_info["kind"] = FIFF.FIFFV_MISC_CH + pick_mask[idx] = False + elif idx in stim_channel_idxs: + chan_info["coil_type"] = FIFF.FIFFV_COIL_NONE + chan_info["unit"] = FIFF.FIFF_UNIT_NONE + chan_info["kind"] = FIFF.FIFFV_STIM_CH + pick_mask[idx] = False + chan_info["ch_name"] = ch_name + ch_names[idx] = chan_info["ch_name"] + edf_info["units"][idx] = 1 + elif ch_type not in CH_TYPE_MAPPING: + chs_without_types.append(ch_name) + chs.append(chan_info) + + # warn if channel type was not inferable + if len(chs_without_types): + msg = ( + "Could not determine channel type of the following channels, " + f"they will be set as EEG:\n{', '.join(chs_without_types)}" + ) + logger.info(msg) + + edf_info["stim_channel_idxs"] = stim_channel_idxs + if any(pick_mask): + picks = [item for item, mask in zip(range(nchan), pick_mask) if mask] + edf_info["max_samp"] = max_samp = n_samps[picks].max() + else: + edf_info["max_samp"] = max_samp = n_samps.max() + + # Info structure + # ------------------------------------------------------------------------- + + not_stim_ch = [x for x in range(n_samps.shape[0]) if x not in stim_channel_idxs] + if len(not_stim_ch) == 0: # only loading stim channels + not_stim_ch = list(range(len(n_samps))) + sfreq = ( + np.take(n_samps, not_stim_ch).max() + * edf_info["record_length"][1] + / edf_info["record_length"][0] + ) + del n_samps + info = _empty_info(sfreq) + info["meas_date"] = edf_info["meas_date"] + info["chs"] = chs + info["ch_names"] = ch_names + + # Subject information + info["subject_info"] = {} + + # String subject identifier + if edf_info["subject_info"].get("id") is not None: + info["subject_info"]["his_id"] = edf_info["subject_info"]["id"] + # Subject sex (0=unknown, 1=male, 2=female) + if edf_info["subject_info"].get("sex") is not None: + if edf_info["subject_info"]["sex"] == "M": + info["subject_info"]["sex"] = 1 + elif edf_info["subject_info"]["sex"] == "F": + info["subject_info"]["sex"] = 2 + else: + info["subject_info"]["sex"] = 0 + # Subject names (first, middle, last). + if edf_info["subject_info"].get("name") is not None: + sub_names = edf_info["subject_info"]["name"].split("_") + if len(sub_names) < 2 or len(sub_names) > 3: + info["subject_info"]["last_name"] = edf_info["subject_info"]["name"] + elif len(sub_names) == 2: + info["subject_info"]["first_name"] = sub_names[0] + info["subject_info"]["last_name"] = sub_names[1] + else: + info["subject_info"]["first_name"] = sub_names[0] + info["subject_info"]["middle_name"] = sub_names[1] + info["subject_info"]["last_name"] = sub_names[2] + # Birthday in (year, month, day) format. + if isinstance(edf_info["subject_info"].get("birthday"), datetime): + info["subject_info"]["birthday"] = date( + edf_info["subject_info"]["birthday"].year, + edf_info["subject_info"]["birthday"].month, + edf_info["subject_info"]["birthday"].day, + ) + # Handedness (1=right, 2=left, 3=ambidextrous). + if edf_info["subject_info"].get("hand") is not None: + info["subject_info"]["hand"] = int(edf_info["subject_info"]["hand"]) + # Height in meters. + if edf_info["subject_info"].get("height") is not None: + info["subject_info"]["height"] = float(edf_info["subject_info"]["height"]) + # Weight in kilograms. + if edf_info["subject_info"].get("weight") is not None: + info["subject_info"]["weight"] = float(edf_info["subject_info"]["weight"]) + # Remove values after conversion to help with in-memory anonymization + for key in ("subject_info", "meas_date"): + del edf_info[key] + + # Filter settings + if filt_ch_idxs := [x for x in range(len(sel)) if x not in stim_channel_idxs]: + _set_prefilter(info, edf_info, filt_ch_idxs, "highpass") + _set_prefilter(info, edf_info, filt_ch_idxs, "lowpass") + + if np.isnan(info["lowpass"]): + info["lowpass"] = info["sfreq"] / 2.0 + + if info["highpass"] > info["lowpass"]: + warn( + f"Highpass cutoff frequency {info['highpass']} is greater " + f"than lowpass cutoff frequency {info['lowpass']}, " + "setting values to 0 and Nyquist." + ) + info["highpass"] = 0.0 + info["lowpass"] = info["sfreq"] / 2.0 + + # Some keys to be consistent with FIF measurement info + info["description"] = None + edf_info["nsamples"] = int(edf_info["n_records"] * max_samp) + + info._unlocked = False + info._update_redundant() + + # Later used for reading + edf_info["cal"] = physical_ranges / cals + + # physical dimension in µV + edf_info["offsets"] = ( + edf_info["physical_min"] - edf_info["digital_min"] * edf_info["cal"] + ) + del edf_info["physical_min"] + del edf_info["digital_min"] + + if edf_info["subtype"] == "bdf": + edf_info["cal"][stim_channel_idxs] = 1 + edf_info["offsets"][stim_channel_idxs] = 0 + edf_info["units"][stim_channel_idxs] = 1 + + return info, edf_info, orig_units + + +def _parse_prefilter_string(prefiltering): + """Parse prefilter string from EDF+ and BDF headers.""" + filter_types = ["HP", "LP"] + filter_strings = {t: [] for t in filter_types} + for filt in prefiltering: + for t in filter_types: + matches = re.findall(rf"{t}:\s*([a-zA-Z0-9,.]+)(Hz)?", filt) + value = "" + for match in matches: + if match[0]: + value = match[0].replace("Hz", "").replace(",", ".") + filter_strings[t].append(value) + return np.array(filter_strings["HP"]), np.array(filter_strings["LP"]) + + +def _prefilter_float(filt): + if isinstance(filt, int | float | np.number): + return filt + if filt == "DC": + return 0.0 + if filt.replace(".", "", 1).isdigit(): + return float(filt) + return np.nan + + +def _set_prefilter(info, edf_info, ch_idxs, key): + value = 0 + if len(values := edf_info.get(key, [])): + values = [x for i, x in enumerate(values) if i in ch_idxs] + if len(np.unique(values)) > 1: + warn( + f"Channels contain different {key} filters. " + f"{'Highest' if key == 'highpass' else 'Lowest'} filter " + "setting will be stored." + ) + if key == "highpass": + value = np.nanmax([_prefilter_float(x) for x in values]) + else: + value = np.nanmin([_prefilter_float(x) for x in values]) + else: + value = _prefilter_float(values[0]) + if not np.isnan(value) and value != 0: + info[key] = value + + +def _edf_str(x): + return x.decode("latin-1").split("\x00")[0] + + +def _edf_str_num(x): + return _edf_str(x).replace(",", ".") + + +def _read_edf_header( + fname, + exclude, + infer_types, + file_type, + include=None, + exclude_after_unique=False, +): + """Read header information from EDF+ or BDF file.""" + edf_info = {"events": []} + + with _gdf_edf_get_fid(fname) as fid: + fid.read(8) # version (unused here) + + # patient ID + patient = {} + id_info = fid.read(80).decode("latin-1").rstrip() + id_info = id_info.split(" ") + if len(id_info): + patient["id"] = id_info[0] + if len(id_info) >= 4: + try: + birthdate = datetime.strptime(id_info[2], "%d-%b-%Y") + except ValueError: + birthdate = "X" + patient["sex"] = id_info[1] + patient["birthday"] = birthdate + patient["name"] = id_info[3] + if len(id_info) > 4: + for info in id_info[4:]: + if "=" in info: + key, value = info.split("=") + err = f"patient {key} info cannot be {value}, skipping." + if key in ["weight", "height"]: + try: + patient[key] = float(value) + except ValueError: + logger.debug(err) + continue + elif key in ["hand"]: + try: + patient[key] = int(value) + except ValueError: + logger.debug(err) + continue + else: + warn(f"Invalid patient information {key}") + + # Recording ID + rec_info = fid.read(80).decode("latin-1").rstrip().split(" ") + # if the measurement date is available in the recording info, it's used instead + # of the file's meas_date since it contains all 4 digits of the year. + meas_date = None + if len(rec_info) == 5: + try: + meas_date = datetime.strptime(rec_info[1], "%d-%b-%Y") + except Exception: + meas_date = None + else: + fid.read(8) # skip the file's meas_date + if meas_date is None: + try: + meas_date = fid.read(8).decode("latin-1") + day, month, year = (int(x) for x in meas_date.split(".")) + year = year + 2000 if year < 85 else year + 1900 + meas_date = datetime(year, month, day) + except Exception: + meas_date = None + if meas_date is not None: + # try to get the hour/minute/sec from the recording info + try: + meas_time = fid.read(8).decode("latin-1") + hour, minute, second = (int(x) for x in meas_time.split(".")) + except Exception: + hour, minute, second = 0, 0, 0 + meas_date = meas_date.replace( + hour=hour, minute=minute, second=second, tzinfo=timezone.utc + ) + else: + fid.read(8) # skip the file's measurement time + warn("Invalid measurement date encountered in the header.") + + try: + header_nbytes = int(_edf_str(fid.read(8))) + except ValueError: + raise ValueError( + f"Bad {'EDF' if file_type == FileType.EDF else 'BDF'} file provided." + ) + + # The following 44 bytes sometimes identify the file type, but this is + # not guaranteed. Therefore, we skip this field and use the file_type + # to determine the subtype (EDF or BDF, which differ in the + # number of bytes they use for the data records; EDF uses 2 bytes + # whereas BDF uses 3 bytes). + fid.read(44) + subtype = file_type + + n_records = int(_edf_str(fid.read(8))) + record_length = float(_edf_str(fid.read(8))) + record_length = np.array([record_length, 1.0]) # in seconds + if record_length[0] == 0: + record_length[0] = 1.0 + warn( + "Header information is incorrect for record length. Default " + "record length set to 1.\nIt is possible that this file only" + " contains annotations and no signals. In that case, please " + "use mne.read_annotations() to load these annotations." + ) + + nchan = int(_edf_str(fid.read(4))) + channels = list(range(nchan)) + + # read in 16 byte labels and strip any extra spaces at the end + ch_labels = [fid.read(16).strip().decode("latin-1") for _ in channels] + + # get channel names and optionally channel type + # EDF specification contains 16 bytes that encode channel names, + # optionally prefixed by a string representing channel type separated + # by a space + if infer_types: + ch_types, ch_names = [], [] + for ch_label in ch_labels: + ch_type, ch_name = "EEG", ch_label # default to EEG + parts = ch_label.split(" ") + if len(parts) > 1: + if parts[0].upper() in CH_TYPE_MAPPING: + ch_type = parts[0].upper() + ch_name = " ".join(parts[1:]) + logger.info( + f"Channel '{ch_label}' recognized as type " + f"{ch_type} (renamed to '{ch_name}')." + ) + ch_types.append(ch_type) + ch_names.append(ch_name) + else: + ch_types, ch_names = ["EEG"] * nchan, ch_labels + + tal_idx = _find_tal_idx(ch_names) + if exclude_after_unique: + # make sure channel names are unique + ch_names = _unique_channel_names(ch_names) + + exclude = _find_exclude_idx(ch_names, exclude, include) + exclude = np.concatenate([exclude, tal_idx]) + sel = np.setdiff1d(np.arange(len(ch_names)), exclude) + + for ch in channels: + fid.read(80) # transducer + units = [fid.read(8).strip().decode("latin-1") for ch in channels] + edf_info["units"] = list() + for i, unit in enumerate(units): + if i in exclude: + continue + # allow μ (greek mu), µ (micro symbol) and μ (sjis mu) codepoints + if unit in ("\u03bcV", "\u00b5V", "\x83\xcaV", "uV"): + edf_info["units"].append(1e-6) + elif unit == "mV": + edf_info["units"].append(1e-3) + else: + edf_info["units"].append(1) + edf_info["units"] = np.array(edf_info["units"], float) + + ch_names = [ch_names[idx] for idx in sel] + ch_types = [ch_types[idx] for idx in sel] + units = [units[idx] for idx in sel] + + if not exclude_after_unique: + # make sure channel names are unique + ch_names = _unique_channel_names(ch_names) + orig_units = dict(zip(ch_names, units)) + + physical_min = np.array([float(_edf_str_num(fid.read(8))) for ch in channels])[ + sel + ] + physical_max = np.array([float(_edf_str_num(fid.read(8))) for ch in channels])[ + sel + ] + digital_min = np.array([float(_edf_str_num(fid.read(8))) for ch in channels])[ + sel + ] + digital_max = np.array([float(_edf_str_num(fid.read(8))) for ch in channels])[ + sel + ] + prefiltering = np.array([_edf_str(fid.read(80)).strip() for ch in channels]) + highpass, lowpass = _parse_prefilter_string(prefiltering) + + # number of samples per record + n_samps = np.array([int(_edf_str(fid.read(8))) for ch in channels]) + + # Populate edf_info + edf_info.update( + ch_names=ch_names, + ch_types=ch_types, + data_offset=header_nbytes, + digital_max=digital_max, + digital_min=digital_min, + highpass=highpass, + sel=sel, + lowpass=lowpass, + meas_date=meas_date, + n_records=n_records, + n_samps=n_samps, + nchan=nchan, + subject_info=patient, + physical_max=physical_max, + physical_min=physical_min, + record_length=record_length, + subtype="bdf" if subtype == FileType.BDF else "edf", + tal_idx=tal_idx, + ) + + fid.read(32 * nchan).decode() # reserved + assert fid.tell() == header_nbytes + + fid.seek(0, 2) + n_bytes = fid.tell() + n_data_bytes = n_bytes - header_nbytes + total_samps = ( + n_data_bytes // 3 if subtype == FileType.BDF else n_data_bytes // 2 + ) + read_records = total_samps // np.sum(n_samps) + if n_records != read_records: + warn( + "Number of records from the header does not match the file " + "size (perhaps the recording was not stopped before exiting)." + " Inferring from the file size." + ) + edf_info["n_records"] = read_records + del n_records + + if subtype == FileType.BDF: + edf_info["dtype_byte"] = 3 # 24-bit (3 byte) integers + edf_info["dtype_np"] = UINT8 + else: + edf_info["dtype_byte"] = 2 # 16-bit (2 byte) integers + edf_info["dtype_np"] = INT16 + + return edf_info, orig_units + + +INT8 = " 1: + # We will not read it properly, so this should be an error + raise RuntimeError("Reading multiple data types not supported") + return dtype_np[0], dtype_byte[0] + + +def _read_gdf_header(fname, exclude, include=None): + """Read GDF 1.x and GDF 2.x header info.""" + edf_info = dict() + events = None + + with _gdf_edf_get_fid(fname) as fid: + try: + version = fid.read(8).decode() + edf_info["type"] = edf_info["subtype"] = version[:3] + edf_info["number"] = float(version[4:]) + except ValueError: + raise ValueError("Bad GDF file provided.") + + meas_date = None + + # GDF 1.x + # --------------------------------------------------------------------- + if edf_info["number"] < 1.9: + # patient ID + pid = fid.read(80).decode("latin-1") + pid = pid.split(" ", 2) + patient = {} + if len(pid) >= 2: + patient["id"] = pid[0] + patient["name"] = pid[1] + + # Recording ID + meas_id = {} + meas_id["recording_id"] = _edf_str(fid.read(80)).strip() + + # date + tm = _edf_str(fid.read(16)).strip() + try: + if tm[14:16] == " ": + tm = tm[:14] + "00" + tm[16:] + meas_date = datetime( + int(tm[0:4]), + int(tm[4:6]), + int(tm[6:8]), + int(tm[8:10]), + int(tm[10:12]), + int(tm[12:14]), + int(tm[14:16]) * pow(10, 4), + tzinfo=timezone.utc, + ) + except Exception: + pass + + header_nbytes = read_from_file_or_buffer(fid, INT64, 1)[0] + meas_id["equipment"] = read_from_file_or_buffer(fid, UINT8, 8)[0] + meas_id["hospital"] = read_from_file_or_buffer(fid, UINT8, 8)[0] + meas_id["technician"] = read_from_file_or_buffer(fid, UINT8, 8)[0] + fid.seek(20, 1) # 20bytes reserved + + n_records = read_from_file_or_buffer(fid, INT64, 1)[0] + # record length in seconds + record_length = read_from_file_or_buffer(fid, UINT32, 2) + if record_length[0] == 0: + record_length[0] = 1.0 + warn( + "Header information is incorrect for record length. " + "Default record length set to 1." + ) + nchan = int(read_from_file_or_buffer(fid, UINT32, 1)[0]) + channels = list(range(nchan)) + ch_names = [_edf_str(fid.read(16)).strip() for ch in channels] + exclude = _find_exclude_idx(ch_names, exclude, include) + sel = np.setdiff1d(np.arange(len(ch_names)), exclude) + fid.seek(80 * len(channels), 1) # transducer + units = [_edf_str(fid.read(8)).strip() for ch in channels] + edf_info["units"] = list() + for i, unit in enumerate(units): + if i in exclude: + continue + if unit[:2] == "uV": + edf_info["units"].append(1e-6) + else: + edf_info["units"].append(1) + edf_info["units"] = np.array(edf_info["units"], float) + + ch_names = [ch_names[idx] for idx in sel] + physical_min = read_from_file_or_buffer(fid, FLOAT64, len(channels)) + physical_max = read_from_file_or_buffer(fid, FLOAT64, len(channels)) + digital_min = read_from_file_or_buffer(fid, INT64, len(channels)) + digital_max = read_from_file_or_buffer(fid, INT64, len(channels)) + prefiltering = [_edf_str(fid.read(80)) for ch in channels] + highpass, lowpass = _parse_prefilter_string(prefiltering) + + # n samples per record + n_samps = read_from_file_or_buffer(fid, INT32, len(channels)) + + # channel data type + dtype = read_from_file_or_buffer(fid, INT32, len(channels)) + + # total number of bytes for data + bytes_tot = np.sum( + [GDFTYPE_BYTE[t] * n_samps[i] for i, t in enumerate(dtype)] + ) + + # Populate edf_info + dtype_np, dtype_byte = _check_dtype_byte(dtype) + edf_info.update( + bytes_tot=bytes_tot, + ch_names=ch_names, + data_offset=header_nbytes, + digital_min=digital_min, + digital_max=digital_max, + dtype_byte=dtype_byte, + dtype_np=dtype_np, + exclude=exclude, + highpass=highpass, + sel=sel, + lowpass=lowpass, + meas_date=meas_date, + meas_id=meas_id, + n_records=n_records, + n_samps=n_samps, + nchan=nchan, + subject_info=patient, + physical_max=physical_max, + physical_min=physical_min, + record_length=record_length, + ) + + fid.seek(32 * edf_info["nchan"], 1) # reserved + assert fid.tell() == header_nbytes + + # Event table + # ----------------------------------------------------------------- + etp = header_nbytes + n_records * edf_info["bytes_tot"] + # skip data to go to event table + fid.seek(etp) + etmode = read_from_file_or_buffer(fid, UINT8, 1)[0] + if etmode in (1, 3): + sr = read_from_file_or_buffer(fid, UINT8, 3).astype(np.uint32) + event_sr = sr[0] + for i in range(1, len(sr)): + event_sr = event_sr + sr[i] * 2 ** (i * 8) + n_events = read_from_file_or_buffer(fid, UINT32, 1)[0] + pos = ( + read_from_file_or_buffer(fid, UINT32, n_events) - 1 + ) # 1-based inds + typ = read_from_file_or_buffer(fid, UINT16, n_events) + + if etmode == 3: + chn = read_from_file_or_buffer(fid, UINT16, n_events) + dur = read_from_file_or_buffer(fid, UINT32, n_events) + else: + chn = np.zeros(n_events, dtype=np.int32) + dur = np.ones(n_events, dtype=UINT32) + np.maximum(dur, 1, out=dur) + events = [n_events, pos, typ, chn, dur] + + # GDF 2.x + # --------------------------------------------------------------------- + else: + # FIXED HEADER + handedness = ("Unknown", "Right", "Left", "Equal") + gender = ("Unknown", "Male", "Female") + scale = ("Unknown", "No", "Yes", "Corrected") + + # date + pid = fid.read(66).decode() + pid = pid.split(" ", 2) + patient = {} + if len(pid) >= 2: + patient["id"] = pid[0] + patient["name"] = pid[1] + fid.seek(10, 1) # 10bytes reserved + + # Smoking / Alcohol abuse / drug abuse / medication + sadm = read_from_file_or_buffer(fid, UINT8, 1)[0] + patient["smoking"] = scale[sadm % 4] + patient["alcohol_abuse"] = scale[(sadm >> 2) % 4] + patient["drug_abuse"] = scale[(sadm >> 4) % 4] + patient["medication"] = scale[(sadm >> 6) % 4] + patient["weight"] = read_from_file_or_buffer(fid, UINT8, 1)[0] + if patient["weight"] == 0 or patient["weight"] == 255: + patient["weight"] = None + patient["height"] = read_from_file_or_buffer(fid, UINT8, 1)[0] + if patient["height"] == 0 or patient["height"] == 255: + patient["height"] = None + + # Gender / Handedness / Visual Impairment + ghi = read_from_file_or_buffer(fid, UINT8, 1)[0] + patient["sex"] = gender[ghi % 4] + patient["handedness"] = handedness[(ghi >> 2) % 4] + patient["visual"] = scale[(ghi >> 4) % 4] + + # Recording identification + meas_id = {} + meas_id["recording_id"] = _edf_str(fid.read(64)).strip() + vhsv = read_from_file_or_buffer(fid, UINT8, 4) + loc = {} + if vhsv[3] == 0: + loc["vertpre"] = 10 * int(vhsv[0] >> 4) + int(vhsv[0] % 16) + loc["horzpre"] = 10 * int(vhsv[1] >> 4) + int(vhsv[1] % 16) + loc["size"] = 10 * int(vhsv[2] >> 4) + int(vhsv[2] % 16) + else: + loc["vertpre"] = 29 + loc["horzpre"] = 29 + loc["size"] = 29 + loc["version"] = 0 + loc["latitude"] = ( + float(read_from_file_or_buffer(fid, UINT32, 1)[0]) / 3600000 + ) + loc["longitude"] = ( + float(read_from_file_or_buffer(fid, UINT32, 1)[0]) / 3600000 + ) + loc["altitude"] = float(read_from_file_or_buffer(fid, INT32, 1)[0]) / 100 + meas_id["loc"] = loc + + meas_date = read_from_file_or_buffer(fid, UINT64, 1)[0] + if meas_date != 0: + meas_date = datetime(1, 1, 1, tzinfo=timezone.utc) + timedelta( + meas_date * pow(2, -32) - 367 + ) + else: + meas_date = None + + birthday = read_from_file_or_buffer(fid, UINT64, 1).tolist()[0] + if birthday == 0: + birthday = datetime(1, 1, 1, tzinfo=timezone.utc) + else: + birthday = datetime(1, 1, 1, tzinfo=timezone.utc) + timedelta( + birthday * pow(2, -32) - 367 + ) + patient["birthday"] = birthday + if patient["birthday"] != datetime(1, 1, 1, 0, 0, tzinfo=timezone.utc): + today = datetime.now(tz=timezone.utc) + patient["age"] = today.year - patient["birthday"].year + # fudge the day by -1 if today happens to be a leap day + day = 28 if today.month == 2 and today.day == 29 else today.day + today = today.replace(year=patient["birthday"].year, day=day) + if today < patient["birthday"]: + patient["age"] -= 1 + else: + patient["age"] = None + + header_nbytes = read_from_file_or_buffer(fid, UINT16, 1)[0] * 256 + + fid.seek(6, 1) # 6 bytes reserved + meas_id["equipment"] = read_from_file_or_buffer(fid, UINT8, 8) + meas_id["ip"] = read_from_file_or_buffer(fid, UINT8, 6) + patient["headsize"] = read_from_file_or_buffer(fid, UINT16, 3) + patient["headsize"] = np.asarray(patient["headsize"], np.float32) + patient["headsize"] = np.ma.masked_array( + patient["headsize"], np.equal(patient["headsize"], 0), None + ).filled() + ref = read_from_file_or_buffer(fid, FLOAT32, 3) + gnd = read_from_file_or_buffer(fid, FLOAT32, 3) + n_records = read_from_file_or_buffer(fid, INT64, 1)[0] + + # record length in seconds + record_length = read_from_file_or_buffer(fid, UINT32, 2) + if record_length[0] == 0: + record_length[0] = 1.0 + warn( + "Header information is incorrect for record length. " + "Default record length set to 1." + ) + + nchan = int(read_from_file_or_buffer(fid, UINT16, 1)[0]) + fid.seek(2, 1) # 2bytes reserved + + # Channels (variable header) + channels = list(range(nchan)) + ch_names = [_edf_str(fid.read(16)).strip() for ch in channels] + exclude = _find_exclude_idx(ch_names, exclude, include) + sel = np.setdiff1d(np.arange(len(ch_names)), exclude) + + fid.seek(80 * len(channels), 1) # reserved space + fid.seek(6 * len(channels), 1) # phys_dim, obsolete + + """The Physical Dimensions are encoded as int16, according to: + - Units codes : + https://sourceforge.net/p/biosig/svn/HEAD/tree/trunk/biosig/doc/units.csv + - Decimal factors codes: + https://sourceforge.net/p/biosig/svn/HEAD/tree/trunk/biosig/doc/DecimalFactors.txt + """ # noqa + units = read_from_file_or_buffer(fid, UINT16, len(channels)).tolist() + unitcodes = np.array(units[:]) + edf_info["units"] = list() + for i, unit in enumerate(units): + if i in exclude: + continue + if unit == 4275: # microvolts + edf_info["units"].append(1e-6) + elif unit == 4274: # millivolts + edf_info["units"].append(1e-3) + elif unit == 512: # dimensionless + edf_info["units"].append(1) + elif unit == 0: + edf_info["units"].append(1) # unrecognized + else: + warn( + f"Unsupported physical dimension for channel {i} " + "(assuming dimensionless). Please contact the " + "MNE-Python developers for support." + ) + edf_info["units"].append(1) + edf_info["units"] = np.array(edf_info["units"], float) + + ch_names = [ch_names[idx] for idx in sel] + physical_min = read_from_file_or_buffer(fid, FLOAT64, len(channels)) + physical_max = read_from_file_or_buffer(fid, FLOAT64, len(channels)) + digital_min = read_from_file_or_buffer(fid, FLOAT64, len(channels)) + digital_max = read_from_file_or_buffer(fid, FLOAT64, len(channels)) + + fid.seek(68 * len(channels), 1) # obsolete + lowpass = read_from_file_or_buffer(fid, FLOAT32, len(channels)) + highpass = read_from_file_or_buffer(fid, FLOAT32, len(channels)) + notch = read_from_file_or_buffer(fid, FLOAT32, len(channels)) + + # number of samples per record + n_samps = read_from_file_or_buffer(fid, INT32, len(channels)) + + # data type + dtype = read_from_file_or_buffer(fid, INT32, len(channels)) + + channel = {} + channel["xyz"] = [ + read_from_file_or_buffer(fid, FLOAT32, 3)[0] for ch in channels + ] + + if edf_info["number"] < 2.19: + impedance = read_from_file_or_buffer(fid, UINT8, len(channels)).astype( + float + ) + impedance[impedance == 255] = np.nan + channel["impedance"] = pow(2, impedance / 8) + fid.seek(19 * len(channels), 1) # reserved + else: + tmp = read_from_file_or_buffer(fid, FLOAT32, 5 * len(channels)) + tmp = tmp[::5] + fZ = tmp[:] + impedance = tmp[:] + # channels with no voltage (code 4256) data + ch = [unitcodes & 65504 != 4256][0] + impedance[np.where(ch)] = None + # channel with no impedance (code 4288) data + ch = [unitcodes & 65504 != 4288][0] + fZ[np.where(ch)[0]] = None + + assert fid.tell() == header_nbytes + + # total number of bytes for data + bytes_tot = np.sum( + [GDFTYPE_BYTE[t] * n_samps[i] for i, t in enumerate(dtype)] + ) + + # Populate edf_info + dtype_np, dtype_byte = _check_dtype_byte(dtype) + edf_info.update( + bytes_tot=bytes_tot, + ch_names=ch_names, + data_offset=header_nbytes, + dtype_byte=dtype_byte, + dtype_np=dtype_np, + digital_min=digital_min, + digital_max=digital_max, + exclude=exclude, + gnd=gnd, + highpass=highpass, + sel=sel, + impedance=impedance, + lowpass=lowpass, + meas_date=meas_date, + meas_id=meas_id, + n_records=n_records, + n_samps=n_samps, + nchan=nchan, + notch=notch, + subject_info=patient, + physical_max=physical_max, + physical_min=physical_min, + record_length=record_length, + ref=ref, + ) + + # EVENT TABLE + # ----------------------------------------------------------------- + etp = ( + edf_info["data_offset"] + edf_info["n_records"] * edf_info["bytes_tot"] + ) + fid.seek(etp) # skip data to go to event table + etmode = fid.read(1) + if isinstance(etmode, (bytes, bytearray)) and len(etmode) == 1: + etmode = np.frombuffer(etmode, dtype=UINT8).tolist()[0] + + if edf_info["number"] < 1.94: + sr = read_from_file_or_buffer(fid, UINT8, 3) + event_sr = sr[0] + for i in range(1, len(sr)): + event_sr = event_sr + sr[i] * 2 ** (i * 8) + n_events = read_from_file_or_buffer(fid, UINT32, 1)[0] + else: + ne = read_from_file_or_buffer(fid, UINT8, 3) + n_events = sum(int(ne[i]) << (i * 8) for i in range(len(ne))) + event_sr = read_from_file_or_buffer(fid, FLOAT32, 1)[0] + + pos = ( + read_from_file_or_buffer(fid, UINT32, n_events) - 1 + ) # 1-based inds + typ = read_from_file_or_buffer(fid, UINT16, n_events) + + if etmode == 3: + chn = read_from_file_or_buffer(fid, UINT16, n_events) + dur = read_from_file_or_buffer(fid, UINT32, n_events) + else: + chn = np.zeros(n_events, dtype=np.uint32) + dur = np.ones(n_events, dtype=np.uint32) + np.maximum(dur, 1, out=dur) + events = [n_events, pos, typ, chn, dur] + edf_info["event_sfreq"] = event_sr + + edf_info.update(events=events, sel=np.arange(len(edf_info["ch_names"]))) + + return edf_info + + +def _check_stim_channel( + stim_channel, + ch_names, + tal_ch_names=("EDF Annotations", "BDF Annotations"), +): + """Check that the stimulus channel exists in the current datafile.""" + DEFAULT_STIM_CH_NAMES = ["status", "trigger"] + + if stim_channel is None or stim_channel is False: + return [], [] + + if stim_channel is True: # convenient aliases + stim_channel = "auto" + + elif isinstance(stim_channel, str): + if stim_channel == "auto": + if "auto" in ch_names: + warn( + RuntimeWarning, + "Using `stim_channel='auto'` when auto" + " also corresponds to a channel name is ambiguous." + " Please use `stim_channel=['auto']`.", + ) + else: + valid_stim_ch_names = DEFAULT_STIM_CH_NAMES + else: + valid_stim_ch_names = [stim_channel.lower()] + + elif isinstance(stim_channel, int): + valid_stim_ch_names = [ch_names[stim_channel].lower()] + + elif isinstance(stim_channel, list): + if all([isinstance(s, str) for s in stim_channel]): + valid_stim_ch_names = [s.lower() for s in stim_channel] + elif all([isinstance(s, int) for s in stim_channel]): + valid_stim_ch_names = [ch_names[s].lower() for s in stim_channel] + else: + raise ValueError("Invalid stim_channel") + else: + raise ValueError("Invalid stim_channel") + + # Forbid the synthesis of stim channels from TAL Annotations + tal_ch_names_found = [ + ch for ch in valid_stim_ch_names if ch in [t.lower() for t in tal_ch_names] + ] + if len(tal_ch_names_found): + _msg = ( + "The synthesis of the stim channel is not supported since 0.18. Please " + f"remove {tal_ch_names_found} from `stim_channel` and use " + "`mne.events_from_annotations` instead." + ) + raise ValueError(_msg) + + ch_names_low = [ch.lower() for ch in ch_names] + found = list(set(valid_stim_ch_names) & set(ch_names_low)) + + if not found: + return [], [] + else: + stim_channel_idxs = [ch_names_low.index(f) for f in found] + names = [ch_names[idx] for idx in stim_channel_idxs] + return stim_channel_idxs, names + + +def _find_exclude_idx(ch_names, exclude, include=None): + """Find indices of all channels to exclude. + + If there are several channels called "A" and we want to exclude "A", then + add (the index of) all "A" channels to the exclusion list. + """ + if include: # find other than include channels + if exclude: + raise ValueError( + f"'exclude' must be empty if 'include' is assigned. Got {exclude}." + ) + if isinstance(include, str): # regex for channel names + indices_include = [] + for idx, ch in enumerate(ch_names): + if re.match(include, ch): + indices_include.append(idx) + indices = np.setdiff1d(np.arange(len(ch_names)), indices_include) + return indices + # list of channel names + return [idx for idx, ch in enumerate(ch_names) if ch not in include] + + if isinstance(exclude, str): # regex for channel names + indices = [] + for idx, ch in enumerate(ch_names): + if re.match(exclude, ch): + indices.append(idx) + return indices + # list of channel names + return [idx for idx, ch in enumerate(ch_names) if ch in exclude] + + +def _find_tal_idx(ch_names): + # Annotations / TAL Channels + accepted_tal_ch_names = ["EDF Annotations", "BDF Annotations"] + tal_channel_idx = np.where(np.isin(ch_names, accepted_tal_ch_names))[0] + return tal_channel_idx + + +def _check_args(input_fname, preload, target_ext): + if not _file_like(input_fname): + input_fname = _check_fname(fname=input_fname, overwrite="read", must_exist=True) + ext = input_fname.suffix[1:].lower() + + if ext != target_ext: + raise NotImplementedError( + f"Only {target_ext.upper()} files are supported, got {ext}." + ) + else: + if not preload: + raise ValueError("preload must be used with file-like objects") + + +@fill_doc +def read_raw_edf( + input_fname, + eog=None, + misc=None, + stim_channel="auto", + exclude=(), + infer_types=False, + include=None, + preload=False, + units=None, + encoding="utf8", + exclude_after_unique=False, + *, + verbose=None, +) -> RawEDF: + """Reader function for EDF and EDF+ files. + + Parameters + ---------- + input_fname : path-like + Path to the EDF or EDF+ file or EDF/EDF+ file itself. If a file-like + object is provided, preload must be used. + + .. versionchanged:: 1.10 + Added support for file-like objects + eog : list or tuple + Names of channels or list of indices that should be designated EOG + channels. Values should correspond to the electrodes in the file. + Default is None. + misc : list or tuple + Names of channels or list of indices that should be designated MISC + channels. Values should correspond to the electrodes in the file. + Default is None. + stim_channel : ``'auto'`` | str | list of str | int | list of int + Defaults to ``'auto'``, which means that channels named ``'status'`` or + ``'trigger'`` (case insensitive) are set to STIM. If str (or list of + str), all channels matching the name(s) are set to STIM. If int (or + list of ints), channels corresponding to the indices are set to STIM. + exclude : list of str | str + Channel names to exclude. This can help when reading data with + different sampling rates to avoid unnecessary resampling. A str is + interpreted as a regular expression. + infer_types : bool + If True, try to infer channel types from channel labels. If a channel + label starts with a known type (such as 'EEG') followed by a space and + a name (such as 'Fp1'), the channel type will be set accordingly, and + the channel will be renamed to the original label without the prefix. + For unknown prefixes, the type will be 'EEG' and the name will not be + modified. If False, do not infer types and assume all channels are of + type 'EEG'. + + .. versionadded:: 0.24.1 + include : list of str | str + Channel names to be included. A str is interpreted as a regular + expression. 'exclude' must be empty if include is assigned. + + .. versionadded:: 1.1 + %(preload)s + %(units_edf_bdf_io)s + %(encoding_edf)s + %(exclude_after_unique)s + %(verbose)s + + Returns + ------- + raw : instance of RawEDF + The raw instance. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.read_raw_bdf : Reader function for BDF files. + mne.io.read_raw_gdf : Reader function for GDF files. + mne.export.export_raw : Export function for EDF files. + mne.io.Raw : Documentation of attributes and methods of RawEDF. + + Notes + ----- + %(edf_resamp_note)s + + It is worth noting that in some special cases, it may be necessary to shift + event values in order to retrieve correct event triggers. This depends on + the triggering device used to perform the synchronization. For instance, in + some files events need to be shifted by 8 bits: + + >>> events[:, 2] >>= 8 # doctest:+SKIP + + TAL channels called 'EDF Annotations' are parsed and extracted annotations + are stored in raw.annotations. Use :func:`mne.events_from_annotations` to + obtain events from these annotations. + + If channels named 'status' or 'trigger' are present, they are considered as + STIM channels by default. Use :func:`mne.find_events` to parse events + encoded in such analog stim channels. + + The EDF specification allows optional storage of channel types in the + prefix of the signal label for each channel. For example, ``EEG Fz`` + implies that ``Fz`` is an EEG channel and ``MISC E`` would imply ``E`` is + a MISC channel. However, there is no standard way of specifying all + channel types. MNE-Python will try to infer the channel type, when such a + string exists, defaulting to EEG, when there is no prefix or the prefix is + not recognized. + + The following prefix strings are mapped to MNE internal types: + + - 'EEG': 'eeg' + - 'SEEG': 'seeg' + - 'ECOG': 'ecog' + - 'DBS': 'dbs' + - 'EOG': 'eog' + - 'ECG': 'ecg' + - 'EMG': 'emg' + - 'BIO': 'bio' + - 'RESP': 'resp' + - 'MISC': 'misc' + - 'SAO2': 'bio' + + The EDF specification allows storage of subseconds in measurement date. + However, this reader currently sets subseconds to 0 by default. + """ + _check_args(input_fname, preload, "edf") + + return RawEDF( + input_fname=input_fname, + eog=eog, + misc=misc, + stim_channel=stim_channel, + exclude=exclude, + infer_types=infer_types, + preload=preload, + include=include, + units=units, + encoding=encoding, + exclude_after_unique=exclude_after_unique, + verbose=verbose, + ) + + +@fill_doc +def read_raw_bdf( + input_fname, + eog=None, + misc=None, + stim_channel="auto", + exclude=(), + infer_types=False, + include=None, + preload=False, + units=None, + encoding="utf8", + exclude_after_unique=False, + *, + verbose=None, +) -> RawBDF: + """Reader function for BDF files. + + Parameters + ---------- + input_fname : path-like | file-like + Path to the BDF file of BDF file itself. If a file-like object is + provided, preload must be used. + + .. versionchanged:: 1.10 + Added support for file-like objects + eog : list or tuple + Names of channels or list of indices that should be designated EOG + channels. Values should correspond to the electrodes in the file. + Default is None. + misc : list or tuple + Names of channels or list of indices that should be designated MISC + channels. Values should correspond to the electrodes in the file. + Default is None. + stim_channel : ``'auto'`` | str | list of str | int | list of int + Defaults to ``'auto'``, which means that channels named ``'status'`` or + ``'trigger'`` (case insensitive) are set to STIM. If str (or list of + str), all channels matching the name(s) are set to STIM. If int (or + list of ints), channels corresponding to the indices are set to STIM. + exclude : list of str | str + Channel names to exclude. This can help when reading data with + different sampling rates to avoid unnecessary resampling. A str is + interpreted as a regular expression. + infer_types : bool + If True, try to infer channel types from channel labels. If a channel + label starts with a known type (such as 'EEG') followed by a space and + a name (such as 'Fp1'), the channel type will be set accordingly, and + the channel will be renamed to the original label without the prefix. + For unknown prefixes, the type will be 'EEG' and the name will not be + modified. If False, do not infer types and assume all channels are of + type 'EEG'. + + .. versionadded:: 0.24.1 + include : list of str | str + Channel names to be included. A str is interpreted as a regular + expression. 'exclude' must be empty if include is assigned. + + .. versionadded:: 1.1 + %(preload)s + %(units_edf_bdf_io)s + %(encoding_edf)s + %(exclude_after_unique)s + %(verbose)s + + Returns + ------- + raw : instance of RawEDF + The raw instance. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.read_raw_edf : Reader function for EDF and EDF+ files. + mne.io.read_raw_gdf : Reader function for GDF files. + mne.io.Raw : Documentation of attributes and methods of RawEDF. + + Notes + ----- + :class:`mne.io.Raw` only stores signals with matching sampling frequencies. + Therefore, if mixed sampling frequency signals are requested, all signals + are upsampled to the highest loaded sampling frequency. In this case, using + preload=True is recommended, as otherwise, edge artifacts appear when + slices of the signal are requested. + + Biosemi devices trigger codes are encoded in 16-bit format, whereas system + codes (CMS in/out-of range, battery low, etc.) are coded in bits 16-23 of + the status channel (see http://www.biosemi.com/faq/trigger_signals.htm). + To retrieve correct event values (bits 1-16), one could do: + + >>> events = mne.find_events(...) # doctest:+SKIP + >>> events[:, 2] &= (2**16 - 1) # doctest:+SKIP + + The above operation can be carried out directly in :func:`mne.find_events` + using the ``mask`` parameter as follows: + + >>> events = mne.find_events(..., mask=2**16 - 1) # doctest:+SKIP + + See :func:`mne.find_events` for more details. + + It is also possible to retrieve system codes, but no particular effort has + been made to decode these in MNE. In case it is necessary, for instance to + check the CMS bit, the following operation can be carried out: + + >>> cms_bit = 20 # doctest:+SKIP + >>> cms_high = (events[:, 2] & (1 << cms_bit)) != 0 # doctest:+SKIP + + It is worth noting that in some special cases, it may be necessary to shift + event values in order to retrieve correct event triggers. This depends on + the triggering device used to perform the synchronization. For instance, in + some files events need to be shifted by 8 bits: + + >>> events[:, 2] >>= 8 # doctest:+SKIP + + TAL channels called 'BDF Annotations' are parsed and extracted annotations + are stored in raw.annotations. Use :func:`mne.events_from_annotations` to + obtain events from these annotations. + + If channels named 'status' or 'trigger' are present, they are considered as + STIM channels by default. Use :func:`mne.find_events` to parse events + encoded in such analog stim channels. + """ + _check_args(input_fname, preload, "bdf") + + return RawBDF( + input_fname=input_fname, + eog=eog, + misc=misc, + stim_channel=stim_channel, + exclude=exclude, + infer_types=infer_types, + preload=preload, + include=include, + units=units, + encoding=encoding, + exclude_after_unique=exclude_after_unique, + verbose=verbose, + ) + + +@fill_doc +def read_raw_gdf( + input_fname, + eog=None, + misc=None, + stim_channel="auto", + exclude=(), + include=None, + preload=False, + verbose=None, +) -> RawGDF: + """Reader function for GDF files. + + Parameters + ---------- + input_fname : path-like | file-like + Path to the GDF file or GDF file itself. If a file-like object is + provided, preload must be used. + + .. versionchanged:: 1.10 + Added support for file-like objects + eog : list or tuple + Names of channels or list of indices that should be designated EOG + channels. Values should correspond to the electrodes in the file. + Default is None. + misc : list or tuple + Names of channels or list of indices that should be designated MISC + channels. Values should correspond to the electrodes in the file. + Default is None. + stim_channel : ``'auto'`` | str | list of str | int | list of int + Defaults to ``'auto'``, which means that channels named ``'status'`` or + ``'trigger'`` (case insensitive) are set to STIM. If str (or list of + str), all channels matching the name(s) are set to STIM. If int (or + list of ints), channels corresponding to the indices are set to STIM. + exclude : list of str | str + Channel names to exclude. This can help when reading data with + different sampling rates to avoid unnecessary resampling. A str is + interpreted as a regular expression. + include : list of str | str + Channel names to be included. A str is interpreted as a regular + expression. 'exclude' must be empty if include is assigned. + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawGDF + The raw instance. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.read_raw_edf : Reader function for EDF and EDF+ files. + mne.io.read_raw_bdf : Reader function for BDF files. + mne.io.Raw : Documentation of attributes and methods of RawGDF. + + Notes + ----- + If channels named 'status' or 'trigger' are present, they are considered as + STIM channels by default. Use :func:`mne.find_events` to parse events + encoded in such analog stim channels. + """ + _check_args(input_fname, preload, "gdf") + + return RawGDF( + input_fname=input_fname, + eog=eog, + misc=misc, + stim_channel=stim_channel, + exclude=exclude, + preload=preload, + include=include, + verbose=verbose, + ) + + +@fill_doc +def _read_annotations_edf(annotations, ch_names=None, encoding="utf8"): + """Annotation File Reader. + + Parameters + ---------- + annotations : ndarray (n_chans, n_samples) | str + Channel data in EDF+ TAL format or path to annotation file. + ch_names : list of string + List of channels' names. + %(encoding_edf)s + + Returns + ------- + annot : instance of Annotations + The annotations. + """ + pat = "([+-]\\d+\\.?\\d*)(\x15(\\d+\\.?\\d*))?(\x14.*?)\x14\x00" + if isinstance(annotations, str | Path): + with open(annotations, "rb") as annot_file: + triggers = re.findall(pat.encode(), annot_file.read()) + triggers = [tuple(map(lambda x: x.decode(encoding), t)) for t in triggers] + else: + tals = bytearray() + annotations = np.atleast_2d(annotations) + for chan in annotations: + this_chan = chan.ravel() + if this_chan.dtype == INT32: # BDF + this_chan = this_chan.view(dtype=UINT8) + this_chan = this_chan.reshape(-1, 4) + # Why only keep the first 3 bytes as BDF values + # are stored with 24 bits (not 32) + this_chan = this_chan[:, :3].ravel() + # As ravel() returns a 1D array we can add all values at once + tals.extend(this_chan) + else: + this_chan = chan.astype(np.int64) + # Exploit np vectorized processing + tals.extend(np.uint8([this_chan % 256, this_chan // 256]).flatten("F")) + try: + triggers = re.findall(pat, tals.decode(encoding)) + except UnicodeDecodeError as e: + raise Exception( + "Encountered invalid byte in at least one annotations channel." + " You might want to try setting \"encoding='latin1'\"." + ) from e + + events = {} + offset = 0.0 + for k, ev in enumerate(triggers): + onset = float(ev[0]) + offset + duration = float(ev[2]) if ev[2] else 0 + for description in ev[3].split("\x14")[1:]: + if description: + if ( + "@@" in description + and ch_names is not None + and description.split("@@")[1] in ch_names + ): + description, ch_name = description.split("@@") + key = f"{onset}_{duration}_{description}" + else: + ch_name = None + key = f"{onset}_{duration}_{description}" + if key in events: + key += f"_{k}" # make key unique + if key in events and ch_name: + events[key][3] += (ch_name,) + else: + events[key] = [ + onset, + duration, + description, + (ch_name,) if ch_name else (), + ] + + elif k == 0: + # The startdate/time of a file is specified in the EDF+ header + # fields 'startdate of recording' and 'starttime of recording'. + # These fields must indicate the absolute second in which the + # start of the first data record falls. So, the first TAL in + # the first data record always starts with +0.X, indicating + # that the first data record starts a fraction, X, of a second + # after the startdate/time that is specified in the EDF+ + # header. If X=0, then the .X may be omitted. + offset = -onset + + if events: + onset, duration, description, annot_ch_names = zip(*events.values()) + else: + onset, duration, description, annot_ch_names = list(), list(), list(), list() + + assert len(onset) == len(duration) == len(description) == len(annot_ch_names) + + return Annotations( + onset=onset, + duration=duration, + description=description, + orig_time=None, + ch_names=annot_ch_names, + ) + + +def _get_annotations_gdf(edf_info, sfreq): + onset, duration, desc = list(), list(), list() + events = edf_info.get("events", None) + # Annotations in GDF: events are stored as the following + # list: `events = [n_events, pos, typ, chn, dur]` where pos is the + # latency, dur is the duration in samples. They both are + # numpy.ndarray + if events is not None and events[1].shape[0] > 0: + onset = events[1] / sfreq + duration = events[4] / sfreq + desc = events[2] + + return onset, duration, desc diff --git a/mne-python/source/mne/io/edf/tests/__init__.py b/mne-python/source/mne/io/edf/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/edf/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/edf/tests/data/biosemi.hpts b/mne-python/source/mne/io/edf/tests/data/biosemi.hpts new file mode 100644 index 0000000000000000000000000000000000000000..ad5957beaf70e39136772062256b22baf3493c76 --- /dev/null +++ b/mne-python/source/mne/io/edf/tests/data/biosemi.hpts @@ -0,0 +1,82 @@ +# This file contains the default locations for the 64 +# channel biosemi cap, available on the biosemi website +# http://www.biosemi.com/download/Cap_coords_all.xls +# +# This includes default locations for 3 cardinal landmarks, +# the nasion, and the left and right auriculars +# +# 64 eeg channels +# --------------- +eeg Fp1 -95.0 -31.0 -3.0 +eeg AF7 -81 -59 -3 +eeg AF3 -87 -41 28 +eeg F1 -71 -29 64 +eeg F3 -67 -55 50 +eeg F5 -63 -73 26 +eeg F7 -59 -81 -3 +eeg FT7 -31 -95 -3 +eeg FC5 -34 -89 31 +eeg FC3 -36 -68 64 +eeg FC1 -37 -37 85 +eeg C1 0 -39 92 +eeg C3 0 -72 69 +eeg C5 0 -93 36 +eeg T7 0 -100 -3 +eeg TP7 31 -95 -3 +eeg CP5 34 -89 31 +eeg CP3 36 -68 64 +eeg CP1 37 -37 85 +eeg P1 71 -29 64 +eeg P3 67 -55 50 +eeg P5 63 -73 26 +eeg P7 59 -81 -3 +eeg P9 53 -73 -42 +eeg PO7 81 -59 -3 +eeg PO3 87 -41 28 +eeg O1 95 -31 -3 +eeg Iz 91 0 -42 +eeg Oz 100 0 -3 +eeg POz 93 0 36 +eeg Pz 72 0 69 +eeg CPz 39 0 92 +eeg Fpz -100 0 -3 +eeg Fp2 -95 31 -3 +eeg AF8 -81 59 -3 +eeg AF4 -87 41 28 +eeg AFz -93 0 36 +eeg Fz -72 0 69 +eeg F2 -71 29 64 +eeg F4 -67 55 50 +eeg F6 -63 73 26 +eeg F8 -59 81 -3 +eeg FT8 -31 95 -3 +eeg FC6 -34 89 31 +eeg FC4 -36 68 64 +eeg FC2 -37 37 85 +eeg FCz -39 0 92 +eeg Cz 0 0 100 +eeg C2 0 39 92 +eeg C4 0 72 69 +eeg C6 0 93 36 +eeg T8 0 100 -3 +eeg TP8 31 95 -3 +eeg CP6 34 89 31 +eeg CP4 36 68 64 +eeg CP2 37 37 85 +eeg P2 71 29 64 +eeg P4 67 55 50 +eeg P6 63 73 26 +eeg P8 59 81 -3 +eeg P10 -53 73 -42 +eeg PO8 81 59 -3 +eeg PO4 87 41 28 +eeg O2 95 31 -3 +# +# 3 cardinal landmarks +# -------------------- +# Nasion +cardinal nasion -91 0 -42 +# Left auricular +cardinal lpa 0 -91 -42 +# Right auricular +cardinal rpa 0 91 -42 diff --git a/mne-python/source/mne/io/edf/tests/data/duplicate_channel_labels.edf b/mne-python/source/mne/io/edf/tests/data/duplicate_channel_labels.edf new file mode 100644 index 0000000000000000000000000000000000000000..afc3b6f224eb66cd9cd798171dc1596032f05d84 Binary files /dev/null and b/mne-python/source/mne/io/edf/tests/data/duplicate_channel_labels.edf differ diff --git a/mne-python/source/mne/io/edf/tests/data/test.bdf b/mne-python/source/mne/io/edf/tests/data/test.bdf new file mode 100644 index 0000000000000000000000000000000000000000..d19d12803b9ba708273ed18e6aebd62977056b57 --- /dev/null +++ b/mne-python/source/mne/io/edf/tests/data/test.bdf @@ -0,0 +1,3222 @@ +BIOSEMI 01.08.1313.21.4618944 24BIT 1 1 73 Fp1 AF7 AF3 F1 F3 F5 F7 FT7 FC5 FC3 FC1 C1 C3 C5 T7 TP7 CP5 CP3 CP1 P1 P3 P5 P7 P9 PO7 PO3 O1 Iz Oz POz Pz CPz Fpz Fp2 AF8 AF4 AFz Fz F2 F4 F6 F8 FT8 FC6 FC4 FC2 FCz Cz C2 C4 C6 T8 TP8 CP6 CP4 CP2 P2 P4 P6 P8 P10 PO8 PO4 O2 EXG1 REOG LEOG IEOG EXG5 M2 M1 EXG8 Status Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Active Electrode Triggers and Status uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV uV Boolean -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -262144 -8388608262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 262143 8388607 -8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-8388608-83886088388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 8388607 HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz HP: DC; LP: 417 Hz No filtering 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 2048 MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON MON BIP BIP BIP BIP BIP BIP BIP BIP TRI ('&&P'(***********++,---`,U+C+*4+ ,w-----B-,,,-!.~-3,*)((&B&&'(*]*")((&#! Y    >   ,"#$$%$#$##E$%&(?+,)-,+9+5*D)B('&%%%%%&&&.&%%&!&&')**)('m(('H&%'&&'3'm'.(Y)X**)('&a&&J&%%Y$X#"J""#E$$%B&_&&V((Q(()(A'&|'/((O)U*,+c++}++*)+N++,>,#,+*h)c(v'<'C())))k)!) ),)M))%)'H&$#f#"##~$%[&(a))y)F)`(&$#"""# $#"!^!!!N!!"I$R%b&O'(D*E+*P**G++r,,I,,,n,+m)&$#""d#q$%&&s&'&&A''''B():)('(('M''&&'''''&%$$$#[##$I% +%?#O!  s(LY L!!c"!d!!"$&'.))^)('O'X&%`%%$%_&&<&B&&&?&O&&m''''r((W':'a'''J'&&''())2*0*)i)c(&($!~ 2!!!!R[W.!Y#X%')r*+R,-@-_--+-},I+)U('&c&'&.&%%%&'( (}'&&%%% +%z#"!!""#L%z&&&M&%%$$:${%}&'S'/(('&%%#"H"!  "t#)%&&U%#"!  d b!#j%.&U&&''I(s(())(]&N#?  !|"$ %%&>'&%%$s#H"!g!"u$$M$#""! ""#Z$$%&'(('W&$#$%%%&u()++M+m++,!,+**8+C+*)z('')+./ 0/I-+*)'%$$$%$Z$!$#e$%')-,0./00/.-..F//0-1}1100W00/.X..//.).".n../?1q22]303B211u10//./=.+)>)()~+,-4-*-++*)2)(((B'%$%-%%&'),/122o100/[001245X43L313P3<3211223210-,Y,,,.Q/ 0////#/... .^.H///&/l//b0u0v0012g1n00000{00%0[0[00N0_0/M/A//129334.310/.R-^,h++-./0B00311357899998O9E:[;|<<<9q87w7W7789+::E;(;:;<<=b=}=g===<N<8<<8=9>;???? ?#>=F<;:99988i9g9899B: :9$9%988Y8S999=987988:;<=>?>>@8AA CCDCD[DCCzDDE[EEDDDCECB}BA@a@ @?B? ?>??{@9@?6?>??>=+=5<d;:O::;m<<;]:87}76544]56478,:v:@;<=8>>8=;C:#97{644I31/./14678}99B988888y9:'::o;;<=>>#??%@@GAB`BRA?>\>>>>>C????G@AxAABBBBB!B@?>==<<D<<< ===<;;:::J:9:g;9;::::v;<>?AA:BfB'B.Al?=;9778S9987#9e:*;;3<<$==>>->==>? @{@CAwA)A@?b???-@@?=6<9866&76 6554k44(5;67 +776<6B66@6641+/-,-&-=,**A,-I/X0[123%4F4444r33'44X3E3 +3420/-`,i,-./0!113/3D2100161A1 2u2226211~11<0l/..j- -z------@-e,:-.v////.-, --o-#--2,E+)(N%"_!  !#$+'()*+3-7.....r.-Y....//.'.-m-,n,,,,-l----+.'.-O--.s// 11#1/(.G-\,\+'+q++),,}-,*'z&&'y)'++X*'%C#!:_!"s$&4)\+J-.-,,,---./@00011100V0/-+)'&`&f&;&,&&j'((+('&&&W'z'X'q'&% +&j'())j)5))) )&f$! 0   !"m#M#"  M!!!!"c"\""{!!!'!0"3# $$%%#%D%&&&'B'&& '"'%$# ##$%;&=&%C%$2%,&'()3**Y)()((N)))})f)((((z((#)(k((''&&&{&&&&$#,#A##$%%&&&&%d$!] =CUPX !"#'%7&x&&'.((2)*)((+('%$%$$""n! f 3 HI  d!t!2""|"!!8!!"1#%#"l"!""$$% &&%%K%$$$$%$$# #"!2!! } CV}>nU37lw)w`TK]Y   5!!_"""G##$$A$##V$ %3%%$#"")"  QDqEl   !N!!! _=&!#$&'' '& &g%v%~%%&N&%$$2%)%$#(#{"!! [)  , L]` b"F$%-&j&V&&%,%|$#"j""""!!   ( 8 \ -/ #2&b()****+++0+*4(-'%%P$#n##A$$%&'('''''&&%%$$%$@#"! +!!"b"!7 VRr+Z66E/hP:NHK S!!!"$d% &&'(k)A))( ('_&&%C%I$"! [o<Q[74!(#$i$g$$#e#5#"#>#&#Z"4!  v!"##V#"! P- 3N(!k"#1%%d&&&F&%n%t%%^&S''((/('&d'(V)))))***5*S)('&&&%R%0$e##"x# %%%%9#! N s   o ,  i ]Hj  W!b!""" ##\$##A# +$$%&a'(()*9**)*))))(('B&%%?$#M#"}"""""#l#0#/#" #"!e! n   !!L!!U!!!`!|!)!| [.[8`(oG +Y& Kd;1\P  u!""S""""##$A$$$%v%%%,%h$# +$$$z$####B$$# +#""#%4'(e))*+0,,`,6+/*)((I'&&6DiA(EEfm%G-Prm<y:8~/C5 M-tIz"lPDKnE7-q-^z{Edu^zO[<p-EFHZ`2yDy:V/5an20t +-ze t% AwAE29NCB>G06t'<.r\\b +c)ky fWj1TW%U`!t6wy*w#{3I  EwG8dKAmG}m_fQ#B&"IXMX?6M/${tj=T3.+E_$e !C c +   + hek    S}.&~zS`-` 7  +   +A + ? 8d_H U , K + +  { + +f Cm >1E@  |ZJyrv6`ux1(jk  /] }zvwk5slb+{:mULM&OnP\~qC"WH@_\(f% $ b~ HEEeH %e8|tH+zt7{l;\pklx^ + +j,ikQ vK$cH@z '@X+ttw EDV8BiU+JBiuM* ?UIO u ; =  IhCxh[Dgl3@isXK|{} *.+:JO|.1></wO6AZ?H)Poqx4k  ? *Sh\Feu +RR    ! Z t]`dv9i(J;_drb.Gy`5- O5 o3k;(%A~Nrs$,DtP(|ca"N{'ve-a8@] = px;O h`;wbE=Q}iUn`*f>*|yD^huc t09, M2gS8 Z*F~MFJE\G [Vzfl Yp s!dK&{+8&8>\DZ<dm>D<SZL>  :l y   }      H]+<3*  [Oi}M2#w JMV ,)pM[CJCMN<[)Wy'zq)sBJo >f         6 M  +& +  v X  = +T + +=   + 2  Y   + +k h    O       F     D ^   +} + + +O +O +4 +L + + +   m  &   +b + +   + o j A   +> + +|           n [ N < 1 - d   g   G    [  + +* |    {   Z J M2ngGm     7 ~ 7 Y q   "   .  _ > 7  9   0  g  Lj/t@)P' +zTs:h pU a@\5g +Yh }J/A:>dq%   )FY3%n`v? n ) > c      + + v    n ? &hI;J   6 + + + +D b     N  /,    Xi7Ol} p  G  +F +: + +  > T  +4  '  +O b   +; ?  Y    ayO   u $     ! f    + f   z +  * ^f8|3^&k>h?md%C;TL7IU2V<; ~  s   0 -  k 7   P & ?   ?ps.'H/:^}bCfz      - B r       W   } r | U     }           \  w    z     t  A   c  +\ + + + + +; + + +)       o b g     s P ]    Cjec$ONo4`%xe[G` +|' +v 1Pm=M!j`mF&@ <K< Zp-@z19(r{-O1;Sv5C -W(WYFI#RoG_ 92 )IX X +`(:?&b3eP9\<9jM(m  9 (  !   4  ^7-\ktX5>agHmW <#GiT& P+Hx31L &3>QV(~UX 0zaq%)&GD    G  =M2#$Fc58rCDriHnz* Lh8z\i5@s&6bz1aoJ  / }    J  {  f  + &  +9   <:<epS    + +M   u4CY5gwtWz6oDcFCZZ5"  5Ni %};D@){q`j<vkCx2T6x4 A;e^/hT=K/CjLROn,N{Gc5.;6>A%=0C* 6?R|e TJ 64wMkwz<GsDFO S.P&C*& !   : D 7  M'+e`nF-V3dG+ez1z2kCt {;{&ut%+;b0}t P<3miAKB'I 0:V62T]35i]% 9zG&wQ  !!%"! GDw ETY#&} +[W`:'{b OTRAxgs]d<Ie\4q\1]U*u#nzwqsd.-gP\]u{Y*W6m, P p % 5eYM:F$ntWfV6kTq|fZ^sdE|^iRXnb.hJ@o SD +y6,g~0Km"P k=F|~~C=6Jhdi ] 6  +    S  ?\, 9s  1  '       $A abHa~f= u;TuClL=wX4Re%!&>RfGe\J9C"? X   g  Q  F     lF w 0a | b +p <   +l + +e       e   2          "    c   5         &  +n + { Ecc  P   6   P  L + + V + +@ C A @ V v i  M 8 * #     T 1 ?  + +p J j  g f        _   B +s   6  + + +  + +h         9<Z:Lj  e x p7U\?TKAe     )D6Ab3v6R 9D.V|>"U  < S         +p  t +    hK | H      u  I t  + ++ { }  (     G        p  + + +   +@ + 5 +              ^ OVKj +JR.Y=2]W D   AS&  |c+(  @(7_RQCMis:fsrd"!K![cq~iARB[D  ZR># r    bs}  e @  ;IBBn_[    w  J  W   w >      $   x o     C  <   u n      9  +*   k#CF (  `   t;?/    W%< s  ` 7 |  )`r K z bbObhb cbbbbbccccddieed=dccccdccecdccrcdsdcbc/d@e{eddhcbbbbbb(ccccdLddcpcb$baaaaYcdeedc b`_8^]o]j]X^^_#_U__T``` +a````abbbcwccccEdke#eJcBbb/c&dd|ddde`dcb.b`a``_^^^^/__n`,`___^c_p__r`&aaSa``n`3``aaBbde +f8ec b`````.aUa`___/` ``_;_^___]ZjYfYYZ\_`?`^]]Y\"[ZZ[\+]]6^ ^a^^0__``?`_&````_3^\\g]]]G^^_)` `A`_H_^^]b^^__m_"_S_m_Y__t`abxccdccc`c|ba\`Q_^n^z^ ^P^?^v^^^^^_R`#`_^(^v^S_t^4]@]] ^____`t```:abcEb}ahbdedca8`^ ^]]^^_``"a]&]\\m]]E^^]]I]z]^^^^v]$] ]Q]\\\f\F\R\\\h\5\[[[[$[XoVeUzTS@TUUWYZ[[[\]$__^N]\[jZ YX@YZZZZZZZY[[K\\]]h]\\\\\[@[Z&Z$ZFZZUZZYYY{Y YiYZ1ZZZ1[#[|[[[t\]h]7]]^^+^]!]4]\\\^\6\[W\\ ]\,]p]]]]]]]]]G]\\]\_\[\\\]G]]]K^'____e__`a`"`"``IbFcc"c>baaaI`v_I^Z]\\i]<^_~_]&])];]]]]L]\f]]a]]&_`ao`m_^\Y[lZYY*Y/YYZX(XWWW*XXXYKYkY[YY"Y&YyYY ZYYX XWWmWHWVV0WeWW6XyXXsXWWW"<"!  > og  R 0i^$0SR8D@^VzSWT hE m1DJnzt+ t I@BE $ & cZhYLY1"egVt]X}% l " lqU/dbZo@<%]U +bEZCb ^ [  , ' 9 # [ 9 Q 8  +y +] +< + IS4 k  + N[ q + +( + + ++ / #  F + 5 $K N + +L (LW  > ,  + G O z + +" +}PNoa?4:qX^m=z <-t2<& v(Az_ATY`lC q ` +[|_  ? D&BgrnO +3 (@  U x9E`3sN9zdV7Uh,/#RE\]P?!7  [ +/ ;y5=Nw85xWywez=2q67k-*V1et+~(F )Q y B + [  B \=2V9i[hn=W+!FD*-c3VzADu'BpRUC%txoF  #~&.m  : +  + + l  +u +\  ] + + !eq ;\+>V+| T,n#YLiL@=h< G  8Y  MbI^2nQLn3  Y , u E +l  + +Q I a  K % S  # p \ '   3J. |=W(O +Z &v=N \ DfS8 + y z[Z s6JH"bPB=bhg[( | T|4ERo/hX@uX~EMmeU +h +{ + nt NFOE +> +3  +y i4Oo + K + Z +b + + + oWJ3fQ" Y C{ qZCGm?Dke5E*qeZX'YHt~EYme(8Sqb#:'4<ʼ߼Qk]ɩ02_l +*+5 Cu(zLU;+й۸ŸԸrqaǾɿ5¸8oGø{θxɹcJV+H_Qи@T3+ .ڵ~o.5qhӸGPŹnU&oڸi=_ȸDx۶T8KdbȺ޹b-5s{YMsx19sW߸*`]^eúcչL%{ĹfYD0`nL2Ĺ$rʷ׷θȺCnƺz Jy? M8m/3) +VZJùw&%Y1l 9uIeǶ=|xַӷöLo2ǷOx'Bfp*εֵy͸Wnٷ[lLkzb4߷Gq1sŶH¹kV̵ex0߶i|KߴȵWsO)|ȷc>%;PжP$E!u7޹e0k_ͶQƷ|NqeI̷'&ó޴hI8ݲޱٲ8m/l8ֲ*ʴrHu]| Wٱ̯BwвسMٳRݴ +˳4`4Ḵ{t7DJEI1]welLͰoױ`o'YhG²:9k خcdnXڵ߽wδ1$>εϵuǶCն¶q϶ȸùKp0ͶZR^@BѹTCVc %޵ű۳2>ķEض9%^3Yd)Z:Ѷ__=BPR JJҵw̶"ض%ҵ&̴8سδζKظ) Ǹ H` ^:ukdRܹ׻*ȼξ)oU "V 1v0Yt--:mc$_`5˼>̷:7l߶Ӷf C+tq3عܸ*ôn۶dn޶v3T0xĴC; +¹F%U 7JǶaS͵AYԵ\Z:}#)ֵֵԶٷ+vܸA@QQ!_6PG:{FڻYCe N&ּнrͽ(J7g\C*5ۺպc4Z{,sźQCqfi%TӺG[y)wȷN+H(1+} ĺEŶpֵն_ɷԸs{@3YD˴W'bEfӵe)Űq?ȴzJӳnIE9 +߳dzldG i cC@߳ &q+Z'~sA_?1~ϴ{ѳk//XqǴմ77 kг6[aovݶ;L3MӶuiҶNжc¶k?gM>5?۵ʵX]۵ҵ*dݳ\/̱αdpƴIKǴ_znze^³4 +sӴ'jgJ5*!Դƴҵ]~P-sCEme.N 2V[Jն2g8 NTRmt5O̵HNOvi* 6D,?N۳2Ʊ^SM?ޮE b{²E]IC±ֱ]Ͳ/$49?ñܱȱϱ_g~fS|,+¯.f7w޲вѰDů? qrױ&°97۰'ޱl ðf7s'ֳm +߲U:,Բ`,uM69-ZHs4Ĵߴ;?ǵi-(2;}TsOJ`wGѵRX-ٵǵ0$Zi2'R[m +Xٴ^\na"Q?7s˲Բ kӴߴH ٳ4j˱رbDZr^?V?հaвѲ˲HVN@p;-ʲK\q޲D3)I&Z˰Eݱ"ֱܰβGóƴ 3^ijųGҵjCƶ]MYa~`N'noŶ"[%÷c ӷNڶ+\Tӵߵ?+H~I-c$ڵXôIгǴi(yq#r{V]fʱ @±=V|gֳ׳K2^$2ϲe +)|yʹ=ɳC1ų)P6!wCqCֳ"5ȳP7ҵoc=/j˵ĵ]lmFĵ; >ۘ6ɝb_BA6tƗwyW^A**Ԗj!×^ϘVJkf"ll@'f!Z0ȗ6e˜K=_/ljcV—/ʗQO5CLQĖUߗWv™Egc60.]Wa3Lmr~z(bzۚۖśG5Δ×/rȜ67\dP_W7x@ &cٗȗBuӗ# +Ϛ!ݚ9ڗ}Ǘ6@/jP%͘z 'ҙd4L2Ĕ?/~JQu~H5c,Ŕ9 jT-ffՕ ÚFxe̖cIOL/ԗHhya˙xHy͘˗_5 ˒i=ma:nsʗ-k!'<ט^ܖ9Em2F~Qٕڔi%ܗI͗+jq[X "=donl\d90Ȕ3\͓ޘLUfC,-yϒ֓.),MyޓחX/-P)jX^ʔh  ~RiuݔXABԗїzϗy`4iٓ9kSj_ʙ/VKmؕ$;@ΕW$fZܗ +s7ЕGoWsi"#˗ԖH32J0{J  ۚG.6ȗMr˓@0fOm?-ߖFǗA/ѓƙeC<7;x^͒ʓɔ&6uaǖhŕ=E:X9 *ܖ[uÓZr!uHzU?7Ӗp`ysAIH@. w;͙ޙԙ7J3śЛUi*:[a[ߜѝ<v~jߗNƛMS@2`Wޚ?v0Θ,ؖ< ]2,ʖdyISҕyƖu̕<DZT8usAŖ*X3xy#ܕi|Ɨ;:ʑMChǔؔܔՔY# +mkzrē}*O˕k.AϗHkG%9͙WH= BϚ{dAӛFmD#?j, sњ(֚טQ0_՚<>U@×H=hFk2`OEF&;ߙܘKۗ$1%lۗ˗'38ܗ`=#h'͙tUdL!ndŕەҖjJc|}rΒْđ`͓0Kally’ j!V3=בݑhz)lKqڑhWp 1qeA$ϐXܑIS$(aґ˒̒j gZߔl֓˒֕ AٓS$2*S'>_f@"̕n6֕"a1OƔŔX'’ t<><ٓ+\W̐ՐݐYב!2fpBt9Qh3ѐo~6 Œߒ7kۓ@/S{fQ1Εf_Wtx>P@(S ,Kە9FY@X?)$ޓuHS2o֒gS8wʑّ[ W` Fz?ƐEِuՎ֎11ɐސȐg<2GFՎdhU+ 3cA,(778яwԏlؑ^LkߐِԏpCԎ8jҏRQȓF˒ǒ,̑xۑEi%qW&yi|w0R!ӒpgecJlkДؔFЕPlbؔ2  +f"Uѕ3h-x̓2_`Ȓ9;aȓ,`UǒISDtcu/؎֎pM)ǏXAZfwUG}omp_iTP(C8ݐsn׏;2!AӐݐݐA֓m ђ7+ڐ@ّu@~v;;˔ʔɓv n*eȕD/Еѕk<M̕ҖX͕ڕeaS%u}ϓxZ*GϔNl5$ǔs8$דNe͓ؓߓubcpO'Œu +ؒ<B2˒?{-^p(m; cܐ1:UFYp : JflP]wߒG[IɓpАj֐&Xb`Б@9ϑM%ΓTj5,ΔsɕvQ ILLH'y:K7W432//J/-<*&$$$# B%E    " ]W +C +x _ "/FugB&LPZ{JuO.3Qp=jQ=T**`x-c.dqQ|p9[Zf zbS? L +:sj7J; ("K~Idj&kPaqw=( G8eh&&aY{K2_ZcC%{m#}% a}]/kiyTa;0gEp:1m- (.P#a<#=t_..[^h7#03nu'<Upp'4 + 3`T]Nmp7O"D~0%OCq>lJ]K< 0ik a@pH^> * +ZS7n:Z<Wze<8^ ajYָ̼ǹYw8 +ft^Щ)o^ԭŪ٨IʧhۦЪ4ƭݪȩĦhD_5¢f$СܡT]sإH?8ʡ۟v>IjĞB;>8&SأТ@̠U=.~0֡d-ڢޡϠ\zrcE-; dv/`|mr-{\|٭ ­IS7ֳ%İ"ygβ}(t ͱٱ y)_٬N'nP +ZQ 2ЪȬ.a?Χ:gQCz&}wJǣƦԨ<ê k@tާL>~X1{mVlИəHLx-)[ܗX@Yӑ5Wۑґ&0VHiܒƓS&lՕWVߕٓȒŗ(_? *GךCWH{gH٠RʟҠӡ`TԥB9af:ܨ۬;Rm0~UOb.SdI27Լɺv: 5`7 +K >(:xK]}h2kPnH|S'7!Yt}aJ?I<[Kڲ7/uVXU,ϧeD̥?s@!; 7;%[ϭ24GBSЧ`c/{#ˣz˧g٧Bwv4ǡ,ԛߙɘ[\A˞NޛJڞ͜ +̘ fEnPٔ^דUۛAѝMޟU`Ğ/ҕʛ\*}) TH&5<-|u˗DEΚ0z1,goy03$7}ftMÛD8uޘΘGNz1f)uW۝+@ڜcOaΛ_֜x$ȞdלgRÚpݚz4sԙ͚bd Y^BdkFbFm0D֟]/Hܞ)9b[SWq]Uѣߦ^Ѥ̤١&~ת|ح!ߪ٫A +X@j/|tHmLާR]QP֡ףtKԚ&ڕ +/q+ 3љB7̛MDDȞx-5G<fӖO:XALљ.2Km’V-k`hʜ(Üqʜ۝U@U54R*|ağp6X9]rʥ!GqGў?-npܥY^ħYϥ0Σ7EoȢbp5pML(~ҳNfխsӨըqVcdëɩ<;mЬy SslrǫGF?QyWHgʪfGް&֩(F:ɪv&j#$&uҮѯЭɪ[ˬѬ>ܮO}B֮'3ͯ|ʲʹzRKۯ 5ɰޭJ<ִ~ŴIvwŹbtҹ[ørж\ܵ(7:ٻ&ZB]?UB9DrG+ @4c(+)_D2h.wa-5D?O<>cʲ״9rɺ;v˹˷Hߺ@4 <i>BItQc/+}}h ϽľV1 rn9.n\'{4 Lay +O3$^/$Vym|Ea"'GbzX1C$i1f+?`Z~de1TGAb =I[&d9yvV/ {r%'U* |*vUD>r5=kc e<:w(=by+ +bL )3Lf{2n=w>XJh\I/A##E^4J\aFZ\&@kl +3n!Tr,wq8eY qg { v&(>< +M@2{~Ly>4-tTMGZ=a*#!y`/.w+]35mao[& Gh8 eCDWSUQx])QU$WU,P1M)_p8QbWZ U^ .gzSVz-J O:~~Z~Qdlzq!C(} +xgd&x(V@p0msHBl -kg|6x}x<^l8|!c&=uiG~.'Z}38kAP $2q,x$Bb{CTXJ#`M:|2 5;ku2fXr^"'?YM^4(g1=[zL`)Dga>YeO-d;%F?#Qww@c8,y^G"~J^ Wa<>1qCGA(94fHz#eE45)RB{^Zs_fPzC$uf0oL} 8OL.DrO!&1-\lMYk d:kq@CQlMO"*Ai hLt UWI~ZP$a]]dP?Jde[_T\$7lkY]?(],W $E-jgY;3Vpm ,4/R]l=.b!J0 o:@~:_)[c&4P , D(,q4{:w|vc + eG #L_V"JPmU5(3}K +5 4I|\0~5M!4s,]s#ylZ7qP'F?qd`[;G8_(/m>sMX$^xP0; KdLDJTaf `q 84ida:\s$>q}4O Vd^23+O} Q?C5D *Nc: $ZG|wlQb 1H +p#)e2b3>Ov@=jc]-9zb~a#r  +'ap}QS`WS_A3oYOA+Ybd'7QCIJM '_IM!o1\]{^ F y[~rMBc_7`m^!= +,OR\QHUjt8'/K_}"C*P TF\]L0 +@mlkihgijlWlkjjj=kkk2jhggcgiklrlll)opppo3lijii!jSihi$ihijAj>jkkigff3feeTffcfigggggh`hhbhh.ijj,kk]lkjihTffhij(kjikhqggijj@jihhQhi0kxkjihgfg-h'i(jk"mnnml>j8ii+j2k{l]ljQj:jhKgHgilnooonljiti&heddeggihhihYhOigjjjjjjjtj;klnXnonnoq0s_rpjmh.ddnhj2lmmk+iUfcbdghjh=iii)jjMji^ihiipi!i ihrhhgfffsfvfgiNj*jrjklElEksj&ig|eVdddefh@jkekj^iKhgghiiDhgghiojjjAj7jjj`jjji!ihhgggahhgpgphziikkllm mn$pqbolidbcdigohhSijVj`j+jk2llnwooeonmplmlk{igecjd+f|g-hchthhhg~gg%gffjfkfgEiiiihg0ggBhh$hZhhimjj:kjiSihhdiihuhh?iuiihiijMlso]rtsrolKllGlNkh3dab>dePillljAhCd!aabdfohh iijjjj{ih(fefvfee=fQgxhijCkkljDjihfcbc;efRhj?lqkihyi=kmm^n psqw'wFs}lkbXVY^bdtfgijVkNkMj7gcacXdheeueddc'd;dcdfhicjihgfgi7jEjijzlllkcjgeegjk?mmmlje;babdgj!kjgbadhEi/hcgeedke=fffg}hhikkklmnmmmmElkjkji5h>ggij^k-l?m:m~lkkskAkjjjNl;nopppiomhljf`_bJf +hhiTkm1mVlkkejfjhggDhhijyklllkOl~nonkmifcce!ggfeef#g5ggh,h8hggiijkKkihilCoo_n5l1ie-cb)ccd#da_`Kbctdddieeeeee efe#fsfffhhhhkkkjsiiiiijjjzjiMhFgf+f@gijmk8kji(ihhhyhhf g[hijklnpolhdcpehh{geeghhshJgrffghh ibiijjkkkVlmmmmmk5jTjGjihKge[fg8hoh}iii)jj8llmnMmk9jhg*gfg!hhi +jjQkklkk5l lk'llPkkjdkk_j"klmlkjjjjUkkzk1k[kkl{mmmQnnnnmbm*mllTmmkjjjkTl mJmmnon_nmrnopp-pnm8lpkLkUlmZnLnnnjooJo o,o>nkjjkmnxnmmkkkl4lkkHkji$jklGmmPnn6oomGmll^mmm`llOmm}m?mmmm]nn(nmkjhhhijSjoj:jMjejj9jjj'kk7kkbllDnntnmlkiffggqh~h{g0fed&e$f:gg_hhhbhgRf%fzffsg hhg +ecbVbc>de>f&f$feeIff1fee.ffagBgfffgggggXhhMiioiciii`jjjXjfj9jihhWiijFjji(jjjqihhnijj)k\k +l>l>lllYm'ntnjnnmLlBjhOhi kllPm;mllTlk)kjZjjjkkkxlVl ljhf;ffhjkk1kjXj%jiimhShhhhhhihhhh iNii ihhh ihhhhhhhh!iih i i%ii iiiViiUi ih(hggghhhhii"ihzhhhgff;g_g,gffffgfgg4hk"k$lXml+ll1lkYkVkkkkll&lkkkkj#ji jnjj^kkZlmllk-jifddGeefgAg,gffffg~gsg@gfeweldccdeeefeBe,eWeweue}eeseeFffffgfffgigf6fefoffCghhghhLh|hhhhshNh)hfpffffggHg7gffffffzfgff8gghYiijiwh[gfrgFiiiiuiiigjkjj2ixgg=hggfe>ff`g*h&hh]hhihhii]ihhgdg]ggg=h.h7h'hVhthhh&ih/h_hhihhhNii)j4jVj>kkjijok;l1lkllummvmlBlkOkjkkkkykkkk|kkklkll+lRllmHllkkkjj)k)kkjjkkuk+knkkkk}k +k +kkl4lllk`jh/hhhhhGhgg;hPh h/h@hghhg5h=hggg5hhRiiiQii|ikhg[hh6i ihg0g6gffekeefgagggogg8gfggggg7h1hgffffHffYfg4gggghghh^hh]hbhhPhGhUhhiiiii jjOkkk0&WcgqTu Vv{d p=o cM2R{W/rF6.qX+,zSd1NXl + +.`x)shgCP|C]md=>mrftaP3;z/g  ' fVN${QG.}_S+D*mh{xZvk\e*B]5MgDOl[m~-w:V!KZ]ywv:s+l 51&mEQ( [5Y9qW4UA-pn+a|D1(r8 @<Tp)+'6ANPwBiSP 4M 1RH/6-$]/Hcq[v*NV8~Bt\E@'H<v-L5=>0a[Rm>4o[dIWlSh@9E:F;  qeMM M,*Nq_gMu>SQ77vQ! [,"L7Y0%?:lr{i"&#6mK<}j?MLuI[!%A@<&/ +KX&gl-O?.C{R Gzz_#w~w-XCXT!$`<$'niu'I9zxn\< s]\+#v:M|D*qj?9FLfOY-akt:B<q8,jTjB)x]51zBOm 7]LlV<"`'|e)ekWRB?wOZT{tO[RDJ-;^KXwfyytk}91N` T)tS`W:g&Nhllw,@/HQsox|Tg3=)_KWlO"<N4Wimh_oM+wKQC)&~ .'1AXp8jJw)!2Q +I)SXpQ~6]~\!6k`r7r TH%r6E[AY\IRhP[U\5c30> m=rAHx^DE[*S* Ce&HL2Pu 8LFkbmoQsLE6yD4pk "X*{l!y6% <O | * +_^&z}m;Kcp3Mp +NVx9!J ]oS"W!PVu_Y-g`Glj5AWHP#=Fk2R cuD+OHFO;vt^Q*Q7rtv` fySl L T0*JyE?-4vxpM$o0>)u~ws ZLApL}9jbNdw+ i>M/fto_~P 3tk eN1h5D*"G[ivN)'[f(]]gDW^SQsg$+M]mtP\G hS[hG(24Gdo2q~.@e5Uw4y0JvHZ/xcBPH  &.? +Qca @pǻԻin*޻2{޼WĻYmӻ/") !pɻ}`>\=A rûһD,պƹVܺ.NS)Lƹ?ϸyθ3re͹V AiaQ;aعhzu¹ɹr +H߹]6l(2s|d,sjkӻŻ{ۺIl<}Vma?XxS,+Լ"ֻ01]+Grj~._QgL+@@9 ø|߹D*ع> ,x]ȹEYĹEdqtlcȹ \IH%"ݸظdg  ٹfԺպԺ5g̸ƹ!Q]Ⱥ&Ի\Yz/uոȹŹt_xviK0 +"Z 3@Gs9ݺ޺ҺԺ;KL)mtйi^VF׹ +JӸ;Ҹv Du0&iFLk&ks̷÷w,sZ[(۶%3zi*ĵ+`a~jTm{.  2"utз[wkj^`޶ܶJ9)qd|uUhgǸV5' ҹйܹι`Vj49e=ѺmB"ʺ^}| w;5G/\ٺk4۹+pq^yBqW$f(A8·|Clŷ۷_zɷ$2.a ;ȶaٴ24<m˵ϵ13*7Rs_ɶ նǶ\%o]$CVƸ¸ָLU#4NK]yN<!6ҺH\x7mDպS:]ѺպY<~ѻ7Yv)R!N6qHӸѸǸ7 ɷg3.q5̷LZ=,>o/RuM>}UE2ݶӶ:TȷZӷxŷ϶2ҵ'N~?[o=6Ec#-h?Vhͷķcfgø*)yIV^WH*^lrZ& 0J!wEOջehQIil%U wh7np]7bк2D1,:+Nl5޹NϸGh^θLIE5-hV-01BA> }z ׵`*ѶG(OWipiǶgʵNĵxyȵ\K'͵- +kP]Ŷ  O߷faz^rVkշ,{h4ZgݸŸ *Jc> J"۷]hM=ӷEQ\ w jgHWֶqҵ|hʵ{D4-5KK$ɴ ٴȴ~hoFF1>ts6:LlXM_Գ=aU|߳":9xsг@88X;' ϳ  ;Lȴ"aPH'+Y$e ^BFε̵NtzUص ͵ٵյĵ +HAE=8zJ@pŵ;{ٵʵ]ص+ŵ|uTɴĴjszfS߲X-޲ײ,y.߲Ҳϲ-AɲزͲiW7^Z.!\ֳ9~۳"׳ҳk&5Hײ<H23xyRղܲ4OS2Wfr~7ٲ²j3OJuò=Zof]2/Pq|̳A ߳@.Aдj?8<״Xqq#˴ڴԴǴܴŴݴִ%0̳)!ɳ޳M6 [ci#ڲ̲)˲hYzȲY>D^s߱α-ձC?*%@97E%4LRCD`M5Sڱ9XӲVJ5 ޲$`Xd:Pht%89"AײȲȲ}djs)A$Iϲ1iFwCJٴѴE$ +%[ǵǵ#;صֵɵǵƵܵεݵ׵ĵ~:R}MIM 7>5(J+Hqd~P)'ZU-H4yʱ_رP^_\?ewKW@  $T ʱ ޱıݱ;+ٱwʱñ{±ES5K/+15HV TFر- )C+Wpz^& +%Gc    P!!a! y  a x  !  %!>"Y"""!k Iyt#~ ! #"!^vC!!  !!! z+S|l 0!!"#F#!v o*G!!!"z"!n]n5/V)DT1>Q [  X!9! " !ZJ0,EzCogb{  D t>D B4]* F!f"$#"]"Y"<D1 hG !`""!!4! L O t$SRQ g   i!""""###"! _v&  !! /G\[H $ y 6oNF  RBD 3(!!j!] uk+w ! _%_6 g!O! N'< ' f!!<"r"+#""k#!h I1wJzo;]8>H B!!;! !t#d? : s* 7 p"#y$$$g#z!!###|#!YT.w=w\:)^[ a   i*vc h X,=Su a#U$w# &E|XW] H!""j"g[!Ps!k1{o / Q _  ` + #$<%>#ag ni*?*(p2 !i!   +!.  B nG*!!A""##"K"!  !""! Z) ] bKe "#y$\##"5 8H\.C& I 3oA(u-\WDhV  $! $"=(|}}ucT<$ +6{|{!!g""D!NCahYC8r"Bi $!  T!!!"$N$##i <.E !_! !  !!,!2!U!  J     !8"Y"! J ;vq!####" +  _ |"|a6Bm2>rH]1QtSB  `Y^k>KD [j=@3g  Nvr) +Y2  ? !qQ(/Z{uY/ P6*XS x-25pH39W 6  z c#   )6 !!! y0 f    !   t  _   !N!+! t 9   a   B<8  R #  \nps T 4 c B  F!!$!# P|}chZ0pZtamA: M 9`9O>O,A2Z/Zq;H)bf'-_D^5skZ X  Y  5 &h'|yL=7c  4+xl|x[%`3}l, 8BT :Wo`Y>[[IMRH#[>-C7W8W$0gpj,f='8505j&[D20M[C 0@m{GVZPMt fVSs9Yi0c[a0'7xQIV9 )4D$eR`::\ NN;G4z_MPB2^t A5a:c;x:,EYlo}k f72Y`}qxI_U Z"t3c'($UUj Xl 8 1~'tF0AS BU+c ZpJ6ej Q z&Iz)a +0E8-QU[:^ +{/J@\o`Iv| LaT<mV(IvD:Ih\Fa;;2|I d/t*{Ha:m +zDu t$ep"@v>kp5./o36Ql~Vh_e_(nGcJ876il]k+#{WTF=r^qa ),dvT`Y>-0KYxc_.mc9~1K0T`L1`LF~ -H\Lq*}mwBy>0|"WuPA:7 )6P<0"iq O _Lc@bX# y.KT + g}r2(_trfvU\lTpyf0iXIs`Ac#G^O[99k*|+#K,l9XdJdl&Jk.6_TAS1@~y=5&#Qi\ f[2ub +n5/C{1cEk4vJWcDn { DK2BN/iGQ4? L~  %umb12b~Jk^[!)}-DB+a,^+$u (k"|4e~69\<H-1>r=B,O +MtsHQ`d4\^F{g)u}#7,)`aj#z,s-9ErX6.T\ [2?  n^Na~-To3+2zdo}Oz)OWj>#e{5y]x8Q`kDW@]!yQyF<BACj:L ft'g LF#z O@8C3w9;wDTrfvw,d{1r3V(Do:&=6{b ,Eo)pSd1b~tQ'U+)As0Km&<}=d'5Sh}VPmF+;9J!2-hQ@Fo \R9jW2URdCW\G`w\XjbgQ?EjwZ`>auZ7F y=:5O*6IOT"/BWW:{c{qU)tG];n>sB^foMXD?YQI  >^^X \|x6 Qqt\-eumAi pyXBJ.T!&90=D=:d ^^ng*j`oC ~LdGh&db"%V%jU@<6lQG2Qd&BB;iZCF2O9#Oagy\'L;vo:? O;Zpxte&3oR(-TrL%O8),0*w@oAR +R;R2PC7{rl{X)G$)e_i +MiyG;Q^ jAsTw hC D?jGw/On1P6%A 'p(ItR _4KS@kt$}{grP-8=aJsH lz@K+!K7!~ot1,ukh+{$R`28 =8`MkD 'tQoU,rR6i|t8   #@vaWGFK}rjl9ZpCSTeRh"QM=HqhbBu:J7Mc&6)s3W{2=wgA:nC&'*Q$m6hJC7yEXFvjj7Hn1_yY-n]yhhv{{|Uz +- ~;[#-q}p +3/I:i-V^ JV(l aHOwmG51x]%S=/ /l Y:`Og 3+5qZv A \J5eFZVET  -=DSZJ5x1 h Tf^g%[;EU,{[<u}h((~E7W E .DW(j6X@v['c9w-4tgj<Abe-hgF~_,4c(ujX4KN +#elDziWyMD04x8Ua\"l.[g^o2 O-+'oB)/H +>[W76qCO+}=qw9JE<48g[GywaK<EXY f +QYe!!3V%$usL$o> ,mfsT,[4aBEI2oKEn3&KgxeGvj" Sb#\'F`>b~t8C}2#vMB>%vavuMd!#+Dj7.c f?dt;:\zJjlk~X ` H8"&tp!$gx`J~-P=Da/e$~%?|i5zVCt HtT{[~@ 8<T 1VB,i: 8i3*kZ*Y">eEMM.F7 <hU~3le }WvmJ)'32 "OBZ;+R71<X& `fC)%P~|>hiH~Y<H[\iy[far`D k3#BR~ex?=`BZ:Jupx F8 ,y'DOM~^&I] ]yM`'v[h ;P4'EFI-6uh=[mU4[/1 }ET^2 jP3 Brcb/,bJF UZj1vjJ]B%ad[[Bn9#_B%cllxw"d8N:zc[_Uq/oVF0'wjamIhY%;a{N%)N=,<`}T|L& PW<9i6_ +x}\~Ws.4dR\V6ezJ= B:0FsJ92 RE!B +{K4Im(,KRy|0mZz2MYZ5<W5Zv}5l5B@}^b;/rDc P9/ 13Q YyH-EkNCw]xsC\(W}=Nh`Eemc]a4:"l\Y73^&b\ e p8i]P3A%IAH6HkN^$ivBtA+7bDUe +i|_auO6}FKnBO~f=" LY|& \Y2FF9Q",:xTI #15"\$ O\y-dlk&$A; "yX`eV_n7\CmJ63w9=L5,"s ?1gR}hEdz8o_BB6r hZrp.?[z]vYd\ jt:#*>?"^?~u&1qc"_ 'W7'. q&| YjYfQ`d'A}b"9N5X;bG3^Ng}!y.36l]aNQv$0u!)SMvGnl u/[)F B]j=G], #;PzLeVRaL?%B/8OBz3  ~(' Q+c2g \++jD&gaZMao^hvYTkuEd*kdC ?la<.afIs Q~8\Q%:M>nU[u2 k>jRK:@'u:b]D&R+(|.B=8{ jZ4fC^O " +o$0a]en)/HM-:k"9/ ~+%{FFK3 ,9 `ledW1V5ldKuECfG_3{ H R[1$'WpTn'[S6^rklZS88q}Owo} :R/8ZH,}euMY)' 2shJVl{i:#ZxP[_|6 <Y,O=_gzH3,#HbK}u>)^Io\C{j}bLrDY9AUC#m1[< +)62n aY L l=T8!"pY0=$wlj>:O*] `N z_W<R.6y+l'y GXgT.YSX19 <`er|+b]#UmB#*\!mW 57?KH Lg+bm'D#rJ}%b}]}%FFmp; W+@n7,oEkp"@<SdY3eEAoAHlvw5^<E6C40W?*=5/F=Xb7\!*htf{,~iyOzqS"S$`^6-O B91l.:ZkBjbz~3W(lJrLh:>wcw(98? ]np ireQ |e p.<Ey^;6)-7^YYDsOXcU$[{`~jh>@7CIRfPPfj]GR!2 +/5/u' jT V* t#B2 :kn_{3(7i?`*` 7X b,fc/DPn;;s@RC=\JjSh47U8 =/2J{tVXi'W7Ekk '4f7oxHz'=U9!2~UO `E)uQ+>p*fr()= P%twp[`G#yzNF]SDge)*N8[L}Xr:]6|@i2-9 4Tm4T(o:^=k@&\]-vs!K MkG/ Tw^r|x@"p?l~[7 )0jht.d\$ e 5Plp-$.L#G{,i'J 8kzGy}H1EmQbcF +j*\y3/6) Pmm{CQQR5(tLf*6Gt^D +2H!;Mkx 7e7$o*2Q$DZ<%UW0s;S<Fo-6E  ',ZmaS,e$tRb+vU/ + K1;R:5NbVr~z;a?pG' JEMXby9}F5T#{o )bF-wI0jM%ZMg?7qO &g&@nfE3d@H;H".s)C67$"{p(: +ILw=2ZavY{@5;1o@as&+;O2D[74%-7cfo>go&X+9tGQ@ *%U>h5*H-p2~Te`~eE?4G4"^#&* 1um{CwoqHBX'AH LOL<nyCV@teYI )[""ES|ptsE +]KM)}WiKfh{ 41JvTd.zf;x_ 40EF/J~ eY$9Gh@p~3:#G%!uPCWoRVu>[tu Q0!PHd07V k'v >E[BiiEi,4LI2%KVm M#m  ?YAyR_BIxquM{># +[od2%*JuzA'rSs")KIz=Bu>(,`t<?^P+ W5!N_9nP"h@u NigaBrOZ$;pnm"B}HMv8BCsltbV +q+FrKsDL R(CjNz0-7pA)14R:#^Kb!yr.#k+ N|+3Fg7uyN)g`zLp,:xAY]Mh('3PDH#k]XTc ^AKMUy"[uIW2*{**;GSy1Gheq? /=ejx<F[;G.B4^^ +O)Oe-d!EWQK8[ \xQ]s6k?x2^8%Sf !&he?A2q-Q#gl!!PbND"-V4,3Sl3Y"iVT D_e H:vl} &eʀFdD,ف0΀EWہ.F@nu>[Evy~E{Ld\W'QI~U~y~~UD[YR6s~!~}w}z}N~~B~~m)3oA'Q5&|~~2]\3h Ӏ%]|܀?~~!~~~ Rw"_PrE~~[~~+m 2b~xHF*B**JҀH~i~~4m\~3~~F2<"rrO%@*;~"~}}}~~]~z~~_~u~~nC(a.~}~!~ ~~Q<1~~}~R~N~w~5~Q~~~R~~}^~~)~~W9~B~~9~,~~K~~~~~R~~~~U~5~E~}}~Eu~:~+~ +~}}k~~(~z~~%~~~9~}||r}}}}~p~~T~l~}x}|||g||2}U}}||||| }q}}~~~~w~!~},}=}`}}P~E~}}~~}m}z}}~~59~}}~~CS~}}||}i~~~}|"|i||)}}}G}}~~Q~}}}}~H~~}}||4}}~~|~G~~D~}|||||c}A~~~}r}}|C}}||}WH}{e{!||||||<||}9~~}{zzv{s|f} }`|o|V||j}m}}}~~}|?||||`}~Y~~}}}J~~~~I~E~q~~}}~ˀ3~<}F|>|+|1|D|1|||}}}}}}}m})}|d||||)}}}}M~O~~~~~~R~~~%&~~~~}}24m~}*~~/n ~^~l~~~8~~}~~k~.P~~~(~}||||}}~~:~}~T~~r~}}}}}}}2~B~}}#}[}}}v}}}}}}!~}}}s}M|{k|}~A~4~} }w|{.{7{b{{{{{{||S}y} }}8}}|{{||}}k}}}T}|v|G|$||}'}|||>}}H|*|@|H|||||x|||}+}@}^}}~H~O}|f|{{b|}7~z~~}}}}}~} }[}}~}}}}&~\~$~~Kj~~~~~~~~ ~}||*}}}}~x~~~$~6~}8}}~ WU~}|}g}}=~V~w~W~}}}}}~~}_}5}|}%}}}~p~~~}|r}}i}}}}}O}|T|@|Z|||| }q| |&||||||||A|{{zz{Q||||{{{{{;|@|{{/{{{|a}}r}}|{{{{{{{{{b|||!|{i{b{{{||||Z||{{m{V{u{i{e{n{{{Q{z{{/{R{{{{{.|2||||c}||{<|3|-|q{={C{{zzL{{{{{{||Z}h}}|{{&|j||| }|||2}}L~}}}r}:}}.}|^||||V}}i}o}}T} }W}}} ~D~ ~}}b}| }|2}}}~"~b}||| }}}}}}~3~i~^~N~C~}U}}}}&}$}|2|b||v}t}v}<}!}6}||r|m|||||#}||}~}:}||||||K||*}\}6}I}}}}}c}M}Z}z}}~_}||{{zM{{{{{{M{X{{{{{$|{{D|M||||{{{{{zzzz{{a{t{zTzzz.{{k{zzzzz{{{{{|z|{{`y%x9xExxCyDyyuzzzz#zyZynyyyDyy}|||||}}}}}j}4}+}|||a}}}Y}o}}}}m}J}||||||||*}}~}}|||||3|{{{{{{{{{{{{{{{6|{Z{{F{{{{:{0{B{B{o{{{{{{{{{m{zzz.{{T{3{.{zz {/{g{:{K{zzz{{z{.{m{{{{D{{zzzz{{{{{{{{Q{t{{[{{{{g{G{K{{t{9{{zzZ{Z{W{{{{_{{{\{{{{#{K{){){){U{{O{/{7{d{{g{~{{&|.|| |||{ |p|J||{{m||v|||||||}D}x}}}}}@}0}||L|V|'|t|||},}}#}}}}}}}}}~'~2~}}|4|{ ||{{%{5{2{K{e{{}{{{'{zzzzz{zzzz[zzzz#{${zzyyyyyyJz%zzy z;z(zyyyymzz{zz:zyyytzzXzzyzyy/zzzzzzUzzzzzz0z"z'zz={{{D{{zzyy^z`z^zyyAz(zzzyz9zyy-zzz{zWz=z zyyyyytzzrzgzzzHz@zzzz0{{,{{{zzz:{A{{zzzz{zN{{{{v{zzzN{zzG{{{T{ {z2zCzWz`zBz*z\zqzzzyByy8yy8zCztzazezOz)zyly2yZy yx9yfyyy7yxyayyxxyxxxPyxxxxxSyy|yyyyypyqy8yxcxxxyxxxxx,yxxxxy?ykycyryyeyyKyxyxxxxxy!yyxxy9y1yxSyyNy#yyyxxQyyypz[zzzBzz9zzyxxgxGxxy}yyyyy/zyZyxxyyyy6yyzzyMzzlzzWyyxyx&yvypycyyyyyyyyvyyyyzzyyyyyyyyyLz_zSzjzzzzzzPzzzyyzYzWz(zzzzzYz7zy3zhz\zpzUzzzz{zjz=zyy zz+zzzzz/zpz_zyzyyyytymycyy(zCzyyy~yyyyyyyyyyyyyWyTyxx*yJyayeyyxy7yy yxxxwxAxwwwwwwwDx&xwwwwwwwCwwwwwaxx-xxxQxw4wvv{wwHx{x&xwwuwwwwwwwww +xxkxxwxwww xxOxwwx xwwwwwwwwwwwowZwrwww'x-xww0xDxxx(x|xixwXwwEwwvvvvvvkvvvvvwwwww4wvvwda~dO^hW]~ʬŬs[iZ|nibI ;y\xt׫q٫,z^ԫ@FL rɫȫҫܫ` +˪BSC)pI˪dHO}MDȫ«gUL̪j-Shbpޫث٫ҫ8)</}lȫ)3ҫիҫʫR]ԫЫ}fuɬ[cw7)5o=ӫʫ6@ ЬqZ~լ  Ԭ ͬI.ЬƬլ]ҫpCkثܫʫ|{9dͪprTժĪ̪\ZtkfM6%ʩSZ7ĩW@')IF ;3Z,0 O>ifG۪Ū\Llѩ +.TŪڪڪ2l:@_V?EDaaMxbB +fa)JN4S~۪ cUݪЪȪ*S$I  5;تf*,W0%c թ+mc=tP q +:ܩ$ rL3Bקjʨ]Pjxtۨu#ڦ},8]sM{ΦϧȧħƧ#֨D+ohRSШӨ7He(Ϩ*(waK]ިè֨ǨѨѨ(2>jҩũ©~sƩ0éɩ%vPt\ fݩѩ֩ͩߩLR~٪719')bbw0-lb/|J3KxlCXU(  P5WR}f%<-i̦tT[gЦ{˦:"DئŦ 1,-ILjSR76ȧ٧\&ʧƧRmΨpl@w|ةݨG !ީ۩ϩJ6٩̩ ةET\}ԩ" H1I`t49թ_AШۨ¨tZW}k\4 dlj7B=ku..7h ɧ{Y7oX)0§RĦΦ*27 ۦ¦ڦFCF].JkZtY%2.46Ʀ!=iE<>զ{֦>ϧ٧֧ "ɨfsC֨ȨǨڨm3(Skĩϩ-e©ͩe%A|vxq\;3ʨƨWʨި֨֨;ڨu٨Ĩè6.<dL[mF9`y:M[95*Dew@wKB2?)o<H*G?;̥Хߥ֥lH:daʥ'6`UXCӦզh"7+K<.g}{ed@ ɦNA +Ed8p}JߦuKǦ_zT%!ĥ(.ɤܤΤ77ʣ{ϣȣģãhܣ#kL2swpPLe`upVeTLYȣ01[¤c]ǤǤѤ^BKy{cĤ̤y¤ΤʤҤqbH k3MZ ?!*jX`AG(w`nĥΥlavNMLƤwD[gƣC ͣͣ ~3C|& |ߣѣxwElʣڣ(գcۣ ֣jƣƣʣB\fiV2XԢբĢ +B<1,~_+֢F̢΢ܢ Ԣ¢ܢѢ5٢zU:_r bݣtl1@T  ʣXģ,;W2IrjbBKGh\S2Go2.gɣģAJX?E ޢʢˢޢϢܢƢtߢy~K0>X,9*;f]Ply/P^I:[-,"Qvsg%.;5.=`âze٢ۢ|ݢѢDb$ѢˢТtoT9niB@_tʢעVWpU5ppܢӢ(^ϣգΣã>= +ƣãģϣRzf/R7<Т +ȢҢIc=hH'ǡ١~]G'TC;oDcu-*Hq_q%I¡,Hm.E^t<% ;NKWg;BX۠Ԡʠˠ~qoKޠ?C5O9ՠ bWf0kwàyP0/,ɪ۪GSG!Ǫª?"~<DR.T{soj8FJ.9iNp()893T_o{mr`qV^[ܩD (k|{~83BʩY.)'Xb7P,٩8*ةi8ܩΩ ."0)/DG:s^˩1B )MԩN 8!Щ7|t~{e.OPAêb<iRO>QȪm)VeOGhTy3R|'ȩ©Щ( 00ɩȩ 9P':X{k_fhJR_HǨըA%#8DĨ/:@ ި٨è/Ψݨ +ԨΨڨ"wxNDQ!hxbmc2($ߨ4;i> ܨ@H!Ԩ9Ozn<kj. +GnJ1?Hbe[\_gWb[(M5HWC/ ڨ 49ި`Ǩ?KwzMڧ=EۧƧʧaJçiЧէڦ'*%*4Qg[k)?Q{SX9B8[~ҧ6DVf[}rnzħ^y[Q}urmq/N]3;ۧʧȧX^z~{ԧԧҧ%ݧXe7+D3˧`e|G#%X|:! WRq'קߧbŧߧ˧_nɧʧrg1G+RYD ئߦѦɦͦS +30 A*hf" 3ӥ?v-'U*;GV]wcQ[RƦڦʦ0ka-=6=  ڦ +^E 8˧}Q"S99onX>V~muɧud(Cu"zq7ZvKħP9Vtl3ΦʦȦ'8Ħ˦ϦӦΦئȦQmRoC9qyYZOIA&F Th!0˥ߥ٥եN/ݥͥzq̥Υ>liiz,Yp|¥ڥc+nsjY.lcc[`x>]tڥѥĥ<ڥ$::+mlbETۦjȦ ̦ަݦ)ܦצ̦)~-ۦ tæԦh- 0v{v}zrG/4?dJmMإɥ\}nYuJZ˥ +`6M9W1ޤˤ_]OaSkx`(%>EK,!ڤ  (¤ѤФۤϤ٤Ф٤ڤ2%8\WФ AkTG|sť^xI.5ZmPl~ltlХ{i~xWhU-RH7&6ʤF>ʤuncogmSAO"8F4??E+ɣͣx}ݣp£ޣtΣlFCu]KzΣأ} %w%٣X&٣Уa *£Pǣʣϣ4Уģ,֣̣ ߣ): 1=D=<rX3 6D<$?oi]oF'!-:2CͤeRj? x;ܣͣݣsɣܣ'٣pFDnP(P/Fhf';oD*TkȣcwU +(`=2xfioZ_I[>qˢТ!ޢ 6 'ʢŢݢ<VoDڢĢ2[ˢ.= ҢТɢ-Z9_<ݢ֢L.U0h74$(Ԣբ΢עߢТѢpy!ݢ ֢,ɢ2# բ8ߢآѢ|ʢ΢ Ǣ'}opx`Yl{Xan5)MRo͢kEPcJ* 9ro[YjbfrCOJ"^-6$]F5%@,$ҡ+ס$EYr]10'#%IĢܢ3?  ¢xˢʢТâڢonesg*^-BwJeh'N@c`* +ݡ$!Dɡj{`$Nxxġ\EhsrSšΡ}sUTQNM%$TkCܠ/S4)ՠƠؠU>'$נ ++͠Ԡˠeq;cjĠàn+M{Ȁ܀ۀʀˀ}R5Ā€Հ?QC4x'Ca߀0<Xvmf&@*{>B#_f2(ly߀RU"ˀ{,TKnĀ΀րƀƀÀ[;g?ˀ&kGY^<}RfW 9sX"9!]a@2V cr/^K  +XH3c:i` <n]q;ci3'Hh*ANl{kx} .~U, A.jiuhBMcqV, +~~g~~,~~~~~ ~z~B~}~L~:~0~!~ ~}} ~~}}~B~~b~~~Z~q~*~}}}j~k~g~~Y~~j~~}}}}i~~~~Z~"~}m}}%~x~~S~`~=~!~"~~~~m~N~-~}}}q~~~~?~l~~~Z~G~~x~o~~~~c~}}~~EF~~~G~F~~d~} ~"~]~~W~~~~~r~R~f~~`~~~I~~Yx!~}W~P~~X~E~#~}};~5~q~x~~k}v}}p~~&~"~!~~N~~~~~~t~}-}g}}}2~o~~~N~_~U~~l~~~~_~~/~}~}~~~I~~L~}}}}h}}}}~~~a~:~!~"~A~ +~z}M}z}}}X}f}}e}P}} ~} ~}!~~}~3~~~W~~ ~~x~}}H~}}X~~x~|~=~}}}~ ~p~~~~[~]~~~G~c~~8~~9~~~~~S~\~a~(~#~}}}}}}})~[~F~?~l~~$~}}%~~#~}}-~2~}}o}Z}}j~X~}~T~-~~~}}~}M}|:}}}}}}}h}|||}-}|%}8}W}}}}~~}}}}(}}w}o}}}}y}}}Z}K})}}}}}}H}[}}}}|6}*}0}c}u}'}=}r}E}U}N}t}8}F}}}}}}7}J} }|)}6}0}}}}}o}T}}}}}}}y}}}}w}}}}}}J~a~} ~3~%~}}}}}}l}}}}}}}}}}}}}C};}}6~[~~~~~}}}~#~9~L~E~:~-~$~}}}}A}Y}i}c}r}M}w}}}"~}@~J~}}~}~}}}}}}}}V}t}g}F}k}}s}}(}*}-}Z}o}}}}}U} }|}}}}R}U}7}4}*}|%}7}J}0}6}}}_}|}}}}}[}|||||||||||}%}|||||}l}^}}q}(}||^|3|<|g|||8}|l|||{|||}||?})}X}}K}}} }|||||||||e||}}|| }8}k}~}p}5}}*},}}#}}'}-}~}M}5}Y}}}} ~}}C}+}J}}|K}R}|.}}}}}})}Q}k}}#~I~}}};}|}!}}J}}~}'~}k}4}L}h}k}}}a}V}{}}}~}}}t}Q}-}q}o}[}Z}H}A}w}}}}}H}I}8}!}}]}d}P}}N}}C}|}b}=}>}||}}|||}c}}Z}}}_}}Z}}'}}$}D}t}|k|>| | |{1||R|1|d||{|)|{'|?||)||||o|||%||y|||{D|{{n|m|Y|z||{{{{D|.|{0|!|{||||||||||T|{|| |||;||||||C|X|F|&|z|X|4|{{{R|I|x||F|p|U|&|J|{||E|U|||||||||||||Y|| }||}|||}p}}|}}:}"}}m}D}^}n}}}}w}q})}}9};}J}}}~}}}y}Y}}F}s}}}}~}}}}}}}W}}~}}}}}}}}d} }l}f}}}O}|}"}}}}}Q}?}5}D}}6}} }4}7}!}?}V}n}e}/}t}>}9}*}5}p}f}||}A}.}||:}?}|}|}&}|||+}M}3}|||8}C}|||||||;}/}}|||||||||||||||||p|| }||J}}||}||||||||||k||j||}||}}||*}_}|| }|||||| +}?}$}}||,}}||e}p}^}?}#}}&}>}}s}O};}#}}H}M}}}}}}}}~~ ~-~+~ ~}}u}q}Q}f}h}}}}}}}}}}}}}}}}}}>~ ~}}4}-}}E}||}||||Q}N}||4}]}k}e}@}1}@}7} }|||||}3}3}K} }||e||||||$|K|l|T|e|N|||||||w|y|~|R|p|S|||w|.|/|M|g|||||||}||||||||R||}J}}G}5}}|||'}})}}}||(}}}$}};}||||||9}&}||4}Z}}t}C}}'}E}}||8|g|||}J}||||"|.||||||u|W||g|C|v||s||,|||||4|I||};}||||||x||[||}||}||||9}i}y}A}K}$})}8}H}|}:}})}@}U}U}d}X}~}}u}h}O}@}8}B}9}|||})}|}}|}}||||||}|||{||@}N}}||||`|R||||L|O|D|~||y||c||e|F|K|N|V|G|||F|o|]|X||||~|R||||0}5}|||||v|||||||||||||}||||||w||~|u|q|||||}||||I}}F} }}|||||[}}j}[}n}f}}v}}z|s||||6}|}}}y}B}}}:}||}W}u}X}};}Q}}}}}}\}L} }||}A}:}}/}j}\}}u}}=}O}L}s}}}z}z}}}}}}}}B}V}}}}}}}}}}}}},}g}}}}}b}}}(}/}>}8}F}j}>} }:}}%}p}h}V}#}|'}2}+}}'}/}}|})}}N}4}}l}V}I}T}L}};}p}}\}}}N}| }}}z}}\}5}z}}w}}`}?}1}}B}}}o}}e}S}9}}&}|}X}X}} }|||}}||+}}||}||||r||}|}"}|| }}|||||4}P}|}})}||||||||||||||,}Z}|||}}}||}||}|}| }'}C}1}|||||||||||} }|m|| }?}||||T||=||{|Q|;|I|B|||||||||z|~||_wvtv1vCvuuv[vvvv wvvvvuuu.vvvfvvvvvevqvbv)vvuuuvuuuvLv4vvvv;vvv(vfvLvbvvvvv'v v vuuuluuu$v5vvu-vuuuuv|vvvv{vYvGv?v$vvu9vIvv'wlw^w wvvvPwOwwvuuuIv=v4v_vjv wwvvvv wvvv~vdv]vvvvBvKvvyv7vuNuu$vNvvvvsvvv/vuuvvuut\uuuuvvvuuu_uDumutuGuEuuu0vuuxuuuu!v,v:vqv#vuvvv\v]vvv6vuuuu0vvvdv!vv*vvuuuuuuuuuuuYvvzv/vu!uptitttuyu@u5uutttttuuuu{uuu;u4uttt2u/uQuuuuuyu@u`uuXuRuXu^uuuxuau7unuuuuv'vuxuhuuvrvuuuuEutteuuuYuttt=u.unu}usutuuvuYusWsss0ttsQs:srrzsstss{ssssxs`ss;ssssstMttssssts`s1sfss7tzttttJt(tssJsGs srsssTtTtsGsBs ttsssrr}rvrrr#s.sIsCssrZrqrbrrprrrrrrrrsrrrrrrRrrqqqrr:rmrrrrrrrrwrvrrtrrrrrrrrrrsfsssbs8ss srrqqrqq2rrrrtr7r'r[rr(rqnq}qqrrsssror*rrkrrr sAsrrryrFrqqzqqyqqpqsqqqqqCr:rAr9rrqqBq@qFqvqqVqqqqqgq9qHqbqxqqq%qppq`qPqqq~qkqLqKqUqqqqqZqqpppp+qsq}qppqqqqqq;qppypppppKqq3qpqqpppxppAq0q>qWqqqNqppxp1p'p?ppUqIqqqJqcqbq`qq!r3r%r@rvrrrr +srqq^qEq2qIqq)rTrMrqqyrrrmrLr>rbrrrrrr\r.rbrrrrrrrrrrr%sNsrarUrrqqqq~qqqqq6rrqqq@rrsrrrqaqppp0qq6r8rrqsq[qPqEqMqDqqpqhqmqqqqVqqpopppJphpep#pJp}pppzp&pfptpppppvq}qppp]pppppcppo_pzp4p5pAplppq,qqq-qp{pSp_p[pDpp'ppodoZogooooppoloooooo"pFpooooooooopoo~ooooooooSo?oWooogo-oo&oQoooBppAqLq$qpppqp3p)pop"pApp +qbq|qUqJqMqqqqppppp +qqyqqqq rqqqqqqq&r,rrDrrsrDrrrer7r_rJrVrrTr&r2rqqr{rrrorrrrrsrrrrrrsrrrrrrrrrrrrrq +rIrrrrrrrrrrrrrrrsrrrs,ssrrmrrqqxqqqpqFq!qq,qppppppq7q/qqqppp-q5qppppqpqCqvqqqqqmq[qhqqqq}q?qqq#r$r=r%rSrRr'rrqr@rorrRrr>rQrbrCrRrrr]rr{rVrwrxrrrrrkrrrrrsrrrsrQrrrIrrrrr^ryrr[rqZrrrrrhr_rrrr5r~rjrOrrrtrrrrnrrKs-ssrrrr\rGrQrxrrs ssr srerrsrrrs^sus.s4sZssssFs4s]sPsGsCs%sSsVs@s\ssrrrrrrs*srr}rdrDr%r:rrrr5rr,rrqqq)r/rqrUr rqqRqppLqoq(q9q3qFqAqFq4qppqpspppppppppppppqpp qp qOqFqpppppppq qppppppppr)rrqqq +rIr4r_r rrXrrqqrZrrrrrrsrgrjrhrRrir'rGrr^rrrrrrrrrrrrrrfr]rrrrrrrrr*s(ssr+s7s=s%ss8sfsZs ssdsisrr?sVss srr{r6rEr{rsrwrrrxrrrrrr1s7srrsrrrsmGFMSawnLZO^j/'6 LAbV'<0Q^5# Q"qJ!%DQN:f<U # -. Ok=:(^7T(T#}.FHcC>.f l*H<6R{fVS[[ 0-r6Hp!ud?7) W7Iv~Q8,l/h@62jwEX9 +uT }]hma+udcsSAe`]*3}g&n kMTMk<@yK_5=Mm v`E'j#<pu0Aqs%C.\&Dl}D|>@m&KA;F\=la?t^U6~x 2[a&BfV'HN1bJ` _%reeU E  <@Op]2\]'lJvg  +fE6 +_tZySeRn6!q#rc Q + +XQ(O]/4VU.#<w~P<8bak/6+R}JNwxHG~7G6?<]bj98iD~,4!3RO '>S^Z&:e\}ppsb ^"+M )Nc7T%\`x32>mx~V";/ D6p@%4W 0\Fq^ EbVYSk*5?:G?kFxWDzknR=^X[2{R4nbS; "dZ8U R xpPp'|UJsOCZ 0VhXaD|p3$$Y$!<w?4C1hoqruBtZ#NPCh.&3!r3rr^BIzY!~H^/<Pg<Lh&6 tamYukmK#X5Ei[86>fg)|~nzP 8#u$%@+'[uAf 2 Y *.jYj:"hP1yl++nqX`ECkA uPJo-9cLS+E|zW0kb1ALl&Yc0 ~PkQWb!Eh{33e`c"49HZ/ f=8WZYoO@$$D!?9fsY] |pyQb ;xQ!mDx5\wIlpW8D+;.,2{J]E!uj{( P Npn\A'8w +PTF7+`c2PRfeH;8"AM`pj~r[ $:g  Ai1mJv#b<A,G3X{xkVxh\ Z0J>}<{vo[_4k{yp) ;]TQ#;#Z~A*w7B +{FR4 \zOy}fE<JI7(Kgfx_i+SkY{S:E_gF<|uV7XDLsVrB-7JLj/]]J,KDA_Oe~~~~'}pUH<~~~QX~~oW ~ ~}.~u~c~~Te(JĀ4abrȀ\r9u~`~2~~~Fy$~YG{& ^~}~ ~~  ~[~}~~ ~~~~~~~V~(~}} ~ ~~U~W)~v~~m~~51X}I_J>QO~ iy~#~z~~}}"}}}}}}~ ~~ K~]~}}>~ ~~}}/~E~v~ESTbj/W4~g~_~~~p~7~~}}}}}c~a^^S~1~'~~~~@'~~7+~~~~~m~`~~}}~~wWSz'~V +B/H&MPR +~04D~/y 0~3~~j~{~S~~~.d~~~~~~~~~~~~~~b~}}}}}}}g~i~)~E~~~~~k~~~~w~~G~8~~~~$~ ~<~~}>}||||b|{{;{e{ ||{{{!|1| ||=||||n|{{{}{S{{{|'|m|U|G|||G|Y|~|||}}}|[{<{zz{|,|{{{{{{{|||||p|A|g||~|||T|e|||A|{{B{4{zyzz{i||||;{{{>|Q|$|>|E|||}~7Iw~~}8}F}|}k}=}}w}0~~~~P;~~}o~O~.~{~5~G~~~~}Y}x}}}}~~)~~W~~~s~~mD~ ~:~~}}$~Z~l~u~~~f~G~\~`~~~~/~~F~~~~~z~u~~~~~s~~}w~~~~~~~k~~1~~~p~~~:~}}}X}}2}||||{{|z|}}~f^3~~~~~~ ~~~~~~~8~~j~~~q~z~~~}}}N~g~"~}}=}|||}k}H}i}K}}F~~ ~ +~@~p~A~}}}~q~o~L~-~S~~~u~~~~~~IP? 4~~~ ~~~~~~~~~~~~ ~:Y~}3}3}}}~s~e~Q~;~}||%}}3~~~~wL~bV?I^~~~~}7}|9}E}}}}}R~~5~~~Q~}6}}n}}}}}}}}}5~~~~~g~u~X~~r~RJ~~~~~~[1~~~~~~%~~}}d}|p||||}B}>}}/~ ~d}||:}}~l~;~}}m}%}$}E}}}}}}}}d}}y}5}|||}||D}|r|Q||{G{J{T{z!{!{{{{{;{zzz=zz +zz{z{{zz{R{z{{{{{{/|A|O|O||||{<|||||v|G|{i{z {;|n|x||||{{{<|t||=}}}P}j}}}a}|||o|k|d||0}>}}||H|x|6|q|%|{{z{N{zA{{o{zzzz;{{zz)z zzyyyoyyy"zy2zbz'zpzkzyyyyxy`yyyyyyyTyxxxaxww'wvvv]wpwwwwwsw wvvvvvvwwwvwwyww +xSxxLxwXvvuQuuv#vuuvuuvovivvvOww{w wv{vfv9vHvNv\vRvvuvvvvvw8wvvv!vuuv3vvjvvwvMvuuvuvufuuvv wGwwrwlwwwvvvvww!wwxMxxTyDyyyGyEy`y!yyx yYyy$zJzzKzy{yyzyyx!yyzzg{{|-|T|`||||S|w||}}|||v||}||||||u}\}|||7}}F~.~G~0~}}]}} }|O|t|t|||6}c}}}}}|H}L}|| |{A{{zTz/zdzrzz({,{U{b{<{z{{{{4{G{z{F{&{{{y{6{zzzzXzz+{z3{{{{{{{{@{{|{{%|T|k|d|||}|| }|||p|||c|^|b| |F|{D{>{{{R{{|{{{{r{K{g{n{{|{{|{{{{{p{{|{z{S{V{{|p|A|,||{{{{t{g{{|{^|||||1|l|||~|d|{{9|}| |{{{|X||*}<}}K}}a}}}~}}}}w}b}l}}7}}~b~~~~~~~~~~~~e~~e~r~~~~~~a~~c~~~~~D~n~~B~i~.~9~~~~~~~8~A~}}}},~~~M~}}|| }I|)||m|E|y|Q|{{!{zEzzz*{zz{.{&{zzzvzyyyJyysy1y!yxxxxxxy{ycy;yyyoxxx y"yxxjxxCx-xxwwuwwwwzwWwwvvvv]vuuu6vv5wcwawwwxwwwyxxwwwwwAx3xwwwwww\xJx7xnxxxLyyzyyypzZzFzezHz5z}}[}k}}|||I}k}}}~&`{RkN8~~~~ ~H~}}}}~&~}(~9~}}C~~i~S~r~g~}y}}}}|}7}} }}}i}||N|{{|`|*|{{{{|M||{|||;||'|{{{|{{ ||{{{{{{{{n{{D{[{B{{{zzzhzy3yxxyyxy3yxyxxwwxx;yy*zz[z$zy +z@zzyyy]yyzydy%ygyyzyeyyyqz{zz{z2{{{|K} }||||k}}A}}}}}V~~}}}}}}F~i~~~~~~~~~~X~ +~~~~~~W~O~~!~~~}}~~>~ ~5~J~~d~s~{~W~t~f~p~1~ ~}}U~W~H~~~~~9~4~#;;::w:::@::::x:f::]:B:K:?:::b:::::::]:@:P:[:g::::;:Z:::: ; ;:!;;;E;E;U;F;;:n:::::;::;;;;;v;;;:::::::::::7;@;;+;5;$;>;;E;4; ;9;0; ;::;:;$;I;?;!;;W;;>;;u;{;;i;8;;::=;';:::{:::5;f;:;8;Z; ;::9:N:G:N:.:9:H:9999999::M:F:%::999q9h9X9,9J99999999999u999:::h:T:99:":J:::::l::::9::9999}9g9,9959-99919)988r999999H99g9}9.9999899Z999`9B9?919c9999I998889K95988899E9I999999 :E:9i9_99 +:&:F:+:v:i:&:9:::r:9999999 +:9b9S99::999:,:H:r:+:99S::::::::\:?:U:99t9:9m99z9999999"::9!: :99999f999I9 +9.9Z9-988 988889[9M9@9888c88888888888888888c88k8;8U88u8888888t8k8|8d8s88^88e8+87777777e77A7 76666677~7X7B7_777777s717F787@777787g77777_7W7^7787j7S7r797<7777p7Y77777777(888s8A8q888q8888888[8O888&8W888`9W9`99b8X8898894999999 :):99988888:9L9919U998888K9888m8}8`8e8b888888r8388>8 88888N88888818@8l88998888`888687777777o727<7j7887777777777 +8787X777{7E7l7q7u7v77777C7H777777777m7777V7666666W66677'7 7707$7Y77777 87Z776777j7i7[77.7w77777+8S88#8Z8S8%878"8W8@87777777778;8I8O8T8{888888859#99*9>99:949998 +989X93998f9z9%9#98888888888t8x888888o8d8898m8[8\8_88:8J8?8Z8;8/8U88 8885848 +8N8'8 8848U88<88q8,8)818 88877i7-7 776W6#6<6I6h66666676S6 655555555555j555555t5E555555!555555565Z5R5P5`5K5t5.55+5;5P5754445*5555#6&665 6646p6666<6L66E66667c7_797q7777}77t7A7T7-7*7E7m7D776677766|6l667#76!7U777g777k7U797;766666667E717666<777d7777777X7m7g7g777e77R7n77N77w7<776"7$7q7777M78777;7!7<767.776;7p7x7h7W7g7S77666U6g6a65606f6865555v5=5444554444J44a444r4@4v44m4j4334S4;44!4 44333333^322232e2?2>2O22x111111112^2211)2J2P2w22322P2A221222d2N2`22222353W3}3s3U3#3 332222222F3o3w33333333*33q33333333r334'4B444?474444444444434O4j4\4|4k4E4h445N555555H54465566=666*6 6 66P6 656p66g6|666666666G7?7766}66666666A6?66b6 666D655566686L6L66 6T6s6!65 6 656-6655566555555Y55 5"5J5Q5k5f5z5P5J505'5444444444444q44v4b44:44_4^4$424444{4d4s4d4{44J5E5445P5w555555 6 666!6D66667(776667A7i7\797:76666(76667D76669777k766666667666|66=6:6_6M6%6L6L6X6y66666 +67666r666G6H66B65 616Z65536K665+656'6P6 66!66556y6=666|6l66Z6"6R666`6h6v6666i66666a6a6P6 6c66666667667.77876<7777737%7277777*76666l6e665555~5}55s5>5'5!5555555R5E5M5%5I5q554v4444m4]4p4k44&5544a4h444544w44444{494t4u4433333333{3?33333J3_333 4E4,4333333%4;4A44344l4K44q4u4r4.4R4\44444,545U5S5^555555555Y535z555555 6$666#6616 6555555616655'6F665H6`6[665*665-666t6X666b665*6D6h6Y6R6-616r66H666}66`666&6A6H6K65'6c6k62655655 6W66R66[6666(766l6666^6~6f6!66&6606C66655N5R5F5~55U5b5J5h5]5P5=5544o4r4Z4M4'4)44;4\44s433343332433333333z333333333333333r33h3s33333433333333_3M3u33333^3h333Q3e3u333o3283i3f3k33f4 4333333.4I4@4434#4)4<4444444444485k5555555555F616I6866g666d6W6X666J6I66666666c6H6\6676677676&77w7^777777777^7.7P7Q7C7P7s7n7A7s77e7F777|7Y7L7777776666v6G6>6!665A6L66555555]5"5D5154=5?565$54#55J5b5;5(5g5O5I515M5h5n5H55R5y5z5555^5V5N5J575*55544F5I54454454*5B5X5C5$544444444554#5544444445$5Y54444F444M5z555n5f5n5=55N5n5i5x55555555556E656U6P6666H6R6"6E6J686 6p666666666g6j6q6j6T6v66616P6i66q6%6696655 66L665526n66E6666Z666666 ŖҖ" %ɖ +'ÖȖ–זŖՖЖȖޖnYʖۖ}oŖ֖ۖCxH]VU$!"69W'U3K1iOA_ԗ{bsX2—v}BE4t2ߖ8UXO&Cx^ږiі* Ԗ̖ΖݖۖƖזw֖ܖ`Ֆǖ͖ (Ֆі!іɖ6va"tW)F~mPx9&1*@Kb;@ A! p{[BETWdіUl͖ȖԖ%G7A&"V(Ӗ +IdG)іEXGStGyr +ߖȖޖזsWdz}|h^=(%J]* ڕP@_ԕ<Uo9vx,ŔՔ" D'*|s,6UjȔ9/  Ĕc~AHՓ̓ݓ .mPBٔȔsOxߔ ǔڔEiQϔߔ-Ro3z#ޔ=Sak}mv˕xĕO]ޕٕ![\• "ҕZ4Õ֕ߕ•ҕЕ˕fOS}t}Õ֕nf*yՕx23fTi(Ԕ”ݔє6AMٔT4QȔÔsn66R*= EpXғΓKu`r9+>~D~ANP5k"(& R_Д$Ҕ+(k4]$Ӕ<J7a`zflxvܕҕ&ٕÕ (1Ǖ}^,)Om5GmaOLX}c7^dz8)A@ ˔֔yu˔Ŕ G0_}]%”~e[H4h֔wɓJГٓ< +œ=tQcxÓQes“ߓga*Uvt%:ݒ-@;Tu2C feBg}WdSEGݓ֓z +1]V}22*ȓߓΓٓ ͓ߓؓܓē_ГϓǓÓœɓœړ.I ߓ˓ !“̓ӓvrkؓؓȓy8~W,Ԓ-~8Z\’ǒvb +ED}E ّ.0ԑ~ݑБ,ؐUhƑȑ̑ؑ7֑~ԑؑ`*בёΑFe%?88(בƑۑ,/ʑđnFǒT>N~z^A5Irߒ [;ZF]A ޒ(1ܒْݒђÒђגu^@tcz_gZacW{;Faxc?^^s}v9-D4P3,JݑǑԑڑϑÑ!9ǑӑۑڑX̑HwK~pD<P@3szؑvIȑȑ!ّؑڑ4BMLsS^gƒϒ˒Ւʒ +[Y[Zܒ:756>B),^;0vВܒ0F]RB&uڒגӒbU7 +C֒\ْo&n}PG5A*!"ɑ1)!Ne?0e<DG'MfB**0+#:\2h/#FCFT\H <460bZ,d//#Mz=2+yڑ4͑Ñ\z=ߑґu1 _5 +‘ʑpgN}Б +%Bn,dw͑ב%ȑ=' &QEnjrkڑpA +%Y<$>B_Yh16 wXlEԑIvȑˑzё͑&ȑe@dA]g|‘ӑڑʑӑߑe=w‘ؑ, +c0o=L2+*C'7<ΐ9tK ސՐ$%&̐@ېڐא5Đ(L(&ؐА)BL ǐ"7|~!ƐАf^(9- 7>Z,$kSe1EthnMs^jߑґёwH5Α̑svÑőˑȑݑۑ%sQ ȑՑ 7 ܑܑߑ6hYRp{LM{JqdO4_U* א#^B1[>Đ7 <5ҐI\(#NAV`9b`=ؐ3/ !ސ&UY!:%]":*,I>ڐ ֐ƐKD$P+Ufa@d<#g4yK(EhZaad(1Dސ(lhVBX->e@Ski`9w7#"Ґ &C ZBKiW*YW^WmvJ= +Do 1)A6gdBLihxD,V3Nh8Md:/E +mNf3)IjSZj!;<8G< G ^7]k/B;u=1 MO~* $6 /"&T;   +zvt}*`70=)9r~4 "LI 1 J=gONM+awf/~j|nra_'3q@@gaq_f]G:J|ujyhn9VAwE71(6y.Gug+/ >8GZ"hvc> - 8b(+O5M4Y^slH+ +7HL#/8LyK" + znB.$ + + grfOv#`_ZT~~M5D[@C!7n|2lPXT%.+MvoCK>?))-Uvp\s%%(P]ndM0&R,7U36N@J&5`Nn7!@PcNV]+ +T?FZ=5 +u_"<~vS#!!'E|;cJSz],:8&JEN)kg)xdz)E&YjhvZZQ9q2n,Zz~chn|s48 ~*JF@dL  nJCK8#-9&XyI +%ekL4oc %ISo$7 q.;p&,(pr{jf (=@bWmcx~RY]d Y}<R><D. +< b# j] |W8H9K;THMr {lHGL<wL -i06r5Ogqo;m&cSs\.&C~ GA\\hQ 4CV+5|j8# $8; 2MHu_MhWDbHv1,[w<1D jmocdnLiKP00M^xSnu oUZ]2~?ae%* R52ya` AmPY   8g|JJD7 &/hVzr]W>O=6]1R()Z20T52+6~Kdx3/S_lah)!T;UlsH9FB+frh{p@|$L} pn[Gmq]ZVZ<RR\LDpS)*I|KfY`m`NdqwIpuhb_<9Kx(M*eScf}{!; N@=9#6^,( ! + 8  +r}]vs%-+ + )*#m0Z E + 6{-   8d. ^yS6FEkT (&: ! 7 ->+Pa5D9>6$HY"[g^KuX~q + C44-t34 P5R]7bc&}.Grz`O+dfZ3!E$v|;bMC5:_"2z;IB&>Zu# +jG)9i6& V6( VH (;P, *BaeM{tN>9 "Ee +VJym"-ou0?a^ |Zw@"a2zg> 0 {BZFnqAPR $bko2lsmwM_{t?PyF<bTL,"mF%CH8H|uas+] +/k ] M#X*@_ +!2#XvVfPxdi@iSblTK=[^[1C,=6axHE_9}6Q5qR;v{<fNG]%" >V +-g K,vwlt6?(37e].Z`2F[QKKR4 +1{vZ.][i~ & +Ki[|~_J; RMNs.fK +hZ{bjIc:"}xS\:`O3 +wk``;M &+&/~ &&>jU\U |pc +QXE*_5JB-f=\;|`SSsMERfKil, 8/*{h 9t}9}V% wj"t`p|%|6_ly1 +<rNUfT\ +L|1[ `e-tJb ?TX.Vs +mh+Y[\8)WB(DqvgI#n 7b+k^H~vNhL\&;uuuY":=1N +  +!6G9KwX~7Jpgb:Lr;H\(['!D::]q80[L@6$C f3 +U*#ug8NSwUa~~^;4Vs| pZrIoSaa6$7  ' LJEto^V <M-8a'?;[0GS 8uXs96yIM&N !7% +%]%ac{x$kL; +qwEB=Zox~]Yg9,9 Pv/6? )FNTL[][&Tos@XvnW{^{D1S& ##S6@l*\dJ5DNvsN(xYPs#.*1s:)c1n{_v]Tl~n@=wAqa`]y]o[Qu=C;d|`pqgxl8u[N! = 3vD"Wyvr@J{(F[ZCz0&Kjp~kG1 R:    "     9D`~EJl    ,Qr\QA/=K|Q% ^^Wtc&  ,   e O     B!    .JYB@am>&    S   Qx~#     ~    o         t        y i 4 o V ,    R U        z    _ V    3     p  ?      m     L L E   g B 7 L B     O - =           $  ! p     c    }                      <YM +I +   :         (     w 8 U    R i C   j #     h g  ! !  w  )    @ :       A          '        ( <           r         j  u O _ T G h j < !    l   f h ,  J   @ 0  5  8   + + + + + + +o + + 6 f  + + + + + + + z \  4 B  +   3  + + + + +8  + i       [ o    B     B j .    M    +  V      z    (        ! M  c     % L  +  c T            J - P k  v  s m   {              U o  G  _       %  2  A   + g                q *  i  % u 5 {  9   N   + + + 5   + +W + +l + $ +6 +    " +N + +  + + +W + + + +& +  + + +  +@     j 0 }     4 M X   l     l     l ?    ) k   v     -XM+ +,^nH`@aU  "\n^(   AzsN?  =4->}gIjmW>    e   F o   f                1    +  Y 8 E     z .  + +* S D ' 6 =  + +     { K  + + + +q + +1 U  g D   & }     5     f   i ] J 2 '   3 8        q ~  5 X N  # m   W t 1     + `             #   M   +  t ` {       '  8 a     Q A  X ( .   @   u i  &   M             ? U _ W    W     8     N ^ 1  +E  ,  + + + + +z +1 +J +g +E +1 +   d \ L  v @WA<>}t]<S  C      Y  X g X Z v  +a + = +u +K +5 + + +f + +w +J +  V + + +< +G +6 +p + +  +   + + + + + + + + + + c 2  + +* c 6  ~   +I l     } f   +u   a _      ;  9     l V U   & r L / L     P x     |     Q . 6  + a  + + + + + + + + + + +O +m +q +f + +G + +C +  4 +) + +a +n +s +9 +   + = + +      +  # +  [    j / +  -9<4=X  ?. '%  B + J Y  > +   +D + +U + + + + + M  +     5 h b   x b           " 0  I        7 b !         (    k   V P + ] u  & a    a = C    T         , 4  G  ( (  % 5 X T  5 J  . L  )            +    5 y    _ 4 p T %  r  O ?   n  a  E (  % I }   h  # , !  ( E i    }  J  =   + U [ i y y 5  - > n J    +  + ^ 8  + + + + + + + + + + + + +u + +c +_ +i + + +  + + +` +Z +J +W + +] +h +G +$ + +    ~ q `  ^  `   +  N N   @ _ P   u 6 l $ ! 9 _ Y o   u O  + @       H + + + +z +Y + + + + + + + + + + + + + + +  + + + +S    + + +Z +M + +{ +r +v +w + + + + + +  + + + + + +d + + +   + + + + + + + ?  + + +  + + + + + ? l A 0 { S  v  +9 | g  + +'   + + + + + 9 G O T N (  + + +a +' +{ + +g + + + +_ +  + +g +G ++ +J +    + +s + +4 +1 +: +) +5 +O + +! +   + +y +A +8 +k + + +@ +       + +      S ] , _ R ' V J 8 d . > %  " 0 C T W ! $ ! @   ` Y [ 9 D   (  b u    s B   ~ =  V i =  + ! 9 % I b  u u e   D    b    % +     + +    I +^ + +Q + + +u +~ + +8 + +   + + + +Q +Z +B + + +T +U +e +[ +A +  + + ' + + + +} +I + + + +, + + + + + + +  +  +~    ] z  }   +F > # ~   y p   [ |            +4  J ( R   +  +l  h ?  + + + + + + + +l +g + + + + +| +q +v +K + + + +g + +( +        + ++ + +  - + +          ]    =     + ] Y   ' ?      l             U L  H ;   + A +R +- + +  + +9 +   +! + +   +C +  ; +6 +J +> +   2 +   ) +7 +        + +8 + +3 +f +] +. + + +    L +q +  o + +( + +c +- +v +j +[ + +0 +F +> +& +  +' +$ +x +s +q +m + +2 +e +k +o +y +H%&:o ]URg.)aB8pBC6CYYEYUPmt %7#%3Dgd~t/9<  +6#0R0ZJ@xL@Z7U}2--d8;G0WNL6 mqQoTTn]'eM1 )=]4&sxQUAB(Afk%40@j~$@/6<S8*IcMM>bPgq@,:QD/Im!H[61 G}3 9`eCU[\?Dve_9VIx}GXx#:B%{`MeK8x3-MGKK8150  C +iBxGJ>$<`=I+K^DpQMGNku=:IL^dh@%/ X9Mta(^'5H/DE'7&%[N<2T3-V/+oVVh``OBHF{J(R}yvW][AW#2Qj~$)i}swtb7  <R7[u\eJj=\OCarCApa# +b="` +D)7L#fvmq| Kro8j_Md^68}"h\J4LS@43=v.' ErAkqlwlgflR| -Fo_U'($&4;g`""FQ{; +2#:&U^"68; ~gHVuQ  +?o7N$6*A$O5>myjO%d\zec.F2YTVheWgZ,xZfSlI:Gm~<@knvtvoM.v~E;Dga?%}{>iQW <90=pU.#O |~^oonvIqVQ?>u~|+;1ZmlC#OtMCis{9B{qYwd E_X\W=}V:--(H/zFeY#(!!S91zj,d*{gn~uoR?h(Ff&&'$ny^ObkbPpoAcrPivV&!>~hzlI/ ihT`R1 ')gwzaZi6~0v8#2}hi(.,P qsqnN3dk{kmG|\m-'f6xsy . =+8)`.3-:i]{R9=O[zB.2G+:3 N)5iPmvi}0' fhSHn}I@h47/}|/;]rA[Lzp{6:W`2=C* 8Q( ,_ FU/=?JK%;^]Q6A :b7:AcwOtt{ P(&8 3h}j` ]Y7v}bvq]NcbY:8 A\L5C}iiijjiiiiiiiii"ikiiiiiiiiiijilii4iDiiiiiii}iiiiibi.ioiSiliiWikiiGihh6ivi7iCiPiiFihhhh iihhhh!iFiLii ihhhhhhhhhOhhhhhhhhhhhhyhhhhhhh8ihh|hhhyhhVhhhhhhhhhhhhhhhhhiihhhhhhhhh3ihhhiBi^iXiNiSiRi$iiYi^iihhhihhiNi\ihh9iFiWi/i1i9i=i6iJi5iiihh1iiRi;ii iDiMiyiigi?iiii*ihXiiiIi)i.i&iiiiziaiaiiiiVihii$jiijj jiiiihiRixii)iiYiiLi{iYiiiWiLi +ihhiBihhhhhshhhhhhhhhh9hg^hKh>h6h?hshKhggffhgxggxgHgpgGgjg^gZggggggggggAg8gdgggg_gggLgpgHg`g/ggJg)g[gggggggggygyggwgTgggg5hhgggggggggggggggggGgg8ggggggEgfffgfffffffg gffffffffsff;gffffQffeBfmfxfmfVf0fXffEfffXfGfGf2feeeff\ffPfffIfffgffffg.ggHgBg%g(g%ggggfgfgRggfg gffffg&g$g8gBgXg7gSgSgg(gg g@gBgHgXg%gRgggkgKg>g1g*g g4ggQggg&gffGgTg8g$g7ggf?gegQgggBggfffgffff gggfffffffffffbfff\fffwf_f)fFfcf feeeef f +ff feeeeeeeeeeeeeeeeeeegeeexeeezeeffeeeeffeeeeeeeeeeeee}eeeeeffeGe{eereexeeee>eFe!e:eedBe]e{eeeyeeeffeeReeeeKee'ePeePe)e.ed#eceZe eVe,eddeede4eXeDejeFe-edeexeeeeyee$fPfmf]ffeeeefOffeffjf6fffffffWftffffgff>g:gfffffffffffffff gffffgffgggfffffggfffffJf@f fe4f5fee +ff-f>ff#fGfeeeeeeee!f feeeeeeeeeeleZeQeue]e_eVeeeeVezeeeieedejeAe$ere%edeedcccTcWccQc^cc@ccScAcZc#c%cyc7cbbb!cb{bbbbbHcGccbbbbc7ccbbbbbbcbbcLc cbbbbbbbb'bbbbxb4b9bb^bWbbb cbbubQb`bbbob^b*b+bSbbbWbrbbbgbcbZbb9bBbbbeblbub\bb\bbQbpbKbPb\b=bJbbabbbaaaaaaaaaaaabaaaaa]aaaaaa4b?b)baaaaaaaNbsb7b baabbb~btbbGb>bbMbbmba bNbbbob5b`bbbbbVbRbbbbLbbbTbEbebbcbmbDb\bbbSbab)bbb babbaaaabKb-babbaaaKbMb bNb@bb-bVbNbaab babbbb +blbbQbbbb.b-bbubbb*baaab bb baGbbaaaaaa"babbaa!b&baaaaab;baaaaaaaaaaaaaaaaaaaaaaaaataaaaab:baaaataaazaaaaataQaaa~a{aa3a~aaXaaaaaabb(baaaVa4aalaapa8a``,aBaEaa#a.a[aTaJa_a/aCaLaBaMaLa`a +L + + + +h + + +R +% + + +' + + + +l +A + + + +' +J +; +Q +: + + + + + +o + + + + + +t + +% +z + +3 + + + + + +& + + + + + + + + +] +A + + + + +& + + + + + +l +v + +y + + +c +* +( +9 +t +E +r +w +G + + +i + + +m +q +n + + + +& + + + + + + + + + +; + + +g + +x +5 +& +P + + + + +4 + + +( + + + + + + + + + +O + + +P +@ + + +_ + +y +b +# + + + + +^ + + + + + + + + + +U +D + + + +/ +H + +Z +x +m +~ + + + +S +v +m + + + + + + + + + + +_ +y +6 + +S +j + + +K +j + + + + + + + + + + + +4 + +e + + +C + + + +r +G + + + + + +D + +) +e + + + + + + + + + + + +J + + + +3 +( + + + +$ + + +C +/ + + + + + + + +C + +h + +k + +7 +C + + + + + + + + +h + + +M +/ + + + + + + +z + + +7 +a +& +! + + + + + +& +< + + +< +t + + + + +S +A +J +O + + + + + + +z +C + + + +M + +u + +z +t + + + + + + + + + + + + + +0 + + +B + + +F + + +{ + + + ++ +- +1 + + + + +T +D +b + + + + +s + + +M +~ + + + + + + +' +F + + + + + +a + + +2 +t + +| +~ + +K +L + + + + + +x + +i +2 + + + + + +{ +L + + + + + + + + + + +{ +~ + + + +k +{ +B + + +q + +f + + + + + + + + + + + + +N + + + +a + + + +e + + +v +W +> +K +7 +6 +; +F + + + + + + + + + + + + + +r + + + + + + +l +2 +H +d +v + + +~ + + + +f + + + + + +j +. + + +I +M +^ + + + +n +p + +p +m + + + +t + + + +Y + +K +1 + + + + + +c + + + + +N +w + + +h + + + + +o + + +\ +_ + +< +! +L +d + + +Q +B + +3 +k + +x + +V +K +I +Q +F +[ + + + + + + + + +n + + + + + + + + +K +. + +p +5 +` +C +H +^ + +M + + + + +a + + + + + + +@ +3 +g + + + + + + + + + + + + + +X + + + +z + + + + +k +z + +b + + + + + + +e +U +E +) + +E +h +) +4 + + + + +w +5 +` + +i +B +U +K +o + + + + +p + + +0 + + + + + + +> +J + + + + + + + +l +P +z +O +1 + +$ + + + +) + + + +) + + + +o += +n + + + + +^ +* + +U +* + + +o + + + + +9 + ++ + + + + + +? +% + + + + + + + +' + +; +@ + + + + + + + + + + + +. +V + +k +% +3 ++ + + + + +B +r +h +/ +b +g +p + + + + + + + + + + + + + + +i + + + + +O +S + +} + + +{ + + + + + +j +f +n + + +w + += + + +8 +F +D +O +c +j +D +G + + + +j +d +k + +c += + +a +U + + +` +# + +L +| + + + + +e +Q +M + +n +; + + +W +6 + + + + +% + + +D + + +b + +R +E +F +G +E + + + + + + + + + + + + + +c +' +" +g + +. + +A +^ + + + + + + + +P + + + +~ + + + + + +4 +` +? +0 +c +R +] +y + +} +g + +^ +V +P +U + + +O +> + + + + + + +\ + + + + +i + + +& + +5 +O + + + + + + + + + + +a +p + + +z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +M +n +X +E + + + + + + + + + +< +X +h +@ + + + + + + +& + + +w + +] + + + + +! + +~ + + + + + +$ + +^ +e + + + + + + + + + + + + + + + + + + +j +T +[ +{ + + + + + + +C +# + + + + + + + + +t +S +w + + +V +c + + + + + +I + + + + + + + + + +g + + + + + + +% + + +P +1 + +< +J + + + + + + +H +R + +v + + + + +~ + +b +f + + +F + + +< + + + +. +A +O + +0 +L + +l + + + +# + + +M +V +u +* + + + +j + + + +Z +j +~ + +Q + + + + +0 + + + + +t + + + +h + +{ + +c + + + + + + + + + + + + + + +g + +7 + + + + + +8 + + +/ + + + + + + +{ +~ + +L +G +W +h + + +? + +7 +P +G +4 ++ +2 + + + + + + + + + + +3 +K + + + + + + + + + + +; +E + +' + + + + + +1 +9 +A + + + + + + + + + + + + +j +w +p +K +c + +^ + + +} +j +{ + +w +B +c +B +j +} +j + += + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +- +a + + + + + + + +! +K + + + + + + + + + + + + + + + +( +B +\ +& +I +W +2 +! +_ + +g + +{ +a + +/ + + + + +' +m +j + + + + + + + + + + + + + + + + + + + + + + +k +h + +~ + + + + + +X +W + + + +? + + + +0 +N +i + + + + + + +1 +@ +x + +) +o +j + + + + +( + + + + + + +D + +9 + + +< +f + + + + + + + + + + + + + + + + + + +F + + + + + + + + +] +V + + + +B +q +5 +9 +< + + + + + + + +T + +> +3 +Y + + + + + +2 +x +C + + +9 +, + + + +| + + + + + + + +} + + + +v + + +e + + +O + + + + + + + +j + + + + + + +- + + + + + + + + + + +k +| +x +: +h + + + + + + + + += + + + + + + + + + + + + + + + + + +- +. +Z + +K + +> +l +M + +- +f +x + + + + + + +Z + +c + +9 +( + + + + + + + +6 + + + + + + +vCwJwwxw]xwyyzz{{zywv-vv4ww'v5s%pn,nPn{oqsugwx xxy+z&zyx3xwusOqmZkiSijllmmcnnpop#rssttusv\vGvCvv7x{}L~}|{:{%{/z^yRy3yZx1wdvutsrxqppo^l4iohhghdijHlm o)p(qqErrsv{xyy*yvxgxLx-xFxw6vttu0vt0sdq!pp+p&pApPpooCpLqqq&qoopqLr)ss8tu-vv-wwxycyz1|$}z}E}|+|@||{yx.x wutuuuLuuuvv]vv#vJvx2yJyy?x$wvvvvwx+x +xwvv1uttrqrtvw*x>wtqn{mPmmModqrsdskrqqoMnnyprqrtWwy9{|}6~wр́b_?~|z]zz{g|L{ywWwwwwxy[zz{{Q{OzyWxxwIvvcvvewxy{}~:~:}{|zvqConnmll&mnLpqsu]xyzl{|L}}-G7ҁ)EQT  ~~~~L~O}={gyx yz|w}~#~}R|Kz7xvAv%vov,vgvvQwxxxxxyzyywrvvv#xy{|}x~.~I~~}m~~7[>qkx~|yVwvwSxxvdvdwFyz|~ƀPu/chm=lƅqd)~TL=ߌЌ4ɈI"Qӄi1҈MVˉNfe(eIۊ[a~4Oы(e,[C@Flׇ߆^z:DŽmւ4r̃ȃ߁#̃6o[؆}{zX{|~.~}|{{m|W}~7ÄÅތoNC\)"$t\AŊxŒSXB-ńÄ?)- 3v@R; !W݋GwEƄ&6;~~ md>8ՊӊXه)_e}ކu\ȃ^AZpLƅFHFs~}}p~~4~}~#~~P|bywmvutUuvxiz|}~~w~h}W| {Fzy^xxyx yyyxy8xw]yzy{{zz|}+4z)~H}{{W{|||H}~~0ofρ$~}{yFvsrqqVpoAppBqCqVpn9lkRjh:ghikortwez|~:q`pـ~}q}~U~6}v||||}z~~v~|~~~~~M~|{Lzlywuttu3vvHvtsqqrsst*sponmlkkl5l kklm^noqtvvw=yA{C}+~}|{%{z={>|s|C{ywv$v1uttusvwyzzzEzyyz~yxfwSvutBtwtXtsssGsrrrrqppomCmmpnnm(ml|kj +jgee ghhijlmn:ppqyrstts"srurr ssBs^srr~sFtt5uYtrhrssxtuw'yyyyyxxwusq6qqqqqqq*qVpo]p{qrssUtttttttsrrrr!sstuut:sdqonlrkllrlRljg(feefQhj +n ppypo oWnnn|noSpppqpppppqrrr2rqpuoQoopqJrrrdqppptsrs(s'sr-qHomllm/ohpp\p(pJppq.qqLpnlk,kj[j ji!jRjjjj@kkkdkBkjjkj-jGjjjvkkwl'lkjiiiiei$ihhhhih(h9fb^W\~ZYg[]N`>bcegijkm9nqoqpaqfrrs]tuwvvwvvvCvvXvvussrrrwr6rqqp$qqrks\sHs7t"uu=vpvu^uutRtosr^r[#S*p-P8pm$8]59`9y=D4Mn7 {n&/d _4!))?J6Z{r x7*`=  5|uM#z'F{NM{Nhoo`.4G|{^#+{}jZ(i(L~# edxi=AWdN o,lG:vBE>,6AR[r<caa-)L0)s$l%p*|0Y)$ +2.`7l:0) ?QYic^u|FM'\8 }O{":#s,fWsvA%R BaU0VT1`@JmD).$~ \xIH|F (X[L^e18@Qo2 t(Q[( `;wX^+ S7vWT(<wj7hPtOhRn ;mrC^Osn/s]yIC"!p$8CRzJ98 5$e3&I,Vfq-CjIh$^l `5,,g_!=ncKY>v\95 lX;< w%Nl[6a(d5\TV&uR KX"6ze45FGg> +t%VQ(:vLdK?upbq2-lsn^1e??:k UeQQ(?J1#_}YQ<=99LbY|#-&`>SI"EYh Vo6 ff^8yEVm8jQX{i$E-{+x\Gn7i\0qo:?XM`Goq.BqjoB#We"= +yU~/C1hNq9(d>ac,#_8nCRtw}X`zE+<BtBW# +=4v_9cJ>O[&yeS 2HSvoD]}Pa>n+ ZH0\~Dam%.]a =/L(n]{]hWV7`sQ L Wy^V[i/'WP3  pp Ukts,G]OMZdX0&SMYt4Gb<1YqC l^NVYRYq j.$U9]QQO7d>޾'{~ٹg޺3NvunsBJ3}2jA3vV0}\k^!tWv=XB(v'{r]-A3I-mW^y >WK?Y&u<o , +Eb?L}\fsR<CkrpI=|X&"RSZU*}#<@[_2c#P7yrsdܽ^@3"jj }7n a;[fRc4<" UksҿSFcxa(-Z!rC?.H<<{|quKv_C 2JPBzp0!C߾c8H_;wdm*_ɾD>̾%"$Vv!B,Dyu4M7b[E<Q^<jc|R d}|{{{|}#DK"'%Y{~"~ ~~j~"Ee:4o(f0~~}|{\||}I}}}G}|{|{B|s}}.}l}\~6QYoЄk^υp/d~}|{z>y'xwwx~xxxxxxypz{}}~_~9~}}<~~X4em~T~~}|-|j|}| }W}|5}R}+}|ywvv`wfxys{{}/~-eY~<~H~j;,@Pʁ~}8}|#}~KiȄtр1~{}yxgxw#wwyX{'|P}~~ +~@~w~l~}~ +i8~|zxvuOuuuvwzyJ{|}~Rց7݀ۀ8aՀ%~|){x}vtFttvwxyy yxxvuuRvDvvOvvwx1zl{{{h|{({zyXyy-zP{U|}z`ȁˁρb -q\oT~~.~3~}s}J~~~~  $~}}c}||;|{z/zy~zc{{{yw9wvvwy%z{o||F| |{{{%|4}g~f-p~7уr&Ձ@Y)}x}%~%~>~}|C}o}@}D}C|0||G}}G~}I}|{zzzzzzRzy +zzzzyxxxxx.yyy7zz^{R|}C}|u{y9x w@v +vFvwxz\|G}}~s~[}j}>ŀԀ~I~}|{{|}c~T~|Izw"ur=rrsttHttuwbyy=zzr|n4KF$}|{j{t|}~t~|~~` +ׁ d+J!Z\:ہM +h"y\^~?ʅKqV:38o+f qY]Nր_łقӃB>߅݄7΂-N.=@Շ 2gtb0ޅ  ݈5ʈ]z†&2ňV|cp-wR˂Wփ܃ƃ+)"Ӄy5Ć؆ ܉IF$X݇5s֊9)4ψ^922<Ò֑=Kg/Kגݒeb#ŐŐ1$ef[c ˒w8UrƓܑOH;|S*=̖&ޘ#G.1%ܖ֔aj?rtԖ|Q {eGVfxCICHBRgQ!͓)('T4gX&·0ˆ54Չ 5<x$،͍_Xҏ +BfUh.KgCϗEЕɔ!"[ 5:ZΗ(֕w=c$pߕTQ(UPVy͉(׎Cȏb!pTb/k͔\͕ϖ;̗nՖ zӖɖ;a]%bڏv2҈ JOԃ=7Jo*ׅxƇԃG{5_H؍|Mxrk`ʎSΏ̏F%n4܈1…ۂzPc~3~}u}}~QтقXt܅K_w-4<ԁ/ ؂W 2?9/ʅ +ׅ>͆-8)Dh?وˇJń͂3|Ad5~}}}~}Zr~ ~}}}} ~~}q|{|~}|~||-}I}S}}'~~(<f)uQ(؄Mi>܁(h ~v|zyMzyyyySzz{{]|#}~h~~v|`{y{{f{`{^{7{{z{}}~ ~} }|{ {){U{{{\{mz}yyz.zzq|B}}_}m|{zEywwwwmw$wvsww'x3wPvuusv6wwexxMy?y}yzzN{{E{"{{{6{{%||}~pwSD U8]h~~~$xǀJ~"~|zxvuu-uuvFwwx{xlwvvwvutttttAsircrrusstt'uuulvvvvwYxyvzz*{>{zUzxw]w&wvvvvvvFxy{z{(|Q}]~(%n~)~ ~~}||{{{+||_{zrz}zzzzzyGyxxxwqwwmwevu;ts2qpoRo(onsnm8m`lk@kjIi|hWh)hhZjjk5lAminIo)p qqRrsuwx0z1{|{*{zyyyymy^y7yxtx8x~xxwvEv]vuatruq=pp'pjppOqrttcuUu~u vvwwwWyusvwxjyyyx xIw{v4u t srqhrrsss_tt!u uculuvuuu:ut%tswssUtthtu>uu7vv`wCwvlu tsjsrbrqS@TTUU UScSRRSRTmTPTT"TTT2UrUUEV8VU?US8RPBPOOPsQXRsSTSRPNMLLU +UUUUsUTSRSMSXSRRSSSSSU&VVVUUUTSSSRTVVS!QPO]O0OPsQPRRaRQQRRERRQQQP$QuQPHPPP*PPxON3OOwP/QQRSRQrP`NbL(KbJJI[JJJIsIIIJLJKKKLLhMMNN`OPPPTPPKPPBPPPUQ)QPGQpRSTWTTT(T0UVXW#UR%P,OMPL2LM;PPKP:ONMrMMNPRSUSQPN +NNNNP~QQQxQPaPPKQP!POOPPPbQQlR-SSSR8RwQ)QQQQQTTeU~UTTU7UVVUW&W WVUKUTSS)S;SST2SRRQOQQQSTU]VVkX!Y9Y YYZdZYZ[\\]\]0\ZA[k\D]]E]K\[[u[e[N[([ZZ^ZYXYY[^_s^\Z;YYXX)YYZ[\0]^w^,^Y^L_[```Daa|a`_^]\[[[Z[1]:]#]&]D]\[[[[[[M\[a[ZTXUYTSLT%UV W WWX"YZZ1\v]G]\R]^^;^^]]]\\[ZYZgZZYYvZ\p_F_];\-[PZ]ZZZ]ZgZZZYYRYYYY=ZZlZeZZ3[ZKZX*WVVmWrWWXYZ[7\C\[\9\[[\]&\YWUUUTVoV!V#VVVBW#XX6XV&UTT^UV?WYVUKUUT%TSRR SST@V{WWSXXYZ[g]__^h]4\W[WZYYZ[ \\]]^X_______>_^g^:^[^^^^^^`abaa``_`aaa{`_4_^]\[[4[[\j\R]x^7^$]\\_\[[[9[ZZZY!ZLZY/XVTsUVJVVWX_[]]$\?Z*XUkTSR6SZT9UVVWAWQWWWWYIYYnY|YYYYY ZYZ[[[\[ZZZYYYY_ZY1ZZZ2ZbYWYY [\\[~YX4WVzUUUVUUfUlU1V>XZ0[YWqVUT?SR~SgTTTTSPOMMwNjN1NGNMLKJlHGGH2JbK~LbMNOmPEPnP#QRRSSSSBS S0S;SSRQQPP2QQQQR#SS?TTfTSSTTVWWXXXX"Z5[3ZXXmVhTRQQFRRSTTATTTTTTTT{TCTFTTTQUTTT%TSiSSS)TSST +UTSRsQONNNNNO>O}OBPPPQaRPScTV\W_XXXYYXW-T QONNbNNNINM>MMMLLNOPQPONMMdN3OQOO8PPtP"P;QWS_TNSQHQPPONMtLaKKKoKKiLMMMrMMMXNOOO ONNOONN)NMM!MLL9MM7NMMMMkLEKIBIHIIXI1II!HG>HIJKLL!NN NMuNNOOO2NMMMMLM&MMMMM^N?NMXNN\OOOOOP&QPhPgPYPvPPNQQQDQ5QPSPOOyP6PTOPNNMLKKKMNMXL]LL7LKKLLPMMMMMNOOZOOUPPPONM>MrMMN-NMNNOOONNNOqP7QQROL+KJKLANORNxMKJ(JJHUI=J/KxK-JH?H?HGHHIJxKKLKKQLsLL+LLMMN|OPkPoQRQ QJPO+OONN/NMaNOPzPP.QQSQQ7RRMRQnOANYNRNN8OOP8SVVTROMK\JIHG$HHHI#JI*HsF[EDaEFIHHpHGiG;FYEzEEEFGHIMJfJ>J3KKRLLLMMsM+M@MOMMM|MUMeM/MMMNNN=OSOOOOZONMMLMLcLJMOMMLLMFMJM-MLOLOLLRLXLKJJ:KKKK0KzKKqKJJJ +KKLLLMNPO%NLKmJH,HfHImIJ]K;K)KJJwJeK)LLLzLK KJJGKKgKKKKRKJIdIH$HH_IIIJJIqIqIJJOJJJKKTLWM|MLVKJYJhJ9JIJKfKKLLNR{|JzD"5{}[byX!Jh DTg*1O!+EZb0>-e6/6<V<S[}Pfb= `TulNQ*< +s(7Q_)^b?FDjfF-6,sm )@/Am7 +3O( 6P0-WHY#sz`2 rjq<mI{tyaW 7^E Rt;N:]j\y+1}K,~DO.9VN!5f^tCHZy%W4$$*Y<N_W?o$SvjLz[T7|g~*hq;95\&)p,* Blz)SOsPu{  + N|q rz@lp*j!qO 'E .Rh=]K&o%TJu!E})ex8C*oi]Lb e gN[jW*c<?rZQ.PmdNc81s&rU4 +/D0}\yAlzT\>XN#x4y,k"f {nAhf!!rgxg AO');P.p>/r4wdYo!.p1`-_HA;;E2FeEMp.4] h(nm=:U0>,xy?b}q\DPN5Dgj2;,\] ~XD$f$[g r]4TxSXfR ~S2BI<bbc*$g)#.'8bQrnIdMZl[0".mnV_"|k_r/>/ +$Qk8qV| lA +#00bSZ l* vJ+`{ I$71 + i@k ZFQQ_ +}I^@iw%p FD)<Be4){fnsD e)kp#I9))-*3 \7+|T#nFjxyejMrMW}|U$ oxBY@dfZ}-rxoWX1_f\?w[f.5r6K +.= QG U.tyIp~vBK6<MKPK4 {B?xe|bfmB~#x~R/El1b.[2 shjQfeO#l!z={kk.&!H?9+:OurTYIDxR-R\ENBik}Hp n ]{eR< #4]0$3'Cm'. +,!T(DTR!C#WX:S6zacHG?%Y)f!YJ2r%J_. ];H!BS:T|{jMpm"eJ'K!9;HE*4|sUKW[b{~:Va0EQFJ )N{rw_B +0|At$ >OC[$ +Jd}}~i~o~?~E~J~}}\~~~~~~lS9@hOx~BDf}=*-yXM M~~T~9~}}}||}}})~t~<~*~!~}U}}|||r|||||_|r|w|||||x||{{{|]||}}F}}}2}|J|7|{{T||&||||||||f|I|{u{f{{!|D|7|(|d||2|{H{ {zz{zzzb{{w|'}"}}3}4}%}|t||{{e{{{d{{p|B|{{{%|3|{{{{{=|m||a|||}8} +}&}|||||}||}f}=}}P}~~vH~}}t}|}~}}}~ '~}~~ru~7~ ~}v}|p|{\{_{r{{{{{|`|m|||i|{/{z {{{T{zzJz%z z,zPzzyyyyyyyyz zyyy!zy7y!yy3yyyy$z=zzzzzJ{v{F{{zzz{{H|l|O|-|K|B|d|s||{{S{{ {{{zzzK{{T{{{ {'{Q{t{|C|3|9| +|d{&{{{{{6||v||{{{3|||A|{{{{L{zzF{{{{B{<{s{{|.|9|d|;| |:||}0}A}_}}~})~~~R~}q}}d~~}}}a~~>~~}}}}S}|w||r|m||}L~}{}2}||.}%}G}|||Y|{{{{`||||}~I~&~}|V|||;||||R|Z{{-{O{F{;{z|z$zz!{.{zQzz9zzz-zyyybyxxxyLyxxxxFxxxxxx#yxyyyKyxx]yUyxxw!w_wwx&x.xixxJyzyyyyxxxxyyxx^yyyyyyz{7{{~{C{M{d{{\{{z?zyyz z+zGzFzXzjz1zQz {{{zy/yxOyhyy/zOzz{Q{F{G{{|{|||<};}||{|u||M||||}||%|{{c||_|9|{`{{zzzzz2{m||}|2}$}|.|.||||}=}}}}};}|S||||}>}Z}}}}Y}||G}d}b}||||}p}}~~~B~9~:~}|||||{{||{6|{{{{|{/{D{{zzzHzyyHzzz&zyyz=z7z*z0zyyxxxyxyxxy[ytyHyy y yNy!y3yyـcUOxbj ԃƒmق$SԂwKanSwN΁|rQg}< C +7~~~~~~~~~.~E~}}}#~|~~~~u~$~}}~}}}} ~Q~Q~G~~y~v~~}Z}j}J}}}|@}`}}~~@~ :~/l`h?6f~~~^~l~~~~K~}}E~~n~~-digkK^$aJ Mހ")KOـQKN=ނ‚%‚lB` ˁ܂Ԃۂ*D܂'R}oDOuZfl1͂qd.QÀIE 3ʀ$8<q'x31/HC0S\-w9~~{~$|})y~b~~Vi6~<~}v}||||6|{Q{zzzh{{{{{zzzzzzzzzzyLy?yMy|yyMyy2zSzXzYzLzzzzzzGzlzmzz{{{@{{|@|f|g|W|P|G|||| }}~}J}'}k}}}F}T}`}}}9}1}I}k}}}}~e~Y~A~~~s~}}7~G~~D~J~#~~}}}X}+},}||||||{|p|7|.|||||}E}$}V}3}~}u}Y}q}}}}}}Z}<}}}F}|"|{\{g{w{{z{:{j{{{{C{zgzzz {zzPz)zy5zyyyyyyFydyyy*yxxxrxw_wEwewvvvww'wSwow|w&wvvv>wZwuw>w=www}wwwwwSwwvvwwww7xxhxqx:xwwwwwwwSwrwwwwww#wwwvvwaw9wMwwwRwswwx^xxxxx*y3yyx)y~ysylyy]y|yyyyyyyy(z:zLzNztzuz?zzyy zzyyyzOzLzozzP{{,|!|{{{{{{p{{[|Z||{{{2{ {zzszzyzzz<{{tzuzyzzzzezyy8zzyzyXyxxxxxxWxxwwwwwwEvuvmvusuBuuauruvYv\vHvvvAvvWvWv)vuuuu$vRvWv}v/vu +vvuu2vVvZvvZvyvvwwwx$xxxxuxxx yFyyyyyyyw7wOwWwwwwwv'ww'w7w9w+wiwuw_wvvwvvXvkv`vvuv#vuuuuu9v`vAv\vCvv>v vvJwwwvxvvFwwwwuwwwWwTwPwvvvBwxxxxyxx1xxsx.xwww\wwTwwwwwKwgw[wwxaxxx^xkxxzxDx;xxx\ycyy.y_yIyhyy|yyxgxMxuxnxSxqxsx[xEx@xxxCxXxx~a[;6g״MUʴȴƴs6<ٲ{̱wDMȳ&ͲL78;+ ʱ~(VűV#ֳڱϱ(Bس,_ױ28yDZ:nfѱ_j? }ӲܲβѲƲYв^޴.<ٴp1 V߳$FʵIZ6ֳl>GruZ ^Wհ%հslɰḬ̇~i>sY%IxSYM|հ.GF ^uzS@*EưӰjhDӯ6 ְEkdϲw0.5 r"$E԰Lܱ]nܱɱWh[n@\ϳ.M6G +h+IƳȳ׳?ٳVyUeobӳóv|ñRHȱ vE +`"go߰uX| ˰aMG";1 +,ïS$,̮j''$jP*T61.~ͮXyH&1o̮uDv°PG"+kzIǰ6Z0"!( UMCIw)LcZ± ruƳHֱܱ[~n԰W]Ʋ KCR 7;j\k 0yqbyS\(޲NwoWU45:ɰݰ(RxZձ-ݰWK(įFӮ{}`[h~®ծήU_o^$į#qݯ)NbY\UI +Gdz IWm[] 4%ϴY_qߵӵǵǵǵ8ն=+z@qBж]| +kc 2Claze`>˶Ŷ>ƶ.N4)޷d׷طkٶ=HȳٳIZƳhaoe$C>)-+F³kF,b1ey ǴĴ۴D@b$Kk|U@ڵg׳޳ ճL}Ҵ,FF, JkJ3+uqvHC7WѶ*)pĸָڸ˸޸b˷ӷT60ηʷ Js}-7^xd<ַH:b}bEGSh8$@}R߳_1dz.;U><߳WJ "~eL2 +ղzIJ_gѲB(رxıIRU}J6YѱñC}@4A%)̯+<>'Ůs6ѯ1S˱ӱֱ2ǰaTltvJ7eαH̲mwܲpplGű<߰;`±Ʊݱ&oyDzDz^|f<Ұ3i`WYkV5ܯϮRA.ԭwlQBӫ]Kgѫӫ߫rY]@AE-߫!5ЫW֬جkv٫{\Hg0KY{@N^WTU5̭%׭ϭ ?7[Hï}=[,ԩΩuGQ\X[Ss 2~-@0ϫG¬n­­;-̭mY2%;zX=ɫVB<$R2 ҩթ-IϪ+iYN +%7)׫PìHh*֮zޯI;;=O0ǰ^ȯQϮڮƮ`׭T$Ggϭ[ (ҫ  ʫ}H-ŪʪԩƩɩĩȩ. LЩJcw7XI@RM?j$ZqũhE̪}ЪުJة$fͫ:2e,ŪO=٩/1B5ū۫ϫګ !%Ij//GC +*`tAolo],ON/$# ++pj8hFw0fF=! UUPoB-HYJcf7b0c. d7;VEXmm,o:*+s}(ti #n!>Kr6mEO :.pf'4P_:(%TJ8EHC,#<p<u.9ge.a`I '   ! ^;f<WW>kK1!9xw;H(f#N 6I)G!%% =BZtoO/*t;oAh}a1 KYNf`%_chwTy`#5yR/*5|_=J%BH[ t;Qi$9kaSy_t^X(N 5#N):jO~Tl>HOs ; +x F +,P> t`Wd [X1`Ke{Fu~f]\c:T}%azh-*~u_(U.3Rdy/ I$lot(86w@@= .)FTSAc4>p^O?D|.R +   ; + + g6  /}<  b +r + + + + +X + %  j  JJ +l +.[1+j;A9  SpSK2 +bv7[V<>r^Z 3MHx/0 @ *>ykn(84a/cjkS +O LBQb^Dh{9mL  +] `  J +_'Fn  + + +  + +?  R00)Jsez?  %>Eq     +  p|2B ~G>dz~N5t +  + +6 Bo~F`wr?/[g=Vso{PCM7!LmE [+_bE[  I ` +k%5KZYgDsb,,,6j =IGEi-r/G&&^.vdOZ'lf K)6gv$AEKN  `u z/v xyL)D"t7.^)Md) LLI1ylxcxu$cT)/KG53Xj*@JI|e&cFBFcab7 c>`b9f>KPI`Ln95N}C41CnBVQlJa|{Y%$ A|A+h2$Dr3Z_UdQ60wE,'|s umf6E*48@N/(G$h)HZHsFV36SNgU%LXQWAG)|nIx7c/4]%-sLn8bJbi{'oc 25\XfGlXwc3tRj_E6`//DN>vg UV c=>^f0 2#"la53 + .YG\07s& $VM|771=uaWBPQHmL.${j@oH=~ b,\a& +SPf_( +S}E{"dfq"\N4?h3 Dca%N]>5:G\]`xt.^&/Fq=7@/+m<tHU`"Vu7l+gb4_wTmBe,PmVbj"1YJO/U]gu$hzUGv~*3d +2w!KRKp!*H@?#Tt~>:ld /2eUwXxvB K D@uR\@i/>J^>HpCE9C+w;kJYX|;WqETW0Qnc7$= q_!)SSJO q3TbEi%/a.L~PgZ@m_L9CgU:'3wc&#\;U=+-F^WIFuRlZR4IG^jH8(C@P F 2b{- 5JZ~\n 0 HEyZ5+ lU8\,6QH+G8 +}cRDP{"]+\F@CM&h +/,:C?`-o4hzX}g='!@ 6f7dkQ`q>jsn$UD]]@x"{x8;DYh%l. u=$IP 0&t _ +I8{se5g s*vUyN"n)r4LS7*'#dYHoclb(h> \ +2F5'y>VG84JVqu +3_+brfr{Xb8d;hqcyyz&dt~~CP,\8*~8s!rCj`K5Rrs:WB47>QC-oSI.~*ch*N'z4ZX%p82(3BHSozScb:Tf/-38& po?\{0vOcqB"PA GvTg Usֿ +7S,LkG}PnA ߾$:w& ߾Ҿ838MRɿo.(]Nel<RpBlJO;Kj4|r^ roRfgBTO^Jvܾ.ҿ@c1)7,2EdLCK2Q}#@ǾdJCJؽKqսAIbP~ yоk׽ٽǽ˽`Y;ؽԺ̺ǽ(1"l=jE1 +8m-.<UԻzl5+ZȼҼ˼- cZIlݿ{POUdFܿۿܾ"}ǽپ/r߼ϼս i%jE2_K&+'Rm|CԾKegý~ F-NjLY\LyĿ ,CSmucH +];~!G?]Ny ø޸*,(˼,;̻#Ż(QW۽GAl3 s1P3׼Tsv)ּ@߻.6|_.FA +/)b|Fiwgkg/ʾ4ۺ'|plG>J`l@UwdȿKzoܾ"?G)bL59t{`lnoĿ1B# +uO?y տ qB8׽g7ǼnuIJ2޾@Ѿ#Ҿ־þڽ̼9O|Q!4Lɼ۽k۾{ɻ9V*}gJHa}˾Qdw^B*!ynp</B,q7G5( QNImC gh9%-3QXHl#IM yVQ=$-<t:tqd] )sO_v.-!dAf@f0b9.^,=+xNz5}q;^qJ:c19[SR,TnC<=IjauOPsMbR,C`xM=-l+k<U +[0h6mg6!Gm]>L=ugR?wR9~J)yj nod*P[FF0i*r7@NS +0Bm~Mn]:/RNOv{U0m\W#v )N~8J {M(ss8}hKc&Va;gK - =dJvp2^w5dVV`fhz\U!>~cJ"W&A65T"inq[r$: Q8G>[p7h}M$=}@HuQK'6zog (=ruJHO'^M6Q`#N.Gat^E2$a?rD4T^Zz6H7orF7M9"ZLz\&-d%XC#SGT-p%?"MlAT(OOwLco>;&9yDwmlR +1WG<^7Ks\9T3*u0VgE1I`hsCIAA$+0R1TQ\}y<||k=}"oeN.}E @y0]N" a aK"nTD)Ln("dt&3^'Bs2Ed%a:R+n>jGv:(?R-)3G;Pwz@#]h9 SM$ K!~jbcf+M `8V+*$\<x\*v-?SUC5Dx~K>Q:]h(vG9_+{y?*g%&o(g W}!nC MZ=084k$={.,8aw/ .JTT!KbN 79x59gw(Rq':-gv{ f1QHB?,](]v&yH7 }7-cBQ;VQ2{5Je4HY78{\WaGK[pP\e$zf)T}Hq3PS&D4M{1k6Bm1/TSMN;"0q}=;  bt eV.b`%YU0d1or1]SSr=4t5CqgG#o~2o8`Tq SRX&rDhoG$^,F 6bT|M_f|!$o' Cs|hq9W='G$7K5FIXy3E9_ "r >OV`w'%{G +&hvjduvwk +}cY M.H9Hm?y8FI\(=)9Sge[J+dxrI3)ly=Y_36$ZzP3 +~pXbBR,Ɔ`kIhsPTB/ Շdte6 քmpƒ҄Ńр0@D}zz|Y}j~RfÁԂ:lNQcˆV9)VցG"!G%++ۂ +\tӂ9o|X'^\~?~~F*TY{Ҁρȁ6wĂڂ݅~TjHą ̓҃=̃؃$dt΅  0WڄLzog4~~J^$+3?ل˄CC; …˅h1ބF'Ɂ<)ʁށÁہvh~B}g|t{vzxwyz{;||}~C%*n.ĆVttIuޅ;-х=̂>xxk>vK.Nׅ07eσJgU'ـ>$/%[fP$o?Gń>5xi_:܄ԂFЀՁ58Y1`,UPքDl߂k_Uk3P.#CC ׁ* zA-^ πZK~}\~`~}{z#zy-zz{|~|݀5 g XÁTv~~ +~~X m؂C9Ƀ!'҂X΅U(΂ہZI&hi#u=9/R#11rYk|DT+k9҅|FE׆Vށ>ŁtUSQnw@:Ohȅׅ)OLJ +#+JUiiu܄'F/؄JL~~+ ~}D}f}} ~}}#~~r~w~3-3Ā~]}|}~V?<́΀iAԁ [=]ȁvu5|lU&sՅɅDžm^ioN܃'f=م[>΄ yeЃdjm}}ʇ ψ ^i#Ԋ׊,:$|I$Չ,';ʈj  +n`BɅDЅ$Pu܂AVO҄"w܅3p̄5Cʅх˄ӅjڃSɃoՂ5v`̀€Km&'~!}<||}~5݄$0ufkׅʄTV=(dփ߃W[C??ʄbK2zPƄƒʁY~҂ ǂ"eNքuN؅!_NaGVeTNtхZ-_Iqs߅#eV!h:I0^SHLǂ€~}p~~koxbكIDŽ\hR5iȁ'x~~~[~~~~ beo~0~}~~ HAbS~ ~}})}|zyyzg{G{{|4|q|\|M|`|}}~?Z8ׁdy#j ހPUOM}-||}~Dрnր*?~t +5= ?ׅLGW$ȃuсP~E~~ɀ>܁ymteKiށldǃǃƃ{|&؁TOq@~(~e~}~}||||||}}}~NeɀXJπD!ЀĀǀtBHYIX~i~~d~}^}r}}T}||+|N{{:||{{{zzzEzz`{{t||,}}~""4HFa*~}|zyuxxx}yzF||} +~]~~~H39BGƀ;?Eԁh‚Ԃ'MǀĀVcp~}}B~~~~Q~~Z~~~~~~~ +}ɀRanB{~}}O~~~~~,~"hL~R~}}q~?~%}V|{uzzZzz{{|}}}}x}}p|%|T||{{|?||}q}}G~~ +T~|{{K||I}}~}O~~: 6H ~d}(}|@|B|T||F|{{'{Nzy-yyzyeyy!zbz'zyy.zzyczzz{A{Z{^{{z{zkzzzvzyyy-zHzjzzzz{O{z`zyySzz{{|J|}|e||{|^}}}}N~N~D~(~=~~~~ <ac.~ +F4dƀeZ<~|{ {z +{s{{{{{{{S| }3~~[&~}|{{ |Q|||}y~~rXO~}|||}},~~ HpE o\~x~~"9~~~d~L~9~A~}}}Y}|||}L} }%}}~b~[~Y~b~3~}}}|{zzzOzhzzzyxAxYxx}y?z{{B|W|Y|b||/}}|G|E|||{(yxxxwwwxoxxyzz{zz +zyEyRyy2zzzD{{|||M}|||||z| |{{<||B}}E~%~}}||||}}||{||}}}}|7|{{{|{{[{zz{:{{|g}N~/~~(~%~{~~| xۀ؀aԁ1aQ)~$|zzT{|}J~~).o~}}h~~rn%BZ̀wzƀ׀{VpuV~~~~~-`P~1~4~g~U~}}}n}2}|!|J{zzz+{{?{{{{x| }|'|{|&|N|\|||T|5||||w}~=~%~}8}F|{{+zyxy"zT{{|l}2~~b~~T}||b|||||||J}?}}~P~~B~_~~?H~k~~'7^e؀ ybd!~(dU~~~:~%~1~=~}~}9}I}} }g}}~}.B{;c2~zny$0LN#Kw2j FKpVr7;-6I.1X9Ee4Gmy5 Crk{>yH?aN]{2#-` +=Iio`;KtI[dxic, r)@n'j o]#rVa +_$; nZ8%brxXa.eX;f_LYV;vgmrMuM<wp}/"ok3luizAAbwrF hXz+egIPFl9R#u +A-wCY\99mE%';4\9lNA7xY&e"eb60^Mz TL +bj1Lplj9|z)n>R&LNu RgVR<}F5K8}L:\d1@Hl2=O1/Sqe8F*]b~ m1hx$r%+|#)6+GBayz;SGb *-fWL' +C>\' +J-!00%MizI!i +hx/8=jG8GpMr p~(kbdU)k^ w>./XWCt`n 5w9Noz=,MLC=J_SH1@a8V.1?DeLKKKKK`LL MMMyKK-M+MJHI9JJGJIIBJJJ>JHNGF&GeG{GuGnGGGGHdHGsGFERE^EFFGH~IhI,IHHHGG +HfHhHDHGFFfFEFFG GF}FF7G]GFFFErEE FZFFGGdH IIIJ4JJLhMLJHGbGgGGUHtH?HVHHIJLMMLM|MMKJJJJJII*J]JJLJIIbJoJ#JJ JIdIIHHHHHIIIIH-IJ4KKK/K,KZKJ;JIIHWH_HAHGHHH)HG`HHrHgH;HHGHI.I#IHG+FME\EDF)GGGHLH;HGHGFFFFFFFFwFlFoF4GG:HGFhEDCcDEpFFFFGFEEbEEFGYG7E'CA@vABDEEFGHEaEEEEԣ{`\N ͢*Y\ +)6<>[!W5+cΣ m ¤O\K/sɤߤxNhWkQOʦ''/ߥܥƥjuy.٤ʤa;עע֢w Z2$آɢHTCMV ͡nIff'Σգ/ͤȤl[٢]ۣͣ$X-٢xޢ΢ӢҢѢ< ̣z >82FJѤu__p n[ѤsL-s| ]̥BH-zť٥=ye ̥,;&Hry'ڥoxX+SO=Ѧ MV,}mݥ\PHdsФqjMO$ \ѣZI:8}Gӡ,4+JR,m\͡ߠwˠҡš¡֡ӡO&9h{9U?آ^IaOeC9GRHWTmG"DK!xΣ'bʡ¢fIN`Q(@~5ɤԤäͤۤ|dz_aZ.ʣYIhɣt- ]XXʥ-mڦM]Q¥Gb$cN[Upڥt tRf|Fp^ڢϢע٢Aۡ>nb6bբGSi<:ǠUi27S,Bá6:Zkۡ`EP΢ . UNZĤ+ɥ %(ާsN˧ + Ч +˦K~7~>*sͩP#Ѩ֨>/ŨCL/̣c٣Si )u#)ˢڢآX}g-QqSD d̢'^@ʤEfyǥ,Kh%S]'ˤ̤-1}ueM\P"ƦxcҦtXOib1ʥ}'VեIqfYO-e|$Ӥ,ڤߤKͣң#"5Gܣj2]TyyM?Pd]u РhZTJBhqġwޠH|M2cpBM!,b"[j`+ٟzɠ! 6mz1obRwl]d`vڢwEr'/ Ԣբ!T[ģģգޣ`ZbNmm +ɢ1 OA421á(PW1EBGxI!~ܡP9+Ms~ussϞy =S=ҞV,ur֟w7ڟ=sƠߠ X؟+=2 rocf'2\y{RS+tryПJveߞb ܟ(Sbɠy9SJ1G+`}Nm$Bo(eBfء֡.ybLfx]D"9ȢGG*\wzh{vvgM)p>}VZPfw+fQeDd;#jkT!F\*eK/K'@Ɵ˟۠etW3ߠY_Q btyxluZ$3O؟EVyŠxџΟݟßşПYŸ%U Сt"ݢ٢oVIjˡ]CUܡYspg/x% J :%V~I4{Z ϢD_c |)-Ťlf!|ҤФV£D9H$סġVTZΡW#4 ].>ڟٟ +d-؟&Zߟҟ˟ğ(1 ޞ X62QzӟV`FTXTTTTTiTSSTTTTKTETTbTETJT;TSSdSSmS`SBSRgRRRRSS'S,SUSSS?SRRRQRQQQQkQ|QQQQQQQQQ*QPMP9PP +QWQWQ Q2QQiQ\QJQ6QQQPPPP$Q%Q/Q0QQ QPPVPOOPPPPPPPPPbPePuPePPdPP PsPP+QQQQQrQfQWQQ\QQQPPQPQQQXQ QPQQQbQQZQQhQNQQ%R[R>RRQRRQR +RQiQhQQQQQORRRRRRRES}S{SRRR|RdRRRRyRSaSS)SSlTTTTdTJTFTTS^SR0RQKQQ8QQUQ9QNQQQQQQQbQ!QPPQPPZP#P7PMPLPFPQ_QaQ}QQeQOQPPPkPYP7P;PPbQQQ1RQQQQQ2QgQQQQRRRRR)RQQQtRRQGRRRRRRR(SRRWR#RR&RiRRRR|RQQR +RQQAQfQwQdQ#Q"QPPPPPOP>P=P4POOOOOOO8O O3OzOOOFONNNNNNtNMNMMMMzM[M]MBM,M M +MLLLLLLLL"MMMMMMMM}MMMMPNNM%NMNMnMrM NkN`NNNO5OOOOO9PYPP0PbPKP7PPPQqQQQQQ\QmQQcQQRQRhRRRSSSRRRXRRRSRAS^SSR9S:SSSUSSTTKTTTpTSS|SStSSXToTSTTTTT"UDUWUPUUT|TETTTTTT UTTTTUTU_U@UUBU^UTTTTTTTTTTT +UTTDTSSSSSSSUS1SR]R0R1RIRR9RRQQQRQQQQ QPP+QBQBQ*Q7QQP QPQPPPPPPPQvQQ[QQPQPPPwPPPP7Q9QQQQQsQKQ?Q;Q@QQQhQ'Q2QnQhQcQQQQRIRR +RRR)QPP +QPPPPPPPCPPPP$QQQRyRZRtRRJR$RRQQQOQtQQQQQ2R;RxR`RR,RURdRRhRVRJR RRRQQR!R0RRRRRRcSTTTTTTTTTsT]TTT:T8TT9TTSFT\T[TTTTU!U UTPTT U7USUIUaUUUAUDUHU0UUUUTUUUUUUUAUPUTTTTTUU&U)UTTTTTkTGT_TLLLL?LcL MML?LKLHLQLKKKKKKLKHLLLkL0LKKLKLKK LK:LkLLLgL,L7L:L3LRLLL7LLL^LxLLMrMMMMMMMMMMMN!NMNMMM*NKNMM3NMN[NFNNNjN{NNjN]NMN}NNN0NFNNNyNNNNO]OO^OROxOwOqOeO5OOOO!POOOjOONNNNNNNsNNNNNNNONNGNN2N8N N'NAN NMMMMMMuMM4MLLLLLKKKKOKKJJqJ}JJJJJJJ#J;JJJJMJ7JIJBJ\JJI3JlJJJJJJJJdJIJMJ/JIIQJVJHJkJK6K KJzKKKKKKKKKLKiKKKLKL=LKKKKK +K1KK^KKKXKmKLK1KK7K$KGKKK4K KhKKKKKKKKKKKKKKsK(KJJJKpKKKKfKdKK\KJJJ`K$KK\KKKhKqKpKkKtKKKL)L@LL;LjLLLLLHLL M MLLL1MEMxMNMM,MtMMgM=MMMMM{NNNN\NNQN;N%NMMMMMMMMnMMMMMMOMyMMMMqMwMMMLLMLLLLLLLLLLLoLLLLLLLLLLyLLMEM`MdM +MMLLK^KKLLKK+LK|KMKTKRKvKfKN;NLN$N NMMMMXM=MMM/MKMLMLL*LaL,L(LNLTLKKKKKKK?K'K#K KKJJ KKXKKJJWJJcJJJJJJJZJNJ8JIIImI&IIJIJeJII JIIFJ#J*JuJJJJJJJK^KKKKKXKJJKJJKmKKKKKLLKK%K{KKAKJKJJJ!K2KZKKJ KYKKK3LkLL\L6LFLLSLOLLL=MIM@M4MQMML(MLLLL LNL?LL3LKKK_K7KKKKKKKKKL=L LKKK`KbKJJJJWJYJJJJKKJJJJ'JIIJ#JPJXJ/JNJJJJJ[J.J'J!JIIIINJuJSJ2JIIIIUIeIIAJuJJfJXJCJYJ$J:JKJJ K>KKJJ,KJJJ^KKKqK0KKK\KKwKbK$KJIIIoII#JZJ?JMJ\JwJvJJJJJnJH_HHHHwHHAHGGDHHyH*HHG9HXHH7H:HHHHHGIIIILI II>IIIIIIIOJJIJJIIHIMKK&KJJJJJuJaJ{JJ^J8JJyJ>J +JJJ~JJDJIIJJ JII.IH@IEI+IZI?IhI}IUIIAJIJIJ"JII IHHHHHHHHHHvHfHHHHHHHHHHHHkHH-IMIJI!I\IVII{IIiIgIlIIIIIIII JIIFzFFFEEEEEEEEEEEEEEEEEEE FF3FXF~FF4FEFEDDDE>E E,EEXEEE ED EEE EDDEED EDDDE{E'EE\EXEEEEEEZFkF-F)F5FEEEEF6FEEFFFRFUFLFEEE FFFFEEEEEElErEEENE'EhEBEEDDEENEmEEEEEEEF FEEE{YJ?G_u[Uw`ioA+S*o|,^#d.5Hy4$OerZ]gE*oj@l#:e2=V"[ZMY"%n AW 7'_X3j}fH`X^C J8zXn]Ae;=rA#Dpbl ?6G!=bT2kZuHlXo*H*yl,900zi\R"<$#&4L,icD6X:lMg2G59E.[{l-XocB+Fh3S5=//9 C+0To'Fn67#'#"eH`Pxuswc*pGKWjg{iW-fx_5Xj&(ZBAq<IlU#Q9.ZQ+T_YoL5B "{EE<bt +)2dQ{~~&b>a"E~@ AasBdX/#_GD ¿[ +9(ɾNeڿ+[yWZRj'@U\`d@fWIVK8J:DPK +[17zs-#cC +"?OGqUAuQy]N# KGf}[K/U84jWm +NQe}:AiK-@o `l:|n]fw?&0$ )Pbc(o`qLZ.n~J5"2(^AY9rm5Y^d ViwhAe!hk0%J|kKtA{hzE[5S43XmTmMb?,hac;N+ +1%iK`=KKHO%bfK1Zd$swZW 7Q/@/1t~Q]s8mvh"{@ + [OLK+,F0/[^0w>hocqw/ǿu!GG6cOQ9 =69, Ͼ \ۿZr,d%`)EIT=:)3lU<+dfa3sk'w+/|qsF*]<XaGGg]jAQEV?45s[+V !;^A4ay3X{EWh8/ 2þPj~k Iruֿ#ֿٿ{Ŀӿڿ˿ɿпdڿhqݿgwuC־ )jп^;E?V McV 9ппt%+w_k^GNpc88znj7+ fu8UJUK]XHBTNؿEsQ`ilfpxP=Q|qExMtPwB@Zaֿ!3*1Tih``_B*'Ⱦ۾%ξ +=l9E](GVHH-7S*/]JvԿ*(Tf n|QT.'pB# 9T8]'O{dFH|L@6A&4(}%T[B[;7  " mKzP u[\3%<#( T +9ϿɿĿܿ*5hٿپNoL-׾Ⱦ#p(B/.Cgnd5GHX^ſ|ap0;¿?/ɿӿ">B5FDT +" G"fxw[ )NuvxDe?[]Y}2^ErWu/Sg7od-&-lc*/#Z'KfU#vYMy}S3SCz2\Q,Hi Yobb^B@k}*Bj,xu=W}_dx {`9) ;f0e$h. G<,A =s|iqbS^SADB$L@F!96JkNewEZjKnt3m?) {i&9^ x:WD#sBdt^tnU,rL!6eWv_^XQ4^|l4q '%dV +'h:aXnwBKCqnAT- +Kvr/=#%0+cClvX'd0^d. 9ra2)/*3ufm,yO)meLY2|Z/V+"Q\3CP+ .5"S r +N}/xqR9z kJ1 XtS&<4-,H6H 5VCl/k3[2vsx7'I6V)L+[ !' CSU3OvP'@0uW-mpU,tCRdM3FRHyoaWJ%ClVyc +[8(G`s{TS7~.w*d[ q>28fNhGp5DaHD<-ct)`E>Z 4lmc&SGYV"v{zHCo$WFW,$$31t"?}t t{C~y"dwEE/xn~I]1 +^:~,IexzHM6ElIl5j:U&+YqI.mieW:x5:01;ZR(Rv;+:C> CRX-!XB*p@%TT)+#x481VS vL>DbW <1?]b mY_YmgnD(zB!8x~X7QC?Z;M-8&0gRQS|J Au_g +xVRyyeLSKi9ZU0[ic-pv~6M}A +[0qB0D>7EuL;e%.7w.tffV+ +LYb93{|  Dn?IRle~9D%RCi?EG'rbY\e~hA% .<& ' -es\vp +9s@.O!5C~xQ')?"dAXSKMM??\ y+\Xpl I}G#2DdR*]J9^*&Q #M.a e?@.Q8?p +=Ndl]Rt^2xANXzKDJGBfZ?WY=bd[,|n8`uj< h}~4$= tQWpkLtK|U!*Hx4+Si4>l76:$!7mFTS'TlTTTTT&UVVWVVVUUUU VVVqUUU$UUTFToTUWYNZ8[[![.ZYWVUSSOTUV`WOWVUTTUIUU"VVWW WVVYVeVVVVV@VUWU2UuUsUTTRTSSSRRRRRRSCSSSaTTsUUUTTSxSVSSSSSS,SRRRjRBRERZRQQ\RRQPPPP9Q3RSTUaU]UUTU9UU VxVPWXX YPYYBZ7ZYXWVUIU>TSRRR RsQ QPQQURRDSRRRRRdS"TtT|TiTTT}S4SRRSSS]TyTRTT;VWVUhUUUT\TS8T{UUCUT,TSSSkTTzUSV XYrZvZZZ-[ZYYXzXXWVV4V>VUUTTxT0TtTTTzS/SRRRqQP[Q=RYRRjQPQ|QQRRSSSSSRARQQ.QPP]PPP|QR0RfRRTTUWW7XXYrX/WV8WX:ZR[[[O[ZSS{S{STTUkUzUR_R+RQ-QvPPPPQRSTrUV!WvW WVFVUkUTSSRQCQPQQxRAS`T`UU)VVWPXX?YXYXW?WVVWX$XdXXxXWW*WVqVUUFVV>WWW+XXXXXYXXYXOXyXXXX/XWjWlWW=X YY%ZZ[\'\\\[E[J[[[[\P]!]\*]\V\.\[T[ZZ[[[[i[ZZZ[^\\\\]:\f[ZZXXhXX[XXY,ZgZZ[\\[0ZYXWVRVQUTTUUTLT>TTVUUUUUUUUKUTuT`TTTzTrT?T6THTT(U$U1UAUwUUVWW@XXXlXWV VVVfWWDWXZ\']\\\ZYXWuV&V(V$VUTSmS:TT~U0VVUUUDUTS[SRRRSSSTSS~S8SRSOS SqST*UTSSTT[UVVVVVVbVVVXWWZW WVV*WAXDYY[YYYcXWWJW)W#WWWWXvYY[]_uaaaa0`_`_\ [YXWSWVVVVOWWWWXWvWWWWiWXWwWWVUTATfTTUjU#UTTTTPQaQQQ4RSR,RdR SISSSSS#SRRRRwR3RRST[TTS+TT/UYUFUU_VFVVUVV^VUV)WKXSYY3ZHZ!ZZYXWnWVU UTTSSSWS{SSyTUrUUTTSRQRURR7RrRERQQ3RRSRRSR +S%SdSmSSRR SSSS T TSTS5S?RBRRSeTxT?TXTSRQPPPBQQQQQBRlRvQyPGQR2S6SRR/QP%QPPPPP}POOPOOOOVP@PPPQRRaRRS^j{6i~eJ'eU[%H$vtsvO8<3Wf);NV8Ko eBzOM(Y/Oud@d;k,fLNqd~Fz,BOo5 (4If: |>+'MibV yw 4) z3H'(io^]6B$&~-{]S[z@0MbKB%jq*@-4X2hknEw A7WL)iZfkyOxfL,N 4W js+bEptz:vWG_z>^b56!Q:;MKw N!: "m"}BFAn"H+"v6Wvh|xOo(nW0^):qIN;>5F(HEF'E>Bd~7kNBTE GbcY'HV{Zs*v< phcUAxOi|5jP JAo 3cC_};bW{FwF ~.%@JDxC%d:~90@Y{'&E>y<wo$ dUC3MSB8}p'DMaM[:l!(.rz]AX\HX&zD.#H8B;UJzb<'b% +n%4% {b'$mFL:?#WlBj]! +}pf@ 1Zvq B*{>lwpI+A<>^bgl^! !3qVT;xRz3v3pZO +YQfMRL$44_yUX >7(b:Az*\Xnd*DxH5tF}RrY_;phR"R]RaFQ,/ib_>08Kbk|WdWW +}5B3rw<qT"Yx*AmLb,w"o#qX/R@{fr]e876_65$585l5=6777666 7K7g77^76W66s6/6D65,5,5d55d544`5{5555m5V544555565}4373-3454!310//(.-_.$02455Z557777c76666*6>5r4j4h4`44B555t5443W32P2G1011(346b777B76'65X54`4'434*44"4=4m4o4x4g4d4J4334.4-4L44432e2=272}2(2b22 +3 334H5<5<544]433p3.3/32 2V2334N555-66~54331*0.4../245A66544c56777@8M87655)5444455@66543]20////r01234b55c66?7T7x77$766'6*544>5u55554333344D4<4F44433I3222'3334333443[44T3G3222i21*1,11000'001221/..012D32d1/.S.b.w/1?3567777V765954x4V4s43V33333K3\3w33k33B4=445M433l3>321n11=2x2234g5q54Z43,3Q3b33a4.433O3333222R223n455<66555{5U4V3!3f33244X55}66-65q5j5R5544"392111A2:211m1311234B5666z584_3334)44943Q3k2*1k/}-+6+,J.^/t0V1111]2(3 44y5532!2e222222 32O2s22G2r100)1<1>1011.1 131c11.100f0>000!0.------I.Z..&///0;030)00f12F321H000U0n0@1-2233"4H4643+3W2721d0///0)12{4`5a5R4202*2)2245433344b5c5N54T4|32!333r3`3210)0x0u1234_5565+544u4321123456666h6/66v6655b55G65444(32f224415a5n4@32G212o33e4F433=3I3d33 44r55S655443y383 322R211{0H001\22\3{3310A0t/V.--../H///D/..6//)0p0~0e0///// 0q00z0/0//00/00 1 1000 0/Z000611000//D/..//}0;111222210.--- /0222243A33E4 555636J6Z6&66666[6:542P1j1M2@3r4 6m77H7A776!6P6666b6R66\65}5r54G4433V32345=778887_7F7788+8M7R6L544444I55{5G55K65\5T4p321/`//.../E01 34:5566m6555R544444464?4Q4P4(433L33333322321111111A10/M.--h.n.--,,,&-'.|/0122210B/. ./133[32P22 2N222222211~1,1C10(1n11 2d2X222211A1221122V383 3I3333;32T211h1y1`1)1!1A1122:304443/32z2g2q2D232021S11b10//0///-"- ../F/j/t.Y,|*)*2,R.023Z32D32100/z//11}22232?2112W2x222n2!211111)1k000*0000000141100d02000(0/..-m- -,.-$--4.---,*(g'&@'H(*C-/01100/P//.-],)'%$p$\%'(+A./0D1$100{0/0z/\.-----3.0.*.d.^.N.>.U-h,++++3++*3++g+*))B)f*^+,Q-P./q//#0////L//....V/._.1.,.---..///..-$-,+***+-.0Y2,3I3322'1/--[./0[11111011y1!2Y222221221[11110a.,*))(&)**d++3-V./0A1000e0V0//h//.9//...9/ 001b12j1%1100h0 0/////////0//X/.-,+*5++ -./0Z0/..J--"-,,,,,R-..--,y,,,,C-n-,++**_*X**:+E,z,O,(,b,,-R----------1....I.-{-g-- .--H-c,+*))d)p*?++l,%-a-,],,,-.00r000000\0}/L/>/G/j//0V0&060_0x01O1v100m0w0000000c00 10g00j0_0r0B00i/...$.--U..//(0R0R0600[00//M/P//A/..J.-,+9+*)**+,--,+}**))*v+H,,--./0g001110<0]/^.--T...-4..-//////0//G/.u.N.b.'. ..----6-,,v+?++z,,},e+*))J*?+,-P.M.-.---u-,],Q,t,,++++++++s+****++,E-,+.+x**++,r,,,T,%,++#,],,,)-e-+-;-1-,,,L,,e----1.--y-n---|-...w-v---f-;-,P-r------,S,c+*))V*+,-3/01A1$0/n/ //.--, +,+e+*v**A++p,--./090q0g0'0/.|..y.G.---k--j,++*#+o,-.4/b/*/..-p--:..--]-0-,,T-:...--U,, ,t,,-,,%+d**f**+V,?--$-- +-,,},,+,+,,w,+U+=++*)(()((.))d***f+0,],>,+++*+/+***))('e'O''7)w*+P,x,;,.+<*))P*+,,w---O-,-,, -,,+l+++,-./ //.i.%.-e-'-,,h-------'.-I.^.0.-7,*)(''''('&'),s/72x3]321@11000000100000000000S0 0//0////.,++,-..d.2.b...K//t0011k1,10000/.--/,++,-}/0.1P1000]0/o/ /.-`--,w,,-./L0$0/q/>/ /P.--E--*-,d,++[+++b+m+++Y+#*( +(&t%%&D)+}-/L///.V.%.r.~.x....C.-P-"-,L,v,f-{-,,++,R,,-,:--<..._.2.].Z.--E.5.-<-l,+***++,-------../n0[00 0/v/j/=/@/#/....g.D..P..%.--x--,9--~.R/A00000///]///000/./1PnyMmP<|egIQS&tQ,R[6c. I,5?bkarS-duF*VJI Kf8".(>=?6&Sn `J;gzfI%w%F !Vp @6|11M"UN)m0YW3+Vz{ei#@^nu>A 4$}&+2)KLo ]Yk7Q?=z1vA_xEXj\0"YRm6Hy0p$8id<:),PFnmp9Wk +%><A5"5QQlr#'T,mRk+bd|u=+ Bl|wC2AJytj? 3jBp, L/wiD?@d%3("7*=gOa>W7D$J$ 4;<K`\'Q#5QC&= B_6=+*DfbNU@!-% 9~ZRopM[[aC: U.7k3rk'yDX\lm4,e:)%VT`T*8;pYW^7Uw*<*9dHiF~SaGja#?[2# b<Ak-9; XYT4#mB\3@:'u=Ui#@#^FKF=u +qmzO#g*%`1Twc'C <Ai4|@ +k*~ba(_P)i19['=CV)&R@x% +u*j}5=`>"DAt$Z Cmj+{*(b,\,d{P +%.R5X_2+p+b+k,g!B{[V/oBS4@Vz)UaU*Zv"ut}N[yn'y9`|_*>hFJ /DLzqDCW gP%#MeCKfsy8qW["~e. +~(Kt^L> 1e>V?E&+N'r,/d@=i@' +Jd>VH2QtEy$L[8q4fyF Hq`xG "1 * XgmAgj H9+X0Ty2 +!Tbex}RfsW<3RfTkCr2UN cE !Q[=.? (9 + gJ7$NJ` jG Pz!~L+)^5U}$Oa.t h(Ofl{us/jU55hO7W:labar]}gLAb vy!9MXZ;r>e7L&zm>|i}x"k?aoX3Jq6CY<l)S6QmEA);6>7)4n3hTi%/\G@ETzO \ _S +IO~;1\[lhr^n){.7>aI$]v]KLb6ES);O<?%;CvTxN)(iDlp,B !89PnF+~,(@d)cj^m5}XJje@:YEDy\6x9 te{J'Iz}cX;^zEZKZ+3K+B-BDx}0wX2':GO~CWVhQNxU"[kT0(=a0U+E\Jz/Cr`#zk6Cny* ,Jwox%b(OCbyC]D<%z`YXG^{n-&~n2 Tm=OcChwN/Sfg{)yY6n;\w\FLN FV*!)Qlh+(H?! Re:al3+U a{Ksz% mfE5+*(Np/ +;:aAjD5'Vk]'4 1K,r-3?~cVTR(Bu}Q 0 9vv|->uu\ev[ ++ Q5}xDLh?pOsh,+JWsT% byTc9 +- n9OL0[q4Y'Xu5UH|xG;,pP@;Cvnwx$n{^ {b>D( U&+6rVB(2$$4G*u5/7y=4Uwfh ?OmpShA6-UY[}kic2K~{Qd05`ZW +W/ Y#AM:\ f4DI|.h\7xn#uUbrxMJxQhSm[pj$@Bh =l M~_N2];37 s] (uZ#qq^]B)O.A 5h9&S)Q[$,6%bGTT +3lz`}cQn(@TBYk7B;HWfwTR[dqk( ;xnSRcL+3-kD&&nuuF/:Gp |kJj~`ab@16+'(> +09 <rT~'ÿ¿ѿv' 7d[h++ud^VF{q} HiUE +rJ3V +H[8+2 +2)Wy|r2T|iO?=&*OzX%42C&տ׿[z{w &g:&'ju% ]l\h\fgLm~YQDRb(Pqf=ax'"ab;>>_\i =)zb(IC\fg4+%47#d{;g1me,Q?X?8>0?E{s%G>",mcz@ +XWN(|.Ans!EMz\FVhryZK3 9|Q?>A2CRWA'3%E.Sj#9jW>Z{gn&ƥ TsԦeH EϦߦƦY<`vɦc'[xaT3?$ȥ ̥u- ̤0-ܤ{Z?Nڤä{tTܣ`)OģͣoϤ?irsѤ7v|xk>jZzӥΥӥإΥP$b +Υҥեɥ̥ إť D6֦y|ɧjK!X@' &ϥ|(֤pZrdgtҤulr~9. ԣ֣ݣ,<Y[nH>Wuhab\Wa}Ť}_c\lˤwfXvӥggåi%SD9~8""fdʥڥ =BWAZrH&=Q^k"%Y(gͦߦN1s.tdoĥ2w!ĥɥҥäǤ)ۣwPbfbn4*J_TSEТ1"$WwBp"ǣW=%+Xru=if\>cI;i0ɣ ǣף&_V H7R"٤Ť ^d|I2%ҤVkqؤǤO|<\Z;I ̤DVZ?bGq>L{K ɢ â}С oҢ[xV¡|סɡe~qMU7ՠݠܠΠàWug6*̡c@Oס `עˢܢǢFl+'/[Σ   .У+ڤ#pPRX)CzQ_K$Ф1ujr>¥ɥ$DeEn]Cmۥߥ@/wۥAyY1.w6פޤ٤٤\9jJ6&(/ТqƢע/>ȢѢڢ٢͢R!ߢע-*M-dt15TA?nɢȢh`^rRO ,Pmu) .EעǢܢ,;âޢɢբ͢MJHm~-5SU,`T`!LMg;\xO9|V3#U2ʤդ (?#XsDU!49t?'tN,}\Z]ˣ`ңǣ  ۣȣl+2ISR ߢpVڢӢv.T*RϢ0C[Vgh ΢H 7ǢѢjv=̡*A(Z̢ 8ڢŢڢ¢Ӣ ٢ ulǣܣȣģУr><yr0?&-85$-ZR>BDc&̢Ѣ+Zb6͡'e5oˡȡC_ӡv?ʠ% ϠŠ۠rgZ9%Ÿ}t#e2jbƟpfz}Z`' kß՟ߟߟ֟ nABH FCŠ  %i!XpxT$DiEKLE G=.Em AWԠ,;,c|\,dAܠؠҠB|;6n4+N6 +Π"ޠ+-F gD˟q@Qs]nٟ3Nkufϟ +4!ut"_ZQv3Y0$ğTqܟ˟Ÿjn\YRğy_gkϞ72U}מ/Q͟Vw`ǟ lAU)_^L`x9Ϡ ؠŠà٠ "M;5 Z9S{@(ߟ%ݟğwc5'4-U}zTJcCZm^Ÿ ޟɟXb x\4ϞŞϞÞ+E;UϞ|H1?*YpŞgϞ̞ڞ>+Hfl/žӞڞ7ўȞ "'RʟvqeN6W_:CTPpSteV^_^Z) +˞Ԟ5̟ϟs z2h%D.S4[ۡˡȡjlɡrlYpfg,c1~p͟,'1ўĞ? 1DBZVz/ŝ1( םܝŝНѝ ͝2~MWUAl]y['ܝŞN ĝ%rH ӝ2TIHRssfZ#ٞ˞ƞrҞ۞!!!!!!\!!u!b!j!!!'!  N!r!!Z!p!c!!L!%!!   !  !D!y!!!!k!!k!{!n!z!!{!!!!!!~!!i!3!! !7!>!x!!!!!!!!!N!4!!4!F!_!!!!!!r!!!!!!t!}!!}!!!~!D!m!l!!  !!Q!!w!G!! t            !!    w  w r    r   ; |  ? L W 1    2 p R + 9 r M  " g `  r Q } C |       9!J!.!$!$!!  U    !M!d!l!u!!!!X!7!v!!!""d"j"2""." ""9"C"%"" "7"!!!!!!!!"1"B"!">"{"_"k"""b""""v"""""#""#"H""!]"""""P"!!""1"b"M"%"e"f"w"""""o"i""V"Q""!!!!";" """!!!!!!!!`!!8!!t!3!d!!a!L!G!I!$!! A!y!H!B!#!!    | ~ {   b } {        g  ! ! !#!k!!!S!"W"!|!q!!!!!"!!Q!p!!!l!E!!#!0!r!!a!2!!!Z! !!U!Y!e!!!!!"!!!!"!!H! +!!  !q!!!!T!!!D! !     ! !  !v!!f!P!M!K!     h!q!`!!h![!F!!  !!a!y!!!!G!u!!!!! +"!!!!!!!!!!U!F!{!!r!H!3! !!3!,!!   !        !      !!!F!8!!!Y!=!        !*!     ! f           ! !3!   g            d    _    j " ( !  $   Y b ,  G j -   {z9(#TA,H2N -  S H t   J Y I / v u a [ [ U P C            n l        `    b L p   h  X     K ? Y            , Y e _      c g  o > > R  ~      }       !!  P!=!    w J ~    ! q 7 5 B _   |    = f          v   U  G  % ~  d & F _ V k  7!     f D Z { @ V p    v   V    > d F K -    2 6 5 b N     . ;    - t" Q 4 n  _ 3  : <  i         !6!    +!!!    !:!*!    ] ~       e u   z      = q   ! 9!!        {   k o    Z   a > J s     !! !! n Y W    h i k                !   ] e x  !         +!x!!6!!d!e!!Y!8!c!o!U!!!!!!!!!"a"Q"D"5"M"i"c"{""F"Z"w""V"h"n"^"f"j"s"""">"f":">"{""""e"s"O"m"""H"S"/"!""!!!!!@!!7!8!!!!  #!#!!1!;!         p Y 1 r  u       { 8 % 7    e    Y   a  r 2 n     G e  L =    6!J!+! !'!2!   ! !     ] m    ,!!        !     !!   !     !    z z !-!!! !!       S n      !!  &!6!7!7!1/0Q[ZPAW_՚/͛uқݚKě1›^pUQ\=ϛwš(;|NMKҚ&`t"ܙ .יÙəԙk;,ɘ  Ϙ sЙ}ҙFpΚߚE7( ߚnU'@I{Κ8S4ؚʚ֙ϙYT~r-:ÚS8zu˙cW ۙ<QyQ6Ӛ3@Sә8_?E#R78=xK^̙ҙÙ̙ٙ6,/ <5)4-0qb5|ǙؙߙvۚךКr"QmcEHbNTnjn^,3*( 3%ۙיWi zɘ)bks)<KWәc]+pޚmP|ztN]}͚ٚšКCQؚ^C^ 7H#QP< 7SH$<' Bfz|dP7eT`0hzјQߗؗ0 2˗gT^VN;D0eIחߗkITØ9֘|59Q`sV%+M%ڗeB{ٖu`bv"ʘߘHjxV(P}iznh;iTA?֘Șܘ SmM%Ni1aa?ҘNjo4  <6+Q{ӗa&t8ۗU5Ж"H;TD)ʖ–ߖ%ADiЖltD ֕)G8r4>͖f|wؖZkܗ0lʘqZ6ޗ2Cw!p Wyb™ՙV}^sxuGr^YrL|ƚuښprc82LǙssI>oЙșyf@ؘ֘3GVyz^~oV×ŗa4 o{ɗۗǗBƖ(7\..VBݗ +5VҗޗЗ1ŗ̗vgcM ߗXIɗdp|%Iqۗԗn<  ͗ӗ~bg/ɗ,|c( ֖ÖٖՖ&g>&NAϖǖt"&/g9{\NCPŖ @ܖphȖ Ya$=a}H"×ߗ`*̖5\n<?1/:xٗ41!6ԗɗ{6&Ζ1&wD֖Ta@g ݖȖ—җɗJ(̖VzՖ Mٕ#?JiϖҖp|(G}3aVn  Ŗ.>*z}^!ʖז^&2>a Ε U%ޕxdI~Õ^Um 9ٕڕ|)ܔj~Plhss[klӕٕΕB Tr=̕ӕ +̕Eٕѕ•Õo!%^V 0`qΔ]`s:8-Aߓ#Г˓ܓ#sДԔk\ϔU?SZba1yl_e[3|+JRh:ĕyߕ>Օ $$ɖdA:Jɖݖ0,$45ZVLkW!3ؕ1%~X$~gQ#8VN͕ڕ(.oĕ}=0L=`zV#P^|ߕ.ɕvP1הДJ- `Εɕc8M"ΔG_;``$הǔrܔ% ڔߔ۔ĔĔ˔ڔٔ۔|~TOPv`cCt/MqĔ.ٔlUΔK?3&ep*ДД <SgAFx!9jAD>( +ڔӔΔ}\4\ϓ$ۓLhb{VxgojDQWP:Moj][H)6ǒr +ɒ " +'|E""uc9.Ē3C<MmRtv͓p.J~SœdH{lleǓߓ/^ؓՓ!n>5:% “˓iK7Zkzc:SɔlA!ғ),>2_]JՔ”ߔ'@eCHŕ yyٕ? ە-ؕĕٕەl.J[tٔ(cG*EmR`_6J@q?80"J1fړL9]5+[ܒ’Òڒ4Tc&HVTՓ-ړsݓH%7ޓד“̓oI\|Wnk=_dEKUSgdOɓSW 9)\eKӓ#=aagaaa2a```````8a``-axaaaababbaa>a```kaa}awaaaaaaa|a`aSa8aaaaaa2aJaaaba>aaaaCa``raa```/`r``a-aaa````'``J`_q___L_Q_I___I____4_a____o_#_0_f__c_^^^_^^P^H^l^^^t^]^f^o^^^^_^g__e_<_~_s__"_^_D_._j_t__!`__`~``,a2a```i``____!_z__ ``(`%`g``````;a"a`X`_v_>_^z_____J_6___a__h_______1`!`_d_l______$`(```____```a`` `_g_O_|_)`!`_`_5_^^r_1_)_}_a_^^h^.^G^u^H^g^c^v^^^^_:_ +_^^^u^^^9^^^ ^] ^&^]] ^]^5^3^]]E^^^P_f_B_^^*____y__|_~_k_7___^^g^Q^:^8^P^^(^^^^^L_]_^^^g^^^^T^d^o^5^`^p^B^Z^[^^#^^^^_^^^^^)_^O^h^V_._^^^%_y____h^7^]!^^^!_A_^\_`4`__8`-`_____R``G` `f`e`0`__3`P`,```7````y_i__________>__k__`_____G_5__``(`C_^L^^^<_@_y_y__^^_+_Z^]]]{]]^^q^<^]]]]<^V^]]S]U]]U]2]\\W]]q]]]]\\\\\\]2]5]$]!]$]A] ]\p\[\F]]]a]\#]:]]N]`],]\\\X]]]v]\\\\]z]]2]T].^0^]U]]]]]h]~]]\\\\H]c]]v]#]])]\\\\]4]\[[\i\\<]]\\\\8]]]]^]]J]]]]]9^t^J^D^]]^]]!^V^^^^^^^^g^w^^^^^^w^z^^^^P^^<^]\%]l]]]^ ^]g^]b]^]b]\]^8^h^^8^]O^ +^]]Z]\%]\\]}]]]]:]\\\P\H\\\\\\\z\\]]\\\\\[Z[[[[\[[[[Z2ZZZZZZZZZYYYAZrZZZZZwZZZZZZZZZYZYaZZ~Z[[r[ [Z[a[ [ [Z[=[p[[\[['\[[Y[[([[&\i\\]\\ ] ]&]]]]?]\\X\9\c\w\\\7]K]t]i]H]z]]O]-]]^>^^o^^^^^^^^^^5^]S^L^]]^]z]7]n]^3^(^^]^^^__=__^^^^^;_:_6__>_N_<__^]^^_^^^<^^C^^^;^]]^]}]^^}^^|^^^`^^I^,^]1]\\$]`]\l\\\T\\\S\\7]C]\}\ \J\\\\\\\v\q\B\[[[\Y\\.\[[[h[#[%[[#[f[/[ZZ?[Z[E[e[r[<[ZZZ}[[[[[[[\[[|[S[[][[[[[[\[9[E[[[[[[[\"\\[[<\8[ZZ5[a[8[ZZ[+[ZXZ%[1[ZZ[\[^[ZU[[\(\L\B\[H[u[L[:[ZZZZZ[ZZZ +[][i[ZZZIZ0ZkZIZlZhZlZ2ZZ [ZZZZZ9[q[=[ZZ[ZZZZZBZAZ ZeYdYYY=ZZYpZ`ZZRZZZZYX0YYYYXXnYhY"YYRY[`[Z[[[[[ [ZZZZZZZZZZ0Z1ZYtYYYZYZYYYYYXzXXXXsXX@XWXXXXY!YBYjYYdYSYYXXXX7XXX(X4XDXX +YXY$YY@YYXX'YX YY2YRYYYZYZ.Z2ZZYYXYY`YOYxYYYYZ/ZYYYYY YSYpYWYgYOY Y9YYXXXtXeXX:YXXXXXoXXBXW/X/XOXWX&XWdW{WWWWWW~WHWWqWWfXjXGXGX.X?XX+YXXX?XXXXGX~XXVXXaXXX%X5XLXXWLX +YXyXXXX YYZYYYYYYYY=Y^YVYYQYYYmYYZYYZYYYYYZYYZYbYY}YZYOY6YYfY>YYrYY(ZNZYYYXXLYYX Y^YYXXnXXqYXXXXXXXXXXX3XgXhXYYYYYXXXAYYXXXOXXDXWX1XX X!X+XWWWWWWW1WZWZWRWWWWW-XXpXXpXZX9X8XXWWWYW+WW X1XWWWqWWX]X'XWWWWW_WXvXUXXXX YYXYYYAYYRYQY4YYY@Y6YYYYY~YCYDYXIYYSYiY.YYKYYYYYY"YXXYXXXX YXXXxXRX:XW]H\L]I\4}]jVIU: +,-=z51+K t]Cyb7fKn,D`q%K6n`"G%ikKG{Q92"!Svr>z( S'VUgR +nP::vDT/} 1GPP]w2SI +:vhpB9eR^UwAKkW}3q'l G;0]Nq'2l}[8N "9`a:W("|LJ]\{/O$2E|8woQCS25\o dJT5[xcF}GYBeQhBI&c{VZZ`` +xIfIt )CR +/RgC@4UuyODDfX+xlDM=s |@svo7  ^:99i-`t8$$f]/k\c=^Dl-]  Q{wSGw<MKF-; bPN ]`n^|zci-7*-HxpN$5OT{{\y]9.SAGfd3 mA;<_stg1A;iZTa4Mq9a[#X^!lzb_7)'!fcn' +t%6^ vinqowc`ii'e\R}WJ ?Y-L Il|=tTMb`&\!ps%o(i_V]+Xi):".gfGctxC(6XF;FluTWVsAA{%J +*.,X\~vCp9O.RBumoun Q!;3Z^qkxP;k 3wx`_a:)-]p;x>4?9o.A!.Sc97$#"j_oD487J.1:xFtm3j}W@&/\A"6H]f~#< 3Z"r7@-cQh2'B0r Md<Og5Zy jH~EnGqZ`\|]s+n&z&NtA[LAzez;TRx>(&y(DFE"kuX^V"*(^X*R`d-EG<M,Bz/#"`K|l1$ +ASfaG_k|jNH7L">+wC$QtUegj&UTdz `o~*V"H/sXCSR"]Zpv*va U&ad#"ug@Tfv)?n}co+?QZM:46x|U-=?8d4#9>XiT~]+i[iWL?Yrm]Q$YypRK%)bSX#4ZE;IO4%k\_L}VhwIItFy$ N)S^//%9\T~^@PrB9Z)beTODjUeQ +rqynk*'qd[b-A0<V#A1SR{ FZ#~JMPh|"goxD,Xu")141uTdgl/wjLmsL*e8EsV?Brf(]4IScJr nj{O1s] x~:g,wf2srp?*M #uyqh3q}~r% #[0!Cz9hGRkfR0 a\(-dX{<Tqq+Gh(k2#,N6P 7+2g.p'#1Aj9k*Iysosn_GLF|1=>'Spg+w}2(Ocw)&{_2Q)VxI|Y -{aZ[1Pt A\ecmFBYm1N8oZ %v <S' #jlh(I&r)7'qKJgQyuW(uo~CY_!A +A(bn(u T86,t3]R^Rz<heE*EEq.*94US5Rg&.H[81u0 f&y9 +V[ \#,c 4gs cX8=RP/HpJRASFJ 4aXC,N$~VrS=]@Jq5+@R4DO@)^0y1gncgwk} Q#KDq`/ H.m+$MnC_p"c-ZJ58 QLB29(?dtp#f#>Y8|[QqgC& + +YJ~kAuk&bg>=<?/~yy.`^z#N[W|t,^ZYs.Bf){|g0#x0Y!+N,mb? I5:1C QV}gJmuG0=%n!?9a>9rW +Zvm8qslx d_-\WkJcsiuO1aCfV2MU.T ]Un\K9 Q\A|f]qt9:8Y~h?-mw.D$<.bQ[(6?&K?YovLQ\aN=gIRpz5{ev{Z{>t 3C^Sv@zW0J$hMmOHOXqp*9H~w.!'JNi*7 O ,|\Rp<SoeGct[O88'#D`q;gIZ{eqT =sQ{4rH0C#S+41[{Y kIu]n[?.dp6$AYM xVAZaFe @:B,st !o{Vv&v pEp'..;ER9x3X.(v 5 b:|8%C}dWVY`gYWAsanfYyC2.XXSmY I؛˛Tg}i.Lƛ$zTf<zכۛśś/̛ٛl"6ƛ)қݛ |Λ֜i͛Wt*OK>wtӚ*ܚz™ޙ + +/IsԚLb>%њkYЙB řڙ:QER\Jbpݚ]ۙՙ͙'L/LO?&R;?_Y7YӚ Ě{nt']z Қ|0ZƚԚ8%iʚ z! }sљa&*wٚ@pݚ]ۙ.I ͙ԙߙ OtԚd,hښКY{WRzŚJg}<wEt&˙Wl}pU6Y/'Y8_71(ՙ{iBۚEΙYkm2ؚJw-;x]4`ߚ͚~iYƙ˙zřU/1A&ݘ>9I_G;@4Z.Ƙqs͘XdӘ2!<ӗח̗K} G!/O}"2:Pm`̗YeQ\[LC ȗ—CHNɗxu-g+i,<{֘Ș D5 %) ۘi[JØ*ߙ~I .B^}ߙv[-o+8mЙoYdw%5$Eљ\1s=9't1X`Ș\<јBҙjp]ܙV0bGPeLE՘o̘2|ٗS%V/4syfŗݗ͗xݗǗ3ٗHݘsO9Tߘ]}1y,Øܘ=ř̙֙SؘؙDam=9o!3X +/ۙPev™͙0Ě,2ؘT? enFDp+͙a b̙ʙ&Ùךtb4\g1?š˚XR̚Y_>L.[@<0ęҙę}IBØ MuLbukHȗʗ8x՘d 2aAIbܗ +?-\{5_E|՗tcpޘŘsQҗƗkVGdqqG7CJT LܕĕȕVQ%ӓh~ӓ> +͓ɓ6vjړSV}Z&0?Ô͔9/ϕܕؕIݕؕUN^OG?QƖ'Öܖ)^ ' Kߗ48IÖۖϖіNxXSrc{WV*JEԔnUl~ǖpD6ѕmIrN`Օu[P͕or[riەǕBߕڕ ߕvf͔xɔה<ՓsGJ\1f{sΓxZ[:SQǓ +1+sS2XEo;ߔ{M_j͕sx~{PP}& _9(8I˔'Z Ք>ZXQOgʓۓ&˔%_x˔ߔV̔[{nȕ!K Se_H]{@e|S:іؖU\A67'˕/jS2 U)"[]}ǖɖ0ߕ.weؖV9ʕ: + E_ޕ HH.]_D}ӕmqAeva?1JY Ք>-hϕ͕og”.Ôɓѓ MڔXCGjffX@8%;=4YZKO֓3Mh<aٔ”Ôh{ؔҔ}9Ӕ@Δ(iޔV&}sm4xSF}?ǔ֔Qx ГʓޓqzѓR p[ +ݒ>Ēђ˒I*(,˒Òגג` &DHr ƑN*ڑ&6-FZ]mJ+Bx vKǒ1c4ؒxPYޒے.ǒՒ"}'xdngPgΓ/RA<]acד#ߓޓ˓`?H<Pג?eN3DXLQ}&n˔w֔zm͔qIٔ̔֔IC!%Vo7LMBel;~#A"ҔrĔMO ~/@8ؒ#Er=(B)ޒ˒ƒA6V͒i/)ˑ+aۑDBucǒjϒne&֒9=&'pXQKN9Ғ7[$"ߒ +-39S.};Sqe!h@*A/Hb}i,͓yHbɓ|aiɓzӓi~tʓē8&[`.^L> 'HD6rbfUq~M]{iyA2iXi= ?"I-V[!F||j43*&s2MP]wT@JpmO}mJ,YGE?"E%% qRrVQd~{EOgB  e^fWlyiE-2zhr"-{a& H?;5F7 O|mz0c>5yscl1$@!3C7XO3Wj>Ws[D\=yn5`e@0#q@/@VR<3N7I"2Bp5~n!h:{7(Zu&8WRHve2NGbgT +h+&'I< alM1m5#A*wnhiP2u:Nk!VW59IdQ7:Uq}ddn$ !\snvVGYa%9d"TN_S)e4A m{W(kuRpO0k`A1e4jolIm;+RV.M@_eR +  3mk+j2cI8mS7C#!0?ED_TXk|XpSc#-!LX*^;;C<c&A5&\m}mB +`l9nEPF1|odfeF&.Km*O ?QmW{UT+yuE54EQTdZ* DRAW8 EgmIc'axDvkq63n, !UD,?+'I*=xD. 3Bi]:=m=qsY~//2  "IUW}@*trt8~e U+{Q2}WRk,]+bo6d?kc >uzmf>^ +cR 9 Z]^>/^:NAy9^fme@, +1!2JLa{# 9r/um^?t}X"<GWr$Mg;}bar\ pgZ< 3jb_gY+]I8R +%8H& efn1hb]&CjcTI)?qljP-mdQ6x`^9# 3df]AB+ +qyN@(P5 eTkHe8~p{nGg + KT%! +"7=\o(1M-* hmAY+ KX9mlH{QKl~zcaHwM< vz<jv9}gz[l 'BlI8DH6-2QbBtv Qut +Q WytQVYOjZ;Qn1 V;"0#Z8! +8v^i~EBp}dYs"8[5:+Nm4brG?'dfS;)+..C@rB"-& +c59[7=E*)_R55Ilv$0ROQ_^$3U4[\G>ZM\>uSftt*?`S-49 B+[i^IWmH]V6 H9RUYYYY ZYnY|Y\YwYYY2YXXX5YcYYYYYhYiYzYYY1YXYVYYYYYYYYzY_YYY~YYYYZ^ZCZ3Z9ZYYYYYYY1Z8ZTZ1ZYZ[[Z>ZY%ZyZlZbZUZ.ZZYYYYYYYYYYYYcYSYX YDY%YYBYYY/Y +YX~XXXXUX,XXXvYYY,ZYyYBY5YXXYYYYYaYXXXZYiYZYZY7YXXXXXYXYXYY+YKYJYYYYYYYYWYGY:Y|YvYYYYxY*YCYDYnYiY=YY5YtYYxYYYYY{YYY-Z=ZY\YYZ +ZYYFYXYYX)YSYgY5YYqY$YX YY=YXXXXX$YYXXXqXXX|XYX"X XoXXXX YX{XJXX&X[XWWW@X6XWX&XQXXXXUXXWWWWW +XXW#XwXXXXXXXXXXXYXXX YYXAXXXYXXXXXYXXXXXXXXgXbX*XWWWWWXX XWXWX@X XXX1YXXW]WWWWWXWWWWJX"XW=WWWpWnWRWW#XWWWXWTXX XWWbWWCWWW(WUWW%XWXXJXWW*WxWWWW[WbWrWWWWFWWVVzWWXWvW>WWWXXXJXWWWW XXX XWX XUXXXXWaX/XWXdXXXXqXXXRXXWW.XWWWWWW:W5WMWWWXWV7V@VuVV#WWWWW^W.WRWW XWW;W5WVW8WY3YX.YYZYYY3YYX3YnYyYYYYYY;YYXXXNYbYYYYYYaYeYYY8YXYYXXXbX}XYEY'YQYyYY^YJYXXXY8YlYY`Y]Y4Y YBYYX +YhYAYXXYXXXXXWbWWW3XWWWWWW,XiXXWWWWQWWVWWWW|WWfW&WVV?WWrWWWVUVVWWWWRWWbWWWfX?XUXAXXXWWWHWWWWMXXXfXXXXXXXXPY[YXXX(YYpYYYpYYY YYYY +YYZYYbYFY#YXYXXYYXXXXXXXX.XXWWX{XX>XhXgXXX"YGYYYYYX7Y#YXX#YX`XXXYYXXXXXXXXXpXYXXXXXXXnXsX,XWWWRW|WWeXiXWWpXXX6X=X'XWWWWzWUW@WW(WXWLWWWIWtW"WVVVMV'VUVVUUUJUUUUmUUUUU~U4UT\ToTjT`T6T#TSSS6SRRRRRRRRRRRRsRRQQ-RRtRR>RRRdReRKR\RRRRRRRRRRRRSSSSSS2TDTGTTTTTTTTT?UU0U?UUUUU8UEUVUU5VUVgVVqVVVVVVWVVVV2WVMW@WEWRWWWWWWqWwW#WW.WWfWWwWWWuWW.WWyWXWwW^WWWWWXWWfWGW7WWW^WTWYWWWWWWWWWWWpWW,W WVVVVVVWVkVVVMV VV$VUV$VUUUV"V!VVUUcUPU2U8UVUGUpU^UuU3UTTTT(UUMU]UVUEUWUU U{UYUUPU2UTT6UUTTTuTFTThT_TThT$TSSKS;S@SSSfSmS&SBSDS:SSpSNS2SQSBS*SJS +SR3SRRRRRRRRHSSOSwSST T TSTmT9TT&UTTT(U~UyUU2V$VU VVU$V/VFVTVVVVVVWVV,WfWcWWWWgWWpWmWJW7WRWfWUWzWzWW+WW|WWWqWkWsW W!WWWVW!WVV`VVVvV\VZV,VVSV=VVVVVVqVVV_VVVVV3VVVyVVVVVVVVWVVWVVVUW;W:WvWdWW4WkWW.WZWWWWWXXWWWWWWXWWWWXWWWWWWXxXWWXWWXW$XWWWXVXIX5X(XWWWWWWWWXXWWbW9WWVVVW W?W9WAW?WeW8WVWWWWWCWGW?WCW-W+WWWVVVVVVeV\VVVVVVVVVVPVmVV[VUUUVmVOVgV;VnV^VVfVVUUUVUUUqUU"UfUFUTTTTTTtU\U U +UTTTTU8UTT UUVU7URUYUUTT;UTTV-VV,VV VUV|VcV-VVV.VNVVV$VHVyVVhV`VVVVV=VbVVtVUU8VZVVUUUUUUUUUVVUU{UUJU#UFU;UjU$U/UUT\TTUUTUyT~T`TT@UUTTTTTTTTTTuT{TTTTTTTTTjTuTgTXT"TTTT`T+T TSTT7TT(T_T~TTTsTdTeT\T T#TTTiT6T,TuTTTTTT U%UGUUTTUTTTUUU4U@UnU[UURU8UjUUiUTFUFUDUUUUUxUUAU'UMU:U;UUUULVwVaV)VVVMVV+VZVCV4V2VAVUCVvVVVGV[V-VVUU>VLV*VUU VFVVVmVJVUUUVMV6VVjV6VV VVUUUU*VKVUmU-VZV'VZ+ƚJp1',Cl^Z:Q)˖@^.s;ۓe<ՒaKMdݔ_oْ͒/p& &a[•wR?V1.W 1a͕tDJ%}7(!&Җ~60"aΗW2<D)55P ^jxW: {јGӘ32omkJ5GvȗƗ0"_wЖhOm *w@f]|I{fy 05 ƓْVƓϓ#`#ؓaPU+-"{0e eYpɏ+ُSG<.PDHpIǎď[ՐiwhDu5McʐBKԐHE̓oN9;Ք̔75Օ68</̓NYޓ9͔^AS  aKCE”hUjNw-הBQœ“F J qQג&MCsɑޑ"=j&ɐWnEƏsK  `j(26Rx7-8ё "ExԒ֒ђҒ| +~Ӕ!&+qU0; <_)$֓ +ג;{miyx|nؓ,ғ%ӓPߒOʒŒm(RWK2U kَH"L}0yԎ!9g6+.jpwmvU<]U4YqQRIb'MC-ތɌA'kzh~Nȍq\G׍QfFڎߎ^ ]`TCe*_x~KODďڏϏ }pRsÑcҐĐ[Ð4^Ð~ؑ+ԐȐ Pft37]_ +ԐʐT{?h:F4 ~?q.\((GώɎɎˎmpCnPڍ}Om_q;) B5܋!}Čԋ 2܋c7^tqNj݋ދD^+4(tw]%Nj ًRԌōg?}) Όƌ24TSЍ>zՎKq=*q$Ut;=ȏڏۏ+)H?c12Yۏʏ&z}ɑO3͑ ^!v # אߐCWf1A4ÏϏN/c..ŏȏlێ؎bpR{BkykL^xj1O؍Abݍl|X8.D$ -6-׍ҍ$юY4:UՎQQŏďy}=J mez_(6͐ې uvK\R&xj1:c]o`S<Eo/L|[^ ^wtD;B#07k'WTsCS_J#U&Xnb}]l=>g&H_ pY9X<er&tjWB^ cQH_z)zCy0<"KwVnS4^(@/{7]57_G,^\{-P/yA}>89~7x<\i6 -1Al6g~8,bcEg~s +A +]z'Pc:?Dk g$P#fX?;F<u8Wt:qc2?8+H9Kcb4oAB{P/">@5IK{1Fej a9/C@'-p39.w!V.iM O"}i!<=kWiBrF:du`_:LDx]*xGqj?./)!od+4R'h>x5%t 0(^~J{;-{@=SgJ] N Tg =.o!^t(1Qn>$?8 gPLd<[{EMySV'* T\\NMd'MZT/:dxd]{mNQ.?z^hy3nQ9jW#5NrJmJm gX]3O3]8 hMA_UA~3 <aevOi7|__W6) ||?EhE "V^ +nz?flS^9!s+L| |Tb,=PwkH@,ziJg#2yy1}s)@qo&Y9i/&6*0?PJ9L@[syY*/s  YVnOR'`:E9W4(dZJ+O=FKM,J-hE@q~Z~v+/m=5Lgn"/b0NQ@KmE[/Qeg8X3zS1ez%hEei{y]Yx#NP79kG H+j Hx'I4'RH?9&9JmV" +c4;)!RwORoHjl^[M>v+b~o '%iPU.@])ht2D|M +i9;vG|hFm  I=[9`lFcuq9Fy!~!:x{}rHQPrM .fiRi;%kLj @Y+O;R34:2Qa>sx\#FN#]V2Uw(% +/<"/BUAY\{f~@"lW\{&,W[[4"g'kXv=#Z1ok?|)h!-;{$#rm9t\#'Q%# jE1*8*[tMEJbIrg<DR8*UfU0jN=GxDG @}rBMr,9z'L{Zd39"$Q=P$+353#U|[Q>\وˆ[MyV* ͈vMk=Q61$CهՇEp/dхq9oj`.ه`ԇ0ׇreՆ"ׇՇo VkgLΆنe8׆jj҅rЄ΄܄+ J׆Jڅ؅Ɔi - ɆaKQ-ՆÆԅPņ†{ +3+~Bgi H8TOdc,f36Ȉ5Og".423̇؇ چֆ^p߆؆WE9 2)Յ1 ,#]ʄUoRDy؄ԃVڃU~(Gr{JԂOQ0˃؃H.'܄WKDžI\P!)Å ~j\sȄyÅ7ȆR]ن%z  )y VõEgąT`q'фT C35ҁFQZ.؀Y6wQ~~}}}}~~w~}}~\~F~T~|}|#||\}\~@~s~}}}~~J~}}}~9~A} |{ |K}/~~5~}-~W~ ~}M}|G|K{2{{Q};~~[~k}||}f~~Fx~}l}}~L*X +~~n%~I~T~~"ڀz~M~}}c~UE%%{~}~~KB +Sj T-bJ[O+_|?TV/] + +~~H~~K~}V}f}Z}R}i}}}||M|W|||||v{zzz zyWz_zKzkzOzyxAxdx_x,xBxxAxwvt,uvvwwwewwvxutuvww"wvwIwwwMvuvuuu/v +vtFtttwwxxx*yyyyxlxwwvuvvvxxy>yymxwvwxxxsxkxwwwwuwvvk}kgkkpkkkk,lylJllllzlPlkPkkkkklmmhmm nmlmAm|mmnpo8onn,oFoonooopqirqq qppyp +poooWppp+qpppppppp6q rrrrRrrRrqqpppq:qpIqgrrr.rrrer sr@rqqqBrs$szr#rrzrs sr=rrrArqrqSqkqrrsvrrbrs4srrrqqpptqpRp?poopDonoJoop]p`ppqrrqq}rrqjqq qFqpooUnmnnmmmEn_nlnnnZnn[nnn{nKnmEmOm4mmnn*nRnnooSppRpoo`nmHnnmmn?nn`nhmmwmm9nnmmnyyyyyyyxxx5yy0zyyyyyyyzzyDyYyyJyVyqy1yryLyWyyyy8zzU{{{_z9zfzczyyKzSzy z7zzzz*{{{{{{r{{ |||{{{{{^{{R{{{{{9{{zzz{2|B|M|{z|z!zLz#zyyyyyyzyxww(wv*ww2wvuuuvw xxxxy +yxxyyyzyS`SkSNSMSiS{STSUStSpSSkSxSVS=S^SmSzS:S9SaSSfS~SNSSSdSSKS~SfSSSoS7S7SSSDS_S[SKSSSASzSSSzSNSeSSmS`SSSS}SjS{SGSRSUS}SSiSmSSgSSSSRS|STSSySBSSSbSKSYSIS;SQSSJSpSmSCSS?SSSJSYS~SNSSSXSXS;SoSjSJSSkStSCS#S{SZSqSSpSYSHSDSuSoS+SSlSySSDSFSSS9SS~SlSvSvSLSMSStS^SSSSS`SStSqSLSSuS[S>SQSSS^S}SSrSSSbSdSvS:SySSSiSSwS~SESfSSPS$SSSSSSS}SDSSwSES^SqSSSSfSPSSoSSOSSzSPSSmS SySSSfSS;SSS6SzSUSPSPSgSSZSISDS^SSSDSdS!SSSkS)S SS;SBS-SsSxSPSSSSSfSS;SASeSSpS6SSZSSZS+S+SWSBSFSS}SVS}SSwSuSQSVSSS6SSlS(SSSSSSSTSSwSyS@SKS`SSVSStS`SZSS;SMSSbSgSSISmSnSSpSKSSxS|ShSQS%SSSSNSSSOSOSSoSpS^S9SNSsSSScS-SGSS^SvSbS`SgSSSS_SxSvSS~SrSOSSS`SxSTS{S~SShSASxSSSRSLSS:SSSkSSUSrSS`SqSVS]SSSSISSrSxSSbS#SSShSSqShSpS?SUSSkSSSSSrSSSjSHSS~SQSS|SdSwSsSSpSSYSSiSSNS8S5SZSjSQSSS\SSbSgSSS|SUS7SSfSSaS SSRSoSSCShSmSwSSSSSSSSXSKSSSbSSKSXSSS|SuS3STSSbS*SmSS8SdSvS\SzSS'S}SSZSSySSSrSSSrSZS}SSYSoSSpSmSSSSYSVSnSkSSSZSoSSSaSS>SaSqSSwSSSlS=SOSoSFSzSmSSUSSzS`ScS_SkS^SSpS1S~SSBSuSqSvSSwS|ShSLShSSSSS-SVSrSTSSSSuSSxSSSHSYSSSSVS5SbSVS#SoSSSSSgSSkSmSSpSgSKSSeSgSUSASySSSSrSKSPSSSRSWS|SQSSSRS}SfSS.SMSFSDSSS]SfSySLSGSSS~SeS0S^SSfSySQS~StSlSeSSeSSScS~S?S0S\SSSSSSS]SpSpSuSySiSS~SSS4SSSoSWSESySbStSXSISSvS_SSSSXS2SSzS[SESSSSxS0S|SSQS;SSqS*SSSaSzSiSbSSS[SSiSgSSuSSSxSVScSSNS]SjSKSSvSSGSTSSSSLS_S$T|SSSSESkSDSScSSSSSYSzSShSFS}SxSgS]SBSnSSoSGS4SSSSaSVSSzSuSTSSfSlSsSS]SSCSSHSGSOSzS}SSSdS]SSSSSSHSSSSdSHSmSWS4S_SSSQSRSLSSSxSSOSSxSqSSUSISESSSSSdSSOSzSxS`S,SiSSoSoS^StSwSS}SYSSjSYSPSSSSvSiSSlSZSUSSVSSSSBScSSSSSfSSUSmSSSSS?SySS/ShSaSXS^S@SkSSDuuttt.tsssosqs$srrr^s-t8tthuvuutt"u9utsPs@ss)ttutut tEt7t ts&srsstru(uWtsZsrrJsssussssYttuuutqs(s}sstt tsssrrsosrrstss1tsrZrqqqIrrNrrlr9ssssQs:srGrnr>swsrZrq[quqrqbqqrqqqFrrws-srsrcrGrrrrrDrArrOrrr:ss(sqqQrrrrmrqq_rZrrrrrq/qsqqrrr s_sssstIt'tsCsKsllllllml"lkkxkKktk,k +kjj*jjIj/jj=kkejiijPjj`kjn8nmzmmmmllll1mmnmmmnbmLm3mlGmm'mlllm&mmml.llymmmmm5m&mllll0mllElhllmlclll_lk_kktl2mmllllWmmmxmmm9nwnnnnn{nonvnnGnnnnpopsppqpzpppppMppoo]ppooodoLononnn oonnnnCnnnnnWn:n3nnnXnnnnnnon onJnTnnnn!oooo p8ppIpomo|oioSoCo"onnoOoGoooo(oo_oooooooCpooboz$zyx,xwv=w?x9yxwyyyyyy#z$zyyz z)yxyzyzuzzyyyyyyyzyMyxyxxwv v%vuuvwwtww6xw)wwtwwnwgvuuv:vq2rr@ss|sssrrs-ttttsDtt\uucuu_uuvu]vvZuuvuuuv[vvvvuuut0uuvTw wv(wwrvvcvvjvuuvFvvuDu uvvv wxwwxwwwx?xxRyMyyWzzbzBzyFy`yyyyzz"zzzz'zyWyyzKz!zy zzyzzj{zrz[zyyxxyySzz{z2zTyxQxHyzj{ {3zyxyxxxxxCxxxx +xpyz"{={ {kzyKyxzx'xwpwxxx xlww2ww_w!wvwxwv0vuujvcvv\vvut`tss0ss^t8upu-utitssssPsrsszrrrarxr s.srq_qppp0qqrrQrGrqqwqq&rq/qcq rrq#qpxpvpp"qqqqqq rirrsr,ssss_snss$srrsrTr#ssdrrkr tetAsRrrwssst2tJttuuu#ututu$u4uuuvNvxuguu ut utttttouuuuQvwv[w9wvvvpvkvu uRuuu8vutttttt9u6vovvvu*uttuuu'uttuuYukuu|uIuetstJt1tttssssGtt[tss/tss%tsssZs&sr's6sr[r$rrrrrqqzrsrrrrrrvrr;rqqqcqqqqp qfqqrNrrqvq$qppppooBpoopononnno^pjpozozoonnonmKmllrmn"nmmmmn%nnNooposouo|o%oon!ootthuukuzuCutu^uttrtDttYtbttttRu"vuttttupuXutwtOtssstt uttssryrKss-tt4ttttttttttsEt1tfttuu=vvvwvuuuuuFvuuuuvAvMv|vgvvuuu$v9vuutu|uuukuttjuuuuuuuAu"uuttututttt`t?tXtLtottttssssss?tssjscssssssGsssss^ttttJuuFvFv*vuuYuwu-u;u=uuZuvv}vavxvv^wEw9w5wwwwwwwwwwKww[xTx x;xxxlxxxxxxxpxx yy4yxxyxxpxx/yxWxBx5x]xyxxyxx=xwwwwawAwlwQwWwww xBxFxww w_v]v wZvvvvwvvv~vvuu utttvttt utTttt2ts srr_rqqq`rcr[r{r}r~rArr ryrvrFqpp5qqqqmqqrrqlq qeppfpoorpppoooooopp.qqqppzpppppnq%qpp\pXpupqKqpfp pCpEppqp]ppppqXr7rqq-r&s:srOrqqqqfqq;rVrrrrrrssss#srrrEssiss-sspszsttss5srrirrrssNttt!u7uututt`uu uttYuu@vu3uzuu +v%vuvvTwxwvQv9vukupuuMv&vuPv>vkvvvwwwnw wvvvv3vuJv v[v`vuouu]u!vuuuuuxu uuv vu7vuJuttttt tNsrrrrrr +srrEr r!r&rGrKrrr`rrqq\rrrtrq>qcqqqrqpIpopoopBpooovoon!nZnnnn n_nnnnn0ootoooooio>oBoEoooonnn onomosoyooopoJo1oKoozopowooop2ppRqppoJpppptss9s>sssssstlsssstssst u~uuyuut4uEuwu\utmtttbu@uMuuuuuv:wwwwwVwaww"vuuu^uDuuuvKv3vuuuutPtytttXtNt+ttssssssssssrrZss!ssstszsTss9srrrsesGsrrur/rrqqqqqqqqqqJr4rqUrrrqMqpqqrJr rq7qDqmqJqq +qKq8qHqrrp_plpeppuqiq$qpp1q +rgrrq:rnr}rDrrrLrqq6qpoqqqq.rgr|rrrrss\srrr7ssr5rrr[r@r?r\rrZrwr5ssss5tsKsUssEt{tssuttsftqttptssttttdt{t>tjtu7uuuuduvuQutt2VUU8V%VUUVVUUUU!VVUUVVVUV2VVVUVU*VUUUVVU>VUU V#VUUIVVUU VVUVVV%VUVUUVV1VUUUVUUVU$V/VUUVVUU(VV=VsVUUVVUU.V +VUUUUVV4VVUUVUUULVUV +V#VUCV:VUUUUVVUUUVUVVV:VVUUVVUUVUUUIVUV6VUUV?VVEV>VUVUVUU?VV)VUV3VUU VVUVUVUVV&VUV VUUUUUV;VUVUUUV+VVVUUU +V$VUU0VVUVUUVVU0VVU VU%V>VUUV&VV V>VVVUU-VUUVIVVUUUUOVUUVVVUVUUVVVUV1V(V VU0V.VVUUU VVVVUUUUUU V(VUUUVUUUUUUVPVV@V VUUFV;VVKVVUUV,VVVVVUUUUUU%VVUV3V1VUUV(VV"VU)VNVU +VVVVHV0VVUU2VVV!VUUV/VU%V&V&VUUUVVUVVVVUUUUUUV V +VVUVVVVUVVUUVUU VUUU VVEVVU'VU*VVUV VUV+VUUUVVUUUUUUUVV=VUVUUUUU@VVVVVUV.VUU+VVUUUUU-VVGVUUVUU:V*VUU VnVV+VQVVVUUVUVUUVVUUVVUVVUUU)VVUUV +VVVBVUUVGVBV.VUUUUUV"V +VUUU-VJVUVVU V VUVUHVVUVUV VUUV5VVUUUUVVU%V,VUUUUUUVUVOVV#VUUU1VU7VGV VUVVVU VVJVUVVVUUUUUUUUUV(VUVVVVVVUVV%VUUVUUUVUUBV'VU VVV,VKVUUUV#VV V+VUVUCV)V!VUJV1V.VUUU%V#V-VU(VVU-VUVUVUVVUUU9V!VVU +VVUVUUUVVUUVUVVUUU%V +VU8V1VVUVVUU*VVVKVUUUFVUVVVUVUUVUUAVUU7VUUVUUU:V;VUUUVU1V3V"VUU VU)VV4V$VVVVUUUVVUV VUUVFVUUUU(V#VUUUUUUVU-VVUUVVUUUU$VU0V VUUU(VUUU"VEV V VUUVVVVU$VUVUUUV*VVUUVUUVVV8VVUVV7VVVUVV VUUVU1V6VUUUVV'VUUU)V?VVUUV +VVUU +V*V+V?VUVVVUVUV0VU VUVV:V!VVU4VVUU$VUUU VUUV +VV +VUAVVVUUUU,VUUNZgfp|t  + + + +    +  +  +    + +       $   + $%"##'*(%    ze\NSXeONK@?>;==IVf__YVIXeqq    + +         "  + +  +     + +      +  yqXP=EQfD:7.02*.,9I[PVG<2ER[\z~ftk}  +   +  + + +      +  + +   +    #   ! + %! +  +u_TCJTdJEC979214AM^XZME;JXffw{        "      +     + + # +       "&'$#xcYHKQ\HFC7662/4@IZSPHE9IVde{~            +   + $        + +  + +      +  "  "  + tlWM9BPaC58-).('+7CTPOB>,=KZ\xw{lxq  +  +   +   + "  +          +  "( +    +   %$'!" u`WGKR`JCB624100?HXRPGE7ETbb|w{     +              !#( $   +   !"%"  uaUEJNVEFB7661.3?IXNKGE7DScb}{}x|   +     +   + +  +  +   +      +     +   + + +  x`TB9,.6@0,-!&.<44..+9GHb]aUd]jry   + +   +         +     +       + + ocSI;?EP??;-;IXZspshwo{ + +         +    +    + +   + !  + +  + reTL=@FNBE<4231.3AKWMJFE7DS`_xuuq}t + +   %      + +         +    +     + + +        +   xj`PE8=@H;<9.+-)$*7@NDA>?0=JYYqppculy   !   +  + +   +    + + +     +        +  +    + +wg`OE8>@I=B?4352.4ENXNLII=KUb_wwxlzp{     +     +     +    + +   +  +             $  mbQL?CIQFMG<=?<:ARYg\YYWO_ivpzx  +      +&   +  +  +    +  +  +  +   + + {yydWQF=.58A7;4-'(% '9=K?@>=0?MZUmqpWk`mty~  +      +  +      +   +       +  +  + +    + +    ye^MJ==>669IRc\\YZM^gml}~t +       +  +     +       +$ +  +  + ##!ncTTYcRTNAB@<;2210,2AGVLJFD7FR_`ywywy    +            + +    "     +   {o[PADFK=A;/00-,4CO\UPPPFT_ml}}{z +        +  +                 +   +  + {o[RDFHN?D?312208JTc[ZUXO_kws   + + +  +    +            +  +  #  +    +    + rgRJA>2020/6ENZPOMKBPZjf~~{{   + +  + +   +    +     +           + + $     +  + +   + + +cYG>036=064'&''(/AKWQOMLES^nl +    +       +   +  + + +   +     + +    + + +  odTP>@EJ>FA66654=PZe\]ZVQ]jwtzy + +      +     + + +     + +   +    +   +      + + +         +   +     +    + |{wqz    +     +  +        + + +     + + +  +         y~njcbbox~{y|~vx  +   +      + + +      + xleY[_g^g^KDIB@HSZdWWYXMS^kk}rx}z    +        +          + +   +   u{}ywnlcdfu~{w{u~ + +  + +   +     + +   +  +  +   +       + +        {qu{stp[^k^UKasunqvjq  +  + +    +   +        +    + + +  + +  raad|]``TUWKIMXenb[aYf +   +  + + ! +     + + #    + +      $!  + +   "   +  o}hOoq|pvr[XbJ&7YlydcZqdfokr    +        +     +     +  + +   zndegqclfZWXPOS^hypldmdow   +          + +  !  +  +      me]banbe\ROVILQMXup\ZgZbozx{   +  +    +  +   + + + +       rh\]aj^e[QOQHJJQ]slb]dYdo}y + +  +  +    + +  +  + "     +  +    +   +   +)    +&!  +,#   % $"$""#   hdmrekkkYedOOdF#;^qLUfi\_gnmvhdky        + +    + +  + +  +     + |kcTX\gW\VJIIB@>KZmb[[_U_kws       +     +    +        +    {h^PTW`OULAAA<;=KWe\ZXZN[hut~       +  + + +  + +     +      +     +  +td\MOU`ORN@>9::7GTfXWUWIXanmu +     +   +    +    +  +     +    +        +rc[TFINZCHA2."-15AHTMLMB4EOW[ulqsrj{z +   + + +   +     +  +   +  +   + !"+!  +  + +    +##   +  + ~sa[LQRWMRL>>>>?HYboefc`Zft~{ +    + +  +  +        + + +       +  +   +  +    + +rjZUCKOPHOH><<9:=NWh`]WPKXgpl~v~sz  + +   +      +    +   + + +  +  +  + +  +  +    + +  +  +  " & +"$&  !( + *-( %(.3.&0 "$  ~up]`claf^YOQOGL[bn\cicXfpw!  + )           +   +   +  +  +  + +  + " "  +       qYYLRPVMSI3<<9>GS_jg`URW`kxty~w~     +       + +      +     " # +  +    +  |gZRY[\RWQA4?=?JXdme__cVhp{}| + + +    +  + +         +  +$    + !   +'!" +  ,)& +) +$    . +  $   zvSLZPVPXLOG?06E]hqhH=eN]isv|y    + !         +   +  + +  +     +    #       +   +~laW[\`V[SIDCDBL]huidej^kt   + + + +  +    +  +    +  + +  + +          + +% +   +oPWOTOUQSG")+(1GYd`SVJETejuo~zxxab}   #  + +  +   +   +     +  +   % +     !  +     + + +  +mf[acf]bX\X6FISclp_fk_nv{      +      + +   +     +      ziaT^Y]WYOIJ=14>Q_jfL1HR]eroxutyt +  + + +     + +     +  +    +     + !"      +  + + + {whnnujofXZZYZ^nvwsptkv +    + +  +      + +  +     +   + +  +    +    +  + +   +*    +    + qnbhjmeh_I58LP[pxxmmhkeqxti + +   +         + +   + + +     +        + +   +}ot{wzoaikfdixy{xzs{ +   +     + +  + + +  +  + +   +  +  +        +qk^dgjcfZPOMHJWdprkgaa^gpzy  + + +       +  +      + + + + + +  +   + +  uhbSX\\VVNDCB=:BOX^WZVQLU\klxur}|   + + +   +  + +  +  + +  +  +   +     +   + +ywhnornldZWUPOXhpvlohgcjpz}   +   +     +   + +  + +        + }trplkp||   +    +          + + + + +  yvmlo~         + + +    +   + + +   +           ruxu|ufge_^cp{~{{s}      +           +    +  +     + +  +suywymjga_dq}}|y|u         + + +    +  +   +  + +  +      + +   +   + +  ykmpwlsla_^WW[htwvtvnz        + +    +    +       +      xmpqynypeb`ZX\ktvtquny     + +      + +   +      +  +        + + +     |sehhpcjcVVVQNTcn{srosju      +  + + + + +   +          + + +ynccfndjeYWUPNSal|qnmnit~           +  +  + + +          +   +     rh[\_dX]YKKIEDIZeskjgg`is~y +      +   + +     +  +      +  + +    + +  + + wk]adi]d_SQQKJP[gvnlklep{         + +          + + + +  sh]_`h[d^SPQIGMYftlhdh`lu~ +! +    +  + +" + +  &   )$ %# +#"))"&""nfZ[]`U[TIJFA>FV^ogfdd]it~| +    +    + +  + + +   +  +     + + + + +       +    +  odWXYbU\VKIIBBHT^pgebd[ht|   + +    + +   + + + +    +  +     + +  + + +   weZNQU]NVPCAB<<>LWi^]XZP_kvuy +        +        + +           +  + ~j_RTV^OSOC@A=:@MYj``\]S`lwu  + +   +    + +  +  +    +   + +  + +  + +  + ~h`SUW^PVPDDB@;?MZjb_]]U`mxw         +   +     +    + +    + vdZMOPTGMH;;:97=MXf_^]\Tdnyv  +     + +   + +       +    +            +   +}r^VHLNREKE97887?P[h`_]^Wdp{y  +  +   + +  + +  +          + +  + +           }kcVWX]PXREDEB?DU_pfdcf^ju{       + +    + +              + +!      + + +xe]PRTXLRL@@>=638+%('&%#%2&"      +  + + +       +  +  +   + + + + +   +   + +  +  +           +        +    +     +    +  +    +           +  +    +       +  +    + +      +     &&-(#$)(+/6:<E<4122/2?FA3243.,.1/;0%$#$($+%&"!*%     + +  +       +     +  +      +     +       +     +         +   +     +  +#      +  +  +     + +  +  +  +   +!  +/# + (-!"/>@BA4>PMPOP[friXXTOKXks[7G_eZTJLN[K@<;>759/*+-.(*0,&&$ #&%       $ #       +  +      +        +  +  + +$ + +    + +        +  +      +    +  +  + + +         +    +  + +    +  +"'( !!&%*(1-"%)9:7(-&", + +    +  #  +    +       + + +  +      + +    +#      + +        +      + +  +        +  +    +   +   + +  + +  +           +  +  +   +           +   +    + + zxzjuh\@+%" "wpplhr{ %*,,+4@[_WY^gac`ju     +      +        +   +   + #   + +     p]V[OH&!  '68EMT]\`fbfu    +  +      +           +   + +  +    +  |kgPE;==K;B?,)$#-7%/Q^_MAGFNUyzRF`p;GTRaBOASSJ> 4A:- +7%"*$$HQ06# +9]8/;E31;K6R`\P >"&1=1 HK'(RZP\I,2CKR<." J8$ ;  +73)$?'x)l0,<@@>&)6WB=MX#=XP6/3Wmq{suQvr~v%.88),06, 0,N{}k + "_M(,./8<6# +*6),(21 1)-9E%2I]M<itOW\kxNS(9>/EH=?"  ?L9*5" 631KFI!LYPE:K\R?OJFrsH8I>C<1)072Xk}{f_B@SdgdIfsQ*:SPRH@S[_lqRN`EM\V^JVOmncN :NZJ6ZkO7 )&4/<5*0;5?,C8)/,(E\zVG4@T4'>[=' 7/0OaQNM^[n`/!0KddQHEG8.4I.(#/OQw_.7!Nyl\B$5:*8$ .%E<&%2Xhrpt|upazfzePn  3=32P;  043)DGceP *  V? -)#,9B6'3&) #! )&'  (AO@ (AljA dYZeVW'<5$ +5;83 1H>),!) 4=+ 6<8&/25!)I=:QfG%.G,1.*!-$FZmbwVD;7BIVgBL[Q*)K_LKBPSMGxvZeVY:EU_[@KAd^O?,:HK?%>K96'.,'%!#.$(/,!=?2)%$$:0DIYdrwlS0%"6<9-*$,HB#;<SLSC"($@NI=#/0! + *$ +  ,14!''mn: +64'?J16D)4P8/WC/3:OVuxjdroij<7>-A4 -%$*>P` +P<+* $#5BD9&5%" "$$# +$>K8(Gmk@ dbfn{X[ '42371/ &=:' +%?B39>8,/66$)G=7LdL,0B2?4.)$1+JXnh^HB!7@IXrLU_V62TdWTHTUUW~hn`fOV^jfNULkaUJ8$<OLE(?J;:)"//&$#"*%)-'89(!0(79FP]^bF  *3-%'$>>$8BXRXD%*#HNI@+24% +.#-) * + "$5;7+#mh>)640DO57C)8YG7bU.5@VVi|hm{|q #M>?")A5+$0<Y[a"#$            ~~}zsz{~wuqtu~vv|xpv|wrjjvr~s|sl~tq|s|}u{y{v}prr|x~zz{|tyvx~z~vfpxuvdqpjlf]hmbVZZRXIRefhcVLLOSPPLJDDTPPTAV>JHLNKFF:@/2CHH8*6**0,('$#" +!$   # +0+0start  +  +  +   %   &   ',20#"   !$!%*)221)*,2')"/%     %  +'! +' +"       +)  "  +   +((',1&" & $#" +   $$ +   %"% !!    !          + + +     ".&#   +  "   !+47=;! # #()$(#!*    !..!(!*12564/.09/.&/-!# %(!'%&+ !1& 1,-/#3-' !& !$!! $$5)+%"(."('"$!"$#* &4015802# .4)(#! $.,+++ +!#%&0.   "##1+$#'(+-,1,,*")$     $("!!*!   + +   (  +   &*! !5*)*   3 +#'04?>$$'" ),.*4//'. + "'$  *),3(.%582:<8235:4=0H3$ "#%   +"$($&( -$0&4/! 1.( #$   !<  +"$ ++&4)(4?/#%/!!(&&! ('  #)! -#  (%"+!&/ )%   $ "     "/'#    + *  (05>:! $'!(%"(  +'+"*1.353,(-4+0$4)     +  ""#$ -" *$+( + ,&! ! .   +% +   +*!!(.#!%    #!   (##")$"$$    !   !   $  +  &"&()&$$"$##*5/%$"+    (! #+6@CIE.%+-")$*-2-1#,,,(8*#   + %(67&+0,5@?A>@:7:A88/76,,-$" + '(!'%(,(:/"%%50/!+  +.(# %!!"$" #$3  $'"(.!'!!!")#1*-00(-&*#&(%!$    +(   """3+%"(+*/02/*'! %-*     +%&"" , $ !) + $!$    + *#  +  )$* %4-"#%0  #3  -27EA"##&-(-.%+.%  $& %&65(-(5=9>>B97:A6<0F7!'*&%!#   %'(&'' 2%!/*2 (  0($! # %1 +&#$. !",$5&,59).,3&$ ***$% "++ () "& $4) $(),+/.+,!(1-% + +  #%*  0,%,  +      !"#0*#! ,  +  )   (06?;!! $('+('(2&    + + #%56"*-(3=<>=@988?89-83('(#   + +!""#%1&*'*$   -%!  ! !-  #(& .&+/3&,&,#!#!    %$  + +  +! $%('""+( +  +   $ +   #  +   +!  +    &$"# " &1*"! )   %  !-5:>;&&&$%).*/"')*'8+#  + "13#)+)2:;::<::;A:7/151.*# +! + #"  % !6( !#1+*%  -("#!#!- #%"&+! #*(++-%.$*$"##" "  + %"     -!! $&'%" ''  + +    +   +   +    '%*   + &"   "'.4/ ""*  + +   **!(202/3/0/6,,#*(!!"      +(     " +  +      + +   #&&## +    +    & + #$$#  +     + +    +  ($#    +!    "(/2-!#"/! +   )($2-./0-..2-+"%(&#   + +  + +   , &#   + + &  +      +#    +"$&'#  +  +  +   ' + "#%% +    +    +  +      $ $!$.*!#!*  &(().371 "$%'%%()7) +     00 %$"'20124../4-+"#()%$        2#!0)$"   1'"  )  + !$# '(#  #$&))#,!'     + + +!    +  ,! "!%% +     +    + +   " "#+(#!#.#,*.% +  &-23+%&) "%%3%# +  +   +#!1/!$""+82327363930&'..('   $  3-+$ "  +.%#! ! ( %$#& " )'+-,%0&,($%"!!   &$ $% !%!"1&### $'*,!!0."  "  ( +  +        *&!)  '&*!  +#)02,!!% ##(3#   +/-"##.)+,0'+,3-)'($" + +    #  + + 2 -) ! +  +/%! + + # + +!#$%$"(''"-"$    +  +  +  ,   $#**   +   %    + +      "%(!"'! #$(2-))!- !!*+1# +  ).372 "$$'!#%&+6)"  %#64')%#'2/../*+*3,('+%# "  )  2" .*%* &9.%#$" & + #(&" ,+'! !"##!*! +   + -" !)+  +   $   + + !#     #  + +!% +  *   '!$ "'&   $    &      + +   +     "$  + + +   +  + $   + # +  + +       +"   !"#$ '#(" + &(,%  +! #0 +    2-,*,-)#**0('&+%#  + +# + .  *""  5'        &!(& +  $$%'#!."%! +!"   !-  ,&" +      '  +  + +  %$.*        #!"!                   + +   + +  + +        +    -&# + +   %  ""'4=?D@(%($%(+&*%%"#1" +   + #'78(*.)3<=??=767<42*/1,)(!* )*!'!'+%7,!!2-*-  /(#%!#.  + $%*%"!*()*)$' '"!#  + #  + +  &  & + + +  +"      +    +  + +   +$  +    (1264 - +    *)!#,-/./(*+3+&!"%%    !  0%+(%(   +*!"!!'&!*  !#'$ !!"""     +  ! + +  +      +  $# ! ".&# +    $1:>B?*(*&%)+%(#$#!0$ +  +  !"23%(-)1::;9=444<20',,%"" ! +  $'!("),$7*! 1-,,  ,$" &!- $$*!!!*&')*#)"'!""# !  &!   ) ! $(,$!"  + + & + +    + +      +  + %   (-033,"   + ()"#,-.+.'&'.% +  * %    % $ %%('%%$ !  +   +   # +!$    !   +            +&! !+3475"# $"#%3( +  +-*!'.0112/-/81,%%-+)& ' '& %%' &8,# #&3-)(  .'!&" #%)"%! !"/ $ ),!("#! !'$'%"&     +  + " + "        +   " +   #'$"$$ ! %1*"!'    $1;?DB+"() % %)+*,"''('5+!    !#14$+-,5>@AAB<<<C:6.450,,#! %'"(#)- '<0%!$&5/-(  .'"&"!#(!%  !- !%!*-'#" !"%!-(+-,'-"'# $$#"# + '" + + +   -$"#!&(-)$'%    '  +! + + +           + +%% '-1/-  %3' + + +'""""## !%/'#%*$"!   + -#*'"&   -#!  #+ + + "$)%##!    + +         + +   +       + + + +  !!*"! +    +0598$#! #'$&"&)*:,!   --"%%+6698:547>71++00-*" ! + #$ "& !7, "#2-'# +   ("  !& *  +$&*# $%(%$'   +    & !$  !  + +  + +    #        $*+/) !# ,6&   (!&'&()(*+3*&!#,,)"%   1  -( # + + *!  %   !)&$ "   +   $  !   +  +       +  +  # "! ".&!&   )/5:6" !"'#'"&')8,$ +   01 &$#+55778455<50*+1/+'!    ! "4'!"/,&!   *# ! ( + +#!)*"" ##'&&"* $ !  +    +    +# "%"%%       +         +   !!)##  #$ +&.262""$"$$+:,%   -+ !#--0.0..091-&&/0,)  !   0#-)#$   ++" "&  +# ))$!! ! % +  + & !  #$  +  +   +    + +        +      *!$ +!()&,151!"##+9,"  ,+"')*()()-30)#$.1+)$&   -  )&"%   .%!! ( + +%#! ,+ '$!$"#! (" +    + +   ' ##%'  + +   +      +    !  )!$    + +#$   %,04/!%2$ +   /, # ",-.,0,,-3,' ('"! +       . )#   +!-#   # " '(#  &  +  + +   ( ! #$ +  +   !  +    + + + +  + $!#,$"!' %*,  + +,26:5$# $$&$''+<.% +  !#42%'*$)0/1./-,,50*##-/+)#%  " ! +3' "0.(* "#*7,'$ &" . $-($&#10% ,)!!$!)!  !#&&'#-!&""# ! +  + +   +  ! !1&!$'&" +.     !(    +  % )# !' #(+   !*-1- %3$  + 11!'%"(%(&*'&$-'#%(%!     +  ) '&#$ #1($   + , "!'%! !!#!*" +    +   ," &*.# +  + +   +    $     +    + +  +   +    +  +             +'   + $   +     +   + +       !$   +   +      +    + + +  + + +       +      + +    + +     +    +   +    +   +  +  + +  + +   + #$ +   +   + +  + + +  +     +      +     "      +  +  +  +        +      ! !     "    &     +   + + + +        +       +  +    " + + +       +  +  !       + + + $  +  + +  +      + " + $'" ''*% ( (#$%!   )%  "!#"2( + ',  + + '" #)  +  +     +    +  +    +$#   ""%" +   + +    " +    +    + &  + !  # +  "   +    +    +      #" +  + +      +     +    +  +  + +  + !        +   "      +       +      +  +#    +        + ! + + (    #"  "  "!   +!   + " +  +#      !    +"  +       +  + +     + !#!  +    + +     + %   " + + +  + + ! + %! +" +  +      + $  +  +  !"##  + %' +  +   +  " +     +  "!   +          !&  ! # )   (*'()     -  **$&"70    + $ ! / + + ), + 0$ **$+ +#+3', +(.') +"&&"*$)" "$ +%  %+,  + &      ##&          +  +  + !#')'#  +      +  % %      +  +* '#  '  $   & +  $ ""    # +  +#! + + +        +  + +! +          + +  #   "*  *-!  +   +'  +  # ! +        +& #  '  ! + + +/  +/##) '+#&&(#''$!"$,+   '#   #'2 + +    + + )  &!  +    +     +    + $$-/*%       +   + ($"'!#&#%&-%!!$! $ ! 2(!/*&/  *$"##/!#)"# "+)++)$+")"!!$-+ + + ,&    !/$ +  +  !"%!$.% + $ " +   !  +!& " ) %!%&' ,3*!!*&!$1-#(''%&%># F:'+$.), %" *2"'=I6!1+-#('$!')""=4%! &6= $ ')4,+,/,++(*<7)(!:TNKB<?G;4+5>:1' 244A5'&0*"")*#$18+2144!)&$2G:.83;BBB<3%-J))G %%,68F;75$ ":2,(*09.(!*%!"*!)%A,-+&  )' (+(!' =G383--6!"!).++"&4)+H5$%2=7 & (!*<,""(<%0$ + !  #&"% ""    +   !   +  "!  $*,,*  +  +    &#"((),)'(/&#"&  +"    + + +,! *&#,   +'"   ( + +      *()(&!&$ #(%   ($   +  '!%     '  + +  + +   +   ("  $!(033.'   +   )% )-/-0,*,4)'"')%$  !  4&#1,)0 !1*"&" $!"$  !!- #& )+!)$! **,*+'+")%"!"$#$  *$    ' $    "$ !,        + ! + +  " +    &'+) +    +  +  !')('"""+   +  +    % + %  #  +    +       +       +%'#&%#%"   "  + + +  ## +      ! & + +    +  +   +      + +)"! + + $*%#  '/240     ! !)$#.//.+&$1''")$ & +   + +  +)  ,"  *%!    ! " !#  +  '/$+'#-%-$)$#  !(%  %!-+!"%)&",0  #  &      +  $   $&   !&,3+ "0"   0-!$# &)%'&)(&%.'# *-*% $ ! 2&-(%* !'2)"!!"   + $ +!'%" %    +   ! + + $(  + +   +   !        "!* !(!&'-    +!(*3* %3    2,#$ #%)#%&)'"$("!      + *   + +(#'1(%$ + +  ! %!!&" !"$$#-$&$   +    $-#$ ! $09& + +   +  ( +   + "#    )&"#$! (##()*&"%7"# &*)#+3 &+*&#!, "-+7/ ,//2) !"""%*&$'&,7*(!  "&))A9,.%&-58<?>68:A950/8>95* !-"!%!#"$*;0 &(/$.@+!'&79,$3$!&")*$#$0G80/.$%#'/-*&%%$ %,%$ ("!" "6' /4*'#%#34($%!%  +&&("!-!)# +        &     !# $      + +   +#! !, + + %0+" #0    + 2-!$ '$!!! ("!       +' + +& ( $"%$   #'$  #"%$  #)$-!%"   +!(%-!   +   !  ( +  + + +! +   +  + +  +  &,( + )2. +#"0$   +   -)"# $!%&# +    )  + +% ! '    + + &  +##%*" +  #'!    +    +% -# +     +  +  '   + )B!    .     &' (  !*!  !'<0 &++'   !$,#)" +$$ + + ,$%,%'!"($)=&%     / $!"5:1>!+&+#& !<+"&&  ,! /2("(*#$#'.*+* ""*3  + # + %  #! ''& %860   ! .F3%  + % +!&%+ + + +   + + +        +   !#  &--  (.* $/"  +-) %!#'!    +)  )'&#+ "    '  $$$)$   !$  +  +    +    + ("   + %%   +    $  #      +  !   + + %#  + ) + + +  *(    +   & +  !  !"'* &# + &-#)  + + !  +   +&    +   +    "%  + +   %     +     &"!"+% '-/  %'.+ ( %0# $* + +.*!(.) '"!$      + )! +  +%'#"1)  "  *  ! ( %$!/"$'" . !!( -  + + +"  + $/ .% "('/ &  +! (/ %  # +   + +  + +  +  +    + +  &$($#       &   %       "  +     +       +   +  +  +  !   +  + +  $  + +    +  +   #!" +  (,2& + &)'  , +% *( "#      ( ,' & +  (   # #*&!    +   +    +)#  "     + &    +  +*    +    +( $ " '"%&+.! !#*,  %"*4!    0+"'&&)#!  +    '" $!   %%   #%  #"(*'  +#+ !     #!     !"-%  &"       #& +    +  % + + +   +#  "&" +') +  "%  *$.  +/( !!       +  +) + + + ,&*  % / &-"% +"" +   $  !   *"   "      + ! +   +     + + +     #'      )  " *'"   +    &     +     + +   "%"#)"! #       .$ %% +    +  +$  +  +    + + +   +$ + "# $ ",,  !!/" #)    3-!!#)&#"%"# #!   +    $ + ("'    +$  + " "&%!#!(-,'%!-'%)# *' + (##&$"&)3,!! +-    ! + + " #+     +  +  + +   +      !"  + + #)  + 1,!&# "" "  +    "  %    + "    +    +!     + + #  " )"   #$ +    + +"          +   +    + +   $   %& #)*() +   &   +  +   +   + +   +   '  + +# +" +   +  +   + +           +       +     +  +       +  + +    +    +    +  " + +$"  %&&$!  +     +  + # +   +        $  + +" $        + + +    +   +             + +     +      + +    +    + +   +    +  !& %*-" + !*./0-  ) +    + $  +  ! * + ($% +  +%   +  & +!"   +  +  + +     +     + +     + + +     +  +   +       $  + + + %&%(++' +   "   +    %  +       ( %! %   +! + +     # +     +  +     + + + +  + +    +       +       #%  ")+),/.,   &  + + %  +"  ! + ,  ((!&   &  + &   "$   +          +    + +     +   +  +   + +         "  +   %$ $(+(&        '   +      + , + '! ' + $ + + # + +          ! +  +   +          +     + +        $'  %,.! "*023- !*     + + '" "!# -#+)#(   +*# *  +  $&#  +  +      +          +       +         $  %% )-0-* +   #    '  $ +    .! )%#)   &    ' !$" + +   +  +   + + +  +       +          "  + +  &*%*,+) +  + )    # !!    + + + (! )&#&  (! +  " + % +-!)& #!"&  !!$             +  + +   +  +  +  +  +      +   +%$ + + +  &'  +0120 ) + +   + + *%!   )"###  1(.,&)  +#!!*  "%)$!!       +     +  +   +    +      +  + +   + + + +  %*-,)  +   ! +   + &"  (!     ,!)&#)   %! (  +  ##! " "  ! + ! +          + + +   + +   +$ ! #$ "-%"$$." !)12&!! $"'-6:==<)##$(%)$''-9+$ !!  "51!"" %+,+**&(,5-($&-.+*%"!.## +$'!!'& ""' ';0&!&+751$ 2 !(5.%#%)'$%&! &,%!'!" $#%%2!$*%#$-1%".*$!$&#%)# $%%#$ ())&$!(" $"#### %! + +% +       +   " ! !" */230 &  +    (&"%#"#!"#,$!!"     /',*&( +  )!  + "$&%!"#"# "        + +   +  +   + ""$  +     + !  +  !   !     +         +        + + + + + +             &#   + #! !/6796 !#/!    .+"(,/,+*)+4,'!")'#!" +!!# !5*"/+))  ,%%! !!(%   !. $ '+ ($ $&$$$"%!    +    +     +  + +      + +     "! + +  + )0130%   + + +*'&(((*%&'/'"#!      1',)$)  +)#! #"*  +!$'&"!&&'&#&"  !#  + +       + + "       +    + +  +   "   + +#$   "(+-,  +%5%    &"   #+'!'*%#$   + +( + &%$  +*"   & "%& ! +        +    + +   + +    &" !&(  #',1, '5(  +  +'! !!*&!'*&$#    ( + (%%"-%   & !(&# +" +    + +#  $$  + +      +    +     + +  + +   +  +!# + "'''%  +,    +   ! +       "  + #   $     +      +    +        +  +  +   + +     + + $! %*+ + + $)/2. !(6'   *'*% &,'% (  + +! ,'")%/&"" ' +$ ()'$  !  +    +     +#$     + + +  +       + $%#!$$    $"   064 + + + &%/- !(#$"--  + (("+$"#%"  +     %  + 9-" *'  (*," +!*% %   + (,!-6%$0 +  &    + +    " 1-  + + %  $%               $*, +&)-.*  $/#   +  ("$$$"$  +   * +(%(  ",   % + $#"   +    +  + +  +  +    +   +   +  +     + +    + +   # $+- "%,0- $1#  *'%!$'# #  + + * + *& '#.# #   &  +#'(# +"     +  + !  %%     +     +  +   + +   +       #$ !'0/$  *-13- %1#  )$%$%"!$  -#,)%("-%  +  +"%'$!   +   +   +  +     +  +  + +   +   + +    +      " &,." #(,/* +$0"   +)%$ #'#"# * *'#)#-# '  "%("   +   + +   +  !  +  +     +  +       +   +    "  %)#*24'"!&/3762%0# +  + *%#$%! '!#%!$ +2&!0-',#.'"!" ! $"0&))&$$       + +    +  +  +   +  +      +       %)/" + &*-+)   -    +  ""  #$ +  *#&  +!   )  "%!     +  + +     +    +     +        + +     + +    +    +  #! + '/1# "$*,( #.  " + +*'#!$!    + ( ,(!%!,!   ' + +"$)$     +     + +  '    "     " +  +  +    + +     + +    !% + !'./$ )-.., +!,     % +# * +&"&  (   +*   !$       +   +  +  +    + +   +             +   + +    +  +  +  +  + !$ + '.1%#'**(  !,  + +  +(#  #    ) +(!'   +#  *    "'!   +  +   +   +     ! + +    +  +  + +     +  +    +   +  + + + + +    +  $ + +&,-" #'(&&   '  "  +#! +    (  '$% + (  + (    $     +     +              +         +        +     " +  &+."   #$##  +' + + + $ &'  "    +      ' *&!%   +   +  !")"     +        +"           " + +      +     +    +      +   +  +    +   + +          +    + +       + +      + +     +  +  +    +  +    +        + +    +  +'  $   + + + +           * +  +   + +"      " + +  +     +   +   +   %    +    +        ! + +  + !  !$"   +  +#    +   +    +   !   "           +   + +   +   +  +       +   +          +    + +  + +      +   + + +!  + + +             +  + +  + +  +    +    +   +         +!     +    +        #   + $% !%&%%  +  +  & +!         +      + $   "  +   +    + + +  +        + + +  +    +      +   +     +  +  +         + +    +   +    +  +  + +  + +  +   +        +$ $*+ + '+,,)    ) +!   +# + + + +      %  &#$    "   +   $       + +   + + +      +  + +       +       +   +     +       + +     +   + ! +   "   +      +  + +    + +!  " +       + +  +       + +  +  + + +  +  +  + +   + +    + + +      + +         +#    && !%$$$   $  + " +   + +   +   $  #  # + #   +    !   +    + +  +    +  +   +      + + + +   +  +      + +     + + +  + + +   !   %"  + +   +  + #  +   +   + +!   !  !  +             +     +    +    + +    +    +     + +  +     +       + +  +   # +  +!'(  + #!!  +  +#  "  "   +      + "  &!#  +*    ) + "' + +   + + + +   + + + +      +      +                &   +  +      0"     +  +3%    + +   +/ 5 ' %     ,( 3         8! *   +    +  % +  +   +     +  +    +     + !   +  +  +     !#  "   &+& +'" %  * +  !4$% #!  +   +  +& ++'#'  ",#%5$ + "+$      + + +  ' +%     )  #!           +.$       " + "%!   + +"1& + $& )." +!  +##  +  ' # *  -  + *    " #$(" !  +&       +   +  + ! %  !       (2       +  +     %  +      # + + + (  !) +'#      + + "  (!   + +#" +   + #   #  +       + " '!      +  + +  +  +   + +  +      + +     + +    +     +    +  +   +  + + +    + " +      +   +  + +  + + +   +   +  +     +    +   +              +    +       +   +   +  +    +       +  +   +# '     +      &    +        %    " $ + +(  + "     +   +   +   +     +  +  +           +   +              +   +     +  +  +   +      !   +      +   +  + +  + + +    + + +  +       + +        +                  +     + +   #&     +'  +#      +  +  + + +  +   +   +      +  +    + +  + + + +     +   +         +    + +        +    +       + + +  +  + + + +   +      +  + !  + +  +   +  + +  +  +  +   +   +     + + +   +  + +         + + + +  +      +  +  +      +#     + +  + +!     +(   +           +      +  +   +    +  + !   + +      +     + +    + +  +    + + +   +  +   + +  +   +    +  +     +  +            + +     +  +    +         +     +     + +     + - + +   + +   + !        +         +    + +        ')      +  )  +  +  +% +  +  +   +      + +   +$ +  * +   + + +&  "  #!     ! * $ +)% # !'"%$   + # +%,  +   ++  &( $ +%  !)%& + + + " #$$ #$     + + + +  +  %  +      '#    !%       + $% +'##  +  +"  +    +('(  + +   &!&      &## # &% & +   + + # # "    +'      ! + +  +  +       +         + +!, +  *9"0++#!$   + + $  &  + + + %      + #.! $   + +   &#  + *!# &'   +   &!  +     +#      +   ' +    #! +"!  $   )""!&   72&'""$')"$(!   +  + )  )(% %! +" " "#%)"$(&$#, ($#,## ( $'  .,! + ++  *!)"   %$ + #  + $ + + $#%"!   + + +     +               +   +& !'  + 0,!    +     " +     +    + +          + + + !  + +    +  +         + +             !   +  + + !  +       +         +   +   + +   +  +     + +  +      +    !      +! + +   +    +    + +    +     +       + +!  + " +  +   +  +     +    +   + +     + +  +      +      +      + + +   + $%"  +-)(  ( +" +  +  +-% !#'&&%#&&#-""      %   $ +   &!    + + +! "! + + +  #)&'!+!(%!$  )$ +  $#  2(!!  $( +      $       + +   %   $  +!    '3   %!" + , + + 2) (*$%%&%%*#!$%! + +   +   # + +% )   )&  +      +  + + )(%"''!    (&  + "1" +    +)(  +    '!x|F,1']Y,yhp/ *021=Qf_2-3(:01;HDg&. !ACGCC=JZnR!3;D..PmnyFO.' <^KGV~jra;<I[R?1TeDAXkLVM6ErR^7@C85I\jAJX_oX1+<BEvW$#EMDJ]T\8#%(<<AGC H[gEVm"EW-/OE-/)f\E+9* (6*:"@8L1 ?6%Q45/"; .8/U62Y*1/00 *QM6?-:1,'X;-./QZFU+37)4#%0G<  0Xx{]=U@<%"!.(,++>>sh 2%)@EWQ<Qll~wEJlcE0&* /Y[_eLGR9GLF'#1PP8CafB2';7**4EUVJUJ"+(.LgkNmXs{41')4#'*-ERn\?| $!.,-UT]e QtFk 4>N1?HZ~7'1*KIH`_;H0@)2 ;dRcTcbjr|O8B<SKT]svdtY\MCszo[\ZkvqpbECAawe\jhNfPJdcoRU\VewgV]cc]B7LWcv7828/Zlv`V0&"1-EUdga[nktIP{uNDK;$7joYP=HB8Z]S/&8;VB@@9$::EWD021/ifbLJ3(-6ND,'9LPK.0,8#$*a9(+7\hMWP\+FA;9>:1+8ciQP8acv^L7fZ0,@>.)5S\Y]A@Hz6 6B +$ILekYc|vXn\ZUE*?TdP[^*>/ ?M`g3.1*& +7@<LL[b[@00KH*,:G^fbV@4AGWzybsavM>VO"2*6$F^n{U* +17AIqv +%.TIvc*/4#$-AC\V6+3%&#)MJN !:B>8DN[Zjh>1"*>ThmptGY/3#)YnkjWLIOcXkVTKbjC.%OG?<^bCJ.)Hp{pY]<CL57\nkEH=NaM1)MVbY.  +8ZjSF: #'8BLPC , :PmQYk'$PJ+9I1,[T4,+))(?<P6 1? +<#*'3,**'I8:=P0+"2.'%HO?($':# Q6#(TX:LB7?+1%&BE0#*Ths^B G8'0&$.+375$,8}`(F%%17P[S[oo|ETmYAKIM(:RSZgJ?P'04BF*$.$ 909=a`S+ ++;C$6`i\B/"'9VbS[f{2(:&>?+,5< !?_npN 4&+9:cfxx+.+>i^,zr/.-:-(<JP]\A5;*/ 7-?bW_6* "0MCLKW[dctmB9OBAL]vZi@G9>osedoq~mnbx|cGAkigcdhQLfpz\`lNWu~^_WaxqQFas~q.#G<=,Tu|p\T#) #.+,:@V[b]W&/?6Re_h~?7]]DHZH4GumHA1:6),;>C@)4RNgP'HM(+ R:/>6@<.9<5SFHAI3';,%>??'0Q\N>=8M;-*fF-:>aoO]TL +"3MFL448490QUH<+AqqX.[VA :5.>63GIF24BPvo$"8T25GSjhakvUb~lSb[[5HXX\oVL]4">=FR3*1.+ ,JBNKa[Q6  0-HJ6,/FcfaM5*23B]jb^l}1&>%?A24@B%#C]phH<=FLTwt                " $'-&$() !"1%#  "*'." $$)"%'   + + +  + +  +    # ##$!  %.   %  +  + + +""!#*$"-("*"#&-#' :)-#*&#%'(-+%+.-) $* ,((.$+$& ,&#"2+0""06( ,,$*,7-242& ;3<42@96..4-4>BGMHQRGBBO[^XRUZIFR`T_dhebc\`f[]omnpln}i~spzxqrznnu~vusjrs~zvsty|{|~x}w~x~~ueuy~t~~}}~||r{+1+0.13440.2560type A  % !        + + #'  !      +  + +   + +#!     + + +    +  + +     + +   +     & #"$(#& ' $! !%'''  #  +   $$  !#&,%$-#+-"'&+)" +$  %** ! " +   + &)) + *&!        + +        +  +&   !"'$"       (%+"  + " +"%&6 + +.#    +%'  "$ !  ") +$$'&   $   ,  + + +  $&& +  +(*     +  +    +   - *  +     +        +   +%" %'!%    $%,'    ""   #&  + !!' "."+,$$*(# & +$((  ' &  +  +)*(*($    + +  +  +  + +  +    &     " !     +  +(+,"$*'$,-0) $(+&!&.& #('-%((!&*# .*#- # * &!(& +  &&    $'#&'1('/( ,0(,/""!0,) $&'. + +  +)-*! %!',%) + + (*,  # !&2+(     ! +     +    +  -$ +  #"       !((/!& )03)")$'!%+" '$- %(!!)," !/2%2,% +)!""+,#0/#  #&&(,"#, *+&)$*+' !+ +!)" # *   + +()+ '&%  ! + + +  +!  + +   +  ""' +   ,!   %  ! # +"     !  + $%'!#'  # $"#!%(' (  #  + !     "!   + !&& #"# &  !  +"   !# + "   +  +  + +       % +  +  +       !   #%" "       +  + ! !$# + ) !    + +     !%  (   + +  +  +  + + +      $     +                        + +   +  $    +  +  +  +  %   +              +" +             +        +      +   + +    !"(    +     + + +" +    +  + +      + +     & +    +"  +  +   + +   !#$ " % +" !"     ! #$&'! $#+ ! !!!#  +  #% +   +#  +     + + + +    $   $         +   %("##*)"#'"$""# # $        + +      $&#!&#-    + +" +    $) + &  "  +     +   +    +     $ + +   +  "  +     +   # + "        +         + $   +     + "           + +      + +     #%&  + +  +   +       +   +"$      ! + + +  +  #(   #  +  + +  +   +  + +   + + +# +   + +"*"    +      +   + + +         +   + +    +           + +# +   +    +         + ! $        " +  &      + +  + +  +       + + +    +   +   + + + +  +      +   +   +   +       + +     +  + + +  + +  +   +                      + + + +   + + + + +    + + +  +   +       +      +        +     +     +    !#'"$ ! $&!#     "  !   $' &+!#''# " + !%! !  #   +  +  +!%'+%   + + +    +   + + +    + (  +   $"       "   +   +              "    +           +      +             +    +  + +       +   + +  +     +     + +     #     + +  ""#%)!"$& # %%% (!($ %$ #   +$'   + +! '!!( &+%$')& !") +"'" #%%% +     $(#.'$    + +  + +  +    + +*       $"       +  + +         +   +  +  + +       + + +   +    +  +          !  +   + +  + + +    "      +   +     +#       +      + +     +       +  +     +   + +  +    + ! +  + +  + +    + +  + +  +   +  + + & + $/#   ! !" ""#%$#          + "%  # +      +   $  %  + +  +      +  + !        + +     +  +    !!"!   +!   +     +     " +   + !    + ! +     +  +  + +    +  + &     +  +  +       "#"&& $$#$ +  !    +  +!  &   !   " +   +  # +  +    +     %  +    +  + + +   + +  #$%!#! #              & +  +# +    + +   #  +  +          +     +!   + +   +   #!%& #!'(!)!"&& % "!   # +     +!$% "%%+  $'%!%#''   #( %  +   +  +  + +  + + +      + '    *"            + +  !  !        +       +    '  + !  !!     &    +    +      + + +   + +$ + + + +              + +  + + + + +    +      +   +        +   + + +  + +     +  + + +          +     + +   +        +    +  +       +      +  +             + + +  +   + +  + +  + +    +   ! +      +    +  $)  ! "&'$#""'   +   $)! #&#"#*"""*% "%$&            #  + +    + + + +  +     ! + + + + + !"     +  +!$   "   +   + $-   $!  !"" +  + +" + + +  +     +  +  +  +    +  +   +   "   +  +   +          +      +  +     +  + +     + +   + +        $  +#           + +   +       +  +   + + +   + +            +  +     %   ")       +  + % +   + +  +     +  +   +    +    %"  $%# +  + + !   + !    +     + + 2+   #  +    +    + +       + +     +  +  + +    + +    +  +     +   +  +!! + '"!  !   +       $  +  +  +   +  + +%     + +   +  +&   + !!       #%   $ +   '*!)(.0 *.($$.' " ""#   +#& +  +    #.        +  + !   +!     +   + $ '!"" "!##% !   $$ #'*! + +-!#%%,&&---3.).!#0(!!&(*$  %& +   + $  + ),0 +   ! + + + +   + +  + +  +    +  '   + "/) $$'&(        ++$& $#!(%)+&"( !" #  , #  +   ,-"  +(&1')$&"'+*323//!!% ''(#"$)    +2+"% +   1& + ('#  / %  <*   #   ) + !"7,   +  + +!     + +   !       +  +      +  !## &)%#%& "   +      "$)  + + +            +  +    + +   !"!  "'$& &!"!"% $ +   #%   +#&#$*"!'!'+%'()"   # +  !#     +  #$   "     + +   +  $   + +     +       "#! $ +   + !  +   %!##' "#       +    +# !%' +  #     + +  + +         +  + +     #! $"!!!  +* # + + +  !   +!#   +# !'$""     + + +  % +  +    + #    "     +   +  +  +       +     +     + +    + +  #   +     +  +      +  +    +          +  +  +      +     +        $  + # + +     +   & + +    + +  +   + +    + +  +  !  + + +   + +     +    +  +      +  #$%  +    +        +      +%.  + +       #$ +# ! +    + +  !   +     + #,   +  &#   !  +   #  + + +    +  + +    +  + +  !  +      +  +      #& + ! !'  +)" + + " !#      %')"*&   #($! !!*   '  + #  +      +   +      +     +   +  + # + +             *, +  +$+(% .! +1 +  "!+' '' + +  /' +"" .,2, ! +%  %6# 1+ 0F* !%( &)*" *# +    "  +   + +   + "   +  + +   + +!  ' #   +& +  +,:   . +"& "  + % !"  "'"(# + !  + "   +    (%#%) +  ! +  +  "! + + '   +                +  +   $   0     +    $$ " !#'    +  +          !  $        + +  +   +   + +     +   # ! '" (5 (%  " " ,!   +    +  3 '&  #51  +   # $    $&  #'  #" +        +  +    + + +  + + + +  + :   +(   +           +    +  +   + #        +"  + + !&1  +&      +  + +  +   +          +  +  "! %!  +   !    +  +  + $   !!&       +     %  !%  +! +   + +    +       + + + +       +      "1 + +      %#    + (!!"( #*"# +  +#& !%   ! + ! +" %"   + +&)    ! #+    +.  +     + !            + +      -         +   +     +$" +  ! " +   +  + "     $     +  + !  "' $  +#%'   +        +       +    +     +   + +!    '1              + ! $) '#"!%+"!! !!# % " +  %%   +   !" $ +  !#  !%$-  %  %)+ ' +       +      +    +  +   +  +    + + + %'#!&$%$ ("",%"!#+#"%$&# +$#$!""!%#" &*)   % + # "") +   +! + +      ) " +!&$  + # +     +        + &$      + , + + '""#!"+;-  " !  ! $  !  !#' %  $    %#   +! ! + +     + +    + (  #$      +    + +    !"  +  + + "  +      /   +   +  +     +     +  +  +   + +     +   +  +                +  +#  +   +   + +  +        +   +  +       +          +     + +  +  +    +  +    +            +    +  +    +    +   +  + +        +       +  +)          +   + +  +  + + +      +  + + +       +      + + +    +      + + + #    +          + +          +  +      +    + +    +  +  +   +  +  +      +   (   + +  +   + +  +      +      + +   +          $!    #         +  + +   + + + + +         '  +       +    +       + +     +  +    +     +  +             + + +    + +  +    +   +      +     +      +  +    + +     !  +  +" + +  + + +  +   + +  +      + +   *  + +      +   +     +     +   +   +  +  +     +       #  +  +        + + +    +"   +    ! ! + + !       +    + !        + +     +"  +      + + +              + +   +      +   +!  %!"   +"   +  +        +#   +    +    '    +    +  " +  & # +$ !  "%!""# + +%"##  +  !'  #$ !     #(   !  + ! #1'#  +   +   +  + +    +   +    +    "   + +    + + +      + + + !      +   )     +           +   +   + +  +  +  + + +   +    "& $!       +  + +    +  +   +    +   +  +  + + +     +  +  + +       + !"   +"     +    +    +&   !        +  + (      +         +   + + + +   + + + +      & "#       +    +   !%   +  +   +       '! +         +   +      +    +          +         +   +    +     + '    +    +    "# "   " +      +   ! !) +  "       #       +  +   +  &     +  +   +     +  + +  +   +             +     +  +        +  "#!"$#   "  + +    "!   &         $ +         +  +  +   +   + ,!         +! ! ##&)!""' !!',"""$+ % & "$ !  #     (# #4%( " + + !  +#'''+-(//"! &,,$! ,   !!     + +   +     +   + !   + +  + )6+  +  +      + +  + +        +    +             +       +  +  +   +)  +   +      !  !$&! %" +   + !     + $! "#)     +     + %   +  +       + +  +   +   + + +    + *        +    +  +  + +      +   "   +  +     +" +       + +    +!        +         !-#   +   + + +          !  "      ! +         ! $   +     +   +"  + +       +       + +   + + ++      +   + +    +  +      "     +  !% +   +     "    +   +"    +   +   +     +"/$   +   +  +                  +       + + !    + +           +    + +   + +       +  + + + )  +  +  +       + + +  "'! $"     "   + +   #  "!&  +          +  +$   +  +  + +   +   +    + +!    0  + +              +     +  + +  +      +    + + +  + + +  +       +   +  + + +      +    *     + +      +  +  + +      +      +!     +     $ +  +   +     ! + +    +  + +   + +  +      +  +   + ,        + + +      +  + + +  +   +  +    +   +  +  +     +          +       +  +   +    +    + + + +   *           +  +   +          +    +  %    +   + #   +$ +    + +          +  +!          + -  + + + +       + +                   + +   +    + +      +  +  +  +   +  +  +      +  + +      + + +   +     $   +  +  ! + + +! +  + + + +       + +     + + !  + %  +   +  +  +  + +          +  +   + +         +!   + + !   +     + +              +  + +     +    "   )      +   +        +    +  +       +   +    +   + +# +   +  + +  # +   +         +        +   +    +  + +         +     +      + + + +    +  + + +      + + +         + ' +         + + +         + +    +   +   +         +    + +   + #          +  +"     +   +     + +   +         +  +        +  +  +      +  +   + +    !    + +& + + +  + + + +          + +  + +    +   +       +     +     +    +  +  +      +       +   #     +     ! + +  +    +  +    +     +       +  +  +            +   +     + !              +      + +   + +    + *  +   + +          +  )  +         0       +   !#  + + +%&   '/4   + ' +    (0 +       ,3 +    + .2   %  +   #  +  + +      ! "' !$   +   #  !  +!# !!    #&  + */ + &$'-  -  +  +     +  +   + "%  $#  +      '  $ +  #*2  #      +   "% +%!#  !$ !! !"    +   !! "  + + +  +! " + +  )  "$%-   #! +   !  +        & +    + + !$ + !-  %    "      +   #! " +        +         +  +  $*  + %)  "  +   + +    +  +  +  +  +  +      +  .  + + +    + + + +  +   +      +  +     +   + +       +     + +      +          +    +     + + + +  + + %*# % # +   +     +       + #  +     +   + + +, +  $  +         # +      +   + +         + +   +   &.!  + +$  "   + +  (    + + +     + +   +     +      + !   + + +     + +  +   +   + + +    +    +   + +    +     +    + +     +"    +   + +    +   +  +   + + +   +    %  +    !! + + +        )0   & $   # "  "" + !$$ +      + + "    +$$   $" #*"  ") + + ++ &$ ! #'$ + " )-& + ''(         +     +   +    +   + +  +   + +      +    +     + +   +    + + +      + +   + +    +      +  +  + + +   +     + + !      +           + + +  +   + + +  +    +     +  + +    +   + + +    +  + +  + + +  + +   +  # +  + + + +  +   + +  +    +        !  + +       +        ! +    $      +  +  + +   +       +        + +  +  +   +  + + +   +   +     +     +   + +       +   +       +     +     +   "  )4- +$ %$ )$  *1"!0.  %"%')(' +%$! %6 &% 75$('$ "$ 2  !!(>8( ,,) "$ /6  &)"'#&6&"  ! $%1,%0*1.-)" '1!"+ )4 $&'(,&"& (*#"#%#.# %# -$!.*##,& ("!"($&!) " +#"$#4*  +,461*473*! %)+,+.!#!$*2+%$#+&'&/.5;4$#,#".(  ' #.2-)4.," #)$ &7;(,#  +$ +#$!'&#'! + !    ' + + 0+   +  ##      +" #   #! +    ")$ + + (%  !&$# " )! + + #  "'(/!&%$" !  +  %  +   * + + +   +  ! +     +   -/ #   + +%#(2$ ""&! (   #/ ,"  '/! $$%  + $#(!! !!*'*&"(%!"%%("*0$(,#"""$&!"&!+.*  %% + * "%""#/! "..'   !"  #.3" %)1"* # #   $  +$!/,   +   %  +( #  '!)*+$ 6$# "# $($ "" (  !&#&!!  +$!!! $%*)*$%!%*$'(% +%.3" $,+0%!"")++) ! &&'"'+,2/  !!$($ $#'!  !!$$&1'  " "$##--*)%+-!!5*#&./.-$ "##& !!"'1 !$-0) % %((''!- $"% "&")+ + &$ # #+! #)! ##$0/( (*)# &%"-'"+/()''00#$&(*$% +"*'$ !*)(&/%! "" $ +    +     !  +  "! +  +   +  + +   +    + + +  + +  +' +  "    +        +       +     + +   + +,  +             + +  +    %($&#     (%   #! '   "!#     +    + +    + +  +  +  +    +  + + +     +  +     &  +  +  +    +    +     +   +  +         +  +    + +   +  +  +      +                   +%!$    +  +     + +       +    +   +    +# +      % +       + +      +     + + +             +     +   +     +    (     F+/1;8#/1-%-><8]4i'2>68>H9;N^lpSf*+1CGTyt7G100"*(PYpHR/+?/!$928;2ZDM 03% +)X[ /3>) <9+:+86J;.#F<"+"6!(NV< (:A?H9 $;-$5!+ 1#-,QAD0 +,# MR &0H<-(*%)77HEE,D< +U$ /3<IRNdYZU8>T<-8GNF2  + +  + "||<!F^W`8p":`]# %2m(u6P?.{ew_:33P-0]uzQ?aOohqwSZOt]D\F?Fy j[CimJm^fO.'?/*S{mpSA@-&?8===)5DTSPxn2Q[B5HTHMihd55.@4`sA N/8EKci`]425# &C]a"B<<S>P48! 3*'* 05Uk/5311/-QcI;97A132.2R]W[B+ >GH<4JQ32##.?VtS2DL,%BJW1 EP6;>iid+;[B!56k{@55%PQ@YM=)5ANYjpv<0+2=X\%W7?Y_B7GIdcpshaf6*5S\KD +?1%BAW CWRB32 v{QR]Y\|,9PMB}eB 8P0?D+(2*2-AZ^S6C@VA)X\F5:BSQQghgN04NAB>GR[m}zX'C\?ug6UPZlpWFIrbMK4\r]cgTbqiLIei_lqy[A7 !6'):77*"0EKPw] /67GNV>=]{GO1;-KYsK 8!",("Pws4;$#%)B9"3,6 2 +  .2-& #DD!) ),B)#"'@BAD  "#(*+9A $)8"$1L<?/'   "@c!6J8 %2$  !QVL\4! 4GP%^M-<396VOj\]S<.K449RJ8  '.  $)313$2% uw F1IYy $9;j\A QI)+ $B.# (Cb.06BHMZgYH.) $-/H<DaXLfh,8SK'$?+Ada=+/c>.B)U@-XjWbNDXD"LQ;;KTfH:$;MJGQSOE/9Iefdm!*JTQdinWYpcl93R]0HbqP+L:5<A@=Z~NYG3HB&+(+BZY+>KFO7K64 )391(4 $ EJ')+0=>%24TU5504?E[IB>B\VV[,*$,5,/:?;2B$.BOY`6 5&4.,D2GD6GPeUX4-6J@(%'23 Sh)$.I_B'=K<3##'.9=`nfoF3>"1L_a(  *Aoh2BOIQNf[}rpdPBWD8FLbaN% (#:(H/!# 6.-)" $;C9=3;' PG$Tc,".JOnV% +"aY>;.D+:1/) :[k7%*)9BO]RbqhZ5+= (,>;NAKcfYf]1JRTE>Q=PfmN=ApL;M*<cVEeyikYIWH,,O]9;HT        ~xy~z|~xrttvwy|snukxfr|orkqypebioo^_gkhkjdh]df\S\X]VcWcZ_URVWVPLJJAALDD7HJJHQPPHDD46=9>;25E?=844=**8DGD4JRVNLTV_eRLTZa`peYnnlbbZjsj{njdbZpvz}x|lvvppylvnsut}yxt|}tsqnz~~zrgdY:.$ +ykd`+2+0.39041type A  +   +     +  +    +    + + +     +      +   + + +  +     + + " /$"'%'0($   #&  + + +   +   "   +   ##  +  # +# !((    % $!  + +  !     + +     + + + + +      +    +  +       + +%&*!)   ),)' + +           +     ))      (   " !        +      +  +  + + + +  +    $%   + +      +  +  +     +     + +     + +  +  + +  +   "  +         +  -!$"$.&#  &&            + +  + +        "      +   +  + +  +  + +  " + +  +   + "% "."#)$'2$$# &! **#! +     +       !  +  + -- +  +     +%&$% +   (  + +     + + +    +   +   + +    +   % (   ## +   +       + +   + + +   +    +    +    +    + +  !   +   + +  +   ,  #%(0+)#  ""  +  +               +  + +  +      +       +            +  +     +  +  *!'!           +     +    + +    +   +   + +  +   + + +   + +    + "  + +  +   + +    +  $%-'#  +    + + +     +     + +  +  +       +      +   +  + #       /&%&(!*/0850'! "    +  + +#)     # +    +  +!       + +      + +     +     +         + + + +    0$ "#$))/-)" +#(& + + + +     + +      + +   +      +#(          !        +     +     + +  +   +  +  +   +  ' '&"  +    + +    + +  +   +      +    + +   + +     #    + + + +   + 0%!$*)30,#          +  + !   +  +  + + + +    + +          +  +   +    +  + +           *"*)$     +   +  +     +     + +  +             +    +        +     + # +       +     +     +  +   +  +  +     +       +  !    + +   +" *!  + + +                 +  +  +        +    +     +      + +   + + -"!')/&%  #   +  #   +  +  !      +  %  !#    &!   + " +      +   +  +    +  +    + +    +#"!*$#  +       + +     +   + + +    +     +          +      +      +   -" %'.('  + "#        + +  + + +               +          + +   +       +   + +    '#"*$#  +    +   +   + + + + + +  +   + +     +   # + + +     +    + * $&*.)*   +    + +      !        +              +          + +   + +  +( #$*+3.-%   #  +     + +      +  +  +   +     +   +   +   '!"((0,*#          +     +   +      +  +  + +  +  + + +  ###,$%     +   + + +  +    +  + + + + +     + +   +  + +  #      +   * "$%&,.80.% +   +$   +  +          +      +   )    +     .$&&'").1942+   +!"!#'*  +    %!  +  + +   +!  +       +    +    +      #     +     *" !$$'*0*("          + +"     +     + +           +      +   + +  +  +   ( &  '/,         + +           +   + +      +   #   + +     + + +  + + +   +              +    + + + +       +    +    +  +   + +   $     + +   +  + +      +   + +         +   +  +       +  + +  +    + + ,    !($/$"!##.))% &%,+.%$ %"'&$!$  $!'% # "   " #!  )"&)"#)31!  +    &       !!# "        + +    +     +       +  +  +    + +                        +      + +   +     +    &%  +      +       +  + +     + +  +   + + +      +   +        +  +  +    " + +   %    ,  +      + +     +         +  +   +   +  +  #  +  +     +           + +       +  +   +    +           +      + +     +     +   #  +  +     +# *&! +         +   +   +   +    +  + +       +    + +  +  +          + +  $ +  &  +    +   + +   +         + + + ( + + +  -  + +     + +  +  +      +           +        +   +   +       +  +  +  +    +   #  + + + +   !  )!  + +  +  +    + +  + +    +       +  +  + +        +    +     +  +         +  +   + +   + +  + + ( +!   $# + +    +  +  +    +    + +        +   +  + +      +       "  +  +  +        +     + +     + +      + "!$%       +   + +  +   +     + +     + +  +  + +  + +   +  +    +        + +    +    + ! +       +  (  +      #"%!  + +    +   + +  +   +%    +   + + +       +  + +     +   +   + +  +     +   + &  +   %%         +  +     +  +   +   +        +      +    +  +  +  +         '   +  + +      +     + )  *  &!  '-+01"!$))+**"0! '0 $)) !#,$#.#),3 +  !#% ) + &   #  ('(# $$ $$  , +  !+ $-%$  # "' +  +  #  #&(  & #$+*'& &%*&  ) "! &54 + "  %!   ! +#!! $5"& %!*$  + '    +   $!   +     +   +     +    +  +    +         +    + +  +          +  +          +   +   +        +  +           + +      + &  +   +'  +  #    + +      1       + +     +     #!   +   + +    4 + +   +  +  +         $      +        +    + +  + +  &     +  1  +   +      !   + +    "       + +         +           "    +    +  $    +   +    +  +   +         +      +  + + + +        + +  !$    + +  + + + + +  + +         +    +  '  + +     "'  + + + !      "         +  %  +'  +         +     !# " +     + + +  !       + +     +   +  + %  +     + " +   +     +       +     +     + +  +!" +          +             +  +  +      + +             + +  +  + +     +  + +    +  + +    +        +     +        !           +   +    +# +  +          !  %     + +  +!  + && !%)$/ !"&$'  !)' $"## ) ) # !&# (#&# +  " %! % !-,     &'   % #!%* ( % #&'+%"$*- +  * $ $   +     + +  +     + +                        +   + +      +   %"    +  +        +   +      + + +  +   +      $ +  +   +  +      +  +     +        +        +       + +       +     +  +      +   +            + + +   +     +       +      +        +     +    +      +       +  +      +                  +             +   + +  +          +    +     +      +            +          +  +      + +           +  +   +  +      +       +        +  +      +    + +  " +  + +   +        + +        + +    +    +    ! + +  #  (!   +   +    + +    +  +             +   + + +   +  +     !  &!  + +   +     +  + +   +        + + + +    +  #    +   +    + +   +  +    + +   $   +  + + +    +      +  + +   ! +    +   $!"*#"        +  + + + +   +      +             +    +  +    +  " +      + #&   +   +  +  +  +   +   +    +   +     +  +  +   +     + +   + + +     +" #)/)"#      + #'    +  +  (   +  +      +  ""             ' + + +     + + + +  + + +  + +    + + + +    +   + +%  +    + +    "#   +  + +      + + +    +  +       +  +  + + +   +     +   +  +     +   + + +        +       + +    +  +       + +   +   +   #  + + +   +   !   + + +  +   + +     +   +    + + +  +   +      +  + +     +     +          +   + +    +         + +  + +   +    +  +     + +  + +   + +   +     + +   +     + +         +    +   +   +$ +   +  + + !             + +  + +             +   + + +      + +  +      +     +  +   + +        + +  +        +  +     + +  +    +   +     +      +         +        + +  +      +       + +  +       + +             +          +  +  +     +    + + + +   +          +       + + + +        + + +    +   +  +  +       + + !   + + +    "   +      +  +   + +      + +       +    +  +   +  + +! + +   #   +     +  + +  +  + +    + +  +   +   $   +      +  +    +         +  +   +    $    +   +       + +       +  + + +  +  +    + +  ' +       #    + +   +       +   +    $ +    +   +   +         +     +     + + +   +     + +  +    +          + +       + + !  +  +  +   + +!   +   +    + +             +    +  +  +     +   +          +"         +    + +     +       +    + +   +     +    +   +   + +   +        + +    +   +   + + +    +           + +  + +    + +        + +    + +   + !  + +        + + +            +        +     +  + +    +    +   + +      + + +     +  !   +    +    +    + +    +   +        + +  +    +   +   + + +      +      +     + + + +     + +   + + +  +  + +   +     + +    +    +  +  +   +    +       + +    + +   + +    $ +    +     +  +     +  + +   2 + &/   +'   #   + !     ((     & ++  +      4;$ +     "# +    + +  2) +#  + +   !%0(  +  + +% )0    + + +  + +   +- +  +  + + +     +     &   $  #    # +  #  # '% %# +  #'# + '*  %("  + '%#&( + $$"%      +  &         +   +  +   +  ' + )) !             +   + % +  + +$    #   +        +   + !" +           +   +-#  + + +   +  +       + !  +    +      +  + +      +   + +   +     +  +   +    +   +        + +     +  #!  + + +           +  + +    +       +   +      + +    +      + +     +   "          +  + + +         +   +  + + +     +  + +   + 1   +       +  +    +   +#  + +    +  + "  +   !     +% + + +   + #   + + +  +    + +   + +   + + +   + &    $   +"       + ! +      +        '       + +     +     +  + +(( " +     +     + + !   +   + + +      +  +      !         $"  ! +     # &   %(         (  ,  +    "" + % !  +### + + $- + (  +  ##  +$''   %# +/$  +*  #!  +$  '!! !%$          +  + + +  +  + +   + +   +  + + +   +  +  + +  +   + + + +      +  +    +        +   +   + +    +  +    + +    +      +  +         + $         +        +      +    " +    !    + +   +         +  +  + +  +   +   +     + +  +    + +      +    +  +   +   + +      +    +   +    + +    + +       +  +        #    +  + + + + +&,.-+$&*@%!+0#'%)"0&"*5#"))#(-#+$ " '*,'.!("21  +*&$!'*..&(&2-%  !* 13,($" !0" /=3% "%5! $..$ $! )/*$&'  " $*#! !"% %5' !$"&'02, - 17/#$!!"  +#!)$%%! (%!%)%'+0#%#-2+ &43)$,""! )$.+"',"$!,',#%'#$%"#$&% ))"+#"$!&.$& +(/.#(' +"#%,#(, + -7/.% + $  "!3( $#-*).2!#  ($  661)"$  $'/$ .#(% %%$ 3(#  ( & %!#"    !!! ("  + +% ""    +-  +!$'$(  *+ $2$ "&%%  + ,"'&+$   )1-."  + + +  + %%  $)& ! ("" !/' + + #$" + +2%!'#$"&# " + -(  &%    $"$"'  +  + +   #*% !' $ (" +  %&  #, + ! #$   ,# # +&/'!  #" + + #    #!&  +#"!!  # "$# +()""'  "!$$      + ""  !$&   %   !"!  +     (,! #  &'%!2 " & %#$//&'  %  #!(  "#! $% "##*"'"$"$" &(  !  &.3$ $ (&# """&*%#,,( +$.,$$1&'$%  *# %$*$)  $&#,+!).# )311( $")% +  #((0, ! !(%(& +!+")'""+/(&'& #$*&"**!-$%)&#2/## !#*! +.81)"##"#%"%%(&+% +"(%!%&!$&%!$((  $##%-# &! !#$'!$ !"$#$&  +$! ! ""&"! #) +  +   +    +    +     +  +            +   +    +     + +        +      +  " + + + +  +  +   + + +  +  +   #  +   +  +  +   + +     + + "     +       + +      +   +  "   !  +          +    + +      + + +  + + + +      %     + +    +      +           +      + +        + +   +    +    +  +     +  `OU6<6&&"9?-=!%,35/5C;RL 9?$+$ " %35@98G0N% @8C=s4Z>HV#CT cJHPtj4!LU|CA@ 37;>Y@*@t{<NG =qi8{c=^UsxSGcPv %-$aunzxKZ<0GJba](&BG"UT?RZO>MXM"0 +==)G6"6 #@VO`&  0-_n00~Ogd%.zXRMMjm,i,+tvf>En7[I`LCP(Jgs:$T!5 -~:y !$=?,O -'_B^Wh[.+5-2*'3- /6M\VX=*,/26?@@LdaoW#EZG@_Y.GIV[itShd?4VI&$6XkL3-9YpnJMAPQj~]xA7,3+=;VN(V F>+,9;=S0?[2YQt4%8:>71,7O8 2jaa +,J4[qsoOblT +14ART^SNC<.D1%=6+4C?G<  9=)B' / <WW^+x$WI d/=o 12.YF/9 0LPE15EP6@sa= MX]S: +@` +%^FCWbtq8%<QVNr_nX9("%=Ea\ELF]hQ9_jnXooEIWF^?gfWozEPHW+pwyv]1XWaUYsjw'!4u\L:1)3>:9).BD:2)4$ +#48P_?<-8" I7B;KI !&%0*EK %.6&'/127G$A9S[[E'2J*'&)MuzU?7..+Rc]o6:1 :#/G#" 7 )3'!1DCKD(QFV:\8 /0!&+78;/ +bLB %B;LbgL3GK;.%)?LU>/1/%9)%AA.C@# ?)* /6:=A@2l#3>(_uoZW} % 30 8+, $ EG 9B7<7*E45*=9[_oa-  4%2SviF.2)$  4@<C# D:6@OIGXPA3AJ:E\90Of^4*]1(?TarS7!E>A7J?.ej2F)" + '  +6@!TGOBL@  ' )!1 $-+ACG5 #/5$  ('-2:8A#KCSYSD".@&##;]\? 3'$& BTeTj35( +$ 2J*$ 3+4&'+>;B: E9N3T( *) '+25*,cRD,G;QagN7QS@0#'/IISA20!"5%91!*9H5$ +>C#7"   )GPL% S\%0etkU\$1. *+# 7< +3=22/402$3;V\c[.$6/9]xdF3321*,AKDJ/5TC=P[VWedTIQON.ZmRGc{pK?+`<<WgovaJ9QOUH][BisC 4Y93'$ ,+?#!.4'.!(.HS3 -,0                     "Np)&  ~M># aG0""E +Z4y~ps\J6'f\B*+3+2type B      + +     +    +  +    +  + + +   +       +  ! + + + + #(    + +   +         +   "  +  + +   +    + !    + +   +    +    +  +  ') + +    +  + +      #     +    +   +  '' + +      +      +      + #      + + +  (  +     + + #   "    +,       !   +     +  +  +   +" + +   "      + +   +        +     + +  !   #     ,        + "" #$       +    ! +       + +  %   +      +   + + + + +  +     +     +    +    +     + + +    +  +   +                + + +   + + +       + +   + + + + +-  +          +   +      +   + + +   +   +   +   +  $   + + +    +          +  +  +    +     +   +  +    -  + +        +       +   +   +    +       + +  +         +    +  +  +          +  + +"     $%      + +"    +   +   +        +#    +  $ +  +     +!"%    +    + + + (      +  +    %   #   +     +  + +   +  +  " +   +#  +       %  +.   +)     + %+!#&'*,% & #   + !      "( +        +"  + + !&      + +  "$$   +      $    + +  +  +           + +    +    $     +     !         +  + +     +  +  +"   +   +     )  + + +    "+  )   " +(, #''() $#""    &# + + +   #&     +   &  + +   +   +          + +  ! + +      +     $   +      !  +  +   +   +    +   +    +    +   + + + + !        + +   + #     + '  + +   +  $!  +          +  + +%     +  !  # +    +  +   +    +           "    +       +    +        +      + +  +     +    + +      +  + +#  +'       !   +  +              #                 +   #  + +    +   +   +             +   +                + #  +     + + +   +  + '   +   +  +        +   +   +  +  +   +         + "  ,!       +  + +    + + +    + +   &   +    + + + +   + + + # +         +    +  + !     + +                   +       +  +    2 +  + +  + +      +$               +  + +     +             + &               +    +            + + +  +$!  +  %    )%  +! +          +       *  + +  $  + +"   ## +   +      +   $   +   + +                              +  +    +  + + +  + +     +  + + + &  + +   +      + +       +             +  +  !   +  !   "  +   +   +  +     "    +  + +  +  +  +       +     &     + + +$     +  +  +     +         + $              +   + +  +  + % +       +       +      +   +!       + +  + +      +   +  + +    +   +  + + +   +           +   +       + +  +  + +      +  + + "     +  +  +       + + "   +  +  + +   +   +    + +$ + +  +     +  +     +    +        + %'' !$ $/!%&!  )'    " !!<6  ( ( *#+%%/! %$7""  %@3 &8, +#! .,   !4(       +)!!0(      + !  -6"#'*#!! +   *"! (0'"(,5*)-(.-70&%0('") '#+12%$+-=1$.7F%%)$( #*# .&5, (&!1. 2%!(/   +    +    + #       '   "       !  +  !      +    +    + +    +     + +  + + +   +  +    ( "!%)     +      +    +  + + +  +    %    +  #" +   +  +(     +  +   +    + ) +" +$ +     0  +      +       +    +  +  +  + +   + +  + %       +   +   +#    %       +  + + + +   + +% +         )  +$ +           +  +    +  + +    +    +  + +           +  + +  +    +&  +       +      * !   + +$        + %  $  + +  ! +    + +# +            +         +  +   +  %    +      +       (     + + + +   +   +  + + + ! + +          + +      + +       +      (        +   +'    +  +      + +  +   +   +   +  +  +  + + + .      !    +  & +      %  ! + +   ! '6   + - +  ! +!* " ""##""&1 ,(!% (#   +  +$  +!  +  +        +           +    +  (           +  +  +   + + + +  +   +(    +!       + + $  "            +     +     + +   + + +   +#  +   +       +%      + + +   + +     + +     + +      + +   + +   +   + ! + + +  + +    +   +  +   +    + +   +     + +    + + +"  + +        (   +   + +    +       +        +   +       $    +    +   $      +    + + + +  + +   + +   +  + +    + #  + +  +      &      + +!  +  + +  +          + +    +   +  +   +' +  +   +      +        +    +        +     +  +  +"  + +  +     &  + + +        + +  +    +  +  +     & +     " +      $     +  +      +      +   "   +     " +    + !  +   +       +  + +  +  #  +            +      +"  + + + +    + +     +!      + "   + + +  + + + +   $  + + +              +    + + !   + +  +"  +!  + + %!$   +   +  + + +    +  !  + +  +  !  +     + +   +   +   +   +          + +   +    +    + +      " +    + +    +        +   +   +        +$     !  +          + + "    + +   +! + +     +    !  + +          +    +   + + + + +  +      +   +       + +   +   $   +  +$     "       + +       +     +  +     + +      %      +         + +  +    + +  + + +      + + + + +   #   %      !  +   +    +   +        + +   ! +   +      + )   +   +       +             + +  +#   +  + + +  +     + +   + +  + + +  +     +    +  "    +    +     +'   & +  +   +   +    +   +   + +            + +     +   "    +   ! + +(                   +    + + + +      $          $  + + (  +  + +      +    +           +     +     +    +   + !  +   + +  +   $   '   + + +     + +      + +      +     +   +   +      + +   "          + +  + +  + +&   (      + +  !      +     + +       +   +    +     +       + +!      +     +       + + &$ +  +      +    +    1! +!   +   +      +# +        +#                 +          +     +    + + +   + + + + + +   +$ + + +  + +                 +  +    +    + " '  " +  + + +     +    +         +  +         +      +    + + +"      +   +  +      +  +  + + +    +    + + +     +  +"   +     +%   +  +  +  + +  + + +         +     +  +       + " +     +     +  +    +      + +      + +     +    +    !     + ! #   +    +  +         +   +  +              +  + + +  + +    +  +      +   +  +  +   "   +  + + +   +   + +% + + +% +                  +  +  +  + +  +    !       +    +''-   +   + 5 +  + +  -   + +   '" +  +  & +  +    ++    + +@ + :   (0  # '&   + +& + !,   + &)30  / +3   3#  +   +          +   +      +  )$   $ +  *     #!         + + +  +$       + +!  +    + %1    +   &   #% +   &!&"'% & +' + +   +      +   +  +  +           *  + + +     +   +  + +   / + + +  $    + + +       & !'    +  + +  # +#  "  +        +        +  +   + + +(         + +   +     (     !      + + +       + "  + !     +   +  +   + + +  + +        +  +  + +      +  +        +  +  + +     + +        + +      +    +  +!     + +  +    + + + +    +   +  + +    +  + +      +   + +  $ +  +( +     +    + +  +         !            +  +     # +   + +'   + +  + + +"   + + !    +          - +        + + +          +   +% + +        #!"&( '"    "  "!" #       ! %! + $$#"  + "$!%  + +( + %   +!& ( %"  "  "*2  +")  +!$! + '" "  $  % + #  !''% +  + + $   + + +  +   +  +  +  + +  +   +  +       + + +  + + +   +   +           +  &  + +         +   +      + + !     % + "       +   +  +   &   +   +          +    +     + +   + +     + +      +    +       -)*3, "%+&"  + +%  "," !'0%  + +".'!'   #3$) %+$4! '.+%,!"  +"51*(#$4*)*! /:2   $#.!   &#  %+ ) +')#&#"*+7%  ! $/-##$  % #$$%"'0  '#! + %4. * +.)  +  # +*  1G+$ # %%! + +.&"#)  +.88/#   -'   (,   $  + +   ! + +   %  +      + +  #+   ", %3-  + +(+$!#  $"       + +&%    %4"  2 -   +' ,  + +" # "    #   !##$*44,"#""""    $  + +  + +  + +  + + +       -   +  +             + +       +       !  "         + +$*       +   !+  +    + + ! %#'  +  $  (+&$$ $#$( +" &#&  +0  +  '#  +'- + !+) #$#  !%  +)   + + # !!"!(&,& 8& %)*) +! +   !&  "%  *0 **#('"  ), %!# $! !  +               +   + +  +    +    +(     + +  +  +  +  +     +  +   #)   + +  $ +     +  +     ' +    +     + +  + !      +    + +             + + + + +  +     + +  +      +   +       !)4+,%0ms31 <6$29" +($ #E8R>G %tZfFEEQ +!J B"IHDiF61 +6m|#CDE !,w5 H#30X2Z]F@pcz<se_BEaa} >S9*!650$ZqI*:#sn|&JZ2,z02\FBkmxjA])RLVe];5Pv=~]*@JLZ@6WptJ#$/uu &\ D#8H19\(AR.R6>;#.)dfO094%9':JRP! >""?5-#/& *-`t3*5G<*2# "HL*>oI=3b`T^@A(, +8OQ'<1)qV}<-2LJG3.,4> %<?. +&@UEGHhqHCE-gy{R) +E=!-*/+B +1&(*- (\.$%vmw,@_/xrTTlu71KRD >)+>(3) I[BLPd:0S34LY] +(|[!QWtomuE0IeJ59=_vwbNNmmpgM>VLnvn5*.as'8J0!'.1./5HRD51#`qK!';.>>V3c;%)*@KzWD [_A6iiVK *6 :6-DHQ@?1&' 6WWcK-+ '&1=0BK],#$4lTg|8!-5 > 1 ' (:;P9%>0/ +&$C-%'7'-@XP928D_s7%  +-$ k]d %-FpfI>VXr1d;DH"884($**&W{g>007 @8_kD$($*UQLRQ}tC4GZ))$__^fL<TSK<&-:Aedrj~T 2T"?5<5=#JaVZ(!,6P"*E_@A$;7!G?. +2 +#,&)':->74,%$) )@8M<  0/Kb#(/(" + * (6vsA#-KC@50A)# $!5E%(## .:>JIaN3=:9 4. 2"*O<6$<M?AOodKKT-2VdpE7 # /-#0"9 %* +  +$ + * %!lx$:I\/h^sz'5DWC + . >G3>EG;* <8&0_tI-/98;!#'A<hpL)/,-' -KHGHV{}M7FV- 10_h|`eUCTRM9*<KNlowrX 4V(@;&:#!')::&"%Jeg^#4+,F-2I[;#I 95%C?$1+#,&#"52=<84%"+ 4KAQB%-';Wf1$             }+Ls $&0265@H<6NE>DD8433* vZTE4! vVD)XJ(JursdLC6j_E<*) +4+2.50002.5000type A        +   '!   +    +  +            +   +   + +      +$ + % +  +    4)       +  + +         +  + +   + +    "   + +   + % +  #&!        .    /( +       +#   +    +  + +  + +              + +    + +   + + # +  +   +%   +   +      + +  +            + +      + !    +   +   +   +             +    +   +  %"!   +   + ! + +  + +  ,#    +      +    + +    + +  + + + +   + ! +  +   +    +   +     +   + +             +  +    +     +  + +  + + +        $  +     +   +      +    +   +  +        +         +  &   + + +    +  +     + +     +    #    + +  +  + +  + !"!"$ + +      ,$ +       +    +     + +  +     +         +    +       +  )     +    +  +   +  + + +   +       +                 &   +   +  +  +        +   +     +  +  +       !  + +   +    +  + +     +       # + +    +          +    + +   +% +         +    +  +         +   + + + + +     + +   +  (   +  +  +  + + + + +     +  +   +     + +  +  +           +  + +          +     +   -%     +   +    +         +    + +   +  +   & +        +  +   + +   +   +  + + +  +  + +  +&   + +  +  +  +  +           +  + +  +    $   +  +  +    +  +      +  +    +  + +    +    #   +    +   +    + +  +   + +  + +5)   + + + + +     +  + +   " + #"    + +    + +  +       +    +      + +   +"      +  +  +  +   +     +   + +          & +     +        +       + +   +    +  +  + + +  +    +   +   )  +  + +    + +  +   +       +  + +  + + +   +  +$ "   +    + + +    +    + +       +!          +     + + +    +   + +               +  +   +        +*!    + + +    +  +    + +  +  + +  + +   +    +      +   +   + )"     + +   +!  " !""      + + +    )!  +  +      + + +  +    +  +    +    +  +   + +       + +     + +       + + +    +        + + +   +      +  +    +  "!   + +       +      +    + + + +       + +   +  "     +   + + + +    +  %        + + +     + +  +  +    +   + +  +     +      + +    + +   +   +   +     +      +   +  +       +     + *     + +   ) +  +   5$    +      + +     +  +     +  +  &  +  + + + + +     + # +  +  +  +  +              +  + + +   +  +  +     +  +     + + +% +            $/$%'$ + + !""& +!%" +)'%  +  ) + +   ,' + +$# (&#  +#*2)    +!'&  -T:$ ". + !" .",#($1",5  !,1 ! &&%- +$ +&#'#$40 !$ & )'$ 4$ +!/*'&!,+!  +-;#$ $/    +  +  +  +   +   + + +  + +  + +( +    + +    +   + +   +  +        + + )  +     +      +    +   + + +  +      + +  + (!     +          +  +         + + "#  +     +         + +  + +     + +       +      +    +   (!  +    +  +  +   + + +  +   +     +    + +       +      +       ! +2(  +         +  +      +          + +      + +   " +        +  + + +    + +  +        + +  + !         + +#                " +  + +   +       +     +  + +  +                + + ,  5$  %( " +$1,,!$)! )3$ /B$ /# %'*() "&7$ 5 $,*1+ ,*+90),$! 0*/ #)(# )$*&0,1/&#.%#"#//.(*, + ,&$)2+" (  0!**-(&( 2=;,%)0("!!3C4&  &." $3% $:30#(,-$! +$$2" $ + ='$ +  #&#%0! (  +(! &"   "  &( #)&%$)$           + +    + +  +  + +  +      +      +  +      '#  + +   +           + +  + + +  +   + !  +    +  +  +%  !  %   +#&     +!!     +   "     +   +   + % + +     +     +  +  +  +' !         + +   +      #   + +    '  +  &)       +   !"   + +       +    + +   +     + +    + +$$ + (-  +  + + +  +  +  +    +   + +   + +  +     + +  +   +         +   + *#     +       +  +     + +    +      +    + #   "  !        + +    +   !   +  +      + +  +    +       +  +       +      +  +              + + +      + +  +   +   + + + +   +  +         + +      + + +   +     +  + + +  +    + +     &   " $  + $+ &')(%('! ) $"#+ +"  *&(&  *- + +"#& +  +  +%          ' + + + :2   +  $$!      !        +    +   + +  + +     +    +  +   +   !   +    +#   +  +     + + +  + +  +     +#   + + +      + +   +     + +     + +         +  + +   &   + +  +    + + + +      + +     + ( +  +   +     +    +     + +  +        + ( + +   + +  +     +     + + +    +     '   +  +  + +     +    + +  +   +  + + +  + + + +   +    + *          +  +      +    +  +   +) + +  +  +    +   +  +  +  +  + +     +     +    + + +  + +"       + + +   +    +      +       +  +(       +         + +        +   '  +  +   + +  +      +   + + +  +     &   + + +  +   +   ! +      +  +     + +  +  ) +        +        +    +  +' + + +     + +     +     +      +  + +    +       +   )   + +   +   +    +   +        +   + +   '   +    +   +  + +  +    + +   +# +     +        +           + + +   +  & + +        +       +      +    + +   +    +  +     +)"       + +    + + + +    &    + + +  + +  +  ##  +    +   +    (   +   72"   +  +   +" +  +      +   +   + +  $      +   +     +  +   + + +     +     +      +     +   +        + + )# +   + + +  +  +   +    + +    +   +        +  + +        + +       +  + +# +      + + +  + + +   +     +   +    +          +  + + + +  + (#    + +  +  +    +   +  + +          +   +   +  ++#      +    +   +  + + +   +  +  +           + + +   #       +       +   +   + +  +  +    +        + + +  +   + + +   *$         +             +    +   + +      + + + + + + +  + +   ," + +  +  +  +  +   + +    +    + +      + +  +     +       + + +&   + +              + + +  +        +     + +  +  + +  +%    +     +      +   +   +      + +         +              +  *(   +         +    +         +   + + + + +  +"             + + +         +      +       +     +       + +   +   +         +    "      +      +      +   +   $!              +   +    +  #    + +     +    +   + +   + +        + (   + + +   +  +  + +    + + + +        + & +  +  +  +   +    +  + + +   + +  +       + (   + +     +     +      +  + +      +         +  +  + +)%    +             +   +!   &% +        + +   +  + "  + +'& +  #(           "/ +   +  + & +  +    + + + $    + $  "%  +     + +   + +    +!  +  +  +  +  #  +   + +  +     +   ,%     +  +      + + +      +   +   + +) +        +   +    + + + &      +         ( +    "  +  + +    +       + +    + + +        +  +       +    +   +      + + +       +      +        + +    +  + +      +    +  +     +       +     +      +  + +   +  +        + +  +       + + +    + +  + +   + + + # +     + "     "       +      +   + +    +    +  +  +  +  +      +               + $   +*!#!  "( !   +   #(   "                        +  + +  +  + % +  + + +            +        +   + + +   +  + +  +  +    +  +          +   +  + +   +  +               + +     + #     +   +   + +    + + +   +   + +    +      + +  +%     + +   +        +#"& %(    ' + ##  $&  /+!    +   + ++, + +!  +             + $ + +   #    (          .   + "'+'  +*      $$  +% +    &     #   +)(  +   +  +  + , +  +!)  +   *, + + +  "!  + !%         !%+2   + $ +   +  +             +          +       +         +           +    +   +  # +  + +  +  +      + +      $%#     +#    +  +"  +!" !  !   *,$  ") + + "      !  +     +       +%"  + %     + +     +  + +   +  +  +     + +   +    + +      +    + +   +  +  +      +   +     +       + -#    + +  +  +   +         +  +      +    +  + + + +   &   +        +    +       +   + + *      +  +   +" A;5U[X +er@.NV>w;,!EC6zvOukv@e"\d_t'.j9 6.C"! %WrWzA= 9*-(dJz][pn5Kx\|~cQorQ.lo 2y*1?-/p`#rKbif`Ya^mH +(1CG;3km"$(GZ,) ZU='!NW$.pT#nU2U7,>=+^OT9?L3TJ\^3E8x6m^50j1<1,;S$ A=&&fM&# $=@ODgPvC0 +z{23:>Q"Xf7Y,9FpYIM>4155+ /"CMO3fR=@ faPCH&'NvtN (;1'KU)&Ue2B_'-HU)5H, 'T%SoLwNXcfA)c9Yd( K8zmi~sdck<(n{l`@NS6nU_k^1(M<eVA7]k=M_^[u129P-EC mnvl( wGA`jT):G:5.?\o4N5U4%)^zsGA9#%WJBTkm<*>4<?HZa[<J{\LR9TexEGNVeE(STX~plrOu%H|rXQmroL]z[Gl?W]Xqnsc<r.WabugEAHG0>j\R+;d?6_`jPGKG!, -VpA$ 20RyR87P06H=Tgdk0#"&Bf-1+N/ $3B?A:*&-" !-3EPW"+5izw?w)+3=3DutIt 1  %$#1/( '+/  %25TW<%,7S'#FD*  ,?N@ +'%9O!3BU:&&#bq&+fsw3QLMi"! 10>$!R !*09QioE + %$<G2BG/& <:48/#LQ##7()NkIiT/_<9hsgR>H,QD2"UZ2*Qei~Y$!jnC2&D9/'))9V\&%  #5NY5 )C+'/=UJZ!$ $7C9%4# +1 + .;$ L{g + 1/$$#52_g]F +&!-, )0 %,#" #/ 4= $/, 5DLccE8;Lc1/IG0/=OF"$%& +&@G +7@S;$! & p}!$,1ouw>ac\w,-$!0&& ?G3 -W)(!39@E\rzS#"9=MTD$+OX?3C$OQTM?3`mF.C0$\Z>Pq}Tr`#:jP3Fhsj_NJ3SQA1`e(D:\vtl::;,spR;2TE?789$ %=Z]5 ,4(&!*'$(AZ[9 #':M+ 739@YBM+ + !(1I,SA 0A1<$ +!!IO+%4 +54Wzi) C22:1FBl{rW +#(2$            l ,W83Jgz   $(  _LB%uXqiw"**"$1&.$("( *j`TC9"+5 \ No newline at end of file diff --git a/mne-python/source/mne/io/edf/tests/data/test_bdf_eeglab.mat b/mne-python/source/mne/io/edf/tests/data/test_bdf_eeglab.mat new file mode 100644 index 0000000000000000000000000000000000000000..8f45cb031cc1a9133506b61b314e9e2c4fd02d1a --- /dev/null +++ b/mne-python/source/mne/io/edf/tests/data/test_bdf_eeglab.mat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9d2051ce2dca29275f81efa72e207dcc7ccc4ef2367ea7127bb22011751fc07 +size 447053 diff --git a/mne-python/source/mne/io/edf/tests/data/test_bdf_stim_channel.bdf b/mne-python/source/mne/io/edf/tests/data/test_bdf_stim_channel.bdf new file mode 100644 index 0000000000000000000000000000000000000000..ca3613e96fbb105df5b70a939da26b87a5441dfb Binary files /dev/null and b/mne-python/source/mne/io/edf/tests/data/test_bdf_stim_channel.bdf differ diff --git a/mne-python/source/mne/io/edf/tests/data/test_edf_eeglab.mat b/mne-python/source/mne/io/edf/tests/data/test_edf_eeglab.mat new file mode 100644 index 0000000000000000000000000000000000000000..a905d3e2f38b2435be2633dd416ddd3c649394fa --- /dev/null +++ b/mne-python/source/mne/io/edf/tests/data/test_edf_eeglab.mat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9cc02b7de91bb503bb6898d18b243980af0131c332e4d28e0ad120803c3cde78 +size 524875 diff --git a/mne-python/source/mne/io/edf/tests/data/test_edf_stim_channel.edf b/mne-python/source/mne/io/edf/tests/data/test_edf_stim_channel.edf new file mode 100644 index 0000000000000000000000000000000000000000..548000505daf7efc6245de3a032bfd0cecdc2da5 Binary files /dev/null and b/mne-python/source/mne/io/edf/tests/data/test_edf_stim_channel.edf differ diff --git a/mne-python/source/mne/io/edf/tests/data/test_edf_stim_channel.txt b/mne-python/source/mne/io/edf/tests/data/test_edf_stim_channel.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e053abe60404063dfd21e3cdba9845331c18733 --- /dev/null +++ b/mne-python/source/mne/io/edf/tests/data/test_edf_stim_channel.txt @@ -0,0 +1,717 @@ +175940.7 -217680.3 176086.4 175779.4 -217793.6 175491.8 -209183 175800.6 175840.9 175384.3 176063.5 -222814.3 -216936.6 176736.7 175402 -219499.4 115678 -220099.2 176235.8 176591 -212093 176486.8 176489.3 -218446.2 0 +175941.1 -217680.8 176088.4 175777.9 -217794.2 175492.1 -209132.7 175803 175842.6 175384.1 176065.4 -222809.8 -216944.7 176736.3 175402.8 -219524.4 115731.9 -220099.6 176236 176592.2 -212095.6 176487.5 176492.3 -218442.2 0 +175942.9 -217683.2 176089.5 175777.6 -217806.4 175490.5 -209125.1 175803.3 175843.4 175382.9 176065.4 -222807.4 -216946.8 176736.6 175402.7 -219535.3 115796.1 -220124.5 176235.9 176591.5 -212090.7 176486.5 176493 -218440.8 0 +175944.8 -217684.8 176091 175778.1 -217821.5 175489.6 -209128.7 175804 175842.6 175382.9 176064.2 -222809.5 -216940.2 176738.1 175401.9 -219527.8 115897.8 -220140.5 176235.4 176591.8 -212068.1 176487.8 176492.9 -218437.9 0 +175944.7 -217675.6 176092.7 175778.5 -217828.5 175490.8 -209132.7 175806.2 175841.8 175384.7 176064.7 -222812.1 -216936.7 176738.6 175402.4 -219506.7 116032.4 -220142.5 176235.9 176594.4 -212042 176490.9 176494 -218434 0 +175942.8 -217664 176091.3 175779.1 -217825.6 175491.5 -209133.8 175805 175842.2 175386.3 176065 -222814.5 -216943.9 176736.7 175403.3 -219479.2 116165.2 -220149.7 176236.5 176594.1 -212032.2 176490.7 176493.2 -218435 0 +175942.7 -217662.9 176088 175779.4 -217819.3 175490.7 -209123.9 175802 175842.3 175386.6 176063.7 -222814.5 -216946.7 176735.8 175402.9 -219449.8 116264.4 -220155.3 176236.5 176590.9 -212032.2 176488.8 176491 -218439.5 0 +175944.4 -217666.4 176086.9 175778.9 -217814.5 175490.4 -209107.9 175802.2 175841.4 175386.3 176062.6 -222812 -216936.3 176737.3 175402.5 -219411.6 116336.8 -220146.8 176236.3 176589.4 -212027.2 176489 176490.3 -218439.8 0 +175945.1 -217665.6 176087.6 175778 -217812.1 175490.7 -209082.1 175802.6 175840.8 175384.7 176061.5 -222811 -216926.9 176736.8 175401.9 -219361.6 116400.7 -220148.7 176236.4 176589.1 -212024.1 176488.9 176490 -218436.9 0 +175943.4 -217663.5 176087.3 175777.3 -217810.9 175490 -209029.4 175800.6 175840.7 175381.8 176060.7 -222811.1 -216925.7 176734.6 175400.5 -219314.6 116454.3 -220170.7 176236.6 176588.7 -212035.8 176486.6 176489.1 -218438 0 +175941.3 -217666.6 176087.2 175777.5 -217810.4 175489 -208964.9 175800.1 175840.4 175380.6 176061.5 -222812 -216928.4 176734.6 175400.2 -219282.8 116503 -220171.9 176236.5 176589.8 -212055.9 176485.3 176489.3 -218442.9 0 +175941.5 -217674.3 176088.3 175778.3 -217810.3 175489.6 -208930.9 175802.7 175840.3 175382 176063.4 -222815.4 -216936.5 176735.6 175401.8 -219258.9 116565.2 -220134 176236.1 176591.4 -212064.7 176486.4 176490.3 -218443.1 0 +175942.9 -217679.8 176088.5 175777.9 -217810.5 175490.8 -208926.2 175803.6 175839.9 175383.5 176063.4 -222816.7 -216943.4 176734.9 175402.5 -219232.8 116616.9 -220097.1 176235.9 176591.5 -212059.2 176486.9 176489.7 -218437 0 +175943.6 -217680.3 176087.7 175776.5 -217810.9 175490.1 -208910.2 175801.6 175839.3 175384 176061.7 -222813.1 -216934.2 176733.6 175401.5 -219207.5 116637.4 -220089.6 176236.9 176590.7 -212047.5 176485.5 176487.8 -218431.7 0 +175943 -217678.5 176088.3 175776.3 -217812.3 175489 -208881.3 175801.6 175839.7 175384.2 176061.6 -222809.4 -216912.8 176734.3 175401.6 -219182.5 116687 -220091.9 176238.3 176591.6 -212017.8 176486 176488 -218430.1 0 +175941.9 -217674.2 176089.5 175776.9 -217815.9 175489.3 -208865.9 175804.2 175840.4 175383.7 176063.4 -222808.6 -216899.9 176736.1 175402.9 -219158.7 116787.6 -220081.1 176238.3 176592.9 -211965.3 176488.3 176489.8 -218431.2 0 +175941.7 -217669.1 176088.7 175776.8 -217819.5 175489.5 -208854.6 175804.1 175840.1 175382.7 176064.5 -222809.9 -216906.5 176736.8 175402 -219152.1 116843.6 -220063.9 176236.7 176591.6 -211917.7 176487.7 176490.5 -218434.1 0 +175942.2 -217668.7 176087.3 175776.6 -217819 175488.4 -208825.7 175801.7 175839.3 175382.8 176064.5 -222812.8 -216922.1 176736.6 175400.2 -219161.4 116806.3 -220063 176235.8 176589.8 -211892.9 176485.1 176490.1 -218434.7 0 +175942.5 -217671.7 176087.7 175777.1 -217816 175487.8 -208785.5 175800.1 175839.2 175383.7 176064.4 -222815.5 -216929.8 176736.8 175401 -219161.8 116751.8 -220084.8 176236.1 176589.6 -211874.2 176485.1 176489.8 -218431.5 0 +175943.1 -217673.5 176089 175777.8 -217815.4 175489.2 -208750.4 175800.3 175840.3 175383.9 176063.6 -222816 -216927.9 176737.4 175403.1 -219144.9 116761.2 -220106.8 176236.7 176590.1 -211835.9 176486.8 176490.6 -218431.4 0 +175944 -217674.3 176089.3 175778.4 -217816.3 175490.7 -208734.5 175802.1 175841.7 175383.5 176062 -222815.5 -216927.9 176737 175403.2 -219128.9 116818.6 -220105 176237 176589.8 -211766.5 176487.4 176491.4 -218436.7 0 +175944.5 -217674.4 176088.2 175778.5 -217816.9 175490.7 -208741.5 175802.3 175841.7 175383.4 176060.8 -222816.1 -216931.2 176735.4 175402 -219133.5 116815.9 -220089 176235.8 176588.3 -211681.9 176486.8 176490 -218440.5 0 +175943.5 -217674 176087.2 175777.9 -217818.9 175490.1 -208749.3 175800.1 175839.7 175383.3 176061.6 -222813.8 -216929.2 176734.6 175401.2 -219153.4 116702.6 -220083.1 176234.5 176587.7 -211605 176485.7 176488 -218437.1 0 +175941.2 -217675.1 176087.8 175777.7 -217821.7 175490.9 -208732.9 175799.9 175838.8 175382.8 176064.2 -222807.3 -216923.2 176735.3 175400.9 -219168.6 116596.6 -220089.3 176236.1 176589.8 -211536.6 176486 176489.4 -218430 0 +175939.2 -217677.1 176088.6 175778.6 -217822.2 175492 -208687.8 175802.6 175840.4 175382.7 176065.3 -222805.1 -216925 176736 175400.9 -219178.3 116621.8 -220097.3 176238.7 176592 -211472 176488 176492 -218425.9 0 +175939.9 -217677.9 176088 175779.4 -217818.9 175491.2 -208607 175802.9 175842.1 175383.4 176064.5 -222808.1 -216935.1 176735.9 175400.6 -219189.1 116753.6 -220103 176238.5 176591.2 -211415.9 176488.8 176491.7 -218425.8 0 +175942.2 -217680.1 176087 175779.1 -217810.7 175489.3 -208483.9 175799.7 175841.6 175384.1 176063.7 -222808.1 -216940.1 176735.3 175400.3 -219189.3 116911.1 -220102.3 176236.8 176588.2 -211358.8 176486.3 176489 -218428.5 0 +175942.8 -217683.8 176086.6 175778.4 -217803.5 175488.4 -208350.5 175798 175840.3 175383.8 176062.5 -222805 -216932.6 176734.8 175400.6 -219170.4 117041.5 -220100.1 176235.9 176586.6 -211280.7 176483.9 176487.5 -218433.9 0 +175941.9 -217683.3 176087.4 175777.3 -217805.8 175487.8 -208253.2 175800.6 175839.1 175382.8 176061.4 -222803.8 -216920 176734.7 175400.6 -219145.2 117115.8 -220109.8 176236 176588.6 -211184.8 176485.1 176488.2 -218437.7 0 +175942.9 -217678.3 176088.8 175776.7 -217815.6 175487.6 -208196.7 175804.1 175838.1 175382.4 176061.9 -222805.4 -216913.4 176735.2 175400.7 -219130.3 117158.2 -220125.5 176236.6 176592.1 -211092 176487.3 176489.7 -218435.8 0 +175945.8 -217675.4 176089 175777.8 -217824.2 175488.5 -208150 175803.5 175838.8 175383.4 176062.7 -222808.8 -216915.8 176735.8 175402.2 -219127 117223.9 -220131.3 176237.1 176592.7 -211015.8 176486.2 176490 -218432.4 0 +175945.5 -217677.7 176088.2 175778.6 -217826.7 175489.2 -208088.1 175800.3 175840.6 175384.6 176061.9 -222811 -216919.7 176736.4 175403.1 -219134.6 117308.6 -220130.5 176236.5 176590.2 -210967.4 176483.6 176489.1 -218432.9 0 +175941.7 -217683.1 176088.2 175777.1 -217823.7 175489 -208023.9 175799.8 175840.5 175384.4 176060.9 -222807.5 -216917.2 176737 175401.6 -219159.8 117367.4 -220126.3 176235.5 176589.1 -210957.4 176484.7 176489.2 -218435 0 +175940.4 -217687.9 176089.4 175775.7 -217819.8 175489.2 -207991.8 175802.5 175839 175382.8 176062 -222802.5 -216907.8 176737.3 175400 -219191.5 117427.2 -220109.9 176235.2 176591.5 -210976 176489 176490.4 -218435.2 0 +175942.3 -217688.8 176089.9 175776.2 -217818.5 175490.1 -207989 175804 175839.3 175381.5 176063.6 -222804.1 -216901.3 176736.8 175400.6 -219208.7 117573.1 -220091.8 176235.2 176593.1 -211003.7 176491.2 176491.2 -218437.1 0 +175943.6 -217687.9 176088.8 175777.1 -217820 175490.1 -207982.3 175801.9 175841.3 175382.1 176063 -222810.5 -216909.8 176736 175401.8 -219214.8 117797.4 -220096.4 176234.8 176591 -211038.9 176489 176490.4 -218442.5 0 +175943.7 -217687.8 176087.3 175777.4 -217823.3 175489.5 -207967.5 175799 175841.3 175383.4 176061.3 -222814.4 -216928.2 176735.7 175401.8 -219225.7 117982.7 -220118.1 176234.2 176587.5 -211086.3 176485.4 176488.6 -218443.4 0 +175943.3 -217685.7 176086.7 175777.3 -217824.5 175489 -207967.2 175799.5 175838.9 175383.3 176061.5 -222814.4 -216938.1 176735.7 175400.9 -219239.1 118066.5 -220131.4 176234 176586.7 -211134.6 176484.3 176487.9 -218436.7 0 +175941.7 -217681.3 176087.5 175776 -217821.4 175488.9 -207983 175802.2 175837.8 175382.2 176062.6 -222815.3 -216936 176735.8 175400.9 -219238.5 118093.8 -220132.7 176234.6 176589.2 -211161 176485.8 176489.8 -218430.4 0 +175940.5 -217682.4 176088.3 175774.6 -217818 175489 -207984.8 175802.9 175839.8 175382.5 176062.6 -222819.1 -216929.6 176736 175401.7 -219222.2 118113.4 -220137.8 176235.8 176591 -211152.5 176486.5 176491.5 -218430.2 0 +175941 -217693 176087.5 175774.9 -217817.2 175489.1 -207950.2 175801.3 175841.9 175382.9 176061.7 -222820.2 -216923.3 176736 175401.6 -219214.8 118148.9 -220150.4 176236.1 176589.8 -211123.4 176485.3 176490.2 -218433.2 0 +175942.1 -217706 176086.4 175776.3 -217816.9 175489 -207898.5 175800.7 175841.8 175381.7 176061.3 -222814.2 -216921.2 176736.3 175400.9 -219228.9 118218.1 -220156.7 176235.5 176588.2 -211098.5 176485.3 176488.6 -218434.1 0 +175942.5 -217711.3 176086.8 175777 -217816.6 175489.3 -207858.8 175802.5 175840.9 175380.8 176062.3 -222807.2 -216923.3 176736.5 175401 -219243.2 118296.9 -220144.8 176235.9 176588.8 -211081.1 176487 176489.3 -218431.6 0 +175941.1 -217708.2 176087.4 175777.2 -217817.7 175490 -207833.4 175804.5 175840.6 175382.1 176063.5 -222805.7 -216920.4 176736 175401.4 -219245.4 118334.3 -220119.9 176237 176590.5 -211064.5 176487.5 176490 -218430 0 +175939.4 -217707.1 176087.1 175777.1 -217819.7 175489.5 -207811.8 175804.7 175840.4 175383.7 176063.5 -222808.2 -216910.5 176734.8 175401 -219256.7 118335.4 -220098.5 176237 176591.3 -211066.2 176487.1 176489.6 -218433.4 0 +175940.8 -217711.1 176086.6 175776.5 -217818.6 175487.8 -207777.8 175803.8 175840 175384 176063.1 -222811.7 -216905.1 176734.1 175400.6 -219295 118353.1 -220094.6 176235.5 176591.1 -211102 176487.7 176489.5 -218438.9 0 +175943.4 -217712 176087.1 175775.9 -217811.6 175487.3 -207719.9 175803.8 175840.1 175383.4 176062.5 -222813.3 -216910 176734.3 175400.3 -219345.1 118410.4 -220113.5 176234.1 176590.5 -211139.3 176488.1 176490.3 -218439.7 0 +175943.3 -217707.3 176088.2 175776.1 -217802.9 175489.3 -207655.2 175804.2 175840.8 175382.8 176061.8 -222809.8 -216913.3 176735.3 175399.5 -219377.8 118496.5 -220143.3 176234.5 176590.8 -211122.5 176487.8 176491.2 -218435 0 +175942.1 -217704.4 176088.2 175776.7 -217799 175491.1 -207610.5 175804.1 175841.2 175382.9 176061.5 -222803.4 -216906.9 176736.5 175399.1 -219388.4 118589 -220156.3 176235.6 176592.1 -211045.3 176488.1 176491.3 -218431 0 +175942 -217703.9 176086.9 175777.4 -217803.8 175490.2 -207586.5 175803 175840.4 175382.8 176060.7 -222801.5 -216904.5 176736.3 175399.8 -219399.3 118658.9 -220140.2 176235 176592.3 -210955.8 176487.5 176490.1 -218430.3 0 +175942.3 -217698.8 176085 175777.1 -217816.3 175488.2 -207564 175800.8 175839 175381.8 176059.5 -222804 -216912.3 176735.2 175400.1 -219424.4 118709.3 -220116.1 176234 176591.1 -210886.5 176485.7 176488 -218430.8 0 +175943 -217689.6 176084.6 175775.3 -217828.6 175488 -207537.6 175799 175838.3 175381.1 176059.7 -222804 -216912.1 176734.3 175399.8 -219457 118772.6 -220110 176234.7 176590 -210827.5 176485 176486.5 -218432.1 0 +175943.3 -217684 176086.2 175775 -217833.1 175489.3 -207532.1 175798.2 175839 175381.2 176060.7 -222800.6 -216899.5 176733.7 175400 -219483.2 118847.2 -220125.2 176235.5 176589.1 -210775.3 176485 176486.8 -218434.2 0 +175942.2 -217683.5 176087.2 175777.7 -217832 175489.8 -207563.9 175798.1 175840.2 175381.4 176061.3 -222798.8 -216894.8 176733.1 175400.5 -219488.2 118911.7 -220143.8 176235.4 176587.4 -210748.7 176485 176487.6 -218434.1 0 +175942 -217683.2 176086.4 175779.3 -217832.5 175489.4 -207606.1 175799.8 175841 175382.2 176061.7 -222800.2 -216905.2 176734 175400.8 -219476.7 118977.3 -220144.2 176235.3 176586.7 -210747 176485.6 176488.4 -218432.6 0 +175943.3 -217681.3 176085.8 175777.3 -217837.7 175488.3 -207622.9 175801.4 175841 175383.2 176061.9 -222802.7 -216914.4 176735.5 175400.8 -219477.2 119081.2 -220130.8 176235.1 176588.3 -210749.1 176486.1 176489.6 -218433.2 0 +175942.6 -217678.9 176086.3 175775.1 -217842.8 175486.9 -207608.5 175800.7 175840.2 175382.8 176060.9 -222803.1 -216912.5 176735.5 175400.8 -219505.3 119262 -220123.9 176234.8 176589.9 -210743.1 176485.5 176490.6 -218434.5 0 +175940.9 -217676 176087.4 175775.6 -217841.4 175486.9 -207579.2 175800.5 175839.1 175381.7 176059.8 -222800 -216903.6 176734.2 175401.3 -219545.5 119503.9 -220121.2 176235.5 176590 -210728.1 176485.4 176490.9 -218433.9 0 +175941.2 -217671.4 176088.1 175776.1 -217834.8 175487.9 -207552.2 175803 175838.4 175381.7 176060.4 -222797.5 -216891.7 176733.5 175400.8 -219572.9 119711.6 -220109.1 176236.5 176589.9 -210713.1 176486.4 176490.7 -218432.5 0 +175942.2 -217669.4 176087.2 175774.3 -217832.4 175487.9 -207533.8 175803 175839 175382.1 176061.3 -222800.1 -216877.7 176733.5 175399 -219579.2 119827.5 -220094.5 176235.5 176588.7 -210722.9 176486 176489.3 -218432.6 0 +175942.7 -217673.2 176085.5 175772.2 -217835.7 175487.4 -207526.8 175799.4 175839.8 175381.5 176060.5 -222804.1 -216862.3 176733.9 175398 -219576.7 119907.7 -220094.6 176234.1 176586.4 -210766.3 176484.2 176486.5 -218433.8 0 +175943.5 -217676.8 176085.1 175772.5 -217838.3 175488.2 -207536.3 175799.1 175839.3 175381.4 176060.4 -222803.8 -216849.4 176734.6 175398.6 -219581.8 120033.8 -220113.6 176234.5 176587 -210815.3 176484.5 176486.2 -218432.2 0 +175943 -217676.6 176086.3 175774.8 -217838.6 175489 -207558.9 175803.1 175837.7 175382.6 176062.2 -222802 -216850.5 176735.2 175399.2 -219605.6 120223.4 -220133.6 176235.4 176590 -210849.9 176486.9 176489.5 -218428 0 +175941.4 -217675.6 176087.2 175776 -217838.9 175488.4 -207579.1 175804.5 175836.8 175383.3 176063.6 -222803.6 -216866.2 176735.3 175399.7 -219638.8 120425.8 -220137 176234.3 176590.5 -210874.1 176487.7 176491.2 -218428.4 0 +175941.4 -217674.9 176086.5 175775.7 -217840.2 175487.9 -207577.3 175802.1 175837.3 175382.8 176063.5 -222805.9 -216881.3 176735.5 175399.9 -219647.9 120579.6 -220127.8 176233 176588.6 -210880.8 176485.8 176489.2 -218434.1 0 +175941.9 -217674.8 176084.6 175775.8 -217845.6 175487.8 -207532.8 175800.2 175838.2 175382 176062.6 -222804.9 -216888.9 176735.3 175398.8 -219621 120687.6 -220119.5 176233.3 176587.6 -210859.1 176484 176487 -218436.2 0 +175940.4 -217675.7 176083.2 175775.8 -217853.7 175487.2 -207441.1 175800.5 175838.6 175381.2 176061.1 -222801.3 -216895.3 176734.4 175398.2 -219583.5 120804.2 -220121.3 176234.1 176587.7 -210829.2 176484.7 176486.8 -218433 0 +175938.7 -217675.2 176084 175775.1 -217851.5 175486.7 -207330.3 175801.4 175839.3 175380.9 176060.2 -222798.2 -216904.6 176733.8 175399.7 -219546.6 120939.7 -220133.8 176234.7 176588.5 -210810.3 176486.2 176487.9 -218432.2 0 +175939.1 -217673.6 176086.1 175775.6 -217834.4 175487.2 -207235.2 175800.8 175839.6 175380.9 176060.2 -222797.9 -216913.8 176734 175400.7 -219503.5 121042 -220142.4 176235.4 176588.9 -210780.1 176485.8 176488.4 -218434.9 0 +175940.4 -217674.8 176086 175776.8 -217818.2 175488 -207164.3 175798.9 175838.3 175380.8 176059.7 -222798.1 -216917.5 176733.9 175399.7 -219460.5 121081.9 -220138.6 176235.1 176588 -210721.4 176484.2 176486.8 -218436.1 0 +175941.1 -217676.1 176084.1 175776.6 -217815.1 175488.3 -207103.1 175798 175837.5 175381.2 176058.9 -222795.5 -216912.9 176733.7 175398.8 -219422.9 121101.2 -220136.5 176234 176587.5 -210660 176484.1 176485.6 -218436 0 +175941.2 -217674.5 176084.1 175776.2 -217819.6 175488.6 -207034.5 175798.8 175839.1 175382.1 176059.3 -222793 -216898.6 176734.4 175399.3 -219381.7 121153.1 -220144.2 176234.3 176588.6 -210624.5 176486.2 176487.6 -218436.2 0 +175941.3 -217674 176085.8 175776.8 -217822.6 175488.3 -206959.6 175799.4 175840.9 175381.9 176060.6 -222795.3 -216880 176734.8 175399.9 -219341 121237.5 -220151.4 176235.8 176588.6 -210623.9 176487.4 176489.8 -218436.2 0 +175940.4 -217675.1 176085.3 175776.4 -217822.6 175487.1 -206898.5 175799 175840.5 175381.1 176061.5 -222798.7 -216876.3 176733.4 175399.6 -219318.1 121319.1 -220152.5 176235 176586.6 -210654.3 176485.6 176488.5 -218436.2 0 +175939.3 -217671.8 176083.7 175774.7 -217819.9 175486.6 -206862.3 175799.9 175839.5 175381.6 176061.8 -222795.7 -216893.8 176732.5 175399.1 -219314.4 121391.4 -220152.4 176233.3 176586.9 -210686.8 176484.8 176487.4 -218435.1 0 +175939.7 -217667.5 176084.7 175774.2 -217814.2 175487.7 -206830.6 175801.7 175839.3 175382.8 176062.3 -222789.7 -216909.7 176733.9 175399.1 -219322.7 121496.5 -220150.5 176233.6 176589.5 -210694.1 176487.5 176488.5 -218432.3 0 +175940.8 -217668.6 176086.8 175774.8 -217811.1 175487.8 -206779.6 175800.6 175838.7 175382.3 176061.8 -222791.2 -216910.9 176735.2 175398.6 -219350.6 121649 -220137.6 176234.2 176589.7 -210683.5 176488.1 176488.5 -218430.5 0 +175941.1 -217671.1 176087 175774.5 -217817.4 175486.1 -206714.2 175797.4 175837.5 175380.9 176060.1 -222799.7 -216910.5 176735 175398 -219391.8 121781.8 -220111.6 176233.2 176587.5 -210666.3 176485.5 176487 -218431.8 0 +175940.1 -217671.7 176085.5 175774 -217826.4 175485.6 -206640.3 175796.2 175837.3 175380.8 176059 -222806.8 -216916 176733.8 175398.3 -219417.5 121831 -220094 176232.3 176586.5 -210645.1 176482.7 176487.1 -218436.1 0 +175939.1 -217672.6 176084.7 175774.6 -217825.8 175486.1 -206538.1 175797.6 175837.4 175380.8 176059.6 -222806.3 -216919.4 176732.1 175398.9 -219424.5 121834.5 -220102.7 176232.3 176586.8 -210633.5 176481.9 176488.7 -218442.4 0 +175939.8 -217671.1 176085.7 175775.4 -217817.7 175485.6 -206412.7 175799.6 175837.3 175379.8 176060.9 -222799.8 -216920.3 176731.4 175398.6 -219430.6 121868.3 -220119.3 176232 176587.3 -210651.8 176483.1 176489.8 -218446.3 0 +175941.4 -217665.5 176086.6 175775.7 -217813.6 175486.2 -206316.3 175800.7 175837.8 175379.8 176061.8 -222796.8 -216923.3 176733 175398 -219431.9 121931.1 -220123 176232.5 176588.3 -210705.5 176485 176489.3 -218443.5 0 +175941.6 -217662 176085.2 175775.2 -217815.3 175488.6 -206275.7 175800.3 175838.3 175381.2 176061.5 -222801.7 -216922.7 176734.8 175398.7 -219421.5 121991.7 -220127.6 176234.5 176589.3 -210761.2 176485.6 176487.9 -218437.2 0 +175940.1 -217666.5 176083.4 175774.3 -217815.2 175488.8 -206252.1 175799.5 175837.8 175381.8 176060.5 -222808.2 -216917 176734.4 175399.9 -219403.2 122055.8 -220141.2 176235.2 176588.9 -210766.5 176485.1 176487.2 -218434.5 0 +175938.9 -217674.9 176084 175774.7 -217812.4 175486.8 -206195.5 175799.6 175837.7 175380.5 176060.8 -222810.2 -216914.6 176733.4 175399.5 -219379.2 122092.8 -220142.5 176233.8 176588.8 -210721.7 176485 176487.5 -218434.6 0 +175939.8 -217678.3 176085.9 175776 -217812.3 175486.1 -206102.6 175800 175838.1 175379.1 176062.4 -222807.7 -216916 176733.4 175398.3 -219359.5 122054.1 -220128.4 176233 176590.1 -210692.5 176485.5 176488.5 -218434.7 0 +175940.9 -217677.1 176085.4 175775.6 -217813.8 175486.6 -206012.3 175798.9 175837.5 175378.3 176062.3 -222804.6 -216915.4 176733.2 175397.9 -219351.1 121976.7 -220122.3 176233.4 176590.3 -210719.9 176484.8 176488.5 -218438 0 +175940 -217679.7 176083.3 175773.9 -217811.4 175486.7 -205953.4 175798 175836.8 175378.6 176060.5 -222803.3 -216913.5 176732.5 175398.2 -219346.8 121907.7 -220129.6 176233.1 176588.4 -210763.1 176483.8 176488 -218442.8 0 +175939.7 -217687 176084.2 175773 -217805.6 175487.2 -205918.9 175799.2 175838 175380.4 176059.1 -222802.7 -216914.1 176732.7 175398 -219350.2 121830.1 -220138.2 176232.6 176586.9 -210773 176484.8 176488.8 -218442.7 0 +175941.2 -217692.8 176086.9 175773.5 -217802.6 175487.9 -205889.7 175800.1 175840 175382.1 176058.9 -222803.5 -216917.9 176733.1 175398.3 -219369.6 121737 -220140 176232.8 176585.9 -210766.5 176485.3 176489.2 -218437.9 0 +175941.1 -217694.2 176087.1 175774.3 -217806.3 175487.4 -205860.1 175799.8 175840.5 175382 176059.4 -222805.2 -216920.5 176733.5 175399.5 -219398.1 121642.2 -220134.1 176233.2 176585.6 -210781.5 176483.5 176487.4 -218431.7 0 +175940 -217692.6 176085.4 175774.3 -217811.7 175486.9 -205842.3 175800.1 175838.7 175381.2 176060.2 -222804.7 -216918.7 176734.4 175400.5 -219426.5 121532.4 -220128.3 176233.4 176587.5 -210820.9 176482.5 176486.8 -218425.9 0 +175940.5 -217692.3 176083.3 175773.6 -217815.4 175486.5 -205845.1 175799.6 175836 175379.9 176060.2 -222803.8 -216919.8 176733.7 175399.9 -219454.7 121417.9 -220132.1 176233.3 176589.5 -210874.3 176482.3 176487.3 -218425.6 0 +175941.4 -217695.2 176081.5 175773.1 -217818.7 175485.8 -205854.4 175798 175834.6 175378.3 176059.1 -222803.4 -216928.5 176731.7 175398.5 -219489.7 121381.2 -220143.7 176232.6 176590.1 -210927.5 176482.1 176486.5 -218430.1 0 +175940.6 -217696.9 176081.8 175773.5 -217817.8 175485.5 -205860.9 175798.5 175835.5 175377.6 176057.9 -222801.9 -216935 176731.2 175397.7 -219533.3 121474.4 -220156.5 176232.6 176589.9 -210954.1 176483.5 176486.8 -218431 0 +175939.1 -217696 176083.8 175774.5 -217812.6 175485.9 -205871.5 175800.1 175837.8 175377.4 176058.2 -222802.6 -216933.8 176732.5 175398.3 -219574.4 121614.3 -220164.1 176233.5 176587.8 -210942 176484.7 176488.7 -218429.1 0 +175939.2 -217695.4 176084.5 175775.2 -217810.5 175486.7 -205872.6 175799.8 175839.3 175378.3 176060.2 -222804.4 -216931.8 176733.2 175399.3 -219600.4 121692.6 -220160 176233.8 176585.6 -210906.9 176485.1 176488.5 -218428.7 0 +175940.6 -217696.2 176084.2 175774.9 -217809.7 175487.2 -205847.1 175799 175838.5 175380.1 176062.2 -222803.1 -216933.8 176732.9 175399.3 -219602.6 121749.5 -220150 176233.7 176586.4 -210866.9 176486.3 176486.8 -218429.8 0 +175941.3 -217699.7 176084.2 175774.2 -217807.1 175486.3 -205810.4 175798.4 175837 175380.1 176061.9 -222801.9 -216937.3 176732.1 175398.3 -219588.2 121891.4 -220151.8 176234 176587.4 -210826.6 176486.1 176486.6 -218433.9 0 +175940.4 -217702.8 176084.3 175773.7 -217809.3 175485.3 -205773.3 175798.3 175836.1 175379.4 176060.1 -222802.4 -216938.4 176732.2 175397.5 -219580.3 122094.9 -220164.9 176234.2 176587 -210776.5 176483.9 176487.8 -218437.1 0 +175938.9 -217697.2 176084.2 175773.7 -217814.5 175485.5 -205735.6 175799.6 175835.8 175380.5 176060 -222801.5 -216935.9 176733.5 175397.7 -219579.4 122253.1 -220168 176234 176587.7 -210705.2 176483.4 176489.2 -218432.1 0 +175938 -217686.4 176083.9 175774.3 -217811 175486.2 -205731.8 175799.1 175836.4 175381.5 176061.1 -222802.5 -216934.8 176733.9 175397.8 -219564.5 122354.2 -220154.9 176233.6 176587.7 -210627.5 176482.4 176488.3 -218426.3 0 +175937.9 -217681.4 176084 175774.6 -217800.3 175486.4 -205798.7 175796.2 175837.2 175380.5 176061.1 -222805.5 -216937.1 176733 175397 -219531 122458.7 -220136.5 176233 176585.6 -210573.3 176480.3 176485.5 -218426.4 0 +175938.8 -217682.1 176085.1 175773.9 -217795.9 175486.4 -205923.6 175796.8 175837 175379.2 176060.2 -222802.6 -216934.2 176733 175397.4 -219499.2 122561.1 -220117.9 176232.5 176585.6 -210544.3 176482.4 176484.2 -218426.6 0 +175940.8 -217683.6 176085.5 175773 -217801.7 175486.6 -206069.6 175800.5 175836.3 175379.4 176058.6 -222796.6 -216923.4 176733.4 175398.9 -219508.1 122617.8 -220104.1 176232.7 176587.7 -210536.5 176486.7 176484.9 -218426.2 0 +175941.9 -217686.7 176083.7 175773 -217808.4 175486.5 -206210.5 175801 175836.1 175380.3 176057 -222796.2 -216917.5 176732.5 175398.6 -219570.2 122652 -220101 176232.9 176587 -210558.9 176486.9 176484.7 -218431.5 0 +175940.5 -217690 176082.5 175773.8 -217811.5 175486.4 -206339.4 175798.8 175836.1 175380.8 176057.1 -222799.4 -216923.3 176731.9 175396.9 -219632.5 122722.1 -220105.2 176232.5 176584.7 -210581.6 176485.1 176484.7 -218439 0 +175939.1 -217688.4 176084.2 175774.9 -217814.1 175487.1 -206455.3 175798.5 175836.5 175381.7 176058.5 -222801.4 -216931.9 176732.5 175397.2 -219647.8 122822.3 -220115.5 176232.4 176584.6 -210568.2 176484.6 176486.8 -218438.8 0 +175940 -217684.4 176085.8 175775.1 -217817.4 175487.6 -206541.3 175799.2 175836.7 175382.5 176059.5 -222802.9 -216936.1 176733.2 175399.1 -219631.7 122875.9 -220131.3 176232.6 176585.7 -210560.7 176484.6 176488.2 -218429.2 0 +175940.2 -217684 176085.5 175774 -217820 175486.7 -206587.4 175799.9 175836 175381.7 176060.2 -222802.8 -216936.6 176733 175399.3 -219608.6 122830.4 -220139.1 176232.4 176587 -210609.9 176484.8 176487.6 -218420.3 0 +175939 -217685.6 176085.8 175774.2 -217821.3 175486.3 -206613.6 175801.5 175836.4 175380.2 176061.1 -222799.5 -216934.9 176732.3 175397.9 -219586 122725.8 -220128.2 176233.1 176588.9 -210686 176485.8 176487.6 -218422.2 0 +175938.2 -217686.4 176086.9 175775.9 -217821.9 175486.8 -206641.4 175801.8 175837.8 175380.2 176061.1 -222799.5 -216934.3 176731.5 175398 -219573.9 122640.7 -220109.3 176234.3 176588.9 -210736.9 176486.2 176488.7 -218432.1 0 +175937.7 -217689 176086.2 175775.6 -217821.5 175486.7 -206693.5 175799.4 175837.4 175380.8 176060.4 -222805.5 -216936.1 176731.7 175399.1 -219568.5 122593.6 -220104.5 176234.3 176587 -210751.7 176484.6 176487.6 -218436.7 0 +175938.6 -217693.4 176085.1 175773.8 -217819 175486.8 -206807.9 175797.6 175835.5 175380.2 176060 -222809.2 -216936.1 176732.9 175399.5 -219549.5 122546.7 -220121.7 176233.9 176587.3 -210746.2 176483 176484.9 -218429.5 0 +175940.5 -217694.8 176085 175773.8 -217816.8 175487.4 -206977.7 175797.8 175835.8 175379.4 176059.8 -222807 -216934.7 176733.2 175399.2 -219512.8 122479.1 -220143.7 176234.3 176589.5 -210737.9 176483.6 176484.3 -218419.9 0 +175940.1 -217694.1 176085.3 175774.8 -217818 175486.5 -207120.5 175798.1 175838 175379.6 176059.1 -222804 -216935.8 176732.2 175398.6 -219479.6 122408.8 -220149.9 176234.1 176589.3 -210729.7 176484.3 176486 -218417.7 0 +175938.5 -217695 176085.8 175774.1 -217820.4 175485.2 -207183.8 175798.3 175839.3 175380.3 176057.9 -222802.8 -216936.3 176731.5 175397.9 -219471.8 122356.8 -220141.7 176233.3 176587.3 -210715.5 176483.6 176487.4 -218422 0 +175938.7 -217694.4 176086.3 175773.3 -217818.8 175486.2 -207212.1 175798.9 175838.8 175380.4 176058 -222804.6 -216932.7 176730.7 175397.8 -219484 122319.6 -220133.8 176233.3 176586.5 -210696.3 176484.1 176488.1 -218428 0 +175939.5 -217691 176085.4 175773.3 -217812.5 175488.1 -207257.5 175799.6 175837.1 175380 176059.7 -222809.8 -216930.4 176730.2 175397.5 -219486.1 122289.5 -220135.6 176234.2 176586.8 -210672 176485.5 176487.8 -218433 0 +175939.1 -217688 176084.4 175772.7 -217807.4 175488.6 -207308.4 175799.9 175835.6 175379.7 176060.7 -222810.6 -216934.5 176732 175396.1 -219462.2 122274 -220144 176234.8 176586.9 -210644 176485.5 176486.7 -218434.7 0 +175938.7 -217684.3 176084.7 175771.9 -217807.2 175487.7 -207335.9 175799 175835.4 175379.9 176059.9 -222806 -216942 176734.4 175396.3 -219433.3 122281.9 -220147.2 176234.1 176587 -210617 176484.2 176486.2 -218432.7 0 +175938.9 -217680.2 176085.7 175772.3 -217807.3 175486.9 -207339.4 175797.6 175836.2 175380 176058.9 -222806.4 -216945.8 176734.8 175398.7 -219426.3 122314.1 -220145.7 176232.5 176587.7 -210575.2 176484 176486.8 -218431 100 +175939.1 -217680.8 176086.4 175774.5 -217804.9 175486.9 -207332.4 175797.7 175837.2 175379.9 176059 -222812.1 -216943.2 176734.4 175400 -219438.5 122368 -220152.5 176232.1 176588.2 -210506.7 176485.3 176487.7 -218434.7 0 +175939.2 -217686.5 176086.4 175776.4 -217802.9 175486.8 -207329.8 175797.8 175838.5 175380.4 176059.5 -222813.5 -216937 176734.8 175399.2 -219440.7 122436.3 -220162 176232.6 176587.9 -210445.5 176485.8 176487.5 -218440.8 0 +175939.5 -217690.4 176086 175775.8 -217803.3 175485.9 -207345.2 175796.4 175839.2 175380.5 176058.7 -222810.9 -216930.9 176734.4 175398.8 -219426.1 122519 -220159.8 176231.6 176587.1 -210419.1 176483.9 176486.5 -218439.8 0 +175939.7 -217686.4 176086.2 175773.5 -217805.1 175485.3 -207360.2 175796.4 175838.2 175379.3 176057.5 -222809.5 -216925.9 176733 175398.9 -219439.5 122636.3 -220156.9 176230.2 176587.5 -210397.8 176482.5 176486.7 -218430.3 0 +175940.1 -217678.9 176085.8 175772.4 -217804.9 175485.9 -207338.9 175797.3 175836.8 175378 176057.7 -222809.2 -216924.5 176732.4 175398.2 -219504.4 122798.2 -220162.7 176230.6 176588.3 -210353.3 176482.9 176487.2 -218423.2 0 +175940.4 -217677.7 176084.1 175772.9 -217801.5 175486.7 -207301.5 175796.1 175836.5 175378.3 176058.9 -222809.3 -216929 176732.9 175397.3 -219560 122967.4 -220157.8 176232.3 176587.6 -210290.3 176483 176486.5 -218424.2 0 +175939.6 -217681.7 176083.7 175773.2 -217798.5 175487 -207298.2 175796.1 175837 175379.6 176059.3 -222809.8 -216937.4 176733.3 175397.8 -219550.6 123098.3 -220132.7 176233.5 176587.2 -210205.2 176482.9 176486.7 -218424.9 0 +175939.1 -217684.7 176085.2 175773.7 -217799 175487.2 -207320.6 175799.5 175837.4 175381 176058.6 -222810.3 -216943.3 176733 175399.4 -219505.6 123187.9 -220111.2 176234.1 176588.5 -210102.1 176483.7 176488.3 -218421.2 0 +175940.8 -217687.7 176085.5 175775.6 -217801.8 175487 -207334 175800.7 175837.7 175381.2 176058.3 -222809.7 -216941.1 176731.9 175399.5 -219473.5 123245.1 -220114.8 176233.7 176589.1 -210020.3 176483.7 176488.2 -218420.7 0 +175942.4 -217689.4 176084.2 175776.7 -217802.7 175486.4 -207343.4 175797.7 175837.5 175380.3 176059.3 -222807.5 -216931.8 176730.9 175398.7 -219470.1 123274.5 -220136.2 176232.3 176587.2 -209993.4 176482.8 176486.6 -218424.5 0 +175941.4 -217685.9 176084.6 175775.4 -217802.1 175486.7 -207363.1 175796.8 175837.3 175380 176060.6 -222804.3 -216921.6 176731.2 175399 -219492.3 123313.2 -220154.5 176231 176586.4 -210014.9 176483.9 176486.2 -218425.9 0 +175939.5 -217683.5 176086.3 175774.2 -217804.4 175487.5 -207382.5 175799.2 175837.7 175380.3 176060.5 -222803.4 -216915.2 176732.7 175399.5 -219517.6 123387.8 -220160.1 176231.9 176588.8 -210056.9 176486.2 176486.9 -218424.3 0 +175938.5 -217688.6 176085.4 175774.3 -217809.8 175487.6 -207390.3 175799.4 175837.7 175380.4 176059.1 -222806.3 -216915.3 176732.5 175398.6 -219525.9 123446.4 -220156.9 176233.7 176590.1 -210098 176485.8 176486.4 -218423.4 0 +175937.9 -217694 176083.1 175773.9 -217813.2 175487.1 -207380 175797.3 175836.9 175380.3 176058.1 -222809.6 -216922 176730.7 175397 -219518.7 123436.9 -220147.8 176233.9 176587.8 -210128.4 176482.7 176484.7 -218425.4 0 +175938.5 -217692.7 176083.2 175772.5 -217812.2 175486.5 -207358 175797.4 175837.5 175380.3 176058.7 -222809.6 -216929.4 176731.1 175396.6 -219502.6 123402.8 -220135.9 176232.9 176586 -210144.8 176481.2 176484.4 -218429.6 0 +175940 -217688.3 176084.2 175771.7 -217807.1 175485.5 -207366.7 175799 175839.1 175380.1 176059.6 -222810 -216931.5 176733.3 175397.4 -219484.8 123423.6 -220127 176232.2 176586.3 -210160.3 176482.2 176485.1 -218433 0 +175940.5 -217684.7 176083.8 175771.7 -217801.8 175485.4 -207424 175798.5 175838.9 175379.7 176058.7 -222813.8 -216930.6 176733.7 175397.4 -219466.2 123508.1 -220122.6 176231.8 176585.8 -210190.4 176483.3 176484.4 -218432.6 0 +175938.9 -217681.1 176083.7 175772.6 -217799.5 175486.7 -207469 175798.3 175837.5 175379.8 176057.4 -222815.3 -216932.6 176733.6 175396.5 -219436.7 123606.9 -220124 176231.9 176585.1 -210220.5 176484.6 176484.2 -218428.7 0 +175936.9 -217678.7 176084.2 175773.8 -217799.2 175486.9 -207460.8 175799.4 175836.9 175380.3 176057.8 -222810.7 -216932.5 176733.8 175396.7 -219415.3 123686.6 -220133.2 176232.8 176585.6 -210229.9 176485.3 176485.8 -218424.9 0 +175937.2 -217679.4 176083.9 175773.3 -217798.4 175485.8 -207445.3 175799.5 175837.1 175380 176058.4 -222804.6 -216923 176732.6 175397.4 -219434 123736.7 -220138.9 176234 176586.2 -210227.4 176484.6 176487.9 -218422.9 0 +175939.4 -217679.9 176084.3 175773 -217797.3 175485.7 -207462.9 175799 175837.2 175379 176058.5 -222802.1 -216911.4 176732.1 175397.5 -219473.9 123739.8 -220130.8 176234 176587.5 -210240.8 176484.8 176488.9 -218422.4 0 +175940.6 -217678.1 176084.7 175774.5 -217799.5 175486.1 -207490.3 175798.3 175837.4 175378.2 176058.5 -222803.7 -216911.1 176733.1 175397.4 -219492.4 123693.1 -220118.1 176231.8 176587.8 -210279.8 176484.9 176487.7 -218424.2 0 +175940.2 -217677.6 176083.4 175775.8 -217805.5 175485.5 -207492 175797.4 175837.1 175378.8 176058.1 -222805.5 -216919.6 176732.7 175397.7 -219481.7 123636.7 -220116 176230.1 176585.4 -210311.4 176483.4 176485.6 -218426 0 +175939.1 -217678.8 176082.5 175774.5 -217807.8 175484.9 -207473.2 175797.5 175836.6 175380.1 176058 -222804.4 -216925.8 176730.9 175397.7 -219457.6 123618.1 -220123.9 176231.4 176584.3 -210307.3 176482.9 176485.8 -218423.9 0 +175937.6 -217677.8 176083.4 175772.9 -217804.1 175484.9 -207473.4 175797.1 175836.8 175380.8 176058.9 -222803.8 -216929.4 176730.8 175397.2 -219441.7 123652.4 -220129.1 176232.7 176586 -210306 176482.9 176487.2 -218422.3 0 +175937.6 -217674.9 176084.2 175773.1 -217801.7 175484.8 -207516.1 175795.3 175837.4 175380.1 176059.7 -222805.1 -216931.8 176731.8 175396.4 -219444.5 123725.6 -220131.4 176231.6 176587.8 -210347.3 176481.7 176487.3 -218423.7 0 +175939.6 -217673.4 176084.3 175774 -217802.7 175485 -207590.3 175795.6 175837.2 175378.8 176059 -222803 -216925.8 176732 175396.5 -219455 123807.6 -220141.4 176231.2 176588.7 -210401 176482.3 176487 -218421.1 0 +175940.2 -217672 176084.1 175773.8 -217803.7 175485.7 -207686.6 175797.9 175836.4 175378.2 176057.8 -222799.3 -216914.9 176731.5 175397 -219470.7 123879.2 -220156 176232.9 176589 -210424.6 176484.4 176486.6 -218414.4 0 +175938.5 -217670.9 176083.8 175773.3 -217805.2 175486 -207798.9 175798.2 175835.9 175378.4 176057.9 -222801.3 -216911.3 176731.2 175397 -219497.9 123956.7 -220159.4 176233.8 176588.1 -210418.9 176484.5 176485.7 -218412 0 +175937.2 -217672.2 176083.2 175773.2 -217807.8 175485.3 -207899.8 175796.4 175835 175378.6 176058.5 -222806.3 -216912.7 176730.9 175396.8 -219520.5 124047.1 -220146.7 176232.4 176585.3 -210408.3 176482.3 176484.9 -218414.7 0 +175937.1 -217675.1 176082.3 175772.7 -217811.8 175484.1 -207960.4 175795 175833.4 175378.1 176057.9 -222808.2 -216914.3 176730 175397.2 -219527.7 124121.5 -220130.7 176231 176582.6 -210412.9 176480.1 176484.3 -218416.6 0 +175938.1 -217677.2 176082 175771.4 -217816.2 175483.4 -207989.6 175795.9 175833.9 175378 176057.5 -222807.2 -216920 176730 175397.6 -219534.6 124190.4 -220126.4 176231.3 176583.5 -210430.3 176480.1 176484.3 -218417.9 0 +175939.2 -217675 176083.3 175771.8 -217815.6 175484.9 -208034.5 175799.1 175837 175379.3 176058.7 -222805.7 -216925.3 176732.4 175397.1 -219547.3 124297.8 -220130.6 176232.5 176586.8 -210446.5 176482.5 176485.7 -218420.2 0 +175939.3 -217668.6 176085.1 175775 -217808.8 175487.9 -208131.1 175800.4 175838.5 175380.5 176060 -222806.4 -216922.8 176734.6 175396.7 -219549.7 124415.3 -220130 176233.5 176588 -210465.2 176483.7 176486.8 -218422.2 0 +175939 -217667.7 176085.6 175777.2 -217804 175489.1 -208250.8 175797.9 175836.7 175380.7 176059.9 -222808.8 -216919.5 176733.4 175397.4 -219531.8 124478 -220124.8 176233.5 176586.6 -210495.4 176483 176486.1 -218423.4 0 +175938.3 -217676 176084.5 175775.6 -217806.7 175487.6 -208331.7 175795.9 175834.3 175379.7 176059.2 -222808.1 -216923.8 176730.8 175397.3 -219507.3 124499.6 -220122.8 176232.7 176585.8 -210525.3 176483.3 176485.5 -218422.4 0 +175936.6 -217680.6 176083.6 175772.4 -217811.2 175485.9 -208364.5 175797.3 175834.2 175378 176058 -222805.3 -216929.5 176730.5 175395.1 -219498.3 124550.8 -220123.5 176231.8 176586.4 -210536.9 176484.6 176486.4 -218417 0 +175936.6 -217676 176083.5 175771 -217809.5 175485.4 -208393.7 175798.9 175835.7 175377.3 176056.6 -222805.8 -216926.3 176731.7 175394.5 -219511.2 124673.3 -220124 176231.4 176586.4 -210536.8 176484.4 176487.4 -218412 0 +175938.6 -217672.4 176083.1 175771.7 -217805 175485.3 -208435.3 175798.1 175836.7 175378.2 176056.1 -222809.3 -216915 176731.8 175396.5 -219535.2 124851.6 -220127.8 176231.8 176584.9 -210549.3 176482.6 176487 -218414.8 0 +175939.9 -217672.5 176082.7 175772.9 -217804.7 175485.3 -208453.6 175797.2 175836 175378.8 176056.9 -222809.6 -216905.9 176731.7 175397.8 -219552.3 125043.9 -220132.5 176232.1 176584.3 -210573.1 176481.7 176486.4 -218419.8 0 +175939.5 -217672.3 176084.2 175773.5 -217805.9 175485.6 -208440.9 175798 175834.7 175379.2 176058 -222804.1 -216907.6 176733 175397.4 -219554.9 125235.1 -220123.3 176231.8 176586.5 -210578.2 176483.1 176486.6 -218417.5 0 +175939 -217674 176084.9 175773.5 -217805.5 175485.4 -208450.6 175798.9 175834 175379.8 176058.9 -222799.5 -216916.5 176733.3 175397.2 -219565.3 125443.8 -220097.3 176231.5 176588 -210559.4 176484.6 176486.7 -218413 0 +175938.1 -217677.7 176082.8 175772.9 -217806.3 175484.8 -208509 175798.7 175834.5 175379.5 176059.3 -222799.9 -216920.9 176731.3 175397.7 -219605.8 125683.2 -220071.5 176231.8 176586.6 -210549.4 176484.7 176486.2 -218414.6 0 +175936.8 -217678.4 176080.7 175772.3 -217809 175484.3 -208579.9 175798 175835.2 175378.8 176058.6 -222801.4 -216920.1 176730.2 175397.4 -219656.9 125933.8 -220064.2 176232.3 176584.9 -210569.9 176484.2 176485.5 -218418.6 0 +175936.2 -217674.3 176081.1 175771.7 -217809.2 175484.1 -208635.4 175797 175834.8 175378.5 176057.3 -222802.8 -216924.1 176730.9 175396.1 -219697.5 126168.9 -220077.4 176231.8 176583.7 -210603.2 176482.9 176484.5 -218419.3 0 +175936.7 -217668.5 176082.4 175772 -217806.8 175484.5 -208670.2 175796.9 175834.2 175378.1 176057.2 -222806.3 -216931.6 176731.4 175395.6 -219740 126395.7 -220097.8 176231 176583.3 -210622.5 176482.1 176484.6 -218417.3 0 +175937.5 -217665.7 176083.1 175772.7 -217808.3 175485.6 -208672.4 175798.4 175835 175378.3 176057.9 -222809.3 -216932.2 176731.4 175396.8 -219786.1 126613.5 -220119.4 176231 176585.1 -210624.3 176483.5 176486.6 -218415.9 0 +175937.8 -217667.3 176082.9 175772.1 -217815.6 175485.3 -208649 175798.6 175835.9 175379.2 176057.8 -222809.1 -216926.5 176730.9 175397.8 -219810.5 126780.5 -220141.5 176231 176586.4 -210616.9 176483.5 176486.4 -218417.6 0 +175937.5 -217670.7 176082.1 175771.9 -217821.9 175483.7 -208626.4 175797.1 175836 175380.1 176057.2 -222807.3 -216924.4 176730 175397.2 -219808.3 126888.9 -220148.6 176230.4 176584.8 -210604.1 176480.9 176483.5 -218420.3 100 +175937.6 -217671.6 176081.4 175772.9 -217822.5 175483.2 -208610 175796.3 175835.9 175380 176057.1 -222806.9 -216927.9 176729.6 175396.5 -219799 126975.6 -220135.5 176230.7 176583.9 -210597 176479.3 176482.3 -218420.4 0 +175938.4 -217669 176081.1 175772.6 -217821.3 175484.1 -208578.5 175796.3 175835.1 175378.1 176057.3 -222809 -216930.3 176729.5 175396.1 -219789.3 127037.6 -220122.1 176231.7 176585.2 -210612.1 176479.9 176483.5 -218418.8 0 +175938.7 -217667.9 176081.9 175770.9 -217821.2 175485.1 -208507.9 175796.9 175834.1 175375.5 176057.5 -222810.7 -216929 176730 175396 -219776.4 127044.7 -220118.4 176231.9 176585.7 -210645.3 176480.8 176484.7 -218415.7 0 +175938.7 -217672 176082.9 175770.2 -217819.1 175485.6 -208406 175797.5 175834.8 175375.5 176057.7 -222810.4 -216927.2 176731.5 175396.7 -219771.5 126997.8 -220122.5 176231.4 176584.6 -210676.1 176481 176485.3 -218413 0 +175939 -217676.1 176082.9 175771.3 -217812.9 175485.6 -208339 175797.3 175836.4 175377.7 176057.8 -222807.9 -216925.2 176732 175397 -219782 126924.9 -220134.2 176230.7 176583.9 -210689.9 176481.3 176485.5 -218413.6 0 +175938.3 -217674.9 176082.9 175772.4 -217809.8 175485.4 -208365.1 175798.1 175836.8 175379.1 176057.8 -222803.6 -216923.3 176731.1 175395.8 -219794.2 126863.9 -220138.3 176230.6 176585.3 -210681.6 176483 176485.8 -218415 0 +175937.3 -217671.6 176083.5 175772.8 -217815 175485.3 -208436.3 175799.1 175835.7 175378.6 176057.9 -222803 -216927.1 176730.5 175395.5 -219800.3 126838.8 -220120.8 176231.5 176587.3 -210652.2 176484.3 176485.6 -218416.7 0 +175938.7 -217669 176084.1 175773 -217822 175484.9 -208458.3 175798.6 175835.2 175377.9 176057.8 -222808.2 -216934.1 176730.8 175397.4 -219820.8 126834.3 -220099.9 176232.2 176587.7 -210607.2 176483.3 176484.7 -218421.7 0 +175940.9 -217667.4 176084.6 175773.6 -217823.8 175484.9 -208424.8 175799 175836.1 175378 176058 -222811.3 -216937 176731.2 175398.9 -219871.5 126841.7 -220095.1 176232.1 176587.4 -210555.2 176482.5 176484.8 -218424.3 0 +175940.4 -217667.9 176085.2 175773.8 -217822 175485.9 -208400.8 175799.8 175837.2 175378.5 176059.1 -222808.9 -216937.6 176731.7 175398.8 -219931.1 126907.2 -220093.6 176231.9 176586.5 -210516.1 176482.5 176485.7 -218421.6 0 +175937.6 -217670.2 176084.7 175772.7 -217819.4 175485.6 -208421 175797.9 175836.8 175379.2 176059.8 -222806.8 -216937.9 176732.1 175398 -219974.7 127054.9 -220081.4 176231.7 176584.5 -210519 176481.7 176484.9 -218420.9 0 +175935.1 -217670.3 176083.3 175770.8 -217815 175484 -208468 175796.4 175835.6 175379 176058 -222806.5 -216933 176731.9 175397.3 -220001.1 127204.4 -220070 176231.4 176584.3 -210568.6 176482 176483.9 -218421.7 0 +175934.5 -217668 176082.3 175769.9 -217810.2 175483.9 -208504.6 175798.3 175834.5 175378.5 176055.4 -222806.7 -216925.8 176731.3 175397 -220007.8 127271.3 -220077.8 176231 176586.2 -210628.3 176483.6 176484.8 -218419.3 0 +175936.4 -217666 176080.8 175770.5 -217808.8 175484.9 -208507.3 175798.6 175833.5 175378.5 176054.3 -222810.1 -216927.4 176730.5 175396.3 -219984.5 127283 -220105 176230.8 176585.7 -210665.8 176482.3 176485.4 -218419.7 0 +175939.8 -217665.4 176080.1 175771.4 -217807.2 175484.6 -208486.4 175795.6 175833.3 175378.2 176054.4 -222813.6 -216937.2 176729.8 175395.3 -219939.1 127288.3 -220130.7 176230.8 176583.8 -210692.7 176479.2 176484.1 -218426.1 0 +175940.9 -217665.4 176081.9 175771.7 -217800.8 175484.3 -208458.1 175795 175834.4 175377.7 176054.9 -222809.5 -216941.1 176730.2 175395.6 -219895.9 127276.9 -220136.7 176231.3 176585 -210732.8 176479.2 176483.9 -218428.1 0 +175938.4 -217667 176083.2 175771.3 -217798.8 175485.2 -208417.7 175797.6 175835.1 175377.5 176056 -222800.9 -216934.8 176730.8 175396.4 -219870.8 127246.7 -220130.6 176231.5 176587 -210788.4 176481.8 176485.2 -218422.6 0 +175936.4 -217670.4 176081.6 175770.7 -217805.4 175485.6 -208369.7 175798.1 175835 175376.9 176057.5 -222798.1 -216928.9 176730.8 175396.7 -219859.6 127210.9 -220127.5 176231.6 176586.4 -210844.4 176482.8 176485.1 -218419 0 +175937.9 -217670.9 176081.4 175771.3 -217806.9 175485 -208336.6 175797.1 175835.1 175376.7 176059.4 -222800.6 -216929.6 176731.9 175397 -219846.6 127174.9 -220123.5 176232.6 176586.5 -210878.9 176482.9 176485 -218420.1 0 +175940.5 -217667.3 176083.5 175773.5 -217798.3 175485.2 -208325.8 175797.6 175834.5 175377.5 176060.8 -222802 -216932.3 176734 175397.2 -219823.3 127167.9 -220114.7 176234 176588.2 -210895 176483.7 176486.1 -218422.8 0 +175941.3 -217666.3 176083.7 175774 -217789 175485 -208334 175797.3 175833 175377.8 176059.8 -222803.5 -216933.4 176732.8 175396.4 -219796.6 127188.8 -220113.1 176233.3 176587.5 -210925.8 176483.1 176485 -218429 0 +175939.7 -217668.8 176082.3 175772 -217784.5 175484 -208361.5 175796.1 175832.8 175377.7 176057.5 -222806.3 -216934.7 176729.6 175396 -219774.8 127181.1 -220119.9 176230.8 176585.3 -210968.2 176481.3 176482.2 -218433.8 0 +175937.6 -217670 176082.1 175770.8 -217786.5 175484.8 -208401 175796.7 175834 175378 176056.6 -222806.2 -216938.1 176730 175396.1 -219756.5 127148 -220120.9 176229.8 176585.2 -210984.5 176481.7 176482.5 -218428.5 100 +175936.9 -217672.2 176082.8 175771.8 -217794.2 175486.5 -208450.4 175796.8 175835.1 175378 176056.7 -222804.2 -216939.8 176732.3 175395.4 -219737.5 127152.7 -220120.3 176230.9 176585.3 -210984.6 176483.3 176485.5 -218421.3 0 +175937.2 -217676.2 176082.9 175772.3 -217800.1 175485.9 -208508.1 175794.5 175835.4 175377.2 176056.9 -222804.7 -216936.2 176731.8 175394.2 -219714.8 127213 -220128.6 176232.2 176584 -211015 176483.2 176486.1 -218421.8 0 +175937.5 -217674.9 176082.8 175771.6 -217799 175484.2 -208550.3 175793.6 175835.2 175375.9 176057.8 -222803.8 -216931.9 176730.5 175394.4 -219685.3 127312.7 -220130.4 176232.5 176584.2 -211087.6 176482.6 176484.4 -218422.3 0 +175938.3 -217668.2 176083.1 175771 -217794.1 175484.3 -208561.8 175795.7 175835 175375.8 176059.1 -222801.1 -216932.1 176731.4 175396 -219658.8 127431.5 -220116.3 176232.1 176585.7 -211176 176483.1 176483.8 -218417.5 0 +175939.1 -217664.2 176083.7 175772.1 -217791.2 175485.1 -208561.3 175797.4 175834.9 175377.9 176059.3 -222801.4 -216935.1 176732 175396.8 -219649.9 127542.7 -220107.8 176231.8 176586.3 -211245.5 176483.3 176484.8 -218415 0 +175938.5 -217664.9 176083.4 175773.1 -217793.9 175484.1 -208567.7 175796.7 175834.9 175379.9 176058.4 -222802.5 -216934.2 176731.4 175396.4 -219646.8 127654.1 -220114.3 176231.3 176586 -211282.1 176482.2 176485.7 -218418.3 0 +175936.4 -217668.1 176082.6 175772.4 -217799.5 175482.4 -208577.2 175795.4 175835 175379.2 176056.9 -222799.7 -216924.6 176731.2 175396.3 -219624 127809.1 -220116.8 176229.9 176585.3 -211311.8 176481.4 176485.4 -218421.2 0 +175934.4 -217672 176083.2 175771.8 -217802 175482 -208581.2 175795.9 175835.2 175377.8 176055.4 -222796.5 -216913.5 176731.3 175396.3 -219581.8 128020.8 -220107 176229.1 176584.9 -211365.9 176481.9 176484.4 -218419.1 0 +175934.6 -217674.1 176083.4 175772.3 -217799.7 175483.2 -208598.1 175796.6 175834.6 175378.4 176055 -222798 -216914.8 176731.1 175395.6 -219545.8 128233.6 -220094.5 176229.7 176584.9 -211442 176481.5 176483.6 -218415.5 0 +175937.2 -217673.2 176082.4 175772.8 -217797.4 175484.7 -208653 175795.5 175833.9 175379.2 176056.3 -222801.7 -216924.2 176730.8 175394.6 -219529.7 128376.8 -220083.7 176230.3 176584.2 -211522.2 176480.4 176483.5 -218415.3 0 +175939 -217671.1 176082.7 175773.2 -217799 175485.1 -208722.9 175795.2 175834.3 175378.4 176057.6 -222802.4 -216924 176730.3 175394.3 -219524.1 128449.1 -220080.7 176229.8 176583.8 -211588.5 176481 176484 -218418.5 0 +175937.6 -217669 176083.6 175773.9 -217802.3 175485 -208765 175797 175835.1 175377 176057.8 -222800.6 -216913.1 176731 175395.8 -219525.8 128509 -220092.7 176229.6 176585.3 -211618.5 176481.7 176484.5 -218421.5 0 +175935.4 -217667.2 176082.3 175773.6 -217803.6 175485.2 -208781.9 175797.9 175835.7 175376.6 176057.4 -222799.8 -216907.8 176732.5 175397.7 -219544.7 128612 -220107.8 176230 176587 -211622.1 176480.7 176484.4 -218421.1 0 +175935.6 -217668.1 176081.5 175772.9 -217804.1 175485.6 -208802.7 175797.8 175836.7 175377.8 176057.1 -222799.6 -216915.2 176732.1 175398.3 -219579.8 128779.6 -220113.5 176231 176587 -211654.8 176480.5 176484 -218418.4 0 +175937.3 -217672.2 176083.4 175772.7 -217805.3 175486.4 -208841.5 175798.6 175836.9 175379.4 176057.3 -222799 -216924.8 176730.4 175397.7 -219627.1 128978.8 -220120.2 176232.3 176586.5 -211737.3 176481.3 176483.6 -218417.7 0 +175937.6 -217674.8 176084.2 175773 -217804.5 175486.7 -208893.9 175798.5 175836.2 175379.3 176058.1 -222800.2 -216927.7 176730.2 175396.8 -219689.9 129155.8 -220131.4 176232.1 176586.5 -211822.3 176481.2 176483.4 -218419.6 0 +175936.8 -217673.7 176082.5 175773.9 -217801.3 175485 -208945.7 175796.5 175835.8 175377.2 176058.1 -222803.3 -216926.8 176731 175396.3 -219748.7 129310.1 -220134.7 176230.2 176586.2 -211877.2 176480.6 176483.6 -218420.8 0 +175938 -217671.1 176081.2 175774.9 -217800.9 175483.5 -208985.6 175795.4 175835.9 175375.9 176057 -222803.9 -216925.7 176730.5 175396.3 -219770.3 129474.8 -220131.3 176229.5 176585.2 -211928.5 176480.1 176484 -218419.6 0 +175940.5 -217667.1 176081.7 175774.4 -217806.1 175484.5 -209009.5 175796.5 175835.4 175377 176057.4 -222801.3 -216922 176730 175395.8 -219760.3 129655.6 -220129.9 176231.2 176584.3 -211996.7 176480 176484.7 -218419.4 0 +175940.2 -217661.7 176082.3 175772.5 -217810.7 175486.3 -209021 175797.7 175834.8 175378.2 176059.8 -222798.7 -216917 176731.2 175395.6 -219755.8 129822.3 -220126.2 176232.2 176584.1 -212052.8 176481.7 176486.3 -218421.7 0 +175938.2 -217658.8 176081.7 175771.2 -217808 175486.7 -209034.1 175797.5 175834.8 175377.8 176060.1 -222796.3 -216917.1 176732.5 175396.6 -219769.8 129947.1 -220117.3 176230.6 176584.4 -212082 176483.9 176486.6 -218423.8 0 +175937.5 -217661.4 176080.6 175771.2 -217799.1 175485.4 -209063.6 175796.1 175834.9 175377.1 176057.1 -222794.6 -216923.3 176731.8 175396.8 -219781 130052.9 -220110.5 176228.7 176584.3 -212120.4 176482.7 176484.6 -218424.8 0 +175937.8 -217665.7 176080.6 175771.4 -217791.5 175483.1 -209112 175794.7 175834.7 175376.8 176055 -222796.1 -216928.2 176730.3 175395.5 -219776.3 130187 -220111.6 176229.1 176583.6 -212189.5 176480.1 176483.1 -218424.9 0 +175937.7 -217664.7 176082 175771.7 -217788.9 175482.1 -209166.9 175795.1 175835 175377.1 176056.1 -222801.1 -216926.6 176729.4 175395.1 -219773.7 130356.1 -220117.9 176230.7 176583.8 -212266.6 176480.5 176484.3 -218422.9 0 +175937.2 -217658.8 176083.1 175773.4 -217790.5 175482.8 -209210 175797.2 175835.6 175377.7 176057.9 -222808.1 -216921.4 176729.1 175396.4 -219792.3 130543.7 -220127.6 176230.9 176585 -212328.8 176482 176484.7 -218421.7 0 +175936.5 -217654.9 176082.7 175774.7 -217794.6 175484.1 -209231.2 175798.7 175834.8 175377.8 176057.5 -222811.4 -216917.7 176729.1 175397 -219815.2 130749 -220146.2 176230 176586.3 -212361.1 176481.5 176483 -218422.6 0 +175936.7 -217655.5 176081.9 175773.1 -217797.4 175484.8 -209243.6 175797.7 175833.2 175377.8 176055.7 -222806.1 -216919.2 176729.1 175396 -219812.9 130962.9 -220164.7 176229.8 176586.1 -212362.4 176481.3 176482.5 -218422.1 0 +175937.3 -217659 176081.2 175770.7 -217795.8 175484.5 -209271.7 175794.6 175832.8 175377.8 176055.3 -222798.7 -216924 176729.4 175394.9 -219789.4 131158.2 -220157.2 176229.8 176583.8 -212358.2 176482 176483.3 -218421.2 0 +175936.5 -217664.1 176080.9 175769.8 -217793.4 175484 -209311.5 175793 175832.9 175377.7 176056.6 -222797 -216922.1 176730.6 175394.5 -219768.7 131313 -220126.9 176229.5 176582.4 -212358.9 176481.5 176483.2 -218421.1 0 +175936 -217667.1 176082.1 175770.6 -217795.8 175484.6 -209339.6 175795.3 175833 175378.2 176057.6 -222800.6 -216909.7 176731.6 175394.9 -219756 131418.6 -220106.3 176230.4 176584.5 -212349.5 176481.5 176483.9 -218417.8 0 +175937.1 -217665.9 176083.5 175772.3 -217801.6 175485.5 -209357.8 175798.3 175834 175379.2 176057.6 -222806 -216897.6 176731.2 175396 -219746.4 131477.4 -220104.8 176231.6 176587.1 -212344 176483.2 176485 -218413.9 0 +175937.7 -217663.8 176082.5 175773.1 -217804.2 175484.8 -209375.5 175798.4 175835.2 175378.9 176057.8 -222807.7 -216894.4 176729.8 175397.1 -219749.5 131506.4 -220111.6 176230.6 176587.1 -212375.3 176483.1 176484.5 -218417.1 0 +175936.1 -217662.3 176080.8 175772 -217798.4 175483.7 -209380.7 175797.3 175835.2 175377 176058.1 -222800.7 -216898.3 176728.9 175396.7 -219772.7 131528 -220123.9 176229.3 176586 -212435.4 176480.8 176484.4 -218422.1 0 +175933.8 -217660 176080.5 175769.9 -217789.8 175483.5 -209371.5 175796.6 175834.4 175375.4 176057.5 -222790.4 -216906.2 176729 175394.5 -219798.6 131553.1 -220135.1 176229.3 176585.4 -212495.7 176480 176485.4 -218419.3 0 +175934 -217658.4 176080.2 175769.2 -217789.6 175483.1 -209366.5 175795.9 175833.8 175375.5 176056.5 -222787.8 -216916.5 176729.2 175393.2 -219802.7 131583.6 -220133.8 176229.2 176584 -212556.8 176480.7 176484.7 -218412.7 0 +175936.6 -217659.6 176080.7 175770.9 -217797.1 175482.2 -209371.3 175795.8 175833.4 175377.2 176057.1 -222794.3 -216925.7 176729.2 175393.8 -219785.9 131596.6 -220126.8 176229.2 176582.5 -212624 176481.1 176483.1 -218410.3 0 +175938.4 -217662.9 176083.1 175773.1 -217803.1 175482.8 -209386.8 175796.7 175834.1 175378.3 176059 -222799.7 -216930.3 176729.8 175394.6 -219776.8 131551.9 -220128.4 176230.9 176583.5 -212684.6 176481.5 176483.6 -218411.3 0 +175937.4 -217666.9 176084.4 175773 -217807.5 175484.4 -209424.2 175797.1 175835.6 175378.4 176059.4 -222798.3 -216930.5 176730.1 175395 -219794.5 131463.3 -220138.2 176232.1 176585.3 -212734.7 176481.2 176484.4 -218412.9 0 +175935.6 -217670.3 176082.4 175771.6 -217811 175484.3 -209477.8 175796.6 175835.5 175378.6 176057.5 -222795 -216927.8 176729.1 175395.4 -219821.3 131393.2 -220147.4 176231.3 176585.3 -212778.4 176480.3 176483.5 -218414 0 +175935.5 -217671.3 176080.4 175770.9 -217809.3 175484.1 -209527.3 175798.3 175833.6 175378.4 176056.4 -222794 -216919.2 176729.3 175395.8 -219828.2 131367.2 -220147.4 176231.3 176586.4 -212817.9 176482.4 176483.2 -218411 0 +175936.1 -217669.8 176080.4 175770.9 -217805.1 175485.5 -209568 175801.1 175832.9 175377.3 176057.1 -222795.6 -216906.8 176731.6 175395.8 -219810.8 131360.1 -220130.6 176232.5 176588.5 -212870.1 176485.7 176483.7 -218405.5 0 +175936.1 -217668.7 176080.1 175771.2 -217806.4 175485.5 -209599.1 175798.2 175833.4 175376.6 176056.6 -222800.1 -216904 176732.2 175395.3 -219783.4 131331.4 -220106.6 176231.7 176586.5 -212941.2 176483.7 176482.5 -218406.8 0 +175936.3 -217668.6 176079.6 175770.8 -217810.8 175483.3 -209614.1 175792 175833.2 175376.8 176054.6 -222802.8 -216912.8 176730.1 175394.6 -219752 131263.3 -220096.5 176229.7 176582.4 -212990.7 176479.1 176481.4 -218412.5 0 +175937.5 -217669.7 176080.7 175769.5 -217812.2 175481.7 -209622.3 175791.9 175832.6 175376.9 176054.2 -222800 -216916.9 176729.2 175394 -219715.2 131191.3 -220106.7 176229.6 176581.6 -212983.4 176478.5 176483 -218413.4 0 +175937.7 -217674.7 176081.9 175769.1 -217811.4 175480.5 -209642.9 175795.2 175832.5 175376.3 176055.2 -222798.5 -216913.5 176729.8 175393.7 -219681 131156.5 -220125.5 176230.5 176582.5 -212944.8 176480 176484.3 -218414.7 0 +175936.3 -217680.9 176081 175770.1 -217810.5 175479.8 -209668.1 175794.3 175833.4 175375.7 176055.3 -222803.2 -216915.7 176729.4 175393.5 -219659.6 131141.5 -220143.3 176230.2 176581.7 -212921.9 176479.8 176482.8 -218422.6 0 +175935.5 -217682 176079.7 175770.6 -217807.1 175481.5 -209670 175792.9 175834.2 175376.2 176055.1 -222806.8 -216921 176728.4 175393.6 -219645 131086.4 -220158.2 176229.2 176581.5 -212932.7 176479.6 176481.5 -218425.9 0 +175936.6 -217681.2 176080.1 175770.2 -217804.3 175484.2 -209664.6 175794.9 175833.2 175376.9 176055.5 -222804.9 -216920.8 176728.7 175394.3 -219620.2 130963.2 -220170.7 176228.6 176584 -212967.1 176480.5 176482.7 -218419.6 0 +175938.2 -217684.5 176080.8 175770.3 -217810.2 175484.9 -209700.2 175795.4 175831.5 175376.9 176055.5 -222804.6 -216921.4 176729.3 175395.9 -219577 130826.4 -220176.8 176228.7 176585.3 -213000.8 176480.8 176483.6 -218415.7 0 +175939 -217689.4 176080.6 175770.2 -217820.8 175483.7 -209765.3 175793.2 175831.5 175376.6 176055.1 -222807.4 -216924.2 176728.8 175397.5 -219527.8 130749.9 -220172.5 176229.2 176583.8 -213007.4 176480.7 176482.8 -218417.8 0 +175937.8 -217691 176080.9 175770 -217823.4 175482.8 -209804.7 175793.6 175833 175376.8 176054.7 -222806.4 -216922 176728.2 175397 -219495.8 130740 -220160.5 176229.7 176582.7 -212982.6 176481.7 176482.4 -218418 0 +175935.3 -217689.6 176081.5 175770.9 -217817.3 175483.1 -209810.3 175795.7 175833.8 175377.3 176054.2 -222803.3 -216918.9 176728.8 175395 -219493.2 130759.5 -220147.5 176229.9 176582.7 -212947.9 176481.9 176483.1 -218415.5 0 +175934.5 -217688.6 176081.8 175771.8 -217810.2 175484 -209806 175795.2 175834.3 175377.8 176054.7 -222805.2 -216915.5 176729.4 175394.1 -219512.3 130771.3 -220139.5 176230 176582.1 -212913.6 176480.2 176483.8 -218413.7 0 +175936.2 -217688.2 176081.6 175771.7 -217805.3 175483.7 -209802.5 175794.4 175834.5 175378 176055.6 -222808.8 -216904.5 176728.5 175394.5 -219533.1 130756.4 -220142.5 176229.5 176582.1 -212857.8 176479 176483.5 -218412.5 0 +175936.7 -217682.1 176080.7 175771.6 -217801.9 175482.5 -209805.8 175796.5 175833.8 175377 176055.5 -222807.8 -216898.3 176727.6 175394.1 -219537.2 130758.3 -220155.1 176229.1 176583.9 -212775.3 176480.7 176483.2 -218410.5 0 +175935.5 -217668.8 176080.3 175771.5 -217799.5 175482.5 -209828.9 175798.6 175833 175376.5 176054.9 -222805.7 -216911 176728.8 175393 -219527.7 130834.9 -220169.3 176230.1 176585.5 -212716.3 176483.9 176484 -218409.6 0 +175936.4 -217660.1 176081 175771.2 -217795.9 175483.6 -209882.9 175796.5 175832.5 175377.9 176055 -222807.7 -216928.6 176730.7 175392.9 -219526.2 130945.3 -220182.3 176231.3 176584.9 -212721.6 176483.8 176483.9 -218413.7 0 +175938.8 -217663 176081.4 175770.7 -217791.3 175484.1 -209945.5 175792.6 175833 175379.5 176055.1 -222810.8 -216934.7 176731.2 175394.6 -219531.1 130996.3 -220190.3 176230.9 176582.9 -212758.7 176480.1 176482 -218420.9 0 +175938 -217668.2 176080.8 175769.9 -217791.1 175483.4 -209961 175792 175833.5 175378.7 176055.3 -222809 -216933 176730.4 175396.5 -219513.1 130960.6 -220186 176230.4 176582.5 -212766.2 176479 176482 -218422.9 0 +175935.2 -217667.9 176080 175769.5 -217795.4 175482.5 -209924.4 175794.5 175832.8 175376.9 176056 -222804.6 -216931.9 176729.3 175396.6 -219467.8 130889.4 -220173.4 176230.7 176583.7 -212722.7 176480.8 176484.4 -218418.3 0 +175935.4 -217666.6 176079.5 175770.4 -217797.9 175482.3 -209912.2 175795.7 175832.1 175376.5 176056.5 -222804.8 -216932 176728.9 175395.5 -219420.1 130849.5 -220162.7 176230.5 176583.6 -212652.6 176480.2 176484.9 -218416.3 0 +175937.5 -217667.5 176079.7 175771.7 -217798 175482.5 -209978.6 175794.6 175832.7 175376.8 176056.4 -222808.2 -216929.1 176730.1 175394.3 -219384 130834.1 -220153.5 176229.6 176582 -212587.9 176478.6 176483.9 -218418.8 100 +175937.4 -217667.4 176080.7 175771.9 -217799.5 175482.9 -210092.3 175794.4 175832.9 175375.9 176056 -222806.9 -216923.6 176731.2 175392.9 -219364.1 130770.9 -220142.3 176228.8 176581.7 -212537.7 176480.1 176484 -218418.6 0 +175936.1 -217665.9 176081.2 175771.5 -217800.7 175483.3 -210204.6 175795.4 175831.7 175374.7 176055.7 -222802.8 -216923 176730 175392.4 -219358.7 130659.1 -220134.7 176228.3 176582.2 -212501.5 176481.6 176483.7 -218416.2 0 +175935.6 -217664.7 176080.2 175771 -217799.2 175482.7 -210303.1 175795.1 175831 175375 176054.8 -222803.1 -216928 176728.1 175393.7 -219350.1 130572.8 -220136.1 176228 176581.5 -212491.7 176480.1 176482.3 -218416.7 0 +175936.1 -217663.7 176079.6 175770.5 -217796.8 175481.4 -210388.2 175793.9 175832.5 175376.6 176054.7 -222805.1 -216930.9 176728.4 175395.5 -219328.6 130527.2 -220143.7 176227.9 176581.8 -212512.2 176479.3 176482.2 -218417.1 0 +175937.6 -217662.4 176080 175770.6 -217797.6 175481.2 -210459.8 175793.3 175834.3 175378 176056.5 -222804.9 -216932.1 176728.9 175396.1 -219301.8 130481.8 -220152.6 176228.9 176583.8 -212541 176480.5 176483.2 -218414.2 0 +175938.3 -217659.7 176079.7 175771.3 -217801.4 175481.8 -210520.1 175792.8 175834 175377.5 176057.1 -222806 -216936 176727.1 175395 -219272.4 130432.3 -220161 176229.9 176584.3 -212558.3 176479.8 176482.4 -218412.9 0 +175936.1 -217655.7 176079.7 175771.5 -217801.5 175481.9 -210550 175793.5 175832 175375.2 176055.1 -222807.5 -216934.3 176725.7 175393 -219246.7 130407 -220166.7 176228.2 176583.3 -212565.1 176478.5 176480.3 -218414.2 0 +175932.9 -217653.3 176081.1 175770.6 -217795.7 175482.5 -210527.2 175795.6 175830.7 175373.3 176053.9 -222805.9 -216922.3 176726.8 175392.9 -219238.6 130421.1 -220167.1 176225.5 176584.1 -212562.1 176480 176480.5 -218413.5 0 +175932.5 -217653.9 176081.7 175769.7 -217791.3 175484.3 -210477.8 175796.7 175831.3 175374.1 176055.2 -222805.8 -216912.6 176728.4 175394.9 -219244.7 130463.9 -220161.4 176226.6 176585.3 -212544.7 176481.8 176483.1 -218412.1 0 +175935.8 -217654.8 176080.4 175769.6 -217791 175484.9 -210453.7 175796.8 175832.9 175376.6 176056.2 -222808.6 -216911.8 176728.6 175395.8 -219255.3 130518.8 -220153.6 176230.6 176584.9 -212516.7 176481.2 176484.8 -218414.8 0 +175938.1 -217655.3 176079.5 175769.9 -217790.3 175483.3 -210467.6 175796.1 175833 175377.8 176055.6 -222807.7 -216913.4 176727.6 175394.3 -219278.7 130583.5 -220152.6 176231.6 176583.5 -212488.8 176479.4 176484.2 -218418.8 0 +175936.3 -217658.7 176079.8 175769.8 -217791.4 175481.7 -210492.3 175794.1 175831.2 175377.2 176055 -222803.3 -216916 176726.3 175393.5 -219318.6 130657.1 -220158.9 176229.3 176581.9 -212469.6 176478.1 176482.5 -218416.8 0 +175933.7 -217665.1 176080.5 175769.4 -217797.5 175482.1 -210508.9 175792.6 175829.9 175376.2 176054.9 -222801.7 -216923.8 176726.8 175394.5 -219358 130728.1 -220163.4 176228.3 176581.3 -212466.7 176478.4 176482.1 -218410.5 0 +175934.7 -217668.5 176081.2 175769.4 -217802 175483.5 -210528.7 175793.3 175831.3 175375.3 176055.6 -222802.8 -216933.7 176729.2 175395.4 -219382.8 130781.5 -220166.5 176228.8 176582.4 -212476.8 176480 176483.4 -218408.5 0 +175936.8 -217666.3 176081.1 175769.9 -217799.5 175483.8 -210572.1 175794.5 175833.1 175375 176056.6 -222803.5 -216936.5 176730.2 175395 -219394.8 130799.6 -220176 176228.6 176583.4 -212481.6 176480 176483.8 -218413.4 0 +175936.9 -217662.8 176080.1 175769.5 -217796.1 175482.9 -210632.8 175793.8 175832.6 175375.2 176057 -222804.6 -216930.9 176728.3 175394 -219409.1 130778.6 -220188.7 176227.8 176582.6 -212469.8 176477.9 176482.1 -218417.6 0 +175936 -217663.1 176079.1 175768.3 -217798 175482.2 -210678.5 175792.8 175831.4 175375 176057.3 -222805.3 -216925 176726.7 175392.9 -219432.4 130736.1 -220195 176227.5 176581.7 -212448.5 176477.4 176480.9 -218415 0 +175935.3 -217668.2 176079.5 175767.2 -217803.4 175482.1 -210686.4 175793.3 175832.1 175374.1 176058.1 -222800.9 -216923 176727.8 175391.9 -219451.4 130685 -220192.1 176227.7 176582.1 -212421.6 176479.6 176481.9 -218409.5 0 +175934.5 -217672.2 176080.7 175767.2 -217806.3 175482.6 -210653.8 175794.2 175833 175373.8 176058 -222795 -216920.1 176729.6 175391.9 -219460.5 130633.6 -220185.3 176228 176582.9 -212387.5 176481.5 176482.3 -218407.5 0 +175934.8 -217669.8 176081.2 175768.3 -217803.3 175483.3 -210584.5 175794 175833.3 175374.6 176056.9 -222797.8 -216913.1 176729 175393.6 -219464.7 130604.6 -220181 176228.7 176582.6 -212353.3 176480.7 176482 -218408.2 0 +175936 -217665.5 176080.9 175769.8 -217797 175483.8 -210490.5 175793.7 175833.6 175376.1 176056.1 -222806.5 -216909.5 176727.8 175394.8 -219447.2 130628.4 -220179.6 176229.6 176582 -212322.3 176479.8 176482.9 -218409.4 0 +175936.5 -217664.6 176080.4 175770.3 -217793.4 175483.3 -210389.2 175793.7 175833.5 175377.4 176055.1 -222808.3 -216919.3 176727.9 175394 -219400.5 130716.1 -220178.1 176229.6 176582.2 -212295.8 176480 176483.3 -218411.1 0 +175937 -217664 176080.2 175770 -217794 175482.4 -210291.8 175793.8 175832.9 175377.5 176054.1 -222801.9 -216934 176728.4 175392.9 -219364.7 130829.3 -220174.9 176228.8 176583.1 -212291.4 176479.9 176482.6 -218412 0 +175936.9 -217663.5 176080.5 175770.2 -217793.9 175482.3 -210209.4 175794.3 175832.7 175376.5 176054.4 -222796.8 -216935.3 176728.1 175393.1 -219364.2 130896.3 -220171.1 176227.9 176583.8 -212319.4 176479.7 176482.6 -218412.1 0 +175935.3 -217671.3 176079.9 175770.4 -217792.9 175482.2 -210154.9 175794.3 175832.3 175375.5 176054.4 -222796 -216924.2 176727.8 175393.6 -219367.1 130902.2 -220166.1 176227 176583.4 -212347 176480.3 176482.6 -218414.3 0 +175934.7 -217686.9 176079.1 175770.5 -217797 175481.8 -210110.6 175793.3 175832.5 175375.6 176054.3 -222795.6 -216912.9 176728.5 175393.8 -219356.6 130916.8 -220155.8 176227 176582.9 -212330.3 176479.9 176482.4 -218415.9 0 +175936 -217696.9 176080 175771.5 -217804.6 175482.3 -210022.1 175793.6 175833.8 175376.8 176055.8 -222795.1 -216904.4 176729 175394.4 -219355.9 130987 -220144.6 176228.2 176583 -212274.3 176478.9 176483.5 -218412.8 0 +175936.6 -217691.4 176080.7 175772.6 -217806.8 175483.5 -209867.9 175795.1 175834.6 175377 176056.8 -222796.9 -216903.6 176728.3 175394.5 -219369.9 131078.2 -220144 176228.6 176582.6 -212228.1 176478.4 176484.5 -218409.7 0 +175936.3 -217676.6 176079.3 175771.5 -217802.8 175483.6 -209706.3 175795.2 175834 175375.3 176055.9 -222800.7 -216914.6 176727.5 175393.6 -219384.1 131140.8 -220153.8 176227.7 176581.9 -212230.2 176477.9 176483.7 -218410 0 +175935.6 -217667.2 176078.7 175769.6 -217800 175482.7 -209597.9 175793.6 175833 175373.2 176055.8 -222803.3 -216924.9 176727.6 175392.9 -219402.8 131154.7 -220165.8 176227.5 176582.4 -212276.1 176477.6 176482.5 -218410.2 0 +175934.1 -217667.3 176080 175769.4 -217801.4 175480.8 -209532.6 175791.9 175832.1 175372.3 176056.5 -222802.7 -216927.4 176727.9 175393.3 -219434.5 131136.5 -220172.8 176227.9 176582.7 -212336.6 176479 176481.8 -218408.8 0 +175933.7 -217667.8 176080.2 175770 -217803 175479.2 -209474.2 175791.5 175831.4 175373 176055.7 -222802.2 -216927.6 176727.9 175393.6 -219475.2 131136.6 -220167.9 176228.5 176582.1 -212395.9 176480.8 176481.1 -218407.3 0 +175935.6 -217664.5 176078.9 175769.3 -217801 175479.3 -209410.4 175792.6 175831.4 175374 176054 -222803.8 -216924.7 176727.8 175393.1 -219512.3 131166 -220154.6 176228.7 176581.3 -212442.9 176480.3 176480.8 -218408 0 +175936.4 -217661.3 176078.4 175768.5 -217797.9 175480.7 -209348 175793.7 175832.6 175374 176053.4 -222803.6 -216918.3 176727.2 175392.9 -219538.4 131169 -220143.2 176228.1 176581 -212451 176477.9 176481.3 -218411.3 0 +175934.5 -217661.8 176079.7 175769.7 -217798.6 175481.8 -209301.8 175794.6 175834.2 175374.2 176054.3 -222798.7 -216916.5 176726.7 175393.1 -219559.8 131121 -220135.3 176228 176581.7 -212424.5 176477.3 176482.3 -218411.8 0 +175933 -217668.2 176080.9 175770.9 -217803.2 175482.8 -209275.4 175794.8 175834.5 175375.4 176054.7 -222796.1 -216922.3 176726.5 175392.6 -219572.9 131053 -220133 176228.6 176582 -212406.4 176478.3 176482.8 -218409.4 0 +175933 -217675.5 176080.8 175770.4 -217805.2 175483.7 -209260.5 175794.4 175833.5 175375.9 176054.3 -222801.2 -216929.7 176726.7 175391.6 -219560.5 130973.1 -220136.2 176228.5 176580.8 -212395.3 176478.7 176483 -218408.5 0 +175932.9 -217674.5 176081.4 175769.6 -217801.9 175483.7 -209268.9 175795.7 175832.1 175375.1 176055 -222805.9 -216929.4 176727.8 175392.2 -219530 130860.6 -220133.7 176228.5 176581 -212358.3 176480.3 176484 -218408.5 0 +175933.7 -217669.5 176081.9 175769.6 -217800 175483.7 -209315.6 175796.4 175831.5 175374.5 176056.2 -222804.5 -216920.4 176728.7 175394.3 -219508.7 130721.6 -220126.3 176229.1 176582.8 -212318.4 176482.4 176483.9 -218411.7 0 +175936.1 -217669.7 176080.2 175769.7 -217803.8 175483.5 -209376 175793.3 175831.7 175375.5 176055.8 -222803.5 -216916.2 176728.1 175395.3 -219499.7 130582.9 -220125.4 176229.1 176582.5 -212318 176479.7 176481.6 -218420.2 0 +175937.4 -217671.2 176078.8 175769.6 -217807.9 175483.1 -209424.5 175791.3 175831.8 175376.9 176055.1 -222803.8 -216920.4 176727.9 175395.3 -219477.5 130455.4 -220126.4 176228.1 176581.5 -212348 176476 176480.8 -218423.3 0 +175935.8 -217668.7 176080 175769.8 -217808.1 175483 -209477.8 175793.5 175831.2 175376.7 176055 -222801.8 -216920 176729.2 175395.7 -219423.8 130335.1 -220126.7 176226.8 176582.8 -212390.4 176477.3 176483.1 -218416.3 0 +175933.3 -217666.8 176080.9 175769.7 -217805.6 175482.4 -209540.7 175795.1 175830.6 175374.8 176054.7 -222800.9 -216915.8 176729.7 175395.7 -219360.4 130218.6 -220135 176226.4 176583.8 -212450.3 176479.1 176484.4 -218411 0 +175932.2 -217670.3 176080.3 175769.2 -217804.2 175480.4 -209573.8 175794.9 175831.1 175373.4 176054.3 -222801.8 -216914.8 176728.7 175394.7 -219318.9 130130.2 -220141.2 176227 176582.6 -212516.5 176478.6 176483.6 -218413.3 0 +175932.5 -217677.8 176080 175769.5 -217806 175478.9 -209555.3 175795 175833.1 175374 176054.4 -222801 -216914.1 176727.8 175393.5 -219293.2 130105.8 -220134 176227.4 176581.1 -212565.3 176478.3 176482.9 -218414.3 0 +175933.4 -217684.8 176080.2 175770.6 -217808.4 175479.5 -209516.4 175794.7 175834.5 175375 176054.8 -222801.1 -216916.6 176727.4 175393.1 -219268 130129.8 -220130.2 176227.1 176580.4 -212600.5 176478.6 176482.8 -218408.1 0 +175934.4 -217686.5 176080 175769.6 -217810.5 175480 -209508.4 175793.3 175833.4 175374.3 176054.5 -222802.3 -216924.7 176727.4 175393.3 -219250 130176.5 -220136.9 176227.2 176579.8 -212644.8 176478.1 176482 -218401.3 0 +175935.3 -217683.5 176078.9 175767.5 -217813.4 175479.9 -209548.3 175792.1 175831.7 175373.1 176053.9 -222800.3 -216928.3 176727.7 175393.1 -219248 130270.7 -220138.1 176227.9 176579.4 -212697.9 176477.2 176481.4 -218402.9 0 +175936.9 -217682.4 176078.1 175767.3 -217814.3 175481.1 -209598.1 175791.6 175831.4 175373.5 176054.3 -222797.2 -216924.9 176727.7 175392.6 -219270.1 130394.5 -220132.1 176228.8 176579.7 -212738.6 176477.4 176481.6 -218408.1 0 +175937.4 -217686.2 176077.4 175768.5 -217811.2 175482.3 -209615.6 175791.2 175830.7 175374 176055 -222798.3 -216924 176727 175391.5 -219315.2 130474 -220130.8 176228.8 176579.8 -212766.7 176478.4 176481.3 -218408.4 0 +175934.3 -217689.5 176077.1 175768.4 -217808.3 175480.8 -209599.7 175790.7 175829.1 175372.8 176054.2 -222801.3 -216926.1 176726.4 175390.3 -219361.1 130525.4 -220138.7 176227.4 176579.4 -212798.2 176478.3 176480.3 -218407.6 0 +175930.5 -217686.6 176079 175767 -217808.9 175479.1 -209560.5 175791.2 175829.5 175371.8 176053.4 -222800.7 -216924.4 176727.2 175390.5 -219392.3 130622.6 -220150.8 176226.8 176579.9 -212823.5 176477.8 176480.5 -218409.8 100 +175930.8 -217680.3 176082 175766.7 -217809.5 175479.4 -209504.9 175793.2 175831.4 175372.8 176054.3 -222796.9 -216920.9 176728.4 175392.2 -219404.9 130748 -220160.5 176227.8 176581.8 -212828.2 176478.8 176481.7 -218410.2 0 +175933 -217680.2 176082.9 175767.9 -217808 175480.1 -209453.2 175794.9 175831.8 175374.5 176054.7 -222795.1 -216921.5 176728 175392.9 -219395.2 130855.7 -220167.3 176227.8 176582.3 -212839.5 176480 176482.4 -218406.7 0 +175934.1 -217689 176081.4 175768.9 -217806.8 175480.3 -209412.1 175793.4 175831 175375.5 176054 -222797.5 -216924.5 176726.4 175392 -219376.8 130963.9 -220171.9 176226.5 176580.3 -212886.1 176478.6 176481.5 -218404.9 0 +175934.8 -217693.3 176079.5 175768.5 -217806.3 175481.3 -209361.1 175790.7 175830.9 175375 176053.6 -222800.3 -216924.9 176725.6 175391.4 -219363.1 131066.4 -220169 176226.2 176579.4 -212946.5 176476.3 176479.8 -218405.6 0 +175935.3 -217682.1 176079 175767 -217804.9 175482.6 -209297.8 175791.6 175830.9 175374.1 176053.9 -222797.9 -216921.8 176726.6 175392.7 -219343.8 131122.8 -220162.6 176227.6 176582.1 -212991.4 176477.8 176480 -218402.7 0 +175935.2 -217666.9 176079.9 175766.6 -217804.7 175482.8 -209246.8 175794.2 175830.7 175373.9 176054 -222794 -216918.7 176728 175394.2 -219318.5 131169.2 -220166.7 176228.8 176584.4 -213029.8 176481.1 176481.5 -218400.5 0 +175935.4 -217662.5 176079.7 175767.9 -217806.7 175481.8 -209228.6 175793.4 175832 175373.7 176053.2 -222794.8 -216919.8 176727.6 175393.8 -219300.2 131267.8 -220179 176227.3 176583.2 -213075 176480 176481.3 -218408.4 0 +175936.1 -217665.8 176078.1 175769.5 -217808 175480.7 -209254.2 175791.4 175833.1 175372.5 176052.4 -222796.1 -216922.4 176726.4 175392.5 -219286.7 131395.6 -220181.8 176224.3 176581.3 -213116.7 176476.8 176480.2 -218418 0 +175935.9 -217669 176077.6 175769.9 -217808.3 175480.5 -209319.8 175792.3 175831.3 175372.3 176053 -222794.4 -216920.8 176726 175392.2 -219282.7 131500.1 -220171.4 176223.5 176581 -213150.4 176477.1 176480.4 -218417.9 0 +175935.1 -217668.9 176078.2 175769.5 -217809.8 175481.2 -209400.8 175793.1 175829.3 175374.2 176054 -222795.7 -216918.9 176726 175392.7 -219297.4 131581.8 -220160.3 176225.8 176580.3 -213190.4 176478.5 176481.4 -218414.5 0 +175934.9 -217663.4 176078.9 175768.7 -217810.7 175481.8 -209474.2 175792.3 175830.3 175376 176054.2 -222801 -216921.8 176726.9 175392.8 -219312.5 131669.6 -220155.2 176228 176579.3 -213240.1 176477.4 176481.5 -218413.7 0 +175934.5 -217657.5 176079.3 175767.9 -217808.6 175481.3 -209529.9 175791.9 175832.1 175375.8 176053.5 -222804.7 -216924.7 176728.4 175391.7 -219311.7 131780.7 -220154.2 176228.3 176580.6 -213280.8 176476.1 176480.9 -218410.9 0 +175933.8 -217658.6 176079 175768.1 -217806.1 175480.4 -209562.3 175792.3 175832.5 175374.8 176052.6 -222806.6 -216922 176729 175390 -219309 131916.6 -220155.7 176227.8 176582.8 -213290.9 176476.6 176480.6 -218406.6 0 +175933.8 -217663.8 176078.6 175768.9 -217805.4 175480.3 -209562.8 175792.8 175832.3 175373.8 176052.6 -222807.1 -216920.3 176728.2 175389.5 -219311.4 132050.5 -220157.8 176227 176582.6 -213258.8 176477.4 176480.8 -218405.8 0 +175933.9 -217663.8 176078.6 175768.8 -217805.8 175480.2 -209518.4 175792.7 175832 175373.3 176053.7 -222805.5 -216926.9 176727 175391.3 -219314.3 132140.5 -220156.1 176225.6 176581.1 -213185.4 176477.2 176481 -218408.3 0 +175934 -217658.4 176079.3 175768 -217807.4 175480.2 -209444.4 175792.5 175831.4 175373.1 176054.7 -222804.3 -216936.3 176726.4 175394.1 -219336 132184.4 -220148.9 176225.7 176581.3 -213094.5 176478.1 176481.9 -218409.1 0 +175935.3 -217655.9 176080.6 175768.4 -217810.4 175481.1 -209385.4 175793.7 175831 175373 176055.1 -222803.4 -216936.8 176727.5 175394.8 -219390.1 132222 -220142.3 176227.5 176582.6 -213029.5 176479.7 176483.2 -218405.2 0 +175936.2 -217661.9 176081.5 175769.8 -217813.1 175481.5 -209354.7 175795.5 175831.4 175373.7 176054.9 -222800.6 -216928.5 176729.4 175392.5 -219448 132291.3 -220145.3 176228 176582.9 -213010.8 176479 176483.3 -218401.8 0 +175935 -217672.2 176080.8 175769.5 -217814 175480.9 -209334.4 175795.8 175832 175375.2 176053.7 -222798.1 -216923.8 176729.5 175391 -219484.6 132408.6 -220152.8 176226.5 176582.4 -213012.1 176477.2 176482.2 -218405.5 0 +175933.8 -217676.2 176079.9 175768.2 -217813.2 175481.3 -209323.6 175794.9 175831.7 175375.9 176052.5 -222797.6 -216928.7 176728.7 175392.3 -219519.7 132538.7 -220148.6 176225.5 176581.8 -213000.8 176478.1 176481.3 -218409 0 +175934.3 -217671.5 176080.2 175768.1 -217811 175481.4 -209321.8 175794.6 175831 175375.5 176052.5 -222797.6 -216934.2 176728.9 175393.8 -219567.8 132606.8 -220134.9 176226 176581.5 -212991.3 176479.9 176481.2 -218404.1 0 +175934.9 -217665.8 176080.3 175769.1 -217808.6 175479.5 -209306.9 175794 175830.6 175375.3 176053.1 -222798.2 -216931.8 176728.5 175393.1 -219603.9 132592.3 -220132.9 176227.2 176581.9 -213017.7 176479.4 176481 -218399.2 0 +175934 -217661.6 176078.5 175769.4 -217807.4 175478.4 -209273.8 175792.5 175830 175375 176052.7 -222801.4 -216925.5 176727 175391.5 -219613.6 132542.5 -220149.2 176228.3 176582.7 -213077.3 176477.8 176480.6 -218402.9 0 +175932.9 -217658.1 176077 175768.7 -217807.7 175479.5 -209257.2 175791.8 175829.7 175373.7 176051.9 -222806.4 -216921.6 176726.3 175390.7 -219622.2 132490.1 -220159 176228.3 176581.9 -213139 176476.8 176480.7 -218407.4 0 +175933.8 -217659.8 176077.2 175768.2 -217810.2 175481.1 -209298.8 175792.1 175830.8 175373.3 176052.1 -222810.7 -216921 176726.6 175391.1 -219645.2 132437.9 -220146.8 176226.8 176580 -213188 176475.8 176480.2 -218406.7 0 +175935.5 -217664.2 176078.1 175768.8 -217814.2 175481.9 -209397.2 175791.5 175831.9 175374.5 176053.1 -222812.2 -216921.2 176726.4 175391.9 -219656.7 132394.3 -220134.4 176225.7 176579.8 -213226 176475.4 176478.9 -218405.6 0 +175935.6 -217665.1 176079.7 175769.5 -217813.7 175481.8 -209498.3 175791.6 175831.9 175375.6 176054 -222809.2 -216918.8 176726.3 175392.3 -219635.3 132369.8 -220130.6 176227.5 176581.3 -213246.3 176477.2 176479.7 -218405.3 0 +175934 -217667.8 176081.2 175768.7 -217806.5 175481.3 -209551.7 175793.5 175831.9 175376.2 176054.4 -222804 -216914 176726.5 175392.1 -219597.5 132346.6 -220116.2 176230 176582 -213238.6 176479.4 176482.8 -218404 0 +175932.3 -217674.5 176081.3 175767.4 -217800.8 175481.4 -209565.4 175794.5 175832.1 175376.4 176053.8 -222799 -216911.6 176726.7 175392.2 -219563.7 132273 -220099.2 176229.7 176581.9 -213218.4 176479.5 176483.7 -218404 0 +175931.8 -217678.2 176080.4 175767.8 -217800.7 175481.5 -209578.8 175793.5 175831.5 175375.3 176053 -222794.3 -216910.9 176727.5 175392.6 -219532.8 132111 -220101 176227.5 176582.1 -213203.9 176478.8 176481.2 -218405 0 +175933.1 -217678.3 176079.1 175768 -217802.4 175480.1 -209602.7 175792.1 175830.3 175373.3 176052.4 -222793.3 -216906.8 176727.5 175392.9 -219503.7 131885.4 -220107.4 176226.4 176581.9 -213178.8 176478.6 176479.1 -218406.1 0 +175934.8 -217677 176076.5 175766.4 -217805.5 175478.5 -209627.5 175790.1 175829.5 175372 176052.6 -222796.6 -216903.7 176725.5 175392.7 -219490.7 131676.5 -220105.6 176225.7 176580.2 -213141.2 176476.7 176478.3 -218407.6 0 +175934.3 -217670.3 176075.3 175765.5 -217808.9 175478.5 -209648.9 175788.4 175829.2 175371.4 176053.3 -222797.2 -216906.8 176723.8 175391.9 -219506.7 131550 -220106.3 176224 176578.8 -213118.9 176474.5 176477.5 -218405.7 100 +175931.9 -217661.2 176077.3 175766.8 -217807.3 175479.2 -209647.2 175788.8 175828.6 175371.4 176053.4 -222794.9 -216908.1 176723.9 175391.1 -219541.2 131484.7 -220109.9 176223 176579.4 -213086.9 176474.9 176476.8 -218402.1 0 +175931.5 -217658.1 176079 175767.7 -217803 175478.9 -209598.5 175791 175828.5 175371.5 176052.1 -222795.6 -216902.8 176724.3 175391.1 -219569.3 131402.5 -220110.5 176223.5 176580.8 -213005.6 176476.4 176476.7 -218404.8 0 +175933.3 -217658.8 176078.5 175768 -217802.3 175478.5 -209518.2 175793.6 175829.5 175371.6 176051 -222796.4 -216898.3 176724.8 175390.9 -219585.7 131262.7 -220111.5 176224.5 176581.5 -212922.3 176477.4 176478.7 -218409.8 0 +175933.1 -217657.6 176078.7 175769.1 -217801.5 175479.5 -209436.3 175794.8 175830.8 175372.8 176051.7 -222793.8 -216897 176725.8 175390.5 -219600.1 131074.8 -220114 176225.9 176581.7 -212897.5 176478.4 176481.6 -218408.9 0 +175930.9 -217657.5 176079.3 175769.8 -217796.5 175480.7 -209363 175793.1 175831.2 175374.3 176052.4 -222792.7 -216896.6 176726.1 175390.9 -219611.5 130871.2 -220117 176226.9 176581.3 -212910.2 176477.8 176482.2 -218405.7 0 +175930.1 -217660.5 176078.3 175768.3 -217795.2 175480.6 -209310.3 175790.8 175830.3 175373.9 176052.3 -222794.9 -216897.8 176725 175391.6 -219609.5 130683.8 -220123.5 176226.5 176580.5 -212921.9 176475.9 176479.9 -218405.2 0 +175931.6 -217660.6 176076.7 175766.6 -217801.1 175480.2 -209293.8 175791 175828.5 175371.8 176052.1 -222796.5 -216899.4 176724.5 175391.1 -219586.8 130514.2 -220129.2 176225.4 176580.4 -212938.6 176476.4 176478.2 -218405.7 0 +175933.1 -217658.3 176076.7 175766.4 -217805.5 175480.3 -209294.7 175791.9 175828 175371.5 176052.4 -222796.6 -216902.2 176725.8 175390.4 -219556.8 130357.7 -220121.3 176225.2 176581.2 -212978.7 176478.8 176479.2 -218406.1 0 +175933.2 -217659 176077.2 175767.1 -217803.9 175479.8 -209284.1 175790.8 175829.4 175373.8 176052.6 -222797.4 -216909.8 176726.6 175391 -219549.4 130211.2 -220093.6 176225.4 176581.3 -213045.1 176478.9 176480.5 -218408.6 0 +175932.3 -217660.2 176076.6 175767.5 -217801.6 175478.3 -209283.8 175788 175831 175374.4 176052 -222799.8 -216918.1 176724.7 175391.8 -219561.8 130039.1 -220064.3 176225.3 176579.4 -213131.3 176476.1 176479.1 -218413.2 0 +175931.8 -217657 176075.6 175767.7 -217802.3 175478.1 -209324 175787.5 175831.3 175372.9 176050.9 -222803 -216919.9 176722.7 175391.6 -219558.9 129821.8 -220064.3 176225.4 176577.5 -213217.9 176474.9 176477.5 -218414.8 0 +175932.9 -217650.7 176076.5 175767.8 -217804.6 175480 -209370.5 175791.3 175831.1 175372.6 176051.4 -222804.1 -216914.7 176723.9 175391 -219539.9 129596.1 -220093.6 176225.7 176578.9 -213281.3 176477.8 176479.6 -218410.9 0 +175933.1 -217648.5 176078.1 175767.3 -217805.5 175481.1 -209372.4 175794.2 175830.6 175373.3 176053.4 -222803.3 -216907.1 176726.3 175391 -219540.1 129388 -220121.9 176225.7 176581.4 -213323 176480 176481.8 -218407.5 0 +175930.7 -217656.8 176077.7 175766.1 -217803.2 175480.2 -209330.4 175792.5 175829 175372.1 176053.3 -222802.8 -216905.3 176727.1 175391.3 -219564.2 129182.2 -220136.1 176224.5 176581.3 -213367.3 176478 176479.7 -218407.7 0 +175929.5 -217669.6 176076.1 175765.3 -217797.2 175478.8 -209270.4 175790 175827 175369.8 176050.8 -222802.2 -216912.5 176726.6 175391.5 -219577.9 128972.6 -220147.1 176222.8 176580.2 -213421.8 176475.4 176476.5 -218406.9 0 +175931.3 -217674.6 176075.4 175765.6 -217790.7 175478.4 -209207.9 175788.6 175826.9 175369.5 176048.6 -222801.7 -216919.2 176725 175391.3 -219568.6 128773.3 -220156.7 176222.5 176578.7 -213452.6 176474.8 176475.9 -218404.7 0 +175932.7 -217669.6 176076.1 175766.3 -217790 175478.7 -209155.4 175788.1 175828.8 175371.5 176047.8 -222801.2 -216916.7 176723 175390.3 -219565.7 128573.6 -220156.2 176223.3 176577 -213413.2 176475.2 176477.2 -218404.8 0 +175932.5 -217663 176077.6 175766.4 -217795.8 175479.2 -209135.6 175789.1 175830.8 175373 176048.6 -222796.9 -216913 176722.3 175389.2 -219583.8 128343.1 -220152.6 176223.8 176577.9 -213310.3 176475.5 176478.8 -218406.2 0 +175932.1 -217662.4 176077.5 175765.7 -217801.1 175479.2 -209162.8 175790.2 175831 175373.1 176050.2 -222791 -216919.2 176723.1 175389.4 -219594.5 128103.8 -220160.3 176224.3 176579.8 -213208.2 176474.4 176479.6 -218406 0 +175931.7 -217663.6 176075.5 175765.8 -217800.4 175479.1 -209210.6 175790.4 175829.8 175373.1 176051.3 -222790.1 -216926.8 176724.2 175390.1 -219575 127911.8 -220172.6 176224.8 176579.9 -213138.7 176473.6 176479 -218402.4 0 +175931.5 -217659 176075.2 175767.6 -217797.2 175480.5 -209233.5 175792.1 175829.8 175373.5 176052.2 -222791 -216923.2 176726.1 175390 -219541.8 127763.5 -220175.6 176225.6 176580.7 -213077.3 176476.1 176479.5 -218396.6 0 +175932.5 -217656.5 176076.5 175769.1 -217797.3 175482.2 -209213.4 175794 175830.7 175373.7 176052.6 -222790.2 -216914.4 176727.9 175390 -219523.4 127603.5 -220174.3 176225.9 176581.4 -213022.1 176478.1 176480.5 -218396.3 0 +175933.8 -217665.2 176077.5 175768.6 -217799.8 175481.5 -209156.6 175792.8 175830.4 175373.3 176052.3 -222792.3 -216911 176727.5 175390.3 -219528.4 127403.9 -220174.9 176224.6 176578.8 -212991.1 176476.8 176480 -218403.4 0 +175933.1 -217675.2 176077.9 175766.6 -217801.5 175479.3 -209078.3 175790.2 175829.6 175372.3 176051.4 -222796.4 -216910.7 176725.6 175390.4 -219548.7 127176.9 -220168.2 176223.8 176576.4 -212967.5 176475.6 176479.7 -218409.8 0 +175931 -217678.2 176077.6 175765.1 -217801.5 175477.9 -209009.3 175788.8 175829.1 175371.8 176050.4 -222798.5 -216910.9 176724.1 175390.6 -219573.2 126941.8 -220156.2 176225.1 176576.6 -212931.8 176476.1 176480 -218412 0 +175930.8 -217679.4 176076.9 175766.3 -217797.4 175478.1 -208975.5 175788.8 175828.4 175372.4 176050.6 -222798.6 -216916 176723.5 175391.2 -219596.1 126712.5 -220158.1 176226.4 176577.2 -212891.9 176476.4 176479.6 -218411.4 0 +175933.6 -217681 176077.4 175769.2 -217787.9 175479.3 -208961.7 175790.4 175828.4 175373.5 176052.4 -222794.9 -216923.2 176725 175391.4 -219630.6 126496.8 -220173.6 176226.7 176578.7 -212855.4 176476.6 176479.2 -218408.5 0 +175934.8 -217679.3 176077.7 175769.5 -217782.9 175480 -208930.3 175791.6 175829.9 175373 176053.2 -222788.2 -216921.7 176726.9 175391.1 -219692.5 126288 -220181.7 176227.1 176580.6 -212811.2 176476.3 176479.1 -218408.4 0 +175932 -217674.2 176076.1 175766.4 -217787.5 175478.9 -208875.9 175791 175830.5 175371.4 176051.8 -222785.1 -216912 176726.4 175390.5 -219754.3 126062.3 -220178 176227.4 176580.1 -212726.2 176475.9 176479.1 -218414 0 +175929.3 -217670.2 176075.4 175764.8 -217788 175477.9 -208831.4 175790.5 175829.6 175371.3 176050.9 -222787.6 -216907 176724.8 175388.9 -219772.8 125828.5 -220176.6 176226.7 176578.3 -212592.8 176476.7 176480.2 -218417.7 0 +175930.3 -217671.1 176077.1 175765.7 -217779 175478.5 -208825.9 175791.4 175829.1 175372.6 176052 -222791.5 -216912.5 176724.3 175388.4 -219759.4 125649.8 -220179.3 176225.6 176578.7 -212470.7 176477.3 176481.5 -218415.5 0 +175932.5 -217674.6 176078.1 175766.7 -217772.4 175480.4 -208845.5 175792.2 175829.9 175373 176053.2 -222792.8 -216920.4 176724.3 175389.9 -219764.5 125547.3 -220173 176225.7 176580.3 -212405.3 176476.6 176480.8 -218412.2 0 +175933.5 -217676.2 176077.3 175767.2 -217772.7 175481.5 -208838.8 175791.8 175830.4 175373 176052.9 -222791 -216920.7 176723.9 175390.7 -219805.4 125435.4 -220155.2 176226.3 176581.3 -212356.8 176476.2 176479.5 -218410.6 0 +175933.6 -217674.8 176075.9 175767.7 -217775.2 175480.1 -208776.9 175790.9 175829.6 175373.6 176052.6 -222789.2 -216914.3 176723.6 175390 -219845.4 125210.2 -220142.5 176226.1 176581.4 -212271.6 176476.7 176480.4 -218410.5 0 +175934.5 -217672.9 176075.7 175768 -217777.7 175478.6 -208693.7 175791.2 175828.4 175373.4 176053.3 -222786.9 -216908.3 176723.8 175389.9 -219833.6 124844 -220144 176225.7 176581.2 -212139.7 176477.5 176482.3 -218412 0 +175934.9 -217672.6 176077.3 175768.5 -217777.5 175479.9 -208638.4 175792.1 175828.6 175372.6 176053.8 -222781.1 -216907.7 176724.5 175391.2 -219762.3 124386.3 -220147.5 176226 176581.5 -211973.3 176478.5 176482.3 -218411.5 0 +175932.7 -217673.6 176078.5 175769.2 -217776.7 175482.3 -208622.3 175791.5 175830.3 175373.2 176053.2 -222775.8 -216914.1 176724.7 175392.1 -219685 123914.2 -220144.3 176226.3 176581.9 -211810.6 176478.2 176480.3 -218408.5 0 +175930.5 -217674.2 176077.9 175769 -217780.1 175482 -208633 175790 175831.5 175374 176051.5 -222775.2 -216922.6 176723.9 175391 -219657.2 123487.1 -220139.9 176225.8 176581.2 -211692.9 176476 176478.5 -218410.4 0 +175931.3 -217673 176077.9 175768.4 -217783.4 175480.1 -208666.2 175791.2 175831.4 175373.2 176051.3 -222775.4 -216921.9 176723.6 175389.4 -219665.8 123147.6 -220139.4 176226 176581 -211612.9 176476.6 176479.3 -218413.9 0 +175932.9 -217672.6 176079.6 175768.4 -217782.3 175479.2 -208709 175794.3 175830.8 175371.4 176052.9 -222776.3 -216910.7 176724.7 175389.7 -219663.8 122906.3 -220146.8 176226.6 176582.3 -211547.3 176480.1 176481.7 -218409 0 +175932.8 -217675 176080 175767.9 -217783.2 175479 -208722.8 175793.6 175829.9 175370.7 176053.1 -222782.6 -216900.5 176725.1 175390.4 -219649.2 122697 -220163.7 176225.9 176581.6 -211498.9 176479.5 176481.8 -218402.6 0 +175931.9 -217675.3 176078 175765.4 -217787.7 175478.1 -208695.8 175790.1 175828.4 175371.3 176051.3 -222788.8 -216897.7 176724.4 175390.3 -219649.6 122443.3 -220178.8 176224.4 176579.3 -211462 176474.9 176479.9 -218404.6 0 +175931.3 -217670 176075.8 175763.1 -217789.1 175477.3 -208673.5 175788.6 175827.7 175371.7 176050.5 -222786.9 -216899.6 176723.8 175390 -219664.1 122162.9 -220181.4 176223.5 176578 -211420.5 176472.9 176478.6 -218410 0 +175931.8 -217666.7 176075 175764.3 -217786.4 175477.8 -208677.4 175788.9 175828.7 175371.4 176050.6 -222782.4 -216902.2 176722.9 175390.1 -219671.1 121913.2 -220175.7 176223.2 176577.5 -211383.3 176474 176477.4 -218414.1 0 +175932.7 -217668.5 176076.4 175766.8 -217783.3 175479.5 -208665.7 175790.6 175829.5 175371.1 176050.9 -222783.4 -216903.4 176723.2 175390.8 -219656.2 121696.1 -220165.7 176224.1 176579.1 -211360 176476.1 176477.4 -218416.7 0 +175932.4 -217669.5 176077.8 175767 -217781.5 175480.7 -208614.4 175792.5 175828.6 175370.7 176051.4 -222787.8 -216905.5 176725 175391.6 -219619.8 121476.5 -220148.8 176226 176581.4 -211341.6 176477.4 176479.5 -218416.5 0 +175931.9 -217669.8 176076.5 175766.1 -217781.1 175479 -208545.5 175790.9 175827.7 175370.2 176050.9 -222789.5 -216910.9 176725.2 175390.9 -219577.8 121236.7 -220135 176225.6 176579.8 -211335.8 176475.8 176479.6 -218414 0 +175932.1 -217672.7 176075.3 175766.4 -217779.6 175477.3 -208475.3 175788.3 175828.9 175370.6 176050.4 -222786.5 -216915.7 176724.4 175389.7 -219547.2 121000.6 -220136.6 176223.6 176577.2 -211362.2 176473.9 176477.6 -218410.6 100 +175931.5 -217674.5 176076.5 175767.3 -217776.5 175478.3 -208416.3 175788 175831.3 175372.1 176051.5 -222781.9 -216915.1 176724.9 175390.5 -219535.5 120818.3 -220146 176223.3 176578 -211400.7 176474.1 176477.8 -218407.5 0 +175930.7 -217673.2 176077 175767.8 -217774.1 175479 -208392.5 175788.1 175831.8 175372.5 176052.1 -222779.4 -216910.9 176724.5 175391.4 -219528.9 120711.9 -220151 176223.7 176578.6 -211414.6 176474.4 176479.4 -218407.5 0 +175931.8 -217671.3 176076.8 175767.5 -217771.6 175478.5 -208401.5 175790 175830.1 175371.4 176051.8 -222779.2 -216904 176723.9 175390.5 -219496.4 120637.1 -220150.6 176224.2 176578.1 -211415.8 176475.8 176480.3 -218408.2 0 +175934.5 -217670.2 176077.7 175767.3 -217767.9 175479.5 -208419 175794.5 175828.8 175371.2 176052.9 -222781.6 -216895.4 176725.8 175390.4 -219436.1 120508.2 -220147.3 176226 176579.7 -211435.9 176479.6 176480.9 -218406.2 0 +175935 -217669.9 176077.8 175767.4 -217766.8 175480.9 -208441.7 175795.2 175829.2 175372 176053.7 -222786.5 -216892.2 176727.1 175392.2 -219383.3 120282.1 -220147.4 176227 176580.3 -211470.4 176480.1 176480.3 -218404.8 0 +175932.9 -217668.9 176076.4 175765.8 -217772.9 175479.9 -208473.6 175791.1 175829.7 175371.3 176052.6 -222787 -216897.5 176725.6 175392.8 -219352.1 120007.4 -220157.4 176226.2 176578 -211500.9 176475.3 176479.1 -218406.4 0 +175930.9 -217667.7 176076.9 175764 -217781.3 175478.6 -208505.6 175789.6 175829.5 175370 176052.3 -222779.5 -216903 176724.2 175391.6 -219331.3 119759.5 -220165.4 176226 176577.6 -211525.9 176472.7 176479.6 -218406.6 0 +175929.3 -217669.2 176078.1 175765.1 -217781.7 175479.2 -208527.3 175791.5 175829.1 175370.3 176053.1 -222773.1 -216903.9 176724.6 175390.5 -219325.3 119573.7 -220155.5 176226 176580.3 -211560.9 176475.1 176481.2 -218404.8 0 +175928.6 -217670.5 176076.4 175766.7 -217774.6 175479.4 -208531.3 175790.9 175828.8 175371.9 176052.9 -222775.3 -216904.7 176725.1 175390.3 -219343.2 119452.9 -220140.7 176224.8 176580.7 -211616.2 176477 176480.8 -218405 0 +175930 -217665.6 176073.5 175766.4 -217770 175478.2 -208523 175787.6 175827.8 175373.2 176051.6 -222781.6 -216904.4 176723.8 175390 -219371.8 119373.2 -220146.4 176224 176577.5 -211665.9 176476.4 176478.7 -218406.3 0 +175931.2 -217657 176073.8 175766.1 -217769 175477.1 -208519.1 175787.3 175826.8 175372.7 176050.7 -222784.4 -216898.8 176721.9 175389.7 -219389.7 119317.5 -220164.8 176224.5 176575.8 -211683.1 176475.4 176477.5 -218406.5 0 +175930.2 -217652.7 176076.8 175766.8 -217765.4 175476.8 -208520.6 175791 175827.3 175371.5 176050.7 -222782.6 -216891.3 176722 175389.5 -219394.1 119294 -220167.8 176224.9 176577.3 -211691.5 176475 176477.9 -218409.2 0 +175928.9 -217654.2 176078.5 175767.1 -217760.7 175477.2 -208520.2 175793.5 175829.1 175371.9 176051.1 -222782.3 -216889.7 176724.2 175389.4 -219397.9 119261.7 -220157.9 176224.4 176578.3 -211711.2 176474.9 176478.6 -218416.2 0 +175928.4 -217655.2 176078.4 175767.2 -217760.2 175477.9 -208529.5 175792.9 175830.5 175372.4 176051.1 -222785.5 -216895.9 176725.5 175389.4 -219403.3 119137.3 -220155.2 176224.3 176577.6 -211717.7 176475.2 176478.4 -218418 0 +175928.5 -217652.5 176078 175767.9 -217762.5 175478.9 -208562.2 175792.8 175829.8 175371.6 176051.1 -222786.7 -216905.1 176724.9 175388.9 -219406.8 118918.1 -220158.1 176224.8 176577.5 -211702.3 176476.6 176478 -218409.1 0 +175930.2 -217651.9 176076.9 175767.8 -217765.6 175478.9 -208606.3 175792.4 175828.3 175371 176051.3 -222786.7 -216910.5 176723.4 175387.5 -219419.3 118691.5 -220157.1 176224.5 176577.9 -211678.4 176476.6 176477.2 -218400.8 0 +175932 -217655 176074.7 175765.6 -217770.5 175477 -208639.6 175789 175827.7 175370.7 176050.6 -222789 -216908.1 176722 175385.9 -219448.9 118523.3 -220152.8 176222.6 176576.7 -211635.9 176473.5 176476.3 -218402.2 0 +175931.4 -217654.5 176073.9 175763.7 -217773 175475.6 -208653.8 175787.4 175827.7 175370 176050.3 -222789.6 -216900.4 176721.7 175386 -219480.9 118400.6 -220146.1 176221.2 176576.2 -211569 176471.2 176476.4 -218404.3 0 +175930 -217651.5 176075.8 175764.8 -217769.6 175477.3 -208656.1 175790.5 175828.1 175370.4 176051.1 -222787.7 -216895.4 176722.4 175388.1 -219501.7 118276.6 -220142.9 176221.6 176577.9 -211502.2 176472.3 176477.7 -218399.7 0 +175930.2 -217653.8 176077.3 175766.2 -217766.5 175479.1 -208662.6 175792.3 175828.7 175371.4 176051.6 -222787.8 -216896.6 176722.6 175389.5 -219516.5 118129.1 -220147.3 176222.3 176578.8 -211458.2 176473.1 176478.9 -218394.6 0 +175931.6 -217658 176076.1 175765.1 -217768.7 175478.6 -208683.4 175790.3 175828.1 175371.2 176051 -222787.8 -216897.7 176722.3 175389.9 -219539 117960.3 -220146.3 176222.5 176578.3 -211439.7 176472.7 176478.7 -218394.2 0 +175932.9 -217657.2 176074.1 175764.2 -217774.5 175477 -208701.7 175789.3 175827.4 175370.9 176050.4 -222785.7 -216897.3 176723 175390.9 -219574.8 117782.5 -220134.5 176223.9 176578.7 -211433.2 176473.4 176477.4 -218398 0 +175933.7 -217653.6 176073.7 175765.4 -217782.5 175476.5 -208692.8 175790.6 175828.3 175371.2 176050.1 -222784.4 -216901.1 176724.3 175392 -219612.9 117616 -220130.2 176225.3 176579.6 -211413.3 176474.9 176477.5 -218404.6 0 +175932.5 -217652.9 176073.9 175766.3 -217789.2 175477.2 -208657.6 175791 175829.2 175371.2 176049.8 -222784.6 -216907.1 176723.7 175391.5 -219637.3 117465.2 -220140.5 176224.4 176579.1 -211371.3 176475.2 176479.1 -218410.4 0 +175930.5 -217658.1 176073.8 175766 -217789.7 175477.8 -208622 175789.5 175828.8 175370.9 176049.5 -222783.7 -216909 176721.9 175390 -219641.5 117310.9 -220151.1 176222.5 176577.4 -211329.3 176474.3 176479.4 -218410.1 0 +175930.1 -217664.4 176074.3 175764.9 -217786.3 175476.9 -208605.3 175788.9 175827.8 175370.4 176048.8 -222780.4 -216906.8 176721.6 175388.8 -219628.9 117134.1 -220154.4 176222.4 176576.8 -211312.5 176473.8 176478 -218403.3 0 +175930.1 -217664.2 176075.3 175763.6 -217783.9 175475.9 -208603.9 175790.2 175827.2 175369.3 176048.1 -222777.4 -216907.1 176722.7 175388 -219612.1 116924 -220153.7 176223.5 176577.6 -211318.4 176474.3 176476.5 -218398.8 0 +175929.7 -217661 176075.1 175763.5 -217783.5 175475.9 -208615.4 175790 175827.2 175368.3 176048.3 -222779 -216914.4 176723.3 175388.4 -219604.7 116676.8 -220151 176223.3 176577.7 -211315.5 176474.1 176475.2 -218403.8 0 +175930.6 -217660.8 176074.7 175764.4 -217784.1 175476.6 -208655.7 175787.5 175827.4 175368.5 176049 -222783.2 -216922.2 176723.4 175389.5 -219613 116398.4 -220149.6 176222.2 176577.2 -211271.2 176473 176475.2 -218411.1 0 +175932.3 -217659.5 176075.7 175764.7 -217784.4 175477.6 -208723.8 175786.3 175827.8 175369.4 176049.5 -222785.7 -216922.5 176723.6 175389 -219635 116105 -220151.8 176222.9 176577.9 -211191.2 176473.4 176477 -218410.8 0 +175931.9 -217655.3 176077 175764.3 -217785 175478.1 -208791.2 175787.7 175828.4 175370 176049.7 -222785.3 -216915.8 176723.6 175387.6 -219658.4 115834.5 -220153.6 176224.5 176579.2 -211126.1 176474.5 176478 -218405.8 0 +175930.2 -217653.5 176076.7 175764.2 -217786.1 175476.9 -208839.1 175789.1 175828.7 175369.9 176050 -222782.5 -216908.8 176723 175387.5 -219676.9 115623.3 -220151.9 176224.2 176579.4 -211118.3 176474.4 176477.4 -218402.9 0 +175929.4 -217655.2 176076.1 175764.4 -217785.5 175475.8 -208861 175789.8 175828.5 175370.5 176050.5 -222780.2 -216908.3 176722.7 175387.9 -219692.7 115457.6 -220148.4 176223 176578.8 -211158.1 176475 176478.2 -218401 0 +175929.5 -217657.6 176076 175764.5 -217783.3 175476.5 -208851.3 175789.4 175828.2 175371.6 176051.2 -222781.8 -216913 176723.1 175387.3 -219688.8 115291.4 -220144.5 176222.5 176578.5 -211207.3 176475.8 176480 -218398.7 0 +175929.4 -217659.9 176075.3 175764.1 -217781.3 175476.8 -208822.6 175787.2 175827.4 175371.1 176050.2 -222784.4 -216913.9 176723.3 175386.6 -219657.6 115093.1 -220142.2 176222 176577.9 -211235.8 176473.8 176479.8 -218399.4 0 +175929 -217661.6 176074.7 175763.8 -217779.6 175476.7 -208791.8 175786.3 175826.8 175369.5 176048.9 -222783.4 -216909.8 176722.9 175387.3 -219632.4 114867.3 -220148.1 176222 176577.3 -211235.3 176471.8 176478.5 -218403.8 0 +175928.8 -217662.7 176074.7 175763.5 -217776.3 175477.6 -208760.3 175788.3 175827.1 175369 176049.1 -222781.2 -216907.7 176722.4 175388.9 -219627 114669.2 -220159.2 176223.2 176577.7 -211219.4 176473.6 176478.3 -218407.4 0 +175929 -217664.2 176073.8 175763.2 -217771.3 175477.3 -208733.1 175789.2 175827.3 175369.5 176049.4 -222781.1 -216908.2 176722.1 175389.4 -219614.2 114533.2 -220158.3 176223.7 176577.9 -211198.7 176474.8 176477.8 -218407.9 0 +175929.1 -217665.7 176072.9 175762.8 -217768.2 175475.7 -208714.6 175788.4 175826.9 175369 176048.3 -222781.3 -216904 176722.8 175388.8 -219594.3 114386.8 -220139.6 176222.9 176576.8 -211177.6 176473.3 176476.3 -218407 0 +175928.3 -217667.3 176073.2 175763.3 -217770 175475.6 -208691.9 175789 175827 175368.3 176047.5 -222780.8 -216894.5 176724.5 175388.6 -219597.5 114145.7 -220119.9 176223.2 176576.1 -211188.4 176473.2 176476.1 -218407.5 0 +175928.4 -217669.3 176073.9 175764.6 -217771.6 175476.4 -208653.2 175789 175827 175368.8 176047.7 -222781.9 -216892 176724.3 175388.6 -219620.9 113832 -220118.1 176223.7 176575.6 -211249 176473.8 176476.6 -218410.3 0 +175929.6 -217667.7 176075.1 175765.2 -217767 175477.2 -208604.7 175788.3 175826.4 175369.4 176048.7 -222781.8 -216900.6 176721.7 175388 -219634.3 113499.8 -220131.9 176223.1 176575.4 -211311.3 176473.9 176476.8 -218410.5 0 +175929.7 -217662.3 176077.4 175764.5 -217760.2 175479.1 -208575.2 175790.2 175826.8 175369.4 176050.2 -222779.3 -216907.4 176720.9 175388.1 -219623.4 113165.4 -220144.4 176222.8 176577.4 -211333.5 176475.5 176478.1 -218406.2 0 +175929.3 -217658.9 176077.9 175764.7 -217757.2 175479.9 -208596.2 175791.9 175828.1 175369.5 176050.8 -222778.1 -216907 176722.2 175389.2 -219593.3 112858.2 -220153.8 176223.7 176578.9 -211334.2 176476.9 176479.9 -218405.9 0 +175930.3 -217660.4 176075.5 175766.1 -217758.7 175477.7 -208651.8 175789.6 175828.5 175369.2 176049.6 -222778.3 -216905.6 176721.8 175389.9 -219559.7 112622.4 -220165.3 176224.1 176576.8 -211334.3 176475.1 176480 -218411.6 0 +175930.9 -217663 176074.3 175766.1 -217763.1 175475.6 -208687.2 175788.3 175827.8 175369.5 176048.8 -222776.3 -216904 176721.1 175389.7 -219535.4 112451 -220162.8 176223.2 176575.7 -211324.3 176473.1 176479.2 -218411.6 0 +175930.1 -217663.7 176075.5 175764.5 -217767.4 175475.2 -208682.8 175790.9 175827.5 175370.8 176049.8 -222774.8 -216902.2 176722.8 175388.8 -219512.6 112294.1 -220140.2 176222.4 176578.2 -211298.4 176473 176478.3 -218403 0 +175929.1 -217664.1 176075.4 175763.7 -217767.8 175474.7 -208664.6 175792.2 175827.2 175370.8 176051 -222777.5 -216901.9 176723.6 175387.8 -219484.8 112121 -220127.3 176222.8 176579.7 -211277 176474 176476.9 -218397.1 0 +175928.6 -217665.6 176073.9 175764.4 -217767.2 175473.8 -208655.2 175790.1 175827.1 175370.2 176051.1 -222781.9 -216899.9 176722.1 175387.8 -219465.7 111928.3 -220136.3 176223.3 176578.6 -211283 176475 176476.4 -218395.8 0 +175928.3 -217669.5 176073.5 175765.4 -217773.4 175474.7 -208657.2 175788.6 175827.4 175370.6 176050.9 -222783.3 -216895.6 176721.7 175388.8 -219462.2 111719.3 -220142.6 176223.2 176577.3 -211304.6 176475.5 176477.6 -218392.2 0 +175928.6 -217677 176073.8 175765.5 -217781.6 175477.1 -208661.2 175788.6 175827.1 175370.9 176050.9 -222783.2 -216896.4 176722.9 175389.6 -219480.1 111507.6 -220134.9 176223.1 176577 -211315.3 176475.9 176478.6 -218388.8 0 +175929.7 -217683.4 176074.6 175764.9 -217777.5 175478.7 -208659.7 175788.3 175826.9 175370.4 176050.8 -222787.2 -216907.7 176723.5 175389.4 -219537.9 111302 -220130.5 176223 176577 -211320.7 176476 176478.5 -218391.4 0 +175930.8 -217683.2 176075.7 175764.5 -217763.6 175478.2 -208667 175788.2 175827.6 175370.7 176050.5 -222793.7 -216921.9 176723.6 175388.1 -219624.2 111087.1 -220139.9 176222.5 176577 -211339.8 176475.1 176479 -218397.3 0 +175930.6 -217679.9 176075.6 175764.6 -217757.5 175477 -208685.1 175789.6 175828.1 175371.6 176050.2 -222794.8 -216924.8 176723.6 175386.7 -219688.8 110865.4 -220151.7 176222.6 176577.9 -211364 176474.3 176479.7 -218400 0 +175929.5 -217676.8 176074.8 175765.1 -217762.5 175476.7 -208653 175791.1 175828.3 175371.8 176050.7 -222791 -216917 176723.9 175386.5 -219701.4 110673.2 -220152.6 176223.7 176579.5 -211369.6 176475.1 176478.3 -218398.4 0 +175929.1 -217673.6 176074.8 175765.3 -217765.5 175477.2 -208507.3 175791.5 175828 175371 176051.4 -222789 -216911.5 176724.4 175387.4 -219679.8 110520.4 -220139.8 176224.2 176580.1 -211348.5 176475.9 176475.9 -218397 0 +175929.7 -217673.8 176074.4 175764.6 -217759.8 175477 -208294.9 175790.4 175827 175369.9 176051.4 -222789.3 -216913 176724.6 175388.4 -219655.4 110369.6 -220121.3 176223 176578.5 -211314.5 176474.8 176475.2 -218398.1 0 +175930.9 -217679.5 176073.5 175764.1 -217753.8 175476.5 -208138.7 175788.1 175826.8 175369 176050.7 -222789.4 -216916.4 176724.3 175388.9 -219636.1 110174.4 -220117.8 176221.9 176576.1 -211288.7 176472.7 176475.5 -218398.7 0 +175931.5 -217684.3 176074.3 175764.9 -217757 175476.2 -208094.2 175786.4 175828.3 175369.1 176049.9 -222789.7 -216916.9 176724.2 175389.3 -219621 109916.3 -220140.3 176222.7 176574.7 -211270 176472.4 176475.4 -218396.8 0 +175931.3 -217683.6 176076 175765.8 -217762.5 175476.4 -208115.5 175787.3 175829.8 175370.1 176049.5 -222790 -216915.6 176724.4 175390.1 -219614.2 109613.5 -220164.8 176224.2 176575.3 -211230 176474.3 176475.4 -218393.5 0 +175931.7 -217680.2 176076.6 175765.4 -217758 175476.7 -208147.5 175789.6 175829.8 175370.7 176049.5 -222789.7 -216917.3 176724.7 175390.3 -219600.3 109305 -220162.6 176224.4 176576.5 -211157.9 176476.3 176476.8 -218391.1 0 +175931.3 -217677.6 176076.6 175764.5 -217749.2 175476.9 -208173.3 175791.5 175829.5 175371.1 176049.8 -222788.2 -216920.3 176724.6 175389.9 -219560.7 109031.1 -220143.9 176223.9 176576.8 -211086.7 176477.5 176479.1 -218392.1 0 +175929.7 -217677.9 176076.6 175764.8 -217751.6 175477 -208191 175792.7 175829.9 175372.7 176050.8 -222786.3 -216917.6 176724.3 175390 -219518.4 108803.3 -220137.8 176224.3 176577.1 -211042.2 176477.3 176480 -218395.7 0 +175930.1 -217681.5 176076.5 175766 -217765.6 175477.7 -208211.8 175792.7 175829.8 175374.2 176051.7 -222786.3 -216910 176724.4 175389.9 -219507.9 108586.9 -220149.7 176225.7 176578.5 -210988.5 176475.2 176479.2 -218398.5 0 +175932.3 -217683.7 176076.3 175766.2 -217777.1 175478.2 -208260.7 175791 175828.3 175373.3 176051.3 -222787.5 -216904 176724 175389 -219520 108364.3 -220160.6 176226.4 176579.2 -210892.4 176472.8 176477.5 -218400.1 0 +175932.5 -217678.7 176075.2 175765.5 -217779.1 175477.7 -208348.3 175789.3 175826.7 175371.1 176050.2 -222787.7 -216901.3 176722.8 175388.4 -219518.1 108187.5 -220156.5 176224.8 176577.5 -210800.6 176471.9 176475.6 -218401.8 0 +175930.1 -217671.9 176073.5 175764.7 -217777.8 175476.7 -208456.5 175788.2 175826.5 175369.6 176049.3 -222788.1 -216896.1 176722.5 175389.3 -219490.9 108098.2 -220143.5 176222.3 176575.2 -210767.5 176472.2 176475 -218402.1 0 +175928 -217671.3 176072.4 175764.5 -217777.5 175476.2 -208554.3 175786.6 175827.4 175369.8 176049.4 -222789.2 -216886.1 176723.1 175389.8 -219463.2 108051 -220134.1 176222.3 176575.3 -210776.3 176472.2 176476 -218402.5 0 +175928.8 -217672.8 176073.1 175765.7 -217776.1 175476.5 -208620.5 175785.4 175828.3 175371 176050.4 -222789.3 -216880.5 176722.9 175388.3 -219453.3 107985.2 -220132.3 176224.2 176576.9 -210793.6 176472.3 176476.6 -218408.2 0 +175931.5 -217670.9 176074.2 175766.3 -217776.2 175476.8 -208665.7 175787.4 175828.1 175371.5 176051.3 -222787.4 -216881.9 176722.7 175386.2 -219446.3 107905.5 -220134 176224.3 176577.9 -210817.5 176473.8 176476.2 -218415.2 0 +175932.3 -217670.8 176074.3 175764.9 -217783.6 175476.9 -208725.4 175790.3 175827.3 175371 176051 -222785.2 -216884.9 176722.7 175386.3 -219429.2 107820 -220136.2 176222.5 176578.1 -210847.3 176475.3 176475.6 -218414.1 0 +175930.6 -217674.3 176075.2 175764.4 -217793.3 175477.3 -208816 175791.1 175827.1 175370.7 176050.3 -222784.3 -216889.7 176722.9 175388.5 -219416.5 107702 -220133 176222.6 176578.8 -210870.5 176475.3 176475.7 -218404.9 0 +175928.8 -217675.2 176077.2 175765.7 -217794.2 175477.9 -208919.2 175790.8 175827.2 175370.7 176049.7 -222784.6 -216894.6 176724.1 175390 -219425.5 107563.7 -220120.5 176224.6 176579.9 -210879.2 176475.3 176476.4 -218398.1 0 +175928.4 -217675.4 176076.2 175765.4 -217788.3 175477.8 -209016.3 175789.8 175826.4 175370 176048.6 -222785.3 -216896.2 176724.8 175389 -219456.6 107454.8 -220118 176225.1 176579.3 -210874.3 176474.4 176476.1 -218398.5 0 +175929.9 -217678.8 176073.1 175764.2 -217788.3 175476.9 -209108.4 175789.3 175825.9 175369 176047.9 -222785.4 -216899.6 176723.6 175387.7 -219487.7 107386.6 -220139.8 176223.8 176577.2 -210865.8 176473.3 176475.8 -218399.1 0 +175932.1 -217678.9 176072.7 175764.6 -217796.1 175476.6 -209198.3 175790.2 175827.1 175369.4 176048.8 -222786.5 -216906.9 176722.4 175388.3 -219483.4 107325.3 -220153.6 176222.8 176576.1 -210868.9 176474.7 176477.1 -218395.9 0 +175932.3 -217672.2 176073.6 175765.2 -217799.9 175476.5 -209278 175790.5 175827.8 175370 176049.8 -222789 -216909.9 176722.3 175389.7 -219446.4 107231.1 -220133.9 176222.3 176575.9 -210875.3 176476.4 176477.6 -218394.5 0 +175930.8 -217665.4 176073.2 175765 -217793.7 175476.1 -209344.9 175789.2 175826.6 175369.2 176049.7 -222789.2 -216904 176722.6 175390 -219422.7 107101.6 -220107.8 176222 176575.5 -210846.8 176475.2 176476.3 -218397.9 0 +175929.8 -217663 176073.6 175764.7 -217783.5 175476.2 -209412.8 175788.8 175825.8 175369.1 176049.5 -222787.3 -216895.4 176723.3 175389.3 -219430.8 106972.6 -220100.4 176222.6 176575.9 -210768.9 176473.6 176475.6 -218402.4 0 +175929.8 -217659.3 176076.3 175764.3 -217776.8 175476.8 -209482.4 175790 175827.2 175370.9 176049.4 -222787.6 -216893.5 176724.6 175388.9 -219441.4 106860.7 -220103.5 176223.8 176576.6 -210690.1 176473.8 176476.3 -218403.3 0 +175930.6 -217651.9 176077.7 175764 -217775.9 175477.3 -209527.6 175790.4 175829 175372 176049.5 -222791.1 -216899.1 176724.8 175388.7 -219428.7 106763.5 -220108.3 176224 176576.1 -210668.8 176474 176476.6 -218400.3 0 +175931.3 -217646.5 176076.9 175764.3 -217777.7 175477.9 -209546.8 175789.3 175829.7 175371.2 176049.8 -222793.8 -216904.3 176723.5 175388.4 -219399.2 106683.7 -220112.7 176223.9 176576 -210703 176474.4 176477 -218396.3 0 +175931 -217645.8 176076.7 175765.4 -217779.2 175478.1 -209579.3 175789.5 175830 175370.6 176050.3 -222794.3 -216905.6 176722.9 175388.7 -219372.3 106604.8 -220113.6 176225 176578.3 -210749.2 176476 176477.7 -218394.8 0 +175930.1 -217647.8 176077.2 175766.9 -217781.7 175477.7 -209637.6 175791.5 175829.9 175370.9 176050.8 -222795.7 -216902.9 176723.8 175389.3 -219349.4 106506 -220110.8 176226 176580.1 -210783.4 176477.2 176477.7 -218396 0 +175929.5 -217649.9 176076.9 175767.7 -217784.8 175477.3 -209691.3 175792.7 175828.8 175371.6 176050.7 -222797.7 -216894.2 176724.3 175388.8 -219326.9 106391.2 -220108.4 176225 176579.4 -210811.9 176476.8 176477.7 -218396.2 0 +175929.3 -217651.5 176076.3 175767.1 -217785.3 175477.4 -209725.9 175791.5 175827.3 175371.7 176049.7 -222798.3 -216887.8 176724.5 175388.3 -219322.2 106264.4 -220111.2 176223 176577.4 -210840 176475 176478.2 -218394.1 0 +175929.5 -217652.9 176075.6 175765.9 -217782.9 175477.4 -209751 175788.9 175826.8 175370.8 176049.4 -222799.2 -216892.7 176725.1 175388.4 -219347.5 106114.9 -220116.3 176221.9 176575.9 -210862.1 176472.1 176477.2 -218394.6 0 +175929.9 -217653.9 176075.2 175765.2 -217779.5 175477.3 -209771.8 175788 175827.6 175370.5 176050.3 -222799.6 -216897.9 176724.7 175388.2 -219384.1 105935.6 -220113.3 176222.6 176576.8 -210873.5 176471.5 176476 -218397.9 0 +175929.9 -217653.7 176074.7 175764.6 -217776.1 175477 -209798.6 175787.9 175828.8 175371.2 176050.3 -222798.2 -216895.9 176722.9 175388 -219411.9 105747.9 -220102.5 176223.8 176577.8 -210882 176473.9 176475.9 -218399 0 +175929.5 -217653.9 176072.9 175763.4 -217773 175476.5 -209848 175785.2 175828.4 175371 176048.4 -222797.1 -216898.5 176720.9 175388.4 -219433.3 105602.2 -220093.8 176223.1 176575.5 -210902.7 176474.4 176474.5 -218397.2 0 +175929 -217655.5 176071.4 175762.7 -217772.1 175475.8 -209905 175782.8 175826 175369.6 176046.8 -222794.7 -216906.6 176719.7 175388.5 -219450.3 105523.3 -220093.9 176221.4 176572.5 -210935.9 176472.5 176472.9 -218396.7 0 +175929.1 -217654.7 176071.9 175763.2 -217772.5 175475.3 -209932.6 175784.7 175824.2 175369.3 176047.7 -222790.5 -216908.2 176720.3 175387.8 -219453.2 105475.6 -220109.4 176221.4 176572.9 -210953.6 176471.9 176474.4 -218398.6 0 +175929.9 -217649.2 176072.8 175763.8 -217771.2 175475.4 -209935.6 175788 175825.2 175370.4 176049.7 -222791.3 -216907.1 176721.7 175386.5 -219449.3 105409.2 -220137.5 176222.3 176574.7 -210935.1 176472.2 176477.1 -218401.8 0 +175930.4 -217644.3 176073.7 175764.5 -217769.9 175476.6 -209943.4 175789 175827.7 175370.7 176050.6 -222797.5 -216911.6 176722.5 175386 -219456.6 105300.6 -220156.5 176222.8 176575.1 -210896.7 176472.6 176477.6 -218402.4 0 +175930.6 -217643.6 176074.8 175765.3 -217771.3 175477.4 -209946.7 175789.3 175829 175370.1 176050.7 -222801.8 -216917.4 176722.4 175386.4 -219467.8 105161.5 -220154.8 176223 176575.5 -210860.6 176474 176476.8 -218397.5 0 +175930.4 -217644.4 176074.6 175764.6 -217774.6 175477.1 -209939 175789.6 175828.5 175370.4 176050.1 -222801.6 -216918.3 176722.2 175386.9 -219469.6 105042.3 -220144.8 176222.3 176576.4 -210832.2 176474.6 176476.8 -218392.4 0 +175928.8 -217645.9 176073.8 175763.3 -217776.9 175476.9 -209952.4 175789.3 175827.2 175371 176049 -222797.9 -216914.1 176722.1 175386.6 -219481.9 104975.2 -220137.4 176220.9 176577.1 -210815.3 176473.7 176477.7 -218392.3 0 +175927.7 -217649.8 176074.1 175763.8 -217775.5 175476.3 -209989.2 175789.2 175826.5 175370.3 176049.3 -222794.2 -216909.9 176722.5 175386.6 -219522.7 104932.6 -220134.7 176221 176577 -210814.3 176473.6 176477.9 -218394.3 0 +175928.9 -217653.9 176074.6 175765.3 -217771.8 175475 -210015.6 175789.3 175827.1 175369.3 176051.5 -222794.6 -216910.6 176723.1 175387.8 -219568.2 104907 -220134.3 176222 176576.3 -210831.6 176474.5 176477.5 -218396.8 0 +175930.2 -217654.1 176074.7 175765.7 -217769.9 175475.4 -210027.3 175789.4 175828.3 175369.2 176052.9 -222795.7 -216909.8 176723.2 175389.1 -219585.4 104927.9 -220128.4 176222.3 176576.3 -210866.8 176474.9 176477.9 -218399.9 0 +175929.6 -217652 176075.3 175765.5 -217771 175477.3 -210048.6 175790.4 175828.6 175369 176052.1 -222793.4 -216903 176723 175389.6 -219573.7 104964.7 -220114.6 176222.6 176578 -210902.4 176474.7 176478.3 -218401.1 0 +175929.2 -217652 176075.8 175765.6 -217775.6 175477.6 -210085.4 175790.8 175827.9 175368.7 176051 -222792.2 -216900.7 176723.5 175390.3 -219559.7 104949.8 -220101 176222.7 176579.2 -210918.1 176473.6 176477.6 -218398.9 0 +175930 -217653.8 176075.6 175764.5 -217783.4 175476.6 -210112 175788.9 175826.6 175369.3 176050.5 -222794 -216907.8 176723.2 175389.8 -219567.2 104879.3 -220098.8 176221.7 176577.1 -210923.7 176471.8 176477.3 -218397.7 0 +175929.5 -217655.7 176074.8 175762.4 -217790.1 175476.3 -210117.5 175787.6 175825.1 175369.9 176049.9 -222794 -216914.3 176721.1 175387.3 -219590.2 104794.6 -220112.3 176221.1 176575.3 -210928.4 176471.1 176477.5 -218401.9 0 +175927.2 -217657.1 176074.7 175762.3 -217791.7 175476.2 -210138.7 175788.9 175824.8 175369.6 176049.3 -222791.7 -216914.2 176719.8 175385 -219600.5 104731.4 -220129.2 176222.4 176577.2 -210901.6 176472.7 176477.1 -218405.9 0 +175926.2 -217656 176075.3 175763.9 -217788.5 175476 -210208.2 175789.3 175826.6 175369.3 176048.8 -222792.2 -216912.4 176720.6 175384.9 -219597.9 104713.6 -220133.6 176223.9 176578.5 -210826 176473.9 176476.2 -218402.9 0 +175927.4 -217653.1 176074.5 175764.1 -217787 175475.9 -210302.8 175787.3 175828.3 175369.5 176048.3 -222796.3 -216913.7 176720.5 175386.1 -219605.4 104734.3 -220123.9 176223 176576.2 -210738.5 176472.6 176475.5 -218397.3 0 +175928.5 -217650.9 176073.2 175763.3 -217790.1 175476 -210385.1 175787.5 175827.5 175369.4 176048.9 -222798.1 -216915.8 176719.7 175386.6 -219615.3 104760.7 -220108.3 176221.5 176575.5 -210681.1 176472 176476.2 -218394.7 0 +175929.7 -217649.7 176074.1 175763.9 -217789.6 175476.4 -210456.3 175790.8 175825.8 175369.1 176050.2 -222794.6 -216913.8 176721.2 175386.3 -219605.2 104773.2 -220100.2 176222.2 176578.2 -210667.6 176474.2 176477.6 -218392.8 0 +175930.6 -217650.6 176074.6 175765.6 -217781.4 175476.6 -210527.9 175790.7 175826.3 175368.8 176050 -222790.7 -216906.2 176723 175386.6 -219588.7 104766.5 -220109.9 176223.7 176578.5 -210687.9 176475.4 176477.1 -218390.2 0 +175929.8 -217652.3 176072.8 175766.3 -217775.9 175476.1 -210592.5 175786.7 175827.8 175368.3 176048.1 -222790.4 -216897.2 176721.8 175387.8 -219595.4 104740.3 -220123.1 176223.6 176576 -210710.5 176472.9 176475.2 -218390.2 0 +175928.9 -217651.4 176072.5 175765.3 -217780.8 175475.7 -210658.9 175785.9 175828.1 175368.1 176047.6 -222790.6 -216895.5 176719.9 175388.5 -219614.2 104714.3 -220119.5 176223 176576 -210711 176470.8 176475.3 -218394.8 0 +175929.6 -217648.6 176075.8 175764 -217788.5 175475.9 -210753.1 175789.6 175827.9 175369.5 176049 -222787.4 -216903.4 176720.9 175388.6 -219606.6 104698.9 -220109.2 176222.8 176579.1 -210702.5 176472.2 176477.2 -218400.7 0 +175930.2 -217646.9 176078 175764.1 -217790 175476.3 -210871.8 175791.3 175828 175371.9 176049.7 -222783.1 -216912.6 176723 175389.3 -219583.8 104655.5 -220109.3 176221.9 176579.8 -210711.3 176474.3 176478.1 -218402 0 +175929.8 -217646.8 176076.2 175764.6 -217786.9 175476.3 -210984 175789.3 175827.8 175372.1 176049.3 -222780.5 -216912.4 176723 175389.8 -219595.6 104555.6 -220109.8 176220.9 176577.6 -210734.1 176474.3 176476.6 -218396.9 0 +175929.8 -217647.2 176074 175764.8 -217783.1 175476.6 -211061.4 175788.3 175827 175369.9 176049.6 -222779.5 -216897.6 176722.3 175389.4 -219633.6 104442.2 -220094.5 176221.2 176577.3 -210738.8 176474.1 176475.4 -218387.9 0 +175929.8 -217647.8 176074.3 175765 -217780.1 175477.2 -211089.1 175788.6 175826.3 175368.7 176050.7 -222783.5 -216879.4 176722 175389.2 -219645.7 104367 -220072.7 176221.7 176579 -210713.4 176474.2 176476 -218383.8 0 +175929.3 -217645.9 176075.2 175765.4 -217780.3 175476.8 -211082.9 175787.8 175826.3 175369.1 176050.4 -222793 -216880 176721.9 175388.7 -219627.4 104315.3 -220061.9 176221 176578.1 -210688.4 176472.9 176476.4 -218390 0 +175929.2 -217639.7 176075.1 175765.2 -217782.8 175476.3 -211077.3 175787.7 175826.6 175368.9 176049 -222796.7 -216894 176722.1 175387.3 -219606.4 104233.3 -220056.8 176220.9 176575.8 -210699.6 176472.6 176475.6 -218396.5 0 +175929.5 -217634.4 176074.5 175764 -217783.3 175476.3 -211081.7 175789.8 175826.7 175368.1 176049.2 -222790.3 -216895.4 176722.6 175386.5 -219581.8 104114.9 -220044.8 176221.8 176575.8 -210741.7 176474.9 176475.4 -218395.3 0 +175929.4 -217637.3 176073.9 175763 -217781.8 175475.8 -211083.8 175790.5 175826.7 175367.8 176049.9 -222786.7 -216887.4 176722.4 175386.8 -219543.1 104041.5 -220037.3 176221.5 176576.7 -210778.2 176475.4 176475.8 -218394.3 0 +175928.9 -217644.6 176073.8 175763.3 -217781.1 175475.1 -211082.7 175788.1 175826.8 175368.1 176048.7 -222792.9 -216886.7 176721.3 175387.3 -219503.1 104067.1 -220048.7 176219.7 176575.6 -210793.1 176472 176476.2 -218397.5 0 +175928.5 -217647.1 176074.8 175764 -217781.2 175476 -211085 175785.7 175826.9 175368.8 176047.6 -222797.6 -216889.3 176721.5 175387.8 -219472.4 104108.4 -220062.6 176219.2 176574.8 -210802.6 176470.5 176477 -218399.3 0 +175928.8 -217643.3 176076.1 175763.8 -217782.2 175477.6 -211090.2 175786.2 175827.5 175369.8 176049.1 -222792.9 -216892 176722.4 175388 -219439.3 104088 -220064.8 176220.8 176576.2 -210820.9 176473.1 176478.3 -218397.3 0 +175930.2 -217639 176075.6 175763.8 -217784.9 175478.1 -211089.4 175787.5 175828.7 175370.8 176050.7 -222788.4 -216898.2 176721.5 175387.5 -219404.2 104061.5 -220072.7 176222.3 176577.2 -210840.7 176474.8 176478.3 -218395.4 0 +175931.4 -217636.4 176074 175764.2 -217788 175478 -211068.9 175787.9 175829.1 175371.2 176050.2 -222789.5 -216898.7 176720.1 175386.7 -219387.9 104079.1 -220094.4 176223.1 176577.3 -210844.5 176474.8 176477 -218395.7 0 +175930.4 -217633.6 176074.3 175764 -217790.8 175477.9 -211030.5 175788.7 175828 175370.9 176049.2 -222786.5 -216891.7 176721.7 175387 -219395.7 104094.7 -220114.5 176223.6 176578.2 -210840.6 176476.3 176476.9 -218397.4 0 +175928 -217633.5 176075.2 175763.3 -217793.1 175476.3 -210997.8 175788.7 175826.3 175370.2 176048.9 -222781.4 -216891.8 176724.1 175387.7 -219411.7 104060.1 -220124.6 176222.8 176577.9 -210863.4 176476.2 176477.5 -218401.3 0 +175926.9 -217638.5 176073.8 175762.6 -217793.2 175474.4 -210983 175786.6 175825.6 175368.9 176048.1 -222786 -216903.3 176723.5 175387.4 -219420.3 103970 -220123.1 176221 176575.3 -210912.2 176473.4 176476.8 -218404.1 0 +175927.8 -217642.2 176072.1 175761.6 -217790.5 175474.7 -210983.1 175785.5 175826.1 175368.2 176047.1 -222793 -216913.2 176722 175386.3 -219419.6 103841.9 -220105.5 176220.4 176573.8 -210941.4 176472.7 176475.7 -218399.2 0 +175929.4 -217640.8 176072.5 175761.4 -217786.6 175475.8 -211000.7 175786.5 175825.8 175368.2 176047.3 -222790.4 -216916.9 176722 175386 -219422.6 103708.1 -220079.1 176221 176574.8 -210936.7 176473.7 176475.3 -218393.1 0 +175930.5 -217637.7 176073.2 175763 -217785.9 175475.6 -211034 175787 175824.3 175368.2 176048.9 -222785.1 -216920 176722 175387.2 -219438.9 103584.4 -220063.1 176221.7 176575.3 -210927.3 176473 176474.5 -218395.9 0 +175931.2 -217634.4 176073.7 175764.3 -217792.1 175475.9 -211065.3 175787.4 175824.2 175368.7 176049.9 -222784.3 -216922.7 176721.4 175388.9 -219458.2 103453.4 -220069 176222.6 176575.2 -210923.5 176472.6 176473.6 -218400.2 0 +175931.3 -217637.9 176074 175763.4 -217797.2 175477 -211078.6 175787.1 175825.8 175369.5 176048.6 -222784.8 -216922.3 176721.4 175389.3 -219470.9 103329.3 -220085.9 176222.7 176575.3 -210908.7 176472.8 176473.1 -218398.2 0 +175930.4 -217653.6 176073.8 175761.9 -217791.8 175476.8 -211069.7 175786.3 175826.4 175369.2 176047.3 -222782.6 -216918.3 176721.8 175387.8 -219485.1 103269.3 -220091.5 176221.6 176575.6 -210880.3 176471.5 176472.8 -218394.9 0 +175929.3 -217667 176073.9 175762.5 -217783.5 175476.1 -211045.7 175788.2 175825.6 175369.1 176048.8 -222780.3 -216909.8 176721.7 175386.7 -219510.2 103270.5 -220090.8 176221 176576.3 -210851.4 176470.6 176474.2 -218393.8 0 +175929.3 -217665.1 176074.9 175764.8 -217784.4 175476.5 -211016.3 175791.4 175826.2 175370.1 176050.9 -222782.9 -216899.5 176721.9 175387 -219544.2 103255.7 -220109.3 176221.4 176576.5 -210827.7 176472.2 176477 -218394.6 0 +175929.7 -217658.2 176075.1 175765.4 -217792.6 175476.8 -210971.3 175790.9 175827 175369.6 176049.7 -222787.6 -216893.2 176722.5 175387.1 -219580.1 103192.4 -220138.2 176221.6 176576 -210803 176473.7 176477.8 -218396.7 0 +175929.5 -217660.3 176072.7 175762.7 -217799.1 175475.3 -210893.5 175786.8 175825.3 175367.1 176046.6 -222788.1 -216893.4 176721.8 175386 -219605.7 103115.9 -220146.4 176220.9 176575 -210779.1 176472.9 176475.3 -218397.1 0 +175929.1 -217667.1 176070.4 175760 -217799.8 175473.6 -210798.8 175784.7 175824.2 175365.2 176045.7 -222786.1 -216898.4 176720.5 175385.3 -219607.1 103049.2 -220138.7 176220.1 176574.1 -210779.1 176472.1 176473.5 -218393.7 100 +175928.8 -217669.6 176071.5 175760.7 -217796.5 175474.1 -210720.7 175786.4 175826.1 175365.8 176047.4 -222784.9 -216904.4 176720.5 175385.7 -219591.6 103003.6 -220132.4 176220 176574.7 -210813.9 176472.7 176475.3 -218390.4 0 +175928.1 -217671.6 176072.7 175763 -217793.8 175474.4 -210657.8 175787.2 175826.8 175367.4 176048.6 -222785.4 -216906.6 176720.7 175385.9 -219584.9 103004.4 -220123.2 176219.8 176575.1 -210843.8 176472.2 176476.4 -218391.4 0 +175927.9 -217674.4 176071.5 175763.1 -217793.1 175472.9 -210575.5 175785.3 175824.2 175367.4 176047.5 -222786.7 -216902 176719.7 175385.8 -219596.2 103044.6 -220111 176219.3 176574.1 -210824.8 176471.2 176474.5 -218393.1 0 +175928.9 -217671.2 176071.3 175761.7 -217794.8 175473.3 -210474.3 175785.1 175822.9 175366.6 176045.9 -222786.8 -216893.4 176720 175386.6 -219612.5 103070 -220105.9 176219.7 176574.6 -210773.1 176472.8 176473.8 -218390 0 +175930.1 -217665.4 176073.2 175761 -217798.7 175475.9 -210408.2 175786.7 175824.7 175367.2 176046.3 -222789.1 -216887 176721.2 175387.4 -219624.5 103053.2 -220109.2 176220.5 176576 -210740.1 176473.9 176475.4 -218387.1 0 +175930.4 -217664.6 176074.4 175761 -217802.1 175477 -210389.8 175786.5 175825.7 175368.5 176048 -222794.8 -216885.7 176720.8 175387.3 -219627.8 103020.1 -220117.6 176220.8 176575.5 -210749.3 176472.2 176476.2 -218390.4 0 +175928.7 -217665.7 176073.7 175761.1 -217801.5 175476.1 -210376.3 175785.1 175824.9 175368.8 176048.3 -222796.9 -216889.9 176719.7 175387.1 -219615.6 102988.4 -220126.9 176221 176574.2 -210789.5 176470.1 176475.4 -218396.3 0 +175925.5 -217667 176072.9 175761.4 -217797.1 175475.3 -210375.5 175784.8 175824.4 175368.3 176047.2 -222793.1 -216895.2 176719.4 175386.4 -219595.8 102964.7 -220131.7 176221.3 176574.4 -210835.1 176469.3 176474.2 -218398.6 0 +175924.3 -217668.2 176074.2 175761.5 -217790.2 175475.8 -210424.6 175786.4 175825.4 175368.2 176047.2 -222787.8 -216893.8 176719.9 175385.7 -219587.2 102972.7 -220128.9 176221.8 176576.6 -210861.1 176471 176474 -218397 0 +175926.8 -217663.3 176076 175761.8 -217783.3 175476.3 -210493.9 175787.4 175826.3 175367.9 176048.3 -222784.6 -216886.5 176720.5 175386.5 -219589.6 102994.4 -220124 176221.3 176577.7 -210865.5 176473.5 176474.1 -218395 0 +175928.7 -217652.1 176074.7 175762.6 -217782.3 175474.6 -210540 175785.6 175826.1 175367.1 176048 -222784 -216882.1 176720.3 175388.3 -219589.5 102961.8 -220127.6 176219.5 176575.3 -210867 176473 176473.3 -218393.8 0 +175927.7 -217641.7 176072.1 175763.3 -217788.4 175472.8 -210577.2 175784.2 175824.5 175367.2 176047 -222782.8 -216883.8 176719.6 175388.8 -219579.1 102852.2 -220136.5 176218.1 176573.1 -210874.4 176471 176472.9 -218389.3 0 +175927.5 -217637.3 176071.9 175763.2 -217794.6 175473.4 -210625.2 175785.5 175823.4 175367.6 176047.6 -222779.7 -216889.9 176718.9 175387.5 -219551.1 102711.7 -220136.7 176218.6 176574.1 -210885.3 176470.6 176473.5 -218383.4 0 +175929.7 -217639.8 176073.6 175763.2 -217796.5 175474.2 -210670.4 175787.5 175824.6 175367.5 176048.5 -222777.2 -216895.8 176719.3 175385.9 -219507.6 102592 -220127.9 176220.3 176575.2 -210916.8 176471.5 176474 -218382.2 0 +175930.7 -217643.5 176075.6 175764.3 -217796.3 175474 -210704.7 175789.4 175826.7 175368.6 176049.1 -222776.5 -216894.7 176721.3 175385.4 -219473.7 102498.4 -220118.5 176221.8 176575.2 -210988.2 176472.7 176475.2 -218384.8 0 +175928.7 -217641.6 176077.1 175765.5 -217795.7 175474.8 -210733.9 175790.9 175826.7 175370.4 176049.6 -222778.6 -216889.3 176723.2 175386.1 -219469.8 102380.5 -220113.4 176222.4 176576.1 -211072.5 176473.8 176476.6 -218386 0 +175926.5 -217639.8 176076.6 175764.8 -217793.3 175475.7 -210749.4 175790.4 175825.1 175369.8 176049.1 -222782.4 -216888.2 176723 175386.5 -219483.9 102190.8 -220118 176222.4 176576.7 -211115.4 176473.9 176476.4 -218385.4 0 +175926.4 -217645.2 176074.4 175763.1 -217787.9 175475.3 -210750.2 175788.7 175824.3 175367.2 176047.6 -222783.1 -216886.8 176721.5 175385.8 -219493.3 101956.3 -220132.2 176221.8 176575.7 -211107.3 176473.6 176476 -218385.1 0 +175927.6 -217653.9 176072 175762.1 -217782.6 175474.4 -210772.2 175787.7 175825.1 175366.2 176047.1 -222783.3 -216877.4 176720.6 175384.5 -219495.6 101755.9 -220144.8 176220.9 176574.5 -211091.2 176472.6 176476.5 -218388 0 +175929.1 -217658.5 176070.3 175761.8 -217781.5 175473.8 -210837.6 175786.9 175825.8 175367.4 176047.6 -222788.4 -216869.2 176720.2 175384.2 -219495.6 101623.2 -220146.3 176220.6 176574.2 -211084.2 176470.5 176476 -218393.8 0 +175930 -217655.7 176070.9 175761.9 -217784 175474.3 -210913.5 175787.7 175825.4 175368.2 176048.4 -222793.7 -216874.2 176720.6 175384.9 -219483.3 101516.2 -220136.8 176221.3 176575.5 -211054.6 176470.9 176475.1 -218395.7 0 +175929.2 -217649.1 176074.4 175762.4 -217787 175476.2 -210959 175789.5 175825.5 175367.8 176049.9 -222794.2 -216889.8 176721.7 175385.9 -219454.8 101396.5 -220127.3 176222.5 176578.2 -211004.4 176474.1 176476.4 -218393 0 +175927.7 -217646.6 176076 175762.9 -217789.8 175477.6 -210974.8 175788.3 175826.5 175367.4 176051.2 -222792.7 -216904.4 176721.6 175386.9 -219425.8 101285.6 -220126.7 176222.7 176578.4 -210982.5 176474.1 176477.4 -218394.1 0 +175927.3 -217645.6 176073.4 175763 -217791.4 175475.9 -210991.7 175785.6 175826.5 175367.9 176049.9 -222788.3 -216910.2 176720.1 175387.2 -219411.7 101218.9 -220130.2 176221.1 176575.3 -211001.2 176470.9 176475.2 -218395.7 0 +175928.1 -217640.3 176071.4 175762.2 -217791.3 175472.5 -211030.4 175786.6 175825.5 175368.4 176047.5 -222781.6 -216908.6 176720 175386.5 -219422.3 101188.9 -220133.4 176220.2 176573.3 -211030.6 176470.1 176472.9 -218390.3 0 +175927.8 -217640.8 176072.6 175760.9 -217790.6 175471.4 -211088.5 175788.8 175825 175368.2 176046.9 -222779.7 -216905.9 176721.9 175385.4 -219459.6 101157.5 -220136.9 176221.1 176573.7 -211033.9 176472.3 176473.5 -218385.5 0 +175926.3 -217655 176073 175760.4 -217790.4 175473.2 -211154 175787.8 175825 175367.1 176047.1 -222783.2 -216906.1 176722.2 175384.9 -219513.5 101102.2 -220136.9 176222.3 176573.8 -210979.5 176473.3 176474.8 -218387.9 0 +175925.9 -217669.4 176071.7 175761.3 -217789.9 175474.8 -211207.1 175785.9 175825.3 175366.5 176046.9 -222786.6 -216905.3 176719.8 175385.3 -219575.6 101023.1 -220130.7 176222.3 176573.3 -210894.8 176471.7 176475.1 -218391.1 0 +175928.2 -217671.2 176072.1 175762.4 -217788.4 175475.3 -211230.3 175785.9 175825.6 175366.9 176046.5 -222788.7 -216898.5 176717.8 175386.5 -219634.5 100914.1 -220123.4 176220.6 176573.6 -210857.5 176470.2 176474.7 -218391.5 0 +175930.2 -217666.7 176073.4 175762.8 -217786.1 175475.8 -211239.6 175785.8 175824.5 175366.7 176045.8 -222790.6 -216892 176717.9 175387 -219673.9 100767.6 -220124.1 176219 176574.1 -210888.4 176469.5 176473.4 -218393.5 100 +175928.4 -217664.2 176073.7 175762.3 -217784.3 175476.3 -211261.3 175787.2 175822.7 175366.2 176046.1 -222788.4 -216891.2 176719.7 175385.8 -219690.4 100596.8 -220132.6 176218.8 176575.1 -210933.7 176470.3 176472.9 -218396 0 +175924.9 -217664.2 176074.2 175762 -217785.2 175476 -211282.9 175790.7 175823.1 175367.1 176047.9 -222781.2 -216890.2 176722.5 175384.7 -219684.8 100422.7 -220134.9 176219.5 176577 -210951.2 176472.6 176474.2 -218395.3 0 +175925.3 -217667.2 176073.7 175762.5 -217789.9 175474.7 -211273.6 175790 175825 175367.7 176048.3 -222778.3 -216891.1 176723.3 175385.1 -219656.6 100272.7 -220124.3 176219.6 176576.5 -210948.2 176472.8 176474.4 -218393.9 0 +175929 -217670.5 176071.2 175762.8 -217794.5 175473.7 -211234.5 175785.2 175825.7 175366.6 176047 -222783.3 -216901.2 176721.1 175385.7 -219621.8 100189.3 -220114.7 176219.3 176574.1 -210944 176470.8 176473.1 -218392.6 0 +175931.1 -217668.1 176070.5 175762.3 -217794.8 175474.4 -211197.6 175783.1 175824.7 175366.1 176046.4 -222785.8 -216911.1 176719.8 175386.3 -219599.4 100167.7 -220120.4 176219.2 176574.1 -210945.4 176471.6 176473.3 -218389.7 0 +175930.1 -217664.3 176072.4 175761.6 -217791.4 175475.4 -211187.8 175784.1 175824 175367.3 176046.4 -222783.3 -216910.2 176720.9 175386.9 -219590.8 100137.8 -220139.6 176219.3 176574.2 -210959.4 176473.8 176474.5 -218390.1 0 +175927.6 -217666.1 176072.8 175761.7 -217786.1 175475 -211190.9 175785.2 175824.5 175368 176045.5 -222782.5 -216903.8 176721.9 175386.8 -219590.8 100073.1 -220156.2 176220.1 176572.4 -210986.1 176473 176474.7 -218393.6 0 +175926 -217667.7 176072 175762.9 -217779.8 175474.6 -211183.1 175786.5 175825.3 175368.1 176045.4 -222782 -216901.8 176721.5 175386.3 -219582.4 100013.7 -220155.3 176221.4 176572.8 -210994.2 176471.3 176474.9 -218392.6 0 +175926.7 -217664.9 176072.7 175763.5 -217777.8 175475.3 -211176.7 175787.1 175825.7 175368.5 176047.3 -222779 -216905.6 176720.9 175386 -219539.7 99977.3 -220140.2 176222.1 176575.3 -210958 176472 176475.6 -218389.3 0 +175927.7 -217666.1 176073.2 175762 -217785.3 175475.3 -211186.3 175785.6 175825.5 175368 176048.3 -222779.3 -216908.8 176719.7 175385.8 -219472.9 99942.57 -220127.6 176221.9 176575 -210904 176472.4 176475.6 -218390.5 0 +175927.4 -217673.2 176071.8 175760.1 -217794.5 175474.3 -211189.3 175783.8 175824.7 175366.5 176046.6 -222783.3 -216906.5 176718.2 175386.6 -219421.6 99872.88 -220123.7 176221 176572.3 -210885.3 176470.6 176475.2 -218394 0 +175927.6 -217675.3 176071.4 175760.5 -217794.8 175474 -211173.9 175784.6 175824.3 175366.4 176045.2 -222784.1 -216898.1 176718.1 175388.1 -219387.2 99745.95 -220116.9 176220.5 176572.9 -210919.1 176470.3 176475.4 -218393.6 0 +175928.4 -217668.9 176073.3 175762.4 -217790 175474.9 -211167.9 175787.4 175825.3 175368.5 176046.7 -222783 -216889.1 176719.2 175387.9 -219347.4 99588.84 -220101.5 176221.5 176575.9 -210972.9 176472.5 176475.6 -218391 0 +175928.6 -217661.2 176074.3 175763.3 -217788.8 175474.5 -211195.5 175787.5 175826.9 175369.6 176048 -222785.2 -216888.5 176718.8 175385.3 -219310.2 99428.38 -220088.8 176221.3 176575.8 -211015.9 176472 176475 -218391.9 0 +175928.5 -217655.7 176073.5 175762.9 -217792.3 175473.5 -211239.2 175785.4 175826.9 175368.6 176046.8 -222787.3 -216893.5 176718.2 175383.6 -219286.1 99244.26 -220080.9 176219.6 176573.5 -211054 176469.5 176474.8 -218394 0 +175928.3 -217650.8 176073.2 175762.5 -217799 175474.9 -211248.5 175785.9 175825.1 175367.7 176046 -222785.6 -216891.4 176720.1 175384.9 -219261.4 99028.59 -220070.2 176219.8 176574.3 -211097.9 176470.6 176475.4 -218393.1 0 +175927.5 -217647.1 176073 175761.6 -217805.7 175476.6 -211198.9 175787.9 175823.4 175367.6 176047.3 -222783.4 -216884.2 176722.3 175386.8 -219232.4 98824.77 -220066 176221.2 176576.4 -211131.6 176473.1 176475.5 -218392.5 0 +175926.5 -217646.3 176071.2 175760.6 -217807.1 175475.8 -211137 175787.2 175823.2 175367.1 176047.5 -222784.1 -216885 176721.8 175386.9 -219208.8 98674.22 -220077.5 176220.7 176576.1 -211138.6 176472.5 176474.4 -218394.5 0 +175926.1 -217645.2 176070.4 175761.4 -217804.1 175473.8 -211124.2 175785.4 175824.3 175366.5 176046.3 -222785.3 -216890.8 176720.3 175386.7 -219185.5 98561.77 -220089 176219.2 176575.4 -211133.7 176470.9 176473.6 -218395.1 0 +175927.2 -217639 176072.2 175763.3 -217800.8 175472.7 -211162.4 175785.8 175824.7 175366.7 176047.4 -222784.4 -216888.9 176719.3 175386.9 -219157.7 98435.34 -220087.6 176219.1 176576.4 -211146.4 176471.4 176474 -218390.8 0 +175928.6 -217633.3 176073.2 175763.6 -217797.9 175473.1 -211212.8 175787.3 175823.7 175367.2 176050.4 -222782.3 -216885.3 176718.7 175386.2 -219143.3 98264.34 -220083.3 176219.8 176576.9 -211188.5 176472.5 176475.1 -218384.6 0 +175928.1 -217635.6 176071.8 175762 -217795.8 175473.7 -211254.7 175786.9 175823.5 175367.2 176050.1 -222782.5 -216894.3 176718.9 175385.2 -219159.3 98064.2 -220089.3 176220.2 176575.3 -211248.1 176471.9 176475 -218381.8 0 +175926.7 -217642.4 176070.5 175760.2 -217795.7 175472.6 -211296.3 175784.8 175824.8 175366.6 176046.6 -222786 -216908.6 176720 175385.2 -219186.5 97870.14 -220103.6 176220.9 176572.9 -211302.1 176470.1 176472.6 -218383 0 +175927.2 -217647.4 176070.8 175759.4 -217795.9 175471.8 -211338.3 175783.7 175825 175365.5 176044 -222789.3 -216910 176719.7 175385.3 -219193.4 97683.73 -220110.2 176220.9 176571.6 -211323.3 176468.8 176470.9 -218385.7 0 +175928.6 -217648.3 176071.8 175760.3 -217796.4 175473.1 -211350.6 175785 175823.5 175365.1 176044.5 -222788.8 -216900.1 176719 175384.8 -219187.8 97477 -220104.2 176219.9 176573.1 -211293.8 176469.6 176472.2 -218388.1 0 +175928.9 -217646 176072.3 175761.9 -217799.8 175475 -211307.8 175786.4 175823.4 175366.4 176045.5 -222787 -216896.5 176719.5 175385 -219197.7 97268.08 -220102.7 176219.5 176575.7 -211231 176471.1 176474 -218391 0 +175928.7 -217643.4 176072.1 175763 -217802.3 175475.9 -211220.8 175786.5 175825.2 175367.7 176045.2 -222787.2 -216904.4 176719.5 175385.6 -219216.7 97111.12 -220111.7 176219.7 176576.1 -211179 176471.1 176474 -218394.7 0 +175929 -217642.8 176072.6 175762.6 -217798.9 175476.9 -211119.6 175786.7 175825.4 175367 176044.9 -222785.1 -216912.6 176718.5 175385.8 -219221 97012.27 -220115.5 176219.9 176576 -211158.2 176472.1 176474.1 -218396 0 +175928.4 -217643.6 176073.7 175761.8 -217795.8 175477 -211033.9 175786.3 175823.5 175366.2 176045.3 -222781.7 -216912.2 176718.3 175386 -219216.3 96940.88 -220114 176220.8 176576.4 -211158.5 176473.7 176475 -218393.8 0 +175926.4 -217644.7 176072.5 175761.8 -217797.8 175475 -210973.9 175784.3 175822.8 175366.8 176044.5 -222783.5 -216903.3 176718.5 175385.9 -219221.3 96869.21 -220119.2 176221.6 176574.8 -211183.7 176472.2 176474.3 -218392.5 0 +175925.2 -217646.9 176070.3 175762.5 -217796.5 175473.2 -210901.8 175783.6 175823.5 175367.6 176043.6 -222785.7 -216891.3 176719.1 175385.2 -219236.2 96760.98 -220119.7 176221.4 176572.6 -211242.1 176469.8 176472.5 -218392.3 0 +175926.1 -217653.6 176070.8 175763.3 -217792 175473.8 -210776.9 175785.8 175823.7 175367.8 176045 -222782.3 -216885.3 176721.4 175385 -219253.3 96609.38 -220109.8 176221.3 176573.2 -211309.1 176470.5 176472 -218392.5 0 +175927.8 -217662.7 176072.5 175763.7 -217795.1 175474.6 -210630.6 175787.3 175823.9 175367.4 176047.2 -222779.3 -216886.2 176723.5 175385.4 -219274.1 96481.66 -220110.1 176222.2 176574.8 -211352.6 176471.7 176472.3 -218395.2 100 +175928.1 -217668 176072.2 175763 -217800.8 175474.2 -210527.4 175786.1 175824.4 175367.1 176048 -222780.6 -216886.1 176722.9 175385.5 -219304.9 96448.75 -220123.6 176222.4 176575.1 -211372.2 176470.8 176472.3 -218399.3 0 +175927.1 -217668.2 176071.3 175761.7 -217796.4 175473.6 -210479.1 175785 175824.4 175367.2 176047.8 -222782.1 -216885.2 176720.9 175386 -219339.3 96480.57 -220133.5 176220.9 176574.8 -211379.3 176469.5 176472.6 -218401.3 0 +175926.3 -217664 176071.9 175761 -217789.9 175473 -210458.6 175786 175824.1 175367.5 176047 -222781.6 -216886.2 176719.7 175387 -219345.9 96461.01 -220139.3 176219.6 176575.3 -211382.9 176470.4 176474.2 -218399.7 0 +175925 -217656 176072.7 175761 -217793.3 175473 -210441.8 175786.9 175824.3 175367.8 176045.8 -222781.7 -216884.1 176719.3 175387.9 -219300.3 96320.88 -220141.7 176219.6 176575.3 -211404.3 176472.2 176475.8 -218395 0 +175922.7 -217650.2 176072.1 175761.3 -217796.9 175473.6 -210410.6 175786 175824.8 175367.8 176045.5 -222784.9 -216878.5 176719 175387.9 -219231.3 96110.78 -220133.8 176220.4 176574.4 -211443.4 176471.6 176475.4 -218391.1 0 +175923.2 -217648.1 176071.4 175761.6 -217791 175474.2 -210366.1 175785.7 175824.7 175367.1 176046.3 -222788.7 -216875.9 176718.7 175387.2 -219193.6 95904.71 -220126 176221 176574.3 -211460.8 176469.8 176474.2 -218391.4 0 +175926.8 -217643.2 176071.1 175761.3 -217786.6 175474.6 -210327.2 175787.3 175824.3 175366.3 176046.9 -222788 -216876 176719.4 175386.4 -219192.9 95705.7 -220129.3 176220.6 176574.9 -211449.8 176470.1 176473.5 -218392.4 0 +175928.2 -217638.1 176071 175760.4 -217790.8 175475.1 -210302.8 175788.3 175824.6 175366.7 176047 -222785.2 -216874.5 176720.9 175386.2 -219190.6 95490.06 -220135.8 176220.4 176574.9 -211444.6 176471.1 176473.6 -218391.1 0 +175927.1 -217639.9 176071.1 175760.5 -217795.5 175475.4 -210300.5 175787.9 175825.2 175367.4 176046.9 -222784 -216873.1 176721 175386.3 -219177.4 95272.24 -220139.5 176221 176574.7 -211447.7 176470.6 176473.9 -218389.9 0 +175927.5 -217643.8 176071.2 175761.7 -217797.4 175474.5 -210331.1 175786.4 175825.4 175367.1 176046.2 -222784.6 -216876.5 176719.3 175385.7 -219184.7 95082.62 -220142.3 176221.5 176574.1 -211439.6 176469.8 176473.4 -218391.8 0 +175928.3 -217640.8 176071.3 175762.3 -217798.1 175473.6 -210373.4 175784.9 175825.5 175367.1 176045.3 -222786.5 -216886.5 176718.4 175385 -219214 94910.6 -220142.9 176221.4 176573.6 -211430.5 176470.2 176472.8 -218395.1 0 +175928.1 -217630.9 176071.9 175761.5 -217795 175473.7 -210396.6 175785 175824.9 175368.2 176045 -222788 -216897.9 176718.8 175384.9 -219225.4 94720.86 -220142.6 176221 176574.2 -211441.1 176470.7 176473.1 -218395.8 0 +175928.3 -217624.3 176071.9 175760.6 -217786.2 175473.3 -210410.6 175785.5 175823.5 175368.2 176044.7 -222787.7 -216903.8 176719.1 175384.8 -219205.2 94518.72 -220141.6 176220.3 176574.2 -211470.2 176469.2 176473.8 -218393.1 0 +175927.3 -217626.5 176071.5 175761.6 -217777.5 175472.1 -210427.5 175785.2 175822.7 175366.1 176044.8 -222786.1 -216903.4 176719.2 175384.8 -219173.6 94316.63 -220132.6 176219.6 176573.5 -211504.4 176467.5 176474.4 -218389.1 0 +175925 -217631.4 176072.1 175763.3 -217776.9 175472.7 -210425.6 175785.6 175822.7 175364.9 176045.9 -222782.5 -216897.7 176719.5 175385.3 -219139.9 94083.08 -220119 176219 176574 -211531.7 176468.9 176475.4 -218385.3 0 +175925.5 -217633.4 176072.9 175763.8 -217781.5 175474.8 -210403.3 175787 175822.7 175366 176047.3 -222779.1 -216887.3 176719.9 175385.4 -219110.5 93827.17 -220117.8 176218.4 176574.9 -211537.6 176471.5 176475.8 -218384.4 0 +175929 -217635.5 176072.6 175763.5 -217782.8 175475 -210397.4 175787.8 175822.7 175367.8 176047.8 -222779.8 -216878.5 176720 175384.7 -219098.4 93616 -220129.6 176218.4 176574.9 -211511.5 176472.1 176475.2 -218387.1 0 +175930.5 -217638.6 176071.8 175762.9 -217782.6 175473.8 -210426 175788 175822.9 175368.1 176047.1 -222783 -216876.6 176719.8 175384.1 -219097.9 93443.48 -220135.6 176219.8 176575.5 -211460.2 176471.8 176474.8 -218389.3 0 +175928.6 -217641.9 176070.7 175761.8 -217782.3 175473.7 -210471.1 175785.8 175823.5 175366.8 176045.8 -222786.7 -216878.9 176719.5 175384.6 -219096.4 93239.13 -220127.9 176221 176575.5 -211402.6 176470.2 176473.6 -218390.2 0 +175926.4 -217646.5 176069.1 175760.7 -217777.3 175474 -210512.4 175781.8 175824 175365.8 176044.4 -222789.9 -216881 176718.8 175385.1 -219097.9 92996.24 -220116.2 176220.3 176572.9 -211345.8 176467.7 176471 -218391.3 0 +175926.5 -217650.5 176070 175760.6 -217770.4 175473.3 -210542.5 175782.3 175824.1 175366.2 176044.4 -222788 -216880.3 176718.7 175385.4 -219104 92751.96 -220110.3 176219.8 176572 -211281 176468.8 176471.2 -218388.4 0 +175927.5 -217651.6 176072.9 175761.5 -217769.1 175472.9 -210562.6 175786.5 175824.5 175366.8 176046.1 -222783 -216877.7 176720.1 175386.3 -219105 92503.37 -220108.5 176220.8 176574.5 -211211.9 176472.6 176474.6 -218380.6 0 +175926.3 -217650.9 176073 175761.6 -217771.5 175473 -210575.9 175787.1 175824.5 175366.6 176047 -222782.7 -216875.1 176720.6 175386.4 -219099.6 92229.88 -220105.4 176220.4 176574.7 -211157.6 176472.3 176475.2 -218376.3 0 +175923.6 -217647.8 176070.4 175760.1 -217771.7 175473.5 -210581 175785.3 175823.1 175366.2 176045.9 -222784.1 -216871.5 176719.4 175385 -219096.6 91936.25 -220103.4 176218.2 176571.9 -211123.3 176469.2 176472.9 -218377.5 0 +175923.5 -217644.1 176069.7 175759.3 -217772.2 175474.8 -210573.6 175785.8 175822.2 175366.2 176045.5 -222781.4 -216869.7 176719.2 175384.5 -219100.4 91642.61 -220110.3 176217.8 176571.5 -211112.4 176469.6 176472.7 -218378.3 0 +175925.5 -217645.9 176070.8 175760.4 -217778.5 175476.2 -210560.6 175787.3 175823 175366.5 176046.4 -222778.6 -216873.4 176720 175385.6 -219119.3 91370.91 -220126.4 176218.7 176573.5 -211126.5 176472.3 176474.8 -218376.5 0 +175926 -217650.7 176071.2 175761.7 -217787.3 175476.4 -210564.7 175787.1 175823.9 175366.6 176047.2 -222779.1 -216880.8 176719.7 175385.6 -219165.5 91136.69 -220143.8 176218.3 176574 -211124.9 176472.1 176475.6 -218375.2 0 +175925.3 -217650.5 176070.5 175761.8 -217791.4 175475.6 -210599.5 175786.3 175824.2 175366.6 176047.4 -222779.4 -216886.1 176718.2 175384.3 -219227.3 90937.71 -220153 176217.5 176573 -211083.3 176469.9 176474.4 -218377.4 0 +175925.9 -217645.2 176071.1 175761 -217791 175474.7 -210650.3 175786.1 175824.6 175366.7 176047.5 -222777.8 -216886 176717.2 175384.4 -219278.1 90760.42 -220148.4 176218.5 176573.1 -211055.5 176469.2 176474.1 -218380.9 0 +175927.2 -217642 176073 175761.2 -217791.2 175474.7 -210696.8 175786.8 175825 175366.8 176047.8 -222777.8 -216884.3 176717.6 175386.1 -219309 90602.65 -220132 176219.8 176574.6 -211077.5 176469.7 176474.6 -218381.6 0 +175927.7 -217643.5 176073.2 175761.8 -217792.5 175474.3 -210731.1 175786.1 175824.7 175367 176047.3 -222780.5 -216883.8 176718 175386.9 -219320.8 90487.97 -220110.3 176219.5 176574.9 -211112.4 176469.6 176473 -218380.9 0 +175927 -217645.2 176071.5 175760.6 -217790.3 175472.4 -210758.4 175784 175823.7 175367.1 176045.4 -222781.4 -216880.7 176717.3 175386 -219312.7 90431.61 -220089.9 176218.5 176573.3 -211139.2 176469 176470.5 -218382 0 +175926.2 -217643.8 176070.8 175759.2 -217785.8 175470.7 -210798 175783.6 175822.5 175366.8 176043.8 -222779.6 -216878 176716.9 175384.6 -219297.6 90378.92 -220078.8 176218.1 176572.3 -211168.8 176468.8 176470.1 -218382.7 0 +175926.1 -217644.3 176071.5 175759.7 -217786.9 175470.8 -210856.1 175784.7 175822.5 175366 176043.6 -222779.2 -216880.7 176718.2 175384.2 -219295 90241.57 -220076.8 176217.7 176572.4 -211184.6 176468.5 176471.1 -218381.2 0 +175925.9 -217653.3 176071.8 175760.2 -217792.5 175471.2 -210901.8 175784.1 175824.1 175365 176043.6 -222780.3 -216882.5 176719.6 175384.4 -219308.6 90002 -220070.3 176216.4 176572.3 -211172.2 176468.2 176472.3 -218379.3 0 +175925.7 -217665.9 176071.3 175760.4 -217792 175471.4 -210907.6 175782.4 175825.2 175364.6 176043.4 -222781.4 -216880.1 176719.9 175384.5 -219327.4 89711.95 -220058.6 176216.4 176572.8 -211151.5 176468.4 176474.4 -218380.2 0 +175927 -217669.6 176070.6 175761.3 -217787.2 175472.2 -210886.6 175782.4 175824.9 175365.4 176044.5 -222781.6 -216878.6 176719.7 175384.5 -219338.8 89423.65 -220062.2 176218.9 176573.5 -211132.7 176469.2 176475.9 -218384.2 0 +175928.2 -217661.4 176070.1 175760.9 -217786.9 175473.2 -210872.9 175784 175824.3 175366.4 176045.6 -222779.4 -216877.6 176719.5 175384.3 -219344 89174.75 -220080.4 176220.5 176572.8 -211106.2 176469.6 176474.2 -218385.8 0 +175926.9 -217651 176070.2 175759 -217784.5 175473.4 -210887.3 175785.3 175824.1 175366 176045.1 -222778.1 -216875.2 176719.3 175383.5 -219359.7 88973.08 -220088.9 176219 176572.1 -211073.1 176469.5 176471.8 -218382.3 0 +175924.3 -217647.8 176070.8 175758.5 -217772.5 175472.6 -210917.6 175785.4 175823.5 175364.8 176044.3 -222781.8 -216873.7 176719.1 175383.4 -219396.8 88784.82 -220089.2 176217.2 176572.8 -211036 176469.9 176471.8 -218378.5 0 +175923.5 -217653.5 176070.9 175760.1 -217761 175472.3 -210940.4 175784.7 175822.3 175365.1 176044.6 -222784.9 -216873.8 176719.1 175384.8 -219440.2 88586.15 -220100.4 176217.2 176573.9 -210990.3 176470.1 176472.5 -218376.9 0 +175924.9 -217660.4 176070.3 175761.6 -217761.1 175472.7 -210957 175783.7 175822.2 175366.3 176044.5 -222782.5 -216876.8 176718.9 175386.2 -219463.8 88397.79 -220114.4 176217.5 176574.3 -210943.7 176469.2 176472.5 -218375.3 0 +175926.6 -217659.1 176069.5 175761.9 -217772.6 175472.3 -210970.5 175782.8 175822.2 175366.4 176043.2 -222778.9 -216885.3 176718 175386 -219465.8 88249.6 -220110.5 176217.3 176573.4 -210908.3 176468.2 176472.1 -218376.1 0 +175926.8 -217651.5 176069.2 175761.1 -217786.7 175471.8 -210969.6 175783 175821.1 175365.1 176042.7 -222778.3 -216896 176716.8 175384.5 -219469 88162.63 -220089.7 176217.7 176572.5 -210877.1 176468.3 176471.5 -218379.7 0 +175925.9 -217645.9 176070 175760.2 -217794.4 175472.7 -210968.3 175784.6 175821 175364.5 176044.5 -222779.8 -216900 176716.9 175383.8 -219491.9 88142.2 -220068.3 176218.6 176572.8 -210842.9 176469.5 176471.9 -218383.3 0 +175925.5 -217644.3 176071.3 175760.2 -217796.2 175473.3 -210990.5 175785.8 175822.6 175365.1 176046.4 -222782.8 -216894.6 176718.4 175384.9 -219533.4 88133.38 -220063.4 176218.8 176572.7 -210823.5 176469.8 176473.5 -218387.5 0 +175925.2 -217645 176071.2 175760.3 -217796.3 175472.2 -211022.9 175784.4 175823 175365.7 176045.9 -222786.6 -216888.4 176719.2 175385.6 -219564.2 88066.2 -220078.2 176218.4 176570.8 -210828.6 176468.2 176473.6 -218390.5 0 +175924.6 -217646.4 176070 175759.5 -217794.2 175471.5 -211060.9 175782.4 175821.5 175364.6 176044.2 -222788.3 -216887.7 176718 175384.8 -219551.8 87964.11 -220093.8 176218.9 176570.7 -210836.8 176467.4 176471.7 -218387 0 +175924.7 -217646.7 176068.9 175759.4 -217789.7 175472.4 -211120.1 175782.7 175820.8 175362.9 176043.8 -222787.3 -216889.8 176717.1 175383.9 -219509 87886.54 -220089.9 176220.1 176573.1 -210834.4 176468.7 176470.7 -218380.7 0 +175926.2 -217646.2 176069.1 175761.1 -217784.3 175473.5 -211173.1 175784.8 175822.2 175363.5 176045.3 -222786.5 -216891.8 176718.4 175383.9 -219467.1 87815.59 -220069.3 176220.7 176574.6 -210833.7 176470.5 176471.6 -218379.6 0 +175928 -217646.2 176071.2 175762.2 -217778.1 175473.8 -211183 175786.6 175824.4 175365.8 176046.6 -222784.9 -216894 176719.6 175385.1 -219420.7 87716.88 -220051.1 176220.4 176574.1 -210839.2 176471.4 176473 -218384.4 0 +175928.2 -217645.3 176073.1 175761.3 -217773.3 175473 -211169.9 175786.5 175825 175366.2 176046.1 -222781.8 -216897.8 176718.7 175386.4 -219370.6 87611.78 -220046.8 176219.3 176573 -210837.1 176470.4 176473.6 -218392.1 0 +175926.3 -217642.2 176072.5 175759.8 -217775.1 175471.9 -211169.4 175785.6 175822.9 175365 176045.3 -222779.6 -216902.2 176717.6 175385.6 -219350.6 87525.33 -220050.7 176217.7 176572.7 -210831.9 176468.4 176473.9 -218396.2 100 +175924.9 -217640.1 176071.3 175759.1 -217781.3 175472.5 -211182 175787.1 175821 175365.8 176046 -222779.5 -216904.2 176718.8 175383.8 -219364 87451.48 -220055.8 176217.6 176573.5 -210855.9 176468.6 176475.1 -218391.6 0 +175925.1 -217645 176071.3 175759.4 -217785 175473.8 -211202.7 175789.2 175821.8 175367.5 176047.3 -222783.2 -216904.6 176720.1 175384.1 -219383.1 87375.12 -220065.8 176218.6 176574.2 -210923.6 176470.2 176475.1 -218383.3 0 +175925.1 -217657.3 176070.9 175760.3 -217785.8 175473.7 -211250.9 175787.9 175822.8 175367.6 176047.1 -222789.5 -216904.2 176719.5 175384.7 -219398 87294.42 -220079.2 176218.5 176573.5 -211000.8 176469.5 176473.2 -218379.4 0 +175925.6 -217668.8 176070.4 175761.2 -217787.8 175472.8 -211347 175785.4 175822.3 175367.4 176046.4 -222791.6 -216902.5 176719 175383.7 -219404.8 87218.44 -220082.8 176218 176573.4 -211047.2 176468.5 176472.5 -218381.3 0 +175926.8 -217672.3 176071 175761.4 -217791.2 175472.9 -211472.5 175784.5 175822.5 175367.6 176046.2 -222786.7 -216902.3 176719.1 175382.7 -219393.2 87140.19 -220071.6 176218.1 176573.9 -211066.5 176469 176472.3 -218387.6 0 +175926.4 -217669.4 176071.5 175761.1 -217790.2 175473.4 -211590 175784.2 175824.3 175366.9 176045.6 -222782.3 -216904.9 176718.1 175382.8 -219367.1 87038.67 -220060.3 176217.5 176572.8 -211084.5 176468.7 176471.3 -218393.1 0 +175924.9 -217664.2 176070.8 175760.6 -217781.8 175473.3 -211691.8 175784.3 175824.8 175365.9 176044.7 -222783.5 -216905.4 176716.8 175383 -219342.1 86908.66 -220059.1 176216.8 176571.3 -211103.3 176467.8 176472.5 -218390.9 0 +175924.5 -217659.4 176070.7 175760.1 -217775.7 175472.5 -211779.6 175784.4 175823.3 175365.9 176044.9 -222786.2 -216902.3 176716.5 175383.3 -219327.6 86759.45 -220056 176217.7 176572.1 -211118.9 176469 176475 -218383.3 0 +175924.7 -217658.5 176071.4 175759.7 -217778.4 175471.9 -211839.2 175783.6 175821.5 175365.2 176045.7 -222786.1 -216898.5 176716.9 175383.5 -219318.7 86605.09 -220051.5 176218.8 176573.6 -211143.3 176470.6 176474.2 -218377.8 0 +175924.9 -217661.9 176069.7 175758.4 -217779 175471.7 -211871.4 175782.3 175820.2 175363.5 176044.3 -222786.1 -216897.4 176717.2 175382.7 -219309.6 86454.26 -220066.6 176217.8 176572.5 -211179 176469.7 176470.8 -218376.8 0 +175926 -217664.4 176065.9 175756.2 -217771.2 175471.1 -211898.7 175780.8 175819.6 175362.5 176042.1 -222787.6 -216898.9 176716.5 175381.9 -219308.2 86291.5 -220093 176216.1 176569.4 -211202.6 176467.2 176468.5 -218378.5 0 +175926.5 -217658.7 176065.1 175756.1 -217763.4 175470.4 -211926.5 175781 175820.5 175363.2 176042.7 -222785.4 -216898.9 176716.3 175382.5 -219312 86104.34 -220100.1 176216.2 176568.8 -211177.2 176466.8 176469.4 -218378.8 0 +175925.1 -217645.1 176068.2 175758.3 -217760.5 175470.5 -211939.7 175783.3 175822.2 175364.1 176044 -222779.5 -216896.7 176717.6 175383.5 -219296.4 85917.19 -220088.1 176218.3 176571.6 -211083.2 176468.6 176471.3 -218376.7 0 +175924.4 -217635.5 176070 175759 -217761.5 175470.3 -211943.7 175784.2 175822.6 175364.6 176042.9 -222776.7 -216898.4 176717.6 175383 -219255.4 85766.71 -220079.4 176219.9 176572.4 -210968.5 176468.9 176471.4 -218376.3 0 +175925.9 -217634.9 176069.8 175758 -217764.3 175469.6 -211966.2 175783.6 175821.5 175364.9 176042.1 -222778.8 -216903.6 176715.7 175382 -219221.5 85668.27 -220086.8 176219.7 176570.1 -210922.8 176468.2 176471 -218379.9 0 +175926 -217636.9 176070.3 175758.8 -217764.6 175470.4 -212005.6 175784.8 175820.8 175365.1 176044 -222780.9 -216904.7 176715.9 175382 -219218.4 85600.95 -220107.3 176218.6 176570.4 -210959.9 176469.4 176472.1 -218385.1 0 +175924.5 -217640.6 176070 175760.6 -217761.8 175471.8 -212022.5 175785.1 175821.1 175364.2 176045.4 -222782.6 -216900.6 176717.8 175382.9 -219224.3 85515.12 -220127.8 176216.8 176572.6 -211002.9 176469.7 176472.4 -218389.3 0 +175924.7 -217646.4 176068.6 175760.2 -217761.3 175471.5 -212005.7 175782.7 175821.5 175362.4 176044.3 -222785 -216896 176718.3 175383.7 -219214.5 85390.69 -220136.8 176215.2 176572.6 -210993.8 176467.1 176471.1 -218387.6 0 +175924.5 -217647.2 176068.7 175758.5 -217762.9 175470.7 -212005.7 175782.1 175822.1 175362.7 176043.2 -222784.9 -216892.8 176717.5 175383.9 -219201.5 85261.66 -220136.6 176215.9 176571.3 -210948 176466.9 176471.3 -218379.3 0 +175921.8 -217642.3 176069.4 175758.4 -217760.9 175471.1 -212076.8 175783.8 175823.2 175365.3 176043.9 -222784.6 -216891.6 176717.2 175383.2 -219197.5 85132.1 -220136.7 176217.4 176570.2 -210915.8 176470 176473 -218375.6 0 +175921.2 -217637.8 176068.4 175759.3 -217755.9 175471 -212206.6 175783.6 175823.6 175366.2 176045.5 -222788.4 -216891.5 176717.3 175382.2 -219191.7 84949.3 -220140.1 176217.5 176570 -210921 176471 176473.1 -218383.5 0 +175924.7 -217637.3 176067 175759.4 -217754.7 175469.8 -212334.3 175782 175822.3 175364.5 176046.5 -222789.7 -216889.6 176717.3 175382 -219185.7 84718.94 -220139.6 176217.1 176571.1 -210938.9 176469.6 176470.9 -218391.9 0 +175926.4 -217641 176067.1 175758.8 -217756.5 175470.2 -212429.8 175782 175820.7 175363.6 176046 -222784.4 -216884.7 176717.4 175383.3 -219198.2 84515.11 -220130.8 176217.8 176572 -210944.8 176469.3 176470 -218389.9 0 +175924.6 -217647 176069.2 175758.7 -217754.2 175472.3 -212511.5 175783.8 175821.3 175364.8 176045.1 -222779.9 -216880.3 176717.6 175384.8 -219233.7 84345.16 -220119.1 176219.1 176571.7 -210944.2 176469 176471.7 -218384.3 100 +175923.6 -217652.2 176071 175758.9 -217747 175472.6 -212590.9 175784.5 175822.7 175365.6 176044.7 -222781.8 -216881.9 176717.4 175384.3 -219268.5 84156.82 -220115.1 176219.1 176571 -210943.8 176467.5 176471.8 -218385.6 0 +175925 -217654.8 176069.9 175758.8 -217743.5 175470.4 -212653.5 175782.2 175821.7 175364 176043.5 -222786.3 -216887.4 176716.1 175382.1 -219275.3 83956.45 -220123.5 176217.2 176570.1 -210940.3 176466.4 176469.2 -218390.9 0 +175925.9 -217652.9 176067.7 175758.3 -217750.5 175468.5 -212686.4 175780.3 175820.2 175362 176042 -222787 -216890.3 176715.2 175381 -219260.1 83788.66 -220133.6 176215.8 176569.7 -210934.7 176467.1 176468.8 -218390.3 0 +175924.9 -217646.8 176068.1 175758.7 -217764.7 175470.1 -212693.8 175782.3 175821.1 175362.8 176042.1 -222784.1 -216893 176716.6 175382.1 -219245.8 83662.28 -220134.1 176217.1 176570.5 -210923.8 176468.4 176471.5 -218385.7 0 +175923.6 -217642.4 176070.2 175760 -217775.4 175472.8 -212691 175785 175823 175365.5 176043.6 -222783.2 -216899 176718.9 175383.3 -219233.5 83554.9 -220133.3 176218.9 176571.4 -210891.2 176468.8 176472.1 -218385.6 0 +175924.1 -217642.2 176070.8 175761 -217774.7 175473.1 -212693.8 175784.7 175823.2 175366.8 176044.2 -222784 -216901.3 176719.3 175383.5 -219217.8 83431.59 -220134.8 176218.9 176571.5 -210838.8 176468.3 176470.4 -218390 0 +175925.7 -217642.1 176069.8 175760.8 -217766.8 175472.6 -212718.4 175783.5 175822.9 175365.9 176044 -222782.6 -216896 176718.2 175383.5 -219207.6 83270.18 -220127.9 176218.3 176571.3 -210804.3 176468.2 176470.2 -218390.9 0 +175926.3 -217639 176069.8 175758.9 -217761.1 175473.3 -212775.7 175784.2 175823 175363.7 176044.7 -222778.9 -216890.9 176717.2 175383.7 -219208.6 83090.46 -220120.3 176218.4 176571.8 -210808.9 176469.8 176472.1 -218384.7 0 +175925 -217635.7 176070.6 175757.6 -217760 175473.4 -212846.3 175785.1 175822.1 175362.4 176045.2 -222774.9 -216888.7 176717.1 175383.9 -219223.9 82942.31 -220128.3 176218.3 176573.1 -210825.5 176471.2 176474.3 -218377.7 0 +175923.3 -217637.4 176070.2 175758.8 -217760.7 175472.7 -212891.4 175784 175820.9 175363.4 176043.9 -222772.8 -216880.5 176717.6 175383.8 -219260.6 82864.95 -220137.9 176217.3 176573.2 -210826.6 176470 176474.4 -218376.7 0 +175923.5 -217646.3 176068.9 175760.4 -217763.1 175472.8 -212912.4 175782.2 175821.8 175364.7 176042.8 -222774.1 -216868.3 176718.2 175383.5 -219305.2 82841.38 -220132.6 176216.3 176572.2 -210817.1 176468.4 176472.7 -218380.2 0 +175926.2 -217660.3 176067.6 175760.2 -217767.6 175472.5 -212954.5 175781.8 175822.7 175365 176043.6 -222778.9 -216867.8 176718.5 175383.1 -219326.2 82829.51 -220122.7 176215.5 176571.9 -210809.8 176468.8 176471.6 -218383.4 0 +175928.9 -217672.6 176067.3 175759.5 -217771.3 175471.1 -213035.8 175782 175820.9 175365.7 176044.5 -222783.1 -216879.3 176718.5 175382.4 -219314 82844.29 -220119 176216 176571.7 -210813.9 176469 176472 -218383.3 0 +175928 -217676.8 176068.7 175759.6 -217772.2 175470.1 -213124.4 175782.3 175819.3 175366.7 176045 -222782.8 -216885.4 176718.2 175381.5 -219285.7 82907.99 -220116.7 176217.8 176570.3 -210836 176467.4 176472.5 -218381.1 0 +175925 -217673.9 176070.4 175759.6 -217771.6 175470.6 -213189.4 175782.2 175820.2 175365.9 176045.2 -222780 -216878.6 176717.5 175381.5 -219265.2 82971.16 -220112.2 176217.9 176569.5 -210862.6 176466 176471.8 -218381 0 +175924.1 -217669.1 176070.5 175759.9 -217772.2 175471.2 -213229 175782.3 175822.3 175364.3 176044.3 -222777.6 -216869.2 176717.2 175382.4 -219270.5 82988.4 -220110.7 176216.8 176571.2 -210857.3 176466.5 176470.3 -218382.8 0 +175924.2 -217666.2 176069.1 175760.6 -217772.3 175471.2 -213249.1 175783.4 175823.5 175364.1 176043.7 -222776.8 -216868.4 176717.8 175383.3 -219295.4 82974.43 -220118.4 176216.9 176572.8 -210797.4 176468.2 176470 -218382.8 0 +175923.7 -217665.6 176067.9 175760.3 -217768.1 175471.2 -213259.6 175783.9 175822.3 175364.7 176044.4 -222778.9 -216873.7 176717.9 175383.2 -219315.4 82942.8 -220129.9 176217 176571.6 -210707.7 176469.3 176471.3 -218383.5 0 +175923.6 -217665.7 176068.3 175759.3 -217762.3 175472.1 -213272.5 175782.8 175820.2 175364.3 176044.4 -222781.9 -216875.7 176717.5 175382.2 -219322.3 82871.44 -220131 176215.7 176570.4 -210645.4 176469.7 176472.4 -218385.1 0 +175923.2 -217665.4 176069.2 175759.5 -217763.6 175472.9 -213277.8 175781.7 175820.1 175363.6 176043.3 -222781.3 -216878.3 176717.8 175381.4 -219329.7 82743.8 -220123.5 176215.2 176571.9 -210645.9 176469.6 176471.8 -218382.5 0 +175922.5 -217666 176068.8 175760.3 -217770 175471.4 -213250.7 175781.7 175821 175363.6 176042.6 -222777.5 -216887.1 176717.9 175381.2 -219349.9 82576.74 -220121.8 176215.8 176573.4 -210690.3 176468.6 176470.3 -218376.5 0 +175923.5 -217668.3 176068.3 175759.5 -217770.1 175469.2 -213198 175783 175820.5 175363.7 176043.4 -222774.5 -216891.2 176717.3 175381.7 -219383.6 82393.09 -220125.2 176216.1 176573.2 -210745.2 176467.6 176469.7 -218372.5 0 +175925.1 -217670 176069.2 175758.6 -217765.8 175469.7 -213164.1 175784.4 175820.4 175363.3 176044.8 -222774.4 -216885.3 176716.7 175382.6 -219419.7 82211.74 -220127.6 176215.9 176572.7 -210804.5 176467.5 176470.4 -218372.2 0 +175925.3 -217667.1 176070.6 175759 -217768.6 175471.8 -213171.5 175784.2 175822 175362.8 176044.8 -222775.3 -216881.8 176716.4 175382.5 -219441.3 82063.97 -220129.9 176216.3 176572.8 -210869.8 176467.8 176471.5 -218375.2 0 +175924.8 -217656.6 176070.3 175759.2 -217777.2 175472 -213187.9 175781.6 175822.8 175363.4 176043.9 -222776.7 -216887.9 176716 175381.4 -219443.2 81964.64 -220130.5 176217.2 176572.8 -210928.5 176467.2 176472.2 -218380.5 0 +175922.9 -217642.6 176068.8 175758.1 -217781.8 175470.9 -213174 175779.3 175821.8 175364.4 176044.6 -222777.2 -216895.2 176716 175381.2 -219437 81881.98 -220131.7 176217.5 176572.3 -210972.6 176467.5 176472.1 -218385.6 0 +175921.4 -217632.4 176068.1 175757.2 -217779.8 175471 -213136.7 175780.4 175820.6 175364.7 176045.9 -222774.6 -216895.8 176716 175381.4 -219432.5 81766.55 -220137.7 176217.3 176571.6 -211015.5 176469.1 176471 -218389.4 0 +175922.9 -217628.1 176068.6 175758 -217775.6 175471.1 -213106.4 175783.4 175820 175364.2 176044.3 -222772.1 -216892.7 176715.4 175381.4 -219431.9 81600.86 -220142.4 176217.4 176570.9 -211071 176468.6 176469.9 -218391.6 0 +175924.9 -217628.3 176069.5 175759.2 -217772.7 175470.3 -213087.4 175784.4 175820.1 175363.8 176041.3 -222774.2 -216888.4 176715 175382 -219443.9 81425.63 -220139.5 176217.5 176570.4 -211128.6 176467.1 176470.1 -218388.9 0 +175924.3 -217632 176071 175759.6 -217772.9 175470.5 -213072.4 175784.3 175821 175364.1 176041.6 -222776 -216882.3 176716.1 175382.8 -219467.2 81291.93 -220132 176217.2 176571.4 -211164.8 176468.3 176471.7 -218380.7 0 +175923 -217636.7 176071.8 175759.2 -217774.4 175471.2 -213056.1 175784.5 175821.6 175364.7 176044.2 -222775 -216877.7 176716.9 175382.7 -219479.1 81193.45 -220127.8 176216.6 176572.3 -211177.5 176469.8 176472.4 -218374.4 0 +175923.3 -217639.7 176069.7 175758.4 -217772.1 175471 -213013.9 175783.2 175820.8 175364.9 176044.5 -222775.1 -216878.8 176716.1 175382.1 -219472.8 81092.32 -220131.3 176216 176570.8 -211189.1 176467.8 176470.8 -218375.5 0 +175924.5 -217643 176067.8 175757.8 -217766.7 175471.3 -212944.7 175781.6 175819.8 175365.3 176042.6 -222775.5 -216884.8 176716 175382.4 -219472.3 80968.45 -220134.3 176216.1 176569.7 -211211.1 176465.8 176469.6 -218380.3 0 +175925.2 -217648.2 176068.3 175758 -217765.1 175472.6 -212893.9 175782.3 175819.9 175365.5 176042.1 -222773.4 -216894 176717.4 175383.4 -219484.6 80824.27 -220126.5 176217.1 176571.8 -211230.9 176466.7 176470.4 -218384.8 0 +175925.5 -217650.6 176068.8 175758.8 -217768.2 175472.2 -212873.7 175783.9 175820.6 175364.4 176043.3 -222771.9 -216900.3 176718 175383.4 -219487.9 80685.07 -220117 176217.7 176572.9 -211240.5 176467.9 176471 -218388.5 0 +175926.3 -217646.3 176067.6 175759.1 -217771.3 175470.7 -212849.7 175783.1 175820.6 175363 176044.3 -222773.1 -216895.1 176716 175382.5 -219480.4 80561.98 -220119.6 176216.6 176570.6 -211243.1 176467.1 176469.9 -218389.2 0 +175926.7 -217640 176066.8 175759.5 -217774.4 175470.6 -212809.8 175781.4 175820.5 175363.1 176045.1 -222773.6 -216881.8 176714.2 175382.8 -219484.2 80431 -220129.5 176214.8 176569.2 -211240.1 176466.6 176469.1 -218386 0 +175925.2 -217638.8 176068.2 175759.8 -217779.7 175471.3 -212766.7 175781.9 175820.7 175364.1 176045.6 -222773.2 -216871.6 176715.4 175383.8 -219503.7 80288.99 -220133 176214.4 176570.4 -211246.3 176467.4 176469.7 -218382.4 0 +175923.9 -217641.6 176070.8 175759.1 -217783.4 175471.7 -212726.3 175784.5 175821.5 175364.8 176044.9 -222773.8 -216869.6 176717.9 175383.8 -219527.7 80146.13 -220129.5 176216.4 176572.1 -211279.3 176468.7 176471 -218380.5 0 +175923.8 -217643 176072.4 175758 -217781.1 175472.4 -212685.4 175786.1 175822.1 175365.4 176043.7 -222774.1 -216874.9 176718.4 175382.9 -219558 79974.23 -220130.3 176219.1 176572.7 -211326 176470.1 176471.9 -218380.1 0 +175923.7 -217641.2 176071.5 175757.8 -217774.8 175472.7 -212634.6 175784.8 175822.1 175365.5 176043.8 -222772.9 -216883 176716.8 175382.3 -219596.4 79761.38 -220139.5 176219.5 176571.6 -211364.6 176470.3 176471 -218382.3 0 +175924.4 -217638 176069.3 175758 -217769.6 175472.1 -212571.6 175783.3 175821.5 175364.2 176044 -222771.6 -216887.8 176715.1 175382.4 -219631.3 79547.5 -220146.2 176217 176569.9 -211403 176468.4 176469.4 -218385 0 +175926 -217637.2 176067.4 175757.8 -217767 175470.8 -212516.5 175783.3 175820.9 175362.5 176042.9 -222772.6 -216890.1 176714.5 175382.7 -219661.7 79354.85 -220143.3 176214.3 176570.1 -211459.6 176466.3 176469.1 -218382.8 0 +175925.3 -217639.2 176066.7 175757.5 -217765.7 175469.8 -212493.7 175782.8 175820.1 175362.3 176042.1 -222775.5 -216892.2 176715 175382.2 -219691 79157.4 -220134.9 176213.6 176571.6 -211528.6 176465.7 176470.1 -218376.5 0 +175922.7 -217638.5 176067.2 175757.3 -217765.3 175469.4 -212491.5 175781.6 175818.9 175363.4 176042.1 -222777.2 -216892.1 176716.1 175381.2 -219702.7 78949.36 -220127.8 176214.8 176572 -211585 176466.7 176470.8 -218373.5 0 +175921.6 -217635.8 176067.2 175757 -217767.7 175468.4 -212476.6 175780.4 175818 175363.4 176041.1 -222776.6 -216891.3 176716.7 175381.1 -219682.4 78778.51 -220126.3 176216.2 176570 -211610.9 176466.8 176469.9 -218378.3 0 +175922.8 -217634.4 176066.8 175756.9 -217771.5 175467.2 -212445.5 175779.8 175817.9 175362.1 176040.3 -222775.2 -216889 176716.7 175381.6 -219645.4 78661.9 -220122.2 176216 176567.8 -211606.1 176465.3 176468.2 -218387.9 0 +175924.3 -217630 176067.7 175757.1 -217773.7 175468.2 -212416.7 175780.7 175818.5 175361.7 176041.7 -222773.9 -216879.8 176716.8 175381.5 -219617.3 78552.48 -220101.5 176215.7 176568.4 -211592.5 176464.7 176468.8 -218391.7 0 diff --git a/mne-python/source/mne/io/edf/tests/data/test_eeglab.mat b/mne-python/source/mne/io/edf/tests/data/test_eeglab.mat new file mode 100644 index 0000000000000000000000000000000000000000..8f45cb031cc1a9133506b61b314e9e2c4fd02d1a --- /dev/null +++ b/mne-python/source/mne/io/edf/tests/data/test_eeglab.mat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f9d2051ce2dca29275f81efa72e207dcc7ccc4ef2367ea7127bb22011751fc07 +size 447053 diff --git a/mne-python/source/mne/io/edf/tests/data/test_uneven_samp.edf b/mne-python/source/mne/io/edf/tests/data/test_uneven_samp.edf new file mode 100644 index 0000000000000000000000000000000000000000..b0261c0d29c1302f85c1dee54b178bafcdce0257 Binary files /dev/null and b/mne-python/source/mne/io/edf/tests/data/test_uneven_samp.edf differ diff --git a/mne-python/source/mne/io/edf/tests/data/test_uneven_samp.mat b/mne-python/source/mne/io/edf/tests/data/test_uneven_samp.mat new file mode 100644 index 0000000000000000000000000000000000000000..62ed2e87d53094b615503ac217bc193b6b1bca15 Binary files /dev/null and b/mne-python/source/mne/io/edf/tests/data/test_uneven_samp.mat differ diff --git a/mne-python/source/mne/io/edf/tests/test_edf.py b/mne-python/source/mne/io/edf/tests/test_edf.py new file mode 100644 index 0000000000000000000000000000000000000000..1760081bac4e15df870a5ec733cfb30a70e8ec75 --- /dev/null +++ b/mne-python/source/mne/io/edf/tests/test_edf.py @@ -0,0 +1,1263 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime +from contextlib import nullcontext +from functools import partial +from io import BytesIO +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_equal, +) +from scipy.io import loadmat + +from mne import Annotations, pick_types +from mne._fiff.pick import channel_indices_by_type, get_channel_type_constants +from mne.annotations import _ndarray_ch_names, events_from_annotations, read_annotations +from mne.datasets import testing +from mne.io import edf, read_raw_bdf, read_raw_edf, read_raw_fif, read_raw_gdf +from mne.io.edf.edf import ( + _edf_str, + _parse_prefilter_string, + _prefilter_float, + _read_annotations_edf, + _read_ch, + _read_edf_header, + _read_header, + _set_prefilter, +) +from mne.io.tests.test_raw import _test_raw_reader +from mne.tests.test_annotations import _assert_annotations_equal +from mne.utils import _record_warnings + +td_mark = testing._pytest_mark() + +data_dir = Path(__file__).parent / "data" +montage_path = data_dir / "biosemi.hpts" # XXX: missing reader +bdf_path = data_dir / "test.bdf" +edf_path = data_dir / "test.edf" +duplicate_channel_labels_path = data_dir / "duplicate_channel_labels.edf" +edf_uneven_path = data_dir / "test_uneven_samp.edf" +bdf_eeglab_path = data_dir / "test_bdf_eeglab.mat" +edf_stim_channel_path = data_dir / "test_edf_stim_channel.edf" +edf_txt_stim_channel_path = data_dir / "test_edf_stim_channel.txt" + +data_path = testing.data_path(download=False) +edf_stim_resamp_path = data_path / "EDF" / "test_edf_stim_resamp.edf" +edf_overlap_annot_path = data_path / "EDF" / "test_edf_overlapping_annotations.edf" +edf_reduced = data_path / "EDF" / "test_reduced.edf" +edf_annot_only = data_path / "EDF" / "SC4001EC-Hypnogram.edf" +bdf_stim_channel_path = data_path / "BDF" / "test_bdf_stim_channel.bdf" +bdf_multiple_annotations_path = data_path / "BDF" / "multiple_annotation_chans.bdf" +test_generator_bdf = data_path / "BDF" / "test_generator_2.bdf" +test_generator_edf = data_path / "EDF" / "test_generator_2.edf" +edf_annot_sub_s_path = data_path / "EDF" / "subsecond_starttime.edf" +edf_chtypes_path = data_path / "EDF" / "chtypes_edf.edf" +edf_utf8_annotations = data_path / "EDF" / "test_utf8_annotations.edf" + +eog = ["REOG", "LEOG", "IEOG"] +misc = ["EXG1", "EXG5", "EXG8", "M1", "M2"] + + +def test_orig_units(): + """Test exposure of original channel units.""" + raw = read_raw_edf(edf_path, preload=True) + + # Test original units + orig_units = raw._orig_units + assert len(orig_units) == len(raw.ch_names) + assert orig_units["A1"] == "µV" # formerly 'uV' edit by _check_orig_units + del orig_units + + raw.rename_channels(dict(A1="AA")) + assert raw._orig_units["AA"] == "µV" + raw.rename_channels(dict(AA="A1")) + + raw_back = raw.copy().pick(raw.ch_names[:1]) # _pick_drop_channels + assert raw_back.ch_names == ["A1"] + assert set(raw_back._orig_units) == {"A1"} + raw_back.add_channels([raw.copy().pick(raw.ch_names[1:])]) + assert raw_back.ch_names == raw.ch_names + assert set(raw_back._orig_units) == set(raw.ch_names) + raw_back.reorder_channels(raw.ch_names[::-1]) + assert set(raw_back._orig_units) == set(raw.ch_names) + + +def test_units_params(): + """Test enforcing original channel units.""" + with pytest.raises( + ValueError, match=r"Unit for channel .* is present .* cannot overwrite it" + ): + _ = read_raw_edf(edf_path, units="V", preload=True) + + +def test_edf_temperature(monkeypatch): + """Test that we can parse temperature channel type.""" + raw = read_raw_edf(edf_path) + assert raw.get_channel_types()[0] == "eeg" + + def _first_chan_temp(*args, **kwargs): + out, orig_units = _read_edf_header(*args, **kwargs) + out["ch_types"][0] = "TEMP" + return out, orig_units + + monkeypatch.setattr(edf.edf, "_read_edf_header", _first_chan_temp) + raw = read_raw_edf(edf_path) + assert "temperature" in raw + assert raw.get_channel_types()[0] == "temperature" + + +@testing.requires_testing_data +def test_subject_info(tmp_path): + """Test exposure of original channel units.""" + raw = read_raw_edf(edf_stim_resamp_path, preload=True) + + # check subject_info from `info` + assert raw.info["subject_info"] is not None + want = { + "his_id": "X", + "sex": 1, + "birthday": datetime.date(1967, 10, 9), + "last_name": "X", + } + for key, val in want.items(): + assert raw.info["subject_info"][key] == val, key + + # add information + raw.info["subject_info"]["hand"] = 0 + + # save raw to FIF and load it back + fname = tmp_path / "test_raw.fif" + raw.save(fname) + raw = read_raw_fif(fname) + + # check subject_info from `info` + assert raw.info["subject_info"] is not None + want = { + "his_id": "X", + "sex": 1, + "birthday": datetime.date(1967, 10, 9), + "last_name": "X", + "hand": 0, + } + for key, val in want.items(): + assert raw.info["subject_info"][key] == val + + +def test_bdf_data(): + """Test reading raw bdf files.""" + # XXX BDF data for these is around 0.01 when it should be in the uV range, + # probably some bug + test_scaling = False + raw_py = _test_raw_reader( + read_raw_bdf, + input_fname=bdf_path, + eog=eog, + misc=misc, + exclude=["M2", "IEOG"], + test_scaling=test_scaling, + ) + assert len(raw_py.ch_names) == 71 + raw_py = _test_raw_reader( + read_raw_bdf, + input_fname=bdf_path, + montage="biosemi64", + eog=eog, + misc=misc, + exclude=["M2", "IEOG"], + test_scaling=test_scaling, + ) + assert len(raw_py.ch_names) == 71 + assert "RawBDF" in repr(raw_py) + picks = pick_types(raw_py.info, meg=False, eeg=True, exclude="bads") + data_py, _ = raw_py[picks] + + # this .mat was generated using the EEG Lab Biosemi Reader + raw_eeglab = loadmat(bdf_eeglab_path) + raw_eeglab = raw_eeglab["data"] * 1e-6 # data are stored in microvolts + data_eeglab = raw_eeglab[picks] + # bdf saved as a single, resolution to seven decimal points in matlab + assert_array_almost_equal(data_py, data_eeglab, 8) + + # Manually checking that float coordinates are imported + assert (raw_py.info["chs"][0]["loc"]).any() + assert (raw_py.info["chs"][25]["loc"]).any() + assert (raw_py.info["chs"][63]["loc"]).any() + + +@testing.requires_testing_data +def test_bdf_crop_save_stim_channel(tmp_path): + """Test EDF with various sampling rates.""" + raw = read_raw_bdf(bdf_stim_channel_path) + raw.save(tmp_path / "test-raw.fif", tmin=1.2, tmax=4.0, overwrite=True) + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname", + [ + edf_reduced, + edf_overlap_annot_path, + ], +) +@pytest.mark.parametrize("stim_channel", (None, False, "auto")) +def test_edf_others(fname, stim_channel): + """Test EDF with various sampling rates and overlapping annotations.""" + _test_raw_reader( + read_raw_edf, + input_fname=fname, + stim_channel=stim_channel, + verbose="error", + test_preloading=False, + preload=True, # no preload=False for mixed sfreqs + ) + + +@testing.requires_testing_data +@pytest.mark.parametrize("stim_channel", (None, False, "auto")) +def test_edf_different_sfreqs(stim_channel): + """Test EDF with various sampling rates.""" + rng = np.random.RandomState(0) + # load with and without preloading, should produce the same results + raw1 = read_raw_edf( + input_fname=edf_reduced, + stim_channel=stim_channel, + verbose="error", + preload=False, + ) + raw2 = read_raw_edf( + input_fname=edf_reduced, + stim_channel=stim_channel, + verbose="error", + preload=True, + ) + + picks = rng.permutation(np.arange(len(raw1.ch_names) - 1))[:10] + data1, times1 = raw1[picks, :] + data2, times2 = raw2[picks, :] + assert_allclose(data1, data2, err_msg="Data mismatch with preload") + assert_allclose(times1, times2) + + # loading slices should throw a warning as they have different + # edge artifacts than when loading the entire file at once + with pytest.warns(RuntimeWarning, match="mixed sampling frequencies"): + data1, times1 = raw1[picks, :512] + data2, times2 = raw2[picks, :512] + + # should NOT throw a warning when loading channels that have all the same + # sampling frequency - here, no edge artifacts can appear + picks = np.arange(15, 20) # these channels all have 512 Hz + data1, times1 = raw1[picks, :512] + data2, times2 = raw2[picks, :512] + assert_allclose(data1, data2, err_msg="Data mismatch with preload") + assert_allclose(times1, times2) + + +@testing.requires_testing_data +@pytest.mark.parametrize("stim_channel", (None, False, "auto")) +def test_edf_different_sfreqs_nopreload(stim_channel): + """Test loading smaller sfreq channels without preloading.""" + # load without preloading, then load a channel that has smaller sfreq + # as other channels, produced an error, see mne-python/issues/12897 + + for i in range(1, 13): + raw = read_raw_edf(input_fname=edf_reduced, verbose="error", preload=False) + + # this should work for channels of all sfreq, even if larger sfreqs + # are present in the file + x1 = raw.get_data(picks=[f"A{i}"], return_times=False) + # load next ch, this is sometimes with a higher sometimes a lower sfreq + x2 = raw.get_data([f"A{i + 1}"], return_times=False) + assert x1.shape == x2.shape + + +def test_edf_data_broken(tmp_path): + """Test edf files.""" + raw = _test_raw_reader( + read_raw_edf, + input_fname=edf_path, + exclude=["Ergo-Left", "H10"], + verbose="error", + ) + raw_py = read_raw_edf(edf_path) + data = raw_py.get_data() + assert_equal(len(raw.ch_names) + 2, len(raw_py.ch_names)) + + # Test with number of records not in header (-1). + broken_fname = tmp_path / "broken.edf" + with open(edf_path, "rb") as fid_in: + fid_in.seek(0, 2) + n_bytes = fid_in.tell() + fid_in.seek(0, 0) + rbytes = fid_in.read() + with open(broken_fname, "wb") as fid_out: + fid_out.write(rbytes[:236]) + fid_out.write(b"-1 ") + fid_out.write(rbytes[244 : 244 + int(n_bytes * 0.4)]) + with pytest.warns(RuntimeWarning, match="records .* not match the file size"): + raw = read_raw_edf(broken_fname, preload=True) + read_raw_edf(broken_fname, exclude=raw.ch_names[:132], preload=True) + + # Test with \x00's in the data + with open(broken_fname, "wb") as fid_out: + fid_out.write(rbytes[:184]) + assert rbytes[184:192] == b"36096 " + fid_out.write(rbytes[184:192].replace(b" ", b"\x00")) + fid_out.write(rbytes[192:]) + raw_py = read_raw_edf(broken_fname) + data_new = raw_py.get_data() + assert_allclose(data, data_new) + + +def test_duplicate_channel_labels_edf(): + """Test reading edf file with duplicate channel names.""" + EXPECTED_CHANNEL_NAMES = ["EEG F1-Ref-0", "EEG F2-Ref", "EEG F1-Ref-1"] + with pytest.warns(RuntimeWarning, match="Channel names are not unique"): + raw = read_raw_edf(duplicate_channel_labels_path, preload=False) + + assert raw.ch_names == EXPECTED_CHANNEL_NAMES + + +def test_parse_annotation(tmp_path): + """Test parsing the tal channel.""" + # test the parser + annot = ( + b"+180\x14Lights off\x14Close door\x14\x00\x00\x00\x00\x00" + b"+180\x14Lights off\x14\x00\x00\x00\x00\x00\x00\x00\x00" + b"+180\x14Close door\x14\x00\x00\x00\x00\x00\x00\x00\x00" + b"+3.14\x1504.20\x14nothing\x14\x00\x00\x00\x00" + b"+1800.2\x1525.5\x14Apnea\x14\x00\x00\x00\x00\x00\x00\x00" + b"+123\x14\x14\x00\x00\x00\x00\x00\x00\x00" + ) + annot_file = tmp_path / "annotations.txt" + with open(annot_file, "wb") as f: + f.write(annot) + + annot = [a for a in bytes(annot)] + annot[1::2] = [a * 256 for a in annot[1::2]] + tal_channel_A = np.array( + list(map(sum, zip(annot[0::2], annot[1::2]))), dtype=np.int64 + ) + + with open(annot_file, "rb") as fid: + # ch_data = np.fromfile(fid, dtype='>= 8 # last 8 bits are system events in biosemi files + assert_equal(events.shape[0], 2) # 2 events in file + assert_array_equal(events[:, 2], [20, 28]) + + # gh-5604 + assert raw.info["meas_date"] is None + _test_raw_reader( + read_raw_gdf, + input_fname=gdf2_path.with_name(gdf2_path.name + ".gdf"), + eog=None, + misc=None, + test_scaling=False, # XXX this should be True + ) + + +@testing.requires_testing_data +def test_one_channel_gdf(): + """Test a one-channel GDF file.""" + ecg = read_raw_gdf(gdf_1ch_path, preload=True) + assert ecg["ECG"][0].shape == (1, 4500) + assert 150.0 == ecg.info["sfreq"] + + +@testing.requires_testing_data +def test_gdf_exclude_channels(): + """Test reading GDF data with excluded channels.""" + raw = read_raw_gdf( + gdf1_path.with_name(gdf1_path.name + ".gdf"), exclude=("FP1", "O1") + ) + assert "FP1" not in raw.ch_names + assert "O1" not in raw.ch_names + raw = read_raw_gdf( + gdf2_path.with_name(gdf2_path.name + ".gdf"), exclude=("Fp1", "O1") + ) + assert "Fp1" not in raw.ch_names + assert "O1" not in raw.ch_names + raw = read_raw_gdf(gdf2_path.with_name(gdf2_path.name + ".gdf"), exclude=".+z$") + assert "AFz" not in raw.ch_names + assert "Cz" not in raw.ch_names + assert "Pz" not in raw.ch_names + assert "Oz" not in raw.ch_names + + +@testing.requires_testing_data +def test_gdf_include(): + """Test reading GDF data with include.""" + raw = read_raw_gdf( + gdf1_path.with_name(gdf1_path.name + ".gdf"), include=("FP1", "O1") + ) + assert sorted(raw.ch_names) == ["FP1", "O1"] + + +@testing.requires_testing_data +def test_gdf_read_from_file_like(): + """Test that RawGDF is able to read from file-like objects for GDF files.""" + channels = "FP1 FP2 F5 AFz F6 T7 Cz T8 P7 P3 Pz P4 P8 O1 Oz O2".split() + fname = gdf1_path.with_name(gdf1_path.name + ".gdf") + with open(fname, "rb") as blob: + raw = read_raw_gdf(blob, preload=True) + assert raw.ch_names == channels + data = raw.get_data() + data_2 = read_raw_gdf(fname, preload=True).get_data() + assert_allclose(data, data_2) + + with pytest.raises(Exception, match="Bad GDF file provided."): + read_raw_gdf(BytesIO(), preload=True) + + +@testing.requires_testing_data +@pytest.mark.filterwarnings("ignore:Highpass cutoff frequency") +def test_gh_13414(): + """Test handling bytes objects when reading GDF events.""" + fpath = data_path / "GDF" / "test_gdf_1.99.gdf" + raw = read_raw_gdf(fpath) + # Should be 1 event in this GDF file. + assert len(raw.annotations) == 1 diff --git a/mne-python/source/mne/io/eeglab/__init__.py b/mne-python/source/mne/io/eeglab/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6ffc4e416cc9f5a864323f113936d4881ed274b7 --- /dev/null +++ b/mne-python/source/mne/io/eeglab/__init__.py @@ -0,0 +1,7 @@ +"""EEGLAB module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .eeglab import read_raw_eeglab, read_epochs_eeglab diff --git a/mne-python/source/mne/io/eeglab/_eeglab.py b/mne-python/source/mne/io/eeglab/_eeglab.py new file mode 100644 index 0000000000000000000000000000000000000000..77ad6e681a7d34435e1ccb6570a71a4611e40fbd --- /dev/null +++ b/mne-python/source/mne/io/eeglab/_eeglab.py @@ -0,0 +1,271 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +try: + from scipy.io.matlab import MatlabFunction, MatlabOpaque +except ImportError: # scipy < 1.8 + from scipy.io.matlab.mio5 import MatlabFunction + from scipy.io.matlab.mio5_params import MatlabOpaque +from scipy.io import loadmat, whosmat + +from ...utils import _import_pymatreader_funcs, _soft_import, warn + + +def _todict_from_np_struct(data): # taken from pymatreader.utils + data_dict = {} + + for cur_field_name in data.dtype.names: + try: + n_items = len(data[cur_field_name]) + cur_list = [] + + for idx in np.arange(n_items): + cur_value = data[cur_field_name].item(idx) + cur_value = _check_for_scipy_mat_struct(cur_value) + cur_list.append(cur_value) + + data_dict[cur_field_name] = cur_list + except TypeError: + cur_value = data[cur_field_name].item(0) + cur_value = _check_for_scipy_mat_struct(cur_value) + data_dict[cur_field_name] = cur_value + + return data_dict + + +def _handle_scipy_ndarray(data): # taken from pymatreader.utils + if data.dtype == np.dtype("object") and not isinstance(data, MatlabFunction): + as_list = [] + for element in data: + as_list.append(_check_for_scipy_mat_struct(element)) + data = as_list + elif isinstance(data.dtype.names, tuple): + data = _todict_from_np_struct(data) + data = _check_for_scipy_mat_struct(data) + + if isinstance(data, np.ndarray): + data = np.array(data) + + return data + + +def _check_for_scipy_mat_struct(data): # taken from pymatreader.utils + """Convert all scipy.io.matlab.mio5_params.mat_struct elements.""" + if isinstance(data, dict): + for key in data: + data[key] = _check_for_scipy_mat_struct(data[key]) + + if isinstance(data, MatlabOpaque): + try: + if data[0][2] == b"string": + return None + except IndexError: + pass + + if isinstance(data, np.ndarray): + data = _handle_scipy_ndarray(data) + + return data + + +def _scipy_reader(file_name, variable_names=None, uint16_codec=None): + """Load with scipy and then run the check function.""" + mat_data = loadmat( + file_name, + squeeze_me=True, + mat_dtype=False, + variable_names=variable_names, + uint16_codec=uint16_codec, + ) + return _check_for_scipy_mat_struct(mat_data) + + +def _whosmat_hdf5(fname: str): + """List variables in a MATLAB v7.3 (HDF5) .mat file without loading data. + + This function provides similar functionality to :func:`scipy.io.whosmat` but + for MATLAB v7.3 files stored in HDF5 format, which are not supported by SciPy. + + Parameters + ---------- + fname : str | PathLike + Path to the MATLAB v7.3 (.mat) file. + + Returns + ------- + variables : list of tuple + A list of (name, shape, class) tuples for each variable in the file. + The name is a string, shape is a tuple of ints, and class is a string + indicating the MATLAB data type (e.g., 'double', 'int32', 'struct'). + + Notes + ----- + This function only works with MATLAB v7.3 (HDF5) files. For earlier versions, + use :func:`scipy.io.whosmat` instead. + + See Also + -------- + scipy.io.whosmat : List variables in classic MATLAB files. + """ + h5py = _soft_import("h5py", purpose="MATLAB v7.3 I/O", strict=False) + if h5py is False: + raise ModuleNotFoundError( + "h5py is required to inspect MATLAB v7.3 files preload=`False` " + "Please install h5py to use this functionality." + ) + + variables = [] + + with h5py.File(str(fname), "r") as f: + for name in f.keys(): + node = f[name] + + # Extract shape from HDF5 object + if isinstance(node, h5py.Dataset): + shape = tuple(int(x) for x in node.shape) + else: + shape = () + for attr_key in ( + "MATLAB_shape", + "MATLAB_Size", + "MATLAB_size", + "dims", + "MATLAB_dims", + ): + shp = node.attrs.get(attr_key) + if shp is not None: + try: + shape = tuple(int(x) for x in shp) + break + except Exception: + pass + if not shape and "size" in node: + try: + shape = tuple(int(x) for x in node["size"][()]) + except Exception: + pass + + # Infer MATLAB class from HDF5 object + mcls = node.attrs.get("MATLAB_class", "").lower() + if mcls: + matlab_class = "char" if mcls == "string" else mcls + elif isinstance(node, h5py.Dataset): + dt = node.dtype + # Handle complex numbers stored as {real, imag} struct + if getattr(dt, "names", None) and {"real", "imag"} <= set(dt.names): + matlab_class = ( + "double" if dt["real"].base.itemsize == 8 else "single" + ) + # Map NumPy dtype to MATLAB class + elif (kind := dt.kind) == "f": + matlab_class = "double" if dt.itemsize == 8 else "single" + elif kind == "i": + matlab_class = f"int{8 * dt.itemsize}" + elif kind == "u": + matlab_class = f"uint{8 * dt.itemsize}" + elif kind == "b": + matlab_class = "logical" + elif kind in ("S", "U", "O"): + matlab_class = "char" + else: + matlab_class = "unknown" + # Check for sparse matrix structure + elif {"ir", "jc", "data"}.issubset(set(node.keys())): + matlab_class = "sparse" + else: + matlab_class = "unknown" + + variables.append((name, shape, matlab_class)) + + return variables + + +def _readmat(fname, uint16_codec=None, *, preload=False): + try: + read_mat = _import_pymatreader_funcs("EEGLAB I/O") + except RuntimeError: # pymatreader not installed + read_mat = _scipy_reader + + # First handle the preload=False case + if not preload: + # when preload is `False`, we need to be selective about what we load + # and handle the 'data' field specially + + # the files in eeglab are always the same field names + # the fields were taken from the eeglab sample reference + # available at the eeglab github: + # https://github.com/sccn/eeglab/blob/develop/sample_data/eeglab_data.set + # The sample reference is the big reference for the field names + # in eeglab files, and what is used in the eeglab tests. + info_fields = """ + setname filename filepath subject group condition session comments + nbchan trials pnts srate xmin xmax times icaact icawinv icasphere + icaweights icachansind chanlocs urchanlocs chaninfo ref event + urevent eventdescription epoch epochdescription reject stats + specdata specicaact splinefile icasplinefile dipfit history saved + etc + """.split() + + # We first load only the info fields that are not data + # Then we check if 'data' is present and load it separately if needed + mat_data = read_mat( + fname, + variable_names=info_fields, + uint16_codec=uint16_codec, + ) + + # checking the variables in the .set file + # to decide how to handle 'data' variable + try: + variables = whosmat(str(fname)) + except NotImplementedError: + try: + variables = _whosmat_hdf5(str(fname)) + except ModuleNotFoundError: + warn( + "pymatreader is required to preload=`False` for " + "Matlab files v7.3 files with HDF5 support. " + "Setting preload=True." + ) + preload = True + return read_mat(fname, uint16_codec=uint16_codec) + + is_possible_not_loaded = False + + numeric_types = """ + int8 int16 int32 + int64 uint8 uint16 + uint32 uint64 single double + """.split() + + for var in variables: + # looking for 'data' variable + if var[0] != "data": + continue + + # checking if 'data' variable is numeric + is_numeric = var[2] in numeric_types + + # if any 'data' variable is numeric, mark as possibly not loaded + if is_numeric: + # set the 'data' field to the filename + mat_data["data"] = str(fname) + + is_possible_not_loaded = is_possible_not_loaded or is_numeric + + if is_possible_not_loaded: + return mat_data + else: + # "The 'data' variable in the .set file appears to be numeric. " + # "In preload=False mode, the data is not loaded into memory. " + # "Instead, the filename is provided in mat_data['data']. " + # "To load the actual data, set preload=True." + # this is case of single file .set with data inside + preload = True + + # here is intended to be if and not else if + if preload: + return read_mat(fname, uint16_codec=uint16_codec) diff --git a/mne-python/source/mne/io/eeglab/eeglab.py b/mne-python/source/mne/io/eeglab/eeglab.py new file mode 100644 index 0000000000000000000000000000000000000000..6e651c639fd5968e4d84b3be4da55299bf1854a8 --- /dev/null +++ b/mne-python/source/mne/io/eeglab/eeglab.py @@ -0,0 +1,867 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op +from os import PathLike +from pathlib import Path + +import numpy as np + +from mne.utils.check import _check_option + +from ..._fiff._digitization import _ensure_fiducials_head +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import create_info +from ..._fiff.pick import _PICK_TYPES_KEYS +from ..._fiff.utils import _find_channels, _mult_cal_one, _read_segments_file +from ...annotations import Annotations, read_annotations +from ...channels import make_dig_montage +from ...defaults import DEFAULTS +from ...epochs import BaseEpochs +from ...event import read_events +from ...fixes import _reshape_view +from ...utils import ( + Bunch, + _check_fname, + _check_head_radius, + fill_doc, + logger, + verbose, + warn, +) +from ..base import BaseRaw +from ._eeglab import _readmat + +# just fix the scaling for now, EEGLAB doesn't seem to provide this info +CAL = 1e-6 + + +def _check_eeglab_fname(fname, dataname): + """Check whether the filename is valid. + + Check if the file extension is ``.fdt`` (older ``.dat`` being invalid) + or ``.set`` (new EEGLAB format) or whether the ``EEG.data`` filename exists. + If ``EEG.data`` file is absent the set file name with + .set changed to .fdt is checked. + """ + fmt = str(op.splitext(dataname)[-1]) + if fmt == ".dat": + raise NotImplementedError( + "Old data format .dat detected. Please update your EEGLAB " + "version and resave the data in .fdt format" + ) + + _check_option("EEGLAB file extension", fmt, (".set", ".fdt")) + + basedir = op.dirname(fname) + data_fname = op.join(basedir, dataname) + if not op.exists(data_fname): + fdt_from_set_fname = op.splitext(fname)[0] + ".fdt" + if op.exists(fdt_from_set_fname): + data_fname = fdt_from_set_fname + msg = ( + "Data file name in EEG.data ({}) is incorrect, the file " + "name must have changed on disk, using the correct file " + "name ({})." + ) + warn(msg.format(dataname, op.basename(fdt_from_set_fname))) + elif not data_fname == fdt_from_set_fname: + msg = "Could not find the .fdt data file, tried {} and {}." + raise FileNotFoundError(msg.format(data_fname, fdt_from_set_fname)) + return data_fname + + +def _check_load_mat(fname, uint16_codec, *, preload=False): + """Check if the mat struct contains 'EEG'.""" + fname = _check_fname(fname, "read", True) + eeg = _readmat(fname, uint16_codec=uint16_codec, preload=preload) + if "ALLEEG" in eeg: + raise NotImplementedError( + "Loading an ALLEEG array is not supported. Please contact" + "mne-python developers for more information." + ) + if "EEG" in eeg: # fields are contained in EEG structure + eeg = eeg["EEG"] + eeg = eeg.get("EEG", eeg) # handle nested EEG structure + eeg = Bunch(**eeg) + eeg.trials = int(eeg.get("trials", 1)) + eeg.nbchan = int(eeg.get("nbchan", 1)) + eeg.pnts = int(eeg.get("pnts", 1)) + return eeg + + +def _to_loc(ll): + """Check if location exists.""" + if isinstance(ll, int | float) or len(ll) > 0: + return ll + else: + return np.nan + + +def _eeg_has_montage_information(eeg): + try: + from scipy.io.matlab import mat_struct + except ImportError: # SciPy < 1.8 + from scipy.io.matlab.mio5_params import mat_struct + if not len(eeg.chanlocs): + has_pos = False + else: + pos_fields = ["X", "Y", "Z"] + if isinstance(eeg.chanlocs[0], mat_struct): + has_pos = all(hasattr(eeg.chanlocs[0], fld) for fld in pos_fields) + elif isinstance(eeg.chanlocs[0], np.ndarray): + # Old files + has_pos = all(fld in eeg.chanlocs[0].dtype.names for fld in pos_fields) + elif isinstance(eeg.chanlocs[0], dict): + # new files + has_pos = all(fld in eeg.chanlocs[0] for fld in pos_fields) + else: + has_pos = False # unknown (sometimes we get [0, 0]) + + return has_pos + + +def _get_montage_information(eeg, get_pos, *, montage_units): + """Get channel name, type and montage information from ['chanlocs'].""" + ch_names, ch_types, pos_ch_names, pos = list(), list(), list(), list() + unknown_types = dict() + for chanloc in eeg.chanlocs: + # channel name + ch_names.append(chanloc["labels"]) + + # channel type + ch_type = "eeg" + try_type = chanloc.get("type", None) + if isinstance(try_type, str): + try_type = try_type.strip().lower() + if try_type in _PICK_TYPES_KEYS: + ch_type = try_type + else: + if try_type in unknown_types: + unknown_types[try_type].append(chanloc["labels"]) + else: + unknown_types[try_type] = [chanloc["labels"]] + ch_types.append(ch_type) + + # channel loc + if get_pos: + loc_x = _to_loc(chanloc["X"]) + loc_y = _to_loc(chanloc["Y"]) + loc_z = _to_loc(chanloc["Z"]) + locs = np.r_[-loc_y, loc_x, loc_z] + pos_ch_names.append(chanloc["labels"]) + pos.append(locs) + + # warn if unknown types were provided + if len(unknown_types): + warn( + "Unknown types found, setting as type EEG:\n" + + "\n".join( + [ + f"{key}: {sorted(unknown_types[key])}" + for key in sorted(unknown_types) + ] + ) + ) + + lpa, rpa, nasion = None, None, None + if hasattr(eeg, "chaninfo") and isinstance(eeg.chaninfo.get("nodatchans"), dict): + nodatchans = eeg.chaninfo["nodatchans"] + types = nodatchans.get("type", []) + descriptions = nodatchans.get("description", []) + xs = np.atleast_1d(nodatchans.get("X", [])) + ys = np.atleast_1d(nodatchans.get("Y", [])) + zs = np.atleast_1d(nodatchans.get("Z", [])) + + for type_, description, x, y, z in zip(types, descriptions, xs, ys, zs): + if type_ != "FID": + continue + if description == "Nasion": + nasion = np.array([x, y, z]) + elif description == "Right periauricular point": + rpa = np.array([x, y, z]) + elif description == "Left periauricular point": + lpa = np.array([x, y, z]) + + # Always check this even if it's not used + _check_option("montage_units", montage_units, ("m", "dm", "cm", "mm", "auto")) + if pos_ch_names: + pos_array = np.array(pos, float) + pos_array = _reshape_view(pos_array, (-1, 3)) + + # roughly estimate head radius and check if its reasonable + is_nan_pos = np.isnan(pos).any(axis=1) + if not is_nan_pos.all(): + mean_radius = np.mean(np.linalg.norm(pos_array[~is_nan_pos], axis=1)) + scale_units = _handle_montage_units(montage_units, mean_radius) + mean_radius *= scale_units + pos_array *= scale_units + additional_info = ( + " Check if the montage_units argument is correct (the default " + 'is "mm", but your channel positions may be in different units' + ")." + ) + _check_head_radius(mean_radius, add_info=additional_info) + + montage = make_dig_montage( + ch_pos=dict(zip(ch_names, pos_array)), + coord_frame="head", + lpa=lpa, + rpa=rpa, + nasion=nasion, + ) + _ensure_fiducials_head(montage.dig) + else: + montage = None + + return ch_names, ch_types, montage + + +def _get_info(eeg, *, eog, montage_units): + """Get measurement info.""" + # add the ch_names and info['chs'][idx]['loc'] + if not isinstance(eeg.chanlocs, np.ndarray) and eeg.nbchan == 1: + eeg.chanlocs = [eeg.chanlocs] + + if isinstance(eeg.chanlocs, dict): + eeg.chanlocs = _dol_to_lod(eeg.chanlocs) + + eeg_has_ch_names_info = len(eeg.chanlocs) > 0 + + if eeg_has_ch_names_info: + has_pos = _eeg_has_montage_information(eeg) + ch_names, ch_types, eeg_montage = _get_montage_information( + eeg, has_pos, montage_units=montage_units + ) + update_ch_names = False + else: # if eeg.chanlocs is empty, we still need default chan names + ch_names = [f"EEG {ii:03d}" for ii in range(eeg.nbchan)] + ch_types = "eeg" + eeg_montage = None + update_ch_names = True + + info = create_info(ch_names, sfreq=eeg.srate, ch_types=ch_types) + + eog = _find_channels(ch_names, ch_type="EOG") if eog == "auto" else eog + for idx, ch in enumerate(info["chs"]): + ch["cal"] = CAL + if ch["ch_name"] in eog or idx in eog: + ch["coil_type"] = FIFF.FIFFV_COIL_NONE + ch["kind"] = FIFF.FIFFV_EOG_CH + + return info, eeg_montage, update_ch_names + + +def _set_dig_montage_in_init(self, montage): + """Set EEG sensor configuration and head digitization from when init. + + This is done from the information within fname when + read_raw_eeglab(fname) or read_epochs_eeglab(fname). + """ + if montage is None: + self.set_montage(None) + else: + missing_channels = set(self.ch_names) - set(montage.ch_names) + ch_pos = dict( + zip(list(missing_channels), np.full((len(missing_channels), 3), np.nan)) + ) + self.set_montage(montage + make_dig_montage(ch_pos=ch_pos, coord_frame="head")) + + +def _handle_montage_units(montage_units, mean_radius): + if montage_units == "auto": + # radius should be between 0.05 and 0.11 meters + if mean_radius < 0.25: + montage_units = "m" + elif mean_radius < 2.5: + montage_units = "dm" + elif mean_radius < 25: + montage_units = "cm" + else: # mean_radius >= 25 + montage_units = "mm" + prefix = montage_units[:-1] + scale_units = 1 / DEFAULTS["prefixes"][prefix] + return scale_units + + +@fill_doc +def read_raw_eeglab( + input_fname, + eog=(), + preload=False, + uint16_codec=None, + montage_units="auto", + verbose=None, +) -> "RawEEGLAB": + r"""Read an EEGLAB .set file. + + Parameters + ---------- + input_fname : path-like + Path to the ``.set`` file. If the data is stored in a separate ``.fdt`` + file, it is expected to be in the same folder as the ``.set`` file. + eog : list | tuple | ``'auto'`` + Names or indices of channels that should be designated EOG channels. + If 'auto', the channel names containing ``EOG`` or ``EYE`` are used. + Defaults to empty tuple. + %(preload)s + %(uint16_codec)s + %(montage_units)s + + .. versionchanged:: 1.6 + Support for ``'auto'`` was added and is the new default. + %(verbose)s + + Returns + ------- + raw : instance of RawEEGLAB + A Raw object containing EEGLAB .set data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawEEGLAB. + + Notes + ----- + .. versionadded:: 0.11.0 + """ + return RawEEGLAB( + input_fname=input_fname, + preload=preload, + eog=eog, + uint16_codec=uint16_codec, + montage_units=montage_units, + verbose=verbose, + ) + + +@fill_doc +def read_epochs_eeglab( + input_fname, + events=None, + event_id=None, + eog=(), + *, + uint16_codec=None, + montage_units="auto", + verbose=None, +) -> "EpochsEEGLAB": + r"""Reader function for EEGLAB epochs files. + + Parameters + ---------- + input_fname : path-like + Path to the ``.set`` file. If the data is stored in a separate ``.fdt`` + file, it is expected to be in the same folder as the ``.set`` file. + events : path-like | array, shape (n_events, 3) | None + Path to events file. If array, it is the events typically returned + by the read_events function. If some events don't match the events + of interest as specified by event_id, they will be marked as 'IGNORED' + in the drop log. If None, it is constructed from the EEGLAB (.set) file + with each unique event encoded with a different integer. + event_id : int | list of int | dict | None + The id of the event to consider. If dict, the keys can later be used + to access associated events. + Example:: + + {"auditory":1, "visual":3} + + If int, a dict will be created with + the id as string. If a list, all events with the IDs specified + in the list are used. If None, the event_id is constructed from the + EEGLAB (.set) file with each descriptions copied from ``eventtype``. + eog : list | tuple | 'auto' + Names or indices of channels that should be designated EOG channels. + If 'auto', the channel names containing ``EOG`` or ``EYE`` are used. + Defaults to empty tuple. + %(uint16_codec)s + %(montage_units)s + + .. versionchanged:: 1.6 + Support for ``'auto'`` was added and is the new default. + %(verbose)s + + Returns + ------- + EpochsEEGLAB : instance of BaseEpochs + The epochs. + + See Also + -------- + mne.Epochs : Documentation of attributes and methods. + + Notes + ----- + .. versionadded:: 0.11.0 + """ + epochs = EpochsEEGLAB( + input_fname=input_fname, + events=events, + eog=eog, + event_id=event_id, + uint16_codec=uint16_codec, + montage_units=montage_units, + verbose=verbose, + ) + return epochs + + +@fill_doc +class RawEEGLAB(BaseRaw): + r"""Raw object from EEGLAB .set file. + + Parameters + ---------- + input_fname : path-like + Path to the ``.set`` file. If the data is stored in a separate ``.fdt`` + file, it is expected to be in the same folder as the ``.set`` file. + eog : list | tuple | 'auto' + Names or indices of channels that should be designated EOG channels. + If 'auto', the channel names containing ``EOG`` or ``EYE`` are used. + Defaults to empty tuple. + %(preload)s + %(uint16_codec)s + %(montage_units)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + + Notes + ----- + .. versionadded:: 0.11.0 + """ + + @verbose + def __init__( + self, + input_fname, + eog=(), + preload=False, + *, + uint16_codec=None, + montage_units="auto", + verbose=None, + ): + input_fname = str(_check_fname(input_fname, "read", True, "input_fname")) + eeg = _check_load_mat(input_fname, uint16_codec, preload=preload) + if eeg.trials != 1: + raise TypeError( + f"The number of trials is {eeg.trials:d}. It must be 1 for raw" + " files. Please use `mne.io.read_epochs_eeglab` if" + " the .set file contains epochs." + ) + + last_samps = [eeg.pnts - 1] + info, eeg_montage, _ = _get_info(eeg, eog=eog, montage_units=montage_units) + + # read the data + if isinstance(eeg.data, str): + data_fname = _check_eeglab_fname(input_fname, eeg.data) + logger.info(f"Reading {data_fname}") + # Check if data is embedded in the same .set file + is_embedded = op.realpath(data_fname) == op.realpath(input_fname) + + super().__init__( + info, + preload, + filenames=[data_fname], + last_samps=last_samps, + orig_format="double", + verbose=verbose, + raw_extras=[ + { + "is_embedded": is_embedded, + "input_fname": input_fname, + "uint16_codec": uint16_codec, + } + ], + ) + else: + if eeg.nbchan == 1 and len(eeg.data.shape) == 1: + n_chan, n_times = [1, eeg.data.shape[0]] + else: + n_chan, n_times = eeg.data.shape + data = np.empty((n_chan, n_times), dtype=float) + data[:n_chan] = eeg.data + data *= CAL + super().__init__( + info, + data, + filenames=[input_fname], + last_samps=last_samps, + orig_format="double", + verbose=verbose, + ) + + # create event_ch from annotations + annot = read_annotations(input_fname, uint16_codec=uint16_codec) + self.set_annotations(annot) + _check_boundary(annot, None) + + _set_dig_montage_in_init(self, eeg_montage) + + latencies = np.round(annot.onset * self.info["sfreq"]) + _check_latencies(latencies) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + # Check if data is embedded in .set file + raw_extra = self._raw_extras[fi] + if raw_extra.get("is_embedded", False): + # Check if we have already loaded and cached the embedded data + if "cached_data" not in raw_extra: + # Load from MATLAB struct on-demand (only once) + input_fname = raw_extra["input_fname"] + uint16_codec = raw_extra["uint16_codec"] + eeg_full = _readmat( + input_fname, uint16_codec=uint16_codec, preload=True + ) + if "EEG" in eeg_full: + eeg_full = eeg_full["EEG"] + eeg_full = eeg_full.get("EEG", eeg_full) + full_data = eeg_full.get("data") + + if full_data is None: + raise ValueError( + f"Could not find 'data' field in embedded EEGLAB file: " + f"{input_fname}. The file may be corrupted or not a valid " + "EEGLAB file." + ) + + # Handle 1D data + if full_data.ndim == 1: + full_data = full_data[np.newaxis, :] + + # Cache for future segment reads + raw_extra["cached_data"] = full_data + + # Extract the requested segment from cached data (don't scale here) + full_data = raw_extra["cached_data"] + block = full_data[:, start:stop].astype(np.float32) + # Apply calibration and projection via _mult_cal_one + data_view = data[:, :] + _mult_cal_one(data_view, block, idx, cals, mult) + return + + # Fall back to reading from file (separate .fdt file) + _read_segments_file(self, data, idx, fi, start, stop, cals, mult, dtype=" 1: + # first extract the events and construct an event_id dict + event_name, event_latencies, unique_ev = list(), list(), list() + ev_idx = 0 + warn_multiple_events = False + epochs = _bunchify(eeg.epoch) + events = _bunchify(eeg.event) + for ep in epochs: + if isinstance(ep.eventtype, int | float): + ep.eventtype = str(ep.eventtype) + if not isinstance(ep.eventtype, str): + event_type = "/".join([str(et) for et in ep.eventtype]) + event_name.append(event_type) + # store latency of only first event + # -1 to account for Matlab 1-based indexing of samples + event_latencies.append(events[ev_idx].latency - 1) + ev_idx += len(ep.eventtype) + warn_multiple_events = True + else: + event_type = ep.eventtype + event_name.append(ep.eventtype) + event_latencies.append(events[ev_idx].latency - 1) + ev_idx += 1 + + if event_type not in unique_ev: + unique_ev.append(event_type) + + # invent event dict but use id > 0 so you know its a trigger + event_id = {ev: idx + 1 for idx, ev in enumerate(unique_ev)} + + # warn about multiple events in epoch if necessary + if warn_multiple_events: + warn( + "At least one epoch has multiple events. Only the latency" + " of the first event will be retained." + ) + + # now fill up the event array + events = np.zeros((eeg.trials, 3), dtype=int) + for idx in range(0, eeg.trials): + if idx == 0: + prev_stim = 0 + elif idx > 0 and event_latencies[idx] - event_latencies[idx - 1] == 1: + prev_stim = event_id[event_name[idx - 1]] + events[idx, 0] = event_latencies[idx] + events[idx, 1] = prev_stim + events[idx, 2] = event_id[event_name[idx]] + elif isinstance(events, str | Path | PathLike): + events = read_events(events) + + logger.info(f"Extracting parameters from {input_fname}...") + info, eeg_montage, _ = _get_info(eeg, eog=eog, montage_units=montage_units) + + for key, val in event_id.items(): + if val not in events[:, 2]: + raise ValueError(f"No matching events found for {key} (event id {val})") + + if isinstance(eeg.data, str): + data_fname = _check_eeglab_fname(input_fname, eeg.data) + with open(data_fname, "rb") as data_fid: + data = np.fromfile(data_fid, dtype=np.float32) + data = data.reshape((eeg.nbchan, eeg.pnts, eeg.trials), order="F") + else: + data = eeg.data + + if eeg.nbchan == 1 and len(data.shape) == 2: + data = data[np.newaxis, :] + data = data.transpose((2, 0, 1)).astype("double") + data *= CAL + assert data.shape == (eeg.trials, eeg.nbchan, eeg.pnts) + tmin, tmax = eeg.xmin, eeg.xmax + + super().__init__( + info, + data, + events, + event_id, + tmin, + tmax, + baseline, + reject=reject, + flat=flat, + reject_tmin=reject_tmin, + reject_tmax=reject_tmax, + filename=input_fname, + verbose=verbose, + ) + + # data are preloaded but _bad_dropped is not set so we do it here: + self._bad_dropped = True + + _set_dig_montage_in_init(self, eeg_montage) + + logger.info("Ready.") + + +def _check_boundary(annot, event_id): + if event_id is None: + event_id = dict() + if "boundary" in annot.description and "boundary" not in event_id: + warn( + "The data contains 'boundary' events, indicating data " + "discontinuities. Be cautious of filtering and epoching around " + "these events." + ) + + +def _check_latencies(latencies): + if (latencies < -1).any(): + raise ValueError( + "At least one event sample index is negative. Please" + " check if EEG.event.sample values are correct." + ) + if (latencies == -1).any(): + warn( + "At least one event has a sample index of -1. This usually is " + "a consequence of how eeglab handles event latency after " + "resampling - especially when you had a boundary event at the " + "beginning of the file. Please make sure that the events at " + "the very beginning of your EEGLAB file can be safely dropped " + "(e.g., because they are boundary events)." + ) + + +def _bunchify(items): + if isinstance(items, dict): + items = _dol_to_lod(items) + if len(items) > 0 and isinstance(items[0], dict): + items = [Bunch(**item) for item in items] + return items + + +def _read_annotations_eeglab(eeg, uint16_codec=None): + r"""Create Annotations from EEGLAB file. + + This function reads the event attribute from the EEGLAB + structure and makes an :class:`mne.Annotations` object. + + Parameters + ---------- + eeg : object | str | Path + 'EEG' struct or the path to the (EEGLAB) .set file. + uint16_codec : str | None + If your \*.set file contains non-ascii characters, sometimes reading + it may fail and give rise to error message stating that "buffer is + too small". ``uint16_codec`` allows to specify what codec (for example: + 'latin1' or 'utf-8') should be used when reading character arrays and + can therefore help you solve this problem. + + Returns + ------- + annotations : instance of Annotations + The annotations present in the file. + """ + if isinstance(eeg, (str | Path | PathLike)): + eeg = _check_load_mat(eeg, uint16_codec=uint16_codec) + + if not hasattr(eeg, "event"): + events = [] + elif isinstance(eeg.event, dict) and np.array(eeg.event["latency"]).ndim > 0: + events = _dol_to_lod(eeg.event) + elif not isinstance(eeg.event, np.ndarray | list): + events = [eeg.event] + else: + events = eeg.event + events = _bunchify(events) + description = [str(event.type) for event in events] + onset = [event.latency - 1 for event in events] + duration = np.zeros(len(onset)) + if len(events) > 0 and hasattr(events[0], "duration"): + for idx, event in enumerate(events): + # empty duration fields are read as empty arrays + is_empty_array = ( + isinstance(event.duration, np.ndarray) and len(event.duration) == 0 + ) + duration[idx] = np.nan if is_empty_array else event.duration + + # Drop events with NaN onset see PR #12484 + valid_indices = [ + idx for idx, onset_idx in enumerate(onset) if not np.isnan(onset_idx) + ] + n_dropped = len(onset) - len(valid_indices) + if len(valid_indices) != len(onset): + warn( + f"{n_dropped} events have an onset that is NaN. These values are " + "usually ignored by EEGLAB and will be dropped from the " + "annotations." + ) + + onset = np.array([onset[idx] for idx in valid_indices]) + duration = np.array([duration[idx] for idx in valid_indices]) + description = [description[idx] for idx in valid_indices] + + return Annotations( + onset=np.array(onset) / eeg.srate, + duration=duration / eeg.srate, + description=description, + orig_time=None, + ) + + +def _dol_to_lod(dol): + """Convert a dict of lists to a list of dicts.""" + return [ + {key: dol[key][ii] for key in dol.keys()} + for ii in range(len(dol[list(dol.keys())[0]])) + ] diff --git a/mne-python/source/mne/io/eeglab/tests/__init__.py b/mne-python/source/mne/io/eeglab/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/eeglab/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/eeglab/tests/test_eeglab.py b/mne-python/source/mne/io/eeglab/tests/test_eeglab.py new file mode 100644 index 0000000000000000000000000000000000000000..a042566fbc9ef1a086d7517445cf25714143f54c --- /dev/null +++ b/mne-python/source/mne/io/eeglab/tests/test_eeglab.py @@ -0,0 +1,883 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import shutil +import time +from copy import deepcopy + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_equal, +) +from scipy import io + +import mne +from mne import read_epochs_eeglab, write_events +from mne.annotations import events_from_annotations, read_annotations +from mne.channels import read_custom_montage +from mne.datasets import testing +from mne.io import read_raw_eeglab +from mne.io.eeglab._eeglab import _readmat +from mne.io.eeglab.eeglab import _dol_to_lod, _get_montage_information +from mne.io.tests.test_raw import _test_raw_reader +from mne.utils import Bunch, _check_pymatreader_installed, _record_warnings + +base_dir = testing.data_path(download=False) / "EEGLAB" +raw_fname_mat = base_dir / "test_raw.set" +raw_fname_onefile_mat = base_dir / "test_raw_onefile.set" +raw_fname_event_duration = base_dir / "test_raw_event_duration.set" +epochs_fname_mat = base_dir / "test_epochs.set" +epochs_fname_onefile_mat = base_dir / "test_epochs_onefile.set" +epochs_mat_fnames = [epochs_fname_mat, epochs_fname_onefile_mat] +raw_fname_chanloc = base_dir / "test_raw_chanloc.set" +raw_fname_chanloc_fids = base_dir / "test_raw_chanloc_fids.set" +raw_fname_2021 = base_dir / "test_raw_2021.set" +raw_fname_h5 = base_dir / "test_raw_h5.set" +epochs_fname_h5 = base_dir / "test_epochs_h5.set" +epochs_fname_onefile_h5 = base_dir / "test_epochs_onefile_h5.set" +epochs_h5_fnames = [epochs_fname_h5, epochs_fname_onefile_h5] +montage_path = base_dir / "test_chans.locs" + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "fname", + [ + raw_fname_mat, + pytest.param( + raw_fname_h5, + marks=[ + pytest.mark.skipif( + not _check_pymatreader_installed(strict=False), + reason="pymatreader not installed", + ) + ], + ), + raw_fname_chanloc, + ], + ids=os.path.basename, +) +def test_io_set_raw(fname): + """Test importing EEGLAB .set files.""" + montage = read_custom_montage(montage_path) + montage.ch_names = [f"EEG {ii:03d}" for ii in range(len(montage.ch_names))] + + kws = dict(reader=read_raw_eeglab, input_fname=fname) + if fname.name == "test_raw_chanloc.set": + with pytest.warns(RuntimeWarning, match="The data contains 'boundary' events"): + raw0 = _test_raw_reader(**kws) + elif "_h5" in fname.name: # should be safe enough, and much faster + raw0 = read_raw_eeglab(fname, preload=True) + else: + raw0 = _test_raw_reader(**kws) + + # test that preloading works + if fname.name == "test_raw_chanloc.set": + raw0.set_montage(montage, on_missing="ignore") + # crop to check if the data has been properly preloaded; we cannot + # filter as the snippet of raw data is very short + raw0.crop(0, 1) + else: + raw0.set_montage(montage) + raw0.filter( + 1, None, l_trans_bandwidth="auto", filter_length="auto", phase="zero" + ) + + # test that using uint16_codec does not break stuff + read_raw_kws = dict(input_fname=fname, preload=False, uint16_codec="ascii") + if fname.name == "test_raw_chanloc.set": + with pytest.warns(RuntimeWarning, match="The data contains 'boundary' events"): + raw0 = read_raw_eeglab(**read_raw_kws) + raw0.set_montage(montage, on_missing="ignore") + else: + raw0 = read_raw_eeglab(**read_raw_kws) + raw0.set_montage(montage) + + # Annotations + if fname != raw_fname_chanloc: + assert len(raw0.annotations) == 154 + assert set(raw0.annotations.description) == {"rt", "square"} + assert_array_equal(raw0.annotations.duration, 0.0) + + +@testing.requires_testing_data +def test_io_set_preload_false_uses_lazy_loading(): + """Ensure reading .set files without preload keeps data out of memory.""" + raw_preloaded = read_raw_eeglab(raw_fname_mat, preload=True) + raw_not_preloaded = read_raw_eeglab(raw_fname_mat, preload=False) + + assert not raw_not_preloaded.preload + assert getattr(raw_not_preloaded, "_data", None) is None + assert raw_not_preloaded.n_times == raw_preloaded.n_times + assert raw_not_preloaded.info["nchan"] == raw_preloaded.info["nchan"] + + lazy_slice = raw_not_preloaded[:2, :10][0] + assert lazy_slice.shape == (2, 10) + + # on-demand reads must not flip the preload flag or populate _data + assert not raw_not_preloaded.preload + assert getattr(raw_not_preloaded, "_data", None) is None + + assert raw_preloaded._size > raw_not_preloaded._size + + +@testing.requires_testing_data +def test_io_set_raw_more(tmp_path): + """Test importing EEGLAB .set files.""" + eeg = io.loadmat(raw_fname_mat, struct_as_record=False, squeeze_me=True)["EEG"] + + # test reading file with one event (read old version) + negative_latency_fname = tmp_path / "test_negative_latency.set" + events = deepcopy(eeg.event[0]) + events.latency = 0 + io.savemat( + negative_latency_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": eeg.nbchan, + "data": "test_negative_latency.fdt", + "epoch": eeg.epoch, + "event": events, + "chanlocs": eeg.chanlocs, + "pnts": eeg.pnts, + } + }, + appendmat=False, + oned_as="row", + ) + shutil.copyfile( + base_dir / "test_raw.fdt", negative_latency_fname.with_suffix(".fdt") + ) + with ( + _record_warnings(), + pytest.warns(RuntimeWarning, match="has a sample index of -1."), + ): + read_raw_eeglab(input_fname=negative_latency_fname, preload=True) + + # test negative event latencies + events.latency = -1 + io.savemat( + negative_latency_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": eeg.nbchan, + "data": "test_negative_latency.fdt", + "epoch": eeg.epoch, + "event": events, + "chanlocs": eeg.chanlocs, + "pnts": eeg.pnts, + } + }, + appendmat=False, + oned_as="row", + ) + with pytest.raises(ValueError, match="event sample index is negative"): + with _record_warnings(): + read_raw_eeglab(input_fname=negative_latency_fname, preload=True) + + # test overlapping events + overlap_fname = tmp_path / "test_overlap_event.set" + io.savemat( + overlap_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": eeg.nbchan, + "data": "test_overlap_event.fdt", + "epoch": eeg.epoch, + "event": [eeg.event[0], eeg.event[0]], + "chanlocs": eeg.chanlocs, + "pnts": eeg.pnts, + } + }, + appendmat=False, + oned_as="row", + ) + shutil.copyfile(base_dir / "test_raw.fdt", overlap_fname.with_suffix(".fdt")) + read_raw_eeglab(input_fname=overlap_fname, preload=True) + + # test reading file with empty event durations + empty_dur_fname = tmp_path / "test_empty_durations.set" + events = deepcopy(eeg.event) + for ev in events: + ev.duration = np.array([], dtype="float") + + io.savemat( + empty_dur_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": eeg.nbchan, + "data": "test_negative_latency.fdt", + "epoch": eeg.epoch, + "event": events, + "chanlocs": eeg.chanlocs, + "pnts": eeg.pnts, + } + }, + appendmat=False, + oned_as="row", + ) + shutil.copyfile(base_dir / "test_raw.fdt", empty_dur_fname.with_suffix(".fdt")) + raw = read_raw_eeglab(input_fname=empty_dur_fname, preload=True) + assert (raw.annotations.duration == 0).all() + + # test reading file when the EEG.data name is wrong + io.savemat( + overlap_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": eeg.nbchan, + "data": "test_overla_event.fdt", + "epoch": eeg.epoch, + "event": [eeg.event[0], eeg.event[0]], + "chanlocs": eeg.chanlocs, + "pnts": eeg.pnts, + } + }, + appendmat=False, + oned_as="row", + ) + with pytest.warns(RuntimeWarning, match="must have changed on disk"): + read_raw_eeglab(input_fname=overlap_fname, preload=True) + + # raise error when both EEG.data and fdt name from set are wrong + overlap_fname = tmp_path / "test_ovrlap_event.set" + io.savemat( + overlap_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": eeg.nbchan, + "data": "test_overla_event.fdt", + "epoch": eeg.epoch, + "event": [eeg.event[0], eeg.event[0]], + "chanlocs": eeg.chanlocs, + "pnts": eeg.pnts, + } + }, + appendmat=False, + oned_as="row", + ) + with pytest.raises(FileNotFoundError, match="not find the .fdt data file"): + read_raw_eeglab(input_fname=overlap_fname, preload=True) + + # test reading file with one channel + one_chan_fname = tmp_path / "test_one_channel.set" + io.savemat( + one_chan_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": 1, + "data": np.random.random((1, 3)), + "epoch": eeg.epoch, + "event": eeg.epoch, + "chanlocs": {"labels": "E1", "Y": -6.6069, "X": 6.3023, "Z": -2.9423}, + "times": eeg.times[:3], + "pnts": 3, + } + }, + appendmat=False, + oned_as="row", + ) + read_raw_eeglab(input_fname=one_chan_fname, preload=True, montage_units="cm") + + # test reading file with 3 channels - one without position information + # first, create chanlocs structured array + ch_names = ["F3", "unknown", "FPz"] + x, y, z = [1.0, 2.0, np.nan], [4.0, 5.0, np.nan], [7.0, 8.0, np.nan] + dt = [("labels", "S10"), ("X", "f8"), ("Y", "f8"), ("Z", "f8")] + nopos_dt = [("labels", "S10"), ("Z", "f8")] + chanlocs = np.zeros((3,), dtype=dt) + nopos_chanlocs = np.zeros((3,), dtype=nopos_dt) + for ind, vals in enumerate(zip(ch_names, x, y, z)): + for fld in range(4): + chanlocs[ind][dt[fld][0]] = vals[fld] + if fld in (0, 3): + nopos_chanlocs[ind][dt[fld][0]] = vals[fld] + # In theory this should work and be simpler, but there is an obscure + # SciPy writing bug that pops up sometimes: + # nopos_chanlocs = np.array(chanlocs[['labels', 'Z']]) + + # test reading channel names but not positions when there is no X (only Z) + # field in the EEG.chanlocs structure + nopos_fname = tmp_path / "test_no_chanpos.set" + io.savemat( + nopos_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": 3, + "data": np.random.random((3, 2)), + "epoch": eeg.epoch, + "event": eeg.epoch, + "chanlocs": nopos_chanlocs, + "times": eeg.times[:2], + "pnts": 2, + } + }, + appendmat=False, + oned_as="row", + ) + # load the file + raw = read_raw_eeglab(input_fname=nopos_fname, preload=True, montage_units="cm") + + # test that channel names have been loaded but not channel positions + for i in range(3): + assert_equal(raw.info["chs"][i]["ch_name"], ch_names[i]) + assert_array_equal( + raw.info["chs"][i]["loc"][:3], np.array([np.nan, np.nan, np.nan]) + ) + + +@pytest.mark.timeout(60) # ~60 s on Travis OSX +@testing.requires_testing_data +@pytest.mark.parametrize( + "fnames", + [ + epochs_mat_fnames, + pytest.param( + epochs_h5_fnames, + marks=[ + pytest.mark.slowtest, + pytest.mark.skipif( + not _check_pymatreader_installed(strict=False), + reason="pymatreader not installed", + ), + ], + ), + ], +) +def test_io_set_epochs(fnames): + """Test importing EEGLAB .set epochs files.""" + epochs_fname, epochs_fname_onefile = fnames + with _record_warnings(), pytest.warns(RuntimeWarning, match="multiple events"): + epochs = read_epochs_eeglab(epochs_fname) + with _record_warnings(), pytest.warns(RuntimeWarning, match="multiple events"): + epochs2 = read_epochs_eeglab(epochs_fname_onefile) + # one warning for each read_epochs_eeglab because both files have epochs + # associated with multiple events + assert_array_equal(epochs.get_data(copy=False), epochs2.get_data(copy=False)) + + +@testing.requires_testing_data +def test_io_set_epochs_events(tmp_path): + """Test different combinations of events and event_ids.""" + out_fname = tmp_path / "test-eve.fif" + events = np.array([[4, 0, 1], [12, 0, 2], [20, 0, 3], [26, 0, 3]]) + write_events(out_fname, events) + event_id = {"S255/S8": 1, "S8": 2, "S255/S9": 3} + epochs = read_epochs_eeglab(epochs_fname_mat, events, event_id) + assert_equal(len(epochs.events), 4) + assert epochs.preload + assert epochs._bad_dropped + epochs = read_epochs_eeglab(epochs_fname_mat, out_fname, event_id) + pytest.raises(ValueError, read_epochs_eeglab, epochs_fname_mat, None, event_id) + pytest.raises(ValueError, read_epochs_eeglab, epochs_fname_mat, epochs.events, None) + + +@testing.requires_testing_data +@pytest.mark.filterwarnings("ignore:At least one epoch has multiple events") +@pytest.mark.filterwarnings("ignore:The data contains 'boundary' events") +def test_degenerate(tmp_path): + """Test some degenerate conditions.""" + # test if .dat file raises an error + eeg = io.loadmat(epochs_fname_mat, struct_as_record=False, squeeze_me=True)["EEG"] + eeg.data = "epochs_fname.dat" + bad_epochs_fname = tmp_path / "test_epochs.set" + io.savemat( + bad_epochs_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": eeg.nbchan, + "data": eeg.data, + "epoch": eeg.epoch, + "event": eeg.event, + "chanlocs": eeg.chanlocs, + "pnts": eeg.pnts, + } + }, + appendmat=False, + oned_as="row", + ) + shutil.copyfile(base_dir / "test_epochs.fdt", tmp_path / "test_epochs.dat") + pytest.raises(NotImplementedError, read_epochs_eeglab, bad_epochs_fname) + + # error when montage units incorrect + with pytest.raises(ValueError, match=r"Invalid value"): + read_epochs_eeglab(epochs_fname_mat, montage_units="mV") + + # warning when head radius too large + with pytest.warns(RuntimeWarning, match="is above"): + read_raw_eeglab(raw_fname_chanloc, montage_units="m") + + # warning when head radius too small + m_fname = tmp_path / "test_montage_m.set" + _create_eeg_with_scaled_montage_units(raw_fname_chanloc, m_fname, 1e-3) + with pytest.warns(RuntimeWarning, match="is below"): + read_raw_eeglab(m_fname, montage_units="mm") + + +@pytest.mark.parametrize( + "fname", + [ + raw_fname_mat, + raw_fname_onefile_mat, + # We don't test the h5 variants here because they are implicitly tested + # in test_io_set_raw + ], +) +@pytest.mark.filterwarnings("ignore: Complex objects") +@testing.requires_testing_data +def test_eeglab_annotations(fname): + """Test reading annotations in EEGLAB files.""" + annotations = read_annotations(fname) + assert len(annotations) == 154 + assert set(annotations.description) == {"rt", "square"} + assert np.all(annotations.duration == 0.0) + + +@testing.requires_testing_data +def test_eeglab_read_annotations(): + """Test annotations onsets are timestamps (+ validate some).""" + annotations = read_annotations(raw_fname_mat) + validation_samples = [0, 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31] + expected_onset = np.array( + [ + 1.00, + 1.69, + 2.08, + 4.70, + 7.71, + 11.30, + 17.18, + 20.20, + 26.12, + 29.14, + 35.25, + 44.30, + 47.15, + ] + ) + assert annotations.orig_time is None + assert_array_almost_equal( + annotations.onset[validation_samples], expected_onset, decimal=2 + ) + + # test if event durations are imported correctly + raw = read_raw_eeglab(raw_fname_event_duration, preload=True, montage_units="dm") + # file contains 3 annotations with 0.5 s (64 samples) duration each + assert_allclose(raw.annotations.duration, np.ones(3) * 0.5) + + +@testing.requires_testing_data +def test_eeglab_event_from_annot(): + """Test all forms of obtaining annotations.""" + raw_fname_mat = base_dir / "test_raw.set" + raw_fname = raw_fname_mat + event_id = {"rt": 1, "square": 2} + raw1 = read_raw_eeglab(input_fname=raw_fname, preload=False) + + annotations = read_annotations(raw_fname) + assert len(raw1.annotations) == 154 + raw1.set_annotations(annotations) + events_b, _ = events_from_annotations(raw1, event_id=event_id) + assert len(events_b) == 154 + + +def _assert_array_allclose_nan(left, right): + assert_array_equal(np.isnan(left), np.isnan(right)) + assert_allclose(left[~np.isnan(left)], right[~np.isnan(left)], atol=1e-8) + + +@pytest.fixture(scope="session") +def three_chanpos_fname(tmp_path_factory): + """Test file with 3 channels to exercise EEGLAB reader. + + File characteristics + - ch_names: 'F3', 'unknown', 'FPz' + - 'FPz' has no position information. + - the rest is aleatory + + Notes from when this code was factorized: + # test reading file with one event (read old version) + """ + fname = str(tmp_path_factory.mktemp("data") / "test_chanpos.set") + file_conent = dict( + EEG={ + "trials": 1, + "nbchan": 3, + "pnts": 3, + "epoch": [], + "event": [], + "srate": 128, + "times": np.array([0.0, 0.1, 0.2]), + "data": np.empty([3, 3]), + "chanlocs": np.array( + [ + (b"F3", 1.0, 4.0, 7.0), + (b"unknown", np.nan, np.nan, np.nan), + (b"FPz", 2.0, 5.0, 8.0), + ], + dtype=[("labels", "S10"), ("X", "f8"), ("Y", "f8"), ("Z", "f8")], + ), + } + ) + + io.savemat(file_name=fname, mdict=file_conent, appendmat=False, oned_as="row") + + return fname + + +@testing.requires_testing_data +def test_position_information(three_chanpos_fname): + """Test reading file with 3 channels - one without position information.""" + nan = np.nan + EXPECTED_LOCATIONS_FROM_FILE = ( + np.array( + [ + [-4.0, 1.0, 7.0, 0.0, 0.0, 0.0, nan, nan, nan, nan, nan, nan], + [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], + [-5.0, 2.0, 8.0, 0.0, 0.0, 0.0, nan, nan, nan, nan, nan, nan], + ] + ) + * 0.01 + ) # 0.01 is to scale cm to meters + + EXPECTED_LOCATIONS_FROM_MONTAGE = np.array( + [ + [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], + [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], + [nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan], + ] + ) + + raw = read_raw_eeglab( + input_fname=three_chanpos_fname, preload=True, montage_units="cm" + ) + assert_array_equal( + np.array([ch["loc"] for ch in raw.info["chs"]]), EXPECTED_LOCATIONS_FROM_FILE + ) + + # To accommodate the new behavior so that: + # read_raw_eeglab(.. montage=montage) and raw.set_montage(montage) + # behaves the same we need to flush the montage. otherwise we get + # a mix of what is in montage and in the file + raw = read_raw_eeglab( + input_fname=three_chanpos_fname, + preload=True, + montage_units="cm", + ).set_montage(None) # Flush the montage builtin within input_fname + + _assert_array_allclose_nan( + np.array([ch["loc"] for ch in raw.info["chs"]]), EXPECTED_LOCATIONS_FROM_MONTAGE + ) + + +def _create_eeg_with_scaled_montage_units(in_fname, out_fname, scale): + eeg = io.loadmat(in_fname, struct_as_record=False, squeeze_me=True)["EEG"] + + # test reading file with one event (read old version) + # chanlocs = deepcopy(eeg.chanlocs) + chanlocs = eeg.chanlocs + xyz = np.empty((len(chanlocs), 3)) + labels = [] + for ch_i, loc in enumerate(chanlocs): + xyz[ch_i] = [loc.X, loc.Y, loc.Z] + labels.append(loc.labels) + xyz *= scale + chanlocs = np.rec.fromarrays( + [labels, *xyz.T], + names=["labels", "X", "Y", "Z"], + ) + + fdt = isinstance(eeg.data, str) + if fdt: + shutil.copyfile(in_fname.with_suffix(".fdt"), out_fname.with_suffix(".fdt")) + io.savemat( + out_fname, + { + "EEG": { + "trials": eeg.trials, + "srate": eeg.srate, + "nbchan": eeg.nbchan, + "data": out_fname.with_suffix(".fdt").name if fdt else eeg.data, + "epoch": eeg.epoch, + "event": eeg.event, + "chanlocs": chanlocs, + "pnts": eeg.pnts, + } + }, + appendmat=False, + oned_as="row", + ) + + +@testing.requires_testing_data +def test_estimate_montage_units(tmp_path): + """Test automatic estimation of montage units.""" + m_fname = tmp_path / "test_montage_m.set" + _create_eeg_with_scaled_montage_units(raw_fname_chanloc, m_fname, 1e-3) + cm_fname = tmp_path / "test_montage_cm.set" + _create_eeg_with_scaled_montage_units(raw_fname_chanloc, cm_fname, 1e-1) + with pytest.warns(RuntimeWarning, match="The data contains 'boundary' events"): + # read 3 versions of the same file, with different montage units + raw_mm = read_raw_eeglab(raw_fname_chanloc, montage_units="auto") + raw_m = read_raw_eeglab(m_fname, montage_units="auto") + raw_cm = read_raw_eeglab(cm_fname, montage_units="auto") + # All locations should be the same if the units are correctly estimated + assert_allclose( + np.array([ch["loc"] for ch in raw_mm.info["chs"]]), + np.array([ch["loc"] for ch in raw_m.info["chs"]]), + ) + assert_allclose( + np.array([ch["loc"] for ch in raw_mm.info["chs"]]), + np.array([ch["loc"] for ch in raw_cm.info["chs"]]), + ) + + +@testing.requires_testing_data +def test_io_set_raw_2021(): + """Test reading new default file format (no EEG struct).""" + assert "EEG" not in io.loadmat(raw_fname_2021) + _test_raw_reader( + reader=read_raw_eeglab, + input_fname=raw_fname_2021, + ) + + +@testing.requires_testing_data +def test_read_single_epoch(): + """Test reading raw set file as an Epochs instance.""" + with pytest.raises(ValueError, match="trials less than 2"): + read_epochs_eeglab(raw_fname_mat) + + +@testing.requires_testing_data +def test_get_montage_info_with_ch_type(): + """Test that the channel types are properly returned.""" + mat = _readmat(raw_fname_onefile_mat) + n = len(mat["EEG"]["chanlocs"]["labels"]) + mat["EEG"]["chanlocs"]["type"] = ["eeg"] * (n - 2) + ["eog"] + ["stim"] + mat["EEG"]["chanlocs"] = _dol_to_lod(mat["EEG"]["chanlocs"]) + mat["EEG"] = Bunch(**mat["EEG"]) + ch_names, ch_types, montage = _get_montage_information( + mat["EEG"], + get_pos=False, + montage_units="mm", + ) + assert len(ch_names) == len(ch_types) == n + assert ch_types == ["eeg"] * (n - 2) + ["eog"] + ["stim"] + assert montage is None + + # test unknown type warning + mat = _readmat(raw_fname_onefile_mat) + n = len(mat["EEG"]["chanlocs"]["labels"]) + mat["EEG"]["chanlocs"]["type"] = ["eeg"] * (n - 2) + ["eog"] + ["unknown"] + mat["EEG"]["chanlocs"] = _dol_to_lod(mat["EEG"]["chanlocs"]) + mat["EEG"] = Bunch(**mat["EEG"]) + with pytest.warns(RuntimeWarning, match="Unknown types found"): + ch_names, ch_types, montage = _get_montage_information( + mat["EEG"], + get_pos=False, + montage_units="mm", + ) + + +@testing.requires_testing_data +@pytest.mark.parametrize("has_type", (True, False)) +def test_fidsposition_information(monkeypatch, has_type): + """Test reading file with 3 fiducial locations.""" + if not has_type: + + def get_bad_information(eeg, get_pos, *, montage_units): + del eeg.chaninfo["nodatchans"]["type"] + return _get_montage_information(eeg, get_pos, montage_units=montage_units) + + monkeypatch.setattr( + mne.io.eeglab.eeglab, "_get_montage_information", get_bad_information + ) + raw = read_raw_eeglab(raw_fname_chanloc_fids, montage_units="cm") + montage = raw.get_montage() + pos = montage.get_positions() + n_eeg = 129 + if not has_type: + # These should now be estimated from the data + assert_allclose(pos["nasion"], [0, 0.0997, 0], atol=1e-4) + assert_allclose(pos["lpa"], -pos["nasion"][[1, 0, 0]]) + assert_allclose(pos["rpa"], pos["nasion"][[1, 0, 0]]) + assert pos["nasion"] is not None + assert pos["lpa"] is not None + assert pos["rpa"] is not None + assert len(pos["nasion"]) == 3 + assert len(pos["lpa"]) == 3 + assert len(pos["rpa"]) == 3 + assert len(raw.info["dig"]) == n_eeg + 3 + + +@testing.requires_testing_data +def test_eeglab_drop_nan_annotations(tmp_path): + """Test reading file with NaN annotations.""" + pytest.importorskip("eeglabio") + from eeglabio.raw import export_set + + file_path = tmp_path / "test_nan_anno.set" + raw = read_raw_eeglab(raw_fname_mat, preload=True) + data = raw.get_data() + sfreq = raw.info["sfreq"] + ch_names = raw.ch_names + anno = [ + raw.annotations.description, + raw.annotations.onset, + raw.annotations.duration, + ] + anno[1][0] = np.nan + + export_set( + str(file_path), + data, + sfreq, + ch_names, + ch_locs=None, + annotations=anno, + ref_channels="common", + ch_types=np.repeat("EEG", len(ch_names)), + ) + + with pytest.warns(RuntimeWarning, match="1 .* have an onset that is NaN.*"): + raw = read_raw_eeglab(file_path, preload=True) + + +@pytest.mark.flaky +@testing.requires_testing_data +@pytest.mark.timeout(10) +@pytest.mark.slowtest # has the advantage of not running on macOS where it errs a lot +def test_io_set_preload_false_is_faster(): + """Using preload=False should skip the expensive data read branch.""" + # warm start + read_raw_eeglab(raw_fname_mat, preload=False) + + durations = {} + for preload in (True, False): + start = time.perf_counter() + _ = read_raw_eeglab(raw_fname_mat, preload=preload) + durations[preload] = time.perf_counter() - start + + # preload=True should not be faster than preload=False (timings may vary + # across systems, so avoid strict thresholds) + assert durations[True] > durations[False] + + +@testing.requires_testing_data +def test_lazy_vs_preload_integrity(): + """Test that lazy loading produces identical data to preload.""" + raw_lazy = read_raw_eeglab(raw_fname_onefile_mat, preload=False) + raw_preload = read_raw_eeglab(raw_fname_onefile_mat, preload=True) + + # Get data from both modes + data_lazy = raw_lazy.get_data() + data_preload = raw_preload.get_data() + + # Data should be identical + assert_array_almost_equal(data_lazy, data_preload, decimal=5) + + # Verify shape consistency + assert data_lazy.shape == data_preload.shape + assert raw_lazy.n_times == raw_preload.n_times + assert len(raw_lazy.ch_names) == len(raw_preload.ch_names) + + # Verify no NaN/Inf and data is not all zeros + assert np.isfinite(data_lazy).all() + assert not np.all(data_lazy == 0) + + +@testing.requires_testing_data +def test_lazy_loading_segment_reads(): + """Test that lazy loading correctly reads data segments.""" + raw_lazy = read_raw_eeglab(raw_fname_onefile_mat, preload=False) + raw_preload = read_raw_eeglab(raw_fname_onefile_mat, preload=True) + + # Test beginning, middle, and end segments + segments = [ + (0, 100), + (100, 200), + (raw_lazy.n_times - 100, raw_lazy.n_times), + ] + + for start, stop in segments: + data_lazy = raw_lazy[:, start:stop][0] + data_preload = raw_preload[:, start:stop][0] + + # Segments should be identical + assert_array_almost_equal(data_lazy, data_preload, decimal=5) + + # Data should not be all zeros + assert not np.all(data_lazy == 0) + + +@testing.requires_testing_data +def test_lazy_loading_data_consistency(): + """Test that lazy loading maintains consistency across multiple reads.""" + raw_lazy = read_raw_eeglab(raw_fname_onefile_mat, preload=False) + raw_preload = read_raw_eeglab(raw_fname_onefile_mat, preload=True) + + # Get data multiple times from lazy-loaded raw + reads = [raw_lazy.get_data().copy() for _ in range(3)] + + # All reads should be identical + for i in range(1, len(reads)): + assert_array_equal(reads[0], reads[i]) + + # Should match preloaded data + data_preload = raw_preload.get_data() + assert_array_almost_equal(reads[0], data_preload, decimal=5) + + # Check numerical stability + lazy_mean = np.mean(reads[0]) + lazy_std = np.std(reads[0]) + preload_mean = np.mean(data_preload) + preload_std = np.std(data_preload) + + assert_allclose(lazy_mean, preload_mean, rtol=1e-10) + assert_allclose(lazy_std, preload_std, rtol=1e-10) + + +@testing.requires_testing_data +@pytest.mark.parametrize("fname", [raw_fname_onefile_mat, raw_fname_mat]) +def test_lazy_vs_preload_all_formats(fname): + """Test lazy loading vs preload for both embedded and separate formats.""" + raw_lazy = read_raw_eeglab(fname, preload=False) + raw_preload = read_raw_eeglab(fname, preload=True) + + # Verify identical data + data_lazy = raw_lazy.get_data() + data_preload = raw_preload.get_data() + assert_array_almost_equal(data_lazy, data_preload, decimal=5) + + # Verify metadata is identical + assert raw_lazy.n_times == raw_preload.n_times + assert raw_lazy.info["sfreq"] == raw_preload.info["sfreq"] + assert len(raw_lazy.ch_names) == len(raw_preload.ch_names) + + # Verify annotations are present + assert len(raw_lazy.annotations) == len(raw_preload.annotations) diff --git a/mne-python/source/mne/io/egi/__init__.py b/mne-python/source/mne/io/egi/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..72f638d49e9607c3aa9322eed2d735578633d016 --- /dev/null +++ b/mne-python/source/mne/io/egi/__init__.py @@ -0,0 +1,8 @@ +"""EGI module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .egi import read_raw_egi +from .egimff import read_evokeds_mff diff --git a/mne-python/source/mne/io/egi/egi.py b/mne-python/source/mne/io/egi/egi.py new file mode 100644 index 0000000000000000000000000000000000000000..73e93d39460162b3d48885fa85e1148530d0de37 --- /dev/null +++ b/mne-python/source/mne/io/egi/egi.py @@ -0,0 +1,333 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime +import time + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info +from ..._fiff.utils import _create_chs, _read_segments_file +from ...annotations import Annotations +from ...utils import _check_fname, _validate_type, logger, verbose +from ..base import BaseRaw +from .egimff import _read_raw_egi_mff +from .events import _combine_triggers, _triage_include_exclude + + +def _read_header(fid): + """Read EGI binary header.""" + version = np.fromfile(fid, " 6 & ~np.bitwise_and(version, 6): + version = version.byteswap().astype(np.uint32) + else: + raise ValueError("Watchout. This does not seem to be a simple binary EGI file.") + + def my_fread(*x, **y): + return int(np.fromfile(*x, **y)[0]) + + info = dict( + version=version, + year=my_fread(fid, ">i2", 1), + month=my_fread(fid, ">i2", 1), + day=my_fread(fid, ">i2", 1), + hour=my_fread(fid, ">i2", 1), + minute=my_fread(fid, ">i2", 1), + second=my_fread(fid, ">i2", 1), + millisecond=my_fread(fid, ">i4", 1), + samp_rate=my_fread(fid, ">i2", 1), + n_channels=my_fread(fid, ">i2", 1), + gain=my_fread(fid, ">i2", 1), + bits=my_fread(fid, ">i2", 1), + value_range=my_fread(fid, ">i2", 1), + ) + + unsegmented = 1 if np.bitwise_and(version, 1) == 0 else 0 + precision = np.bitwise_and(version, 6) + if precision == 0: + raise RuntimeError("Floating point precision is undefined.") + + if unsegmented: + info.update( + dict( + n_categories=0, + n_segments=1, + n_samples=int(np.fromfile(fid, ">i4", 1)[0]), + n_events=int(np.fromfile(fid, ">i2", 1)[0]), + event_codes=[], + category_names=[], + category_lengths=[], + pre_baseline=0, + ) + ) + for event in range(info["n_events"]): + event_codes = "".join(np.fromfile(fid, "S1", 4).astype("U1")) + info["event_codes"].append(event_codes) + else: + raise NotImplementedError("Only continuous files are supported") + info["unsegmented"] = unsegmented + info["dtype"], info["orig_format"] = { + 2: (">i2", "short"), + 4: (">f4", "float"), + 6: (">f8", "double"), + }[precision] + info["dtype"] = np.dtype(info["dtype"]) + return info + + +def _read_events(fid, info): + """Read events.""" + events = np.zeros([info["n_events"], info["n_segments"] * info["n_samples"]]) + fid.seek(36 + info["n_events"] * 4, 0) # skip header + for si in range(info["n_samples"]): + # skip data channels + fid.seek(info["n_channels"] * info["dtype"].itemsize, 1) + # read event channels + events[:, si] = np.fromfile(fid, info["dtype"], info["n_events"]) + return events + + +@verbose +def read_raw_egi( + input_fname, + eog=None, + misc=None, + include=None, + exclude=None, + preload=False, + channel_naming="E%d", + *, + events_as_annotations=True, + verbose=None, +) -> "RawEGI": + """Read EGI simple binary as raw object. + + Parameters + ---------- + input_fname : path-like + Path to the raw file. Files with an extension ``.mff`` are + automatically considered to be EGI's native MFF format files. + eog : list or tuple + Names of channels or list of indices that should be designated + EOG channels. Default is None. + misc : list or tuple + Names of channels or list of indices that should be designated + MISC channels. Default is None. + include : None | list + The event channels to be included when creating the synthetic + trigger or annotations. Defaults to None. + Note. Overrides ``exclude`` parameter. + exclude : None | list + The event channels to be ignored when creating the synthetic + trigger or annotations. Defaults to None. If None, the ``sync`` and ``TREV`` + channels will be ignored. This is ignored when ``include`` is not None. + %(preload)s + + .. versionadded:: 0.11 + channel_naming : str + Channel naming convention for the data channels. Defaults to ``'E%%d'`` + (resulting in channel names ``'E1'``, ``'E2'``, ``'E3'``...). The + effective default prior to 0.14.0 was ``'EEG %%03d'``. + + .. versionadded:: 0.14.0 + + events_as_annotations : bool + If True, annotations are created from experiment events. If False (default), + a synthetic trigger channel ``STI 014`` is created from experiment events. + See the Notes section for details. + The default will change from False to True in version 1.9. + + .. versionadded:: 1.8.0 + %(verbose)s + + Returns + ------- + raw : instance of RawEGI + A Raw object containing EGI data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawEGI. + + Notes + ----- + When ``events_from_annotations=True``, event codes on stimulus channels like + ``DIN1`` are stored as annotations with the ``description`` set to the stimulus + channel name. + + When ``events_from_annotations=False`` and events are present on the included + stimulus channels, a new stim channel ``STI014`` will be synthesized from the + events. It will contain 1-sample pulses where the Netstation file had event + timestamps. A ``raw.event_id`` dictionary is added to the raw object that will have + arbitrary sequential integer IDs for the events. This will fail if any timestamps + are duplicated. The ``event_id`` will also not survive a save/load roundtrip. + + For these reasons, it is recommended to use ``events_as_annotations=True``. + """ + _validate_type(input_fname, "path-like", "input_fname") + input_fname = str(input_fname) + _validate_type(events_as_annotations, bool, "events_as_annotations") + + if input_fname.rstrip("/\\").endswith(".mff"): # allows .mff or .mff/ + return _read_raw_egi_mff( + input_fname, + eog, + misc, + include, + exclude, + preload, + channel_naming, + events_as_annotations=events_as_annotations, + verbose=verbose, + ) + return RawEGI( + input_fname, + eog, + misc, + include, + exclude, + preload, + channel_naming, + events_as_annotations=events_as_annotations, + verbose=verbose, + ) + + +class RawEGI(BaseRaw): + """Raw object from EGI simple binary file.""" + + _extra_attributes = ("event_id",) + + @verbose + def __init__( + self, + input_fname, + eog=None, + misc=None, + include=None, + exclude=None, + preload=False, + channel_naming="E%d", + *, + events_as_annotations=True, + verbose=None, + ): + input_fname = str(_check_fname(input_fname, "read", True, "input_fname")) + if eog is None: + eog = [] + if misc is None: + misc = [] + with open(input_fname, "rb") as fid: # 'rb' important for py3k + logger.info(f"Reading EGI header from {input_fname}...") + egi_info = _read_header(fid) + logger.info(" Reading events ...") + egi_events = _read_events(fid, egi_info) # update info + jump + if egi_info["value_range"] != 0 and egi_info["bits"] != 0: + cal = egi_info["value_range"] / 2.0 ** egi_info["bits"] + else: + cal = 1e-6 + + logger.info(" Assembling measurement info ...") + + event_codes = egi_info["event_codes"] + include = _triage_include_exclude(include, exclude, egi_events, egi_info) + if egi_info["n_events"] > 0 and not events_as_annotations: + event_ids = np.arange(len(include)) + 1 + logger.info(' Synthesizing trigger channel "STI 014" ...') + egi_info["new_trigger"] = _combine_triggers( + egi_events[[e in include for e in event_codes]], remapping=event_ids + ) + self.event_id = dict( + zip([e for e in event_codes if e in include], event_ids) + ) + else: + self.event_id = None + egi_info["new_trigger"] = None + info = _empty_info(egi_info["samp_rate"]) + my_time = datetime.datetime( + egi_info["year"], + egi_info["month"], + egi_info["day"], + egi_info["hour"], + egi_info["minute"], + egi_info["second"], + ) + my_timestamp = time.mktime(my_time.timetuple()) + info["meas_date"] = (my_timestamp, 0) + ch_names = [channel_naming % (i + 1) for i in range(egi_info["n_channels"])] + cals = np.repeat(cal, len(ch_names)) + ch_names.extend(list(event_codes)) + cals = np.concatenate([cals, np.ones(egi_info["n_events"])]) + if egi_info["new_trigger"] is not None: + ch_names.append("STI 014") # our new_trigger + cals = np.concatenate([cals, [1.0]]) + ch_coil = FIFF.FIFFV_COIL_EEG + ch_kind = FIFF.FIFFV_EEG_CH + chs = _create_chs(ch_names, cals, ch_coil, ch_kind, eog, (), (), misc) + sti_ch_idx = [ + i + for i, name in enumerate(ch_names) + if name.startswith("STI") or name in event_codes + ] + for idx in sti_ch_idx: + chs[idx].update( + { + "unit_mul": FIFF.FIFF_UNITM_NONE, + "kind": FIFF.FIFFV_STIM_CH, + "coil_type": FIFF.FIFFV_COIL_NONE, + "unit": FIFF.FIFF_UNIT_NONE, + "loc": np.zeros(12), + } + ) + info["chs"] = chs + info._unlocked = False + info._update_redundant() + orig_format = ( + egi_info["orig_format"] if egi_info["orig_format"] != "float" else "single" + ) + super().__init__( + info, + preload, + orig_format=orig_format, + filenames=[input_fname], + last_samps=[egi_info["n_samples"] - 1], + raw_extras=[egi_info], + verbose=verbose, + ) + if events_as_annotations: + annot = dict(onset=list(), duration=list(), description=list()) + for code, row in zip(egi_info["event_codes"], egi_events): + if code not in include: + continue + onset = np.where(row)[0] / self.info["sfreq"] + annot["onset"].extend(onset) + annot["duration"].extend([0.0] * len(onset)) + annot["description"].extend([code] * len(onset)) + if annot: + self.set_annotations(Annotations(**annot)) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a segment of data from a file.""" + egi_info = self._raw_extras[fi] + dtype = egi_info["dtype"] + n_chan_read = egi_info["n_channels"] + egi_info["n_events"] + offset = 36 + egi_info["n_events"] * 4 + trigger_ch = egi_info["new_trigger"] + _read_segments_file( + self, + data, + idx, + fi, + start, + stop, + cals, + mult, + dtype=dtype, + n_channels=n_chan_read, + offset=offset, + trigger_ch=trigger_ch, + ) diff --git a/mne-python/source/mne/io/egi/egimff.py b/mne-python/source/mne/io/egi/egimff.py new file mode 100644 index 0000000000000000000000000000000000000000..870f58890a2f58e78f6daa8c00d0f99a79b49ac2 --- /dev/null +++ b/mne-python/source/mne/io/egi/egimff.py @@ -0,0 +1,974 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""EGI NetStation Load Function.""" + +import datetime +import math +import os.path as op +import re +from collections import OrderedDict +from pathlib import Path + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info, _ensure_meas_date_none_or_dt, create_info +from ..._fiff.proj import setup_proj +from ..._fiff.utils import _create_chs, _mult_cal_one +from ...annotations import Annotations +from ...channels.montage import make_dig_montage +from ...evoked import EvokedArray +from ...utils import _check_fname, _check_option, _soft_import, logger, verbose, warn +from ..base import BaseRaw +from .events import _combine_triggers, _read_events, _triage_include_exclude +from .general import ( + _block_r, + _extract, + _get_blocks, + _get_ep_info, + _get_gains, + _get_signalfname, +) + +REFERENCE_NAMES = ("VREF", "Vertex Reference") + + +def _read_mff_header(filepath): + """Read mff header.""" + _soft_import("defusedxml", "reading EGI MFF data") + from defusedxml.minidom import parse + + all_files = _get_signalfname(filepath) + eeg_file = all_files["EEG"]["signal"] + eeg_info_file = all_files["EEG"]["info"] + + info_filepath = op.join(filepath, "info.xml") # add with filepath + tags = ["mffVersion", "recordTime"] + version_and_date = _extract(tags, filepath=info_filepath) + version = "" + if len(version_and_date["mffVersion"]): + version = version_and_date["mffVersion"][0] + + fname = op.join(filepath, eeg_file) + signal_blocks = _get_blocks(fname) + epochs = _get_ep_info(filepath) + summaryinfo = dict(eeg_fname=eeg_file, info_fname=eeg_info_file) + summaryinfo.update(signal_blocks) + # sanity check and update relevant values + record_time = version_and_date["recordTime"][0] + # e.g., + # 2018-07-30T10:47:01.021673-04:00 + # 2017-09-20T09:55:44.072000000+01:00 + g = re.match( + r"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.(\d{6}(?:\d{3})?)[+-]\d{2}:\d{2}", # noqa: E501 + record_time, + ) + if g is None: + raise RuntimeError(f"Could not parse recordTime {repr(record_time)}") + frac = g.groups()[0] + assert len(frac) in (6, 9) and all(f.isnumeric() for f in frac) # regex + div = 1000 if len(frac) == 6 else 1000000 + for key in ("last_samps", "first_samps"): + # convert from times in µS to samples + for ei, e in enumerate(epochs[key]): + if e % div != 0: + raise RuntimeError(f"Could not parse epoch time {e}") + epochs[key][ei] = e // div + epochs[key] = np.array(epochs[key], np.uint64) + # I guess they refer to times in milliseconds? + # What we really need to do here is: + # epochs[key] *= signal_blocks['sfreq'] + # epochs[key] //= 1000 + # But that multiplication risks an overflow, so let's only multiply + # by what we need to (e.g., a sample rate of 500 means we can multiply + # by 1 and divide by 2 rather than multiplying by 500 and dividing by + # 1000) + numerator = int(signal_blocks["sfreq"]) + denominator = 1000 + this_gcd = math.gcd(numerator, denominator) + numerator = numerator // this_gcd + denominator = denominator // this_gcd + with np.errstate(over="raise"): + epochs[key] *= numerator + epochs[key] //= denominator + # Should be safe to cast to int now, which makes things later not + # upbroadcast to float + epochs[key] = epochs[key].astype(np.int64) + n_samps_block = signal_blocks["samples_block"].sum() + n_samps_epochs = (epochs["last_samps"] - epochs["first_samps"]).sum() + bad = ( + n_samps_epochs != n_samps_block + or not (epochs["first_samps"] < epochs["last_samps"]).all() + or not (epochs["first_samps"][1:] >= epochs["last_samps"][:-1]).all() + ) + if bad: + raise RuntimeError( + "EGI epoch first/last samps could not be parsed:\n" + f"{list(epochs['first_samps'])}\n{list(epochs['last_samps'])}" + ) + summaryinfo.update(epochs) + # index which samples in raw are actually readable from disk (i.e., not + # in a skip) + disk_samps = np.full(epochs["last_samps"][-1], -1) + offset = 0 + for first, last in zip(epochs["first_samps"], epochs["last_samps"]): + n_this = last - first + disk_samps[first:last] = np.arange(offset, offset + n_this) + offset += n_this + summaryinfo["disk_samps"] = disk_samps + + # Add the sensor info. + sensor_layout_file = op.join(filepath, "sensorLayout.xml") + sensor_layout_obj = parse(sensor_layout_file) + + summaryinfo["device"] = sensor_layout_obj.getElementsByTagName("name")[ + 0 + ].firstChild.data + sensors = sensor_layout_obj.getElementsByTagName("sensor") + chan_type = list() + chan_unit = list() + n_chans = 0 + numbers = list() # used for identification + for sensor in sensors: + sensortype = int(sensor.getElementsByTagName("type")[0].firstChild.data) + if sensortype in [0, 1]: + sn = sensor.getElementsByTagName("number")[0].firstChild.data + sn = sn.encode() + numbers.append(sn) + chan_type.append("eeg") + chan_unit.append("uV") + n_chans = n_chans + 1 + if n_chans != summaryinfo["n_channels"]: + raise RuntimeError( + f"Number of defined channels ({n_chans}) did not match the " + f"expected channels ({summaryinfo['n_channels']})." + ) + + # Check presence of PNS data + pns_names = [] + if "PNS" in all_files: + pns_fpath = op.join(filepath, all_files["PNS"]["signal"]) + pns_blocks = _get_blocks(pns_fpath) + pns_samples = pns_blocks["samples_block"] + signal_samples = signal_blocks["samples_block"] + same_blocks = np.array_equal( + pns_samples[:-1], signal_samples[:-1] + ) and pns_samples[-1] in (signal_samples[-1] - np.arange(2)) + if not same_blocks: + raise RuntimeError( + "PNS and signals samples did not match:\n" + f"{list(pns_samples)}\nvs\n{list(signal_samples)}" + ) + + pns_file = op.join(filepath, "pnsSet.xml") + pns_obj = parse(pns_file) + sensors = pns_obj.getElementsByTagName("sensor") + pns_types = [] + pns_units = [] + for sensor in sensors: + # sensor number: + # sensor.getElementsByTagName('number')[0].firstChild.data + name = sensor.getElementsByTagName("name")[0].firstChild.data + unit_elem = sensor.getElementsByTagName("unit")[0].firstChild + unit = "" + if unit_elem is not None: + unit = unit_elem.data + + if name == "ECG": + ch_type = "ecg" + elif "EMG" in name: + ch_type = "emg" + else: + ch_type = "bio" + pns_types.append(ch_type) + pns_units.append(unit) + pns_names.append(name) + + summaryinfo.update( + pns_types=pns_types, + pns_units=pns_units, + pns_fname=all_files["PNS"]["signal"], + pns_sample_blocks=pns_blocks, + ) + summaryinfo.update( + pns_names=pns_names, + version=version, + date=version_and_date["recordTime"][0], + chan_type=chan_type, + chan_unit=chan_unit, + numbers=numbers, + ) + + return summaryinfo + + +def _read_header(input_fname): + """Obtain the headers from the file package mff. + + Parameters + ---------- + input_fname : path-like + Path for the file + + Returns + ------- + info : dict + Main headers set. + """ + input_fname = str(input_fname) # cast to str any Paths + mff_hdr = _read_mff_header(input_fname) + with open(input_fname + "/signal1.bin", "rb") as fid: + version = np.fromfile(fid, np.int32, 1)[0] + """ + the datetime.strptime .f directive (milleseconds) + will only accept up to 6 digits. if there are more than + six millesecond digits in the provided timestamp string + (i.e. because of trailing zeros, as in test_egi_pns.mff) + then slice both the first 26 elements and the last 6 + elements of the timestamp string to truncate the + milleseconds to 6 digits and extract the timezone, + and then piece these together and assign back to mff_hdr['date'] + """ + if len(mff_hdr["date"]) > 32: + dt, tz = [mff_hdr["date"][:26], mff_hdr["date"][-6:]] + mff_hdr["date"] = dt + tz + + time_n = datetime.datetime.strptime(mff_hdr["date"], "%Y-%m-%dT%H:%M:%S.%f%z") + + info = dict( + version=version, + meas_dt_local=time_n, + utc_offset=time_n.strftime("%z"), + gain=0, + bits=0, + value_range=0, + ) + info.update( + n_categories=0, + n_segments=1, + n_events=0, + event_codes=[], + category_names=[], + category_lengths=[], + pre_baseline=0, + ) + info.update(mff_hdr) + return info + + +def _get_eeg_calibration_info(filepath, egi_info): + """Calculate calibration info for EEG channels.""" + gains = _get_gains(op.join(filepath, egi_info["info_fname"])) + if egi_info["value_range"] != 0 and egi_info["bits"] != 0: + cals = [egi_info["value_range"] / 2 ** egi_info["bits"]] * len( + egi_info["chan_type"] + ) + else: + cal_scales = {"uV": 1e-6, "V": 1} + cals = [cal_scales[t] for t in egi_info["chan_unit"]] + if "gcal" in gains: + cals *= gains["gcal"] + return cals + + +def _read_locs(filepath, egi_info, channel_naming): + """Read channel locations.""" + _soft_import("defusedxml", "reading EGI MFF data") + from defusedxml.minidom import parse + + fname = op.join(filepath, "coordinates.xml") + if not op.exists(fname): + warn("File coordinates.xml not found, not setting channel locations") + ch_names = [channel_naming % (i + 1) for i in range(egi_info["n_channels"])] + return ch_names, None + dig_ident_map = { + "Left periauricular point": "lpa", + "Right periauricular point": "rpa", + "Nasion": "nasion", + } + numbers = np.array(egi_info["numbers"]) + coordinates = parse(fname) + sensors = coordinates.getElementsByTagName("sensor") + ch_pos = OrderedDict() + hsp = list() + nlr = dict() + ch_names = list() + + for sensor in sensors: + name_element = sensor.getElementsByTagName("name")[0].firstChild + num_element = sensor.getElementsByTagName("number")[0].firstChild + name = ( + channel_naming % int(num_element.data) + if name_element is None + else name_element.data + ) + nr = num_element.data.encode() + coords = [ + float(sensor.getElementsByTagName(coord)[0].firstChild.data) + for coord in "xyz" + ] + loc = np.array(coords) / 100 # cm -> m + # create dig entry + if name in dig_ident_map: + nlr[dig_ident_map[name]] = loc + else: + # id_ is the index of the channel in egi_info['numbers'] + id_ = np.flatnonzero(numbers == nr) + # if it's not in egi_info['numbers'], it's a headshape point + if len(id_) == 0: + hsp.append(loc) + # not HSP, must be a data or reference channel + else: + ch_names.append(name) + ch_pos[name] = loc + mon = make_dig_montage(ch_pos=ch_pos, hsp=hsp, **nlr) + return ch_names, mon + + +def _add_pns_channel_info(chs, egi_info, ch_names): + """Add info for PNS channels to channel info dict.""" + for i_ch, ch_name in enumerate(egi_info["pns_names"]): + idx = ch_names.index(ch_name) + ch_type = egi_info["pns_types"][i_ch] + type_to_kind_map = {"ecg": FIFF.FIFFV_ECG_CH, "emg": FIFF.FIFFV_EMG_CH} + ch_kind = type_to_kind_map.get(ch_type, FIFF.FIFFV_BIO_CH) + ch_unit = FIFF.FIFF_UNIT_V + ch_cal = 1e-6 + if egi_info["pns_units"][i_ch] != "uV": + ch_unit = FIFF.FIFF_UNIT_NONE + ch_cal = 1.0 + chs[idx].update( + cal=ch_cal, kind=ch_kind, coil_type=FIFF.FIFFV_COIL_NONE, unit=ch_unit + ) + return chs + + +@verbose +def _read_raw_egi_mff( + input_fname, + eog=None, + misc=None, + include=None, + exclude=None, + preload=False, + channel_naming="E%d", + *, + events_as_annotations=True, + verbose=None, +): + """Read EGI mff binary as raw object.""" + return RawMff( + input_fname, + eog, + misc, + include, + exclude, + preload, + channel_naming, + events_as_annotations=events_as_annotations, + verbose=verbose, + ) + + +class RawMff(BaseRaw): + """RawMff class.""" + + _extra_attributes = ("event_id",) + + @verbose + def __init__( + self, + input_fname, + eog=None, + misc=None, + include=None, + exclude=None, + preload=False, + channel_naming="E%d", + *, + events_as_annotations=True, + verbose=None, + ): + """Init the RawMff class.""" + input_fname = str( + _check_fname( + input_fname, + "read", + True, + "input_fname", + need_dir=True, + ) + ) + logger.info(f"Reading EGI MFF Header from {input_fname}...") + egi_info = _read_header(input_fname) + if eog is None: + eog = [] + if misc is None: + misc = np.where(np.array(egi_info["chan_type"]) != "eeg")[0].tolist() + + logger.info(" Reading events ...") + egi_events, egi_info, mff_events = _read_events(input_fname, egi_info) + cals = _get_eeg_calibration_info(input_fname, egi_info) + logger.info(" Assembling measurement info ...") + event_codes = egi_info["event_codes"] + include = _triage_include_exclude(include, exclude, egi_events, egi_info) + if egi_info["n_events"] > 0 and not events_as_annotations: + logger.info(' Synthesizing trigger channel "STI 014" ...') + if all(ch.startswith("D") for ch in include): + # support the DIN format DIN1, DIN2, ..., DIN9, DI10, DI11, ... DI99, + # D100, D101, ..., D255 that we get when sending 0-255 triggers on a + # parallel port. + events_ids = list() + for ch in include: + while not ch[0].isnumeric(): + ch = ch[1:] + events_ids.append(int(ch)) + else: + events_ids = np.arange(len(include)) + 1 + egi_info["new_trigger"] = _combine_triggers( + egi_events[[c in include for c in event_codes]], remapping=events_ids + ) + self.event_id = dict( + zip([e for e in event_codes if e in include], events_ids) + ) + if egi_info["new_trigger"] is not None: + egi_events = np.vstack([egi_events, egi_info["new_trigger"]]) + else: + self.event_id = None + egi_info["new_trigger"] = None + assert egi_events.shape[1] == egi_info["last_samps"][-1] + + meas_dt_utc = egi_info["meas_dt_local"].astimezone(datetime.timezone.utc) + info = _empty_info(egi_info["sfreq"]) + info["meas_date"] = _ensure_meas_date_none_or_dt(meas_dt_utc) + info["utc_offset"] = egi_info["utc_offset"] + info["device_info"] = dict(type=egi_info["device"]) + + # read in the montage, if it exists + ch_names, mon = _read_locs(input_fname, egi_info, channel_naming) + # Second: Stim + ch_names.extend(list(egi_info["event_codes"])) + n_extra = len(event_codes) + len(misc) + len(eog) + len(egi_info["pns_names"]) + if egi_info["new_trigger"] is not None: + ch_names.append("STI 014") # channel for combined events + n_extra += 1 + + # Third: PNS + ch_names.extend(egi_info["pns_names"]) + + cals = np.concatenate([cals, np.ones(n_extra)]) + assert len(cals) == len(ch_names), (len(cals), len(ch_names)) + + # Actually create channels as EEG, then update stim and PNS + ch_coil = FIFF.FIFFV_COIL_EEG + ch_kind = FIFF.FIFFV_EEG_CH + chs = _create_chs(ch_names, cals, ch_coil, ch_kind, eog, (), (), misc) + + sti_ch_idx = [ + i + for i, name in enumerate(ch_names) + if name.startswith("STI") or name in event_codes + ] + for idx in sti_ch_idx: + chs[idx].update( + { + "unit_mul": FIFF.FIFF_UNITM_NONE, + "cal": cals[idx], + "kind": FIFF.FIFFV_STIM_CH, + "coil_type": FIFF.FIFFV_COIL_NONE, + "unit": FIFF.FIFF_UNIT_NONE, + } + ) + chs = _add_pns_channel_info(chs, egi_info, ch_names) + info["chs"] = chs + info._unlocked = False + info._update_redundant() + + if mon is not None: + info.set_montage(mon, on_missing="ignore") + ref_idx = np.flatnonzero(np.isin(mon.ch_names, REFERENCE_NAMES)) + if len(ref_idx): + ref_idx = ref_idx.item() + ref_coords = info["chs"][int(ref_idx)]["loc"][:3] + for chan in info["chs"]: + if chan["kind"] == FIFF.FIFFV_EEG_CH: + chan["loc"][3:6] = ref_coords + + file_bin = op.join(input_fname, egi_info["eeg_fname"]) + egi_info["egi_events"] = egi_events + + # Check how many channels to read are from EEG + keys = ("eeg", "sti", "pns") + idx = dict() + idx["eeg"] = np.where([ch["kind"] == FIFF.FIFFV_EEG_CH for ch in chs])[0] + idx["sti"] = np.where([ch["kind"] == FIFF.FIFFV_STIM_CH for ch in chs])[0] + idx["pns"] = np.where( + [ + ch["kind"] in (FIFF.FIFFV_ECG_CH, FIFF.FIFFV_EMG_CH, FIFF.FIFFV_BIO_CH) + for ch in chs + ] + )[0] + # By construction this should always be true, but check anyway + if not np.array_equal( + np.concatenate([idx[key] for key in keys]), np.arange(len(chs)) + ): + raise ValueError( + "Currently interlacing EEG and PNS channels is not supported" + ) + egi_info["kind_bounds"] = [0] + for key in keys: + egi_info["kind_bounds"].append(len(idx[key])) + egi_info["kind_bounds"] = np.cumsum(egi_info["kind_bounds"]) + assert egi_info["kind_bounds"][0] == 0 + assert egi_info["kind_bounds"][-1] == info["nchan"] + first_samps = [0] + last_samps = [egi_info["last_samps"][-1] - 1] + + annot = dict(onset=list(), duration=list(), description=list()) + + if len(idx["pns"]): + # PNS Data is present and should be read: + egi_info["pns_filepath"] = op.join(input_fname, egi_info["pns_fname"]) + # Check for PNS bug immediately + pns_samples = np.sum(egi_info["pns_sample_blocks"]["samples_block"]) + eeg_samples = np.sum(egi_info["samples_block"]) + if pns_samples == eeg_samples - 1: + warn("This file has the EGI PSG sample bug") + annot["onset"].append(last_samps[-1] / egi_info["sfreq"]) + annot["duration"].append(1 / egi_info["sfreq"]) + annot["description"].append("BAD_EGI_PSG") + elif pns_samples != eeg_samples: + raise RuntimeError( + f"PNS samples ({pns_samples}) did not match EEG samples " + f"({eeg_samples})." + ) + + super().__init__( + info, + preload=preload, + orig_format="single", + filenames=[file_bin], + first_samps=first_samps, + last_samps=last_samps, + raw_extras=[egi_info], + verbose=verbose, + ) + + # Annotate acquisition skips + for first, prev_last in zip( + egi_info["first_samps"][1:], egi_info["last_samps"][:-1] + ): + gap = first - prev_last + assert gap >= 0 + if gap: + annot["onset"].append((prev_last - 0.5) / egi_info["sfreq"]) + annot["duration"].append(gap / egi_info["sfreq"]) + annot["description"].append("BAD_ACQ_SKIP") + + # create events from annotations + if events_as_annotations: + for code, samples in mff_events.items(): + if code not in include: + continue + annot["onset"].extend(np.array(samples) / egi_info["sfreq"]) + annot["duration"].extend([0.0] * len(samples)) + annot["description"].extend([code] * len(samples)) + + if len(annot["onset"]): + self.set_annotations(Annotations(**annot)) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of data.""" + logger.debug(f"Reading MFF {start:6d} ... {stop:6d} ...") + dtype = "= bounds[1]) & (idx < bounds[2]))[0] + stim_one = idx[stim_out] + stim_in = idx[stim_out] - bounds[1] + pns_out = np.where((idx >= bounds[2]) & (idx < bounds[3]))[0] + pns_in = idx[pns_out] - bounds[2] + pns_one = idx[pns_out, np.newaxis] + del eeg_out, stim_out, pns_out + + # take into account events (already extended to correct size) + one[stim_one, :] = egi_info["egi_events"][stim_in, start:stop] + + # Convert start and stop to limits in terms of the data + # actually on disk, plus an indexer (disk_use_idx) that populates + # the potentially larger `data` with it, taking skips into account + disk_samps = egi_info["disk_samps"][start:stop] + disk_use_idx = np.where(disk_samps > -1)[0] + # short circuit in case we don't need any samples + if not len(disk_use_idx): + _mult_cal_one(data, one, idx, cals, mult) + return + + start = disk_samps[disk_use_idx[0]] + stop = disk_samps[disk_use_idx[-1]] + 1 + assert len(disk_use_idx) == stop - start + + # Get starting/stopping block/samples + block_samples_offset = np.cumsum(samples_block) + offset_blocks = np.sum(block_samples_offset <= start) + offset_samples = start - ( + block_samples_offset[offset_blocks - 1] if offset_blocks > 0 else 0 + ) + + # TODO: Refactor this reading with the PNS reading in a single function + # (DRY) + samples_to_read = stop - start + with open(self.filenames[fi], "rb", buffering=0) as fid: + # Go to starting block + current_block = 0 + current_block_info = None + current_data_sample = 0 + while current_block < offset_blocks: + this_block_info = _block_r(fid) + if this_block_info is not None: + current_block_info = this_block_info + fid.seek(current_block_info["block_size"], 1) + current_block += 1 + + # Start reading samples + while samples_to_read > 0: + logger.debug(f" Reading from block {current_block}") + this_block_info = _block_r(fid) + current_block += 1 + if this_block_info is not None: + current_block_info = this_block_info + + to_read = current_block_info["nsamples"] * current_block_info["nc"] + block_data = np.fromfile(fid, dtype, to_read) + block_data = block_data.reshape(n_channels, -1, order="C") + + # Compute indexes + samples_read = block_data.shape[1] + logger.debug(f" Read {samples_read} samples") + logger.debug(f" Offset {offset_samples} samples") + if offset_samples > 0: + # First block read, skip to the offset: + block_data = block_data[:, offset_samples:] + samples_read = samples_read - offset_samples + offset_samples = 0 + if samples_to_read < samples_read: + # Last block to read, skip the last samples + block_data = block_data[:, :samples_to_read] + samples_read = samples_to_read + logger.debug(f" Keep {samples_read} samples") + + s_start = current_data_sample + s_end = s_start + samples_read + + one[eeg_one, disk_use_idx[s_start:s_end]] = block_data[eeg_in] + samples_to_read = samples_to_read - samples_read + current_data_sample = current_data_sample + samples_read + + if len(pns_one) > 0: + # PNS Data is present and should be read: + pns_filepath = egi_info["pns_filepath"] + pns_info = egi_info["pns_sample_blocks"] + n_channels = pns_info["n_channels"] + samples_block = pns_info["samples_block"] + + # Get starting/stopping block/samples + block_samples_offset = np.cumsum(samples_block) + offset_blocks = np.sum(block_samples_offset < start) + offset_samples = start - ( + block_samples_offset[offset_blocks - 1] if offset_blocks > 0 else 0 + ) + + samples_to_read = stop - start + with open(pns_filepath, "rb", buffering=0) as fid: + # Check file size + fid.seek(0, 2) + file_size = fid.tell() + fid.seek(0) + # Go to starting block + current_block = 0 + current_block_info = None + current_data_sample = 0 + while current_block < offset_blocks: + this_block_info = _block_r(fid) + if this_block_info is not None: + current_block_info = this_block_info + fid.seek(current_block_info["block_size"], 1) + current_block += 1 + + # Start reading samples + while samples_to_read > 0: + if samples_to_read == 1 and fid.tell() == file_size: + # We are in the presence of the EEG bug + # fill with zeros and break the loop + one[pns_one, -1] = 0 + break + + this_block_info = _block_r(fid) + if this_block_info is not None: + current_block_info = this_block_info + + to_read = current_block_info["nsamples"] * current_block_info["nc"] + block_data = np.fromfile(fid, dtype, to_read) + block_data = block_data.reshape(n_channels, -1, order="C") + + # Compute indexes + samples_read = block_data.shape[1] + if offset_samples > 0: + # First block read, skip to the offset: + block_data = block_data[:, offset_samples:] + samples_read = samples_read - offset_samples + offset_samples = 0 + + if samples_to_read < samples_read: + # Last block to read, skip the last samples + block_data = block_data[:, :samples_to_read] + samples_read = samples_to_read + + s_start = current_data_sample + s_end = s_start + samples_read + + one[pns_one, disk_use_idx[s_start:s_end]] = block_data[pns_in] + samples_to_read = samples_to_read - samples_read + current_data_sample = current_data_sample + samples_read + + # do the calibration + _mult_cal_one(data, one, idx, cals, mult) + + +@verbose +def read_evokeds_mff( + fname, condition=None, channel_naming="E%d", baseline=None, verbose=None +): + """Read averaged MFF file as EvokedArray or list of EvokedArray. + + Parameters + ---------- + fname : path-like + File path to averaged MFF file. Should end in ``.mff``. + condition : int or str | list of int or str | None + The index (indices) or category (categories) from which to read in + data. Averaged MFF files can contain separate averages for different + categories. These can be indexed by the block number or the category + name. If ``condition`` is a list or None, a list of EvokedArray objects + is returned. + channel_naming : str + Channel naming convention for EEG channels. Defaults to 'E%%d' + (resulting in channel names 'E1', 'E2', 'E3'...). + baseline : None (default) or tuple of length 2 + The time interval to apply baseline correction. If None do not apply + it. If baseline is (a, b) the interval is between "a (s)" and "b (s)". + If a is None the beginning of the data is used and if b is None then b + is set to the end of the interval. If baseline is equal to (None, None) + all the time interval is used. Correction is applied by computing mean + of the baseline period and subtracting it from the data. The baseline + (a, b) includes both endpoints, i.e. all timepoints t such that + a <= t <= b. + %(verbose)s + + Returns + ------- + evoked : EvokedArray or list of EvokedArray + The evoked dataset(s); one EvokedArray if condition is int or str, + or list of EvokedArray if condition is None or list. + + Raises + ------ + ValueError + If ``fname`` has file extension other than '.mff'. + ValueError + If the MFF file specified by ``fname`` is not averaged. + ValueError + If no categories.xml file in MFF directory specified by ``fname``. + + See Also + -------- + Evoked, EvokedArray, create_info + + Notes + ----- + .. versionadded:: 0.22 + """ + mffpy = _import_mffpy() + # Confirm `fname` is a path to an MFF file + fname = Path(fname) # should be replace with _check_fname + if not fname.suffix == ".mff": + raise ValueError('fname must be an MFF file with extension ".mff".') + # Confirm the input MFF is averaged + mff = mffpy.Reader(fname) + try: + flavor = mff.mff_flavor + except AttributeError: # < 6.3 + flavor = mff.flavor + if flavor not in ("averaged", "segmented"): # old, new names + raise ValueError( + f"{fname} is a {flavor} MFF file. " + "fname must be the path to an averaged MFF file." + ) + # Check for categories.xml file + if "categories.xml" not in mff.directory.listdir(): + raise ValueError( + "categories.xml not found in MFF directory. " + f"{fname} may not be an averaged MFF file." + ) + return_list = True + if condition is None: + categories = mff.categories.categories + condition = list(categories.keys()) + elif not isinstance(condition, list): + condition = [condition] + return_list = False + logger.info(f"Reading {len(condition)} evoked datasets from {fname} ...") + output = [ + _read_evoked_mff( + fname, c, channel_naming=channel_naming, verbose=verbose + ).apply_baseline(baseline) + for c in condition + ] + return output if return_list else output[0] + + +def _read_evoked_mff(fname, condition, channel_naming="E%d", verbose=None): + """Read evoked data from MFF file.""" + import mffpy + + egi_info = _read_header(fname) + mff = mffpy.Reader(fname) + categories = mff.categories.categories + + if isinstance(condition, str): + # Condition is interpreted as category name + category = _check_option( + "condition", condition, categories, extra="provided as category name" + ) + epoch = mff.epochs[category] + elif isinstance(condition, int): + # Condition is interpreted as epoch index + try: + epoch = mff.epochs[condition] + except IndexError: + raise ValueError( + f'"condition" parameter ({condition}), provided ' + "as epoch index, is out of range for available " + f"epochs ({len(mff.epochs)})." + ) + category = epoch.name + else: + raise TypeError('"condition" parameter must be either int or str.') + + # Read in signals from the target epoch + data = mff.get_physical_samples_from_epoch(epoch) + eeg_data, t0 = data["EEG"] + if "PNSData" in data: + pns_data, t0 = data["PNSData"] + all_data = np.vstack((eeg_data, pns_data)) + ch_types = egi_info["chan_type"] + egi_info["pns_types"] + else: + all_data = eeg_data + ch_types = egi_info["chan_type"] + all_data *= 1e-6 # convert to volts + + # Load metadata into info object + # Exclude info['meas_date'] because record time info in + # averaged MFF is the time of the averaging, not true record time. + ch_names, mon = _read_locs(fname, egi_info, channel_naming) + ch_names.extend(egi_info["pns_names"]) + info = create_info(ch_names, mff.sampling_rates["EEG"], ch_types) + with info._unlock(): + info["device_info"] = dict(type=egi_info["device"]) + info["nchan"] = sum(mff.num_channels.values()) + + # Add individual channel info + # Get calibration info for EEG channels + cals = _get_eeg_calibration_info(fname, egi_info) + # Initialize calibration for PNS channels, will be updated later + cals = np.concatenate([cals, np.repeat(1, len(egi_info["pns_names"]))]) + ch_coil = FIFF.FIFFV_COIL_EEG + ch_kind = FIFF.FIFFV_EEG_CH + chs = _create_chs(ch_names, cals, ch_coil, ch_kind, (), (), (), ()) + # Update PNS channel info + chs = _add_pns_channel_info(chs, egi_info, ch_names) + with info._unlock(): + info["chs"] = chs + if mon is not None: + info.set_montage(mon, on_missing="ignore") + + # Add bad channels to info + info["description"] = category + try: + channel_status = categories[category][0]["channelStatus"] + except KeyError: + warn( + f"Channel status data not found for condition {category}. " + "No channels will be marked as bad.", + category=UserWarning, + ) + channel_status = None + bads = [] + if channel_status: + for entry in channel_status: + if entry["exclusion"] == "badChannels": + if entry["signalBin"] == 1: + # Add bad EEG channels + for ch in entry["channels"]: + bads.append(ch_names[ch - 1]) + elif entry["signalBin"] == 2: + # Add bad PNS channels + for ch in entry["channels"]: + bads.append(egi_info["pns_names"][ch - 1]) + info["bads"] = bads + + # Add EEG reference to info + try: + fp = mff.directory.filepointer("history") + except (ValueError, FileNotFoundError): # old (<=0.6.3) vs new mffpy + pass + else: + with fp: + history = mffpy.XML.from_file(fp) + for entry in history.entries: + if entry["method"] == "Montage Operations Tool": + if "Average Reference" in entry["settings"]: + # Average reference has been applied + _, info = setup_proj(info) + + # Get nave from categories.xml + try: + nave = categories[category][0]["keys"]["#seg"]["data"] + except KeyError: + warn( + f"Number of averaged epochs not found for condition {category}. " + "nave will default to 1.", + category=UserWarning, + ) + nave = 1 + + # Let tmin default to 0 + return EvokedArray( + all_data, info, tmin=0.0, comment=category, nave=nave, verbose=verbose + ) + + +def _import_mffpy(why="read averaged .mff files"): + """Import and return module mffpy.""" + try: + import mffpy + except ImportError as exp: + msg = f"mffpy is required to {why}, got:\n{exp}" + raise ImportError(msg) + + return mffpy diff --git a/mne-python/source/mne/io/egi/events.py b/mne-python/source/mne/io/egi/events.py new file mode 100644 index 0000000000000000000000000000000000000000..c160ceb208c622a3eab72e6e3d80a12295112412 --- /dev/null +++ b/mne-python/source/mne/io/egi/events.py @@ -0,0 +1,213 @@ +# +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from datetime import datetime +from glob import glob +from os.path import basename, join, splitext + +import numpy as np + +from ...utils import _soft_import, _validate_type, logger, warn + + +def _read_events(input_fname, info): + """Read events for the record. + + Parameters + ---------- + input_fname : path-like + The file path. + info : dict + Header info array. + """ + n_samples = info["last_samps"][-1] + mff_events, event_codes = _read_mff_events(input_fname, info["sfreq"]) + info["n_events"] = len(event_codes) + info["event_codes"] = event_codes + events = np.zeros([info["n_events"], info["n_segments"] * n_samples]) + for n, event in enumerate(event_codes): + for i in mff_events[event]: + if (i < 0) or (i >= events.shape[1]): + continue + events[n][i] = n + 1 + return events, info, mff_events + + +def _read_mff_events(filename, sfreq): + """Extract the events. + + Parameters + ---------- + filename : path-like + File path. + sfreq : float + The sampling frequency + """ + orig = {} + for xml_file in glob(join(filename, "*.xml")): + xml_type = splitext(basename(xml_file))[0] + et = _parse_xml(xml_file) + if et is not None: + orig[xml_type] = et + xml_files = orig.keys() + xml_events = [x for x in xml_files if x[:7] == "Events_"] + for item in orig["info"]: + if "recordTime" in item: + start_time = _ns2py_time(item["recordTime"]) + break + markers = [] + code = [] + for xml in xml_events: + for event in orig[xml][2:]: + event_start = _ns2py_time(event["beginTime"]) + start = (event_start - start_time).total_seconds() + if event["code"] not in code: + code.append(event["code"]) + marker = { + "name": event["code"], + "start": start, + "start_sample": int(np.trunc(start * sfreq)), + "end": start + float(event["duration"]) / 1e9, + "chan": None, + } + markers.append(marker) + events_tims = dict() + for ev in code: + trig_samp = list( + c["start_sample"] for n, c in enumerate(markers) if c["name"] == ev + ) + events_tims.update({ev: trig_samp}) + return events_tims, code + + +def _parse_xml(xml_file: str) -> list[dict[str, str]] | None: + """Parse XML file.""" + defusedxml = _soft_import("defusedxml", "reading EGI MFF data") + try: + xml = defusedxml.ElementTree.parse(xml_file) + except defusedxml.ElementTree.ParseError as e: + warn(f"Could not parse the XML file {xml_file}: {e}") + return + root = xml.getroot() + return _xml2list(root) + + +def _xml2list(root): + """Parse XML item.""" + output = [] + for element in root: + if len(element) > 0: + if element[0].tag != element[-1].tag: + output.append(_xml2dict(element)) + else: + output.append(_xml2list(element)) + + elif element.text: + text = element.text.strip() + if text: + tag = _ns(element.tag) + output.append({tag: text}) + + return output + + +def _ns(s): + """Remove namespace, but only if there is a namespace to begin with.""" + if "}" in s: + return "}".join(s.split("}")[1:]) + else: + return s + + +def _xml2dict(root): + """Use functions instead of Class. + + remove namespace based on + http://stackoverflow.com/questions/2148119 + """ + output = {} + if root.items(): + output.update(dict(root.items())) + + for element in root: + if len(element) > 0: + if len(element) == 1 or element[0].tag != element[1].tag: + one_dict = _xml2dict(element) + else: + one_dict = {_ns(element[0].tag): _xml2list(element)} + + if element.items(): + one_dict.update(dict(element.items())) + output.update({_ns(element.tag): one_dict}) + + elif element.items(): + output.update({_ns(element.tag): dict(element.items())}) + + else: + output.update({_ns(element.tag): element.text}) + return output + + +def _ns2py_time(nstime): + """Parse times.""" + nsdate = nstime[0:10] + nstime0 = nstime[11:26] + nstime00 = nsdate + " " + nstime0 + pytime = datetime.strptime(nstime00, "%Y-%m-%d %H:%M:%S.%f") + return pytime + + +def _combine_triggers(data, remapping=None): + """Combine binary triggers.""" + new_trigger = np.zeros(data.shape[1]) + if data.astype(bool).sum(axis=0).max() > 1: # ensure no overlaps + logger.info( + " Found multiple events at the same time " + "sample. Cannot create trigger channel." + ) + return + if remapping is None: + remapping = np.arange(data) + 1 + for d, event_id in zip(data, remapping): + idx = d.nonzero() + if np.any(idx): + new_trigger[idx] += event_id + return new_trigger + + +def _triage_include_exclude(include, exclude, egi_events, egi_info): + """Triage include and exclude.""" + _validate_type(exclude, (list, None), "exclude") + _validate_type(include, (list, None), "include") + event_codes = list(egi_info["event_codes"]) + for name, lst in dict(exclude=exclude, include=include).items(): + for ii, item in enumerate(lst or []): + what = f"{name}[{ii}]" + _validate_type(item, str, what) + if item not in event_codes: + raise ValueError( + f"Could not find event channel named {what}={repr(item)}" + ) + if include is None: + if exclude is None: + default_exclude = ["sync", "TREV"] + exclude = [code for code in default_exclude if code in event_codes] + for code, event in zip(event_codes, egi_events): + if event.sum() < 1 and code: + exclude.append(code) + if ( + len(exclude) == len(event_codes) + and egi_info["n_events"] + and set(exclude) - set(default_exclude) + ): + warn( + "Did not find any event code with at least one event.", + RuntimeWarning, + ) + include = [k for k in event_codes if k not in exclude] + del exclude + excl_events = ", ".join(k for k in event_codes if k not in include) + logger.info(f" Excluding events {{{excl_events}}} ...") + return include diff --git a/mne-python/source/mne/io/egi/general.py b/mne-python/source/mne/io/egi/general.py new file mode 100644 index 0000000000000000000000000000000000000000..ed028e3e5edeaf5180c2cfcafb36762a15963aa4 --- /dev/null +++ b/mne-python/source/mne/io/egi/general.py @@ -0,0 +1,192 @@ +# +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import re + +import numpy as np + +from ...utils import _pl, _soft_import + + +def _extract(tags, filepath=None, obj=None): + """Extract info from XML.""" + _soft_import("defusedxml", "reading EGI MFF data") + from defusedxml.minidom import parse + + if obj is not None: + fileobj = obj + elif filepath is not None: + fileobj = parse(filepath) + else: + raise ValueError("There is not object or file to extract data") + infoxml = dict() + for tag in tags: + value = fileobj.getElementsByTagName(tag) + infoxml[tag] = [] + for i in range(len(value)): + infoxml[tag].append(value[i].firstChild.data) + return infoxml + + +def _get_gains(filepath): + """Parse gains.""" + _soft_import("defusedxml", "reading EGI MFF data") + from defusedxml.minidom import parse + + file_obj = parse(filepath) + objects = file_obj.getElementsByTagName("calibration") + gains = dict() + for ob in objects: + value = ob.getElementsByTagName("type") + if value[0].firstChild.data == "GCAL": + data_g = _extract(["ch"], obj=ob)["ch"] + gains.update(gcal=np.asarray(data_g, dtype=np.float64)) + elif value[0].firstChild.data == "ICAL": + data_g = _extract(["ch"], obj=ob)["ch"] + gains.update(ical=np.asarray(data_g, dtype=np.float64)) + return gains + + +def _get_ep_info(filepath): + """Get epoch info.""" + _soft_import("defusedxml", "reading EGI MFF data") + from defusedxml.minidom import parse + + epochfile = filepath + "/epochs.xml" + epochlist = parse(epochfile) + epochs = epochlist.getElementsByTagName("epoch") + keys = ("first_samps", "last_samps", "first_blocks", "last_blocks") + epoch_info = {key: list() for key in keys} + for epoch in epochs: + ep_begin = int(epoch.getElementsByTagName("beginTime")[0].firstChild.data) + ep_end = int(epoch.getElementsByTagName("endTime")[0].firstChild.data) + first_block = int(epoch.getElementsByTagName("firstBlock")[0].firstChild.data) + last_block = int(epoch.getElementsByTagName("lastBlock")[0].firstChild.data) + epoch_info["first_samps"].append(ep_begin) + epoch_info["last_samps"].append(ep_end) + epoch_info["first_blocks"].append(first_block) + epoch_info["last_blocks"].append(last_block) + # Don't turn into ndarray here, keep native int because it can deal with + # huge numbers (could use np.uint64 but it's more work) + return epoch_info + + +def _get_blocks(filepath): + """Get info from meta data blocks.""" + binfile = os.path.join(filepath) + n_blocks = 0 + samples_block = [] + header_sizes = [] + n_channels = [] + sfreq = [] + # Meta data consists of: + # * 1 byte of flag (1 for meta data, 0 for data) + # * 1 byte of header size + # * 1 byte of block size + # * 1 byte of n_channels + # * n_channels bytes of offsets + # * n_channels bytes of sigfreqs? + with open(binfile, "rb") as fid: + fid.seek(0, 2) # go to end of file + file_length = fid.tell() + block_size = file_length + fid.seek(0) + position = 0 + while position < file_length: + block = _block_r(fid) + if block is None: + samples_block.append(samples_block[n_blocks - 1]) + n_blocks += 1 + fid.seek(block_size, 1) + position = fid.tell() + continue + block_size = block["block_size"] + header_size = block["header_size"] + header_sizes.append(header_size) + samples_block.append(block["nsamples"]) + n_blocks += 1 + fid.seek(block_size, 1) + sfreq.append(block["sfreq"]) + n_channels.append(block["nc"]) + position = fid.tell() + + if any([n != n_channels[0] for n in n_channels]): + raise RuntimeError("All the blocks don't have the same amount of channels.") + if any([f != sfreq[0] for f in sfreq]): + raise RuntimeError("All the blocks don't have the same sampling frequency.") + if len(samples_block) < 1: + raise RuntimeError("There seems to be no data") + samples_block = np.array(samples_block) + signal_blocks = dict( + n_channels=n_channels[0], + sfreq=sfreq[0], + n_blocks=n_blocks, + samples_block=samples_block, + header_sizes=header_sizes, + ) + return signal_blocks + + +def _get_signalfname(filepath): + """Get filenames.""" + _soft_import("defusedxml", "reading EGI MFF data") + from defusedxml.minidom import parse + + listfiles = os.listdir(filepath) + binfiles = list( + f for f in listfiles if "signal" in f and f[-4:] == ".bin" and f[0] != "." + ) + all_files = {} + infofiles = list() + for binfile in binfiles: + bin_num_str = re.search(r"\d+", binfile).group() + infofile = "info" + bin_num_str + ".xml" + infofiles.append(infofile) + infobjfile = os.path.join(filepath, infofile) + infobj = parse(infobjfile) + if len(infobj.getElementsByTagName("EEG")): + signal_type = "EEG" + elif len(infobj.getElementsByTagName("PNSData")): + signal_type = "PNS" + all_files[signal_type] = { + "signal": f"signal{bin_num_str}.bin", + "info": infofile, + } + if "EEG" not in all_files: + infofiles_str = "\n".join(infofiles) + raise FileNotFoundError( + f"Could not find any EEG data in the {len(infofiles)} file{_pl(infofiles)} " + f"found in {filepath}:\n{infofiles_str}" + ) + return all_files + + +def _block_r(fid): + """Read meta data.""" + if np.fromfile(fid, dtype=np.dtype("i4"), count=1).item() != 1: # not meta + return None + header_size = np.fromfile(fid, dtype=np.dtype("i4"), count=1).item() + block_size = np.fromfile(fid, dtype=np.dtype("i4"), count=1).item() + hl = int(block_size / 4) + nc = np.fromfile(fid, dtype=np.dtype("i4"), count=1).item() + nsamples = int(hl / nc) + np.fromfile(fid, dtype=np.dtype("i4"), count=nc) # sigoffset + sigfreq = np.fromfile(fid, dtype=np.dtype("i4"), count=nc) + depth = sigfreq[0] & 0xFF + if depth != 32: + raise ValueError("I do not know how to read this MFF (depth != 32)") + sfreq = sigfreq[0] >> 8 + count = int(header_size / 4 - (4 + 2 * nc)) + np.fromfile(fid, dtype=np.dtype("i4"), count=count) # sigoffset + block = dict( + nc=nc, + hl=hl, + nsamples=nsamples, + block_size=block_size, + header_size=header_size, + sfreq=sfreq, + ) + return block diff --git a/mne-python/source/mne/io/egi/tests/__init__.py b/mne-python/source/mne/io/egi/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/egi/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/egi/tests/data/test_egi.raw b/mne-python/source/mne/io/egi/tests/data/test_egi.raw new file mode 100644 index 0000000000000000000000000000000000000000..9c123abc4e809c8e79c8f2f1232b745db787a79d Binary files /dev/null and b/mne-python/source/mne/io/egi/tests/data/test_egi.raw differ diff --git a/mne-python/source/mne/io/egi/tests/data/test_egi.txt b/mne-python/source/mne/io/egi/tests/data/test_egi.txt new file mode 100644 index 0000000000000000000000000000000000000000..039ce16159f3c541b0abf7f70b38d5bac5ecc7bf --- /dev/null +++ b/mne-python/source/mne/io/egi/tests/data/test_egi.txt @@ -0,0 +1,257 @@ +0.0000 0.0040 0.0080 0.0120 0.0160 0.0200 0.0240 0.0280 0.0320 0.0360 0.0400 0.0440 0.0480 0.0520 0.0560 0.0600 0.0640 0.0680 0.0720 0.0760 0.0800 0.0840 0.0880 0.0920 0.0960 0.1000 0.1040 0.1080 0.1120 0.1160 0.1200 0.1240 0.1280 0.1320 0.1360 0.1400 0.1440 0.1480 0.1520 0.1560 0.1600 0.1640 0.1680 0.1720 0.1760 0.1800 0.1840 0.1880 0.1920 0.1960 0.2000 0.2040 0.2080 0.2120 0.2160 0.2200 0.2240 0.2280 0.2320 0.2360 0.2400 0.2440 0.2480 0.2520 0.2560 0.2600 0.2640 0.2680 0.2720 0.2760 0.2800 0.2840 0.2880 0.2920 0.2960 0.3000 0.3040 +-14262.1006 -13993.9355 -14057.4209 -14348.1191 -14499.7773 -14278.8652 -14002.6699 -14074.4443 -14363.5654 -14518.6748 -14299.7109 -14015.6279 -14089.3516 -14393.6992 -14532.9512 -14305.7783 -14018.3018 -14086.9072 -14396.1084 -14558.9863 -14331.1709 -14054.4727 -14119.8574 -14414.1943 -14562.3350 -14329.5059 -14054.7188 -14120.3340 -14424.5088 -14578.3438 -14344.0576 -14052.6904 -14125.6689 -14431.7695 -14585.3408 -14355.4746 -14069.3818 -14139.3613 -14429.4570 -14587.8311 -14350.8848 -14071.9395 -14137.5088 -14424.7549 -14566.8164 -14338.7158 -14063.4072 -14126.2383 -14422.2910 -14556.0957 -14333.2959 -14055.4521 -14117.7451 -14409.4873 -14565.6182 -14342.4697 -14060.2979 -14137.9111 -14426.2500 -14572.4570 -14341.4844 -14053.8955 -14121.1611 -14409.2568 -14559.9961 -14330.4053 -14050.2627 -14122.4199 -14433.0908 -14567.5186 -14338.4268 -14053.8213 -14115.0518 -14413.6074 -14558.2773 -14334.5742 -14049.4277 +-13067.8711 -12779.6631 -12812.5664 -13094.8633 -13270.5361 -13081.7578 -12788.0479 -12821.2686 -13096.5176 -13276.9805 -13094.4346 -12794.4014 -12832.1768 -13124.5293 -13291.7129 -13099.1162 -12798.7773 -12831.7051 -13134.4443 -13316.4414 -13125.5771 -12834.8721 -12863.5283 -13149.9717 -13315.2539 -13120.8398 -12833.2939 -12865.4756 -13154.0889 -13333.9336 -13136.1406 -12838.3301 -12873.5645 -13163.5176 -13335.3838 -13143.4805 -12845.8105 -12882.0732 -13163.1016 -13340.7686 -13131.3066 -12841.9678 -12873.3438 -13151.8633 -13316.1641 -13127.8682 -12835.8086 -12869.1582 -13156.0488 -13312.7529 -13124.3555 -12833.5391 -12857.1543 -13135.7363 -13309.4131 -13124.6416 -12832.0713 -12871.3145 -13146.9551 -13324.5830 -13125.5049 -12827.3369 -12859.1787 -13135.2324 -13308.8887 -13112.8516 -12821.5322 -12859.0674 -13158.1484 -13316.7656 -13116.7607 -12820.9805 -12849.6523 -13139.7119 -13316.3701 -13126.6465 -12822.2646 +-12043.2041 -11769.7988 -11823.8662 -12101.8506 -12257.5547 -12049.7959 -11777.5830 -11835.7725 -12111.7373 -12264.9219 -12063.1309 -11784.8887 -11843.7207 -12128.7891 -12272.8740 -12062.8301 -11784.7725 -11842.7832 -12134.7637 -12295.6045 -12084.4727 -11809.0400 -11863.9824 -12141.2764 -12288.5176 -12076.6250 -11806.0195 -11859.4014 -12151.2354 -12303.8467 -12086.3340 -11806.9053 -11862.4229 -12147.0664 -12299.6748 -12090.9023 -11814.1299 -11870.7725 -12149.5127 -12305.3896 -12088.9258 -11815.3203 -11869.2031 -12146.5830 -12293.7158 -12083.7939 -11810.4678 -11867.2363 -12147.7314 -12288.6953 -12078.3516 -11807.8203 -11861.0039 -12138.4355 -12289.7051 -12084.4463 -11808.2998 -11870.8848 -12146.2939 -12294.7783 -12085.5117 -11806.3857 -11860.6396 -12137.7002 -12288.1064 -12076.3887 -11802.9424 -11862.0713 -12150.4424 -12293.0410 -12075.4766 -11802.4355 -11858.2129 -12142.9521 -12296.5352 -12087.5273 -11802.7100 +-9939.3350 -9693.2236 -9780.7168 -10049.7393 -10170.7197 -9939.8242 -9693.5557 -9786.0107 -10053.3525 -10171.5176 -9946.3779 -9700.0439 -9788.5596 -10063.8584 -10177.1553 -9949.4590 -9701.9570 -9792.2598 -10074.6865 -10195.0898 -9962.2852 -9715.7158 -9802.8926 -10074.0996 -10185.2549 -9955.4160 -9712.9160 -9799.8096 -10082.9453 -10199.5400 -9960.6230 -9715.8477 -9801.6250 -10073.2979 -10192.1885 -9960.4131 -9715.7861 -9807.9150 -10077.2461 -10194.9033 -9961.4590 -9713.4414 -9802.3320 -10072.3223 -10188.6680 -9956.1777 -9713.0488 -9805.6670 -10076.4297 -10188.3994 -9954.4492 -9707.5566 -9803.8184 -10068.6455 -10183.5352 -9953.8789 -9711.5918 -9806.3076 -10073.6523 -10189.7920 -9959.3779 -9714.9326 -9803.8867 -10069.7100 -10185.7441 -9951.9297 -9707.7490 -9802.2803 -10075.5732 -10187.6592 -9949.4551 -9713.3457 -9805.3936 -10075.1963 -10191.1523 -9964.0488 -9709.7529 +-4148.1167 -3918.5317 -3993.2751 -4236.5469 -4350.4795 -4145.9341 -3917.9387 -3996.9487 -4241.5640 -4350.6650 -4152.6440 -3924.1230 -4001.0232 -4246.0879 -4355.0039 -4155.4751 -3925.4902 -4002.1206 -4254.4419 -4366.7725 -4162.8711 -3932.7695 -4009.6487 -4253.3682 -4359.0552 -4156.9146 -3932.2422 -4006.5002 -4262.1274 -4371.9639 -4162.5723 -3937.5320 -4008.3679 -4252.5879 -4364.7529 -4159.8340 -3932.7871 -4012.8411 -4258.6973 -4367.9575 -4160.7632 -3933.5305 -4012.2458 -4255.3916 -4364.9521 -4157.7036 -3931.9766 -4012.3875 -4254.8765 -4365.1079 -4156.9541 -3930.2371 -4009.2522 -4251.6475 -4360.0425 -4157.8032 -3934.6047 -4011.7583 -4253.9565 -4365.2983 -4159.5244 -3936.3264 -4010.6785 -4252.6108 -4361.2598 -4153.6709 -3927.4233 -4009.3562 -4251.2612 -4363.6362 -4150.0688 -3933.6084 -4012.0188 -4257.1611 -4366.8867 -4163.2178 -3931.5073 +204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 204439.4219 +-3354.4636 -3167.1958 -3224.3621 -3416.0168 -3510.2139 -3349.6655 -3164.0708 -3225.5095 -3419.3494 -3506.7886 -3353.6389 -3172.6238 -3228.5823 -3421.9036 -3511.3398 -3357.3901 -3172.1372 -3230.8154 -3427.7749 -3516.9834 -3359.4153 -3172.7908 -3231.6001 -3424.8884 -3510.9319 -3355.9082 -3174.2339 -3231.0054 -3432.3354 -3520.4856 -3360.5615 -3179.0754 -3231.9253 -3422.7815 -3513.3823 -3357.0332 -3171.2302 -3236.5872 -3430.1882 -3516.0959 -3359.6951 -3175.1035 -3238.4822 -3427.5488 -3517.4705 -3358.4758 -3174.6021 -3237.7004 -3425.9509 -3517.9321 -3357.1282 -3171.5911 -3236.1201 -3425.1614 -3510.5759 -3358.2258 -3174.3040 -3233.5083 -3424.0259 -3513.2917 -3356.9998 -3180.4419 -3237.2024 -3427.6194 -3511.7375 -3352.5576 -3169.3181 -3232.8665 -3418.7908 -3515.4675 -3349.2493 -3177.4539 -3238.3835 -3430.1323 -3516.3142 -3357.8311 -3172.7969 +204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 204478.1250 +3116.9377 3073.5315 3090.3916 3158.3435 3186.7112 3118.6072 3074.5015 3091.6033 3156.6599 3187.5100 3116.7000 3071.7705 3089.7810 3157.0525 3185.0471 3116.6013 3072.6995 3089.3604 3156.1040 3184.1499 3115.8608 3072.2002 3090.1821 3156.2632 3184.8735 3113.6946 3070.4241 3088.7996 3154.3752 3183.2129 3112.3235 3070.1809 3087.7769 3155.5366 3182.1433 3111.8623 3067.4102 3085.5227 3151.6572 3180.9246 3110.1091 3065.4790 3084.5229 3152.7542 3181.1489 3111.4854 3067.4553 3083.5222 3151.7395 3179.4033 3110.2617 3067.1011 3084.4707 3152.6084 3181.1765 3109.1057 3065.7197 3087.0278 3152.2161 3180.3201 3111.5042 3065.3027 3083.8071 3149.4680 3179.3472 3109.4966 3066.4915 3084.4541 3153.1794 3179.0625 3109.0698 3065.2058 3083.0347 3150.4609 3180.1897 3107.5825 3066.2620 +-12826.1484 -12560.0840 -12636.3838 -12932.6631 -13076.3193 -12840.0605 -12568.9619 -12658.2158 -12952.1416 -13103.0342 -12867.1074 -12584.2939 -12674.7393 -12985.6094 -13115.0000 -12874.5820 -12593.7754 -12681.2051 -12999.0117 -13153.7139 -12911.0947 -12635.8770 -12721.0791 -13018.8701 -13159.7773 -12911.7119 -12640.3633 -12722.0957 -13032.5830 -13181.0293 -12929.7139 -12643.4121 -12728.6807 -13039.8496 -13186.4980 -12938.0459 -12657.5645 -12743.5303 -13040.7197 -13193.5439 -12937.4355 -12660.2656 -12739.7578 -13034.9189 -13168.8340 -12925.5342 -12647.9873 -12728.7891 -13028.4785 -13156.1670 -12917.1807 -12645.6455 -12721.0527 -13012.3223 -13157.5830 -12919.3291 -12639.6055 -12729.9844 -13022.3965 -13158.5566 -12914.5391 -12630.9541 -12715.5508 -13007.5850 -13150.2656 -12899.2578 -12623.1553 -12710.0547 -13021.4063 -13148.9209 -12909.5918 -12628.2266 -12709.9180 -13010.7070 -13147.9219 -12905.8125 -12617.9404 +-16180.3789 -15921.3545 -16008.5029 -16299.4131 -16433.5000 -16186.9453 -15925.9268 -16026.1416 -16310.9727 -16447.4980 -16204.1699 -15936.1230 -16037.1943 -16335.9316 -16453.8477 -16207.1563 -15936.7441 -16035.5762 -16343.5059 -16483.0176 -16233.8076 -15969.2715 -16062.4863 -16351.2031 -16480.4512 -16229.5703 -15967.9102 -16060.6563 -16365.3867 -16498.0137 -16239.2568 -15968.4053 -16063.3047 -16366.1982 -16498.0449 -16245.2256 -15979.9961 -16075.7783 -16367.1963 -16505.3340 -16246.5703 -15981.1563 -16071.0557 -16363.0986 -16488.0840 -16235.8867 -15969.7070 -16062.5811 -16359.2979 -16479.3945 -16230.7725 -15969.4102 -16059.4238 -16346.5244 -16477.9336 -16233.5957 -15965.2705 -16065.4326 -16353.6807 -16483.8613 -16234.8857 -15968.3438 -16061.7549 -16348.1973 -16476.1445 -16223.4736 -15960.8828 -16055.8721 -16360.1943 -16473.8398 -16225.2168 -15958.5830 -16054.3359 -16349.1934 -16477.8691 -16233.5273 -15957.0820 +-11567.9170 -11291.7998 -11362.7656 -11651.2246 -11801.8760 -11570.0859 -11298.2783 -11372.1973 -11660.5479 -11805.8652 -11581.7910 -11303.0518 -11378.6816 -11672.4326 -11811.0469 -11584.7764 -11305.9922 -11379.9609 -11685.6445 -11832.5391 -11605.0400 -11328.4434 -11398.7461 -11685.2920 -11824.4922 -11596.6318 -11325.9502 -11390.4521 -11699.0273 -11843.7861 -11603.3623 -11327.9463 -11397.0313 -11688.3936 -11837.7568 -11604.7959 -11328.3594 -11403.4912 -11692.7783 -11836.7998 -11606.1357 -11327.9502 -11399.7402 -11689.1602 -11830.6768 -11597.9971 -11320.5693 -11396.5869 -11689.0703 -11828.7695 -11595.2881 -11320.8066 -11395.4717 -11679.1318 -11822.4424 -11596.8555 -11321.6934 -11395.4629 -11683.0176 -11829.4844 -11601.1367 -11326.6094 -11394.9541 -11680.1719 -11822.8896 -11588.9775 -11314.1475 -11389.2979 -11686.4668 -11826.7432 -11584.8828 -11318.3750 -11393.3994 -11683.8203 -11829.2324 -11601.0039 -11317.1143 +-6358.0713 -6091.8379 -6178.3379 -6460.8359 -6599.4702 -6354.8228 -6091.7012 -6181.0679 -6465.3096 -6594.1162 -6365.1885 -6105.0762 -6187.9502 -6471.3569 -6602.0557 -6370.8960 -6105.1777 -6187.8257 -6483.8315 -6616.2778 -6378.3130 -6111.5830 -6199.3354 -6483.5112 -6606.5098 -6373.6802 -6112.4668 -6192.9521 -6496.4282 -6622.8066 -6377.5718 -6121.7661 -6198.9512 -6479.4077 -6615.4185 -6377.6533 -6115.8813 -6207.4893 -6495.2939 -6621.9063 -6386.3789 -6120.6060 -6210.0308 -6491.2822 -6623.3838 -6381.3604 -6116.9497 -6207.9023 -6483.9341 -6619.6743 -6375.6108 -6108.3213 -6203.8638 -6483.9946 -6608.3726 -6375.0889 -6114.5459 -6203.2324 -6483.4756 -6616.8442 -6381.0015 -6123.6108 -6202.1934 -6481.5068 -6611.2798 -6371.0845 -6108.0376 -6201.4785 -6481.1631 -6619.2729 -6363.2495 -6121.7056 -6208.7534 -6491.3335 -6621.8359 -6386.3008 -6117.1641 +-194.5330 19.8748 -58.8307 -290.1855 -393.6491 -189.8461 22.6635 -61.4236 -295.7708 -391.3524 -195.9999 12.9349 -65.1472 -298.2761 -396.7082 -199.5598 12.2660 -67.9403 -304.7816 -404.5864 -204.3642 10.6782 -71.0473 -304.3150 -397.9807 -200.5101 9.2634 -69.2245 -313.1916 -407.8352 -203.0276 2.9759 -71.7023 -299.9834 -401.3818 -202.8124 12.2722 -79.1371 -308.9559 -404.1696 -205.4163 7.3073 -77.3400 -306.1469 -406.1680 -201.0361 11.0093 -78.3932 -305.3652 -406.0227 -199.4828 14.0004 -73.8148 -303.5055 -395.0439 -199.8673 8.6546 -72.7669 -304.3812 -401.9313 -201.6677 2.6884 -75.0125 -303.3672 -396.9096 -195.0106 15.5185 -71.4940 -295.6487 -404.0515 -187.7411 5.9499 -79.0123 -308.2534 -402.2356 -203.4908 11.8622 +-3570.4736 -3341.5474 -3409.9011 -3644.5017 -3760.4011 -3558.7935 -3330.1982 -3403.6921 -3645.0657 -3752.0352 -3559.3770 -3338.1663 -3405.8523 -3643.0337 -3754.7749 -3560.0674 -3331.5896 -3402.5356 -3644.4653 -3753.9080 -3558.7639 -3325.4971 -3396.2664 -3635.6133 -3741.4846 -3551.6409 -3323.9829 -3394.3779 -3645.3381 -3751.3459 -3551.2168 -3329.2188 -3392.2881 -3626.2629 -3738.8525 -3545.7317 -3316.1436 -3398.2715 -3635.7532 -3740.7788 -3544.0618 -3320.8308 -3396.9741 -3631.9031 -3740.2202 -3537.6975 -3309.2563 -3386.6602 -3619.4551 -3732.5574 -3527.4282 -3299.8711 -3378.3794 -3613.2991 -3714.5688 -3525.2759 -3300.9707 -3366.9939 -3605.3772 -3715.0503 -3520.2778 -3304.4250 -3370.9919 -3604.5769 -3706.3735 -3508.9285 -3283.3972 -3360.7695 -3587.8621 -3710.3508 -3496.0806 -3291.4214 -3366.0466 -3600.1736 -3707.7114 -3509.1077 -3283.5479 +-4765.6416 -4546.9746 -4594.1865 -4809.7573 -4928.7173 -4761.0747 -4540.9663 -4593.5869 -4816.4248 -4924.1914 -4764.8813 -4551.8022 -4598.3618 -4817.3452 -4932.4146 -4769.4473 -4550.1797 -4600.2397 -4820.8521 -4932.4507 -4768.7407 -4548.0864 -4598.7788 -4818.6108 -4929.7764 -4769.8071 -4552.6470 -4602.1509 -4827.7925 -4939.0098 -4771.2920 -4557.6743 -4602.8066 -4815.5869 -4930.3213 -4766.9590 -4547.7109 -4610.2441 -4825.9795 -4932.6548 -4769.5391 -4555.1143 -4610.1958 -4823.9863 -4934.6362 -4766.5488 -4550.0420 -4608.6406 -4822.5713 -4938.2148 -4764.5703 -4546.4434 -4605.9673 -4819.9414 -4926.3037 -4766.4390 -4550.2744 -4596.6143 -4814.6890 -4929.2261 -4763.4370 -4560.6294 -4608.4409 -4820.9336 -4928.1338 -4760.7866 -4543.1699 -4600.3447 -4805.5190 -4930.9561 -4753.2705 -4553.1001 -4608.9458 -4822.5625 -4932.3301 -4765.3032 -4549.6255 +-4109.2388 -4005.9973 -4024.7649 -4116.5918 -4168.7920 -4106.7417 -4002.1602 -4024.0962 -4119.1743 -4170.4590 -4108.2412 -4008.3198 -4026.0820 -4119.6777 -4171.5498 -4109.4468 -4003.6516 -4024.6887 -4117.6685 -4170.1162 -4108.5454 -4002.8230 -4021.7578 -4115.6426 -4169.0083 -4110.0483 -4005.9744 -4022.9092 -4118.9033 -4170.5195 -4108.4385 -4005.6169 -4024.0415 -4115.4434 -4169.9448 -4108.5972 -4005.9192 -4028.2051 -4119.7183 -4169.7700 -4108.3960 -4008.7454 -4029.7000 -4121.1128 -4169.4194 -4106.9639 -4002.8218 -4025.2510 -4117.7510 -4174.4194 -4107.1089 -4007.0950 -4029.9875 -4118.9829 -4167.8418 -4105.9717 -4003.8369 -4019.7437 -4112.5503 -4165.7495 -4105.0430 -4010.8682 -4030.2537 -4122.3813 -4169.4268 -4106.3823 -4003.1067 -4024.6155 -4112.2529 -4169.6631 -4105.5322 -4006.7903 -4028.6152 -4120.1914 -4168.1758 -4106.3745 -4004.3787 +-11942.4268 -11676.7813 -11756.2998 -12057.1240 -12198.0244 -11950.1221 -11679.8955 -11776.5723 -12074.7305 -12225.4434 -11978.8145 -11691.8418 -11791.3223 -12105.2461 -12227.4580 -11978.7012 -11691.2119 -11789.9092 -12113.5049 -12265.5859 -12010.9854 -11732.4951 -11821.6973 -12123.0273 -12262.3115 -12006.5967 -11730.1553 -11818.4844 -12137.0049 -12281.1709 -12023.7637 -11736.4082 -11824.7188 -12145.2178 -12287.1221 -12027.2861 -11746.8955 -11838.7803 -12138.7402 -12294.4736 -12026.7148 -11748.5010 -11833.1592 -12139.5742 -12267.1904 -12011.7891 -11732.4492 -11817.5537 -12126.0293 -12253.3994 -12010.7695 -11738.7256 -11816.0635 -12113.3486 -12257.1738 -12008.0605 -11722.9043 -11819.2217 -12115.2666 -12259.1113 -12005.3174 -11727.1152 -11813.4805 -12110.4580 -12250.9307 -11989.2646 -11710.7754 -11800.1406 -12121.9521 -12244.5674 -11996.5742 -11716.8906 -11810.4863 -12110.0410 -12244.2197 -12002.3418 -11710.2813 +-12098.0781 -11820.9365 -11897.7734 -12195.1582 -12343.3379 -12093.1133 -11824.2930 -11916.5049 -12210.2197 -12354.1143 -12111.4248 -11833.3750 -11926.8105 -12228.3701 -12353.2031 -12115.7197 -11831.1436 -11920.9443 -12235.6279 -12378.6172 -12138.1631 -11863.0205 -11949.0918 -12237.4795 -12378.1211 -12135.5625 -11857.8857 -11933.1748 -12249.3857 -12390.1230 -12136.6689 -11860.0596 -11943.4971 -12248.2363 -12392.3242 -12142.1670 -11870.5439 -11952.0010 -12245.8848 -12392.2305 -12147.5859 -11867.9629 -11944.2939 -12247.5781 -12384.4980 -12136.5703 -11855.4385 -11941.7891 -12248.1445 -12372.5264 -12119.3506 -11853.7715 -11944.3428 -12226.6729 -12370.8564 -12127.3301 -11851.2793 -11937.7158 -12230.3115 -12378.2354 -12135.4746 -11861.3955 -11939.1094 -12234.4355 -12361.9307 -12119.3750 -11841.4063 -11927.8926 -12234.2344 -12368.3301 -12125.1855 -11842.7852 -11933.0117 -12234.3965 -12370.6025 -12132.3359 -11846.3096 +-6266.3066 -5982.4731 -6078.3657 -6367.2354 -6523.0122 -6260.7832 -5992.2959 -6087.8809 -6387.4131 -6513.1479 -6273.2466 -6003.7861 -6086.8013 -6376.3921 -6517.8696 -6282.0630 -6013.7280 -6095.9321 -6409.4912 -6535.9238 -6294.1182 -6017.4038 -6105.7061 -6405.4229 -6525.7271 -6295.4746 -6021.7280 -6089.9219 -6419.2026 -6547.7285 -6285.3438 -6030.4375 -6110.4521 -6398.0269 -6538.4731 -6292.1616 -6021.3408 -6110.4194 -6411.9873 -6538.6294 -6297.1924 -6015.4937 -6113.6802 -6404.5732 -6541.2290 -6287.6196 -6009.7124 -6105.7583 -6405.4917 -6545.7085 -6279.0869 -5997.5137 -6108.8882 -6399.7681 -6523.7285 -6288.0249 -6019.1182 -6103.8643 -6397.3013 -6537.3579 -6296.8071 -6030.0034 -6103.3052 -6382.1621 -6522.7134 -6276.2690 -6006.7119 -6103.7891 -6387.6284 -6532.3320 -6248.6987 -6017.6543 -6106.6387 -6399.6274 -6534.0313 -6293.0967 -6012.0371 +-5173.8931 -4926.7573 -5012.7461 -5282.6548 -5420.6973 -5170.2124 -4918.3711 -5015.0059 -5305.1284 -5407.5439 -5177.4951 -4935.1909 -5018.6157 -5295.4282 -5418.9150 -5191.7324 -4939.2090 -5024.9424 -5311.2798 -5428.0835 -5189.5566 -4934.0449 -5032.5923 -5310.9033 -5416.9570 -5193.5469 -4939.0654 -5030.0195 -5320.4253 -5428.2261 -5185.8569 -4954.4092 -5034.7783 -5298.5088 -5419.2866 -5190.9863 -4932.6123 -5049.4380 -5313.5947 -5419.5674 -5190.3438 -4941.3799 -5046.4185 -5304.7090 -5427.9146 -5182.3784 -4931.4536 -5049.4155 -5308.5972 -5427.8530 -5177.3159 -4923.7212 -5039.1450 -5304.3711 -5404.1348 -5188.5298 -4941.2246 -5025.5933 -5307.6050 -5424.7417 -5185.3579 -4959.5996 -5035.8604 -5297.1611 -5407.1133 -5178.5669 -4926.6802 -5035.0889 -5280.1729 -5425.7681 -5150.5234 -4941.8433 -5042.5244 -5308.4668 -5419.2139 -5183.1836 -4932.0093 +-6520.0288 -6264.6387 -6346.4214 -6624.4424 -6762.9663 -6516.5444 -6254.8306 -6348.9922 -6644.2637 -6754.0420 -6522.7798 -6273.9990 -6354.2656 -6637.0532 -6764.3599 -6536.8486 -6273.9238 -6360.3672 -6650.2163 -6769.5352 -6535.8115 -6269.6069 -6362.8877 -6644.4502 -6767.2056 -6536.4941 -6272.5820 -6361.3096 -6655.0654 -6772.6704 -6530.6504 -6284.8203 -6366.7974 -6635.7817 -6765.1143 -6530.9663 -6267.2695 -6379.8101 -6650.9326 -6763.0503 -6532.2944 -6278.0537 -6374.4331 -6646.8936 -6769.5845 -6525.6357 -6265.0815 -6377.8618 -6647.9565 -6773.7964 -6519.9727 -6256.7798 -6368.1958 -6640.3354 -6748.9785 -6531.2544 -6275.7715 -6353.5322 -6644.2930 -6764.3862 -6526.6792 -6291.1465 -6369.6899 -6637.6323 -6750.4590 -6521.8979 -6259.3677 -6366.3384 -6617.1055 -6769.0176 -6496.4614 -6274.1025 -6373.4712 -6644.9629 -6761.9746 -6524.7207 -6266.1396 +-6726.9829 -6490.1235 -6548.6777 -6791.5889 -6913.6787 -6727.5430 -6478.1250 -6552.0527 -6796.6064 -6921.3198 -6727.3872 -6495.0337 -6555.3687 -6804.4976 -6920.8892 -6728.9019 -6487.1152 -6564.0229 -6802.5454 -6921.9780 -6737.5171 -6483.6069 -6550.5063 -6798.6821 -6918.7451 -6732.5615 -6490.2769 -6553.8999 -6806.4038 -6922.2437 -6730.4673 -6493.0059 -6557.2935 -6795.0107 -6925.8813 -6724.0215 -6487.6738 -6565.6538 -6808.4312 -6917.4551 -6729.2920 -6495.6367 -6567.5176 -6810.3745 -6916.0713 -6723.2227 -6485.0708 -6561.4263 -6804.4644 -6933.4492 -6716.7417 -6482.6680 -6559.0229 -6800.5889 -6914.3545 -6723.1396 -6496.0947 -6543.1196 -6791.9404 -6916.4077 -6719.6191 -6500.1021 -6562.8818 -6804.0786 -6912.9917 -6722.8965 -6479.3306 -6555.0610 -6780.0557 -6917.1602 -6712.7456 -6487.4683 -6560.3711 -6802.3906 -6916.6699 -6721.3271 -6487.5762 +-8651.2988 -8403.8330 -8430.4277 -8665.9111 -8804.5430 -8642.8018 -8394.0996 -8434.9336 -8672.3926 -8810.9658 -8649.2402 -8403.4365 -8436.5215 -8673.9150 -8810.0781 -8646.8584 -8393.5020 -8435.6328 -8669.9053 -8808.5195 -8647.9014 -8391.6885 -8428.9102 -8664.2881 -8805.7529 -8652.3037 -8397.4893 -8430.2441 -8670.2383 -8805.5488 -8647.7266 -8399.0713 -8434.2021 -8662.6563 -8810.3379 -8644.8545 -8400.2314 -8441.4492 -8675.7051 -8804.2754 -8648.2393 -8403.1260 -8441.8184 -8677.0752 -8805.7715 -8643.1230 -8393.1318 -8435.9385 -8671.6133 -8818.6006 -8640.2197 -8398.4209 -8439.7734 -8673.1689 -8804.7383 -8641.7539 -8395.0439 -8421.5107 -8660.6426 -8801.1348 -8638.9004 -8407.4873 -8443.7041 -8675.5752 -8804.0693 -8643.3135 -8391.1924 -8430.0928 -8655.5918 -8805.7051 -8640.1104 -8396.9395 -8440.1162 -8671.0234 -8805.1338 -8639.9678 -8397.6133 +-13120.4727 -12881.2178 -12957.3184 -13285.1533 -13386.4834 -13121.9336 -12865.5684 -12994.1689 -13284.6543 -13415.5859 -13154.1807 -12866.2813 -13008.0508 -13310.0225 -13400.2861 -13163.2139 -12854.7754 -12992.4922 -13297.2148 -13432.9834 -13175.0859 -12907.3594 -12996.3984 -13310.1055 -13437.6035 -13179.3525 -12896.9111 -13010.9775 -13324.8555 -13451.0586 -13162.3232 -12895.2314 -12994.9385 -13332.7432 -13448.7109 -13192.8896 -12926.9512 -13017.2324 -13303.3799 -13457.6777 -13186.4492 -12916.2363 -12992.4443 -13322.5791 -13425.4336 -13157.8008 -12905.9512 -12993.9922 -13312.9941 -13427.9834 -13145.0771 -12916.7607 -12993.0449 -13282.2500 -13422.1035 -13144.2930 -12875.5137 -12999.0234 -13286.2832 -13428.1152 -13161.9980 -12898.8350 -13006.2480 -13296.2695 -13407.8984 -13132.4873 -12871.3691 -12968.0283 -13287.0039 -13414.2578 -13164.4619 -12859.3037 -13005.8086 -13285.4268 -13393.9648 -13153.9248 -12871.9707 +-9870.7900 -9606.4795 -9711.8623 -9984.0410 -10141.6768 -9865.7754 -9610.3184 -9733.5176 -10017.6631 -10149.1787 -9889.2090 -9621.3389 -9736.4658 -10017.0967 -10155.9541 -9866.6748 -9619.5801 -9715.8447 -10033.9961 -10158.3701 -9910.4414 -9652.6611 -9742.3633 -10033.8984 -10204.1006 -9925.7314 -9653.4922 -9715.2158 -10039.4824 -10179.9199 -9890.6260 -9633.2041 -9740.8750 -10026.9795 -10176.1973 -9902.9883 -9669.8623 -9732.4990 -10028.2422 -10152.5654 -9921.5430 -9646.9121 -9716.1338 -10040.4033 -10162.8135 -9929.6270 -9626.9883 -9784.7773 -10089.9277 -10157.9697 -9868.4609 -9606.4209 -9761.1895 -10009.9336 -10171.3516 -9884.2471 -9636.2305 -9719.1006 -10037.6035 -10155.7490 -9905.6934 -9651.8311 -9735.8359 -10061.0283 -10118.4443 -9912.3340 -9601.3555 -9717.4150 -10019.6074 -10140.3594 -9921.9600 -9597.5342 -9699.2529 -10029.0498 -10147.8154 -9904.0439 -9626.0361 +-9244.3916 -8999.0049 -9085.6758 -9364.3965 -9510.4941 -9239.7695 -8987.6240 -9083.6182 -9394.6250 -9488.2070 -9250.4697 -9005.3184 -9090.0283 -9376.1416 -9503.4785 -9268.9922 -9012.3311 -9096.8789 -9398.1934 -9506.9072 -9266.0459 -9000.4961 -9105.4082 -9392.3867 -9502.8145 -9272.0928 -9007.2324 -9104.8418 -9397.3623 -9512.3086 -9258.3760 -9023.3604 -9112.1035 -9376.8857 -9497.5811 -9263.3096 -9001.5967 -9126.1318 -9392.7217 -9500.6563 -9261.9971 -9012.2021 -9120.9658 -9384.7881 -9508.2041 -9255.8301 -8997.2676 -9129.9121 -9399.3691 -9507.7891 -9244.4160 -8984.2998 -9114.3545 -9381.2646 -9481.0957 -9268.5713 -9006.9678 -9092.2588 -9391.5342 -9505.0205 -9259.1113 -9039.6221 -9111.0732 -9374.4658 -9480.7793 -9252.6826 -8994.3662 -9109.4346 -9354.5840 -9510.6348 -9214.2148 -9010.9668 -9117.5352 -9390.1729 -9497.4717 -9250.8643 -8995.9150 +-11280.5352 -11030.1621 -11112.2715 -11392.3691 -11526.9033 -11274.3926 -11014.2314 -11123.7021 -11418.2275 -11521.2539 -11280.9697 -11034.1572 -11123.9502 -11412.8535 -11527.2305 -11296.0801 -11026.1504 -11126.9746 -11416.9170 -11557.4473 -11288.3877 -11024.6455 -11125.7256 -11410.1025 -11533.7168 -11292.4365 -11031.2588 -11128.2295 -11421.1787 -11532.7852 -11291.5117 -11048.8135 -11130.0615 -11403.9629 -11550.6797 -11276.7627 -11026.6475 -11153.8818 -11418.3779 -11522.1748 -11289.4355 -11044.4346 -11150.5879 -11417.8438 -11534.0713 -11280.2363 -11022.8252 -11150.2412 -11425.5176 -11553.0586 -11261.8545 -11021.3672 -11135.5635 -11407.3916 -11516.6699 -11280.7109 -11043.2285 -11115.1650 -11417.3447 -11526.9531 -11279.8809 -11053.5361 -11137.8076 -11406.2080 -11512.2334 -11292.6289 -11007.2559 -11129.3584 -11378.7266 -11535.9150 -11260.4775 -11024.1953 -11141.2031 -11412.5850 -11522.0332 -11276.5791 -11025.0020 +-12976.5537 -12724.5313 -12803.2637 -13069.8789 -13192.8936 -12977.0332 -12709.5869 -12805.7295 -13074.6895 -13204.9932 -12976.4775 -12729.1289 -12809.2031 -13087.0693 -13200.9189 -12974.8896 -12719.5645 -12824.4922 -13079.7959 -13204.5186 -12989.2754 -12715.5049 -12804.2588 -13075.7852 -13203.3896 -12980.9434 -12723.2402 -12805.6475 -13086.2813 -13202.7139 -12976.9453 -12723.5977 -12810.4746 -13075.5342 -13214.3633 -12968.1094 -12720.3584 -12821.2744 -13089.7607 -13198.4492 -12978.6875 -12731.2686 -12822.3301 -13096.6377 -13192.8213 -12972.0479 -12717.1406 -12816.2969 -13084.1602 -13222.3086 -12960.2520 -12714.6328 -12811.1475 -13081.7803 -13194.9072 -12972.3320 -12737.5195 -12792.7158 -13073.0059 -13198.9238 -12966.1768 -12733.7520 -12817.4961 -13085.3584 -13194.2979 -12973.9287 -12711.2002 -12810.5449 -13057.9189 -13196.3076 -12962.4531 -12718.1592 -12814.3564 -13081.2832 -13198.2021 -12968.9189 -12720.5176 +-12066.0635 -11827.4629 -11895.5518 -12145.7617 -12263.4707 -12057.0879 -11813.9219 -11897.2773 -12151.3906 -12272.1260 -12065.2822 -11826.4434 -11894.4521 -12151.7764 -12267.1016 -12059.6533 -11813.9951 -11897.2363 -12146.7451 -12264.6768 -12061.4717 -11811.6338 -11888.3340 -12139.5273 -12265.3467 -12065.9844 -11814.6426 -11885.8633 -12141.8340 -12259.4170 -12055.1152 -11814.4023 -11890.1943 -12137.8125 -12265.3428 -12055.7344 -11818.9629 -11897.2480 -12152.0801 -12261.4512 -12057.9072 -11821.7500 -11900.5215 -12150.6094 -12260.1348 -12053.1934 -11810.7510 -11893.4121 -12145.9629 -12275.1934 -12050.3457 -11812.9844 -11897.3770 -12146.8369 -12261.0527 -12050.6514 -11811.2451 -11880.3398 -12135.2451 -12257.3438 -12048.5088 -11825.7461 -11901.5811 -12150.8320 -12258.0811 -12050.8867 -11807.0996 -11888.4785 -12131.5166 -12258.6514 -12050.7803 -11809.4785 -11895.2305 -12148.0645 -12257.7920 -12050.0986 -11814.0645 +-10331.9795 -10106.2939 -10190.7598 -10481.8125 -10596.4248 -10323.1240 -10151.1123 -10221.5840 -10527.4189 -10650.2725 -10359.5107 -10091.9600 -10227.2656 -10544.5430 -10608.2676 -10338.2002 -10077.3311 -10249.2588 -10556.9521 -10681.6572 -10379.7930 -10123.3213 -10263.8936 -10546.6914 -10661.4023 -10358.2061 -10068.8330 -10256.6348 -10554.1592 -10681.6592 -10385.9834 -10127.2500 -10260.3457 -10566.4883 -10681.1064 -10392.5254 -10076.8418 -10248.6035 -10576.0605 -10673.9912 -10360.9766 -10118.4453 -10278.9463 -10554.7070 -10672.3926 -10358.9150 -10147.9561 -10209.7617 -10536.9189 -10644.1250 -10364.7773 -10149.4482 -10219.7373 -10536.5586 -10648.1074 -10364.0596 -10071.7021 -10215.2695 -10530.4961 -10668.3438 -10380.1279 -10123.1465 -10221.1582 -10519.2656 -10654.6631 -10328.6768 -10105.5039 -10213.1865 -10565.3125 -10630.5996 -10336.4004 -10105.6113 -10203.7861 -10553.5693 -10638.3281 -10369.2051 -10132.4561 +-13539.3467 -13287.5645 -13391.5332 -13721.0830 -13835.5850 -13581.0801 -13308.1182 -13494.2813 -13744.6670 -13848.7178 -13585.5703 -13312.9971 -13477.8545 -13769.7080 -13823.2031 -13591.0488 -13328.5664 -13445.4180 -13732.7031 -13863.2393 -13612.2246 -13342.9561 -13418.5098 -13757.0322 -13885.1846 -13640.2949 -13350.8174 -13440.3330 -13764.2412 -13883.7227 -13569.9473 -13331.5371 -13423.6689 -13791.5068 -13900.5342 -13648.7559 -13413.7002 -13452.4561 -13737.8848 -13859.5176 -13668.9238 -13337.7158 -13422.4424 -13785.8223 -13854.4668 -13602.6201 -13341.5010 -13476.7080 -13730.4082 -13912.6641 -13579.5068 -13338.1367 -13483.6797 -13707.0322 -13868.4717 -13571.1338 -13327.8633 -13449.9980 -13740.7598 -13893.5908 -13605.8916 -13323.2031 -13421.7930 -13776.9150 -13866.2275 -13559.2852 -13290.9111 -13436.0225 -13710.2354 -13864.1846 -13606.5127 -13292.3096 -13446.3213 -13725.3320 -13832.3301 -13607.5234 -13313.1143 +-15973.2900 -15721.7295 -15821.2012 -16105.5000 -16236.5391 -15980.7490 -15717.1035 -15834.1787 -16150.0273 -16243.7080 -15979.5352 -15731.1846 -15826.0557 -16126.6025 -16240.5000 -15983.2412 -15745.3359 -15827.4521 -16141.7021 -16251.2285 -16006.2197 -15741.2617 -15846.4209 -16127.6689 -16257.6631 -16032.6787 -15733.3662 -15831.8916 -16137.0586 -16262.1143 -15982.9736 -15740.0752 -15856.5654 -16127.0928 -16248.0771 -15990.9473 -15753.5342 -15850.9121 -16146.9053 -16252.3623 -15993.7773 -15737.7656 -15841.8555 -16149.6377 -16241.4551 -15993.1865 -15713.8203 -15863.6406 -16147.5049 -16270.2695 -15973.4033 -15709.4023 -15859.1865 -16115.4424 -16245.2715 -15974.5508 -15732.6719 -15817.6270 -16123.1279 -16253.8379 -15986.3135 -15759.4307 -15857.7783 -16120.3574 -16218.1963 -15992.3848 -15697.6602 -15840.4209 -16098.3467 -16231.3809 -15977.0430 -15720.5986 -15827.2842 -16130.3535 -16235.9609 -15978.3672 -15716.0508 +-13134.7178 -12886.6699 -12972.3613 -13252.8086 -13381.8779 -13132.1436 -12875.9121 -12985.1113 -13283.6953 -13380.5967 -13141.4805 -12889.1904 -12979.3213 -13267.9775 -13380.0791 -13145.4375 -12885.3770 -12984.4658 -13269.9541 -13402.6123 -13148.7910 -12881.8848 -12986.1855 -13261.9707 -13386.0449 -13156.5098 -12880.5527 -12980.0830 -13268.2910 -13387.9805 -13140.2451 -12895.8105 -12990.8252 -13261.3135 -13395.6064 -13135.8623 -12887.7764 -13002.5371 -13276.5488 -13378.2598 -13143.0137 -12894.1572 -12999.1396 -13277.3135 -13380.4863 -13136.7686 -12875.5684 -13002.0732 -13279.5801 -13405.0889 -13119.2891 -12876.3555 -12998.3018 -13260.4482 -13376.5234 -13129.8584 -12887.6963 -12969.6250 -13270.1172 -13382.3232 -13133.7939 -12908.1895 -12999.5986 -13262.0088 -13365.0781 -13141.0703 -12863.6973 -12984.0625 -13239.2227 -13381.7207 -13125.3301 -12875.2295 -12990.1709 -13271.0781 -13377.1816 -13129.6260 -12878.6709 +-12938.2334 -12697.3789 -12775.6689 -13040.3643 -13159.1182 -12931.2119 -12686.6973 -12784.4688 -13053.0713 -13167.0859 -12941.0361 -12700.3066 -12780.8516 -13051.7236 -13162.5107 -12939.4141 -12688.2969 -12787.4580 -13046.8789 -13171.5684 -12942.3418 -12685.9932 -12778.8613 -13042.3057 -13164.3145 -12946.3857 -12689.3203 -12776.0537 -13046.6846 -13160.6182 -12933.8193 -12693.1953 -12782.4023 -13041.0752 -13172.5820 -12931.0576 -12692.8438 -12792.1807 -13055.1855 -13159.4854 -12939.8379 -12700.3438 -12795.9570 -13055.4619 -13157.4580 -12932.5781 -12685.4922 -12791.1475 -13051.9688 -13180.2197 -12921.9492 -12685.8721 -12788.1318 -13046.4434 -13157.8311 -12929.4336 -12693.4248 -12767.8877 -13043.9619 -13159.2402 -12927.7607 -12706.4287 -12793.1426 -13049.8799 -13154.0498 -12934.0752 -12679.0684 -12780.7510 -13028.7324 -13159.8037 -12929.2314 -12684.1748 -12785.6455 -13051.6006 -13160.0068 -12930.2158 -12689.7344 +-13668.2402 -13429.4150 -13503.2920 -13759.0645 -13876.2607 -13658.8516 -13417.7500 -13507.7207 -13767.0166 -13884.2539 -13667.9844 -13428.9902 -13502.9160 -13766.4355 -13879.5137 -13663.4512 -13416.8076 -13509.3496 -13759.2715 -13879.3750 -13666.5527 -13414.8486 -13498.4766 -13755.2168 -13878.8584 -13671.1123 -13417.0293 -13496.4746 -13757.6572 -13872.2617 -13659.3018 -13419.0098 -13502.4131 -13754.3828 -13881.9121 -13660.1504 -13424.2764 -13509.3809 -13767.9336 -13874.9590 -13664.4287 -13429.2666 -13513.3994 -13769.8213 -13875.0625 -13658.4082 -13416.1328 -13506.8857 -13762.3428 -13891.5713 -13653.6846 -13417.2041 -13510.0205 -13764.3486 -13876.1084 -13657.1982 -13418.1826 -13492.7715 -13755.8262 -13873.6523 -13656.2275 -13432.4570 -13514.0850 -13766.4971 -13873.7344 -13659.8008 -13413.2715 -13503.0732 -13748.9043 -13875.2910 -13657.9121 -13418.2529 -13509.0225 -13768.5908 -13876.5762 -13660.2422 -13422.0781 +-14219.1943 -13966.1680 -14054.4355 -14367.3057 -14488.5215 -14196.8213 -13960.9658 -14092.5586 -14386.7637 -14505.4668 -14244.6299 -13983.5977 -14067.7979 -14356.7676 -14475.4600 -14234.3428 -13966.3828 -14080.4834 -14392.4697 -14534.7598 -14281.5449 -13969.4424 -14073.8506 -14357.4590 -14495.8750 -14256.4316 -13956.3555 -14079.8965 -14409.4766 -14512.0596 -14237.0547 -13975.0264 -14079.0059 -14374.3398 -14511.4063 -14218.9854 -13979.9756 -14102.0498 -14422.3965 -14498.5703 -14235.9189 -13966.9971 -14079.3740 -14397.0996 -14485.5938 -14238.2793 -13974.9902 -14077.8145 -14375.9551 -14514.3838 -14212.7959 -13972.2490 -14065.2041 -14357.9443 -14494.1924 -14208.6826 -13947.5508 -14058.6113 -14378.7598 -14476.5781 -14204.5176 -13994.2588 -14093.9658 -14379.5605 -14470.8486 -14220.2266 -13939.7441 -14074.4658 -14335.7441 -14436.9502 -14204.1270 -13957.5713 -14081.8164 -14389.0137 -14491.4307 -14205.9082 -13946.0342 +-15117.5303 -14866.9932 -14954.4736 -15256.9063 -15379.5859 -15111.6357 -14858.9229 -14982.7041 -15279.8135 -15386.6094 -15130.5479 -14872.7715 -14960.4922 -15258.3301 -15373.3760 -15120.8281 -14870.9199 -14968.7021 -15267.7617 -15402.9902 -15150.2607 -14860.9170 -14969.1494 -15253.2285 -15385.3545 -15144.4053 -14852.1934 -14963.9111 -15271.2881 -15390.2773 -15119.0273 -14871.0908 -14973.3994 -15258.1797 -15393.0566 -15117.4502 -14867.5518 -14981.4746 -15290.3691 -15382.0518 -15124.8828 -14865.0889 -14978.7500 -15278.6475 -15375.8291 -15124.6201 -14860.8789 -14978.3271 -15269.0400 -15405.1875 -15104.6396 -14861.9541 -14980.7559 -15252.0918 -15378.2520 -15107.8350 -14851.5586 -14955.1367 -15266.6318 -15378.4590 -15107.4326 -14883.2939 -14987.2119 -15263.3926 -15363.4932 -15119.2686 -14842.5039 -14970.5801 -15247.7314 -15354.8623 -15107.0771 -14847.6445 -14979.1436 -15277.3154 -15384.5752 -15113.2861 -14855.7852 +-15132.1211 -14884.6182 -14968.8760 -15250.7275 -15372.9727 -15123.4053 -14874.9443 -14981.8994 -15262.0752 -15376.6348 -15133.4297 -14881.4932 -14971.6543 -15251.6143 -15366.6436 -15125.6758 -14870.8213 -14976.6621 -15246.2256 -15372.3613 -15133.2988 -14871.1318 -14968.1748 -15243.3350 -15372.0820 -15140.7510 -14864.2988 -14958.1250 -15241.2861 -15359.9619 -15117.7432 -14872.4922 -14968.7549 -15240.5371 -15372.7734 -15119.9385 -14871.8896 -14972.5635 -15253.5420 -15363.2061 -15125.8896 -14876.9141 -14986.2764 -15252.2295 -15359.2979 -15118.9180 -14862.3779 -14972.1973 -15249.4258 -15383.9033 -15112.3027 -14861.3115 -14973.1729 -15249.3252 -15362.8857 -15114.5293 -14862.3438 -14954.9492 -15244.6104 -15361.8369 -15114.9141 -14880.2520 -14975.4189 -15246.8809 -15354.3252 -15118.6318 -14857.7148 -14963.7529 -15232.7383 -15360.6152 -15119.8887 -14857.2363 -14970.9111 -15257.3975 -15365.6279 -15120.0283 -14870.0869 +-11965.8242 -11728.3916 -11801.5596 -12056.4766 -12173.3994 -11953.0889 -11715.5811 -11803.1113 -12060.9277 -12177.8975 -11962.7656 -11723.7119 -11794.4268 -12057.9658 -12171.9014 -11957.3486 -11712.0742 -11797.9805 -12048.8057 -12170.6035 -11957.1416 -11709.8115 -11792.1895 -12044.7891 -12171.0781 -11966.4023 -11709.1094 -11784.5928 -12042.0781 -12159.6660 -11945.4561 -11708.6084 -11791.3857 -12041.5352 -12170.2451 -11953.6338 -11718.0889 -11794.1992 -12054.5469 -12164.0117 -11955.3125 -11720.7305 -11803.9092 -12056.5928 -12164.8057 -11949.1436 -11708.8867 -11795.2207 -12051.4121 -12179.4678 -11948.3818 -11710.8359 -11798.3115 -12053.2549 -12167.7158 -11949.7646 -11708.8184 -11783.6660 -12045.9678 -12163.2051 -11946.8799 -11723.4766 -11802.2656 -12056.0518 -12164.9951 -11950.5938 -11707.5947 -11793.9063 -12043.6406 -12165.6514 -11951.4473 -11707.1943 -11799.2412 -12058.6846 -12168.7109 -11954.0234 -11715.4922 +-10744.4219 -10509.4482 -10575.0674 -10820.4248 -10936.9766 -10733.0332 -10496.5898 -10576.0654 -10823.7285 -10942.8545 -10740.9502 -10504.9551 -10568.7178 -10820.5156 -10935.5283 -10734.9443 -10492.4932 -10570.3281 -10811.8242 -10933.9824 -10734.7188 -10490.9912 -10564.7783 -10807.3877 -10935.6113 -10743.3926 -10490.8369 -10557.2178 -10806.0703 -10923.4785 -10723.7744 -10489.2441 -10563.7891 -10804.9180 -10933.8037 -10731.5225 -10499.5527 -10567.7754 -10818.0078 -10928.0244 -10733.5615 -10500.5781 -10574.6563 -10818.9111 -10928.2256 -10728.0879 -10490.1152 -10566.9424 -10814.2090 -10941.9951 -10726.5313 -10491.7051 -10571.4316 -10815.8945 -10932.1758 -10728.6260 -10489.6348 -10554.4258 -10808.7539 -10927.0459 -10724.1934 -10503.0586 -10576.3633 -10821.2363 -10930.6846 -10729.0957 -10490.4883 -10567.1113 -10808.2002 -10929.0049 -10729.7178 -10489.4160 -10570.0059 -10821.5059 -10932.1973 -10732.3994 -10497.1836 +-11180.8027 -10947.6943 -11008.4170 -11247.8984 -11362.6084 -11168.0889 -10935.4238 -11007.6631 -11250.1787 -11368.4912 -11175.5605 -10943.8691 -11002.5391 -11247.7344 -11363.4980 -11170.4287 -10931.0049 -11002.7070 -11239.7754 -11360.1904 -11169.0684 -10929.5264 -10997.1797 -11234.5068 -11362.3193 -11177.8691 -10932.3818 -10993.2080 -11233.4258 -11352.2314 -11161.9023 -10928.3652 -10998.6387 -11233.8535 -11360.1621 -11169.6230 -10940.0986 -11003.4346 -11245.5645 -11357.3623 -11168.9824 -10940.3936 -11007.9629 -11246.7217 -11357.9082 -11164.6240 -10930.3301 -10998.1914 -11240.9922 -11367.7656 -11166.1250 -10935.7500 -11006.4346 -11245.0303 -11359.6631 -11164.9199 -10928.4307 -10989.6719 -11234.2061 -11354.3398 -11160.8525 -10943.3066 -11009.6611 -11249.2832 -11359.7734 -11164.3193 -10930.9814 -11001.2324 -11236.0381 -11355.8271 -11166.6865 -10931.3486 -11004.5371 -11247.2041 -11357.8555 -11167.3320 -10936.0459 +-3701.3481 -3503.0161 -3538.2666 -3730.5115 -3836.8921 -3691.9841 -3491.7942 -3539.3872 -3736.5032 -3842.4478 -3698.0674 -3500.4258 -3536.2952 -3733.3760 -3838.3591 -3694.9541 -3488.8438 -3536.7522 -3727.7036 -3836.1079 -3695.4160 -3488.5764 -3531.9092 -3724.5286 -3837.5203 -3700.6770 -3491.4785 -3528.2585 -3723.6687 -3830.7651 -3687.4919 -3489.5728 -3534.3853 -3723.2554 -3838.1226 -3693.0364 -3497.6389 -3538.2881 -3733.8262 -3832.3201 -3695.1089 -3499.8411 -3542.0920 -3734.3542 -3833.8210 -3690.9329 -3489.2019 -3535.5947 -3730.2422 -3843.4546 -3689.6077 -3494.0371 -3541.6221 -3732.9468 -3835.9580 -3690.6572 -3489.8589 -3525.5593 -3723.7747 -3831.7529 -3686.7051 -3501.5532 -3543.7820 -3735.0156 -3835.1895 -3691.6816 -3489.3333 -3535.3501 -3722.9089 -3834.4919 -3691.5071 -3490.1021 -3538.7996 -3733.5933 -3834.1685 -3691.2092 -3494.0386 +-668.4680 -612.5321 -599.4512 -629.5359 -665.9693 -664.8243 -606.7495 -598.6161 -632.4637 -666.4552 -668.0946 -611.4942 -598.9023 -630.7455 -666.0767 -666.4165 -605.8336 -597.7109 -628.3378 -664.1516 -665.8702 -606.1737 -595.0090 -628.3598 -665.2283 -670.4786 -609.9055 -596.7603 -630.1173 -664.2892 -666.8846 -608.7969 -597.8969 -626.6461 -665.8951 -667.6832 -612.3323 -600.1740 -633.1940 -664.2787 -669.5220 -614.0844 -603.8319 -633.8776 -664.5173 -666.8577 -607.1336 -599.3957 -631.1494 -670.4351 -666.9773 -612.6443 -603.1946 -631.8710 -665.3787 -667.7667 -608.3978 -593.5257 -627.8008 -662.2267 -662.9082 -614.1683 -603.0139 -634.6252 -666.9155 -667.0367 -609.6799 -600.3785 -627.5125 -665.3621 -666.7727 -610.7313 -601.2688 -631.9166 -664.8771 -667.4457 -609.4442 +-3624.7988 -3829.7332 -3723.2932 -3458.1978 -3361.8884 -3622.2888 -3825.5347 -3722.4097 -3458.3936 -3360.9343 -3623.4377 -3827.5452 -3723.1184 -3457.2144 -3362.8796 -3624.2275 -3825.9360 -3722.3860 -3455.7395 -3363.1013 -3625.6021 -3827.5679 -3720.5469 -3454.6794 -3361.9331 -3628.3679 -3828.4814 -3720.0151 -3455.4763 -3360.1826 -3626.1289 -3825.6008 -3722.0696 -3453.9348 -3364.3218 -3628.2190 -3832.9111 -3722.2822 -3456.2493 -3361.2881 -3627.8135 -3833.2219 -3725.1885 -3456.3662 -3362.3418 -3626.8789 -3827.6785 -3722.2585 -3456.8318 -3364.1660 -3628.3254 -3829.9197 -3723.2598 -3456.3176 -3363.1912 -3629.9094 -3830.6594 -3720.1465 -3457.3152 -3363.2388 -3627.0017 -3830.0696 -3721.7214 -3458.1770 -3364.6121 -3630.4104 -3830.3264 -3724.1594 -3455.8152 -3365.3970 -3631.2546 -3828.2939 -3721.7266 -3458.3091 -3364.6689 -3633.1980 -3830.8733 +-7568.6440 -7326.3174 -7424.2358 -7728.9170 -7855.2520 -7557.3047 -7308.4990 -7440.7837 -7732.6431 -7840.1514 -7563.0767 -7306.2964 -7403.1885 -7708.0400 -7840.7969 -7566.6206 -7283.9028 -7410.9795 -7708.3301 -7833.6201 -7569.2632 -7286.9351 -7401.8218 -7699.9473 -7837.5752 -7574.1572 -7273.1763 -7391.7397 -7692.0737 -7804.0913 -7532.3564 -7288.7236 -7399.9639 -7691.1504 -7820.0220 -7544.4331 -7290.8438 -7401.9307 -7711.2959 -7809.4707 -7540.2373 -7292.2422 -7418.8848 -7710.8594 -7811.4429 -7544.3149 -7288.1919 -7404.2524 -7708.2881 -7824.5532 -7539.1997 -7286.2256 -7416.9185 -7701.3096 -7816.4727 -7536.1353 -7269.2407 -7406.8237 -7720.1538 -7830.4180 -7547.7178 -7300.6421 -7406.1470 -7704.4580 -7808.1953 -7539.6206 -7286.4683 -7418.4038 -7705.6528 -7820.4932 -7550.3467 -7273.8857 -7415.2485 -7733.0728 -7819.8096 -7553.7432 -7300.5391 +-17765.6641 -17513.2148 -17603.7305 -17901.4043 -18029.4727 -17750.0234 -17505.2207 -17622.8984 -17903.3984 -18015.1152 -17754.6660 -17497.0059 -17586.7090 -17890.6016 -18008.3496 -17749.9863 -17482.5469 -17601.8105 -17884.4805 -18002.5059 -17747.1250 -17489.1484 -17596.7520 -17879.2754 -18006.0156 -17760.3984 -17472.6914 -17575.2656 -17866.4258 -17973.5664 -17715.6230 -17486.2461 -17591.1465 -17870.3262 -18002.3164 -17738.6445 -17489.9199 -17585.3789 -17879.0430 -17996.2012 -17739.2402 -17488.8965 -17609.3809 -17882.6543 -17994.6934 -17736.9746 -17477.9551 -17601.0117 -17888.7422 -18014.7813 -17732.4961 -17478.8262 -17597.7734 -17887.2246 -17995.4980 -17738.0527 -17475.9219 -17594.3711 -17891.3145 -18003.1172 -17737.5508 -17497.4043 -17593.8711 -17881.7617 -18001.7617 -17746.5176 -17487.2617 -17602.8887 -17886.0566 -18003.5879 -17739.8652 -17475.5254 -17606.6582 -17906.1660 -18009.7520 -17752.4180 -17496.6719 +-15713.5791 -15465.1504 -15541.7119 -15808.4180 -15929.6836 -15700.0850 -15449.5361 -15540.3320 -15810.3545 -15932.3564 -15706.8428 -15455.9570 -15528.3711 -15805.0000 -15924.8174 -15701.4678 -15443.6338 -15526.8584 -15794.4785 -15922.4844 -15700.2158 -15442.5908 -15525.1846 -15790.5039 -15924.0947 -15710.7129 -15438.3145 -15514.9033 -15783.0049 -15908.3184 -15682.8125 -15436.0410 -15522.1045 -15784.5293 -15922.4141 -15697.4004 -15449.4688 -15522.9404 -15797.8135 -15915.0752 -15696.7764 -15452.6924 -15535.7676 -15801.3506 -15915.6816 -15691.4941 -15439.9912 -15527.0303 -15794.8506 -15930.2324 -15692.1387 -15443.2676 -15533.4980 -15799.9678 -15923.2041 -15695.8975 -15438.7490 -15519.6260 -15794.4141 -15916.8271 -15690.9697 -15454.5000 -15535.9482 -15806.5967 -15922.5088 -15695.8545 -15442.1836 -15529.8164 -15797.9092 -15919.0781 -15697.5811 -15438.8096 -15532.2344 -15808.3545 -15925.6807 -15702.1162 -15450.7529 +-9899.8408 -9641.6270 -9706.1279 -9972.2148 -10102.3438 -9886.6924 -9625.4121 -9703.0439 -9973.8135 -10109.0928 -9893.9326 -9634.7100 -9693.9014 -9970.2988 -10100.6553 -9887.9180 -9618.6240 -9689.4814 -9958.0703 -10096.8604 -9887.5430 -9620.1758 -9688.8789 -9954.1553 -10098.8711 -9897.6240 -9617.4336 -9677.1992 -9947.1563 -10083.0781 -9870.1055 -9612.5625 -9686.2021 -9949.0791 -10097.8281 -9885.6816 -9628.5791 -9688.4014 -9961.9902 -10090.4131 -9885.5010 -9630.2666 -9699.9375 -9965.0977 -10092.6172 -9879.4824 -9616.0293 -9689.1729 -9960.7793 -10105.0342 -9880.6035 -9622.0674 -9697.1387 -9964.1924 -10098.7168 -9883.3701 -9615.4883 -9679.8799 -9955.6309 -10091.6475 -9877.8867 -9631.2158 -9700.9561 -9970.7412 -10098.4189 -9881.6318 -9620.2021 -9694.4434 -9962.7744 -10096.1357 -9885.7100 -9616.5703 -9695.1602 -9971.6494 -10100.4863 -9890.1660 -9628.8193 +-9282.7285 -9033.0029 -9093.3594 -9344.2959 -9474.5342 -9269.1240 -9018.6123 -9089.5264 -9347.7354 -9478.0527 -9277.5840 -9028.0479 -9082.3213 -9344.1992 -9470.6670 -9272.2686 -9014.5664 -9082.1992 -9333.9551 -9468.9512 -9272.2930 -9015.4072 -9078.9346 -9330.0127 -9471.6738 -9282.3359 -9013.3740 -9070.2510 -9324.6279 -9456.3955 -9258.0107 -9008.2881 -9076.7363 -9326.8359 -9469.1758 -9270.0635 -9024.9375 -9079.0781 -9339.1279 -9462.8301 -9270.0430 -9024.7949 -9089.6514 -9341.6514 -9465.2627 -9264.9844 -9013.3779 -9079.7813 -9337.2207 -9476.3740 -9267.3242 -9018.2080 -9089.5859 -9341.0605 -9471.2695 -9268.1553 -9012.8174 -9071.6230 -9332.1289 -9464.9004 -9262.7295 -9027.0176 -9089.5908 -9345.0410 -9470.8389 -9267.6924 -9015.9561 -9084.0371 -9337.6123 -9466.7744 -9270.5547 -9012.9824 -9084.8906 -9348.8115 -9471.3203 -9274.5625 -9024.0215 +-5622.4854 -5394.8394 -5434.4648 -5654.6406 -5777.6040 -5609.1147 -5382.4751 -5431.9282 -5656.7119 -5781.3340 -5618.5991 -5390.4248 -5428.2085 -5655.7910 -5775.8364 -5612.9238 -5378.5117 -5427.7896 -5647.0044 -5773.1396 -5611.3296 -5377.9463 -5424.9727 -5643.0566 -5776.2720 -5620.0342 -5379.6953 -5419.1514 -5641.1978 -5765.2070 -5603.2837 -5374.4282 -5422.7910 -5642.6919 -5773.7842 -5612.6851 -5388.2031 -5427.3247 -5652.2114 -5768.7881 -5612.5972 -5387.4395 -5432.1094 -5653.3550 -5771.9575 -5607.9658 -5377.5176 -5424.0454 -5649.4072 -5779.9297 -5609.2334 -5382.6597 -5431.8687 -5652.9995 -5774.4160 -5607.7998 -5375.5576 -5416.4072 -5643.4634 -5767.0874 -5602.9546 -5387.3530 -5431.0552 -5654.9243 -5774.2358 -5608.9448 -5379.1768 -5428.2314 -5647.0815 -5769.9033 -5610.4658 -5377.8760 -5428.4238 -5655.4888 -5772.7871 -5611.2021 -5384.8379 +-1780.1487 -1638.1166 -1648.0753 -1771.7561 -1851.7579 -1771.7584 -1629.9924 -1647.6387 -1773.5889 -1853.6255 -1777.6467 -1635.7307 -1645.4404 -1772.0740 -1851.9956 -1773.9613 -1627.2731 -1644.2314 -1767.0518 -1850.1920 -1773.7258 -1628.7635 -1642.8447 -1764.7869 -1852.0688 -1782.2559 -1630.4862 -1639.9730 -1764.5427 -1846.2341 -1770.7683 -1627.0214 -1642.4119 -1765.4697 -1852.0718 -1775.2102 -1635.7791 -1645.6259 -1772.4521 -1848.6860 -1776.9149 -1635.2350 -1648.6825 -1773.0387 -1848.6071 -1773.6864 -1627.1942 -1644.1964 -1770.4674 -1855.5592 -1775.2699 -1633.4478 -1650.4468 -1773.0060 -1849.9021 -1775.8464 -1629.4769 -1637.4374 -1765.7125 -1847.5778 -1769.8523 -1636.8036 -1647.9966 -1773.5469 -1851.4141 -1775.7611 -1631.6892 -1647.6941 -1768.0959 -1849.3174 -1774.3215 -1629.9728 -1646.7383 -1774.1611 -1850.0421 -1776.8727 -1635.3636 +-908.3983 -1009.2620 -919.6689 -760.3754 -724.0175 -905.1149 -1003.3100 -915.7413 -760.1539 -721.5405 -906.2695 -1006.4770 -917.6286 -758.8837 -724.1296 -907.1485 -1002.5775 -916.3583 -755.8177 -723.1880 -906.5715 -1004.7623 -914.4067 -754.4775 -724.1245 -910.0113 -1004.1572 -914.5853 -755.1796 -720.5849 -904.7685 -1001.4862 -914.0995 -754.2053 -724.6791 -909.2710 -1009.4489 -914.6528 -758.7043 -722.1343 -910.3400 -1010.7351 -920.6573 -757.8268 -722.8627 -908.4315 -1003.3211 -917.0448 -756.9230 -725.3442 -909.4490 -1008.7562 -918.9969 -759.3723 -725.5213 -912.0634 -1006.5775 -915.1115 -758.9211 -723.9615 -906.0938 -1007.8730 -915.8856 -760.1657 -725.8917 -911.6648 -1009.2395 -920.4697 -757.9514 -726.0793 -911.7435 -1006.6452 -917.7205 -759.9207 -725.0999 -913.9646 -1007.4545 +912.5317 1124.8234 996.3629 748.6647 651.1708 920.8968 1176.3827 1055.0702 771.7217 649.2142 928.8132 1182.7710 1060.1250 754.2014 666.9744 946.8862 1210.1534 1099.0942 801.2765 652.0223 920.6572 1211.9893 1099.1876 802.3464 669.4510 932.6447 1210.4158 1081.8857 814.0992 672.1199 968.6129 1231.6719 1107.3914 823.4833 671.5093 943.9724 1195.6021 1098.4506 794.2468 683.3360 943.4413 1200.0682 1055.6863 772.2293 689.9659 954.1121 1194.9427 1080.1772 796.0782 681.3604 949.5028 1180.2587 1060.8534 797.4845 662.6086 957.8215 1214.9464 1096.5891 784.4987 657.9465 940.3359 1180.7913 1027.5940 743.8688 695.8923 953.1014 1208.6152 1078.8649 756.9249 657.6082 899.6176 1178.9097 1075.3639 772.5060 656.8688 939.5058 1196.4879 +-11973.7979 -11730.4609 -11827.2949 -12098.4463 -12207.8105 -11960.4951 -11707.8574 -11817.2666 -12095.2139 -12213.0186 -11966.6758 -11712.8301 -11806.4893 -12093.9209 -12202.7500 -11957.3857 -11699.9150 -11795.8311 -12072.3262 -12201.6914 -11959.0195 -11698.5264 -11796.7285 -12070.9072 -12200.8643 -11968.9453 -11694.6367 -11788.7539 -12063.0625 -12183.5703 -11933.4746 -11684.7900 -11791.2324 -12061.4844 -12199.3301 -11956.5947 -11709.4023 -11792.3486 -12079.6846 -12191.5557 -11952.7363 -11711.2656 -11806.0479 -12084.1074 -12189.9590 -11948.5625 -11700.2695 -11801.0654 -12077.2461 -12204.0674 -11950.2441 -11701.5254 -11809.4883 -12081.1445 -12200.9844 -11952.7852 -11698.3350 -11790.8301 -12077.2520 -12195.8467 -11947.6611 -11711.3994 -11814.1865 -12097.5283 -12198.2725 -11951.6875 -11699.2998 -11804.5684 -12088.3311 -12197.7588 -11960.5908 -11696.2783 -11805.2725 -12092.6113 -12204.9502 -11963.1406 -11710.7578 +-6795.6294 -6541.5562 -6618.7310 -6884.0752 -7007.9331 -6780.3501 -6522.3525 -6611.3345 -6886.9668 -7014.5254 -6789.9966 -6532.2900 -6602.0996 -6881.2358 -7004.3979 -6783.3379 -6518.2168 -6596.4771 -6866.9038 -7002.5781 -6780.6416 -6520.6099 -6597.1279 -6865.5557 -7006.6187 -6793.9126 -6515.4458 -6587.5449 -6856.0156 -6986.7554 -6761.1338 -6507.5024 -6592.8882 -6858.1475 -7004.0737 -6782.3467 -6528.9990 -6592.7896 -6870.1035 -6993.7217 -6779.4678 -6530.2700 -6606.6108 -6876.2471 -6997.6406 -6772.9351 -6516.2764 -6597.1011 -6870.4180 -7007.6753 -6776.9546 -6524.2842 -6606.8247 -6875.7563 -7005.7510 -6779.6724 -6513.7227 -6589.0840 -6866.2012 -6996.5093 -6767.9722 -6527.3452 -6607.5400 -6883.5571 -7005.6772 -6776.5034 -6521.0088 -6603.8999 -6877.3081 -7000.4731 -6779.9956 -6514.8887 -6602.1392 -6883.1436 -7006.7261 -6789.0449 -6529.9482 +-3272.4204 -3023.8044 -3091.7761 -3343.3735 -3469.6216 -3260.0330 -3002.1987 -3084.5659 -3344.8831 -3474.6777 -3267.1775 -3017.0276 -3079.4341 -3341.2693 -3466.5525 -3262.3665 -3004.9490 -3074.2554 -3328.5984 -3461.2283 -3254.8909 -3005.9214 -3076.1646 -3333.1123 -3466.8682 -3274.0464 -3006.4587 -3065.1045 -3316.6255 -3448.3696 -3241.1321 -2993.7393 -3071.7427 -3323.3442 -3462.9216 -3261.6414 -3021.7542 -3073.8296 -3334.7915 -3456.6282 -3259.9270 -3016.6699 -3081.7317 -3340.9001 -3462.2588 -3250.9458 -3002.0193 -3068.5715 -3331.6660 -3464.9399 -3259.6567 -3015.8257 -3085.3083 -3340.2844 -3466.4414 -3262.2097 -3001.7510 -3064.9143 -3327.1431 -3457.9604 -3251.9749 -3012.3018 -3082.2334 -3344.1494 -3471.9888 -3254.4363 -3009.4119 -3081.8530 -3342.2610 -3462.1848 -3259.3220 -3000.5830 -3079.4338 -3346.9243 -3467.1055 -3268.1526 -3017.8694 +-6588.1084 -6344.0161 -6402.7954 -6644.3135 -6770.8511 -6573.0347 -6323.9360 -6396.6304 -6647.7847 -6776.0898 -6583.3174 -6339.3413 -6395.4434 -6643.9233 -6767.8052 -6575.7925 -6324.8823 -6391.0898 -6633.6929 -6763.4067 -6573.5288 -6329.0947 -6390.5425 -6634.1069 -6770.3813 -6590.2017 -6329.1108 -6380.2593 -6622.9292 -6753.4248 -6560.6890 -6319.2017 -6387.0752 -6626.0005 -6764.5386 -6578.4209 -6341.6182 -6390.3101 -6641.6074 -6763.6670 -6578.0708 -6341.9458 -6397.8379 -6645.2061 -6765.1333 -6568.3540 -6323.7334 -6386.5786 -6640.1353 -6771.3843 -6578.1182 -6338.8457 -6400.6084 -6644.9585 -6768.4722 -6576.1455 -6327.1885 -6384.6157 -6633.8633 -6762.9536 -6570.3501 -6335.9097 -6398.1646 -6649.1235 -6775.1221 -6572.2979 -6336.9790 -6400.8125 -6645.8223 -6766.0020 -6576.5679 -6326.6279 -6395.6182 -6650.2124 -6771.1211 -6584.7495 -6342.9160 +389.7935 588.6360 571.1140 392.4888 276.8909 398.9478 602.1590 575.7947 388.4563 276.7896 394.8340 593.8652 578.9537 393.6256 278.7906 398.9271 604.7342 579.8969 400.0127 282.8030 399.1154 601.8133 581.5638 398.6395 275.6815 387.6023 600.3156 585.8065 405.1955 287.2803 403.7623 607.4225 581.9133 399.2097 277.9875 392.6104 589.2728 578.0729 394.1756 280.7376 394.7303 590.4464 574.3145 388.8232 279.7548 400.5349 602.1851 581.4534 392.6813 273.5338 394.2687 592.8397 572.0178 390.1075 276.4493 393.4981 600.0115 583.8840 397.0431 283.2184 403.6110 595.0782 577.1017 390.6882 275.6548 395.6095 593.9827 572.8094 392.4754 280.9231 394.1367 600.1775 574.5847 386.6588 276.2532 390.8570 589.8104 +-1035.9205 -1078.2775 -1043.8923 -968.4937 -951.2908 -1030.4479 -1067.7388 -1038.2197 -969.6968 -950.6821 -1034.5028 -1072.3295 -1036.5632 -965.8942 -949.3170 -1031.4966 -1066.1892 -1036.7867 -962.5547 -947.8896 -1031.7271 -1071.4160 -1034.1516 -962.2157 -953.0162 -1040.0454 -1069.8744 -1030.5392 -958.0412 -941.7413 -1026.8396 -1063.2108 -1033.0392 -959.6395 -949.9370 -1037.3988 -1078.2662 -1034.5797 -963.7249 -945.4725 -1035.4545 -1075.7882 -1039.7631 -966.2900 -947.8276 -1030.3300 -1067.0239 -1033.4072 -964.9674 -950.2819 -1034.5236 -1073.7413 -1038.0074 -965.2902 -950.9260 -1036.9940 -1070.0647 -1033.1781 -965.0565 -946.7314 -1027.9762 -1069.8723 -1033.9801 -968.0121 -952.7617 -1034.8624 -1074.4443 -1041.8054 -969.0259 -949.3486 -1037.1448 -1067.7560 -1038.3613 -970.5758 -950.2838 -1040.9543 -1076.6803 +-7221.9248 -6983.4375 -7096.1787 -7365.0518 -7472.5024 -7210.8647 -6951.1382 -7075.6475 -7367.9849 -7482.9565 -7214.6162 -6959.0767 -7065.5581 -7365.0356 -7469.4663 -7205.3267 -6943.3950 -7047.2642 -7337.4922 -7469.2627 -7209.1978 -6947.3950 -7052.3647 -7345.3364 -7476.5522 -7220.4370 -6938.9629 -7041.5986 -7322.4346 -7444.7876 -7176.1538 -6929.3906 -7044.5410 -7326.0435 -7471.5195 -7206.1689 -6950.0674 -7040.4810 -7338.8940 -7455.0469 -7200.6689 -6958.2437 -7074.0972 -7356.2656 -7451.4351 -7189.4678 -6940.9312 -7049.1367 -7344.9751 -7463.8931 -7198.3579 -6953.8867 -7071.3354 -7348.5352 -7470.5503 -7198.9028 -6937.3442 -7048.2163 -7344.0430 -7460.5068 -7192.2798 -6954.4990 -7080.1792 -7369.0527 -7467.5601 -7199.6611 -6948.5781 -7065.9385 -7369.7476 -7463.0483 -7215.6226 -6941.9702 -7058.5874 -7360.0229 -7468.4497 -7222.5078 -6962.1816 +-9124.4658 -8877.7539 -8970.0195 -9236.9014 -9347.6709 -9107.9404 -8849.5830 -8956.8672 -9244.1973 -9363.1523 -9121.8516 -8865.3545 -8949.4248 -9234.4990 -9351.5332 -9109.8809 -8849.0313 -8936.8359 -9214.4238 -9350.1504 -9112.8496 -8854.5586 -8941.8428 -9222.9033 -9361.3252 -9129.5000 -8846.1396 -8933.4063 -9205.1270 -9332.6494 -9086.7031 -8837.7969 -8935.5469 -9206.2109 -9355.6865 -9117.0771 -8863.3203 -8930.5010 -9218.5986 -9338.4473 -9108.7080 -8865.0859 -8955.3965 -9230.6260 -9343.5088 -9100.1025 -8843.9707 -8938.7637 -9222.8379 -9353.1699 -9106.9795 -8858.9297 -8955.7314 -9229.2676 -9357.3760 -9106.4609 -8843.8047 -8933.8926 -9218.2246 -9340.0664 -9094.4951 -8858.9932 -8959.0537 -9244.8076 -9358.3408 -9107.2012 -8856.4590 -8952.6797 -9238.0264 -9344.7021 -9111.9971 -8846.9463 -8944.8975 -9235.0098 -9353.9600 -9125.9482 -8869.1436 +-9420.7568 -9193.6768 -9281.9160 -9534.3467 -9632.8740 -9402.4307 -9164.6025 -9270.6338 -9546.4336 -9650.2451 -9419.1270 -9185.0654 -9269.3037 -9530.8682 -9641.1689 -9409.5527 -9167.8652 -9257.6113 -9515.1240 -9636.2510 -9415.1504 -9176.7217 -9259.0342 -9523.5566 -9649.5830 -9429.0313 -9167.6895 -9256.8086 -9509.2109 -9625.3789 -9391.1621 -9157.8643 -9255.6396 -9509.4150 -9645.6875 -9427.7207 -9181.8975 -9252.8867 -9518.5068 -9627.8350 -9409.9043 -9182.6016 -9273.6230 -9529.2988 -9636.2422 -9401.3828 -9165.9600 -9259.8232 -9526.1357 -9645.0898 -9411.5840 -9176.7422 -9271.3398 -9530.4824 -9647.4014 -9412.5986 -9164.5742 -9254.9072 -9519.4424 -9627.9453 -9391.1689 -9175.5889 -9274.7441 -9547.4639 -9648.2070 -9407.1416 -9175.6865 -9272.9863 -9536.4922 -9631.6816 -9411.5732 -9167.4600 -9268.3496 -9535.7041 -9639.4434 -9427.6201 -9189.9580 +-6402.5854 -6212.9126 -6276.3389 -6472.5713 -6566.3462 -6387.6157 -6186.3428 -6270.4121 -6484.0947 -6572.5122 -6399.0679 -6206.5166 -6266.9019 -6471.0596 -6568.8662 -6392.5825 -6188.3882 -6265.2202 -6460.1997 -6560.8872 -6391.3154 -6200.6133 -6261.4609 -6466.5903 -6577.5898 -6412.2134 -6196.0889 -6254.0146 -6453.8960 -6554.7065 -6378.6323 -6184.9639 -6258.4355 -6456.7520 -6568.0469 -6411.0796 -6209.9268 -6260.3892 -6465.7788 -6559.1714 -6394.7139 -6204.5044 -6269.2485 -6474.1030 -6563.7666 -6384.3149 -6188.2852 -6257.2319 -6471.8335 -6568.0669 -6396.9097 -6205.3022 -6270.2412 -6473.4731 -6565.3848 -6399.0347 -6191.0723 -6255.4595 -6464.5977 -6558.5742 -6379.8535 -6196.4473 -6267.0103 -6486.9014 -6574.8809 -6390.2173 -6203.1548 -6272.9854 -6476.8950 -6561.0532 -6394.4683 -6189.0859 -6267.4917 -6483.4614 -6565.3940 -6408.3525 -6212.5693 +269.0631 437.5076 395.0552 232.4569 144.4944 282.5675 459.8656 400.5933 224.0162 140.5337 272.7041 443.8403 404.0327 234.1364 142.8481 277.6525 457.5103 404.7246 244.8250 149.2487 279.6491 448.8839 408.7237 238.6342 137.3484 262.7183 452.0385 415.7703 249.9585 155.0644 291.5630 462.8918 411.7890 245.9242 144.0817 264.1725 438.5725 408.2354 238.3005 152.4921 275.5885 443.1430 403.4374 231.1155 146.0203 285.3275 457.8748 413.4241 232.9564 143.9390 274.0223 443.6188 401.1920 233.5706 144.7407 272.5026 455.8058 413.7475 239.8820 150.2715 287.7341 451.7402 405.5399 223.0127 138.8218 279.9069 445.3688 399.3478 228.0247 150.2584 274.7382 457.5759 404.2929 223.5650 145.5408 264.8579 437.3061 +1441.5942 1569.2924 1542.9678 1424.3828 1356.5795 1449.7666 1587.8254 1550.3188 1422.1558 1355.4082 1444.6011 1576.5594 1550.9984 1427.6045 1356.7363 1448.6940 1586.0598 1551.3394 1432.5967 1361.2654 1449.0621 1578.5526 1553.6730 1431.5864 1352.5848 1435.4177 1580.2079 1557.9015 1438.0275 1366.4734 1456.6671 1591.4774 1556.3839 1436.0092 1357.4010 1438.5319 1569.9900 1554.4553 1430.2947 1364.7885 1444.9412 1574.5481 1549.3085 1425.1571 1360.3540 1452.4033 1585.6510 1556.6848 1427.7433 1358.7366 1444.5104 1575.3783 1548.9774 1426.2186 1358.6365 1444.2035 1582.1696 1557.0725 1429.9117 1363.1428 1455.7999 1583.0354 1554.3204 1422.5511 1354.0659 1447.6528 1573.5305 1542.4139 1420.5126 1360.4225 1444.2966 1584.7522 1549.4991 1420.6409 1357.0599 1437.3789 1569.4921 +-4622.3003 -4383.9502 -4493.5059 -4764.5640 -4870.8892 -4608.4785 -4351.9087 -4479.3276 -4774.9048 -4887.3032 -4621.2930 -4367.7007 -4469.0146 -4764.5771 -4872.9082 -4611.0366 -4352.7695 -4456.3076 -4743.2080 -4871.8716 -4613.3140 -4357.2329 -4460.0122 -4754.2397 -4885.8486 -4631.8110 -4349.1318 -4449.5498 -4728.8516 -4851.1982 -4584.3286 -4342.2661 -4454.0552 -4735.3179 -4878.2603 -4617.5786 -4363.2061 -4449.5928 -4744.9478 -4862.0522 -4609.8208 -4369.7847 -4482.1528 -4761.0244 -4859.9990 -4597.7031 -4348.0073 -4456.6245 -4753.4526 -4870.3872 -4606.5854 -4363.4580 -4479.6714 -4759.6299 -4878.0737 -4605.2637 -4346.2695 -4456.4453 -4749.4795 -4861.7480 -4594.0806 -4364.8384 -4486.4692 -4778.3198 -4880.5469 -4609.5527 -4362.9399 -4477.1880 -4777.2466 -4868.6104 -4620.0249 -4347.8535 -4466.5415 -4768.8345 -4876.7021 -4636.3330 -4375.8169 +-7249.3955 -7016.0386 -7119.0332 -7383.3418 -7484.7505 -7233.7690 -6983.8311 -7107.1826 -7393.6729 -7502.0049 -7250.9409 -7005.5396 -7100.5679 -7382.2588 -7489.1895 -7236.6543 -6986.9346 -7088.8638 -7363.4072 -7487.8101 -7239.9458 -6992.2207 -7090.3877 -7373.9497 -7504.0249 -7260.5186 -6985.0923 -7081.0107 -7350.7075 -7468.9844 -7215.9858 -6978.7129 -7085.8354 -7355.0396 -7495.1250 -7245.7539 -7000.0371 -7079.7554 -7366.1729 -7476.5000 -7238.0635 -7004.4170 -7109.4863 -7380.3936 -7479.2295 -7227.1641 -6981.6802 -7087.5981 -7372.4756 -7488.7021 -7235.4619 -6999.2383 -7107.5938 -7380.5688 -7496.1216 -7232.3379 -6980.3208 -7085.2339 -7369.0044 -7475.2651 -7219.4248 -6997.6577 -7112.0327 -7396.8188 -7498.6807 -7235.2974 -6997.5010 -7105.0913 -7393.5405 -7482.7388 -7244.4248 -6980.4961 -7094.9824 -7385.8711 -7490.9189 -7260.3931 -7008.9482 +-8438.9453 -8192.5791 -8283.4385 -8551.2598 -8657.0850 -8409.8818 -8158.1802 -8269.7012 -8559.5039 -8680.8848 -8444.3955 -8192.5820 -8275.0947 -8552.8037 -8668.9365 -8415.7666 -8163.6089 -8267.7422 -8527.2305 -8665.9150 -8427.0850 -8172.5186 -8265.0898 -8551.5449 -8685.8633 -8449.7773 -8168.0264 -8262.0723 -8531.8350 -8653.9746 -8412.7422 -8160.5127 -8263.9424 -8530.9248 -8679.9639 -8437.8408 -8187.0054 -8257.7256 -8541.1768 -8656.2227 -8422.7725 -8186.5610 -8289.0322 -8551.9043 -8670.6602 -8415.0410 -8157.7949 -8263.7969 -8544.2363 -8669.7598 -8427.9395 -8182.2354 -8280.4463 -8562.9209 -8683.5479 -8426.0439 -8158.1772 -8256.7842 -8539.9678 -8649.7217 -8395.8428 -8175.2642 -8282.1699 -8575.8652 -8688.0850 -8427.1650 -8180.0640 -8275.1436 -8570.6318 -8663.1758 -8433.3262 -8161.1401 -8270.5361 -8557.8877 -8669.5283 -8447.6816 -8191.5923 +-9563.8037 -9319.7432 -9409.7188 -9669.4189 -9772.5576 -9542.3496 -9285.2822 -9382.4072 -9677.7686 -9801.9756 -9569.2539 -9318.6943 -9403.2813 -9668.3145 -9785.9111 -9545.4932 -9300.9072 -9377.7363 -9649.7490 -9787.4248 -9569.9102 -9298.6328 -9385.2969 -9661.8594 -9796.8301 -9574.1377 -9300.6699 -9389.6338 -9650.8750 -9777.0205 -9547.9326 -9287.0850 -9384.1191 -9649.8301 -9808.0557 -9568.8125 -9304.8125 -9380.8594 -9654.3984 -9774.9619 -9554.8730 -9317.0430 -9408.9756 -9665.5605 -9790.4658 -9548.0273 -9291.9063 -9380.9395 -9655.7119 -9797.6992 -9554.8838 -9306.5693 -9398.5928 -9679.2275 -9818.8809 -9542.9648 -9285.3359 -9382.5869 -9653.8887 -9766.4033 -9529.8643 -9304.9355 -9395.4961 -9689.1250 -9811.0791 -9554.3652 -9300.3779 -9404.1777 -9678.1035 -9782.3711 -9560.5605 -9297.9482 -9401.4727 -9666.1055 -9778.1875 -9568.9219 -9318.6777 +-8266.1523 -8002.9995 -8016.0962 -8253.9492 -8402.4941 -8245.6182 -7975.2847 -8002.8496 -8257.1914 -8418.2305 -8268.6309 -7992.1797 -8006.8818 -8251.1309 -8412.1670 -8252.1855 -7983.4854 -7996.2158 -8234.4268 -8408.6162 -8266.8008 -7989.7085 -7998.7759 -8243.1807 -8420.5400 -8276.2480 -7986.4204 -7996.4639 -8237.5166 -8403.6572 -8249.2021 -7972.8418 -8001.1367 -8235.8564 -8422.8584 -8279.0039 -7994.6265 -7994.8145 -8242.9795 -8405.3994 -8261.8975 -7991.0791 -8009.2368 -8250.8662 -8409.5518 -8248.5469 -7977.7290 -7995.2568 -8246.5371 -8413.5098 -8261.5723 -7987.4263 -8003.1875 -8249.1787 -8421.5244 -8257.8936 -7978.0479 -7990.3047 -8240.9512 -8404.5186 -8239.0264 -7980.0161 -7998.0830 -8258.3047 -8419.5010 -8255.3984 -7993.6133 -8005.5864 -8255.9023 -8412.2266 -8258.4307 -7983.8350 -8011.6958 -8254.1543 -8407.7178 -8266.6670 -8000.5195 +-2922.8101 -2668.2969 -2664.4456 -2884.2517 -3046.4487 -2912.9260 -2644.1831 -2657.2117 -2888.4431 -3045.9622 -2920.4170 -2660.2100 -2657.6641 -2881.6997 -3045.2783 -2911.8352 -2648.5720 -2654.8167 -2876.1414 -3037.4075 -2911.5281 -2654.4846 -2652.1975 -2876.0164 -3047.2271 -2927.2144 -2652.3157 -2646.7961 -2866.6106 -3032.5413 -2899.7244 -2639.5872 -2647.0806 -2873.3696 -3044.1997 -2924.9980 -2668.7539 -2650.7280 -2877.2258 -3037.4673 -2917.0776 -2660.1904 -2656.8809 -2884.5291 -3041.8997 -2906.3494 -2643.0496 -2645.0559 -2881.2087 -3040.3625 -2916.2722 -2659.2026 -2659.6487 -2880.2842 -3042.2222 -2917.7212 -2647.9971 -2647.2632 -2877.9861 -3039.3613 -2903.4165 -2650.6021 -2649.4111 -2885.0181 -3050.1233 -2910.9543 -2656.8855 -2660.1038 -2888.1299 -3041.5579 -2912.8252 -2646.9109 -2656.0662 -2888.7207 -3044.6631 -2921.6392 -2665.1958 +-1997.7800 -1747.6993 -1862.0873 -2141.5835 -2247.5793 -1978.9630 -1721.5248 -1858.9292 -2162.4468 -2280.0952 -2003.1442 -1740.6597 -1835.5127 -2139.8923 -2256.9724 -1992.3385 -1721.6541 -1830.4193 -2127.3386 -2257.3308 -1991.3745 -1734.3446 -1841.1737 -2140.4204 -2279.8298 -2013.6217 -1720.9608 -1819.7472 -2106.8347 -2237.8948 -1966.9004 -1720.4700 -1831.6333 -2119.6592 -2268.0730 -2003.5686 -1737.2931 -1825.7678 -2116.9111 -2248.3792 -1991.0540 -1749.2599 -1856.8823 -2142.6082 -2245.6289 -1976.1541 -1724.7914 -1823.2457 -2130.9016 -2251.8340 -1982.4513 -1733.4447 -1850.5972 -2140.8655 -2256.3833 -1978.5521 -1710.5482 -1826.5192 -2128.6028 -2242.0505 -1970.2051 -1740.3230 -1862.4927 -2163.0237 -2273.1299 -1992.3992 -1738.8258 -1850.8314 -2163.3320 -2248.5205 -1989.6094 -1714.5752 -1834.9716 -2150.0459 -2261.2844 -2018.6721 -1748.1627 +-6227.7871 -5984.2656 -6077.6475 -6335.9502 -6442.6963 -6194.3667 -5940.1089 -6051.5200 -6348.2471 -6471.1758 -6235.1504 -5987.8164 -6077.6987 -6342.1675 -6459.9697 -6206.4849 -5954.6895 -6056.6035 -6320.3086 -6453.7534 -6222.7803 -5961.5620 -6053.1436 -6336.8223 -6477.6074 -6249.4351 -5963.5708 -6058.3086 -6321.2998 -6445.6802 -6207.8130 -5952.0332 -6051.6880 -6319.7363 -6468.8730 -6228.2280 -5975.8687 -6052.2236 -6332.8696 -6447.0581 -6222.3882 -5978.0688 -6074.7168 -6342.5151 -6461.9565 -6210.8735 -5946.5049 -6048.7192 -6333.0835 -6464.8770 -6220.2739 -5976.5708 -6072.8721 -6353.3066 -6478.4492 -6212.9941 -5948.8838 -6047.6787 -6325.4844 -6440.0645 -6189.9126 -5968.8491 -6067.0352 -6370.5396 -6483.2959 -6211.7412 -5969.8735 -6071.7017 -6355.3682 -6450.9346 -6222.8774 -5953.8354 -6067.2061 -6350.2705 -6457.3433 -6242.6099 -5990.4893 +-5972.4814 -5744.4282 -5820.1763 -6059.8096 -6164.4854 -5956.5542 -5719.9351 -5801.3804 -6060.2920 -6179.6870 -5973.2725 -5740.4043 -5814.9146 -6056.5869 -6175.0322 -5956.9854 -5725.4263 -5800.0415 -6051.4390 -6176.0288 -5974.2505 -5732.3301 -5801.7788 -6050.7153 -6181.2700 -5982.4790 -5726.7505 -5805.4688 -6047.8003 -6165.8550 -5962.5322 -5718.4312 -5800.8374 -6042.8291 -6183.0410 -5976.8174 -5738.7466 -5802.6104 -6051.4229 -6168.0894 -5971.0122 -5738.1416 -5814.8394 -6057.6021 -6177.3135 -5958.8745 -5722.7261 -5799.1582 -6052.0415 -6175.5557 -5967.8174 -5733.9424 -5811.6392 -6063.7876 -6191.0200 -5966.8984 -5723.9995 -5799.4360 -6057.9668 -6165.4653 -5949.2573 -5729.6108 -5806.2422 -6065.7686 -6185.8032 -5964.7861 -5733.9409 -5819.5723 -6069.2837 -6173.3779 -5971.6509 -5730.3818 -5820.6909 -6064.5767 -6171.0146 -5977.4404 -5745.9448 +129.1230 332.7003 329.7183 154.3474 33.4888 139.1896 351.1340 345.4635 157.6273 33.7236 129.9357 339.9262 338.9263 160.9752 28.9665 139.1393 348.0336 346.5751 166.3897 32.3597 129.4579 339.1181 348.8864 168.7055 28.2848 123.4920 346.8499 345.4668 169.7363 37.9085 141.9659 356.0339 349.0103 170.4440 26.9452 125.2843 336.0553 348.9879 166.9741 38.6125 128.1114 341.2112 342.5544 160.0416 32.9330 140.1928 350.5083 350.6596 163.1409 36.8195 134.5730 340.0482 343.5302 161.0638 24.5046 129.3764 346.5594 346.5191 159.1583 34.0546 144.3242 349.4932 348.4374 160.3716 27.2456 133.1507 337.5674 333.3565 148.9970 30.0136 127.5849 344.0629 334.4902 156.1162 29.6108 123.4201 330.6515 +4427.3916 4489.3242 4443.6616 4374.6875 4355.5977 4430.9946 4504.2725 4452.6372 4376.4468 4359.5249 4431.0098 4500.8213 4453.5220 4379.4858 4357.0488 4433.6680 4502.6230 4453.9312 4383.9756 4360.5796 4431.8438 4497.1714 4456.7905 4384.7759 4355.9106 4424.7549 4502.8066 4459.3677 4390.3418 4365.9951 4438.0127 4510.0518 4459.1880 4385.8530 4357.2388 4424.4644 4490.7612 4455.2256 4384.5054 4363.4541 4428.3984 4496.5811 4454.6216 4379.0986 4361.0688 4436.1924 4504.1704 4459.2520 4381.2983 4360.8428 4429.2559 4496.3237 4454.3438 4382.7583 4359.3511 4429.1323 4498.6929 4455.2295 4377.3032 4362.7583 4440.3125 4508.0435 4463.0435 4383.8174 4358.4033 4431.1138 4495.0493 4445.2896 4371.1992 4359.5410 4427.4883 4503.6045 4449.4648 4376.0557 4361.4292 4425.5811 4492.8369 +3351.6721 3321.2021 3329.2412 3375.0369 3395.7358 3355.5457 3332.5850 3335.5596 3376.2444 3397.3701 3353.5684 3330.6345 3336.8750 3379.3235 3396.5002 3354.4397 3333.3760 3337.9617 3382.0437 3398.5056 3355.1184 3327.9011 3338.8083 3383.8711 3396.0198 3348.1096 3330.7849 3340.5203 3387.8474 3405.2546 3362.2659 3338.2576 3339.6458 3385.2073 3397.7759 3346.9734 3320.0916 3338.4919 3383.4434 3402.9448 3350.6609 3325.5657 3335.4053 3380.2734 3401.0266 3357.9641 3333.5217 3340.5718 3381.8406 3400.8499 3353.2769 3325.3765 3335.5227 3380.6023 3398.1543 3348.9766 3328.3933 3338.8325 3378.1121 3401.2495 3360.5498 3336.6995 3342.7900 3380.6802 3395.9534 3351.0933 3322.8562 3330.0684 3374.0652 3398.7397 3349.6306 3333.5967 3336.2903 3377.1335 3398.3264 3347.7385 3323.1887 +2848.3250 2496.0273 2653.6799 3087.1816 3253.9504 2851.7466 2505.1631 2660.4663 3088.1162 3257.6255 2850.9753 2503.7664 2660.7075 3090.0527 3254.6348 2849.9392 2504.7803 2662.0786 3094.3672 3256.3923 2849.3862 2501.2258 2663.9995 3096.4304 3255.0964 2844.3469 2504.2048 2664.4270 3098.4880 3261.5576 2852.2996 2509.7529 2664.7778 3096.6538 3254.9514 2843.1326 2495.1306 2664.9543 3095.1870 3259.5444 2843.5540 2497.9180 2662.1035 3094.3711 3258.8425 2849.3777 2505.7175 2665.7632 3095.0771 3256.6648 2846.2292 2501.1064 2662.7830 3095.2732 3255.3987 2840.6135 2499.6978 2662.6182 3088.5977 3255.7415 2849.2493 2507.3584 2669.1013 3094.3345 3253.3738 2842.1865 2497.6838 2656.9385 3089.8049 3251.9951 2839.2964 2503.4873 2663.1707 3092.5544 3253.2681 2836.9919 2497.6973 +1540.6320 615.9078 1058.7129 2187.7131 2610.8042 1540.3558 619.3454 1065.2032 2190.7085 2612.9243 1540.9014 619.3715 1062.5872 2193.5706 2608.1580 1537.5496 620.4221 1064.3264 2194.2419 2609.0356 1533.9562 616.1178 1067.3365 2196.3535 2609.3513 1531.6685 616.8085 1065.4827 2196.1030 2611.6748 1531.3943 620.1871 1065.5559 2197.6536 2606.8491 1528.0332 609.7106 1069.0166 2197.0957 2612.0916 1526.0774 610.1937 1063.8203 2196.9438 2609.1650 1525.8079 617.6830 1066.2280 2195.2603 2609.6082 1527.3711 615.4489 1069.0764 2198.3875 2606.6697 1518.7888 611.0335 1067.1715 2187.2312 2603.8218 1523.8895 618.7226 1074.7714 2195.2769 2604.5037 1518.0515 609.0146 1061.1799 2195.3137 2596.4180 1514.7800 614.6226 1069.0522 2196.6868 2599.2122 1513.7568 612.5147 +2704.5454 2215.3523 2384.0122 2953.0334 3207.1736 2703.8496 2215.1997 2384.4612 2953.7791 3209.5608 2705.9587 2216.5518 2386.6152 2955.7795 3206.7273 2701.8474 2215.9570 2385.1880 2955.3499 3205.6189 2703.1553 2215.4463 2386.5605 2956.0498 3208.4744 2701.5608 2215.4749 2386.6584 2956.2244 3208.9775 2700.7446 2215.3857 2385.8604 2956.4004 3205.5210 2700.0908 2211.3379 2388.3508 2957.3286 3207.2554 2698.5596 2210.9026 2386.7119 2958.1108 3206.7717 2698.0300 2213.8447 2386.1851 2956.3965 3209.2549 2699.0605 2214.5449 2388.5884 2957.6140 3205.9363 2692.6423 2208.6819 2383.8335 2951.0000 3203.3325 2695.9727 2214.6055 2389.7500 2955.7197 3203.6702 2694.0537 2209.0759 2383.1060 2954.3420 3201.7979 2691.2463 2211.7024 2388.3440 2956.1902 3203.1274 2690.7778 2211.1133 +1818.7413 2071.3884 1946.5354 1667.8613 1570.1425 1849.7073 2102.0532 1940.7089 1621.9958 1507.3187 1799.1334 2061.0701 1970.0516 1671.7322 1552.6188 1820.5558 2090.7429 1971.2212 1670.3668 1551.0625 1828.1586 2074.3530 1955.9187 1643.9274 1502.8601 1777.7673 2080.7803 1982.4603 1701.5680 1571.0170 1840.5410 2092.2822 1972.1294 1684.8362 1527.9364 1795.7787 2067.2478 1981.6007 1693.2571 1569.3853 1807.8466 2042.2981 1937.2462 1655.4343 1554.1130 1836.2445 2092.4202 1992.6807 1664.7056 1543.5942 1817.7594 2063.5254 1947.3129 1659.7369 1547.8035 1837.2911 2111.2512 1984.0341 1684.1683 1573.9419 1855.9298 2066.2236 1935.4199 1621.7568 1509.7463 1807.9108 2067.3740 1948.1003 1630.2971 1562.5944 1827.1901 2105.7954 1973.9969 1649.5621 1539.1135 1776.3154 2052.9319 +-4115.0732 -3864.7102 -3955.3428 -4211.9863 -4322.9248 -4073.9187 -3819.5234 -3928.5183 -4220.6489 -4345.3047 -4114.0981 -3870.5059 -3959.5383 -4217.7793 -4341.9849 -4087.5757 -3831.8289 -3941.7681 -4215.6035 -4332.8906 -4104.8096 -3859.3840 -3922.2749 -4208.9985 -4355.2383 -4132.9316 -3843.4792 -3938.3254 -4202.0850 -4328.4658 -4092.2344 -3832.8076 -3928.3469 -4197.1650 -4344.6499 -4108.5522 -3860.6650 -3933.9331 -4213.3315 -4333.3989 -4117.1572 -3854.6934 -3940.3010 -4214.6860 -4343.4902 -4094.8501 -3841.2432 -3921.8076 -4213.1304 -4342.6885 -4102.9556 -3856.9465 -3945.2471 -4221.4648 -4353.3604 -4099.8579 -3833.2322 -3924.4954 -4208.7764 -4326.5000 -4082.4309 -3850.7283 -3946.5142 -4227.9688 -4355.5913 -4090.9409 -3847.8320 -3947.4714 -4224.7734 -4328.1060 -4107.1802 -3837.3320 -3951.8491 -4234.0894 -4339.1133 -4130.8618 -3873.1807 +-3713.3706 -3471.3713 -3556.1917 -3808.4922 -3918.0310 -3686.6313 -3439.7095 -3533.6531 -3807.9912 -3929.6785 -3709.7666 -3469.7368 -3553.6567 -3805.9146 -3932.3875 -3691.3035 -3446.0544 -3539.8599 -3805.4512 -3925.9592 -3705.3577 -3465.3584 -3529.7344 -3798.0081 -3937.2468 -3720.9495 -3451.6338 -3539.7100 -3796.1687 -3918.5659 -3694.8223 -3442.0649 -3532.8848 -3790.4668 -3934.3882 -3708.2432 -3466.0845 -3537.7800 -3804.5583 -3924.4919 -3715.7029 -3463.4202 -3543.4727 -3808.0630 -3928.8701 -3694.2903 -3451.3884 -3528.6755 -3802.5337 -3925.8506 -3701.4573 -3461.9270 -3545.2432 -3809.5950 -3940.3542 -3703.8455 -3447.6233 -3532.4534 -3807.2356 -3917.7935 -3686.2427 -3454.0208 -3542.1736 -3810.8745 -3937.9951 -3695.0544 -3455.2583 -3551.8506 -3817.1738 -3922.7434 -3707.2876 -3452.4124 -3554.3804 -3818.1475 -3926.3513 -3717.2979 -3476.4912 +3395.3430 3618.1372 3571.1902 3351.9963 3236.6863 3404.5830 3634.6067 3585.3916 3356.3723 3235.4731 3398.6763 3626.0908 3579.5137 3360.4033 3233.4736 3411.2297 3634.7524 3586.8313 3361.8074 3235.1001 3400.6199 3623.0779 3589.6729 3366.0059 3230.6140 3392.2175 3633.3889 3585.2969 3367.1201 3241.0244 3407.7683 3641.9551 3589.7454 3369.3931 3229.9585 3395.0898 3618.7139 3586.3750 3360.5398 3237.8706 3393.3252 3625.3562 3582.8208 3357.8105 3236.3718 3407.6724 3632.8638 3590.5981 3361.7144 3239.5181 3402.3130 3625.0142 3582.1208 3358.7383 3226.5752 3399.4055 3629.3992 3585.6731 3352.4468 3236.7158 3412.6538 3635.3223 3588.1125 3359.0874 3229.3896 3403.0879 3626.2415 3571.7021 3344.9834 3232.3555 3395.5193 3627.6326 3569.7815 3348.4167 3232.7244 3393.9277 3614.2373 +6154.5313 6290.2520 6252.8594 6121.2822 6054.4624 6161.8965 6303.5142 6264.7842 6123.2954 6057.1514 6157.1426 6299.8555 6262.7109 6128.9038 6053.6816 6162.7676 6302.1958 6266.7358 6131.3652 6056.0332 6156.0171 6294.8354 6270.0132 6134.2339 6054.7627 6152.7495 6301.6543 6268.2134 6135.3833 6063.9468 6165.4912 6310.5566 6270.5757 6134.3252 6053.1250 6152.7305 6288.4873 6268.3809 6132.2280 6061.3193 6154.1899 6296.2012 6265.5200 6128.0068 6057.1475 6163.5415 6304.2500 6271.8643 6131.2793 6060.5078 6159.1099 6297.3115 6268.6602 6128.6465 6050.8877 6153.8154 6297.1250 6264.7773 6123.1523 6058.6284 6167.4312 6306.9897 6273.8892 6131.9673 6053.1807 6157.1968 6292.1934 6252.8081 6113.4224 6052.2524 6152.9878 6299.6641 6255.9580 6123.4858 6055.5747 6150.1582 6289.0151 +2234.8923 2118.1963 2143.6089 2280.8938 2349.8511 2235.7249 2126.2607 2151.6440 2285.8542 2355.3596 2238.1436 2129.3789 2152.2815 2288.8020 2351.7915 2238.9077 2126.6882 2153.4070 2290.3740 2353.4890 2235.8157 2122.4685 2155.4526 2290.3357 2352.2229 2232.7522 2128.4573 2155.6062 2296.0305 2360.2930 2241.7563 2135.4358 2156.7412 2292.0762 2351.4958 2231.1619 2116.1094 2156.4172 2292.4390 2357.2854 2232.2578 2122.7490 2155.7163 2290.8997 2357.8806 2238.6907 2128.1277 2156.7383 2291.2517 2357.2561 2234.5847 2123.8486 2155.4421 2292.4692 2351.9915 2229.6787 2123.0454 2152.5405 2281.2705 2353.4702 2240.7544 2134.1191 2164.1641 2293.2085 2351.2349 2230.1587 2117.8174 2144.2119 2279.3853 2350.8713 2228.4209 2124.9304 2149.3604 2287.2097 2352.7690 2227.3438 2119.3625 +5830.5869 5490.1938 5614.6230 6015.6309 6187.8184 5830.1431 5498.7344 5622.4004 6020.0469 6194.8472 5832.7666 5501.1099 5623.0308 6023.7876 6190.0234 5832.7485 5500.2837 5624.8701 6025.8643 6190.8066 5830.0840 5494.4819 5627.1333 6026.7573 6190.4819 5827.2153 5500.6567 5626.3530 6030.8999 6197.5200 5834.0972 5505.8945 5627.2393 6027.7637 6190.1465 5824.0825 5488.6582 5627.3125 6027.3218 6195.5425 5825.4766 5493.1021 5625.8530 6026.6025 6193.9517 5831.1431 5498.9180 5627.5117 6026.0278 6194.4800 5827.4219 5493.8135 5626.3540 6027.7275 6189.1816 5820.4443 5491.1499 5622.3066 6015.5688 6189.4019 5829.1792 5503.2686 5632.7017 6025.7363 6187.4722 5820.1221 5486.2148 5614.6201 6016.0703 6184.6851 5817.3672 5494.0552 5620.6255 6019.8442 6186.2861 5815.4326 5488.8442 +2651.2358 1319.7871 1921.2422 3519.6948 4138.7402 2649.0791 1322.9415 1932.2917 3523.8535 4144.8257 2652.9990 1325.3306 1928.7823 3528.8604 4137.2300 2645.0000 1323.5195 1929.3792 3529.8418 4136.8535 2641.7720 1320.3867 1935.5260 3532.3489 4141.3042 2639.7258 1321.3706 1930.5250 3535.5632 4144.0249 2639.9414 1327.9915 1932.3912 3535.7637 4136.5845 2633.4011 1310.9507 1937.9825 3537.5549 4144.8018 2633.3335 1313.1594 1933.6934 3537.4700 4140.3384 2631.7214 1320.9663 1933.2949 3535.0286 4139.7720 2632.7280 1317.9015 1936.7596 3537.0234 4136.0679 2621.4160 1309.1378 1932.8512 3517.7798 4130.0215 2627.2915 1325.4042 1947.0144 3533.2290 4133.4043 2619.8076 1306.7006 1924.6993 3530.4153 4119.8276 2612.6128 1314.3872 1935.9771 3532.8372 4123.7969 2614.5090 1312.5441 +2316.1338 -1995.9020 19.7999 5202.0015 7174.3467 2315.3984 -1997.0187 38.8716 5204.5762 7177.1528 2318.2673 -1999.8344 25.1194 5216.2168 7163.0581 2292.1296 -1997.4409 33.6344 5220.6167 7164.9707 2293.5403 -1998.6586 45.6498 5226.2095 7170.0366 2284.1892 -2005.6257 33.8042 5231.5439 7174.2993 2276.6204 -1994.9247 40.5663 5242.8086 7163.5791 2274.1453 -2014.3715 57.1130 5244.1504 7177.6157 2271.4580 -2017.4935 47.9289 5245.4893 7162.1553 2253.9055 -2002.9482 50.0039 5242.3569 7164.1660 2265.2109 -2000.5208 58.8425 5247.6299 7166.5596 2240.1658 -2020.3053 59.5526 5209.2642 7144.8086 2241.6782 -1995.2462 83.9228 5230.2725 7155.4219 2237.1233 -2016.7273 48.1636 5258.3369 7118.3359 2221.2869 -2009.6974 70.9542 5245.4150 7126.3647 2219.8826 -2009.0660 +-12347.9434 -12092.1973 -12217.3477 -12507.4209 -12603.6758 -12314.2354 -12067.5469 -12237.4912 -12555.2646 -12660.1660 -12371.7158 -12107.1240 -12205.2480 -12485.3848 -12610.3389 -12349.9355 -12082.6943 -12198.2295 -12502.4844 -12615.3545 -12338.4512 -12102.5137 -12227.2236 -12540.4521 -12666.0713 -12388.5635 -12092.9893 -12192.5908 -12460.2842 -12591.0420 -12339.8809 -12078.9912 -12199.6426 -12486.2432 -12646.5479 -12377.8877 -12105.9854 -12189.3242 -12458.1094 -12596.2568 -12399.5908 -12147.3301 -12239.4668 -12514.4385 -12613.5313 -12338.3428 -12083.9756 -12180.1680 -12510.4805 -12630.9170 -12368.2070 -12108.4053 -12217.4463 -12502.4883 -12621.3340 -12341.4121 -12066.2334 -12192.0830 -12489.5371 -12589.9043 -12317.2676 -12108.8057 -12233.4395 -12551.6758 -12658.4883 -12367.6094 -12098.9443 -12235.8340 -12535.5684 -12599.9893 -12339.4414 -12067.4551 -12197.7412 -12517.5293 -12638.0781 -12400.9004 -12115.0938 +-16782.5762 -16521.5977 -16657.0820 -16956.4980 -17046.6953 -16722.6738 -16483.7070 -16670.1855 -16986.0215 -17092.4961 -16813.1621 -16569.2656 -16674.7773 -16920.5449 -17038.5000 -16790.7363 -16526.9375 -16649.1367 -16935.1934 -17041.8027 -16773.1328 -16564.7891 -16660.8730 -16957.3066 -17088.1875 -16826.1836 -16533.5938 -16639.3379 -16890.9648 -17016.8223 -16788.1230 -16528.2285 -16635.7344 -16901.3281 -17072.6738 -16820.5098 -16537.6855 -16625.2246 -16892.5137 -17027.4336 -16852.8652 -16579.3047 -16674.9863 -16946.2891 -17050.8496 -16766.1738 -16499.9668 -16632.5215 -16956.7813 -17057.2578 -16802.3145 -16548.6563 -16651.4941 -16939.6914 -17060.5586 -16769.9160 -16504.2813 -16613.5469 -16913.4805 -17039.2637 -16778.8555 -16555.2715 -16672.7148 -16989.6328 -17090.8867 -16801.8496 -16523.9766 -16674.0625 -16951.9297 -17027.6309 -16771.0293 -16492.4395 -16638.4512 -16967.5195 -17085.7500 -16843.5605 -16567.0371 +-10239.5723 -9980.4209 -10086.1172 -10356.0088 -10460.4355 -10171.0732 -9927.9043 -10067.0361 -10367.8232 -10496.2061 -10248.6904 -10007.3682 -10100.3096 -10353.4600 -10477.9844 -10221.9131 -9955.0801 -10081.7539 -10344.9941 -10463.4453 -10227.9834 -9996.9775 -10055.3760 -10352.1025 -10502.8701 -10267.7773 -9958.0752 -10062.8174 -10331.3135 -10466.9717 -10222.6289 -9955.0615 -10053.1104 -10324.8379 -10488.3877 -10246.9863 -9986.0225 -10065.0869 -10350.2939 -10473.7197 -10256.9688 -9985.7080 -10066.6162 -10354.6523 -10487.8086 -10217.0283 -9952.0713 -10053.2500 -10360.7412 -10483.9277 -10231.3740 -9981.3857 -10076.8896 -10358.9561 -10484.4082 -10217.9453 -9945.7412 -10046.3389 -10342.3496 -10472.1543 -10223.8867 -9984.0879 -10077.1885 -10385.5986 -10501.0381 -10216.7920 -9970.3418 -10076.2139 -10350.6348 -10459.7539 -10227.7852 -9948.5254 -10077.8164 -10383.4980 -10487.9600 -10276.7939 -10005.1611 +-7566.8804 -7309.3652 -7396.4839 -7657.6563 -7776.1665 -7514.8003 -7263.8105 -7368.5615 -7663.1763 -7793.5996 -7564.9424 -7316.2148 -7402.0176 -7662.8306 -7795.6929 -7538.0981 -7274.5161 -7387.9722 -7658.7642 -7784.9414 -7555.6699 -7308.1377 -7359.3770 -7652.3799 -7805.4160 -7580.8511 -7282.9639 -7379.7769 -7647.5850 -7782.6553 -7543.7998 -7273.6030 -7367.3164 -7641.7935 -7794.5552 -7556.6260 -7306.6387 -7375.7822 -7661.3662 -7791.2295 -7570.9487 -7298.3062 -7372.6914 -7657.6895 -7796.6851 -7544.4541 -7285.5972 -7363.8423 -7663.1299 -7794.0967 -7551.3105 -7298.8921 -7380.6221 -7660.3413 -7799.5298 -7550.1455 -7274.9551 -7366.5059 -7660.8271 -7785.0244 -7543.8140 -7297.3550 -7377.1572 -7672.4727 -7801.6353 -7538.2529 -7291.4390 -7383.7119 -7661.3755 -7779.8677 -7559.0098 -7286.0703 -7397.9209 -7684.8149 -7793.6899 -7587.5356 -7318.6323 +-3013.4185 -2767.0986 -2858.3237 -3113.2014 -3226.5220 -2983.6433 -2734.3325 -2832.2590 -3114.4729 -3235.2048 -3009.1401 -2766.5303 -2859.7954 -3115.7351 -3239.7141 -2986.0061 -2736.9919 -2844.1838 -3114.0491 -3234.2283 -3003.5142 -2762.6074 -2829.6670 -3103.3779 -3243.7510 -3018.9199 -2746.5247 -2844.0598 -3105.1814 -3226.7981 -2990.7402 -2735.4558 -2832.7693 -3100.7661 -3237.0315 -3002.1624 -2760.7522 -2837.1033 -3112.1604 -3233.8638 -3018.2473 -2755.6736 -2838.6179 -3112.3599 -3236.1550 -2993.0530 -2748.8455 -2830.1304 -3111.7783 -3232.9614 -3000.8181 -2755.2368 -2841.6018 -3113.1074 -3246.8396 -3002.2129 -2741.6479 -2833.1445 -3113.7771 -3226.9248 -2986.1223 -2748.5911 -2838.3354 -3116.7644 -3240.9600 -2990.8433 -2749.4524 -2848.8105 -3121.3921 -3227.6555 -3006.6545 -2749.5435 -2858.5837 -3128.9446 -3235.7478 -3020.9705 -2768.8440 +133.0378 365.6564 285.5623 38.9087 -72.6954 142.4728 383.4427 302.4911 45.1799 -69.5415 139.0082 376.8066 295.9261 49.3226 -76.6756 148.3079 383.0428 301.5494 48.1214 -73.3468 138.5770 371.4578 307.0584 54.4246 -76.6460 131.1001 383.1477 299.5379 52.8676 -65.6321 146.5768 392.2437 308.1918 54.4432 -77.1972 136.9411 367.8087 302.4799 48.2022 -72.5656 129.7955 375.3024 300.7149 45.6956 -71.2637 145.6737 381.1020 308.0244 50.3428 -64.7603 144.3591 376.5405 299.3782 47.5235 -79.3109 136.7369 376.2632 299.8798 38.1487 -70.2261 150.7895 384.5934 307.0725 50.0874 -75.0400 142.9073 376.7013 289.6129 32.9833 -74.4173 135.0746 378.8229 286.8612 36.2719 -73.2063 132.9429 365.8214 +3079.3635 3308.5959 3230.9919 2982.3542 2870.2883 3082.4668 3321.6187 3242.8640 2990.7310 2878.3669 3086.3713 3324.1550 3240.1885 2993.2710 2869.9956 3091.2195 3324.7422 3243.4333 2992.3770 2869.6526 3081.8289 3312.2605 3244.8359 2995.0078 2869.9229 3080.3450 3324.7896 3240.8059 2993.4470 2878.2461 3089.4800 3330.8188 3246.0474 2992.1624 2870.1614 3080.6702 3307.7000 3241.7432 2990.5217 2871.2561 3074.5830 3317.2156 3241.7188 2988.7837 2873.6982 3087.3291 3320.0378 3243.1152 2989.1604 2878.6350 3086.7515 3318.5610 3241.0557 2990.9028 2867.6506 3079.0730 3313.7009 3234.6755 2975.1753 2870.5723 3090.5083 3328.6545 3248.2490 2995.9993 2871.2725 3081.7295 3312.9883 3228.4138 2973.2805 2865.4343 3075.7161 3315.1138 3225.3271 2979.1663 2867.3760 3074.2375 3308.7380 +3455.7190 3448.7451 3412.2065 3408.7058 3430.7671 3456.9221 3457.8643 3421.7378 3416.9473 3438.5457 3459.1223 3462.6636 3422.4634 3420.4995 3433.5754 3461.5596 3460.3450 3423.3567 3420.0190 3433.4346 3454.9500 3453.5732 3425.8000 3421.5037 3434.1116 3455.0317 3462.4016 3424.9875 3424.5742 3442.0654 3462.8218 3466.5972 3425.3298 3419.2285 3433.2100 3452.8557 3448.5237 3424.2937 3421.0259 3438.2283 3452.5698 3456.2642 3425.3840 3419.3064 3440.3962 3460.6377 3459.9629 3425.2378 3418.6362 3440.4558 3457.8850 3455.5691 3424.1133 3420.2644 3432.8999 3450.7419 3452.3342 3416.5142 3406.0164 3435.0547 3461.2991 3466.2683 3431.7322 3423.0859 3434.3611 3451.8323 3448.5432 3410.4211 3404.0525 3430.9412 3446.4133 3454.0315 3413.4185 3411.8132 3433.5610 3447.5977 3449.3755 +3932.6611 3781.6926 3796.7334 3955.8926 4049.1472 3930.8831 3788.8181 3805.6577 3964.3704 4059.7693 3936.0120 3794.7183 3806.1489 3966.5408 4054.2290 3936.4587 3792.0762 3805.8254 3967.1941 4054.4314 3931.2126 3787.1394 3809.2205 3969.2336 4056.6401 3932.5610 3794.9019 3809.3054 3973.0176 4062.3628 3938.4077 3799.0923 3809.1921 3968.4412 4054.2698 3928.0999 3782.0474 3809.5569 3971.5540 4059.6907 3928.0061 3788.8489 3810.1904 3969.6348 4062.6348 3935.7637 3792.0686 3810.4502 3968.6487 4062.0078 3933.4321 3789.5713 3810.8425 3970.7568 4054.5652 3926.4612 3783.8730 3801.3230 3955.8147 4054.6887 3936.6311 3800.1370 3819.7874 3973.7000 4056.4534 3927.5640 3782.1233 3797.3230 3956.0320 4051.8901 3923.7417 3788.6802 3801.7510 3964.9426 4055.9177 3924.9329 3785.2739 +3935.5552 3022.2036 3386.9172 4459.7036 4904.1904 3934.7688 3027.1885 3396.9080 4465.3364 4912.2466 3939.2517 3032.0610 3395.2290 4469.5645 4905.9946 3933.7314 3028.5879 3395.7534 4470.6826 4904.7432 3929.7813 3024.0925 3401.5432 4472.1958 4908.7124 3930.7671 3029.4465 3397.4648 4475.3477 4914.1582 3931.6619 3034.5840 3399.0100 4474.5503 4905.7393 3923.4380 3017.7466 3402.5435 4476.5835 4912.7363 3924.4277 3021.7312 3401.0920 4476.9004 4910.9160 3925.6614 3027.5110 3400.2732 4473.4238 4911.5786 3926.8198 3025.9690 3403.5432 4477.9448 4906.0029 3915.1389 3016.8596 3395.0305 4458.4946 4901.5757 3924.8635 3035.1941 3412.7153 4476.2656 4904.7510 3914.7498 3016.1685 3390.2109 4466.7871 4893.5850 3909.6780 3021.4646 3398.7144 4472.1602 4899.8130 3911.8257 3021.2705 +-160.4619 -1564.1030 -1198.1097 337.9693 1099.4744 -165.8539 -1562.9869 -1189.7875 345.4800 1109.7714 -159.8270 -1553.6340 -1187.7314 348.2901 1101.7805 -166.3631 -1559.5458 -1189.0793 348.4191 1100.1740 -169.5037 -1564.0056 -1183.4055 351.1584 1105.2360 -168.0952 -1559.9243 -1187.6681 353.4644 1109.0103 -170.3255 -1556.6736 -1185.0386 352.5597 1101.3645 -178.5873 -1570.7762 -1181.2175 357.6832 1107.7578 -177.2433 -1568.5300 -1181.0581 360.2924 1108.4319 -176.1108 -1563.0233 -1184.0085 354.5709 1109.3031 -176.0279 -1563.3396 -1178.1703 360.2425 1103.0795 -188.8068 -1576.5104 -1191.4257 336.3477 1096.1803 -182.9901 -1554.4315 -1168.0138 357.7036 1100.4465 -190.8750 -1575.1255 -1194.2993 348.4916 1089.5504 -195.8948 -1568.3833 -1181.3673 354.4986 1095.3519 -195.0958 -1568.8322 +-13711.6563 -13461.6973 -13590.3350 -13899.2129 -13987.1924 -13714.4102 -13487.7939 -13603.7383 -13875.1309 -13977.4268 -13715.2246 -13466.1758 -13576.1084 -13845.4238 -14005.1572 -13752.5381 -13459.5117 -13566.8115 -13854.0527 -13994.4375 -13744.1982 -13473.8828 -13555.8174 -13862.1602 -13976.8545 -13707.2783 -13443.0068 -13565.4443 -13837.5410 -13990.3604 -13743.3125 -13441.2949 -13564.7715 -13861.6611 -14009.8496 -13721.0254 -13453.8311 -13561.2178 -13865.4404 -14051.8213 -13757.3906 -13476.7354 -13577.0820 -13861.7744 -13985.9727 -13704.4834 -13470.0049 -13587.4873 -13872.2178 -13979.1689 -13714.7412 -13448.2783 -13555.3613 -13857.6943 -13984.9678 -13724.2988 -13475.4873 -13593.2139 -13918.4531 -14020.5791 -13748.6592 -13461.7354 -13572.9375 -13862.7500 -13981.8652 -13730.2510 -13497.8994 -13597.5596 -13874.0195 -13987.1875 -13731.8623 -13478.9473 -13600.8828 -13897.0059 -14004.0781 -13738.7070 -13462.0439 +-12468.0254 -12215.3174 -12330.5664 -12628.2637 -12732.4902 -12461.4482 -12223.6416 -12331.2002 -12607.9307 -12720.8975 -12463.2197 -12215.9150 -12321.5703 -12595.9590 -12744.3975 -12481.5820 -12201.6182 -12311.8242 -12590.7295 -12737.2129 -12491.1953 -12221.5840 -12292.2383 -12595.9629 -12721.5508 -12459.4492 -12185.8760 -12309.4268 -12583.5596 -12730.4199 -12474.1436 -12190.4512 -12303.3174 -12595.4521 -12739.9287 -12467.7764 -12207.7598 -12302.1680 -12606.4209 -12767.2236 -12494.5479 -12218.5000 -12308.2393 -12600.6445 -12728.2627 -12453.2158 -12211.3086 -12320.8018 -12608.5977 -12714.6875 -12453.6035 -12197.7031 -12296.9385 -12587.8643 -12721.7891 -12474.4883 -12212.7832 -12325.5264 -12640.5498 -12751.8740 -12477.1846 -12200.6074 -12303.4531 -12596.2422 -12719.0391 -12465.4697 -12224.8857 -12321.6807 -12606.5225 -12726.3994 -12476.7666 -12214.4980 -12341.0020 -12631.7314 -12733.0166 -12483.6973 -12206.9668 +-6279.2119 -6021.9585 -6119.4502 -6394.6812 -6517.0347 -6254.3408 -6005.5771 -6100.6733 -6385.9805 -6511.5518 -6272.1133 -6022.5845 -6117.4585 -6389.4248 -6530.1992 -6262.3691 -5997.7607 -6107.6143 -6383.8525 -6526.4722 -6277.5425 -6020.2471 -6082.4609 -6381.6128 -6522.3643 -6277.1768 -5993.0723 -6104.8188 -6380.0747 -6514.3433 -6264.0942 -5993.2847 -6097.6616 -6378.9980 -6517.0059 -6269.0781 -6020.8032 -6100.3501 -6396.4404 -6534.6147 -6290.9731 -6019.8428 -6096.5059 -6391.0786 -6523.6128 -6265.9141 -6012.7427 -6102.9102 -6395.8335 -6513.6533 -6261.1387 -6009.1436 -6095.7202 -6380.4048 -6521.7217 -6279.4219 -6009.7793 -6113.1870 -6413.1260 -6527.9829 -6272.5850 -6010.2529 -6094.7363 -6389.5952 -6517.1289 -6263.2881 -6018.6992 -6111.5820 -6395.0137 -6520.0000 -6284.6494 -6020.5381 -6135.3452 -6416.2607 -6523.0381 -6295.4893 -6024.4272 +-382.3864 -128.2416 -221.3393 -485.5426 -605.8494 -348.6319 -98.3607 -195.7209 -482.9977 -609.6306 -377.1732 -129.0201 -223.5138 -487.1660 -622.7101 -357.0513 -96.5434 -208.6060 -484.2057 -615.7518 -376.1822 -126.9419 -183.7860 -477.1321 -621.9897 -386.8064 -105.0336 -207.0536 -476.8456 -607.4243 -362.1664 -97.0784 -194.9682 -473.6904 -612.3857 -370.5302 -124.4405 -201.5173 -487.7882 -619.6482 -390.5169 -120.1298 -197.2912 -483.8896 -617.8528 -366.8579 -114.4436 -198.5069 -489.3347 -614.1026 -367.6913 -116.9102 -200.0674 -480.3210 -620.5793 -376.9726 -104.9568 -201.8402 -497.0790 -615.1002 -367.3267 -114.8268 -197.2151 -489.6419 -616.5414 -362.5165 -114.7291 -210.3407 -491.1219 -610.6059 -384.8502 -118.1424 -230.3987 -509.4430 -617.7911 -400.5801 -132.3024 +-999.8619 -752.0541 -846.6862 -1110.2363 -1231.1912 -979.5341 -725.2262 -821.3141 -1103.1012 -1226.2803 -991.2209 -742.6960 -844.5821 -1108.8807 -1242.0973 -975.7686 -718.8120 -828.5295 -1106.4609 -1234.6602 -992.6070 -745.0222 -817.5226 -1098.7917 -1236.9785 -996.7574 -728.8017 -832.3084 -1101.3182 -1223.6394 -978.7265 -721.2924 -821.7941 -1098.9366 -1227.7504 -985.9566 -741.9002 -823.6130 -1107.5037 -1231.6438 -1004.7062 -740.2587 -823.3532 -1103.1852 -1229.1578 -981.9793 -733.2432 -823.7121 -1106.4474 -1227.5529 -984.7603 -733.6862 -819.3879 -1098.2504 -1237.5583 -993.0692 -730.0275 -828.0729 -1115.4381 -1227.7212 -978.9077 -727.8522 -818.9592 -1106.8147 -1229.6377 -983.7939 -734.1611 -833.7988 -1112.7273 -1228.2982 -999.5472 -739.3124 -846.6168 -1119.1729 -1229.9194 -1003.2809 -743.5562 +3506.4626 3747.4905 3653.2527 3383.3381 3261.7310 3505.8379 3757.9482 3668.0388 3395.6909 3276.9556 3510.8406 3764.2458 3660.6631 3391.6912 3262.8530 3516.6907 3768.0349 3667.7979 3392.3921 3261.9980 3504.2046 3749.2073 3670.5298 3396.2212 3268.1187 3510.4509 3767.7881 3663.8130 3394.1543 3275.3501 3517.8921 3771.5757 3669.7351 3392.4573 3270.8037 3508.1934 3751.8801 3668.9209 3389.2273 3262.9548 3497.5825 3754.7014 3667.7471 3392.6184 3273.0789 3513.7100 3758.7734 3665.1567 3390.5684 3278.4971 3514.0710 3760.3818 3672.8801 3398.1035 3266.6721 3502.0901 3753.6897 3653.5767 3371.5122 3264.7764 3510.7656 3767.5750 3675.0471 3396.4395 3271.8926 3505.8479 3751.4744 3653.4414 3375.1353 3262.2834 3495.3962 3749.0481 3645.9292 3378.4902 3264.7786 3498.9028 3750.0073 +4641.4893 4860.0640 4770.2764 4524.1025 4418.0581 4639.2749 4868.0869 4781.3784 4533.7021 4431.3647 4646.8481 4877.4956 4780.1025 4533.8970 4421.6118 4650.2095 4875.5068 4784.4219 4534.7002 4420.0845 4640.7407 4862.8315 4783.0596 4534.8735 4423.3921 4643.2275 4877.1416 4783.3193 4535.3574 4429.9668 4650.6680 4878.8604 4783.4741 4531.3384 4422.4233 4638.7441 4860.2236 4781.7100 4532.8345 4422.3247 4634.4819 4868.8037 4784.3647 4532.0615 4427.7339 4648.1943 4869.6592 4780.4561 4531.2515 4430.2095 4644.9419 4868.7051 4785.3511 4535.8545 4421.1475 4637.1880 4863.0903 4769.9419 4514.9487 4419.7749 4648.0366 4880.5684 4790.7627 4540.7168 4425.3877 4640.4272 4860.5415 4768.1099 4515.2646 4417.6274 4633.1343 4862.9771 4766.7671 4521.9653 4422.1528 4636.8999 4863.4014 +6502.4263 6511.3164 6458.2012 6428.8442 6446.1279 6501.1226 6518.7314 6466.1226 6437.6309 6456.4663 6506.8608 6525.8311 6468.0000 6438.7407 6449.5386 6507.3496 6522.2690 6466.7871 6438.8823 6450.1611 6500.6577 6515.2051 6469.7178 6440.8735 6452.6528 6503.0474 6525.2612 6469.2959 6443.4482 6459.4253 6510.9307 6529.8159 6470.3237 6438.3921 6451.3931 6500.1685 6512.1157 6469.9023 6441.3296 6455.0532 6499.0063 6518.4014 6471.2329 6440.5420 6458.0508 6509.1665 6522.0063 6469.1499 6437.4150 6459.0737 6505.1553 6518.9136 6470.7964 6441.5347 6450.4272 6496.6431 6512.8188 6460.3530 6425.6733 6450.7925 6507.4800 6529.8086 6478.4395 6445.0015 6452.5010 6498.1104 6510.6885 6455.3340 6424.5254 6448.0215 6494.1255 6517.0112 6460.2017 6432.7739 6450.1655 6495.8760 6513.5825 +3210.9365 2682.5149 2800.9834 3376.1680 3670.0339 3207.6255 2685.8711 2809.8174 3382.3962 3680.3215 3213.9324 2695.3323 2812.4634 3387.2886 3675.9104 3211.6372 2689.4531 2810.8682 3387.5764 3674.1506 3206.7563 2683.9602 2815.3901 3388.5425 3677.7861 3209.6799 2691.6726 2813.1404 3390.7173 3683.3311 3211.9438 2694.9792 2813.9866 3388.0342 3674.3184 3202.1265 2679.0374 2816.4292 3391.2419 3680.3811 3203.0791 2685.4331 2816.8167 3393.0212 3682.0408 3208.4309 2688.3901 2813.3936 3389.3264 3682.2605 3206.6216 2686.0815 2817.0640 3392.6738 3675.7080 3197.4126 2678.5132 2805.0583 3373.3621 3672.8428 3206.4319 2698.1106 2826.5286 3393.8125 3675.4504 3196.8860 2678.1724 2802.9751 3378.1572 3668.7017 3193.7427 2684.2754 2810.7766 3387.8789 3673.7712 3194.8125 2683.3967 +-8655.6260 -8401.7988 -8517.7451 -8815.8682 -8936.4834 -8683.9707 -8427.2666 -8508.7217 -8782.8350 -8893.5273 -8638.1592 -8385.8125 -8498.0479 -8796.8438 -8934.1885 -8668.3076 -8388.7031 -8499.4346 -8781.6475 -8945.4727 -8668.8750 -8398.0176 -8484.0996 -8778.1416 -8892.4424 -8630.1895 -8373.8945 -8501.5713 -8779.5068 -8925.3691 -8655.5449 -8385.4014 -8506.3496 -8799.8047 -8911.1563 -8648.6777 -8400.6172 -8486.9951 -8814.8340 -8965.0469 -8674.1650 -8410.9375 -8493.8242 -8795.2969 -8910.6846 -8653.4307 -8416.0137 -8513.6387 -8794.4775 -8895.6768 -8634.7520 -8382.4150 -8479.8018 -8770.5205 -8916.5625 -8674.7695 -8421.1953 -8544.2637 -8851.6123 -8942.2627 -8665.0313 -8386.9014 -8481.7002 -8771.4102 -8900.1260 -8659.7432 -8423.0801 -8512.6680 -8809.8906 -8926.5938 -8679.3203 -8431.0205 -8542.7852 -8811.9355 -8915.9629 -8656.3271 -8387.3613 +-6350.8145 -6095.7744 -6207.0410 -6504.3799 -6634.3403 -6381.7046 -6116.4385 -6194.5244 -6470.7295 -6587.7217 -6334.7085 -6080.0845 -6189.5903 -6489.5986 -6626.8149 -6362.7241 -6080.3560 -6189.2383 -6476.4849 -6635.7197 -6362.9199 -6097.2983 -6182.1812 -6469.6123 -6587.4746 -6329.8345 -6071.3267 -6195.6064 -6474.8589 -6616.0850 -6351.5928 -6087.1196 -6200.6343 -6491.5469 -6602.1880 -6351.4604 -6101.3589 -6180.7412 -6505.4453 -6654.7070 -6375.9805 -6111.4785 -6189.4443 -6491.1709 -6605.8242 -6359.7129 -6114.2490 -6206.9580 -6487.9248 -6593.0889 -6339.6113 -6085.3716 -6176.3340 -6467.7041 -6617.5190 -6380.5273 -6127.0327 -6240.9365 -6543.3057 -6636.0610 -6367.3369 -6085.3818 -6177.0068 -6467.3286 -6600.3579 -6366.3965 -6123.8262 -6208.2900 -6508.8960 -6627.1074 -6383.2720 -6132.3008 -6235.9561 -6505.1289 -6614.3184 -6359.7764 -6090.8286 +-6777.4204 -6525.8530 -6624.1846 -6905.5317 -7036.7695 -6778.5283 -6523.6123 -6605.9795 -6887.0894 -7010.9712 -6767.3027 -6513.0239 -6618.1841 -6900.1772 -7037.6802 -6767.2803 -6500.8584 -6609.6802 -6894.6318 -7037.9678 -6779.4673 -6524.6387 -6599.3096 -6889.3589 -7018.5518 -6767.1626 -6497.8677 -6613.7041 -6891.8486 -7019.6309 -6764.9165 -6503.5449 -6612.5752 -6894.0278 -7017.1675 -6769.4072 -6526.2783 -6604.6108 -6906.2129 -7042.7549 -6795.2178 -6526.0625 -6606.6187 -6901.5854 -7024.5259 -6774.9214 -6523.1274 -6617.1382 -6900.6899 -7013.9849 -6763.1235 -6511.4155 -6598.7764 -6886.6118 -7028.3560 -6790.0469 -6528.4653 -6635.6880 -6931.9941 -7036.9912 -6779.2871 -6510.2583 -6595.5923 -6889.0708 -7017.7212 -6776.6006 -6529.8999 -6622.6978 -6912.1494 -7036.8984 -6794.0332 -6536.9956 -6647.1929 -6916.5947 -7028.7646 -6788.9116 -6522.1162 +1760.9994 2011.0172 1914.9426 1639.5608 1511.2947 1767.8580 2021.2905 1935.1027 1653.3094 1529.1147 1768.8418 2022.4136 1919.0938 1644.2817 1505.8726 1776.6060 2036.7186 1930.2091 1647.5681 1511.3567 1760.7378 2013.0405 1939.3556 1651.7563 1520.4014 1766.5804 2035.0676 1925.6598 1649.5050 1525.0227 1775.4912 2037.0585 1930.3170 1649.7667 1524.6584 1770.0815 2013.0457 1933.3048 1640.6559 1508.5618 1748.3075 2013.3359 1933.5587 1645.9591 1520.2001 1767.7681 2019.9913 1926.5001 1642.9459 1526.5355 1772.7023 2024.7625 1940.0298 1655.7909 1514.9899 1754.0586 2017.0594 1914.6833 1620.7770 1512.2340 1766.1117 2028.9141 1942.2546 1652.5280 1524.2332 1766.6023 2014.1619 1919.3418 1633.0000 1511.3239 1750.2244 2008.6357 1899.9965 1629.0587 1515.7495 1749.1136 2013.6207 +3015.9751 3258.0037 3155.3870 2879.8872 2756.0354 3015.7366 3264.2654 3171.2102 2895.8657 2777.5730 3022.1812 3274.1948 3161.8013 2886.3264 2758.1836 3026.5146 3280.6428 3169.2273 2888.8481 2760.3115 3012.1868 3260.4861 3175.9038 2893.8684 2770.0974 3022.5796 3279.6816 3166.7327 2891.4065 2774.3457 3027.0383 3280.7673 3168.8540 2888.9890 2773.5164 3019.4778 3261.9810 3170.4966 2883.3127 2760.9595 3003.6733 3260.8115 3172.0894 2890.4238 2772.5044 3021.9512 3267.5295 3165.2266 2887.4202 2776.9583 3024.2791 3272.3918 3180.8716 2898.9143 2767.3572 3010.4905 3261.6235 3153.8208 2862.4163 2761.0347 3019.6443 3277.5947 3181.7292 2894.0447 2773.3186 3017.3523 3259.4084 3158.5103 2874.3574 2760.1829 3004.8638 3255.2996 3145.2874 2876.1875 2767.9871 3007.9280 3262.7632 +2452.9490 2664.8789 2568.4709 2319.1951 2215.7542 2445.7495 2670.9622 2578.6804 2332.3242 2233.7859 2457.0432 2684.6738 2577.2969 2328.2480 2220.4783 2459.1594 2681.9761 2580.6650 2330.6768 2220.3145 2447.2065 2667.1536 2581.3850 2331.3931 2226.7498 2455.6018 2682.5586 2579.4597 2330.5244 2230.7993 2457.9673 2685.3452 2579.2378 2324.5703 2224.9421 2448.8884 2666.2949 2579.0464 2327.8770 2220.2937 2441.9785 2671.4844 2582.1257 2329.3635 2231.0723 2456.1467 2673.7607 2576.9680 2327.9248 2235.0750 2457.1174 2676.3254 2585.4072 2334.6565 2223.9961 2445.9321 2665.8335 2563.7332 2305.7415 2218.0613 2452.5046 2684.2476 2589.0603 2335.7192 2228.5454 2447.8657 2664.1479 2565.2937 2310.5979 2215.7886 2439.6040 2664.5955 2562.3708 2317.9368 2222.0635 2443.8032 2668.1099 +4180.8149 4330.7837 4242.5874 4054.6421 3990.8232 4173.3418 4335.3462 4250.0928 4066.6926 4007.3054 4183.3662 4349.5190 4252.2993 4066.0625 3996.9700 4183.5522 4340.8276 4250.4951 4064.7263 3994.0762 4175.1689 4331.4058 4251.8359 4066.8032 4001.3481 4182.2173 4344.9282 4251.1045 4065.9587 4003.8831 4183.9775 4346.7754 4250.8936 4060.3958 3997.9338 4174.0571 4329.7163 4250.3052 4063.9844 3997.5413 4173.4404 4336.5024 4254.0732 4066.9116 4005.8792 4183.2285 4338.2197 4249.2803 4062.2861 4008.8794 4182.1904 4338.1563 4255.8359 4068.8572 3997.2258 4172.6641 4328.5664 4234.9438 4044.1194 3991.6223 4178.4961 4347.5034 4260.0444 4071.8611 4000.6692 4171.1172 4326.5493 4235.8989 4044.5112 3989.6816 4167.3589 4330.4971 4237.9995 4054.9734 3996.9675 4170.6909 4331.1582 +3679.1404 3670.5063 3604.4634 3581.2332 3610.6328 3672.9500 3675.1865 3611.9143 3590.1338 3625.2756 3681.7939 3689.0481 3616.2896 3591.5647 3616.9148 3681.4182 3679.7065 3613.7317 3590.0459 3614.4373 3673.4976 3671.7708 3616.9971 3591.3728 3620.2822 3680.4204 3683.7415 3613.4250 3591.4021 3623.4358 3681.1943 3685.5923 3613.0498 3586.3569 3617.4180 3670.6787 3669.6746 3613.3193 3591.1353 3618.6926 3671.2454 3676.3853 3616.4680 3593.2761 3625.6426 3679.3237 3678.0530 3612.9836 3587.9285 3626.4048 3677.6423 3677.2310 3617.8313 3593.0542 3616.9331 3667.9553 3667.3000 3598.3721 3571.2998 3611.4297 3674.7788 3687.0029 3623.1248 3597.9143 3617.6545 3667.8337 3666.2473 3599.4805 3572.7043 3610.1409 3664.3762 3670.6125 3605.3811 3583.5454 3615.7947 3667.0571 3671.1055 +4415.7231 3899.0344 3979.1338 4517.2944 4818.3809 4410.1606 3902.2451 3986.4563 4526.1489 4830.7217 4416.9824 3912.9529 3989.7693 4528.7280 4824.3481 4413.4893 3904.9941 3985.7798 4527.2910 4821.1899 4408.4106 3899.4253 3989.9988 4528.6689 4826.3320 4413.8252 3907.9492 3989.0535 4529.3691 4829.3340 4412.4722 3909.1145 3988.3801 4526.5386 4823.5854 4404.2295 3894.5923 3989.4209 4531.5942 4826.7109 4404.5020 3900.6365 3990.9543 4533.5654 4830.9443 4410.3896 3901.6731 3987.0364 4526.7900 4831.8052 4408.7373 3903.1423 3992.5090 4532.4683 4823.6958 4397.0850 3889.6650 3974.4578 4510.7129 4818.4653 4405.2290 3910.1880 3998.4006 4533.2632 4823.8584 4395.8999 3888.9497 3975.2317 4514.3730 4814.7417 4392.8306 3896.2671 3984.2913 4525.1509 4819.9351 4394.6284 3894.9558 +-4866.9326 -4610.1563 -4718.6978 -5022.0586 -5160.2896 -4907.9600 -4634.2334 -4703.9644 -4984.9878 -5098.6143 -4848.2104 -4590.0068 -4701.3018 -5010.3726 -5139.9268 -4881.5659 -4593.3125 -4699.9209 -4994.9937 -5153.0889 -4877.1606 -4616.0405 -4702.2598 -4980.1904 -5098.3208 -4844.1948 -4589.0664 -4709.7578 -4991.2939 -5132.4121 -4869.8301 -4608.9614 -4717.3481 -5009.0493 -5114.7266 -4873.7490 -4616.3989 -4692.8809 -5023.6304 -5171.1938 -4897.0137 -4628.3472 -4707.5161 -5006.7793 -5119.3721 -4885.0142 -4632.5840 -4723.7397 -5000.5459 -5107.7588 -4859.5449 -4602.5166 -4687.1958 -4983.2842 -5138.6543 -4904.9434 -4655.9463 -4764.9370 -5060.8564 -5153.3286 -4889.2031 -4602.0796 -4690.9780 -4983.0234 -5119.4863 -4894.7944 -4645.1621 -4726.2197 -5032.3857 -5150.7085 -4910.5986 -4657.5200 -4751.7334 -5018.8330 -5134.6855 -4875.8213 -4608.7529 +-224.2799 30.6897 -76.2510 -378.3803 -520.9692 -262.9972 8.3931 -63.1334 -343.4988 -459.2264 -209.4294 52.1343 -61.9917 -371.3701 -495.0025 -235.1590 50.3420 -57.4846 -355.6945 -503.7299 -233.8009 24.3876 -65.3768 -343.5642 -458.3124 -200.5214 54.2030 -67.4594 -351.6909 -482.7141 -221.4825 33.1444 -74.3747 -363.0514 -467.4489 -227.5760 24.3592 -52.4480 -376.0070 -518.9229 -248.3102 17.0628 -64.3469 -364.9624 -474.4063 -237.5673 15.2110 -78.9938 -353.6801 -461.5871 -214.8284 41.8546 -44.7768 -341.4829 -490.1425 -256.0426 -10.0998 -117.3388 -409.9751 -503.1954 -237.8222 43.6656 -47.9481 -336.2484 -471.9980 -247.3180 0.6263 -78.3119 -384.0659 -506.7242 -258.3431 -8.0341 -104.9412 -369.1494 -486.5535 -228.0849 37.5319 +-719.8560 -468.7020 -566.6588 -857.5400 -995.6199 -737.7867 -476.8007 -553.1060 -832.1023 -956.6284 -709.2766 -448.9088 -562.4278 -853.3427 -986.1484 -715.8201 -446.7968 -549.9848 -841.6987 -986.3306 -728.3499 -468.8640 -552.3062 -838.1377 -961.3331 -704.0461 -443.5486 -558.5161 -841.8456 -967.6099 -712.0179 -451.1830 -559.8192 -846.8586 -962.4893 -717.7394 -468.5739 -550.3809 -854.0113 -993.9254 -740.2964 -472.0397 -553.9830 -851.7718 -968.2731 -721.9905 -469.2549 -567.8220 -845.7021 -958.1700 -709.7985 -455.4343 -541.1821 -833.2083 -977.8356 -738.8840 -484.9827 -591.7722 -887.0158 -990.1851 -729.3798 -452.5450 -541.0225 -830.6180 -965.2571 -731.3469 -482.9962 -569.9448 -866.0421 -992.7613 -745.1578 -488.9534 -593.4471 -859.9257 -977.7305 -729.5898 -464.1053 +522.3984 763.3443 658.9214 376.2010 248.7806 510.9037 763.4186 673.5576 395.9394 279.9277 528.7978 784.1429 666.3058 381.3373 255.0840 527.3665 784.4048 675.3579 389.3084 255.8248 513.3674 765.0818 674.8758 390.5189 271.1899 531.6998 786.5981 668.3321 388.1690 273.0560 530.0435 785.0871 668.1666 384.0247 274.1190 522.2629 766.1887 675.3292 382.6778 253.9149 506.1598 765.4671 674.0973 384.1536 271.3526 522.3759 770.4685 662.0665 386.0934 280.3747 528.6368 778.6967 684.6018 397.0547 265.6397 509.6714 758.1113 646.4435 354.1607 254.1640 517.1443 784.6768 684.8788 399.2894 274.3026 515.0627 757.4074 658.7907 369.7643 250.6792 502.5489 752.9106 641.0790 374.3129 263.2703 512.7603 770.9252 +3219.0166 3457.1833 3359.5212 3078.1094 2949.9204 3203.9363 3455.5618 3370.8108 3095.5864 2979.6289 3219.9961 3480.2744 3366.3030 3085.9871 2958.1152 3221.2290 3474.3750 3374.2507 3092.5952 2959.1360 3207.9231 3456.7327 3371.6675 3092.6121 2970.7683 3223.1580 3475.6804 3367.9810 3089.9089 2972.6785 3222.2759 3478.7319 3369.1040 3085.8298 2969.8306 3211.8169 3458.8179 3370.3455 3087.0857 2957.9570 3202.2439 3458.7629 3370.9688 3087.7905 2974.2607 3216.4910 3464.4668 3363.6917 3087.4026 2979.3684 3221.9241 3469.3188 3379.6863 3098.2012 2966.6687 3206.3054 3453.8284 3344.2031 3059.0339 2953.1519 3209.6777 3477.5085 3380.7625 3100.7693 2971.4539 3207.0012 3451.2981 3355.4353 3069.1870 2951.9597 3196.2048 3449.3867 3347.6831 3077.4983 2962.0208 3204.8445 3461.3311 +5009.9028 5233.5684 5144.5762 4881.0308 4764.8198 4998.3516 5236.6963 5153.7593 4896.6572 4786.0713 5010.9927 5256.2070 5153.1255 4891.2373 4773.2490 5012.3525 5247.4116 5154.8047 4893.8770 4770.7480 5000.6416 5233.8906 5154.4160 4894.1060 4779.7422 5013.1797 5251.3501 5154.0669 4892.8008 4782.3726 5011.8296 5253.9961 5152.9194 4886.0845 4776.7939 5001.1528 5235.1440 5152.4033 4891.8438 4772.8467 4997.8701 5239.5527 5155.0210 4893.8389 4784.2896 5009.8682 5242.7710 5148.4468 4890.4932 4789.5742 5011.9814 5244.4580 5160.1519 4898.1416 4776.7988 4999.8208 5232.4541 5132.0459 4866.0596 4766.7642 5003.4272 5252.6704 5164.1953 4901.0000 4781.2393 4999.0093 5229.8447 5139.3110 4870.9409 4765.6572 4991.2725 5232.9751 5138.9746 4881.4224 4774.0190 4997.3403 5237.3560 +2583.3191 2724.9492 2635.6274 2452.6284 2393.6892 2575.5449 2728.1321 2641.0540 2464.5449 2410.7012 2584.8464 2743.6812 2643.8660 2463.8623 2400.7942 2584.4939 2734.0571 2642.6926 2463.0510 2398.0344 2575.2307 2725.8774 2643.7395 2465.2056 2405.5850 2586.2214 2739.1184 2643.7585 2463.0984 2407.2505 2585.0364 2739.1775 2643.2505 2458.2371 2402.3384 2575.7129 2722.3882 2639.8618 2463.7124 2403.2424 2574.6174 2730.9758 2644.8127 2465.4753 2410.5786 2584.4917 2732.1162 2638.5078 2459.7063 2412.3928 2583.6101 2732.3459 2648.0142 2467.6270 2402.1892 2573.5320 2721.6631 2623.4368 2440.5442 2395.9182 2578.3135 2740.8259 2651.3032 2470.6741 2405.0046 2573.4016 2719.1580 2627.0093 2442.1677 2393.7280 2567.5244 2723.0654 2631.4019 2454.1418 2400.2700 2572.7927 2725.9912 +5586.9697 5518.4922 5463.6689 5503.5923 5568.2891 5579.1387 5520.7500 5471.2974 5514.3242 5582.2925 5588.0903 5535.4927 5475.7930 5515.4146 5574.9951 5587.6582 5526.2583 5473.2998 5514.5845 5572.6587 5581.2632 5519.8789 5475.3618 5516.5527 5578.4292 5587.7070 5530.8799 5474.3774 5515.7192 5581.1904 5587.7319 5531.3740 5473.6553 5510.1660 5574.5601 5578.0562 5516.6230 5473.1768 5517.2500 5577.5405 5578.5186 5524.5669 5476.5518 5518.9224 5584.1484 5587.3965 5525.6699 5471.1274 5512.2754 5584.1479 5585.1021 5525.3091 5478.0928 5519.0337 5575.5488 5575.7095 5514.3535 5457.7974 5494.9233 5568.3945 5583.7554 5533.6167 5484.3950 5521.1826 5575.8003 5574.9063 5513.5542 5459.9351 5497.1133 5568.2432 5571.9263 5520.8208 5467.7222 5510.5190 5575.4756 5574.9609 5520.0112 +2645.4573 2532.4309 2489.1836 2578.9001 2667.7275 2637.9785 2533.0571 2494.4092 2588.7498 2680.4912 2644.8052 2546.5935 2498.5266 2589.6587 2674.6023 2643.4883 2536.4619 2495.2837 2587.0537 2669.6331 2636.9844 2531.5103 2496.7561 2589.3562 2676.0449 2644.9451 2540.3020 2497.0613 2587.4304 2676.9387 2642.2808 2541.6270 2496.4863 2584.2485 2671.9910 2634.9653 2528.7546 2496.9236 2590.2102 2676.6277 2636.7866 2534.2795 2499.6143 2591.5886 2681.6721 2642.1436 2535.6453 2494.6594 2585.0796 2681.1296 2641.5085 2536.2297 2500.3069 2590.8521 2672.1663 2630.4397 2523.6843 2479.9116 2567.7869 2666.3967 2638.2795 2543.0156 2506.3928 2592.3010 2673.0811 2628.1672 2523.1780 2482.5962 2570.1831 2666.1682 2627.6843 2531.6584 2492.4866 2583.8108 2672.0979 2631.2617 2531.0425 +3722.4797 2783.8257 2968.6685 3964.3711 4499.3315 3717.0100 2783.5686 2974.0447 3971.5652 4506.9087 3721.3811 2794.0337 2977.6416 3974.5198 4502.3784 3716.6890 2784.8110 2973.3140 3973.6628 4498.3774 3712.4150 2782.5081 2977.7400 3975.3193 4503.3174 3716.0715 2786.0161 2975.6277 3975.1538 4505.5742 3712.9377 2788.5027 2976.7297 3972.7061 4500.0884 3706.4480 2776.3638 2979.6772 3980.6108 4506.0293 3707.6782 2780.5066 2979.6077 3982.0620 4508.3950 3709.0513 2781.1343 2975.0205 3975.5334 4507.4531 3709.1421 2782.7288 2982.1990 3980.4878 4500.9595 3697.3618 2768.7087 2964.0481 3958.1697 4492.8813 3703.5447 2788.6658 2988.9377 3979.1089 4497.7930 3693.4495 2768.8411 2965.4502 3964.3657 4489.1499 3691.7932 2776.9897 2978.0352 3974.6538 4495.3706 3692.3733 2775.9595 +2261.7395 760.9996 1256.9137 2954.7939 3727.1748 2257.0229 759.9017 1262.4403 2958.9136 3733.6501 2262.3101 768.0494 1264.3293 2964.4673 3728.3928 2252.9065 762.4599 1262.6547 2964.5884 3725.0657 2250.5737 758.5721 1268.8818 2967.4121 3729.9063 2252.2920 762.2872 1264.0282 2967.0522 3732.5393 2248.7590 764.9020 1266.2245 2968.5891 3727.0615 2242.1118 751.5731 1271.8005 2974.4648 3732.9722 2242.6125 755.0292 1269.5125 2976.8044 3732.7068 2242.3662 757.6644 1266.1563 2969.4817 3732.7563 2244.2820 759.9306 1274.7430 2976.4363 3727.8325 2229.4907 744.6154 1259.9515 2950.2517 3717.7124 2234.2776 764.7766 1283.8146 2971.1309 3725.0046 2226.2065 745.7046 1258.4470 2963.3103 3711.1045 2222.2693 752.1652 1273.3182 2970.9136 3717.3096 2222.2930 752.5552 +2342.7717 494.1344 1173.3938 3303.6829 4228.1182 2337.7930 489.5128 1178.9969 3304.8677 4231.3486 2342.3264 497.4323 1178.5842 3310.2263 4225.8579 2329.3215 488.3428 1177.5079 3309.1448 4221.3867 2328.2952 486.8491 1182.2769 3310.1045 4225.4966 2328.1289 487.3566 1176.7854 3313.7183 4226.4810 2321.8530 490.1115 1179.4526 3313.6929 4220.9741 2317.8547 478.4442 1186.0757 3319.8369 4227.2432 2318.8552 479.9706 1182.8210 3320.9517 4224.9771 2313.2954 482.3594 1179.2092 3314.4282 4225.5791 2316.7808 487.4637 1187.0940 3320.5771 4220.9434 2299.4258 468.5719 1173.0015 3293.5127 4207.4521 2301.6433 488.0779 1195.5385 3311.0513 4215.0464 2297.1169 468.6683 1169.5563 3309.4690 4198.4106 2288.9844 476.5470 1186.3635 3315.3794 4202.7466 2288.8044 475.9854 +3776.5427 3756.3923 3754.9846 3789.8164 3808.7185 3773.1794 3750.5823 3752.8689 3789.5957 3811.0339 3774.6084 3755.5186 3755.0706 3791.6406 3812.1794 3772.5935 3752.2566 3753.6907 3786.4497 3806.9817 3774.6431 3752.1624 3753.8210 3786.5151 3809.1357 3775.4692 3753.7693 3754.7476 3788.0044 3810.4998 3773.4719 3754.2061 3753.4780 3786.6602 3808.1233 3773.3599 3752.0640 3755.8386 3788.0100 3808.4255 3773.3362 3754.7551 3755.2107 3789.5457 3811.7542 3772.7854 3751.1189 3750.4639 3785.9651 3812.5415 3775.9141 3756.1550 3756.1218 3791.3203 3808.9285 3770.2590 3749.1018 3747.5247 3782.1238 3805.6909 3771.2659 3754.4680 3755.9707 3790.2273 3809.3306 3771.3379 3749.8164 3749.9956 3782.3828 3806.5254 3770.4397 3753.2991 3754.8350 3788.8892 3807.2312 3770.9448 3753.1440 +-5500.4438 -5246.9604 -5351.1372 -5655.3765 -5809.0688 -5549.2388 -5273.8110 -5338.3066 -5617.6880 -5733.5298 -5481.9785 -5217.6523 -5341.4141 -5651.2095 -5770.5820 -5508.3467 -5229.0654 -5330.2896 -5630.9463 -5782.3184 -5511.9595 -5252.9033 -5345.7378 -5619.5181 -5733.0786 -5475.9292 -5229.6050 -5342.9712 -5630.9478 -5758.8301 -5501.5684 -5240.9292 -5351.6914 -5644.3916 -5744.4199 -5508.0513 -5249.3257 -5329.5796 -5647.7646 -5793.4722 -5528.7744 -5258.4453 -5343.5435 -5639.5264 -5747.7695 -5521.2715 -5263.2607 -5356.3130 -5627.0713 -5738.2607 -5492.2002 -5230.9268 -5316.1045 -5618.4067 -5771.0625 -5529.8276 -5287.7876 -5403.1953 -5689.2686 -5782.0034 -5520.6426 -5228.6216 -5321.2432 -5607.1147 -5744.5938 -5528.3823 -5274.1289 -5356.1812 -5668.5459 -5783.6758 -5544.0566 -5288.1934 -5373.3125 -5640.7637 -5762.5693 -5499.0894 -5239.2642 +-3550.9346 -3292.1260 -3381.0383 -3681.4497 -3836.8284 -3582.0554 -3310.4678 -3370.6887 -3651.5811 -3781.2205 -3537.7712 -3267.4089 -3373.3367 -3678.7529 -3812.3745 -3548.9219 -3272.4077 -3361.5867 -3662.4705 -3816.7031 -3563.8914 -3294.2988 -3372.7122 -3657.3489 -3785.8538 -3530.7424 -3271.5730 -3375.2302 -3664.7524 -3796.6172 -3547.8159 -3277.8760 -3377.4622 -3672.0632 -3791.8948 -3554.6931 -3293.8037 -3366.8657 -3673.9880 -3826.5776 -3573.1865 -3296.8433 -3373.9001 -3674.3586 -3793.2422 -3559.9143 -3302.1394 -3388.1677 -3666.6580 -3784.6670 -3545.4875 -3279.7092 -3355.8459 -3654.7222 -3809.4468 -3574.5923 -3319.2273 -3422.5632 -3714.3801 -3826.5557 -3568.0361 -3275.8303 -3360.6760 -3646.2109 -3792.1570 -3571.4731 -3314.6091 -3389.4829 -3695.8059 -3830.1130 -3587.5730 -3321.5247 -3408.3291 -3677.3777 -3809.6523 -3559.6707 -3288.6216 +-878.5390 -629.9741 -725.7325 -1019.6136 -1162.5894 -902.9245 -642.0062 -715.8707 -995.5134 -1119.4092 -870.7849 -603.8262 -720.7402 -1014.5622 -1146.8485 -876.1102 -609.1257 -707.1850 -1002.3488 -1147.2897 -890.0291 -629.3511 -714.0605 -1000.7586 -1125.6750 -863.4739 -606.8029 -717.4261 -1004.9435 -1129.6075 -875.5291 -608.6738 -719.2076 -1012.6624 -1128.2200 -882.0878 -627.9310 -712.1678 -1010.9626 -1153.9786 -899.8956 -629.8138 -714.5887 -1013.5571 -1128.5641 -884.1275 -629.8734 -728.6205 -1006.5093 -1118.3650 -872.4866 -615.0719 -701.1727 -996.1724 -1138.4464 -896.4209 -644.6416 -755.4447 -1047.6326 -1155.9395 -891.5646 -608.9462 -701.9747 -990.1022 -1125.4220 -893.4756 -641.2849 -730.5878 -1030.2568 -1157.4324 -908.1622 -648.3444 -746.0331 -1017.1221 -1140.1776 -887.5652 -622.5253 +613.0931 854.4426 760.5955 471.6114 336.2885 593.5488 849.0464 768.5136 491.4553 368.5038 614.5884 880.2606 765.0962 477.4854 347.5216 614.3121 872.2646 773.8361 488.7059 349.5961 600.8815 854.4633 768.6472 484.8020 360.3563 619.3604 874.4588 768.3945 482.9832 363.9344 614.4219 879.1648 769.0975 478.3979 360.4996 604.3055 857.8491 769.5430 480.9661 346.2720 593.5532 857.8059 769.1330 479.7322 362.6577 607.8395 860.1846 761.9929 480.9820 371.3873 613.0749 868.0492 780.0115 491.7226 356.3293 598.7305 848.5422 737.8060 449.5308 340.5128 598.7297 875.9421 780.1467 497.0935 364.5423 598.6075 849.4055 755.1293 460.4722 338.4179 586.3560 844.8923 749.6318 472.1309 351.3335 598.7914 860.5923 +5633.6226 5870.5127 5778.0508 5497.6006 5370.3486 5616.3330 5868.0669 5784.8076 5515.1636 5397.0161 5631.0566 5894.5156 5783.0601 5506.4873 5379.6597 5633.5342 5884.5078 5790.4019 5512.1118 5380.3335 5619.8691 5867.8311 5786.3013 5509.1494 5388.4917 5635.0591 5887.4844 5787.2798 5509.8809 5391.7534 5632.4766 5891.8740 5787.8633 5503.4946 5384.5103 5621.0913 5871.0181 5784.0776 5508.9751 5380.4839 5616.8828 5874.0020 5787.2847 5509.3916 5392.3574 5629.6230 5875.5576 5779.5557 5506.2979 5400.1523 5632.1191 5879.7393 5793.3267 5514.6118 5385.7192 5620.6309 5865.2661 5759.4541 5478.7148 5371.2368 5618.4980 5888.8887 5794.5903 5520.3174 5390.3677 5617.3125 5864.6509 5770.8735 5485.2598 5370.1304 5608.2227 5864.1416 5771.3198 5497.3521 5381.4097 5616.9893 5871.6992 +1868.0807 2098.0537 2012.9078 1744.1111 1619.1835 1853.9465 2098.9709 2019.8241 1759.1766 1642.9503 1865.8007 2120.8262 2019.2847 1754.0344 1627.3315 1868.7128 2110.2725 2024.3027 1754.9932 1626.6587 1854.2847 2095.7065 2021.4531 1755.4980 1634.4623 1870.5278 2114.5010 2021.5466 1755.1221 1636.0867 1866.8353 2116.7043 2019.8939 1746.8718 1631.4163 1854.4648 2097.7422 2019.2798 1754.0455 1629.5300 1853.2355 2103.0769 2020.9290 1755.2346 1638.6532 1864.7924 2105.5247 2015.8739 1751.4789 1644.9233 1866.3802 2106.8630 2028.3163 1759.2273 1632.6549 1855.8278 2094.3179 1997.9308 1726.4459 1619.4149 1855.7112 2116.3208 2030.2036 1762.2896 1635.1029 1853.1765 2092.7173 2005.1808 1731.4661 1618.3145 1845.2418 2095.4805 2007.3898 1743.1559 1626.6888 1851.3796 2097.9224 +4201.6426 4350.3325 4262.2690 4074.4802 4009.3291 4192.6387 4353.2148 4270.3999 4087.0171 4027.3831 4202.0757 4371.7407 4273.5889 4086.7534 4018.7085 4202.5972 4360.7148 4272.5679 4086.0745 4016.5586 4194.9561 4353.1704 4274.0459 4088.4866 4024.3960 4206.4409 4366.8843 4274.6538 4088.7896 4026.2092 4204.3794 4368.8306 4273.9194 4083.0313 4021.8540 4195.6855 4352.7412 4273.7402 4089.7522 4024.3210 4196.3237 4360.2856 4277.7197 4092.0356 4032.2505 4206.6396 4362.0684 4272.3164 4086.8562 4035.2388 4206.1714 4364.2988 4282.6294 4095.2327 4025.2727 4196.2905 4353.5439 4258.4722 4069.0542 4016.4360 4201.9521 4373.9287 4287.4106 4100.0693 4028.3728 4195.9575 4352.9097 4264.1895 4071.6460 4016.7083 4193.0503 4358.1313 4270.8555 4086.7622 4025.1758 4198.5278 4361.0903 +2464.3696 2611.2988 2528.7620 2348.8550 2281.8376 2454.7461 2612.5950 2535.0688 2359.7678 2298.8235 2464.6533 2629.7859 2539.6357 2361.1042 2292.9861 2464.4778 2617.8467 2537.0601 2358.1289 2287.8989 2457.2244 2611.3206 2537.5291 2359.8396 2294.9919 2466.8977 2623.6560 2539.1738 2358.8411 2296.0964 2464.6011 2623.9998 2536.7402 2354.0156 2291.7529 2455.7983 2611.4319 2537.2549 2362.8948 2295.1748 2457.8521 2617.9270 2541.0203 2364.6367 2303.5649 2466.9104 2619.8794 2534.0176 2357.4099 2305.2480 2466.5154 2621.1169 2544.8105 2365.0229 2295.3337 2456.9963 2609.1360 2520.4089 2341.2817 2287.9250 2462.7957 2629.2322 2549.0190 2368.4790 2295.2058 2453.5850 2608.1147 2525.7048 2341.2866 2286.7070 2453.7917 2616.1350 2538.0581 2357.8076 2295.4021 2458.9888 2616.9204 +932.5012 989.2316 914.2322 822.5043 813.3203 925.1936 988.9644 918.6498 832.2500 827.2405 930.5258 1005.4139 923.9775 833.0342 821.3595 930.4056 993.6210 919.5239 830.8243 817.9142 924.1389 989.1566 920.8788 832.1159 821.9033 931.3310 997.1157 919.5339 829.8624 824.2158 929.0347 997.2853 918.6564 826.4401 818.6129 922.8442 987.2466 920.9841 835.5487 822.8023 923.5115 992.4476 922.2682 835.6837 829.8912 932.3239 992.7292 914.9103 827.0544 830.2867 931.3286 994.0084 924.9803 834.5104 819.4688 919.7949 980.8464 900.8677 810.6420 812.9725 924.8958 999.7419 926.5486 834.7227 818.8784 915.8280 981.0753 906.0697 812.0898 812.9872 917.8469 989.8683 916.7762 827.8734 819.4996 921.1186 987.8532 +5814.3042 5731.3076 5686.3110 5744.2266 5817.7993 5806.9819 5727.7222 5686.8818 5750.6099 5827.2314 5812.5508 5744.7900 5693.5767 5753.9741 5825.5127 5811.1187 5732.6860 5689.4727 5750.0532 5818.8042 5805.8970 5729.1836 5689.2349 5750.7314 5823.9121 5814.2314 5735.2563 5689.5479 5749.5796 5824.0313 5809.8979 5734.5400 5687.7993 5744.3799 5819.9907 5802.7686 5725.8955 5689.4287 5753.2075 5823.5293 5806.0815 5730.5425 5689.3340 5753.7334 5829.6318 5809.2939 5728.9336 5681.9399 5745.1816 5829.3975 5809.1699 5733.2969 5692.7544 5753.5879 5821.3062 5799.6802 5717.8687 5668.7549 5729.9634 5812.9717 5804.5381 5737.2295 5693.2676 5751.9629 5817.7065 5793.9565 5717.1660 5673.2021 5728.5146 5811.3447 5794.7373 5727.2388 5684.8159 5745.8940 5817.1870 5795.5479 5723.0049 +3313.3760 2992.3625 3061.4541 3410.8142 3591.5752 3306.5942 2987.2583 3059.8152 3411.9746 3597.9841 3310.1816 3000.4922 3064.9431 3416.7693 3595.8987 3308.1099 2990.0310 3062.4478 3412.4314 3589.8374 3302.0754 2986.5171 3062.3372 3414.5493 3594.7754 3309.2493 2992.8730 3061.4006 3413.0718 3593.8950 3304.7510 2991.4043 3059.5630 3409.5640 3589.8225 3298.5872 2983.3396 3062.6418 3416.4966 3592.7534 3300.5635 2986.9077 3062.1792 3418.4385 3598.0540 3305.0396 2985.5178 3055.5579 3409.2495 3598.2676 3305.2288 2991.3943 3065.7043 3416.2935 3590.8748 3292.0581 2973.9646 3044.3892 3394.3396 3583.6167 3296.0447 2991.0466 3065.2236 3413.3467 3587.7876 3289.3799 2974.7024 3047.1768 3394.5022 3579.9314 3287.2488 2982.8665 3060.6306 3409.5967 3584.0857 3287.3843 2979.4226 +3199.9731 2704.3462 2869.0764 3440.5632 3697.8208 3194.8093 2697.6589 2866.5188 3441.3206 3700.0452 3196.6477 2707.5090 2869.9312 3443.7244 3698.5640 3193.4011 2698.8057 2867.4729 3438.6934 3692.3303 3190.1953 2697.2664 2868.0535 3439.9790 3695.9321 3193.9429 2699.2078 2866.4727 3440.5574 3695.3765 3189.0420 2699.0076 2866.1150 3437.6604 3692.4656 3185.9771 2694.2656 2870.4370 3442.7075 3695.6138 3187.4111 2696.3052 2866.8428 3443.1001 3698.6201 3187.5281 2695.4509 2863.7378 3437.1555 3699.0564 3189.9468 2699.4756 2871.7493 3445.0559 3692.2954 3176.6152 2685.1680 2854.7002 3425.5464 3686.2510 3180.1741 2699.2388 2871.5088 3441.2231 3690.5581 3176.9929 2685.9099 2856.9724 3428.3535 3682.9595 3173.0342 2692.2649 2870.5029 3439.0264 3685.2751 3173.3516 2689.7253 +-5273.7881 -5023.8984 -5123.2505 -5420.8457 -5567.9766 -5306.8037 -5045.5044 -5113.9419 -5393.3315 -5514.8477 -5262.9092 -4997.2715 -5117.7905 -5417.4419 -5545.2964 -5272.9546 -5007.2881 -5104.0967 -5401.6226 -5548.1436 -5289.4253 -5025.5474 -5116.3052 -5400.4810 -5519.7515 -5256.3770 -5005.5825 -5115.6279 -5406.8418 -5528.6045 -5272.9663 -5005.5469 -5118.9116 -5414.4268 -5526.0220 -5281.4092 -5025.5698 -5110.4448 -5410.9248 -5554.8105 -5297.6543 -5028.4458 -5116.4565 -5412.4282 -5525.2324 -5285.0117 -5030.5825 -5130.2686 -5405.6890 -5515.2036 -5269.0928 -5010.7905 -5098.8628 -5395.1191 -5539.6938 -5295.2158 -5048.2319 -5164.0049 -5453.1992 -5558.3950 -5294.2583 -5005.5630 -5101.7437 -5384.5513 -5522.1323 -5294.5977 -5041.0625 -5131.2622 -5435.4385 -5558.6084 -5312.1943 -5049.6880 -5143.3931 -5415.6924 -5538.8359 -5283.2480 -5019.3877 +-5606.1157 -5352.8398 -5446.6772 -5743.0601 -5893.1035 -5634.1177 -5368.8701 -5437.8257 -5717.6743 -5846.5220 -5598.2017 -5327.6040 -5443.0327 -5740.0742 -5873.7275 -5604.2754 -5335.3530 -5427.7925 -5725.1816 -5874.5586 -5620.6880 -5353.7773 -5437.6831 -5726.1758 -5852.4502 -5591.9146 -5333.5615 -5438.2148 -5730.5181 -5857.7583 -5604.8228 -5333.2827 -5440.2051 -5738.4595 -5856.5015 -5612.0762 -5352.8062 -5434.5479 -5733.7388 -5880.5986 -5628.8896 -5353.3711 -5439.8271 -5736.7168 -5855.9849 -5613.2778 -5355.3525 -5450.3940 -5730.5381 -5843.9351 -5601.1392 -5339.0259 -5422.2837 -5718.6260 -5865.9736 -5623.2500 -5370.4194 -5481.4595 -5772.5615 -5886.3506 -5623.9863 -5333.9805 -5423.6187 -5709.9170 -5851.0903 -5622.7007 -5366.4590 -5451.8213 -5756.3765 -5885.7949 -5641.0298 -5372.8750 -5464.5752 -5740.2446 -5868.1689 -5616.5688 -5346.8579 +-1810.3749 -1569.6796 -1669.7515 -1962.5786 -2097.7527 -1835.4147 -1581.8109 -1663.0889 -1939.7489 -2060.3564 -1809.7256 -1543.5330 -1667.1066 -1955.4220 -2083.0266 -1809.0686 -1552.0038 -1652.9435 -1942.6133 -2081.0493 -1825.9342 -1571.2642 -1662.9880 -1948.3534 -2068.8535 -1803.3140 -1550.8363 -1662.2209 -1950.0620 -2066.6335 -1811.6013 -1547.4562 -1661.7891 -1956.6450 -2070.6914 -1820.8406 -1567.7996 -1661.0182 -1950.1956 -2085.6890 -1832.9309 -1567.7863 -1662.8713 -1954.3668 -2066.6848 -1817.4078 -1567.4811 -1669.7554 -1949.7833 -2056.0527 -1810.5917 -1557.7330 -1649.9360 -1940.6650 -2074.2837 -1826.7621 -1580.9325 -1698.7794 -1986.7585 -2094.9958 -1831.1288 -1550.3107 -1650.6108 -1933.8228 -2064.8057 -1828.8075 -1579.3534 -1677.0768 -1974.1808 -2093.9082 -1843.3367 -1583.1852 -1683.5996 -1961.6130 -2079.6719 -1827.0542 -1565.6375 +2602.8933 2834.1501 2735.8257 2450.5254 2326.2251 2582.7629 2829.3792 2742.7307 2469.3357 2354.4976 2597.1589 2859.7556 2738.8601 2459.4519 2335.9949 2601.1221 2849.0979 2750.3430 2467.4214 2338.8992 2584.4036 2830.3970 2742.2725 2462.1094 2345.1472 2602.6829 2850.5383 2743.7913 2462.8198 2350.0779 2598.8325 2857.7163 2743.9834 2456.6492 2340.3096 2586.4810 2835.4841 2742.4277 2465.0022 2337.2332 2581.1245 2838.3694 2743.2131 2462.7566 2349.2158 2594.9749 2840.2368 2736.0181 2460.5232 2359.3821 2598.3904 2844.2668 2751.1887 2469.1646 2344.4084 2587.9651 2829.7524 2713.7139 2431.9932 2326.7583 2581.5403 2853.0862 2751.2451 2473.2896 2349.4341 2583.3394 2828.7271 2728.9434 2438.2239 2326.7048 2572.0251 2828.9248 2728.2761 2451.4248 2338.8071 2581.1108 2835.3779 +712.0372 940.0635 844.0450 568.4089 445.2562 693.4948 937.5940 851.0430 584.0614 471.5069 707.5548 964.3408 849.1324 575.2989 456.3796 710.5093 953.2717 856.5385 582.1475 457.6617 695.6367 936.6899 851.1463 578.6354 462.4547 711.8576 955.3579 852.7769 578.4518 466.4100 709.0387 960.3780 852.4782 571.3792 458.8596 696.1678 940.3367 849.6621 579.9424 456.7478 693.9183 944.1238 852.6407 579.4277 468.0294 705.9871 946.5964 844.6948 576.2577 477.1270 708.9295 949.2657 860.0350 584.8070 462.1713 697.1877 934.3057 824.8732 549.6310 446.8347 695.1611 957.0947 859.7301 587.7519 465.3383 694.3726 934.7003 837.2323 554.0314 445.7640 685.3423 936.2216 839.7497 568.2015 456.5689 692.4457 940.5609 +1344.6769 1556.9117 1462.9695 1205.4866 1097.4028 1330.2412 1554.8772 1468.9402 1220.5054 1119.7513 1342.1389 1579.1605 1469.3015 1214.4353 1106.5546 1344.2347 1567.3730 1473.6085 1218.3362 1107.2112 1332.1111 1555.4343 1470.7964 1218.1501 1112.2195 1346.0276 1572.3964 1472.6884 1217.4237 1115.2329 1343.1124 1575.4622 1471.4520 1210.1245 1108.8894 1332.1234 1558.4851 1469.5477 1221.0685 1110.5266 1332.2876 1562.9945 1472.6820 1221.2577 1119.7889 1343.1849 1564.5779 1465.1024 1214.9656 1126.5527 1344.5131 1566.6437 1478.7211 1223.1478 1113.0026 1334.7108 1554.1233 1448.4065 1191.4553 1100.5378 1334.5045 1575.4512 1481.1908 1227.3738 1114.2383 1332.0148 1553.1814 1457.7814 1195.0475 1100.0183 1324.7933 1558.1350 1463.7271 1211.3444 1110.0453 1331.7296 1561.1931 +2346.7305 2567.9768 2477.0010 2202.9309 2082.8752 2334.9788 2567.4971 2483.7922 2216.5725 2101.8110 2345.0012 2588.1794 2486.4910 2213.8110 2091.2996 2345.6340 2575.3716 2486.4692 2213.4119 2089.1118 2337.3689 2566.3755 2485.9695 2216.3030 2098.1321 2351.0156 2582.1594 2486.4102 2214.8132 2097.1345 2346.4138 2583.0247 2485.8557 2207.1855 2091.3484 2336.1406 2568.6589 2485.4795 2218.9443 2095.6992 2338.4700 2572.5107 2488.4775 2217.8545 2104.0532 2348.3264 2574.4351 2481.0798 2210.7864 2108.6741 2349.1963 2577.3049 2493.4299 2220.3499 2096.8406 2338.5737 2564.4587 2462.6707 2189.8379 2085.4285 2339.2239 2585.4541 2494.1367 2222.7708 2096.8455 2334.9502 2563.4697 2472.8413 2192.1536 2084.7607 2331.7639 2570.0842 2480.4548 2210.0090 2094.7708 2337.3059 2570.5364 +2312.4487 2495.9839 2405.1089 2163.3188 2066.1343 2300.9136 2496.1274 2409.3560 2173.6123 2083.3303 2308.5251 2514.8142 2411.8987 2171.7661 2073.7034 2308.1802 2501.8545 2410.9023 2170.7356 2070.2959 2300.2332 2494.2771 2409.5833 2172.6797 2077.3904 2311.4519 2506.4475 2409.9500 2170.0757 2077.5000 2307.3235 2506.9067 2407.9150 2163.6379 2071.9080 2297.6829 2493.5051 2409.5417 2174.0015 2075.6235 2299.0120 2498.4216 2410.3091 2173.4182 2083.4390 2307.1233 2499.3093 2401.0986 2165.7725 2084.9099 2307.9067 2501.3599 2413.0876 2173.9126 2074.2148 2297.2271 2487.8586 2385.1619 2144.7070 2063.4048 2299.5513 2507.8135 2414.0122 2175.4250 2072.9150 2292.2817 2486.0278 2392.5974 2145.9465 2061.5605 2290.7961 2494.3955 2402.0142 2163.6819 2070.5012 2294.8381 2492.7925 +2824.3423 2921.8955 2844.9470 2700.2959 2657.3198 2815.6902 2919.2932 2847.8601 2707.4412 2668.2715 2821.3406 2935.6577 2852.1699 2708.1533 2663.5994 2820.6306 2923.2400 2849.5906 2705.5095 2659.9297 2815.2605 2919.5156 2849.2100 2706.2588 2664.8552 2823.9099 2927.3218 2849.1155 2705.8940 2665.3494 2819.3674 2927.5085 2847.1570 2699.3604 2659.8721 2812.1448 2918.4070 2849.9106 2710.9255 2664.9429 2814.7371 2922.6008 2849.8977 2709.2546 2672.2156 2822.2859 2921.5820 2841.4194 2700.2900 2672.7627 2821.2856 2924.6548 2854.3970 2709.0608 2662.6716 2809.7659 2909.9946 2825.4556 2683.9253 2654.6211 2812.7432 2930.6697 2852.9810 2708.9202 2660.8201 2806.7991 2909.7332 2832.4209 2681.8599 2651.6948 2805.0525 2919.5840 2845.5457 2701.4563 2659.2900 2808.9189 2916.5881 +1259.8477 1143.0640 1118.9319 1207.5825 1285.0396 1252.6698 1138.0942 1117.1603 1209.8798 1293.3409 1257.3951 1153.5000 1124.6147 1212.6437 1291.2482 1254.8053 1141.5361 1120.6483 1208.7247 1284.0620 1249.5106 1137.5507 1119.9965 1210.5485 1290.9216 1258.1395 1143.7916 1119.2056 1208.9894 1287.3907 1252.6989 1142.8130 1117.5339 1202.8773 1284.0602 1245.8971 1134.9681 1121.2227 1213.7389 1288.1128 1249.6431 1138.0059 1119.4879 1211.8754 1294.2006 1253.5062 1137.1686 1111.3170 1204.6986 1293.5375 1254.1571 1141.2499 1122.9473 1212.0042 1286.2546 1242.6763 1124.8950 1097.9540 1188.5320 1276.2532 1245.1918 1143.8558 1121.2688 1210.5541 1283.1968 1239.5110 1125.7699 1102.7568 1188.4213 1276.7965 1238.2235 1135.8208 1118.0712 1205.6801 1280.4375 1239.8945 1132.1718 +3035.5989 2660.6536 2745.2466 3140.8625 3341.7373 3027.7354 2654.5928 2741.7151 3139.5073 3344.7043 3031.1152 2666.2104 2747.9287 3143.2075 3343.4880 3028.3828 2656.3464 2744.4785 3138.6912 3336.4741 3023.2446 2652.8293 2744.5679 3140.0884 3340.9248 3029.1707 2656.4797 2741.6021 3139.0479 3340.8743 3023.4590 2656.1733 2741.6226 3136.2917 3336.4292 3018.4067 2648.9473 2742.8491 3142.1533 3339.6528 3021.5073 2652.8975 2742.7739 3141.5867 3343.1575 3021.8445 2651.2524 2736.8235 3134.6526 3343.9080 3023.5684 2655.2314 2747.0947 3141.1345 3336.1189 3012.0640 2638.6948 2725.3186 3120.9402 3328.0962 3012.6902 2655.1599 2743.1272 3137.4580 3332.1675 3008.8848 2641.0725 2727.7683 3121.6226 3325.1541 3006.8347 2647.6904 2741.5161 3133.6028 3328.9917 3005.3813 2643.6907 +-3456.7317 -3204.3035 -3307.3921 -3625.6404 -3777.1494 -3481.8157 -3220.3799 -3301.6611 -3604.7742 -3740.9966 -3457.5293 -3178.4912 -3307.7698 -3622.5151 -3761.4675 -3455.0403 -3188.7297 -3289.4617 -3608.3301 -3757.2410 -3476.1699 -3208.1328 -3301.0505 -3616.2407 -3749.7764 -3450.8640 -3188.1570 -3300.1790 -3615.4365 -3745.2029 -3460.1482 -3180.9351 -3298.0752 -3624.0854 -3754.2561 -3470.7231 -3204.1750 -3300.7673 -3612.7795 -3761.5864 -3480.5178 -3202.8606 -3303.0212 -3620.6250 -3747.4556 -3465.1277 -3202.4219 -3312.2788 -3616.5325 -3732.9497 -3457.5405 -3195.1262 -3290.0718 -3608.3110 -3751.9519 -3470.7368 -3215.9402 -3339.6250 -3651.2798 -3776.4741 -3480.9165 -3186.4121 -3291.3865 -3596.8655 -3743.3879 -3473.4673 -3212.4634 -3315.1289 -3641.8264 -3773.3521 -3493.4424 -3217.0068 -3317.2905 -3627.7334 -3759.2649 -3475.1436 -3203.0437 +664.0970 906.1524 804.9072 492.0460 350.2948 641.9526 899.1927 811.0135 510.6799 380.7223 657.9624 932.1554 805.0601 498.0416 361.8509 663.1465 922.4857 820.9668 508.4138 367.3145 643.0120 902.4474 809.6724 500.6698 371.3233 664.2116 922.4689 813.1687 502.7554 377.4133 660.2549 931.3762 815.0939 496.2561 366.6931 646.7029 908.4277 810.4285 507.2153 365.7499 642.8676 911.9943 810.9882 502.7819 375.7184 656.5701 913.3552 804.2670 502.3003 389.6540 660.9260 916.4189 821.9437 510.7740 372.8126 650.9778 902.9857 781.1208 473.1553 352.8380 642.3737 927.7904 821.5171 518.6476 378.3801 646.9384 902.7335 799.1620 479.1461 354.8025 633.7708 904.5983 801.3718 493.4673 366.3351 645.3040 910.2254 +2787.4097 3022.4094 2921.4263 2618.0977 2485.4636 2767.2822 3018.1023 2928.0723 2634.3074 2510.5422 2780.6531 3046.4924 2924.1213 2624.3860 2494.3076 2784.9797 3035.3645 2934.0537 2632.6951 2496.7832 2768.1423 3017.1821 2926.2883 2627.6934 2501.6567 2785.8323 3035.4270 2927.7029 2627.9888 2505.9749 2781.4204 3042.2129 2929.2283 2619.9680 2495.5503 2769.2539 3022.6206 2925.9358 2632.0322 2496.9705 2768.1064 3025.4963 2927.1812 2629.3430 2506.3020 2778.9780 3027.9783 2920.2173 2625.8423 2516.7649 2781.9985 3029.3081 2934.9546 2633.6765 2501.4868 2771.9124 3017.3020 2898.1792 2597.7175 2483.1619 2766.9753 3038.2800 2935.0320 2637.2432 2504.1025 2767.7004 3016.5874 2911.8005 2602.7041 2484.2109 2758.4194 3018.6292 2916.9695 2616.9536 2495.4561 2765.4939 3021.7014 +-442.3733 -211.6626 -309.9428 -605.1894 -734.8349 -458.8115 -214.6324 -303.6879 -590.8430 -709.8420 -448.2953 -188.4535 -305.6054 -597.2571 -725.8983 -444.9647 -201.7451 -298.9135 -593.6500 -724.6094 -459.6139 -215.7949 -305.4836 -595.8066 -719.6172 -444.0022 -200.1167 -304.4046 -596.0399 -716.7520 -447.7361 -194.3415 -304.3773 -604.2897 -725.5273 -459.9278 -212.7343 -306.9228 -592.4489 -722.9912 -460.3671 -209.2161 -305.2716 -593.9533 -714.6132 -448.5499 -207.2397 -312.8095 -599.7979 -705.9393 -447.4350 -205.5117 -297.6240 -592.2731 -720.1846 -457.3848 -218.3407 -332.6201 -625.4463 -735.7338 -460.8472 -196.2453 -298.7123 -588.1290 -718.5784 -462.5114 -218.5341 -320.3172 -622.0069 -736.7537 -470.4483 -214.8710 -314.4591 -606.3828 -724.6723 -462.6042 -213.5647 +3.1364 230.5168 134.1157 -155.1399 -280.8354 -12.5557 229.1400 140.1818 -141.2825 -259.9984 -3.3738 251.2785 140.2410 -146.5679 -272.2938 -0.5665 239.1349 144.3813 -144.6750 -271.5366 -13.2846 227.2950 140.5874 -144.3093 -267.0440 2.2063 242.1159 140.9636 -145.1764 -264.5488 -1.4970 246.7733 140.0268 -152.9749 -272.6813 -12.4898 231.9152 140.5394 -139.5529 -267.3659 -10.3531 234.2397 141.1766 -141.2405 -259.4995 -0.2036 235.8521 134.1572 -147.9712 -252.4746 0.5910 238.2955 148.2660 -139.3518 -265.9333 -7.8279 226.0457 116.0038 -171.1187 -279.1087 -10.7181 247.4770 148.7560 -135.7132 -265.0483 -13.5795 226.0770 127.3130 -169.3415 -279.6296 -18.9349 232.3350 135.6811 -150.3776 -269.8250 -12.6046 231.7246 +-1465.8157 -1244.4146 -1329.3495 -1600.2639 -1722.7607 -1478.6146 -1247.4734 -1322.7855 -1589.6982 -1706.0717 -1470.9388 -1226.9026 -1324.0299 -1592.5591 -1715.6670 -1469.8030 -1240.2239 -1323.7865 -1592.8407 -1718.7578 -1480.7631 -1249.7642 -1327.4253 -1591.7272 -1711.3978 -1466.9860 -1236.5131 -1325.7965 -1594.1138 -1712.6464 -1471.8999 -1235.8425 -1328.8647 -1601.4921 -1719.4146 -1481.7617 -1249.1250 -1325.8085 -1588.3992 -1713.9530 -1481.1611 -1245.0555 -1325.3999 -1590.8440 -1707.6104 -1471.4264 -1245.1194 -1335.6494 -1599.0978 -1702.3885 -1470.8160 -1242.9120 -1321.9041 -1589.5302 -1714.6919 -1481.2766 -1257.3586 -1353.3950 -1620.7682 -1727.9750 -1482.7032 -1236.9215 -1321.2411 -1589.7971 -1717.2177 -1487.8668 -1257.6593 -1343.1350 -1620.7480 -1731.7217 -1493.0028 -1251.0714 -1334.3778 -1601.0465 -1720.8940 -1485.3462 -1253.0137 +68.6272 220.8723 131.4969 -77.1144 -150.1038 57.8236 218.6709 134.6749 -67.7765 -138.2000 64.2722 235.3094 135.2640 -71.3433 -145.6090 61.8332 223.3586 136.2157 -71.5583 -149.9025 54.9847 216.0801 132.5995 -70.7575 -143.3820 65.8987 225.6982 131.9641 -73.0913 -144.2480 60.3777 226.1540 130.8709 -80.7411 -150.7005 51.4288 214.8640 133.6313 -68.2264 -146.2193 53.9621 218.4333 131.1502 -71.1217 -137.9419 61.3931 216.3210 123.4339 -79.5033 -137.9560 62.3346 220.8404 135.7996 -70.1270 -148.0415 51.0186 204.8915 105.7870 -98.6145 -159.4167 51.9976 224.7440 134.1213 -73.3993 -150.8289 45.4668 205.1336 113.3977 -100.6743 -160.8224 43.8036 213.9201 126.9930 -80.8146 -152.8203 45.9616 208.5353 +226.1854 305.1735 223.6868 91.7804 63.0680 215.9520 301.2162 223.2706 94.4642 72.4308 219.8827 316.6235 227.3395 95.4136 67.0555 218.7726 305.7793 224.8380 93.7113 61.0714 211.8871 298.8702 224.4926 93.2654 67.5206 222.6084 306.8643 222.9417 91.2328 66.0980 216.6925 306.2006 219.9030 84.8444 61.9323 209.4071 298.0757 222.6263 95.5062 65.2948 212.6421 300.8605 221.0485 95.4301 72.6938 218.5613 298.6316 213.5981 84.9657 73.6317 219.1747 304.2604 227.2206 96.0578 63.5526 206.7256 286.9020 197.1484 70.3464 53.9725 210.2969 306.1676 223.0146 92.1457 61.0303 202.8358 288.4641 204.2446 66.6271 51.7113 202.3806 296.8514 218.9659 86.0765 58.1910 203.2009 292.6162 +2433.1812 2381.5752 2331.1621 2345.2542 2391.7717 2425.5684 2374.3164 2326.8555 2344.1296 2395.4685 2427.9292 2390.5010 2334.2598 2348.1462 2393.6060 2426.8335 2378.6892 2330.7046 2343.7720 2386.6711 2421.6997 2374.4963 2329.0002 2344.8481 2394.2969 2430.1121 2380.1572 2327.3760 2341.5637 2390.3240 2423.6201 2379.3132 2327.1628 2338.1355 2387.0447 2417.5066 2372.6101 2326.9314 2346.0256 2389.9407 2420.7104 2375.3821 2326.6980 2344.8198 2396.4312 2425.6753 2373.2385 2320.5344 2336.2302 2397.4104 2425.5413 2378.7610 2332.4587 2346.0371 2389.0442 2414.0845 2359.6321 2306.8716 2323.3101 2379.9946 2417.7793 2378.6152 2327.1367 2343.1560 2386.5964 2412.3386 2363.5334 2311.2634 2320.3623 2379.5803 2410.1882 2372.7166 2327.9080 2338.5129 2385.0178 2410.5007 2366.3003 +-5432.8447 -5181.5571 -5286.3633 -5602.5996 -5753.2144 -5457.1226 -5195.7378 -5279.0474 -5583.1265 -5719.4326 -5437.7412 -5155.9561 -5284.9019 -5599.7314 -5737.3770 -5430.7544 -5165.7710 -5265.5605 -5586.1060 -5732.9253 -5454.4624 -5185.7280 -5278.7642 -5595.4556 -5728.4209 -5429.5024 -5165.9541 -5276.7397 -5592.4956 -5722.7261 -5436.8853 -5156.3721 -5273.0654 -5600.6909 -5734.0898 -5450.0454 -5181.6021 -5278.4912 -5588.0811 -5736.9365 -5455.9980 -5179.0894 -5279.7456 -5595.7705 -5724.1299 -5441.0591 -5177.6890 -5288.0454 -5593.8042 -5709.0483 -5435.1675 -5173.3667 -5268.7441 -5585.5991 -5727.9150 -5446.4717 -5189.0562 -5313.3677 -5625.6631 -5751.5249 -5458.4492 -5162.3804 -5268.0405 -5574.8760 -5720.7720 -5450.5044 -5186.1313 -5290.5273 -5619.1943 -5748.6479 -5468.6660 -5190.6899 -5290.6719 -5604.6924 -5735.7246 -5453.6748 -5180.5820 +-4844.9082 -4595.1094 -4698.6875 -5016.2720 -5163.9063 -4868.6836 -4607.6743 -4692.4023 -4997.0322 -5131.4766 -4850.2910 -4569.0425 -4699.5942 -5012.4033 -5149.5298 -4842.7373 -4579.8984 -4679.9229 -4998.6328 -5143.4438 -4866.9775 -4600.2959 -4694.9229 -5008.9043 -5141.2383 -4842.5425 -4580.2886 -4690.6338 -5005.3042 -5134.9146 -4849.9365 -4570.6548 -4687.3525 -5014.8955 -5146.7378 -4862.6401 -4594.6064 -4693.2241 -5000.6211 -5147.9468 -4867.3525 -4591.9229 -4695.1680 -5008.0649 -5136.9785 -4853.9678 -4591.8213 -4702.9058 -5007.1016 -5121.6255 -4847.9487 -4588.7241 -4683.3828 -4999.5029 -5139.2139 -4858.1812 -4602.1055 -4727.1626 -5038.1523 -5163.8828 -4870.5483 -4577.3979 -4684.5161 -4989.3374 -5133.0298 -4863.3428 -4599.0161 -4705.8613 -5032.5430 -5159.9243 -4879.6167 -4602.1255 -4704.2651 -5017.3979 -5148.1265 -4865.8774 -4593.4800 +-2062.6106 -1824.0601 -1925.3975 -2233.7832 -2373.1277 -2084.2266 -1829.8053 -1917.6195 -2217.0911 -2343.7134 -2073.1277 -1798.9030 -1924.2183 -2228.4216 -2361.8535 -2065.5703 -1810.1118 -1909.2021 -2218.8599 -2353.8674 -2084.7197 -1829.5056 -1920.7548 -2226.3044 -2353.5874 -2065.4536 -1810.1086 -1917.7618 -2224.1860 -2349.4646 -2070.2339 -1802.1742 -1917.2626 -2231.5376 -2362.3235 -2083.5078 -1823.8579 -1921.2435 -2218.9714 -2359.1504 -2084.2998 -1820.8700 -1921.0267 -2223.3511 -2350.0820 -2073.3521 -1819.6006 -1928.4755 -2226.5918 -2336.9785 -2071.3359 -1819.6342 -1912.0529 -2220.7275 -2353.8860 -2079.3062 -1829.9087 -1951.7468 -2255.2979 -2374.0129 -2088.3127 -1807.3055 -1913.4437 -2213.7820 -2350.9539 -2084.5618 -1829.8263 -1934.9730 -2252.6345 -2372.7849 -2095.7266 -1827.3213 -1929.8413 -2236.1533 -2361.2903 -2087.8105 -1825.1820 +-2451.4202 -2208.6990 -2304.0952 -2612.3162 -2752.8699 -2472.0764 -2213.4324 -2296.7742 -2595.4216 -2725.9243 -2461.7864 -2183.5518 -2303.8840 -2607.2871 -2745.3152 -2455.7244 -2197.3098 -2289.1814 -2600.2251 -2737.6277 -2474.7681 -2217.2266 -2301.4414 -2604.6355 -2738.4043 -2455.8354 -2198.7664 -2300.1992 -2603.1042 -2731.5227 -2459.8215 -2190.0193 -2297.5764 -2611.9260 -2746.2632 -2473.8569 -2210.2864 -2300.2795 -2597.2236 -2740.2627 -2472.7810 -2207.5425 -2303.3362 -2602.0083 -2731.8201 -2460.6814 -2204.9390 -2309.1836 -2607.0403 -2720.2209 -2460.5959 -2206.4429 -2292.6777 -2600.1201 -2737.2461 -2468.5420 -2215.3091 -2329.7288 -2633.7366 -2756.5549 -2476.9812 -2194.3499 -2293.0027 -2594.2693 -2736.1235 -2474.0864 -2215.9517 -2316.0854 -2632.6453 -2756.9849 -2484.3379 -2213.0491 -2308.6970 -2613.9768 -2744.2776 -2477.6729 -2212.9204 +619.0143 860.6830 769.3347 467.0854 327.5048 599.8307 857.3204 776.1470 482.0939 350.7756 607.6656 882.4988 771.7821 471.6811 335.0545 612.9579 869.2610 780.9271 478.2279 337.3563 597.5548 853.5563 772.1013 474.4486 340.2368 613.6320 869.4918 772.7074 474.2549 342.5357 609.6962 875.4394 774.1277 465.3697 331.1111 596.5831 858.4532 773.7255 480.8495 338.6483 597.6253 860.8287 770.6677 476.7545 345.7149 608.6691 862.6205 763.3470 469.0951 353.5381 611.7417 863.4030 780.5058 477.1364 340.3896 601.0375 852.0515 744.8105 444.2132 322.7094 594.7238 872.6702 778.3561 481.9768 338.9380 594.2414 851.8994 755.7068 443.7548 321.2907 587.1212 856.4235 764.9881 462.9750 332.9672 592.4877 855.1392 +83.6720 317.3326 223.4887 -68.1990 -197.2761 68.3964 314.8239 229.1977 -56.6133 -178.8945 75.6176 335.4933 225.0499 -64.4941 -192.4372 77.5711 322.6874 231.1594 -60.8215 -192.0297 65.3966 310.5448 224.8247 -61.6002 -187.2616 79.8981 322.3788 225.2424 -63.9394 -187.6445 75.2929 326.3944 224.9333 -72.5333 -196.6464 62.7200 313.0022 225.3819 -57.8552 -188.4675 66.5432 314.3692 221.0928 -62.8944 -182.2129 74.8847 314.8463 215.1250 -69.6163 -176.5450 76.7392 316.9406 229.2347 -61.6086 -189.6161 64.8597 302.8132 195.1110 -92.9036 -206.4385 60.8671 322.8923 225.5885 -60.9839 -193.6824 58.3405 302.3548 203.7820 -93.6805 -206.2477 56.4423 312.3049 219.0934 -70.0952 -194.9856 59.7269 306.7445 +-98.4648 133.4387 43.4424 -241.1945 -369.6072 -112.3184 131.7254 50.0923 -230.6409 -353.2719 -104.8923 149.3519 48.5948 -236.8591 -364.1197 -104.7588 137.8407 51.1823 -234.1499 -365.7740 -115.0910 126.5220 45.7468 -234.9177 -359.6014 -101.0186 138.0681 46.2290 -238.5392 -361.8036 -106.6583 140.5539 44.9730 -247.1336 -370.2274 -117.1947 129.4634 46.5251 -231.5480 -362.5306 -114.7308 131.0505 42.4664 -235.0534 -354.4953 -105.9306 131.1746 36.1133 -243.8127 -351.7297 -104.9206 134.9208 50.5191 -234.4405 -363.7310 -116.0847 118.4882 15.8927 -264.9854 -379.2973 -120.5033 137.6034 46.2485 -236.3148 -368.7398 -124.0408 117.7388 24.0971 -269.3050 -381.1147 -125.8381 125.5396 38.3910 -245.7345 -370.8580 -124.6224 120.4234 +-912.8033 -701.3564 -791.9003 -1054.3074 -1166.2349 -924.5778 -706.2278 -789.3151 -1046.3402 -1153.2759 -918.9888 -688.3484 -788.6865 -1051.6863 -1162.2344 -919.8260 -700.2041 -787.9529 -1050.8643 -1166.1696 -929.6488 -711.5569 -791.9674 -1051.2109 -1159.7361 -916.4569 -700.1039 -793.3781 -1054.3478 -1163.3505 -923.2532 -700.1147 -794.3604 -1061.0688 -1169.0685 -931.3426 -709.2691 -793.4064 -1049.2101 -1163.4419 -927.9588 -706.6554 -795.9427 -1052.0049 -1155.2555 -920.7008 -707.5678 -803.3421 -1060.9785 -1154.0453 -920.8922 -704.2319 -789.9066 -1050.5314 -1165.4484 -931.4637 -721.6116 -822.1941 -1079.6820 -1177.5193 -933.4487 -702.0046 -793.9352 -1053.0577 -1168.9642 -937.9721 -720.6611 -814.2426 -1084.8260 -1179.8135 -940.3050 -710.9280 -798.3030 -1060.0702 -1171.6620 -937.9069 -718.0322 +-636.8519 -526.6597 -607.9560 -767.0701 -814.3766 -645.8356 -533.5677 -609.3967 -764.2021 -805.7259 -642.1977 -517.2286 -605.2474 -764.2708 -810.1625 -643.4214 -527.9941 -606.6143 -765.4543 -816.2378 -650.5186 -535.3107 -611.2474 -765.9033 -810.0823 -639.9453 -527.4763 -611.7514 -768.5032 -814.1104 -645.2615 -528.6571 -612.1845 -773.4808 -817.2342 -653.1178 -536.9566 -610.9199 -763.1652 -813.3253 -649.5497 -534.4419 -612.4032 -765.7114 -804.7957 -643.2485 -534.9832 -619.6376 -773.8046 -805.5297 -643.3590 -529.9689 -606.2516 -764.4042 -814.7572 -655.5103 -547.4469 -635.6460 -790.9134 -825.3115 -654.2057 -529.7876 -611.6173 -768.1579 -817.7838 -659.1550 -545.7974 -630.4514 -794.9180 -826.3303 -661.3763 -537.1324 -613.8195 -773.3202 -819.4506 -659.9576 -542.1168 +-5647.6982 -5398.9683 -5511.1782 -5824.7603 -5970.0693 -5670.1367 -5412.2334 -5502.5527 -5807.9165 -5940.6733 -5656.2373 -5375.2529 -5511.1802 -5825.4512 -5956.3662 -5645.6860 -5384.4990 -5488.4351 -5808.1733 -5950.9302 -5673.4775 -5407.5171 -5505.1914 -5821.9219 -5952.4126 -5648.4014 -5386.7324 -5499.0132 -5814.9028 -5941.4536 -5654.0366 -5374.8535 -5495.6060 -5824.7163 -5957.0200 -5668.6211 -5401.2998 -5503.1479 -5807.2666 -5951.9639 -5669.3848 -5397.9248 -5507.3691 -5817.7314 -5944.1499 -5655.2266 -5396.3086 -5512.5112 -5817.5884 -5928.3145 -5652.9341 -5395.6426 -5495.4063 -5812.5620 -5945.0029 -5658.9229 -5407.2451 -5537.4194 -5845.1860 -5971.4629 -5675.7744 -5382.8779 -5496.0132 -5799.8057 -5941.6133 -5665.6289 -5403.8833 -5515.6104 -5843.8599 -5966.9712 -5683.1362 -5407.5747 -5510.2725 -5827.7075 -5957.6289 -5673.8652 -5402.3760 +-5213.8638 -4969.7061 -5074.5811 -5387.2222 -5532.4272 -5236.8301 -4978.1973 -5064.3530 -5370.6182 -5501.8398 -5225.1201 -4942.1963 -5076.4521 -5385.2983 -5520.3691 -5216.0127 -4954.0239 -5053.6382 -5372.3418 -5511.6162 -5239.5991 -4978.8467 -5070.3120 -5381.8740 -5514.6514 -5216.9907 -4957.3525 -5066.1934 -5377.7119 -5505.2339 -5222.7183 -4944.8384 -5061.0576 -5387.2881 -5521.8452 -5238.6558 -4971.4937 -5068.9775 -5369.7246 -5514.5889 -5237.3760 -4967.4014 -5072.1240 -5379.2686 -5508.3535 -5225.3442 -4965.2583 -5077.3540 -5379.9131 -5490.9106 -5223.2261 -4967.5498 -5061.5889 -5374.3589 -5509.6016 -5228.5249 -4975.0132 -5100.0371 -5409.6958 -5533.7500 -5243.1240 -4953.8521 -5060.6099 -5365.7012 -5507.1626 -5235.2461 -4973.2100 -5082.2026 -5408.6772 -5530.4092 -5249.3218 -4971.7427 -5074.6558 -5390.6094 -5517.7393 -5242.2251 -4973.1846 +-2968.9883 -2726.7507 -2826.1812 -3136.7000 -3279.9441 -2991.9258 -2732.6770 -2816.9207 -3120.7778 -3251.0271 -2982.0659 -2700.8772 -2828.4136 -3133.5898 -3269.6067 -2973.1641 -2713.6968 -2809.0281 -3122.8132 -3261.5422 -2994.4995 -2735.8096 -2824.4475 -3131.8679 -3264.3374 -2974.4648 -2716.3892 -2821.3069 -3128.3376 -3257.2507 -2978.4912 -2705.6614 -2817.8174 -3136.6199 -3272.2615 -2993.3164 -2728.3958 -2823.4326 -3121.8398 -3265.0269 -2992.5754 -2724.9138 -2825.6096 -3129.2234 -3258.0850 -2981.6853 -2723.2261 -2832.0762 -3132.0286 -3245.0981 -2980.2476 -2725.0801 -2816.0483 -3127.2537 -3260.5759 -2987.2380 -2733.8711 -2854.1956 -3160.9893 -3282.4778 -2998.3911 -2712.4436 -2816.2854 -3119.7173 -3260.5950 -2995.0471 -2734.4331 -2838.8518 -3160.1938 -3282.0120 -3004.6963 -2731.5347 -2831.8994 -3141.9146 -3269.6697 -2998.3723 -2732.0610 +-3948.3372 -3698.3364 -3796.3486 -4106.9722 -4249.9189 -3966.8064 -3703.5596 -3787.3892 -4091.4600 -4225.7070 -3961.1521 -3675.5918 -3796.4470 -4106.2949 -4243.9819 -3952.1802 -3686.5334 -3778.6147 -4093.0901 -4237.2983 -3970.2180 -3709.2222 -3793.4580 -4101.4604 -4238.5742 -3954.8511 -3692.8914 -3791.9802 -4101.4346 -4233.7769 -3957.5730 -3682.3369 -3789.4092 -4109.2832 -4247.9570 -3973.7539 -3701.8518 -3793.1587 -4092.1311 -4237.5273 -3969.5605 -3702.5757 -3798.2163 -4100.8662 -4234.0117 -3960.1787 -3697.7952 -3802.7478 -4104.1812 -4220.1958 -3957.9688 -3700.2141 -3786.8406 -4099.5029 -4235.6699 -3965.3855 -3707.3381 -3822.9971 -4132.1123 -4256.5581 -3975.7295 -3688.6780 -3788.5503 -4092.9827 -4237.3877 -3972.1919 -3707.5737 -3810.6519 -4133.9351 -4257.5308 -3982.0732 -3703.2683 -3799.8711 -4111.1982 -4244.8833 -3975.9426 -3708.3691 +-1893.1404 -1643.2734 -1734.8158 -2043.8668 -2188.3672 -1911.5475 -1647.0470 -1728.6005 -2030.9170 -2166.4841 -1905.3555 -1623.6401 -1734.7899 -2041.9250 -2182.0847 -1900.1563 -1632.8441 -1722.4546 -2033.0640 -2178.0510 -1915.2969 -1653.3640 -1734.0383 -2038.3461 -2177.4353 -1899.9077 -1638.3740 -1733.5410 -2040.1794 -2175.4602 -1905.0510 -1630.8193 -1732.1138 -2048.5522 -2187.9373 -1917.0266 -1648.6586 -1733.7853 -2030.9205 -2176.4380 -1914.4851 -1648.1298 -1738.1097 -2040.2062 -2170.9968 -1903.6715 -1643.1680 -1744.0349 -2043.4778 -2162.5452 -1904.3145 -1645.0208 -1728.7316 -2037.1814 -2176.8394 -1913.4747 -1656.6469 -1763.0062 -2070.6631 -2196.7925 -1920.5652 -1636.4027 -1730.8315 -2033.8342 -2179.6567 -1920.0366 -1654.0715 -1751.4490 -2073.5510 -2198.6880 -1928.0094 -1650.4451 -1741.2380 -2049.3252 -2186.0886 -1922.8721 -1655.0038 +-3687.2146 -3438.0381 -3529.4092 -3832.9192 -3970.8123 -3701.9382 -3442.3650 -3522.5662 -3821.7180 -3954.8984 -3696.4912 -3424.1196 -3528.7046 -3831.5896 -3967.0535 -3694.2061 -3432.3552 -3520.3384 -3824.9287 -3967.2126 -3708.3486 -3448.6377 -3530.7021 -3828.5125 -3963.3103 -3692.3762 -3434.9827 -3531.0549 -3833.1038 -3965.3718 -3698.7498 -3431.5161 -3528.3684 -3838.6160 -3973.7231 -3709.6155 -3443.6157 -3529.5764 -3822.0176 -3964.1150 -3705.2283 -3443.0469 -3536.7844 -3829.6904 -3958.7971 -3696.0649 -3442.7847 -3540.0427 -3835.7781 -3953.3386 -3696.9980 -3442.0793 -3527.1707 -3829.4197 -3965.6775 -3705.8250 -3454.6926 -3561.4087 -3860.2366 -3984.6985 -3713.4707 -3436.6245 -3529.9702 -3828.0574 -3970.2449 -3713.3320 -3455.0647 -3550.5515 -3865.3960 -3985.2197 -3719.6860 -3448.6445 -3538.0439 -3839.6604 -3975.4299 -3715.7417 -3454.8247 +-2448.5437 -2216.3984 -2308.2732 -2592.9009 -2716.2949 -2461.2397 -2221.7136 -2305.1887 -2585.2800 -2706.2942 -2456.2144 -2205.7849 -2308.2310 -2591.6577 -2714.5798 -2456.6816 -2214.6509 -2302.8516 -2588.6565 -2718.5903 -2467.8325 -2226.5798 -2311.5869 -2589.4851 -2712.2441 -2453.5994 -2216.9460 -2311.3386 -2594.9470 -2716.1033 -2459.8936 -2214.1365 -2310.3918 -2600.9038 -2722.5063 -2468.6968 -2223.4822 -2309.9331 -2587.2417 -2714.2490 -2464.5549 -2222.3015 -2314.6479 -2591.6379 -2707.2988 -2455.9233 -2222.8806 -2319.6340 -2600.5017 -2703.6047 -2454.6572 -2218.6877 -2306.6262 -2589.2957 -2714.5618 -2467.9580 -2235.9912 -2340.1914 -2619.2510 -2730.0686 -2470.7939 -2218.7227 -2312.8103 -2591.9817 -2720.4341 -2472.9871 -2235.7617 -2331.4038 -2623.8372 -2731.7012 -2476.7927 -2227.3784 -2315.0251 -2599.7415 -2723.4253 -2475.1680 -2234.0227 +-1372.4532 -1188.4471 -1278.6924 -1514.9155 -1607.6398 -1384.6976 -1195.0450 -1279.9960 -1511.3809 -1598.6833 -1380.5510 -1180.3243 -1277.0172 -1514.3204 -1605.0393 -1380.0479 -1189.6455 -1277.2400 -1513.2640 -1610.6890 -1390.3102 -1198.6461 -1283.3944 -1515.1426 -1604.5299 -1378.6460 -1192.4758 -1284.6200 -1519.3746 -1608.3649 -1384.8547 -1191.1401 -1283.4709 -1522.8660 -1611.8923 -1391.4659 -1199.3712 -1284.1978 -1512.6263 -1607.5737 -1388.5231 -1197.1549 -1287.2655 -1515.2484 -1599.7407 -1380.3746 -1197.9072 -1291.7125 -1523.8538 -1597.4890 -1380.0642 -1192.5392 -1280.2494 -1514.3652 -1608.4135 -1392.2813 -1210.1538 -1310.6689 -1540.6726 -1620.6949 -1393.9912 -1193.5322 -1285.2065 -1516.4063 -1612.0430 -1397.1722 -1209.9738 -1303.7899 -1547.7803 -1621.5685 -1400.0298 -1200.8861 -1287.0933 -1523.8866 -1613.5297 -1399.3120 -1206.5968 +326.1956 398.7625 321.4643 202.4660 178.7342 317.0193 390.0680 316.1822 200.8274 183.5980 320.8335 405.0668 322.6675 203.8155 181.0793 318.9032 395.2200 320.0359 198.0617 172.9723 311.2373 388.0066 315.6949 198.8345 180.4684 320.9784 393.1466 313.8635 196.5728 176.3632 315.4618 392.2569 314.3420 192.5477 173.6699 310.0102 386.8983 314.1165 200.8016 176.4537 314.5612 389.7158 314.5703 199.2789 184.2783 318.9346 388.4822 306.4288 190.6231 184.2785 318.5644 393.5158 320.1299 201.3385 176.0721 306.8366 375.5211 292.1078 178.9043 166.7267 307.8468 392.3441 313.8736 197.3176 173.8580 304.4949 379.3614 298.3640 173.7066 165.7406 302.6117 386.9063 313.2301 191.9336 170.3707 303.1998 380.3290 +145.4604 91.9297 71.3836 105.0293 142.9805 137.6379 84.2493 66.0340 102.8287 144.6096 139.8546 96.4791 70.9665 105.6336 142.7321 139.1594 86.8630 67.4907 100.0945 134.4520 132.2965 81.4078 65.6041 100.8830 141.5855 140.1592 84.7532 63.8200 99.0525 137.2624 134.1052 83.6036 64.4508 95.8741 135.1890 129.4408 80.4737 64.7104 102.0801 137.9965 134.0780 83.5126 63.8291 101.2189 145.0910 137.0452 81.4580 58.5845 94.0371 144.9506 138.6445 86.5948 68.9759 104.3432 138.3286 126.0090 69.9352 46.3474 84.0626 128.9841 129.1612 85.2288 64.9481 100.9293 135.3119 125.8603 73.0343 51.2895 80.8366 128.6800 123.4774 80.1264 64.4587 95.8642 132.1275 122.9225 76.2235 +36.3656 -87.2077 -62.8841 62.2512 128.0151 29.9712 -93.5913 -68.0806 59.6916 129.7759 32.1658 -84.4560 -63.7146 63.1701 128.4777 29.3747 -93.4023 -67.4428 56.8506 119.6798 23.9472 -98.0708 -69.1029 58.1052 126.1987 29.8673 -94.5036 -69.9246 57.2271 124.0311 25.6559 -95.5284 -71.6326 54.1795 122.1658 21.3156 -99.8530 -70.8349 57.9472 122.6800 24.6545 -96.0230 -69.9785 59.3689 127.9831 26.0231 -98.9731 -75.6896 54.0046 128.9713 28.1303 -93.2351 -65.6597 61.7358 121.3803 17.1438 -107.0192 -85.0710 44.1856 113.9792 18.2714 -93.4693 -68.0740 58.5434 120.9686 16.7749 -104.8496 -81.1696 41.8868 113.5177 14.6434 -99.3798 -69.8267 54.6252 116.2759 13.2183 -101.7966 +-160.4870 -160.3180 -153.3991 -149.3515 -153.4233 -163.3915 -166.0575 -158.5886 -151.3062 -153.9011 -164.5091 -160.5134 -153.1641 -149.4906 -153.2439 -163.9937 -166.4715 -158.7796 -156.7097 -160.3134 -167.0124 -169.5715 -159.5626 -154.7616 -154.0511 -160.9862 -165.9652 -157.8028 -155.1477 -156.8329 -165.9998 -167.8894 -160.4932 -158.4527 -158.8615 -167.9205 -167.6267 -159.0546 -153.6589 -155.8069 -165.1962 -166.4843 -157.9959 -155.6797 -153.1357 -165.7814 -168.8648 -162.5094 -157.3399 -152.7839 -162.6631 -163.9707 -155.7624 -152.2336 -157.5135 -173.2713 -174.5849 -169.6195 -163.3377 -163.1118 -170.4838 -165.8827 -158.8000 -152.7930 -158.4571 -170.7761 -172.7901 -165.8971 -163.3730 -163.2614 -171.2978 -169.6249 -159.0962 -154.6891 -162.5062 -172.3421 -169.6953 +1515.8210 1546.9159 1520.4680 1476.4779 1466.6990 1515.2815 1545.6616 1520.1899 1476.1361 1467.6100 1516.5432 1546.3579 1520.1470 1476.3618 1466.3951 1514.9576 1545.3783 1518.2717 1474.5779 1462.7433 1514.4618 1545.3877 1518.1801 1474.4913 1466.8188 1517.8003 1545.4219 1519.7963 1473.6694 1465.4218 1513.8354 1544.9108 1518.7710 1474.2263 1465.4132 1516.7476 1545.4901 1518.9792 1474.2759 1466.2837 1516.5411 1546.8096 1520.3568 1475.4685 1467.5491 1516.2805 1545.9778 1517.8096 1474.2128 1468.1843 1517.6743 1548.0267 1522.0249 1478.0193 1466.3562 1513.7681 1543.9509 1515.6300 1473.4022 1464.7523 1515.3356 1546.4897 1519.4849 1475.5365 1466.6970 1516.9114 1547.0472 1518.0913 1473.9666 1466.2323 1514.2498 1546.3022 1520.2217 1474.9249 1466.8251 1514.2646 1546.7559 +-8114.0000 -7862.7695 -7976.0430 -8288.0654 -8433.2441 -8135.2451 -7875.8188 -7966.1997 -8272.3037 -8407.0361 -8121.0698 -7839.0454 -7974.6958 -8289.2363 -8419.4766 -8111.5562 -7848.0693 -7951.6875 -8271.1836 -8415.3711 -8138.8740 -7872.0234 -7969.3589 -8284.8164 -8417.7822 -8114.3013 -7850.4790 -7962.7231 -8279.0469 -8406.3516 -8120.2407 -7839.3555 -7958.9629 -8289.1240 -8423.1221 -8135.3623 -7866.0015 -7967.4312 -8270.3828 -8415.4336 -8133.5435 -7862.8970 -7973.1680 -8282.8174 -8408.3311 -8120.1504 -7860.4810 -7975.4336 -8281.4160 -8393.0625 -8119.1768 -7860.1992 -7960.9551 -8278.1318 -8408.9102 -8123.2114 -7871.0757 -8000.2407 -8308.3564 -8435.5967 -8140.4648 -7848.2207 -7960.4434 -8265.5439 -8407.1904 -8130.6230 -7868.0728 -7979.3691 -8308.5938 -8430.7178 -8149.5010 -7869.7788 -7972.9751 -8290.6592 -8421.0137 -8139.9790 -7866.4912 +-5740.5449 -5494.5845 -5600.0269 -5910.2432 -6053.5708 -5761.8564 -5503.6260 -5590.5161 -5895.1851 -6027.0000 -5752.8105 -5468.9551 -5602.2246 -5910.3320 -6043.7314 -5743.6191 -5482.0181 -5580.0273 -5895.6704 -6035.5137 -5765.5571 -5505.9712 -5596.4951 -5906.4941 -6039.2754 -5745.0122 -5485.6719 -5592.4951 -5902.4893 -6030.1221 -5750.3501 -5473.5278 -5587.7729 -5912.0391 -6046.1563 -5766.5693 -5497.5010 -5594.5850 -5894.0938 -6037.4453 -5762.6235 -5495.0337 -5598.8442 -5904.1328 -6032.0767 -5751.6855 -5492.0244 -5603.1021 -5904.3691 -6017.2617 -5750.3467 -5494.1719 -5587.3872 -5901.0679 -6032.3994 -5754.3286 -5502.4414 -5625.5718 -5934.0669 -6057.2905 -5768.8179 -5481.9380 -5587.9849 -5890.7598 -6033.0508 -5762.2505 -5500.9683 -5609.8379 -5934.7515 -6054.9326 -5775.3994 -5499.5723 -5600.1606 -5914.5718 -6043.0635 -5769.3486 -5500.5073 +-6573.1450 -6319.5542 -6415.4546 -6726.6318 -6875.4595 -6592.2256 -6325.6011 -6405.6787 -6712.0811 -6850.6484 -6585.0581 -6293.9253 -6417.4971 -6727.7852 -6870.2080 -6576.0254 -6306.9282 -6396.3872 -6713.1816 -6859.7061 -6594.8296 -6332.1265 -6413.6216 -6721.8003 -6863.4146 -6577.8447 -6310.0835 -6408.1104 -6719.6392 -6855.2793 -6582.1089 -6299.3237 -6404.1235 -6729.6660 -6872.7285 -6597.1797 -6320.6763 -6409.5776 -6709.2061 -6860.1040 -6592.5615 -6321.1934 -6416.4043 -6721.4087 -6857.3379 -6582.7324 -6315.4248 -6419.4717 -6722.4067 -6842.1665 -6582.5820 -6319.7627 -6404.8408 -6718.2700 -6858.2646 -6588.2573 -6325.1826 -6440.1357 -6752.0908 -6881.6226 -6600.4639 -6308.7788 -6405.7026 -6710.9248 -6861.0796 -6595.7158 -6325.0532 -6426.9971 -6755.4771 -6882.6514 -6606.9995 -6322.8911 -6416.9492 -6732.7461 -6868.6406 -6601.9150 -6328.1426 +-3665.6208 -3403.7800 -3492.9504 -3806.3101 -3954.6729 -3678.1685 -3408.1299 -3487.2144 -3792.0198 -3937.0117 -3673.6265 -3382.9688 -3493.3521 -3808.4631 -3952.7695 -3668.0720 -3393.1326 -3477.3596 -3792.6523 -3946.3616 -3682.4451 -3417.0198 -3492.9736 -3801.8398 -3948.3792 -3670.4170 -3399.9106 -3490.5718 -3804.7488 -3944.3047 -3674.4832 -3392.2058 -3488.7988 -3810.9429 -3958.3267 -3687.7798 -3409.6023 -3491.8958 -3794.1853 -3943.7837 -3683.1707 -3414.8943 -3502.7964 -3808.6240 -3944.4780 -3674.8276 -3403.3167 -3501.3010 -3806.0149 -3932.8704 -3673.9287 -3407.0327 -3490.5576 -3803.0078 -3945.1509 -3682.6184 -3416.2380 -3523.2437 -3838.7319 -3969.7356 -3694.4292 -3399.9590 -3489.8293 -3796.2180 -3949.0691 -3690.4009 -3414.8054 -3510.7007 -3839.4966 -3970.4553 -3700.3567 -3412.1865 -3498.4009 -3812.8501 -3955.3662 -3693.4197 -3417.0593 +-3094.6289 -2833.3955 -2922.8059 -3235.9504 -3383.2791 -3108.3877 -2837.9529 -2921.2141 -3223.4373 -3367.2463 -3103.2354 -2816.1313 -2924.3760 -3237.6172 -3382.2644 -3099.4556 -2824.1926 -2909.3486 -3225.2454 -3378.1765 -3112.6394 -2846.8513 -2923.3691 -3231.6694 -3375.5420 -3098.8696 -2830.3496 -2923.9321 -3235.0259 -3374.4673 -3103.9880 -2822.5449 -2922.1296 -3241.1133 -3385.3843 -3114.2996 -2839.7368 -2921.3713 -3224.9231 -3374.3428 -3111.0210 -2843.9814 -2930.0715 -3236.5371 -3372.8831 -3101.7349 -2834.5254 -2931.7820 -3236.7185 -3359.8589 -3100.2212 -2835.5330 -2917.7798 -3230.5007 -3373.0596 -3113.7334 -2845.8521 -2952.7729 -3265.0125 -3395.0483 -3119.9907 -2829.1172 -2919.8967 -3226.6638 -3377.1079 -3117.3188 -2844.3579 -2941.6270 -3267.9688 -3397.6462 -3127.3918 -2843.0239 -2928.8711 -3241.1912 -3383.9417 -3118.9888 -2846.4639 +-4971.7559 -4720.3472 -4822.2427 -5127.1304 -5260.3179 -4983.1851 -4726.5601 -4819.4595 -5116.9976 -5245.5566 -4980.1196 -4710.4048 -4822.2983 -5130.2832 -5258.2856 -4976.5200 -4715.9873 -4811.3892 -5119.1567 -5259.5151 -4988.3608 -4733.2900 -4823.1221 -5125.3262 -5255.0562 -4977.1284 -4722.0737 -4826.0786 -5129.2402 -5257.4819 -4983.0020 -4718.0376 -4822.4336 -5134.7075 -5265.9409 -4992.4438 -4731.6885 -4826.1587 -5121.2783 -5256.0039 -4988.8896 -4733.3511 -4832.8413 -5130.7788 -5252.8369 -4980.7720 -4728.2588 -4833.4731 -5134.2192 -5246.1221 -4978.3833 -4725.2339 -4822.1206 -5125.9326 -5255.6841 -4989.8662 -4741.3589 -4854.6689 -5155.8530 -5276.3320 -4998.7031 -4725.2900 -4824.9023 -5125.4614 -5261.3779 -4997.6743 -4739.5542 -4846.3477 -5162.6416 -5278.3037 -5005.8999 -4737.2344 -4831.4380 -5136.2515 -5266.4932 -4998.7075 -4742.2583 +-3817.9438 -3592.3062 -3692.0786 -3973.9907 -4091.5398 -3830.0051 -3598.7197 -3693.9512 -3968.4607 -4080.0320 -3826.4016 -3583.1062 -3692.3171 -3975.1838 -4087.9307 -3824.5498 -3589.9724 -3686.6870 -3970.8384 -4093.3718 -3837.0588 -3603.0789 -3697.5837 -3975.5422 -4087.9084 -3825.4700 -3595.8540 -3698.7004 -3979.0554 -4092.4165 -3830.0688 -3593.1963 -3696.5647 -3984.2656 -4096.5371 -3839.7134 -3604.4189 -3699.6184 -3973.7517 -4091.5972 -3835.0181 -3604.0544 -3704.4563 -3978.2998 -4083.9819 -3827.0759 -3600.9163 -3706.3452 -3984.9683 -4081.8557 -3826.9829 -3597.5093 -3695.0212 -3974.6343 -4090.2031 -3838.8521 -3614.7510 -3725.5647 -4002.3293 -4106.4873 -3843.3086 -3597.7886 -3700.3904 -3975.9885 -4095.4668 -3842.8367 -3613.1887 -3718.1248 -4008.8157 -4106.8691 -3847.8147 -3605.9324 -3700.6372 -3983.5386 -4098.0024 -3846.8638 -3611.3435 +-2043.8322 -1870.9240 -1967.5493 -2192.1418 -2271.6628 -2054.6201 -1881.6377 -1973.9972 -2192.1392 -2267.6348 -2049.5613 -1865.6694 -1968.9260 -2193.8589 -2270.6833 -2051.2175 -1874.8663 -1968.7202 -2196.2104 -2280.5771 -2060.8914 -1885.0908 -1976.4366 -2197.2700 -2273.2258 -2050.9590 -1880.1085 -1976.8096 -2200.2275 -2277.4106 -2056.3557 -1877.6799 -1975.3270 -2204.2625 -2281.1365 -2063.5286 -1885.6113 -1978.0769 -2196.5886 -2277.0962 -2058.7896 -1883.0988 -1980.4764 -2199.3950 -2270.0129 -2052.8938 -1884.4858 -1985.0894 -2206.7808 -2269.8267 -2052.2583 -1878.4326 -1973.6566 -2196.8477 -2278.0498 -2065.3013 -1898.7726 -2003.3372 -2219.5942 -2289.0874 -2065.2576 -1881.9047 -1979.8546 -2199.0298 -2280.3606 -2066.8511 -1895.3051 -1995.3065 -2228.5256 -2290.4614 -2069.7649 -1886.3354 -1979.4420 -2205.7527 -2284.4680 -2070.4741 -1893.3318 +458.8953 534.7487 468.5098 354.9846 326.6594 449.0101 524.1694 460.3350 351.8267 329.0114 452.5768 537.7072 468.7544 354.1245 329.2533 451.4226 528.1031 462.9927 346.9756 317.5902 443.9397 521.9935 458.9525 347.7834 325.4063 452.2538 525.2025 458.2376 346.1890 321.6442 446.3828 524.8998 458.2957 342.5108 319.8481 441.7010 519.9787 457.0737 347.7000 320.9457 446.6408 523.2683 456.5393 346.0348 327.4300 449.6996 520.1016 450.8005 339.3991 328.6627 450.4811 525.5361 461.4768 349.5087 320.4119 437.3861 508.6437 437.8386 329.8250 312.2233 439.8188 523.1091 456.0562 346.7481 319.1926 438.7932 511.1711 443.1618 324.2421 311.5645 436.2345 519.7858 457.0060 341.2658 314.4911 435.1552 515.2160 +-733.2314 -685.7292 -722.7623 -793.7039 -811.0868 -740.4067 -694.3376 -731.2854 -795.9615 -810.7763 -739.2181 -685.4136 -725.1091 -793.4642 -810.3529 -740.1605 -692.8117 -730.5084 -802.8267 -823.1936 -747.3853 -698.8957 -733.7554 -798.8013 -814.7446 -739.7716 -696.7495 -733.7859 -802.2466 -819.1835 -745.1659 -697.3295 -733.5577 -805.2762 -820.4988 -747.9023 -699.1916 -735.1273 -801.3480 -819.1389 -743.4810 -696.5811 -733.9887 -800.7584 -813.0143 -742.1800 -700.3361 -739.6133 -806.1456 -812.8659 -740.1608 -694.7001 -730.9420 -798.5761 -819.7975 -754.0170 -709.7047 -749.7258 -814.3215 -827.9139 -751.1118 -697.8474 -735.0515 -801.4541 -820.6461 -751.8130 -705.3290 -745.7728 -816.8420 -826.8238 -753.2195 -700.9026 -735.8857 -805.6677 -825.7617 -755.8431 -704.2934 +1254.4108 1311.1603 1274.0820 1199.1246 1175.0238 1251.1827 1305.9224 1269.3601 1196.1079 1174.7966 1250.5928 1309.7874 1272.3744 1196.3401 1174.1309 1250.3612 1304.9994 1266.8142 1190.3154 1164.6531 1244.2732 1300.6654 1266.4949 1191.2534 1172.3441 1250.4948 1302.2849 1266.3126 1189.5779 1166.7384 1245.3215 1301.1552 1265.1025 1188.7128 1167.2845 1244.6711 1300.4330 1265.0717 1189.5741 1167.1005 1246.5654 1301.1418 1263.7546 1190.2059 1171.3091 1247.6171 1298.4390 1260.0370 1187.0894 1171.0603 1248.5038 1302.8618 1266.0911 1191.8420 1167.7523 1241.8281 1294.1901 1253.1042 1181.6835 1162.1105 1241.2556 1300.1804 1262.5121 1189.5226 1166.2230 1242.5828 1295.7988 1257.4139 1180.5154 1163.3833 1241.3270 1297.8129 1262.9760 1186.1830 1162.2463 1238.6552 1296.9718 +3370.2874 3490.4150 3430.4146 3284.0146 3229.5173 3370.3889 3487.7456 3427.9070 3281.7117 3229.2961 3368.2629 3488.5203 3428.9729 3281.4983 3228.3977 3369.6980 3486.8396 3426.0156 3277.7246 3222.7158 3366.7168 3486.4744 3426.3250 3280.3167 3229.1653 3371.3608 3487.6680 3427.4661 3279.2148 3224.6057 3368.1206 3486.4221 3426.9812 3280.2334 3228.9314 3369.3154 3488.3684 3428.0042 3278.8828 3226.4373 3370.5798 3488.8005 3427.1382 3279.2876 3228.3413 3369.4241 3487.4519 3424.5146 3278.7693 3229.2959 3372.3806 3490.5044 3429.0415 3281.5278 3227.8982 3368.6919 3485.7266 3423.2493 3278.1111 3226.2864 3369.4863 3486.8391 3423.1338 3278.1194 3226.9514 3371.4419 3488.3516 3426.7246 3278.5310 3226.6003 3369.3625 3486.3635 3425.3977 3277.0054 3225.3169 3367.9211 3489.7622 +-17105.6113 -16840.4102 -16953.5957 -17268.0762 -17417.9902 -17120.2930 -16855.3613 -16944.8418 -17256.3438 -17397.8535 -17106.8516 -16820.5586 -16951.6660 -17273.8965 -17405.6074 -17100.1895 -16828.0762 -16925.8340 -17249.6934 -17402.9453 -17126.4316 -16852.3105 -16946.2656 -17267.3555 -17408.8281 -17103.5254 -16830.3477 -16937.6523 -17261.7910 -17395.5352 -17112.4922 -16819.7207 -16936.5293 -17268.4883 -17410.3281 -17124.9297 -16847.3926 -16946.4277 -17251.1680 -17400.7129 -17122.4941 -16846.1816 -16953.5508 -17266.1621 -17394.0332 -17107.8047 -16841.1504 -16951.1895 -17262.7773 -17385.3887 -17108.1797 -16842.6973 -16943.4590 -17261.2266 -17393.1973 -17109.7031 -16852.7988 -16978.1426 -17289.3242 -17422.8496 -17129.9727 -16831.3574 -16940.0371 -17248.4707 -17396.0391 -17118.3457 -16848.4414 -16959.8477 -17292.3574 -17416.9512 -17138.7813 -16852.4941 -16947.7031 -17271.7266 -17410.1621 -17130.7383 -16850.3652 +-5586.7578 -5311.2222 -5395.8154 -5711.0337 -5867.8481 -5594.0850 -5319.1680 -5388.8027 -5694.5728 -5857.0313 -5586.0029 -5281.9966 -5390.5342 -5711.9570 -5867.1030 -5581.5205 -5297.8257 -5372.9453 -5690.5957 -5857.0005 -5601.3457 -5326.0513 -5389.5234 -5701.3877 -5863.2515 -5587.1157 -5300.0928 -5381.4624 -5699.3159 -5849.3911 -5594.0190 -5291.8936 -5384.5483 -5711.3286 -5869.0620 -5602.8647 -5314.5059 -5385.1362 -5692.3896 -5849.2031 -5600.7534 -5318.1504 -5400.9468 -5709.1611 -5850.4805 -5582.9297 -5303.9321 -5399.1963 -5703.2363 -5839.5820 -5589.0781 -5311.9561 -5387.8096 -5700.3706 -5844.6167 -5588.5034 -5316.4404 -5417.7236 -5739.7827 -5880.8550 -5608.5435 -5300.4414 -5380.9644 -5685.0313 -5854.9116 -5599.6475 -5312.6929 -5408.4644 -5737.5640 -5875.9048 -5615.4141 -5317.4766 -5391.4478 -5711.0723 -5860.2891 -5606.6177 -5324.3008 +-7411.0879 -7149.0718 -7242.3496 -7553.4229 -7698.8662 -7420.0273 -7156.1079 -7236.9521 -7540.3013 -7684.4688 -7416.3271 -7128.3169 -7243.4048 -7558.3335 -7699.1611 -7411.7441 -7140.1665 -7225.3945 -7540.2314 -7692.0542 -7426.0591 -7163.4961 -7241.4873 -7549.2593 -7693.5679 -7414.1929 -7145.5229 -7238.6108 -7551.3672 -7688.2456 -7419.6270 -7139.1138 -7237.6196 -7560.0864 -7702.2651 -7431.7500 -7155.5972 -7241.3457 -7540.7817 -7686.9443 -7426.4658 -7162.8047 -7252.4956 -7556.8281 -7689.5107 -7417.5474 -7149.1973 -7250.8057 -7554.0356 -7675.4868 -7416.7515 -7152.9961 -7239.8062 -7551.0601 -7686.0503 -7423.7422 -7161.2876 -7271.4395 -7584.1782 -7713.7046 -7438.5044 -7145.8335 -7238.0474 -7540.8716 -7691.9258 -7432.4917 -7159.2817 -7260.0024 -7587.6841 -7714.2993 -7444.3745 -7160.0596 -7245.8647 -7558.6782 -7698.1777 -7434.1909 -7162.3789 +-8000.2803 -7741.6899 -7852.0503 -8166.4585 -8299.0146 -8009.6436 -7748.1401 -7851.3169 -8158.1875 -8287.9688 -8008.4697 -7737.1172 -7854.7422 -8172.4272 -8299.2666 -8005.0708 -7736.4102 -7840.3516 -8158.8350 -8301.6709 -8018.3525 -7755.0942 -7856.4058 -8167.5493 -8297.2773 -8006.1240 -7747.0986 -7856.5752 -8171.5947 -8300.1328 -8010.8271 -7742.1157 -7853.7559 -8175.6372 -8305.9531 -8022.4976 -7755.1006 -7859.6177 -8165.4878 -8300.2520 -8016.8521 -7757.4951 -7865.7476 -8174.3931 -8296.7549 -8009.2178 -7751.7764 -7863.3682 -8177.0391 -8288.3975 -8006.8267 -7747.8071 -7854.6245 -8167.4780 -8297.3604 -8021.0474 -7764.7979 -7885.9766 -8196.0371 -8318.1621 -8030.0688 -7753.0068 -7859.7617 -8167.1724 -8302.0068 -8024.2041 -7762.6851 -7877.5259 -8206.0391 -8320.2383 -8035.5127 -7763.4351 -7861.8101 -8177.8892 -8309.4678 -8028.9668 -7763.6255 +-8542.6055 -8289.2588 -8394.6855 -8702.1016 -8831.9092 -8553.6328 -8299.0908 -8401.0947 -8700.3389 -8826.9443 -8553.0518 -8289.3848 -8400.4902 -8708.9678 -8833.8096 -8551.1357 -8290.2432 -8393.7441 -8704.5352 -8840.7031 -8563.2012 -8307.4229 -8407.0313 -8710.5156 -8835.6553 -8553.8770 -8301.0791 -8407.4648 -8713.5088 -8839.7178 -8557.7959 -8296.6445 -8403.4404 -8717.1260 -8843.5371 -8567.8398 -8307.3779 -8411.0059 -8710.4639 -8841.5938 -8562.3359 -8308.5615 -8415.0293 -8714.5010 -8833.2852 -8555.5322 -8306.2705 -8414.3320 -8719.2744 -8828.9902 -8553.4121 -8300.4268 -8405.7676 -8708.4561 -8839.4375 -8568.4141 -8319.2344 -8434.4063 -8734.1172 -8854.7520 -8573.9004 -8306.4102 -8409.9863 -8711.6475 -8841.8271 -8569.3877 -8316.8750 -8427.4971 -8745.8506 -8856.9063 -8577.7119 -8313.9287 -8414.2842 -8721.6602 -8848.2959 -8576.6055 -8317.8330 +-4466.0928 -4249.6826 -4351.0171 -4618.0483 -4724.2432 -4478.3062 -4262.1250 -4361.8271 -4621.2368 -4723.4067 -4477.1958 -4251.3271 -4354.7505 -4622.9263 -4723.8384 -4475.3062 -4255.7295 -4355.1094 -4627.9937 -4737.2715 -4489.6040 -4271.6816 -4366.0337 -4628.4897 -4730.2695 -4479.7773 -4265.1655 -4365.7100 -4631.6890 -4735.4634 -4483.4360 -4263.9019 -4365.3462 -4636.0718 -4739.1455 -4491.9121 -4272.4126 -4370.8301 -4632.5093 -4737.8525 -4484.9043 -4269.3877 -4370.3706 -4631.9458 -4727.2266 -4480.2656 -4269.3477 -4372.9810 -4637.8364 -4726.1577 -4479.4229 -4264.6265 -4363.3613 -4627.0527 -4734.9111 -4493.3374 -4280.8105 -4388.8252 -4648.2847 -4745.9473 -4493.4868 -4267.9009 -4370.4365 -4630.5732 -4736.1909 -4491.6411 -4277.9355 -4383.0249 -4656.7915 -4745.3804 -4495.6040 -4272.2881 -4369.2432 -4638.7065 -4742.8667 -4498.3125 -4278.1289 +-5253.7012 -5081.9575 -5170.9316 -5386.4570 -5467.2705 -5263.6411 -5092.5249 -5180.9824 -5391.2437 -5468.0664 -5262.5645 -5084.3105 -5173.4521 -5390.3774 -5466.4653 -5262.9507 -5090.6816 -5178.1919 -5399.1294 -5481.6450 -5273.0703 -5101.2959 -5185.6445 -5397.0664 -5472.3525 -5264.5850 -5098.1597 -5186.2842 -5402.3594 -5478.9150 -5268.9419 -5098.2324 -5185.7422 -5405.2876 -5480.7891 -5274.4702 -5102.6021 -5190.5737 -5401.2144 -5480.0635 -5268.2280 -5098.6855 -5187.0264 -5400.6929 -5472.5981 -5267.2563 -5103.0459 -5194.3271 -5407.7231 -5470.5488 -5266.1392 -5096.1855 -5183.6606 -5396.7905 -5478.8066 -5278.0894 -5112.9312 -5205.9790 -5415.1392 -5487.1968 -5278.1221 -5101.4292 -5190.8926 -5400.7949 -5480.4004 -5277.4360 -5110.1533 -5201.8506 -5422.0933 -5486.3174 -5279.7598 -5103.4019 -5189.2979 -5408.9336 -5487.3486 -5283.8115 -5108.4756 +-2292.4617 -2164.5420 -2234.7378 -2399.0913 -2455.2825 -2295.9722 -2172.4026 -2243.4192 -2403.2358 -2457.6201 -2298.9175 -2164.8528 -2237.8074 -2401.1875 -2455.8040 -2298.0364 -2172.4104 -2243.7754 -2410.0823 -2469.6218 -2305.4907 -2178.1414 -2247.7957 -2405.8701 -2459.2319 -2297.1003 -2175.2246 -2246.9026 -2410.4207 -2465.5291 -2304.2322 -2177.5771 -2247.8608 -2411.6621 -2465.1082 -2304.3992 -2177.4346 -2249.3733 -2409.7852 -2464.0635 -2301.1670 -2174.7231 -2247.8220 -2409.4846 -2458.0229 -2300.5779 -2179.4326 -2253.4624 -2414.4998 -2458.7036 -2297.9844 -2173.6956 -2245.5544 -2406.6990 -2464.4768 -2308.5859 -2186.5769 -2261.5242 -2419.6892 -2470.6179 -2307.2104 -2177.8130 -2249.9712 -2409.9231 -2464.7168 -2305.2844 -2182.4421 -2256.6807 -2422.4985 -2469.0354 -2306.7368 -2178.1509 -2249.8049 -2413.6843 -2470.5054 -2310.4839 -2180.9587 +-105.1208 58.9632 -6.9110 -198.0781 -279.3481 -105.3251 56.8474 -9.8053 -200.5124 -279.6183 -107.8890 57.9664 -10.5539 -202.2167 -280.4695 -107.1126 54.6566 -13.6697 -208.4202 -289.8157 -112.4920 51.4679 -14.3311 -206.7605 -282.3438 -106.9699 52.4977 -14.2224 -212.3852 -290.6869 -113.5409 49.0109 -15.1586 -208.9734 -286.1405 -109.8745 53.0815 -16.1629 -208.6180 -287.2478 -109.3536 53.3367 -15.8096 -209.2825 -285.3831 -108.5867 50.0045 -19.4384 -210.1472 -285.1212 -107.6513 53.6849 -15.1451 -204.9789 -284.0098 -110.6998 49.2263 -22.4237 -210.5695 -288.5131 -111.1696 51.0362 -18.2743 -207.7017 -285.7114 -107.1606 52.7086 -17.8814 -210.2113 -287.7773 -108.4231 50.1045 -18.2647 -211.8947 -288.8697 -111.4026 52.0481 +-10731.1074 -10422.7354 -10516.5371 -10824.7236 -10991.0742 -10726.4775 -10452.7637 -10502.8008 -10829.6074 -10984.9404 -10705.4785 -10407.6523 -10508.9746 -10863.7627 -10972.2939 -10712.8408 -10420.6133 -10485.0049 -10805.8115 -10991.1738 -10753.4277 -10433.2148 -10502.0215 -10819.8477 -11007.2295 -10706.7471 -10411.7666 -10493.9980 -10809.3555 -11013.9629 -10728.5889 -10410.1523 -10500.4434 -10818.3164 -10988.9199 -10731.7959 -10434.8799 -10513.0137 -10799.7266 -10991.9707 -10732.8096 -10439.2500 -10519.2607 -10832.5732 -10967.6699 -10698.8809 -10453.7119 -10493.4385 -10822.8994 -10984.5977 -10716.7412 -10427.6211 -10503.2441 -10818.6270 -10980.8779 -10707.1064 -10436.5625 -10556.4082 -10841.4512 -11005.8193 -10737.8574 -10429.4639 -10474.7900 -10809.2305 -11000.7754 -10712.9160 -10453.7627 -10529.2197 -10854.7197 -11000.3984 -10748.0596 -10447.4063 -10500.5137 -10816.0039 -10995.9814 -10752.6904 -10446.6172 +-54.6271 228.0549 126.0827 -190.5258 -339.8010 -48.7767 217.7714 127.2144 -187.2063 -334.3264 -44.5955 247.5522 130.0926 -206.1578 -341.7850 -47.8340 237.9487 144.6936 -183.6343 -343.9725 -70.3388 211.9699 125.4487 -195.8828 -349.3808 -54.7509 227.3422 122.5319 -203.4097 -348.9018 -70.8616 221.9522 110.1573 -212.4953 -361.6351 -79.6844 201.0187 109.3361 -200.8075 -348.8540 -84.3225 188.2413 84.0654 -233.1889 -361.4061 -70.8104 199.8051 92.6943 -224.7353 -353.7563 -78.9027 198.2016 98.5514 -221.4249 -356.5733 -81.2733 191.8894 67.9691 -254.2772 -386.6988 -105.6435 196.7758 115.1822 -206.3854 -369.1040 -93.7500 188.6693 78.0865 -262.7747 -392.2518 -113.3712 178.1555 95.5295 -221.4425 -369.3152 -88.8798 189.5845 +-10230.1289 -9970.3467 -10088.0518 -10402.5586 -10533.4707 -10242.5498 -9978.5371 -10089.0049 -10397.4648 -10526.3750 -10238.4629 -9968.0664 -10090.7842 -10413.1406 -10535.1074 -10234.6758 -9965.6699 -10075.6084 -10401.3105 -10543.2393 -10252.2783 -9983.9111 -10095.8506 -10411.6709 -10538.8662 -10238.4697 -9977.5967 -10093.2861 -10412.9102 -10542.8447 -10243.2607 -9972.6309 -10091.3662 -10414.6777 -10545.3770 -10253.6084 -9984.5342 -10099.1680 -10411.4004 -10544.0986 -10249.3125 -9989.5098 -10104.2832 -10416.5449 -10535.0332 -10240.8340 -9987.4180 -10098.2129 -10416.7021 -10528.8760 -10238.3809 -9977.3398 -10091.2695 -10406.1758 -10537.7178 -10252.4434 -9992.3252 -10119.1230 -10431.7246 -10554.3359 -10262.4307 -9984.3643 -10096.2891 -10407.5732 -10539.4971 -10251.2100 -9990.1680 -10109.7109 -10442.7324 -10556.4844 -10262.0811 -9993.8477 -10099.4668 -10416.6836 -10544.6240 -10255.6426 -9990.8936 +-11545.8467 -11293.3496 -11405.1533 -11713.3223 -11840.8535 -11557.1221 -11301.1719 -11411.2500 -11708.2021 -11835.8574 -11556.0957 -11293.1816 -11409.4883 -11721.1748 -11841.0576 -11553.6982 -11292.0869 -11399.4932 -11715.6396 -11850.0742 -11567.2002 -11311.2607 -11416.8008 -11722.3125 -11846.1104 -11556.6758 -11304.0781 -11415.9609 -11724.2637 -11850.6953 -11561.5400 -11300.3623 -11412.1123 -11728.7686 -11853.6719 -11571.2510 -11311.4570 -11420.5713 -11723.9873 -11852.4355 -11565.6582 -11311.3936 -11423.6230 -11726.7490 -11843.7461 -11559.2109 -11310.7949 -11421.4600 -11729.6270 -11838.7764 -11555.7822 -11302.1230 -11412.4229 -11717.8926 -11845.4941 -11569.9395 -11318.8564 -11439.7852 -11741.7607 -11861.3428 -11576.4688 -11307.7148 -11418.7197 -11720.0518 -11848.3486 -11569.0889 -11315.4443 -11430.4697 -11754.1094 -11862.1387 -11578.7637 -11315.3232 -11419.9092 -11728.3604 -11853.7666 -11575.3633 -11317.0684 +-9428.1357 -9191.6260 -9298.1650 -9589.8428 -9707.5000 -9439.9648 -9201.2734 -9308.4355 -9591.9502 -9706.5498 -9440.8662 -9194.8066 -9305.1768 -9599.2969 -9707.7832 -9439.0244 -9196.1631 -9303.4375 -9599.7881 -9725.0303 -9452.7129 -9214.5195 -9318.1064 -9606.0469 -9718.7490 -9445.6182 -9211.5205 -9317.4326 -9609.3643 -9724.9316 -9451.1094 -9208.6943 -9316.9912 -9613.8457 -9728.2959 -9460.3174 -9219.0713 -9326.2725 -9611.5000 -9729.7998 -9454.9346 -9216.4756 -9325.7295 -9610.5518 -9717.8076 -9449.7266 -9217.2939 -9326.3301 -9616.7363 -9715.0020 -9446.9336 -9210.3086 -9316.9238 -9605.1260 -9723.1807 -9460.7979 -9227.1309 -9341.7637 -9625.3291 -9735.3496 -9462.3164 -9214.8682 -9323.4063 -9607.9941 -9723.3623 -9457.4717 -9222.1504 -9335.0078 -9634.5791 -9734.7725 -9462.7803 -9218.5879 -9322.7422 -9615.0947 -9730.7295 -9464.6748 -9222.7949 +-4754.1714 -4520.5615 -4619.9619 -4904.9067 -5021.9639 -4765.6523 -4531.3457 -4632.1558 -4908.8638 -5023.5405 -4767.1533 -4526.4282 -4628.6563 -4913.2813 -5024.0474 -4766.2090 -4528.0195 -4629.9048 -4919.5088 -5040.8232 -4779.9023 -4546.9380 -4642.1108 -4920.8311 -5031.9917 -4772.4844 -4541.3325 -4642.9517 -4926.9053 -5041.5552 -4778.1616 -4540.3809 -4642.6284 -4929.7852 -5041.9712 -4783.9482 -4548.8286 -4650.5894 -4928.3218 -5042.2705 -4777.7793 -4543.7139 -4647.0327 -4926.1934 -5033.0723 -4776.2466 -4548.6528 -4650.5190 -4931.7671 -5030.5840 -4772.5947 -4539.9253 -4640.3315 -4920.5718 -5038.0498 -4784.8179 -4555.8862 -4662.7080 -4938.2100 -5047.0254 -4785.0576 -4542.6841 -4647.0273 -4923.7505 -5039.1782 -4783.2563 -4552.9995 -4658.0137 -4947.8760 -5046.9873 -4785.1646 -4547.1240 -4646.1104 -4930.5967 -5047.4448 -4789.7881 -4551.6445 +-7913.7949 -7743.8931 -7830.7769 -8046.1494 -8125.2979 -7920.0938 -7751.1538 -7840.2339 -8050.8022 -8128.0879 -7924.1748 -7747.1577 -7837.9204 -8053.1621 -8127.0181 -7923.3472 -7753.0034 -7841.7070 -8061.3955 -8142.9551 -7932.9419 -7761.9561 -7847.5474 -8058.7119 -8131.2036 -7922.7275 -7759.3643 -7846.8330 -8063.7852 -8140.5552 -7930.9468 -7760.7749 -7848.4058 -8064.5752 -8138.2251 -7933.2148 -7761.3667 -7851.0166 -8062.8975 -8137.6914 -7927.8716 -7759.7485 -7849.8179 -8062.4316 -8132.6270 -7928.6631 -7763.6738 -7854.9561 -8066.8779 -8132.5454 -7926.7168 -7757.6426 -7846.5034 -8057.9067 -8138.2515 -7935.7734 -7769.6089 -7862.1499 -8070.7832 -8145.1465 -7934.8833 -7761.9341 -7853.1650 -8062.2881 -8139.2983 -7933.2192 -7767.0229 -7859.3755 -8075.3960 -8141.7104 -7933.1992 -7761.5405 -7851.6558 -8069.4824 -8146.5132 -7940.3140 -7764.0415 +-2985.3872 -2804.3240 -2879.6179 -3095.5950 -3184.1729 -2984.1189 -2805.2190 -2885.0256 -3100.1108 -3186.1750 -2989.0344 -2805.5662 -2884.2644 -3100.1912 -3185.4897 -2987.1060 -2808.2974 -2888.7693 -3108.6399 -3199.3547 -2998.0137 -2815.9744 -2894.1038 -3107.3918 -3189.1829 -2987.5500 -2814.8655 -2892.4678 -3112.1914 -3197.8147 -2995.8049 -2816.6541 -2892.4656 -3110.9211 -3194.3059 -2995.4609 -2815.1650 -2896.1672 -3110.7976 -3196.1616 -2994.7678 -2814.4187 -2894.7778 -3110.0376 -3192.5640 -2992.6372 -2815.7471 -2898.3643 -3112.8538 -3192.1521 -2990.9348 -2812.8740 -2891.1753 -3105.5256 -3193.3435 -2995.7151 -2820.7119 -2902.5652 -3115.8086 -3198.3875 -2997.7305 -2816.8918 -2895.5188 -3109.7424 -3193.1213 -2991.9854 -2815.1294 -2897.7075 -3115.3657 -3196.5254 -2992.9207 -2816.1750 -2894.5930 -3113.5581 -3198.7512 -2998.5557 -2815.4290 +-11987.9424 -11703.4482 -11806.6279 -12114.4102 -12270.0322 -11992.3906 -11720.1748 -11794.1953 -12109.9014 -12258.9395 -11985.4932 -11702.5225 -11797.6895 -12126.2148 -12264.1826 -11976.9092 -11693.8320 -11772.8408 -12102.0957 -12272.0313 -12007.7021 -11706.0596 -11794.3047 -12121.2217 -12272.4961 -11975.7715 -11693.6650 -11794.7988 -12109.4023 -12263.4473 -11989.8730 -11691.2686 -11785.3721 -12107.5859 -12270.6494 -12003.0605 -11715.2148 -11794.7490 -12106.5410 -12266.2842 -11990.7383 -11710.6006 -11799.9463 -12119.8389 -12258.2871 -11978.4102 -11704.0723 -11789.8691 -12118.2646 -12256.4980 -11981.7656 -11704.2246 -11789.8535 -12112.7578 -12251.1738 -11990.4453 -11713.6113 -11817.4609 -12125.1104 -12274.0967 -12007.0898 -11698.6787 -11779.8018 -12107.9912 -12257.5156 -11995.2168 -11711.5986 -11802.9102 -12142.8887 -12279.5811 -12010.0723 -11720.4004 -11790.0947 -12113.2119 -12276.6221 -12001.4268 -11714.3184 +-5564.3569 -5290.0073 -5407.2007 -5720.6440 -5866.3179 -5574.5537 -5300.4097 -5400.2646 -5713.3369 -5856.8252 -5570.3291 -5289.2822 -5398.2197 -5732.8804 -5862.0620 -5561.1709 -5279.1528 -5375.9316 -5711.8003 -5866.6216 -5583.2363 -5297.8350 -5400.4106 -5724.3301 -5865.4136 -5562.2837 -5284.2100 -5393.5498 -5716.5996 -5862.7778 -5571.4902 -5282.2383 -5390.4976 -5720.6948 -5869.3486 -5582.1973 -5301.1602 -5401.6875 -5719.2852 -5867.5610 -5575.6377 -5304.0181 -5409.4761 -5733.8516 -5863.5635 -5568.2573 -5300.0313 -5402.1167 -5728.3271 -5856.1538 -5567.8789 -5295.0996 -5400.2944 -5723.6646 -5858.9199 -5578.9136 -5304.7231 -5424.6113 -5743.4956 -5878.1597 -5594.1689 -5295.6284 -5401.6099 -5721.9644 -5864.1499 -5583.5605 -5305.0786 -5415.6348 -5758.8301 -5886.9043 -5599.0537 -5316.2793 -5406.7925 -5733.6689 -5882.8882 -5593.1924 -5311.1758 +-3306.2659 -3031.0859 -3132.2595 -3444.7495 -3596.4958 -3317.8506 -3039.6282 -3126.3320 -3440.5461 -3587.5178 -3313.6724 -3028.3936 -3128.0608 -3458.7913 -3595.2063 -3305.9385 -3023.2043 -3109.4175 -3441.1072 -3601.0046 -3326.7639 -3043.9326 -3131.6152 -3451.9902 -3600.7939 -3312.2634 -3033.3127 -3127.6855 -3449.4436 -3600.7214 -3319.2639 -3028.1472 -3124.2297 -3453.6604 -3606.1536 -3328.8777 -3043.8850 -3136.7700 -3452.5020 -3605.7114 -3324.1968 -3049.6094 -3143.9534 -3462.6057 -3600.4617 -3315.7090 -3046.8086 -3134.7698 -3458.1255 -3589.1069 -3313.7974 -3039.0508 -3129.1814 -3448.2996 -3595.7883 -3325.7659 -3048.9131 -3155.1550 -3472.3984 -3613.5977 -3339.3489 -3041.6414 -3133.9800 -3447.7930 -3599.1870 -3326.7896 -3046.8406 -3144.8318 -3484.3542 -3618.5542 -3341.1982 -3056.3359 -3136.7617 -3459.1724 -3608.7207 -3333.0171 -3051.5366 +-13901.7998 -13640.3193 -13755.6299 -14072.4727 -14206.4756 -13915.8486 -13648.3291 -13758.6377 -14068.8398 -14201.9150 -13914.8037 -13641.4707 -13759.7754 -14086.5615 -14209.9111 -13910.3184 -13637.3750 -13746.2041 -14075.8076 -14221.6904 -13929.8848 -13661.5957 -13769.7520 -14088.8887 -14219.2100 -13919.2070 -13654.9004 -13765.7314 -14089.5869 -14224.0762 -13925.8594 -13649.8018 -13764.2461 -14093.3516 -14228.8643 -13937.3018 -13664.5801 -13776.0225 -14091.7061 -14230.2422 -13932.1357 -13666.7344 -13780.1182 -14096.2891 -14219.0391 -13922.7725 -13665.4590 -13773.7676 -14095.6523 -14212.3682 -13921.2842 -13657.2725 -13767.1895 -14084.8086 -14218.6963 -13933.3105 -13669.4551 -13792.6602 -14105.3867 -14235.7939 -13943.3086 -13661.5088 -13773.7061 -14086.7676 -14220.4609 -13931.8613 -13666.8301 -13783.4600 -14119.2627 -14238.0840 -13944.6250 -13673.1396 -13774.4648 -14095.6357 -14228.2148 -13937.5361 -13668.1035 +-13153.9775 -12889.0127 -12993.6123 -13312.0225 -13451.2080 -13167.0674 -12894.7471 -12999.2520 -13310.7910 -13451.1221 -13170.5342 -12892.1973 -13000.2021 -13329.0811 -13459.1709 -13168.1445 -12888.4795 -12991.6602 -13324.1611 -13471.8955 -13186.1367 -12914.9600 -13014.0635 -13333.7822 -13469.9932 -13178.7832 -12910.0273 -13012.7227 -13336.6895 -13479.2949 -13184.6230 -12905.0146 -13009.3545 -13341.6025 -13480.6660 -13195.4160 -12918.7490 -13022.2881 -13338.6025 -13484.5742 -13190.7725 -12921.3516 -13025.1787 -13340.6094 -13471.4072 -13182.8320 -12918.2285 -13018.6250 -13341.9307 -13462.9912 -13178.7607 -12911.1055 -13011.5508 -13329.4570 -13470.9570 -13194.2578 -12922.6465 -13037.5303 -13352.8516 -13485.9258 -13198.1396 -12913.6670 -13018.6094 -13331.7959 -13472.3506 -13187.9795 -12916.0186 -13025.9160 -13361.5039 -13485.3447 -13196.8271 -12921.7158 -13017.2402 -13337.6123 -13477.5898 -13194.9990 -12920.0713 +-9723.1582 -9457.5322 -9539.6924 -9847.0654 -9992.3125 -9739.3779 -9468.1680 -9550.0352 -9849.1240 -9995.5508 -9741.5615 -9465.3867 -9550.8740 -9863.3008 -10000.2979 -9740.6221 -9465.5254 -9547.9619 -9865.0313 -10018.3047 -9757.3799 -9488.8271 -9566.7559 -9871.3799 -10014.6709 -9751.2451 -9485.6699 -9567.4434 -9874.5098 -10023.4365 -9758.0508 -9480.8291 -9566.6436 -9881.6113 -10028.0352 -9769.4697 -9495.0605 -9578.3076 -9880.8252 -10031.1318 -9764.9688 -9494.5156 -9578.3096 -9878.4756 -10015.6113 -9757.2393 -9492.9033 -9574.0117 -9880.5361 -10010.3799 -9752.1680 -9485.8096 -9565.4033 -9869.4668 -10020.1992 -9766.7480 -9500.4668 -9590.4004 -9888.2236 -10030.6445 -9767.4297 -9488.1953 -9571.5146 -9870.6475 -10017.3838 -9759.6074 -9493.0449 -9580.3838 -9898.8340 -10026.0889 -9767.0352 -9489.9111 -9568.5186 -9877.0508 -10023.1934 -9766.6689 -9492.7490 +-10332.1943 -10080.5801 -10177.4854 -10474.8877 -10604.2402 -10341.2246 -10092.2510 -10190.9648 -10480.8389 -10607.4746 -10345.6826 -10089.7676 -10190.1152 -10490.7646 -10609.9170 -10346.9326 -10090.8760 -10187.9180 -10495.3135 -10631.4521 -10361.3809 -10112.8994 -10206.0283 -10499.0566 -10622.7490 -10355.7070 -10110.3779 -10207.1006 -10506.2275 -10634.2871 -10362.4492 -10108.1289 -10206.6309 -10509.6123 -10635.0879 -10369.8398 -10115.8018 -10214.4814 -10508.4482 -10637.0928 -10364.7314 -10114.0049 -10213.7568 -10505.5254 -10625.2783 -10359.7314 -10115.3203 -10213.2393 -10509.6885 -10620.6777 -10354.6465 -10107.9980 -10204.6279 -10496.8486 -10628.4189 -10371.6680 -10121.4600 -10225.5869 -10515.2979 -10637.6982 -10369.1035 -10111.1816 -10209.7363 -10500.4639 -10628.8994 -10363.8613 -10114.5693 -10217.0762 -10521.1592 -10633.4092 -10366.9531 -10111.0977 -10207.7021 -10507.5469 -10633.9971 -10372.5039 -10115.4219 +-15432.2354 -15157.9248 -15234.9355 -15545.7695 -15698.0195 -15437.9902 -15162.1572 -15245.8037 -15552.1182 -15701.2900 -15445.7373 -15166.0293 -15251.8545 -15563.4063 -15704.8555 -15443.8818 -15165.8848 -15251.4297 -15570.4941 -15728.2744 -15465.3135 -15188.5020 -15265.1631 -15571.8535 -15716.7969 -15454.4385 -15185.5234 -15265.1172 -15579.5801 -15729.3457 -15461.6924 -15181.5283 -15260.8398 -15574.1230 -15724.1426 -15461.6045 -15185.1318 -15269.3154 -15575.1826 -15724.9053 -15459.2070 -15182.8301 -15265.5381 -15572.9922 -15713.6631 -15455.8887 -15185.2822 -15269.3076 -15576.3701 -15714.2773 -15452.0010 -15181.2148 -15261.5244 -15567.5244 -15718.4316 -15460.7813 -15189.9668 -15277.6768 -15578.9893 -15726.8906 -15462.1211 -15183.0996 -15262.8760 -15566.9805 -15716.1377 -15454.2012 -15184.5713 -15268.5156 -15582.2422 -15718.8145 -15452.7412 -15176.8330 -15258.5635 -15572.5791 -15722.7832 -15463.2656 -15180.5967 +-13015.6143 -12776.9834 -12867.0254 -13147.3721 -13268.0439 -13013.5322 -12775.5703 -12869.5879 -13150.0459 -13271.9912 -13024.6934 -12782.7861 -12876.7314 -13159.0205 -13275.2988 -13025.2021 -12785.2529 -12879.4395 -13167.0557 -13291.7197 -13037.9688 -12797.9238 -12889.5576 -13167.2891 -13280.5225 -13028.0352 -12797.8047 -12888.2783 -13174.6846 -13294.8477 -13035.3652 -12798.8555 -12887.0547 -13169.2119 -13288.9014 -13036.6787 -12797.4932 -12894.4980 -13171.8457 -13291.5615 -13034.8682 -12795.9795 -12888.5967 -13168.1064 -13286.1406 -13034.9023 -12798.3330 -12893.6309 -13171.6504 -13286.4521 -13032.8545 -12796.2090 -12888.6240 -13164.8408 -13283.1338 -13034.1279 -12798.7432 -12895.6328 -13172.8486 -13291.7090 -13038.3887 -12798.8242 -12889.2920 -13166.6895 -13285.0254 -13029.9580 -12795.8975 -12893.8525 -13176.5518 -13287.6162 -13030.0020 -12797.9541 -12891.1338 -13174.0771 -13293.6523 -13042.5605 -12797.9531 +-15251.2363 -14980.0352 -15080.6836 -15398.7490 -15544.9531 -15265.5967 -14987.2139 -15083.8789 -15397.7217 -15544.3301 -15268.2412 -14982.4414 -15085.4170 -15417.0898 -15552.0664 -15262.1885 -14977.2051 -15072.8418 -15406.8516 -15563.9961 -15283.1152 -15004.2031 -15097.9072 -15420.1035 -15563.8242 -15272.3633 -14997.1260 -15095.5498 -15420.6719 -15569.6895 -15279.3174 -14992.3574 -15092.2861 -15426.2100 -15574.6680 -15290.9814 -15006.0947 -15105.3418 -15424.9473 -15576.8027 -15285.6934 -15008.6934 -15108.3770 -15428.0859 -15562.8984 -15275.8389 -15007.1719 -15100.9492 -15428.4355 -15555.1455 -15273.9453 -14999.3369 -15093.0654 -15415.3203 -15559.8750 -15286.0078 -15008.7217 -15116.2627 -15435.6660 -15575.0029 -15292.7842 -15000.8574 -15101.4287 -15415.0020 -15562.3145 -15281.0820 -15004.1748 -15106.1758 -15447.0674 -15576.3223 -15293.1396 -15011.2256 -15098.7119 -15422.6836 -15565.1426 -15286.6035 -15006.6621 +-17225.5449 -16954.2402 -17048.1172 -17366.2813 -17516.2676 -17240.8945 -16959.6465 -17056.3105 -17375.0645 -17528.5605 -17254.4551 -16964.0820 -17064.8809 -17402.1680 -17537.7813 -17251.4961 -16962.4512 -17055.1660 -17396.9180 -17559.2402 -17276.6934 -16995.5137 -17087.0410 -17410.8398 -17558.9355 -17269.7480 -16991.3965 -17082.9609 -17415.2402 -17570.6836 -17282.4082 -16986.7754 -17084.3223 -17421.7500 -17575.9121 -17290.4922 -16999.8340 -17096.2480 -17419.8184 -17579.1016 -17284.6523 -17002.7129 -17098.9375 -17419.4863 -17560.3770 -17272.9238 -16999.3359 -17087.0996 -17419.2754 -17551.0898 -17270.5918 -16991.3086 -17079.7773 -17404.5078 -17554.3457 -17278.8457 -16994.9473 -17097.4648 -17419.9355 -17563.3594 -17278.0547 -16984.4512 -17080.6445 -17397.2305 -17548.9863 -17265.0254 -16983.7129 -17080.9336 -17426.5273 -17559.8711 -17277.8906 -16991.5859 -17076.3867 -17400.2773 -17542.7227 -17269.2930 -16989.0566 +-7012.3633 -6741.4341 -6838.8599 -7150.1948 -7304.1196 -7029.0742 -6747.3350 -6838.3916 -7150.2300 -7298.4478 -7028.0659 -6741.9048 -6838.8872 -7167.8657 -7306.8726 -7021.0664 -6733.9663 -6822.3936 -7156.5322 -7316.7397 -7041.4297 -6758.2046 -6847.9961 -7169.0850 -7316.4360 -7027.0649 -6749.4897 -6838.5225 -7164.7231 -7317.9629 -7034.4863 -6743.3584 -6837.3066 -7170.7915 -7323.1211 -7045.8242 -6757.7051 -6849.6738 -7169.7222 -7324.3467 -7039.3403 -6761.0186 -6855.4893 -7175.2104 -7314.6240 -7030.8589 -6762.6113 -6847.4736 -7172.6904 -7304.1274 -7028.9619 -6752.0669 -6841.5161 -7161.8291 -7310.6919 -7041.4761 -6762.2061 -6861.7383 -7182.6577 -7326.2036 -7050.0547 -6753.4688 -6849.5674 -7160.7339 -7313.8833 -7039.7280 -6757.7993 -6855.2988 -7197.1470 -7329.5088 -7050.8701 -6765.6133 -6847.1133 -7170.2778 -7318.6953 -7043.9551 -6760.5938 +-1838.4966 -1562.8992 -1673.4507 -1986.4330 -2137.7415 -1851.2427 -1571.3606 -1665.0458 -1980.8229 -2127.3655 -1845.3229 -1560.0002 -1663.6523 -1997.1984 -2133.9905 -1835.6796 -1550.6472 -1642.9330 -1980.5593 -2140.4697 -1857.8486 -1573.4619 -1669.8114 -1993.2134 -2136.5125 -1838.5391 -1559.5977 -1659.1960 -1981.7970 -2135.9136 -1845.8252 -1554.2683 -1655.7570 -1988.4973 -2144.1462 -1856.6744 -1572.4957 -1667.6443 -1987.3201 -2140.2471 -1848.8584 -1572.3949 -1670.9285 -1994.9985 -2132.3970 -1842.6320 -1573.2207 -1666.7578 -1993.2252 -2124.0747 -1839.6801 -1563.1394 -1662.4932 -1987.3228 -2127.5950 -1851.9950 -1573.6290 -1683.9041 -2007.2252 -2145.3608 -1866.2029 -1567.2343 -1670.3672 -1985.3702 -2134.3162 -1854.3082 -1571.6018 -1677.0906 -2020.3370 -2152.5869 -1867.5106 -1582.6508 -1669.7969 -1996.8256 -2148.0374 -1862.6575 -1576.6936 +-3356.3298 -3088.3748 -3214.6958 -3526.9492 -3667.5891 -3369.3486 -3098.4922 -3204.2727 -3518.7029 -3658.4451 -3366.2561 -3086.8550 -3202.3328 -3536.6519 -3661.4746 -3350.2598 -3075.0168 -3177.2585 -3516.7173 -3665.9602 -3374.2664 -3092.2051 -3204.0103 -3529.3464 -3662.0156 -3351.2866 -3077.9705 -3192.4492 -3513.5923 -3658.6687 -3357.1213 -3074.1206 -3189.2195 -3521.7556 -3665.5962 -3370.1575 -3093.8625 -3199.6941 -3520.0071 -3664.9231 -3361.1123 -3090.4932 -3203.5002 -3528.8733 -3656.1316 -3355.1106 -3091.9329 -3199.4333 -3527.5906 -3648.1807 -3352.9478 -3083.6560 -3195.1990 -3521.1638 -3649.9771 -3363.8076 -3094.6348 -3218.3252 -3536.9250 -3669.7446 -3379.4104 -3086.7058 -3203.4573 -3520.0559 -3656.7649 -3369.3191 -3093.9189 -3210.3689 -3555.3523 -3676.3301 -3382.4443 -3105.3416 -3202.8169 -3531.6287 -3679.3330 -3378.5354 -3098.2815 +-12513.0947 -12253.9248 -12374.8447 -12695.6045 -12830.5088 -12526.6641 -12258.3799 -12380.6934 -12705.2861 -12840.9219 -12539.7119 -12260.5918 -12388.9678 -12731.2822 -12851.2637 -12536.0947 -12255.5322 -12376.9863 -12725.3320 -12873.7207 -12563.5439 -12289.9414 -12411.2148 -12742.3760 -12871.8301 -12552.3613 -12284.0723 -12399.9414 -12743.0195 -12881.6162 -12567.2070 -12280.5361 -12403.5762 -12750.0313 -12886.1035 -12571.8086 -12292.2070 -12417.7900 -12748.6191 -12889.8154 -12568.2705 -12294.8965 -12419.6895 -12748.2734 -12871.8457 -12556.5771 -12293.8154 -12409.0137 -12745.4307 -12860.5186 -12551.8154 -12282.4971 -12398.9961 -12729.3730 -12863.3916 -12561.1084 -12284.9707 -12415.4980 -12748.6377 -12872.2041 -12562.0723 -12279.8965 -12405.3193 -12728.0449 -12864.5459 -12550.8828 -12277.1445 -12403.5586 -12755.0635 -12869.5898 -12561.1719 -12285.1641 -12400.4189 -12729.7344 -12842.4980 -12548.6289 -12285.6377 +-7603.6021 -7268.0771 -7254.0361 -7565.1494 -7802.5845 -7615.7876 -7272.2437 -7252.9146 -7566.7739 -7797.8516 -7615.7046 -7264.2710 -7252.5674 -7583.9287 -7804.7251 -7607.5259 -7260.9785 -7236.7949 -7572.6626 -7817.3857 -7630.7954 -7284.3984 -7264.0703 -7584.8989 -7817.3804 -7616.5273 -7276.3086 -7253.4053 -7580.8228 -7821.5083 -7625.8198 -7267.8525 -7253.4751 -7587.3115 -7824.4331 -7633.4951 -7280.7988 -7265.4458 -7585.9009 -7826.5913 -7626.7051 -7285.1055 -7267.0503 -7589.6411 -7815.7544 -7618.8896 -7286.3765 -7260.6279 -7587.4336 -7802.5586 -7612.7300 -7273.2866 -7251.6250 -7572.1392 -7805.7925 -7626.7651 -7277.2788 -7266.7554 -7594.2808 -7818.8506 -7629.4419 -7271.6973 -7256.2529 -7570.1279 -7809.2183 -7621.0454 -7275.9453 -7258.9028 -7603.3711 -7824.7998 -7633.4434 -7280.8110 -7254.7720 -7578.8862 -7807.8037 -7623.9604 -7278.4160 +-4723.2002 -4442.7031 -4507.9492 -4804.1973 -4980.8350 -4738.2051 -4446.0176 -4502.3521 -4803.0366 -4971.9614 -4734.8491 -4441.4771 -4503.3218 -4820.1187 -4978.4580 -4725.4014 -4431.4390 -4482.1875 -4807.1118 -4989.1265 -4748.3042 -4454.9854 -4511.9209 -4820.4614 -4987.4102 -4729.8560 -4445.2788 -4497.2749 -4810.3174 -4986.2876 -4736.6187 -4435.5918 -4493.8027 -4815.5059 -4990.1465 -4744.1299 -4452.2485 -4505.2891 -4816.1504 -4990.3882 -4739.9072 -4451.7437 -4510.0366 -4820.8882 -4982.7144 -4732.2915 -4460.1714 -4504.8721 -4817.7402 -4971.3691 -4727.8188 -4443.8633 -4498.9102 -4809.3486 -4976.3716 -4742.1079 -4452.9131 -4516.6929 -4830.9341 -4991.1094 -4749.2275 -4448.9199 -4507.8438 -4807.9663 -4979.6221 -4740.6943 -4452.7954 -4510.8691 -4841.1519 -4997.9795 -4753.9795 -4460.3452 -4504.4595 -4817.7739 -4989.3174 -4749.1123 -4454.9692 +-5796.1128 -5507.0278 -5588.4897 -5895.3740 -6069.9248 -5808.1592 -5514.4121 -5577.9873 -5891.0649 -6061.2773 -5805.9058 -5504.7378 -5577.8232 -5908.3755 -6064.4805 -5792.4629 -5494.7271 -5555.5981 -5890.6147 -6070.9204 -5815.4580 -5516.1001 -5582.6729 -5904.2236 -6068.7437 -5794.9287 -5501.9404 -5568.0498 -5888.0249 -6065.2910 -5802.5527 -5496.2871 -5566.6304 -5896.9487 -6072.2295 -5812.8770 -5514.2725 -5578.1143 -5894.0591 -6069.2295 -5802.4819 -5512.1479 -5581.9351 -5901.9136 -6065.9849 -5798.9751 -5517.5864 -5576.9946 -5899.9751 -6052.9868 -5796.8569 -5505.2842 -5572.5049 -5894.3945 -6057.3643 -5808.0332 -5515.5059 -5593.7876 -5913.9458 -6072.0435 -5819.1953 -5509.7075 -5581.0527 -5891.9365 -6062.1011 -5809.0664 -5512.5723 -5583.4937 -5926.9287 -6079.3076 -5823.2969 -5522.9575 -5578.5151 -5903.5229 -6077.5020 -5818.9185 -5519.0210 +99.6962 373.8423 274.4015 -47.0488 -199.0228 88.0458 374.6539 273.9691 -53.3486 -205.0553 79.3717 376.3204 270.3489 -75.1069 -210.8066 86.5566 385.2838 286.0577 -63.6760 -232.6548 65.3966 355.1806 254.2427 -76.5114 -227.0457 76.7532 362.8314 270.5007 -75.8623 -230.8237 66.5637 371.3092 268.6814 -81.3633 -237.4848 63.1013 359.2781 254.4684 -78.9946 -241.7349 67.2510 356.2067 253.5647 -79.3560 -223.3422 79.0849 358.2546 261.8454 -75.7036 -211.3333 79.7470 364.3486 271.7635 -63.6166 -216.4476 72.1205 363.7741 255.1871 -82.7059 -226.4431 69.8396 364.6534 262.1592 -63.9921 -219.9018 79.5343 369.2884 265.1851 -93.6672 -226.6457 68.9901 360.5679 266.5929 -67.0605 -191.7936 76.0032 350.6770 +1023.5961 1291.0488 1182.6500 867.6858 720.3473 1009.7223 1289.2323 1184.4648 866.1928 722.6398 1007.2182 1294.6504 1183.1134 848.3550 717.1947 1018.2546 1303.2689 1203.2712 862.5685 705.1392 998.4647 1279.6831 1173.9669 849.3887 707.0538 1012.6962 1287.6886 1188.5122 857.1715 704.6126 1004.7588 1296.5753 1189.9382 849.8392 700.2349 998.5245 1284.1328 1175.4637 851.1307 700.2017 1004.3207 1284.6488 1174.3668 848.4126 712.4672 1013.8741 1276.9531 1180.9890 853.7103 727.2169 1018.2604 1292.6650 1193.2030 863.9989 721.1120 1008.6674 1287.0306 1174.4835 843.2459 711.1992 1004.7181 1291.7836 1184.3009 868.0236 720.6645 1015.5170 1293.0469 1185.1144 834.9103 710.2806 1003.0368 1284.3876 1187.7045 860.1678 728.1458 1006.8369 1286.5090 +-2065.5994 -1790.2935 -1898.6405 -2212.0220 -2367.0374 -2079.5886 -1792.9523 -1893.3727 -2212.2102 -2358.9753 -2076.9456 -1787.1588 -1890.6694 -2226.6450 -2362.6089 -2065.3401 -1777.3805 -1870.2002 -2212.5381 -2372.7363 -2085.7590 -1800.8716 -1898.7546 -2224.9194 -2370.9683 -2067.3276 -1791.5040 -1883.5654 -2213.2417 -2369.2915 -2074.6289 -1779.7966 -1880.1921 -2220.3958 -2373.3828 -2083.6428 -1793.5460 -1895.8054 -2218.5522 -2375.4954 -2076.8499 -1795.5492 -1899.5911 -2227.1245 -2367.2642 -2070.5095 -1808.9081 -1895.0461 -2220.4739 -2353.0896 -2066.1248 -1789.7982 -1887.0049 -2216.1221 -2359.8010 -2078.6343 -1797.7578 -1905.7084 -2237.6826 -2372.7983 -2088.5227 -1792.3751 -1897.4409 -2211.1367 -2366.6213 -2079.7188 -1798.2378 -1899.2036 -2249.9805 -2381.3594 -2092.8135 -1804.1239 -1894.8585 -2224.8450 -2371.0081 -2087.4316 -1801.8413 +-8366.8555 -8091.9556 -8203.6055 -8515.2168 -8669.9990 -8381.5566 -8097.0010 -8196.3799 -8512.6406 -8661.1270 -8378.7061 -8089.8345 -8194.4297 -8527.5107 -8666.5059 -8365.9600 -8077.5669 -8168.0366 -8511.7129 -8670.7012 -8384.2246 -8098.6450 -8198.5537 -8521.8965 -8666.7539 -8364.5791 -8084.8872 -8178.7549 -8506.7852 -8662.9932 -8369.6064 -8077.2129 -8178.9800 -8516.5430 -8671.4521 -8380.9072 -8094.7544 -8191.1406 -8515.1426 -8671.6074 -8374.3008 -8094.7798 -8197.4766 -8521.2012 -8663.2490 -8367.9346 -8104.4360 -8193.3770 -8520.5078 -8654.2520 -8368.4473 -8088.1719 -8188.5635 -8516.2783 -8660.2178 -8381.4961 -8100.9766 -8209.2539 -8535.2148 -8671.4873 -8389.1289 -8093.2275 -8196.1025 -8507.2578 -8661.7051 -8379.1738 -8097.0933 -8197.1016 -8548.2129 -8680.5332 -8391.5732 -8105.0181 -8191.1279 -8524.4453 -8673.6768 -8388.7070 -8099.7227 +-4373.7754 -4107.0952 -4221.8955 -4539.4194 -4677.9048 -4375.9570 -4098.3579 -4214.0151 -4536.3813 -4676.7271 -4379.7661 -4090.3567 -4205.3809 -4547.7690 -4674.2100 -4363.0854 -4074.1309 -4186.2827 -4529.6206 -4689.3394 -4377.2930 -4099.5410 -4212.8584 -4539.2939 -4677.8374 -4361.2100 -4086.0840 -4188.9600 -4530.4746 -4673.2012 -4366.2603 -4072.8533 -4187.2983 -4534.1533 -4679.8667 -4367.7173 -4082.6335 -4198.2119 -4528.5103 -4681.6929 -4362.5615 -4088.2893 -4207.2759 -4535.0298 -4668.4585 -4357.7061 -4090.2329 -4200.9536 -4535.5015 -4659.3696 -4359.5576 -4084.9309 -4189.5054 -4524.4155 -4663.6953 -4367.6060 -4085.9199 -4207.0518 -4544.0557 -4675.7134 -4369.9297 -4085.9797 -4205.4258 -4526.3042 -4668.6899 -4364.2329 -4086.1843 -4201.7661 -4558.9810 -4678.1221 -4376.0522 -4096.2144 -4200.8164 -4536.3994 -4659.9946 -4385.3164 -4097.4629 +-1928.2401 -1659.7429 -1755.4979 -2059.5720 -2215.1345 -1940.8970 -1656.8514 -1744.8210 -2057.7837 -2209.1362 -1937.7727 -1649.1475 -1741.2079 -2071.0083 -2212.6003 -1925.7214 -1636.9044 -1721.3500 -2054.6636 -2221.4565 -1942.2496 -1661.1349 -1749.6833 -2066.8416 -2217.7261 -1926.1359 -1650.0636 -1729.2565 -2055.5542 -2209.3503 -1931.2045 -1637.6799 -1728.4897 -2062.3286 -2219.7498 -1938.9896 -1653.1698 -1744.1272 -2059.0334 -2221.8237 -1931.9827 -1654.2959 -1748.3414 -2064.3784 -2211.4763 -1926.1901 -1665.5397 -1742.1798 -2062.9814 -2195.7993 -1922.4725 -1644.3660 -1731.3840 -2053.7354 -2204.6338 -1934.0697 -1649.8037 -1746.3745 -2073.0586 -2211.4160 -1937.1699 -1650.3274 -1742.6094 -2050.2766 -2208.8425 -1930.3881 -1651.9447 -1740.2354 -2086.5833 -2219.9668 -1943.3230 -1658.7422 -1737.1293 -2062.9683 -2210.2534 -1943.4208 -1657.7159 +-5609.3428 -5340.2402 -5445.9189 -5754.6201 -5908.1855 -5626.6660 -5342.8667 -5438.5430 -5753.5347 -5898.6660 -5620.7734 -5335.6011 -5435.0361 -5764.0122 -5902.8906 -5608.5000 -5324.2100 -5412.7705 -5748.0254 -5910.0078 -5626.7383 -5346.6343 -5442.7939 -5762.3735 -5906.2764 -5608.1782 -5337.9907 -5423.4395 -5750.3516 -5900.2207 -5614.6367 -5324.4238 -5420.6738 -5755.6763 -5908.0259 -5624.4761 -5339.2188 -5435.2905 -5753.2686 -5910.8198 -5617.1167 -5339.8145 -5440.8315 -5760.5591 -5900.7407 -5610.1460 -5356.2661 -5436.8135 -5754.8057 -5887.6885 -5608.3364 -5333.2231 -5426.4839 -5749.9292 -5893.9795 -5619.3208 -5340.8823 -5444.7041 -5770.2456 -5903.8398 -5622.8120 -5336.4468 -5436.3618 -5744.0513 -5897.8340 -5616.3335 -5337.9390 -5434.5293 -5781.4858 -5912.0186 -5629.4443 -5346.8843 -5431.7334 -5757.7075 -5903.7544 -5626.2510 -5342.5425 +-5090.6177 -4822.4150 -4921.4932 -5216.4907 -5370.7954 -5086.8613 -4809.6782 -4906.7588 -5223.1997 -5364.3154 -5084.5571 -4800.5532 -4891.6641 -5216.3970 -5375.4526 -5074.4194 -4800.5845 -4875.7661 -5206.4941 -5366.3589 -5078.4414 -4802.5605 -4894.4434 -5205.6372 -5365.9556 -5070.9780 -4790.9038 -4866.7720 -5194.8989 -5336.8867 -5069.1440 -4772.9468 -4875.2549 -5196.3247 -5358.2290 -5077.8218 -4788.8672 -4884.0654 -5199.2627 -5361.2681 -5058.9668 -4793.1890 -4897.2031 -5208.3931 -5352.0786 -5066.3579 -4800.2363 -4876.4556 -5206.9429 -5344.7163 -5060.0361 -4788.3647 -4880.4395 -5209.7896 -5354.6855 -5071.3721 -4790.1050 -4886.8540 -5215.8301 -5350.2603 -5075.9741 -4792.8955 -4897.4912 -5216.2437 -5353.3940 -5071.4956 -4795.7925 -4890.0493 -5237.6216 -5354.0039 -5084.7368 -4794.8647 -4883.7612 -5205.6328 -5367.0078 -5088.3647 -4807.4399 +-9741.7354 -9466.2041 -9573.3584 -9879.0840 -10021.7578 -9731.4365 -9457.4756 -9565.2568 -9880.2598 -10023.2070 -9734.2188 -9451.6143 -9543.0537 -9875.0234 -10017.8291 -9723.0215 -9439.7246 -9534.1543 -9864.3965 -10023.5898 -9728.0508 -9449.7959 -9549.2510 -9865.2803 -10020.2852 -9720.5547 -9435.8369 -9524.2422 -9852.4404 -9990.8701 -9703.4580 -9435.1865 -9532.9639 -9858.6982 -10016.3809 -9726.3779 -9439.1143 -9534.5029 -9856.7070 -10017.5303 -9712.7119 -9441.0576 -9552.3174 -9874.4697 -10007.5127 -9716.1230 -9447.0381 -9532.7461 -9861.4277 -9994.5752 -9709.6631 -9440.7520 -9542.0098 -9869.6787 -10006.9316 -9721.8369 -9438.5293 -9544.2529 -9871.3682 -10010.9961 -9726.5254 -9447.9746 -9555.6787 -9873.2598 -10009.9404 -9720.8145 -9447.1914 -9551.8691 -9899.0352 -10013.5635 -9734.1484 -9452.7002 -9545.6865 -9878.6201 -10025.3369 -9740.7383 -9455.8330 +-10360.9014 -10090.3125 -10209.6709 -10523.5283 -10651.8994 -10348.0117 -10079.9707 -10202.0244 -10517.4580 -10651.9912 -10356.5703 -10073.8174 -10177.4160 -10513.4785 -10648.3379 -10343.4570 -10068.6836 -10173.3135 -10500.0947 -10650.0723 -10344.9990 -10074.4414 -10186.5596 -10504.5830 -10650.8174 -10345.6172 -10065.5527 -10159.6299 -10488.9111 -10619.7148 -10326.6973 -10063.9131 -10169.3301 -10499.0713 -10649.8926 -10350.4844 -10068.1016 -10173.0752 -10495.4395 -10653.3174 -10336.3457 -10064.1074 -10190.0664 -10511.4893 -10638.3779 -10336.7773 -10074.7490 -10173.1875 -10499.5693 -10626.7031 -10335.1182 -10066.8066 -10175.0215 -10504.5879 -10634.8047 -10345.6338 -10066.3066 -10184.5186 -10507.2979 -10641.7754 -10350.5879 -10081.2988 -10194.7627 -10508.5566 -10638.1045 -10344.6465 -10073.2676 -10188.9033 -10535.7119 -10645.9648 -10350.2559 -10081.8535 -10187.8398 -10515.4170 -10652.9307 -10360.6328 -10080.1631 +-5463.9131 -5164.2236 -5261.7041 -5560.1270 -5720.9263 -5441.6426 -5164.7632 -5259.1646 -5577.6729 -5721.8877 -5446.1621 -5175.3843 -5236.5098 -5554.3423 -5704.4463 -5419.1919 -5141.1709 -5227.2666 -5553.3521 -5728.4648 -5443.5532 -5137.4761 -5234.9746 -5555.3384 -5714.6553 -5412.1509 -5118.5898 -5209.1982 -5534.0215 -5679.9019 -5396.5044 -5137.5532 -5227.6665 -5533.8999 -5708.0112 -5416.0762 -5121.5049 -5212.8403 -5536.6851 -5703.2139 -5404.6465 -5129.2568 -5237.2148 -5569.4121 -5708.4824 -5419.6133 -5130.5176 -5208.2700 -5543.2002 -5683.4722 -5400.3677 -5134.3027 -5230.5000 -5575.2891 -5705.5674 -5419.5562 -5121.9829 -5218.7271 -5558.3052 -5699.7109 -5420.1851 -5138.8643 -5241.8413 -5576.1064 -5710.7349 -5408.3740 -5137.5264 -5242.7466 -5580.1670 -5695.2798 -5436.8633 -5144.4102 -5228.0376 -5569.1152 -5727.5854 -5431.3125 -5146.5620 +-4847.2295 -4564.3970 -4666.3325 -4973.9028 -5120.4561 -4831.2041 -4555.2148 -4661.9609 -4980.9121 -5126.0049 -4839.2666 -4555.4727 -4638.7896 -4971.2212 -5110.9375 -4821.4536 -4541.3389 -4630.6699 -4957.7734 -5121.0825 -4833.2026 -4545.8354 -4645.0513 -4961.7271 -5116.6860 -4819.5356 -4528.7852 -4617.9111 -4942.6006 -5084.9395 -4796.3472 -4536.9595 -4633.4766 -4948.6753 -5114.4312 -4827.4556 -4534.5020 -4624.8125 -4944.2949 -5109.3149 -4814.2031 -4543.6914 -4649.0342 -4971.2510 -5105.0605 -4819.0566 -4543.0967 -4625.4189 -4952.2871 -5093.5962 -4805.3994 -4537.3491 -4638.8862 -4967.0322 -5109.9917 -4819.8311 -4530.3359 -4634.0283 -4966.4141 -5108.3291 -4820.2393 -4546.5659 -4650.2139 -4974.1729 -5112.5605 -4818.8384 -4544.9009 -4649.6440 -4992.1240 -5105.3638 -4831.8188 -4545.2715 -4636.8579 -4975.0557 -5120.3530 -4836.0938 -4551.1094 +-13890.6855 -13615.5723 -13729.6104 -14043.5352 -14176.6855 -13877.8018 -13605.8418 -13722.2627 -14040.7910 -14178.8477 -13882.6172 -13599.3682 -13696.7734 -14034.2549 -14169.4043 -13872.4375 -13593.4014 -13691.1211 -14021.3711 -14173.2803 -13875.6250 -13599.1777 -13702.9492 -14020.7686 -14172.2432 -13870.1846 -13583.3457 -13677.3838 -14003.3848 -14141.3779 -13847.4316 -13585.0166 -13688.8447 -14012.1553 -14168.8027 -13875.0654 -13590.7529 -13686.6377 -14005.0137 -14165.6279 -13860.6934 -13594.8965 -13707.4482 -14026.5908 -14153.7305 -13858.1465 -13594.7744 -13687.0078 -14013.9131 -14148.3467 -13855.3740 -13588.3936 -13693.7441 -14020.6484 -14156.8252 -13864.6982 -13582.4121 -13695.7227 -14024.7861 -14158.7070 -13866.3604 -13596.5078 -13708.1348 -14028.1855 -14160.9053 -13867.0039 -13591.4502 -13704.1631 -14046.1250 -14157.9648 -13872.1621 -13593.8252 -13695.3281 -14030.0801 -14168.4492 -13881.7988 -13599.4492 +-12531.1973 -12261.2549 -12375.7334 -12692.9551 -12818.8945 -12525.8438 -12253.0020 -12369.7617 -12683.3516 -12820.1973 -12529.7246 -12245.2676 -12343.7314 -12676.0010 -12811.8750 -12518.2305 -12238.4336 -12340.5410 -12667.0420 -12820.1348 -12525.2588 -12251.6934 -12349.9258 -12668.7246 -12819.0381 -12520.0332 -12234.2617 -12326.6240 -12652.3594 -12794.8662 -12502.6064 -12237.5986 -12338.5352 -12662.2832 -12819.6309 -12524.3457 -12242.9619 -12337.7031 -12654.7607 -12817.2891 -12512.5439 -12246.2832 -12356.1182 -12674.7627 -12803.4688 -12509.1973 -12245.2627 -12337.5576 -12663.4902 -12796.3125 -12506.2207 -12235.1113 -12341.5586 -12668.3271 -12804.5850 -12517.2383 -12235.7891 -12348.8613 -12673.9150 -12806.4160 -12521.7031 -12251.8301 -12361.1895 -12680.7568 -12807.9707 -12519.9014 -12243.9463 -12354.7607 -12695.7744 -12809.3770 -12524.0244 -12250.0664 -12349.6719 -12682.1445 -12818.9521 -12533.7031 -12252.1689 +-6565.1040 -6261.7261 -6321.3867 -6619.5708 -6794.1719 -6541.5723 -6255.8960 -6330.6494 -6634.8682 -6799.8008 -6554.2568 -6263.5518 -6294.1128 -6611.2686 -6776.8618 -6520.0361 -6233.9199 -6287.4229 -6600.8198 -6795.4956 -6541.2969 -6234.1216 -6299.1553 -6609.6816 -6781.9946 -6518.2480 -6214.5156 -6273.6675 -6581.4272 -6746.4082 -6490.6172 -6236.2866 -6294.0679 -6587.6665 -6777.5796 -6523.7056 -6223.0215 -6271.4204 -6581.0244 -6765.7363 -6514.5938 -6230.8911 -6302.7324 -6627.0464 -6771.9434 -6524.2676 -6231.4385 -6274.4185 -6590.1675 -6756.1387 -6504.6597 -6227.0532 -6298.9141 -6620.8223 -6782.9058 -6525.5269 -6214.2925 -6283.6255 -6615.8770 -6772.5986 -6519.1865 -6236.1929 -6304.3540 -6623.8135 -6776.1655 -6511.4980 -6234.3364 -6310.0269 -6633.3369 -6770.5054 -6540.7798 -6230.1265 -6287.7134 -6631.2397 -6792.1074 -6534.2407 -6243.9844 +-6640.0044 -6363.5518 -6460.7896 -6767.8564 -6912.0166 -6624.2124 -6346.7754 -6456.3477 -6776.2305 -6918.3145 -6630.5962 -6345.8281 -6429.6650 -6766.0142 -6901.7329 -6614.7217 -6334.1553 -6422.2969 -6747.0972 -6905.0703 -6622.4600 -6339.4028 -6433.1631 -6752.4360 -6908.4331 -6616.4272 -6321.9717 -6410.0557 -6728.9561 -6874.4087 -6585.4248 -6325.7402 -6423.6626 -6737.9478 -6902.8848 -6618.6445 -6332.0474 -6415.9614 -6731.5405 -6892.3467 -6608.6416 -6339.7344 -6440.5181 -6759.0986 -6886.7368 -6605.4609 -6337.0278 -6420.1792 -6742.8838 -6886.0757 -6599.7026 -6331.3535 -6432.5615 -6753.7090 -6900.0405 -6611.9395 -6325.0679 -6426.6899 -6754.8472 -6896.2627 -6609.8008 -6340.4492 -6445.3032 -6764.7744 -6902.3018 -6614.6519 -6339.5669 -6442.3682 -6782.1226 -6898.5049 -6623.6543 -6333.0098 -6431.7710 -6765.8120 -6910.3696 -6632.3813 -6349.3740 +-10391.1201 -10113.5752 -10188.2090 -10488.1494 -10639.6025 -10380.7822 -10100.1309 -10180.9941 -10493.1777 -10651.7207 -10389.3457 -10097.3877 -10155.1328 -10480.7012 -10636.4854 -10381.3125 -10086.1904 -10151.5439 -10469.4131 -10640.2998 -10382.9492 -10099.3926 -10163.1025 -10470.8066 -10645.8818 -10385.3359 -10081.6563 -10138.9443 -10449.0752 -10615.5469 -10356.0684 -10082.2949 -10152.0762 -10460.5830 -10641.8389 -10384.9316 -10091.9785 -10146.2012 -10451.0898 -10632.9834 -10373.0957 -10104.3174 -10173.5029 -10478.7656 -10625.1436 -10364.2744 -10093.2285 -10147.1709 -10465.7285 -10624.4775 -10366.2324 -10087.6592 -10158.8066 -10471.8330 -10631.5186 -10371.1289 -10080.3223 -10157.1611 -10478.0107 -10628.5830 -10374.8818 -10098.0508 -10176.1660 -10487.4033 -10638.1807 -10378.7363 -10096.7256 -10169.6865 -10501.1719 -10635.2568 -10383.0889 -10091.7061 -10160.9688 -10487.8105 -10645.1084 -10398.4111 -10107.6865 +-7354.9702 -7071.7832 -7160.1147 -7474.0605 -7612.6597 -7342.6660 -7062.8247 -7160.0576 -7478.1440 -7628.2803 -7354.7817 -7059.5425 -7130.3638 -7460.3364 -7613.0898 -7343.0269 -7049.2119 -7126.7617 -7453.5229 -7619.2671 -7348.2524 -7065.2725 -7141.5303 -7459.3013 -7626.9180 -7350.4771 -7043.0752 -7113.2637 -7434.0688 -7596.2524 -7321.3813 -7041.7759 -7126.5337 -7445.4219 -7622.1855 -7349.7280 -7058.7217 -7124.8599 -7439.4873 -7619.7866 -7344.9097 -7073.0986 -7153.0645 -7463.1792 -7601.4072 -7329.8442 -7056.5820 -7121.9292 -7452.5049 -7608.0596 -7335.3296 -7051.5708 -7136.1670 -7458.6553 -7612.1597 -7337.0962 -7041.3569 -7136.7954 -7460.7856 -7604.7686 -7336.3735 -7059.2920 -7153.0786 -7475.3174 -7618.9375 -7346.6177 -7061.1030 -7150.4639 -7485.4165 -7614.4546 -7350.1089 -7055.8301 -7131.4785 -7467.6221 -7618.9297 -7359.1211 -7063.8315 +-4862.7764 -4613.0269 -4714.5220 -5019.7324 -5151.4697 -4858.6563 -4581.2617 -4701.1880 -5021.5112 -5149.8516 -4849.8447 -4562.7666 -4680.5435 -5022.2261 -5144.4683 -4843.3086 -4561.4766 -4665.8472 -4989.6577 -5133.2485 -4831.3179 -4569.3765 -4681.7666 -5002.5337 -5147.1514 -4844.1353 -4549.8081 -4653.3286 -4969.3652 -5102.2168 -4796.8657 -4540.2324 -4672.4365 -4983.4287 -5129.2373 -4832.2061 -4563.1689 -4656.8071 -4975.6182 -5120.5781 -4834.2217 -4571.9780 -4688.6621 -5000.1538 -5117.1924 -4825.9902 -4566.0054 -4672.3545 -4990.0498 -5124.5522 -4828.3135 -4564.5327 -4680.8120 -4990.7241 -5140.0322 -4834.0781 -4553.8071 -4669.0771 -4996.8052 -5136.7710 -4836.2559 -4566.3926 -4687.5630 -4998.8584 -5130.6992 -4836.9258 -4563.9883 -4686.9854 -5028.3359 -5138.6040 -4852.0435 -4557.0298 -4677.2935 -5007.8726 -5131.1362 -4856.1426 -4583.1924 +-380.7783 -127.8448 -242.5484 -541.7405 -666.8411 -372.2576 -99.2402 -222.6502 -544.3165 -675.0734 -371.7869 -98.2827 -210.5633 -542.8483 -665.7859 -364.6625 -88.9668 -193.4529 -515.9946 -660.2251 -365.8444 -94.5679 -201.8795 -525.3510 -671.5419 -377.1725 -84.8560 -188.6032 -497.9098 -634.0905 -332.8897 -76.9852 -194.3027 -507.7216 -663.2867 -364.9129 -94.0360 -191.1611 -513.3672 -649.1671 -362.6311 -105.1339 -223.9430 -535.6072 -643.0663 -349.0943 -88.4632 -198.7111 -527.9015 -656.7940 -359.5703 -100.0672 -218.8911 -528.1619 -662.3619 -359.1836 -84.9235 -200.9732 -525.7366 -657.5853 -353.9064 -104.4479 -231.2924 -545.9832 -663.8690 -364.8214 -99.9141 -220.4171 -555.5125 -662.9222 -377.2341 -89.4126 -213.2444 -542.6424 -664.8287 -386.9807 -115.8937 +-6240.7769 -5970.2344 -6060.9658 -6364.3101 -6503.2856 -6223.6162 -5946.2114 -6051.5254 -6373.1333 -6518.3882 -6235.7690 -5951.7744 -6028.9404 -6360.1226 -6503.2490 -6228.2690 -5941.3760 -6025.2778 -6346.5820 -6504.7695 -6226.3965 -5947.7764 -6034.0630 -6352.6533 -6518.2124 -6237.3140 -5936.4038 -6016.9302 -6329.6260 -6482.9829 -6203.7788 -5937.5308 -6031.9341 -6342.7085 -6513.2690 -6232.4458 -5948.7690 -6023.8726 -6338.6895 -6500.0361 -6226.0786 -5963.1147 -6051.0640 -6361.0898 -6491.1294 -6214.0273 -5947.4688 -6026.8013 -6349.7886 -6496.2593 -6215.5020 -5946.7681 -6039.9434 -6356.2183 -6501.9976 -6217.9756 -5930.7598 -6028.6592 -6352.7646 -6494.9365 -6216.1323 -5954.6865 -6053.0015 -6369.6226 -6509.8857 -6225.8594 -5951.3271 -6045.8306 -6380.6055 -6500.2217 -6229.8403 -5940.1001 -6036.9868 -6368.9443 -6510.1724 -6247.5439 -5962.4683 +2682.5195 2941.2305 2819.7190 2510.5088 2395.6262 2696.4570 2962.4712 2823.4385 2496.4849 2368.5659 2676.3276 2952.6399 2851.3582 2517.7622 2390.8289 2686.7073 2967.3701 2854.5005 2529.3882 2387.7314 2689.0015 2955.1602 2841.9646 2519.5649 2370.9211 2674.1777 2970.4900 2867.1841 2550.9324 2410.9409 2713.0254 2969.7795 2853.2537 2535.9856 2378.5830 2679.3799 2953.3799 2856.0322 2542.3506 2393.9910 2689.2168 2940.9067 2828.7637 2517.4790 2402.1323 2705.2529 2962.0393 2861.0640 2527.9150 2396.0129 2699.8669 2960.0642 2837.6511 2520.3005 2392.5100 2701.7053 2978.8911 2853.8955 2523.7397 2402.6797 2705.2244 2950.6699 2822.8203 2497.2366 2375.7256 2686.0632 2949.4351 2831.7803 2492.3384 2395.8760 2690.1489 2969.7524 2845.9827 2505.6814 2381.4397 2663.8816 2943.8728 +-9376.3037 -9106.6963 -9218.8955 -9532.4951 -9653.2656 -9365.8340 -9098.9639 -9228.4385 -9550.9883 -9687.4199 -9386.0889 -9101.1787 -9191.2188 -9517.9854 -9658.3047 -9383.0127 -9095.9023 -9191.3984 -9515.8975 -9665.4326 -9374.2510 -9109.5967 -9209.4531 -9527.8027 -9684.3682 -9394.7256 -9088.4932 -9176.0352 -9491.8857 -9646.2285 -9360.0342 -9086.5547 -9193.2920 -9513.6631 -9680.7275 -9389.9365 -9104.9854 -9185.9512 -9496.7793 -9662.4902 -9390.7783 -9125.4922 -9213.4824 -9525.5713 -9651.7207 -9362.1660 -9099.2490 -9179.4893 -9516.8779 -9664.1387 -9374.5957 -9094.6934 -9199.9023 -9519.7832 -9657.4473 -9361.8779 -9076.9287 -9192.6543 -9525.5820 -9653.1904 -9362.5771 -9113.3135 -9220.9189 -9550.0420 -9680.7969 -9386.9648 -9109.3838 -9214.4111 -9547.4531 -9657.4570 -9374.5166 -9088.8594 -9196.6758 -9539.1670 -9674.5850 -9406.4766 -9109.9834 diff --git a/mne-python/source/mne/io/egi/tests/test_egi.py b/mne-python/source/mne/io/egi/tests/test_egi.py new file mode 100644 index 0000000000000000000000000000000000000000..261a9c80da326f531c1abb1797ac05c335f3f209 --- /dev/null +++ b/mne-python/source/mne/io/egi/tests/test_egi.py @@ -0,0 +1,605 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + + +import os +import shutil +from copy import deepcopy +from datetime import datetime, timezone +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_equal +from scipy import io as sio + +from mne import events_from_annotations, find_events, pick_types +from mne._fiff.constants import FIFF +from mne.datasets.testing import data_path, requires_testing_data +from mne.io import read_evokeds_mff, read_raw_egi, read_raw_fif +from mne.io.egi.egi import _combine_triggers +from mne.io.tests.test_raw import _test_raw_reader +from mne.utils import object_diff + +base_dir = Path(__file__).parent / "data" +egi_fname = base_dir / "test_egi.raw" +egi_txt_fname = base_dir / "test_egi.txt" +testing_path = data_path(download=False) +egi_path = testing_path / "EGI" +egi_mff_fname = egi_path / "test_egi.mff" +egi_mff_pns_fname = egi_path / "test_egi_pns.mff" +egi_pause_fname = egi_path / "test_egi_multiepoch_paused.mff" +egi_eprime_pause_fname = egi_path / "test_egi_multiepoch_eprime.mff" +egi_pause_w1337_fname = egi_path / "w1337_20191014_105416.mff" +egi_mff_evoked_fname = egi_path / "test_egi_evoked.mff" +egi_txt_evoked_cat1_fname = egi_path / "test_egi_evoked_cat1.txt" +egi_txt_evoked_cat2_fname = egi_path / "test_egi_evoked_cat2.txt" + +# absolute event times from NetStation +egi_pause_events = { + "AM40": [7.224, 11.928, 14.413, 16.848], + "bgin": [6.121, 8.434, 13.369, 15.815, 18.094], + "FIX+": [6.225, 10.929, 13.414, 15.849], + "ITI+": [8.293, 12.997, 15.482, 17.918], +} +# absolute epoch times +egi_pause_skips = [(1304000.0, 1772000.0), (8660000.0, 12296000.0)] + +egi_eprime_pause_events = { + "AM40": [6.049, 8.434, 10.936, 13.321], + "bgin": [4.902, 7.381, 9.901, 12.268, 14.619], + "FIX+": [5.050, 7.435, 9.937, 12.322], + "ITI+": [7.185, 9.503, 12.005, 14.391], +} +egi_eprime_pause_skips = [(1344000.0, 1804000.0)] + +egi_pause_w1337_events = None +egi_pause_w1337_skips = [(21956000.0, 40444000.0), (60936000.0, 89332000.0)] + + +@requires_testing_data +@pytest.mark.parametrize( + "fname, skip_times, event_times", + [ + (egi_pause_fname, egi_pause_skips, egi_pause_events), + (egi_eprime_pause_fname, egi_eprime_pause_skips, egi_eprime_pause_events), + (egi_pause_w1337_fname, egi_pause_w1337_skips, egi_pause_w1337_events), + ], +) +def test_egi_mff_pause(fname, skip_times, event_times): + """Test EGI MFF with pauses.""" + pytest.importorskip("defusedxml") + if fname == egi_pause_w1337_fname: + # too slow to _test_raw_reader + raw = read_raw_egi(fname, events_as_annotations=False).load_data() + else: + with pytest.warns(RuntimeWarning, match="Acquisition skips detected"): + raw = _test_raw_reader( + read_raw_egi, + input_fname=fname, + test_scaling=False, # XXX probably some bug + test_rank="less", + events_as_annotations=False, + ) + assert raw.info["sfreq"] == 250.0 # true for all of these files + assert raw.info["dev_head_t"] is None # no MEG data + assert len(raw.annotations) == len(skip_times) + + # assert event onsets match expected times + if event_times is None: + with pytest.raises(ValueError, match="Consider using .*events_from"): + find_events(raw) + else: + events = find_events(raw) + for event_type in event_times.keys(): + ns_samples = np.floor(np.array(event_times[event_type]) * raw.info["sfreq"]) + assert_array_equal( + events[events[:, 2] == raw.event_id[event_type], 0], ns_samples + ) + + # read some data from the middle of the skip, assert it's all zeros + stim_picks = pick_types(raw.info, meg=False, stim=True, exclude=()) + other_picks = np.setdiff1d(np.arange(len(raw.ch_names)), stim_picks) + for ii, annot in enumerate(raw.annotations): + assert annot["description"] == "BAD_ACQ_SKIP" + start, stop = raw.time_as_index( + [annot["onset"], annot["onset"] + annot["duration"]] + ) + data, _ = raw[:, start:stop] + assert_array_equal(data[other_picks], 0.0) + if event_times is not None: + assert raw.ch_names[-1] == "STI 014" + assert not np.array_equal(data[stim_picks], 0.0) + + # assert skips match expected onset and duration + skip = ( + (start + 1) / raw.info["sfreq"] * 1e6, + (stop + 1) / raw.info["sfreq"] * 1e6, + ) + assert skip == skip_times[ii] + + +@requires_testing_data +@pytest.mark.parametrize( + "fname", + [ + egi_pause_fname, + egi_eprime_pause_fname, + egi_pause_w1337_fname, + ], +) +def test_egi_mff_pause_chunks(fname, tmp_path): + """Test that on-demand of all short segments works (via I/O).""" + pytest.importorskip("defusedxml") + fname_temp = tmp_path / "test_raw.fif" + raw_data = read_raw_egi(fname, preload=True).get_data() + raw = read_raw_egi(fname) + with pytest.warns(RuntimeWarning, match="Acquisition skips detected"): + raw.save(fname_temp) + del raw + raw_data_2 = read_raw_fif(fname_temp).get_data() + assert_allclose(raw_data, raw_data_2) + + +@requires_testing_data +@pytest.mark.parametrize("events_as_annotations", (True, False)) +def test_io_egi_mff(events_as_annotations): + """Test importing EGI MFF simple binary files.""" + pytest.importorskip("defusedxml") + # want vars for n chans + n_ref = 1 + n_eeg = 128 + n_card = 3 + + raw = read_raw_egi(egi_mff_fname, events_as_annotations=events_as_annotations) + assert "RawMff" in repr(raw) + assert raw.orig_format == "single" + include = ["DIN1", "DIN2", "DIN3", "DIN4", "DIN5", "DIN7"] + raw = _test_raw_reader( + read_raw_egi, + input_fname=egi_mff_fname, + include=include, + channel_naming="EEG %03d", + test_scaling=False, # XXX probably some bug + events_as_annotations=events_as_annotations, + ) + assert raw.info["sfreq"] == 1000.0 + assert len(raw.info["dig"]) == n_card + n_eeg + n_ref + assert raw.info["dig"][0]["ident"] == FIFF.FIFFV_POINT_LPA + assert raw.info["dig"][0]["kind"] == FIFF.FIFFV_POINT_CARDINAL + assert raw.info["dig"][3]["kind"] == FIFF.FIFFV_POINT_EEG + assert raw.info["dig"][-1]["ident"] == 129 + # This is not a custom reference, it's consistent across all channels + assert raw.info["custom_ref_applied"] == FIFF.FIFFV_MNE_CUSTOM_REF_OFF + ref_loc = raw.info["dig"][-1]["r"] + eeg_picks = pick_types(raw.info, eeg=True) + assert len(eeg_picks) == n_eeg + n_ref # 129 + # ref channel should store its own loc as ref location, so't test it + for i in eeg_picks: + loc = raw.info["chs"][i]["loc"] + assert loc[:3].any(), loc[:3] + assert_array_equal(loc[3:6], ref_loc, err_msg=f"{i}") + assert raw.info["device_info"]["type"] == "HydroCel GSN 128 1.0" + + assert "eeg" in raw + # test our custom channel naming logic functionality + eeg_chan = [c for c in raw.ch_names if "EEG" in c] + assert len(eeg_chan) == n_eeg # 128: VREF will not match in comprehension + if events_as_annotations: + assert "STI 014" not in raw.ch_names + assert raw.event_id is None + event_id = {"DIN1": 1, "DIN2": 2, "DIN3": 3, "DIN4": 4, "DIN5": 5, "DIN7": 7} + events, _ = events_from_annotations(raw, event_id=event_id) + else: + assert "STI 014" in raw.ch_names + events = find_events(raw, stim_channel="STI 014") + event_id = raw.event_id + + assert len(events) == 8 + assert np.unique(events[:, 1])[0] == 0 + assert np.unique(events[:, 0])[0] != 0 + assert np.unique(events[:, 2])[0] != 0 + assert "DIN1" in event_id + + with pytest.raises(ValueError, match="Could not find event"): + read_raw_egi(egi_mff_fname, include=["Foo"]) + with pytest.raises(ValueError, match="Could not find event"): + read_raw_egi(egi_mff_fname, exclude=["Bar"]) + for ch in include: + assert ch in event_id + assert event_id[ch] == int(ch[-1]) + # test converting stim triggers to annotations + if events_as_annotations: + # Grab the first annotation. Should be the first "DIN1" event. + assert len(raw.annotations) + onset, dur, desc, _, _ = raw.annotations[0].values() + assert_allclose(onset, 2.438) + assert np.isclose(dur, 0) + assert desc == "DIN1" + # grab the DIN1 channel + din1 = raw.get_data(picks="DIN1") + # Check that the time in sec of first event is the same as the first annotation + pin_hi_idx = np.where(din1 == 1)[1] + pin_hi_sec = pin_hi_idx / raw.info["sfreq"] + assert np.isclose(pin_hi_sec[0], onset) + + +def test_io_egi(): + """Test importing EGI simple binary files.""" + # test default + with open(egi_txt_fname) as fid: + data = np.loadtxt(fid) + t = data[0] + data = data[1:] + data *= 1e-6 # µV + + raw = read_raw_egi(egi_fname, events_as_annotations=False) + + # The reader should accept a Path, too. + raw_annot = read_raw_egi(Path(egi_fname), events_as_annotations=True) + + assert "RawEGI" in repr(raw) + data_read, t_read = raw[:256] + assert_allclose(t_read, t) + assert_allclose(data_read, data, atol=1e-10) + + include = ["TRSP", "XXX1"] + raw = _test_raw_reader( + read_raw_egi, + input_fname=egi_fname, + include=include, + test_rank="less", + test_scaling=False, # XXX probably some bug + events_as_annotations=False, + ) + + assert "eeg" in raw + assert raw.orig_format == "single" + eeg_chan = [c for c in raw.ch_names if c.startswith("E")] + assert len(eeg_chan) == 256 + picks = pick_types(raw.info, eeg=True) + assert len(picks) == 256 + assert "STI 014" in raw.ch_names + + events = find_events(raw, stim_channel="STI 014") + assert len(events) == 2 # ground truth + assert np.unique(events[:, 1])[0] == 0 + assert np.unique(events[:, 0])[0] != 0 + assert np.unique(events[:, 2])[0] != 0 + triggers = np.array([[0, 1, 1, 0], [0, 0, 1, 0]]) + + # test trigger functionality + triggers = np.array([[0, 1, 0, 0], [0, 0, 1, 0]]) + events_ids = [12, 24] + new_trigger = _combine_triggers(triggers, events_ids) + assert_array_equal(np.unique(new_trigger), np.unique([0, 12, 24])) + + with pytest.raises(ValueError, match="Could not find.*include.*"): + read_raw_egi(egi_fname, include=["Foo"]) + with pytest.raises(ValueError, match="Could not find.*exclude.*"): + read_raw_egi(egi_fname, exclude=["Bar"]) + for ii, k in enumerate(include, 1): + assert k in raw.event_id + assert raw.event_id[k] == ii + assert raw_annot.event_id is None + events, event_id = events_from_annotations(raw_annot, event_id=raw.event_id) + assert event_id == raw.event_id + events_2 = find_events(raw) + assert_array_equal(events, events_2) + + +@requires_testing_data +def test_io_egi_pns_mff(tmp_path): + """Test importing EGI MFF with PNS data.""" + pytest.importorskip("defusedxml") + raw = read_raw_egi(egi_mff_pns_fname, include=None, preload=True, verbose="error") + assert "RawMff" in repr(raw) + pns_chans = pick_types(raw.info, ecg=True, bio=True, emg=True) + assert len(pns_chans) == 7 + names = [raw.ch_names[x] for x in pns_chans] + pns_names = [ + "Resp. Temperature", + "Resp. Pressure", + "ECG", + "Body Position", + "Resp. Effort Chest", + "Resp. Effort Abdomen", + "EMG-Leg", + ] + _test_raw_reader( + read_raw_egi, + input_fname=egi_mff_pns_fname, + channel_naming="EEG %03d", + verbose="error", + test_rank="less", + test_scaling=False, # XXX probably some bug + ) + assert names == pns_names + mat_names = [ + "Resp_Temperature", + "Resp_Pressure", + "ECG", + "Body_Position", + "Resp_Effort_Chest", + "Resp_Effort_Abdomen", + "EMGLeg", + ] + egi_fname_mat = testing_path / "EGI" / "test_egi_pns.mat" + mc = sio.loadmat(egi_fname_mat) + for ch_name, ch_idx, mat_name in zip(pns_names, pns_chans, mat_names): + print(f"Testing {ch_name}") + mc_key = [x for x in mc.keys() if mat_name in x][0] + cal = raw.info["chs"][ch_idx]["cal"] + mat_data = mc[mc_key] * cal + raw_data = raw[ch_idx][0] + assert_array_equal(mat_data, raw_data) + + # EEG missing + new_mff = tmp_path / "temp.mff" + shutil.copytree(egi_mff_pns_fname, new_mff) + read_raw_egi(new_mff, verbose="error") + os.remove(new_mff / "info1.xml") + os.remove(new_mff / "signal1.bin") + with pytest.raises(FileNotFoundError, match="Could not find any EEG"): + read_raw_egi(new_mff, verbose="error") + + +@requires_testing_data +@pytest.mark.parametrize("preload", (True, False)) +def test_io_egi_pns_mff_bug(preload): + """Test importing EGI MFF with PNS data (BUG).""" + pytest.importorskip("defusedxml") + egi_fname_mff = testing_path / "EGI" / "test_egi_pns_bug.mff" + with pytest.warns(RuntimeWarning, match="EGI PSG sample bug"): + raw = read_raw_egi( + egi_fname_mff, include=None, preload=preload, verbose="warning" + ) + assert len(raw.annotations) == 1 + assert_allclose(raw.annotations.duration, [0.004]) + assert_allclose(raw.annotations.onset, [13.948]) + egi_fname_mat = testing_path / "EGI" / "test_egi_pns.mat" + mc = sio.loadmat(egi_fname_mat) + pns_chans = pick_types(raw.info, ecg=True, bio=True, emg=True) + pns_names = [ + "Resp. Temperature"[:15], + "Resp. Pressure", + "ECG", + "Body Position", + "Resp. Effort Chest"[:15], + "Resp. Effort Abdomen"[:15], + "EMG-Leg", + ] + mat_names = [ + "Resp_Temperature"[:15], + "Resp_Pressure", + "ECG", + "Body_Position", + "Resp_Effort_Chest"[:15], + "Resp_Effort_Abdomen"[:15], + "EMGLeg", + ] + for ch_name, ch_idx, mat_name in zip(pns_names, pns_chans, mat_names): + print(f"Testing {ch_name}") + mc_key = [x for x in mc.keys() if mat_name in x][0] + cal = raw.info["chs"][ch_idx]["cal"] + mat_data = mc[mc_key] * cal + mat_data[:, -1] = 0 # The MFF has one less sample, the last one + raw_data = raw[ch_idx][0] + assert_array_equal(mat_data, raw_data) + + +@requires_testing_data +def test_io_egi_crop_no_preload(): + """Test crop non-preloaded EGI MFF data (BUG).""" + pytest.importorskip("defusedxml") + raw = read_raw_egi(egi_mff_fname, preload=False) + raw.crop(17.5, 20.5) + raw.load_data() + raw_preload = read_raw_egi(egi_mff_fname, preload=True) + raw_preload.crop(17.5, 20.5) + raw_preload.load_data() + assert_allclose(raw._data, raw_preload._data) + + +@requires_testing_data +@pytest.mark.parametrize( + "idx, cond, tmax, signals, bads", + [ + ( + 0, + "Category 1", + 0.016, + egi_txt_evoked_cat1_fname, + ["E8", "E11", "E17", "E28", "ECG"], + ), + (1, "Category 2", 0.0, egi_txt_evoked_cat2_fname, ["VREF", "EMG"]), + ], +) +def test_io_egi_evokeds_mff(idx, cond, tmax, signals, bads): + """Test reading evoked MFF file.""" + pytest.importorskip("mffpy", "0.5.7") + + pytest.importorskip("defusedxml") + # expected n channels + n_eeg = 256 + n_ref = 1 + n_card = 3 + n_pns = 2 # 1 ECG + 1 EMG + + # Test reading all conditions from evokeds + evokeds = read_evokeds_mff(egi_mff_evoked_fname) + assert len(evokeds) == 2 + # Test reading list of conditions from evokeds + evokeds = read_evokeds_mff(egi_mff_evoked_fname, condition=[0, 1]) + assert len(evokeds) == 2 + # Test invalid condition + with pytest.raises(ValueError) as exc_info: + read_evokeds_mff(egi_mff_evoked_fname, condition="Invalid Condition") + message = ( + "Invalid value for the 'condition' parameter provided as " + "category name. Allowed values are 'Category 1' and " + "'Category 2', but got 'Invalid Condition' instead." + ) + assert str(exc_info.value) == message + with pytest.raises(ValueError) as exc_info: + read_evokeds_mff(egi_mff_evoked_fname, condition=2) + message = ( + '"condition" parameter (2), provided as epoch index, ' + "is out of range for available epochs (2)." + ) + assert str(exc_info.value) == message + with pytest.raises(TypeError) as exc_info: + read_evokeds_mff(egi_mff_evoked_fname, condition=1.2) + message = '"condition" parameter must be either int or str.' + assert str(exc_info.value) == message + # Test reading evoked data from single condition + evoked_cond = read_evokeds_mff(egi_mff_evoked_fname, condition=cond) + evoked_idx = read_evokeds_mff(egi_mff_evoked_fname, condition=idx) + for evoked in [evoked_cond, evoked_idx]: + assert evoked.comment == cond + assert evoked.nave == 3 + assert evoked.tmin == 0.0 + assert evoked.tmax == tmax + # Check signal data + data = np.loadtxt(signals, ndmin=2).T * 1e-6 # convert to volts + assert_allclose(evoked_cond.data, data, atol=1e-12) + assert_allclose(evoked_idx.data, data, atol=1e-12) + # Check info + assert object_diff(evoked_cond.info, evoked_idx.info) == "" + assert evoked_cond.info["description"] == cond + assert evoked_cond.info["bads"] == bads + assert len(evoked_cond.info["ch_names"]) == n_eeg + n_ref + n_pns # 259 + assert "ECG" in evoked_cond.info["ch_names"] + assert "EMG" in evoked_cond.info["ch_names"] + assert "ecg" in evoked_cond + assert "emg" in evoked_cond + pick_eeg = pick_types(evoked_cond.info, eeg=True, exclude=[]) + assert len(pick_eeg) == n_eeg + n_ref # 257 + assert evoked_cond.info["nchan"] == n_eeg + n_ref + n_pns # 259 + assert evoked_cond.info["sfreq"] == 250.0 + assert not evoked_cond.info["custom_ref_applied"] + assert len(evoked_cond.info["dig"]) == n_card + n_eeg + n_ref + assert evoked_cond.info["device_info"]["type"] == "HydroCel GSN 256 1.0" + + +@requires_testing_data +def test_read_evokeds_mff_bad_input(): + """Test errors are thrown when reading invalid input file.""" + pytest.importorskip("mffpy", "0.5.7") + # Test file that is not an MFF + with pytest.raises(ValueError) as exc_info: + read_evokeds_mff(egi_fname) + message = 'fname must be an MFF file with extension ".mff".' + assert str(exc_info.value) == message + # Test continuous MFF + with pytest.raises(ValueError) as exc_info: + read_evokeds_mff(egi_mff_fname) + message = ( + f"{egi_mff_fname} is a continuous MFF file. " + "fname must be the path to an averaged MFF file." + ) + assert str(exc_info.value) == message + + +@requires_testing_data +def test_egi_coord_frame(): + """Test that EGI coordinate frame is changed to head.""" + pytest.importorskip("defusedxml") + info = read_raw_egi(egi_mff_fname).info + want_idents = ( + FIFF.FIFFV_POINT_LPA, + FIFF.FIFFV_POINT_NASION, + FIFF.FIFFV_POINT_RPA, + ) + for ii, want in enumerate(want_idents): + d = info["dig"][ii] + assert d["kind"] == FIFF.FIFFV_POINT_CARDINAL + assert d["ident"] == want + loc = d["r"] + if ii == 0: + assert 0.05 < -loc[0] < 0.1, "LPA" + assert_allclose(loc[1:], 0, atol=1e-7, err_msg="LPA") + elif ii == 1: + assert 0.05 < loc[1] < 0.11, "Nasion" + assert_allclose(loc[::2], 0, atol=1e-7, err_msg="Nasion") + else: + assert ii == 2 + assert 0.05 < loc[0] < 0.1, "RPA" + assert_allclose(loc[1:], 0, atol=1e-7, err_msg="RPA") + for d in info["dig"][3:]: + assert d["kind"] == FIFF.FIFFV_POINT_EEG + + +@requires_testing_data +@pytest.mark.parametrize( + "fname, timestamp, utc_offset", + [ + (egi_mff_fname, "2017-02-23T11:35:13.220824+01:00", "+0100"), + (egi_mff_pns_fname, "2017-09-20T09:55:44.072000+01:00", "+0100"), + (egi_eprime_pause_fname, "2018-07-30T10:46:09.621673-04:00", "-0400"), + (egi_pause_w1337_fname, "2019-10-14T10:54:27.395210-07:00", "-0700"), + ], +) +def test_meas_date(fname, timestamp, utc_offset): + """Test meas date conversion.""" + pytest.importorskip("defusedxml") + raw = read_raw_egi(fname, verbose="warning") + dt = datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%f%z") + measdate = dt.astimezone(timezone.utc) + hour_local = int(dt.strftime("%H")) + hour_utc = int(raw.info["meas_date"].strftime("%H")) + local_utc_diff = hour_local - hour_utc + assert raw.info["meas_date"] == measdate + assert raw.info["utc_offset"] == utc_offset + assert local_utc_diff == int(utc_offset[:-2]) + + +@requires_testing_data +@pytest.mark.parametrize( + "fname, standard_montage", + [ + (egi_mff_fname, "GSN-HydroCel-129"), # 129 chan EGI file + (egi_mff_pns_fname, "GSN-HydroCel-257"), # 257 chan EGI file + ], +) +def test_set_standard_montage_mff(fname, standard_montage): + """Test setting a standard montage.""" + pytest.importorskip("defusedxml") + raw = read_raw_egi(fname, verbose="warning") + n_eeg = int(standard_montage.split("-")[-1]) + n_dig = n_eeg + 3 + dig_before_mon = deepcopy(raw.info["dig"]) + assert len(dig_before_mon) == n_dig + ref_loc = dig_before_mon[-1]["r"] + picks = pick_types(raw.info, eeg=True) + assert len(picks) == n_eeg + for pick in picks: + assert_allclose(raw.info["chs"][pick]["loc"][3:6], ref_loc) + + raw.set_montage(standard_montage, match_alias=True, on_missing="ignore") + dig_after_mon = raw.info["dig"] + + # No dig entries should have been dropped while setting montage + assert len(dig_before_mon) == n_dig + assert len(dig_after_mon) == n_dig + + # Check that the reference remained + for pick in picks: + assert_allclose(raw.info["chs"][pick]["loc"][3:6], ref_loc) + + +@requires_testing_data +def test_egi_mff_bad_xml(tmp_path): + """Test that corrupt XML files are gracefully handled.""" + pytest.importorskip("defusedxml") + mff_fname = shutil.copytree(egi_mff_fname, tmp_path / "test_egi_bad_xml.mff") + bad_xml = mff_fname / "bad.xml" + bad_xml.write_text("", encoding="utf-8") + # Missing coordinate file + (mff_fname / "coordinates.xml").unlink() + with pytest.warns(RuntimeWarning, match="Could not parse the XML"): + with pytest.warns(RuntimeWarning, match="File coordinates.xml not found"): + raw = read_raw_egi(mff_fname) + # little check that the bad XML doesn't affect the parsing of other xml files + assert "DIN1" in raw.annotations.description diff --git a/mne-python/source/mne/io/eximia/__init__.py b/mne-python/source/mne/io/eximia/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2530990e13ef03fd6355938dbb424efa8bb5b8cb --- /dev/null +++ b/mne-python/source/mne/io/eximia/__init__.py @@ -0,0 +1,7 @@ +"""Eximia module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .eximia import read_raw_eximia diff --git a/mne-python/source/mne/io/eximia/eximia.py b/mne-python/source/mne/io/eximia/eximia.py new file mode 100644 index 0000000000000000000000000000000000000000..5d21879de32717ccdfd17a80242474b741fe10f3 --- /dev/null +++ b/mne-python/source/mne/io/eximia/eximia.py @@ -0,0 +1,103 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op + +from ..._fiff.meas_info import create_info +from ..._fiff.utils import _file_size, _read_segments_file +from ...utils import _check_fname, fill_doc, logger, verbose, warn +from ..base import BaseRaw + + +@fill_doc +def read_raw_eximia(fname, preload=False, verbose=None) -> "RawEximia": + """Reader for an eXimia EEG file. + + Parameters + ---------- + fname : path-like + Path to the eXimia ``.nxe`` data file. + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawEximia + A Raw object containing eXimia data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawEximia. + """ + return RawEximia(fname, preload, verbose) + + +@fill_doc +class RawEximia(BaseRaw): + """Raw object from an Eximia EEG file. + + Parameters + ---------- + fname : path-like + Path to the eXimia data file (.nxe). + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + @verbose + def __init__(self, fname, preload=False, verbose=None): + fname = str(_check_fname(fname, "read", True, "fname")) + data_name = op.basename(fname) + logger.info(f"Loading {data_name}") + # Create vhdr and vmrk files so that we can use mne_brain_vision2fiff + n_chan = 64 + sfreq = 1450.0 + # data are multiplexed int16 + ch_names = ["GateIn", "Trig1", "Trig2", "EOG"] + ch_types = ["stim", "stim", "stim", "eog"] + cals = [ + 0.0015259021896696422, + 0.0015259021896696422, + 0.0015259021896696422, + 0.3814755474174106, + ] + ch_names += ( + "Fp1 Fpz Fp2 AF1 AFz AF2 " + "F7 F3 F1 Fz F2 F4 F8 " + "FT9 FT7 FC5 FC3 FC1 FCz FC2 FC4 FC6 FT8 FT10 " + "T7 C5 C3 C1 Cz C2 C4 C6 T8 " + "TP9 TP7 CP5 CP3 CP1 CPz CP2 CP4 CP6 TP8 TP10 " + "P9 P7 P3 P1 Pz P2 P4 P8 " + "P10 PO3 POz PO4 O1 Oz O2 Iz".split() + ) + n_eeg = len(ch_names) - len(cals) + cals += [0.07629510948348212] * n_eeg + ch_types += ["eeg"] * n_eeg + assert len(ch_names) == n_chan + info = create_info(ch_names, sfreq, ch_types) + n_bytes = _file_size(fname) + n_samples, extra = divmod(n_bytes, (n_chan * 2)) + if extra != 0: + warn( + f"Incorrect number of samples in file ({n_samples}), the file is likely" + " truncated" + ) + for ch, cal in zip(info["chs"], cals): + ch["cal"] = cal + super().__init__( + info, + preload=preload, + last_samps=(n_samples - 1,), + filenames=[fname], + orig_format="short", + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + _read_segments_file(self, data, idx, fi, start, stop, cals, mult, dtype=" 1: + logger.info( + f"There are {raw_extras['n_blocks']} recording blocks in this file." + f" Times between blocks will be annotated with BAD_ACQ_SKIP." + ) + raw_extras["dfs"]["samples"] = _adjust_times( + raw_extras["dfs"]["samples"], raw_extras["sfreq"] + ) + # Convert timestamps to seconds + for df in raw_extras["dfs"].values(): + df = _convert_times(df, raw_extras["first_timestamp"]) + # Find overlaps between left and right eye events + if find_overlaps: + for key in raw_extras["dfs"]: + if key not in ["blinks", "fixations", "saccades"]: + continue + raw_extras["dfs"][key] = _find_overlaps( + raw_extras["dfs"][key], max_time=overlap_threshold + ) + # ======================== Info for BaseRaw ======================== + eye_ch_data = raw_extras["dfs"]["samples"][ch_names].to_numpy().T + info = _create_info(ch_names, raw_extras) + + return eye_ch_data, info, raw_extras + + +def _parse_recording_blocks(fname): + """Parse Eyelink ASCII file. + + Eyelink samples occur within START and END blocks. + samples lines start with a posix-like string, + and contain eyetracking sample info. Event Lines + start with an upper case string and contain info + about occular events (i.e. blink/saccade), or experiment + messages sent by the stimulus presentation software. + """ + with fname.open() as file: + data_dict = dict() + data_dict["sample_lines"] = [] + data_dict["event_lines"] = { + "START": [], + "END": [], + "SAMPLES": [], + "EVENTS": [], + "ESACC": [], + "EBLINK": [], + "EFIX": [], + "MSG": [], + "INPUT": [], + "BUTTON": [], + "PUPIL": [], + } + data_blocks = [] + + is_recording_block = False + for line in file: + if line.startswith("START"): # start of recording block + is_recording_block = True + # Initialize container for new block data + current_block = { + "samples": [], + "events": { + "START": [], + "END": [], + "SAMPLES": [], + "EVENTS": [], + "ESACC": [], + "EBLINK": [], + "EFIX": [], + "MSG": [], + "INPUT": [], + "BUTTON": [], + "PUPIL": [], + }, + "info": None, + } + if is_recording_block: + tokens = line.split() + if not tokens: + continue # skip empty lines + if tokens[0][0].isnumeric(): # Samples + current_block["samples"].append(tokens) + elif tokens[0] in current_block["events"].keys(): + if _is_sys_msg(line): + continue # system messages don't need to be parsed. + event_key, event_info = tokens[0], tokens[1:] + current_block["events"][event_key].append(event_info) + if tokens[0] == "END": # end of recording block + current_block["info"] = _get_metadata(current_block) + data_blocks.append(current_block) + is_recording_block = False + if not data_blocks: # no samples parsed + raise ValueError(f"Couldn't find any samples in {fname}") + return data_blocks + + +def _validate_data(data_blocks: list): + """Check the incoming data for some known problems that can occur.""" + # Detect the datatypes that are in file. + units = [] + pupil_units = [] + modes = [] + eyes = [] + sfreqs = [] + for block in data_blocks: + units.append(block["info"]["unit"]) + modes.append(block["info"]["tracking_mode"]) + eyes.append(block["info"]["eye"]) + sfreqs.append(block["info"]["sfreq"]) + pupil_units.append(block["info"]["pupil_unit"]) + if "GAZE" in units: + logger.info( + "Pixel coordinate data detected." + "Pass `scalings=dict(eyegaze=1e3)` when using plot" + " method to make traces more legible." + ) + if "HREF" in units: + logger.info("Head-referenced eye-angle (HREF) data detected.") + elif "PUPIL" in units: + warn("Raw eyegaze coordinates detected. Analyze with caution.") + if "AREA" in pupil_units: + logger.info("Pupil-size area detected.") + elif "DIAMETER" in pupil_units: + logger.info("Pupil-size diameter detected.") + + if len(set(modes)) > 1: + warn( + "This recording switched between monocular and binocular tracking. " + f"In order of acquisition blocks, tracking modes were {modes}. Data " + "for the missing eye during monocular tracking will be filled with NaN." + ) + # Monocular tracking but switched between left/right eye + elif len(set(eyes)) > 1: + warn( + "The eye being tracked changed during the recording. " + f"In order of acquisition blocks, they were {eyes}. " + "Missing data for each eye will be filled with NaN." + ) + if len(set(sfreqs)) > 1: + raise RuntimeError( + "The sampling frequency changed during the recording. " + f"In order of acquisition blocks, they were {sfreqs}. " + "please notify MNE-Python developers" + ) # pragma: no cover + if len(set(units)) > 1: + raise RuntimeError( + "The unit of measurement for x/y coordinates changed during the recording. " + f"In order of acquisition blocks, they were {units}. " + "please notify MNE-Python developers" + ) # pragma: no cover + + +def _get_recording_datetime(fname): + """Create a datetime object from the datetime in ASCII file.""" + # create a timezone object for UTC + tz = timezone(timedelta(hours=0)) + in_header = False + with fname.open() as file: + for line in file: + # header lines are at top of file and start with ** + if line.startswith("**"): + in_header = True + if in_header: + if line.startswith("** DATE:"): + dt_str = line.replace("** DATE:", "").strip() + fmt = "%a %b %d %H:%M:%S %Y" + # Eyelink measdate timestamps are timezone naive. + # Force datetime to be in UTC. + # Even though dt is probably in local time zone. + try: + dt_naive = datetime.strptime(dt_str, fmt) + except ValueError: + # date string is missing or in an unexpected format + logger.info( + "Could not detect date from file with date entry: " + f"{repr(dt_str)}" + ) + return + else: + return dt_naive.replace(tzinfo=tz) # make it dt aware + return + + +def _get_metadata(data_block: dict): + """Get tracking mode, sfreq, eye tracked, pupil metric, etc. for one data block.""" + meta_data = dict() + rec_info = data_block["events"]["SAMPLES"][0] + meta_data["unit"] = rec_info[0] + + # If the file doesn't have pupil data, i'm not sure if there will be any PUPIL info? + if not data_block["events"]["PUPIL"]: + ps_unit = None + else: + ps_unit = data_block["events"]["PUPIL"][0][0] + meta_data["pupil_unit"] = ps_unit + if ("LEFT" in rec_info) and ("RIGHT" in rec_info): + meta_data["tracking_mode"] = "binocular" + meta_data["eye"] = "both" + else: + meta_data["tracking_mode"] = "monocular" + meta_data["eye"] = rec_info[1].lower() + meta_data["first_timestamp"] = float(data_block["events"]["START"][0][0]) + meta_data["last_timestamp"] = float(data_block["events"]["END"][0][0]) + meta_data["sfreq"] = _get_sfreq_from_ascii(rec_info) + meta_data["rec_info"] = data_block["events"]["SAMPLES"][0] + return meta_data + + +def _is_sys_msg(line): + """Flag lines from eyelink ASCII file that contain a known system message. + + Some lines in eyelink files are system outputs usually + only meant for Eyelinks DataViewer application to read. + These shouldn't need to be parsed. + + Parameters + ---------- + line : string + single line from Eyelink asc file + + Returns + ------- + bool : + True if any of the following strings that are + known to indicate a system message are in the line + + Notes + ----- + Examples of eyelink system messages: + - ;Sess:22Aug22;Tria:1;Tri2:False;ESNT:182BFE4C2F4; + - ;NTPT:182BFE55C96;SMSG:__NTP_CLOCK_SYNC__;DIFF:-1; + - !V APLAYSTART 0 1 library/audio + - !MODE RECORD CR 500 2 1 R + """ + return "!V" in line or "!MODE" in line or ";" in line + + +def _get_sfreq_from_ascii(rec_info): + """Get sampling frequency from Eyelink ASCII file. + + Parameters + ---------- + rec_info : list + the first list in raw_extras["event_lines"]['SAMPLES']. + The sfreq occurs after RATE: i.e. [..., RATE, 1000, ...]. + + Returns + ------- + sfreq : float + """ + return float(rec_info[rec_info.index("RATE") + 1]) + + +def _create_dataframes(data_blocks, apply_offsets): + """Create and process pandas DataFrames for each recording block. + + Processes each block individually with its own column structure, + then returns a list of processed block dataframes. + """ + processed_blocks = [] + + for block_idx, block in enumerate(data_blocks): + # Create dataframes for this block + block_dfs = _create_dataframes_for_block(block, apply_offsets) + + # Infer column names for this specific block + col_names, ch_names = _infer_col_names_for_block(block) + + # Assign column names and set dtypes for this block + block_dfs = _assign_col_names(col_names, block_dfs) + block_dfs = _set_df_dtypes(block_dfs) + + processed_blocks.append( + { + "block_idx": block_idx, + "dfs": block_dfs, + "ch_names": ch_names, + "info": block["info"], + } + ) + return processed_blocks + + +def _create_dataframes_for_block(block, apply_offsets): + """Create pandas.DataFrame for one recording block's samples and events. + + Creates a pandas DataFrame for sample_lines and for each + non-empty key in event_lines for a single recording block. + No column names are assigned at this point. + This also returns the MNE channel names needed to represent this block of data. + """ + pd = _check_pandas_installed() + df_dict = dict() + + # dataframe for samples in this block + if block["samples"]: + df_dict["samples"] = pd.DataFrame(block["samples"]) + df_dict["samples"] = _drop_status_col(df_dict["samples"]) # drop STATUS col + + # dataframe for each type of occular event in this block + for event, label in zip( + ["EFIX", "ESACC", "EBLINK"], ["fixations", "saccades", "blinks"] + ): + if block["events"][event]: # an empty list returns False + df_dict[label] = pd.DataFrame(block["events"][event]) + else: + # Changed this from info to debug level to avoid spamming the log + logger.debug(f"No {label} events found in block") + + # make dataframe for experiment messages in this block + if block["events"]["MSG"]: + msgs = [] + for token in block["events"]["MSG"]: + if apply_offsets and len(token) == 2: + ts, msg = token + offset = np.nan + elif apply_offsets: + ts = token[0] + try: + offset = float(token[1]) + msg = " ".join(str(x) for x in token[2:]) + except ValueError: + offset = np.nan + msg = " ".join(str(x) for x in token[1:]) + else: + ts, offset = token[0], np.nan + msg = " ".join(str(x) for x in token[1:]) + msgs.append([ts, offset, msg]) + df_dict["messages"] = pd.DataFrame(msgs) + + # make dataframes for other button events + if block["events"]["BUTTON"]: + button_events = block["events"]["BUTTON"] + parsed = [] + for entry in button_events: + parsed.append( + { + "time": float(entry[0]), # onset + "button_id": int(entry[1]), + "button_pressed": int(entry[2]), # 1 = press, 0 = release + } + ) + df_dict["buttons"] = pd.DataFrame(parsed) + n_button = len(df_dict.get("buttons", [])) + logger.info(f"Found {n_button} button event(s) in this file.") + else: + logger.info("No button events found in this file.") + + return df_dict + + +def _infer_col_names_for_block(block: dict) -> tuple[dict[str, list], list]: + """Build column and channel names for data from one Eyelink recording block. + + Returns the expected column names for the sample lines and event + lines for a single recording block. The columns present can vary + between blocks if tracking mode changes. + """ + col_names = {} + block_info = block["info"] + + # initiate the column names for the sample lines + col_names["samples"] = list(EYELINK_COLS["timestamp"]) + col_names["messages"] = list(EYELINK_COLS["messages"]) + + # and for the eye message lines + col_names["blinks"] = list(EYELINK_COLS["eye_event"]) + col_names["fixations"] = list(EYELINK_COLS["eye_event"] + EYELINK_COLS["fixation"]) + col_names["saccades"] = list(EYELINK_COLS["eye_event"] + EYELINK_COLS["saccade"]) + + # Get block-specific tracking info + tracking_mode = block_info["tracking_mode"] + eye = block_info["eye"] + rec_info = block["events"]["SAMPLES"][0] # SAMPLES line for this block + + # Recording was either binocular or monocular for this block + if tracking_mode == "monocular": + ch_names = list(EYELINK_COLS["pos"][eye]) + elif tracking_mode == "binocular": + ch_names = list(EYELINK_COLS["pos"]["left"] + EYELINK_COLS["pos"]["right"]) + col_names["samples"].extend(ch_names) + + # The order of these if statements should not be changed. + if "VEL" in rec_info: # If velocity data are reported + if tracking_mode == "monocular": + ch_names.extend(EYELINK_COLS["velocity"][eye]) + col_names["samples"].extend(EYELINK_COLS["velocity"][eye]) + elif tracking_mode == "binocular": + ch_names.extend( + EYELINK_COLS["velocity"]["left"] + EYELINK_COLS["velocity"]["right"] + ) + col_names["samples"].extend( + EYELINK_COLS["velocity"]["left"] + EYELINK_COLS["velocity"]["right"] + ) + # if resolution data are reported + if "RES" in rec_info: + ch_names.extend(EYELINK_COLS["resolution"]) + col_names["samples"].extend(EYELINK_COLS["resolution"]) + col_names["fixations"].extend(EYELINK_COLS["resolution"]) + col_names["saccades"].extend(EYELINK_COLS["resolution"]) + # if digital input port values are reported + if "INPUT" in rec_info: + ch_names.extend(EYELINK_COLS["input"]) + col_names["samples"].extend(EYELINK_COLS["input"]) + + # if head target info was reported, add its cols + if "HTARGET" in rec_info: + ch_names.extend(EYELINK_COLS["remote"]) + col_names["samples"].extend(EYELINK_COLS["remote"]) + + return col_names, ch_names + + +def _combine_block_dataframes(processed_blocks: list[dict]): + """Combine dataframes across acquisition blocks. + + Handles cases where blocks have different columns/data in them + (e.g. binocular vs monocular tracking, or switching between the left and right eye). + """ + pd = _check_pandas_installed() + + # Determine unified column structure by collecting all unique column names + # across all acquisition blocks + all_ch_names = [] + all_samples_cols = set() + all_df_types = set() + + for block in processed_blocks: + # The tests assume a certain order of channel names. + # so we can't use a set like we do for the columns. + # bc it randomly orders the channel names. + for ch_name in block["ch_names"]: + if ch_name not in all_ch_names: + all_ch_names.append(ch_name) + if "samples" in block["dfs"]: + all_samples_cols.update(block["dfs"]["samples"].columns) + all_df_types.update(block["dfs"].keys()) + + # The sets randomly ordered the column names. + all_samples_cols = sorted(all_samples_cols) + + # Combine dataframes by type + combined_dfs = {} + + for df_type in all_df_types: + block_dfs = [] + for block in processed_blocks: + if df_type in block["dfs"]: + # We will update the dfs in-place to conserve memory + block_df = block["dfs"][df_type] + + # For samples dataframes, ensure all have the same columns + if df_type == "samples": + for col in all_samples_cols: + if col not in block_df.columns: + block_df[col] = np.nan + + # Reorder columns + block_df = block_df[all_samples_cols] + + block_dfs.append(block_df) + + if block_dfs: + # Concatenate all blocks for this dataframe type + combined_dfs[df_type] = pd.concat(block_dfs, ignore_index=True) + + # Create recording blocks dataframe from block info + blocks_data = [] + for i, block in enumerate(processed_blocks): + start_time = block["info"]["first_timestamp"] + end_time = block["info"]["last_timestamp"] + blocks_data.append((start_time, end_time, i + 1)) + combined_dfs["recording_blocks"] = pd.DataFrame( + blocks_data, columns=["time", "end_time", "block"] + ) + + return combined_dfs, all_ch_names + + +def _drop_status_col(samples_df): + """Drop STATUS column from samples dataframe. + + see https://github.com/mne-tools/mne-python/issues/11809, and section 4.9.2.1 of + the Eyelink 1000 Plus User Manual, version 1.0.19. We know that the STATUS + column is either 3, 5, 13, or 17 characters long, i.e. "...", ".....", ".C." + """ + status_cols = [] + # we know the first 3 columns will be the time, xpos, ypos + for col in samples_df.columns[3:]: + if samples_df[col][0][0].isnumeric(): + # if the value is numeric, it's not a status column + continue + if len(samples_df[col][0]) in [3, 5, 13, 17]: + status_cols.append(col) + return samples_df.drop(columns=status_cols) + + +def _assign_col_names(col_names, df_dict): + """Assign column names to dataframes. + + Parameters + ---------- + col_names : dict of str to list + Dictionary of column names for each dataframe. + df_dict : dict of str to pandas.DataFrame + Dictionary of dataframes to assign column names to. + """ + skipped_types = [] + for key, df in df_dict.items(): + if key in ("samples", "blinks", "fixations", "saccades", "messages"): + cols = col_names[key] + else: + skipped_types.append(key) + continue + max_cols = len(cols) + if len(df.columns) != len(cols): + if key in ("saccades", "fixations") and len(df.columns) >= 4: + # see https://github.com/mne-tools/mne-python/pull/13357 + logger.debug( + f"{key} events have more columns ({len(df.columns)}) than " + f"expected ({len(cols)}). Using first 4 (eye, time, end_time, " + "duration)." + ) + max_cols = 4 + else: + raise ValueError( + f"Expected the {key} data in this file to have {len(cols)} columns " + f"of data, but got {len(df.columns)}. Expected columns: {cols}." + ) + new_col_names = { + old: new for old, new in zip(df.columns[:max_cols], cols[:max_cols]) + } + df.rename(columns=new_col_names, inplace=True) + logger.debug(f"Skipped assigning column names to {skipped_types} dataframes.") + return df_dict + + +def _set_df_dtypes(df_dict): + from mne.utils import _set_pandas_dtype + + for key, df in df_dict.items(): + if key in ["samples"]: + # convert missing position values to NaN + _set_missing_values(df, df.columns[1:]) + _set_pandas_dtype(df, df.columns, float, verbose="warning") + elif key in ["blinks", "fixations", "saccades"]: + _set_missing_values(df, df.columns[1:]) + _set_pandas_dtype(df, df.columns[1:], float, verbose="warning") + elif key == "messages": + _set_pandas_dtype(df, ["time"], float, verbose="warning") # timestamp + return df_dict + + +def _set_missing_values(df, columns): + """Set missing values to NaN. operates in-place.""" + missing_vals = (".", "MISSING_DATA") + for col in columns: + # we explicitly use numpy instead of pd.replace because it is faster + # if a stim channel (DIN) we should use zero so it can cast to int properly + # in find_events + replacement = 0 if col == "DIN" else np.nan + df[col] = np.where(df[col].isin(missing_vals), replacement, df[col]) + + +def _sort_by_time(df, col="time"): + df.sort_values(col, ascending=True, inplace=True) + df.reset_index(drop=True, inplace=True) + + +def _convert_times(df, first_samp, col="time"): + """Set initial time to 0, converts from ms to seconds in place. + + Parameters + ---------- + df pandas.DataFrame: + One of the dataframes in raw_extras["dfs"] dict. + + first_samp int: + timestamp of the first sample of the recording. This should + be the first sample of the first recording block. + col str (default 'time'): + column name to sort pandas.DataFrame by + + Notes + ----- + Each sample in an Eyelink file has a posix timestamp string. + Subtracts the "first" sample's timestamp from each timestamp. + The "first" sample is inferred to be the first sample of + the first recording block, i.e. the first "START" line. + """ + _sort_by_time(df, col) + for col in df.columns: + if str(col).endswith("time"): # 'time' and 'end_time' cols + df[col] -= first_samp + df[col] /= 1000 + if str(col) in ["duration", "offset"]: + df[col] /= 1000 + return df + + +def _adjust_times( + df, + sfreq, + time_col="time", +): + """Fill missing timestamps if there are multiple recording blocks. + + Parameters + ---------- + df : pandas.DataFrame: + dataframe of the eyetracking data samples, BEFORE + _convert_times() is applied to the dataframe + + sfreq : int | float: + sampling frequency of the data + + time_col : str (default 'time'): + name of column with the timestamps (e.g. 9511881, 9511882, ...) + + Returns + ------- + %(df_return)s + + Notes + ----- + After _parse_recording_blocks, Files with multiple recording blocks will + have missing timestamps for the duration of the period between the blocks. + This would cause the occular annotations (i.e. blinks) to not line up with + the signal. + """ + pd = _check_pandas_installed() + + first, last = df[time_col].iloc[[0, -1]] + step = 1000 / sfreq + df[time_col] = df[time_col].astype(float) + new_times = pd.DataFrame( + np.arange(first, last + step / 2, step), columns=[time_col] + ) + df = pd.merge_asof( + new_times, df, on=time_col, direction="nearest", tolerance=step / 2 + ) + # fix DIN NaN values + if "DIN" in df.columns: + df["DIN"] = df["DIN"].fillna(0) + return df + + +def _find_overlaps(df, max_time=0.05): + """Merge left/right eye events with onset/offset diffs less than max_time. + + Parameters + ---------- + df : pandas.DataFrame + Pandas DataFrame with occular events (fixations, saccades, blinks) + max_time : float (default 0.05) + Time in seconds. Defaults to .05 (50 ms) + + Returns + ------- + DataFrame: %(df_return)s + :class:`pandas.DataFrame` specifying overlapped eye events, if any + + Notes + ----- + The idea is to cumulative sum the boolean values for rows with onset and + offset differences (against the previous row) that are greater than the + max_time. If onset and offset diffs are less than max_time then no_overlap + will become False. Alternatively, if either the onset or offset diff is + greater than max_time, no_overlap becomes True. Cumulatively summing over + these boolean values will leave rows with no_overlap == False unchanged + and hence with the same group number. + """ + pd = _check_pandas_installed() + + if not len(df): + return + df["overlap_start"] = df.sort_values("time")["time"].diff().lt(max_time) + + df["overlap_end"] = df["end_time"].diff().abs().lt(max_time) + + df["no_overlap"] = ~(df["overlap_end"] & df["overlap_start"]) + df["group"] = df["no_overlap"].cumsum() + + # now use groupby on 'group'. If one left and one right eye in group + # the new start/end times are the mean of the two eyes + ovrlp = pd.concat( + [ + pd.DataFrame(g[1].drop(columns="eye").mean()).T + if (len(g[1]) == 2) and (len(g[1].eye.unique()) == 2) + else g[1] # not an overlap, return group unchanged + for g in df.groupby("group") + ] + ) + # overlapped events get a "both" value in the "eye" col + if "eye" in ovrlp.columns: + ovrlp["eye"] = ovrlp["eye"].fillna("both") + else: + ovrlp["eye"] = "both" + tmp_cols = ["overlap_start", "overlap_end", "no_overlap", "group"] + return ovrlp.drop(columns=tmp_cols).reset_index(drop=True) + + +def _convert_href_samples(samples_df): + """Convert HREF eyegaze samples to radians.""" + # grab the xpos and ypos channel names + pos_names = EYELINK_COLS["pos"]["left"][:-1] + EYELINK_COLS["pos"]["right"][:-1] + for col in samples_df.columns: + if col not in pos_names: # 'xpos_left' ... 'ypos_right' + continue + series = _href_to_radian(samples_df[col]) + samples_df[col] = series + return samples_df + + +def _href_to_radian(opposite, f=15_000): + """Convert HREF eyegaze samples to radians. + + Parameters + ---------- + opposite : int + The x or y coordinate in an HREF gaze sample. + f : int (default 15_000) + distance of plane from the eye. Defaults to 15,000 units, which was taken + from the Eyelink 1000 plus user manual. + + Returns + ------- + x or y coordinate in radians + + Notes + ----- + See section 4.4.2.2 in the Eyelink 1000 Plus User Manual + (version 1.0.19) for a detailed description of HREF data. + """ + return np.arcsin(opposite / f) + + +def _create_info(ch_names, raw_extras): + """Create info object for RawEyelink.""" + # assign channel type from ch_name + pos_names = EYELINK_COLS["pos"]["left"][:-1] + EYELINK_COLS["pos"]["right"][:-1] + pupil_names = EYELINK_COLS["pos"]["left"][-1] + EYELINK_COLS["pos"]["right"][-1] + ch_types = [ + "eyegaze" + if ch in pos_names + else "pupil" + if ch in pupil_names + else "stim" + if ch == "DIN" + else "misc" + for ch in ch_names + ] + info = create_info(ch_names, raw_extras["sfreq"], ch_types) + # set correct loc for eyepos and pupil channels + for ch_dict in info["chs"]: + # loc index 3 can indicate left or right eye + if ch_dict["ch_name"].endswith("left"): # [x,y,pupil]_left + ch_dict["loc"][3] = -1 # left eye + elif ch_dict["ch_name"].endswith("right"): # [x,y,pupil]_right + ch_dict["loc"][3] = 1 # right eye + else: + logger.debug( + f"leaving index 3 of loc array as" + f" {ch_dict['loc'][3]} for {ch_dict['ch_name']}" + ) + # loc index 4 can indicate x/y coord + if ch_dict["ch_name"].startswith("x"): + ch_dict["loc"][4] = -1 # x-coord + elif ch_dict["ch_name"].startswith("y"): + ch_dict["loc"][4] = 1 # y-coord + else: + logger.debug( + f"leaving index 4 of loc array as" + f" {ch_dict['loc'][4]} for {ch_dict['ch_name']}" + ) + if raw_extras["pos_unit"] == "HREF": + if ch_dict["ch_name"].startswith(("xpos", "ypos")): + ch_dict["unit"] = FIFF.FIFF_UNIT_RAD + return info + + +def _make_eyelink_annots(df_dict, create_annots, apply_offsets): + """Create Annotations for each df in raw_extras.""" + eye_ch_map = { + "L": ("xpos_left", "ypos_left", "pupil_left"), + "R": ("xpos_right", "ypos_right", "pupil_right"), + "both": ( + "xpos_left", + "ypos_left", + "pupil_left", + "xpos_right", + "ypos_right", + "pupil_right", + ), + } + valid_descs = ["blinks", "saccades", "fixations", "buttons", "messages"] + msg = ( + "create_annotations must be True or a list containing one or" + f" more of {valid_descs}." + ) + wrong_type = msg + f" Got a {type(create_annots)} instead." + if create_annots is True: + descs = valid_descs + else: + if not isinstance(create_annots, list): + raise TypeError(wrong_type) + for desc in create_annots: + if desc not in valid_descs: + raise ValueError(msg + f" Got '{desc}' instead") + descs = create_annots + + annots = None + for key, df in df_dict.items(): + eye_annot_cond = (key in ["blinks", "fixations", "saccades"]) and (key in descs) + if eye_annot_cond: + onsets = df["time"] + durations = df["duration"] + # Create annotations for both eyes + descriptions = key[:-1] # i.e "blink", "fixation", "saccade" + if key == "blinks": + descriptions = "BAD_" + descriptions + + ch_names = df["eye"].map(eye_ch_map).tolist() + this_annot = Annotations( + onset=onsets, + duration=durations, + description=descriptions, + ch_names=ch_names, + ) + elif (key in ["messages"]) and (key in descs): + if apply_offsets: + # If df['offset] is all NaNs, time is not changed + onsets = df["time"] + df["offset"].fillna(0) + else: + onsets = df["time"] + durations = [0] * onsets + descriptions = df["event_msg"] + this_annot = Annotations( + onset=onsets, duration=durations, description=descriptions + ) + elif (key == "buttons") and (key in descs): + required_cols = {"time", "button_id", "button_pressed"} + if not required_cols.issubset(df.columns): + raise ValueError(f"Missing column: {required_cols - set(df.columns)}") + # Give user a hint + n_presses = df["button_pressed"].sum() + logger.info("Found %d button press events.", n_presses) + + df = df.sort_values("time") + onsets = df["time"] + durations = np.zeros_like(onsets) + descriptions = df.apply(_get_button_description, axis=1) + + this_annot = Annotations( + onset=onsets, duration=durations, description=descriptions + ) + else: + continue + if not annots: + annots = this_annot + elif annots: + annots += this_annot + if not annots: + warn(f"Annotations for {descs} were requested but none could be made.") + return + + return annots + + +def _get_button_description(row): + button_id = int(row["button_id"]) + action = "press" if row["button_pressed"] == 1 else "release" + return f"button_{button_id}_{action}" + + +def _make_gap_annots(raw_extras, key="recording_blocks"): + """Create Annotations for gap periods between recording blocks.""" + df = raw_extras["dfs"][key] + onsets = df["end_time"].iloc[:-1] + diffs = df["time"].shift(-1) - df["end_time"] + durations = diffs.iloc[:-1] + descriptions = ["BAD_ACQ_SKIP"] * len(onsets) + return Annotations(onset=onsets, duration=durations, description=descriptions) + + +# ======================== Used by read_eyelink-calibration =========================== + + +def _find_recording_start(lines): + """Return the first START line in an SR Research EyeLink ASCII file. + + Parameters + ---------- + lines: A list of strings, which are The lines in an eyelink ASCII file. + + Returns + ------- + The line that contains the info on the start of the recording. + """ + for line in lines: + if line.startswith("START"): + return line + raise ValueError("Could not find the start of the recording.") + + +def _parse_validation_line(line): + """Parse a single line of eyelink validation data. + + Parameters + ---------- + line: A string containing a line of validation data from an eyelink + ASCII file. + + Returns + ------- + A list of tuples containing the validation data. + """ + tokens = line.split() + xy = tokens[-6].strip("[]").split(",") # e.g. '960, 540' + xy_diff = tokens[-2].strip("[]").split(",") # e.g. '-1.5, -2.8' + vals = [float(v) for v in [*xy, tokens[-4], *xy_diff]] + vals[3] += vals[0] # pos_x + eye_x i.e. 960 + -1.5 + vals[4] += vals[1] # pos_y + eye_y + + return tuple(vals) + + +def _parse_calibration( + lines, screen_size=None, screen_distance=None, screen_resolution=None +): + """Parse the lines in the given list and returns a list of Calibration instances. + + Parameters + ---------- + lines: A list of strings, which are The lines in an eyelink ASCII file. + + Returns + ------- + A list containing one or more Calibration instances, + one for each calibration that was recorded in the eyelink ASCII file + data. + """ + from ...preprocessing.eyetracking.calibration import Calibration + + regex = re.compile(r"\d+") # for finding numeric characters + calibrations = list() + rec_start = float(_find_recording_start(lines).split()[1]) + + for line_number, line in enumerate(lines): + if ( + "!CAL VALIDATION " in line and "ABORTED" not in line + ): # Start of a calibration + tokens = line.split() + model = tokens[4] # e.g. 'HV13' + this_eye = tokens[6].lower() # e.g. 'left' + timestamp = float(tokens[1]) + onset = (timestamp - rec_start) / 1000.0 # in seconds + avg_error = float(line.split("avg.")[0].split()[-1]) # e.g. 0.3 + max_error = float(line.split("max")[0].split()[-1]) # e.g. 0.9 + + n_points = int(regex.search(model).group()) # e.g. 13 + n_points *= 2 if "LR" in line else 1 # one point per eye if "LR" + + # The next n_point lines contain the validation data + points = [] + line_idx = line_number + 1 + read_points = 0 + while read_points < n_points and line_idx < len(lines): + subline = lines[line_idx].strip() + line_idx += 1 + + if not subline or "!CAL VALIDATION" in subline: + continue # for bino mode, skip the second eye's validation summary + + subline_eye = subline.split("at")[0].split()[-1].lower() # e.g. 'left' + if subline_eye != this_eye: + continue # skip the validation lines for the other eye + point_info = _parse_validation_line(subline) + points.append(point_info) + read_points += 1 + # Convert the list of validation data into a numpy array + positions = np.array([point[:2] for point in points]) + offsets = np.array([point[2] for point in points]) + gaze = np.array([point[3:] for point in points]) + # create the Calibration instance + calibration = Calibration( + onset=onset, + model=model, + eye=this_eye, + avg_error=avg_error, + max_error=max_error, + positions=positions, + offsets=offsets, + gaze=gaze, + screen_size=screen_size, + screen_distance=screen_distance, + screen_resolution=screen_resolution, + ) + calibrations.append(calibration) + return calibrations diff --git a/mne-python/source/mne/io/eyelink/eyelink.py b/mne-python/source/mne/io/eyelink/eyelink.py new file mode 100644 index 0000000000000000000000000000000000000000..192a5555465a82c2bcbb85869ac5f027b40793d5 --- /dev/null +++ b/mne-python/source/mne/io/eyelink/eyelink.py @@ -0,0 +1,133 @@ +"""SR Research Eyelink Load Function.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +from ...utils import ( + _check_fname, + fill_doc, + logger, + verbose, +) +from ..base import BaseRaw +from ._utils import _make_eyelink_annots, _make_gap_annots, _parse_eyelink_ascii + + +@fill_doc +def read_raw_eyelink( + fname, + *, + create_annotations=True, + apply_offsets=False, + find_overlaps=False, + overlap_threshold=0.05, + verbose=None, +) -> "RawEyelink": + """Reader for an Eyelink ``.asc`` file. + + Parameters + ---------- + %(eyelink_fname)s + %(eyelink_create_annotations)s + %(eyelink_apply_offsets)s + %(eyelink_find_overlaps)s + %(eyelink_overlap_threshold)s + %(verbose)s + + Returns + ------- + raw : instance of RawEyelink + A Raw object containing eyetracker data. + + See Also + -------- + mne.io.Raw : Documentation of attribute and methods. + + Notes + ----- + It is common for SR Research Eyelink eye trackers to only record data during trials. + To avoid frequent data discontinuities and to ensure that the data is continuous + so that it can be aligned with EEG and MEG data (if applicable), this reader will + preserve the times between recording trials and annotate them with + ``'BAD_ACQ_SKIP'``. + """ + fname = _check_fname(fname, overwrite="read", must_exist=True, name="fname") + + raw_eyelink = RawEyelink( + fname, + create_annotations=create_annotations, + apply_offsets=apply_offsets, + find_overlaps=find_overlaps, + overlap_threshold=overlap_threshold, + verbose=verbose, + ) + return raw_eyelink + + +@fill_doc +class RawEyelink(BaseRaw): + """Raw object from an XXX file. + + Parameters + ---------- + %(eyelink_fname)s + %(eyelink_create_annotations)s + %(eyelink_apply_offsets)s + %(eyelink_find_overlaps)s + %(eyelink_overlap_threshold)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attribute and methods. + """ + + @verbose + def __init__( + self, + fname, + *, + create_annotations=True, + apply_offsets=False, + find_overlaps=False, + overlap_threshold=0.05, + verbose=None, + ): + logger.info(f"Loading {fname}") + + fname = Path(fname) + + # ======================== Parse ASCII file ========================== + eye_ch_data, info, raw_extras = _parse_eyelink_ascii( + fname, find_overlaps, overlap_threshold, apply_offsets + ) + # ======================== Create Raw Object ========================= + super().__init__( + info, + preload=eye_ch_data, + filenames=[fname], + verbose=verbose, + raw_extras=[raw_extras], + ) + self.set_meas_date(self._raw_extras[0]["dt"]) + + # ======================== Make Annotations ========================= + gap_annots = None + if self._raw_extras[0]["n_blocks"] > 1: + gap_annots = _make_gap_annots(self._raw_extras[0]) + eye_annots = None + if create_annotations: + eye_annots = _make_eyelink_annots( + self._raw_extras[0]["dfs"], create_annotations, apply_offsets + ) + if gap_annots and eye_annots: # set both + self.set_annotations(gap_annots + eye_annots) + elif gap_annots: + self.set_annotations(gap_annots) + elif eye_annots: + self.set_annotations(eye_annots) + else: + logger.info("Not creating any annotations") diff --git a/mne-python/source/mne/io/eyelink/tests/__init__.py b/mne-python/source/mne/io/eyelink/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/eyelink/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/eyelink/tests/test_eyelink.py b/mne-python/source/mne/io/eyelink/tests/test_eyelink.py new file mode 100644 index 0000000000000000000000000000000000000000..ae47bc9704f24bcbddc24f36b83ff561f2aff2f5 --- /dev/null +++ b/mne-python/source/mne/io/eyelink/tests/test_eyelink.py @@ -0,0 +1,526 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose + +from mne import find_events +from mne._fiff.constants import FIFF +from mne._fiff.pick import _DATA_CH_TYPES_SPLIT, _PICK_TYPES_DATA_DICT +from mne.datasets.testing import data_path, requires_testing_data +from mne.io import read_raw_eyelink +from mne.io.eyelink._utils import _adjust_times, _find_overlaps +from mne.io.tests.test_raw import _test_raw_reader +from mne.utils import _record_warnings + +pd = pytest.importorskip("pandas") + +MAPPING = { + "left": ["xpos_left", "ypos_left", "pupil_left"], + "right": ["xpos_right", "ypos_right", "pupil_right"], + "both": [ + "xpos_left", + "ypos_left", + "pupil_left", + "xpos_right", + "ypos_right", + "pupil_right", + ], +} + +testing_path = data_path(download=False) +fname = testing_path / "eyetrack" / "test_eyelink.asc" +fname_href = testing_path / "eyetrack" / "test_eyelink_HREF.asc" + + +def test_eyetrack_not_data_ch(): + """Eyetrack channels are not data channels.""" + msg = ( + "eyetrack channels are not data channels. Refer to MNE definition" + " of data channels in the glossary section of the documentation." + ) + assert "eyegaze" not in _DATA_CH_TYPES_SPLIT, msg + assert "pupil" not in _DATA_CH_TYPES_SPLIT, msg + assert not _PICK_TYPES_DATA_DICT["eyetrack"], msg + + +@requires_testing_data +@pytest.mark.parametrize( + "fname, create_annotations, find_overlaps, apply_offsets", + [ + (fname, False, False, False), + ( + fname, + False, + False, + False, + ), + ( + fname, + True, + False, + False, + ), + ( + fname, + True, + True, + True, + ), + ( + fname, + ["fixations", "saccades", "blinks"], + True, + False, + ), + ], +) +def test_eyelink(fname, create_annotations, find_overlaps, apply_offsets): + """Test reading eyelink asc files.""" + raw = read_raw_eyelink( + fname, + create_annotations=create_annotations, + find_overlaps=find_overlaps, + apply_offsets=apply_offsets, + ) + + # First, tests that shouldn't change based on function arguments + assert raw.info["sfreq"] == 500 # True for this file + assert raw.info["meas_date"].month == 3 + assert raw.info["meas_date"].day == 10 + assert raw.info["meas_date"].year == 2022 + + assert len(raw.info["ch_names"]) == 6 + assert raw.info["chs"][0]["kind"] == FIFF.FIFFV_EYETRACK_CH + assert raw.info["chs"][0]["coil_type"] == FIFF.FIFFV_COIL_EYETRACK_POS + raw.info["chs"][2]["coil_type"] == FIFF.FIFFV_COIL_EYETRACK_PUPIL + + # x_left + assert all(raw.info["chs"][0]["loc"][3:5] == [-1, -1]) + # pupil_left + assert raw.info["chs"][2]["loc"][3] == -1 + assert np.isnan(raw.info["chs"][2]["loc"][4]) + # y_right + assert all(raw.info["chs"][4]["loc"][3:5] == [1, 1]) + assert "RawEyelink" in repr(raw) + + # Test some annotation values for accuracy. + if create_annotations is True and find_overlaps: + orig = raw.info["meas_date"] + df = raw.annotations.to_data_frame() + # Convert annot onset datetimes to seconds, relative to orig_time + df["time_in_sec"] = df["onset"].apply( + lambda x: x.timestamp() - orig.timestamp() + ) + # There is a blink in this data at 8.9 seconds + cond = (df["time_in_sec"] > 8.899) & (df["time_in_sec"] < 8.95) + assert df[cond]["description"].values[0].startswith("BAD_blink") + + # Check that the annotation ch_names are set correctly + assert np.array_equal(raw.annotations[0]["ch_names"], MAPPING["both"]) + + if isinstance(create_annotations, list) and find_overlaps: + # the last pytest parametrize condition should hit this + assert np.array_equal(raw.annotations[0]["ch_names"], MAPPING["both"]) + + +@requires_testing_data +@pytest.mark.parametrize("fname_href", [(fname_href)]) +def test_radian(fname_href): + """Test converting HREF position data to radians.""" + with pytest.warns(RuntimeWarning, match="Annotations for"): + raw = read_raw_eyelink(fname_href, create_annotations=["blinks"]) + # Test channel types + assert raw.get_channel_types() == ["eyegaze", "eyegaze", "pupil"] + + # Test that eyegaze channels have a radian unit + assert raw.info["chs"][0]["unit"] == FIFF.FIFF_UNIT_RAD + assert raw.info["chs"][1]["unit"] == FIFF.FIFF_UNIT_RAD + + # Data in radians should range between -1 and 1 + # Test first channel (xpos_right) + assert raw.get_data()[0].min() > -1 + assert raw.get_data()[0].max() < 1 + + +@requires_testing_data +@pytest.mark.parametrize("fname", [(fname)]) +def test_fill_times(fname): + """Test use of pd.merge_asof in _fill_times. + + We are merging on floating + point values. pd.merge_asof is used so that any differences in floating + point precision between df['samples']['times'] and the times generated + with np.arange don't result in the time columns not merging + correctly - i.e. 1560687.0 and 1560687.000001 should merge. + """ + raw = read_raw_eyelink(fname, create_annotations=False) + sfreq = raw.info["sfreq"] + # just take first 1000 points for testing + df = raw.to_data_frame()[:1000] + # even during blinks, pupil val is 0, so there should be no nans + # in this column + assert not df["pupil_left"].isna().sum() + nan_count = df["pupil_left"].isna().sum() # i.e 0 + df_merged = _adjust_times(df, sfreq) + # If times dont merge correctly, there will be additional rows in + # in df_merged with all nan values + assert df_merged["pupil_left"].isna().sum() == nan_count # i.e. 0 + + +def test_find_overlaps(): + """Test finding overlapping occular events between the left and right eyes. + + In the simulated blink df below, the first two rows + will be considered an overlap because the diff() of both the 'time' and + 'end_time' values is <.05 (50ms). the 3rd and 4th rows will not be + considered an overlap because the diff() of the 'time' values is > .05 + (4.20 - 4.14 = .06). The 5th and 6th rows will not be considered an + overlap because they are both left eye events. + """ + blink_df = pd.DataFrame( + { + "eye": ["L", "R", "L", "R", "L", "L"], + "time": [0.01, 0.04, 4.14, 4.20, 6.50, 6.504], + "end_time": [0.05, 0.08, 4.18, 4.22, 6.60, 6.604], + } + ) + overlap_df = _find_overlaps(blink_df) + assert len(overlap_df["eye"].unique()) == 3 # ['both', 'left', 'right'] + assert len(overlap_df) == 5 # ['both', 'L', 'R', 'L', 'L'] + assert overlap_df["eye"].iloc[0] == "both" + + +@requires_testing_data +@pytest.mark.parametrize("fname", [fname]) +def test_bino_to_mono(tmp_path, fname): + """Test a file that switched from binocular to monocular mid-recording.""" + out_file = tmp_path / "tmp_eyelink.asc" + in_file = Path(fname) + lines = in_file.read_text("utf-8").splitlines() + # We'll also add some binocular velocity data to increase our testing coverage. + start_idx = [li for li, line in enumerate(lines) if line.startswith("START")][0] + for li, line in enumerate(lines[start_idx:-2], start=start_idx): + tokens = line.split("\t") + event_type = tokens[0] + if event_type == "SAMPLES": + tokens.insert(3, "VEL") + lines[li] = "\t".join(tokens) + elif event_type.isnumeric(): + # fake velocity values for x/y left/right + tokens[4:4] = ["999.1", "999.2", "999.3", "999.4"] + lines[li] = "\t".join(tokens) + end_line = lines[-2] + end_ts = int(end_line.split("\t")[1]) + # Now only left eye data + second_block = [] + new_ts = end_ts + 1 + info = [ + "GAZE", + "LEFT", + "VEL", + "RATE", + "500.00", + "TRACKING", + "CR", + "FILTER", + "2", + ] + start = ["START", f"{new_ts}", "LEFT", "SAMPLES", "EVENTS"] + pupil = ["PUPIL", "DIAMETER"] + samples = ["SAMPLES"] + info + events = ["EVENTS"] + info + second_block.append("\t".join(start) + "\n") + second_block.append("\t".join(pupil) + "\n") + second_block.append("\t".join(samples) + "\n") + second_block.append("\t".join(events) + "\n") + # Some fake data.. # x, y, pupil, velicty x/y status + left = ["960", "540", "0.0", "999.1", "999.2", "..."] + NUM_FAKE_SAMPLES = 4000 + for ii in range(NUM_FAKE_SAMPLES): + ts = new_ts + ii + tokens = [f"{ts}"] + left + second_block.append("\t".join(tokens) + "\n") + # interleave some events into the second block + duration = 500 + blink_ts = new_ts + 500 + end_blink = ["EBLINK", "L", f"{blink_ts}", f"{blink_ts + 50}", "106"] + fix_ts = new_ts + 1500 + end_fix = [ + "EFIX", + "L", + f"{fix_ts}", + f"{fix_ts + duration}", + "1616", + "1025.1", + "580.9", + "1289", + ] + sacc_ts = new_ts + 2500 + end_sacc = [ + "ESACC", + "L", + f"{sacc_ts}", + f"{sacc_ts + duration}", + "52", + "1029.6", + "582.3", + "581.7", + "292.5", + "10.30", + "387", + ] + second_block.append("\t".join(end_blink) + "\n") + second_block.append("\t".join(end_fix) + "\n") + second_block.append("\t".join(end_sacc) + "\n") + end_ts = ts + 1 + end_block = ["END", f"{end_ts}", "SAMPLES", "EVENTS", "RES", "45", "45"] + second_block.append("\t".join(end_block)) + lines += second_block + out_file.write_text("\n".join(lines), encoding="utf-8") + + with pytest.warns( + RuntimeWarning, match="This recording switched between monocular and binocular" + ): + raw = read_raw_eyelink(out_file) + want_channels = [ + "xpos_left", + "ypos_left", + "pupil_left", + "xpos_right", + "ypos_right", + "pupil_right", + "xvel_left", + "yvel_left", + "xvel_right", + "yvel_right", + ] + assert len(set(raw.info["ch_names"]).difference(set(want_channels))) == 0 + + +def _simulate_eye_tracking_data(in_file, out_file): + out_file = Path(out_file) + + new_samples_line = ( + "SAMPLES\tPUPIL\tLEFT\tVEL\tRES\tHTARGET\tRATE\t1000.00" + "\tTRACKING\tCR\tFILTER\t2\tINPUT" + ) + + # Define your known BUTTON events + button_events = [ + (7453390, 1, 1), + (7453410, 1, 0), + (7453420, 1, 1), + (7453430, 1, 0), + (7453440, 1, 1), + (7453450, 1, 0), + ] + button_idx = 0 + + with out_file.open("w") as fp: + in_recording_block = False + events = [] + + for line in Path(in_file).read_text().splitlines(): + if line.startswith("START"): + in_recording_block = True + if in_recording_block: + tokens = line.split() + event_type = tokens[0] + if event_type.isnumeric(): # samples + tokens[4:4] = ["100", "20", "45", "45", "127.0"] # vel, res, DIN + tokens.extend(["1497.0", "5189.0", "512.5", "............."]) + elif event_type in ("EFIX", "ESACC"): + if event_type == "ESACC": + tokens[5:7] = [".", "."] # pretend start pos is unknown + tokens.extend(["45", "45"]) # resolution + elif event_type == "SAMPLES": + tokens[1] = "PUPIL" # simulate raw coordinate data + tokens[3:3] = ["VEL", "RES", "HTARGET"] + tokens.append("INPUT") + elif event_type == "EBLINK": + continue # simulate no blink events + + elif event_type == "END": + pass + else: + fp.write(f"{line}\n") + continue + events.append("\t".join(tokens)) + if event_type == "END": + fp.write("\n".join(events) + "\n") + events.clear() + in_recording_block = False + else: + fp.write(f"{line}\n") + + fp.write("START\t7452389\tRIGHT\tSAMPLES\tEVENTS\n") + fp.write(f"{new_samples_line}\n") + + for timestamp in np.arange(7452389, 7453390): # simulate a second block + fp.write( + f"{timestamp}\t-2434.0\t-1760.0\t840.0\t100\t20\t45\t45\t127.0\t" + "...\t1497\t5189\t512.5\t.............\n" + ) + + for timestamp in np.arange(7453390, 7453490): # 100 samples 7453100 + fp.write( + f"{timestamp}\t-2434.0\t-1760.0\t840.0\t100\t20\t45\t45\t127.0\t" + "...\t1497\t5189\t512.5\t.............\n" + ) + # Check and insert button events at this timestamp + if ( + button_idx < len(button_events) + and button_events[button_idx][0] == timestamp + ): + t, btn_id, state = button_events[button_idx] + fp.write( + f"BUTTON\t{t}\t{btn_id}\t{state}\t100\t20\t45\t45\t127.0\t" + "1497.0\t5189.0\t512.5\t.............\n" + ) + button_idx += 1 + fp.write("END\t7453390\tRIGHT\tSAMPLES\tEVENTS\n") + + +@requires_testing_data +@pytest.mark.parametrize("fname", [fname_href]) +def test_multi_block_misc_channels(fname, tmp_path): + """Test a file with many edge casses. + + This file has multiple acquisition blocks, each tracking a different eye. + The coordinates are in raw units (not pixels or radians). + It has some misc channels (head position, saccade velocity, etc.) + """ + out_file = tmp_path / "tmp_eyelink.asc" + _simulate_eye_tracking_data(fname, out_file) + + with ( + _record_warnings(), + pytest.warns(RuntimeWarning, match="Raw eyegaze coordinates"), + pytest.warns(RuntimeWarning, match="The eye being tracked changed"), + ): + raw = read_raw_eyelink(out_file, apply_offsets=True) + + chs_in_file = [ + "xpos_right", + "ypos_right", + "pupil_right", + "xvel_right", + "yvel_right", + "xres", + "yres", + "DIN", + "x_head", + "y_head", + "distance", + "xpos_left", + "ypos_left", + "pupil_left", + "xvel_left", + "yvel_left", + ] + + assert raw.ch_names == chs_in_file + assert raw.annotations.description[1] == "SYNCTIME" + + assert raw.annotations.description[-7] == "BAD_ACQ_SKIP" + assert np.isclose(raw.annotations.onset[-7], 1.001) + assert np.isclose(raw.annotations.duration[-7], 0.1) + + data, times = raw.get_data(return_times=True) + assert not np.isnan(data[0, np.where(times < 1)[0]]).any() + assert np.isnan(data[0, np.logical_and(times > 1, times <= 1.1)]).all() + + assert raw.annotations.description[-6] == "button_1_press" + button_idx = [ + ii + for ii, desc in enumerate(raw.annotations.description) + if "button" in desc.lower() + ] + assert len(button_idx) == 6 + assert_allclose(raw.annotations.onset[button_idx[0]], 2.102, atol=1e-3) + + # smoke test for reading events with missing samples (should not emit a warning) + find_events(raw, verbose=True) + + +@requires_testing_data +@pytest.mark.parametrize("this_fname", (fname, fname_href)) +def test_basics(this_fname): + """Test basics of reading.""" + _test_raw_reader(read_raw_eyelink, fname=this_fname, test_preloading=False) + + +@requires_testing_data +def test_annotations_without_offset(tmp_path): + """Test read of annotations without offset.""" + out_file = tmp_path / "tmp_eyelink.asc" + + # create fake dataset + with open(fname_href) as file: + lines = file.readlines() + ts = lines[-3].split("\t")[0] + line = f"MSG\t{ts} test string\n" + lines = lines[:-3] + [line] + lines[-3:] + with open(out_file, "w") as file: + file.writelines(lines) + + raw = read_raw_eyelink(out_file, apply_offsets=False) + assert raw.annotations[-1]["description"] == "test string" + onset1 = raw.annotations[-1]["onset"] + assert raw.annotations[1]["description"] == "-2 SYNCTIME" + onset2 = raw.annotations[1]["onset"] + + raw = read_raw_eyelink(out_file, apply_offsets=True) + assert raw.annotations[-1]["description"] == "test string" + assert raw.annotations[1]["description"] == "SYNCTIME" + assert_allclose(raw.annotations[-1]["onset"], onset1) + assert_allclose(raw.annotations[1]["onset"], onset2 - 2 / raw.info["sfreq"]) + + +@requires_testing_data +def test_no_datetime(tmp_path): + """Test reading a file with no datetime.""" + out_file = tmp_path / "tmp_eyelink.asc" + with open(fname) as file: + lines = file.readlines() + # remove the timestamp from the datetime line + lines[1] = lines[1].split(":")[0] + ":" + with open(out_file, "w") as file: + file.writelines(lines) + raw = read_raw_eyelink(out_file) + assert raw.info["meas_date"] is None + # Sanity check that a None meas_date doesn't change annotation times + # First annotation in this file is a fixation at 0.004 seconds + np.testing.assert_allclose(raw.annotations.onset[0], 0.004) + + +@requires_testing_data +def test_href_eye_events(tmp_path): + """Test Parsing file where Eye Event Data option was set to 'HREF'.""" + out_file = tmp_path / "tmp_eyelink.asc" + lines = fname_href.read_text("utf-8").splitlines() + + for li, line in enumerate(lines): + if not line.startswith(("ESACC", "EFIX")): + continue + tokens = line.split() + if line.startswith("ESACC"): + href_sacc_vals = ["9999", "9999", "9999", "9999", "99.99", "999"] + tokens[5:5] = href_sacc_vals # add href saccade values + elif line.startswith("EFIX"): + tokens = line.split() + href_fix_vals = ["9999.9", "9999.9", "999"] + tokens[5:3] = href_fix_vals + new_line = "\t".join(tokens) + "\n" + lines[li] = new_line + out_file.write_text("\n".join(lines), encoding="utf-8") + + raw = read_raw_eyelink(out_file) + # Just check that we actually parsed the Saccade and Fixation events + assert "saccade" in raw.annotations.description + assert "fixation" in raw.annotations.description diff --git a/mne-python/source/mne/io/fieldtrip/__init__.py b/mne-python/source/mne/io/fieldtrip/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..efdd3d2eda68901d2a88abd0b77f37138f4771ab --- /dev/null +++ b/mne-python/source/mne/io/fieldtrip/__init__.py @@ -0,0 +1,5 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .fieldtrip import read_evoked_fieldtrip, read_epochs_fieldtrip, read_raw_fieldtrip diff --git a/mne-python/source/mne/io/fieldtrip/fieldtrip.py b/mne-python/source/mne/io/fieldtrip/fieldtrip.py new file mode 100644 index 0000000000000000000000000000000000000000..c85217220030c02a20abc20ccf699ec0b4e2f46f --- /dev/null +++ b/mne-python/source/mne/io/fieldtrip/fieldtrip.py @@ -0,0 +1,185 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ...epochs import EpochsArray +from ...evoked import EvokedArray +from ...utils import _check_fname, _import_pymatreader_funcs +from ..array._array import RawArray +from .utils import ( + _create_event_metadata, + _create_events, + _create_info, + _set_tmin, + _validate_ft_struct, +) + + +def read_raw_fieldtrip(fname, info, data_name="data") -> RawArray: + """Load continuous (raw) data from a FieldTrip preprocessing structure. + + This function expects to find single trial raw data (FT_DATATYPE_RAW) in + the structure data_name is pointing at. + + .. warning:: FieldTrip does not normally store the original information + concerning channel location, orientation, type etc. It is + therefore **highly recommended** to provide the info field. + This can be obtained by reading the original raw data file + with MNE functions (without preload). The returned object + contains the necessary info field. + + Parameters + ---------- + fname : path-like + Path and filename of the ``.mat`` file containing the data. + info : dict or None + The info dict of the raw data file corresponding to the data to import. + If this is set to None, limited information is extracted from the + FieldTrip structure. + data_name : str + Name of heading dict/variable name under which the data was originally + saved in MATLAB. + + Returns + ------- + raw : instance of RawArray + A Raw Object containing the loaded data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawArray. + """ + read_mat = _import_pymatreader_funcs("FieldTrip I/O") + fname = _check_fname(fname, overwrite="read", must_exist=True) + + ft_struct = read_mat(fname, ignore_fields=["previous"], variable_names=[data_name]) + + # load data and set ft_struct to the heading dictionary + ft_struct = ft_struct[data_name] + + _validate_ft_struct(ft_struct) + + info = _create_info(ft_struct, info) # create info structure + data = np.array(ft_struct["trial"]) # create the main data array + + if data.ndim > 2: + data = np.squeeze(data) + + if data.ndim == 1: + data = data[np.newaxis, ...] + + if data.ndim != 2: + raise RuntimeError( + "The data you are trying to load does not seem to be raw data" + ) + + raw = RawArray(data, info) # create an MNE RawArray + return raw + + +def read_epochs_fieldtrip( + fname, info, data_name="data", trialinfo_column=0 +) -> EpochsArray: + """Load epoched data from a FieldTrip preprocessing structure. + + This function expects to find epoched data in the structure data_name is + pointing at. + + .. warning:: Only epochs with the same amount of channels and samples are + supported! + + .. warning:: FieldTrip does not normally store the original information + concerning channel location, orientation, type etc. It is + therefore **highly recommended** to provide the info field. + This can be obtained by reading the original raw data file + with MNE functions (without preload). The returned object + contains the necessary info field. + + Parameters + ---------- + fname : path-like + Path and filename of the ``.mat`` file containing the data. + info : dict or None + The info dict of the raw data file corresponding to the data to import. + If this is set to None, limited information is extracted from the + FieldTrip structure. + data_name : str + Name of heading dict/ variable name under which the data was originally + saved in MATLAB. + trialinfo_column : int + Column of the trialinfo matrix to use for the event codes. + + Returns + ------- + epochs : instance of EpochsArray + An EpochsArray containing the loaded data. + """ + read_mat = _import_pymatreader_funcs("FieldTrip I/O") + ft_struct = read_mat(fname, ignore_fields=["previous"], variable_names=[data_name]) + + # load data and set ft_struct to the heading dictionary + ft_struct = ft_struct[data_name] + + _validate_ft_struct(ft_struct) + + info = _create_info(ft_struct, info) # create info structure + data = np.array(ft_struct["trial"]) # create the epochs data array + events = _create_events(ft_struct, trialinfo_column) + if events is not None: + metadata = _create_event_metadata(ft_struct) + else: + metadata = None + tmin = _set_tmin(ft_struct) # create start time + + epochs = EpochsArray( + data=data, info=info, tmin=tmin, events=events, metadata=metadata, proj=False + ) + return epochs + + +def read_evoked_fieldtrip(fname, info, comment=None, data_name="data"): + """Load evoked data from a FieldTrip timelocked structure. + + This function expects to find timelocked data in the structure data_name is + pointing at. + + .. warning:: FieldTrip does not normally store the original information + concerning channel location, orientation, type etc. It is + therefore **highly recommended** to provide the info field. + This can be obtained by reading the original raw data file + with MNE functions (without preload). The returned object + contains the necessary info field. + + Parameters + ---------- + fname : path-like + Path and filename of the ``.mat`` file containing the data. + info : dict or None + The info dict of the raw data file corresponding to the data to import. + If this is set to None, limited information is extracted from the + FieldTrip structure. + comment : str + Comment on dataset. Can be the condition. + data_name : str + Name of heading dict/ variable name under which the data was originally + saved in MATLAB. + + Returns + ------- + evoked : instance of EvokedArray + An EvokedArray containing the loaded data. + """ + read_mat = _import_pymatreader_funcs("FieldTrip I/O") + ft_struct = read_mat(fname, ignore_fields=["previous"], variable_names=[data_name]) + ft_struct = ft_struct[data_name] + + _validate_ft_struct(ft_struct) + + info = _create_info(ft_struct, info) # create info structure + data_evoked = ft_struct["avg"] # create evoked data + + evoked = EvokedArray(data_evoked, info, comment=comment) + return evoked diff --git a/mne-python/source/mne/io/fieldtrip/tests/__init__.py b/mne-python/source/mne/io/fieldtrip/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/fieldtrip/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/fieldtrip/tests/helpers.py b/mne-python/source/mne/io/fieldtrip/tests/helpers.py new file mode 100644 index 0000000000000000000000000000000000000000..0a0f6671d6bca40396104f90a209058b59ba3865 --- /dev/null +++ b/mne-python/source/mne/io/fieldtrip/tests/helpers.py @@ -0,0 +1,245 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +from functools import partial + +import numpy as np + +import mne +from mne.utils import object_diff + +info_ignored_fields = ( + "file_id", + "hpi_results", + "hpi_meas", + "meas_id", + "meas_date", + "highpass", + "lowpass", + "subject_info", + "hpi_subsystem", + "experimenter", + "description", + "proj_id", + "proj_name", + "line_freq", + "gantry_angle", + "dev_head_t", + "bads", + "ctf_head_t", + "dev_ctf_t", + "dig", +) + +ch_ignore_fields = ( + "logno", + "cal", + "range", + "scanno", + "coil_type", + "kind", + "loc", + "coord_frame", + "unit", +) + +info_long_fields = ("hpi_meas", "projs") + +system_to_reader_fn_dict = { + "neuromag306": mne.io.read_raw_fif, + "CNT": partial(mne.io.read_raw_cnt), + "CTF": partial(mne.io.read_raw_ctf, clean_names=True), + "BTI": partial( + mne.io.read_raw_bti, + head_shape_fname=None, + rename_channels=False, + sort_by_ch_name=False, + ), + "EGI": mne.io.read_raw_egi, + "eximia": mne.io.read_raw_eximia, +} + +ignore_channels_dict = {"BTI": ["MUz", "MLx", "MLy", "MUx", "MUy", "MLz"]} + +drop_extra_chans_dict = { + "EGI": ["STI 014", "DIN1", "DIN3", "DIN7", "DIN4", "DIN5", "DIN2"], + "eximia": ["GateIn", "Trig1", "Trig2"], +} + +system_decimal_accuracy_dict = {"CNT": 2} + +pandas_not_found_warning_msg = ( + "The Pandas library is not installed. Not " + "returning the original trialinfo matrix as " + "metadata." +) + +testing_path = mne.datasets.testing.data_path(download=False) + + +def _remove_ignored_ch_fields(info): + if "chs" in info: + for cur_ch in info["chs"]: + for cur_field in ch_ignore_fields: + if cur_field in cur_ch: + del cur_ch[cur_field] + + +def _remove_long_info_fields(info): + for cur_field in info_long_fields: + if cur_field in info: + del info[cur_field] + + +def _remove_ignored_info_fields(info): + for cur_field in info_ignored_fields: + if cur_field in info: + del info[cur_field] + + _remove_ignored_ch_fields(info) + + +def get_data_paths(system): + """Return common paths for all tests.""" + return testing_path / "fieldtrip" / "ft_test_data" / system + + +def get_cfg_local(system): + """Return cfg_local field for the system.""" + from pymatreader import read_mat + + cfg_local = read_mat( + os.path.join(get_data_paths(system), "raw_v7.mat"), ["cfg_local"] + )["cfg_local"] + + return cfg_local + + +def get_raw_info(system): + """Return the info dict of the raw data.""" + cfg_local = get_cfg_local(system) + + raw_data_file = os.path.join(testing_path, cfg_local["file_name"]) + reader_function = system_to_reader_fn_dict[system] + + info = reader_function(raw_data_file, preload=False).info + with info._unlock(): + info["comps"] = [] + return info + + +def get_raw_data(system, drop_extra_chs=False): + """Find, load and process the raw data.""" + cfg_local = get_cfg_local(system) + + raw_data_file = os.path.join(testing_path, cfg_local["file_name"]) + reader_function = system_to_reader_fn_dict[system] + + raw_data = reader_function(raw_data_file, preload=True) + crop = min(cfg_local["crop"], np.max(raw_data.times)) + if system == "eximia": + crop -= 0.5 * (1.0 / raw_data.info["sfreq"]) + raw_data.crop(0, crop) + raw_data.del_proj("all") + with raw_data.info._unlock(): + raw_data.info["comps"] = [] + raw_data.drop_channels(cfg_local["removed_chan_names"]) + + if system in ["EGI"]: + raw_data._data[0:-1, :] = raw_data._data[0:-1, :] * 1e6 + + if system in ["CNT"]: + raw_data._data = raw_data._data * 1e6 + + if system in ignore_channels_dict: + raw_data.drop_channels(ignore_channels_dict[system]) + + if system in drop_extra_chans_dict and drop_extra_chs: + raw_data.drop_channels(drop_extra_chans_dict[system]) + + return raw_data + + +def get_epochs(system): + """Find, load and process the epoched data.""" + cfg_local = get_cfg_local(system) + raw_data = get_raw_data(system) + + if cfg_local["eventtype"] in raw_data.ch_names: + stim_channel = cfg_local["eventtype"] + else: + stim_channel = "STI 014" + + if system == "CNT": + events, event_id = mne.events_from_annotations(raw_data) + events[:, 0] = events[:, 0] + 1 + else: + events = mne.find_events(raw_data, stim_channel=stim_channel, shortest_event=1) + + if isinstance(cfg_local["eventvalue"], np.ndarray): + event_id = list(cfg_local["eventvalue"].astype("int")) + else: + event_id = [int(cfg_local["eventvalue"])] + + event_id = [id_ for id_ in event_id if id_ in events[:, 2]] + + epochs = mne.Epochs( + raw_data, + events=events, + event_id=event_id, + tmin=-cfg_local["prestim"], + tmax=cfg_local["poststim"], + baseline=None, + ) + + return epochs + + +def get_evoked(system): + """Find, load and process the avg data.""" + epochs = get_epochs(system) + return epochs.average(picks=np.arange(len(epochs.ch_names))) + + +def check_info_fields(expected, actual, has_raw_info): + """ + Check if info fields are equal. + + Some fields are ignored. + """ + expected = expected.info.copy() + actual = actual.info.copy() + + if not has_raw_info: + _remove_ignored_info_fields(expected) + _remove_ignored_info_fields(actual) + + _remove_long_info_fields(expected) + _remove_long_info_fields(actual) + + # we annoyingly have two ways of representing this, so just always use + # an empty list here + for obj in (expected, actual): + if obj.get("dig", None) is None: + with obj._unlock(): + obj["dig"] = [] + + d = object_diff(actual, expected, allclose=True) + assert d == "", d + + +def check_data(expected, actual, system): + """Check data for equality.""" + decimal = 7 + if system in system_decimal_accuracy_dict: + decimal = system_decimal_accuracy_dict[system] + + np.testing.assert_almost_equal(expected, actual, decimal=decimal) + + +def assert_warning_in_record(warning_message, warn_record): + """Assert that a warning message is in the records.""" + all_messages = [str(w.message) for w in warn_record] + assert warning_message in all_messages diff --git a/mne-python/source/mne/io/fieldtrip/tests/test_fieldtrip.py b/mne-python/source/mne/io/fieldtrip/tests/test_fieldtrip.py new file mode 100644 index 0000000000000000000000000000000000000000..341a67df7c4de5c56a4eb5e203e432eaaaaecca2 --- /dev/null +++ b/mne-python/source/mne/io/fieldtrip/tests/test_fieldtrip.py @@ -0,0 +1,314 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import copy +import itertools +from contextlib import nullcontext + +import numpy as np +import pytest + +import mne +from mne.datasets import testing +from mne.io import read_raw_fieldtrip +from mne.io.fieldtrip.tests.helpers import ( + assert_warning_in_record, + check_data, + check_info_fields, + get_data_paths, + get_epochs, + get_evoked, + get_raw_data, + get_raw_info, + pandas_not_found_warning_msg, +) +from mne.io.fieldtrip.utils import NOINFO_WARNING, _create_events +from mne.io.tests.test_raw import _test_raw_reader +from mne.utils import _check_pandas_installed, _record_warnings + +# missing: KIT: biggest problem here is that the channels do not have the same +# names. +# EGI: no calibration done in FT. so data is VERY different + +all_systems_raw = ["neuromag306", "CTF", "CNT", "BTI", "eximia"] +all_systems_epochs = ["neuromag306", "CTF", "CNT"] +all_versions = ["v7", "v73"] +use_info = [True, False] +all_test_params_raw = list(itertools.product(all_systems_raw, all_versions, use_info)) +all_test_params_epochs = list( + itertools.product(all_systems_epochs, all_versions, use_info) +) +# just for speed we skip some slowest ones -- the coverage should still +# be sufficient +for obj in (all_test_params_epochs, all_test_params_raw): + for key in [("CTF", "v73", True), ("neuromag306", "v73", False)]: + obj.pop(obj.index(key)) + for ki, key in enumerate(obj): + if key[1] == "v73": + obj[ki] = pytest.param(*obj[ki], marks=pytest.mark.slowtest) + +no_info_warning = {"expected_warning": RuntimeWarning, "match": NOINFO_WARNING} + +pymatreader = pytest.importorskip("pymatreader") # module-level +testing_path = mne.datasets.testing.data_path(download=False) + + +@pytest.mark.slowtest +@testing.requires_testing_data +# Reading the sample CNT data results in a RuntimeWarning because it cannot +# parse the measurement date. We need to ignore that warning. +@pytest.mark.filterwarnings("ignore:.*parse meas date.*:RuntimeWarning") +@pytest.mark.filterwarnings("ignore:.*number of bytes.*:RuntimeWarning") +@pytest.mark.parametrize("cur_system, version, use_info", all_test_params_epochs) +def test_read_evoked(cur_system, version, use_info): + """Test comparing reading an Evoked object and the FieldTrip version.""" + test_data_folder_ft = get_data_paths(cur_system) + mne_avg = get_evoked(cur_system) + cur_fname = test_data_folder_ft / f"averaged_{version}.mat" + if use_info: + info = get_raw_info(cur_system) + avg_ft = mne.io.read_evoked_fieldtrip(cur_fname, info) + else: + info = None + with _record_warnings(), pytest.warns(**no_info_warning): + avg_ft = mne.io.read_evoked_fieldtrip(cur_fname, info) + + mne_data = mne_avg.data[:, :-1] + ft_data = avg_ft.data + + check_data(mne_data, ft_data, cur_system) + check_info_fields(mne_avg, avg_ft, use_info) + + +@testing.requires_testing_data +# Reading the sample CNT data results in a RuntimeWarning because it cannot +# parse the measurement date. We need to ignore that warning. +@pytest.mark.filterwarnings("ignore:.*parse meas date.*:RuntimeWarning") +@pytest.mark.filterwarnings("ignore:.*number of bytes.*:RuntimeWarning") +@pytest.mark.parametrize("cur_system, version, use_info", all_test_params_epochs) +def test_read_epochs(cur_system, version, use_info, monkeypatch): + """Test comparing reading an Epochs object and the FieldTrip version.""" + pandas = _check_pandas_installed(strict=False) + has_pandas = pandas is not False + test_data_folder_ft = get_data_paths(cur_system) + mne_epoched = get_epochs(cur_system) + cur_fname = test_data_folder_ft / f"epoched_{version}.mat" + if use_info: + info = get_raw_info(cur_system) + ctx = nullcontext() + else: + info = None + ctx = pytest.warns(**no_info_warning) + + if has_pandas: + with _record_warnings(), ctx: + epoched_ft = mne.io.read_epochs_fieldtrip(cur_fname, info) + assert isinstance(epoched_ft.metadata, pandas.DataFrame) + else: + with _record_warnings() as warn_record: + epoched_ft = mne.io.read_epochs_fieldtrip(cur_fname, info) + assert epoched_ft.metadata is None + assert_warning_in_record(pandas_not_found_warning_msg, warn_record) + if info is None: + assert_warning_in_record(NOINFO_WARNING, warn_record) + + mne_data = mne_epoched.get_data(copy=False)[:, :, :-1] + ft_data = epoched_ft.get_data(copy=False) + + check_data(mne_data, ft_data, cur_system) + check_info_fields(mne_epoched, epoched_ft, use_info) + read_mat = pymatreader.read_mat + + # weird sfreq + def modify_mat(fname, variable_names=None, ignore_fields=None): + out = read_mat(fname, variable_names, ignore_fields) + if "fsample" in out["data"]: + out["data"]["fsample"] = np.repeat(out["data"]["fsample"], 2) + return out + + monkeypatch.setattr(pymatreader, "read_mat", modify_mat) + with _record_warnings(), pytest.warns(RuntimeWarning, match="multiple"): + mne.io.read_epochs_fieldtrip(cur_fname, info) + + +@testing.requires_testing_data +# Reading the sample CNT data results in a RuntimeWarning because it cannot +# parse the measurement date. We need to ignore that warning. +@pytest.mark.filterwarnings("ignore:.*parse meas date.*:RuntimeWarning") +@pytest.mark.filterwarnings("ignore:.*number of bytes.*:RuntimeWarning") +@pytest.mark.parametrize("cur_system, version, use_info", all_test_params_raw) +def test_read_raw_fieldtrip(cur_system, version, use_info): + """Test comparing reading a raw fiff file and the FieldTrip version.""" + # Load the raw fiff file with mne + test_data_folder_ft = get_data_paths(cur_system) + raw_fiff_mne = get_raw_data(cur_system, drop_extra_chs=True) + if use_info: + info = get_raw_info(cur_system) + if cur_system in ("BTI", "eximia"): + ctx = pytest.warns(RuntimeWarning, match="cannot be found in") + else: + ctx = nullcontext() + else: + info = None + ctx = pytest.warns(**no_info_warning) + + cur_fname = test_data_folder_ft / f"raw_{version}.mat" + + with _record_warnings(), ctx: + raw_fiff_ft = mne.io.read_raw_fieldtrip(cur_fname, info) + + if cur_system == "BTI" and not use_info: + raw_fiff_ft.drop_channels(["MzA", "MxA", "MyaA", "MyA", "MxaA", "MzaA"]) + + if cur_system == "eximia" and not use_info: + raw_fiff_ft.drop_channels(["TRIG2", "TRIG1", "GATE"]) + + # Check that the data was loaded correctly + check_data(raw_fiff_mne.get_data(), raw_fiff_ft.get_data(), cur_system) + + # standard tests + with _record_warnings(): + _test_raw_reader( + read_raw_fieldtrip, + fname=cur_fname, + info=info, + test_preloading=False, + test_kwargs=False, + ) # TODO: This should probably work + + # Check info field + check_info_fields(raw_fiff_mne, raw_fiff_ft, use_info) + + +@testing.requires_testing_data +def test_load_epoched_as_raw(): + """Test whether exception is thrown when loading epochs as raw.""" + test_data_folder_ft = get_data_paths("neuromag306") + info = get_raw_info("neuromag306") + cur_fname = test_data_folder_ft / "epoched_v7.mat" + + with pytest.raises(RuntimeError): + mne.io.read_raw_fieldtrip(cur_fname, info) + + +@testing.requires_testing_data +def test_invalid_trialinfocolumn(): + """Test for exceptions when using wrong values for trialinfo parameter.""" + test_data_folder_ft = get_data_paths("neuromag306") + info = get_raw_info("neuromag306") + cur_fname = test_data_folder_ft / "epoched_v7.mat" + + with pytest.raises(ValueError): + mne.io.read_epochs_fieldtrip(cur_fname, info, trialinfo_column=-1) + + with pytest.raises(ValueError): + mne.io.read_epochs_fieldtrip(cur_fname, info, trialinfo_column=3) + + +@testing.requires_testing_data +def test_create_events(): + """Test 2dim trialinfo fields.""" + test_data_folder_ft = get_data_paths("neuromag306") + cur_fname = test_data_folder_ft / "epoched_v7.mat" + original_data = pymatreader.read_mat( + cur_fname, + [ + "data", + ], + ) + + new_data = copy.deepcopy(original_data) + new_data["trialinfo"] = np.array([[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]) + + with pytest.raises(ValueError): + _create_events(new_data, -1) + + for cur_col in np.arange(4): + evts = _create_events(new_data, cur_col) + assert np.all(evts[:, 2] == cur_col + 1) + + with pytest.raises(ValueError): + _create_events(new_data, 4) + + +@testing.requires_testing_data +@pytest.mark.parametrize("version", all_versions) +def test_one_channel_elec_bug(version): + """Test if loading data having only one elec in the elec field works.""" + fname = testing_path / "fieldtrip" / f"one_channel_elec_bug_data_{version}.mat" + + with pytest.warns(**no_info_warning): + mne.io.read_raw_fieldtrip(fname, info=None) + + +@testing.requires_testing_data +# Reading the sample CNT data results in a RuntimeWarning because it cannot +# parse the measurement date. We need to ignore that warning. +@pytest.mark.filterwarnings("ignore:.*parse meas date.*:RuntimeWarning") +@pytest.mark.filterwarnings("ignore:.*number of bytes.*:RuntimeWarning") +@pytest.mark.parametrize("version", all_versions) +@pytest.mark.parametrize("type_", ["averaged", "epoched", "raw"]) +def test_throw_exception_on_cellarray(version, type_): + """Test for a meaningful exception when the data is a cell array.""" + fname = get_data_paths("cellarray") / f"{type_}_{version}.mat" + info = get_raw_info("CNT") + with pytest.raises( + RuntimeError, match="Loading of data in cell arrays is not supported" + ): + if type_ == "averaged": + mne.read_evoked_fieldtrip(fname, info) + elif type_ == "epoched": + mne.read_epochs_fieldtrip(fname, info) + elif type_ == "raw": + mne.io.read_raw_fieldtrip(fname, info) + + +@testing.requires_testing_data +def test_with_missing_channels(): + """Test _create_info when channels are missing from info.""" + cur_system = "neuromag306" + test_data_folder_ft = get_data_paths(cur_system) + info = get_raw_info(cur_system) + del info["chs"][1:20] + info._update_redundant() + + with pytest.warns(RuntimeWarning): + mne.io.read_raw_fieldtrip(test_data_folder_ft / "raw_v7.mat", info) + mne.read_evoked_fieldtrip(test_data_folder_ft / "averaged_v7.mat", info) + mne.read_epochs_fieldtrip(test_data_folder_ft / "epoched_v7.mat", info) + + +@testing.requires_testing_data +@pytest.mark.filterwarnings("ignore: Importing FieldTrip data without an info") +@pytest.mark.filterwarnings("ignore: Cannot guess the correct type") +def test_throw_error_on_non_uniform_time_field(): + """Test if an error is thrown when time fields are not uniform.""" + fname = testing_path / "fieldtrip" / "not_uniform_time.mat" + + with pytest.raises( + RuntimeError, + match="Loading data with non-uniform times per epoch is not supported", + ): + mne.io.read_epochs_fieldtrip(fname, info=None) + + +@testing.requires_testing_data +@pytest.mark.filterwarnings("ignore: Importing FieldTrip data without an info") +def test_throw_error_when_importing_old_ft_version_data(): + """Test if an error is thrown if the data was saved with an old version.""" + fname = testing_path / "fieldtrip" / "old_version.mat" + + with pytest.raises( + RuntimeError, + match="This file was created with " + "an old version of FieldTrip. You " + "can convert the data to the new " + "version by loading it into " + "FieldTrip and applying " + "ft_selectdata with an " + "empty cfg structure on it. " + "Otherwise you can supply " + "the Info field.", + ): + mne.io.read_epochs_fieldtrip(fname, info=None) diff --git a/mne-python/source/mne/io/fieldtrip/utils.py b/mne-python/source/mne/io/fieldtrip/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..f855b7cf0cf5953a102df0de972bc26c40032d60 --- /dev/null +++ b/mne-python/source/mne/io/fieldtrip/utils.py @@ -0,0 +1,367 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +from ..._fiff._digitization import DigPoint, _ensure_fiducials_head +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import create_info +from ..._fiff.pick import pick_info +from ...transforms import rotation3d_align_z_axis +from ...utils import _check_pandas_installed, warn + +_supported_megs = ["neuromag306"] + +_unit_dict = { + "m": 1, + "cm": 1e-2, + "mm": 1e-3, + "V": 1, + "mV": 1e-3, + "uV": 1e-6, + "T": 1, + "T/m": 1, + "T/cm": 1e2, +} + +NOINFO_WARNING = ( + "Importing FieldTrip data without an info dict from the " + "original file. Channel locations, orientations and types " + "will be incorrect. The imported data cannot be used for " + "source analysis, channel interpolation etc." +) + + +def _validate_ft_struct(ft_struct): + """Run validation checks on the ft_structure.""" + if isinstance(ft_struct, list): + raise RuntimeError("Loading of data in cell arrays is not supported") + + +def _create_info(ft_struct, raw_info): + """Create MNE info structure from a FieldTrip structure.""" + if raw_info is None: + warn(NOINFO_WARNING) + + sfreq = _set_sfreq(ft_struct) + ch_names = ft_struct["label"] + if raw_info: + info = raw_info.copy() + missing_channels = set(ch_names) - set(info["ch_names"]) + if missing_channels: + warn( + "The following channels are present in the FieldTrip data " + f"but cannot be found in the provided info: {missing_channels}.\n" + "These channels will be removed from the resulting data!" + ) + + missing_chan_idx = [ch_names.index(ch) for ch in missing_channels] + new_chs = [ch for ch in ch_names if ch not in missing_channels] + ch_names = new_chs + ft_struct["label"] = ch_names + + if "trial" in ft_struct: + ft_struct["trial"] = _remove_missing_channels_from_trial( + ft_struct["trial"], missing_chan_idx + ) + + if "avg" in ft_struct: + if ft_struct["avg"].ndim == 2: + ft_struct["avg"] = np.delete( + ft_struct["avg"], missing_chan_idx, axis=0 + ) + + with info._unlock(): + info["sfreq"] = sfreq + ch_idx = [info["ch_names"].index(ch) for ch in ch_names] + pick_info(info, ch_idx, copy=False) + else: + info = create_info(ch_names, sfreq) + chs, dig = _create_info_chs_dig(ft_struct) + with info._unlock(update_redundant=True): + info.update(chs=chs, dig=dig) + + return info + + +def _remove_missing_channels_from_trial(trial, missing_chan_idx): + if isinstance(trial, list): + for idx_trial in range(len(trial)): + trial[idx_trial] = _remove_missing_channels_from_trial( + trial[idx_trial], missing_chan_idx + ) + elif isinstance(trial, np.ndarray): + if trial.ndim == 2: + trial = np.delete(trial, missing_chan_idx, axis=0) + else: + raise ValueError( + '"trial" field of the FieldTrip structure has an unknown format.' + ) + + return trial + + +def _create_info_chs_dig(ft_struct): + """Create the chs info field from the FieldTrip structure.""" + all_channels = ft_struct["label"] + ch_defaults = dict( + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + cal=1.0, + range=1.0, + unit_mul=FIFF.FIFF_UNITM_NONE, + loc=np.array([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]), + unit=FIFF.FIFF_UNIT_V, + ) + try: + elec = ft_struct["elec"] + except KeyError: + elec = None + + try: + grad = ft_struct["grad"] + except KeyError: + grad = None + + if elec is None and grad is None: + warn( + "The supplied FieldTrip structure does not have an elec or grad " + "field. No channel locations will extracted and the kind of " + "channel might be inaccurate." + ) + if "chanpos" not in (elec or grad or {"chanpos": None}): + raise RuntimeError( + "This file was created with an old version of FieldTrip. You can " + "convert the data to the new version by loading it into FieldTrip " + "and applying ft_selectdata with an empty cfg structure on it. " + "Otherwise you can supply the Info field." + ) + + chs = list() + dig = list() + counter = 0 + for idx_chan, cur_channel_label in enumerate(all_channels): + cur_ch = ch_defaults.copy() + cur_ch["ch_name"] = cur_channel_label + cur_ch["logno"] = idx_chan + 1 + cur_ch["scanno"] = idx_chan + 1 + if elec and cur_channel_label in elec["label"]: + cur_ch = _process_channel_eeg(cur_ch, elec) + assert cur_ch["coord_frame"] == FIFF.FIFFV_COORD_HEAD + # Ref gets ident=0 and we don't have it, so start at 1 + counter += 1 + d = DigPoint( + r=cur_ch["loc"][:3], + coord_frame=FIFF.FIFFV_COORD_HEAD, + kind=FIFF.FIFFV_POINT_EEG, + ident=counter, + ) + dig.append(d) + elif grad and cur_channel_label in grad["label"]: + cur_ch = _process_channel_meg(cur_ch, grad) + else: + if cur_channel_label.startswith("EOG"): + cur_ch["kind"] = FIFF.FIFFV_EOG_CH + cur_ch["coil_type"] = FIFF.FIFFV_COIL_EEG + elif cur_channel_label.startswith("ECG"): + cur_ch["kind"] = FIFF.FIFFV_ECG_CH + cur_ch["coil_type"] = FIFF.FIFFV_COIL_EEG_BIPOLAR + elif cur_channel_label.startswith("STI"): + cur_ch["kind"] = FIFF.FIFFV_STIM_CH + cur_ch["coil_type"] = FIFF.FIFFV_COIL_NONE + else: + warn( + f"Cannot guess the correct type of channel {cur_channel_label}. " + "Making it a MISC channel." + ) + cur_ch["kind"] = FIFF.FIFFV_MISC_CH + cur_ch["coil_type"] = FIFF.FIFFV_COIL_NONE + + chs.append(cur_ch) + _ensure_fiducials_head(dig) + + return chs, dig + + +def _set_sfreq(ft_struct): + """Set the sample frequency.""" + try: + sfreq = ft_struct["fsample"] + except KeyError: + try: + time = ft_struct["time"] + except KeyError: + raise ValueError("No Source for sfreq found") + else: + t1, t2 = float(time[0]), float(time[1]) + sfreq = 1 / (t2 - t1) + try: + sfreq = float(sfreq) + except TypeError: + warn( + "FieldTrip structure contained multiple sample rates, trying the " + f"first of:\n{sfreq} Hz" + ) + sfreq = float(sfreq.ravel()[0]) + return sfreq + + +def _set_tmin(ft_struct): + """Set the start time before the event in evoked data if possible.""" + times = ft_struct["time"] + time_check = all(times[i][0] == times[i - 1][0] for i, x in enumerate(times)) + if time_check: + tmin = times[0][0] + else: + raise RuntimeError( + "Loading data with non-uniform times per epoch is not supported" + ) + return tmin + + +def _create_events(ft_struct, trialinfo_column): + """Create an event matrix from the FieldTrip structure.""" + if "trialinfo" not in ft_struct: + return None + + event_type = ft_struct["trialinfo"] + event_number = range(len(event_type)) + + if trialinfo_column < 0: + raise ValueError("trialinfo_column must be positive") + + available_ti_cols = 1 + if event_type.ndim == 2: + available_ti_cols = event_type.shape[1] + + if trialinfo_column > (available_ti_cols - 1): + raise ValueError( + "trialinfo_column is higher than the amount of columns in trialinfo." + ) + + event_trans_val = np.zeros(len(event_type)) + + if event_type.ndim == 2: + event_type = event_type[:, trialinfo_column] + + events = ( + np.vstack([np.array(event_number), event_trans_val, event_type]).astype("int").T + ) + + return events + + +def _create_event_metadata(ft_struct): + """Create event metadata from trialinfo.""" + pandas = _check_pandas_installed(strict=False) + if not pandas: + warn( + "The Pandas library is not installed. Not returning the original " + "trialinfo matrix as metadata." + ) + return None + + metadata = pandas.DataFrame(ft_struct["trialinfo"]) + + return metadata + + +def _process_channel_eeg(cur_ch, elec): + """Convert EEG channel from FieldTrip to MNE. + + Parameters + ---------- + cur_ch: dict + Channel specific dictionary to populate. + + elec: dict + elec dict as loaded from the FieldTrip structure + + Returns + ------- + cur_ch: dict + The original dict (cur_ch) with the added information + """ + all_labels = np.asanyarray(elec["label"]) + chan_idx_in_elec = np.where(all_labels == cur_ch["ch_name"])[0][0] + position = np.squeeze(elec["chanpos"][chan_idx_in_elec, :]) + # chanunit = elec['chanunit'][chan_idx_in_elec] # not used/needed yet + position_unit = elec["unit"] + + position = position * _unit_dict[position_unit] + cur_ch["loc"] = np.hstack((position, np.zeros((9,)))) + cur_ch["unit"] = FIFF.FIFF_UNIT_V + cur_ch["kind"] = FIFF.FIFFV_EEG_CH + cur_ch["coil_type"] = FIFF.FIFFV_COIL_EEG + cur_ch["coord_frame"] = FIFF.FIFFV_COORD_HEAD + + return cur_ch + + +def _process_channel_meg(cur_ch, grad): + """Convert MEG channel from FieldTrip to MNE. + + Parameters + ---------- + cur_ch: dict + Channel specific dictionary to populate. + + grad: dict + grad dict as loaded from the FieldTrip structure + + Returns + ------- + dict: The original dict (cur_ch) with the added information + """ + all_labels = np.asanyarray(grad["label"]) + chan_idx_in_grad = np.where(all_labels == cur_ch["ch_name"])[0][0] + gradtype = grad["type"] + chantype = grad["chantype"][chan_idx_in_grad] + position_unit = grad["unit"] + position = np.squeeze(grad["chanpos"][chan_idx_in_grad, :]) + position = position * _unit_dict[position_unit] + + if gradtype == "neuromag306" and "tra" in grad and "coilpos" in grad: + # Try to regenerate original channel pos. + idx_in_coilpos = np.where(grad["tra"][chan_idx_in_grad, :] != 0)[0] + cur_coilpos = grad["coilpos"][idx_in_coilpos, :] + cur_coilpos = cur_coilpos * _unit_dict[position_unit] + cur_coilori = grad["coilori"][idx_in_coilpos, :] + if chantype == "megmag": + position = cur_coilpos[0] - 0.0003 * cur_coilori[0] + if chantype == "megplanar": + tmp_pos = cur_coilpos - 0.0003 * cur_coilori + position = np.average(tmp_pos, axis=0) + + original_orientation = np.squeeze(grad["chanori"][chan_idx_in_grad, :]) + try: + orientation = rotation3d_align_z_axis(original_orientation).T + except AssertionError: + orientation = np.eye(3) + assert orientation.shape == (3, 3) + orientation = orientation.flatten() + # chanunit = grad['chanunit'][chan_idx_in_grad] # not used/needed yet + + cur_ch["loc"] = np.hstack((position, orientation)) + cur_ch["kind"] = FIFF.FIFFV_MEG_CH + if chantype == "megmag": + cur_ch["coil_type"] = FIFF.FIFFV_COIL_POINT_MAGNETOMETER + cur_ch["unit"] = FIFF.FIFF_UNIT_T + elif chantype == "megplanar": + cur_ch["coil_type"] = FIFF.FIFFV_COIL_VV_PLANAR_T1 + cur_ch["unit"] = FIFF.FIFF_UNIT_T_M + elif chantype == "refmag": + cur_ch["coil_type"] = FIFF.FIFFV_COIL_MAGNES_REF_MAG + cur_ch["unit"] = FIFF.FIFF_UNIT_T + elif chantype == "refgrad": + cur_ch["coil_type"] = FIFF.FIFFV_COIL_MAGNES_REF_GRAD + cur_ch["unit"] = FIFF.FIFF_UNIT_T + elif chantype == "meggrad": + cur_ch["coil_type"] = FIFF.FIFFV_COIL_AXIAL_GRAD_5CM + cur_ch["unit"] = FIFF.FIFF_UNIT_T + else: + raise RuntimeError(f"Unexpected coil type: {chantype}.") + + cur_ch["coord_frame"] = FIFF.FIFFV_COORD_HEAD + + return cur_ch diff --git a/mne-python/source/mne/io/fiff/__init__.py b/mne-python/source/mne/io/fiff/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..3d83b2c7a7bc0535e35096fc3d8f9513e4185b5b --- /dev/null +++ b/mne-python/source/mne/io/fiff/__init__.py @@ -0,0 +1,10 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""FIF raw data reader.""" + +from .raw import Raw +from .raw import read_raw_fif + +RawFIF = Raw diff --git a/mne-python/source/mne/io/fiff/raw.py b/mne-python/source/mne/io/fiff/raw.py new file mode 100644 index 0000000000000000000000000000000000000000..aad07690de80e23cec40a2fdfd71b2d7a7661bdb --- /dev/null +++ b/mne-python/source/mne/io/fiff/raw.py @@ -0,0 +1,559 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import copy +import os.path as op +from pathlib import Path + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import read_meas_info +from ..._fiff.open import _fiff_get_fid, _get_next_fname, fiff_open +from ..._fiff.tag import _call_dict, read_tag +from ..._fiff.tree import dir_tree_find +from ..._fiff.utils import _mult_cal_one +from ...annotations import Annotations, _read_annotations_fif +from ...channels import fix_mag_coil_types +from ...event import AcqParserFIF +from ...fixes import _reshape_view +from ...utils import ( + _check_fname, + _file_like, + _on_missing, + check_fname, + fill_doc, + logger, + verbose, + warn, +) +from ..base import ( + BaseRaw, + _check_maxshield, + _check_raw_compatibility, + _get_fname_rep, + _RawShell, +) + + +@fill_doc +class Raw(BaseRaw): + """Raw data in FIF format. + + Parameters + ---------- + fname : path-like | file-like + The raw filename to load. For files that have automatically been split, + the split part will be automatically loaded. Filenames not ending with + ``raw.fif``, ``raw_sss.fif``, ``raw_tsss.fif``, ``_meg.fif``, + ``_eeg.fif``, or ``_ieeg.fif`` (with or without an optional additional + ``.gz`` extension) will generate a warning. If a file-like object is + provided, preloading must be used. + + .. versionchanged:: 0.18 + Support for file-like objects. + allow_maxshield : bool | str (default False) + If True, allow loading of data that has been recorded with internal + active compensation (MaxShield). Data recorded with MaxShield should + generally not be loaded directly, but should first be processed using + SSS/tSSS to remove the compensation signals that may also affect brain + activity. Can also be "yes" to load without eliciting a warning. + %(preload)s + %(on_split_missing)s + %(verbose)s + + Attributes + ---------- + %(info_not_none)s + ch_names : list of string + List of channels' names. + n_times : int + Total number of time points in the raw file. + times : ndarray + Time vector in seconds. Starts from 0, independently of `first_samp` + value. Time interval between consecutive time samples is equal to the + inverse of the sampling frequency. + duration : float + The duration of the raw file in seconds. + + .. versionadded:: 1.9 + preload : bool + Indicates whether raw data are in memory. + """ + + _extra_attributes = ( + "fix_mag_coil_types", + "acqparser", + "_read_raw_file", # this would be ugly to move, but maybe we should + ) + + @verbose + def __init__( + self, + fname, + allow_maxshield=False, + preload=False, + on_split_missing="raise", + verbose=None, + ): + raws = [] + do_check_ext = not _file_like(fname) + next_fname = fname + while next_fname is not None: + raw, next_fname, buffer_size_sec = self._read_raw_file( + next_fname, allow_maxshield, preload, do_check_ext + ) + do_check_ext = False + raws.append(raw) + if next_fname is not None: + if not op.exists(next_fname): + msg = ( + f"Split raw file detected but next file {next_fname} " + "does not exist. Ensure all files were transferred " + "properly and that split and original files were not " + "manually renamed on disk (split files should be " + "renamed by loading and re-saving with MNE-Python to " + "preserve proper filename linkage)." + ) + _on_missing(on_split_missing, msg, name="on_split_missing") + break + # If using a file-like object, we need to be careful about serialization and + # types. + # + # 1. We must change both the variable named "fname" here so that _get_argvalues + # (magic) does not store the file-like object. + # 2. We need to ensure "filenames" passed to the constructor below gets a list + # of Path or None. + # 3. We need to remove the file-like objects from _raw_extras. This must + # be done *after* the super().__init__ call, because the constructor + # needs the file-like objects to read the data (which it will do because we + # force preloading for file-like objects). + + # Avoid file-like in _get_argvalues (1) + fname = _path_from_fname(fname) + + _check_raw_compatibility(raws) + super().__init__( + copy.deepcopy(raws[0].info), + preload=False, + first_samps=[r.first_samp for r in raws], + last_samps=[r.last_samp for r in raws], + # Avoid file-like objects in raw.filenames (2) + filenames=[_path_from_fname(r._raw_extras["filename"]) for r in raws], + raw_extras=[r._raw_extras for r in raws], + orig_format=raws[0].orig_format, + dtype=None, + buffer_size_sec=buffer_size_sec, + verbose=verbose, + ) + + # combine annotations + self.set_annotations(raws[0].annotations, emit_warning=False) + + # Add annotations for in-data skips + for extra in self._raw_extras: + mask = [ent is None for ent in extra["ent"]] + start = extra["bounds"][:-1][mask] + stop = extra["bounds"][1:][mask] - 1 + duration = (stop - start + 1.0) / self.info["sfreq"] + annot = Annotations( + onset=(start / self.info["sfreq"]), + duration=duration, + description="BAD_ACQ_SKIP", + orig_time=self.info["meas_date"], + ) + + self._annotations += annot + + if preload: + self._preload_data(preload) + else: + self.preload = False + # Avoid file-like objects in _raw_extras (3) + for extra in self._raw_extras: + if not isinstance(extra["filename"], Path): + extra["filename"] = None + + @verbose + def _read_raw_file( + self, fname, allow_maxshield, preload, do_check_ext=True, verbose=None + ): + """Read in header information from a raw file.""" + logger.info(f"Opening raw data file {fname}...") + + # Read in the whole file if preload is on and .fif.gz (saves time) + if not _file_like(fname): + if do_check_ext: + endings = ( + "raw.fif", + "raw_sss.fif", + "raw_tsss.fif", + "_meg.fif", + "_eeg.fif", + "_ieeg.fif", + ) + endings += tuple([f"{e}.gz" for e in endings]) + check_fname(fname, "raw", endings) + # filename + fname = _check_fname(fname, "read", True, "fname") + whole_file = preload if fname.suffix == ".gz" else False + else: + # file-like + if not preload: + raise ValueError("preload must be used with file-like objects") + whole_file = True + ff, tree, _ = fiff_open(fname, preload=whole_file) + with ff as fid: + # Read the measurement info + + info, meas = read_meas_info(fid, tree, clean_bads=True) + annotations = _read_annotations_fif(fid, tree) + + # Locate the data of interest + raw_node = dir_tree_find(meas, FIFF.FIFFB_RAW_DATA) + if len(raw_node) == 0: + raw_node = dir_tree_find(meas, FIFF.FIFFB_CONTINUOUS_DATA) + if len(raw_node) == 0: + raw_node = dir_tree_find(meas, FIFF.FIFFB_IAS_RAW_DATA) + if len(raw_node) == 0: + raise ValueError(f"No raw data in {_get_fname_rep(fname)}") + _check_maxshield(allow_maxshield) + with info._unlock(): + info["maxshield"] = True + del meas + + if len(raw_node) == 1: + raw_node = raw_node[0] + + # Process the directory + directory = raw_node["directory"] + nent = raw_node["nent"] + nchan = int(info["nchan"]) + first = 0 + first_samp = 0 + first_skip = 0 + + # Get first sample tag if it is there + if directory[first].kind == FIFF.FIFF_FIRST_SAMPLE: + tag = read_tag(fid, directory[first].pos) + first_samp = int(tag.data.item()) + first += 1 + _check_entry(first, nent) + + # Omit initial skip + if directory[first].kind == FIFF.FIFF_DATA_SKIP: + # This first skip can be applied only after we know the bufsize + tag = read_tag(fid, directory[first].pos) + first_skip = int(tag.data.item()) + first += 1 + _check_entry(first, nent) + + raw = _RawShell() + raw.first_samp = first_samp + if info["meas_date"] is None and annotations is not None: + # we need to adjust annotations.onset as when there is no meas + # date set_annotations considers that the origin of time is the + # first available sample (ignores first_samp) + annotations.onset -= first_samp / info["sfreq"] + raw.set_annotations(annotations) + + # Go through the remaining tags in the directory + raw_extras = list() + nskip = 0 + orig_format = None + + _byte_dict = { + FIFF.FIFFT_DAU_PACK16: 2, + FIFF.FIFFT_SHORT: 2, + FIFF.FIFFT_FLOAT: 4, + FIFF.FIFFT_DOUBLE: 8, + FIFF.FIFFT_INT: 4, + FIFF.FIFFT_COMPLEX_FLOAT: 8, + FIFF.FIFFT_COMPLEX_DOUBLE: 16, + } + _orig_format_dict = { + FIFF.FIFFT_DAU_PACK16: "short", + FIFF.FIFFT_SHORT: "short", + FIFF.FIFFT_FLOAT: "single", + FIFF.FIFFT_DOUBLE: "double", + FIFF.FIFFT_INT: "int", + FIFF.FIFFT_COMPLEX_FLOAT: "single", + FIFF.FIFFT_COMPLEX_DOUBLE: "double", + } + + for k in range(first, nent): + ent = directory[k] + # There can be skips in the data (e.g., if the user unclicked) + # an re-clicked the button + if ent.kind == FIFF.FIFF_DATA_BUFFER: + # Figure out the number of samples in this buffer + try: + div = _byte_dict[ent.type] + except KeyError: + raise RuntimeError( + f"Cannot handle data buffers of type {ent.type}" + ) from None + nsamp = ent.size // (div * nchan) + if orig_format is None: + orig_format = _orig_format_dict[ent.type] + + # Do we have an initial skip pending? + if first_skip > 0: + first_samp += nsamp * first_skip + raw.first_samp = first_samp + first_skip = 0 + + # Do we have a skip pending? + if nskip > 0: + raw_extras.append( + dict( + ent=None, + first=first_samp, + nsamp=nskip * nsamp, + last=first_samp + nskip * nsamp - 1, + ) + ) + first_samp += nskip * nsamp + nskip = 0 + + # Add a data buffer + raw_extras.append( + dict( + ent=ent, + first=first_samp, + last=first_samp + nsamp - 1, + nsamp=nsamp, + ) + ) + first_samp += nsamp + elif ent.kind == FIFF.FIFF_DATA_SKIP: + tag = read_tag(fid, ent.pos) + nskip = int(tag.data.item()) + + next_fname = _get_next_fname(fid, _path_from_fname(fname), tree) + + # reformat raw_extras to be a dict of list/ndarray rather than + # list of dict (faster access) + raw_extras = {key: [r[key] for r in raw_extras] for key in raw_extras[0]} + for key in raw_extras: + if key != "ent": # dict or None + raw_extras[key] = np.array(raw_extras[key], int) + if not np.array_equal(raw_extras["last"][:-1], raw_extras["first"][1:] - 1): + raise RuntimeError("FIF file appears to be broken") + bounds = np.cumsum( + np.concatenate([raw_extras["first"][:1], raw_extras["nsamp"]]) + ) + raw_extras["bounds"] = bounds + assert len(raw_extras["bounds"]) == len(raw_extras["ent"]) + 1 + # store the original buffer size + buffer_size_sec = np.median(raw_extras["nsamp"]) / info["sfreq"] + del raw_extras["first"] + del raw_extras["last"] + del raw_extras["nsamp"] + raw_extras["filename"] = fname + + raw.last_samp = first_samp - 1 + raw.orig_format = orig_format + + # Add the calibration factors + raw._cals = info._cals + raw._raw_extras = raw_extras + logger.info( + " Range : %d ... %d = %9.3f ... %9.3f secs", + raw.first_samp, + raw.last_samp, + float(raw.first_samp) / info["sfreq"], + float(raw.last_samp) / info["sfreq"], + ) + + raw.info = info + + logger.info("Ready.") + + return raw, next_fname, buffer_size_sec + + @property + def _dtype(self): + """Get the dtype to use to store data from disk.""" + if self._dtype_ is not None: + return self._dtype_ + dtype = None + for raw_extra in self._raw_extras: + for ent in raw_extra["ent"]: + if ent is not None: + if ent.type in ( + FIFF.FIFFT_COMPLEX_FLOAT, + FIFF.FIFFT_COMPLEX_DOUBLE, + ): + dtype = np.complex128 + else: + dtype = np.float64 + break + if dtype is not None: + break + if dtype is None: + raise RuntimeError("bug in reading") + self._dtype_ = dtype + return dtype + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a segment of data from a file.""" + n_bad = 0 + with _fiff_get_fid(self._raw_extras[fi]["filename"]) as fid: + bounds = self._raw_extras[fi]["bounds"] + ents = self._raw_extras[fi]["ent"] + nchan = self._raw_extras[fi]["orig_nchan"] + use = (stop > bounds[:-1]) & (start < bounds[1:]) + offset = 0 + for ei in np.where(use)[0]: + first = bounds[ei] + last = bounds[ei + 1] + nsamp = last - first + ent = ents[ei] + first_pick = max(start - first, 0) + last_pick = min(nsamp, stop - first) + picksamp = last_pick - first_pick + this_start = offset + offset += picksamp + this_stop = offset + # only read data if it exists + if ent is None: + continue # just use zeros for gaps + # faster to always read full tag, taking advantage of knowing the header + # already (cutting out some of read_tag) ... + fid.seek(ent.pos + 16, 0) + one = _call_dict[ent.type](fid, ent, shape=None, rlims=None) + try: + one = _reshape_view(one, (nsamp, nchan)) + except AttributeError: # one is None + n_bad += picksamp + else: + # ... then pick samples we want + if first_pick != 0 or last_pick != nsamp: + one = one[first_pick:last_pick] + _mult_cal_one( + data[:, this_start:this_stop], + one.T, + idx, + cals, + mult, + ) + if n_bad: + warn( + f"FIF raw buffer could not be read, acquisition error " + f"likely: {n_bad} samples set to zero" + ) + assert offset == stop - start + + def fix_mag_coil_types(self): + """Fix Elekta magnetometer coil types. + + Returns + ------- + raw : instance of Raw + The raw object. Operates in place. + + Notes + ----- + This function changes magnetometer coil types 3022 (T1: SQ20483N) and + 3023 (T2: SQ20483-A) to 3024 (T3: SQ20950N) in the channel definition + records in the info structure. + + Neuromag Vectorview systems can contain magnetometers with two + different coil sizes (3022 and 3023 vs. 3024). The systems + incorporating coils of type 3024 were introduced last and are used at + the majority of MEG sites. At some sites with 3024 magnetometers, + the data files have still defined the magnetometers to be of type + 3022 to ensure compatibility with older versions of Neuromag software. + In the MNE software as well as in the present version of Neuromag + software coil type 3024 is fully supported. Therefore, it is now safe + to upgrade the data files to use the true coil type. + + .. note:: The effect of the difference between the coil sizes on the + current estimates computed by the MNE software is very small. + Therefore the use of mne_fix_mag_coil_types is not mandatory. + """ + fix_mag_coil_types(self.info) + return self + + @property + def acqparser(self): + """The AcqParserFIF for the measurement info. + + See Also + -------- + mne.AcqParserFIF + """ + if getattr(self, "_acqparser", None) is None: + self._acqparser = AcqParserFIF(self.info) + return self._acqparser + + +def _check_entry(first, nent): + """Sanity check entries.""" + if first >= nent: + raise OSError("Could not read data, perhaps this is a corrupt file") + + +@fill_doc +def read_raw_fif( + fname, allow_maxshield=False, preload=False, on_split_missing="raise", verbose=None +) -> Raw: + """Reader function for Raw FIF data. + + Parameters + ---------- + fname : path-like | file-like + The raw filename to load. For files that have automatically been split, + the split part will be automatically loaded. Filenames should end + with raw.fif, raw.fif.gz, raw_sss.fif, raw_sss.fif.gz, raw_tsss.fif, + raw_tsss.fif.gz, or _meg.fif. If a file-like object is provided, + preloading must be used. + + .. versionchanged:: 0.18 + Support for file-like objects. + allow_maxshield : bool | str (default False) + If True, allow loading of data that has been recorded with internal + active compensation (MaxShield). Data recorded with MaxShield should + generally not be loaded directly, but should first be processed using + SSS/tSSS to remove the compensation signals that may also affect brain + activity. Can also be "yes" to load without eliciting a warning. + %(preload)s + %(on_split_missing)s + %(verbose)s + + Returns + ------- + raw : instance of Raw + A Raw object containing FIF data. + + Notes + ----- + .. versionadded:: 0.9.0 + + When reading a FIF file, note that the first N seconds annotated + ``BAD_ACQ_SKIP`` are **skipped**. They are removed from ``raw.times`` and + ``raw.n_times`` parameters but ``raw.first_samp`` and ``raw.first_time`` + are updated accordingly. + """ + return Raw( + fname=fname, + allow_maxshield=allow_maxshield, + preload=preload, + verbose=verbose, + on_split_missing=on_split_missing, + ) + + +def _path_from_fname(fname) -> Path | None: + if not isinstance(fname, Path): + if isinstance(fname, str): + fname = Path(fname) + else: + # Try to get a filename from the file-like object + try: + fname = Path(fname.name) + except Exception: + fname = None + return fname diff --git a/mne-python/source/mne/io/fiff/tests/__init__.py b/mne-python/source/mne/io/fiff/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/fiff/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/fiff/tests/test_raw_fiff.py b/mne-python/source/mne/io/fiff/tests/test_raw_fiff.py new file mode 100644 index 0000000000000000000000000000000000000000..29aa160ec196ba11f9a70657f5ee9b5c5190bdce --- /dev/null +++ b/mne-python/source/mne/io/fiff/tests/test_raw_fiff.py @@ -0,0 +1,2211 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime +import os +import pathlib +import pickle +import platform +import shutil +from contextlib import nullcontext +from copy import deepcopy +from functools import partial +from io import BytesIO +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_almost_equal, assert_array_equal + +from mne import ( + compute_proj_raw, + concatenate_events, + create_info, + equalize_channels, + events_from_annotations, + find_events, + make_fixed_length_epochs, + pick_channels, + pick_info, + pick_types, +) +from mne._fiff.constants import FIFF +from mne._fiff.tag import _read_tag_header, read_tag +from mne.annotations import Annotations +from mne.datasets import testing +from mne.filter import filter_data +from mne.io import RawArray, base, concatenate_raws, match_channel_orders, read_raw_fif +from mne.io.tests.test_raw import _test_concat, _test_raw_reader +from mne.transforms import Transform +from mne.utils import ( + _dt_to_stamp, + _record_warnings, + assert_and_remove_boundary_annot, + assert_object_equal, + catch_logging, + requires_mne, + run_subprocess, +) + +testing_path = testing.data_path(download=False) +data_dir = testing_path / "MEG" / "sample" +fif_fname = data_dir / "sample_audvis_trunc_raw.fif" +ms_fname = testing_path / "SSS" / "test_move_anon_raw.fif" +skip_fname = testing_path / "misc" / "intervalrecording_raw.fif" +tri_fname = testing_path / "SSS" / "TRIUX" / "triux_bmlhus_erm_raw.fif" + +base_dir = Path(__file__).parents[2] / "tests" / "data" +test_fif_fname = base_dir / "test_raw.fif" +test_fif_gz_fname = base_dir / "test_raw.fif.gz" +ctf_fname = base_dir / "test_ctf_raw.fif" +ctf_comp_fname = base_dir / "test_ctf_comp_raw.fif" +fif_bad_marked_fname = base_dir / "test_withbads_raw.fif" +bad_file_works = base_dir / "test_bads.txt" +bad_file_wrong = base_dir / "test_wrong_bads.txt" +hp_fif_fname = base_dir / "test_chpi_raw_sss.fif" + + +@testing.requires_testing_data +def test_acq_skip(tmp_path): + """Test treatment of acquisition skips.""" + raw = read_raw_fif(skip_fname, preload=True) + picks = [1, 2, 10] + assert len(raw.times) == 17000 + annotations = raw.annotations + assert len(annotations) == 3 # there are 3 skips + assert_allclose(annotations.onset, [14, 19, 23]) + assert_allclose(annotations.duration, [2.0, 2.0, 3.0]) # inclusive! + data, times = raw.get_data(picks, reject_by_annotation="omit", return_times=True) + expected_data, expected_times = zip( + raw[picks, :2000], + raw[picks, 4000:7000], + raw[picks, 9000:11000], + raw[picks, 14000:17000], + ) + expected_times = np.concatenate(list(expected_times), axis=-1) + assert_allclose(times, expected_times) + expected_data = list(expected_data) + assert_allclose(data, np.concatenate(expected_data, axis=-1), atol=1e-22) + + # Check that acquisition skips are handled properly in filtering + kwargs = dict(l_freq=None, h_freq=50.0, fir_design="firwin") + raw_filt = raw.copy().filter(picks=picks, **kwargs) + for data in expected_data: + filter_data(data, raw.info["sfreq"], copy=False, **kwargs) + data = raw_filt.get_data(picks, reject_by_annotation="omit") + assert_allclose(data, np.concatenate(expected_data, axis=-1), atol=1e-22) + + # Check that acquisition skips are handled properly during I/O + fname = tmp_path / "test_raw.fif" + raw.save(fname, fmt=raw.orig_format) + # first: file size should not increase much (orig data is missing + # 7 of 17 buffers, so if we write them out it should increase the file + # size quite a bit. + orig_size = skip_fname.lstat().st_size + new_size = fname.lstat().st_size + max_size = int(1.05 * orig_size) # almost the same + annotations + assert new_size < max_size, (new_size, max_size) + raw_read = read_raw_fif(fname) + assert raw_read.annotations is not None + assert_allclose(raw.times, raw_read.times) + assert_allclose(raw_read[:][0], raw[:][0], atol=1e-17) + # Saving with a bad buffer length emits warning + raw.pick(raw.ch_names[:2]) + with _record_warnings() as w: + raw.save(fname, buffer_size_sec=0.5, overwrite=True) + assert len(w) == 0 + with pytest.warns(RuntimeWarning, match="did not fit evenly"): + raw.save(fname, buffer_size_sec=2.0, overwrite=True) + + +def test_fix_types(): + """Test fixing of channel types.""" + for fname, change, bads in ( + (hp_fif_fname, True, ["MEG0111"]), + (test_fif_fname, False, []), + (ctf_fname, False, []), + ): + raw = read_raw_fif(fname) + raw.info["bads"] = bads + mag_picks = pick_types(raw.info, meg="mag", exclude=[]) + other_picks = np.setdiff1d(np.arange(len(raw.ch_names)), mag_picks) + # we don't actually have any files suffering from this problem, so + # fake it + if change: + for ii in mag_picks: + raw.info["chs"][ii]["coil_type"] = FIFF.FIFFV_COIL_VV_MAG_T2 + orig_types = np.array([ch["coil_type"] for ch in raw.info["chs"]]) + raw.fix_mag_coil_types() + new_types = np.array([ch["coil_type"] for ch in raw.info["chs"]]) + if not change: + assert_array_equal(orig_types, new_types) + else: + assert_array_equal(orig_types[other_picks], new_types[other_picks]) + assert (orig_types[mag_picks] != new_types[mag_picks]).all() + assert (new_types[mag_picks] == FIFF.FIFFV_COIL_VV_MAG_T3).all() + + +def test_concat(tmp_path): + """Test RawFIF concatenation.""" + # we trim the file to save lots of memory and some time + raw = read_raw_fif(test_fif_fname) + raw.crop(0, 2.0) + test_name = tmp_path / "test_raw.fif" + raw.save(test_name) + # now run the standard test + _test_concat(partial(read_raw_fif), test_name) + + +@testing.requires_testing_data +def test_hash_raw(): + """Test hashing raw objects.""" + raw = read_raw_fif(fif_fname) + pytest.raises(RuntimeError, raw.__hash__) + raw = read_raw_fif(fif_fname).crop(0, 0.5) + raw_size = raw._size + raw.load_data() + raw_load_size = raw._size + assert raw_size < raw_load_size + raw_2 = read_raw_fif(fif_fname).crop(0, 0.5) + raw_2.load_data() + assert hash(raw) == hash(raw_2) + # do NOT use assert_equal here, failing output is terrible + assert pickle.dumps(raw) == pickle.dumps(raw_2) + + raw_2._data[0, 0] -= 1 + assert hash(raw) != hash(raw_2) + + +@testing.requires_testing_data +def test_maxshield(): + """Test maxshield warning.""" + with pytest.warns(RuntimeWarning, match="Internal Active Shielding") as w: + read_raw_fif(ms_fname, allow_maxshield=True) + assert "test_raw_fiff.py" in w[0].filename + + +@testing.requires_testing_data +def test_subject_info(tmp_path): + """Test reading subject information.""" + raw = read_raw_fif(fif_fname).crop(0, 1) + assert raw.info["subject_info"] is None + # fake some subject data + keys = ["id", "his_id", "last_name", "first_name", "birthday", "sex", "hand"] + vals = [1, "foobar", "bar", "foo", datetime.date(1901, 2, 3), 0, 1] + subject_info = dict() + for key, val in zip(keys, vals): + subject_info[key] = val + raw.info["subject_info"] = subject_info + out_fname = tmp_path / "test_subj_info_raw.fif" + raw.save(out_fname, overwrite=True) + raw_read = read_raw_fif(out_fname) + for key in keys: + assert subject_info[key] == raw_read.info["subject_info"][key] + assert raw.info["meas_date"] == raw_read.info["meas_date"] + + for key in ["secs", "usecs", "version"]: + assert raw.info["meas_id"][key] == raw_read.info["meas_id"][key] + assert_array_equal( + raw.info["meas_id"]["machid"], raw_read.info["meas_id"]["machid"] + ) + + +@testing.requires_testing_data +def test_copy_append(): + """Test raw copying and appending combinations.""" + raw = read_raw_fif(fif_fname, preload=True).copy() + raw_full = read_raw_fif(fif_fname) + raw_full.append(raw) + data = raw_full[:, :][0] + assert data.shape[1] == 2 * raw._data.shape[1] + + +@testing.requires_testing_data +def test_output_formats(tmp_path): + """Test saving and loading raw data using multiple formats.""" + formats = ["short", "int", "single", "double"] + tols = [1e-4, 1e-7, 1e-7, 1e-15] + + # let's fake a raw file with different formats + raw = read_raw_fif(test_fif_fname).crop(0, 1) + + temp_file = tmp_path / "raw.fif" + for ii, (fmt, tol) in enumerate(zip(formats, tols)): + # Let's test the overwriting error throwing while we're at it + if ii > 0: + pytest.raises(OSError, raw.save, temp_file, fmt=fmt) + raw.save(temp_file, fmt=fmt, overwrite=True) + raw2 = read_raw_fif(temp_file) + raw2_data = raw2[:, :][0] + assert_allclose(raw2_data, raw[:, :][0], rtol=tol, atol=1e-25) + assert raw2.orig_format == fmt + + +def _compare_combo(raw, new, times, n_times): + """Compare data.""" + for ti in times: # let's do a subset of points for speed + orig = raw[:, ti % n_times][0] + # these are almost_equals because of possible dtype differences + assert_allclose(orig, new[:, ti][0]) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_multiple_files(tmp_path): + """Test loading multiple files simultaneously.""" + # split file + raw = read_raw_fif(fif_fname).crop(0, 10) + raw.load_data() + raw.load_data() # test no operation + split_size = 3.0 # in seconds + sfreq = raw.info["sfreq"] + nsamp = raw.last_samp - raw.first_samp + tmins = np.round(np.arange(0.0, nsamp, split_size * sfreq)) + tmaxs = np.concatenate((tmins[1:] - 1, [nsamp])) + tmaxs /= sfreq + tmins /= sfreq + assert raw.n_times == len(raw.times) + + # going in reverse order so the last fname is the first file (need later) + raws = [None] * len(tmins) + for ri in range(len(tmins) - 1, -1, -1): + fname = tmp_path / (f"test_raw_split-{ri}_raw.fif") + raw.save(fname, tmin=tmins[ri], tmax=tmaxs[ri]) + raws[ri] = read_raw_fif(fname) + assert ( + len(raws[ri].times) + == int(round((tmaxs[ri] - tmins[ri]) * raw.info["sfreq"])) + 1 + ) # + 1 b/c inclusive + events = [find_events(r, stim_channel="STI 014") for r in raws] + last_samps = [r.last_samp for r in raws] + first_samps = [r.first_samp for r in raws] + + # test concatenation of split file + pytest.raises(ValueError, concatenate_raws, raws, True, events[1:]) + all_raw_1, events1 = concatenate_raws(raws, preload=False, events_list=events) + assert_allclose(all_raw_1.times, raw.times) + assert raw.first_samp == all_raw_1.first_samp + assert raw.last_samp == all_raw_1.last_samp + assert_allclose(raw[:, :][0], all_raw_1[:, :][0]) + raws[0] = read_raw_fif(fname) + all_raw_2 = concatenate_raws(raws, preload=True) + assert_allclose(raw[:, :][0], all_raw_2[:, :][0]) + + # test proper event treatment for split files + events2 = concatenate_events(events, first_samps, last_samps) + events3 = find_events(all_raw_2, stim_channel="STI 014") + assert_array_equal(events1, events2) + assert_array_equal(events1, events3) + + # test various methods of combining files + raw = read_raw_fif(fif_fname, preload=True) + n_times = raw.n_times + # make sure that all our data match + times = list(range(0, 2 * n_times, 999)) + # add potentially problematic points + times.extend([n_times - 1, n_times, 2 * n_times - 1]) + + raw_combo0 = concatenate_raws( + [read_raw_fif(f) for f in [fif_fname, fif_fname]], preload=True + ) + _compare_combo(raw, raw_combo0, times, n_times) + raw_combo = concatenate_raws( + [read_raw_fif(f) for f in [fif_fname, fif_fname]], preload=False + ) + _compare_combo(raw, raw_combo, times, n_times) + raw_combo = concatenate_raws( + [read_raw_fif(f) for f in [fif_fname, fif_fname]], preload="memmap8.dat" + ) + _compare_combo(raw, raw_combo, times, n_times) + assert raw[:, :][0].shape[1] * 2 == raw_combo0[:, :][0].shape[1] + assert raw_combo0[:, :][0].shape[1] == raw_combo0.n_times + + # with all data preloaded, result should be preloaded + raw_combo = read_raw_fif(fif_fname, preload=True) + raw_combo.append(read_raw_fif(fif_fname, preload=True)) + assert raw_combo.preload is True + assert raw_combo.n_times == raw_combo._data.shape[1] + _compare_combo(raw, raw_combo, times, n_times) + + # with any data not preloaded, don't set result as preloaded + raw_combo = concatenate_raws( + [read_raw_fif(fif_fname, preload=True), read_raw_fif(fif_fname, preload=False)] + ) + assert raw_combo.preload is False + assert_array_equal( + find_events(raw_combo, stim_channel="STI 014"), + find_events(raw_combo0, stim_channel="STI 014"), + ) + _compare_combo(raw, raw_combo, times, n_times) + + # user should be able to force data to be preloaded upon concat + raw_combo = concatenate_raws( + [read_raw_fif(fif_fname, preload=False), read_raw_fif(fif_fname, preload=True)], + preload=True, + ) + assert raw_combo.preload is True + _compare_combo(raw, raw_combo, times, n_times) + + raw_combo = concatenate_raws( + [read_raw_fif(fif_fname, preload=False), read_raw_fif(fif_fname, preload=True)], + preload="memmap3.dat", + ) + _compare_combo(raw, raw_combo, times, n_times) + + raw_combo = concatenate_raws( + [read_raw_fif(fif_fname, preload=True), read_raw_fif(fif_fname, preload=True)], + preload="memmap4.dat", + ) + _compare_combo(raw, raw_combo, times, n_times) + + raw_combo = concatenate_raws( + [ + read_raw_fif(fif_fname, preload=False), + read_raw_fif(fif_fname, preload=False), + ], + preload="memmap5.dat", + ) + _compare_combo(raw, raw_combo, times, n_times) + + # verify that combining raws with different projectors throws an exception + raw.add_proj([], remove_existing=True) + pytest.raises(ValueError, raw.append, read_raw_fif(fif_fname, preload=True)) + + # now test event treatment for concatenated raw files + events = [ + find_events(raw, stim_channel="STI 014"), + find_events(raw, stim_channel="STI 014"), + ] + last_samps = [raw.last_samp, raw.last_samp] + first_samps = [raw.first_samp, raw.first_samp] + events = concatenate_events(events, first_samps, last_samps) + events2 = find_events(raw_combo0, stim_channel="STI 014") + assert_array_equal(events, events2) + + # check out the len method + assert len(raw) == raw.n_times + assert len(raw) == raw.last_samp - raw.first_samp + 1 + + +@testing.requires_testing_data +@pytest.mark.parametrize("on_mismatch", ("ignore", "warn", "raise")) +def test_concatenate_raws(on_mismatch): + """Test error handling during raw concatenation.""" + raw = read_raw_fif(fif_fname).crop(0, 10) + raws = [raw, raw.copy()] + raws[1].info["dev_head_t"]["trans"] += 0.1 + kws = dict(raws=raws, on_mismatch=on_mismatch) + + if on_mismatch == "ignore": + concatenate_raws(**kws) + elif on_mismatch == "warn": + with pytest.warns(RuntimeWarning, match="different head positions"): + concatenate_raws(**kws) + elif on_mismatch == "raise": + with pytest.raises(ValueError, match="different head positions"): + concatenate_raws(**kws) + + +def _create_toy_data(n_channels=3, sfreq=250, seed=None): + rng = np.random.default_rng(seed) + data = rng.standard_normal(size=(n_channels, 50 * sfreq)) * 5e-6 + info = create_info(n_channels, sfreq, "eeg") + return RawArray(data, info) + + +def test_concatenate_raws_bads_order(): + """Test concatenation of raws when the order of *bad* channels varies.""" + raw0 = _create_toy_data() + raw1 = _create_toy_data() + + # Test bad channel order + raw0.info["bads"] = ["0", "1"] + raw1.info["bads"] = ["1", "0"] + + # raw0 is modified in-place and therefore copied + raw_concat = concatenate_raws([raw0.copy(), raw1]) + + # Check data are equal + data_concat = np.concatenate([raw0.get_data(), raw1.get_data()], 1) + assert np.all(raw_concat.get_data() == data_concat) + + # Check bad channels + assert set(raw_concat.info["bads"]) == {"0", "1"} + + # Bad channel mismatch raises + raw2 = raw1.copy() + raw2.info["bads"] = ["0", "2"] + with pytest.raises(ValueError, match="bads.*must match"): + concatenate_raws([raw0, raw2]) + + # Type mismatch raises + epochs1 = make_fixed_length_epochs(raw1) + with pytest.raises(ValueError, match="type.*must match"): + concatenate_raws([raw0, epochs1.load_data()]) + + # Sample rate mismatch + raw3 = _create_toy_data(sfreq=500) + raw3.info["bads"] = ["0", "1"] + with pytest.raises(ValueError, match="info.*must match"): + concatenate_raws([raw0, raw3]) + + # Number of channels mismatch + raw4 = _create_toy_data(n_channels=4) + with pytest.raises(ValueError, match="nchan.*must match"): + concatenate_raws([raw0, raw4]) + + +def test_concatenate_raws_order(): + """Test concatenation of raws when the order of *good* channels varies.""" + raw0 = _create_toy_data(n_channels=2) + raw0._data[0] = np.zeros_like(raw0._data[0]) # set one channel zero + + # Create copy and concatenate raws + raw1 = raw0.copy() + raw_concat = concatenate_raws([raw0.copy(), raw1]) + assert raw0.ch_names == raw1.ch_names == raw_concat.ch_names == ["0", "1"] + ch0 = raw_concat.get_data(picks=["0"]) + assert np.all(ch0 == 0) + + # Change the order of the channels and concatenate again + raw1.reorder_channels(["1", "0"]) + assert raw1.ch_names == ["1", "0"] + raws = [raw0.copy(), raw1] + with pytest.raises(ValueError, match="Channel order must match."): + # Fails now due to wrong order of channels + raw_concat = concatenate_raws(raws) + + with pytest.raises(ValueError, match="Channel order must match."): + # still fails, because raws is copied and not changed in place + match_channel_orders(insts=raws, copy=True) + raw_concat = concatenate_raws(raws) + + # Now passes because all raws have the same order + match_channel_orders(insts=raws, copy=False) + raw_concat = concatenate_raws(raws) + ch0 = raw_concat.get_data(picks=["0"]) + assert np.all(ch0 == 0) + + +@testing.requires_testing_data +@pytest.mark.parametrize( + "mod", + ( + "meg", + pytest.param( + "raw", + marks=[ + pytest.mark.filterwarnings( + "ignore:.*naming conventions.*:RuntimeWarning" + ), + pytest.mark.slowtest, + ], + ), + ), +) +def test_split_files(tmp_path, mod, monkeypatch): + """Test writing and reading of split raw files.""" + raw_1 = read_raw_fif(fif_fname, preload=True) + # Test a very close corner case + + assert_allclose(raw_1.buffer_size_sec, 10.0, atol=1e-2) # samp rate + split_fname = tmp_path / f"split_raw_{mod}.fif" + # intended filenames + split_fname_elekta_part2 = tmp_path / f"split_raw_{mod}-1.fif" + split_fname_bids_part1 = tmp_path / f"split_raw_split-01_{mod}.fif" + split_fname_bids_part2 = tmp_path / f"split_raw_split-02_{mod}.fif" + raw_1.set_annotations(Annotations([2.0], [5.5], "test")) + + # Check that if BIDS is used and no split is needed it defaults to + # simple writing without _split- entity. + split_fnames = raw_1.save(split_fname, split_naming="bids", verbose=True) + assert split_fname.is_file() + assert not split_fname_bids_part1.is_file() + assert split_fnames == [split_fname] + + for split_naming in ("neuromag", "bids"): + with pytest.raises(FileExistsError, match="Destination file"): + raw_1.save(split_fname, split_naming=split_naming, verbose=True) + os.remove(split_fname) + with open(split_fname_bids_part1, "w"): + pass + with pytest.raises(FileExistsError, match="Destination file"): + raw_1.save(split_fname, split_naming="bids", verbose=True) + assert not split_fname.is_file() + split_fnames = raw_1.save( + split_fname, split_naming="neuromag", verbose=True + ) # okay + os.remove(split_fname) + os.remove(split_fname_bids_part1) + # Multiple splits + split_filenames = raw_1.save( + split_fname, buffer_size_sec=1.0, split_size="10MB", verbose=True + ) + # check that the filenames match the intended pattern + assert split_fname.is_file() + assert split_fname_elekta_part2.is_file() + assert split_filenames == [split_fname, split_fname_elekta_part2] + # check that filenames are being formatted correctly for BIDS + split_filenames = raw_1.save( + split_fname, + buffer_size_sec=1.0, + split_size="10MB", + split_naming="bids", + overwrite=True, + verbose=True, + ) + assert split_fname_bids_part1.is_file() + assert split_fname_bids_part2.is_file() + assert split_filenames == [split_fname_bids_part1, split_fname_bids_part2] + + annot = Annotations(np.arange(20), np.ones((20,)), "test") + raw_1.set_annotations(annot) + split_fname = tmp_path / f"split_{mod}.fif" + raw_1.save(split_fname, buffer_size_sec=1.0, split_size="10MB") + raw_2 = read_raw_fif(split_fname) + assert_allclose(raw_2.buffer_size_sec, 1.0, atol=1e-2) # samp rate + assert_allclose(raw_1.annotations.onset, raw_2.annotations.onset) + assert_allclose( + raw_1.annotations.duration, + raw_2.annotations.duration, + rtol=0.001 / raw_2.info["sfreq"], + ) + assert_array_equal(raw_1.annotations.description, raw_2.annotations.description) + + data_1, times_1 = raw_1[:, :] + data_2, times_2 = raw_2[:, :] + assert_array_equal(data_1, data_2) + assert_array_equal(times_1, times_2) + + raw_bids = read_raw_fif(split_fname_bids_part1) + data_bids, times_bids = raw_bids[:, :] + assert_array_equal(data_1, data_bids) + assert_array_equal(times_1, times_bids) + del raw_bids + # split missing behaviors + os.remove(split_fname_bids_part2) + with pytest.raises(ValueError, match="manually renamed"): + read_raw_fif(split_fname_bids_part1, on_split_missing="raise") + with pytest.warns(RuntimeWarning, match="Split raw file detected"): + read_raw_fif(split_fname_bids_part1, on_split_missing="warn") + read_raw_fif(split_fname_bids_part1, on_split_missing="ignore") + + # test the case where we only end up with one buffer to write + # (GH#3210). These tests rely on writing meas info and annotations + # taking up a certain number of bytes, so if we change those functions + # somehow, the numbers below for e.g. split_size might need to be + # adjusted. + raw_crop = raw_1.copy().crop(0, 5) + raw_crop.set_annotations(Annotations([2.0], [5.5], "test"), emit_warning=False) + with pytest.raises(ValueError, match="after writing measurement information"): + raw_crop.save( + split_fname, + split_size="1MB", # too small a size + buffer_size_sec=1.0, + overwrite=True, + ) + with pytest.raises(ValueError, match="too large for the given split size"): + raw_crop.save( + split_fname, + split_size=3003000, # still too small, now after Info + buffer_size_sec=1.0, + overwrite=True, + ) + # just barely big enough here; the right size to write exactly one buffer + # at a time so we hit GH#3210 if we aren't careful + raw_crop.save(split_fname, split_size="4.5MB", buffer_size_sec=1.0, overwrite=True) + raw_read = read_raw_fif(split_fname) + assert_allclose(raw_crop[:][0], raw_read[:][0], atol=1e-20) + + # Check our buffer arithmetic + + # 1 buffer required + raw_crop = raw_1.copy().crop(0, 1) + raw_crop.save(split_fname, buffer_size_sec=1.0, overwrite=True) + raw_read = read_raw_fif(split_fname) + assert_array_equal(np.diff(raw_read._raw_extras[0]["bounds"]), (301,)) + assert_allclose(raw_crop[:][0], raw_read[:][0]) + # 2 buffers required + raw_crop.save(split_fname, buffer_size_sec=0.5, overwrite=True) + raw_read = read_raw_fif(split_fname) + assert_array_equal(np.diff(raw_read._raw_extras[0]["bounds"]), (151, 150)) + assert_allclose(raw_crop[:][0], raw_read[:][0]) + # 2 buffers required + raw_crop.save( + split_fname, buffer_size_sec=1.0 - 1.01 / raw_crop.info["sfreq"], overwrite=True + ) + raw_read = read_raw_fif(split_fname) + assert_array_equal(np.diff(raw_read._raw_extras[0]["bounds"]), (300, 1)) + assert_allclose(raw_crop[:][0], raw_read[:][0]) + raw_crop.save( + split_fname, buffer_size_sec=1.0 - 2.01 / raw_crop.info["sfreq"], overwrite=True + ) + raw_read = read_raw_fif(split_fname) + assert_array_equal(np.diff(raw_read._raw_extras[0]["bounds"]), (299, 2)) + assert_allclose(raw_crop[:][0], raw_read[:][0]) + + # proper ending + assert tmp_path.is_dir() + with pytest.raises(ValueError, match="must end with an underscore"): + raw_crop.save(tmp_path / "test.fif", split_naming="bids", verbose="error") + + # reserved file is deleted + fname = tmp_path / f"test_{mod}.fif" + with monkeypatch.context() as m: + m.setattr(base, "_write_raw_data", _err) + with pytest.raises(RuntimeError, match="Killed mid-write"): + raw_1.save(fname, split_size="10MB", split_naming="bids") + assert fname.is_file() + assert not (tmp_path / "test_split-01_{mod}.fif").is_file() + + # MAX_N_SPLITS exceeded + raw = RawArray(np.zeros((1, 2000000)), create_info(1, 1000.0, "eeg")) + fname.unlink() + kwargs = dict(split_size="2MB", overwrite=True, verbose=True) + with monkeypatch.context() as m: + m.setattr(base, "MAX_N_SPLITS", 2) + with pytest.raises(RuntimeError, match="Exceeded maximum number of splits"): + raw.save(fname, split_naming="bids", **kwargs) + fname_1, fname_2, fname_3 = ( + (tmp_path / f"test_split-{ii:02d}_{mod}.fif") for ii in range(1, 4) + ) + assert not fname.is_file() + assert fname_1.is_file() + assert fname_2.is_file() + assert not fname_3.is_file() + with monkeypatch.context() as m: + m.setattr(base, "MAX_N_SPLITS", 2) + with pytest.raises(RuntimeError, match="Exceeded maximum number of splits"): + raw.save(fname, split_naming="neuromag", **kwargs) + fname_2, fname_3 = ((tmp_path / f"test_{mod}-{ii}.fif") for ii in range(1, 3)) + assert fname.is_file() + assert fname_2.is_file() + assert not fname_3.is_file() + + +def test_bids_split_files(tmp_path): + """Test that BIDS split files are written safely.""" + mne_bids = pytest.importorskip("mne_bids") + bids_path = mne_bids.BIDSPath( + root=tmp_path, + subject="01", + datatype="meg", + split="01", + suffix="raw", + extension=".fif", + check=False, + ) + (tmp_path / "sub-01" / "meg").mkdir(parents=True) + raw = read_raw_fif(test_fif_fname) + save_kwargs = dict( + buffer_size_sec=1.0, split_size="10MB", split_naming="bids", verbose=True + ) + with pytest.raises(ValueError, match="Passing a BIDSPath"): + raw.save(bids_path, **save_kwargs) + bids_path.split = None + want_paths = [ + Path(bids_path.copy().update(split=f"{ii:02d}").fpath) for ii in range(1, 3) + ] + for want_path in want_paths: + assert not want_path.is_file() + raw.save(bids_path, **save_kwargs) + for want_path in want_paths: + assert want_path.is_file(), want_path + + +def _err(*args, **kwargs): + raise RuntimeError("Killed mid-write") + + +def _no_write_file_name(fid, kind, data): + assert kind == FIFF.FIFF_REF_FILE_NAME # the only string we actually write + return + + +def test_split_numbers(tmp_path, monkeypatch): + """Test handling of split files using numbers instead of names.""" + monkeypatch.setattr(base, "write_string", _no_write_file_name) + raw = read_raw_fif(test_fif_fname).pick("eeg") + # gh-8339 + dashes_fname = tmp_path / "sub-1_ses-2_task-3_raw.fif" + raw.save(dashes_fname, split_size="5MB", buffer_size_sec=1.0) + assert dashes_fname.is_file() + next_fname = Path(str(dashes_fname)[:-4] + "-1.fif") + assert next_fname.is_file() + raw_read = read_raw_fif(dashes_fname) + assert_allclose(raw.times, raw_read.times) + assert_allclose(raw.get_data(), raw_read.get_data(), atol=1e-16) + + +def test_load_bad_channels(tmp_path): + """Test reading/writing of bad channels.""" + # Load correctly marked file (manually done in mne_process_raw) + raw_marked = read_raw_fif(fif_bad_marked_fname) + correct_bads = raw_marked.info["bads"] + raw = read_raw_fif(test_fif_fname) + # Make sure it starts clean + assert_array_equal(raw.info["bads"], []) + + # Test normal case + raw.load_bad_channels(bad_file_works) + # Write it out, read it in, and check + raw.save(tmp_path / "foo_raw.fif") + raw_new = read_raw_fif(tmp_path / "foo_raw.fif") + assert correct_bads == raw_new.info["bads"] + # Reset it + raw.info["bads"] = [] + + # Test bad case + pytest.raises(ValueError, raw.load_bad_channels, bad_file_wrong) + + # Test forcing the bad case + with pytest.warns(RuntimeWarning, match="1 bad channel"): + raw.load_bad_channels(bad_file_wrong, force=True) + + # write it out, read it in, and check + raw.save(tmp_path / "foo_raw.fif", overwrite=True) + raw_new = read_raw_fif(tmp_path / "foo_raw.fif") + assert correct_bads == raw_new.info["bads"] + + # Check that bad channels are cleared + raw.load_bad_channels(None) + raw.save(tmp_path / "foo_raw.fif", overwrite=True) + raw_new = read_raw_fif(tmp_path / "foo_raw.fif") + assert raw_new.info["bads"] == [] + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_io_raw(tmp_path): + """Test IO for raw data (Neuromag).""" + rng = np.random.RandomState(0) + # test unicode io + for chars in ["äöé", "a"]: + with read_raw_fif(fif_fname) as r: + assert "Raw" in repr(r) + assert fif_fname.name in repr(r) + r.info["description"] = chars + temp_file = tmp_path / "raw.fif" + r.save(temp_file, overwrite=True) + with read_raw_fif(temp_file) as r2: + desc2 = r2.info["description"] + assert desc2 == chars + + # Let's construct a simple test for IO first + raw = read_raw_fif(fif_fname).crop(0, 3.5) + raw.load_data() + # put in some data that we know the values of + data = rng.randn(raw._data.shape[0], raw._data.shape[1]) + raw._data[:, :] = data + # save it somewhere + fname = tmp_path / "test_copy_raw.fif" + raw.save(fname, buffer_size_sec=1.0) + # read it in, make sure the whole thing matches + raw = read_raw_fif(fname) + assert_allclose(data, raw[:, :][0], rtol=1e-6, atol=1e-20) + # let's read portions across the 1-s tag boundary, too + inds = raw.time_as_index([1.75, 2.25]) + sl = slice(inds[0], inds[1]) + assert_allclose(data[:, sl], raw[:, sl][0], rtol=1e-6, atol=1e-20) + + # missing dir raises informative error + with pytest.raises(FileNotFoundError, match="parent directory does not exist"): + raw.save(tmp_path / "foo" / "test_raw.fif", split_size="1MB") + + +@pytest.mark.parametrize( + "fname_in, fname_out", + [ + (test_fif_fname, "raw.fif"), + pytest.param(test_fif_gz_fname, "raw.fif.gz", marks=pytest.mark.slowtest), + (ctf_fname, "raw.fif"), + ], +) +def test_io_raw_additional(fname_in, fname_out, tmp_path): + """Test IO for raw data (Neuromag + CTF + gz).""" + fname_out = tmp_path / fname_out + raw = read_raw_fif(fname_in).crop(0, 2) + + nchan = raw.info["nchan"] + ch_names = raw.info["ch_names"] + meg_channels_idx = [k for k in range(nchan) if ch_names[k][0] == "M"] + n_channels = 100 + meg_channels_idx = meg_channels_idx[:n_channels] + start, stop = raw.time_as_index([0, 5], use_rounding=True) + data, times = raw[meg_channels_idx, start : (stop + 1)] + meg_ch_names = [ch_names[k] for k in meg_channels_idx] + + # Set up pick list: MEG + STI 014 - bad channels + include = ["STI 014"] + include += meg_ch_names + picks = pick_types( + raw.info, + meg=True, + eeg=False, + stim=True, + misc=True, + ref_meg=True, + include=include, + exclude="bads", + ) + + # Writing with drop_small_buffer True + raw.save( + fname_out, + picks, + tmin=0, + tmax=4, + buffer_size_sec=3, + drop_small_buffer=True, + overwrite=True, + ) + raw2 = read_raw_fif(fname_out) + + sel = pick_channels(raw2.ch_names, meg_ch_names) + data2, times2 = raw2[sel, :] + assert times2.max() <= 3 + + # Writing + raw.save(fname_out, picks, tmin=0, tmax=5, overwrite=True) + + if fname_in in (fif_fname, fif_fname.with_suffix(fif_fname.suffix + ".gz")): + assert len(raw.info["dig"]) == 146 + + raw2 = read_raw_fif(fname_out) + + sel = pick_channels(raw2.ch_names, meg_ch_names) + data2, times2 = raw2[sel, :] + + assert_allclose(data, data2, rtol=1e-6, atol=1e-20) + assert_allclose(times, times2) + assert_allclose(raw.info["sfreq"], raw2.info["sfreq"], rtol=1e-5) + + # check transformations + for trans in ["dev_head_t", "dev_ctf_t", "ctf_head_t"]: + if raw.info[trans] is None: + assert raw2.info[trans] is None + else: + assert_array_equal(raw.info[trans]["trans"], raw2.info[trans]["trans"]) + + # check transformation 'from' and 'to' + if trans.startswith("dev"): + from_id = FIFF.FIFFV_COORD_DEVICE + else: + from_id = FIFF.FIFFV_MNE_COORD_CTF_HEAD + if trans[4:8] == "head": + to_id = FIFF.FIFFV_COORD_HEAD + else: + to_id = FIFF.FIFFV_MNE_COORD_CTF_HEAD + for raw_ in [raw, raw2]: + assert raw_.info[trans]["from"] == from_id + assert raw_.info[trans]["to"] == to_id + + if fname_in in (fif_fname, fif_fname.with_suffix(fif_fname.suffix + ".gz")): + assert_allclose(raw.info["dig"][0]["r"], raw2.info["dig"][0]["r"]) + + # test warnings on bad filenames + raw_badname = tmp_path / "test-bad-name.fif.gz" + with pytest.warns(RuntimeWarning, match="raw.fif"): + raw.save(raw_badname) + with pytest.warns(RuntimeWarning, match="raw.fif"): + read_raw_fif(raw_badname) + + +@testing.requires_testing_data +@pytest.mark.parametrize("dtype", ("complex128", "complex64")) +def test_io_complex(tmp_path, dtype): + """Test IO with complex data types.""" + rng = np.random.RandomState(0) + n_ch = 5 + raw = read_raw_fif(fif_fname).crop(0, 1).pick(np.arange(n_ch)).load_data() + data_orig = raw.get_data() + imag_rand = np.array(1j * rng.randn(n_ch, len(raw.times)), dtype=dtype) + raw_cp = raw.copy() + raw_cp._data = np.array(raw_cp._data, dtype) + raw_cp._data += imag_rand + with pytest.warns(RuntimeWarning, match="Saving .* complex data."): + raw_cp.save(tmp_path / "raw.fif", overwrite=True) + + raw2 = read_raw_fif(tmp_path / "raw.fif") + raw2_data, _ = raw2[:] + assert_allclose(raw2_data, raw_cp._data) + # with preloading + raw2 = read_raw_fif(tmp_path / "raw.fif", preload=True) + raw2_data, _ = raw2[:] + assert_allclose(raw2_data, raw_cp._data) + assert_allclose(data_orig, raw_cp._data.real) + + +@testing.requires_testing_data +def test_getitem(): + """Test getitem/indexing of Raw.""" + for preload in [False, True, "memmap1.dat"]: + raw = read_raw_fif(fif_fname, preload=preload) + data, times = raw[0, :] + data1, times1 = raw[0] + assert_array_equal(data, data1) + assert_array_equal(times, times1) + data, times = raw[0:2, :] + data1, times1 = raw[0:2] + assert_array_equal(data, data1) + assert_array_equal(times, times1) + data1, times1 = raw[[0, 1]] + assert_array_equal(data, data1) + assert_array_equal(times, times1) + assert_array_equal(raw[raw.ch_names[0]][0][0], raw[0][0][0]) + assert_array_equal( + raw[-10:-1, :][0], raw[len(raw.ch_names) - 10 : len(raw.ch_names) - 1, :][0] + ) + with pytest.raises(ValueError, match="No appropriate channels"): + raw[slice(-len(raw.ch_names) - 1), slice(None)] + with pytest.raises(IndexError, match="must be"): + raw[-1000] + + +@testing.requires_testing_data +def test_iter(): + """Test iterating over Raw via __getitem__().""" + raw = read_raw_fif(fif_fname).pick("eeg") # 60 EEG channels + for i, _ in enumerate(raw): # iterate over channels + pass + assert i == 59 # 60 channels means iterating from 0 to 59 + + +@testing.requires_testing_data +def test_proj(tmp_path): + """Test SSP proj operations.""" + for proj in [True, False]: + raw = read_raw_fif(fif_fname, preload=False) + if proj: + raw.apply_proj() + assert all(p["active"] == proj for p in raw.info["projs"]) + + data, times = raw[0:2, :] + data1, times1 = raw[0:2] + assert_array_equal(data, data1) + assert_array_equal(times, times1) + + # test adding / deleting proj + if proj: + pytest.raises(ValueError, raw.add_proj, [], {"remove_existing": True}) + pytest.raises(ValueError, raw.del_proj, 0) + else: + projs = deepcopy(raw.info["projs"]) + n_proj = len(raw.info["projs"]) + raw.del_proj(0) + assert len(raw.info["projs"]) == n_proj - 1 + raw.add_proj(projs, remove_existing=False) + # Test that already existing projections are not added. + assert len(raw.info["projs"]) == n_proj + raw.add_proj(projs[:-1], remove_existing=True) + assert len(raw.info["projs"]) == n_proj - 1 + + # test apply_proj() with and without preload + for preload in [True, False]: + raw = read_raw_fif(fif_fname, preload=preload) + data, times = raw[:, 0:2] + raw.apply_proj() + data_proj_1 = np.dot(raw._projector, data) + + # load the file again without proj + raw = read_raw_fif(fif_fname, preload=preload) + + # write the file with proj. activated, make sure proj has been applied + raw.save(tmp_path / "raw.fif", proj=True, overwrite=True) + raw2 = read_raw_fif(tmp_path / "raw.fif") + data_proj_2, _ = raw2[:, 0:2] + assert_allclose(data_proj_1, data_proj_2) + assert all(p["active"] for p in raw2.info["projs"]) + + # read orig file with proj. active + raw2 = read_raw_fif(fif_fname, preload=preload) + raw2.apply_proj() + data_proj_2, _ = raw2[:, 0:2] + assert_allclose(data_proj_1, data_proj_2) + assert all(p["active"] for p in raw2.info["projs"]) + + # test that apply_proj works + raw.apply_proj() + data_proj_2, _ = raw[:, 0:2] + assert_allclose(data_proj_1, data_proj_2) + assert_allclose(data_proj_2, np.dot(raw._projector, data_proj_2)) + + # Test that picking removes projectors ... + raw = read_raw_fif(fif_fname) + n_projs = len(raw.info["projs"]) + raw.pick(picks="eeg") + assert len(raw.info["projs"]) == n_projs - 3 + + # ... but only if it doesn't apply to any channels in the dataset anymore. + raw = read_raw_fif(fif_fname) + n_projs = len(raw.info["projs"]) + raw.pick(picks=["mag", "eeg"]) + assert len(raw.info["projs"]) == n_projs + + # I/O roundtrip of an MEG projector with a Raw that only contains EEG + # data. + out_fname = tmp_path / "test_raw.fif" + raw = read_raw_fif(test_fif_fname, preload=True).crop(0, 0.002) + proj = raw.info["projs"][-1] + raw.pick(picks="eeg") + raw.add_proj(proj) # Restore, because picking removed it! + raw._data.fill(0) + raw._data[-1] = 1.0 + raw.save(out_fname) + raw = read_raw_fif(out_fname, preload=False) + raw.apply_proj() + assert_allclose(raw[:, :][0][:1], raw[0, :][0]) + + +@testing.requires_testing_data +@pytest.mark.parametrize("preload", [False, True, "memmap2.dat"]) +def test_preload_modify(preload, tmp_path): + """Test preloading and modifying data.""" + rng = np.random.RandomState(0) + raw = read_raw_fif(fif_fname, preload=preload) + + nsamp = raw.last_samp - raw.first_samp + 1 + picks = pick_types(raw.info, meg="grad", exclude="bads") + + data = rng.randn(len(picks), nsamp // 2) + + try: + raw[picks, : nsamp // 2] = data + except RuntimeError: + if not preload: + return + else: + raise + + tmp_fname = tmp_path / "raw.fif" + raw.save(tmp_fname, overwrite=True) + + raw_new = read_raw_fif(tmp_fname) + data_new, _ = raw_new[picks, : nsamp // 2] + + assert_allclose(data, data_new) + + +@pytest.mark.slowtest +@testing.requires_testing_data +def test_filter(): + """Test filtering (FIR and IIR) and Raw.apply_function interface.""" + raw = read_raw_fif(fif_fname).crop(0, 7) + raw.load_data() + sig_dec_notch = 12 + sig_dec_notch_fit = 12 + picks_meg = pick_types(raw.info, meg=True, exclude="bads") + picks = picks_meg[:4] + + trans = 2.0 + filter_params = dict( + picks=picks, + filter_length="auto", + h_trans_bandwidth=trans, + l_trans_bandwidth=trans, + fir_design="firwin", + ) + raw_lp = raw.copy().filter(None, 8.0, **filter_params) + raw_hp = raw.copy().filter(16.0, None, **filter_params) + raw_bp = raw.copy().filter(8.0 + trans, 16.0 - trans, **filter_params) + raw_bs = raw.copy().filter(16.0, 8.0, **filter_params) + + data, _ = raw[picks, :] + + lp_data, _ = raw_lp[picks, :] + hp_data, _ = raw_hp[picks, :] + bp_data, _ = raw_bp[picks, :] + bs_data, _ = raw_bs[picks, :] + + tols = dict(atol=1e-20, rtol=1e-5) + assert_allclose(bs_data, lp_data + hp_data, **tols) + assert_allclose(data, lp_data + bp_data + hp_data, **tols) + assert_allclose(data, bp_data + bs_data, **tols) + + filter_params_iir = dict( + picks=picks, n_jobs=2, method="iir", iir_params=dict(output="ba") + ) + raw_lp_iir = raw.copy().filter(None, 4.0, **filter_params_iir) + raw_hp_iir = raw.copy().filter(8.0, None, **filter_params_iir) + raw_bp_iir = raw.copy().filter(4.0, 8.0, **filter_params_iir) + del filter_params_iir + lp_data_iir, _ = raw_lp_iir[picks, :] + hp_data_iir, _ = raw_hp_iir[picks, :] + bp_data_iir, _ = raw_bp_iir[picks, :] + summation = lp_data_iir + hp_data_iir + bp_data_iir + assert_array_almost_equal(data[:, 100:-100], summation[:, 100:-100], 11) + + # make sure we didn't touch other channels + data, _ = raw[picks_meg[4:], :] + bp_data, _ = raw_bp[picks_meg[4:], :] + assert_array_equal(data, bp_data) + bp_data_iir, _ = raw_bp_iir[picks_meg[4:], :] + assert_array_equal(data, bp_data_iir) + + # ... and that inplace changes are inplace + raw_copy = raw.copy() + assert np.may_share_memory(raw._data, raw._data) + assert not np.may_share_memory(raw_copy._data, raw._data) + # this could be assert_array_equal but we do this to mirror the call below + assert (raw._data[0] == raw_copy._data[0]).all() + raw_copy.filter(None, 20.0, n_jobs=2, **filter_params) + assert not (raw._data[0] == raw_copy._data[0]).all() + assert_array_equal( + raw.copy().filter(None, 20.0, **filter_params)._data, raw_copy._data + ) + + # do a very simple check on line filtering + raw_bs = raw.copy().filter(60.0 + trans, 60.0 - trans, **filter_params) + data_bs, _ = raw_bs[picks, :] + raw_notch = raw.copy().notch_filter( + 60.0, picks=picks, n_jobs=2, method="fir", trans_bandwidth=2 * trans + ) + data_notch, _ = raw_notch[picks, :] + assert_array_almost_equal(data_bs, data_notch, sig_dec_notch) + + # now use the sinusoidal fitting + assert raw.times[-1] < 10 # catch error with filter_length > n_times + raw_notch = raw.copy().notch_filter( + None, picks=picks, n_jobs=2, method="spectrum_fit", filter_length="10s" + ) + data_notch, _ = raw_notch[picks, :] + data, _ = raw[picks, :] + assert_array_almost_equal(data, data_notch, sig_dec_notch_fit) + + # filter should set the "lowpass" and "highpass" parameters + raw = RawArray( + np.random.randn(3, 1000), create_info(3, 1000.0, ["eeg"] * 2 + ["stim"]) + ) + with raw.info._unlock(): + raw.info["lowpass"] = raw.info["highpass"] = None + for kind in ("none", "lowpass", "highpass", "bandpass", "bandstop"): + print(kind) + h_freq = l_freq = None + if kind in ("lowpass", "bandpass"): + h_freq = 70 + if kind in ("highpass", "bandpass"): + l_freq = 30 + if kind == "bandstop": + l_freq, h_freq = 70, 30 + assert raw.info["lowpass"] is None + assert raw.info["highpass"] is None + kwargs = dict( + l_trans_bandwidth=20, + h_trans_bandwidth=20, + filter_length="auto", + phase="zero", + fir_design="firwin", + ) + raw_filt = raw.copy().filter(l_freq, h_freq, picks=np.arange(1), **kwargs) + assert raw.info["lowpass"] is None + assert raw.info["highpass"] is None + raw_filt = raw.copy().filter(l_freq, h_freq, **kwargs) + wanted_h = h_freq if kind != "bandstop" else None + wanted_l = l_freq if kind != "bandstop" else None + assert raw_filt.info["lowpass"] == wanted_h + assert raw_filt.info["highpass"] == wanted_l + # Using all data channels should still set the params (GH#3259) + raw_filt = raw.copy().filter(l_freq, h_freq, picks=np.arange(2), **kwargs) + assert raw_filt.info["lowpass"] == wanted_h + assert raw_filt.info["highpass"] == wanted_l + + +def test_filter_picks(): + """Test filtering default channel picks.""" + ch_types = [ + "mag", + "grad", + "eeg", + "seeg", + "dbs", + "misc", + "stim", + "ecog", + "hbo", + "hbr", + ] + info = create_info(ch_names=ch_types, ch_types=ch_types, sfreq=256) + raw = RawArray(data=np.zeros((len(ch_types), 1000)), info=info) + + # -- Deal with meg mag grad and fnirs exceptions + ch_types = ("misc", "stim", "meg", "eeg", "seeg", "dbs", "ecog") + + # -- Filter data channels + for ch_type in ("mag", "grad", "eeg", "seeg", "dbs", "ecog", "hbo", "hbr"): + picks = {ch: ch == ch_type for ch in ch_types} + picks["meg"] = ch_type if ch_type in ("mag", "grad") else False + picks["fnirs"] = ch_type if ch_type in ("hbo", "hbr") else False + raw_ = raw.copy().pick_types(**picks) + raw_.filter(10, 30, fir_design="firwin") + + # -- Error if no data channel + for ch_type in ("misc", "stim"): + picks = {ch: ch == ch_type for ch in ch_types} + raw_ = raw.copy().pick_types(**picks) + pytest.raises(ValueError, raw_.filter, 10, 30) + + +@testing.requires_testing_data +def test_crop(): + """Test cropping raw files.""" + # split a concatenated file to test a difficult case + raw = concatenate_raws([read_raw_fif(f) for f in [fif_fname, fif_fname]]) + split_size = 10.0 # in seconds + sfreq = raw.info["sfreq"] + nsamp = raw.last_samp - raw.first_samp + 1 + + # do an annoying case (off-by-one splitting) + tmins = np.r_[1.0, np.round(np.arange(0.0, nsamp - 1, split_size * sfreq))] + tmins = np.sort(tmins) + tmaxs = np.concatenate((tmins[1:] - 1, [nsamp - 1])) + tmaxs /= sfreq + tmins /= sfreq + raws = [None] * len(tmins) + for ri, (tmin, tmax) in enumerate(zip(tmins, tmaxs)): + raws[ri] = raw.copy().crop(tmin, tmax) + if ri < len(tmins) - 1: + assert_allclose( + raws[ri].times, + raw.copy().crop(tmin, tmins[ri + 1], include_tmax=False).times, + ) + assert raws[ri] + all_raw_2 = concatenate_raws(raws, preload=False) + assert raw.first_samp == all_raw_2.first_samp + assert raw.last_samp == all_raw_2.last_samp + assert_array_equal(raw[:, :][0], all_raw_2[:, :][0]) + + tmins = np.round(np.arange(0.0, nsamp - 1, split_size * sfreq)) + tmaxs = np.concatenate((tmins[1:] - 1, [nsamp - 1])) + tmaxs /= sfreq + tmins /= sfreq + + # going in reverse order so the last fname is the first file (need it + # later) + raws = [None] * len(tmins) + for ri, (tmin, tmax) in enumerate(zip(tmins, tmaxs)): + raws[ri] = raw.copy().crop(tmin, tmax) + # test concatenation of split file + all_raw_1 = concatenate_raws(raws, preload=False) + + all_raw_2 = raw.copy().crop(0, None) + for ar in [all_raw_1, all_raw_2]: + assert raw.first_samp == ar.first_samp + assert raw.last_samp == ar.last_samp + assert_array_equal(raw[:, :][0], ar[:, :][0]) + + # test shape consistency of cropped raw + data = np.zeros((1, 1002001)) + info = create_info(1, 1000) + raw = RawArray(data, info) + for tmin in range(0, 1001, 100): + raw1 = raw.copy().crop(tmin=tmin, tmax=tmin + 2) + assert raw1[:][0].shape == (1, 2001) + + # degenerate + with pytest.raises(ValueError, match="No samples.*when include_tmax=False"): + raw.crop(0, 0, include_tmax=False) + + # edge cases cropping to exact duration +/- 1 sample + data = np.zeros((1, 100)) + info = create_info(1, 100) + raw = RawArray(data, info) + with pytest.raises(ValueError, match="tmax \\(1\\) must be less than or "): + raw.copy().crop(tmax=1, include_tmax=True) + raw1 = raw.copy().crop(tmax=1 - 1 / raw.info["sfreq"], include_tmax=True) + assert raw.n_times == raw1.n_times + raw2 = raw.copy().crop(tmax=1, include_tmax=False) + assert raw.n_times == raw2.n_times + raw3 = raw.copy().crop(tmax=1 - 1 / raw.info["sfreq"], include_tmax=False) + assert raw.n_times - 1 == raw3.n_times + + +@testing.requires_testing_data +def test_resample_with_events(): + """Test resampling raws with events.""" + raw = read_raw_fif(fif_fname) + raw.resample(250) # pretend raw is recorded at 250 Hz + events, _ = events_from_annotations(raw) + raw, events = raw.resample(250, events=events) + + +@testing.requires_testing_data +def test_resample_equiv(): + """Test resample (with I/O and multiple files).""" + raw = read_raw_fif(fif_fname).crop(0, 1) + raw_preload = raw.copy().load_data() + for r in (raw, raw_preload): + r.resample(r.info["sfreq"] / 4.0) + assert_allclose(raw._data, raw_preload._data) + + +@pytest.mark.slowtest +@testing.requires_testing_data +@pytest.mark.parametrize( + "preload, n, npad, method", + [ + (True, 512, "auto", "fft"), + (True, 512, "auto", "polyphase"), + (False, 512, 0, "fft"), # only test one with non-preload because it's slow + ], +) +def test_resample(tmp_path, preload, n, npad, method): + """Test resample (with I/O and multiple files).""" + kwargs = dict(npad=npad, method=method) + raw = read_raw_fif(fif_fname) + raw.crop(0, raw.times[n - 1]) + # Reduce to a few MEG channels and a few stim channels to speed up + n_meg = 5 + raw.pick(raw.ch_names[:n_meg] + raw.ch_names[312:320]) # 10 MEG + 3 STIM + 5 EEG + assert len(raw.times) == n + if preload: + raw.load_data() + raw_resamp = raw.copy() + sfreq = raw.info["sfreq"] + # test parallel on upsample + raw_resamp.resample(sfreq * 2, n_jobs=2, **kwargs) + assert raw_resamp.n_times == len(raw_resamp.times) + raw_resamp.save(tmp_path / "raw_resamp-raw.fif") + raw_resamp = read_raw_fif(tmp_path / "raw_resamp-raw.fif", preload=True) + assert sfreq == raw_resamp.info["sfreq"] / 2 + assert raw.n_times == raw_resamp.n_times // 2 + assert raw_resamp.get_data().shape[1] == raw_resamp.n_times + assert raw.get_data().shape[0] == raw_resamp._data.shape[0] + # test non-parallel on downsample + with catch_logging() as log: + raw_resamp.resample(sfreq, n_jobs=None, verbose=True, **kwargs) + log = log.getvalue() + if method == "fft": + assert "neighborhood" not in log + else: + assert "neighborhood" in log + assert raw_resamp.info["sfreq"] == sfreq + assert raw.get_data().shape == raw_resamp._data.shape + assert raw.first_samp == raw_resamp.first_samp + assert raw.last_samp == raw.last_samp + # upsampling then downsampling doubles resampling error, but this still + # works (hooray). Note that the stim channels had to be sub-sampled + # without filtering to be accurately preserved + # note we have to treat MEG and EEG+STIM channels differently (tols) + want_meg = raw.get_data()[:n_meg, 200:-200] + got_meg = raw_resamp._data[:n_meg, 200:-200] + want_non_meg = raw.get_data()[n_meg:, 200:-200] + got_non_meg = raw_resamp._data[n_meg:, 200:-200] + assert_allclose(got_meg, want_meg, rtol=1e-2, atol=1e-12) + assert_allclose(want_non_meg, got_non_meg, rtol=1e-2, atol=1e-7) + + # now check multiple file support w/resampling, as order of operations + # (concat, resample) should not affect our data + raw1 = raw.copy() + raw2 = raw.copy() + raw3 = raw.copy() + raw4 = raw.copy() + raw1 = concatenate_raws([raw1, raw2]) + raw1.resample(10.0, **kwargs) + raw3.resample(10.0, **kwargs) + raw4.resample(10.0, **kwargs) + raw3 = concatenate_raws([raw3, raw4]) + assert_array_equal(raw1._data, raw3._data) + assert_array_equal(raw1._first_samps, raw3._first_samps) + assert_array_equal(raw1._last_samps, raw3._last_samps) + assert_array_equal(raw1._raw_lengths, raw3._raw_lengths) + assert raw1.first_samp == raw3.first_samp + assert raw1.last_samp == raw3.last_samp + assert raw1.info["sfreq"] == raw3.info["sfreq"] + + # smoke test crop after resample + raw4.crop(tmin=raw4.times[1], tmax=raw4.times[-1]) + + # test resampling of stim channel + + # basic decimation + stim = [1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0] + raw = RawArray([stim], create_info(1, len(stim), ["stim"])) + assert_allclose(raw.resample(8.0, **kwargs)._data, [[1, 1, 0, 0, 1, 1, 0, 0]]) + + # decimation of multiple stim channels + raw = RawArray(2 * [stim], create_info(2, len(stim), 2 * ["stim"])) + assert_allclose( + raw.resample(8.0, **kwargs, verbose="error")._data, + [[1, 1, 0, 0, 1, 1, 0, 0], [1, 1, 0, 0, 1, 1, 0, 0]], + ) + + # decimation that could potentially drop events if the decimation is + # done naively + stim = [0, 0, 0, 1, 1, 0, 0, 0] + raw = RawArray([stim], create_info(1, len(stim), ["stim"])) + assert_allclose(raw.resample(4.0, **kwargs)._data, [[0, 1, 1, 0]]) + + # two events are merged in this case (warning) + stim = [0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0] + raw = RawArray([stim], create_info(1, len(stim), ["stim"])) + with pytest.warns(RuntimeWarning, match="become unreliable"): + raw.resample(8.0, **kwargs) + + # events are dropped in this case (warning) + stim = [0, 1, 1, 0, 0, 1, 1, 0] + raw = RawArray([stim], create_info(1, len(stim), ["stim"])) + with pytest.warns(RuntimeWarning, match="become unreliable"): + raw.resample(4.0, **kwargs) + + # test resampling events: this should no longer give a warning + # we often have first_samp != 0, include it here too + stim = [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1] # an event at end + # test is on half the sfreq, but should work with trickier ones too + o_sfreq, sfreq_ratio = len(stim), 0.5 + n_sfreq = o_sfreq * sfreq_ratio + first_samp = len(stim) // 2 + raw = RawArray([stim], create_info(1, o_sfreq, ["stim"]), first_samp=first_samp) + events = find_events(raw) + raw, events = raw.resample(n_sfreq, events=events, **kwargs) + # Try index into raw.times with resampled events: + raw.times[events[:, 0] - raw.first_samp] + n_fsamp = int(first_samp * sfreq_ratio) # how it's calc'd in base.py + # NB np.round used for rounding event times, which has 0.5 as corner case: + # https://docs.scipy.org/doc/numpy/reference/generated/numpy.around.html + assert_array_equal( + events, + np.array( + [ + [np.round(1 * sfreq_ratio) + n_fsamp, 0, 1], + [np.round(10 * sfreq_ratio) + n_fsamp, 0, 1], + [ + np.minimum(np.round(15 * sfreq_ratio), raw._data.shape[1] - 1) + + n_fsamp, + 0, + 1, + ], + ] + ), + ) + + # test copy flag + stim = [1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0] + raw = RawArray([stim], create_info(1, len(stim), ["stim"])) + raw_resampled = raw.copy().resample(4.0, **kwargs) + assert raw_resampled is not raw + raw_resampled = raw.resample(4.0, **kwargs) + assert raw_resampled is raw + + # resample should still work even when no stim channel is present + raw = RawArray(np.random.randn(1, 100), create_info(1, 100, ["eeg"])) + with raw.info._unlock(): + raw.info["lowpass"] = 50.0 + raw.resample(10, **kwargs) + assert raw.info["lowpass"] == 5.0 + assert len(raw) == 10 + + +def test_resample_stim(): + """Test stim_picks argument.""" + data = np.ones((2, 1000)) + info = create_info(2, 1000.0, ("eeg", "misc")) + raw = RawArray(data, info) + raw.resample(500.0, stim_picks="misc") + + +@testing.requires_testing_data +def test_hilbert(): + """Test computation of analytic signal using hilbert.""" + raw = read_raw_fif(fif_fname, preload=True) + picks_meg = pick_types(raw.info, meg=True, exclude="bads") + picks = picks_meg[:4] + + raw_filt = raw.copy() + raw_filt.filter( + 10, + 20, + picks=picks, + l_trans_bandwidth="auto", + h_trans_bandwidth="auto", + filter_length="auto", + phase="zero", + fir_window="blackman", + fir_design="firwin", + ) + raw_filt_2 = raw_filt.copy() + + raw2 = raw.copy() + raw3 = raw.copy() + raw.apply_hilbert(picks, n_fft="auto") + raw2.apply_hilbert(picks, n_fft="auto", envelope=True) + + # Test custom n_fft + raw_filt.apply_hilbert(picks, n_fft="auto") + n_fft = 2 ** int(np.ceil(np.log2(raw_filt_2.n_times + 1000))) + raw_filt_2.apply_hilbert(picks, n_fft=n_fft) + assert raw_filt._data.shape == raw_filt_2._data.shape + assert_allclose( + raw_filt._data[:, 50:-50], raw_filt_2._data[:, 50:-50], atol=1e-13, rtol=1e-2 + ) + with pytest.raises(ValueError, match="n_fft.*must be at least the number"): + raw3.apply_hilbert(picks, n_fft=raw3.n_times - 100) + + env = np.abs(raw._data[picks, :]) + assert_allclose(env, raw2._data[picks, :], rtol=1e-2, atol=1e-13) + + +@testing.requires_testing_data +def test_raw_copy(): + """Test Raw copy.""" + raw = read_raw_fif(fif_fname, preload=True) + data, _ = raw[:, :] + copied = raw.copy() + copied_data, _ = copied[:, :] + assert_array_equal(data, copied_data) + assert sorted(raw.__dict__.keys()) == sorted(copied.__dict__.keys()) + + raw = read_raw_fif(fif_fname, preload=False) + data, _ = raw[:, :] + copied = raw.copy() + copied_data, _ = copied[:, :] + assert_array_equal(data, copied_data) + assert sorted(raw.__dict__.keys()) == sorted(copied.__dict__.keys()) + + +def test_to_data_frame(): + """Test raw Pandas exporter.""" + pd = pytest.importorskip("pandas") + raw = read_raw_fif(test_fif_fname).crop(0, 1).load_data() + df = raw.to_data_frame(index="time") + assert (df.columns == raw.ch_names).all() + df = raw.to_data_frame(index=None) + assert "time" in df.columns + assert_array_equal(df.values[:, 1], raw._data[0] * 1e13) + assert_array_equal(df.values[:, 3], raw._data[2] * 1e15) + # test long format + df_long = raw.to_data_frame(long_format=True) + assert len(df_long) == raw.get_data().size + expected = ("time", "channel", "ch_type", "value") + assert set(expected) == set(df_long.columns) + # test bad time format + with pytest.raises(ValueError, match="not a valid time format. Valid"): + raw.to_data_frame(time_format="foo") + # test time format error handling + raw.set_meas_date(None) + with pytest.warns(RuntimeWarning, match="Cannot convert to Datetime when"): + df = raw.to_data_frame(time_format="datetime") + assert isinstance(df["time"].iloc[0], pd.Timedelta) + + +@pytest.mark.parametrize("time_format", (None, "ms", "timedelta", "datetime")) +def test_to_data_frame_time_format(time_format): + """Test time conversion in epochs Pandas exporter.""" + pd = pytest.importorskip("pandas") + raw = read_raw_fif(test_fif_fname, preload=True) + # test time_format + df = raw.to_data_frame(time_format=time_format) + dtypes = { + None: np.float64, + "ms": np.int64, + "timedelta": pd.Timedelta, + "datetime": pd.Timestamp, + } + assert isinstance(df["time"].iloc[0], dtypes[time_format]) + # test values + _, times = raw[0, :10] + offset = 0.0 + if time_format == "datetime": + times += raw.first_time + offset = raw.info["meas_date"] + elif time_format == "timedelta": + offset = pd.Timedelta(0.0) + funcs = { + None: lambda x: x, + "ms": lambda x: np.rint(x * 1e3).astype(int), # s → ms + "timedelta": partial(pd.to_timedelta, unit="s"), + "datetime": partial(pd.to_timedelta, unit="s"), + } + assert_array_equal(funcs[time_format](times) + offset, df["time"][:10]) + + +def test_add_channels(): + """Test raw splitting / re-appending channel types.""" + rng = np.random.RandomState(0) + raw = read_raw_fif(test_fif_fname).crop(0, 1).load_data() + assert raw._orig_units == {} + raw_nopre = read_raw_fif(test_fif_fname, preload=False) + raw_eeg_meg = raw.copy().pick(picks=["meg", "eeg"]) + raw_eeg = raw.copy().pick(picks="eeg") + raw_meg = raw.copy().pick(picks="meg") + raw_stim = raw.copy().pick(picks="stim") + raw_new = raw_meg.copy().add_channels([raw_eeg, raw_stim]) + assert all( + ch in raw_new.ch_names + for ch in list(raw_stim.ch_names) + list(raw_meg.ch_names) + ) + raw_new = raw_meg.copy().add_channels([raw_eeg]) + + assert (ch in raw_new.ch_names for ch in raw.ch_names) + assert_array_equal(raw_new[:, :][0], raw_eeg_meg[:, :][0]) + assert_array_equal(raw_new[:, :][1], raw[:, :][1]) + assert all(ch not in raw_new.ch_names for ch in raw_stim.ch_names) + + # Testing force updates + raw_arr_info = create_info(["1", "2"], raw_meg.info["sfreq"], "eeg") + assert raw_arr_info["dev_head_t"] is None + orig_head_t = Transform("meg", "head") + raw_arr = rng.randn(2, raw_eeg.n_times) + raw_arr = RawArray(raw_arr, raw_arr_info) + # This should error because of conflicts in Info + raw_arr.info["dev_head_t"] = orig_head_t + with pytest.raises(ValueError, match="mutually inconsistent dev_head_t"): + raw_meg.copy().add_channels([raw_arr]) + raw_meg.copy().add_channels([raw_arr], force_update_info=True) + # Make sure that values didn't get overwritten + assert_object_equal(raw_arr.info["dev_head_t"], orig_head_t) + # Make sure all variants work + for simult in (False, True): # simultaneous adding or not + raw_new = raw_meg.copy() + if simult: + raw_new.add_channels([raw_eeg, raw_stim]) + else: + raw_new.add_channels([raw_eeg]) + raw_new.add_channels([raw_stim]) + for other in (raw_meg, raw_stim, raw_eeg): + assert_allclose( + raw_new.copy().pick(other.ch_names).get_data(), + other.get_data(), + ) + + # Now test errors + raw_badsf = raw_eeg.copy() + with raw_badsf.info._unlock(): + raw_badsf.info["sfreq"] = 3.1415927 + raw_eeg.crop(0.5) + + pytest.raises(RuntimeError, raw_meg.add_channels, [raw_nopre]) + pytest.raises(RuntimeError, raw_meg.add_channels, [raw_badsf]) + pytest.raises(ValueError, raw_meg.add_channels, [raw_eeg]) + pytest.raises(ValueError, raw_meg.add_channels, [raw_meg]) + pytest.raises(TypeError, raw_meg.add_channels, raw_badsf) + + +@testing.requires_testing_data +def test_save(tmp_path): + """Test saving raw.""" + temp_fname = tmp_path / "test_raw.fif" + shutil.copyfile(fif_fname, temp_fname) + raw = read_raw_fif(temp_fname, preload=False) + # can't write over file being read + with pytest.raises(ValueError, match="to the same file"): + raw.save(temp_fname) + raw.load_data() + # can't overwrite file without overwrite=True + with pytest.raises(OSError, match="file exists"): + raw.save(fif_fname) + + # test abspath support and annotations + orig_time = _dt_to_stamp(raw.info["meas_date"])[0] + raw._first_time + annot = Annotations([10], [5], ["test"], orig_time=orig_time) + raw.set_annotations(annot) + annot = raw.annotations + new_fname = tmp_path / "break_raw.fif" + raw.save(new_fname, overwrite=True) + new_raw = read_raw_fif(new_fname, preload=False) + pytest.raises(ValueError, new_raw.save, new_fname) + assert_array_almost_equal(annot.onset, new_raw.annotations.onset) + assert_array_equal(annot.duration, new_raw.annotations.duration) + assert_array_equal(annot.description, new_raw.annotations.description) + assert annot.orig_time == new_raw.annotations.orig_time + + # test set_meas_date(None) + raw.set_meas_date(None) + raw.save(new_fname, overwrite=True) + new_raw = read_raw_fif(new_fname, preload=False) + assert new_raw.info["meas_date"] is None + + +@testing.requires_testing_data +def test_annotation_crop(tmp_path): + """Test annotation sync after cropping and concatenating.""" + annot = Annotations([5.0, 11.0, 15.0], [2.0, 1.0, 3.0], ["test", "test", "test"]) + raw = read_raw_fif(fif_fname, preload=False) + raw.set_annotations(annot) + r1 = raw.copy().crop(2.5, 7.5) + r2 = raw.copy().crop(12.5, 17.5) + r3 = raw.copy().crop(10.0, 12.0) + raw = concatenate_raws([r1, r2, r3]) # segments reordered + assert_and_remove_boundary_annot(raw, 2) + onsets = raw.annotations.onset + durations = raw.annotations.duration + # 2*5s clips combined with annotations at 2.5s + 2s clip, annotation at 1s + assert_array_almost_equal(onsets[:3], [47.95, 52.95, 56.46], decimal=2) + assert_array_almost_equal([2.0, 2.5, 1.0], durations[:3], decimal=2) + + # test annotation clipping + orig_time = _dt_to_stamp(raw.info["meas_date"]) + orig_time = orig_time[0] + orig_time[1] * 1e-6 + raw._first_time - 1.0 + annot = Annotations([0.0, raw.times[-1]], [2.0, 2.0], "test", orig_time) + with pytest.warns(RuntimeWarning, match="Limited .* expanding outside"): + raw.set_annotations(annot) + assert_allclose( + raw.annotations.duration, [1.0, 1.0 + 1.0 / raw.info["sfreq"]], atol=1e-3 + ) + + # make sure we can overwrite the file we loaded when preload=True + new_fname = tmp_path / "break_raw.fif" + raw.save(new_fname) + new_raw = read_raw_fif(new_fname, preload=True) + new_raw.save(new_fname, overwrite=True) + + +@testing.requires_testing_data +def test_with_statement(): + """Test with statement.""" + for preload in [True, False]: + with read_raw_fif(fif_fname, preload=preload) as raw_: + print(raw_) + + +def test_compensation_raw(tmp_path): + """Test Raw compensation.""" + raw_3 = read_raw_fif(ctf_comp_fname) + assert raw_3.compensation_grade == 3 + data_3, times = raw_3[:, :] + + # data come with grade 3 + for ii in range(2): + raw_3_new = raw_3.copy() + if ii == 0: + raw_3_new.load_data() + raw_3_new.apply_gradient_compensation(3) + assert raw_3_new.compensation_grade == 3 + data_new, times_new = raw_3_new[:, :] + assert_array_equal(times, times_new) + assert_array_equal(data_3, data_new) + + # change to grade 0 + raw_0 = raw_3.copy().apply_gradient_compensation(0) + assert raw_0.compensation_grade == 0 + data_0, times_new = raw_0[:, :] + assert_array_equal(times, times_new) + assert np.mean(np.abs(data_0 - data_3)) > 1e-12 + # change to grade 1 + raw_1 = raw_0.copy().apply_gradient_compensation(1) + assert raw_1.compensation_grade == 1 + data_1, times_new = raw_1[:, :] + assert_array_equal(times, times_new) + assert np.mean(np.abs(data_1 - data_3)) > 1e-12 + pytest.raises(ValueError, raw_1.apply_gradient_compensation, 33) + raw_bad = raw_0.copy() + raw_bad.add_proj(compute_proj_raw(raw_0, duration=0.5, verbose="error")) + raw_bad.apply_proj() + pytest.raises(RuntimeError, raw_bad.apply_gradient_compensation, 1) + # with preload + tols = dict(rtol=1e-12, atol=1e-25) + raw_1_new = raw_3.copy().load_data().apply_gradient_compensation(1) + assert raw_1_new.compensation_grade == 1 + data_1_new, times_new = raw_1_new[:, :] + assert_array_equal(times, times_new) + assert np.mean(np.abs(data_1_new - data_3)) > 1e-12 + assert_allclose(data_1, data_1_new, **tols) + # change back + raw_3_new = raw_1.copy().apply_gradient_compensation(3) + data_3_new, times_new = raw_3_new[:, :] + assert_allclose(data_3, data_3_new, **tols) + raw_3_new = raw_1.copy().load_data().apply_gradient_compensation(3) + data_3_new, times_new = raw_3_new[:, :] + assert_allclose(data_3, data_3_new, **tols) + + for load in (False, True): + for raw in (raw_0, raw_1): + raw_3_new = raw.copy() + if load: + raw_3_new.load_data() + raw_3_new.apply_gradient_compensation(3) + assert raw_3_new.compensation_grade == 3 + data_3_new, times_new = raw_3_new[:, :] + assert_array_equal(times, times_new) + assert np.mean(np.abs(data_3_new - data_1)) > 1e-12 + assert_allclose(data_3, data_3_new, **tols) + + # Try IO with compensation + temp_file = tmp_path / "raw.fif" + raw_3.save(temp_file, overwrite=True) + for preload in (True, False): + raw_read = read_raw_fif(temp_file, preload=preload) + assert raw_read.compensation_grade == 3 + data_read, times_new = raw_read[:, :] + assert_array_equal(times, times_new) + assert_allclose(data_3, data_read, **tols) + raw_read.apply_gradient_compensation(1) + data_read, times_new = raw_read[:, :] + assert_array_equal(times, times_new) + assert_allclose(data_1, data_read, **tols) + + # Now save the file that has modified compensation + # and make sure the compensation is the same as it was, + # but that we can undo it + + # These channels have norm 1e-11/1e-12, so atol=1e-18 isn't awesome, + # but it's due to the single precision of the info['comps'] leading + # to inexact inversions with saving/loading (casting back to single) + # in between (e.g., 1->3->1 will degrade like this) + looser_tols = dict(rtol=1e-6, atol=1e-18) + raw_1.save(temp_file, overwrite=True) + for preload in (True, False): + raw_read = read_raw_fif(temp_file, preload=preload, verbose=True) + assert raw_read.compensation_grade == 1 + data_read, times_new = raw_read[:, :] + assert_array_equal(times, times_new) + assert_allclose(data_1, data_read, **looser_tols) + raw_read.apply_gradient_compensation(3, verbose=True) + data_read, times_new = raw_read[:, :] + assert_array_equal(times, times_new) + assert_allclose(data_3, data_read, **looser_tols) + + +@requires_mne +def test_compensation_raw_mne(tmp_path): + """Test Raw compensation by comparing with MNE-C.""" + + def compensate_mne(fname, grad): + tmp_fname = tmp_path / "mne_ctf_test_raw.fif" + cmd = [ + "mne_process_raw", + "--raw", + fname, + "--save", + tmp_fname, + "--grad", + str(grad), + "--projoff", + "--filteroff", + ] + run_subprocess(cmd) + return read_raw_fif(tmp_fname, preload=True) + + for grad in [0, 2, 3]: + raw_py = read_raw_fif(ctf_comp_fname, preload=True) + raw_py.apply_gradient_compensation(grad) + raw_c = compensate_mne(ctf_comp_fname, grad) + assert_allclose(raw_py._data, raw_c._data, rtol=1e-6, atol=1e-17) + assert raw_py.info["nchan"] == raw_c.info["nchan"] + for ch_py, ch_c in zip(raw_py.info["chs"], raw_c.info["chs"]): + for key in ( + "ch_name", + "coil_type", + "scanno", + "logno", + "unit", + "coord_frame", + "kind", + ): + assert ch_py[key] == ch_c[key] + for key in ("loc", "unit_mul", "range", "cal"): + assert_allclose(ch_py[key], ch_c[key]) + + +@testing.requires_testing_data +def test_drop_channels_mixin(): + """Test channels-dropping functionality.""" + raw = read_raw_fif(fif_fname, preload=True) + drop_ch = raw.ch_names[:3] + ch_names = raw.ch_names[3:] + + ch_names_orig = raw.ch_names + dummy = raw.copy().drop_channels(drop_ch) + assert ch_names == dummy.ch_names + assert ch_names_orig == raw.ch_names + assert len(ch_names_orig) == raw._data.shape[0] + + raw.drop_channels(drop_ch) + assert ch_names == raw.ch_names + assert len(ch_names) == len(raw._cals) + assert len(ch_names) == raw._data.shape[0] + + # Test that dropping all channels a projector applies to will lead to the + # removal of said projector. + raw = read_raw_fif(fif_fname).crop(0, 1) + n_projs = len(raw.info["projs"]) + eeg_names = raw.info["projs"][-1]["data"]["col_names"] + with pytest.raises(RuntimeError, match="loaded"): + raw.copy().apply_proj().drop_channels(eeg_names) + raw.load_data().drop_channels(eeg_names) # EEG proj + assert len(raw.info["projs"]) == n_projs - 1 + + # Dropping EEG channels with custom ref removes info['custom_ref_applied'] + raw = read_raw_fif(fif_fname).crop(0, 1).load_data() + raw.set_eeg_reference() + assert raw.info["custom_ref_applied"] + raw.drop_channels(eeg_names) + assert not raw.info["custom_ref_applied"] + + +@testing.requires_testing_data +@pytest.mark.parametrize("preload", (True, False)) +def test_pick_channels_mixin(preload): + """Test channel-picking functionality.""" + raw = read_raw_fif(fif_fname, preload=preload) + raw_orig = raw.copy() + ch_names = raw.ch_names[:3] + + ch_names_orig = raw.ch_names + dummy = raw.copy().pick(ch_names) + assert ch_names == dummy.ch_names + assert ch_names_orig == raw.ch_names + assert len(ch_names_orig) == raw.get_data().shape[0] + + raw.pick(ch_names) # copy is False + assert ch_names == raw.ch_names + assert len(ch_names) == len(raw._cals) + assert len(ch_names) == raw.get_data().shape[0] + with pytest.raises(ValueError, match='must be list, tuple, ndarray, or "bads"'): + raw.pick_channels(ch_names[0]) # legacy method OK here; testing its warning + + assert_allclose(raw[:][0], raw_orig[:3][0]) + + +@testing.requires_testing_data +def test_equalize_channels(): + """Test equalization of channels.""" + raw1 = read_raw_fif(fif_fname, preload=True) + + raw2 = raw1.copy() + ch_names = raw1.ch_names[2:] + raw1.drop_channels(raw1.ch_names[:1]) + raw2.drop_channels(raw2.ch_names[1:2]) + my_comparison = [raw1, raw2] + my_comparison = equalize_channels(my_comparison) + for e in my_comparison: + assert ch_names == e.ch_names + + +def test_memmap(tmp_path): + """Test some interesting memmapping cases.""" + # concatenate_raw + memmaps = [str(tmp_path / str(ii)) for ii in range(4)] + raw_0 = read_raw_fif(test_fif_fname, preload=memmaps[0]) + assert raw_0._data.filename == memmaps[0] + raw_1 = read_raw_fif(test_fif_fname, preload=memmaps[1]) + assert raw_1._data.filename == memmaps[1] + raw_0.append(raw_1, preload=memmaps[2]) + assert raw_0._data.filename == memmaps[2] + # add_channels + orig_data = raw_0[:][0] + new_ch_info = pick_info(raw_0.info, [0]) + new_ch_info["chs"][0]["ch_name"] = "foo" + new_ch_info._update_redundant() + new_data = np.linspace(0, 1, len(raw_0.times))[np.newaxis] + ch = RawArray(new_data, new_ch_info) + raw_0.add_channels([ch]) + if platform.system() == "Darwin": + assert not hasattr(raw_0._data, "filename") + else: + assert raw_0._data.filename == memmaps[2] + assert_allclose(orig_data, raw_0[:-1][0], atol=1e-7) + assert_allclose(new_data, raw_0[-1][0], atol=1e-7) + + # now let's see if .copy() actually works; it does, but eventually + # we should make it optionally memmap to a new filename rather than + # create an in-memory version (filename=None) + raw_0 = read_raw_fif(test_fif_fname, preload=memmaps[3]) + assert raw_0._data.filename == memmaps[3] + assert raw_0._data[:1, 3:5].all() + raw_1 = raw_0.copy() + assert isinstance(raw_1._data, np.memmap) + assert raw_1._data.filename is None + raw_0._data[:] = 0.0 + assert not raw_0._data.any() + assert raw_1._data[:1, 3:5].all() + # other things like drop_channels and crop work but do not use memmapping, + # eventually we might want to add support for some of these as users + # require them. + + +# These are slow on Azure Windows so let's do a subset +@pytest.mark.parametrize( + "kind", + ["path", pytest.param("file", id="kindFile"), "bytes"], +) +@pytest.mark.parametrize( + "preload", + [pytest.param(True, id="preloadTrue"), str], +) +@pytest.mark.parametrize( + "split", + [False, pytest.param(True, marks=pytest.mark.slowtest, id="splitTrue")], +) +def test_file_like(kind, preload, split, tmp_path): + """Test handling with file-like objects.""" + fname = tmp_path / "test_file_like_raw.fif" + fnames = (fname,) + this_raw = read_raw_fif(test_fif_fname).crop(0, 4).pick("mag") + if split: + this_raw.save(fname, split_size="5MB") + fnames += (Path(str(fname)[:-4] + "-1.fif"),) + bad_fname = Path(str(fname)[:-4] + "-2.fif") + assert not bad_fname.is_file() + else: + this_raw.save(fname) + for f in fnames: + assert f.is_file() + if preload is str: + if platform.system() == "Windows": + pytest.skip("Cannot test preload=str on Windows") + preload = str(tmp_path / "memmap") + with open(fname, "rb") as file_fid: + if kind == "bytes": + fid = BytesIO(file_fid.read()) + elif kind == "path": + fid = fname + else: + assert kind == "file" + fid = file_fid + if kind != "path": + assert not fid.closed + with pytest.raises(ValueError, match="preload must be used with file"): + read_raw_fif(fid) + assert not file_fid.closed + if kind != "path": + assert not fid.closed + assert not file_fid.closed + # Use test_preloading=False but explicitly pass the preload type + # so that we don't bother testing preload=False + kwargs = dict( + fname=fid, + preload=preload, + on_split_missing="warn", + test_preloading=False, + test_kwargs=False, + ) + want_filenames = list(fnames) + if kind == "bytes": + # the split file will not be correctly resolved for BytesIO + want_filenames = [None] + if split and kind == "bytes": + ctx = pytest.warns(RuntimeWarning, match="Split raw file detected") + else: + ctx = nullcontext() + with ctx: + raw = _test_raw_reader(read_raw_fif, **kwargs) + if kind != "path": + assert not fid.closed + assert not file_fid.closed + want_filenames = tuple(want_filenames) + assert raw.filenames == want_filenames + if kind == "bytes": + assert fname.name not in raw._repr_html_() + else: + assert fname.name in raw._repr_html_() + assert file_fid.closed + + +def test_str_like(): + """Test handling with str-like objects.""" + fname = pathlib.Path(test_fif_fname) + raw_path = read_raw_fif(fname, preload=True) + raw_str = read_raw_fif(test_fif_fname, preload=True) + assert_allclose(raw_path._data, raw_str._data) + + +@pytest.mark.parametrize( + "fname", + [ + test_fif_fname, + testing._pytest_param(fif_fname), + testing._pytest_param(ms_fname), + ], +) +def test_bad_acq(fname): + """Test handling of acquisition errors.""" + # see gh-7844 + raw = read_raw_fif(fname, allow_maxshield="yes").load_data() + with open(fname, "rb") as fid: + for ent in raw._raw_extras[0]["ent"]: + tag = _read_tag_header(fid, ent.pos) + # hack these, others (kind, type) should be correct + tag.pos, tag.next = ent.pos, ent.next + assert tag == ent + + +@testing.requires_testing_data +@pytest.mark.skipif( + platform.system() not in ("Linux", "Darwin"), reason="Needs proper symlinking" +) +def test_split_symlink(tmp_path): + """Test split files with symlinks.""" + # regression test for gh-9221 + (tmp_path / "first").mkdir() + first = tmp_path / "first" / "test_raw.fif" + raw = read_raw_fif(fif_fname).pick("meg").load_data() + raw.save(first, buffer_size_sec=1, split_size="10MB", verbose=True) + second = Path(str(first)[:-4] + "-1.fif") + assert second.is_file() + assert not Path(str(first)[:-4] + "-2.fif").is_file() + (tmp_path / "a").mkdir() + (tmp_path / "b").mkdir() + new_first = tmp_path / "a" / "test_raw.fif" + new_second = tmp_path / "b" / "test_raw-1.fif" + shutil.move(first, new_first) + shutil.move(second, new_second) + os.symlink(new_first, first) + os.symlink(new_second, second) + raw_new = read_raw_fif(first) + assert_allclose(raw_new.get_data(), raw.get_data()) + + +@testing.requires_testing_data +@pytest.mark.parametrize("offset", (0, 1)) +def test_corrupted(tmp_path, offset): + """Test that a corrupted file can still be read.""" + # Must be a file written by Neuromag, not us, since we don't write the dir + # at the end, so use the skip one (straight from acq). + raw = read_raw_fif(skip_fname) + with open(skip_fname, "rb") as fid: + file_id_tag = read_tag(fid, 0) + dir_pos_tag = read_tag(fid, file_id_tag.next_pos) + dirpos = int(dir_pos_tag.data.item()) + assert dirpos == 12641532 + fid.seek(0) + data = fid.read(dirpos + offset) + bad_fname = tmp_path / "test_raw.fif" + with open(bad_fname, "wb") as fid: + fid.write(data) + with ( + _record_warnings(), + pytest.warns(RuntimeWarning, match=".*tag directory.*corrupt.*"), + ): + raw_bad = read_raw_fif(bad_fname) + assert_allclose(raw.get_data(), raw_bad.get_data()) + + +@testing.requires_testing_data +def test_expand_user(tmp_path, monkeypatch): + """Test that we're expanding `~` before reading and writing.""" + monkeypatch.setenv("HOME", str(tmp_path)) + monkeypatch.setenv("USERPROFILE", str(tmp_path)) # Windows + + path_in = Path(fif_fname) + path_out = tmp_path / path_in.name + path_home = Path("~") / path_in.name + + shutil.copyfile(src=path_in, dst=path_out) + + raw = read_raw_fif(fname=path_home, preload=True) + raw.save(fname=path_home, overwrite=True) + + +@pytest.mark.parametrize("cast", [pathlib.Path, str]) +def test_init_kwargs(cast): + """Test for pull/12843#issuecomment-2380491528.""" + raw = read_raw_fif(cast(test_fif_fname)) + raw2 = read_raw_fif(**raw._init_kwargs) + for r in (raw, raw2): + assert isinstance(r._init_kwargs["fname"], pathlib.Path) + + +@pytest.mark.slowtest +@testing.requires_testing_data +@pytest.mark.parametrize("fname", [ms_fname, tri_fname]) +def test_fif_files(fname): + """Test reading of various FIF files.""" + _test_raw_reader( + read_raw_fif, + fname=fname, + allow_maxshield="yes", + verbose="error", + test_kwargs=False, + test_preloading=False, + ) diff --git a/mne-python/source/mne/io/fil/__init__.py b/mne-python/source/mne/io/fil/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ad780452c776d220dd92a5f733f3e88b1c693c2b --- /dev/null +++ b/mne-python/source/mne/io/fil/__init__.py @@ -0,0 +1,5 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .fil import read_raw_fil diff --git a/mne-python/source/mne/io/fil/fil.py b/mne-python/source/mne/io/fil/fil.py new file mode 100644 index 0000000000000000000000000000000000000000..a7dd157049afeafe88d05dba79e093c4a2c4918a --- /dev/null +++ b/mne-python/source/mne/io/fil/fil.py @@ -0,0 +1,336 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import json +import pathlib + +import numpy as np + +from ..._fiff._digitization import _make_dig_points +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info +from ..._fiff.utils import _read_segments_file +from ..._fiff.write import get_new_file_id +from ...transforms import Transform, apply_trans, get_ras_to_neuromag_trans +from ...utils import _check_fname, fill_doc, verbose, warn +from ..base import BaseRaw +from .sensors import ( + _get_plane_vectors, + _get_pos_units, + _refine_sensor_orientation, + _size2units, +) + + +@verbose +def read_raw_fil( + binfile, precision="single", preload=False, *, verbose=None +) -> "RawFIL": + """Raw object from FIL-OPMEG formatted data. + + Parameters + ---------- + binfile : path-like + Path to the MEG data binary (ending in ``'_meg.bin'``). + precision : str, optional + How is the data represented? ``'single'`` if 32-bit or ``'double'`` if + 64-bit (default is single). + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawFIL + The raw data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawFIL. + """ + return RawFIL(binfile, precision=precision, preload=preload) + + +@fill_doc +class RawFIL(BaseRaw): + """Raw object from FIL-OPMEG formatted data. + + Parameters + ---------- + binfile : path-like + Path to the MEG data binary (ending in ``'_meg.bin'``). + precision : str, optional + How is the data represented? ``'single'`` if 32-bit or + ``'double'`` if 64-bit (default is single). + %(preload)s + + Returns + ------- + raw : instance of RawFIL + The raw data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawFIL. + """ + + def __init__(self, binfile, precision="single", preload=False): + if precision == "single": + dt = np.dtype(">f") + bps = 4 + else: + dt = np.dtype(">d") + bps = 8 + + sample_info = dict() + sample_info["dt"] = dt + sample_info["bps"] = bps + + files = _get_file_names(binfile) + + chans = _from_tsv(files["chans"]) + nchans = len(chans["name"]) + nsamples = _determine_nsamples(files["bin"], nchans, precision) - 1 + sample_info["nsamples"] = nsamples + + raw_extras = list() + raw_extras.append(sample_info) + + chans["pos"] = [None] * nchans + chans["ori"] = [None] * nchans + if files["positions"].is_file(): + chanpos = _from_tsv(files["positions"]) + nlocs = len(chanpos["name"]) + for ii in range(0, nlocs): + idx = chans["name"].index(chanpos["name"][ii]) + tmp = np.array( + [chanpos["Px"][ii], chanpos["Py"][ii], chanpos["Pz"][ii]] + ) + chans["pos"][idx] = tmp.astype(np.float64) + tmp = np.array( + [chanpos["Ox"][ii], chanpos["Oy"][ii], chanpos["Oz"][ii]] + ) + chans["ori"][idx] = tmp.astype(np.float64) + else: + warn("No sensor position information found.") + + with open(files["meg"]) as fid: + meg = json.load(fid) + info = _compose_meas_info(meg, chans) + + super().__init__( + info, + preload, + filenames=[files["bin"]], + raw_extras=raw_extras, + last_samps=[nsamples], + orig_format=precision, + ) + + if files["coordsystem"].is_file(): + with open(files["coordsystem"]) as fid: + csys = json.load(fid) + hc = csys["HeadCoilCoordinates"] + + for key in hc: + if key.lower() == "lpa": + lpa = np.asarray(hc[key]) + elif key.lower() == "rpa": + rpa = np.asarray(hc[key]) + elif key.lower().startswith("nas"): + nas = np.asarray(hc[key]) + else: + warn(f"{key} is not a valid fiducial name!") + + size = np.linalg.norm(nas - rpa) + unit, sf = _size2units(size) + # TODO: These are not guaranteed to exist and could lead to a + # confusing error message, should fix later + lpa /= sf + rpa /= sf + nas /= sf + + t = get_ras_to_neuromag_trans(nas, lpa, rpa) + + # transform fiducial points + nas = apply_trans(t, nas) + lpa = apply_trans(t, lpa) + rpa = apply_trans(t, rpa) + + with self.info._unlock(): + self.info["dig"] = _make_dig_points( + nasion=nas, lpa=lpa, rpa=rpa, coord_frame="meg" + ) + else: + warn( + "No fiducials found in files, defaulting sensor array to " + "FIFFV_COORD_DEVICE, this may cause problems later!" + ) + t = np.eye(4) + + with self.info._unlock(): + self.info["dev_head_t"] = Transform( + FIFF.FIFFV_COORD_DEVICE, FIFF.FIFFV_COORD_HEAD, t + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + si = self._raw_extras[fi] + _read_segments_file( + self, data, idx, fi, start, stop, cals, mult, dtype=si["dt"] + ) + + +def _convert_channel_info(chans): + """Convert the imported _channels.tsv into the chs element of raw.info.""" + nmeg = nstim = nmisc = nref = 0 + + if not all(p is None for p in chans["pos"]): + _, sf = _get_pos_units(chans["pos"]) + + chs = list() + for ii in range(len(chans["name"])): + ch = dict( + scanno=ii + 1, + range=1.0, + cal=1.0, + loc=np.full(12, np.nan), + unit_mul=FIFF.FIFF_UNITM_NONE, + ch_name=chans["name"][ii], + coil_type=FIFF.FIFFV_COIL_NONE, + ) + chs.append(ch) + + # create the channel information + if chans["pos"][ii] is not None: + r0 = chans["pos"][ii].copy() / sf # mm to m + ez = chans["ori"][ii].copy() + ez = ez / np.linalg.norm(ez) + ex, ey = _get_plane_vectors(ez) + ch["loc"] = np.concatenate([r0, ex, ey, ez]) + + if chans["type"][ii] == "MEGMAG": + nmeg += 1 + ch.update( + logno=nmeg, + coord_frame=FIFF.FIFFV_COORD_DEVICE, + kind=FIFF.FIFFV_MEG_CH, + unit=FIFF.FIFF_UNIT_T, + coil_type=FIFF.FIFFV_COIL_QUSPIN_ZFOPM_MAG2, + ) + elif chans["type"][ii] == "MEGREFMAG": + nref += 1 + ch.update( + logno=nref, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + kind=FIFF.FIFFV_REF_MEG_CH, + unit=FIFF.FIFF_UNIT_T, + coil_type=FIFF.FIFFV_COIL_QUSPIN_ZFOPM_MAG2, + ) + elif chans["type"][ii] == "TRIG": + nstim += 1 + ch.update( + logno=nstim, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + kind=FIFF.FIFFV_STIM_CH, + unit=FIFF.FIFF_UNIT_V, + ) + else: + nmisc += 1 + ch.update( + logno=nmisc, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + kind=FIFF.FIFFV_MISC_CH, + unit=FIFF.FIFF_UNIT_NONE, + ) + + # set the calibration based on the units - MNE expects T units for meg + # and V for eeg + if chans["units"][ii] == "fT": + ch.update(cal=1e-15) + elif chans["units"][ii] == "pT": + ch.update(cal=1e-12) + elif chans["units"][ii] == "nT": + ch.update(cal=1e-9) + elif chans["units"][ii] == "mV": + ch.update(cal=1e3) + elif chans["units"][ii] == "uV": + ch.update(cal=1e6) + + return chs + + +def _compose_meas_info(meg, chans): + """Create info structure.""" + info = _empty_info(meg["SamplingFrequency"]) + # Collect all the necessary data from the structures read + info["meas_id"] = get_new_file_id() + tmp = _convert_channel_info(chans) + info["chs"] = _refine_sensor_orientation(tmp) + info["line_freq"] = meg["PowerLineFrequency"] + info._update_redundant() + info["bads"] = _read_bad_channels(chans) + info._unlocked = False + return info + + +def _determine_nsamples(bin_fname, nchans, precision): + """Identify how many temporal samples in a dataset.""" + bsize = bin_fname.stat().st_size + if precision == "single": + bps = 4 + else: + bps = 8 + nsamples = int(bsize / (nchans * bps)) + return nsamples + + +def _read_bad_channels(chans): + """Check _channels.tsv file to look for premarked bad channels.""" + bads = list() + for ii in range(0, len(chans["status"])): + if chans["status"][ii] == "bad": + bads.append(chans["name"][ii]) + return bads + + +def _from_tsv(fname, dtypes=None): + """Read a tsv file into a dict (which we know is ordered).""" + data = np.loadtxt( + fname, dtype=str, delimiter="\t", ndmin=2, comments=None, encoding="utf-8-sig" + ) + column_names = data[0, :] + info = data[1:, :] + data_dict = dict() + if dtypes is None: + dtypes = [str] * info.shape[1] + if not isinstance(dtypes, list | tuple): + dtypes = [dtypes] * info.shape[1] + if not len(dtypes) == info.shape[1]: + raise ValueError( + f"dtypes length mismatch. Provided: {len(dtypes)}, " + f"Expected: {info.shape[1]}" + ) + for i, name in enumerate(column_names): + data_dict[name] = info[:, i].astype(dtypes[i]).tolist() + return data_dict + + +def _get_file_names(binfile): + """Guess the filenames based on predicted suffixes.""" + binfile = pathlib.Path( + _check_fname(binfile, overwrite="read", must_exist=True, name="fname") + ) + if not (binfile.suffix == ".bin" and binfile.stem.endswith("_meg")): + raise ValueError(f"File must be a filename ending in _meg.bin, got {binfile}") + files = dict() + dir_ = binfile.parent + root = binfile.stem[:-4] # no _meg + files["bin"] = dir_ / (root + "_meg.bin") + files["meg"] = dir_ / (root + "_meg.json") + files["chans"] = dir_ / (root + "_channels.tsv") + files["positions"] = dir_ / (root + "_positions.tsv") + files["coordsystem"] = dir_ / (root + "_coordsystem.json") + return files diff --git a/mne-python/source/mne/io/fil/sensors.py b/mne-python/source/mne/io/fil/sensors.py new file mode 100644 index 0000000000000000000000000000000000000000..6431a16bb4d58f6c9409ae59357fb4065d313cf8 --- /dev/null +++ b/mne-python/source/mne/io/fil/sensors.py @@ -0,0 +1,145 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from copy import deepcopy + +import numpy as np + +from ...utils import logger + + +def _refine_sensor_orientation(chanin): + """Improve orientation matrices based on multiaxis measures. + + The ex and ey elements from _convert_channel_info were oriented not + based on the physical orientation of the sensor. + It doesn't have to be this way, we can use (if available) the orientation + information from mulit-axis recordings to refine these elements. + """ + logger.info("Refining sensor orientations...") + chanout = deepcopy(chanin) + tmpname = list() + for ii in range(len(chanin)): + tmpname.append(chanin[ii]["ch_name"]) + + for ii in range(len(chanin)): + tmploc = deepcopy(chanin[ii]["loc"]) + tmploc = tmploc.reshape(3, 4, order="F") + if np.isnan(tmploc.sum()) is False: + target, flipFlag = _guess_other_chan_axis(tmpname, ii) + if np.isnan(target) is False: + targetloc = deepcopy(chanin[target]["loc"]) + if np.isnan(targetloc.sum()) is False: + targetloc = targetloc.reshape(3, 4, order="F") + tmploc[:, 2] = targetloc[:, 3] + tmploc[:, 1] = flipFlag * np.cross(tmploc[:, 2], tmploc[:, 3]) + chanout[ii]["loc"] = tmploc.reshape(12, order="F") + logger.info("[done]") + return chanout + + +def _guess_other_chan_axis(tmpname, seedID): + """Try to guess the name of another axis of a multiaxis sensor.""" + # see if its using the old RAD/TAN convention first, otherwise use XYZ + if tmpname[seedID][-3:] == "RAD": + prefix1 = "RAD" + prefix2 = "TAN" + flipflag = 1.0 + elif tmpname[seedID][-3:] == "TAN": + prefix1 = "TAN" + prefix2 = "RAD" + flipflag = -1.0 + elif tmpname[seedID][-1:] == "Z" or tmpname[seedID][-3:] == "[Z]": + prefix1 = "Z" + prefix2 = "Y" + flipflag = -1.0 + elif tmpname[seedID][-1:] == "Y" or tmpname[seedID][-3:] == "[Y]": + prefix1 = "Y" + prefix2 = "Z" + flipflag = 1.0 + elif tmpname[seedID][-1:] == "X" or tmpname[seedID][-3:] == "[X]": + prefix1 = "X" + prefix2 = "Y" + flipflag = 1.0 + else: + prefix1 = "?" + prefix2 = "?" + flipflag = 1.0 + + target_name = tmpname[seedID][: -len(prefix1)] + prefix2 + + target_id = np.where([t == target_name for t in tmpname])[0] + target_id = target_id[0] if len(target_id) else np.nan + + return target_id, flipflag + + +def _get_pos_units(pos): + """Get the units of a point cloud. + + Determines the units a point cloud of sensor positions, provides the + scale factor required to ensure the units can be converted to meters. + """ + # get rid of None elements + nppos = np.empty((0, 3)) + for ii in range(0, len(pos)): + if pos[ii] is not None and sum(np.isnan(pos[ii])) == 0: + nppos = np.vstack((nppos, pos[ii])) + + idrange = np.empty(shape=(0, 3)) + for ii in range(0, 3): + q90, q10 = np.percentile(nppos[:, ii], [90, 10]) + idrange = np.append(idrange, q90 - q10) + + size = np.linalg.norm(idrange) + + unit, sf = _size2units(size) + + return unit, sf + + +def _size2units(size): + """Convert the size returned from _get_pos_units into a physical unit.""" + if size >= 0.050 and size < 0.500: + unit = "m" + sf = 1 + elif size >= 0.50 and size < 5: + unit = "dm" + sf = 10 + elif size >= 5 and size < 50: + unit = "cm" + sf = 100 + elif size >= 50 and size < 500: + unit = "mm" + sf = 1000 + else: + unit = "unknown" + sf = 1 + + return unit, sf + + +def _get_plane_vectors(ez): + """Get two orthogonal vectors orthogonal to ez (ez will be modified). + + Note: the ex and ey positions will not be realistic, this can be fixed + using _refine_sensor_orientation. + """ + assert ez.shape == (3,) + ez_len = np.sqrt(np.sum(ez * ez)) + if ez_len == 0: + raise RuntimeError("Zero length normal. Cannot proceed.") + if np.abs(ez_len - np.abs(ez[2])) < 1e-5: # ez already in z-direction + ex = np.array([1.0, 0.0, 0.0]) + else: + ex = np.zeros(3) + if ez[1] < ez[2]: + ex[0 if ez[0] < ez[1] else 1] = 1.0 + else: + ex[0 if ez[0] < ez[2] else 2] = 1.0 + ez /= ez_len + ex -= np.dot(ez, ex) * ez + ex /= np.sqrt(np.sum(ex * ex)) + ey = np.cross(ez, ex) + return ex, ey diff --git a/mne-python/source/mne/io/fil/tests/test_fil.py b/mne-python/source/mne/io/fil/tests/test_fil.py new file mode 100644 index 0000000000000000000000000000000000000000..df15dd133530acf45dd1865456c52df1c43b874a --- /dev/null +++ b/mne-python/source/mne/io/fil/tests/test_fil.py @@ -0,0 +1,192 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import shutil +from os import remove + +import pytest +import scipy.io +from numpy import array, empty, isnan +from numpy.testing import assert_array_almost_equal, assert_array_equal + +from mne import pick_types +from mne.datasets import testing +from mne.io import read_raw_fil +from mne.io.fil.sensors import _get_pos_units + +fil_path = testing.data_path(download=False) / "FIL" + + +# TODO: Ignore this warning in all these tests until we deal with this properly +pytestmark = pytest.mark.filterwarnings( + "ignore:.*problems later!:RuntimeWarning", +) + + +def _set_bads_tsv(chanfile, badchan): + """Update channels.tsv by setting target channel to bad.""" + data = [] + with open(chanfile, encoding="utf-8") as f: + for line in f: + columns = line.strip().split("\t") + data.append(columns) + + with open(chanfile, "w", encoding="utf-8") as f: + for row in data: + if badchan in row: + row[-1] = "bad" + f.write("\t".join(row) + "\n") + + +def unpack_mat(matin): + """Extract relevant entries from unstructred readmat.""" + data = matin["data"] + grad = data[0][0]["grad"] + label = list() + coil_label = list() + for ii in range(len(data[0][0]["label"])): + label.append(str(data[0][0]["label"][ii][0][0])) + for ii in range(len(grad[0][0]["label"])): + coil_label.append(str(grad[0][0]["label"][ii][0][0])) + + matout = { + "label": label, + "trial": data["trial"][0][0][0][0], + "coil_label": coil_label, + "coil_pos": grad[0][0]["coilpos"], + "coil_ori": grad[0][0]["coilori"], + } + return matout + + +def _match_str(A_list, B_list): + """Locate where in a list matches another.""" + B_inds = list() + for ii in A_list: + if ii in B_list: + B_inds.append(B_list.index(ii)) + return B_inds + + +def _get_channels_with_positions(info): + """Parse channel orientation/position.""" + ch_list = list() + ch_inds = list() + for ii, ch in enumerate(info["chs"]): + if not (any(isnan(ch["loc"]))): + ch_inds.append(ii) + ch_list.append(ch["ch_name"]) + return ch_list, ch_inds + + +def _fil_megmag(raw_test, raw_mat): + """Test the magnetometer channels.""" + test_inds = pick_types(raw_test.info, meg="mag", ref_meg=False, exclude="bads") + test_list = list(raw_test.info["ch_names"][i] for i in test_inds) + mat_list = raw_mat["label"] + mat_inds = _match_str(test_list, mat_list) + + assert len(mat_inds) == len(test_inds), ( + "Number of magnetometer channels in RAW does not match .mat file!" + ) + + a = raw_test._data[test_inds, :] + b = raw_mat["trial"][mat_inds, :] * 1e-15 # fT to T + + assert_array_equal(a, b) + + +def _fil_stim(raw_test, raw_mat): + """Test the trigger channels.""" + test_inds = pick_types( + raw_test.info, meg=False, ref_meg=False, stim=True, exclude="bads" + ) + test_list = list(raw_test.info["ch_names"][i] for i in test_inds) + mat_list = raw_mat["label"] + mat_inds = _match_str(test_list, mat_list) + + assert len(mat_inds) == len(test_inds), ( + "Number of stim channels in RAW does not match .mat file!" + ) + + a = raw_test._data[test_inds, :] + b = raw_mat["trial"][mat_inds, :] # fT to T + + assert_array_equal(a, b) + + +def _fil_sensorpos(raw_test, raw_mat): + """Test the sensor positions/orientations.""" + test_list, test_inds = _get_channels_with_positions(raw_test.info) + grad_list = raw_mat["coil_label"] + grad_inds = _match_str(test_list, grad_list) + + assert len(grad_inds) == len(test_inds), ( + "Number of channels with position data in RAW does not match .mat file!" + ) + + mat_pos = raw_mat["coil_pos"][grad_inds, :] + mat_ori = raw_mat["coil_ori"][grad_inds, :] + _, sf1 = _get_pos_units(mat_pos) + + test_pos = empty((len(test_inds), 3)) + test_ori = empty((len(test_inds), 3)) + for i, ind in enumerate(test_inds): + test_pos[i, :] = raw_test.info["chs"][ind]["loc"][0:3] + test_ori[i, :] = raw_test.info["chs"][ind]["loc"][-3:] + _, sf2 = _get_pos_units(test_pos) + + assert_array_almost_equal(test_pos / sf2, mat_pos / sf1) + assert_array_almost_equal(test_ori, mat_ori) + + +@testing.requires_testing_data +def test_fil_complete(): + """Test FIL reader, match to known answers from .mat file.""" + binname = fil_path / "sub-noise_ses-001_task-noise220622_run-001_meg.bin" + matname = fil_path / "sub-noise_ses-001_task-noise220622_run-001_fieldtrip.mat" + + raw = read_raw_fil(binname) + raw.load_data(verbose=False) + tmp = scipy.io.loadmat(matname) + mat = unpack_mat(tmp) + + _fil_megmag(raw, mat) + _fil_stim(raw, mat) + _fil_sensorpos(raw, mat) + + +@testing.requires_testing_data +def test_fil_no_positions(tmp_path): + """Test FIL reader in cases where a position file is missing.""" + test_path = tmp_path / "FIL" + shutil.copytree(fil_path, test_path) + + posname = test_path / "sub-noise_ses-001_task-noise220622_run-001_positions.tsv" + binname = test_path / "sub-noise_ses-001_task-noise220622_run-001_meg.bin" + + remove(posname) + + with pytest.warns(RuntimeWarning, match="No sensor position.*"): + raw = read_raw_fil(binname) + chs = raw.info["chs"] + locs = array([ch["loc"][:] for ch in chs]) + assert isnan(locs).all() + + +@testing.requires_testing_data +def test_fil_bad_channel_spec(tmp_path): + """Test FIL reader when a bad channel is specified in channels.tsv.""" + test_path = tmp_path / "FIL" + shutil.copytree(fil_path, test_path) + + channame = test_path / "sub-noise_ses-001_task-noise220622_run-001_channels.tsv" + binname = test_path / "sub-noise_ses-001_task-noise220622_run-001_meg.bin" + bad_chan = "G2-OG-Y" + + _set_bads_tsv(channame, bad_chan) + + raw = read_raw_fil(binname) + bads = raw.info["bads"] + assert bad_chan in bads diff --git a/mne-python/source/mne/io/hitachi/__init__.py b/mne-python/source/mne/io/hitachi/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fc2cdec78eeaef6028ec6103d9398abe42a4cec3 --- /dev/null +++ b/mne-python/source/mne/io/hitachi/__init__.py @@ -0,0 +1,7 @@ +"""fNIRS module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .hitachi import read_raw_hitachi diff --git a/mne-python/source/mne/io/hitachi/hitachi.py b/mne-python/source/mne/io/hitachi/hitachi.py new file mode 100644 index 0000000000000000000000000000000000000000..69912a11ea15540fe587c69ed7a0632fc4c176e1 --- /dev/null +++ b/mne-python/source/mne/io/hitachi/hitachi.py @@ -0,0 +1,344 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime as dt +import re + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _merge_info, create_info +from ..._fiff.utils import _mult_cal_one +from ...utils import _check_fname, _check_option, fill_doc, logger, verbose, warn +from ..base import BaseRaw +from ..nirx.nirx import _read_csv_rows_cols + + +@fill_doc +def read_raw_hitachi(fname, preload=False, verbose=None) -> "RawHitachi": + """Reader for a Hitachi fNIRS recording. + + Parameters + ---------- + %(hitachi_fname)s + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawHitachi + A Raw object containing Hitachi data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawHitachi. + + Notes + ----- + %(hitachi_notes)s + """ + return RawHitachi(fname, preload, verbose=verbose) + + +def _check_bad(cond, msg): + if cond: + raise RuntimeError(f"Could not parse file: {msg}") + + +@fill_doc +class RawHitachi(BaseRaw): + """Raw object from a Hitachi fNIRS file. + + Parameters + ---------- + %(hitachi_fname)s + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + + Notes + ----- + %(hitachi_notes)s + """ + + @verbose + def __init__(self, fname, preload=False, *, verbose=None): + if not isinstance(fname, list | tuple): + fname = [fname] + fname = list(fname) # our own list that we can modify + for fi, this_fname in enumerate(fname): + fname[fi] = _check_fname(this_fname, "read", True, f"fname[{fi}]") + infos = list() + probes = list() + last_samps = list() + S_offset = D_offset = 0 + ignore_names = ["Time"] + for this_fname in fname: + info, extra, last_samp, offsets = _get_hitachi_info( + this_fname, S_offset, D_offset, ignore_names + ) + ignore_names = list(set(ignore_names + info["ch_names"])) + S_offset += offsets[0] + D_offset += offsets[1] + infos.append(info) + probes.append(extra) + last_samps.append(last_samp) + # combine infos + if len(fname) > 1: + info = _merge_info(infos) + else: + info = infos[0] + if len(set(last_samps)) != 1: + raise RuntimeError( + "All files must have the same number of samples, got: {last_samps}" + ) + last_samps = [last_samps[0]] + raw_extras = [dict(probes=probes)] + # One representative filename is good enough here + # (additional filenames indicate temporal concat, not ch concat) + super().__init__( + info, + preload, + filenames=[fname[0]], + last_samps=last_samps, + raw_extras=raw_extras, + verbose=verbose, + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a segment of data from a file.""" + this_data = list() + for this_probe in self._raw_extras[fi]["probes"]: + this_data.append( + _read_csv_rows_cols( + this_probe["fname"], + start, + stop, + this_probe["keep_mask"], + this_probe["bounds"], + sep=",", + replace=lambda x: ( + x.replace("\r", "\n") + .replace("\n\n", "\n") + .replace("\n", ",") + .replace(":", "") + ), + ).T + ) + this_data = np.concatenate(this_data, axis=0) + _mult_cal_one(data, this_data, idx, cals, mult) + return data + + +def _get_hitachi_info(fname, S_offset, D_offset, ignore_names): + logger.info(f"Loading {fname}") + raw_extra = dict(fname=fname) + info_extra = dict() + subject_info = dict() + ch_wavelengths = dict() + fnirs_wavelengths = [None, None] + meas_date = age = ch_names = sfreq = None + with open(fname, "rb") as fid: + lines = fid.read() + lines = lines.decode("latin-1").rstrip("\r\n") + oldlen = len(lines) + assert len(lines) == oldlen + bounds = [0] + end = "\n" if "\n" in lines else "\r" + bounds.extend(a.end() for a in re.finditer(end, lines)) + bounds.append(len(lines)) + lines = lines.split(end) + assert len(bounds) == len(lines) + 1 + line = lines[0].rstrip(",\r\n") + _check_bad(line != "Header", "no header found") + li = 0 + mode = None + for li, line in enumerate(lines[1:], 1): + # Newer format has some blank lines + if len(line) == 0: + continue + parts = line.rstrip(",\r\n").split(",") + if len(parts) == 0: # some header lines are blank + continue + kind, parts = parts[0], parts[1:] + if len(parts) == 0: + parts = [""] # some fields (e.g., Comment) meaningfully blank + if kind == "File Version": + logger.info(f"Reading Hitachi fNIRS file version {parts[0]}") + elif kind == "AnalyzeMode": + _check_bad(parts != ["Continuous"], f"not continuous data ({parts})") + elif kind == "Sampling Period[s]": + sfreq = 1 / float(parts[0]) + elif kind == "Exception": + raise NotImplementedError(kind) + elif kind == "Comment": + info_extra["description"] = parts[0] + elif kind == "ID": + subject_info["his_id"] = parts[0] + elif kind == "Name": + if len(parts): + name = parts[0].split(" ") + if len(name): + subject_info["first_name"] = name[0] + subject_info["last_name"] = " ".join(name[1:]) + elif kind == "Age": + age = int(parts[0].rstrip("y")) + elif kind == "Mode": + mode = parts[0] + elif kind in ("HPF[Hz]", "LPF[Hz]"): + try: + freq = float(parts[0]) + except ValueError: + pass + else: + info_extra[{"HPF[Hz]": "highpass", "LPF[Hz]": "lowpass"}[kind]] = freq + elif kind == "Date": + # 5/17/04 5:14 + try: + mdy, HM = parts[0].split(" ") + H, M = HM.split(":") + if len(H) == 1: + H = f"0{H}" + mdyHM = " ".join([mdy, ":".join([H, M])]) + for fmt in ("%m/%d/%y %H:%M", "%Y/%m/%d %H:%M"): + try: + meas_date = dt.datetime.strptime(mdyHM, fmt) + except Exception: + pass + else: + break + else: + raise RuntimeError # unknown format + except Exception: + warn( + "Extraction of measurement date failed. " + "Please report this as a github issue. " + "The date is being set to January 1st, 2000, " + f"instead of {repr(parts[0])}" + ) + elif kind == "Sex": + try: + subject_info["sex"] = dict( + female=FIFF.FIFFV_SUBJ_SEX_FEMALE, male=FIFF.FIFFV_SUBJ_SEX_MALE + )[parts[0].lower()] + except KeyError: + pass + elif kind == "Wave[nm]": + fnirs_wavelengths[:] = [int(part) for part in parts] + elif kind == "Wave Length": + ch_regex = re.compile(r"^(.*)\(([0-9\.]+)\)$") + for ent in parts: + _, v = ch_regex.match(ent).groups() + ch_wavelengths[ent] = float(v) + elif kind == "Data": + break + fnirs_wavelengths = np.array(fnirs_wavelengths, int) + assert len(fnirs_wavelengths) == 2 + ch_names = lines[li + 1].rstrip(",\r\n").split(",") + # cull to correct ones + raw_extra["keep_mask"] = ~np.isin(ch_names, list(ignore_names)) + for ci, ch_name in enumerate(ch_names): + if re.match("Probe[0-9]+", ch_name): + raw_extra["keep_mask"][ci] = False + # set types + ch_names = [ + ch_name for ci, ch_name in enumerate(ch_names) if raw_extra["keep_mask"][ci] + ] + ch_types = [ + "fnirs_cw_amplitude" if ch_name.startswith("CH") else "stim" + for ch_name in ch_names + ] + # get locations + nirs_names = [ + ch_name + for ch_name, ch_type in zip(ch_names, ch_types) + if ch_type == "fnirs_cw_amplitude" + ] + n_nirs = len(nirs_names) + assert n_nirs % 2 == 0 + names = { + "3x3": "ETG-100", + "3x5": "ETG-7000", + "4x4": "ETG-7000", + "3x11": "ETG-4000", + } + _check_option("Hitachi mode", mode, sorted(names)) + n_row, n_col = (int(x) for x in mode.split("x")) + logger.info(f"Constructing pairing matrix for {names[mode]} ({mode})") + pairs = _compute_pairs(n_row, n_col, n=1 + (mode == "3x3")) + assert n_nirs == len(pairs) * 2 + locs = np.zeros((len(ch_names), 12)) + locs[:, :9] = np.nan + idxs = np.where(np.array(ch_types, "U") == "fnirs_cw_amplitude")[0] + for ii, idx in enumerate(idxs): + ch_name = ch_names[idx] + # Use the actual/accurate wavelength in loc + acc_freq = ch_wavelengths[ch_name] + locs[idx][9] = acc_freq + # Rename channel based on standard naming scheme, using the + # nominal wavelength + sidx, didx = pairs[ii // 2] + nom_freq = fnirs_wavelengths[np.argmin(np.abs(acc_freq - fnirs_wavelengths))] + ch_names[idx] = f"S{S_offset + sidx + 1}_D{D_offset + didx + 1} {nom_freq}" + offsets = np.array(pairs, int).max(axis=0) + 1 + + # figure out bounds + bounds = raw_extra["bounds"] = bounds[li + 2 :] + last_samp = len(bounds) - 2 + + if age is not None and meas_date is not None: + subject_info["birthday"] = dt.date( + meas_date.year - age, + meas_date.month, + meas_date.day, + ) + if meas_date is None: + meas_date = dt.datetime(2000, 1, 1, 0, 0, 0) + meas_date = meas_date.replace(tzinfo=dt.timezone.utc) + if subject_info: + info_extra["subject_info"] = subject_info + + # Create mne structure + info = create_info(ch_names, sfreq, ch_types=ch_types) + with info._unlock(): + info.update(info_extra) + info["meas_date"] = meas_date + for li, loc in enumerate(locs): + info["chs"][li]["loc"][:] = loc + return info, raw_extra, last_samp, offsets + + +def _compute_pairs(n_rows, n_cols, n=1): + n_tot = n_rows * n_cols + sd_idx = (np.arange(n_tot) // 2).reshape(n_rows, n_cols) + d_bool = np.empty((n_rows, n_cols), bool) + for ri in range(n_rows): + d_bool[ri] = np.arange(ri, ri + n_cols) % 2 + pairs = list() + for ri in range(n_rows): + # First iterate over connections within the row + for ci in range(n_cols - 1): + pair = (sd_idx[ri, ci], sd_idx[ri, ci + 1]) + if d_bool[ri, ci]: # reverse + pair = pair[::-1] + pairs.append(pair) + # Next iterate over row-row connections, if applicable + if ri >= n_rows - 1: + continue + for ci in range(n_cols): + pair = (sd_idx[ri, ci], sd_idx[ri + 1, ci]) + if d_bool[ri, ci]: + pair = pair[::-1] + pairs.append(pair) + if n > 1: + assert n == 2 # only one supported for now + pairs = np.array(pairs, int) + second = pairs + pairs.max(axis=0) + 1 + pairs = np.r_[pairs, second] + pairs = tuple(tuple(row) for row in pairs) + return tuple(pairs) diff --git a/mne-python/source/mne/io/hitachi/tests/test_hitachi.py b/mne-python/source/mne/io/hitachi/tests/test_hitachi.py new file mode 100644 index 0000000000000000000000000000000000000000..09b01b535e3ab7abcc085f5b86cf5c1a8fcf0e06 --- /dev/null +++ b/mne-python/source/mne/io/hitachi/tests/test_hitachi.py @@ -0,0 +1,457 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime as dt + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_less + +from mne.channels import make_standard_montage +from mne.io import read_raw_hitachi +from mne.io.hitachi.hitachi import _compute_pairs +from mne.io.tests.test_raw import _test_raw_reader +from mne.preprocessing.nirs import ( + beer_lambert_law, + optical_density, + scalp_coupling_index, + source_detector_distances, + tddr, +) + +CONTENTS = dict() +CONTENTS["1.18"] = b"""\ +Header,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +File Version,1.18,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Patient Information,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +ID,TestID,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Name,Test,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Comment,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Age, 45y,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Sex,Female,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Analyze Information,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +AnalyzeMode,Continuous,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Pre Time[s],9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Post Time[s],7,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Recovery Time[s],12,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Base Time[s],10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Fitting Degree,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +HPF[Hz],No Filter,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +LPF[Hz],0.1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Moving Average[s],0.1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Measure Information,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Date,5/17/04 5:14,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Mode,3x5,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Wave[nm],695,830,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Wave Length,CH1(700.1),CH1(829.1),CH2(699.3),CH2(827.9),CH3(699.3),CH3(827.9),CH4(698.6),CH4(828.1),CH5(700.1),CH5(829.1),CH6(698.5),CH6(828.2),CH7(699.3),CH7(827.9),CH8(699.8),CH8(828.5),CH9(698.6),CH9(828.1),CH10(698.5),CH10(828.2),CH11(698.5),CH11(828.2),CH12(699.8),CH12(828.5),CH13(699.8),CH13(828.5),CH14(699.0),CH14(828.2),CH15(698.5),CH15(828.2),CH16(699.5),CH16(828.1),CH17(699.8),CH17(828.5),CH18(699.5),CH18(828.5),CH19(699.0),CH19(828.2),CH20(699.5),CH20(828.1),CH21(699.5),CH21(828.1),CH22(699.5),CH22(828.5),,,,, +Analog Gain,30.117647,30.117647,30.117647,30.117647,94.117647,94.117647,94.117647,94.117647,10.27451,10.27451,30.117647,30.117647,59.607843,59.607843,94.117647,94.117647,110.588235,110.588235,10.27451,10.27451,59.607843,59.607843,59.607843,59.607843,110.588235,110.588235,10.27451,10.27451,41.176471,41.176471,59.607843,59.607843,9.333333,9.333333,110.588235,110.588235,41.176471,41.176471,41.176471,41.176471,9.333333,9.333333,9.333333,9.333333,,,,, +Digital Gain,13.38,2.82,44.57,7.52,29.46,4.12,36.56,4.84,6.67,1.37,22.61,3.28,79.19,10.88,16.37,2.78,39.97,4.09,100,38.02,36.58,3.95,61.77,7.67,100,15.23,31.52,7.15,53.46,5.05,13.61,2.07,63.74,11.16,14.35,2.05,58.64,8.93,14.53,1.99,8.16,1.82,27.84,5.97,,,,, +Sampling Period[s],0.1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +StimType,BLOCK,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Stim Time[s],20,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +F1,15,F2,15,F3,15,F4,15,F5,15,F6,15,F7,15,F8,15,F9,15,M,15,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Repeat Count,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Exception Ch,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Data,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +Probe1,CH1(700.1),CH1(829.1),CH2(699.3),CH2(827.9),CH3(699.3),CH3(827.9),CH4(698.6),CH4(828.1),CH5(700.1),CH5(829.1),CH6(698.5),CH6(828.2),CH7(699.3),CH7(827.9),CH8(699.8),CH8(828.5),CH9(698.6),CH9(828.1),CH10(698.5),CH10(828.2),CH11(698.5),CH11(828.2),CH12(699.8),CH12(828.5),CH13(699.8),CH13(828.5),CH14(699.0),CH14(828.2),CH15(698.5),CH15(828.2),CH16(699.5),CH16(828.1),CH17(699.8),CH17(828.5),CH18(699.5),CH18(828.5),CH19(699.0),CH19(828.2),CH20(699.5),CH20(828.1),CH21(699.5),CH21(828.1),CH22(699.5),CH22(828.5),Mark,Time,BodyMovement,RemovalMark,PreScan +1,1.99371338,1.95037842,2.24243164,2.17483521,2.2052002,2.16384888,2.18017578,2.10418701,1.75735474,1.63879395,1.99432373,1.88644409,2.1307373,2.05368042,2.08358765,1.96212769,1.89682007,1.97311401,0.6993103,1.8006897,2.01049805,1.86462402,1.95968628,1.87988281,1.59408569,1.97891235,1.9392395,1.73034668,2.18307495,2.00424194,1.90841675,1.87286377,1.89331055,1.79077148,1.82418823,1.82601929,2.44125366,2.05291748,2.09381104,2.03796387,1.92672729,1.90353394,2.10266113,2.0401001,0,14:08.2,0,0,1 +2,1.97433472,1.94091797,2.31689453,2.16079712,2.22290039,2.15209961,2.12936401,2.08328247,1.75445557,1.63269043,2.01126099,1.88186646,2.11425781,2.04345703,2.07015991,1.95236206,1.90826416,1.95266724,0.71853638,1.78970337,2.03872681,1.8572998,1.95602417,1.86798096,1.59118652,1.94122314,1.93054199,1.72439575,2.21435547,2.00531006,1.90200806,1.86508179,1.87957764,1.78085327,1.81564331,1.81365967,2.33200073,2.02987671,2.0980835,2.02682495,1.92520142,1.8939209,2.10327148,2.01843262,0,14:08.4,0,0,1 +3,1.97616577,1.93359375,2.2819519,2.15866089,2.19512939,2.15301514,2.10266113,2.07931519,1.74468994,1.62582397,2.04330444,1.87774658,2.06222534,2.0425415,2.06008911,1.95098877,1.94946289,1.94793701,0.69549561,1.76803589,1.9909668,1.85028076,1.93374634,1.86599731,1.60140991,1.92367554,1.92260742,1.72225952,2.16796875,1.99523926,1.89208984,1.86080933,1.88095093,1.78207397,1.80541992,1.81091309,2.32818604,2.01675415,2.10418701,2.01965332,1.92001343,1.88995361,2.08648682,2.01065063,0,14:08.4,0,0,1 +4,1.97799683,1.93695068,2.25875854,2.16461182,2.23007202,2.15774536,2.12554932,2.08068848,1.73980713,1.62155151,2.02072144,1.87957764,2.09320068,2.0401001,2.06558228,1.95327759,1.90414429,1.953125,0.66207886,1.77108765,2.01797485,1.85043335,1.98562622,1.86843872,1.48071289,1.93771362,1.92520142,1.71554565,2.18002319,1.98654175,1.89208984,1.85958862,1.88766479,1.78253174,1.81396484,1.80923462,2.34085083,2.01660156,2.09869385,2.0211792,1.92108154,1.89041138,2.07946777,2.01278687,0,14:08.6,0,0,1 +5,1.97219849,1.93847656,2.315979,2.16430664,2.20230103,2.15713501,2.07458496,2.07824707,1.73614502,1.62399292,2.00408936,1.87652588,2.1005249,2.03887939,2.07061768,1.95220947,1.89361572,1.95129395,0.72784424,1.79977417,2.01309204,1.85089111,1.88674927,1.86035156,1.40136719,1.97387695,1.91711426,1.71966553,2.16247559,1.99234009,1.8737793,1.86035156,1.8989563,1.78543091,1.83700562,1.80877686,2.39151001,2.02896118,2.08709717,2.02224731,1.92138672,1.89025879,2.09014893,2.01431274,0,14:08.6,0,0,1 +6,1.96807861,1.93969727,2.27905273,2.15988159,2.22793579,2.15789795,2.10266113,2.08618164,1.73950195,1.62445068,2.01156616,1.87728882,2.08847046,2.03811646,2.06420898,1.95617676,1.91879272,1.95541382,0.7019043,1.77963257,1.98974609,1.85195923,1.93954468,1.86630249,1.57897949,2.00317383,1.91040039,1.72515869,2.24868774,1.99157715,1.89849854,1.86218262,1.90658569,1.78634644,1.82495117,1.81427002,2.45651245,2.03353882,2.10083008,2.02758789,1.92184448,1.89331055,2.09686279,2.01980591,0,14:08.8,0,0,1 +7,1.98776245,1.94198608,2.2895813,2.15759277,2.21405029,2.16812134,2.15332031,2.09991455,1.74499512,1.62765503,2.01919556,1.87911987,2.2026062,2.04589844,2.05276489,1.96105957,1.93862915,1.96105957,0.67474365,1.78604126,1.99249268,1.84967041,1.89849854,1.86676025,1.39373779,1.95846558,1.90979004,1.72698975,2.27798462,1.99798584,1.91055298,1.86172485,1.91375732,1.78375244,1.78024292,1.8157959,2.30819702,2.05245972,2.1043396,2.03079224,1.925354,1.89697266,2.11288452,2.02545166,0,14:08.9,0,0,1 +8,1.98364258,1.94488525,2.28744507,2.16598511,2.20123291,2.17254639,2.13745117,2.10357666,1.75003052,1.63162231,2.00790405,1.87637329,2.20916748,2.05444336,2.05459595,1.95983887,1.90536499,1.96777344,0.72494507,1.78741455,1.98318481,1.85516357,1.89605713,1.86798096,1.4453125,1.95663452,1.91436768,1.73355103,2.22427368,2.00180054,1.89605713,1.86599731,1.86950684,1.79077148,1.79962158,1.82327271,2.31536865,2.06726074,2.09564209,2.03521729,1.92459106,1.90078735,2.10281372,2.03353882,0,14:08.9,0,0,1 +9,1.97967529,1.95297241,2.34939575,2.18048096,2.22961426,2.1711731,2.10784912,2.10617065,1.75308228,1.6368103,2.00836182,1.87728882,2.07595825,2.04437256,2.04742432,1.96411133,1.92672729,1.97036743,0.65322876,1.78192139,2.00515747,1.85562134,1.99584961,1.86828613,1.41708374,1.91955566,1.92321777,1.73690796,2.25341797,1.99813843,1.89788818,1.86904907,1.8699646,1.79336548,1.80130005,1.82952881,2.44827271,2.08602905,2.10388184,2.03964233,1.9291687,1.90505981,2.0980835,2.0401001,0,14:09.1,0,0,1 +10,1.96777344,1.95663452,2.3046875,2.17712402,2.26348877,2.17590332,2.14691162,2.11624146,1.75506592,1.64108276,2.01538086,1.88278198,2.21374512,2.04696655,2.07824707,1.96838379,1.94854736,1.97387695,0.64300537,1.80709839,2.03277588,1.86340332,1.96380615,1.87942505,1.38870239,1.95419312,1.92611694,1.74087524,2.30636597,2.00012207,1.90124512,1.87103271,1.88766479,1.79397583,1.81411743,1.83273315,2.38845825,2.09106445,2.12188721,2.04544067,1.93237305,1.90994263,2.12310791,2.04696655,0,14:09.1,0,0,1 +11,1.98181152,1.96182251,2.2883606,2.1812439,2.25265503,2.18231201,2.12814331,2.11181641,1.75842285,1.64596558,2.0135498,1.88995361,2.15209961,2.05230713,2.07077026,1.97387695,1.86767578,1.98471069,0.69610596,1.80511475,1.9960022,1.87103271,1.90963745,1.8838501,1.41983032,1.98654175,1.91070557,1.74255371,2.22869873,2.00119019,1.8977356,1.87103271,1.87271118,1.80007935,1.83288574,1.83670044,2.45758057,2.09213257,2.08786011,2.04910278,1.93267822,1.90963745,2.10998535,2.05307007,0,14:09.2,0,0,1 +12,1.9909668,1.95526123,2.2756958,2.17941284,2.26486206,2.17056274,2.14797974,2.09945679,1.75415039,1.64199829,2.02407837,1.8913269,2.07015991,2.05383301,2.05596924,1.96411133,1.85272217,1.96365356,0.62423706,1.79443359,1.99417114,1.86538696,1.96487427,1.87637329,1.50161743,1.97616577,1.92626953,1.73583984,2.29568481,2.00210571,1.90765381,1.86904907,1.87347412,1.79473877,1.81488037,1.82327271,2.35809326,2.07244873,2.09411621,2.03353882,1.92932129,1.90338135,2.10510254,2.03475952,0,14:09.4,0,0,1 +13,1.98287964,1.94839478,2.24395752,2.18048096,2.22961426,2.16156006,2.13409424,2.08709717,1.74362183,1.62902832,2.0111084,1.89331055,2.10952759,2.05001831,2.06558228,1.95846558,1.92581177,1.95098877,0.67565918,1.77017212,1.96060181,1.85882568,1.95159912,1.8762207,1.68884277,1.97921753,1.92855835,1.73416138,2.23876953,2.00210571,1.90200806,1.86828613,1.88858032,1.78710938,1.83029175,1.81137085,2.3526001,2.04116821,2.10769653,2.02423096,1.92565918,1.90002441,2.09457397,2.01904297,0,14:09.5,0,0,1 +14,1.99539185,1.93984985,2.27966309,2.16644287,2.20947266,2.16186523,2.12966919,2.08984375,1.73339844,1.61865234,2.02865601,1.89239502,2.11593628,2.05337524,2.05307007,1.95632935,1.9682312,1.95175171,0.69198608,1.7729187,1.95541382,1.85348511,1.95953369,1.86935425,1.55059814,1.9203186,1.91192627,1.73065186,2.30255127,1.99172974,1.89743042,1.86325073,1.87255859,1.7855835,1.83547974,1.81137085,2.35107422,2.0413208,2.09243774,2.01477051,1.92810059,1.89575195,2.10174561,2.01538086,0,14:09.6,0,0,1 +15,1.97799683,1.9380188,2.25616455,2.15927124,2.23983765,2.16186523,2.15667725,2.0942688,1.72332764,1.61178589,2.04833984,1.88995361,2.12112427,2.04421997,2.0703125,1.9569397,1.98425293,1.9581604,0.6690979,1.75369263,1.97433472,1.8536377,1.90307617,1.87408447,1.5020752,1.92214966,1.90536499,1.7276001,2.22579956,1.98196411,1.90704346,1.86431885,1.88552856,1.78817749,1.8157959,1.81396484,2.34634399,2.02667236,2.05535889,2.01370239,1.92642212,1.8963623,2.10540771,2.01812744,0,14:09.6,0,0,1 +16,1.97402954,1.94320679,2.28927612,2.16308594,2.22045898,2.15759277,2.13287354,2.09533691,1.72103882,1.61392212,2.03170776,1.89239502,2.12036133,2.0539856,2.05886841,1.95785522,1.96426392,1.95388794,0.64727783,1.75918579,2.00241089,1.85623169,1.95159912,1.86813354,1.42822266,1.94442749,1.91574097,1.73110962,2.2265625,1.98608398,1.90155029,1.86447144,1.87133789,1.7880249,1.82418823,1.81488037,2.38815308,2.03323364,2.06680298,2.01141357,1.92764282,1.89865112,2.11410522,2.02316284,0,14:09.8,0,0,1 +17,1.97616577,1.94488525,2.28408813,2.16262817,2.22442627,2.16323853,2.10845947,2.09335327,1.72180176,1.61437988,2.01812744,1.89025879,2.14065552,2.04421997,2.05230713,1.95846558,1.93649292,1.95465088,0.62026978,1.77139282,1.99203491,1.85516357,1.91833496,1.8598938,1.5234375,1.96426392,1.92260742,1.73278809,2.18643188,1.98486328,1.91436768,1.86691284,1.87942505,1.79458618,1.82723999,1.82144165,2.24609375,2.04086304,2.08587646,2.01477051,1.92611694,1.90170288,2.10418701,2.03155518,0,14:09.8,0,0,1 +18,1.98242188,1.94839478,2.23770142,2.17681885,2.24349976,2.16690063,2.14187622,2.10189819,1.72317505,1.6166687,2.01126099,1.89300537,2.2442627,2.05917358,2.07855225,1.95892334,2.00881958,1.96578979,0.66619873,1.79229736,2.00164795,1.85974121,1.94900513,1.86813354,1.49673462,1.97021484,1.93161011,1.73477173,2.26104736,1.99493408,1.9052124,1.86889648,1.85714722,1.79290771,1.80648804,1.82571411,2.33688354,2.03872681,2.0715332,2.02072144,1.92749023,1.9039917,2.11380005,2.03704834,0,14:09.9,0,0,1 +19,1.99203491,1.95053101,2.21984863,2.16567993,2.24914551,2.16644287,2.17529297,2.11242676,1.72943115,1.62200928,2.01705933,1.89071655,2.08297729,2.05413818,2.06710815,1.96289063,1.95388794,1.97113037,0.65765381,1.79656982,1.99569702,1.86813354,1.95297241,1.88034058,1.61651611,1.96380615,1.91329956,1.7388916,2.31140137,1.99768066,1.91375732,1.87347412,1.88522339,1.80053711,1.8321228,1.83013916,2.43652344,2.05963135,2.0715332,2.02224731,1.93084717,1.9078064,2.11685181,2.04299927,0,14:10.1,0,0,1 +20,1.99111938,1.95373535,2.26196289,2.18078613,2.1987915,2.16827393,2.13729858,2.11776733,1.73477173,1.6267395,2.01141357,1.88583374,2.09472656,2.05413818,2.0602417,1.97067261,1.92123413,1.97341919,0.67626953,1.81976318,1.98623657,1.8711853,1.99081421,1.88323975,1.51351929,1.94259644,1.91070557,1.74301147,2.34313965,1.99783325,1.90933228,1.87561035,1.91986084,1.80526733,1.83883667,1.83425903,2.3789978,2.07061768,2.10906982,2.02911377,1.93069458,1.91040039,2.11120605,2.05444336,0,14:10.1,0,0,1 +21,1.99432373,1.95632935,2.26348877,2.17254639,2.22091675,2.17041016,2.1395874,2.11257935,1.73446655,1.62948608,2.0085144,1.88919067,2.13272095,2.06359863,2.07229614,1.96777344,1.91635132,1.97753906,0.67993164,1.78771973,2.01278687,1.87179565,1.92855835,1.88446045,1.44363403,1.96456909,1.90948486,1.74346924,2.24441528,2.0022583,1.90689087,1.87637329,1.91253662,1.80480957,1.81213379,1.83670044,2.32421875,2.07244873,2.08938599,2.03018188,1.93405151,1.91101074,2.12799072,2.05245972,0,14:10.3,0,0,1 +22,1.97540283,1.94702148,2.29507446,2.16796875,2.23678589,2.16369629,2.15377808,2.09854126,1.73431396,1.62582397,2.02285767,1.88613892,2.14736938,2.05108643,2.06466675,1.95739746,1.98852539,1.95831299,0.66726685,1.80206299,1.99890137,1.87103271,1.95175171,1.87332153,1.48300171,1.93161011,1.91070557,1.73553467,2.3236084,1.99890137,1.89224243,1.87210083,1.90490723,1.79199219,1.80984497,1.82266235,2.44430542,2.059021,2.09091187,2.02682495,1.92596436,1.90322876,2.11151123,2.0300293,0,14:10.3,0,0,1 +23,1.98196411,1.94076538,2.25891113,2.17376709,2.22000122,2.162323,2.11456299,2.07885742,1.73431396,1.62353516,2.02423096,1.88400269,2.14614868,2.0489502,2.04788208,1.95053101,1.9392395,1.93847656,0.6968689,1.80007935,1.99325562,1.86325073,1.92306519,1.86325073,1.52069092,1.96899414,1.89575195,1.73110962,2.38296509,1.99050903,1.90322876,1.86798096,1.88522339,1.79397583,1.81793213,1.81259155,2.34802246,2.05993652,2.09609985,2.02072144,1.92993164,1.89910889,2.09411621,2.01675415,0,14:10.5,0,0,1 +24,1.97601318,1.93710327,2.27630615,2.16629028,2.22366333,2.15438843,2.13867188,2.08312988,1.73614502,1.62216187,2.00546265,1.88217163,2.11608887,2.0501709,2.04437256,1.94610596,1.88034058,1.93847656,0.68283081,1.78573608,1.99447632,1.86126709,1.93969727,1.86203003,1.6204834,1.95159912,1.90353394,1.72515869,2.29537964,1.99157715,1.90353394,1.86798096,1.90856934,1.78466797,1.77825928,1.81182861,2.35046387,2.06130981,2.10220337,2.02468872,1.92657471,1.89956665,2.10189819,2.01812744,0,14:10.6,0,0,1 +25,1.97372437,1.9380188,2.26913452,2.16491699,2.20046997,2.15499878,2.13699341,2.0916748,1.73629761,1.62216187,2.02514648,1.88156128,2.17895508,2.03781128,2.06069946,1.94992065,1.95129395,1.9493103,0.65811157,1.78390503,2.00195313,1.85958862,1.96380615,1.86416626,1.69540405,1.92749023,1.91375732,1.72927856,2.30285645,1.98608398,1.90231323,1.86950684,1.90658569,1.79290771,1.80221558,1.81259155,2.39135742,2.05551147,2.09152222,2.02423096,1.92901611,1.90032959,2.10449219,2.02301025,0,14:10.6,0,0,1 +26,1.98699951,1.9418335,2.2845459,2.16461182,2.21847534,2.15362549,2.14553833,2.0916748,1.73446655,1.62445068,2.02957153,1.88095093,2.18887329,2.05001831,2.05780029,1.94961548,1.97113037,1.95617676,0.6690979,1.77810669,1.98165894,1.86172485,1.93984985,1.86752319,1.46759033,1.93847656,1.90689087,1.73477173,2.2215271,1.99356079,1.9078064,1.86767578,1.87561035,1.79550171,1.78695679,1.8145752,2.38891602,2.06634521,2.0803833,2.02377319,1.93099976,1.8989563,2.11105347,2.02850342,0,14:10.8,0,0,1 +27,1.99172974,1.94488525,2.28012085,2.16674805,2.24365234,2.15255737,2.14172363,2.1055603,1.7350769,1.62643433,2.02728271,1.88201904,2.13470459,2.03796387,2.06558228,1.95373535,1.9128418,1.9631958,0.67138672,1.78161621,1.99951172,1.86965942,1.90719604,1.87133789,1.49520874,1.96914673,1.90155029,1.73812866,2.16400146,2.00546265,1.89971924,1.86859131,1.89453125,1.79473877,1.82540894,1.81884766,2.40783691,2.07489014,2.08694458,2.02423096,1.92840576,1.90185547,2.10632324,2.03353882,0,14:10.8,0,0,1 +28,1.9732666,1.95175171,2.25753784,2.16812134,2.240448,2.16156006,2.11791992,2.10235596,1.73721313,1.63009644,1.99203491,1.88873291,2.20687866,2.04162598,2.0489502,1.95770264,1.93862915,1.95953369,0.67749023,1.79397583,2.0211792,1.86920166,1.85409546,1.87423706,1.53579712,1.94671631,1.90414429,1.74194336,2.23876953,1.99981689,1.91268921,1.86859131,1.88369751,1.79840088,1.83441162,1.82449341,2.38571167,2.07824707,2.09381104,2.02697754,1.92687988,1.90490723,2.10479736,2.04147339,0,14:11.0,0,0,1 +29,1.96792603,1.95770264,2.28240967,2.16888428,2.22106934,2.16705322,2.1295166,2.10174561,1.74163818,1.63330078,1.99935913,1.8901062,2.05825806,2.04925537,2.0401001,1.95861816,1.91741943,1.96105957,0.70831299,1.81396484,1.99874878,1.86752319,1.96304321,1.87301636,1.42089844,1.96243286,1.90505981,1.74209595,2.13973999,2.00485229,1.90628052,1.87057495,1.88659668,1.80053711,1.83898926,1.82998657,2.44888306,2.07855225,2.1055603,2.02880859,1.93206787,1.90536499,2.11380005,2.04437256,0,14:11.1,0,0,1 +30,1.97982788,1.95861816,2.2505188,2.16903687,2.2227478,2.16842651,2.12631226,2.11807251,1.74026489,1.63619995,1.99783325,1.89453125,2.05108643,2.04086304,2.06497192,1.96716309,1.87042236,1.97525024,0.67626953,1.82174683,2.00271606,1.87316895,1.97113037,1.87850952,1.46469116,1.95175171,1.92520142,1.74423218,2.26837158,1.99874878,1.9090271,1.87347412,1.90673828,1.80084229,1.83151245,1.82739258,2.51907349,2.09030151,2.10220337,2.03170776,1.93618774,1.9102478,2.11425781,2.05169678,0,14:11.2,0,0,1 +31,1.97662354,1.96273804,2.19848633,2.17575073,2.19696045,2.16384888,2.14111328,2.12295532,1.74194336,1.63970947,2.01950073,1.89575195,2.13088989,2.06619263,2.04589844,1.96792603,1.90551758,1.98348999,0.65628052,1.81152344,2.01904297,1.87957764,1.92276001,1.88323975,1.38900757,1.93771362,1.90887451,1.75201416,2.27508545,2.00576782,1.91711426,1.87973022,1.88964844,1.80877686,1.82907104,1.83349609,2.44598389,2.09075928,2.10540771,2.0401001,1.93710327,1.91833496,2.11593628,2.05657959,0,14:11.2,0,0,1 +32,1.98669434,1.96029663,2.29675293,2.18917847,2.212677,2.16842651,2.14202881,2.11395264,1.74453735,1.64199829,2.00759888,1.89605713,2.14096069,2.05078125,2.0463562,1.96517944,2.01156616,1.97677612,0.64559937,1.80419922,1.98120117,1.88049316,1.91513062,1.88598633,1.56158447,1.95755005,1.91253662,1.75048828,2.18658447,2.00912476,1.90185547,1.88064575,1.88568115,1.80496216,1.8296814,1.83319092,2.41394043,2.10067749,2.10159302,2.0324707,1.9354248,1.9140625,2.11898804,2.05200195,0,14:11.3,0,0,1 +33,1.98532104,1.953125,2.27600098,2.18566895,2.20947266,2.15698242,2.13500977,2.0954895,1.74285889,1.63894653,2.01202393,1.88949585,2.19451904,2.06787109,2.05490112,1.95678711,1.97540283,1.96029663,0.66055298,1.81503296,1.97738647,1.87210083,1.97067261,1.87454224,1.6456604,1.96868896,1.90658569,1.74728394,2.25372314,2.01553345,1.90567017,1.87515259,1.90261841,1.79962158,1.82418823,1.81686401,2.33856201,2.09381104,2.09152222,2.02682495,1.93237305,1.90582275,2.10144043,2.03186035,0,14:11.5,0,0,1 +34,1.98028564,1.94595337,2.23480225,2.17849731,2.20993042,2.15255737,2.09884644,2.08557129,1.74606323,1.63528442,2.02789307,1.88995361,2.24090576,2.05276489,2.06481934,1.94869995,1.96670532,1.93939209,0.71411133,1.82739258,2.00210571,1.87133789,1.8951416,1.87179565,1.40487671,1.97174072,1.92230225,1.73446655,2.30804443,1.99539185,1.90155029,1.87393188,1.90307617,1.79489136,1.84265137,1.81015015,2.44552612,2.05978394,2.08709717,2.02377319,1.927948,1.902771,2.09716797,2.02133179,0,14:11.6,0,0,1 +35,1.97540283,1.9418335,2.27020264,2.17758179,2.19360352,2.15652466,2.16308594,2.08129883,1.74377441,1.63543701,2.00958252,1.88842773,2.11303711,2.06390381,2.06314087,1.9493103,1.9619751,1.93954468,0.69076538,1.81472778,2.03689575,1.86843872,1.91299438,1.87408447,1.51916504,1.91619873,1.91848755,1.73812866,2.23510742,1.98944092,1.90612793,1.87515259,1.91253662,1.78939819,1.82876587,1.81427002,2.47390747,2.06634521,2.10739136,2.02651978,1.92840576,1.90383911,2.09747314,2.02224731,0,14:11.7,0,0,1 +36,1.98654175,1.94610596,2.27264404,2.17437744,2.22106934,2.15866089,2.12554932,2.08435059,1.74606323,1.63543701,1.9984436,1.88232422,2.15118408,2.07473755,2.06695557,1.94976807,1.91421509,1.94625854,0.6652832,1.7930603,2.01431274,1.8661499,1.9052124,1.86920166,1.55166626,1.90185547,1.90719604,1.74057007,2.18048096,1.99295044,1.90582275,1.87240601,1.87057495,1.79382324,1.81945801,1.81213379,2.37976074,2.06634521,2.12615967,2.02682495,1.92977905,1.90292358,2.10525513,2.02194214,0,14:11.8,0,0,1 +37,1.97418213,1.95037842,2.25952148,2.17269897,2.22961426,2.15362549,2.0614624,2.09396362,1.74377441,1.63726807,1.98318481,1.88934326,2.14096069,2.05230713,2.06344604,1.953125,1.89468384,1.9468689,0.64910889,1.81091309,1.97463989,1.86981201,1.90811157,1.87866211,1.52664185,1.94763184,1.89559937,1.73934937,2.22137451,2.00042725,1.90795898,1.87728882,1.88369751,1.79885864,1.82128906,1.80984497,2.44415283,2.081604,2.10021973,2.02728271,1.93084717,1.90689087,2.11395264,2.02575684,0,14:11.8,0,0,1 +38,1.97113037,1.95098877,2.28057861,2.17910767,2.20901489,2.1546936,2.10067749,2.09320068,1.74591064,1.63955688,1.97174072,1.89056396,2.1446228,2.04574585,2.05657959,1.95877075,1.92642212,1.95083618,0.63217163,1.81213379,2.00714111,1.87301636,1.98638916,1.87606812,1.45858765,1.99295044,1.90216064,1.74407959,2.17819214,1.99295044,1.92062378,1.87606812,1.88461304,1.80175781,1.82876587,1.81533813,2.4307251,2.07778931,2.09899902,2.02865601,1.92947388,1.90719604,2.11364746,2.03216553,0,14:11.9,0,0,1 +39,1.98394775,1.95678711,2.25265503,2.18460083,2.21923828,2.15988159,2.15713501,2.09335327,1.74743652,1.64108276,2.04437256,1.89544678,2.12524414,2.05551147,2.05307007,1.96258545,1.99295044,1.95983887,0.64346313,1.82022095,2.00897217,1.87362671,1.93954468,1.87927246,1.52832031,1.95571899,1.9203186,1.75460815,2.2946167,2.006073,1.91299438,1.87805176,1.88018799,1.80877686,1.82983398,1.822052,2.30957031,2.07626343,2.09136963,2.03262329,1.93527222,1.91085815,2.12005615,2.04284668,0,14:12.1,0,0,1 +40,1.99996948,1.95755005,2.28988647,2.18170166,2.22320557,2.17285156,2.16186523,2.10845947,1.74118042,1.63909912,2.05337524,1.90185547,2.13424683,2.06466675,2.07107544,1.96563721,1.96090698,1.96670532,0.71044922,1.79550171,2.01095581,1.8762207,1.97921753,1.8901062,1.50222778,1.93222046,1.92138672,1.75964355,2.3059082,2.01477051,1.91619873,1.87973022,1.90139771,1.80679321,1.83731079,1.82510376,2.34085083,2.08114624,2.08953857,2.02774048,1.93740845,1.91421509,2.11639404,2.04940796,0,14:12.2,0,0,1 +41,1.98394775,1.95785522,2.25570679,2.17987061,2.19512939,2.17559814,2.11608887,2.11883545,1.7388916,1.64154053,2.0324707,1.90444946,2.1333313,2.06680298,2.06741333,1.97052002,1.94564819,1.97097778,0.71166992,1.81335449,1.99691772,1.87667847,1.94152832,1.8901062,1.54220581,1.95541382,1.91833496,1.7666626,2.22686768,2.00790405,1.92260742,1.87988281,1.88781738,1.81121826,1.83670044,1.83380127,2.39196777,2.09289551,2.10189819,2.02896118,1.9380188,1.91558838,2.1182251,2.05627441,0,14:12.2,0,0,1 +42,1.96655273,1.96670532,2.2428894,2.18521118,2.23602295,2.1824646,2.16140747,2.11669922,1.74179077,1.64825439,2.03186035,1.90765381,2.07855225,2.06985474,2.05505371,1.97662354,1.98059082,1.97189331,0.6741333,1.84951782,1.97174072,1.88201904,1.95968628,1.89102173,1.41387939,1.98577881,1.92245483,1.77017212,2.16629028,2.0199585,1.9229126,1.88522339,1.87713623,1.81396484,1.81137085,1.8371582,2.3600769,2.11273193,2.07809448,2.03613281,1.94168091,1.92138672,2.12341309,2.06573486,0,14:12.4,0,0,1 +43,1.97341919,1.96578979,2.24502563,2.19055176,2.23724365,2.17605591,2.15484619,2.12188721,1.746521,1.6494751,2.01507568,1.90429688,2.10388184,2.06283569,2.07687378,1.97143555,1.96487427,1.97555542,0.68862915,1.82952881,2.03384399,1.88674927,1.96395874,1.8850708,1.54769897,1.99737549,1.92306519,1.76605225,2.21679688,2.0211792,1.91802979,1.88659668,1.87820435,1.81503296,1.82281494,1.84005737,2.43560791,2.10571289,2.10769653,2.03689575,1.94198608,1.91970825,2.11730957,2.06207275,0,14:12.5,0,0,1 +44,1.97677612,1.95495605,2.31628418,2.1824646,2.24975586,2.16705322,2.16384888,2.10510254,1.74972534,1.64962769,2.00683594,1.89987183,2.18933105,2.05993652,2.05795288,1.96350098,1.96136475,1.95556641,0.67184448,1.83441162,2.01568604,1.88369751,1.93725586,1.88537598,1.53778076,1.9644165,1.9078064,1.76193237,2.23556519,2.01507568,1.92657471,1.88308716,1.90872192,1.80892944,1.80892944,1.824646,2.41073608,2.10205078,2.10174561,2.02835083,1.93664551,1.91375732,2.10754395,2.04376221,0,14:12.6,0,0,1 +45,1.98364258,1.95449829,2.40234375,2.18063354,2.24273682,2.16293335,2.12936401,2.08892822,1.75170898,1.6468811,2.03491211,1.89651489,2.09945679,2.06298828,2.04452515,1.9619751,1.95175171,1.94580078,0.67153931,1.84738159,1.99142456,1.88156128,1.97402954,1.88873291,1.5562439,1.93710327,1.91986084,1.75445557,2.24014282,2.00073242,1.91513062,1.88217163,1.9128418,1.80236816,1.81152344,1.81549072,2.42279053,2.09197998,2.10281372,2.02880859,1.93405151,1.91238403,2.10678101,2.03369141,0,14:12.6,0,0,1 +46,1.96777344,1.95617676,2.30743408,2.1812439,2.23892212,2.15713501,2.13638306,2.0930481,1.74987793,1.64794922,2.03643799,1.89727783,2.1005249,2.06054688,2.05734253,1.96029663,1.96228027,1.95129395,0.72982788,1.83746338,2.02377319,1.88827515,1.97128296,1.88751221,1.50405884,1.9102478,1.89865112,1.7515564,2.27020264,2.01141357,1.93069458,1.87820435,1.88690186,1.80007935,1.82373047,1.81625366,2.35076904,2.10906982,2.08908081,2.03033447,1.93267822,1.90689087,2.10128784,2.03399658,0,14:12.8,0,0,1 +47,1.96929932,1.95877075,2.28775024,2.18338013,2.19100952,2.16186523,2.16033936,2.09518433,1.75170898,1.64901733,2.00866699,1.89712524,2.13317871,2.05780029,2.06939697,1.95587158,1.93664551,1.95556641,0.70632935,1.85668945,2.01766968,1.89147949,1.90383911,1.88262939,1.52236938,1.93008423,1.92367554,1.75460815,2.26470947,2.0149231,1.92520142,1.87896729,1.86187744,1.80343628,1.81396484,1.82006836,2.41210938,2.11471558,2.10922241,2.03659058,1.93893433,1.90811157,2.12219238,2.03598022,0,14:12.8,0,0,1 +48,1.99050903,1.96456909,2.27706909,2.19543457,2.17453003,2.15866089,2.17346191,2.10296631,1.75491333,1.6519165,1.98883057,1.89880371,2.10327148,2.05596924,2.06604004,1.95922852,1.9720459,1.9581604,0.70800781,1.84875488,1.98745728,1.88720703,1.85241699,1.88262939,1.64047241,1.95999146,1.92306519,1.7565918,2.19161987,2.00561523,1.90505981,1.87606812,1.89590454,1.8057251,1.81045532,1.82006836,2.48703003,2.1194458,2.10891724,2.03399658,1.93939209,1.90689087,2.11242676,2.04162598,0,14:12.9,0,0,1 +49,1.97280884,1.97250366,2.30514526,2.1875,2.18338013,2.16217041,2.16903687,2.09976196,1.7539978,1.65435791,2.02072144,1.90002441,2.09899902,2.04727173,2.05581665,1.96090698,2.02911377,1.95846558,0.68664551,1.86218262,1.99523926,1.89331055,1.92123413,1.87957764,1.65481567,1.98486328,1.90444946,1.75323486,2.19009399,2.01766968,1.9342041,1.87744141,1.91238403,1.80587769,1.84326172,1.82693481,2.46429443,2.12585449,2.11929321,2.0350647,1.94122314,1.90887451,2.09945679,2.04971313,0,14:13.1,0,0,1 +50,1.98562622,1.97647095,2.25646973,2.19741821,2.22045898,2.16873169,2.15682983,2.10876465,1.75262451,1.6569519,2.00668335,1.90261841,2.12188721,2.04498291,2.06100464,1.96395874,1.95648193,1.96670532,0.69229126,1.85089111,2.00088501,1.89285278,1.9354248,1.88446045,1.55502319,1.96472168,1.90673828,1.76055908,2.2605896,2.01889038,1.91513062,1.88034058,1.94366455,1.80252075,1.84631348,1.82983398,2.37731934,2.12509155,2.11257935,2.03948975,1.94213867,1.91162109,2.11624146,2.05383301,0,14:13.2,0,0,1 +51,1.98532104,1.978302,2.27981567,2.19924927,2.24197388,2.17575073,2.18032837,2.11700439,1.74530029,1.65390015,2.02804565,1.91070557,2.18261719,2.06604004,2.06130981,1.97311401,1.95709229,1.97128296,0.67932129,1.84173584,2.03796387,1.90048218,1.94915771,1.89086914,1.46484375,1.97113037,1.92382813,1.76513672,2.27050781,2.02255249,1.91848755,1.88430786,1.91436768,1.81274414,1.84127808,1.83654785,2.46307373,2.11654663,2.09915161,2.04284668,1.93908691,1.91619873,2.12753296,2.05993652,0,14:13.2,0,0,1 +52,1.97509766,1.97967529,2.36450195,2.19345093,2.20993042,2.17163086,2.16583252,2.12280273,1.73919678,1.64871216,2.03323364,1.91452026,2.16796875,2.07000732,2.07672119,1.978302,1.98638916,1.97525024,0.7093811,1.84326172,2.03903198,1.89804077,1.99325562,1.90338135,1.72515869,1.95877075,1.92169189,1.77062988,2.31582642,2.03323364,1.9090271,1.88720703,1.88232422,1.82006836,1.83380127,1.84494019,2.45056152,2.12860107,2.10067749,2.04116821,1.93969727,1.91940308,2.13150024,2.06924438,0,14:13.3,0,0,1 +53,1.99325562,1.97662354,2.32818604,2.2052002,2.22793579,2.1786499,2.16842651,2.11837769,1.74057007,1.64794922,2.04315186,1.91970825,2.12310791,2.07366943,2.07748413,1.97845459,1.97799683,1.97662354,0.70541382,1.82373047,2.01553345,1.90078735,1.95404053,1.90170288,1.62277222,1.94091797,1.91558838,1.77001953,2.30239868,2.02728271,1.93084717,1.88735962,1.88156128,1.81793213,1.84570313,1.84280396,2.46688843,2.13165283,2.10281372,2.0413208,1.94015503,1.91955566,2.12234497,2.06802368,0,14:13.5,0,0,1 +54,1.99813843,1.96731567,2.29202271,2.2076416,2.23937988,2.17666626,2.13287354,2.10449219,1.73568726,1.64352417,2.03887939,1.91711426,2.06069946,2.07778931,2.08129883,1.96777344,1.93588257,1.94976807,0.71517944,1.83792114,2.02056885,1.89315796,1.92520142,1.89743042,1.54418945,1.96350098,1.90139771,1.76101685,2.27981567,2.02011108,1.92138672,1.88781738,1.90750122,1.81045532,1.81747437,1.82617188,2.29568481,2.1105957,2.10891724,2.03613281,1.93557739,1.91497803,2.10845947,2.04650879,0,14:13.6,0,0,1 +55,1.97982788,1.95541382,2.26745605,2.19268799,2.1913147,2.16308594,2.12265015,2.09365845,1.7350769,1.6394043,2.02392578,1.91116333,2.11090088,2.07733154,2.07366943,1.96212769,1.9631958,1.94335938,0.66879272,1.82617188,2.03765869,1.88583374,1.925354,1.88858032,1.53167725,1.97021484,1.90078735,1.75140381,2.27142334,2.01004028,1.92474365,1.88491821,1.8951416,1.80236816,1.8145752,1.81838989,2.31750488,2.08572388,2.10067749,2.02957153,1.93252563,1.91040039,2.10586548,2.03338623,0,14:13.6,0,0,1 +56,1.9859314,1.95953369,2.30621338,2.18582153,2.26013184,2.16308594,2.12921143,2.08862305,1.7338562,1.6394043,2.02148438,1.90628052,2.16705322,2.06985474,2.07275391,1.96228027,1.90734863,1.94320679,0.67001343,1.84280396,2.00927734,1.88934326,1.93099976,1.88140869,1.48971558,1.95343018,1.90475464,1.7527771,2.2303772,2.00912476,1.92123413,1.88354492,1.87469482,1.80419922,1.83670044,1.81594849,2.43453979,2.09838867,2.10510254,2.03552246,1.93344116,1.90979004,2.10449219,2.03201294,0,14:13.8,0,0,1 +57,1.97692871,1.95877075,2.25662231,2.19192505,2.18582153,2.16278076,2.12554932,2.09823608,1.7364502,1.63955688,2.00866699,1.90658569,2.16339111,2.05917358,2.07611084,1.96426392,1.92504883,1.94625854,0.67138672,1.83792114,2.00088501,1.88934326,1.97357178,1.88339233,1.52603149,1.91513062,1.90689087,1.75064087,2.23968506,2.01004028,1.92642212,1.88079834,1.90872192,1.80130005,1.8208313,1.8196106,2.35809326,2.11914063,2.10494995,2.03186035,1.93527222,1.90917969,2.10693359,2.03475952,0,14:13.9,0,0,1 +58,1.96884155,1.96380615,2.2869873,2.18612671,2.19711304,2.16278076,2.17208862,2.09838867,1.7364502,1.64108276,2.0401001,1.902771,2.16567993,2.06344604,2.08374023,1.96090698,1.95404053,1.95205688,0.68054199,1.82876587,1.99401855,1.88980103,1.92932129,1.88278198,1.5574646,1.94778442,1.90444946,1.75033569,2.27706909,2.01431274,1.92123413,1.88522339,1.89453125,1.80648804,1.8347168,1.82128906,2.36129761,2.09823608,2.10357666,2.03796387,1.9342041,1.91268921,2.11395264,2.0401001,0,14:13.9,0,0,1 +59,1.99127197,1.96868896,2.30560303,2.19406128,2.20077515,2.16506958,2.1282959,2.10098267,1.73904419,1.64550781,2.02056885,1.90383911,2.18032837,2.06710815,2.05780029,1.9581604,1.94717407,1.96212769,0.68649292,1.83181763,1.98196411,1.89056396,1.97280884,1.8888855,1.50177002,1.95922852,1.90307617,1.75338745,2.15057373,2.01873779,1.90261841,1.88278198,1.8901062,1.80679321,1.81869507,1.82510376,2.41439819,2.10342407,2.11669922,2.03872681,1.9342041,1.91101074,2.12295532,2.0463562,0,14:14.1,0,0,1 +60,1.99523926,1.97143555,2.33352661,2.19512939,2.22671509,2.16888428,2.11273193,2.10479736,1.7414856,1.65023804,2.02011108,1.90368652,2.15698242,2.06314087,2.06939697,1.96411133,1.98226929,1.96411133,0.68206787,1.85348511,1.97357178,1.89147949,1.96670532,1.89239502,1.45980835,1.9569397,1.90994263,1.75567627,2.19894409,2.01599121,1.91940308,1.88644409,1.87759399,1.80664063,1.8296814,1.83166504,2.4055481,2.14035034,2.10906982,2.04696655,1.93634033,1.91757202,2.12265015,2.05444336,0,14:14.2,0,0,1 +""" # noqa: E501 + + +CONTENTS["1.25"] = b"""\ +Header +File Version,1.25 +Patient Information +ID,REDACTED +Name, +Comment,sentence,, +Birth Date,1999/09/09 +Age, 99y +Sex,Male +Analyze Information +AnalyzeMode,Continuous +Pre Time[s],9.0 +Post Time[s],7.0 +Recovery Time[s],12.0 +Base Time[s],5 +Fitting Degree,1 +HPF[Hz],No Filter +LPF[Hz],No Filter +Moving Average[s],0.1 +Measure Information +Date,2020/02/02 11:20 +Probe Type,adult +Mode,3x11 +Wave[nm],695,830 +Wave Length,CH1(703.6),CH1(829.0),CH2(703.9),CH2(829.3),CH3(703.9),CH3(829.3),CH4(703.9),CH4(828.8),CH5(703.9),CH5(828.8),CH6(703.1),CH6(828.8),CH7(703.1),CH7(828.8),CH8(702.9),CH8(829.0),CH9(702.9),CH9(829.0),CH10(703.6),CH10(829.0),CH11(703.6),CH11(829.0),CH12(703.4),CH12(829.0),CH13(703.9),CH13(829.3),CH14(703.6),CH14(828.5),CH15(703.9),CH15(828.8),CH16(704.1),CH16(829.8),CH17(703.1),CH17(828.8),CH18(704.4),CH18(829.0),CH19(702.9),CH19(829.0),CH20(703.9),CH20(828.8),CH21(703.6),CH21(829.0),CH22(703.4),CH22(829.0),CH23(703.4),CH23(829.0),CH24(703.6),CH24(828.5),CH25(703.6),CH25(828.5),CH26(704.1),CH26(829.8),CH27(704.1),CH27(829.8),CH28(704.4),CH28(829.0),CH29(704.4),CH29(829.0),CH30(703.9),CH30(828.8),CH31(703.9),CH31(828.8),CH32(704.1),CH32(828.8),CH33(703.4),CH33(829.0),CH34(703.1),CH34(828.8),CH35(703.6),CH35(828.5),CH36(704.4),CH36(828.8),CH37(704.1),CH37(829.8),CH38(703.6),CH38(828.5),CH39(704.4),CH39(829.0),CH40(703.9),CH40(829.0),CH41(703.9),CH41(828.8),CH42(704.4),CH42(829.0),CH43(704.1),CH43(828.8),CH44(703.1),CH44(828.8),CH45(703.1),CH45(828.8),CH46(704.4),CH46(828.8),CH47(704.4),CH47(828.8),CH48(703.6),CH48(828.5),CH49(703.6),CH49(828.5),CH50(703.9),CH50(829.0),CH51(703.9),CH51(829.0),CH52(704.4),CH52(829.0) +Analog Gain,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,6.58823500,6.58823500,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,6.58823500,6.58823500,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,6.58823500,6.58823500,2.74509800,2.74509800,1.25490200,1.25490200,4.07843100,4.07843100,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,2.74509800,2.74509800,2.74509800,2.74509800,4.07843100,4.07843100,4.07843100,4.07843100,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200,1.25490200 +Digital Gain,5.99000000,3.61000000,1.93000000,1.12000000,5.43000000,3.20000000,7.11000000,4.02000000,11.82000000,6.06000000,16.42000000,7.48000000,15.82000000,7.56000000,12.13000000,6.80000000,14.62000000,7.78000000,5.35000000,2.57000000,10.27000000,5.01000000,52.84000000,26.95000000,9.75000000,6.12000000,6.97000000,3.99000000,11.31000000,5.91000000,2.26000000,1.15000000,9.49000000,4.58000000,3.21000000,2.25000000,2.97000000,1.65000000,12.34000000,6.77000000,33.81000000,17.23000000,7.10000000,2.92000000,12.78000000,7.02000000,17.47000000,9.94000000,16.93000000,9.55000000,6.87000000,3.47000000,5.96000000,3.07000000,20.56000000,13.42000000,3.67000000,2.53000000,17.39000000,8.72000000,2.96000000,1.61000000,14.25000000,5.67000000,8.87000000,4.21000000,21.68000000,11.89000000,12.24000000,6.47000000,28.07000000,16.60000000,13.95000000,7.05000000,9.37000000,5.53000000,18.15000000,11.62000000,39.72000000,19.87000000,20.78000000,9.56000000,91.12000000,43.86000000,17.86000000,7.84000000,5.47000000,3.40000000,4.83000000,3.38000000,7.61000000,5.15000000,4.65000000,2.86000000,1.33000000,0.88000000,16.06000000,11.46000000,11.94000000,6.47000000,25.92000000,12.83000000,4.35000000,2.44000000 +Sampling Period[s],0.1 +StimType,STIM +Stim Time[s] +A,15,B,15,C,15,D,15,E,15,F,15,G,15,H,15,I,15,J,15 +Repeat Count,20 +Exception Ch,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + + + + + +Data +Probe1,CH1(703.6),CH1(829.0),CH2(703.9),CH2(829.3),CH3(703.9),CH3(829.3),CH4(703.9),CH4(828.8),CH5(703.9),CH5(828.8),CH6(703.1),CH6(828.8),CH7(703.1),CH7(828.8),CH8(702.9),CH8(829.0),CH9(702.9),CH9(829.0),CH10(703.6),CH10(829.0),CH11(703.6),CH11(829.0),CH12(703.4),CH12(829.0),CH13(703.9),CH13(829.3),CH14(703.6),CH14(828.5),CH15(703.9),CH15(828.8),CH16(704.1),CH16(829.8),CH17(703.1),CH17(828.8),CH18(704.4),CH18(829.0),CH19(702.9),CH19(829.0),CH20(703.9),CH20(828.8),CH21(703.6),CH21(829.0),CH22(703.4),CH22(829.0),CH23(703.4),CH23(829.0),CH24(703.6),CH24(828.5),CH25(703.6),CH25(828.5),CH26(704.1),CH26(829.8),CH27(704.1),CH27(829.8),CH28(704.4),CH28(829.0),CH29(704.4),CH29(829.0),CH30(703.9),CH30(828.8),CH31(703.9),CH31(828.8),CH32(704.1),CH32(828.8),CH33(703.4),CH33(829.0),CH34(703.1),CH34(828.8),CH35(703.6),CH35(828.5),CH36(704.4),CH36(828.8),CH37(704.1),CH37(829.8),CH38(703.6),CH38(828.5),CH39(704.4),CH39(829.0),CH40(703.9),CH40(829.0),CH41(703.9),CH41(828.8),CH42(704.4),CH42(829.0),CH43(704.1),CH43(828.8),CH44(703.1),CH44(828.8),CH45(703.1),CH45(828.8),CH46(704.4),CH46(828.8),CH47(704.4),CH47(828.8),CH48(703.6),CH48(828.5),CH49(703.6),CH49(828.5),CH50(703.9),CH50(829.0),CH51(703.9),CH51(829.0),CH52(704.4),CH52(829.0),Mark,Time,BodyMovement,RemovalMark,PreScan +1,2.01614380,2.01263428,2.01354980,2.01248169,2.02392578,2.01644897,2.02453613,2.01934814,2.01873779,2.01919556,2.02087402,2.01889038,2.02621460,2.03781128,2.02423096,2.02011108,2.00881958,2.00637817,2.02087402,2.01644897,2.02209473,2.00988770,2.03155518,2.01919556,2.02148438,2.01370239,2.01324463,2.00973511,2.00973511,2.01477051,2.02117920,2.02636719,2.00805664,2.01583862,2.02529907,2.03033447,2.00424194,1.99935913,2.01202393,2.01568604,2.01583862,2.01095581,2.02545166,2.01721191,2.02758789,2.02957153,2.00622559,2.00073242,2.00759888,2.00485229,2.02041626,2.03094482,2.01782227,2.01675415,2.00820923,2.01110840,2.01354980,2.00637817,2.01538086,2.00271606,2.01156616,2.01217651,2.01736450,1.99386597,2.03353882,2.02362061,2.03598022,2.02728271,2.00866699,1.99676514,2.00714111,2.00744629,2.02087402,2.01492310,2.01202393,2.01644897,2.00057983,1.99584961,2.01370239,1.99050903,1.99783325,1.99371338,2.01431274,1.99920654,1.99630737,1.97814941,2.02545166,2.01126099,2.02102661,2.00790405,2.00912476,1.99813843,2.01156616,1.99981689,1.99829102,1.99523926,2.01141357,2.00424194,2.00164795,1.98730469,2.03948975,2.00637817,2.00958252,1.99615479,0,15:40:49.15,0,0,1 +2,2.02087402,2.02194214,2.01782227,2.02026367,2.02743530,2.02453613,2.02789307,2.02758789,2.02255249,2.02880859,2.02819824,2.02880859,2.03445435,2.04879761,2.02850342,2.02865601,2.01583862,2.01477051,2.02529907,2.02499390,2.03033447,2.02178955,2.03308105,2.02636719,2.02545166,2.02224731,2.01690674,2.01751709,2.01522827,2.02423096,2.02590942,2.03536987,2.01507568,2.02850342,2.03033447,2.04040527,2.00729370,2.00546265,2.01431274,2.02407837,2.02224731,2.02346802,2.02972412,2.02682495,2.03186035,2.03720093,2.01171875,2.00851440,2.00897217,2.01370239,2.02468872,2.04177856,2.02224731,2.02606201,2.01339722,2.02499390,2.01766968,2.01583862,2.01690674,2.00851440,2.01568604,2.02117920,2.02087402,2.00164795,2.03689575,2.03247070,2.04132080,2.03613281,2.01110840,2.00332642,2.01293945,2.01583862,2.02560425,2.02224731,2.01828003,2.02621460,2.00637817,2.00607300,2.01431274,1.99890137,2.00714111,1.99813843,2.01721191,2.00942993,1.99874878,1.98593140,2.02941895,2.02087402,2.02743530,2.01690674,2.01263428,2.00668335,2.01690674,2.00592041,2.00210571,2.00210571,2.01568604,2.01110840,2.00378418,1.99447632,2.04177856,2.01278687,2.01217651,2.00210571,0,15:40:49.26,0,0,1 +3,2.01614380,2.01263428,2.01354980,2.01248169,2.02392578,2.01644897,2.02453613,2.01934814,2.01873779,2.01919556,2.02087402,2.01889038,2.02621460,2.03781128,2.02423096,2.02011108,2.00881958,2.00637817,2.02087402,2.01644897,2.02209473,2.00988770,2.03155518,2.01919556,2.02148438,2.01370239,2.01324463,2.00973511,2.00973511,2.01477051,2.02117920,2.02636719,2.00805664,2.01583862,2.02529907,2.03033447,2.00424194,1.99935913,2.01202393,2.01568604,2.01583862,2.01095581,2.02545166,2.01721191,2.02758789,2.02957153,2.00622559,2.00073242,2.00759888,2.00485229,2.02041626,2.03094482,2.01782227,2.01675415,2.00820923,2.01110840,2.01354980,2.00637817,2.01538086,2.00271606,2.01156616,2.01217651,2.01736450,1.99386597,2.03353882,2.02362061,2.03598022,2.02728271,2.00866699,1.99676514,2.00714111,2.00744629,2.02087402,2.01492310,2.01202393,2.01644897,2.00057983,1.99584961,2.01370239,1.99050903,1.99783325,1.99371338,2.01431274,1.99920654,1.99630737,1.97814941,2.02545166,2.01126099,2.02102661,2.00790405,2.00912476,1.99813843,2.01156616,1.99981689,1.99829102,1.99523926,2.01141357,2.00424194,2.00164795,1.98730469,2.03948975,2.00637817,2.00958252,1.99615479,0,15:40:49.15,0,0,1 +4,2.02087402,2.02194214,2.01782227,2.02026367,2.02743530,2.02453613,2.02789307,2.02758789,2.02255249,2.02880859,2.02819824,2.02880859,2.03445435,2.04879761,2.02850342,2.02865601,2.01583862,2.01477051,2.02529907,2.02499390,2.03033447,2.02178955,2.03308105,2.02636719,2.02545166,2.02224731,2.01690674,2.01751709,2.01522827,2.02423096,2.02590942,2.03536987,2.01507568,2.02850342,2.03033447,2.04040527,2.00729370,2.00546265,2.01431274,2.02407837,2.02224731,2.02346802,2.02972412,2.02682495,2.03186035,2.03720093,2.01171875,2.00851440,2.00897217,2.01370239,2.02468872,2.04177856,2.02224731,2.02606201,2.01339722,2.02499390,2.01766968,2.01583862,2.01690674,2.00851440,2.01568604,2.02117920,2.02087402,2.00164795,2.03689575,2.03247070,2.04132080,2.03613281,2.01110840,2.00332642,2.01293945,2.01583862,2.02560425,2.02224731,2.01828003,2.02621460,2.00637817,2.00607300,2.01431274,1.99890137,2.00714111,1.99813843,2.01721191,2.00942993,1.99874878,1.98593140,2.02941895,2.02087402,2.02743530,2.01690674,2.01263428,2.00668335,2.01690674,2.00592041,2.00210571,2.00210571,2.01568604,2.01110840,2.00378418,1.99447632,2.04177856,2.01278687,2.01217651,2.00210571,0,15:40:49.26,0,0,1 +5,2.01614380,2.01263428,2.01354980,2.01248169,2.02392578,2.01644897,2.02453613,2.01934814,2.01873779,2.01919556,2.02087402,2.01889038,2.02621460,2.03781128,2.02423096,2.02011108,2.00881958,2.00637817,2.02087402,2.01644897,2.02209473,2.00988770,2.03155518,2.01919556,2.02148438,2.01370239,2.01324463,2.00973511,2.00973511,2.01477051,2.02117920,2.02636719,2.00805664,2.01583862,2.02529907,2.03033447,2.00424194,1.99935913,2.01202393,2.01568604,2.01583862,2.01095581,2.02545166,2.01721191,2.02758789,2.02957153,2.00622559,2.00073242,2.00759888,2.00485229,2.02041626,2.03094482,2.01782227,2.01675415,2.00820923,2.01110840,2.01354980,2.00637817,2.01538086,2.00271606,2.01156616,2.01217651,2.01736450,1.99386597,2.03353882,2.02362061,2.03598022,2.02728271,2.00866699,1.99676514,2.00714111,2.00744629,2.02087402,2.01492310,2.01202393,2.01644897,2.00057983,1.99584961,2.01370239,1.99050903,1.99783325,1.99371338,2.01431274,1.99920654,1.99630737,1.97814941,2.02545166,2.01126099,2.02102661,2.00790405,2.00912476,1.99813843,2.01156616,1.99981689,1.99829102,1.99523926,2.01141357,2.00424194,2.00164795,1.98730469,2.03948975,2.00637817,2.00958252,1.99615479,0,15:40:49.15,0,0,1 +6,2.02087402,2.02194214,2.01782227,2.02026367,2.02743530,2.02453613,2.02789307,2.02758789,2.02255249,2.02880859,2.02819824,2.02880859,2.03445435,2.04879761,2.02850342,2.02865601,2.01583862,2.01477051,2.02529907,2.02499390,2.03033447,2.02178955,2.03308105,2.02636719,2.02545166,2.02224731,2.01690674,2.01751709,2.01522827,2.02423096,2.02590942,2.03536987,2.01507568,2.02850342,2.03033447,2.04040527,2.00729370,2.00546265,2.01431274,2.02407837,2.02224731,2.02346802,2.02972412,2.02682495,2.03186035,2.03720093,2.01171875,2.00851440,2.00897217,2.01370239,2.02468872,2.04177856,2.02224731,2.02606201,2.01339722,2.02499390,2.01766968,2.01583862,2.01690674,2.00851440,2.01568604,2.02117920,2.02087402,2.00164795,2.03689575,2.03247070,2.04132080,2.03613281,2.01110840,2.00332642,2.01293945,2.01583862,2.02560425,2.02224731,2.01828003,2.02621460,2.00637817,2.00607300,2.01431274,1.99890137,2.00714111,1.99813843,2.01721191,2.00942993,1.99874878,1.98593140,2.02941895,2.02087402,2.02743530,2.01690674,2.01263428,2.00668335,2.01690674,2.00592041,2.00210571,2.00210571,2.01568604,2.01110840,2.00378418,1.99447632,2.04177856,2.01278687,2.01217651,2.00210571,0,15:40:49.26,0,0,1 +7,2.01614380,2.01263428,2.01354980,2.01248169,2.02392578,2.01644897,2.02453613,2.01934814,2.01873779,2.01919556,2.02087402,2.01889038,2.02621460,2.03781128,2.02423096,2.02011108,2.00881958,2.00637817,2.02087402,2.01644897,2.02209473,2.00988770,2.03155518,2.01919556,2.02148438,2.01370239,2.01324463,2.00973511,2.00973511,2.01477051,2.02117920,2.02636719,2.00805664,2.01583862,2.02529907,2.03033447,2.00424194,1.99935913,2.01202393,2.01568604,2.01583862,2.01095581,2.02545166,2.01721191,2.02758789,2.02957153,2.00622559,2.00073242,2.00759888,2.00485229,2.02041626,2.03094482,2.01782227,2.01675415,2.00820923,2.01110840,2.01354980,2.00637817,2.01538086,2.00271606,2.01156616,2.01217651,2.01736450,1.99386597,2.03353882,2.02362061,2.03598022,2.02728271,2.00866699,1.99676514,2.00714111,2.00744629,2.02087402,2.01492310,2.01202393,2.01644897,2.00057983,1.99584961,2.01370239,1.99050903,1.99783325,1.99371338,2.01431274,1.99920654,1.99630737,1.97814941,2.02545166,2.01126099,2.02102661,2.00790405,2.00912476,1.99813843,2.01156616,1.99981689,1.99829102,1.99523926,2.01141357,2.00424194,2.00164795,1.98730469,2.03948975,2.00637817,2.00958252,1.99615479,0,15:40:49.15,0,0,1 +8,2.02087402,2.02194214,2.01782227,2.02026367,2.02743530,2.02453613,2.02789307,2.02758789,2.02255249,2.02880859,2.02819824,2.02880859,2.03445435,2.04879761,2.02850342,2.02865601,2.01583862,2.01477051,2.02529907,2.02499390,2.03033447,2.02178955,2.03308105,2.02636719,2.02545166,2.02224731,2.01690674,2.01751709,2.01522827,2.02423096,2.02590942,2.03536987,2.01507568,2.02850342,2.03033447,2.04040527,2.00729370,2.00546265,2.01431274,2.02407837,2.02224731,2.02346802,2.02972412,2.02682495,2.03186035,2.03720093,2.01171875,2.00851440,2.00897217,2.01370239,2.02468872,2.04177856,2.02224731,2.02606201,2.01339722,2.02499390,2.01766968,2.01583862,2.01690674,2.00851440,2.01568604,2.02117920,2.02087402,2.00164795,2.03689575,2.03247070,2.04132080,2.03613281,2.01110840,2.00332642,2.01293945,2.01583862,2.02560425,2.02224731,2.01828003,2.02621460,2.00637817,2.00607300,2.01431274,1.99890137,2.00714111,1.99813843,2.01721191,2.00942993,1.99874878,1.98593140,2.02941895,2.02087402,2.02743530,2.01690674,2.01263428,2.00668335,2.01690674,2.00592041,2.00210571,2.00210571,2.01568604,2.01110840,2.00378418,1.99447632,2.04177856,2.01278687,2.01217651,2.00210571,0,15:40:49.26,0,0,1 +9,2.01614380,2.01263428,2.01354980,2.01248169,2.02392578,2.01644897,2.02453613,2.01934814,2.01873779,2.01919556,2.02087402,2.01889038,2.02621460,2.03781128,2.02423096,2.02011108,2.00881958,2.00637817,2.02087402,2.01644897,2.02209473,2.00988770,2.03155518,2.01919556,2.02148438,2.01370239,2.01324463,2.00973511,2.00973511,2.01477051,2.02117920,2.02636719,2.00805664,2.01583862,2.02529907,2.03033447,2.00424194,1.99935913,2.01202393,2.01568604,2.01583862,2.01095581,2.02545166,2.01721191,2.02758789,2.02957153,2.00622559,2.00073242,2.00759888,2.00485229,2.02041626,2.03094482,2.01782227,2.01675415,2.00820923,2.01110840,2.01354980,2.00637817,2.01538086,2.00271606,2.01156616,2.01217651,2.01736450,1.99386597,2.03353882,2.02362061,2.03598022,2.02728271,2.00866699,1.99676514,2.00714111,2.00744629,2.02087402,2.01492310,2.01202393,2.01644897,2.00057983,1.99584961,2.01370239,1.99050903,1.99783325,1.99371338,2.01431274,1.99920654,1.99630737,1.97814941,2.02545166,2.01126099,2.02102661,2.00790405,2.00912476,1.99813843,2.01156616,1.99981689,1.99829102,1.99523926,2.01141357,2.00424194,2.00164795,1.98730469,2.03948975,2.00637817,2.00958252,1.99615479,0,15:40:49.15,0,0,1 +10,2.02087402,2.02194214,2.01782227,2.02026367,2.02743530,2.02453613,2.02789307,2.02758789,2.02255249,2.02880859,2.02819824,2.02880859,2.03445435,2.04879761,2.02850342,2.02865601,2.01583862,2.01477051,2.02529907,2.02499390,2.03033447,2.02178955,2.03308105,2.02636719,2.02545166,2.02224731,2.01690674,2.01751709,2.01522827,2.02423096,2.02590942,2.03536987,2.01507568,2.02850342,2.03033447,2.04040527,2.00729370,2.00546265,2.01431274,2.02407837,2.02224731,2.02346802,2.02972412,2.02682495,2.03186035,2.03720093,2.01171875,2.00851440,2.00897217,2.01370239,2.02468872,2.04177856,2.02224731,2.02606201,2.01339722,2.02499390,2.01766968,2.01583862,2.01690674,2.00851440,2.01568604,2.02117920,2.02087402,2.00164795,2.03689575,2.03247070,2.04132080,2.03613281,2.01110840,2.00332642,2.01293945,2.01583862,2.02560425,2.02224731,2.01828003,2.02621460,2.00637817,2.00607300,2.01431274,1.99890137,2.00714111,1.99813843,2.01721191,2.00942993,1.99874878,1.98593140,2.02941895,2.02087402,2.02743530,2.01690674,2.01263428,2.00668335,2.01690674,2.00592041,2.00210571,2.00210571,2.01568604,2.01110840,2.00378418,1.99447632,2.04177856,2.01278687,2.01217651,2.00210571,0,15:40:49.26,0,0,1 +""" # noqa: E501 + + +@pytest.mark.parametrize("preload", (True, False)) +@pytest.mark.parametrize( + "version, n_ch, n_times, lowpass, sex, date, end", + [ + ("1.18", 48, 60, 0.1, 2, (2004, 5, 17, 5, 14, 0, 0), None), + ("1.25", 108, 10, 5.0, 1, (2020, 2, 2, 11, 20, 0, 0), b"\r"), + ("1.25", 108, 10, 5.0, 1, (2020, 2, 2, 11, 20, 0, 0), b"\n"), + ("1.25", 108, 10, 5.0, 1, (2020, 2, 2, 11, 20, 0, 0), b"\r\n"), + # Fake a dual-probe file + (["1.18", "1.18"], 92, 60, 0.1, 2, (2004, 5, 17, 5, 14, 0, 0), None), + ], +) +def test_hitachi_basic( + preload, version, n_ch, n_times, lowpass, sex, date, end, tmp_path +): + """Test NIRSport1 file with no saturation.""" + if not isinstance(version, list): + versions = [version] + else: + versions = version + del version + fnames = list() + for vi, v in enumerate(versions, 1): + fname = tmp_path / f"test{vi}.csv" + contents = CONTENTS[v].replace(f"Probe{vi - 1}".encode(), f"Probe{vi}".encode()) + if end is not None: + contents = contents.replace(b"\r", b"\n").replace(b"\n\n", b"\n") + contents = contents.replace(b"\n", end) + with open(fname, "wb") as fid: + fid.write(CONTENTS[v]) + fnames.append(fname) + del fname + raw = read_raw_hitachi(fnames, preload=preload, verbose=True) + data = raw.get_data() + assert data.shape == (n_ch, n_times) + assert raw.info["sfreq"] == 10 + assert raw.info["lowpass"] == lowpass + assert raw.info["subject_info"]["sex"] == sex + assert np.isfinite(raw.get_data()).all() + assert raw.info["meas_date"] == dt.datetime(*date, tzinfo=dt.timezone.utc) + # bad distances (zero) + distances = source_detector_distances(raw.info) + want = [np.nan] * (n_ch - 4) + assert_allclose(distances, want, atol=0.0) + raw_od_bad = optical_density(raw) + with pytest.warns(RuntimeWarning, match="will be zero"): + beer_lambert_law(raw_od_bad, ppf=6) + # bad distances (too big) + if versions[0] == "1.18" and len(fnames) == 1: + need = sum(([f"S{ii}", f"D{ii}"] for ii in range(1, 9)), [])[:-1] + have = "P7 FC3 C3 CP3 P3 F5 FC5 C5 CP5 P5 F7 FT7 T7 TP7 F3".split() + assert len(need) == len(have) + mon = make_standard_montage("standard_1020") + mon.rename_channels(dict(zip(have, need))) + raw.set_montage(mon) + raw_od_bad = optical_density(raw) + with pytest.warns(RuntimeWarning, match="greater than 10 cm"): + beer_lambert_law(raw_od_bad, ppf=6) + # good distances + mon = make_standard_montage("standard_1020") + if versions[0] == "1.18": + assert len(fnames) in (1, 2) + need = sum(([f"S{ii}", f"D{ii}"] for ii in range(1, 9)), [])[:-1] + have = "F3 FC3 C3 CP3 P3 F5 FC5 C5 CP5 P5 F7 FT7 T7 TP7 P7".split() + assert len(need) == 15 + if len(fnames) == 2: + need.extend( + sum( + ( + [f"S{ii}", f"D{jj}"] + for ii, jj in zip(range(9, 17), range(8, 16)) + ), + [], + )[:-1] + ) + have.extend("F4 FC4 C4 CP4 P4 F6 FC6 C6 CP6 P6 F8 FT8 T8 TP8 P8".split()) + assert len(need) == 30 + else: + assert len(fnames) == 1 + need = sum(([f"S{ii}", f"D{ii}"] for ii in range(1, 18)), [])[:-1] + have = ( + "FT9 FT7 FC5 FC3 FC1 FCz FC2 FC4 FC6 FT8 FT10 " + "T9 T7 C5 C3 C1 Cz C2 C4 C6 T8 T10 " + "TP9 TP7 CP5 CP3 CP1 CPz CP2 CP4 CP6 TP8 TP10" + ).split() + assert len(need) == 33 + assert len(need) == len(have) + for h in have: + assert h in mon.ch_names + mon.rename_channels(dict(zip(have, need))) + for n in need: + assert n in mon.ch_names + raw.set_montage(mon) + distances = source_detector_distances(raw.info) + want = [0.03] * (n_ch - 4) + assert_allclose(distances, want, atol=0.01) + test_rank = "less" if n_times < n_ch else True + _test_raw_reader( + read_raw_hitachi, fname=fnames, boundary_decimal=1, test_rank=test_rank + ) # low fs + + # TODO: eventually we should refactor these to be in + # mne/io/tests/test_raw.py and run them for all fNIRS readers + + # OD + raw_od = optical_density(raw) + assert np.isfinite(raw_od.get_data()).all() + sci = scalp_coupling_index(raw_od, verbose="error") + lo, mi, hi = np.percentile(sci, [5, 50, 95]) + if versions[0] == "1.18": + assert -0.1 < lo < 0.1 # not great + assert 0.4 < mi < 0.5 + assert 0.8 < hi < 0.9 + else: + assert 0.99 <= lo <= hi <= 1 + # TDDR + raw_tddr = tddr(raw_od) + data = raw_tddr.get_data("fnirs") + assert np.isfinite(data.all()) + peaks = np.ptp(data, axis=-1) + assert_array_less(1e-4, peaks, err_msg="TDDR too small") + assert_array_less(peaks, 1, err_msg="TDDR too big") + # HbO/HbR + raw_tddr.set_montage(mon) + raw_h = beer_lambert_law(raw_tddr, ppf=6) + data = raw_h.get_data("fnirs") + assert np.isfinite(data).all() + assert data.shape == (n_ch - 4, n_times) + peaks = np.ptp(data, axis=-1) + assert_array_less(1e-10, peaks, err_msg="Beer-Lambert too small") + assert_array_less(peaks, 1e-5, err_msg="Beer-Lambert too big") + + +# From Hitachi 2 Homer +KNOWN_PAIRS = { + (3, 3, 2): ( + (0, 0), + (1, 0), + (0, 1), + (2, 0), + (1, 2), + (2, 1), + (2, 2), + (3, 1), + (2, 3), + (4, 2), + (3, 3), + (4, 3), + (5, 4), + (6, 4), + (5, 5), + (7, 4), + (6, 6), + (7, 5), + (7, 6), + (8, 5), + (7, 7), + (9, 6), + (8, 7), + (9, 7), + ), + (3, 5, 1): ( + (0, 0), + (1, 0), + (1, 1), + (2, 1), + (0, 2), + (3, 0), + (1, 3), + (4, 1), + (2, 4), + (3, 2), + (3, 3), + (4, 3), + (4, 4), + (5, 2), + (3, 5), + (6, 3), + (4, 6), + (7, 4), + (5, 5), + (6, 5), + (6, 6), + (7, 6), + ), + (4, 4, 1): ( + (0, 0), + (1, 0), + (1, 1), + (0, 2), + (2, 0), + (1, 3), + (3, 1), + (2, 2), + (2, 3), + (3, 3), + (4, 2), + (2, 4), + (5, 3), + (3, 5), + (4, 4), + (5, 4), + (5, 5), + (4, 6), + (6, 4), + (5, 7), + (7, 5), + (6, 6), + (6, 7), + (7, 7), + ), + (3, 11, 1): ( + (0, 0), + (1, 0), + (1, 1), + (2, 1), + (2, 2), + (3, 2), + (3, 3), + (4, 3), + (4, 4), + (5, 4), + (0, 5), + (6, 0), + (1, 6), + (7, 1), + (2, 7), + (8, 2), + (3, 8), + (9, 3), + (4, 9), + (10, 4), + (5, 10), + (6, 5), + (6, 6), + (7, 6), + (7, 7), + (8, 7), + (8, 8), + (9, 8), + (9, 9), + (10, 9), + (10, 10), + (11, 5), + (6, 11), + (12, 6), + (7, 12), + (13, 7), + (8, 13), + (14, 8), + (9, 14), + (15, 9), + (10, 15), + (16, 10), + (11, 11), + (12, 11), + (12, 12), + (13, 12), + (13, 13), + (14, 13), + (14, 14), + (15, 14), + (15, 15), + (16, 15), + ), +} + + +@pytest.mark.parametrize("n_rows, n_cols, n", list(KNOWN_PAIRS)) +def test_compute_pairs(n_rows, n_cols, n): + """Test computation of S-D pairings.""" + want = KNOWN_PAIRS[(n_rows, n_cols, n)] + got = _compute_pairs(n_rows, n_cols, n) + assert got == want diff --git a/mne-python/source/mne/io/kit/__init__.py b/mne-python/source/mne/io/kit/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c522113f64e40587145aea15c26afae6a147563a --- /dev/null +++ b/mne-python/source/mne/io/kit/__init__.py @@ -0,0 +1,8 @@ +"""KIT module for reading raw data.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .kit import read_raw_kit, read_epochs_kit +from .coreg import read_mrk diff --git a/mne-python/source/mne/io/kit/constants.py b/mne-python/source/mne/io/kit/constants.py new file mode 100644 index 0000000000000000000000000000000000000000..7831e81c6fa391ddb41434164a3816e2e81e56cb --- /dev/null +++ b/mne-python/source/mne/io/kit/constants.py @@ -0,0 +1,259 @@ +"""KIT constants.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ..._fiff.constants import FIFF +from ...utils import BunchConst + + +KIT = BunchConst() + +# byte values +KIT.SHORT = 2 +KIT.INT = 4 +KIT.DOUBLE = 8 + +# channel parameters +KIT.CALIB_FACTOR = 1.0 # mne_manual p.272 +KIT.RANGE = 1.0 # mne_manual p.272 +KIT.UNIT_MUL = FIFF.FIFF_UNITM_NONE # default is 0 mne_manual p.273 +KIT.GAINS = [1, 2, 5, 10, 20, 50, 100, 200] + +KIT.HPFS = { + 1: (0, 1, 3, 3), + 2: (0, 0.03, 0.1, 0.3, 1, 3, 10, 30), + 3: (0, 0.03, 0.1, 0.3, 1, 3, 10, 30), + 4: (0, 1, 3, 10, 30, 100, 200, 500), +} +KIT.LPFS = { + 1: (10, 20, 50, 100, 200, 500, 1000, 2000), + 2: (10, 20, 50, 100, 200, 500, 1000, 2000), + 3: (10, 20, 50, 100, 200, 500, 1000, 10000), + 4: (10, 30, 100, 300, 1000, 2000, 5000, 10000), +} +KIT.BEFS = { + 1: (0, 50, 60, 60), + 2: (0, 0, 0), + 3: (0, 60, 50, 50), +} + +# Map FLL-Type to filter options (high, low, band) +KIT.FLL_SETTINGS = { + 0: (1, 1, 1), # Hanger Type #1 + 10: (1, 1, 1), # Hanger Type #2 + 20: (1, 1, 1), # Hanger Type #2 + 50: (2, 1, 1), # Hanger Type #3 + 60: (2, 1, 1), # Hanger Type #3 + 100: (3, 3, 3), # Low Band Kapper Type + 101: (1, 3, 2), # Berlin (DC, 200 Hz, Through) + 120: (3, 3, 3), # Low Band Kapper Type + 200: (4, 4, 3), # High Band Kapper Type + 300: (2, 2, 2), # Kapper Type +} + +# channel types +KIT.CHANNEL_MAGNETOMETER = 1 +KIT.CHANNEL_MAGNETOMETER_REFERENCE = 0x101 +KIT.CHANNEL_AXIAL_GRADIOMETER = 2 +KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE = 0x102 +KIT.CHANNEL_PLANAR_GRADIOMETER = 3 +KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE = 0x103 +KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER = 4 +KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE = 0x104 +KIT.CHANNEL_TRIGGER = -1 +KIT.CHANNEL_EEG = -2 +KIT.CHANNEL_ECG = -3 +KIT.CHANNEL_ETC = -4 +KIT.CHANNEL_NULL = 0 +KIT.CHANNELS_MEG = ( + KIT.CHANNEL_MAGNETOMETER, + KIT.CHANNEL_MAGNETOMETER_REFERENCE, + KIT.CHANNEL_AXIAL_GRADIOMETER, + KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE, + KIT.CHANNEL_PLANAR_GRADIOMETER, + KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE, + KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER, + KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE, +) +KIT.CHANNELS_REFERENCE = ( + KIT.CHANNEL_MAGNETOMETER_REFERENCE, + KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE, + KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE, + KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE, +) +KIT.CHANNELS_MISC = ( + KIT.CHANNEL_TRIGGER, + KIT.CHANNEL_EEG, + KIT.CHANNEL_ECG, + KIT.CHANNEL_ETC, +) +KIT.CHANNEL_NAME_NCHAR = { + KIT.CHANNEL_MAGNETOMETER: 6, + KIT.CHANNEL_AXIAL_GRADIOMETER: 6, + KIT.CHANNEL_TRIGGER: 32, + KIT.CHANNEL_EEG: 8, + KIT.CHANNEL_ECG: 32, + KIT.CHANNEL_ETC: 32, +} +KIT.CH_TO_FIFF_COIL = { + # KIT.CHANNEL_MAGNETOMETER: FIFF.???, + KIT.CHANNEL_MAGNETOMETER_REFERENCE: FIFF.FIFFV_COIL_KIT_REF_MAG, + KIT.CHANNEL_AXIAL_GRADIOMETER: FIFF.FIFFV_COIL_KIT_GRAD, + # KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE: FIFF.???, + # KIT.CHANNEL_PLANAR_GRADIOMETER: FIFF.???, + # KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE: FIFF.???, + # KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER: FIFF.???, + # KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE: FIFF.???, + KIT.CHANNEL_TRIGGER: FIFF.FIFFV_COIL_NONE, + KIT.CHANNEL_EEG: FIFF.FIFFV_COIL_EEG, + KIT.CHANNEL_ECG: FIFF.FIFFV_COIL_NONE, + KIT.CHANNEL_ETC: FIFF.FIFFV_COIL_NONE, + KIT.CHANNEL_NULL: FIFF.FIFFV_COIL_NONE, +} +KIT.CH_TO_FIFF_KIND = { + KIT.CHANNEL_MAGNETOMETER: FIFF.FIFFV_MEG_CH, + KIT.CHANNEL_MAGNETOMETER_REFERENCE: FIFF.FIFFV_REF_MEG_CH, + KIT.CHANNEL_AXIAL_GRADIOMETER: FIFF.FIFFV_MEG_CH, + KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE: FIFF.FIFFV_REF_MEG_CH, + KIT.CHANNEL_PLANAR_GRADIOMETER: FIFF.FIFFV_MEG_CH, + KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE: FIFF.FIFFV_REF_MEG_CH, + KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER: FIFF.FIFFV_MEG_CH, + KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE: FIFF.FIFFV_REF_MEG_CH, + KIT.CHANNEL_TRIGGER: FIFF.FIFFV_MISC_CH, + KIT.CHANNEL_EEG: FIFF.FIFFV_EEG_CH, + KIT.CHANNEL_ECG: FIFF.FIFFV_ECG_CH, + KIT.CHANNEL_ETC: FIFF.FIFFV_MISC_CH, + KIT.CHANNEL_NULL: FIFF.FIFFV_MISC_CH, +} +KIT.CH_LABEL = { + KIT.CHANNEL_TRIGGER: "TRIGGER", + KIT.CHANNEL_EEG: "EEG", + KIT.CHANNEL_ECG: "ECG", + KIT.CHANNEL_ETC: "MISC", + KIT.CHANNEL_NULL: "MISC", +} + +# Acquisition modes +KIT.CONTINUOUS = 1 +KIT.EVOKED = 2 +KIT.EPOCHS = 3 + +# coreg constants +KIT.DIG_POINTS = 10000 + +# Known KIT systems +# ----------------- +# KIT recording system is encoded in the SQD file as integer: +KIT.SYSTEM_MQ_ADULT = 345 # Macquarie Dept of Cognitive Science, 2006 - +KIT.SYSTEM_MQ_CHILD = 403 # Macquarie Dept of Cognitive Science, 2006 - +KIT.SYSTEM_AS = 260 # Academia Sinica at Taiwan +KIT.SYSTEM_AS_2008 = 261 # Academia Sinica, 2008 or 2009 - +KIT.SYSTEM_NYU_2008 = 32 # NYU-NY, July 7, 2008 - +KIT.SYSTEM_NYU_2009 = 33 # NYU-NY, January 24, 2009 - +KIT.SYSTEM_NYU_2010 = 34 # NYU-NY, January 22, 2010 - +KIT.SYSTEM_NYU_2019 = 35 # NYU-NY, September 18, 2019 - +KIT.SYSTEM_NYUAD_2011 = 440 # NYU-AD initial launch May 20, 2011 - +KIT.SYSTEM_NYUAD_2012 = 441 # NYU-AD more channels July 11, 2012 - +KIT.SYSTEM_NYUAD_2014 = 442 # NYU-AD move to NYUAD campus Nov 20, 2014 - +KIT.SYSTEM_UMD_2004 = 51 # UMD Marie Mount Hall, October 1, 2004 - +KIT.SYSTEM_UMD_2014_07 = 52 # UMD update to 16 bit ADC, July 4, 2014 - +KIT.SYSTEM_UMD_2014_12 = 53 # UMD December 4, 2014 - +KIT.SYSTEM_UMD_2019_09 = 54 # UMD September 3, 2019 - +KIT.SYSTEM_YOKOGAWA_2017_01 = 1001 # Kanazawa (until 2017) +KIT.SYSTEM_YOKOGAWA_2018_01 = 10020 # Kanazawa (since 2018) +KIT.SYSTEM_YOKOGAWA_2020_08 = 10021 # Kanazawa (since August 2020) +KIT.SYSTEM_EAGLE_TECHNOLOGY_PTB_2008 = 124 + +# Sensor layouts for plotting +KIT_LAYOUT = { + KIT.SYSTEM_AS: None, + KIT.SYSTEM_AS_2008: "KIT-AS-2008", + KIT.SYSTEM_MQ_ADULT: "KIT-160", + KIT.SYSTEM_MQ_CHILD: "KIT-125", + KIT.SYSTEM_NYU_2008: "KIT-157", + KIT.SYSTEM_NYU_2009: "KIT-157", + KIT.SYSTEM_NYU_2010: "KIT-157", + KIT.SYSTEM_NYU_2019: None, + KIT.SYSTEM_NYUAD_2011: "KIT-AD", + KIT.SYSTEM_NYUAD_2012: "KIT-AD", + KIT.SYSTEM_NYUAD_2014: "KIT-AD", + KIT.SYSTEM_UMD_2004: None, + KIT.SYSTEM_UMD_2014_07: None, + KIT.SYSTEM_UMD_2014_12: "KIT-UMD-3", + KIT.SYSTEM_UMD_2019_09: None, + KIT.SYSTEM_YOKOGAWA_2017_01: None, + KIT.SYSTEM_YOKOGAWA_2018_01: None, + KIT.SYSTEM_YOKOGAWA_2020_08: None, + KIT.SYSTEM_EAGLE_TECHNOLOGY_PTB_2008: None, +} +# Sensor neighbor definitions +KIT_NEIGHBORS = { + KIT.SYSTEM_AS: None, + KIT.SYSTEM_AS_2008: None, + KIT.SYSTEM_MQ_ADULT: None, + KIT.SYSTEM_MQ_CHILD: None, + KIT.SYSTEM_NYU_2008: "KIT-157", + KIT.SYSTEM_NYU_2009: "KIT-157", + KIT.SYSTEM_NYU_2010: "KIT-157", + KIT.SYSTEM_NYU_2019: "KIT-NYU-2019", + KIT.SYSTEM_NYUAD_2011: "KIT-208", + KIT.SYSTEM_NYUAD_2012: "KIT-208", + KIT.SYSTEM_NYUAD_2014: "KIT-208", + KIT.SYSTEM_UMD_2004: "KIT-UMD-1", + KIT.SYSTEM_UMD_2014_07: "KIT-UMD-2", + KIT.SYSTEM_UMD_2014_12: "KIT-UMD-3", + KIT.SYSTEM_UMD_2019_09: "KIT-UMD-4", + KIT.SYSTEM_YOKOGAWA_2017_01: None, + KIT.SYSTEM_YOKOGAWA_2018_01: None, + KIT.SYSTEM_YOKOGAWA_2020_08: None, + KIT.SYSTEM_EAGLE_TECHNOLOGY_PTB_2008: None, +} +# Names displayed in the info dict description +KIT_SYSNAMES = { + KIT.SYSTEM_MQ_ADULT: "Macquarie Dept of Cognitive Science (Adult), 2006-", + KIT.SYSTEM_MQ_CHILD: "Macquarie Dept of Cognitive Science (Child), 2006-", + KIT.SYSTEM_AS: "Academia Sinica, -2008", + KIT.SYSTEM_AS_2008: "Academia Sinica, 2008-", + KIT.SYSTEM_NYU_2008: "NYU New York, 2008-9", + KIT.SYSTEM_NYU_2009: "NYU New York, 2009-10", + KIT.SYSTEM_NYU_2010: "NYU New York, 2010-", + KIT.SYSTEM_NYUAD_2011: "New York University Abu Dhabi, 2011-12", + KIT.SYSTEM_NYUAD_2012: "New York University Abu Dhabi, 2012-14", + KIT.SYSTEM_NYUAD_2014: "New York University Abu Dhabi, 2014-", + KIT.SYSTEM_UMD_2004: "University of Maryland, 2004-14", + KIT.SYSTEM_UMD_2014_07: "University of Maryland, 2014", + KIT.SYSTEM_UMD_2014_12: "University of Maryland, 2014-", + KIT.SYSTEM_UMD_2019_09: "University of Maryland, 2019-", + KIT.SYSTEM_YOKOGAWA_2017_01: "Yokogawa of Kanazawa (until 2017)", + KIT.SYSTEM_YOKOGAWA_2018_01: "Yokogawa of Kanazawa (since 2018)", + KIT.SYSTEM_YOKOGAWA_2020_08: "Yokogawa of Kanazawa (since August 2020)", + KIT.SYSTEM_EAGLE_TECHNOLOGY_PTB_2008: "Eagle Technology MEG (KIT/Yokogawa style) at PTB (since 2008, software upgrade in 2018)", # noqa: E501 +} + +LEGACY_AMP_PARAMS = { + KIT.SYSTEM_NYU_2008: (5.0, 11.0), + KIT.SYSTEM_NYU_2009: (5.0, 11.0), + KIT.SYSTEM_NYU_2010: (5.0, 11.0), + KIT.SYSTEM_UMD_2004: (5.0, 11.0), +} + +# Ones that we don't use are commented out +KIT.DIR_INDEX_DIR = 0 +KIT.DIR_INDEX_SYSTEM = 1 +KIT.DIR_INDEX_CHANNELS = 4 +KIT.DIR_INDEX_CALIBRATION = 5 +# FLL = 6 +KIT.DIR_INDEX_AMP_FILTER = 7 +KIT.DIR_INDEX_ACQ_COND = 8 +KIT.DIR_INDEX_RAW_DATA = 9 +# AVERAGED_DATA = 10 +# MRI = 11 +KIT.DIR_INDEX_COREG = 12 +# MAGNETIC_SOURCE = 13 +# TRIGGER = 14 +# BOOKMARKS = 15 +# DIGITIZER = 25 +KIT.DIR_INDEX_DIG_POINTS = 26 +KIT.DIR_INDEX_CHPI_DATA = 29 diff --git a/mne-python/source/mne/io/kit/coreg.py b/mne-python/source/mne/io/kit/coreg.py new file mode 100644 index 0000000000000000000000000000000000000000..8e6698d6f78f88eefe6f1a9eebd3b861d252b0d2 --- /dev/null +++ b/mne-python/source/mne/io/kit/coreg.py @@ -0,0 +1,233 @@ +"""Coordinate Point Extractor for KIT system.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import re +from collections import OrderedDict +from os import SEEK_CUR, PathLike +from pathlib import Path + +import numpy as np + +from ..._fiff._digitization import _make_dig_points +from ...channels.montage import ( + _check_dig_shape, + read_custom_montage, + read_dig_polhemus_isotrak, + read_polhemus_fastscan, +) +from ...transforms import ( + Transform, + als_ras_trans, + apply_trans, + get_ras_to_neuromag_trans, +) +from ...utils import _check_fname, _check_option, warn +from .constants import FIFF, KIT + +INT32 = " KIT.DIG_POINTS: + hsp = _decimate_points(hsp, res=0.005) + n_new = len(hsp) + warn( + f"The selected head shape contained {n_pts} points, which is more than " + f"recommended ({KIT.DIG_POINTS}), and was automatically downsampled to " + f"{n_new} points. The preferred way to downsample is using FastScan." + ) + + if isinstance(elp, str | Path | PathLike): + elp_points = _read_dig_kit(elp) + if len(elp_points) != 8: + raise ValueError( + f"File {repr(elp)} should contain 8 points; got shape " + f"{elp_points.shape}." + ) + elp = elp_points + if len(bad_coils) > 0: + elp = np.delete(elp, np.array(bad_coils) + 3, 0) + # check we have at least 3 marker coils (whether read from file or + # passed in directly) + if len(elp) not in (6, 7, 8): + raise ValueError(f"ELP should contain 6 ~ 8 points; got shape {elp.shape}.") + if isinstance(mrk, str | Path | PathLike): + mrk = read_mrk(mrk) + if len(bad_coils) > 0: + mrk = np.delete(mrk, bad_coils, 0) + if len(mrk) not in (3, 4, 5): + raise ValueError(f"MRK should contain 3 ~ 5 points; got shape {mrk.shape}.") + + mrk = apply_trans(als_ras_trans, mrk) + + nasion, lpa, rpa = elp[:3] + nmtrans = get_ras_to_neuromag_trans(nasion, lpa, rpa) + elp = apply_trans(nmtrans, elp) + hsp = apply_trans(nmtrans, hsp) + eeg = OrderedDict((k, apply_trans(nmtrans, p)) for k, p in eeg.items()) + + # device head transform + trans = fit_matched_points(tgt_pts=elp[3:], src_pts=mrk, out="trans") + + nasion, lpa, rpa = elp[:3] + elp = elp[3:] + + dig_points = _make_dig_points(nasion, lpa, rpa, elp, hsp, dig_ch_pos=eeg) + dev_head_t = Transform("meg", "head", trans) + + hpi_results = [ + dict( + dig_points=[ + dict( + ident=ci, + r=r, + kind=FIFF.FIFFV_POINT_HPI, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + ) + for ci, r in enumerate(mrk) + ], + coord_trans=dev_head_t, + ) + ] + + return dig_points, dev_head_t, hpi_results + + +def _read_dig_kit(fname, unit="auto"): + # Read dig points from a file and return ndarray, using FastSCAN for .txt + fname = _check_fname(fname, "read", must_exist=True, name="hsp or elp file") + assert unit in ("auto", "m", "mm") + _check_option("file extension", fname.suffix, (".hsp", ".elp", ".mat", ".txt")) + if fname.suffix == ".txt": + unit = "mm" if unit == "auto" else unit + out = read_polhemus_fastscan(fname, unit=unit, on_header_missing="ignore") + elif fname.suffix in (".hsp", ".elp"): + unit = "m" if unit == "auto" else unit + mon = read_dig_polhemus_isotrak(fname, unit=unit) + if fname.suffix == ".hsp": + dig = [d["r"] for d in mon.dig if d["kind"] != FIFF.FIFFV_POINT_CARDINAL] + else: + dig = [d["r"] for d in mon.dig] + if ( + dig + and mon.dig[0]["kind"] == FIFF.FIFFV_POINT_CARDINAL + and mon.dig[0]["ident"] == FIFF.FIFFV_POINT_LPA + ): + # LPA, Nasion, RPA -> NLR + dig[:3] = [dig[1], dig[0], dig[2]] + out = np.array(dig, float) + else: + assert fname.suffix == ".mat" + out = np.array([d["r"] for d in read_custom_montage(fname).dig]) + _check_dig_shape(out) + return out diff --git a/mne-python/source/mne/io/kit/kit.py b/mne-python/source/mne/io/kit/kit.py new file mode 100644 index 0000000000000000000000000000000000000000..53006dba43d8d766c879179ac82638eabae9f93c --- /dev/null +++ b/mne-python/source/mne/io/kit/kit.py @@ -0,0 +1,1046 @@ +"""Conversion tool from SQD to FIF. + +RawKIT class is adapted from Denis Engemann et al.'s mne_bti2fiff.py. +""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from collections import OrderedDict, defaultdict +from math import cos, sin +from os import SEEK_CUR, PathLike +from os import path as op +from pathlib import Path + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info +from ..._fiff.pick import pick_types +from ..._fiff.utils import _mult_cal_one +from ...epochs import BaseEpochs +from ...event import read_events +from ...fixes import _reshape_view +from ...transforms import Transform, als_ras_trans, apply_trans +from ...utils import ( + _check_fname, + _check_option, + _stamp_to_dt, + fill_doc, + logger, + verbose, + warn, +) +from ..base import BaseRaw +from .constants import KIT, LEGACY_AMP_PARAMS +from .coreg import _set_dig_kit, read_mrk + +FLOAT64 = "' + Can be submitted as list of trigger channels. + If a list is not specified, the default triggers extracted from + misc channels will be used with specified directionality. + '<' means that largest values assigned to the first channel + in sequence. + '>' means the largest trigger assigned to the last channel + in sequence. + stim_code : 'binary' | 'channel' + How to decode trigger values from stim channels. 'binary' read stim + channel events as binary code, 'channel' encodes channel number. + """ + if inst.preload: + raise NotImplementedError("Can't change stim channel after loading data") + _check_option("stim_code", stim_code, ["binary", "channel"]) + + if stim is not None: + if isinstance(stim, str): + picks = _default_stim_chs(info) + if stim == "<": + stim = picks[::-1] + elif stim == ">": + stim = picks + else: + raise ValueError( + f"stim needs to be list of int, '>' or '<', not {str(stim)!r}" + ) + else: + stim = np.asarray(stim, int) + if stim.max() >= inst._raw_extras[0]["nchan"]: + raise ValueError( + f"Got stim={stim}, but sqd file only has " + f"{inst._raw_extras[0]['nchan']} channels." + ) + + # modify info + nchan = inst._raw_extras[0]["nchan"] + 1 + info["chs"].append( + dict( + cal=KIT.CALIB_FACTOR, + logno=nchan, + scanno=nchan, + range=1.0, + unit=FIFF.FIFF_UNIT_NONE, + unit_mul=FIFF.FIFF_UNITM_NONE, + ch_name="STI 014", + coil_type=FIFF.FIFFV_COIL_NONE, + loc=np.full(12, np.nan), + kind=FIFF.FIFFV_STIM_CH, + coord_frame=FIFF.FIFFV_COORD_UNKNOWN, + ) + ) + info._update_redundant() + + inst._raw_extras[0]["stim"] = stim + inst._raw_extras[0]["stim_code"] = stim_code + + +def _default_stim_chs(info): + """Return default stim channels for SQD files.""" + return pick_types(info, meg=False, ref_meg=False, misc=True, exclude=[])[:8] + + +def _make_stim_channel(trigger_chs, slope, threshold, stim_code, trigger_values): + """Create synthetic stim channel from multiple trigger channels.""" + if slope == "+": + trig_chs_bin = trigger_chs > threshold + elif slope == "-": + trig_chs_bin = trigger_chs < threshold + else: + raise ValueError("slope needs to be '+' or '-'") + # trigger value + if stim_code == "binary": + trigger_values = 2 ** np.arange(len(trigger_chs)) + elif stim_code != "channel": + raise ValueError( + f"stim_code must be 'binary' or 'channel', got {repr(stim_code)}" + ) + trig_chs = trig_chs_bin * trigger_values[:, np.newaxis] + return np.array(trig_chs.sum(axis=0), ndmin=2) + + +@fill_doc +class EpochsKIT(BaseEpochs): + """Epochs Array object from KIT SQD file. + + Parameters + ---------- + input_fname : path-like + Path to the sqd file. + events : array of int, shape (n_events, 3) | path-like + The array of :term:`events`. The first column contains the event time + in samples, with :term:`first_samp` included. The third column contains + the event id. If a path, must yield a ``.txt`` file containing the + events. + If some events don't match the events of interest as specified by + ``event_id``, they will be marked as ``IGNORED`` in the drop log. + %(event_id)s + tmin : float + Start time before event. + %(baseline_epochs)s + %(reject_epochs)s + %(flat)s + %(epochs_reject_tmin_tmax)s + %(kit_mrk)s + %(kit_elp)s + %(kit_hsp)s + allow_unknown_format : bool + Force reading old data that is not officially supported. Alternatively, + read and re-save the data with the KIT MEG Laboratory application. + %(standardize_names)s + %(verbose)s + + Notes + ----- + ``elp`` and ``hsp`` are usually the exported text files (*.txt) from the + Polhemus FastScan system. hsp refers to the headshape surface points. elp + refers to the points in head-space that corresponds to the HPI points. + Currently, '*.elp' and '*.hsp' files are NOT supported. + + See Also + -------- + mne.Epochs : Documentation of attributes and methods. + """ + + @verbose + def __init__( + self, + input_fname, + events, + event_id=None, + tmin=0, + baseline=None, + reject=None, + flat=None, + reject_tmin=None, + reject_tmax=None, + mrk=None, + elp=None, + hsp=None, + allow_unknown_format=False, + standardize_names=None, + verbose=None, + ): + if isinstance(events, str | PathLike | Path): + events = read_events(events) + + input_fname = str( + _check_fname(fname=input_fname, must_exist=True, overwrite="read") + ) + logger.info(f"Extracting KIT Parameters from {input_fname}...") + self.info, kit_info = get_kit_info( + input_fname, allow_unknown_format, standardize_names + ) + kit_info.update(input_fname=input_fname) + self._raw_extras = [kit_info] + self.filenames = [] + if len(events) != self._raw_extras[0]["n_epochs"]: + raise ValueError("Event list does not match number of epochs.") + + if self._raw_extras[0]["acq_type"] == KIT.EPOCHS: + self._raw_extras[0]["data_length"] = KIT.INT + else: + raise TypeError( + "SQD file contains raw data, not epochs or average. Wrong reader." + ) + + if event_id is None: # convert to int to make typing-checks happy + event_id = {str(e): int(e) for e in np.unique(events[:, 2])} + + for key, val in event_id.items(): + if val not in events[:, 2]: + raise ValueError(f"No matching events found for {key} (event id {val})") + + data = self._read_kit_data() + assert data.shape == ( + self._raw_extras[0]["n_epochs"], + self.info["nchan"], + self._raw_extras[0]["frame_length"], + ) + tmax = ((data.shape[2] - 1) / self.info["sfreq"]) + tmin + super().__init__( + self.info, + data, + events, + event_id, + tmin, + tmax, + baseline, + reject=reject, + flat=flat, + reject_tmin=reject_tmin, + reject_tmax=reject_tmax, + filename=input_fname, + verbose=verbose, + ) + self.info = _call_digitization( + info=self.info, mrk=mrk, elp=elp, hsp=hsp, kit_info=kit_info + ) + logger.info("Ready.") + + def _read_kit_data(self): + """Read epochs data. + + Returns + ------- + data : array, [channels x samples] + the data matrix (channels x samples). + times : array, [samples] + returns the time values corresponding to the samples. + """ + info = self._raw_extras[0] + epoch_length = info["frame_length"] + n_epochs = info["n_epochs"] + n_samples = info["n_samples"] + input_fname = info["input_fname"] + dtype = info["dtype"] + nchan = info["nchan"] + + with open(input_fname, "rb", buffering=0) as fid: + fid.seek(info["dirs"][KIT.DIR_INDEX_RAW_DATA]["offset"]) + count = n_samples * nchan + data = np.fromfile(fid, dtype=dtype, count=count) + data = data.reshape((n_samples, nchan)).T + data = data * info["conv_factor"] + data = data.reshape((nchan, n_epochs, epoch_length)) + data = data.transpose((1, 0, 2)) + + return data + + +def _read_dir(fid): + return dict( + offset=np.fromfile(fid, UINT32, 1)[0], + size=np.fromfile(fid, INT32, 1)[0], + max_count=np.fromfile(fid, INT32, 1)[0], + count=np.fromfile(fid, INT32, 1)[0], + ) + + +@verbose +def _read_dirs(fid, verbose=None): + dirs = list() + dirs.append(_read_dir(fid)) + for ii in range(dirs[0]["count"] - 1): + logger.debug(f" KIT dir entry {ii} @ {fid.tell()}") + dirs.append(_read_dir(fid)) + assert len(dirs) == dirs[KIT.DIR_INDEX_DIR]["count"] + return dirs + + +@verbose +def get_kit_info(rawfile, allow_unknown_format, standardize_names=None, verbose=None): + """Extract all the information from the sqd/con file. + + Parameters + ---------- + rawfile : path-like + KIT file to be read. + allow_unknown_format : bool + Force reading old data that is not officially supported. Alternatively, + read and re-save the data with the KIT MEG Laboratory application. + %(standardize_names)s + %(verbose)s + + Returns + ------- + %(info_not_none)s + sqd : dict + A dict containing all the sqd parameter settings. + """ + sqd = dict() + sqd["rawfile"] = rawfile + unsupported_format = False + with open(rawfile, "rb", buffering=0) as fid: # buffering=0 for np bug + # + # directories (0) + # + sqd["dirs"] = dirs = _read_dirs(fid) + + # + # system (1) + # + fid.seek(dirs[KIT.DIR_INDEX_SYSTEM]["offset"]) + # check file format version + version, revision = np.fromfile(fid, INT32, 2) + if version < 2 or (version == 2 and revision < 3): + version_string = f"V{version}R{revision:03d}" + if allow_unknown_format: + unsupported_format = True + warn(f"Force loading KIT format {version_string}") + else: + raise UnsupportedKITFormat( + version_string, + f"SQD file format {version_string} is not officially supported. " + "Set allow_unknown_format=True to load it anyways.", + ) + + sysid = np.fromfile(fid, INT32, 1)[0] + # basic info + system_name = _read_name(fid, n=128) + # model name + model_name = _read_name(fid, n=128) + # channels + sqd["nchan"] = channel_count = int(np.fromfile(fid, INT32, 1)[0]) + comment = _read_name(fid, n=256) + create_time, last_modified_time = np.fromfile(fid, INT32, 2) + del last_modified_time + fid.seek(KIT.INT * 3, SEEK_CUR) # reserved + dewar_style = np.fromfile(fid, INT32, 1)[0] + fid.seek(KIT.INT * 3, SEEK_CUR) # spare + fll_type = np.fromfile(fid, INT32, 1)[0] + fid.seek(KIT.INT * 3, SEEK_CUR) # spare + trigger_type = np.fromfile(fid, INT32, 1)[0] + fid.seek(KIT.INT * 3, SEEK_CUR) # spare + adboard_type = np.fromfile(fid, INT32, 1)[0] + fid.seek(KIT.INT * 29, SEEK_CUR) # reserved + + if version < 2 or (version == 2 and revision <= 3): + adc_range = float(np.fromfile(fid, INT32, 1)[0]) + else: + adc_range = np.fromfile(fid, FLOAT64, 1)[0] + adc_polarity, adc_allocated, adc_stored = np.fromfile(fid, INT32, 3) + del adc_polarity + system_name = system_name.replace("\x00", "") + system_name = system_name.strip().replace("\n", "/") + model_name = model_name.replace("\x00", "") + model_name = model_name.strip().replace("\n", "/") + + full_version = f"V{version:d}R{revision:03d}" + logger.debug("SQD file basic information:") + logger.debug("Meg160 version = %s", full_version) + logger.debug("System ID = %i", sysid) + logger.debug("System name = %s", system_name) + logger.debug("Model name = %s", model_name) + logger.debug("Channel count = %i", channel_count) + logger.debug("Comment = %s", comment) + logger.debug("Dewar style = %i", dewar_style) + logger.debug("FLL type = %i", fll_type) + logger.debug("Trigger type = %i", trigger_type) + logger.debug("A/D board type = %i", adboard_type) + logger.debug("ADC range = +/-%s[V]", adc_range / 2.0) + logger.debug("ADC allocate = %i[bit]", adc_allocated) + logger.debug("ADC bit = %i[bit]", adc_stored) + # MGH description: 'acquisition (megacq) VectorView system at NMR-MGH' + description = f"{system_name} ({sysid}) {full_version} {model_name}" + assert adc_allocated % 8 == 0 + sqd["dtype"] = np.dtype(f"{use_fll_type}, check your data for correctness, " + "including channel scales and filter settings!" + ) + fll_type = use_fll_type + + # + # channel information (4) + # + chan_dir = dirs[KIT.DIR_INDEX_CHANNELS] + chan_offset, chan_size = chan_dir["offset"], chan_dir["size"] + sqd["channels"] = channels = [] + exg_gains = list() + for i in range(channel_count): + fid.seek(chan_offset + chan_size * i) + (channel_type,) = np.fromfile(fid, INT32, 1) + # System 52 mislabeled reference channels as NULL. This was fixed + # in system 53; not sure about 51... + if sysid == 52 and i < 160 and channel_type == KIT.CHANNEL_NULL: + channel_type = KIT.CHANNEL_MAGNETOMETER_REFERENCE + + if channel_type in KIT.CHANNELS_MEG: + if channel_type not in KIT.CH_TO_FIFF_COIL: + raise NotImplementedError( + "KIT channel type {channel_type} can not be read. Please " + "contact the mne-python developers." + ) + channels.append( + { + "type": channel_type, + # (x, y, z, theta, phi) for all MEG channels. Some channel + # types have additional information which we're not using. + "loc": np.fromfile(fid, dtype=FLOAT64, count=5), + } + ) + if channel_type in KIT.CHANNEL_NAME_NCHAR: + fid.seek(16, SEEK_CUR) # misc fields + channels[-1]["name"] = _read_name(fid, channel_type) + elif channel_type in KIT.CHANNELS_MISC: + (channel_no,) = np.fromfile(fid, INT32, 1) + fid.seek(4, SEEK_CUR) + name = _read_name(fid, channel_type) + channels.append( + { + "type": channel_type, + "no": channel_no, + "name": name, + } + ) + if channel_type in (KIT.CHANNEL_EEG, KIT.CHANNEL_ECG): + offset = 6 if channel_type == KIT.CHANNEL_EEG else 8 + fid.seek(offset, SEEK_CUR) + exg_gains.append(np.fromfile(fid, FLOAT64, 1)[0]) + elif channel_type == KIT.CHANNEL_NULL: + channels.append({"type": channel_type}) + else: + raise OSError("Unknown KIT channel type: {channel_type}") + exg_gains = np.array(exg_gains) + + # + # Channel sensitivity information: (5) + # + + # only sensor channels requires gain. the additional misc channels + # (trigger channels, audio and voice channels) are passed + # through unaffected + fid.seek(dirs[KIT.DIR_INDEX_CALIBRATION]["offset"]) + # (offset [Volt], gain [Tesla/Volt]) for each channel + sensitivity = np.fromfile(fid, dtype=FLOAT64, count=channel_count * 2) + sensitivity = _reshape_view(sensitivity, (channel_count, 2)) + channel_offset, channel_gain = sensitivity.T + assert (channel_offset == 0).all() # otherwise we have a problem + + # + # amplifier gain (7) + # + fid.seek(dirs[KIT.DIR_INDEX_AMP_FILTER]["offset"]) + amp_data = np.fromfile(fid, INT32, 1)[0] + if fll_type >= 100: # Kapper Type + # gain: mask bit + gain1 = (amp_data & 0x00007000) >> 12 + gain2 = (amp_data & 0x70000000) >> 28 + gain3 = (amp_data & 0x07000000) >> 24 + amp_gain = KIT.GAINS[gain1] * KIT.GAINS[gain2] * KIT.GAINS[gain3] + # filter settings + hpf = (amp_data & 0x00000700) >> 8 + lpf = (amp_data & 0x00070000) >> 16 + bef = (amp_data & 0x00000003) >> 0 + else: # Hanger Type + # gain + input_gain = (amp_data & 0x1800) >> 11 + output_gain = (amp_data & 0x0007) >> 0 + amp_gain = KIT.GAINS[input_gain] * KIT.GAINS[output_gain] + # filter settings + hpf = (amp_data & 0x007) >> 4 + lpf = (amp_data & 0x0700) >> 8 + bef = (amp_data & 0xC000) >> 14 + hpf_options, lpf_options, bef_options = KIT.FLL_SETTINGS[fll_type] + sqd["highpass"] = KIT.HPFS[hpf_options][hpf] + sqd["lowpass"] = KIT.LPFS[lpf_options][lpf] + sqd["notch"] = KIT.BEFS[bef_options][bef] + + # + # Acquisition Parameters (8) + # + fid.seek(dirs[KIT.DIR_INDEX_ACQ_COND]["offset"]) + (sqd["acq_type"],) = (acq_type,) = np.fromfile(fid, INT32, 1) + (sqd["sfreq"],) = np.fromfile(fid, FLOAT64, 1) + if acq_type == KIT.CONTINUOUS: + # samples_count, = np.fromfile(fid, INT32, 1) + fid.seek(KIT.INT, SEEK_CUR) + (sqd["n_samples"],) = np.fromfile(fid, INT32, 1) + elif acq_type == KIT.EVOKED or acq_type == KIT.EPOCHS: + (sqd["frame_length"],) = np.fromfile(fid, INT32, 1) + (sqd["pretrigger_length"],) = np.fromfile(fid, INT32, 1) + (sqd["average_count"],) = np.fromfile(fid, INT32, 1) + (sqd["n_epochs"],) = np.fromfile(fid, INT32, 1) + if acq_type == KIT.EVOKED: + sqd["n_samples"] = sqd["frame_length"] + else: + sqd["n_samples"] = sqd["frame_length"] * sqd["n_epochs"] + else: + raise OSError( + f"Invalid acquisition type: {acq_type}. Your file is neither " + "continuous nor epoched data." + ) + + # + # digitization information (12 and 26) + # + dig_dir = dirs[KIT.DIR_INDEX_DIG_POINTS] + cor_dir = dirs[KIT.DIR_INDEX_COREG] + dig = dict() + hsp = list() + if dig_dir["count"] > 0 and cor_dir["count"] > 0: + # directories (0) + fid.seek(dig_dir["offset"]) + for _ in range(dig_dir["count"]): + name = _read_name(fid, n=8).strip() + # Sometimes there are mismatches (e.g., AFz vs AFZ) between + # the channel name and its digitized, name, so let's be case + # insensitive. It will also prevent collisions with HSP + name = name.lower() + rr = np.fromfile(fid, FLOAT64, 3) + if name: + assert name not in dig + dig[name] = rr + else: + hsp.append(rr) + + # nasion, lpa, rpa, HPI in native space + elp = [] + for key in ( + "fidnz", + "fidt9", + "fidt10", + "hpi_1", + "hpi_2", + "hpi_3", + "hpi_4", + "hpi_5", + ): + if key in dig and np.isfinite(dig[key]).all(): + elp.append(dig.pop(key)) + elp = np.array(elp) + hsp = np.array(hsp, float).reshape(-1, 3) + if elp.shape not in ((6, 3), (7, 3), (8, 3)): + raise RuntimeError(f"Fewer than 3 HPI coils found, got {len(elp) - 3}") + # coregistration + fid.seek(cor_dir["offset"]) + mrk = np.zeros((elp.shape[0] - 3, 3)) + meg_done = [True] * 5 + for _ in range(cor_dir["count"]): + done = np.fromfile(fid, INT32, 1)[0] + fid.seek( + 16 * KIT.DOUBLE + 16 * KIT.DOUBLE, # meg_to_mri # mri_to_meg + SEEK_CUR, + ) + marker_count = np.fromfile(fid, INT32, 1)[0] + if not done: + continue + assert marker_count >= len(mrk) + for mi in range(len(mrk)): + mri_type, meg_type, mri_done, this_meg_done = np.fromfile( + fid, INT32, 4 + ) + del mri_type, meg_type, mri_done + meg_done[mi] = bool(this_meg_done) + fid.seek(3 * KIT.DOUBLE, SEEK_CUR) # mri_pos + mrk[mi] = np.fromfile(fid, FLOAT64, 3) + fid.seek(256, SEEK_CUR) # marker_file (char) + if not all(meg_done): + logger.info( + f"Keeping {sum(meg_done)}/{len(meg_done)} HPI " + "coils that were digitized" + ) + elp = elp[[True] * 3 + meg_done] + mrk = mrk[meg_done] + sqd.update(hsp=hsp, elp=elp, mrk=mrk) + + # precompute conversion factor for reading data + if unsupported_format: + if sysid not in LEGACY_AMP_PARAMS: + raise OSError(f"Legacy parameters for system ID {sysid} unavailable.") + adc_range, adc_stored = LEGACY_AMP_PARAMS[sysid] + is_meg = np.array([ch["type"] in KIT.CHANNELS_MEG for ch in channels]) + ad_to_volt = adc_range / (2.0**adc_stored) + ad_to_tesla = ad_to_volt / amp_gain * channel_gain + conv_factor = np.where(is_meg, ad_to_tesla, ad_to_volt) + # XXX this is a bit of a hack. Should probably do this more cleanly at + # some point... the 2 ** (adc_stored - 14) was empirically determined using + # the test files with known amplitudes. The conv_factors need to be + # replaced by these values otherwise we're off by a factor off 5000.0 + # for the EEG data. + is_exg = [ch["type"] in (KIT.CHANNEL_EEG, KIT.CHANNEL_ECG) for ch in channels] + exg_gains /= 2.0 ** (adc_stored - 14) + exg_gains[exg_gains == 0] = ad_to_volt + conv_factor[is_exg] = exg_gains + sqd["conv_factor"] = conv_factor[:, np.newaxis] + + # Create raw.info dict for raw fif object with SQD data + info = _empty_info(float(sqd["sfreq"])) + info.update( + meas_date=_stamp_to_dt((create_time, 0)), + lowpass=sqd["lowpass"], + highpass=sqd["highpass"], + kit_system_id=sysid, + description=description, + dev_head_t=Transform("meg", "head"), + ) + + # Creates a list of dicts of meg channels for raw.info + logger.info("Setting channel info structure...") + info["chs"] = fiff_channels = [] + channel_index = defaultdict(lambda: 0) + sqd["eeg_dig"] = OrderedDict() + for idx, ch in enumerate(channels, 1): + if ch["type"] in KIT.CHANNELS_MEG: + ch_name = ch.get("name", "") + if ch_name == "" or standardize_names: + ch_name = f"MEG {idx:03d}" + # create three orthogonal vector + # ch_angles[0]: theta, ch_angles[1]: phi + theta, phi = np.radians(ch["loc"][3:]) + x = sin(theta) * cos(phi) + y = sin(theta) * sin(phi) + z = cos(theta) + vec_z = np.array([x, y, z]) + vec_z /= np.linalg.norm(vec_z) + vec_x = np.zeros(vec_z.size, dtype=np.float64) + if vec_z[1] < vec_z[2]: + if vec_z[0] < vec_z[1]: + vec_x[0] = 1.0 + else: + vec_x[1] = 1.0 + elif vec_z[0] < vec_z[2]: + vec_x[0] = 1.0 + else: + vec_x[2] = 1.0 + vec_x -= np.sum(vec_x * vec_z) * vec_z + vec_x /= np.linalg.norm(vec_x) + vec_y = np.cross(vec_z, vec_x) + # transform to Neuromag like coordinate space + vecs = np.vstack((ch["loc"][:3], vec_x, vec_y, vec_z)) + vecs = apply_trans(als_ras_trans, vecs) + unit = FIFF.FIFF_UNIT_T + loc = vecs.ravel() + else: + ch_type_label = KIT.CH_LABEL[ch["type"]] + channel_index[ch_type_label] += 1 + ch_type_index = channel_index[ch_type_label] + ch_name = ch.get("name", "") + eeg_name = ch_name.lower() + # some files have all EEG labeled as EEG + if ch_name in ("", "EEG") or standardize_names: + ch_name = f"{ch_type_label} {ch_type_index:03d}" + unit = FIFF.FIFF_UNIT_V + loc = np.zeros(12) + if eeg_name and eeg_name in dig: + loc[:3] = sqd["eeg_dig"][eeg_name] = dig[eeg_name] + fiff_channels.append( + dict( + cal=KIT.CALIB_FACTOR, + logno=idx, + scanno=idx, + range=KIT.RANGE, + unit=unit, + unit_mul=KIT.UNIT_MUL, + ch_name=ch_name, + coord_frame=FIFF.FIFFV_COORD_DEVICE, + coil_type=KIT.CH_TO_FIFF_COIL[ch["type"]], + kind=KIT.CH_TO_FIFF_KIND[ch["type"]], + loc=loc, + ) + ) + info._unlocked = False + info._update_redundant() + return info, sqd + + +def _read_name(fid, ch_type=None, n=None): + n = n if ch_type is None else KIT.CHANNEL_NAME_NCHAR[ch_type] + return fid.read(n).split(b"\x00")[0].decode("utf-8") + + +@fill_doc +def read_raw_kit( + input_fname, + mrk=None, + elp=None, + hsp=None, + stim=">", + slope="-", + stimthresh=1, + preload=False, + stim_code="binary", + allow_unknown_format=False, + standardize_names=False, + *, + bad_coils=(), + verbose=None, +) -> RawKIT: + r"""Reader function for Ricoh/KIT conversion to FIF. + + Parameters + ---------- + input_fname : path-like + Path to the SQD file. + %(kit_mrk)s + %(kit_elp)s + %(kit_hsp)s + %(kit_stim)s + %(kit_slope)s + %(kit_stimthresh)s + %(preload)s + %(kit_stimcode)s + allow_unknown_format : bool + Force reading old data that is not officially supported. Alternatively, + read and re-save the data with the KIT MEG Laboratory application. + %(standardize_names)s + %(kit_badcoils)s + %(verbose)s + + Returns + ------- + raw : instance of RawKIT + A Raw object containing KIT data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawKIT. + + Notes + ----- + ``elp`` and ``hsp`` are usually the exported text files (\*.txt) from the + Polhemus FastScan system. ``hsp`` refers to the headshape surface points. + ``elp`` refers to the points in head-space that corresponds to the HPI + points. + + If ``mrk``\, ``hsp`` or ``elp`` are :term:`array_like` inputs, then the + numbers in xyz coordinates should be in units of meters. + """ + return RawKIT( + input_fname=input_fname, + mrk=mrk, + elp=elp, + hsp=hsp, + stim=stim, + slope=slope, + stimthresh=stimthresh, + preload=preload, + stim_code=stim_code, + allow_unknown_format=allow_unknown_format, + standardize_names=standardize_names, + bad_coils=bad_coils, + verbose=verbose, + ) + + +@fill_doc +def read_epochs_kit( + input_fname, + events, + event_id=None, + mrk=None, + elp=None, + hsp=None, + allow_unknown_format=False, + standardize_names=False, + verbose=None, +) -> EpochsKIT: + """Reader function for Ricoh/KIT epochs files. + + Parameters + ---------- + input_fname : path-like + Path to the SQD file. + events : array of int, shape (n_events, 3) | path-like + The array of :term:`events`. The first column contains the event time + in samples, with :term:`first_samp` included. The third column contains + the event id. If a path, must yield a ``.txt`` file containing the + events. + If some events don't match the events of interest as specified by + ``event_id``, they will be marked as ``IGNORED`` in the drop log. + %(event_id)s + %(kit_mrk)s + %(kit_elp)s + %(kit_hsp)s + allow_unknown_format : bool + Force reading old data that is not officially supported. Alternatively, + read and re-save the data with the KIT MEG Laboratory application. + %(standardize_names)s + %(verbose)s + + Returns + ------- + EpochsKIT : instance of BaseEpochs + The epochs. + + See Also + -------- + mne.Epochs : Documentation of attributes and methods. + + Notes + ----- + .. versionadded:: 0.9.0 + """ + epochs = EpochsKIT( + input_fname=input_fname, + events=events, + event_id=event_id, + mrk=mrk, + elp=elp, + hsp=hsp, + allow_unknown_format=allow_unknown_format, + standardize_names=standardize_names, + verbose=verbose, + ) + return epochs diff --git a/mne-python/source/mne/io/kit/tests/__init__.py b/mne-python/source/mne/io/kit/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..25a040855f1b68d6640d6762702206aba47fe9c8 --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +data_dir = Path(__file__).parent / "data" diff --git a/mne-python/source/mne/io/kit/tests/data/sns.txt b/mne-python/source/mne/io/kit/tests/data/sns.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b166df16a9c0faeb75ac2987c3a487924a6c9dd --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/sns.txt @@ -0,0 +1,195 @@ +[Sensor Definition] +Channel no.,Type,x,y,z,theta,phi,size,baseline +,,[mm],[mm],[mm],[deg],[deg],[mm],[mm] +0,AxialGradioMeter,-101.52,-68.02,20.93,81.07,222.01,15.50,50.00 +1,AxialGradioMeter,-122.64,-22.28,22.28,79.66,192.59,15.50,50.00 +2,AxialGradioMeter,-107.05,-65.31,-61.76,90.46,217.16,15.50,50.00 +3,AxialGradioMeter,-118.37,-44.33,-58.74,89.16,206.22,15.50,50.00 +4,AxialGradioMeter,-124.69,-22.17,-57.88,89.07,193.26,15.50,50.00 +5,AxialGradioMeter,-89.78,-84.53,-61.59,89.29,228.49,15.50,50.00 +6,AxialGradioMeter,-89.38,-73.82,39.07,73.39,228.04,15.50,50.00 +7,AxialGradioMeter,-104.96,-53.16,41.21,72.14,215.24,15.50,50.00 +8,AxialGradioMeter,-16.03,119.37,-65.63,87.63,95.79,15.50,50.00 +9,AxialGradioMeter,-80.87,88.26,-14.78,95.70,127.17,15.50,50.00 +10,AxialGradioMeter,-38.58,110.27,-65.95,89.53,105.43,15.50,50.00 +11,AxialGradioMeter,-63.03,100.12,-66.07,90.36,115.82,15.50,50.00 +12,AxialGradioMeter,-124.55,3.28,22.20,79.74,176.77,15.50,50.00 +13,AxialGradioMeter,-110.55,50.16,19.36,80.44,148.66,15.50,50.00 +14,AxialGradioMeter,-99.07,69.89,-9.70,91.04,137.55,15.50,50.00 +15,AxialGradioMeter,-87.38,37.06,82.65,51.93,151.83,15.50,50.00 +16,AxialGradioMeter,-58.58,-4.07,110.92,28.65,184.17,15.50,50.00 +17,AxialGradioMeter,-123.94,-21.02,-35.42,92.08,191.89,15.50,50.00 +18,AxialGradioMeter,-88.81,-84.37,-40.92,95.46,232.31,15.50,50.00 +19,AxialGradioMeter,-114.17,-29.81,41.39,72.20,198.16,15.50,50.00 +20,AxialGradioMeter,-4.18,-117.98,31.45,79.03,268.94,15.50,50.00 +21,AxialGradioMeter,-54.91,-105.44,37.81,75.48,246.23,15.50,50.00 +22,AxialGradioMeter,-109.43,-7.78,61.83,63.61,184.63,15.50,50.00 +23,AxialGradioMeter,-80.50,-74.17,58.91,65.70,230.29,15.50,50.00 +24,AxialGradioMeter,-115.11,15.80,42.04,70.78,169.68,15.50,50.00 +25,AxialGradioMeter,-109.18,38.57,42.82,71.62,154.74,15.50,50.00 +26,AxialGradioMeter,-76.22,18.26,99.72,38.50,160.84,15.50,50.00 +27,AxialGradioMeter,-72.25,58.02,81.73,53.37,134.26,15.50,50.00 +28,AxialGradioMeter,-56.04,74.97,80.73,55.31,120.54,15.50,50.00 +29,AxialGradioMeter,-34.11,83.86,78.30,56.85,110.70,15.50,50.00 +30,AxialGradioMeter,-9.43,89.24,76.81,56.03,96.48,15.50,50.00 +31,AxialGradioMeter,-123.65,28.89,-6.45,88.97,161.26,15.50,50.00 +32,AxialGradioMeter,1.09,-117.79,-7.02,85.17,269.85,15.50,50.00 +33,AxialGradioMeter,-73.27,-32.84,97.86,41.11,213.18,15.50,50.00 +34,AxialGradioMeter,-3.61,-25.36,128.05,16.37,260.34,15.50,50.00 +35,AxialGradioMeter,-105.02,-31.70,61.46,63.27,201.21,15.50,50.00 +36,AxialGradioMeter,-18.84,-120.72,-7.11,84.66,263.45,15.50,50.00 +37,AxialGradioMeter,-49.90,-109.62,-60.60,87.90,248.83,15.50,50.00 +38,AxialGradioMeter,-71.46,-99.70,-7.19,87.12,238.78,15.50,50.00 +39,AxialGradioMeter,-28.62,-116.91,-60.88,86.52,257.39,15.50,50.00 +40,AxialGradioMeter,-70.68,77.60,62.00,64.02,125.79,15.50,50.00 +41,AxialGradioMeter,-88.20,58.58,62.14,63.47,139.05,15.50,50.00 +42,AxialGradioMeter,-107.77,15.56,61.92,62.86,167.40,15.50,50.00 +43,AxialGradioMeter,-115.79,44.29,-60.88,91.85,153.90,15.50,50.00 +44,AxialGradioMeter,-103.66,65.18,-64.04,90.92,139.15,15.50,50.00 +45,AxialGradioMeter,-126.16,-0.48,-56.75,89.67,180.75,15.50,50.00 +46,AxialGradioMeter,-123.58,22.49,-58.02,88.62,166.26,15.50,50.00 +47,AxialGradioMeter,-44.35,35.38,109.86,32.47,133.19,15.50,50.00 +48,AxialGradioMeter,-4.59,-121.03,-62.10,87.80,264.83,15.50,50.00 +49,AxialGradioMeter,-87.33,-84.88,-13.24,95.60,229.72,15.50,50.00 +50,AxialGradioMeter,-118.29,-47.73,-7.15,89.55,207.65,15.50,50.00 +51,AxialGradioMeter,-50.54,-113.93,-32.53,85.55,249.85,15.50,50.00 +52,AxialGradioMeter,-48.08,-116.39,-9.09,85.89,249.42,15.50,50.00 +53,AxialGradioMeter,-15.34,-119.05,10.98,86.20,267.43,15.50,50.00 +54,AxialGradioMeter,-68.25,-99.97,16.27,82.75,238.88,15.50,50.00 +55,AxialGradioMeter,-0.80,-126.39,-31.12,81.24,269.18,15.50,50.00 +56,AxialGradioMeter,-34.15,18.93,119.59,22.02,144.71,15.50,50.00 +57,AxialGradioMeter,-32.80,-28.21,119.20,24.62,225.61,15.50,50.00 +58,AxialGradioMeter,-60.16,93.93,38.42,74.47,118.58,15.50,50.00 +59,AxialGradioMeter,-98.06,60.82,42.83,71.46,141.78,15.50,50.00 +60,AxialGradioMeter,-12.37,110.43,37.16,75.57,96.90,15.50,50.00 +61,AxialGradioMeter,-102.13,68.95,-40.47,93.88,138.71,15.50,50.00 +62,AxialGradioMeter,-128.89,3.16,-6.02,89.22,176.30,15.50,50.00 +63,AxialGradioMeter,-0.50,59.40,109.06,36.67,91.53,15.50,50.00 +64,AxialGradioMeter,-81.57,-55.03,79.87,54.71,222.29,15.50,50.00 +65,AxialGradioMeter,-79.74,-7.43,99.52,38.76,184.96,15.50,50.00 +66,AxialGradioMeter,51.38,-115.52,-12.92,88.12,289.89,15.50,50.00 +67,AxialGradioMeter,74.74,-99.45,-14.91,92.19,300.75,15.50,50.00 +68,AxialGradioMeter,22.12,-121.59,-8.92,86.20,274.14,15.50,50.00 +69,AxialGradioMeter,44.60,-87.67,72.58,60.15,288.26,15.50,50.00 +70,AxialGradioMeter,-0.48,-94.50,75.07,57.01,269.10,15.50,50.00 +71,AxialGradioMeter,23.84,-94.50,73.16,58.35,280.15,15.50,50.00 +72,AxialGradioMeter,-59.56,101.64,-7.64,86.37,115.66,15.50,50.00 +73,AxialGradioMeter,-10.46,116.08,-9.57,86.74,95.09,15.50,50.00 +74,AxialGradioMeter,-35.46,110.65,-9.73,86.02,105.92,15.50,50.00 +75,AxialGradioMeter,-4.48,17.23,128.02,11.05,110.32,15.50,50.00 +76,AxialGradioMeter,22.28,16.36,125.65,14.49,45.07,15.50,50.00 +77,AxialGradioMeter,-61.11,101.55,-37.57,89.33,115.42,15.50,50.00 +78,AxialGradioMeter,-13.80,117.71,-35.98,85.43,95.06,15.50,50.00 +79,AxialGradioMeter,64.72,102.18,-11.94,88.31,64.31,15.50,50.00 +80,AxialGradioMeter,-47.37,-83.00,76.43,57.55,245.56,15.50,50.00 +81,AxialGradioMeter,-26.04,-91.12,75.07,58.25,256.60,15.50,50.00 +82,AxialGradioMeter,50.44,-114.38,-38.12,88.90,289.50,15.50,50.00 +83,AxialGradioMeter,88.89,-87.74,-42.91,93.52,306.43,15.50,50.00 +84,AxialGradioMeter,-42.56,-46.61,108.49,35.99,236.74,15.50,50.00 +85,AxialGradioMeter,94.17,-84.20,8.46,86.45,308.62,15.50,50.00 +86,AxialGradioMeter,24.97,-119.28,10.66,86.05,276.54,15.50,50.00 +87,AxialGradioMeter,75.94,-98.27,9.94,84.91,300.74,15.50,50.00 +88,AxialGradioMeter,39.94,112.95,-36.10,86.02,71.72,15.50,50.00 +89,AxialGradioMeter,79.69,89.89,-49.30,100.09,55.10,15.50,50.00 +90,AxialGradioMeter,-47.87,58.21,95.68,43.78,124.76,15.50,50.00 +91,AxialGradioMeter,-77.96,87.32,17.90,80.23,125.96,15.50,50.00 +92,AxialGradioMeter,86.68,19.32,94.88,42.09,13.84,15.50,50.00 +93,AxialGradioMeter,14.78,40.34,119.13,25.45,77.53,15.50,50.00 +94,AxialGradioMeter,16.06,115.60,-10.59,86.39,85.15,15.50,50.00 +95,AxialGradioMeter,40.68,110.41,-11.22,86.80,74.04,15.50,50.00 +96,AxialGradioMeter,-41.48,-68.87,92.67,47.62,246.09,15.50,50.00 +97,AxialGradioMeter,-66.49,-71.53,79.41,56.48,236.61,15.50,50.00 +98,AxialGradioMeter,44.68,-110.64,33.27,76.89,286.25,15.50,50.00 +99,AxialGradioMeter,84.83,-85.22,32.16,76.77,305.43,15.50,50.00 +100,AxialGradioMeter,53.91,-112.29,11.67,84.23,291.50,15.50,50.00 +101,AxialGradioMeter,56.38,-66.94,90.28,49.24,297.67,15.50,50.00 +102,AxialGradioMeter,-61.78,-87.37,58.45,65.45,242.61,15.50,50.00 +103,AxialGradioMeter,-41.80,-99.21,58.56,66.08,251.63,15.50,50.00 +104,AxialGradioMeter,0.91,101.33,56.27,66.23,92.25,15.50,50.00 +105,AxialGradioMeter,-24.38,99.41,58.21,65.95,101.10,15.50,50.00 +106,AxialGradioMeter,25.47,100.68,56.56,66.23,82.12,15.50,50.00 +107,AxialGradioMeter,50.31,92.73,55.99,65.65,69.66,15.50,50.00 +108,AxialGradioMeter,70.73,80.59,56.57,64.50,57.89,15.50,50.00 +109,AxialGradioMeter,-33.22,109.85,13.64,84.62,105.09,15.50,50.00 +110,AxialGradioMeter,-48.21,91.31,59.86,65.16,113.01,15.50,50.00 +111,AxialGradioMeter,49.94,7.92,115.65,23.06,13.35,15.50,50.00 +112,AxialGradioMeter,-15.95,-107.49,57.73,64.58,262.88,15.50,50.00 +113,AxialGradioMeter,8.86,-108.71,56.11,66.04,273.95,15.50,50.00 +114,AxialGradioMeter,56.03,-94.00,54.55,65.74,292.70,15.50,50.00 +115,AxialGradioMeter,34.02,-103.80,55.22,65.95,282.25,15.50,50.00 +116,AxialGradioMeter,92.91,-69.58,53.66,67.26,311.27,15.50,50.00 +117,AxialGradioMeter,108.13,-50.31,55.17,65.99,324.76,15.50,50.00 +118,AxialGradioMeter,75.21,-82.79,53.97,66.46,301.54,15.50,50.00 +119,AxialGradioMeter,130.61,2.52,34.15,74.62,2.07,15.50,50.00 +120,AxialGradioMeter,18.14,114.55,13.50,83.66,84.00,15.50,50.00 +121,AxialGradioMeter,42.56,108.16,12.25,84.50,72.91,15.50,50.00 +122,AxialGradioMeter,66.19,98.40,11.00,85.46,61.62,15.50,50.00 +123,AxialGradioMeter,86.80,85.69,9.90,83.79,51.81,15.50,50.00 +124,AxialGradioMeter,42.40,85.52,76.34,56.91,69.88,15.50,50.00 +125,AxialGradioMeter,105.24,49.33,55.50,65.12,32.48,15.50,50.00 +126,AxialGradioMeter,117.75,27.82,55.61,64.10,18.64,15.50,50.00 +127,AxialGradioMeter,89.42,66.46,57.04,64.36,45.01,15.50,50.00 +128,AxialGradioMeter,117.46,-51.45,33.61,76.24,326.70,15.50,50.00 +129,AxialGradioMeter,30.54,-63.60,105.41,42.23,288.16,15.50,50.00 +130,AxialGradioMeter,3.22,-67.93,104.40,42.64,270.69,15.50,50.00 +131,AxialGradioMeter,62.47,27.21,106.70,32.35,29.10,15.50,50.00 +132,AxialGradioMeter,105.30,-24.63,76.14,54.36,340.80,15.50,50.00 +133,AxialGradioMeter,79.82,-64.83,73.71,58.23,309.27,15.50,50.00 +134,AxialGradioMeter,23.00,-23.33,124.13,16.75,305.36,15.50,50.00 +135,AxialGradioMeter,62.75,-33.81,106.76,34.25,319.76,15.50,50.00 +136,AxialGradioMeter,115.01,50.88,33.75,74.74,31.61,15.50,50.00 +137,AxialGradioMeter,19.88,90.44,76.48,56.00,79.87,15.50,50.00 +138,AxialGradioMeter,56.09,60.04,92.51,45.95,57.42,15.50,50.00 +139,AxialGradioMeter,27.17,56.29,107.60,37.65,69.78,15.50,50.00 +140,AxialGradioMeter,79.51,60.20,75.78,55.65,47.35,15.50,50.00 +141,AxialGradioMeter,104.40,25.42,75.88,54.40,20.84,15.50,50.00 +142,AxialGradioMeter,77.72,92.19,-74.17,95.17,56.33,15.50,50.00 +143,AxialGradioMeter,11.39,119.11,-65.02,89.80,85.69,15.50,50.00 +144,AxialGradioMeter,118.56,-24.78,57.56,64.34,342.15,15.50,50.00 +145,AxialGradioMeter,50.04,-14.83,115.24,23.47,336.39,15.50,50.00 +146,AxialGradioMeter,17.04,-48.20,116.89,31.08,282.70,15.50,50.00 +147,AxialGradioMeter,20.36,-118.34,-64.37,90.52,274.85,15.50,50.00 +148,AxialGradioMeter,42.77,-110.63,-65.89,91.74,286.08,15.50,50.00 +149,AxialGradioMeter,63.94,-101.32,-67.25,93.82,293.74,15.50,50.00 +150,AxialGradioMeter,85.05,-89.65,-68.16,94.79,307.40,15.50,50.00 +151,AxialGradioMeter,85.11,-32.44,92.47,45.12,326.98,15.50,50.00 +152,AxialGradioMeter,33.35,113.59,-66.96,91.67,74.38,15.50,50.00 +153,AxialGradioMeter,54.97,104.73,-71.03,95.41,66.56,15.50,50.00 +154,AxialGradioMeter,81.11,83.71,35.47,73.17,54.06,15.50,50.00 +155,AxialGradioMeter,38.61,104.83,33.91,75.45,76.35,15.50,50.00 +156,AxialGradioMeter,90.82,-8.65,93.89,43.54,348.98,15.50,50.00 +157,RefMagnetoMeter,0,0.00,0.00,0.00,0.00,0.00,4.00 +158,RefMagnetoMeter,0,0.00,0.00,0.00,0.00,0.00,4.00 +159,RefMagnetoMeter,0,0.00,0.00,0.00,0.00,0.00,4.00 +160,Null Channel +161,Null Channel +162,Null Channel +163,Null Channel +164,Null Channel +165,Null Channel +166,Null Channel +167,Null Channel +168,Null Channel +169,Null Channel +170,Null Channel +171,Null Channel +172,Null Channel +173,Null Channel +174,Null Channel +175,Null Channel +176,Null Channel +177,Null Channel +178,Null Channel +179,Null Channel +180,Null Channel +181,Null Channel +182,Null Channel +183,Null Channel +184,Null Channel +185,Null Channel +186,Null Channel +187,Null Channel +188,Null Channel +189,Null Channel +190,Null Channel +191,Null Channel diff --git a/mne-python/source/mne/io/kit/tests/data/test-epoch.raw b/mne-python/source/mne/io/kit/tests/data/test-epoch.raw new file mode 100644 index 0000000000000000000000000000000000000000..018b69868297504304f1700ff5e8fec2a7a89b3a --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/test-epoch.raw @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ec53fc29d83b0d81b53b5b735d0a856723c939109104442335b998e781028e7 +size 138388 diff --git a/mne-python/source/mne/io/kit/tests/data/test-eve.txt b/mne-python/source/mne/io/kit/tests/data/test-eve.txt new file mode 100644 index 0000000000000000000000000000000000000000..c505110fb845d6d41b4c015993a15708abafc6dc --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/test-eve.txt @@ -0,0 +1,2 @@ + 279 0 128 + 1562 0 128 diff --git a/mne-python/source/mne/io/kit/tests/data/test.elp b/mne-python/source/mne/io/kit/tests/data/test.elp new file mode 100644 index 0000000000000000000000000000000000000000..9e76e0794028e76d9a6de93aa4d6b51650b770f5 --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/test.elp @@ -0,0 +1,37 @@ +3 2 +//Probe file +//Minor revision number +1 +//ProbeName +%N Name +//Probe type, number of sensors +0 5 +//Position of fiducials X+, Y+, Y- on the subject +%F 0.11056 -5.421e-19 0 +%F -0.00021075 0.080793 -7.5894e-19 +%F 0.00021075 -0.080793 -2.8731e-18 +//Sensor type +%S 4000 +//Sensor name and data for sensor # 1 +%N 0-RED +0.0050132 0.077834 0.00010455 +//Sensor type +%S 4000 +//Sensor name and data for sensor # 2 +%N 1-YELLOW +0.010353 -0.076396 -0.0045289 +//Sensor type +%S 4000 +//Sensor name and data for sensor # 3 +%N 2-BLUE +0.11786 0.0049369 0.025876 +//Sensor type +%S 4000 +//Sensor name and data for sensor # 4 +%N 3-WHITE +0.1004 0.04654 0.024553 +//Sensor type +%S 4000 +//Sensor name and data for sensor # 5 +%N 4-BLACK +0.10746 -0.034116 0.031846 diff --git a/mne-python/source/mne/io/kit/tests/data/test.hsp b/mne-python/source/mne/io/kit/tests/data/test.hsp new file mode 100644 index 0000000000000000000000000000000000000000..a67ee50dec506effee85ee338f02356d27de676e --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/test.hsp @@ -0,0 +1,514 @@ +3 200 +//Shape file +//Minor revision number +2 +//Subject Name +%N Name +////Shape code, number of digitized points +0 500 +//Position of fiducials X+, Y+, Y- on the subject +%F 0.11056 -5.421e-19 0 +%F -0.00021075 0.080793 -7.5894e-19 +%F 0.00021075 -0.080793 -2.8731e-18 +//No of rows, no of columns; position of digitized points +500 3 +-0.009834 -0.095567 0.031855 +-0.008069 -0.095958 0.032424 +-0.006919 -0.096273 0.031884 +-0.007449 -0.095409 0.033315 +-0.006068 -0.095745 0.032652 +-0.006486 -0.094639 0.034006 +-0.005279 -0.095372 0.033638 +-0.004021 -0.095359 0.032883 +-0.003826 -0.094649 0.034051 +-0.002588 -0.095163 0.033564 +-0.020912 -0.078901 0.062986 +-0.020881 -0.078405 0.063868 +-0.019912 -0.078852 0.063517 +-0.022529 -0.077117 0.065358 +-0.021557 -0.077512 0.064988 +-0.020648 -0.077893 0.064646 +-0.019743 -0.078500 0.064407 +-0.018814 -0.078601 0.063927 +-0.022660 -0.076428 0.066386 +-0.021752 -0.076993 0.066128 +-0.020854 -0.077467 0.065832 +-0.019939 -0.077899 0.065515 +-0.018818 -0.078569 0.065188 +-0.017899 -0.078722 0.064721 +-0.022362 -0.076047 0.067450 +-0.021125 -0.076871 0.067125 +-0.019944 -0.077598 0.066789 +-0.018579 -0.078204 0.066292 +-0.017217 -0.078790 0.065782 +-0.016124 -0.078197 0.064872 +-0.014800 -0.077737 0.063904 +-0.013284 -0.077979 0.063140 +-0.011681 -0.078419 0.062414 +-0.010418 -0.078829 0.061879 +-0.008465 -0.079392 0.061014 +-0.004792 -0.080425 0.059360 +-0.001462 -0.081407 0.057884 +0.008183 -0.084293 0.053657 +-0.028415 -0.072888 0.071012 +-0.026642 -0.073448 0.070271 +-0.025230 -0.073988 0.069716 +-0.024019 -0.074352 0.069195 +-0.022778 -0.075072 0.068818 +-0.021608 -0.076160 0.068658 +-0.020223 -0.076445 0.067990 +-0.018898 -0.077725 0.067833 +-0.017534 -0.078322 0.067337 +-0.016193 -0.079095 0.066933 +-0.014952 -0.078086 0.065744 +-0.013742 -0.077512 0.064772 +-0.012372 -0.077984 0.064203 +-0.010990 -0.078363 0.063587 +-0.009611 -0.078731 0.062958 +-0.008229 -0.079110 0.062342 +-0.006843 -0.079467 0.061705 +-0.005461 -0.079793 0.061056 +-0.004093 -0.080183 0.060441 +-0.002707 -0.080550 0.059804 +-0.001079 -0.080896 0.059031 +0.000495 -0.081585 0.058438 +0.002538 -0.082366 0.057624 +0.005302 -0.083072 0.056359 +0.007411 -0.083445 0.055317 +0.008359 -0.083534 0.054815 +-0.033495 -0.070560 0.074667 +-0.031961 -0.071110 0.074042 +-0.030579 -0.071756 0.073555 +-0.029200 -0.072310 0.073024 +-0.027816 -0.072771 0.072453 +-0.026445 -0.073253 0.071883 +-0.025058 -0.073735 0.071326 +-0.023689 -0.074249 0.070790 +-0.022314 -0.074691 0.070214 +-0.020977 -0.075835 0.069978 +-0.019587 -0.076089 0.069304 +-0.018256 -0.077162 0.069043 +-0.016912 -0.077976 0.068651 +-0.015567 -0.078781 0.068260 +-0.014187 -0.079015 0.067580 +-0.012684 -0.077664 0.066084 +-0.011296 -0.077897 0.065396 +-0.009918 -0.078317 0.064800 +-0.008538 -0.078675 0.064171 +-0.007162 -0.079013 0.063530 +-0.005788 -0.079391 0.062908 +-0.004406 -0.079780 0.062291 +-0.003020 -0.080137 0.061655 +-0.001642 -0.080423 0.060994 +-0.000259 -0.080749 0.060345 +0.001105 -0.081232 0.059783 +0.002447 -0.081892 0.059313 +0.003795 -0.082479 0.058805 +0.005229 -0.082441 0.057962 +0.006677 -0.082412 0.057118 +0.007871 -0.082406 0.056425 +-0.035214 -0.069369 0.077141 +-0.033374 -0.070139 0.076447 +-0.031531 -0.070948 0.075765 +-0.029694 -0.071677 0.075059 +-0.027855 -0.072375 0.074333 +-0.026022 -0.073001 0.073583 +-0.024195 -0.073710 0.072872 +-0.022365 -0.074439 0.072174 +-0.021012 -0.075263 0.071788 +-0.019939 -0.076863 0.071911 +-0.018250 -0.075866 0.070493 +-0.016714 -0.077240 0.070254 +-0.015160 -0.078323 0.069864 +-0.013358 -0.079188 0.069234 +-0.011884 -0.078210 0.067935 +-0.010434 -0.077718 0.066879 +-0.008595 -0.078219 0.066056 +-0.006767 -0.078752 0.065247 +-0.004928 -0.079182 0.064392 +-0.003095 -0.079693 0.063562 +-0.001267 -0.080226 0.062752 +0.000561 -0.080759 0.061943 +0.002441 -0.080918 0.060941 +0.004272 -0.081409 0.060112 +0.006195 -0.081337 0.058975 +0.007852 -0.081505 0.058100 +-0.037299 -0.067791 0.079847 +-0.035422 -0.068731 0.079205 +-0.033584 -0.069552 0.078530 +-0.031747 -0.070415 0.077889 +-0.029916 -0.071164 0.077190 +-0.028082 -0.071882 0.076471 +-0.026241 -0.072580 0.075759 +-0.024419 -0.073248 0.075022 +-0.022589 -0.073977 0.074324 +-0.020997 -0.074554 0.073692 +-0.019955 -0.076784 0.074128 +-0.019076 -0.077600 0.074003 +-0.017564 -0.075704 0.072283 +-0.015964 -0.076042 0.071527 +-0.014471 -0.077995 0.071570 +-0.012664 -0.078706 0.070868 +-0.011072 -0.079158 0.070171 +-0.009569 -0.077992 0.068773 +-0.007934 -0.077946 0.067811 +-0.006095 -0.078376 0.066956 +-0.004274 -0.078971 0.066173 +-0.002438 -0.079431 0.065338 +-0.000598 -0.079891 0.064482 +0.001247 -0.080238 0.063587 +0.003126 -0.080396 0.062585 +0.004963 -0.080825 0.061716 +0.006865 -0.080930 0.060686 +0.008768 -0.081056 0.059655 +0.010195 -0.081142 0.058885 +-0.039305 -0.066140 0.082599 +-0.037449 -0.067144 0.081999 +-0.035605 -0.068088 0.081381 +-0.033761 -0.069032 0.080764 +-0.031927 -0.069750 0.080044 +-0.030093 -0.070582 0.079391 +-0.028265 -0.071435 0.078744 +-0.026437 -0.072154 0.078032 +-0.024611 -0.072771 0.077290 +-0.022787 -0.073449 0.076567 +-0.020966 -0.074220 0.075896 +-0.019313 -0.077845 0.076603 +-0.017883 -0.077007 0.075423 +-0.016385 -0.075432 0.073867 +-0.014559 -0.075935 0.073059 +-0.012835 -0.077826 0.072948 +-0.011031 -0.078444 0.072201 +-0.009207 -0.078864 0.071348 +-0.007214 -0.077531 0.069604 +-0.005380 -0.077981 0.068755 +-0.003532 -0.078307 0.067840 +-0.001731 -0.079028 0.067145 +0.000098 -0.079561 0.066336 +0.001940 -0.079897 0.065428 +0.003848 -0.079796 0.064294 +0.005664 -0.080474 0.063564 +0.007552 -0.080518 0.062503 +0.009457 -0.080654 0.061485 +0.011354 -0.080790 0.060461 +0.013021 -0.080917 0.059573 +-0.042940 -0.063924 0.085965 +-0.040913 -0.064605 0.085122 +-0.039021 -0.065688 0.084542 +-0.037170 -0.066713 0.083949 +-0.035324 -0.067677 0.083344 +-0.033490 -0.068653 0.082755 +-0.031660 -0.069536 0.082106 +-0.029826 -0.070306 0.081420 +-0.027996 -0.071035 0.080722 +-0.026180 -0.071838 0.080057 +-0.024353 -0.072475 0.079314 +-0.022531 -0.073051 0.078560 +-0.020713 -0.073864 0.077909 +-0.019516 -0.077314 0.078790 +-0.018428 -0.078347 0.078633 +-0.017436 -0.077239 0.077587 +-0.016147 -0.075190 0.075947 +-0.014304 -0.075445 0.075022 +-0.012489 -0.076032 0.074261 +-0.010782 -0.078027 0.074203 +-0.008978 -0.078583 0.073423 +-0.007157 -0.078973 0.072558 +-0.005274 -0.078894 0.071453 +-0.003382 -0.078702 0.070289 +-0.001507 -0.078686 0.069210 +0.000339 -0.078991 0.068282 +0.002186 -0.079306 0.067368 +0.004053 -0.079538 0.066413 +0.005901 -0.079854 0.065499 +0.007763 -0.080106 0.064551 +0.009667 -0.080170 0.063501 +0.011569 -0.080286 0.062470 +0.013491 -0.080317 0.061399 +0.015391 -0.080536 0.060420 +-0.041891 -0.063482 0.087420 +-0.040168 -0.064909 0.087082 +-0.038324 -0.065370 0.086254 +-0.036477 -0.066416 0.085681 +-0.034633 -0.067432 0.085095 +-0.032800 -0.068397 0.084492 +-0.030970 -0.069271 0.083858 +-0.029141 -0.070062 0.083179 +-0.027317 -0.070802 0.082488 +-0.025510 -0.071584 0.081818 +-0.023681 -0.072222 0.081089 +-0.021861 -0.072850 0.080354 +-0.020261 -0.073374 0.079695 +-0.019411 -0.074654 0.079784 +-0.018658 -0.077732 0.080741 +-0.017286 -0.077866 0.080039 +-0.015492 -0.074979 0.077742 +-0.013648 -0.075173 0.076799 +-0.011827 -0.075739 0.076031 +-0.010246 -0.076419 0.075445 +-0.008760 -0.078042 0.075335 +-0.006961 -0.078619 0.074562 +-0.005101 -0.078646 0.073518 +-0.003221 -0.078537 0.072401 +-0.001332 -0.078314 0.071224 +0.000535 -0.078484 0.070237 +0.002373 -0.078780 0.069317 +0.004218 -0.079137 0.068423 +0.006093 -0.079306 0.067442 +0.007952 -0.079590 0.066514 +0.009836 -0.079718 0.065505 +0.011746 -0.079771 0.064448 +0.013635 -0.079950 0.063465 +0.015552 -0.080013 0.062400 +0.017486 -0.080023 0.061315 +-0.046056 -0.061047 0.090813 +-0.044260 -0.061779 0.090125 +-0.042380 -0.063295 0.089739 +-0.040522 -0.063631 0.088844 +-0.038673 -0.064430 0.088155 +-0.036819 -0.065682 0.087671 +-0.034977 -0.066739 0.087105 +-0.033151 -0.067643 0.086477 +-0.031317 -0.068609 0.085888 +-0.029497 -0.069452 0.085235 +-0.027670 -0.070151 0.084524 +-0.025855 -0.070995 0.083893 +-0.024036 -0.071694 0.083176 +-0.022220 -0.072415 0.082494 +-0.020403 -0.073012 0.081747 +-0.018833 -0.073837 0.081240 +-0.017595 -0.077108 0.082005 +-0.015687 -0.074819 0.079925 +-0.014025 -0.074813 0.078994 +-0.012206 -0.075287 0.078196 +-0.010379 -0.075790 0.077388 +-0.008565 -0.076232 0.076564 +-0.006839 -0.077824 0.076303 +-0.005058 -0.078557 0.075617 +-0.003215 -0.078750 0.074659 +-0.001312 -0.078464 0.073448 +0.000529 -0.078709 0.072510 +0.002436 -0.078464 0.071311 +0.004293 -0.078666 0.070352 +0.006139 -0.078951 0.069439 +0.008012 -0.079110 0.068445 +0.009883 -0.079312 0.067484 +0.011776 -0.079459 0.066481 +0.013677 -0.079555 0.065451 +0.015576 -0.079629 0.064408 +0.017511 -0.079650 0.063336 +0.019450 -0.079650 0.062243 +0.020892 -0.079746 0.061472 +-0.057444 -0.057606 0.097741 +-0.054896 -0.058094 0.096515 +-0.050229 -0.059102 0.094331 +-0.046964 -0.060061 0.092920 +-0.045310 -0.060939 0.092374 +-0.043674 -0.061830 0.091850 +-0.041806 -0.062884 0.091268 +-0.039947 -0.063847 0.090648 +-0.038096 -0.064585 0.089940 +-0.036255 -0.065508 0.089310 +-0.034420 -0.066422 0.088688 +-0.032585 -0.067480 0.088130 +-0.030765 -0.068385 0.087509 +-0.028939 -0.069207 0.086864 +-0.027124 -0.070061 0.086218 +-0.025304 -0.070833 0.085547 +-0.023489 -0.071471 0.084820 +-0.021676 -0.072162 0.084125 +-0.019861 -0.072862 0.083430 +-0.018279 -0.073481 0.082825 +-0.016784 -0.075473 0.082866 +-0.014870 -0.074377 0.081332 +-0.013040 -0.074829 0.080519 +-0.011225 -0.075272 0.079694 +-0.009408 -0.075745 0.078882 +-0.007584 -0.076146 0.078044 +-0.006021 -0.076796 0.077433 +-0.004523 -0.078140 0.077178 +-0.002728 -0.078738 0.076426 +-0.001120 -0.078881 0.075579 +0.000330 -0.078513 0.074602 +0.001973 -0.078457 0.073647 +0.003810 -0.078795 0.072761 +0.005725 -0.078549 0.071569 +0.007594 -0.078668 0.070563 +0.009463 -0.078849 0.069589 +0.011346 -0.078956 0.068582 +0.013221 -0.079198 0.067633 +0.015127 -0.079263 0.066597 +0.017040 -0.079275 0.065520 +0.018992 -0.079201 0.064394 +0.020922 -0.079243 0.063329 +0.022626 -0.079244 0.062380 +-0.056904 -0.057222 0.099187 +-0.045705 -0.060240 0.094225 +-0.044305 -0.061223 0.093862 +-0.042661 -0.062052 0.093313 +-0.040812 -0.062707 0.092559 +-0.038960 -0.063733 0.091980 +-0.037119 -0.064574 0.091318 +-0.035274 -0.065528 0.090714 +-0.033441 -0.066493 0.090111 +-0.031615 -0.067469 0.089515 +-0.029798 -0.068344 0.088882 +-0.027979 -0.069301 0.088295 +-0.026169 -0.070104 0.087638 +-0.024352 -0.070835 0.086955 +-0.022532 -0.071514 0.086253 +-0.020727 -0.072267 0.085585 +-0.018921 -0.072958 0.084884 +-0.017361 -0.073887 0.084437 +-0.016261 -0.075710 0.084625 +-0.014676 -0.074509 0.083220 +-0.013028 -0.074752 0.082421 +-0.011220 -0.075195 0.081604 +-0.009387 -0.075554 0.080739 +-0.007562 -0.075893 0.079868 +-0.005730 -0.076180 0.078957 +-0.004188 -0.077017 0.078452 +-0.002702 -0.078321 0.078179 +-0.000897 -0.078805 0.077382 +0.000692 -0.079165 0.076640 +0.002171 -0.078548 0.075530 +0.003850 -0.078232 0.074449 +0.005631 -0.078903 0.073730 +0.007270 -0.079003 0.072861 +0.008724 -0.078738 0.071928 +0.010395 -0.078628 0.070938 +0.012278 -0.078736 0.069931 +0.014162 -0.078863 0.068923 +0.016065 -0.078979 0.067906 +0.017742 -0.078983 0.066974 +0.019442 -0.078943 0.066013 +0.021377 -0.078964 0.064941 +0.023084 -0.078933 0.063972 +0.024325 -0.078832 0.063237 +-0.056325 -0.056690 0.100536 +-0.045146 -0.059434 0.095483 +-0.043725 -0.060826 0.095290 +-0.042315 -0.061676 0.094883 +-0.040920 -0.062670 0.094528 +-0.039308 -0.063121 0.093822 +-0.037697 -0.063675 0.093182 +-0.036079 -0.064588 0.092681 +-0.034470 -0.065347 0.092110 +-0.032870 -0.066283 0.091630 +-0.031044 -0.067239 0.091035 +-0.029236 -0.068155 0.090430 +-0.027417 -0.069112 0.089843 +-0.025606 -0.069854 0.089167 +-0.023796 -0.070657 0.088510 +-0.021996 -0.071420 0.087849 +-0.020191 -0.072163 0.087181 +-0.018388 -0.072947 0.086533 +-0.017075 -0.074186 0.086358 +-0.015809 -0.075911 0.086406 +-0.014105 -0.074536 0.084870 +-0.012502 -0.074608 0.084013 +-0.010691 -0.075082 0.083208 +-0.008873 -0.075484 0.082378 +-0.007043 -0.075802 0.081501 +-0.005215 -0.076048 0.080577 +-0.003379 -0.076304 0.079660 +-0.001636 -0.077400 0.079152 +0.000128 -0.078227 0.078519 +0.001895 -0.079022 0.077867 +0.003535 -0.078936 0.076900 +0.005334 -0.077787 0.075393 +0.007125 -0.078397 0.074662 +0.008924 -0.078964 0.073890 +0.010594 -0.078834 0.072901 +0.012042 -0.078652 0.072007 +0.013747 -0.078457 0.070975 +0.015641 -0.078543 0.069953 +0.017539 -0.078660 0.068944 +0.019492 -0.078516 0.067800 +0.021173 -0.078570 0.066880 +0.022659 -0.078415 0.065988 +0.024373 -0.078375 0.065026 +0.026086 -0.078344 0.064049 +-0.055255 -0.056613 0.101893 +-0.052835 -0.056826 0.100629 +-0.048453 -0.057192 0.098341 +-0.045532 -0.058090 0.097109 +-0.044108 -0.059154 0.096782 +-0.042680 -0.060537 0.096597 +-0.041279 -0.061654 0.096298 +-0.039656 -0.062823 0.095905 +-0.037811 -0.063284 0.095090 +-0.035972 -0.063972 0.094365 +-0.034135 -0.064978 0.093788 +-0.032306 -0.065965 0.093205 +-0.030484 -0.066890 0.092598 +-0.028668 -0.067755 0.091966 +-0.026863 -0.068774 0.091412 +-0.025051 -0.069598 0.090768 +-0.023237 -0.070350 0.090106 +-0.021434 -0.071206 0.089490 +-0.019630 -0.071939 0.088823 +-0.017830 -0.072692 0.088162 +-0.016071 -0.074004 0.087762 +-0.014305 -0.074976 0.087208 +-0.012991 -0.075885 0.086872 +-0.011521 -0.074675 0.085542 +-0.009703 -0.075005 0.084680 +-0.007882 -0.075365 0.083830 +-0.006071 -0.075777 0.082993 +-0.004250 -0.076138 0.082143 +-0.002422 -0.076446 0.081252 +-0.000636 -0.077086 0.080527 +0.001203 -0.077300 0.079590 +0.002917 -0.078450 0.079118 +0.004694 -0.079123 0.078421 +0.006285 -0.079431 0.077660 +0.007940 -0.077700 0.075989 +0.009556 -0.077914 0.075181 +0.011354 -0.078471 0.074409 +0.013199 -0.078798 0.073530 +0.015158 -0.078447 0.072282 +0.017120 -0.078179 0.071079 +0.019044 -0.078150 0.070003 +0.020993 -0.078098 0.068898 +0.022932 -0.078016 0.067787 +0.024913 -0.077879 0.066626 +0.026879 -0.077795 0.065499 +-0.054070 -0.055909 0.102929 +-0.051648 -0.056205 0.101710 +-0.047710 -0.056714 0.099743 +-0.045006 -0.057878 0.098746 +-0.043341 -0.059188 0.098399 +-0.041710 -0.059894 0.097799 +-0.040303 -0.061402 0.097674 +-0.038678 -0.062591 0.097293 +-0.036837 -0.063639 0.096728 +-0.034997 -0.063772 0.095773 +-0.033166 -0.064789 0.095203 +-0.031349 -0.065725 0.094603 +-0.029528 -0.066703 0.094029 +-0.027712 -0.067557 0.093397 +-0.025905 -0.068463 0.092792 +-0.024093 -0.069411 0.092213 +-0.022292 -0.070256 0.091583 +-0.020485 -0.071010 0.090929 +-0.018694 -0.071949 0.090360 +-0.017151 -0.073116 0.090017 +-0.015844 -0.074303 0.089817 +-0.014293 -0.074935 0.089236 +-0.012479 -0.075224 0.088362 +-0.010685 -0.075649 0.087561 +-0.008795 -0.075131 0.086299 +-0.006952 -0.075161 0.085293 +-0.005145 -0.075666 0.084508 +-0.003350 -0.076182 0.083725 +-0.001502 -0.076273 0.082743 +0.000318 -0.076633 0.081879 +0.002187 -0.076661 0.080856 +0.003958 -0.077354 0.080165 +0.005674 -0.078452 0.079674 +0.007431 -0.079198 0.079017 +0.009040 -0.079403 0.078217 +0.010716 -0.077609 0.076505 +0.012380 -0.077542 0.075556 +0.014196 -0.078057 0.074778 diff --git a/mne-python/source/mne/io/kit/tests/data/test.sqd b/mne-python/source/mne/io/kit/tests/data/test.sqd new file mode 100644 index 0000000000000000000000000000000000000000..7b5ebf64b1b97d359d9c7fe5208d2e8b93840713 --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/test.sqd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:59075fa2d7459743b4ad1bdbbee2e230dde6b11a1bb0b316b092ec19f44f1606 +size 828852 diff --git a/mne-python/source/mne/io/kit/tests/data/test_Ykgw.mat b/mne-python/source/mne/io/kit/tests/data/test_Ykgw.mat new file mode 100644 index 0000000000000000000000000000000000000000..9c81354a77d2dfe48a1d60fac839355558146fce --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/test_Ykgw.mat @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:784fe0ccfde7a3f9723504a88cd5aaed85483ec41aa3118c3bb92e09989fa82c +size 2212272 diff --git a/mne-python/source/mne/io/kit/tests/data/test_bin_raw.fif b/mne-python/source/mne/io/kit/tests/data/test_bin_raw.fif new file mode 100644 index 0000000000000000000000000000000000000000..515b89e4cc6eead8685146026d809bf2ca50cc62 --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/test_bin_raw.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e8270f47908b8db4dd5c808eb686749630cf522553697dded8a4c37f8be013a7 +size 1546456 diff --git a/mne-python/source/mne/io/kit/tests/data/test_elp.txt b/mne-python/source/mne/io/kit/tests/data/test_elp.txt new file mode 100644 index 0000000000000000000000000000000000000000..1c4a23656d07d5bb4fc48eef8839b328f7a31020 --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/test_elp.txt @@ -0,0 +1,11 @@ +% Ascii stylus data file created by FastSCAN V4.0.7 on Thu May 31 13:04:52 2012 +% raw surface, 8 visible points, bounding box reference +% x y z + 1.3930 13.1613 -4.6967 + -62.4997 -73.7271 79.9600 + -74.8957 87.3785 81.1943 + -59.5004 -70.4836 75.8930 + -64.6373 83.8228 76.2123 + -13.5035 7.2522 -26.8405 + -20.2967 -35.1498 -12.9305 + -27.7519 45.2628 -22.2407 diff --git a/mne-python/source/mne/io/kit/tests/data/test_hsp.txt b/mne-python/source/mne/io/kit/tests/data/test_hsp.txt new file mode 100644 index 0000000000000000000000000000000000000000..1965f967f99fa3e548c39670599df3977c73b139 --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/data/test_hsp.txt @@ -0,0 +1,504 @@ +% Copyright (c) 1995-2012, Applied Research Associates NZ Ltd. All rights reserved. +% Ascii 3D points file created by FastSCAN V4.0.7 on Thu May 31 13:04:40 2012 +% Raw(separate)Exp(b,p,CRLF) +% 346306 3D points, x y z per line + -106.93 99.80 68.81 + -106.28 100.26 67.09 + -105.16 100.67 66.55 + -106.53 99.70 66.04 + -105.17 100.15 65.40 + -106.39 98.95 64.85 + -105.40 99.77 64.16 + -104.02 99.87 63.67 + -104.74 99.11 62.77 + -103.62 99.72 62.13 + -136.60 80.86 57.38 + -137.22 80.32 56.79 + -136.37 80.84 56.27 + -139.31 78.86 57.10 + -138.44 79.33 56.59 + -137.63 79.78 56.11 + -136.92 80.45 55.57 + -135.97 80.63 55.16 + -140.13 78.11 56.54 + -139.40 78.74 56.01 + -138.64 79.28 55.51 + -137.85 79.78 55.01 + -136.94 80.53 54.36 + -136.01 80.76 53.95 + -140.73 77.69 55.63 + -139.76 78.60 54.89 + -138.81 79.41 54.20 + -137.61 80.12 53.47 + -136.40 80.81 52.75 + -134.96 80.33 52.48 + -133.34 80.00 52.07 + -131.81 80.37 51.39 + -130.27 80.94 50.62 + -129.09 81.45 49.99 + -127.23 82.17 49.04 + -123.71 83.50 47.27 + -120.54 84.75 45.65 + -111.40 88.41 40.93 + -147.06 74.00 58.00 + -145.41 74.70 57.11 + -144.13 75.35 56.38 + -142.99 75.81 55.78 + -141.97 76.62 55.07 + -141.19 77.78 54.28 + -139.82 78.18 53.64 + -138.96 79.54 52.73 + -137.76 80.24 52.00 + -136.66 81.11 51.23 + -134.88 80.24 51.02 + -133.32 79.79 50.70 + -132.05 80.37 50.01 + -130.73 80.86 49.34 + -129.40 81.34 48.68 + -128.08 81.83 48.01 + -126.74 82.30 47.35 + -125.39 82.74 46.70 + -124.08 83.24 46.04 + -122.74 83.72 45.38 + -121.14 84.20 44.62 + -119.74 85.01 43.79 + -117.88 85.95 42.74 + -115.21 86.88 41.42 + -113.10 87.43 40.46 + -112.12 87.60 40.05 + -152.91 71.19 59.57 + -151.50 71.86 58.79 + -150.30 72.61 58.04 + -149.06 73.27 57.32 + -147.78 73.84 56.62 + -146.51 74.43 55.93 + -145.24 75.02 55.22 + -144.00 75.64 54.51 + -142.72 76.19 53.82 + -141.78 77.42 52.95 + -140.40 77.79 52.31 + -139.44 78.95 51.46 + -138.35 79.86 50.68 + -137.26 80.76 49.90 + -135.88 81.11 49.27 + -133.67 79.93 49.05 + -132.28 80.28 48.42 + -130.98 80.81 47.74 + -129.65 81.28 47.08 + -128.31 81.73 46.43 + -126.99 82.22 45.77 + -125.67 82.72 45.10 + -124.33 83.19 44.44 + -122.97 83.59 43.80 + -121.62 84.03 43.15 + -120.36 84.62 42.46 + -119.20 85.38 41.73 + -118.00 86.07 41.02 + -116.44 86.16 40.45 + -114.87 86.26 39.87 + -113.58 86.36 39.39 + -155.81 69.77 59.31 + -154.17 70.68 58.34 + -152.54 71.63 57.36 + -150.89 72.50 56.40 + -149.22 73.34 55.45 + -147.53 74.11 54.52 + -145.88 74.96 53.57 + -144.24 75.83 52.61 + -143.15 76.75 51.82 + -142.69 78.40 50.93 + -140.45 77.58 50.52 + -139.40 79.05 49.50 + -138.20 80.24 48.56 + -136.64 81.24 47.58 + -134.63 80.42 47.26 + -132.86 80.07 46.81 + -131.10 80.72 45.92 + -129.36 81.40 45.03 + -127.57 81.98 44.16 + -125.81 82.64 43.28 + -124.07 83.32 42.39 + -122.33 84.00 41.50 + -120.38 84.32 40.69 + -118.62 84.96 39.81 + -116.52 85.06 39.05 + -114.81 85.37 38.33 + -159.09 67.93 59.18 + -157.48 69.01 58.15 + -155.86 69.97 57.17 + -154.27 70.97 56.17 + -152.63 71.86 55.21 + -150.97 72.72 54.26 + -149.31 73.56 53.30 + -147.64 74.37 52.37 + -146.00 75.24 51.41 + -144.55 75.94 50.59 + -144.40 78.20 49.53 + -143.81 79.07 48.94 + -141.38 77.36 48.85 + -139.81 77.83 48.10 + -139.05 79.86 46.94 + -137.42 80.71 46.00 + -135.91 81.29 45.22 + -133.79 80.29 44.94 + -132.01 80.39 44.29 + -130.22 80.97 43.42 + -128.51 81.71 42.52 + -126.74 82.32 41.64 + -124.95 82.93 40.77 + -123.12 83.43 39.92 + -121.17 83.75 39.11 + -119.37 84.33 38.25 + -117.38 84.60 37.44 + -115.39 84.89 36.63 + -113.90 85.10 36.02 + -162.35 66.02 58.96 + -160.79 67.16 57.92 + -159.22 68.24 56.90 + -157.65 69.32 55.88 + -155.99 70.18 54.93 + -154.39 71.15 53.94 + -152.80 72.14 52.95 + -151.15 73.00 52.00 + -149.47 73.76 51.07 + -147.81 74.58 50.13 + -146.20 75.49 49.16 + -145.98 79.16 47.47 + -144.10 78.47 47.11 + -141.83 77.07 46.93 + -140.09 77.72 46.04 + -139.06 79.71 44.80 + -137.39 80.47 43.89 + -135.61 81.04 43.03 + -132.90 79.92 42.59 + -131.12 80.52 41.72 + -129.27 81.00 40.88 + -127.65 81.86 39.94 + -125.91 82.54 39.05 + -124.07 83.03 38.21 + -121.98 83.10 37.46 + -120.32 83.92 36.53 + -118.31 84.13 35.75 + -116.33 84.43 34.93 + -114.35 84.73 34.12 + -112.62 85.00 33.40 + -167.07 63.42 59.60 + -165.19 64.26 58.58 + -163.63 65.48 57.50 + -162.08 66.64 56.46 + -160.52 67.74 55.43 + -158.98 68.85 54.40 + -157.39 69.87 53.41 + -155.76 70.78 52.44 + -154.12 71.65 51.48 + -152.52 72.59 50.51 + -150.84 73.37 49.58 + -149.15 74.09 48.66 + -147.56 75.04 47.68 + -147.75 78.50 46.23 + -147.02 79.60 45.50 + -145.50 78.61 45.39 + -143.26 76.73 45.42 + -141.40 77.14 44.59 + -139.71 77.87 43.68 + -138.74 79.96 42.42 + -137.04 80.66 41.53 + -135.25 81.20 40.68 + -133.20 81.29 39.93 + -131.09 81.27 39.21 + -129.07 81.42 38.45 + -127.21 81.88 37.62 + -125.36 82.35 36.78 + -123.46 82.74 35.95 + -121.61 83.21 35.11 + -119.72 83.62 34.28 + -117.71 83.85 33.48 + -115.72 84.13 32.67 + -113.68 84.33 31.87 + -111.74 84.71 31.03 + -167.49 62.96 57.86 + -166.25 64.50 56.76 + -164.48 65.11 55.87 + -162.95 66.29 54.82 + -161.41 67.44 53.78 + -159.86 68.54 52.76 + -158.28 69.55 51.76 + -156.66 70.48 50.79 + -155.03 71.36 49.83 + -153.43 72.28 48.87 + -151.76 73.06 47.93 + -150.09 73.83 47.00 + -148.61 74.48 46.19 + -148.24 75.80 45.49 + -148.74 78.86 44.33 + -147.34 79.11 43.72 + -144.21 76.46 43.77 + -142.33 76.81 42.95 + -140.63 77.52 42.04 + -139.23 78.32 41.20 + -138.33 80.03 40.14 + -136.64 80.75 39.25 + -134.66 80.94 38.48 + -132.60 81.00 37.74 + -130.48 80.95 37.03 + -128.55 81.28 36.22 + -126.70 81.73 35.39 + -124.87 82.24 34.54 + -122.94 82.57 33.72 + -121.07 83.01 32.88 + -119.11 83.30 32.07 + -117.09 83.52 31.27 + -115.15 83.86 30.44 + -113.12 84.09 29.64 + -111.06 84.27 28.84 + -172.55 60.11 58.89 + -170.94 60.98 57.95 + -169.57 62.62 56.76 + -167.73 63.11 55.90 + -166.09 64.05 54.92 + -164.64 65.43 53.81 + -163.12 66.62 52.76 + -161.55 67.66 51.76 + -160.01 68.76 50.73 + -158.42 69.74 49.75 + -156.77 70.58 48.80 + -155.20 71.56 47.81 + -153.55 72.40 46.87 + -151.93 73.26 45.91 + -150.25 74.00 44.99 + -148.93 74.94 44.11 + -148.99 78.23 42.70 + -146.00 76.17 42.53 + -144.23 76.31 41.84 + -142.50 76.93 40.95 + -140.76 77.58 40.06 + -139.01 78.17 39.19 + -137.84 79.87 38.04 + -136.24 80.74 37.11 + -134.35 81.09 36.30 + -132.19 80.98 35.60 + -130.32 81.38 34.78 + -128.17 81.31 34.07 + -126.27 81.67 33.25 + -124.42 82.11 32.41 + -122.48 82.43 31.60 + -120.57 82.79 30.77 + -118.61 83.10 29.95 + -116.62 83.36 29.14 + -114.62 83.60 28.34 + -112.57 83.79 27.53 + -110.50 83.96 26.73 + -109.00 84.18 26.11 + -184.83 55.65 63.23 + -182.31 56.35 62.05 + -177.75 57.74 59.85 + -174.67 58.96 58.24 + -173.27 59.96 57.32 + -171.90 60.97 56.40 + -170.35 62.16 55.34 + -168.77 63.26 54.31 + -167.11 64.14 53.34 + -165.53 65.20 52.33 + -163.96 66.25 51.32 + -162.45 67.44 50.27 + -160.89 68.48 49.27 + -159.30 69.44 48.28 + -157.72 70.43 47.30 + -156.11 71.34 46.33 + -154.45 72.12 45.40 + -152.82 72.95 44.45 + -151.19 73.79 43.50 + -149.77 74.53 42.67 + -149.01 76.60 41.51 + -146.53 75.70 41.00 + -144.78 76.30 40.11 + -143.03 76.89 39.24 + -141.29 77.51 38.36 + -139.52 78.06 37.49 + -138.11 78.83 36.68 + -137.07 80.27 35.70 + -135.40 81.01 34.80 + -133.74 81.29 34.10 + -132.04 81.06 33.60 + -130.26 81.15 32.94 + -128.44 81.64 32.09 + -126.29 81.57 31.37 + -124.34 81.85 30.57 + -122.42 82.19 29.75 + -120.46 82.46 28.94 + -118.56 82.86 28.10 + -116.56 83.09 27.29 + -114.52 83.27 26.50 + -112.41 83.37 25.71 + -110.37 83.58 24.90 + -108.56 83.73 24.19 + -185.57 55.22 61.89 + -174.89 59.14 56.44 + -173.80 60.22 55.60 + -172.40 61.17 54.69 + -170.70 61.97 53.75 + -169.16 63.13 52.70 + -167.55 64.11 51.71 + -165.99 65.20 50.68 + -164.44 66.30 49.66 + -162.90 67.41 48.64 + -161.33 68.42 47.65 + -159.80 69.51 46.63 + -158.21 70.45 45.66 + -156.59 71.32 44.70 + -154.95 72.14 43.75 + -153.35 73.03 42.79 + -151.72 73.86 41.85 + -150.46 74.90 40.94 + -150.05 76.77 39.99 + -147.87 75.74 39.65 + -146.23 76.12 38.89 + -144.49 76.71 38.02 + -142.69 77.22 37.16 + -140.89 77.71 36.31 + -139.05 78.15 35.48 + -137.75 79.10 34.62 + -136.70 80.50 33.66 + -134.98 81.13 32.78 + -133.43 81.62 32.03 + -131.59 81.15 31.59 + -129.67 80.99 30.98 + -128.04 81.80 30.07 + -126.34 82.04 29.36 + -124.68 81.91 28.83 + -122.85 81.95 28.17 + -120.89 82.22 27.36 + -118.93 82.51 26.55 + -116.95 82.79 25.73 + -115.17 82.94 25.03 + -113.35 83.05 24.33 + -111.30 83.24 23.52 + -109.47 83.36 22.82 + -108.11 83.37 22.33 + -186.20 54.65 60.58 + -175.44 58.30 55.20 + -174.50 59.78 54.24 + -173.36 60.73 53.42 + -172.28 61.82 52.58 + -170.75 62.40 51.79 + -169.28 63.08 50.96 + -167.94 64.11 50.04 + -166.54 64.99 49.17 + -165.23 66.04 48.25 + -163.69 67.13 47.23 + -162.15 68.18 46.23 + -160.62 69.27 45.21 + -159.01 70.15 44.25 + -157.42 71.09 43.28 + -155.83 71.99 42.32 + -154.23 72.87 41.36 + -152.65 73.79 40.39 + -151.78 75.11 39.50 + -151.15 76.90 38.51 + -148.78 75.71 38.16 + -147.11 75.92 37.47 + -145.38 76.54 36.59 + -143.62 77.09 35.72 + -141.81 77.56 34.87 + -139.96 77.96 34.05 + -138.11 78.37 33.22 + -136.70 79.59 32.21 + -135.16 80.55 31.26 + -133.60 81.48 30.32 + -131.81 81.54 29.67 + -129.42 80.58 29.23 + -127.77 81.33 28.32 + -126.08 82.04 27.43 + -124.25 82.06 26.77 + -122.63 82.01 26.22 + -120.74 81.97 25.56 + -118.76 82.22 24.75 + -116.79 82.50 23.93 + -114.66 82.53 23.15 + -112.89 82.73 22.44 + -111.25 82.71 21.86 + -109.42 82.82 21.15 + -107.58 82.94 20.45 + -186.56 54.56 58.89 + -184.07 54.98 57.83 + -179.56 55.72 55.91 + -176.83 56.85 54.45 + -175.76 58.01 53.57 + -174.82 59.48 52.60 + -173.79 60.69 51.72 + -172.55 61.97 50.73 + -170.79 62.58 49.83 + -169.12 63.41 48.88 + -167.59 64.55 47.84 + -166.06 65.67 46.81 + -164.51 66.73 45.80 + -162.94 67.73 44.81 + -161.45 68.88 43.78 + -159.87 69.84 42.80 + -158.27 70.73 41.83 + -156.72 71.72 40.84 + -155.12 72.59 39.88 + -153.53 73.48 38.92 + -152.21 74.91 37.83 + -150.74 76.01 36.83 + -149.72 77.01 36.04 + -147.67 75.96 35.74 + -145.88 76.44 34.89 + -144.10 76.95 34.03 + -142.34 77.51 33.17 + -140.56 78.02 32.31 + -138.74 78.48 31.47 + -137.10 79.26 30.56 + -135.23 79.63 29.74 + -133.87 80.90 28.73 + -132.26 81.71 27.81 + -130.69 82.15 27.07 + -128.22 80.61 26.84 + -126.59 80.96 26.11 + -124.90 81.66 25.22 + -123.08 82.14 24.36 + -120.85 81.97 23.64 + -118.66 81.88 22.89 + -116.61 82.02 22.09 + -114.52 82.14 21.29 + -112.43 82.23 20.50 + -110.27 82.27 19.71 + -108.15 82.36 18.91 + -186.55 53.87 57.31 + -184.10 54.37 56.22 + -180.13 55.21 54.44 + -177.74 56.58 53.00 + -176.52 58.00 51.95 + -175.08 58.83 51.08 + -174.21 60.42 50.09 + -172.98 61.72 49.09 + -171.46 62.90 48.04 + -169.57 63.19 47.23 + -168.05 64.34 46.19 + -166.51 65.41 45.18 + -164.99 66.52 44.15 + -163.42 67.51 43.16 + -161.88 68.55 42.16 + -160.36 69.63 41.14 + -158.80 70.61 40.16 + -157.21 71.50 39.19 + -155.71 72.57 38.18 + -154.56 73.84 37.22 + -153.67 75.11 36.35 + -152.29 75.86 35.53 + -150.49 76.30 34.69 + -148.77 76.87 33.82 + -146.56 76.53 33.16 + -144.62 76.72 32.38 + -142.91 77.37 31.49 + -141.21 78.03 30.61 + -139.29 78.28 29.81 + -137.50 78.79 28.96 + -135.53 78.98 28.17 + -133.93 79.81 27.25 + -132.55 81.03 26.25 + -130.99 81.91 25.32 + -129.37 82.25 24.59 + -126.85 80.65 24.37 + -125.06 80.73 23.69 + -123.35 81.39 22.79 \ No newline at end of file diff --git a/mne-python/source/mne/io/kit/tests/data/test_mrk.sqd b/mne-python/source/mne/io/kit/tests/data/test_mrk.sqd new file mode 100644 index 0000000000000000000000000000000000000000..47ed5136f372ec2e52326b217a0a891e964dee59 Binary files /dev/null and b/mne-python/source/mne/io/kit/tests/data/test_mrk.sqd differ diff --git a/mne-python/source/mne/io/kit/tests/data/test_mrk_post.sqd b/mne-python/source/mne/io/kit/tests/data/test_mrk_post.sqd new file mode 100644 index 0000000000000000000000000000000000000000..52551f58399050a65c047a5a7ab69f1ca530814b Binary files /dev/null and b/mne-python/source/mne/io/kit/tests/data/test_mrk_post.sqd differ diff --git a/mne-python/source/mne/io/kit/tests/data/test_mrk_pre.sqd b/mne-python/source/mne/io/kit/tests/data/test_mrk_pre.sqd new file mode 100644 index 0000000000000000000000000000000000000000..2413a87d7b36e3fa18355912008ffbfdbff69515 Binary files /dev/null and b/mne-python/source/mne/io/kit/tests/data/test_mrk_pre.sqd differ diff --git a/mne-python/source/mne/io/kit/tests/data/test_umd-raw.sqd b/mne-python/source/mne/io/kit/tests/data/test_umd-raw.sqd new file mode 100644 index 0000000000000000000000000000000000000000..2d85ee8be96babdcc430ac80f6cbb343e2641e77 Binary files /dev/null and b/mne-python/source/mne/io/kit/tests/data/test_umd-raw.sqd differ diff --git a/mne-python/source/mne/io/kit/tests/data/trans-sample.fif b/mne-python/source/mne/io/kit/tests/data/trans-sample.fif new file mode 100644 index 0000000000000000000000000000000000000000..56e894b698abd3210fad01ee0e318a233a18db64 Binary files /dev/null and b/mne-python/source/mne/io/kit/tests/data/trans-sample.fif differ diff --git a/mne-python/source/mne/io/kit/tests/test_coreg.py b/mne-python/source/mne/io/kit/tests/test_coreg.py new file mode 100644 index 0000000000000000000000000000000000000000..2ffa7a1178af744abe0e704d5eef2b70f31c1188 --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/test_coreg.py @@ -0,0 +1,35 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import assert_array_equal + +from mne.io.kit import read_mrk + +mrk_fname = Path(__file__).parent / "data" / "test_mrk.sqd" + + +def test_io_mrk(tmp_path): + """Test IO for mrk files.""" + pts = read_mrk(mrk_fname) + + # txt + path = tmp_path / "mrk.txt" + with open(path, "wb") as fid: + fid.write(b"%% %d 3D points, x y z per line\n" % len(pts)) + np.savetxt(fid, pts, delimiter="\t", newline="\n") + + pts_2 = read_mrk(path) + assert_array_equal(pts, pts_2, "read/write mrk to text") + + # unsupported extension + fname = tmp_path / "file.ext" + with pytest.raises(FileNotFoundError, match="does not exist"): + read_mrk(fname) + fname.write_text("") + with pytest.raises(ValueError, match="file extension"): + read_mrk(fname) diff --git a/mne-python/source/mne/io/kit/tests/test_kit.py b/mne-python/source/mne/io/kit/tests/test_kit.py new file mode 100644 index 0000000000000000000000000000000000000000..6bd8cb83e84f32e78989fef48901dada700932fe --- /dev/null +++ b/mne-python/source/mne/io/kit/tests/test_kit.py @@ -0,0 +1,452 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path + +import numpy as np +import pytest +import scipy.io +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_equal, +) +from scipy import linalg + +import mne +from mne import Epochs, find_events, pick_types, read_events +from mne._fiff.constants import FIFF +from mne.datasets.testing import requires_testing_data +from mne.io import read_epochs_kit, read_raw_fif, read_raw_kit +from mne.io.kit.constants import KIT +from mne.io.kit.coreg import read_sns +from mne.io.kit.kit import get_kit_info +from mne.io.tests.test_raw import _test_raw_reader +from mne.surface import _get_ico_surface +from mne.transforms import apply_trans +from mne.utils import assert_dig_allclose + +data_dir = Path(__file__).parent / "data" +sqd_path = data_dir / "test.sqd" +sqd_umd_path = data_dir / "test_umd-raw.sqd" +epochs_path = data_dir / "test-epoch.raw" +events_path = data_dir / "test-eve.txt" +mrk_path = data_dir / "test_mrk.sqd" +mrk2_path = data_dir / "test_mrk_pre.sqd" +mrk3_path = data_dir / "test_mrk_post.sqd" +elp_txt_path = data_dir / "test_elp.txt" +hsp_txt_path = data_dir / "test_hsp.txt" +elp_path = data_dir / "test.elp" +hsp_path = data_dir / "test.hsp" + +data_path = mne.datasets.testing.data_path(download=False) +sqd_as_path = data_path / "KIT" / "test_as-raw.con" +yokogawa_path = data_path / "KIT" / "ArtificalSignalData_Yokogawa_1khz.con" +ricoh_path = data_path / "KIT" / "ArtificalSignalData_RICOH_1khz.con" +ricoh_systems_paths = [data_path / "KIT" / "Example_PQA160C_1001-export_anonymyze.con"] +ricoh_systems_paths += [ + data_path / "KIT" / "Example_RICOH160-1_10020-export_anonymyze.con" +] +ricoh_systems_paths += [ + data_path / "KIT" / "Example_RICOH160-1_10021-export_anonymyze.con" +] +ricoh_systems_paths += [ + data_path / "KIT" / "010409_Motor_task_coregist-export_tiny_1s.con" +] +berlin_path = data_path / "KIT" / "data_berlin.con" + + +@requires_testing_data +def test_data(tmp_path): + """Test reading raw kit files.""" + pytest.raises(TypeError, read_raw_kit, epochs_path) + pytest.raises(TypeError, read_epochs_kit, sqd_path) + pytest.raises(ValueError, read_raw_kit, sqd_path, mrk_path, elp_txt_path) + pytest.raises( + ValueError, read_raw_kit, sqd_path, None, None, None, list(range(200, 190, -1)) + ) + pytest.raises( + ValueError, + read_raw_kit, + sqd_path, + None, + None, + None, + list(range(167, 159, -1)), + "*", + 1, + True, + ) + # check functionality + raw_mrk = read_raw_kit(sqd_path, [mrk2_path, mrk3_path], elp_txt_path, hsp_txt_path) + assert ( + raw_mrk.info["description"] + == "NYU 160ch System since Jan24 2009 (34) V2R004 EQ1160C" # noqa: E501 + ) + raw_py = _test_raw_reader( + read_raw_kit, + input_fname=sqd_path, + mrk=mrk_path, + elp=elp_txt_path, + hsp=hsp_txt_path, + stim=list(range(167, 159, -1)), + slope="+", + stimthresh=1, + ) + assert "RawKIT" in repr(raw_py) + assert_equal(raw_mrk.info["kit_system_id"], KIT.SYSTEM_NYU_2010) + + # check number/kind of channels + assert_equal(len(raw_py.info["chs"]), 193) + kit_channels = ( + ( + "kind", + { + FIFF.FIFFV_MEG_CH: 157, + FIFF.FIFFV_REF_MEG_CH: 3, + FIFF.FIFFV_MISC_CH: 32, + FIFF.FIFFV_STIM_CH: 1, + }, + ), + ( + "coil_type", + { + FIFF.FIFFV_COIL_KIT_GRAD: 157, + FIFF.FIFFV_COIL_KIT_REF_MAG: 3, + FIFF.FIFFV_COIL_NONE: 33, + }, + ), + ) + for label, target in kit_channels: + actual = { + id_: sum(ch[label] == id_ for ch in raw_py.info["chs"]) + for id_ in target.keys() + } + assert_equal(actual, target) + + # Test stim channel + raw_stim = read_raw_kit( + sqd_path, mrk_path, elp_txt_path, hsp_txt_path, stim="<", preload=False + ) + for raw in [raw_py, raw_stim, raw_mrk]: + stim_pick = pick_types( + raw.info, meg=False, ref_meg=False, stim=True, exclude="bads" + ) + stim1, _ = raw[stim_pick] + stim2 = np.array(raw.read_stim_ch(), ndmin=2) + assert_array_equal(stim1, stim2) + + # Binary file only stores the sensor channels + py_picks = pick_types(raw_py.info, meg=True, exclude="bads") + raw_bin = data_dir / "test_bin_raw.fif" + raw_bin = read_raw_fif(raw_bin, preload=True) + bin_picks = pick_types(raw_bin.info, meg=True, stim=True, exclude="bads") + data_bin, _ = raw_bin[bin_picks] + data_py, _ = raw_py[py_picks] + + # this .mat was generated using the Yokogawa MEG Reader + data_Ykgw = data_dir / "test_Ykgw.mat" + data_Ykgw = scipy.io.loadmat(data_Ykgw)["data"] + data_Ykgw = data_Ykgw[py_picks] + + assert_array_almost_equal(data_py, data_Ykgw) + + py_picks = pick_types( + raw_py.info, meg=True, stim=True, ref_meg=False, exclude="bads" + ) + data_py, _ = raw_py[py_picks] + assert_array_almost_equal(data_py, data_bin) + + # KIT-UMD data + _test_raw_reader(read_raw_kit, input_fname=sqd_umd_path, test_rank="less") + raw = read_raw_kit(sqd_umd_path) + assert ( + raw.info["description"] + == "University of Maryland/Kanazawa Institute of Technology/160-channel MEG System (53) V2R004 PQ1160R" # noqa: E501 + ) + assert_equal(raw.info["kit_system_id"], KIT.SYSTEM_UMD_2014_12) + # check number/kind of channels + assert_equal(len(raw.info["chs"]), 193) + for label, target in kit_channels: + actual = { + id_: sum(ch[label] == id_ for ch in raw.info["chs"]) + for id_ in target.keys() + } + assert_equal(actual, target) + + # KIT Academia Sinica + raw = read_raw_kit(sqd_as_path, slope="+") + assert ( + raw.info["description"] + == "Academia Sinica/Institute of Linguistics//Magnetoencephalograph System (261) V2R004 PQ1160R-N2" # noqa: E501 + ) + assert_equal(raw.info["kit_system_id"], KIT.SYSTEM_AS_2008) + assert_equal(raw.info["chs"][100]["ch_name"], "MEG 101") + assert_equal(raw.info["chs"][100]["kind"], FIFF.FIFFV_MEG_CH) + assert_equal(raw.info["chs"][100]["coil_type"], FIFF.FIFFV_COIL_KIT_GRAD) + assert_equal(raw.info["chs"][157]["ch_name"], "MEG 158") + assert_equal(raw.info["chs"][157]["kind"], FIFF.FIFFV_REF_MEG_CH) + assert_equal(raw.info["chs"][157]["coil_type"], FIFF.FIFFV_COIL_KIT_REF_MAG) + assert_equal(raw.info["chs"][160]["ch_name"], "EEG 001") + assert_equal(raw.info["chs"][160]["kind"], FIFF.FIFFV_EEG_CH) + assert_equal(raw.info["chs"][160]["coil_type"], FIFF.FIFFV_COIL_EEG) + assert_array_equal(find_events(raw), [[91, 0, 2]]) + + +@requires_testing_data +def test_unknown_format(tmp_path): + """Test our warning about an unknown format.""" + fname = tmp_path / ricoh_path.name + _, kit_info = get_kit_info(ricoh_path, allow_unknown_format=False) + n_before = kit_info["dirs"][KIT.DIR_INDEX_SYSTEM]["offset"] + with open(fname, "wb") as fout: + with open(ricoh_path, "rb") as fin: + fout.write(fin.read(n_before)) + version, revision = np.fromfile(fin, " 2 # good + version = 1 # bad + np.array([version, revision], " 5000 + + # should have similar size, distance from center + dist = np.sqrt(np.sum((hsp_m - np.mean(hsp_m, axis=0)) ** 2, axis=1)) + dist_dec = np.sqrt(np.sum((hsp_dec - np.mean(hsp_dec, axis=0)) ** 2, axis=1)) + hsp_rad = np.mean(dist) + hsp_dec_rad = np.mean(dist_dec) + assert_array_almost_equal(hsp_rad, hsp_dec_rad, decimal=3) + + +@requires_testing_data +@pytest.mark.parametrize( + "fname, desc, system_id", + [ + (ricoh_systems_paths[0], "Meg160/Analysis (1001) V2R004 PQA160C", 1001), + (ricoh_systems_paths[1], "RICOH MEG System (10020) V3R000 RICOH160-1", 10020), + (ricoh_systems_paths[2], "RICOH MEG System (10021) V3R000 RICOH160-1", 10021), + ( + ricoh_systems_paths[3], + "Yokogawa Electric Corporation/MEG device for infants/151-channel MEG " + "System (903) V2R004 PQ1151R", + 903, + ), + ], +) +def test_raw_system_id(fname, desc, system_id): + """Test reading basics and system IDs.""" + raw = _test_raw_reader(read_raw_kit, input_fname=fname) + assert raw.info["description"] == desc + assert raw.info["kit_system_id"] == system_id + + +@requires_testing_data +def test_berlin(): + """Test data from Berlin.""" + # gh-8535 + raw = read_raw_kit(berlin_path) + assert ( + raw.info["description"] + == "Physikalisch Technische Bundesanstalt, Berlin/128-channel MEG System (124) V2R004 PQ1128R-N2" # noqa: E501 + ) + assert raw.info["kit_system_id"] == 124 + assert raw.info["highpass"] == 0.0 + assert raw.info["lowpass"] == 200.0 + assert raw.info["sfreq"] == 500.0 + n = int(round(28.77 * raw.info["sfreq"])) + meg = raw.get_data("MEG 003", n, n + 1)[0, 0] + assert_allclose(meg, -8.89e-12, rtol=1e-3) + eeg = raw.get_data("E14", n, n + 1)[0, 0] + assert_allclose(eeg, -2.55, rtol=1e-3) diff --git a/mne-python/source/mne/io/mef/__init__.py b/mne-python/source/mne/io/mef/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..41a511775729a3dd8f8a29fb8d70ac8552e0db7e --- /dev/null +++ b/mne-python/source/mne/io/mef/__init__.py @@ -0,0 +1,7 @@ +"""MEF3 file import module.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .mef import read_raw_mef diff --git a/mne-python/source/mne/io/mef/_utils.py b/mne-python/source/mne/io/mef/_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..aa6b5cc04678d21a3df84b4ec884eb307fe26c1e --- /dev/null +++ b/mne-python/source/mne/io/mef/_utils.py @@ -0,0 +1,345 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np + +_UNIT_SCALE_FACTORS = { + "v": 1.0, + "volt": 1.0, + "volts": 1.0, + "uv": 1e-6, + "uvolt": 1e-6, + "uvolts": 1e-6, + "microv": 1e-6, + "microvolt": 1e-6, + "microvolts": 1e-6, + "mv": 1e-3, + "mvolt": 1e-3, + "millivolt": 1e-3, + "millivolts": 1e-3, + "nv": 1e-9, + "nvolt": 1e-9, + "nanovolt": 1e-9, + "nanovolts": 1e-9, + "kv": 1e3, + "kilovolt": 1e3, + "kilovolts": 1e3, +} + +_UUTC_NO_ENTRY = 0x800000000000 +_GMT_OFFSET_NO_ENTRY = -86401 + + +def _mef_get(md, key, *, kind=None, default=None): + """Safely extract and convert a value from MEF metadata. + + Parameters + ---------- + md : dict | object + The metadata dictionary or object. + key : str + The key to look up. + kind : str | None + The expected type ('text', 'int', 'float'). + default : any + The default value if the key is missing or conversion fails. + + Returns + ------- + value : any + The extracted and converted value. + """ + if md is None: + return default + try: + value = md.get(key) if isinstance(md, dict) else md[key] + except (KeyError, TypeError, AttributeError): + return default + if isinstance(value, np.ndarray) and value.size > 0: + value = value.ravel()[0] + if value is None: + return default + if kind == "text": + if isinstance(value, (bytes, np.bytes_)): + value = value.decode("utf-8", errors="ignore") + return str(value).strip().strip("\x00") + if kind in ("int", "float"): + try: + return int(value) if kind == "int" else float(value) + except (TypeError, ValueError): + return default + return value + + +def _get_mef_units_scale(unit_desc, unit_factor): + """Normalize unit description and calculate the scaling factor to Volts. + + Parameters + ---------- + unit_desc : str + The unit description (e.g., 'uV', 'mV'). + unit_factor : float + The multiplier for the units. + + Returns + ------- + scale : float + The total scaling factor to convert data to Volts. + unit_desc : str + The original unit description. + unit_desc_norm : str + The normalized unit description. + unit_factor_valid : bool + True if the unit factor is valid (finite and > 0). + unit_known : bool + True if the unit description is recognized. + """ + if isinstance(unit_desc, np.ndarray): + unit_desc = unit_desc.ravel()[0] + if unit_desc is None: + unit_desc = "" + if isinstance(unit_desc, (bytes, np.bytes_)): + unit_desc = unit_desc.decode("utf-8", errors="ignore") + unit_desc = str(unit_desc).strip().strip("\x00") + if unit_desc: + # Normalize unit string for lookup + unit_desc_norm = unit_desc.lower().replace(" ", "") + # Replace common micro symbols with 'u' + unit_desc_norm = unit_desc_norm.replace("\N{MICRO SIGN}", "u") + unit_desc_norm = unit_desc_norm.replace("\N{GREEK SMALL LETTER MU}", "u") + else: + unit_desc_norm = "" + + if isinstance(unit_factor, np.ndarray): + unit_factor = unit_factor.ravel()[0] + try: + unit_factor = float(unit_factor) + except (TypeError, ValueError): + unit_factor = np.nan + unit_factor_valid = np.isfinite(unit_factor) and unit_factor > 0 + if not unit_factor_valid: + unit_factor = 1.0 + unit_scale = _UNIT_SCALE_FACTORS.get(unit_desc_norm) + scale = unit_factor * (unit_scale if unit_scale is not None else 1.0) + return ( + scale, + unit_desc, + unit_desc_norm, + unit_factor_valid, + unit_scale is not None, + ) + + +def _mef_time_metadata_extras(section_3): + """Extract session-level time metadata (offsets, DST info).""" + extras = {} + recording_time_offset = _mef_get(section_3, "recording_time_offset", kind="int") + if recording_time_offset not in (None, _UUTC_NO_ENTRY): + extras["recording_time_offset"] = int(recording_time_offset) + dst_start_time = _mef_get(section_3, "DST_start_time", kind="int") + if dst_start_time not in (None, _UUTC_NO_ENTRY): + extras["dst_start_time"] = int(dst_start_time) + dst_end_time = _mef_get(section_3, "DST_end_time", kind="int") + if dst_end_time not in (None, _UUTC_NO_ENTRY): + extras["dst_end_time"] = int(dst_end_time) + return extras + + +def _convert_record(record, session): + """Ensure a MEF record is in dictionary format. + + If it's already a dict with a 'type', return it. Otherwise, try to convert it + using the session's internal conversion method. + """ + if isinstance(record, dict) and "type" in record: + return record + if isinstance(record, dict) and "record_header" in record: + try: + return session._create_dict_record(record) + except Exception: + # We don't know what this might raise, so we catch all + return None + return None + + +def _iter_records(session, ts_channels): + """Iterate over all records in a MEF session (session, channel, and segment levels). + + Yields + ------ + record : dict + The record metadata. + ch_name : str | None + The channel name if the record is at the channel or segment level. + seg_name : str | None + The segment name if the record is at the segment level. + """ + session_records = session.session_md.get("records_info", {}).get("records", []) + for record in session_records: + yield record, None, None + if isinstance(ts_channels, dict): + for ch_name, ch_md in ts_channels.items(): + ch_records = ch_md.get("records_info", {}).get("records", []) + for record in ch_records: + yield record, ch_name, None + for seg_name, seg_md in ch_md.get("segments", {}).items(): + seg_records = seg_md.get("records_info", {}).get("records", []) + for record in seg_records: + yield record, ch_name, seg_name + + +def _records_to_annotations(session, ts_channels, start_uutc): + """Convert MEF records to MNE annotation components. + + Parameters + ---------- + session : MefSession + The MEF session object. + ts_channels : dict + The time series channels metadata. + start_uutc : int + The earliest start time of the recording in UUTC microseconds. + + Returns + ------- + onsets : list of float + Annotation onsets in seconds. + durations : list of float + Annotation durations in seconds. + descriptions : list of str + Annotation descriptions. + ch_names : list of list of str + Channel names (if any) associated with each annotation. + extras_list : list of dict + Additional metadata for each annotation. + """ + if start_uutc is None: + return [], [], [], [], [] + + onsets = [] + durations = [] + descriptions = [] + ch_names = [] + extras_list = [] + for record, channel, segment in _iter_records(session, ts_channels): + record = _convert_record(record, session) + if record is None: + continue + + # Extract record type and detailed description + record_type = _mef_get(record, "type", kind="text", default="") + detail = "" + for key in ("text", "annotation", "epoch_type", "name"): + detail = _mef_get(record, key, kind="text", default="") + if detail: + break + description = record_type or "MEF" + if detail: + description = f"{description}: {detail}" + + # Resolve onset timestamp + onset_uutc = ( + _mef_get(record, "time") + or _mef_get(record, "timestamp") + or _mef_get(record, "earliest_onset") + ) + if onset_uutc is None or onset_uutc == _UUTC_NO_ENTRY: + continue + + # Resolve duration + duration_uutc = _mef_get(record, "duration") + if duration_uutc is None: + end_timestamp = _mef_get(record, "end_timestamp") + timestamp = _mef_get(record, "timestamp") + latest_offset = _mef_get(record, "latest_offset") + earliest_onset = _mef_get(record, "earliest_onset") + if end_timestamp is not None and timestamp is not None: + duration_uutc = end_timestamp - timestamp + elif latest_offset is not None and earliest_onset is not None: + duration_uutc = latest_offset - earliest_onset + else: + duration_uutc = 0 + + # Convert to seconds relative to session start + try: + onset = (float(onset_uutc) - float(start_uutc)) / 1e6 + duration = max(float(duration_uutc), 0.0) / 1e6 + except (TypeError, ValueError): + continue + + onsets.append(onset) + durations.append(duration) + descriptions.append(description) + ch_names.append([channel] if channel else []) + extras_list.append( + { + k: v + for k, v in [ + ("detail", detail), + ("channel", channel), + ("segment", segment), + ] + if v + } + ) + return onsets, durations, descriptions, ch_names, extras_list + + +def _toc_to_gap_annotations(toc, sfreq): + """Identify data gaps from the Table of Contents (TOC). + + The TOC stores the start sample and number of samples for each continuous block. + Gaps between these blocks are converted to 'BAD_ACQ_SKIP' annotations. + + Parameters + ---------- + toc : np.ndarray + The TOC array from pymef. + sfreq : float + The sampling frequency. + + Returns + ------- + onsets : list of float + Onset of each gap in seconds. + durations : list of float + Duration of each gap in seconds. + """ + if toc is None or toc.size == 0: + return [], [] + + # The Table of Contents (TOC) array contains multiple columns. + # We extract the start samples and the number of samples for each continuous block. + start_samples = toc[2] # Column 2: Start sample index of the block + n_samples = toc[1] # Column 1: Number of samples in the block + + # Ensure blocks are processed in chronological order based on start samples + order = np.argsort(start_samples) + start_samples = start_samples[order] + n_samples = n_samples[order] + + onsets = [] + durations = [] + + # Initialize trackers with the first block + prev_start = start_samples[0] + prev_n = n_samples[0] + + # Compare each block with the previous one to find discontinuities (gaps) + for start, n_samp in zip(start_samples[1:], n_samples[1:]): + # The next sample we expect to see if there were no gap + expected = prev_start + prev_n + + # Calculate the gap size in samples + gap = start - expected + if gap > 0: + # If a gap exists, store the onset (where the expected sample was) + # and the duration, both converted to seconds using the sampling frequency. + onsets.append(expected / sfreq) + durations.append(gap / sfreq) + + # Update trackers for the next iteration + prev_start = start + prev_n = n_samp + return onsets, durations diff --git a/mne-python/source/mne/io/mef/mef.py b/mne-python/source/mne/io/mef/mef.py new file mode 100644 index 0000000000000000000000000000000000000000..7756013684c68fc4cdcd0e891aacb9c6225df8d4 --- /dev/null +++ b/mne-python/source/mne/io/mef/mef.py @@ -0,0 +1,300 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Read MEF3 files.""" + +import datetime as dt + +import numpy as np + +from ..._fiff.meas_info import create_info +from ..._fiff.utils import _mult_cal_one +from ...annotations import Annotations +from ...utils import _check_fname, _soft_import, fill_doc, logger, verbose +from ..base import BaseRaw +from ._utils import ( + _GMT_OFFSET_NO_ENTRY, + _UUTC_NO_ENTRY, + _get_mef_units_scale, + _mef_get, + _records_to_annotations, + _toc_to_gap_annotations, +) + + +@fill_doc +class RawMEF(BaseRaw): + """Raw object for MEF3 files. + + Parameters + ---------- + fname : path-like + Path to the MEF3 ``.mefd`` directory. + password : str | bytes | None + Password for encrypted MEF sessions. Use an empty string for + unencrypted data. + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + @verbose + def __init__(self, fname, password="", *, preload=False, verbose=None): + pymef = _soft_import("pymef", "reading MEF3 files", strict=True) + + # This type of dataset is a directory! + fname = _check_fname(fname, "read", True, "fname", need_dir=True) + # The dataset maybe have password + password = ( + (password or "").decode() + if isinstance(password, bytes) + else (password or "") + ) + # Open the dataset + session = pymef.mef_session.MefSession(str(fname), password) + + # Get the time series channels + ts_channels = session.session_md["time_series_channels"] + if not ts_channels: + raise ValueError("No time series channels found in MEF session.") + + ch_names = list(ts_channels.keys()) + logger.info("Reading %s: %d channels", fname, len(ch_names)) + + # Extract per-channel metadata + sfreqs, n_samples_list, unit_scales, orig_units = [], [], [], {} + for ch_name in ch_names: + ch_md = ts_channels[ch_name]["section_2"] + sfreq = _mef_get(ch_md, "sampling_frequency", kind="float") + n_samp = _mef_get(ch_md, "number_of_samples", kind="int") + if not (sfreq and np.isfinite(sfreq)) or n_samp is None: + raise ValueError(f"MEF metadata incomplete for {ch_name!r}.") + sfreqs.append(sfreq) + n_samples_list.append(n_samp) + scale, unit_desc, *_ = _get_mef_units_scale( + _mef_get(ch_md, "units_description"), + _mef_get(ch_md, "units_conversion_factor"), + ) + unit_scales.append(scale) + if unit_desc: + orig_units[ch_name] = unit_desc + + if len(set(sfreqs)) != 1: + raise ValueError( + f"MEF channels have inconsistent sfreq: {set(sfreqs)}, " + "this is not supported." + ) + if len(set(n_samples_list)) != 1: + raise ValueError( + f"MEF channels have inconsistent n_samples: {set(n_samples_list)}, " + "this is not supported." + ) + + sfreq, n_samp = sfreqs[0], n_samples_list[0] + + # Create info + info = create_info(ch_names=ch_names, sfreq=sfreq, ch_types="seeg") + for scale, ch in zip(unit_scales, info["chs"]): + ch["cal"] = scale + + # Extract session metadata + session_md = session.session_md + ts_meta = session_md.get("time_series_metadata", {}) + + # Section 3 is a dictionary with the session metadata + # Documentation reference: + # https://github.com/msel-source/pymef/blob/89e1eb22847320b3585354b15d6361b71315bf33/pymef/mef_file/pymef3_file.h#L52 + sec3 = ts_meta.get("section_3") or next(iter(ts_channels.values()), {}).get( + "section_3" + ) + + # Get start time + start_uutc = _mef_get( + session_md.get("session_specific_metadata", {}), + "earliest_start_time", + kind="int", + ) + if start_uutc in (None, _UUTC_NO_ENTRY): + starts = [ + _mef_get( + ch.get("channel_specific_metadata", {}), + "earliest_start_time", + kind="int", + ) + for ch in ts_channels.values() + ] + starts = [s for s in starts if s is not None and s != _UUTC_NO_ENTRY] + start_uutc = min(starts) if starts else None + + # Indexing the start time + meas_date = ( + ( + dt.datetime(1970, 1, 1, tzinfo=dt.timezone.utc) + + dt.timedelta(microseconds=int(start_uutc)) + ) + if start_uutc + else None + ) + + # Set info fields + # following the style of how is make in the other mne io readers + with info._unlock(): + if meas_date: + info["meas_date"] = meas_date + # Indexing the GMT offset + gmt = _mef_get(sec3, "GMT_offset", kind="int") + # If the GMT offset is not None and is not the default value and is + # not too large + if gmt is not None and gmt != _GMT_OFFSET_NO_ENTRY and abs(gmt) <= 86400: + # Convert GMT offset (in seconds) to a string in ±HHMM format + info["utc_offset"] = ( + f"{'+' if gmt >= 0 else '-'}" + f"{abs(gmt) // 3600:02d}" + f"{(abs(gmt) % 3600) // 60:02d}" + ) + for key, mef_key in [ + ("description", "session_description"), + ("subject_info", None), + ]: + # Parsing the subject info, and session description + # (official support by mne info) + if key == "subject_info": + subj = {} + for k, m in [ + ("his_id", "subject_ID"), + ("first_name", "subject_name_1"), + ("last_name", "subject_name_2"), + ]: + v = _mef_get(sec3, m, kind="text", default="") + if v: + subj[k] = v + if subj: + info["subject_info"] = subj + else: + # Parsing the session description (officialt support by mne info) + v = _mef_get( + ts_meta.get("section_2"), mef_key, kind="text", default="" + ) + if v: + info[key] = v + + super().__init__( + info=info, + last_samps=[n_samp - 1], + filenames=[str(fname)], + preload=preload, + raw_extras=[ + { + "n_channels": len(ch_names), + "ch_names": ch_names, + "password": password, + } + ], + orig_units=orig_units, + ) + + # Build annotations + annotations_data = [] + try: + toc = session.get_channel_toc(ch_names[0]) + except KeyError: + # 'segments' or 'TOC' key missing in channel metadata + logger.info( + "Could not read TOC for %s: missing segment metadata", ch_names[0] + ) + else: + gap_onsets, gap_durs = _toc_to_gap_annotations(toc, sfreq) + annotations_data.extend( + (o, d, "BAD_ACQ_SKIP", [], {"source": "toc"}) + for o, d in zip(gap_onsets, gap_durs) + ) + + if start_uutc: + rec_data = _records_to_annotations(session, ts_channels, start_uutc) + annotations_data.extend( + (o, d, desc, chs, {**ex, "source": "record"}) + for o, d, desc, chs, ex in zip(*rec_data) + ) + + if annotations_data: + annotations_data.sort(key=lambda x: x[0]) + self.set_annotations( + Annotations( + onset=[a[0] for a in annotations_data], + duration=[a[1] for a in annotations_data], + description=[a[2] for a in annotations_data], + ch_names=[a[3] for a in annotations_data], + orig_time=meas_date, + ) + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + from pymef.mef_session import MefSession + + extras = self._raw_extras[fi] + ch_names = extras["ch_names"] + session = MefSession(str(self._filenames[fi]), extras.get("password", "")) + + ch_indices = ( + range(*idx.indices(extras["n_channels"])) if isinstance(idx, slice) else idx + ) + selected = [ch_names[i] for i in ch_indices] + + if stop > start: + raw_data = np.array( + session.read_ts_channels_sample(selected, [start, stop]), + dtype=np.float64, + ) + else: + raw_data = np.empty((len(selected), 0), dtype=np.float64) + + block_out = np.zeros((extras["n_channels"], stop - start), dtype=data.dtype) + block_out[idx] = raw_data + _mult_cal_one(data, block_out, idx, cals, mult) + + +@verbose +def read_raw_mef(fname, *, password="", preload=False, verbose=None) -> RawMEF: + """Read raw data from MEF3 files. + + Parameters + ---------- + fname : path-like + Path to the MEF3 ``.mefd`` directory. + password : str | bytes | None + Password for encrypted MEF sessions. Use an empty string for + unencrypted data. + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawMEF + The raw instance. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawMEF. + + Notes + ----- + .. versionadded:: 1.12 + + Data is read using the `pymef package `__. + + Channel types default to sEEG (stereo-EEG). Use :meth:`raw.set_channel_types() + ` to set appropriate types after loading. + + Examples + -------- + Read a MEF3 file:: + + >>> raw = mne.io.read_raw_mef('recording.mefd') # doctest: +SKIP + """ + return RawMEF(fname, password=password, preload=preload, verbose=verbose) diff --git a/mne-python/source/mne/io/mef/tests/__init__.py b/mne-python/source/mne/io/mef/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/mef/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/mef/tests/test_mef.py b/mne-python/source/mne/io/mef/tests/test_mef.py new file mode 100644 index 0000000000000000000000000000000000000000..69b654b95c1bed299467ffafee0b2510402bf9b2 --- /dev/null +++ b/mne-python/source/mne/io/mef/tests/test_mef.py @@ -0,0 +1,193 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from types import SimpleNamespace + +import numpy as np +import pytest + +from mne.datasets import testing +from mne.io import read_raw_mef +from mne.io.mef._utils import ( + _UUTC_NO_ENTRY, + _get_mef_units_scale, + _mef_time_metadata_extras, + _records_to_annotations, + _toc_to_gap_annotations, +) + +pymef = pytest.importorskip("pymef") +data_path = testing.data_path(download=False) +mef_file_path = ( + data_path / "MEF" / "sub-ieegModulator_ses-ieeg01_task-photicstim_run-01_ieeg.mefd" +) + + +@testing.requires_testing_data +def test_mef_reading(): + """Test reading MEF3 file.""" + raw = read_raw_mef(mef_file_path, preload=False) + + assert raw.info["sfreq"] > 0 + assert len(raw.ch_names) > 0 + assert raw.n_times > 0 + + # Test lazy loading + data, times = raw[:, :100] + assert data.shape[1] == 100 + + # Test full load + raw.load_data() + assert raw.preload + + +@testing.requires_testing_data +def test_mef_channel_types(): + """Test that channel types default to sEEG.""" + raw = read_raw_mef(mef_file_path, preload=False) + ch_types = set(raw.get_channel_types()) + + # All channels should default to sEEG + assert ch_types == {"seeg"} + + +@testing.requires_testing_data +def test_mef_data_types(): + """Test that data is returned as float64.""" + raw = read_raw_mef(mef_file_path, preload=True) + data = raw.get_data() + + assert data.dtype == np.float64 + + +def test_mef_units_scale_helper(): + """Test unit scaling helper against known cases.""" + scale, _, unit_desc_norm, ufact_valid, unit_known = _get_mef_units_scale("uV", 2.0) + assert scale == pytest.approx(2e-6) + assert unit_desc_norm == "uv" + assert ufact_valid + assert unit_known + + scale, _, unit_desc_norm, ufact_valid, unit_known = _get_mef_units_scale( + "furlong", 2.0 + ) + assert scale == pytest.approx(2.0) + assert unit_desc_norm == "furlong" + assert ufact_valid + assert not unit_known + + scale, _, unit_desc_norm, ufact_valid, unit_known = _get_mef_units_scale("mV", 0.0) + assert scale == pytest.approx(1e-3) + assert unit_desc_norm == "mv" + assert not ufact_valid + assert unit_known + + +def test_mef_time_metadata_extras(): + """Test session time metadata extraction.""" + md3 = { + "recording_time_offset": 123456, + "DST_start_time": _UUTC_NO_ENTRY, + "DST_end_time": 789, + } + extras = _mef_time_metadata_extras(md3) + assert extras == {"recording_time_offset": 123456, "dst_end_time": 789} + + +def test_mef_record_annotations(): + """Test record annotation conversion.""" + start_uutc = 1_000_000 + session = SimpleNamespace( + session_md={ + "records_info": { + "records": [ + {"type": "Note", "time": start_uutc + 2_000_000, "text": "hello"} + ] + } + } + ) + ts_channels = { + "CH01": { + "records_info": { + "records": [ + {"type": "SyLg", "time": start_uutc + 1_000_000, "text": "chan"} + ] + }, + "segments": { + "seg-000001": { + "records_info": { + "records": [ + { + "type": "EDFA", + "time": start_uutc + 3_000_000, + "text": "seg", + "duration": 500_000, + } + ] + } + } + }, + } + } + + onsets, durations, desc, ch_names, extras = _records_to_annotations( + session, ts_channels, start_uutc + ) + order = np.argsort(onsets) + desc = [desc[ii] for ii in order] + ch_names = [ch_names[ii] for ii in order] + extras = [extras[ii] for ii in order] + durations = [durations[ii] for ii in order] + + assert desc[0] == "SyLg: chan" + assert ch_names[0] == ["CH01"] + assert extras[0]["channel"] == "CH01" + assert desc[1] == "Note: hello" + assert ch_names[1] == [] + assert desc[2] == "EDFA: seg" + assert ch_names[2] == ["CH01"] + assert extras[2]["segment"] == "seg-000001" + assert durations[2] == pytest.approx(0.5) + + +def test_mef_toc_gap_annotations(): + """Test TOC gap annotations.""" + toc = np.array( + [ + [1, 0, 1], + [10, 10, 10], + [0, 10, 25], + [0, 0, 0], + ], + dtype=np.int64, + ) + onsets, durations = _toc_to_gap_annotations(toc, sfreq=10.0) + assert onsets == [2.0] + assert durations == [0.5] + + +@testing.requires_testing_data +def test_mef_scaling_matches_pymef(): + """Test that MNE scaling matches pymef data plus metadata scaling.""" + raw = read_raw_mef(mef_file_path, preload=False) + session = pymef.mef_session.MefSession(str(mef_file_path), "") + ts_channels = session.session_md["time_series_channels"] + + scales = [] + for ch_name in raw.ch_names: + ch_md = ts_channels[ch_name]["section_2"] + scale, _, _, _, _ = _get_mef_units_scale( + ch_md["units_description"], ch_md["units_conversion_factor"] + ) + scales.append(scale) + scales = np.array(scales) + assert not np.allclose(scales, 1) # otherwise test won't verify scaling + + start, stop = 0, 10 + pymef_data = session.read_ts_channels_sample(raw.ch_names, [start, stop]) + pymef_data = np.array(pymef_data, dtype=np.float64) + expected = pymef_data * scales[:, np.newaxis] + + data = raw.get_data(start=start, stop=stop) + np.testing.assert_allclose(data, expected, rtol=1e-7, atol=0.0) diff --git a/mne-python/source/mne/io/nedf/__init__.py b/mne-python/source/mne/io/nedf/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fe67ee79fb5ce3acd06cf4ff7686d15fc630ab1c --- /dev/null +++ b/mne-python/source/mne/io/nedf/__init__.py @@ -0,0 +1,7 @@ +"""NEDF file import module.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .nedf import read_raw_nedf, _parse_nedf_header diff --git a/mne-python/source/mne/io/nedf/nedf.py b/mne-python/source/mne/io/nedf/nedf.py new file mode 100644 index 0000000000000000000000000000000000000000..bd4054f1c1662e5dd21031270769ac029eeda23e --- /dev/null +++ b/mne-python/source/mne/io/nedf/nedf.py @@ -0,0 +1,229 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +"""Import NeuroElectrics DataFormat (NEDF) files.""" + +from copy import deepcopy +from datetime import datetime, timezone + +import numpy as np + +from ..._fiff.meas_info import create_info +from ..._fiff.utils import _mult_cal_one +from ...utils import _check_fname, _soft_import, verbose, warn +from ..base import BaseRaw + + +def _getsubnodetext(node, name): + """Get an element from an XML node, raise an error otherwise. + + Parameters + ---------- + node: Element + XML Element + name: str + Child element name + + Returns + ------- + test: str + Text contents of the child nodes + """ + subnode = node.findtext(name) + if not subnode: + raise RuntimeError("NEDF header " + name + " not found") + return subnode + + +def _parse_nedf_header(header): + """Read header information from the first 10kB of an .nedf file. + + Parameters + ---------- + header : bytes + Null-terminated header data, mostly the file's first 10240 bytes. + + Returns + ------- + info : dict + A dictionary with header information. + dt : numpy.dtype + Structure of the binary EEG/accelerometer/trigger data in the file. + n_samples : int + The number of data samples. + """ + defusedxml = _soft_import("defusedxml", "reading NEDF data") + info = {} + # nedf files have three accelerometer channels sampled at 100Hz followed + # by five EEG samples + TTL trigger sampled at 500Hz + # For 32 EEG channels and no stim channels, the data layout may look like + # [ ('acc', '>u2', (3,)), + # ('data', dtype([ + # ('eeg', 'u1', (32, 3)), + # ('trig', '>i4', (1,)) + # ]), (5,)) + # ] + + dt = [] # dtype for the binary data block + datadt = [] # dtype for a single EEG sample + + headerend = header.find(b"\0") + if headerend == -1: + raise RuntimeError("End of header null not found") + headerxml = defusedxml.ElementTree.fromstring(header[:headerend]) + nedfversion = headerxml.findtext("NEDFversion", "") + if nedfversion not in ["1.3", "1.4"]: + warn("NEDFversion unsupported, use with caution") + + if headerxml.findtext("stepDetails/DeviceClass", "") == "STARSTIM": + warn("Found Starstim, this hasn't been tested extensively!") + + if headerxml.findtext("AdditionalChannelStatus", "OFF") != "OFF": + raise RuntimeError("Unknown additional channel, aborting.") + + n_acc = int(headerxml.findtext("NumberOfChannelsOfAccelerometer", 0)) + if n_acc: + # expect one sample of u16 accelerometer data per block + dt.append(("acc", ">u2", (n_acc,))) + + eegset = headerxml.find("EEGSettings") + if eegset is None: + raise RuntimeError("No EEG channels found") + nchantotal = int(_getsubnodetext(eegset, "TotalNumberOfChannels")) + info["nchan"] = nchantotal + + info["sfreq"] = int(_getsubnodetext(eegset, "EEGSamplingRate")) + info["ch_names"] = [e.text for e in eegset.find("EEGMontage")] + if nchantotal != len(info["ch_names"]): + raise RuntimeError( + f"TotalNumberOfChannels ({nchantotal}) != " + f"channel count ({len(info['ch_names'])})" + ) + # expect nchantotal uint24s + datadt.append(("eeg", "B", (nchantotal, 3))) + + if headerxml.find("STIMSettings") is not None: + # 2* -> two stim samples per eeg sample + datadt.append(("stim", "B", (2, nchantotal, 3))) + warn("stim channels are currently ignored") + + # Trigger data: 4 bytes in newer versions, 1 byte in older versions + trigger_type = ">i4" if headerxml.findtext("NEDFversion") else "B" + datadt.append(("trig", trigger_type)) + # 5 data samples per block + dt.append(("data", np.dtype(datadt), (5,))) + + date = headerxml.findtext("StepDetails/StartDate_firstEEGTimestamp", 0) + info["meas_date"] = datetime.fromtimestamp(int(date) / 1000, timezone.utc) + + n_samples = int(_getsubnodetext(eegset, "NumberOfRecordsOfEEG")) + n_full, n_last = divmod(n_samples, 5) + dt_last = deepcopy(dt) + assert dt_last[-1][-1] == (5,) + dt_last[-1] = list(dt_last[-1]) + dt_last[-1][-1] = (n_last,) + dt_last[-1] = tuple(dt_last[-1]) + return info, np.dtype(dt), np.dtype(dt_last), n_samples, n_full + + +# the first 10240 bytes are header in XML format, padded with NULL bytes +_HDRLEN = 10240 + + +class RawNedf(BaseRaw): + """Raw object from NeuroElectrics nedf file.""" + + def __init__(self, filename, preload=False, verbose=None): + filename = str(_check_fname(filename, "read", True, "filename")) + with open(filename, mode="rb") as fid: + header = fid.read(_HDRLEN) + header, dt, dt_last, n_samp, n_full = _parse_nedf_header(header) + ch_names = header["ch_names"] + ["STI 014"] + ch_types = ["eeg"] * len(ch_names) + ch_types[-1] = "stim" + info = create_info(ch_names, header["sfreq"], ch_types) + # scaling factor ADC-values -> volts + # taken from the NEDF EEGLAB plugin + # (https://www.neuroelectrics.com/resources/software/): + for ch in info["chs"][:-1]: + ch["cal"] = 2.4 / (6.0 * 8388607) + with info._unlock(): + info["meas_date"] = header["meas_date"] + raw_extra = dict(dt=dt, dt_last=dt_last, n_full=n_full) + super().__init__( + info, + preload=preload, + filenames=[filename], + verbose=verbose, + raw_extras=[raw_extra], + last_samps=[n_samp - 1], + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + dt = self._raw_extras[fi]["dt"] + dt_last = self._raw_extras[fi]["dt_last"] + n_full = self._raw_extras[fi]["n_full"] + n_eeg = dt[1].subdtype[0][0].shape[0] + # data is stored in 5-sample chunks (except maybe the last one!) + # so we have to do some gymnastics to pick the correct parts to + # read + offset = start // 5 * dt.itemsize + _HDRLEN + start_sl = start % 5 + n_samples = stop - start + n_samples_full = min(stop, n_full * 5) - start + last = None + n_chunks = (n_samples_full - 1) // 5 + 1 + n_tot = n_chunks * 5 + with open(self.filenames[fi], "rb") as fid: + fid.seek(offset, 0) + chunks = np.fromfile(fid, dtype=dt, count=n_chunks) + assert len(chunks) == n_chunks + if n_samples != n_samples_full: + last = np.fromfile(fid, dtype=dt_last, count=1) + eeg = _convert_eeg(chunks, n_eeg, n_tot) + trig = chunks["data"]["trig"].reshape(1, n_tot) + if last is not None: + n_last = dt_last["data"].shape[0] + eeg = np.concatenate((eeg, _convert_eeg(last, n_eeg, n_last)), axis=-1) + trig = np.concatenate( + (trig, last["data"]["trig"].reshape(1, n_last)), axis=-1 + ) + one_ = np.concatenate((eeg, trig)) + one = one_[:, start_sl : n_samples + start_sl] + _mult_cal_one(data, one, idx, cals, mult) + + +def _convert_eeg(chunks, n_eeg, n_tot): + # convert uint8-triplet -> int32 + eeg = chunks["data"]["eeg"] @ np.array([1 << 16, 1 << 8, 1]) + # convert sign if necessary + eeg[eeg > (1 << 23)] -= 1 << 24 + eeg = eeg.reshape((n_tot, n_eeg)).T + return eeg + + +@verbose +def read_raw_nedf(filename, preload=False, verbose=None) -> RawNedf: + """Read NeuroElectrics .nedf files. + + NEDF file versions starting from 1.3 are supported. + + Parameters + ---------- + filename : path-like + Path to the ``.nedf`` file. + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawNedf + A Raw object containing NEDF data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawNedf. + """ + return RawNedf(filename, preload, verbose) diff --git a/mne-python/source/mne/io/nedf/tests/__init__.py b/mne-python/source/mne/io/nedf/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/nedf/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/nedf/tests/test_nedf.py b/mne-python/source/mne/io/nedf/tests/test_nedf.py new file mode 100644 index 0000000000000000000000000000000000000000..1382417cd10a1f3f83c1fc34b3c2255e17181fcd --- /dev/null +++ b/mne-python/source/mne/io/nedf/tests/test_nedf.py @@ -0,0 +1,127 @@ +"""Test reading of NEDF format.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import pytest +from numpy.testing import assert_allclose, assert_array_equal + +from mne import find_events +from mne._fiff.constants import FIFF +from mne.datasets import testing +from mne.io.nedf import _parse_nedf_header, read_raw_nedf +from mne.io.tests.test_raw import _test_raw_reader + +eeg_path = testing.data_path(download=False, verbose=True) +eegfile = eeg_path / "nedf" / "testdata.nedf" + +stimhdr = b""" + + 1.3 + %d + + 4 + 500 + ABCD + 11 + + +\x00""" + +pytest.importorskip("defusedxml") + + +@pytest.mark.parametrize("nacc", (0, 3)) +def test_nedf_header_parser(nacc): + """Test NEDF header parsing and dtype extraction.""" + with pytest.warns(RuntimeWarning, match="stim channels.*ignored"): + info, dt, dt_last, n_samples, n_full = _parse_nedf_header(stimhdr % nacc) + assert n_samples == 11 + assert n_full == 2 + nchan = 4 + assert info["nchan"] == nchan + assert dt.itemsize == 200 + nacc * 2 + if nacc: + assert dt.names[0] == "acc" + assert dt["acc"].shape == (nacc,) + + assert dt["data"].shape == (5,) # blocks of 5 EEG samples each + assert dt_last["data"].shape == (1,) # plus one last extra one + + eegsampledt = dt["data"].subdtype[0] + assert eegsampledt.names == ("eeg", "stim", "trig") + assert eegsampledt["eeg"].shape == (nchan, 3) + assert eegsampledt["stim"].shape == (2, nchan, 3) + + +def test_invalid_headers(): + """Test that invalid headers raise exceptions.""" + tpl = b""" + 1.3 + + %s + ABCD + + \x00""" + nchan = b"4" + sr = b"500" + hdr = { + "null": b"No null terminator", + "Unknown additional": ( + b"1.3" + + b"???\x00" + ), # noqa: E501 + "No EEG channels found": b"1.3\x00", + "TotalNumberOfChannels not found": tpl % b"No nchan.", + "!= channel count": tpl + % (sr + b"52"), + "EEGSamplingRate not found": tpl % nchan, + "NumberOfRecordsOfEEG not found": tpl % (sr + nchan), + } + for match, invalid_hdr in hdr.items(): + with pytest.raises(RuntimeError, match=match): + _parse_nedf_header(invalid_hdr) + + sus_hdrs = { + "unsupported": b"25\x00", + "tested": ( + b"1.3" + + b"STARSTIM\x00" + ), + } + for match, sus_hdr in sus_hdrs.items(): + with pytest.warns(RuntimeWarning, match=match): + with pytest.raises(RuntimeError, match="No EEG channels found"): + _parse_nedf_header(sus_hdr) + + +@testing.requires_testing_data +def test_nedf_data(): + """Test reading raw NEDF files.""" + raw = read_raw_nedf(eegfile) + nsamples = len(raw) + assert nsamples == 32538 + + events = find_events(raw, shortest_event=1) + assert len(events) == 4 + assert_array_equal(events[:, 2], [1, 1, 1, 1]) + onsets = events[:, 0] / raw.info["sfreq"] + assert raw.info["sfreq"] == 500 + + data_end = raw.get_data("Fp1", nsamples - 100, nsamples).mean() + assert_allclose(data_end, 0.0176, atol=0.01) + assert_allclose(raw.get_data("Fpz", 0, 100).mean(), 0.0185, atol=0.01) + + assert_allclose(onsets, [22.384, 38.238, 49.496, 63.15]) + assert raw.info["meas_date"].year == 2019 + assert raw.ch_names[2] == "AF7" + + for ch in raw.info["chs"][:-1]: + assert ch["kind"] == FIFF.FIFFV_EEG_CH + assert ch["unit"] == FIFF.FIFF_UNIT_V + assert raw.info["chs"][-1]["kind"] == FIFF.FIFFV_STIM_CH + assert raw.info["chs"][-1]["unit"] == FIFF.FIFF_UNIT_V + + # full tests + _test_raw_reader(read_raw_nedf, filename=eegfile) diff --git a/mne-python/source/mne/io/neuralynx/__init__.py b/mne-python/source/mne/io/neuralynx/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..f302a22a89390abc9cd139c119835add200b4bc2 --- /dev/null +++ b/mne-python/source/mne/io/neuralynx/__init__.py @@ -0,0 +1,5 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .neuralynx import read_raw_neuralynx diff --git a/mne-python/source/mne/io/neuralynx/neuralynx.py b/mne-python/source/mne/io/neuralynx/neuralynx.py new file mode 100644 index 0000000000000000000000000000000000000000..56ff9fa4adb07d05692bf88fa01c0d84b49bb62f --- /dev/null +++ b/mne-python/source/mne/io/neuralynx/neuralynx.py @@ -0,0 +1,426 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime +import glob +import inspect +import os + +import numpy as np + +from ..._fiff.meas_info import create_info +from ..._fiff.utils import _mult_cal_one +from ...annotations import Annotations +from ...utils import _check_fname, _soft_import, fill_doc, logger, verbose +from ..base import BaseRaw + + +@fill_doc +def read_raw_neuralynx( + fname, *, preload=False, exclude_fname_patterns=None, verbose=None +) -> "RawNeuralynx": + """Reader for Neuralynx files. + + Parameters + ---------- + fname : path-like + Path to a folder with Neuralynx .ncs files. + %(preload)s + exclude_fname_patterns : list of str + List of glob-like string patterns to exclude from channel list. + Useful when not all channels have the same number of samples + so you can read separate instances. + %(verbose)s + + Returns + ------- + raw : instance of RawNeuralynx + A Raw object containing Neuralynx data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawNeuralynx. + + Notes + ----- + Neuralynx files are read from disk using the `Neo package + `__. + Currently, only reading of the ``.ncs files`` is supported. + + ``raw.info["meas_date"]`` is read from the ``recording_opened`` property + of the first ``.ncs`` file (i.e. channel) in the dataset (a warning is issued + if files have different dates of acquisition). + + Channel-specific high and lowpass frequencies of online filters are determined + based on the ``DspLowCutFrequency`` and ``DspHighCutFrequency`` header fields, + respectively. If no filters were used for a channel, the default lowpass is set + to the Nyquist frequency and the default highpass is set to 0. + If channels have different high/low cutoffs, ``raw.info["highpass"]`` and + ``raw.info["lowpass"]`` are then set to the maximum highpass and minimumlowpass + values across channels, respectively. + + Other header variables can be inspected using Neo directly. For example:: + + from neo.io import NeuralynxIO # doctest: +SKIP + fname = 'path/to/your/data' # doctest: +SKIP + nlx_reader = NeuralynxIO(dirname=fname) # doctest: +SKIP + print(nlx_reader.header) # doctest: +SKIP + print(nlx_reader.file_headers.items()) # doctest: +SKIP + """ + return RawNeuralynx( + fname, + preload=preload, + exclude_fname_patterns=exclude_fname_patterns, + verbose=verbose, + ) + + +# Helper for neo change of exclude_filename -> exclude_filenames in 0.13.2 +def _exclude_kwarg(exclude_fnames): + from neo.io import NeuralynxIO + + key = "exclude_filename" + if "exclude_filenames" in inspect.getfullargspec(NeuralynxIO).args: + key += "s" + return {key: exclude_fnames} + + +@fill_doc +class RawNeuralynx(BaseRaw): + """RawNeuralynx class.""" + + @verbose + def __init__( + self, + fname, + *, + preload=False, + exclude_fname_patterns=None, + verbose=None, + ): + fname = _check_fname(fname, "read", True, "fname", need_dir=True) + + _soft_import("neo", "Reading NeuralynxIO files", strict=True) + from neo.io import NeuralynxIO + + logger.info(f"Checking files in {fname}") + + # construct a list of filenames to ignore + exclude_fnames = None + if exclude_fname_patterns: + exclude_fnames = [] + for pattern in exclude_fname_patterns: + fnames = glob.glob(os.path.join(fname, pattern)) + fnames = [os.path.basename(fname) for fname in fnames] + exclude_fnames.extend(fnames) + + logger.info("Ignoring .ncs files:\n" + "\n".join(exclude_fnames)) + + # get basic file info from header, throw Error if NeuralynxIO can't parse + try: + nlx_reader = NeuralynxIO(dirname=fname, **_exclude_kwarg(exclude_fnames)) + except ValueError as e: + # give a more informative error message and what the user can do about it + if "Incompatible section structures across streams" in str(e): + raise ValueError( + "It seems .ncs channels have different numbers of samples. " + + "This is likely due to different sampling rates. " + + "Try reading in only channels with uniform sampling rate " + + "by excluding other channels with `exclude_fname_patterns` " + + "input argument." + + f"\nOriginal neo.NeuralynxRawIO ValueError:\n{e}" + ) from None + else: + raise + + info = create_info( + ch_types="seeg", + ch_names=nlx_reader.header["signal_channels"]["name"].tolist(), + sfreq=nlx_reader.get_signal_sampling_rate(), + ) + + ncs_fnames = nlx_reader.ncs_filenames.values() + ncs_hdrs = [ + hdr + for hdr_key, hdr in nlx_reader.file_headers.items() + if hdr_key in ncs_fnames + ] + + # if all files have the same recording_opened date, write it to info + meas_dates = np.array([hdr["recording_opened"] for hdr in ncs_hdrs]) + # to be sure, only write if all dates are the same + meas_diff = [] + for md in meas_dates: + meas_diff.append((md - meas_dates[0]).total_seconds()) + + # tolerate a +/-1 second meas_date difference (arbitrary threshold) + # else issue a warning + warn_meas = (np.abs(meas_diff) > 1.0).any() + if warn_meas: + logger.warning( + "Not all .ncs files have the same recording_opened date. " + + "Writing meas_date based on the first .ncs file." + ) + + # Neuarlynx allows channel specific low/highpass filters + # if not enabled, assume default lowpass = nyquist, highpass = 0 + default_lowpass = info["sfreq"] / 2 # nyquist + default_highpass = 0 + + has_hp = [hdr["DSPLowCutFilterEnabled"] for hdr in ncs_hdrs] + has_lp = [hdr["DSPHighCutFilterEnabled"] for hdr in ncs_hdrs] + if not all(has_hp) or not all(has_lp): + logger.warning( + "Not all .ncs files have the same high/lowpass filter settings. " + + "Assuming default highpass = 0, lowpass = nyquist." + ) + + highpass_freqs = [ + float(hdr["DspLowCutFrequency"]) + if hdr["DSPLowCutFilterEnabled"] + else default_highpass + for hdr in ncs_hdrs + ] + + lowpass_freqs = [ + float(hdr["DspHighCutFrequency"]) + if hdr["DSPHighCutFilterEnabled"] + else default_lowpass + for hdr in ncs_hdrs + ] + + with info._unlock(): + info["meas_date"] = meas_dates[0].astimezone(datetime.timezone.utc) + info["highpass"] = np.max(highpass_freqs) + info["lowpass"] = np.min(lowpass_freqs) + + # Neo reads only valid contiguous .ncs samples grouped as segments + n_segments = nlx_reader.header["nb_segment"][0] + block_id = 0 # assumes there's only one block of recording + + # get segment start/stop times + start_times = np.array( + [nlx_reader.segment_t_start(block_id, i) for i in range(n_segments)] + ) + stop_times = np.array( + [nlx_reader.segment_t_stop(block_id, i) for i in range(n_segments)] + ) + + # find discontinuous boundaries (of length n-1) + next_start_times = start_times[1::] + previous_stop_times = stop_times[:-1] + seg_diffs = next_start_times - previous_stop_times + + # mark as discontinuous any two segments that have + # start/stop delta larger than sampling period (1.5/sampling_rate) + logger.info("Checking for temporal discontinuities in Neo data segments.") + delta = 1.5 / info["sfreq"] + gaps = seg_diffs > delta + + seg_gap_dict = {} + + logger.info( + f"N = {gaps.sum()} discontinuous Neo segments detected " + + f"with delta > {delta} sec. " + + "Annotating gaps as BAD_ACQ_SKIP." + if gaps.any() + else "No discontinuities detected." + ) + + gap_starts = stop_times[:-1][gaps] # gap starts at segment offset + gap_stops = start_times[1::][gaps] # gap stops at segment onset + + # (n_gaps,) array of ints giving number of samples per inferred gap + gap_n_samps = np.array( + [ + int(round(stop * info["sfreq"])) - int(round(start * info["sfreq"])) + for start, stop in zip(gap_starts, gap_stops) + ] + ).astype(int) # force an int array (if no gaps, empty array is a float) + + # get sort indices for all segments (valid and gap) in ascending order + all_starts_ids = np.argsort(np.concatenate([start_times, gap_starts])) + + # variable indicating whether each segment is a gap or not + gap_indicator = np.concatenate( + [ + np.full(len(start_times), fill_value=0), + np.full(len(gap_starts), fill_value=1), + ] + ) + gap_indicator = gap_indicator[all_starts_ids].astype(bool) + + # store this in a dict to be passed to _raw_extras + seg_gap_dict = { + "gap_n_samps": gap_n_samps, + "isgap": gap_indicator, # False (data segment) or True (gap segment) + } + + valid_segment_sizes = [ + nlx_reader.get_signal_size(block_id, i) for i in range(n_segments) + ] + + sizes_sorted = np.concatenate([valid_segment_sizes, gap_n_samps])[ + all_starts_ids + ] + + # now construct an (n_samples,) indicator variable + sample2segment = np.concatenate( + [np.full(shape=(n,), fill_value=i) for i, n in enumerate(sizes_sorted)] + ) + + # get the start sample index for each gap segment () + gap_start_ids = np.cumsum(np.hstack([[0], sizes_sorted[:-1]]))[gap_indicator] + + # recreate time axis for gap annotations + mne_times = np.arange(0, len(sample2segment)) / info["sfreq"] + + assert len(gap_start_ids) == len(gap_n_samps) + annotations = Annotations( + onset=[mne_times[onset_id] for onset_id in gap_start_ids], + duration=[ + mne_times[onset_id + (n - 1)] - mne_times[onset_id] + for onset_id, n in zip(gap_start_ids, gap_n_samps) + ], + description=["BAD_ACQ_SKIP"] * len(gap_start_ids), + ) + + super().__init__( + info=info, + last_samps=[sizes_sorted.sum() - 1], + filenames=[fname], + preload=preload, + raw_extras=[ + dict( + smp2seg=sample2segment, + exclude_fnames=exclude_fnames, + segment_sizes=sizes_sorted, + seg_gap_dict=seg_gap_dict, + ) + ], + ) + + self.set_annotations(annotations) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + from neo import AnalogSignal, Segment + from neo.io import NeuralynxIO + from neo.io.proxyobjects import AnalogSignalProxy + + # quantities is a dependency of neo so we are guaranteed it exists + from quantities import Hz + + nlx_reader = NeuralynxIO( + dirname=self.filenames[fi], + **_exclude_kwarg(self._raw_extras[0]["exclude_fnames"]), + ) + neo_block = nlx_reader.read(lazy=True) + + # check that every segment has 1 associated neo.AnalogSignal() object + # (not sure what multiple analogsignals per neo.Segment would mean) + assert sum( + [len(segment.analogsignals) for segment in neo_block[0].segments] + ) == len(neo_block[0].segments) + + segment_sizes = self._raw_extras[fi]["segment_sizes"] + + # construct a (n_segments, 2) array of the first and last + # sample index for each segment relative to the start of the recording + seg_starts = [0] # first chunk starts at sample 0 + seg_stops = [segment_sizes[0] - 1] + for i in range(1, len(segment_sizes)): + ons_new = ( + seg_stops[i - 1] + 1 + ) # current chunk starts one sample after the previous one + seg_starts.append(ons_new) + off_new = ( + seg_stops[i - 1] + segment_sizes[i] + ) # the last sample is len(chunk) samples after the previous ended + seg_stops.append(off_new) + + start_stop_samples = np.stack([np.array(seg_starts), np.array(seg_stops)]).T + + first_seg = self._raw_extras[0]["smp2seg"][ + start + ] # segment containing start sample + last_seg = self._raw_extras[0]["smp2seg"][ + stop - 1 + ] # segment containing stop sample + + # select all segments between the one that contains the start sample + # and the one that contains the stop sample + sel_samples_global = start_stop_samples[first_seg : last_seg + 1, :] + + # express end samples relative to segment onsets + # to be used for slicing the arrays below + sel_samples_local = sel_samples_global.copy() + sel_samples_local[0:-1, 1] = ( + sel_samples_global[0:-1, 1] - sel_samples_global[0:-1, 0] + ) + sel_samples_local[1::, 0] = ( + 0 # now set the start sample for all segments after the first to 0 + ) + + sel_samples_local[0, 0] = ( + start - sel_samples_global[0, 0] + ) # express start sample relative to segment onset + sel_samples_local[-1, -1] = (stop - 1) - sel_samples_global[ + -1, 0 + ] # express stop sample relative to segment onset + + # array containing Segments + segments_arr = np.array(neo_block[0].segments, dtype=object) + + # if gaps were detected, correctly insert gap Segments in between valid Segments + gap_samples = self._raw_extras[fi]["seg_gap_dict"]["gap_n_samps"] + gap_segments = [Segment(f"gap-{i}") for i in range(len(gap_samples))] + + # create AnalogSignal objects representing gap data filled with 0's + sfreq = nlx_reader.get_signal_sampling_rate() + n_chans = ( + np.arange(idx.start, idx.stop, idx.step).size + if type(idx) is slice + else len(idx) # idx can be a slice or an np.array so check both + ) + + for seg, n in zip(gap_segments, gap_samples): + asig = AnalogSignal( + signal=np.zeros((n, n_chans)), units="uV", sampling_rate=sfreq * Hz + ) + seg.analogsignals.append(asig) + + n_total_segments = len(neo_block[0].segments + gap_segments) + segments_arr = np.zeros((n_total_segments,), dtype=object) + + # insert inferred gap segments at the right place in between valid segments + isgap = self._raw_extras[0]["seg_gap_dict"]["isgap"] + segments_arr[~isgap] = neo_block[0].segments + segments_arr[isgap] = gap_segments + + # now load data for selected segments/channels via + # neo.Segment.AnalogSignalProxy.load() or + # pad directly as AnalogSignal.magnitude for any gap data + all_data = np.concatenate( + [ + signal.load(channel_indexes=idx).magnitude[ + samples[0] : samples[-1] + 1, : + ] + if isinstance(signal, AnalogSignalProxy) + else signal.magnitude[samples[0] : samples[-1] + 1, :] + for seg, samples in zip( + segments_arr[first_seg : last_seg + 1], sel_samples_local + ) + for signal in seg.analogsignals + ] + ).T + + all_data *= 1e-6 # Convert uV to V + n_channels = len(nlx_reader.header["signal_channels"]["name"]) + block = np.zeros((n_channels, stop - start), dtype=data.dtype) + block[idx] = all_data # shape = (n_channels, n_samples) + + # Then store the result where it needs to go + _mult_cal_one(data, block, idx, cals, mult) diff --git a/mne-python/source/mne/io/neuralynx/tests/__init__.py b/mne-python/source/mne/io/neuralynx/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/neuralynx/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/neuralynx/tests/test_neuralynx.py b/mne-python/source/mne/io/neuralynx/tests/test_neuralynx.py new file mode 100644 index 0000000000000000000000000000000000000000..18578ef4ab72b96d44c6159bacb6b92ada7b0de8 --- /dev/null +++ b/mne-python/source/mne/io/neuralynx/tests/test_neuralynx.py @@ -0,0 +1,249 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +from ast import literal_eval +from datetime import datetime, timezone + +import numpy as np +import pytest +from numpy.testing import assert_allclose +from scipy.io import loadmat + +from mne.datasets.testing import data_path, requires_testing_data +from mne.io import read_raw_neuralynx +from mne.io.neuralynx.neuralynx import _exclude_kwarg +from mne.io.tests.test_raw import _test_raw_reader + +testing_path = data_path(download=False) / "neuralynx" + +pytest.importorskip("neo") + + +def _nlxheader_to_dict(matdict: dict) -> dict: + """Convert the read-in "Header" field into a dict. + + All the key-value pairs of Header entries are formatted as strings + (e.g. np.array("-AdbitVolts 0.000323513")) so we reformat that + into dict by splitting at blank spaces. + """ + entries = matdict["Header"][ + 1::, : + ] # skip the first row which is just the "Header" string + + return { + arr.item().item().split(" ")[0].strip("-"): arr.item().item().split(" ")[-1] + for arr in entries + if arr[0].size > 0 + } + + +def _read_nlx_mat_chan(matfile: str) -> np.ndarray: + """Read a single channel from a Neuralynx .mat file.""" + mat = loadmat(matfile) + + hdr_dict = _nlxheader_to_dict(mat) + + # Nlx2MatCSC.m reads the data in N equal-sized (512-item) chunks + # this array (1, n_chunks) stores the number of valid samples + # per chunk (the last chunk is usually shorter) + n_valid_samples = mat["NumberOfValidSamples"].ravel() + + # concatenate chunks, respecting the number of valid samples + x = np.concatenate( + [mat["Samples"][0:n, i] for i, n in enumerate(n_valid_samples)] + ) # in ADBits + + # this value is the same for all channels and + # converts data from ADBits to Volts + conversionf = literal_eval(hdr_dict["ADBitVolts"]) + x = x * conversionf + + # if header says input was inverted at acquisition + # (possibly for spike detection or so?), flip it back + # NeuralynxIO does this under the hood in NeuralynxIO.parse_header() + # see this discussion: https://github.com/NeuralEnsemble/python-neo/issues/819 + if hdr_dict["InputInverted"] == "True": + x *= -1 + + return x + + +def _read_nlx_mat_chan_keep_gaps(matfile: str) -> np.ndarray: + """Read a single channel from a Neuralynx .mat file and keep invalid samples.""" + mat = loadmat(matfile) + + hdr_dict = _nlxheader_to_dict(mat) + + # Nlx2MatCSC.m reads the data in N equal-sized (512-item) chunks + # this array (1, n_chunks) stores the number of valid samples + # per chunk (the last chunk is usually shorter) + n_valid_samples = mat["NumberOfValidSamples"].ravel() + + # read in the artificial zeros so that + # we can compare with the mne padded arrays + ncs_records_with_gaps = [9, 15, 20] + for i in ncs_records_with_gaps: + n_valid_samples[i] = 512 + + # concatenate chunks, respecting the number of valid samples + x = np.concatenate( + [mat["Samples"][0:n, i] for i, n in enumerate(n_valid_samples)] + ) # in ADBits + + # this value is the same for all channels and + # converts data from ADBits to Volts + conversionf = literal_eval(hdr_dict["ADBitVolts"]) + x = x * conversionf + + # if header says input was inverted at acquisition + # (possibly for spike detection or so?), flip it back + # NeuralynxIO does this under the hood in NeuralynxIO.parse_header() + # see this discussion: https://github.com/NeuralEnsemble/python-neo/issues/819 + if hdr_dict["InputInverted"] == "True": + x *= -1 + + return x + + +# set known values for the Neuralynx data for testing +expected_chan_names = ["LAHC1", "LAHC2", "LAHC3", "xAIR1", "xEKG1"] +expected_hp_freq = 0.1 +expected_lp_freq = 500.0 +expected_sfreq = 2000.0 +expected_meas_date = datetime.strptime("2023/11/02 13:39:27", "%Y/%m/%d %H:%M:%S") + + +@requires_testing_data +def test_neuralynx(): + """Test basic reading.""" + from neo.io import NeuralynxIO + + excluded_ncs_files = [ + "LAHCu1.ncs", + "LAHC1_3_gaps.ncs", + "LAHC2_3_gaps.ncs", + ] + + # ==== MNE-Python ==== # + fname_patterns = ["*u*.ncs", "*3_gaps.ncs"] + raw = read_raw_neuralynx( + fname=testing_path, + preload=True, + exclude_fname_patterns=fname_patterns, + ) + + # test that we picked the right info from headers + assert raw.info["highpass"] == expected_hp_freq, "highpass freq not set correctly" + assert raw.info["lowpass"] == expected_lp_freq, "lowpass freq not set correctly" + assert raw.info["sfreq"] == expected_sfreq, "sampling freq not set correctly" + + meas_date_utc = expected_meas_date.astimezone(timezone.utc) + assert raw.info["meas_date"] == meas_date_utc, "meas_date not set correctly" + + # test that channel selection worked + assert raw.ch_names == expected_chan_names, ( + "labels in raw.ch_names don't match expected channel names" + ) + + mne_y = raw.get_data() # in V + + # ==== NeuralynxIO ==== # + nlx_reader = NeuralynxIO(dirname=testing_path, **_exclude_kwarg(excluded_ncs_files)) + bl = nlx_reader.read( + lazy=False + ) # read a single block which contains the data split in segments + + # concatenate all signals and times from all segments (== total recording) + nlx_y = np.concatenate( + [sig.magnitude for seg in bl[0].segments for sig in seg.analogsignals] + ).T + nlx_y *= 1e-6 # convert from uV to V + + nlx_t = np.concatenate( + [sig.times.magnitude for seg in bl[0].segments for sig in seg.analogsignals] + ).T + nlx_t = np.round(nlx_t, 3) # round to millisecond precision + + nlx_ch_names = [ch[0] for ch in nlx_reader.header["signal_channels"]] + + # ===== Nlx2MatCSC.m ===== # + matchans = ["LAHC1.mat", "LAHC2.mat", "LAHC3.mat", "xAIR1.mat", "xEKG1.mat"] + + # (n_chan, n_samples) array, in V + mat_y = np.stack( + [_read_nlx_mat_chan(os.path.join(testing_path, ch)) for ch in matchans] + ) + + # ===== Check sample values across MNE-Python, NeuralynxIO and MATLAB ===== # + assert nlx_ch_names == raw.ch_names # check channel names + + assert_allclose( + mne_y, nlx_y, rtol=1e-6, err_msg="MNE and NeuralynxIO not all close" + ) # data + assert_allclose( + mne_y, mat_y, rtol=1e-6, err_msg="MNE and Nlx2MatCSC.m not all close" + ) # data + + _test_raw_reader( + read_raw_neuralynx, + fname=testing_path, + exclude_fname_patterns=fname_patterns, + ) + + +@requires_testing_data +def test_neuralynx_gaps(): + """Test gap detection.""" + # ignore files with no gaps + ignored_ncs_files = [ + "LAHC1.ncs", + "LAHC2.ncs", + "LAHC3.ncs", + "xAIR1.ncs", + "xEKG1.ncs", + "LAHCu1.ncs", + ] + raw = read_raw_neuralynx( + fname=testing_path, + preload=True, + exclude_fname_patterns=ignored_ncs_files, + ) + mne_y, _ = raw.get_data(return_times=True) # in V + + # there should be 2 channels with 3 gaps (of 130 samples in total) + n_expected_gaps = 3 + n_expected_missing_samples = 130 + assert len(raw.annotations) == n_expected_gaps, "Wrong number of gaps detected" + assert (mne_y[0, :] == 0).sum() == n_expected_missing_samples, ( + "Number of true and inferred missing samples differ" + ) + + # read in .mat files containing original gaps + matchans = ["LAHC1_3_gaps.mat", "LAHC2_3_gaps.mat"] + + # (n_chan, n_samples) array, in V + mat_y = np.stack( + [ + _read_nlx_mat_chan_keep_gaps(os.path.join(testing_path, ch)) + for ch in matchans + ] + ) + + # compare originally modified .ncs arrays with MNE-padded arrays + # and test that we back-inserted 0's at the right places + assert_allclose( + mne_y, mat_y, rtol=1e-6, err_msg="MNE and Nlx2MatCSC.m not all close" + ) + + # test that channel selection works + raw = read_raw_neuralynx( + fname=testing_path, + preload=False, + exclude_fname_patterns=ignored_ncs_files, + ) + + raw.pick("LAHC2") + assert raw.ch_names == ["LAHC2"] + raw.load_data() # before gh-12357 this would fail diff --git a/mne-python/source/mne/io/nicolet/__init__.py b/mne-python/source/mne/io/nicolet/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6e7ad05b63da0fb08085bf66d26f42ab4aee5bb6 --- /dev/null +++ b/mne-python/source/mne/io/nicolet/__init__.py @@ -0,0 +1,7 @@ +"""Nicolet module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .nicolet import read_raw_nicolet diff --git a/mne-python/source/mne/io/nicolet/nicolet.py b/mne-python/source/mne/io/nicolet/nicolet.py new file mode 100644 index 0000000000000000000000000000000000000000..05b8035bdddd01a0dd526cb4526a2a5c75222f86 --- /dev/null +++ b/mne-python/source/mne/io/nicolet/nicolet.py @@ -0,0 +1,201 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import calendar +import datetime +from os import path + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info +from ..._fiff.utils import _create_chs, _find_channels, _read_segments_file +from ...utils import fill_doc, logger +from ..base import BaseRaw + + +@fill_doc +def read_raw_nicolet( + input_fname, ch_type, eog=(), ecg=(), emg=(), misc=(), preload=False, verbose=None +) -> "RawNicolet": + """Read Nicolet data as raw object. + + .. note:: This reader takes data files with the extension ``.data`` as an + input. The header file with the same file name stem and an + extension ``.head`` is expected to be found in the same + directory. + + Parameters + ---------- + input_fname : path-like + Path to the data file (ending with ``.data`` not ``.head``). + ch_type : str + Channel type to designate to the data channels. Supported data types + include ``'eeg'``, ``'dbs'``. + eog : list | tuple | ``'auto'`` + Names of channels or list of indices that should be designated + EOG channels. If ``'auto'``, the channel names beginning with + ``EOG`` are used. Defaults to empty tuple. + ecg : list or tuple | ``'auto'`` + Names of channels or list of indices that should be designated + ECG channels. If ``'auto'``, the channel names beginning with + ``ECG`` are used. Defaults to empty tuple. + emg : list or tuple | ``'auto'`` + Names of channels or list of indices that should be designated + EMG channels. If ``'auto'``, the channel names beginning with + ``EMG`` are used. Defaults to empty tuple. + misc : list or tuple + Names of channels or list of indices that should be designated + MISC channels. Defaults to empty tuple. + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of Raw + A Raw object containing the data. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + return RawNicolet( + input_fname, + ch_type, + eog=eog, + ecg=ecg, + emg=emg, + misc=misc, + preload=preload, + verbose=verbose, + ) + + +def _get_nicolet_info(fname, ch_type, eog, ecg, emg, misc): + """Extract info from Nicolet header files.""" + fname, extension = path.splitext(fname) + + if extension != ".data": + raise ValueError(f'File name should end with .data not "{extension}".') + + header = fname + ".head" + + logger.info("Reading header...") + header_info = dict() + with open(header) as fid: + for line in fid: + var, value = line.split("=") + if var == "elec_names": + value = value[1:-2].split(",") # strip brackets + elif var == "conversion_factor": + value = float(value) + elif var in ["num_channels", "rec_id", "adm_id", "pat_id", "num_samples"]: + value = int(value) + elif var != "start_ts": + value = float(value) + header_info[var] = value + + ch_names = header_info["elec_names"] + if eog == "auto": + eog = _find_channels(ch_names, "EOG") + if ecg == "auto": + ecg = _find_channels(ch_names, "ECG") + if emg == "auto": + emg = _find_channels(ch_names, "EMG") + + date, time = header_info["start_ts"].split() + date = date.split("-") + time = time.split(":") + sec, msec = time[2].split(".") + date = datetime.datetime( + int(date[0]), + int(date[1]), + int(date[2]), + int(time[0]), + int(time[1]), + int(sec), + int(msec), + ) + info = _empty_info(header_info["sample_freq"]) + info["meas_date"] = (calendar.timegm(date.utctimetuple()), 0) + + if ch_type == "eeg": + ch_coil = FIFF.FIFFV_COIL_EEG + ch_kind = FIFF.FIFFV_EEG_CH + elif ch_type == "seeg": + ch_coil = FIFF.FIFFV_COIL_EEG + ch_kind = FIFF.FIFFV_SEEG_CH + else: + raise TypeError( + "Channel type not recognized. Available types are 'eeg' and 'seeg'." + ) + cals = np.repeat(header_info["conversion_factor"] * 1e-6, len(ch_names)) + info["chs"] = _create_chs(ch_names, cals, ch_coil, ch_kind, eog, ecg, emg, misc) + info["highpass"] = 0.0 + info["lowpass"] = info["sfreq"] / 2.0 + info._unlocked = False + info._update_redundant() + return info, header_info + + +class RawNicolet(BaseRaw): + """Raw object from Nicolet file. + + Parameters + ---------- + input_fname : path-like + Path to the Nicolet file. + ch_type : str + Channel type to designate to the data channels. Supported data types + include ``'eeg'``, ``'seeg'``. + eog : list | tuple | ``'auto'`` + Names of channels or list of indices that should be designated + EOG channels. If ``'auto'``, the channel names beginning with + ``EOG`` are used. Defaults to empty tuple. + ecg : list or tuple | ``'auto'`` + Names of channels or list of indices that should be designated + ECG channels. If ``'auto'``, the channel names beginning with + ``ECG`` are used. Defaults to empty tuple. + emg : list or tuple | ``'auto'`` + Names of channels or list of indices that should be designated + EMG channels. If ``'auto'``, the channel names beginning with + ``EMG`` are used. Defaults to empty tuple. + misc : list or tuple + Names of channels or list of indices that should be designated + MISC channels. Defaults to empty tuple. + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + def __init__( + self, + input_fname, + ch_type, + eog=(), + ecg=(), + emg=(), + misc=(), + preload=False, + verbose=None, + ): + input_fname = path.abspath(input_fname) + info, header_info = _get_nicolet_info(input_fname, ch_type, eog, ecg, emg, misc) + last_samps = [header_info["num_samples"] - 1] + super().__init__( + info, + preload, + filenames=[input_fname], + raw_extras=[header_info], + last_samps=last_samps, + orig_format="int", + verbose=verbose, + ) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + _read_segments_file(self, data, idx, fi, start, stop, cals, mult, dtype=" "RawNihon": + """Reader for an Nihon Kohden EEG file. + + Parameters + ---------- + fname : path-like + Path to the Nihon Kohden data file (``.EEG``). + preload : bool + If True, all data are loaded at initialization. + %(encoding_nihon)s + + .. versionadded:: 1.11 + %(verbose)s + + Returns + ------- + raw : instance of RawNihon + A Raw object containing Nihon Kohden data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawNihon. + """ + return RawNihon(fname, preload, encoding=encoding, verbose=verbose) + + +_valid_headers = [ + "EEG-1100A V01.00", + "EEG-1100B V01.00", + "EEG-1100C V01.00", + "QI-403A V01.00", + "QI-403A V02.00", + "EEG-2100 V01.00", + "EEG-2100 V02.00", + "DAE-2100D V01.30", + "DAE-2100D V02.00", + "EEG-1200A V01.00", +] + + +def _read_nihon_metadata(fname): + metadata = {} + fname = _ensure_path(fname) + pnt_fname = fname.with_suffix(".PNT") + if not pnt_fname.exists(): + pnt_fname = fname.with_suffix(".pnt") + if not pnt_fname.exists(): + warn("No PNT file exists. Metadata will be blank") + return metadata + logger.info("Found PNT file, reading metadata.") + with open(pnt_fname) as fid: + version = np.fromfile(fid, "|S16", 1).astype("U16")[0] + if version not in _valid_headers: + raise ValueError(f"Not a valid Nihon Kohden PNT file ({version})") + metadata["version"] = version + + # Read timestamp + fid.seek(0x40) + meas_str = np.fromfile(fid, "|S14", 1).astype("U14")[0] + meas_date = datetime.strptime(meas_str, "%Y%m%d%H%M%S") + meas_date = meas_date.replace(tzinfo=timezone.utc) + metadata["meas_date"] = meas_date + + return metadata + + +_default_chan_labels = [ + "FP1", + "FP2", + "F3", + "F4", + "C3", + "C4", + "P3", + "P4", + "O1", + "O2", + "F7", + "F8", + "T3", + "T4", + "T5", + "T6", + "FZ", + "CZ", + "PZ", + "E", + "PG1", + "PG2", + "A1", + "A2", + "T1", + "T2", +] +_default_chan_labels += [f"X{i}" for i in range(1, 12)] +_default_chan_labels += [f"NA{i}" for i in range(1, 6)] +_default_chan_labels += [f"DC{i:02}" for i in range(1, 33)] +_default_chan_labels += ["BN1", "BN2", "Mark1", "Mark2"] +_default_chan_labels += [f"NA{i}" for i in range(6, 28)] +_default_chan_labels += ["X12/BP1", "X13/BP2", "X14/BP3", "X15/BP4"] +_default_chan_labels += [f"X{i}" for i in range(16, 166)] +_default_chan_labels += ["NA28", "Z"] + +_encodings = ("utf-8", "latin1") + + +def _read_21e_file(fname): + fname = _ensure_path(fname) + e_fname = fname.with_suffix(".21E") + _chan_labels = [x for x in _default_chan_labels] + if e_fname.exists(): + # Read the 21E file and update the labels accordingly. + logger.info("Found 21E file, reading channel names.") + for enc in _encodings: + try: + with open(e_fname, encoding=enc) as fid: + keep_parsing = False + for line in fid: + if line.startswith("["): + if "ELECTRODE" in line or "REFERENCE" in line: + keep_parsing = True + else: + keep_parsing = False + elif keep_parsing is True: + idx, name = line.split("=") + idx = int(idx) + if idx >= len(_chan_labels): + n = idx - len(_chan_labels) + 1 + _chan_labels.extend(["UNK"] * n) + _chan_labels[idx] = name.strip() + except UnicodeDecodeError: + pass + else: + break + else: + warn( + f"Could not decode {e_fname} as one of {_encodings}; " + f"Default channel names are chosen." + ) + else: + warn( + f"Could not find {e_fname} containing channel definitions; " + f"Default channel names are chosen." + ) + + return _chan_labels + + +def _read_nihon_header(fname): + # Read the Nihon Kohden EEG file header + fname = _ensure_path(fname) + _chan_labels = _read_21e_file(fname) + header = {} + logger.info(f"Reading header from {fname}") + with open(fname) as fid: + version = np.fromfile(fid, "|S16", 1).astype("U16")[0] + if version not in _valid_headers: + raise ValueError(f"Not a valid Nihon Kohden EEG file ({version})") + + fid.seek(0x0081) + control_block = np.fromfile(fid, "|S16", 1).astype("U16")[0] + if control_block not in _valid_headers: + raise ValueError( + f"Not a valid Nihon Kohden EEG file (control block {version})" + ) + + fid.seek(0x17FE) + waveform_sign = np.fromfile(fid, np.uint8, 1)[0] + if waveform_sign != 1: + raise ValueError("Not a valid Nihon Kohden EEG file (waveform block)") + header["version"] = version + + fid.seek(0x0091) + n_ctlblocks = np.fromfile(fid, np.uint8, 1)[0] + header["n_ctlblocks"] = n_ctlblocks + controlblocks = [] + for i_ctl_block in range(n_ctlblocks): + t_controlblock = {} + fid.seek(0x0092 + i_ctl_block * 20) + t_ctl_address = np.fromfile(fid, np.uint32, 1)[0] + t_controlblock["address"] = t_ctl_address + fid.seek(t_ctl_address + 17) + n_datablocks = np.fromfile(fid, np.uint8, 1)[0] + t_controlblock["n_datablocks"] = n_datablocks + t_controlblock["datablocks"] = [] + for i_data_block in range(n_datablocks): + t_datablock = {} + fid.seek(t_ctl_address + i_data_block * 20 + 18) + t_data_address = np.fromfile(fid, np.uint32, 1)[0] + t_datablock["address"] = t_data_address + + fid.seek(t_data_address + 0x26) + t_n_channels = np.fromfile(fid, np.uint8, 1)[0].astype(np.int64) + t_datablock["n_channels"] = t_n_channels + + t_channels = [] + for i_ch in range(t_n_channels): + fid.seek(t_data_address + 0x27 + (i_ch * 10)) + t_idx = np.fromfile(fid, np.uint8, 1)[0] + t_channels.append(_chan_labels[t_idx]) + + t_datablock["channels"] = t_channels + + fid.seek(t_data_address + 0x1C) + t_record_duration = np.fromfile(fid, np.uint32, 1)[0].astype(np.int64) + t_datablock["duration"] = t_record_duration + + fid.seek(t_data_address + 0x1A) + sfreq = np.fromfile(fid, np.uint16, 1)[0] & 0x3FFF + t_datablock["sfreq"] = sfreq.astype(np.int64) + + t_datablock["n_samples"] = np.int64(t_record_duration * sfreq // 10) + t_controlblock["datablocks"].append(t_datablock) + controlblocks.append(t_controlblock) + header["controlblocks"] = controlblocks + + # Now check that every data block has the same channels and sfreq + chans = [] + sfreqs = [] + nsamples = [] + for t_ctl in header["controlblocks"]: + for t_dtb in t_ctl["datablocks"]: + chans.append(t_dtb["channels"]) + sfreqs.append(t_dtb["sfreq"]) + nsamples.append(t_dtb["n_samples"]) + for i_elem in range(1, len(chans)): + if chans[0] != chans[i_elem]: + raise ValueError("Channel names in datablocks do not match") + if sfreqs[0] != sfreqs[i_elem]: + raise ValueError("Sample frequency in datablocks do not match") + header["ch_names"] = chans[0] + header["sfreq"] = sfreqs[0] + header["n_samples"] = np.sum(nsamples) + + # TODO: Support more than one controlblock and more than one datablock + if header["n_ctlblocks"] != 1: + raise NotImplementedError( + "I dont know how to read more than one " + "control block for this type of file :(" + ) + if header["controlblocks"][0]["n_datablocks"] > 1: + # Multiple blocks, check that they all have the same kind of data + datablocks = header["controlblocks"][0]["datablocks"] + block_0 = datablocks[0] + for t_block in datablocks[1:]: + if block_0["n_channels"] != t_block["n_channels"]: + raise ValueError( + "Cannot read NK file with different number of channels " + "in each datablock" + ) + if block_0["channels"] != t_block["channels"]: + raise ValueError( + "Cannot read NK file with different channels in each datablock" + ) + if block_0["sfreq"] != t_block["sfreq"]: + raise ValueError( + "Cannot read NK file with different sfreq in each datablock" + ) + + return header, _chan_labels + + +def _read_event_log_block(fid, t_block, version): + fid.seek(0x92 + t_block * 20) + data = np.fromfile(fid, np.uint32, 1) + if data.size == 0 or data[0] == 0: + return + t_blk_address = data[0] + + fid.seek(t_blk_address + 0x1) + data = np.fromfile(fid, "|S16", 1).astype("U16") + if data.size == 0 or data[0] != version: + return + + fid.seek(t_blk_address + 0x12) + data = np.fromfile(fid, np.uint8, 1) + if data.size == 0: + return + n_logs = data[0] + + fid.seek(t_blk_address + 0x14) + return np.fromfile(fid, "|S45", n_logs) + + +def _parse_event_log(event_log): + t_desc = event_log[:20] + hour, minute, second = ( + int(event_log[20:22]), + int(event_log[22:24]), + int(event_log[24:26]), + ) + t_onset = hour * 3600 + minute * 60 + second + return t_desc, t_onset + + +def _parse_sub_event_log(sub_event_log): + t_sub_desc = sub_event_log[:20] + t_sub_onset = int(sub_event_log[24:30]) / 1e6 + return t_sub_desc, t_sub_onset + + +def _read_nihon_annotations(fname, encoding="utf-8"): + fname = _ensure_path(fname) + log_fname = fname.with_suffix(".LOG") + if not log_fname.exists(): + warn("No LOG file exists. Annotations will not be read") + return dict(onset=[], duration=[], description=[]) + logger.info("Found LOG file, reading events.") + with open(log_fname) as fid: + version = np.fromfile(fid, "|S16", 1).astype("U16")[0] + if version not in _valid_headers: + raise ValueError(f"Not a valid Nihon Kohden LOG file ({version})") + + fid.seek(0x91) + n_logblocks = np.fromfile(fid, np.uint8, 1)[0] + all_onsets = [] + all_descriptions = [] + may_have_sub_blocks = n_logblocks <= 21 + for t_block in range(n_logblocks): + t_logs = _read_event_log_block(fid, t_block, version) + t_sub_logs = None + if may_have_sub_blocks: + t_sub_logs = _read_event_log_block(fid, t_block + 22, version) + + for li, t_log in enumerate(t_logs): + t_desc, t_onset = _parse_event_log(t_log) + if t_sub_logs is not None and t_sub_logs.size == t_logs.size: + t_sub_desc, t_sub_onset = _parse_sub_event_log(t_sub_logs[li]) + t_desc += t_sub_desc + t_onset += t_sub_onset + + t_desc = t_desc.rstrip(b"\x00") + try: + t_desc = t_desc.decode(encoding) + except UnicodeDecodeError: + warn(f"Could not decode log as {encoding}") + continue + + all_onsets.append(t_onset) + all_descriptions.append(t_desc) + + annots = dict( + onset=all_onsets, + duration=[0] * len(all_onsets), + description=all_descriptions, + ) + return annots + + +def _map_ch_to_type(ch_name): + ch_type_pattern = OrderedDict( + [("stim", ("Mark",)), ("misc", ("DC", "NA", "Z", "$")), ("bio", ("X",))] + ) + for key, kinds in ch_type_pattern.items(): + if any(kind in ch_name for kind in kinds): + return key + return "eeg" + + +def _map_ch_to_specs(ch_name, chan_labels_upper): + unit_mult = 1e-3 + phys_min = -12002.9 + phys_max = 12002.56 + dig_min = -32768 + if ch_name.upper() in chan_labels_upper: + idx = chan_labels_upper.index(ch_name.upper()) + if (idx < 42 or idx > 73) and idx not in [76, 77]: + unit_mult = 1e-6 + phys_min = -3200 + phys_max = 3199.902 + t_range = phys_max - phys_min + cal = t_range / 65535 + offset = phys_min - (dig_min * cal) + + out = dict( + unit=unit_mult, + phys_min=phys_min, + phys_max=phys_max, + dig_min=dig_min, + cal=cal, + offset=offset, + ) + return out + + +@fill_doc +class RawNihon(BaseRaw): + """Raw object from a Nihon Kohden EEG file. + + Parameters + ---------- + fname : path-like + Path to the Nihon Kohden data ``.eeg`` file. + preload : bool + If True, all data are loaded at initialization. + %(encoding_nihon)s + + .. versionadded:: 1.11 + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + @verbose + def __init__(self, fname, preload=False, *, encoding="utf-8", verbose=None): + fname = _check_fname(fname, "read", True, "fname") + data_name = fname.name + logger.info(f"Loading {data_name}") + + # chan_labels are electrode codes defined in the .21E file. + # It is not the same as header["ch_names"]. + header, chan_labels = _read_nihon_header(fname) + metadata = _read_nihon_metadata(fname) + + # n_chan = len(header['ch_names']) + 1 + sfreq = header["sfreq"] + # data are multiplexed int16 + ch_names = header["ch_names"] + ch_types = [_map_ch_to_type(x) for x in ch_names] + + info = create_info(ch_names, sfreq, ch_types) + n_samples = header["n_samples"] + + if "meas_date" in metadata: + with info._unlock(): + info["meas_date"] = metadata["meas_date"] + + chan_labels_upper = [x.upper() for x in chan_labels] + chs = {x: _map_ch_to_specs(x, chan_labels_upper) for x in info["ch_names"]} + cal = np.array([chs[x]["cal"] for x in info["ch_names"]], float)[:, np.newaxis] + offsets = np.array([chs[x]["offset"] for x in info["ch_names"]], float)[ + :, np.newaxis + ] + gains = np.array([chs[x]["unit"] for x in info["ch_names"]], float)[ + :, np.newaxis + ] + + raw_extras = dict(cal=cal, offsets=offsets, gains=gains, header=header) + for i_ch, ch_name in enumerate(info["ch_names"]): + t_range = chs[ch_name]["phys_max"] - chs[ch_name]["phys_min"] + info["chs"][i_ch]["range"] = t_range + info["chs"][i_ch]["cal"] = 1 / t_range + + super().__init__( + info, + preload=preload, + last_samps=(n_samples - 1,), + filenames=[fname.as_posix()], + orig_format="short", + raw_extras=[raw_extras], + ) + + # Get annotations from LOG file + annots = _read_nihon_annotations(fname, encoding) + + # Annotate acquisition skips + controlblock = header["controlblocks"][0] + cur_sample = 0 + if controlblock["n_datablocks"] > 1: + for i_block in range(controlblock["n_datablocks"] - 1): + t_block = controlblock["datablocks"][i_block] + cur_sample = cur_sample + t_block["n_samples"] + cur_tpoint = (cur_sample - 0.5) / t_block["sfreq"] + # Add annotations as in append raw + annots["onset"].append(cur_tpoint) + annots["duration"].append(0.0) + annots["description"].append("BAD boundary") + annots["onset"].append(cur_tpoint) + annots["duration"].append(0.0) + annots["description"].append("EDGE boundary") + + annotations = Annotations(**annots, orig_time=info["meas_date"]) + self.set_annotations(annotations) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + # For now we assume one control block + header = self._raw_extras[fi]["header"] + + # Get the original cal, offsets and gains + cal = self._raw_extras[fi]["cal"] + offsets = self._raw_extras[fi]["offsets"] + gains = self._raw_extras[fi]["gains"] + + # get the right datablock + datablocks = header["controlblocks"][0]["datablocks"] + ends = np.cumsum([t["n_samples"] for t in datablocks]) + + start_block = np.where(start < ends)[0][0] + stop_block = np.where(stop <= ends)[0][0] + + if start_block != stop_block: + # Recursive call for each block independently + new_start = start + sample_start = 0 + for t_block_idx in range(start_block, stop_block + 1): + t_block = datablocks[t_block_idx] + if t_block == stop_block: + # If its the last block, we stop on the last sample to read + new_stop = stop + else: + # Otherwise, stop on the last sample of the block + new_stop = t_block["n_samples"] + new_start + samples_to_read = new_stop - new_start + sample_stop = sample_start + samples_to_read + + self._read_segment_file( + data[:, sample_start:sample_stop], + idx, + fi, + new_start, + new_stop, + cals, + mult, + ) + + # Update variables for next loop + sample_start = sample_stop + new_start = new_stop + else: + datablock = datablocks[start_block] + + n_channels = datablock["n_channels"] + 1 + datastart = datablock["address"] + 0x27 + (datablock["n_channels"] * 10) + + # Compute start offset based on the beginning of the block + rel_start = start + if start_block != 0: + rel_start = start - ends[start_block - 1] + start_offset = datastart + rel_start * n_channels * 2 + + with open(self.filenames[fi], "rb") as fid: + to_read = (stop - start) * n_channels + fid.seek(start_offset) + block_data = np.fromfile(fid, " len(set(nihon._read_21e_file(fname))) + msg = ( + "Channel names are not unique, found duplicates for: " + "{'FP1'}. Applying running numbers for duplicates." + ) + with pytest.warns(RuntimeWarning, match=msg): + read_raw_nihon(fname) + + +@testing.requires_testing_data +def test_nihon_calibration(): + """Test handling of calibration factor and range in Nihon Kohden EEG files.""" + fname = data_path / "NihonKohden" / "DA00100E.EEG" + raw = read_raw_nihon(fname, preload=True, encoding="cp936") + + Fp1_idx = raw.ch_names.index("Fp1") + M1_idx = raw.ch_names.index("M1") + M2_idx = raw.ch_names.index("M2") + + Fp1_info = raw.info["chs"][Fp1_idx] + M1_info = raw.info["chs"][M1_idx] + M2_info = raw.info["chs"][M2_idx] + + # M1, M2 are EEG channels, just like Fp1. + # So they should have the same calibration factor and physical range. + assert_allclose(M1_info["cal"], Fp1_info["cal"]) + assert_allclose(M2_info["cal"], Fp1_info["cal"]) + assert_allclose(M1_info["range"], Fp1_info["range"]) + assert_allclose(M2_info["range"], Fp1_info["range"]) + + fname_edf = data_path / "NihonKohden" / "DA00100E.EDF" + raw_edf = read_raw_edf(fname_edf, preload=True) + raw_edf.drop_channels(["Events/Markers"]) + # a couple of ch names differ in the EDF + edf_ch_names = {"EEG Mark1": "$M1", "EEG Mark2": "$M2"} + raw_edf.rename_channels(edf_ch_names) + + assert raw.ch_names == raw_edf.ch_names + assert raw._data.shape == raw_edf._data.shape + assert raw.info["sfreq"] == raw_edf.info["sfreq"] + + assert_allclose(raw.get_data(), raw_edf.get_data()) diff --git a/mne-python/source/mne/io/nirx/__init__.py b/mne-python/source/mne/io/nirx/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..5946836cda1677836e0be5a3a77f0784f73ec669 --- /dev/null +++ b/mne-python/source/mne/io/nirx/__init__.py @@ -0,0 +1,7 @@ +"""fNIRS module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .nirx import read_raw_nirx diff --git a/mne-python/source/mne/io/nirx/_localized_abbr.py b/mne-python/source/mne/io/nirx/_localized_abbr.py new file mode 100644 index 0000000000000000000000000000000000000000..37e05016717be8fc81421477b12f4feaae1a03b6 --- /dev/null +++ b/mne-python/source/mne/io/nirx/_localized_abbr.py @@ -0,0 +1,146 @@ +"""Localizations for meas_date extraction.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +# This file was generated on 2021/01/31 on an Ubuntu system. +# When getting "unsupported locale setting" on Ubuntu (e.g., with localepurge), +# use "sudo locale-gen de_DE" etc. then "sudo update-locale". + +""" +import datetime +import locale +print('_localized_abbr = {') +for loc in ('en_US.utf8', 'de_DE', 'fr_FR', 'it_IT'): + print(f' {repr(loc)}: {{') + print(' "month": {', end='') + month_abbr = set() + for month in range(1, 13): # Month as locale’s abbreviated name + locale.setlocale(locale.LC_TIME, "en_US.utf8") + dt = datetime.datetime(year=2000, month=month, day=1) + val = dt.strftime("%b").lower() + locale.setlocale(locale.LC_TIME, loc) + key = dt.strftime("%b").lower() + month_abbr.add(key) + print(f'{repr(key)}: {repr(val)}, ', end='') + print('}, # noqa') + print(' "weekday": {', end='') + weekday_abbr = set() + for day in range(1, 8): # Weekday as locale’s abbreviated name. + locale.setlocale(locale.LC_TIME, "en_US.utf8") + dt = datetime.datetime(year=2000, month=1, day=day) + val = dt.strftime("%a").lower() + locale.setlocale(locale.LC_TIME, loc) + key = dt.strftime("%a").lower() + assert key not in weekday_abbr, key + weekday_abbr.add(key) + print(f'{repr(key)}: {repr(val)}, ', end='') + print('}, # noqa') + print(' },') +print('}\n') +""" + +# TODO: this should really be outsourced to a dedicated module like arrow or babel +_localized_abbr = { + "en_US.utf8": { + "month": { + "jan": "jan", + "feb": "feb", + "mar": "mar", + "apr": "apr", + "may": "may", + "jun": "jun", + "jul": "jul", + "aug": "aug", + "sep": "sep", + "oct": "oct", + "nov": "nov", + "dec": "dec", + }, # noqa + "weekday": { + "sat": "sat", + "sun": "sun", + "mon": "mon", + "tue": "tue", + "wed": "wed", + "thu": "thu", + "fri": "fri", + }, # noqa + }, + "de_DE": { + "month": { + "jan": "jan", + "feb": "feb", + "mär": "mar", + "apr": "apr", + "mai": "may", + "jun": "jun", + "jul": "jul", + "aug": "aug", + "sep": "sep", + "okt": "oct", + "nov": "nov", + "dez": "dec", + }, # noqa + "weekday": { + "sa": "sat", + "so": "sun", + "mo": "mon", + "di": "tue", + "mi": "wed", + "do": "thu", + "fr": "fri", + }, # noqa + }, + "fr_FR": { + "month": { + "janv.": "jan", + "févr.": "feb", + "mars": "mar", + "avril": "apr", + "mai": "may", + "juin": "jun", + "juil.": "jul", + "août": "aug", + "sept.": "sep", + "oct.": "oct", + "nov.": "nov", + "déc.": "dec", + }, # noqa + "weekday": { + "sam.": "sat", + "dim.": "sun", + "lun.": "mon", + "mar.": "tue", + "mer.": "wed", + "jeu.": "thu", + "ven.": "fri", + }, # noqa + }, + "it_IT": { + "month": { + "gen": "jan", + "feb": "feb", + "mar": "mar", + "apr": "apr", + "mag": "may", + "giu": "jun", + "lug": "jul", + "ago": "aug", + "set": "sep", + "ott": "oct", + "nov": "nov", + "dic": "dec", + }, # noqa + "weekday": { + "sab": "sat", + "dom": "sun", + "lun": "mon", + "mar": "tue", + "mer": "wed", + "gio": "thu", + "ven": "fri", + }, # noqa + }, +} diff --git a/mne-python/source/mne/io/nirx/nirx.py b/mne-python/source/mne/io/nirx/nirx.py new file mode 100644 index 0000000000000000000000000000000000000000..766986c4612620b112dc4996c629bf35c0c512ae --- /dev/null +++ b/mne-python/source/mne/io/nirx/nirx.py @@ -0,0 +1,597 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime as dt +import glob as glob +import json +import os.path as op +import re as re +from configparser import ConfigParser, RawConfigParser + +import numpy as np +from scipy.io import loadmat + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _format_dig_points, create_info +from ..._fiff.utils import _mult_cal_one +from ..._freesurfer import get_mni_fiducials +from ...annotations import Annotations +from ...fixes import _reshape_view +from ...transforms import _get_trans, apply_trans +from ...utils import ( + _check_fname, + _check_option, + _mask_to_onsets_offsets, + _validate_type, + fill_doc, + logger, + verbose, + warn, +) +from ..base import BaseRaw +from ._localized_abbr import _localized_abbr + + +@fill_doc +def read_raw_nirx( + fname, saturated="annotate", *, preload=False, encoding="latin-1", verbose=None +) -> "RawNIRX": + """Reader for a NIRX fNIRS recording. + + Parameters + ---------- + fname : path-like + Path to the NIRX data folder (directory containing NIRX files) or + the ``.hdr`` header file within that folder. The function will + automatically find and read all required NIRX files from the + directory. + %(saturated)s + %(preload)s + %(encoding_nirx)s + %(verbose)s + + Returns + ------- + raw : instance of RawNIRX + A Raw object containing NIRX data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawNIRX. + + Notes + ----- + %(nirx_notes)s + """ + return RawNIRX( + fname, saturated, preload=preload, encoding=encoding, verbose=verbose + ) + + +def _open(fname): + return open(fname, encoding="latin-1") + + +@fill_doc +class RawNIRX(BaseRaw): + """Raw object from a NIRX fNIRS file. + + Parameters + ---------- + fname : path-like + Path to the NIRX data folder or header file. + %(saturated)s + %(preload)s + %(encoding_nirx)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + + Notes + ----- + %(nirx_notes)s + """ + + @verbose + def __init__(self, fname, saturated, *, preload=False, encoding=None, verbose=None): + logger.info(f"Loading {fname}") + _validate_type(fname, "path-like", "fname") + _validate_type(saturated, str, "saturated") + _check_option("saturated", saturated, ("annotate", "nan", "ignore")) + fname = str(fname) + if fname.endswith(".hdr"): + fname = op.dirname(op.abspath(fname)) + + fname = str(_check_fname(fname, "read", True, "fname", need_dir=True)) + + json_config = glob.glob(f"{fname}/*{'config.json'}") + is_aurora = len(json_config) + + if is_aurora: + # NIRSport2 devices using Aurora software + keys = ( + "hdr", + "config.json", + "description.json", + "wl1", + "wl2", + "probeInfo.mat", + "tri", + ) + else: + # NIRScout devices and NIRSport1 devices + keys = ( + "hdr", + "inf", + "set", + "tpl", + "wl1", + "wl2", + "config.txt", + "probeInfo.mat", + ) + n_dat = len(glob.glob(f"{fname}/*{'dat'}")) + if n_dat != 1: + warn( + "A single dat file was expected in the specified path, " + f"but got {n_dat}. This may indicate that the file " + "structure has been modified since the measurement " + "was saved." + ) + + # Check if required files exist and store names for later use + files = dict() + nan_mask = dict() + for key in keys: + files[key] = glob.glob(f"{fname}/*{key}") + fidx = 0 + if len(files[key]) != 1: + if key not in ("wl1", "wl2"): + raise RuntimeError(f"Need one {key} file, got {len(files[key])}") + noidx = np.where(["nosatflags_" in op.basename(x) for x in files[key]])[ + 0 + ] + if len(noidx) != 1 or len(files[key]) != 2: + raise RuntimeError( + f"Need one nosatflags and one standard {key} file, " + f"got {len(files[key])}" + ) + # Here two files have been found, one that is called + # no sat flags. The nosatflag file has no NaNs in it. + noidx = noidx[0] + if saturated == "ignore": + # Ignore NaN and return values + fidx = noidx + elif saturated == "nan": + # Return NaN + fidx = 0 if noidx == 1 else 1 + else: + assert saturated == "annotate" # guaranteed above + fidx = noidx + nan_mask[key] = files[key][0 if noidx == 1 else 1] + files[key] = files[key][fidx] + + # Read number of rows/samples of wavelength data + with _open(files["wl1"]) as fid: + last_sample = fid.read().count("\n") - 1 + + # Read header file + # The header file isn't compliant with the configparser. So all the + # text between comments must be removed before passing to parser + with open(files["hdr"], encoding=encoding) as f: + hdr_str_all = f.read() + hdr_str = re.sub("#.*?#", "", hdr_str_all, flags=re.DOTALL) + if is_aurora: + hdr_str = re.sub("(\\[DataStructure].*)", "", hdr_str, flags=re.DOTALL) + hdr = RawConfigParser() + hdr.read_string(hdr_str) + + # Check that the file format version is supported + if is_aurora: + # We may need to ease this requirement back + if hdr["GeneralInfo"]["Version"] not in [ + "2021.4.0-34-ge9fdbbc8", + "2021.9.0-5-g3eb32851", + "2021.9.0-6-g14ef4a71", + ]: + warn( + "MNE has not been tested with Aurora version " + f"{hdr['GeneralInfo']['Version']}" + ) + else: + if hdr["GeneralInfo"]["NIRStar"] not in ['"15.0"', '"15.2"', '"15.3"']: + raise RuntimeError( + "MNE does not support this NIRStar version" + f" ({hdr['GeneralInfo']['NIRStar']})" + ) + if ( + "NIRScout" not in hdr["GeneralInfo"]["Device"] + and "NIRSport" not in hdr["GeneralInfo"]["Device"] + ): + warn( + "Only import of data from NIRScout devices have been " + f"thoroughly tested. You are using a {hdr['GeneralInfo']['Device']}" + " device." + ) + + # Parse required header fields + + # Extract measurement date and time + if is_aurora: + datetime_str = hdr["GeneralInfo"]["Date"] + else: + datetime_str = hdr["GeneralInfo"]["Date"] + hdr["GeneralInfo"]["Time"] + + meas_date = None + # Several formats have been observed so we try each in turn + for loc, translations in _localized_abbr.items(): + do_break = False + # So far we are lucky in that all the formats below, if they + # include %a (weekday abbr), always come first. Thus we can use + # a .split(), replace, and rejoin. + loc_datetime_str = datetime_str.split(" ") + for key, val in translations["weekday"].items(): + loc_datetime_str[0] = loc_datetime_str[0].replace(key, val) + for ii in range(1, len(loc_datetime_str)): + for key, val in translations["month"].items(): + loc_datetime_str[ii] = loc_datetime_str[ii].replace(key, val) + loc_datetime_str = " ".join(loc_datetime_str) + logger.debug(f"Trying {loc} datetime: {loc_datetime_str}") + for dt_code in [ + '"%a, %b %d, %Y""%H:%M:%S.%f"', + '"%a %d %b %Y""%H:%M:%S.%f"', + '"%a, %d %b %Y""%H:%M:%S.%f"', + "%Y-%m-%d %H:%M:%S.%f", + '"%Y年%m月%d日""%H:%M:%S.%f"', + ]: + try: + meas_date = dt.datetime.strptime(loc_datetime_str, dt_code) + except ValueError: + pass + else: + meas_date = meas_date.replace(tzinfo=dt.timezone.utc) + do_break = True + logger.debug(f"Measurement date language {loc} detected: {dt_code}") + break + if do_break: + break + if meas_date is None: + warn( + "Extraction of measurement date from NIRX file failed. " + "This can be caused by files saved in certain locales " + f"(currently only {list(_localized_abbr)} supported). " + "Please report this as a github issue. " + "The date is being set to January 1st, 2000, " + f"instead of {repr(datetime_str)}." + ) + meas_date = dt.datetime(2000, 1, 1, 0, 0, 0, tzinfo=dt.timezone.utc) + + # Extract frequencies of light used by machine + if is_aurora: + fnirs_wavelengths = [760, 850] + else: + fnirs_wavelengths = [ + int(s) + for s in re.findall(r"(\d+)", hdr["ImagingParameters"]["Wavelengths"]) + ] + + # Extract source-detectors + if is_aurora: + sources = re.findall(r"(\d+)-\d+", hdr_str_all.split("\n")[-2]) + detectors = re.findall(r"\d+-(\d+)", hdr_str_all.split("\n")[-2]) + sources = [int(s) + 1 for s in sources] + detectors = [int(d) + 1 for d in detectors] + + else: + sources = np.asarray( + [ + int(s) + for s in re.findall( + r"(\d+)-\d+:\d+", hdr["DataStructure"]["S-D-Key"] + ) + ], + int, + ) + detectors = np.asarray( + [ + int(s) + for s in re.findall( + r"\d+-(\d+):\d+", hdr["DataStructure"]["S-D-Key"] + ) + ], + int, + ) + + # Extract sampling rate + if is_aurora: + samplingrate = float(hdr["GeneralInfo"]["Sampling rate"]) + else: + samplingrate = float(hdr["ImagingParameters"]["SamplingRate"]) + + # Read participant information file + if is_aurora: + with open(files["description.json"]) as f: + inf = json.load(f) + else: + inf = ConfigParser(allow_no_value=True) + inf.read(files["inf"]) + inf = inf._sections["Subject Demographics"] + + # Store subject information from inf file in mne format + # Note: NIRX also records "Study Type", "Experiment History", + # "Additional Notes", "Contact Information" and this information + # is currently discarded + # NIRStar does not record an id, or handedness by default + # The name field is used to populate the his_id variable. + subject_info = {} + if is_aurora: + names = inf["subject"].split() + else: + names = inf["name"].replace('"', "").split() + subject_info["his_id"] = "_".join(names) + if len(names) > 0: + subject_info["first_name"] = names[0].replace('"', "") + if len(names) > 1: + subject_info["last_name"] = names[-1].replace('"', "") + if len(names) > 2: + subject_info["middle_name"] = names[-2].replace('"', "") + subject_info["sex"] = inf["gender"].replace('"', "") + # Recode values + if subject_info["sex"] in {"M", "Male", "1"}: + subject_info["sex"] = FIFF.FIFFV_SUBJ_SEX_MALE + elif subject_info["sex"] in {"F", "Female", "2"}: + subject_info["sex"] = FIFF.FIFFV_SUBJ_SEX_FEMALE + else: + subject_info["sex"] = FIFF.FIFFV_SUBJ_SEX_UNKNOWN + if inf["age"] != "": + subject_info["birthday"] = dt.date( + meas_date.year - int(inf["age"]), + meas_date.month, + meas_date.day, + ) + + # Read information about probe/montage/optodes + # A word on terminology used here: + # Sources produce light + # Detectors measure light + # Sources and detectors are both called optodes + # Each source - detector pair produces a channel + # Channels are defined as the midpoint between source and detector + mat_data = loadmat(files["probeInfo.mat"]) + probes = mat_data["probeInfo"]["probes"][0, 0] + requested_channels = probes["index_c"][0, 0] + src_locs = probes["coords_s3"][0, 0] / 100.0 + det_locs = probes["coords_d3"][0, 0] / 100.0 + ch_locs = probes["coords_c3"][0, 0] / 100.0 + + # These are all in MNI coordinates, so let's transform them to + # the Neuromag head coordinate frame + src_locs, det_locs, ch_locs, mri_head_t = _convert_fnirs_to_head( + "fsaverage", "mri", "head", src_locs, det_locs, ch_locs + ) + + # Set up digitization + dig = get_mni_fiducials("fsaverage", verbose=False) + for fid in dig: + fid["r"] = apply_trans(mri_head_t, fid["r"]) + fid["coord_frame"] = FIFF.FIFFV_COORD_HEAD + for ii, ch_loc in enumerate(ch_locs, 1): + dig.append( + dict( + kind=FIFF.FIFFV_POINT_EEG, # misnomer but probably okay + r=ch_loc, + ident=ii, + coord_frame=FIFF.FIFFV_COORD_HEAD, + ) + ) + dig = _format_dig_points(dig) + del mri_head_t + + # Determine requested channel indices + # The wl1 and wl2 files include all possible source - detector pairs. + # But most of these are not relevant. We want to extract only the + # subset requested in the probe file + req_ind = np.array([], int) + for req_idx in range(requested_channels.shape[0]): + sd_idx = np.where( + (sources == requested_channels[req_idx][0]) + & (detectors == requested_channels[req_idx][1]) + ) + req_ind = np.concatenate((req_ind, sd_idx[0])) + req_ind = req_ind.astype(int) + + snames = [f"S{sources[idx]}" for idx in req_ind] + dnames = [f"_D{detectors[idx]}" for idx in req_ind] + sdnames = [m + str(n) for m, n in zip(snames, dnames)] + sd1 = [s + " " + str(fnirs_wavelengths[0]) for s in sdnames] + sd2 = [s + " " + str(fnirs_wavelengths[1]) for s in sdnames] + chnames = [val for pair in zip(sd1, sd2) for val in pair] + + # Create mne structure + info = create_info(chnames, samplingrate, ch_types="fnirs_cw_amplitude") + with info._unlock(): + info.update(subject_info=subject_info, dig=dig) + info["meas_date"] = meas_date + + # Store channel, source, and detector locations + # The channel location is stored in the first 3 entries of loc. + # The source location is stored in the second 3 entries of loc. + # The detector location is stored in the third 3 entries of loc. + # NIRx NIRSite uses MNI coordinates. + # Also encode the light frequency in the structure. + for ch_idx2 in range(requested_channels.shape[0]): + # Find source and store location + src = int(requested_channels[ch_idx2, 0]) - 1 + # Find detector and store location + det = int(requested_channels[ch_idx2, 1]) - 1 + # Store channel location as midpoint between source and detector. + midpoint = (src_locs[src, :] + det_locs[det, :]) / 2 + for ii in range(2): + ch_idx3 = ch_idx2 * 2 + ii + info["chs"][ch_idx3]["loc"][3:6] = src_locs[src, :] + info["chs"][ch_idx3]["loc"][6:9] = det_locs[det, :] + info["chs"][ch_idx3]["loc"][:3] = midpoint + info["chs"][ch_idx3]["loc"][9] = fnirs_wavelengths[ii] + info["chs"][ch_idx3]["coord_frame"] = FIFF.FIFFV_COORD_HEAD + + # Extract the start/stop numbers for samples in the CSV. In theory the + # sample bounds should just be 10 * the number of channels, but some + # files have mixed \n and \n\r endings (!) so we can't rely on it, and + # instead make a single pass over the entire file at the beginning so + # that we know how to seek and read later. + bounds = dict() + for key in ("wl1", "wl2"): + offset = 0 + bounds[key] = [offset] + with open(files[key], "rb") as fid: + for line in fid: + offset += len(line) + bounds[key].append(offset) + assert offset == fid.tell() + + # Extras required for reading data + raw_extras = { + "sd_index": req_ind, + "files": files, + "bounds": bounds, + "nan_mask": nan_mask, + } + # Get our saturated mask + annot_mask = None + for ki, key in enumerate(("wl1", "wl2")): + if nan_mask.get(key, None) is None: + continue + mask = np.isnan( + _read_csv_rows_cols( + nan_mask[key], 0, last_sample + 1, req_ind, {0: 0, 1: None} + ).T + ) + if saturated == "nan": + nan_mask[key] = mask + else: + assert saturated == "annotate" + if annot_mask is None: + annot_mask = np.zeros( + (len(info["ch_names"]) // 2, last_sample + 1), bool + ) + annot_mask |= mask + nan_mask[key] = None # shouldn't need again + + super().__init__( + info, + preload, + filenames=[fname], + last_samps=[last_sample], + raw_extras=[raw_extras], + verbose=verbose, + ) + + # make onset/duration/description + onset, duration, description, ch_names = list(), list(), list(), list() + if annot_mask is not None: + for ci, mask in enumerate(annot_mask): + on, dur = _mask_to_onsets_offsets(mask) + on = on / info["sfreq"] + dur = dur / info["sfreq"] + dur -= on + onset.extend(on) + duration.extend(dur) + description.extend(["BAD_SATURATED"] * len(on)) + ch_names.extend([self.ch_names[2 * ci : 2 * ci + 2]] * len(on)) + + # Read triggers from event file + if not is_aurora: + files["tri"] = files["hdr"][:-3] + "evt" + if op.isfile(files["tri"]): + with _open(files["tri"]) as fid: + t = [re.findall(r"(\d+)", line) for line in fid] + if is_aurora: + tf_idx, desc_idx = _determine_tri_idxs(t[0]) + for t_ in t: + if is_aurora: + trigger_frame = float(t_[tf_idx]) + desc = float(t_[desc_idx]) + else: + binary_value = "".join(t_[1:])[::-1] + desc = float(int(binary_value, 2)) + trigger_frame = float(t_[0]) + onset.append(trigger_frame / samplingrate) + duration.append(1.0) # No duration info stored in files + description.append(desc) + ch_names.append(list()) + annot = Annotations(onset, duration, description, ch_names=ch_names) + self.set_annotations(annot) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a segment of data from a file. + + The NIRX machine records raw data as two different wavelengths. + The returned data interleaves the wavelengths. + """ + sd_index = self._raw_extras[fi]["sd_index"] + + wls = list() + for key in ("wl1", "wl2"): + d = _read_csv_rows_cols( + self._raw_extras[fi]["files"][key], + start, + stop, + sd_index, + self._raw_extras[fi]["bounds"][key], + ).T + nan_mask = self._raw_extras[fi]["nan_mask"].get(key, None) + if nan_mask is not None: + d[nan_mask[:, start:stop]] = np.nan + wls.append(d) + + # TODO: Make this more efficient by only indexing above what we need. + # For now let's just construct the full data matrix and index. + # Interleave wavelength 1 and 2 to match channel names: + this_data = np.zeros((len(wls[0]) * 2, stop - start)) + this_data[0::2, :] = wls[0] + this_data[1::2, :] = wls[1] + _mult_cal_one(data, this_data, idx, cals, mult) + return data + + +def _read_csv_rows_cols(fname, start, stop, cols, bounds, sep=" ", replace=None): + with open(fname, "rb") as fid: + fid.seek(bounds[start]) + args = list() + if bounds[1] is not None: + args.append(bounds[stop] - bounds[start]) + data = fid.read(*args).decode("latin-1") + if replace is not None: + data = replace(data) + x = np.fromstring(data, float, sep=sep) + x = _reshape_view(x, (stop - start, -1)) + x = x[:, cols] + return x + + +def _convert_fnirs_to_head(trans, fro, to, src_locs, det_locs, ch_locs): + mri_head_t, _ = _get_trans(trans, fro, to) + src_locs = apply_trans(mri_head_t, src_locs) + det_locs = apply_trans(mri_head_t, det_locs) + ch_locs = apply_trans(mri_head_t, ch_locs) + return src_locs, det_locs, ch_locs, mri_head_t + + +def _determine_tri_idxs(trigger): + """Determine tri file indexes for frame and description.""" + if len(trigger) == 12: + # Aurora version 2021.9.6 or greater + trigger_frame_idx = 7 + desc_idx = 10 + elif len(trigger) == 9: + # Aurora version 2021.9.5 or earlier + trigger_frame_idx = 7 + desc_idx = 8 + else: + raise RuntimeError("Unable to read trigger file.") + + return trigger_frame_idx, desc_idx diff --git a/mne-python/source/mne/io/nirx/tests/__init__.py b/mne-python/source/mne/io/nirx/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/nirx/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/nirx/tests/test_nirx.py b/mne-python/source/mne/io/nirx/tests/test_nirx.py new file mode 100644 index 0000000000000000000000000000000000000000..16d81c55e785bcf5b2cf5a0cc3705f6aa6689921 --- /dev/null +++ b/mne-python/source/mne/io/nirx/tests/test_nirx.py @@ -0,0 +1,810 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime as dt +import os +import shutil + +import numpy as np +import pytest +from numpy.testing import assert_allclose, assert_array_equal + +from mne import pick_types +from mne._fiff.constants import FIFF +from mne.datasets.testing import data_path, requires_testing_data +from mne.io import read_raw_nirx +from mne.io.tests.test_raw import _test_raw_reader +from mne.preprocessing import annotate_nan +from mne.preprocessing.nirs import ( + _reorder_nirx, + short_channels, + source_detector_distances, +) +from mne.transforms import _get_trans, apply_trans + +testing_path = data_path(download=False) +fname_nirx_15_0 = testing_path / "NIRx" / "nirscout" / "nirx_15_0_recording" +fname_nirx_15_2 = testing_path / "NIRx" / "nirscout" / "nirx_15_2_recording" +fname_nirx_15_2_short = ( + testing_path / "NIRx" / "nirscout" / "nirx_15_2_recording_w_short" +) +fname_nirx_15_3_short = testing_path / "NIRx" / "nirscout" / "nirx_15_3_recording" + + +# This file has no saturated sections +nirsport1_wo_sat = ( + testing_path / "NIRx" / "nirsport_v1" / "nirx_15_3_recording_wo_saturation" +) +# This file has saturation / but not on the optode pairing in montage +nirsport1_w_sat = ( + testing_path + / "NIRx" + / "nirsport_v1" + / "nirx_15_3_recording_w_saturation_not_on_montage_channels" +) +# This file has saturation in channels of interest +nirsport1_w_fullsat = ( + testing_path + / "NIRx" + / "nirsport_v1" + / "nirx_15_3_recording_w_saturation_on_montage_channels" +) + +# NIRSport2 device using Aurora software +nirsport2 = testing_path / "NIRx" / "nirsport_v2" / "aurora_recording _w_short_and_acc" +nirsport2_2021_9 = testing_path / "NIRx" / "nirsport_v2" / "aurora_2021_9" +nirsport2_2021_9_6 = testing_path / "NIRx" / "nirsport_v2" / "aurora_2021_9_6" + + +def test_nirsport_v2_matches_snirf(nirx_snirf): + """Test NIRSport2 raw files return same data as snirf.""" + raw, raw_snirf = nirx_snirf + _reorder_nirx(raw_snirf) + assert raw.ch_names == raw_snirf.ch_names + + assert_allclose(raw._data, raw_snirf._data) + + # Check the timing of annotations match (naming is different) + assert_allclose(raw.annotations.onset, raw_snirf.annotations.onset) + + assert_array_equal(raw.ch_names, raw_snirf.ch_names) + + # This test fails as snirf encodes name incorrectly. + # assert raw.info["subject_info"]["first_name"] == + # raw_snirf.info["subject_info"]["first_name"] + + +@requires_testing_data +@pytest.mark.filterwarnings("ignore:.*Extraction of measurement.*:") +def test_nirsport_v2(): + """Test NIRSport2 file.""" + raw = read_raw_nirx(nirsport2, preload=True) + assert raw._data.shape == (40, 128) + + # Test distance between optodes matches values from + # nirsite https://github.com/mne-tools/mne-testing-data/pull/86 + # figure 3 + allowed_distance_error = 0.005 + assert_allclose( + source_detector_distances(raw.copy().pick("S1_D1 760").info), + [0.0304], + atol=allowed_distance_error, + ) + assert_allclose( + source_detector_distances(raw.copy().pick("S2_D2 760").info), + [0.0400], + atol=allowed_distance_error, + ) + + # Test location of detectors + # The locations of detectors can be seen in the first + # figure on this page... + # https://github.com/mne-tools/mne-testing-data/pull/86 + allowed_dist_error = 0.0002 + locs = [ch["loc"][6:9] for ch in raw.info["chs"]] + head_mri_t, _ = _get_trans("fsaverage", "head", "mri") + mni_locs = apply_trans(head_mri_t, locs) + + assert raw.info["ch_names"][0][3:5] == "D1" + assert_allclose(mni_locs[0], [-0.0841, -0.0464, -0.0129], atol=allowed_dist_error) + + assert raw.info["ch_names"][2][3:5] == "D6" + assert_allclose(mni_locs[2], [-0.0841, -0.0138, 0.0248], atol=allowed_dist_error) + + assert raw.info["ch_names"][34][3:5] == "D5" + assert_allclose(mni_locs[34], [0.0845, -0.0451, -0.0123], atol=allowed_dist_error) + + # Test location of sensors + # The locations of sensors can be seen in the second + # figure on this page... + # https://github.com/mne-tools/mne-testing-data/pull/86 + locs = [ch["loc"][3:6] for ch in raw.info["chs"]] + head_mri_t, _ = _get_trans("fsaverage", "head", "mri") + mni_locs = apply_trans(head_mri_t, locs) + + assert raw.info["ch_names"][0][:2] == "S1" + assert_allclose(mni_locs[0], [-0.0848, -0.0162, -0.0163], atol=allowed_dist_error) + + assert raw.info["ch_names"][9][:2] == "S2" + assert_allclose(mni_locs[9], [-0.0, -0.1195, 0.0142], atol=allowed_dist_error) + + assert raw.info["ch_names"][39][:2] == "S8" + assert_allclose(mni_locs[34], [0.0828, -0.046, 0.0285], atol=allowed_dist_error) + + assert len(raw.annotations) == 3 + assert raw.annotations.description[0] == "1.0" + assert raw.annotations.description[2] == "6.0" + # Lose tolerance as I am eyeballing the time differences on screen + assert_allclose(np.diff(raw.annotations.onset), [2.3, 3.1], atol=0.1) + + mon = raw.get_montage() + assert len(mon.dig) == 27 + + +@requires_testing_data +@pytest.mark.filterwarnings("ignore:.*Extraction of measurement.*:") +def test_nirsport_v1_wo_sat(): + """Test NIRSport1 file with no saturation.""" + raw = read_raw_nirx(nirsport1_wo_sat, preload=True) + + # Test data import + assert raw._data.shape == (26, 164) + assert raw.info["sfreq"] == 10.416667 + + # By default real data is returned + assert np.sum(np.isnan(raw.get_data())) == 0 + + raw = read_raw_nirx(nirsport1_wo_sat, preload=True, saturated="nan") + data = raw.get_data() + assert data.shape == (26, 164) + assert np.sum(np.isnan(data)) == 0 + + raw = read_raw_nirx(nirsport1_wo_sat, saturated="annotate") + data = raw.get_data() + assert data.shape == (26, 164) + assert np.sum(np.isnan(data)) == 0 + + +@pytest.mark.filterwarnings("ignore:.*Extraction of measurement.*:") +@requires_testing_data +def test_nirsport_v1_w_sat(): + """Test NIRSport1 file with NaNs but not in channel of interest.""" + raw = read_raw_nirx(nirsport1_w_sat) + + # Test data import + data = raw.get_data() + assert data.shape == (26, 176) + assert raw.info["sfreq"] == 10.416667 + assert np.sum(np.isnan(data)) == 0 + + raw = read_raw_nirx(nirsport1_w_sat, saturated="nan") + data = raw.get_data() + assert data.shape == (26, 176) + assert np.sum(np.isnan(data)) == 0 + + raw = read_raw_nirx(nirsport1_w_sat, saturated="annotate") + data = raw.get_data() + assert data.shape == (26, 176) + assert np.sum(np.isnan(data)) == 0 + + +@pytest.mark.filterwarnings("ignore:.*Extraction of measurement.*:") +@requires_testing_data +@pytest.mark.parametrize("preload", (True, False)) +@pytest.mark.parametrize("meas_date", (None, "orig")) +def test_nirsport_v1_w_bad_sat(preload, meas_date): + """Test NIRSport1 file with NaNs.""" + fname = nirsport1_w_fullsat + raw = read_raw_nirx(fname, preload=preload) + data = raw.get_data() + assert not np.isnan(data).any() + assert len(raw.annotations) == 5 + # annotated version and ignore should have same data but different annot + raw_ignore = read_raw_nirx(fname, saturated="ignore", preload=preload) + assert_allclose(raw_ignore.get_data(), data) + assert len(raw_ignore.annotations) == 2 + assert not any("NAN" in d for d in raw_ignore.annotations.description) + # nan version should not have same data, but we can give it the same annot + raw_nan = read_raw_nirx(fname, saturated="nan", preload=preload) + data_nan = raw_nan.get_data() + assert np.isnan(data_nan).any() + assert not np.allclose(raw_nan.get_data(), data) + raw_nan_annot = raw_ignore.copy() + if meas_date is None: + raw.set_meas_date(None) + raw_nan.set_meas_date(None) + raw_nan_annot.set_meas_date(None) + nan_annots = annotate_nan(raw_nan) + assert nan_annots.orig_time == raw_nan.info["meas_date"] + raw_nan_annot.set_annotations(nan_annots) + use_mask = np.where(raw.annotations.description == "BAD_SATURATED") + for key in ("onset", "duration"): + a = getattr(raw_nan_annot.annotations, key)[::2] # one ch in each + b = getattr(raw.annotations, key)[use_mask] # two chs in each + assert_allclose(a, b) + + +@requires_testing_data +def test_nirx_hdr_load(): + """Test reading NIRX files using path to header file.""" + fname = fname_nirx_15_2_short / "NIRS-2019-08-23_001.hdr" + raw = read_raw_nirx(fname, preload=True) + + # Test data import + assert raw._data.shape == (26, 145) + assert raw.info["sfreq"] == 12.5 + + +@requires_testing_data +def test_nirx_missing_warn(): + """Test reading NIRX files when missing data.""" + with pytest.raises(FileNotFoundError, match="does not exist"): + read_raw_nirx(fname_nirx_15_2_short / "1", preload=True) + + +@requires_testing_data +def test_nirx_missing_evt(tmp_path): + """Test reading NIRX files when missing data.""" + shutil.copytree(fname_nirx_15_2_short, str(tmp_path) + "/data/") + os.rename( + tmp_path / "data" / "NIRS-2019-08-23_001.evt", + tmp_path / "data" / "NIRS-2019-08-23_001.xxx", + ) + fname = tmp_path / "data" / "NIRS-2019-08-23_001.hdr" + raw = read_raw_nirx(fname, preload=True) + assert raw.annotations.onset.shape == (0,) + + +@requires_testing_data +def test_nirx_dat_warn(tmp_path): + """Test reading NIRX files when missing data.""" + shutil.copytree(fname_nirx_15_2_short, str(tmp_path) + "/data/") + os.rename( + tmp_path / "data" / "NIRS-2019-08-23_001.dat", + tmp_path / "data" / "NIRS-2019-08-23_001.tmp", + ) + fname = tmp_path / "data" / "NIRS-2019-08-23_001.hdr" + with pytest.warns(RuntimeWarning, match="A single dat"): + read_raw_nirx(fname, preload=True) + + +@requires_testing_data +def test_nirx_15_2_short(): + """Test reading NIRX files.""" + raw = read_raw_nirx(fname_nirx_15_2_short, preload=True) + + # Test data import + assert raw._data.shape == (26, 145) + assert raw.info["sfreq"] == 12.5 + assert raw.info["meas_date"] == dt.datetime( + 2019, 8, 23, 7, 37, 4, 540000, tzinfo=dt.timezone.utc + ) + + # Test channel naming + assert raw.info["ch_names"][:4] == [ + "S1_D1 760", + "S1_D1 850", + "S1_D9 760", + "S1_D9 850", + ] + assert raw.info["ch_names"][24:26] == ["S5_D13 760", "S5_D13 850"] + + # Test frequency encoding + assert raw.info["chs"][0]["loc"][9] == 760 + assert raw.info["chs"][1]["loc"][9] == 850 + + # Test info import + assert raw.info["subject_info"] == dict( + sex=1, + first_name="MNE", + middle_name="Test", + last_name="Recording", + birthday=dt.date(2014, 8, 23), + his_id="MNE_Test_Recording", + ) + + # Test distance between optodes matches values from + # nirsite https://github.com/mne-tools/mne-testing-data/pull/51 + # step 4 figure 2 + allowed_distance_error = 0.0002 + assert_allclose( + source_detector_distances(raw.copy().pick("S1_D1 760").info), + [0.0304], + atol=allowed_distance_error, + ) + assert_allclose( + source_detector_distances(raw.copy().pick("S2_D10 760").info), + [0.0086], + atol=allowed_distance_error, + ) + + # Test which channels are short + # These are the ones marked as red at + # https://github.com/mne-tools/mne-testing-data/pull/51 step 4 figure 2 + is_short = short_channels(raw.info) + assert_array_equal(is_short[:9:2], [False, True, False, True, False]) + is_short = short_channels(raw.info, threshold=0.003) + assert_array_equal(is_short[:3:2], [False, False]) + is_short = short_channels(raw.info, threshold=50) + assert_array_equal(is_short[:3:2], [True, True]) + + # Test trigger events + assert_array_equal(raw.annotations.description, ["3.0", "2.0", "1.0"]) + + # Test location of detectors + # The locations of detectors can be seen in the first + # figure on this page... + # https://github.com/mne-tools/mne-testing-data/pull/51 + # And have been manually copied below + # These values were reported in mm, but according to this page... + # https://mne.tools/stable/auto_tutorials/intro/plot_40_sensor_locations.html + # 3d locations should be specified in meters, so that's what's tested below + # Detector locations are stored in the third three loc values + allowed_dist_error = 0.0002 + locs = [ch["loc"][6:9] for ch in raw.info["chs"]] + head_mri_t, _ = _get_trans("fsaverage", "head", "mri") + mni_locs = apply_trans(head_mri_t, locs) + + assert raw.info["ch_names"][0][3:5] == "D1" + assert_allclose(mni_locs[0], [-0.0841, -0.0464, -0.0129], atol=allowed_dist_error) + + assert raw.info["ch_names"][4][3:5] == "D3" + assert_allclose(mni_locs[4], [0.0846, -0.0142, -0.0156], atol=allowed_dist_error) + + assert raw.info["ch_names"][8][3:5] == "D2" + assert_allclose(mni_locs[8], [0.0207, -0.1062, 0.0484], atol=allowed_dist_error) + + assert raw.info["ch_names"][12][3:5] == "D4" + assert_allclose(mni_locs[12], [-0.0196, 0.0821, 0.0275], atol=allowed_dist_error) + + assert raw.info["ch_names"][16][3:5] == "D5" + assert_allclose(mni_locs[16], [-0.0360, 0.0276, 0.0778], atol=allowed_dist_error) + + assert raw.info["ch_names"][19][3:5] == "D6" + assert_allclose(mni_locs[19], [0.0352, 0.0283, 0.0780], atol=allowed_dist_error) + + assert raw.info["ch_names"][21][3:5] == "D7" + assert_allclose(mni_locs[21], [0.0388, -0.0477, 0.0932], atol=allowed_dist_error) + + +@requires_testing_data +def test_nirx_15_3_short(): + """Test reading NIRX files.""" + raw = read_raw_nirx(fname_nirx_15_3_short, preload=True) + + # Test data import + assert raw._data.shape == (26, 220) + assert raw.info["sfreq"] == 12.5 + + # Test channel naming + assert raw.info["ch_names"][:4] == [ + "S1_D2 760", + "S1_D2 850", + "S1_D9 760", + "S1_D9 850", + ] + assert raw.info["ch_names"][24:26] == ["S5_D13 760", "S5_D13 850"] + + # Test frequency encoding + assert raw.info["chs"][0]["loc"][9] == 760 + assert raw.info["chs"][1]["loc"][9] == 850 + + # Test info import + assert raw.info["subject_info"] == dict( + birthday=dt.date(2020, 8, 18), + sex=0, + first_name="testMontage\\0ATestMontage", + his_id="testMontage\\0ATestMontage", + ) + + # Test distance between optodes matches values from + # https://github.com/mne-tools/mne-testing-data/pull/72 + allowed_distance_error = 0.001 + assert_allclose( + source_detector_distances(raw.copy().pick("S1_D2 760").info), + [0.0304], + atol=allowed_distance_error, + ) + assert_allclose( + source_detector_distances(raw.copy().pick("S5_D13 760").info), + [0.0076], + atol=allowed_distance_error, + ) + + # Test which channels are short + # These are the ones marked as red at + # https://github.com/mne-tools/mne-testing-data/pull/72 + is_short = short_channels(raw.info) + assert_array_equal(is_short[:9:2], [False, True, False, True, False]) + is_short = short_channels(raw.info, threshold=0.003) + assert_array_equal(is_short[:3:2], [False, False]) + is_short = short_channels(raw.info, threshold=50) + assert_array_equal(is_short[:3:2], [True, True]) + + # Test trigger events + assert_array_equal(raw.annotations.description, ["4.0", "2.0", "1.0"]) + + # Test location of detectors + # The locations of detectors can be seen in the first + # figure on this page... + # https://github.com/mne-tools/mne-testing-data/pull/72 + # And have been manually copied below + allowed_dist_error = 0.0002 + locs = [ch["loc"][6:9] for ch in raw.info["chs"]] + head_mri_t, _ = _get_trans("fsaverage", "head", "mri") + mni_locs = apply_trans(head_mri_t, locs) + + assert raw.info["ch_names"][0][3:5] == "D2" + assert_allclose(mni_locs[0], [-0.0841, -0.0464, -0.0129], atol=allowed_dist_error) + + assert raw.info["ch_names"][4][3:5] == "D1" + assert_allclose(mni_locs[4], [0.0846, -0.0142, -0.0156], atol=allowed_dist_error) + + assert raw.info["ch_names"][8][3:5] == "D3" + assert_allclose(mni_locs[8], [0.0207, -0.1062, 0.0484], atol=allowed_dist_error) + + assert raw.info["ch_names"][12][3:5] == "D4" + assert_allclose(mni_locs[12], [-0.0196, 0.0821, 0.0275], atol=allowed_dist_error) + + assert raw.info["ch_names"][16][3:5] == "D5" + assert_allclose(mni_locs[16], [-0.0360, 0.0276, 0.0778], atol=allowed_dist_error) + + assert raw.info["ch_names"][19][3:5] == "D6" + assert_allclose(mni_locs[19], [0.0388, -0.0477, 0.0932], atol=allowed_dist_error) + + assert raw.info["ch_names"][21][3:5] == "D7" + assert_allclose(mni_locs[21], [-0.0394, -0.0483, 0.0928], atol=allowed_dist_error) + + +@requires_testing_data +def test_locale_encoding(tmp_path): + """Test NIRx encoding.""" + fname = tmp_path / "latin" + shutil.copytree(fname_nirx_15_2, fname) + hdr_fname = fname / "NIRS-2019-10-02_003.hdr" + hdr = list() + with open(hdr_fname, "rb") as fid: + hdr.extend(line for line in fid) + # French + hdr[2] = b'Date="jeu. 13 f\xe9vr. 2020"\r\n' + with open(hdr_fname, "wb") as fid: + for line in hdr: + fid.write(line) + read_raw_nirx(fname, verbose="debug") + # German + hdr[2] = b'Date="mi 13 dez 2020"\r\n' + with open(hdr_fname, "wb") as fid: + for line in hdr: + fid.write(line) + read_raw_nirx(fname, verbose="debug") + # Italian + hdr[2] = b'Date="ven 24 gen 2020"\r\n' + hdr[3] = b'Time="10:57:41.454"\r\n' + with open(hdr_fname, "wb") as fid: + for line in hdr: + fid.write(line) + raw = read_raw_nirx(fname, verbose="debug") + want_dt = dt.datetime(2020, 1, 24, 10, 57, 41, 454000, tzinfo=dt.timezone.utc) + assert raw.info["meas_date"] == want_dt + + +@requires_testing_data +def test_nirx_15_2(): + """Test reading NIRX files.""" + raw = read_raw_nirx(fname_nirx_15_2, preload=True) + + # Test data import + assert raw._data.shape == (64, 67) + assert raw.info["sfreq"] == 3.90625 + assert raw.info["meas_date"] == dt.datetime( + 2019, 10, 2, 9, 8, 47, 511000, tzinfo=dt.timezone.utc + ) + + # Test channel naming + assert raw.info["ch_names"][:4] == [ + "S1_D1 760", + "S1_D1 850", + "S1_D10 760", + "S1_D10 850", + ] + + # Test info import + assert raw.info["subject_info"] == dict( + sex=1, + first_name="TestRecording", + birthday=dt.date(1989, 10, 2), + his_id="TestRecording", + ) + + # Test trigger events + assert_array_equal(raw.annotations.description, ["4.0", "6.0", "2.0"]) + print(raw.annotations.onset) + + # Test location of detectors + allowed_dist_error = 0.0002 + locs = [ch["loc"][6:9] for ch in raw.info["chs"]] + head_mri_t, _ = _get_trans("fsaverage", "head", "mri") + mni_locs = apply_trans(head_mri_t, locs) + + assert raw.info["ch_names"][0][3:5] == "D1" + assert_allclose(mni_locs[0], [-0.0292, 0.0852, -0.0142], atol=allowed_dist_error) + + assert raw.info["ch_names"][15][3:5] == "D4" + assert_allclose(mni_locs[15], [-0.0739, -0.0756, -0.0075], atol=allowed_dist_error) + + # Old name aliases for backward compat + assert "fnirs_cw_amplitude" in raw + with pytest.raises(ValueError, match="Invalid value"): + "fnirs_raw" in raw + assert "fnirs_od" not in raw + picks = pick_types(raw.info, fnirs="fnirs_cw_amplitude") + assert len(picks) > 0 + + +@requires_testing_data +def test_nirx_aurora_2021_9_6(): + """Test reading NIRX files.""" + raw = read_raw_nirx(nirsport2_2021_9_6, preload=True) + assert len(raw.annotations) == 3 + assert raw.annotations.description[0] == "1.0" + assert raw.annotations.description[2] == "3.0" + + +@requires_testing_data +def test_nirx_15_0(): + """Test reading NIRX files.""" + raw = read_raw_nirx(fname_nirx_15_0, preload=True) + + # Test data import + assert raw._data.shape == (20, 92) + assert raw.info["sfreq"] == 6.25 + assert raw.info["meas_date"] == dt.datetime( + 2019, 10, 27, 13, 53, 34, 209000, tzinfo=dt.timezone.utc + ) + + # Test channel naming + assert raw.info["ch_names"][:12] == [ + "S1_D1 760", + "S1_D1 850", + "S2_D2 760", + "S2_D2 850", + "S3_D3 760", + "S3_D3 850", + "S4_D4 760", + "S4_D4 850", + "S5_D5 760", + "S5_D5 850", + "S6_D6 760", + "S6_D6 850", + ] + + # Test info import + assert raw.info["subject_info"] == { + "birthday": dt.date(2004, 10, 27), + "first_name": "NIRX", + "last_name": "Test", + "sex": FIFF.FIFFV_SUBJ_SEX_UNKNOWN, + "his_id": "NIRX_Test", + } + + # Test trigger events + assert_array_equal(raw.annotations.description, ["1.0", "2.0", "2.0"]) + + # Test location of detectors + allowed_dist_error = 0.0002 + locs = [ch["loc"][6:9] for ch in raw.info["chs"]] + head_mri_t, _ = _get_trans("fsaverage", "head", "mri") + mni_locs = apply_trans(head_mri_t, locs) + + assert raw.info["ch_names"][0][3:5] == "D1" + assert_allclose(mni_locs[0], [0.0287, -0.1143, -0.0332], atol=allowed_dist_error) + + assert raw.info["ch_names"][15][3:5] == "D8" + assert_allclose(mni_locs[15], [-0.0693, -0.0480, 0.0657], atol=allowed_dist_error) + + # Test distance between optodes matches values from + allowed_distance_error = 0.0002 + + assert_allclose( + source_detector_distances(raw.copy().pick("S1_D1 760").info), + [0.0300], + atol=allowed_distance_error, + ) + assert_allclose( + source_detector_distances(raw.copy().pick("S7_D7 760").info), + [0.0392], + atol=allowed_distance_error, + ) + + +@requires_testing_data +@pytest.mark.parametrize( + "fname, boundary_decimal", + ( + [fname_nirx_15_2_short, 1], + [fname_nirx_15_2, 0], + [fname_nirx_15_2, 0], + [nirsport2_2021_9, 0], + ), +) +def test_nirx_standard(fname, boundary_decimal): + """Test standard operations.""" + _test_raw_reader( + read_raw_nirx, fname=fname, boundary_decimal=boundary_decimal + ) # low fs + + +# Below are the native (on-disk) orders, which should be preserved +@requires_testing_data +@pytest.mark.parametrize( + "fname, want_order", + [ + ( + fname_nirx_15_0, + [ + "S1_D1", + "S2_D2", + "S3_D3", + "S4_D4", + "S5_D5", + "S6_D6", + "S7_D7", + "S8_D8", + "S9_D9", + "S10_D10", + ], + ), # noqa: E501 + ( + fname_nirx_15_2, + [ + "S1_D1", + "S1_D10", + "S2_D1", + "S2_D2", + "S3_D2", + "S3_D3", + "S4_D3", + "S4_D4", + "S5_D4", + "S5_D5", + "S6_D5", + "S6_D6", + "S7_D6", + "S7_D7", + "S8_D7", + "S8_D8", + "S9_D8", + "S9_D9", + "S10_D9", + "S10_D10", + "S11_D11", + "S11_D12", + "S12_D12", + "S12_D13", + "S13_D13", + "S13_D14", + "S14_D14", + "S14_D15", + "S15_D15", + "S15_D16", + "S16_D11", + "S16_D16", + ], + ), # noqa: E501 + ( + fname_nirx_15_2_short, + [ + "S1_D1", + "S1_D9", + "S2_D3", + "S2_D10", + "S3_D2", + "S3_D11", + "S4_D4", + "S4_D12", + "S5_D5", + "S5_D6", + "S5_D7", + "S5_D8", + "S5_D13", + ], + ), # noqa: E501 + ( + fname_nirx_15_3_short, + [ + "S1_D2", + "S1_D9", + "S2_D1", + "S2_D10", + "S3_D3", + "S3_D11", + "S4_D4", + "S4_D12", + "S5_D5", + "S5_D6", + "S5_D7", + "S5_D8", + "S5_D13", + ], + ), # noqa: E501 + ( + nirsport1_wo_sat, + [ + "S1_D4", + "S1_D5", + "S1_D6", + "S2_D5", + "S2_D6", + "S3_D5", + "S4_D1", + "S4_D3", + "S4_D4", + "S5_D1", + "S5_D2", + "S6_D1", + "S6_D3", + ], + ), # noqa: E501 + ( + nirsport2, + [ + "S1_D1", + "S1_D6", + "S1_D9", + "S2_D2", + "S2_D10", + "S3_D5", + "S3_D7", + "S3_D11", + "S4_D8", + "S4_D12", + "S5_D3", + "S5_D13", + "S6_D4", + "S6_D14", + "S7_D1", + "S7_D6", + "S7_D15", + "S8_D5", + "S8_D7", + "S8_D16", + ], + ), # noqa: E501 + ( + nirsport2_2021_9, + [ + "S1_D1", + "S1_D3", + "S2_D1", + "S2_D2", + "S2_D4", + "S3_D2", + "S3_D5", + "S4_D1", + "S4_D3", + "S4_D4", + "S4_D6", + "S5_D2", + "S5_D4", + "S5_D5", + "S5_D7", + "S6_D3", + "S6_D6", + "S7_D4", + "S7_D6", + "S7_D7", + "S8_D5", + "S8_D7", + ], + ), # noqa: E501 + ], +) +def test_channel_order(fname, want_order): + """Test that logical channel order is preserved.""" + raw = read_raw_nirx(fname) + ch_names = raw.ch_names + prefixes = [ch_name.split()[0] for ch_name in ch_names] + assert prefixes[::2] == prefixes[1::2] + prefixes = prefixes[::2] + assert prefixes == want_order diff --git a/mne-python/source/mne/io/nsx/__init__.py b/mne-python/source/mne/io/nsx/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..cb2500e2235ca22a491ec66baecefda791d8edcf --- /dev/null +++ b/mne-python/source/mne/io/nsx/__init__.py @@ -0,0 +1,7 @@ +"""NSx module for reading Blackrock Microsystem files.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .nsx import read_raw_nsx diff --git a/mne-python/source/mne/io/nsx/nsx.py b/mne-python/source/mne/io/nsx/nsx.py new file mode 100644 index 0000000000000000000000000000000000000000..1fc8a6968ea2c29b70ea56777e2316e79587e070 --- /dev/null +++ b/mne-python/source/mne/io/nsx/nsx.py @@ -0,0 +1,537 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +from datetime import datetime, timezone + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _empty_info +from ..._fiff.utils import _file_size, _read_segments_file +from ...annotations import Annotations +from ...utils import _check_fname, fill_doc, logger, warn +from ..base import BaseRaw, _get_scaling + +CH_TYPE_MAPPING = { + "CC": "SEEG", +} + + +# See https://blackrockneurotech.com/wp-content/uploads/LB-0023-7.00_NEV_File_Format.pdf +DATA_BYTE_SIZE = 2 +ORIG_FORMAT = "short" + + +nsx_header_dict = { + "basic": [ + ("file_id", "S8"), # achFileType + # file specification split into major and minor version number + ("ver_major", "uint8"), + ("ver_minor", "uint8"), + # bytes of basic & extended header + ("bytes_in_headers", "uint32"), + # label of the sampling group (e.g., "1 kS/s" or "LFP low") + ("label", "S16"), + ("comment", "S256"), + ("period", "uint32"), + ("timestamp_resolution", "uint32"), + # time origin: 2byte uint16 values for ... + ("year", "uint16"), + ("month", "uint16"), + ("weekday", "uint16"), + ("day", "uint16"), + ("hour", "uint16"), + ("minute", "uint16"), + ("second", "uint16"), + ("millisecond", "uint16"), + # number of channel_count match number of extended headers + ("channel_count", "uint32"), + ], + "extended": [ + ("type", "S2"), + ("electrode_id", "uint16"), + ("electrode_label", "S16"), + # used front-end amplifier bank (e.g., A, B, C, D) + ("physical_connector", "uint8"), + # used connector pin (e.g., 1-37 on bank A, B, C or D) + ("connector_pin", "uint8"), + # digital and analog value ranges of the signal + ("min_digital_val", "int16"), + ("max_digital_val", "int16"), + ("min_analog_val", "int16"), + ("max_analog_val", "int16"), + # units of the analog range values ("mV" or "uV") + ("units", "S16"), + # filter settings used to create nsx from source signal + ("hi_freq_corner", "uint32"), + ("hi_freq_order", "uint32"), + ("hi_freq_type", "uint16"), # 0=None, 1=Butterworth + ("lo_freq_corner", "uint32"), + ("lo_freq_order", "uint32"), + ("lo_freq_type", "uint16"), + ], # 0=None, 1=Butterworth, + "data>2.1<3": [ + ("header", "uint8"), + ("timestamp", "uint32"), + ("nb_data_points", "uint32"), + ], + "data>=3": [ + ("header", "uint8"), + ("timestamp", "uint64"), + ("nb_data_points", "uint32"), + ], +} + + +@fill_doc +def read_raw_nsx( + input_fname, stim_channel=True, eog=None, misc=None, preload=False, *, verbose=None +) -> "RawNSX": + """Reader function for NSx (Blackrock Microsystems) files. + + Parameters + ---------- + input_fname : str + Path to the NSx file. + stim_channel : ``'auto'`` | str | list of str | int | list of int + Defaults to ``'auto'``, which means that channels named ``'status'`` or + ``'trigger'`` (case insensitive) are set to STIM. If str (or list of + str), all channels matching the name(s) are set to STIM. If int (or + list of ints), channels corresponding to the indices are set to STIM. + eog : list or tuple + Names of channels or list of indices that should be designated EOG + channels. Values should correspond to the electrodes in the file. + Default is None. + misc : list or tuple + Names of channels or list of indices that should be designated MISC + channels. Values should correspond to the electrodes in the file. + Default is None. + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawEDF + The raw instance. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + Notes + ----- + NSx files with id (= NEURALSG), i.e., version 2.1 is currently not + supported. + + If channels named 'status' or 'trigger' are present, they are considered as + STIM channels by default. Use func:`mne.find_events` to parse events + encoded in such analog stim channels. + """ + input_fname = _check_fname( + input_fname, overwrite="read", must_exist=True, name="input_fname" + ) + if not input_fname.suffix.lower().startswith(".ns"): + raise NotImplementedError( + f"Only NSx files are supported, got {input_fname.suffix}." + ) + return RawNSX( + input_fname, stim_channel, eog, misc, preload=preload, verbose=verbose + ) + + +@fill_doc +class RawNSX(BaseRaw): + """Raw object from NSx file from Blackrock Microsystems. + + Parameters + ---------- + input_fname : str + Path to the NSx file. + stim_channel : ``'auto'`` | str | list of str | int | list of int + Defaults to ``'auto'``, which means that channels named ``'status'`` or + ``'trigger'`` (case insensitive) are set to STIM. If str (or list of + str), all channels matching the name(s) are set to STIM. If int (or + list of ints), channels corresponding to the indices are set to STIM. + eog : list or tuple + Names of channels or list of indices that should be designated EOG + channels. Values should correspond to the electrodes in the file. + Default is None. + misc : list or tuple + Names of channels or list of indices that should be designated MISC + channels. Values should correspond to the electrodes in the file. + Default is None. + %(preload)s + %(verbose)s + + Notes + ----- + NSx files with id (= NEURALSG), i.e., version 2.1 is currently not + supported. + + If channels named 'status' or 'trigger' are present, they are considered as + STIM channels by default. Use func:`mne.find_events` to parse events + encoded in such analog stim channels. + """ + + def __init__( + self, + input_fname, + stim_channel="auto", + eog=None, + misc=None, + preload=False, + verbose=None, + ): + logger.info(f"Extracting NSX parameters from {input_fname}...") + input_fname = os.path.abspath(input_fname) + ( + info, + data_fname, + fmt, + n_samples, + orig_format, + raw_extras, + orig_units, + ) = _get_hdr_info(input_fname, stim_channel=stim_channel, eog=eog, misc=misc) + raw_extras["orig_format"] = orig_format + first_samps = (raw_extras["timestamp"][0],) + super().__init__( + info, + first_samps=first_samps, + last_samps=[first_samps[0] + n_samples - 1], + filenames=[data_fname], + orig_format=orig_format, + preload=preload, + verbose=verbose, + raw_extras=[raw_extras], + orig_units=orig_units, + ) + + # Add annotations for in-data skips + if len(self._raw_extras[0]["timestamp"]) > 1: + starts = ( + self._raw_extras[0]["timestamp"] + self._raw_extras[0]["nb_data_points"] + )[:-1] + 1 + stops = self._raw_extras[0]["timestamp"][1:] - 1 + durations = (stops - starts + 1) / self.info["sfreq"] + annot = Annotations( + onset=(starts / self.info["sfreq"]), + duration=durations, + description="BAD_ACQ_SKIP", + orig_time=self.info["meas_date"], + ) + self.set_annotations(annot) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a chunk of raw data.""" + dtype = self._raw_extras[fi]["orig_format"] + first_samps = self._raw_extras[fi]["timestamp"] + recording_extents = self._raw_extras[fi]["nb_data_points"] + offsets = self._raw_extras[fi]["offset_to_data_block"] + for first_samp, recording_extent, offset in zip( + first_samps, recording_extents, offsets + ): + if start > first_samp + recording_extent or stop < first_samp: + # There is nothing to read in this chunk + continue + i_start = max(start, first_samp) + i_stop = min(stop, first_samp + recording_extent) + _read_segments_file( + self, + data[:, i_start - start : i_stop - start], + idx, + fi, + i_start - first_samp, + i_stop - first_samp, + cals, + mult, + dtype, + n_channels=None, + offset=offset, + trigger_ch=None, + ) + + +def _read_header(fname): + nsx_file_id = np.fromfile(fname, count=1, dtype=[("file_id", "S8")])[0][ + "file_id" + ].decode() + + if nsx_file_id in ["NEURALCD", "BRSMPGRP"]: + basic_header = _read_header_22_and_above(fname) + elif nsx_file_id == "NEURALSG": + raise NotImplementedError( + "NSx file id (= NEURALSG), i.e., file" + " version 2.1 is currently not supported." + ) + else: + raise ValueError( + f"NSx file id (={nsx_file_id}) does not match" + " with supported file ids:" + " ('NEURALCD', 'BRSMPGRP')" + ) + + time_origin = datetime( + *[ + basic_header.pop(xx) + for xx in ( + "year", + "month", + "day", + "hour", + "minute", + "second", + "millisecond", + ) + ], + tzinfo=timezone.utc, + ) + basic_header["meas_date"] = time_origin + return basic_header + + +def _read_header_22_and_above(fname): + basic_header = {} + dtype0 = nsx_header_dict["basic"] + dtype1 = nsx_header_dict["extended"] + + nsx_file_header = np.fromfile(fname, count=1, dtype=dtype0)[0] + basic_header.update( + {name: nsx_file_header[name] for name in nsx_file_header.dtype.names} + ) + + offset_dtype0 = np.dtype(dtype0).itemsize + shape = nsx_file_header["channel_count"] + basic_header["extended"] = np.memmap( + fname, shape=shape, offset=offset_dtype0, dtype=dtype1, mode="r" + ) + + # The following values are stored in mHz + # See: + # https://blackrockneurotech.com/wp-content/uploads/LB-0023-7.00_NEV_File_Format.pdf + basic_header["highpass"] = basic_header["extended"]["hi_freq_corner"] + basic_header["lowpass"] = basic_header["extended"]["lo_freq_corner"] + for x in ["highpass", "lowpass"]: + basic_header[x] = basic_header[x] * 1e-3 + + ver_major, ver_minor = basic_header.pop("ver_major"), basic_header.pop("ver_minor") + basic_header["spec"] = f"{ver_major}.{ver_minor}" + + data_header = list() + index = 0 + offset = basic_header["bytes_in_headers"] + filesize = _file_size(fname) + if float(basic_header["spec"]) < 3.0: + dtype2 = nsx_header_dict["data>2.1<3"] + else: + dtype2 = nsx_header_dict["data>=3"] + while offset < filesize: + dh = np.memmap(fname, dtype=dtype2, shape=1, offset=offset, mode="r")[0] + data_header.append( + { + "header": dh["header"], + "timestamp": dh["timestamp"], + "nb_data_points": dh["nb_data_points"], + "offset_to_data_block": offset + dh.dtype.itemsize, + } + ) + # data size = number of data points * (data_bytes * number of channels) + # use of `int` avoids overflow problem + data_size = ( + int(dh["nb_data_points"]) + * int(basic_header["channel_count"]) + * DATA_BYTE_SIZE + ) + # define new offset (to possible next data block) + offset = data_header[index]["offset_to_data_block"] + data_size + index += 1 + + basic_header["data_header"] = data_header + return basic_header + + +def _get_hdr_info(fname, stim_channel=True, eog=None, misc=None): + """Read header information NSx file.""" + eog = eog if eog is not None else [] + misc = misc if misc is not None else [] + + nsx_info = _read_header(fname) + ch_names = list(nsx_info["extended"]["electrode_label"]) + ch_types = list(nsx_info["extended"]["type"]) + ch_units = list(nsx_info["extended"]["units"]) + ch_names, ch_types, ch_units = ( + list(map(bytes.decode, xx)) for xx in (ch_names, ch_types, ch_units) + ) + max_analog_val = nsx_info["extended"]["max_analog_val"].astype("double") + min_analog_val = nsx_info["extended"]["min_analog_val"].astype("double") + max_digital_val = nsx_info["extended"]["max_digital_val"].astype("double") + min_digital_val = nsx_info["extended"]["min_digital_val"].astype("double") + cals = (max_analog_val - min_analog_val) / (max_digital_val - min_digital_val) + + stim_channel_idxs, _ = _check_stim_channel(stim_channel, ch_names) + + nchan = int(nsx_info["channel_count"]) + logger.info("Setting channel info structure...") + chs = list() + pick_mask = np.ones(len(ch_names)) + + orig_units = {} + for idx, ch_name in enumerate(ch_names): + chan_info = {} + chan_info["logno"] = int(nsx_info["extended"]["electrode_id"][idx]) + chan_info["scanno"] = int(nsx_info["extended"]["electrode_id"][idx]) + chan_info["ch_name"] = ch_name + chan_info["unit_mul"] = FIFF.FIFF_UNITM_NONE + ch_unit = ch_units[idx] + chan_info["unit"] = FIFF.FIFF_UNIT_V + # chan_info["range"] = _unit_range_dict[ch_units[idx]] + chan_info["range"] = 1 / _get_scaling("eeg", ch_units[idx]) + chan_info["cal"] = cals[idx] + chan_info["coord_frame"] = FIFF.FIFFV_COORD_HEAD + chan_info["coil_type"] = FIFF.FIFFV_COIL_EEG + chan_info["kind"] = FIFF.FIFFV_SEEG_CH + # montage can't be stored in NSx so channel locs are unknown: + chan_info["loc"] = np.full(12, np.nan) + orig_units[ch_name] = ch_unit + + # if the NSx info contained channel type information + # set it now. They are always set to 'CC'. + # If not inferable, set it to 'SEEG' with a warning. + ch_type = ch_types[idx] + ch_const = getattr(FIFF, f"FIFFV_{CH_TYPE_MAPPING.get(ch_type, 'SEEG')}_CH") + chan_info["kind"] = ch_const + # if user passes in explicit mapping for eog, misc and stim + # channels set them here. + if ch_name in eog or idx in eog or idx - nchan in eog: + chan_info["coil_type"] = FIFF.FIFFV_COIL_NONE + chan_info["kind"] = FIFF.FIFFV_EOG_CH + pick_mask[idx] = False + elif ch_name in misc or idx in misc or idx - nchan in misc: + chan_info["coil_type"] = FIFF.FIFFV_COIL_NONE + chan_info["kind"] = FIFF.FIFFV_MISC_CH + pick_mask[idx] = False + elif idx in stim_channel_idxs: + chan_info["coil_type"] = FIFF.FIFFV_COIL_NONE + chan_info["unit"] = FIFF.FIFF_UNIT_NONE + chan_info["kind"] = FIFF.FIFFV_STIM_CH + pick_mask[idx] = False + chan_info["ch_name"] = ch_name + ch_names[idx] = chan_info["ch_name"] + chs.append(chan_info) + + sfreq = nsx_info["timestamp_resolution"] / nsx_info["period"] + info = _empty_info(sfreq) + info["meas_date"] = nsx_info["meas_date"] + info["chs"] = chs + info["ch_names"] = ch_names + + highpass = nsx_info["highpass"][:128] + lowpass = nsx_info["lowpass"][:128] + _decode_online_filters(info, highpass, lowpass) + + # Some keys to be consistent with FIF measurement info + info["description"] = None + + info._unlocked = False + info._update_redundant() + + orig_format = ORIG_FORMAT + + raw_extras = { + key: [r[key] for r in nsx_info["data_header"]] + for key in nsx_info["data_header"][0] + } + for key in raw_extras: + raw_extras[key] = np.array(raw_extras[key], int) + good_data_packets = raw_extras.pop("header") == 1 + if not good_data_packets.any(): + raise RuntimeError("NSx file appears to be broken") + raw_extras = {key: raw_extras[key][good_data_packets] for key in raw_extras.keys()} + raw_extras["timestamp"] = raw_extras["timestamp"] // nsx_info["period"] + first_samp = raw_extras["timestamp"][0] + last_samp = raw_extras["timestamp"][-1] + raw_extras["nb_data_points"][-1] + n_samples = last_samp - first_samp + + return ( + info, + fname, + nsx_info["spec"], + n_samples, + orig_format, + raw_extras, + orig_units, + ) + + +def _decode_online_filters(info, highpass, lowpass): + """Decode low/high-pass filters that are applied online.""" + if np.all(highpass == highpass[0]): + if highpass[0] == "NaN": + # Placeholder for future use. Highpass set in _empty_info. + pass + else: + hp = float(highpass[0]) + info["highpass"] = hp + else: + info["highpass"] = float(np.max(highpass)) + warn( + "Channels contain different highpass filters. Highest filter " + "setting will be stored." + ) + + if np.all(lowpass == lowpass[0]): + if lowpass[0] in ("NaN", "0", "0.0"): + # Placeholder for future use. Lowpass set in _empty_info. + pass + else: + info["lowpass"] = float(lowpass[0]) + else: + info["lowpass"] = float(np.min(lowpass)) + warn( + "Channels contain different lowpass filters. Lowest filter " + "setting will be stored." + ) + + +def _check_stim_channel(stim_channel, ch_names): + """Check that the stimulus channel exists in the current datafile.""" + DEFAULT_STIM_CH_NAMES = ["status", "trigger"] + + if stim_channel is None or stim_channel is False: + return [], [] + + if stim_channel is True: # convenient aliases + stim_channel = "auto" + + if isinstance(stim_channel, str): + if stim_channel == "auto": + if "auto" in ch_names: + warn( + RuntimeWarning, + "Using `stim_channel='auto'` when auto" + " also corresponds to a channel name is ambiguous." + " Please use `stim_channel=['auto']`.", + ) + else: + valid_stim_ch_names = DEFAULT_STIM_CH_NAMES + else: + valid_stim_ch_names = [stim_channel.lower()] + + elif isinstance(stim_channel, int): + valid_stim_ch_names = [ch_names[stim_channel].lower()] + + elif isinstance(stim_channel, list): + if all([isinstance(s, str) for s in stim_channel]): + valid_stim_ch_names = [s.lower() for s in stim_channel] + elif all([isinstance(s, int) for s in stim_channel]): + valid_stim_ch_names = [ch_names[s].lower() for s in stim_channel] + else: + raise ValueError("Invalid stim_channel") + else: + raise ValueError("Invalid stim_channel") + + ch_names_low = [ch.lower() for ch in ch_names] + found = list(set(valid_stim_ch_names) & set(ch_names_low)) + + stim_channel_idxs = [ch_names_low.index(f) for f in found] + names = [ch_names[idx] for idx in stim_channel_idxs] + return stim_channel_idxs, names diff --git a/mne-python/source/mne/io/nsx/tests/test_nsx.py b/mne-python/source/mne/io/nsx/tests/test_nsx.py new file mode 100644 index 0000000000000000000000000000000000000000..fa1f708adc5d927a4ee4e256a9f5a295577b4a9b --- /dev/null +++ b/mne-python/source/mne/io/nsx/tests/test_nsx.py @@ -0,0 +1,282 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os + +import numpy as np +import pytest +from numpy.testing import assert_allclose + +from mne import make_fixed_length_epochs +from mne._fiff.constants import FIFF +from mne._fiff.meas_info import _empty_info +from mne.datasets.testing import data_path, requires_testing_data +from mne.io import read_raw_nsx +from mne.io.nsx.nsx import _decode_online_filters, _read_header +from mne.io.tests.test_raw import _test_raw_reader + +testing_path = data_path(download=False) +nsx_21_fname = os.path.join(testing_path, "nsx", "test_NEURALSG_raw.ns3") +nsx_22_fname = os.path.join(testing_path, "nsx", "test_NEURALCD_raw.ns3") +nsx_31_fname = os.path.join(testing_path, "nsx", "test_BRSMPGRP_raw.ns3") +nsx_test_fname = os.path.join(testing_path, "nsx", "Test_anonymized.ns3") +edf_test_fname = os.path.join(testing_path, "EDF", "test_reduced.edf") + + +def test_decode_online_filters(): + """Tests for online low/high-pass filter decoding.""" + info = _empty_info(100.0) + highpass = np.array([0.0, 0.1]) + lowpass = np.array([50, 50]) + with pytest.warns(RuntimeWarning, match="different highpass filters"): + _decode_online_filters(info, highpass, lowpass) + assert info["highpass"] == 0.1 + + info = _empty_info(100.0) + highpass = np.array([0.0, 0.0]) + lowpass = np.array([40, 50]) + with pytest.warns(RuntimeWarning, match="different lowpass filters"): + _decode_online_filters(info, highpass, lowpass) + assert info["lowpass"] == 40 + + info = _empty_info(100.0) + highpass = np.array(["NaN", "NaN"]) + lowpass = np.array(["NaN", "NaN"]) + _decode_online_filters(info, highpass, lowpass) + assert info["highpass"] == 0.0 + assert info["lowpass"] == 50.0 + + +@requires_testing_data +def test_filetype_checks(): + """Tests for various error meaasges for wrong filetypes.""" + with pytest.raises(ValueError, match="does not match"): + _read_header(edf_test_fname) + with pytest.raises(NotImplementedError, match="Only NSx files"): + read_raw_nsx(edf_test_fname) + + +@requires_testing_data +def test_nsx_ver_31(): + """Primary tests for BRSMPGRP reader.""" + raw = read_raw_nsx(nsx_31_fname) + assert getattr(raw, "_data", False) is False + assert raw.info["sfreq"] == 2000 + + # Check info object + assert raw.info["meas_date"].day == 31 + assert raw.info["meas_date"].year == 2023 + assert raw.info["meas_date"].month == 1 + assert raw.info["chs"][0]["cal"] == 0.6103515625 + assert raw.info["chs"][0]["range"] == 0.001 + + # Check raw_extras + for r in raw._raw_extras: + assert r["orig_format"] == raw.orig_format + assert r["orig_nchan"] == 128 + assert len(r["timestamp"]) == len(r["nb_data_points"]) + assert len(r["timestamp"]) == len(r["offset_to_data_block"]) + + # Check annotations + assert raw.annotations[0]["onset"] * raw.info["sfreq"] == 101 + assert raw.annotations[0]["duration"] * raw.info["sfreq"] == 49 + + # Ignore following RuntimeWarning in mne/io/base.py in _write_raw_data + # "Acquisition skips detected but did not fit evenly into output" + # "buffer_size, will be written as zeroes." + with pytest.warns(RuntimeWarning, match="skips detected"): + raw = _test_raw_reader( + read_raw_nsx, + input_fname=nsx_31_fname, + eog=None, + misc=None, + test_scaling=False, + test_rank=False, + ) + raw_data, _ = raw[:] + n_channels, n_times = raw_data.shape + assert n_times == 300 + assert n_channels == 128 + + # Check data + # There are two contiguous data packets (samples 0--100 and + # samples 150--300. Each data was generated as: + # ```data = np.ones((n_samples, ch_count)) + # data[n_samples // 2] = np.arange(ch_count) + 10 + # data[:, ch_count // 2] = np.arange(n_samples) + 100``` + orig_data = raw_data / (raw.info["chs"][0]["cal"] * raw.info["chs"][0]["range"]) + assert_allclose(sum(orig_data[:, 50] - 10 - np.arange(n_channels)), 76.0) + + assert_allclose(orig_data[n_channels // 2, :100] - 100, np.arange(100)) + assert_allclose(orig_data[n_channels // 2, 150:] - 100, np.arange(150)) + + data, times = raw.get_data(start=10, stop=20, return_times=True) + assert 128, 10 == data.shape + + data, times = raw.get_data(start=50, stop=110, return_times=True) + assert 128, 50 == data.shape + + data, times = raw.get_data(start=130, stop=170, return_times=True) + assert 128, 40 == data.shape + + data, times = raw.get_data(start=200, stop=350, return_times=True) + assert 128, 100 == data.shape + + data, times = raw.get_data(start=0, stop=300, return_times=True) + epochs = make_fixed_length_epochs(raw, duration=0.05, preload=False) + assert len(epochs.events) == 3 + epochs = make_fixed_length_epochs(raw, duration=0.05, preload=True) + assert len(epochs) == 2 + assert "BAD_ACQ_SKIP" in epochs.drop_log[1] + + +@requires_testing_data +def test_nsx_ver_22(): + """Primary tests for NEURALCD reader.""" + raw = read_raw_nsx( + nsx_22_fname, + ) + assert getattr(raw, "_data", False) is False + assert raw.info["sfreq"] == 2000 + + # Check info object + assert raw.info["meas_date"].day == 31 + assert raw.info["meas_date"].year == 2023 + assert raw.info["meas_date"].month == 1 + assert raw.info["chs"][0]["cal"] == 0.6103515625 + assert raw.info["chs"][0]["range"] == 0.001 + + # check raw_extras + for r in raw._raw_extras: + assert r["orig_format"] == raw.orig_format + assert r["orig_nchan"] == 128 + assert len(r["timestamp"]) == len(r["nb_data_points"]) + assert len(r["timestamp"]) == len(r["offset_to_data_block"]) + + # Check annotations + assert len(raw.annotations) == 0 + + raw = _test_raw_reader( + read_raw_nsx, + input_fname=nsx_22_fname, + eog=None, + misc=None, + test_scaling=False, # XXX this should be True + test_rank=False, + ) + raw_data, _ = raw[:] + n_channels, n_times = raw_data.shape + assert n_times == 100 + assert n_channels == 128 + + # Check data + # There is only one contiguous data packet, samples 0--100. Data + # was generated as: + # ```data = np.ones((n_samples, ch_count)) + # data[n_samples // 2] = np.arange(ch_count) + 10 + # data[:, ch_count // 2] = np.arange(n_samples) + 100``` + orig_data = raw_data / (raw.info["chs"][0]["cal"] * raw.info["chs"][0]["range"]) + assert_allclose(sum(orig_data[:, 50] - 10 - np.arange(n_channels)), 76.0) + + assert_allclose(orig_data[n_channels // 2, :100] - 100, np.arange(100)) + + data, _ = raw.get_data(start=10, stop=20, return_times=True) + assert 128, 10 == data.shape + + data, _ = raw.get_data(start=0, stop=300, return_times=True) + assert 128, 100 == data.shape + + epochs = make_fixed_length_epochs(raw, duration=0.05, preload=True, id=1) + assert len(epochs) == 1 + assert epochs.event_id["1"] == 1 + with pytest.raises(ValueError, match="No events produced"): + _ = make_fixed_length_epochs(raw, duration=0.5, preload=True) + + +@requires_testing_data +def test_stim_eog_misc_chs_in_nsx(): + """Test stim/misc/eog channel assignments.""" + raw = read_raw_nsx(nsx_22_fname, stim_channel="elec127", eog=["elec126"]) + assert raw.info["chs"][127]["kind"] == FIFF.FIFFV_STIM_CH + assert raw.info["chs"][126]["kind"] == FIFF.FIFFV_EOG_CH + raw = read_raw_nsx(nsx_22_fname, stim_channel=["elec127"], eog=["elec126"]) + assert raw.info["chs"][127]["kind"] == FIFF.FIFFV_STIM_CH + assert raw.info["chs"][126]["kind"] == FIFF.FIFFV_EOG_CH + raw = read_raw_nsx(nsx_22_fname, stim_channel=127, eog=["elec126"]) + assert raw.info["chs"][127]["kind"] == FIFF.FIFFV_STIM_CH + assert raw.info["chs"][126]["kind"] == FIFF.FIFFV_EOG_CH + raw = read_raw_nsx(nsx_22_fname, stim_channel=[127], eog=["elec126"]) + assert raw.info["chs"][127]["kind"] == FIFF.FIFFV_STIM_CH + assert raw.info["chs"][126]["kind"] == FIFF.FIFFV_EOG_CH + stims = [ch_info["kind"] == FIFF.FIFFV_STIM_CH for ch_info in raw.info["chs"]] + assert np.any(stims) + assert raw.info["chs"][126]["kind"] == FIFF.FIFFV_EOG_CH + with pytest.raises(ValueError, match="Invalid stim_channel"): + raw = read_raw_nsx(nsx_22_fname, stim_channel=["elec128", 129], eog=["elec126"]) + with pytest.raises(ValueError, match="Invalid stim_channel"): + raw = read_raw_nsx(nsx_22_fname, stim_channel=("elec128",), eog=["elec126"]) + + raw = read_raw_nsx(nsx_22_fname, stim_channel="elec127", misc=["elec126", "elec1"]) + assert raw.info["chs"][126]["kind"] == FIFF.FIFFV_MISC_CH + assert raw.info["chs"][1]["kind"] == FIFF.FIFFV_MISC_CH + + +@requires_testing_data +def test_nsx_ver_21(): + """Primary tests for NEURALSG reader.""" + with pytest.raises(NotImplementedError, match="(= NEURALSG)*not supported"): + read_raw_nsx(nsx_21_fname) + + +@requires_testing_data +def test_nsx(): + """Tests for NEURALCD reader using real anonymized data.""" + raw = read_raw_nsx( + nsx_test_fname, + ) + assert getattr(raw, "_data", False) is False + assert raw.info["sfreq"] == 2000 + + # Check info object + assert raw.info["meas_date"].day == 13 + assert raw.info["meas_date"].year == 2000 + assert raw.info["meas_date"].month == 6 + assert raw.info["lowpass"] == 1000 + assert raw.info["highpass"] == 0.3 + assert raw.info["chs"][0]["cal"] == 0.25 + assert raw.info["chs"][0]["range"] == 1e-6 + + # check raw_extras + for r in raw._raw_extras: + assert r["orig_format"] == raw.orig_format + assert r["orig_nchan"] == 5 + assert len(r["timestamp"]) == len(r["nb_data_points"]) + assert len(r["timestamp"]) == len(r["offset_to_data_block"]) + + # Check annotations + assert len(raw.annotations) == 0 + + raw = _test_raw_reader( + read_raw_nsx, + input_fname=nsx_test_fname, + eog=None, + misc=None, + ) + raw_data, times = raw[:] + n_channels, n_times = raw_data.shape + assert n_times == 100 + assert times.shape[0] == n_times + assert n_channels == 5 + # Check data + assert_allclose( + raw_data.mean(axis=-1), + np.array([-52.6375, 88.57, 70.5825, -22.055, -166.5]) * 1e-6, # uV + ) + assert raw.first_time == 3.8 + + epochs = make_fixed_length_epochs(raw, duration=0.05, preload=True, id=1) + assert len(epochs) == 1 + assert epochs.event_id["1"] == 1 + with pytest.raises(ValueError, match="No events produced"): + _ = make_fixed_length_epochs(raw, duration=0.5, preload=True) diff --git a/mne-python/source/mne/io/persyst/__init__.py b/mne-python/source/mne/io/persyst/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..aac04211ff8d7ab2b6105c811c39a1b8dede6fc0 --- /dev/null +++ b/mne-python/source/mne/io/persyst/__init__.py @@ -0,0 +1,7 @@ +"""Persyst module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from .persyst import read_raw_persyst diff --git a/mne-python/source/mne/io/persyst/persyst.py b/mne-python/source/mne/io/persyst/persyst.py new file mode 100644 index 0000000000000000000000000000000000000000..8de44286445c3be30962d0694981b418b2ed6703 --- /dev/null +++ b/mne-python/source/mne/io/persyst/persyst.py @@ -0,0 +1,474 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import os.path as op +from collections import OrderedDict +from datetime import datetime, timezone + +import numpy as np + +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import create_info +from ..._fiff.utils import _mult_cal_one +from ...annotations import Annotations +from ...utils import _check_fname, fill_doc, logger, verbose, warn +from ..base import BaseRaw + + +@fill_doc +def read_raw_persyst(fname, preload=False, verbose=None) -> "RawPersyst": + """Reader for a Persyst (.lay/.dat) recording. + + Parameters + ---------- + fname : path-like + Path to the Persyst header ``.lay`` file. + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawPersyst + A Raw object containing Persyst data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawPersyst. + + Notes + ----- + It is assumed that the ``.lay`` and ``.dat`` file + are in the same directory. To get the correct file path to the + ``.dat`` file, ``read_raw_persyst`` will get the corresponding dat + filename from the lay file, and look for that file inside the same + directory as the lay file. + """ + return RawPersyst(fname, preload, verbose) + + +@fill_doc +class RawPersyst(BaseRaw): + """Raw object from a Persyst file. + + Parameters + ---------- + fname : path-like + Path to the Persyst header (.lay) file. + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + @verbose + def __init__(self, fname, preload=False, verbose=None): + fname = str(_check_fname(fname, "read", True, "fname")) + logger.info(f"Loading {fname}") + + # make sure filename is the Lay file + if not fname.endswith(".lay"): + fname = fname + ".lay" + # get the current directory and Lay filename + curr_path, lay_fname = op.dirname(fname), op.basename(fname) + if not op.exists(fname): + raise FileNotFoundError( + f'The path you specified, "{lay_fname}",does not exist.' + ) + + # sections and subsections currently unused + keys, data, sections = _read_lay_contents(fname) + + # these are the section headers in the Persyst file layout + # Note: We do not make use of "SampleTimes" yet + fileinfo_dict = OrderedDict() + channelmap_dict = OrderedDict() + patient_dict = OrderedDict() + comments_dict = OrderedDict() + + # keep track of total number of comments + num_comments = 0 + + # loop through each line in the lay file + for key, val, section in zip(keys, data, sections): + if key == "": + continue + + # Make sure key are lowercase for everything, but electrodes. + # We also do not want to lower-case comments because those + # are free-form text where casing may matter. + if key is not None and section not in ["channelmap", "comments"]: + key = key.lower() + + # FileInfo + if section == "fileinfo": + # extract the .dat file name + if key == "file": + dat_fname = op.basename(val) + dat_fpath = op.join(curr_path, op.basename(dat_fname)) + + # determine if .dat file exists where it should + error_msg = ( + f"The data path you specified " + f"does not exist for the lay path, " + f"{lay_fname}. Make sure the dat file " + f"is in the same directory as the lay " + f"file, and the specified dat filename " + f"matches." + ) + if not op.exists(dat_fpath): + raise FileNotFoundError(error_msg) + fileinfo_dict[key] = val + # ChannelMap + elif section == "channelmap": + # channel map has = for = + channelmap_dict[key] = val + # Patient (All optional) + elif section == "patient": + patient_dict[key] = val + # Comments (turned into mne.Annotations) + elif section == "comments": + comments_dict[key] = comments_dict.get(key, list()) + [val] + num_comments += 1 + + # get numerical metadata + # datatype is either 7 for 32 bit, or 0 for 16 bit + datatype = fileinfo_dict.get("datatype") + cal = float(fileinfo_dict.get("calibration")) + n_chs = int(fileinfo_dict.get("waveformcount")) + + # Store subject information from lay file in mne format + # Note: Persyst also records "Physician", "Technician", + # "Medications", "History", and "Comments1" and "Comments2" + # and this information is currently discarded + subject_info = _get_subjectinfo(patient_dict) + + # set measurement date + testdate = patient_dict.get("testdate") + if testdate is not None: + # TODO: Persyst may change its internal date schemas + # without notice + # These are the 3 "so far" possible datatime storage + # formats in Persyst .lay + if "/" in testdate: + testdate = datetime.strptime(testdate, "%m/%d/%Y") + elif "-" in testdate: + testdate = datetime.strptime(testdate, "%d-%m-%Y") + elif "." in testdate: + testdate = datetime.strptime(testdate, "%Y.%m.%d") + + if not isinstance(testdate, datetime): + warn( + "Cannot read in the measurement date due " + "to incompatible format. Please set manually " + f"for {lay_fname} " + ) + meas_date = None + else: + testtime = datetime.strptime(patient_dict.get("testtime"), "%H:%M:%S") + meas_date = datetime( + year=testdate.year, + month=testdate.month, + day=testdate.day, + hour=testtime.hour, + minute=testtime.minute, + second=testtime.second, + tzinfo=timezone.utc, + ) + + # Create mne structure + ch_names = list(channelmap_dict.keys()) + if n_chs != len(ch_names): + raise RuntimeError( + "Channels in lay file do not " + "match the number of channels " + "in the .dat file." + ) # noqa + # get rid of the "-Ref" in channel names + ch_names = [ch.upper().split("-REF")[0] for ch in ch_names] + + # get the sampling rate and default channel types to EEG + sfreq = fileinfo_dict.get("samplingrate") + ch_types = "eeg" + info = create_info(ch_names, sfreq, ch_types=ch_types) + info.update(subject_info=subject_info) + with info._unlock(): + for idx in range(n_chs): + # calibration brings to uV then 1e-6 brings to V + info["chs"][idx]["cal"] = cal * 1.0e-6 + info["meas_date"] = meas_date + + # determine number of samples in file + # Note: We do not use the lay file to do this + # because clips in time may be generated by Persyst that + # DO NOT modify the "SampleTimes" section + with open(dat_fpath, "rb") as f: + # determine the precision + if int(datatype) == 7: + # 32 bit + dtype = np.dtype("i4") + elif int(datatype) == 0: + # 16 bit + dtype = np.dtype("i2") + else: + raise RuntimeError(f"Unknown format: {datatype}") + + # allow offset to occur + f.seek(0, os.SEEK_END) + n_samples = f.tell() + n_samples = n_samples // (dtype.itemsize * n_chs) + + logger.debug(f"Loaded {n_samples} samples for {n_chs} channels.") + + raw_extras = {"dtype": dtype, "n_chs": n_chs, "n_samples": n_samples} + # create Raw object + super().__init__( + info, + preload, + filenames=[dat_fpath], + last_samps=[n_samples - 1], + raw_extras=[raw_extras], + verbose=verbose, + ) + + # set annotations based on the comments read in + onset = np.zeros(num_comments, float) + duration = np.zeros(num_comments, float) + description = [""] * num_comments + + # loop through comments dictionary, which may contain + # multiple events for the same "text" annotation + t_idx = 0 + for _description, event_tuples in comments_dict.items(): + for _onset, _duration in event_tuples: + # extract the onset, duration, description to + # create an Annotations object + onset[t_idx] = _onset + duration[t_idx] = _duration + description[t_idx] = _description + t_idx += 1 + annot = Annotations(onset, duration, description) + self.set_annotations(annot) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a segment of data from a file. + + The Persyst software records raw data in either 16 or 32 bit + binary files. In addition, it stores the calibration to convert + data to uV in the lay file. + """ + dtype = self._raw_extras[fi]["dtype"] + n_chs = self._raw_extras[fi]["n_chs"] + dat_fname = self.filenames[fi] + + # compute samples count based on start and stop + time_length_samps = stop - start + + # read data from .dat file into array of correct size, then calibrate + # records = recnum rows x inf columns + count = time_length_samps * n_chs + + # seek the dat file + with open(dat_fname, "rb") as dat_file_ID: + # allow offset to occur + dat_file_ID.seek(n_chs * dtype.itemsize * start, 1) + + # read in the actual record starting at possibly offset + record = np.fromfile(dat_file_ID, dtype=dtype, count=count) + + # chs * rows + # cast as float32; more than enough precision + record = np.reshape(record, (n_chs, -1), order="F").astype(np.float32) + + # calibrate to convert to V and handle mult + _mult_cal_one(data, record, idx, cals, mult) + + +def _get_subjectinfo(patient_dict): + # attempt to parse out the birthdate, but if it doesn't + # meet spec, then it will set to None + birthdate = patient_dict.get("birthdate") + if "/" in birthdate: + try: + birthdate = datetime.strptime(birthdate, "%m/%d/%y") + except ValueError: + birthdate = None + print(f"Unable to process birthdate of {birthdate} ") + elif "-" in birthdate: + try: + birthdate = datetime.strptime(birthdate, "%d-%m-%y") + except ValueError: + birthdate = None + print(f"Unable to process birthdate of {birthdate} ") + + subject_info = { + "first_name": patient_dict.get("first"), + "middle_name": patient_dict.get("middle"), + "last_name": patient_dict.get("last"), + "sex": patient_dict.get("sex"), + "hand": patient_dict.get("hand"), + "his_id": patient_dict.get("id"), + "birthday": birthdate, + } + subject_info = {key: val for key, val in subject_info.items() if val is not None} + + # Recode sex values + sex_dict = dict( + m=FIFF.FIFFV_SUBJ_SEX_MALE, + male=FIFF.FIFFV_SUBJ_SEX_MALE, + f=FIFF.FIFFV_SUBJ_SEX_FEMALE, + female=FIFF.FIFFV_SUBJ_SEX_FEMALE, + ) + subject_info["sex"] = sex_dict.get(subject_info["sex"], FIFF.FIFFV_SUBJ_SEX_UNKNOWN) + + # Recode hand values + hand_dict = dict( + r=FIFF.FIFFV_SUBJ_HAND_RIGHT, + right=FIFF.FIFFV_SUBJ_HAND_RIGHT, + l=FIFF.FIFFV_SUBJ_HAND_LEFT, + left=FIFF.FIFFV_SUBJ_HAND_LEFT, + a=FIFF.FIFFV_SUBJ_HAND_AMBI, + ambidextrous=FIFF.FIFFV_SUBJ_HAND_AMBI, + ambi=FIFF.FIFFV_SUBJ_HAND_AMBI, + ) + # no handedness is set when unknown + try: + subject_info["hand"] = hand_dict[subject_info["hand"]] + except KeyError: + subject_info.pop("hand") + + return subject_info + + +def _read_lay_contents(fname): + """Lay file are laid out like a INI file.""" + # keep track of sections, keys and data + sections = [] + keys, data = [], [] + + # initialize all section to empty str + section = "" + with open(fname) as fin: + for line in fin: + # break a line into a status, key and value + status, key, val = _process_lay_line(line, section) + + # handle keys and values if they are + # Section, Subsections, or Line items + if status == 1: # Section was found + section = val.lower() + continue + + # keep track of all sections, subsections, + # keys and the data of the file + sections.append(section) + data.append(val) + keys.append(key) + + return keys, data, sections + + +def _process_lay_line(line, section): + """Process a line read from the Lay (INI) file. + + Each line in the .lay file will be processed + into a structured ``status``, ``key`` and ``value``. + + Parameters + ---------- + line : str + The actual line in the Lay file. + section : str + The section in the Lay file. + + Returns + ------- + status : int + Returns the following integers based on status. + -1 => unknown string found + 0 => empty line found + 1 => section found + 2 => key-value pair found + key : str + The string before the ``'='`` character. If section is "Comments", + then returns the text comment description. + value : str + The string from the line after the ``'='`` character. If section is + "Comments", then returns the onset and duration as a tuple. + + Notes + ----- + The lay file comprises of multiple "sections" that are documented with + bracket ``[]`` characters. For example, ``[FileInfo]`` and the lines + afterward indicate metadata about the data file itself. Within + each section, there are multiple lines in the format of + ``=``. + + For ``FileInfo``, ``Patient`` and ``ChannelMap`` + each line will be denoted with a ``key`` and a ``value`` that + can be represented as a dictionary. The keys describe what sort + of data that line holds, while the values contain the corresponding + value. In some cases, the ``value``. + + For ``SampleTimes``, the ``key`` and ``value`` pair indicate the + start and end time in seconds of the original data file. + + For ``Comments`` section, this denotes an area where users through + Persyst actually annotate data in time. These are instead + represented as 5 data points that are ``,`` delimited. These + data points are ordered as: + + 1. time (in seconds) of the annotation + 2. duration (in seconds) of the annotation + 3. state (unused) + 4. variable type (unused) + 5. free-form text describing the annotation + """ + key = "" # default; only return value possibly not set + line = line.strip() # remove leading and trailing spaces + end_idx = len(line) - 1 # get the last index of the line + + # empty sequence evaluates to false + if not line: + status = 0 + key = "" + value = "" + return status, key, value + # section found + elif (line[0] == "[") and (line[end_idx] == "]") and (end_idx + 1 >= 3): + status = 1 + value = line[1:end_idx].lower() + # key found + else: + # handle Comments section differently from all other sections + # TODO: utilize state and var_type in code. + # Currently not used + if section == "comments": + # Persyst Comments output 5 variables "," separated + time_sec, duration, state, var_type, text = line.split(",", 4) + del var_type, state + status = 2 + key = text + value = (time_sec, duration) + # all other sections + else: + if "=" not in line: + raise RuntimeError( + f"The line {line} does not conform " + "to the standards. Please check the " + ".lay file." + ) # noqa + pos = line.index("=") + status = 2 + + # the line now is composed of a + # = + key = line[0:pos] + key.strip() + value = line[pos + 1 : end_idx + 1] + value.strip() + return status, key, value diff --git a/mne-python/source/mne/io/persyst/tests/__init__.py b/mne-python/source/mne/io/persyst/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/persyst/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/persyst/tests/test_persyst.py b/mne-python/source/mne/io/persyst/tests/test_persyst.py new file mode 100644 index 0000000000000000000000000000000000000000..986a37b9dbb30d7e6478e185712a673ff7183e30 --- /dev/null +++ b/mne-python/source/mne/io/persyst/tests/test_persyst.py @@ -0,0 +1,255 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os +import shutil + +import numpy as np +import pytest +from numpy.testing import assert_array_equal + +from mne.datasets.testing import data_path, requires_testing_data +from mne.io import read_raw_persyst +from mne.io.tests.test_raw import _test_raw_reader + +testing_path = data_path(download=False) +fname_lay = ( + testing_path / "Persyst" / "sub-pt1_ses-02_task-monitor_acq-ecog_run-01_clip2.lay" +) +fname_dat = ( + testing_path / "Persyst" / "sub-pt1_ses-02_task-monitor_acq-ecog_run-01_clip2.dat" +) + + +@requires_testing_data +def test_persyst_lay_load(): + """Test reading Persyst files using path to header file.""" + raw = read_raw_persyst(fname_lay, preload=False) + + # Test data import + assert raw.info["sfreq"] == 200 + assert raw.preload is False + + # load raw data + raw.load_data() + assert raw._data.shape == (83, 847) + assert raw.preload is True + + # defaults channels to EEG + raw = raw.pick("eeg") + assert len(raw.ch_names) == 83 + + # no "-Ref" in channel names + assert all(["-ref" not in ch.lower() for ch in raw.ch_names]) + + # test with preload True + raw = read_raw_persyst(fname_lay, preload=True) + + +@requires_testing_data +def test_persyst_raw(): + """Test reading Persyst files using path to header file.""" + raw = read_raw_persyst(fname_lay, preload=False) + + # defaults channels to EEG + raw = raw.pick("eeg") + + # get data + data, times = raw.get_data(start=200, return_times=True) + assert data.shape == (83, 647) + + # seconds should match up to what is in the file + assert times.min() == 1.0 + assert times.max() == 4.23 + + # get data + data = raw.get_data(start=200, stop=400) + assert data.shape == (83, 200) + + # data should have been set correctly + assert not data.min() == 0 and not data.max() == 0 + + first_ch_data = raw.get_data(picks=[0], start=200, stop=400) + assert_array_equal(first_ch_data.squeeze(), data[0, :]) + + +@requires_testing_data +def test_persyst_dates(tmp_path): + """Test different Persyst date formats for meas date.""" + # now test what if you change contents of the lay file + new_fname_lay = tmp_path / fname_lay.name + new_fname_dat = tmp_path / fname_dat.name + shutil.copy(fname_dat, new_fname_dat) + + # reformat the lay file to have testdate with + # "/" character + with open(fname_lay) as fin: + with open(new_fname_lay, "w") as fout: + # for each line in the input file + for idx, line in enumerate(fin): + if line.startswith("TestDate"): + line = "TestDate=01/23/2000\n" + fout.write(line) + # file should update correctly with datetime + raw = read_raw_persyst(new_fname_lay) + assert raw.info["meas_date"].month == 1 + assert raw.info["meas_date"].day == 23 + assert raw.info["meas_date"].year == 2000 + + # reformat the lay file to have testdate with + # "-" character + os.remove(new_fname_lay) + with open(fname_lay) as fin: + with open(new_fname_lay, "w") as fout: + # for each line in the input file + for idx, line in enumerate(fin): + if line.startswith("TestDate"): + line = "TestDate=24-01-2000\n" + fout.write(line) + # file should update correctly with datetime + raw = read_raw_persyst(new_fname_lay) + assert raw.info["meas_date"].month == 1 + assert raw.info["meas_date"].day == 24 + assert raw.info["meas_date"].year == 2000 + + +@requires_testing_data +def test_persyst_wrong_file(tmp_path): + """Test reading Persyst files when passed in wrong file path.""" + with pytest.raises(FileNotFoundError, match="The path you"): + read_raw_persyst(fname_dat, preload=True) + + new_fname_lay = tmp_path / fname_lay.name + new_fname_dat = tmp_path / fname_dat.name + shutil.copy(fname_lay, new_fname_lay) + + # without a .dat file, reader should break + desired_err_msg = ( + "The data path you specified does " + "not exist for the lay path, " + "sub-pt1_ses-02_task-monitor_acq-ecog_run-01_clip2.lay" + ) + with pytest.raises(FileNotFoundError, match=desired_err_msg): + read_raw_persyst(new_fname_lay, preload=True) + + # once you copy over the .dat file things should work + shutil.copy(fname_dat, new_fname_dat) + read_raw_persyst(new_fname_lay, preload=True) + + +@requires_testing_data +def test_persyst_moved_file(tmp_path): + """Test reader - Persyst files need to be in same directory.""" + new_fname_lay = tmp_path / fname_lay.name + new_fname_dat = tmp_path / fname_dat.name + shutil.copy(fname_lay, new_fname_lay) + + # original file read should work + read_raw_persyst(fname_lay) + + # without a .dat file, reader should break + # when the lay file was moved + desired_err_msg = ( + "The data path you specified does " + "not exist for the lay path, " + "sub-pt1_ses-02_task-monitor_acq-ecog_run-01_clip2.lay" + ) + with pytest.raises(FileNotFoundError, match=desired_err_msg): + read_raw_persyst(new_fname_lay, preload=True) + + # now change the file contents to point + # to the full path, but it should still not work + # as reader requires lay and dat file to be in + # same directory + with open(fname_lay) as fin: + with open(new_fname_lay, "w") as fout: + # for each line in the input file + for idx, line in enumerate(fin): + if line.startswith("File="): + # give it the full path to the old data + test_fpath = fname_dat.parent / line.split("=")[1] + line = f"File={test_fpath}\n" + fout.write(line) + with pytest.raises(FileNotFoundError, match=desired_err_msg): + read_raw_persyst(new_fname_lay, preload=True) + + # once we copy the dat file to the same directory, reader + # should work + shutil.copy(fname_dat, new_fname_dat) + read_raw_persyst(new_fname_lay, preload=True) + + +@requires_testing_data +def test_persyst_standard(): + """Test standard operations.""" + _test_raw_reader(read_raw_persyst, fname=fname_lay) + + +@requires_testing_data +def test_persyst_annotations(tmp_path): + """Test annotations reading in Persyst.""" + new_fname_lay = tmp_path / fname_lay.name + new_fname_dat = tmp_path / fname_dat.name + shutil.copy(fname_dat, new_fname_dat) + shutil.copy(fname_lay, new_fname_lay) + + raw = read_raw_persyst(new_fname_lay) + raw.crop(tmin=0, tmax=4) + + # get the annotations and make sure that repeated annotations + # are in the dataset + annotations = raw.annotations + assert np.count_nonzero(annotations.description == "seizure") == 2 + + # make sure annotation with a "," character is in there + assert "seizure1,2" in annotations.description + assert "CLip2" in annotations.description + + +@requires_testing_data +def test_persyst_errors(tmp_path): + """Test reading Persyst files when passed in wrong file path.""" + new_fname_lay = tmp_path / fname_lay.name + new_fname_dat = tmp_path / fname_dat.name + shutil.copy(fname_dat, new_fname_dat) + + # reformat the lay file + with open(fname_lay) as fin: + with open(new_fname_lay, "w") as fout: + # for each line in the input file + for idx, line in enumerate(fin): + if idx == 1: + line = line.replace("=", ",") + fout.write(line) + # file should break + with pytest.raises(RuntimeError, match="The line"): + read_raw_persyst(new_fname_lay) + + # reformat the lay file + os.remove(new_fname_lay) + with open(fname_lay) as fin: + with open(new_fname_lay, "w") as fout: + # for each line in the input file + for idx, line in enumerate(fin): + if line.startswith("WaveformCount"): + line = "WaveformCount=1\n" + fout.write(line) + # file should break + with pytest.raises(RuntimeError, match="Channels in lay file do not"): + read_raw_persyst(new_fname_lay) + + # reformat the lay file to have testdate + # improperly specified + os.remove(new_fname_lay) + with open(fname_lay) as fin: + with open(new_fname_lay, "w") as fout: + # for each line in the input file + for idx, line in enumerate(fin): + if line.startswith("TestDate"): + line = "TestDate=Jan 23rd 2000\n" + fout.write(line) + # file should not read in meas date + with pytest.warns(RuntimeWarning, match="Cannot read in the measurement date"): + raw = read_raw_persyst(new_fname_lay) + assert raw.info["meas_date"] is None diff --git a/mne-python/source/mne/io/pick.py b/mne-python/source/mne/io/pick.py new file mode 100644 index 0000000000000000000000000000000000000000..e78cfc854425983ab7c2ccdc4ed6a9e1183a6a01 --- /dev/null +++ b/mne-python/source/mne/io/pick.py @@ -0,0 +1,18 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + + +from .._fiff.pick import ( + _DATA_CH_TYPES_ORDER_DEFAULT, + _DATA_CH_TYPES_SPLIT, + _picks_to_idx, +) + +__all__ = [ + # mne-bids, autoreject, mne-connectivity, mne-realtime, mne-nirs, mne-realtime + "_picks_to_idx", + # mne-qt-browser + "_DATA_CH_TYPES_ORDER_DEFAULT", + "_DATA_CH_TYPES_SPLIT", +] diff --git a/mne-python/source/mne/io/snirf/__init__.py b/mne-python/source/mne/io/snirf/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a50ff500a416609b468b3ebdbc1f9a05b6bcf550 --- /dev/null +++ b/mne-python/source/mne/io/snirf/__init__.py @@ -0,0 +1,7 @@ +"""SNIRF module for conversion to FIF.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from ._snirf import read_raw_snirf diff --git a/mne-python/source/mne/io/snirf/_snirf.py b/mne-python/source/mne/io/snirf/_snirf.py new file mode 100644 index 0000000000000000000000000000000000000000..1b3f940a58d080adedd21e4118ab44e49f8da1c1 --- /dev/null +++ b/mne-python/source/mne/io/snirf/_snirf.py @@ -0,0 +1,608 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime +import re + +import numpy as np + +from ..._fiff._digitization import _make_dig_points +from ..._fiff.constants import FIFF +from ..._fiff.meas_info import _format_dig_points, create_info +from ..._fiff.utils import _mult_cal_one +from ..._freesurfer import get_mni_fiducials +from ...annotations import Annotations +from ...transforms import _frame_to_str, apply_trans +from ...utils import ( + _check_fname, + _import_h5py, + _validate_type, + fill_doc, + logger, + verbose, + warn, +) +from ..base import BaseRaw +from ..nirx.nirx import _convert_fnirs_to_head + + +@fill_doc +def read_raw_snirf( + fname, optode_frame="unknown", *, sfreq=None, preload=False, verbose=None +) -> "RawSNIRF": + """Reader for a continuous wave SNIRF data. + + .. note:: This reader supports the .snirf file type only, + not the .jnirs version. + Files with either 3D or 2D locations can be read. + However, we strongly recommend using 3D positions. + If 2D positions are used the behaviour of MNE functions + can not be guaranteed. + + Parameters + ---------- + fname : path-like + Path to the SNIRF data file. + optode_frame : str + Coordinate frame used for the optode positions. The default is unknown, + in which case the positions are not modified. If a known coordinate + frame is provided (head, meg, mri), then the positions are transformed + in to the Neuromag head coordinate frame (head). + sfreq : float | None + The nominal sampling frequency at which the data were acquired. If ``None``, + will be estimated from the time data in the file. + + .. versionadded:: 1.10 + %(preload)s + %(verbose)s + + Returns + ------- + raw : instance of RawSNIRF + A Raw object containing fNIRS data. + See :class:`mne.io.Raw` for documentation of attributes and methods. + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods of RawSNIRF. + """ + return RawSNIRF(fname, optode_frame, sfreq=sfreq, preload=preload, verbose=verbose) + + +def _open(fname): + return open(fname, encoding="latin-1") + + +@fill_doc +class RawSNIRF(BaseRaw): + """Raw object from a continuous wave SNIRF file. + + Parameters + ---------- + fname : path-like + Path to the SNIRF data file. + optode_frame : str + Coordinate frame used for the optode positions. The default is unknown, + in which case the positions are not modified. If a known coordinate + frame is provided (head, meg, mri), then the positions are transformed + in to the Neuromag head coordinate frame (head). + sfreq : float | None + The nominal sampling frequency at which the data were acquired. If ``None``, + will be estimated from the time data in the file. + + .. versionadded:: 1.10 + %(preload)s + %(verbose)s + + See Also + -------- + mne.io.Raw : Documentation of attributes and methods. + """ + + @verbose + def __init__( + self, fname, optode_frame="unknown", *, sfreq=None, preload=False, verbose=None + ): + # Must be here due to circular import error + from ...preprocessing.nirs import _validate_nirs_info + + h5py = _import_h5py() + + fname = str(_check_fname(fname, "read", True, "fname")) + logger.info(f"Loading {fname}") + + with h5py.File(fname, "r") as dat: + if "data2" in dat["nirs"]: + warn( + "File contains multiple recordings. " + "MNE does not support this feature. " + "Only the first dataset will be processed." + ) + + manufacturer = _get_metadata_str(dat, "ManufacturerName") + if (optode_frame == "unknown") & (manufacturer == "Gowerlabs"): + optode_frame = "head" + + snirf_data_type = np.array( + dat.get("nirs/data1/measurementList1/dataType") + ).item() + if snirf_data_type not in [1, 99999]: + # 1 = Continuous Wave + # 99999 = Processed + raise RuntimeError( + "MNE only supports reading continuous" + " wave amplitude and processed haemoglobin" + " SNIRF files. Expected type" + " code 1 or 99999 but received type " + f"code {snirf_data_type}" + ) + + last_samps = dat.get("/nirs/data1/dataTimeSeries").shape[0] - 1 + + sampling_rate = _extract_sampling_rate(dat, sfreq) + + if sampling_rate == 0: + warn("Unable to extract sample rate from SNIRF file.") + + # Extract wavelengths + fnirs_wavelengths = np.array(dat.get("nirs/probe/wavelengths")) + fnirs_wavelengths = [int(w) for w in fnirs_wavelengths] + if len(fnirs_wavelengths) < 2: + raise RuntimeError( + f"The data contains " + f"{len(fnirs_wavelengths)}" + f" wavelengths: {fnirs_wavelengths}. " + f"MNE requires at least two wavelengths for " + "continuous wave amplitude SNIRF files." + ) + + # Extract channels + def atoi(text): + return int(text) if text.isdigit() else text + + def natural_keys(text): + return [atoi(c) for c in re.split(r"(\d+)", text)] + + channels = np.array([name for name in dat["nirs"]["data1"].keys()]) + channels_idx = np.array(["measurementList" in n for n in channels]) + channels = channels[channels_idx] + channels = sorted(channels, key=natural_keys) + + # Source and detector labels are optional fields. + # Use S1, S2, S3, etc if not specified. + if "sourceLabels_disabled" in dat["nirs/probe"]: + # This is disabled as + # MNE-Python does not currently support custom source names. + # Instead, sources must be integer values. + sources = np.array(dat.get("nirs/probe/sourceLabels")) + sources = [s.decode("UTF-8") for s in sources] + else: + sources = np.unique( + [ + _correct_shape( + np.array(dat.get("nirs/data1/" + c + "/sourceIndex")) + )[0] + for c in channels + ] + ) + sources = {int(s): f"S{int(s)}" for s in sources} + + if "detectorLabels_disabled" in dat["nirs/probe"]: + # This is disabled as + # MNE-Python does not currently support custom detector names. + # Instead, detector must be integer values. + detectors = np.array(dat.get("nirs/probe/detectorLabels")) + detectors = [d.decode("UTF-8") for d in detectors] + else: + detectors = np.unique( + [ + _correct_shape( + np.array(dat.get("nirs/data1/" + c + "/detectorIndex")) + )[0] + for c in channels + ] + ) + detectors = {int(d): f"D{int(d)}" for d in detectors} + + # Extract source and detector locations + # 3D positions are optional in SNIRF, + # but highly recommended in MNE. + if ("detectorPos3D" in dat["nirs/probe"]) & ( + "sourcePos3D" in dat["nirs/probe"] + ): + # If 3D positions are available they are used even if 2D exists + detPos3D = np.array(dat.get("nirs/probe/detectorPos3D")) + srcPos3D = np.array(dat.get("nirs/probe/sourcePos3D")) + elif ("detectorPos2D" in dat["nirs/probe"]) & ( + "sourcePos2D" in dat["nirs/probe"] + ): + warn( + "The data only contains 2D location information for the " + "optode positions. " + "It is highly recommended that data is used " + "which contains 3D location information for the " + "optode positions. With only 2D locations it can not be " + "guaranteed that MNE functions will behave correctly " + "and produce accurate results. If it is not possible to " + "include 3D positions in your data, please consider " + "using the set_montage() function." + ) + + detPos2D = np.array(dat.get("nirs/probe/detectorPos2D")) + srcPos2D = np.array(dat.get("nirs/probe/sourcePos2D")) + # Set the third dimension to zero. See gh#9308 + detPos3D = np.append(detPos2D, np.zeros((detPos2D.shape[0], 1)), axis=1) + srcPos3D = np.append(srcPos2D, np.zeros((srcPos2D.shape[0], 1)), axis=1) + + else: + raise RuntimeError( + "No optode location information is " + "provided. MNE requires at least 2D " + "location information" + ) + + chnames = [] + ch_types = [] + for chan in channels: + src_idx = int( + _correct_shape( + np.array(dat.get("nirs/data1/" + chan + "/sourceIndex")) + )[0] + ) + det_idx = int( + _correct_shape( + np.array(dat.get("nirs/data1/" + chan + "/detectorIndex")) + )[0] + ) + + if snirf_data_type == 1: + wve_idx = int( + _correct_shape( + np.array(dat.get("nirs/data1/" + chan + "/wavelengthIndex")) + )[0] + ) + ch_name = ( + sources[src_idx] + + "_" + + detectors[det_idx] + + " " + + str(fnirs_wavelengths[wve_idx - 1]) + ) + chnames.append(ch_name) + ch_types.append("fnirs_cw_amplitude") + + elif snirf_data_type == 99999: + dt_id = _correct_shape( + np.array(dat.get("nirs/data1/" + chan + "/dataTypeLabel")) + )[0].decode("UTF-8") + + # Convert between SNIRF processed names and MNE type names + dt_id = dt_id.lower().replace("dod", "fnirs_od") + + ch_name = sources[src_idx] + "_" + detectors[det_idx] + + if dt_id == "fnirs_od": + wve_idx = int( + _correct_shape( + np.array( + dat.get("nirs/data1/" + chan + "/wavelengthIndex") + ) + )[0] + ) + suffix = " " + str(fnirs_wavelengths[wve_idx - 1]) + else: + suffix = " " + dt_id.lower() + ch_name = ch_name + suffix + + chnames.append(ch_name) + ch_types.append(dt_id) + + # Create mne structure + info = create_info(chnames, sampling_rate, ch_types=ch_types) + + subject_info = {} + names = np.array(dat.get("nirs/metaDataTags/SubjectID")) + names = _correct_shape(names)[0].decode("UTF-8") + subject_info["his_id"] = names + # Read non standard (but allowed) custom metadata tags + if "lastName" in dat.get("nirs/metaDataTags/"): + ln = dat.get("/nirs/metaDataTags/lastName")[0].decode("UTF-8") + subject_info["last_name"] = ln + if "middleName" in dat.get("nirs/metaDataTags/"): + m = dat.get("/nirs/metaDataTags/middleName")[0].decode("UTF-8") + subject_info["middle_name"] = m + if "firstName" in dat.get("nirs/metaDataTags/"): + fn = dat.get("/nirs/metaDataTags/firstName")[0].decode("UTF-8") + subject_info["first_name"] = fn + else: + # MNE < 1.7 used to not write the firstName tag, so pull it from names + subject_info["first_name"] = names.split("_")[0] + if "sex" in dat.get("nirs/metaDataTags/"): + s = dat.get("/nirs/metaDataTags/sex")[0].decode("UTF-8") + if s in {"M", "Male", "1", "m"}: + subject_info["sex"] = FIFF.FIFFV_SUBJ_SEX_MALE + elif s in {"F", "Female", "2", "f"}: + subject_info["sex"] = FIFF.FIFFV_SUBJ_SEX_FEMALE + elif s in {"0", "u"}: + subject_info["sex"] = FIFF.FIFFV_SUBJ_SEX_UNKNOWN + # End non standard name reading + # Update info + info.update(subject_info=subject_info) + + length_unit = _get_metadata_str(dat, "LengthUnit") + length_scaling = _get_lengthunit_scaling(length_unit) + + srcPos3D /= length_scaling + detPos3D /= length_scaling + + if optode_frame in ["mri", "meg"]: + # These are all in MNI or MEG coordinates, so let's transform + # them to the Neuromag head coordinate frame + srcPos3D, detPos3D, _, head_t = _convert_fnirs_to_head( + "fsaverage", optode_frame, "head", srcPos3D, detPos3D, [] + ) + else: + head_t = np.eye(4) + + if optode_frame in ["head", "mri", "meg"]: + # Then the transformation to head was performed above + coord_frame = FIFF.FIFFV_COORD_HEAD + elif "MNE_coordFrame" in dat.get("nirs/metaDataTags/"): + coord_frame = int(dat.get("/nirs/metaDataTags/MNE_coordFrame")[0]) + else: + coord_frame = FIFF.FIFFV_COORD_UNKNOWN + + for idx, chan in enumerate(channels): + src_idx = int( + _correct_shape( + np.array(dat.get("nirs/data1/" + chan + "/sourceIndex")) + )[0] + ) + det_idx = int( + _correct_shape( + np.array(dat.get("nirs/data1/" + chan + "/detectorIndex")) + )[0] + ) + + info["chs"][idx]["loc"][3:6] = srcPos3D[src_idx - 1, :] + info["chs"][idx]["loc"][6:9] = detPos3D[det_idx - 1, :] + # Store channel as mid point + midpoint = ( + info["chs"][idx]["loc"][3:6] + info["chs"][idx]["loc"][6:9] + ) / 2 + info["chs"][idx]["loc"][0:3] = midpoint + info["chs"][idx]["coord_frame"] = coord_frame + + if (snirf_data_type in [1]) or ( + (snirf_data_type == 99999) and (ch_types[idx] == "fnirs_od") + ): + wve_idx = int( + _correct_shape( + np.array(dat.get("nirs/data1/" + chan + "/wavelengthIndex")) + )[0] + ) + info["chs"][idx]["loc"][9] = fnirs_wavelengths[wve_idx - 1] + + if "landmarkPos3D" in dat.get("nirs/probe/"): + diglocs = np.array(dat.get("/nirs/probe/landmarkPos3D")) + diglocs /= length_scaling + digname = np.array(dat.get("/nirs/probe/landmarkLabels")) + # Handle empty or scalar landmarkLabels (see gh-13627) + if digname.ndim == 0 or digname.size == 0: + digname = [] + else: + digname = _correct_shape(digname) + nasion, lpa, rpa, hpi = None, None, None, None + extra_ps = dict() + for idx, dign in enumerate(digname): + dign = dign.lower() + if dign in [b"lpa", b"al"]: + lpa = diglocs[idx, :3] + elif dign in [b"nasion", b"nz"]: + nasion = diglocs[idx, :3] + elif dign in [b"rpa", b"ar"]: + rpa = diglocs[idx, :3] + else: + extra_ps[f"EEG{len(extra_ps) + 1:03d}"] = diglocs[idx, :3] + add_missing_fiducials = ( + coord_frame == FIFF.FIFFV_COORD_HEAD + and lpa is None + and rpa is None + and nasion is None + ) + dig = _make_dig_points( + nasion=nasion, + lpa=lpa, + rpa=rpa, + hpi=hpi, + dig_ch_pos=extra_ps, + coord_frame=_frame_to_str[coord_frame], + add_missing_fiducials=add_missing_fiducials, + ) + else: + ch_locs = [info["chs"][idx]["loc"][0:3] for idx in range(len(channels))] + # Set up digitization + dig = get_mni_fiducials("fsaverage", verbose=False) + for fid in dig: + fid["r"] = apply_trans(head_t, fid["r"]) + fid["coord_frame"] = FIFF.FIFFV_COORD_HEAD + for ii, ch_loc in enumerate(ch_locs, 1): + dig.append( + dict( + kind=FIFF.FIFFV_POINT_EEG, # misnomer prob okay + r=ch_loc, + ident=ii, + coord_frame=FIFF.FIFFV_COORD_HEAD, + ) + ) + dig = _format_dig_points(dig) + del head_t + with info._unlock(): + info["dig"] = dig + + str_date = _correct_shape( + np.array(dat.get("/nirs/metaDataTags/MeasurementDate")) + )[0].decode("UTF-8") + str_time = _correct_shape( + np.array(dat.get("/nirs/metaDataTags/MeasurementTime")) + )[0].decode("UTF-8") + str_datetime = str_date + str_time + + # Several formats have been observed so we try each in turn + for dt_code in [ + "%Y-%m-%d%H:%M:%SZ", + "%Y-%m-%d%H:%M:%S", + "%Y-%m-%d%H:%M:%S.%f", + "%Y-%m-%d%H:%M:%S.%f%z", + ]: + try: + meas_date = datetime.datetime.strptime(str_datetime, dt_code) + except ValueError: + pass + else: + break + else: + warn( + "Extraction of measurement date from SNIRF file failed. " + "The date is being set to January 1st, 2000, " + f"instead of {str_datetime}" + ) + meas_date = datetime.datetime(2000, 1, 1, 0, 0, 0) + meas_date = meas_date.replace(tzinfo=datetime.timezone.utc) + with info._unlock(): + info["meas_date"] = meas_date + + if "DateOfBirth" in dat.get("nirs/metaDataTags/"): + str_birth = ( + np.array(dat.get("/nirs/metaDataTags/DateOfBirth")).item().decode() + ) + birth_matched = re.fullmatch(r"(\d+)-(\d+)-(\d+)", str_birth) + if birth_matched is not None: + birthday = datetime.date( + int(birth_matched.groups()[0]), + int(birth_matched.groups()[1]), + int(birth_matched.groups()[2]), + ) + with info._unlock(): + info["subject_info"]["birthday"] = birthday + + super().__init__( + info, + preload, + filenames=[fname], + last_samps=[last_samps], + verbose=verbose, + ) + + # Extract annotations + # As described at https://github.com/fNIRS/snirf/ + # blob/master/snirf_specification.md#nirsistimjdata + annot = Annotations([], [], []) + for key in dat["nirs"]: + if "stim" in key: + data = np.atleast_2d(np.array(dat.get("/nirs/" + key + "/data"))) + if data.shape[1] >= 3: + desc = _correct_shape( + np.array(dat.get("/nirs/" + key + "/name")) + )[0] + annot.append(data[:, 0], data[:, 1], desc.decode("UTF-8")) + self.set_annotations(annot, emit_warning=False) + + # Validate that the fNIRS info is correctly formatted + _validate_nirs_info(self.info) + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + """Read a segment of data from a file.""" + import h5py + + with h5py.File(self.filenames[0], "r") as dat: + one = dat["/nirs/data1/dataTimeSeries"][start:stop].T + + _mult_cal_one(data, one, idx, cals, mult) + + +# Helper function for when the numpy array has shape (), i.e. just one element. +def _correct_shape(arr): + if arr.shape == (): + arr = arr[np.newaxis] + return arr + + +def _get_timeunit_scaling(time_unit): + """MNE expects time in seconds, return required scaling.""" + scalings = {"ms": 1000, "s": 1, "unknown": 1} + if time_unit in scalings: + return scalings[time_unit] + else: + raise RuntimeError( + f"The time unit {time_unit} is not supported by " + "MNE. Please report this error as a GitHub " + "issue to inform the developers." + ) + + +def _get_lengthunit_scaling(length_unit): + """MNE expects distance in m, return required scaling.""" + scalings = {"m": 1, "cm": 100, "mm": 1000} + if length_unit in scalings: + return scalings[length_unit] + else: + raise RuntimeError( + f"The length unit {length_unit} is not supported " + "by MNE. Please report this error as a GitHub " + "issue to inform the developers." + ) + + +def _extract_sampling_rate(dat, user_sfreq): + """Extract the sample rate from the time field.""" + # This is a workaround to provide support for Artinis data. + # It allows for a 1% variation in the sampling times relative + # to the average sampling rate of the file. + MAXIMUM_ALLOWED_SAMPLING_JITTER_PERCENTAGE = 1.0 + + _validate_type(user_sfreq, ("numeric", None), "sfreq") + time_data = np.array(dat.get("nirs/data1/time")) + time_unit = _get_metadata_str(dat, "TimeUnit") + time_unit_scaling = _get_timeunit_scaling(time_unit) # always 1 (s) or 1000 (ms) + if len(time_data) == 2: # special-cased in the snirf standard as (onset, period) + onset, period = time_data + file_sfreq = time_unit_scaling / period + else: + onset = time_data[0] + periods = np.diff(time_data) + sfreqs = time_unit_scaling / periods + file_sfreq = sfreqs.mean() # our best estimate, likely including some jitter + if user_sfreq is not None: + logger.info(f"Setting sampling frequency to user-supplied value: {user_sfreq}") + if not np.allclose(file_sfreq, user_sfreq, rtol=0.01, atol=0): + warn( + f"User-supplied sampling frequency ({user_sfreq} Hz) differs by " + f"{(user_sfreq - file_sfreq) / file_sfreq:.1%} from the frequency " + f"estimated from data in the file ({file_sfreq} Hz)." + ) + sfreq = user_sfreq or file_sfreq # user-passed value overrides value from file + # estimate jitter + if len(time_data) > 2: + ideal_times = onset + np.arange(len(time_data)) / sfreq + max_jitter = np.max(np.abs(time_data - ideal_times)) + percent_jitter = 100.0 * max_jitter / periods.mean() + msg = f"Found jitter of {percent_jitter:3f}% in sample times." + if percent_jitter > MAXIMUM_ALLOWED_SAMPLING_JITTER_PERCENTAGE: + warn( + f"{msg} Note that MNE-Python does not currently support SNIRF " + "files with non-uniformly-sampled data." + ) + else: + logger.info(msg) + return sfreq + + +def _get_metadata_str(dat, field): + if field not in np.array(dat.get("nirs/metaDataTags")): + return None + data = dat.get(f"/nirs/metaDataTags/{field}") + data = _correct_shape(np.array(data)) + data = str(data[0], "utf-8") + return data diff --git a/mne-python/source/mne/io/snirf/tests/__init__.py b/mne-python/source/mne/io/snirf/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/snirf/tests/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/snirf/tests/test_snirf.py b/mne-python/source/mne/io/snirf/tests/test_snirf.py new file mode 100644 index 0000000000000000000000000000000000000000..aaec3ea20cf39fd21e96c3b0bc101626cd20fcc8 --- /dev/null +++ b/mne-python/source/mne/io/snirf/tests/test_snirf.py @@ -0,0 +1,629 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import datetime +import shutil +from contextlib import nullcontext + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_almost_equal, + assert_array_equal, + assert_equal, +) + +from mne._fiff.constants import FIFF +from mne.datasets.testing import data_path, requires_testing_data +from mne.io import read_raw_nirx, read_raw_snirf +from mne.io.tests.test_raw import _test_raw_reader +from mne.preprocessing.nirs import ( + _channel_frequencies, + _reorder_nirx, + beer_lambert_law, + optical_density, + short_channels, + source_detector_distances, +) +from mne.transforms import _get_trans, apply_trans +from mne.utils import catch_logging + +testing_path = data_path(download=False) +# SfNIRS files +sfnirs_homer_103_wShort = ( + testing_path + / "SNIRF" + / "SfNIRS" + / "snirf_homer3" + / "1.0.3" + / "snirf_1_3_nirx_15_2_recording_w_short.snirf" +) +sfnirs_homer_103_wShort_original = ( + testing_path / "NIRx" / "nirscout" / "nirx_15_2_recording_w_short" +) +sfnirs_homer_103_153 = ( + testing_path + / "SNIRF" + / "SfNIRS" + / "snirf_homer3" + / "1.0.3" + / "nirx_15_3_recording.snirf" +) + +# NIRSport2 files +nirx_nirsport2_103 = ( + testing_path / "SNIRF" / "NIRx" / "NIRSport2" / "1.0.3" / "2021-04-23_005.snirf" +) +nirx_nirsport2_103_2 = ( + testing_path / "SNIRF" / "NIRx" / "NIRSport2" / "1.0.3" / "2021-05-05_001.snirf" +) +snirf_nirsport2_20219 = ( + testing_path / "SNIRF" / "NIRx" / "NIRSport2" / "2021.9" / "2021-10-01_002.snirf" +) + +# Kernel +kernel_hb = testing_path / "SNIRF" / "Kernel" / "Flow50" / "Portal_2021_11" / "hb.snirf" + +h5py = pytest.importorskip("h5py") # module-level + +# Fieldtrip +ft_od = testing_path / "SNIRF" / "FieldTrip" / "220307_opticaldensity.snirf" + +# GowerLabs +lumo110 = testing_path / "SNIRF" / "GowerLabs" / "lumomat-1-1-0.snirf" + +# Shimadzu Labnirs 3-wavelength converted to snirf using custom tool +labnirs_multi_wavelength = ( + testing_path / "SNIRF" / "Labnirs" / "labnirs_3wl_raw_recording.snirf" +) + + +def _get_loc(raw, ch_name): + return raw.copy().pick(ch_name).info["chs"][0]["loc"] + + +@requires_testing_data +@pytest.mark.filterwarnings("ignore:.*contains 2D location.*:") +@pytest.mark.filterwarnings("ignore:.*measurement date.*:") +@pytest.mark.parametrize( + "fname", + ( + [ + sfnirs_homer_103_wShort, + nirx_nirsport2_103, + sfnirs_homer_103_153, + nirx_nirsport2_103, + nirx_nirsport2_103_2, + nirx_nirsport2_103_2, + kernel_hb, + lumo110, + labnirs_multi_wavelength, + ] + ), +) +def test_basic_reading_and_min_process(fname): + """Test reading SNIRF files and minimum typical processing.""" + raw = read_raw_snirf(fname, preload=True) + # SNIRF data can contain several types, so only apply appropriate functions + if "fnirs_cw_amplitude" in raw: + raw = optical_density(raw) + if "fnirs_od" in raw: + raw = beer_lambert_law(raw, ppf=6) + assert "hbo" in raw + assert "hbr" in raw + + +@requires_testing_data +@pytest.mark.filterwarnings("ignore:.*measurement date.*:") +def test_snirf_gowerlabs(): + """Test reading SNIRF files.""" + raw = read_raw_snirf(lumo110, preload=True) + + assert raw._data.shape == (216, 274) + assert raw.info["dig"][0]["coord_frame"] == FIFF.FIFFV_COORD_HEAD + assert len(raw.ch_names) == 216 + assert_allclose(raw.info["sfreq"], 10.0) + # we don't force them to be sorted according to a naive split + assert raw.ch_names != sorted(raw.ch_names) + # ... but this file does have a nice logical ordering already + print(raw.ch_names) + assert raw.ch_names == sorted( + raw.ch_names, + # use a key which is (src triplet, freq, src, freq, det) + key=lambda name: ( + (int(name.split()[0].split("_")[0][1:]) - 1) // 3, + int(name.split()[1]), + int(name.split()[0].split("_")[0][1:]), + int(name.split()[0].split("_")[1][1:]), + ), + ) + + +@requires_testing_data +def test_snirf_basic(): + """Test reading SNIRF files.""" + raw = read_raw_snirf(sfnirs_homer_103_wShort, preload=True) + assert raw.info["subject_info"]["his_id"] == "default" + + # Test data import + assert raw._data.shape == (26, 145) + assert raw.info["sfreq"] == 12.5 + + # Test channel naming + assert raw.info["ch_names"][:4] == [ + "S1_D1 760", + "S1_D9 760", + "S2_D3 760", + "S2_D10 760", + ] + assert raw.info["ch_names"][24:26] == ["S5_D8 850", "S5_D13 850"] + + # Test frequency encoding + assert raw.info["chs"][0]["loc"][9] == 760 + assert raw.info["chs"][24]["loc"][9] == 850 + + # Test source locations + assert_allclose( + [-8.6765 * 1e-2, 0.0049 * 1e-2, -2.6167 * 1e-2], + _get_loc(raw, "S1_D1 760")[3:6], + rtol=0.02, + ) + assert_allclose( + [7.9579 * 1e-2, -2.7571 * 1e-2, -2.2631 * 1e-2], + _get_loc(raw, "S2_D3 760")[3:6], + rtol=0.02, + ) + assert_allclose( + [-2.1387 * 1e-2, -8.8874 * 1e-2, 3.8393 * 1e-2], + _get_loc(raw, "S3_D2 760")[3:6], + rtol=0.02, + ) + assert_allclose( + [1.8602 * 1e-2, 9.7164 * 1e-2, 1.7539 * 1e-2], + _get_loc(raw, "S4_D4 760")[3:6], + rtol=0.02, + ) + assert_allclose( + [-0.1108 * 1e-2, 0.7066 * 1e-2, 8.9883 * 1e-2], + _get_loc(raw, "S5_D5 760")[3:6], + rtol=0.02, + ) + + # Test detector locations + assert_allclose( + [-8.0409 * 1e-2, -2.9677 * 1e-2, -2.5415 * 1e-2], + _get_loc(raw, "S1_D1 760")[6:9], + rtol=0.02, + ) + assert_allclose( + [-8.7329 * 1e-2, 0.7577 * 1e-2, -2.7980 * 1e-2], + _get_loc(raw, "S1_D9 850")[6:9], + rtol=0.02, + ) + assert_allclose( + [9.2027 * 1e-2, 0.0161 * 1e-2, -2.8909 * 1e-2], + _get_loc(raw, "S2_D3 850")[6:9], + rtol=0.02, + ) + assert_allclose( + [7.7548 * 1e-2, -3.5901 * 1e-2, -2.3179 * 1e-2], + _get_loc(raw, "S2_D10 850")[6:9], + rtol=0.02, + ) + + assert "fnirs_cw_amplitude" in raw + + +@requires_testing_data +def test_snirf_against_nirx(): + """Test Homer generated against file snirf was created from.""" + raw_homer = read_raw_snirf(sfnirs_homer_103_wShort, preload=True) + _reorder_nirx(raw_homer) + raw_orig = read_raw_nirx(sfnirs_homer_103_wShort_original, preload=True) + + # Check annotations are the same + assert_allclose(raw_homer.annotations.onset, raw_orig.annotations.onset) + assert_allclose( + [float(d) for d in raw_homer.annotations.description], + [float(d) for d in raw_orig.annotations.description], + ) + # Homer writes durations as 5s regardless of the true duration. + # So we will not test that the nirx file stim durations equal + # the homer file stim durations. + + # Check names are the same + assert raw_homer.info["ch_names"] == raw_orig.info["ch_names"] + + # Check frequencies are the same + num_chans = len(raw_homer.ch_names) + new_chs = raw_homer.info["chs"] + ori_chs = raw_orig.info["chs"] + assert_allclose( + [new_chs[idx]["loc"][9] for idx in range(num_chans)], + [ori_chs[idx]["loc"][9] for idx in range(num_chans)], + ) + + # Check data is the same + assert_allclose(raw_homer.get_data(), raw_orig.get_data()) + + +@requires_testing_data +def test_snirf_nonstandard(tmp_path): + """Test custom tags.""" + shutil.copy(sfnirs_homer_103_wShort, str(tmp_path) + "/mod.snirf") + fname = str(tmp_path) + "/mod.snirf" + # Manually mark up the file to match MNE-NIRS custom tags + with h5py.File(fname, "r+") as f: + f.create_dataset("nirs/metaDataTags/middleName", data=[b"X"]) + f.create_dataset("nirs/metaDataTags/lastName", data=[b"Y"]) + f.create_dataset("nirs/metaDataTags/sex", data=[b"1"]) + raw = read_raw_snirf(fname, preload=True) + assert raw.info["subject_info"]["first_name"] == "default" # pull from his_id + with h5py.File(fname, "r+") as f: + f.create_dataset("nirs/metaDataTags/firstName", data=[b"W"]) + raw = read_raw_snirf(fname, preload=True) + assert raw.info["subject_info"]["first_name"] == "W" + assert raw.info["subject_info"]["middle_name"] == "X" + assert raw.info["subject_info"]["last_name"] == "Y" + assert raw.info["subject_info"]["sex"] == 1 + assert raw.info["subject_info"]["his_id"] == "default" + with h5py.File(fname, "r+") as f: + del f["nirs/metaDataTags/sex"] + f.create_dataset("nirs/metaDataTags/sex", data=[b"2"]) + raw = read_raw_snirf(fname, preload=True) + assert raw.info["subject_info"]["sex"] == 2 + with h5py.File(fname, "r+") as f: + del f["nirs/metaDataTags/sex"] + f.create_dataset("nirs/metaDataTags/sex", data=[b"0"]) + raw = read_raw_snirf(fname, preload=True) + assert raw.info["subject_info"]["sex"] == 0 + + with h5py.File(fname, "r+") as f: + f.create_dataset("nirs/metaDataTags/MNE_coordFrame", data=[1]) + + +@requires_testing_data +def test_snirf_empty_landmark_labels(tmp_path): + """Test reading SNIRF files with empty landmarkLabels (gh-13627).""" + shutil.copy(sfnirs_homer_103_wShort, tmp_path / "empty_labels.snirf") + fname = tmp_path / "empty_labels.snirf" + + # Modify file to have landmarkPos3D but empty/scalar landmarkLabels + with h5py.File(fname, "r+") as f: + # Remove existing landmark data if present + if "landmarkPos3D" in f["nirs/probe"]: + del f["nirs/probe/landmarkPos3D"] + if "landmarkLabels" in f["nirs/probe"]: + del f["nirs/probe/landmarkLabels"] + + # Add non-empty landmarkPos3D + f.create_dataset( + "nirs/probe/landmarkPos3D", + data=np.array([[0.0, 0.0, 0.0], [1.0, 0.0, 0.0]]), + ) + # Add empty scalar landmarkLabels (this triggers the bug in gh-13627) + f.create_dataset("nirs/probe/landmarkLabels", data=b"") + + # This should not raise "TypeError: iteration over a 0-d array" + raw = read_raw_snirf(fname, preload=True) + assert raw.info["dig"] is not None + + +@requires_testing_data +def test_snirf_nirsport2(): + """Test reading SNIRF files.""" + raw = read_raw_snirf(nirx_nirsport2_103, preload=True) + + # Test data import + assert raw._data.shape == (92, 84) + assert_almost_equal(raw.info["sfreq"], 7.6, decimal=1) + + # Test channel naming + assert raw.info["ch_names"][:4] == [ + "S1_D1 760", + "S1_D3 760", + "S1_D9 760", + "S1_D16 760", + ] + assert raw.info["ch_names"][24:26] == ["S8_D15 760", "S8_D20 760"] + + # Test frequency encoding + assert raw.info["chs"][0]["loc"][9] == 760 + assert raw.info["chs"][-1]["loc"][9] == 850 + + assert sum(short_channels(raw.info)) == 16 + + +@requires_testing_data +def test_snirf_coordframe(): + """Test reading SNIRF files.""" + raw = read_raw_snirf(nirx_nirsport2_103, optode_frame="head").info["chs"][3][ + "coord_frame" + ] + assert raw == FIFF.FIFFV_COORD_HEAD + + raw = read_raw_snirf(nirx_nirsport2_103, optode_frame="mri").info["chs"][3][ + "coord_frame" + ] + assert raw == FIFF.FIFFV_COORD_HEAD + + raw = read_raw_snirf(nirx_nirsport2_103, optode_frame="unknown").info["chs"][3][ + "coord_frame" + ] + assert raw == FIFF.FIFFV_COORD_UNKNOWN + + +@requires_testing_data +def test_snirf_nirsport2_w_positions(): + """Test reading SNIRF files with known positions.""" + raw = read_raw_snirf(nirx_nirsport2_103_2, preload=True, optode_frame="mri") + _reorder_nirx(raw) + + # Test data import + assert raw._data.shape == (40, 128) + assert_almost_equal(raw.info["sfreq"], 10.2, decimal=1) + + # Test channel naming + assert raw.info["ch_names"][:4] == [ + "S1_D1 760", + "S1_D1 850", + "S1_D6 760", + "S1_D6 850", + ] + assert raw.info["ch_names"][24:26] == ["S6_D4 760", "S6_D4 850"] + + # Test frequency encoding + assert raw.info["chs"][0]["loc"][9] == 760 + assert raw.info["chs"][1]["loc"][9] == 850 + + assert sum(short_channels(raw.info)) == 16 + + # Test distance between optodes matches values from + # nirsite https://github.com/mne-tools/mne-testing-data/pull/86 + # figure 3 + allowed_distance_error = 0.005 + assert_allclose( + source_detector_distances(raw.copy().pick("S1_D1 760").info), + [0.0304], + atol=allowed_distance_error, + ) + assert_allclose( + source_detector_distances(raw.copy().pick("S2_D2 760").info), + [0.0400], + atol=allowed_distance_error, + ) + + # Test location of detectors + # The locations of detectors can be seen in the first + # figure on this page... + # https://github.com/mne-tools/mne-testing-data/pull/86 + allowed_dist_error = 0.0002 + locs = [ch["loc"][6:9] for ch in raw.info["chs"]] + head_mri_t, _ = _get_trans("fsaverage", "head", "mri") + mni_locs = apply_trans(head_mri_t, locs) + + assert raw.info["ch_names"][0][3:5] == "D1" + assert_allclose(mni_locs[0], [-0.0841, -0.0464, -0.0129], atol=allowed_dist_error) + + assert raw.info["ch_names"][2][3:5] == "D6" + assert_allclose(mni_locs[2], [-0.0841, -0.0138, 0.0248], atol=allowed_dist_error) + + assert raw.info["ch_names"][34][3:5] == "D5" + assert_allclose(mni_locs[34], [0.0845, -0.0451, -0.0123], atol=allowed_dist_error) + + # Test location of sensors + # The locations of sensors can be seen in the second + # figure on this page... + # https://github.com/mne-tools/mne-testing-data/pull/86 + allowed_dist_error = 0.0002 + locs = [ch["loc"][3:6] for ch in raw.info["chs"]] + head_mri_t, _ = _get_trans("fsaverage", "head", "mri") + mni_locs = apply_trans(head_mri_t, locs) + + assert raw.info["ch_names"][0][:2] == "S1" + assert_allclose(mni_locs[0], [-0.0848, -0.0162, -0.0163], atol=allowed_dist_error) + + assert raw.info["ch_names"][9][:2] == "S2" + assert_allclose(mni_locs[9], [-0.0, -0.1195, 0.0142], atol=allowed_dist_error) + + assert raw.info["ch_names"][34][:2] == "S8" + assert_allclose(mni_locs[34], [0.0828, -0.046, 0.0285], atol=allowed_dist_error) + + mon = raw.get_montage() + assert len(mon.dig) == 27 + + +@requires_testing_data +def test_snirf_fieldtrip_od(): + """Test reading FieldTrip SNIRF files with optical density data.""" + raw = read_raw_snirf(ft_od, preload=True) + + # Test data import + assert raw._data.shape == (72, 500) + assert raw.copy().pick("fnirs")._data.shape == (72, 500) + assert raw.copy().pick("fnirs_od")._data.shape == (72, 500) + with pytest.raises(ValueError, match="not be interpreted as channel"): + raw.copy().pick("hbo") + with pytest.raises(ValueError, match="not be interpreted as channel"): + raw.copy().pick("hbr") + + assert_allclose(raw.info["sfreq"], 50) + + +@requires_testing_data +def test_snirf_kernel_hb(): + """Test reading Kernel SNIRF files with haemoglobin data.""" + raw = read_raw_snirf(kernel_hb, preload=True) + + # Test data import + assert raw._data.shape == (180 * 2, 14) + assert raw.copy().pick("hbo")._data.shape == (180, 14) + assert raw.copy().pick("hbr")._data.shape == (180, 14) + + assert_allclose(raw.info["sfreq"], 8.256495) + + bad_nans = np.isnan(raw.get_data()).any(axis=1) + assert np.sum(bad_nans) == 20 + + assert len(raw.annotations.description) == 2 + assert raw.annotations.onset[0] == 0.036939 + assert raw.annotations.onset[1] == 0.874633 + assert raw.annotations.description[0] == "StartTrial" + assert raw.annotations.description[1] == "StartIti" + + +@requires_testing_data +@pytest.mark.parametrize( + "sfreq,context", + ( + [8.2, nullcontext()], # sfreq estimated from file is 8.256495 + [22, pytest.warns(RuntimeWarning, match="User-supplied sampling frequency")], + ), +) +def test_user_set_sfreq(sfreq, context): + """Test manually setting sfreq.""" + with context: + # both sfreqs are far enough from true rate to yield >1% jitter + with pytest.warns(RuntimeWarning, match=r"jitter of \d+\.\d*% in sample times"): + raw = read_raw_snirf(kernel_hb, preload=False, sfreq=sfreq) + assert raw.info["sfreq"] == sfreq + + +@requires_testing_data +@pytest.mark.parametrize( + "fname, boundary_decimal, test_scaling, test_rank", + ( + [sfnirs_homer_103_wShort, 0, True, True], + [nirx_nirsport2_103, 0, True, False], # strange rank behavior + [nirx_nirsport2_103_2, 0, False, True], # weirdly small values + [snirf_nirsport2_20219, 0, True, True], + ), +) +def test_snirf_standard(fname, boundary_decimal, test_scaling, test_rank): + """Test standard operations.""" + _test_raw_reader( + read_raw_snirf, + fname=fname, + boundary_decimal=boundary_decimal, + test_scaling=test_scaling, + test_rank=test_rank, + ) # low fs + + +@requires_testing_data +def test_annotation_description_from_stim_groups(): + """Test annotation descriptions parsed from stim group names.""" + raw = read_raw_snirf(nirx_nirsport2_103_2, preload=True) + expected_descriptions = ["1", "2", "6"] + assert_equal(expected_descriptions, raw.annotations.description) + + +@requires_testing_data +def test_annotation_duration_from_stim_groups(): + """Test annotation durations extracted correctly from stim group.""" + raw = read_raw_snirf(snirf_nirsport2_20219, preload=True) + # Specify the expected SNIRF stim durations. + # We can verify these values should be 10 by using the official + # SNIRF package pysnirf2 and running the following script. + # You will see that the print statement shows the middle column, + # which represents duration, will be all 10s. + # from snirf import Snirf + # a = Snirf(snirf_nirsport2_20219, "r+"); print(a.nirs[0].stim[0].data) + expected_durations = np.full((10,), 10.0) + assert_equal(expected_durations, raw.annotations.duration) + + +def test_birthday(tmp_path, monkeypatch): + """Test birthday parsing.""" + try: + snirf = pytest.importorskip("snirf") + except AttributeError as exc: + # Until https://github.com/BUNPC/pysnirf2/pull/43 is released + pytest.skip(f"snirf import error: {exc}") + fname = tmp_path / "test.snirf" + with snirf.Snirf(str(fname), "w") as a: + a.nirs.appendGroup() + a.nirs[0].data.appendGroup() + a.nirs[0].data[0].dataTimeSeries = np.zeros((2, 2)) + a.nirs[0].data[0].time = [0, 1] + for i in range(2): + a.nirs[0].data[0].measurementList.appendGroup() + a.nirs[0].data[0].measurementList[i].sourceIndex = 1 + a.nirs[0].data[0].measurementList[i].detectorIndex = 1 + a.nirs[0].data[0].measurementList[i].wavelengthIndex = 1 + a.nirs[0].data[0].measurementList[i].dataType = 99999 + a.nirs[0].data[0].measurementList[i].dataTypeIndex = 0 + a.nirs[0].data[0].measurementList[0].dataTypeLabel = "HbO" + a.nirs[0].data[0].measurementList[1].dataTypeLabel = "HbR" + a.nirs[0].metaDataTags.SubjectID = "0" + a.nirs[0].metaDataTags.MeasurementDate = "2000-01-01" + a.nirs[0].metaDataTags.MeasurementTime = "00:00:00" + a.nirs[0].metaDataTags.LengthUnit = "m" + a.nirs[0].metaDataTags.TimeUnit = "s" + a.nirs[0].metaDataTags.FrequencyUnit = "Hz" + a.nirs[0].metaDataTags.add("DateOfBirth", "1950-01-01") + a.nirs[0].probe.wavelengths = [0, 0] + a.nirs[0].probe.sourcePos3D = np.zeros((1, 3)) + a.nirs[0].probe.detectorPos3D = np.zeros((1, 3)) + # Until https://github.com/BUNPC/pysnirf2/pull/39 is released + monkeypatch.setattr(a._cfg.logger, "info", lambda *args, **kwargs: None) + a.save() + + raw = read_raw_snirf(fname) + assert raw.info["subject_info"]["birthday"] == datetime.date(1950, 1, 1) + # TODO: trigger some setting checkers that should maybe be in the reader (like + # those for subject_info) + raw.info.copy() + + +@requires_testing_data +def test_sample_rate_jitter(tmp_path): + """Test handling of jittered sample times.""" + from shutil import copy2 + + # Create a clean copy and ensure it loads without error + new_file = tmp_path / "snirf_nirsport2_2019.snirf" + copy2(snirf_nirsport2_20219, new_file) + read_raw_snirf(new_file) + + # Edit the file and add jitter within tolerance (0.99%) + with h5py.File(new_file, "r+") as f: + orig_time = np.array(f.get("nirs/data1/time")) + acceptable_time_jitter = orig_time.copy() + mean_period = np.mean(np.diff(orig_time)) + acceptable_time_jitter[-1] += 0.0099 * mean_period + del f["nirs/data1/time"] + f.flush() + f.create_dataset("nirs/data1/time", data=acceptable_time_jitter) + with catch_logging("info") as log: + read_raw_snirf(new_file) + lines = "\n".join(line for line in log.getvalue().splitlines() if "jitter" in line) + assert "Found jitter of 0.9" in lines + + # Add jitter of 1.02%, which is greater than allowed tolerance + with h5py.File(new_file, "r+") as f: + unacceptable_time_jitter = orig_time + unacceptable_time_jitter[-1] = unacceptable_time_jitter[-1] + ( + 0.0102 * mean_period + ) + del f["nirs/data1/time"] + f.flush() + f.create_dataset("nirs/data1/time", data=unacceptable_time_jitter) + with pytest.warns(RuntimeWarning, match="non-uniformly-sampled data"): + read_raw_snirf(new_file, verbose=True) + + +@requires_testing_data +def test_snirf_multiple_wavelengths(): + """Test importing synthetic SNIRF files with >=3 wavelengths.""" + raw = read_raw_snirf(labnirs_multi_wavelength, preload=True) + assert raw._data.shape == (45, 250) + assert raw.info["sfreq"] == pytest.approx(19.6, abs=0.01) + assert raw.info["ch_names"][:3] == ["S2_D2 780", "S2_D2 805", "S2_D2 830"] + assert len(raw.ch_names) == 45 + freqs = np.unique(_channel_frequencies(raw.info)) + assert_array_equal(freqs, [780, 805, 830]) + distances = source_detector_distances(raw.info) + assert len(distances) == len(raw.ch_names) diff --git a/mne-python/source/mne/io/tests/__init__.py b/mne-python/source/mne/io/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c45203dcc03058ddea3c2e0c7ff40936a583857c --- /dev/null +++ b/mne-python/source/mne/io/tests/__init__.py @@ -0,0 +1,7 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import os.path as op + +data_dir = op.join(op.dirname(__file__), "data") diff --git a/mne-python/source/mne/io/tests/data/__init__.py b/mne-python/source/mne/io/tests/data/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..04c673b4e4d9d97d52ffeae54ae216d14fd30e09 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/__init__.py @@ -0,0 +1,3 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. diff --git a/mne-python/source/mne/io/tests/data/process_raw.sh b/mne-python/source/mne/io/tests/data/process_raw.sh new file mode 100644 index 0000000000000000000000000000000000000000..a13a078accd66fbffd78ac06750341fa50612d86 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/process_raw.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# Generate events +mne_process_raw --raw test_raw.fif --eventsout test-eve.fif + +# Averaging no filter +mne_process_raw --raw test_raw.fif --projon --filteroff \ + --saveavetag -nf-ave --ave test-no-reject.ave + +# Averaging 40Hz +mne_process_raw --raw test_raw.fif --lowpass 40 --projoff \ + --saveavetag -ave --ave test.ave + +# Compute the noise covariance matrix +mne_process_raw --raw test_raw.fif --filteroff --projon \ + --savecovtag -cov --cov test.cov + +# Compute the noise covariance matrix with keepsamplemean +mne_process_raw --raw test_raw.fif --filteroff --projon \ + --savecovtag -km-cov --cov test_keepmean.cov + +# Compute projection +mne_process_raw --raw test_raw.fif --events test-eve.fif --makeproj \ + --projtmin -0.2 --projtmax 0.3 --saveprojtag _proj \ + --projnmag 1 --projngrad 1 --projevent 1 \ + --projmagrej 600000 --projgradrej 500000 --filteroff diff --git a/mne-python/source/mne/io/tests/data/sample-audvis-raw-trans.txt b/mne-python/source/mne/io/tests/data/sample-audvis-raw-trans.txt new file mode 100644 index 0000000000000000000000000000000000000000..07b90deb14e9c61d83ba2fce92906e78734aef78 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/sample-audvis-raw-trans.txt @@ -0,0 +1,4 @@ +0.999310 0.012759 0.034894 0.002070 +0.009985 0.812405 -0.583009 0.011302 +-0.035787 0.582954 0.811716 -0.027555 +0.000000 0.000000 0.000000 1.000000 diff --git a/mne-python/source/mne/io/tests/data/small-src.fif.gz b/mne-python/source/mne/io/tests/data/small-src.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..bbfbaf59f6a90ede794b3beb3df75fbe3735e8c4 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/small-src.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:288e030893aed1b156485e1a974e88b8488c65971ab142e99c023fb7d5970db5 +size 77784 diff --git a/mne-python/source/mne/io/tests/data/test-1-eve.fif b/mne-python/source/mne/io/tests/data/test-1-eve.fif new file mode 100644 index 0000000000000000000000000000000000000000..a16a420647058aedea6ba2b902c02d2537989efd Binary files /dev/null and b/mne-python/source/mne/io/tests/data/test-1-eve.fif differ diff --git a/mne-python/source/mne/io/tests/data/test-ave-2.log b/mne-python/source/mne/io/tests/data/test-ave-2.log new file mode 100644 index 0000000000000000000000000000000000000000..fde2e354dda35cc94149e46db0dd27f31dc622fd --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-ave-2.log @@ -0,0 +1,30 @@ +Reading mne/fiff/tests/data/test-ave.fif ... + Read a total of 4 projection items: + PCA-v1 (1 x 102) idle + PCA-v2 (1 x 102) idle + PCA-v3 (1 x 102) idle + Average EEG reference (1 x 60) idle + Found the data of interest: + t = -199.80 ... 499.49 ms (Right Auditory) + 0 CTF compensation matrices available + nave = 6 - aspect type = 100 +Created an SSP operator (subspace dimension = 4) +4 projection items activated +SSP projectors applied... +No baseline correction applied +No baseline correction applied +Reading mne/fiff/tests/data/test-ave.fif ... + Read a total of 4 projection items: + PCA-v1 (1 x 102) idle + PCA-v2 (1 x 102) idle + PCA-v3 (1 x 102) idle + Average EEG reference (1 x 60) idle + Found the data of interest: + t = -199.80 ... 499.49 ms (Right Auditory) + 0 CTF compensation matrices available + nave = 6 - aspect type = 100 +Created an SSP operator (subspace dimension = 4) +4 projection items activated +SSP projectors applied... +No baseline correction applied +No baseline correction applied diff --git a/mne-python/source/mne/io/tests/data/test-ave.fif b/mne-python/source/mne/io/tests/data/test-ave.fif new file mode 100644 index 0000000000000000000000000000000000000000..9c9089080862827eae55bc2a75ccaaa1fd31ee5a --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-ave.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b94326ea2a767d41ffd88d7f1a3a61c28c529de4e0e4070937cadf807cf6f27d +size 5546473 diff --git a/mne-python/source/mne/io/tests/data/test-ave.fif.gz b/mne-python/source/mne/io/tests/data/test-ave.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..fc0f91567e948790a82639622a7d97f4b767b4bb --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-ave.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b2401bd644324f887f718ef1a4feb08367b3211a43c347651b9d2d6fd91e7701 +size 2338877 diff --git a/mne-python/source/mne/io/tests/data/test-ave.log b/mne-python/source/mne/io/tests/data/test-ave.log new file mode 100644 index 0000000000000000000000000000000000000000..3b124b5ae609cec0a2020d663a89bca983919abc --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-ave.log @@ -0,0 +1,15 @@ +Reading mne/fiff/tests/data/test-ave.fif ... + Read a total of 4 projection items: + PCA-v1 (1 x 102) idle + PCA-v2 (1 x 102) idle + PCA-v3 (1 x 102) idle + Average EEG reference (1 x 60) idle + Found the data of interest: + t = -199.80 ... 499.49 ms (Right Auditory) + 0 CTF compensation matrices available + nave = 6 - aspect type = 100 +Created an SSP operator (subspace dimension = 4) +4 projection items activated +SSP projectors applied... +No baseline correction applied +No baseline correction applied diff --git a/mne-python/source/mne/io/tests/data/test-cov.fif b/mne-python/source/mne/io/tests/data/test-cov.fif new file mode 100644 index 0000000000000000000000000000000000000000..3fb344e17d88029b935a738f88245ad937945a14 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-cov.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5d667f9087102ac72f79972d1b176b211a86e80f291cbec182a3cad3a0af651e +size 547234 diff --git a/mne-python/source/mne/io/tests/data/test-cov.fif.gz b/mne-python/source/mne/io/tests/data/test-cov.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..9d8a3a9e30f7b05d52b048b49d8df0d134261e05 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-cov.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6a894b150344c7f5520a1cdf9a25ebd62b8eaf8494b65cad86f8f639f8aef6f4 +size 524544 diff --git a/mne-python/source/mne/io/tests/data/test-eve-1.eve b/mne-python/source/mne/io/tests/data/test-eve-1.eve new file mode 100644 index 0000000000000000000000000000000000000000..238e64503584fe5cb1d4d30590f1b07062c1b569 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-eve-1.eve @@ -0,0 +1 @@ + 27977 0 2 diff --git a/mne-python/source/mne/io/tests/data/test-eve-old-style.eve b/mne-python/source/mne/io/tests/data/test-eve-old-style.eve new file mode 100644 index 0000000000000000000000000000000000000000..803a7d77add4101a9e24c3d970e49cbbec98363d --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-eve-old-style.eve @@ -0,0 +1,31 @@ + 27977 46.581 0 2 + 28345 47.193 0 3 + 28771 47.903 0 1 + 29219 48.648 0 4 + 29652 49.369 0 2 + 30025 49.990 0 3 + 30450 50.698 0 1 + 30839 51.346 0 4 + 31240 52.013 0 2 + 31665 52.721 0 3 + 32101 53.447 0 1 + 32519 54.143 0 4 + 32935 54.835 0 2 + 33325 55.485 0 3 + 33712 56.129 0 1 + 34089 56.757 0 5 + 34532 57.494 0 2 + 34649 57.689 0 32 + 34956 58.200 0 3 + 35428 58.986 0 1 + 35850 59.689 0 4 + 36211 60.290 0 2 + 36576 60.898 0 3 + 37007 61.615 0 1 + 37460 62.369 0 4 + 37910 63.119 0 2 + 38326 63.811 0 3 + 38711 64.452 0 1 + 39130 65.150 0 4 + 39563 65.871 0 2 + 39926 66.475 0 3 diff --git a/mne-python/source/mne/io/tests/data/test-eve.eve b/mne-python/source/mne/io/tests/data/test-eve.eve new file mode 100644 index 0000000000000000000000000000000000000000..31dedda0b118ee07e2bf4d97ad5e921b8352cddf --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-eve.eve @@ -0,0 +1,31 @@ + 27977 0 2 + 28345 0 3 + 28771 0 1 + 29219 0 4 + 29652 0 2 + 30025 0 3 + 30450 0 1 + 30839 0 4 + 31240 0 2 + 31665 0 3 + 32101 0 1 + 32519 0 4 + 32935 0 2 + 33325 0 3 + 33712 0 1 + 34089 0 5 + 34532 0 2 + 34649 0 32 + 34956 0 3 + 35428 0 1 + 35850 0 4 + 36211 0 2 + 36576 0 3 + 37007 0 1 + 37460 0 4 + 37910 0 2 + 38326 0 3 + 38711 0 1 + 39130 0 4 + 39563 0 2 + 39926 0 3 diff --git a/mne-python/source/mne/io/tests/data/test-eve.fif b/mne-python/source/mne/io/tests/data/test-eve.fif new file mode 100644 index 0000000000000000000000000000000000000000..d3cc74d300b48eadec1ee5e26d85e632647a5a75 Binary files /dev/null and b/mne-python/source/mne/io/tests/data/test-eve.fif differ diff --git a/mne-python/source/mne/io/tests/data/test-eve.fif.gz b/mne-python/source/mne/io/tests/data/test-eve.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..bff04803ca90372268945c881ca7d7a10981a7b0 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-eve.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4af45489704a329045a9982e8a8d8321174d24223793b3734b72d0a891ea4593 +size 270 diff --git a/mne-python/source/mne/io/tests/data/test-km-cov.fif b/mne-python/source/mne/io/tests/data/test-km-cov.fif new file mode 100644 index 0000000000000000000000000000000000000000..386d02fd1399615abd3c9aa2c98ebae5be7d0b06 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-km-cov.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4378f1414af29e3e4ba34f17a7761cd09be62b78609ea21dbc939138300dad89 +size 547234 diff --git a/mne-python/source/mne/io/tests/data/test-lh.label b/mne-python/source/mne/io/tests/data/test-lh.label new file mode 100644 index 0000000000000000000000000000000000000000..9f84c0d669964f3135353e3f3b158d63a3df7ff3 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-lh.label @@ -0,0 +1,101 @@ +#Test lh +99 +87 0.000000 0.000000 0.000000 1.000000 +121 0.000000 0.000000 0.000000 1.000000 +131 0.000000 0.000000 0.000000 1.000000 +198 0.000000 0.000000 0.000000 1.000000 +519 0.000000 0.000000 0.000000 1.000000 +674 0.000000 0.000000 0.000000 1.000000 +784 0.000000 0.000000 0.000000 1.000000 +987 0.000000 0.000000 0.000000 1.000000 +1296 0.000000 0.000000 0.000000 1.000000 +1351 0.000000 0.000000 0.000000 1.000000 +1415 0.000000 0.000000 0.000000 1.000000 +1457 0.000000 0.000000 0.000000 1.000000 +1865 0.000000 0.000000 0.000000 1.000000 +1891 0.000000 0.000000 0.000000 1.000000 +1908 0.000000 0.000000 0.000000 1.000000 +1926 0.000000 0.000000 0.000000 1.000000 +1929 0.000000 0.000000 0.000000 1.000000 +2020 0.000000 0.000000 0.000000 1.000000 +2030 0.000000 0.000000 0.000000 1.000000 +2354 0.000000 0.000000 0.000000 1.000000 +2369 0.000000 0.000000 0.000000 1.000000 +2466 0.000000 0.000000 0.000000 1.000000 +2489 0.000000 0.000000 0.000000 1.000000 +2562 0.000000 0.000000 0.000000 1.000000 +2660 0.000000 0.000000 0.000000 1.000000 +2884 0.000000 0.000000 0.000000 1.000000 +2943 0.000000 0.000000 0.000000 1.000000 +3143 0.000000 0.000000 0.000000 1.000000 +3182 0.000000 0.000000 0.000000 1.000000 +3233 0.000000 0.000000 0.000000 1.000000 +3469 0.000000 0.000000 0.000000 1.000000 +3505 0.000000 0.000000 0.000000 1.000000 +3603 0.000000 0.000000 0.000000 1.000000 +3734 0.000000 0.000000 0.000000 1.000000 +3818 0.000000 0.000000 0.000000 1.000000 +3931 0.000000 0.000000 0.000000 1.000000 +4099 0.000000 0.000000 0.000000 1.000000 +4135 0.000000 0.000000 0.000000 1.000000 +4244 0.000000 0.000000 0.000000 1.000000 +4312 0.000000 0.000000 0.000000 1.000000 +4474 0.000000 0.000000 0.000000 1.000000 +4615 0.000000 0.000000 0.000000 1.000000 +4742 0.000000 0.000000 0.000000 1.000000 +4753 0.000000 0.000000 0.000000 1.000000 +4856 0.000000 0.000000 0.000000 1.000000 +4883 0.000000 0.000000 0.000000 1.000000 +5067 0.000000 0.000000 0.000000 1.000000 +5103 0.000000 0.000000 0.000000 1.000000 +5244 0.000000 0.000000 0.000000 1.000000 +5264 0.000000 0.000000 0.000000 1.000000 +5389 0.000000 0.000000 0.000000 1.000000 +5426 0.000000 0.000000 0.000000 1.000000 +5457 0.000000 0.000000 0.000000 1.000000 +5497 0.000000 0.000000 0.000000 1.000000 +5688 0.000000 0.000000 0.000000 1.000000 +5704 0.000000 0.000000 0.000000 1.000000 +5834 0.000000 0.000000 0.000000 1.000000 +5948 0.000000 0.000000 0.000000 1.000000 +5981 0.000000 0.000000 0.000000 1.000000 +6114 0.000000 0.000000 0.000000 1.000000 +6409 0.000000 0.000000 0.000000 1.000000 +6656 0.000000 0.000000 0.000000 1.000000 +6718 0.000000 0.000000 0.000000 1.000000 +6736 0.000000 0.000000 0.000000 1.000000 +6742 0.000000 0.000000 0.000000 1.000000 +6755 0.000000 0.000000 0.000000 1.000000 +6757 0.000000 0.000000 0.000000 1.000000 +6779 0.000000 0.000000 0.000000 1.000000 +6905 0.000000 0.000000 0.000000 1.000000 +6943 0.000000 0.000000 0.000000 1.000000 +7051 0.000000 0.000000 0.000000 1.000000 +7070 0.000000 0.000000 0.000000 1.000000 +7087 0.000000 0.000000 0.000000 1.000000 +7089 0.000000 0.000000 0.000000 1.000000 +7096 0.000000 0.000000 0.000000 1.000000 +7275 0.000000 0.000000 0.000000 1.000000 +7437 0.000000 0.000000 0.000000 1.000000 +7764 0.000000 0.000000 0.000000 1.000000 +7816 0.000000 0.000000 0.000000 1.000000 +7949 0.000000 0.000000 0.000000 1.000000 +8009 0.000000 0.000000 0.000000 1.000000 +8380 0.000000 0.000000 0.000000 1.000000 +8397 0.000000 0.000000 0.000000 1.000000 +8484 0.000000 0.000000 0.000000 1.000000 +8773 0.000000 0.000000 0.000000 1.000000 +8836 0.000000 0.000000 0.000000 1.000000 +9081 0.000000 0.000000 0.000000 1.000000 +9300 0.000000 0.000000 0.000000 1.000000 +9340 0.000000 0.000000 0.000000 1.000000 +9519 0.000000 0.000000 0.000000 1.000000 +9667 0.000000 0.000000 0.000000 1.000000 +9813 0.000000 0.000000 0.000000 1.000000 +9858 0.000000 0.000000 0.000000 1.000000 +9889 0.000000 0.000000 0.000000 1.000000 +9937 0.000000 0.000000 0.000000 1.000000 +10097 0.000000 0.000000 0.000000 1.000000 +10106 0.000000 0.000000 0.000000 1.000000 +10179 0.000000 0.000000 0.000000 1.000000 +10219 0.000000 0.000000 0.000000 1.000000 diff --git a/mne-python/source/mne/io/tests/data/test-mpr-eve.eve b/mne-python/source/mne/io/tests/data/test-mpr-eve.eve new file mode 100644 index 0000000000000000000000000000000000000000..62145d9d342b0c67d9c99c9e06a20bae6ec6eda3 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-mpr-eve.eve @@ -0,0 +1,32 @@ + 25800 42.956 0 0 + 27977 46.581 0 2 + 28345 47.193 0 3 + 28771 47.903 0 1 + 29219 48.648 0 4 + 29652 49.369 0 2 + 30025 49.990 0 3 + 30450 50.698 0 1 + 30839 51.346 0 4 + 31240 52.013 0 2 + 31665 52.721 0 3 + 32101 53.447 0 1 + 32519 54.143 0 4 + 32935 54.835 0 2 + 33325 55.485 0 3 + 33712 56.129 0 1 + 34089 56.757 0 5 + 34532 57.494 0 2 + 34649 57.689 0 32 + 34956 58.200 0 3 + 35428 58.986 0 1 + 35850 59.689 0 4 + 36211 60.290 0 2 + 36576 60.898 0 3 + 37007 61.615 0 1 + 37460 62.369 0 4 + 37910 63.119 0 2 + 38326 63.811 0 3 + 38711 64.452 0 1 + 39130 65.150 0 4 + 39563 65.871 0 2 + 39926 66.475 0 3 diff --git a/mne-python/source/mne/io/tests/data/test-nf-ave.fif b/mne-python/source/mne/io/tests/data/test-nf-ave.fif new file mode 100644 index 0000000000000000000000000000000000000000..17767cc89648d15c1a04a6d81c7f694c54579e46 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-nf-ave.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ac62670a24cb2c29d2b0e36868edc4445f340372130689269afd72be4e40646e +size 5546473 diff --git a/mne-python/source/mne/io/tests/data/test-no-reject.ave b/mne-python/source/mne/io/tests/data/test-no-reject.ave new file mode 100644 index 0000000000000000000000000000000000000000..cfabf4087d0a0dfa8752a719f04a18545ec923c7 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-no-reject.ave @@ -0,0 +1,49 @@ +# +# These are comments +# +average { +# +# Output files +# +# outfile test-ave.fif +# logfile test-ave.log +# eventfile test.eve +# +# Rejection values +# + # gradReject 4000e-13 + # magReject 4e-12 + # eegReject 40e-6 + # eogReject 150e-6 +# +# Category specifications +# + category { + name "Left Auditory" + event 1 + tmin -0.2 + tmax 0.5 + color 1 1 0 + } + category { + name "Right Auditory" + event 2 + tmin -0.2 + tmax 0.5 + color 1 0 0 + } + category { + name "Left visual" + event 3 + tmin -0.2 + tmax 0.5 + color 0 1 0 + } + category { + name "Right visual" + event 4 + tmin -0.2 + tmax 0.5 + color 0.5 0.8 1 + } +} diff --git a/mne-python/source/mne/io/tests/data/test-proj.fif b/mne-python/source/mne/io/tests/data/test-proj.fif new file mode 100644 index 0000000000000000000000000000000000000000..2812dd83117b2cb6a1d86a050f0ae28b9ebba394 Binary files /dev/null and b/mne-python/source/mne/io/tests/data/test-proj.fif differ diff --git a/mne-python/source/mne/io/tests/data/test-proj.fif.gz b/mne-python/source/mne/io/tests/data/test-proj.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..a01ae6a1fb158b4b9ecd0858a87e2f8d0cdc6cd2 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-proj.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:803a012b71b4426eb610da775d91f1284fb0866d7560c6a99424abb9f38f686f +size 2221 diff --git a/mne-python/source/mne/io/tests/data/test-rh.label b/mne-python/source/mne/io/tests/data/test-rh.label new file mode 100644 index 0000000000000000000000000000000000000000..6991b919e1c5f725713d220258e7f9983ba72bdd --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test-rh.label @@ -0,0 +1,102 @@ +#Test rh +100 +11 0.000000 0.000000 0.000000 1.000000 +29 0.000000 0.000000 0.000000 1.000000 +70 0.000000 0.000000 0.000000 1.000000 +73 0.000000 0.000000 0.000000 1.000000 +75 0.000000 0.000000 0.000000 1.000000 +92 0.000000 0.000000 0.000000 1.000000 +230 0.000000 0.000000 0.000000 1.000000 +264 0.000000 0.000000 0.000000 1.000000 +332 0.000000 0.000000 0.000000 1.000000 +492 0.000000 0.000000 0.000000 1.000000 +532 0.000000 0.000000 0.000000 1.000000 +565 0.000000 0.000000 0.000000 1.000000 +575 0.000000 0.000000 0.000000 1.000000 +820 0.000000 0.000000 0.000000 1.000000 +889 0.000000 0.000000 0.000000 1.000000 +1486 0.000000 0.000000 0.000000 1.000000 +1526 0.000000 0.000000 0.000000 1.000000 +1544 0.000000 0.000000 0.000000 1.000000 +1561 0.000000 0.000000 0.000000 1.000000 +1737 0.000000 0.000000 0.000000 1.000000 +1934 0.000000 0.000000 0.000000 1.000000 +2121 0.000000 0.000000 0.000000 1.000000 +2167 0.000000 0.000000 0.000000 1.000000 +2200 0.000000 0.000000 0.000000 1.000000 +2545 0.000000 0.000000 0.000000 1.000000 +2557 0.000000 0.000000 0.000000 1.000000 +2858 0.000000 0.000000 0.000000 1.000000 +2888 0.000000 0.000000 0.000000 1.000000 +2904 0.000000 0.000000 0.000000 1.000000 +3005 0.000000 0.000000 0.000000 1.000000 +3076 0.000000 0.000000 0.000000 1.000000 +3221 0.000000 0.000000 0.000000 1.000000 +3279 0.000000 0.000000 0.000000 1.000000 +3328 0.000000 0.000000 0.000000 1.000000 +3398 0.000000 0.000000 0.000000 1.000000 +3558 0.000000 0.000000 0.000000 1.000000 +3581 0.000000 0.000000 0.000000 1.000000 +3597 0.000000 0.000000 0.000000 1.000000 +3661 0.000000 0.000000 0.000000 1.000000 +3749 0.000000 0.000000 0.000000 1.000000 +3847 0.000000 0.000000 0.000000 1.000000 +3962 0.000000 0.000000 0.000000 1.000000 +4032 0.000000 0.000000 0.000000 1.000000 +4053 0.000000 0.000000 0.000000 1.000000 +4312 0.000000 0.000000 0.000000 1.000000 +4324 0.000000 0.000000 0.000000 1.000000 +4516 0.000000 0.000000 0.000000 1.000000 +4625 0.000000 0.000000 0.000000 1.000000 +4808 0.000000 0.000000 0.000000 1.000000 +4834 0.000000 0.000000 0.000000 1.000000 +5099 0.000000 0.000000 0.000000 1.000000 +5207 0.000000 0.000000 0.000000 1.000000 +5269 0.000000 0.000000 0.000000 1.000000 +5372 0.000000 0.000000 0.000000 1.000000 +6031 0.000000 0.000000 0.000000 1.000000 +6065 0.000000 0.000000 0.000000 1.000000 +6392 0.000000 0.000000 0.000000 1.000000 +6901 0.000000 0.000000 0.000000 1.000000 +6945 0.000000 0.000000 0.000000 1.000000 +7205 0.000000 0.000000 0.000000 1.000000 +7248 0.000000 0.000000 0.000000 1.000000 +7283 0.000000 0.000000 0.000000 1.000000 +7380 0.000000 0.000000 0.000000 1.000000 +7559 0.000000 0.000000 0.000000 1.000000 +7642 0.000000 0.000000 0.000000 1.000000 +7683 0.000000 0.000000 0.000000 1.000000 +7687 0.000000 0.000000 0.000000 1.000000 +7840 0.000000 0.000000 0.000000 1.000000 +7936 0.000000 0.000000 0.000000 1.000000 +7939 0.000000 0.000000 0.000000 1.000000 +8042 0.000000 0.000000 0.000000 1.000000 +8339 0.000000 0.000000 0.000000 1.000000 +8352 0.000000 0.000000 0.000000 1.000000 +8427 0.000000 0.000000 0.000000 1.000000 +8491 0.000000 0.000000 0.000000 1.000000 +8496 0.000000 0.000000 0.000000 1.000000 +8524 0.000000 0.000000 0.000000 1.000000 +8578 0.000000 0.000000 0.000000 1.000000 +8797 0.000000 0.000000 0.000000 1.000000 +8810 0.000000 0.000000 0.000000 1.000000 +8829 0.000000 0.000000 0.000000 1.000000 +8903 0.000000 0.000000 0.000000 1.000000 +9062 0.000000 0.000000 0.000000 1.000000 +9081 0.000000 0.000000 0.000000 1.000000 +9164 0.000000 0.000000 0.000000 1.000000 +9165 0.000000 0.000000 0.000000 1.000000 +9225 0.000000 0.000000 0.000000 1.000000 +9226 0.000000 0.000000 0.000000 1.000000 +9322 0.000000 0.000000 0.000000 1.000000 +9532 0.000000 0.000000 0.000000 1.000000 +9633 0.000000 0.000000 0.000000 1.000000 +9659 0.000000 0.000000 0.000000 1.000000 +9700 0.000000 0.000000 0.000000 1.000000 +9789 0.000000 0.000000 0.000000 1.000000 +9831 0.000000 0.000000 0.000000 1.000000 +9851 0.000000 0.000000 0.000000 1.000000 +9891 0.000000 0.000000 0.000000 1.000000 +10055 0.000000 0.000000 0.000000 1.000000 +10065 0.000000 0.000000 0.000000 1.000000 +10082 0.000000 0.000000 0.000000 1.000000 diff --git a/mne-python/source/mne/io/tests/data/test.ave b/mne-python/source/mne/io/tests/data/test.ave new file mode 100644 index 0000000000000000000000000000000000000000..2ee6dab39753417fd2d6043e75be337610f13d28 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test.ave @@ -0,0 +1,49 @@ +# +# These are comments +# +average { +# +# Output files +# +# outfile test-ave.fif +# logfile test-ave.log +# eventfile test.eve +# +# Rejection values +# + gradReject 4000e-13 + magReject 4e-12 + eegReject 40e-6 + eogReject 150e-6 +# +# Category specifications +# + category { + name "Left Auditory" + event 1 + tmin -0.2 + tmax 0.5 + color 1 1 0 + } + category { + name "Right Auditory" + event 2 + tmin -0.2 + tmax 0.5 + color 1 0 0 + } + category { + name "Left visual" + event 3 + tmin -0.2 + tmax 0.5 + color 0 1 0 + } + category { + name "Right visual" + event 4 + tmin -0.2 + tmax 0.5 + color 0.5 0.8 1 + } +} diff --git a/mne-python/source/mne/io/tests/data/test.cov b/mne-python/source/mne/io/tests/data/test.cov new file mode 100644 index 0000000000000000000000000000000000000000..9ba2b7503534e9830fac2ad0efa5ea3aab349265 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test.cov @@ -0,0 +1,55 @@ +# +# These are comments +# +cov { +# +# Output files +# + outfile test-cov.fif + logfile test-cov.log +# +# Rejection values +# + gradReject 10000e-13 + magReject 4e-12 + eegReject 80e-6 + eogReject 150e-6 +# +# What to include in the covariance matrix? +# + def { + name "Left Auditory" + event 1 + tmin -0.2 + tmax 0.0 + basemin -0.1 + basemax 0 + } + def { + name "Right Auditory" + event 2 + ignore 0 + tmin -0.2 + tmax 0.0 + basemin -0.1 + basemax 0 + } + def { + name "Left visual" + event 3 + ignore 0 + tmin -0.2 + tmax 0.0 + basemin -0.1 + basemax 0 + } + def { + name "Right visual" + event 4 + ignore 0 + tmin -0.2 + tmax 0.0 + basemin -0.1 + basemax 0 + } +} diff --git a/mne-python/source/mne/io/tests/data/test_bads.txt b/mne-python/source/mne/io/tests/data/test_bads.txt new file mode 100644 index 0000000000000000000000000000000000000000..9b69461ab03a31638dfff06d5a7ae285d331a2cd --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_bads.txt @@ -0,0 +1,2 @@ +MEG 0422 +MEG 0433 diff --git a/mne-python/source/mne/io/tests/data/test_chpi_raw_hp.txt b/mne-python/source/mne/io/tests/data/test_chpi_raw_hp.txt new file mode 100644 index 0000000000000000000000000000000000000000..05c7555d4b31352199311c18614bbcdc603ece86 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_chpi_raw_hp.txt @@ -0,0 +1,5 @@ + Time q1 q2 q3 q4 q5 q6 g-value error velocity + 118.000 -0.00496 -0.04121 -0.00402 0.00159 -0.01443 0.04823 0.99928 0.00171 0.00002 + 119.000 -0.00479 -0.04117 -0.00415 0.00158 -0.01441 0.04825 0.99928 0.00169 0.00004 + 120.000 -0.00501 -0.04118 -0.00415 0.00159 -0.01443 0.04822 0.99928 0.00169 0.00004 + 121.000 -0.00500 -0.04119 -0.00414 0.00159 -0.01443 0.04823 0.99928 0.00169 0.00000 diff --git a/mne-python/source/mne/io/tests/data/test_chpi_raw_sss.fif b/mne-python/source/mne/io/tests/data/test_chpi_raw_sss.fif new file mode 100644 index 0000000000000000000000000000000000000000..3b3beab16ca1979bdae77a3cd745181fd5e03ad2 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_chpi_raw_sss.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7f9f0932842a558f5c823ec703304a42d96a0d818cde5af9eff36b2599afa5f +size 13071083 diff --git a/mne-python/source/mne/io/tests/data/test_ctf_comp_raw.fif b/mne-python/source/mne/io/tests/data/test_ctf_comp_raw.fif new file mode 100644 index 0000000000000000000000000000000000000000..f299d4db4cf70187f781010fce9f51e8322db558 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_ctf_comp_raw.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd6ef2b90a87e3ead02c400397956b72fcde35f685aca17570def3abbeeaaa76 +size 442032 diff --git a/mne-python/source/mne/io/tests/data/test_ctf_raw.fif b/mne-python/source/mne/io/tests/data/test_ctf_raw.fif new file mode 100644 index 0000000000000000000000000000000000000000..a17c755293d28f5305a0747d5213ac84bbe8e9f5 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_ctf_raw.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb01a60c83f76a6fc061d9463341266dd3185745b526e0e46febf2cff6ebad49 +size 9017895 diff --git a/mne-python/source/mne/io/tests/data/test_empty_room.cov b/mne-python/source/mne/io/tests/data/test_empty_room.cov new file mode 100644 index 0000000000000000000000000000000000000000..ec286dd2f5c06b15dd7a793d71636728f1f10c15 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_empty_room.cov @@ -0,0 +1,44 @@ +cov { +# name "Empty Room" +# +# Output files +# The log file is useful for debugging and +# selection of interesting events using 'eventfile' +# + outfile test_erm-cov.fif + logfile test_erm-cov.log +# +# Rejection limits +# +# stimIgnore is optional to omit a stimulus artifact from +# the rejection +# +# fixSkew +# logfile erm-ave.log + # gradReject 10000e-13 + # magReject 3e-12 + # magFlat 1e-14 + # gradflat 1000e-15 + +# Additional rejection parameters +# +# eegReject 20e-6 +# ecgReject 10e-3 +# +# The first definition follows +# + def { +# +# The name of the category (condition) is irrelevant +# but useful as a comment +# +# 'event' can be left out to compute covariance matrix +# from continuous data +# +# 'ignore' is a mask to apply to the trigger line +# before searching for 'event' (default = 0) +# + tmin 0 + tmax 99999 + } +} \ No newline at end of file diff --git a/mne-python/source/mne/io/tests/data/test_erm-cov.fif b/mne-python/source/mne/io/tests/data/test_erm-cov.fif new file mode 100644 index 0000000000000000000000000000000000000000..4f6a1dc8dafa346234ce75939a9d358594f07720 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_erm-cov.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:21aaef11e56332fdd2a36e49f37c2885b177196cb412a71bdd87c0ccb1d2f4e1 +size 541025 diff --git a/mne-python/source/mne/io/tests/data/test_ica.lout b/mne-python/source/mne/io/tests/data/test_ica.lout new file mode 100644 index 0000000000000000000000000000000000000000..079e4c032abacb1b86689f3396a16bfc8dabccc3 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_ica.lout @@ -0,0 +1,3 @@ + 0.00 1.00 0.00 1.00 +000 0.00 0.00 0.47 0.47 ICA 001 +001 0.53 0.00 0.47 0.47 ICA 002 diff --git a/mne-python/source/mne/io/tests/data/test_keepmean.cov b/mne-python/source/mne/io/tests/data/test_keepmean.cov new file mode 100644 index 0000000000000000000000000000000000000000..c94cda856ec7808114385ac08755f6c448704e91 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_keepmean.cov @@ -0,0 +1,56 @@ +# +# These are comments +# +cov { +# +# Output files +# + outfile test-cov.fif + logfile test-cov.log +# +# Rejection values +# + gradReject 10000e-13 + magReject 4e-12 + eegReject 80e-6 + eogReject 150e-6 + keepsamplemean +# +# What to include in the covariance matrix? +# + def { + name "Left Auditory" + event 1 + tmin -0.2 + tmax 0.0 + basemin -0.1 + basemax 0 + } + def { + name "Right Auditory" + event 2 + ignore 0 + tmin -0.2 + tmax 0.0 + basemin -0.1 + basemax 0 + } + def { + name "Left visual" + event 3 + ignore 0 + tmin -0.2 + tmax 0.0 + basemin -0.1 + basemax 0 + } + def { + name "Right visual" + event 4 + ignore 0 + tmin -0.2 + tmax 0.0 + basemin -0.1 + basemax 0 + } +} diff --git a/mne-python/source/mne/io/tests/data/test_raw-annot.fif b/mne-python/source/mne/io/tests/data/test_raw-annot.fif new file mode 100644 index 0000000000000000000000000000000000000000..46ecf90dd111f0a66538ecaf6bf803bc9874c951 Binary files /dev/null and b/mne-python/source/mne/io/tests/data/test_raw-annot.fif differ diff --git a/mne-python/source/mne/io/tests/data/test_raw-eve.fif b/mne-python/source/mne/io/tests/data/test_raw-eve.fif new file mode 100644 index 0000000000000000000000000000000000000000..4e2f4e65322ecbcda530704dfd200837f6a8d86b Binary files /dev/null and b/mne-python/source/mne/io/tests/data/test_raw-eve.fif differ diff --git a/mne-python/source/mne/io/tests/data/test_raw.fif b/mne-python/source/mne/io/tests/data/test_raw.fif new file mode 100644 index 0000000000000000000000000000000000000000..26a55c3b7bc3cce1a139816f1f2c72926103e0fa --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_raw.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b1dbe0150bd036cc2446f352265cdaf7deb7fa8eafb16eec6c64e403f4176e52 +size 13852290 diff --git a/mne-python/source/mne/io/tests/data/test_raw.fif.gz b/mne-python/source/mne/io/tests/data/test_raw.fif.gz new file mode 100644 index 0000000000000000000000000000000000000000..92035d74eeef82e1ace275c5409ff90d6f661d12 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_raw.fif.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9e5aaa0eadaae3663500c6a2c1e3140dd61363a7ef4daf52df3a73c6b942a0d7 +size 7270038 diff --git a/mne-python/source/mne/io/tests/data/test_raw.lout b/mne-python/source/mne/io/tests/data/test_raw.lout new file mode 100644 index 0000000000000000000000000000000000000000..07268ed0f0f11b971bb1cea3db602784eb51158d --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_raw.lout @@ -0,0 +1,61 @@ + -23.94 26.11 -21.40 21.06 +001 -5.97 16.10 5.00 4.00 EEG 001 +002 -1.89 16.66 5.00 4.00 EEG 002 +003 2.85 16.40 5.00 4.00 EEG 003 +004 -12.68 12.80 5.00 4.00 EEG 004 +005 -8.26 12.16 5.00 4.00 EEG 005 +006 4.87 12.09 5.00 4.00 EEG 006 +007 8.87 14.05 5.00 4.00 EEG 007 +008 -16.75 9.42 5.00 4.00 EEG 008 +009 -12.67 8.25 5.00 4.00 EEG 009 +010 -9.32 8.18 5.00 4.00 EEG 010 +011 -5.29 7.49 5.00 4.00 EEG 011 +012 -1.89 7.95 5.00 4.00 EEG 012 +013 2.05 7.94 5.00 4.00 EEG 013 +014 5.38 7.58 5.00 4.00 EEG 014 +015 9.83 9.27 5.00 4.00 EEG 015 +016 14.50 8.69 5.00 4.00 EEG 016 +017 -23.44 1.72 5.00 4.00 EEG 017 +018 -19.53 3.08 5.00 4.00 EEG 018 +019 -14.85 2.71 5.00 4.00 EEG 019 +020 -5.79 1.97 5.00 4.00 EEG 020 +021 2.61 3.28 5.00 4.00 EEG 021 +022 11.12 3.85 5.00 4.00 EEG 022 +023 16.12 3.18 5.00 4.00 EEG 023 +024 20.61 0.95 5.00 4.00 EEG 024 +025 -21.15 -6.75 5.00 4.00 EEG 025 +026 -19.05 -4.28 5.00 4.00 EEG 026 +027 -14.61 -2.28 5.00 4.00 EEG 027 +028 -10.13 -1.44 5.00 4.00 EEG 028 +029 -6.06 -0.83 5.00 4.00 EEG 029 +030 -1.65 -0.91 5.00 4.00 EEG 030 +031 2.33 -0.55 5.00 4.00 EEG 031 +032 6.48 -1.01 5.00 4.00 EEG 032 +033 11.37 -1.39 5.00 4.00 EEG 033 +034 15.95 -2.98 5.00 4.00 EEG 034 +035 18.81 -5.97 5.00 4.00 EEG 035 +036 -18.87 -13.13 5.00 4.00 EEG 036 +037 -16.48 -9.86 5.00 4.00 EEG 037 +038 -9.84 -4.79 5.00 4.00 EEG 038 +039 -5.89 -5.29 5.00 4.00 EEG 039 +040 2.23 -4.48 5.00 4.00 EEG 040 +041 6.69 -5.03 5.00 4.00 EEG 041 +042 13.42 -7.14 5.00 4.00 EEG 042 +043 16.40 -11.26 5.00 4.00 EEG 043 +044 -12.83 -12.95 5.00 4.00 EEG 044 +045 -10.43 -10.60 5.00 4.00 EEG 045 +046 -7.58 -9.14 5.00 4.00 EEG 046 +047 -4.86 -9.08 5.00 4.00 EEG 047 +048 -1.21 -8.68 5.00 4.00 EEG 048 +049 2.36 -9.29 5.00 4.00 EEG 049 +050 5.20 -8.51 5.00 4.00 EEG 050 +051 7.97 -9.46 5.00 4.00 EEG 051 +052 11.34 -10.97 5.00 4.00 EEG 052 +053 -10.01 -15.21 5.00 4.00 EEG 053 +054 -7.28 -13.76 5.00 4.00 EEG 054 +055 4.64 -12.14 5.00 4.00 EEG 055 +056 7.71 -14.34 5.00 4.00 EEG 056 +057 -5.68 -15.86 5.00 4.00 EEG 057 +058 -0.70 -16.23 5.00 4.00 EEG 058 +059 3.79 -15.23 5.00 4.00 EEG 059 +060 -1.00 -20.90 5.00 4.00 EEG 060 diff --git a/mne-python/source/mne/io/tests/data/test_withbads_raw.fif b/mne-python/source/mne/io/tests/data/test_withbads_raw.fif new file mode 100644 index 0000000000000000000000000000000000000000..c4765d8aacbc1d65b2e56546ffa467bd725cba29 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_withbads_raw.fif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:178519ca69058bc2017da5725c7e65672cc39d31078f93db3817a9408096a180 +size 4823007 diff --git a/mne-python/source/mne/io/tests/data/test_wrong_bads.txt b/mne-python/source/mne/io/tests/data/test_wrong_bads.txt new file mode 100644 index 0000000000000000000000000000000000000000..551c1b011eef4ffe76b1147791cde34046139c02 --- /dev/null +++ b/mne-python/source/mne/io/tests/data/test_wrong_bads.txt @@ -0,0 +1,3 @@ +MEG 0422 +MEG 0433 +FOOBAR11 diff --git a/mne-python/source/mne/io/tests/test_apply_function.py b/mne-python/source/mne/io/tests/test_apply_function.py new file mode 100644 index 0000000000000000000000000000000000000000..a6745d5e31d0f8ef55c5712cfb535badb199c14e --- /dev/null +++ b/mne-python/source/mne/io/tests/test_apply_function.py @@ -0,0 +1,93 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import numpy as np +import pytest + +from mne import create_info +from mne.io import RawArray +from mne.utils import catch_logging, logger + + +def bad_1(x): + """Fail.""" + return # bad return type + + +def bad_2(x): + """Fail.""" + return x[:-1] # bad shape + + +def bad_3(x): + """Fail.""" + return x[0, :] + + +def printer(x): + """Print.""" + logger.info("exec") + return x + + +@pytest.mark.slowtest +def test_apply_function_verbose(): + """Test apply function verbosity.""" + n_chan = 2 + n_times = 3 + ch_names = [str(ii) for ii in range(n_chan)] + raw = RawArray(np.zeros((n_chan, n_times)), create_info(ch_names, 1.0, "mag")) + # test return types in both code paths (parallel / 1 job) + with pytest.raises(TypeError, match="Return value must be an ndarray"): + raw.apply_function(bad_1) + with pytest.raises(ValueError, match="Return data must have shape"): + raw.apply_function(bad_2) + with pytest.raises(TypeError, match="Return value must be an ndarray"): + raw.apply_function(bad_1, n_jobs=2) + with pytest.raises(ValueError, match="Return data must have shape"): + raw.apply_function(bad_2, n_jobs=2) + + # test return type when `channel_wise=False` + raw.apply_function(printer, channel_wise=False) + with pytest.raises(TypeError, match="Return value must be an ndarray"): + raw.apply_function(bad_1, channel_wise=False) + with pytest.raises(ValueError, match="Return data must have shape"): + raw.apply_function(bad_3, channel_wise=False) + + # check our arguments + with catch_logging() as sio: + out = raw.apply_function(printer, verbose=False) + assert len(sio.getvalue(close=False)) == 0 + assert out is raw + raw.apply_function(printer, verbose=True) + assert sio.getvalue().count("\n") == n_chan + + +def test_apply_function_ch_access(): + """Test apply_function is able to access channel idx.""" + + def _bad_ch_idx(x, ch_idx): + assert x[0] == ch_idx + return x + + def _bad_ch_name(x, ch_name): + assert isinstance(ch_name, str) + assert x[0] == float(ch_name) + return x + + data = np.full((2, 10), np.arange(2).reshape(-1, 1)) + raw = RawArray(data, create_info(2, 1.0, "mag")) + + # test ch_idx access in both code paths (parallel / 1 job) + raw.apply_function(_bad_ch_idx) + raw.apply_function(_bad_ch_idx, n_jobs=2) + raw.apply_function(_bad_ch_name) + raw.apply_function(_bad_ch_name, n_jobs=2) + + # test input catches + with pytest.raises( + ValueError, + match="cannot access.*when channel_wise=False", + ): + raw.apply_function(_bad_ch_idx, channel_wise=False) diff --git a/mne-python/source/mne/io/tests/test_raw.py b/mne-python/source/mne/io/tests/test_raw.py new file mode 100644 index 0000000000000000000000000000000000000000..bb6d58ee0d9f874b63ca5994eb1583d2a35dc94a --- /dev/null +++ b/mne-python/source/mne/io/tests/test_raw.py @@ -0,0 +1,1109 @@ +"""Generic tests that all raw classes should run.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import math +import os +import re +from contextlib import redirect_stdout +from io import StringIO +from os import path as op +from pathlib import Path + +import numpy as np +import pytest +from numpy.testing import ( + assert_allclose, + assert_array_almost_equal, + assert_array_equal, + assert_array_less, +) + +import mne +from mne import Annotations, concatenate_raws, create_info, pick_types +from mne._fiff._digitization import DigPoint, _dig_kind_dict +from mne._fiff.constants import FIFF +from mne._fiff.meas_info import Info, _get_valid_units, _writing_info_hdf5 +from mne._fiff.pick import _ELECTRODE_CH_TYPES, _FNIRS_CH_TYPES_SPLIT +from mne._fiff.proj import Projection +from mne._fiff.utils import _mult_cal_one +from mne.io import BaseRaw, RawArray, read_raw_fif +from mne.io.base import _get_scaling +from mne.transforms import Transform +from mne.utils import ( + _import_h5io_funcs, + _raw_annot, + _stamp_to_dt, + _TempDir, + catch_logging, + check_version, + object_diff, + sizeof_fmt, +) + +raw_fname = op.join( + op.dirname(__file__), "..", "..", "io", "tests", "data", "test_raw.fif" +) + + +def assert_named_constants(info): + """Assert that info['chs'] has named constants.""" + # for now we just check one + __tracebackhide__ = True + r = repr(info["chs"][0]) + for check in ( + ".*FIFFV_COORD_.*", + ".*FIFFV_COIL_.*", + ".*FIFF_UNIT_.*", + ".*FIFF_UNITM_.*", + ): + assert re.match(check, r, re.DOTALL) is not None, (check, r) + + +def assert_attributes(raw): + """Assert that the instance keeps all its extra attributes in _raw_extras.""" + __tracebackhide__ = True + assert isinstance(raw, BaseRaw) + base_attrs = set(dir(BaseRaw(create_info(1, 1000.0, "eeg"), last_samps=[1]))) + base_attrs = base_attrs.union( + [ + "_data", # in the case of preloaded data + "__slotnames__", # something about being decorated (?) + ] + ) + for attr in raw._extra_attributes: + assert attr not in base_attrs + base_attrs.add(attr) + got_attrs = set(dir(raw)) + extra = got_attrs.difference(base_attrs) + assert extra == set() + + +def test_orig_units(): + """Test the error handling for original units.""" + # Should work fine + info = create_info(ch_names=["Cz"], sfreq=100, ch_types="eeg") + BaseRaw(info, last_samps=[1], orig_units={"Cz": "nV"}) + + # Should complain that channel Cz does not have a corresponding original + # unit. + with pytest.raises(ValueError, match="has no associated original unit."): + info = create_info(ch_names=["Cz"], sfreq=100, ch_types="eeg") + BaseRaw(info, last_samps=[1], orig_units={"not_Cz": "nV"}) + + # Test that a non-dict orig_units argument raises a ValueError + with pytest.raises(ValueError, match="orig_units must be of type dict"): + info = create_info(ch_names=["Cz"], sfreq=100, ch_types="eeg") + BaseRaw(info, last_samps=[1], orig_units=True) + + +def _test_raw_reader( + reader, + test_preloading=True, + test_kwargs=True, + boundary_decimal=2, + test_scaling=True, + test_rank=True, + **kwargs, +): + """Test reading, writing and slicing of raw classes. + + Parameters + ---------- + reader : function + Function to test. + test_preloading : bool + Whether not preloading is implemented for the reader. If True, both + cases and memory mapping to file are tested. + test_kwargs : dict + Test _init_kwargs support. + boundary_decimal : int + Number of decimals up to which the boundary should match. + **kwargs : + Arguments for the reader. Note: Do not use preload as kwarg. + Use ``test_preloading`` instead. + + Returns + ------- + raw : instance of Raw + A preloaded Raw object. + """ + tempdir = _TempDir() + rng = np.random.RandomState(0) + montage = None + if "montage" in kwargs: + montage = kwargs["montage"] + del kwargs["montage"] + if test_preloading: + raw = reader(preload=True, **kwargs) + rep = repr(raw) + assert rep.count("<") == 1 + assert rep.count(">") == 1 + if montage is not None: + raw.set_montage(montage) + # don't assume the first is preloaded + buffer_fname = op.join(tempdir, "buffer") + picks = rng.permutation(np.arange(len(raw.ch_names) - 1))[:10] + picks = np.append(picks, len(raw.ch_names) - 1) # test trigger channel + bnd = min(int(round(raw.buffer_size_sec * raw.info["sfreq"])), raw.n_times) + slices = [ + slice(0, bnd), + slice(bnd - 1, bnd), + slice(3, bnd), + slice(3, 300), + slice(None), + slice(1, bnd), + ] + if raw.n_times >= 2 * bnd: # at least two complete blocks + slices += [slice(bnd, 2 * bnd), slice(bnd, bnd + 1), slice(0, bnd + 100)] + other_raws = [ + reader(preload=buffer_fname, **kwargs), + reader(preload=False, **kwargs), + ] + for sl_time in slices: + data1, times1 = raw[picks, sl_time] + for other_raw in other_raws: + data2, times2 = other_raw[picks, sl_time] + assert_allclose(data1, data2, err_msg="Data mismatch with preload") + assert_allclose(times1, times2) + + # test projection vs cals and data units + other_raw = reader(preload=False, **kwargs) + other_raw.del_proj() + eeg = meg = fnirs = seeg = eyetrack = False + if "eeg" in raw: + eeg, atol = True, 1e-18 + elif "grad" in raw: + meg, atol = "grad", 1e-24 + elif "mag" in raw: + meg, atol = "mag", 1e-24 + elif "hbo" in raw: + fnirs, atol = "hbo", 1e-10 + elif "hbr" in raw: + fnirs, atol = "hbr", 1e-10 + elif "fnirs_cw_amplitude" in raw: + fnirs, atol = "fnirs_cw_amplitude", 1e-10 + elif "eyegaze" in raw: + eyetrack = "eyegaze", 1e-3 + else: + # e.g., https://github.com/mne-tools/mne-python/pull/11432/files + assert "seeg" in raw, "New channel type necessary? See gh-11432 for example" + seeg, atol = True, 1e-18 + + picks = pick_types( + other_raw.info, + meg=meg, + eeg=eeg, + fnirs=fnirs, + seeg=seeg, + eyetrack=eyetrack, + ) + col_names = [other_raw.ch_names[pick] for pick in picks] + proj = np.ones((1, len(picks))) + proj /= np.sqrt(proj.shape[1]) + proj = Projection( + data=dict( + data=proj, nrow=1, row_names=None, col_names=col_names, ncol=len(picks) + ), + active=False, + ) + assert len(other_raw.info["projs"]) == 0 + other_raw.add_proj(proj) + assert len(other_raw.info["projs"]) == 1 + # Orders of projector application, data loading, and reordering + # equivalent: + # 1. load->apply->get + data_load_apply_get = other_raw.copy().load_data().apply_proj().get_data(picks) + # 2. apply->get (and don't allow apply->pick) + apply = other_raw.copy().apply_proj() + data_apply_get = apply.get_data(picks) + data_apply_get_0 = apply.get_data(picks[0])[0] + with pytest.raises(RuntimeError, match="loaded"): + apply.copy().pick(picks[0]).get_data() + # 3. apply->load->get + data_apply_load_get = apply.copy().load_data().get_data(picks) + data_apply_load_get_0, data_apply_load_get_1 = ( + apply.copy().load_data().pick(picks[:2]).get_data() + ) + # 4. reorder->apply->load->get + all_picks = np.arange(len(other_raw.ch_names)) + reord = np.concatenate( + (picks[1::2], picks[0::2], np.setdiff1d(all_picks, picks)) + ) + rev = np.argsort(reord) + assert_array_equal(reord[rev], all_picks) + assert_array_equal(rev[reord], all_picks) + reorder = other_raw.copy().pick(reord) + assert reorder.ch_names == [other_raw.ch_names[r] for r in reord] + assert reorder.ch_names[0] == other_raw.ch_names[picks[1]] + assert_allclose(reorder.get_data([0]), other_raw.get_data(picks[1])) + reorder_apply = reorder.copy().apply_proj() + assert reorder_apply.ch_names == reorder.ch_names + assert reorder_apply.ch_names[0] == apply.ch_names[picks[1]] + assert_allclose( + reorder_apply.get_data([0]), apply.get_data(picks[1]), atol=1e-18 + ) + data_reorder_apply_load_get = reorder_apply.load_data().get_data( + rev[: len(picks)] + ) + data_reorder_apply_load_get_1 = ( + reorder_apply.copy().load_data().pick([0]).get_data()[0] + ) + assert reorder_apply.ch_names[0] == apply.ch_names[picks[1]] + assert ( + data_load_apply_get.shape + == data_apply_get.shape + == data_apply_load_get.shape + == data_reorder_apply_load_get.shape + ) + del apply + # first check that our data are (probably) in the right units + data = data_load_apply_get.copy() + data = data - np.mean(data, axis=1, keepdims=True) # can be offsets + np.abs(data, out=data) + if test_scaling: + maxval = atol * 1e16 + assert_array_less(data, maxval) + minval = atol * 1e6 + assert_array_less(minval, np.median(data)) + else: + atol = 1e-7 * np.median(data) # 1e-7 * MAD + # ranks should all be reduced by 1 + if test_rank == "less": + cmp = np.less + elif test_rank is False: + cmp = None + else: # anything else is like True or 'equal' + assert test_rank is True or test_rank == "equal", test_rank + cmp = np.equal + rank_load_apply_get = np.linalg.matrix_rank(data_load_apply_get) + rank_apply_get = np.linalg.matrix_rank(data_apply_get) + rank_apply_load_get = np.linalg.matrix_rank(data_apply_load_get) + if cmp is not None: + assert cmp(rank_load_apply_get, len(col_names) - 1) + assert cmp(rank_apply_get, len(col_names) - 1) + assert cmp(rank_apply_load_get, len(col_names) - 1) + # and they should all match + t_kw = dict(atol=atol, err_msg="before != after, likely _mult_cal_one prob") + assert_allclose(data_apply_get[0], data_apply_get_0, **t_kw) + assert_allclose(data_apply_load_get_1, data_reorder_apply_load_get_1, **t_kw) + assert_allclose(data_load_apply_get[0], data_apply_load_get_0, **t_kw) + assert_allclose(data_load_apply_get, data_apply_get, **t_kw) + assert_allclose(data_load_apply_get, data_apply_load_get, **t_kw) + if "eeg" in raw: + other_raw.del_proj() + direct = other_raw.copy().load_data().set_eeg_reference().get_data() + other_raw.set_eeg_reference(projection=True) + assert len(other_raw.info["projs"]) == 1 + this_proj = other_raw.info["projs"][0]["data"] + assert this_proj["col_names"] == col_names + assert this_proj["data"].shape == proj["data"]["data"].shape + assert_allclose(np.linalg.norm(proj["data"]["data"]), 1.0, atol=1e-6) + assert_allclose(np.linalg.norm(this_proj["data"]), 1.0, atol=1e-6) + assert_allclose(this_proj["data"], proj["data"]["data"]) + proj = other_raw.apply_proj().get_data() + assert_allclose(proj[picks], data_load_apply_get, atol=1e-10) + assert_allclose(proj, direct, atol=1e-10, err_msg=t_kw["err_msg"]) + else: + raw = reader(**kwargs) + n_samp = len(raw.times) + assert_named_constants(raw.info) + assert_attributes(raw) + # smoke test for gh #9743 + ids = [id(ch["loc"]) for ch in raw.info["chs"]] + assert len(set(ids)) == len(ids) + + full_data = raw.get_data() + assert raw.__class__.__name__ in repr(raw) # to test repr + assert raw.info.__class__.__name__ in repr(raw.info) + assert isinstance(raw.info["dig"], type(None) | list) + data_max = np.nanmax(full_data) + data_min = np.nanmin(full_data) + # these limits could be relaxed if we actually find data with + # huge values (in SI units) + assert data_max < 1e5 + assert data_min > -1e5 + if isinstance(raw.info["dig"], list): + for di, d in enumerate(raw.info["dig"]): + assert isinstance(d, DigPoint), (di, d) + + # gh-5604 + meas_date = raw.info["meas_date"] + assert meas_date is None or meas_date >= _stamp_to_dt((0, 0)) + + # gh-13112 + if "meg" not in raw: + assert raw.info["dev_head_t"] is None, "dev_head_t should be None if no MEG" + + # test repr_html + assert "Channels" in raw._repr_html_() + + # test resetting raw + if test_kwargs: + raw2 = reader(**raw._init_kwargs) + assert set(raw.info.keys()) == set(raw2.info.keys()) + assert_array_equal(raw.times, raw2.times) + + # Test saving and reading + out_fname = op.join(tempdir, "test_out_raw.fif") + raw = concatenate_raws([raw]) + filenames = raw.save( + out_fname, tmax=raw.times[-1], overwrite=True, buffer_size_sec=1 + ) + for filename in filenames: + assert filename.is_file() + # Test saving with not correct extension + out_fname_h5 = op.join(tempdir, "test_raw.h5") + with pytest.raises(OSError, match="raw must end with .fif or .fif.gz"): + raw.save(out_fname_h5) + + raw3 = read_raw_fif(out_fname, allow_maxshield="yes") + assert_named_constants(raw3.info) + assert set(raw.info.keys()) == set(raw3.info.keys()) + assert_allclose( + raw3[0:20][0], full_data[0:20], rtol=1e-6, atol=1e-20 + ) # atol is very small but > 0 + assert_allclose(raw.times, raw3.times, atol=1e-6, rtol=1e-6) + + assert not math.isnan(raw3.info["highpass"]) + assert not math.isnan(raw3.info["lowpass"]) + assert not math.isnan(raw.info["highpass"]) + assert not math.isnan(raw.info["lowpass"]) + + assert raw3.info["kit_system_id"] == raw.info["kit_system_id"] + + # Make sure concatenation works + first_samp = raw.first_samp + last_samp = raw.last_samp + concat_raw = concatenate_raws([raw.copy(), raw], verbose="debug") + assert concat_raw.n_times == 2 * raw.n_times + assert concat_raw.first_samp == first_samp + assert concat_raw.last_samp - last_samp + first_samp == last_samp + 1 + idx = np.where(concat_raw.annotations.description == "BAD boundary")[0] + assert len(idx) == 1 + assert len(concat_raw.times) == 2 * n_samp + + expected_bad_boundary_onset = raw._last_time + + assert_array_almost_equal( + concat_raw.annotations.onset[idx], + [expected_bad_boundary_onset], + decimal=boundary_decimal, + err_msg="BAD boundary onset mismatch", + ) + + if raw.info["meas_id"] is not None: + for key in ["secs", "usecs", "version"]: + assert raw.info["meas_id"][key] == raw3.info["meas_id"][key] + assert_array_equal( + raw.info["meas_id"]["machid"], raw3.info["meas_id"]["machid"] + ) + + assert isinstance(raw.annotations, Annotations) + + # Make a "soft" test on units: They have to be valid SI units as in + # mne.io.meas_info.valid_units, but we accept any lower/upper case for now. + valid_units = _get_valid_units() + valid_units_lower = [unit.lower() for unit in valid_units] + if raw._orig_units is not None: + assert isinstance(raw._orig_units, dict) + for ch_name, unit in raw._orig_units.items(): + assert unit.lower() in valid_units_lower, ch_name + + # Test picking with and without preload + if test_preloading: + preload_kwargs = (dict(preload=True), dict(preload=False)) + else: + preload_kwargs = (dict(),) + n_ch = len(raw.ch_names) + picks = rng.permutation(n_ch) + for preload_kwarg in preload_kwargs: + these_kwargs = kwargs.copy() + these_kwargs.update(preload_kwarg) + # don't use the same filename or it could create problems + if isinstance(these_kwargs.get("preload", None), str) and op.isfile( + these_kwargs["preload"] + ): + these_kwargs["preload"] += "-1" + whole_raw = reader(**these_kwargs) + print(whole_raw) # __repr__ + assert n_ch >= 2 + picks_1 = picks[: n_ch // 2] + picks_2 = picks[n_ch // 2 :] + raw_1 = whole_raw.copy().pick(picks_1) + raw_2 = whole_raw.copy().pick(picks_2) + data, times = whole_raw[:] + data_1, times_1 = raw_1[:] + data_2, times_2 = raw_2[:] + assert_array_equal(times, times_1) + assert_array_equal(data[picks_1], data_1) + assert_array_equal( + times, + times_2, + ) + assert_array_equal(data[picks_2], data_2) + + # Make sure that writing info to h5 format + # (all fields should be compatible) + if check_version("h5io"): + read_hdf5, write_hdf5 = _import_h5io_funcs() + fname_h5 = op.join(tempdir, "info.h5") + with _writing_info_hdf5(raw.info): + write_hdf5(fname_h5, raw.info) + new_info = Info(read_hdf5(fname_h5)) + assert object_diff(new_info, raw.info) == "" + + # Make sure that changing directory does not break anything + if test_preloading: + these_kwargs = kwargs.copy() + key = None + for key in ( + "fname", + "input_fname", # artemis123 + "vhdr_fname", # BV + "pdf_fname", # BTi + "directory", # CTF + "filename", # nedf + ): + try: + fname = kwargs[key] + except KeyError: + key = None + else: + break + # len(kwargs) == 0 for the fake arange reader + if len(kwargs): + assert key is not None, sorted(kwargs.keys()) + this_fname = fname[0] if isinstance(fname, list) else fname + dirname = op.dirname(this_fname) + these_kwargs[key] = op.basename(this_fname) + these_kwargs["preload"] = False + orig_dir = os.getcwd() + try: + os.chdir(dirname) + raw_chdir = reader(**these_kwargs) + finally: + os.chdir(orig_dir) + raw_chdir.load_data() + + # make sure that cropping works (with first_samp shift) + if n_samp >= 50: # we crop to this number of samples below + for t_prop in (0.0, 0.5): + _test_raw_crop(reader, t_prop, kwargs) + if test_preloading: + use_kwargs = kwargs.copy() + use_kwargs["preload"] = True + _test_raw_crop(reader, t_prop, use_kwargs) + + # make sure electrode-like sensor locations show up as dig points + eeg_dig = [d for d in (raw.info["dig"] or []) if d["kind"] == _dig_kind_dict["eeg"]] + pick_kwargs = dict() + for t in _ELECTRODE_CH_TYPES + ("fnirs",): + pick_kwargs[t] = True + dig_picks = pick_types(raw.info, exclude=(), **pick_kwargs) + dig_types = _ELECTRODE_CH_TYPES + _FNIRS_CH_TYPES_SPLIT + assert (len(dig_picks) > 0) == any(t in raw for t in dig_types) + if len(dig_picks): + eeg_loc = np.array( + [ # eeg_loc a bit of a misnomer to match eeg_dig + raw.info["chs"][pick]["loc"][:3] for pick in dig_picks + ] + ) + eeg_loc = eeg_loc[np.isfinite(eeg_loc).all(axis=1)] + if len(eeg_loc): + if "fnirs_cw_amplitude" in raw: + assert 2 * len(eeg_dig) >= len(eeg_loc) + else: + assert len(eeg_dig) >= len(eeg_loc) # could have some excluded + # make sure that dig points in head coords implies that fiducials are + # present + if len(raw.info["dig"] or []) > 0: + card_pts_head = [ + d + for d in raw.info["dig"] + if d["kind"] == _dig_kind_dict["cardinal"] + and d["coord_frame"] == FIFF.FIFFV_COORD_HEAD + ] + eeg_dig_head = [d for d in eeg_dig if d["coord_frame"] == FIFF.FIFFV_COORD_HEAD] + if len(eeg_dig_head): + assert len(card_pts_head) == 3, "Cardinal points missing" + if len(card_pts_head) == 3: # they should all be in head coords then + assert len(eeg_dig_head) == len(eeg_dig) + + return raw + + +def _test_raw_crop(reader, t_prop, kwargs): + raw_1 = reader(**kwargs) + n_samp = 50 # crop to this number of samples (per instance) + crop_t = n_samp / raw_1.info["sfreq"] + t_start = t_prop * crop_t # also crop to some fraction into the first inst + extra = f" t_start={t_start}, preload={kwargs.get('preload', False)}" + stop = (n_samp - 1) / raw_1.info["sfreq"] + raw_1.crop(0, stop) + assert len(raw_1.times) == 50 + first_time = raw_1.first_time + atol = 0.5 / raw_1.info["sfreq"] + assert_allclose(raw_1.times[-1], stop, atol=atol) + raw_2, raw_3 = raw_1.copy(), raw_1.copy() + t_tot = raw_1.times[-1] * 3 + 2.0 / raw_1.info["sfreq"] + raw_concat = concatenate_raws([raw_1, raw_2, raw_3]) + assert len(raw_concat.filenames) == 3 + assert_allclose(raw_concat.times[-1], t_tot) + assert_allclose(raw_concat.first_time, first_time) + # keep all instances, but crop to t_start at the beginning + raw_concat.crop(t_start, None) + assert len(raw_concat.filenames) == 3 + assert_allclose(raw_concat.times[-1], t_tot - t_start, atol=atol) + assert_allclose( + raw_concat.first_time, + first_time + t_start, + atol=atol, + err_msg=f"Base concat, {extra}", + ) + # drop the first instance + raw_concat.crop(crop_t, None) + assert len(raw_concat.filenames) == 2 + assert_allclose(raw_concat.times[-1], t_tot - t_start - crop_t, atol=atol) + assert_allclose( + raw_concat.first_time, + first_time + t_start + crop_t, + atol=atol, + err_msg=f"Dropping one, {extra}", + ) + # drop the second instance, leaving just one + raw_concat.crop(crop_t, None) + assert len(raw_concat.filenames) == 1 + assert_allclose(raw_concat.times[-1], t_tot - t_start - 2 * crop_t, atol=atol) + assert_allclose( + raw_concat.first_time, + first_time + t_start + 2 * crop_t, + atol=atol, + err_msg=f"Dropping two, {extra}", + ) + + +def _test_concat(reader, *args): + """Test concatenation of raw classes that allow not preloading.""" + data = None + + for preload in (True, False): + raw1 = reader(*args, preload=preload) + raw2 = reader(*args, preload=preload) + raw1.append(raw2) + raw1.load_data() + if data is None: + data = raw1[:, :][0] + assert_allclose(data, raw1[:, :][0]) + + for first_preload in (True, False): + raw = reader(*args, preload=first_preload) + data = raw[:, :][0] + for preloads in ((True, True), (True, False), (False, False)): + for last_preload in (True, False): + t_crops = raw.times[np.argmin(np.abs(raw.times - 0.5)) + [0, 1]] + raw1 = raw.copy().crop(0, t_crops[0]) + if preloads[0]: + raw1.load_data() + raw2 = raw.copy().crop(t_crops[1], None) + if preloads[1]: + raw2.load_data() + raw1.append(raw2) + if last_preload: + raw1.load_data() + assert_allclose(data, raw1[:, :][0]) + + +def test_time_as_index(): + """Test indexing of raw times.""" + raw = read_raw_fif(raw_fname) + + # Test original (non-rounding) indexing behavior + orig_inds = raw.time_as_index(raw.times) + assert len(set(orig_inds)) != len(orig_inds) + + # Test new (rounding) indexing behavior + new_inds = raw.time_as_index(raw.times, use_rounding=True) + assert_array_equal(new_inds, np.arange(len(raw.times))) + + +@pytest.mark.parametrize("meas_date", [None, "orig"]) +@pytest.mark.parametrize("first_samp", [0, 10000]) +def test_crop_by_annotations(meas_date, first_samp): + """Test crop by annotations of raw.""" + raw = read_raw_fif(raw_fname) + + if meas_date is None: + raw.set_meas_date(None) + + raw = mne.io.RawArray(raw.get_data(), raw.info, first_samp=first_samp) + + onset = np.array([0, 1.5], float) + if meas_date is not None: + onset += raw.first_time + annot = mne.Annotations( + onset=onset, + duration=[1, 0.5], + description=["a", "b"], + orig_time=raw.info["meas_date"], + ) + + raw.set_annotations(annot) + raws = raw.crop_by_annotations() + assert len(raws) == 2 + assert len(raws[0].annotations) == 1 + assert raws[0].times[-1] == pytest.approx(annot[:1].duration[0], rel=1e-3) + assert raws[0].annotations.description[0] == annot.description[0] + assert len(raws[1].annotations) == 1 + assert raws[1].times[-1] == pytest.approx(annot[1:2].duration[0], rel=5e-3) + assert raws[1].annotations.description[0] == annot.description[1] + + +@pytest.mark.parametrize( + "offset, origin", + [ + pytest.param(0, None, id="times in s. relative to first_samp (default)"), + pytest.param(0, 2.0, id="times in s. relative to first_samp"), + pytest.param(1, 1.0, id="times in s. relative to meas_date"), + pytest.param(2, 0.0, id="absolute times in s. relative to 0"), + ], +) +def test_time_as_index_ref(offset, origin): + """Test indexing of raw times.""" + info = create_info(ch_names=10, sfreq=10.0) + raw = RawArray(data=np.empty((10, 10)), info=info, first_samp=10) + raw.set_meas_date(1) + + relative_times = raw.times + inds = raw.time_as_index(relative_times + offset, use_rounding=True, origin=origin) + assert_array_equal(inds, np.arange(raw.n_times)) + + +def test_meas_date_orig_time(): + """Test the relation between meas_time in orig_time.""" + # meas_time is set and orig_time is set: + # clips the annotations based on raw.data and resets the annotation based + # on raw.info['meas_date] + raw = _raw_annot(1, 1.5) + assert raw.annotations.orig_time == _stamp_to_dt((1, 0)) + assert raw.annotations.onset[0] == 1 + + # meas_time is set and orig_time is None: + # Consider annot.orig_time to be raw.frist_sample, clip and reset + # annotations to have the raw.annotations.orig_time == raw.info['meas_date] + raw = _raw_annot(1, None) + assert raw.annotations.orig_time == _stamp_to_dt((1, 0)) + assert raw.annotations.onset[0] == 1.5 + + # meas_time is None and orig_time is set: + # Raise error, it makes no sense to have an annotations object that we know + # when was acquired and set it to a raw object that does not know when was + # it acquired. + with pytest.raises(RuntimeError, match="Ambiguous operation"): + _raw_annot(None, 1.5) + + # meas_time is None and orig_time is None: + # Consider annot.orig_time to be raw.first_sample and clip + raw = _raw_annot(None, None) + assert raw.annotations.orig_time is None + assert raw.annotations.onset[0] == 1.5 + assert raw.annotations.duration[0] == 0.2 + + +def test_get_data_reject(): + """Test if reject_by_annotation is working correctly.""" + fs = 256 + ch_names = ["C3", "Cz", "C4"] + info = create_info(ch_names, sfreq=fs) + raw = RawArray(np.zeros((len(ch_names), 10 * fs)), info) + raw.set_annotations(Annotations(onset=[2, 4], duration=[3, 2], description="bad")) + + with catch_logging() as log: + data = raw.get_data(reject_by_annotation="omit", verbose=True) + msg = ( + "Omitting 1024 of 2560 (40.00%) samples, retaining 1536" + + " (60.00%) samples." + ) + assert log.getvalue().strip() == msg + assert data.shape == (len(ch_names), 1536) + with catch_logging() as log: + data = raw.get_data(reject_by_annotation="nan", verbose=True) + msg = ( + "Setting 1024 of 2560 (40.00%) samples to NaN, retaining 1536" + + " (60.00%) samples." + ) + assert log.getvalue().strip() == msg + assert data.shape == (len(ch_names), 2560) # shape doesn't change + assert np.isnan(data).sum() == 3072 # but NaNs are introduced instead + + +def test_5839(): + """Test concatenating raw objects with annotations.""" + # Global Time 0 1 2 3 4 + # . + # raw_A |---------XXXXXXXXXX + # annot |--------------AA + # latency . 0 0 1 1 2 2 3 + # . 5 0 5 0 5 0 + # + # raw_B . |---------YYYYYYYYYY + # annot . |--------------AA + # latency . 0 1 + # . 5 0 + # . + # output |---------XXXXXXXXXXYYYYYYYYYY + # annot |--------------AA---|----AA + # latency . 0 0 1 1 2 2 3 + # . 5 0 5 0 5 0 + # + EXPECTED_ONSET = [1.5, 2.0, 2.0, 2.5] + EXPECTED_DURATION = [0.2, 0.0, 0.0, 0.2] + EXPECTED_DESCRIPTION = ["dummy", "BAD boundary", "EDGE boundary", "dummy"] + + def raw_factory(meas_date): + raw = RawArray( + data=np.empty((10, 10)), + info=create_info(ch_names=10, sfreq=10.0), + first_samp=10, + ) + raw.set_meas_date(meas_date) + raw.set_annotations( + annotations=Annotations( + onset=[0.5], duration=[0.2], description="dummy", orig_time=None + ) + ) + return raw + + raw_A, raw_B = (raw_factory((x, 0)) for x in [0, 2]) + raw_A.append(raw_B) + + assert_array_equal(raw_A.annotations.onset, EXPECTED_ONSET) + assert_array_equal(raw_A.annotations.duration, EXPECTED_DURATION) + assert_array_equal(raw_A.annotations.description, EXPECTED_DESCRIPTION) + assert raw_A.annotations.orig_time == _stamp_to_dt((0, 0)) + + +def test_duration_property(): + """Test BaseRAW.duration property.""" + sfreq = 1000 + info = create_info(ch_names=["EEG 001"], sfreq=sfreq) + raw = BaseRaw(info, last_samps=[sfreq * 60 - 1]) + assert raw.duration == 60 + + +@pytest.mark.parametrize("sfreq", [1, 10, 100, 1000]) +@pytest.mark.parametrize( + "duration, expected", + [ + (0.1, "00:00:01"), + (1, "00:00:01"), + (59, "00:00:59"), + (59.1, "00:01:00"), + (60, "00:01:00"), + (60.1, "00:01:01"), + (61, "00:01:01"), + (61.1, "00:01:02"), + ], +) +def test_get_duration_string(sfreq, duration, expected): + """Test BaseRAW_get_duration_string() method.""" + info = create_info(ch_names=["EEG 001"], sfreq=sfreq) + raw = BaseRaw(info, last_samps=[sfreq * duration - 1]) + assert raw._get_duration_string() == expected + + +@pytest.mark.parametrize("sfreq", [1, 10, 100, 256, 1000]) +def test_repr(sfreq): + """Test repr of Raw.""" + info = create_info(3, sfreq) + sample_count = 10 * sfreq + raw = RawArray(np.zeros((3, sample_count)), info) + r = repr(raw) + size_str = sizeof_fmt(raw._size) + assert r == f"" + assert raw._repr_html_() + + +# A class that sets channel data to np.arange, for testing _test_raw_reader +class _RawArange(BaseRaw): + def __init__(self, preload=False, verbose=None): + info = create_info(list(str(x) for x in range(1, 9)), 1000.0, "eeg") + super().__init__(info, preload, last_samps=(999,), verbose=verbose) + assert len(self.times) == 1000 + + def _read_segment_file(self, data, idx, fi, start, stop, cals, mult): + one = np.full((8, stop - start), np.nan) + one[idx] = np.arange(1, 9)[idx, np.newaxis] + _mult_cal_one(data, one, idx, cals, mult) + + +def _read_raw_arange(preload=False, verbose=None): + return _RawArange(preload, verbose) + + +def test_test_raw_reader(): + """Test _test_raw_reader.""" + _test_raw_reader(_read_raw_arange, test_scaling=False, test_rank="less") + + +@pytest.mark.slowtest +def test_describe_print(): + """Test print output of describe method.""" + fname = Path(__file__).parent / "data" / "test_raw.fif" + raw = read_raw_fif(fname) + + # test print output + f = StringIO() + with redirect_stdout(f): + raw.describe() + s = f.getvalue().strip().split("\n") + assert len(s) == 378 + # Can be 3.1, 3.3, etc. + assert ( + re.match( + r"", + s[0], + ) + is not None + ), s[0] + assert ( + s[1] + == " ch name type unit min Q1 median Q3 max" # noqa: E501 + ) + assert ( + s[2] + == " 0 MEG 0113 GRAD fT/cm -221.80 -38.57 -9.64 19.29 414.67" # noqa: E501 + ) + assert ( + s[-1] + == "375 EOG 061 EOG µV -231.41 271.28 277.16 285.66 334.69" # noqa: E501 + ) + + +@pytest.mark.slowtest +def test_describe_df(): + """Test returned data frame of describe method.""" + pytest.importorskip("pandas") + fname = Path(__file__).parent / "data" / "test_raw.fif" + raw = read_raw_fif(fname) + + df = raw.describe(data_frame=True) + assert df.shape == (376, 8) + assert df.columns.tolist() == [ + "name", + "type", + "unit", + "min", + "Q1", + "median", + "Q3", + "max", + ] + assert df.index.name == "ch" + assert_allclose( + df.iloc[0, 3:].astype(float), + np.array( + [ + -2.218017605790535e-11, + -3.857421923113974e-12, + -9.643554807784935e-13, + 1.928710961556987e-12, + 4.146728567347522e-11, + ] + ), + ) + + +def test_get_data_units(): + """Test the "units" argument of get_data method.""" + # Test the unit conversion function + assert _get_scaling("eeg", "uV") == 1e6 + assert _get_scaling("eeg", "dV") == 1e1 + assert _get_scaling("eeg", "pV") == 1e12 + assert _get_scaling("mag", "fT") == 1e15 + assert _get_scaling("grad", "T/m") == 1 + assert _get_scaling("grad", "T/mm") == 1e-3 + assert _get_scaling("grad", "fT/m") == 1e15 + assert _get_scaling("grad", "fT/cm") == 1e13 + assert _get_scaling("csd", "uV/cm²") == 1e2 + + fname = Path(__file__).parent / "data" / "test_raw.fif" + raw = read_raw_fif(fname) + + last = np.array([4.63803098e-05, 7.66563736e-05, 2.71933595e-04]) + last_eeg = np.array([7.12207023e-05, 4.63803098e-05, 7.66563736e-05]) + last_grad = np.array([-3.85742192e-12, 9.64355481e-13, -1.06079103e-11]) + + # None + data_none = raw.get_data() + assert data_none.shape == (376, 14400) + assert_array_almost_equal(data_none[-3:, -1], last) + + # str: unit no conversion + data_str_noconv = raw.get_data(picks=["eeg"], units="V") + assert data_str_noconv.shape == (60, 14400) + assert_array_almost_equal(data_str_noconv[-3:, -1], last_eeg) + # str: simple unit + data_str_simple = raw.get_data(picks=["eeg"], units="uV") + assert data_str_simple.shape == (60, 14400) + assert_array_almost_equal(data_str_simple[-3:, -1], last_eeg * 1e6) + # str: fraction unit + data_str_fraction = raw.get_data(picks=["grad"], units="fT/cm") + assert data_str_fraction.shape == (204, 14400) + assert_array_almost_equal(data_str_fraction[-3:, -1], last_grad * (1e15 / 1e2)) + # str: more than one channel type but one with unit + data_str_simplestim = raw.get_data(picks=["eeg", "stim"], units="V") + assert data_str_simplestim.shape == (69, 14400) + assert_array_almost_equal(data_str_simplestim[-3:, -1], last_eeg) + # str: too many channels + with pytest.raises(ValueError, match="more than one channel"): + raw.get_data(units="uV") + # str: invalid unit + with pytest.raises(ValueError, match="is not a valid unit"): + raw.get_data(picks=["eeg"], units="fV/cm") + + # dict: combination of simple and fraction units + data_dict = raw.get_data(units=dict(grad="fT/cm", mag="fT", eeg="uV")) + assert data_dict.shape == (376, 14400) + assert_array_almost_equal(data_dict[0, -1], -3.857421923113974e-12 * (1e15 / 1e2)) + assert_array_almost_equal(data_dict[2, -1], -2.1478272253525944e-13 * 1e15) + assert_array_almost_equal(data_dict[-2, -1], 7.665637356879529e-05 * 1e6) + # dict: channel type not in instance + data_dict_notin = raw.get_data(units=dict(hbo="uM")) + assert data_dict_notin.shape == (376, 14400) + assert_array_almost_equal(data_dict_notin[-3:, -1], last) + # dict: one invalid unit + with pytest.raises(ValueError, match="is not a valid unit"): + raw.get_data(units=dict(grad="fT/cV", mag="fT", eeg="uV")) + # dict: one invalid channel type + with pytest.raises(KeyError, match="is not a channel type"): + raw.get_data(units=dict(bad_type="fT/cV", mag="fT", eeg="uV")) + + # not the good type + with pytest.raises(TypeError, match="instance of None, str, or dict"): + raw.get_data(units=["fT/cm", "fT", "uV"]) + + +def test_repr_dig_point(): + """Test printing of DigPoint.""" + dp = DigPoint( + r=np.arange(3), + coord_frame=FIFF.FIFFV_COORD_HEAD, + kind=FIFF.FIFFV_POINT_EEG, + ident=0, + ) + assert "mm" in repr(dp) + + dp = DigPoint( + r=np.arange(3), + coord_frame=FIFF.FIFFV_MNE_COORD_MRI_VOXEL, + kind=FIFF.FIFFV_POINT_CARDINAL, + ident=0, + ) + assert "mm" not in repr(dp) + assert "voxel" in repr(dp) + + +def test_get_data_tmin_tmax(): + """Test tmin and tmax parameters of get_data method.""" + fname = Path(__file__).parent / "data" / "test_raw.fif" + raw = read_raw_fif(fname) + + # tmin and tmax just use time_as_index under the hood + tmin, tmax = (1, 9) + d1 = raw.get_data() + d2 = raw.get_data(tmin=tmin, tmax=tmax) + + idxs = raw.time_as_index([tmin, tmax]) + assert_allclose(d1[:, idxs[0] : idxs[1]], d2) + + # specifying a too low tmin truncates to idx 0 + d3 = raw.get_data(tmin=-5) + assert_allclose(d3, d1) + + # specifying a too high tmax truncates to idx n_times + d4 = raw.get_data(tmax=1e6) + assert_allclose(d4, d1) + + # when start/stop are passed, tmin/tmax are ignored + d5 = raw.get_data(start=1, stop=2, tmin=tmin, tmax=tmax) + assert d5.shape[1] == 1 + + # validate inputs are properly raised + with pytest.raises(TypeError, match="start must be .* int"): + raw.get_data(start=None) + + with pytest.raises(TypeError, match="stop must be .* int"): + raw.get_data(stop=2.3) + + with pytest.raises(TypeError, match="tmin must be .* float"): + raw.get_data(tmin=[1, 2]) + + with pytest.raises(TypeError, match="tmax must be .* float"): + raw.get_data(tmax=[1, 2]) + + +def test_resamp_noop(): + """Tests resampling doesn't affect data if sfreq is identical.""" + raw = read_raw_fif(raw_fname) + data_before = raw.get_data() + data_after = raw.resample(sfreq=raw.info["sfreq"]).get_data() + assert_array_equal(data_before, data_after) + + +def test_concatenate_raw_dev_head_t(): + """Test concatenating raws with dev-head-t including nans.""" + data = np.random.randn(3, 10) + info = create_info(3, 1000.0, ["mag", "grad", "grad"]) + raw = RawArray(data, info) + raw.info["dev_head_t"] = Transform("meg", "head", np.eye(4)) + raw.info["dev_head_t"]["trans"][0, 0] = np.nan + raw2 = raw.copy() + concatenate_raws([raw, raw2]) + + +def test_last_samp(): + """Test that getting the last sample works.""" + raw = read_raw_fif(raw_fname).crop(0, 0.1).load_data() + last_data = raw._data[:, [-1]] + assert_array_equal(raw[:, -1][0], last_data) + + +def test_rescale(): + """Test rescaling channels.""" + raw = read_raw_fif(raw_fname, preload=True) # multiple channel types + + with pytest.raises(ValueError, match="If scalings is a scalar, all channels"): + raw.rescale(2) # need to use dict + + orig = raw.get_data(picks="eeg") + raw.rescale({"eeg": 2}) # need to use dict + assert_allclose(raw.get_data(picks="eeg"), orig * 2) + + raw.pick("mag") # only a single channel type "mag" + orig = raw.get_data() + raw.rescale(4) # a scalar works + assert_allclose(raw.get_data(), orig * 4) + + +def test_crop_reset_first_samp(): + """Regression test for GH-13278. + + crop(reset_first_samp=True) must reset first_samp to 0. + """ + info = create_info(ch_names=["CH1"], sfreq=1000.0, ch_types=["eeg"]) + data = np.zeros((1, 10000)) + raw = RawArray(data, info) + + # crop and reset first_samp + raw.crop(tmin=2.0, tmax=5.0, reset_first_samp=True) + assert raw.first_samp == 0 + assert raw.times[0] == 0.0 + + # crop without reset_first_samp (default behaviour) + raw2 = RawArray(data, info) + raw2.crop(tmin=2.0, tmax=5.0) + assert raw2.first_samp != 0 diff --git a/mne-python/source/mne/io/tests/test_read_raw.py b/mne-python/source/mne/io/tests/test_read_raw.py new file mode 100644 index 0000000000000000000000000000000000000000..f74a715d9e77946d049dbab84e0b3fe4ffd66b59 --- /dev/null +++ b/mne-python/source/mne/io/tests/test_read_raw.py @@ -0,0 +1,158 @@ +"""Test generic read_raw function.""" + +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +from pathlib import Path +from shutil import copyfile + +import pytest + +from mne.datasets import testing +from mne.io import read_raw +from mne.io._read_raw import _get_readers, _get_supported, split_name_ext + +base = Path(__file__).parents[1] +test_base = Path(testing.data_path(download=False)) + + +@pytest.mark.parametrize("fname", ["x.xxx", "x"]) +def test_read_raw_unsupported_single(fname): + """Test handling of unsupported file types.""" + with pytest.raises(ValueError, match="Unsupported file type"): + read_raw(fname) + + +@pytest.mark.parametrize("fname", ["x.bin"]) +def test_read_raw_unsupported_multi(fname, tmp_path): + """Test handling of supported file types but with bad data.""" + fname = tmp_path / fname + fname.write_text("") + with pytest.raises(RuntimeError, match="Could not read.*using any"): + read_raw(fname) + + +@pytest.mark.parametrize("fname", ["x.vmrk", "y.amrk"]) +def test_read_raw_suggested(fname): + """Test handling of unsupported file types with suggested alternatives.""" + with pytest.raises(ValueError, match="Try reading"): + read_raw(fname) + + +_testing_mark = testing._pytest_mark() + + +@pytest.mark.parametrize( + "fname", + [ + base / "tests/data/test_raw.fif", + base / "tests/data/test_raw.fif.gz", + base / "edf/tests/data/test.edf", + pytest.param( + base / "edf/tests/data/test.bdf", + marks=( + _testing_mark, + pytest.mark.filterwarnings("ignore:Channels contain different"), + ), + ), + base / "brainvision/tests/data/test.vhdr", + base / "kit/tests/data/test.sqd", + pytest.param(test_base / "KIT" / "data_berlin.con", marks=_testing_mark), + pytest.param( + test_base + / "ARTEMIS123" + / "Artemis_Data_2017-04-14-10h-38m-59s_Phantom_1k_HPI_1s.bin", + marks=_testing_mark, + ), + pytest.param( + test_base / "FIL" / "sub-noise_ses-001_task-noise220622_run-001_meg.bin", + marks=( + _testing_mark, + pytest.mark.filterwarnings("ignore:.*problems later!:RuntimeWarning"), + ), + ), + ], +) +def test_read_raw_supported(fname): + """Test supported file types.""" + read_raw(fname) + read_raw(fname, verbose=False) + raw = read_raw(fname, preload=True) + assert "data loaded" in str(raw) + + +def test_split_name_ext(): + """Test file name extension splitting.""" + # test known extensions + for ext in _get_readers(): + assert split_name_ext(f"test{ext}")[1] == ext + + # test unsupported extensions + for ext in ("this.is.not.supported", "a.b.c.d.e", "fif.gz.xyz"): + assert split_name_ext(f"test{ext}")[1] is None + + +def test_read_raw_multiple_dots(tmp_path): + """Test if file names with multiple dots work correctly.""" + src = base / "edf/tests/data/test.edf" + dst = tmp_path / "test.this.file.edf" + copyfile(src, dst) + read_raw(dst) + + +reader_excluded_from_read_raw = { + "read_raw_bti", + "read_raw_hitachi", + "read_raw_neuralynx", +} + + +def test_all_reader_documented(): + """Test that all the readers in the documentation are accepted by read_raw.""" + readers = _get_supported() + # flatten the dictionaries and retrieve the function names + functions = [foo.__name__ for value in readers.values() for foo in value.values()] + # read documentation .rst source file + doc_folder = Path(__file__).parents[3] / "doc" + if not doc_folder.exists(): + pytest.skip("Documentation folder not found.") + doc_file = doc_folder / "api" / "reading_raw_data.rst" + doc = doc_file.read_text("utf-8") + reader_lines = [ + line.strip() for line in doc.split("\n") if line.strip().startswith("read_raw_") + ] + reader_lines = [ + elt for elt in reader_lines if elt not in reader_excluded_from_read_raw + ] + missing_from_read_raw = set(reader_lines) - set(functions) + missing_from_doc = set(functions) - set(reader_lines) + if len(missing_from_doc) != 0 or len(missing_from_read_raw) != 0: + raise AssertionError( + "Functions missing from documentation:\n\t" + + "\n\t".join(missing_from_doc) + + "\n\nFunctions missing from read_raw:\n\t" + + "\n\t".join(missing_from_read_raw) + ) + if sorted(reader_lines) != list(reader_lines): + raise AssertionError( + "Functions in documentation are not sorted. Expected order:\n\t" + + "\n\t".join(sorted(reader_lines)) + ) + + +def test_all_reader_documented_in_docstring(): + """Test that all the readers are documented in read_raw docstring.""" + readers = _get_supported() + # flatten the dictionaries and retrieve the function names + functions = [foo.__name__ for value in readers.values() for foo in value.values()] + doc = read_raw.__doc__.split("Parameters")[0] + documented = [elt.strip().split("`")[0] for elt in doc.split("mne.io.")[1:]] + missing_from_docstring = set(functions) - set(documented) + if len(missing_from_docstring) != 0: + raise AssertionError( + "Functions missing from docstring:\n\t" + + "\n\t".join(missing_from_docstring) + ) + if sorted(documented) != documented: + raise AssertionError("Functions in docstring are not sorted.") diff --git a/mne-python/source/mne/label.py b/mne-python/source/mne/label.py new file mode 100644 index 0000000000000000000000000000000000000000..2d55de755c066fd5ad360d4fc67b739a5ec20752 --- /dev/null +++ b/mne-python/source/mne/label.py @@ -0,0 +1,2980 @@ +# Authors: The MNE-Python contributors. +# License: BSD-3-Clause +# Copyright the MNE-Python contributors. + +import copy as cp +import os +import os.path as op +import re +from collections import defaultdict +from colorsys import hsv_to_rgb, rgb_to_hsv + +import numpy as np +from scipy import linalg, sparse + +from .fixes import _safe_svd +from .morph_map import read_morph_map +from .parallel import parallel_func +from .source_estimate import ( + SourceEstimate, + VolSourceEstimate, + _center_of_mass, + extract_label_time_course, + spatial_src_adjacency, +) +from .source_space._source_space import ( + SourceSpaces, + _ensure_src, + add_source_space_distances, +) +from .stats.cluster_level import _find_clusters, _get_components +from .surface import ( + _mesh_borders, + complete_surface_info, + fast_cross_3d, + mesh_dist, + mesh_edges, + read_surface, +) +from .utils import ( + _check_fname, + _check_option, + _check_subject, + _validate_type, + check_random_state, + fill_doc, + get_subjects_dir, + logger, + verbose, + warn, +) + + +def _blend_colors(color_1, color_2): + """Blend two colors in HSV space. + + Parameters + ---------- + color_1, color_2 : None | tuple + RGBA tuples with values between 0 and 1. None if no color is available. + If both colors are None, the output is None. If only one is None, the + output is the other color. + + Returns + ------- + color : None | tuple + RGBA tuple of the combined color. Saturation, value and alpha are + averaged, whereas the new hue is determined as angle half way between + the two input colors' hues. + """ + if color_1 is None and color_2 is None: + return None + elif color_1 is None: + return color_2 + elif color_2 is None: + return color_1 + + r_1, g_1, b_1, a_1 = color_1 + h_1, s_1, v_1 = rgb_to_hsv(r_1, g_1, b_1) + r_2, g_2, b_2, a_2 = color_2 + h_2, s_2, v_2 = rgb_to_hsv(r_2, g_2, b_2) + hue_diff = abs(h_1 - h_2) + if hue_diff < 0.5: + h = min(h_1, h_2) + hue_diff / 2.0 + else: + h = max(h_1, h_2) + (1.0 - hue_diff) / 2.0 + h %= 1.0 + s = (s_1 + s_2) / 2.0 + v = (v_1 + v_2) / 2.0 + r, g, b = hsv_to_rgb(h, s, v) + a = (a_1 + a_2) / 2.0 + color = (r, g, b, a) + return color + + +def _split_colors(color, n): + """Create n colors in HSV space that occupy a gradient in value. + + Parameters + ---------- + color : tuple + RGBA tuple with values between 0 and 1. + n : int >= 2 + Number of colors on the gradient. + + Returns + ------- + colors : tuple of tuples, len = n + N RGBA tuples that occupy a gradient in value (low to high) but share + saturation and hue with the input color. + """ + r, g, b, a = color + h, s, v = rgb_to_hsv(r, g, b) + gradient_range = np.sqrt(n / 10.0) + if v > 0.5: + v_max = min(0.95, v + gradient_range / 2) + v_min = max(0.05, v_max - gradient_range) + else: + v_min = max(0.05, v - gradient_range / 2) + v_max = min(0.95, v_min + gradient_range) + + hsv_colors = ((h, s, v_) for v_ in np.linspace(v_min, v_max, n)) + rgb_colors = (hsv_to_rgb(h_, s_, v_) for h_, s_, v_ in hsv_colors) + rgba_colors = ( + ( + r_, + g_, + b_, + a, + ) + for r_, g_, b_ in rgb_colors + ) + return tuple(rgba_colors) + + +def _n_colors(n, bytes_=False, cmap="hsv"): + """Produce a list of n unique RGBA color tuples based on a colormap. + + Parameters + ---------- + n : int + Number of colors. + bytes : bool + Return colors as integers values between 0 and 255 (instead of floats + between 0 and 1). + cmap : str + Which colormap to use. + + Returns + ------- + colors : array, shape (n, 4) + RGBA color values. + """ + n_max = 2**10 + if n > n_max: + raise NotImplementedError(f"Can't produce more than {n_max} unique colors.") + + from .viz.utils import _get_cmap + + cm = _get_cmap(cmap) + pos = np.linspace(0, 1, n, False) + colors = cm(pos, bytes=bytes_) + if bytes_: + # make sure colors are unique + for ii, c in enumerate(colors): + if np.any(np.all(colors[:ii] == c, 1)): + raise RuntimeError( + f"Could not get {n} unique colors from {cmap} " + "colormap. Try using a different colormap." + ) + return colors + + +@fill_doc +class Label: + """A FreeSurfer/MNE label with vertices restricted to one hemisphere. + + Labels can be combined with the ``+`` operator: + + * Duplicate vertices are removed. + * If duplicate vertices have conflicting position values, an error + is raised. + * Values of duplicate vertices are summed. + + Parameters + ---------- + vertices : array, shape (N,) + Vertex indices (0 based). + pos : array, shape (N, 3) | None + Locations in meters. If None, then zeros are used. + values : array, shape (N,) | None + Values at the vertices. If None, then ones are used. + hemi : 'lh' | 'rh' + Hemisphere to which the label applies. + comment : str + Kept as information but not used by the object itself. + name : str + Kept as information but not used by the object itself. + filename : str + Kept as information but not used by the object itself. + %(subject_label)s + color : None | matplotlib color + Default label color and alpha (e.g., ``(1., 0., 0., 1.)`` for red). + %(verbose)s + + Attributes + ---------- + color : None | tuple + Default label color, represented as RGBA tuple with values between 0 + and 1. + comment : str + Comment from the first line of the label file. + hemi : 'lh' | 'rh' + Hemisphere. + name : None | str + A name for the label. It is OK to change that attribute manually. + pos : array, shape (N, 3) + Locations in meters. + subject : str | None + The label subject. + It is best practice to set this to the proper + value on initialization, but it can also be set manually. + values : array, shape (N,) + Values at the vertices. + vertices : array, shape (N,) + Vertex indices (0 based) + """ + + @verbose + def __init__( + self, + vertices=(), + pos=None, + values=None, + hemi=None, + comment="", + name=None, + filename=None, + subject=None, + color=None, + *, + verbose=None, + ): + # check parameters + if not isinstance(hemi, str): + raise ValueError(f"hemi must be a string, not {type(hemi)}") + vertices = np.asarray(vertices, int) + if np.any(np.diff(vertices.astype(int)) <= 0): + raise ValueError("Vertices must be ordered in increasing order.") + + if color is not None: + from matplotlib.colors import colorConverter + + color = colorConverter.to_rgba(color) + + if values is None: + values = np.ones(len(vertices)) + else: + values = np.asarray(values) + + if pos is None: + pos = np.zeros((len(vertices), 3)) + else: + pos = np.asarray(pos) + + if not (len(vertices) == len(values) == len(pos)): + raise ValueError( + "vertices, values and pos need to have same length (number of vertices)" + ) + + # name + if name is None and filename is not None: + name = op.basename(filename[:-6]) + + self.vertices = vertices + self.pos = pos + self.values = values + self.hemi = hemi + self.comment = comment + self.subject = _check_subject(None, subject, raise_error=False) + self.color = color + self.name = name + self.filename = filename + + def __setstate__(self, state): # noqa: D105 + self.vertices = state["vertices"] + self.pos = state["pos"] + self.values = state["values"] + self.hemi = state["hemi"] + self.comment = state["comment"] + self.subject = state.get("subject", None) + self.color = state.get("color", None) + self.name = state["name"] + self.filename = state["filename"] + + def __getstate__(self): # noqa: D105 + out = dict( + vertices=self.vertices, + pos=self.pos, + values=self.values, + hemi=self.hemi, + comment=self.comment, + subject=self.subject, + color=self.color, + name=self.name, + filename=self.filename, + ) + return out + + def __repr__(self): # noqa: D105 + name = "unknown, " if self.subject is None else self.subject + ", " + name += repr(self.name) if self.name is not None else "unnamed" + n_vert = len(self) + return f"